From dc2113d67a27ab3142c8f136408d330f6bfde5bb Mon Sep 17 00:00:00 2001 From: Martine Lenders <mail@martine-lenders.eu> Date: Wed, 22 Jul 2015 20:56:17 +0200 Subject: [PATCH] ng_sixlowpan_frag: fixes --- .../ng_sixlowpan/frag/ng_sixlowpan_frag.c | 7 +- .../network_layer/ng_sixlowpan/frag/rbuf.c | 90 ++++++--------- .../network_layer/ng_sixlowpan/frag/rbuf.h | 2 +- .../network_layer/ng_sixlowpan/ng_sixlowpan.c | 107 ++++++++---------- 4 files changed, 89 insertions(+), 117 deletions(-) diff --git a/sys/net/network_layer/ng_sixlowpan/frag/ng_sixlowpan_frag.c b/sys/net/network_layer/ng_sixlowpan/frag/ng_sixlowpan_frag.c index e9bb35ecd8..c31a77600a 100644 --- a/sys/net/network_layer/ng_sixlowpan/frag/ng_sixlowpan_frag.c +++ b/sys/net/network_layer/ng_sixlowpan/frag/ng_sixlowpan_frag.c @@ -191,7 +191,7 @@ static uint16_t _send_nth_fragment(ng_sixlowpan_netif_t *iface, ng_pktsnip_t *pk } } - DEBUG("6lo frag: send first fragment (datagram size: %u, " + DEBUG("6lo frag: send subsequent fragment (datagram size: %u, " "datagram tag: %" PRIu16 ", offset: %" PRIu8 " (%u bytes), " "fragment size: %" PRIu16 ")\n", (unsigned int)datagram_size, _tag, hdr->offset, hdr->offset << 3, @@ -217,6 +217,7 @@ void ng_sixlowpan_frag_send(kernel_pid_t pid, ng_pktsnip_t *pkt, if ((res = _send_1st_fragment(iface, pkt, payload_len, datagram_size)) == 0) { /* error sending first fragment */ + DEBUG("6lo frag: error sending 1st fragment\n"); ng_pktbuf_release(pkt); return; } @@ -226,7 +227,9 @@ void ng_sixlowpan_frag_send(kernel_pid_t pid, ng_pktsnip_t *pkt, while (offset < datagram_size) { if ((res = _send_nth_fragment(iface, pkt, payload_len, datagram_size, offset)) == 0) { - /* error sending first fragment */ + /* error sending subsequent fragment */ + DEBUG("6lo frag: error sending subsequent fragment (offset = %" PRIu16 + ")\n", offset); ng_pktbuf_release(pkt); return; } diff --git a/sys/net/network_layer/ng_sixlowpan/frag/rbuf.c b/sys/net/network_layer/ng_sixlowpan/frag/rbuf.c index 6ca8d22d16..7d6ac64dac 100644 --- a/sys/net/network_layer/ng_sixlowpan/frag/rbuf.c +++ b/sys/net/network_layer/ng_sixlowpan/frag/rbuf.c @@ -16,10 +16,7 @@ #include <stdbool.h> #include "rbuf.h" -#include "net/ng_netapi.h" -#include "net/ng_netif.h" -#include "net/ng_netif/hdr.h" -#include "net/ng_pktbuf.h" +#include "net/ng_netbase.h" #include "net/ng_ipv6/netif.h" #include "net/ng_sixlowpan.h" #include "net/ng_sixlowpan/frag.h" @@ -67,7 +64,6 @@ void rbuf_add(ng_netif_hdr_t *netif_hdr, ng_sixlowpan_frag_t *frag, rbuf_t *entry; rbuf_int_t *ptr; uint8_t *data = ((uint8_t *)frag) + sizeof(ng_sixlowpan_frag_t); - uint16_t dg_frag_size = frag_size; /* may differ on first fragment */ _rbuf_gc(); entry = _rbuf_get(ng_netif_hdr_get_src_addr(netif_hdr), netif_hdr->src_l2addr_len, @@ -83,10 +79,12 @@ void rbuf_add(ng_netif_hdr_t *netif_hdr, ng_sixlowpan_frag_t *frag, ptr = entry->ints; /* dispatches in the first fragment are ignored */ - if (offset != 0) { - switch (((uint8_t *)(entry->pkt->data))[0]) { + if (offset == 0) { + switch (data[0]) { case NG_SIXLOWPAN_UNCOMPRESSED: - offset++; + data++; /* skip 6LoWPAN dispatch */ + frag_size--; + entry->compressed = 0; /* datagram is not compressed */ break; @@ -94,19 +92,9 @@ void rbuf_add(ng_netif_hdr_t *netif_hdr, ng_sixlowpan_frag_t *frag, break; } - data++; /* also don't take offset field */ } else { - switch (data[0]) { - case NG_SIXLOWPAN_UNCOMPRESSED: - dg_frag_size--; - - break; - - default: - break; - } - + data++; /* FRAGN header is one byte longer (offset) */ } if ((offset + frag_size) > entry->pkt->size) { @@ -117,7 +105,7 @@ void rbuf_add(ng_netif_hdr_t *netif_hdr, ng_sixlowpan_frag_t *frag, } while (ptr != NULL) { - if (_rbuf_int_in(ptr, offset, offset + dg_frag_size - 1)) { + if (_rbuf_int_in(ptr, offset, offset + frag_size - 1)) { DEBUG("6lo rfrag: overlapping or same intervals, discarding datagram\n"); ng_pktbuf_release(entry->pkt); _rbuf_rem(entry); @@ -127,31 +115,13 @@ void rbuf_add(ng_netif_hdr_t *netif_hdr, ng_sixlowpan_frag_t *frag, ptr = ptr->next; } - if (_rbuf_update_ints(entry, offset, dg_frag_size)) { - if (dg_frag_size < frag_size) { - /* some dispatches do not count to datagram size and we need - * more space because of that */ - if (ng_pktbuf_realloc_data(entry->pkt, entry->pkt->size + - (frag_size - dg_frag_size)) < 0) { - DEBUG("6lo rbuf: could not reallocate packet data.\n"); - return; - } - - /* move already inserted fragments (frag_size - dg_frag_size) to the right */ - if (entry->cur_size > 0) { - for (int i = entry->pkt->size - (frag_size - dg_frag_size); i > 0; i--) { - uint8_t *d = ((uint8_t *)(entry->pkt->data)) + i; - *d = *(d - 1); - } - } - } - + if (_rbuf_update_ints(entry, offset, frag_size)) { DEBUG("6lo rbuf: add fragment data\n"); - entry->cur_size += (uint16_t)dg_frag_size; + entry->cur_size += (uint16_t)frag_size; memcpy(((uint8_t *)entry->pkt->data) + offset, data, frag_size); } - if (entry->cur_size == entry->datagram_size) { + if (entry->cur_size == entry->pkt->size) { kernel_pid_t iface = netif_hdr->if_pid; ng_pktsnip_t *netif = ng_netif_hdr_build(entry->src, entry->src_len, entry->dst, entry->dst_len); @@ -159,6 +129,7 @@ void rbuf_add(ng_netif_hdr_t *netif_hdr, ng_sixlowpan_frag_t *frag, if (netif == NULL) { DEBUG("6lo rbuf: error allocating netif header\n"); ng_pktbuf_release(entry->pkt); + _rbuf_rem(entry); return; } @@ -166,8 +137,18 @@ void rbuf_add(ng_netif_hdr_t *netif_hdr, ng_sixlowpan_frag_t *frag, netif_hdr->if_pid = iface; LL_APPEND(entry->pkt, netif); - DEBUG("6lo rbuf: datagram complete, send to self\n"); - ng_netapi_receive(thread_getpid(), entry->pkt); + if (entry->compressed) { + DEBUG("6lo rbuf: datagram complete, send to self for decompression\n"); + ng_netapi_receive(thread_getpid(), entry->pkt); + } + else { + DEBUG("6lo rbuf: datagram complete, send to IPv6 listeners\n"); + if (!ng_netapi_dispatch_receive(NG_NETTYPE_IPV6, NG_NETREG_DEMUX_CTX_ALL, + entry->pkt)) { + DEBUG("6lo rbuf: No receivers for this packet found\n"); + ng_pktbuf_release(entry->pkt); + } + } _rbuf_rem(entry); } } @@ -222,9 +203,9 @@ static bool _rbuf_update_ints(rbuf_t *entry, uint16_t offset, size_t frag_size) DEBUG("6lo rfrag: add interval (%" PRIu16 ", %" PRIu16 ") to entry (%s, ", new->start, new->end, ng_netif_addr_to_str(l2addr_str, sizeof(l2addr_str), entry->src, entry->src_len)); - DEBUG("%s, %u, %" PRIu16 ")\n", ng_netif_addr_to_str(l2addr_str, - sizeof(l2addr_str), entry->dst, entry->dst_len), entry->datagram_size, - entry->tag); + DEBUG("%s, %u, %u)\n", ng_netif_addr_to_str(l2addr_str, + sizeof(l2addr_str), entry->dst, entry->dst_len), + (unsigned)entry->pkt->size, entry->tag); LL_PREPEND(entry->ints, new); @@ -247,10 +228,10 @@ static void _rbuf_gc(void) ((now.seconds - rbuf[i].arrival) > RBUF_TIMEOUT)) { DEBUG("6lo rfrag: entry (%s, ", ng_netif_addr_to_str(l2addr_str, sizeof(l2addr_str), rbuf[i].src, rbuf[i].src_len)); - DEBUG("%s, %u, %" PRIu16 ") timed out\n", + DEBUG("%s, %u, %u) timed out\n", ng_netif_addr_to_str(l2addr_str, sizeof(l2addr_str), rbuf[i].dst, rbuf[i].dst_len), - rbuf[i].datagram_size, rbuf[i].tag); + (unsigned)rbuf[i].pkt->size, rbuf[i].tag); ng_pktbuf_release(rbuf[i].pkt); _rbuf_rem(&(rbuf[i])); @@ -278,7 +259,7 @@ static rbuf_t *_rbuf_get(const void *src, size_t src_len, for (unsigned int i = 0; i < RBUF_SIZE; i++) { /* check first if entry already available */ - if ((rbuf[i].pkt != NULL) && (rbuf[i].datagram_size == size) && + if ((rbuf[i].pkt != NULL) && (rbuf[i].pkt->size == size) && (rbuf[i].tag == tag) && (rbuf[i].src_len == src_len) && (rbuf[i].dst_len == dst_len) && (memcmp(rbuf[i].src, src, src_len) == 0) && @@ -286,10 +267,10 @@ static rbuf_t *_rbuf_get(const void *src, size_t src_len, DEBUG("6lo rfrag: entry %p (%s, ", (void *)(&rbuf[i]), ng_netif_addr_to_str(l2addr_str, sizeof(l2addr_str), rbuf[i].src, rbuf[i].src_len)); - DEBUG("%s, %u, %" PRIu16 ") found\n", + DEBUG("%s, %u, %u) found\n", ng_netif_addr_to_str(l2addr_str, sizeof(l2addr_str), rbuf[i].dst, rbuf[i].dst_len), - rbuf[i].datagram_size, rbuf[i].tag); + (unsigned)rbuf[i].pkt->size, rbuf[i].tag); rbuf[i].arrival = now.seconds; return &(rbuf[i]); } @@ -315,15 +296,16 @@ static rbuf_t *_rbuf_get(const void *src, size_t src_len, res->src_len = src_len; res->dst_len = dst_len; res->tag = tag; - res->datagram_size = size; res->cur_size = 0; + res->compressed = 1; DEBUG("6lo rfrag: entry %p (%s, ", (void *)res, ng_netif_addr_to_str(l2addr_str, sizeof(l2addr_str), res->src, res->src_len)); - DEBUG("%s, %u, %" PRIu16 ") created\n", + DEBUG("%s, %u, %u) created\n", ng_netif_addr_to_str(l2addr_str, sizeof(l2addr_str), res->dst, - res->dst_len), res->datagram_size, res->tag); + res->dst_len), (unsigned)res->pkt->size, + res->tag); } return res; diff --git a/sys/net/network_layer/ng_sixlowpan/frag/rbuf.h b/sys/net/network_layer/ng_sixlowpan/frag/rbuf.h index 61675f856b..2a96ff6556 100644 --- a/sys/net/network_layer/ng_sixlowpan/frag/rbuf.h +++ b/sys/net/network_layer/ng_sixlowpan/frag/rbuf.h @@ -77,8 +77,8 @@ typedef struct { uint8_t src_len; /**< length of source address */ uint8_t dst_len; /**< length of destination address */ uint16_t tag; /**< the datagram's tag */ - uint16_t datagram_size; /**< the datagram's size (without 6lo dispatches) */ uint16_t cur_size; /**< the datagram's current size */ + uint16_t compressed; /**< the datagram has a compressed header */ } rbuf_t; /** diff --git a/sys/net/network_layer/ng_sixlowpan/ng_sixlowpan.c b/sys/net/network_layer/ng_sixlowpan/ng_sixlowpan.c index 0acdd4f599..b89d48251e 100644 --- a/sys/net/network_layer/ng_sixlowpan/ng_sixlowpan.c +++ b/sys/net/network_layer/ng_sixlowpan/ng_sixlowpan.c @@ -146,18 +146,31 @@ static void _receive(ng_pktsnip_t *pkt) } } +static inline bool _add_uncompr_disp(ng_pktsnip_t *pkt) +{ + ng_pktsnip_t *sixlowpan; + uint8_t *disp; + + DEBUG("6lo: Send uncompressed\n"); + + sixlowpan = ng_pktbuf_add(NULL, NULL, sizeof(uint8_t), NG_NETTYPE_SIXLOWPAN); + + if (sixlowpan == NULL) { + return false; + } + sixlowpan->next = pkt->next; + pkt->next = sixlowpan; + disp = sixlowpan->data; + disp[0] = NG_SIXLOWPAN_UNCOMPRESSED; + return true; +} + static void _send(ng_pktsnip_t *pkt) { ng_netif_hdr_t *hdr; - ng_pktsnip_t *ipv6, *sixlowpan; + ng_pktsnip_t *pkt2; ng_sixlowpan_netif_t *iface; - /* cppcheck: datagram_size will be read by frag */ - /* cppcheck-suppress unreadVariable */ - size_t payload_len, datagram_size; - uint16_t max_frag_size; - /* cppcheck: disp is needed in other build paths on this level already */ - /* cppcheck-suppress variableScope */ - uint8_t *disp; + size_t datagram_size, dispatch_len = 0; if ((pkt == NULL) || (pkt->size < sizeof(ng_netif_hdr_t))) { DEBUG("6lo: Sending packet has no netif header\n"); @@ -165,33 +178,21 @@ static void _send(ng_pktsnip_t *pkt) return; } - hdr = pkt->data; - ipv6 = pkt->next; - - if ((ipv6 == NULL) || (ipv6->type != NG_NETTYPE_IPV6)) { + if ((pkt->next == NULL) || (pkt->next->type != NG_NETTYPE_IPV6)) { DEBUG("6lo: Sending packet has no IPv6 header\n"); ng_pktbuf_release(pkt); return; } - /* payload length and datagram size are different in that the payload - * length is the length of the IPv6 datagram + 6LoWPAN dispatches, - * while the datagram size is the size of only the IPv6 datagram */ - payload_len = ng_pkt_len(ipv6); - /* cppcheck: datagram_size will be read by ng_sixlowpan_frag implementation */ - /* cppcheck-suppress unreadVariable */ - datagram_size = (uint16_t)payload_len; + pkt2 = ng_pktbuf_start_write(pkt); - /* use sixlowpan packet snip as temporary one */ - sixlowpan = ng_pktbuf_start_write(pkt); - - if (sixlowpan == NULL) { + if (pkt2 == NULL) { DEBUG("6lo: no space left in packet buffer\n"); ng_pktbuf_release(pkt); return; } - pkt = sixlowpan; + hdr = pkt2->data; iface = ng_sixlowpan_netif_get(hdr->if_pid); if (iface == NULL) { @@ -212,73 +213,59 @@ static void _send(ng_pktsnip_t *pkt) #ifdef MODULE_NG_SIXLOWPAN_IPHC if (iface->iphc_enabled) { - if (!ng_sixlowpan_iphc_encode(pkt)) { + if (!ng_sixlowpan_iphc_encode(pkt2)) { DEBUG("6lo: error on IPHC encoding\n"); - ng_pktbuf_release(pkt); + ng_pktbuf_release(pkt2); return; } + /* IPHC dispatch does not count on dispatch length since it _shortens_ + * the datagram */ } else { - DEBUG("6lo: Send uncompressed\n"); - - sixlowpan = ng_pktbuf_add(NULL, NULL, sizeof(uint8_t), - NG_NETTYPE_SIXLOWPAN); - - if (sixlowpan == NULL) { + if (!_add_uncompr_disp(pkt2)) { + /* adding uncompressed dispatch failed */ DEBUG("6lo: no space left in packet buffer\n"); - ng_pktbuf_release(pkt); + ng_pktbuf_release(pkt2); return; } - - sixlowpan->next = ipv6; - pkt->next = sixlowpan; - disp = sixlowpan->data; - disp[0] = NG_SIXLOWPAN_UNCOMPRESSED; - payload_len++; + dispatch_len += 1; } #else /* suppress clang-analyzer report about iface being not read */ (void) iface; - - DEBUG("6lo: Send uncompressed\n"); - - sixlowpan = ng_pktbuf_add(NULL, NULL, sizeof(uint8_t), NG_NETTYPE_SIXLOWPAN); - - if (sixlowpan == NULL) { + if (!_add_uncompr_disp(pkt2)) { + /* adding uncompressed dispatch failed */ DEBUG("6lo: no space left in packet buffer\n"); - ng_pktbuf_release(pkt); + ng_pktbuf_release(pkt2); return; } - - sixlowpan->next = ipv6; - pkt->next = sixlowpan; - disp = sixlowpan->data; - disp[0] = NG_SIXLOWPAN_UNCOMPRESSED; - payload_len++; + dispatch_len += 1; #endif + datagram_size = ng_pkt_len(pkt2->next); - DEBUG("6lo: max_frag_size = %" PRIu16 " for interface %" - PRIkernel_pid "\n", max_frag_size, hdr->if_pid); + DEBUG("6lo: iface->max_frag_size = %" PRIu16 " for interface %" + PRIkernel_pid "\n", iface->max_frag_size, hdr->if_pid); /* IP should not send anything here if it is not a 6LoWPAN interface, * so we don't need to check for NULL pointers */ - if (payload_len <= max_frag_size) { + if ((datagram_size + dispatch_len) <= iface->max_frag_size) { DEBUG("6lo: Send SND command for %p to %" PRIu16 "\n", - (void *)pkt, hdr->if_pid); - ng_netapi_send(hdr->if_pid, pkt); + (void *)pkt2, hdr->if_pid); + ng_netapi_send(hdr->if_pid, pkt2); return; } #ifdef MODULE_NG_SIXLOWPAN_FRAG else { DEBUG("6lo: Send fragmented (%u > %" PRIu16 ")\n", - (unsigned int)payload_len, max_frag_size); - ng_sixlowpan_frag_send(hdr->if_pid, pkt, payload_len, datagram_size); + (unsigned int)datagram_size + dispatch_len, iface->max_frag_size); + ng_sixlowpan_frag_send(hdr->if_pid, pkt2, datagram_size + dispatch_len, + datagram_size); } #else (void)datagram_size; DEBUG("6lo: packet too big (%u> %" PRIu16 ")\n", - (unsigned int)payload_len, max_frag_size); + (unsigned int)(datagram_size + dispatch_len), iface->max_frag_size); #endif } -- GitLab