From 7c0d86e3609470b0cba668b86aba01ac9dde646b Mon Sep 17 00:00:00 2001 From: Martine Lenders Date: Mon, 27 Apr 2015 21:44:42 +0200 Subject: [PATCH 1/3] ng_sixlowpan_frag: fix reassembly buffer --- .../network_layer/ng_sixlowpan/frag/rbuf.c | 109 +++++++++++------- .../network_layer/ng_sixlowpan/frag/rbuf.h | 1 + 2 files changed, 66 insertions(+), 44 deletions(-) diff --git a/sys/net/network_layer/ng_sixlowpan/frag/rbuf.c b/sys/net/network_layer/ng_sixlowpan/frag/rbuf.c index dab51fb62c..fd2f3badc0 100644 --- a/sys/net/network_layer/ng_sixlowpan/frag/rbuf.c +++ b/sys/net/network_layer/ng_sixlowpan/frag/rbuf.c @@ -67,6 +67,7 @@ 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, @@ -81,8 +82,42 @@ 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]) { + case NG_SIXLOWPAN_UNCOMPRESSED: + offset++; + + break; + + default: + break; + } + + data++; /* also don't take offset field */ + } + else { + switch (data[0]) { + case NG_SIXLOWPAN_UNCOMPRESSED: + dg_frag_size--; + + break; + + default: + break; + } + + } + + if ((offset + frag_size) > entry->pkt->size) { + DEBUG("6lo rfrag: fragment too big for resulting datagram, discarding datagram\n"); + ng_pktbuf_release(entry->pkt); + _rbuf_rem(entry); + return; + } + while (ptr != NULL) { - if (_rbuf_int_in(ptr, offset, offset + frag_size - 1)) { + if (_rbuf_int_in(ptr, offset, offset + dg_frag_size - 1)) { DEBUG("6lo rfrag: overlapping or same intervals, discarding datagram\n"); ng_pktbuf_release(entry->pkt); _rbuf_rem(entry); @@ -92,48 +127,31 @@ void rbuf_add(ng_netif_hdr_t *netif_hdr, ng_sixlowpan_frag_t *frag, ptr = ptr->next; } - if (_rbuf_update_ints(entry, offset, frag_size)) { - if (offset == 0) { + 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 */ - switch (data[0]) { - case NG_SIXLOWPAN_UNCOMPRESSED: - if (ng_pktbuf_realloc_data(entry->pkt, entry->pkt->size + 1) < 0) { - DEBUG("6lo rbuf: could not reallocate packet data.\n"); - return; - } - - /* move already inserted fragments 1 to the right */ - for (int i = entry->pkt->size - 1; i > 0; i--) { - uint8_t *d = ((uint8_t *)(entry->pkt->data)) + i; - *d = *(d - 1); - } - - default: - break; + 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; } - } - else { - data += 1; /* skip offset field in fragmentation header */ - } - /* also adapt offset according to stored dispatch */ - /* above case only applies for first fragment incoming, this for all */ - switch (*((uint8_t *)entry->pkt->data)) { - case NG_SIXLOWPAN_UNCOMPRESSED: - offset++; - break; - - default: - break; + /* 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); + } + } } DEBUG("6lo rbuf: add fragment data\n"); + entry->cur_size += (uint16_t)dg_frag_size; memcpy(((uint8_t *)entry->pkt->data) + offset, data, frag_size); - entry->cur_size += (uint16_t)frag_size; } - if (entry->cur_size == entry->pkt->size) { + if (entry->cur_size == entry->datagram_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); @@ -146,7 +164,7 @@ void rbuf_add(ng_netif_hdr_t *netif_hdr, ng_sixlowpan_frag_t *frag, netif_hdr = netif->data; netif_hdr->if_pid = iface; - entry->pkt->next = netif; + LL_APPEND(entry->pkt, netif); DEBUG("6lo rbuf: datagram complete, send to self\n"); ng_netapi_receive(thread_getpid(), entry->pkt); @@ -163,7 +181,7 @@ static inline bool _rbuf_int_in(rbuf_int_t *i, uint16_t start, uint16_t end) static rbuf_int_t *_rbuf_int_get_free(void) { - for (int i = 0; i < RBUF_INT_SIZE; i++) { + for (unsigned int i = 0; i < RBUF_INT_SIZE; i++) { if (rbuf_int[i].end == 0) { /* start must be smaller than end anyways*/ return rbuf_int + i; } @@ -205,7 +223,7 @@ static bool _rbuf_update_ints(rbuf_t *entry, uint16_t offset, size_t frag_size) new->start, new->end, ng_netif_addr_to_str(l2addr_str, sizeof(l2addr_str), entry->src, entry->src_len)); DEBUG("%s, %zu, %" PRIu16 ")\n", ng_netif_addr_to_str(l2addr_str, - sizeof(l2addr_str), entry->dst, entry->dst_len), entry->pkt->size, + sizeof(l2addr_str), entry->dst, entry->dst_len), entry->datagram_size, entry->tag); LL_PREPEND(entry->ints, new); @@ -217,7 +235,7 @@ static void _rbuf_gc(void) { rbuf_t *oldest = NULL; timex_t now; - int i; + unsigned int i; vtimer_now(&now); @@ -229,7 +247,7 @@ static void _rbuf_gc(void) DEBUG("%s, %zu, %" PRIu16 ") timed out\n", ng_netif_addr_to_str(l2addr_str, sizeof(l2addr_str), rbuf[i].dst, rbuf[i].dst_len), - rbuf[i].pkt->size, rbuf[i].tag); + rbuf[i].datagram_size, rbuf[i].tag); ng_pktbuf_release(rbuf[i].pkt); _rbuf_rem(&(rbuf[i])); @@ -239,7 +257,7 @@ static void _rbuf_gc(void) } } - if (((i >= RBUF_SIZE) && (oldest != NULL))) { + if ((i >= RBUF_SIZE) && (oldest != NULL) && (oldest->pkt != NULL)) { DEBUG("6lo rfrag: reassembly buffer full, remove oldest entry"); ng_pktbuf_release(oldest->pkt); _rbuf_rem(oldest); @@ -255,9 +273,9 @@ static rbuf_t *_rbuf_get(const void *src, size_t src_len, vtimer_now(&now); - for (int i = 0; i < RBUF_SIZE; i++) { + for (unsigned int i = 0; i < RBUF_SIZE; i++) { /* check first if entry already available */ - if ((rbuf[i].pkt != NULL) && (rbuf[i].pkt->size == size) && + if ((rbuf[i].pkt != NULL) && (rbuf[i].datagram_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) && @@ -267,8 +285,8 @@ static rbuf_t *_rbuf_get(const void *src, size_t src_len, DEBUG("%s, %zu, %" PRIu16 ") found\n", ng_netif_addr_to_str(l2addr_str, sizeof(l2addr_str), rbuf[i].dst, rbuf[i].dst_len), - rbuf[i].pkt->size, rbuf[i].tag); - res->arrival = now.seconds; + rbuf[i].datagram_size, rbuf[i].tag); + rbuf[i].arrival = now.seconds; return &(rbuf[i]); } @@ -280,6 +298,8 @@ static rbuf_t *_rbuf_get(const void *src, size_t src_len, if (res != NULL) { /* entry not in buffer but found empty spot */ res->pkt = ng_pktbuf_add(NULL, NULL, size, NG_NETTYPE_SIXLOWPAN); + *((uint64_t *)res->pkt->data) = 0; /* clean first few bytes for later + * look-ups */ if (res->pkt == NULL) { DEBUG("6lo rfrag: can not allocate reassembly buffer space.\n"); @@ -292,13 +312,14 @@ 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; DEBUG("6lo rfrag: entry (%s, ", ng_netif_addr_to_str(l2addr_str, sizeof(l2addr_str), res->src, res->src_len)); DEBUG("%s, %zu, %" PRIu16 ") created\n", ng_netif_addr_to_str(l2addr_str, sizeof(l2addr_str), res->dst, - res->dst_len), res->pkt->size, res->tag); + res->dst_len), res->datagram_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 bee9711184..61675f856b 100644 --- a/sys/net/network_layer/ng_sixlowpan/frag/rbuf.h +++ b/sys/net/network_layer/ng_sixlowpan/frag/rbuf.h @@ -77,6 +77,7 @@ 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 */ } rbuf_t; From 4f5995a4cf0ca82272a4d3436b0e1281cfe1dd4d Mon Sep 17 00:00:00 2001 From: Martine Lenders Date: Tue, 28 Apr 2015 13:44:20 +0200 Subject: [PATCH 2/3] ng_sixlowpan_frag: add missing return --- sys/net/network_layer/ng_sixlowpan/ng_sixlowpan.c | 1 + 1 file changed, 1 insertion(+) diff --git a/sys/net/network_layer/ng_sixlowpan/ng_sixlowpan.c b/sys/net/network_layer/ng_sixlowpan/ng_sixlowpan.c index 83a3c351dc..cbcbfb13b6 100644 --- a/sys/net/network_layer/ng_sixlowpan/ng_sixlowpan.c +++ b/sys/net/network_layer/ng_sixlowpan/ng_sixlowpan.c @@ -85,6 +85,7 @@ void _receive(ng_pktsnip_t *pkt) else if (ng_sixlowpan_frag_is((ng_sixlowpan_frag_t *)dispatch)) { DEBUG("6lo: received 6LoWPAN fragment\n"); ng_sixlowpan_frag_handle_pkt(pkt); + return; } #endif else { From 450abe615498185a5555aef6a51474ca5a6e084b Mon Sep 17 00:00:00 2001 From: Martine Lenders Date: Tue, 28 Apr 2015 14:51:06 +0200 Subject: [PATCH 3/3] ng_sixlowpan: use ng_pktbuf_remove_snip() --- sys/net/network_layer/ng_sixlowpan/ng_sixlowpan.c | 10 ++++++++-- 1 file changed, 8 insertions(+), 2 deletions(-) diff --git a/sys/net/network_layer/ng_sixlowpan/ng_sixlowpan.c b/sys/net/network_layer/ng_sixlowpan/ng_sixlowpan.c index cbcbfb13b6..adcf74197c 100644 --- a/sys/net/network_layer/ng_sixlowpan/ng_sixlowpan.c +++ b/sys/net/network_layer/ng_sixlowpan/ng_sixlowpan.c @@ -78,8 +78,14 @@ void _receive(ng_pktsnip_t *pkt) /* packet is uncompressed: just mark and remove the dispatch */ sixlowpan = ng_pktbuf_add(payload, payload->data, sizeof(uint8_t), NG_NETTYPE_SIXLOWPAN); - LL_DELETE(pkt, sixlowpan); - ng_pktbuf_release(sixlowpan); + + if (sixlowpan == NULL) { + DEBUG("6lo: can not mark 6LoWPAN dispatch\n"); + ng_pktbuf_release(pkt); + return; + } + + pkt = ng_pktbuf_remove_snip(pkt, sixlowpan); } #ifdef MODULE_NG_SIXLOWPAN_FRAG else if (ng_sixlowpan_frag_is((ng_sixlowpan_frag_t *)dispatch)) {