static void refresh_cache(struct ip_addr *dst_ip) { struct netif *netif; netif = ip_route(dst_ip); errval_t r = etharp_request(netif, dst_ip); assert(err_is_ok(r)); while (is_ip_present_in_arp_cache(dst_ip) == false) { r = event_dispatch(ws); if (err_is_fail(r)) { DEBUG_ERR(r, "in event_dispatch"); abort(); } } // end while: till arp not present }
extern ipal_result_t ipal_arp_request(ipal_ipv4addr_t ip, ipal_arp_cachemode_t cm) { int8_t ret; err_t err; ipal_eth_hid_netif * netif_ptr; struct ip_addr ipaddr; struct eth_addr *eth_ret; struct ip_addr *ip_ret; #warning: arp cache mode useless //in lwip i can not found something similar to cachemode. if(0 == ipal_sys_hid_started) { return(ipal_res_NOK_generic); } ipaddr.addr = ipal2lwip_ipv4addr(ip); ipal_base_hid_threadsafety_lock(); netif_ptr = ipal_eth_hid_getnetif(); ret = etharp_find_addr(&(netif_ptr->netif), &ipaddr, ð_ret, &ip_ret); if(ret != -1 ) { //ip addr presente in arp tbl, allora ritorno con sucesso ipal_base_hid_threadsafety_unlock(); return(ipal_res_OK); } //se sopno qui ==> ip addr non presente in tbl arp ==> faccio una request err = etharp_request(&(netif_ptr->netif), &ipaddr); ipal_base_hid_threadsafety_unlock(); return( (ERR_OK == err) ? (ipal_res_OK) : (ipal_res_NOK_generic) ); //se sono qui vuol dire che devoi fare una arp request e che quindi la mia arp table non contiene ancora nessuna entry relatina a @ip //return(ipal_res_NOK_generic); }
/** * Clears expired entries in the ARP table. * * This function should be called every ARP_TMR_INTERVAL milliseconds (1 second), * in order to expire entries in the ARP table. */ void etharp_tmr(void) { u8_t i; LWIP_DEBUGF(ETHARP_DEBUG, ("etharp_timer\n")); /* remove expired entries from the ARP table */ for (i = 0; i < ARP_TABLE_SIZE; ++i) { u8_t state = arp_table[i].state; if (state != ETHARP_STATE_EMPTY #if ETHARP_SUPPORT_STATIC_ENTRIES && (state != ETHARP_STATE_STATIC) #endif /* ETHARP_SUPPORT_STATIC_ENTRIES */ ) { arp_table[i].ctime++; if ((arp_table[i].ctime >= ARP_MAXAGE) || ((arp_table[i].state == ETHARP_STATE_PENDING) && (arp_table[i].ctime >= ARP_MAXPENDING))) { /* pending or stable entry has become old! */ LWIP_DEBUGF(ETHARP_DEBUG, ("etharp_timer: expired %s entry %"U16_F".\n", arp_table[i].state >= ETHARP_STATE_STABLE ? "stable" : "pending", (u16_t)i)); /* clean up entries that have just been expired */ etharp_free_entry(i); } else if (arp_table[i].state == ETHARP_STATE_STABLE_REREQUESTING_1) { /* Don't send more than one request every 2 seconds. */ arp_table[i].state = ETHARP_STATE_STABLE_REREQUESTING_2; } else if (arp_table[i].state == ETHARP_STATE_STABLE_REREQUESTING_2) { /* Reset state to stable, so that the next transmitted packet will re-send an ARP request. */ arp_table[i].state = ETHARP_STATE_STABLE; } else if (arp_table[i].state == ETHARP_STATE_PENDING) { /* still pending, resend an ARP query */ etharp_request(arp_table[i].netif, &arp_table[i].ipaddr); } } } }
/** * Send an ARP request for the given IP address and/or queue a packet. * * If the IP address was not yet in the cache, a pending ARP cache entry * is added and an ARP request is sent for the given address. The packet * is queued on this entry. * * If the IP address was already pending in the cache, a new ARP request * is sent for the given address. The packet is queued on this entry. * * If the IP address was already stable in the cache, and a packet is * given, it is directly sent and no ARP request is sent out. * * If the IP address was already stable in the cache, and no packet is * given, an ARP request is sent out. * * @param netif The lwIP network interface on which ipaddr * must be queried for. * @param ipaddr The IP address to be resolved. * @param q If non-NULL, a pbuf that must be delivered to the IP address. * q is not freed by this function. * * @return * - ERR_BUF Could not make room for Ethernet header. * - ERR_MEM Hardware address unknown, and no more ARP entries available * to query for address or queue the packet. * - ERR_MEM Could not queue packet due to memory shortage. * - ERR_RTE No route to destination (no gateway to external networks). * - ERR_ARG Non-unicast address given, those will not appear in ARP cache. * */ err_t etharp_query(struct netif *netif, struct ip_addr *ipaddr, struct pbuf *q) { struct eth_addr * srcaddr = (struct eth_addr *)netif->hwaddr; err_t result = ERR_MEM; s8_t i; /* ARP entry index */ u8_t k; /* Ethernet address octet index */ /* non-unicast address? */ if (ip_addr_isbroadcast(ipaddr, netif) || ip_addr_ismulticast(ipaddr) || ip_addr_isany(ipaddr)) { LWIP_DEBUGF(ETHARP_DEBUG | DBG_TRACE, ("etharp_query: will not add non-unicast IP address to ARP cache\n")); return ERR_ARG; } /* find entry in ARP cache, ask to create entry if queueing packet */ i = find_entry(ipaddr, ETHARP_TRY_HARD); /* could not find or create entry? */ if (i < 0) { LWIP_DEBUGF(ETHARP_DEBUG | DBG_TRACE, ("etharp_query: could not create ARP entry\n")); if (q) LWIP_DEBUGF(ETHARP_DEBUG | DBG_TRACE, ("etharp_query: packet dropped\n")); return (err_t)i; } /* mark a fresh entry as pending (we just sent a request) */ if (arp_table[i].state == ETHARP_STATE_EMPTY) { arp_table[i].state = ETHARP_STATE_PENDING; } /* { i is either a STABLE or (new or existing) PENDING entry } */ LWIP_ASSERT("arp_table[i].state == PENDING or STABLE", ((arp_table[i].state == ETHARP_STATE_PENDING) || (arp_table[i].state == ETHARP_STATE_STABLE))); /* do we have a pending entry? or an implicit query request? */ if ((arp_table[i].state == ETHARP_STATE_PENDING) || (q == NULL)) { /* try to resolve it; send out ARP request */ result = etharp_request(netif, ipaddr); } /* packet given? */ if (q != NULL) { /* stable entry? */ if (arp_table[i].state == ETHARP_STATE_STABLE) { /* we have a valid IP->Ethernet address mapping, * fill in the Ethernet header for the outgoing packet */ struct eth_hdr *ethhdr = q->payload; for(k = 0; k < netif->hwaddr_len; k++) { ethhdr->dest.addr[k] = arp_table[i].ethaddr.addr[k]; ethhdr->src.addr[k] = srcaddr->addr[k]; } ethhdr->type = htons(ETHTYPE_IP); LWIP_DEBUGF(ETHARP_DEBUG | DBG_TRACE, ("etharp_query: sending packet %p\n", (void *)q)); /* send the packet */ result = netif->linkoutput(netif, q); /* pending entry? (either just created or already pending */ } else if (arp_table[i].state == ETHARP_STATE_PENDING) { #if ARP_QUEUEING /* queue the given q packet */ struct pbuf *p; /* copy any PBUF_REF referenced payloads into PBUF_RAM */ /* (the caller of lwIP assumes the referenced payload can be * freed after it returns from the lwIP call that brought us here) */ p = pbuf_take(q); /* packet could be taken over? */ if (p != NULL) { /* queue packet ... */ if (arp_table[i].p == NULL) { /* ... in the empty queue */ pbuf_ref(p); arp_table[i].p = p; #if 0 /* multi-packet-queueing disabled, see bug #11400 */ } else { /* ... at tail of non-empty queue */ pbuf_queue(arp_table[i].p, p); #endif } LWIP_DEBUGF(ETHARP_DEBUG | DBG_TRACE, ("etharp_query: queued packet %p on ARP entry %"S16_F"\n", (void *)q, (s16_t)i)); result = ERR_OK; } else { LWIP_DEBUGF(ETHARP_DEBUG | DBG_TRACE, ("etharp_query: could not queue a copy of PBUF_REF packet %p (out of memory)\n", (void *)q)); /* { result == ERR_MEM } through initialization */ } #else /* ARP_QUEUEING == 0 */ /* q && state == PENDING && ARP_QUEUEING == 0 => result = ERR_MEM */ /* { result == ERR_MEM } through initialization */ LWIP_DEBUGF(ETHARP_DEBUG | DBG_TRACE, ("etharp_query: Ethernet destination address unknown, queueing disabled, packet %p dropped\n", (void *)q)); #endif } } return result; }
static int LinkLocal_IP_Query(uint32 IP, struct netif *netif){ struct ip_addr ipaddr; ipaddr.addr = IP; return etharp_request(netif, &ipaddr); }
/** * Has to be called in loop every AUTOIP_TMR_INTERVAL milliseconds */ void autoip_tmr () { struct netif *netif = netif_list; /* loop through netif's */ while (netif != NULL) { /* only act on AutoIP configured interfaces */ if (netif->autoip != NULL) { if (netif->autoip->lastconflict > 0) { netif->autoip->lastconflict--; } LWIP_DEBUGF (AUTOIP_DEBUG | LWIP_DBG_TRACE, ("autoip_tmr() AutoIP-State: %" U16_F ", ttw=%" U16_F "\n", (u16_t) (netif->autoip->state), netif->autoip->ttw)); switch (netif->autoip->state) { case AUTOIP_STATE_PROBING: if (netif->autoip->ttw > 0) { netif->autoip->ttw--; } else { if (netif->autoip->sent_num == PROBE_NUM) { netif->autoip->state = AUTOIP_STATE_ANNOUNCING; netif->autoip->sent_num = 0; netif->autoip->ttw = ANNOUNCE_WAIT * AUTOIP_TICKS_PER_SECOND; } else { etharp_request (netif, &(netif->autoip->llipaddr)); LWIP_DEBUGF (AUTOIP_DEBUG | LWIP_DBG_TRACE | 3, ("autoip_tmr() PROBING Sent Probe\n")); netif->autoip->sent_num++; /* calculate time to wait to next probe */ netif->autoip->ttw = (u16_t) ((LWIP_AUTOIP_RAND (netif) % ((PROBE_MAX - PROBE_MIN) * AUTOIP_TICKS_PER_SECOND)) + PROBE_MIN * AUTOIP_TICKS_PER_SECOND); } } break; case AUTOIP_STATE_ANNOUNCING: if (netif->autoip->ttw > 0) { netif->autoip->ttw--; } else { if (netif->autoip->sent_num == 0) { /* We are here the first time, so we waited ANNOUNCE_WAIT seconds * Now we can bind to an IP address and use it */ autoip_bind (netif); } if (netif->autoip->sent_num == ANNOUNCE_NUM) { netif->autoip->state = AUTOIP_STATE_BOUND; netif->autoip->sent_num = 0; netif->autoip->ttw = 0; } else { autoip_arp_announce (netif); LWIP_DEBUGF (AUTOIP_DEBUG | LWIP_DBG_TRACE | 3, ("autoip_tmr() ANNOUNCING Sent Announce\n")); netif->autoip->sent_num++; netif->autoip->ttw = ANNOUNCE_INTERVAL * AUTOIP_TICKS_PER_SECOND; } } break; } } /* proceed to next network interface */ netif = netif->next; } }