48#if LWIP_IPV4 && LWIP_ARP
61#ifdef LWIP_HOOK_FILENAME
62#include LWIP_HOOK_FILENAME
67#define ARP_AGE_REREQUEST_USED_UNICAST (ARP_MAXAGE - 30)
68#define ARP_AGE_REREQUEST_USED_BROADCAST (ARP_MAXAGE - 15)
77#define ARP_MAXPENDING 5
81 ETHARP_STATE_EMPTY = 0,
84 ETHARP_STATE_STABLE_REREQUESTING_1,
85 ETHARP_STATE_STABLE_REREQUESTING_2
86#if ETHARP_SUPPORT_STATIC_ENTRIES
94 struct etharp_q_entry *q;
101 struct eth_addr ethaddr;
108#if !LWIP_NETIF_HWADDRHINT
109static netif_addr_idx_t etharp_cached_entry;
114#define ETHARP_FLAG_TRY_HARD 1
115#define ETHARP_FLAG_FIND_ONLY 2
116#if ETHARP_SUPPORT_STATIC_ENTRIES
117#define ETHARP_FLAG_STATIC_ENTRY 4
120#if LWIP_NETIF_HWADDRHINT
121#define ETHARP_SET_ADDRHINT(netif, addrhint) do { if (((netif) != NULL) && ((netif)->hints != NULL)) { \
122 (netif)->hints->addr_hint = (addrhint); }} while(0)
124#define ETHARP_SET_ADDRHINT(netif, addrhint) (etharp_cached_entry = (addrhint))
129#if (ARP_TABLE_SIZE > NETIF_ADDR_IDX_MAX)
130#error "ARP_TABLE_SIZE must fit in an s16_t, you have to reduce it in your lwipopts.h"
148free_etharp_q(
struct etharp_q_entry *q)
150 struct etharp_q_entry *r;
151 LWIP_ASSERT(
"q != NULL", q != NULL);
155 LWIP_ASSERT(
"r->p != NULL", (r->p != NULL));
163#define free_etharp_q(q) pbuf_free(q)
169etharp_free_entry(
int i)
172 mib2_remove_arp_entry(arp_table[i].
netif, &arp_table[i].ipaddr);
174 if (arp_table[i].q != NULL) {
176 LWIP_DEBUGF(
ETHARP_DEBUG, (
"etharp_free_entry: freeing entry %"U16_F
", packet queue %p.\n", (u16_t)i, (
void *)(arp_table[i].q)));
177 free_etharp_q(arp_table[i].q);
178 arp_table[i].q = NULL;
181 arp_table[i].state = ETHARP_STATE_EMPTY;
184 arp_table[i].ctime = 0;
185 arp_table[i].netif = NULL;
187 arp_table[i].ethaddr = ethzero;
205 u8_t state = arp_table[i].state;
206 if (state != ETHARP_STATE_EMPTY
208 && (state != ETHARP_STATE_STATIC)
211 arp_table[i].ctime++;
213 ((arp_table[i].state == ETHARP_STATE_PENDING) &&
214 (arp_table[i].ctime >= ARP_MAXPENDING))) {
216 LWIP_DEBUGF(
ETHARP_DEBUG, (
"etharp_timer: expired %s entry %d.\n",
217 arp_table[i].state >= ETHARP_STATE_STABLE ?
"stable" :
"pending", i));
219 etharp_free_entry(i);
220 }
else if (arp_table[i].state == ETHARP_STATE_STABLE_REREQUESTING_1) {
222 arp_table[i].state = ETHARP_STATE_STABLE_REREQUESTING_2;
223 }
else if (arp_table[i].state == ETHARP_STATE_STABLE_REREQUESTING_2) {
226 arp_table[i].state = ETHARP_STATE_STABLE;
227 }
else if (arp_table[i].state == ETHARP_STATE_PENDING) {
229 etharp_request(arp_table[i].
netif, &arp_table[i].ipaddr);
265 u16_t age_queue = 0, age_pending = 0, age_stable = 0;
285 u8_t state = arp_table[i].state;
288 LWIP_DEBUGF(
ETHARP_DEBUG, (
"etharp_find_entry: found empty entry %d\n", (
int)i));
291 }
else if (state != ETHARP_STATE_EMPTY) {
292 LWIP_ASSERT(
"state == ETHARP_STATE_PENDING || state >= ETHARP_STATE_STABLE",
293 state == ETHARP_STATE_PENDING || state >= ETHARP_STATE_STABLE);
295 if (ipaddr && ip4_addr_eq(ipaddr, &arp_table[i].ipaddr)
305 if (state == ETHARP_STATE_PENDING) {
307 if (arp_table[i].q != NULL) {
308 if (arp_table[i].ctime >= age_queue) {
310 age_queue = arp_table[i].ctime;
315 if (arp_table[i].ctime >= age_pending) {
317 age_pending = arp_table[i].ctime;
321 }
else if (state >= ETHARP_STATE_STABLE) {
322#if ETHARP_SUPPORT_STATIC_ENTRIES
324 if (state < ETHARP_STATE_STATIC)
328 if (arp_table[i].ctime >= age_stable) {
330 age_stable = arp_table[i].ctime;
339 if (((flags & ETHARP_FLAG_FIND_ONLY) != 0) ||
341 ((empty ==
ARP_TABLE_SIZE) && ((flags & ETHARP_FLAG_TRY_HARD) == 0))) {
366 LWIP_ASSERT(
"arp_table[i].q == NULL", arp_table[i].q == NULL);
371 LWIP_DEBUGF(
ETHARP_DEBUG |
LWIP_DBG_TRACE, (
"etharp_find_entry: selecting oldest pending entry %d (without queue)\n", (
int)i));
376 LWIP_DEBUGF(
ETHARP_DEBUG |
LWIP_DBG_TRACE, (
"etharp_find_entry: selecting oldest pending entry %d, freeing packet queue %p\n", (
int)i, (
void *)(arp_table[i].q)));
385 etharp_free_entry(i);
389 LWIP_ASSERT(
"arp_table[i].state == ETHARP_STATE_EMPTY",
390 arp_table[i].state == ETHARP_STATE_EMPTY);
393 if (ipaddr != NULL) {
397 arp_table[i].ctime = 0;
398#if ETHARP_TABLE_MATCH_NETIF
399 arp_table[i].netif =
netif;
426 LWIP_ASSERT(
"netif->hwaddr_len == ETH_HWADDR_LEN",
netif->
hwaddr_len == ETH_HWADDR_LEN);
427 LWIP_DEBUGF(
ETHARP_DEBUG |
LWIP_DBG_TRACE, (
"etharp_update_arp_entry: %"U16_F
".%"U16_F
".%"U16_F
".%"U16_F
" - %02"X16_F
":%02"X16_F
":%02"X16_F
":%02"X16_F
":%02"X16_F
":%02"X16_F
"\n",
428 ip4_addr1_16(ipaddr), ip4_addr2_16(ipaddr), ip4_addr3_16(ipaddr), ip4_addr4_16(ipaddr),
429 (u16_t)ethaddr->addr[0], (u16_t)ethaddr->addr[1], (u16_t)ethaddr->addr[2],
430 (u16_t)ethaddr->addr[3], (u16_t)ethaddr->addr[4], (u16_t)ethaddr->addr[5]));
432 if (ip4_addr_isany(ipaddr) ||
433 ip4_addr_isbroadcast(ipaddr,
netif) ||
434 ip4_addr_ismulticast(ipaddr)) {
439 i = etharp_find_entry(ipaddr, flags,
netif);
445#if ETHARP_SUPPORT_STATIC_ENTRIES
446 if (flags & ETHARP_FLAG_STATIC_ENTRY) {
448 arp_table[i].state = ETHARP_STATE_STATIC;
449 }
else if (arp_table[i].state == ETHARP_STATE_STATIC) {
456 arp_table[i].state = ETHARP_STATE_STABLE;
460 arp_table[i].netif =
netif;
462 mib2_add_arp_entry(
netif, &arp_table[i].ipaddr);
466 SMEMCPY(&arp_table[i].ethaddr, ethaddr, ETH_HWADDR_LEN);
468 arp_table[i].ctime = 0;
471 while (arp_table[i].q != NULL) {
474 struct etharp_q_entry *q = arp_table[i].q;
476 arp_table[i].q = q->
next;
482 if (arp_table[i].q != NULL) {
483 struct pbuf *p = arp_table[i].q;
484 arp_table[i].q = NULL;
494#if ETHARP_SUPPORT_STATIC_ENTRIES
508 LWIP_DEBUGF(
ETHARP_DEBUG |
LWIP_DBG_TRACE, (
"etharp_add_static_entry: %"U16_F
".%"U16_F
".%"U16_F
".%"U16_F
" - %02"X16_F
":%02"X16_F
":%02"X16_F
":%02"X16_F
":%02"X16_F
":%02"X16_F
"\n",
509 ip4_addr1_16(ipaddr), ip4_addr2_16(ipaddr), ip4_addr3_16(ipaddr), ip4_addr4_16(ipaddr),
510 (u16_t)ethaddr->addr[0], (u16_t)ethaddr->addr[1], (u16_t)ethaddr->addr[2],
511 (u16_t)ethaddr->addr[3], (u16_t)ethaddr->addr[4], (u16_t)ethaddr->addr[5]));
513 netif = ip4_route(ipaddr);
518 return etharp_update_arp_entry(
netif, ipaddr, ethaddr, ETHARP_FLAG_TRY_HARD | ETHARP_FLAG_STATIC_ENTRY);
530etharp_remove_static_entry(
const ip4_addr_t *ipaddr)
535 ip4_addr1_16(ipaddr), ip4_addr2_16(ipaddr), ip4_addr3_16(ipaddr), ip4_addr4_16(ipaddr)));
538 i = etharp_find_entry(ipaddr, ETHARP_FLAG_FIND_ONLY, NULL);
544 if (arp_table[i].
state != ETHARP_STATE_STATIC) {
549 etharp_free_entry(i);
565 u8_t
state = arp_table[i].state;
567 etharp_free_entry(i);
589 LWIP_ASSERT(
"eth_ret != NULL && ip_ret != NULL",
590 eth_ret != NULL && ip_ret != NULL);
594 i = etharp_find_entry(ipaddr, ETHARP_FLAG_FIND_ONLY,
netif);
595 if ((i >= 0) && (arp_table[i].
state >= ETHARP_STATE_STABLE)) {
596 *eth_ret = &arp_table[i].ethaddr;
597 *ip_ret = &arp_table[i].ipaddr;
615 LWIP_ASSERT(
"ipaddr != NULL", ipaddr != NULL);
616 LWIP_ASSERT(
"netif != NULL",
netif != NULL);
617 LWIP_ASSERT(
"eth_ret != NULL", eth_ret != NULL);
620 *ipaddr = &arp_table[i].ipaddr;
621 *
netif = arp_table[i].netif;
622 *eth_ret = &arp_table[i].ethaddr;
647 u8_t for_us, from_us;
651 LWIP_ERROR(
"netif != NULL", (
netif != NULL),
return;);
657 (hdr->hwlen != ETH_HWADDR_LEN) ||
661 (
"etharp_input: packet dropped, wrong hw type, hwlen, proto, protolen or ethernet type (%"U16_F
"/%"U16_F
"/%"U16_F
"/%"U16_F
")\n",
662 hdr->hwtype, (u16_t)hdr->hwlen, hdr->proto, (u16_t)hdr->protolen));
663 ETHARP_STATS_INC(etharp.proterr);
664 ETHARP_STATS_INC(etharp.drop);
668 ETHARP_STATS_INC(etharp.recv);
678 acd_arp_reply(
netif, hdr);
687 if (ip4_addr_isany_val(*netif_ip4_addr(
netif))) {
692 for_us = (u8_t)ip4_addr_eq(&dipaddr, netif_ip4_addr(
netif));
694 from_us = (u8_t)ip4_addr_eq(&sipaddr, netif_ip4_addr(
netif));
702 etharp_update_arp_entry(
netif, &sipaddr, &(hdr->shwaddr),
703 for_us ? ETHARP_FLAG_TRY_HARD : ETHARP_FLAG_FIND_ONLY);
706 switch (hdr->opcode) {
708 case PP_HTONS(ARP_REQUEST):
715 if (for_us && !from_us) {
720 &hdr->shwaddr, &sipaddr,
723 }
else if (ip4_addr_isany_val(*netif_ip4_addr(
netif))) {
732 case PP_HTONS(ARP_REPLY):
738 ETHARP_STATS_INC(etharp.err);
749etharp_output_to_arp_index(
struct netif *
netif,
struct pbuf *q, netif_addr_idx_t arp_idx)
751 LWIP_ASSERT(
"arp_table[arp_idx].state >= ETHARP_STATE_STABLE",
752 arp_table[arp_idx].state >= ETHARP_STATE_STABLE);
756 if (arp_table[arp_idx].state == ETHARP_STATE_STABLE) {
757 if (arp_table[arp_idx].ctime >= ARP_AGE_REREQUEST_USED_BROADCAST) {
759 if (etharp_request(
netif, &arp_table[arp_idx].ipaddr) ==
ERR_OK) {
760 arp_table[arp_idx].state = ETHARP_STATE_STABLE_REREQUESTING_1;
762 }
else if (arp_table[arp_idx].ctime >= ARP_AGE_REREQUEST_USED_UNICAST) {
764 if (etharp_request_dst(
netif, &arp_table[arp_idx].ipaddr, &arp_table[arp_idx].ethaddr) ==
ERR_OK) {
765 arp_table[arp_idx].state = ETHARP_STATE_STABLE_REREQUESTING_1;
799 LWIP_ASSERT(
"netif != NULL",
netif != NULL);
800 LWIP_ASSERT(
"q != NULL", q != NULL);
801 LWIP_ASSERT(
"ipaddr != NULL", ipaddr != NULL);
807 if (ip4_addr_isbroadcast(ipaddr,
netif)) {
809 dest = (
const struct eth_addr *)ðbroadcast;
811 }
else if (ip4_addr_ismulticast(ipaddr)) {
814 mcastaddr.addr[1] = LL_IP4_MULTICAST_ADDR_1;
815 mcastaddr.addr[2] = LL_IP4_MULTICAST_ADDR_2;
816 mcastaddr.addr[3] = ip4_addr2(ipaddr) & 0x7f;
817 mcastaddr.addr[4] = ip4_addr3(ipaddr);
818 mcastaddr.addr[5] = ip4_addr4(ipaddr);
826 if (!ip4_addr_net_eq(ipaddr, netif_ip4_addr(
netif), netif_ip4_netmask(
netif)) &&
827 !ip4_addr_islinklocal(ipaddr)) {
834 if (!ip4_addr_islinklocal(&iphdr->src))
837#ifdef LWIP_HOOK_ETHARP_GET_GW
840 dst_addr = LWIP_HOOK_ETHARP_GET_GW(
netif, ipaddr);
841 if (dst_addr == NULL)
845 if (!ip4_addr_isany_val(*netif_ip4_gw(
netif))) {
847 dst_addr = netif_ip4_gw(
netif);
856#if LWIP_NETIF_HWADDRHINT
857 if (
netif->hints != NULL) {
859 netif_addr_idx_t etharp_cached_entry =
netif->hints->addr_hint;
862 if ((arp_table[etharp_cached_entry].state >= ETHARP_STATE_STABLE) &&
864 (arp_table[etharp_cached_entry].
netif ==
netif) &&
866 (ip4_addr_eq(dst_addr, &arp_table[etharp_cached_entry].ipaddr))) {
868 ETHARP_STATS_INC(etharp.cachehit);
869 return etharp_output_to_arp_index(
netif, q, etharp_cached_entry);
871#if LWIP_NETIF_HWADDRHINT
879 if ((arp_table[i].state >= ETHARP_STATE_STABLE) &&
883 (ip4_addr_eq(dst_addr, &arp_table[i].ipaddr))) {
885 ETHARP_SET_ADDRHINT(
netif, i);
886 return etharp_output_to_arp_index(
netif, q, i);
891 return etharp_query(
netif, dst_addr, q);
938 int is_new_entry = 0;
943 if (ip4_addr_isbroadcast(ipaddr,
netif) ||
944 ip4_addr_ismulticast(ipaddr) ||
945 ip4_addr_isany(ipaddr)) {
951 i_err = etharp_find_entry(ipaddr, ETHARP_FLAG_TRY_HARD,
netif);
958 ETHARP_STATS_INC(etharp.memerr);
962 LWIP_ASSERT(
"type overflow", (
size_t)i_err < NETIF_ADDR_IDX_MAX);
963 i = (netif_addr_idx_t)i_err;
966 if (arp_table[i].state == ETHARP_STATE_EMPTY) {
968 arp_table[i].state = ETHARP_STATE_PENDING;
970 arp_table[i].netif =
netif;
974 LWIP_ASSERT(
"arp_table[i].state == PENDING or STABLE",
975 ((arp_table[i].state == ETHARP_STATE_PENDING) ||
976 (arp_table[i].state >= ETHARP_STATE_STABLE)));
979 if (is_new_entry || (q == NULL)) {
981 result = etharp_request(
netif, ipaddr);
989 if ((arp_table[i].state == ETHARP_STATE_PENDING) && !is_new_entry) {
993 arp_table[i].ctime = 0;
1002 LWIP_ASSERT(
"q != NULL", q != NULL);
1004 if (arp_table[i].state >= ETHARP_STATE_STABLE) {
1006 ETHARP_SET_ADDRHINT(
netif, i);
1008 result = ethernet_output(
netif, q, srcaddr, &(arp_table[i].ethaddr),
ETHTYPE_IP);
1010 }
else if (arp_table[i].state == ETHARP_STATE_PENDING) {
1013 int copy_needed = 0;
1018 LWIP_ASSERT(
"no packet queues allowed!", (p->len != p->tot_len) || (p->next == NULL));
1037 struct etharp_q_entry *new_entry;
1039 new_entry = (
struct etharp_q_entry *)
memp_malloc(MEMP_ARP_QUEUE);
1040 if (new_entry != NULL) {
1041 unsigned int qlen = 0;
1042 new_entry->next = NULL;
1044 if (arp_table[i].q != NULL) {
1046 struct etharp_q_entry *r;
1049 while (r->next != NULL) {
1053 r->next = new_entry;
1056 arp_table[i].q = new_entry;
1060 struct etharp_q_entry *old;
1061 old = arp_table[i].q;
1062 arp_table[i].q = arp_table[i].q->next;
1072 LWIP_DEBUGF(
ETHARP_DEBUG |
LWIP_DBG_TRACE, (
"etharp_query: could not queue a copy of PBUF_REF packet %p (out of memory)\n", (
void *)q));
1077 if (arp_table[i].q != NULL) {
1078 LWIP_DEBUGF(
ETHARP_DEBUG |
LWIP_DBG_TRACE, (
"etharp_query: dropped previously queued packet %p for ARP entry %"U16_F
"\n", (
void *)q, (u16_t)i));
1086 ETHARP_STATS_INC(etharp.memerr);
1087 LWIP_DEBUGF(
ETHARP_DEBUG |
LWIP_DBG_TRACE, (
"etharp_query: could not queue a copy of PBUF_REF packet %p (out of memory)\n", (
void *)q));
1111 const struct eth_addr *ethdst_addr,
1120 LWIP_ASSERT(
"netif != NULL",
netif != NULL);
1127 (
"etharp_raw: could not allocate pbuf for ARP request.\n"));
1128 ETHARP_STATS_INC(etharp.memerr);
1131 LWIP_ASSERT(
"check that first pbuf can hold struct etharp_hdr",
1132 (p->len >= SIZEOF_ETHARP_HDR));
1136 hdr->opcode = lwip_htons(opcode);
1138 LWIP_ASSERT(
"netif->hwaddr_len must be the same as ETH_HWADDR_LEN for etharp!",
1142 SMEMCPY(&hdr->shwaddr, hwsrc_addr, ETH_HWADDR_LEN);
1143 SMEMCPY(&hdr->dhwaddr, hwdst_addr, ETH_HWADDR_LEN);
1152 hdr->hwlen = ETH_HWADDR_LEN;
1160 if (ip4_addr_islinklocal(ipsrc_addr)) {
1168 ETHARP_STATS_INC(etharp.xmit);
1194 ipaddr, ARP_REQUEST);
1210 return etharp_request_dst(
netif, ipaddr, ðbroadcast);
1229 ipaddr, ARP_REQUEST);
1247 ipaddr, ARP_REQUEST);
#define ip4_addr_copy(dest, src)
#define ip4_addr_set_zero(ipaddr)
#define LWIP_UNUSED_ARG(x)
#define LWIP_ALIGNMENT_CAST(target_type, val)
#define LWIP_DBG_LEVEL_SERIOUS
#define LWIP_DBG_LEVEL_WARNING
@ LWIP_IANA_HWTYPE_ETHERNET
#define ETHARP_TABLE_MATCH_NETIF
#define ETHARP_SUPPORT_STATIC_ENTRIES
#define LWIP_ASSERT_CORE_LOCKED()
#define SMEMCPY(dst, src, len)
void pbuf_ref(struct pbuf *p)
#define PBUF_NEEDS_COPY(p)
u8 pbuf_free(struct pbuf *p)
struct pbuf * pbuf_clone(pbuf_layer l, pbuf_type type, struct pbuf *p)
#define IPADDR_WORDALIGNED_COPY_FROM_IP4_ADDR_T(dest, src)
#define IPADDR_WORDALIGNED_COPY_TO_IP4_ADDR_T(dest, src)
#define LL_IP4_MULTICAST_ADDR_0
void * memp_malloc(memp_t type)
void memp_free(memp_t type, void *mem)
struct ip4_addr ip4_addr_t
u8 hwaddr[NETIF_MAX_HWADDR_LEN]