diff --git a/sys/include/net/gnrc/sixlowpan/frag/vrb.h b/sys/include/net/gnrc/sixlowpan/frag/vrb.h index 61d7a5d486..b1923d8026 100644 --- a/sys/include/net/gnrc/sixlowpan/frag/vrb.h +++ b/sys/include/net/gnrc/sixlowpan/frag/vrb.h @@ -75,6 +75,28 @@ gnrc_sixlowpan_frag_vrb_t *gnrc_sixlowpan_frag_vrb_add( const gnrc_sixlowpan_frag_rb_base_t *base, gnrc_netif_t *out_netif, const uint8_t *out_dst, size_t out_dst_len); +/** + * @brief Generate reassembly buffer from a header's forwarding information. + * + * @param[in] base Base data of the datagram. Must not be `NULL`. + * @param[in] netif Restict route to this interface. May be `NULL` for any + * interface. + * @param[in] hdr Header from which to take the forwarding information from + * (e.g. IPv6 header implies `hdr->type == GNRC_NETTYPE_IPV6`). + * + * @pre `base != NULL` + * @pre `(hdr != NULL) && (hdr->data != NULL) && (hdr->size > 0)` + * + * @return The VRB entry pointing to the next hop based on the forwarding + * information provided in @p hdr and present in the respective + * forwarding information base for `hdr->type`. + * @return NULL, if VRB is full or if there is no route to destination in + * @p hdr. + */ +gnrc_sixlowpan_frag_vrb_t *gnrc_sixlowpan_frag_vrb_from_route( + const gnrc_sixlowpan_frag_rb_base_t *base, + gnrc_netif_t *netif, const gnrc_pktsnip_t *hdr); + /** * @brief Checks timeouts and removes entries if necessary */ diff --git a/sys/net/gnrc/network_layer/sixlowpan/frag/vrb/gnrc_sixlowpan_frag_vrb.c b/sys/net/gnrc/network_layer/sixlowpan/frag/vrb/gnrc_sixlowpan_frag_vrb.c index 8c091bcb31..cf6f1bfdc5 100644 --- a/sys/net/gnrc/network_layer/sixlowpan/frag/vrb/gnrc_sixlowpan_frag_vrb.c +++ b/sys/net/gnrc/network_layer/sixlowpan/frag/vrb/gnrc_sixlowpan_frag_vrb.c @@ -14,6 +14,11 @@ */ #include "net/ieee802154.h" +#ifdef MODULE_GNRC_IPV6_NIB +#include "net/ipv6/addr.h" +#include "net/gnrc/ipv6/nib.h" +#endif /* MODULE_GNRC_IPV6_NIB */ +#include "net/gnrc/netif.h" #include "xtimer.h" #include "net/gnrc/sixlowpan/frag/vrb.h" @@ -22,7 +27,11 @@ #include "debug.h" static gnrc_sixlowpan_frag_vrb_t _vrb[GNRC_SIXLOWPAN_FRAG_VRB_SIZE]; +#ifdef MODULE_GNRC_IPV6_NIB +static char addr_str[IPV6_ADDR_MAX_STR_LEN]; +#else /* MODULE_GNRC_IPV6_NIB */ static char addr_str[3 * IEEE802154_LONG_ADDRESS_LEN]; +#endif /* MODULE_GNRC_IPV6_NIB */ #if !defined(MODULE_GNRC_SIXLOWPAN_FRAG) && defined(TEST_SUITES) /* mock for e.g. testing */ @@ -91,6 +100,50 @@ gnrc_sixlowpan_frag_vrb_t *gnrc_sixlowpan_frag_vrb_add( return vrbe; } +gnrc_sixlowpan_frag_vrb_t *gnrc_sixlowpan_frag_vrb_from_route( + const gnrc_sixlowpan_frag_rb_base_t *base, + gnrc_netif_t *netif, const gnrc_pktsnip_t *hdr) +{ + gnrc_sixlowpan_frag_vrb_t *res = NULL; + + assert(base != NULL); + assert((hdr != NULL) && (hdr->data != NULL) && (hdr->size > 0)); + switch (hdr->type) { +#ifdef MODULE_GNRC_IPV6_NIB + case GNRC_NETTYPE_IPV6: { + assert(hdr->size >= sizeof(ipv6_hdr_t)); + const ipv6_addr_t *addr = &((const ipv6_hdr_t *)hdr->data)->dst; + gnrc_ipv6_nib_nc_t nce; + + if (!ipv6_addr_is_link_local(addr) && + (gnrc_netif_get_by_ipv6_addr(addr) == NULL) && + (gnrc_ipv6_nib_get_next_hop_l2addr(addr, netif, NULL, + &nce) == 0)) { + + DEBUG("6lo vrb: FIB entry for IPv6 destination %s found\n", + ipv6_addr_to_str(addr_str, addr, sizeof(addr_str))); + res = gnrc_sixlowpan_frag_vrb_add( + base, + gnrc_netif_get_by_pid(gnrc_ipv6_nib_nc_get_iface(&nce)), + nce.l2addr, nce.l2addr_len + ); + } + else { + DEBUG("6lo vrb: no FIB entry for IPv6 destination %s found\n", + ipv6_addr_to_str(addr_str, addr, sizeof(addr_str))); + } + break; + } +#endif /* MODULE_GNRC_IPV6_NIB */ + default: + (void)base; + (void)netif; + DEBUG("6lo vrb: unknown forwarding header type %d\n", hdr->type); + break; + } + return res; +} + gnrc_sixlowpan_frag_vrb_t *gnrc_sixlowpan_frag_vrb_get( const uint8_t *src, size_t src_len, unsigned src_tag) {