/[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.6 by likewise, Mon Nov 11 14:34:29 2002 UTC revision 1.7 by likewise, Wed Nov 13 08:56:11 2002 UTC
# Line 3  Line 3 
3   * Address Resolution Protocol module for IP over Ethernet   * Address Resolution Protocol module for IP over Ethernet
4   *   *
5   * $Log$   * $Log$
6     * Revision 1.7  2002/11/13 08:56:11  likewise
7     * Implemented conditional insertion of ARP entries to update_arp_entry using ARP_INSERT_FLAG.
8     *
9   * Revision 1.6  2002/11/11 14:34:29  likewise   * Revision 1.6  2002/11/11 14:34:29  likewise
10   * Changed static etharp_query() to support queueing packets. This fix  missed in last commit.   * Changed static etharp_query() to support queueing packets. This fix  missed in last commit.
11   *   *
# Line 53  Line 56 
56   * Author: Adam Dunkels <adam@sics.se>   * Author: Adam Dunkels <adam@sics.se>
57   *   *
58   */   */
59    
60    /*
61     * TODO:
62     *
63    RFC 3220 4.6          IP Mobility Support for IPv4          January 2002
64    
65          -  A Gratuitous ARP [45] is an ARP packet sent by a node in order
66             to spontaneously cause other nodes to update an entry in their
67             ARP cache.  A gratuitous ARP MAY use either an ARP Request or
68             an ARP Reply packet.  In either case, the ARP Sender Protocol
69             Address and ARP Target Protocol Address are both set to the IP
70             address of the cache entry to be updated, and the ARP Sender
71             Hardware Address is set to the link-layer address to which this
72             cache entry should be updated.  When using an ARP Reply packet,
73             the Target Hardware Address is also set to the link-layer
74             address to which this cache entry should be updated (this field
75             is not used in an ARP Request packet).
76    
77             In either case, for a gratuitous ARP, the ARP packet MUST be
78             transmitted as a local broadcast packet on the local link.  As
79             specified in [36], any node receiving any ARP packet (Request
80             or Reply) MUST update its local ARP cache with the Sender
81             Protocol and Hardware Addresses in the ARP packet, if the
82             receiving node has an entry for that IP address already in its
83             ARP cache.  This requirement in the ARP protocol applies even
84             for ARP Request packets, and for ARP Reply packets that do not
85             match any ARP Request transmitted by the receiving node [36].
86    *
87      My suggestion would be to send a ARP request for our newly obtained
88      address upon configuration of an Ethernet interface.
89    
90    */
91    
92  #include "lwip/opt.h"  #include "lwip/opt.h"
93  #include "lwip/debug.h"  #include "lwip/debug.h"
# Line 67  Line 102 
102  #  include "lwip/dhcp.h"  #  include "lwip/dhcp.h"
103  #endif  #endif
104    
105  /** the time an ARP entry stays valid after its last update */  /** the time an ARP entry stays valid after its last update, (120 * 10) seconds = 20 minutes. */
106  #define ARP_MAXAGE 120  /* 120 * 10 seconds = 20 minutes. */  #define ARP_MAXAGE 120  
107  /** the maximum time waiting for ARP reply to a ARP request */  /** the time an ARP entry stays pending after first request, (2 * 10) seconds = 20 seconds. */
108  #define ARP_MAXPENDING 2 /* 2 * 10 seconds = 20 seconds. */  #define ARP_MAXPENDING 2
109    
110  #define HWTYPE_ETHERNET 1  #define HWTYPE_ETHERNET 1
111    
# Line 138  static const struct eth_addr ethbroadcas Line 173  static const struct eth_addr ethbroadcas
173  static struct etharp_entry arp_table[ARP_TABLE_SIZE];  static struct etharp_entry arp_table[ARP_TABLE_SIZE];
174  static u8_t ctime;  static u8_t ctime;
175    
176  static struct pbuf *insert_arp_entry(struct ip_addr *ipaddr, struct eth_addr *ethaddr);  static struct pbuf *update_arp_entry(struct ip_addr *ipaddr, struct eth_addr *ethaddr, u8_t flags);
177    #define ARP_INSERT_FLAG 1
178    
179  /**  /**
180   * Initializes ARP module.   * Initializes ARP module.
# Line 151  etharp_init(void) Line 187  etharp_init(void)
187    for(i = 0; i < ARP_TABLE_SIZE; ++i) {    for(i = 0; i < ARP_TABLE_SIZE; ++i) {
188      arp_table[i].state = ETHARP_STATE_EMPTY;      arp_table[i].state = ETHARP_STATE_EMPTY;
189    }    }
190      /* reset ARP current time */
191    ctime = 0;    ctime = 0;
192  }  }
193    
# Line 223  find_arp_entry(void) Line 260  find_arp_entry(void)
260  }  }
261    
262  /**  /**
263   * Insert an entry into the ARP cache, or update an existing one.   * Update (or insert) an entry in the ARP cache.
264   *   *
265   * @param ipaddr IP address of the inserted ARP entry.   * @param ipaddr IP address of the inserted ARP entry.
266   * @param ethaddr Ethernet address of the inserted ARP entry.   * @param ethaddr Ethernet address of the inserted ARP entry.
267   *   * @param flags Defines behaviour:
268     * - ARP_INSERT_FLAG Allows ARP to insert this as a new item. If not specified,
269     * only existing ARP entries will be updated.
270   * @return pbuf If non-NULL, a packet that was queued on a pending entry.   * @return pbuf If non-NULL, a packet that was queued on a pending entry.
271   * You should sent it and must call pbuf_free().   * You should sent it and must call pbuf_free().
272   *   *
273   * @see pbuf_free()   * @see pbuf_free()
274   */   */
275  static struct pbuf *  static struct pbuf *
276  insert_arp_entry(struct ip_addr *ipaddr, struct eth_addr *ethaddr)  update_arp_entry(struct ip_addr *ipaddr, struct eth_addr *ethaddr, u8_t flags)
277  {  {
278    u8_t i, k;    u8_t i, k;
279    struct pbuf *p;    struct pbuf *p;
# Line 250  insert_arp_entry(struct ip_addr *ipaddr, Line 289  insert_arp_entry(struct ip_addr *ipaddr,
289    
290        /* check those entries that are already in use. */        /* check those entries that are already in use. */
291        if(arp_table[i].state == ETHARP_STATE_STABLE) {        if(arp_table[i].state == ETHARP_STATE_STABLE) {
292          DEBUGF(ETHARP_DEBUG, ("insert_arp_entry: updating stable entry %u\n", i));          DEBUGF(ETHARP_DEBUG, ("update_arp_entry: updating stable entry %u\n", i));
293          /* An old entry found, update this and return. */          /* An old entry found, update this and return. */
294          for(k = 0; k < 6; ++k) {          for(k = 0; k < 6; ++k) {
295            arp_table[i].ethaddr.addr[k] = ethaddr->addr[k];            arp_table[i].ethaddr.addr[k] = ethaddr->addr[k];
# Line 260  insert_arp_entry(struct ip_addr *ipaddr, Line 299  insert_arp_entry(struct ip_addr *ipaddr,
299        }        }
300        else if(arp_table[i].state == ETHARP_STATE_PENDING) {        else if(arp_table[i].state == ETHARP_STATE_PENDING) {
301          /* A pending entry was found, so we fill this in and return          /* A pending entry was found, so we fill this in and return
302             the queued packet (if any). */          the queued packet (if any). */
303          DEBUGF(ETHARP_DEBUG, ("insert_arp_entry: pending entry %u made stable\n", i));          DEBUGF(ETHARP_DEBUG, ("update_arp_entry: pending entry %u made stable\n", i));
304          for(k = 0; k < 6; ++k) {          for(k = 0; k < 6; ++k) {
305            arp_table[i].ethaddr.addr[k] = ethaddr->addr[k];            arp_table[i].ethaddr.addr[k] = ethaddr->addr[k];
306          }          }
# Line 281  insert_arp_entry(struct ip_addr *ipaddr, Line 320  insert_arp_entry(struct ip_addr *ipaddr,
320            }            }
321    
322            ethhdr->type = htons(ETHTYPE_IP);                                  ethhdr->type = htons(ETHTYPE_IP);                      
323            DEBUGF(ETHARP_DEBUG, ("insert_arp_entry: returning queued packet %p\n", p));            DEBUGF(ETHARP_DEBUG, ("update_arp_entry: returning queued packet %p\n", p));
324          }          }
325          /* return queued packet, if any */          /* return queued packet, if any */
326          return p;          return p;
327        }        }
328      }      }
329    }    }
330    /* no matching ARP entry was found. find an empty or old entry. */    /* no matching ARP entry was found */
331    i = find_arp_entry();    /* allowed to insert an entry? */
332    if(i == ARP_TABLE_SIZE) {    if (flags & ARP_INSERT_FLAG)
333      DEBUGF(ETHARP_DEBUG, ("insert_arp_entry: no available entry found\n"));    {
334      return NULL;      /* find an empty or old entry. */
335    }      i = find_arp_entry();
336        if(i == ARP_TABLE_SIZE) {
337          DEBUGF(ETHARP_DEBUG, ("update_arp_entry: no available entry found\n"));
338          return NULL;
339        }
340    
341    if (arp_table[i].state == ETHARP_STATE_STABLE) {      if (arp_table[i].state == ETHARP_STATE_STABLE) {
342      DEBUGF(ETHARP_DEBUG, ("insert_arp_entry: overwriting old stable entry %u\n", i));        DEBUGF(ETHARP_DEBUG, ("update_arp_entry: overwriting old stable entry %u\n", i));
343    }      }
344    else {      else {
345      DEBUGF(ETHARP_DEBUG, ("insert_arp_entry: using empty entry %u\n", i));        DEBUGF(ETHARP_DEBUG, ("update_arp_entry: using empty entry %u\n", i));
346    }        }  
347    ip_addr_set(&arp_table[i].ipaddr, ipaddr);      ip_addr_set(&arp_table[i].ipaddr, ipaddr);
348    for(k = 0; k < 6; ++k) {      for(k = 0; k < 6; ++k) {
349      arp_table[i].ethaddr.addr[k] = ethaddr->addr[k];        arp_table[i].ethaddr.addr[k] = ethaddr->addr[k];
350        }
351        arp_table[i].ctime = ctime;
352        arp_table[i].state = ETHARP_STATE_STABLE;
353        arp_table[i].p = NULL;
354    }    }
   arp_table[i].ctime = ctime;  
   arp_table[i].state = ETHARP_STATE_STABLE;  
   arp_table[i].p = NULL;  
   
355    return NULL;    return NULL;
356  }  }
357    
# Line 346  etharp_ip_input(struct netif *netif, str Line 389  etharp_ip_input(struct netif *netif, str
389      return NULL;      return NULL;
390    }    }
391    DEBUGF(ETHARP_DEBUG, ("etharp_ip_input: updating ETHARP table.\n"));    DEBUGF(ETHARP_DEBUG, ("etharp_ip_input: updating ETHARP table.\n"));
392    /* update ARP table */    /* update ARP table, may insert */
393    return insert_arp_entry(&(hdr->ip.src), &(hdr->eth.src));    return update_arp_entry(&(hdr->ip.src), &(hdr->eth.src), ARP_INSERT_FLAG);
394  }  }
395    
396    
# Line 432  etharp_arp_input(struct netif *netif, st Line 475  etharp_arp_input(struct netif *netif, st
475      if(ip_addr_cmp(&(hdr->dipaddr), &(netif->ip_addr))) {          if(ip_addr_cmp(&(hdr->dipaddr), &(netif->ip_addr))) {    
476        struct pbuf *q;        struct pbuf *q;
477        DEBUGF(ETHARP_DEBUG, ("etharp_arp_input: ARP reply for us\n"));        DEBUGF(ETHARP_DEBUG, ("etharp_arp_input: ARP reply for us\n"));
478        /* insert_arp_entry() can return a pbuf that has previously been        /* update_arp_entry() can return a pbuf that has previously been
479        queued waiting for this IP address to become ARP stable. */        queued waiting for this IP address to become ARP stable. */
480        q = insert_arp_entry(&(hdr->sipaddr), &(hdr->shwaddr));        q = update_arp_entry(&(hdr->sipaddr), &(hdr->shwaddr), ARP_INSERT_FLAG);
481        /* free incoming ARP reply pbuf */        /* free incoming ARP reply pbuf */
482        pbuf_free(p);        pbuf_free(p);
483        p = NULL;        p = NULL;

Legend:
Removed from v.1.6  
changed lines
  Added in v.1.7

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