diff --git a/examples/nanocoap_server/Makefile b/examples/nanocoap_server/Makefile index bc42fcb766c4cd00eeb62839891a401d99878c13..f4303ec89341ef6f0cbb6a21efb1ee21c893fd42 100644 --- a/examples/nanocoap_server/Makefile +++ b/examples/nanocoap_server/Makefile @@ -9,7 +9,7 @@ RIOTBASE ?= $(CURDIR)/../.. BOARD_INSUFFICIENT_MEMORY := chronos msb-430 msb-430h nucleo32-f031 nucleo32-f042 \ nucleo32-l031 nucleo-f030 nucleo-l053 stm32f0discovery \ - telosb + telosb z1 # Include packages that pull up and auto-init the link layer. # NOTE: 6LoWPAN will be included if IEEE802.15.4 devices are present diff --git a/sys/include/net/gnrc/ipv6/nib.h b/sys/include/net/gnrc/ipv6/nib.h index 43fe775635d6083ffc4e267688b01c8046800454..22f1ff989a6cacb31bd836083d5557ec473a7431 100644 --- a/sys/include/net/gnrc/ipv6/nib.h +++ b/sys/include/net/gnrc/ipv6/nib.h @@ -14,6 +14,7 @@ * @todo Add detailed description * @todo Implement multihop DAD * @todo Implement classic SLAAC + * @todo Implement MLD * @{ * * @file @@ -86,16 +87,6 @@ extern "C" { */ #define GNRC_IPV6_NIB_SEARCH_RTR (0x4fc3U) -/** - * @brief Reconfirm router event. - * - * This message type is for the event the reconfirmation of a router (which - * implies sending a unicast Router Solicitation). The expected message context - * is a pointer to a valid on-link entry representing the router that is to be - * confirmed. - */ -#define GNRC_IPV6_NIB_RECONFIRM_RTR (0x4fc4U) - /** * @brief Reply Router Solicitation event. * @@ -153,17 +144,6 @@ extern "C" { */ #define GNRC_IPV6_NIB_ADDR_REG_TIMEOUT (0x4fc9U) -/** - * @brief 6LoWPAN context timeout event. - * - * This message type is for the event of a 6LoWPAN compression context timeout. - * The expected message context is the compression context's numerical - * identifier. - * - * @note Only handled with @ref GNRC_IPV6_NIB_CONF_6LN != 0 - */ -#define GNRC_IPV6_NIB_6LO_CTX_TIMEOUT (0x4fcaU) - /** * @brief Authoritative border router timeout event. * @@ -201,6 +181,17 @@ extern "C" { * @note Only handled with @ref GNRC_IPV6_NIB_CONF_ARSM != 0 */ #define GNRC_IPV6_NIB_RECALC_REACH_TIME (0x4fceU) + +/** + * @brief Reregister address. + * + * This message type is for the event of reregistering an IPv6 address to the + * upstream router. The expected message context is an IPv6 address assigned to + * one of the nodes interfaces. + * + * @note Only handled with @ref GNRC_IPV6_NIB_CONF_6LN != 0 + */ +#define GNRC_IPV6_NIB_REREG_ADDRESS (0x4fcfU) /** @} */ /** diff --git a/sys/include/net/gnrc/ipv6/nib/conf.h b/sys/include/net/gnrc/ipv6/nib/conf.h index 90992df16583363a3503bc4c9aadf533ee6e06ca..999350eaad28884cf5624a21d70c50a02ed9bbe5 100644 --- a/sys/include/net/gnrc/ipv6/nib/conf.h +++ b/sys/include/net/gnrc/ipv6/nib/conf.h @@ -29,6 +29,9 @@ extern "C" { #ifndef GNRC_IPV6_NIB_CONF_6LBR #define GNRC_IPV6_NIB_CONF_6LBR (1) #endif +#ifndef GNRC_IPV6_NIB_NUMOF +#define GNRC_IPV6_NIB_NUMOF (16) +#endif #endif #ifdef MODULE_GNRC_IPV6_NIB_6LR @@ -174,8 +177,12 @@ extern "C" { * @see [RFC 6775, section 8.1](https://tools.ietf.org/html/rfc6775#section-8.1) */ #ifndef GNRC_IPV6_NIB_CONF_MULTIHOP_P6C +#if GNRC_IPV6_NIB_CONF_6LN +#define GNRC_IPV6_NIB_CONF_MULTIHOP_P6C (1) +#else #define GNRC_IPV6_NIB_CONF_MULTIHOP_P6C (0) #endif +#endif /** * @brief Multihop duplicate address detection diff --git a/sys/include/net/gnrc/netif2/ipv6.h b/sys/include/net/gnrc/netif2/ipv6.h index 4357ddcf5bd88995442de76e0567dd264312ad47..56e5dfe26ecf900b1000141f662a5694c4d5754f 100644 --- a/sys/include/net/gnrc/netif2/ipv6.h +++ b/sys/include/net/gnrc/netif2/ipv6.h @@ -148,6 +148,18 @@ typedef struct { * and @ref net_gnrc_ipv6_nib "NIB" */ evtimer_msg_event_t search_rtr; +#if GNRC_IPV6_NIB_CONF_6LN || DOXYGEN + /** + * @brief Timers for address re-registration + * + * @note Only available with module @ref net_gnrc_ipv6 "gnrc_ipv6" and + * @ref net_gnrc_ipv6_nib "NIB" and if + * @ref GNRC_IPV6_NIB_CONF_6LN != 0 + * @note Might also be usable in the later default SLAAC implementation + * for NS retransmission timers. + */ + evtimer_msg_event_t addrs_timers[GNRC_NETIF2_IPV6_ADDRS_NUMOF]; +#endif #if GNRC_IPV6_NIB_CONF_ROUTER || DOXYGEN /** @@ -210,16 +222,13 @@ typedef struct { */ uint8_t ra_sent; #endif -#if GNRC_IPV6_NIB_CONF_6LN || DOXYGEN /** * @brief number of unsolicited router solicitations scheduled * * @note Only available with module @ref net_gnrc_ipv6 "gnrc_ipv6" and - * @ref net_gnrc_ipv6_nib "NIB" and if - * @ref GNRC_IPV6_NIB_CONF_6LN != 0 + * @ref net_gnrc_ipv6_nib "NIB" */ uint8_t rs_sent; -#endif /** * @brief number of unsolicited neighbor advertisements scheduled * diff --git a/sys/include/net/gnrc/sixlowpan/nd.h b/sys/include/net/gnrc/sixlowpan/nd.h index 61bc05255699c633f54a846b217a77239f4f5667..7a97f326cce15f0c30b141e708368d05d3c9358d 100644 --- a/sys/include/net/gnrc/sixlowpan/nd.h +++ b/sys/include/net/gnrc/sixlowpan/nd.h @@ -26,45 +26,15 @@ #include <stdint.h> #include "kernel_types.h" -#include "net/gnrc/ipv6/nc.h" -#include "net/gnrc/ipv6/netif.h" #include "net/ipv6/addr.h" #include "net/ndp.h" #include "net/sixlowpan/nd.h" #include "timex.h" -#include "net/gnrc/sixlowpan/nd/border_router.h" -#include "net/gnrc/sixlowpan/nd/router.h" - #ifdef __cplusplus extern "C" { #endif -/** - * @brief Message type for next multicast router solicitation. - */ -#define GNRC_SIXLOWPAN_ND_MSG_MC_RTR_SOL (0x0220) - -/** - * @brief Message type for next unicast router solicitation. - */ -#define GNRC_SIXLOWPAN_ND_MSG_UC_RTR_SOL (0x0221) - -/** - * @brief Message type for removing 6LoWPAN contexts. - */ -#define GNRC_SIXLOWPAN_ND_MSG_DELETE_CTX (0x0222) - -/** - * @brief Message type for authoritative border router timeout - */ -#define GNRC_SIXLOWPAN_ND_MSG_ABR_TIMEOUT (0x0223) - -/** - * @brief Message type for address registration timeout - */ -#define GNRC_SIXLOWPAN_ND_MSG_AR_TIMEOUT (0x0224) - #ifndef GNRC_SIXLOWPAN_ND_AR_LTIME /** * @brief Registration lifetime in minutes for the address registration option @@ -79,101 +49,6 @@ extern "C" { #define GNRC_SIXLOWPAN_ND_AR_LTIME (15U) #endif -/** - * @name Border router constants - * @{ - * @see <a href="https://tools.ietf.org/html/rfc6775#section-9"> - * RFC 6775, section 9 - * </a> - */ -#define GNRC_SIXLOWPAN_ND_RTR_MIN_CTX_DELAY (300U) /**< minimum delay between context change and - * stop of C=0 dissimination in seconds */ -/** @} */ -/** - * @name Host constants - * @{ - * @see <a href="https://tools.ietf.org/html/rfc6775#section-9"> - * RFC 6775, section 9 - * </a> - */ -#define GNRC_SIXLOWPAN_ND_RTR_SOL_INT (10U) /**< replacement value (in seconds) for - * @ref GNRC_NDP_MAX_RTR_SOL_INT */ -#define GNRC_SIXLOWPAN_ND_MAX_RTR_SOL_INT (60U) /**< retransmission increment for exponential - * backoff of subsequent RS */ -/** @} */ -/** - * @name Router constants - * @{ - * @see <a href="https://tools.ietf.org/html/rfc6775#section-9"> - * RFC 6775, section 9 - * </a> - */ -#define GNRC_SIXLOWPAN_ND_MIN_RTR_ADV_DELAY (10U) /**< replacement value (in seconds) for - * @ref GNRC_NDP_MIN_RTR_ADV_DELAY */ -/** - * @brief replacement value (in microseconds) for @ref GNRC_NDP_MAX_RTR_ADV_DELAY - */ -#define GNRC_SIXLOWPAN_ND_MAX_RTR_ADV_DELAY (2U * US_PER_SEC) -/** - * @brief Lifetime of a tentative address entry in seconds - */ -#define GNRC_SIXLOWPAN_ND_TENTATIVE_NCE_LIFETIME (20U) -/** - * @brief 6LoWPAN Multihop Hoplimit - */ -#define GNRC_SIXLOWPAN_ND_MULTIHOP_HOPLIMIT (64U) -/** @} */ - -/** - * @brief Initializes 6LoWPAN neighbor discovery for the interface. - * @pre @p iface->flags & GNRC_IPV6_NETIF_FLAGS_SIXLOWPAN - * @param[in] iface An IPv6 interface. - */ -void gnrc_sixlowpan_nd_init(gnrc_ipv6_netif_t *iface); - -/** - * @brief Multicasts a router solicitation over @p iface - * @pre @p iface->flags & GNRC_IPV6_NETIF_FLAGS_SIXLOWPAN - * @param[in] iface An IPv6 interface. - */ -void gnrc_sixlowpan_nd_mc_rtr_sol(gnrc_ipv6_netif_t *iface); - -/** - * @brief Unicasts a router solicitation to the neighbor represented by @p nce - * @pre @p nce->iface is an IPv6 interface and @ref GNRC_IPV6_NETIF_FLAGS_SIXLOWPAN is set - * in its flags. - * @param[in] nce The neighbor to send the router solicitation to. - */ -void gnrc_sixlowpan_nd_uc_rtr_sol(gnrc_ipv6_nc_t *nce); - -/** - * @brief Get link-layer address and interface for next hop to destination - * IPv6 address. - * - * @param[out] l2addr The link-layer for the next hop to @p dst. - * @param[out] l2addr_len Length of @p l2addr. - * @param[in] iface The interface to search the next hop on. - * May be @ref KERNEL_PID_UNDEF if not specified. - * @param[in] dst An IPv6 address to search the next hop for. - * - * @return The PID of the interface, on success. - * @return -EHOSTUNREACH, if @p dst is not reachable. - * @return -ENOBUFS, if @p l2addr_len was smaller than the resulting @p l2addr - * would be long. - */ -kernel_pid_t gnrc_sixlowpan_nd_next_hop_l2addr(uint8_t *l2addr, uint8_t *l2addr_len, - kernel_pid_t iface, ipv6_addr_t *dst); - -/** - * @brief Reschedules the next router advertisement for a neighboring router. - * - * @pre nce != NULL && sec_delay != 0U - * - * @param[in] nce Neighbor cache entry representing the neighboring router. - * @param[in] sec_delay The delay for the next router solicitation in seconds. - */ -void gnrc_sixlowpan_nd_rtr_sol_reschedule(gnrc_ipv6_nc_t *nce, uint32_t sec_delay); - /** * @brief Builds the address registration option. * @@ -188,62 +63,6 @@ void gnrc_sixlowpan_nd_rtr_sol_reschedule(gnrc_ipv6_nc_t *nce, uint32_t sec_dela gnrc_pktsnip_t *gnrc_sixlowpan_nd_opt_ar_build(uint8_t status, uint16_t ltime, eui64_t *eui64, gnrc_pktsnip_t *next); -/** - * @brief Handles address registration option. - * - * @param[in] iface The interface the ARO was received on. - * @param[in] ipv6 The IPv6 header the ARO was received in. - * @param[in] icmpv6_type Message type of the ICMPv6 message that contained. - * this message. - * @param[in] addr The IPv6 address to register. - * @param[in] ar_opt The address registration option. - * @param[in] sl2a The link-layer source address contained in SL2A accompanying this - * option. May be NULL for icmpv6_type == ICMPV6_NBR_ADV. - * @param[in] sl2a_len Length of @p sl2a. May be 0 if sl2a == NULL. - * - * @return Status for the ARO in the replying NA (always 0 if icmpv6_type == ICMPV6_NBR_ADV). - */ -uint8_t gnrc_sixlowpan_nd_opt_ar_handle(kernel_pid_t iface, ipv6_hdr_t *ipv6, - uint8_t icmpv6_type, ipv6_addr_t *addr, - sixlowpan_nd_opt_ar_t *ar_opt, - uint8_t *sl2a, size_t sl2a_len); - -/** - * @brief Handles 6LoWPAN context option. - * - * @param[in] icmpv6_type Message type of the ICMPv6 message that contained. - * this message. - * @param[in] ctx_opt The 6LoWPAN context option. - * - * @return true, when 6LoWPAN context option was correct. - * @return false, when it was incorrect. - */ -bool gnrc_sixlowpan_nd_opt_6ctx_handle(uint8_t icmpv6_type, sixlowpan_nd_opt_6ctx_t *ctx_opt); - -/** - * @brief Handles registration calls after node-wakeup. - * - * @see <a href="https://tools.ietf.org/html/rfc6775#section-5.8.2"> - * RFC 6776, section 5.8.2 - * </a> - */ -void gnrc_sixlowpan_nd_wakeup(void); - -#ifdef MODULE_GNRC_SIXLOWPAN_ND_ROUTER -/** - * @brief Handles authoritative border router option. - * - * @param[in] iface Interface the source link-layer option was received - * on. - * @param[in] rtr_adv The router advertisement containing the ABRO. - * @param[in] icmpv6_size The size of the @p rtr_adv. - * @param[in] abr_opt The ABRO. - * - * @note Erroneous ABROs are always ignored silently. - */ -void gnrc_sixlowpan_nd_opt_abr_handle(kernel_pid_t iface, ndp_rtr_adv_t *rtr_adv, int icmpv6_size, - sixlowpan_nd_opt_abr_t *abr_opt); - /** * @brief Builds the 6LoWPAN context option. * @@ -272,11 +91,6 @@ gnrc_pktsnip_t *gnrc_sixlowpan_nd_opt_6ctx_build(uint8_t prefix_len, uint8_t fla */ gnrc_pktsnip_t *gnrc_sixlowpan_nd_opt_abr_build(uint32_t version, uint16_t ltime, ipv6_addr_t *braddr, gnrc_pktsnip_t *next); -#else -#define gnrc_sixlowpan_nd_opt_abr_handle(iface, rtr_adv, icmpv6_size, abr_opt) -#define gnrc_sixlowpan_nd_opt_6ctx_build(prefix_len, flags, ltime, prefix, next) (NULL) -#define gnrc_sixlowpan_nd_opt_abr_build(version, ltime, braddr, next) (NULL) -#endif #ifdef __cplusplus } diff --git a/sys/include/net/ndp.h b/sys/include/net/ndp.h index df8a25a386f7a0b55a09750c0da3ea529222e704..11830388db9199ff9df375b27352bbb7c97750a3 100644 --- a/sys/include/net/ndp.h +++ b/sys/include/net/ndp.h @@ -123,6 +123,7 @@ extern "C" { /** * @{ * @name Router constants + * @see [RFC 4861, section 6.2.1](https://tools.ietf.org/html/rfc4861#section-6.2.1) * @see [RFC 4861, section 10](https://tools.ietf.org/html/rfc4861#section-10) */ #define NDP_MAX_INIT_RA_INTERVAL (16000U) /**< MAX_INITIAL_RTR_ADVERT_INTERVAL (in ms) */ @@ -130,6 +131,9 @@ extern "C" { #define NDP_MAX_FIN_RA_NUMOF (3U) /**< MAX_FINAL_RTR_ADVERTISEMENT */ #define NDP_MIN_MS_DELAY_BETWEEN_RAS (3000U) /**< MIN_DELAY_BETWEEN_RAS (in ms) */ #define NDP_MAX_RA_DELAY (500U) /**< MAX_RA_DELAY_TIME (in ms) */ +#define NDP_MAX_RA_INTERVAL_MS (600000U) /**< default of MaxRtrAdvInterval (in ms) */ +#define NDP_MIN_RA_INTERVAL_MS (198000U) /**< default of MinRtrAdvInterval (in ms) */ +#define NDP_RTR_LTIME_SEC (1800U) /**< default of AdvDefaultLifetime (in sec) */ /** @} */ /** @@ -149,6 +153,13 @@ extern "C" { */ #define NDP_MAX_MC_SOL_NUMOF (3U) /**< MAX_MULTICAST_SOLICIT */ #define NDP_MAX_UC_SOL_NUMOF (3U) /**< MAX_UNICAST_SOLICIT */ + +/** + * @brief Default for DupAddrDetectTransmits + * @see [RFC 4862, section 5.1](https://tools.ietf.org/html/rfc4862#section-5.1) + * @note May not be greater than 7. + */ +#define NDP_DAD_TRANSMIT_NUMOF (1U) #define NDP_MAX_ANYCAST_MS_DELAY (1000U) /**< MAX_ANYCAST_DELAY_TIME (in ms) */ #define NDP_MAX_NA_NUMOF (3U) /**< MAX_NEIGHBOR_ADVERTISEMENT */ #define NDP_REACH_MS (30000U) /**< REACHABLE_TIME (in ms) */ diff --git a/sys/include/net/sixlowpan/nd.h b/sys/include/net/sixlowpan/nd.h index c7e6eda749662aef78480dc93835bd0f0a20d89b..2c631e42eb46fcf1d3520c4285f0ea20c2d49b6b 100644 --- a/sys/include/net/sixlowpan/nd.h +++ b/sys/include/net/sixlowpan/nd.h @@ -37,6 +37,8 @@ extern "C" { * @name Lengths for fixed length options * @note Options don't use bytes as their length unit, but 8 bytes. */ +#define SIXLOWPAN_ND_OPT_6CTX_LEN_MIN (2U) +#define SIXLOWPAN_ND_OPT_6CTX_LEN_MAX (3U) #define SIXLOWPAN_ND_OPT_AR_LEN (2U) #define SIXLOWPAN_ND_OPT_ABR_LEN (3U) /** @@ -110,6 +112,12 @@ extern "C" { * @see [RFC 6775, section 9](https://tools.ietf.org/html/rfc6775#section-9) * @{ */ +/** + * @brief Number of address registration retries + * + * @note May not be greater than 7. + */ +#define SIXLOWPAN_ND_REG_TRANSMIT_NUMOF (3U) /** * @brief RTR_SOLICITATION_INTERVAL (in msec) */ diff --git a/sys/net/gnrc/application_layer/uhcpc/gnrc_uhcpc.c b/sys/net/gnrc/application_layer/uhcpc/gnrc_uhcpc.c index 05984803a060f4fc75ba25f156699af4cd6e37f5..cdcc01eea0145f50ebb7e497c4a9fd257c59386e 100644 --- a/sys/net/gnrc/application_layer/uhcpc/gnrc_uhcpc.c +++ b/sys/net/gnrc/application_layer/uhcpc/gnrc_uhcpc.c @@ -6,12 +6,10 @@ * directory for more details. */ -#include "net/fib.h" +#include "net/gnrc/ipv6/nib.h" #include "net/gnrc/ipv6.h" -#include "net/gnrc/ipv6/nc.h" -#include "net/gnrc/ipv6/netif.h" #include "net/gnrc/netapi.h" -#include "net/gnrc/netif.h" +#include "net/gnrc/netif2.h" #include "net/ipv6/addr.h" #include "net/netdev.h" #include "net/netopt.h" @@ -31,19 +29,13 @@ static void set_interface_roles(void) kernel_pid_t dev = netif->pid; int is_wired = gnrc_netapi_get(dev, NETOPT_IS_WIRED, 0, NULL, 0); if ((!gnrc_border_interface) && (is_wired == 1)) { - ipv6_addr_t addr; + ipv6_addr_t addr, defroute = IPV6_ADDR_UNSPECIFIED; gnrc_border_interface = dev; ipv6_addr_from_str(&addr, "fe80::2"); gnrc_netapi_set(dev, NETOPT_IPV6_ADDR, 64 << 8, &addr, sizeof(addr)); -#ifdef MODULE_FIB - ipv6_addr_t defroute = IPV6_ADDR_UNSPECIFIED; - ipv6_addr_from_str(&addr, "fe80::1"); - fib_add_entry(&gnrc_ipv6_fib_table, dev, defroute.u8, 16, - 0x00, addr.u8, 16, 0, - (uint32_t)FIB_LIFETIME_NO_EXPIRE); -#endif + gnrc_ipv6_nib_ft_add(&defroute, IPV6_ADDR_BIT_LEN, &addr, dev); } else if ((!gnrc_wireless_interface) && (is_wired != 1)) { gnrc_wireless_interface = dev; @@ -92,6 +84,10 @@ void uhcp_handle_prefix(uint8_t *prefix, uint8_t prefix_len, uint16_t lifetime, gnrc_netapi_set(gnrc_wireless_interface, NETOPT_IPV6_ADDR, (64 << 8), prefix, sizeof(ipv6_addr_t)); +#if defined(MODULE_GNRC_IPV6_NIB) && GNRC_IPV6_NIB_CONF_6LBR && \ + GNRC_IPV6_NIB_CONF_MULTIHOP_P6C + gnrc_ipv6_nib_abr_add((ipv6_addr_t *)prefix); +#endif gnrc_netapi_set(gnrc_wireless_interface, NETOPT_IPV6_ADDR_REMOVE, 0, &_prefix, sizeof(_prefix)); print_str("gnrc_uhcpc: uhcp_handle_prefix(): configured new prefix "); @@ -101,6 +97,10 @@ void uhcp_handle_prefix(uint8_t *prefix, uint8_t prefix_len, uint16_t lifetime, if (!ipv6_addr_is_unspecified(&_prefix)) { gnrc_netapi_set(gnrc_wireless_interface, NETOPT_IPV6_ADDR_REMOVE, 0, &_prefix, sizeof(_prefix)); +#if defined(MODULE_GNRC_IPV6_NIB) && GNRC_IPV6_NIB_CONF_6LBR && \ + GNRC_IPV6_NIB_CONF_MULTIHOP_P6C + gnrc_ipv6_nib_abr_del(&_prefix); +#endif print_str("gnrc_uhcpc: uhcp_handle_prefix(): removed old prefix "); ipv6_addr_print(&_prefix); puts("/64"); diff --git a/sys/net/gnrc/netif2/gnrc_netif2.c b/sys/net/gnrc/netif2/gnrc_netif2.c index 2d643bea4f1fb1d3d3e1630648e8e129cb85821d..804d7aa69356abd9b67f6c55490d5a664eaf30dd 100644 --- a/sys/net/gnrc/netif2/gnrc_netif2.c +++ b/sys/net/gnrc/netif2/gnrc_netif2.c @@ -550,10 +550,30 @@ int gnrc_netif2_ipv6_addr_add(gnrc_netif2_t *netif, const ipv6_addr_t *addr, } netif->ipv6.addrs_flags[idx] = flags; memcpy(&netif->ipv6.addrs[idx], addr, sizeof(netif->ipv6.addrs[idx])); - /* TODO: - * - update prefix list, if flags == VALID - * - with SLAAC, send out NS otherwise for DAD probing */ +#ifdef MODULE_GNRC_IPV6_NIB + if (_get_state(netif, idx) == GNRC_NETIF2_IPV6_ADDRS_FLAGS_STATE_VALID) { + void *state = NULL; + gnrc_ipv6_nib_pl_t ple; + bool in_pl = false; + + while (gnrc_ipv6_nib_pl_iter(netif->pid, &state, &ple)) { + if (ipv6_addr_match_prefix(&ple.pfx, addr) >= pfx_len) { + in_pl = true; + } + } + if (!in_pl) { + gnrc_ipv6_nib_pl_set(netif->pid, addr, pfx_len, + UINT32_MAX, UINT32_MAX); + } + } +#if GNRC_IPV6_NIB_CONF_SLAAC + else { + /* TODO: send out NS to solicited nodes for DAD probing */ + } +#endif +#else (void)pfx_len; +#endif gnrc_netif2_release(netif); return idx; } @@ -569,8 +589,6 @@ void gnrc_netif2_ipv6_addr_remove(gnrc_netif2_t *netif, if (idx >= 0) { netif->ipv6.addrs_flags[idx] = 0; ipv6_addr_set_unspecified(&netif->ipv6.addrs[idx]); - /* TODO: - * - update prefix list, if necessary */ } gnrc_netif2_release(netif); } diff --git a/sys/net/gnrc/network_layer/ipv6/gnrc_ipv6.c b/sys/net/gnrc/network_layer/ipv6/gnrc_ipv6.c index e70da32d3587ee99a0815a98cdfae90fac5a2807..7fd41fb0859fc928c056a948d04ff464da6d5d77 100644 --- a/sys/net/gnrc/network_layer/ipv6/gnrc_ipv6.c +++ b/sys/net/gnrc/network_layer/ipv6/gnrc_ipv6.c @@ -290,17 +290,16 @@ static void *_event_loop(void *args) case GNRC_IPV6_NIB_SND_MC_NS: case GNRC_IPV6_NIB_SND_NA: case GNRC_IPV6_NIB_SEARCH_RTR: - case GNRC_IPV6_NIB_RECONFIRM_RTR: case GNRC_IPV6_NIB_REPLY_RS: case GNRC_IPV6_NIB_SND_MC_RA: case GNRC_IPV6_NIB_REACH_TIMEOUT: case GNRC_IPV6_NIB_DELAY_TIMEOUT: case GNRC_IPV6_NIB_ADDR_REG_TIMEOUT: - case GNRC_IPV6_NIB_6LO_CTX_TIMEOUT: case GNRC_IPV6_NIB_ABR_TIMEOUT: case GNRC_IPV6_NIB_PFX_TIMEOUT: case GNRC_IPV6_NIB_RTR_TIMEOUT: case GNRC_IPV6_NIB_RECALC_REACH_TIME: + case GNRC_IPV6_NIB_REREG_ADDRESS: DEBUG("ipv6: NIB timer event received\n"); gnrc_ipv6_nib_handle_timer_event(msg.content.ptr, msg.type); break; 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 e4beb0e09f023be4ce6b317a798153aab63ac195..982635b9b86ad88ca88c6afe274edd96d7171d37 100644 --- a/sys/net/gnrc/network_layer/ipv6/nib/_nib-6ln.c +++ b/sys/net/gnrc/network_layer/ipv6/nib/_nib-6ln.c @@ -15,6 +15,7 @@ #include "net/gnrc/netif2/internal.h" #include "net/gnrc/ipv6/nib.h" +#include "net/gnrc/ndp2.h" #include "_nib-6ln.h" #include "_nib-6lr.h" @@ -27,11 +28,13 @@ static char addr_str[IPV6_ADDR_MAX_STR_LEN]; #endif +extern void _handle_search_rtr(gnrc_netif2_t *netif); + static inline bool _is_iface_eui64(gnrc_netif2_t *netif, const eui64_t *eui64) { /* TODO: adapt for short addresses */ return (netif->l2addr_len == sizeof(eui64_t)) && - (memcmp(&netif->l2addr, eui64, netif->l2addr_len) == 0); + (memcmp(&netif->l2addr, eui64, netif->l2addr_len) == 0); } static inline uint8_t _reverse_iid(const ipv6_addr_t *dst, @@ -47,7 +50,7 @@ static inline uint8_t _reverse_iid(const ipv6_addr_t *dst, l2addr[4] = dst->u8[14]; l2addr[5] = dst->u8[15]; return ETHERNET_ADDR_LEN; -#endif +#endif /* MODULE_NETDEV_ETH */ #ifdef MODULE_NETDEV_IEEE802154 case NETDEV_TYPE_IEEE802154: /* assume address was based on EUI-64 @@ -55,12 +58,12 @@ static inline uint8_t _reverse_iid(const ipv6_addr_t *dst, memcpy(l2addr, &dst->u64[1], sizeof(dst->u64[1])); l2addr[0] ^= 0x02; return sizeof(dst->u64[1]); -#endif +#endif /* MODULE_NETDEV_IEEE802154 */ #ifdef MODULE_CC110X case NETDEV_TYPE_CC110X: l2addr[0] = dst->u8[15]; return sizeof(uint8_t); -#endif +#endif /* MODULE_CC110X */ default: (void)dst; (void)l2addr; @@ -104,9 +107,6 @@ uint8_t _handle_aro(gnrc_netif2_t *netif, const ipv6_hdr_t *ipv6, const sixlowpan_nd_opt_ar_t *aro, const ndp_opt_t *sl2ao, _nib_onl_entry_t *nce) { -#if !GNRC_IPV6_NIB_CONF_6LR - (void)sl2ao; -#endif assert(netif != NULL); if (gnrc_netif2_is_6ln(netif) && (aro->len == SIXLOWPAN_ND_OPT_AR_LEN)) { DEBUG("nib: valid ARO received\n"); @@ -125,23 +125,27 @@ uint8_t _handle_aro(gnrc_netif2_t *netif, const ipv6_hdr_t *ipv6, switch (aro->status) { case SIXLOWPAN_ND_STATUS_SUCCESS: { uint16_t ltime = byteorder_ntohs(aro->ltime); - uint32_t next_ns; + uint32_t rereg_time; + int idx = gnrc_netif2_ipv6_addr_idx(netif, &ipv6->dst); /* if ltime 1min, reschedule NS in 30sec, otherwise 1min * before timeout */ - next_ns = (ltime == 1U) ? (30 * MS_PER_SEC) : - (byteorder_ntohs(aro->ltime) - 1U) * - SEC_PER_MIN * MS_PER_SEC; - DEBUG("nib: Address registration successful. " - "Scheduling re-registration in %" PRIu32 "ms\n", - next_ns); - assert(nce != NULL); - _evtimer_add(nce, GNRC_IPV6_NIB_SND_UC_NS, &nce->nud_timeout, - next_ns); + rereg_time = (ltime == 1U) ? (30 * MS_PER_SEC) : + (ltime - 1U) * SEC_PER_MIN * MS_PER_SEC; + DEBUG("nib: Address registration of %s successful. " + "Scheduling re-registration in %" PRIu32 "ms\n", + ipv6_addr_to_str(addr_str, &ipv6->dst, + sizeof(addr_str)), rereg_time); + netif->ipv6.addrs_flags[idx] &= ~GNRC_NETIF2_IPV6_ADDRS_FLAGS_STATE_MASK; + netif->ipv6.addrs_flags[idx] |= GNRC_NETIF2_IPV6_ADDRS_FLAGS_STATE_VALID; + _evtimer_add(&netif->ipv6.addrs[idx], + GNRC_IPV6_NIB_REREG_ADDRESS, + &netif->ipv6.addrs_timers[idx], + rereg_time); break; } case SIXLOWPAN_ND_STATUS_DUP: DEBUG("nib: Address registration reports duplicate. " - "Removing address %s%%%u\n", + "Removing address %s%%%u\n", ipv6_addr_to_str(addr_str, &ipv6->dst, sizeof(addr_str)), netif->pid); @@ -150,17 +154,18 @@ uint8_t _handle_aro(gnrc_netif2_t *netif, const ipv6_hdr_t *ipv6, break; case SIXLOWPAN_ND_STATUS_NC_FULL: { DEBUG("nib: Router's neighbor cache is full. " - "Searching new router for DAD\n"); + "Searching new router for DAD\n"); _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 */ netif->ipv6.rs_sent = 0; - /* TODO: search new router */ + /* search (hopefully) new router */ + _handle_search_rtr(netif); } else { assert(dr->next_hop != NULL); - _snd_uc_ns(dr->next_hop, true); + _handle_rereg_address(&ipv6->dst); } } break; @@ -170,17 +175,153 @@ uint8_t _handle_aro(gnrc_netif2_t *netif, const ipv6_hdr_t *ipv6, #if GNRC_IPV6_NIB_CONF_6LR else if (gnrc_netif2_is_6lr(netif) && (icmpv6->type == ICMPV6_NBR_SOL)) { - return _reg_addr_upstream(netif, ipv6, icmpv6, aro, sl2ao); + assert(nce != NULL); + return _reg_addr_upstream(netif, ipv6, icmpv6, aro, sl2ao, nce); } -#endif +#else /* GNRC_IPV6_NIB_CONF_6LR */ + (void)sl2ao; + (void)nce; +#endif /* GNRC_IPV6_NIB_CONF_6LR */ } #if ENABLE_DEBUG else if (aro->len != SIXLOWPAN_ND_OPT_AR_LEN) { DEBUG("nib: ARO of unexpected length %u, ignoring ARO\n", aro->len); } -#endif +#endif /* ENABLE_DEBUG */ return _ADDR_REG_STATUS_IGNORE; } + +static inline bool _is_tentative(const gnrc_netif2_t *netif, int idx) +{ + return (gnrc_netif2_ipv6_addr_get_state(netif, idx) & + GNRC_NETIF2_IPV6_ADDRS_FLAGS_STATE_TENTATIVE); +} + +static inline bool _is_valid(const gnrc_netif2_t *netif, int idx) +{ + return (gnrc_netif2_ipv6_addr_get_state(netif, idx) == + GNRC_NETIF2_IPV6_ADDRS_FLAGS_STATE_VALID); +} + +void _handle_rereg_address(const ipv6_addr_t *addr) +{ + gnrc_netif2_t *netif = gnrc_netif2_get_by_ipv6_addr(addr); + _nib_dr_entry_t *router = _nib_drl_get_dr(); + + if ((netif != NULL) && (router != NULL)) { + assert((unsigned)netif->pid == _nib_onl_get_if(router->next_hop)); + DEBUG("nib: Re-registering %s", + ipv6_addr_to_str(addr_str, addr, sizeof(addr_str))); + DEBUG(" with upstream router %s\n", + ipv6_addr_to_str(addr_str, &router->next_hop->ipv6, + sizeof(addr_str))); + _snd_ns(&router->next_hop->ipv6, netif, addr, &router->next_hop->ipv6); + } + else { + DEBUG("nib: Couldn't re-register %s, no current router found or address " + "wasn't assigned to any interface anymore.\n", + ipv6_addr_to_str(addr_str, addr, sizeof(addr_str))); + } + if (netif != NULL) { + int idx = gnrc_netif2_ipv6_addr_idx(netif, addr); + + if (_is_valid(netif, idx) || (_is_tentative(netif, idx) && + (gnrc_netif2_ipv6_addr_dad_trans(netif, idx) < + SIXLOWPAN_ND_REG_TRANSMIT_NUMOF))) { + uint32_t retrans_time; + + if (_is_valid(netif, idx)) { + retrans_time = SIXLOWPAN_ND_MAX_RS_SEC_INTERVAL; + } + else { + retrans_time = netif->ipv6.retrans_time; + /* increment encoded retransmission count */ + netif->ipv6.addrs_flags[idx]++; + } + _evtimer_add(&netif->ipv6.addrs[idx], GNRC_IPV6_NIB_REREG_ADDRESS, + &netif->ipv6.addrs_timers[idx], retrans_time); + } + else { + netif->ipv6.rs_sent = 0; + _handle_search_rtr(netif); + } + } +} + +#if GNRC_IPV6_NIB_CONF_MULTIHOP_P6C +_nib_abr_entry_t *_handle_abro(const sixlowpan_nd_opt_abr_t *abro) +{ + _nib_abr_entry_t *abr = NULL; + + if (abro->len != SIXLOWPAN_ND_OPT_ABR_LEN) { + /* ignore silently */ + return NULL; + } + abr = _nib_abr_add(&abro->braddr); + if (abr != NULL) { + uint32_t abro_version = sixlowpan_nd_opt_abr_get_version(abro); + uint16_t ltime = byteorder_ntohs(abro->ltime); + + if (abr->version >= abro_version) { + abr->version = abro_version; + abr->valid_until = _now_min() + ltime; + } + /* correct for default value */ + ltime = (ltime == 0) ? SIXLOWPAN_ND_OPT_ABR_LTIME_DEFAULT : ltime; + _evtimer_add(abr, GNRC_IPV6_NIB_ABR_TIMEOUT, &abr->timeout, + /* UINT16_MAX min < UINT32_MAX ms so no risk of overflow */ + MS_PER_SEC * SEC_PER_MIN * ltime); + } + return abr; +} +#endif /* GNRC_IPV6_NIB_CONF_MULTIHOP_P6C */ + +#if GNRC_IPV6_NIB_CONF_MULTIHOP_P6C +uint32_t _handle_6co(const icmpv6_hdr_t *icmpv6, + const sixlowpan_nd_opt_6ctx_t *sixco, + _nib_abr_entry_t *abr) +#else /* GNRC_IPV6_NIB_CONF_MULTIHOP_P6C */ +uint32_t _handle_6co(const icmpv6_hdr_t *icmpv6, + const sixlowpan_nd_opt_6ctx_t *sixco) +#endif /* GNRC_IPV6_NIB_CONF_MULTIHOP_P6C */ +{ + uint16_t ltime; + +#ifdef MODULE_GNRC_SIXLOWPAN_CTX + uint8_t cid; +#endif /* MODULE_GNRC_SIXLOWPAN_CTX */ + + if ((sixco->len != SIXLOWPAN_ND_OPT_6CTX_LEN_MIN) || + ((sixco->len != SIXLOWPAN_ND_OPT_6CTX_LEN_MAX) && + (sixco->ctx_len > 64U)) || + (icmpv6->type != ICMPV6_RTR_ADV)) { + DEBUG("nib: received 6CO of invalid length (%u), must be %u " + "or wasn't delivered by RA." + "\n", + sixco->len, + (sixco->ctx_len > 64U) ? SIXLOWPAN_ND_OPT_6CTX_LEN_MAX : + SIXLOWPAN_ND_OPT_6CTX_LEN_MIN); + return UINT32_MAX; + } + ltime = byteorder_ntohs(sixco->ltime); +#ifdef MODULE_GNRC_SIXLOWPAN_CTX + cid = sixlowpan_nd_opt_6ctx_get_cid(sixco); + gnrc_sixlowpan_ctx_update(cid, (ipv6_addr_t *)(sixco + 1), sixco->ctx_len, + ltime, sixlowpan_nd_opt_6ctx_is_comp(sixco)); +#if GNRC_IPV6_NIB_CONF_MULTIHOP_P6C + assert(abr != NULL); /* should have been set in _handle_abro() */ + if (ltime == 0) { + bf_unset(abr->ctxs, cid); + } + else { + bf_set(abr->ctxs, cid); + } +#endif /* GNRC_IPV6_NIB_CONF_MULTIHOP_P6C */ +#else /* MODULE_GNRC_SIXLOWPAN_CTX */ + (void)abr; +#endif /* MODULE_GNRC_SIXLOWPAN_CTX */ + return ltime * SEC_PER_MIN * MS_PER_SEC; +} #else /* GNRC_IPV6_NIB_CONF_6LN */ typedef int dont_be_pedantic; #endif /* GNRC_IPV6_NIB_CONF_6LN */ 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 1ba822bf58caeb3b039bce39be7c91cec22a0be5..d371aebc9372b2eb2acb9a3003c9034a2a1a980a 100644 --- a/sys/net/gnrc/network_layer/ipv6/nib/_nib-6ln.h +++ b/sys/net/gnrc/network_layer/ipv6/nib/_nib-6ln.h @@ -23,6 +23,8 @@ #include "net/gnrc/ipv6/nib/conf.h" #include "net/sixlowpan/nd.h" +#include "timex.h" +#include "xtimer.h" #include "_nib-arsm.h" #include "_nib-internal.h" @@ -31,6 +33,12 @@ extern "C" { #endif +static inline uint32_t _now_min(void) +{ + return (uint32_t)((xtimer_now_usec64() / (US_PER_SEC * SEC_PER_MIN)) & + UINT32_MAX); +} + #if GNRC_IPV6_NIB_CONF_6LN || defined(DOXYGEN) /** * @brief Additional (local) status to ARO status values for tentative @@ -57,6 +65,37 @@ extern "C" { bool _resolve_addr_from_ipv6(const ipv6_addr_t *dst, gnrc_netif2_t *netif, gnrc_ipv6_nib_nc_t *nce); +/** + * @brief Calculates exponential backoff for RS retransmissions + * + * @see [RFC 6775, section 5.3](https://tools.ietf.org/html/rfc6775#section-5.3) + * + * @param[in] netif The network interface that the RS will be sent over. + * + * @return The interval in ms to the next RS + */ +static inline uint32_t _get_next_rs_interval(const gnrc_netif2_t *netif) +{ + if (gnrc_netif2_is_6ln(netif)) { + if (netif->ipv6.rs_sent < SIXLOWPAN_ND_MAX_RS_NUMOF) { + return SIXLOWPAN_ND_RS_MSEC_INTERVAL; + } + else { + unsigned exp = netif->ipv6.rs_sent - SIXLOWPAN_ND_MAX_RS_NUMOF; + uint32_t tmp = SIXLOWPAN_ND_RS_MSEC_INTERVAL + + ((1 << exp) * (NDP_RS_MS_INTERVAL)); + + if (tmp > (SIXLOWPAN_ND_MAX_RS_SEC_INTERVAL * MS_PER_SEC)) { + tmp = SIXLOWPAN_ND_MAX_RS_SEC_INTERVAL * MS_PER_SEC; + } + return tmp; + } + } + else { + return NDP_RS_MS_INTERVAL; + } +} + /** * @brief Handles ARO * @@ -74,11 +113,36 @@ 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); + +/** + * @brief Handler for @ref GNRC_IPV6_NIB_REREG_ADDRESS event handler + * + * @param[in] addr An IPv6 address. + */ +void _handle_rereg_address(const ipv6_addr_t *addr); + +#if GNRC_IPV6_NIB_CONF_MULTIHOP_P6C || defined(DOXYGEN) +_nib_abr_entry_t *_handle_abro(const sixlowpan_nd_opt_abr_t *abro); +uint32_t _handle_6co(const icmpv6_hdr_t *icmpv6, + const sixlowpan_nd_opt_6ctx_t *sixco, + _nib_abr_entry_t *abr); +#else /* GNRC_IPV6_NIB_CONF_MULTIHOP_P6C || defined(DOXYGEN) */ +uint32_t _handle_6co(const icmpv6_hdr_t *icmpv6, + const sixlowpan_nd_opt_6ctx_t *sixco); +#endif /* GNRC_IPV6_NIB_CONF_MULTIHOP_P6C || defined(DOXYGEN) */ #else /* GNRC_IPV6_NIB_CONF_6LN || defined(DOXYGEN) */ #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 */ +#define _get_next_rs_interval(netif) (NDP_RS_MS_INTERVAL) +#define _handle_rereg_address(netif) (void)netif +#if GNRC_IPV6_NIB_CONF_MULTIHOP_P6C || defined(DOXYGEN) +#define _handle_abro(abro) (NULL) +#define _handle_6co(icmpv6, sixco, abr) (UINT32_MAX) +#else /* GNRC_IPV6_NIB_CONF_MULTIHOP_P6C || defined(DOXYGEN) */ +#define _handle_6co(icmpv6, sixco) (UINT32_MAX) +#endif /* GNRC_IPV6_NIB_CONF_MULTIHOP_P6C || defined(DOXYGEN) */ #endif /* GNRC_IPV6_NIB_CONF_6LN || defined(DOXYGEN) */ 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 9cfaf55f0aa3ab4457d1122150814e1d8dad56e0..4342b0b354e39339baba13afa3f48732cb7b3738 100644 --- a/sys/net/gnrc/network_layer/ipv6/nib/_nib-6lr.c +++ b/sys/net/gnrc/network_layer/ipv6/nib/_nib-6lr.c @@ -51,11 +51,9 @@ static uint8_t _update_nce_ar_state(const sixlowpan_nd_opt_ar_t *aro, 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) + const ndp_opt_t *sl2ao, _nib_onl_entry_t *nce) { if (!ipv6_addr_is_unspecified(&ipv6->src) && (sl2ao != NULL)) { - _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", ipv6_addr_to_str(addr_str, &ipv6->src, sizeof(addr_str)), @@ -66,9 +64,11 @@ uint8_t _reg_addr_upstream(gnrc_netif2_t *netif, const ipv6_hdr_t *ipv6, (memcmp(&nce->eui64, &aro->eui64, sizeof(aro->eui64)) == 0)) { #if GNRC_IPV6_NIB_CONF_MULTIHOP_DAD /* TODO */ -#endif +#endif /* GNRC_IPV6_NIB_CONF_MULTIHOP_DAD */ if (aro->ltime.u16 != 0) { _handle_sl2ao(netif, ipv6, icmpv6, sl2ao); + /* re-get NCE in case it was updated */ + nce = _nib_onl_get(&ipv6->src, netif->pid); return _update_nce_ar_state(aro, nce); } else if (nce != NULL) { @@ -76,7 +76,8 @@ uint8_t _reg_addr_upstream(gnrc_netif2_t *netif, const ipv6_hdr_t *ipv6, return SIXLOWPAN_ND_STATUS_SUCCESS; } } - else { + else if (_get_ar_state(nce) != GNRC_IPV6_NIB_NC_INFO_AR_STATE_GC) { + /* ignore address registration requests from upstream */ DEBUG("nib: Could not register %s, duplicate entry with EUI-64 " "%02x:%02x:%02x:%02x:%02x:%02x:%02x:%02x\n", ipv6_addr_to_str(addr_str, &ipv6->src, sizeof(addr_str)), @@ -116,7 +117,7 @@ gnrc_pktsnip_t *_copy_and_handle_aro(gnrc_netif2_t *netif, DEBUG("nib: Address was marked TENTATIVE => not replying NS, " "waiting for DAC\n"); } -#endif +#endif /* GNRC_IPV6_NIB_CONF_MULTIHOP_DAD */ } return reply_aro; } 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 6248600e69cef16fcdc6b541c81705c73d7fec0b..e7b7661a55317c58567e711c9c816ad9e8974dd0 100644 --- a/sys/net/gnrc/network_layer/ipv6/nib/_nib-6lr.h +++ b/sys/net/gnrc/network_layer/ipv6/nib/_nib-6lr.h @@ -83,6 +83,9 @@ static inline bool _rtr_sol_on_6lr(const gnrc_netif2_t *netif, * handed to the SL2AO handler function). * @param[in] aro ARO that carries the address registration information. * @param[in] sl2ao SL2AO associated with the ARO. + * @param[in] nce The local neighbor cache entry the registration + * information is supposed to be copied into. May be NULL + * (this might create one). * * @return registration status of the address (including * @ref _ADDR_REG_STATUS_TENTATIVE and @ref _ADDR_REG_STATUS_IGNORE). @@ -90,7 +93,7 @@ static inline bool _rtr_sol_on_6lr(const gnrc_netif2_t *netif, 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); + const ndp_opt_t *sl2ao, _nib_onl_entry_t *nce); /** @@ -112,15 +115,23 @@ gnrc_pktsnip_t *_copy_and_handle_aro(gnrc_netif2_t *netif, const ipv6_hdr_t *ipv const ndp_nbr_sol_t *nbr_sol, const sixlowpan_nd_opt_ar_t *aro, const ndp_opt_t *sl2ao); + +/** + * @brief Sets the @ref GNRC_NETIF2_FLAGS_IPV6_RTR_ADV flags of an interface + * + * @param[in] netif The interface. + */ +void _set_rtr_adv(gnrc_netif2_t *netif); #else /* GNRC_IPV6_NIB_CONF_6LR || defined(DOXYGEN) */ #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(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 */ +#define _copy_and_handle_aro(netif, ipv6, icmpv6, aro, sl2ao) \ + (NULL) +#define _set_rtr_adv(netif) (void)netif #endif /* GNRC_IPV6_NIB_CONF_6LR || defined(DOXYGEN) */ #ifdef __cplusplus 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 22ac8c2ce19ed2b27865d12e9b2ba5ec90b284c5..a1d814e10e1af7baa9784ec7bfb62d921ac5ca05 100644 --- a/sys/net/gnrc/network_layer/ipv6/nib/_nib-arsm.c +++ b/sys/net/gnrc/network_layer/ipv6/nib/_nib-arsm.c @@ -19,9 +19,10 @@ #include "net/gnrc/netif2/internal.h" #ifdef MODULE_GNRC_SIXLOWPAN_ND #include "net/gnrc/sixlowpan/nd.h" -#endif +#endif /* MODULE_GNRC_SIXLOWPAN_ND */ #include "_nib-arsm.h" +#include "_nib-router.h" #include "_nib-6lr.h" #define ENABLE_DEBUG (0) @@ -88,16 +89,16 @@ void _snd_uc_ns(_nib_onl_entry_t *nbr, bool reset) if (reset) { nbr->ns_sent = 0; } -#else +#else /* GNRC_IPV6_NIB_CONF_ARSM */ (void)reset; -#endif +#endif /* GNRC_IPV6_NIB_CONF_ARSM */ _snd_ns(&nbr->ipv6, netif, NULL, &nbr->ipv6); _evtimer_add(nbr, GNRC_IPV6_NIB_SND_UC_NS, &nbr->nud_timeout, netif->ipv6.retrans_time); gnrc_netif2_release(netif); #if GNRC_IPV6_NIB_CONF_ARSM nbr->ns_sent++; -#endif +#endif /* GNRC_IPV6_NIB_CONF_ARSM */ } void _handle_sl2ao(gnrc_netif2_t *netif, const ipv6_hdr_t *ipv6, @@ -118,7 +119,7 @@ void _handle_sl2ao(gnrc_netif2_t *netif, const ipv6_hdr_t *ipv6, (memcmp(nce->l2addr, sl2ao + 1, nce->l2addr_len) != 0)) && /* a 6LR MUST NOT modify an existing NCE based on an SL2AO in an RS * see https://tools.ietf.org/html/rfc6775#section-6.3 */ - !_rtr_sol_on_6lr(netif, icmpv6)) { + !_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(netif, nce, GNRC_IPV6_NIB_NC_INFO_NUD_STATE_STALE); @@ -142,13 +143,13 @@ void _handle_sl2ao(gnrc_netif2_t *netif, const ipv6_hdr_t *ipv6, &nce->addr_reg_timeout, SIXLOWPAN_ND_TENTATIVE_NCE_SEC_LTIME * MS_PER_SEC); } -#endif +#endif /* GNRC_IPV6_NIB_CONF_MULTIHOP_DAD && GNRC_IPV6_NIB_CONF_6LR */ } #if ENABLE_DEBUG else { DEBUG("nib: Neighbor cache full\n"); } -#endif +#endif /* ENABLE_DEBUG */ } /* not else to include NCE created in nce == NULL branch */ if ((nce != NULL) && (nce->mode & _NC)) { @@ -171,7 +172,7 @@ void _handle_sl2ao(gnrc_netif2_t *netif, const ipv6_hdr_t *ipv6, nce->l2addr_len = l2addr_len; memcpy(nce->l2addr, sl2ao + 1, l2addr_len); } -#endif +#endif /* GNRC_IPV6_NIB_CONF_ARSM */ } } @@ -183,17 +184,17 @@ static inline unsigned _get_l2addr_len(gnrc_netif2_t *netif, case NETDEV_TYPE_CC110X: (void)opt; return sizeof(uint8_t); -#endif +#endif /* MODULE_CC110X */ #ifdef MODULE_NETDEV_ETH case NETDEV_TYPE_ETHERNET: (void)opt; return ETHERNET_ADDR_LEN; -#endif +#endif /* MODULE_NETDEV_ETH */ #ifdef MODULE_NETDEV_NRFMIN case NETDEV_TYPE_NRFMIN: (void)opt; return sizeof(uint16_t); -#endif +#endif /* MODULE_NETDEV_NRFMIN */ #ifdef MODULE_NETDEV_IEEE802154 case NETDEV_TYPE_IEEE802154: switch (opt->len) { @@ -204,7 +205,7 @@ static inline unsigned _get_l2addr_len(gnrc_netif2_t *netif, default: return 0U; } -#endif +#endif /* MODULE_NETDEV_IEEE802154 */ default: (void)opt; return 0U; @@ -314,6 +315,7 @@ void _handle_state_timeout(_nib_onl_entry_t *nbr) void _probe_nbr(_nib_onl_entry_t *nbr, bool reset) { const uint16_t state = _get_nud_state(nbr); + DEBUG("nib: Probing "); switch (state) { case GNRC_IPV6_NIB_NC_INFO_NUD_STATE_UNMANAGED: @@ -363,7 +365,7 @@ void _probe_nbr(_nib_onl_entry_t *nbr, bool reset) sizeof(addr_str)), (unsigned)netif->ipv6.retrans_time); } -#endif +#endif /* ENABLE_DEBUG */ gnrc_netif2_release(netif); } break; @@ -483,14 +485,14 @@ void _set_nud_state(gnrc_netif2_t *netif, _nib_onl_entry_t *nce, #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)); + if (netif != NULL) { + _call_route_info_cb(netif, GNRC_IPV6_NIB_ROUTE_INFO_TYPE_NSC, + &nce->ipv6, (void *)((intptr_t)state)); } gnrc_netif2_release(netif); -#else +#else /* GNRC_IPV6_NIB_CONF_ROUTER */ (void)netif; -#endif +#endif /* GNRC_IPV6_NIB_CONF_ROUTER */ } /* internal functions */ @@ -515,7 +517,7 @@ static inline bool _redirect_with_tl2ao(icmpv6_hdr_t *icmpv6, ndp_opt_t *tl2ao) { return (icmpv6->type == ICMPV6_REDIRECT) && (tl2ao != NULL); } -#endif +#endif /* GNRC_IPV6_NIB_CONF_REDIRECT */ static inline bool _tl2ao_changes_nce(_nib_onl_entry_t *nce, const ndp_opt_t *tl2ao, 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 4b1be07f50cf741106a8651f6adbffdd5f9b2233..98d528d839b6751f20a673d913628430cbc6c7d7 100644 --- a/sys/net/gnrc/network_layer/ipv6/nib/_nib-internal.c +++ b/sys/net/gnrc/network_layer/ipv6/nib/_nib-internal.c @@ -25,6 +25,7 @@ #include "random.h" #include "_nib-internal.h" +#include "_nib-router.h" #define ENABLE_DEBUG (0) #include "debug.h" @@ -39,7 +40,7 @@ static _nib_dr_entry_t _def_routers[GNRC_IPV6_NIB_DEFAULT_ROUTER_NUMOF]; #if GNRC_IPV6_NIB_CONF_MULTIHOP_P6C static _nib_abr_entry_t _abrs[GNRC_IPV6_NIB_ABR_NUMOF]; -#endif +#endif /* GNRC_IPV6_NIB_CONF_MULTIHOP_P6C */ #if ENABLE_DEBUG static char addr_str[IPV6_ADDR_MAX_STR_LEN]; @@ -62,8 +63,8 @@ void _nib_init(void) memset(_dsts, 0, sizeof(_dsts)); #if GNRC_IPV6_NIB_CONF_MULTIHOP_P6C memset(_abrs, 0, sizeof(_abrs)); -#endif -#endif +#endif /* GNRC_IPV6_NIB_CONF_MULTIHOP_P6C */ +#endif /* TEST_SUITES */ evtimer_init_msg(&_nib_evtimer); /* TODO: load ABR information from persistent memory */ } @@ -103,7 +104,7 @@ _nib_onl_entry_t *_nib_onl_alloc(const ipv6_addr_t *addr, unsigned iface) else { DEBUG(" NIB full\n"); } -#endif +#endif /* ENABLE_DEBUG */ return node; } @@ -233,15 +234,15 @@ void _nib_nc_set_reachable(_nib_onl_entry_t *node) if (netif == NULL) { return; } -#endif +#endif /* TEST_SUITES */ 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, netif->ipv6.reach_time); -#else +#else /* GNRC_IPV6_NIB_CONF_ARSM */ (void)node; -#endif +#endif /* GNRC_IPV6_NIB_CONF_ARSM */ } void _nib_nc_remove(_nib_onl_entry_t *node) @@ -253,10 +254,13 @@ void _nib_nc_remove(_nib_onl_entry_t *node) evtimer_del((evtimer_t *)&_nib_evtimer, &node->snd_na.event); #if GNRC_IPV6_NIB_CONF_ARSM evtimer_del((evtimer_t *)&_nib_evtimer, &node->nud_timeout.event); -#endif +#endif /* GNRC_IPV6_NIB_CONF_ARSM */ +#if GNRC_IPV6_NIB_CONF_ROUTER + evtimer_del((evtimer_t *)&_nib_evtimer, &node->reply_rs.event); +#endif /* GNRC_IPV6_NIB_CONF_ROUTER */ #if GNRC_IPV6_NIB_CONF_6LR evtimer_del((evtimer_t *)&_nib_evtimer, &node->addr_reg_timeout.event); -#endif +#endif /* GNRC_IPV6_NIB_CONF_6LR */ #if GNRC_IPV6_NIB_CONF_QUEUE_PKT gnrc_pktqueue_t *tmp; for (gnrc_pktqueue_t *ptr = node->pktqueue; @@ -293,17 +297,17 @@ void _nib_nc_get(const _nib_onl_entry_t *node, gnrc_ipv6_nib_nc_t *nce) return; } } -#else +#else /* GNRC_IPV6_NIB_CONF_6LN */ /* Prevent unused function error thrown by clang */ (void)_get_l2addr_from_ipv6; -#endif +#endif /* GNRC_IPV6_NIB_CONF_6LN */ nce->l2addr_len = node->l2addr_len; memcpy(&nce->l2addr, &node->l2addr, node->l2addr_len); -#else +#else /* GNRC_IPV6_NIB_CONF_ARSM */ assert(ipv6_addr_is_link_local(&nce->ipv6)); _get_l2addr_from_ipv6(nce->l2addr, &node->ipv6); nce->l2addr_len = sizeof(uint64_t); -#endif +#endif /* GNRC_IPV6_NIB_CONF_ARSM */ } _nib_dr_entry_t *_nib_drl_add(const ipv6_addr_t *router_addr, unsigned iface) @@ -495,7 +499,7 @@ static inline bool _in_abrs(const _nib_abr_entry_t *abr) { return (abr < (_abrs + GNRC_IPV6_NIB_ABR_NUMOF)); } -#endif +#endif /* GNRC_IPV6_NIB_CONF_MULTIHOP_P6C */ void _nib_offl_clear(_nib_offl_entry_t *dst) { @@ -588,14 +592,22 @@ int _nib_get_route(const ipv6_addr_t *dst, gnrc_pktsnip_t *pkt, (void *)pkt); _nib_offl_entry_t *offl = _nib_offl_get_match(dst); - assert((dst != NULL) && (fte != NULL)); if ((offl == NULL) || (offl->mode == _PL)) { /* give default router precedence over PLE */ _nib_dr_entry_t *router = _nib_drl_get_dr(); if ((router == NULL) && (offl == NULL)) { +#if GNRC_IPV6_NIB_CONF_ROUTER + gnrc_netif2_t *ptr = NULL; + + while ((ptr = gnrc_netif2_iter(ptr))) { + _call_route_info_cb(ptr, + GNRC_IPV6_NIB_ROUTE_INFO_TYPE_RRQ, + dst, pkt); + } +#else /* GNRC_IPV6_NIB_CONF_ROUTER */ (void)pkt; - /* TODO: ask RRP to search for route (using pkt) */ +#endif /* GNRC_IPV6_NIB_CONF_ROUTER */ return -ENETUNREACH; } else if (router != NULL) { @@ -629,7 +641,7 @@ void _nib_pl_remove(_nib_offl_entry_t *nib_offl) } } } -#endif +#endif /* GNRC_IPV6_NIB_CONF_MULTIHOP_P6C */ } #if GNRC_IPV6_NIB_CONF_MULTIHOP_P6C @@ -660,7 +672,7 @@ _nib_abr_entry_t *_nib_abr_add(const ipv6_addr_t *addr) else { DEBUG(" NIB full\n"); } -#endif +#endif /* ENABLE_DEBUG */ return abr; } @@ -682,7 +694,7 @@ void _nib_abr_remove(const ipv6_addr_t *addr) gnrc_sixlowpan_ctx_remove(i); } } -#endif +#endif /* MODULE_GNRC_SIXLOWPAN_CTX */ memset(abr, 0, sizeof(_nib_abr_entry_t)); } } 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 97af9ec93e4b37ef305c8f2f7005e3585686ad85..9b914c12a1101eba3614dc68fa3ceb28a8c34286 100644 --- a/sys/net/gnrc/network_layer/ipv6/nib/_nib-internal.h +++ b/sys/net/gnrc/network_layer/ipv6/nib/_nib-internal.h @@ -60,6 +60,15 @@ extern "C" { to this @ref _nib_onl_entry_t */ /** @} */ +/** + * @name Off-link entry flags + * @anchor net_gnrc_ipv6_nib_offl_flags + * @{ + */ +#define _PFX_ON_LINK (0x0001) +#define _PFX_SLAAC (0x0002) +/** @} */ + /** * @brief Shorter name for convenience ;-) */ @@ -131,6 +140,9 @@ typedef struct _nib_onl_entry { * @brief Event for @ref GNRC_IPV6_NIB_SND_NA */ evtimer_msg_event_t snd_na; +#if GNRC_IPV6_NIB_CONF_ROUTER || defined(DOXYGEN) + evtimer_msg_event_t reply_rs; /**< Event for @ref GNRC_IPV6_NIB_REPLY_RS */ +#endif #if GNRC_IPV6_NIB_CONF_6LR || defined(DOXYGEN) evtimer_msg_event_t addr_reg_timeout; /**< Event for @ref GNRC_IPV6_NIB_ADDR_REG_TIMEOUT */ #endif @@ -150,12 +162,14 @@ typedef struct _nib_onl_entry { * @see [Mode flags for entries](@ref net_gnrc_ipv6_nib_mode). */ uint8_t mode; +#if GNRC_IPV6_NIB_CONF_ARSM || defined(DOXYGEN) /** * @brief Neighbor solicitations sent for probing + * + * @note Only available if @ref GNRC_IPV6_NIB_CONF_ARSM != 0. */ uint8_t ns_sent; -#if GNRC_IPV6_NIB_CONF_ARSM || defined(DOXYGEN) /** * @brief length in bytes of _nib_onl_entry_t::l2addr * @@ -187,6 +201,7 @@ typedef struct { evtimer_msg_event_t pfx_timeout; uint8_t mode; /**< [mode](@ref net_gnrc_ipv6_nib_mode) of the * off-link entry */ + uint16_t flags; /**< [flags](@ref net_gnrc_ipv6_nib_offl_flags */ uint32_t valid_until; /**< timestamp (in ms) until which the prefix valid (UINT32_MAX means forever) */ uint32_t pref_until; /**< timestamp (in ms) until which the prefix @@ -201,6 +216,8 @@ typedef struct { ipv6_addr_t addr; /**< The address of the border router */ uint32_t version; /**< last received version of the info of * the _nib_abr_entry_t::addr */ + uint32_t valid_until; /**< timestamp (in minutes) until which + * information is valid */ evtimer_msg_event_t timeout; /**< timeout of the information */ /** * @brief Bitfield marking the prefixes in the NIB's off-link entries @@ -589,11 +606,15 @@ static inline void _nib_dc_remove(_nib_offl_entry_t *nib_offl) * @pre `(pfx != NULL) && (pfx != "::") && (pfx_len != 0) && (pfx_len <= 128)` * @pre `(pref_ltime <= valid_ltime)` * - * @param[in] iface The interface to the prefix is added to. - * @param[in] pfx The IPv6 prefix or address of the destination. - * May not be NULL or unspecified address. Use - * @ref _nib_drl_add() for default route destinations. - * @param[in] pfx_len The length in bits of @p pfx in bits. + * @param[in] iface The interface to the prefix is added to. + * @param[in] pfx The IPv6 prefix or address of the destination. + * May not be NULL or unspecified address. Use + * @ref _nib_drl_add() for default route destinations. + * @param[in] pfx_len The length in bits of @p pfx in bits. + * @param[in] valid_ltime Valid lifetime in microseconds. `UINT32_MAX` for + * infinite. + * @param[in] pref_ltime Preferred lifetime in microseconds. `UINT32_MAX` for + * infinite. * * @return A new or existing off-link entry with _nib_offl_entry_t::pfx set to * @p pfx. diff --git a/sys/net/gnrc/network_layer/ipv6/nib/_nib-router.c b/sys/net/gnrc/network_layer/ipv6/nib/_nib-router.c new file mode 100644 index 0000000000000000000000000000000000000000..90d95baad168efe547d01896c3b4e91cc50ab6c9 --- /dev/null +++ b/sys/net/gnrc/network_layer/ipv6/nib/_nib-router.c @@ -0,0 +1,203 @@ +/* + * Copyright (C) 2017 Freie Universität Berlin + * + * This file is subject to the terms and conditions of the GNU Lesser + * General Public License v2.1. See the file LICENSE in the top level + * directory for more details. + */ + +/** + * @{ + * + * @file + * @author Martine Lenders <m.lenders@fu-berlin.de> + */ + +#include "net/gnrc/ipv6/nib.h" +#include "net/gnrc/ndp2.h" +#include "net/gnrc/netif2/internal.h" +#include "net/gnrc/sixlowpan/nd.h" + +#if GNRC_IPV6_NIB_CONF_MULTIHOP_P6C +#include "_nib-6ln.h" +#endif /* GNRC_IPV6_NIB_CONF_MULTIHOP_P6C */ +#include "_nib-router.h" + +#define ENABLE_DEBUG (0) +#include "debug.h" + +#if GNRC_IPV6_NIB_CONF_ROUTER +#if ENABLE_DEBUG +static char addr_str[IPV6_ADDR_MAX_STR_LEN]; +#endif + +static void _snd_ra(gnrc_netif2_t *netif, const ipv6_addr_t *dst, + bool final, _nib_abr_entry_t *abr); + +void _handle_reply_rs(_nib_onl_entry_t *host) +{ + gnrc_netif2_t *netif = gnrc_netif2_get_by_pid(_nib_onl_get_if(host)); + + assert(netif != NULL); + gnrc_netif2_acquire(netif); + if (gnrc_netif2_is_rtr_adv(netif)) { + _snd_rtr_advs(netif, &host->ipv6, false); + } + gnrc_netif2_release(netif); +} + +void _handle_snd_mc_ra(gnrc_netif2_t *netif) +{ + gnrc_netif2_acquire(netif); + assert(netif != NULL); + if (!gnrc_netif2_is_6ln(netif)) { + bool final_ra = (netif->ipv6.ra_sent > (UINT8_MAX - NDP_MAX_FIN_RA_NUMOF)); + uint32_t next_ra_time = random_uint32_range(NDP_MIN_RA_INTERVAL_MS, + NDP_MAX_RA_INTERVAL_MS); + + /* router has router advertising interface or the RA is one of the + * (now deactivated) routers final one */ + if (final_ra || gnrc_netif2_is_rtr_adv(netif)) { + _snd_rtr_advs(netif, NULL, final_ra); + netif->ipv6.last_ra = (xtimer_now_usec64() / US_PER_MS) & UINT32_MAX; + if ((netif->ipv6.ra_sent < NDP_MAX_INIT_RA_NUMOF) || final_ra) { + if ((netif->ipv6.ra_sent < NDP_MAX_INIT_RA_NUMOF) && + (next_ra_time > NDP_MAX_INIT_RA_INTERVAL)) { + next_ra_time = NDP_MAX_INIT_RA_INTERVAL; + } + netif->ipv6.ra_sent++; + } + /* netif->ipv6.ra_sent overflowed => this was our last final RA */ + if (netif->ipv6.ra_sent != 0) { + _evtimer_add(netif, GNRC_IPV6_NIB_SND_MC_RA, &netif->ipv6.snd_mc_ra, + next_ra_time); + } + } + } + gnrc_netif2_release(netif); +} + +void _snd_rtr_advs(gnrc_netif2_t *netif, const ipv6_addr_t *dst, bool final) +{ +#if GNRC_IPV6_NIB_CONF_MULTIHOP_P6C + _nib_abr_entry_t *abr = NULL; + + DEBUG("nib: Send router advertisements for each border router:\n"); + while ((abr = _nib_abr_iter(abr))) { + DEBUG(" - %s\n", ipv6_addr_to_str(addr_str, &abr->addr, + sizeof(addr_str))); + _snd_ra(netif, dst, final, abr); + } +#else /* GNRC_IPV6_NIB_CONF_MULTIHOP_P6C */ + _snd_ra(netif, dst, final, NULL); +#endif /* GNRC_IPV6_NIB_CONF_MULTIHOP_P6C */ +} + +static gnrc_pktsnip_t *_offl_to_pio(_nib_offl_entry_t *offl, + gnrc_pktsnip_t *ext_opts) +{ + uint32_t now = (xtimer_now_usec64() / US_PER_MS) & UINT32_MAX; + gnrc_pktsnip_t *pio; + uint8_t flags = 0; + uint32_t valid_ltime = (offl->valid_until == UINT32_MAX) ? UINT32_MAX : + (offl->valid_until - now); + uint32_t pref_ltime = (offl->pref_until == UINT32_MAX) ? UINT32_MAX : + (offl->pref_until - now); + + DEBUG("nib: Build PIO for %s/%u\n", + ipv6_addr_to_str(addr_str, &offl->pfx, sizeof(addr_str)), + offl->pfx_len); + if (offl->flags & _PFX_ON_LINK) { + flags |= NDP_OPT_PI_FLAGS_L; + } + if (offl->flags & _PFX_SLAAC) { + flags |= NDP_OPT_PI_FLAGS_A; + } + pio = gnrc_ndp2_opt_pi_build(&offl->pfx, offl->pfx_len, valid_ltime, + pref_ltime, flags, ext_opts); + + if ((pio == NULL) && (ext_opts != NULL)) { + DEBUG("nib: No space left in packet buffer. Not adding PIO\n"); + return NULL; + } + return pio; +} + +static gnrc_pktsnip_t *_build_ext_opts(gnrc_netif2_t *netif, + _nib_abr_entry_t *abr) +{ + gnrc_pktsnip_t *ext_opts = NULL; + _nib_offl_entry_t *pfx = NULL; + unsigned id = netif->pid; + +#if GNRC_IPV6_NIB_CONF_MULTIHOP_P6C + uint16_t ltime; + gnrc_pktsnip_t *abro; + +#ifdef MODULE_GNRC_SIXLOWPAN_CTX + for (int i = 0; i < GNRC_SIXLOWPAN_CTX_SIZE; i++) { + gnrc_sixlowpan_ctx_t *ctx; + if (bf_isset(abr->ctxs, i) && + ((ctx = gnrc_sixlowpan_ctx_lookup_id(i)) != NULL)) { + gnrc_pktsnip_t *sixco = gnrc_sixlowpan_nd_opt_6ctx_build( + ctx->prefix_len, ctx->flags_id, + ctx->ltime, &ctx->prefix, NULL); + if (sixco == NULL) { + DEBUG("nib: No space left in packet buffer. Not adding 6LO\n"); + return NULL; + } + ext_opts = sixco; + } + } +#endif /* MODULE_GNRC_SIXLOWPAN_CTX */ + while ((pfx = _nib_abr_iter_pfx(abr, pfx))) { + if (_nib_onl_get_if(pfx->next_hop) == id) { + if ((ext_opts = _offl_to_pio(pfx, ext_opts)) == NULL) { + return NULL; + } + } + } + ltime = (gnrc_netif2_is_6lbr(netif)) ? + (SIXLOWPAN_ND_OPT_ABR_LTIME_DEFAULT) : + (abr->valid_until - _now_min()); + (void)ltime; /* gnrc_sixlowpan_nd_opt_abr_build might evaluate to NOP */ + abro = gnrc_sixlowpan_nd_opt_abr_build(abr->version, ltime, &abr->addr, + ext_opts); + if (abro == NULL) { + DEBUG("nib: No space left in packet buffer. Not adding ABRO\n"); + return NULL; + } + ext_opts = abro; +#else /* GNRC_IPV6_NIB_CONF_MULTIHOP_P6C */ + (void)abr; + while ((pfx = _nib_offl_iter(pfx))) { + if ((pfx->mode & _PL) && (_nib_onl_get_if(pfx->next_hop) == id)) { + if ((ext_opts = _offl_to_pio(pfx, ext_opts)) == NULL) { + return NULL; + } + } + } +#endif /* GNRC_IPV6_NIB_CONF_MULTIHOP_P6C */ + return ext_opts; +} + +void _set_rtr_adv(gnrc_netif2_t *netif) +{ + DEBUG("nib: set RTR_ADV flag for interface %i\n", netif->pid); + netif->ipv6.ra_sent = 0; + netif->flags |= GNRC_NETIF2_FLAGS_IPV6_RTR_ADV; + _handle_snd_mc_ra(netif); +} + +static void _snd_ra(gnrc_netif2_t *netif, const ipv6_addr_t *dst, + bool final, _nib_abr_entry_t *abr) +{ + gnrc_pktsnip_t *ext_opts = _build_ext_opts(netif, abr); + + gnrc_ndp2_rtr_adv_send(netif, NULL, dst, final, ext_opts); +} +#else /* GNRC_IPV6_NIB_CONF_ROUTER */ +typedef int dont_be_pedantic; +#endif /* GNRC_IPV6_NIB_CONF_ROUTER */ + +/** @} */ diff --git a/sys/net/gnrc/network_layer/ipv6/nib/_nib-router.h b/sys/net/gnrc/network_layer/ipv6/nib/_nib-router.h new file mode 100644 index 0000000000000000000000000000000000000000..1205dc555f2a0f7ff73de8a100bec87e832ee58d --- /dev/null +++ b/sys/net/gnrc/network_layer/ipv6/nib/_nib-router.h @@ -0,0 +1,132 @@ +/* + * Copyright (C) 2017 Freie Universität Berlin + * + * This file is subject to the terms and conditions of the GNU Lesser + * General Public License v2.1. See the file LICENSE in the top level + * directory for more details. + */ + +/** + * @ingroup net_gnrc_ipv6_nib + * @internal + * @{ + * + * @file + * @brief Definitions related to router functionality of NIB + * + * @author Martine Lenders <m.lenders@fu-berlin.de> + */ +#ifndef PRIV_NIB_ROUTER_H +#define PRIV_NIB_ROUTER_H + +#include "net/gnrc/ipv6/nib/conf.h" +#include "net/gnrc/netif2/internal.h" +#include "net/gnrc/netif2/ipv6.h" +#include "net/ipv6/addr.h" +#include "net/ndp.h" + +#include "_nib-internal.h" + +#ifdef __cplusplus +extern "C" { +#endif + +#if GNRC_IPV6_NIB_CONF_ROUTER || defined(DOXYGEN) +/** + * @brief Initializes interface for router behavior + * + * @param[in] netif An interface. + */ +static inline void _init_iface_router(gnrc_netif2_t *netif) +{ + netif->ipv6.rtr_ltime = NDP_RTR_LTIME_SEC; + 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 /* !GNRC_IPV6_NIB_CONF_6LR || GNRC_IPV6_NIB_CONF_6LBR */ +#if GNRC_IPV6_NIB_CONF_6LBR + netif->flags |= GNRC_NETIF2_FLAGS_6LO_ABR; +#endif /* GNRC_IPV6_NIB_CONF_6LBR */ + gnrc_netif2_ipv6_group_join(netif, &ipv6_addr_all_routers_link_local); +} + +/** + * @brief Helper function to safely call the + * [route info callback](@ref gnrc_netif2_ipv6_t::route_info_cb) of an + * interface + * + * @param[in] netif An interface. + * @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. + */ +static inline void _call_route_info_cb(gnrc_netif2_t *netif, unsigned type, + const ipv6_addr_t *ctx_addr, + const void *ctx) +{ + if (netif->ipv6.route_info_cb != NULL) { + netif->ipv6.route_info_cb(type, ctx_addr, ctx); + } +} + +/** + * @brief Handler for @ref GNRC_IPV6_NIB_REPLY_RS event handler + * + * @param[in] host Host that sent the router solicitation + */ +void _handle_reply_rs(_nib_onl_entry_t *host); + +/** + * @brief Handler for @ref GNRC_IPV6_NIB_SND_MC_RA event handler + * + * @param[in] netif Network interface to send multicast router advertisement + * over. + */ +void _handle_snd_mc_ra(gnrc_netif2_t *netif); + +/** + * @brief Set the @ref GNRC_NETIF2_FLAGS_IPV6_RTR_ADV flag for an interface + * and starts advertising that interface as a router + * + * @param[in] netif Interface to set the @ref GNRC_NETIF2_FLAGS_IPV6_RTR_ADV + * for. + */ +void _set_rtr_adv(gnrc_netif2_t *netif); + +/** + * @brief Send router advertisements + * + * If @ref GNRC_IPV6_NIB_CONF_MULTIHOP_P6C is not 0 this sends one router + * advertisement per configured ABR, otherwise it just sends one single router + * advertisement for the interface. + * + * @param[in] netif The interface to send the router advertisement over. + * @param[in] dst Destination address for the router advertisement. + * @param[in] final The router advertisement are the final ones of the @p netif + * (because it was set to be a non-forwarding interface e.g.). + */ +void _snd_rtr_advs(gnrc_netif2_t *netif, const ipv6_addr_t *dst, + bool final); +#else /* GNRC_IPV6_NIB_CONF_ROUTER */ +#define _init_iface_router(netif) (void)netif +#define _call_route_info_cb(netif, type, ctx_addr, ctx) (void)netif; \ + (void)type; \ + (void)ctx_addr; \ + (void)ctx +#define _handle_reply_rs(host) (void)host +#define _handle_snd_mc_ra(netif) (void)netif +#define _set_rtr_adv(netif) (void)netif +#define _snd_rtr_advs(netif, dst, final) (void)netif; \ + (void)dst; \ + (void)final +#endif /* GNRC_IPV6_NIB_CONF_ROUTER */ + +#ifdef __cplusplus +} +#endif + +#endif /* PRIV_NIB_ROUTER_H */ +/** @} */ diff --git a/sys/net/gnrc/network_layer/ipv6/nib/nib.c b/sys/net/gnrc/network_layer/ipv6/nib/nib.c index 58219d4503fb17f0c7696e2f6021636a56f81d33..9ff8d152757ce4d67b79a0ece2e5a30f52eea874 100644 --- a/sys/net/gnrc/network_layer/ipv6/nib/nib.c +++ b/sys/net/gnrc/network_layer/ipv6/nib/nib.c @@ -29,6 +29,7 @@ #include "_nib-internal.h" #include "_nib-arsm.h" +#include "_nib-router.h" #include "_nib-6ln.h" #include "_nib-6lr.h" @@ -44,12 +45,18 @@ static char addr_str[IPV6_ADDR_MAX_STR_LEN]; #if GNRC_IPV6_NIB_CONF_QUEUE_PKT static gnrc_pktqueue_t _queue_pool[GNRC_IPV6_NIB_NUMOF]; -#endif +#endif /* GNRC_IPV6_NIB_CONF_QUEUE_PKT */ /** * @internal * @{ */ +#if GNRC_IPV6_NIB_CONF_ROUTER +static void _handle_rtr_sol(gnrc_netif2_t *netif, const ipv6_hdr_t *ipv6, + const ndp_rtr_sol_t *rtr_sol, size_t icmpv6_len); +#endif /* GNRC_IPV6_NIB_CONF_ROUTER */ +static void _handle_rtr_adv(gnrc_netif2_t *netif, const ipv6_hdr_t *ipv6, + const ndp_rtr_adv_t *rtr_adv, size_t icmpv6_len); 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(gnrc_netif2_t *netif, const ipv6_hdr_t *ipv6, @@ -59,7 +66,19 @@ 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_pfx_timeout(_nib_offl_entry_t *pfx); +static void _handle_rtr_timeout(_nib_dr_entry_t *router); static void _handle_snd_na(gnrc_pktsnip_t *pkt); +#if GNRC_IPV6_NIB_CONF_6LN || GNRC_IPV6_NIB_CONF_SLAAC +static void _auto_configure_addr(gnrc_netif2_t *netif, const ipv6_addr_t *pfx, + uint8_t pfx_len); +#else /* GNRC_IPV6_NIB_CONF_6LN || GNRC_IPV6_NIB_CONF_SLAAC */ +#define _auto_configure_addr(netif, pfx, pfx_len) (void)netif; \ + (void)pfx; \ + (void)pfx_len +#endif /* GNRC_IPV6_NIB_CONF_6LN || GNRC_IPV6_NIB_CONF_SLAAC */ +/* needs to be exported for 6LN's ARO handling */ +void _handle_search_rtr(gnrc_netif2_t *netif); /** @} */ void gnrc_ipv6_nib_init(void) @@ -78,51 +97,20 @@ void gnrc_ipv6_nib_init(void) void gnrc_ipv6_nib_init_iface(gnrc_netif2_t *netif) { - ipv6_addr_t addr = IPV6_ADDR_UNSPECIFIED; - 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 - * - join solicited nodes group of link-local address here for address - * resolution here - * - 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(netif); netif->ipv6.retrans_time = NDP_RETRANS_TIMER_MS; - netif->ipv6.na_sent = 0; -#if GNRC_IPV6_NIB_CONF_ROUTER - 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 -#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_SLAAC || GNRC_IPV6_NIB_CONF_6LN + /* TODO: set differently dependent on GNRC_IPV6_NIB_CONF_SLAAC if + * alternatives exist */ + netif->ipv6.aac_mode = GNRC_NETIF2_AAC_AUTO; +#endif /* GNRC_IPV6_NIB_CONF_SLAAC || GNRC_IPV6_NIB_CONF_6LN */ + _init_iface_router(netif); #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; @@ -134,35 +122,52 @@ void gnrc_ipv6_nib_init_iface(gnrc_netif2_t *netif) * 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); +#endif /* GNRC_IPV6_NIB_CONF_6LN */ + netif->ipv6.na_sent = 0; + if (gnrc_netif2_ipv6_group_join(netif, + &ipv6_addr_all_nodes_link_local) < 0) { + DEBUG("nib: Can't join link-local all-nodes on interface %u\n", + netif->pid); + gnrc_netif2_release(netif); 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; + _auto_configure_addr(netif, &ipv6_addr_link_local_prefix, 64U); + if (!(gnrc_netif2_is_rtr_adv(netif)) || + (gnrc_netif2_is_6ln(netif) && !gnrc_netif2_is_6lbr(netif))) { + uint32_t next_rs_time = random_uint32_range(0, NDP_MAX_RS_MS_DELAY); + + _evtimer_add(netif, GNRC_IPV6_NIB_SEARCH_RTR, &netif->ipv6.search_rtr, + next_rs_time); } -#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 +#if GNRC_IPV6_NIB_CONF_ROUTER + else { + _handle_snd_mc_ra(netif); + } +#endif /* GNRC_IPV6_NIB_CONF_ROUTER */ gnrc_netif2_release(netif); } +static bool _on_link(const ipv6_addr_t *dst, unsigned *iface) +{ + _nib_offl_entry_t *entry = NULL; + +#if GNRC_IPV6_NIB_CONF_6LN + if (*iface != 0) { + if (gnrc_netif2_is_6ln(gnrc_netif2_get_by_pid(*iface))) { + return ipv6_addr_is_link_local(dst); + } + } +#endif /* GNRC_IPV6_NIB_CONF_6LN */ + while ((entry = _nib_offl_iter(entry))) { + if ((entry->mode & _PL) && (entry->flags & _PFX_ON_LINK) && + (ipv6_addr_match_prefix(dst, &entry->pfx) >= entry->pfx_len)) { + *iface = _nib_onl_get_if(entry->next_hop); + return true; + } + } + return ipv6_addr_is_link_local(dst); +} + int gnrc_ipv6_nib_get_next_hop_l2addr(const ipv6_addr_t *dst, gnrc_netif2_t *netif, gnrc_pktsnip_t *pkt, gnrc_ipv6_nib_nc_t *nce) @@ -175,19 +180,71 @@ int gnrc_ipv6_nib_get_next_hop_l2addr(const ipv6_addr_t *dst, 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 */ + _nib_onl_entry_t *node = _nib_onl_get(dst, + (netif == NULL) ? 0 : netif->pid); + /* consider neighbor cache entries first */ + unsigned iface = (node == NULL) ? 0 : _nib_onl_get_if(node); + + if ((node != NULL) || _on_link(dst, &iface)) { + DEBUG("nib: %s is on-link or in NC, start address resolution\n", + ipv6_addr_to_str(addr_str, dst, sizeof(addr_str))); + /* on-link prefixes return their interface */ + if (!ipv6_addr_is_link_local(dst) && (iface != 0)) { + /* release preassumed interface */ + gnrc_netif2_release(netif); + netif = gnrc_netif2_get_by_pid(iface); + gnrc_netif2_acquire(netif); + } if ((netif == NULL) || - !_resolve_addr(dst, netif, pkt, nce, - _nib_onl_get(dst, netif->pid))) { + !_resolve_addr(dst, netif, pkt, nce, node)) { + DEBUG("nib: host unreachable\n"); res = -EHOSTUNREACH; break; } } else { - /* TODO: Off-link next hop determination; - * might need netif locking */ - res = -EHOSTUNREACH; + gnrc_ipv6_nib_ft_t route; + + DEBUG("nib: %s is off-link, resolve route\n", + ipv6_addr_to_str(addr_str, dst, sizeof(addr_str))); + res = _nib_get_route(dst, pkt, &route); + if ((res < 0) || ipv6_addr_is_unspecified(&route.next_hop)) { + DEBUG("nib: no route to %s found or is prefix list entry, " + "search neighbor cache\n", + ipv6_addr_to_str(addr_str, dst, sizeof(addr_str))); + + if (res == 0) { + DEBUG("nib: prefix list entry => taking dst as next hop\n"); + memcpy(&route.next_hop, dst, sizeof(route.next_hop)); + } + else { + res = -ENETUNREACH; + break; + } + } + if ((netif != NULL) && (netif->pid != route.iface)) { + /* drop pre-assumed netif */ + gnrc_netif2_release(netif); + } + if ((netif == NULL) || (netif->pid != route.iface)) { + /* get actual netif */ + netif = gnrc_netif2_get_by_pid(route.iface); + gnrc_netif2_acquire(netif); + } + node = _nib_onl_get(&route.next_hop, + (netif == NULL) ? netif->pid : 0); + if (_resolve_addr(&route.next_hop, netif, pkt, nce, node)) { + _call_route_info_cb(netif, + GNRC_IPV6_NIB_ROUTE_INFO_TYPE_RN, + &route.dst, + (void *)((intptr_t)route.dst_len)); +#if GNRC_IPV6_NIB_CONF_DC + _nib_dc_add(&route.next_hop, netif->pid, dst); +#endif /* GNRC_IPV6_NIB_CONF_DC */ + } + else { + res = -EHOSTUNREACH; + } } } while (0); mutex_unlock(&_nib_mutex); @@ -205,11 +262,11 @@ void gnrc_ipv6_nib_handle_pkt(gnrc_netif2_t *netif, const ipv6_hdr_t *ipv6, switch (icmpv6->type) { #if GNRC_IPV6_NIB_CONF_ROUTER case ICMPV6_RTR_SOL: - /* TODO */ + _handle_rtr_sol(netif, ipv6, (ndp_rtr_sol_t *)icmpv6, icmpv6_len); break; #endif /* GNRC_IPV6_NIB_CONF_ROUTER */ case ICMPV6_RTR_ADV: - /* TODO */ + _handle_rtr_adv(netif, ipv6, (ndp_rtr_adv_t *)icmpv6, icmpv6_len); break; case ICMPV6_NBR_SOL: _handle_nbr_sol(netif, ipv6, (ndp_nbr_sol_t *)icmpv6, icmpv6_len); @@ -241,7 +298,6 @@ 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: @@ -259,38 +315,37 @@ void gnrc_ipv6_nib_handle_timer_event(void *ctx, uint16_t type) _handle_snd_na(ctx); break; case GNRC_IPV6_NIB_SEARCH_RTR: - /* TODO */ - break; - case GNRC_IPV6_NIB_RECONFIRM_RTR: - /* TODO */ + _handle_search_rtr(ctx); break; #if GNRC_IPV6_NIB_CONF_ROUTER case GNRC_IPV6_NIB_REPLY_RS: - /* TODO */ + _handle_reply_rs(ctx); break; case GNRC_IPV6_NIB_SND_MC_RA: - /* TODO */ + _handle_snd_mc_ra(ctx); break; #endif /* GNRC_IPV6_NIB_CONF_ROUTER */ -#if GNRC_IPV6_NIB_CONF_6LN +#if GNRC_IPV6_NIB_CONF_6LR case GNRC_IPV6_NIB_ADDR_REG_TIMEOUT: - /* TODO */ + _nib_nc_remove(ctx); break; - case GNRC_IPV6_NIB_6LO_CTX_TIMEOUT: - /* TODO */ - break; -#endif /* GNRC_IPV6_NIB_CONF_6LN */ +#endif /* GNRC_IPV6_NIB_CONF_6LR */ #if GNRC_IPV6_NIB_CONF_MULTIHOP_P6C case GNRC_IPV6_NIB_ABR_TIMEOUT: - /* TODO */ + _nib_abr_remove(&((_nib_abr_entry_t *)ctx)->addr); break; #endif /* GNRC_IPV6_NIB_CONF_MULTIHOP_P6C */ case GNRC_IPV6_NIB_PFX_TIMEOUT: - /* TODO */ + _handle_pfx_timeout(ctx); break; case GNRC_IPV6_NIB_RTR_TIMEOUT: - /* TODO */ + _handle_rtr_timeout(ctx); + break; +#if GNRC_IPV6_NIB_CONF_6LN + case GNRC_IPV6_NIB_REREG_ADDRESS: + _handle_rereg_address(ctx); break; +#endif /* GNRC_IPV6_NIB_CONF_6LN */ default: break; } @@ -300,18 +355,39 @@ void gnrc_ipv6_nib_handle_timer_event(void *ctx, uint16_t type) #if GNRC_IPV6_NIB_CONF_ROUTER void gnrc_ipv6_nib_change_rtr_adv_iface(gnrc_netif2_t *netif, bool enable) { + gnrc_netif2_acquire(netif); if (enable) { - netif->flags |= GNRC_NETIF2_FLAGS_IPV6_RTR_ADV; - /* TODO: start router advertisements */ + _set_rtr_adv(netif); } else { + uint32_t next_rs_time = random_uint32_range(0, NDP_MAX_RS_MS_DELAY); + + netif->ipv6.ra_sent = (UINT8_MAX - NDP_MAX_FIN_RA_NUMOF) + 1; netif->flags &= ~GNRC_NETIF2_FLAGS_IPV6_RTR_ADV; - /* TODO: - * - start final router advertisements, - * - start router solicitations? */ + /* send final router advertisements */ + _handle_snd_mc_ra(netif); + _evtimer_add(netif, GNRC_IPV6_NIB_SEARCH_RTR, &netif->ipv6.search_rtr, + next_rs_time); } + gnrc_netif2_release(netif); } -#endif +#endif /* GNRC_IPV6_NIB_CONF_ROUTER */ + +/* + * @internal + * @{ + */ +static void _handle_mtuo(gnrc_netif2_t *netif, const icmpv6_hdr_t *icmpv6, + const ndp_opt_mtu_t *mtuo); +#if GNRC_IPV6_NIB_CONF_MULTIHOP_P6C +static uint32_t _handle_pio(gnrc_netif2_t *netif, const icmpv6_hdr_t *icmpv6, + const ndp_opt_pi_t *pio, + _nib_abr_entry_t *abr); +#else /* GNRC_IPV6_NIB_CONF_MULTIHOP_P6C */ +static uint32_t _handle_pio(gnrc_netif2_t *netif, const icmpv6_hdr_t *icmpv6, + const ndp_opt_pi_t *pio); +#endif /* GNRC_IPV6_NIB_CONF_MULTIHOP_P6C */ +/** @} */ /* Iterator for NDP options in a packet */ #define FOREACH_OPT(ndp_pkt, opt, icmpv6_len) \ @@ -320,16 +396,323 @@ void gnrc_ipv6_nib_change_rtr_adv_iface(gnrc_netif2_t *netif, bool enable) icmpv6_len -= (opt->len << 3), \ opt = (ndp_opt_t *)(((uint8_t *)opt) + (opt->len << 3))) +#if GNRC_IPV6_NIB_CONF_ROUTER +static void _handle_rtr_sol(gnrc_netif2_t *netif, const ipv6_hdr_t *ipv6, + const ndp_rtr_sol_t *rtr_sol, size_t icmpv6_len) +{ + size_t tmp_len = icmpv6_len - sizeof(ndp_rtr_sol_t); + _nib_onl_entry_t *nce = NULL; + ndp_opt_t *opt; + uint32_t next_ra_delay = random_uint32_range(0, NDP_MAX_RA_DELAY); + + assert(netif != NULL); + /* check validity, see: https://tools.ietf.org/html/rfc4861#section-6.1.1 */ + /* checksum is checked by GNRC's ICMPv6 module */ + if (!(gnrc_netif2_is_rtr(netif)) || (ipv6->hl != 255U) || + (rtr_sol->code != 0U) || (icmpv6_len < sizeof(ndp_rtr_sol_t))) { + DEBUG("nib: Received router solicitation is invalid (or interface %i " + "is not a forwarding interface). Discarding silently\n", + netif->pid); + DEBUG(" - IP Hop Limit: %u (should be 255)\n", ipv6->hl); + DEBUG(" - ICMP code: %u (should be 0)\n", rtr_sol->code); + DEBUG(" - ICMP length: %u (should > %u)\n", icmpv6_len, + sizeof(ndp_rtr_sol_t)); + return; + } + /* pre-check option length */ + FOREACH_OPT(rtr_sol, opt, tmp_len) { + if (tmp_len > icmpv6_len) { + DEBUG("nib: Payload length (%u) of RS doesn't align with options\n", + (unsigned)icmpv6_len); + return; + } + if (opt->len == 0U) { + DEBUG("nib: Option of length 0 detected. " + "Discarding router solicitation silently\n"); + return; + } + if ((opt->type == NDP_OPT_SL2A) && + ipv6_addr_is_unspecified(&ipv6->src)) { + DEBUG("nib: RS contains SLLAO, but source was unspecfied. " + "Discarding router solicitation silently\n"); + return; + } + } + DEBUG("nib: Received valid router solicitation:\n"); + DEBUG(" - Source address: %s\n", + ipv6_addr_to_str(addr_str, &ipv6->src, sizeof(addr_str))); + DEBUG(" - Destination address: %s\n", + ipv6_addr_to_str(addr_str, &ipv6->dst, sizeof(addr_str))); + if (!ipv6_addr_is_unspecified(&ipv6->src)) { + tmp_len = icmpv6_len - sizeof(ndp_rtr_sol_t); + FOREACH_OPT(rtr_sol, opt, tmp_len) { + switch (opt->type) { + case NDP_OPT_SL2A: + if (!gnrc_netif2_is_6ln(netif)) { + _handle_sl2ao(netif, ipv6, (const icmpv6_hdr_t *)rtr_sol, + opt); + } + + break; + default: + break; + } + } + nce = _nib_onl_get(&ipv6->src, netif->pid); + } + if (!gnrc_netif2_is_6ln(netif)) { + uint32_t next_ra_scheduled = _evtimer_lookup(netif, + GNRC_IPV6_NIB_SND_MC_RA); + if (next_ra_scheduled < next_ra_delay) { + DEBUG("nib: There is a MC RA scheduled within the next %" PRIu32 "ms. " + "Using that to advertise router\n", next_ra_scheduled); + return; + } + else if (nce != NULL) { + /* we send unicast RAs so we do not need to rate-limit as + * https://tools.ietf.org/html/rfc4861#section-6.2.6 asks for */ + _evtimer_add(nce, GNRC_IPV6_NIB_REPLY_RS, &nce->reply_rs, + next_ra_delay); + } + else { + uint32_t now = (xtimer_now_usec64() / MS_PER_SEC) & UINT32_MAX; + + /* check for integer overflows and initial value of last_ra */ + if (((netif->ipv6.last_ra > (UINT32_MAX - NDP_MIN_MS_DELAY_BETWEEN_RAS) && + (now < NDP_MIN_MS_DELAY_BETWEEN_RAS))) || + ((now - NDP_MIN_MS_DELAY_BETWEEN_RAS) > netif->ipv6.last_ra)) { + next_ra_delay += NDP_MIN_MS_DELAY_BETWEEN_RAS; + } + _evtimer_add(netif, GNRC_IPV6_NIB_SND_MC_RA, &netif->ipv6.snd_mc_ra, + next_ra_delay); + } + } +#if GNRC_IPV6_NIB_CONF_6LR + else if (gnrc_netif2_is_rtr(netif) && gnrc_netif2_is_rtr_adv(netif)) { + _snd_rtr_advs(netif, &ipv6->src, false); + } +#endif /* GNRC_IPV6_NIB_CONF_6LR */ +} +#endif /* GNRC_IPV6_NIB_CONF_ROUTER */ + +static inline uint32_t _min(uint32_t a, uint32_t b) +{ + return (a < b) ? a : b; +} + +static void _handle_rtr_adv(gnrc_netif2_t *netif, const ipv6_hdr_t *ipv6, + const ndp_rtr_adv_t *rtr_adv, size_t icmpv6_len) +{ + size_t tmp_len = icmpv6_len - sizeof(ndp_rtr_adv_t); + _nib_dr_entry_t *dr = NULL; + ndp_opt_t *opt; + +#if GNRC_IPV6_NIB_CONF_MULTIHOP_P6C + sixlowpan_nd_opt_abr_t *abro = NULL; + _nib_abr_entry_t *abr = NULL; +#endif /* GNRC_IPV6_NIB_CONF_MULTIHOP_P6C */ + uint32_t next_timeout = UINT32_MAX; + + assert(netif != NULL); + /* check validity, see: https://tools.ietf.org/html/rfc4861#section-6.1.1 */ + /* checksum is checked by GNRC's ICMPv6 module */ + if (!(ipv6_addr_is_link_local(&ipv6->src)) || + (ipv6->hl != 255U) || (rtr_adv->code != 0U) || + (icmpv6_len < sizeof(ndp_rtr_adv_t)) || + (!gnrc_netif2_is_6ln(netif) && + (byteorder_ntohs(rtr_adv->ltime) > NDP_RTR_ADV_LTIME_SEC_MAX))) { + DEBUG("nib: Received router advertisement is invalid. " + "Discarding silently\n"); + DEBUG(" - IP Hop Limit: %u (should be 255)\n", ipv6->hl); + DEBUG(" - ICMP code: %u (should be 0)\n", rtr_adv->code); + DEBUG(" - ICMP length: %u (should > %u)\n", (unsigned)icmpv6_len, + sizeof(ndp_rtr_adv_t)); + DEBUG(" - Source address: %s (should be link-local)\n", + ipv6_addr_to_str(addr_str, &ipv6->src, sizeof(addr_str))); + DEBUG(" - Router lifetime: %u (should be <= 9000 on non-6LN)\n", + byteorder_ntohs(rtr_adv->ltime)); + return; + } + /* pre-check option length */ + FOREACH_OPT(rtr_adv, opt, tmp_len) { + if (tmp_len > icmpv6_len) { + DEBUG("nib: Payload length (%u) of RA doesn't align with options\n", + (unsigned)icmpv6_len); + return; + } + if (opt->len == 0U) { + DEBUG("nib: Option of length 0 detected. " + "Discarding router advertisement silently\n"); + return; + } +#if GNRC_IPV6_NIB_CONF_MULTIHOP_P6C + if (opt->type == NDP_OPT_ABR) { + if (abro != NULL) { + DEBUG("nib: More than one ABRO. " + "Discarding router advertisement silently\n"); + return; + } + abro = (sixlowpan_nd_opt_abr_t *)opt; + } +#endif /* GNRC_IPV6_NIB_CONF_MULTIHOP_P6C */ + } + DEBUG("nib: Received valid router advertisement:\n"); + DEBUG(" - Source address: %s\n", + ipv6_addr_to_str(addr_str, &ipv6->src, sizeof(addr_str))); + DEBUG(" - Destination address: %s\n", + ipv6_addr_to_str(addr_str, &ipv6->dst, sizeof(addr_str))); + DEBUG(" - Cur Hop Limit: %u\n", rtr_adv->cur_hl); + DEBUG(" - Flags: %c%c\n", + (rtr_adv->flags & NDP_RTR_ADV_FLAGS_M) ? 'M' : '-', + (rtr_adv->flags & NDP_RTR_ADV_FLAGS_O) ? 'O' : '-'); + DEBUG(" - Router Lifetime: %us\n", byteorder_ntohs(rtr_adv->ltime)); + DEBUG(" - Reachable Time: %" PRIu32 "ms\n", + byteorder_ntohl(rtr_adv->reach_time)); + DEBUG(" - Retrans Timer: %" PRIu32 "ms\n", + byteorder_ntohl(rtr_adv->retrans_timer)); +#if GNRC_IPV6_NIB_CONF_MULTIHOP_P6C + if (abro != NULL) { + if ((abr = _handle_abro(abro)) == NULL) { + DEBUG("nib: could not allocate space for new border router or " + "there is no new information in the RA. " + "Discarding silently\n"); + return; + } + /* UINT16_MAX * 60 * 1000 < UINT32_MAX so there are no overflows */ + next_timeout = _min(next_timeout, + byteorder_ntohs(abro->ltime) * SEC_PER_MIN * + MS_PER_SEC); + } +#if !GNRC_IPV6_NIB_CONF_6LBR + else { + DEBUG("nib: multihop prefix and context dissemination activated,\n" + " but no ABRO found. Discarding router advertisement silently\n"); + return; + } +#endif /* !GNRC_IPV6_NIB_CONF_6LBR */ +#endif /* GNRC_IPV6_NIB_CONF_MULTIHOP_P6C */ + if (rtr_adv->ltime.u16 != 0) { + dr = _nib_drl_add(&ipv6->src, netif->pid); + if (dr != NULL) { + dr->ltime = byteorder_ntohs(rtr_adv->ltime); + } + else { + DEBUG("nib: default router list is full. Ignoring RA from %s\n", + ipv6_addr_to_str(addr_str, &ipv6->src, sizeof(addr_str))); + return; + } + /* UINT16_MAX * 1000 < UINT32_MAX so there are no overflows */ + next_timeout = _min(next_timeout, dr->ltime * MS_PER_SEC); + } + else { + dr = _nib_drl_get(&ipv6->src, netif->pid); + + DEBUG("nib: router lifetime was 0. Removing router and routes via it."); + if (dr != NULL) { + _handle_rtr_timeout(dr); + } + dr = NULL; + } + if (rtr_adv->cur_hl != 0) { + netif->cur_hl = rtr_adv->cur_hl; + } +#if GNRC_IPV6_NIB_CONF_ARSM + if (rtr_adv->reach_time.u32 != 0) { + uint32_t reach_time = byteorder_ntohl(rtr_adv->reach_time); + + if (reach_time != netif->ipv6.reach_time_base) { + _evtimer_add(netif, GNRC_IPV6_NIB_RECALC_REACH_TIME, + &netif->ipv6.recalc_reach_time, + GNRC_IPV6_NIB_CONF_REACH_TIME_RESET); + netif->ipv6.reach_time_base = reach_time; + _recalc_reach_time(&netif->ipv6); + } + } +#endif /* GNRC_IPV6_NIB_CONF_ARSM */ + if (rtr_adv->retrans_timer.u32 != 0) { + netif->ipv6.retrans_time = byteorder_ntohl(rtr_adv->retrans_timer); + } +#if GNRC_IPV6_NIB_CONF_6LN + if ((dr != NULL) && gnrc_netif2_is_6ln(netif) && + !gnrc_netif2_is_6lbr(netif) && + !(netif->flags & GNRC_NETIF2_FLAGS_6LO_ADDRS_REG)) { + /* (register addresses already assigned)*/ + for (int i = 0; i < GNRC_NETIF2_IPV6_ADDRS_NUMOF; i++) { + if ((netif->ipv6.addrs_flags[i] != 0)) { + _handle_rereg_address(&netif->ipv6.addrs[i]); + } + } + netif->flags |= GNRC_NETIF2_FLAGS_6LO_ADDRS_REG; + } +#endif /* GNRC_IPV6_NIB_CONF_6LN */ + tmp_len = icmpv6_len - sizeof(ndp_rtr_adv_t); + FOREACH_OPT(rtr_adv, opt, tmp_len) { + switch (opt->type) { + case NDP_OPT_SL2A: + _handle_sl2ao(netif, ipv6, (const icmpv6_hdr_t *)rtr_adv, + opt); + + break; + case NDP_OPT_MTU: + _handle_mtuo(netif, (const icmpv6_hdr_t *)rtr_adv, + (ndp_opt_mtu_t *)opt); + break; + case NDP_OPT_PI: { + uint32_t min_pfx_timeout; +#if GNRC_IPV6_NIB_CONF_MULTIHOP_P6C + min_pfx_timeout = _handle_pio(netif, + (const icmpv6_hdr_t *)rtr_adv, + (ndp_opt_pi_t *)opt, abr); +#else /* GNRC_IPV6_NIB_CONF_MULTIHOP_P6C */ + min_pfx_timeout = _handle_pio(netif, + (const icmpv6_hdr_t *)rtr_adv, + (ndp_opt_pi_t *)opt); +#endif /* GNRC_IPV6_NIB_CONF_MULTIHOP_P6C */ + next_timeout = _min(next_timeout, min_pfx_timeout); + break; + } + /* ABRO was already secured in the option check above */ +#if GNRC_IPV6_NIB_CONF_6LN + case NDP_OPT_6CTX: +#if GNRC_IPV6_NIB_CONF_MULTIHOP_P6C + next_timeout = _min(_handle_6co((icmpv6_hdr_t *)rtr_adv, + (sixlowpan_nd_opt_6ctx_t *)opt, + abr), next_timeout); +#else /* GNRC_IPV6_NIB_CONF_MULTIHOP_P6C */ + next_timeout = _min(_handle_6co((icmpv6_hdr_t *)rtr_adv, + (sixlowpan_nd_opt_6ctx_t *)opt), + next_timeout); +#endif /* GNRC_IPV6_NIB_CONF_MULTIHOP_P6C */ + break; +#endif /* GNRC_IPV6_NIB_CONF_6LN */ + default: + break; + } + } + /* stop sending router solicitations + * see https://tools.ietf.org/html/rfc4861#section-6.3.7 */ + evtimer_del(&_nib_evtimer, &netif->ipv6.search_rtr.event); +#if GNRC_IPV6_NIB_CONF_6LN + if (gnrc_netif2_is_6ln(netif) && !gnrc_netif2_is_6lbr(netif)) { + _set_rtr_adv(netif); + /* but re-fetch information from router in time */ + _evtimer_add(netif, GNRC_IPV6_NIB_SEARCH_RTR, + &netif->ipv6.search_rtr, (next_timeout >> 2) * 3); + /* i.e. 3/4 of the time before the earliest expires */ + } +#endif /* GNRC_IPV6_NIB_CONF_6LN */ +} + static inline size_t _get_l2src(const gnrc_netif2_t *netif, uint8_t *l2src) { #if GNRC_NETIF2_L2ADDR_MAXLEN > 0 memcpy(l2src, netif->l2addr, netif->l2addr_len); return netif->l2addr_len; -#else +#else /* GNRC_NETIF2_L2ADDR_MAXLEN > 0 */ (void)netif; (void)l2src; return 0; -#endif +#endif /* GNRC_NETIF2_L2ADDR_MAXLEN > 0 */ } static void _send_delayed_nbr_adv(const gnrc_netif2_t *netif, @@ -345,7 +728,7 @@ static void _send_delayed_nbr_adv(const gnrc_netif2_t *netif, if (gnrc_netif2_is_rtr(netif)) { reply_flags |= NDP_NBR_ADV_FLAGS_R; } -#endif +#endif /* GNRC_IPV6_NIB_CONF_ROUTER */ #if GNRC_NETIF2_L2ADDR_MAXLEN > 0 if (ipv6_addr_is_multicast(dst)) { uint8_t l2addr[GNRC_NETIF2_L2ADDR_MAXLEN]; @@ -369,7 +752,7 @@ static void _send_delayed_nbr_adv(const gnrc_netif2_t *netif, } #else /* GNRC_NETIF2_L2ADDR_MAXLEN > 0 */ reply_flags |= NDP_NBR_ADV_FLAGS_O; -#endif +#endif /* GNRC_NETIF2_L2ADDR_MAXLEN > 0 */ /* discard const qualifier */ nbr_adv = gnrc_ndp2_nbr_adv_build(tgt, reply_flags, extra_opts); if (nbr_adv == NULL) { @@ -382,8 +765,7 @@ static void _send_delayed_nbr_adv(const gnrc_netif2_t *netif, /* usually this should be the case, but when NCE is full, just * ignore the sending. Other nodes in this anycast group are * then preferred */ - _evtimer_add(nce, GNRC_IPV6_NIB_SND_NA, - &nce->snd_na, + _evtimer_add(nce, GNRC_IPV6_NIB_SND_NA, &nce->snd_na, random_uint32_range(0, NDP_MAX_ANYCAST_MS_DELAY)); } } @@ -412,7 +794,7 @@ static void _handle_nbr_sol(gnrc_netif2_t *netif, const ipv6_hdr_t *ipv6, DEBUG(" - Source address: %s\n", ipv6_addr_to_str(addr_str, &ipv6->src, sizeof(addr_str))); DEBUG(" - Destination address: %s (should be of format " - "ff02::1:ffxx:xxxx if source address is ::)\n", + "ff02::1:ffxx:xxxx if source address is ::)\n", ipv6_addr_to_str(addr_str, &ipv6->dst, sizeof(addr_str))); return; } @@ -484,6 +866,7 @@ static void _handle_nbr_sol(gnrc_netif2_t *netif, const ipv6_hdr_t *ipv6, default: DEBUG("nib: Ignoring unrecognized option type %u for NS\n", opt->type); + break; } } reply_aro = _copy_and_handle_aro(netif, ipv6, nbr_sol, aro, sl2ao); @@ -554,12 +937,12 @@ static void _handle_nbr_adv(gnrc_netif2_t *netif, const ipv6_hdr_t *ipv6, (nbr_adv->flags & NDP_NBR_ADV_FLAGS_O) ? 'O' : '-'); #if GNRC_IPV6_NIB_CONF_SLAAC /* TODO SLAAC behavior */ -#endif +#endif /* GNRC_IPV6_NIB_CONF_SLAAC */ if (((nce = _nib_onl_get(&nbr_adv->tgt, netif->pid)) != NULL) && (nce->mode & _NC)) { #if GNRC_IPV6_NIB_CONF_ARSM bool tl2ao_avail = false; -#endif +#endif /* GNRC_IPV6_NIB_CONF_ARSM */ tmp_len = icmpv6_len - sizeof(ndp_nbr_adv_t); FOREACH_OPT(nbr_adv, opt, tmp_len) { @@ -569,13 +952,13 @@ static void _handle_nbr_adv(gnrc_netif2_t *netif, const ipv6_hdr_t *ipv6, _handle_adv_l2(netif, nce, (icmpv6_hdr_t *)nbr_adv, opt); tl2ao_avail = true; break; -#endif +#endif /* GNRC_IPV6_NIB_CONF_ARSM */ #if GNRC_IPV6_NIB_CONF_6LN case NDP_OPT_AR: _handle_aro(netif, ipv6, (const icmpv6_hdr_t *)nbr_adv, (const sixlowpan_nd_opt_ar_t *)opt, opt, nce); break; -#endif +#endif /* GNRC_IPV6_NIB_CONF_6LN */ default: DEBUG("nib: Ignoring unrecognized option type %u for NA\n", opt->type); @@ -590,7 +973,7 @@ static void _handle_nbr_adv(gnrc_netif2_t *netif, const ipv6_hdr_t *ipv6, if (!(netif->flags & GNRC_NETIF2_FLAGS_HAS_L2ADDR)) { _handle_adv_l2(netif, nce, (icmpv6_hdr_t *)nbr_adv, NULL); } -#endif +#endif /* GNRC_IPV6_NIB_CONF_ARSM */ } } @@ -606,7 +989,7 @@ static inline bool _is_reachable(_nib_onl_entry_t *entry) return true; } } -#endif +#endif /* GNRC_IPV6_NIB_CONF_ARSM */ #if GNRC_IPV6_NIB_CONF_QUEUE_PKT static gnrc_pktqueue_t *_alloc_queue_entry(gnrc_pktsnip_t *pkt) @@ -619,13 +1002,14 @@ static gnrc_pktqueue_t *_alloc_queue_entry(gnrc_pktsnip_t *pkt) } return NULL; } -#endif +#endif /* GNRC_IPV6_NIB_CONF_QUEUE_PKT */ 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) { bool res = false; + if ((netif != NULL) && (netif->device_type == NETDEV_TYPE_SLIP)) { /* XXX: Linux doesn't do neighbor discovery for SLIP so no use sending * NS and since SLIP doesn't have link-layer addresses anyway, we can @@ -648,7 +1032,7 @@ static bool _resolve_addr(const ipv6_addr_t *dst, gnrc_netif2_t *netif, _nib_nc_get(entry, nce); res = true; } -#else +#else /* GNRC_IPV6_NIB_CONF_ARSM */ if (entry != NULL) { DEBUG("nib: resolve address %s%%%u from neighbor cache\n", ipv6_addr_to_str(addr_str, &entry->ipv6, sizeof(addr_str)), @@ -656,11 +1040,11 @@ static bool _resolve_addr(const ipv6_addr_t *dst, gnrc_netif2_t *netif, _nib_nc_get(entry, nce); res = true; } -#endif +#endif /* GNRC_IPV6_NIB_CONF_ARSM */ else if (!(res = _resolve_addr_from_ipv6(dst, netif, nce))) { #if GNRC_IPV6_NIB_CONF_ARSM bool reset = false; -#endif +#endif /* GNRC_IPV6_NIB_CONF_ARSM */ DEBUG("nib: resolve address %s by probing neighbors\n", ipv6_addr_to_str(addr_str, dst, sizeof(addr_str))); @@ -671,14 +1055,16 @@ static bool _resolve_addr(const ipv6_addr_t *dst, gnrc_netif2_t *netif, 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); + if (netif != NULL) { + _call_route_info_cb(netif, + GNRC_IPV6_NIB_ROUTE_INFO_TYPE_NSC, + dst, + (void *)GNRC_IPV6_NIB_NC_INFO_NUD_STATE_INCOMPLETE); } -#endif +#endif /* GNRC_IPV6_NIB_CONF_ROUTER */ #if GNRC_IPV6_NIB_CONF_ARSM reset = true; -#endif +#endif /* GNRC_IPV6_NIB_CONF_ARSM */ } if (pkt != NULL) { #if GNRC_IPV6_NIB_CONF_QUEUE_PKT @@ -698,7 +1084,7 @@ static bool _resolve_addr(const ipv6_addr_t *dst, gnrc_netif2_t *netif, } #if GNRC_IPV6_NIB_CONF_ARSM _probe_nbr(entry, reset); -#endif +#endif /* GNRC_IPV6_NIB_CONF_ARSM */ } return res; } @@ -712,10 +1098,257 @@ static void _handle_snd_na(gnrc_pktsnip_t *pkt) DEBUG("nib: No receivers for neighbor advertisement\n"); gnrc_pktbuf_release_error(pkt, EBADF); } -#else +#else /* MODULE_GNRC_IPV6 */ (void)pkt; DEBUG("nib: No IPv6 module to send delayed neighbor advertisement\n"); -#endif +#endif /* MODULE_GNRC_IPV6 */ +} + +static void _handle_pfx_timeout(_nib_offl_entry_t *pfx) +{ + gnrc_netif2_t *netif = gnrc_netif2_get_by_pid(_nib_onl_get_if(pfx->next_hop)); + uint32_t now = (xtimer_now_usec64() / US_PER_MS) & UINT32_MAX; + + gnrc_netif2_acquire(netif); + if (now >= pfx->valid_until) { + evtimer_del(&_nib_evtimer, &pfx->pfx_timeout.event); + for (int i = 0; i < GNRC_NETIF2_IPV6_ADDRS_NUMOF; i++) { + if (ipv6_addr_match_prefix(&netif->ipv6.addrs[i], + &pfx->pfx) >= pfx->pfx_len) { + gnrc_netif2_ipv6_addr_remove(netif, &netif->ipv6.addrs[i]); + } + } + pfx->mode &= ~_PL; + _nib_offl_clear(pfx); + } + else if (now >= pfx->pref_until) { + for (int i = 0; i < GNRC_NETIF2_IPV6_ADDRS_NUMOF; i++) { + if (ipv6_addr_match_prefix(&netif->ipv6.addrs[i], + &pfx->pfx) >= pfx->pfx_len) { + netif->ipv6.addrs_flags[i] &= ~GNRC_NETIF2_IPV6_ADDRS_FLAGS_STATE_MASK; + netif->ipv6.addrs_flags[i] |= GNRC_NETIF2_IPV6_ADDRS_FLAGS_STATE_DEPRECATED; + } + } + _evtimer_add(pfx, GNRC_IPV6_NIB_PFX_TIMEOUT, &pfx->pfx_timeout, + pfx->valid_until - now); + } + gnrc_netif2_release(netif); +} + +static void _handle_rtr_timeout(_nib_dr_entry_t *router) +{ + if ((router->next_hop != NULL) && (router->next_hop->mode & _DRL)) { + _nib_offl_entry_t *route = NULL; + unsigned iface = _nib_onl_get_if(router->next_hop); + ipv6_addr_t addr; + + memcpy(&addr, &router->next_hop, sizeof(addr)); + _nib_drl_remove(router); + /* also remove all routes to that router */ + while ((route = _nib_offl_iter(route))) { + if ((route->next_hop != NULL) && + (_nib_onl_get_if(route->next_hop) == iface) && + (ipv6_addr_equal(&route->next_hop->ipv6, &addr))) { + route->mode = _EMPTY; + route->next_hop->mode &= ~_DST; + _nib_offl_clear(route); + /* XXX routing protocol get's informed in case NUD + * determines ipv6->src (still in neighbor cache) to be + * unreachable */ + } + } + } +} + +void _handle_search_rtr(gnrc_netif2_t *netif) +{ + gnrc_netif2_acquire(netif); + if (!(gnrc_netif2_is_rtr_adv(netif)) || gnrc_netif2_is_6ln(netif)) { + uint32_t next_rs = _evtimer_lookup(netif, GNRC_IPV6_NIB_SEARCH_RTR); + uint32_t interval = _get_next_rs_interval(netif); + + if (next_rs > interval) { + gnrc_ndp2_rtr_sol_send(netif, &ipv6_addr_all_routers_link_local); + if (netif->ipv6.rs_sent < 10U) { + /* with more the backoff (required in RFC 6775) is truncated + * anyway and this way we prevent overflows. 10 is arbitrary, so + * we do not need a define here */ + netif->ipv6.rs_sent++; + } + if ((netif->ipv6.rs_sent < NDP_MAX_RS_NUMOF) || + gnrc_netif2_is_6ln(netif)) { + /* 6LN will solicitate indefinitely */ + _evtimer_add(netif, GNRC_IPV6_NIB_SEARCH_RTR, + &netif->ipv6.search_rtr, interval); + } + } + } + gnrc_netif2_release(netif); +} + +static void _handle_mtuo(gnrc_netif2_t *netif, const icmpv6_hdr_t *icmpv6, + const ndp_opt_mtu_t *mtuo) +{ + if ((mtuo->len != NDP_OPT_MTU_LEN) || (icmpv6->type != ICMPV6_RTR_ADV)) { + return; + } + if (byteorder_ntohl(mtuo->mtu) >= IPV6_MIN_MTU) { + netif->ipv6.mtu = byteorder_ntohl(mtuo->mtu); + } +} + +static void _remove_prefix(const ipv6_addr_t *pfx, unsigned pfx_len) +{ + _nib_offl_entry_t *offl = NULL; + + while ((offl = _nib_offl_iter(offl))) { + if ((offl->mode & _PL) && + (offl->pfx_len == pfx_len) && + (ipv6_addr_match_prefix(&offl->pfx, pfx) >= pfx_len)) { + _nib_pl_remove(offl); + } + } + return; +} + +#if GNRC_IPV6_NIB_CONF_MULTIHOP_P6C +static uint32_t _handle_pio(gnrc_netif2_t *netif, const icmpv6_hdr_t *icmpv6, + const ndp_opt_pi_t *pio, _nib_abr_entry_t *abr) +#else /* GNRC_IPV6_NIB_CONF_MULTIHOP_P6C */ +static uint32_t _handle_pio(gnrc_netif2_t *netif, const icmpv6_hdr_t *icmpv6, + const ndp_opt_pi_t *pio) +#endif /* GNRC_IPV6_NIB_CONF_MULTIHOP_P6C */ +{ + uint32_t valid_ltime; + uint32_t pref_ltime; + + valid_ltime = byteorder_ntohl(pio->valid_ltime); + pref_ltime = byteorder_ntohl(pio->pref_ltime); + if ((pio->len != NDP_OPT_PI_LEN) || (icmpv6->type != ICMPV6_RTR_ADV) || + ipv6_addr_is_link_local(&pio->prefix) || (valid_ltime < pref_ltime)) { + DEBUG("nib: ignoring PIO with invalid data\n"); + return UINT32_MAX; + } + DEBUG("nib: received valid Prefix Information option:\n"); + DEBUG(" - Prefix: %s/%u\n", + ipv6_addr_to_str(addr_str, &pio->prefix, sizeof(addr_str)), + pio->prefix_len); + DEBUG(" - Flags: %c%c\n", + (pio->flags & NDP_OPT_PI_FLAGS_L) ? 'L' : '-', + (pio->flags & NDP_OPT_PI_FLAGS_A) ? 'A' : '-'); + DEBUG(" - Valid lifetime: %" PRIu32 "\n", + byteorder_ntohl(pio->valid_ltime)); + DEBUG(" - Preferred lifetime: %" PRIu32 "\n", + byteorder_ntohl(pio->pref_ltime)); + +#if GNRC_IPV6_NIB_CONF_SLAAC || GNRC_IPV6_NIB_CONF_6LN + if (pio->flags & NDP_OPT_PI_FLAGS_A) { + _auto_configure_addr(netif, &pio->prefix, pio->prefix_len); + } +#endif /* GNRC_IPV6_NIB_CONF_SLAAC || GNRC_IPV6_NIB_CONF_6LN */ + if ((pio->flags & NDP_OPT_PI_FLAGS_L) || gnrc_netif2_is_6lr(netif)) { + _nib_offl_entry_t *pfx; + + if (pio->valid_ltime.u32 == 0) { + DEBUG("nib: PIO for %s/%u with lifetime 0. Removing prefix.\n", + ipv6_addr_to_str(addr_str, &pio->prefix, sizeof(addr_str)), + pio->prefix_len); + _remove_prefix(&pio->prefix, pio->prefix_len); + return UINT32_MAX; + } + + if (valid_ltime < UINT32_MAX) { /* UINT32_MAX means infinite lifetime */ + /* the valid lifetime is given in seconds, but our timers work in + * microseconds, so we have to scale down to the smallest possible + * value (UINT32_MAX). This is however alright since we ask for a + * new router advertisement before this timeout expires */ + valid_ltime = (valid_ltime > (UINT32_MAX / MS_PER_SEC)) ? + UINT32_MAX : valid_ltime * MS_PER_SEC; + } + if (pref_ltime < UINT32_MAX) { /* UINT32_MAX means infinite lifetime */ + /* same treatment for pref_ltime */ + pref_ltime = (pref_ltime > (UINT32_MAX / MS_PER_SEC)) ? + UINT32_MAX : pref_ltime * MS_PER_SEC; + } + if ((pfx = _nib_pl_add(netif->pid, &pio->prefix, pio->prefix_len, + valid_ltime, pref_ltime))) { +#if GNRC_IPV6_NIB_CONF_MULTIHOP_P6C + assert(abr != NULL); /* should have been set in _handle_abro() */ + _nib_abr_add_pfx(abr, pfx); +#endif /* GNRC_IPV6_NIB_CONF_MULTIHOP_P6C */ + if (pio->flags & NDP_OPT_PI_FLAGS_L) { + pfx->flags |= _PFX_ON_LINK; + } + if (pio->flags & NDP_OPT_PI_FLAGS_A) { + pfx->flags |= _PFX_SLAAC; + } + return _min(pref_ltime, valid_ltime); + } + } + return UINT32_MAX; +} + +#if GNRC_IPV6_NIB_CONF_6LN || GNRC_IPV6_NIB_CONF_SLAAC +static void _auto_configure_addr(gnrc_netif2_t *netif, const ipv6_addr_t *pfx, + uint8_t pfx_len) +{ + ipv6_addr_t addr = IPV6_ADDR_UNSPECIFIED; + int idx; + uint8_t flags = GNRC_NETIF2_IPV6_ADDRS_FLAGS_STATE_TENTATIVE; + + DEBUG("nib: add address based on %s/%u automatically to interface %u\n", + ipv6_addr_to_str(addr_str, pfx, sizeof(addr_str)), + pfx_len, netif->pid); +#if GNRC_IPV6_NIB_CONF_6LN + bool new_address = false; +#endif /* GNRC_IPV6_NIB_CONF_6LN */ + gnrc_netif2_ipv6_get_iid(netif, (eui64_t *)&addr.u64[1]); + ipv6_addr_init_prefix(&addr, pfx, pfx_len); + if ((idx = gnrc_netif2_ipv6_addr_idx(netif, &addr)) < 0) { + if ((idx = gnrc_netif2_ipv6_addr_add(netif, &addr, pfx_len, flags)) < 0) { + DEBUG("nib: Can't add link-local address on interface %u\n", + netif->pid); + return; + } +#if GNRC_IPV6_NIB_CONF_6LN + new_address = true; +#endif /* GNRC_IPV6_NIB_CONF_6LN */ + } + +#if GNRC_IPV6_NIB_CONF_6LN + if (gnrc_netif2_is_6ln(netif)) { + /* don't do this beforehand or risk a deadlock: + * * gnrc_netif2_ipv6_addr_add() adds VALID (i.e. manually configured + * addresses to the prefix list locking the NIB's mutex which is already + * locked here) */ + netif->ipv6.addrs_flags[idx] &= ~GNRC_NETIF2_IPV6_ADDRS_FLAGS_STATE_MASK; + netif->ipv6.addrs_flags[idx] |= GNRC_NETIF2_IPV6_ADDRS_FLAGS_STATE_VALID; + } +#endif /* GNRC_IPV6_NIB_CONF_6LN */ + (void)idx; + /* TODO: make this line conditional on 6LN when there is a SLAAC + * implementation */ +#if GNRC_IPV6_NIB_CONF_ARSM + /* TODO: SHOULD delay join between 0 and MAX_RTR_SOLICITATION_DELAY + * for SLAAC */ + ipv6_addr_set_solicited_nodes(&addr, &addr); + if (gnrc_netif2_ipv6_group_join(netif, &addr) < 0) { + DEBUG("nib: Can't join solicited-nodes of link-local address on " + "interface %u\n", netif->pid); + return; + } +#endif /* GNRC_IPV6_NIB_CONF_ARSM */ +#if GNRC_IPV6_NIB_CONF_6LN + if (new_address && gnrc_netif2_is_6ln(netif) && + !gnrc_netif2_is_6lbr(netif)) { + _handle_rereg_address(&netif->ipv6.addrs[idx]); + } +#endif /* GNRC_IPV6_NIB_CONF_6LN */ +#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 /* GNRC_IPV6_NIB_CONF_SLAAC */ } +#endif /* GNRC_IPV6_NIB_CONF_6LN || GNRC_IPV6_NIB_CONF_SLAAC */ /** @} */ diff --git a/sys/net/gnrc/network_layer/ipv6/nib/nib_pl.c b/sys/net/gnrc/network_layer/ipv6/nib/nib_pl.c index 125582a2a7164f040fdf58c8384ad36214ef19fb..49abce66a5d633dcc872ac7e565e64ebf509b806 100644 --- a/sys/net/gnrc/network_layer/ipv6/nib/nib_pl.c +++ b/sys/net/gnrc/network_layer/ipv6/nib/nib_pl.c @@ -18,10 +18,12 @@ #include <stdio.h> #include "net/gnrc/ipv6/nib/pl.h" +#include "net/gnrc/netif2/internal.h" #include "timex.h" #include "xtimer.h" #include "_nib-internal.h" +#include "_nib-router.h" int gnrc_ipv6_nib_pl_set(unsigned iface, const ipv6_addr_t *pfx, unsigned pfx_len, @@ -47,8 +49,40 @@ int gnrc_ipv6_nib_pl_set(unsigned iface, if (dst == NULL) { res = -ENOMEM; } +#ifdef MODULE_GNRC_NETIF2 + gnrc_netif2_t *netif = gnrc_netif2_get_by_pid(iface); + int idx; + + if (netif == NULL) { + mutex_unlock(&_nib_mutex); + return res; + } + gnrc_netif2_acquire(netif); + if (!gnrc_netif2_is_6ln(netif) && + ((idx = gnrc_netif2_ipv6_addr_match(netif, pfx)) >= 0) && + (ipv6_addr_match_prefix(&netif->ipv6.addrs[idx], pfx) >= pfx_len)) { + dst->flags |= _PFX_ON_LINK; + } + if (netif->ipv6.aac_mode == GNRC_NETIF2_AAC_AUTO) { + dst->flags |= _PFX_SLAAC; + } +#if GNRC_IPV6_NIB_CONF_6LBR && GNRC_IPV6_NIB_CONF_MULTIHOP_P6C + if (gnrc_netif2_is_6lbr(netif)) { + _nib_abr_entry_t *abr = NULL; + + while ((abr = _nib_abr_iter(abr))) { + abr->version++; + _nib_abr_add_pfx(abr, dst); + } + } +#endif + gnrc_netif2_release(netif); +#endif /* MODULE_GNRC_NETIF2 */ mutex_unlock(&_nib_mutex); - /* TODO: send RA with PIO, if iface is allowed to send RAs */ +#if defined(MODULE_GNRC_NETIF2) && GNRC_IPV6_NIB_CONF_ROUTER + /* update prefixes down-stream */ + _handle_snd_mc_ra(netif); +#endif return res; } @@ -66,7 +100,14 @@ void gnrc_ipv6_nib_pl_del(unsigned iface, (ipv6_addr_match_prefix(pfx, &dst->pfx) >= pfx_len)) { _nib_pl_remove(dst); mutex_unlock(&_nib_mutex); - /* TODO: send RA with PIO, if iface is allowed to send RAs */ +#if GNRC_IPV6_NIB_CONF_ROUTER + gnrc_netif2_t *netif = gnrc_netif2_get_by_pid(iface); + + if (netif) { + /* update prefixes down-stream */ + _handle_snd_mc_ra(netif); + } +#endif return; } } diff --git a/sys/net/gnrc/network_layer/sixlowpan/nd/gnrc_sixlowpan_nd.c b/sys/net/gnrc/network_layer/sixlowpan/nd/gnrc_sixlowpan_nd.c index 42f60163f1238f99843a7d15a9f61ae0db9bc7c7..7b3526051afbc7abd8f81ab1aaf0ee6fb4821e49 100644 --- a/sys/net/gnrc/network_layer/sixlowpan/nd/gnrc_sixlowpan_nd.c +++ b/sys/net/gnrc/network_layer/sixlowpan/nd/gnrc_sixlowpan_nd.c @@ -42,6 +42,42 @@ gnrc_pktsnip_t *gnrc_sixlowpan_nd_opt_ar_build(uint8_t status, uint16_t ltime, e return pkt; } -/* gnrc_sixlowpan_nd_opt_abr_handle etc. implemented in gnrc_sixlowpan_nd_router */ +gnrc_pktsnip_t *gnrc_sixlowpan_nd_opt_6ctx_build(uint8_t prefix_len, uint8_t flags, uint16_t ltime, + ipv6_addr_t *prefix, gnrc_pktsnip_t *next) +{ + gnrc_pktsnip_t *pkt = gnrc_ndp2_opt_build(NDP_OPT_6CTX, + sizeof(sixlowpan_nd_opt_6ctx_t) + (prefix_len / 8), + next); + + if (pkt != NULL) { + sixlowpan_nd_opt_6ctx_t *ctx_opt = pkt->data; + ctx_opt->ctx_len = prefix_len; + ctx_opt->resv_c_cid = flags; + ctx_opt->resv.u16 = 0; + ctx_opt->ltime = byteorder_htons(ltime); + /* Bits beyond prefix_len MUST be 0 */ + memset(ctx_opt + 1, 0, pkt->size - sizeof(sixlowpan_nd_opt_6ctx_t)); + ipv6_addr_init_prefix((ipv6_addr_t *)(ctx_opt + 1), prefix, prefix_len); + } + + return pkt; +} + +gnrc_pktsnip_t *gnrc_sixlowpan_nd_opt_abr_build(uint32_t version, uint16_t ltime, + ipv6_addr_t *braddr, gnrc_pktsnip_t *next) +{ + gnrc_pktsnip_t *pkt = gnrc_ndp2_opt_build(NDP_OPT_ABR, sizeof(sixlowpan_nd_opt_abr_t), next); + + if (pkt != NULL) { + sixlowpan_nd_opt_abr_t *abr_opt = pkt->data; + abr_opt->vlow = byteorder_htons(version & 0xffff); + abr_opt->vhigh = byteorder_htons(version >> 16); + abr_opt->ltime = byteorder_htons(ltime); + abr_opt->braddr.u64[0] = braddr->u64[0]; + abr_opt->braddr.u64[1] = braddr->u64[1]; + } + + return pkt; +} /** @} */ diff --git a/sys/net/gnrc/network_layer/sixlowpan/nd/router/gnrc_sixlowpan_nd_router.c b/sys/net/gnrc/network_layer/sixlowpan/nd/router/gnrc_sixlowpan_nd_router.c index 9c933ac7527373ffa44e2b64b1b30067eb21ad6e..2b5eb055d96076b20f0e5baed578d549a51d1de0 100644 --- a/sys/net/gnrc/network_layer/sixlowpan/nd/router/gnrc_sixlowpan_nd_router.c +++ b/sys/net/gnrc/network_layer/sixlowpan/nd/router/gnrc_sixlowpan_nd_router.c @@ -22,41 +22,4 @@ #include "net/gnrc/sixlowpan/nd/router.h" -gnrc_pktsnip_t *gnrc_sixlowpan_nd_opt_6ctx_build(uint8_t prefix_len, uint8_t flags, uint16_t ltime, - ipv6_addr_t *prefix, gnrc_pktsnip_t *next) -{ - gnrc_pktsnip_t *pkt = gnrc_ndp2_opt_build(NDP_OPT_6CTX, - sizeof(sixlowpan_nd_opt_6ctx_t) + (prefix_len / 8), - next); - - if (pkt != NULL) { - sixlowpan_nd_opt_6ctx_t *ctx_opt = pkt->data; - ctx_opt->ctx_len = prefix_len; - ctx_opt->resv_c_cid = flags; - ctx_opt->resv.u16 = 0; - ctx_opt->ltime = byteorder_htons(ltime); - /* Bits beyond prefix_len MUST be 0 */ - memset(ctx_opt + 1, 0, pkt->size - sizeof(sixlowpan_nd_opt_6ctx_t)); - ipv6_addr_init_prefix((ipv6_addr_t *)(ctx_opt + 1), prefix, prefix_len); - } - - return pkt; -} - -gnrc_pktsnip_t *gnrc_sixlowpan_nd_opt_abr_build(uint32_t version, uint16_t ltime, - ipv6_addr_t *braddr, gnrc_pktsnip_t *next) -{ - gnrc_pktsnip_t *pkt = gnrc_ndp2_opt_build(NDP_OPT_ABR, sizeof(sixlowpan_nd_opt_abr_t), next); - - if (pkt != NULL) { - sixlowpan_nd_opt_abr_t *abr_opt = pkt->data; - abr_opt->vlow = byteorder_htons(version & 0xffff); - abr_opt->vhigh = byteorder_htons(version >> 16); - abr_opt->ltime = byteorder_htons(ltime); - abr_opt->braddr.u64[0] = braddr->u64[0]; - abr_opt->braddr.u64[1] = braddr->u64[1]; - } - - return pkt; -} /** @} */ diff --git a/tests/driver_enc28j60/Makefile b/tests/driver_enc28j60/Makefile index df44329a4edc662478c1dd6da4f5d5c6433c030b..2628a8b292b38248a93fd38d23212d3e3ee44fb2 100644 --- a/tests/driver_enc28j60/Makefile +++ b/tests/driver_enc28j60/Makefile @@ -5,7 +5,7 @@ FEATURES_REQUIRED = periph_spi periph_gpio BOARD_INSUFFICIENT_MEMORY := msb-430 msb-430h nucleo32-f031 nucleo32-f042 \ nucleo32-l031 nucleo-f334 nucleo-l053 \ - stm32f0discovery telosb z1 + stm32f0discovery telosb wsn430-v1_3b wsn430-v1_4 z1 USEMODULE += gnrc_netdev_default USEMODULE += auto_init_gnrc_netif diff --git a/tests/driver_encx24j600/Makefile b/tests/driver_encx24j600/Makefile index 8aa520540a61a052621cc5c33a3d5449dac5dc2c..b5ce8a03da06ead4b06766fc4367d2d524bb75aa 100644 --- a/tests/driver_encx24j600/Makefile +++ b/tests/driver_encx24j600/Makefile @@ -5,7 +5,7 @@ FEATURES_REQUIRED = periph_spi periph_gpio BOARD_INSUFFICIENT_MEMORY := msb-430 msb-430h nucleo32-f031 nucleo32-f042 \ nucleo32-l031 nucleo-l053 stm32f0discovery telosb \ - z1 + wsn430-v1_3b wsn430-v1_4 z1 USEMODULE += gnrc_netdev_default USEMODULE += auto_init_gnrc_netif diff --git a/tests/gnrc_ipv6_nib/Makefile b/tests/gnrc_ipv6_nib/Makefile index c11f93011d95c3f5a04a89b8147ee1362ce361ee..908369ad8d138f7ed8fc8fe8ef29dd777eb342af 100644 --- a/tests/gnrc_ipv6_nib/Makefile +++ b/tests/gnrc_ipv6_nib/Makefile @@ -2,7 +2,8 @@ APPLICATION = gnrc_ipv6_nib include ../Makefile.tests_common -BOARD_INSUFFICIENT_MEMORY := chronos nucleo32-f031 nucleo32-f042 nucleo32-l031 +BOARD_INSUFFICIENT_MEMORY := chronos nucleo32-f031 nucleo32-f042 nucleo32-l031 \ + telosb wsn430-v1_3b wsn430-v1_4 USEMODULE += gnrc_ipv6 USEMODULE += gnrc_ipv6_nib diff --git a/tests/gnrc_ipv6_nib/main.c b/tests/gnrc_ipv6_nib/main.c index 68e90aeb64ef762054ecdde3ec077e65acf0e757..a1ee3c8fc553b3cf827759b3aef24c76d686c155 100644 --- a/tests/gnrc_ipv6_nib/main.c +++ b/tests/gnrc_ipv6_nib/main.c @@ -29,16 +29,28 @@ #include "net/gnrc.h" #include "net/gnrc/ipv6/nib.h" #include "net/gnrc/ipv6/nib/nc.h" +#include "net/gnrc/netif2/internal.h" #include "net/ndp.h" #include "sched.h" #define _BUFFER_SIZE (128) +#define _CUR_HL (155) +#define _RTR_LTIME (6612U) +#define _REACH_TIME (1210388825UL) +#define _RETRANS_TIMER (3691140UL) +#define _LOC_GB_PFX_LEN (45U) +#define _REM_GB_PFX_LEN (37U) +#define _PIO_PFX_LTIME (0x8476fedf) static const uint8_t _loc_l2[] = { _LL0, _LL1, _LL2, _LL3, _LL4, _LL5 }; static const ipv6_addr_t _loc_ll = { { 0xfe, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, _LL0 ^ 2, _LL1, _LL2, 0xff, 0xfe, _LL3, _LL4, _LL5 } }; +static const ipv6_addr_t _loc_gb = { { + 0x20, 0x01, 0x2b, 0x2e, 0x43, 0x80, 0x00, 0x00, + _LL0 ^ 2, _LL1, _LL2, 0xff, 0xfe, _LL3, _LL4, _LL5 + } }; static const ipv6_addr_t _loc_sol_nodes = { { 0xff, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0xff, _LL3, _LL4, _LL5 @@ -49,6 +61,10 @@ static const ipv6_addr_t _rem_ll = { { 0xfe, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, _LL0 ^ 2, _LL1, _LL2, 0xff, 0xfe, _LL3, _LL4, _LL5 + 1 } }; +static const ipv6_addr_t _rem_gb = { { + 0x20, 0x01, 0x18, 0xc9, 0xf8, 0x00, 0x00, 0x00, + _LL0 ^ 2, _LL1, _LL2, 0xff, 0xfe, _LL3, _LL4, _LL5 + 1 + } }; #define _rem_iid _rem_ll.u64[1].u8 static uint8_t _buffer[_BUFFER_SIZE]; static ipv6_hdr_t *ipv6 = (ipv6_hdr_t *)&_buffer[0]; @@ -59,6 +75,12 @@ static inline size_t ceil8(size_t size); static void _set_up(void) { _common_set_up(); + gnrc_netif2_acquire(_mock_netif); + /* reset some fields not set by the nib interface initializer */ + _mock_netif->ipv6.mtu = ETHERNET_DATA_LEN; + _mock_netif->cur_hl = GNRC_NETIF2_DEFAULT_HL; + gnrc_netif2_ipv6_addr_remove(_mock_netif, &_loc_gb); + gnrc_netif2_release(_mock_netif); memset(_buffer, 0, sizeof(_buffer)); gnrc_pktbuf_init(); /* remove messages */ @@ -68,24 +90,42 @@ static void _set_up(void) } } -static void test_get_next_hop_l2addr__link_local_EHOSTUNREACH(gnrc_netif2_t *netif) +static void test_get_next_hop_l2addr__EHOSTUNREACH(const ipv6_addr_t *dst, + gnrc_netif2_t *netif, + bool on_link) { + ipv6_addr_t addr; msg_t msg; gnrc_ipv6_nib_nc_t nce; void *state = NULL; gnrc_pktsnip_t *pkt; + memcpy(&addr, &_rem_gb, sizeof(addr)); + addr.u8[15]--; + if (ipv6_addr_is_link_local(dst)) { + on_link = true; + } + else if (on_link) { + /* add _rem_gb prefix as on-link prefix */ + TEST_ASSERT(gnrc_netif2_ipv6_addr_add(_mock_netif, &addr, + _REM_GB_PFX_LEN, + GNRC_NETIF2_IPV6_ADDRS_FLAGS_STATE_VALID) >= 0); + } + else { + TEST_ASSERT_EQUAL_INT(0, gnrc_ipv6_nib_ft_add(NULL, 0, &_rem_ll, + _mock_netif->pid)); + } TEST_ASSERT_EQUAL_INT(-EHOSTUNREACH, - gnrc_ipv6_nib_get_next_hop_l2addr(&_rem_ll, netif, + gnrc_ipv6_nib_get_next_hop_l2addr(dst, netif, NULL, &nce)); - if (netif != NULL) { + if (on_link && (netif != NULL)) { ndp_nbr_sol_t *nbr_sol; bool contains_sl2ao = false; TEST_ASSERT_MESSAGE(gnrc_ipv6_nib_nc_iter(0, &state, &nce), "Expected neighbor cache entry"); - TEST_ASSERT_MESSAGE(ipv6_addr_equal(&_rem_ll, &nce.ipv6), - "_rem_ll != nce->ipv6"); + TEST_ASSERT_MESSAGE(ipv6_addr_equal(dst, &nce.ipv6), + "dst != nce->ipv6"); TEST_ASSERT_EQUAL_INT(0, nce.l2addr_len); TEST_ASSERT_EQUAL_INT(GNRC_IPV6_NIB_NC_INFO_NUD_STATE_INCOMPLETE, gnrc_ipv6_nib_nc_get_nud_state(&nce)); @@ -118,16 +158,46 @@ static void test_get_next_hop_l2addr__link_local_EHOSTUNREACH(gnrc_netif2_t *net gnrc_pktbuf_release(pkt); TEST_ASSERT(gnrc_pktbuf_is_empty()); } + gnrc_netif2_ipv6_addr_remove(_mock_netif, &addr); } static void test_get_next_hop_l2addr__link_local_EHOSTUNREACH_no_iface(void) { - test_get_next_hop_l2addr__link_local_EHOSTUNREACH(NULL); + test_get_next_hop_l2addr__EHOSTUNREACH(&_rem_ll, NULL, false); } static void test_get_next_hop_l2addr__link_local_EHOSTUNREACH_iface(void) { - test_get_next_hop_l2addr__link_local_EHOSTUNREACH(_mock_netif); + test_get_next_hop_l2addr__EHOSTUNREACH(&_rem_ll, _mock_netif, false); +} + +static void test_get_next_hop_l2addr__global_EHOSTUNREACH_no_iface_off_link(void) +{ + test_get_next_hop_l2addr__EHOSTUNREACH(&_rem_gb, NULL, false); +} + +static void test_get_next_hop_l2addr__global_EHOSTUNREACH_iface_off_link(void) +{ + test_get_next_hop_l2addr__EHOSTUNREACH(&_rem_gb, _mock_netif, false); +} + +static void test_get_next_hop_l2addr__global_EHOSTUNREACH_no_iface_on_link(void) +{ + test_get_next_hop_l2addr__EHOSTUNREACH(&_rem_gb, NULL, true); +} + +static void test_get_next_hop_l2addr__global_EHOSTUNREACH_iface_on_link(void) +{ + test_get_next_hop_l2addr__EHOSTUNREACH(&_rem_gb, _mock_netif, true); +} + +static void test_get_next_hop_l2addr__ENETUNREACH(void) +{ + gnrc_ipv6_nib_nc_t nce; + + TEST_ASSERT_EQUAL_INT(-ENETUNREACH, + gnrc_ipv6_nib_get_next_hop_l2addr(&_rem_gb, NULL, + NULL, &nce)); } static void test_get_next_hop_l2addr__link_local_static_conf(void) @@ -682,6 +752,470 @@ static void test_handle_pkt__nbr_adv__unsolicited(void) TEST_ASSERT_EQUAL_INT(0, msg_avail()); } +static size_t _set_rtr_sol(const ipv6_addr_t *ipv6_src, + const ipv6_addr_t *ipv6_dst, + uint8_t ipv6_hl, uint8_t rtr_sol_code, + const uint8_t *sl2ao_addr, size_t sl2ao_addr_len) +{ + size_t icmpv6_len = sizeof(ndp_rtr_sol_t); + ndp_rtr_sol_t *rtr_sol = (ndp_rtr_sol_t *)icmpv6; + + ipv6_hdr_set_version(ipv6); + ipv6->hl = ipv6_hl; + memcpy(&ipv6->src, ipv6_src, sizeof(ipv6->src)); + memcpy(&ipv6->dst, ipv6_dst, sizeof(ipv6->dst)); + rtr_sol->type = ICMPV6_RTR_SOL; + rtr_sol->code = rtr_sol_code; + + if ((sl2ao_addr != NULL) && (sl2ao_addr_len > 0)) { + ndp_opt_t *sl2ao = (ndp_opt_t *)&_buffer[sizeof(ipv6_hdr_t) + + sizeof(ndp_rtr_sol_t)]; + + sl2ao->type = NDP_OPT_SL2A; + sl2ao->len = ceil8(sizeof(ndp_opt_t) + sl2ao_addr_len) / 8; + memcpy(sl2ao + 1, sl2ao_addr, sl2ao_addr_len); + icmpv6_len += ceil8(sizeof(ndp_opt_t) + sl2ao_addr_len); + } + + return icmpv6_len; +} + +static void test_handle_pkt__rtr_sol(void) +{ + gnrc_ipv6_nib_nc_t nce; + void *state = NULL; + size_t icmpv6_len = _set_rtr_sol(&_rem_ll, &_loc_ll, + 255U, 0U, _rem_l2, sizeof(_rem_l2)); + + gnrc_ipv6_nib_handle_pkt(_mock_netif, ipv6, icmpv6, icmpv6_len); + TEST_ASSERT_MESSAGE(!gnrc_ipv6_nib_nc_iter(0, &state, &nce), + "There is an unexpected neighbor cache entry"); + TEST_ASSERT_EQUAL_INT(0, msg_avail()); +} + +static size_t _set_rtr_adv(const ipv6_addr_t *ipv6_src, + uint8_t ipv6_hl, uint8_t rtr_adv_code, + bool set_rtr_adv_fields, + uint8_t rtr_adv_flags, + const uint8_t *sl2ao_addr, size_t sl2ao_addr_len, + uint16_t mtu, + const ipv6_addr_t *pfx, unsigned pfx_len, + uint8_t pfx_flags) +{ + size_t icmpv6_len = sizeof(ndp_rtr_adv_t); + ndp_rtr_adv_t *rtr_adv = (ndp_rtr_adv_t *)icmpv6; + + ipv6_hdr_set_version(ipv6); + ipv6->hl = ipv6_hl; + memcpy(&ipv6->src, ipv6_src, sizeof(ipv6->src)); + memcpy(&ipv6->dst, &_loc_ll, sizeof(ipv6->dst)); + rtr_adv->type = ICMPV6_RTR_ADV; + rtr_adv->code = rtr_adv_code; + rtr_adv->flags = rtr_adv_flags; + if (set_rtr_adv_fields) { + rtr_adv->cur_hl = _CUR_HL, + rtr_adv->ltime = byteorder_htons(_RTR_LTIME); + rtr_adv->reach_time = byteorder_htonl(_REACH_TIME); + rtr_adv->retrans_timer = byteorder_htonl(_RETRANS_TIMER); + } + + if (mtu > 0) { + ndp_opt_mtu_t *mtuo = (ndp_opt_mtu_t *)&_buffer[sizeof(ipv6_hdr_t) + + icmpv6_len]; + + mtuo->type = NDP_OPT_MTU; + mtuo->len = NDP_OPT_MTU_LEN; + mtuo->mtu = byteorder_htonl(mtu); + icmpv6_len += sizeof(ndp_opt_mtu_t); + } + if ((pfx != NULL) && (pfx_len > 0)) { + ndp_opt_pi_t *pio = (ndp_opt_pi_t *)&_buffer[sizeof(ipv6_hdr_t) + + icmpv6_len]; + + pio->type = NDP_OPT_PI; + pio->len = NDP_OPT_PI_LEN; + pio->prefix_len = pfx_len; + pio->flags = pfx_flags; + pio->valid_ltime = byteorder_htonl(_PIO_PFX_LTIME); + pio->pref_ltime = byteorder_htonl(_PIO_PFX_LTIME); + ipv6_addr_init_prefix(&pio->prefix, pfx, pfx_len); + icmpv6_len += sizeof(ndp_opt_pi_t); + } + if ((sl2ao_addr != NULL) && (sl2ao_addr_len > 0)) { + ndp_opt_t *sl2ao = (ndp_opt_t *)&_buffer[sizeof(ipv6_hdr_t) + + icmpv6_len]; + + sl2ao->type = NDP_OPT_SL2A; + sl2ao->len = ceil8(sizeof(ndp_opt_t) + sl2ao_addr_len) / 8; + memcpy(sl2ao + 1, sl2ao_addr, sl2ao_addr_len); + icmpv6_len += ceil8(sizeof(ndp_opt_t) + sl2ao_addr_len); + } + + return icmpv6_len; +} + +typedef struct { + uint32_t reach_time_base; + uint32_t reach_time; + uint32_t retrans_timer; + uint16_t mtu; + uint8_t addr_count; + uint8_t cur_hl; +} _netif_exp_t; + +static uint8_t _netif_addr_count(const gnrc_netif2_t *netif) +{ + unsigned count = 0U; + + for (int i = 0; i < GNRC_NETIF2_IPV6_ADDRS_NUMOF; i++) { + if (netif->ipv6.addrs_flags[i] != 0) { + count++; + } + } + return count; +} + +static inline void _get_netif_exp(const gnrc_netif2_t *netif, + _netif_exp_t *exp) +{ + exp->reach_time_base = netif->ipv6.reach_time_base; + exp->reach_time = netif->ipv6.reach_time; + exp->retrans_timer = netif->ipv6.retrans_time; + exp->mtu = netif->ipv6.mtu; + exp->addr_count = _netif_addr_count(netif); + exp->cur_hl = netif->cur_hl; +} + +#define TEST_ASSERT_NETIF_UNCHANGED(netif, exp) \ + TEST_ASSERT_EQUAL_INT(exp.reach_time_base, \ + netif->ipv6.reach_time_base); \ + TEST_ASSERT_EQUAL_INT(exp.reach_time, netif->ipv6.reach_time); \ + TEST_ASSERT_EQUAL_INT(exp.retrans_timer, netif->ipv6.retrans_time); \ + TEST_ASSERT_EQUAL_INT(exp.mtu, netif->ipv6.mtu); \ + TEST_ASSERT_EQUAL_INT(exp.addr_count, _netif_addr_count(netif)); \ + TEST_ASSERT_EQUAL_INT(exp.cur_hl, netif->cur_hl) + +static void test_handle_pkt__rtr_adv__invalid_src(void) +{ + gnrc_ipv6_nib_nc_t nce; + gnrc_ipv6_nib_ft_t route; + void *state = NULL; + size_t icmpv6_len = _set_rtr_adv(&_rem_gb, + 255U, 0U, true, 0U, + _loc_l2, sizeof(_loc_l2), + 32397U, &_loc_gb, _LOC_GB_PFX_LEN, + NDP_OPT_PI_FLAGS_L | NDP_OPT_PI_FLAGS_A); + _netif_exp_t exp_netif; + + _get_netif_exp(_mock_netif, &exp_netif); + gnrc_ipv6_nib_handle_pkt(_mock_netif, ipv6, icmpv6, icmpv6_len); + TEST_ASSERT_MESSAGE(!gnrc_ipv6_nib_nc_iter(0, &state, &nce), + "There is an unexpected neighbor cache entry"); + state = NULL; + TEST_ASSERT_MESSAGE(!gnrc_ipv6_nib_ft_iter(NULL, 0, &state, &route), + "There is an unexpected forwarding entry"); + TEST_ASSERT_NETIF_UNCHANGED(_mock_netif, exp_netif); + TEST_ASSERT_EQUAL_INT(0, msg_avail()); +} + +static void test_handle_pkt__rtr_adv__invalid_hl(void) +{ + gnrc_ipv6_nib_nc_t nce; + gnrc_ipv6_nib_ft_t route; + void *state = NULL; + size_t icmpv6_len = _set_rtr_adv(&_rem_ll, + 194U, 0U, true, 0U, + _loc_l2, sizeof(_loc_l2), + 32397U, &_loc_gb, _LOC_GB_PFX_LEN, + NDP_OPT_PI_FLAGS_L | NDP_OPT_PI_FLAGS_A); + _netif_exp_t exp_netif; + + _get_netif_exp(_mock_netif, &exp_netif); + gnrc_ipv6_nib_handle_pkt(_mock_netif, ipv6, icmpv6, icmpv6_len); + TEST_ASSERT_MESSAGE(!gnrc_ipv6_nib_nc_iter(0, &state, &nce), + "There is an unexpected neighbor cache entry"); + state = NULL; + TEST_ASSERT_MESSAGE(!gnrc_ipv6_nib_ft_iter(NULL, 0, &state, &route), + "There is an unexpected forwarding entry"); + TEST_ASSERT_NETIF_UNCHANGED(_mock_netif, exp_netif); + TEST_ASSERT_EQUAL_INT(0, msg_avail()); +} + +static void test_handle_pkt__rtr_adv__invalid_code(void) +{ + gnrc_ipv6_nib_nc_t nce; + gnrc_ipv6_nib_ft_t route; + void *state = NULL; + size_t icmpv6_len = _set_rtr_adv(&_rem_ll, + 255U, 201U, true, 0U, + _loc_l2, sizeof(_loc_l2), + 32397U, &_loc_gb, _LOC_GB_PFX_LEN, + NDP_OPT_PI_FLAGS_L | NDP_OPT_PI_FLAGS_A); + _netif_exp_t exp_netif; + + _get_netif_exp(_mock_netif, &exp_netif); + gnrc_ipv6_nib_handle_pkt(_mock_netif, ipv6, icmpv6, icmpv6_len); + TEST_ASSERT_MESSAGE(!gnrc_ipv6_nib_nc_iter(0, &state, &nce), + "There is an unexpected neighbor cache entry"); + state = NULL; + TEST_ASSERT_MESSAGE(!gnrc_ipv6_nib_ft_iter(NULL, 0, &state, &route), + "There is an unexpected forwarding entry"); + TEST_ASSERT_NETIF_UNCHANGED(_mock_netif, exp_netif); + TEST_ASSERT_EQUAL_INT(0, msg_avail()); +} + +static void test_handle_pkt__rtr_adv__invalid_icmpv6_len(void) +{ + gnrc_ipv6_nib_nc_t nce; + gnrc_ipv6_nib_ft_t route; + void *state = NULL; + _netif_exp_t exp_netif; + + _get_netif_exp(_mock_netif, &exp_netif); + _set_rtr_adv(&_rem_ll, 255U, 201U, true, 0U, _loc_l2, sizeof(_loc_l2), + 32397U, &_loc_gb, _LOC_GB_PFX_LEN, + NDP_OPT_PI_FLAGS_L | NDP_OPT_PI_FLAGS_A); + gnrc_ipv6_nib_handle_pkt(_mock_netif, ipv6, icmpv6, + sizeof(ndp_rtr_adv_t) - 1); + TEST_ASSERT_MESSAGE(!gnrc_ipv6_nib_nc_iter(0, &state, &nce), + "There is an unexpected neighbor cache entry"); + state = NULL; + TEST_ASSERT_MESSAGE(!gnrc_ipv6_nib_ft_iter(NULL, 0, &state, &route), + "There is an unexpected forwarding entry"); + TEST_ASSERT_NETIF_UNCHANGED(_mock_netif, exp_netif); + TEST_ASSERT_EQUAL_INT(0, msg_avail()); +} + +static void test_handle_pkt__rtr_adv__invalid_opt_len(void) +{ + gnrc_ipv6_nib_nc_t nce; + gnrc_ipv6_nib_ft_t route; + void *state = NULL; + size_t icmpv6_len = _set_rtr_adv(&_rem_ll, + 255U, 201U, true, 0U, + _loc_l2, sizeof(_loc_l2), + 32397U, &_loc_gb, _LOC_GB_PFX_LEN, + NDP_OPT_PI_FLAGS_L | NDP_OPT_PI_FLAGS_A); + ndp_opt_t *opt = (ndp_opt_t *)&_buffer[icmpv6_len]; + _netif_exp_t exp_netif; + + _get_netif_exp(_mock_netif, &exp_netif); + opt->type = NDP_OPT_SL2A; + opt->len = 0U; + icmpv6_len += sizeof(ndp_opt_t); + + gnrc_ipv6_nib_handle_pkt(_mock_netif, ipv6, icmpv6, icmpv6_len); + TEST_ASSERT_MESSAGE(!gnrc_ipv6_nib_nc_iter(0, &state, &nce), + "There is an unexpected neighbor cache entry"); + state = NULL; + TEST_ASSERT_MESSAGE(!gnrc_ipv6_nib_ft_iter(NULL, 0, &state, &route), + "There is an unexpected forwarding entry"); + TEST_ASSERT_NETIF_UNCHANGED(_mock_netif, exp_netif); + TEST_ASSERT_EQUAL_INT(0, msg_avail()); +} + +static void test_handle_pkt__rtr_adv__success(uint8_t rtr_adv_flags, + bool set_rtr_adv_fields, + bool sl2ao, bool mtuo, + bool pio, uint8_t pio_flags) +{ + gnrc_ipv6_nib_pl_t prefix; + gnrc_ipv6_nib_nc_t nce; + gnrc_ipv6_nib_ft_t route; + void *state = NULL; + size_t icmpv6_len = _set_rtr_adv(&_rem_ll, 255U, 0U, + set_rtr_adv_fields, rtr_adv_flags, + (sl2ao) ? _rem_l2 : NULL, sizeof(_rem_l2), + (mtuo) ? 32397U : 0U, + (pio) ? &_loc_gb : NULL, _LOC_GB_PFX_LEN, + pio_flags); + const unsigned exp_addr_count = _netif_addr_count(_mock_netif); + _netif_exp_t exp_netif; + + _get_netif_exp(_mock_netif, &exp_netif); + TEST_ASSERT(gnrc_netif2_ipv6_addr_idx(_mock_netif, &_loc_gb) < 0); + gnrc_ipv6_nib_handle_pkt(_mock_netif, ipv6, icmpv6, icmpv6_len); + if (set_rtr_adv_fields) { + while (gnrc_ipv6_nib_ft_iter(NULL, 0, &state, &route)) { + /* is default route */ + if (ipv6_addr_is_unspecified(&route.dst)) { + break; + } + } + TEST_ASSERT_MESSAGE(ipv6_addr_equal(&_rem_ll, &route.next_hop), + "default route is not via RA's source"); + TEST_ASSERT_EQUAL_INT(_mock_netif->pid, route.iface); + TEST_ASSERT_EQUAL_INT(_REACH_TIME, _mock_netif->ipv6.reach_time_base); + TEST_ASSERT_MESSAGE(((_REACH_TIME / 2) <= _mock_netif->ipv6.reach_time) && + (_mock_netif->ipv6.reach_time <= + (_REACH_TIME + (_REACH_TIME / 2))), + "Randomized reachable time was out of expected range."); + TEST_ASSERT_EQUAL_INT(_RETRANS_TIMER, _mock_netif->ipv6.retrans_time); + TEST_ASSERT_EQUAL_INT(_CUR_HL, _mock_netif->cur_hl); + } + else { + while (gnrc_ipv6_nib_ft_iter(NULL, 0, &state, &route)) { + TEST_ASSERT_MESSAGE(!ipv6_addr_is_unspecified(&route.dst), + "There is a default route, " + "though RA's router lifetime was 0."); + } + TEST_ASSERT_EQUAL_INT(exp_netif.reach_time_base, + _mock_netif->ipv6.reach_time_base); + TEST_ASSERT_EQUAL_INT(exp_netif.reach_time, + _mock_netif->ipv6.reach_time); + TEST_ASSERT_EQUAL_INT(exp_netif.retrans_timer, + _mock_netif->ipv6.retrans_time); + TEST_ASSERT_EQUAL_INT(exp_netif.cur_hl, + _mock_netif->cur_hl); + } + state = NULL; + if (sl2ao) { + TEST_ASSERT_MESSAGE(gnrc_ipv6_nib_nc_iter(0, &state, &nce), + "No neighbor cache entry found"); + TEST_ASSERT_MESSAGE((memcmp(&_rem_ll, &nce.ipv6, sizeof(_rem_ll)) == 0), + "_rem_ll != nce.ipv6"); + TEST_ASSERT_EQUAL_INT(sizeof(_rem_l2), nce.l2addr_len); + TEST_ASSERT_MESSAGE((memcmp(&_rem_l2, &nce.l2addr, nce.l2addr_len) == 0), + "_rem_l2 != nce.l2addr"); + TEST_ASSERT_EQUAL_INT(GNRC_IPV6_NIB_NC_INFO_NUD_STATE_STALE, + gnrc_ipv6_nib_nc_get_nud_state(&nce)); + TEST_ASSERT_EQUAL_INT(_mock_netif->pid, gnrc_ipv6_nib_nc_get_iface(&nce)); + TEST_ASSERT_EQUAL_INT(GNRC_IPV6_NIB_NC_INFO_AR_STATE_GC, + gnrc_ipv6_nib_nc_get_ar_state(&nce)); + } + else { + TEST_ASSERT_MESSAGE(!gnrc_ipv6_nib_nc_iter(0, &state, &nce), + "There is an unexpected neighbor cache entry"); + } + if (mtuo) { + TEST_ASSERT_EQUAL_INT(32397U, _mock_netif->ipv6.mtu); + } + else { + TEST_ASSERT_EQUAL_INT(exp_netif.mtu, _mock_netif->ipv6.mtu); + } + state = NULL; + if (pio) { + if (pio_flags & NDP_OPT_PI_FLAGS_A) { + TEST_ASSERT_MESSAGE(gnrc_netif2_ipv6_addr_idx(_mock_netif, + &_loc_gb) >= 0, + "Address was not configured by PIO"); + } + else { + TEST_ASSERT_MESSAGE(gnrc_netif2_ipv6_addr_idx(_mock_netif, + &_loc_gb) < 0, + "Address was configured by PIO, " + "but A flag was set"); + } + if (pio_flags & NDP_OPT_PI_FLAGS_L) { + TEST_ASSERT_MESSAGE(gnrc_ipv6_nib_pl_iter(0, &state, &prefix), + "No prefix list entry found"); + TEST_ASSERT_MESSAGE(ipv6_addr_match_prefix(&_loc_gb, + &prefix.pfx) >= _LOC_GB_PFX_LEN, + "Unexpected prefix configured"); + TEST_ASSERT_EQUAL_INT(_LOC_GB_PFX_LEN, prefix.pfx_len); + TEST_ASSERT_EQUAL_INT(_mock_netif->pid, prefix.iface); + TEST_ASSERT(_PIO_PFX_LTIME < prefix.valid_until); + TEST_ASSERT(_PIO_PFX_LTIME < prefix.pref_until); + } + } + if (!pio || !(pio_flags & NDP_OPT_PI_FLAGS_L)) { + if (!pio) { + TEST_ASSERT_EQUAL_INT(exp_addr_count, + _netif_addr_count(_mock_netif)); + } + TEST_ASSERT_MESSAGE(!gnrc_ipv6_nib_pl_iter(0, &state, &prefix), + "There is an unexpected prefix list entry"); + } + TEST_ASSERT_EQUAL_INT(0, msg_avail()); +} + +static void test_handle_pkt__rtr_adv__success_all_zero(void) +{ + test_handle_pkt__rtr_adv__success(0U, false, false, false, false, 0U); +} + +static void test_handle_pkt__rtr_adv__success_no_flags_no_opt(void) +{ + test_handle_pkt__rtr_adv__success(0U, true, false, false, false, 0U); +} + +static void test_handle_pkt__rtr_adv__success_no_opt(void) +{ + /* these flags only make sense with SLAAC, so don't further test them below + * (except for PIO ;-)) */ + test_handle_pkt__rtr_adv__success(NDP_RTR_ADV_FLAGS_M | NDP_RTR_ADV_FLAGS_O, + true, false, false, false, 0U); +} + +static void test_handle_pkt__rtr_adv__success_sl2ao(void) +{ + test_handle_pkt__rtr_adv__success(0U, true, true, false, false, 0U); +} + +static void test_handle_pkt__rtr_adv__success_mtuo(void) +{ + test_handle_pkt__rtr_adv__success(0U, true, false, true, false, 0U); +} + +static void test_handle_pkt__rtr_adv__success_pio_00(void) +{ + test_handle_pkt__rtr_adv__success(0U, true, false, false, true, 0U); +} + +static void test_handle_pkt__rtr_adv__success_pio_L0(void) +{ + test_handle_pkt__rtr_adv__success(0U, true, false, false, true, + NDP_OPT_PI_FLAGS_L); +} + +static void test_handle_pkt__rtr_adv__success_pio_0A(void) +{ + test_handle_pkt__rtr_adv__success(0U, true, false, false, true, + NDP_OPT_PI_FLAGS_A); +} + +static void test_handle_pkt__rtr_adv__success_pio_LA(void) +{ + test_handle_pkt__rtr_adv__success(0U, true, false, false, true, + NDP_OPT_PI_FLAGS_L | NDP_OPT_PI_FLAGS_A); +} + +static void test_handle_pkt__rtr_adv__success_sl2ao_mtuo_pio_00(void) +{ + test_handle_pkt__rtr_adv__success(0U, true, true, true, true, 0U); +} + +static void test_handle_pkt__rtr_adv__success_sl2ao_mtuo_pio_L0(void) +{ + test_handle_pkt__rtr_adv__success(0U, true, true, true, true, + NDP_OPT_PI_FLAGS_L); +} + +static void test_handle_pkt__rtr_adv__success_sl2ao_mtuo_pio_0A(void) +{ + test_handle_pkt__rtr_adv__success(0U, true, true, true, true, + NDP_OPT_PI_FLAGS_A); +} + +static void test_handle_pkt__rtr_adv__success_sl2ao_mtuo_pio_LA(void) +{ + test_handle_pkt__rtr_adv__success(0U, true, true, true, true, + NDP_OPT_PI_FLAGS_L | NDP_OPT_PI_FLAGS_A); +} + +static void test_change_rtr_adv_iface(void) +{ + TEST_ASSERT_MESSAGE(!(_mock_netif->flags & GNRC_NETIF2_FLAGS_IPV6_RTR_ADV), + "RTR_ADV was unexpectedly set"); + gnrc_ipv6_nib_change_rtr_adv_iface(_mock_netif, true); + TEST_ASSERT_MESSAGE(!(_mock_netif->flags & GNRC_NETIF2_FLAGS_IPV6_RTR_ADV), + "RTR_ADV was unexpectedly changed"); + gnrc_ipv6_nib_change_rtr_adv_iface(_mock_netif, false); + TEST_ASSERT_MESSAGE(!(_mock_netif->flags & GNRC_NETIF2_FLAGS_IPV6_RTR_ADV), + "RTR_ADV was unexpectedly changed"); + TEST_ASSERT_EQUAL_INT(0, msg_avail()); +} + static Test *tests_gnrc_ipv6_nib(void) { EMB_UNIT_TESTFIXTURES(fixtures) { @@ -690,6 +1224,11 @@ static Test *tests_gnrc_ipv6_nib(void) /* TODO: ENETUNREACH when non-link-local communication is implemented */ new_TestFixture(test_get_next_hop_l2addr__link_local_EHOSTUNREACH_no_iface), new_TestFixture(test_get_next_hop_l2addr__link_local_EHOSTUNREACH_iface), + new_TestFixture(test_get_next_hop_l2addr__global_EHOSTUNREACH_no_iface_off_link), + new_TestFixture(test_get_next_hop_l2addr__global_EHOSTUNREACH_iface_off_link), + new_TestFixture(test_get_next_hop_l2addr__global_EHOSTUNREACH_no_iface_on_link), + new_TestFixture(test_get_next_hop_l2addr__global_EHOSTUNREACH_iface_on_link), + new_TestFixture(test_get_next_hop_l2addr__ENETUNREACH), new_TestFixture(test_get_next_hop_l2addr__link_local_static_conf), new_TestFixture(test_get_next_hop_l2addr__link_local_after_handshake_iface), new_TestFixture(test_get_next_hop_l2addr__link_local_after_handshake_iface_router), @@ -716,9 +1255,29 @@ static Test *tests_gnrc_ipv6_nib(void) new_TestFixture(test_handle_pkt__nbr_adv__unspecified_src), new_TestFixture(test_handle_pkt__nbr_adv__unsolicited), /* solicited tested in get_next_hop_l2addr */ + new_TestFixture(test_handle_pkt__rtr_sol), + new_TestFixture(test_handle_pkt__rtr_adv__invalid_src), + new_TestFixture(test_handle_pkt__rtr_adv__invalid_hl), + new_TestFixture(test_handle_pkt__rtr_adv__invalid_code), + new_TestFixture(test_handle_pkt__rtr_adv__invalid_icmpv6_len), + new_TestFixture(test_handle_pkt__rtr_adv__invalid_opt_len), + new_TestFixture(test_handle_pkt__rtr_adv__success_all_zero), + new_TestFixture(test_handle_pkt__rtr_adv__success_no_flags_no_opt), + new_TestFixture(test_handle_pkt__rtr_adv__success_no_opt), + new_TestFixture(test_handle_pkt__rtr_adv__success_sl2ao), + new_TestFixture(test_handle_pkt__rtr_adv__success_mtuo), + new_TestFixture(test_handle_pkt__rtr_adv__success_pio_00), + new_TestFixture(test_handle_pkt__rtr_adv__success_pio_L0), + new_TestFixture(test_handle_pkt__rtr_adv__success_pio_0A), + new_TestFixture(test_handle_pkt__rtr_adv__success_pio_LA), + new_TestFixture(test_handle_pkt__rtr_adv__success_sl2ao_mtuo_pio_00), + new_TestFixture(test_handle_pkt__rtr_adv__success_sl2ao_mtuo_pio_L0), + new_TestFixture(test_handle_pkt__rtr_adv__success_sl2ao_mtuo_pio_0A), + new_TestFixture(test_handle_pkt__rtr_adv__success_sl2ao_mtuo_pio_LA), /* gnrc_ipv6_nib_handle_timer_event not testable in this context since * we do not have access to the (internally defined) contexts required * for it */ + new_TestFixture(test_change_rtr_adv_iface), }; EMB_UNIT_TESTCALLER(tests, _set_up, NULL, fixtures); diff --git a/tests/gnrc_ipv6_nib/mockup_netif.c b/tests/gnrc_ipv6_nib/mockup_netif.c index fce45710f470b2e79c3b1021fdfd07fed43ff0ff..d36f9d6b430eb3ec38020feda6b1be2a6c6a2cc9 100644 --- a/tests/gnrc_ipv6_nib/mockup_netif.c +++ b/tests/gnrc_ipv6_nib/mockup_netif.c @@ -83,6 +83,11 @@ void _tests_init(void) "mockup_eth", &_mock_netdev.netdev ); assert(_mock_netif != NULL); + /* we do not want to test for SLAAC here so just assure the configured + * address is valid */ + assert(!ipv6_addr_is_unspecified(&_mock_netif->ipv6.addrs[0])); + _mock_netif->ipv6.addrs_flags[0] &= ~GNRC_NETIF2_IPV6_ADDRS_FLAGS_STATE_MASK; + _mock_netif->ipv6.addrs_flags[0] |= GNRC_NETIF2_IPV6_ADDRS_FLAGS_STATE_VALID; gnrc_netreg_entry_init_pid(&dumper, GNRC_NETREG_DEMUX_CTX_ALL, sched_active_pid); gnrc_netreg_register(GNRC_NETTYPE_NDP2, &dumper); diff --git a/tests/gnrc_ipv6_nib_6ln/Makefile b/tests/gnrc_ipv6_nib_6ln/Makefile index 2d9b05ee300e68536f71e5ed354819dd43d1486a..8642c81a9148b3066adcbe509be41d2a846120e3 100644 --- a/tests/gnrc_ipv6_nib_6ln/Makefile +++ b/tests/gnrc_ipv6_nib_6ln/Makefile @@ -3,10 +3,12 @@ APPLICATION = gnrc_ipv6_nib_6ln include ../Makefile.tests_common BOARD_INSUFFICIENT_MEMORY := chronos nucleo-f030 nucleo-l053 nucleo32-f031 \ - nucleo32-l031 nucleo32-f042 stm32f0discovery + nucleo32-l031 nucleo32-f042 stm32f0discovery \ + telosb wsn430-v1_3b wsn430-v1_4 USEMODULE += gnrc_ipv6 USEMODULE += gnrc_sixlowpan +USEMODULE += gnrc_sixlowpan_ctx USEMODULE += gnrc_ipv6_nib_6ln USEMODULE += gnrc_netif2 USEMODULE += embunit diff --git a/tests/gnrc_ipv6_nib_6ln/main.c b/tests/gnrc_ipv6_nib_6ln/main.c index b9da5942ac952dadf8196206148219372a6c2d19..a034888272eb4e95b961437ca623ed17c2aac9f8 100644 --- a/tests/gnrc_ipv6_nib_6ln/main.c +++ b/tests/gnrc_ipv6_nib_6ln/main.c @@ -29,10 +29,25 @@ #include "net/gnrc.h" #include "net/gnrc/ipv6/nib.h" #include "net/gnrc/ipv6/nib/nc.h" +#include "net/gnrc/netif2/internal.h" +#include "net/gnrc/sixlowpan/ctx.h" +#include "net/gnrc/sixlowpan/nd.h" #include "net/ndp.h" +#include "net/sixlowpan/nd.h" #include "sched.h" -#define _BUFFER_SIZE (128) +#define _BUFFER_SIZE (196) +#define _ARO_LTIME (4224) +#define _CUR_HL (155) +#define _RTR_LTIME (6612U) +#define _REACH_TIME (1210388825UL) +#define _RETRANS_TIMER (3691140UL) +#define _LOC_GB_PFX_LEN (45U) +#define _REM_GB_PFX_LEN (37U) +#define _PIO_PFX_LTIME (0x8476fedf) +#define _CTX_LTIME (29169U) +#define _ABR_VERSION (4065834664U) +#define _ABR_LIME (5286U) static const uint8_t _loc_l2[] = { _LL0, _LL1, _LL2, _LL3, _LL4, _LL5, _LL6, _LL7 }; @@ -40,6 +55,10 @@ static const ipv6_addr_t _loc_ll = { { 0xfe, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, _LL0 ^ 2, _LL1, _LL2, _LL3, _LL4, _LL5, _LL6, _LL7 } }; +static const ipv6_addr_t _loc_gb = { { + 0x20, 0x01, 0x2b, 0x2e, 0x43, 0x80, 0x00, 0x00, + _LL0 ^ 2, _LL1, _LL2, _LL3, _LL4, _LL5, _LL6, _LL7 + } }; #define _loc_iid _loc_ll.u64[1].u8 static const uint8_t _rem_l2[] = { _LL0, _LL1, _LL2, _LL3, _LL4, _LL5, _LL6, _LL7 + 1 }; @@ -47,7 +66,15 @@ static const ipv6_addr_t _rem_ll = { { 0xfe, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, _LL0 ^ 2, _LL1, _LL2, _LL3, _LL4, _LL5, _LL6, _LL7 + 1 } }; +static const ipv6_addr_t _rem_gb = { { + 0x20, 0x01, 0x18, 0xc9, 0xf8, 0x00, 0x00, 0x00, + _LL0 ^ 2, _LL1, _LL2, _LL3, _LL4, _LL5, _LL6, _LL7 + 1 + } }; #define _rem_iid _rem_ll.u64[1].u8 +static const ipv6_addr_t _abr_gb = { { + 0x20, 0x01, 0x2b, 0x2e, 0x43, 0x80, 0x00, 0x00, + _LL0 ^ 2, _LL1, _LL2, _LL3, _LL4, _LL5, _LL6, _LL7 - 1 + } }; static uint8_t _buffer[_BUFFER_SIZE]; static ipv6_hdr_t *ipv6 = (ipv6_hdr_t *)&_buffer[0]; static icmpv6_hdr_t *icmpv6 = (icmpv6_hdr_t *)&_buffer[sizeof(ipv6_hdr_t)]; @@ -57,6 +84,13 @@ static inline size_t ceil8(size_t size); static void _set_up(void) { _common_set_up(); + gnrc_netif2_acquire(_mock_netif); + /* reset some fields not set by the nib interface initializer */ + _mock_netif->ipv6.mtu = IPV6_MIN_MTU; + _mock_netif->cur_hl = GNRC_NETIF2_DEFAULT_HL; + gnrc_netif2_ipv6_addr_remove(_mock_netif, &_loc_gb); + _mock_netif->flags &= ~GNRC_NETIF2_FLAGS_6LO_ADDRS_REG; + gnrc_netif2_release(_mock_netif); memset(_buffer, 0, sizeof(_buffer)); gnrc_pktbuf_init(); /* remove messages */ @@ -64,6 +98,7 @@ static void _set_up(void) msg_t msg; msg_receive(&msg); } + gnrc_sixlowpan_ctx_reset(); } static void test_get_next_hop_l2addr__link_local_EHOSTUNREACH(void) @@ -71,12 +106,24 @@ static void test_get_next_hop_l2addr__link_local_EHOSTUNREACH(void) gnrc_ipv6_nib_nc_t nce; TEST_ASSERT_EQUAL_INT(-EHOSTUNREACH, - gnrc_ipv6_nib_get_next_hop_l2addr(&_rem_ll, NULL, + gnrc_ipv6_nib_get_next_hop_l2addr(&_rem_ll, + NULL, NULL, &nce)); TEST_ASSERT_EQUAL_INT(0, msg_avail()); TEST_ASSERT(gnrc_pktbuf_is_empty()); } +static void test_get_next_hop_l2addr__ENETUNREACH(void) +{ + gnrc_ipv6_nib_nc_t nce; + + TEST_ASSERT_EQUAL_INT(-ENETUNREACH, + gnrc_ipv6_nib_get_next_hop_l2addr(&_rem_gb, + NULL, NULL, &nce)); + TEST_ASSERT_EQUAL_INT(0, msg_avail()); + TEST_ASSERT(gnrc_pktbuf_is_empty()); +} + static void test_get_next_hop_l2addr__link_local_static_conf(void) { gnrc_ipv6_nib_nc_t nce; @@ -123,6 +170,20 @@ static void test_get_next_hop_l2addr__link_local(void) TEST_ASSERT(gnrc_pktbuf_is_empty()); } +static void test_get_next_hop_l2addr__global_with_default_route(void) +{ + gnrc_ipv6_nib_nc_t nce; + + /* add _rem_ll as default router */ + TEST_ASSERT_EQUAL_INT(0, gnrc_ipv6_nib_ft_add(NULL, 0, &_rem_ll, + _mock_netif->pid)); + TEST_ASSERT_EQUAL_INT(0, gnrc_ipv6_nib_get_next_hop_l2addr(&_rem_gb, + NULL, NULL, + &nce)); + TEST_ASSERT_EQUAL_INT(0, msg_avail()); + TEST_ASSERT(gnrc_pktbuf_is_empty()); +} + static void test_handle_pkt__unknown_type(void) { gnrc_ipv6_nib_nc_t nce; @@ -397,7 +458,8 @@ static size_t _set_nbr_adv(const ipv6_addr_t *ipv6_src, uint8_t ipv6_hl, uint8_t nbr_adv_code, uint8_t nbr_adv_flags, const ipv6_addr_t *nbr_adv_tgt, - const uint8_t *tl2ao_addr, size_t tl2ao_addr_len) + const uint8_t *tl2ao_addr, size_t tl2ao_addr_len, + eui64_t *aro_eui, uint8_t aro_status) { size_t icmpv6_len = sizeof(ndp_nbr_adv_t); ndp_nbr_adv_t *nbr_adv = (ndp_nbr_adv_t *)icmpv6; @@ -420,6 +482,17 @@ static size_t _set_nbr_adv(const ipv6_addr_t *ipv6_src, memcpy(tl2ao + 1, tl2ao_addr, tl2ao_addr_len); icmpv6_len += ceil8(sizeof(ndp_opt_t) + tl2ao_addr_len); } + if (aro_eui) { + sixlowpan_nd_opt_ar_t *aro = (sixlowpan_nd_opt_ar_t *)&_buffer[sizeof(ipv6_hdr_t) + + icmpv6_len]; + + aro->type = NDP_OPT_AR; + aro->len = SIXLOWPAN_ND_OPT_AR_LEN; + aro->status = aro_status; + aro->ltime = byteorder_htons(_ARO_LTIME); + aro->eui64.uint64 = aro_eui->uint64; + icmpv6_len += sizeof(sixlowpan_nd_opt_ar_t); + } return icmpv6_len; } @@ -430,7 +503,7 @@ static void test_handle_pkt__nbr_adv__invalid_hl(void) void *state = NULL; size_t icmpv6_len = _set_nbr_adv(&_rem_ll, &_loc_ll, 194U, 0U, NDP_NBR_ADV_FLAGS_S, &_loc_ll, _rem_l2, - sizeof(_rem_l2)); + sizeof(_rem_l2), NULL, 0U); gnrc_ipv6_nib_handle_pkt(_mock_netif, ipv6, icmpv6, icmpv6_len); TEST_ASSERT_MESSAGE(!gnrc_ipv6_nib_nc_iter(0, &state, &nce), @@ -445,7 +518,7 @@ static void test_handle_pkt__nbr_adv__invalid_code(void) void *state = NULL; size_t icmpv6_len = _set_nbr_adv(&_rem_ll, &_loc_ll, 255U, 201U, NDP_NBR_ADV_FLAGS_S, &_loc_ll, _rem_l2, - sizeof(_rem_l2)); + sizeof(_rem_l2), NULL, 0U); gnrc_ipv6_nib_handle_pkt(_mock_netif, ipv6, icmpv6, icmpv6_len); TEST_ASSERT_MESSAGE(!gnrc_ipv6_nib_nc_iter(0, &state, &nce), @@ -461,7 +534,7 @@ static void test_handle_pkt__nbr_adv__invalid_icmpv6_len(void) _set_nbr_adv(&_rem_ll, &_loc_ll, 255U, 0U, NDP_NBR_ADV_FLAGS_S, &_loc_ll, _rem_l2, - sizeof(_rem_l2)); + sizeof(_rem_l2), NULL, 0U); gnrc_ipv6_nib_handle_pkt(_mock_netif, ipv6, icmpv6, sizeof(ndp_nbr_adv_t) - 1); @@ -478,7 +551,7 @@ static void test_handle_pkt__nbr_adv__invalid_tgt(void) size_t icmpv6_len = _set_nbr_adv(&_rem_ll, &_loc_ll, 255U, 0U, NDP_NBR_ADV_FLAGS_S, &ipv6_addr_all_routers_site_local, _rem_l2, - sizeof(_rem_l2)); + sizeof(_rem_l2), NULL, 0U); gnrc_ipv6_nib_handle_pkt(_mock_netif, ipv6, icmpv6, icmpv6_len); TEST_ASSERT_MESSAGE(!gnrc_ipv6_nib_nc_iter(0, &state, &nce), @@ -493,7 +566,7 @@ static void test_handle_pkt__nbr_adv__invalid_flags(void) void *state = NULL; size_t icmpv6_len = _set_nbr_adv(&_rem_ll, &ipv6_addr_all_nodes_link_local, 255U, 0U, NDP_NBR_ADV_FLAGS_S, &_loc_ll, - NULL, 0); + NULL, 0, NULL, 0U); gnrc_ipv6_nib_handle_pkt(_mock_netif, ipv6, icmpv6, icmpv6_len); TEST_ASSERT_MESSAGE(!gnrc_ipv6_nib_nc_iter(0, &state, &nce), @@ -508,7 +581,7 @@ static void test_handle_pkt__nbr_adv__invalid_opt_len(void) void *state = NULL; size_t icmpv6_len = _set_nbr_adv(&_rem_ll, &_loc_ll, 255U, 0U, NDP_NBR_ADV_FLAGS_S, &_loc_ll, _rem_l2, - sizeof(_rem_l2)); + sizeof(_rem_l2), NULL, 0U); ndp_opt_t *opt = (ndp_opt_t *)&_buffer[icmpv6_len]; opt->type = NDP_OPT_SL2A; @@ -527,7 +600,7 @@ static void test_handle_pkt__nbr_adv__unspecified_src(void) void *state = NULL; size_t icmpv6_len = _set_nbr_adv(&ipv6_addr_unspecified, &_loc_ll, 255U, 0U, NDP_NBR_ADV_FLAGS_S, &_loc_ll, _rem_l2, - sizeof(_rem_l2)); + sizeof(_rem_l2), NULL, 0U); gnrc_ipv6_nib_handle_pkt(_mock_netif, ipv6, icmpv6, icmpv6_len); TEST_ASSERT_MESSAGE(!gnrc_ipv6_nib_nc_iter(0, &state, &nce), @@ -542,7 +615,7 @@ static void test_handle_pkt__nbr_adv__unsolicited(void) void *state = NULL; size_t icmpv6_len = _set_nbr_adv(&_rem_ll, &_loc_ll, 255U, 0U, NDP_NBR_ADV_FLAGS_S, &_loc_ll, - _rem_l2, sizeof(_rem_l2)); + _rem_l2, sizeof(_rem_l2), NULL, 0U); gnrc_ipv6_nib_handle_pkt(_mock_netif, ipv6, icmpv6, icmpv6_len); TEST_ASSERT_MESSAGE(!gnrc_ipv6_nib_nc_iter(0, &state, &nce), @@ -550,6 +623,612 @@ static void test_handle_pkt__nbr_adv__unsolicited(void) TEST_ASSERT_EQUAL_INT(0, msg_avail()); } +static void test_handle_pkt__nbr_adv__aro_not_my_eui64(void) +{ + size_t icmpv6_len = _set_nbr_adv(&_rem_gb, &_loc_gb, 255U, 0U, 0U, &_rem_ll, + 0U, 0U, (eui64_t *)&_rem_l2, + SIXLOWPAN_ND_STATUS_SUCCESS); + int idx; + + idx = gnrc_netif2_ipv6_addr_add(_mock_netif, &_loc_gb, _LOC_GB_PFX_LEN, + GNRC_NETIF2_IPV6_ADDRS_FLAGS_STATE_TENTATIVE); + TEST_ASSERT(idx >= 0); + gnrc_ipv6_nib_handle_pkt(_mock_netif, ipv6, icmpv6, icmpv6_len); + TEST_ASSERT(ipv6_addr_equal(&_loc_gb, &_mock_netif->ipv6.addrs[idx])); + TEST_ASSERT(_mock_netif->ipv6.addrs_flags[idx] & + GNRC_NETIF2_IPV6_ADDRS_FLAGS_STATE_TENTATIVE); +} + +static void test_handle_pkt__nbr_adv__aro_duplicate(void) +{ + size_t icmpv6_len = _set_nbr_adv(&_rem_gb, &_loc_gb, 255U, 0U, 0U, &_rem_ll, + NULL, 0U, (eui64_t *)&_loc_l2, + SIXLOWPAN_ND_STATUS_DUP); + int idx; + + TEST_ASSERT_EQUAL_INT(0, gnrc_ipv6_nib_nc_set(&_rem_ll, _mock_netif->pid, + _rem_l2, sizeof(_rem_l2))); + idx = gnrc_netif2_ipv6_addr_add(_mock_netif, &_loc_gb, _LOC_GB_PFX_LEN, + GNRC_NETIF2_IPV6_ADDRS_FLAGS_STATE_TENTATIVE); + TEST_ASSERT(idx >= 0); + gnrc_ipv6_nib_handle_pkt(_mock_netif, ipv6, icmpv6, icmpv6_len); + TEST_ASSERT(gnrc_netif2_ipv6_addr_idx(_mock_netif, &_loc_gb) < 0); +} + +static size_t _set_rtr_sol(const ipv6_addr_t *ipv6_src, + const ipv6_addr_t *ipv6_dst, + uint8_t ipv6_hl, uint8_t rtr_sol_code, + const uint8_t *sl2ao_addr, size_t sl2ao_addr_len) +{ + size_t icmpv6_len = sizeof(ndp_rtr_sol_t); + ndp_rtr_sol_t *rtr_sol = (ndp_rtr_sol_t *)icmpv6; + + ipv6_hdr_set_version(ipv6); + ipv6->hl = ipv6_hl; + memcpy(&ipv6->src, ipv6_src, sizeof(ipv6->src)); + memcpy(&ipv6->dst, ipv6_dst, sizeof(ipv6->dst)); + rtr_sol->type = ICMPV6_RTR_SOL; + rtr_sol->code = rtr_sol_code; + + if ((sl2ao_addr != NULL) && (sl2ao_addr_len > 0)) { + ndp_opt_t *sl2ao = (ndp_opt_t *)&_buffer[sizeof(ipv6_hdr_t) + + sizeof(ndp_rtr_sol_t)]; + + sl2ao->type = NDP_OPT_SL2A; + sl2ao->len = ceil8(sizeof(ndp_opt_t) + sl2ao_addr_len) / 8; + memcpy(sl2ao + 1, sl2ao_addr, sl2ao_addr_len); + icmpv6_len += ceil8(sizeof(ndp_opt_t) + sl2ao_addr_len); + } + + return icmpv6_len; +} + +static void test_handle_pkt__rtr_sol(void) +{ + gnrc_ipv6_nib_nc_t nce; + void *state = NULL; + size_t icmpv6_len = _set_rtr_sol(&_rem_ll, &_loc_ll, + 255U, 0U, _rem_l2, sizeof(_rem_l2)); + + gnrc_ipv6_nib_handle_pkt(_mock_netif, ipv6, icmpv6, icmpv6_len); + TEST_ASSERT_MESSAGE(!gnrc_ipv6_nib_nc_iter(0, &state, &nce), + "There is an unexpected neighbor cache entry"); + TEST_ASSERT_EQUAL_INT(0, msg_avail()); +} + +static size_t _set_rtr_adv(const ipv6_addr_t *ipv6_src, + uint8_t ipv6_hl, uint8_t rtr_adv_code, + bool set_rtr_adv_fields, + uint8_t rtr_adv_flags, + const uint8_t *sl2ao_addr, size_t sl2ao_addr_len, + uint16_t mtu, + const ipv6_addr_t *pfx, unsigned pfx_len, + uint8_t pfx_flags, + bool include_pfx_6co, + const ipv6_addr_t *abr, uint32_t abr_version) +{ + size_t icmpv6_len = sizeof(ndp_rtr_adv_t); + ndp_rtr_adv_t *rtr_adv = (ndp_rtr_adv_t *)icmpv6; + + ipv6_hdr_set_version(ipv6); + ipv6->hl = ipv6_hl; + memcpy(&ipv6->src, ipv6_src, sizeof(ipv6->src)); + memcpy(&ipv6->dst, &_loc_ll, sizeof(ipv6->dst)); + rtr_adv->type = ICMPV6_RTR_ADV; + rtr_adv->code = rtr_adv_code; + rtr_adv->flags = rtr_adv_flags; + if (set_rtr_adv_fields) { + rtr_adv->cur_hl = _CUR_HL, + rtr_adv->ltime = byteorder_htons(_RTR_LTIME); + rtr_adv->reach_time = byteorder_htonl(_REACH_TIME); + rtr_adv->retrans_timer = byteorder_htonl(_RETRANS_TIMER); + } + + if (mtu > 0) { + ndp_opt_mtu_t *mtuo = (ndp_opt_mtu_t *)&_buffer[sizeof(ipv6_hdr_t) + + icmpv6_len]; + + mtuo->type = NDP_OPT_MTU; + mtuo->len = NDP_OPT_MTU_LEN; + mtuo->mtu = byteorder_htonl(mtu); + icmpv6_len += sizeof(ndp_opt_mtu_t); + } + if (abr != NULL) { + sixlowpan_nd_opt_abr_t *abro = (sixlowpan_nd_opt_abr_t *)&_buffer[sizeof(ipv6_hdr_t) + + icmpv6_len]; + + abro->type = NDP_OPT_ABR; + abro->len = SIXLOWPAN_ND_OPT_ABR_LEN; + sixlowpan_nd_opt_abr_set_version(abro, abr_version); + abro->ltime = byteorder_htons(_ABR_LIME); + memcpy(&abro->braddr, abr, sizeof(abro->braddr)); + icmpv6_len += sizeof(sixlowpan_nd_opt_abr_t); + } + if ((pfx != NULL) && (pfx_len > 0)) { + ndp_opt_pi_t *pio = (ndp_opt_pi_t *)&_buffer[sizeof(ipv6_hdr_t) + + icmpv6_len]; + + pio->type = NDP_OPT_PI; + pio->len = NDP_OPT_PI_LEN; + pio->prefix_len = pfx_len; + pio->flags = pfx_flags; + pio->valid_ltime = byteorder_htonl(_PIO_PFX_LTIME); + pio->pref_ltime = byteorder_htonl(_PIO_PFX_LTIME); + ipv6_addr_init_prefix(&pio->prefix, pfx, pfx_len); + icmpv6_len += sizeof(ndp_opt_pi_t); + + if (include_pfx_6co) { + sixlowpan_nd_opt_6ctx_t *ctx = (sixlowpan_nd_opt_6ctx_t *)&_buffer[sizeof(ipv6_hdr_t) + + icmpv6_len]; + ipv6_addr_t *ctx_pfx = (ipv6_addr_t *)(ctx + 1); + + ctx->type = NDP_OPT_6CTX; + ctx->len = (pfx_len > 64) ? SIXLOWPAN_ND_OPT_6CTX_LEN_MAX : + SIXLOWPAN_ND_OPT_6CTX_LEN_MIN; + ctx->ctx_len = pfx_len; + ctx->resv_c_cid |= SIXLOWPAN_ND_OPT_6CTX_FLAGS_C; + ctx->ltime = byteorder_htons(_CTX_LTIME); + ipv6_addr_init_prefix(ctx_pfx, pfx, pfx_len); + icmpv6_len += ctx->len * 8U; + } + } + if ((sl2ao_addr != NULL) && (sl2ao_addr_len > 0)) { + ndp_opt_t *sl2ao = (ndp_opt_t *)&_buffer[sizeof(ipv6_hdr_t) + + icmpv6_len]; + + sl2ao->type = NDP_OPT_SL2A; + sl2ao->len = ceil8(sizeof(ndp_opt_t) + sl2ao_addr_len) / 8; + memcpy(sl2ao + 1, sl2ao_addr, sl2ao_addr_len); + icmpv6_len += ceil8(sizeof(ndp_opt_t) + sl2ao_addr_len); + } + + return icmpv6_len; +} + +typedef struct { + uint32_t retrans_timer; + uint16_t mtu; + uint8_t addr_count; + uint8_t cur_hl; +} _netif_exp_t; + +static uint8_t _netif_addr_count(const gnrc_netif2_t *netif) +{ + unsigned count = 0U; + + for (int i = 0; i < GNRC_NETIF2_IPV6_ADDRS_NUMOF; i++) { + if (netif->ipv6.addrs_flags[i] != 0) { + count++; + } + } + return count; +} + +static inline void _get_netif_exp(const gnrc_netif2_t *netif, + _netif_exp_t *exp) +{ + exp->retrans_timer = netif->ipv6.retrans_time; + exp->mtu = netif->ipv6.mtu; + exp->addr_count = _netif_addr_count(netif); + exp->cur_hl = netif->cur_hl; +} + +#define TEST_ASSERT_NETIF_UNCHANGED(netif, exp) \ + TEST_ASSERT_EQUAL_INT(exp.retrans_timer, netif->ipv6.retrans_time); \ + TEST_ASSERT_EQUAL_INT(exp.mtu, netif->ipv6.mtu); \ + TEST_ASSERT_EQUAL_INT(exp.addr_count, _netif_addr_count(netif)); \ + TEST_ASSERT_EQUAL_INT(exp.cur_hl, netif->cur_hl) + +static void test_handle_pkt__rtr_adv__invalid_src(void) +{ + gnrc_ipv6_nib_nc_t nce; + gnrc_ipv6_nib_ft_t route; + void *state = NULL; + size_t icmpv6_len = _set_rtr_adv(&_rem_gb, + 255U, 0U, true, 0U, + _loc_l2, sizeof(_loc_l2), + 32397U, &_loc_gb, _LOC_GB_PFX_LEN, + NDP_OPT_PI_FLAGS_L | NDP_OPT_PI_FLAGS_A, + true, &_abr_gb, _ABR_VERSION); + _netif_exp_t exp_netif; + + _get_netif_exp(_mock_netif, &exp_netif); + gnrc_ipv6_nib_handle_pkt(_mock_netif, ipv6, icmpv6, icmpv6_len); + TEST_ASSERT_MESSAGE(!gnrc_ipv6_nib_nc_iter(0, &state, &nce), + "There is an unexpected neighbor cache entry"); + state = NULL; + TEST_ASSERT_MESSAGE(!gnrc_ipv6_nib_ft_iter(NULL, 0, &state, &route), + "There is an unexpected forwarding entry"); + TEST_ASSERT_NETIF_UNCHANGED(_mock_netif, exp_netif); + TEST_ASSERT_EQUAL_INT(0, msg_avail()); +} + +static void test_handle_pkt__rtr_adv__invalid_hl(void) +{ + gnrc_ipv6_nib_nc_t nce; + gnrc_ipv6_nib_ft_t route; + void *state = NULL; + size_t icmpv6_len = _set_rtr_adv(&_rem_ll, + 194U, 0U, true, 0U, + _loc_l2, sizeof(_loc_l2), + 32397U, &_loc_gb, _LOC_GB_PFX_LEN, + NDP_OPT_PI_FLAGS_L | NDP_OPT_PI_FLAGS_A, + true, &_abr_gb, _ABR_VERSION); + _netif_exp_t exp_netif; + + _get_netif_exp(_mock_netif, &exp_netif); + gnrc_ipv6_nib_handle_pkt(_mock_netif, ipv6, icmpv6, icmpv6_len); + TEST_ASSERT_MESSAGE(!gnrc_ipv6_nib_nc_iter(0, &state, &nce), + "There is an unexpected neighbor cache entry"); + state = NULL; + TEST_ASSERT_MESSAGE(!gnrc_ipv6_nib_ft_iter(NULL, 0, &state, &route), + "There is an unexpected forwarding entry"); + TEST_ASSERT_NETIF_UNCHANGED(_mock_netif, exp_netif); + TEST_ASSERT_EQUAL_INT(0, msg_avail()); +} + +static void test_handle_pkt__rtr_adv__invalid_code(void) +{ + gnrc_ipv6_nib_nc_t nce; + gnrc_ipv6_nib_ft_t route; + void *state = NULL; + size_t icmpv6_len = _set_rtr_adv(&_rem_ll, + 255U, 201U, true, 0U, + _loc_l2, sizeof(_loc_l2), + 32397U, &_loc_gb, _LOC_GB_PFX_LEN, + NDP_OPT_PI_FLAGS_L | NDP_OPT_PI_FLAGS_A, + true, &_abr_gb, _ABR_VERSION); + _netif_exp_t exp_netif; + + _get_netif_exp(_mock_netif, &exp_netif); + gnrc_ipv6_nib_handle_pkt(_mock_netif, ipv6, icmpv6, icmpv6_len); + TEST_ASSERT_MESSAGE(!gnrc_ipv6_nib_nc_iter(0, &state, &nce), + "There is an unexpected neighbor cache entry"); + state = NULL; + TEST_ASSERT_MESSAGE(!gnrc_ipv6_nib_ft_iter(NULL, 0, &state, &route), + "There is an unexpected forwarding entry"); + TEST_ASSERT_NETIF_UNCHANGED(_mock_netif, exp_netif); + TEST_ASSERT_EQUAL_INT(0, msg_avail()); +} + +static void test_handle_pkt__rtr_adv__invalid_icmpv6_len(void) +{ + gnrc_ipv6_nib_nc_t nce; + gnrc_ipv6_nib_ft_t route; + void *state = NULL; + _netif_exp_t exp_netif; + + _get_netif_exp(_mock_netif, &exp_netif); + _set_rtr_adv(&_rem_ll, 255U, 201U, true, 0U, _loc_l2, sizeof(_loc_l2), + 32397U, &_loc_gb, _LOC_GB_PFX_LEN, + NDP_OPT_PI_FLAGS_L | NDP_OPT_PI_FLAGS_A, + true, &_abr_gb, _ABR_VERSION); + gnrc_ipv6_nib_handle_pkt(_mock_netif, ipv6, icmpv6, + sizeof(ndp_rtr_adv_t) - 1); + TEST_ASSERT_MESSAGE(!gnrc_ipv6_nib_nc_iter(0, &state, &nce), + "There is an unexpected neighbor cache entry"); + state = NULL; + TEST_ASSERT_MESSAGE(!gnrc_ipv6_nib_ft_iter(NULL, 0, &state, &route), + "There is an unexpected forwarding entry"); + TEST_ASSERT_NETIF_UNCHANGED(_mock_netif, exp_netif); + TEST_ASSERT_EQUAL_INT(0, msg_avail()); +} + +static void test_handle_pkt__rtr_adv__invalid_opt_len(void) +{ + gnrc_ipv6_nib_nc_t nce; + gnrc_ipv6_nib_ft_t route; + void *state = NULL; + size_t icmpv6_len = _set_rtr_adv(&_rem_ll, + 255U, 201U, true, 0U, + _loc_l2, sizeof(_loc_l2), + 32397U, &_loc_gb, _LOC_GB_PFX_LEN, + NDP_OPT_PI_FLAGS_L | NDP_OPT_PI_FLAGS_A, + true, &_abr_gb, _ABR_VERSION); + ndp_opt_t *opt = (ndp_opt_t *)&_buffer[icmpv6_len]; + _netif_exp_t exp_netif; + + _get_netif_exp(_mock_netif, &exp_netif); + opt->type = NDP_OPT_SL2A; + opt->len = 0U; + icmpv6_len += sizeof(ndp_opt_t); + + gnrc_ipv6_nib_handle_pkt(_mock_netif, ipv6, icmpv6, icmpv6_len); + TEST_ASSERT_MESSAGE(!gnrc_ipv6_nib_nc_iter(0, &state, &nce), + "There is an unexpected neighbor cache entry"); + state = NULL; + TEST_ASSERT_MESSAGE(!gnrc_ipv6_nib_ft_iter(NULL, 0, &state, &route), + "There is an unexpected forwarding entry"); + TEST_ASSERT_NETIF_UNCHANGED(_mock_netif, exp_netif); + TEST_ASSERT_EQUAL_INT(0, msg_avail()); +} + +static void test_handle_pkt__rtr_adv__invalid_no_abro(void) +{ + gnrc_ipv6_nib_nc_t nce; + gnrc_ipv6_nib_ft_t route; + void *state = NULL; + _netif_exp_t exp_netif; + + _get_netif_exp(_mock_netif, &exp_netif); + _set_rtr_adv(&_rem_ll, 255U, 201U, true, 0U, _loc_l2, sizeof(_loc_l2), + 32397U, &_loc_gb, _LOC_GB_PFX_LEN, + NDP_OPT_PI_FLAGS_L | NDP_OPT_PI_FLAGS_A, + true, NULL, 0); + gnrc_ipv6_nib_handle_pkt(_mock_netif, ipv6, icmpv6, + sizeof(ndp_rtr_adv_t)); + TEST_ASSERT_MESSAGE(!gnrc_ipv6_nib_nc_iter(0, &state, &nce), + "There is an unexpected neighbor cache entry"); + state = NULL; + TEST_ASSERT_MESSAGE(!gnrc_ipv6_nib_ft_iter(NULL, 0, &state, &route), + "There is an unexpected forwarding entry"); + TEST_ASSERT_NETIF_UNCHANGED(_mock_netif, exp_netif); + TEST_ASSERT_EQUAL_INT(0, msg_avail()); +} + +static void test_handle_pkt__rtr_adv__success(uint8_t rtr_adv_flags, + bool set_rtr_adv_fields, + bool sl2ao, bool mtuo, + bool pio, uint8_t pio_flags, + bool ctxo) +{ + gnrc_ipv6_nib_pl_t prefix; + gnrc_ipv6_nib_nc_t nce; + gnrc_ipv6_nib_ft_t route; + void *state = NULL; + size_t icmpv6_len = _set_rtr_adv(&_rem_ll, 255U, 0U, + set_rtr_adv_fields, rtr_adv_flags, + (sl2ao) ? _rem_l2 : NULL, sizeof(_rem_l2), + (mtuo) ? 32397U : 0U, + (pio) ? &_loc_gb : NULL, _LOC_GB_PFX_LEN, + pio_flags, + ctxo, &_abr_gb, _ABR_VERSION); + const unsigned exp_addr_count = _netif_addr_count(_mock_netif); + _netif_exp_t exp_netif; + + _get_netif_exp(_mock_netif, &exp_netif); + TEST_ASSERT(gnrc_netif2_ipv6_addr_idx(_mock_netif, &_loc_gb) < 0); + gnrc_ipv6_nib_handle_pkt(_mock_netif, ipv6, icmpv6, icmpv6_len); + if (set_rtr_adv_fields) { + while (gnrc_ipv6_nib_ft_iter(NULL, 0, &state, &route)) { + /* is default route */ + if (ipv6_addr_is_unspecified(&route.dst)) { + break; + } + } + TEST_ASSERT_MESSAGE(ipv6_addr_equal(&_rem_ll, &route.next_hop), + "default route is not via RA's source"); + TEST_ASSERT_EQUAL_INT(_mock_netif->pid, route.iface); + TEST_ASSERT_EQUAL_INT(_RETRANS_TIMER, _mock_netif->ipv6.retrans_time); + TEST_ASSERT_EQUAL_INT(_CUR_HL, _mock_netif->cur_hl); + } + else { + while (gnrc_ipv6_nib_ft_iter(NULL, 0, &state, &route)) { + TEST_ASSERT_MESSAGE(!ipv6_addr_is_unspecified(&route.dst), + "There is a default route, " + "though RA's router lifetime was 0."); + } + TEST_ASSERT_EQUAL_INT(exp_netif.retrans_timer, + _mock_netif->ipv6.retrans_time); + TEST_ASSERT_EQUAL_INT(exp_netif.cur_hl, + _mock_netif->cur_hl); + } + state = NULL; + if (ctxo) { + gnrc_sixlowpan_ctx_t *ctx; + + TEST_ASSERT_NOT_NULL((ctx = gnrc_sixlowpan_ctx_lookup_addr(&_loc_gb))); + TEST_ASSERT(ipv6_addr_match_prefix(&_loc_gb, + &ctx->prefix) >= _LOC_GB_PFX_LEN); + TEST_ASSERT_EQUAL_INT(0U, ctx->flags_id & GNRC_SIXLOWPAN_CTX_FLAGS_CID_MASK); + TEST_ASSERT(ctx->flags_id & GNRC_SIXLOWPAN_CTX_FLAGS_COMP); + TEST_ASSERT_EQUAL_INT(_CTX_LTIME, ctx->ltime); + } + else { + TEST_ASSERT_NULL(gnrc_sixlowpan_ctx_lookup_addr(&_loc_gb)); + } + if (sl2ao) { + TEST_ASSERT_MESSAGE(gnrc_ipv6_nib_nc_iter(0, &state, &nce), + "No neighbor cache entry found"); + TEST_ASSERT_MESSAGE((memcmp(&_rem_ll, &nce.ipv6, sizeof(_rem_ll)) == 0), + "_rem_ll != nce.ipv6"); + TEST_ASSERT_EQUAL_INT(sizeof(_rem_l2), nce.l2addr_len); + TEST_ASSERT_MESSAGE((memcmp(&_rem_l2, &nce.l2addr, nce.l2addr_len) == 0), + "_rem_l2 != nce.l2addr"); + TEST_ASSERT_EQUAL_INT(GNRC_IPV6_NIB_NC_INFO_NUD_STATE_STALE, + gnrc_ipv6_nib_nc_get_nud_state(&nce)); + TEST_ASSERT_EQUAL_INT(_mock_netif->pid, gnrc_ipv6_nib_nc_get_iface(&nce)); + TEST_ASSERT_EQUAL_INT(GNRC_IPV6_NIB_NC_INFO_AR_STATE_GC, + gnrc_ipv6_nib_nc_get_ar_state(&nce)); + } + else { + TEST_ASSERT_MESSAGE(!gnrc_ipv6_nib_nc_iter(0, &state, &nce), + "There is an unexpected neighbor cache entry"); + } + if (mtuo) { + TEST_ASSERT_EQUAL_INT(32397U, _mock_netif->ipv6.mtu); + } + else { + TEST_ASSERT_EQUAL_INT(exp_netif.mtu, _mock_netif->ipv6.mtu); + } + state = NULL; + if (pio) { + if (pio_flags & NDP_OPT_PI_FLAGS_A) { + TEST_ASSERT_MESSAGE(gnrc_netif2_ipv6_addr_idx(_mock_netif, + &_loc_gb) >= 0, + "Address was not configured by PIO"); + } + else { + TEST_ASSERT_MESSAGE(gnrc_netif2_ipv6_addr_idx(_mock_netif, + &_loc_gb) < 0, + "Address was configured by PIO, " + "but A flag was set"); + } + if (pio_flags & NDP_OPT_PI_FLAGS_L) { + TEST_ASSERT_MESSAGE(gnrc_ipv6_nib_pl_iter(0, &state, &prefix), + "No prefix list entry found"); + TEST_ASSERT_MESSAGE(ipv6_addr_match_prefix(&_loc_gb, + &prefix.pfx) >= _LOC_GB_PFX_LEN, + "Unexpected prefix configured"); + TEST_ASSERT_EQUAL_INT(_LOC_GB_PFX_LEN, prefix.pfx_len); + TEST_ASSERT_EQUAL_INT(_mock_netif->pid, prefix.iface); + TEST_ASSERT(_PIO_PFX_LTIME < prefix.valid_until); + TEST_ASSERT(_PIO_PFX_LTIME < prefix.pref_until); + } + } + if (!pio) { + if (!pio) { + TEST_ASSERT_EQUAL_INT(exp_addr_count, + _netif_addr_count(_mock_netif)); + } + TEST_ASSERT_MESSAGE(!gnrc_ipv6_nib_pl_iter(0, &state, &prefix), + "There is an unexpected prefix list entry"); + } + if (set_rtr_adv_fields) { + TEST_ASSERT(msg_avail() > 0); + while (msg_avail()) { + gnrc_netif_hdr_t *netif_hdr; + ipv6_hdr_t *ipv6_hdr; + ndp_nbr_sol_t *nbr_sol; + gnrc_pktsnip_t *pkt; + msg_t msg; + + msg_receive(&msg); + TEST_ASSERT_EQUAL_INT(GNRC_NETAPI_MSG_TYPE_SND, msg.type); + pkt = msg.content.ptr; + /* first snip is a netif header to _mock_netif */ + TEST_ASSERT_NOT_NULL(pkt); + TEST_ASSERT_EQUAL_INT(GNRC_NETTYPE_NETIF, pkt->type); + TEST_ASSERT(sizeof(gnrc_netif_hdr_t) <= pkt->size); + netif_hdr = pkt->data; + TEST_ASSERT_EQUAL_INT(_mock_netif->pid, netif_hdr->if_pid); + /* second snip is an IPv6 header to router (source of RA) */ + TEST_ASSERT_NOT_NULL(pkt->next); + TEST_ASSERT_EQUAL_INT(GNRC_NETTYPE_IPV6, pkt->next->type); + TEST_ASSERT_EQUAL_INT(sizeof(ipv6_hdr_t), pkt->next->size); + ipv6_hdr = pkt->next->data; + TEST_ASSERT_MESSAGE(ipv6_addr_equal(&_rem_ll, &ipv6_hdr->dst), + "_rem_ll != ipv6_hdr->dst"); + TEST_ASSERT_EQUAL_INT(255, ipv6_hdr->hl); + /* third snip is a valid solicited neighbor advertisement to tgt */ + TEST_ASSERT_NOT_NULL(pkt->next->next); + TEST_ASSERT_EQUAL_INT(GNRC_NETTYPE_ICMPV6, pkt->next->next->type); + TEST_ASSERT_EQUAL_INT(sizeof(ndp_nbr_sol_t), pkt->next->next->size); + nbr_sol = pkt->next->next->data; + TEST_ASSERT_EQUAL_INT(ICMPV6_NBR_SOL, nbr_sol->type); + TEST_ASSERT_EQUAL_INT(0, nbr_sol->code); + TEST_ASSERT(!ipv6_addr_is_multicast(&nbr_sol->tgt)); + TEST_ASSERT_MESSAGE(ipv6_addr_equal(&_rem_ll, &nbr_sol->tgt), + "_rem_ll != nbr_sol->tgt"); + /* ARO and SL2AO (fields not checked here) are also there */ + TEST_ASSERT_NOT_NULL(pkt->next->next->next); + TEST_ASSERT_NOT_NULL(pkt->next->next->next->next); + TEST_ASSERT_NULL(pkt->next->next->next->next->next); + gnrc_pktbuf_release(pkt); + } + TEST_ASSERT(gnrc_pktbuf_is_empty()); + } + else { + TEST_ASSERT_EQUAL_INT(0, msg_avail()); + } +} + +static void test_handle_pkt__rtr_adv__success_all_zero(void) +{ + test_handle_pkt__rtr_adv__success(0U, false, false, false, false, 0U, + false); +} + +static void test_handle_pkt__rtr_adv__success_no_flags_no_opt(void) +{ + test_handle_pkt__rtr_adv__success(0U, true, false, false, false, 0U, false); +} + +static void test_handle_pkt__rtr_adv__success_no_opt(void) +{ + /* these flags only make sense with SLAAC, so don't further test them below + * (except for PIO ;-)) */ + test_handle_pkt__rtr_adv__success(NDP_RTR_ADV_FLAGS_M | NDP_RTR_ADV_FLAGS_O, + true, false, false, false, 0U, false); +} + +static void test_handle_pkt__rtr_adv__success_sl2ao(void) +{ + test_handle_pkt__rtr_adv__success(0U, true, true, false, false, 0U, false); +} + +static void test_handle_pkt__rtr_adv__success_mtuo(void) +{ + test_handle_pkt__rtr_adv__success(0U, true, false, true, false, 0U, false); +} + +static void test_handle_pkt__rtr_adv__success_pio_00(void) +{ + test_handle_pkt__rtr_adv__success(0U, true, false, false, true, 0U, false); +} + +static void test_handle_pkt__rtr_adv__success_pio_L0(void) +{ + test_handle_pkt__rtr_adv__success(0U, true, false, false, true, + NDP_OPT_PI_FLAGS_L, false); +} + +static void test_handle_pkt__rtr_adv__success_pio_0A(void) +{ + test_handle_pkt__rtr_adv__success(0U, true, false, false, true, + NDP_OPT_PI_FLAGS_A, false); +} + +static void test_handle_pkt__rtr_adv__success_pio_LA(void) +{ + test_handle_pkt__rtr_adv__success(0U, true, false, false, true, + NDP_OPT_PI_FLAGS_L | NDP_OPT_PI_FLAGS_A, + false); +} + +static void test_handle_pkt__rtr_adv__success_6co_pio_0A(void) +{ + test_handle_pkt__rtr_adv__success(0U, true, false, false, true, + NDP_OPT_PI_FLAGS_A, true); +} + +static void test_handle_pkt__rtr_adv__success_6co_sl2ao_mtuo_pio_00(void) +{ + test_handle_pkt__rtr_adv__success(0U, true, true, true, true, 0U, true); +} + +static void test_handle_pkt__rtr_adv__success_6co_sl2ao_mtuo_pio_L0(void) +{ + test_handle_pkt__rtr_adv__success(0U, true, true, true, true, + NDP_OPT_PI_FLAGS_L, true); +} + +static void test_handle_pkt__rtr_adv__success_6co_sl2ao_mtuo_pio_0A(void) +{ + test_handle_pkt__rtr_adv__success(0U, true, true, true, true, + NDP_OPT_PI_FLAGS_A, true); +} + +static void test_handle_pkt__rtr_adv__success_6co_sl2ao_mtuo_pio_LA(void) +{ + test_handle_pkt__rtr_adv__success(0U, true, true, true, true, + NDP_OPT_PI_FLAGS_L | NDP_OPT_PI_FLAGS_A, + true); +} + +static void test_change_rtr_adv_iface(void) +{ + TEST_ASSERT_MESSAGE(!(_mock_netif->flags & GNRC_NETIF2_FLAGS_IPV6_RTR_ADV), + "RTR_ADV was unexpectedly set"); + gnrc_ipv6_nib_change_rtr_adv_iface(_mock_netif, true); + TEST_ASSERT_MESSAGE(!(_mock_netif->flags & GNRC_NETIF2_FLAGS_IPV6_RTR_ADV), + "RTR_ADV was unexpectedly changed"); + gnrc_ipv6_nib_change_rtr_adv_iface(_mock_netif, false); + TEST_ASSERT_MESSAGE(!(_mock_netif->flags & GNRC_NETIF2_FLAGS_IPV6_RTR_ADV), + "RTR_ADV was unexpectedly changed"); + TEST_ASSERT_EQUAL_INT(0, msg_avail()); +} + static Test *tests_gnrc_ipv6_nib(void) { EMB_UNIT_TESTFIXTURES(fixtures) { @@ -557,8 +1236,10 @@ static Test *tests_gnrc_ipv6_nib(void) * set-up (otherwise the following tests wouldn't work) */ /* TODO: ENETUNREACH when non-link-local communication is implemented */ new_TestFixture(test_get_next_hop_l2addr__link_local_EHOSTUNREACH), + new_TestFixture(test_get_next_hop_l2addr__ENETUNREACH), new_TestFixture(test_get_next_hop_l2addr__link_local_static_conf), new_TestFixture(test_get_next_hop_l2addr__link_local), + new_TestFixture(test_get_next_hop_l2addr__global_with_default_route), new_TestFixture(test_handle_pkt__unknown_type), new_TestFixture(test_handle_pkt__nbr_sol__invalid_hl), new_TestFixture(test_handle_pkt__nbr_sol__invalid_code), @@ -580,10 +1261,34 @@ static Test *tests_gnrc_ipv6_nib(void) new_TestFixture(test_handle_pkt__nbr_adv__invalid_opt_len), new_TestFixture(test_handle_pkt__nbr_adv__unspecified_src), new_TestFixture(test_handle_pkt__nbr_adv__unsolicited), + new_TestFixture(test_handle_pkt__nbr_adv__aro_not_my_eui64), + new_TestFixture(test_handle_pkt__nbr_adv__aro_duplicate), /* solicited tested in get_next_hop_l2addr */ + new_TestFixture(test_handle_pkt__rtr_sol), + new_TestFixture(test_handle_pkt__rtr_adv__invalid_src), + new_TestFixture(test_handle_pkt__rtr_adv__invalid_hl), + new_TestFixture(test_handle_pkt__rtr_adv__invalid_code), + new_TestFixture(test_handle_pkt__rtr_adv__invalid_icmpv6_len), + new_TestFixture(test_handle_pkt__rtr_adv__invalid_opt_len), + new_TestFixture(test_handle_pkt__rtr_adv__invalid_no_abro), + new_TestFixture(test_handle_pkt__rtr_adv__success_all_zero), + new_TestFixture(test_handle_pkt__rtr_adv__success_no_flags_no_opt), + new_TestFixture(test_handle_pkt__rtr_adv__success_no_opt), + new_TestFixture(test_handle_pkt__rtr_adv__success_sl2ao), + new_TestFixture(test_handle_pkt__rtr_adv__success_mtuo), + new_TestFixture(test_handle_pkt__rtr_adv__success_pio_00), + new_TestFixture(test_handle_pkt__rtr_adv__success_pio_L0), + new_TestFixture(test_handle_pkt__rtr_adv__success_pio_0A), + new_TestFixture(test_handle_pkt__rtr_adv__success_pio_LA), + new_TestFixture(test_handle_pkt__rtr_adv__success_6co_pio_0A), + new_TestFixture(test_handle_pkt__rtr_adv__success_6co_sl2ao_mtuo_pio_00), + new_TestFixture(test_handle_pkt__rtr_adv__success_6co_sl2ao_mtuo_pio_L0), + new_TestFixture(test_handle_pkt__rtr_adv__success_6co_sl2ao_mtuo_pio_0A), + new_TestFixture(test_handle_pkt__rtr_adv__success_6co_sl2ao_mtuo_pio_LA), /* gnrc_ipv6_nib_handle_timer_event not testable in this context since * we do not have access to the (internally defined) contexts required * for it */ + new_TestFixture(test_change_rtr_adv_iface), }; EMB_UNIT_TESTCALLER(tests, _set_up, NULL, fixtures); diff --git a/tests/gnrc_ndp2/Makefile b/tests/gnrc_ndp2/Makefile index fc374964e64c55137c0e65b9dcb17ed860897ab9..90d2dcdfc84627e5db0ad9d524ad805abe7e861c 100644 --- a/tests/gnrc_ndp2/Makefile +++ b/tests/gnrc_ndp2/Makefile @@ -2,9 +2,10 @@ APPLICATION = gnrc_ndp2 include ../Makefile.tests_common -BOARD_INSUFFICIENT_MEMORY := chronos nucleo32-f031 nucleo32-f042 nucleo32-l031 +BOARD_INSUFFICIENT_MEMORY := chronos nucleo32-f031 nucleo32-f042 nucleo32-l031 \ + telosb wsn430-v1_3b wsn430-v1_4 -USEMODULE += gnrc_ipv6_nib +USEMODULE += gnrc_ipv6_nib_router USEMODULE += gnrc_ndp2 USEMODULE += gnrc_netif2 USEMODULE += embunit diff --git a/tests/gnrc_sock_dns/Makefile b/tests/gnrc_sock_dns/Makefile index 8b65f7cc9b0882c799ac338f4632173d2a97cdd4..b6a0c0b46cd4abc09fb6b6a345911355f1db5e97 100644 --- a/tests/gnrc_sock_dns/Makefile +++ b/tests/gnrc_sock_dns/Makefile @@ -3,7 +3,9 @@ include ../Makefile.tests_common RIOTBASE ?= $(CURDIR)/../.. -BOARD_INSUFFICIENT_MEMORY := chronos telosb nucleo32-f042 nucleo32-f031 nucleo-f030 nucleo-l053 nucleo32-l031 stm32f0discovery +BOARD_INSUFFICIENT_MEMORY := chronos telosb nucleo32-f042 nucleo32-f031 \ + nucleo-f030 nucleo-l053 nucleo32-l031 \ + stm32f0discovery z1 USEMODULE += sock_dns USEMODULE += gnrc_sock_udp diff --git a/tests/gnrc_sock_ip/Makefile b/tests/gnrc_sock_ip/Makefile index b4ecfa77797177f33b165263e1c1e8cbe4e6d839..d289634d3335248734932b2efbedb6c054ec0f55 100644 --- a/tests/gnrc_sock_ip/Makefile +++ b/tests/gnrc_sock_ip/Makefile @@ -1,7 +1,7 @@ APPLICATION = gnrc_sock_ip include ../Makefile.tests_common -BOARD_INSUFFICIENT_MEMORY := nucleo32-f031 +BOARD_INSUFFICIENT_MEMORY := chronos nucleo32-f031 nucleo32-f042 nucleo32-l031 USEMODULE += gnrc_sock_ip USEMODULE += gnrc_ipv6 diff --git a/tests/gnrc_sock_udp/Makefile b/tests/gnrc_sock_udp/Makefile index d502c90b1ccad3984c8bb785f1c2ae9a5f50d587..df172f0e81986fcc016c7fe56328ea8842785ec2 100644 --- a/tests/gnrc_sock_udp/Makefile +++ b/tests/gnrc_sock_udp/Makefile @@ -1,7 +1,7 @@ APPLICATION = gnrc_sock_udp include ../Makefile.tests_common -BOARD_INSUFFICIENT_MEMORY := chronos nucleo32-f031 nucleo32-f042 +BOARD_INSUFFICIENT_MEMORY := chronos nucleo32-f031 nucleo32-f042 nucleo32-l031 USEMODULE += gnrc_sock_check_reuse USEMODULE += gnrc_sock_udp diff --git a/tests/unittests/tests-gnrc_ipv6_nib/Makefile.include b/tests/unittests/tests-gnrc_ipv6_nib/Makefile.include index 54383e241189049ba0e3efc48613477fc19d883c..24fa30541cc48ef900063fb7520d5ecafb4047cc 100644 --- a/tests/unittests/tests-gnrc_ipv6_nib/Makefile.include +++ b/tests/unittests/tests-gnrc_ipv6_nib/Makefile.include @@ -1,4 +1,5 @@ USEMODULE += gnrc_ipv6_nib +USEMODULE += gnrc_sixlowpan_nd # required for GNRC_IPV6_NIB_CONF_MULTIHOP_P6C CFLAGS += -DGNRC_IPV6_NIB_CONF_ROUTER=1 CFLAGS += -DGNRC_IPV6_NIB_NUMOF=16 diff --git a/tests/unittests/tests-ipv6_nc/Makefile b/tests/unittests/tests-ipv6_nc/Makefile deleted file mode 100644 index 48422e909a47d7cd428d10fa73825060ccc8d8c2..0000000000000000000000000000000000000000 --- a/tests/unittests/tests-ipv6_nc/Makefile +++ /dev/null @@ -1 +0,0 @@ -include $(RIOTBASE)/Makefile.base diff --git a/tests/unittests/tests-ipv6_nc/Makefile.include b/tests/unittests/tests-ipv6_nc/Makefile.include deleted file mode 100644 index d7162f43dc69390da4f3aa344b3384eab6e6b4d7..0000000000000000000000000000000000000000 --- a/tests/unittests/tests-ipv6_nc/Makefile.include +++ /dev/null @@ -1,2 +0,0 @@ -USEMODULE += gnrc_ipv6_nc -USEMODULE += gnrc_ipv6_netif diff --git a/tests/unittests/tests-ipv6_nc/tests-ipv6_nc.c b/tests/unittests/tests-ipv6_nc/tests-ipv6_nc.c deleted file mode 100644 index b97f239eeb0155a683bc7bccf4bbec6e87be66d2..0000000000000000000000000000000000000000 --- a/tests/unittests/tests-ipv6_nc/tests-ipv6_nc.c +++ /dev/null @@ -1,489 +0,0 @@ -/* - * Copyright (C) 2014 Martine Lenders <mlenders@inf.fu-berlin.de> - * - * This file is subject to the terms and conditions of the GNU Lesser - * General Public License v2.1. See the file LICENSE in the top level - * directory for more details. - */ - -/** - * @{ - * - * @file - */ -#include <errno.h> -#include <stdlib.h> - -#include "embUnit.h" - -#include "net/ipv6/addr.h" -#include "net/gnrc/ipv6/nc.h" -#include "net/gnrc/ipv6/netif.h" - -#include "unittests-constants.h" -#include "tests-ipv6_nc.h" - -/* default interface for testing */ -#define DEFAULT_TEST_NETIF (TEST_UINT16) -/* default IPv6 addr for testing */ -#define DEFAULT_TEST_IPV6_ADDR { { \ - 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, \ - 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f \ - } \ - } - -/* another interface for testing */ -#define OTHER_TEST_NETIF (TEST_UINT16 + TEST_UINT8) -/* another IPv6 addr for testing */ -#define OTHER_TEST_IPV6_ADDR { { \ - 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, \ - 0x18, 0x19, 0x1a, 0x1b, 0x1c, 0x1d, 0x1e, 0x1f \ - } \ - } - -/* a third IPv6 addr for testing */ -#define THIRD_TEST_IPV6_ADDR { { \ - 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, \ - 0x28, 0x29, 0x2a, 0x2b, 0x2c, 0x2d, 0x2e, 0x2f \ - } \ - } - -static void set_up(void) -{ - gnrc_ipv6_nc_init(); - gnrc_ipv6_netif_add(DEFAULT_TEST_NETIF); -} - -static void tear_down(void) -{ - /* remove all ncache entries, this is necesaary in case - * the last test initializes timers. */ - gnrc_ipv6_nc_init(); - gnrc_ipv6_netif_init(); -} - -static void test_ipv6_nc_add__address_registered(void) -{ - ipv6_addr_t addr = DEFAULT_TEST_IPV6_ADDR; - gnrc_ipv6_nc_t *entry1, *entry2; - - TEST_ASSERT_NOT_NULL((entry1 = gnrc_ipv6_nc_add(DEFAULT_TEST_NETIF, &addr, TEST_STRING4, - sizeof(TEST_STRING4), 0))); - TEST_ASSERT_NOT_NULL((entry2 = gnrc_ipv6_nc_add(DEFAULT_TEST_NETIF, &addr, TEST_STRING4, - sizeof(TEST_STRING4), 0))); - TEST_ASSERT(entry1 == entry2); -} - -static void test_ipv6_nc_add__address_NULL(void) -{ - TEST_ASSERT_NULL(gnrc_ipv6_nc_add(DEFAULT_TEST_NETIF, NULL, TEST_STRING4, - sizeof(TEST_STRING4), 0)); -} - -static void test_ipv6_nc_add__iface_KERNEL_PID_UNDEF(void) -{ - ipv6_addr_t addr = DEFAULT_TEST_IPV6_ADDR; - - TEST_ASSERT_NOT_NULL(gnrc_ipv6_nc_add(KERNEL_PID_UNDEF, &addr, TEST_STRING4, - sizeof(TEST_STRING4), 0)); -} - -static void test_ipv6_nc_add__addr_unspecified(void) -{ - ipv6_addr_t addr = IPV6_ADDR_UNSPECIFIED; - - TEST_ASSERT_NULL(gnrc_ipv6_nc_add(DEFAULT_TEST_NETIF, &addr, TEST_STRING4, - sizeof(TEST_STRING4), 0)); -} - -static void test_ipv6_nc_add__l2addr_too_long(void) -{ - ipv6_addr_t addr = DEFAULT_TEST_IPV6_ADDR; - - TEST_ASSERT_NULL(gnrc_ipv6_nc_add(DEFAULT_TEST_NETIF, &addr, TEST_STRING4, - GNRC_IPV6_NC_L2_ADDR_MAX + TEST_UINT8, 0)); -} - -static void test_ipv6_nc_add__full(void) -{ - ipv6_addr_t addr = DEFAULT_TEST_IPV6_ADDR; - - for (int i = 0; i < GNRC_IPV6_NC_SIZE; i++) { - TEST_ASSERT_NOT_NULL(gnrc_ipv6_nc_add(DEFAULT_TEST_NETIF, &addr, TEST_STRING4, - sizeof(TEST_STRING4), 0)); - addr.u16[7].u16++; - } - - TEST_ASSERT_NULL(gnrc_ipv6_nc_add(DEFAULT_TEST_NETIF, &addr, TEST_STRING4, - sizeof(TEST_STRING4), 0)); -} - -static void test_ipv6_nc_add__success(void) -{ - ipv6_addr_t addr = DEFAULT_TEST_IPV6_ADDR; - gnrc_ipv6_nc_t *entry1, *entry2; - - TEST_ASSERT_NOT_NULL((entry1 = gnrc_ipv6_nc_add(DEFAULT_TEST_NETIF, &addr, TEST_STRING4, - sizeof(TEST_STRING4), 0))); - - TEST_ASSERT_NOT_NULL((entry2 = gnrc_ipv6_nc_get(DEFAULT_TEST_NETIF, &addr))); - TEST_ASSERT(entry1 == entry2); -} - -static void test_ipv6_nc_add__address_update_despite_free_entry(void) -{ - ipv6_addr_t default_addr = DEFAULT_TEST_IPV6_ADDR; - ipv6_addr_t other_addr = OTHER_TEST_IPV6_ADDR; - gnrc_ipv6_nc_t *entry1, *entry2; - - TEST_ASSERT_NOT_NULL(gnrc_ipv6_nc_add(OTHER_TEST_NETIF, &other_addr, TEST_STRING4, - sizeof(TEST_STRING4), 0)); - TEST_ASSERT_NOT_NULL((entry1 = gnrc_ipv6_nc_add(DEFAULT_TEST_NETIF, &default_addr, TEST_STRING4, - sizeof(TEST_STRING4), 0))); - - /* create space by removing first entry and see if duplicate is still detected & updated */ - gnrc_ipv6_nc_remove(OTHER_TEST_NETIF, &other_addr); - TEST_ASSERT_NOT_NULL((entry2 = gnrc_ipv6_nc_add(DEFAULT_TEST_NETIF, &default_addr, TEST_STRING4, - sizeof(TEST_STRING4), 0))); - TEST_ASSERT(entry1 == entry2); -} - -static void test_ipv6_nc_remove__no_entry_pid(void) -{ - ipv6_addr_t addr = DEFAULT_TEST_IPV6_ADDR; - - test_ipv6_nc_add__success(); /* adds DEFAULT_TEST_IPV6_ADDR to DEFAULT_TEST_NETIF */ - gnrc_ipv6_nc_remove(OTHER_TEST_NETIF, &addr); - TEST_ASSERT_NOT_NULL(gnrc_ipv6_nc_get(DEFAULT_TEST_NETIF, &addr)); - TEST_ASSERT_NULL(gnrc_ipv6_nc_get(OTHER_TEST_NETIF, &addr)); -} - -static void test_ipv6_nc_remove__no_entry_addr1(void) -{ - ipv6_addr_t addr = OTHER_TEST_IPV6_ADDR; - ipv6_addr_t exp_addr = DEFAULT_TEST_IPV6_ADDR; - - test_ipv6_nc_add__success(); /* adds DEFAULT_TEST_IPV6_ADDR to DEFAULT_TEST_NETIF */ - gnrc_ipv6_nc_remove(DEFAULT_TEST_NETIF, &addr); - TEST_ASSERT_NOT_NULL(gnrc_ipv6_nc_get(DEFAULT_TEST_NETIF, &exp_addr)); - TEST_ASSERT_NULL(gnrc_ipv6_nc_get(DEFAULT_TEST_NETIF, &addr)); -} - -static void test_ipv6_nc_remove__no_entry_addr2(void) -{ - ipv6_addr_t addr = IPV6_ADDR_UNSPECIFIED; - ipv6_addr_t exp_addr = DEFAULT_TEST_IPV6_ADDR; - - test_ipv6_nc_add__success(); /* adds DEFAULT_TEST_IPV6_ADDR to DEFAULT_TEST_NETIF */ - gnrc_ipv6_nc_remove(DEFAULT_TEST_NETIF, &addr); - TEST_ASSERT_NOT_NULL(gnrc_ipv6_nc_get(DEFAULT_TEST_NETIF, &exp_addr)); - TEST_ASSERT_NULL(gnrc_ipv6_nc_get(DEFAULT_TEST_NETIF, &addr)); -} - -static void test_ipv6_nc_remove__success(void) -{ - ipv6_addr_t addr = DEFAULT_TEST_IPV6_ADDR; - - test_ipv6_nc_add__success(); /* adds DEFAULT_TEST_IPV6_ADDR to DEFAULT_TEST_NETIF */ - TEST_ASSERT_NOT_NULL(gnrc_ipv6_nc_get(DEFAULT_TEST_NETIF, &addr)); - gnrc_ipv6_nc_remove(DEFAULT_TEST_NETIF, &addr); - TEST_ASSERT_NULL(gnrc_ipv6_nc_get(DEFAULT_TEST_NETIF, &addr)); -} - -static void test_ipv6_nc_get__empty(void) -{ - ipv6_addr_t addr = DEFAULT_TEST_IPV6_ADDR; - - TEST_ASSERT_NULL(gnrc_ipv6_nc_get(DEFAULT_TEST_NETIF, &addr)); -} - -static void test_ipv6_nc_get__different_if(void) -{ - ipv6_addr_t addr = DEFAULT_TEST_IPV6_ADDR; - - test_ipv6_nc_add__success(); /* adds DEFAULT_TEST_IPV6_ADDR to DEFAULT_TEST_NETIF */ - - TEST_ASSERT_NULL(gnrc_ipv6_nc_get(OTHER_TEST_NETIF, &addr)); -} - -static void test_ipv6_nc_get__different_addr(void) -{ - ipv6_addr_t addr = OTHER_TEST_IPV6_ADDR; - - test_ipv6_nc_add__success(); /* adds DEFAULT_TEST_IPV6_ADDR to DEFAULT_TEST_NETIF */ - - TEST_ASSERT_NULL(gnrc_ipv6_nc_get(DEFAULT_TEST_NETIF, &addr)); -} - -static void test_ipv6_nc_get__success_if_local(void) -{ - ipv6_addr_t addr = DEFAULT_TEST_IPV6_ADDR; - gnrc_ipv6_nc_t *entry = NULL; - - test_ipv6_nc_add__success(); /* adds DEFAULT_TEST_IPV6_ADDR to DEFAULT_TEST_NETIF */ - - TEST_ASSERT_NOT_NULL((entry = gnrc_ipv6_nc_get(DEFAULT_TEST_NETIF, &addr))); - TEST_ASSERT_EQUAL_INT(DEFAULT_TEST_NETIF, entry->iface); - TEST_ASSERT(ipv6_addr_equal(&(entry->ipv6_addr), &addr)); - TEST_ASSERT_EQUAL_STRING(TEST_STRING4, (char *)entry->l2_addr); - TEST_ASSERT_EQUAL_INT(sizeof(TEST_STRING4), entry->l2_addr_len); - TEST_ASSERT_EQUAL_INT(0, entry->flags); -} - -static void test_ipv6_nc_get__success_if_global(void) -{ - ipv6_addr_t addr = DEFAULT_TEST_IPV6_ADDR; - gnrc_ipv6_nc_t *entry = NULL; - - test_ipv6_nc_add__success(); /* adds DEFAULT_TEST_IPV6_ADDR to DEFAULT_TEST_NETIF */ - - TEST_ASSERT_NOT_NULL((entry = gnrc_ipv6_nc_get(KERNEL_PID_UNDEF, &addr))); - TEST_ASSERT_EQUAL_INT(DEFAULT_TEST_NETIF, entry->iface); - TEST_ASSERT(ipv6_addr_equal(&(entry->ipv6_addr), &addr)); - TEST_ASSERT_EQUAL_STRING(TEST_STRING4, (char *)entry->l2_addr); - TEST_ASSERT_EQUAL_INT(sizeof(TEST_STRING4), entry->l2_addr_len); - TEST_ASSERT_EQUAL_INT(0, entry->flags); -} - -static void test_ipv6_nc_get_next__empty(void) -{ - TEST_ASSERT_NULL(gnrc_ipv6_nc_get_next(NULL)); -} - -static void test_ipv6_nc_get_next__1_entry(void) -{ - gnrc_ipv6_nc_t *entry = NULL; - - test_ipv6_nc_add__success(); /* adds DEFAULT_TEST_IPV6_ADDR to DEFAULT_TEST_NETIF */ - - TEST_ASSERT_NOT_NULL((entry = gnrc_ipv6_nc_get_next(NULL))); - TEST_ASSERT_NULL(gnrc_ipv6_nc_get_next(entry)); -} - -static void test_ipv6_nc_get_next__2_entries(void) -{ - ipv6_addr_t addr = OTHER_TEST_IPV6_ADDR; - gnrc_ipv6_nc_t *entry = NULL; - - test_ipv6_nc_add__success(); /* adds DEFAULT_TEST_IPV6_ADDR to DEFAULT_TEST_NETIF */ - TEST_ASSERT_NOT_NULL(gnrc_ipv6_nc_add(DEFAULT_TEST_NETIF, &addr, TEST_STRING8, - sizeof(TEST_STRING8) - 1, 0)); - - - TEST_ASSERT_NOT_NULL((entry = gnrc_ipv6_nc_get_next(NULL))); - TEST_ASSERT_NOT_NULL((entry = gnrc_ipv6_nc_get_next(entry))); - TEST_ASSERT_NULL(gnrc_ipv6_nc_get_next(entry)); -} - -static void test_ipv6_nc_get_next__holey(void) -{ - ipv6_addr_t addr1 = OTHER_TEST_IPV6_ADDR; - ipv6_addr_t addr2 = THIRD_TEST_IPV6_ADDR; - gnrc_ipv6_nc_t *entry = NULL, *exp_entry = NULL; - - /* adds DEFAULT_TEST_IPV6_ADDR and OTHER_TEST_IPV6_ADDR to DEFAULT_TEST_NETIF */ - test_ipv6_nc_get_next__2_entries(); - TEST_ASSERT_NOT_NULL(gnrc_ipv6_nc_add(DEFAULT_TEST_NETIF, &addr2, TEST_STRING8, - sizeof(TEST_STRING8) - 2, 0)); - TEST_ASSERT_NOT_NULL((exp_entry = gnrc_ipv6_nc_get(DEFAULT_TEST_NETIF, &addr2))); - gnrc_ipv6_nc_remove(DEFAULT_TEST_NETIF, &addr1); - - TEST_ASSERT_NOT_NULL((entry = gnrc_ipv6_nc_get_next(NULL))); - TEST_ASSERT_NOT_NULL((entry = gnrc_ipv6_nc_get_next(entry))); - TEST_ASSERT(exp_entry == entry); - TEST_ASSERT_NULL(gnrc_ipv6_nc_get_next(entry)); -} - -static void test_ipv6_nc_get_next_router__empty(void) -{ - TEST_ASSERT_NULL(gnrc_ipv6_nc_get_next_router(NULL)); -} - -static void test_ipv6_nc_get_next_router__first_entry(void) -{ - gnrc_ipv6_nc_t *entry = NULL; - - /* adds DEFAULT_TEST_IPV6_ADDR and OTHER_TEST_IPV6_ADDR to DEFAULT_TEST_NETIF */ - test_ipv6_nc_get_next__2_entries(); - TEST_ASSERT_NOT_NULL((entry = gnrc_ipv6_nc_get_next(NULL))); - entry->flags = (GNRC_IPV6_NC_STATE_REACHABLE << GNRC_IPV6_NC_STATE_POS); - entry->flags |= GNRC_IPV6_NC_IS_ROUTER; - - TEST_ASSERT_NOT_NULL((entry = gnrc_ipv6_nc_get_next_router(NULL))); - TEST_ASSERT_NULL(gnrc_ipv6_nc_get_next_router(entry)); -} - -static void test_ipv6_nc_get_next_router__second_entry(void) -{ - gnrc_ipv6_nc_t *entry1 = NULL, *entry2 = NULL; - - /* adds DEFAULT_TEST_IPV6_ADDR and OTHER_TEST_IPV6_ADDR to DEFAULT_TEST_NETIF */ - test_ipv6_nc_get_next__2_entries(); - TEST_ASSERT_NOT_NULL((entry1 = gnrc_ipv6_nc_get_next(NULL))); - TEST_ASSERT_NOT_NULL((entry2 = gnrc_ipv6_nc_get_next(entry1))); - entry2->flags = (GNRC_IPV6_NC_STATE_REACHABLE << GNRC_IPV6_NC_STATE_POS); - entry2->flags |= GNRC_IPV6_NC_IS_ROUTER; - - TEST_ASSERT_NOT_NULL((entry1 = gnrc_ipv6_nc_get_next_router(NULL))); - TEST_ASSERT(entry2 == entry1); - TEST_ASSERT_NULL(gnrc_ipv6_nc_get_next_router(entry1)); -} - -static void test_ipv6_nc_is_reachable__incomplete(void) -{ - ipv6_addr_t addr = DEFAULT_TEST_IPV6_ADDR; - gnrc_ipv6_nc_t *entry = NULL; - - test_ipv6_nc_add__success(); /* adds DEFAULT_TEST_IPV6_ADDR to DEFAULT_TEST_NETIF */ - - TEST_ASSERT_NOT_NULL((entry = gnrc_ipv6_nc_get(KERNEL_PID_UNDEF, &addr))); - entry->flags = (GNRC_IPV6_NC_STATE_INCOMPLETE << GNRC_IPV6_NC_STATE_POS); - TEST_ASSERT(!gnrc_ipv6_nc_is_reachable(entry)); -} - -static void test_ipv6_nc_is_reachable__reachable(void) -{ - ipv6_addr_t addr = DEFAULT_TEST_IPV6_ADDR; - gnrc_ipv6_nc_t *entry = NULL; - - test_ipv6_nc_add__success(); /* adds DEFAULT_TEST_IPV6_ADDR to DEFAULT_TEST_NETIF */ - - TEST_ASSERT_NOT_NULL((entry = gnrc_ipv6_nc_get(DEFAULT_TEST_NETIF, &addr))); - entry->flags = (GNRC_IPV6_NC_STATE_REACHABLE << GNRC_IPV6_NC_STATE_POS); - TEST_ASSERT(gnrc_ipv6_nc_is_reachable(entry)); -} - -static void test_ipv6_nc_is_reachable__unmanaged(void) -{ - ipv6_addr_t addr = DEFAULT_TEST_IPV6_ADDR; - gnrc_ipv6_nc_t *entry = NULL; - - test_ipv6_nc_add__success(); /* adds DEFAULT_TEST_IPV6_ADDR to DEFAULT_TEST_NETIF */ - - TEST_ASSERT_NOT_NULL((entry = gnrc_ipv6_nc_get(DEFAULT_TEST_NETIF, &addr))); - entry->flags = (GNRC_IPV6_NC_STATE_UNMANAGED << GNRC_IPV6_NC_STATE_POS); - TEST_ASSERT(gnrc_ipv6_nc_is_reachable(entry)); -} - -static void test_ipv6_nc_still_reachable__incomplete(void) -{ - ipv6_addr_t addr = DEFAULT_TEST_IPV6_ADDR; - gnrc_ipv6_nc_t *entry = NULL; - - /* adds DEFAULT_TEST_IPV6_ADDR to DEFAULT_TEST_NETIF and sets flags to - * (GNRC_IPV6_NC_STATE_INCOMPLETE << GNRC_IPV6_NC_STATE_POS) */ - test_ipv6_nc_is_reachable__incomplete(); - - TEST_ASSERT_NOT_NULL((entry = gnrc_ipv6_nc_get(KERNEL_PID_UNDEF, &addr))); - TEST_ASSERT(!gnrc_ipv6_nc_is_reachable(entry)); - TEST_ASSERT_NOT_NULL(gnrc_ipv6_nc_still_reachable(&addr)); - TEST_ASSERT(!gnrc_ipv6_nc_is_reachable(entry)); -} - -static void test_ipv6_nc_still_reachable__success(void) -{ - ipv6_addr_t addr = DEFAULT_TEST_IPV6_ADDR; - gnrc_ipv6_nc_t *entry = NULL; - - /* adds DEFAULT_TEST_IPV6_ADDR to DEFAULT_TEST_NETIF and sets flags to - * (GNRC_IPV6_NC_STATE_REACHABLE << GNRC_IPV6_NC_STATE_POS) */ - test_ipv6_nc_is_reachable__reachable(); - - TEST_ASSERT_NOT_NULL((entry = gnrc_ipv6_nc_get(KERNEL_PID_UNDEF, &addr))); - TEST_ASSERT(gnrc_ipv6_nc_is_reachable(entry)); - - entry->flags = (GNRC_IPV6_NC_STATE_STALE << GNRC_IPV6_NC_STATE_POS); - - TEST_ASSERT_NOT_NULL(gnrc_ipv6_nc_still_reachable(&addr)); - TEST_ASSERT(gnrc_ipv6_nc_is_reachable(entry)); -} - -static void test_ipv6_nc_get_l2_addr__NULL_entry(void) -{ - gnrc_ipv6_nc_t *entry = NULL; - uint8_t l2_addr[GNRC_IPV6_NC_L2_ADDR_MAX]; - uint8_t l2_addr_len = 0; - - TEST_ASSERT_EQUAL_INT(KERNEL_PID_UNDEF, - gnrc_ipv6_nc_get_l2_addr(l2_addr, &l2_addr_len, entry)); -} - -static void test_ipv6_nc_get_l2_addr__unreachable(void) -{ - ipv6_addr_t addr = DEFAULT_TEST_IPV6_ADDR; - gnrc_ipv6_nc_t *entry = NULL; - uint8_t l2_addr[GNRC_IPV6_NC_L2_ADDR_MAX]; - uint8_t l2_addr_len = 0; - - test_ipv6_nc_add__success(); /* adds DEFAULT_TEST_IPV6_ADDR to DEFAULT_TEST_NETIF */ - - TEST_ASSERT_NOT_NULL((entry = gnrc_ipv6_nc_get(KERNEL_PID_UNDEF, &addr))); - entry->flags = (GNRC_IPV6_NC_STATE_INCOMPLETE << GNRC_IPV6_NC_STATE_POS); - TEST_ASSERT_EQUAL_INT(KERNEL_PID_UNDEF, - gnrc_ipv6_nc_get_l2_addr(l2_addr, &l2_addr_len, entry)); -} - -static void test_ipv6_nc_get_l2_addr__reachable(void) -{ - ipv6_addr_t addr = DEFAULT_TEST_IPV6_ADDR; - gnrc_ipv6_nc_t *entry = NULL; - uint8_t l2_addr[GNRC_IPV6_NC_L2_ADDR_MAX]; - uint8_t l2_addr_len = 0; - - test_ipv6_nc_add__success(); /* adds DEFAULT_TEST_IPV6_ADDR to DEFAULT_TEST_NETIF */ - - TEST_ASSERT_NOT_NULL((entry = gnrc_ipv6_nc_get(KERNEL_PID_UNDEF, &addr))); - entry->flags = (GNRC_IPV6_NC_STATE_REACHABLE << GNRC_IPV6_NC_STATE_POS); - TEST_ASSERT_EQUAL_INT(DEFAULT_TEST_NETIF, - gnrc_ipv6_nc_get_l2_addr(l2_addr, &l2_addr_len, entry)); - TEST_ASSERT_EQUAL_STRING(TEST_STRING4, (char *)l2_addr); - TEST_ASSERT_EQUAL_INT(sizeof(TEST_STRING4), l2_addr_len); -} - -Test *tests_ipv6_nc_tests(void) -{ - EMB_UNIT_TESTFIXTURES(fixtures) { - new_TestFixture(test_ipv6_nc_add__address_registered), - new_TestFixture(test_ipv6_nc_add__address_NULL), - new_TestFixture(test_ipv6_nc_add__iface_KERNEL_PID_UNDEF), - new_TestFixture(test_ipv6_nc_add__addr_unspecified), - new_TestFixture(test_ipv6_nc_add__l2addr_too_long), - new_TestFixture(test_ipv6_nc_add__full), - new_TestFixture(test_ipv6_nc_add__success), - new_TestFixture(test_ipv6_nc_add__address_update_despite_free_entry), - new_TestFixture(test_ipv6_nc_remove__no_entry_pid), - new_TestFixture(test_ipv6_nc_remove__no_entry_addr1), - new_TestFixture(test_ipv6_nc_remove__no_entry_addr2), - new_TestFixture(test_ipv6_nc_remove__success), - new_TestFixture(test_ipv6_nc_get__empty), - new_TestFixture(test_ipv6_nc_get__different_if), - new_TestFixture(test_ipv6_nc_get__different_addr), - new_TestFixture(test_ipv6_nc_get__success_if_local), - new_TestFixture(test_ipv6_nc_get__success_if_global), - new_TestFixture(test_ipv6_nc_get_next__empty), - new_TestFixture(test_ipv6_nc_get_next__1_entry), - new_TestFixture(test_ipv6_nc_get_next__2_entries), - new_TestFixture(test_ipv6_nc_get_next__holey), - new_TestFixture(test_ipv6_nc_get_next_router__empty), - new_TestFixture(test_ipv6_nc_get_next_router__first_entry), - new_TestFixture(test_ipv6_nc_get_next_router__second_entry), - new_TestFixture(test_ipv6_nc_is_reachable__incomplete), - new_TestFixture(test_ipv6_nc_is_reachable__reachable), - new_TestFixture(test_ipv6_nc_is_reachable__unmanaged), - new_TestFixture(test_ipv6_nc_still_reachable__incomplete), - new_TestFixture(test_ipv6_nc_still_reachable__success), - new_TestFixture(test_ipv6_nc_get_l2_addr__NULL_entry), - new_TestFixture(test_ipv6_nc_get_l2_addr__unreachable), - new_TestFixture(test_ipv6_nc_get_l2_addr__reachable), - }; - - EMB_UNIT_TESTCALLER(ipv6_nc_tests, set_up, tear_down, fixtures); - - return (Test *)&ipv6_nc_tests; -} - -void tests_ipv6_nc(void) -{ - TESTS_RUN(tests_ipv6_nc_tests()); -} -/** @} */ diff --git a/tests/unittests/tests-ipv6_nc/tests-ipv6_nc.h b/tests/unittests/tests-ipv6_nc/tests-ipv6_nc.h deleted file mode 100644 index 457c6baa9a7455cccfc0d1ae3f43efc4472c9681..0000000000000000000000000000000000000000 --- a/tests/unittests/tests-ipv6_nc/tests-ipv6_nc.h +++ /dev/null @@ -1,37 +0,0 @@ -/* - * Copyright (C) 2014 Martin Lenders - * - * This file is subject to the terms and conditions of the GNU Lesser - * General Public License v2.1. See the file LICENSE in the top level - * directory for more details. - */ - -/** - * @addtogroup unittests - * @{ - * - * @file - * @brief Unittests for the ``ipv6_nc`` module - * - * @author Martine Lenders <mlenders@inf.fu-berlin.de> - */ -#ifndef TESTS_IPV6_NC_H -#define TESTS_IPV6_NC_H - -#include "embUnit.h" - -#ifdef __cplusplus -extern "C" { -#endif - -/** - * @brief The entry point of this test suite. - */ -void tests_ipv6_nc(void); - -#ifdef __cplusplus -} -#endif - -#endif /* TESTS_IPV6_NC_H */ -/** @} */ diff --git a/tests/unittests/tests-ipv6_netif/Makefile b/tests/unittests/tests-ipv6_netif/Makefile deleted file mode 100644 index 48422e909a47d7cd428d10fa73825060ccc8d8c2..0000000000000000000000000000000000000000 --- a/tests/unittests/tests-ipv6_netif/Makefile +++ /dev/null @@ -1 +0,0 @@ -include $(RIOTBASE)/Makefile.base diff --git a/tests/unittests/tests-ipv6_netif/Makefile.include b/tests/unittests/tests-ipv6_netif/Makefile.include deleted file mode 100644 index 5a15cf42f54d7569f5baa7bae7f2bb8e6edae60d..0000000000000000000000000000000000000000 --- a/tests/unittests/tests-ipv6_netif/Makefile.include +++ /dev/null @@ -1,6 +0,0 @@ -USEMODULE += ipv6_addr -USEMODULE += gnrc_ipv6_netif -USEMODULE += gnrc_netif -USEMODULE += gnrc_ndp_node - -CFLAGS += -DGNRC_NETIF_NUMOF=3 diff --git a/tests/unittests/tests-ipv6_netif/tests-ipv6_netif.c b/tests/unittests/tests-ipv6_netif/tests-ipv6_netif.c deleted file mode 100644 index a4150474619e311a0aba8d43e1f022a64e78b4ed..0000000000000000000000000000000000000000 --- a/tests/unittests/tests-ipv6_netif/tests-ipv6_netif.c +++ /dev/null @@ -1,583 +0,0 @@ -/* - * Copyright (C) 2015 Martine Lenders <mlenders@inf.fu-berlin.de> - * - * This file is subject to the terms and conditions of the GNU Lesser - * General Public License v2.1. See the file LICENSE in the top level - * directory for more details. - */ - -/** - * @{ - * - * @file - */ -#include <errno.h> -#include <stdint.h> -#include <stdlib.h> - -#include "embUnit/embUnit.h" - -#include "byteorder.h" -#include "net/gnrc/netif.h" -#include "net/gnrc/ipv6/netif.h" - -#include "unittests-constants.h" -#include "tests-ipv6_netif.h" - -/* default interface for testing */ -#define DEFAULT_TEST_NETIF (TEST_UINT16) -/* default IPv6 addr for testing */ -#define DEFAULT_TEST_IPV6_ADDR { { \ - 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, \ - 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f \ - } \ - } -/* default IPv6 prefix length */ -#define DEFAULT_TEST_PREFIX_LEN (18) - -/* another interface for testing */ -#define OTHER_TEST_NETIF (TEST_UINT16 + TEST_UINT8) -/* another IPv6 addr for testing */ -#define OTHER_TEST_IPV6_ADDR { { \ - 0x0f, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, \ - 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f \ - } \ - } -/* matches DEFAULT_TEST_IPV6_ADDR with 18 byte */ -#define DEFAULT_TEST_IPV6_PREFIX18 { { \ - 0x00, 0x01, 0x22, 0x03, 0x04, 0x05, 0x06, 0x07, \ - 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f \ - } \ - } -/* matches DEFAULT_TEST_IPV6_ADDR with 23 byte */ -#define DEFAULT_TEST_IPV6_PREFIX23 { { \ - 0x00, 0x01, 0x03, 0x03, 0x04, 0x05, 0x06, 0x07, \ - 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f \ - } \ - } -/* matches DEFAULT_TEST_IPV6_ADDR with 64 byte */ -#define DEFAULT_TEST_IPV6_PREFIX64 { { \ - 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, \ - 0x88, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f \ - } \ - } - -static void set_up(void) -{ - gnrc_netif_init(); - gnrc_ipv6_netif_init(); -} - -static void test_ipv6_netif_add__success(void) -{ - gnrc_ipv6_netif_t *entry; - - gnrc_ipv6_netif_add(DEFAULT_TEST_NETIF); - - TEST_ASSERT_NOT_NULL((entry = gnrc_ipv6_netif_get(DEFAULT_TEST_NETIF))); - TEST_ASSERT_EQUAL_INT(DEFAULT_TEST_NETIF, entry->pid); -} - -static void test_netif_add__success_with_ipv6(void) -{ - kernel_pid_t pids[GNRC_NETIF_NUMOF]; - size_t pid_num; - gnrc_ipv6_netif_t *entry; - ipv6_addr_t exp_addr = IPV6_ADDR_ALL_NODES_LINK_LOCAL; - - gnrc_netif_add(DEFAULT_TEST_NETIF); - - TEST_ASSERT_EQUAL_INT(1, (pid_num = gnrc_netif_get(pids))); - TEST_ASSERT_EQUAL_INT(1, pid_num); - TEST_ASSERT_EQUAL_INT(DEFAULT_TEST_NETIF, pids[0]); - TEST_ASSERT_NOT_NULL((entry = gnrc_ipv6_netif_get(DEFAULT_TEST_NETIF))); - TEST_ASSERT_EQUAL_INT(DEFAULT_TEST_NETIF, entry->pid); - TEST_ASSERT_EQUAL_STRING((char *)exp_addr.u8, (char *)entry->addrs[0].addr.u8); -} - -static void test_ipv6_netif_add__despite_free_entry(void) -{ - /* Tests for possible duplicates as described in http://github.com/RIOT-OS/RIOT/issues/2965 */ - - gnrc_ipv6_netif_add(OTHER_TEST_NETIF); - test_ipv6_netif_add__success(); /* adds DEFAULT_TEST_NETIF as interface */ - - /* create space by removing first entry */ - gnrc_ipv6_netif_remove(OTHER_TEST_NETIF); - - /* add DEFAULT_TEST_NETIF yet again and remove it */ - test_ipv6_netif_add__success(); - gnrc_ipv6_netif_remove(DEFAULT_TEST_NETIF); - - /* see if there's a duplicate left */ - TEST_ASSERT_NULL(gnrc_ipv6_netif_get(DEFAULT_TEST_NETIF)); -} - -static void test_ipv6_netif_remove__not_allocated(void) -{ - test_ipv6_netif_add__success(); /* adds DEFAULT_TEST_NETIF as interface */ - gnrc_ipv6_netif_remove(OTHER_TEST_NETIF); - TEST_ASSERT_NULL(gnrc_ipv6_netif_get(OTHER_TEST_NETIF)); - TEST_ASSERT_NOT_NULL(gnrc_ipv6_netif_get(DEFAULT_TEST_NETIF)); -} - -static void test_ipv6_netif_remove__success(void) -{ - test_ipv6_netif_add__success(); /* adds DEFAULT_TEST_NETIF as interface */ - gnrc_ipv6_netif_remove(DEFAULT_TEST_NETIF); - TEST_ASSERT_NULL(gnrc_ipv6_netif_get(DEFAULT_TEST_NETIF)); -} - -static void test_ipv6_netif_get__empty(void) -{ - for (kernel_pid_t pid = KERNEL_PID_FIRST; pid <= KERNEL_PID_LAST; pid++) { - TEST_ASSERT_NULL(gnrc_ipv6_netif_get(pid)); - } -} - -static void test_ipv6_netif_add_addr__no_iface1(void) -{ - ipv6_addr_t addr = DEFAULT_TEST_IPV6_ADDR; - - TEST_ASSERT_NULL(gnrc_ipv6_netif_add_addr(DEFAULT_TEST_NETIF, &addr, DEFAULT_TEST_PREFIX_LEN, 0)); -} - -static void test_ipv6_netif_add_addr__no_iface2(void) -{ - TEST_ASSERT_NULL(gnrc_ipv6_netif_add_addr(DEFAULT_TEST_NETIF, NULL, DEFAULT_TEST_PREFIX_LEN, 0)); -} - -static void test_ipv6_netif_add_addr__addr_NULL(void) -{ - test_ipv6_netif_add__success(); /* adds DEFAULT_TEST_NETIF as interface */ - - TEST_ASSERT_NULL(gnrc_ipv6_netif_add_addr(DEFAULT_TEST_NETIF, NULL, DEFAULT_TEST_PREFIX_LEN, 0)); -} - -static void test_ipv6_netif_add_addr__addr_unspecified(void) -{ - ipv6_addr_t addr = IPV6_ADDR_UNSPECIFIED; - - test_ipv6_netif_add__success(); /* adds DEFAULT_TEST_NETIF as interface */ - - TEST_ASSERT_NULL(gnrc_ipv6_netif_add_addr(DEFAULT_TEST_NETIF, &addr, DEFAULT_TEST_PREFIX_LEN, 0)); -} - -static void test_ipv6_netif_add_addr__full(void) -{ - ipv6_addr_t addr = DEFAULT_TEST_IPV6_ADDR, *res = &addr; - int i; - - /* make link local to avoid automatic link local adding */ - ipv6_addr_set_link_local_prefix(&addr); - - test_ipv6_netif_add__success(); /* adds DEFAULT_TEST_NETIF as interface */ - - for (i = 0; res != NULL; i++, addr.u8[15]++) { - res = gnrc_ipv6_netif_add_addr(DEFAULT_TEST_NETIF, &addr, DEFAULT_TEST_PREFIX_LEN, 0); - } -} - -static void test_ipv6_netif_add_addr__success(void) -{ - ipv6_addr_t addr = DEFAULT_TEST_IPV6_ADDR; - - test_ipv6_netif_add__success(); /* adds DEFAULT_TEST_NETIF as interface */ - - TEST_ASSERT_NOT_NULL(gnrc_ipv6_netif_add_addr(DEFAULT_TEST_NETIF, &addr, - DEFAULT_TEST_PREFIX_LEN, 0)); -} - -static void test_ipv6_netif_add_addr__despite_free_entry(void) -{ - /* Tests for possible duplicates as described in http://github.com/RIOT-OS/RIOT/issues/2965 */ - ipv6_addr_t *entry_1; - ipv6_addr_t *entry_2; - - ipv6_addr_t default_addr = DEFAULT_TEST_IPV6_ADDR; - ipv6_addr_t sol_addr; - - test_ipv6_netif_add__success(); /* adds DEFAULT_TEST_NETIF as interface */ - - /* add addresses to the interface */ - TEST_ASSERT_NOT_NULL((entry_1 = gnrc_ipv6_netif_add_addr(DEFAULT_TEST_NETIF, &default_addr, - DEFAULT_TEST_PREFIX_LEN, 0))); - - /* remove default_addr, but not the corresponding solicited-node addr that - * came with it */ - gnrc_ipv6_netif_remove_addr(DEFAULT_TEST_NETIF, &default_addr); - - /* create and re-add corresponding solicited node address and check that it - * hasn't taken the old place of default_addr*/ - ipv6_addr_set_solicited_nodes(&sol_addr, &default_addr); - TEST_ASSERT_NOT_NULL((entry_2 = gnrc_ipv6_netif_add_addr(DEFAULT_TEST_NETIF, &sol_addr, - DEFAULT_TEST_PREFIX_LEN, 0))); - - TEST_ASSERT(entry_1 != entry_2); -} - -static void test_ipv6_netif_remove_addr__not_allocated(void) -{ - ipv6_addr_t addr = DEFAULT_TEST_IPV6_ADDR; - ipv6_addr_t other_addr = OTHER_TEST_IPV6_ADDR; - - test_ipv6_netif_add_addr__success(); /* adds DEFAULT_TEST_IPV6_ADDR to - * DEFAULT_TEST_NETIF */ - - gnrc_ipv6_netif_remove_addr(DEFAULT_TEST_NETIF, &other_addr); - - TEST_ASSERT_NULL(gnrc_ipv6_netif_find_addr(DEFAULT_TEST_NETIF, &other_addr)); - TEST_ASSERT_NOT_NULL(gnrc_ipv6_netif_find_addr(DEFAULT_TEST_NETIF, &addr)); -} - -static void test_ipv6_netif_remove_addr__success(void) -{ - ipv6_addr_t addr = DEFAULT_TEST_IPV6_ADDR; - - test_ipv6_netif_add_addr__success(); /* adds DEFAULT_TEST_IPV6_ADDR to - * DEFAULT_TEST_NETIF */ - - gnrc_ipv6_netif_remove_addr(DEFAULT_TEST_NETIF, &addr); - - TEST_ASSERT_NULL(gnrc_ipv6_netif_find_addr(DEFAULT_TEST_NETIF, &addr)); -} - -static void test_ipv6_netif_reset_addr__success(void) -{ - ipv6_addr_t addr = DEFAULT_TEST_IPV6_ADDR; - - test_ipv6_netif_add_addr__success(); /* adds DEFAULT_TEST_IPV6_ADDR to - * DEFAULT_TEST_NETIF */ - - gnrc_ipv6_netif_reset_addr(DEFAULT_TEST_NETIF); - - TEST_ASSERT_NULL(gnrc_ipv6_netif_find_addr(DEFAULT_TEST_NETIF, &addr)); -} - -static void test_ipv6_netif_find_by_addr__empty(void) -{ - ipv6_addr_t addr = DEFAULT_TEST_IPV6_ADDR; - ipv6_addr_t *out = NULL; - - TEST_ASSERT_EQUAL_INT(KERNEL_PID_UNDEF, gnrc_ipv6_netif_find_by_addr(&out, &addr)); - TEST_ASSERT_NULL(out); -} - -static void test_ipv6_netif_find_by_addr__success(void) -{ - ipv6_addr_t addr = DEFAULT_TEST_IPV6_ADDR; - ipv6_addr_t *out = NULL; - - test_ipv6_netif_add_addr__success(); /* adds DEFAULT_TEST_IPV6_ADDR to - * DEFAULT_TEST_NETIF */ - - TEST_ASSERT_EQUAL_INT(DEFAULT_TEST_NETIF, gnrc_ipv6_netif_find_by_addr(&out, &addr)); - TEST_ASSERT_NOT_NULL(out); - TEST_ASSERT(out != &addr); - TEST_ASSERT_EQUAL_INT(true, ipv6_addr_equal(out, &addr)); -} - -static void test_ipv6_netif_find_addr__no_iface(void) -{ - ipv6_addr_t addr = DEFAULT_TEST_IPV6_ADDR; - - TEST_ASSERT_NULL(gnrc_ipv6_netif_find_addr(DEFAULT_TEST_NETIF, &addr)); -} - -static void test_ipv6_netif_find_addr__wrong_iface(void) -{ - ipv6_addr_t addr = DEFAULT_TEST_IPV6_ADDR; - - test_ipv6_netif_add_addr__success(); /* adds DEFAULT_TEST_IPV6_ADDR to - * DEFAULT_TEST_NETIF */ - - TEST_ASSERT_NULL(gnrc_ipv6_netif_find_addr(OTHER_TEST_NETIF, &addr)); -} - -static void test_ipv6_netif_find_addr__wrong_addr(void) -{ - ipv6_addr_t addr = OTHER_TEST_IPV6_ADDR; - - test_ipv6_netif_add_addr__success(); /* adds DEFAULT_TEST_IPV6_ADDR to - * DEFAULT_TEST_NETIF */ - - TEST_ASSERT_NULL(gnrc_ipv6_netif_find_addr(DEFAULT_TEST_NETIF, &addr)); -} - -static void test_ipv6_netif_find_addr__success(void) -{ - ipv6_addr_t addr = DEFAULT_TEST_IPV6_ADDR; - ipv6_addr_t *out = NULL; - - test_ipv6_netif_add_addr__success(); /* adds DEFAULT_TEST_IPV6_ADDR to - * DEFAULT_TEST_NETIF */ - - TEST_ASSERT_NOT_NULL((out = gnrc_ipv6_netif_find_addr(DEFAULT_TEST_NETIF, &addr))); - TEST_ASSERT(out != &addr); - TEST_ASSERT_EQUAL_INT(true, ipv6_addr_equal(out, &addr)); - - /* also test for link local address */ - ipv6_addr_set_solicited_nodes(&addr, &addr); - TEST_ASSERT_NOT_NULL((out = gnrc_ipv6_netif_find_addr(DEFAULT_TEST_NETIF, &addr))); - TEST_ASSERT_EQUAL_INT(true, ipv6_addr_equal(out, &addr)); -} - -static void test_ipv6_netif_find_by_prefix__success1(void) -{ - ipv6_addr_t addr = DEFAULT_TEST_IPV6_PREFIX23; - ipv6_addr_t *out = NULL; - - test_ipv6_netif_add_addr__success(); /* adds DEFAULT_TEST_IPV6_ADDR to - * DEFAULT_TEST_NETIF */ - - TEST_ASSERT_EQUAL_INT(DEFAULT_TEST_NETIF, gnrc_ipv6_netif_find_by_prefix(&out, &addr)); - TEST_ASSERT_NOT_NULL(out); - TEST_ASSERT(out != &addr); - TEST_ASSERT_EQUAL_INT(23, ipv6_addr_match_prefix(out, &addr)); -} - -static void test_ipv6_netif_find_by_prefix__success2(void) -{ - ipv6_addr_t addr = DEFAULT_TEST_IPV6_PREFIX18; - ipv6_addr_t *out = NULL; - - test_ipv6_netif_add_addr__success(); /* adds DEFAULT_TEST_IPV6_ADDR to - * DEFAULT_TEST_NETIF */ - - TEST_ASSERT_EQUAL_INT(DEFAULT_TEST_NETIF, gnrc_ipv6_netif_find_by_prefix(&out, &addr)); - TEST_ASSERT_NOT_NULL(out); - TEST_ASSERT(out != &addr); - TEST_ASSERT_EQUAL_INT(18, ipv6_addr_match_prefix(out, &addr)); -} - -static void test_ipv6_netif_find_by_prefix__success3(void) -{ - ipv6_addr_t addr = DEFAULT_TEST_IPV6_PREFIX64; - ipv6_addr_t *out = NULL; - - test_ipv6_netif_add_addr__success(); /* adds DEFAULT_TEST_IPV6_ADDR to - * DEFAULT_TEST_NETIF */ - - TEST_ASSERT_EQUAL_INT(DEFAULT_TEST_NETIF, gnrc_ipv6_netif_find_by_prefix(&out, &addr)); - TEST_ASSERT_NOT_NULL(out); - TEST_ASSERT(out != &addr); - TEST_ASSERT_EQUAL_INT(64, ipv6_addr_match_prefix(out, &addr)); -} - -static void test_ipv6_netif_match_prefix__success1(void) -{ - ipv6_addr_t addr = DEFAULT_TEST_IPV6_PREFIX23; - ipv6_addr_t *out = NULL; - - test_ipv6_netif_add_addr__success(); /* adds DEFAULT_TEST_IPV6_ADDR to - * DEFAULT_TEST_NETIF */ - - TEST_ASSERT_NOT_NULL((out = gnrc_ipv6_netif_match_prefix(DEFAULT_TEST_NETIF, &addr))); - TEST_ASSERT(out != &addr); - TEST_ASSERT_EQUAL_INT(23, ipv6_addr_match_prefix(out, &addr)); -} - -static void test_ipv6_netif_match_prefix__success2(void) -{ - ipv6_addr_t addr = DEFAULT_TEST_IPV6_PREFIX18; - ipv6_addr_t *out = NULL; - - test_ipv6_netif_add_addr__success(); /* adds DEFAULT_TEST_IPV6_ADDR to - * DEFAULT_TEST_NETIF */ - - TEST_ASSERT_NOT_NULL((out = gnrc_ipv6_netif_match_prefix(DEFAULT_TEST_NETIF, &addr))); - TEST_ASSERT(out != &addr); - TEST_ASSERT_EQUAL_INT(18, ipv6_addr_match_prefix(out, &addr)); -} - -static void test_ipv6_netif_match_prefix__success3(void) -{ - ipv6_addr_t addr = DEFAULT_TEST_IPV6_PREFIX64; - ipv6_addr_t *out = NULL; - - test_ipv6_netif_add_addr__success(); /* adds DEFAULT_TEST_IPV6_ADDR to - * DEFAULT_TEST_NETIF */ - - TEST_ASSERT_NOT_NULL((out = gnrc_ipv6_netif_match_prefix(DEFAULT_TEST_NETIF, &addr))); - TEST_ASSERT(out != &addr); - TEST_ASSERT_EQUAL_INT(64, ipv6_addr_match_prefix(out, &addr)); -} - -static void test_ipv6_netif_find_best_src_addr__no_unicast(void) -{ - ipv6_addr_t ll_dst_addr = IPV6_ADDR_UNSPECIFIED; - ipv6_addr_t mc_addr1 = IPV6_ADDR_ALL_NODES_LINK_LOCAL; - ipv6_addr_t mc_addr2 = IPV6_ADDR_ALL_ROUTERS_SITE_LOCAL; - - ll_dst_addr.u8[15] = 1; - ipv6_addr_set_link_local_prefix(&ll_dst_addr); - - test_ipv6_netif_add__success(); /* adds DEFAULT_TEST_NETIF as interface */ - TEST_ASSERT_NOT_NULL(gnrc_ipv6_netif_add_addr(DEFAULT_TEST_NETIF, &mc_addr1, - DEFAULT_TEST_PREFIX_LEN, 0)); - TEST_ASSERT_NOT_NULL(gnrc_ipv6_netif_add_addr(DEFAULT_TEST_NETIF, &mc_addr2, - DEFAULT_TEST_PREFIX_LEN, 0)); - - TEST_ASSERT_NULL(gnrc_ipv6_netif_find_best_src_addr(DEFAULT_TEST_NETIF, &ll_dst_addr, false)); -} - -static void test_ipv6_netif_find_best_src_addr__success(void) -{ - ipv6_addr_t ll_addr1 = IPV6_ADDR_UNSPECIFIED; - ipv6_addr_t ll_addr2 = IPV6_ADDR_UNSPECIFIED; - ipv6_addr_t mc_addr = IPV6_ADDR_ALL_NODES_LINK_LOCAL; - ipv6_addr_t *out = NULL; - - ll_addr1.u8[15] = 1; - ipv6_addr_set_link_local_prefix(&ll_addr1); - ll_addr2.u8[15] = 2; - ipv6_addr_set_link_local_prefix(&ll_addr2); - - TEST_ASSERT_EQUAL_INT(126, ipv6_addr_match_prefix(&ll_addr2, &ll_addr1)); - - test_ipv6_netif_add__success(); /* adds DEFAULT_TEST_NETIF as interface */ - TEST_ASSERT_NOT_NULL(gnrc_ipv6_netif_add_addr(DEFAULT_TEST_NETIF, &mc_addr, - DEFAULT_TEST_PREFIX_LEN, 0)); - TEST_ASSERT_NOT_NULL(gnrc_ipv6_netif_add_addr(DEFAULT_TEST_NETIF, &ll_addr1, - DEFAULT_TEST_PREFIX_LEN, 0)); - - TEST_ASSERT_NOT_NULL((out = gnrc_ipv6_netif_find_best_src_addr(DEFAULT_TEST_NETIF, &ll_addr2, false))); - TEST_ASSERT(out != &ll_addr1); - TEST_ASSERT(out != &ll_addr2); - TEST_ASSERT_EQUAL_INT(true, ipv6_addr_equal(out, &ll_addr1)); -} - -static void test_ipv6_netif_find_best_src_addr__multicast_input(void) -{ - ipv6_addr_t mc_addr = IPV6_ADDR_ALL_ROUTERS_LINK_LOCAL; - ipv6_addr_t *out = NULL; - - /* Adds DEFAULT_TEST_NETIF as interface and to it fe80::1, fe80::2 and ff02::1 */ - test_ipv6_netif_find_best_src_addr__success(); - - TEST_ASSERT_NOT_NULL((out = gnrc_ipv6_netif_find_best_src_addr(DEFAULT_TEST_NETIF, &mc_addr, false))); - TEST_ASSERT_EQUAL_INT(false, ipv6_addr_equal(&mc_addr, out)); - TEST_ASSERT_EQUAL_INT(false, ipv6_addr_is_unspecified(out)); -} - -static void test_ipv6_netif_find_best_src_addr__other_subnet(void) -{ - ipv6_addr_t addr1 = DEFAULT_TEST_IPV6_ADDR; - ipv6_addr_t addr2 = OTHER_TEST_IPV6_ADDR; - - ipv6_addr_t *out = NULL; - - test_ipv6_netif_add__success(); /* adds DEFAULT_TEST_NETIF as interface */ - TEST_ASSERT_NOT_NULL(gnrc_ipv6_netif_add_addr(DEFAULT_TEST_NETIF, &addr1, DEFAULT_TEST_PREFIX_LEN, - 0)); - - TEST_ASSERT_NOT_NULL((out = gnrc_ipv6_netif_find_best_src_addr(DEFAULT_TEST_NETIF, &addr2, false))); - TEST_ASSERT(out != &addr1); - TEST_ASSERT_EQUAL_INT(true, ipv6_addr_equal(out, &addr1)); -} - -static void test_ipv6_netif_addr_is_non_unicast__unicast(void) -{ - ipv6_addr_t addr = DEFAULT_TEST_IPV6_ADDR; - ipv6_addr_t *out = NULL; - - test_ipv6_netif_add_addr__success(); /* adds DEFAULT_TEST_IPV6_ADDR to - * DEFAULT_TEST_NETIF */ - - TEST_ASSERT_NOT_NULL((out = gnrc_ipv6_netif_find_addr(DEFAULT_TEST_NETIF, &addr))); - TEST_ASSERT_EQUAL_INT(false, gnrc_ipv6_netif_addr_is_non_unicast(out)); -} - -static void test_ipv6_netif_addr_is_non_unicast__anycast(void) -{ - ipv6_addr_t addr = DEFAULT_TEST_IPV6_ADDR; - ipv6_addr_t *out = NULL; - - test_ipv6_netif_add__success(); /* adds DEFAULT_TEST_NETIF as interface */ - - TEST_ASSERT_NOT_NULL(gnrc_ipv6_netif_add_addr(DEFAULT_TEST_NETIF, &addr, DEFAULT_TEST_PREFIX_LEN, - GNRC_IPV6_NETIF_ADDR_FLAGS_NON_UNICAST)); - - TEST_ASSERT_NOT_NULL((out = gnrc_ipv6_netif_find_addr(DEFAULT_TEST_NETIF, &addr))); - TEST_ASSERT_EQUAL_INT(true, gnrc_ipv6_netif_addr_is_non_unicast(out)); -} - -static void test_ipv6_netif_addr_is_non_unicast__multicast1(void) -{ - ipv6_addr_t addr = IPV6_ADDR_ALL_ROUTERS_LINK_LOCAL; - ipv6_addr_t *out = NULL; - - test_ipv6_netif_add__success(); /* adds DEFAULT_TEST_NETIF as interface */ - - TEST_ASSERT_NOT_NULL(gnrc_ipv6_netif_add_addr(DEFAULT_TEST_NETIF, &addr, - DEFAULT_TEST_PREFIX_LEN, 0)); - - TEST_ASSERT_NOT_NULL((out = gnrc_ipv6_netif_find_addr(DEFAULT_TEST_NETIF, &addr))); - TEST_ASSERT_EQUAL_INT(true, gnrc_ipv6_netif_addr_is_non_unicast(out)); -} - -static void test_ipv6_netif_addr_is_non_unicast__multicast2(void) -{ - ipv6_addr_t addr = IPV6_ADDR_ALL_ROUTERS_LINK_LOCAL; - ipv6_addr_t *out = NULL; - - test_ipv6_netif_add__success(); /* adds DEFAULT_TEST_NETIF as interface */ - - TEST_ASSERT_NOT_NULL(gnrc_ipv6_netif_add_addr(DEFAULT_TEST_NETIF, &addr, DEFAULT_TEST_PREFIX_LEN, - GNRC_IPV6_NETIF_ADDR_FLAGS_NON_UNICAST)); - - TEST_ASSERT_NOT_NULL((out = gnrc_ipv6_netif_find_addr(DEFAULT_TEST_NETIF, &addr))); - TEST_ASSERT_EQUAL_INT(true, gnrc_ipv6_netif_addr_is_non_unicast(out)); -} - -Test *tests_ipv6_netif_tests(void) -{ - EMB_UNIT_TESTFIXTURES(fixtures) { - new_TestFixture(test_ipv6_netif_add__success), - new_TestFixture(test_netif_add__success_with_ipv6), - new_TestFixture(test_ipv6_netif_add__despite_free_entry), - new_TestFixture(test_ipv6_netif_remove__not_allocated), - new_TestFixture(test_ipv6_netif_remove__success), - new_TestFixture(test_ipv6_netif_get__empty), - new_TestFixture(test_ipv6_netif_add_addr__no_iface1), - new_TestFixture(test_ipv6_netif_add_addr__no_iface2), - new_TestFixture(test_ipv6_netif_add_addr__addr_NULL), - new_TestFixture(test_ipv6_netif_add_addr__addr_unspecified), - new_TestFixture(test_ipv6_netif_add_addr__full), - new_TestFixture(test_ipv6_netif_add_addr__success), - new_TestFixture(test_ipv6_netif_add_addr__despite_free_entry), - new_TestFixture(test_ipv6_netif_remove_addr__not_allocated), - new_TestFixture(test_ipv6_netif_remove_addr__success), - new_TestFixture(test_ipv6_netif_reset_addr__success), - new_TestFixture(test_ipv6_netif_find_by_addr__empty), - new_TestFixture(test_ipv6_netif_find_by_addr__success), - new_TestFixture(test_ipv6_netif_find_addr__no_iface), - new_TestFixture(test_ipv6_netif_find_addr__wrong_iface), - new_TestFixture(test_ipv6_netif_find_addr__wrong_addr), - new_TestFixture(test_ipv6_netif_find_addr__success), - new_TestFixture(test_ipv6_netif_find_by_prefix__success1), - new_TestFixture(test_ipv6_netif_find_by_prefix__success2), - new_TestFixture(test_ipv6_netif_find_by_prefix__success3), - new_TestFixture(test_ipv6_netif_match_prefix__success1), - new_TestFixture(test_ipv6_netif_match_prefix__success2), - new_TestFixture(test_ipv6_netif_match_prefix__success3), - new_TestFixture(test_ipv6_netif_find_best_src_addr__no_unicast), - new_TestFixture(test_ipv6_netif_find_best_src_addr__success), - new_TestFixture(test_ipv6_netif_find_best_src_addr__multicast_input), - new_TestFixture(test_ipv6_netif_find_best_src_addr__other_subnet), - new_TestFixture(test_ipv6_netif_addr_is_non_unicast__unicast), - new_TestFixture(test_ipv6_netif_addr_is_non_unicast__anycast), - new_TestFixture(test_ipv6_netif_addr_is_non_unicast__multicast1), - new_TestFixture(test_ipv6_netif_addr_is_non_unicast__multicast2), - }; - - EMB_UNIT_TESTCALLER(ipv6_netif_tests, set_up, NULL, fixtures); - - return (Test *)&ipv6_netif_tests; -} - -void tests_ipv6_netif(void) -{ - TESTS_RUN(tests_ipv6_netif_tests()); -} -/** @} */ diff --git a/tests/unittests/tests-ipv6_netif/tests-ipv6_netif.h b/tests/unittests/tests-ipv6_netif/tests-ipv6_netif.h deleted file mode 100644 index 5962a8f925e4e531c99bd0ae25a1b4791889c6dd..0000000000000000000000000000000000000000 --- a/tests/unittests/tests-ipv6_netif/tests-ipv6_netif.h +++ /dev/null @@ -1,37 +0,0 @@ -/* - * Copyright (C) 2015 Martine Lenders <mlenders@inf.fu-berlin.de> - * - * This file is subject to the terms and conditions of the GNU Lesser - * General Public License v2.1. See the file LICENSE in the top level - * directory for more details. - */ - -/** - * @addtogroup unittests - * @{ - * - * @file - * @brief Unittests for the ``gnrc_ipv6_netif`` module - * - * @author Martine Lenders <mlenders@inf.fu-berlin.de> - */ -#ifndef TESTS_IPV6_NETIF_H -#define TESTS_IPV6_NETIF_H - -#include "embUnit.h" - -#ifdef __cplusplus -extern "C" { -#endif - -/** - * @brief The entry point of this test suite. - */ -void tests_ipv6_netif(void); - -#ifdef __cplusplus -} -#endif - -#endif /* TESTS_IPV6_NETIF_H */ -/** @} */