151 |
|
|
152 |
DEBUGF(ETHARP_DEBUG, ("etharp_timer\n")); |
DEBUGF(ETHARP_DEBUG, ("etharp_timer\n")); |
153 |
/* remove expired entries from the ARP table */ |
/* remove expired entries from the ARP table */ |
154 |
for(i = 0; i < ARP_TABLE_SIZE; ++i) { |
for (i = 0; i < ARP_TABLE_SIZE; ++i) { |
155 |
arp_table[i].ctime++; |
arp_table[i].ctime++; |
156 |
if ((arp_table[i].state == ETHARP_STATE_STABLE) && |
if ((arp_table[i].state == ETHARP_STATE_STABLE) && |
157 |
(arp_table[i].ctime >= ARP_MAXAGE)) { |
(arp_table[i].ctime >= ARP_MAXAGE)) { |
158 |
DEBUGF(ETHARP_DEBUG, ("etharp_timer: expired stable entry %u.\n", i)); |
DEBUGF(ETHARP_DEBUG, ("etharp_timer: expired stable entry %u.\n", i)); |
159 |
arp_table[i].state = ETHARP_STATE_EMPTY; |
arp_table[i].state = ETHARP_STATE_EMPTY; |
160 |
#if ARP_QUEUEING |
#if ARP_QUEUEING |
161 |
/* remove any queued packet */ |
/* remove any queued packet */ |
162 |
pbuf_free(arp_table[i].p); |
pbuf_free(arp_table[i].p); |
163 |
arp_table[i].p = NULL; |
arp_table[i].p = NULL; |
164 |
#endif |
#endif |
165 |
} else if ((arp_table[i].state == ETHARP_STATE_PENDING) && |
} else if ((arp_table[i].state == ETHARP_STATE_PENDING) && |
168 |
#if ARP_QUEUEING |
#if ARP_QUEUEING |
169 |
DEBUGF(ETHARP_DEBUG, ("etharp_timer: expired pending entry %u - dequeueing %p.\n", i, (void *)(arp_table[i].p))); |
DEBUGF(ETHARP_DEBUG, ("etharp_timer: expired pending entry %u - dequeueing %p.\n", i, (void *)(arp_table[i].p))); |
170 |
/* remove any queued packet */ |
/* remove any queued packet */ |
171 |
pbuf_free(arp_table[i].p); |
pbuf_free(arp_table[i].p); |
172 |
arp_table[i].p = NULL; |
arp_table[i].p = NULL; |
173 |
#else |
#else |
174 |
DEBUGF(ETHARP_DEBUG, ("etharp_timer: expired pending entry %u.\n", i)); |
DEBUGF(ETHARP_DEBUG, ("etharp_timer: expired pending entry %u.\n", i)); |
190 |
u8_t i, j, maxtime; |
u8_t i, j, maxtime; |
191 |
|
|
192 |
/* Try to find an unused entry in the ARP table. */ |
/* Try to find an unused entry in the ARP table. */ |
193 |
for(i = 0; i < ARP_TABLE_SIZE; ++i) { |
for (i = 0; i < ARP_TABLE_SIZE; ++i) { |
194 |
if (arp_table[i].state == ETHARP_STATE_EMPTY) { |
if (arp_table[i].state == ETHARP_STATE_EMPTY) { |
195 |
DEBUGF(ETHARP_DEBUG, ("find_arp_entry: found empty entry %u\n", i)); |
DEBUGF(ETHARP_DEBUG, ("find_arp_entry: found empty entry %u\n", i)); |
196 |
break; |
break; |
202 |
if (i == ARP_TABLE_SIZE) { |
if (i == ARP_TABLE_SIZE) { |
203 |
maxtime = 0; |
maxtime = 0; |
204 |
j = ARP_TABLE_SIZE; |
j = ARP_TABLE_SIZE; |
205 |
for(i = 0; i < ARP_TABLE_SIZE; ++i) { |
for (i = 0; i < ARP_TABLE_SIZE; ++i) { |
206 |
/* remember entry with oldest stable entry in j*/ |
/* remember entry with oldest stable entry in j*/ |
207 |
if ((arp_table[i].state == ETHARP_STATE_STABLE) && |
if ((arp_table[i].state == ETHARP_STATE_STABLE) && |
208 |
#if ARP_QUEUEING /* do not want to re-use an entry with queued packets */ |
#if ARP_QUEUEING /* do not want to re-use an entry with queued packets */ |
214 |
} |
} |
215 |
} |
} |
216 |
if (j != ARP_TABLE_SIZE) { |
if (j != ARP_TABLE_SIZE) { |
217 |
DEBUGF(ETHARP_DEBUG, ("find_arp_entry: found oldest stable entry %u\n", j)); |
DEBUGF(ETHARP_DEBUG, ("find_arp_entry: found oldest stable entry %u\n", j)); |
218 |
} else { |
} else { |
219 |
DEBUGF(ETHARP_DEBUG, ("find_arp_entry: no replacable entry could be found\n")); |
DEBUGF(ETHARP_DEBUG, ("find_arp_entry: no replacable entry could be found\n")); |
220 |
} |
} |
242 |
update_arp_entry(struct netif *netif, struct ip_addr *ipaddr, struct eth_addr *ethaddr, u8_t flags) |
update_arp_entry(struct netif *netif, struct ip_addr *ipaddr, struct eth_addr *ethaddr, u8_t flags) |
243 |
{ |
{ |
244 |
u8_t i, k; |
u8_t i, k; |
|
#if ARP_QUEUEING |
|
|
struct pbuf *p; |
|
|
struct eth_hdr *ethhdr; |
|
|
#endif |
|
245 |
DEBUGF(ETHARP_DEBUG | DBG_TRACE | 3, ("update_arp_entry()\n")); |
DEBUGF(ETHARP_DEBUG | DBG_TRACE | 3, ("update_arp_entry()\n")); |
246 |
|
LWIP_ASSERT("netif->hwaddr_len != 0", netif->hwaddr_len != 0); |
247 |
DEBUGF(ETHARP_DEBUG | DBG_TRACE, ("update_arp_entry: %u.%u.%u.%u - %02x:%02x:%02x:%02x:%02x:%02x\n", ip4_addr1(ipaddr), ip4_addr2(ipaddr), ip4_addr3(ipaddr), ip4_addr4(ipaddr), |
DEBUGF(ETHARP_DEBUG | DBG_TRACE, ("update_arp_entry: %u.%u.%u.%u - %02x:%02x:%02x:%02x:%02x:%02x\n", ip4_addr1(ipaddr), ip4_addr2(ipaddr), ip4_addr3(ipaddr), ip4_addr4(ipaddr), |
248 |
ethaddr->addr[0], ethaddr->addr[1], ethaddr->addr[2], ethaddr->addr[3], ethaddr->addr[4], ethaddr->addr[5])); |
ethaddr->addr[0], ethaddr->addr[1], ethaddr->addr[2], ethaddr->addr[3], ethaddr->addr[4], ethaddr->addr[5])); |
249 |
/* do not update for 0.0.0.0 addresses */ |
/* do not update for 0.0.0.0 addresses */ |
254 |
/* Walk through the ARP mapping table and try to find an entry to |
/* Walk through the ARP mapping table and try to find an entry to |
255 |
update. If none is found, the IP -> MAC address mapping is |
update. If none is found, the IP -> MAC address mapping is |
256 |
inserted in the ARP table. */ |
inserted in the ARP table. */ |
257 |
for(i = 0; i < ARP_TABLE_SIZE; ++i) { |
for (i = 0; i < ARP_TABLE_SIZE; ++i) { |
258 |
/* Check if the source IP address of the incoming packet matches |
/* Check if the source IP address of the incoming packet matches |
259 |
the IP address in this ARP table entry. */ |
the IP address in this ARP table entry. */ |
260 |
if (ip_addr_cmp(ipaddr, &arp_table[i].ipaddr)) { |
if (ip_addr_cmp(ipaddr, &arp_table[i].ipaddr)) { |
267 |
} |
} |
268 |
/* stable entry? (possible just marked to become stable) */ |
/* stable entry? (possible just marked to become stable) */ |
269 |
if (arp_table[i].state == ETHARP_STATE_STABLE) { |
if (arp_table[i].state == ETHARP_STATE_STABLE) { |
270 |
|
#if ARP_QUEUEING |
271 |
|
struct pbuf *p; |
272 |
|
struct eth_hdr *ethhdr; |
273 |
|
#endif |
274 |
DEBUGF(ETHARP_DEBUG | DBG_TRACE, ("update_arp_entry: updating stable entry %u\n", i)); |
DEBUGF(ETHARP_DEBUG | DBG_TRACE, ("update_arp_entry: updating stable entry %u\n", i)); |
275 |
/* An old entry found, update this and return. */ |
/* An old entry found, update this and return. */ |
276 |
for(k = 0; k < netif->hwaddr_len; ++k) { |
for (k = 0; k < netif->hwaddr_len; ++k) { |
277 |
arp_table[i].ethaddr.addr[k] = ethaddr->addr[k]; |
arp_table[i].ethaddr.addr[k] = ethaddr->addr[k]; |
278 |
} |
} |
279 |
/* reset time stamp */ |
/* reset time stamp */ |
280 |
arp_table[i].ctime = 0; |
arp_table[i].ctime = 0; |
281 |
#if ARP_QUEUEING |
#if ARP_QUEUEING |
282 |
|
p = arp_table[i].p; |
283 |
/* queued packet present? */ |
/* queued packet present? */ |
284 |
if ((p = arp_table[i].p) != NULL) { |
if (p != NULL) { |
285 |
/* Null out attached buffer immediately */ |
/* NULL attached buffer immediately */ |
286 |
arp_table[i].p = NULL; |
arp_table[i].p = NULL; |
287 |
/* fill-in Ethernet header */ |
/* fill-in Ethernet header */ |
288 |
ethhdr = p->payload; |
ethhdr = p->payload; |
289 |
for(k = 0; k < netif->hwaddr_len; ++k) { |
for (k = 0; k < netif->hwaddr_len; ++k) { |
290 |
ethhdr->dest.addr[k] = ethaddr->addr[k]; |
ethhdr->dest.addr[k] = ethaddr->addr[k]; |
291 |
} |
} |
292 |
ethhdr->type = htons(ETHTYPE_IP); |
ethhdr->type = htons(ETHTYPE_IP); |
330 |
/* set IP address */ |
/* set IP address */ |
331 |
ip_addr_set(&arp_table[i].ipaddr, ipaddr); |
ip_addr_set(&arp_table[i].ipaddr, ipaddr); |
332 |
/* set Ethernet hardware address */ |
/* set Ethernet hardware address */ |
333 |
for(k = 0; k < netif->hwaddr_len; ++k) { |
for (k = 0; k < netif->hwaddr_len; ++k) { |
334 |
arp_table[i].ethaddr.addr[k] = ethaddr->addr[k]; |
arp_table[i].ethaddr.addr[k] = ethaddr->addr[k]; |
335 |
} |
} |
336 |
/* reset time-stamp */ |
/* reset time-stamp */ |
421 |
reply. In any case, we time-stamp any existing ARP entry, |
reply. In any case, we time-stamp any existing ARP entry, |
422 |
and possiby send out an IP packet that was queued on it. */ |
and possiby send out an IP packet that was queued on it. */ |
423 |
|
|
424 |
DEBUGF(ETHARP_DEBUG | DBG_TRACE, ("etharp_arp_input: incoming ARP request\n")); |
DEBUGF (ETHARP_DEBUG | DBG_TRACE, ("etharp_arp_input: incoming ARP request\n")); |
425 |
/* we are not configured? */ |
/* we are not configured? */ |
426 |
if (netif->ip_addr.addr == 0) { |
if (netif->ip_addr.addr == 0) { |
427 |
DEBUGF(ETHARP_DEBUG | DBG_TRACE, ("etharp_arp_input: we are unconfigured, ARP request ignored.\n")); |
DEBUGF(ETHARP_DEBUG | DBG_TRACE, ("etharp_arp_input: we are unconfigured, ARP request ignored.\n")); |
648 |
struct pbuf *p; |
struct pbuf *p; |
649 |
err_t result = ERR_OK; |
err_t result = ERR_OK; |
650 |
u8_t i; |
u8_t i; |
651 |
/* prevent warning if ARP_QUEUEING == 0 */ |
u8_t perform_arp_request = 1; |
652 |
if (q); |
/* prevent 'unused argument' warning if ARP_QUEUEING == 0 */ |
653 |
|
(void)q; |
654 |
srcaddr = (struct eth_addr *)netif->hwaddr; |
srcaddr = (struct eth_addr *)netif->hwaddr; |
655 |
/* bail out if this IP address is pending */ |
/* bail out if this IP address is pending */ |
656 |
for(i = 0; i < ARP_TABLE_SIZE; ++i) { |
for (i = 0; i < ARP_TABLE_SIZE; ++i) { |
657 |
if (ip_addr_cmp(ipaddr, &arp_table[i].ipaddr)) { |
if (ip_addr_cmp(ipaddr, &arp_table[i].ipaddr)) { |
658 |
if (arp_table[i].state == ETHARP_STATE_PENDING) { |
if (arp_table[i].state == ETHARP_STATE_PENDING) { |
659 |
DEBUGF(ETHARP_DEBUG | DBG_TRACE | DBG_STATE, ("etharp_query: requested IP already pending as entry %u\n", i)); |
DEBUGF(ETHARP_DEBUG | DBG_TRACE | DBG_STATE, ("etharp_query: requested IP already pending as entry %u\n", i)); |
660 |
/* break out of for-loop, user may wish to queue a packet on a stable entry */ |
/* break out of for-loop, user may wish to queue a packet on a stable entry */ |
661 |
|
/* TODO: we will issue a new ARP request, which should not occur too often */ |
662 |
|
/* we might want to run a faster timer on ARP to limit this */ |
663 |
break; |
break; |
664 |
} |
} |
665 |
else if (arp_table[i].state == ETHARP_STATE_STABLE) { |
else if (arp_table[i].state == ETHARP_STATE_STABLE) { |
666 |
DEBUGF(ETHARP_DEBUG | DBG_TRACE | DBG_STATE, ("etharp_query: requested IP already stable as entry %u\n", i)); |
DEBUGF(ETHARP_DEBUG | DBG_TRACE | DBG_STATE, ("etharp_query: requested IP already stable as entry %u\n", i)); |
667 |
/* TODO: user may wish to queue a packet on a stable entry. */ |
/* user may wish to queue a packet on a stable entry, so we proceed without ARP requesting */ |
668 |
return NULL; |
/* TODO: even if the ARP entry is stable, we might do an ARP request anyway */ |
669 |
|
perform_arp_request = 0; |
670 |
|
break; |
671 |
} |
} |
672 |
} |
} |
673 |
} |
} |
679 |
/* bail out if no ARP entries are available */ |
/* bail out if no ARP entries are available */ |
680 |
if (i == ARP_TABLE_SIZE) { |
if (i == ARP_TABLE_SIZE) { |
681 |
DEBUGF(ETHARP_DEBUG | 2, ("etharp_query: no more ARP entries available.\n")); |
DEBUGF(ETHARP_DEBUG | 2, ("etharp_query: no more ARP entries available.\n")); |
682 |
return NULL; |
return ERR_MEM; |
683 |
} |
} |
684 |
|
/* we will now recycle entry i */ |
685 |
DEBUGF(ETHARP_DEBUG | DBG_TRACE, ("etharp_query: created ARP table entry %u.\n", i)); |
DEBUGF(ETHARP_DEBUG | DBG_TRACE, ("etharp_query: created ARP table entry %u.\n", i)); |
686 |
/* i is available, create ARP entry */ |
/* i is available, create ARP entry */ |
687 |
ip_addr_set(&arp_table[i].ipaddr, ipaddr); |
ip_addr_set(&arp_table[i].ipaddr, ipaddr); |
688 |
arp_table[i].ctime = 0; |
arp_table[i].ctime = 0; |
689 |
arp_table[i].state = ETHARP_STATE_PENDING; |
arp_table[i].state = ETHARP_STATE_PENDING; |
690 |
#if ARP_QUEUEING |
#if ARP_QUEUEING |
691 |
arp_table[i].p = NULL; |
/* free queued packet, as entry is now invalidated */ |
692 |
|
if (arp_table[i].p != NULL) { |
693 |
|
pbuf_free(arp_table[i].p); |
694 |
|
arp_table[i].p = NULL; |
695 |
|
DEBUGF(ETHARP_DEBUG | DBG_TRACE | 3, ("etharp_query: dropped packet on ARP queue. Should not occur.\n")); |
696 |
|
} |
697 |
#endif |
#endif |
698 |
} |
} |
699 |
#if ARP_QUEUEING |
#if ARP_QUEUEING |
700 |
/* any pbuf to queue and queue is empty? */ |
/* any pbuf to queue and queue is empty? */ |
701 |
if ((q != NULL) && (arp_table[i].p == NULL)) { |
if (q != NULL) { |
702 |
/* copy PBUF_REF referenced payloads to PBUF_RAM */ |
/* yield later packets over older packets? */ |
703 |
q = pbuf_take(q); |
#if ARP_QUEUE_FIRST == 0 |
704 |
/* remember pbuf to queue, if any */ |
/* earlier queued packet on this entry? */ |
705 |
arp_table[i].p = q; |
if (arp_table[i].p != NULL) { |
706 |
/* pbufs are queued, increase the reference count */ |
pbuf_free(arp_table[i].p); |
707 |
pbuf_ref(q); |
arp_table[i].p = NULL; |
708 |
DEBUGF(ETHARP_DEBUG | DBG_TRACE | DBG_STATE, ("etharp_query: queued packet %p on ARP entry %u.\n", (void *)q, i)); |
DEBUGF(ETHARP_DEBUG | DBG_TRACE | 3, ("etharp_query: dropped packet on ARP queue. Should not occur.\n")); |
709 |
} |
/* fall-through into next if */ |
710 |
#endif |
} |
711 |
/* allocate a pbuf for the outgoing ARP request packet */ |
#endif |
712 |
p = pbuf_alloc(PBUF_LINK, sizeof(struct etharp_hdr), PBUF_RAM); |
/* packet can be queued? */ |
713 |
/* could allocate pbuf? */ |
if (arp_table[i].p == NULL) { |
714 |
if (p != NULL) { |
/* copy PBUF_REF referenced payloads into PBUF_RAM */ |
715 |
u8_t j; |
q = pbuf_take(q); |
716 |
DEBUGF(ETHARP_DEBUG | DBG_TRACE, ("etharp_query: sending ARP request.\n")); |
/* remember pbuf to queue, if any */ |
717 |
hdr = p->payload; |
arp_table[i].p = q; |
718 |
hdr->opcode = htons(ARP_REQUEST); |
/* pbufs are queued, increase the reference count */ |
719 |
for(j = 0; j < netif->hwaddr_len; ++j) |
pbuf_ref(q); |
720 |
{ |
DEBUGF(ETHARP_DEBUG | DBG_TRACE | DBG_STATE, ("etharp_query: queued packet %p on ARP entry %u.\n", (void *)q, i)); |
|
hdr->dhwaddr.addr[j] = 0x00; |
|
|
hdr->shwaddr.addr[j] = srcaddr->addr[j]; |
|
721 |
} |
} |
722 |
ip_addr_set(&(hdr->dipaddr), ipaddr); |
} |
723 |
ip_addr_set(&(hdr->sipaddr), &(netif->ip_addr)); |
#endif |
724 |
|
/* ARP request? */ |
725 |
|
if (perform_arp_request) |
726 |
|
{ |
727 |
|
/* allocate a pbuf for the outgoing ARP request packet */ |
728 |
|
p = pbuf_alloc(PBUF_LINK, sizeof(struct etharp_hdr), PBUF_RAM); |
729 |
|
/* could allocate pbuf? */ |
730 |
|
if (p != NULL) { |
731 |
|
u8_t j; |
732 |
|
DEBUGF(ETHARP_DEBUG | DBG_TRACE, ("etharp_query: sending ARP request.\n")); |
733 |
|
hdr = p->payload; |
734 |
|
hdr->opcode = htons(ARP_REQUEST); |
735 |
|
for(j = 0; j < netif->hwaddr_len; ++j) |
736 |
|
{ |
737 |
|
hdr->dhwaddr.addr[j] = 0x00; |
738 |
|
hdr->shwaddr.addr[j] = srcaddr->addr[j]; |
739 |
|
} |
740 |
|
ip_addr_set(&(hdr->dipaddr), ipaddr); |
741 |
|
ip_addr_set(&(hdr->sipaddr), &(netif->ip_addr)); |
742 |
|
|
743 |
hdr->hwtype = htons(HWTYPE_ETHERNET); |
hdr->hwtype = htons(HWTYPE_ETHERNET); |
744 |
ARPH_HWLEN_SET(hdr, netif->hwaddr_len); |
ARPH_HWLEN_SET(hdr, netif->hwaddr_len); |
745 |
|
|
746 |
hdr->proto = htons(ETHTYPE_IP); |
hdr->proto = htons(ETHTYPE_IP); |
747 |
ARPH_PROTOLEN_SET(hdr, sizeof(struct ip_addr)); |
ARPH_PROTOLEN_SET(hdr, sizeof(struct ip_addr)); |
748 |
for(j = 0; j < netif->hwaddr_len; ++j) |
for(j = 0; j < netif->hwaddr_len; ++j) |
749 |
{ |
{ |
750 |
hdr->ethhdr.dest.addr[j] = 0xff; |
hdr->ethhdr.dest.addr[j] = 0xff; |
751 |
hdr->ethhdr.src.addr[j] = srcaddr->addr[j]; |
hdr->ethhdr.src.addr[j] = srcaddr->addr[j]; |
752 |
|
} |
753 |
|
hdr->ethhdr.type = htons(ETHTYPE_ARP); |
754 |
|
/* send ARP query */ |
755 |
|
result = netif->linkoutput(netif, p); |
756 |
|
/* free ARP query packet */ |
757 |
|
pbuf_free(p); |
758 |
|
p = NULL; |
759 |
|
} else { |
760 |
|
result = ERR_MEM; |
761 |
|
DEBUGF(ETHARP_DEBUG | DBG_TRACE | 2, ("etharp_query: could not allocate pbuf for ARP request.\n")); |
762 |
} |
} |
|
hdr->ethhdr.type = htons(ETHTYPE_ARP); |
|
|
/* send ARP query */ |
|
|
result = netif->linkoutput(netif, p); |
|
|
/* free ARP query packet */ |
|
|
pbuf_free(p); |
|
|
p = NULL; |
|
|
} else { |
|
|
result = ERR_MEM; |
|
|
DEBUGF(ETHARP_DEBUG | DBG_TRACE | 2, ("etharp_query: could not allocate pbuf for ARP request.\n")); |
|
763 |
} |
} |
764 |
return result; |
return result; |
765 |
} |
} |