113 |
struct eth_addr ethaddr; |
struct eth_addr ethaddr; |
114 |
enum etharp_state state; |
enum etharp_state state; |
115 |
#if ARP_QUEUEING |
#if ARP_QUEUEING |
116 |
|
/** |
117 |
|
* Pointer to queue of pending outgoing packets on this ARP entry. |
118 |
|
* Must be at most a single packet for now. */ |
119 |
struct pbuf *p; |
struct pbuf *p; |
120 |
#endif |
#endif |
121 |
u8_t ctime; |
u8_t ctime; |
158 |
/* remove expired entries from the ARP table */ |
/* remove expired entries from the ARP table */ |
159 |
for (i = 0; i < ARP_TABLE_SIZE; ++i) { |
for (i = 0; i < ARP_TABLE_SIZE; ++i) { |
160 |
arp_table[i].ctime++; |
arp_table[i].ctime++; |
161 |
|
/* a resolved/stable entry? */ |
162 |
if ((arp_table[i].state == ETHARP_STATE_STABLE) && |
if ((arp_table[i].state == ETHARP_STATE_STABLE) && |
163 |
|
/* entry has become old? */ |
164 |
(arp_table[i].ctime >= ARP_MAXAGE)) { |
(arp_table[i].ctime >= ARP_MAXAGE)) { |
165 |
LWIP_DEBUGF(ETHARP_DEBUG, ("etharp_timer: expired stable entry %u.\n", i)); |
LWIP_DEBUGF(ETHARP_DEBUG, ("etharp_timer: expired stable entry %u.\n", i)); |
166 |
goto empty; |
goto empty; |
167 |
|
/* an unresolved/pending entry? */ |
168 |
} else if ((arp_table[i].state == ETHARP_STATE_PENDING) && |
} else if ((arp_table[i].state == ETHARP_STATE_PENDING) && |
169 |
|
/* entry unresolved/pending for too long? */ |
170 |
(arp_table[i].ctime >= ARP_MAXPENDING)) { |
(arp_table[i].ctime >= ARP_MAXPENDING)) { |
171 |
LWIP_DEBUGF(ETHARP_DEBUG, ("etharp_timer: expired pending entry %u.\n", i)); |
LWIP_DEBUGF(ETHARP_DEBUG, ("etharp_timer: expired pending entry %u.\n", i)); |
172 |
empty: |
empty: |
173 |
|
/* empty old entry */ |
174 |
arp_table[i].state = ETHARP_STATE_EMPTY; |
arp_table[i].state = ETHARP_STATE_EMPTY; |
175 |
#if ARP_QUEUEING |
#if ARP_QUEUEING |
176 |
|
/* and empty packet queue */ |
177 |
if (arp_table[i].p != NULL) { |
if (arp_table[i].p != NULL) { |
178 |
/* remove any queued packet */ |
/* remove any queued packet */ |
179 |
LWIP_DEBUGF(ETHARP_DEBUG, ("etharp_timer: freeing entry %u, packet queue %p.\n", i, (void *)(arp_table[i].p))); |
LWIP_DEBUGF(ETHARP_DEBUG, ("etharp_timer: freeing entry %u, packet queue %p.\n", i, (void *)(arp_table[i].p))); |
206 |
} |
} |
207 |
|
|
208 |
/* If no unused entry is found, we try to find the oldest entry and |
/* If no unused entry is found, we try to find the oldest entry and |
209 |
throw it away. If all entries are new and have 0 ctime drop one */ |
throw it away. If all entries are new and ctime drop one */ |
210 |
if (i == ARP_TABLE_SIZE) { |
if (i == ARP_TABLE_SIZE) { |
211 |
maxtime = 0; |
maxtime = 0; |
212 |
j = ARP_TABLE_SIZE; |
j = ARP_TABLE_SIZE; |
213 |
for (i = 0; i < ARP_TABLE_SIZE; ++i) { |
for (i = 0; i < ARP_TABLE_SIZE; ++i) { |
214 |
/* remember entry with oldest stable entry in j*/ |
/* remember entry with oldest stable entry in j */ |
215 |
if ((arp_table[i].state == ETHARP_STATE_STABLE) && |
if ((arp_table[i].state == ETHARP_STATE_STABLE) && |
216 |
#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 */ |
217 |
(arp_table[i].p == NULL) && |
(arp_table[i].p == NULL) && |
219 |
(arp_table[i].ctime >= maxtime)) { |
(arp_table[i].ctime >= maxtime)) { |
220 |
maxtime = arp_table[i].ctime; |
maxtime = arp_table[i].ctime; |
221 |
j = i; |
j = i; |
222 |
|
/* { j = oldest stable entry } */ |
223 |
} |
} |
224 |
} |
} |
225 |
if (j != ARP_TABLE_SIZE) { |
if (j != ARP_TABLE_SIZE) { |
522 |
* This ARP request is returned as a pbuf, which should be sent by |
* This ARP request is returned as a pbuf, which should be sent by |
523 |
* the caller. |
* the caller. |
524 |
* |
* |
|
* If ARP failed to allocate resources, NULL is returned. |
|
|
* |
|
525 |
* A returned non-NULL packet should be sent by the caller. |
* A returned non-NULL packet should be sent by the caller. |
526 |
* |
* |
527 |
|
* If ARP failed to allocate resources, NULL is returned. |
528 |
|
* |
529 |
* @param netif The lwIP network interface which the IP packet will be sent on. |
* @param netif The lwIP network interface which the IP packet will be sent on. |
530 |
* @param ipaddr The IP address of the packet destination. |
* @param ipaddr The IP address of the packet destination. |
531 |
* @param pbuf The pbuf(s) containing the IP packet to be sent. |
* @param pbuf The pbuf(s) containing the IP packet to be sent. |
540 |
struct eth_hdr *ethhdr; |
struct eth_hdr *ethhdr; |
541 |
u8_t i; |
u8_t i; |
542 |
|
|
543 |
/* Make room for Ethernet header. */ |
/* make room for Ethernet header */ |
544 |
if (pbuf_header(q, sizeof(struct eth_hdr)) != 0) { |
if (pbuf_header(q, sizeof(struct eth_hdr)) != 0) { |
545 |
/* The pbuf_header() call shouldn't fail, and we'll just bail |
/* The pbuf_header() call shouldn't fail, and we'll just bail |
546 |
out if it does.. */ |
out if it does.. */ |
549 |
return NULL; |
return NULL; |
550 |
} |
} |
551 |
|
|
|
/* obtain source Ethernet address of the given interface */ |
|
|
srcaddr = (struct eth_addr *)netif->hwaddr; |
|
|
|
|
552 |
/* assume unresolved Ethernet address */ |
/* assume unresolved Ethernet address */ |
553 |
dest = NULL; |
dest = NULL; |
554 |
/* Construct Ethernet header. Start with looking up deciding which |
/* Construct Ethernet header. Start with looking up deciding which |
576 |
} |
} |
577 |
/* destination IP address is an IP unicast address */ |
/* destination IP address is an IP unicast address */ |
578 |
else { |
else { |
579 |
/* destination IP network address not on local network? */ |
/* destination IP network address not on local network? |
580 |
/* this occurs if the packet is routed to the default gateway on this interface */ |
* IP layer wants us to forward to the default gateway */ |
581 |
if (!ip_addr_maskcmp(ipaddr, &(netif->ip_addr), &(netif->netmask))) { |
if (!ip_addr_maskcmp(ipaddr, &(netif->ip_addr), &(netif->netmask))) { |
582 |
/* gateway available? */ |
/* interface has default gateway? */ |
583 |
if (netif->gw.addr != 0) |
if (netif->gw.addr != 0) |
584 |
{ |
{ |
585 |
/* use the gateway IP address */ |
/* route to default gateway IP address */ |
586 |
ipaddr = &(netif->gw); |
ipaddr = &(netif->gw); |
587 |
} |
} |
588 |
/* no gateway available? */ |
/* no gateway available? */ |
589 |
else |
else |
590 |
{ |
{ |
591 |
/* IP destination address outside local network, but no gateway available */ |
/* IP destination address outside local network, but no gateway available */ |
592 |
|
/* { packet is discarded } */ |
593 |
return NULL; |
return NULL; |
594 |
} |
} |
595 |
} |
} |
608 |
/* ARP query for the IP address, submit this IP packet for queueing */ |
/* ARP query for the IP address, submit this IP packet for queueing */ |
609 |
/* TODO: How do we handle netif->ipaddr == ipaddr? */ |
/* TODO: How do we handle netif->ipaddr == ipaddr? */ |
610 |
etharp_query(netif, ipaddr, q); |
etharp_query(netif, ipaddr, q); |
611 |
|
/* { packet was queued (ERR_OK), or discarded } */ |
612 |
/* return nothing */ |
/* return nothing */ |
613 |
return NULL; |
return NULL; |
614 |
} |
} |
621 |
|
|
622 |
/* destination Ethernet address known */ |
/* destination Ethernet address known */ |
623 |
if (dest != NULL) { |
if (dest != NULL) { |
624 |
/* A valid IP->MAC address mapping was found, so we construct the |
/* obtain source Ethernet address of the given interface */ |
625 |
Ethernet header for the outgoing packet. */ |
srcaddr = (struct eth_addr *)netif->hwaddr; |
626 |
|
|
627 |
|
/* A valid IP->MAC address mapping was found, fill in the |
628 |
|
* Ethernet header for the outgoing packet */ |
629 |
ethhdr = q->payload; |
ethhdr = q->payload; |
630 |
|
|
631 |
for(i = 0; i < netif->hwaddr_len; i++) { |
for(i = 0; i < netif->hwaddr_len; i++) { |
666 |
{ |
{ |
667 |
struct eth_addr *srcaddr; |
struct eth_addr *srcaddr; |
668 |
struct etharp_hdr *hdr; |
struct etharp_hdr *hdr; |
|
struct pbuf *p; |
|
669 |
err_t result = ERR_OK; |
err_t result = ERR_OK; |
670 |
u8_t i; |
u8_t i; |
671 |
u8_t perform_arp_request = 1; |
u8_t perform_arp_request = 1; |
694 |
/* queried address not yet in ARP table? */ |
/* queried address not yet in ARP table? */ |
695 |
if (i == ARP_TABLE_SIZE) { |
if (i == ARP_TABLE_SIZE) { |
696 |
LWIP_DEBUGF(ETHARP_DEBUG | DBG_TRACE, ("etharp_query: IP address not found in ARP table\n")); |
LWIP_DEBUGF(ETHARP_DEBUG | DBG_TRACE, ("etharp_query: IP address not found in ARP table\n")); |
697 |
/* find an available entry */ |
/* find an available (unused or old) entry */ |
698 |
i = find_arp_entry(); |
i = find_arp_entry(); |
699 |
/* bail out if no ARP entries are available */ |
/* bail out if no ARP entries are available */ |
700 |
if (i == ARP_TABLE_SIZE) { |
if (i == ARP_TABLE_SIZE) { |
701 |
LWIP_DEBUGF(ETHARP_DEBUG | 2, ("etharp_query: no more ARP entries available.\n")); |
LWIP_DEBUGF(ETHARP_DEBUG | 2, ("etharp_query: no more ARP entries available. Should seldom occur.\n")); |
702 |
return ERR_MEM; |
return ERR_MEM; |
703 |
} |
} |
704 |
/* we will now recycle entry i */ |
/* we will now recycle entry i */ |
707 |
ip_addr_set(&arp_table[i].ipaddr, ipaddr); |
ip_addr_set(&arp_table[i].ipaddr, ipaddr); |
708 |
arp_table[i].ctime = 0; |
arp_table[i].ctime = 0; |
709 |
arp_table[i].state = ETHARP_STATE_PENDING; |
arp_table[i].state = ETHARP_STATE_PENDING; |
710 |
#if ARP_QUEUEING |
#if ARP_QUEUEING /* deal with queue of recycled entry */ |
711 |
/* free queued packet, as entry is now invalidated */ |
/* free queued packet, as entry is now invalidated and recycled */ |
712 |
if (arp_table[i].p != NULL) { |
if (arp_table[i].p != NULL) { |
713 |
pbuf_free(arp_table[i].p); |
pbuf_free(arp_table[i].p); |
714 |
|
LWIP_DEBUGF(ETHARP_DEBUG | DBG_TRACE | 3, |
715 |
|
("etharp_query: dropped packet %p from recycled ARP entry queue. Should not occur.\n", (void *)arp_table[i].p)); |
716 |
arp_table[i].p = NULL; |
arp_table[i].p = NULL; |
|
LWIP_DEBUGF(ETHARP_DEBUG | DBG_TRACE | 3, ("etharp_query: dropped packet on ARP queue. Should not occur.\n")); |
|
717 |
} |
} |
718 |
#endif |
#endif |
719 |
} |
} |
725 |
/* earlier queued packet on this entry? */ |
/* earlier queued packet on this entry? */ |
726 |
if (arp_table[i].p != NULL) { |
if (arp_table[i].p != NULL) { |
727 |
pbuf_free(arp_table[i].p); |
pbuf_free(arp_table[i].p); |
728 |
|
LWIP_DEBUGF(ETHARP_DEBUG | DBG_TRACE | 3, ("etharp_query: dropped packet %p on ARP queue. Should not occur.\n", (void *)arp_table[i].p)); |
729 |
arp_table[i].p = NULL; |
arp_table[i].p = NULL; |
|
LWIP_DEBUGF(ETHARP_DEBUG | DBG_TRACE | 3, ("etharp_query: dropped packet on ARP queue. Should not occur.\n")); |
|
730 |
/* fall-through into next if */ |
/* fall-through into next if */ |
731 |
} |
} |
732 |
#endif |
#endif |
745 |
/* ARP request? */ |
/* ARP request? */ |
746 |
if (perform_arp_request) |
if (perform_arp_request) |
747 |
{ |
{ |
748 |
|
struct pbuf *p; |
749 |
/* allocate a pbuf for the outgoing ARP request packet */ |
/* allocate a pbuf for the outgoing ARP request packet */ |
750 |
p = pbuf_alloc(PBUF_LINK, sizeof(struct etharp_hdr), PBUF_RAM); |
p = pbuf_alloc(PBUF_LINK, sizeof(struct etharp_hdr), PBUF_RAM); |
751 |
/* could allocate pbuf? */ |
/* could allocate pbuf? */ |