From 9cc85aadf6dca024c34134856f1586fe342b9a9c Mon Sep 17 00:00:00 2001 From: Gregory Nutt Date: Fri, 8 Sep 2017 09:23:40 -0600 Subject: [PATCH] 6LoWPAN: Correct an error in uncompressing multicast address. --- configs/sim/README.txt | 2 +- include/nuttx/net/sixlowpan.h | 24 ++++++++---- net/sixlowpan/sixlowpan_hc06.c | 67 ++++++++++++++++++++++++---------- 3 files changed, 65 insertions(+), 28 deletions(-) diff --git a/configs/sim/README.txt b/configs/sim/README.txt index 4e133d822d..4952acbc7a 100644 --- a/configs/sim/README.txt +++ b/configs/sim/README.txt @@ -844,7 +844,7 @@ pf_ieee802154 pktradio This configuration is identical to the 'sixlowpan configuration - described below EXCEPT that is uses the genericl packet radio + described below EXCEPT that is uses the generic packet radio loopback network device. sixlowpan diff --git a/include/nuttx/net/sixlowpan.h b/include/nuttx/net/sixlowpan.h index 839e19b1fb..02fb79f360 100644 --- a/include/nuttx/net/sixlowpan.h +++ b/include/nuttx/net/sixlowpan.h @@ -182,17 +182,25 @@ #define SIXLOWPAN_IPHC_CID 0x80 /* Bit 8: Context identifier extension */ #define SIXLOWPAN_IPHC_SAC 0x40 /* Bit 9: Source address compression */ #define SIXLOWPAN_IPHC_SAM_MASK 0x30 /* Bits 10-11: Source address mode */ -# define SIXLOWPAN_IPHC_SAM_128 0x00 /* 128-bits */ -# define SIXLOWPAN_IPHC_SAM_64 0x10 /* 64-bits */ -# define SIXLOWPAN_IPHC_SAM_16 0x20 /* 16-bits */ -# define SIXLOWPAN_IPHC_SAM_0 0x30 /* 0-bits */ +# define SIXLOWPAN_IPHC_SAM_128 0x00 /* 128-bits */ +# define SIXLOWPAN_IPHC_SAM_64 0x10 /* 64-bits */ +# define SIXLOWPAN_IPHC_SAM_16 0x20 /* 16-bits */ +# define SIXLOWPAN_IPHC_SAM_0 0x30 /* 0-bits */ #define SIXLOWPAN_IPHC_M 0x08 /* Bit 12: Multicast compression */ #define SIXLOWPAN_IPHC_DAC 0x04 /* Bit 13: Destination address compression */ #define SIXLOWPAN_IPHC_DAM_MASK 0x03 /* Bits 14-15: Destination address mode */ -# define SIXLOWPAN_IPHC_DAM_128 0x00 /* 128-bits */ -# define SIXLOWPAN_IPHC_DAM_64 0x01 /* 64-bits */ -# define SIXLOWPAN_IPHC_DAM_16 0x02 /* 16-bits */ -# define SIXLOWPAN_IPHC_DAM_0 0x03 /* 0-bits */ + /* M=0 DAC=0/1: */ +# define SIXLOWPAN_IPHC_DAM_128 0x00 /* 128-bits */ +# define SIXLOWPAN_IPHC_DAM_64 0x01 /* 64-bits */ +# define SIXLOWPAN_IPHC_DAM_16 0x02 /* 16-bits */ +# define SIXLOWPAN_IPHC_DAM_0 0x03 /* 0-bits */ + /* M=1 DAC=0: */ +# define SIXLOWPAN_IPHC_MDAM_128 0x00 /* 128-bits */ +# define SIXLOWPAN_IPHC_MDAM_48 0x01 /* 48-bits: ffxx::00xx:xxxx:xxxx */ +# define SIXLOWPAN_IPHC_MDAM_32 0x02 /* 16-bits: ffxx::00xx:xxxx */ +# define SIXLOWPAN_IPHC_MDAM_8 0x03 /* 8-bits: ff02::00xx */ + /* M=1 DAC=1: */ +# define SIXLOWPAN_IPHC_MDDAM_48 0x00 /* 48-bits: ffxx:xxll:pppp:pppp:pppp:pppp:xxxx:xxxx */ #define SIXLOWPAN_IPHC_SAM_BIT 4 #define SIXLOWPAN_IPHC_DAM_BIT 0 diff --git a/net/sixlowpan/sixlowpan_hc06.c b/net/sixlowpan/sixlowpan_hc06.c index deca07733a..a50eeebe6b 100644 --- a/net/sixlowpan/sixlowpan_hc06.c +++ b/net/sixlowpan/sixlowpan_hc06.c @@ -70,6 +70,21 @@ #ifdef CONFIG_NET_6LOWPAN_COMPRESSION_HC06 +/**************************************************************************** + * Pre-processor Definitions + ****************************************************************************/ + +/* Used in the encoding of address uncompress rules */ + +#define UNCOMPRESS_POSTLEN_SHIFT 0 +#define UNCOMPRESS_POSTLEN_MASK (0x0f << UNCOMPRESS_POSTLEN_SHIFT) +# define UNCOMPRESS_POSTLEN(n) (((n) & UNCOMPRESS_POSTLEN_MASK) >> UNCOMPRESS_POSTLEN_SHIFT) +#define UNCOMPRESS_PREFLEN_SHIFT 4 +#define UNCOMPRESS_PREFLEN_MASK (0x0f << UNCOMPRESS_PREFLEN_SHIFT) +# define UNCOMPRESS_PREFLEN(n) (((n) & UNCOMPRESS_PREFLEN_MASK) >> UNCOMPRESS_PREFLEN_SHIFT) +#define UNCOMPRESS_MACBASED (1 << 8) +#define UNCOMPRESS_ZEROPAD (1 << 9) + /**************************************************************************** * Private Types ****************************************************************************/ @@ -139,15 +154,17 @@ static const uint16_t g_unc_ctxconf[] = /* Uncompression of mx-based * - * 0 -> 0 bits from packet - * 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 + * 0 -> 0 bits from prefix / 16 bytes inline + * 1 -> 2 bytes from prefix / 5 bytes inline: ffxx::00xx:xxxx:xxxx + * 2 -> 2 bytes from prefix / 3 bytes inline: ffxx::00xx:xxxx + * 3 -> 2 bytes from prefix / 1 byte inline: ff02::00xx + * + * All other bits required zero padding. */ static const uint16_t g_unc_mxconf[] = { - 0x000f, 0x0025, 0x0023, 0x0121 + 0x020f, 0x0225, 0x0223, 0x0221 }; /* Link local prefix */ @@ -391,9 +408,9 @@ static void uncompress_addr(FAR const struct netdev_varaddr_s *addr, { FAR const uint8_t *srcptr; bool fullmac = false; - bool usemac = (prefpost & 0x0100) != 0; - uint8_t prefcount = (prefpost >> 4) & 0xf; - uint8_t postcount = prefpost & 0x0f; + bool usemac = (prefpost & UNCOMPRESS_MACBASED) != 0; + uint8_t prefcount = UNCOMPRESS_PREFLEN(prefpost); + uint8_t postcount = UNCOMPRESS_POSTLEN(prefpost); int destndx; int endndx; int i; @@ -448,9 +465,15 @@ static void uncompress_addr(FAR const struct netdev_varaddr_s *addr, if (postcount > 0) { - if (postcount <= 2 && prefcount < 11) + /* If there is space for the ...:00ff:fe00:... and if we were not + * asked t specifically zero pad the address, then add these magic + * bits to the decoded address. + */ + + if (postcount <= 2 && prefcount < 11 && + (prefpost & UNCOMPRESS_ZEROPAD) == 0) { - /* 16 bits uncompression ipaddr=0000:00ff:fe00:XXXX */ + /* 16 bit uncompression ipaddr=0000:00ff:fe00:xxxx */ ipaddr[5] = HTONS(0x00ff); ipaddr[6] = HTONS(0xfe00); @@ -833,18 +856,24 @@ int sixlowpan_compresshdr_hc06(FAR struct radio_driver_s *radio, iphc1 |= SIXLOWPAN_IPHC_M; if (SIXLOWPAN_IS_MCASTADDR_COMPRESSABLE8(ipv6->destipaddr)) { - iphc1 |= SIXLOWPAN_IPHC_DAM_0; + iphc1 |= SIXLOWPAN_IPHC_MDAM_8; - /* Use last byte */ + /* Use "last" byte ("last" meaning the LS byte in host order. + * destipaddr is in big-endian network order). + */ - *g_hc06ptr = ipv6->destipaddr[7] & 0x00ff; +#ifdef CONFIG_ENDIAN_BIG + *g_hc06ptr = (ipv6->destipaddr[7] & 0xff); +#else + *g_hc06ptr = (ipv6->destipaddr[7] >> 8); +#endif g_hc06ptr += 1; } else if (SIXLOWPAN_IS_MCASTADDR_COMPRESSABLE32(ipv6->destipaddr)) { FAR uint8_t *iptr = (FAR uint8_t *)ipv6->destipaddr; - iphc1 |= SIXLOWPAN_IPHC_DAM_16; + iphc1 |= SIXLOWPAN_IPHC_MDAM_32; /* Second byte + the last three */ @@ -856,7 +885,7 @@ int sixlowpan_compresshdr_hc06(FAR struct radio_driver_s *radio, { FAR uint8_t *iptr = (FAR uint8_t *)ipv6->destipaddr; - iphc1 |= SIXLOWPAN_IPHC_DAM_64; + iphc1 |= SIXLOWPAN_IPHC_MDAM_48; /* Second byte + the last five */ @@ -866,7 +895,7 @@ int sixlowpan_compresshdr_hc06(FAR struct radio_driver_s *radio, } else { - iphc1 |= SIXLOWPAN_IPHC_DAM_128; + iphc1 |= SIXLOWPAN_IPHC_MDAM_128; /* Full address */ @@ -1233,9 +1262,9 @@ void sixlowpan_uncompresshdr_hc06(FAR struct radio_driver_s *radio, /* Non-address context based multicast compression * * DAM 00: 128 bits - * DAM 01: 48 bits FFXX::00XX:XXXX:XXXX - * DAM 10: 32 bits FFXX::00XX:XXXX - * DAM 11: 8 bits FF02::00XX + * DAM 01: 48 bits ffxx::00xx:xxxx:xxxx + * DAM 10: 32 bits ffxx::00xx:xxxx + * DAM 11: 8 bits ff02::00xx */ uint8_t prefix[] = { 0xff, 0x02 };