diff --git a/sys/include/net/gnrc/ipv6/nib/abr.h b/sys/include/net/gnrc/ipv6/nib/abr.h index effb1ebd48..18345b8ac7 100644 --- a/sys/include/net/gnrc/ipv6/nib/abr.h +++ b/sys/include/net/gnrc/ipv6/nib/abr.h @@ -28,7 +28,18 @@ extern "C" { #endif -#if (GNRC_IPV6_NIB_CONF_6LBR && GNRC_IPV6_NIB_CONF_MULTIHOP_P6C) || defined(DOXYGEN) +/** + * @brief Authoritative border router list entry view on NIB + */ +typedef struct { + ipv6_addr_t addr; /**< The address of the border router */ + uint32_t version; /**< last received version */ + uint32_t valid_until; /**< timestamp (in minutes) until which the + * information is valid */ +} gnrc_ipv6_nib_abr_t; + +#if GNRC_IPV6_NIB_CONF_MULTIHOP_P6C || defined(DOXYGEN) +#if GNRC_IPV6_NIB_CONF_6LBR || defined(DOXYGEN) /** * @brief Adds the address of an authoritative border router to the NIB * @@ -36,6 +47,8 @@ extern "C" { * * @return 0 on success. * @return -ENOMEM, if no space is left in the neighbor cache. + * @return -ENOTSUP, if @ref GNRC_IPV6_NIB_CONF_6LBR or + * @ref GNRC_IPV6_NIB_CONF_MULTIHOP_P6C is not defined */ int gnrc_ipv6_nib_abr_add(const ipv6_addr_t *addr); @@ -45,7 +58,59 @@ int gnrc_ipv6_nib_abr_add(const ipv6_addr_t *addr); * @param[in] addr The address of an authoritative border router. */ void gnrc_ipv6_nib_abr_del(const ipv6_addr_t *addr); -#endif /* (GNRC_IPV6_NIB_CONF_6LBR && GNRC_IPV6_NIB_CONF_MULTIHOP_P6C) || defined(DOXYGEN) */ +#else /* GNRC_IPV6_NIB_CONF_6LBR || defined(DOXYGEN) */ +#define gnrc_ipv6_nib_abr_add(addr) (-ENOTSUP) +#define gnrc_ipv6_nib_abr_del(addr) (void)(addr) +#endif /* GNRC_IPV6_NIB_CONF_6LBR || defined(DOXYGEN) */ + +/** + * @brief Iterates over all authoritative border router in the NIB + * + * @pre `(state != NULL) && (abr != NULL)` + * + * @param[in,out] state Iteration state of the authoritative border router list. + * Must point to NULL pointer to start iteration + * @param[out] abr The next authoritative border router list entry. + * + * Usage example: + * + * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ {.c} + * #include "net/gnrc/ipv6/nib/abr.h" + * + * int main(void) { + * void *state = NULL; + * gnrc_ipv6_nib_abr_t abr; + * + * puts("My border routers:"); + * while (gnrc_ipv6_nib_abr_iter(&state, &abr)) { + * gnrc_ipv6_nib_abr_print(&abr); + * } + * return 0; + * } + * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + * + * @note The list may change during iteration. + * + * @return true, if iteration can be continued. + * @return false, if @p abr is the last authoritative border router entry in + * the NIB. + */ +bool gnrc_ipv6_nib_abr_iter(void **state, gnrc_ipv6_nib_abr_t *abr); + +/** + * @brief Prints an authoritative border router list entry + * + * @pre `abr != NULL` + * + * @param[in] abr An authoritative border router list entry + */ +void gnrc_ipv6_nib_abr_print(gnrc_ipv6_nib_abr_t *abr); +#else /* GNRC_IPV6_NIB_CONF_MULTIHOP_P6C || defined(DOXYGEN) */ +#define gnrc_ipv6_nib_abr_add(addr) (-ENOTSUP) +#define gnrc_ipv6_nib_abr_del(addr) (void)(addr) +#define gnrc_ipv6_nib_abr_iter(state, abr) (false) +#define gnrc_ipv6_nib_abr_print(abr) (void)(abr) +#endif /* GNRC_IPV6_NIB_CONF_MULTIHOP_P6C || defined(DOXYGEN) */ #ifdef __cplusplus } diff --git a/sys/net/gnrc/network_layer/ipv6/nib/nib_abr.c b/sys/net/gnrc/network_layer/ipv6/nib/nib_abr.c index 5c926b7abe..ec3231249e 100644 --- a/sys/net/gnrc/network_layer/ipv6/nib/nib_abr.c +++ b/sys/net/gnrc/network_layer/ipv6/nib/nib_abr.c @@ -13,11 +13,15 @@ * @author Martine Lenders */ +#include + #include "net/gnrc/ipv6/nib/abr.h" +#include "_nib-6ln.h" #include "_nib-internal.h" -#if GNRC_IPV6_NIB_CONF_6LBR && GNRC_IPV6_NIB_CONF_MULTIHOP_P6C +#if GNRC_IPV6_NIB_CONF_MULTIHOP_P6C +#if GNRC_IPV6_NIB_CONF_6LBR int gnrc_ipv6_nib_abr_add(const ipv6_addr_t *addr) { _nib_abr_entry_t *abr; @@ -28,6 +32,7 @@ int gnrc_ipv6_nib_abr_add(const ipv6_addr_t *addr) mutex_unlock(&_nib_mutex); return -ENOMEM; } + abr->valid_until = 0U; while ((offl = _nib_offl_iter(offl))) { if (offl->mode & _PL) { _nib_abr_add_pfx(abr, offl); @@ -39,7 +44,7 @@ int gnrc_ipv6_nib_abr_add(const ipv6_addr_t *addr) bf_set(abr->ctxs, id); } } -#endif +#endif /* MODULE_GNRC_SIXLOWPAN_CTX */ mutex_unlock(&_nib_mutex); return 0; } @@ -50,8 +55,39 @@ void gnrc_ipv6_nib_abr_del(const ipv6_addr_t *addr) _nib_abr_remove(addr); mutex_unlock(&_nib_mutex); } +#endif /* GNRC_IPV6_NIB_CONF_6LBR */ + +bool gnrc_ipv6_nib_abr_iter(void **state, gnrc_ipv6_nib_abr_t *entry) +{ + _nib_abr_entry_t *abr = *state; + + mutex_lock(&_nib_mutex); + while ((abr = _nib_abr_iter(abr)) != NULL) { + if (!ipv6_addr_is_unspecified(&abr->addr)) { + memcpy(&entry->addr, &abr->addr, sizeof(entry->addr)); + entry->version = abr->version; + entry->valid_until = abr->valid_until; + break; + } + } + mutex_unlock(&_nib_mutex); + *state = abr; + return (*state != NULL); +} + +void gnrc_ipv6_nib_abr_print(gnrc_ipv6_nib_abr_t *abr) +{ + char addr_str[IPV6_ADDR_MAX_STR_LEN]; + uint32_t now = _now_min(); + + printf("%s v%" PRIu32 " expires %" PRIu32 "min\n", + ipv6_addr_to_str(addr_str, &abr->addr, sizeof(addr_str)), + abr->version, + (abr->valid_until != 0) ? (abr->valid_until - now) : + SIXLOWPAN_ND_OPT_ABR_LTIME_DEFAULT); +} #else typedef int dont_be_pedantic; -#endif +#endif /* GNRC_IPV6_NIB_CONF_MULTIHOP_P6C */ /** @} */