From 922454d51513eaa4ac1872f6b6e2ce91356e3638 Mon Sep 17 00:00:00 2001 From: Gregory Nutt Date: Thu, 22 Jun 2017 13:55:08 -0600 Subject: [PATCH] 6LoWPAN: Loopback driver needs to initialize the MAC meta data; Address decompression logic must have the MAC address to handle the most common compression cases. --- net/sixlowpan/sixlowpan_hc06.c | 182 +++++++++++++++++------ net/sixlowpan/sixlowpan_input.c | 2 +- net/sixlowpan/sixlowpan_internal.h | 18 ++- wireless/ieee802154/mac802154_loopback.c | 30 +++- 4 files changed, 179 insertions(+), 53 deletions(-) diff --git a/net/sixlowpan/sixlowpan_hc06.c b/net/sixlowpan/sixlowpan_hc06.c index 99e71d860f2..eac66fadace 100644 --- a/net/sixlowpan/sixlowpan_hc06.c +++ b/net/sixlowpan/sixlowpan_hc06.c @@ -109,43 +109,58 @@ static FAR uint8_t *g_hc06ptr; /* Uncompression of linklocal * * 0 -> 16 bytes from packet - * 1 -> 2 bytes from prefix - bunch of zeroes and 8 from packet + * 1 -> 2 bytes from prefix - 16 bytes from packet * 2 -> 2 bytes from prefix - 0000::00ff:fe00:XXXX from packet - * 3 -> 2 bytes from prefix - infer 8 bytes from MAC address + * 3 -> 2 bytes from prefix - Infer 2 or 8 bytes from MAC address * * NOTE: => the uncompress function does change 0xf to 0x10 * NOTE: 0x00 => no-autoconfig => unspecified */ -static const uint8_t g_unc_llconf[] = { 0x0f, 0x28, 0x22, 0x20 }; +static const uint16_t g_unc_llconf[] = +{ + 0x000f, 0x0028, 0x0022, 0x0120 +}; /* Uncompression of ctx-based * * 0 -> 0 bits from packet [unspecified / reserved] - * 1 -> 8 bytes from prefix - bunch of zeroes and 8 from packet - * 2 -> 8 bytes from prefix - 0000::00ff:fe00:XXXX + 2 from packet - * 3 -> 8 bytes from prefix - infer 8 bytes from MAC address + * 1 -> 8 bytes from prefix - Bunch of zeroes and 8 bytes from packet + * 2 -> 8 bytes from prefix - 0000::00ff:fe00:XXXX and 2 bytes from packet + * 3 -> 8 bytes from prefix - Infer 2 or 8 bytes from MAC address */ -static const uint8_t g_unc_ctxconf[] = { 0x00, 0x88, 0x82, 0x80 }; +static const uint16_t g_unc_ctxconf[] = +{ + 0x0000, 0x0088, 0x0082, 0x0180 +}; /* Uncompression of ctx-based * * 0 -> 0 bits from packet - * 1 -> 2 bytes from prefix - bunch of zeroes 5 from packet - * 2 -> 2 bytes from prefix - zeroes + 3 from packet - * 3 -> 2 bytes from prefix - infer 1 bytes from MAC address + * 1 -> 2 bytes from prefix - Bunch of zeroes 5 bytes from packet + * 2 -> 2 bytes from prefix - Zeroes + 3 bytes from packet + * 3 -> 2 bytes from prefix - Infer 1 bytes from MAC address */ -static const uint8_t g_unc_mxconf[] = { 0x0f, 0x25, 0x23, 0x21 }; +static const uint16_t g_unc_mxconf[] = +{ + 0x000f, 0x0025, 0x0023, 0x0121 +}; /* Link local prefix */ -static const uint8_t g_llprefix[] = { 0xfe, 0x80 }; +static const uint8_t g_llprefix[] = +{ + 0xfe, 0x80 +}; /* TTL uncompression values */ -static const uint8_t g_ttl_values[] = { 0, 1, 64, 255 }; +static const uint8_t g_ttl_values[] = +{ + 0, 1, 64, 255 +}; /**************************************************************************** @@ -297,43 +312,114 @@ static uint8_t compress_laddr(FAR const net_ipv6addr_t ipaddr, * ****************************************************************************/ -static void uncompress_addr(FAR net_ipv6addr_t ipaddr, uint8_t const prefix[], - uint8_t prefpost) +static void uncompress_addr(FAR const struct ieee802154_addr_s *addr, + FAR const uint8_t *prefix, uint16_t prefpost, + FAR net_ipv6addr_t ipaddr) { - uint8_t prefcount = prefpost >> 4; - uint8_t postcount = prefpost & 0x0f; + FAR const uint8_t *srcptr; + bool fullmac = false; + bool usemac = (prefpost & 0x0100) != 0; + uint8_t prefcount = (prefpost >> 4) & 0xf; + uint8_t postcount = prefpost & 0x0f; /* The value 16 is encoded as 0xf in the 4 bit-fields. */ prefcount = prefcount == 15 ? 16 : prefcount; postcount = postcount == 15 ? 16 : postcount; + /* Select the data source */ + + srcptr = g_hc06ptr; + if (usemac) + { + bool saddr = (addr->mode == IEEE802154_ADDRMODE_SHORT); + uint16_t addrsize = saddr ? NET_6LOWPAN_SADDRSIZE: NET_6LOWPAN_EADDRSIZE; + + /* Select the source the address data */ + + srcptr = saddr ? addr->saddr : addr->eaddr; + + /* If the provided postcount is zero and we are taking data from the + * MAC address, set postcount to the address length. + */ + + if (postcount == 0) + { + postcount = addrsize; + } + + /* If we are converting the entire MAC address, then we need to some some + * special bit operations. + */ + + fullmac = (postcount == addrsize); + } + + /* Copy any prefix */ + if (prefcount > 0) { memcpy(ipaddr, prefix, prefcount); } + /* Clear bytes between int prefcount and postcount */ + if (prefcount + postcount < 16) { - FAR uint8_t *iptr = (FAR uint8_t *)&ipaddr[0]; + FAR uint8_t *destptr = (FAR uint8_t *)&ipaddr[0]; - memset(&iptr[prefcount], 0, 16 - (prefcount + postcount)); + memset(&destptr[prefcount], 0, 16 - (prefcount + postcount)); } + /* Copy the remaining data from the source */ + if (postcount > 0) { - FAR uint8_t *iptr = (FAR uint8_t *)&ipaddr[0]; - - memcpy(&iptr[16 - postcount], g_hc06ptr, postcount); if (postcount == 2 && prefcount < 11) { /* 16 bits uncompression => 0000:00ff:fe00:XXXX */ - iptr[11] = 0xff; - iptr[12] = 0xfe; + ipaddr[5] = HTONS(0x00ff); + ipaddr[6] = HTONS(0xfe00); } - g_hc06ptr += postcount; + /* If the postcount is even then take extra care with endian-ness */ + + if ((postcount & 1) == 0) + { + int destndx = 8 - (postcount >> 1); + int i; + + for (i = destndx; i < 8; i++) + { + ipaddr[i] = (uint16_t)srcptr[0] << 8 | (uint16_t)srcptr[1]; + srcptr += 2; + } + + /* If the was a standard MAC based address then toggle */ + + if (fullmac) + { + ipaddr[destndx] ^= 0x200; + } + } + + /* postcount is odd... */ + + else + { + FAR uint8_t *destptr = (FAR uint8_t *)&ipaddr[0]; + int offset = 16 - postcount; + + memcpy(&destptr[offset], srcptr, postcount); + } + + /* If we took the data from packet, then update the packet pointer */ + + if (!usemac) + { + g_hc06ptr += postcount; + } } else if (prefcount > 0) { @@ -342,9 +428,10 @@ static void uncompress_addr(FAR net_ipv6addr_t ipaddr, uint8_t const prefix[], nwarn("WARNING: No IID based configuration\n"); } - ninfo("Uncompressing %d + %d => %04x:%04x:%04x:%04x:%04x:%04x:%04x:%04x\n", - prefcount, postcount, ipaddr[0], ipaddr[2], ipaddr[3], ipaddr[5], - ipaddr[5], ipaddr[6], ipaddr[7]); + ninfo("Uncompressing %d + %d => %04x:%04x:%04x:%04x:%04x:%04x:%04x:%04\n", + prefcount, postcount, + ipaddr[0], ipaddr[1], ipaddr[2], ipaddr[3], + ipaddr[4], ipaddr[5], ipaddr[6], ipaddr[7]); } /**************************************************************************** @@ -860,20 +947,22 @@ void sixlowpan_compresshdr_hc06(FAR struct ieee802154_driver_s *ieee, * appropriate values * * Input Parmeters: - * iplen - Equal to 0 if the packet is not a fragment (IP length is then - * inferred from the L2 length), non 0 if the packet is a first - * fragment. - * iob - Pointer to the IOB containing the received frame. - * fptr - Pointer to frame to be compressed. - * bptr - Output goes here. Normally this is a known offset into d_buf, - * may be redirected to a "bitbucket" on the case of FRAGN frames. + * ind - MAC header meta data including node addressing information. + * iplen - Equal to 0 if the packet is not a fragment (IP length is then + * inferred from the L2 length), non 0 if the packet is a first + * fragment. + * iob - Pointer to the IOB containing the received frame. + * fptr - Pointer to frame to be compressed. + * bptr - Output goes here. Normally this is a known offset into d_buf, + * may be redirected to a "bitbucket" on the case of FRAGN frames. * * Returned Value: * None * ****************************************************************************/ -void sixlowpan_uncompresshdr_hc06(uint16_t iplen, FAR struct iob_s *iob, +void sixlowpan_uncompresshdr_hc06(FAR const struct ieee802154_data_ind_s *ind, + uint16_t iplen, FAR struct iob_s *iob, FAR uint8_t *fptr, FAR uint8_t *bptr) { FAR struct ipv6_hdr_s *ipv6 = (FAR struct ipv6_hdr_s *)bptr; @@ -1014,8 +1103,9 @@ void sixlowpan_uncompresshdr_hc06(uint16_t iplen, FAR struct iob_s *iob, * address. */ - uncompress_addr(ipv6->srcipaddr, - tmp != 0 ? addrcontext->prefix : NULL, g_unc_ctxconf[tmp]); + uncompress_addr(&ind->src, + tmp != 0 ? addrcontext->prefix : NULL, + g_unc_ctxconf[tmp], ipv6->srcipaddr); } else { @@ -1024,7 +1114,8 @@ void sixlowpan_uncompresshdr_hc06(uint16_t iplen, FAR struct iob_s *iob, * address. */ - uncompress_addr(ipv6->srcipaddr, g_llprefix, g_unc_llconf[tmp]); + uncompress_addr(&ind->src, g_llprefix, g_unc_llconf[tmp], + ipv6->srcipaddr); } /* Destination address */ @@ -1059,7 +1150,8 @@ void sixlowpan_uncompresshdr_hc06(uint16_t iplen, FAR struct iob_s *iob, g_hc06ptr++; } - uncompress_addr(ipv6->destipaddr, prefix, g_unc_mxconf[tmp]); + uncompress_addr(&ind->dest, prefix, g_unc_mxconf[tmp], + ipv6->destipaddr); } } else @@ -1082,13 +1174,17 @@ void sixlowpan_uncompresshdr_hc06(uint16_t iplen, FAR struct iob_s *iob, return; } - uncompress_addr(ipv6->destipaddr, addrcontext->prefix, g_unc_ctxconf[tmp]); + uncompress_addr(&ind->src, addrcontext->prefix, + g_unc_ctxconf[tmp], ipv6->destipaddr); } else { - /* Not address context based => link local M = 0, DAC = 0 - same as SAC */ + /* Not address context based => link local M = 0, DAC = 0 - same + * as SAC. + */ - uncompress_addr(ipv6->destipaddr, g_llprefix, g_unc_llconf[tmp]); + uncompress_addr(&ind->src,g_llprefix, g_unc_llconf[tmp], + ipv6->destipaddr); } } diff --git a/net/sixlowpan/sixlowpan_input.c b/net/sixlowpan/sixlowpan_input.c index a9fd0e36932..dc17d652159 100644 --- a/net/sixlowpan/sixlowpan_input.c +++ b/net/sixlowpan/sixlowpan_input.c @@ -532,7 +532,7 @@ static int sixlowpan_frame_process(FAR struct ieee802154_driver_s *ieee, if ((hc1[SIXLOWPAN_HC1_DISPATCH] & SIXLOWPAN_DISPATCH_IPHC_MASK) == SIXLOWPAN_DISPATCH_IPHC) { ninfo("IPHC Dispatch\n"); - sixlowpan_uncompresshdr_hc06(fragsize, iob, fptr, bptr); + sixlowpan_uncompresshdr_hc06(ind, fragsize, iob, fptr, bptr); } else #endif /* CONFIG_NET_6LOWPAN_COMPRESSION_HC06 */ diff --git a/net/sixlowpan/sixlowpan_internal.h b/net/sixlowpan/sixlowpan_internal.h index 37821e98284..662c5e6e1d8 100644 --- a/net/sixlowpan/sixlowpan_internal.h +++ b/net/sixlowpan/sixlowpan_internal.h @@ -441,13 +441,14 @@ void sixlowpan_compresshdr_hc06(FAR struct ieee802154_driver_s *ieee, * appropriate values * * Input Parmeters: - * iplen - Equal to 0 if the packet is not a fragment (IP length is then - * inferred from the L2 length), non 0 if the packet is a first - * fragment. - * iob - Pointer to the IOB containing the received frame. - * fptr - Pointer to frame to be compressed. - * bptr - Output goes here. Normally this is a known offset into d_buf, - * may be redirected to a "bitbucket" on the case of FRAGN frames. + * ind - MAC header meta data including node addressing information. + * iplen - Equal to 0 if the packet is not a fragment (IP length is then + * inferred from the L2 length), non 0 if the packet is a first + * fragment. + * iob - Pointer to the IOB containing the received frame. + * fptr - Pointer to frame to be compressed. + * bptr - Output goes here. Normally this is a known offset into d_buf, + * may be redirected to a "bitbucket" on the case of FRAGN frames. * * Returned Value: * None @@ -455,7 +456,8 @@ void sixlowpan_compresshdr_hc06(FAR struct ieee802154_driver_s *ieee, ****************************************************************************/ #ifdef CONFIG_NET_6LOWPAN_COMPRESSION_HC06 -void sixlowpan_uncompresshdr_hc06(uint16_t iplen, FAR struct iob_s *iob, +void sixlowpan_uncompresshdr_hc06(FAR const struct ieee802154_data_ind_s *ind, + uint16_t iplen, FAR struct iob_s *iob, FAR uint8_t *fptr, FAR uint8_t *bptr); #endif diff --git a/wireless/ieee802154/mac802154_loopback.c b/wireless/ieee802154/mac802154_loopback.c index 26c8879a0ba..28c84b117ff 100644 --- a/wireless/ieee802154/mac802154_loopback.c +++ b/wireless/ieee802154/mac802154_loopback.c @@ -118,7 +118,7 @@ static uint8_t g_iobuffer[CONFIG_NET_6LOWPAN_MTU + CONFIG_NET_GUARDSIZE]; static uint8_t g_eaddr[IEEE802154_EADDRSIZE] = { - 0x00, 0xfa, 0xde, 0x00, 0xde, 0xad, 0xbe, 0xef + 0x0c, 0xfa, 0xde, 0x00, 0xde, 0xad, 0xbe, 0xef }; static uint8_t g_saddr[IEEE802154_SADDRSIZE] = @@ -131,6 +131,16 @@ static uint8_t g_panid[IEEE802154_PANIDSIZE] = 0xca, 0xfe }; +static const uint8_t g_src_eaddr[IEEE802154_EADDRSIZE] = +{ + 0x0a, 0xfa, 0xde, 0x00, 0xde, 0xad, 0xbe, 0xef +}; + +static const uint8_t g_src_saddr[IEEE802154_SADDRSIZE] = +{ + 0x12, 0x34 +}; + /**************************************************************************** * Private Function Prototypes ****************************************************************************/ @@ -289,8 +299,26 @@ static int lo_loopback(FAR struct net_driver_s *dev) FAR struct iob_s *iob; int ret; + /* Create some fake metadata */ + memset(&ind, 0, sizeof(struct ieee802154_data_ind_s)); +#ifdef CONFIG_NET_6LOWPAN_EXTENDEDADDR + ind.src.mode = IEEE802154_ADDRMODE_EXTENDED; + ind.dest.mode = IEEE802154_ADDRMODE_EXTENDED; +#else + ind.src.mode = IEEE802154_ADDRMODE_SHORT; + ind.dest.mode = IEEE802154_ADDRMODE_SHORT; +#endif + + IEEE802154_PANIDCOPY(ind.src.panid, g_panid); + IEEE802154_SADDRCOPY(ind.src.saddr, g_src_saddr); + IEEE802154_EADDRCOPY(ind.src.eaddr, g_src_eaddr); + + IEEE802154_PANIDCOPY(ind.dest.panid, g_panid); + IEEE802154_SADDRCOPY(ind.dest.saddr, g_saddr); + IEEE802154_EADDRCOPY(ind.dest.eaddr, g_eaddr); + /* Loop while there framelist to be sent, i.e., while the freme list is not * emtpy. Sending, of course, just means relaying back through the network * for this driver.