diff --git a/net/sixlowpan/sixlowpan_framelist.c b/net/sixlowpan/sixlowpan_framelist.c index 6aca0069342..994b7bfc7b4 100644 --- a/net/sixlowpan/sixlowpan_framelist.c +++ b/net/sixlowpan/sixlowpan_framelist.c @@ -101,17 +101,15 @@ * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ * * Input Parameters: - * ieee - Pointer to IEEE802.15.4 MAC driver structure. - * destip - Pointer to the IPv6 header to "compress" - * fptr - Pointer to the beginning of the frame under construction + * ipv6hdr - Pointer to the IPv6 header to "compress" + * fptr - Pointer to the beginning of the frame under construction * * Returned Value: * None * ****************************************************************************/ -static void sixlowpan_compress_ipv6hdr(FAR struct ieee802154_driver_s *ieee, - FAR const struct ipv6_hdr_s *destip, +static void sixlowpan_compress_ipv6hdr(FAR const struct ipv6_hdr_s *ipv6hdr, FAR uint8_t *fptr) { /* Indicate the IPv6 dispatch and length */ @@ -121,11 +119,93 @@ static void sixlowpan_compress_ipv6hdr(FAR struct ieee802154_driver_s *ieee, /* Copy the IPv6 header and adjust pointers */ - memcpy(&fptr[g_frame_hdrlen] , destip, IPv6_HDRLEN); + memcpy(&fptr[g_frame_hdrlen] , ipv6hdr, IPv6_HDRLEN); g_frame_hdrlen += IPv6_HDRLEN; g_uncomp_hdrlen += IPv6_HDRLEN; } +/**************************************************************************** + * Name: sixlowpan_copy_protohdr + * + * Description: + * The IPv6 header should have already been processed (as reflected in the + * g_uncomphdrlen). But we probably still need to copy the following + * protocol header. + * + * Input Parameters: + * ipv6hdr - Pointer to the IPv6 header to "compress" + * fptr - Pointer to the beginning of the frame under construction + * + * Returned Value: + * None. But g_frame_hdrlen and g_uncomp_hdrlen updated. + * + ****************************************************************************/ + +static void sixlowpan_copy_protohdr(FAR const struct ipv6_hdr_s *ipv6hdr, + FAR uint8_t *fptr) +{ + uint16_t combined; + uint16_t protosize; + uint16_t copysize; + + /* What is the total size of the IPv6 + protocol header? */ + + switch (ipv6hdr->proto) + { +#ifdef CONFIG_NET_TCP + case IP_PROTO_TCP: + combined = sizeof(struct ipv6tcp_hdr_s); + protosize = sizeof(struct tcp_hdr_s); + break; +#endif + +#ifdef CONFIG_NET_UDP + case IP_PROTO_UDP: + combined = sizeof(struct ipv6udp_hdr_s); + protosize = sizeof(struct udp_hdr_s); + break; +#endif + +#ifdef CONFIG_NET_ICMPv6 + case IP_PROTO_ICMP6: + combined = sizeof(struct ipv6icmp_hdr_s); + protosize = sizeof(struct icmpv6_hdr_s); + break; +#endif + + default: + nwarn("WARNING: Unrecognized proto: %u\n", ipv6hdr->proto); + combined = sizeof(struct ipv6_hdr_s); + protosize = 0; + break; + } + + /* Copy the remaining protocol header. */ + + if (g_uncomp_hdrlen > IPv6_HDRLEN) + { + nwarn("WARNING: Protocol header not copied: " + "g_uncomp_hdren=%u IPv6_HDRLEN=%u\n", + g_uncomp_hdrlen, IPv6_HDRLEN); + return; + } + + copysize = combined - g_uncomp_hdrlen; + if (copysize != protosize) + { + nwarn("WARNING: Protocol header size mismatch: " + "g_uncomp_hdren=%u copysize=%u protosize=%u\n", + g_uncomp_hdrlen, copysize, protosize); + return; + } + + memcpy(fptr + g_frame_hdrlen, (FAR uint8_t *)ipv6hdr + g_uncomp_hdrlen, + copysize); + + g_frame_hdrlen += copysize; + g_uncomp_hdrlen += copysize; +} + /**************************************************************************** * Public Functions ****************************************************************************/ @@ -172,6 +252,7 @@ int sixlowpan_queue_frames(FAR struct ieee802154_driver_s *ieee, FAR uint8_t *fptr; int framer_hdrlen; struct rimeaddr_s bcastmac; + uint16_t paysize; #ifdef CONFIG_NET_6LOWPAN_FRAG uint16_t outlen = 0; #endif @@ -267,7 +348,7 @@ int sixlowpan_queue_frames(FAR struct ieee802154_driver_s *ieee, { /* Small.. use IPv6 dispatch (no compression) */ - sixlowpan_compress_ipv6hdr(ieee, destip, fptr); + sixlowpan_compress_ipv6hdr(destip, fptr); } ninfo("Header of length %d\n", g_frame_hdrlen); @@ -276,9 +357,7 @@ int sixlowpan_queue_frames(FAR struct ieee802154_driver_s *ieee, /* Check if we need to fragment the packet into several frames */ - if ((int)buflen - (int)g_uncomp_hdrlen > - (int)CONFIG_NET_6LOWPAN_MAXPAYLOAD - framer_hdrlen - - (int)g_frame_hdrlen) + if (buflen > (CONFIG_NET_6LOWPAN_MAXPAYLOAD - g_frame_hdrlen)) { #ifdef CONFIG_NET_6LOWPAN_FRAG /* ieee->i_framelist will hold the generated frames; frames will be @@ -295,7 +374,7 @@ int sixlowpan_queue_frames(FAR struct ieee802154_driver_s *ieee, * The following fragments contain only the fragn dispatch. */ - ninfo("Fragmentation sending packet length %d\n", buflen); + ninfo("Sending fragmented packet length %d\n", buflen); /* Create 1st Fragment */ /* Add the frame header using the pre-allocated IOB. */ @@ -325,25 +404,28 @@ int sixlowpan_queue_frames(FAR struct ieee802154_driver_s *ieee, PUTINT16(fptr, RIME_FRAG_DISPATCH_SIZE, ((SIXLOWPAN_DISPATCH_FRAG1 << 8) | buflen)); + PUTINT16(fptr, RIME_FRAG_TAG, ieee->i_dgramtag); ieee->i_dgramtag++; + g_frame_hdrlen += SIXLOWPAN_FRAG1_HDR_LEN; + + /* Copy protocol header that follows the IPv6 header */ + + sixlowpan_copy_protohdr(destip, fptr); + /* Copy payload and enqueue */ - g_frame_hdrlen += SIXLOWPAN_FRAG1_HDR_LEN; - g_rime_payloadlen = - (CONFIG_NET_6LOWPAN_MAXPAYLOAD - framer_hdrlen - g_frame_hdrlen) & 0xf8; - - memcpy(fptr + g_frame_hdrlen, - (FAR uint8_t *)destip + g_uncomp_hdrlen, g_rime_payloadlen); - iob->io_len += g_rime_payloadlen + g_frame_hdrlen; + paysize = (CONFIG_NET_6LOWPAN_MAXPAYLOAD - g_frame_hdrlen) & 0xf8; + memcpy(fptr + g_frame_hdrlen, buf, paysize); /* Set outlen to what we already sent from the IP payload */ - outlen = g_rime_payloadlen + g_uncomp_hdrlen; + iob->io_len = paysize + g_frame_hdrlen; + outlen = paysize; ninfo("First fragment: length %d, tag %d\n", - g_rime_payloadlen, ieee->i_dgramtag); + paysize, ieee->i_dgramtag); sixlowpan_dumpbuffer("Outgoing frame", (FAR const uint8_t *)iob->io_data, iob->io_len); @@ -394,30 +476,33 @@ int sixlowpan_queue_frames(FAR struct ieee802154_driver_s *ieee, PUTINT16(fptr, RIME_FRAG_TAG, ieee->i_dgramtag); fptr[RIME_FRAG_OFFSET] = outlen >> 3; + /* Copy protocol header that follows the IPv6 header */ + + sixlowpan_copy_protohdr(destip, fptr); + /* Copy payload and enqueue */ + /* Check for the last fragment */ - if (buflen - outlen < g_rime_payloadlen) + if (buflen - outlen < paysize) { - /* Last fragment */ + /* Last fragment, truncate to the correct length */ - g_rime_payloadlen = buflen - outlen; + paysize = buflen - outlen; } else { - g_rime_payloadlen = - (CONFIG_NET_6LOWPAN_MAXPAYLOAD - framer_hdrlen - g_frame_hdrlen) & 0xf8; + paysize = (CONFIG_NET_6LOWPAN_MAXPAYLOAD - g_frame_hdrlen) & 0xf8; } - memcpy(fptr + g_frame_hdrlen, (FAR uint8_t *)destip + outlen, - g_rime_payloadlen); - iob->io_len = g_rime_payloadlen + g_frame_hdrlen; + memcpy(fptr + g_frame_hdrlen, buf + outlen, paysize); /* Set outlen to what we already sent from the IP payload */ - outlen += (g_rime_payloadlen + g_uncomp_hdrlen); + iob->io_len = paysize + g_frame_hdrlen; + outlen += paysize; - ninfo("sixlowpan output: fragment offset %d, length %d, tag %d\n", - outlen >> 3, g_rime_payloadlen, ieee->i_dgramtag); + ninfo("Fragment offset %d, length %d, tag %d\n", + outlen >> 3, paysize, ieee->i_dgramtag); sixlowpan_dumpbuffer("Outgoing frame", (FAR const uint8_t *)iob->io_data, iob->io_len); @@ -453,11 +538,14 @@ int sixlowpan_queue_frames(FAR struct ieee802154_driver_s *ieee, DEBUGASSERT(verify == framer_hdrlen); UNUSED(verify); + /* Copy protocol header that follows the IPv6 header */ + + sixlowpan_copy_protohdr(destip, fptr); + /* Copy the payload and queue */ - memcpy(fptr + g_frame_hdrlen, (FAR uint8_t *)destip + g_uncomp_hdrlen, - buflen - g_uncomp_hdrlen); - iob->io_len = buflen - g_uncomp_hdrlen + g_frame_hdrlen; + memcpy(fptr + g_frame_hdrlen, buf, buflen); + iob->io_len = buflen + g_frame_hdrlen; ninfo("Non-fragmented: length %d\n", iob->io_len); sixlowpan_dumpbuffer("Outgoing frame", diff --git a/net/sixlowpan/sixlowpan_globals.c b/net/sixlowpan/sixlowpan_globals.c index 8f48ade9f2f..aac17f7eb9c 100644 --- a/net/sixlowpan/sixlowpan_globals.c +++ b/net/sixlowpan/sixlowpan_globals.c @@ -54,15 +54,6 @@ * during that processing */ -/* The length of the payload in the Rime buffer. - * - * The payload is what comes after the compressed or uncompressed headers - * (can be the IP payload if the IP header only is compressed or the UDP - * payload if the UDP header is also compressed) - */ - -uint8_t g_rime_payloadlen; - /* g_uncomp_hdrlen is the length of the headers before compression (if HC2 * is used this includes the UDP header in addition to the IP header). */ diff --git a/net/sixlowpan/sixlowpan_input.c b/net/sixlowpan/sixlowpan_input.c index 257e7b48c9e..95bb7c1cee2 100644 --- a/net/sixlowpan/sixlowpan_input.c +++ b/net/sixlowpan/sixlowpan_input.c @@ -213,6 +213,7 @@ static int sixlowpan_frame_process(FAR struct ieee802154_driver_s *ieee, 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 */ uint8_t fragoffset = 0; /* Offset of the fragment in the IP packet */ int reqsize; /* Required buffer size */ int hdrsize; /* Size of the IEEE802.15.4 header */ @@ -282,12 +283,12 @@ static int sixlowpan_frame_process(FAR struct ieee802154_driver_s *ieee, fragtag = GETINT16(payptr, RIME_FRAG_TAG); fragsize = GETINT16(payptr, RIME_FRAG_DISPATCH_SIZE) & 0x07ff; - ninfo("FRAGN: size %d, tag %d, offset %d\n", + ninfo("FRAGN: size=%d tag=%d offset=%d\n", fragsize, fragtag, fragoffset); g_frame_hdrlen += SIXLOWPAN_FRAGN_HDR_LEN; - ninfo("FRAGN: i_accumlen %d g_rime_payloadlen %d fragsize %d\n", + ninfo("FRAGN: i_accumlen=%d paysize=%u fragsize=%u\n", ieee->i_accumlen, iob->io_len - g_frame_hdrlen, fragsize); /* Indicate that this frame is a another fragment for reassembly */ @@ -501,28 +502,28 @@ copypayload: * and g_frame_hdrlen are non-zerio, fragoffset is. */ - g_rime_payloadlen = iob->io_len - g_frame_hdrlen; - if (g_rime_payloadlen > CONFIG_NET_6LOWPAN_MTU) + paysize = iob->io_len - g_frame_hdrlen; + if (paysize > CONFIG_NET_6LOWPAN_MTU) { nwarn("WARNING: Packet dropped due to payload (%u) > packet buffer (%u)\n", - g_rime_payloadlen, CONFIG_NET_6LOWPAN_MTU); + paysize, CONFIG_NET_6LOWPAN_MTU); return OK; } /* Sanity-check size of incoming packet to avoid buffer overflow */ - reqsize = g_uncomp_hdrlen + (uint16_t) (fragoffset << 3) + g_rime_payloadlen; + reqsize = g_uncomp_hdrlen + (uint16_t) (fragoffset << 3) + paysize; if (reqsize > CONFIG_NET_6LOWPAN_MTU) { ninfo("Required buffer size: %d+%d+%d=%d Available: %d\n", - g_uncomp_hdrlen, (int)(fragoffset << 3), g_rime_payloadlen, + g_uncomp_hdrlen, (int)(fragoffset << 3), paysize, reqsize, CONFIG_NET_6LOWPAN_MTU); return -ENOMEM; } memcpy((FAR uint8_t *)ieee->i_dev.d_buf + g_uncomp_hdrlen + (int)(fragoffset << 3), payptr + g_frame_hdrlen, - g_rime_payloadlen); + paysize); #ifdef CONFIG_NET_6LOWPAN_FRAG /* Update ieee->i_accumlen if the frame is a fragment, ieee->i_pktlen @@ -548,15 +549,14 @@ copypayload: } else { - ieee->i_accumlen += g_rime_payloadlen; + ieee->i_accumlen += paysize; } - ninfo("i_accumlen %d, g_rime_payloadlen %d\n", - ieee->i_accumlen, g_rime_payloadlen); + ninfo("i_accumlen %d, paysize %d\n", ieee->i_accumlen, paysize); } else { - ieee->i_pktlen = g_rime_payloadlen + g_uncomp_hdrlen; + ieee->i_pktlen = paysize + g_uncomp_hdrlen; } /* If we have a full IP packet in sixlowpan_buf, deliver it to @@ -580,7 +580,7 @@ copypayload: #else /* Deliver the packet to the IP stack */ - ieee->i_dev.d_len = g_rime_payloadlen + g_uncomp_hdrlen; + ieee->i_dev.d_len = paysize + g_uncomp_hdrlen; return INPUT_COMPLETE; #endif /* CONFIG_NET_6LOWPAN_FRAG */ } @@ -706,6 +706,10 @@ int sixlowpan_input(FAR struct ieee802154_driver_s *ieee) ret = sixlowpan_frame_process(ieee, iob); + /* Free the IOB the held the consumed frame */ + + iob_free(iob); + /* Was the frame successfully processed? Is the packet in d_buf fully * reassembled? */ diff --git a/net/sixlowpan/sixlowpan_internal.h b/net/sixlowpan/sixlowpan_internal.h index d6a795c5540..bd366c884ec 100644 --- a/net/sixlowpan/sixlowpan_internal.h +++ b/net/sixlowpan/sixlowpan_internal.h @@ -409,15 +409,6 @@ struct frame802154_s extern FAR uint8_t *g_rimeptr; -/* The length of the payload in the Rime buffer. - * - * The payload is what comes after the compressed or uncompressed headers - * (can be the IP payload if the IP header only is compressed or the UDP - * payload if the UDP header is also compressed) - */ - -extern uint8_t g_rime_payloadlen; - /* g_uncomp_hdrlen is the length of the headers before compression (if HC2 * is used this includes the UDP header in addition to the IP header). */