Main Page | Alphabetical List | Data Structures | File List | Data Fields | Globals | Related Pages

etharp.h File Reference

#include "lwip/pbuf.h"
#include "lwip/ip_addr.h"
#include "lwip/netif.h"
#include "lwip/ip.h"

Include dependency graph for etharp.h:

This graph shows which files directly or indirectly include this file:

Go to the source code of this file.

Data Structures

struct  eth_addr
struct  eth_hdr
struct  etharp_hdr
struct  ethip_hdr

Defines

#define ARP_TMR_INTERVAL   10000
#define ETHTYPE_ARP   0x0806
#define ETHTYPE_IP   0x0800

Functions

void etharp_init (void)
void etharp_tmr (void)
pbufetharp_ip_input (struct netif *netif, struct pbuf *p)
pbufetharp_arp_input (struct netif *netif, struct eth_addr *ethaddr, struct pbuf *p)
pbufetharp_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

PACK_STRUCT_BEGIN struct eth_addr PACK_STRUCT_STRUCT


Define Documentation

#define ARP_TMR_INTERVAL   10000
 

Definition at line 82 of file etharp.h.

#define ETHTYPE_ARP   0x0806
 

Definition at line 84 of file etharp.h.

#define ETHTYPE_IP   0x0800
 

Definition at line 85 of file etharp.h.


Function Documentation

struct pbuf* etharp_arp_input struct netif netif,
struct eth_addr ethaddr,
struct pbuf p
 

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.

Parameters:
netif The lwIP network interface on which the ARP packet pbuf arrived.
pbuf The ARP packet that arrived on netif. Is freed by this function.
ethaddr Ethernet address of netif.
Returns:
NULL
See also:
pbuf_free()

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:

void etharp_init void   ) 
 

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().

00129 {
00130   u8_t i;
00131   /* clear ARP entries */
00132   for(i = 0; i < ARP_TABLE_SIZE; ++i) {
00133     arp_table[i].state = ETHARP_STATE_EMPTY;
00134 #if ARP_QUEUEING
00135     arp_table[i].p = NULL;
00136 #endif
00137   }
00138 }

struct pbuf* etharp_ip_input struct netif netif,
struct pbuf p
 

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.

Parameters:
netif The lwIP network interface on which the IP packet pbuf arrived.
pbuf The IP packet that arrived on netif.
Returns:
NULL
See also:
pbuf_free()

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:

struct pbuf* etharp_output struct netif netif,
struct ip_addr ipaddr,
struct pbuf q
 

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.

Parameters:
netif The lwIP network interface which the IP packet will be sent on.
ipaddr The IP address of the packet destination.
pbuf The pbuf(s) containing the IP packet to be sent.
Returns:
If non-NULL, a packet ready to be sent.
See also:
etharp_output_sent()

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 *)&ethbroadcast;
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:

err_t etharp_query struct netif netif,
struct ip_addr ipaddr,
struct pbuf q
 

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.

Parameters:
netif The lwIP network interface where ipaddr must be queried for.
ipaddr The IP address to be resolved.
q If non-NULL, a pbuf that must be queued on the ARP entry for the ipaddr IP address.
Returns:
NULL.
Note:
Might be used in the future by manual IP configuration as well.
TODO: enqueue q here if possible (BEWARE: possible other packet already queued. TODO: The host requirements RFC states that ARP should save at least one packet, and this should be the _latest_ packet. TODO: use the ctime field to see how long ago an ARP request was sent, possibly retry.

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:

void etharp_tmr void   ) 
 

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:


Variable Documentation

PACK_STRUCT_END PACK_STRUCT_BEGIN struct etharp_hdr PACK_STRUCT_STRUCT
 

the ARP message


Generated on Wed Jan 14 12:59:04 2004 for RTL-lwIP-0.4 by doxygen 1.3.4