diff --git a/Documentation/NuttxPortingGuide.html b/Documentation/NuttxPortingGuide.html index 0d3b978d0bc46239b7453cf1efaa225cc1aee0e5..992548fafd6cc0e7accfcf2f7e285838ee9af884 100644 --- a/Documentation/NuttxPortingGuide.html +++ b/Documentation/NuttxPortingGuide.html @@ -1643,7 +1643,10 @@ The system can be re-made subsequently by just typing <code>make</code>. <code>CONFIG_NET_ARPTAB_SIZE</code>: The size of the ARP table </li> <li> - <code>CONFIG_NET_BROADCAST</code>: Broadcast support + <code>CONFIG_NET_BROADCAST</code>: Incoming UDP broadcast support + </li> + <li> + <code>CONFIG_NET_MULTICAST</code>: Outgoing multi-cast address support </li> <li> <code>CONFIG_NET_LLH_LEN</code>: The link level header length diff --git a/configs/README.txt b/configs/README.txt index 176cbbe6ffc505449480b8daed84bb9687ee7d13..ab27e3252afcd6b22a22da04ecb34aff123a9807 100644 --- a/configs/README.txt +++ b/configs/README.txt @@ -304,7 +304,8 @@ defconfig -- This is a configuration file similar to the Linux CONFIG_NET_RECEIVE_WINDOW - The size of the advertised receiver's window CONFIG_NET_ARPTAB_SIZE - The size of the ARP table - CONFIG_NET_BROADCAST - Broadcast support + CONFIG_NET_BROADCAST - Incoming UDP broadcast support + CONFIG_NET_MULTICAST - Outgoing multi-cast address support CONFIG_NET_LLH_LEN - The link level header length CONFIG_NET_FWCACHE_SIZE - number of packets to remember when looking for duplicates diff --git a/net/uip/uip-arp.c b/net/uip/uip-arp.c index 6c48ec1b0121d9ae0de3b605320e1475f5ba3f2a..79fbaa3146afc54c480926f75e28c3d3403b1b64 100644 --- a/net/uip/uip-arp.c +++ b/net/uip/uip-arp.c @@ -2,7 +2,7 @@ * net/uip/uip-arp.c * Implementation of the ARP Address Resolution Protocol. * - * Copyright (C) 2007 Gregory Nutt. All rights reserved. + * Copyright (C) 2007, 2008 Gregory Nutt. All rights reserved. * Author: Gregory Nutt <spudmonkey@racsa.co.cr> * * Based on uIP which also has a BSD style license: @@ -126,13 +126,36 @@ struct arp_entry * Private Data ****************************************************************************/ -static const struct ether_addr broadcast_ethaddr = +/* Support for broadcast address */ + +static const struct ether_addr g_broadcast_ethaddr = {{0xff, 0xff, 0xff, 0xff, 0xff, 0xff}}; -static const uint16 broadcast_ipaddr[2] = {0xffff, 0xffff}; +static const uint16 g_broadcast_ipaddr[2] = {0xffff, 0xffff}; -static struct arp_entry arp_table[CONFIG_NET_ARPTAB_SIZE]; -static uint8 g_arptime; +/* Support for IGMP multicast addresses. + * + * Well-known ethernet multicast address: + * + * ADDRESS TYPE USAGE + * 01-00-0c-cc-cc-cc 0x0802 CDP (Cisco Discovery Protocol), VTP (Virtual Trunking Protocol) + * 01-00-0c-cc-cc-cd 0x0802 Cisco Shared Spanning Tree Protocol Address + * 01-80-c2-00-00-00 0x0802 Spanning Tree Protocol (for bridges) IEEE 802.1D + * 01-80-c2-00-00-02 0x0809 Ethernet OAM Protocol IEEE 802.3ah + * 01-00-5e-xx-xx-xx 0x0800 IPv4 IGMP Multicast Address + * 33-33-00-00-00-00 0x86DD IPv6 Neighbor Discovery + * 33-33-xx-xx-xx-xx 0x86DD IPv6 Multicast Address (RFC3307) + * + * The following is the first three octects of the IGMP address: + */ + +#if defined(CONFIG_NET_MULTICAST) && !defined(CONFIG_NET_IPv6) +static const ubyte g_multicast_ethaddr[3] = {0x01, 0x00, 0x5e}; +#endif +/* The table of known address mappings */ + +static struct arp_entry g_arptable[CONFIG_NET_ARPTAB_SIZE]; +static uint8 g_arptime; /**************************************************************************** * Private Functions @@ -173,7 +196,7 @@ static void uip_arp_update(uint16 *pipaddr, uint8 *ethaddr) for (i = 0; i < CONFIG_NET_ARPTAB_SIZE; ++i) { - tabptr = &arp_table[i]; + tabptr = &g_arptable[i]; /* Only check those entries that are actually in use. */ @@ -201,7 +224,7 @@ static void uip_arp_update(uint16 *pipaddr, uint8 *ethaddr) for (i = 0; i < CONFIG_NET_ARPTAB_SIZE; ++i) { - tabptr = &arp_table[i]; + tabptr = &g_arptable[i]; if (tabptr->at_ipaddr == 0) { break; @@ -218,7 +241,7 @@ static void uip_arp_update(uint16 *pipaddr, uint8 *ethaddr) int j = 0; for (i = 0; i < CONFIG_NET_ARPTAB_SIZE; ++i) { - tabptr = &arp_table[i]; + tabptr = &g_arptable[i]; if (g_arptime - tabptr->at_time > tmpage) { tmpage = g_arptime - tabptr->at_time; @@ -226,7 +249,7 @@ static void uip_arp_update(uint16 *pipaddr, uint8 *ethaddr) } } i = j; - tabptr = &arp_table[i]; + tabptr = &g_arptable[i]; } /* Now, i is the ARP table entry which we will fill with the new @@ -249,7 +272,7 @@ void uip_arp_init(void) int i; for (i = 0; i < CONFIG_NET_ARPTAB_SIZE; ++i) { - memset(&arp_table[i].at_ipaddr, 0, sizeof(in_addr_t)); + memset(&g_arptable[i].at_ipaddr, 0, sizeof(in_addr_t)); } } @@ -268,7 +291,7 @@ void uip_arp_timer(void) ++g_arptime; for (i = 0; i < CONFIG_NET_ARPTAB_SIZE; ++i) { - tabptr = &arp_table[i]; + tabptr = &g_arptable[i]; if (tabptr->at_ipaddr != 0 && g_arptime - tabptr->at_time >= UIP_ARP_MAXAGE) { tabptr->at_ipaddr = 0; @@ -394,10 +417,33 @@ void uip_arp_out(struct uip_driver_s *dev) /* First check if destination is a local broadcast. */ - if (uiphdr_ipaddr_cmp(IPBUF->eh_destipaddr, broadcast_ipaddr)) + if (uiphdr_ipaddr_cmp(IPBUF->eh_destipaddr, g_broadcast_ipaddr)) { - memcpy(ETHBUF->dest, broadcast_ethaddr.ether_addr_octet, ETHER_ADDR_LEN); + memcpy(ETHBUF->dest, g_broadcast_ethaddr.ether_addr_octet, ETHER_ADDR_LEN); } +#if defined(CONFIG_NET_MULTICAST) && !defined(CONFIG_NET_IPv6) + /* Check if the destination address is a multicast address + * + * - IPv4: multicast addresses lie in the class D group -- The address range + * 224.0.0.0 to 239.255.255.255 (224.0.0.0/4) + * + * - IPv6 multicast addresses are have the high-order octet of the + * addresses=0xff (ff00::/8.) + */ + + else if (IPBUF->eh_destipaddr[0] >= HTONS(0xe000) && + IPBUF->eh_destipaddr[0] <= HTONS(0xefff)) + { + /* Build the well-known IPv4 IGMP ethernet address. The first + * three bytes are fixed; the final three variable come from the + * last three bytes of the IP address. + */ + + const ubyte *ip = ((ubyte*)IPBUF->eh_destipaddr) + 1; + memcpy(ETHBUF->dest, g_multicast_ethaddr, 3); + memcpy(ÐBUF->dest[3], ip, 3); + } +#endif else { /* Check if the destination address is on the local network. */ @@ -423,7 +469,7 @@ void uip_arp_out(struct uip_driver_s *dev) for (i = 0; i < CONFIG_NET_ARPTAB_SIZE; ++i) { - tabptr = &arp_table[i]; + tabptr = &g_arptable[i]; if (uip_ipaddr_cmp(ipaddr, tabptr->at_ipaddr)) { break;