#include "lwip/opt.h"
#include "lwip/inet.h"
#include "netif/etharp.h"
#include "lwip/ip.h"
#include "lwip/stats.h"
Include dependency graph for etharp.c:
Go to the source code of this file.
Data Structures | |
struct | etharp_entry |
Defines | |
#define | htons HTONS |
#define | htonl HTONL |
#define | ARP_MAXAGE 120 |
#define | ARP_MAXPENDING 2 |
#define | HWTYPE_ETHERNET 1 |
#define | ARP_REQUEST 1 |
#define | ARP_REPLY 2 |
#define | ARPH_HWLEN(hdr) (ntohs((hdr)->_hwlen_protolen) >> 8) |
#define | ARPH_PROTOLEN(hdr) (ntohs((hdr)->_hwlen_protolen) & 0xff) |
#define | ARPH_HWLEN_SET(hdr, len) (hdr)->_hwlen_protolen = htons(ARPH_PROTOLEN(hdr) | ((len) << 8)) |
#define | ARPH_PROTOLEN_SET(hdr, len) (hdr)->_hwlen_protolen = htons((len) | (ARPH_HWLEN(hdr) << 8)) |
#define | ARP_INSERT_FLAG 1 |
Enumerations | |
enum | etharp_state { ETHARP_STATE_EMPTY, ETHARP_STATE_PENDING, ETHARP_STATE_STABLE } |
Functions | |
pbuf * | update_arp_entry (struct netif *netif, struct ip_addr *ipaddr, struct eth_addr *ethaddr, u8_t flags) |
void | etharp_init (void) |
void | etharp_tmr (void) |
u8_t | find_arp_entry (void) |
pbuf * | etharp_ip_input (struct netif *netif, struct pbuf *p) |
pbuf * | etharp_arp_input (struct netif *netif, struct eth_addr *ethaddr, struct pbuf *p) |
pbuf * | etharp_output (struct netif *netif, struct ip_addr *ipaddr, struct pbuf *q) |
err_t | etharp_query (struct netif *netif, struct ip_addr *ipaddr, struct pbuf *q) |
Variables | |
const struct eth_addr | ethbroadcast = {{0xff,0xff,0xff,0xff,0xff,0xff}} |
etharp_entry | arp_table [ARP_TABLE_SIZE] |
Definition in file etharp.c.
|
Definition at line 122 of file etharp.c. Referenced by etharp_arp_input(), etharp_ip_input(), and update_arp_entry(). |
|
the time an ARP entry stays valid after its last update, (120 * 10) seconds = 20 minutes. |
|
the time an ARP entry stays pending after first request, (2 * 10) seconds = 20 seconds. Definition at line 88 of file etharp.c. Referenced by etharp_tmr(). |
|
|
|
ARP message types |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
Definition at line 102 of file etharp.c.
00102 { 00103 ETHARP_STATE_EMPTY, 00104 ETHARP_STATE_PENDING, 00105 ETHARP_STATE_STABLE 00106 }; |
|
Responds to ARP requests, updates ARP entries and sends queued IP packets. Should be called for incoming ARP packets. The pbuf in the argument is freed by this function.
Definition at line 396 of file etharp.c. References ip_addr::addr, ARP_INSERT_FLAG, ARP_REPLY, ARP_REQUEST, ARPH_HWLEN_SET, ARPH_PROTOLEN_SET, DBG_TRACE, DEBUGF, ETHARP_DEBUG, ETHTYPE_ARP, ETHTYPE_IP, htons, netif::hwaddr_len, HWTYPE_ETHERNET, netif::ip_addr, ip_addr_cmp, ip_addr_set, netif::linkoutput, NULL, pbuf::payload, pbuf_free(), pbuf::tot_len, u8_t, and update_arp_entry(). Referenced by rt_3c905cif_input(), and rt_rtl8139if_input().
00397 { 00398 struct etharp_hdr *hdr; 00399 u8_t i; 00400 00401 /* drop short ARP packets */ 00402 if(p->tot_len < sizeof(struct etharp_hdr)) { 00403 DEBUGF(ETHARP_DEBUG | DBG_TRACE | 1, ("etharp_arp_input: packet too short (%d/%d)\n", p->tot_len, sizeof(struct etharp_hdr))); 00404 pbuf_free(p); 00405 return NULL; 00406 } 00407 00408 hdr = p->payload; 00409 00410 switch(htons(hdr->opcode)) { 00411 /* ARP request? */ 00412 case ARP_REQUEST: 00413 /* ARP request. If it asked for our address, we send out a 00414 reply. In any case, we time-stamp any existing ARP entry, 00415 and possiby send out an IP packet that was queued on it. */ 00416 00417 DEBUGF(ETHARP_DEBUG | DBG_TRACE, ("etharp_arp_input: incoming ARP request\n")); 00418 /* we are not configured? */ 00419 if(netif->ip_addr.addr == 0) { 00420 DEBUGF(ETHARP_DEBUG | DBG_TRACE, ("etharp_arp_input: we are unconfigured, ARP request ignored.\n")); 00421 pbuf_free(p); 00422 return NULL; 00423 } 00424 /* update the ARP cache */ 00425 update_arp_entry(netif, &(hdr->sipaddr), &(hdr->shwaddr), 0); 00426 /* ARP request for our address? */ 00427 if(ip_addr_cmp(&(hdr->dipaddr), &(netif->ip_addr))) { 00428 00429 DEBUGF(ETHARP_DEBUG | DBG_TRACE, ("etharp_arp_input: replying to ARP request for our IP address\n")); 00430 /* re-use pbuf to send ARP reply */ 00431 hdr->opcode = htons(ARP_REPLY); 00432 00433 ip_addr_set(&(hdr->dipaddr), &(hdr->sipaddr)); 00434 ip_addr_set(&(hdr->sipaddr), &(netif->ip_addr)); 00435 00436 for(i = 0; i < netif->hwaddr_len; ++i) { 00437 hdr->dhwaddr.addr[i] = hdr->shwaddr.addr[i]; 00438 hdr->shwaddr.addr[i] = ethaddr->addr[i]; 00439 hdr->ethhdr.dest.addr[i] = hdr->dhwaddr.addr[i]; 00440 hdr->ethhdr.src.addr[i] = ethaddr->addr[i]; 00441 } 00442 00443 hdr->hwtype = htons(HWTYPE_ETHERNET); 00444 ARPH_HWLEN_SET(hdr, netif->hwaddr_len); 00445 00446 hdr->proto = htons(ETHTYPE_IP); 00447 ARPH_PROTOLEN_SET(hdr, sizeof(struct ip_addr)); 00448 00449 hdr->ethhdr.type = htons(ETHTYPE_ARP); 00450 /* return ARP reply */ 00451 netif->linkoutput(netif, p); 00452 } else { 00453 DEBUGF(ETHARP_DEBUG | DBG_TRACE, ("etharp_arp_input: incoming ARP request was not for us.\n")); 00454 } 00455 break; 00456 case ARP_REPLY: 00457 /* ARP reply. We insert or update the ARP table. */ 00458 DEBUGF(ETHARP_DEBUG | DBG_TRACE, ("etharp_arp_input: incoming ARP reply\n")); 00459 #if (LWIP_DHCP && DHCP_DOES_ARP_CHECK) 00460 /* DHCP needs to know about ARP replies */ 00461 dhcp_arp_reply(netif, &hdr->sipaddr); 00462 #endif 00463 /* ARP reply directed to us? */ 00464 if(ip_addr_cmp(&(hdr->dipaddr), &(netif->ip_addr))) { 00465 DEBUGF(ETHARP_DEBUG | DBG_TRACE, ("etharp_arp_input: incoming ARP reply is for us\n")); 00466 /* update_the ARP cache, ask to insert */ 00467 update_arp_entry(netif, &(hdr->sipaddr), &(hdr->shwaddr), ARP_INSERT_FLAG); 00468 /* ARP reply not directed to us */ 00469 } else { 00470 DEBUGF(ETHARP_DEBUG | DBG_TRACE, ("etharp_arp_input: incoming ARP reply is not for us\n")); 00471 /* update the destination address pair */ 00472 update_arp_entry(netif, &(hdr->sipaddr), &(hdr->shwaddr), 0); 00473 /* update the destination address pair */ 00474 update_arp_entry(netif, &(hdr->dipaddr), &(hdr->dhwaddr), 0); 00475 } 00476 break; 00477 default: 00478 DEBUGF(ETHARP_DEBUG | DBG_TRACE, ("etharp_arp_input: ARP unknown opcode type %d\n", htons(hdr->opcode))); 00479 break; 00480 } 00481 /* free ARP packet */ 00482 pbuf_free(p); 00483 p = NULL; 00484 /* nothing to send, we did it! */ 00485 return NULL; 00486 } |
Here is the call graph for this function:
|
Initializes ARP module. Definition at line 128 of file etharp.c. References arp_table, ETHARP_STATE_EMPTY, NULL, etharp_entry::state, and u8_t. Referenced by rt_3c905cif_init(), and rt_rtl8139if_init().
|
|
Updates the ARP table using the given packet. Uses the incoming IP packet's source address to update the ARP cache for the local network. The function does not alter or free the packet. This function must be called before the packet p is passed to the IP layer.
Definition at line 361 of file etharp.c. References ARP_INSERT_FLAG, DBG_TRACE, DEBUGF, ETHARP_DEBUG, netif::ip_addr, ip_addr_maskcmp, netif::netmask, NULL, pbuf::payload, and update_arp_entry(). Referenced by rt_3c905cif_input(), and rt_rtl8139if_input().
00362 { 00363 struct ethip_hdr *hdr; 00364 00365 /* Only insert an entry if the source IP address of the 00366 incoming IP packet comes from a host on the local network. */ 00367 hdr = p->payload; 00368 /* source is on local network? */ 00369 if(!ip_addr_maskcmp(&(hdr->ip.src), &(netif->ip_addr), &(netif->netmask))) { 00370 /* do nothing */ 00371 return NULL; 00372 } 00373 00374 DEBUGF(ETHARP_DEBUG | DBG_TRACE, ("etharp_ip_input: updating ETHARP table.\n")); 00375 /* update ARP table, ask to insert entry */ 00376 update_arp_entry(netif, &(hdr->ip.src), &(hdr->eth.src), ARP_INSERT_FLAG); 00377 return NULL; 00378 } |
Here is the call graph for this function:
|
Resolve and fill-in Ethernet address header for outgoing packet. If ARP has the Ethernet address in cache, the given packet is returned, ready to be sent. If ARP does not have the Ethernet address in cache the packet is queued and a ARP request is sent (on a best-effort basis). This ARP request is returned as a pbuf, which should be sent by the caller. If ARP failed to allocate resources, NULL is returned. A returned non-NULL packet should be sent by the caller and etharp_output_sent() must be called afterwards to free any ARP request.
Definition at line 513 of file etharp.c. References ip_addr::addr, arp_table, DBG_TRACE, DEBUGF, etharp_entry::ethaddr, ETHARP_DEBUG, etharp_query(), ETHARP_STATE_STABLE, ethbroadcast, ETHTYPE_IP, netif::gw, htons, netif::hwaddr, netif::hwaddr_len, ip4_addr2, ip4_addr3, ip4_addr4, netif::ip_addr, ip_addr_cmp, ip_addr_isany, ip_addr_isbroadcast, ip_addr_ismulticast, ip_addr_maskcmp, ipaddr, netif::netmask, NULL, pbuf::payload, pbuf_header(), etharp_entry::state, and u8_t. Referenced by rt_3c905cif_output(), and rt_rtl8139if_output().
00514 { 00515 struct eth_addr *dest, *srcaddr, mcastaddr; 00516 struct eth_hdr *ethhdr; 00517 u8_t i; 00518 00519 /* Make room for Ethernet header. */ 00520 if(pbuf_header(q, sizeof(struct eth_hdr)) != 0) { 00521 /* The pbuf_header() call shouldn't fail, and we'll just bail 00522 out if it does.. */ 00523 DEBUGF(ETHARP_DEBUG | DBG_TRACE | 2, ("etharp_output: could not allocate room for header.\n")); 00524 #ifdef LINK_STATS 00525 ++lwip_stats.link.lenerr; 00526 #endif /* LINK_STATS */ 00527 return NULL; 00528 } 00529 00530 /* obtain source Ethernet address of the given interface */ 00531 srcaddr = (struct eth_addr *)netif->hwaddr; 00532 00533 /* assume unresolved Ethernet address */ 00534 dest = NULL; 00535 /* Construct Ethernet header. Start with looking up deciding which 00536 MAC address to use as a destination address. Broadcasts and 00537 multicasts are special, all other addresses are looked up in the 00538 ARP table. */ 00539 00540 /* destination IP address is an IP broadcast address? */ 00541 if(ip_addr_isany(ipaddr) || 00542 ip_addr_isbroadcast(ipaddr, &(netif->netmask))) { 00543 /* broadcast on Ethernet also */ 00544 dest = (struct eth_addr *)ðbroadcast; 00545 } 00546 /* destination IP address is an IP multicast address? */ 00547 else if(ip_addr_ismulticast(ipaddr)) { 00548 /* Hash IP multicast address to MAC address. */ 00549 mcastaddr.addr[0] = 0x01; 00550 mcastaddr.addr[1] = 0x0; 00551 mcastaddr.addr[2] = 0x5e; 00552 mcastaddr.addr[3] = ip4_addr2(ipaddr) & 0x7f; 00553 mcastaddr.addr[4] = ip4_addr3(ipaddr); 00554 mcastaddr.addr[5] = ip4_addr4(ipaddr); 00555 /* destination Ethernet address is multicast */ 00556 dest = &mcastaddr; 00557 } 00558 /* destination IP address is an IP unicast address */ 00559 else { 00560 /* destination IP network address not on local network? */ 00561 /* this occurs if the packet is routed to the default gateway on this interface */ 00562 if(!ip_addr_maskcmp(ipaddr, &(netif->ip_addr), &(netif->netmask))) { 00563 /* gateway available? */ 00564 if (netif->gw.addr != 0) 00565 { 00566 /* use the gateway IP address */ 00567 ipaddr = &(netif->gw); 00568 } 00569 /* no gateway available? */ 00570 else 00571 { 00572 /* IP destination address outside local network, but no gateway available */ 00573 return NULL; 00574 } 00575 } 00576 00577 /* Ethernet address for IP destination address is in ARP cache? */ 00578 for(i = 0; i < ARP_TABLE_SIZE; ++i) { 00579 /* match found? */ 00580 if(arp_table[i].state == ETHARP_STATE_STABLE && 00581 ip_addr_cmp(ipaddr, &arp_table[i].ipaddr)) { 00582 dest = &arp_table[i].ethaddr; 00583 break; 00584 } 00585 } 00586 /* could not find the destination Ethernet address in ARP cache? */ 00587 if (dest == NULL) { 00588 /* ARP query for the IP address, submit this IP packet for queueing */ 00589 etharp_query(netif, ipaddr, q); 00590 /* return nothing */ 00591 return NULL; 00592 } 00593 /* destination Ethernet address resolved from ARP cache */ 00594 else 00595 { 00596 /* fallthrough */ 00597 } 00598 } 00599 00600 /* destination Ethernet address known */ 00601 if (dest != NULL) { 00602 /* A valid IP->MAC address mapping was found, so we construct the 00603 Ethernet header for the outgoing packet. */ 00604 ethhdr = q->payload; 00605 00606 for(i = 0; i < netif->hwaddr_len; i++) { 00607 ethhdr->dest.addr[i] = dest->addr[i]; 00608 ethhdr->src.addr[i] = srcaddr->addr[i]; 00609 } 00610 00611 ethhdr->type = htons(ETHTYPE_IP); 00612 /* return the outgoing packet */ 00613 return q; 00614 } 00615 /* never reached; here for safety */ 00616 return NULL; 00617 } |
Here is the call graph for this function:
|
Send an ARP request for the given IP address. Sends an ARP request for the given IP address, unless a request for this address is already pending. Optionally queues an outgoing packet on the resulting ARP entry.
Definition at line 644 of file etharp.c. References ARP_REQUEST, arp_table, ARPH_HWLEN_SET, ARPH_PROTOLEN_SET, etharp_entry::ctime, DBG_STATE, DBG_TRACE, DEBUGF, ERR_MEM, ERR_OK, err_t, ETHARP_DEBUG, ETHARP_STATE_PENDING, ETHARP_STATE_STABLE, ETHTYPE_ARP, ETHTYPE_IP, find_arp_entry(), htons, netif::hwaddr, netif::hwaddr_len, HWTYPE_ETHERNET, netif::ip_addr, ip_addr_cmp, ip_addr_set, ipaddr, netif::linkoutput, NULL, pbuf_alloc(), pbuf_free(), PBUF_LINK, PBUF_RAM, pbuf_ref(), pbuf_take(), etharp_entry::state, and u8_t. Referenced by dhcp_check(), and etharp_output().
00645 { 00646 struct eth_addr *srcaddr; 00647 struct etharp_hdr *hdr; 00648 struct pbuf *p; 00649 err_t result = ERR_OK; 00650 u8_t i; 00651 u8_t perform_arp_request = 1; 00652 /* prevent warning if ARP_QUEUEING == 0 */ 00653 if (q); 00654 00655 srcaddr = (struct eth_addr *)netif->hwaddr; 00656 /* bail out if this IP address is pending */ 00657 for(i = 0; i < ARP_TABLE_SIZE; ++i) { 00658 if(ip_addr_cmp(ipaddr, &arp_table[i].ipaddr)) { 00659 if (arp_table[i].state == ETHARP_STATE_PENDING) { 00660 DEBUGF(ETHARP_DEBUG | DBG_TRACE | DBG_STATE, ("etharp_query: requested IP already pending as entry %u\n", i)); 00661 /* break out of for-loop, user may wish to queue a packet on a stable entry */ 00662 break; 00663 } 00664 else if (arp_table[i].state == ETHARP_STATE_STABLE) { 00665 DEBUGF(ETHARP_DEBUG | DBG_TRACE | DBG_STATE, ("etharp_query: requested IP already stable as entry %u\n", i)); 00666 /* user may wish to queue a packet on a stable entry, so we proceed without ARP requesting */ 00667 /* TODO: even if the ARP entry is stable, we might do an ARP request anyway in some cases? */ 00668 perform_arp_request = 0; 00669 break; 00670 } 00671 } 00672 } 00673 /* queried address not yet in ARP table? */ 00674 if (i == ARP_TABLE_SIZE) { 00675 DEBUGF(ETHARP_DEBUG | DBG_TRACE, ("etharp_query: IP address not found in ARP table\n")); 00676 /* find an available entry */ 00677 i = find_arp_entry(); 00678 /* bail out if no ARP entries are available */ 00679 if (i == ARP_TABLE_SIZE) { 00680 DEBUGF(ETHARP_DEBUG | 2, ("etharp_query: no more ARP entries available.\n")); 00681 return ERR_MEM; 00682 } 00683 DEBUGF(ETHARP_DEBUG | DBG_TRACE, ("etharp_query: created ARP table entry %u.\n", i)); 00684 /* i is available, create ARP entry */ 00685 ip_addr_set(&arp_table[i].ipaddr, ipaddr); 00686 arp_table[i].ctime = 0; 00687 arp_table[i].state = ETHARP_STATE_PENDING; 00688 #if ARP_QUEUEING 00689 /* free queued packet, as entry is now invalidated */ 00690 if (arp_table[i].p != NULL) { 00691 pbuf_free(arp_table[i].p); 00692 arp_table[i].p = NULL; 00693 DEBUGF(ETHARP_DEBUG | DBG_TRACE | 3, ("etharp_query: dropped packet on ARP queue. Should not occur.\n")); 00694 } 00695 #endif 00696 } 00697 #if ARP_QUEUEING 00698 /* any pbuf to queue and queue is empty? */ 00699 if (q != NULL) { 00700 /* yield later packets over older packets? */ 00701 #if ARP_QUEUE_FIRST == 0 00702 /* earlier queued packet on this entry? */ 00703 if (arp_table[i].p != NULL) { 00704 pbuf_free(arp_table[i].p); 00705 arp_table[i].p = NULL; 00706 DEBUGF(ETHARP_DEBUG | DBG_TRACE | 3, ("etharp_query: dropped packet on ARP queue. Should not occur.\n")); 00707 } 00708 #endif 00709 /* packet can be queued? */ 00710 if (arp_table[i].p == NULL) { 00711 /* copy PBUF_REF referenced payloads to PBUF_RAM */ 00712 q = pbuf_take(q); 00713 /* remember pbuf to queue, if any */ 00714 arp_table[i].p = q; 00715 /* pbufs are queued, increase the reference count */ 00716 pbuf_ref(q); 00717 DEBUGF(ETHARP_DEBUG | DBG_TRACE | DBG_STATE, ("etharp_query: queued packet %p on ARP entry %u.\n", (void *)q, i)); 00718 } 00719 } 00720 #endif 00721 /* ARP request? */ 00722 if (perform_arp_request) 00723 { 00724 /* allocate a pbuf for the outgoing ARP request packet */ 00725 p = pbuf_alloc(PBUF_LINK, sizeof(struct etharp_hdr), PBUF_RAM); 00726 /* could allocate pbuf? */ 00727 if (p != NULL) { 00728 u8_t j; 00729 DEBUGF(ETHARP_DEBUG | DBG_TRACE, ("etharp_query: sending ARP request.\n")); 00730 hdr = p->payload; 00731 hdr->opcode = htons(ARP_REQUEST); 00732 for(j = 0; j < netif->hwaddr_len; ++j) 00733 { 00734 hdr->dhwaddr.addr[j] = 0x00; 00735 hdr->shwaddr.addr[j] = srcaddr->addr[j]; 00736 } 00737 ip_addr_set(&(hdr->dipaddr), ipaddr); 00738 ip_addr_set(&(hdr->sipaddr), &(netif->ip_addr)); 00739 00740 hdr->hwtype = htons(HWTYPE_ETHERNET); 00741 ARPH_HWLEN_SET(hdr, netif->hwaddr_len); 00742 00743 hdr->proto = htons(ETHTYPE_IP); 00744 ARPH_PROTOLEN_SET(hdr, sizeof(struct ip_addr)); 00745 for(j = 0; j < netif->hwaddr_len; ++j) 00746 { 00747 hdr->ethhdr.dest.addr[j] = 0xff; 00748 hdr->ethhdr.src.addr[j] = srcaddr->addr[j]; 00749 } 00750 hdr->ethhdr.type = htons(ETHTYPE_ARP); 00751 /* send ARP query */ 00752 result = netif->linkoutput(netif, p); 00753 /* free ARP query packet */ 00754 pbuf_free(p); 00755 p = NULL; 00756 } else { 00757 result = ERR_MEM; 00758 DEBUGF(ETHARP_DEBUG | DBG_TRACE | 2, ("etharp_query: could not allocate pbuf for ARP request.\n")); 00759 } 00760 } 00761 return result; 00762 } |
Here is the call graph for this function:
|
Clears expired entries in the ARP table. This function should be called every ETHARP_TMR_INTERVAL microseconds (10 seconds), in order to expire entries in the ARP table. Definition at line 147 of file etharp.c. References ARP_MAXAGE, ARP_MAXPENDING, arp_table, etharp_entry::ctime, DEBUGF, ETHARP_DEBUG, ETHARP_STATE_EMPTY, ETHARP_STATE_PENDING, ETHARP_STATE_STABLE, NULL, pbuf_free(), etharp_entry::state, and u8_t. Referenced by rt_3com905cif_etharp_timer(), and rt_rtl8139_ifetharp_timer().
00148 { 00149 u8_t i; 00150 00151 DEBUGF(ETHARP_DEBUG, ("etharp_timer\n")); 00152 /* remove expired entries from the ARP table */ 00153 for(i = 0; i < ARP_TABLE_SIZE; ++i) { 00154 arp_table[i].ctime++; 00155 if((arp_table[i].state == ETHARP_STATE_STABLE) && 00156 (arp_table[i].ctime >= ARP_MAXAGE)) { 00157 DEBUGF(ETHARP_DEBUG, ("etharp_timer: expired stable entry %u.\n", i)); 00158 arp_table[i].state = ETHARP_STATE_EMPTY; 00159 #if ARP_QUEUEING 00160 /* remove any queued packet */ 00161 pbuf_free(arp_table[i].p); 00162 arp_table[i].p = NULL; 00163 #endif 00164 } else if((arp_table[i].state == ETHARP_STATE_PENDING) && 00165 (arp_table[i].ctime >= ARP_MAXPENDING)) { 00166 arp_table[i].state = ETHARP_STATE_EMPTY; 00167 #if ARP_QUEUEING 00168 DEBUGF(ETHARP_DEBUG, ("etharp_timer: expired pending entry %u - dequeueing %p.\n", i, (void *)(arp_table[i].p))); 00169 /* remove any queued packet */ 00170 pbuf_free(arp_table[i].p); 00171 arp_table[i].p = NULL; 00172 #else 00173 DEBUGF(ETHARP_DEBUG, ("etharp_timer: expired pending entry %u.\n", i)); 00174 #endif 00175 } 00176 } 00177 } |
Here is the call graph for this function:
|
Return an empty ARP entry or, if the table is full, ARP_TABLE_SIZE if all entries are pending, otherwise the oldest entry.
Definition at line 187 of file etharp.c. References arp_table, etharp_entry::ctime, DEBUGF, ETHARP_DEBUG, ETHARP_STATE_EMPTY, ETHARP_STATE_STABLE, NULL, etharp_entry::state, and u8_t. Referenced by etharp_query(), and update_arp_entry().
00188 { 00189 u8_t i, j, maxtime; 00190 00191 /* Try to find an unused entry in the ARP table. */ 00192 for(i = 0; i < ARP_TABLE_SIZE; ++i) { 00193 if(arp_table[i].state == ETHARP_STATE_EMPTY) { 00194 DEBUGF(ETHARP_DEBUG, ("find_arp_entry: found empty entry %u\n", i)); 00195 break; 00196 } 00197 } 00198 00199 /* If no unused entry is found, we try to find the oldest entry and 00200 throw it away. If all entries are new and have 0 ctime drop one */ 00201 if(i == ARP_TABLE_SIZE) { 00202 maxtime = 0; 00203 j = ARP_TABLE_SIZE; 00204 for(i = 0; i < ARP_TABLE_SIZE; ++i) { 00205 /* remember entry with oldest stable entry in j*/ 00206 if((arp_table[i].state == ETHARP_STATE_STABLE) && 00207 #if ARP_QUEUEING /* do not want to re-use an entry with queued packets */ 00208 (arp_table[i].p == NULL) && 00209 #endif 00210 (arp_table[i].ctime >= maxtime)) { 00211 maxtime = arp_table[i].ctime; 00212 j = i; 00213 } 00214 } 00215 DEBUGF(ETHARP_DEBUG, ("find_arp_entry: found oldest stable entry %u\n", j)); 00216 i = j; 00217 } 00218 DEBUGF(ETHARP_DEBUG, ("find_arp_entry: returning %u, state %u\n", i, arp_table[i].state)); 00219 return i; 00220 } |
|
Update (or insert) a IP/MAC address pair in the ARP cache.
Definition at line 237 of file etharp.c. References ip_addr::addr, ARP_INSERT_FLAG, arp_table, etharp_entry::ctime, DBG_STATE, DBG_TRACE, DEBUGF, etharp_entry::ethaddr, ETHARP_ALWAYS_INSERT, ETHARP_DEBUG, ETHARP_STATE_EMPTY, ETHARP_STATE_PENDING, ETHARP_STATE_STABLE, ETHTYPE_IP, find_arp_entry(), htons, netif::hwaddr_len, ip4_addr1, ip4_addr2, ip4_addr3, ip4_addr4, ip_addr_cmp, ip_addr_set, ipaddr, netif::linkoutput, LWIP_ASSERT, NULL, pbuf_free(), etharp_entry::state, and u8_t. Referenced by etharp_arp_input(), and etharp_ip_input().
00238 { 00239 u8_t i, k; 00240 #if ARP_QUEUEING 00241 struct pbuf *p; 00242 struct eth_hdr *ethhdr; 00243 #endif 00244 DEBUGF(ETHARP_DEBUG | DBG_TRACE | 3, ("update_arp_entry()\n")); 00245 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), 00246 ethaddr->addr[0], ethaddr->addr[1], ethaddr->addr[2], ethaddr->addr[3], ethaddr->addr[4], ethaddr->addr[5])); 00247 /* do not update for 0.0.0.0 addresses */ 00248 if (ipaddr->addr == 0) { 00249 DEBUGF(ETHARP_DEBUG | DBG_TRACE, ("update_arp_entry: will not add 0.0.0.0 to ARP cache\n")); 00250 return NULL; 00251 } 00252 /* Walk through the ARP mapping table and try to find an entry to 00253 update. If none is found, the IP -> MAC address mapping is 00254 inserted in the ARP table. */ 00255 for(i = 0; i < ARP_TABLE_SIZE; ++i) { 00256 /* Check if the source IP address of the incoming packet matches 00257 the IP address in this ARP table entry. */ 00258 if(ip_addr_cmp(ipaddr, &arp_table[i].ipaddr)) { 00259 /* pending entry? */ 00260 if(arp_table[i].state == ETHARP_STATE_PENDING) { 00261 DEBUGF(ETHARP_DEBUG | DBG_TRACE, ("update_arp_entry: pending entry %u goes stable\n", i)); 00262 /* A pending entry was found, mark it stable */ 00263 arp_table[i].state = ETHARP_STATE_STABLE; 00264 /* fall-through to next if */ 00265 } 00266 /* stable entry? (possible just marked to become stable) */ 00267 if(arp_table[i].state == ETHARP_STATE_STABLE) { 00268 DEBUGF(ETHARP_DEBUG | DBG_TRACE, ("update_arp_entry: updating stable entry %u\n", i)); 00269 /* An old entry found, update this and return. */ 00270 for(k = 0; k < netif->hwaddr_len; ++k) { 00271 arp_table[i].ethaddr.addr[k] = ethaddr->addr[k]; 00272 } 00273 /* reset time stamp */ 00274 arp_table[i].ctime = 0; 00275 #if ARP_QUEUEING 00276 /* queued packet present? */ 00277 if((p = arp_table[i].p) != NULL) { 00278 /* Null out attached buffer immediately */ 00279 arp_table[i].p = NULL; 00280 /* fill-in Ethernet header */ 00281 ethhdr = p->payload; 00282 for(k = 0; k < netif->hwaddr_len; ++k) { 00283 ethhdr->dest.addr[k] = ethaddr->addr[k]; 00284 } 00285 ethhdr->type = htons(ETHTYPE_IP); 00286 DEBUGF(ETHARP_DEBUG | DBG_TRACE, ("update_arp_entry: sending queued IP packet.\n")); 00287 /* send the queued IP packet */ 00288 netif->linkoutput(netif, p); 00289 /* free the queued IP packet */ 00290 pbuf_free(p); 00291 } 00292 #endif 00293 return NULL; 00294 } 00295 } /* if */ 00296 } /* for */ 00297 00298 /* no matching ARP entry was found */ 00299 LWIP_ASSERT("update_arp_entry: i == ARP_TABLE_SIZE", i == ARP_TABLE_SIZE); 00300 00301 DEBUGF(ETHARP_DEBUG | DBG_TRACE, ("update_arp_entry: IP address not yet in table\n")); 00302 /* allowed to insert an entry? */ 00303 if ((ETHARP_ALWAYS_INSERT) || (flags & ARP_INSERT_FLAG)) 00304 { 00305 DEBUGF(ETHARP_DEBUG | DBG_TRACE, ("update_arp_entry: adding entry to table\n")); 00306 /* find an empty or old entry. */ 00307 i = find_arp_entry(); 00308 if(i == ARP_TABLE_SIZE) { 00309 DEBUGF(ETHARP_DEBUG | DBG_TRACE, ("update_arp_entry: no available entry found\n")); 00310 return NULL; 00311 } 00312 /* see if find_arp_entry() gave us an old stable, or empty entry to re-use */ 00313 if (arp_table[i].state == ETHARP_STATE_STABLE) { 00314 DEBUGF(ETHARP_DEBUG | DBG_TRACE, ("update_arp_entry: overwriting old stable entry %u\n", i)); 00315 /* stable entries should have no queued packets (TODO: allow later) */ 00316 #if ARP_QUEUEING 00317 LWIP_ASSERT("update_arp_entry: arp_table[i].p == NULL", arp_table[i].p == NULL); 00318 #endif 00319 } else { 00320 DEBUGF(ETHARP_DEBUG | DBG_TRACE | DBG_STATE, ("update_arp_entry: filling empty entry %u with state %u\n", i, arp_table[i].state)); 00321 LWIP_ASSERT("update_arp_entry: arp_table[i].state == ETHARP_STATE_EMPTY", arp_table[i].state == ETHARP_STATE_EMPTY); 00322 } 00323 /* set IP address */ 00324 ip_addr_set(&arp_table[i].ipaddr, ipaddr); 00325 /* set Ethernet hardware address */ 00326 for(k = 0; k < netif->hwaddr_len; ++k) { 00327 arp_table[i].ethaddr.addr[k] = ethaddr->addr[k]; 00328 } 00329 /* reset time-stamp */ 00330 arp_table[i].ctime = 0; 00331 /* mark as stable */ 00332 arp_table[i].state = ETHARP_STATE_STABLE; 00333 /* no queued packet */ 00334 #if ARP_QUEUEING 00335 arp_table[i].p = NULL; 00336 #endif 00337 } 00338 else 00339 { 00340 DEBUGF(ETHARP_DEBUG | DBG_TRACE, ("update_arp_entry: no matching stable entry to update\n")); 00341 } 00342 return NULL; 00343 } |
Here is the call graph for this function:
|
Definition at line 119 of file etharp.c. Referenced by etharp_init(), etharp_output(), etharp_query(), etharp_tmr(), find_arp_entry(), and update_arp_entry(). |
|
Definition at line 118 of file etharp.c. Referenced by etharp_output(). |