/[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.44 by likewise, Wed Jun 4 08:58:51 2003 UTC revision 1.45 by likewise, Mon Jun 9 20:28:10 2003 UTC
# Line 10  Line 10 
10    
11  /*  /*
12   * Copyright (c) 2001-2003 Swedish Institute of Computer Science.   * Copyright (c) 2001-2003 Swedish Institute of Computer Science.
13   * All rights reserved.   * All rights reserved.
14   *   *
15   * Redistribution and use in source and binary forms, with or without modification,   * Redistribution and use in source and binary forms, with or without modification,
16   * are permitted provided that the following conditions are met:   * are permitted provided that the following conditions are met:
17   *   *
18   * 1. Redistributions of source code must retain the above copyright notice,   * 1. Redistributions of source code must retain the above copyright notice,
# Line 21  Line 21 
21   *    this list of conditions and the following disclaimer in the documentation   *    this list of conditions and the following disclaimer in the documentation
22   *    and/or other materials provided with the distribution.   *    and/or other materials provided with the distribution.
23   * 3. The name of the author may not be used to endorse or promote products   * 3. The name of the author may not be used to endorse or promote products
24   *    derived from this software without specific prior written permission.   *    derived from this software without specific prior written permission.
25   *   *
26   * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED   * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED
27   * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF   * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
28   * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT   * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT
29   * SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,   * SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
30   * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT   * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT
31   * OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS   * OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
32   * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN   * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
33   * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING   * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING
34   * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY   * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY
35   * OF SUCH DAMAGE.   * OF SUCH DAMAGE.
36   *   *
37   * This file is part of the lwIP TCP/IP stack.   * This file is part of the lwIP TCP/IP stack.
38   *   *
39   * Author: Adam Dunkels <adam@sics.se>   * Author: Adam Dunkels <adam@sics.se>
40   *   *
41   */   */
42    
43  /*  /*
44   * TODO:   * TODO:
45   *   *
46  RFC 3220 4.6          IP Mobility Support for IPv4          January 2002  RFC 3220 4.6          IP Mobility Support for IPv4          January 2002
47    
48        -  A Gratuitous ARP [45] is an ARP packet sent by a node in order        -  A Gratuitous ARP [45] is an ARP packet sent by a node in order
49           to spontaneously cause other nodes to update an entry in their           to spontaneously cause other nodes to update an entry in their
50           ARP cache.  A gratuitous ARP MAY use either an ARP Request or           ARP cache.  A gratuitous ARP MAY use either an ARP Request or
51           an ARP Reply packet.  In either case, the ARP Sender Protocol           an ARP Reply packet.  In either case, the ARP Sender Protocol
52           Address and ARP Target Protocol Address are both set to the IP           Address and ARP Target Protocol Address are both set to the IP
53           address of the cache entry to be updated, and the ARP Sender           address of the cache entry to be updated, and the ARP Sender
54           Hardware Address is set to the link-layer address to which this           Hardware Address is set to the link-layer address to which this
55           cache entry should be updated.  When using an ARP Reply packet,           cache entry should be updated.  When using an ARP Reply packet,
56           the Target Hardware Address is also set to the link-layer           the Target Hardware Address is also set to the link-layer
57           address to which this cache entry should be updated (this field           address to which this cache entry should be updated (this field
58           is not used in an ARP Request packet).           is not used in an ARP Request packet).
59    
60           In either case, for a gratuitous ARP, the ARP packet MUST be           In either case, for a gratuitous ARP, the ARP packet MUST be
61           transmitted as a local broadcast packet on the local link.  As           transmitted as a local broadcast packet on the local link.  As
62           specified in [36], any node receiving any ARP packet (Request           specified in [36], any node receiving any ARP packet (Request
63           or Reply) MUST update its local ARP cache with the Sender           or Reply) MUST update its local ARP cache with the Sender
64           Protocol and Hardware Addresses in the ARP packet, if the           Protocol and Hardware Addresses in the ARP packet, if the
65           receiving node has an entry for that IP address already in its           receiving node has an entry for that IP address already in its
66           ARP cache.  This requirement in the ARP protocol applies even           ARP cache.  This requirement in the ARP protocol applies even
67           for ARP Request packets, and for ARP Reply packets that do not           for ARP Request packets, and for ARP Reply packets that do not
68           match any ARP Request transmitted by the receiving node [36].           match any ARP Request transmitted by the receiving node [36].
69  *  *
70    My suggestion would be to send a ARP request for our newly obtained    My suggestion would be to send a ARP request for our newly obtained
71    address upon configuration of an Ethernet interface.    address upon configuration of an Ethernet interface.
# Line 84  RFC 3220 4.6          IP Mobility Suppor Line 84  RFC 3220 4.6          IP Mobility Suppor
84  #endif  #endif
85    
86  /** the time an ARP entry stays valid after its last update, (120 * 10) seconds = 20 minutes. */  /** the time an ARP entry stays valid after its last update, (120 * 10) seconds = 20 minutes. */
87  #define ARP_MAXAGE 120    #define ARP_MAXAGE 120
88  /** the time an ARP entry stays pending after first request, (2 * 10) seconds = 20 seconds. */  /** the time an ARP entry stays pending after first request, (2 * 10) seconds = 20 seconds. */
89  #define ARP_MAXPENDING 2  #define ARP_MAXPENDING 2
90    
91  #define HWTYPE_ETHERNET 1  #define HWTYPE_ETHERNET 1
92    
# Line 148  void Line 148  void
148  etharp_tmr(void)  etharp_tmr(void)
149  {  {
150    u8_t i;    u8_t i;
151      
152    DEBUGF(ETHARP_DEBUG, ("etharp_timer\n"));    DEBUGF(ETHARP_DEBUG, ("etharp_timer\n"));
153    /* remove expired entries from the ARP table */    /* remove expired entries from the ARP table */
154    for (i = 0; i < ARP_TABLE_SIZE; ++i) {    for (i = 0; i < ARP_TABLE_SIZE; ++i) {
155      arp_table[i].ctime++;      arp_table[i].ctime++;
156      if ((arp_table[i].state == ETHARP_STATE_STABLE) &&            if ((arp_table[i].state == ETHARP_STATE_STABLE) &&
157          (arp_table[i].ctime >= ARP_MAXAGE)) {          (arp_table[i].ctime >= ARP_MAXAGE)) {
158        DEBUGF(ETHARP_DEBUG, ("etharp_timer: expired stable entry %u.\n", i));        DEBUGF(ETHARP_DEBUG, ("etharp_timer: expired stable entry %u.\n", i));
159        arp_table[i].state = ETHARP_STATE_EMPTY;        arp_table[i].state = ETHARP_STATE_EMPTY;
160  #if ARP_QUEUEING  #if ARP_QUEUEING
161        /* remove any queued packet */        if (arp_table[i].p != NULL) {
162        pbuf_free(arp_table[i].p);                /* remove any queued packet */
163        arp_table[i].p = NULL;          DEBUGF(ETHARP_DEBUG, ("etharp_timer: freeing packet queue %p.\n", i, (void *)(arp_table[i].p)));
164            pbuf_free(arp_table[i].p);
165            arp_table[i].p = NULL;
166          }
167  #endif  #endif
168      } else if ((arp_table[i].state == ETHARP_STATE_PENDING) &&      } else if ((arp_table[i].state == ETHARP_STATE_PENDING) &&
169                (arp_table[i].ctime >= ARP_MAXPENDING)) {                (arp_table[i].ctime >= ARP_MAXPENDING)) {
170        arp_table[i].state = ETHARP_STATE_EMPTY;        arp_table[i].state = ETHARP_STATE_EMPTY;
 #if ARP_QUEUEING  
       DEBUGF(ETHARP_DEBUG, ("etharp_timer: expired pending entry %u - dequeueing %p.\n", i, (void *)(arp_table[i].p)));  
       /* remove any queued packet */  
       pbuf_free(arp_table[i].p);        
       arp_table[i].p = NULL;  
 #else  
171        DEBUGF(ETHARP_DEBUG, ("etharp_timer: expired pending entry %u.\n", i));        DEBUGF(ETHARP_DEBUG, ("etharp_timer: expired pending entry %u.\n", i));
172    #if ARP_QUEUEING
173          if (arp_table[i].p != NULL) {
174            /* remove any queued packet */
175            DEBUGF(ETHARP_DEBUG, ("etharp_timer: freeing packet queue %p.\n", i, (void *)(arp_table[i].p)));
176            pbuf_free(arp_table[i].p);
177            arp_table[i].p = NULL;
178          }
179  #endif  #endif
180      }      }
181    }      }
182  }  }
183    
184  /**  /**
# Line 188  static u8_t Line 192  static u8_t
192  find_arp_entry(void)  find_arp_entry(void)
193  {  {
194    u8_t i, j, maxtime;    u8_t i, j, maxtime;
195      
196    /* Try to find an unused entry in the ARP table. */    /* Try to find an unused entry in the ARP table. */
197    for (i = 0; i < ARP_TABLE_SIZE; ++i) {    for (i = 0; i < ARP_TABLE_SIZE; ++i) {
198      if (arp_table[i].state == ETHARP_STATE_EMPTY) {      if (arp_table[i].state == ETHARP_STATE_EMPTY) {
# Line 196  find_arp_entry(void) Line 200  find_arp_entry(void)
200        break;        break;
201      }      }
202    }    }
203      
204    /* If no unused entry is found, we try to find the oldest entry and    /* If no unused entry is found, we try to find the oldest entry and
205       throw it away. If all entries are new and have 0 ctime drop one  */       throw it away. If all entries are new and have 0 ctime drop one  */
206    if (i == ARP_TABLE_SIZE) {    if (i == ARP_TABLE_SIZE) {
# Line 289  update_arp_entry(struct netif *netif, st Line 293  update_arp_entry(struct netif *netif, st
293            for (k = 0; k < netif->hwaddr_len; ++k) {            for (k = 0; k < netif->hwaddr_len; ++k) {
294              ethhdr->dest.addr[k] = ethaddr->addr[k];              ethhdr->dest.addr[k] = ethaddr->addr[k];
295            }            }
296            ethhdr->type = htons(ETHTYPE_IP);                                  ethhdr->type = htons(ETHTYPE_IP);
297            DEBUGF(ETHARP_DEBUG | DBG_TRACE, ("update_arp_entry: sending queued IP packet.\n"));            DEBUGF(ETHARP_DEBUG | DBG_TRACE, ("update_arp_entry: sending queued IP packet.\n"));
298            /* send the queued IP packet */            /* send the queued IP packet */
299            netif->linkoutput(netif, p);            netif->linkoutput(netif, p);
# Line 327  update_arp_entry(struct netif *netif, st Line 331  update_arp_entry(struct netif *netif, st
331        DEBUGF(ETHARP_DEBUG | DBG_TRACE | DBG_STATE, ("update_arp_entry: filling empty entry %u with state %u\n", i, arp_table[i].state));        DEBUGF(ETHARP_DEBUG | DBG_TRACE | DBG_STATE, ("update_arp_entry: filling empty entry %u with state %u\n", i, arp_table[i].state));
332        LWIP_ASSERT("update_arp_entry: arp_table[i].state == ETHARP_STATE_EMPTY", arp_table[i].state == ETHARP_STATE_EMPTY);        LWIP_ASSERT("update_arp_entry: arp_table[i].state == ETHARP_STATE_EMPTY", arp_table[i].state == ETHARP_STATE_EMPTY);
333      }      }
334      /* set IP address */        /* set IP address */
335      ip_addr_set(&arp_table[i].ipaddr, ipaddr);      ip_addr_set(&arp_table[i].ipaddr, ipaddr);
336      /* set Ethernet hardware address */        /* set Ethernet hardware address */
337      for (k = 0; k < netif->hwaddr_len; ++k) {      for (k = 0; k < netif->hwaddr_len; ++k) {
338        arp_table[i].ethaddr.addr[k] = ethaddr->addr[k];        arp_table[i].ethaddr.addr[k] = ethaddr->addr[k];
339      }      }
340      /* reset time-stamp */        /* reset time-stamp */
341      arp_table[i].ctime = 0;      arp_table[i].ctime = 0;
342      /* mark as stable */        /* mark as stable */
343      arp_table[i].state = ETHARP_STATE_STABLE;      arp_table[i].state = ETHARP_STATE_STABLE;
344      /* no queued packet */        /* no queued packet */
345  #if ARP_QUEUEING  #if ARP_QUEUEING
346      arp_table[i].p = NULL;      arp_table[i].p = NULL;
347  #endif  #endif
# Line 359  update_arp_entry(struct netif *netif, st Line 363  update_arp_entry(struct netif *netif, st
363   *   *
364   * @param netif The lwIP network interface on which the IP packet pbuf arrived.   * @param netif The lwIP network interface on which the IP packet pbuf arrived.
365   * @param pbuf The IP packet that arrived on netif.   * @param pbuf The IP packet that arrived on netif.
366   *   *
367   * @return NULL   * @return NULL
368   *   *
369   * @see pbuf_free()   * @see pbuf_free()
# Line 368  struct pbuf * Line 372  struct pbuf *
372  etharp_ip_input(struct netif *netif, struct pbuf *p)  etharp_ip_input(struct netif *netif, struct pbuf *p)
373  {  {
374    struct ethip_hdr *hdr;    struct ethip_hdr *hdr;
375      
376    /* Only insert an entry if the source IP address of the    /* Only insert an entry if the source IP address of the
377       incoming IP packet comes from a host on the local network. */       incoming IP packet comes from a host on the local network. */
378    hdr = p->payload;    hdr = p->payload;
# Line 377  etharp_ip_input(struct netif *netif, str Line 381  etharp_ip_input(struct netif *netif, str
381      /* do nothing */      /* do nothing */
382      return NULL;      return NULL;
383    }    }
384      
385    DEBUGF(ETHARP_DEBUG | DBG_TRACE, ("etharp_ip_input: updating ETHARP table.\n"));    DEBUGF(ETHARP_DEBUG | DBG_TRACE, ("etharp_ip_input: updating ETHARP table.\n"));
386    /* update ARP table, ask to insert entry */    /* update ARP table, ask to insert entry */
387    update_arp_entry(netif, &(hdr->ip.src), &(hdr->eth.src), ARP_INSERT_FLAG);    update_arp_entry(netif, &(hdr->ip.src), &(hdr->eth.src), ARP_INSERT_FLAG);
# Line 387  etharp_ip_input(struct netif *netif, str Line 391  etharp_ip_input(struct netif *netif, str
391    
392  /**  /**
393   * Responds to ARP requests, updates ARP entries and sends queued IP packets.   * Responds to ARP requests, updates ARP entries and sends queued IP packets.
394   *   *
395   * Should be called for incoming ARP packets. The pbuf in the argument   * Should be called for incoming ARP packets. The pbuf in the argument
396   * is freed by this function.   * is freed by this function.
397   *   *
# Line 451  etharp_arp_input(struct netif *netif, st Line 455  etharp_arp_input(struct netif *netif, st
455        ARPH_HWLEN_SET(hdr, netif->hwaddr_len);        ARPH_HWLEN_SET(hdr, netif->hwaddr_len);
456    
457          hdr->proto = htons(ETHTYPE_IP);          hdr->proto = htons(ETHTYPE_IP);
458        ARPH_PROTOLEN_SET(hdr, sizeof(struct ip_addr));              ARPH_PROTOLEN_SET(hdr, sizeof(struct ip_addr));
459    
460          hdr->ethhdr.type = htons(ETHTYPE_ARP);                hdr->ethhdr.type = htons(ETHTYPE_ARP);
461        /* return ARP reply */        /* return ARP reply */
462        netif->linkoutput(netif, p);        netif->linkoutput(netif, p);
463      } else {      } else {
464        DEBUGF(ETHARP_DEBUG | DBG_TRACE, ("etharp_arp_input: incoming ARP request was not for us.\n"));        DEBUGF(ETHARP_DEBUG | DBG_TRACE, ("etharp_arp_input: incoming ARP request was not for us.\n"));
465      }      }
466      break;      break;
467    case ARP_REPLY:        case ARP_REPLY:
468      /* ARP reply. We insert or update the ARP table. */      /* ARP reply. We insert or update the ARP table. */
469      DEBUGF(ETHARP_DEBUG | DBG_TRACE, ("etharp_arp_input: incoming ARP reply\n"));      DEBUGF(ETHARP_DEBUG | DBG_TRACE, ("etharp_arp_input: incoming ARP reply\n"));
470  #if (LWIP_DHCP && DHCP_DOES_ARP_CHECK)  #if (LWIP_DHCP && DHCP_DOES_ARP_CHECK)
# Line 492  etharp_arp_input(struct netif *netif, st Line 496  etharp_arp_input(struct netif *netif, st
496    return NULL;    return NULL;
497  }  }
498    
499  /**  /**
500   * Resolve and fill-in Ethernet address header for outgoing packet.   * Resolve and fill-in Ethernet address header for outgoing packet.
501   *   *
502   * If ARP has the Ethernet address in cache, the given packet is   * If ARP has the Ethernet address in cache, the given packet is
# Line 510  etharp_arp_input(struct netif *netif, st Line 514  etharp_arp_input(struct netif *netif, st
514   * @param netif The lwIP network interface which the IP packet will be sent on.   * @param netif The lwIP network interface which the IP packet will be sent on.
515   * @param ipaddr The IP address of the packet destination.   * @param ipaddr The IP address of the packet destination.
516   * @param pbuf The pbuf(s) containing the IP packet to be sent.   * @param pbuf The pbuf(s) containing the IP packet to be sent.
517   *   *
518   * @return If non-NULL, a packet ready to be sent.   * @return If non-NULL, a packet ready to be sent.
519   */   */
520  struct pbuf *  struct pbuf *
521  etharp_output(struct netif *netif, struct ip_addr *ipaddr, struct pbuf *q)  etharp_output(struct netif *netif, struct ip_addr *ipaddr, struct pbuf *q)
# Line 521  etharp_output(struct netif *netif, struc Line 525  etharp_output(struct netif *netif, struc
525    u8_t i;    u8_t i;
526    
527    /* Make room for Ethernet header. */    /* Make room for Ethernet header. */
528    if (pbuf_header(q, sizeof(struct eth_hdr)) != 0) {        if (pbuf_header(q, sizeof(struct eth_hdr)) != 0) {
529      /* The pbuf_header() call shouldn't fail, and we'll just bail      /* The pbuf_header() call shouldn't fail, and we'll just bail
530      out if it does.. */      out if it does.. */
531      DEBUGF(ETHARP_DEBUG | DBG_TRACE | 2, ("etharp_output: could not allocate room for header.\n"));      DEBUGF(ETHARP_DEBUG | DBG_TRACE | 2, ("etharp_output: could not allocate room for header.\n"));
# Line 580  etharp_output(struct netif *netif, struc Line 584  etharp_output(struct netif *netif, struc
584    
585      /* Ethernet address for IP destination address is in ARP cache? */      /* Ethernet address for IP destination address is in ARP cache? */
586      for(i = 0; i < ARP_TABLE_SIZE; ++i) {      for(i = 0; i < ARP_TABLE_SIZE; ++i) {
587        /* match found? */            /* match found? */
588        if (arp_table[i].state == ETHARP_STATE_STABLE &&        if (arp_table[i].state == ETHARP_STATE_STABLE &&
589          ip_addr_cmp(ipaddr, &arp_table[i].ipaddr)) {          ip_addr_cmp(ipaddr, &arp_table[i].ipaddr)) {
590          dest = &arp_table[i].ethaddr;          dest = &arp_table[i].ethaddr;
# Line 616  etharp_output(struct netif *netif, struc Line 620  etharp_output(struct netif *netif, struc
620      /* return the outgoing packet */      /* return the outgoing packet */
621      return q;      return q;
622    }    }
623    /* never reached; here for safety */    /* never reached; here for safety */
624    return NULL;    return NULL;
625  }  }
626    
# Line 750  err_t etharp_query(struct netif *netif, Line 754  err_t etharp_query(struct netif *netif,
754          hdr->ethhdr.dest.addr[j] = 0xff;          hdr->ethhdr.dest.addr[j] = 0xff;
755          hdr->ethhdr.src.addr[j] = srcaddr->addr[j];          hdr->ethhdr.src.addr[j] = srcaddr->addr[j];
756        }        }
757        hdr->ethhdr.type = htons(ETHTYPE_ARP);              hdr->ethhdr.type = htons(ETHTYPE_ARP);
758        /* send ARP query */        /* send ARP query */
759        result = netif->linkoutput(netif, p);        result = netif->linkoutput(netif, p);
760        /* free ARP query packet */        /* free ARP query packet */

Legend:
Removed from v.1.44  
changed lines
  Added in v.1.45

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