Skip to content
Snippets Groups Projects
Commit 254f16e8 authored by Martine Lenders's avatar Martine Lenders
Browse files

gnrc_sixlowpan_frag: add asynchronous rbuf GC

While the current approach for garbage collection in the 6Lo reassembly
buffer is good for best-effort handling of
*fragmented* packets and nicely RAM saving, it has the problem that
incomplete, huge datagrams can basically DoS a node, if no further
fragmented datagram is received for a while (since the packet buffer is
full and GC is not triggered).

This change adds a asynchronous GC (utilizing the existing
functionality) to the reassembly buffer, so that even if there is no new
fragmented packet received, fragments older than `RBUF_TIMEOUT` will be
removed from the reassembly buffer, freeing up the otherwise wasted
packet buffer space.
parent 6e6716a1
No related branches found
No related tags found
No related merge requests found
......@@ -38,10 +38,20 @@
extern "C" {
#endif
/**
* @name Message types
* @{
*/
/**
* @brief Message type for passing one 6LoWPAN fragment down the network stack
*/
#define GNRC_SIXLOWPAN_MSG_FRAG_SND (0x0225)
#define GNRC_SIXLOWPAN_MSG_FRAG_SND (0x0225)
/**
* @brief Message type for triggering garbage collection reassembly buffer
*/
#define GNRC_SIXLOWPAN_MSG_FRAG_GC_RBUF (0x0226)
/** @} */
/**
* @brief An entry in the 6LoWPAN reassembly buffer.
......@@ -114,6 +124,11 @@ void gnrc_sixlowpan_frag_send(gnrc_pktsnip_t *pkt, void *ctx, unsigned page);
*/
void gnrc_sixlowpan_frag_recv(gnrc_pktsnip_t *pkt, void *ctx, unsigned page);
/**
* @brief Garbage collect reassembly buffer.
*/
void gnrc_sixlowpan_frag_gc_rbuf(void);
#ifdef __cplusplus
}
#endif
......
......@@ -320,4 +320,9 @@ void gnrc_sixlowpan_frag_recv(gnrc_pktsnip_t *pkt, void *ctx, unsigned page)
gnrc_pktbuf_release(pkt);
}
void gnrc_sixlowpan_frag_gc_rbuf(void)
{
rbuf_gc();
}
/** @} */
......@@ -48,6 +48,9 @@ static rbuf_t rbuf[RBUF_SIZE];
static char l2addr_str[3 * IEEE802154_LONG_ADDRESS_LEN];
static xtimer_t _gc_timer;
static msg_t _gc_timer_msg = { .type = GNRC_SIXLOWPAN_MSG_FRAG_GC_RBUF };
/* ------------------------------------
* internal function definitions
* ------------------------------------*/
......@@ -59,8 +62,6 @@ static rbuf_int_t *_rbuf_int_get_free(void);
static void _rbuf_rem(rbuf_t *entry);
/* update interval buffer of entry */
static bool _rbuf_update_ints(rbuf_t *entry, uint16_t offset, size_t frag_size);
/* checks timeouts and removes entries if necessary (oldest if full) */
static void _rbuf_gc(void);
/* 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,
......@@ -78,7 +79,7 @@ void rbuf_add(gnrc_netif_hdr_t *netif_hdr, gnrc_pktsnip_t *pkt,
rbuf_int_t *ptr;
uint8_t *data = ((uint8_t *)pkt->data) + sizeof(sixlowpan_frag_t);
_rbuf_gc();
rbuf_gc();
entry = _rbuf_get(gnrc_netif_hdr_get_src_addr(netif_hdr), netif_hdr->src_l2addr_len,
gnrc_netif_hdr_get_dst_addr(netif_hdr), netif_hdr->dst_l2addr_len,
byteorder_ntohs(frag->disp_size) & SIXLOWPAN_FRAG_SIZE_MASK,
......@@ -246,7 +247,7 @@ static bool _rbuf_update_ints(rbuf_t *entry, uint16_t offset, size_t frag_size)
return true;
}
static void _rbuf_gc(void)
void rbuf_gc(void)
{
uint32_t now_usec = xtimer_now_usec();
unsigned int i;
......@@ -271,6 +272,11 @@ static void _rbuf_gc(void)
}
}
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)
......@@ -295,6 +301,7 @@ static rbuf_t *_rbuf_get(const void *src, size_t src_len,
l2addr_str),
(unsigned)rbuf[i].super.pkt->size, rbuf[i].super.tag);
rbuf[i].arrival = now_usec;
_set_rbuf_timeout();
return &(rbuf[i]);
}
......@@ -347,6 +354,8 @@ static rbuf_t *_rbuf_get(const void *src, size_t src_len,
l2addr_str), (unsigned)res->super.pkt->size,
res->super.tag);
_set_rbuf_timeout();
return res;
}
......
......@@ -85,6 +85,11 @@ typedef struct {
void rbuf_add(gnrc_netif_hdr_t *netif_hdr, gnrc_pktsnip_t *frag,
size_t frag_size, size_t offset);
/**
* @brief Checks timeouts and removes entries if necessary
*/
void rbuf_gc(void);
#ifdef __cplusplus
}
#endif
......
......@@ -375,6 +375,10 @@ static void *_event_loop(void *args)
DEBUG("6lo: send fragmented event received\n");
gnrc_sixlowpan_frag_send(NULL, msg.content.ptr, 0);
break;
case GNRC_SIXLOWPAN_MSG_FRAG_GC_RBUF:
DEBUG("6lo: garbage collect reassembly buffer event received\n");
gnrc_sixlowpan_frag_gc_rbuf();
break;
#endif
default:
......
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