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
Branches
No related tags found
No related merge requests found
...@@ -38,10 +38,20 @@ ...@@ -38,10 +38,20 @@
extern "C" { extern "C" {
#endif #endif
/**
* @name Message types
* @{
*/
/** /**
* @brief Message type for passing one 6LoWPAN fragment down the network stack * @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. * @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); ...@@ -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); 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 #ifdef __cplusplus
} }
#endif #endif
......
...@@ -320,4 +320,9 @@ void gnrc_sixlowpan_frag_recv(gnrc_pktsnip_t *pkt, void *ctx, unsigned page) ...@@ -320,4 +320,9 @@ void gnrc_sixlowpan_frag_recv(gnrc_pktsnip_t *pkt, void *ctx, unsigned page)
gnrc_pktbuf_release(pkt); gnrc_pktbuf_release(pkt);
} }
void gnrc_sixlowpan_frag_gc_rbuf(void)
{
rbuf_gc();
}
/** @} */ /** @} */
...@@ -48,6 +48,9 @@ static rbuf_t rbuf[RBUF_SIZE]; ...@@ -48,6 +48,9 @@ static rbuf_t rbuf[RBUF_SIZE];
static char l2addr_str[3 * IEEE802154_LONG_ADDRESS_LEN]; 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 * internal function definitions
* ------------------------------------*/ * ------------------------------------*/
...@@ -59,8 +62,6 @@ static rbuf_int_t *_rbuf_int_get_free(void); ...@@ -59,8 +62,6 @@ static rbuf_int_t *_rbuf_int_get_free(void);
static void _rbuf_rem(rbuf_t *entry); static void _rbuf_rem(rbuf_t *entry);
/* update interval buffer of entry */ /* 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(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 */ /* gets an entry identified by its tupel */
static rbuf_t *_rbuf_get(const void *src, size_t src_len, static rbuf_t *_rbuf_get(const void *src, size_t src_len,
const void *dst, size_t dst_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, ...@@ -78,7 +79,7 @@ void rbuf_add(gnrc_netif_hdr_t *netif_hdr, gnrc_pktsnip_t *pkt,
rbuf_int_t *ptr; rbuf_int_t *ptr;
uint8_t *data = ((uint8_t *)pkt->data) + sizeof(sixlowpan_frag_t); 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, 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, gnrc_netif_hdr_get_dst_addr(netif_hdr), netif_hdr->dst_l2addr_len,
byteorder_ntohs(frag->disp_size) & SIXLOWPAN_FRAG_SIZE_MASK, 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) ...@@ -246,7 +247,7 @@ static bool _rbuf_update_ints(rbuf_t *entry, uint16_t offset, size_t frag_size)
return true; return true;
} }
static void _rbuf_gc(void) void rbuf_gc(void)
{ {
uint32_t now_usec = xtimer_now_usec(); uint32_t now_usec = xtimer_now_usec();
unsigned int i; unsigned int i;
...@@ -271,6 +272,11 @@ static void _rbuf_gc(void) ...@@ -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, static rbuf_t *_rbuf_get(const void *src, size_t src_len,
const void *dst, size_t dst_len, const void *dst, size_t dst_len,
size_t size, uint16_t tag) size_t size, uint16_t tag)
...@@ -295,6 +301,7 @@ static rbuf_t *_rbuf_get(const void *src, size_t src_len, ...@@ -295,6 +301,7 @@ static rbuf_t *_rbuf_get(const void *src, size_t src_len,
l2addr_str), l2addr_str),
(unsigned)rbuf[i].super.pkt->size, rbuf[i].super.tag); (unsigned)rbuf[i].super.pkt->size, rbuf[i].super.tag);
rbuf[i].arrival = now_usec; rbuf[i].arrival = now_usec;
_set_rbuf_timeout();
return &(rbuf[i]); return &(rbuf[i]);
} }
...@@ -347,6 +354,8 @@ static rbuf_t *_rbuf_get(const void *src, size_t src_len, ...@@ -347,6 +354,8 @@ static rbuf_t *_rbuf_get(const void *src, size_t src_len,
l2addr_str), (unsigned)res->super.pkt->size, l2addr_str), (unsigned)res->super.pkt->size,
res->super.tag); res->super.tag);
_set_rbuf_timeout();
return res; return res;
} }
......
...@@ -85,6 +85,11 @@ typedef struct { ...@@ -85,6 +85,11 @@ typedef struct {
void rbuf_add(gnrc_netif_hdr_t *netif_hdr, gnrc_pktsnip_t *frag, void rbuf_add(gnrc_netif_hdr_t *netif_hdr, gnrc_pktsnip_t *frag,
size_t frag_size, size_t offset); size_t frag_size, size_t offset);
/**
* @brief Checks timeouts and removes entries if necessary
*/
void rbuf_gc(void);
#ifdef __cplusplus #ifdef __cplusplus
} }
#endif #endif
......
...@@ -375,6 +375,10 @@ static void *_event_loop(void *args) ...@@ -375,6 +375,10 @@ static void *_event_loop(void *args)
DEBUG("6lo: send fragmented event received\n"); DEBUG("6lo: send fragmented event received\n");
gnrc_sixlowpan_frag_send(NULL, msg.content.ptr, 0); gnrc_sixlowpan_frag_send(NULL, msg.content.ptr, 0);
break; break;
case GNRC_SIXLOWPAN_MSG_FRAG_GC_RBUF:
DEBUG("6lo: garbage collect reassembly buffer event received\n");
gnrc_sixlowpan_frag_gc_rbuf();
break;
#endif #endif
default: default:
......
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Please register or to comment