6loWPAN: Add calculation of TCP header size. It is not a constant.

This commit is contained in:
Gregory Nutt 2017-04-07 17:04:57 -06:00
parent e3b4d77ee2
commit 60f0186258
3 changed files with 63 additions and 21 deletions

View File

@ -154,29 +154,37 @@ static void sixlowpan_copy_protohdr(FAR const struct ipv6_hdr_s *ipv6hdr,
{
#ifdef CONFIG_NET_TCP
case IP_PROTO_TCP:
combined = sizeof(struct ipv6tcp_hdr_s);
protosize = sizeof(struct tcp_hdr_s);
{
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).
*/
protosize = ((uint16_t)tcp->tcpoffset >> 4) << 2;
combined = sizeof(struct ipv6_hdr_s) + protosize;
}
break;
#endif
#ifdef CONFIG_NET_UDP
case IP_PROTO_UDP:
combined = sizeof(struct ipv6udp_hdr_s);
protosize = sizeof(struct udp_hdr_s);
combined = sizeof(struct ipv6udp_hdr_s);
break;
#endif
#ifdef CONFIG_NET_ICMPv6
case IP_PROTO_ICMP6:
combined = sizeof(struct ipv6icmp_hdr_s);
protosize = sizeof(struct icmpv6_hdr_s);
combined = sizeof(struct ipv6icmp_hdr_s);
break;
#endif
default:
nwarn("WARNING: Unrecognized proto: %u\n", ipv6hdr->proto);
combined = sizeof(struct ipv6_hdr_s);
protosize = 0;
combined = sizeof(struct ipv6_hdr_s);
break;
}

View File

@ -86,6 +86,7 @@
/* 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 Functions
@ -728,7 +729,7 @@ int sixlowpan_input(FAR struct ieee802154_driver_s *ieee)
* layer protocol header.
*/
ipv6hdr = (FAR struct ipv6_hdr_s *)(ieee->i_dev.d_buf);
ipv6hdr = IPv6BUF(&ieee->i_dev);
/* Get the Rime MAC address of the destination. This
* assumes an encoding of the MAC address in the IPv6
@ -743,7 +744,15 @@ int sixlowpan_input(FAR struct ieee802154_driver_s *ieee)
if (ipv6hdr->proto != IP_PROTO_TCP)
{
hdrlen = IPv6_HDRLEN + TCP_HDRLEN;
FAR struct tcp_hdr_s *tcp = TCPBUF(&ieee->i_dev);
uint16_t tcplen;
/* The TCP header length is encoded in the top 4 bits
* of the tcpoffset field (in units of 32-bit words).
*/
tcplen = ((uint16_t)tcp->tcpoffset >> 4) << 2;
hdrlen = IPv6_HDRLEN + tcplen;
}
else if (ipv6hdr->proto != IP_PROTO_UDP)
{

View File

@ -88,6 +88,7 @@ static uint16_t sixlowpan_tcp_chksum(FAR struct ipv6tcp_hdr_s *ipv6tcp,
FAR const uint8_t *buf, uint16_t buflen)
{
uint16_t upperlen;
uint16_t tcplen;
uint16_t sum;
/* The length reported in the IPv6 header is the length of the payload
@ -115,9 +116,14 @@ static uint16_t sixlowpan_tcp_chksum(FAR struct ipv6tcp_hdr_s *ipv6tcp,
sum = chksum(sum, (FAR uint8_t *)ipv6tcp->ipv6.srcipaddr,
2 * sizeof(net_ipv6addr_t));
/* Sum the TCP header */
/* Sum the TCP header
*
* The TCP header length is encoded in the top 4 bits of the tcpoffset
* field (in units of 32-bit words).
*/
sum = chksum(sum, (FAR uint8_t *)&ipv6tcp->tcp, TCP_HDRLEN);
tcplen = ((uint16_t)ipv6tcp->tcp.tcpoffset >> 4) << 2;
sum = chksum(sum, (FAR uint8_t *)&ipv6tcp->tcp, tcplen);
/* Sum payload data. */
@ -383,43 +389,62 @@ void sixlowpan_tcp_send(FAR struct net_driver_s *dev)
if (dev != NULL && dev->d_len > 0)
{
FAR struct ipv6_hdr_s *ipv6hdr;
FAR struct ipv6tcp_hdr_s *ipv6hdr;
/* The IPv6 header followed by a TCP headers should lie at the
* beginning of d_buf since there is no link layer protocol header
* and the TCP state machine should only response with TCP packets.
*/
ipv6hdr = (FAR struct ipv6_hdr_s *)(dev->d_buf);
ipv6hdr = (FAR struct ipv6tcp_hdr_s *)(dev->d_buf);
/* The TCP data payload should follow the IPv6 header plus the
* protocol header.
*/
if (ipv6hdr->proto != IP_PROTO_TCP)
if (ipv6hdr->ipv6.proto != IP_PROTO_TCP)
{
nwarn("WARNING: Expected TCP protoype: %u\n", ipv6hdr->proto);
nwarn("WARNING: Expected TCP protoype: %u vs %s\n",
ipv6hdr->ipv6.proto, IP_PROTO_TCP);
}
else
{
struct rimeaddr_s destmac;
FAR uint8_t *buf;
size_t buflen;
uint16_t hdrlen;
uint16_t buflen;
/* Get the Rime MAC address of the destination. This assumes an
* encoding of the MAC address in the IPv6 address.
*/
sixlowpan_rimefromip(ipv6hdr->destipaddr, &destmac);
sixlowpan_rimefromip(ipv6hdr->ipv6.destipaddr, &destmac);
/* Convert the outgoing packet into a frame list. */
/* Get the IPv6 + TCP combined header length. The size of the TCP
* header is encoded in the top 4 bits of the tcpoffset field (in
* units of 32-bit words).
*/
buf = dev->d_buf + sizeof(struct ipv6_hdr_s);
buflen = dev->d_len - sizeof(struct ipv6_hdr_s);
hdrlen = IPv6_HDRLEN + (((uint16_t)ipv6hdr->tcp.tcpoffset >> 4) << 2);
(void)sixlowpan_queue_frames(
(FAR struct ieee802154_driver_s *)dev, ipv6hdr,
buf, buflen, &destmac);
/* Drop the packet if the buffer length is less than this. */
if (hdrlen > dev->d_len)
{
nwarn("WARNING: Dropping small TCP packet: %u < %u\n",
buflen, hdrlen);
}
else
{
/* Convert the outgoing packet into a frame list. */
buf = dev->d_buf + hdrlen;
buflen = dev->d_len - hdrlen;
(void)sixlowpan_queue_frames(
(FAR struct ieee802154_driver_s *)dev, &ipv6hdr->ipv6,
buf, buflen, &destmac);
}
}
}