/[lwip]/lwip/src/netif/etharp.c
ViewVC logotype

Diff of /lwip/src/netif/etharp.c

Parent Directory Parent Directory | Revision Log Revision Log | View Patch Patch

revision 1.47.2.6 by likewise, Fri Nov 14 19:23:08 2003 UTC revision 1.47.2.7 by likewise, Sat Nov 15 00:41:48 2003 UTC
# Line 124  struct etharp_entry { Line 124  struct etharp_entry {
124  static const struct eth_addr ethbroadcast = {{0xff,0xff,0xff,0xff,0xff,0xff}};  static const struct eth_addr ethbroadcast = {{0xff,0xff,0xff,0xff,0xff,0xff}};
125  static struct etharp_entry arp_table[ARP_TABLE_SIZE];  static struct etharp_entry arp_table[ARP_TABLE_SIZE];
126    
127  static struct pbuf *update_arp_entry(struct netif *netif, struct ip_addr *ipaddr, struct eth_addr *ethaddr, u8_t flags);  static s8_t find_arp_entry(void);
128  #define ARP_INSERT_FLAG 1  #define ARP_INSERT_FLAG 1
129    static struct pbuf *update_arp_entry(struct netif *netif, struct ip_addr *ipaddr, struct eth_addr *ethaddr, u8_t flags);
130    #if ARP_QUEUEING
131    static struct pbuf *etharp_enqueue(s8_t i, struct pbuf *q);
132    static struct pbuf *etharp_dequeue(s8_t i);
133    #endif
134  /**  /**
135   * Initializes ARP module.   * Initializes ARP module.
136   */   */
137  void  void
138  etharp_init(void)  etharp_init(void)
139  {  {
140    u8_t i;    s8_t i;
141    /* clear ARP entries */    /* clear ARP entries */
142    for(i = 0; i < ARP_TABLE_SIZE; ++i) {    for(i = 0; i < ARP_TABLE_SIZE; ++i) {
143      arp_table[i].state = ETHARP_STATE_EMPTY;      arp_table[i].state = ETHARP_STATE_EMPTY;
144  #if ARP_QUEUEING  #if ARP_QUEUEING
145      arp_table[i].p = NULL;      arp_table[i].p = NULL;
146  #endif  #endif
147        arp_table[i].ctime = 0;
148    }    }
149  }  }
150    
# Line 152  etharp_init(void) Line 157  etharp_init(void)
157  void  void
158  etharp_tmr(void)  etharp_tmr(void)
159  {  {
160    u8_t i;    s8_t i;
161    
162    LWIP_DEBUGF(ETHARP_DEBUG, ("etharp_timer\n"));    LWIP_DEBUGF(ETHARP_DEBUG, ("etharp_timer\n"));
163    /* remove expired entries from the ARP table */    /* remove expired entries from the ARP table */
# Line 186  etharp_tmr(void) Line 191  etharp_tmr(void)
191  }  }
192    
193  /**  /**
194   * Return an empty ARP entry or, if the table is full, ARP_TABLE_SIZE if all   * Return an empty ARP entry (possibly recycling the oldest stable entry).
  * entries are pending, otherwise the oldest entry.  
195   *   *
196   * @return The ARP entry index that is available, ARP_TABLE_SIZE if no usable   * @return The ARP entry index that is available, ERR_MEM if no usable
197   * entry is found.   * entry is found.
198   */   */
199  static u8_t  static s8_t
200  find_arp_entry(void)  find_arp_entry(void)
201  {  {
202    u8_t i, j, maxtime;    s8_t i, j;
203      u8_t maxtime = 0;
204    
205    /* Try to find an unused entry in the ARP table. */    j = ARP_TABLE_SIZE;
206      /* search ARP table for an unused or old entry */
207    for (i = 0; i < ARP_TABLE_SIZE; ++i) {    for (i = 0; i < ARP_TABLE_SIZE; ++i) {
208            /* empty entry? */
209      if (arp_table[i].state == ETHARP_STATE_EMPTY) {      if (arp_table[i].state == ETHARP_STATE_EMPTY) {
210        LWIP_DEBUGF(ETHARP_DEBUG, ("find_arp_entry: found empty entry %u\n", i));        LWIP_DEBUGF(ETHARP_DEBUG, ("find_arp_entry: returning empty entry %u\n", i));
211        break;        return i;
212            /* stable entry? */
213        } else if (arp_table[i].state == ETHARP_STATE_STABLE) {
214          /* remember entry with oldest stable entry in j */
215          if (arp_table[i].ctime >= maxtime) maxtime = arp_table[j = i].ctime;
216      }      }
217    }    }
218      /* no empty entry found? */
   /* If no unused entry is found, we try to find the oldest entry and  
      throw it away. If all entries are new and ctime drop one */  
219    if (i == ARP_TABLE_SIZE) {    if (i == ARP_TABLE_SIZE) {
220      maxtime = 0;          LWIP_DEBUGF(ETHARP_DEBUG, ("find_arp_entry: found oldest stable entry %u\n", j));
221      j = ARP_TABLE_SIZE;      /* fall-back to oldest stable */
222      for (i = 0; i < ARP_TABLE_SIZE; ++i) {          i = j;
223        /* remember entry with oldest stable entry in j */    }
224        if ((arp_table[i].state == ETHARP_STATE_STABLE) &&    /* no available entry found? */
225  #if ARP_QUEUEING /* do not want to re-use an entry with queued packets */    if (i == ARP_TABLE_SIZE) {
226        (arp_table[i].p == NULL) &&      LWIP_DEBUGF(ETHARP_DEBUG, ("find_arp_entry: no replacable entry could be found\n"));
227  #endif      /* return failure */
228        (arp_table[i].ctime >= maxtime)) {      return ERR_MEM;
         maxtime = arp_table[i].ctime;  
         j = i;  
         /* { j = oldest stable entry } */  
       }  
     }  
     if (j != ARP_TABLE_SIZE) {  
       LWIP_DEBUGF(ETHARP_DEBUG, ("find_arp_entry: found oldest stable entry %u\n", j));  
     } else {  
       LWIP_DEBUGF(ETHARP_DEBUG, ("find_arp_entry: no replacable entry could be found\n"));  
     }  
     i = j;  
229    }    }
230    LWIP_DEBUGF(ETHARP_DEBUG, ("find_arp_entry: returning %u, state %u\n", i, arp_table[i].state));  
231      /* clean up the recycled stable entry */
232      if (arp_table[i].state == ETHARP_STATE_STABLE) {
233    #if ARP_QUEUEING
234            struct pbuf *q;
235        /* free packets on queue */
236        q = etharp_dequeue(i);
237        if (q != NULL) pbuf_free(q);
238    #endif
239        LWIP_DEBUGF(ETHARP_DEBUG | DBG_TRACE, ("find_arp_entry: recycling oldest stable entry %u\n", i));
240        arp_table[i].state = ETHARP_STATE_EMPTY;
241        arp_table[i].ctime = 0;
242      }
243      LWIP_DEBUGF(ETHARP_DEBUG, ("find_arp_entry: returning %u\n", i));
244    return i;    return i;
245  }  }
246    
247    #if ARP_QUEUEING
248    static struct pbuf *
249    etharp_enqueue(s8_t i, struct pbuf *q)
250    {
251      /* any pbuf to queue? */
252      if (q != NULL) {
253    /* remove old packet on queue? */
254    #if ARP_QUEUE_FIRST == 0
255        struct pbuf *p;
256        p = etharp_dequeue(i);
257        if (p != NULL) pbuf_free(p);
258        LWIP_DEBUGF(ETHARP_DEBUG | DBG_TRACE | 3, ("etharp_query: dropped packet %p on ARP queue. Should not occur.\n", (void *)arp_table[i].p));
259    #endif
260        /* packet can be queued? */
261        if (arp_table[i].p == NULL) {
262          /* copy PBUF_REF referenced payloads into PBUF_RAM */
263          q = pbuf_take(q);
264          /* remember pbuf to queue, if any */
265          arp_table[i].p = q;
266          /* pbufs are queued, increase the reference count */
267          pbuf_ref(q);
268          LWIP_DEBUGF(ETHARP_DEBUG | DBG_TRACE | DBG_STATE, ("etharp_query: queued packet %p on ARP entry %u.\n", (void *)q, i));
269        }
270      }
271      return arp_table[i].p;
272    }
273    
274    static struct pbuf *
275    etharp_dequeue(s8_t i)
276    {
277      /* queued packets on a stable entry (work in progress) */
278      if (arp_table[i].p != NULL) {
279        /* send the queued IP packets */
280        netif->linkoutput(netif, arp_table[i].p);
281        LWIP_DEBUGF(ETHARP_DEBUG | DBG_TRACE | 3,
282          ("find_arp_entry: sent queued packet %p.\n", (void *)arp_table[i].p));
283        arp_table[i].p = NULL;
284      }
285      return arp_table[i].p;
286    }
287    #endif
288    
289  /**  /**
290   * Update (or insert) a IP/MAC address pair in the ARP cache.   * Update (or insert) a IP/MAC address pair in the ARP cache.
291   *   *
# Line 250  find_arp_entry(void) Line 303  find_arp_entry(void)
303  static struct pbuf *  static struct pbuf *
304  update_arp_entry(struct netif *netif, struct ip_addr *ipaddr, struct eth_addr *ethaddr, u8_t flags)  update_arp_entry(struct netif *netif, struct ip_addr *ipaddr, struct eth_addr *ethaddr, u8_t flags)
305  {  {
306    u8_t i, k;    s8_t i, k;
307    LWIP_DEBUGF(ETHARP_DEBUG | DBG_TRACE | 3, ("update_arp_entry()\n"));    LWIP_DEBUGF(ETHARP_DEBUG | DBG_TRACE | 3, ("update_arp_entry()\n"));
308    LWIP_ASSERT("netif->hwaddr_len != 0", netif->hwaddr_len != 0);    LWIP_ASSERT("netif->hwaddr_len != 0", netif->hwaddr_len != 0);
309    LWIP_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),    LWIP_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),
# Line 322  update_arp_entry(struct netif *netif, st Line 375  update_arp_entry(struct netif *netif, st
375      LWIP_DEBUGF(ETHARP_DEBUG | DBG_TRACE, ("update_arp_entry: adding entry to table\n"));      LWIP_DEBUGF(ETHARP_DEBUG | DBG_TRACE, ("update_arp_entry: adding entry to table\n"));
376      /* find an empty or old entry. */      /* find an empty or old entry. */
377      i = find_arp_entry();      i = find_arp_entry();
378      if (i == ARP_TABLE_SIZE) {      if (i == ERR_MEM) {
379        LWIP_DEBUGF(ETHARP_DEBUG | DBG_TRACE, ("update_arp_entry: no available entry found\n"));        LWIP_DEBUGF(ETHARP_DEBUG | DBG_TRACE, ("update_arp_entry: no available entry found\n"));
380        return NULL;        return NULL;
381      }      }
     /* see if find_arp_entry() gave us an old stable, or empty entry to re-use */  
     if (arp_table[i].state == ETHARP_STATE_STABLE) {  
       LWIP_DEBUGF(ETHARP_DEBUG | DBG_TRACE, ("update_arp_entry: overwriting old stable entry %u\n", i));  
       /* stable entries should have no queued packets (TODO: allow later) */  
 #if ARP_QUEUEING  
       LWIP_ASSERT("update_arp_entry: arp_table[i].p == NULL", arp_table[i].p == NULL);  
 #endif  
     } else {  
       LWIP_DEBUGF(ETHARP_DEBUG | DBG_TRACE | DBG_STATE, ("update_arp_entry: filling empty entry %u with state %u\n", i, arp_table[i].state));  
       LWIP_ASSERT("update_arp_entry: arp_table[i].state == ETHARP_STATE_EMPTY", arp_table[i].state == ETHARP_STATE_EMPTY);  
     }  
382      /* set IP address */      /* set IP address */
383      ip_addr_set(&arp_table[i].ipaddr, ipaddr);      ip_addr_set(&arp_table[i].ipaddr, ipaddr);
384      /* set Ethernet hardware address */      /* set Ethernet hardware address */
# Line 538  etharp_output(struct netif *netif, struc Line 580  etharp_output(struct netif *netif, struc
580  {  {
581    struct eth_addr *dest, *srcaddr, mcastaddr;    struct eth_addr *dest, *srcaddr, mcastaddr;
582    struct eth_hdr *ethhdr;    struct eth_hdr *ethhdr;
583    u8_t i;    s8_t i;
584    
585    /* make room for Ethernet header */    /* make room for Ethernet header */
586    if (pbuf_header(q, sizeof(struct eth_hdr)) != 0) {    if (pbuf_header(q, sizeof(struct eth_hdr)) != 0) {
# Line 667  err_t etharp_query(struct netif *netif, Line 709  err_t etharp_query(struct netif *netif,
709    struct eth_addr *srcaddr;    struct eth_addr *srcaddr;
710    struct etharp_hdr *hdr;    struct etharp_hdr *hdr;
711    err_t result = ERR_OK;    err_t result = ERR_OK;
712    u8_t i;    s8_t i;
713    u8_t perform_arp_request = 1;    u8_t perform_arp_request = 1;
714    /* prevent 'unused argument' warning if ARP_QUEUEING == 0 */    /* prevent 'unused argument' warning if ARP_QUEUEING == 0 */
715    (void)q;    (void)q;
# Line 677  err_t etharp_query(struct netif *netif, Line 719  err_t etharp_query(struct netif *netif,
719      if (ip_addr_cmp(ipaddr, &arp_table[i].ipaddr)) {      if (ip_addr_cmp(ipaddr, &arp_table[i].ipaddr)) {
720        if (arp_table[i].state == ETHARP_STATE_PENDING) {        if (arp_table[i].state == ETHARP_STATE_PENDING) {
721          LWIP_DEBUGF(ETHARP_DEBUG | DBG_TRACE | DBG_STATE, ("etharp_query: requested IP already pending as entry %u\n", i));          LWIP_DEBUGF(ETHARP_DEBUG | DBG_TRACE | DBG_STATE, ("etharp_query: requested IP already pending as entry %u\n", i));
722          /* break out of for-loop, user may wish to queue a packet on a stable entry */          /* break out of for-loop, user may wish to queue a packet on a pending entry */
723          /* TODO: we will issue a new ARP request, which should not occur too often */          /* TODO: we will issue a new ARP request, which should not occur too often */
724          /* we might want to run a faster timer on ARP to limit this */          /* we might want to run a faster timer on ARP to limit this */
725          break;          break;
# Line 697  err_t etharp_query(struct netif *netif, Line 739  err_t etharp_query(struct netif *netif,
739      /* find an available (unused or old) entry */      /* find an available (unused or old) entry */
740      i = find_arp_entry();      i = find_arp_entry();
741      /* bail out if no ARP entries are available */      /* bail out if no ARP entries are available */
742      if (i == ARP_TABLE_SIZE) {      if (i == ERR_MEM) {
743        LWIP_DEBUGF(ETHARP_DEBUG | 2, ("etharp_query: no more ARP entries available. Should seldom occur.\n"));        LWIP_DEBUGF(ETHARP_DEBUG | 2, ("etharp_query: no more ARP entries available. Should seldom occur.\n"));
744        return ERR_MEM;        return ERR_MEM;
745      }      }
     /* we will now recycle entry i */  
     LWIP_DEBUGF(ETHARP_DEBUG | DBG_TRACE, ("etharp_query: created ARP table entry %u.\n", i));  
746      /* i is available, create ARP entry */      /* i is available, create ARP entry */
     ip_addr_set(&arp_table[i].ipaddr, ipaddr);  
     arp_table[i].ctime = 0;  
747      arp_table[i].state = ETHARP_STATE_PENDING;      arp_table[i].state = ETHARP_STATE_PENDING;
748  #if ARP_QUEUEING /* deal with queue of recycled entry */      ip_addr_set(&arp_table[i].ipaddr, ipaddr);
749      /* free queued packet, as entry is now invalidated and recycled */    /* queried address was already in ARP table */
750      if (arp_table[i].p != NULL) {    } else {
       pbuf_free(arp_table[i].p);  
       LWIP_DEBUGF(ETHARP_DEBUG | DBG_TRACE | 3,  
         ("etharp_query: dropped packet %p from recycled ARP entry queue. Should not occur.\n", (void *)arp_table[i].p));  
       arp_table[i].p = NULL;  
     }  
 #endif  
   }  
751  #if ARP_QUEUEING  #if ARP_QUEUEING
752    /* any pbuf to queue and queue is empty? */      etharp_enqueue(i, q);
   if (q != NULL) {  
 /* yield later packets over older packets? */  
 #if ARP_QUEUE_FIRST == 0  
     /* earlier queued packet on this entry? */  
     if (arp_table[i].p != NULL) {  
       pbuf_free(arp_table[i].p);  
       LWIP_DEBUGF(ETHARP_DEBUG | DBG_TRACE | 3, ("etharp_query: dropped packet %p on ARP queue. Should not occur.\n", (void *)arp_table[i].p));  
       arp_table[i].p = NULL;  
       /* fall-through into next if */  
     }  
753  #endif  #endif
     /* packet can be queued? */  
     if (arp_table[i].p == NULL) {  
       /* copy PBUF_REF referenced payloads into PBUF_RAM */  
       q = pbuf_take(q);  
       /* remember pbuf to queue, if any */  
       arp_table[i].p = q;  
       /* pbufs are queued, increase the reference count */  
       pbuf_ref(q);  
       LWIP_DEBUGF(ETHARP_DEBUG | DBG_TRACE | DBG_STATE, ("etharp_query: queued packet %p on ARP entry %u.\n", (void *)q, i));  
     }  
754    }    }
 #endif  
755    /* ARP request? */    /* ARP request? */
756    if (perform_arp_request)    if (perform_arp_request)
757    {    {

Legend:
Removed from v.1.47.2.6  
changed lines
  Added in v.1.47.2.7

savannah-hackers-public@gnu.org
ViewVC Help
Powered by ViewVC 1.1.26