diff --git a/configs/sim/pktradio/defconfig b/configs/sim/pktradio/defconfig index 08872ccffc..071b502c16 100644 --- a/configs/sim/pktradio/defconfig +++ b/configs/sim/pktradio/defconfig @@ -25,19 +25,19 @@ CONFIG_EXAMPLES_NETTEST_SERVER_PORTNO=61616 CONFIG_EXAMPLES_NETTEST_SERVERIPv6ADDR_1=0xfe80 CONFIG_EXAMPLES_NETTEST_SERVERIPv6ADDR_6=0x00ff CONFIG_EXAMPLES_NETTEST_SERVERIPv6ADDR_7=0xfe00 -CONFIG_EXAMPLES_NETTEST_SERVERIPv6ADDR_8=0xcda9 +CONFIG_EXAMPLES_NETTEST_SERVERIPv6ADDR_8=0x00a9 CONFIG_EXAMPLES_NETTEST_STACKSIZE1=4096 CONFIG_EXAMPLES_NETTEST=y CONFIG_EXAMPLES_NSH=y CONFIG_EXAMPLES_UDPBLASTER_HOSTIPv6_1=0xfe80 CONFIG_EXAMPLES_UDPBLASTER_HOSTIPv6_6=0x00ff CONFIG_EXAMPLES_UDPBLASTER_HOSTIPv6_7=0xfe00 -CONFIG_EXAMPLES_UDPBLASTER_HOSTIPv6_8=0x1034 +CONFIG_EXAMPLES_UDPBLASTER_HOSTIPv6_8=0x0010 CONFIG_EXAMPLES_UDPBLASTER_STACKSIZE=8192 CONFIG_EXAMPLES_UDPBLASTER_TARGETIPv6_1=0xfe80 CONFIG_EXAMPLES_UDPBLASTER_TARGETIPv6_6=0x00ff CONFIG_EXAMPLES_UDPBLASTER_TARGETIPv6_7=0xfe00 -CONFIG_EXAMPLES_UDPBLASTER_TARGETIPv6_8=0xa9cd +CONFIG_EXAMPLES_UDPBLASTER_TARGETIPv6_8=0x00a9 CONFIG_EXAMPLES_UDPBLASTER=y CONFIG_EXPERIMENTAL=y CONFIG_FAT_LCNAMES=y diff --git a/include/nuttx/net/sixlowpan.h b/include/nuttx/net/sixlowpan.h index 8c56f6cead..d3e67d5a11 100644 --- a/include/nuttx/net/sixlowpan.h +++ b/include/nuttx/net/sixlowpan.h @@ -267,6 +267,26 @@ * NOTE: we currently assume 64-bits prefixes */ +/* Check whether we can compress the IID in address 'a' to 16 bits. This is + * used for unicast addresses only, and is true if the address is on the + * format ::0000:00ff:fe00:00xx. + * + * NOTE: we currently assume 64-bits prefixes. Big-endian, network order is + * assumed. + */ + +/* Check whether we can compress the IID in address 'a' to 8 bits. This is + * used for unicast addresses only, and is true if the address is on the + * format ::0000:00ff:fe00:00XX. + * + * NOTE: we currently assume 64-bits prefixes. Big-endian, network order is + * assumed. + */ + +#define SIXLOWPAN_IS_IID_8BIT_COMPRESSABLE(a) \ + ((((a)[4]) == 0x0000) && (((a)[5]) == HTONS(0x00ff)) && \ + (((a)[6]) == HTONS(0xfe00)) && ((((a)[7]) & HTONS(0x00ff)) == 0)) + /* Check whether we can compress the IID in address 'a' to 16 bits. This is * used for unicast addresses only, and is true if the address is on the * format ::0000:00ff:fe00:XXXX. diff --git a/net/sixlowpan/sixlowpan_tcpsend.c b/net/sixlowpan/sixlowpan_tcpsend.c index 949ff4e4f2..dd1b808292 100644 --- a/net/sixlowpan/sixlowpan_tcpsend.c +++ b/net/sixlowpan/sixlowpan_tcpsend.c @@ -852,7 +852,7 @@ ssize_t psock_6lowpan_tcp_send(FAR struct socket *psock, FAR const void *buf, conn->u.ipv6.raddr, &destmac); if (ret < 0) { - nerr("ERROR: Failed to dest MAC address: %d\n", ret); + nerr("ERROR: Failed to get dest MAC address: %d\n", ret); return (ssize_t)ret; } @@ -971,7 +971,7 @@ void sixlowpan_tcp_send(FAR struct net_driver_s *dev, ipv6hdr->ipv6.destipaddr, &destmac); if (ret < 0) { - nerr("ERROR: Failed to dest MAC address: %d\n", ret); + nerr("ERROR: Failed to get dest MAC address: %d\n", ret); goto drop; } diff --git a/net/sixlowpan/sixlowpan_udpsend.c b/net/sixlowpan/sixlowpan_udpsend.c index 17c9abdf11..5e661bceec 100644 --- a/net/sixlowpan/sixlowpan_udpsend.c +++ b/net/sixlowpan/sixlowpan_udpsend.c @@ -314,7 +314,7 @@ ssize_t psock_6lowpan_udp_sendto(FAR struct socket *psock, to6->sin6_addr.in6_u.u6_addr16, &destmac); if (ret < 0) { - nerr("ERROR: Failed to dest MAC address: %d\n", ret); + nerr("ERROR: Failed to get dest MAC address: %d\n", ret); return (ssize_t)ret; } @@ -490,7 +490,7 @@ void sixlowpan_udp_send(FAR struct net_driver_s *dev, ipv6udp->ipv6.destipaddr, &destmac); if (ret < 0) { - nerr("ERROR: Failed to dest MAC address: %d\n", ret); + nerr("ERROR: Failed to get dest MAC address: %d\n", ret); goto drop; } diff --git a/net/sixlowpan/sixlowpan_utils.c b/net/sixlowpan/sixlowpan_utils.c index e7f6f27a1e..895d232c52 100644 --- a/net/sixlowpan/sixlowpan_utils.c +++ b/net/sixlowpan/sixlowpan_utils.c @@ -64,6 +64,41 @@ #ifdef CONFIG_NET_6LOWPAN +/**************************************************************************** + * Pre-processor Definitions + ****************************************************************************/ + +/* REVISIT: The setting CONFIG_PKTRADIO_ADDRLEN should be the *maximum* + * address length. If there is only a single packet radio then it should be + * the exact address length of that radio. If there are multiple packet + * radios with different address lengths, then it will be inexact; it will + * be the size of the longest address. + */ + +#undef HAVE_BYTEADDR +#undef HAVE_SADDR +#undef HAVE_EADDR + +#ifdef CONFIG_WIRELESS_IEEE802154 +# define HAVE_SADDR 1 +# define HAVE_EADDR 1 +#endif + +#ifdef CONFIG_WIRELESS_PKTRADIO +# if CONFIG_PKTRADIO_ADDRLEN == 1 +# define HAVE_BYTEADDR 1 +# elif CONFIG_PKTRADIO_ADDRLEN == 2 +# define HAVE_BYTEADDR 1 +# define HAVE_SADDR 1 +# elif CONFIG_PKTRADIO_ADDRLEN == 8 +# define HAVE_BYTEADDR 1 +# define HAVE_SADDR 1 +# define HAVE_EADDR 1 +# else +# error Unsupported value for CONFIG_PKTRADIO_ADDRLEN +# endif +#endif + /**************************************************************************** * Private Functions ****************************************************************************/ @@ -86,6 +121,18 @@ ****************************************************************************/ #ifndef CONFIG_NET_STARPOINT +#ifdef HAVE_BYTEADDR +static void sixlowpan_baddrfromip(const net_ipv6addr_t ipaddr, FAR uint8_t *baddr) +{ + DEBUGASSERT(ipaddr[0] == HTONS(0xfe80)); + + /* Big-endian uint16_t to byte order */ + + baddr[0] = ipaddr[7] >> 8 ^ 0x02; +} +#endif + +#ifdef HAVE_SADDR static void sixlowpan_saddrfromip(const net_ipv6addr_t ipaddr, FAR uint8_t *saddr) { DEBUGASSERT(ipaddr[0] == HTONS(0xfe80)); @@ -96,7 +143,9 @@ static void sixlowpan_saddrfromip(const net_ipv6addr_t ipaddr, FAR uint8_t *sadd saddr[1] = ipaddr[7] & 0xff; saddr[0] ^= 0x02; } +#endif +#ifdef HAVE_EADDR static void sixlowpan_eaddrfromip(const net_ipv6addr_t ipaddr, FAR uint8_t *eaddr) { FAR uint8_t *eptr = eaddr; @@ -114,6 +163,7 @@ static void sixlowpan_eaddrfromip(const net_ipv6addr_t ipaddr, FAR uint8_t *eadd eaddr[0] ^= 0x02; } +#endif #endif /* !CONFIG_NET_STARPOINT */ /**************************************************************************** @@ -221,7 +271,7 @@ int sixlowpan_destaddrfromip(FAR struct sixlowpan_driver_s *radio, const net_ipv6addr_t ipaddr, FAR struct netdev_varaddr_s *destaddr) { -#ifdef CONFIG_NET_STARPOINT +#ifdef CONFIG_NET_STARPOINT int ret; /* If this node is a "point" in a star topology, then the destination @@ -239,25 +289,98 @@ int sixlowpan_destaddrfromip(FAR struct sixlowpan_driver_s *radio, return ret; -#else - DEBUGASSERT(ipaddr[0] == HTONS(0xfe80)); +#else /* CONFIG_NET_STARPOINT */ - /* Otherwise, the destination MAC address is encoded in the IP address */ + /* Otherwise, the destination MAC address is encoded in the IP address */ - if (SIXLOWPAN_IS_IID_16BIT_COMPRESSABLE(ipaddr)) - { - memset(destaddr, 0, sizeof(struct netdev_varaddr_s)); - sixlowpan_saddrfromip(ipaddr, destaddr->nv_addr); - destaddr->nv_addrlen = NET_6LOWPAN_SADDRSIZE; - } - else - { - sixlowpan_eaddrfromip(ipaddr, destaddr->nv_addr); - destaddr->nv_addrlen = NET_6LOWPAN_EADDRSIZE; - } +#ifdef CONFIG_WIRELESS_PKTRADIO + /* If this is a packet radio, then we cannot know the correct size of the + * radio's MAC address without asking. The setting CONFIG_PKTRADIO_ADDRLEN + * is inexact if there are multiple packet radios with different address + * lengths; it that case it will be the size of the longest address. + * + * NOTE: This logic assumes that the packet radio's address length is a + * constant. + */ - return OK; +#ifdef CONFIG_WIRELESS_IEEE802154 + if (radio->r_dev.d_lltype == NET_LL_PKTRADIO) #endif + { + struct sixlowpan_properties_s properties; + int ret; + + DEBUGASSERT(radio->r_properties != NULL); + ret = radio->r_properties(radio, &properties); + if (ret < 0) + { + return ret; + } + + DEBUGASSERT(ipaddr[0] == HTONS(0xfe80)); + +#ifdef HAVE_BYTEADDR + if (properties.sp_addrlen == 1 && + SIXLOWPAN_IS_IID_8BIT_COMPRESSABLE(ipaddr)) + { + memset(destaddr, 0, sizeof(struct netdev_varaddr_s)); + sixlowpan_baddrfromip(ipaddr, destaddr->nv_addr); + destaddr->nv_addrlen = 1; + return OK; + } + else +#endif +#ifdef HAVE_SADDR + if (properties.sp_addrlen == 2 && + SIXLOWPAN_IS_IID_16BIT_COMPRESSABLE(ipaddr)) + { + memset(destaddr, 0, sizeof(struct netdev_varaddr_s)); + sixlowpan_saddrfromip(ipaddr, destaddr->nv_addr); + destaddr->nv_addrlen = 2; + return OK; + } + else +#endif +#ifdef HAVE_EADDR + if (properties.sp_addrlen == 8) + { + sixlowpan_eaddrfromip(ipaddr, destaddr->nv_addr); + destaddr->nv_addrlen = 8; + return OK; + } + else +#endif + { + /* Just to satisfy the last dangling 'else' */ + } + + return -EADDRNOTAVAIL; + } + +#endif /* CONFIG_WIRELESS_PKTRADIO */ + +#ifdef CONFIG_WIRELESS_IEEE802154 +#ifdef CONFIG_WIRELESS_PKTRADIO + else +#endif + { + if (SIXLOWPAN_IS_IID_16BIT_COMPRESSABLE(ipaddr)) + { + memset(destaddr, 0, sizeof(struct netdev_varaddr_s)); + sixlowpan_saddrfromip(ipaddr, destaddr->nv_addr); + destaddr->nv_addrlen = NET_6LOWPAN_SADDRSIZE; + } + else + { + sixlowpan_eaddrfromip(ipaddr, destaddr->nv_addr); + destaddr->nv_addrlen = NET_6LOWPAN_EADDRSIZE; + } + + return OK; + } + +#endif /* CONFIG_WIRELESS_IEEE802154 */ +#endif /* CONFIG_NET_STARPOINT */ } /**************************************************************************** @@ -276,7 +399,7 @@ int sixlowpan_destaddrfromip(FAR struct sixlowpan_driver_s *radio, * ****************************************************************************/ -#ifdef CONFIG_WIRELESS_PKTRADIO +#ifdef HAVE_BYTEADDR static inline void sixlowpan_ipfrombyte(FAR const uint8_t *byte, FAR net_ipv6addr_t ipaddr) { @@ -291,6 +414,7 @@ static inline void sixlowpan_ipfrombyte(FAR const uint8_t *byte, } #endif +#ifdef HAVE_SADDR static inline void sixlowpan_ipfromsaddr(FAR const uint8_t *saddr, FAR net_ipv6addr_t ipaddr) { @@ -304,7 +428,9 @@ static inline void sixlowpan_ipfromsaddr(FAR const uint8_t *saddr, ipaddr[7] = (uint16_t)saddr[0] << 8 | (uint16_t)saddr[1]; ipaddr[7] ^= 0x0200; } +#endif +#ifdef HAVE_EADDR static inline void sixlowpan_ipfromeaddr(FAR const uint8_t *eaddr, FAR net_ipv6addr_t ipaddr) { @@ -318,25 +444,30 @@ static inline void sixlowpan_ipfromeaddr(FAR const uint8_t *eaddr, ipaddr[7] = (uint16_t)eaddr[6] << 8 | (uint16_t)eaddr[7]; ipaddr[4] ^= 0x0200; } +#endif void sixlowpan_ipfromaddr(FAR const struct netdev_varaddr_s *addr, FAR net_ipv6addr_t ipaddr) { switch (addr->nv_addrlen) { -#ifdef CONFIG_WIRELESS_PKTRADIO +#ifdef HAVE_BYTEADDR case 1: sixlowpan_ipfrombyte(addr->nv_addr, ipaddr); break; #endif +#ifdef HAVE_SADDR case NET_6LOWPAN_SADDRSIZE: sixlowpan_ipfromsaddr(addr->nv_addr, ipaddr); break; +#endif +#ifdef HAVE_EADDR case NET_6LOWPAN_EADDRSIZE: sixlowpan_ipfromeaddr(addr->nv_addr, ipaddr); break; +#endif default: nerr("ERROR: Unsupported address length: %u\n", addr->nv_addrlen); @@ -360,7 +491,7 @@ void sixlowpan_ipfromaddr(FAR const struct netdev_varaddr_s *addr, * ****************************************************************************/ -#ifdef CONFIG_WIRELESS_PKTRADIO +#ifdef HAVE_BYTEADDR static inline bool sixlowpan_isbytebased(const net_ipv6addr_t ipaddr, uint8_t byte) { @@ -392,16 +523,20 @@ bool sixlowpan_ismacbased(const net_ipv6addr_t ipaddr, { switch (addr->nv_addrlen) { -#ifdef CONFIG_WIRELESS_PKTRADIO +#ifdef HAVE_BYTEADDR case 1: return sixlowpan_isbytebased(ipaddr, addr->nv_addr[0]); #endif +#ifdef HAVE_SADDR case NET_6LOWPAN_SADDRSIZE: return sixlowpan_issaddrbased(ipaddr, addr->nv_addr); +#endif +#ifdef HAVE_EADDR case NET_6LOWPAN_EADDRSIZE: return sixlowpan_iseaddrbased(ipaddr, addr->nv_addr); +#endif default: nerr("ERROR: Unsupported address length: %u\n", addr->nv_addrlen); diff --git a/wireless/pktradio/pktradio_loopback.c b/wireless/pktradio/pktradio_loopback.c index eea89ebce6..8c6ad88eeb 100644 --- a/wireless/pktradio/pktradio_loopback.c +++ b/wireless/pktradio/pktradio_loopback.c @@ -264,7 +264,7 @@ static inline void lo_netmask(FAR struct net_driver_s *dev) dev->d_ipv6netmask[4] = 0xffff; dev->d_ipv6netmask[5] = 0xffff; dev->d_ipv6netmask[6] = 0xffff; - dev->d_ipv6netmask[7] = HTONS(0x00ff); + dev->d_ipv6netmask[7] = HTONS(0xff00); #elif CONFIG_PKTRADIO_ADDRLEN == 2 dev->d_ipv6netmask[4] = 0xffff;