mirror of
https://github.com/RIOT-OS/RIOT.git
synced 2024-12-29 04:50:03 +01:00
Merge pull request #10988 from miri64/gnrc_sixlowpan_frag/enh/expose-interval-type
gnrc_sixlowpan_frag: prepare reassembly base types for VRB
This commit is contained in:
commit
b6655a2bba
@ -56,33 +56,65 @@ extern "C" {
|
||||
/** @} */
|
||||
|
||||
/**
|
||||
* @brief An entry in the 6LoWPAN reassembly buffer.
|
||||
* @brief Fragment intervals to identify limits of fragments and duplicates.
|
||||
*
|
||||
* A recipient of a fragment SHALL use
|
||||
* @note Fragments MUST NOT overlap and overlapping fragments are to be
|
||||
* discarded
|
||||
*
|
||||
* @see <a href="https://tools.ietf.org/html/rfc4944#section-5.3">
|
||||
* RFC 4944, section 5.3
|
||||
* </a>
|
||||
*/
|
||||
typedef struct gnrc_sixlowpan_rbuf_int {
|
||||
/**
|
||||
* @brief next element in fragment interval list
|
||||
*/
|
||||
struct gnrc_sixlowpan_rbuf_int *next;
|
||||
uint16_t start; /**< start byte of the fragment interval */
|
||||
uint16_t end; /**< end byte of the fragment interval */
|
||||
} gnrc_sixlowpan_rbuf_int_t;
|
||||
|
||||
/**
|
||||
* @brief Base class for both reassembly buffer and virtual reassembly buffer
|
||||
*
|
||||
* 1. the source address,
|
||||
* 2. the destination address,
|
||||
* 3. the datagram size (gnrc_pktsnip_t::size of rbuf_t::pkt), and
|
||||
* 3. the datagram size, 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)
|
||||
* @see https://tools.ietf.org/html/draft-ietf-lwig-6lowpan-virtual-reassembly-01
|
||||
*/
|
||||
typedef struct {
|
||||
/**
|
||||
* @brief The reassembled packet in the packet buffer
|
||||
*/
|
||||
gnrc_pktsnip_t *pkt;
|
||||
gnrc_sixlowpan_rbuf_int_t *ints; /**< intervals of already received fragments */
|
||||
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 */
|
||||
uint16_t datagram_size; /**< the datagram's size */
|
||||
/**
|
||||
* @brief The number of bytes currently received of the complete datagram
|
||||
*/
|
||||
uint16_t current_size;
|
||||
uint32_t arrival; /**< time in microseconds of arrival of
|
||||
* last received fragment */
|
||||
} gnrc_sixlowpan_rbuf_base_t;
|
||||
|
||||
/**
|
||||
* @brief An entry in the 6LoWPAN reassembly buffer.
|
||||
*
|
||||
* A recipient of a fragment SHALL use
|
||||
*
|
||||
*/
|
||||
typedef struct {
|
||||
gnrc_sixlowpan_rbuf_base_t super; /**< base class */
|
||||
/**
|
||||
* @brief The reassembled packet in the packet buffer
|
||||
*/
|
||||
gnrc_pktsnip_t *pkt;
|
||||
} gnrc_sixlowpan_rbuf_t;
|
||||
|
||||
/**
|
||||
@ -137,6 +169,13 @@ void gnrc_sixlowpan_frag_recv(gnrc_pktsnip_t *pkt, void *ctx, unsigned page);
|
||||
*/
|
||||
uint16_t gnrc_sixlowpan_frag_next_tag(void);
|
||||
|
||||
/**
|
||||
* @brief Remove base entry
|
||||
*
|
||||
* @param[in,out] entry Entry to remove
|
||||
*/
|
||||
void gnrc_sixlowpan_frag_rbuf_base_rm(gnrc_sixlowpan_rbuf_base_t *entry);
|
||||
|
||||
/**
|
||||
* @brief Garbage collect reassembly buffer.
|
||||
*/
|
||||
|
@ -329,6 +329,19 @@ uint16_t gnrc_sixlowpan_frag_next_tag(void)
|
||||
return (++_current_tag);
|
||||
}
|
||||
|
||||
void gnrc_sixlowpan_frag_rbuf_base_rm(gnrc_sixlowpan_rbuf_base_t *entry)
|
||||
{
|
||||
while (entry->ints != NULL) {
|
||||
gnrc_sixlowpan_rbuf_int_t *next = entry->ints->next;
|
||||
|
||||
entry->ints->start = 0;
|
||||
entry->ints->end = 0;
|
||||
entry->ints->next = NULL;
|
||||
entry->ints = next;
|
||||
}
|
||||
entry->datagram_size = 0;
|
||||
}
|
||||
|
||||
void gnrc_sixlowpan_frag_rbuf_gc(void)
|
||||
{
|
||||
rbuf_gc();
|
||||
@ -337,7 +350,7 @@ void gnrc_sixlowpan_frag_rbuf_gc(void)
|
||||
void gnrc_sixlowpan_frag_rbuf_remove(gnrc_sixlowpan_rbuf_t *rbuf)
|
||||
{
|
||||
assert(rbuf != NULL);
|
||||
rbuf_rm((rbuf_t *)rbuf);
|
||||
rbuf_rm(rbuf);
|
||||
}
|
||||
|
||||
void gnrc_sixlowpan_frag_rbuf_dispatch_when_complete(gnrc_sixlowpan_rbuf_t *rbuf,
|
||||
@ -345,11 +358,11 @@ void gnrc_sixlowpan_frag_rbuf_dispatch_when_complete(gnrc_sixlowpan_rbuf_t *rbuf
|
||||
{
|
||||
assert(rbuf);
|
||||
assert(netif_hdr);
|
||||
if (rbuf->current_size == rbuf->pkt->size) {
|
||||
gnrc_pktsnip_t *netif = gnrc_netif_hdr_build(rbuf->src,
|
||||
rbuf->src_len,
|
||||
rbuf->dst,
|
||||
rbuf->dst_len);
|
||||
if (rbuf->super.current_size == rbuf->pkt->size) {
|
||||
gnrc_pktsnip_t *netif = gnrc_netif_hdr_build(rbuf->super.src,
|
||||
rbuf->super.src_len,
|
||||
rbuf->super.dst,
|
||||
rbuf->super.dst_len);
|
||||
|
||||
if (netif == NULL) {
|
||||
DEBUG("6lo rbuf: error allocating netif header\n");
|
||||
|
@ -42,9 +42,9 @@
|
||||
#define RBUF_INT_SIZE (DIV_CEIL(IPV6_MIN_MTU, GNRC_SIXLOWPAN_FRAG_SIZE) * RBUF_SIZE)
|
||||
#endif
|
||||
|
||||
static rbuf_int_t rbuf_int[RBUF_INT_SIZE];
|
||||
static gnrc_sixlowpan_rbuf_int_t rbuf_int[RBUF_INT_SIZE];
|
||||
|
||||
static rbuf_t rbuf[RBUF_SIZE];
|
||||
static gnrc_sixlowpan_rbuf_t rbuf[RBUF_SIZE];
|
||||
|
||||
static char l2addr_str[3 * IEEE802154_LONG_ADDRESS_LEN];
|
||||
|
||||
@ -55,15 +55,18 @@ static msg_t _gc_timer_msg = { .type = GNRC_SIXLOWPAN_MSG_FRAG_GC_RBUF };
|
||||
* internal function definitions
|
||||
* ------------------------------------*/
|
||||
/* checks whether start and end overlaps, but not identical to, given interval i */
|
||||
static inline bool _rbuf_int_overlap_partially(rbuf_int_t *i, uint16_t start, uint16_t end);
|
||||
static inline bool _rbuf_int_overlap_partially(gnrc_sixlowpan_rbuf_int_t *i,
|
||||
uint16_t start, uint16_t end);
|
||||
/* gets a free entry from interval buffer */
|
||||
static rbuf_int_t *_rbuf_int_get_free(void);
|
||||
static gnrc_sixlowpan_rbuf_int_t *_rbuf_int_get_free(void);
|
||||
/* update interval buffer of entry */
|
||||
static bool _rbuf_update_ints(rbuf_t *entry, uint16_t offset, size_t frag_size);
|
||||
static bool _rbuf_update_ints(gnrc_sixlowpan_rbuf_base_t *entry,
|
||||
uint16_t offset, size_t frag_size);
|
||||
/* gets an entry identified by its tupel */
|
||||
static rbuf_t *_rbuf_get(const void *src, size_t src_len,
|
||||
const void *dst, size_t dst_len,
|
||||
size_t size, uint16_t tag, unsigned page);
|
||||
static gnrc_sixlowpan_rbuf_t *_rbuf_get(const void *src, size_t src_len,
|
||||
const void *dst, size_t dst_len,
|
||||
size_t size, uint16_t tag,
|
||||
unsigned page);
|
||||
/* internal add to repeat add when fragments overlapped */
|
||||
static int _rbuf_add(gnrc_netif_hdr_t *netif_hdr, gnrc_pktsnip_t *pkt,
|
||||
size_t offset, unsigned page);
|
||||
@ -73,8 +76,35 @@ enum {
|
||||
RBUF_ADD_SUCCESS,
|
||||
RBUF_ADD_ERROR,
|
||||
RBUF_ADD_REPEAT,
|
||||
RBUF_ADD_DUPLICATE,
|
||||
};
|
||||
|
||||
static int _check_fragments(gnrc_sixlowpan_rbuf_base_t *entry,
|
||||
size_t frag_size, size_t offset)
|
||||
{
|
||||
gnrc_sixlowpan_rbuf_int_t *ptr = entry->ints;
|
||||
|
||||
/* If the fragment overlaps another fragment and differs in either the size
|
||||
* or the offset of the overlapped fragment, discards the datagram
|
||||
* https://tools.ietf.org/html/rfc4944#section-5.3 */
|
||||
while (ptr != NULL) {
|
||||
if (_rbuf_int_overlap_partially(ptr, offset, offset + frag_size - 1)) {
|
||||
|
||||
/* "A fresh reassembly may be commenced with the most recently
|
||||
* received link fragment"
|
||||
* https://tools.ietf.org/html/rfc4944#section-5.3 */
|
||||
return RBUF_ADD_REPEAT;
|
||||
}
|
||||
/* End was already checked in overlap check */
|
||||
if (ptr->start == offset) {
|
||||
DEBUG("6lo rbuf: fragment already in reassembly buffer");
|
||||
return RBUF_ADD_DUPLICATE;
|
||||
}
|
||||
ptr = ptr->next;
|
||||
}
|
||||
return RBUF_ADD_SUCCESS;
|
||||
}
|
||||
|
||||
void rbuf_add(gnrc_netif_hdr_t *netif_hdr, gnrc_pktsnip_t *pkt,
|
||||
size_t offset, unsigned page)
|
||||
{
|
||||
@ -86,9 +116,8 @@ void rbuf_add(gnrc_netif_hdr_t *netif_hdr, gnrc_pktsnip_t *pkt,
|
||||
static int _rbuf_add(gnrc_netif_hdr_t *netif_hdr, gnrc_pktsnip_t *pkt,
|
||||
size_t offset, unsigned page)
|
||||
{
|
||||
rbuf_t *entry;
|
||||
gnrc_sixlowpan_rbuf_t *entry;
|
||||
sixlowpan_frag_n_t *frag = pkt->data;
|
||||
rbuf_int_t *ptr;
|
||||
uint8_t *data = ((uint8_t *)pkt->data) + sizeof(sixlowpan_frag_t);
|
||||
size_t frag_size;
|
||||
|
||||
@ -109,8 +138,6 @@ static int _rbuf_add(gnrc_netif_hdr_t *netif_hdr, gnrc_pktsnip_t *pkt,
|
||||
return RBUF_ADD_ERROR;
|
||||
}
|
||||
|
||||
ptr = entry->ints;
|
||||
|
||||
/* dispatches in the first fragment are ignored */
|
||||
if (offset == 0) {
|
||||
frag_size = pkt->size - sizeof(sixlowpan_frag_t);
|
||||
@ -123,38 +150,28 @@ static int _rbuf_add(gnrc_netif_hdr_t *netif_hdr, gnrc_pktsnip_t *pkt,
|
||||
data++; /* FRAGN header is one byte longer (offset) */
|
||||
}
|
||||
|
||||
if ((offset + frag_size) > entry->super.pkt->size) {
|
||||
if ((offset + frag_size) > entry->super.datagram_size) {
|
||||
DEBUG("6lo rfrag: fragment too big for resulting datagram, discarding datagram\n");
|
||||
gnrc_pktbuf_release(entry->super.pkt);
|
||||
gnrc_pktbuf_release(entry->pkt);
|
||||
gnrc_pktbuf_release(pkt);
|
||||
rbuf_rm(entry);
|
||||
return RBUF_ADD_ERROR;
|
||||
}
|
||||
|
||||
/* If the fragment overlaps another fragment and differs in either the size
|
||||
* or the offset of the overlapped fragment, discards the datagram
|
||||
* https://tools.ietf.org/html/rfc4944#section-5.3 */
|
||||
while (ptr != NULL) {
|
||||
if (_rbuf_int_overlap_partially(ptr, offset, offset + frag_size - 1)) {
|
||||
switch (_check_fragments(&entry->super, frag_size, offset)) {
|
||||
case RBUF_ADD_REPEAT:
|
||||
DEBUG("6lo rfrag: overlapping intervals, discarding datagram\n");
|
||||
gnrc_pktbuf_release(entry->super.pkt);
|
||||
gnrc_pktbuf_release(entry->pkt);
|
||||
rbuf_rm(entry);
|
||||
|
||||
/* "A fresh reassembly may be commenced with the most recently
|
||||
* received link fragment"
|
||||
* https://tools.ietf.org/html/rfc4944#section-5.3 */
|
||||
return RBUF_ADD_REPEAT;
|
||||
}
|
||||
/* End was already checked in overlap check */
|
||||
if (ptr->start == offset) {
|
||||
DEBUG("6lo rbuf: fragment already in reassembly buffer");
|
||||
case RBUF_ADD_DUPLICATE:
|
||||
gnrc_pktbuf_release(pkt);
|
||||
return RBUF_ADD_SUCCESS;
|
||||
}
|
||||
ptr = ptr->next;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
if (_rbuf_update_ints(entry, offset, frag_size)) {
|
||||
if (_rbuf_update_ints(&entry->super, offset, frag_size)) {
|
||||
DEBUG("6lo rbuf: add fragment data\n");
|
||||
entry->super.current_size += (uint16_t)frag_size;
|
||||
if (offset == 0) {
|
||||
@ -163,12 +180,12 @@ static int _rbuf_add(gnrc_netif_hdr_t *netif_hdr, gnrc_pktsnip_t *pkt,
|
||||
gnrc_pktsnip_t *frag_hdr = gnrc_pktbuf_mark(pkt,
|
||||
sizeof(sixlowpan_frag_t), GNRC_NETTYPE_SIXLOWPAN);
|
||||
if (frag_hdr == NULL) {
|
||||
gnrc_pktbuf_release(entry->super.pkt);
|
||||
gnrc_pktbuf_release(entry->pkt);
|
||||
gnrc_pktbuf_release(pkt);
|
||||
rbuf_rm(entry);
|
||||
return RBUF_ADD_ERROR;
|
||||
}
|
||||
gnrc_sixlowpan_iphc_recv(pkt, &entry->super, 0);
|
||||
gnrc_sixlowpan_iphc_recv(pkt, entry, 0);
|
||||
return RBUF_ADD_SUCCESS;
|
||||
}
|
||||
else
|
||||
@ -177,22 +194,23 @@ static int _rbuf_add(gnrc_netif_hdr_t *netif_hdr, gnrc_pktsnip_t *pkt,
|
||||
data++;
|
||||
}
|
||||
}
|
||||
memcpy(((uint8_t *)entry->super.pkt->data) + offset, data,
|
||||
memcpy(((uint8_t *)entry->pkt->data) + offset, data,
|
||||
frag_size);
|
||||
}
|
||||
gnrc_sixlowpan_frag_rbuf_dispatch_when_complete(&entry->super, netif_hdr);
|
||||
gnrc_sixlowpan_frag_rbuf_dispatch_when_complete(entry, netif_hdr);
|
||||
gnrc_pktbuf_release(pkt);
|
||||
return RBUF_ADD_SUCCESS;
|
||||
}
|
||||
|
||||
static inline bool _rbuf_int_overlap_partially(rbuf_int_t *i, uint16_t start, uint16_t end)
|
||||
static inline bool _rbuf_int_overlap_partially(gnrc_sixlowpan_rbuf_int_t *i,
|
||||
uint16_t start, uint16_t end)
|
||||
{
|
||||
/* start and ends are both inclusive, so using <= for both */
|
||||
return ((i->start <= end) && (start <= i->end)) && /* overlaps */
|
||||
((start != i->start) || (end != i->end)); /* not identical */
|
||||
}
|
||||
|
||||
static rbuf_int_t *_rbuf_int_get_free(void)
|
||||
static gnrc_sixlowpan_rbuf_int_t *_rbuf_int_get_free(void)
|
||||
{
|
||||
for (unsigned int i = 0; i < RBUF_INT_SIZE; i++) {
|
||||
if (rbuf_int[i].end == 0) { /* start must be smaller than end anyways*/
|
||||
@ -203,23 +221,16 @@ static rbuf_int_t *_rbuf_int_get_free(void)
|
||||
return NULL;
|
||||
}
|
||||
|
||||
void rbuf_rm(rbuf_t *entry)
|
||||
void rbuf_rm(gnrc_sixlowpan_rbuf_t *entry)
|
||||
{
|
||||
while (entry->ints != NULL) {
|
||||
rbuf_int_t *next = entry->ints->next;
|
||||
|
||||
entry->ints->start = 0;
|
||||
entry->ints->end = 0;
|
||||
entry->ints->next = NULL;
|
||||
entry->ints = next;
|
||||
}
|
||||
|
||||
entry->super.pkt = NULL;
|
||||
gnrc_sixlowpan_frag_rbuf_base_rm(&entry->super);
|
||||
entry->pkt = NULL;
|
||||
}
|
||||
|
||||
static bool _rbuf_update_ints(rbuf_t *entry, uint16_t offset, size_t frag_size)
|
||||
static bool _rbuf_update_ints(gnrc_sixlowpan_rbuf_base_t *entry,
|
||||
uint16_t offset, size_t frag_size)
|
||||
{
|
||||
rbuf_int_t *new;
|
||||
gnrc_sixlowpan_rbuf_int_t *new;
|
||||
uint16_t end = (uint16_t)(offset + frag_size - 1);
|
||||
|
||||
new = _rbuf_int_get_free();
|
||||
@ -233,13 +244,13 @@ static bool _rbuf_update_ints(rbuf_t *entry, uint16_t offset, size_t frag_size)
|
||||
new->end = end;
|
||||
|
||||
DEBUG("6lo rfrag: add interval (%" PRIu16 ", %" PRIu16 ") to entry (%s, ",
|
||||
new->start, new->end, gnrc_netif_addr_to_str(entry->super.src,
|
||||
entry->super.src_len,
|
||||
new->start, new->end, gnrc_netif_addr_to_str(entry->src,
|
||||
entry->src_len,
|
||||
l2addr_str));
|
||||
DEBUG("%s, %u, %u)\n", gnrc_netif_addr_to_str(entry->super.dst,
|
||||
entry->super.dst_len,
|
||||
DEBUG("%s, %u, %u)\n", gnrc_netif_addr_to_str(entry->dst,
|
||||
entry->dst_len,
|
||||
l2addr_str),
|
||||
(unsigned)entry->super.pkt->size, entry->super.tag);
|
||||
entry->datagram_size, entry->tag);
|
||||
|
||||
LL_PREPEND(entry->ints, new);
|
||||
|
||||
@ -253,8 +264,8 @@ void rbuf_gc(void)
|
||||
|
||||
for (i = 0; i < RBUF_SIZE; i++) {
|
||||
/* since pkt occupies pktbuf, aggressivly collect garbage */
|
||||
if ((rbuf[i].super.pkt != NULL) &&
|
||||
((now_usec - rbuf[i].arrival) > RBUF_TIMEOUT)) {
|
||||
if ((rbuf[i].pkt != NULL) &&
|
||||
((now_usec - rbuf[i].super.arrival) > RBUF_TIMEOUT)) {
|
||||
DEBUG("6lo rfrag: entry (%s, ",
|
||||
gnrc_netif_addr_to_str(rbuf[i].super.src,
|
||||
rbuf[i].super.src_len,
|
||||
@ -263,9 +274,9 @@ void rbuf_gc(void)
|
||||
gnrc_netif_addr_to_str(rbuf[i].super.dst,
|
||||
rbuf[i].super.dst_len,
|
||||
l2addr_str),
|
||||
(unsigned)rbuf[i].super.pkt->size, rbuf[i].super.tag);
|
||||
(unsigned)rbuf[i].super.datagram_size, rbuf[i].super.tag);
|
||||
|
||||
gnrc_pktbuf_release(rbuf[i].super.pkt);
|
||||
gnrc_pktbuf_release(rbuf[i].pkt);
|
||||
rbuf_rm(&(rbuf[i]));
|
||||
}
|
||||
}
|
||||
@ -276,16 +287,17 @@ static inline void _set_rbuf_timeout(void)
|
||||
xtimer_set_msg(&_gc_timer, RBUF_TIMEOUT, &_gc_timer_msg, sched_active_pid);
|
||||
}
|
||||
|
||||
static rbuf_t *_rbuf_get(const void *src, size_t src_len,
|
||||
const void *dst, size_t dst_len,
|
||||
size_t size, uint16_t tag, unsigned page)
|
||||
static gnrc_sixlowpan_rbuf_t *_rbuf_get(const void *src, size_t src_len,
|
||||
const void *dst, size_t dst_len,
|
||||
size_t size, uint16_t tag,
|
||||
unsigned page)
|
||||
{
|
||||
rbuf_t *res = NULL, *oldest = NULL;
|
||||
gnrc_sixlowpan_rbuf_t *res = NULL, *oldest = NULL;
|
||||
uint32_t now_usec = xtimer_now_usec();
|
||||
|
||||
for (unsigned int i = 0; i < RBUF_SIZE; i++) {
|
||||
/* check first if entry already available */
|
||||
if ((rbuf[i].super.pkt != NULL) && (rbuf[i].super.pkt->size == size) &&
|
||||
if ((rbuf[i].pkt != NULL) && (rbuf[i].super.datagram_size == size) &&
|
||||
(rbuf[i].super.tag == tag) && (rbuf[i].super.src_len == src_len) &&
|
||||
(rbuf[i].super.dst_len == dst_len) &&
|
||||
(memcmp(rbuf[i].super.src, src, src_len) == 0) &&
|
||||
@ -298,8 +310,8 @@ static rbuf_t *_rbuf_get(const void *src, size_t src_len,
|
||||
gnrc_netif_addr_to_str(rbuf[i].super.dst,
|
||||
rbuf[i].super.dst_len,
|
||||
l2addr_str),
|
||||
(unsigned)rbuf[i].super.pkt->size, rbuf[i].super.tag);
|
||||
rbuf[i].arrival = now_usec;
|
||||
(unsigned)rbuf[i].super.datagram_size, rbuf[i].super.tag);
|
||||
rbuf[i].super.arrival = now_usec;
|
||||
_set_rbuf_timeout();
|
||||
return &(rbuf[i]);
|
||||
}
|
||||
@ -311,7 +323,8 @@ static rbuf_t *_rbuf_get(const void *src, size_t src_len,
|
||||
|
||||
/* remember oldest slot */
|
||||
/* note that xtimer_now will overflow in ~1.2 hours */
|
||||
if ((oldest == NULL) || (oldest->arrival - rbuf[i].arrival < UINT32_MAX / 2)) {
|
||||
if ((oldest == NULL) ||
|
||||
(oldest->super.arrival - rbuf[i].super.arrival < UINT32_MAX / 2)) {
|
||||
oldest = &(rbuf[i]);
|
||||
}
|
||||
}
|
||||
@ -323,10 +336,10 @@ static rbuf_t *_rbuf_get(const void *src, size_t src_len,
|
||||
* oldest could have been picked as res) */
|
||||
assert(!rbuf_entry_empty(oldest));
|
||||
if (GNRC_SIXLOWPAN_FRAG_RBUF_AGGRESSIVE_OVERRIDE ||
|
||||
((now_usec - oldest->arrival) >
|
||||
((now_usec - oldest->super.arrival) >
|
||||
GNRC_SIXLOWPAN_FRAG_RBUF_TIMEOUT_US)) {
|
||||
DEBUG("6lo rfrag: reassembly buffer full, remove oldest entry\n");
|
||||
gnrc_pktbuf_release(oldest->super.pkt);
|
||||
gnrc_pktbuf_release(oldest->pkt);
|
||||
rbuf_rm(oldest);
|
||||
res = oldest;
|
||||
}
|
||||
@ -348,15 +361,16 @@ static rbuf_t *_rbuf_get(const void *src, size_t src_len,
|
||||
default:
|
||||
reass_type = GNRC_NETTYPE_UNDEF;
|
||||
}
|
||||
res->super.pkt = gnrc_pktbuf_add(NULL, NULL, size, reass_type);
|
||||
if (res->super.pkt == NULL) {
|
||||
res->pkt = gnrc_pktbuf_add(NULL, NULL, size, reass_type);
|
||||
if (res->pkt == NULL) {
|
||||
DEBUG("6lo rfrag: can not allocate reassembly buffer space.\n");
|
||||
return NULL;
|
||||
}
|
||||
|
||||
*((uint64_t *)res->super.pkt->data) = 0; /* clean first few bytes for later
|
||||
*((uint64_t *)res->pkt->data) = 0; /* clean first few bytes for later
|
||||
* look-ups */
|
||||
res->arrival = now_usec;
|
||||
res->super.datagram_size = size;
|
||||
res->super.arrival = now_usec;
|
||||
memcpy(res->super.src, src, src_len);
|
||||
memcpy(res->super.dst, dst, dst_len);
|
||||
res->super.src_len = src_len;
|
||||
@ -369,7 +383,7 @@ static rbuf_t *_rbuf_get(const void *src, size_t src_len,
|
||||
l2addr_str));
|
||||
DEBUG("%s, %u, %u) created\n",
|
||||
gnrc_netif_addr_to_str(res->super.dst, res->super.dst_len,
|
||||
l2addr_str), (unsigned)res->super.pkt->size,
|
||||
l2addr_str), res->super.datagram_size,
|
||||
res->super.tag);
|
||||
|
||||
_set_rbuf_timeout();
|
||||
@ -383,15 +397,15 @@ void rbuf_reset(void)
|
||||
xtimer_remove(&_gc_timer);
|
||||
memset(rbuf_int, 0, sizeof(rbuf_int));
|
||||
for (unsigned int i = 0; i < RBUF_SIZE; i++) {
|
||||
if ((rbuf[i].super.pkt != NULL) &&
|
||||
(rbuf[i].super.pkt->users > 0)) {
|
||||
gnrc_pktbuf_release(rbuf[i].super.pkt);
|
||||
if ((rbuf[i].pkt != NULL) &&
|
||||
(rbuf[i].pkt->users > 0)) {
|
||||
gnrc_pktbuf_release(rbuf[i].pkt);
|
||||
}
|
||||
}
|
||||
memset(rbuf, 0, sizeof(rbuf));
|
||||
}
|
||||
|
||||
const rbuf_t *rbuf_array(void)
|
||||
const gnrc_sixlowpan_rbuf_t *rbuf_array(void)
|
||||
{
|
||||
return &rbuf[0];
|
||||
}
|
||||
|
@ -40,40 +40,6 @@ extern "C" {
|
||||
#define RBUF_TIMEOUT (GNRC_SIXLOWPAN_FRAG_RBUF_TIMEOUT_US)
|
||||
/** @} */
|
||||
|
||||
/**
|
||||
* @brief Fragment intervals to identify limits of fragments.
|
||||
*
|
||||
* @note Fragments MUST NOT overlap and overlapping fragments are to be
|
||||
* discarded
|
||||
*
|
||||
* @see <a href="https://tools.ietf.org/html/rfc4944#section-5.3">
|
||||
* RFC 4944, section 5.3
|
||||
* </a>
|
||||
*
|
||||
* @internal
|
||||
*/
|
||||
typedef struct rbuf_int {
|
||||
struct rbuf_int *next; /**< next element in interval list */
|
||||
uint16_t start; /**< start byte of interval */
|
||||
uint16_t end; /**< end byte of interval */
|
||||
} rbuf_int_t;
|
||||
|
||||
/**
|
||||
* @brief Internal representation of the 6LoWPAN reassembly buffer.
|
||||
*
|
||||
* Additional members help with correct reassembly of the buffer.
|
||||
*
|
||||
* @internal
|
||||
*
|
||||
* @extends gnrc_sixlowpan_rbuf_t
|
||||
*/
|
||||
typedef struct {
|
||||
gnrc_sixlowpan_rbuf_t super; /**< exposed part of the reassembly buffer */
|
||||
rbuf_int_t *ints; /**< intervals of the fragment */
|
||||
uint32_t arrival; /**< time in microseconds of arrival of
|
||||
* last received fragment */
|
||||
} rbuf_t;
|
||||
|
||||
/**
|
||||
* @brief Adds a new fragment to the reassembly buffer. If the packet is
|
||||
* complete, dispatch the packet with the transmit information of
|
||||
@ -106,7 +72,7 @@ void rbuf_gc(void);
|
||||
*
|
||||
* @internal
|
||||
*/
|
||||
void rbuf_rm(rbuf_t *rbuf);
|
||||
void rbuf_rm(gnrc_sixlowpan_rbuf_t *rbuf);
|
||||
|
||||
/**
|
||||
* @brief Checks if a reassembly buffer entry is unset
|
||||
@ -118,8 +84,8 @@ void rbuf_rm(rbuf_t *rbuf);
|
||||
*
|
||||
* @internal
|
||||
*/
|
||||
static inline bool rbuf_entry_empty(const rbuf_t *rbuf) {
|
||||
return (rbuf->super.pkt == NULL);
|
||||
static inline bool rbuf_entry_empty(const gnrc_sixlowpan_rbuf_t *rbuf) {
|
||||
return (rbuf->pkt == NULL);
|
||||
}
|
||||
|
||||
#if defined(TEST_SUITES) || defined(DOXYGEN)
|
||||
@ -139,7 +105,7 @@ void rbuf_reset(void);
|
||||
* access is immediately spotted at compile time of tests. The `const`
|
||||
* qualifier may however be discarded if required by the tests.
|
||||
*/
|
||||
const rbuf_t *rbuf_array(void);
|
||||
const gnrc_sixlowpan_rbuf_t *rbuf_array(void);
|
||||
#endif
|
||||
|
||||
#ifdef __cplusplus
|
||||
|
@ -556,7 +556,7 @@ void gnrc_sixlowpan_iphc_recv(gnrc_pktsnip_t *sixlo, void *rbuf_ptr,
|
||||
uint16_t payload_len;
|
||||
if (rbuf != NULL) {
|
||||
/* for a fragmented datagram we know the overall length already */
|
||||
payload_len = (uint16_t)(rbuf->pkt->size - sizeof(ipv6_hdr_t));
|
||||
payload_len = (uint16_t)(rbuf->super.datagram_size - sizeof(ipv6_hdr_t));
|
||||
}
|
||||
else {
|
||||
/* set IPv6 header payload length field to the length of whatever is left
|
||||
@ -577,7 +577,7 @@ void gnrc_sixlowpan_iphc_recv(gnrc_pktsnip_t *sixlo, void *rbuf_ptr,
|
||||
((uint8_t *)sixlo->data) + payload_offset,
|
||||
sixlo->size - payload_offset);
|
||||
if (rbuf != NULL) {
|
||||
rbuf->current_size += (uncomp_hdr_len - payload_offset);
|
||||
rbuf->super.current_size += (uncomp_hdr_len - payload_offset);
|
||||
gnrc_sixlowpan_frag_rbuf_dispatch_when_complete(rbuf, netif_hdr);
|
||||
}
|
||||
else {
|
||||
|
@ -204,9 +204,9 @@ static void _set_up(void)
|
||||
_set_fragment_offset(_fragment4, TEST_FRAGMENT4_OFFSET);
|
||||
}
|
||||
|
||||
static const rbuf_t *_first_non_empty_rbuf(void)
|
||||
static const gnrc_sixlowpan_rbuf_t *_first_non_empty_rbuf(void)
|
||||
{
|
||||
const rbuf_t *rbuf = rbuf_array();
|
||||
const gnrc_sixlowpan_rbuf_t *rbuf = rbuf_array();
|
||||
|
||||
for (unsigned i = 0; i < RBUF_SIZE; i++) {
|
||||
if (!rbuf_entry_empty(&rbuf[i])) {
|
||||
@ -216,12 +216,13 @@ static const rbuf_t *_first_non_empty_rbuf(void)
|
||||
return NULL;
|
||||
}
|
||||
|
||||
static void _test_entry(const rbuf_t *entry, unsigned exp_current_size,
|
||||
static void _test_entry(const gnrc_sixlowpan_rbuf_t *entry,
|
||||
unsigned exp_current_size,
|
||||
unsigned exp_int_start, unsigned exp_int_end)
|
||||
{
|
||||
TEST_ASSERT_NOT_NULL(entry);
|
||||
TEST_ASSERT_NOT_NULL(entry->super.pkt);
|
||||
TEST_ASSERT_EQUAL_INT(TEST_DATAGRAM_SIZE, entry->super.pkt->size);
|
||||
TEST_ASSERT_NOT_NULL(entry->pkt);
|
||||
TEST_ASSERT_EQUAL_INT(TEST_DATAGRAM_SIZE, entry->pkt->size);
|
||||
TEST_ASSERT_EQUAL_INT(sizeof(_test_netif_hdr_src),
|
||||
entry->super.src_len);
|
||||
TEST_ASSERT_MESSAGE(memcmp(entry->super.src, _test_netif_hdr_src,
|
||||
@ -234,16 +235,16 @@ static void _test_entry(const rbuf_t *entry, unsigned exp_current_size,
|
||||
"entry->super.dst != TEST_NETIF_HDR_DST");
|
||||
TEST_ASSERT_EQUAL_INT(TEST_TAG, entry->super.tag);
|
||||
TEST_ASSERT_EQUAL_INT(exp_current_size, entry->super.current_size);
|
||||
TEST_ASSERT_NOT_NULL(entry->ints);
|
||||
TEST_ASSERT_NULL(entry->ints->next);
|
||||
TEST_ASSERT_EQUAL_INT(exp_int_start, entry->ints->start);
|
||||
TEST_ASSERT_EQUAL_INT(exp_int_end, entry->ints->end);
|
||||
TEST_ASSERT_NOT_NULL(entry->super.ints);
|
||||
TEST_ASSERT_NULL(entry->super.ints->next);
|
||||
TEST_ASSERT_EQUAL_INT(exp_int_start, entry->super.ints->start);
|
||||
TEST_ASSERT_EQUAL_INT(exp_int_end, entry->super.ints->end);
|
||||
}
|
||||
|
||||
static void _check_pktbuf(const rbuf_t *entry)
|
||||
static void _check_pktbuf(const gnrc_sixlowpan_rbuf_t *entry)
|
||||
{
|
||||
if (entry != NULL) {
|
||||
gnrc_pktbuf_release(entry->super.pkt);
|
||||
gnrc_pktbuf_release(entry->pkt);
|
||||
}
|
||||
TEST_ASSERT_MESSAGE(gnrc_pktbuf_is_empty(), "Packet buffer is not empty");
|
||||
}
|
||||
@ -252,7 +253,7 @@ static void test_rbuf_add__success_first_fragment(void)
|
||||
{
|
||||
gnrc_pktsnip_t *pkt = gnrc_pktbuf_add(NULL, _fragment1, sizeof(_fragment1),
|
||||
GNRC_NETTYPE_SIXLOWPAN);
|
||||
const rbuf_t *entry;
|
||||
const gnrc_sixlowpan_rbuf_t *entry;
|
||||
|
||||
TEST_ASSERT_NOT_NULL(pkt);
|
||||
rbuf_add(&_test_netif_hdr.hdr, pkt, TEST_FRAGMENT1_OFFSET, TEST_PAGE);
|
||||
@ -268,7 +269,7 @@ static void test_rbuf_add__success_subsequent_fragment(void)
|
||||
{
|
||||
gnrc_pktsnip_t *pkt = gnrc_pktbuf_add(NULL, _fragment2, sizeof(_fragment2),
|
||||
GNRC_NETTYPE_SIXLOWPAN);
|
||||
const rbuf_t *entry;
|
||||
const gnrc_sixlowpan_rbuf_t *entry;
|
||||
|
||||
TEST_ASSERT_NOT_NULL(pkt);
|
||||
rbuf_add(&_test_netif_hdr.hdr, pkt, TEST_FRAGMENT2_OFFSET, TEST_PAGE);
|
||||
@ -286,7 +287,7 @@ static void test_rbuf_add__success_duplicate_fragments(void)
|
||||
GNRC_NETTYPE_SIXLOWPAN);
|
||||
gnrc_pktsnip_t *pkt2 = gnrc_pktbuf_add(NULL, _fragment3, sizeof(_fragment3),
|
||||
GNRC_NETTYPE_SIXLOWPAN);
|
||||
const rbuf_t *entry;
|
||||
const gnrc_sixlowpan_rbuf_t *entry;
|
||||
|
||||
TEST_ASSERT_NOT_NULL(pkt1);
|
||||
rbuf_add(&_test_netif_hdr.hdr, pkt1, TEST_FRAGMENT3_OFFSET, TEST_PAGE);
|
||||
@ -347,7 +348,7 @@ static void test_rbuf_add__success_complete(void)
|
||||
static void test_rbuf_add__full_rbuf(void)
|
||||
{
|
||||
gnrc_pktsnip_t *pkt;
|
||||
const rbuf_t *rbuf;
|
||||
const gnrc_sixlowpan_rbuf_t *rbuf;
|
||||
|
||||
for (unsigned i = 0; i < RBUF_SIZE; i++) {
|
||||
pkt = gnrc_pktbuf_add(NULL, _fragment1, sizeof(_fragment1),
|
||||
@ -365,20 +366,19 @@ static void test_rbuf_add__full_rbuf(void)
|
||||
TEST_PAGE);
|
||||
rbuf = rbuf_array();
|
||||
for (unsigned i = 0; i < RBUF_SIZE; i++) {
|
||||
const rbuf_t *entry = &rbuf[i];
|
||||
const gnrc_sixlowpan_rbuf_t *entry = &rbuf[i];
|
||||
|
||||
TEST_ASSERT_MESSAGE(!rbuf_entry_empty(entry),
|
||||
"Reassembly buffer entry unexpectedly empty");
|
||||
TEST_ASSERT((sizeof(_fragment1) - sizeof(sixlowpan_frag_t)) <
|
||||
entry->super.pkt->size);
|
||||
entry->pkt->size);
|
||||
TEST_ASSERT_MESSAGE(
|
||||
memcmp(entry->super.pkt->data,
|
||||
&_fragment1[sizeof(sixlowpan_frag_t)],
|
||||
memcmp(entry->pkt->data, &_fragment1[sizeof(sixlowpan_frag_t)],
|
||||
sizeof(_fragment1) - sizeof(sixlowpan_frag_t)) != 0,
|
||||
"Reassembly buffer contains fragment that was not supposed "
|
||||
"to fit");
|
||||
/* releasing pkt to check if packet buffer is empty in the end */
|
||||
gnrc_pktbuf_release(entry->super.pkt);
|
||||
gnrc_pktbuf_release(entry->pkt);
|
||||
}
|
||||
_check_pktbuf(NULL);
|
||||
}
|
||||
@ -409,7 +409,7 @@ static void test_rbuf_add__overlap_lhs(void)
|
||||
gnrc_pktsnip_t *pkt1 = gnrc_pktbuf_add(NULL, _fragment1, sizeof(_fragment1),
|
||||
GNRC_NETTYPE_SIXLOWPAN);
|
||||
gnrc_pktsnip_t *pkt2;
|
||||
const rbuf_t *rbuf;
|
||||
const gnrc_sixlowpan_rbuf_t *rbuf;
|
||||
unsigned rbuf_entries = 0;
|
||||
|
||||
_set_fragment_offset(_fragment2, pkt2_offset);
|
||||
@ -422,7 +422,7 @@ static void test_rbuf_add__overlap_lhs(void)
|
||||
rbuf_add(&_test_netif_hdr.hdr, pkt2, pkt2_offset, TEST_PAGE);
|
||||
rbuf = rbuf_array();
|
||||
for (unsigned i = 0; i < RBUF_SIZE; i++) {
|
||||
const rbuf_t *entry = &rbuf[i];
|
||||
const gnrc_sixlowpan_rbuf_t *entry = &rbuf[i];
|
||||
if (!rbuf_entry_empty(entry)) {
|
||||
static const size_t pkt3_offset = TEST_FRAGMENT3_OFFSET - 8U - 1;
|
||||
|
||||
@ -436,7 +436,7 @@ static void test_rbuf_add__overlap_lhs(void)
|
||||
TEST_FRAGMENT3_OFFSET - TEST_FRAGMENT2_OFFSET,
|
||||
(unsigned)pkt2_offset, (unsigned)pkt3_offset);
|
||||
/* releasing pkt to check if packet buffer is empty in the end */
|
||||
gnrc_pktbuf_release(entry->super.pkt);
|
||||
gnrc_pktbuf_release(entry->pkt);
|
||||
}
|
||||
}
|
||||
TEST_ASSERT_EQUAL_INT(1U, rbuf_entries);
|
||||
@ -451,7 +451,7 @@ static void test_rbuf_add__overlap_rhs(void)
|
||||
gnrc_pktsnip_t *pkt2;
|
||||
gnrc_pktsnip_t *pkt3 = gnrc_pktbuf_add(NULL, _fragment3, sizeof(_fragment3),
|
||||
GNRC_NETTYPE_SIXLOWPAN);
|
||||
const rbuf_t *rbuf;
|
||||
const gnrc_sixlowpan_rbuf_t *rbuf;
|
||||
unsigned rbuf_entries = 0;
|
||||
|
||||
_set_fragment_offset(_fragment2, pkt2_offset);
|
||||
@ -466,7 +466,7 @@ static void test_rbuf_add__overlap_rhs(void)
|
||||
rbuf_add(&_test_netif_hdr.hdr, pkt2, pkt2_offset, TEST_PAGE);
|
||||
rbuf = rbuf_array();
|
||||
for (unsigned i = 0; i < RBUF_SIZE; i++) {
|
||||
const rbuf_t *entry = &rbuf[i];
|
||||
const gnrc_sixlowpan_rbuf_t *entry = &rbuf[i];
|
||||
if (!rbuf_entry_empty(entry)) {
|
||||
static const size_t pkt3_offset = TEST_FRAGMENT3_OFFSET + 8U - 1U;
|
||||
|
||||
@ -480,7 +480,7 @@ static void test_rbuf_add__overlap_rhs(void)
|
||||
TEST_FRAGMENT3_OFFSET - TEST_FRAGMENT2_OFFSET,
|
||||
(unsigned)pkt2_offset, (unsigned)pkt3_offset);
|
||||
/* releasing pkt to check if packet buffer is empty in the end */
|
||||
gnrc_pktbuf_release(entry->super.pkt);
|
||||
gnrc_pktbuf_release(entry->pkt);
|
||||
}
|
||||
}
|
||||
TEST_ASSERT_EQUAL_INT(1U, rbuf_entries);
|
||||
@ -489,7 +489,7 @@ static void test_rbuf_add__overlap_rhs(void)
|
||||
|
||||
static void test_rbuf_rm(void)
|
||||
{
|
||||
const rbuf_t *entry;
|
||||
const gnrc_sixlowpan_rbuf_t *entry;
|
||||
|
||||
test_rbuf_add__success_first_fragment();
|
||||
entry = _first_non_empty_rbuf();
|
||||
@ -497,7 +497,7 @@ static void test_rbuf_rm(void)
|
||||
TEST_ASSERT_NOT_NULL(entry);
|
||||
/* intentionally discarding const qualifier since we enter rbuf's internal
|
||||
* context again */
|
||||
rbuf_rm((rbuf_t *)entry);
|
||||
rbuf_rm((gnrc_sixlowpan_rbuf_t *)entry);
|
||||
/* reassembly buffer is now empty */
|
||||
TEST_ASSERT_NULL(_first_non_empty_rbuf());
|
||||
_check_pktbuf(NULL);
|
||||
@ -507,15 +507,15 @@ static void test_rbuf_gc__manually(void)
|
||||
{
|
||||
gnrc_pktsnip_t *pkt = gnrc_pktbuf_add(NULL, _fragment1, sizeof(_fragment1),
|
||||
GNRC_NETTYPE_SIXLOWPAN);
|
||||
rbuf_t *entry;
|
||||
gnrc_sixlowpan_rbuf_t *entry;
|
||||
|
||||
TEST_ASSERT_NOT_NULL(pkt);
|
||||
rbuf_add(&_test_netif_hdr.hdr, pkt, TEST_FRAGMENT1_OFFSET, TEST_PAGE);
|
||||
/* discarding const qualifier intentionally to override `arrival` */
|
||||
entry = (rbuf_t *)_first_non_empty_rbuf();
|
||||
entry = (gnrc_sixlowpan_rbuf_t *)_first_non_empty_rbuf();
|
||||
TEST_ASSERT_NOT_NULL(entry);
|
||||
/* set arrival RBUF_TIMEOUT into the past */
|
||||
entry->arrival -= RBUF_TIMEOUT;
|
||||
entry->super.arrival -= RBUF_TIMEOUT;
|
||||
rbuf_gc();
|
||||
/* reassembly buffer is now empty */
|
||||
TEST_ASSERT_NULL(_first_non_empty_rbuf());
|
||||
@ -527,12 +527,12 @@ static void test_rbuf_gc__timed(void)
|
||||
msg_t msg;
|
||||
gnrc_pktsnip_t *pkt = gnrc_pktbuf_add(NULL, _fragment1, sizeof(_fragment1),
|
||||
GNRC_NETTYPE_SIXLOWPAN);
|
||||
rbuf_t *entry;
|
||||
gnrc_sixlowpan_rbuf_t *entry;
|
||||
|
||||
TEST_ASSERT_NOT_NULL(pkt);
|
||||
rbuf_add(&_test_netif_hdr.hdr, pkt, TEST_FRAGMENT1_OFFSET, TEST_PAGE);
|
||||
/* discarding const qualifier intentionally to override `arrival` */
|
||||
entry = (rbuf_t *)_first_non_empty_rbuf();
|
||||
entry = (gnrc_sixlowpan_rbuf_t *)_first_non_empty_rbuf();
|
||||
TEST_ASSERT_NOT_NULL(entry);
|
||||
TEST_ASSERT_MESSAGE(
|
||||
xtimer_msg_receive_timeout(&msg, TEST_GC_TIMEOUT) >= 0,
|
||||
|
Loading…
Reference in New Issue
Block a user