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;
108#if !LWIP_NETIF_HWADDRHINT
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"
134static err_t etharp_request_dst(
struct netif *
netif,
const ip4_addr_t *ipaddr,
const struct eth_addr *hw_dst_addr);
137 const struct eth_addr *hwsrc_addr,
const ip4_addr_t *ipsrc_addr,
138 const struct eth_addr *hwdst_addr,
const ip4_addr_t *ipdst_addr,
148free_etharp_q(
struct etharp_q_entry *
q)
150 struct etharp_q_entry *
r;
163#define free_etharp_q(q) pbuf_free(q)
169etharp_free_entry(
int i)
174 if (arp_table[
i].
q !=
NULL) {
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;
186 ip4_addr_set_zero(&arp_table[
i].ipaddr);
187 arp_table[
i].ethaddr = ethzero;
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))) {
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;
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) ||
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) {
395 ip4_addr_copy(arp_table[
i].ipaddr, *ipaddr);
397 arp_table[
i].ctime = 0;
398#if ETHARP_TABLE_MATCH_NETIF
399 arp_table[
i].netif =
netif;
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)) {
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;
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
504etharp_add_static_entry(
const ip4_addr_t *ipaddr,
struct eth_addr *ethaddr)
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);
567 etharp_free_entry(
i);
584etharp_find_addr(
struct netif *
netif,
const ip4_addr_t *ipaddr,
585 struct eth_addr **eth_ret,
const ip4_addr_t **ip_ret)
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;
613etharp_get_entry(
size_t i, ip4_addr_t **ipaddr,
struct netif **
netif,
struct eth_addr **eth_ret)
620 *ipaddr = &arp_table[
i].ipaddr;
621 *
netif = arp_table[
i].netif;
622 *eth_ret = &arp_table[
i].ethaddr;
646 ip4_addr_t sipaddr, dipaddr;
647 u8_t for_us, from_us;
658 (
hdr->protolen !=
sizeof(ip4_addr_t)) ||
661 (
"etharp_input: packet dropped, wrong hw type, hwlen, proto, protolen or ethernet type (%"U16_F"/%"U16_F"/%"U16_F"/%"U16_F")\n",
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) {
715 if (for_us && !from_us) {
720 &
hdr->shwaddr, &sipaddr,
723 }
else if (ip4_addr_isany_val(*netif_ip4_addr(
netif))) {
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;
792etharp_output(
struct netif *
netif,
struct pbuf *
q,
const ip4_addr_t *ipaddr)
796 const ip4_addr_t *dst_addr = ipaddr;
807 if (ip4_addr_isbroadcast(ipaddr,
netif)) {
811 }
else if (ip4_addr_ismulticast(ipaddr)) {
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
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))) {
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);
934etharp_query(
struct netif *
netif,
const ip4_addr_t *ipaddr,
struct pbuf *
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);
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)) {
989 if ((arp_table[
i].
state == ETHARP_STATE_PENDING) && !is_new_entry) {
993 arp_table[
i].ctime = 0;
1004 if (arp_table[
i].
state >= ETHARP_STATE_STABLE) {
1006 ETHARP_SET_ADDRHINT(
netif,
i);
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;
1077 if (arp_table[
i].
q !=
NULL) {
1111 const struct eth_addr *ethdst_addr,
1112 const struct eth_addr *hwsrc_addr,
const ip4_addr_t *ipsrc_addr,
1113 const struct eth_addr *hwdst_addr,
const ip4_addr_t *ipdst_addr,
1127 (
"etharp_raw: could not allocate pbuf for ARP request.\n"));
1131 LWIP_ASSERT(
"check that first pbuf can hold struct etharp_hdr",
1138 LWIP_ASSERT(
"netif->hwaddr_len must be the same as ETH_HWADDR_LEN for etharp!",
1153 hdr->protolen =
sizeof(ip4_addr_t);
1160 if (ip4_addr_islinklocal(ipsrc_addr)) {
1190etharp_request_dst(
struct netif *
netif,
const ip4_addr_t *ipaddr,
const struct eth_addr *hw_dst_addr)
1207etharp_request(
struct netif *
netif,
const ip4_addr_t *ipaddr)
1210 return etharp_request_dst(
netif, ipaddr, ðbroadcast);
1225etharp_acd_probe(
struct netif *
netif,
const ip4_addr_t *ipaddr)
1243etharp_acd_announce(
struct netif *
netif,
const ip4_addr_t *ipaddr)
static const WCHAR empty[]
#define LWIP_DEBUGF(debug, message)
#define LWIP_ERROR(message, expression, handler)
#define LWIP_ASSERT(message, assertion)
#define mib2_remove_arp_entry(ni, ip)
#define mib2_add_arp_entry(ni, ip)
GLdouble GLdouble GLdouble r
GLdouble GLdouble GLdouble GLdouble q
GLsizei GLenum const GLvoid GLsizei GLenum GLbyte GLbyte GLbyte GLdouble GLdouble GLdouble GLfloat GLfloat GLfloat GLint GLint GLint GLshort GLshort GLshort GLubyte GLubyte GLubyte GLuint GLuint GLuint GLushort GLushort GLushort GLbyte GLbyte GLbyte GLbyte GLdouble GLdouble GLdouble GLdouble GLfloat GLfloat GLfloat GLfloat GLint GLint GLint GLint GLshort GLshort GLshort GLshort GLubyte GLubyte GLubyte GLubyte GLuint GLuint GLuint GLuint GLushort GLushort GLushort GLushort GLboolean const GLdouble const GLfloat const GLint const GLshort const GLbyte const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLdouble const GLfloat const GLfloat const GLint const GLint const GLshort const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort GLenum GLenum GLenum GLfloat GLenum GLint GLenum GLenum GLenum GLfloat GLenum GLenum GLint GLenum GLfloat GLenum GLint GLint GLushort GLenum GLenum GLfloat GLenum GLenum GLint GLfloat const GLubyte GLenum GLenum GLenum const GLfloat GLenum GLenum const GLint GLenum GLint GLint GLsizei GLsizei GLint GLenum GLenum const GLvoid GLenum GLenum const GLfloat GLenum GLenum const GLint GLenum GLenum const GLdouble GLenum GLenum const GLfloat GLenum GLenum const GLint GLsizei GLuint GLfloat GLuint GLbitfield GLfloat GLint GLuint GLboolean GLenum GLfloat GLenum GLbitfield GLenum GLfloat GLfloat GLint GLint const GLfloat GLenum GLfloat GLfloat GLint GLint GLfloat GLfloat GLint GLint const GLfloat GLint GLfloat GLfloat GLint GLfloat GLfloat GLint GLfloat GLfloat const GLdouble const GLfloat const GLdouble const GLfloat GLint i
#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)
struct pbuf * pbuf_alloc(pbuf_layer layer, u16_t length, pbuf_type type)
u8_t pbuf_free(struct pbuf *p)
struct pbuf * pbuf_clone(pbuf_layer layer, pbuf_type type, struct pbuf *p)
#define SIZEOF_ETHARP_HDR
#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_2
#define LL_IP4_MULTICAST_ADDR_1
#define LL_IP4_MULTICAST_ADDR_0
void * memp_malloc(memp_t type)
void memp_free(memp_t type, void *mem)
#define NETIF_ADDR_IDX_MAX
#define ETHARP_STATS_INC(x)
u8_t hwaddr[NETIF_MAX_HWADDR_LEN]