diff --git a/TODO b/TODO index b85d4803354..ed6d93238b7 100644 --- a/TODO +++ b/TODO @@ -19,7 +19,7 @@ nuttx/: (8) Kernel/Protected Build (3) C++ Support (6) Binary loaders (binfmt/) - (15) Network (net/, drivers/net) + (14) Network (net/, drivers/net) (4) USB (drivers/usbdev, drivers/usbhost) (0) Other drivers (drivers/) (12) Libraries (libc/, libm/) @@ -1006,8 +1006,8 @@ o Network (net/, drivers/net) however. Others support the address filtering interfaces but have never been verifed: - C5471, LM3X, ez80, DM0x90 NIC, PIC: Do not support address - filteringing. + C5471, LM3S, ez80, DM0x90 NIC, PIC: Do not support address + filtering. Kinetis, LPC17xx, LPC43xx: Untested address filter support Status: Open @@ -1089,15 +1089,6 @@ o Network (net/, drivers/net) Status: Open Priority: Low - Title: REMOVE CONFIG_NET_MULTIBUFFER - Description: The CONFIG_NET_MULTIBUFFER controls some details in the layout - of the network device structure. This is really a unnecessary - complexity and should be removed. The cost for those network - drivers that currently do not support CONFIG_NET_MULTIBUFFER - is the size of one pointer. - Status: Open - Priority: Low - Title: ETHERNET WITH MULTIPLE LPWORK THREADS Description: Recently, Ethernet drivers were modified to support multiple work queue structures. The question was raised: "My only diff --git a/arch/arm/src/stm32/Kconfig b/arch/arm/src/stm32/Kconfig index 86b5b714351..1aa55388f7e 100644 --- a/arch/arm/src/stm32/Kconfig +++ b/arch/arm/src/stm32/Kconfig @@ -1625,6 +1625,7 @@ config STM32_STM32F429 select STM32_HAVE_UART7 select STM32_HAVE_UART8 select STM32_HAVE_TIM1 + select STM32_HAVE_TIM5 select STM32_HAVE_TIM6 select STM32_HAVE_TIM7 select STM32_HAVE_TIM8 diff --git a/include/nuttx/net/sixlowpan.h b/include/nuttx/net/sixlowpan.h index e2f3eaf1f7d..eb3a4580ebc 100644 --- a/include/nuttx/net/sixlowpan.h +++ b/include/nuttx/net/sixlowpan.h @@ -160,14 +160,22 @@ /* 6lowpan dispatches */ -#define SIXLOWPAN_DISPATCH_IPV6 0x41 /* 01000001 = 65 */ -#define SIXLOWPAN_DISPATCH_HC1 0x42 /* 01000010 = 66 */ +#define SIXLOWPAN_DISPATCH_NALP 0x00 /* 00xxxxxx Not a LoWPAN packet */ +#define SIXLOWPAN_DISPATCH_NALP_MASK 0xc0 /* 11000000 */ -#define SIXLOWPAN_DISPATCH_IPHC 0x60 /* 011xxxxx */ +#define SIXLOWPAN_DISPATCH_IPV6 0x41 /* 01000001 Uncompressed IPv6 addresses */ +#define SIXLOWPAN_DISPATCH_HC1 0x42 /* 01000010 HC1 Compressed IPv6 header */ +#define SIXLOWPAN_DISPATCH_BC0 0x50 /* 01010000 BC0 Broadcast header */ +#define SIXLOWPAN_DISPATCH_ESC 0x7f /* 01111111 Additional Dispatch octet follows */ + +#define SIXLOWPAN_DISPATCH_IPHC 0x60 /* 011xxxxx IP Header Compression (IPHC)*/ #define SIXLOWPAN_DISPATCH_IPHC_MASK 0xe0 /* 11100000 */ -#define SIXLOWPAN_DISPATCH_FRAG1 0xc0 /* 11000xxx */ -#define SIXLOWPAN_DISPATCH_FRAGN 0xe0 /* 11100xxx */ +#define SIXLOWPAN_DISPATCH_MESH 0x80 /* 10xxxxxx Mesh routing header */ +#define SIXLOWPAN_DISPATCH_MESH_MASK 0xc0 /* 11000000 */ + +#define SIXLOWPAN_DISPATCH_FRAG1 0xc0 /* 11000xxx Fragmentation header (first) */ +#define SIXLOWPAN_DISPATCH_FRAGN 0xe0 /* 11100xxx Fragmentation header (subsequent) */ #define SIXLOWPAN_DISPATCH_FRAG_MASK 0xf8 /* 11111000 */ /* HC1 encoding */ diff --git a/net/sixlowpan/README.txt b/net/sixlowpan/README.txt index 643735dd869..e325533474e 100644 --- a/net/sixlowpan/README.txt +++ b/net/sixlowpan/README.txt @@ -32,10 +32,10 @@ Optimal 6loWPAN Configuration 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. +A fragment header is placed at the beginning of the outgoing packet just +after the FCF 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 @@ -47,25 +47,36 @@ 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 + 01 08 01 0000 3412 ### 7-byte FCF header + c50e 000b ### 4-byte FRAG1 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 + + 80 byte Payload follows: + 4f4e452064617920 48656e6e792d7065 6e6e792077617320 7069636b696e6720 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 + 01 08 01 0000 3412 ### 7-byte FCF header + e50e 000b 0a ### 5 byte FRAGN 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 + + 80 byte Payload follows: + 6869742068657220 75706f6e20746865 20686561642e2027 476f6f646e657373 2067726163696f75 73206d6521272073 6169642048656e6e 792d70656e6e793b - 202774686520736b 79277320612d676f 696e6720746f2066 + 202774686520736b 79277320612d676f + 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 diff --git a/net/sixlowpan/sixlowpan_framelist.c b/net/sixlowpan/sixlowpan_framelist.c index d8b751e8a75..23969c09f33 100644 --- a/net/sixlowpan/sixlowpan_framelist.c +++ b/net/sixlowpan/sixlowpan_framelist.c @@ -330,6 +330,8 @@ int sixlowpan_queue_frames(FAR struct ieee802154_driver_s *ieee, FAR struct iob_s *qtail; FAR uint8_t *frame1; + FAR uint8_t *fragptr; + uint16_t frag1_hdrlen; int verify; /* The outbound IPv6 packet is too large to fit into a single 15.4 @@ -352,7 +354,9 @@ int sixlowpan_queue_frames(FAR struct ieee802154_driver_s *ieee, * beginning of the frame. */ - memmove(fptr + SIXLOWPAN_FRAG1_HDR_LEN, fptr, g_frame_hdrlen); + fragptr = fptr + framer_hdrlen; + memmove(fragptr + SIXLOWPAN_FRAG1_HDR_LEN, fragptr, + g_frame_hdrlen - framer_hdrlen); /* Setup up the fragment header. * @@ -370,9 +374,9 @@ int sixlowpan_queue_frames(FAR struct ieee802154_driver_s *ieee, */ pktlen = buflen + g_uncomp_hdrlen; - PUTINT16(fptr, RIME_FRAG_DISPATCH_SIZE, + PUTINT16(fragptr, RIME_FRAG_DISPATCH_SIZE, ((SIXLOWPAN_DISPATCH_FRAG1 << 8) | pktlen)); - PUTINT16(fptr, RIME_FRAG_TAG, ieee->i_dgramtag); + PUTINT16(fragptr, RIME_FRAG_TAG, ieee->i_dgramtag); g_frame_hdrlen += SIXLOWPAN_FRAG1_HDR_LEN; @@ -385,8 +389,8 @@ int sixlowpan_queue_frames(FAR struct ieee802154_driver_s *ieee, /* Set outlen to what we already sent from the IP payload */ - iob->io_len = paysize + g_frame_hdrlen; - outlen = paysize; + iob->io_len = paysize + g_frame_hdrlen; + outlen = paysize; ninfo("First fragment: length %d, tag %d\n", paysize, ieee->i_dgramtag); @@ -404,7 +408,9 @@ int sixlowpan_queue_frames(FAR struct ieee802154_driver_s *ieee, /* Create following fragments */ - frame1 = iob->io_data; + frame1 = iob->io_data; + frag1_hdrlen = g_frame_hdrlen; + while (outlen < buflen) { uint16_t fragn_hdrlen; @@ -424,21 +430,27 @@ int sixlowpan_queue_frames(FAR struct ieee802154_driver_s *ieee, iob->io_pktlen = 0; fptr = iob->io_data; - /* Copy the frame header from first frame, into the correct - * location after the FRAGN header. + /* Copy the frame header at the beginning of the frame. */ + + memcpy(fptr, frame1, framer_hdrlen); + + /* Move HC1/HC06/IPv6 header the frame header from first + * frame, into the correct location after the FRAGN header + * of subsequent frames. */ - memmove(fptr + SIXLOWPAN_FRAGN_HDR_LEN, - frame1 + SIXLOWPAN_FRAG1_HDR_LEN, - framer_hdrlen); - fragn_hdrlen = framer_hdrlen; + fragptr = fptr + framer_hdrlen; + memcpy(fragptr + SIXLOWPAN_FRAGN_HDR_LEN, + frame1 + framer_hdrlen + SIXLOWPAN_FRAG1_HDR_LEN, + frag1_hdrlen - framer_hdrlen); + fragn_hdrlen = frag1_hdrlen - SIXLOWPAN_FRAG1_HDR_LEN; - /* Setup up the FRAGN header at the beginning of the frame */ + /* Setup up the FRAGN header after the frame header. */ - PUTINT16(fptr, RIME_FRAG_DISPATCH_SIZE, + PUTINT16(fragptr, RIME_FRAG_DISPATCH_SIZE, ((SIXLOWPAN_DISPATCH_FRAGN << 8) | pktlen)); - PUTINT16(fptr, RIME_FRAG_TAG, ieee->i_dgramtag); - fptr[RIME_FRAG_OFFSET] = outlen >> 3; + PUTINT16(fragptr, RIME_FRAG_TAG, ieee->i_dgramtag); + fragptr[RIME_FRAG_OFFSET] = outlen >> 3; fragn_hdrlen += SIXLOWPAN_FRAGN_HDR_LEN; diff --git a/net/sixlowpan/sixlowpan_hc06.c b/net/sixlowpan/sixlowpan_hc06.c index d449f829360..8a4999579e6 100644 --- a/net/sixlowpan/sixlowpan_hc06.c +++ b/net/sixlowpan/sixlowpan_hc06.c @@ -68,13 +68,10 @@ #ifdef CONFIG_NET_6LOWPAN_COMPRESSION_HC06 - /**************************************************************************** * Pre-processor Definitions ****************************************************************************/ -#define IPv6BUF(ieee) \ - ((FAR struct ipv6_hdr_s *)((ieee)->i_dev.d_buf)) #define UDPIPv6BUF(ieee) \ ((FAR struct udp_hdr_s *)&((ieee)->i_dev.d_buf[IPv6_HDRLEN])) @@ -223,7 +220,7 @@ static FAR struct sixlowpan_addrcontext_s * } /**************************************************************************** - * Name: uncompress_addr + * Name: compress_addr_64 * * Description: * Uncompress addresses based on a prefix and a postfix with zeroes in @@ -835,23 +832,23 @@ void sixlowpan_compresshdr_hc06(FAR struct ieee802154_driver_s *ieee, * appropriate values * * Input Parmeters: - * ieee - A reference to the IEE802.15.4 network device state * 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(FAR struct ieee802154_driver_s *ieee, - uint16_t iplen, FAR struct iob_s *iob, - FAR uint8_t *fptr) +void sixlowpan_uncompresshdr_hc06(uint16_t iplen, FAR struct iob_s *iob, + FAR uint8_t *fptr, FAR uint8_t *bptr) { - FAR struct ipv6_hdr_s *ipv6 = IPv6BUF(ieee); + FAR struct ipv6_hdr_s *ipv6 = (FAR struct ipv6_hdr_s *)bptr; FAR uint8_t *iphc; uint8_t iphc0; uint8_t iphc1; @@ -1019,7 +1016,7 @@ void sixlowpan_uncompresshdr_hc06(FAR struct ieee802154_driver_s *ieee, * * DAM 00: 128 bits * DAM 01: 48 bits FFXX::00XX:XXXX:XXXX - * DAM 0: 32 bits FFXX::00XX:XXXX + * DAM 10: 32 bits FFXX::00XX:XXXX * DAM 11: 8 bits FF02::00XX */ @@ -1049,7 +1046,7 @@ void sixlowpan_uncompresshdr_hc06(FAR struct ieee802154_driver_s *ieee, if (addrcontext == NULL) { - ninfo("ERROR: Address context not found\n"); + nerr("ERROR: Address context not found\n"); return; } @@ -1071,7 +1068,7 @@ void sixlowpan_uncompresshdr_hc06(FAR struct ieee802154_driver_s *ieee, if ((iphc0 & SIXLOWPAN_IPHC_NH) != 0) { - FAR struct udp_hdr_s *udp = UDPIPv6BUF(ieee); + FAR struct udp_hdr_s *udp = (FAR struct udp_hdr_s *)(bptr + IPv6_HDRLEN); /* The next header is compressed, NHC is following */ @@ -1195,7 +1192,7 @@ void sixlowpan_uncompresshdr_hc06(FAR struct ieee802154_driver_s *ieee, if (ipv6->proto == IP_PROTO_UDP) { - FAR struct udp_hdr_s *udp = UDPIPv6BUF(ieee); + FAR struct udp_hdr_s *udp = (FAR struct udp_hdr_s *)(bptr + IPv6_HDRLEN); memcpy(&udp->udplen, &ipv6->len[0], 2); } } diff --git a/net/sixlowpan/sixlowpan_hc1.c b/net/sixlowpan/sixlowpan_hc1.c index 9f657a12dc6..313fc388ab3 100644 --- a/net/sixlowpan/sixlowpan_hc1.c +++ b/net/sixlowpan/sixlowpan_hc1.c @@ -57,15 +57,6 @@ #ifdef CONFIG_NET_6LOWPAN_COMPRESSION_HC1 -/**************************************************************************** - * Pre-processor Definitions - ****************************************************************************/ - -/* Buffer access helpers */ - -#define IPv6BUF(dev) ((FAR struct ipv6_hdr_s *)((dev)->d_buf)) -#define UDPIPv6BUF(dev) ((FAR struct udp_hdr_s *)&(dev)->d_buf[IPv6_HDRLEN]) - /**************************************************************************** * Public Functions ****************************************************************************/ @@ -253,12 +244,13 @@ void sixlowpan_compresshdr_hc1(FAR struct ieee802154_driver_s *ieee, * are set to the appropriate values * * Input Parameters: - * ieee - A reference to the IEE802.15.4 network device state - * 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 1st - * fragment. - * iob - Pointer to the IOB containing the received frame. - * fptr - Pointer to frame to be uncompressed. + * 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 1st + * fragment. + * iob - Pointer to the IOB containing the received frame. + * fptr - Pointer to frame to be uncompressed. + * 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: * Zero (OK) is returned on success, on failure a negater errno value is @@ -266,11 +258,10 @@ void sixlowpan_compresshdr_hc1(FAR struct ieee802154_driver_s *ieee, * ****************************************************************************/ -int sixlowpan_uncompresshdr_hc1(FAR struct ieee802154_driver_s *ieee, - uint16_t iplen, FAR struct iob_s *iob, - FAR uint8_t *fptr) +int sixlowpan_uncompresshdr_hc1(uint16_t iplen, FAR struct iob_s *iob, + FAR uint8_t *fptr, FAR uint8_t *bptr) { - FAR struct ipv6_hdr_s *ipv6 = IPv6BUF(&ieee->i_dev); + FAR struct ipv6_hdr_s *ipv6 = (FAR struct ipv6_hdr_s *)bptr; FAR uint8_t *hc1 = fptr + g_frame_hdrlen; /* Format the IPv6 header in the device d_buf */ @@ -311,7 +302,7 @@ int sixlowpan_uncompresshdr_hc1(FAR struct ieee802154_driver_s *ieee, #if CONFIG_NET_UDP case SIXLOWPAN_HC1_NH_UDP: { - FAR struct udp_hdr_s *udp = UDPIPv6BUF(&ieee->i_dev); + FAR struct udp_hdr_s *udp = (FAR struct udp_hdr_s *)(bptr + IPv6_HDRLEN); FAR uint8_t *hcudp = fptr + g_frame_hdrlen; ipv6->proto = IP_PROTO_UDP; @@ -377,7 +368,7 @@ int sixlowpan_uncompresshdr_hc1(FAR struct ieee802154_driver_s *ieee, if (ipv6->proto == IP_PROTO_UDP) { - FAR struct udp_hdr_s *udp = UDPIPv6BUF(&ieee->i_dev); + FAR struct udp_hdr_s *udp = (FAR struct udp_hdr_s *)(bptr + IPv6_HDRLEN); memcpy(&udp->udplen, &ipv6->len[0], 2); } #endif diff --git a/net/sixlowpan/sixlowpan_input.c b/net/sixlowpan/sixlowpan_input.c index b19fa8ffba0..119dd4dfd21 100644 --- a/net/sixlowpan/sixlowpan_input.c +++ b/net/sixlowpan/sixlowpan_input.c @@ -83,11 +83,48 @@ #define NET_6LOWPAN_TIMEOUT SEC2TICK(CONFIG_NET_6LOWPAN_MAXAGE) +/* This is the size of a buffer large enough to hold the largest uncompressed + * HC06 or HC1 headers. + */ + +#ifdef CONFIG_NET_TCP +/* The basic TCP header length is TCP_HDRLEN but could include up to 16 + * additional 32-bit words of optional data. + */ + +# define UNCOMP_MAXHDR (IPv6_HDRLEN + TCP_HDRLEN + 16*sizeof(uint32_t)) + +#elif defined(CONFIG_NET_UDP) +/* The UDP header length is always 8 bytes */ + +# define UNCOMP_MAXHDR (IPv6_HDRLEN + TCP_HDRLEN) + +#elif defined(CONFIG_NET_ICMPv6) +/* The ICMPv6 header length is a mere 4 bytes */ + +# define UNCOMP_MAXHDR (IPv6_HDRLEN + ICMPv6_HDRLEN) + +#else +/* No other header type is handled. */ + +# define UNCOMP_MAXHDR IPv6_HDRLEN +#endif + /* Buffer access helpers */ #define IPv6BUF(dev) ((FAR struct ipv6_hdr_s *)((dev)->d_buf)) #define TCPBUF(dev) ((FAR struct tcp_hdr_s *)&(dev)->d_buf[IPv6_HDRLEN]) +/**************************************************************************** + * Private Data + ****************************************************************************/ + +#ifdef CONFIG_NET_6LOWPAN_FRAG +/* This big buffer could be avoided with a little more effort */ + +static uint8_t g_bitbucket[UNCOMP_MAXHDR]; +#endif + /**************************************************************************** * Private Functions ****************************************************************************/ @@ -96,7 +133,7 @@ * Name: sixlowpan_recv_hdrlen * * Description: - * Get the length of the IEEE802.15.4 header on the received frame. + * Get the length of the IEEE802.15.4 FCF header on the received frame. * * Input Parameters: * ieee - The IEEE802.15.4 MAC network driver interface. @@ -112,26 +149,12 @@ int sixlowpan_recv_hdrlen(FAR const uint8_t *fptr) { - uint16_t hdrlen = 0; + uint16_t hdrlen; uint8_t addrmode; - uint8_t tmp; - - /* Check for a fragment header preceding the IEEE802.15.4 FCF */ - - tmp = *fptr & SIXLOWPAN_DISPATCH_FRAG_MASK; - if (tmp == SIXLOWPAN_DISPATCH_FRAG1) - { - hdrlen += SIXLOWPAN_FRAG1_HDR_LEN; - } - else if (tmp == SIXLOWPAN_DISPATCH_FRAGN) - { - hdrlen += SIXLOWPAN_FRAGN_HDR_LEN; - } /* Minimum header: 2 byte FCF + 1 byte sequence number */ - fptr += hdrlen; - hdrlen += 3; + hdrlen = 3; /* Account for destination address size */ @@ -207,18 +230,18 @@ int sixlowpan_recv_hdrlen(FAR const uint8_t *fptr) * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ * * Input Parameters: - * ieee - The IEEE802.15.4 MAC network driver interface. * fptr - Pointer to the beginning of the frame under construction + * bptr - Output goes here. Normally this is a known offset into d_buf, + * may be redirected to g_bitbucket on the case of FRAGN frames. * * Returned Value: * None * ****************************************************************************/ -static void sixlowpan_uncompress_ipv6hdr(FAR struct ieee802154_driver_s *ieee, - FAR uint8_t *fptr) +static void sixlowpan_uncompress_ipv6hdr(FAR uint8_t *fptr, FAR uint8_t *bptr) { - FAR struct ipv6_hdr_s *ipv6 = IPv6BUF(&ieee->i_dev); + FAR struct ipv6_hdr_s *ipv6 = (FAR struct ipv6_hdr_s *)bptr; uint16_t protosize; /* Put uncompressed IPv6 header in d_buf. */ @@ -310,6 +333,7 @@ static int sixlowpan_frame_process(FAR struct ieee802154_driver_s *ieee, FAR struct iob_s *iob) { FAR uint8_t *fptr; /* Convenience pointer to beginning of the frame */ + FAR uint8_t *bptr; /* Used to redirect uncompressed header to the bitbucket */ FAR uint8_t *hc1; /* Convenience pointer to HC1 data */ uint16_t fragsize = 0; /* Size of the IP packet (read from fragment) */ uint16_t paysize; /* Size of the data payload */ @@ -318,6 +342,7 @@ static int sixlowpan_frame_process(FAR struct ieee802154_driver_s *ieee, int hdrsize; /* Size of the IEEE802.15.4 header */ #ifdef CONFIG_NET_6LOWPAN_FRAG + FAR uint8_t *fragptr; /* Pointer to the fragmentation header */ bool isfrag = false; bool isfirstfrag = false; uint16_t fragtag = 0; /* Tag of the fragment */ @@ -349,7 +374,8 @@ static int sixlowpan_frame_process(FAR struct ieee802154_driver_s *ieee, * already includes the fragementation header, if presetn. */ - switch ((GETINT16(fptr, RIME_FRAG_DISPATCH_SIZE) & 0xf800) >> 8) + fragptr = fptr + hdrsize; + switch ((GETINT16(fragptr, RIME_FRAG_DISPATCH_SIZE) & 0xf800) >> 8) { /* First fragment of new reassembly */ @@ -357,16 +383,17 @@ static int sixlowpan_frame_process(FAR struct ieee802154_driver_s *ieee, { /* Set up for the reassembly */ - fragsize = GETINT16(fptr, RIME_FRAG_DISPATCH_SIZE) & 0x07ff; - fragtag = GETINT16(fptr, RIME_FRAG_TAG); + fragsize = GETINT16(fragptr, RIME_FRAG_DISPATCH_SIZE) & 0x07ff; + fragtag = GETINT16(fragptr, RIME_FRAG_TAG); + g_frame_hdrlen += SIXLOWPAN_FRAG1_HDR_LEN; ninfo("FRAG1: fragsize=%d fragtag=%d fragoffset=%d\n", fragsize, fragtag, fragoffset); /* Indicate the first fragment of the reassembly */ - isfirstfrag = true; - isfrag = true; + isfirstfrag = true; + isfrag = true; } break; @@ -374,9 +401,10 @@ static int sixlowpan_frame_process(FAR struct ieee802154_driver_s *ieee, { /* Set offset, tag, size. Offset is in units of 8 bytes. */ - fragoffset = fptr[RIME_FRAG_OFFSET]; - fragtag = GETINT16(fptr, RIME_FRAG_TAG); - fragsize = GETINT16(fptr, RIME_FRAG_DISPATCH_SIZE) & 0x07ff; + fragoffset = fragptr[RIME_FRAG_OFFSET]; + fragtag = GETINT16(fragptr, RIME_FRAG_TAG); + fragsize = GETINT16(fragptr, RIME_FRAG_DISPATCH_SIZE) & 0x07ff; + g_frame_hdrlen += SIXLOWPAN_FRAGN_HDR_LEN; ninfo("FRAGN: fragsize=%d fragtag=%d fragoffset=%d\n", fragsize, fragtag, fragoffset); @@ -385,7 +413,7 @@ static int sixlowpan_frame_process(FAR struct ieee802154_driver_s *ieee, /* Indicate that this frame is a another fragment for reassembly */ - isfrag = true; + isfrag = true; } break; @@ -397,6 +425,7 @@ static int sixlowpan_frame_process(FAR struct ieee802154_driver_s *ieee, /* Check if we are currently reassembling a packet */ + bptr = ieee->i_dev.d_buf; if (ieee->i_accumlen > 0) { /* If reassembly timed out, cancel it */ @@ -470,12 +499,11 @@ static int sixlowpan_frame_process(FAR struct ieee802154_driver_s *ieee, else { /* Looks good. We are currently processing a reassembling sequence - * and we recieved a valid FRAGN fragment. Skip the header - * compression dispatch logic. + * and we recieved a valid FRAGN fragment. Redirect the header + * uncompression to our bitbucket. */ - g_uncomp_hdrlen = ieee->i_boffset; - goto copypayload; + bptr = g_bitbucket; } } @@ -522,7 +550,7 @@ 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"); - sixlowpan_uncompresshdr_hc06(ieee, fragsize, iob, fptr); + sixlowpan_uncompresshdr_hc06(fragsize, iob, fptr, bptr); } else #endif /* CONFIG_NET_6LOWPAN_COMPRESSION_HC06 */ @@ -531,7 +559,7 @@ static int sixlowpan_frame_process(FAR struct ieee802154_driver_s *ieee, if (hc1[RIME_HC1_DISPATCH] == SIXLOWPAN_DISPATCH_HC1) { ninfo("HC1 Dispatch\n"); - sixlowpan_uncompresshdr_hc1(ieee, fragsize, iob, fptr); + sixlowpan_uncompresshdr_hc1(fragsize, iob, fptr, bptr); } else #endif /* CONFIG_NET_6LOWPAN_COMPRESSION_HC1 */ @@ -539,30 +567,40 @@ static int sixlowpan_frame_process(FAR struct ieee802154_driver_s *ieee, if (hc1[RIME_HC1_DISPATCH] == SIXLOWPAN_DISPATCH_IPV6) { ninfo("IPv6 Dispatch\n"); - sixlowpan_uncompress_ipv6hdr(ieee, fptr); + sixlowpan_uncompress_ipv6hdr(fptr, bptr); } else { /* Unknown or unsupported header */ - nwarn("WARNING unknown dispatch: %u\n", hc1[RIME_HC1_DISPATCH]); + nwarn("WARNING: Unknown dispatch: %u\n", hc1[RIME_HC1_DISPATCH]); return OK; } #ifdef CONFIG_NET_6LOWPAN_FRAG - /* Non-fragmented and FRAG1 frames pass through here. Remember the - * offset from the beginning of d_buf where be begin placing the data - * payload. - */ + /* Is this the first fragment is a sequence? */ + if (isfirstfrag) { + /* Yes.. Remember the offset from the beginning of d_buf where we + * begin placing the data payload. + */ + ieee->i_boffset = g_uncomp_hdrlen; } - /* We branch to here on all good FRAGN frames */ + /* No.. is this a subsequent fragment in the same sequence? */ + + else if (isfrag) + { + /* Yes, recover the offset from the beginning of the d_buf where + * we began placing payload data. + */ + + g_uncomp_hdrlen = ieee->i_boffset; + } -copypayload: #endif /* CONFIG_NET_6LOWPAN_FRAG */ /* Copy "payload" from the rime buffer to the IEEE802.15.4 MAC driver's @@ -584,7 +622,7 @@ copypayload: reqsize = g_uncomp_hdrlen + (fragoffset << 3) + paysize; if (reqsize > CONFIG_NET_6LOWPAN_MTU) { - ninfo("Required buffer size: %u+%u+%u=%u Available=%u\n", + nwarn("WARNING: Required buffer size: %u+%u+%u=%u Available=%u\n", g_uncomp_hdrlen, (fragoffset << 3), paysize, reqsize, CONFIG_NET_6LOWPAN_MTU); return -ENOMEM; diff --git a/net/sixlowpan/sixlowpan_internal.h b/net/sixlowpan/sixlowpan_internal.h index be29abc8cae..deede9d3b8f 100644 --- a/net/sixlowpan/sixlowpan_internal.h +++ b/net/sixlowpan/sixlowpan_internal.h @@ -497,12 +497,13 @@ void sixlowpan_compresshdr_hc06(FAR struct ieee802154_driver_s *ieee, * appropriate values * * Input Parmeters: - * ieee - A reference to the IEE802.15.4 network device state * 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 uncompressed. + * 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 @@ -510,9 +511,8 @@ void sixlowpan_compresshdr_hc06(FAR struct ieee802154_driver_s *ieee, ****************************************************************************/ #ifdef CONFIG_NET_6LOWPAN_COMPRESSION_HC06 -void sixlowpan_uncompresshdr_hc06(FAR struct ieee802154_driver_s *ieee, - uint16_t iplen, FAR struct iob_s *iob, - FAR uint8_t *fptr); +void sixlowpan_uncompresshdr_hc06(uint16_t iplen, FAR struct iob_s *iob, + FAR uint8_t *fptr, FAR uint8_t *bptr); #endif /**************************************************************************** @@ -530,7 +530,7 @@ void sixlowpan_uncompresshdr_hc06(FAR struct ieee802154_driver_s *ieee, * ipv6 - The IPv6 header to be compressed * destmac - L2 destination address, needed to compress the IP * destination field - * fptr - Pointer to frame to be compressed. + * fptr - Pointer to frame to be compressed. * * Returned Value: * None @@ -557,22 +557,23 @@ void sixlowpan_compresshdr_hc1(FAR struct ieee802154_driver_s *ieee, * are set to the appropriate values * * Input Parameters: - * ieee - A reference to the IEE802.15.4 network device state * 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 + * inferred from the L2 length), non 0 if the packet is a 1st * fragment. - * iob - Pointer to the IOB containing the received frame. - * fptr - Pointer to frame to be uncompressed. + * iob - Pointer to the IOB containing the received frame. + * fptr - Pointer to frame to be uncompressed. + * 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 + * Zero (OK) is returned on success, on failure a negater errno value is + * returned. * ****************************************************************************/ #ifdef CONFIG_NET_6LOWPAN_COMPRESSION_HC1 -int sixlowpan_uncompresshdr_hc1(FAR struct ieee802154_driver_s *ieee, - uint16_t ip_len, FAR struct iob_s *iob, - FAR uint8_t *fptr); +int sixlowpan_uncompresshdr_hc1(uint16_t iplen, FAR struct iob_s *iob, + FAR uint8_t *fptr, FAR uint8_t *bptr); #endif /****************************************************************************