6LoWPAN: Modify the the way TCP headers are transferred -- yet again. TCP packet reassembly now seems to work OK, but no there now does not seem to be a listener on the port.

This commit is contained in:
Gregory Nutt 2017-06-24 21:12:46 -06:00
parent 73d32a962d
commit 58e3558c55
5 changed files with 163 additions and 155 deletions

View File

@ -125,8 +125,6 @@
static void sixlowpan_compress_ipv6hdr(FAR const struct ipv6_hdr_s *ipv6hdr,
FAR uint8_t *fptr)
{
uint16_t protosize;
/* Indicate the IPv6 dispatch and length */
fptr[g_frame_hdrlen] = SIXLOWPAN_DISPATCH_IPV6;
@ -134,52 +132,69 @@ static void sixlowpan_compress_ipv6hdr(FAR const struct ipv6_hdr_s *ipv6hdr,
/* Copy the IPv6 header and adjust pointers */
memcpy(&fptr[g_frame_hdrlen] , ipv6hdr, IPv6_HDRLEN);
memcpy(&fptr[g_frame_hdrlen], ipv6hdr, IPv6_HDRLEN);
g_frame_hdrlen += IPv6_HDRLEN;
g_uncomp_hdrlen += IPv6_HDRLEN;
}
/* Copy the following protocol header, */
/****************************************************************************
* Name: sixlowpan_protosize
*
* Description:
* Get the size of any uncompresssed protocol header that follows the
* IPv6 header.
*
****************************************************************************/
switch (ipv6hdr->proto)
{
static uint16_t sixlowpan_protosize(FAR const struct ipv6_hdr_s *ipv6hdr,
FAR uint8_t *fptr)
{
uint16_t protosize;
/* Do we already have an encoded protocol header? If not, it needs to
* coped as raw data in the fist packet of a fragement.
*/
if (!g_have_protohdr)
{
/* Copy the following protocol header, */
switch (ipv6hdr->proto)
{
#ifdef CONFIG_NET_TCP
case IP_PROTO_TCP:
{
FAR struct tcp_hdr_s *tcp = &((FAR struct ipv6tcp_hdr_s *)ipv6hdr)->tcp;
case IP_PROTO_TCP:
{
FAR struct tcp_hdr_s *tcp =
&((FAR struct ipv6tcp_hdr_s *)ipv6hdr)->tcp;
/* The TCP header length is encoded in the top 4 bits of the
* tcpoffset field (in units of 32-bit words).
*/
/* 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;
protosize = ((uint16_t)tcp->tcpoffset >> 4) << 2;
}
break;
#endif
#ifdef CONFIG_NET_UDP
case IP_PROTO_UDP:
protosize = sizeof(struct udp_hdr_s);
break;
case IP_PROTO_UDP:
protosize = UDP_HDRLEN;
break;
#endif
#ifdef CONFIG_NET_ICMPv6
case IP_PROTO_ICMP6:
protosize = sizeof(struct icmpv6_hdr_s);
break;
case IP_PROTO_ICMP6:
protosize = ICMPv6_HDRLEN;
break;
#endif
default:
nwarn("WARNING: Unrecognized proto: %u\n", ipv6hdr->proto);
return;
}
default:
nwarn("WARNING: Unrecognized proto: %u\n", ipv6hdr->proto);
return 0;
}
}
/* Copy the protocol header. */
memcpy(fptr + g_frame_hdrlen, (FAR uint8_t *)ipv6hdr + g_uncomp_hdrlen,
protosize);
g_frame_hdrlen += protosize;
g_uncomp_hdrlen += protosize;
return protosize;
}
/****************************************************************************
@ -234,6 +249,7 @@ int sixlowpan_queue_frames(FAR struct ieee802154_driver_s *ieee,
#ifdef CONFIG_NET_6LOWPAN_FRAG
uint16_t outlen = 0;
#endif
uint8_t protosize;
int ret;
ninfo("buflen=%lu\n", (unsigned long)buflen);
@ -244,6 +260,7 @@ int sixlowpan_queue_frames(FAR struct ieee802154_driver_s *ieee,
g_uncomp_hdrlen = 0;
g_frame_hdrlen = 0;
g_have_protohdr = false;
/* Reset frame meta data */
@ -381,9 +398,13 @@ int sixlowpan_queue_frames(FAR struct ieee802154_driver_s *ieee,
ninfo("Header of length %d\n", g_frame_hdrlen);
/* Get the size of any uncompressed protocol headers */
protosize = sixlowpan_protosize(destip, fptr);
/* Check if we need to fragment the packet into several frames */
if (buflen > (SIXLOWPAN_FRAMELEN - g_frame_hdrlen))
if (buflen > (SIXLOWPAN_FRAMELEN - g_frame_hdrlen - protosize))
{
#ifdef CONFIG_NET_6LOWPAN_FRAG
/* qhead will hold the generated frame list; frames will be
@ -420,29 +441,39 @@ int sixlowpan_queue_frames(FAR struct ieee802154_driver_s *ieee,
* 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.
* 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.
*/
pktlen = buflen + g_uncomp_hdrlen;
pktlen = buflen + g_uncomp_hdrlen + protosize;
PUTHOST16(fragptr, SIXLOWPAN_FRAG_DISPATCH_SIZE,
((SIXLOWPAN_DISPATCH_FRAG1 << 8) | pktlen));
PUTHOST16(fragptr, SIXLOWPAN_FRAG_TAG, ieee->i_dgramtag);
g_frame_hdrlen += SIXLOWPAN_FRAG1_HDR_LEN;
/* Copy any uncompressed protocol headers that must appear only in th
* first fragment.
*/
if (protosize > 0)
{
FAR uint8_t *src = (FAR uint8_t *)destip + IPv6_HDRLEN;
memcpy(fptr + g_frame_hdrlen, src, protosize);
}
/* Copy payload and enqueue. NOTE that the size is a multiple of eight
* bytes.
*/
paysize = (SIXLOWPAN_FRAMELEN - g_frame_hdrlen) & ~7;
memcpy(fptr + g_frame_hdrlen, buf, paysize);
memcpy(fptr + g_frame_hdrlen + protosize, buf, paysize - protosize);
/* Set outlen to what we already sent from the IP payload */
@ -471,7 +502,7 @@ int sixlowpan_queue_frames(FAR struct ieee802154_driver_s *ieee,
frame1 = iob->io_data;
frag1_hdrlen = g_frame_hdrlen;
while (outlen < buflen)
while (outlen < (buflen + protosize))
{
uint16_t fragn_hdrlen;
@ -515,14 +546,14 @@ int sixlowpan_queue_frames(FAR struct ieee802154_driver_s *ieee,
paysize = (SIXLOWPAN_FRAMELEN - fragn_hdrlen) &
SIXLOWPAN_DISPATCH_FRAG_MASK;
if (buflen - outlen < paysize)
if (paysize > buflen - outlen + protosize)
{
/* Last fragment, truncate to the correct length */
paysize = buflen - outlen;
paysize = buflen - outlen + protosize;
}
memcpy(fptr + fragn_hdrlen, buf + outlen, paysize);
memcpy(fptr + fragn_hdrlen, buf + outlen - protosize, paysize);
/* Set outlen to what we already sent from the IP payload */
@ -587,10 +618,20 @@ int sixlowpan_queue_frames(FAR struct ieee802154_driver_s *ieee,
* and send in one frame.
*/
/* Copy any uncompressed protocol headers that must appear only in th
* first fragment.
*/
if (protosize > 0)
{
FAR uint8_t *src = (FAR uint8_t *)destip + IPv6_HDRLEN;
memcpy(fptr + g_frame_hdrlen, src, protosize);
}
/* Copy the payload into the frame. */
memcpy(fptr + g_frame_hdrlen, buf, buflen);
iob->io_len = buflen + g_frame_hdrlen;
memcpy(fptr + g_frame_hdrlen + protosize, buf, buflen);
iob->io_len = buflen + g_frame_hdrlen + protosize;
iob->io_pktlen = iob->io_len;
ninfo("Non-fragmented: length %d\n", iob->io_len);

View File

@ -67,4 +67,8 @@ uint8_t g_uncomp_hdrlen;
uint8_t g_frame_hdrlen;
/* g_have_protohdr: true=Protocal header copied. */
bool g_have_protohdr;
#endif /* CONFIG_NET_6LOWPAN */

View File

@ -878,132 +878,87 @@ void sixlowpan_compresshdr_hc06(FAR struct ieee802154_driver_s *ieee,
g_uncomp_hdrlen = IPv6_HDRLEN;
/* Add protocol header */
switch (ipv6->proto)
{
#ifdef CONFIG_NET_UDP
/* UDP header compression */
/* UDP header compression */
case IP_PROTO_UDP:
if (ipv6->proto == IP_PROTO_UDP)
{
/* The UDP header will follow the IPv6 header */
FAR struct udp_hdr_s *udp =
(FAR struct udp_hdr_s *)((FAR uint8_t *)ipv6 + IPv6_HDRLEN);
ninfo("Uncompressed UDP ports: srcport=%04x destport=%04x\n",
ntohs(udp->srcport), ntohs(udp->destport));
/* Mask out the last 4 bits can be used as a mask */
if (((ntohs(udp->srcport) & 0xfff0) == SIXLOWPAN_UDP_4_BIT_PORT_MIN) &&
((ntohs(udp->destport) & 0xfff0) == SIXLOWPAN_UDP_4_BIT_PORT_MIN))
{
/* The UDP header will follow the IPv6 header */
/* We can compress 12 bits of both source and dest */
FAR struct udp_hdr_s *udp =
(FAR struct udp_hdr_s *)((FAR uint8_t *)ipv6 + IPv6_HDRLEN);
*g_hc06ptr = SIXLOWPAN_NHC_UDP_CS_P_11;
ninfo("Uncompressed UDP ports: srcport=%04x destport=%04x\n",
ntohs(udp->srcport), ntohs(udp->destport));
ninfo("Remove 12b of both source & dest with prefix 0xf0b*\n");
/* Mask out the last 4 bits can be used as a mask */
*(g_hc06ptr + 1) =
(uint8_t)((ntohs(udp->srcport) - SIXLOWPAN_UDP_4_BIT_PORT_MIN) << 4) +
(uint8_t)((ntohs(udp->destport) - SIXLOWPAN_UDP_4_BIT_PORT_MIN));
if (((ntohs(udp->srcport) & 0xfff0) == SIXLOWPAN_UDP_4_BIT_PORT_MIN) &&
((ntohs(udp->destport) & 0xfff0) == SIXLOWPAN_UDP_4_BIT_PORT_MIN))
{
/* We can compress 12 bits of both source and dest */
*g_hc06ptr = SIXLOWPAN_NHC_UDP_CS_P_11;
ninfo("Remove 12b of both source & dest with prefix 0xf0b*\n");
*(g_hc06ptr + 1) =
(uint8_t)((ntohs(udp->srcport) - SIXLOWPAN_UDP_4_BIT_PORT_MIN) << 4) +
(uint8_t)((ntohs(udp->destport) - SIXLOWPAN_UDP_4_BIT_PORT_MIN));
g_hc06ptr += 2;
}
else if ((ntohs(udp->destport) & 0xff00) ==
SIXLOWPAN_UDP_8_BIT_PORT_MIN)
{
/* We can compress 8 bits of dest, leave source. */
*g_hc06ptr = SIXLOWPAN_NHC_UDP_CS_P_01;
ninfo("Leave source, remove 8 bits of dest with prefix 0xF0\n");
memcpy(g_hc06ptr + 1, &udp->srcport, 2);
*(g_hc06ptr + 3) =
(uint8_t) ((ntohs(udp->destport) -
SIXLOWPAN_UDP_8_BIT_PORT_MIN));
g_hc06ptr += 4;
}
else if ((ntohs(udp->srcport) & 0xff00) ==
SIXLOWPAN_UDP_8_BIT_PORT_MIN)
{
/* We can compress 8 bits of src, leave dest. Copy compressed port */
*g_hc06ptr = SIXLOWPAN_NHC_UDP_CS_P_10;
ninfo("Remove 8 bits of source with prefix 0xF0, leave dest. hch: %u\n",
*g_hc06ptr);
*(g_hc06ptr + 1) =
(uint8_t)((ntohs(udp->srcport) - SIXLOWPAN_UDP_8_BIT_PORT_MIN));
memcpy(g_hc06ptr + 2, &udp->destport, 2);
g_hc06ptr += 4;
}
else
{
/* we cannot compress. Copy uncompressed ports, full checksum */
*g_hc06ptr = SIXLOWPAN_NHC_UDP_CS_P_00;
nwarn("WARNING: Cannot compress headers\n");
memcpy(g_hc06ptr + 1, &udp->srcport, 4);
g_hc06ptr += 5;
}
/* Always inline the checksum */
if (1)
{
memcpy(g_hc06ptr, &udp->udpchksum, 2);
g_hc06ptr += 2;
}
g_uncomp_hdrlen += UDP_HDRLEN;
g_hc06ptr += 2;
}
break;
#endif /* CONFIG_NET_UDP */
#ifdef CONFIG_NET_TCP
/* TCP header -- not compressed */
case IP_PROTO_TCP:
else if ((ntohs(udp->destport) & 0xff00) ==
SIXLOWPAN_UDP_8_BIT_PORT_MIN)
{
FAR struct tcp_hdr_s *tcp =
(FAR struct tcp_hdr_s *)((FAR uint8_t *)ipv6 + IPv6_HDRLEN);
unsigned int hdrsize;
/* We can compress 8 bits of dest, leave source. */
hdrsize = ((uint16_t)tcp->tcpoffset >> 4) << 2;
memcpy(g_hc06ptr, tcp, hdrsize);
*g_hc06ptr = SIXLOWPAN_NHC_UDP_CS_P_01;
g_uncomp_hdrlen += hdrsize;
g_hc06ptr += hdrsize;
ninfo("Leave source, remove 8 bits of dest with prefix 0xF0\n");
memcpy(g_hc06ptr + 1, &udp->srcport, 2);
*(g_hc06ptr + 3) =
(uint8_t) ((ntohs(udp->destport) -
SIXLOWPAN_UDP_8_BIT_PORT_MIN));
g_hc06ptr += 4;
}
break;
#endif
#ifdef CONFIG_NET_ICMPv6
/* TCP header -- not compressed */
case IP_PROTO_ICMP:
else if ((ntohs(udp->srcport) & 0xff00) ==
SIXLOWPAN_UDP_8_BIT_PORT_MIN)
{
FAR const uint8_t *src = (FAR const uint8_t *)ipv6 + IPv6_HDRLEN;
/* We can compress 8 bits of src, leave dest. Copy compressed port */
memcpy(g_hc06ptr, src, ICMPv6_HDRLEN)
g_uncomp_hdrlen += ICMPv6_HDRLEN;
g_hc06ptr += ICMPv6_HDRLEN;
*g_hc06ptr = SIXLOWPAN_NHC_UDP_CS_P_10;
ninfo("Remove 8 bits of source with prefix 0xF0, leave dest. hch: %u\n",
*g_hc06ptr);
*(g_hc06ptr + 1) =
(uint8_t)((ntohs(udp->srcport) - SIXLOWPAN_UDP_8_BIT_PORT_MIN));
memcpy(g_hc06ptr + 2, &udp->destport, 2);
g_hc06ptr += 4;
}
break;
#endif
else
{
/* we cannot compress. Copy uncompressed ports, full checksum */
default:
nerr("ERROR: Unsupported protocol: %02x\n", ipv6->proto);
break;
*g_hc06ptr = SIXLOWPAN_NHC_UDP_CS_P_00;
nwarn("WARNING: Cannot compress headers\n");
memcpy(g_hc06ptr + 1, &udp->srcport, 4);
g_hc06ptr += 5;
}
/* Always inline the checksum */
memcpy(g_hc06ptr, &udp->udpchksum, 2);
g_hc06ptr += 2;
g_uncomp_hdrlen += UDP_HDRLEN;
g_have_protohdr = true;
}
#endif /* CONFIG_NET_UDP */
/* Before the g_frame_hdrlen operation */

View File

@ -265,6 +265,8 @@ void sixlowpan_compresshdr_hc1(FAR struct ieee802154_driver_s *ieee,
hc1[SIXLOWPAN_HC1_TTL] = ipv6->ttl;
g_frame_hdrlen += SIXLOWPAN_HC1_HDR_LEN;
}
g_have_protohdr = true;
}
break;
#endif /* CONFIG_NET_UDP */

View File

@ -58,7 +58,9 @@
****************************************************************************/
#include <nuttx/config.h>
#include <sys/types.h>
#include <stdbool.h>
#include <nuttx/net/tcp.h>
#include <nuttx/net/udp.h>
@ -207,6 +209,10 @@ extern uint8_t g_uncomp_hdrlen;
extern uint8_t g_frame_hdrlen;
/* g_have_protohdr: true=Protocal header copied. */
extern bool g_have_protohdr;
/****************************************************************************
* Public Types
****************************************************************************/