From a7d2c65b362a85a28beae3af187d92f1ab7f3951 Mon Sep 17 00:00:00 2001 From: Martine Lenders <m.lenders@fu-berlin.de> Date: Mon, 31 Jul 2017 17:51:20 +0200 Subject: [PATCH] gnrc_ipv6_nib: port to gnrc_netif2 --- Makefile.dep | 57 +--- sys/include/net/gnrc/ipv6.h | 4 +- sys/include/net/gnrc/ipv6/nib.h | 94 +++++- sys/include/net/gnrc/ipv6/nib/conf.h | 6 +- sys/include/net/gnrc/netif2/conf.h | 5 +- sys/include/net/gnrc/netif2/ipv6.h | 5 +- sys/net/gnrc/netif2/gnrc_netif2.c | 13 +- .../gnrc/network_layer/icmpv6/gnrc_icmpv6.c | 42 +-- sys/net/gnrc/network_layer/ipv6/gnrc_ipv6.c | 141 +-------- .../ipv6/netif/gnrc_ipv6_netif.c | 9 - .../gnrc/network_layer/ipv6/nib/_nib-6ln.c | 106 ++++--- .../gnrc/network_layer/ipv6/nib/_nib-6ln.h | 26 +- .../gnrc/network_layer/ipv6/nib/_nib-6lr.c | 14 +- .../gnrc/network_layer/ipv6/nib/_nib-6lr.h | 30 +- .../gnrc/network_layer/ipv6/nib/_nib-arsm.c | 206 +++++++++---- .../gnrc/network_layer/ipv6/nib/_nib-arsm.h | 59 ++-- .../network_layer/ipv6/nib/_nib-internal.c | 61 +--- .../network_layer/ipv6/nib/_nib-internal.h | 74 ----- sys/net/gnrc/network_layer/ipv6/nib/nib.c | 279 +++++++++++------- sys/net/gnrc/network_layer/ipv6/nib/nib_nc.c | 11 +- sys/shell/commands/sc_gnrc_ipv6_nib.c | 5 +- 21 files changed, 571 insertions(+), 676 deletions(-) diff --git a/Makefile.dep b/Makefile.dep index b350a9a1f7..d7b244c58a 100644 --- a/Makefile.dep +++ b/Makefile.dep @@ -136,29 +136,30 @@ endif ifneq (,$(filter gnrc_sixlowpan_default,$(USEMODULE))) USEMODULE += gnrc_ipv6_default + USEMODULE += gnrc_ipv6_nib_6ln USEMODULE += gnrc_sixlowpan - USEMODULE += gnrc_sixlowpan_nd USEMODULE += gnrc_sixlowpan_frag USEMODULE += gnrc_sixlowpan_iphc endif ifneq (,$(filter gnrc_sixlowpan_router_default,$(USEMODULE))) USEMODULE += gnrc_ipv6_router_default + USEMODULE += gnrc_ipv6_nib_6lr USEMODULE += gnrc_sixlowpan_router USEMODULE += gnrc_sixlowpan_frag USEMODULE += gnrc_sixlowpan_iphc endif ifneq (,$(filter gnrc_sixlowpan_border_router_default,$(USEMODULE))) + USEMODULE += gnrc_ipv6_nib_6lbr USEMODULE += gnrc_ipv6_router_default - USEMODULE += gnrc_sixlowpan_nd_border_router USEMODULE += gnrc_sixlowpan_router USEMODULE += gnrc_sixlowpan_frag USEMODULE += gnrc_sixlowpan_iphc endif ifneq (,$(filter gnrc_sixlowpan_router,$(USEMODULE))) - USEMODULE += gnrc_sixlowpan_nd_router + USEMODULE += gnrc_ipv6_router endif ifneq (,$(filter gnrc_sixlowpan_frag,$(USEMODULE))) @@ -182,50 +183,14 @@ ifneq (,$(filter gnrc_sixlowpan_ctx,$(USEMODULE))) USEMODULE += xtimer endif -ifneq (,$(filter gnrc_sixlowpan_nd_border_router,$(USEMODULE))) - USEMODULE += gnrc_sixlowpan_nd_router -endif - -ifneq (,$(filter gnrc_sixlowpan_nd_router,$(USEMODULE))) - USEMODULE += gnrc_sixlowpan_nd -endif - -ifneq (,$(filter gnrc_sixlowpan_nd,$(USEMODULE))) - USEMODULE += gnrc_ndp - USEMODULE += gnrc_ndp_internal - USEMODULE += gnrc_sixlowpan_ctx - USEMODULE += random - USEMODULE += xtimer -endif - ifneq (,$(filter gnrc_ipv6_default,$(USEMODULE))) USEMODULE += gnrc_ipv6 USEMODULE += gnrc_icmpv6 - ifeq (1,$(GNRC_NETIF_NUMOF)) - ifeq (,$(filter gnrc_sixlowpan_nd,$(USEMODULE))) - USEMODULE += gnrc_ndp_host - endif - else - USEMODULE += gnrc_ndp_host - endif endif ifneq (,$(filter gnrc_ipv6_router_default,$(USEMODULE))) USEMODULE += gnrc_ipv6_router USEMODULE += gnrc_icmpv6 - ifeq (1,$(GNRC_NETIF_NUMOF)) - ifeq (,$(filter gnrc_sixlowpan_nd_router,$(USEMODULE))) - USEMODULE += gnrc_ndp_router - endif - else - USEMODULE += gnrc_ndp_router - endif -endif - -ifneq (,$(filter gnrc_ndp_host,$(USEMODULE))) - USEMODULE += gnrc_ndp_node - USEMODULE += random - USEMODULE += xtimer endif ifneq (,$(filter gnrc_ndp_router,$(USEMODULE))) @@ -242,18 +207,6 @@ ifneq (,$(filter gnrc_ndp_%,$(USEMODULE))) USEMODULE += gnrc_ndp endif -ifneq (,$(filter gnrc_ndp,$(USEMODULE))) - ifneq (,$(filter gnrc_sixlowpan,$(USEMODULE))) - USEMODULE += gnrc_sixlowpan_nd - else - USEMODULE += gnrc_ndp_node - endif - USEMODULE += gnrc_ndp_internal - USEMODULE += gnrc_icmpv6 - USEMODULE += random - USEMODULE += xtimer -endif - ifneq (,$(filter gnrc_ndp2,$(USEMODULE))) USEMODULE += gnrc_icmpv6 USEMODULE += gnrc_netif2 @@ -302,7 +255,7 @@ ifneq (,$(filter gnrc_ipv6,$(USEMODULE))) USEMODULE += inet_csum USEMODULE += ipv6_addr USEMODULE += gnrc_ipv6_hdr - USEMODULE += gnrc_ipv6_nc + USEMODULE += gnrc_ipv6_nib USEMODULE += gnrc_netif2 endif diff --git a/sys/include/net/gnrc/ipv6.h b/sys/include/net/gnrc/ipv6.h index 0b9704b247..661531b4da 100644 --- a/sys/include/net/gnrc/ipv6.h +++ b/sys/include/net/gnrc/ipv6.h @@ -36,9 +36,7 @@ #include "net/ipv6.h" #include "net/gnrc/ipv6/ext.h" #include "net/gnrc/ipv6/hdr.h" -#ifndef MODULE_GNRC_IPV6_NIB -#include "net/gnrc/ipv6/nc.h" -#endif +#include "net/gnrc/ipv6/nib.h" #ifdef MODULE_FIB #include "net/fib.h" diff --git a/sys/include/net/gnrc/ipv6/nib.h b/sys/include/net/gnrc/ipv6/nib.h index 0883a2cc58..43fe775635 100644 --- a/sys/include/net/gnrc/ipv6/nib.h +++ b/sys/include/net/gnrc/ipv6/nib.h @@ -33,6 +33,7 @@ #include "net/ipv6/addr.h" #include "net/ipv6/hdr.h" #include "net/gnrc/ipv6/nib/nc.h" +#include "net/gnrc/netif2.h" #include "net/gnrc/pkt.h" #ifdef __cplusplus @@ -194,13 +195,67 @@ extern "C" { * @brief Recalculate reachability timeout time. * * This message type is for the event of recalculating the reachability timeout - * time. The expected message context is a valid interface. + * time. The expected message context is a valid + * [interface](@ref net_gnrc_netif2). * * @note Only handled with @ref GNRC_IPV6_NIB_CONF_ARSM != 0 */ #define GNRC_IPV6_NIB_RECALC_REACH_TIME (0x4fceU) /** @} */ +/** + * @brief Types for gnrc_netif2_ipv6_t::route_info_cb + * @anchor net_gnrc_ipv6_nib_route_info_type + */ +enum { + GNRC_IPV6_NIB_ROUTE_INFO_TYPE_UNDEF = 0, /**< undefined */ + /** + * @brief reactive routing query + * + * A reactive routing query is issued when a route is unknown to the NIB. + * A reactive routing protocol can use this call to search for a route in a + * reactive manner. + * + * The `ctx_addr` will be the destination address of the unknown route, + * `ctx` a pointer to the packet as `gnrc_pktsnip_t` that caused the route + * look-up (to possibly queue it for later sending). + */ + GNRC_IPV6_NIB_ROUTE_INFO_TYPE_RRQ, + + /** + * @brief route notification + * + * A route notification is issued when an already established route is + * taken. A routing protocol can use this call to update its information on + * the route. + * + * The `ctx_addr` is the prefix of the route, `ctx` is set to a value equal + * to the length of the prefix in bits. + */ + GNRC_IPV6_NIB_ROUTE_INFO_TYPE_RN, + + /** + * @brief neighbor state change + * + * A neighbor state change is issued when ever the NUD state of a neighbor + * changes. A routing protocol can use this call to update its information + * on routes via this neighbor. + * + * The `ctx_addr` is the address of the neighbor, `ctx` is a value equal + * to the new NUD state as defined in [the NC info flags](@ref + * net_gnrc_ipv6_nib_nc_info). If the entry is deleted, `ctx` will be set + * to @ref GNRC_IPV6_NIB_NC_INFO_NUD_STATE_UNREACHABLE (except if it was + * already in the `UNREACHABLE` state). This does not include cache-outs, + * since they give no information about the neighbor's reachability (you + * might however get an INCOMPLETE or STALE notification due to that, as + * soon as the neighbor enters the neighbor cache again). + * + * Be adviced to only use `ctx_addr` in the context of the callback, since + * it might be overwritten, after the callback was left. + */ + GNRC_IPV6_NIB_ROUTE_INFO_TYPE_NSC, +}; + /** * @brief Initialize NIB */ @@ -209,11 +264,11 @@ void gnrc_ipv6_nib_init(void); /** * @brief Adds an interface to be managed by the NIB. * - * @pre `(KERNEL_PID_UNDEF < iface)` + * @pre `netif != NULL` * - * @param[in] iface The interface to be managed by the NIB + * @param[in,out] netif The interface to be managed by the NIB */ -void gnrc_ipv6_nib_init_iface(kernel_pid_t iface); +void gnrc_ipv6_nib_init_iface(gnrc_netif2_t *netif); /** * @brief Gets link-layer address of next hop to a destination address @@ -221,8 +276,8 @@ void gnrc_ipv6_nib_init_iface(kernel_pid_t iface); * @pre `(dst != NULL) && (nce != NULL)` * * @param[in] dst Destination address of a packet. - * @param[in] iface Restrict search to this interface. May be - * `KERNEL_PID_UNDEF` for any interface. + * @param[in] netif Restrict search to this interface. May be `NULL` for any + * interface. * @param[in] pkt The IPv6 packet in sending order for which the next hop * is searched. Needed for queuing for with reactive * routing or address resolution. May be `NULL`. @@ -237,13 +292,13 @@ void gnrc_ipv6_nib_init_iface(kernel_pid_t iface); * solicitation sent). */ int gnrc_ipv6_nib_get_next_hop_l2addr(const ipv6_addr_t *dst, - kernel_pid_t iface, gnrc_pktsnip_t *pkt, + gnrc_netif2_t *netif, gnrc_pktsnip_t *pkt, gnrc_ipv6_nib_nc_t *nce); /** * @brief Handles a received ICMPv6 packet * - * @pre `iface != KERNEL_PID_UNDEF` + * @pre `netif != NULL` * @pre `ipv6 != NULL` * @pre `icmpv6 != NULL` * @pre `icmpv6_len > sizeof(icmpv6_hdr_t)` @@ -274,13 +329,13 @@ int gnrc_ipv6_nib_get_next_hop_l2addr(const ipv6_addr_t *dst, * @see [RFC 6775, section 8.2.4](https://tools.ietf.org/html/rfc6775#section-8.2.4) * @see [RFC 6775, section 8.2.5](https://tools.ietf.org/html/rfc6775#section-8.2.5) * - * @param[in] iface The interface the packet came over. + * @param[in] netif The interface the packet came over. * @param[in] ipv6 The IPv6 header of the received packet. * @param[in] icmpv6 The ICMPv6 header and payload of the received * packet. * @param[in] icmpv6_len The number of bytes at @p icmpv6. */ -void gnrc_ipv6_nib_handle_pkt(kernel_pid_t iface, const ipv6_hdr_t *ipv6, +void gnrc_ipv6_nib_handle_pkt(gnrc_netif2_t *netif, const ipv6_hdr_t *ipv6, const icmpv6_hdr_t *icmpv6, size_t icmpv6_len); /** @@ -292,6 +347,25 @@ void gnrc_ipv6_nib_handle_pkt(kernel_pid_t iface, const ipv6_hdr_t *ipv6, */ void gnrc_ipv6_nib_handle_timer_event(void *ctx, uint16_t type); +#if GNRC_IPV6_NIB_CONF_ROUTER || defined(DOXYGEN) +/** + * @brief Changes the state if an interface advertises itself as a router + * or not + * + * @param[in] netif The interface for which the state should be changed. + * @param[in] enable `true`, to enable advertising the interface as a router. + * `false`, to disable advertising the interface as a + * router. + */ +void gnrc_ipv6_nib_change_rtr_adv_iface(gnrc_netif2_t *netif, bool enable); +#else +/** + * @brief Optimization to NOP for non-routers + */ +#define gnrc_ipv6_nib_change_rtr_adv_iface(netif, enable) \ + (void)netif; (void)enable +#endif + #ifdef __cplusplus } #endif diff --git a/sys/include/net/gnrc/ipv6/nib/conf.h b/sys/include/net/gnrc/ipv6/nib/conf.h index e3c28286e0..90992df165 100644 --- a/sys/include/net/gnrc/ipv6/nib/conf.h +++ b/sys/include/net/gnrc/ipv6/nib/conf.h @@ -199,10 +199,8 @@ extern "C" { /** * @brief Maximum link-layer address length (aligned) */ -#if (GNRC_NETIF_HDR_L2ADDR_MAX_LEN % 8) -#define GNRC_IPV6_NIB_L2ADDR_MAX_LEN (((GNRC_NETIF_HDR_L2ADDR_MAX_LEN >> 3) + 1) << 3) -#else -#define GNRC_IPV6_NIB_L2ADDR_MAX_LEN (GNRC_NETIF_HDR_L2ADDR_MAX_LEN) +#ifndef GNRC_IPV6_NIB_L2ADDR_MAX_LEN +#define GNRC_IPV6_NIB_L2ADDR_MAX_LEN (8U) #endif /** diff --git a/sys/include/net/gnrc/netif2/conf.h b/sys/include/net/gnrc/netif2/conf.h index 80544f7169..085f622a25 100644 --- a/sys/include/net/gnrc/netif2/conf.h +++ b/sys/include/net/gnrc/netif2/conf.h @@ -20,6 +20,7 @@ #include "net/ieee802154.h" #include "net/ethernet/hdr.h" +#include "net/gnrc/ipv6/nib/conf.h" #include "thread.h" #ifdef __cplusplus @@ -60,7 +61,7 @@ extern "C" { * * @note Used for calculation of @ref GNRC_NETIF2_IPV6_GROUPS_NUMOF */ -#ifdef MODULE_GNRC_IPV6_ROUTER +#if GNRC_IPV6_NIB_CONF_ROUTER #define GNRC_NETIF2_IPV6_RTR_ADDR (1) #else #define GNRC_NETIF2_IPV6_RTR_ADDR (0) @@ -109,7 +110,7 @@ extern "C" { #elif MODULE_CC110X #define GNRC_NETIF2_L2ADDR_MAXLEN (1U) #else -#define GNRC_NETIF2_L2ADDR_MAXLEN (8U) +#define GNRC_NETIF2_L2ADDR_MAXLEN (GNRC_IPV6_NIB_L2ADDR_MAX_LEN) #endif #endif diff --git a/sys/include/net/gnrc/netif2/ipv6.h b/sys/include/net/gnrc/netif2/ipv6.h index ba9b9811dc..4357ddcf5b 100644 --- a/sys/include/net/gnrc/netif2/ipv6.h +++ b/sys/include/net/gnrc/netif2/ipv6.h @@ -115,9 +115,8 @@ typedef struct { * The callback may be `NULL` if no such behavior is required by the routing * protocol (or no routing protocol is present). * - * @todo Define types (RRQ, RRN, NSC) in NIB - * - * @param[in] type Type of the route info. + * @param[in] type [Type](@ref net_gnrc_ipv6_nib_route_info_type) of + * the route info. * @param[in] ctx_addr Context address of the route info. * @param[in] ctx Further context of the route info. */ diff --git a/sys/net/gnrc/netif2/gnrc_netif2.c b/sys/net/gnrc/netif2/gnrc_netif2.c index a72c2f9939..18ea7ec008 100644 --- a/sys/net/gnrc/netif2/gnrc_netif2.c +++ b/sys/net/gnrc/netif2/gnrc_netif2.c @@ -19,6 +19,9 @@ #include "net/ethernet.h" #include "net/ipv6.h" #include "net/gnrc.h" +#ifdef MODULE_GNRC_IPV6_NIB +#include "net/gnrc/ipv6/nib.h" +#endif /* MODULE_GNRC_IPV6_NIB */ #ifdef MODULE_NETSTATS_IPV6 #include "net/netstats.h" #endif @@ -278,7 +281,7 @@ int gnrc_netif2_set_from_netdev(gnrc_netif2_t *netif, } else { if (gnrc_netif2_is_rtr_adv(netif)) { - gnrc_ipv6_nib_iface_cease_rtr_adv(netif); + gnrc_ipv6_nib_change_rtr_adv_iface(netif, false); } netif->flags &= ~GNRC_NETIF2_FLAGS_IPV6_FORWARDING; } @@ -286,12 +289,8 @@ int gnrc_netif2_set_from_netdev(gnrc_netif2_t *netif, break; case NETOPT_IPV6_SND_RTR_ADV: assert(opt->data_len == sizeof(netopt_enable_t)); - if (*(((netopt_enable_t *)opt->data)) == NETOPT_ENABLE) { - gnrc_ipv6_nib_iface_start_rtr_adv(netif); - } - else { - gnrc_ipv6_nib_iface_cease_rtr_adv(netif); - } + gnrc_ipv6_nib_change_rtr_adv_iface(netif, + (*(((netopt_enable_t *)opt->data)) == NETOPT_ENABLE)); res = sizeof(netopt_enable_t); break; #endif /* GNRC_IPV6_NIB_CONF_ROUTER */ diff --git a/sys/net/gnrc/network_layer/icmpv6/gnrc_icmpv6.c b/sys/net/gnrc/network_layer/icmpv6/gnrc_icmpv6.c index 1ce69e48ac..9184a29b88 100644 --- a/sys/net/gnrc/network_layer/icmpv6/gnrc_icmpv6.c +++ b/sys/net/gnrc/network_layer/icmpv6/gnrc_icmpv6.c @@ -23,11 +23,7 @@ #include "kernel_types.h" #include "net/ipv6/hdr.h" #include "net/gnrc.h" -#ifndef MODULE_GNRC_IPV6_NIB -#include "net/gnrc/ndp.h" -#else #include "net/gnrc/ipv6/nib.h" -#endif #include "net/protnum.h" #include "od.h" #include "utlist.h" @@ -98,40 +94,6 @@ void gnrc_icmpv6_demux(kernel_pid_t iface, gnrc_pktsnip_t *pkt) break; #endif -#ifndef MODULE_GNRC_IPV6_NIB -#if (defined(MODULE_GNRC_NDP_ROUTER) || defined(MODULE_GNRC_SIXLOWPAN_ND_ROUTER)) - case ICMPV6_RTR_SOL: - DEBUG("icmpv6: router solicitation received\n"); - gnrc_ndp_rtr_sol_handle(iface, pkt, ipv6->data, (ndp_rtr_sol_t *)hdr, - icmpv6->size); - break; -#endif - -#ifdef MODULE_GNRC_NDP - case ICMPV6_RTR_ADV: - DEBUG("icmpv6: router advertisement received\n"); - gnrc_ndp_rtr_adv_handle(iface, pkt, ipv6->data, (ndp_rtr_adv_t *)hdr, - icmpv6->size); - break; - - case ICMPV6_NBR_SOL: - DEBUG("icmpv6: neighbor solicitation received\n"); - gnrc_ndp_nbr_sol_handle(iface, pkt, ipv6->data, (ndp_nbr_sol_t *)hdr, - icmpv6->size); - break; - - case ICMPV6_NBR_ADV: - DEBUG("icmpv6: neighbor advertisement received\n"); - gnrc_ndp_nbr_adv_handle(iface, pkt, ipv6->data, (ndp_nbr_adv_t *)hdr, - icmpv6->size); - break; -#endif - - case ICMPV6_REDIRECT: - DEBUG("icmpv6: redirect message received\n"); - /* TODO */ - break; -#else /* MODULE_GNRC_IPV6_NIB */ case ICMPV6_RTR_SOL: case ICMPV6_RTR_ADV: case ICMPV6_NBR_SOL: @@ -140,9 +102,9 @@ void gnrc_icmpv6_demux(kernel_pid_t iface, gnrc_pktsnip_t *pkt) case ICMPV6_DAR: case ICMPV6_DAC: DEBUG("icmpv6: NDP message received. Handle with gnrc_ipv6_nib\n"); - gnrc_ipv6_nib_handle_pkt(iface, ipv6->data, hdr, icmpv6->size); + gnrc_ipv6_nib_handle_pkt(gnrc_netif2_get_by_pid(iface), + ipv6->data, hdr, icmpv6->size); break; -#endif /* MODULE_GNRC_IPV6_NIB */ default: DEBUG("icmpv6: unknown type field %u\n", hdr->type); diff --git a/sys/net/gnrc/network_layer/ipv6/gnrc_ipv6.c b/sys/net/gnrc/network_layer/ipv6/gnrc_ipv6.c index ffa95c1ccb..e70da32d35 100644 --- a/sys/net/gnrc/network_layer/ipv6/gnrc_ipv6.c +++ b/sys/net/gnrc/network_layer/ipv6/gnrc_ipv6.c @@ -29,11 +29,7 @@ #include "thread.h" #include "utlist.h" -#ifndef MODULE_GNRC_IPV6_NIB -#include "net/gnrc/ipv6/nc.h" -#else #include "net/gnrc/ipv6/nib.h" -#endif #include "net/gnrc/netif2/internal.h" #include "net/gnrc/ipv6/whitelist.h" #include "net/gnrc/ipv6/blacklist.h" @@ -290,83 +286,6 @@ static void *_event_loop(void *args) msg_reply(&msg, &reply); break; -#ifndef MODULE_GNRC_IPV6_NIB -#ifdef MODULE_GNRC_NDP - case GNRC_NDP_MSG_RTR_TIMEOUT: - DEBUG("ipv6: Router timeout received\n"); - ((gnrc_ipv6_nc_t *)msg.content.ptr)->flags &= ~GNRC_IPV6_NC_IS_ROUTER; - break; - - /* XXX reactivate when https://github.com/RIOT-OS/RIOT/issues/5122 is - * solved properly */ - /* case GNRC_NDP_MSG_ADDR_TIMEOUT: */ - /* DEBUG("ipv6: Router advertisement timer event received\n"); */ - /* gnrc_ipv6_netif_remove_addr(KERNEL_PID_UNDEF, */ - /* msg.content.ptr); */ - /* break; */ - - case GNRC_NDP_MSG_NBR_SOL_RETRANS: - DEBUG("ipv6: Neigbor solicitation retransmission timer event received\n"); - gnrc_ndp_retrans_nbr_sol(msg.content.ptr); - break; - - case GNRC_NDP_MSG_NC_STATE_TIMEOUT: - DEBUG("ipv6: Neigbor cache state timeout received\n"); - gnrc_ndp_state_timeout(msg.content.ptr); - break; -#endif -#ifdef MODULE_GNRC_NDP_ROUTER - case GNRC_NDP_MSG_RTR_ADV_RETRANS: - DEBUG("ipv6: Router advertisement retransmission event received\n"); - gnrc_ndp_router_retrans_rtr_adv(msg.content.ptr); - break; - case GNRC_NDP_MSG_RTR_ADV_DELAY: - DEBUG("ipv6: Delayed router advertisement event received\n"); - gnrc_ndp_router_send_rtr_adv(msg.content.ptr); - break; -#endif -#ifdef MODULE_GNRC_NDP_HOST - case GNRC_NDP_MSG_RTR_SOL_RETRANS: - DEBUG("ipv6: Router solicitation retransmission event received\n"); - gnrc_ndp_host_retrans_rtr_sol(msg.content.ptr); - break; -#endif -#ifdef MODULE_GNRC_SIXLOWPAN_ND - case GNRC_SIXLOWPAN_ND_MSG_MC_RTR_SOL: - DEBUG("ipv6: Multicast router solicitation event received\n"); - gnrc_sixlowpan_nd_mc_rtr_sol(msg.content.ptr); - break; - case GNRC_SIXLOWPAN_ND_MSG_UC_RTR_SOL: - DEBUG("ipv6: Unicast router solicitation event received\n"); - gnrc_sixlowpan_nd_uc_rtr_sol(msg.content.ptr); - break; -# ifdef MODULE_GNRC_SIXLOWPAN_CTX - case GNRC_SIXLOWPAN_ND_MSG_DELETE_CTX: - DEBUG("ipv6: Delete 6LoWPAN context event received\n"); - gnrc_sixlowpan_ctx_remove(((((gnrc_sixlowpan_ctx_t *)msg.content.ptr)->flags_id) & - GNRC_SIXLOWPAN_CTX_FLAGS_CID_MASK)); - break; -# endif -#endif -#ifdef MODULE_GNRC_SIXLOWPAN_ND_ROUTER - case GNRC_SIXLOWPAN_ND_MSG_ABR_TIMEOUT: - DEBUG("ipv6: border router timeout event received\n"); - gnrc_sixlowpan_nd_router_abr_remove(msg.content.ptr); - break; - /* XXX reactivate when https://github.com/RIOT-OS/RIOT/issues/5122 is - * solved properly */ - /* case GNRC_SIXLOWPAN_ND_MSG_AR_TIMEOUT: */ - /* DEBUG("ipv6: address registration timeout received\n"); */ - /* gnrc_sixlowpan_nd_router_gc_nc(msg.content.ptr); */ - /* break; */ - case GNRC_NDP_MSG_RTR_ADV_SIXLOWPAN_DELAY: - DEBUG("ipv6: Delayed router advertisement event received\n"); - gnrc_ipv6_nc_t *nc_entry = msg.content.ptr; - gnrc_ndp_internal_send_rtr_adv(nc_entry->iface, NULL, - &(nc_entry->ipv6_addr), false); - break; -#endif -#else /* MODULE_GNRC_IPV6_NIB */ case GNRC_IPV6_NIB_SND_UC_NS: case GNRC_IPV6_NIB_SND_MC_NS: case GNRC_IPV6_NIB_SND_NA: @@ -385,7 +304,6 @@ static void *_event_loop(void *args) DEBUG("ipv6: NIB timer event received\n"); gnrc_ipv6_nib_handle_timer_event(msg.content.ptr, msg.type); break; -#endif /* MODULE_GNRC_IPV6_NIB */ default: break; } @@ -646,38 +564,6 @@ static void _send_multicast(gnrc_netif2_t *netif, gnrc_pktsnip_t *pkt, #endif /* GNRC_NETIF_NUMOF */ } -#ifndef MODULE_GNRC_IPV6_NIB -static inline kernel_pid_t _next_hop_l2addr(uint8_t *l2addr, uint8_t *l2addr_len, - kernel_pid_t iface, ipv6_addr_t *dst, - gnrc_pktsnip_t *pkt) -{ - kernel_pid_t found_iface; -#if defined(MODULE_GNRC_SIXLOWPAN_ND) - (void)pkt; - found_iface = gnrc_sixlowpan_nd_next_hop_l2addr(l2addr, l2addr_len, iface, dst); - if (found_iface > KERNEL_PID_UNDEF) { - return found_iface; - } -#endif -#if defined(MODULE_GNRC_NDP_NODE) - found_iface = gnrc_ndp_node_next_hop_l2addr(l2addr, l2addr_len, iface, dst, pkt); -#elif !defined(MODULE_GNRC_SIXLOWPAN_ND) && defined(MODULE_GNRC_IPV6_NC) - (void)pkt; - gnrc_ipv6_nc_t *nc = gnrc_ipv6_nc_get(iface, dst); - found_iface = gnrc_ipv6_nc_get_l2_addr(l2addr, l2addr_len, nc); -#elif !defined(MODULE_GNRC_SIXLOWPAN_ND) - found_iface = KERNEL_PID_UNDEF; - (void)l2addr; - (void)l2addr_len; - (void)iface; - (void)dst; - (void)pkt; - *l2addr_len = 0; -#endif - return found_iface; -} -#endif /* MODULE_GNRC_IPV6_NIB */ - static void _send(gnrc_pktsnip_t *pkt, bool prep_hdr) { kernel_pid_t iface = KERNEL_PID_UNDEF; @@ -771,32 +657,10 @@ static void _send(gnrc_pktsnip_t *pkt, bool prep_hdr) } } else { -#ifndef MODULE_GNRC_IPV6_NIB - uint8_t l2addr_len = GNRC_IPV6_NC_L2_ADDR_MAX; - uint8_t l2addr[l2addr_len]; - - iface = _next_hop_l2addr(l2addr, &l2addr_len, iface, &hdr->dst, pkt); - - if (iface == KERNEL_PID_UNDEF) { - DEBUG("ipv6: error determining next hop's link layer address\n"); - gnrc_pktbuf_release(pkt); - return; - } - netif = gnrc_netif2_get_by_pid(iface); - assert(netif != NULL); - if (prep_hdr) { - if (_fill_ipv6_hdr(netif, ipv6, payload) < 0) { - /* error on filling up header */ - gnrc_pktbuf_release(pkt); - return; - } - } - - _send_unicast(netif, l2addr, l2addr_len, pkt); -#else /* MODULE_GNRC_IPV6_NIB */ gnrc_ipv6_nib_nc_t nce; + gnrc_netif2_t *netif = gnrc_netif2_get_by_pid(iface); - if (gnrc_ipv6_nib_get_next_hop_l2addr(&hdr->dst, iface, pkt, + if (gnrc_ipv6_nib_get_next_hop_l2addr(&hdr->dst, netif, pkt, &nce) < 0) { /* packet is released by NIB */ return; @@ -814,7 +678,6 @@ static void _send(gnrc_pktsnip_t *pkt, bool prep_hdr) _send_unicast(netif, nce.l2addr, nce.l2addr_len, pkt); -#endif /* MODULE_GNRC_IPV6_NIB */ } } diff --git a/sys/net/gnrc/network_layer/ipv6/netif/gnrc_ipv6_netif.c b/sys/net/gnrc/network_layer/ipv6/netif/gnrc_ipv6_netif.c index 8d71d9092e..b9bf3934d4 100644 --- a/sys/net/gnrc/network_layer/ipv6/netif/gnrc_ipv6_netif.c +++ b/sys/net/gnrc/network_layer/ipv6/netif/gnrc_ipv6_netif.c @@ -25,9 +25,6 @@ #include "net/eui64.h" #include "net/ipv6/addr.h" -#ifdef MODULE_GNRC_IPV6_NIB -#include "net/gnrc/ipv6/nib.h" -#endif #include "net/gnrc/ndp.h" #include "net/gnrc/netapi.h" #include "net/gnrc/netif.h" @@ -176,11 +173,9 @@ static void _ipv6_netif_remove(gnrc_ipv6_netif_t *entry) return; } -#ifndef MODULE_GNRC_IPV6_NIB #ifdef MODULE_GNRC_NDP gnrc_ndp_netif_remove(entry); #endif -#endif /* MODULE_GNRC_IPV6_NIB */ mutex_lock(&entry->mutex); xtimer_remove(&entry->rtr_sol_timer); @@ -240,13 +235,9 @@ void gnrc_ipv6_netif_add(kernel_pid_t pid) mutex_unlock(&free_entry->mutex); -#ifndef MODULE_GNRC_IPV6_NIB #ifdef MODULE_GNRC_NDP gnrc_ndp_netif_add(free_entry); #endif -#else /* MODULE_GNRC_IPV6_NIB */ - gnrc_ipv6_nib_init_iface(pid); -#endif /* MODULE_GNRC_IPV6_NIB */ DEBUG(" * pid = %" PRIkernel_pid " ", free_entry->pid); DEBUG("cur_hl = %d ", free_entry->cur_hl); diff --git a/sys/net/gnrc/network_layer/ipv6/nib/_nib-6ln.c b/sys/net/gnrc/network_layer/ipv6/nib/_nib-6ln.c index 8f0908bdde..e4beb0e09f 100644 --- a/sys/net/gnrc/network_layer/ipv6/nib/_nib-6ln.c +++ b/sys/net/gnrc/network_layer/ipv6/nib/_nib-6ln.c @@ -13,6 +13,7 @@ * @author Martine Lenders <m.lenders@fu-berlin.de> */ +#include "net/gnrc/netif2/internal.h" #include "net/gnrc/ipv6/nib.h" #include "_nib-6ln.h" @@ -26,49 +27,88 @@ static char addr_str[IPV6_ADDR_MAX_STR_LEN]; #endif -static bool _is_iface_eui64(kernel_pid_t iface, const eui64_t *eui64) +static inline bool _is_iface_eui64(gnrc_netif2_t *netif, const eui64_t *eui64) { - eui64_t iface_eui64; + /* TODO: adapt for short addresses */ + return (netif->l2addr_len == sizeof(eui64_t)) && + (memcmp(&netif->l2addr, eui64, netif->l2addr_len) == 0); +} - /* XXX: this *should* return successful so don't test it ;-) */ - gnrc_netapi_get(iface, NETOPT_ADDRESS_LONG, 0, - &iface_eui64, sizeof(iface_eui64)); - return (memcmp(&iface_eui64, eui64, sizeof(iface_eui64)) != 0); +static inline uint8_t _reverse_iid(const ipv6_addr_t *dst, + const gnrc_netif2_t *netif, uint8_t *l2addr) +{ + switch (netif->device_type) { +#ifdef MODULE_NETDEV_ETH + case NETDEV_TYPE_ETHERNET: + l2addr[0] = dst->u8[8] ^ 0x02; + l2addr[1] = dst->u8[9]; + l2addr[2] = dst->u8[10]; + l2addr[3] = dst->u8[13]; + l2addr[4] = dst->u8[14]; + l2addr[5] = dst->u8[15]; + return ETHERNET_ADDR_LEN; +#endif +#ifdef MODULE_NETDEV_IEEE802154 + case NETDEV_TYPE_IEEE802154: + /* assume address was based on EUI-64 + * (see https://tools.ietf.org/html/rfc6775#section-5.2) */ + memcpy(l2addr, &dst->u64[1], sizeof(dst->u64[1])); + l2addr[0] ^= 0x02; + return sizeof(dst->u64[1]); +#endif +#ifdef MODULE_CC110X + case NETDEV_TYPE_CC110X: + l2addr[0] = dst->u8[15]; + return sizeof(uint8_t); +#endif + default: + (void)dst; + (void)l2addr; + return 0; + } } -bool _resolve_addr_from_ipv6(const ipv6_addr_t *dst, kernel_pid_t iface, +bool _resolve_addr_from_ipv6(const ipv6_addr_t *dst, gnrc_netif2_t *netif, gnrc_ipv6_nib_nc_t *nce) { - gnrc_ipv6_netif_t *netif = gnrc_ipv6_netif_get(iface); - bool res = (netif != NULL) && _is_6ln(netif) && + bool res = (netif != NULL) && gnrc_netif2_is_6ln(netif) && ipv6_addr_is_link_local(dst); if (res) { - memcpy(&nce->ipv6, dst, sizeof(nce->ipv6)); - memcpy(&nce->l2addr, &dst->u64[1], sizeof(dst->u64[1])); - nce->l2addr[0] ^= 0x02; - nce->info = 0; - nce->info |= (iface << GNRC_IPV6_NIB_NC_INFO_IFACE_POS) & - GNRC_IPV6_NIB_NC_INFO_IFACE_MASK; - nce->info |= GNRC_IPV6_NIB_NC_INFO_NUD_STATE_REACHABLE; - nce->info |= GNRC_IPV6_NIB_NC_INFO_AR_STATE_REGISTERED; - nce->l2addr_len = sizeof(dst->u64[1]); + uint8_t l2addr_len; + + if ((l2addr_len = _reverse_iid(dst, netif, nce->l2addr)) > 0) { + DEBUG("nib: resolve address %s%%%u by reverse translating to ", + ipv6_addr_to_str(addr_str, dst, sizeof(addr_str)), + (unsigned)netif->pid); + nce->l2addr_len = l2addr_len; + DEBUG("%s\n", + gnrc_netif2_addr_to_str(nce->l2addr, nce->l2addr_len, + addr_str)); + memcpy(&nce->ipv6, dst, sizeof(nce->ipv6)); + nce->info = 0; + nce->info |= (netif->pid << GNRC_IPV6_NIB_NC_INFO_IFACE_POS) & + GNRC_IPV6_NIB_NC_INFO_IFACE_MASK; + nce->info |= GNRC_IPV6_NIB_NC_INFO_NUD_STATE_REACHABLE; + nce->info |= GNRC_IPV6_NIB_NC_INFO_AR_STATE_REGISTERED; + } + else { + res = false; + } } return res; } -uint8_t _handle_aro(kernel_pid_t iface, const ipv6_hdr_t *ipv6, +uint8_t _handle_aro(gnrc_netif2_t *netif, const ipv6_hdr_t *ipv6, const icmpv6_hdr_t *icmpv6, const sixlowpan_nd_opt_ar_t *aro, const ndp_opt_t *sl2ao, _nib_onl_entry_t *nce) { - gnrc_ipv6_netif_t *netif = gnrc_ipv6_netif_get(iface); - #if !GNRC_IPV6_NIB_CONF_6LR (void)sl2ao; #endif assert(netif != NULL); - if (_is_6ln(netif) && (aro->len == SIXLOWPAN_ND_OPT_AR_LEN)) { + if (gnrc_netif2_is_6ln(netif) && (aro->len == SIXLOWPAN_ND_OPT_AR_LEN)) { DEBUG("nib: valid ARO received\n"); DEBUG(" - length: %u\n", aro->len); DEBUG(" - status: %u\n", aro->status); @@ -78,7 +118,7 @@ uint8_t _handle_aro(kernel_pid_t iface, const ipv6_hdr_t *ipv6, aro->eui64.uint8[3], aro->eui64.uint8[4], aro->eui64.uint8[5], aro->eui64.uint8[6], aro->eui64.uint8[7]); if (icmpv6->type == ICMPV6_NBR_ADV) { - if (!_is_iface_eui64(iface, &aro->eui64)) { + if (!_is_iface_eui64(netif, &aro->eui64)) { DEBUG("nib: ARO EUI-64 is not mine, ignoring ARO\n"); return _ADDR_REG_STATUS_IGNORE; } @@ -92,7 +132,7 @@ uint8_t _handle_aro(kernel_pid_t iface, const ipv6_hdr_t *ipv6, (byteorder_ntohs(aro->ltime) - 1U) * SEC_PER_MIN * MS_PER_SEC; DEBUG("nib: Address registration successful. " - "Scheduling re-registration in %ums\n", + "Scheduling re-registration in %" PRIu32 "ms\n", next_ns); assert(nce != NULL); _evtimer_add(nce, GNRC_IPV6_NIB_SND_UC_NS, &nce->nud_timeout, @@ -103,22 +143,19 @@ uint8_t _handle_aro(kernel_pid_t iface, const ipv6_hdr_t *ipv6, DEBUG("nib: Address registration reports duplicate. " "Removing address %s%%%u\n", ipv6_addr_to_str(addr_str, - &((ndp_nbr_adv_t *)icmpv6)->tgt, - sizeof(addr_str)), - iface); - gnrc_ipv6_netif_remove_addr(iface, - &((ndp_nbr_adv_t *)icmpv6)->tgt); + &ipv6->dst, + sizeof(addr_str)), netif->pid); + gnrc_netif2_ipv6_addr_remove(netif, &ipv6->dst); /* TODO: generate new address */ break; case SIXLOWPAN_ND_STATUS_NC_FULL: { DEBUG("nib: Router's neighbor cache is full. " "Searching new router for DAD\n"); - _nib_dr_entry_t *dr = _nib_drl_get(&ipv6->src, iface); + _nib_dr_entry_t *dr = _nib_drl_get(&ipv6->src, netif->pid); assert(dr != NULL); /* otherwise we wouldn't be here */ _nib_drl_remove(dr); if (_nib_drl_iter(NULL) == NULL) { /* no DRL left */ - _nib_iface_t *nib_iface = _nib_iface_get(iface); - nib_iface->rs_sent = 0; + netif->ipv6.rs_sent = 0; /* TODO: search new router */ } else { @@ -131,8 +168,9 @@ uint8_t _handle_aro(kernel_pid_t iface, const ipv6_hdr_t *ipv6, return aro->status; } #if GNRC_IPV6_NIB_CONF_6LR - else if (_is_6lr(netif) && (icmpv6->type == ICMPV6_NBR_SOL)) { - return _reg_addr_upstream(iface, ipv6, icmpv6, aro, sl2ao); + else if (gnrc_netif2_is_6lr(netif) && + (icmpv6->type == ICMPV6_NBR_SOL)) { + return _reg_addr_upstream(netif, ipv6, icmpv6, aro, sl2ao); } #endif } diff --git a/sys/net/gnrc/network_layer/ipv6/nib/_nib-6ln.h b/sys/net/gnrc/network_layer/ipv6/nib/_nib-6ln.h index 6967c3a8d9..1ba822bf58 100644 --- a/sys/net/gnrc/network_layer/ipv6/nib/_nib-6ln.h +++ b/sys/net/gnrc/network_layer/ipv6/nib/_nib-6ln.h @@ -44,38 +44,23 @@ extern "C" { */ #define _ADDR_REG_STATUS_IGNORE (4) -/** - * @brief Checks if interface represents a 6LN - * - * @todo Use corresponding function in `gnrc_netif2` instead. - * - * @param[in] netif A network interface. - * - * @return true, when the @p netif represents a 6LN. - * @return false, when the @p netif does not represent a 6LN. - */ -static inline bool _is_6ln(const gnrc_ipv6_netif_t *netif) -{ - return (netif->flags & GNRC_IPV6_NETIF_FLAGS_SIXLOWPAN); -} - /** * @brief Resolves address statically from destination address using reverse * translation of the IID * * @param[in] dst A destination address. - * @param[in] iface The interface to @p dst. + * @param[in] netif The interface to @p dst. * @param[out] nce Neighbor cache entry to resolve into * * @return true when @p nce was set, false when not. */ -bool _resolve_addr_from_ipv6(const ipv6_addr_t *dst, kernel_pid_t iface, +bool _resolve_addr_from_ipv6(const ipv6_addr_t *dst, gnrc_netif2_t *netif, gnrc_ipv6_nib_nc_t *nce); /** * @brief Handles ARO * - * @param[in] iface The interface the ARO-carrying message came over. + * @param[in] netif The interface the ARO-carrying message came over. * @param[in] ipv6 The IPv6 header of the message carrying the ARO. * @param[in] icmpv6 The message carrying the ARO. * @param[in] aro ARO that carries the address registration information. @@ -85,13 +70,12 @@ bool _resolve_addr_from_ipv6(const ipv6_addr_t *dst, kernel_pid_t iface, * @return registration status of the address (including * @ref _ADDR_REG_STATUS_TENTATIVE and @ref _ADDR_REG_STATUS_IGNORE). */ -uint8_t _handle_aro(kernel_pid_t iface, const ipv6_hdr_t *ipv6, +uint8_t _handle_aro(gnrc_netif2_t *netif, const ipv6_hdr_t *ipv6, const icmpv6_hdr_t *icmpv6, const sixlowpan_nd_opt_ar_t *aro, const ndp_opt_t *sl2ao, _nib_onl_entry_t *nce); #else /* GNRC_IPV6_NIB_CONF_6LN || defined(DOXYGEN) */ -#define _is_6ln(netif) (false) -#define _resolve_addr_from_ipv6(dst, iface, nce) (false) +#define _resolve_addr_from_ipv6(dst, netif, nce) (false) /* _handle_aro() doesn't make sense without 6LR so don't even use it * => throw error in case it is compiled in => don't define it here as NOP macro */ diff --git a/sys/net/gnrc/network_layer/ipv6/nib/_nib-6lr.c b/sys/net/gnrc/network_layer/ipv6/nib/_nib-6lr.c index b85ed57558..9cfaf55f0a 100644 --- a/sys/net/gnrc/network_layer/ipv6/nib/_nib-6lr.c +++ b/sys/net/gnrc/network_layer/ipv6/nib/_nib-6lr.c @@ -14,6 +14,7 @@ */ #include "net/gnrc/ipv6/nib.h" +#include "net/gnrc/netif2/internal.h" #include "net/gnrc/sixlowpan/nd.h" #include "_nib-6lr.h" @@ -47,13 +48,13 @@ static uint8_t _update_nce_ar_state(const sixlowpan_nd_opt_ar_t *aro, } } -uint8_t _reg_addr_upstream(kernel_pid_t iface, const ipv6_hdr_t *ipv6, +uint8_t _reg_addr_upstream(gnrc_netif2_t *netif, const ipv6_hdr_t *ipv6, const icmpv6_hdr_t *icmpv6, const sixlowpan_nd_opt_ar_t *aro, const ndp_opt_t *sl2ao) { if (!ipv6_addr_is_unspecified(&ipv6->src) && (sl2ao != NULL)) { - _nib_onl_entry_t *nce = _nib_onl_get(&ipv6->src, iface); + _nib_onl_entry_t *nce = _nib_onl_get(&ipv6->src, netif->pid); DEBUG("nib: Trying to register %s with EUI-64 " "%02x:%02x:%02x:%02x:%02x:%02x:%02x:%02x\n", @@ -66,8 +67,8 @@ uint8_t _reg_addr_upstream(kernel_pid_t iface, const ipv6_hdr_t *ipv6, #if GNRC_IPV6_NIB_CONF_MULTIHOP_DAD /* TODO */ #endif - if (byteorder_ntohs(aro->ltime) != 0) { - _handle_sl2ao(iface, ipv6, icmpv6, sl2ao); + if (aro->ltime.u16 != 0) { + _handle_sl2ao(netif, ipv6, icmpv6, sl2ao); return _update_nce_ar_state(aro, nce); } else if (nce != NULL) { @@ -88,7 +89,8 @@ uint8_t _reg_addr_upstream(kernel_pid_t iface, const ipv6_hdr_t *ipv6, return _ADDR_REG_STATUS_IGNORE; } -gnrc_pktsnip_t *_copy_and_handle_aro(kernel_pid_t iface, const ipv6_hdr_t *ipv6, +gnrc_pktsnip_t *_copy_and_handle_aro(gnrc_netif2_t *netif, + const ipv6_hdr_t *ipv6, const ndp_nbr_sol_t *nbr_sol, const sixlowpan_nd_opt_ar_t *aro, const ndp_opt_t *sl2ao) @@ -96,7 +98,7 @@ gnrc_pktsnip_t *_copy_and_handle_aro(kernel_pid_t iface, const ipv6_hdr_t *ipv6, gnrc_pktsnip_t *reply_aro = NULL; if (aro != NULL) { - uint8_t status = _handle_aro(iface, ipv6, (icmpv6_hdr_t *)nbr_sol, aro, + uint8_t status = _handle_aro(netif, ipv6, (icmpv6_hdr_t *)nbr_sol, aro, sl2ao, NULL); if ((status != _ADDR_REG_STATUS_TENTATIVE) && diff --git a/sys/net/gnrc/network_layer/ipv6/nib/_nib-6lr.h b/sys/net/gnrc/network_layer/ipv6/nib/_nib-6lr.h index 0fc0049e58..6248600e69 100644 --- a/sys/net/gnrc/network_layer/ipv6/nib/_nib-6lr.h +++ b/sys/net/gnrc/network_layer/ipv6/nib/_nib-6lr.h @@ -33,21 +33,6 @@ extern "C" { #endif #if GNRC_IPV6_NIB_CONF_6LR || defined(DOXYGEN) -/** - * @brief Checks if interface represents a 6LR - * - * @todo Use corresponding function in `gnrc_netif2` instead. - * - * @param[in] netif A network interface. - * - * @return true, when the @p netif represents a 6LR. - * @return false, when the @p netif does not represent a 6LR. - */ -static inline bool _is_6lr(const gnrc_ipv6_netif_t *netif) -{ - return _is_6ln(netif) && (netif->flags & GNRC_IPV6_NETIF_FLAGS_ROUTER); -} - /** * @brief Gets address registration state of a neighbor * @@ -81,17 +66,17 @@ static inline void _set_ar_state(_nib_onl_entry_t *entry, uint16_t state) * @param[in] netif A network interface. * @param[in] icmpv6 An ICMPv6 message. */ -static inline bool _rtr_sol_on_6lr(const gnrc_ipv6_netif_t *netif, +static inline bool _rtr_sol_on_6lr(const gnrc_netif2_t *netif, const icmpv6_hdr_t *icmpv6) { - return _is_6lr(netif) && (icmpv6->type == ICMPV6_RTR_SOL); + return gnrc_netif2_is_6lr(netif) && (icmpv6->type == ICMPV6_RTR_SOL); } /** * @brief Registers an address to the (upstream; in case of multihop DAD) * router * - * @param[in] iface The interface the ARO-carrying NS came over. + * @param[in] netif The interface the ARO-carrying NS came over. * @param[in] ipv6 The IPv6 header of the message carrying the ARO. * @param[in] icmpv6 The neighbor solicitation carrying the ARO * (handed over as @ref icmpv6_hdr_t, since it is just @@ -102,7 +87,7 @@ static inline bool _rtr_sol_on_6lr(const gnrc_ipv6_netif_t *netif, * @return registration status of the address (including * @ref _ADDR_REG_STATUS_TENTATIVE and @ref _ADDR_REG_STATUS_IGNORE). */ -uint8_t _reg_addr_upstream(kernel_pid_t iface, const ipv6_hdr_t *ipv6, +uint8_t _reg_addr_upstream(gnrc_netif2_t *netif, const ipv6_hdr_t *ipv6, const icmpv6_hdr_t *icmpv6, const sixlowpan_nd_opt_ar_t *aro, const ndp_opt_t *sl2ao); @@ -111,7 +96,7 @@ uint8_t _reg_addr_upstream(kernel_pid_t iface, const ipv6_hdr_t *ipv6, /** * @brief Handles and copies ARO from NS to NA * - * @param[in] iface The interface the ARO-carrying NS came over. + * @param[in] netif The interface the ARO-carrying NS came over. * @param[in] ipv6 The IPv6 header of the message carrying the original * ARO. * @param[in] nbr_sol The neighbor solicitation carrying the original ARO @@ -123,16 +108,15 @@ uint8_t _reg_addr_upstream(kernel_pid_t iface, const ipv6_hdr_t *ipv6, * @return registration status of the address (including * @ref _ADDR_REG_STATUS_TENTATIVE and @ref _ADDR_REG_STATUS_IGNORE). */ -gnrc_pktsnip_t *_copy_and_handle_aro(kernel_pid_t iface, const ipv6_hdr_t *ipv6, +gnrc_pktsnip_t *_copy_and_handle_aro(gnrc_netif2_t *netif, const ipv6_hdr_t *ipv6, const ndp_nbr_sol_t *nbr_sol, const sixlowpan_nd_opt_ar_t *aro, const ndp_opt_t *sl2ao); #else /* GNRC_IPV6_NIB_CONF_6LR || defined(DOXYGEN) */ -#define _is_6lr(netif) (false) #define _rtr_sol_on_6lr(netif, icmpv6) (false) #define _get_ar_state(nbr) (_ADDR_REG_STATUS_IGNORE) #define _set_ar_state(nbr, state) (void)nbr; (void)state -#define _copy_and_handle_aro(iface, ipv6, icmpv6, aro, sl2ao) \ +#define _copy_and_handle_aro(netif, ipv6, icmpv6, aro, sl2ao) \ (NULL) /* _reg_addr_upstream() doesn't make sense without 6LR so don't even use it * => throw error in case it is compiled in => don't define it here as NOP macro diff --git a/sys/net/gnrc/network_layer/ipv6/nib/_nib-arsm.c b/sys/net/gnrc/network_layer/ipv6/nib/_nib-arsm.c index c678f3cecb..22ac8c2ce1 100644 --- a/sys/net/gnrc/network_layer/ipv6/nib/_nib-arsm.c +++ b/sys/net/gnrc/network_layer/ipv6/nib/_nib-arsm.c @@ -16,6 +16,10 @@ #include "xtimer.h" #include "net/gnrc/ndp2.h" #include "net/gnrc/ipv6/nib.h" +#include "net/gnrc/netif2/internal.h" +#ifdef MODULE_GNRC_SIXLOWPAN_ND +#include "net/gnrc/sixlowpan/nd.h" +#endif #include "_nib-arsm.h" #include "_nib-6lr.h" @@ -36,26 +40,50 @@ static char addr_str[IPV6_ADDR_MAX_STR_LEN]; * * @return The length of the L2 address carried in @p opt. */ -static inline unsigned _get_l2addr_len(gnrc_ipv6_netif_t *netif, +static inline unsigned _get_l2addr_len(gnrc_netif2_t *netif, const ndp_opt_t *opt); -void _snd_ns(const ipv6_addr_t *tgt, gnrc_ipv6_netif_t *netif, +void _snd_ns(const ipv6_addr_t *tgt, gnrc_netif2_t *netif, const ipv6_addr_t *src, const ipv6_addr_t *dst) { gnrc_pktsnip_t *ext_opt = NULL; +#ifdef MODULE_GNRC_SIXLOWPAN_ND + _nib_dr_entry_t *dr = _nib_drl_get_dr(); + + assert(netif != NULL); + /* add ARO based on interface */ + if ((src != NULL) && gnrc_netif2_is_6ln(netif) && + (_nib_onl_get_if(dr->next_hop) == (unsigned)netif->pid) && + ipv6_addr_equal(&dr->next_hop->ipv6, dst)) { + netdev_t *dev = netif->dev; + uint8_t l2src[GNRC_NETIF2_L2ADDR_MAXLEN]; + size_t l2src_len = (uint16_t)dev->driver->get(dev, NETOPT_ADDRESS_LONG, + l2src, sizeof(l2src)); + if (l2src_len != sizeof(eui64_t)) { + DEBUG("nib: can't get EUI-64 of the interface for ARO\n"); + return; + } + ext_opt = gnrc_sixlowpan_nd_opt_ar_build(0, GNRC_SIXLOWPAN_ND_AR_LTIME, + (eui64_t *)l2src, NULL); + if (ext_opt == NULL) { + DEBUG("nib: error allocating ARO.\n"); + return; + } + } +#endif /* MODULE_GNRC_SIXLOWPAN_ND */ gnrc_ndp2_nbr_sol_send(tgt, netif, src, dst, ext_opt); } void _snd_uc_ns(_nib_onl_entry_t *nbr, bool reset) { - gnrc_ipv6_netif_t *netif = gnrc_ipv6_netif_get(_nib_onl_get_if(nbr)); - _nib_iface_t *iface = _nib_iface_get(_nib_onl_get_if(nbr)); + gnrc_netif2_t *netif = gnrc_netif2_get_by_pid(_nib_onl_get_if(nbr)); - DEBUG("unicast to %s (retrans. timer = %ums)\n", + assert(netif != NULL); + gnrc_netif2_acquire(netif); + DEBUG("nib: unicast to %s (retrans. timer = %ums)\n", ipv6_addr_to_str(addr_str, &nbr->ipv6, sizeof(addr_str)), - (unsigned)iface->retrans_time); - assert((netif != NULL) && (iface != NULL)); + (unsigned)netif->ipv6.retrans_time); #if GNRC_IPV6_NIB_CONF_ARSM if (reset) { nbr->ns_sent = 0; @@ -65,20 +93,20 @@ void _snd_uc_ns(_nib_onl_entry_t *nbr, bool reset) #endif _snd_ns(&nbr->ipv6, netif, NULL, &nbr->ipv6); _evtimer_add(nbr, GNRC_IPV6_NIB_SND_UC_NS, &nbr->nud_timeout, - iface->retrans_time); + netif->ipv6.retrans_time); + gnrc_netif2_release(netif); #if GNRC_IPV6_NIB_CONF_ARSM nbr->ns_sent++; #endif } -void _handle_sl2ao(kernel_pid_t iface, const ipv6_hdr_t *ipv6, +void _handle_sl2ao(gnrc_netif2_t *netif, const ipv6_hdr_t *ipv6, const icmpv6_hdr_t *icmpv6, const ndp_opt_t *sl2ao) { - _nib_onl_entry_t *nce = _nib_onl_get(&ipv6->src, iface); - gnrc_ipv6_netif_t *netif = gnrc_ipv6_netif_get(iface); + assert(netif != NULL); + _nib_onl_entry_t *nce = _nib_onl_get(&ipv6->src, netif->pid); unsigned l2addr_len; - assert(netif != NULL); l2addr_len = _get_l2addr_len(netif, sl2ao); if (l2addr_len == 0U) { DEBUG("nib: Unexpected SL2AO length. Ignoring SL2AO\n"); @@ -93,13 +121,14 @@ void _handle_sl2ao(kernel_pid_t iface, const ipv6_hdr_t *ipv6, !_rtr_sol_on_6lr(netif, icmpv6)) { DEBUG("nib: L2 address differs. Setting STALE\n"); evtimer_del(&_nib_evtimer, &nce->nud_timeout.event); - _set_nud_state(nce, GNRC_IPV6_NIB_NC_INFO_NUD_STATE_STALE); + _set_nud_state(netif, nce, GNRC_IPV6_NIB_NC_INFO_NUD_STATE_STALE); } #endif /* GNRC_IPV6_NIB_CONF_ARSM */ if ((nce == NULL) || !(nce->mode & _NC)) { DEBUG("nib: Creating NCE for (ipv6 = %s, iface = %u, nud_state = STALE)\n", - ipv6_addr_to_str(addr_str, &ipv6->src, sizeof(addr_str)), iface); - nce = _nib_nc_add(&ipv6->src, iface, + ipv6_addr_to_str(addr_str, &ipv6->src, sizeof(addr_str)), + netif->pid); + nce = _nib_nc_add(&ipv6->src, netif->pid, GNRC_IPV6_NIB_NC_INFO_NUD_STATE_STALE); if (nce != NULL) { if (icmpv6->type == ICMPV6_NBR_SOL) { @@ -126,13 +155,13 @@ void _handle_sl2ao(kernel_pid_t iface, const ipv6_hdr_t *ipv6, if (icmpv6->type == ICMPV6_RTR_ADV) { DEBUG("nib: %s%%%u is a router\n", ipv6_addr_to_str(addr_str, &nce->ipv6, sizeof(addr_str)), - iface); + netif->pid); nce->info |= GNRC_IPV6_NIB_NC_INFO_IS_ROUTER; } else if (icmpv6->type != ICMPV6_NBR_SOL) { DEBUG("nib: %s%%%u is probably not a router\n", ipv6_addr_to_str(addr_str, &nce->ipv6, sizeof(addr_str)), - iface); + netif->pid); nce->info &= ~GNRC_IPV6_NIB_NC_INFO_IS_ROUTER; } #if GNRC_IPV6_NIB_CONF_ARSM @@ -146,27 +175,40 @@ void _handle_sl2ao(kernel_pid_t iface, const ipv6_hdr_t *ipv6, } } -static inline unsigned _get_l2addr_len(gnrc_ipv6_netif_t *netif, +static inline unsigned _get_l2addr_len(gnrc_netif2_t *netif, const ndp_opt_t *opt) { -#if GNRC_IPV6_NIB_CONF_6LN - if (_is_6ln(netif)) { - switch (opt->len) { - case 1U: - return 2U; - case 2U: - return 8U; - default: - return 0U; - } - } -#else - (void)netif; -#endif /* GNRC_IPV6_NIB_CONF_6LN */ - if (opt->len == 1U) { - return 6U; + switch (netif->device_type) { +#ifdef MODULE_CC110X + case NETDEV_TYPE_CC110X: + (void)opt; + return sizeof(uint8_t); +#endif +#ifdef MODULE_NETDEV_ETH + case NETDEV_TYPE_ETHERNET: + (void)opt; + return ETHERNET_ADDR_LEN; +#endif +#ifdef MODULE_NETDEV_NRFMIN + case NETDEV_TYPE_NRFMIN: + (void)opt; + return sizeof(uint16_t); +#endif +#ifdef MODULE_NETDEV_IEEE802154 + case NETDEV_TYPE_IEEE802154: + switch (opt->len) { + case 1U: + return IEEE802154_SHORT_ADDRESS_LEN; + case 2U: + return IEEE802154_LONG_ADDRESS_LEN; + default: + return 0U; + } +#endif + default: + (void)opt; + return 0U; } - return 0U; } #if GNRC_IPV6_NIB_CONF_ARSM @@ -207,7 +249,7 @@ static inline bool _rflag_set(const ndp_nbr_adv_t *nbr_adv); * * @param[in] nce A neighbor cache entry. * @param[in] tl2ao The TL2AO. - * @param[in] iface The interface the TL2AO came over. + * @param[in] netif The interface the TL2AO came over. * @param[in] tl2ao_addr_len Length of the L2 address in the TL2AO. * * @return `true`, if the TL2AO changes the NCE. @@ -215,7 +257,7 @@ static inline bool _rflag_set(const ndp_nbr_adv_t *nbr_adv); */ static inline bool _tl2ao_changes_nce(_nib_onl_entry_t *nce, const ndp_opt_t *tl2ao, - kernel_pid_t iface, + gnrc_netif2_t *netif, unsigned tl2ao_addr_len); void _handle_snd_ns(_nib_onl_entry_t *nbr) @@ -233,7 +275,10 @@ void _handle_snd_ns(_nib_onl_entry_t *nbr) break; case GNRC_IPV6_NIB_NC_INFO_NUD_STATE_PROBE: if (nbr->ns_sent >= NDP_MAX_UC_SOL_NUMOF) { - _set_nud_state(nbr, GNRC_IPV6_NIB_NC_INFO_NUD_STATE_UNREACHABLE); + gnrc_netif2_t *netif = gnrc_netif2_get_by_pid(_nib_onl_get_if(nbr)); + + _set_nud_state(netif, nbr, + GNRC_IPV6_NIB_NC_INFO_NUD_STATE_UNREACHABLE); } /* falls through intentionally */ case GNRC_IPV6_NIB_NC_INFO_NUD_STATE_UNREACHABLE: @@ -253,13 +298,16 @@ void _handle_state_timeout(_nib_onl_entry_t *nbr) DEBUG("nib: Timeout reachability\n"); new_state = GNRC_IPV6_NIB_NC_INFO_NUD_STATE_STALE; /* falls through intentionally */ - case GNRC_IPV6_NIB_NC_INFO_NUD_STATE_DELAY: - _set_nud_state(nbr, new_state); + case GNRC_IPV6_NIB_NC_INFO_NUD_STATE_DELAY: { + gnrc_netif2_t *netif = gnrc_netif2_get_by_pid(_nib_onl_get_if(nbr)); + + _set_nud_state(netif, nbr, new_state); if (new_state == GNRC_IPV6_NIB_NC_INFO_NUD_STATE_PROBE) { DEBUG("nib: Timeout DELAY state\n"); _probe_nbr(nbr, true); } break; + } } } @@ -274,24 +322,25 @@ void _probe_nbr(_nib_onl_entry_t *nbr, bool reset) break; case GNRC_IPV6_NIB_NC_INFO_NUD_STATE_INCOMPLETE: case GNRC_IPV6_NIB_NC_INFO_NUD_STATE_UNREACHABLE: { - _nib_iface_t *iface = _nib_iface_get(_nib_onl_get_if(nbr)); + gnrc_netif2_t *netif = gnrc_netif2_get_by_pid(_nib_onl_get_if(nbr)); uint32_t next_ns = _evtimer_lookup(nbr, GNRC_IPV6_NIB_SND_MC_NS); - if (next_ns > iface->retrans_time) { - gnrc_ipv6_netif_t *netif = gnrc_ipv6_netif_get(_nib_onl_get_if(nbr)); + + assert(netif != NULL); + gnrc_netif2_acquire(netif); + if (next_ns > netif->ipv6.retrans_time) { ipv6_addr_t sol_nodes; - uint32_t retrans_time = iface->retrans_time; + uint32_t retrans_time = netif->ipv6.retrans_time; DEBUG("multicast to %s's solicited nodes ", ipv6_addr_to_str(addr_str, &nbr->ipv6, sizeof(addr_str))); - assert(netif != NULL); if (reset) { nbr->ns_sent = 0; } if (state == GNRC_IPV6_NIB_NC_INFO_NUD_STATE_UNREACHABLE) { /* first 3 retransmissions in PROBE, assume 1 higher to - * not send after iface->retrans_timer sec again, + * not send after netif->ipv6.retrans_timer sec again, * but the next backoff after that => subtract 2 */ retrans_time = _exp_backoff_retrans_timer(nbr->ns_sent - 2, retrans_time); @@ -312,9 +361,10 @@ void _probe_nbr(_nib_onl_entry_t *nbr, bool reset) "a multicast NS within %ums)\n", ipv6_addr_to_str(addr_str, &nbr->ipv6, sizeof(addr_str)), - (unsigned)iface->retrans_time); + (unsigned)netif->ipv6.retrans_time); } #endif + gnrc_netif2_release(netif); } break; case GNRC_IPV6_NIB_NC_INFO_NUD_STATE_PROBE: @@ -324,10 +374,9 @@ void _probe_nbr(_nib_onl_entry_t *nbr, bool reset) } } -void _handle_adv_l2(kernel_pid_t iface, _nib_onl_entry_t *nce, +void _handle_adv_l2(gnrc_netif2_t *netif, _nib_onl_entry_t *nce, const icmpv6_hdr_t *icmpv6, const ndp_opt_t *tl2ao) { - gnrc_ipv6_netif_t *netif = gnrc_ipv6_netif_get(iface); unsigned l2addr_len = 0; assert(nce != NULL); @@ -342,7 +391,7 @@ void _handle_adv_l2(kernel_pid_t iface, _nib_onl_entry_t *nce, if ((_get_nud_state(nce) == GNRC_IPV6_NIB_NC_INFO_NUD_STATE_INCOMPLETE) || _oflag_set((ndp_nbr_adv_t *)icmpv6) || _redirect_with_tl2ao(icmpv6, tl2ao) || - _tl2ao_changes_nce(nce, tl2ao, iface, l2addr_len)) { + _tl2ao_changes_nce(nce, tl2ao, netif, l2addr_len)) { bool nce_was_incomplete = (_get_nud_state(nce) == GNRC_IPV6_NIB_NC_INFO_NUD_STATE_INCOMPLETE); if (tl2ao != NULL) { @@ -353,17 +402,17 @@ void _handle_adv_l2(kernel_pid_t iface, _nib_onl_entry_t *nce, nce->l2addr_len = 0; } if (_sflag_set((ndp_nbr_adv_t *)icmpv6)) { - _set_reachable(iface, nce); + _set_reachable(netif, nce); } else if ((icmpv6->type != ICMPV6_NBR_ADV) || !_sflag_set((ndp_nbr_adv_t *)icmpv6) || (!nce_was_incomplete && - _tl2ao_changes_nce(nce, tl2ao, iface, l2addr_len))) { + _tl2ao_changes_nce(nce, tl2ao, netif, l2addr_len))) { DEBUG("nib: Set %s%%%u to STALE\n", ipv6_addr_to_str(addr_str, &nce->ipv6, sizeof(addr_str)), - iface); + (unsigned)netif->pid); evtimer_del(&_nib_evtimer, &nce->nud_timeout.event); - _set_nud_state(nce, GNRC_IPV6_NIB_NC_INFO_NUD_STATE_STALE); + _set_nud_state(netif, nce, GNRC_IPV6_NIB_NC_INFO_NUD_STATE_STALE); } if (_oflag_set((ndp_nbr_adv_t *)icmpv6) || ((icmpv6->type == ICMPV6_NBR_ADV) && nce_was_incomplete)) { @@ -391,30 +440,57 @@ void _handle_adv_l2(kernel_pid_t iface, _nib_onl_entry_t *nce, if ((icmpv6->type == ICMPV6_NBR_ADV) && !_sflag_set((ndp_nbr_adv_t *)icmpv6) && (_get_nud_state(nce) == GNRC_IPV6_NIB_NC_INFO_NUD_STATE_REACHABLE) && - _tl2ao_changes_nce(nce, tl2ao, iface, l2addr_len)) { + _tl2ao_changes_nce(nce, tl2ao, netif, l2addr_len)) { evtimer_del(&_nib_evtimer, &nce->nud_timeout.event); - _set_nud_state(nce, GNRC_IPV6_NIB_NC_INFO_NUD_STATE_STALE); + _set_nud_state(netif, nce, GNRC_IPV6_NIB_NC_INFO_NUD_STATE_STALE); } } else if ((icmpv6->type == ICMPV6_NBR_ADV) && (_get_nud_state(nce) != GNRC_IPV6_NIB_NC_INFO_NUD_STATE_INCOMPLETE) && (_get_nud_state(nce) != GNRC_IPV6_NIB_NC_INFO_NUD_STATE_UNMANAGED) && _sflag_set((ndp_nbr_adv_t *)icmpv6) && - !_tl2ao_changes_nce(nce, tl2ao, iface, l2addr_len)) { - _set_reachable(iface, nce); + !_tl2ao_changes_nce(nce, tl2ao, netif, l2addr_len)) { + _set_reachable(netif, nce); } } -void _set_reachable(unsigned iface, _nib_onl_entry_t *nce) +void _recalc_reach_time(gnrc_netif2_ipv6_t *netif) { - _nib_iface_t *nib_netif = _nib_iface_get(iface); + const uint32_t half = (netif->reach_time_base >> 1); + + netif->reach_time = random_uint32_range(half, + netif->reach_time_base + half); + _evtimer_add(netif, GNRC_IPV6_NIB_RECALC_REACH_TIME, + &netif->recalc_reach_time, + GNRC_IPV6_NIB_CONF_REACH_TIME_RESET); +} +void _set_reachable(gnrc_netif2_t *netif, _nib_onl_entry_t *nce) +{ DEBUG("nib: Set %s%%%u to REACHABLE for %ums\n", ipv6_addr_to_str(addr_str, &nce->ipv6, sizeof(addr_str)), - iface, (unsigned)nib_netif->reach_time); - _set_nud_state(nce, GNRC_IPV6_NIB_NC_INFO_NUD_STATE_REACHABLE); + netif->pid, (unsigned)netif->ipv6.reach_time); + _set_nud_state(netif, nce, GNRC_IPV6_NIB_NC_INFO_NUD_STATE_REACHABLE); _evtimer_add(nce, GNRC_IPV6_NIB_REACH_TIMEOUT, &nce->nud_timeout, - nib_netif->reach_time); + netif->ipv6.reach_time); +} + +void _set_nud_state(gnrc_netif2_t *netif, _nib_onl_entry_t *nce, + uint16_t state) +{ + nce->info &= ~GNRC_IPV6_NIB_NC_INFO_NUD_STATE_MASK; + nce->info |= state; + +#if GNRC_IPV6_NIB_CONF_ROUTER + gnrc_netif2_acquire(netif); + if ((netif != NULL) && (netif->ipv6.route_info_cb)) { + netif->ipv6.route_info_cb(GNRC_IPV6_NIB_ROUTE_INFO_TYPE_NSC, + &nce->ipv6, (void *)((intptr_t)state)); + } + gnrc_netif2_release(netif); +#else + (void)netif; +#endif } /* internal functions */ @@ -443,13 +519,13 @@ static inline bool _redirect_with_tl2ao(icmpv6_hdr_t *icmpv6, ndp_opt_t *tl2ao) static inline bool _tl2ao_changes_nce(_nib_onl_entry_t *nce, const ndp_opt_t *tl2ao, - kernel_pid_t iface, + gnrc_netif2_t *netif, unsigned tl2ao_addr_len) { return ((tl2ao != NULL) && (((nce->l2addr_len != tl2ao_addr_len) && (memcmp(nce->l2addr, tl2ao + 1, tl2ao_addr_len) != 0)) || - (_nib_onl_get_if(nce) != (unsigned)iface))); + (_nib_onl_get_if(nce) != (unsigned)netif->pid))); } static inline bool _oflag_set(const ndp_nbr_adv_t *nbr_adv) diff --git a/sys/net/gnrc/network_layer/ipv6/nib/_nib-arsm.h b/sys/net/gnrc/network_layer/ipv6/nib/_nib-arsm.h index 44b681273d..b0c356f3c4 100644 --- a/sys/net/gnrc/network_layer/ipv6/nib/_nib-arsm.h +++ b/sys/net/gnrc/network_layer/ipv6/nib/_nib-arsm.h @@ -24,6 +24,7 @@ #include <stdint.h> #include "net/gnrc/ipv6/nib/conf.h" +#include "net/gnrc/netif2.h" #include "net/ndp.h" #include "net/icmpv6.h" @@ -47,7 +48,7 @@ extern "C" { * @param[in] dst Destination address for neighbor solicitation. May not * be NULL. */ -void _snd_ns(const ipv6_addr_t *tgt, gnrc_ipv6_netif_t *netif, +void _snd_ns(const ipv6_addr_t *tgt, gnrc_netif2_t *netif, const ipv6_addr_t *src, const ipv6_addr_t *dst); /** @@ -72,12 +73,12 @@ void _snd_uc_ns(_nib_onl_entry_t *nbr, bool reset); * to the ARSM, but ARSM isn't the only mechanism using it (e.g. the * 6Lo address registration uses it). * - * @param[in] iface Interface the SL2AO was sent over. + * @param[in] netif Interface the SL2AO was sent over. * @param[in] ipv6 IPv6 header of the message carrying the SL2AO. * @param[in] icmpv6 ICMPv6 header of the message carrying the SL2AO. * @param[in] sl2ao The SL2AO */ -void _handle_sl2ao(kernel_pid_t iface, const ipv6_hdr_t *ipv6, +void _handle_sl2ao(gnrc_netif2_t *netif, const ipv6_hdr_t *ipv6, const icmpv6_hdr_t *icmpv6, const ndp_opt_t *sl2ao); #if GNRC_IPV6_NIB_CONF_ARSM || defined(DOXYGEN) @@ -111,7 +112,7 @@ void _probe_nbr(_nib_onl_entry_t *nbr, bool reset); * This can either be an TL2AO or for a link-layer without addresses just a * neighbor advertisement. * - * @param[in] iface Interface the link-layer information was advertised + * @param[in] netif Interface the link-layer information was advertised * over. * @param[in] nce Neighbor cache entry that is updated by the advertised * link-layer information. @@ -120,53 +121,62 @@ void _probe_nbr(_nib_onl_entry_t *nbr, bool reset); * @param[in] tl2ao The TL2AO carrying the link-layer information. May be * NULL for link-layers without addresses. */ -void _handle_adv_l2(kernel_pid_t iface, _nib_onl_entry_t *nce, +void _handle_adv_l2(gnrc_netif2_t *netif, _nib_onl_entry_t *nce, const icmpv6_hdr_t *icmpv6, const ndp_opt_t *tl2ao); + +/** + * @brief Recalculates the (randomized) reachable time of on a network + * interface. + * + * @see [RFC 4861, section 6.3.4](https://tools.ietf.org/html/rfc4861#section-6.3.4) + * + * @param[in] netif Interface to set reachable time for. + */ +void _recalc_reach_time(gnrc_netif2_ipv6_t *netif); + /** * @brief Sets a neighbor cache entry reachable and starts the required * event timers * - * @param[in] iface Interface to the NCE + * @param[in] netif Interface to the NCE * @param[in] nce The neighbor cache entry to set reachable */ -void _set_reachable(unsigned iface, _nib_onl_entry_t *nce); +void _set_reachable(gnrc_netif2_t *netif, _nib_onl_entry_t *nce); /** * @brief Initializes interface for address registration state machine * - * @param[in] nib_iface An interface + * @param[in] netif An interface */ -static inline void _init_iface_arsm(_nib_iface_t *nib_iface) +static inline void _init_iface_arsm(gnrc_netif2_t *netif) { - nib_iface->reach_time_base = NDP_REACH_MS; - nib_iface->retrans_time = NDP_RETRANS_TIMER_MS; - _nib_iface_recalc_reach_time(nib_iface); + netif->ipv6.reach_time_base = NDP_REACH_MS; + _recalc_reach_time(&netif->ipv6); } /** * @brief Gets neighbor unreachability state of a neighbor * - * @param[in] entry Neighbor cache entry representing the neighbor. + * @param[in] nbr Neighbor cache entry representing the neighbor. * - * @return Neighbor unreachability state of the @p entry. + * @return Neighbor unreachability state of the @p nbr. */ -static inline uint16_t _get_nud_state(_nib_onl_entry_t *entry) +static inline uint16_t _get_nud_state(_nib_onl_entry_t *nbr) { - return (entry->info & GNRC_IPV6_NIB_NC_INFO_NUD_STATE_MASK); + return (nbr->info & GNRC_IPV6_NIB_NC_INFO_NUD_STATE_MASK); } /** * @brief Sets neighbor unreachablility state of a neighbor * - * @param[in] entry Neighbor cache entry representing the neighbor. + * @param[in] netif The network interface (to signal routing protocol using + * gnrc_netif_t::ipv6::route_info_cb()) + * @param[in] nbr Neighbor cache entry representing the neighbor. * @param[in] state Neighbor unreachability state for the neighbor. */ -static inline void _set_nud_state(_nib_onl_entry_t *entry, uint16_t state) -{ - entry->info &= ~GNRC_IPV6_NIB_NC_INFO_NUD_STATE_MASK; - entry->info |= state; -} +void _set_nud_state(gnrc_netif2_t *netif, _nib_onl_entry_t *nbr, + uint16_t state); #else /* GNRC_IPV6_NIB_CONF_ARSM || defined(DOXYGEN) */ #define _handle_snd_ns(ctx) (void)ctx @@ -175,11 +185,12 @@ static inline void _set_nud_state(_nib_onl_entry_t *entry, uint16_t state) #define _init_iface_arsm(netif) (void)netif #define _handle_adv_l2(netif, nce, icmpv6, tl2ao) (void)netif; (void)nce; \ (void)icmpv6; (void)tl2ao +#define _recalc_reach_time(netif) (void)netif; #define _set_reachable(netif, nce) (void)netif; (void)nce #define _init_iface_arsm(netif) (void)netif -#define _get_nud_state(entry) (GNRC_IPV6_NIB_NC_INFO_NUD_STATE_UNMANAGED) -#define _set_nud_state(entry, state) (void)entry; (void)state +#define _get_nud_state(nbr) (GNRC_IPV6_NIB_NC_INFO_NUD_STATE_UNMANAGED) +#define _set_nud_state(netif, nce, state) (void)netif; (void)nbr; (void)state #endif /* GNRC_IPV6_NIB_CONF_ARSM || defined(DOXYGEN) */ #ifdef __cplusplus diff --git a/sys/net/gnrc/network_layer/ipv6/nib/_nib-internal.c b/sys/net/gnrc/network_layer/ipv6/nib/_nib-internal.c index 854d5e8e5b..4b1be07f50 100644 --- a/sys/net/gnrc/network_layer/ipv6/nib/_nib-internal.c +++ b/sys/net/gnrc/network_layer/ipv6/nib/_nib-internal.c @@ -21,7 +21,7 @@ #include "net/gnrc/ipv6/nib/conf.h" #include "net/gnrc/ipv6/nib/nc.h" #include "net/gnrc/ipv6/nib.h" -#include "net/gnrc/netif.h" +#include "net/gnrc/netif2/internal.h" #include "random.h" #include "_nib-internal.h" @@ -36,7 +36,6 @@ static clist_node_t _next_removable = { NULL }; static _nib_onl_entry_t _nodes[GNRC_IPV6_NIB_NUMOF]; static _nib_offl_entry_t _dsts[GNRC_IPV6_NIB_OFFL_NUMOF]; static _nib_dr_entry_t _def_routers[GNRC_IPV6_NIB_DEFAULT_ROUTER_NUMOF]; -static _nib_iface_t _nis[GNRC_NETIF_NUMOF]; #if GNRC_IPV6_NIB_CONF_MULTIHOP_P6C static _nib_abr_entry_t _abrs[GNRC_IPV6_NIB_ABR_NUMOF]; @@ -61,7 +60,6 @@ void _nib_init(void) memset(_nodes, 0, sizeof(_nodes)); memset(_def_routers, 0, sizeof(_def_routers)); memset(_dsts, 0, sizeof(_dsts)); - memset(_nis, 0, sizeof(_nis)); #if GNRC_IPV6_NIB_CONF_MULTIHOP_P6C memset(_abrs, 0, sizeof(_abrs)); #endif @@ -226,15 +224,21 @@ _nib_onl_entry_t *_nib_onl_get(const ipv6_addr_t *addr, unsigned iface) void _nib_nc_set_reachable(_nib_onl_entry_t *node) { #if GNRC_IPV6_NIB_CONF_ARSM - _nib_iface_t *iface = _nib_iface_get(_nib_onl_get_if(node)); + gnrc_netif2_t *netif = gnrc_netif2_get_by_pid(_nib_onl_get_if(node)); - DEBUG("nib: set %s%%%u reachable (reachable time = %u)\n", - ipv6_addr_to_str(addr_str, &node->ipv6, sizeof(addr_str)), - _nib_onl_get_if(node), iface->reach_time); node->info &= ~GNRC_IPV6_NIB_NC_INFO_NUD_STATE_MASK; node->info |= GNRC_IPV6_NIB_NC_INFO_NUD_STATE_REACHABLE; +#ifdef TEST_SUITES + /* exit early for unittests */ + if (netif == NULL) { + return; + } +#endif + DEBUG("nib: set %s%%%u reachable (reachable time = %u)\n", + ipv6_addr_to_str(addr_str, &node->ipv6, sizeof(addr_str)), + _nib_onl_get_if(node), (unsigned)netif->ipv6.reach_time); _evtimer_add(node, GNRC_IPV6_NIB_REACH_TIMEOUT, &node->nud_timeout, - iface->reach_time); + netif->ipv6.reach_time); #else (void)node; #endif @@ -281,10 +285,9 @@ void _nib_nc_get(const _nib_onl_entry_t *node, gnrc_ipv6_nib_nc_t *nce) #if GNRC_IPV6_NIB_CONF_ARSM #if GNRC_IPV6_NIB_CONF_6LN if (ipv6_addr_is_link_local(&nce->ipv6)) { - gnrc_ipv6_netif_t *netif = gnrc_ipv6_netif_get(_nib_onl_get_if(node)); + gnrc_netif2_t *netif = gnrc_netif2_get_by_pid(_nib_onl_get_if(node)); assert(netif != NULL); - if ((netif->flags & GNRC_IPV6_NETIF_FLAGS_SIXLOWPAN) && - !(netif->flags & GNRC_IPV6_NETIF_FLAGS_ROUTER)) { + if (gnrc_netif2_is_6ln(netif) && !gnrc_netif2_is_rtr(netif)) { _get_l2addr_from_ipv6(nce->l2addr, &node->ipv6); nce->l2addr_len = sizeof(uint64_t); return; @@ -768,42 +771,6 @@ _nib_offl_entry_t *_nib_pl_add(unsigned iface, return dst; } -_nib_iface_t *_nib_iface_get(unsigned iface) -{ - _nib_iface_t *ni = NULL; - - assert(iface <= _NIB_IF_MAX); - for (unsigned i = 0; i < GNRC_NETIF_NUMOF; i++) { - _nib_iface_t *tmp = &_nis[i]; - if (((unsigned)tmp->pid) == iface) { - return tmp; - } - if ((ni == NULL) && (tmp->pid == KERNEL_PID_UNDEF)) { - ni = tmp; - } - } - if (ni != NULL) { - memset(ni, 0, sizeof(_nib_iface_t)); - /* TODO: set random reachable time using constants from #6220 */ - ni->pid = (kernel_pid_t)iface; - } - return ni; -} - -#if GNRC_IPV6_NIB_CONF_ARSM -void _nib_iface_recalc_reach_time(_nib_iface_t *iface) -{ - uint32_t factor = random_uint32_range(NDP_MIN_RANDOM_FACTOR, - NDP_MAX_RANDOM_FACTOR); - - /* random factor was times 1000 so we need to divide it again */ - iface->reach_time = (iface->reach_time_base * factor) / 1000; - _evtimer_add(iface, GNRC_IPV6_NIB_RECALC_REACH_TIME, - &iface->recalc_reach_time, - GNRC_IPV6_NIB_CONF_REACH_TIME_RESET); -} -#endif - static void _override_node(const ipv6_addr_t *addr, unsigned iface, _nib_onl_entry_t *node) { diff --git a/sys/net/gnrc/network_layer/ipv6/nib/_nib-internal.h b/sys/net/gnrc/network_layer/ipv6/nib/_nib-internal.h index 24e39f4234..97af9ec93e 100644 --- a/sys/net/gnrc/network_layer/ipv6/nib/_nib-internal.h +++ b/sys/net/gnrc/network_layer/ipv6/nib/_nib-internal.h @@ -193,56 +193,6 @@ typedef struct { preferred (UINT32_MAX means forever) */ } _nib_offl_entry_t; -/** - * @brief Interface specific information for Neighbor Discovery - */ -typedef struct { -#if GNRC_IPV6_NIB_CONF_ARSM - /** - * @brief base for random reachable time calculation - */ - uint32_t reach_time_base; - uint32_t reach_time; /**< reachable time (in ms) */ -#endif - uint32_t retrans_time; /**< retransmission time (in ms) */ -#if GNRC_IPV6_NIB_CONF_ROUTER || defined(DOXYGEN) - /** - * @brief timestamp in milliseconds of last unsolicited router - * advertisement - * - * @note Only available if @ref GNRC_IPV6_NIB_CONF_ROUTER. - */ - uint32_t last_ra; -#endif -#if GNRC_IPV6_NIB_CONF_ARSM || defined(DOXYGEN) - /** - * @brief Event for @ref GNRC_IPV6_NIB_RECALC_REACH_TIME - */ - evtimer_msg_event_t recalc_reach_time; -#endif - kernel_pid_t pid; /**< identifier of the interface */ -#if GNRC_IPV6_NIB_CONF_ROUTER || defined(DOXYGEN) - /** - * @brief number of unsolicited router advertisements sent - * - * This only counts up to the first @ref NDP_MAX_INIT_RA_NUMOF on interface - * initialization. The last @ref NDP_MAX_FIN_RA_NUMOF of an advertising - * interface are counted from UINT8_MAX - @ref NDP_MAX_FIN_RA_NUMOF + 1. - * - * @note Only available if @ref GNRC_IPV6_NIB_CONF_ROUTER. - */ - uint8_t ra_sent; -#endif - /** - * @brief number of unsolicited router solicitations scheduled - */ - uint8_t rs_sent; - /** - * @brief number of unsolicited neighbor advertisements scheduled - */ - uint8_t na_sent; -} _nib_iface_t; - /** * @brief Internal NIB-representation of the authoritative border router * for multihop prefix and 6LoWPAN context dissemination @@ -795,30 +745,6 @@ void _nib_ft_get(const _nib_offl_entry_t *dst, gnrc_ipv6_nib_ft_t *fte); int _nib_get_route(const ipv6_addr_t *dst, gnrc_pktsnip_t *ctx, gnrc_ipv6_nib_ft_t *entry); -/** - * @brief Gets (or creates if it not exists) interface information for - * neighbor discovery - * - * @pre `(iface <= _NIB_IF_MAX)` - * - * @param[in] iface Interface identifier to get information for. - * - * @return Interface information on @p iface. - * @return NULL, if no space left for interface. - */ -_nib_iface_t *_nib_iface_get(unsigned iface); - -/** - * @brief Recalculates randomized reachable time of an interface. - * - * @param[in] iface An interface. - */ -#if GNRC_IPV6_NIB_CONF_ARSM -void _nib_iface_recalc_reach_time(_nib_iface_t *iface); -#else -#define _nib_iface_recalc_reach_time(iface) (void)iface -#endif - /** * @brief Looks up if an event is queued in the event timer * diff --git a/sys/net/gnrc/network_layer/ipv6/nib/nib.c b/sys/net/gnrc/network_layer/ipv6/nib/nib.c index e36a1f5536..e1a6533524 100644 --- a/sys/net/gnrc/network_layer/ipv6/nib/nib.c +++ b/sys/net/gnrc/network_layer/ipv6/nib/nib.c @@ -16,9 +16,10 @@ #include <errno.h> #include <stdbool.h> +#include "log.h" #include "net/ipv6/addr.h" #include "net/gnrc/nettype.h" -#include "net/gnrc/ipv6/netif.h" +#include "net/gnrc/netif2/internal.h" #include "net/gnrc/ipv6/nib.h" #include "net/gnrc/ndp2.h" #include "net/gnrc/pktqueue.h" @@ -49,24 +50,16 @@ static gnrc_pktqueue_t _queue_pool[GNRC_IPV6_NIB_NUMOF]; * @internal * @{ */ -static void _handle_nbr_sol(kernel_pid_t iface, const ipv6_hdr_t *ipv6, +static void _handle_nbr_sol(gnrc_netif2_t *netif, const ipv6_hdr_t *ipv6, const ndp_nbr_sol_t *nbr_sol, size_t icmpv6_len); -static void _handle_nbr_adv(kernel_pid_t iface, const ipv6_hdr_t *ipv6, +static void _handle_nbr_adv(gnrc_netif2_t *netif, const ipv6_hdr_t *ipv6, const ndp_nbr_adv_t *nbr_adv, size_t icmpv6_len); -static bool _resolve_addr(const ipv6_addr_t *dst, kernel_pid_t iface, +static bool _resolve_addr(const ipv6_addr_t *dst, gnrc_netif2_t *netif, gnrc_pktsnip_t *pkt, gnrc_ipv6_nib_nc_t *nce, _nib_onl_entry_t *entry); static void _handle_snd_na(gnrc_pktsnip_t *pkt); - -/* interface flag checks */ -#if GNRC_IPV6_NIB_CONF_ROUTER -static inline bool _is_rtr(const gnrc_ipv6_netif_t *netif) -{ - return (netif->flags & GNRC_IPV6_NETIF_FLAGS_ROUTER); -} -#endif /** @} */ void gnrc_ipv6_nib_init(void) @@ -83,27 +76,13 @@ void gnrc_ipv6_nib_init(void) mutex_unlock(&_nib_mutex); } -void gnrc_ipv6_nib_init_iface(kernel_pid_t iface) +void gnrc_ipv6_nib_init_iface(gnrc_netif2_t *netif) { - _nib_iface_t *nib_iface; + ipv6_addr_t addr = IPV6_ADDR_UNSPECIFIED; - assert(iface > KERNEL_PID_UNDEF); - DEBUG("nib: Initialize interface %u\n", (unsigned)iface); - mutex_lock(&_nib_mutex); - nib_iface = _nib_iface_get(iface); -#ifdef TEST_SUITES - if (nib_iface == NULL) { - /* in the unittests old NC and NIB are mixed, so this function leads to - * crashes. To prevent this we early exit here, if the interface was - * not found - * TODO: remove when gnrc_ipv6_nc is removed. - */ - mutex_unlock(&_nib_mutex); - return; - } -#else - assert(nib_iface != NULL); -#endif + assert(netif != NULL); + DEBUG("nib: Initialize interface %u\n", netif->pid); + gnrc_netif2_acquire(netif); /* TODO: * - set link-local address here for stateless address auto-configuration * and 6LN @@ -112,46 +91,116 @@ void gnrc_ipv6_nib_init_iface(kernel_pid_t iface) * - join all router group of link-local address here on router node here * - become an router advertising interface here on non-6LR here */ - _init_iface_arsm(nib_iface); - nib_iface->rs_sent = 0; - nib_iface->na_sent = 0; + _init_iface_arsm(netif); + netif->ipv6.retrans_time = NDP_RETRANS_TIMER_MS; + netif->ipv6.na_sent = 0; #if GNRC_IPV6_NIB_CONF_ROUTER - nib_iface->last_ra = UINT32_MAX; - nib_iface->ra_sent = 0; + netif->ipv6.rtr_ltime = 1800U; + netif->ipv6.last_ra = UINT32_MAX; + netif->ipv6.ra_sent = 0; + netif->flags |= GNRC_NETIF2_FLAGS_IPV6_FORWARDING; +#if !GNRC_IPV6_NIB_CONF_6LR || GNRC_IPV6_NIB_CONF_6LBR + netif->flags |= GNRC_NETIF2_FLAGS_IPV6_RTR_ADV; #endif - mutex_unlock(&_nib_mutex); +#if GNRC_IPV6_NIB_CONF_6LBR + netif->flags |= GNRC_NETIF2_FLAGS_6LO_ABR; +#endif + memcpy(&addr, &ipv6_addr_all_routers_link_local, sizeof(addr)); + if (gnrc_netif2_ipv6_group_join(netif, &addr) < 0) { + LOG_ERROR("nib: Can't join link-local all-routers on interface %u\n", + netif->pid); + return; + } +#endif +#if GNRC_IPV6_NIB_CONF_6LN + netif->ipv6.rs_sent = 0; +#endif + memcpy(&addr, &ipv6_addr_all_nodes_link_local, sizeof(addr)); + if (gnrc_netif2_ipv6_group_join(netif, &addr) < 0) { + LOG_ERROR("nib: Can't join link-local all-nodes on interface %u\n", + netif->pid); + return; + } +#if GNRC_IPV6_NIB_CONF_6LN || GNRC_IPV6_NIB_CONF_SLAAC +#if GNRC_IPV6_NIB_CONF_6LN + if (netif->device_type == NETDEV_TYPE_IEEE802154) { + /* see https://tools.ietf.org/html/rfc6775#section-5.2 */ + uint16_t src_len = IEEE802154_LONG_ADDRESS_LEN; + gnrc_netapi_opt_t opt = { .opt = NETOPT_SRC_LEN, + .data = &src_len, + .data_len = sizeof(src_len) }; + + /* XXX we are supposed to be in interface context here, so use driver + * directly everything else would deadlock anyway */ + netif->ops->set(netif, &opt); + } +#endif + uint8_t flags = GNRC_NETIF2_IPV6_ADDRS_FLAGS_STATE_VALID; + /* TODO: set TENTATIVE as soon as there is a SLAAC implementation if not + * 6LN ;-) */ + + gnrc_netif2_ipv6_get_iid(netif, (eui64_t *)&addr.u64[1]); + ipv6_addr_set_link_local_prefix(&addr); + if (gnrc_netif2_ipv6_addr_add(netif, &addr, 64U, flags) < 0) { + LOG_ERROR("nib: Can't add link-local address on interface %u\n", + netif->pid); + return; + } +#if GNRC_IPV6_NIB_CONF_ARSM + /* TODO: SHOULD delay join between 0 and MAX_RTR_SOLICITATION_DELAY */ + ipv6_addr_set_solicited_nodes(&addr, &addr); + if (gnrc_netif2_ipv6_group_join(netif, &addr) < 0) { + LOG_ERROR("nib: Can't join solicited-nodes of link-local address on " + "interface %u\n", netif->pid); + return; + } +#endif +#if GNRC_IPV6_NIB_CONF_SLAAC + /* TODO send NS to solicited nodes and wait netif->ipv6.retrans_time to + * confirm uniqueness of the link-local address */ +#endif +#endif + gnrc_netif2_release(netif); } int gnrc_ipv6_nib_get_next_hop_l2addr(const ipv6_addr_t *dst, - kernel_pid_t iface, gnrc_pktsnip_t *pkt, + gnrc_netif2_t *netif, gnrc_pktsnip_t *pkt, gnrc_ipv6_nib_nc_t *nce) { int res = 0; + DEBUG("nib: get next hop link-layer address of %s%%%u\n", + ipv6_addr_to_str(addr_str, dst, sizeof(addr_str)), + (netif != NULL) ? (unsigned)netif->pid : 0U); + gnrc_netif2_acquire(netif); mutex_lock(&_nib_mutex); do { /* XXX: hidden goto ;-) */ if (ipv6_addr_is_link_local(dst)) { /* TODO: Prefix-based on-link determination */ - if ((iface == KERNEL_PID_UNDEF) || - !_resolve_addr(dst, iface, pkt, nce, - _nib_onl_get(dst, iface))) { + if ((netif == NULL) || + !_resolve_addr(dst, netif, pkt, nce, + _nib_onl_get(dst, netif->pid))) { res = -EHOSTUNREACH; break; } } else { - /* TODO: Off-link next hop determination */ + /* TODO: Off-link next hop determination; + * might need netif locking */ res = -EHOSTUNREACH; } } while (0); mutex_unlock(&_nib_mutex); + gnrc_netif2_release(netif); return res; } -void gnrc_ipv6_nib_handle_pkt(kernel_pid_t iface, const ipv6_hdr_t *ipv6, +void gnrc_ipv6_nib_handle_pkt(gnrc_netif2_t *netif, const ipv6_hdr_t *ipv6, const icmpv6_hdr_t *icmpv6, size_t icmpv6_len) { DEBUG("nib: Handle packet (icmpv6->type = %u)\n", icmpv6->type); + assert(netif != NULL); + gnrc_netif2_acquire(netif); mutex_lock(&_nib_mutex); switch (icmpv6->type) { #if GNRC_IPV6_NIB_CONF_ROUTER @@ -163,10 +212,10 @@ void gnrc_ipv6_nib_handle_pkt(kernel_pid_t iface, const ipv6_hdr_t *ipv6, /* TODO */ break; case ICMPV6_NBR_SOL: - _handle_nbr_sol(iface, ipv6, (ndp_nbr_sol_t *)icmpv6, icmpv6_len); + _handle_nbr_sol(netif, ipv6, (ndp_nbr_sol_t *)icmpv6, icmpv6_len); break; case ICMPV6_NBR_ADV: - _handle_nbr_adv(iface, ipv6, (ndp_nbr_adv_t *)icmpv6, icmpv6_len); + _handle_nbr_adv(netif, ipv6, (ndp_nbr_adv_t *)icmpv6, icmpv6_len); break; #if GNRC_IPV6_NIB_CONF_REDIRECT case ICMPV6_REDIRECT: @@ -183,6 +232,7 @@ void gnrc_ipv6_nib_handle_pkt(kernel_pid_t iface, const ipv6_hdr_t *ipv6, #endif /* GNRC_IPV6_NIB_CONF_MULTIHOP_DAD */ } mutex_unlock(&_nib_mutex); + gnrc_netif2_release(netif); } void gnrc_ipv6_nib_handle_timer_event(void *ctx, uint16_t type) @@ -191,6 +241,7 @@ void gnrc_ipv6_nib_handle_timer_event(void *ctx, uint16_t type) ctx, type, (unsigned)xtimer_now_usec() / 1000); mutex_lock(&_nib_mutex); switch (type) { + /* TODO: remember netif locking if ctx is a gnrc_netif2_t */ #if GNRC_IPV6_NIB_CONF_ARSM case GNRC_IPV6_NIB_SND_UC_NS: case GNRC_IPV6_NIB_SND_MC_NS: @@ -201,7 +252,7 @@ void gnrc_ipv6_nib_handle_timer_event(void *ctx, uint16_t type) _handle_state_timeout(ctx); break; case GNRC_IPV6_NIB_RECALC_REACH_TIME: - _nib_iface_recalc_reach_time(ctx); + _recalc_reach_time(ctx); break; #endif /* GNRC_IPV6_NIB_CONF_ARSM */ case GNRC_IPV6_NIB_SND_NA: @@ -246,6 +297,22 @@ void gnrc_ipv6_nib_handle_timer_event(void *ctx, uint16_t type) mutex_unlock(&_nib_mutex); } +#if GNRC_IPV6_NIB_CONF_ROUTER +void gnrc_ipv6_nib_change_rtr_adv_iface(gnrc_netif2_t *netif, bool enable) +{ + if (enable) { + netif->flags |= GNRC_NETIF2_FLAGS_IPV6_RTR_ADV; + /* TODO: start router advertisements */ + } + else { + netif->flags &= ~GNRC_NETIF2_FLAGS_IPV6_RTR_ADV; + /* TODO: + * - start final router advertisements, + * - start router solicitations? */ + } +} +#endif + /* Iterator for NDP options in a packet */ #define FOREACH_OPT(ndp_pkt, opt, icmpv6_len) \ for (opt = (ndp_opt_t *)(ndp_pkt + 1); \ @@ -253,40 +320,19 @@ void gnrc_ipv6_nib_handle_timer_event(void *ctx, uint16_t type) icmpv6_len -= (opt->len << 3), \ opt = (ndp_opt_t *)(((uint8_t *)opt) + (opt->len << 3))) -static size_t _get_l2src(kernel_pid_t iface, uint8_t *l2src, - size_t l2src_maxlen) +static inline size_t _get_l2src(const gnrc_netif2_t *netif, uint8_t *l2src) { - bool try_long = false; - int res; - uint16_t l2src_len; - /* maximum address length that fits into a minimum length (8) S/TL2A - * option */ - const uint16_t max_short_len = 6; - - /* try getting source address */ - if ((gnrc_netapi_get(iface, NETOPT_SRC_LEN, 0, &l2src_len, - sizeof(l2src_len)) >= 0) && - (l2src_len > max_short_len)) { - try_long = true; - } - - if (try_long && ((res = gnrc_netapi_get(iface, NETOPT_ADDRESS_LONG, 0, - l2src, l2src_maxlen)) > max_short_len)) { - l2src_len = (uint16_t)res; - } - else if ((res = gnrc_netapi_get(iface, NETOPT_ADDRESS, 0, l2src, - l2src_maxlen)) >= 0) { - l2src_len = (uint16_t)res; - } - else { - DEBUG("nib: No link-layer address found.\n"); - l2src_len = 0; - } - - return l2src_len; +#if GNRC_NETIF2_L2ADDR_MAXLEN > 0 + memcpy(l2src, netif->l2addr, netif->l2addr_len); + return netif->l2addr_len; +#else + (void)netif; + (void)l2src; + return 0; +#endif } -static void _send_delayed_nbr_adv(const gnrc_ipv6_netif_t *netif, +static void _send_delayed_nbr_adv(const gnrc_netif2_t *netif, const ipv6_addr_t *tgt, const ipv6_addr_t *dst, gnrc_pktsnip_t *reply_aro) @@ -296,13 +342,15 @@ static void _send_delayed_nbr_adv(const gnrc_ipv6_netif_t *netif, uint8_t reply_flags = NDP_NBR_ADV_FLAGS_S; #if GNRC_IPV6_NIB_CONF_ROUTER - if (_is_rtr(netif)) { + if (gnrc_netif2_is_rtr(netif)) { reply_flags |= NDP_NBR_ADV_FLAGS_R; } #endif +#if GNRC_NETIF2_L2ADDR_MAXLEN > 0 if (ipv6_addr_is_multicast(dst)) { - uint8_t l2addr[GNRC_IPV6_NIB_L2ADDR_MAX_LEN]; - size_t l2addr_len = _get_l2src(netif->pid, l2addr, sizeof(l2addr)); + uint8_t l2addr[GNRC_NETIF2_L2ADDR_MAXLEN]; + size_t l2addr_len = _get_l2src(netif, l2addr); + if (l2addr_len > 0) { extra_opts = gnrc_ndp2_opt_tl2a_build(l2addr, l2addr_len, extra_opts); @@ -319,6 +367,10 @@ static void _send_delayed_nbr_adv(const gnrc_ipv6_netif_t *netif, else { reply_flags |= NDP_NBR_ADV_FLAGS_O; } +#else /* GNRC_NETIF2_L2ADDR_MAXLEN > 0 */ + reply_flags |= NDP_NBR_ADV_FLAGS_O; +#endif + /* discard const qualifier */ nbr_adv = gnrc_ndp2_nbr_adv_build(tgt, reply_flags, extra_opts); if (nbr_adv == NULL) { DEBUG("nib: No space left in packet buffer. Not replying NS"); @@ -336,12 +388,12 @@ static void _send_delayed_nbr_adv(const gnrc_ipv6_netif_t *netif, } } -static void _handle_nbr_sol(kernel_pid_t iface, const ipv6_hdr_t *ipv6, +static void _handle_nbr_sol(gnrc_netif2_t *netif, const ipv6_hdr_t *ipv6, const ndp_nbr_sol_t *nbr_sol, size_t icmpv6_len) { size_t tmp_len = icmpv6_len - sizeof(ndp_nbr_sol_t); + int tgt_idx; ndp_opt_t *opt; - ipv6_addr_t *local; /* check validity, see: https://tools.ietf.org/html/rfc4861#section-7.1.1 */ /* checksum is checked by GNRC's ICMPv6 module */ @@ -365,9 +417,9 @@ static void _handle_nbr_sol(kernel_pid_t iface, const ipv6_hdr_t *ipv6, return; } /* check if target is assigned only now in case the length was wrong */ - local = gnrc_ipv6_netif_find_addr(iface, &nbr_sol->tgt); - if (local == NULL) { - DEBUG("nib: Target address %s is not assigned to a local interface\n", + tgt_idx = gnrc_netif2_ipv6_addr_idx(netif, &nbr_sol->tgt); + if (tgt_idx < 0) { + DEBUG("nib: Target address %s is not assigned to the local interface\n", ipv6_addr_to_str(addr_str, &nbr_sol->tgt, sizeof(addr_str))); return; } @@ -395,6 +447,7 @@ static void _handle_nbr_sol(kernel_pid_t iface, const ipv6_hdr_t *ipv6, /* TODO SLAAC behavior */ #endif /* GNRC_IPV6_NIB_CONF_SLAAC */ if (!ipv6_addr_is_unspecified(&ipv6->src)) { + gnrc_pktsnip_t *reply_aro = NULL; #if GNRC_IPV6_NIB_CONF_6LR ndp_opt_t *sl2ao = NULL; sixlowpan_nd_opt_ar_t *aro = NULL; @@ -402,23 +455,24 @@ static void _handle_nbr_sol(kernel_pid_t iface, const ipv6_hdr_t *ipv6, #define sl2ao (NULL) #define aro (NULL) #endif /* GNRC_IPV6_NIB_CONF_6LR */ - gnrc_ipv6_netif_t *netif; - gnrc_pktsnip_t *reply_aro = NULL; tmp_len = icmpv6_len - sizeof(ndp_nbr_sol_t); - netif = gnrc_ipv6_netif_get(iface); - /* TODO: Set STALE NCE if link-layer has no addresses */ + if (!(netif->flags & GNRC_NETIF2_FLAGS_HAS_L2ADDR)) { + /* Set STALE NCE if link-layer has no addresses */ + _nib_nc_add(&ipv6->src, netif->pid, + GNRC_IPV6_NIB_NC_INFO_NUD_STATE_STALE); + } FOREACH_OPT(nbr_sol, opt, tmp_len) { switch (opt->type) { case NDP_OPT_SL2A: #if GNRC_IPV6_NIB_CONF_6LR - if (_is_6lr(netif)) { + if (gnrc_netif2_is_6lr(netif)) { DEBUG("nib: Storing SL2AO for later handling\n"); sl2ao = opt; break; } #endif /* GNRC_IPV6_NIB_CONF_6LR */ - _handle_sl2ao(iface, ipv6, (const icmpv6_hdr_t *)nbr_sol, + _handle_sl2ao(netif, ipv6, (const icmpv6_hdr_t *)nbr_sol, opt); break; #if GNRC_IPV6_NIB_CONF_6LR @@ -432,9 +486,9 @@ static void _handle_nbr_sol(kernel_pid_t iface, const ipv6_hdr_t *ipv6, opt->type); } } - reply_aro = _copy_and_handle_aro(iface, ipv6, nbr_sol, aro, sl2ao); + reply_aro = _copy_and_handle_aro(netif, ipv6, nbr_sol, aro, sl2ao); /* check if target address is anycast */ - if (gnrc_ipv6_netif_addr_is_non_unicast(local)) { + if (netif->ipv6.addrs_flags[tgt_idx] & GNRC_NETIF2_IPV6_ADDRS_FLAGS_ANYCAST) { _send_delayed_nbr_adv(netif, &nbr_sol->tgt, &ipv6->dst, reply_aro); } else { @@ -445,7 +499,7 @@ static void _handle_nbr_sol(kernel_pid_t iface, const ipv6_hdr_t *ipv6, } } -static void _handle_nbr_adv(kernel_pid_t iface, const ipv6_hdr_t *ipv6, +static void _handle_nbr_adv(gnrc_netif2_t *netif, const ipv6_hdr_t *ipv6, const ndp_nbr_adv_t *nbr_adv, size_t icmpv6_len) { size_t tmp_len = icmpv6_len - sizeof(ndp_nbr_adv_t); @@ -501,7 +555,7 @@ static void _handle_nbr_adv(kernel_pid_t iface, const ipv6_hdr_t *ipv6, #if GNRC_IPV6_NIB_CONF_SLAAC /* TODO SLAAC behavior */ #endif - if (((nce = _nib_onl_get(&nbr_adv->tgt, iface)) != NULL) && + if (((nce = _nib_onl_get(&nbr_adv->tgt, netif->pid)) != NULL) && (nce->mode & _NC)) { #if GNRC_IPV6_NIB_CONF_ARSM bool tl2ao_avail = false; @@ -512,13 +566,13 @@ static void _handle_nbr_adv(kernel_pid_t iface, const ipv6_hdr_t *ipv6, switch (opt->type) { #if GNRC_IPV6_NIB_CONF_ARSM case NDP_OPT_TL2A: - _handle_adv_l2(iface, nce, (icmpv6_hdr_t *)nbr_adv, opt); + _handle_adv_l2(netif, nce, (icmpv6_hdr_t *)nbr_adv, opt); tl2ao_avail = true; break; #endif #if GNRC_IPV6_NIB_CONF_6LN case NDP_OPT_AR: - _handle_aro(iface, ipv6, (const icmpv6_hdr_t *)nbr_adv, + _handle_aro(netif, ipv6, (const icmpv6_hdr_t *)nbr_adv, (const sixlowpan_nd_opt_ar_t *)opt, opt, nce); break; #endif @@ -531,11 +585,11 @@ static void _handle_nbr_adv(kernel_pid_t iface, const ipv6_hdr_t *ipv6, if (!tl2ao_avail && (nbr_adv->flags & NDP_NBR_ADV_FLAGS_S) && (_get_nud_state(nce) != GNRC_IPV6_NIB_NC_INFO_NUD_STATE_INCOMPLETE)) { /* reachability confirmed without TL2AO */ - _set_reachable(iface, nce); + _set_reachable(netif, nce); + } + if (!(netif->flags & GNRC_NETIF2_FLAGS_HAS_L2ADDR)) { + _handle_adv_l2(netif, nce, (icmpv6_hdr_t *)nbr_adv, NULL); } - /* TODO: handling for of advertised link-layer with link-layers without - * addresses */ - /* _handle_adv_l2(iface, nce, (icmpv6_hdr_t *)nbr_adv, NULL); */ #endif } } @@ -567,7 +621,7 @@ static gnrc_pktqueue_t *_alloc_queue_entry(gnrc_pktsnip_t *pkt) } #endif -static bool _resolve_addr(const ipv6_addr_t *dst, kernel_pid_t iface, +static bool _resolve_addr(const ipv6_addr_t *dst, gnrc_netif2_t *netif, gnrc_pktsnip_t *pkt, gnrc_ipv6_nib_nc_t *nce, _nib_onl_entry_t *entry) { @@ -575,29 +629,44 @@ static bool _resolve_addr(const ipv6_addr_t *dst, kernel_pid_t iface, #if GNRC_IPV6_NIB_CONF_ARSM if ((entry != NULL) && (entry->mode & _NC) && _is_reachable(entry)) { if (_get_nud_state(entry) == GNRC_IPV6_NIB_NC_INFO_NUD_STATE_STALE) { - _set_nud_state(entry, GNRC_IPV6_NIB_NC_INFO_NUD_STATE_DELAY); + _set_nud_state(netif, entry, GNRC_IPV6_NIB_NC_INFO_NUD_STATE_DELAY); _evtimer_add(entry, GNRC_IPV6_NIB_DELAY_TIMEOUT, &entry->nud_timeout, NDP_DELAY_FIRST_PROBE_MS); } + DEBUG("nib: resolve address %s%%%u from neighbor cache\n", + ipv6_addr_to_str(addr_str, &entry->ipv6, sizeof(addr_str)), + _nib_onl_get_if(entry)); _nib_nc_get(entry, nce); res = true; } #else if (entry != NULL) { + DEBUG("nib: resolve address %s%%%u from neighbor cache\n", + ipv6_addr_to_str(addr_str, &entry->ipv6, sizeof(addr_str)), + _nib_onl_get_if(entry)); _nib_nc_get(entry, nce); res = true; } #endif - else if (!(res = _resolve_addr_from_ipv6(dst, iface, nce))) { + else if (!(res = _resolve_addr_from_ipv6(dst, netif, nce))) { #if GNRC_IPV6_NIB_CONF_ARSM bool reset = false; #endif + + DEBUG("nib: resolve address %s by probing neighbors\n", + ipv6_addr_to_str(addr_str, dst, sizeof(addr_str))); if ((entry == NULL) || !(entry->mode & _NC)) { - entry = _nib_nc_add(dst, iface, + entry = _nib_nc_add(dst, (netif != NULL) ? netif->pid : 0, GNRC_IPV6_NIB_NC_INFO_NUD_STATE_INCOMPLETE); if (entry == NULL) { return false; } +#if GNRC_IPV6_NIB_CONF_ROUTER + if ((netif != NULL) && (netif->ipv6.route_info_cb != NULL)) { + netif->ipv6.route_info_cb(GNRC_IPV6_NIB_ROUTE_INFO_TYPE_NSC, + dst, (void *)GNRC_IPV6_NIB_NC_INFO_NUD_STATE_INCOMPLETE); + } +#endif #if GNRC_IPV6_NIB_CONF_ARSM reset = true; #endif diff --git a/sys/net/gnrc/network_layer/ipv6/nib/nib_nc.c b/sys/net/gnrc/network_layer/ipv6/nib/nib_nc.c index 4cd920a535..09b7245f91 100644 --- a/sys/net/gnrc/network_layer/ipv6/nib/nib_nc.c +++ b/sys/net/gnrc/network_layer/ipv6/nib/nib_nc.c @@ -18,7 +18,7 @@ #include <stdio.h> #include "net/gnrc/ipv6.h" -#include "net/gnrc/netif.h" +#include "net/gnrc/netif2.h" #include "net/gnrc/ipv6/nib/nc.h" @@ -127,15 +127,16 @@ static const char *_ar_str[] = { void gnrc_ipv6_nib_nc_print(gnrc_ipv6_nib_nc_t *entry) { - char addr_str[IPV6_ADDR_MAX_STR_LEN]; + char addr_str[(IPV6_ADDR_MAX_STR_LEN > GNRC_IPV6_NIB_L2ADDR_MAX_LEN) ? + IPV6_ADDR_MAX_STR_LEN : GNRC_IPV6_NIB_L2ADDR_MAX_LEN]; printf("%s ", ipv6_addr_to_str(addr_str, &entry->ipv6, sizeof(addr_str))); if (gnrc_ipv6_nib_nc_get_iface(entry) != KERNEL_PID_UNDEF) { printf("dev #%u ", gnrc_ipv6_nib_nc_get_iface(entry)); } - printf("lladdr %s ", gnrc_netif_addr_to_str(addr_str, sizeof(addr_str), - entry->l2addr, - entry->l2addr_len)); + printf("lladdr %s ", gnrc_netif2_addr_to_str(entry->l2addr, + entry->l2addr_len, + addr_str)); if (gnrc_ipv6_nib_nc_is_router(entry)) { printf("router"); } diff --git a/sys/shell/commands/sc_gnrc_ipv6_nib.c b/sys/shell/commands/sc_gnrc_ipv6_nib.c index 4c7c2f34b7..83f6c5c698 100644 --- a/sys/shell/commands/sc_gnrc_ipv6_nib.c +++ b/sys/shell/commands/sc_gnrc_ipv6_nib.c @@ -106,8 +106,7 @@ static int _nib_neigh(int argc, char **argv) return 1; } if ((argc > 5) && /* TODO also check if interface supports link-layers or not */ - (l2addr_len = gnrc_netif_addr_from_str(l2addr, sizeof(l2addr), - argv[5])) == 0) { + (l2addr_len = gnrc_netif2_addr_from_str(argv[5], l2addr)) == 0) { _usage_nib_neigh(argv); return 1; } @@ -150,7 +149,7 @@ static int _nib_prefix(int argc, char **argv) ipv6_addr_t pfx; unsigned iface = atoi(argv[3]); unsigned pfx_len = ipv6_addr_split_prefix(argv[4]); - unsigned valid_ltime = UINT32_MAX, pref_ltime = UINT32_MAX; + uint32_t valid_ltime = UINT32_MAX, pref_ltime = UINT32_MAX; if (ipv6_addr_from_str(&pfx, argv[4]) == NULL) { _usage_nib_prefix(argv); -- GitLab