diff --git a/sys/net/gnrc/network_layer/sixlowpan/frag/rb/gnrc_sixlowpan_frag_rb.c b/sys/net/gnrc/network_layer/sixlowpan/frag/rb/gnrc_sixlowpan_frag_rb.c index 4a98dcee8f..a84b060b02 100644 --- a/sys/net/gnrc/network_layer/sixlowpan/frag/rb/gnrc_sixlowpan_frag_rb.c +++ b/sys/net/gnrc/network_layer/sixlowpan/frag/rb/gnrc_sixlowpan_frag_rb.c @@ -29,6 +29,7 @@ #include "net/gnrc/sixlowpan/frag/minfwd.h" #include "net/gnrc/sixlowpan/frag/vrb.h" #include "net/sixlowpan.h" +#include "net/sixlowpan/sfr.h" #include "thread.h" #include "xtimer.h" #include "utlist.h" @@ -205,9 +206,18 @@ static gnrc_sixlowpan_frag_rb_t *_rbuf_get_by_tag(const gnrc_netif_hdr_t *netif_ #ifndef NDEBUG static bool _valid_offset(gnrc_pktsnip_t *pkt, size_t offset) { - return (sixlowpan_frag_1_is(pkt->data) && (offset == 0)) || - (sixlowpan_frag_n_is(pkt->data) && - (offset == sixlowpan_frag_offset(pkt->data))); + return ( + IS_USED(MODULE_GNRC_SIXLOWPAN_FRAG) && + ((sixlowpan_frag_1_is(pkt->data) && (offset == 0)) || + (sixlowpan_frag_n_is(pkt->data) && + (offset == sixlowpan_frag_offset(pkt->data)))) + ) || ( + IS_USED(MODULE_GNRC_SIXLOWPAN_FRAG_SFR) && + /* offset == 0 is an abort condition that should not be handed to the + * reassembly buffer */ + sixlowpan_sfr_rfrag_is(pkt->data) && + (sixlowpan_sfr_rfrag_get_offset(pkt->data) != 0) + ); } #endif @@ -239,6 +249,25 @@ static size_t _6lo_frag_size(gnrc_pktsnip_t *pkt, size_t offset, uint8_t *data) return frag_size; } +static uint16_t _6lo_sfr_datagram_size(gnrc_pktsnip_t *pkt, size_t offset) +{ + /* offset doubles as datagram size in RFRAG header when sequence number is 0 + * see https://tools.ietf.org/html/draft-ietf-6lo-fragment-recovery-08#section-5.1 */ + return (offset == 0) ? sixlowpan_sfr_rfrag_get_offset(pkt->data) : 0; +} + +static uint8_t *_6lo_sfr_payload(gnrc_pktsnip_t *pkt) +{ + return ((uint8_t *)pkt->data) + sizeof(sixlowpan_sfr_rfrag_t); +} + +static size_t _6lo_sfr_frag_size(gnrc_pktsnip_t *pkt) +{ + /* TODO: if necessary check MAC layer here, + * see https://tools.ietf.org/html/draft-ietf-6lo-fragment-recovery-08#section-5.1 */ + return sixlowpan_sfr_rfrag_get_frag_size(pkt->data); +} + static int _rbuf_add(gnrc_netif_hdr_t *netif_hdr, gnrc_pktsnip_t *pkt, size_t offset, unsigned page) { @@ -249,18 +278,37 @@ static int _rbuf_add(gnrc_netif_hdr_t *netif_hdr, gnrc_pktsnip_t *pkt, } entry; const uint8_t *src = gnrc_netif_hdr_get_src_addr(netif_hdr); const uint8_t *dst = gnrc_netif_hdr_get_dst_addr(netif_hdr); - uint8_t *data; - size_t frag_size; + uint8_t *data = NULL; + size_t frag_size = 0; /* assign 0, otherwise cppcheck complains ;-) */ int res; uint16_t datagram_size; uint16_t datagram_tag; /* check if provided offset is the same as in fragment */ assert(_valid_offset(pkt, offset)); - data = _6lo_frag_payload(pkt); - frag_size = _6lo_frag_size(pkt, offset, data); - datagram_size = sixlowpan_frag_datagram_size(pkt->data); - datagram_tag = sixlowpan_frag_datagram_tag(pkt->data); + if (IS_USED(MODULE_GNRC_SIXLOWPAN_FRAG) && sixlowpan_frag_is(pkt->data)) { + data = _6lo_frag_payload(pkt); + frag_size = _6lo_frag_size(pkt, offset, data); + datagram_size = sixlowpan_frag_datagram_size(pkt->data); + datagram_tag = sixlowpan_frag_datagram_tag(pkt->data); + } + else if (IS_USED(MODULE_GNRC_SIXLOWPAN_FRAG_SFR) && + sixlowpan_sfr_rfrag_is(pkt->data)) { + sixlowpan_sfr_rfrag_t *rfrag = pkt->data;; + + data = _6lo_sfr_payload(pkt); + frag_size = _6lo_sfr_frag_size(pkt); + /* offset doubles as datagram size in RFRAG header when sequence number + * is 0 */ + datagram_size = _6lo_sfr_datagram_size(pkt, offset); + datagram_tag = rfrag->base.tag; + } + else { + /* either one of the if branches above was taken */ + assert(data != NULL); + gnrc_pktbuf_release(pkt); + return RBUF_ADD_ERROR; + } gnrc_sixlowpan_frag_rb_gc(); /* only check VRB for subsequent frags, first frags create and not get VRB