Merge pull request #9352 from miri64/gnrc_sixlowpan_frag/enh/expose-rbuf
gnrc_sixlowpan_frag: expose (parts of) reassembly buffer
This commit is contained in:
commit
acb9e4aed2
@ -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" {
|
|||||||
*/
|
*/
|
||||||
#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];
|
|||||||
|
|
||||||
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,
|
|||||||
#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,
|
|||||||
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,
|
|||||||
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,
|
|||||||
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,
|
|||||||
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)
|
|||||||
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)
|
|||||||
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)
|
|||||||
|
|
||||||
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,
|
|||||||
|
|
||||||
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,
|
|||||||
/* 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 @@
|
|||||||
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 {
|
|||||||
} 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;
|
||||||
|
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user