diff --git a/include/nuttx/net/sixlowpan.h b/include/nuttx/net/sixlowpan.h index dfc8a13a76..a98cfa457c 100644 --- a/include/nuttx/net/sixlowpan.h +++ b/include/nuttx/net/sixlowpan.h @@ -63,6 +63,83 @@ * Pre-processor Definitions ****************************************************************************/ +/* Frame format definitions *************************************************/ +/* Fragment header. + * + * The fragment header is used when the payload is too large to fit in a + * single IEEE 802.15.4 frame. The fragment header contains three fields: + * Datagram size, datagram tag and datagram offset. + * + * 1. Datagram size describes the total (un-fragmented) payload. + * 2. Datagram tag identifies the set of fragments and is used to match + * fragments of the same payload. + * 3. Datagram offset identifies the fragment’s offset within the un- + * fragmented payload. + * + * The fragment header length is 4 bytes for the first header and 5 + * bytes for all subsequent headers. + */ + +#define RIME_FRAG_DISPATCH_SIZE 0 /* 16 bit */ +#define RIME_FRAG_TAG 2 /* 16 bit */ +#define RIME_FRAG_OFFSET 4 /* 8 bit */ + +/* Define the Rime buffer as a byte array */ + +#define RIME_HC1_DISPATCH 0 /* 8 bit */ +#define RIME_HC1_ENCODING 1 /* 8 bit */ +#define RIME_HC1_TTL 2 /* 8 bit */ + +#define RIME_HC1_HC_UDP_DISPATCH 0 /* 8 bit */ +#define RIME_HC1_HC_UDP_HC1_ENCODING 1 /* 8 bit */ +#define RIME_HC1_HC_UDP_UDP_ENCODING 2 /* 8 bit */ +#define RIME_HC1_HC_UDP_TTL 3 /* 8 bit */ +#define RIME_HC1_HC_UDP_PORTS 4 /* 8 bit */ +#define RIME_HC1_HC_UDP_CHKSUM 5 /* 16 bit */ + +/* These are some definitions of element values used in the FCF. See the + * IEEE802.15.4 spec for details. + */ + +#define FRAME802154_FRAMETYPE_SHIFT (0) /* Bits 0-2: Frame type */ +#define FRAME802154_FRAMETYPE_MASK (7 << FRAME802154_FRAMETYPE_SHIFT) +#define FRAME802154_SECENABLED_SHIFT (3) /* Bit 3: Security enabled */ +#define FRAME802154_FRAMEPENDING_SHIFT (4) /* Bit 4: Frame pending */ +#define FRAME802154_ACKREQUEST_SHIFT (5) /* Bit 5: ACK request */ +#define FRAME802154_PANIDCOMP_SHIFT (6) /* Bit 6: PANID compression */ + /* Bits 7-9: Reserved */ +#define FRAME802154_DSTADDR_SHIFT (2) /* Bits 10-11: Dest address mode */ +#define FRAME802154_DSTADDR_MASK (3 << FRAME802154_DSTADDR_SHIFT) +#define FRAME802154_VERSION_SHIFT (4) /* Bit 12-13: Frame version */ +#define FRAME802154_VERSION_MASK (3 << FRAME802154_VERSION_SHIFT) +#define FRAME802154_SRCADDR_SHIFT (6) /* Bits 14-15: Source address mode */ +#define FRAME802154_SRCADDR_MASK (3 << FRAME802154_SRCADDR_SHIFT) + +/* Unshifted values for use in struct frame802154_fcf_s */ + +#define FRAME802154_BEACONFRAME (0) +#define FRAME802154_DATAFRAME (1) +#define FRAME802154_ACKFRAME (2) +#define FRAME802154_CMDFRAME (3) + +#define FRAME802154_BEACONREQ (7) + +#define FRAME802154_IEEERESERVED (0) +#define FRAME802154_NOADDR (0) /* Only valid for ACK or Beacon frames */ +#define FRAME802154_SHORTADDRMODE (2) +#define FRAME802154_LONGADDRMODE (3) + +#define FRAME802154_NOBEACONS 0x0f + +#define FRAME802154_BROADCASTADDR 0xffff +#define FRAME802154_BROADCASTPANDID 0xffff + +#define FRAME802154_IEEE802154_2003 (0) +#define FRAME802154_IEEE802154_2006 (1) + +#define FRAME802154_SECURITY_LEVEL_NONE (0) +#define FRAME802154_SECURITY_LEVEL_128 (3) + /* Min and Max compressible UDP ports - HC06 */ #define SIXLOWPAN_UDP_4_BIT_PORT_MIN 0xf0b0 @@ -171,9 +248,71 @@ #define SIXLOWPAN_MAC_STDFRAME 127 -/* Frame buffer helper macros. +/* Address compressibility test macros **************************************/ + +/* 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 * - * The IEEE802.15.4 MAC driver structures includes a list of IOB + * 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:XXXX. + * + * NOTE: we currently assume 64-bits prefixes. Big-endian, network order is + * assumed. + */ + +#define SIXLOWPAN_IS_IID_16BIT_COMPRESSABLE(a) \ + ((((a)[4]) == 0x0000) && (((a)[5]) == HTONS(0x00ff)) && \ + (((a)[6]) == 0xfe00)) + +/* Check whether the 9-bit group-id of the compressed multicast address is + * known. It is true if the 9-bit group is the all nodes or all routers + * group. Parameter 'a' is typed uint8_t * + */ + +#define SIXLOWPAN_IS_MCASTADDR_DECOMPRESSABLE(a) \ + (((*a & 0x01) == 0) && \ + ((*(a + 1) == 0x01) || (*(a + 1) == 0x02))) + +/* Check whether the 112-bit group-id of the multicast address is mappable + * to a 9-bit group-id. It is true if the group is the all nodes or all + * routers group: + * + * XXXX:0000:0000:0000:0000:0000:0000:0001 All nodes address + * XXXX:0000:0000:0000:0000:0000:0000:0002 All routers address + */ + +#define SIXLOWPAN_IS_MCASTADDR_COMPRESSABLE(a) \ + ((a)[1] == 0 && (a)[2] == 0 && (a)[3] == 0 && \ + (a)[4] == 0 && (a)[5] == 0 && (a)[6] == 0 && \ + ((a)[7] == HTONS(0x0001) || (a)[7] == HTONS(0x0002))) + +/* FFXX:0000:0000:0000:0000:00XX:XXXX:XXXX */ + +#define SIXLOWPAN_IS_MCASTADDR_COMPRESSABLE48(a) \ + ((a)[1] == 0 && (a)[2] == 0 && (a)[3] == 0 && \ + (a)[4] == 0 && (((a)[5] & HTONS(0xff00)) == 0)) + +/* FFXX:0000:0000:0000:0000:0000:00XX:XXXX */ + +#define SIXLOWPAN_IS_MCASTADDR_COMPRESSABLE32(a) \ + ((a)[1] == 0 && (a)[2] == 0 && (a)[3] == 0 && \ + (a)[4] == 0 && (a)[5] == 0 && ((a)[6] & HTONS(0xff00)) == 0) + +/* FF02:0000:0000:0000:0000:0000:0000:00XX */ + +#define SIXLOWPAN_IS_MCASTADDR_COMPRESSABLE8(a) \ + ((((a)[0] & HTONS(0x00ff)) == HTONS(0x0002)) && \ + (a)[1] == 0 && (a)[2] == 0 && (a)[3] == 0 && \ + (a)[4] == 0 && (a)[5] == 0 && (a)[6] == 0 && \ + (((a)[7] & HTONS(0xff00)) == 0x0000)) + +/* Frame buffer helper macros ***********************************************/ +/* The IEEE802.15.4 MAC driver structures includes a list of IOB * structures, i_framelist, containing frames to be sent by the driver or * that were received by the driver. The IOB structure is defined in * include/nuttx/net/iob.h. The length of data in the IOB is provided by diff --git a/net/sixlowpan/README.txt b/net/sixlowpan/README.txt index b9968c318b..643735dd86 100644 --- a/net/sixlowpan/README.txt +++ b/net/sixlowpan/README.txt @@ -1,4 +1,5 @@ -Optimal 6loWPAN Configuration: +Optimal 6loWPAN Configuration +----------------------------- 1. Link local IP addresses: @@ -27,4 +28,46 @@ Optimal 6loWPAN Configuration: 5. IOBs: Must be big enough to hold one IEEE802.15.4 frame (CONFIG_NET_6LOWPAN_FRAMELEN, typically 127). There must be enough IOBs to decompose the largest IPv6 - packet (CONFIG_NET_6LOWPAN_MTU, default 1294, plus per frame overhead). \ No newline at end of file + packet (CONFIG_NET_6LOWPAN_MTU, default 1294, plus per frame overhead). + +Fragmentation Headers +--------------------- +A fragment header is placed at the beginning of the outgoing packet when the +payload is too large to fit in a single IEEE 802.15.4 frame. The fragment +header contains three fields: Datagram size, datagram tag and datagram +offset. + +1. Datagram size describes the total (un-fragmented) payload. +2. Datagram tag identifies the set of fragments and is used to match + fragments of the same payload. +3. Datagram offset identifies the fragment’s offset within the un- + fragmented payload (in units of 8 bytes). + +The length of the fragment header length is four bytes for the first header +(FRAG1) and five bytes for all subsequent headers (FRAGN). For example, +this is a HC1 compressed first frame of a packet + + c50e 000b ### 4-byte FRAG1 header + 01 08 01 0000 3412 ### 7-byte FCF header + 42 ### SIXLOWPAN_DISPATCH_HC1 + fb ### RIME_HC1_HC_UDP_HC1_ENCODING + e0 ### RIME_HC1_HC_UDP_UDP_ENCODING + 00 ### RIME_HC1_HC_UDP_TTL + 10 ### RIME_HC1_HC_UDP_PORTS + 0000 ### RIME_HC1_HC_UDP_CHKSUM + 4f4e452064617920 48656e6e792d7065 6e6e792077617320 7069636b696e6720 ### 80 byte payload + 757020636f726e20 696e207468652063 6f726e7961726420 7768656e2d2d7768 + 61636b212d2d736f 6d657468696e6720 g + +This is the second frame of the same transfer: + + e50e 000b 0a ### 5 byte FRAGN header + 01 08 01 0000 3412 ### 7-byte FCF header + 6869742068657220 75706f6e20746865 20686561642e2027 476f6f646e657373 ### 88 byte payload + 2067726163696f75 73206d6521272073 6169642048656e6e 792d70656e6e793b + 202774686520736b 79277320612d676f 696e6720746f2066 + +The payload length is encoded in the LS 11-bits of the first 16-bit value: +In this example the payload size is 0x050e or 1,294. The tag is 0x000b. In +the second frame, the fifth byte contains the offset 0x0a which is 10 << 3 = +80 bytes, the size of the payload on the first packet. diff --git a/net/sixlowpan/sixlowpan_input.c b/net/sixlowpan/sixlowpan_input.c index e491394c7b..b19fa8ffba 100644 --- a/net/sixlowpan/sixlowpan_input.c +++ b/net/sixlowpan/sixlowpan_input.c @@ -190,6 +190,91 @@ int sixlowpan_recv_hdrlen(FAR const uint8_t *fptr) return 0; } +/**************************************************************************** + * Name: sixlowpan_compress_ipv6hdr + * + * Description: + * IPv6 dispatch "compression" function. Packets "Compression" when only + * IPv6 dispatch is used + * + * There is no compression in this case, all fields are sent + * inline. We just add the IPv6 dispatch byte before the packet. + * + * 0 1 2 3 + * 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 + * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ + * | IPv6 Dsp | IPv6 header and payload ... + * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ + * + * Input Parameters: + * ieee - The IEEE802.15.4 MAC network driver interface. + * fptr - Pointer to the beginning of the frame under construction + * + * Returned Value: + * None + * + ****************************************************************************/ + +static void sixlowpan_uncompress_ipv6hdr(FAR struct ieee802154_driver_s *ieee, + FAR uint8_t *fptr) +{ + FAR struct ipv6_hdr_s *ipv6 = IPv6BUF(&ieee->i_dev); + uint16_t protosize; + + /* Put uncompressed IPv6 header in d_buf. */ + + g_frame_hdrlen += SIXLOWPAN_IPV6_HDR_LEN; + memcpy(ipv6, fptr + g_frame_hdrlen, IPv6_HDRLEN); + + /* Update g_uncomp_hdrlen and g_frame_hdrlen. */ + + g_frame_hdrlen += IPv6_HDRLEN; + g_uncomp_hdrlen += IPv6_HDRLEN; + + /* Copy the following protocol header, */ + + switch (ipv6->proto) + { +#ifdef CONFIG_NET_TCP + case IP_PROTO_TCP: + { + FAR struct tcp_hdr_s *tcp = &((FAR struct ipv6tcp_hdr_s *)ipv6)->tcp; + + /* The TCP header length is encoded in the top 4 bits of the + * tcpoffset field (in units of 32-bit words). + */ + + protosize = ((uint16_t)tcp->tcpoffset >> 4) << 2; + } + break; +#endif + +#ifdef CONFIG_NET_UDP + case IP_PROTO_UDP: + protosize = sizeof(struct udp_hdr_s); + break; +#endif + +#ifdef CONFIG_NET_ICMPv6 + case IP_PROTO_ICMP6: + protosize = sizeof(struct icmpv6_hdr_s); + break; +#endif + + default: + nwarn("WARNING: Unrecognized proto: %u\n", ipv6->proto); + return; + } + + /* Copy the protocol header. */ + + memcpy((FAR uint8_t *)ipv6 + g_uncomp_hdrlen, fptr + g_frame_hdrlen, + protosize); + + g_frame_hdrlen += protosize; + g_uncomp_hdrlen += protosize; +} + /**************************************************************************** * Public Functions ****************************************************************************/ @@ -437,9 +522,6 @@ static int sixlowpan_frame_process(FAR struct ieee802154_driver_s *ieee, if ((hc1[RIME_HC1_DISPATCH] & SIXLOWPAN_DISPATCH_IPHC_MASK) == SIXLOWPAN_DISPATCH_IPHC) { ninfo("IPHC Dispatch\n"); - - /* Payload starts after the IEEE802.15.4 header(s) */ - sixlowpan_uncompresshdr_hc06(ieee, fragsize, iob, fptr); } else @@ -449,29 +531,15 @@ static int sixlowpan_frame_process(FAR struct ieee802154_driver_s *ieee, if (hc1[RIME_HC1_DISPATCH] == SIXLOWPAN_DISPATCH_HC1) { ninfo("HC1 Dispatch\n"); - - /* Payload starts after the IEEE802.15.4 header(s) */ - - sixlowpan_uncompresshdr_hc1(ieee, fragsize, iob, fptr); + sixlowpan_uncompresshdr_hc1(ieee, fragsize, iob, fptr); } else #endif /* CONFIG_NET_6LOWPAN_COMPRESSION_HC1 */ if (hc1[RIME_HC1_DISPATCH] == SIXLOWPAN_DISPATCH_IPV6) { - FAR struct ipv6_hdr_s *ipv6 = IPv6BUF(&ieee->i_dev); - ninfo("IPv6 Dispatch\n"); - g_frame_hdrlen += SIXLOWPAN_IPV6_HDR_LEN; - - /* Put uncompressed IP header in d_buf. */ - - memcpy(ipv6, fptr + g_frame_hdrlen, IPv6_HDRLEN); - - /* Update g_uncomp_hdrlen and g_frame_hdrlen. */ - - g_frame_hdrlen += IPv6_HDRLEN; - g_uncomp_hdrlen += IPv6_HDRLEN; + sixlowpan_uncompress_ipv6hdr(ieee, fptr); } else { diff --git a/net/sixlowpan/sixlowpan_internal.h b/net/sixlowpan/sixlowpan_internal.h index 0f04a068b2..5445686373 100644 --- a/net/sixlowpan/sixlowpan_internal.h +++ b/net/sixlowpan/sixlowpan_internal.h @@ -84,82 +84,6 @@ /* Pointers in the Rime buffer */ -/* Fragment header. - * - * The fragment header is used when the payload is too large to fit in a - * single IEEE 802.15.4 frame. The fragment header contains three fields: - * Datagram size, datagram tag and datagram offset. - * - * 1. Datagram size describes the total (un-fragmented) payload. - * 2. Datagram tag identifies the set of fragments and is used to match - * fragments of the same payload. - * 3. Datagram offset identifies the fragment’s offset within the un- - * fragmented payload. - * - * The fragment header length is 4 bytes for the first header and 5 - * bytes for all subsequent headers. - */ - -#define RIME_FRAG_DISPATCH_SIZE 0 /* 16 bit */ -#define RIME_FRAG_TAG 2 /* 16 bit */ -#define RIME_FRAG_OFFSET 4 /* 8 bit */ - -/* Define the Rime buffer as a byte array */ - -#define RIME_HC1_DISPATCH 0 /* 8 bit */ -#define RIME_HC1_ENCODING 1 /* 8 bit */ -#define RIME_HC1_TTL 2 /* 8 bit */ - -#define RIME_HC1_HC_UDP_DISPATCH 0 /* 8 bit */ -#define RIME_HC1_HC_UDP_HC1_ENCODING 1 /* 8 bit */ -#define RIME_HC1_HC_UDP_UDP_ENCODING 2 /* 8 bit */ -#define RIME_HC1_HC_UDP_TTL 3 /* 8 bit */ -#define RIME_HC1_HC_UDP_PORTS 4 /* 8 bit */ -#define RIME_HC1_HC_UDP_CHKSUM 5 /* 16 bit */ - -/* These are some definitions of element values used in the FCF. See the - * IEEE802.15.4 spec for details. - */ - -#define FRAME802154_FRAMETYPE_SHIFT (0) /* Bits 0-2: Frame type */ -#define FRAME802154_FRAMETYPE_MASK (7 << FRAME802154_FRAMETYPE_SHIFT) -#define FRAME802154_SECENABLED_SHIFT (3) /* Bit 3: Security enabled */ -#define FRAME802154_FRAMEPENDING_SHIFT (4) /* Bit 4: Frame pending */ -#define FRAME802154_ACKREQUEST_SHIFT (5) /* Bit 5: ACK request */ -#define FRAME802154_PANIDCOMP_SHIFT (6) /* Bit 6: PANID compression */ - /* Bits 7-9: Reserved */ -#define FRAME802154_DSTADDR_SHIFT (2) /* Bits 10-11: Dest address mode */ -#define FRAME802154_DSTADDR_MASK (3 << FRAME802154_DSTADDR_SHIFT) -#define FRAME802154_VERSION_SHIFT (4) /* Bit 12-13: Frame version */ -#define FRAME802154_VERSION_MASK (3 << FRAME802154_VERSION_SHIFT) -#define FRAME802154_SRCADDR_SHIFT (6) /* Bits 14-15: Source address mode */ -#define FRAME802154_SRCADDR_MASK (3 << FRAME802154_SRCADDR_SHIFT) - -/* Unshifted values for use in struct frame802154_fcf_s */ - -#define FRAME802154_BEACONFRAME (0) -#define FRAME802154_DATAFRAME (1) -#define FRAME802154_ACKFRAME (2) -#define FRAME802154_CMDFRAME (3) - -#define FRAME802154_BEACONREQ (7) - -#define FRAME802154_IEEERESERVED (0) -#define FRAME802154_NOADDR (0) /* Only valid for ACK or Beacon frames */ -#define FRAME802154_SHORTADDRMODE (2) -#define FRAME802154_LONGADDRMODE (3) - -#define FRAME802154_NOBEACONS 0x0f - -#define FRAME802154_BROADCASTADDR 0xffff -#define FRAME802154_BROADCASTPANDID 0xffff - -#define FRAME802154_IEEE802154_2003 (0) -#define FRAME802154_IEEE802154_2006 (1) - -#define FRAME802154_SECURITY_LEVEL_NONE (0) -#define FRAME802154_SECURITY_LEVEL_128 (3) - /* Packet buffer Definitions */ #define PACKETBUF_ATTR_PACKET_TYPE_DATA 0 @@ -215,69 +139,6 @@ #define PACKETBUF_NUM_ADDRS 4 -/* Address compressibility test macros **************************************/ - -/* 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 - * - * 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:XXXX. - * - * NOTE: we currently assume 64-bits prefixes. Big-endian, network order is - * assumed. - */ - -#define SIXLOWPAN_IS_IID_16BIT_COMPRESSABLE(a) \ - ((((a)[4]) == 0x0000) && (((a)[5]) == HTONS(0x00ff)) && \ - (((a)[6]) == 0xfe00)) - -/* Check whether the 9-bit group-id of the compressed multicast address is - * known. It is true if the 9-bit group is the all nodes or all routers - * group. Parameter 'a' is typed uint8_t * - */ - -#define SIXLOWPAN_IS_MCASTADDR_DECOMPRESSABLE(a) \ - (((*a & 0x01) == 0) && \ - ((*(a + 1) == 0x01) || (*(a + 1) == 0x02))) - -/* Check whether the 112-bit group-id of the multicast address is mappable - * to a 9-bit group-id. It is true if the group is the all nodes or all - * routers group: - * - * XXXX:0000:0000:0000:0000:0000:0000:0001 All nodes address - * XXXX:0000:0000:0000:0000:0000:0000:0002 All routers address - */ - -#define SIXLOWPAN_IS_MCASTADDR_COMPRESSABLE(a) \ - ((a)[1] == 0 && (a)[2] == 0 && (a)[3] == 0 && \ - (a)[4] == 0 && (a)[5] == 0 && (a)[6] == 0 && \ - ((a)[7] == HTONS(0x0001) || (a)[7] == HTONS(0x0002))) - -/* FFXX:0000:0000:0000:0000:00XX:XXXX:XXXX */ - -#define SIXLOWPAN_IS_MCASTADDR_COMPRESSABLE48(a) \ - ((a)[1] == 0 && (a)[2] == 0 && (a)[3] == 0 && \ - (a)[4] == 0 && (((a)[5] & HTONS(0xff00)) == 0)) - -/* FFXX:0000:0000:0000:0000:0000:00XX:XXXX */ - -#define SIXLOWPAN_IS_MCASTADDR_COMPRESSABLE32(a) \ - ((a)[1] == 0 && (a)[2] == 0 && (a)[3] == 0 && \ - (a)[4] == 0 && (a)[5] == 0 && ((a)[6] & HTONS(0xff00)) == 0) - -/* FF02:0000:0000:0000:0000:0000:0000:00XX */ - -#define SIXLOWPAN_IS_MCASTADDR_COMPRESSABLE8(a) \ - ((((a)[0] & HTONS(0x00ff)) == HTONS(0x0002)) && \ - (a)[1] == 0 && (a)[2] == 0 && (a)[3] == 0 && \ - (a)[4] == 0 && (a)[5] == 0 && (a)[6] == 0 && \ - (((a)[7] & HTONS(0xff00)) == 0x0000)) - /* General helper macros ****************************************************/ #define GETINT16(ptr,index) \