Skip to content
Snippets Groups Projects
Unverified Commit acb9e4ae authored by Cenk Gündoğan's avatar Cenk Gündoğan Committed by GitHub
Browse files

Merge pull request #9352 from miri64/gnrc_sixlowpan_frag/enh/expose-rbuf

gnrc_sixlowpan_frag: expose (parts of) reassembly buffer
parents 99460669 86cbde2d
No related branches found
No related tags found
No related merge requests found
...@@ -31,6 +31,7 @@ ...@@ -31,6 +31,7 @@
#include "byteorder.h" #include "byteorder.h"
#include "kernel_types.h" #include "kernel_types.h"
#include "net/gnrc/pkt.h" #include "net/gnrc/pkt.h"
#include "net/ieee802154.h"
#include "net/sixlowpan.h" #include "net/sixlowpan.h"
#ifdef __cplusplus #ifdef __cplusplus
...@@ -42,6 +43,32 @@ extern "C" { ...@@ -42,6 +43,32 @@ extern "C" {
*/ */
#define GNRC_SIXLOWPAN_MSG_FRAG_SND (0x0225) #define GNRC_SIXLOWPAN_MSG_FRAG_SND (0x0225)
/**
* @brief An entry in the 6LoWPAN reassembly buffer.
*
* A recipient of a fragment SHALL use
*
* 1. the source address,
* 2. the destination address,
* 3. the datagram size (gnrc_pktsnip_t::size of rbuf_t::pkt), and
* 4. the datagram tag
*
* to identify all fragments that belong to the given datagram.
*
* @see [RFC 4944, section 5.3](https://tools.ietf.org/html/rfc4944#section-5.3)
*/
typedef struct {
/**
* @brief The reassembled packet in the packet buffer
*/
gnrc_pktsnip_t *pkt;
uint8_t src[IEEE802154_LONG_ADDRESS_LEN]; /**< source address */
uint8_t dst[IEEE802154_LONG_ADDRESS_LEN]; /**< destination address */
uint8_t src_len; /**< length of gnrc_sixlowpan_rbuf_t::src */
uint8_t dst_len; /**< length of gnrc_sixlowpan_rbuf_t::dst */
uint16_t tag; /**< the datagram's tag */
} gnrc_sixlowpan_rbuf_t;
/** /**
* @brief Definition of 6LoWPAN fragmentation type. * @brief Definition of 6LoWPAN fragmentation type.
*/ */
......
...@@ -46,7 +46,7 @@ static rbuf_int_t rbuf_int[RBUF_INT_SIZE]; ...@@ -46,7 +46,7 @@ static rbuf_int_t rbuf_int[RBUF_INT_SIZE];
static rbuf_t rbuf[RBUF_SIZE]; static rbuf_t rbuf[RBUF_SIZE];
static char l2addr_str[3 * RBUF_L2ADDR_MAX_LEN]; static char l2addr_str[3 * IEEE802154_LONG_ADDRESS_LEN];
/* ------------------------------------ /* ------------------------------------
* internal function definitions * internal function definitions
...@@ -100,11 +100,13 @@ void rbuf_add(gnrc_netif_hdr_t *netif_hdr, gnrc_pktsnip_t *pkt, ...@@ -100,11 +100,13 @@ void rbuf_add(gnrc_netif_hdr_t *netif_hdr, gnrc_pktsnip_t *pkt,
#ifdef MODULE_GNRC_SIXLOWPAN_IPHC #ifdef MODULE_GNRC_SIXLOWPAN_IPHC
else if (sixlowpan_iphc_is(data)) { else if (sixlowpan_iphc_is(data)) {
size_t iphc_len, nh_len = 0; size_t iphc_len, nh_len = 0;
iphc_len = gnrc_sixlowpan_iphc_decode(&entry->pkt, pkt, entry->pkt->size, iphc_len = gnrc_sixlowpan_iphc_decode(&entry->super.pkt, pkt,
sizeof(sixlowpan_frag_t), &nh_len); entry->super.pkt->size,
sizeof(sixlowpan_frag_t),
&nh_len);
if (iphc_len == 0) { if (iphc_len == 0) {
DEBUG("6lo rfrag: could not decode IPHC dispatch\n"); DEBUG("6lo rfrag: could not decode IPHC dispatch\n");
gnrc_pktbuf_release(entry->pkt); gnrc_pktbuf_release(entry->super.pkt);
_rbuf_rem(entry); _rbuf_rem(entry);
return; return;
} }
...@@ -121,9 +123,9 @@ void rbuf_add(gnrc_netif_hdr_t *netif_hdr, gnrc_pktsnip_t *pkt, ...@@ -121,9 +123,9 @@ void rbuf_add(gnrc_netif_hdr_t *netif_hdr, gnrc_pktsnip_t *pkt,
data++; /* FRAGN header is one byte longer (offset) */ data++; /* FRAGN header is one byte longer (offset) */
} }
if ((offset + frag_size) > entry->pkt->size) { if ((offset + frag_size) > entry->super.pkt->size) {
DEBUG("6lo rfrag: fragment too big for resulting datagram, discarding datagram\n"); DEBUG("6lo rfrag: fragment too big for resulting datagram, discarding datagram\n");
gnrc_pktbuf_release(entry->pkt); gnrc_pktbuf_release(entry->super.pkt);
_rbuf_rem(entry); _rbuf_rem(entry);
return; return;
} }
...@@ -134,7 +136,7 @@ void rbuf_add(gnrc_netif_hdr_t *netif_hdr, gnrc_pktsnip_t *pkt, ...@@ -134,7 +136,7 @@ void rbuf_add(gnrc_netif_hdr_t *netif_hdr, gnrc_pktsnip_t *pkt,
while (ptr != NULL) { while (ptr != NULL) {
if (_rbuf_int_overlap_partially(ptr, offset, offset + frag_size - 1)) { if (_rbuf_int_overlap_partially(ptr, offset, offset + frag_size - 1)) {
DEBUG("6lo rfrag: overlapping intervals, discarding datagram\n"); DEBUG("6lo rfrag: overlapping intervals, discarding datagram\n");
gnrc_pktbuf_release(entry->pkt); gnrc_pktbuf_release(entry->super.pkt);
_rbuf_rem(entry); _rbuf_rem(entry);
/* "A fresh reassembly may be commenced with the most recently /* "A fresh reassembly may be commenced with the most recently
...@@ -151,17 +153,19 @@ void rbuf_add(gnrc_netif_hdr_t *netif_hdr, gnrc_pktsnip_t *pkt, ...@@ -151,17 +153,19 @@ void rbuf_add(gnrc_netif_hdr_t *netif_hdr, gnrc_pktsnip_t *pkt,
if (_rbuf_update_ints(entry, offset, frag_size)) { if (_rbuf_update_ints(entry, offset, frag_size)) {
DEBUG("6lo rbuf: add fragment data\n"); DEBUG("6lo rbuf: add fragment data\n");
entry->cur_size += (uint16_t)frag_size; entry->cur_size += (uint16_t)frag_size;
memcpy(((uint8_t *)entry->pkt->data) + offset + data_offset, data, memcpy(((uint8_t *)entry->super.pkt->data) + offset + data_offset, data,
frag_size - data_offset); frag_size - data_offset);
} }
if (entry->cur_size == entry->pkt->size) { if (entry->cur_size == entry->super.pkt->size) {
gnrc_pktsnip_t *netif = gnrc_netif_hdr_build(entry->src, entry->src_len, gnrc_pktsnip_t *netif = gnrc_netif_hdr_build(entry->super.src,
entry->dst, entry->dst_len); entry->super.src_len,
entry->super.dst,
entry->super.dst_len);
if (netif == NULL) { if (netif == NULL) {
DEBUG("6lo rbuf: error allocating netif header\n"); DEBUG("6lo rbuf: error allocating netif header\n");
gnrc_pktbuf_release(entry->pkt); gnrc_pktbuf_release(entry->super.pkt);
_rbuf_rem(entry); _rbuf_rem(entry);
return; return;
} }
...@@ -175,8 +179,8 @@ void rbuf_add(gnrc_netif_hdr_t *netif_hdr, gnrc_pktsnip_t *pkt, ...@@ -175,8 +179,8 @@ void rbuf_add(gnrc_netif_hdr_t *netif_hdr, gnrc_pktsnip_t *pkt,
new_netif_hdr->flags = netif_hdr->flags; new_netif_hdr->flags = netif_hdr->flags;
new_netif_hdr->lqi = netif_hdr->lqi; new_netif_hdr->lqi = netif_hdr->lqi;
new_netif_hdr->rssi = netif_hdr->rssi; new_netif_hdr->rssi = netif_hdr->rssi;
LL_APPEND(entry->pkt, netif); LL_APPEND(entry->super.pkt, netif);
gnrc_sixlowpan_dispatch_recv(entry->pkt, NULL, 0); gnrc_sixlowpan_dispatch_recv(entry->super.pkt, NULL, 0);
_rbuf_rem(entry); _rbuf_rem(entry);
} }
} }
...@@ -210,7 +214,7 @@ static void _rbuf_rem(rbuf_t *entry) ...@@ -210,7 +214,7 @@ static void _rbuf_rem(rbuf_t *entry)
entry->ints = next; entry->ints = next;
} }
entry->pkt = NULL; entry->super.pkt = NULL;
} }
static bool _rbuf_update_ints(rbuf_t *entry, uint16_t offset, size_t frag_size) static bool _rbuf_update_ints(rbuf_t *entry, uint16_t offset, size_t frag_size)
...@@ -229,12 +233,13 @@ static bool _rbuf_update_ints(rbuf_t *entry, uint16_t offset, size_t frag_size) ...@@ -229,12 +233,13 @@ static bool _rbuf_update_ints(rbuf_t *entry, uint16_t offset, size_t frag_size)
new->end = end; new->end = end;
DEBUG("6lo rfrag: add interval (%" PRIu16 ", %" PRIu16 ") to entry (%s, ", DEBUG("6lo rfrag: add interval (%" PRIu16 ", %" PRIu16 ") to entry (%s, ",
new->start, new->end, gnrc_netif_addr_to_str(entry->src, new->start, new->end, gnrc_netif_addr_to_str(entry->super.src,
entry->src_len, entry->super.src_len,
l2addr_str)); l2addr_str));
DEBUG("%s, %u, %u)\n", gnrc_netif_addr_to_str(entry->dst, entry->dst_len, DEBUG("%s, %u, %u)\n", gnrc_netif_addr_to_str(entry->super.dst,
entry->super.dst_len,
l2addr_str), l2addr_str),
(unsigned)entry->pkt->size, entry->tag); (unsigned)entry->super.pkt->size, entry->super.tag);
LL_PREPEND(entry->ints, new); LL_PREPEND(entry->ints, new);
...@@ -248,17 +253,19 @@ static void _rbuf_gc(void) ...@@ -248,17 +253,19 @@ static void _rbuf_gc(void)
for (i = 0; i < RBUF_SIZE; i++) { for (i = 0; i < RBUF_SIZE; i++) {
/* since pkt occupies pktbuf, aggressivly collect garbage */ /* since pkt occupies pktbuf, aggressivly collect garbage */
if ((rbuf[i].pkt != NULL) && if ((rbuf[i].super.pkt != NULL) &&
((now_usec - rbuf[i].arrival) > RBUF_TIMEOUT)) { ((now_usec - rbuf[i].arrival) > RBUF_TIMEOUT)) {
DEBUG("6lo rfrag: entry (%s, ", DEBUG("6lo rfrag: entry (%s, ",
gnrc_netif_addr_to_str(rbuf[i].src, rbuf[i].src_len, gnrc_netif_addr_to_str(rbuf[i].super.src,
rbuf[i].super.src_len,
l2addr_str)); l2addr_str));
DEBUG("%s, %u, %u) timed out\n", DEBUG("%s, %u, %u) timed out\n",
gnrc_netif_addr_to_str(rbuf[i].dst, rbuf[i].dst_len, gnrc_netif_addr_to_str(rbuf[i].super.dst,
rbuf[i].super.dst_len,
l2addr_str), l2addr_str),
(unsigned)rbuf[i].pkt->size, rbuf[i].tag); (unsigned)rbuf[i].super.pkt->size, rbuf[i].super.tag);
gnrc_pktbuf_release(rbuf[i].pkt); gnrc_pktbuf_release(rbuf[i].super.pkt);
_rbuf_rem(&(rbuf[i])); _rbuf_rem(&(rbuf[i]));
} }
} }
...@@ -273,24 +280,26 @@ static rbuf_t *_rbuf_get(const void *src, size_t src_len, ...@@ -273,24 +280,26 @@ static rbuf_t *_rbuf_get(const void *src, size_t src_len,
for (unsigned int i = 0; i < RBUF_SIZE; i++) { for (unsigned int i = 0; i < RBUF_SIZE; i++) {
/* check first if entry already available */ /* check first if entry already available */
if ((rbuf[i].pkt != NULL) && (rbuf[i].pkt->size == size) && if ((rbuf[i].super.pkt != NULL) && (rbuf[i].super.pkt->size == size) &&
(rbuf[i].tag == tag) && (rbuf[i].src_len == src_len) && (rbuf[i].super.tag == tag) && (rbuf[i].super.src_len == src_len) &&
(rbuf[i].dst_len == dst_len) && (rbuf[i].super.dst_len == dst_len) &&
(memcmp(rbuf[i].src, src, src_len) == 0) && (memcmp(rbuf[i].super.src, src, src_len) == 0) &&
(memcmp(rbuf[i].dst, dst, dst_len) == 0)) { (memcmp(rbuf[i].super.dst, dst, dst_len) == 0)) {
DEBUG("6lo rfrag: entry %p (%s, ", (void *)(&rbuf[i]), DEBUG("6lo rfrag: entry %p (%s, ", (void *)(&rbuf[i]),
gnrc_netif_addr_to_str(rbuf[i].src, rbuf[i].src_len, gnrc_netif_addr_to_str(rbuf[i].super.src,
rbuf[i].super.src_len,
l2addr_str)); l2addr_str));
DEBUG("%s, %u, %u) found\n", DEBUG("%s, %u, %u) found\n",
gnrc_netif_addr_to_str(rbuf[i].dst, rbuf[i].dst_len, gnrc_netif_addr_to_str(rbuf[i].super.dst,
rbuf[i].super.dst_len,
l2addr_str), l2addr_str),
(unsigned)rbuf[i].pkt->size, rbuf[i].tag); (unsigned)rbuf[i].super.pkt->size, rbuf[i].super.tag);
rbuf[i].arrival = now_usec; rbuf[i].arrival = now_usec;
return &(rbuf[i]); return &(rbuf[i]);
} }
/* if there is a free spot: remember it */ /* if there is a free spot: remember it */
if ((res == NULL) && (rbuf[i].pkt == NULL)) { if ((res == NULL) && (rbuf[i].super.pkt == NULL)) {
res = &(rbuf[i]); res = &(rbuf[i]);
} }
...@@ -304,36 +313,39 @@ static rbuf_t *_rbuf_get(const void *src, size_t src_len, ...@@ -304,36 +313,39 @@ static rbuf_t *_rbuf_get(const void *src, size_t src_len,
/* entry not in buffer and no empty spot found */ /* entry not in buffer and no empty spot found */
if (res == NULL) { if (res == NULL) {
assert(oldest != NULL); assert(oldest != NULL);
assert(oldest->pkt != NULL); /* if oldest->pkt == NULL, res must not be NULL */ /* if oldest->pkt == NULL, res must not be NULL */
assert(oldest->super.pkt != NULL);
DEBUG("6lo rfrag: reassembly buffer full, remove oldest entry\n"); DEBUG("6lo rfrag: reassembly buffer full, remove oldest entry\n");
gnrc_pktbuf_release(oldest->pkt); gnrc_pktbuf_release(oldest->super.pkt);
_rbuf_rem(oldest); _rbuf_rem(oldest);
res = oldest; res = oldest;
} }
/* now we have an empty spot */ /* now we have an empty spot */
res->pkt = gnrc_pktbuf_add(NULL, NULL, size, GNRC_NETTYPE_IPV6); res->super.pkt = gnrc_pktbuf_add(NULL, NULL, size, GNRC_NETTYPE_IPV6);
if (res->pkt == NULL) { if (res->super.pkt == NULL) {
DEBUG("6lo rfrag: can not allocate reassembly buffer space.\n"); DEBUG("6lo rfrag: can not allocate reassembly buffer space.\n");
return NULL; return NULL;
} }
*((uint64_t *)res->pkt->data) = 0; /* clean first few bytes for later *((uint64_t *)res->super.pkt->data) = 0; /* clean first few bytes for later
* look-ups */ * look-ups */
res->arrival = now_usec; res->arrival = now_usec;
memcpy(res->src, src, src_len); memcpy(res->super.src, src, src_len);
memcpy(res->dst, dst, dst_len); memcpy(res->super.dst, dst, dst_len);
res->src_len = src_len; res->super.src_len = src_len;
res->dst_len = dst_len; res->super.dst_len = dst_len;
res->tag = tag; res->super.tag = tag;
res->cur_size = 0; res->cur_size = 0;
DEBUG("6lo rfrag: entry %p (%s, ", (void *)res, DEBUG("6lo rfrag: entry %p (%s, ", (void *)res,
gnrc_netif_addr_to_str(res->src, res->src_len, l2addr_str)); gnrc_netif_addr_to_str(res->super.src, res->super.src_len,
l2addr_str));
DEBUG("%s, %u, %u) created\n", DEBUG("%s, %u, %u) created\n",
gnrc_netif_addr_to_str(res->dst, res->dst_len, l2addr_str), (unsigned)res->pkt->size, gnrc_netif_addr_to_str(res->super.dst, res->super.dst_len,
res->tag); l2addr_str), (unsigned)res->super.pkt->size,
res->super.tag);
return res; return res;
} }
......
...@@ -30,7 +30,6 @@ ...@@ -30,7 +30,6 @@
extern "C" { extern "C" {
#endif #endif
#define RBUF_L2ADDR_MAX_LEN (8U) /**< maximum length for link-layer addresses */
#define RBUF_SIZE (4U) /**< size of the reassembly buffer */ #define RBUF_SIZE (4U) /**< size of the reassembly buffer */
#define RBUF_TIMEOUT (3U * US_PER_SEC) /**< timeout for reassembly in microseconds */ #define RBUF_TIMEOUT (3U * US_PER_SEC) /**< timeout for reassembly in microseconds */
...@@ -53,33 +52,19 @@ typedef struct rbuf_int { ...@@ -53,33 +52,19 @@ typedef struct rbuf_int {
} rbuf_int_t; } rbuf_int_t;
/** /**
* @brief An entry in the 6LoWPAN reassembly buffer. * @brief Internal representation of the 6LoWPAN reassembly buffer.
* *
* @details A receipient of a fragment SHALL use * Additional members help with correct reassembly of the buffer.
*
* 1. the source address,
* 2. the destination address,
* 3. the datagram size (gnrc_pktsnip_t::size of rbuf_t::pkt), and
* 4. the datagram tag
*
* to identify all fragments that belong to the given datagram.
*
* @see <a href="https://tools.ietf.org/html/rfc4944#section-5.3">
* RFC 4944, section 5.3
* </a>
* *
* @internal * @internal
*
* @extends gnrc_sixlowpan_rbuf_t
*/ */
typedef struct { typedef struct {
gnrc_sixlowpan_rbuf_t super; /**< exposed part of the reassembly buffer */
rbuf_int_t *ints; /**< intervals of the fragment */ rbuf_int_t *ints; /**< intervals of the fragment */
gnrc_pktsnip_t *pkt; /**< the reassembled packet in packet buffer */
uint32_t arrival; /**< time in microseconds of arrival of uint32_t arrival; /**< time in microseconds of arrival of
* last received fragment */ * last received fragment */
uint8_t src[RBUF_L2ADDR_MAX_LEN]; /**< source address */
uint8_t dst[RBUF_L2ADDR_MAX_LEN]; /**< destination address */
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 cur_size; /**< the datagram's current size */ uint16_t cur_size; /**< the datagram's current size */
} rbuf_t; } rbuf_t;
......
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment