/[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.12 by likewise, Thu Nov 28 09:26:18 2002 UTC revision 1.13 by likewise, Fri Nov 29 16:02: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.13  2002/11/29 16:02:11  likewise
7     * More complete ARP protocol implementation.
8     *
9   * Revision 1.12  2002/11/28 09:26:18  likewise   * Revision 1.12  2002/11/28 09:26:18  likewise
10   * All ARP queueing code is now conditionally compiled-in.   * All ARP queueing code is now conditionally compiled-in.
11   *   *
# Line 104  RFC 3220 4.6          IP Mobility Suppor Line 107  RFC 3220 4.6          IP Mobility Suppor
107  /** 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. */
108  #define ARP_MAXPENDING 2  #define ARP_MAXPENDING 2
109    
110  /** dis/enable existing ARP entries updates on any ARP traffic */  /**
111  #ifndef ETHARP_SNOOP_UPDATES   *
112  #  define ETHARP_SNOOP_UPDATES 0   * - If enabled, cache entries are generated for every kind of ARP/IP traffic.
113     * This enhances behaviour for sending to a dynamic set of hosts, for example
114     * if acting as a gateway.
115     * - If disabled, cache entries are generated only for IP destination addresses
116     * in use by lwIP or applications. This enhances performance if sending to a small,
117     * reasonably static number of hosts. Typically for embedded devices.
118     */
119    #ifndef ETHARP_ALWAYS_INSERT
120    #  define ETHARP_ALWAYS_INSERT 1
121  #endif  #endif
122    
123  #define HWTYPE_ETHERNET 1  #define HWTYPE_ETHERNET 1
# Line 141  static const struct eth_addr ethbroadcas Line 152  static const struct eth_addr ethbroadcas
152  static struct etharp_entry arp_table[ARP_TABLE_SIZE];  static struct etharp_entry arp_table[ARP_TABLE_SIZE];
153  static u8_t ctime;  static u8_t ctime;
154    
155  static struct pbuf *update_arp_entry(struct ip_addr *ipaddr, struct eth_addr *ethaddr, u8_t flags);  static struct pbuf *update_arp_entry(struct netif *netif, struct ip_addr *ipaddr, struct eth_addr *ethaddr, u8_t flags);
156  #define ARP_INSERT_FLAG 1  #define ARP_INSERT_FLAG 1
157    
158  /**  /**
# Line 171  etharp_tmr(void) Line 182  etharp_tmr(void)
182    u8_t i;    u8_t i;
183        
184    ++ctime;    ++ctime;
185      DEBUGF(ETHARP_DEBUG, ("etharp_timer\n"));
186    /* remove expired entries from the ARP table */    /* remove expired entries from the ARP table */
187    for(i = 0; i < ARP_TABLE_SIZE; ++i) {    for(i = 0; i < ARP_TABLE_SIZE; ++i) {
188      if((arp_table[i].state == ETHARP_STATE_STABLE) &&            if((arp_table[i].state == ETHARP_STATE_STABLE) &&      
189         (ctime - arp_table[i].ctime >= ARP_MAXAGE)) {         (ctime - arp_table[i].ctime >= ARP_MAXAGE)) {
190        DEBUGF(ETHARP_DEBUG, ("etharp_timer: expired stable entry %u.\n", i));        DEBUGF(ETHARP_DEBUG, ("etharp_timer: expired stable entry %u.\n", i));
191        arp_table[i].state = ETHARP_STATE_EMPTY;        arp_table[i].state = ETHARP_STATE_EMPTY;
192    #if ARP_QUEUEING
193          /* remove any queued packet */
194          pbuf_free(arp_table[i].p);      
195          arp_table[i].p = NULL;
196    #endif
197      } else if((arp_table[i].state == ETHARP_STATE_PENDING) &&      } else if((arp_table[i].state == ETHARP_STATE_PENDING) &&
198                (ctime - arp_table[i].ctime >= ARP_MAXPENDING)) {                (ctime - arp_table[i].ctime >= ARP_MAXPENDING)) {
199        DEBUGF(ETHARP_DEBUG, ("etharp_timer: expired pending entry %u - dequeueing %p.\n", i, arp_table[i].p));        DEBUGF(ETHARP_DEBUG, ("etharp_timer: expired pending entry %u - dequeueing %p.\n", i, arp_table[i].p));
# Line 230  find_arp_entry(void) Line 247  find_arp_entry(void)
247  }  }
248    
249  /**  /**
250   * Update (or insert) an entry in the ARP cache.   * Update (or insert) a IP/MAC address pair in the ARP cache.
251   *   *
252   * @param ipaddr IP address of the inserted ARP entry.   * @param ipaddr IP address of the inserted ARP entry.
253   * @param ethaddr Ethernet address of the inserted ARP entry.   * @param ethaddr Ethernet address of the inserted ARP entry.
254   * @param flags Defines behaviour:   * @param flags Defines behaviour:
255   * - ARP_INSERT_FLAG Allows ARP to insert this as a new item. If not specified,   * - ARP_INSERT_FLAG Allows ARP to insert this as a new item. If not specified,
256   * only existing ARP entries will be updated.   * only existing ARP entries will be updated.
257     *
258   * @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.
259   * You should sent it and must call pbuf_free().   * You should sent it and must call pbuf_free() afterwards.
260   *   *
261   * @see pbuf_free()   * @see pbuf_free()
262   */   */
263  static struct pbuf *  static struct pbuf *
264  update_arp_entry(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)
265  {  {
266    u8_t i, k;    u8_t i, k;
267    struct eth_hdr *ethhdr;    struct eth_hdr *ethhdr;
268  #if ARP_QUEUEING    /* do not update for 0.0.0.0 addresses */
269    struct pbuf *p;    if (ipaddr->addr == 0) return NULL;
 #endif  
   
270    /* Walk through the ARP mapping table and try to find an entry to    /* Walk through the ARP mapping table and try to find an entry to
271    update. If none is found, the IP -> MAC address mapping is    update. If none is found, the IP -> MAC address mapping is
272    inserted in the ARP table. */    inserted in the ARP table. */
# Line 258  update_arp_entry(struct ip_addr *ipaddr, Line 274  update_arp_entry(struct ip_addr *ipaddr,
274      /* Check if the source IP address of the incoming packet matches      /* Check if the source IP address of the incoming packet matches
275      the IP address in this ARP table entry. */      the IP address in this ARP table entry. */
276      if(ip_addr_cmp(ipaddr, &arp_table[i].ipaddr)) {      if(ip_addr_cmp(ipaddr, &arp_table[i].ipaddr)) {
277          /* pending entry? */
278        /* check those entries that are already in use. */        if(arp_table[i].state == ETHARP_STATE_PENDING) {
279            DEBUGF(ETHARP_DEBUG, ("update_arp_entry: pending entry %u goes stable\n", i));
280            /* A pending entry was found, mark it stable */
281            arp_table[i].state = ETHARP_STATE_STABLE;
282            /* fall-through to next if */
283          }
284          /* stable entry? (possible just marked to become stable) */
285        if(arp_table[i].state == ETHARP_STATE_STABLE) {        if(arp_table[i].state == ETHARP_STATE_STABLE) {
286          DEBUGF(ETHARP_DEBUG, ("update_arp_entry: updating stable entry %u\n", i));          DEBUGF(ETHARP_DEBUG, ("update_arp_entry: updating stable entry %u\n", i));
287          /* An old entry found, update this and return. */          /* An old entry found, update this and return. */
288          for(k = 0; k < 6; ++k) {          for(k = 0; k < 6; ++k) {
289            arp_table[i].ethaddr.addr[k] = ethaddr->addr[k];            arp_table[i].ethaddr.addr[k] = ethaddr->addr[k];
290          }          }
291            /* time stamp */
292          arp_table[i].ctime = ctime;          arp_table[i].ctime = ctime;
         return NULL;  
       }  
       else if(arp_table[i].state == ETHARP_STATE_PENDING) {  
         /* A pending entry was found, so we fill this in and return  
         the queued packet (if any). */  
         DEBUGF(ETHARP_DEBUG, ("update_arp_entry: pending entry %u made stable\n", i));  
         for(k = 0; k < 6; ++k) {  
           arp_table[i].ethaddr.addr[k] = ethaddr->addr[k];  
         }  
         arp_table[i].ctime = ctime;  
         arp_table[i].state = ETHARP_STATE_STABLE;  
293  #if ARP_QUEUEING  #if ARP_QUEUEING
         p = arp_table[i].p;  
294          // queued packet present? */          // queued packet present? */
295          if(p != NULL) {          if(arp_table[i].p != NULL) {    
           /* remove queued packet from ARP entry (must be freed by the caller) */  
           arp_table[i].p = NULL;          
296    
297            /* fill-in Ethernet header */            /* fill-in Ethernet header */
298            ethhdr = p->payload;            ethhdr = arp_table[i].p->payload;
   
299            for(k = 0; k < 6; ++k) {            for(k = 0; k < 6; ++k) {
300              ethhdr->dest.addr[k] = ethaddr->addr[k];              ethhdr->dest.addr[k] = ethaddr->addr[k];
301            }            }
   
302            ethhdr->type = htons(ETHTYPE_IP);                                  ethhdr->type = htons(ETHTYPE_IP);                      
303            DEBUGF(ETHARP_DEBUG, ("update_arp_entry: returning queued packet %p\n", p));            DEBUGF(ETHARP_DEBUG, ("update_arp_entry: sending queued IP packet.\n"));
304              /* send the queued IP packet */
305              netif->linkoutput(netif, arp_table[i].p);
306              /* free the queued IP packet */
307              pbuf_free(arp_table[i].p);
308              /* remove queued packet from ARP entry (must be freed by the caller) */
309              arp_table[i].p = NULL;        
310          }          }
         /* return queued packet, if any */  
         return p;  
 #else  
         /* ARP queueing disabled */  
         return NULL;  
311  #endif  #endif
312            return NULL;
313        }        }
314      }      } /* if */
315    }    } /* for */
316    
317    /* no matching ARP entry was found */    /* no matching ARP entry was found */
318      ASSERT("update_arp_entry: i == ARP_TABLE_SIZE", i == ARP_TABLE_SIZE);
319    
320    /* allowed to insert an entry? */    /* allowed to insert an entry? */
321    if (flags & ARP_INSERT_FLAG)    if ((ETHARP_ALWAYS_INSERT) || (flags & ARP_INSERT_FLAG))
322    {    {
323      /* find an empty or old entry. */      /* find an empty or old entry. */
324      i = find_arp_entry();      i = find_arp_entry();
# Line 314  update_arp_entry(struct ip_addr *ipaddr, Line 326  update_arp_entry(struct ip_addr *ipaddr,
326        DEBUGF(ETHARP_DEBUG, ("update_arp_entry: no available entry found\n"));        DEBUGF(ETHARP_DEBUG, ("update_arp_entry: no available entry found\n"));
327        return NULL;        return NULL;
328      }      }
329        /* see if find_arp_entry() gave us an old stable, or empty entry to re-use */
330      if (arp_table[i].state == ETHARP_STATE_STABLE) {      if (arp_table[i].state == ETHARP_STATE_STABLE) {
331        DEBUGF(ETHARP_DEBUG, ("update_arp_entry: overwriting old stable entry %u\n", i));        DEBUGF(ETHARP_DEBUG, ("update_arp_entry: overwriting old stable entry %u\n", i));
332          /* stable entries should have no queued packets (TODO: allow later) */
333          ASSERT("update_arp_entry: arp_table[i].p != NULL", arp_table[i].p != NULL);
334        } else {
335          DEBUGF(ETHARP_DEBUG, ("update_arp_entry: filling empty entry %u with state %u\n", i, arp_table[i].stat));
336          ASSERT("update_arp_entry: arp_table[i].state == ETHARP_STATE_EMPTY", arp_table[i].state == ETHARP_STATE_EMPTY);
337      }      }
338      else {      /* set IP address */  
       DEBUGF(ETHARP_DEBUG, ("update_arp_entry: using empty entry %u\n", i));  
     }    
339      ip_addr_set(&arp_table[i].ipaddr, ipaddr);      ip_addr_set(&arp_table[i].ipaddr, ipaddr);
340        /* set Ethernet hardware address */  
341      for(k = 0; k < 6; ++k) {      for(k = 0; k < 6; ++k) {
342        arp_table[i].ethaddr.addr[k] = ethaddr->addr[k];        arp_table[i].ethaddr.addr[k] = ethaddr->addr[k];
343      }      }
344        /* time-stamp */  
345      arp_table[i].ctime = ctime;      arp_table[i].ctime = ctime;
346        /* mark as stable */  
347      arp_table[i].state = ETHARP_STATE_STABLE;      arp_table[i].state = ETHARP_STATE_STABLE;
348        /* no queued packet */  
349      arp_table[i].p = NULL;      arp_table[i].p = NULL;
350    }    }
351      else
352      {
353        DEBUGF(ETHARP_DEBUG, ("update_arp_entry: no matching stable entry to update\n", i));
354      }
355    return NULL;    return NULL;
356  }  }
357    
358  /**  /**
359   * Updates the ARP table and may return any queued packet to be sent.   * Updates the ARP table using the given packet.
360   *   *
361   * Should be called for all incoming packets of IP kind. It updates   * Uses the incoming IP packet's source address to update the
362   * the ARP table for the local network. The function does not alter   * ARP cache for the local network. The function does not alter
363   * the packet in any way and does not free it. After this function has   * or free the packet. This function must be called before the
364   * been called, the packet p must be given to the IP layer.   * packet p is passed to the IP layer.
365   *   *
366   * @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.
  *  
367   * @param pbuf The IP packet that arrived on netif.   * @param pbuf The IP packet that arrived on netif.
368   *   *
369   * @return If non-NULL, a pbuf that was queued on an ARP entry. The device   * @return NULL
  * driver must transmit this packet onto the network, and call pbuf_free()  
  * for the pbuf.  
370   *   *
371   * @see pbuf_free()   * @see pbuf_free()
372   */   */
# Line 355  etharp_ip_input(struct netif *netif, str Line 375  etharp_ip_input(struct netif *netif, str
375  {  {
376    struct ethip_hdr *hdr;    struct ethip_hdr *hdr;
377        
378    hdr = p->payload;    /* Only insert an entry if the source IP address of the
     
   /* Only insert/update an entry if the source IP address of the  
379       incoming IP packet comes from a host on the local network. */       incoming IP packet comes from a host on the local network. */
380          hdr = p->payload;
381    /* source is on local network? */    /* source is on local network? */
382    if(!ip_addr_maskcmp(&(hdr->ip.src), &(netif->ip_addr), &(netif->netmask))) {    if(!ip_addr_maskcmp(&(hdr->ip.src), &(netif->ip_addr), &(netif->netmask))) {
383      /* do nothing */      /* do nothing */
384      return NULL;      return NULL;
385    }    }
386      
387    DEBUGF(ETHARP_DEBUG, ("etharp_ip_input: updating ETHARP table.\n"));    DEBUGF(ETHARP_DEBUG, ("etharp_ip_input: updating ETHARP table.\n"));
388    /* update ARP table, may insert */    /* update ARP table, ask to insert entry */
389    return update_arp_entry(&(hdr->ip.src), &(hdr->eth.src), ARP_INSERT_FLAG);    update_arp_entry(netif, &(hdr->ip.src), &(hdr->eth.src), ARP_INSERT_FLAG);
390      return NULL;
391  }  }
392    
393    
394  /**  /**
395   * Updates the ARP table and returns an ARP reply or a queued IP packet.   * Responds to ARP requests, updates ARP entries and sends queued IP packets.
396   *   *
397   * Should be called for incoming ARP packets. The pbuf in the argument   * Should be called for incoming ARP packets. The pbuf in the argument
398   * is freed by this function. The returned pbuf is to be sent and then   * is freed by this function.
  * freed by the caller.  
399   *   *
400   * @param netif The lwIP network interface on which the ARP packet pbuf arrived.   * @param netif The lwIP network interface on which the ARP packet pbuf arrived.
401   * @param pbuf The ARP packet that arrived on netif. Is freed by this function.   * @param pbuf The ARP packet that arrived on netif. Is freed by this function.
402   * @param ethaddr Ethernet address of netif.   * @param ethaddr Ethernet address of netif.
403   *   *
404   * @return pbuf to be sent and freed by the caller.   * @return NULL
405   *   *
406   * @see pbuf_free()   * @see pbuf_free()
407   */   */
# Line 390  struct pbuf * Line 409  struct pbuf *
409  etharp_arp_input(struct netif *netif, struct eth_addr *ethaddr, struct pbuf *p)  etharp_arp_input(struct netif *netif, struct eth_addr *ethaddr, struct pbuf *p)
410  {  {
411    struct etharp_hdr *hdr;    struct etharp_hdr *hdr;
   struct pbuf *q;  
412    u8_t i;    u8_t i;
413    
414    /* drop short ARP packets */    /* drop short ARP packets */
415    if(p->tot_len < sizeof(struct etharp_hdr)) {    if(p->tot_len < sizeof(struct etharp_hdr)) {
416      DEBUGF(ETHARP_DEBUG, ("etharp_etharp_input: packet too short (%d/%d)\n", p->tot_len, sizeof(struct etharp_hdr)));      DEBUGF(ETHARP_DEBUG, ("etharp_arp_input: packet too short (%d/%d)\n", p->tot_len, sizeof(struct etharp_hdr)));
417      pbuf_free(p);      pbuf_free(p);
418      return NULL;      return NULL;
419    }    }
# Line 406  etharp_arp_input(struct netif *netif, st Line 424  etharp_arp_input(struct netif *netif, st
424    /* ARP request? */    /* ARP request? */
425    case ARP_REQUEST:    case ARP_REQUEST:
426      /* ARP request. If it asked for our address, we send out a      /* ARP request. If it asked for our address, we send out a
427      reply. */      reply. In any case, we time-stamp any existing ARP entry,
428      DEBUGF(ETHARP_DEBUG, ("etharp_arp_input: ARP request\n"));      and possiby send out an IP packet that was queued on it. */
429    
430        DEBUGF(ETHARP_DEBUG, ("etharp_arp_input: incoming ARP request\n"));
431        /* we are not configured? */
432        if(netif->ip_addr.addr == 0) {
433          DEBUGF(ETHARP_DEBUG, ("etharp_arp_input: we are unconfigured, ARP request ignored.\n"));
434          pbuf_free(p);
435          return NULL;
436        }
437        /* update the ARP cache */
438        update_arp_entry(netif, &(hdr->sipaddr), &(hdr->shwaddr), 0);
439      /* ARP request for our address? */      /* ARP request for our address? */
440      if(ip_addr_cmp(&(hdr->dipaddr), &(netif->ip_addr))) {      if(ip_addr_cmp(&(hdr->dipaddr), &(netif->ip_addr))) {
441    
442        DEBUGF(ETHARP_DEBUG, ("etharp_arp_input: ARP request for our address\n"));        DEBUGF(ETHARP_DEBUG, ("etharp_arp_input: replying to ARP request for our IP address\n"));
443        /* re-use pbuf to send ARP reply */        /* re-use pbuf to send ARP reply */
444        hdr->opcode = htons(ARP_REPLY);        hdr->opcode = htons(ARP_REPLY);
445    
# Line 433  etharp_arp_input(struct netif *netif, st Line 461  etharp_arp_input(struct netif *netif, st
461    
462          hdr->ethhdr.type = htons(ETHTYPE_ARP);                hdr->ethhdr.type = htons(ETHTYPE_ARP);      
463        /* return ARP reply */        /* return ARP reply */
464        return p;        netif->linkoutput(netif, p);
465        } else {
466          DEBUGF(ETHARP_DEBUG, ("etharp_arp_input: ARP request, but not for us.\n"));
467      }      }
 #if ETHARP_SNOOP_UPDATES  
     /* request, NOT for our address */  
     else {  
       /* update_arp_entry() can return a pbuf that has previously been  
       queued waiting for this IP address to become ARP stable. */  
       q = update_arp_entry(&(hdr->sipaddr), &(hdr->shwaddr), 0);  
       pbuf_free(p);  
       p = NULL;  
       return q;  
     }  
 #endif  
468      break;      break;
469    case ARP_REPLY:        case ARP_REPLY:    
470      /* ARP reply. We insert or update the ARP table. */      /* ARP reply. We insert or update the ARP table. */
# Line 454  etharp_arp_input(struct netif *netif, st Line 473  etharp_arp_input(struct netif *netif, st
473      /* DHCP needs to know about ARP replies */      /* DHCP needs to know about ARP replies */
474      dhcp_arp_reply(&hdr->sipaddr);      dhcp_arp_reply(&hdr->sipaddr);
475  #endif  #endif
476      /* for our address? */      /* ARP reply directed to us? */
477      if(ip_addr_cmp(&(hdr->dipaddr), &(netif->ip_addr))) {          if(ip_addr_cmp(&(hdr->dipaddr), &(netif->ip_addr))) {
478        DEBUGF(ETHARP_DEBUG, ("etharp_arp_input: ARP reply for us\n"));        DEBUGF(ETHARP_DEBUG, ("etharp_arp_input: ARP reply for us\n"));
479        /* update_arp_entry() can return a pbuf that has previously been        /* update_the ARP cache, ask to insert */
480        queued waiting for this IP address to become ARP stable. */        update_arp_entry(netif, &(hdr->sipaddr), &(hdr->shwaddr), ARP_INSERT_FLAG);
481        q = update_arp_entry(&(hdr->sipaddr), &(hdr->shwaddr), ARP_INSERT_FLAG);      /* ARP reply not directed to us */
482        /* free incoming ARP reply pbuf */      } else {
483        pbuf_free(p);        DEBUGF(ETHARP_DEBUG, ("etharp_arp_input: ARP reply, but NOT for us\n"));
484        p = NULL;        /* update the destination address pair */
485        return q;        update_arp_entry(netif, &(hdr->sipaddr), &(hdr->shwaddr), 0);
486      }        /* update the destination address pair */
487  #if ETHARP_SNOOP_UPDATES        update_arp_entry(netif, &(hdr->dipaddr), &(hdr->dhwaddr), 0);
     /* ARP reply, NOT for our address */  
     else {  
       /* update_arp_entry() can return a pbuf that has previously been  
       queued waiting for this IP address to become ARP stable. */  
       q = update_arp_entry(&(hdr->sipaddr), &(hdr->shwaddr), 0);  
       pbuf_free(p);  
       p = NULL;  
       return q;  
488      }      }
 #endif  
489      break;      break;
490    default:    default:
491      DEBUGF(ETHARP_DEBUG, ("etharp_arp_input: unknown type %d\n", htons(hdr->opcode)));      DEBUGF(ETHARP_DEBUG, ("etharp_arp_input: unknown type %d\n", htons(hdr->opcode)));
492      break;      break;
493    }    }
494      /* free ARP packet */
495    pbuf_free(p);    pbuf_free(p);
496      p = NULL;
497      /* nothing to send, we did it! */
498    return NULL;    return NULL;
499  }  }
500    
# Line 514  etharp_output(struct netif *netif, struc Line 527  etharp_output(struct netif *netif, struc
527  {  {
528    struct eth_addr *dest, *srcaddr, mcastaddr;    struct eth_addr *dest, *srcaddr, mcastaddr;
529    struct eth_hdr *ethhdr;    struct eth_hdr *ethhdr;
   struct pbuf *p;  
530    u8_t i;    u8_t i;
531    
532    /* Make room for Ethernet header. */    /* Make room for Ethernet header. */
# Line 559  etharp_output(struct netif *netif, struc Line 571  etharp_output(struct netif *netif, struc
571    /* destination IP address is an IP unicast address */    /* destination IP address is an IP unicast address */
572    else {    else {
573      /* destination IP network address not on local network? */      /* destination IP network address not on local network? */
574        /* this occurs if the packet is routed to the default gateway on this interface */
575      if(!ip_addr_maskcmp(ipaddr, &(netif->ip_addr), &(netif->netmask))) {      if(!ip_addr_maskcmp(ipaddr, &(netif->ip_addr), &(netif->netmask))) {
576        /* gateway available? */        /* gateway available? */
577        if (netif->gw.addr != 0)        if (netif->gw.addr != 0)
578        {        {
579          /* use the default gateway IP address */          /* use the gateway IP address */
580          ipaddr = &(netif->gw);          ipaddr = &(netif->gw);
581        }        }
582          /* no gateway available? */
583        else        else
584        {        {
585          /* IP destination address outside local network, but no gateway available */          /* IP destination address outside local network, but no gateway available */
# Line 584  etharp_output(struct netif *netif, struc Line 598  etharp_output(struct netif *netif, struc
598      }      }
599      /* could not find the destination Ethernet address in ARP cache? */      /* could not find the destination Ethernet address in ARP cache? */
600      if (dest == NULL) {      if (dest == NULL) {
601        /* query for the IP address using ARP request */        /* ARP query for the IP address, submit this IP packet for queueing */
602        p = etharp_query(netif, ipaddr, q);        etharp_query(netif, ipaddr, q);
603        /* return the ARP request */        /* return nothing */
604        return p;        return NULL;
605      }      }
606      /* destination Ethernet address resolved from ARP cache*/      /* destination Ethernet address resolved from ARP cache */
607      else      else
608      {      {
609        /* fallthrough */        /* fallthrough */
# Line 600  etharp_output(struct netif *netif, struc Line 614  etharp_output(struct netif *netif, struc
614    if (dest != NULL) {    if (dest != NULL) {
615      /* A valid IP->MAC address mapping was found, so we construct the      /* A valid IP->MAC address mapping was found, so we construct the
616      Ethernet header for the outgoing packet. */      Ethernet header for the outgoing packet. */
   
617      ethhdr = q->payload;      ethhdr = q->payload;
618    
619      for(i = 0; i < 6; i++) {      for(i = 0; i < 6; i++) {
# Line 633  struct pbuf * Line 646  struct pbuf *
646  etharp_output_sent(struct pbuf *p)  etharp_output_sent(struct pbuf *p)
647  {  {
648    struct etharp_hdr *hdr;    struct etharp_hdr *hdr;
649    hdr=p->payload;    hdr = p->payload;
650    if (hdr->opcode == htons(ARP_REQUEST)) {    if (hdr->opcode == htons(ARP_REQUEST)) {
651      pbuf_free(p);      pbuf_free(p);
652      p = NULL;      p = NULL;
# Line 654  etharp_output_sent(struct pbuf *p) Line 667  etharp_output_sent(struct pbuf *p)
667   * @param q If non-NULL, a pbuf that must be queued on the   * @param q If non-NULL, a pbuf that must be queued on the
668   * ARP entry for the ipaddr IP address.   * ARP entry for the ipaddr IP address.
669   *   *
670   * @return pbuf containing the ARP request, NULL on failure.   * @return NULL.
671   *   *
672   * @note Might be used in the future by manual IP configuration   * @note Might be used in the future by manual IP configuration
673   * as well.   * as well.
674   *   *
675     * TODO: enqueue q here if possible (BEWARE: possible other packet already
676     * queued.
677     * TODO: The host requirements RFC states that ARP should save at least one
678     * packet, and this should be the _latest_ packet.
679     * TODO: use the ctime field to see how long ago an ARP request was sent,
680     * possibly retry.
681   */   */
682  struct pbuf *etharp_query(struct netif *netif, struct ip_addr *ipaddr, struct pbuf *q)  struct pbuf *etharp_query(struct netif *netif, struct ip_addr *ipaddr, struct pbuf *q)
683  {  {
# Line 670  struct pbuf *etharp_query(struct netif * Line 689  struct pbuf *etharp_query(struct netif *
689    srcaddr = (struct eth_addr *)netif->hwaddr;    srcaddr = (struct eth_addr *)netif->hwaddr;
690    /* bail out if this IP address is pending */    /* bail out if this IP address is pending */
691    for(i = 0; i < ARP_TABLE_SIZE; ++i) {    for(i = 0; i < ARP_TABLE_SIZE; ++i) {
692      if(arp_table[i].state == ETHARP_STATE_PENDING &&      if(ip_addr_cmp(ipaddr, &arp_table[i].ipaddr)) {
693        ip_addr_cmp(ipaddr, &arp_table[i].ipaddr)) {        if (arp_table[i].state == ETHARP_STATE_PENDING) {
694        DEBUGF(ETHARP_DEBUG, ("etharp_query: request already pending\n"));          DEBUGF(ETHARP_DEBUG, ("etharp_query: requested IP already pending\n"));
695        /* TODO: enqueue q here if possible (BEWARE: possible other packet already          /* break out of for-loop */
696           queued. */          break;
697        /* TODO: The host requirements RFC states that ARP should save at least one        }
698           packet, and this should be the _latest_ packet. */        else if (arp_table[i].state == ETHARP_STATE_STABLE) {
699        /* TODO: use the ctime field to see how long ago an ARP request was sent,          DEBUGF(ETHARP_DEBUG, ("etharp_query: requested IP already stable\n"));
700           possibly retry. */          return NULL;
701        return NULL;        }
702      }      }
703    }    }
704    i = find_arp_entry();    /* queried address not yet pending in ARP table? */
705    /* bail out if no ARP entries are available */    if (i == ARP_TABLE_SIZE)
   if(i == ARP_TABLE_SIZE)  
706    {    {
707      DEBUGF(ETHARP_DEBUG, ("etharp_query: no more ARP table entries available.\n"));      DEBUGF(ETHARP_DEBUG, ("etharp_query: IP address non-pending\n"));
708      return NULL;      /* find an available entry */
709        i = find_arp_entry();
710        /* bail out if no ARP entries are available */
711        if(i == ARP_TABLE_SIZE)
712        {
713          DEBUGF(ETHARP_DEBUG, ("etharp_query: no more ARP table entries available.\n"));
714          return NULL;
715        }
716        DEBUGF(ETHARP_DEBUG, ("etharp_query: created ARP table entry.\n"));
717        /* i is available, create ARP entry */
718        ip_addr_set(&arp_table[i].ipaddr, ipaddr);
719        arp_table[i].ctime = ctime;
720        arp_table[i].state = ETHARP_STATE_PENDING;
721        arp_table[i].p = NULL;
722    }    }
   
   /* i is an available ARP table entry */  
723    /* allocate a pbuf for the outgoing ARP request packet */    /* allocate a pbuf for the outgoing ARP request packet */
724    p = pbuf_alloc(PBUF_LINK, sizeof(struct etharp_hdr), PBUF_RAM);    p = pbuf_alloc(PBUF_LINK, sizeof(struct etharp_hdr), PBUF_RAM);
725    /* could allocate pbuf? */    /* could allocate pbuf? */
726    if (p != NULL) {    if (p != NULL) {
727      ip_addr_set(&arp_table[i].ipaddr, ipaddr);      DEBUGF(ETHARP_DEBUG, ("etharp_query: sending ARP request.\n"));
728      arp_table[i].ctime = ctime;      hdr = p->payload;
729      arp_table[i].state = ETHARP_STATE_PENDING;      hdr->opcode = htons(ARP_REQUEST);
730  #if ARP_QUEUEING      for(i = 0; i < 6; ++i)
731      /* any pbuf to queue? */      {
732      if (q != NULL) {        hdr->dhwaddr.addr[i] = 0x00;
733        /* copy PBUF_REF referenced payloads to PBUF_RAM */        hdr->shwaddr.addr[i] = srcaddr->addr[i];
       q = pbuf_unref(q);  
       /* pbufs are queued, increase the reference count */  
       pbuf_ref_chain(q);  
734      }      }
735      /* remember pbuf to queue, if any */      ip_addr_set(&(hdr->dipaddr), ipaddr);
736      arp_table[i].p = q;      ip_addr_set(&(hdr->sipaddr), &(netif->ip_addr));
 #else  
     arp_table[i].p = NULL;  
 #endif  
   }  
   /* could not allocate pbuf for ARP request */  
   else {  
     return NULL;  
   }  
   /* p is the allocated pbuf */  
     
   hdr = p->payload;  
   hdr->opcode = htons(ARP_REQUEST);  
   
   for(i = 0; i < 6; ++i)  
   {  
     hdr->dhwaddr.addr[i] = 0x00;  
     hdr->shwaddr.addr[i] = srcaddr->addr[i];  
   }  
   
   ip_addr_set(&(hdr->dipaddr), ipaddr);  
   ip_addr_set(&(hdr->sipaddr), &(netif->ip_addr));  
   
   hdr->hwtype = htons(HWTYPE_ETHERNET);  
   ARPH_HWLEN_SET(hdr, 6);  
737    
738    hdr->proto = htons(ETHTYPE_IP);      hdr->hwtype = htons(HWTYPE_ETHERNET);
739    ARPH_PROTOLEN_SET(hdr, sizeof(struct ip_addr));      ARPH_HWLEN_SET(hdr, 6);
740    
741    for(i = 0; i < 6; ++i)      hdr->proto = htons(ETHTYPE_IP);
742    {      ARPH_PROTOLEN_SET(hdr, sizeof(struct ip_addr));
743      hdr->ethhdr.dest.addr[i] = 0xff;      for(i = 0; i < 6; ++i)
744      hdr->ethhdr.src.addr[i] = srcaddr->addr[i];      {
745          hdr->ethhdr.dest.addr[i] = 0xff;
746          hdr->ethhdr.src.addr[i] = srcaddr->addr[i];
747        }
748        hdr->ethhdr.type = htons(ETHTYPE_ARP);      
749        /* send ARP query */
750        netif->linkoutput(netif, p);
751        /* free ARP query packet */
752        pbuf_free(p);
753        p = NULL;
754      } else {
755        DEBUGF(ETHARP_DEBUG, ("etharp_query: could not allocate pbuf for ARP request.\n"));
756    }    }
757    #if ARP_QUEUEING
758    hdr->ethhdr.type = htons(ETHTYPE_ARP);          /* any pbuf to queue and queue is empty? */
759    return p;    if ((q != NULL) && (arp_table[i].p == NULL)) {
760        /* copy PBUF_REF referenced payloads to PBUF_RAM */
761        q = pbuf_unref(q);
762        /* pbufs are queued, increase the reference count */
763        pbuf_ref_chain(q);
764        /* remember pbuf to queue, if any */
765        arp_table[i].p = q;
766        DEBUGF(ETHARP_DEBUG, ("etharp_query: queued packet on ARP entry.\n"));
767      }
768    #endif
769      return NULL;
770  }  }

Legend:
Removed from v.1.12  
changed lines
  Added in v.1.13

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