6loWPAN: Fix breakage in IPv6 dispatch caused by fixes to HC1 dispatch; Move some standard definitions from internal header file to include/nuttx/net/sixlowpan.h. Update a README.

This commit is contained in:
Gregory Nutt 2017-04-08 10:18:44 -06:00
parent 143b8f9591
commit 3f51180cca
4 changed files with 273 additions and 162 deletions

View File

@ -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 fragments 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 <PREFIX>::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 <PREFIX>::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

View File

@ -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).
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 fragments 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.

View File

@ -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
{

View File

@ -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 fragments 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 <PREFIX>::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 <PREFIX>::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) \