From 637459b868de8686a234250aa9e8aec71133be76 Mon Sep 17 00:00:00 2001 From: Martine Lenders Date: Tue, 16 May 2017 13:23:54 +0200 Subject: [PATCH 01/31] gnrc_netif2: Introduction of a new GNRC network interface API --- sys/include/net/gnrc/netif2.h | 669 ++++++++++ sys/include/net/gnrc/netif2/ethernet.h | 49 + sys/include/net/gnrc/netif2/internal.h | 350 ++++++ sys/include/net/netopt.h | 61 + sys/net/crosslayer/netopt/netopt.c | 9 + .../gnrc/link_layer/netdev/gnrc_netdev_eth.c | 112 -- sys/net/gnrc/netif2/gnrc_netif2.c | 1078 +++++++++++++++++ sys/net/gnrc/netif2/gnrc_netif2_ethernet.c | 250 ++++ 8 files changed, 2466 insertions(+), 112 deletions(-) create mode 100644 sys/include/net/gnrc/netif2.h create mode 100644 sys/include/net/gnrc/netif2/ethernet.h create mode 100644 sys/include/net/gnrc/netif2/internal.h create mode 100644 sys/net/gnrc/netif2/gnrc_netif2.c create mode 100644 sys/net/gnrc/netif2/gnrc_netif2_ethernet.c diff --git a/sys/include/net/gnrc/netif2.h b/sys/include/net/gnrc/netif2.h new file mode 100644 index 0000000000000..ebb594e22376d --- /dev/null +++ b/sys/include/net/gnrc/netif2.h @@ -0,0 +1,669 @@ +/* + * 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. + */ + +/** + * @defgroup net_gnrc_netif2 New network interface API + * @ingroup net_gnrc + * @brief Abstraction layer for GNRC's network interfaces + * + * Network interfaces in the context of GNRC are threads for protocols that are + * below the network layer. + * + * @{ + * + * @file + * @brief Definition for GNRC's network interfaces + * + * @author Martine Lenders + */ +#ifndef GNRC_NETIF2_H +#define GNRC_NETIF2_H + +#include +#include +#include + +#include "kernel_types.h" +#include "msg.h" +#include "net/ieee802154.h" +#include "net/ipv6/addr.h" +#include "net/ethernet/hdr.h" +#include "net/gnrc/netapi.h" +#ifdef MODULE_GNRC_IPV6_NIB +#include "net/gnrc/ipv6/nib/conf.h" +#endif +#include "net/gnrc/pkt.h" +#include "net/gnrc/mac/mac.h" +#include "net/netdev.h" +#include "net/netstats.h" +#include "rmutex.h" + +#ifdef __cplusplus +extern "C" { +#endif + +/** + * @brief Maximum number of network interfaces + * + * @note Intentially not calling it `GNRC_NETIF2_NUMOF` to not require + * rewrites throughout the stack. + */ +#ifndef GNRC_NETIF_NUMOF +#define GNRC_NETIF_NUMOF (1) +#endif + +/** + * @brief PID of the (virtual) loopback interface + */ +#define GNRC_NETIF2_LOOPBACK_PID (KERNEL_PID_LAST + 1) + +/** + * @brief Number of multicast addressed needed for @ref net_gnrc_rpl "RPL". + * + * @note Used for calculation of @ref GNRC_NETIF2_IPV6_GROUPS_NUMOF + */ +#ifdef MODULE_GNRC_RPL +#define GNRC_NETIF2_RPL_ADDR (1) +#else +#define GNRC_NETIF2_RPL_ADDR (0) +#endif + +/** + * @brief Number of multicast addresses needed for a @ref net_gnrc_ipv6 "IPv6" + * router + * + * @note Used for calculation of @ref GNRC_NETIF2_IPV6_GROUPS_NUMOF + */ +#ifdef MODULE_GNRC_IPV6_ROUTER +#define GNRC_NETIF2_IPV6_RTR_ADDR (1) +#else +#define GNRC_NETIF2_IPV6_RTR_ADDR (0) +#endif + +/** + * @brief Maximum number of unicast and anycast addresses per interface + * + * Default: 2 (link-local + corresponding global address) + */ +#ifndef GNRC_NETIF2_IPV6_ADDRS_NUMOF +#define GNRC_NETIF2_IPV6_ADDRS_NUMOF (2) +#endif + +/** + * @brief Maximum number of multicast groups per interface + * + * Default: 2 (all-nodes + solicited-nodes of link-local and global unicast + * address) + @ref GNRC_NETIF2_RPL_ADDR + @ref GNRC_NETIF2_IPV6_RTR_ADDR + */ +#ifndef GNRC_NETIF2_IPV6_GROUPS_NUMOF +#define GNRC_NETIF2_IPV6_GROUPS_NUMOF (2 + GNRC_NETIF2_RPL_ADDR + GNRC_NETIF2_IPV6_RTR_ADDR) +#endif + +/** + * @brief Maximum length of the link-layer address. + * + * The value for the maximum length of a link-layer address is dependent + * on the @ref drivers_netdev_api "netdev" adapters compiled in: + * - Setting it via `CFLAGS` has the most precedence. + * - The default is 8. + * - 1, if only @ref drivers_cc110x devices are compiled in. + * - @ref ETHERNET_ADDR_LEN, if additionally (or only) ethernet devices are + * compiled in. + * - @ref IEEE802154_LONG_ADDRESS_LEN, if additionally (or only) IEEE802.15.4 + * devices are compiled in. + * + * @note Implementers note: From longest to shortest extend, if new link-layer + * address types are included + */ +#ifndef GNRC_NETIF2_L2ADDR_MAXLEN +#if defined(MODULE_NETDEV_IEEE802154) || defined(MODULE_XBEE) +#define GNRC_NETIF2_L2ADDR_MAXLEN (IEEE802154_LONG_ADDRESS_LEN) +#elif MODULE_NETDEV_ETH +#define GNRC_NETIF2_L2ADDR_MAXLEN (ETHERNET_ADDR_LEN) +#elif MODULE_CC110X +#define GNRC_NETIF2_L2ADDR_MAXLEN (1U) +#else +#define GNRC_NETIF2_L2ADDR_MAXLEN (8U) +#endif +#endif + +#ifndef GNRC_NETIF2_DEFAULT_HL +#define GNRC_NETIF2_DEFAULT_HL (64U) /**< default hop limit */ +#endif + +/** + * @name Network interface flags + * @anchor net_gnrc_netif2_flags + * @{ + */ +/** + * @brief Network interface has link-layer address + * + * There are link-layers (e.g. SLIP) that do not have (nor require) link-layer + * addresses. This flag signifies this fact to upper layers by leaving it unset. + */ +#define GNRC_NETIF2_FLAGS_HAS_L2ADDR (0x00000001U) + +/** + * @brief Network interface is enabled for IPv6 forwarding + */ +#define GNRC_NETIF2_FLAGS_IPV6_FORWARDING (0x00000002U) + +/** + * @brief Network interface advertises itself as an IPv6 router + * (implies @ref GNRC_NETIF2_FLAGS_IPV6_FORWARDING to be set) + */ +#define GNRC_NETIF2_FLAGS_IPV6_RTR_ADV (0x00000004U) + +/** + * @brief This interface advertises its gnrc_netif2_t::mtu to other nodes + * (implies @ref GNRC_NETIF2_FLAGS_IPV6_RTR_ADV to be set) + */ +#define GNRC_NETIF2_FLAGS_IPV6_ADV_MTU (0x00000008U) + +/** + * @brief This interface advertises its gnrc_netif2_t::cur_hl to other nodes + * (implies @ref GNRC_NETIF2_FLAGS_IPV6_RTR_ADV to be set) + */ +#define GNRC_NETIF2_FLAGS_IPV6_ADV_CUR_HL (0x00000010U) + +/** + * @brief This interface advertises its reachable time to other nodes + * (implies @ref GNRC_NETIF2_FLAGS_IPV6_RTR_ADV to be set) + */ +#define GNRC_NETIF2_FLAGS_IPV6_ADV_REACH_TIME (0x00000020U) + +/** + * @brief This interface advertises its retransmission timer to other nodes + * (implies @ref GNRC_NETIF2_FLAGS_IPV6_RTR_ADV to be set) + */ +#define GNRC_NETIF2_FLAGS_IPV6_ADV_RETRANS_TIMER (0x00000040U) + +/** + * @brief This interface uses 6Lo header compression + * + * @see [RFC 6282](https://tools.ietf.org/html/rfc6282) + */ +#define GNRC_NETIF2_FLAGS_6LO_HC (0x00000080U) + +/** + * @brief This interface acts as a 6Lo border router to the LLN + */ +#define GNRC_NETIF2_FLAGS_6LO_ABR (0x00000100U) + +/** + * @brief This interface acts as a mesh-under node (route-over topology when + * unset) + */ +#define GNRC_NETIF2_FLAGS_6LO_MESH (0x00000200U) + +/** + * @brief Interface supports 6LoWPAN general header compression + * + * @attention GHC not implemented yet + * @see [RFC 7400, section 3.3](https://tools.ietf.org/html/rfc7400#section-3.3) + */ +#define GNRC_NETIF2_FLAGS_6LO_BACKBONE (0x00000400U) + +/** + * @brief Mask for @ref gnrc_mac_tx_feedback_t + */ +#define GNRC_NETIF2_FLAGS_MAC_TX_FEEDBACK_MASK (0x00006000U) + +/** + * @brief Flag to track if a transmission might have corrupted a received + * packet + */ +#define GNRC_NETIF2_FLAGS_MAC_RX_STARTED (0x00008000U) +/** + * @} + */ + +/** + * @name IPv6 unicast and anycast address flags + * @anchor net_gnrc_netif2_ipv6_addrs_flags + * @{ + */ +/** + * @brief Mask for the address' state + */ +#define GNRC_NETIF2_IPV6_ADDRS_FLAGS_STATE_MASK (0x03U) + +/** + * @brief Tentative address state + */ +#define GNRC_NETIF2_IPV6_ADDRS_FLAGS_STATE_TENTATIVE (0x01U) + +/** + * @brief Deprecated address state (still valid, but not preferred) + */ +#define GNRC_NETIF2_IPV6_ADDRS_FLAGS_STATE_DEPRECATED (0x02U) + +/** + * @brief Valid address state + */ +#define GNRC_NETIF2_IPV6_ADDRS_FLAGS_STATE_VALID (0x03U) + +/** + * @brief Address is an anycast address + */ +#define GNRC_NETIF2_IPV6_ADDRS_FLAGS_ANYCAST (0x04U) +/** + * @} + */ + +/** + * @brief Auto-address configuration modes + */ +enum { + GNRC_NETIF2_AAC_NONE = 0, /**< no configuration */ + GNRC_NETIF2_AAC_AUTO, /**< Use some automatic bootstrapping (e.g. SLAAC with IPv6) */ + GNRC_NETIF2_AAC_DHCP, /**< Use DHCP(v6) */ + /* extend if needed */ +}; + +/** + * @brief Operations to an interface + */ +typedef struct gnrc_netif2_ops gnrc_netif2_ops_t; + +/** + * @brief Representation of a network interface + */ +typedef struct { + const gnrc_netif2_ops_t *ops; /**< Operations of the network interface */ + netdev_t *dev; /**< Network device of the network interface */ +#if defined(MODULE_GNRC_MAC) || DOXYGEN +#if ((GNRC_MAC_RX_QUEUE_SIZE != 0) || (GNRC_MAC_DISPATCH_BUFFER_SIZE != 0)) || DOXYGEN + /** + * @brief MAC internal object which stores reception parameters, queues, and + * state machines. + * + * @note Only available if @ref GNRC_MAC_RX_QUEUE_SIZE or + * @ref GNRC_MAC_DISPATCH_BUFFER_SIZE is greater than 0. + */ + gnrc_mac_rx_t rx; +#endif /* ((GNRC_MAC_RX_QUEUE_SIZE != 0) || (GNRC_MAC_DISPATCH_BUFFER_SIZE != 0)) || DOXYGEN */ + +#if ((GNRC_MAC_TX_QUEUE_SIZE != 0) || (GNRC_MAC_NEIGHBOR_COUNT != 0)) || DOXYGEN + /** + * @brief MAC internal object which stores transmission parameters, queues, and + * state machines. + * + * @note Only available if @ref GNRC_MAC_TX_QUEUE_SIZE or + * @ref GNRC_MAC_NEIGHBOR_COUNT is greater than 0. + */ + gnrc_mac_tx_t tx; +#endif /* ((GNRC_MAC_TX_QUEUE_SIZE != 0) || (GNRC_MAC_NEIGHBOR_COUNT == 0)) || DOXYGEN */ +#endif /* MODULE_GNRC_MAC */ +#ifdef MODULE_NETSTATS_IPV6 + /** + * @brief IPv6 packet statistics + * + * @note Only available with module `netstats_ipv6`. + */ + netstats_t ipv6_stats; +#endif + rmutex_t mutex; /**< Mutex of the interface */ +#if (GNRC_NETIF2_L2ADDR_MAXLEN > 0) + /** + * @brief The link-layer address currently used as the source address + * on this interface. + * + * @note Only available if @ref GNRC_NETIF2_L2ADDR_MAXLEN > 0 + */ + uint8_t l2addr[GNRC_NETIF2_L2ADDR_MAXLEN]; +#endif +#if defined(MODULE_GNRC_IPV6) || DOXYGEN + /** + * @brief Flags for gnrc_netif2_t::ipv6_addrs + * + * @see net_gnrc_netif2_ipv6_addrs_flags + * + * @note Only available with module @ref net_gnrc_ipv6 "gnrc_ipv6". + */ + uint8_t ipv6_addrs_flags[GNRC_NETIF2_IPV6_ADDRS_NUMOF]; + + /** + * @brief IPv6 unicast and anycast addresses of the interface + * + * @note Only available with module @ref net_gnrc_ipv6 "gnrc_ipv6". + */ + ipv6_addr_t ipv6_addrs[GNRC_NETIF2_IPV6_ADDRS_NUMOF]; + + /** + * @brief IPv6 multicast groups of the interface + * + * @note Only available with module @ref net_gnrc_ipv6 "gnrc_ipv6". + */ + ipv6_addr_t ipv6_groups[GNRC_NETIF2_IPV6_GROUPS_NUMOF]; + +#if defined(MODULE_GNRC_IPV6_NIB) || DOXYGEN +#if GNRC_IPV6_NIB_CONF_ROUTER || DOXYGEN + /** + * @brief Route info callback + * + * This callback is called by the @ref net_gnrc_ipv6_nib "NIB" to inform + * the routing protocol about state changes, route usages, missing routes + * etc. + * + * @todo Define types (RRQ, RRN, NSC) in NIB + * + * @param[in] type Type of the route info. + * @param[in] ctx_addr Context address of the route info. + * @param[in] ctx Further context of the route info. + */ + int (*route_info_cb)(unsigned type, const ipv6_addr_t *ctx_addr, + const void *ctx); + /** + * @brief Event for @ref GNRC_IPV6_NIB_SND_MC_RA + * + * @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_ROUTER != 0 + */ + evtimer_msg_event_t snd_mc_ra; +#endif /* GNRC_IPV6_NIB_CONF_ROUTER */ +#if GNRC_IPV6_NIB_CONF_ARSM || DOXYGEN + /** + * @brief Event for @ref GNRC_IPV6_NIB_RECALC_REACH_TIME + * + * @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_ARSM != 0 + */ + evtimer_msg_event_t recalc_reach_time; +#endif /* GNRC_IPV6_NIB_CONF_ARSM */ + /** + * @brief Event for @ref GNRC_IPV6_NIB_SEARCH_RTR + * + * @note Only available with module @ref net_gnrc_ipv6 "gnrc_ipv6". + * and @ref net_gnrc_ipv6_nib "NIB" + */ + evtimer_msg_event_t search_rtr; + +#if GNRC_IPV6_NIB_CONF_ROUTER || DOXYGEN + /** + * @brief Timestamp in milliseconds of last unsolicited router + * advertisement + * + * @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_ROUTER != 0 + */ + uint32_t last_ra; +#endif /* GNRC_IPV6_NIB_CONF_ROUTER */ +#if GNRC_IPV6_NIB_CONF_ARSM || defined(DOXYGEN) + /** + * @brief Base for random reachable time calculation and advertised + * reachable time in ms (if @ref GNRC_NETIF2_FLAGS_IPV6_RTR_ADV is + * set) + * + * @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_ARSM != 0 + */ + uint32_t reach_time_base; + + /** + * @brief Reachable time (in ms) + * + * @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_ARSM != 0 + */ + uint32_t reach_time; +#endif /* GNRC_IPV6_NIB_CONF_ARSM */ + /** + * @brief Retransmission time and advertised retransmission time (in ms) + * + * @note Only available with module @ref net_gnrc_ipv6 "gnrc_ipv6" and + * @ref net_gnrc_ipv6_nib "NIB" + */ + uint32_t retrans_time; +#endif /* MODULE_GNRC_IPV6_NIB */ + + /** + * @brief Maximum transition unit (MTU) for IPv6 packets + * + * @note Only available with module @ref net_gnrc_ipv6 "gnrc_ipv6". + */ + uint16_t ipv6_mtu; +#if defined(MODULE_GNRC_IPV6_NIB) || DOXYGEN +#if GNRC_IPV6_NIB_CONF_ROUTER || DOXYGEN + /** + * @brief number of unsolicited router advertisements sent + * + * This only counts up to the first @ref NDP_MAX_INIT_RA_NUMOF on interface + * initialization. The last @ref NDP_MAX_FIN_RA_NUMOF of an advertising + * interface are counted from UINT8_MAX - @ref NDP_MAX_FIN_RA_NUMOF + 1. + * + * @note Only available with module @ref net_gnrc_ipv6 "gnrc_ipv6". + * and @ref net_gnrc_ipv6_nib "NIB" and if + * @ref GNRC_IPV6_NIB_CONF_ROUTER != 0 + */ + uint8_t ra_sent; +#endif + /** + * @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" + */ + uint8_t rs_sent; + /** + * @brief number of unsolicited neighbor advertisements scheduled + * + * @note Only available with module @ref net_gnrc_ipv6 "gnrc_ipv6" and + * @ref net_gnrc_ipv6_nib "NIB" + */ + uint8_t na_sent; +#endif + + /** + * @brief IPv6 auto-address configuration mode + * + * @note Only available with module @ref net_gnrc_ipv6 "gnrc_ipv6" + */ + uint8_t ipv6_aac_mode; +#endif /* gnrc_ipv6 */ + /** + * @brief Flags for the interface + * + * @see net_gnrc_netif2_flags + */ + uint16_t flags; + kernel_pid_t pid; /**< PID of the network interface's thread */ +#if (GNRC_NETIF2_L2ADDR_MAXLEN > 0) + /** + * @brief Length in bytes of gnrc_netif2_t::l2addr + * + * @note Only available if @ref GNRC_NETIF2_L2ADDR_MAXLEN > 0 + */ + uint8_t l2addr_len; +#endif +#if defined(MODULE_GNRC_SIXLOWPAN_FRAG) || DOXYGEN + /** + * @brief Maximum fragment size for 6LoWPAN fragmentation. + * + * @note Only available with module + * @ref net_gnrc_sixlowpan_frag "gnrc_sixlowpan_frag". + */ + uint8_t max_frag_size; +#endif + uint8_t cur_hl; /**< Current hop-limit for out-going packets */ + uint8_t device_type; /**< Device type */ +} gnrc_netif2_t; + +/** + * @see gnrc_netif2_ops_t + */ +struct gnrc_netif2_ops { + /** + * @brief Send a @ref net_gnrc_pkt "packet" over the network interface + * + * @pre `netif != NULL && pkt != NULL` + * + * @note The function re-formats the content of @p pkt to a format expected + * by the netdev_driver_t::send() method of gnrc_netif_t::dev and + * releases the it before returning (so no additional release should + * be required after calling this method). + * + * @param[in] netif The network interface. + * @param[in] pkt A packet to send. + * + * @return The number of bytes actually sent on success + * @return -EBADMSG, if the @ref net_gnrc_netif_hdr in @p pkt is missing + * or of an unexpected format. + * @return -ENOTSUP, if sending @p pkt in the given format isn't supported + * (e.g. empty payload with Ethernet). + * @return Any negative error code reported by gnrc_netif2_t::dev. + */ + int (*send)(gnrc_netif2_t *netif, gnrc_pktsnip_t *pkt); + + /** + * @brief Receives a @ref net_gnrc_pkt "packet" from the network interface + * + * @pre `netif != NULL` + * + * @note The function takes the bytes received from via + * netdev_driver_t::recv() from gnrc_netif_t::dev and re-formats it to + * a @ref net_gnrc_pkt "packet" containing a @ref net_gnrc_netif_hdr + * and a payload header in receive order. + * + * @param[in] netif The network interface. + * + * @return The packet received. Contains the payload (with the type marked + * accordingly) and a @ref net_gnrc_netif_hdr in receive order. + * @return NULL, if @ref net_gnrc_pktbuf was full. + */ + gnrc_pktsnip_t *(*recv)(gnrc_netif2_t *netif); + + /** + * @brief Get an option from the network interface + * + * Use gnrc_netif2_get_from_netdev() to just get options from + * gnrc_netif2_t::dev. + * + * @param[in] netif The network interface. + * @param[in] opt The option parameters. + * + * @return Number of bytes in @p data. + * @return -EOVERFLOW, if @p max_len is lesser than the required space. + * @return -ENOTSUP, if @p opt is not supported to be set. + * @return Any negative error code reported by gnrc_netif2_t::dev. + */ + int (*get)(gnrc_netif2_t *netif, gnrc_netapi_opt_t *opt); + + /** + * @brief Get an option from the network interface + * + * Use gnrc_netif2_set_from_netdev() to just get options from + * gnrc_netif2_t::dev. + * + * @param[in] netif The network interface. + * @param[in] opt The option parameters. + * + * @return Number of bytes written to gnrc_netif2_t::dev. + * @return -EOVERFLOW, if @p data_len is greater than the allotted space in + * gnrc_netif2_t::dev or gnrc_netif_t. + * @return -ENOTSUP, if @p opt is not supported to be set. + * @return Any negative error code reported by gnrc_netif2_t::dev. + */ + int (*set)(gnrc_netif2_t *netif, const gnrc_netapi_opt_t *opt); + + /** + * @brief Message handler for network interface + * + * This message handler is used, when the network interface needs to handle + * message types beyond the ones defined in @ref net_gnrc_netapi "netapi". + * Leave NULL if this is not the case. + * + * @param[in] netif The network interface. + * @param[in] msg Message to be handled. + */ + void (*msg_handler)(gnrc_netif2_t *netif, msg_t *msg); +}; + +/** + * @brief Deprecated address state (still valid, but not preferred) + */ +#define GNRC_NETIF2_IPV6_ADDRS_FLAGS_STATE_DEPRECATED (0x02U) + +/** + * @brief Creates a network interface + * + * @param[in] stack The stack for the network interface's thread. + * @param[in] stacksize Size of @p stack. + * @param[in] priority Priority for the network interface's thread. + * @param[in] name Name for the network interface. May be NULL. + * @param[in] dev Device for the interface. + * @param[in] ops Operations for the network interface. + * + * @note If @ref DEVELHELP is defined netif_params_t::name is used as the + * name of the network interface's thread. + * + * @return The network interface on success. + * @return NULL, on error. + */ +gnrc_netif2_t *gnrc_netif2_create(char *stack, int stacksize, char priority, + const char *name, netdev_t *dev, + const gnrc_netif2_ops_t *ops); + +/** +int gnrc_netif2_get_from_netdev(gnrc_netif2_t *netif, netopt_t opt, void *data, + size_t max_len); + * @brief Get number of network interfaces actually allocated + * + * @return Number of network interfaces actually allocated + */ +unsigned gnrc_netif2_numof(void); + +/** + * @brief Iterate over all network interfaces. + * + * @param[in] prev previous interface in iteration. NULL to start iteration. + * + * @return The next network interface after @p prev. + * @return NULL, if @p prev was the last network interface. + */ +gnrc_netif2_t *gnrc_netif2_iter(const gnrc_netif2_t *prev); + +/** + * @brief Default operation for gnrc_netif2_ops_t::get() + * + * @note Can also be used to be called *after* a custom operation. + * + * @param[in] netif The network interface. + * @param[out] opt The option parameters. + * + * @return Return value of netdev_driver_t::get() of gnrc_netif2_t::dev of + * @p netif. + */ +int gnrc_netif2_get_from_netdev(gnrc_netif2_t *netif, gnrc_netapi_opt_t *opt); + +/** + * @brief Default operation for gnrc_netif2_ops_t::set() + * + * @note Can also be used to be called *after* a custom operation. + * + * @param[in] netif The network interface. + * @param[in] opt The option parameters. + * + * @return Return value of netdev_driver_t::set() of gnrc_netif2_t::dev of + * @p netif. + */ +int gnrc_netif2_set_from_netdev(gnrc_netif2_t *netif, + const gnrc_netapi_opt_t *opt); + +#ifdef __cplusplus +} +#endif + +#endif /* GNRC_NETIF2_H */ +/** @} */ diff --git a/sys/include/net/gnrc/netif2/ethernet.h b/sys/include/net/gnrc/netif2/ethernet.h new file mode 100644 index 0000000000000..05e0aac620378 --- /dev/null +++ b/sys/include/net/gnrc/netif2/ethernet.h @@ -0,0 +1,49 @@ +/* + * 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_netif2 + * @{ + * + * @file + * @brief Ethernet adaption for @ref net_gnrc_netif2 + * + * @author Martine Lenders + */ +#ifndef NET_GNRC_NETIF2_ETH_H +#define NET_GNRC_NETIF2_ETH_H + +#include "net/gnrc/netif2.h" + +#ifdef __cplusplus +extern "C" { +#endif + +/** + * @brief Creates an Ethernet network interface + * + * @param[in] stack The stack for the network interface's thread. + * @param[in] stacksize Size of @p stack. + * @param[in] priority Priority for the network interface's thread. + * @param[in] name Name for the network interface. May be NULL. + * @param[in] dev Device for the interface. + * + * @see @ref gnrc_netif2_create() + * + * @return The network interface on success. + * @return NULL, on error. + */ +gnrc_netif2_t *gnrc_netif2_eth_create(char *stack, int stacksize, char priority, + char *name, netdev_t *dev); + +#ifdef __cplusplus +} +#endif + +#endif /* NET_GNRC_NETIF2_ETH_H */ +/** @} */ diff --git a/sys/include/net/gnrc/netif2/internal.h b/sys/include/net/gnrc/netif2/internal.h new file mode 100644 index 0000000000000..6562b29b6ae53 --- /dev/null +++ b/sys/include/net/gnrc/netif2/internal.h @@ -0,0 +1,350 @@ +/* + * 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. + */ + +/** + * @addtogroup net_gnrc_netif + * @internal + * @attention **FOR GNRC-INTERNAL USE ONLY. PLEASE USE @ref net_gnrc_netapi + * "NETAPI" (WITH THE INTERFACE'S PID) FOR EXTERNAL MANIPULATION** + * @{ + * + * @file + * @brief GNRC-internal network interface definitions + * + * @author Martine Lenders + */ +#ifndef NET_GNRC_NETIF2_INTERNAL_H +#define NET_GNRC_NETIF2_INTERNAL_H + +#include "net/gnrc/netif2.h" + +#ifdef __cplusplus +extern "C" { +#endif + +/** + * @brief Message type for @ref netdev_event_t "netdev events" + */ +#define NETDEV_MSG_TYPE_EVENT (0x1234) + +/** + * @brief Acquire exclusive access to the interface + * + * @param[in] netif the network interface + * + * @internal + */ +static inline void gnrc_netif2_acquire(gnrc_netif2_t *netif) +{ + if (netif->ops) { + rmutex_lock(&netif->mutex); + } +} + +/** + * @brief Release exclusive access to the interface + * + * @param[in] netif the network interface + * + * @internal + */ +static inline void gnrc_netif2_release(gnrc_netif2_t *netif) +{ + if (netif->ops) { + rmutex_unlock(&netif->mutex); + } +} + +/** + * @brief Get network interface by PID + * + * @param[in] pid A PID of a network interface. + * + * @return The network interface on success. + * @return NULL, if no network interface with PID exists. + */ +gnrc_netif2_t *gnrc_netif2_get_by_pid(kernel_pid_t pid); + +#if defined(MODULE_GNRC_IPV6) || DOXYGEN +/** + * @brief Adds an IPv6 address to the interface + * + * @pre `(netif != NULL) && (addr != NULL)` + * @pre @p addr is not multicast (starts with `ff00::/8`) + * @pre `(pfx_len > 0) && (pfx_len <= 128)` + * + * @param[in,out] netif the network interface. May not be NULL. + * @param[in] addr the address to add. If the address is already on the + * interface the function will return 0, but @p flags + * will be ignored. May not be NULL and may not be + * link-local or multicast + * @param[in] pfx_len length in bits of the prefix of @p addr + * @param[in] flags initial flags for the address. Setting the address' + * state to @ref GNRC_NETIF2_IPV6_ADDRS_FLAGS_STATE_VALID + * means that state-less auto-address configuration is + * skipped and the address is considered to be manually + * configured. If the state in the flgas is unset, + * GNRC_NETIF2_IPV6_ADDRS_FLAGS_STATE_TENTATIVE is assumed. + * + * @note Only available with @ref net_gnrc_ipv6 "gnrc_ipv6". + * + * @return 0, on success + * @return -ENOMEM, when no space for new addresses is left on the interface + */ +int gnrc_netif2_ipv6_addr_add(gnrc_netif2_t *netif, const ipv6_addr_t *addr, + unsigned pfx_len, uint8_t flags); + +/** + * @brief Removes an IPv6 address from the interface + * + * @pre `(netif != NULL) && (addr != NULL)` + * + * @param[in,out] netif the network interface + * @param[in] addr the address to remove + * + * @note Only available with @ref net_gnrc_ipv6 "gnrc_ipv6". + */ +void gnrc_netif2_ipv6_addr_remove(gnrc_netif2_t *netif, + const ipv6_addr_t *addr); + + +/** + * @brief Returns the index of @p addr in gnrc_netif2_t::ipv6_addrs of @p + * netif + * + * @pre `(netif != NULL) && (addr != NULL)` + * + * Can be used to check if an address is assigned to an interface. + * + * @param[in] netif the network interface + * @param[in] addr the address to check + * + * @note Only available with @ref net_gnrc_ipv6 "gnrc_ipv6". + * + * @return index of @p addr in gnrc_netif2_t::ipv6_addrs of @p netif + * @return -1, if @p addr isn't assigned to @p netif + */ +int gnrc_netif2_ipv6_addr_idx(gnrc_netif2_t *netif, + const ipv6_addr_t *addr); + +/** + * @brief Returns the index of an address in gnrc_netif2_t::ipv6_addrs of @p + * netif that matches @p addr best + * + * @pre `(netif != NULL) && (addr != NULL)` + * + * Can be used to check if a prefix is assigned to an interface. + * + * @param[in] netif the network interface + * @param[in] addr the prefix to match + * + * + * @note Only available with @ref net_gnrc_ipv6 "gnrc_ipv6". + * + * @return index of an address in gnrc_netif2_t::ipv6_addrs of @p netif that + * best matches @p addr. + * @return -1, if no address on @p netif matches @p addr + */ +int gnrc_netif2_ipv6_addr_match(gnrc_netif2_t *netif, + const ipv6_addr_t *addr); + +/** + * @brief Searches for the best address on an interface usable as a source + * address for a given destination address. + * + * @pre `(netif != NULL) && (dst != NULL)` + * + * @param[in] netif the network interface + * @param[in] dst the destination address you want to find a source for. + * @param[in] ll_only only link local addresses qualify + * + * @see [RFC 6724](https://tools.ietf.org/html/rfc6724) + * + * @note Only available with @ref net_gnrc_ipv6 "gnrc_ipv6". + * + * @todo Rule 4 from RFC 6724 is currently not implemented. Has to updated as + * soon as gnrc supports Mobile IP. + * + * @todo Rule 6 from RFC 6724 is currently not implemented. Has to updated as + * soon as gnrc supports flow labels. + * + * @todo Rule 7 from RFC 6724 is currently not implemented. Has to updated as + * soon as gnrc supports temporary addresses. + * + * @return The best source address for a packet addressed to @p dst + * @return NULL, if no matching address can be found on the interface. + */ +ipv6_addr_t *gnrc_netif2_ipv6_addr_best_src(gnrc_netif2_t *netif, + const ipv6_addr_t *dst, + bool ll_only); + +/** + * @brief Gets an interface by an address assigned to it. + * + * @pre `addr != NULL` + * + * @param[in] addr an IPv6 address + * + * @return The network interface that has @p addr assigned + * @return NULL, if no interface has @p addr assigned + */ +gnrc_netif2_t *gnrc_netif2_get_by_ipv6_addr(const ipv6_addr_t *addr); + +/** + * @brief Gets an interface by an address matching a given prefix best + * + * @param[in] prefix an IPv6 address or prefix + * + * @return The network interface that has an address assigned, that matches + * @p prefix best + * @return NULL, if there is no address on any interface that matches @prefix + */ +gnrc_netif2_t *gnrc_netif2_get_by_prefix(const ipv6_addr_t *prefix); + +/** + * @brief Joins interface to an IPv6 multicast group + * + * @pre `(netif != NULL) && (addr != NULL)` + * @pre @p addr is a multicast address (starts with `ff00::/8`) + * + * @param[in,out] netif the network interface + * @param[in] addr the address of the multicast group + * + * @note Only available with @ref net_gnrc_ipv6 "gnrc_ipv6". + * + * @return 0, on success + * @return -ENOMEM, when no space for new addresses is left on the interface + */ +int gnrc_netif2_ipv6_group_join(gnrc_netif2_t *netif, + const ipv6_addr_t *addr); + +/** + * @brief Let interface leave from an IPv6 multicast group + * + * @pre `(netif != NULL) && (addr != NULL)` + * + * @param[in,out] netif the network interface + * @param[in] addr the address of the multicast group + * + * @note Only available with @ref net_gnrc_ipv6 "gnrc_ipv6". + */ +void gnrc_netif2_ipv6_group_leave(gnrc_netif2_t *netif, + const ipv6_addr_t *addr); + +/** + * @brief Get interface identifier (IID) of an interface's link-layer address + * + * @param[in] netif the network interface + * @param[out] eui64 the IID, set to all 0 if interface has no link-layer + * address or if gnrc_netif2_t::device_type is not + * supported. + */ +void gnrc_netif2_ipv6_get_iid(gnrc_netif2_t *netif, + eui64_t *eui64); +#endif /* MODULE_GNRC_IPV6 */ + +/** + * @brief Checks if the interface represents a router according to RFC 4861 + * + * @attention Requires prior locking + * + * @param[in] netif the network interface + * + * @see [RFC 4861, section 2.1](https://tools.ietf.org/html/rfc4861#section-2.1) + * + * @return true, if the interface represents a router + * @return false, if the interface does not represent a router + */ +static inline bool gnrc_netif2_is_rtr(const gnrc_netif2_t *netif) +{ + return (netif->flags & GNRC_NETIF2_FLAGS_IPV6_FORWARDING); +} + +/** + * @brief Checks if the interface is allowed to send out router advertisements + * + * @attention Requiors prior locking + * + * @param[in] netif the network interface + * + * @return true, if the interface is allowed to send out router adverisements + * @return false, if the interface is allowed to send out router adverisements + */ +static inline bool gnrc_netif2_is_rtr_adv(const gnrc_netif2_t *netif) +{ + return (netif->flags & GNRC_NETIF2_FLAGS_IPV6_RTR_ADV); +} + +/** + * @brief Checks if the interface represents a 6Lo node (6LN) according to + * RFC 6775 + * + * @attention Requires prior locking + * + * @param[in] netif the network interface + * + * @see [RFC 6775, section 2](https://tools.ietf.org/html/rfc6776#section-2) + * + * @return true, if the interface represents a 6LN + * @return false, if the interface does not represent a 6LN + */ +static inline bool gnrc_netif2_is_6ln(const gnrc_netif2_t *netif) +{ + switch (netif->device_type) { + case NETDEV_TYPE_IEEE802154: + case NETDEV_TYPE_CC110X: + case NETDEV_TYPE_NRFMIN: + return true; + default: + return false; + } +} + +/** + * @brief Checks if the interface represents a 6Lo router (6LR) according to + * RFC 6775 + * + * @attention Requires prior locking + * + * @param[in] netif the network interface + * + * @see [RFC 6775, section 2](https://tools.ietf.org/html/rfc6776#section-2) + * + * @return true, if the interface represents a 6LR + * @return false, if the interface does not represent a 6LR + */ +static inline bool gnrc_netif2_is_6lr(const gnrc_netif2_t *netif) +{ + return gnrc_netif2_is_rtr(netif) && gnrc_netif2_is_6ln(netif); +} + +/** + * @brief Checks if the interface represents a 6Lo border router (6LBR) + * according to RFC 6775 + * + * @attention Requires prior locking + * + * @param[in] netif the network interface + * + * @see [RFC 6775, section 2](https://tools.ietf.org/html/rfc6776#section-2) + * + * @return true, if the interface represents a 6LBR + * @return false, if the interface does not represent a 6LBR + */ +static inline bool gnrc_netif2_is_6lbr(const gnrc_netif2_t *netif) +{ + return (netif->flags & GNRC_NETIF2_FLAGS_6LO_ABR) && + gnrc_netif2_is_6lr(netif); +} + +#ifdef __cplusplus +} +#endif + +#endif /* NET_GNRC_NETIF2_INTERNAL_H */ +/** @} */ diff --git a/sys/include/net/netopt.h b/sys/include/net/netopt.h index 6fba559496527..dac51d8e2059b 100644 --- a/sys/include/net/netopt.h +++ b/sys/include/net/netopt.h @@ -58,6 +58,11 @@ typedef enum { */ NETOPT_NID, + /** + * @brief get/set hop limit as uint8_t + */ + NETOPT_HOP_LIMIT, + /** * @brief get the IPv6 interface identifier of a network interface as * eui64_t. @@ -73,6 +78,58 @@ typedef enum { * RFC 4944). */ NETOPT_IPV6_IID, + + /** + * @brief get IPv6 addresses of an interface as array of @ref ipv6_addr_t + * or add an IPv6 address as @ref ipv6_addr_t to an interface + * + * When adding an IPv6 address to a GNRC interface using + * @ref GNRC_NETAPI_MSG_TYPE_SET, the gnrc_netapi_opt_t::context field can + * be used to pass the prefix length (8 MSB) and some flags (8 LSB) + * according to @ref net_gnrc_netif2_ipv6_addrs_flags. The address is however always + * considered to be manually added. + * When getting the option you can pass an array of @ref ipv6_addr_t of any + * length greater than 0 to the getter. The array will be filled up to to + * its maximum and the remaining addresses on the interface will be ignored + */ + NETOPT_IPV6_ADDR, + /** + * @brief Removes an IPv6 address as @ref ipv6_addr_t from an interface + */ + NETOPT_IPV6_ADDR_REMOVE, + /** + * @brief get the flags to the addresses returned by @ref NETOPT_IPV6_ADDR + * as array of uint8_t + * + * The information contained in the array is very specific to the + * interface's API. For GNRC e.g. the values are according to + * @ref net_gnrc_netif2_ipv6_addrs_flags. + */ + NETOPT_IPV6_ADDR_FLAGS, + /** + * @brief get IPv6 multicast groups of an interface as array of + * @ref ipv6_addr_t or join an IPv6 multicast group as + * @ref ipv6_addr_t on an interface + * + * When adding an IPv6 address to a GNRC interface using + * @ref GNRC_NETAPI_MSG_TYPE_SET, the gnrc_netapi_opt_t::context field can + * be used to pass the prefix length (8 MSB) and some flags (8 LSB) + * according to @ref net_gnrc_netif2_ipv6_addrs_flags. The address is however always + * considered to be manually added. + * When getting the option you can pass an array of @ref ipv6_addr_t of any + * length greater than 0 to the getter. The array will be filled up to to + * its maximum and the remaining addresses on the interface will be ignored + */ + NETOPT_IPV6_GROUP, + /** + * @brief Leaves an IPv6 multicast group as @ref ipv6_addr_t on an + * interface + */ + NETOPT_IPV6_GROUP_LEAVE, + NETOPT_IPV6_FORWARDING, /**< en/disable IPv6 forwarding or read the + * current state */ + NETOPT_IPV6_SND_RTR_ADV, /**< en/disable sending of IPv6 router + * advertisements or read the current state */ NETOPT_TX_POWER, /**< get/set the output power for radio * devices in dBm as int16_t in host byte * order */ @@ -340,6 +397,10 @@ typedef enum { */ NETOPT_IQ_INVERT, + NETOPT_6LO_IPHC, /**< en/disable header compression according to + * [RFC 6282](https://tools.ietf.org/html/rfc6282) + * or read the current state */ + /** * @brief Get retry amount from missing ACKs of the last transmission * diff --git a/sys/net/crosslayer/netopt/netopt.c b/sys/net/crosslayer/netopt/netopt.c index 59fea27ea3523..36b78ba21f8a3 100644 --- a/sys/net/crosslayer/netopt/netopt.c +++ b/sys/net/crosslayer/netopt/netopt.c @@ -31,7 +31,15 @@ static const char *_netopt_strmap[] = { [NETOPT_ADDR_LEN] = "NETOPT_ADDR_LEN", [NETOPT_SRC_LEN] = "NETOPT_SRC_LEN", [NETOPT_NID] = "NETOPT_NID", + [NETOPT_HOP_LIMIT] = "NETOPT_HOP_LIMIT", [NETOPT_IPV6_IID] = "NETOPT_IPV6_IID", + [NETOPT_IPV6_ADDR] = "NETOPT_IPV6_ADDR", + [NETOPT_IPV6_ADDR_REMOVE] = "NETOPT_IPV6_ADDR_REMOVE", + [NETOPT_IPV6_ADDR_FLAGS] = "NETOPT_IPV6_ADDR_FLAGS", + [NETOPT_IPV6_GROUP] = "NETOPT_IPV6_GROUP", + [NETOPT_IPV6_GROUP_LEAVE] = "NETOPT_IPV6_GROUP_LEAVE", + [NETOPT_IPV6_FORWARDING] = "NETOPT_IPV6_FORWARDING", + [NETOPT_IPV6_SND_RTR_ADV] = "NETOPT_IPV6_SND_RTR_ADV", [NETOPT_TX_POWER] = "NETOPT_TX_POWER", [NETOPT_MAX_PACKET_SIZE] = "NETOPT_MAX_PACKET_SIZE", [NETOPT_PRELOADING] = "NETOPT_PRELOADING", @@ -75,6 +83,7 @@ static const char *_netopt_strmap[] = { [NETOPT_FIXED_HEADER] = "NETOPT_FIXED_HEADER", [NETOPT_IQ_INVERT] = "NETOPT_IQ_INVERT", [NETOPT_TX_RETRIES_NEEDED] = "NETOPT_TX_RETRIES_NEEDED", + [NETOPT_6LO_IPHC] = "NETOPT_6LO_IPHC", [NETOPT_NUMOF] = "NETOPT_NUMOF", }; diff --git a/sys/net/gnrc/link_layer/netdev/gnrc_netdev_eth.c b/sys/net/gnrc/link_layer/netdev/gnrc_netdev_eth.c index cb532e16b037d..0de93b127d76a 100644 --- a/sys/net/gnrc/link_layer/netdev/gnrc_netdev_eth.c +++ b/sys/net/gnrc/link_layer/netdev/gnrc_netdev_eth.c @@ -119,118 +119,6 @@ static gnrc_pktsnip_t *_recv(gnrc_netdev_t *gnrc_netdev) return NULL; } -static inline void _addr_set_broadcast(uint8_t *dst) -{ - memset(dst, 0xff, ETHERNET_ADDR_LEN); -} - -static inline void _addr_set_multicast(uint8_t *dst, gnrc_pktsnip_t *payload) -{ - switch (payload->type) { -#ifdef MODULE_GNRC_IPV6 - case GNRC_NETTYPE_IPV6: - /* https://tools.ietf.org/html/rfc2464#section-7 */ - dst[0] = 0x33; - dst[1] = 0x33; - ipv6_hdr_t *ipv6 = payload->data; - memcpy(dst + 2, ipv6->dst.u8 + 12, 4); - break; -#endif - default: - _addr_set_broadcast(dst); - break; - } -} - -static int _send(gnrc_netdev_t *gnrc_netdev, gnrc_pktsnip_t *pkt) -{ - ethernet_hdr_t hdr; - gnrc_netif_hdr_t *netif_hdr; - gnrc_pktsnip_t *payload; - int res; - - netdev_t *dev = gnrc_netdev->dev; - - if (pkt == NULL) { - DEBUG("gnrc_netdev_eth: pkt was NULL\n"); - return -EINVAL; - } - - payload = pkt->next; - - if (pkt->type != GNRC_NETTYPE_NETIF) { - DEBUG("gnrc_netdev_eth: First header was not generic netif header\n"); - return -EBADMSG; - } - - if (payload) { - hdr.type = byteorder_htons(gnrc_nettype_to_ethertype(payload->type)); - } - else { - hdr.type = byteorder_htons(ETHERTYPE_UNKNOWN); - } - - netif_hdr = pkt->data; - - /* set ethernet header */ - if (netif_hdr->src_l2addr_len == ETHERNET_ADDR_LEN) { - memcpy(hdr.dst, gnrc_netif_hdr_get_src_addr(netif_hdr), - netif_hdr->src_l2addr_len); - } - else { - dev->driver->get(dev, NETOPT_ADDRESS, hdr.src, ETHERNET_ADDR_LEN); - } - - if (netif_hdr->flags & GNRC_NETIF_HDR_FLAGS_BROADCAST) { - _addr_set_broadcast(hdr.dst); - } - else if (netif_hdr->flags & GNRC_NETIF_HDR_FLAGS_MULTICAST) { - if (payload == NULL) { - DEBUG("gnrc_netdev_eth: empty multicast packets over Ethernet "\ - "are not yet supported\n"); - return -ENOTSUP; - } - _addr_set_multicast(hdr.dst, payload); - } - else if (netif_hdr->dst_l2addr_len == ETHERNET_ADDR_LEN) { - memcpy(hdr.dst, gnrc_netif_hdr_get_dst_addr(netif_hdr), - ETHERNET_ADDR_LEN); - } - else { - DEBUG("gnrc_netdev_eth: destination address had unexpected format\n"); - return -EBADMSG; - } - - DEBUG("gnrc_netdev_eth: send to %02x:%02x:%02x:%02x:%02x:%02x\n", - hdr.dst[0], hdr.dst[1], hdr.dst[2], - hdr.dst[3], hdr.dst[4], hdr.dst[5]); - - size_t n; - payload = gnrc_pktbuf_get_iovec(pkt, &n); /* use payload as temporary - * variable */ - res = -ENOBUFS; - if (payload != NULL) { - pkt = payload; /* reassign for later release; vec_snip is prepended to pkt */ - struct iovec *vector = (struct iovec *)pkt->data; - vector[0].iov_base = (char*)&hdr; - vector[0].iov_len = sizeof(ethernet_hdr_t); -#ifdef MODULE_NETSTATS_L2 - if ((netif_hdr->flags & GNRC_NETIF_HDR_FLAGS_BROADCAST) || - (netif_hdr->flags & GNRC_NETIF_HDR_FLAGS_MULTICAST)) { - gnrc_netdev->dev->stats.tx_mcast_count++; - } - else { - gnrc_netdev->dev->stats.tx_unicast_count++; - } -#endif - res = dev->driver->send(dev, vector, n); - } - - gnrc_pktbuf_release(pkt); - - return res; -} - int gnrc_netdev_eth_init(gnrc_netdev_t *gnrc_netdev, netdev_t *dev) { gnrc_netdev->send = _send; diff --git a/sys/net/gnrc/netif2/gnrc_netif2.c b/sys/net/gnrc/netif2/gnrc_netif2.c new file mode 100644 index 0000000000000..b17f331a48e50 --- /dev/null +++ b/sys/net/gnrc/netif2/gnrc_netif2.c @@ -0,0 +1,1078 @@ +/* + * Copyright (C) 2014-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 + * @author Oliver Hahm + */ + +#include "bitfield.h" +#include "net/gnrc.h" +#include "log.h" +#include "sched.h" + +#include "net/gnrc/netif2.h" +#include "net/gnrc/netif2/internal.h" + +#define ENABLE_DEBUG (0) +#include "debug.h" + +#define _NETIF_NETAPI_MSG_QUEUE_SIZE (8) + +static gnrc_netif2_t _netifs[GNRC_NETIF_NUMOF]; + +static void _update_l2addr_from_dev(gnrc_netif2_t *netif); +static void *_gnrc_netif2_thread(void *args); +static void _event_cb(netdev_t *dev, netdev_event_t event); + +gnrc_netif2_t *gnrc_netif2_create(char *stack, int stacksize, char priority, + const char *name, netdev_t *netdev, + const gnrc_netif2_ops_t *ops) +{ + gnrc_netif2_t *netif = NULL; + int res; + + for (int i = 0; i < GNRC_NETIF_NUMOF; i++) { + if (_netifs[i].ops == NULL) { + netif = &_netifs[i]; + break; + } + } + if (netif == NULL) { + LOG_ERROR("gnrc_netif2: can not allocate network interface.\n" + "Set GNRC_NETIF_NUMOF to a higher value\n"); + return NULL; + } + rmutex_init(&netif->mutex); + netif->ops = ops; + assert(netif->dev == NULL); + netif->dev = netdev; + res = thread_create(stack, stacksize, priority, THREAD_CREATE_STACKTEST, + _gnrc_netif2_thread, (void *)netif, name); + assert(res > 0); + return netif; +} + +unsigned gnrc_netif2_numof(void) +{ + gnrc_netif2_t *netif = NULL; + unsigned res = 0; + + while ((netif = gnrc_netif2_iter(netif))) { + if (netif->ops != NULL) { + res++; + } + } + return res; +} + +gnrc_netif2_t *gnrc_netif2_iter(const gnrc_netif2_t *prev) +{ + assert((prev == NULL) || (prev >= _netifs)); + for (const gnrc_netif2_t *netif = (prev == NULL) ? _netifs : (prev + 1); + netif < (_netifs + GNRC_NETIF_NUMOF); netif++) { + if (netif->ops != NULL) { + /* we don't care about external modification */ + return (gnrc_netif2_t *)netif; + } + } + return NULL; +} + +int gnrc_netif2_get_from_netdev(gnrc_netif2_t *netif, gnrc_netapi_opt_t *opt) +{ + int res = -ENOTSUP; + + gnrc_netif2_acquire(netif); + switch (opt->opt) { + case NETOPT_HOP_LIMIT: + assert(opt->data_len == sizeof(uint8_t)); + *((uint8_t *)opt->data) = netif->cur_hl; + res = sizeof(uint8_t); + break; + case NETOPT_STATS: + assert(opt->data_len == sizeof(netstats_t)); + switch ((int16_t)opt->context) { + case GNRC_NETTYPE_NETIF: + case GNRC_NETTYPE_UNDEF: + /* take from device */ + break; +#if defined(MODULE_NETSTATS_IPV6) && defined(MODULE_GNRC_IPV6) + case GNRC_NETTYPE_IPV6: + memcpy(opt->data, &netif->ipv6_stats, + sizeof(netif->ipv6_stats)); + res = sizeof(netif->ipv6_stats); + break; +#endif + default: + break; + } +#ifdef MODULE_GNRC_IPV6 + case NETOPT_IPV6_ADDR: { + assert(opt->data_len >= sizeof(ipv6_addr_t)); + ipv6_addr_t *tgt = opt->data; + + res = 0; + for (ipv6_addr_t *addr = netif->ipv6_addrs; + (res < opt->data_len) && + (addr < netif->ipv6_addrs + GNRC_NETIF2_IPV6_ADDRS_NUMOF); + addr++, tgt++, res += sizeof(ipv6_addr_t)) { + } + } + break; + case NETOPT_IPV6_ADDR_FLAGS: + res = (opt->data_len < GNRC_NETIF2_IPV6_ADDRS_NUMOF) ? + opt->data_len : GNRC_NETIF2_IPV6_ADDRS_NUMOF; + memcpy(opt->data, netif->ipv6_addrs_flags, res); + case NETOPT_IPV6_GROUP: { + assert(opt->data_len >= sizeof(ipv6_addr_t)); + ipv6_addr_t *tgt = opt->data; + + res = 0; + for (ipv6_addr_t *addr = netif->ipv6_groups; + (res < opt->data_len) && + (addr < netif->ipv6_groups + GNRC_NETIF2_IPV6_ADDRS_NUMOF); + addr++, tgt++, res += sizeof(ipv6_addr_t)) { + memcpy(tgt, addr, sizeof(ipv6_addr_t)); + } + } + break; + case NETOPT_IPV6_IID: + assert(opt->data_len >= sizeof(eui64_t)); + gnrc_netif2_ipv6_get_iid(netif, opt->data); + res = sizeof(eui64_t); + break; + case NETOPT_MAX_PACKET_SIZE: + if (opt->context == GNRC_NETTYPE_IPV6) { + assert(opt->data_len == sizeof(uint16_t)); + *((uint16_t *)opt->data) = netif->ipv6_mtu; + res = sizeof(uint16_t); + } + /* else ask device */ + break; +#if GNRC_IPV6_NIB_CONF_ROUTER + case NETOPT_IPV6_FORWARDING: + assert(opt->data_len == sizeof(netopt_enable_t)); + *((netopt_enable_t *)opt->data) = (gnrc_netif2_is_rtr(netif)) ? + NETOPT_ENABLE : NETOPT_DISABLE; + break; + case NETOPT_IPV6_SND_RTR_ADV: + assert(opt->data_len == sizeof(netopt_enable_t)); + *((netopt_enable_t *)opt->data) = (gnrc_netif2_is_rtr_adv(netif)) ? + NETOPT_ENABLE : NETOPT_DISABLE; + break; +#endif /* GNRC_IPV6_NIB_CONF_ROUTER */ +#endif /* MODULE_GNRC_IPV6 */ +#ifdef MODULE_GNRC_SIXLOWPAN_IPHC + case NETOPT_6LO_IPHC: + assert(opt->data_len == sizeof(netopt_enable_t)); + *((netopt_enable_t *)opt->data) = (netif->flags & GNRC_NETIF2_FLAGS_6LO_HC) ? + NETOPT_ENABLE : NETOPT_DISABLE; + break; +#endif /* MODULE_GNRC_SIXLOWPAN_IPHC */ + default: + break; + } + if (res == -ENOTSUP) { + res = netif->dev->driver->get(netif->dev, opt->opt, opt->data, opt->data_len); + } + gnrc_netif2_release(netif); + return res; +} + +int gnrc_netif2_set_from_netdev(gnrc_netif2_t *netif, + const gnrc_netapi_opt_t *opt) +{ + int res = -ENOTSUP; + + gnrc_netif2_acquire(netif); + switch (opt->opt) { + case NETOPT_HOP_LIMIT: + assert(opt->data_len == sizeof(uint8_t)); + netif->cur_hl = *((uint8_t *)opt->data); + res = sizeof(uint8_t); + break; +#ifdef MODULE_GNRC_IPV6 + case NETOPT_IPV6_ADDR: { + assert(opt->data_len == sizeof(ipv6_addr_t)); + /* always assume manually added */ + uint8_t flags = ((((uint8_t)opt->context & 0xff) & + ~GNRC_NETIF2_IPV6_ADDRS_FLAGS_STATE_MASK) | + GNRC_NETIF2_IPV6_ADDRS_FLAGS_STATE_VALID); + uint8_t pfx_len = (uint8_t)(opt->context >> 8U); + /* acquire locks a recursive mutex so we are save calling this + * public function */ + gnrc_netif2_ipv6_addr_add(netif, opt->data, pfx_len, flags); + res = sizeof(ipv6_addr_t); + } + break; + case NETOPT_IPV6_ADDR_REMOVE: + assert(opt->data_len == sizeof(ipv6_addr_t)); + /* acquire locks a recursive mutex so we are save calling this + * public function */ + gnrc_netif2_ipv6_addr_remove(netif, opt->data); + res = sizeof(ipv6_addr_t); + break; + case NETOPT_IPV6_GROUP: + assert(opt->data_len == sizeof(ipv6_addr_t)); + /* acquire locks a recursive mutex so we are save calling this + * public function */ + gnrc_netif2_ipv6_group_join(netif, opt->data); + res = sizeof(ipv6_addr_t); + break; + case NETOPT_IPV6_GROUP_LEAVE: + assert(opt->data_len == sizeof(ipv6_addr_t)); + /* acquire locks a recursive mutex so we are save calling this + * public function */ + gnrc_netif2_ipv6_group_leave(netif, opt->data); + res = sizeof(ipv6_addr_t); + break; + case NETOPT_MAX_PACKET_SIZE: + if (opt->context == GNRC_NETTYPE_IPV6) { + assert(opt->data_len == sizeof(uint16_t)); + netif->ipv6_mtu = *((uint16_t *)opt->data); + res = sizeof(uint16_t); + } + /* else set device */ + break; +#if GNRC_IPV6_NIB_CONF_ROUTER + case NETOPT_IPV6_FORWARDING: + assert(opt->data_len == sizeof(netopt_enable_t)); + if (*(((netopt_enable_t *)opt->data)) == NETOPT_ENABLE) { + netif->flags |= GNRC_NETIF2_FLAGS_IPV6_FORWARDING; + } + else { + if (gnrc_netif2_is_rtr_adv(netif)) { + gnrc_ipv6_nib_iface_cease_rtr_adv(netif); + } + netif->flags &= ~GNRC_NETIF2_FLAGS_IPV6_FORWARDING; + } + break; + case NETOPT_IPV6_SND_RTR_ADV: + assert(opt->data_len == sizeof(netopt_enable_t)); + if (*(((netopt_enable_t *)opt->data)) == NETOPT_ENABLE) { + gnrc_ipv6_nib_iface_start_rtr_adv(netif); + } + else { + gnrc_ipv6_nib_iface_cease_rtr_adv(netif); + } + break; +#endif /* GNRC_IPV6_NIB_CONF_ROUTER */ +#endif /* MODULE_GNRC_IPV6 */ +#ifdef MODULE_GNRC_SIXLOWPAN_IPHC + case NETOPT_6LO_IPHC: + assert(opt->data_len == sizeof(netopt_enable_t)); + if (*(((netopt_enable_t *)opt->data)) == NETOPT_ENABLE) { + netif->flags |= GNRC_NETIF2_FLAGS_6LO_HC; + } + else { + netif->flags &= ~GNRC_NETIF2_FLAGS_6LO_HC; + } + break; +#endif /* MODULE_GNRC_SIXLOWPAN_IPHC */ + default: + break; + } + if (res == -ENOTSUP) { + res = netif->dev->driver->set(netif->dev, opt->opt, opt->data, + opt->data_len); + if (res > 0) { + switch (opt->opt) { + case NETOPT_ADDRESS: + case NETOPT_ADDRESS_LONG: + case NETOPT_ADDR_LEN: + case NETOPT_SRC_LEN: + _update_l2addr_from_dev(netif); + break; + default: + break; + } + } + } + gnrc_netif2_release(netif); + return res; +} + +gnrc_netif2_t *gnrc_netif2_get_by_pid(kernel_pid_t pid) +{ + gnrc_netif2_t *netif = NULL; + + while ((netif = gnrc_netif2_iter(netif))) { + if (netif->pid == pid) { + return netif; + } + } + return NULL; +} + +#ifdef MODULE_GNRC_IPV6 +static inline bool _addr_anycast(const gnrc_netif2_t *netif, unsigned idx); +static int _addr_idx(const gnrc_netif2_t *netif, const ipv6_addr_t *addr); + +/** + * @brief Matches an address by prefix to an address on the interface + * + * @param[in] netif the network interface + * @param[in] addr the address to match + * @param[in] filter a bitfield with the bits at the position equal to the + * indexes of the addresses you want to include in the + * search set to one. NULL for all addresses + * @param[out] idx index of the best match. -1 if no match was found. + * + * @return bits up to which the best match matches @p addr + * @return 0, if no match was found + */ +static unsigned _match(const gnrc_netif2_t *netif, const ipv6_addr_t *addr, + const uint8_t *filter, int *idx); + +/** + * @brief Determines the scope of the given address. + * + * @param[in] addr The IPv6 address to check. + * + * @return The scope of the address. + * + * @pre address is not loopback or unspecified. + * see http://tools.ietf.org/html/rfc6724#section-4 + */ +static uint8_t _get_scope(const ipv6_addr_t *addr); +static inline unsigned _get_state(const gnrc_netif2_t *netif, unsigned idx); + +/** + * @brief selects potential source address candidates + * @see + * RFC6724, section 4 + * + * @param[in] netif the interface used for sending + * @param[in] dst the destination address + * @param[in] ll_only only consider link-local addresses + * @param[out] candidate_set a bitfield representing all addresses + * configured to @p netif, potential candidates + * will be marked as 1 + * + * @return -1 if no candidates were found + * @return the index of the first candidate otherwise + * + * @pre the interface entry and its set of addresses must not be changed during + * runtime of this function + */ +static int _create_candidate_set(const gnrc_netif2_t *netif, + const ipv6_addr_t *dst, bool ll_only, + uint8_t *candidate_set); + +/** @brief Find the best candidate among the configured addresses + * for a certain destination address according to the 8 rules + * specified in RFC 6734, section 5. + * @see + * RFC6724, section 5 + * + * + * @param[in] netif The interface for sending. + * @param[in] dst The destination IPv6 address. + * @param[in, out] candidate_set The preselected set of candidate addresses as + * a bitfield. + * + * @pre @p dst is not unspecified. + * + * @return The best matching candidate found on @p netif, may be NULL if none + * is found. + */ +static ipv6_addr_t *_src_addr_selection(gnrc_netif2_t *netif, + const ipv6_addr_t *dst, + uint8_t *candidate_set); + +int gnrc_netif2_ipv6_addr_add(gnrc_netif2_t *netif, const ipv6_addr_t *addr, + unsigned pfx_len, uint8_t flags) +{ + unsigned idx = UINT_MAX; + + gnrc_netif2_acquire(netif); + if ((flags & GNRC_NETIF2_IPV6_ADDRS_FLAGS_STATE_MASK) == 0) { + flags |= GNRC_NETIF2_IPV6_ADDRS_FLAGS_STATE_TENTATIVE; + } + for (unsigned i = 0; i < GNRC_NETIF2_IPV6_ADDRS_NUMOF; i++) { + if (ipv6_addr_equal(&netif->ipv6_addrs[i], addr)) { + return 0; + } + if ((idx == UINT_MAX) && (netif->ipv6_addrs_flags[i] == 0)) { + idx = i; + } + } + if (idx == UINT_MAX) { + return -ENOMEM; + } + 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 */ + gnrc_netif2_release(netif); + return idx; +} + +void gnrc_netif2_ipv6_addr_remove(gnrc_netif2_t *netif, + const ipv6_addr_t *addr) +{ + int idx; + + assert((netif != NULL) && (addr != NULL)); + gnrc_netif2_acquire(netif); + idx = _addr_idx(netif, addr); + 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); +} + +int gnrc_netif2_ipv6_addr_idx(gnrc_netif2_t *netif, + const ipv6_addr_t *addr) +{ + int idx; + + assert((netif != NULL) && (addr != NULL)); + gnrc_netif2_acquire(netif); + idx = _addr_idx(netif, addr); + gnrc_netif2_release(netif); + return idx; +} + +int gnrc_netif2_ipv6_addr_match(gnrc_netif2_t *netif, + const ipv6_addr_t *addr) +{ + int idx; + + assert((netif != NULL) && (addr != NULL)); + gnrc_netif2_acquire(netif); + _match(netif, addr, NULL, &idx); + gnrc_netif2_release(netif); + return idx; +} + +ipv6_addr_t *gnrc_netif2_ipv6_addr_best_src(gnrc_netif2_t *netif, + const ipv6_addr_t *dst, + bool ll_only) +{ + ipv6_addr_t *best_src = NULL; + BITFIELD(candidate_set, GNRC_NETIF2_IPV6_ADDRS_NUMOF); + + memset(candidate_set, 0, sizeof(candidate_set)); + gnrc_netif2_acquire(netif); + int first_candidate = _create_candidate_set(netif, dst, ll_only, + candidate_set); + if (first_candidate >= 0) { + best_src = _src_addr_selection(netif, dst, candidate_set); + if (best_src == NULL) { + best_src = &(netif->ipv6_addrs[first_candidate]); + } + } + gnrc_netif2_release(netif); + return best_src; +} + +gnrc_netif2_t *gnrc_netif2_get_by_ipv6_addr(const ipv6_addr_t *addr) +{ + gnrc_netif2_t *netif = NULL; + + while ((netif = gnrc_netif2_iter(netif))) { + if (_addr_idx(netif, addr) >= 0) { + break; + } + } + return netif; +} + +gnrc_netif2_t *gnrc_netif2_get_by_prefix(const ipv6_addr_t *prefix) +{ + gnrc_netif2_t *netif = NULL, *best_netif = NULL; + unsigned best_match = 0; + + while ((netif = gnrc_netif2_iter(netif))) { + unsigned match; + int idx; + + if (((match = _match(netif, prefix, NULL, &idx)) > 0) && + (match > best_match)) { + best_match = match; + best_netif = netif; + } + } + return best_netif; +} + +int gnrc_netif2_ipv6_group_join(gnrc_netif2_t *netif, + const ipv6_addr_t *addr) +{ + unsigned idx = UINT_MAX; + + gnrc_netif2_acquire(netif); + for (unsigned i = 0; i < GNRC_NETIF2_IPV6_GROUPS_NUMOF; i++) { + if (ipv6_addr_equal(&netif->ipv6_groups[i], addr)) { + return 0; + } + if ((idx == UINT_MAX) && (ipv6_addr_is_unspecified(&netif->ipv6_groups[i]))) { + idx = i; + } + } + if (idx == UINT_MAX) { + return -ENOMEM; + } + memcpy(&netif->ipv6_groups[idx], addr, sizeof(netif->ipv6_groups[idx])); + /* TODO: + * - MLD action + */ + gnrc_netif2_release(netif); + return idx; +} + +void gnrc_netif2_ipv6_group_leave(gnrc_netif2_t *netif, + const ipv6_addr_t *addr) +{ + int idx; + + assert((netif != NULL) && (addr != NULL)); + gnrc_netif2_acquire(netif); + for (unsigned i = 0; i < GNRC_NETIF2_IPV6_ADDRS_NUMOF; i++) { + if (ipv6_addr_equal(&netif->ipv6_groups[i], addr)) { + ipv6_addr_set_unspecified(&netif->ipv6_groups[idx]); + /* TODO: + * - MLD action */ + break; + } + } + gnrc_netif2_release(netif); +} + +void gnrc_netif2_ipv6_get_iid(gnrc_netif2_t *netif, + eui64_t *eui64) +{ +#if GNRC_NETIF2_L2ADDR_MAXLEN > 0 + if (netif->flags & GNRC_NETIF2_FLAGS_HAS_L2ADDR) { + switch (netif->device_type) { +#ifdef MODULE_NETDEV_ETH + case NETDEV_TYPE_ETHERNET: + assert(netif->l2addr_len == ETHERNET_ADDR_LEN); + eui64->uint8[0] = netif->l2addr[0] ^ 0x02; + eui64->uint8[1] = netif->l2addr[1]; + eui64->uint8[2] = netif->l2addr[2]; + eui64->uint8[3] = 0xff; + eui64->uint8[4] = 0xfe; + eui64->uint8[5] = netif->l2addr[3]; + eui64->uint8[6] = netif->l2addr[4]; + eui64->uint8[7] = netif->l2addr[5]; + return; +#endif +#ifdef MODULE_NETDEV_IEEE802154 + case NETDEV_TYPE_IEEE802154: + switch (netif->l2addr_len) { + case IEEE802154_SHORT_ADDRESS_LEN: + eui64->uint8[0] = 0x0; + eui64->uint8[1] = 0x0; + eui64->uint8[2] = 0x0; + eui64->uint8[3] = 0xff; + eui64->uint8[4] = 0xfe; + eui64->uint8[5] = 0x0; + eui64->uint8[6] = netif->l2addr[0]; + eui64->uint8[7] = netif->l2addr[1]; + return; + case IEEE802154_LONG_ADDRESS_LEN: + memcpy(eui64, netif->l2addr, sizeof(eui64_t)); + eui64->uint8[0] ^= 0x02; + return; + default: + /* this should not happen */ + assert(false); + break; + } + break; +#endif +#ifdef MODULE_CC110X + case NETDEV_TYPE_CC110X: + assert(netif->l2addr_len == 1U); + eui64->uint8[0] = 0x0; + eui64->uint8[1] = 0x0; + eui64->uint8[2] = 0x0; + eui64->uint8[3] = 0xff; + eui64->uint8[4] = 0xfe; + eui64->uint8[5] = 0x0; + eui64->uint8[6] = 0x0; + eui64->uint8[7] = netif->l2addr[0]; + return; +#endif + default: + break; + } + } +#endif + memset(eui64, 0, sizeof(eui64_t)); +} + +static inline bool _addr_anycast(const gnrc_netif2_t *netif, unsigned idx) +{ + return (netif->ipv6_addrs_flags[idx] & GNRC_NETIF2_IPV6_ADDRS_FLAGS_ANYCAST); +} + +static int _addr_idx(const gnrc_netif2_t *netif, const ipv6_addr_t *addr) +{ + for (unsigned i = 0; i < GNRC_NETIF2_IPV6_ADDRS_NUMOF; i++) { + if (ipv6_addr_equal(&netif->ipv6_addrs[i], addr)) { + return i; + } + } + return -1; +} + +static unsigned _match(const gnrc_netif2_t *netif, const ipv6_addr_t *addr, + const uint8_t *filter, int *idx) +{ + unsigned best_match = 0; + + assert(idx != NULL); + *idx = -1; + for (int i = 0; i < GNRC_NETIF2_IPV6_ADDRS_NUMOF; i++) { + unsigned match; + + if ((netif->ipv6_addrs_flags[i] == 0) || + ((filter != NULL) && _addr_anycast(netif, i)) || + /* discard const intentionally */ + ((filter != NULL) && !(bf_isset((uint8_t *)filter, i)))) { + continue; + } + match = ipv6_addr_match_prefix(&(netif->ipv6_addrs[i]), addr); + if (((match > 64U) || !ipv6_addr_is_link_local(&(netif->ipv6_addrs[i]))) && + (match > best_match)) { + if (idx != NULL) { + *idx = i; + } + best_match = match; + } + } +#if ENABLE_DEBUG + if (*idx >= 0) { + DEBUG("gnrc_netif2: Found %s on interface %" PRIkernel_pid " matching ", + ipv6_addr_to_str(addr_str, &netif->ipv6_addrs[*idx], + sizeof(addr_str)), + netif->pid); + DEBUG("%s by %" PRIu8 " bits (used as source address = %s)\n", + ipv6_addr_to_str(addr_str, addr, sizeof(addr_str)), + best_match, + (filter != NULL) ? "true" : "false"); + } + else { + DEBUG("gnrc_netif2: Did not found any address on interface %" PRIkernel_pid + " matching %s (used as source address = %s)\n", + netif->pid, + ipv6_addr_to_str(addr_str, addr, sizeof(addr_str)), + (filter != NULL) ? "true" : "false"); + } +#endif + return best_match; +} + +static uint8_t _get_scope(const ipv6_addr_t *addr) +{ + if (ipv6_addr_is_link_local(addr)) { + return IPV6_ADDR_MCAST_SCP_LINK_LOCAL; + } + else if (ipv6_addr_is_site_local(addr)) { + return IPV6_ADDR_MCAST_SCP_SITE_LOCAL; + } + else { + return IPV6_ADDR_MCAST_SCP_GLOBAL; + } +} + +static inline unsigned _get_state(const gnrc_netif2_t *netif, unsigned idx) +{ + return (netif->ipv6_addrs_flags[idx] & + GNRC_NETIF2_IPV6_ADDRS_FLAGS_STATE_MASK); +} + +/** + * @brief selects potential source address candidates + * @see + * RFC6724, section 4 + * + * @param[in] netif the interface used for sending + * @param[in] dst the destination address + * @param[in] ll_only only consider link-local addresses + * @param[out] candidate_set a bitfield representing all addresses + * configured to @p netif, potential candidates + * will be marked as 1 + * + * @return -1 if no candidates were found + * @return the index of the first candidate otherwise + * + * @pre the interface entry and its set of addresses must not be changed during + * runtime of this function + */ +static int _create_candidate_set(const gnrc_netif2_t *netif, + const ipv6_addr_t *dst, bool ll_only, + uint8_t *candidate_set) +{ + int res = -1; + + DEBUG("gathering candidates\n"); + /* currently this implementation supports only addresses as source address + * candidates assigned to this interface. Thus we assume all addresses to be + * on interface @p netif */ + (void) dst; + for (int i = 0; i < GNRC_NETIF2_IPV6_ADDRS_NUMOF; i++) { + const ipv6_addr_t *tmp = &(netif->ipv6_addrs[i]); + + DEBUG("Checking address: %s\n", + ipv6_addr_to_str(addr_str, tmp, sizeof(addr_str))); + /* "In any case, multicast addresses and the unspecified address MUST NOT + * be included in a candidate set." + */ + if (netif->ipv6_addrs_flags[i] == 0) { + continue; + } + /* Check if we only want link local addresses */ + if (ll_only && !ipv6_addr_is_link_local(tmp)) { + continue; + } + /* "For all multicast and link-local destination addresses, the set of + * candidate source addresses MUST only include addresses assigned to + * interfaces belonging to the same link as the outgoing interface." + * + * "For site-local unicast destination addresses, the set of candidate + * source addresses MUST only include addresses assigned to interfaces + * belonging to the same site as the outgoing interface." + * -> we should also be fine, since we're only iterating addresses of + * the sending interface + */ + /* put all other addresses into the candidate set */ + DEBUG("add to candidate set\n"); + bf_set(candidate_set, i); + if (res < 0) { + res = i; + } + } + return res; +} + +/* number of "points" assigned to an source address candidate with equal scope + * than destination address */ +#define RULE_2A_PTS (4) +/* number of "points" assigned to an source address candidate with smaller scope + * than destination address */ +#define RULE_2B_PTS (2) +/* number of "points" assigned to an source address candidate in preferred state */ +#define RULE_3_PTS (1) + +static ipv6_addr_t *_src_addr_selection(gnrc_netif2_t *netif, + const ipv6_addr_t *dst, + uint8_t *candidate_set) +{ + /* create temporary set for assigning "points" to candidates wining in the + * corresponding rules. + */ + uint8_t winner_set[GNRC_NETIF2_IPV6_ADDRS_NUMOF]; + memset(winner_set, 0, GNRC_NETIF2_IPV6_ADDRS_NUMOF); + uint8_t max_pts = 0; + /* _create_candidate_set() assures that `dst` is not unspecified and if + * `dst` is loopback rule 1 will fire anyway. */ + uint8_t dst_scope = _get_scope(dst); + + DEBUG("finding the best match within the source address candidates\n"); + for (unsigned i = 0; i < GNRC_NETIF2_IPV6_ADDRS_NUMOF; i++) { + ipv6_addr_t *ptr = &(netif->ipv6_addrs[i]); + + DEBUG("Checking address: %s\n", + ipv6_addr_to_str(addr_str, ptr, sizeof(addr_str))); + /* entries which are not part of the candidate set can be ignored */ + if (!(bf_isset(candidate_set, i))) { + DEBUG("Not part of the candidate set - skipping\n"); + continue; + } + /* Rule 1: if we have an address configured that equals the destination + * use this one as source */ + if (ipv6_addr_equal(ptr, dst)) { + DEBUG("Ease one - rule 1\n"); + return ptr; + } + /* Rule 2: Prefer appropriate scope. */ + /* both link local */ + uint8_t candidate_scope = _get_scope(ptr); + if (candidate_scope == dst_scope) { + DEBUG("winner for rule 2 (same scope) found\n"); + winner_set[i] += RULE_2A_PTS; + if (winner_set[i] > max_pts) { + max_pts = RULE_2A_PTS; + } + } + else if (candidate_scope < dst_scope) { + DEBUG("winner for rule 2 (smaller scope) found\n"); + winner_set[i] += RULE_2B_PTS; + if (winner_set[i] > max_pts) { + max_pts = winner_set[i]; + } + } + /* Rule 3: Avoid deprecated addresses. */ + if (_get_state(netif, i) == GNRC_NETIF2_IPV6_ADDRS_FLAGS_STATE_DEPRECATED) { + DEBUG("winner for rule 3 found\n"); + winner_set[i] += RULE_3_PTS; + if (winner_set[i] > max_pts) { + max_pts = winner_set[i]; + } + } + + /* Rule 4: Prefer home addresses. + * Does not apply, gnrc does not support Mobile IP. + * TODO: update as soon as gnrc supports Mobile IP + */ + + /* Rule 5: Prefer outgoing interface. + * RFC 6724 says: + * "It is RECOMMENDED that the candidate source addresses be the set of + * unicast addresses assigned to the interface that will be used to + * send to the destination (the "outgoing" interface). On routers, + * the candidate set MAY include unicast addresses assigned to any + * interface that forwards packets, subject to the restrictions + * described below." + * Currently this implementation uses ALWAYS source addresses assigned + * to the outgoing interface. Hence, Rule 5 is always fulfilled. + */ + + /* Rule 6: Prefer matching label. + * Flow labels are currently not supported by gnrc. + * TODO: update as soon as gnrc supports flow labels + */ + + /* Rule 7: Prefer temporary addresses. + * Temporary addresses are currently not supported by gnrc. + * TODO: update as soon as gnrc supports temporary addresses + */ + } + /* reset candidate set to mark winners */ + memset(candidate_set, 0, (GNRC_NETIF2_IPV6_ADDRS_NUMOF + 7) / 8); + /* check if we have a clear winner */ + /* collect candidates with maximum points */ + for (int i = 0; i < GNRC_NETIF2_IPV6_ADDRS_NUMOF; i++) { + if (winner_set[i] == max_pts) { + bf_set(candidate_set, i); + } + } + /* otherwise apply rule 8: Use longest matching prefix. */ + int res; + _match(netif, dst, candidate_set, &res); + return (res < 0) ? NULL : &netif->ipv6_addrs[res]; +} +#endif /* MODULE_GNRC_IPV6 */ + +static void _update_l2addr_from_dev(gnrc_netif2_t *netif) +{ + netdev_t *dev = netif->dev; + int res; + netopt_t opt = NETOPT_ADDRESS; + + switch (netif->device_type) { +#ifdef MODULE_NETDEV_IEEE802154 + case NETDEV_TYPE_IEEE802154: + res = dev->driver->get(dev, NETOPT_SRC_LEN, &tmp, sizeof(tmp)); + assert(res == sizeof(tmp)); + netif->l2addr_len = (uint8_t)tmp; + if (tmp == IEEE802154_LONG_ADDRESS_LEN) { + opt = NETOPT_ADDRESS_LONG; + } + break; +#endif + default: + break; + } + res = dev->driver->get(dev, opt, netif->l2addr, + sizeof(netif->l2addr)); + if (res == -ENOTSUP) { + netif->flags |= GNRC_NETIF2_FLAGS_HAS_L2ADDR; + } +} + +static void _init_from_device(gnrc_netif2_t *netif) +{ + int res; + netdev_t *dev = netif->dev; + uint16_t tmp; + + res = dev->driver->get(dev, NETOPT_DEVICE_TYPE, &tmp, sizeof(tmp)); + assert(res == sizeof(tmp)); + netif->device_type = (uint8_t)tmp; + switch (netif->device_type) { +#ifdef MODULE_NETDEV_IEEE802154 + case NETDEV_TYPE_IEEE802154: +#ifdef MODULE_GNRC_SIXLOWPAN_IPHC + netif->flags |= GNRC_NETIF2_FLAGS_6LO_HC; +#endif + res = dev->driver->get(dev, NETOPT_MAX_PACKET_SIZE, &tmp, sizeof(tmp)); + assert(res == sizeof(tmp)); +#ifdef MODULE_GNRC_SIXLOWPAN_FRAG + netif->ipv6_mtu = IPV6_MIN_MTU; + netif->max_frag_size = tmp; +#else + netif->ipv6_mtu = tmp; +#endif + break; +#endif /* MODULE_NETDEV_IEEE802154 */ +#ifdef MODULE_NETDEV_ETH + case NETDEV_TYPE_ETHERNET: + netif->ipv6_mtu = ETHERNET_DATA_LEN; + break; +#endif + default: + res = dev->driver->get(dev, NETOPT_MAX_PACKET_SIZE, &tmp, sizeof(tmp)); + assert(res == sizeof(tmp)); + netif->ipv6_mtu = tmp; + } + _update_l2addr_from_dev(netif); +} + +static void *_gnrc_netif2_thread(void *args) +{ + gnrc_netapi_opt_t *opt; + gnrc_netif2_t *netif; + netdev_t *dev; + int res; + msg_t reply = { .type = GNRC_NETAPI_MSG_TYPE_ACK }; + msg_t msg, msg_queue[_NETIF_NETAPI_MSG_QUEUE_SIZE]; + + DEBUG("gnrc_netif2: starting thread %i\n", sched_active_pid); + netif = args; + gnrc_netif2_acquire(netif); + dev = netif->dev; + netif->pid = sched_active_pid; + /* setup the link-layer's message queue */ + msg_init_queue(msg_queue, _NETIF_NETAPI_MSG_QUEUE_SIZE); + /* register the event callback with the device driver */ + dev->event_callback = _event_cb; + dev->context = netif; + /* initialize low-level driver */ + dev->driver->init(dev); + _init_from_device(netif); + netif->cur_hl = GNRC_NETIF2_DEFAULT_HL; +#ifdef MODULE_GNRC_IPV6_NIB + gnrc_ipv6_nib_init_iface(netif); +#endif + /* now let rest of GNRC use the interface */ + gnrc_netif2_release(netif); + + while (1) { + DEBUG("gnrc_netif2: waiting for incoming messages\n"); + msg_receive(&msg); + /* dispatch netdev, MAC and gnrc_netapi messages */ + switch (msg.type) { + case NETDEV_MSG_TYPE_EVENT: + DEBUG("gnrc_netif2: GNRC_NETDEV_MSG_TYPE_EVENT received\n"); + dev->driver->isr(dev); + break; + case GNRC_NETAPI_MSG_TYPE_SND: + DEBUG("gnrc_netif2: GNRC_NETDEV_MSG_TYPE_SND received\n"); + res = netif->ops->send(netif, msg.content.ptr); +#if ENABLE_DEBUG + if (res < 0) { + DEBUG("gnrc_netif2: error sending packet %p (code: %u)\n", + msg.content.ptr, res); + } +#endif + break; + case GNRC_NETAPI_MSG_TYPE_SET: + opt = msg.content.ptr; + DEBUG("gnrc_netif2: GNRC_NETAPI_MSG_TYPE_SET received. opt=%s\n", + netopt2str(opt->opt)); + /* set option for device driver */ + res = netif->ops->set(netif, opt); + DEBUG("gnrc_netif2: response of netif->ops->set(): %i\n", res); + reply.content.value = (uint32_t)res; + msg_reply(&msg, &reply); + break; + case GNRC_NETAPI_MSG_TYPE_GET: + opt = msg.content.ptr; + DEBUG("gnrc_netif2: GNRC_NETAPI_MSG_TYPE_GET received. opt=%s\n", + netopt2str(opt->opt)); + /* get option from device driver */ + res = netif->ops->get(netif, opt); + DEBUG("gnrc_netif2: response of netif->ops->get(): %i\n", res); + reply.content.value = (uint32_t)res; + msg_reply(&msg, &reply); + break; + default: + if (netif->ops->msg_handler) { + DEBUG("gnrc_netif2: delegate message of type 0x%04x to " + "netif->ops->msg_handler()\n", msg.type); + netif->ops->msg_handler(netif, &msg); + } +#if ENABLE_DEBUG + else { + DEBUG("gnrc_netif2: unknown message type 0x%04x" + "(no message handler defined)\n", msg.type); + } +#endif + break; + } + } + /* never reached */ + return NULL; +} + +static void _pass_on_packet(gnrc_pktsnip_t *pkt) +{ + /* throw away packet if no one is interested */ + if (!gnrc_netapi_dispatch_receive(pkt->type, GNRC_NETREG_DEMUX_CTX_ALL, pkt)) { + DEBUG("gnrc_netif2: unable to forward packet of type %i\n", pkt->type); + gnrc_pktbuf_release(pkt); + return; + } +} + +static void _event_cb(netdev_t *dev, netdev_event_t event) +{ + gnrc_netif2_t *netif = (gnrc_netif2_t*) dev->context; + + if (event == NETDEV_EVENT_ISR) { + msg_t msg = { .type = NETDEV_MSG_TYPE_EVENT, + .content = { .ptr = netif } }; + + if (msg_send(&msg, netif->pid) <= 0) { + puts("gnrc_netif2: possibly lost interrupt."); + } + } + else { + DEBUG("gnrc_netif2: event triggered -> %i\n", event); + switch(event) { + case NETDEV_EVENT_RX_COMPLETE: + { + gnrc_pktsnip_t *pkt = netif->ops->recv(netif); + + if (pkt) { + _pass_on_packet(pkt); + } + + break; + } +#ifdef MODULE_NETSTATS_L2 + case NETDEV_EVENT_TX_MEDIUM_BUSY: + /* we are the only ones supposed to touch this variable, + * so no acquire necessary */ + dev->stats.tx_failed++; + break; + case NETDEV_EVENT_TX_COMPLETE: + /* we are the only ones supposed to touch this variable, + * so no acquire necessary */ + dev->stats.tx_success++; + break; +#endif + default: + DEBUG("gnrc_netif2: warning: unhandled event %u.\n", event); + } + } +} +/** @} */ diff --git a/sys/net/gnrc/netif2/gnrc_netif2_ethernet.c b/sys/net/gnrc/netif2/gnrc_netif2_ethernet.c new file mode 100644 index 0000000000000..b2664f8e71887 --- /dev/null +++ b/sys/net/gnrc/netif2/gnrc_netif2_ethernet.c @@ -0,0 +1,250 @@ +/* + * Copyright (C) 2015 Kaspar Schleiser + * 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 + * @author Kaspar Schleiser + */ + +#include "net/ethernet/hdr.h" +#include "net/gnrc.h" +#include "net/gnrc/netif2/ethernet.h" +#ifdef MODULE_GNRC_IPV6 +#include "net/ipv6/hdr.h" +#endif + +#define ENABLE_DEBUG (0) +#include "debug.h" + +static int _send(gnrc_netif2_t *netif, gnrc_pktsnip_t *pkt); +static gnrc_pktsnip_t *_recv(gnrc_netif2_t *netif); + +static const gnrc_netif2_ops_t ethernet_ops = { + .send = _send, + .recv = _recv, + .get = gnrc_netif2_get_from_netdev, + .set = gnrc_netif2_set_from_netdev, + .msg_handler = NULL, +}; + +gnrc_netif2_t *gnrc_netif2_ethernet_create(char *stack, int stacksize, + char priority, char *name, + netdev_t *dev) +{ + return gnrc_netif2_create(stack, stacksize, priority, name, dev, + ðernet_ops); +} + +static inline void _addr_set_broadcast(uint8_t *dst) +{ + memset(dst, 0xff, ETHERNET_ADDR_LEN); +} + +static inline void _addr_set_multicast(uint8_t *dst, gnrc_pktsnip_t *payload) +{ + switch (payload->type) { +#ifdef MODULE_GNRC_IPV6 + case GNRC_NETTYPE_IPV6: + /* https://tools.ietf.org/html/rfc2464#section-7 */ + dst[0] = 0x33; + dst[1] = 0x33; + ipv6_hdr_t *ipv6 = payload->data; + memcpy(dst + 2, ipv6->dst.u8 + 12, 4); + break; +#endif + default: + _addr_set_broadcast(dst); + break; + } +} + +static int _send(gnrc_netif2_t *netif, gnrc_pktsnip_t *pkt) +{ + ethernet_hdr_t hdr; + gnrc_netif_hdr_t *netif_hdr; + gnrc_pktsnip_t *payload; + int res; + + netdev_t *dev = netif->dev; + + if (pkt == NULL) { + DEBUG("gnrc_netif2_ethernet: pkt was NULL\n"); + return -EINVAL; + } + + payload = pkt->next; + + if (pkt->type != GNRC_NETTYPE_NETIF) { + DEBUG("gnrc_netif2_ethernet: First header was not generic netif header\n"); + return -EBADMSG; + } + + if (payload) { + hdr.type = byteorder_htons(gnrc_nettype_to_ethertype(payload->type)); + } + else { + hdr.type = byteorder_htons(ETHERTYPE_UNKNOWN); + } + + netif_hdr = pkt->data; + + /* set ethernet header */ + if (netif_hdr->src_l2addr_len == ETHERNET_ADDR_LEN) { + memcpy(hdr.dst, gnrc_netif_hdr_get_src_addr(netif_hdr), + netif_hdr->src_l2addr_len); + } + else { + dev->driver->get(dev, NETOPT_ADDRESS, hdr.src, ETHERNET_ADDR_LEN); + } + + if (netif_hdr->flags & GNRC_NETIF_HDR_FLAGS_BROADCAST) { + _addr_set_broadcast(hdr.dst); + } + else if (netif_hdr->flags & GNRC_NETIF_HDR_FLAGS_MULTICAST) { + if (payload == NULL) { + DEBUG("gnrc_netif2_ethernet: empty multicast packets over Ethernet " + "are not yet supported\n"); + return -ENOTSUP; + } + _addr_set_multicast(hdr.dst, payload); + } + else if (netif_hdr->dst_l2addr_len == ETHERNET_ADDR_LEN) { + memcpy(hdr.dst, gnrc_netif_hdr_get_dst_addr(netif_hdr), + ETHERNET_ADDR_LEN); + } + else { + DEBUG("gnrc_netif2_ethernet: destination address had unexpected " + "format\n"); + return -EBADMSG; + } + + DEBUG("gnrc_netif2_ethernet: send to %02x:%02x:%02x:%02x:%02x:%02x\n", + hdr.dst[0], hdr.dst[1], hdr.dst[2], + hdr.dst[3], hdr.dst[4], hdr.dst[5]); + + size_t n; + payload = gnrc_pktbuf_get_iovec(pkt, &n); /* use payload as temporary + * variable */ + res = -ENOBUFS; + if (payload != NULL) { + pkt = payload; /* reassign for later release; vec_snip is prepended to pkt */ + struct iovec *vector = (struct iovec *)pkt->data; + vector[0].iov_base = (char*)&hdr; + vector[0].iov_len = sizeof(ethernet_hdr_t); +#ifdef MODULE_NETSTATS_L2 + if ((netif_hdr->flags & GNRC_NETIF_HDR_FLAGS_BROADCAST) || + (netif_hdr->flags & GNRC_NETIF_HDR_FLAGS_MULTICAST)) { + dev->stats.tx_mcast_count++; + } + else { + dev->stats.tx_unicast_count++; + } +#endif + res = dev->driver->send(dev, vector, n); + } + + gnrc_pktbuf_release(pkt); + + return res; +} + +static gnrc_pktsnip_t *_recv(gnrc_netif2_t *netif) +{ + netdev_t *dev = netif->dev; + int bytes_expected = dev->driver->recv(dev, NULL, 0, NULL); + gnrc_pktsnip_t *pkt = NULL; + + if (bytes_expected > 0) { + pkt = gnrc_pktbuf_add(NULL, NULL, + bytes_expected, + GNRC_NETTYPE_UNDEF); + + if(!pkt) { + DEBUG("gnrc_netif2_ethernet: cannot allocate pktsnip.\n"); + + /* drop the packet */ + dev->driver->recv(dev, NULL, bytes_expected, NULL); + + goto out; + } + + int nread = dev->driver->recv(dev, pkt->data, bytes_expected, NULL); + if(nread <= 0) { + DEBUG("gnrc_netif2_ethernet: read error.\n"); + goto safe_out; + } + + if (nread < bytes_expected) { + /* we've got less then the expected packet size, + * so free the unused space.*/ + + DEBUG("gnrc_netif2_ethernet: reallocating.\n"); + gnrc_pktbuf_realloc_data(pkt, nread); + } + + /* mark ethernet header */ + gnrc_pktsnip_t *eth_hdr = gnrc_pktbuf_mark(pkt, sizeof(ethernet_hdr_t), GNRC_NETTYPE_UNDEF); + if (!eth_hdr) { + DEBUG("gnrc_netif2_ethernet: no space left in packet buffer\n"); + goto safe_out; + } + + ethernet_hdr_t *hdr = (ethernet_hdr_t *)eth_hdr->data; + +#ifdef MODULE_L2FILTER + if (!l2filter_pass(dev->filter, hdr->src, ETHERNET_ADDR_LEN)) { + DEBUG("gnrc_netif2_ethernet: incoming packet filtered by l2filter\n"); + goto safe_out; + } +#endif + + /* set payload type from ethertype */ + pkt->type = gnrc_nettype_from_ethertype(byteorder_ntohs(hdr->type)); + + /* create netif header */ + gnrc_pktsnip_t *netif_hdr; + netif_hdr = gnrc_pktbuf_add(NULL, NULL, + sizeof(gnrc_netif_hdr_t) + (2 * ETHERNET_ADDR_LEN), + GNRC_NETTYPE_NETIF); + + if (netif_hdr == NULL) { + DEBUG("gnrc_netif2_ethernet: no space left in packet buffer\n"); + pkt = eth_hdr; + goto safe_out; + } + + gnrc_netif_hdr_init(netif_hdr->data, ETHERNET_ADDR_LEN, ETHERNET_ADDR_LEN); + gnrc_netif_hdr_set_src_addr(netif_hdr->data, hdr->src, ETHERNET_ADDR_LEN); + gnrc_netif_hdr_set_dst_addr(netif_hdr->data, hdr->dst, ETHERNET_ADDR_LEN); + ((gnrc_netif_hdr_t *)netif_hdr->data)->if_pid = thread_getpid(); + + DEBUG("gnrc_netif2_ethernet: received packet from %02x:%02x:%02x:%02x:%02x:%02x " + "of length %d\n", + hdr->src[0], hdr->src[1], hdr->src[2], hdr->src[3], hdr->src[4], + hdr->src[5], nread); +#if defined(MODULE_OD) && ENABLE_DEBUG + od_hex_dump(hdr, nread, OD_WIDTH_DEFAULT); +#endif + + gnrc_pktbuf_remove_snip(pkt, eth_hdr); + LL_APPEND(pkt, netif_hdr); + } + +out: + return pkt; + +safe_out: + gnrc_pktbuf_release(pkt); + return NULL; +} + +/** @} */ From 36334fcdbcd19dd5f42a689c9f86069a3d193193 Mon Sep 17 00:00:00 2001 From: Martine Lenders Date: Wed, 19 Jul 2017 14:25:57 +0200 Subject: [PATCH 02/31] fixup! gnrc_netif2: Introduction of a new GNRC network interface API --- sys/include/net/gnrc/netif2.h | 8 ++------ 1 file changed, 2 insertions(+), 6 deletions(-) diff --git a/sys/include/net/gnrc/netif2.h b/sys/include/net/gnrc/netif2.h index ebb594e22376d..d6124d4b0a824 100644 --- a/sys/include/net/gnrc/netif2.h +++ b/sys/include/net/gnrc/netif2.h @@ -220,9 +220,7 @@ extern "C" { * packet */ #define GNRC_NETIF2_FLAGS_MAC_RX_STARTED (0x00008000U) -/** - * @} - */ +/** @} */ /** * @name IPv6 unicast and anycast address flags @@ -253,9 +251,7 @@ extern "C" { * @brief Address is an anycast address */ #define GNRC_NETIF2_IPV6_ADDRS_FLAGS_ANYCAST (0x04U) -/** - * @} - */ +/** @} */ /** * @brief Auto-address configuration modes From 7d0e4cae3904ab6fa7e9ab1166eda69199568230 Mon Sep 17 00:00:00 2001 From: Martine Lenders Date: Wed, 19 Jul 2017 15:53:27 +0200 Subject: [PATCH 03/31] fixup! gnrc_netif2: Introduction of a new GNRC network interface API --- sys/include/net/gnrc/netif2.h | 4 +- .../gnrc/link_layer/netdev/gnrc_netdev_eth.c | 112 ++++++++++++++++++ sys/net/gnrc/netif2/gnrc_netif2.c | 18 +-- sys/net/gnrc/netif2/gnrc_netif2_ethernet.c | 20 ++-- 4 files changed, 132 insertions(+), 22 deletions(-) diff --git a/sys/include/net/gnrc/netif2.h b/sys/include/net/gnrc/netif2.h index d6124d4b0a824..eb996ae3346ac 100644 --- a/sys/include/net/gnrc/netif2.h +++ b/sys/include/net/gnrc/netif2.h @@ -295,7 +295,7 @@ typedef struct { * @ref GNRC_MAC_NEIGHBOR_COUNT is greater than 0. */ gnrc_mac_tx_t tx; -#endif /* ((GNRC_MAC_TX_QUEUE_SIZE != 0) || (GNRC_MAC_NEIGHBOR_COUNT == 0)) || DOXYGEN */ +#endif /* ((GNRC_MAC_TX_QUEUE_SIZE != 0) || (GNRC_MAC_NEIGHBOR_COUNT == 0)) || DOXYGEN */ #endif /* MODULE_GNRC_MAC */ #ifdef MODULE_NETSTATS_IPV6 /** @@ -612,8 +612,6 @@ gnrc_netif2_t *gnrc_netif2_create(char *stack, int stacksize, char priority, const gnrc_netif2_ops_t *ops); /** -int gnrc_netif2_get_from_netdev(gnrc_netif2_t *netif, netopt_t opt, void *data, - size_t max_len); * @brief Get number of network interfaces actually allocated * * @return Number of network interfaces actually allocated diff --git a/sys/net/gnrc/link_layer/netdev/gnrc_netdev_eth.c b/sys/net/gnrc/link_layer/netdev/gnrc_netdev_eth.c index 0de93b127d76a..cb532e16b037d 100644 --- a/sys/net/gnrc/link_layer/netdev/gnrc_netdev_eth.c +++ b/sys/net/gnrc/link_layer/netdev/gnrc_netdev_eth.c @@ -119,6 +119,118 @@ static gnrc_pktsnip_t *_recv(gnrc_netdev_t *gnrc_netdev) return NULL; } +static inline void _addr_set_broadcast(uint8_t *dst) +{ + memset(dst, 0xff, ETHERNET_ADDR_LEN); +} + +static inline void _addr_set_multicast(uint8_t *dst, gnrc_pktsnip_t *payload) +{ + switch (payload->type) { +#ifdef MODULE_GNRC_IPV6 + case GNRC_NETTYPE_IPV6: + /* https://tools.ietf.org/html/rfc2464#section-7 */ + dst[0] = 0x33; + dst[1] = 0x33; + ipv6_hdr_t *ipv6 = payload->data; + memcpy(dst + 2, ipv6->dst.u8 + 12, 4); + break; +#endif + default: + _addr_set_broadcast(dst); + break; + } +} + +static int _send(gnrc_netdev_t *gnrc_netdev, gnrc_pktsnip_t *pkt) +{ + ethernet_hdr_t hdr; + gnrc_netif_hdr_t *netif_hdr; + gnrc_pktsnip_t *payload; + int res; + + netdev_t *dev = gnrc_netdev->dev; + + if (pkt == NULL) { + DEBUG("gnrc_netdev_eth: pkt was NULL\n"); + return -EINVAL; + } + + payload = pkt->next; + + if (pkt->type != GNRC_NETTYPE_NETIF) { + DEBUG("gnrc_netdev_eth: First header was not generic netif header\n"); + return -EBADMSG; + } + + if (payload) { + hdr.type = byteorder_htons(gnrc_nettype_to_ethertype(payload->type)); + } + else { + hdr.type = byteorder_htons(ETHERTYPE_UNKNOWN); + } + + netif_hdr = pkt->data; + + /* set ethernet header */ + if (netif_hdr->src_l2addr_len == ETHERNET_ADDR_LEN) { + memcpy(hdr.dst, gnrc_netif_hdr_get_src_addr(netif_hdr), + netif_hdr->src_l2addr_len); + } + else { + dev->driver->get(dev, NETOPT_ADDRESS, hdr.src, ETHERNET_ADDR_LEN); + } + + if (netif_hdr->flags & GNRC_NETIF_HDR_FLAGS_BROADCAST) { + _addr_set_broadcast(hdr.dst); + } + else if (netif_hdr->flags & GNRC_NETIF_HDR_FLAGS_MULTICAST) { + if (payload == NULL) { + DEBUG("gnrc_netdev_eth: empty multicast packets over Ethernet "\ + "are not yet supported\n"); + return -ENOTSUP; + } + _addr_set_multicast(hdr.dst, payload); + } + else if (netif_hdr->dst_l2addr_len == ETHERNET_ADDR_LEN) { + memcpy(hdr.dst, gnrc_netif_hdr_get_dst_addr(netif_hdr), + ETHERNET_ADDR_LEN); + } + else { + DEBUG("gnrc_netdev_eth: destination address had unexpected format\n"); + return -EBADMSG; + } + + DEBUG("gnrc_netdev_eth: send to %02x:%02x:%02x:%02x:%02x:%02x\n", + hdr.dst[0], hdr.dst[1], hdr.dst[2], + hdr.dst[3], hdr.dst[4], hdr.dst[5]); + + size_t n; + payload = gnrc_pktbuf_get_iovec(pkt, &n); /* use payload as temporary + * variable */ + res = -ENOBUFS; + if (payload != NULL) { + pkt = payload; /* reassign for later release; vec_snip is prepended to pkt */ + struct iovec *vector = (struct iovec *)pkt->data; + vector[0].iov_base = (char*)&hdr; + vector[0].iov_len = sizeof(ethernet_hdr_t); +#ifdef MODULE_NETSTATS_L2 + if ((netif_hdr->flags & GNRC_NETIF_HDR_FLAGS_BROADCAST) || + (netif_hdr->flags & GNRC_NETIF_HDR_FLAGS_MULTICAST)) { + gnrc_netdev->dev->stats.tx_mcast_count++; + } + else { + gnrc_netdev->dev->stats.tx_unicast_count++; + } +#endif + res = dev->driver->send(dev, vector, n); + } + + gnrc_pktbuf_release(pkt); + + return res; +} + int gnrc_netdev_eth_init(gnrc_netdev_t *gnrc_netdev, netdev_t *dev) { gnrc_netdev->send = _send; diff --git a/sys/net/gnrc/netif2/gnrc_netif2.c b/sys/net/gnrc/netif2/gnrc_netif2.c index b17f331a48e50..a8eb90667afa5 100644 --- a/sys/net/gnrc/netif2/gnrc_netif2.c +++ b/sys/net/gnrc/netif2/gnrc_netif2.c @@ -464,6 +464,7 @@ ipv6_addr_t *gnrc_netif2_ipv6_addr_best_src(gnrc_netif2_t *netif, bool ll_only) { ipv6_addr_t *best_src = NULL; + BITFIELD(candidate_set, GNRC_NETIF2_IPV6_ADDRS_NUMOF); memset(candidate_set, 0, sizeof(candidate_set)); @@ -779,6 +780,7 @@ static ipv6_addr_t *_src_addr_selection(gnrc_netif2_t *netif, * corresponding rules. */ uint8_t winner_set[GNRC_NETIF2_IPV6_ADDRS_NUMOF]; + memset(winner_set, 0, GNRC_NETIF2_IPV6_ADDRS_NUMOF); uint8_t max_pts = 0; /* _create_candidate_set() assures that `dst` is not unspecified and if @@ -922,7 +924,7 @@ static void _init_from_device(gnrc_netif2_t *netif) netif->ipv6_mtu = tmp; #endif break; -#endif /* MODULE_NETDEV_IEEE802154 */ +#endif /* MODULE_NETDEV_IEEE802154 */ #ifdef MODULE_NETDEV_ETH case NETDEV_TYPE_ETHERNET: netif->ipv6_mtu = ETHERNET_DATA_LEN; @@ -987,7 +989,7 @@ static void *_gnrc_netif2_thread(void *args) case GNRC_NETAPI_MSG_TYPE_SET: opt = msg.content.ptr; DEBUG("gnrc_netif2: GNRC_NETAPI_MSG_TYPE_SET received. opt=%s\n", - netopt2str(opt->opt)); + netopt2str(opt->opt)); /* set option for device driver */ res = netif->ops->set(netif, opt); DEBUG("gnrc_netif2: response of netif->ops->set(): %i\n", res); @@ -997,7 +999,7 @@ static void *_gnrc_netif2_thread(void *args) case GNRC_NETAPI_MSG_TYPE_GET: opt = msg.content.ptr; DEBUG("gnrc_netif2: GNRC_NETAPI_MSG_TYPE_GET received. opt=%s\n", - netopt2str(opt->opt)); + netopt2str(opt->opt)); /* get option from device driver */ res = netif->ops->get(netif, opt); DEBUG("gnrc_netif2: response of netif->ops->get(): %i\n", res); @@ -1035,7 +1037,7 @@ static void _pass_on_packet(gnrc_pktsnip_t *pkt) static void _event_cb(netdev_t *dev, netdev_event_t event) { - gnrc_netif2_t *netif = (gnrc_netif2_t*) dev->context; + gnrc_netif2_t *netif = (gnrc_netif2_t *) dev->context; if (event == NETDEV_EVENT_ISR) { msg_t msg = { .type = NETDEV_MSG_TYPE_EVENT, @@ -1047,17 +1049,15 @@ static void _event_cb(netdev_t *dev, netdev_event_t event) } else { DEBUG("gnrc_netif2: event triggered -> %i\n", event); - switch(event) { - case NETDEV_EVENT_RX_COMPLETE: - { + switch (event) { + case NETDEV_EVENT_RX_COMPLETE: { gnrc_pktsnip_t *pkt = netif->ops->recv(netif); if (pkt) { _pass_on_packet(pkt); } - - break; } + break; #ifdef MODULE_NETSTATS_L2 case NETDEV_EVENT_TX_MEDIUM_BUSY: /* we are the only ones supposed to touch this variable, diff --git a/sys/net/gnrc/netif2/gnrc_netif2_ethernet.c b/sys/net/gnrc/netif2/gnrc_netif2_ethernet.c index b2664f8e71887..6ceab4280a317 100644 --- a/sys/net/gnrc/netif2/gnrc_netif2_ethernet.c +++ b/sys/net/gnrc/netif2/gnrc_netif2_ethernet.c @@ -138,7 +138,7 @@ static int _send(gnrc_netif2_t *netif, gnrc_pktsnip_t *pkt) if (payload != NULL) { pkt = payload; /* reassign for later release; vec_snip is prepended to pkt */ struct iovec *vector = (struct iovec *)pkt->data; - vector[0].iov_base = (char*)&hdr; + vector[0].iov_base = (char *)&hdr; vector[0].iov_len = sizeof(ethernet_hdr_t); #ifdef MODULE_NETSTATS_L2 if ((netif_hdr->flags & GNRC_NETIF_HDR_FLAGS_BROADCAST) || @@ -165,10 +165,10 @@ static gnrc_pktsnip_t *_recv(gnrc_netif2_t *netif) if (bytes_expected > 0) { pkt = gnrc_pktbuf_add(NULL, NULL, - bytes_expected, - GNRC_NETTYPE_UNDEF); + bytes_expected, + GNRC_NETTYPE_UNDEF); - if(!pkt) { + if (!pkt) { DEBUG("gnrc_netif2_ethernet: cannot allocate pktsnip.\n"); /* drop the packet */ @@ -178,7 +178,7 @@ static gnrc_pktsnip_t *_recv(gnrc_netif2_t *netif) } int nread = dev->driver->recv(dev, pkt->data, bytes_expected, NULL); - if(nread <= 0) { + if (nread <= 0) { DEBUG("gnrc_netif2_ethernet: read error.\n"); goto safe_out; } @@ -213,8 +213,8 @@ static gnrc_pktsnip_t *_recv(gnrc_netif2_t *netif) /* create netif header */ gnrc_pktsnip_t *netif_hdr; netif_hdr = gnrc_pktbuf_add(NULL, NULL, - sizeof(gnrc_netif_hdr_t) + (2 * ETHERNET_ADDR_LEN), - GNRC_NETTYPE_NETIF); + sizeof(gnrc_netif_hdr_t) + (2 * ETHERNET_ADDR_LEN), + GNRC_NETTYPE_NETIF); if (netif_hdr == NULL) { DEBUG("gnrc_netif2_ethernet: no space left in packet buffer\n"); @@ -228,9 +228,9 @@ static gnrc_pktsnip_t *_recv(gnrc_netif2_t *netif) ((gnrc_netif_hdr_t *)netif_hdr->data)->if_pid = thread_getpid(); DEBUG("gnrc_netif2_ethernet: received packet from %02x:%02x:%02x:%02x:%02x:%02x " - "of length %d\n", - hdr->src[0], hdr->src[1], hdr->src[2], hdr->src[3], hdr->src[4], - hdr->src[5], nread); + "of length %d\n", + hdr->src[0], hdr->src[1], hdr->src[2], hdr->src[3], hdr->src[4], + hdr->src[5], nread); #if defined(MODULE_OD) && ENABLE_DEBUG od_hex_dump(hdr, nread, OD_WIDTH_DEFAULT); #endif From 2486f3b1287f0e51872145d92be1d929ea54d653 Mon Sep 17 00:00:00 2001 From: Martine Lenders Date: Thu, 20 Jul 2017 10:53:19 +0200 Subject: [PATCH 04/31] fixup! gnrc_netif2: Introduction of a new GNRC network interface API --- sys/include/net/gnrc/netif2.h | 6 +- sys/include/net/gnrc/netif2/ethernet.h | 4 +- sys/include/net/gnrc/netif2/internal.h | 35 +++++-- sys/net/gnrc/Makefile | 3 + sys/net/gnrc/netif2/Makefile | 3 + sys/net/gnrc/netif2/gnrc_netif2.c | 123 ++++++++++++++++++------- 6 files changed, 130 insertions(+), 44 deletions(-) create mode 100644 sys/net/gnrc/netif2/Makefile diff --git a/sys/include/net/gnrc/netif2.h b/sys/include/net/gnrc/netif2.h index eb996ae3346ac..f51a34a83208c 100644 --- a/sys/include/net/gnrc/netif2.h +++ b/sys/include/net/gnrc/netif2.h @@ -58,9 +58,11 @@ extern "C" { #endif /** - * @brief PID of the (virtual) loopback interface + * @brief Default priority for network interface threads */ -#define GNRC_NETIF2_LOOPBACK_PID (KERNEL_PID_LAST + 1) +#ifndef GNRC_NETIF2_PRIO +#define GNRC_NETIF2_PRIO (THREAD_PRIORITY_MAIN - 5) +#endif /** * @brief Number of multicast addressed needed for @ref net_gnrc_rpl "RPL". diff --git a/sys/include/net/gnrc/netif2/ethernet.h b/sys/include/net/gnrc/netif2/ethernet.h index 05e0aac620378..c143783b83c96 100644 --- a/sys/include/net/gnrc/netif2/ethernet.h +++ b/sys/include/net/gnrc/netif2/ethernet.h @@ -38,8 +38,8 @@ extern "C" { * @return The network interface on success. * @return NULL, on error. */ -gnrc_netif2_t *gnrc_netif2_eth_create(char *stack, int stacksize, char priority, - char *name, netdev_t *dev); +gnrc_netif2_t *gnrc_netif2_ethernet_create(char *stack, int stacksize, char priority, + char *name, netdev_t *dev); #ifdef __cplusplus } diff --git a/sys/include/net/gnrc/netif2/internal.h b/sys/include/net/gnrc/netif2/internal.h index 6562b29b6ae53..9c256ad75b35c 100644 --- a/sys/include/net/gnrc/netif2/internal.h +++ b/sys/include/net/gnrc/netif2/internal.h @@ -75,7 +75,8 @@ gnrc_netif2_t *gnrc_netif2_get_by_pid(kernel_pid_t pid); * @brief Adds an IPv6 address to the interface * * @pre `(netif != NULL) && (addr != NULL)` - * @pre @p addr is not multicast (starts with `ff00::/8`) + * @pre @p addr is not multicast (starts with `ff00::/8`), unspecified (`::`), + * or loopback * @pre `(pfx_len > 0) && (pfx_len <= 128)` * * @param[in,out] netif the network interface. May not be NULL. @@ -93,7 +94,7 @@ gnrc_netif2_t *gnrc_netif2_get_by_pid(kernel_pid_t pid); * * @note Only available with @ref net_gnrc_ipv6 "gnrc_ipv6". * - * @return 0, on success + * @return >= 0, on success * @return -ENOMEM, when no space for new addresses is left on the interface */ int gnrc_netif2_ipv6_addr_add(gnrc_netif2_t *netif, const ipv6_addr_t *addr, @@ -236,16 +237,36 @@ int gnrc_netif2_ipv6_group_join(gnrc_netif2_t *netif, void gnrc_netif2_ipv6_group_leave(gnrc_netif2_t *netif, const ipv6_addr_t *addr); +/** + * @brief Returns the index of @p addr in gnrc_netif2_t::ipv6_groups of @p + * netif + * + * @pre `(netif != NULL) && (addr != NULL)` + * + * Can be used to check if a multicast address is assigned to an interface. + * + * @param[in] netif the network interface + * @param[in] addr the multicast address to check + * + * @note Only available with @ref net_gnrc_ipv6 "gnrc_ipv6". + * + * @return index of @p addr in gnrc_netif2_t::ipv6_groups of @p netif + * @return -1, if @p netif is not in group @p addr + */ +int gnrc_netif2_ipv6_group_idx(gnrc_netif2_t *netif, + const ipv6_addr_t *addr); + /** * @brief Get interface identifier (IID) of an interface's link-layer address * * @param[in] netif the network interface - * @param[out] eui64 the IID, set to all 0 if interface has no link-layer - * address or if gnrc_netif2_t::device_type is not - * supported. + * @param[out] eui64 the IID + * + * @return 0, on success + * @return -ENOTSUP, if interface has no link-layer address or if + * gnrc_netif2_t::device_type is not supported. */ -void gnrc_netif2_ipv6_get_iid(gnrc_netif2_t *netif, - eui64_t *eui64); +int gnrc_netif2_ipv6_get_iid(gnrc_netif2_t *netif, eui64_t *eui64); #endif /* MODULE_GNRC_IPV6 */ /** diff --git a/sys/net/gnrc/Makefile b/sys/net/gnrc/Makefile index 7b9670b4fe6a8..bb256db02e424 100644 --- a/sys/net/gnrc/Makefile +++ b/sys/net/gnrc/Makefile @@ -49,6 +49,9 @@ endif ifneq (,$(filter gnrc_netapi,$(USEMODULE))) DIRS += netapi endif +ifneq (,$(filter gnrc_netif2,$(USEMODULE))) + DIRS += netif2 +endif ifneq (,$(filter gnrc_netif,$(USEMODULE))) DIRS += netif endif diff --git a/sys/net/gnrc/netif2/Makefile b/sys/net/gnrc/netif2/Makefile new file mode 100644 index 0000000000000..590336f5daeca --- /dev/null +++ b/sys/net/gnrc/netif2/Makefile @@ -0,0 +1,3 @@ +MODULE := gnrc_netif2 + +include $(RIOTBASE)/Makefile.base diff --git a/sys/net/gnrc/netif2/gnrc_netif2.c b/sys/net/gnrc/netif2/gnrc_netif2.c index a8eb90667afa5..846be309b09a3 100644 --- a/sys/net/gnrc/netif2/gnrc_netif2.c +++ b/sys/net/gnrc/netif2/gnrc_netif2.c @@ -15,6 +15,7 @@ */ #include "bitfield.h" +#include "net/ethernet.h" #include "net/gnrc.h" #include "log.h" #include "sched.h" @@ -121,34 +122,51 @@ int gnrc_netif2_get_from_netdev(gnrc_netif2_t *netif, gnrc_netapi_opt_t *opt) ipv6_addr_t *tgt = opt->data; res = 0; - for (ipv6_addr_t *addr = netif->ipv6_addrs; - (res < opt->data_len) && - (addr < netif->ipv6_addrs + GNRC_NETIF2_IPV6_ADDRS_NUMOF); - addr++, tgt++, res += sizeof(ipv6_addr_t)) { + for (unsigned i = 0; + (res < opt->data_len) && (i < GNRC_NETIF2_IPV6_ADDRS_NUMOF); + i++, tgt++) { + if (netif->ipv6_addrs_flags[i] != 0) { + memcpy(tgt, &netif->ipv6_addrs[i], sizeof(ipv6_addr_t)); + res += sizeof(ipv6_addr_t); + } + } + } + break; + case NETOPT_IPV6_ADDR_FLAGS: { + assert(opt->data_len >= sizeof(uint8_t)); + uint8_t *tgt = opt->data; + + res = 0; + for (unsigned i = 0; + (res < opt->data_len) && (i < GNRC_NETIF2_IPV6_ADDRS_NUMOF); + i++, tgt++) { + if (netif->ipv6_addrs_flags[i] != 0) { + *tgt = netif->ipv6_addrs_flags[i]; + res += sizeof(uint8_t); + } } } break; - case NETOPT_IPV6_ADDR_FLAGS: - res = (opt->data_len < GNRC_NETIF2_IPV6_ADDRS_NUMOF) ? - opt->data_len : GNRC_NETIF2_IPV6_ADDRS_NUMOF; - memcpy(opt->data, netif->ipv6_addrs_flags, res); case NETOPT_IPV6_GROUP: { assert(opt->data_len >= sizeof(ipv6_addr_t)); ipv6_addr_t *tgt = opt->data; res = 0; - for (ipv6_addr_t *addr = netif->ipv6_groups; - (res < opt->data_len) && - (addr < netif->ipv6_groups + GNRC_NETIF2_IPV6_ADDRS_NUMOF); - addr++, tgt++, res += sizeof(ipv6_addr_t)) { - memcpy(tgt, addr, sizeof(ipv6_addr_t)); + for (unsigned i = 0; + (res < opt->data_len) && (i < GNRC_NETIF2_IPV6_GROUPS_NUMOF); + i++, tgt++) { + if (!ipv6_addr_is_unspecified(&netif->ipv6_groups[i])) { + memcpy(tgt, &netif->ipv6_groups[i], sizeof(ipv6_addr_t)); + res += sizeof(ipv6_addr_t); + } } } break; case NETOPT_IPV6_IID: assert(opt->data_len >= sizeof(eui64_t)); - gnrc_netif2_ipv6_get_iid(netif, opt->data); - res = sizeof(eui64_t); + if (gnrc_netif2_ipv6_get_iid(netif, opt->data) == 0) { + res = sizeof(eui64_t); + } break; case NETOPT_MAX_PACKET_SIZE: if (opt->context == GNRC_NETTYPE_IPV6) { @@ -163,11 +181,13 @@ int gnrc_netif2_get_from_netdev(gnrc_netif2_t *netif, gnrc_netapi_opt_t *opt) assert(opt->data_len == sizeof(netopt_enable_t)); *((netopt_enable_t *)opt->data) = (gnrc_netif2_is_rtr(netif)) ? NETOPT_ENABLE : NETOPT_DISABLE; + res = sizeof(netopt_enable_t); break; case NETOPT_IPV6_SND_RTR_ADV: assert(opt->data_len == sizeof(netopt_enable_t)); *((netopt_enable_t *)opt->data) = (gnrc_netif2_is_rtr_adv(netif)) ? NETOPT_ENABLE : NETOPT_DISABLE; + res = sizeof(netopt_enable_t); break; #endif /* GNRC_IPV6_NIB_CONF_ROUTER */ #endif /* MODULE_GNRC_IPV6 */ @@ -176,6 +196,7 @@ int gnrc_netif2_get_from_netdev(gnrc_netif2_t *netif, gnrc_netapi_opt_t *opt) assert(opt->data_len == sizeof(netopt_enable_t)); *((netopt_enable_t *)opt->data) = (netif->flags & GNRC_NETIF2_FLAGS_6LO_HC) ? NETOPT_ENABLE : NETOPT_DISABLE; + res = sizeof(netopt_enable_t); break; #endif /* MODULE_GNRC_SIXLOWPAN_IPHC */ default: @@ -255,6 +276,7 @@ int gnrc_netif2_set_from_netdev(gnrc_netif2_t *netif, } netif->flags &= ~GNRC_NETIF2_FLAGS_IPV6_FORWARDING; } + res = sizeof(netopt_enable_t); break; case NETOPT_IPV6_SND_RTR_ADV: assert(opt->data_len == sizeof(netopt_enable_t)); @@ -264,6 +286,7 @@ int gnrc_netif2_set_from_netdev(gnrc_netif2_t *netif, else { gnrc_ipv6_nib_iface_cease_rtr_adv(netif); } + res = sizeof(netopt_enable_t); break; #endif /* GNRC_IPV6_NIB_CONF_ROUTER */ #endif /* MODULE_GNRC_IPV6 */ @@ -276,6 +299,7 @@ int gnrc_netif2_set_from_netdev(gnrc_netif2_t *netif, else { netif->flags &= ~GNRC_NETIF2_FLAGS_6LO_HC; } + res = sizeof(netopt_enable_t); break; #endif /* MODULE_GNRC_SIXLOWPAN_IPHC */ default: @@ -388,25 +412,32 @@ static int _create_candidate_set(const gnrc_netif2_t *netif, static ipv6_addr_t *_src_addr_selection(gnrc_netif2_t *netif, const ipv6_addr_t *dst, uint8_t *candidate_set); +static int _group_idx(const gnrc_netif2_t *netif, const ipv6_addr_t *addr); int gnrc_netif2_ipv6_addr_add(gnrc_netif2_t *netif, const ipv6_addr_t *addr, unsigned pfx_len, uint8_t flags) { unsigned idx = UINT_MAX; + assert((netif != NULL) && (addr != NULL)); + assert(!(ipv6_addr_is_multicast(addr) || ipv6_addr_is_unspecified(addr) || + ipv6_addr_is_loopback(addr))); + assert((pfx_len > 0) && (pfx_len <= 128)); gnrc_netif2_acquire(netif); if ((flags & GNRC_NETIF2_IPV6_ADDRS_FLAGS_STATE_MASK) == 0) { flags |= GNRC_NETIF2_IPV6_ADDRS_FLAGS_STATE_TENTATIVE; } for (unsigned i = 0; i < GNRC_NETIF2_IPV6_ADDRS_NUMOF; i++) { if (ipv6_addr_equal(&netif->ipv6_addrs[i], addr)) { - return 0; + gnrc_netif2_release(netif); + return i; } if ((idx == UINT_MAX) && (netif->ipv6_addrs_flags[i] == 0)) { idx = i; } } if (idx == UINT_MAX) { + gnrc_netif2_release(netif); return -ENOMEM; } netif->ipv6_addrs_flags[idx] = flags; @@ -414,6 +445,7 @@ int gnrc_netif2_ipv6_addr_add(gnrc_netif2_t *netif, const ipv6_addr_t *addr, /* TODO: * - update prefix list, if flags == VALID * - with SLAAC, send out NS otherwise for DAD probing */ + (void)pfx_len; gnrc_netif2_release(netif); return idx; } @@ -464,9 +496,9 @@ ipv6_addr_t *gnrc_netif2_ipv6_addr_best_src(gnrc_netif2_t *netif, bool ll_only) { ipv6_addr_t *best_src = NULL; - BITFIELD(candidate_set, GNRC_NETIF2_IPV6_ADDRS_NUMOF); + assert((netif != NULL) && (dst != NULL)); memset(candidate_set, 0, sizeof(candidate_set)); gnrc_netif2_acquire(netif); int first_candidate = _create_candidate_set(netif, dst, ll_only, @@ -519,13 +551,15 @@ int gnrc_netif2_ipv6_group_join(gnrc_netif2_t *netif, gnrc_netif2_acquire(netif); for (unsigned i = 0; i < GNRC_NETIF2_IPV6_GROUPS_NUMOF; i++) { if (ipv6_addr_equal(&netif->ipv6_groups[i], addr)) { - return 0; + gnrc_netif2_release(netif); + return i; } if ((idx == UINT_MAX) && (ipv6_addr_is_unspecified(&netif->ipv6_groups[i]))) { idx = i; } } if (idx == UINT_MAX) { + gnrc_netif2_release(netif); return -ENOMEM; } memcpy(&netif->ipv6_groups[idx], addr, sizeof(netif->ipv6_groups[idx])); @@ -543,19 +577,27 @@ void gnrc_netif2_ipv6_group_leave(gnrc_netif2_t *netif, assert((netif != NULL) && (addr != NULL)); gnrc_netif2_acquire(netif); - for (unsigned i = 0; i < GNRC_NETIF2_IPV6_ADDRS_NUMOF; i++) { - if (ipv6_addr_equal(&netif->ipv6_groups[i], addr)) { - ipv6_addr_set_unspecified(&netif->ipv6_groups[idx]); - /* TODO: - * - MLD action */ - break; - } + idx = _group_idx(netif, addr); + if (idx >= 0) { + ipv6_addr_set_unspecified(&netif->ipv6_groups[idx]); + /* TODO: + * - MLD action */ } gnrc_netif2_release(netif); } -void gnrc_netif2_ipv6_get_iid(gnrc_netif2_t *netif, - eui64_t *eui64) +int gnrc_netif2_ipv6_group_idx(gnrc_netif2_t *netif, const ipv6_addr_t *addr) +{ + int idx; + + assert((netif != NULL) && (addr != NULL)); + gnrc_netif2_acquire(netif); + idx = _group_idx(netif, addr); + gnrc_netif2_release(netif); + return idx; +} + +int gnrc_netif2_ipv6_get_iid(gnrc_netif2_t *netif, eui64_t *eui64) { #if GNRC_NETIF2_L2ADDR_MAXLEN > 0 if (netif->flags & GNRC_NETIF2_FLAGS_HAS_L2ADDR) { @@ -571,7 +613,7 @@ void gnrc_netif2_ipv6_get_iid(gnrc_netif2_t *netif, eui64->uint8[5] = netif->l2addr[3]; eui64->uint8[6] = netif->l2addr[4]; eui64->uint8[7] = netif->l2addr[5]; - return; + return 0; #endif #ifdef MODULE_NETDEV_IEEE802154 case NETDEV_TYPE_IEEE802154: @@ -585,11 +627,11 @@ void gnrc_netif2_ipv6_get_iid(gnrc_netif2_t *netif, eui64->uint8[5] = 0x0; eui64->uint8[6] = netif->l2addr[0]; eui64->uint8[7] = netif->l2addr[1]; - return; + return 0; case IEEE802154_LONG_ADDRESS_LEN: memcpy(eui64, netif->l2addr, sizeof(eui64_t)); eui64->uint8[0] ^= 0x02; - return; + return 0; default: /* this should not happen */ assert(false); @@ -608,14 +650,15 @@ void gnrc_netif2_ipv6_get_iid(gnrc_netif2_t *netif, eui64->uint8[5] = 0x0; eui64->uint8[6] = 0x0; eui64->uint8[7] = netif->l2addr[0]; - return; + return 0; #endif default: + (void)eui64; break; } } #endif - memset(eui64, 0, sizeof(eui64_t)); + return -ENOTSUP; } static inline bool _addr_anycast(const gnrc_netif2_t *netif, unsigned idx) @@ -871,6 +914,17 @@ static ipv6_addr_t *_src_addr_selection(gnrc_netif2_t *netif, _match(netif, dst, candidate_set, &res); return (res < 0) ? NULL : &netif->ipv6_addrs[res]; } + +static int _group_idx(const gnrc_netif2_t *netif, const ipv6_addr_t *addr) +{ + for (unsigned i = 0; i < GNRC_NETIF2_IPV6_GROUPS_NUMOF; i++) { + if (ipv6_addr_equal(&netif->ipv6_groups[i], addr)) { + return i; + } + } + return -1; +} + #endif /* MODULE_GNRC_IPV6 */ static void _update_l2addr_from_dev(gnrc_netif2_t *netif) @@ -895,9 +949,12 @@ static void _update_l2addr_from_dev(gnrc_netif2_t *netif) } res = dev->driver->get(dev, opt, netif->l2addr, sizeof(netif->l2addr)); - if (res == -ENOTSUP) { + if (res != -ENOTSUP) { netif->flags |= GNRC_NETIF2_FLAGS_HAS_L2ADDR; } + if (res > 0) { + netif->l2addr_len = res; + } } static void _init_from_device(gnrc_netif2_t *netif) From 7a3617eb6cda069b377e10b731c637d09550f687 Mon Sep 17 00:00:00 2001 From: Martine Lenders Date: Fri, 21 Jul 2017 15:34:51 +0200 Subject: [PATCH 05/31] tests: add tests for gnrc_netif2 --- tests/gnrc_netif2/Makefile | 30 + tests/gnrc_netif2/common.c | 163 +++++ tests/gnrc_netif2/common.h | 88 +++ tests/gnrc_netif2/main.c | 1040 +++++++++++++++++++++++++++++ tests/gnrc_netif2/tests/01-run.py | 82 +++ 5 files changed, 1403 insertions(+) create mode 100644 tests/gnrc_netif2/Makefile create mode 100644 tests/gnrc_netif2/common.c create mode 100644 tests/gnrc_netif2/common.h create mode 100644 tests/gnrc_netif2/main.c create mode 100755 tests/gnrc_netif2/tests/01-run.py diff --git a/tests/gnrc_netif2/Makefile b/tests/gnrc_netif2/Makefile new file mode 100644 index 0000000000000..f7bca268a8ead --- /dev/null +++ b/tests/gnrc_netif2/Makefile @@ -0,0 +1,30 @@ +# name of your application +APPLICATION = gnrc_ipv6_nib +include ../Makefile.tests_common + +BOARD_INSUFFICIENT_MEMORY := + +USEMODULE += embunit +USEMODULE += gnrc_netif2 +USEMODULE += gnrc_pktdump +USEMODULE += gnrc_sixlowpan_frag +USEMODULE += gnrc_sixlowpan_frag +USEMODULE += gnrc_sixlowpan_iphc +USEMODULE += gnrc_ipv6 +USEMODULE += netdev_eth +USEMODULE += netdev_test +USEMODULE += od + +CFLAGS += -DDEVELHELP +CFLAGS += -DGNRC_NETIF_NUMOF=4 +CFLAGS += -DGNRC_NETIF2_ADDRS_NUMOF=16 +CFLAGS += -DGNRC_NETIF2_GROUPS_NUMOF=8 +CFLAGS += -DLOG_LEVEL=LOG_NONE +CFLAGS += -DTEST_SUITES + +include $(RIOTBASE)/Makefile.include + +test: +# `testrunner` calls `make term` recursively, results in duplicated `TERMFLAGS`. +# So clears `TERMFLAGS` before run. + TERMFLAGS= tests/01-run.py diff --git a/tests/gnrc_netif2/common.c b/tests/gnrc_netif2/common.c new file mode 100644 index 0000000000000..d106ee3d098a1 --- /dev/null +++ b/tests/gnrc_netif2/common.c @@ -0,0 +1,163 @@ +/* + * 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 + */ + +#include +#include + +#include "common.h" +#include "net/ethernet.h" +#include "net/gnrc/netreg.h" +#include "net/gnrc/pktdump.h" +#include "net/ipv6.h" +#include "net/netdev_test.h" +#include "od.h" + +static netdev_test_t _devs[GNRC_NETIF_NUMOF]; + +netdev_t *ethernet_dev = (netdev_t *)&_devs[0]; +netdev_t *devs[DEFAULT_DEVS_NUMOF]; + +#define MSG_QUEUE_SIZE (8) + +static gnrc_netreg_entry_t dumper_undef, dumper_ipv6; +static msg_t _main_msg_queue[MSG_QUEUE_SIZE]; +static uint8_t tmp_buffer[ETHERNET_DATA_LEN]; +static size_t tmp_buffer_bytes = 0; + +static int _dump_send_packet(netdev_t *netdev, const struct iovec *vector, + int count) +{ + int res; + + tmp_buffer_bytes = 0; + + printf("Sending data from "); + if (netdev == ethernet_dev) { + printf("Ethernet "); + } + else { + printf("unknown "); + } + puts("device:"); + for (int i = 0; i < count; i++) { + if ((tmp_buffer_bytes + vector[i].iov_len) > ETHERNET_DATA_LEN) { + return -ENOBUFS; + } + memcpy(&tmp_buffer[tmp_buffer_bytes], vector[i].iov_base, + vector[i].iov_len); + tmp_buffer_bytes += vector[i].iov_len; + } + od_hex_dump(tmp_buffer, tmp_buffer_bytes, OD_WIDTH_DEFAULT); + res = (int)tmp_buffer_bytes; + return res; +} + +void _test_trigger_recv(gnrc_netif2_t *netif, const uint8_t *data, + size_t data_len) +{ + netdev_t *dev = netif->dev; + + assert(data_len <= ETHERNET_DATA_LEN); + if ((data != NULL) || (data_len > 0)) { + tmp_buffer_bytes = data_len; + memcpy(tmp_buffer, data, data_len); + } + else { + tmp_buffer_bytes = 0; + } + assert(dev->event_callback); + dev->event_callback(dev, NETDEV_EVENT_ISR); +} + +static int _netdev_recv(netdev_t *dev, char *buf, int len, void *info) +{ + int res; + + (void)dev; + (void)info; + res = (int)tmp_buffer_bytes; + if (buf == NULL) { + if (len > 0) { + tmp_buffer_bytes = 0; + } + return res; + } + if (((unsigned)len) < tmp_buffer_bytes) { + return -ENOBUFS; + } + memcpy(buf, tmp_buffer, tmp_buffer_bytes); + return res; +} + +static void _netdev_isr(netdev_t *dev) +{ + assert(dev->event_callback); + dev->event_callback(dev, NETDEV_EVENT_RX_COMPLETE); +} + +static int _get_netdev_device_type(netdev_t *netdev, void *value, size_t max_len) +{ + netdev_test_t *dev = (netdev_test_t *)netdev; + assert(max_len == sizeof(uint16_t)); + if (dev->state == 0x0) { + *((uint16_t *)value) = NETDEV_TYPE_ETHERNET; + } + else { + *((uint16_t *)value) = NETDEV_TYPE_UNKNOWN; + } + return sizeof(uint16_t); +} +static int _get_netdev_max_packet_size(netdev_t *netdev, void *value, size_t max_len) +{ + netdev_test_t *dev = (netdev_test_t *)netdev; + assert(max_len == sizeof(uint16_t)); + if (dev->state == 0x0) { + *((uint16_t *)value) = ETHERNET_DATA_LEN; + } + else { + *((uint16_t *)value) = IPV6_MIN_MTU; + } + return sizeof(uint16_t); +} + + +void _tests_init(void) +{ + msg_init_queue(_main_msg_queue, MSG_QUEUE_SIZE); + netdev_test_setup((netdev_test_t *)ethernet_dev, 0); + netdev_test_set_send_cb((netdev_test_t *)ethernet_dev, _dump_send_packet); + netdev_test_set_recv_cb((netdev_test_t *)ethernet_dev, _netdev_recv); + netdev_test_set_isr_cb((netdev_test_t *)ethernet_dev, _netdev_isr); + netdev_test_set_get_cb((netdev_test_t *)ethernet_dev, NETOPT_DEVICE_TYPE, + _get_netdev_device_type); + netdev_test_set_get_cb((netdev_test_t *)ethernet_dev, NETOPT_MAX_PACKET_SIZE, + _get_netdev_max_packet_size); + for (intptr_t i = SPECIAL_DEVS; i < GNRC_NETIF_NUMOF; i++) { + devs[i - SPECIAL_DEVS] = (netdev_t *)&_devs[i]; + netdev_test_setup(&_devs[i], (void *)i); + netdev_test_set_get_cb(&_devs[i], NETOPT_DEVICE_TYPE, + _get_netdev_device_type); + netdev_test_set_get_cb(&_devs[i], NETOPT_MAX_PACKET_SIZE, + _get_netdev_max_packet_size); + } + gnrc_netreg_entry_init_pid(&dumper_undef, GNRC_NETREG_DEMUX_CTX_ALL, + gnrc_pktdump_pid); + gnrc_netreg_entry_init_pid(&dumper_ipv6, GNRC_NETREG_DEMUX_CTX_ALL, + gnrc_pktdump_pid); + gnrc_netreg_register(GNRC_NETTYPE_UNDEF, &dumper_undef); + gnrc_netreg_register(GNRC_NETTYPE_IPV6, &dumper_ipv6); +} + +/** @} */ diff --git a/tests/gnrc_netif2/common.h b/tests/gnrc_netif2/common.h new file mode 100644 index 0000000000000..7144bd723d19c --- /dev/null +++ b/tests/gnrc_netif2/common.h @@ -0,0 +1,88 @@ +/* + * 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. + */ + +/** + * @defgroup tests_gnrc_ipv6_nib Common header for GNRC's NIB tests + * @ingroup tests + * @brief Common definitions for GNRC's NIB tests + * @{ + * + * @file + * + * @author Martine Lenders + */ +#ifndef COMMON_H +#define COMMON_H + + +#include "net/gnrc/netif2.h" + +#ifdef __cplusplus +extern "C" { +#endif + +#define SPECIAL_DEVS (1) +#define DEFAULT_DEVS_NUMOF (GNRC_NETIF_NUMOF - SPECIAL_DEVS) + +#define GP1 (0x20U) +#define GP2 (0x01U) +#define GP3 (0x0dU) +#define GP4 (0xb8U) +#define GP5 (0x00U) +#define GP6 (0x00U) +#define GP7 (0x5aU) +#define GP8 (0x1aU) + +#define LP1 (0xfeU) +#define LP2 (0x80U) +#define LP3 (0x00U) +#define LP4 (0x00U) +#define LP5 (0x00U) +#define LP6 (0x00U) +#define LP7 (0x00U) +#define LP8 (0x00U) + +#define LA1 (0x3eU) +#define LA2 (0xe6U) +#define LA3 (0xb5U) +#define LA4 (0x0fU) +#define LA5 (0x19U) +#define LA6 (0x22U) +#define LA7 (0xfdU) +#define LA8 (0x0aU) + +#define ETHERNET_SRC { LA1, LA2, LA3, LA6, LA7, LA8 } +#define ETHERNET_IPV6_LL { LP1, LP2, LP3, LP4, LP5, LP6, LP7, LP8, \ + LA1 ^ 0x2, LA2, LA3, 0xff, 0xfe, LA6, LA7, LA8 } +#define ETHERNET_IPV6_G { GP1, GP2, GP3, GP4, GP5, GP6, GP7, GP8, \ + LA1 ^ 0x2, LA2, LA3, 0xff, 0xfe, LA6, LA7, LA8 } +#define NETIF0_SRC { LA1, LA2 + 1, LA3, LA4, LA5, LA6, LA7, LA8 } +#define NETIF0_IPV6_LL { LP1, LP2, LP3, LP4, LP5, LP6, LP7, LP8, \ + LA1 ^ 0x2, LA2 + 1, LA3, LA4, LA5, LA6, LA7, LA8 } +#define NETIF0_IPV6_G { GP1, GP2, GP3, GP4, GP5, GP6, GP7, GP8, \ + LA1 ^ 0x2, LA2 + 1, LA3, LA4, LA5, LA6, LA7, LA8 } +#define GLOBAL_PFX18 { GP1, GP2, GP3 ^ 0x3f, GP4, GP5, GP6, GP7, GP8, \ + LA1 ^ 0x2, LA2, LA3, LA4, LA5, LA6, LA7, LA8 } +#define GLOBAL_PFX23 { GP1, GP2, GP3 ^ 0x1, GP4, GP5, GP6, GP7, GP8, \ + LA1 ^ 0x2, LA2, LA3, LA4, LA5, LA6, LA7, LA8 } +#define GLOBAL_PFX64 { GP1, GP2, GP3, GP4, GP5, GP6, GP7, GP8, \ + LA1 ^ 0x82, LA2, LA3, LA4, LA5, LA6, LA7, LA8 } + +extern netdev_t *ethernet_dev; +extern netdev_t *devs[DEFAULT_DEVS_NUMOF]; + +void _tests_init(void); +void _test_trigger_recv(gnrc_netif2_t *netif, const uint8_t *data, + size_t data_len); + +#ifdef __cplusplus +} +#endif + +#endif /* COMMON_H */ +/** @} */ diff --git a/tests/gnrc_netif2/main.c b/tests/gnrc_netif2/main.c new file mode 100644 index 0000000000000..d34f5c6785a33 --- /dev/null +++ b/tests/gnrc_netif2/main.c @@ -0,0 +1,1040 @@ +/* + * 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 tests + * @{ + * + * @file + * @brief Tests default configuration of GNRC's Network Information Base + * + * @author Martine Lenders + * + * @} + */ + +#include +#include + +#include "common.h" +#include "embUnit.h" +#include "embUnit/embUnit.h" +#include "net/ethernet.h" +#include "net/ipv6.h" +#include "net/gnrc.h" +#include "net/gnrc/ipv6/hdr.h" +#include "net/gnrc/netif/hdr.h" +#include "net/gnrc/netif2.h" +#include "net/gnrc/netif2/ethernet.h" +#include "net/gnrc/netif2/internal.h" +#include "net/netdev_test.h" +#include "utlist.h" +#include "xtimer.h" + +#define GP1 (0x20U) +#define GP2 (0x01U) +#define GP3 (0x0dU) +#define GP4 (0xb8U) +#define GP5 (0x00U) +#define GP6 (0x00U) +#define GP7 (0x5aU) +#define GP8 (0x1aU) + +#define LP1 (0xfeU) +#define LP2 (0x80U) +#define LP3 (0x00U) +#define LP4 (0x00U) +#define LP5 (0x00U) +#define LP6 (0x00U) +#define LP7 (0x00U) +#define LP8 (0x00U) + +#define LA1 (0x3eU) +#define LA2 (0xe6U) +#define LA3 (0xb5U) +#define LA4 (0x0fU) +#define LA5 (0x19U) +#define LA6 (0x22U) +#define LA7 (0xfdU) +#define LA8 (0x0aU) + +#define ETHERNET_SRC { LA1, LA2, LA3, LA6, LA7, LA8 } +#define ETHERNET_IPV6_LL { LP1, LP2, LP3, LP4, LP5, LP6, LP7, LP8, \ + LA1 ^ 0x2, LA2, LA3, 0xff, 0xfe, LA6, LA7, LA8 } +#define ETHERNET_IPV6_G { GP1, GP2, GP3, GP4, GP5, GP6, GP7, GP8, \ + LA1 ^ 0x2, LA2, LA3, 0xff, 0xfe, LA6, LA7, LA8 } +#define ETHERNET_STACKSIZE (THREAD_STACKSIZE_MAIN) +#define NETIF0_SRC { LA1, LA2 + 1, LA3, LA4, LA5, LA6, LA7, LA8 } +#define NETIF0_IPV6_LL { LP1, LP2, LP3, LP4, LP5, LP6, LP7, LP8, \ + LA1 ^ 0x2, LA2 + 1, LA3, LA4, LA5, LA6, LA7, LA8 } +#define NETIF0_IPV6_G { GP1, GP2, GP3, GP4, GP5, GP6, GP7, GP8, \ + LA1 ^ 0x2, LA2 + 1, LA3, LA4, LA5, LA6, LA7, LA8 } +#define GLOBAL_PFX18 { GP1, GP2, GP3 ^ 0x3f, GP4, GP5, GP6, GP7, GP8, \ + LA1 ^ 0x2, LA2, LA3, LA4, LA5, LA6, LA7, LA8 } +#define GLOBAL_PFX23 { GP1, GP2, GP3 ^ 0x1, GP4, GP5, GP6, GP7, GP8, \ + LA1 ^ 0x2, LA2, LA3, LA4, LA5, LA6, LA7, LA8 } +#define GLOBAL_PFX64 { GP1, GP2, GP3, GP4, GP5, GP6, GP7, GP8, \ + LA1 ^ 0x82, LA2, LA3, LA4, LA5, LA6, LA7, LA8 } + +static gnrc_netif2_t *ethernet_netif = NULL; +static gnrc_netif2_t *netifs[DEFAULT_DEVS_NUMOF]; +static char ethernet_netif_stack[ETHERNET_STACKSIZE]; +static char netifs_stack[DEFAULT_DEVS_NUMOF][THREAD_STACKSIZE_DEFAULT]; + +static inline int _mock_netif_send(gnrc_netif2_t *netif, gnrc_pktsnip_t *pkt); +static inline gnrc_pktsnip_t *_mock_netif_recv(gnrc_netif2_t * netif); +static int _get_netdev_address(netdev_t *dev, void *value, size_t max_len); +static int _set_netdev_address(netdev_t *dev, void *value, size_t value_len); + +static const gnrc_netif2_ops_t default_ops = { + .send = _mock_netif_send, + .recv = _mock_netif_recv, + .get = gnrc_netif2_get_from_netdev, + .set = gnrc_netif2_set_from_netdev, + .msg_handler = NULL, +}; + +static void _set_up(void) +{ + msg_t msg; + + if (ethernet_netif != NULL) { + memset(ethernet_netif->ipv6_addrs_flags, 0, + sizeof(ethernet_netif->ipv6_addrs_flags)); + memset(ethernet_netif->ipv6_addrs, 0, + sizeof(ethernet_netif->ipv6_addrs)); + memset(ethernet_netif->ipv6_groups, 0, + sizeof(ethernet_netif->ipv6_groups)); + } + for (unsigned i = 0; i < DEFAULT_DEVS_NUMOF; i++) { + if (netifs[i] != NULL) { + memset(netifs[i]->ipv6_addrs_flags, 0, + sizeof(netifs[i]->ipv6_addrs_flags)); + memset(netifs[i]->ipv6_addrs, 0, sizeof(netifs[i]->ipv6_addrs)); + memset(netifs[i]->ipv6_groups, 0, sizeof(netifs[i]->ipv6_groups)); + } + } + /* empty message queue */ + while (msg_try_receive(&msg) > 0) {} +} + +static void test_creation(void) +{ + char test_stack[4]; + gnrc_netif2_t *ptr = NULL; + + TEST_ASSERT_EQUAL_INT(0, gnrc_netif2_numof()); + TEST_ASSERT_NULL(gnrc_netif2_iter(ptr)); + TEST_ASSERT_NOT_NULL((ethernet_netif = gnrc_netif2_ethernet_create( + ethernet_netif_stack, ETHERNET_STACKSIZE, GNRC_NETIF2_PRIO, + "eth", ethernet_dev + ))); + TEST_ASSERT_EQUAL_INT(1, gnrc_netif2_numof()); + TEST_ASSERT_NOT_NULL((ptr = gnrc_netif2_iter(ptr))); + TEST_ASSERT_NULL((ptr = gnrc_netif2_iter(ptr))); + TEST_ASSERT_NOT_NULL(ethernet_netif->ops); + TEST_ASSERT_NOT_NULL(ethernet_netif->dev); + TEST_ASSERT_EQUAL_INT(ETHERNET_DATA_LEN, ethernet_netif->ipv6_mtu); + TEST_ASSERT_EQUAL_INT(GNRC_NETIF2_DEFAULT_HL, ethernet_netif->cur_hl); + TEST_ASSERT_EQUAL_INT(NETDEV_TYPE_ETHERNET, ethernet_netif->device_type); + TEST_ASSERT(ethernet_netif->pid > KERNEL_PID_UNDEF); +#ifdef DEVELHELP + TEST_ASSERT_EQUAL_STRING("eth", sched_threads[ethernet_netif->pid]->name); +#endif + TEST_ASSERT_NOT_NULL(sched_threads[ethernet_netif->pid]->msg_array); + for (unsigned i = 0; i < DEFAULT_DEVS_NUMOF; i++) { + TEST_ASSERT_NOT_NULL((netifs[i] = gnrc_netif2_create( + netifs_stack[i], THREAD_STACKSIZE_DEFAULT, + GNRC_NETIF2_PRIO, "netif", devs[i], &default_ops + ))); + TEST_ASSERT_NOT_NULL(netifs[i]->ops); + TEST_ASSERT_NOT_NULL(netifs[i]->dev); + TEST_ASSERT_EQUAL_INT(GNRC_NETIF2_DEFAULT_HL, netifs[i]->cur_hl); + TEST_ASSERT_EQUAL_INT(NETDEV_TYPE_UNKNOWN, netifs[i]->device_type); + TEST_ASSERT(netifs[i]->pid > KERNEL_PID_UNDEF); + TEST_ASSERT_NOT_NULL(sched_threads[netifs[i]->pid]->msg_array); + TEST_ASSERT_EQUAL_INT(i + 2, gnrc_netif2_numof()); + for (unsigned j = 0; j < (i + 2); j++) { + TEST_ASSERT_NOT_NULL((ptr = gnrc_netif2_iter(ptr))); + } + TEST_ASSERT_NULL((ptr = gnrc_netif2_iter(ptr))); + } + TEST_ASSERT_NULL(gnrc_netif2_create(test_stack, 4, GNRC_NETIF2_PRIO, + "netif", NULL, &default_ops)); +} + +static void test_get_by_pid(void) +{ + TEST_ASSERT(ethernet_netif == gnrc_netif2_get_by_pid(ethernet_netif->pid)); + for (kernel_pid_t i = 0; i < DEFAULT_DEVS_NUMOF; i++) { + TEST_ASSERT(netifs[i] == gnrc_netif2_get_by_pid(netifs[i]->pid)); + } +} + +static void test_ipv6_addr_add__ENOMEM(void) +{ + ipv6_addr_t addr = { .u8 = NETIF0_IPV6_G }; + + for (unsigned i = 0; i < GNRC_NETIF2_IPV6_ADDRS_NUMOF; + i++, addr.u16[3].u16++) { + TEST_ASSERT(0 <= gnrc_netif2_ipv6_addr_add(netifs[0], &addr, 64U, + GNRC_NETIF2_IPV6_ADDRS_FLAGS_STATE_VALID)); + } + TEST_ASSERT_EQUAL_INT(-ENOMEM, + gnrc_netif2_ipv6_addr_add(netifs[0], &addr, 64U, + GNRC_NETIF2_IPV6_ADDRS_FLAGS_STATE_VALID)); +} + +static void test_ipv6_addr_add__success(void) +{ + static const ipv6_addr_t addr = { .u8 = NETIF0_IPV6_LL }; + int idx; + + TEST_ASSERT(0 <= (idx = gnrc_netif2_ipv6_addr_add(netifs[0], &addr, 64U, + GNRC_NETIF2_IPV6_ADDRS_FLAGS_STATE_VALID))); + /* check duplicate addition */ + TEST_ASSERT_EQUAL_INT(idx, + gnrc_netif2_ipv6_addr_add(netifs[0], &addr, 64U, + GNRC_NETIF2_IPV6_ADDRS_FLAGS_STATE_VALID)); + TEST_ASSERT_EQUAL_INT(GNRC_NETIF2_IPV6_ADDRS_FLAGS_STATE_VALID, + netifs[0]->ipv6_addrs_flags[idx]); + TEST_ASSERT(ipv6_addr_equal(&addr, &netifs[0]->ipv6_addrs[idx])); +} + +static void test_ipv6_addr_add__readd_with_free_entry(void) +{ + /* Tests for possible duplicates (see #2965) */ + static const ipv6_addr_t addr1 = { .u8 = NETIF0_IPV6_LL }; + static const ipv6_addr_t addr2 = { .u8 = NETIF0_IPV6_G }; + int idx; + + TEST_ASSERT(0 <= gnrc_netif2_ipv6_addr_add(netifs[0], &addr1, 64U, + GNRC_NETIF2_IPV6_ADDRS_FLAGS_STATE_VALID)); + TEST_ASSERT(0 <= (idx = gnrc_netif2_ipv6_addr_add(netifs[0], &addr2, 64U, + GNRC_NETIF2_IPV6_ADDRS_FLAGS_STATE_VALID))); + gnrc_netif2_ipv6_addr_remove(netifs[0], &addr1); + TEST_ASSERT_EQUAL_INT(idx, + gnrc_netif2_ipv6_addr_add(netifs[0], &addr2, 64U, + GNRC_NETIF2_IPV6_ADDRS_FLAGS_STATE_VALID)); +} + +static void test_ipv6_addr_remove__not_allocated(void) +{ + static const ipv6_addr_t addr1 = { .u8 = NETIF0_IPV6_LL }; + static const ipv6_addr_t addr2 = { .u8 = NETIF0_IPV6_G }; + + test_ipv6_addr_add__success(); + TEST_ASSERT(0 <= gnrc_netif2_ipv6_addr_idx(netifs[0], &addr1)); + TEST_ASSERT(0 <= gnrc_netif2_ipv6_addr_add(netifs[0], &addr2, 64U, + GNRC_NETIF2_IPV6_ADDRS_FLAGS_STATE_VALID)); + gnrc_netif2_ipv6_addr_remove(netifs[0], &addr2); + TEST_ASSERT(0 <= gnrc_netif2_ipv6_addr_idx(netifs[0], &addr1)); +} + +static void test_ipv6_addr_remove__success(void) +{ + static const ipv6_addr_t addr = { .u8 = NETIF0_IPV6_LL }; + + test_ipv6_addr_add__success(); + gnrc_netif2_ipv6_addr_remove(netifs[0], &addr); + TEST_ASSERT_EQUAL_INT(-1, gnrc_netif2_ipv6_addr_idx(netifs[0], &addr)); +} + +static void test_ipv6_addr_idx__empty(void) +{ + static const ipv6_addr_t addr = { .u8 = NETIF0_IPV6_LL }; + + TEST_ASSERT_EQUAL_INT(-1, gnrc_netif2_ipv6_addr_idx(netifs[0], &addr)); +} + +static void test_ipv6_addr_idx__wrong_netif(void) +{ + static const ipv6_addr_t addr = { .u8 = NETIF0_IPV6_LL }; + + test_ipv6_addr_add__success(); + TEST_ASSERT_EQUAL_INT(-1, gnrc_netif2_ipv6_addr_idx(netifs[1], &addr)); +} + +static void test_ipv6_addr_idx__wrong_addr(void) +{ + static const ipv6_addr_t addr2 = { .u8 = NETIF0_IPV6_G }; + + test_ipv6_addr_add__success(); + TEST_ASSERT_EQUAL_INT(-1, gnrc_netif2_ipv6_addr_idx(netifs[0], &addr2)); +} + +static void test_ipv6_addr_idx__success(void) +{ + static const ipv6_addr_t addr = { .u8 = NETIF0_IPV6_LL }; + + test_ipv6_addr_add__success(); + TEST_ASSERT(0 <= gnrc_netif2_ipv6_addr_idx(netifs[0], &addr)); +} + +static void test_ipv6_addr_match__empty(void) +{ + static const ipv6_addr_t addr = { .u8 = NETIF0_IPV6_G }; + + TEST_ASSERT_EQUAL_INT(-1, gnrc_netif2_ipv6_addr_match(netifs[0], &addr)); +} + +static void test_ipv6_addr_match__wrong_netif(void) +{ + static const ipv6_addr_t addr = { .u8 = NETIF0_IPV6_G }; + + test_ipv6_addr_add__success(); + TEST_ASSERT_EQUAL_INT(-1, gnrc_netif2_ipv6_addr_match(netifs[1], &addr)); +} + +static void test_ipv6_addr_match__wrong_addr(void) +{ + static const ipv6_addr_t addr2 = { .u8 = NETIF0_IPV6_G }; + + test_ipv6_addr_add__success(); + TEST_ASSERT_EQUAL_INT(-1, gnrc_netif2_ipv6_addr_match(netifs[0], &addr2)); +} + +static void test_ipv6_addr_match__success18(void) +{ + static const ipv6_addr_t addr = { .u8 = NETIF0_IPV6_G }; + + static const ipv6_addr_t pfx = { .u8 = GLOBAL_PFX18 }; + int idx; + + TEST_ASSERT(0 <= (idx = gnrc_netif2_ipv6_addr_add(netifs[0], &addr, 64U, + GNRC_NETIF2_IPV6_ADDRS_FLAGS_STATE_VALID))); + TEST_ASSERT_EQUAL_INT(idx, gnrc_netif2_ipv6_addr_match(netifs[0], &pfx)); + TEST_ASSERT_EQUAL_INT(18, ipv6_addr_match_prefix(&netifs[0]->ipv6_addrs[idx], + &pfx)); +} + +static void test_ipv6_addr_match__success23(void) +{ + static const ipv6_addr_t addr = { .u8 = NETIF0_IPV6_G }; + + static const ipv6_addr_t pfx = { .u8 = GLOBAL_PFX23 }; + int idx; + + TEST_ASSERT(0 <= (idx = gnrc_netif2_ipv6_addr_add(netifs[0], &addr, 64U, + GNRC_NETIF2_IPV6_ADDRS_FLAGS_STATE_VALID))); + TEST_ASSERT_EQUAL_INT(idx, gnrc_netif2_ipv6_addr_match(netifs[0], &pfx)); + TEST_ASSERT_EQUAL_INT(23, ipv6_addr_match_prefix(&netifs[0]->ipv6_addrs[idx], + &pfx)); +} + +static void test_ipv6_addr_match__success64(void) +{ + static const ipv6_addr_t addr = { .u8 = NETIF0_IPV6_G }; + + static const ipv6_addr_t pfx = { .u8 = GLOBAL_PFX64 }; + int idx; + + TEST_ASSERT(0 <= (idx = gnrc_netif2_ipv6_addr_add(netifs[0], &addr, 64U, + GNRC_NETIF2_IPV6_ADDRS_FLAGS_STATE_VALID))); + TEST_ASSERT_EQUAL_INT(idx, gnrc_netif2_ipv6_addr_match(netifs[0], &pfx)); + TEST_ASSERT_EQUAL_INT(64, ipv6_addr_match_prefix(&netifs[0]->ipv6_addrs[idx], + &pfx)); +} + +static void test_ipv6_addr_best_src__multicast_input(void) +{ + static const ipv6_addr_t addr1 = { .u8 = NETIF0_IPV6_G }; + + static const ipv6_addr_t addr2 = { .u8 = GLOBAL_PFX18 }; + ipv6_addr_t *out; + + /* adds a link-local address */ + test_ipv6_addr_add__success(); + TEST_ASSERT(0 <= gnrc_netif2_ipv6_addr_add(netifs[0], &addr1, 64U, + GNRC_NETIF2_IPV6_ADDRS_FLAGS_STATE_VALID)); + TEST_ASSERT_NOT_NULL((out = gnrc_netif2_ipv6_addr_best_src(netifs[0], + &addr2, + false))); + TEST_ASSERT(!ipv6_addr_equal(&addr2, out)); + TEST_ASSERT(ipv6_addr_equal(&addr1, out)); +} + +static void test_ipv6_addr_best_src__other_subnet(void) +{ + static const ipv6_addr_t mc_addr = IPV6_ADDR_ALL_ROUTERS_SITE_LOCAL; + ipv6_addr_t *out = NULL; + + test_ipv6_addr_add__success(); + TEST_ASSERT_NOT_NULL((out = gnrc_netif2_ipv6_addr_best_src(netifs[0], + &mc_addr, + false))); + TEST_ASSERT(!ipv6_addr_equal(&mc_addr, out)); + TEST_ASSERT(!ipv6_addr_is_multicast(out)); + TEST_ASSERT(!ipv6_addr_is_unspecified(out)); +} + +static void test_get_by_ipv6_addr__empty(void) +{ + static const ipv6_addr_t addr = { .u8 = NETIF0_IPV6_LL }; + + TEST_ASSERT_NULL(gnrc_netif2_get_by_ipv6_addr(&addr)); +} + +static void test_get_by_ipv6_addr__success(void) +{ + static const ipv6_addr_t addr = { .u8 = NETIF0_IPV6_LL }; + + test_ipv6_addr_add__success(); + TEST_ASSERT_NOT_NULL(netifs[0]); + TEST_ASSERT(netifs[0] == gnrc_netif2_get_by_ipv6_addr(&addr)); +} + +static void test_get_by_prefix__empty(void) +{ + static const ipv6_addr_t addr = { .u8 = NETIF0_IPV6_G }; + + TEST_ASSERT_NULL(gnrc_netif2_get_by_prefix(&addr)); +} + +static void test_get_by_prefix__success18(void) +{ + static const ipv6_addr_t addr = { .u8 = NETIF0_IPV6_G }; + static const ipv6_addr_t pfx = { .u8 = GLOBAL_PFX18 }; + + TEST_ASSERT(0 <= gnrc_netif2_ipv6_addr_add(netifs[0], &addr, 64U, + GNRC_NETIF2_IPV6_ADDRS_FLAGS_STATE_VALID)); + TEST_ASSERT_NOT_NULL(netifs[0]); + TEST_ASSERT(netifs[0] == gnrc_netif2_get_by_prefix(&pfx)); + test_ipv6_addr_match__success18(); +} + +static void test_get_by_prefix__success23(void) +{ + static const ipv6_addr_t addr = { .u8 = NETIF0_IPV6_G }; + static const ipv6_addr_t pfx = { .u8 = GLOBAL_PFX23 }; + + TEST_ASSERT(0 <= gnrc_netif2_ipv6_addr_add(netifs[0], &addr, 64U, + GNRC_NETIF2_IPV6_ADDRS_FLAGS_STATE_VALID)); + TEST_ASSERT_NOT_NULL(netifs[0]); + TEST_ASSERT(netifs[0] == gnrc_netif2_get_by_prefix(&pfx)); + test_ipv6_addr_match__success23(); +} + +static void test_get_by_prefix__success64(void) +{ + static const ipv6_addr_t addr = { .u8 = NETIF0_IPV6_G }; + static const ipv6_addr_t pfx = { .u8 = GLOBAL_PFX64 }; + + TEST_ASSERT(0 <= gnrc_netif2_ipv6_addr_add(netifs[0], &addr, 64U, + GNRC_NETIF2_IPV6_ADDRS_FLAGS_STATE_VALID)); + TEST_ASSERT_NOT_NULL(netifs[0]); + TEST_ASSERT(netifs[0] == gnrc_netif2_get_by_prefix(&pfx)); + test_ipv6_addr_match__success64(); +} + +static void test_ipv6_group_join__ENOMEM(void) +{ + ipv6_addr_t addr = IPV6_ADDR_ALL_NODES_LINK_LOCAL; + + for (unsigned i = 0; i < GNRC_NETIF2_IPV6_ADDRS_NUMOF; + i++, addr.u16[7].u16++) { + TEST_ASSERT(0 <= gnrc_netif2_ipv6_group_join(netifs[0], &addr)); + } + TEST_ASSERT_EQUAL_INT(-ENOMEM, + gnrc_netif2_ipv6_group_join(netifs[0], &addr)); +} + +static void test_ipv6_group_join__success(void) +{ + int idx; + + TEST_ASSERT(0 <= (idx = gnrc_netif2_ipv6_group_join(netifs[0], + &ipv6_addr_all_nodes_link_local))); + /* check duplicate addition */ + TEST_ASSERT_EQUAL_INT(idx, + gnrc_netif2_ipv6_group_join(netifs[0], + &ipv6_addr_all_nodes_link_local)); + TEST_ASSERT(ipv6_addr_equal(&ipv6_addr_all_nodes_link_local, + &netifs[0]->ipv6_groups[idx])); +} + +static void test_ipv6_group_join__readd_with_free_entry(void) +{ + /* Tests for possible duplicates (see #2965) */ + int idx; + + TEST_ASSERT(0 <= gnrc_netif2_ipv6_group_join(netifs[0], + &ipv6_addr_all_nodes_link_local)); + TEST_ASSERT(0 <= (idx = gnrc_netif2_ipv6_group_join(netifs[0], + &ipv6_addr_all_routers_link_local))); + gnrc_netif2_ipv6_group_leave(netifs[0], &ipv6_addr_all_nodes_link_local); + TEST_ASSERT_EQUAL_INT(idx, + gnrc_netif2_ipv6_group_join(netifs[0], + &ipv6_addr_all_routers_link_local)); +} + +static void test_ipv6_group_leave__not_allocated(void) +{ + test_ipv6_group_join__success(); + TEST_ASSERT(0 <= gnrc_netif2_ipv6_group_idx(netifs[0], + &ipv6_addr_all_nodes_link_local)); + TEST_ASSERT(0 <= gnrc_netif2_ipv6_group_join(netifs[0], + &ipv6_addr_all_routers_link_local)); + gnrc_netif2_ipv6_group_leave(netifs[0], &ipv6_addr_all_routers_link_local); + TEST_ASSERT(0 <= gnrc_netif2_ipv6_group_idx(netifs[0], + &ipv6_addr_all_nodes_link_local)); +} + +static void test_ipv6_group_leave__success(void) +{ + test_ipv6_group_join__success(); + gnrc_netif2_ipv6_group_leave(netifs[0], &ipv6_addr_all_nodes_link_local); + TEST_ASSERT_EQUAL_INT(-1, gnrc_netif2_ipv6_group_idx(netifs[0], + &ipv6_addr_all_nodes_link_local)); +} + +static void test_ipv6_group_idx__empty(void) +{ + TEST_ASSERT_EQUAL_INT(-1, gnrc_netif2_ipv6_group_idx(netifs[0], + &ipv6_addr_all_nodes_link_local)); +} + +static void test_ipv6_group_idx__wrong_netif(void) +{ + test_ipv6_group_join__success(); + TEST_ASSERT_EQUAL_INT(-1, gnrc_netif2_ipv6_group_idx(netifs[1], + &ipv6_addr_all_nodes_link_local)); +} + +static void test_ipv6_group_idx__wrong_addr(void) +{ + test_ipv6_group_join__success(); + TEST_ASSERT_EQUAL_INT(-1, gnrc_netif2_ipv6_group_idx(netifs[0], + &ipv6_addr_all_routers_link_local)); +} + +static void test_ipv6_group_idx__success(void) +{ + test_ipv6_group_join__success(); + TEST_ASSERT(0 <= gnrc_netif2_ipv6_group_idx(netifs[0], &ipv6_addr_all_nodes_link_local)); +} + +static void test_ipv6_get_iid(void) +{ + static const ipv6_addr_t ethernet_ipv6_ll = { .u8 = ETHERNET_IPV6_LL }; + eui64_t res; + + TEST_ASSERT_EQUAL_INT(0, gnrc_netif2_ipv6_get_iid(ethernet_netif, &res)); + TEST_ASSERT_EQUAL_INT(0, memcmp(&res, ðernet_ipv6_ll.u64[1], + sizeof(res))); + for (unsigned i = 0; i < DEFAULT_DEVS_NUMOF; i++) { + TEST_ASSERT_EQUAL_INT(-ENOTSUP, gnrc_netif2_ipv6_get_iid(netifs[i], &res)); + } +} + +static void test_netapi_get__HOP_LIMIT(void) +{ + uint8_t value; + + TEST_ASSERT_EQUAL_INT(sizeof(value), + gnrc_netapi_get(netifs[0]->pid, NETOPT_HOP_LIMIT, + 0, &value, sizeof(value))); + TEST_ASSERT_EQUAL_INT(netifs[0]->cur_hl, value); +} + +static void test_netapi_get__IPV6_ADDR(void) +{ + static const ipv6_addr_t exp = { NETIF0_IPV6_LL }; + ipv6_addr_t value[GNRC_NETIF2_IPV6_ADDRS_NUMOF]; + + test_ipv6_addr_add__success(); + TEST_ASSERT_EQUAL_INT(sizeof(ipv6_addr_t), gnrc_netapi_get(netifs[0]->pid, + NETOPT_IPV6_ADDR, + 0, &value, + sizeof(value))); + TEST_ASSERT(ipv6_addr_equal(&exp, &value[0])); +} + +static void test_netapi_get__IPV6_ADDR_FLAGS(void) +{ + uint8_t value[GNRC_NETIF2_IPV6_ADDRS_NUMOF]; + + test_ipv6_addr_add__success(); + TEST_ASSERT_EQUAL_INT(sizeof(uint8_t), gnrc_netapi_get(netifs[0]->pid, + NETOPT_IPV6_ADDR_FLAGS, + 0, &value, + sizeof(value))); + TEST_ASSERT_EQUAL_INT(GNRC_NETIF2_IPV6_ADDRS_FLAGS_STATE_VALID, + value[0]); +} + +static void test_netapi_get__IPV6_GROUP(void) +{ + ipv6_addr_t value[GNRC_NETIF2_IPV6_GROUPS_NUMOF]; + + test_ipv6_group_join__success(); + TEST_ASSERT_EQUAL_INT(sizeof(ipv6_addr_t), gnrc_netapi_get(netifs[0]->pid, + NETOPT_IPV6_GROUP, + 0, &value, + sizeof(value))); + TEST_ASSERT(ipv6_addr_equal(&ipv6_addr_all_nodes_link_local, &value[0])); +} + +static void test_netapi_get__IPV6_IID(void) +{ + static const ipv6_addr_t ethernet_ipv6_ll = { .u8 = ETHERNET_IPV6_LL }; + eui64_t value; + + TEST_ASSERT_EQUAL_INT(sizeof(eui64_t), gnrc_netapi_get(ethernet_netif->pid, + NETOPT_IPV6_IID, + 0, &value, sizeof(value))); + TEST_ASSERT_EQUAL_INT(0, memcmp(&value, ðernet_ipv6_ll.u64[1], + sizeof(value))); + TEST_ASSERT_EQUAL_INT(-ENOTSUP, gnrc_netapi_get(netifs[0]->pid, + NETOPT_IPV6_IID, + 0, &value, sizeof(value))); +} + +static void test_netapi_get__MAX_PACKET_SIZE(void) +{ + uint16_t value; + + TEST_ASSERT_EQUAL_INT(sizeof(uint16_t), gnrc_netapi_get(ethernet_netif->pid, + NETOPT_MAX_PACKET_SIZE, + GNRC_NETTYPE_IPV6, + &value, sizeof(value))); + TEST_ASSERT_EQUAL_INT(ETHERNET_DATA_LEN, value); + TEST_ASSERT_EQUAL_INT(sizeof(uint16_t), gnrc_netapi_get(ethernet_netif->pid, + NETOPT_MAX_PACKET_SIZE, + GNRC_NETTYPE_NETIF, + &value, sizeof(value))); + TEST_ASSERT_EQUAL_INT(ETHERNET_DATA_LEN, value); + TEST_ASSERT_EQUAL_INT(sizeof(uint16_t), gnrc_netapi_get(netifs[0]->pid, + NETOPT_MAX_PACKET_SIZE, + GNRC_NETTYPE_IPV6, + &value, sizeof(value))); + TEST_ASSERT_EQUAL_INT(IPV6_MIN_MTU, value); + TEST_ASSERT_EQUAL_INT(sizeof(uint16_t), gnrc_netapi_get(netifs[0]->pid, + NETOPT_MAX_PACKET_SIZE, + GNRC_NETTYPE_NETIF, + &value, sizeof(value))); + TEST_ASSERT_EQUAL_INT(IPV6_MIN_MTU, value); +} + +static void test_netapi_get__6LO_IPHC(void) +{ + netopt_enable_t value; + + TEST_ASSERT_EQUAL_INT(sizeof(netopt_enable_t), + gnrc_netapi_get(ethernet_netif->pid, + NETOPT_6LO_IPHC, 0, + &value, sizeof(value))); + TEST_ASSERT_EQUAL_INT(NETOPT_DISABLE, value); + TEST_ASSERT_EQUAL_INT(sizeof(netopt_enable_t), + gnrc_netapi_get(netifs[0]->pid, + NETOPT_6LO_IPHC, 0, + &value, sizeof(value))); + TEST_ASSERT_EQUAL_INT(NETOPT_DISABLE, value); +} + +static void test_netapi_get__ADDRESS(void) +{ + static const uint8_t exp_ethernet[] = ETHERNET_SRC; + uint8_t value[GNRC_NETIF2_L2ADDR_MAXLEN]; + + TEST_ASSERT_EQUAL_INT(sizeof(exp_ethernet), + gnrc_netapi_get(ethernet_netif->pid, + NETOPT_ADDRESS, 0, + &value, sizeof(value))); + TEST_ASSERT_EQUAL_INT(0, memcmp(exp_ethernet, value, sizeof(exp_ethernet))); +} + +static void test_netapi_get__ADDRESS_LONG(void) +{ + uint8_t value[GNRC_NETIF2_L2ADDR_MAXLEN]; + + TEST_ASSERT_EQUAL_INT(-ENOTSUP, + gnrc_netapi_get(ethernet_netif->pid, + NETOPT_ADDRESS_LONG, 0, + &value, sizeof(value))); + TEST_ASSERT_EQUAL_INT(-ENOTSUP, + gnrc_netapi_get(netifs[0]->pid, + NETOPT_ADDRESS_LONG, 0, + &value, sizeof(value))); +} + +static void test_netapi_set__HOP_LIMIT(void) +{ + uint8_t value = 89; + + TEST_ASSERT_EQUAL_INT(sizeof(value), + gnrc_netapi_set(netifs[0]->pid, + NETOPT_HOP_LIMIT, 0, + &value, sizeof(value))); + TEST_ASSERT_EQUAL_INT(value, netifs[0]->cur_hl); +} + +static void test_netapi_set__IPV6_ADDR(void) +{ + ipv6_addr_t value = { .u8 = NETIF0_IPV6_LL }; + static const uint16_t context = (64U << 8) | + (GNRC_NETIF2_IPV6_ADDRS_FLAGS_STATE_VALID); + + TEST_ASSERT(0 > gnrc_netif2_ipv6_addr_idx(netifs[0], &value)); + TEST_ASSERT_EQUAL_INT(sizeof(value), + gnrc_netapi_set(netifs[0]->pid, + NETOPT_IPV6_ADDR, context, + &value, sizeof(value))); + TEST_ASSERT(0 <= gnrc_netif2_ipv6_addr_idx(netifs[0], &value)); +} + +static void test_netapi_set__IPV6_ADDR_REMOVE(void) +{ + ipv6_addr_t value = { .u8 = NETIF0_IPV6_LL }; + + test_ipv6_addr_add__success(); + TEST_ASSERT(0 <= gnrc_netif2_ipv6_addr_idx(netifs[0], &value)); + TEST_ASSERT_EQUAL_INT(sizeof(value), + gnrc_netapi_set(netifs[0]->pid, + NETOPT_IPV6_ADDR_REMOVE, 0, + &value, sizeof(value))); + TEST_ASSERT(0 > gnrc_netif2_ipv6_addr_idx(netifs[0], &value)); +} + +static void test_netapi_set__IPV6_GROUP(void) +{ + ipv6_addr_t value = IPV6_ADDR_ALL_NODES_LINK_LOCAL; + + TEST_ASSERT(0 > gnrc_netif2_ipv6_group_idx(netifs[0], &value)); + TEST_ASSERT_EQUAL_INT(sizeof(value), + gnrc_netapi_set(netifs[0]->pid, + NETOPT_IPV6_GROUP, 0, + &value, sizeof(value))); + TEST_ASSERT(0 <= gnrc_netif2_ipv6_group_idx(netifs[0], &value)); +} + +static void test_netapi_set__IPV6_GROUP_LEAVE(void) +{ + ipv6_addr_t value = IPV6_ADDR_ALL_NODES_LINK_LOCAL; + + test_ipv6_group_join__success(); + TEST_ASSERT(0 <= gnrc_netif2_ipv6_group_idx(netifs[0], &value)); + TEST_ASSERT_EQUAL_INT(sizeof(value), + gnrc_netapi_set(netifs[0]->pid, + NETOPT_IPV6_GROUP_LEAVE, 0, + &value, sizeof(value))); + TEST_ASSERT(0 > gnrc_netif2_ipv6_group_idx(netifs[0], &value)); +} + +static void test_netapi_set__MAX_PACKET_SIZE(void) +{ + uint16_t value = 57194; + + TEST_ASSERT_EQUAL_INT(sizeof(value), + gnrc_netapi_set(netifs[0]->pid, + NETOPT_MAX_PACKET_SIZE, + GNRC_NETTYPE_IPV6, + &value, sizeof(value))); + TEST_ASSERT_EQUAL_INT(value, netifs[0]->ipv6_mtu); + TEST_ASSERT_EQUAL_INT(-ENOTSUP, + gnrc_netapi_set(netifs[0]->pid, + NETOPT_MAX_PACKET_SIZE, 0, + &value, sizeof(value))); +} + +static void test_netapi_set__6LO_IPHC(void) +{ + netopt_enable_t value = NETOPT_ENABLE; + + TEST_ASSERT_EQUAL_INT(sizeof(value), + gnrc_netapi_set(netifs[0]->pid, + NETOPT_6LO_IPHC, 0, + &value, sizeof(value))); + TEST_ASSERT(netifs[0]->flags & GNRC_NETIF2_FLAGS_6LO_HC); +} + +static void test_netapi_set__ADDRESS(void) +{ + static const uint8_t exp_ethernet[] = ETHERNET_SRC; + uint8_t value[] = { LA1 + 1, LA2 + 2, LA3 + 3, LA4 + 4, LA5 + 5, LA6 + 6 }; + + TEST_ASSERT_EQUAL_INT(sizeof(exp_ethernet), + gnrc_netapi_set(ethernet_netif->pid, + NETOPT_ADDRESS, 0, + &value, sizeof(value))); + TEST_ASSERT_EQUAL_INT(sizeof(value), ethernet_netif->l2addr_len); + TEST_ASSERT_EQUAL_INT(0, memcmp(value, ethernet_netif->l2addr, + sizeof(value))); + TEST_ASSERT_EQUAL_INT(-ENOTSUP, + gnrc_netapi_set(netifs[0]->pid, + NETOPT_ADDRESS_LONG, 0, + &value, sizeof(value))); + /* return addresses to previous state for further testing */ + memcpy(value, exp_ethernet, sizeof(exp_ethernet)); + TEST_ASSERT_EQUAL_INT(sizeof(exp_ethernet), + gnrc_netapi_set(ethernet_netif->pid, + NETOPT_ADDRESS, 0, + &value, sizeof(value))); + TEST_ASSERT_EQUAL_INT(sizeof(value), ethernet_netif->l2addr_len); + TEST_ASSERT_EQUAL_INT(0, memcmp(value, ethernet_netif->l2addr, + sizeof(value))); +} + +static void test_netapi_set__ADDRESS_LONG(void) +{ + uint8_t value[GNRC_NETIF2_L2ADDR_MAXLEN]; + + TEST_ASSERT_EQUAL_INT(-ENOTSUP, + gnrc_netapi_set(ethernet_netif->pid, + NETOPT_ADDRESS_LONG, 0, + &value, sizeof(value))); + TEST_ASSERT_EQUAL_INT(-ENOTSUP, + gnrc_netapi_set(netifs[0]->pid, + NETOPT_ADDRESS_LONG, 0, + &value, sizeof(value))); +} + +static void test_netapi_send__raw_unicast_ethernet_packet(void) +{ + uint8_t dst[] = { LA1, LA2, LA3, LA4, LA5, LA6 + 1 }; + gnrc_pktsnip_t *pkt = gnrc_pktbuf_add(NULL, "ABCDEFG", + sizeof("ABCDEFG"), + GNRC_NETTYPE_UNDEF); + TEST_ASSERT_NOT_NULL(pkt); + gnrc_pktsnip_t *netif = gnrc_netif_hdr_build(NULL, 0, dst, sizeof(dst)); + TEST_ASSERT_NOT_NULL(netif); + LL_PREPEND(pkt, netif); + gnrc_netapi_send(ethernet_netif->pid, pkt); +} + +static void test_netapi_send__raw_broadcast_ethernet_packet(void) +{ + gnrc_netif_hdr_t *hdr; + gnrc_pktsnip_t *pkt = gnrc_pktbuf_add(NULL, "ABCDEFG", + sizeof("ABCDEFG"), + GNRC_NETTYPE_UNDEF); + TEST_ASSERT_NOT_NULL(pkt); + gnrc_pktsnip_t *netif = gnrc_netif_hdr_build(NULL, 0, NULL, 0); + TEST_ASSERT_NOT_NULL(netif); + hdr = netif->data; + hdr->flags |= GNRC_NETIF_HDR_FLAGS_BROADCAST; + LL_PREPEND(pkt, netif); + gnrc_netapi_send(ethernet_netif->pid, pkt); +} + +static void test_netapi_send__ipv6_unicast_ethernet_packet(void) +{ + ipv6_hdr_t *ipv6_hdr; + uint8_t dst_netif[] = { LA1, LA2, LA3, LA4, LA5, LA6 + 1 }; + static const ipv6_addr_t dst_ipv6 = { .u8 = { LP1, LP2, LP3, LP4, + LP5, LP6, LP7, LP8, + LA1 ^ 0x2, LA2, LA3, 0xff, + 0xfe, LA4, LA5, LA6 + 1} }; + static const ipv6_addr_t src_ipv6 = { .u8 = ETHERNET_IPV6_LL }; + gnrc_pktsnip_t *payload = gnrc_pktbuf_add(NULL, "ABCDEFG", + sizeof("ABCDEFG"), + GNRC_NETTYPE_UNDEF); + TEST_ASSERT_NOT_NULL(payload); + /* we don't send through gnrc_ipv6 (because we are lazy and don't want + * to update the neighbor cache ;-)) so we need to set the IPv6 source + * address */ + gnrc_pktsnip_t *pkt = gnrc_ipv6_hdr_build(payload, &src_ipv6, &dst_ipv6); + TEST_ASSERT_NOT_NULL(pkt); + ipv6_hdr = pkt->data; + ipv6_hdr->len = byteorder_htons(sizeof("ABCDEFG")); + ipv6_hdr->nh = PROTNUM_IPV6_NONXT; + ipv6_hdr->hl = ethernet_netif->cur_hl; + gnrc_pktsnip_t *netif = gnrc_netif_hdr_build(NULL, 0, dst_netif, + sizeof(dst_netif)); + TEST_ASSERT_NOT_NULL(netif); + LL_PREPEND(pkt, netif); + gnrc_netapi_send(ethernet_netif->pid, pkt); +} + +static void test_netapi_send__ipv6_multicast_ethernet_packet(void) +{ + ipv6_hdr_t *ipv6_hdr; + gnrc_netif_hdr_t *netif_hdr; + static const ipv6_addr_t src_ipv6 = { .u8 = ETHERNET_IPV6_LL }; + gnrc_pktsnip_t *payload = gnrc_pktbuf_add(NULL, "ABCDEFG", + sizeof("ABCDEFG"), + GNRC_NETTYPE_UNDEF); + TEST_ASSERT_NOT_NULL(payload); + /* we don't send through gnrc_ipv6 (because we are lazy and don't want + * to update the neighbor cache ;-)) so we need to set the IPv6 source + * address */ + gnrc_pktsnip_t *pkt = gnrc_ipv6_hdr_build(payload, &src_ipv6, + &ipv6_addr_all_nodes_link_local); + TEST_ASSERT_NOT_NULL(pkt); + ipv6_hdr = pkt->data; + ipv6_hdr->len = byteorder_htons(sizeof("ABCDEFG")); + ipv6_hdr->nh = PROTNUM_IPV6_NONXT; + ipv6_hdr->hl = ethernet_netif->cur_hl; + gnrc_pktsnip_t *netif = gnrc_netif_hdr_build(NULL, 0, NULL, 0); + TEST_ASSERT_NOT_NULL(netif); + netif_hdr = netif->data; + netif_hdr->flags |= GNRC_NETIF_HDR_FLAGS_MULTICAST; + LL_PREPEND(pkt, netif); + gnrc_netapi_send(ethernet_netif->pid, pkt); +} + +static void test_netapi_recv__empty_ethernet_payload(void) +{ + static const uint8_t data[] = { LA1, LA2, LA3, LA6, LA7, LA8, + LA1, LA2, LA3, LA6, LA7, LA8 + 1, + 0xff, 0xff }; + + puts("pktdump dumping Ethernet packet with empty payload"); + _test_trigger_recv(ethernet_netif, data, sizeof(data)); +} + +static void test_netapi_recv__raw_ethernet_payload(void) +{ + static const uint8_t data[] = { LA1, LA2, LA3, LA6, LA7, LA8, + LA1, LA2, LA3, LA6, LA7, LA8 + 1, + 0xff, 0xff, 0x12, 0x34, 0x45, 0x56 }; + + puts("pktdump dumping Ethernet packet with payload 12 34 45 56"); + _test_trigger_recv(ethernet_netif, data, sizeof(data)); +} + +static void test_netapi_recv__ipv6_ethernet_payload(void) +{ + static const uint8_t data[] = { LA1, LA2, LA3, LA6, LA7, LA8, + LA1, LA2, LA3, LA6, LA7, LA8 + 1, + 0x86, 0xdd, /* Ethertype: IPv6 */ + 0x60, 0, 0, 0, /* Version + TC + FL */ + 0, 1, /* payload length 1 */ + 59, /* next header: no next header */ + 64, /* hop limit */ + /* IPv6 source */ + LP1, LP2, LP3, LP4, LP5, LP6, LP7, LP8, + LA1 ^ 1, LA2, LA3, 0xff, 0xfe, LA6, LA7, LA8, + /* IPv6 destination */ + LP1, LP2, LP3, LP4, LP5, LP6, LP7, LP8, + LA1 ^ 1, LA2, LA3, 0xff, 0xfe, LA6, LA7, LA8 + 1, + 0x01 /* payload */ + }; + + puts("pktdump dumping IPv6 over Ethernet packet with payload 01"); + _test_trigger_recv(ethernet_netif, data, sizeof(data)); +} + +static Test *embunit_tests_gnrc_netif2(void) +{ + EMB_UNIT_TESTFIXTURES(fixtures) { + new_TestFixture(test_creation), + new_TestFixture(test_get_by_pid), + new_TestFixture(test_ipv6_addr_add__ENOMEM), + new_TestFixture(test_ipv6_addr_add__success), + new_TestFixture(test_ipv6_addr_add__readd_with_free_entry), + new_TestFixture(test_ipv6_addr_remove__not_allocated), + new_TestFixture(test_ipv6_addr_remove__success), + new_TestFixture(test_ipv6_addr_idx__empty), + new_TestFixture(test_ipv6_addr_idx__wrong_netif), + new_TestFixture(test_ipv6_addr_idx__wrong_addr), + new_TestFixture(test_ipv6_addr_idx__success), + new_TestFixture(test_ipv6_addr_match__empty), + new_TestFixture(test_ipv6_addr_match__wrong_netif), + new_TestFixture(test_ipv6_addr_match__wrong_addr), + new_TestFixture(test_ipv6_addr_match__success18), + new_TestFixture(test_ipv6_addr_match__success23), + new_TestFixture(test_ipv6_addr_match__success64), + new_TestFixture(test_ipv6_addr_best_src__multicast_input), + new_TestFixture(test_ipv6_addr_best_src__other_subnet), + new_TestFixture(test_get_by_ipv6_addr__empty), + new_TestFixture(test_get_by_ipv6_addr__success), + new_TestFixture(test_get_by_prefix__empty), + new_TestFixture(test_get_by_prefix__success18), + new_TestFixture(test_get_by_prefix__success23), + new_TestFixture(test_get_by_prefix__success64), + new_TestFixture(test_ipv6_group_join__ENOMEM), + new_TestFixture(test_ipv6_group_join__success), + new_TestFixture(test_ipv6_group_join__readd_with_free_entry), + new_TestFixture(test_ipv6_group_leave__not_allocated), + new_TestFixture(test_ipv6_group_leave__success), + new_TestFixture(test_ipv6_group_idx__empty), + new_TestFixture(test_ipv6_group_idx__wrong_netif), + new_TestFixture(test_ipv6_group_idx__wrong_addr), + new_TestFixture(test_ipv6_group_idx__success), + new_TestFixture(test_ipv6_get_iid), + new_TestFixture(test_netapi_get__HOP_LIMIT), + new_TestFixture(test_netapi_get__IPV6_ADDR), + new_TestFixture(test_netapi_get__IPV6_ADDR_FLAGS), + new_TestFixture(test_netapi_get__IPV6_GROUP), + new_TestFixture(test_netapi_get__IPV6_IID), + new_TestFixture(test_netapi_get__MAX_PACKET_SIZE), + new_TestFixture(test_netapi_get__6LO_IPHC), + new_TestFixture(test_netapi_get__ADDRESS), + new_TestFixture(test_netapi_get__ADDRESS_LONG), + new_TestFixture(test_netapi_set__HOP_LIMIT), + new_TestFixture(test_netapi_set__IPV6_ADDR), + new_TestFixture(test_netapi_set__IPV6_ADDR_REMOVE), + new_TestFixture(test_netapi_set__IPV6_GROUP), + new_TestFixture(test_netapi_set__IPV6_GROUP_LEAVE), + new_TestFixture(test_netapi_set__MAX_PACKET_SIZE), + new_TestFixture(test_netapi_set__6LO_IPHC), + new_TestFixture(test_netapi_set__ADDRESS), + new_TestFixture(test_netapi_set__ADDRESS_LONG), + /* only add tests not involving output here */ + }; + EMB_UNIT_TESTCALLER(tests, _set_up, NULL, fixtures); + + return (Test *)&tests; +} + +int main(void) +{ + _tests_init(); + netdev_test_set_get_cb((netdev_test_t *)ethernet_dev, NETOPT_ADDRESS, + _get_netdev_address); + netdev_test_set_set_cb((netdev_test_t *)ethernet_dev, NETOPT_ADDRESS, + _set_netdev_address); + TESTS_START(); + TESTS_RUN(embunit_tests_gnrc_netif2()); + TESTS_END(); + /* add netapi send and receive tests here */ + test_netapi_send__raw_unicast_ethernet_packet(); + test_netapi_send__raw_broadcast_ethernet_packet(); + test_netapi_send__ipv6_unicast_ethernet_packet(); + test_netapi_send__ipv6_multicast_ethernet_packet(); + test_netapi_recv__empty_ethernet_payload(); + test_netapi_recv__raw_ethernet_payload(); + test_netapi_recv__ipv6_ethernet_payload(); + return 0; +} + +static inline int _mock_netif_send(gnrc_netif2_t *netif, gnrc_pktsnip_t *pkt) +{ + (void)netif; + (void)pkt; + return -1; +} + +static inline gnrc_pktsnip_t *_mock_netif_recv(gnrc_netif2_t * netif) +{ + (void)netif; + return NULL; +} + +static uint8_t ethernet_l2addr[] = ETHERNET_SRC; + +static int _get_netdev_address(netdev_t *dev, void *value, size_t max_len) +{ + if (dev == ethernet_dev) { + assert(max_len >= sizeof(ethernet_l2addr)); + memcpy(value, ethernet_l2addr, sizeof(ethernet_l2addr)); + return sizeof(ethernet_l2addr); + } + return -ENOTSUP; +} + +static int _set_netdev_address(netdev_t *dev, void *value, size_t value_len) +{ + if (dev == ethernet_dev) { + assert(value_len <= sizeof(ethernet_l2addr)); + memcpy(ethernet_l2addr, value, value_len); + return value_len; + } + return -ENOTSUP; +} diff --git a/tests/gnrc_netif2/tests/01-run.py b/tests/gnrc_netif2/tests/01-run.py new file mode 100755 index 0000000000000..584bf4465b763 --- /dev/null +++ b/tests/gnrc_netif2/tests/01-run.py @@ -0,0 +1,82 @@ +#!/usr/bin/env python3 + +# Copyright (C) 2016 Kaspar Schleiser +# Copyright (C) 2016 Takuo Yonezawa +# +# 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. + +import os +import sys + +sys.path.append(os.path.join(os.environ['RIOTBASE'], 'dist/tools/testrunner')) +import testrunner + +def testfunc(child): + # embUnit tests + child.expect(r"OK \(\d+ tests\)") + # output cross-checked hex data with WireShark -> "Import from Hex Dump..." + # test_netapi_send__raw_unicast_ethernet_packet + child.expect("Sending data from Ethernet device:") + child.expect("00000000 3E E6 B5 0F 19 23 3E E6 B5 22 FD 0A " + + "FF FF 41 42") + child.expect("00000010 43 44 45 46 47 00") + # test_netapi_send__raw_broadcast_ethernet_packet + child.expect("Sending data from Ethernet device:") + child.expect("00000000 FF FF FF FF FF FF 3E E6 B5 22 FD 0A " + + "FF FF 41 42") + child.expect("00000010 43 44 45 46 47 00") + # test_netapi_send__ipv6_unicast_ethernet_packet + child.expect("Sending data from Ethernet device:") + child.expect("00000000 3E E6 B5 0F 19 23 3E E6 B5 22 FD 0A 86 DD 60 00") + child.expect("00000010 00 00 00 08 3B 40 FE 80 00 00 00 00 00 00 3C E6") + child.expect("00000020 B5 FF FE 22 FD 0A FE 80 00 00 00 00 00 00 3C E6") + child.expect("00000030 B5 FF FE 0F 19 23 41 42 43 44 45 46 47 00") + # test_netapi_send__ipv6_multicast_ethernet_packet + child.expect("Sending data from Ethernet device:") + child.expect("00000000 33 33 00 00 00 01 3E E6 B5 22 FD 0A 86 DD 60 00") + child.expect("00000010 00 00 00 08 3B 40 FE 80 00 00 00 00 00 00 3C E6") + child.expect("00000020 B5 FF FE 22 FD 0A FF 02 00 00 00 00 00 00 00 00") + child.expect("00000030 00 00 00 00 00 01 41 42 43 44 45 46 47 00") + # test_netapi_recv__empty_ethernet_payload + child.expect("pktdump dumping Ethernet packet with empty payload") + child.expect("PKTDUMP: data received:") + child.expect(r"~~ SNIP 0 - size: 0 byte, type: NETTYPE_UNDEF \(0\)") + child.expect(r"00000000~~ SNIP 1 - size: 20 byte, type: NETTYPE_NETIF \(-1\)") + child.expect(r"if_pid: \d+ rssi: 0 lqi: 0") + child.expect("flags: 0x0") + child.expect("src_l2addr: 3e:e6:b5:22:fd:0b") + child.expect("dst_l2addr: 3e:e6:b5:22:fd:0a") + child.expect("~~ PKT - 2 snips, total size: 20 byte") + # test_netapi_recv__raw_ethernet_payload + child.expect("pktdump dumping Ethernet packet with payload 12 34 45 56") + child.expect("PKTDUMP: data received:") + child.expect(r"~~ SNIP 0 - size: 4 byte, type: NETTYPE_UNDEF \(0\)") + child.expect("00000000 12 34 45 56") + child.expect(r"~~ SNIP 1 - size: 20 byte, type: NETTYPE_NETIF \(-1\)") + child.expect(r"if_pid: \d+ rssi: 0 lqi: 0") + child.expect("flags: 0x0") + child.expect("src_l2addr: 3e:e6:b5:22:fd:0b") + child.expect("dst_l2addr: 3e:e6:b5:22:fd:0a") + child.expect("~~ PKT - 2 snips, total size: 24 byte") + # test_netapi_recv__ipv6_ethernet_payload + child.expect("pktdump dumping IPv6 over Ethernet packet with payload 01") + child.expect("PKTDUMP: data received:") + # payload not dumped because not parsed yet, but header looks okay, so let's + # assume the payload is as well + child.expect(r"~~ SNIP 0 - size: 41 byte, type: NETTYPE_IPV6 \(2\)") + child.expect(r"traffic class: 0x00 \(ECN: 0x0, DSCP: 0x00\)") + child.expect("flow label: 0x00000") + child.expect("length: 1 next header: 59 hop limit: 64") + child.expect("source address: fe80::3fe6:b5ff:fe22:fd0a") + child.expect("destination address: fe80::3fe6:b5ff:fe22:fd0b") + child.expect(r"~~ SNIP 1 - size: 20 byte, type: NETTYPE_NETIF \(-1\)") + child.expect(r"if_pid: \d+ rssi: 0 lqi: 0") + child.expect("flags: 0x0") + child.expect("src_l2addr: 3e:e6:b5:22:fd:0b") + child.expect("dst_l2addr: 3e:e6:b5:22:fd:0a") + child.expect("~~ PKT - 2 snips, total size: 61 byte") + +if __name__ == "__main__": + sys.exit(testrunner.run(testfunc, timeout=1, traceback=True)) From e9240fb50ca7cfb1309164c900d455e785bdb387 Mon Sep 17 00:00:00 2001 From: Martine Lenders Date: Mon, 24 Jul 2017 16:46:30 +0200 Subject: [PATCH 06/31] fixup! gnrc_netif2: Introduction of a new GNRC network interface API --- sys/include/net/gnrc/netif2.h | 10 ++++++++++ sys/include/net/gnrc/netif2/internal.h | 10 ---------- sys/net/gnrc/netif2/gnrc_netif2.c | 11 ++++++----- 3 files changed, 16 insertions(+), 15 deletions(-) diff --git a/sys/include/net/gnrc/netif2.h b/sys/include/net/gnrc/netif2.h index f51a34a83208c..84f0bd3e5a4e6 100644 --- a/sys/include/net/gnrc/netif2.h +++ b/sys/include/net/gnrc/netif2.h @@ -630,6 +630,16 @@ unsigned gnrc_netif2_numof(void); */ gnrc_netif2_t *gnrc_netif2_iter(const gnrc_netif2_t *prev); +/** + * @brief Get network interface by PID + * + * @param[in] pid A PID of a network interface. + * + * @return The network interface on success. + * @return NULL, if no network interface with PID exists. + */ +gnrc_netif2_t *gnrc_netif2_get_by_pid(kernel_pid_t pid); + /** * @brief Default operation for gnrc_netif2_ops_t::get() * diff --git a/sys/include/net/gnrc/netif2/internal.h b/sys/include/net/gnrc/netif2/internal.h index 9c256ad75b35c..952cc2fa492a1 100644 --- a/sys/include/net/gnrc/netif2/internal.h +++ b/sys/include/net/gnrc/netif2/internal.h @@ -60,16 +60,6 @@ static inline void gnrc_netif2_release(gnrc_netif2_t *netif) } } -/** - * @brief Get network interface by PID - * - * @param[in] pid A PID of a network interface. - * - * @return The network interface on success. - * @return NULL, if no network interface with PID exists. - */ -gnrc_netif2_t *gnrc_netif2_get_by_pid(kernel_pid_t pid); - #if defined(MODULE_GNRC_IPV6) || DOXYGEN /** * @brief Adds an IPv6 address to the interface diff --git a/sys/net/gnrc/netif2/gnrc_netif2.c b/sys/net/gnrc/netif2/gnrc_netif2.c index 846be309b09a3..fc8c46091cf4f 100644 --- a/sys/net/gnrc/netif2/gnrc_netif2.c +++ b/sys/net/gnrc/netif2/gnrc_netif2.c @@ -102,18 +102,19 @@ int gnrc_netif2_get_from_netdev(gnrc_netif2_t *netif, gnrc_netapi_opt_t *opt) case NETOPT_STATS: assert(opt->data_len == sizeof(netstats_t)); switch ((int16_t)opt->context) { - case GNRC_NETTYPE_NETIF: - case GNRC_NETTYPE_UNDEF: - /* take from device */ - break; #if defined(MODULE_NETSTATS_IPV6) && defined(MODULE_GNRC_IPV6) - case GNRC_NETTYPE_IPV6: + case NETSTATS_IPV6: memcpy(opt->data, &netif->ipv6_stats, sizeof(netif->ipv6_stats)); res = sizeof(netif->ipv6_stats); break; #endif + case NETSTATS_ALL: + /* doesn't make sense */ + res = -EINVAL; + break; default: + /* take from device */ break; } #ifdef MODULE_GNRC_IPV6 From f02e8a21859378d13a4d839956d835988ad6ee52 Mon Sep 17 00:00:00 2001 From: Martine Lenders Date: Mon, 24 Jul 2017 22:07:00 +0200 Subject: [PATCH 07/31] fixup! gnrc_netif2: Introduction of a new GNRC network interface API --- sys/net/gnrc/netif2/gnrc_netif2.c | 15 +++++++++++---- 1 file changed, 11 insertions(+), 4 deletions(-) diff --git a/sys/net/gnrc/netif2/gnrc_netif2.c b/sys/net/gnrc/netif2/gnrc_netif2.c index fc8c46091cf4f..09b04adfe0b25 100644 --- a/sys/net/gnrc/netif2/gnrc_netif2.c +++ b/sys/net/gnrc/netif2/gnrc_netif2.c @@ -100,13 +100,13 @@ int gnrc_netif2_get_from_netdev(gnrc_netif2_t *netif, gnrc_netapi_opt_t *opt) res = sizeof(uint8_t); break; case NETOPT_STATS: - assert(opt->data_len == sizeof(netstats_t)); + /* XXX discussed this with Oleg, it's supposed to be a pointer */ + assert(opt->data_len == sizeof(netstats_t *)); switch ((int16_t)opt->context) { #if defined(MODULE_NETSTATS_IPV6) && defined(MODULE_GNRC_IPV6) case NETSTATS_IPV6: - memcpy(opt->data, &netif->ipv6_stats, - sizeof(netif->ipv6_stats)); - res = sizeof(netif->ipv6_stats); + *((netstats_t **)opt->data) = &netif->ipv6_stats; + res = sizeof(&netif->ipv6_stats); break; #endif case NETSTATS_ALL: @@ -117,6 +117,7 @@ int gnrc_netif2_get_from_netdev(gnrc_netif2_t *netif, gnrc_netapi_opt_t *opt) /* take from device */ break; } + break; #ifdef MODULE_GNRC_IPV6 case NETOPT_IPV6_ADDR: { assert(opt->data_len >= sizeof(ipv6_addr_t)); @@ -973,6 +974,7 @@ static void _init_from_device(gnrc_netif2_t *netif) #ifdef MODULE_GNRC_SIXLOWPAN_IPHC netif->flags |= GNRC_NETIF2_FLAGS_6LO_HC; #endif +#ifdef MODULE_GNRC_IPV6 res = dev->driver->get(dev, NETOPT_MAX_PACKET_SIZE, &tmp, sizeof(tmp)); assert(res == sizeof(tmp)); #ifdef MODULE_GNRC_SIXLOWPAN_FRAG @@ -980,18 +982,23 @@ static void _init_from_device(gnrc_netif2_t *netif) netif->max_frag_size = tmp; #else netif->ipv6_mtu = tmp; +#endif #endif break; #endif /* MODULE_NETDEV_IEEE802154 */ #ifdef MODULE_NETDEV_ETH case NETDEV_TYPE_ETHERNET: +#ifdef MODULE_GNRC_IPV6 netif->ipv6_mtu = ETHERNET_DATA_LEN; +#endif break; #endif default: res = dev->driver->get(dev, NETOPT_MAX_PACKET_SIZE, &tmp, sizeof(tmp)); assert(res == sizeof(tmp)); +#ifdef MODULE_GNRC_IPV6 netif->ipv6_mtu = tmp; +#endif } _update_l2addr_from_dev(netif); } From 591ad2f8973817393c05c9f3d57ccbf884c0dc69 Mon Sep 17 00:00:00 2001 From: Martine Lenders Date: Tue, 25 Jul 2017 11:31:12 +0200 Subject: [PATCH 08/31] fixup! gnrc_netif2: Introduction of a new GNRC network interface API --- sys/include/net/gnrc/netif2.h | 38 ++++++++++++++ sys/net/gnrc/netif2/gnrc_netif2.c | 87 +++++++++++++++++++++++++++++++ 2 files changed, 125 insertions(+) diff --git a/sys/include/net/gnrc/netif2.h b/sys/include/net/gnrc/netif2.h index 84f0bd3e5a4e6..cbfb408d26d63 100644 --- a/sys/include/net/gnrc/netif2.h +++ b/sys/include/net/gnrc/netif2.h @@ -667,6 +667,44 @@ int gnrc_netif2_get_from_netdev(gnrc_netif2_t *netif, gnrc_netapi_opt_t *opt); int gnrc_netif2_set_from_netdev(gnrc_netif2_t *netif, const gnrc_netapi_opt_t *opt); +/** + * @brief Converts a hardware address to a human readable string. + * + * @details The format will be like `xx:xx:xx:xx` where `xx` are the bytes + * of @p addr in hexadecimal representation. + * + * @pre `(out != NULL) && ((addr != NULL) || (addr_len == 0))` + * @pre @p out **MUST** have allocated at least 3 * @p addr_len bytes. + * + * @param[in] addr A hardware address. + * @param[in] addr_len Length of @p addr. + * @param[out] out A string to store the output in. Must at least have + * 3 * @p addr_len bytes allocated. + * + * @return @p out. + */ +char *gnrc_netif2_addr_to_str(const uint8_t *addr, size_t addr_len, char *out); + +/** + * @brief Parses a string of colon-separated hexadecimals to a hardware + * address. + * + * @details The input format must be like `xx:xx:xx:xx` where `xx` will be the + * bytes of @p addr in hexadecimal representation. + * + * @pre `(out != NULL)` + * @pre @p out **MUST** have allocated at least + * @ref GNRC_NETIF2_L2ADDR_MAXLEN bytes. + * + * @param[in] str A string of colon-separated hexadecimals. + * @param[out] out The resulting hardware address. Must at least have + * @ref GNRC_NETIF2_L2ADDR_MAXLEN bytes allocated. + * + * @return Actual length of @p out on success. + * @return 0, on failure. + */ +size_t gnrc_netif2_addr_from_str(const char *str, uint8_t *out); + #ifdef __cplusplus } #endif diff --git a/sys/net/gnrc/netif2/gnrc_netif2.c b/sys/net/gnrc/netif2/gnrc_netif2.c index 09b04adfe0b25..e779e4a6da681 100644 --- a/sys/net/gnrc/netif2/gnrc_netif2.c +++ b/sys/net/gnrc/netif2/gnrc_netif2.c @@ -11,6 +11,7 @@ * * @file * @author Martine Lenders + * @author René Kijewski * @author Oliver Hahm */ @@ -339,6 +340,92 @@ gnrc_netif2_t *gnrc_netif2_get_by_pid(kernel_pid_t pid) return NULL; } +static inline char _half_byte_to_char(uint8_t half_byte) +{ + return (half_byte < 10) ? ('0' + half_byte) : ('a' + (half_byte - 10)); +} + +char *gnrc_netif2_addr_to_str(const uint8_t *addr, size_t addr_len, char *out) +{ + char *res = out; + + assert((out != NULL) && ((addr != NULL) || (addr_len == 0U))); + out[0] = '\0'; + for (size_t i = 0; i < addr_len; i++) { + *(out++) = _half_byte_to_char(*(addr) >> 4); + *(out++) = _half_byte_to_char(*(addr++) & 0xf); + *(out++) = (i == (addr_len - 1)) ? '\0' : ':'; + } + return res; +} + +static inline int _dehex(char c, int default_) +{ + if ('0' <= c && c <= '9') { + return c - '0'; + } + else if ('A' <= c && c <= 'F') { + return c - 'A' + 10; + } + else if ('a' <= c && c <= 'f') { + return c - 'a' + 10; + } + else { + return default_; + } +} + +size_t gnrc_netif2_addr_from_str(const char *str, uint8_t *out) +{ + /* Walk over str from the end. */ + /* Take two chars a time as one hex value (%hhx). */ + /* Leading zeros can be omitted. */ + /* Every non-hexadimal character is a delimiter. */ + /* Leading, tailing and adjacent delimiters are forbidden. */ + const char *end_str = str; + uint8_t *out_end = out; + size_t count = 0; + int assert_cell = 1; + + assert(out != NULL); + if ((str == NULL) && (str[0] == 0)) { + return 0; + } + /* find end of string */ + while (end_str[1]) { + ++end_str; + } + while (end_str >= str) { + int a = 0, b = _dehex(*end_str--, -1); + + if (b < 0) { + if (assert_cell) { + return 0; + } + else { + assert_cell = 1; + continue; + } + } + assert_cell = 0; + if (end_str >= str) { + a = _dehex(*end_str--, 0); + } + count++; + *out_end++ = (a << 4) | b; + } + if (assert_cell) { + return 0; + } + /* out is reversed */ + while (out < --out_end) { + uint8_t tmp = *out_end; + *out_end = *out; + *out++ = tmp; + } + return count; +} + #ifdef MODULE_GNRC_IPV6 static inline bool _addr_anycast(const gnrc_netif2_t *netif, unsigned idx); static int _addr_idx(const gnrc_netif2_t *netif, const ipv6_addr_t *addr); From 5a1559b6d035139ed12616d0d6e03fb88076b7d1 Mon Sep 17 00:00:00 2001 From: Martine Lenders Date: Tue, 25 Jul 2017 11:31:19 +0200 Subject: [PATCH 09/31] fixup! tests: add tests for gnrc_netif2 --- tests/gnrc_netif2/main.c | 31 +++++++++++++++++++++++++++++++ 1 file changed, 31 insertions(+) diff --git a/tests/gnrc_netif2/main.c b/tests/gnrc_netif2/main.c index d34f5c6785a33..3131ac69067fa 100644 --- a/tests/gnrc_netif2/main.c +++ b/tests/gnrc_netif2/main.c @@ -176,6 +176,35 @@ static void test_get_by_pid(void) } } +static void test_addr_to_str(void) +{ + static const uint8_t ethernet_l2addr[] = ETHERNET_SRC; + static const uint8_t netif0_l2addr[] = NETIF0_SRC; + char out[sizeof(netif0_l2addr) * 3]; + + TEST_ASSERT(out == gnrc_netif2_addr_to_str(NULL, 0, out)); + TEST_ASSERT_EQUAL_STRING("", &out[0]); + TEST_ASSERT(out == gnrc_netif2_addr_to_str(ethernet_l2addr, + sizeof(ethernet_l2addr), out)); + TEST_ASSERT_EQUAL_STRING("3e:e6:b5:22:fd:0a", &out[0]); + TEST_ASSERT(out == gnrc_netif2_addr_to_str(netif0_l2addr, + sizeof(netif0_l2addr), + out)); + TEST_ASSERT_EQUAL_STRING("3e:e7:b5:0f:19:22:fd:0a", &out[0]); +} + +static void test_addr_from_str(void) +{ + static const uint8_t ethernet_l2addr[] = ETHERNET_SRC; + uint8_t out[GNRC_NETIF2_L2ADDR_MAXLEN]; + + TEST_ASSERT_EQUAL_INT(0, gnrc_netif2_addr_from_str("", out)); + TEST_ASSERT_EQUAL_INT(sizeof(ethernet_l2addr), + gnrc_netif2_addr_from_str("3e:e6:b5:22:fd:0a", out)); + TEST_ASSERT_EQUAL_INT(0, memcmp(ethernet_l2addr, out, + sizeof(ethernet_l2addr))); +} + static void test_ipv6_addr_add__ENOMEM(void) { ipv6_addr_t addr = { .u8 = NETIF0_IPV6_G }; @@ -925,6 +954,8 @@ static Test *embunit_tests_gnrc_netif2(void) EMB_UNIT_TESTFIXTURES(fixtures) { new_TestFixture(test_creation), new_TestFixture(test_get_by_pid), + new_TestFixture(test_addr_to_str), + new_TestFixture(test_addr_from_str), new_TestFixture(test_ipv6_addr_add__ENOMEM), new_TestFixture(test_ipv6_addr_add__success), new_TestFixture(test_ipv6_addr_add__readd_with_free_entry), From 13a1b375a3e53818e23ab040e7ca551697f7f71b Mon Sep 17 00:00:00 2001 From: Martine Lenders Date: Tue, 25 Jul 2017 19:58:12 +0200 Subject: [PATCH 10/31] fixup! gnrc_netif2: Introduction of a new GNRC network interface API --- sys/net/gnrc/netif2/gnrc_netif2.c | 16 ++++++++++------ 1 file changed, 10 insertions(+), 6 deletions(-) diff --git a/sys/net/gnrc/netif2/gnrc_netif2.c b/sys/net/gnrc/netif2/gnrc_netif2.c index e779e4a6da681..afd3c4a32d991 100644 --- a/sys/net/gnrc/netif2/gnrc_netif2.c +++ b/sys/net/gnrc/netif2/gnrc_netif2.c @@ -17,6 +17,7 @@ #include "bitfield.h" #include "net/ethernet.h" +#include "net/ipv6.h" #include "net/gnrc.h" #include "log.h" #include "sched.h" @@ -1024,12 +1025,15 @@ static void _update_l2addr_from_dev(gnrc_netif2_t *netif) switch (netif->device_type) { #ifdef MODULE_NETDEV_IEEE802154 - case NETDEV_TYPE_IEEE802154: - res = dev->driver->get(dev, NETOPT_SRC_LEN, &tmp, sizeof(tmp)); - assert(res == sizeof(tmp)); - netif->l2addr_len = (uint8_t)tmp; - if (tmp == IEEE802154_LONG_ADDRESS_LEN) { - opt = NETOPT_ADDRESS_LONG; + case NETDEV_TYPE_IEEE802154: { + uint16_t tmp; + + res = dev->driver->get(dev, NETOPT_SRC_LEN, &tmp, sizeof(tmp)); + assert(res == sizeof(tmp)); + netif->l2addr_len = (uint8_t)tmp; + if (tmp == IEEE802154_LONG_ADDRESS_LEN) { + opt = NETOPT_ADDRESS_LONG; + } } break; #endif From 60ca751c693ae6febb2d3061b771e1e4599a0873 Mon Sep 17 00:00:00 2001 From: Martine Lenders Date: Tue, 25 Jul 2017 19:58:27 +0200 Subject: [PATCH 11/31] fixup! tests: add tests for gnrc_netif2 --- tests/gnrc_netif2/main.c | 49 +++------------------------------------- 1 file changed, 3 insertions(+), 46 deletions(-) diff --git a/tests/gnrc_netif2/main.c b/tests/gnrc_netif2/main.c index 3131ac69067fa..df867bd09b0ac 100644 --- a/tests/gnrc_netif2/main.c +++ b/tests/gnrc_netif2/main.c @@ -36,50 +36,7 @@ #include "utlist.h" #include "xtimer.h" -#define GP1 (0x20U) -#define GP2 (0x01U) -#define GP3 (0x0dU) -#define GP4 (0xb8U) -#define GP5 (0x00U) -#define GP6 (0x00U) -#define GP7 (0x5aU) -#define GP8 (0x1aU) - -#define LP1 (0xfeU) -#define LP2 (0x80U) -#define LP3 (0x00U) -#define LP4 (0x00U) -#define LP5 (0x00U) -#define LP6 (0x00U) -#define LP7 (0x00U) -#define LP8 (0x00U) - -#define LA1 (0x3eU) -#define LA2 (0xe6U) -#define LA3 (0xb5U) -#define LA4 (0x0fU) -#define LA5 (0x19U) -#define LA6 (0x22U) -#define LA7 (0xfdU) -#define LA8 (0x0aU) - -#define ETHERNET_SRC { LA1, LA2, LA3, LA6, LA7, LA8 } -#define ETHERNET_IPV6_LL { LP1, LP2, LP3, LP4, LP5, LP6, LP7, LP8, \ - LA1 ^ 0x2, LA2, LA3, 0xff, 0xfe, LA6, LA7, LA8 } -#define ETHERNET_IPV6_G { GP1, GP2, GP3, GP4, GP5, GP6, GP7, GP8, \ - LA1 ^ 0x2, LA2, LA3, 0xff, 0xfe, LA6, LA7, LA8 } -#define ETHERNET_STACKSIZE (THREAD_STACKSIZE_MAIN) -#define NETIF0_SRC { LA1, LA2 + 1, LA3, LA4, LA5, LA6, LA7, LA8 } -#define NETIF0_IPV6_LL { LP1, LP2, LP3, LP4, LP5, LP6, LP7, LP8, \ - LA1 ^ 0x2, LA2 + 1, LA3, LA4, LA5, LA6, LA7, LA8 } -#define NETIF0_IPV6_G { GP1, GP2, GP3, GP4, GP5, GP6, GP7, GP8, \ - LA1 ^ 0x2, LA2 + 1, LA3, LA4, LA5, LA6, LA7, LA8 } -#define GLOBAL_PFX18 { GP1, GP2, GP3 ^ 0x3f, GP4, GP5, GP6, GP7, GP8, \ - LA1 ^ 0x2, LA2, LA3, LA4, LA5, LA6, LA7, LA8 } -#define GLOBAL_PFX23 { GP1, GP2, GP3 ^ 0x1, GP4, GP5, GP6, GP7, GP8, \ - LA1 ^ 0x2, LA2, LA3, LA4, LA5, LA6, LA7, LA8 } -#define GLOBAL_PFX64 { GP1, GP2, GP3, GP4, GP5, GP6, GP7, GP8, \ - LA1 ^ 0x82, LA2, LA3, LA4, LA5, LA6, LA7, LA8 } +#define ETHERNET_STACKSIZE (THREAD_STACKSIZE_MAIN) static gnrc_netif2_t *ethernet_netif = NULL; static gnrc_netif2_t *netifs[DEFAULT_DEVS_NUMOF]; @@ -158,8 +115,8 @@ static void test_creation(void) TEST_ASSERT_EQUAL_INT(NETDEV_TYPE_UNKNOWN, netifs[i]->device_type); TEST_ASSERT(netifs[i]->pid > KERNEL_PID_UNDEF); TEST_ASSERT_NOT_NULL(sched_threads[netifs[i]->pid]->msg_array); - TEST_ASSERT_EQUAL_INT(i + 2, gnrc_netif2_numof()); - for (unsigned j = 0; j < (i + 2); j++) { + TEST_ASSERT_EQUAL_INT(i + SPECIAL_DEVS + 1, gnrc_netif2_numof()); + for (unsigned j = 0; j < (i + SPECIAL_DEVS + 1); j++) { TEST_ASSERT_NOT_NULL((ptr = gnrc_netif2_iter(ptr))); } TEST_ASSERT_NULL((ptr = gnrc_netif2_iter(ptr))); From d9d9bf46b7c46b4a23b82e57b1f8d8431e47e488 Mon Sep 17 00:00:00 2001 From: Martine Lenders Date: Wed, 26 Jul 2017 14:00:43 +0200 Subject: [PATCH 12/31] fixup! gnrc_netif2: Introduction of a new GNRC network interface API --- sys/include/net/gnrc/netif2.h | 5 ----- 1 file changed, 5 deletions(-) diff --git a/sys/include/net/gnrc/netif2.h b/sys/include/net/gnrc/netif2.h index cbfb408d26d63..5cea9d3cc4228 100644 --- a/sys/include/net/gnrc/netif2.h +++ b/sys/include/net/gnrc/netif2.h @@ -588,11 +588,6 @@ struct gnrc_netif2_ops { void (*msg_handler)(gnrc_netif2_t *netif, msg_t *msg); }; -/** - * @brief Deprecated address state (still valid, but not preferred) - */ -#define GNRC_NETIF2_IPV6_ADDRS_FLAGS_STATE_DEPRECATED (0x02U) - /** * @brief Creates a network interface * From c47a177318ed7a57f9cbe96c9f9dceec9dec0737 Mon Sep 17 00:00:00 2001 From: Martine Lenders Date: Thu, 27 Jul 2017 15:28:07 +0200 Subject: [PATCH 13/31] fixup! gnrc_netif2: Introduction of a new GNRC network interface API --- sys/include/net/gnrc/netif2.h | 2 +- sys/net/gnrc/netif2/gnrc_netif2.c | 2 +- tests/gnrc_netif2/Makefile | 2 -- 3 files changed, 2 insertions(+), 4 deletions(-) diff --git a/sys/include/net/gnrc/netif2.h b/sys/include/net/gnrc/netif2.h index 5cea9d3cc4228..63e289cfc8389 100644 --- a/sys/include/net/gnrc/netif2.h +++ b/sys/include/net/gnrc/netif2.h @@ -485,7 +485,7 @@ typedef struct { */ uint8_t l2addr_len; #endif -#if defined(MODULE_GNRC_SIXLOWPAN_FRAG) || DOXYGEN +#if defined(MODULE_GNRC_SIXLOWPAN) || DOXYGEN /** * @brief Maximum fragment size for 6LoWPAN fragmentation. * diff --git a/sys/net/gnrc/netif2/gnrc_netif2.c b/sys/net/gnrc/netif2/gnrc_netif2.c index afd3c4a32d991..54a7c103e0190 100644 --- a/sys/net/gnrc/netif2/gnrc_netif2.c +++ b/sys/net/gnrc/netif2/gnrc_netif2.c @@ -1068,7 +1068,7 @@ static void _init_from_device(gnrc_netif2_t *netif) #ifdef MODULE_GNRC_IPV6 res = dev->driver->get(dev, NETOPT_MAX_PACKET_SIZE, &tmp, sizeof(tmp)); assert(res == sizeof(tmp)); -#ifdef MODULE_GNRC_SIXLOWPAN_FRAG +#ifdef MODULE_GNRC_SIXLOWPAN netif->ipv6_mtu = IPV6_MIN_MTU; netif->max_frag_size = tmp; #else diff --git a/tests/gnrc_netif2/Makefile b/tests/gnrc_netif2/Makefile index f7bca268a8ead..fdae4203a1b14 100644 --- a/tests/gnrc_netif2/Makefile +++ b/tests/gnrc_netif2/Makefile @@ -7,8 +7,6 @@ BOARD_INSUFFICIENT_MEMORY := USEMODULE += embunit USEMODULE += gnrc_netif2 USEMODULE += gnrc_pktdump -USEMODULE += gnrc_sixlowpan_frag -USEMODULE += gnrc_sixlowpan_frag USEMODULE += gnrc_sixlowpan_iphc USEMODULE += gnrc_ipv6 USEMODULE += netdev_eth From 3072ef7111a74dbbfa0412eaf2af52804ef73237 Mon Sep 17 00:00:00 2001 From: Martine Lenders Date: Fri, 28 Jul 2017 14:20:46 +0200 Subject: [PATCH 14/31] fixup! gnrc_netif2: Introduction of a new GNRC network interface API Restructure headers a bit --- sys/include/net/gnrc/netif2.h | 439 ++-------------------------- sys/include/net/gnrc/netif2/conf.h | 121 ++++++++ sys/include/net/gnrc/netif2/flags.h | 127 ++++++++ sys/include/net/gnrc/netif2/ipv6.h | 234 +++++++++++++++ sys/include/net/gnrc/netif2/mac.h | 58 ++++ sys/net/gnrc/netif2/gnrc_netif2.c | 74 ++--- 6 files changed, 597 insertions(+), 456 deletions(-) create mode 100644 sys/include/net/gnrc/netif2/conf.h create mode 100644 sys/include/net/gnrc/netif2/flags.h create mode 100644 sys/include/net/gnrc/netif2/ipv6.h create mode 100644 sys/include/net/gnrc/netif2/mac.h diff --git a/sys/include/net/gnrc/netif2.h b/sys/include/net/gnrc/netif2.h index 63e289cfc8389..e8b3de40256f1 100644 --- a/sys/include/net/gnrc/netif2.h +++ b/sys/include/net/gnrc/netif2.h @@ -31,240 +31,26 @@ #include "kernel_types.h" #include "msg.h" #include "net/ieee802154.h" -#include "net/ipv6/addr.h" #include "net/ethernet/hdr.h" #include "net/gnrc/netapi.h" -#ifdef MODULE_GNRC_IPV6_NIB -#include "net/gnrc/ipv6/nib/conf.h" -#endif #include "net/gnrc/pkt.h" -#include "net/gnrc/mac/mac.h" +#ifdef MODULE_GNRC_SIXLOWPAN +#include "net/gnrc/netif2/6lo.h" +#endif +#include "net/gnrc/netif2/flags.h" +#ifdef MODULE_GNRC_IPV6 +#include "net/gnrc/netif2/ipv6.h" +#endif +#ifdef MODULE_GNRC_MAC +#include "net/gnrc/netif2/mac.h" +#endif #include "net/netdev.h" -#include "net/netstats.h" #include "rmutex.h" #ifdef __cplusplus extern "C" { #endif -/** - * @brief Maximum number of network interfaces - * - * @note Intentially not calling it `GNRC_NETIF2_NUMOF` to not require - * rewrites throughout the stack. - */ -#ifndef GNRC_NETIF_NUMOF -#define GNRC_NETIF_NUMOF (1) -#endif - -/** - * @brief Default priority for network interface threads - */ -#ifndef GNRC_NETIF2_PRIO -#define GNRC_NETIF2_PRIO (THREAD_PRIORITY_MAIN - 5) -#endif - -/** - * @brief Number of multicast addressed needed for @ref net_gnrc_rpl "RPL". - * - * @note Used for calculation of @ref GNRC_NETIF2_IPV6_GROUPS_NUMOF - */ -#ifdef MODULE_GNRC_RPL -#define GNRC_NETIF2_RPL_ADDR (1) -#else -#define GNRC_NETIF2_RPL_ADDR (0) -#endif - -/** - * @brief Number of multicast addresses needed for a @ref net_gnrc_ipv6 "IPv6" - * router - * - * @note Used for calculation of @ref GNRC_NETIF2_IPV6_GROUPS_NUMOF - */ -#ifdef MODULE_GNRC_IPV6_ROUTER -#define GNRC_NETIF2_IPV6_RTR_ADDR (1) -#else -#define GNRC_NETIF2_IPV6_RTR_ADDR (0) -#endif - -/** - * @brief Maximum number of unicast and anycast addresses per interface - * - * Default: 2 (link-local + corresponding global address) - */ -#ifndef GNRC_NETIF2_IPV6_ADDRS_NUMOF -#define GNRC_NETIF2_IPV6_ADDRS_NUMOF (2) -#endif - -/** - * @brief Maximum number of multicast groups per interface - * - * Default: 2 (all-nodes + solicited-nodes of link-local and global unicast - * address) + @ref GNRC_NETIF2_RPL_ADDR + @ref GNRC_NETIF2_IPV6_RTR_ADDR - */ -#ifndef GNRC_NETIF2_IPV6_GROUPS_NUMOF -#define GNRC_NETIF2_IPV6_GROUPS_NUMOF (2 + GNRC_NETIF2_RPL_ADDR + GNRC_NETIF2_IPV6_RTR_ADDR) -#endif - -/** - * @brief Maximum length of the link-layer address. - * - * The value for the maximum length of a link-layer address is dependent - * on the @ref drivers_netdev_api "netdev" adapters compiled in: - * - Setting it via `CFLAGS` has the most precedence. - * - The default is 8. - * - 1, if only @ref drivers_cc110x devices are compiled in. - * - @ref ETHERNET_ADDR_LEN, if additionally (or only) ethernet devices are - * compiled in. - * - @ref IEEE802154_LONG_ADDRESS_LEN, if additionally (or only) IEEE802.15.4 - * devices are compiled in. - * - * @note Implementers note: From longest to shortest extend, if new link-layer - * address types are included - */ -#ifndef GNRC_NETIF2_L2ADDR_MAXLEN -#if defined(MODULE_NETDEV_IEEE802154) || defined(MODULE_XBEE) -#define GNRC_NETIF2_L2ADDR_MAXLEN (IEEE802154_LONG_ADDRESS_LEN) -#elif MODULE_NETDEV_ETH -#define GNRC_NETIF2_L2ADDR_MAXLEN (ETHERNET_ADDR_LEN) -#elif MODULE_CC110X -#define GNRC_NETIF2_L2ADDR_MAXLEN (1U) -#else -#define GNRC_NETIF2_L2ADDR_MAXLEN (8U) -#endif -#endif - -#ifndef GNRC_NETIF2_DEFAULT_HL -#define GNRC_NETIF2_DEFAULT_HL (64U) /**< default hop limit */ -#endif - -/** - * @name Network interface flags - * @anchor net_gnrc_netif2_flags - * @{ - */ -/** - * @brief Network interface has link-layer address - * - * There are link-layers (e.g. SLIP) that do not have (nor require) link-layer - * addresses. This flag signifies this fact to upper layers by leaving it unset. - */ -#define GNRC_NETIF2_FLAGS_HAS_L2ADDR (0x00000001U) - -/** - * @brief Network interface is enabled for IPv6 forwarding - */ -#define GNRC_NETIF2_FLAGS_IPV6_FORWARDING (0x00000002U) - -/** - * @brief Network interface advertises itself as an IPv6 router - * (implies @ref GNRC_NETIF2_FLAGS_IPV6_FORWARDING to be set) - */ -#define GNRC_NETIF2_FLAGS_IPV6_RTR_ADV (0x00000004U) - -/** - * @brief This interface advertises its gnrc_netif2_t::mtu to other nodes - * (implies @ref GNRC_NETIF2_FLAGS_IPV6_RTR_ADV to be set) - */ -#define GNRC_NETIF2_FLAGS_IPV6_ADV_MTU (0x00000008U) - -/** - * @brief This interface advertises its gnrc_netif2_t::cur_hl to other nodes - * (implies @ref GNRC_NETIF2_FLAGS_IPV6_RTR_ADV to be set) - */ -#define GNRC_NETIF2_FLAGS_IPV6_ADV_CUR_HL (0x00000010U) - -/** - * @brief This interface advertises its reachable time to other nodes - * (implies @ref GNRC_NETIF2_FLAGS_IPV6_RTR_ADV to be set) - */ -#define GNRC_NETIF2_FLAGS_IPV6_ADV_REACH_TIME (0x00000020U) - -/** - * @brief This interface advertises its retransmission timer to other nodes - * (implies @ref GNRC_NETIF2_FLAGS_IPV6_RTR_ADV to be set) - */ -#define GNRC_NETIF2_FLAGS_IPV6_ADV_RETRANS_TIMER (0x00000040U) - -/** - * @brief This interface uses 6Lo header compression - * - * @see [RFC 6282](https://tools.ietf.org/html/rfc6282) - */ -#define GNRC_NETIF2_FLAGS_6LO_HC (0x00000080U) - -/** - * @brief This interface acts as a 6Lo border router to the LLN - */ -#define GNRC_NETIF2_FLAGS_6LO_ABR (0x00000100U) - -/** - * @brief This interface acts as a mesh-under node (route-over topology when - * unset) - */ -#define GNRC_NETIF2_FLAGS_6LO_MESH (0x00000200U) - -/** - * @brief Interface supports 6LoWPAN general header compression - * - * @attention GHC not implemented yet - * @see [RFC 7400, section 3.3](https://tools.ietf.org/html/rfc7400#section-3.3) - */ -#define GNRC_NETIF2_FLAGS_6LO_BACKBONE (0x00000400U) - -/** - * @brief Mask for @ref gnrc_mac_tx_feedback_t - */ -#define GNRC_NETIF2_FLAGS_MAC_TX_FEEDBACK_MASK (0x00006000U) - -/** - * @brief Flag to track if a transmission might have corrupted a received - * packet - */ -#define GNRC_NETIF2_FLAGS_MAC_RX_STARTED (0x00008000U) -/** @} */ - -/** - * @name IPv6 unicast and anycast address flags - * @anchor net_gnrc_netif2_ipv6_addrs_flags - * @{ - */ -/** - * @brief Mask for the address' state - */ -#define GNRC_NETIF2_IPV6_ADDRS_FLAGS_STATE_MASK (0x03U) - -/** - * @brief Tentative address state - */ -#define GNRC_NETIF2_IPV6_ADDRS_FLAGS_STATE_TENTATIVE (0x01U) - -/** - * @brief Deprecated address state (still valid, but not preferred) - */ -#define GNRC_NETIF2_IPV6_ADDRS_FLAGS_STATE_DEPRECATED (0x02U) - -/** - * @brief Valid address state - */ -#define GNRC_NETIF2_IPV6_ADDRS_FLAGS_STATE_VALID (0x03U) - -/** - * @brief Address is an anycast address - */ -#define GNRC_NETIF2_IPV6_ADDRS_FLAGS_ANYCAST (0x04U) -/** @} */ - -/** - * @brief Auto-address configuration modes - */ -enum { - GNRC_NETIF2_AAC_NONE = 0, /**< no configuration */ - GNRC_NETIF2_AAC_AUTO, /**< Use some automatic bootstrapping (e.g. SLAAC with IPv6) */ - GNRC_NETIF2_AAC_DHCP, /**< Use DHCP(v6) */ - /* extend if needed */ -}; - /** * @brief Operations to an interface */ @@ -276,38 +62,19 @@ typedef struct gnrc_netif2_ops gnrc_netif2_ops_t; typedef struct { const gnrc_netif2_ops_t *ops; /**< Operations of the network interface */ netdev_t *dev; /**< Network device of the network interface */ + rmutex_t mutex; /**< Mutex of the interface */ +#if defined(MODULE_GNRC_IPV6) || DOXYGEN + gnrc_netif2_ipv6_t ipv6; /**< IPv6 component */ +#endif #if defined(MODULE_GNRC_MAC) || DOXYGEN -#if ((GNRC_MAC_RX_QUEUE_SIZE != 0) || (GNRC_MAC_DISPATCH_BUFFER_SIZE != 0)) || DOXYGEN - /** - * @brief MAC internal object which stores reception parameters, queues, and - * state machines. - * - * @note Only available if @ref GNRC_MAC_RX_QUEUE_SIZE or - * @ref GNRC_MAC_DISPATCH_BUFFER_SIZE is greater than 0. - */ - gnrc_mac_rx_t rx; -#endif /* ((GNRC_MAC_RX_QUEUE_SIZE != 0) || (GNRC_MAC_DISPATCH_BUFFER_SIZE != 0)) || DOXYGEN */ - -#if ((GNRC_MAC_TX_QUEUE_SIZE != 0) || (GNRC_MAC_NEIGHBOR_COUNT != 0)) || DOXYGEN - /** - * @brief MAC internal object which stores transmission parameters, queues, and - * state machines. - * - * @note Only available if @ref GNRC_MAC_TX_QUEUE_SIZE or - * @ref GNRC_MAC_NEIGHBOR_COUNT is greater than 0. - */ - gnrc_mac_tx_t tx; -#endif /* ((GNRC_MAC_TX_QUEUE_SIZE != 0) || (GNRC_MAC_NEIGHBOR_COUNT == 0)) || DOXYGEN */ + gnrc_netif2_mac_t mac; /**< @ref gnrc_mac component */ #endif /* MODULE_GNRC_MAC */ -#ifdef MODULE_NETSTATS_IPV6 /** - * @brief IPv6 packet statistics + * @brief Flags for the interface * - * @note Only available with module `netstats_ipv6`. + * @see net_gnrc_netif2_flags */ - netstats_t ipv6_stats; -#endif - rmutex_t mutex; /**< Mutex of the interface */ + uint32_t flags; #if (GNRC_NETIF2_L2ADDR_MAXLEN > 0) /** * @brief The link-layer address currently used as the source address @@ -316,168 +83,7 @@ typedef struct { * @note Only available if @ref GNRC_NETIF2_L2ADDR_MAXLEN > 0 */ uint8_t l2addr[GNRC_NETIF2_L2ADDR_MAXLEN]; -#endif -#if defined(MODULE_GNRC_IPV6) || DOXYGEN - /** - * @brief Flags for gnrc_netif2_t::ipv6_addrs - * - * @see net_gnrc_netif2_ipv6_addrs_flags - * - * @note Only available with module @ref net_gnrc_ipv6 "gnrc_ipv6". - */ - uint8_t ipv6_addrs_flags[GNRC_NETIF2_IPV6_ADDRS_NUMOF]; - /** - * @brief IPv6 unicast and anycast addresses of the interface - * - * @note Only available with module @ref net_gnrc_ipv6 "gnrc_ipv6". - */ - ipv6_addr_t ipv6_addrs[GNRC_NETIF2_IPV6_ADDRS_NUMOF]; - - /** - * @brief IPv6 multicast groups of the interface - * - * @note Only available with module @ref net_gnrc_ipv6 "gnrc_ipv6". - */ - ipv6_addr_t ipv6_groups[GNRC_NETIF2_IPV6_GROUPS_NUMOF]; - -#if defined(MODULE_GNRC_IPV6_NIB) || DOXYGEN -#if GNRC_IPV6_NIB_CONF_ROUTER || DOXYGEN - /** - * @brief Route info callback - * - * This callback is called by the @ref net_gnrc_ipv6_nib "NIB" to inform - * the routing protocol about state changes, route usages, missing routes - * etc. - * - * @todo Define types (RRQ, RRN, NSC) in NIB - * - * @param[in] type Type of the route info. - * @param[in] ctx_addr Context address of the route info. - * @param[in] ctx Further context of the route info. - */ - int (*route_info_cb)(unsigned type, const ipv6_addr_t *ctx_addr, - const void *ctx); - /** - * @brief Event for @ref GNRC_IPV6_NIB_SND_MC_RA - * - * @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_ROUTER != 0 - */ - evtimer_msg_event_t snd_mc_ra; -#endif /* GNRC_IPV6_NIB_CONF_ROUTER */ -#if GNRC_IPV6_NIB_CONF_ARSM || DOXYGEN - /** - * @brief Event for @ref GNRC_IPV6_NIB_RECALC_REACH_TIME - * - * @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_ARSM != 0 - */ - evtimer_msg_event_t recalc_reach_time; -#endif /* GNRC_IPV6_NIB_CONF_ARSM */ - /** - * @brief Event for @ref GNRC_IPV6_NIB_SEARCH_RTR - * - * @note Only available with module @ref net_gnrc_ipv6 "gnrc_ipv6". - * and @ref net_gnrc_ipv6_nib "NIB" - */ - evtimer_msg_event_t search_rtr; - -#if GNRC_IPV6_NIB_CONF_ROUTER || DOXYGEN - /** - * @brief Timestamp in milliseconds of last unsolicited router - * advertisement - * - * @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_ROUTER != 0 - */ - uint32_t last_ra; -#endif /* GNRC_IPV6_NIB_CONF_ROUTER */ -#if GNRC_IPV6_NIB_CONF_ARSM || defined(DOXYGEN) - /** - * @brief Base for random reachable time calculation and advertised - * reachable time in ms (if @ref GNRC_NETIF2_FLAGS_IPV6_RTR_ADV is - * set) - * - * @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_ARSM != 0 - */ - uint32_t reach_time_base; - - /** - * @brief Reachable time (in ms) - * - * @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_ARSM != 0 - */ - uint32_t reach_time; -#endif /* GNRC_IPV6_NIB_CONF_ARSM */ - /** - * @brief Retransmission time and advertised retransmission time (in ms) - * - * @note Only available with module @ref net_gnrc_ipv6 "gnrc_ipv6" and - * @ref net_gnrc_ipv6_nib "NIB" - */ - uint32_t retrans_time; -#endif /* MODULE_GNRC_IPV6_NIB */ - - /** - * @brief Maximum transition unit (MTU) for IPv6 packets - * - * @note Only available with module @ref net_gnrc_ipv6 "gnrc_ipv6". - */ - uint16_t ipv6_mtu; -#if defined(MODULE_GNRC_IPV6_NIB) || DOXYGEN -#if GNRC_IPV6_NIB_CONF_ROUTER || DOXYGEN - /** - * @brief number of unsolicited router advertisements sent - * - * This only counts up to the first @ref NDP_MAX_INIT_RA_NUMOF on interface - * initialization. The last @ref NDP_MAX_FIN_RA_NUMOF of an advertising - * interface are counted from UINT8_MAX - @ref NDP_MAX_FIN_RA_NUMOF + 1. - * - * @note Only available with module @ref net_gnrc_ipv6 "gnrc_ipv6". - * and @ref net_gnrc_ipv6_nib "NIB" and if - * @ref GNRC_IPV6_NIB_CONF_ROUTER != 0 - */ - uint8_t ra_sent; -#endif - /** - * @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" - */ - uint8_t rs_sent; - /** - * @brief number of unsolicited neighbor advertisements scheduled - * - * @note Only available with module @ref net_gnrc_ipv6 "gnrc_ipv6" and - * @ref net_gnrc_ipv6_nib "NIB" - */ - uint8_t na_sent; -#endif - - /** - * @brief IPv6 auto-address configuration mode - * - * @note Only available with module @ref net_gnrc_ipv6 "gnrc_ipv6" - */ - uint8_t ipv6_aac_mode; -#endif /* gnrc_ipv6 */ - /** - * @brief Flags for the interface - * - * @see net_gnrc_netif2_flags - */ - uint16_t flags; - kernel_pid_t pid; /**< PID of the network interface's thread */ -#if (GNRC_NETIF2_L2ADDR_MAXLEN > 0) /** * @brief Length in bytes of gnrc_netif2_t::l2addr * @@ -486,16 +92,11 @@ typedef struct { uint8_t l2addr_len; #endif #if defined(MODULE_GNRC_SIXLOWPAN) || DOXYGEN - /** - * @brief Maximum fragment size for 6LoWPAN fragmentation. - * - * @note Only available with module - * @ref net_gnrc_sixlowpan_frag "gnrc_sixlowpan_frag". - */ - uint8_t max_frag_size; + gnrc_netif2_6lo_t sixlo; /**< 6Lo component */ #endif uint8_t cur_hl; /**< Current hop-limit for out-going packets */ uint8_t device_type; /**< Device type */ + kernel_pid_t pid; /**< PID of the network interface's thread */ } gnrc_netif2_t; /** diff --git a/sys/include/net/gnrc/netif2/conf.h b/sys/include/net/gnrc/netif2/conf.h new file mode 100644 index 0000000000000..b7d8b8eeeceff --- /dev/null +++ b/sys/include/net/gnrc/netif2/conf.h @@ -0,0 +1,121 @@ +/* + * 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_netif2 + * @{ + * + * @file + * @brief Configuration macros for @ref net_gnrc_netif2 + * + * @author Martine Lenders + */ +#ifndef NET_GNRC_NETIF2_CONF_H +#define NET_GNRC_NETIF2_CONF_H + +#ifdef __cplusplus +extern "C" { +#endif + +/** + * @brief Maximum number of network interfaces + * + * @note Intentially not calling it `GNRC_NETIF2_NUMOF` to not require + * rewrites throughout the stack. + */ +#ifndef GNRC_NETIF_NUMOF +#define GNRC_NETIF_NUMOF (1) +#endif + +/** + * @brief Default priority for network interface threads + */ +#ifndef GNRC_NETIF2_PRIO +#define GNRC_NETIF2_PRIO (THREAD_PRIORITY_MAIN - 5) +#endif + +/** + * @brief Number of multicast addressed needed for @ref net_gnrc_rpl "RPL". + * + * @note Used for calculation of @ref GNRC_NETIF2_IPV6_GROUPS_NUMOF + */ +#ifdef MODULE_GNRC_RPL +#define GNRC_NETIF2_RPL_ADDR (1) +#else +#define GNRC_NETIF2_RPL_ADDR (0) +#endif + +/** + * @brief Number of multicast addresses needed for a @ref net_gnrc_ipv6 "IPv6" + * router + * + * @note Used for calculation of @ref GNRC_NETIF2_IPV6_GROUPS_NUMOF + */ +#ifdef MODULE_GNRC_IPV6_ROUTER +#define GNRC_NETIF2_IPV6_RTR_ADDR (1) +#else +#define GNRC_NETIF2_IPV6_RTR_ADDR (0) +#endif + +/** + * @brief Maximum number of unicast and anycast addresses per interface + * + * Default: 2 (link-local + corresponding global address) + */ +#ifndef GNRC_NETIF2_IPV6_ADDRS_NUMOF +#define GNRC_NETIF2_IPV6_ADDRS_NUMOF (2) +#endif + +/** + * @brief Maximum number of multicast groups per interface + * + * Default: 2 (all-nodes + solicited-nodes of link-local and global unicast + * address) + @ref GNRC_NETIF2_RPL_ADDR + @ref GNRC_NETIF2_IPV6_RTR_ADDR + */ +#ifndef GNRC_NETIF2_IPV6_GROUPS_NUMOF +#define GNRC_NETIF2_IPV6_GROUPS_NUMOF (2 + GNRC_NETIF2_RPL_ADDR + GNRC_NETIF2_IPV6_RTR_ADDR) +#endif + +/** + * @brief Maximum length of the link-layer address. + * + * The value for the maximum length of a link-layer address is dependent + * on the @ref drivers_netdev_api "netdev" adapters compiled in: + * - Setting it via `CFLAGS` has the most precedence. + * - The default is 8. + * - 1, if only @ref drivers_cc110x devices are compiled in. + * - @ref ETHERNET_ADDR_LEN, if additionally (or only) ethernet devices are + * compiled in. + * - @ref IEEE802154_LONG_ADDRESS_LEN, if additionally (or only) IEEE802.15.4 + * devices are compiled in. + * + * @note Implementers note: From longest to shortest extend, if new link-layer + * address types are included + */ +#ifndef GNRC_NETIF2_L2ADDR_MAXLEN +#if defined(MODULE_NETDEV_IEEE802154) || defined(MODULE_XBEE) +#define GNRC_NETIF2_L2ADDR_MAXLEN (IEEE802154_LONG_ADDRESS_LEN) +#elif MODULE_NETDEV_ETH +#define GNRC_NETIF2_L2ADDR_MAXLEN (ETHERNET_ADDR_LEN) +#elif MODULE_CC110X +#define GNRC_NETIF2_L2ADDR_MAXLEN (1U) +#else +#define GNRC_NETIF2_L2ADDR_MAXLEN (8U) +#endif +#endif + +#ifndef GNRC_NETIF2_DEFAULT_HL +#define GNRC_NETIF2_DEFAULT_HL (64U) /**< default hop limit */ +#endif + +#ifdef __cplusplus +} +#endif + +#endif /* NET_GNRC_NETIF2_CONF_H */ +/** @} */ diff --git a/sys/include/net/gnrc/netif2/flags.h b/sys/include/net/gnrc/netif2/flags.h new file mode 100644 index 0000000000000..8ee6799e3e6be --- /dev/null +++ b/sys/include/net/gnrc/netif2/flags.h @@ -0,0 +1,127 @@ +/* + * 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_netif2 + * @{ + * + * @file + * @brief Flag definitions for @ref net_gnrc_netif2 + * + * @author Martine Lenders + */ +#ifndef NET_GNRC_NETIF2_FLAGS_H +#define NET_GNRC_NETIF2_FLAGS_H + +#ifdef __cplusplus +extern "C" { +#endif + +/** + * @brief Auto-address configuration modes + * @anchor net_gnrc_netif2_aac + */ +enum { + GNRC_NETIF2_AAC_NONE = 0, /**< no configuration */ + GNRC_NETIF2_AAC_AUTO, /**< Use some automatic bootstrapping (e.g. SLAAC with IPv6) */ + GNRC_NETIF2_AAC_DHCP, /**< Use DHCP(v6) */ + /* extend if needed */ +}; + +/** + * @name Network interface flags + * @anchor net_gnrc_netif2_flags + * @{ + */ +/** + * @brief Network interface has link-layer address + * + * There are link-layers (e.g. SLIP) that do not have (nor require) link-layer + * addresses. This flag signifies this fact to upper layers by leaving it unset. + */ +#define GNRC_NETIF2_FLAGS_HAS_L2ADDR (0x00000001U) + +/** + * @brief Network interface is enabled for IPv6 forwarding + */ +#define GNRC_NETIF2_FLAGS_IPV6_FORWARDING (0x00000002U) + +/** + * @brief Network interface advertises itself as an IPv6 router + * (implies @ref GNRC_NETIF2_FLAGS_IPV6_FORWARDING to be set) + */ +#define GNRC_NETIF2_FLAGS_IPV6_RTR_ADV (0x00000004U) + +/** + * @brief This interface advertises its gnrc_netif2_t::mtu to other nodes + * (implies @ref GNRC_NETIF2_FLAGS_IPV6_RTR_ADV to be set) + */ +#define GNRC_NETIF2_FLAGS_IPV6_ADV_MTU (0x00000008U) + +/** + * @brief This interface advertises its gnrc_netif2_t::cur_hl to other nodes + * (implies @ref GNRC_NETIF2_FLAGS_IPV6_RTR_ADV to be set) + */ +#define GNRC_NETIF2_FLAGS_IPV6_ADV_CUR_HL (0x00000010U) + +/** + * @brief This interface advertises its reachable time to other nodes + * (implies @ref GNRC_NETIF2_FLAGS_IPV6_RTR_ADV to be set) + */ +#define GNRC_NETIF2_FLAGS_IPV6_ADV_REACH_TIME (0x00000020U) + +/** + * @brief This interface advertises its retransmission timer to other nodes + * (implies @ref GNRC_NETIF2_FLAGS_IPV6_RTR_ADV to be set) + */ +#define GNRC_NETIF2_FLAGS_IPV6_ADV_RETRANS_TIMER (0x00000040U) + +/** + * @brief This interface uses 6Lo header compression + * + * @see [RFC 6282](https://tools.ietf.org/html/rfc6282) + */ +#define GNRC_NETIF2_FLAGS_6LO_HC (0x00000080U) + +/** + * @brief This interface acts as a 6Lo border router to the LLN + */ +#define GNRC_NETIF2_FLAGS_6LO_ABR (0x00000100U) + +/** + * @brief This interface acts as a mesh-under node (route-over topology when + * unset) + */ +#define GNRC_NETIF2_FLAGS_6LO_MESH (0x00000200U) + +/** + * @brief Interface supports 6LoWPAN general header compression + * + * @attention GHC not implemented yet + * @see [RFC 7400, section 3.3](https://tools.ietf.org/html/rfc7400#section-3.3) + */ +#define GNRC_NETIF2_FLAGS_6LO_BACKBONE (0x00000400U) + +/** + * @brief Mask for @ref gnrc_mac_tx_feedback_t + */ +#define GNRC_NETIF2_FLAGS_MAC_TX_FEEDBACK_MASK (0x00006000U) + +/** + * @brief Flag to track if a transmission might have corrupted a received + * packet + */ +#define GNRC_NETIF2_FLAGS_MAC_RX_STARTED (0x00008000U) +/** @} */ + +#ifdef __cplusplus +} +#endif + +#endif /* NET_GNRC_NETIF2_FLAGS_H */ +/** @} */ diff --git a/sys/include/net/gnrc/netif2/ipv6.h b/sys/include/net/gnrc/netif2/ipv6.h new file mode 100644 index 0000000000000..811e23dac0e06 --- /dev/null +++ b/sys/include/net/gnrc/netif2/ipv6.h @@ -0,0 +1,234 @@ +/* + * 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_netif2 + * @{ + * + * @file + * @brief IPv6 defintions for @ref net_gnrc_netif2 + * + * @author Martine Lenders + */ +#ifndef NET_GNRC_NETIF2_IPV6_H +#define NET_GNRC_NETIF2_IPV6_H + +#include "net/ipv6/addr.h" +#ifdef MODULE_GNRC_IPV6_NIB +#include "net/gnrc/ipv6/nib/conf.h" +#endif +#include "net/gnrc/netif2/conf.h" +#include "net/netstats.h" + +#ifdef __cplusplus +extern "C" { +#endif + +/** + * @name IPv6 unicast and anycast address flags + * @anchor net_gnrc_netif2_ipv6_addrs_flags + * @{ + */ +/** + * @brief Mask for the address' state + */ +#define GNRC_NETIF2_IPV6_ADDRS_FLAGS_STATE_MASK (0x03U) + +/** + * @brief Tentative address state + */ +#define GNRC_NETIF2_IPV6_ADDRS_FLAGS_STATE_TENTATIVE (0x01U) + +/** + * @brief Deprecated address state (still valid, but not preferred) + */ +#define GNRC_NETIF2_IPV6_ADDRS_FLAGS_STATE_DEPRECATED (0x02U) + +/** + * @brief Valid address state + */ +#define GNRC_NETIF2_IPV6_ADDRS_FLAGS_STATE_VALID (0x03U) + +/** + * @brief Address is an anycast address + */ +#define GNRC_NETIF2_IPV6_ADDRS_FLAGS_ANYCAST (0x04U) +/** @} */ + +/** + * @brief IPv6 component for @ref gnrc_netif2_t + * + * @note only available with @ref net_gnrc_ipv6. + */ +typedef struct { + /** + * @brief Flags for gnrc_netif2_t::ipv6_addrs + * + * @see net_gnrc_netif2_ipv6_addrs_flags + * + * @note Only available with module @ref net_gnrc_ipv6 "gnrc_ipv6". + */ + uint8_t addrs_flags[GNRC_NETIF2_IPV6_ADDRS_NUMOF]; + + /** + * @brief IPv6 unicast and anycast addresses of the interface + * + * @note Only available with module @ref net_gnrc_ipv6 "gnrc_ipv6". + */ + ipv6_addr_t addrs[GNRC_NETIF2_IPV6_ADDRS_NUMOF]; + + /** + * @brief IPv6 multicast groups of the interface + * + * @note Only available with module @ref net_gnrc_ipv6 "gnrc_ipv6". + */ + ipv6_addr_t groups[GNRC_NETIF2_IPV6_GROUPS_NUMOF]; +#ifdef MODULE_NETSTATS_IPV6 + /** + * @brief IPv6 packet statistics + * + * @note Only available with module `netstats_ipv6`. + */ + netstats_t stats; +#endif +#if defined(MODULE_GNRC_IPV6_NIB) || DOXYGEN +#if GNRC_IPV6_NIB_CONF_ROUTER || DOXYGEN + /** + * @brief Route info callback + * + * This callback is called by the @ref net_gnrc_ipv6_nib "NIB" to inform + * the routing protocol about state changes, route usages, missing routes + * etc. + * + * @todo Define types (RRQ, RRN, NSC) in NIB + * + * @param[in] type Type of the route info. + * @param[in] ctx_addr Context address of the route info. + * @param[in] ctx Further context of the route info. + */ + int (*route_info_cb)(unsigned type, const ipv6_addr_t *ctx_addr, + const void *ctx); + /** + * @brief Event for @ref GNRC_IPV6_NIB_SND_MC_RA + * + * @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_ROUTER != 0 + */ + evtimer_msg_event_t snd_mc_ra; +#endif /* GNRC_IPV6_NIB_CONF_ROUTER */ +#if GNRC_IPV6_NIB_CONF_ARSM || DOXYGEN + /** + * @brief Event for @ref GNRC_IPV6_NIB_RECALC_REACH_TIME + * + * @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_ARSM != 0 + */ + evtimer_msg_event_t recalc_reach_time; +#endif /* GNRC_IPV6_NIB_CONF_ARSM */ + /** + * @brief Event for @ref GNRC_IPV6_NIB_SEARCH_RTR + * + * @note Only available with module @ref net_gnrc_ipv6 "gnrc_ipv6". + * and @ref net_gnrc_ipv6_nib "NIB" + */ + evtimer_msg_event_t search_rtr; + +#if GNRC_IPV6_NIB_CONF_ROUTER || DOXYGEN + /** + * @brief Timestamp in milliseconds of last unsolicited router + * advertisement + * + * @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_ROUTER != 0 + */ + uint32_t last_ra; +#endif /* GNRC_IPV6_NIB_CONF_ROUTER */ +#if GNRC_IPV6_NIB_CONF_ARSM || defined(DOXYGEN) + /** + * @brief Base for random reachable time calculation and advertised + * reachable time in ms (if @ref GNRC_NETIF2_FLAGS_IPV6_RTR_ADV is + * set) + * + * @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_ARSM != 0 + */ + uint32_t reach_time_base; + + /** + * @brief Reachable time (in ms) + * + * @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_ARSM != 0 + */ + uint32_t reach_time; +#endif /* GNRC_IPV6_NIB_CONF_ARSM */ + /** + * @brief Retransmission time and advertised retransmission time (in ms) + * + * @note Only available with module @ref net_gnrc_ipv6 "gnrc_ipv6" and + * @ref net_gnrc_ipv6_nib "NIB" + */ + uint32_t retrans_time; +#endif /* MODULE_GNRC_IPV6_NIB */ +#if defined(MODULE_GNRC_IPV6_NIB) || DOXYGEN +#if GNRC_IPV6_NIB_CONF_ROUTER || DOXYGEN + /** + * @brief number of unsolicited router advertisements sent + * + * This only counts up to the first @ref NDP_MAX_INIT_RA_NUMOF on interface + * initialization. The last @ref NDP_MAX_FIN_RA_NUMOF of an advertising + * interface are counted from UINT8_MAX - @ref NDP_MAX_FIN_RA_NUMOF + 1. + * + * @note Only available with module @ref net_gnrc_ipv6 "gnrc_ipv6". + * and @ref net_gnrc_ipv6_nib "NIB" and if + * @ref GNRC_IPV6_NIB_CONF_ROUTER != 0 + */ + uint8_t ra_sent; +#endif + /** + * @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" + */ + uint8_t rs_sent; + /** + * @brief number of unsolicited neighbor advertisements scheduled + * + * @note Only available with module @ref net_gnrc_ipv6 "gnrc_ipv6" and + * @ref net_gnrc_ipv6_nib "NIB" + */ + uint8_t na_sent; +#endif + + /** + * @brief IPv6 auto-address configuration mode + * + * @note Only available with module @ref net_gnrc_ipv6 "gnrc_ipv6" + */ + uint8_t aac_mode; + + /** + * @brief Maximum transition unit (MTU) for IPv6 packets + * + * @note Only available with module @ref net_gnrc_ipv6 "gnrc_ipv6". + */ + uint16_t mtu; +} gnrc_netif2_ipv6_t; + +#ifdef __cplusplus +} +#endif + +#endif /* NET_GNRC_NETIF2_IPV6_H */ +/** @} */ diff --git a/sys/include/net/gnrc/netif2/mac.h b/sys/include/net/gnrc/netif2/mac.h new file mode 100644 index 0000000000000..f2028d1495261 --- /dev/null +++ b/sys/include/net/gnrc/netif2/mac.h @@ -0,0 +1,58 @@ +/* + * 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_netif2 + * @{ + * + * @file + * @brief @ref net_gnrc_mac definitions for @ref net_gnrc_netif2 + * + * @author Martine Lenders + */ +#ifndef NET_GNRC_NETIF2_MAC_H +#define NET_GNRC_NETIF2_MAC_H + +#include "net/gnrc/mac/mac.h" + +#ifdef __cplusplus +extern "C" { +#endif + +/** + * @brief @ref net_gnrc_mac component of @ref gnrc_netif2_mac_t + */ +typedef struct { +#if ((GNRC_MAC_RX_QUEUE_SIZE != 0) || (GNRC_MAC_DISPATCH_BUFFER_SIZE != 0)) || DOXYGEN + /** + * @brief MAC internal object which stores reception parameters, queues, and + * state machines. + * + * @note Only available if @ref GNRC_MAC_RX_QUEUE_SIZE or + * @ref GNRC_MAC_DISPATCH_BUFFER_SIZE is greater than 0. + */ + gnrc_mac_rx_t rx; +#endif /* ((GNRC_MAC_RX_QUEUE_SIZE != 0) || (GNRC_MAC_DISPATCH_BUFFER_SIZE != 0)) || DOXYGEN */ +#if ((GNRC_MAC_TX_QUEUE_SIZE != 0) || (GNRC_MAC_NEIGHBOR_COUNT != 0)) || DOXYGEN + /** + * @brief MAC internal object which stores transmission parameters, queues, and + * state machines. + * + * @note Only available if @ref GNRC_MAC_TX_QUEUE_SIZE or + * @ref GNRC_MAC_NEIGHBOR_COUNT is greater than 0. + */ + gnrc_mac_tx_t tx; +#endif /* ((GNRC_MAC_TX_QUEUE_SIZE != 0) || (GNRC_MAC_NEIGHBOR_COUNT == 0)) || DOXYGEN */ +} gnrc_netif2_mac_t; + +#ifdef __cplusplus +} +#endif + +#endif /* NET_GNRC_NETIF2_MAC_H */ +/** @} */ diff --git a/sys/net/gnrc/netif2/gnrc_netif2.c b/sys/net/gnrc/netif2/gnrc_netif2.c index 54a7c103e0190..b04e5c53f28ac 100644 --- a/sys/net/gnrc/netif2/gnrc_netif2.c +++ b/sys/net/gnrc/netif2/gnrc_netif2.c @@ -107,8 +107,8 @@ int gnrc_netif2_get_from_netdev(gnrc_netif2_t *netif, gnrc_netapi_opt_t *opt) switch ((int16_t)opt->context) { #if defined(MODULE_NETSTATS_IPV6) && defined(MODULE_GNRC_IPV6) case NETSTATS_IPV6: - *((netstats_t **)opt->data) = &netif->ipv6_stats; - res = sizeof(&netif->ipv6_stats); + *((netstats_t **)opt->data) = &netif->ipv6.stats; + res = sizeof(&netif->ipv6.stats); break; #endif case NETSTATS_ALL: @@ -129,8 +129,8 @@ int gnrc_netif2_get_from_netdev(gnrc_netif2_t *netif, gnrc_netapi_opt_t *opt) for (unsigned i = 0; (res < opt->data_len) && (i < GNRC_NETIF2_IPV6_ADDRS_NUMOF); i++, tgt++) { - if (netif->ipv6_addrs_flags[i] != 0) { - memcpy(tgt, &netif->ipv6_addrs[i], sizeof(ipv6_addr_t)); + if (netif->ipv6.addrs_flags[i] != 0) { + memcpy(tgt, &netif->ipv6.addrs[i], sizeof(ipv6_addr_t)); res += sizeof(ipv6_addr_t); } } @@ -144,8 +144,8 @@ int gnrc_netif2_get_from_netdev(gnrc_netif2_t *netif, gnrc_netapi_opt_t *opt) for (unsigned i = 0; (res < opt->data_len) && (i < GNRC_NETIF2_IPV6_ADDRS_NUMOF); i++, tgt++) { - if (netif->ipv6_addrs_flags[i] != 0) { - *tgt = netif->ipv6_addrs_flags[i]; + if (netif->ipv6.addrs_flags[i] != 0) { + *tgt = netif->ipv6.addrs_flags[i]; res += sizeof(uint8_t); } } @@ -159,8 +159,8 @@ int gnrc_netif2_get_from_netdev(gnrc_netif2_t *netif, gnrc_netapi_opt_t *opt) for (unsigned i = 0; (res < opt->data_len) && (i < GNRC_NETIF2_IPV6_GROUPS_NUMOF); i++, tgt++) { - if (!ipv6_addr_is_unspecified(&netif->ipv6_groups[i])) { - memcpy(tgt, &netif->ipv6_groups[i], sizeof(ipv6_addr_t)); + if (!ipv6_addr_is_unspecified(&netif->ipv6.groups[i])) { + memcpy(tgt, &netif->ipv6.groups[i], sizeof(ipv6_addr_t)); res += sizeof(ipv6_addr_t); } } @@ -175,7 +175,7 @@ int gnrc_netif2_get_from_netdev(gnrc_netif2_t *netif, gnrc_netapi_opt_t *opt) case NETOPT_MAX_PACKET_SIZE: if (opt->context == GNRC_NETTYPE_IPV6) { assert(opt->data_len == sizeof(uint16_t)); - *((uint16_t *)opt->data) = netif->ipv6_mtu; + *((uint16_t *)opt->data) = netif->ipv6.mtu; res = sizeof(uint16_t); } /* else ask device */ @@ -263,7 +263,7 @@ int gnrc_netif2_set_from_netdev(gnrc_netif2_t *netif, case NETOPT_MAX_PACKET_SIZE: if (opt->context == GNRC_NETTYPE_IPV6) { assert(opt->data_len == sizeof(uint16_t)); - netif->ipv6_mtu = *((uint16_t *)opt->data); + netif->ipv6.mtu = *((uint16_t *)opt->data); res = sizeof(uint16_t); } /* else set device */ @@ -518,11 +518,11 @@ int gnrc_netif2_ipv6_addr_add(gnrc_netif2_t *netif, const ipv6_addr_t *addr, flags |= GNRC_NETIF2_IPV6_ADDRS_FLAGS_STATE_TENTATIVE; } for (unsigned i = 0; i < GNRC_NETIF2_IPV6_ADDRS_NUMOF; i++) { - if (ipv6_addr_equal(&netif->ipv6_addrs[i], addr)) { + if (ipv6_addr_equal(&netif->ipv6.addrs[i], addr)) { gnrc_netif2_release(netif); return i; } - if ((idx == UINT_MAX) && (netif->ipv6_addrs_flags[i] == 0)) { + if ((idx == UINT_MAX) && (netif->ipv6.addrs_flags[i] == 0)) { idx = i; } } @@ -530,8 +530,8 @@ int gnrc_netif2_ipv6_addr_add(gnrc_netif2_t *netif, const ipv6_addr_t *addr, gnrc_netif2_release(netif); return -ENOMEM; } - netif->ipv6_addrs_flags[idx] = flags; - memcpy(&netif->ipv6_addrs[idx], addr, sizeof(netif->ipv6_addrs[idx])); + 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 */ @@ -549,8 +549,8 @@ void gnrc_netif2_ipv6_addr_remove(gnrc_netif2_t *netif, gnrc_netif2_acquire(netif); idx = _addr_idx(netif, addr); if (idx >= 0) { - netif->ipv6_addrs_flags[idx] = 0; - ipv6_addr_set_unspecified(&netif->ipv6_addrs[idx]); + netif->ipv6.addrs_flags[idx] = 0; + ipv6_addr_set_unspecified(&netif->ipv6.addrs[idx]); /* TODO: * - update prefix list, if necessary */ } @@ -596,7 +596,7 @@ ipv6_addr_t *gnrc_netif2_ipv6_addr_best_src(gnrc_netif2_t *netif, if (first_candidate >= 0) { best_src = _src_addr_selection(netif, dst, candidate_set); if (best_src == NULL) { - best_src = &(netif->ipv6_addrs[first_candidate]); + best_src = &(netif->ipv6.addrs[first_candidate]); } } gnrc_netif2_release(netif); @@ -640,11 +640,11 @@ int gnrc_netif2_ipv6_group_join(gnrc_netif2_t *netif, gnrc_netif2_acquire(netif); for (unsigned i = 0; i < GNRC_NETIF2_IPV6_GROUPS_NUMOF; i++) { - if (ipv6_addr_equal(&netif->ipv6_groups[i], addr)) { + if (ipv6_addr_equal(&netif->ipv6.groups[i], addr)) { gnrc_netif2_release(netif); return i; } - if ((idx == UINT_MAX) && (ipv6_addr_is_unspecified(&netif->ipv6_groups[i]))) { + if ((idx == UINT_MAX) && (ipv6_addr_is_unspecified(&netif->ipv6.groups[i]))) { idx = i; } } @@ -652,7 +652,7 @@ int gnrc_netif2_ipv6_group_join(gnrc_netif2_t *netif, gnrc_netif2_release(netif); return -ENOMEM; } - memcpy(&netif->ipv6_groups[idx], addr, sizeof(netif->ipv6_groups[idx])); + memcpy(&netif->ipv6.groups[idx], addr, sizeof(netif->ipv6.groups[idx])); /* TODO: * - MLD action */ @@ -669,7 +669,7 @@ void gnrc_netif2_ipv6_group_leave(gnrc_netif2_t *netif, gnrc_netif2_acquire(netif); idx = _group_idx(netif, addr); if (idx >= 0) { - ipv6_addr_set_unspecified(&netif->ipv6_groups[idx]); + ipv6_addr_set_unspecified(&netif->ipv6.groups[idx]); /* TODO: * - MLD action */ } @@ -753,13 +753,13 @@ int gnrc_netif2_ipv6_get_iid(gnrc_netif2_t *netif, eui64_t *eui64) static inline bool _addr_anycast(const gnrc_netif2_t *netif, unsigned idx) { - return (netif->ipv6_addrs_flags[idx] & GNRC_NETIF2_IPV6_ADDRS_FLAGS_ANYCAST); + return (netif->ipv6.addrs_flags[idx] & GNRC_NETIF2_IPV6_ADDRS_FLAGS_ANYCAST); } static int _addr_idx(const gnrc_netif2_t *netif, const ipv6_addr_t *addr) { for (unsigned i = 0; i < GNRC_NETIF2_IPV6_ADDRS_NUMOF; i++) { - if (ipv6_addr_equal(&netif->ipv6_addrs[i], addr)) { + if (ipv6_addr_equal(&netif->ipv6.addrs[i], addr)) { return i; } } @@ -776,14 +776,14 @@ static unsigned _match(const gnrc_netif2_t *netif, const ipv6_addr_t *addr, for (int i = 0; i < GNRC_NETIF2_IPV6_ADDRS_NUMOF; i++) { unsigned match; - if ((netif->ipv6_addrs_flags[i] == 0) || + if ((netif->ipv6.addrs_flags[i] == 0) || ((filter != NULL) && _addr_anycast(netif, i)) || /* discard const intentionally */ ((filter != NULL) && !(bf_isset((uint8_t *)filter, i)))) { continue; } - match = ipv6_addr_match_prefix(&(netif->ipv6_addrs[i]), addr); - if (((match > 64U) || !ipv6_addr_is_link_local(&(netif->ipv6_addrs[i]))) && + match = ipv6_addr_match_prefix(&(netif->ipv6.addrs[i]), addr); + if (((match > 64U) || !ipv6_addr_is_link_local(&(netif->ipv6.addrs[i]))) && (match > best_match)) { if (idx != NULL) { *idx = i; @@ -794,7 +794,7 @@ static unsigned _match(const gnrc_netif2_t *netif, const ipv6_addr_t *addr, #if ENABLE_DEBUG if (*idx >= 0) { DEBUG("gnrc_netif2: Found %s on interface %" PRIkernel_pid " matching ", - ipv6_addr_to_str(addr_str, &netif->ipv6_addrs[*idx], + ipv6_addr_to_str(addr_str, &netif->ipv6.addrs[*idx], sizeof(addr_str)), netif->pid); DEBUG("%s by %" PRIu8 " bits (used as source address = %s)\n", @@ -828,7 +828,7 @@ static uint8_t _get_scope(const ipv6_addr_t *addr) static inline unsigned _get_state(const gnrc_netif2_t *netif, unsigned idx) { - return (netif->ipv6_addrs_flags[idx] & + return (netif->ipv6.addrs_flags[idx] & GNRC_NETIF2_IPV6_ADDRS_FLAGS_STATE_MASK); } @@ -862,14 +862,14 @@ static int _create_candidate_set(const gnrc_netif2_t *netif, * on interface @p netif */ (void) dst; for (int i = 0; i < GNRC_NETIF2_IPV6_ADDRS_NUMOF; i++) { - const ipv6_addr_t *tmp = &(netif->ipv6_addrs[i]); + const ipv6_addr_t *tmp = &(netif->ipv6.addrs[i]); DEBUG("Checking address: %s\n", ipv6_addr_to_str(addr_str, tmp, sizeof(addr_str))); /* "In any case, multicast addresses and the unspecified address MUST NOT * be included in a candidate set." */ - if (netif->ipv6_addrs_flags[i] == 0) { + if (netif->ipv6.addrs_flags[i] == 0) { continue; } /* Check if we only want link local addresses */ @@ -922,7 +922,7 @@ static ipv6_addr_t *_src_addr_selection(gnrc_netif2_t *netif, DEBUG("finding the best match within the source address candidates\n"); for (unsigned i = 0; i < GNRC_NETIF2_IPV6_ADDRS_NUMOF; i++) { - ipv6_addr_t *ptr = &(netif->ipv6_addrs[i]); + ipv6_addr_t *ptr = &(netif->ipv6.addrs[i]); DEBUG("Checking address: %s\n", ipv6_addr_to_str(addr_str, ptr, sizeof(addr_str))); @@ -1002,13 +1002,13 @@ static ipv6_addr_t *_src_addr_selection(gnrc_netif2_t *netif, /* otherwise apply rule 8: Use longest matching prefix. */ int res; _match(netif, dst, candidate_set, &res); - return (res < 0) ? NULL : &netif->ipv6_addrs[res]; + return (res < 0) ? NULL : &netif->ipv6.addrs[res]; } static int _group_idx(const gnrc_netif2_t *netif, const ipv6_addr_t *addr) { for (unsigned i = 0; i < GNRC_NETIF2_IPV6_GROUPS_NUMOF; i++) { - if (ipv6_addr_equal(&netif->ipv6_groups[i], addr)) { + if (ipv6_addr_equal(&netif->ipv6.groups[i], addr)) { return i; } } @@ -1069,10 +1069,10 @@ static void _init_from_device(gnrc_netif2_t *netif) res = dev->driver->get(dev, NETOPT_MAX_PACKET_SIZE, &tmp, sizeof(tmp)); assert(res == sizeof(tmp)); #ifdef MODULE_GNRC_SIXLOWPAN - netif->ipv6_mtu = IPV6_MIN_MTU; + netif->ipv6.mtu = IPV6_MIN_MTU; netif->max_frag_size = tmp; #else - netif->ipv6_mtu = tmp; + netif->ipv6.mtu = tmp; #endif #endif break; @@ -1080,7 +1080,7 @@ static void _init_from_device(gnrc_netif2_t *netif) #ifdef MODULE_NETDEV_ETH case NETDEV_TYPE_ETHERNET: #ifdef MODULE_GNRC_IPV6 - netif->ipv6_mtu = ETHERNET_DATA_LEN; + netif->ipv6.mtu = ETHERNET_DATA_LEN; #endif break; #endif @@ -1088,7 +1088,7 @@ static void _init_from_device(gnrc_netif2_t *netif) res = dev->driver->get(dev, NETOPT_MAX_PACKET_SIZE, &tmp, sizeof(tmp)); assert(res == sizeof(tmp)); #ifdef MODULE_GNRC_IPV6 - netif->ipv6_mtu = tmp; + netif->ipv6.mtu = tmp; #endif } _update_l2addr_from_dev(netif); From 6125c3c7d96f87fbf96516359297b1a45159a30e Mon Sep 17 00:00:00 2001 From: Martine Lenders Date: Fri, 28 Jul 2017 14:36:08 +0200 Subject: [PATCH 15/31] fixup! tests: add tests for gnrc_netif2 Adapt tests for definition changes --- tests/gnrc_netif2/main.c | 36 ++++++++++++++++++------------------ 1 file changed, 18 insertions(+), 18 deletions(-) diff --git a/tests/gnrc_netif2/main.c b/tests/gnrc_netif2/main.c index df867bd09b0ac..f6d77613c1dc2 100644 --- a/tests/gnrc_netif2/main.c +++ b/tests/gnrc_netif2/main.c @@ -61,19 +61,19 @@ static void _set_up(void) msg_t msg; if (ethernet_netif != NULL) { - memset(ethernet_netif->ipv6_addrs_flags, 0, - sizeof(ethernet_netif->ipv6_addrs_flags)); - memset(ethernet_netif->ipv6_addrs, 0, - sizeof(ethernet_netif->ipv6_addrs)); - memset(ethernet_netif->ipv6_groups, 0, - sizeof(ethernet_netif->ipv6_groups)); + memset(ethernet_netif->ipv6.addrs_flags, 0, + sizeof(ethernet_netif->ipv6.addrs_flags)); + memset(ethernet_netif->ipv6.addrs, 0, + sizeof(ethernet_netif->ipv6.addrs)); + memset(ethernet_netif->ipv6.groups, 0, + sizeof(ethernet_netif->ipv6.groups)); } for (unsigned i = 0; i < DEFAULT_DEVS_NUMOF; i++) { if (netifs[i] != NULL) { - memset(netifs[i]->ipv6_addrs_flags, 0, - sizeof(netifs[i]->ipv6_addrs_flags)); - memset(netifs[i]->ipv6_addrs, 0, sizeof(netifs[i]->ipv6_addrs)); - memset(netifs[i]->ipv6_groups, 0, sizeof(netifs[i]->ipv6_groups)); + memset(netifs[i]->ipv6.addrs_flags, 0, + sizeof(netifs[i]->ipv6.addrs_flags)); + memset(netifs[i]->ipv6.addrs, 0, sizeof(netifs[i]->ipv6.addrs)); + memset(netifs[i]->ipv6.groups, 0, sizeof(netifs[i]->ipv6.groups)); } } /* empty message queue */ @@ -96,7 +96,7 @@ static void test_creation(void) TEST_ASSERT_NULL((ptr = gnrc_netif2_iter(ptr))); TEST_ASSERT_NOT_NULL(ethernet_netif->ops); TEST_ASSERT_NOT_NULL(ethernet_netif->dev); - TEST_ASSERT_EQUAL_INT(ETHERNET_DATA_LEN, ethernet_netif->ipv6_mtu); + TEST_ASSERT_EQUAL_INT(ETHERNET_DATA_LEN, ethernet_netif->ipv6.mtu); TEST_ASSERT_EQUAL_INT(GNRC_NETIF2_DEFAULT_HL, ethernet_netif->cur_hl); TEST_ASSERT_EQUAL_INT(NETDEV_TYPE_ETHERNET, ethernet_netif->device_type); TEST_ASSERT(ethernet_netif->pid > KERNEL_PID_UNDEF); @@ -188,8 +188,8 @@ static void test_ipv6_addr_add__success(void) gnrc_netif2_ipv6_addr_add(netifs[0], &addr, 64U, GNRC_NETIF2_IPV6_ADDRS_FLAGS_STATE_VALID)); TEST_ASSERT_EQUAL_INT(GNRC_NETIF2_IPV6_ADDRS_FLAGS_STATE_VALID, - netifs[0]->ipv6_addrs_flags[idx]); - TEST_ASSERT(ipv6_addr_equal(&addr, &netifs[0]->ipv6_addrs[idx])); + netifs[0]->ipv6.addrs_flags[idx]); + TEST_ASSERT(ipv6_addr_equal(&addr, &netifs[0]->ipv6.addrs[idx])); } static void test_ipv6_addr_add__readd_with_free_entry(void) @@ -295,7 +295,7 @@ static void test_ipv6_addr_match__success18(void) TEST_ASSERT(0 <= (idx = gnrc_netif2_ipv6_addr_add(netifs[0], &addr, 64U, GNRC_NETIF2_IPV6_ADDRS_FLAGS_STATE_VALID))); TEST_ASSERT_EQUAL_INT(idx, gnrc_netif2_ipv6_addr_match(netifs[0], &pfx)); - TEST_ASSERT_EQUAL_INT(18, ipv6_addr_match_prefix(&netifs[0]->ipv6_addrs[idx], + TEST_ASSERT_EQUAL_INT(18, ipv6_addr_match_prefix(&netifs[0]->ipv6.addrs[idx], &pfx)); } @@ -309,7 +309,7 @@ static void test_ipv6_addr_match__success23(void) TEST_ASSERT(0 <= (idx = gnrc_netif2_ipv6_addr_add(netifs[0], &addr, 64U, GNRC_NETIF2_IPV6_ADDRS_FLAGS_STATE_VALID))); TEST_ASSERT_EQUAL_INT(idx, gnrc_netif2_ipv6_addr_match(netifs[0], &pfx)); - TEST_ASSERT_EQUAL_INT(23, ipv6_addr_match_prefix(&netifs[0]->ipv6_addrs[idx], + TEST_ASSERT_EQUAL_INT(23, ipv6_addr_match_prefix(&netifs[0]->ipv6.addrs[idx], &pfx)); } @@ -323,7 +323,7 @@ static void test_ipv6_addr_match__success64(void) TEST_ASSERT(0 <= (idx = gnrc_netif2_ipv6_addr_add(netifs[0], &addr, 64U, GNRC_NETIF2_IPV6_ADDRS_FLAGS_STATE_VALID))); TEST_ASSERT_EQUAL_INT(idx, gnrc_netif2_ipv6_addr_match(netifs[0], &pfx)); - TEST_ASSERT_EQUAL_INT(64, ipv6_addr_match_prefix(&netifs[0]->ipv6_addrs[idx], + TEST_ASSERT_EQUAL_INT(64, ipv6_addr_match_prefix(&netifs[0]->ipv6.addrs[idx], &pfx)); } @@ -441,7 +441,7 @@ static void test_ipv6_group_join__success(void) gnrc_netif2_ipv6_group_join(netifs[0], &ipv6_addr_all_nodes_link_local)); TEST_ASSERT(ipv6_addr_equal(&ipv6_addr_all_nodes_link_local, - &netifs[0]->ipv6_groups[idx])); + &netifs[0]->ipv6.groups[idx])); } static void test_ipv6_group_join__readd_with_free_entry(void) @@ -721,7 +721,7 @@ static void test_netapi_set__MAX_PACKET_SIZE(void) NETOPT_MAX_PACKET_SIZE, GNRC_NETTYPE_IPV6, &value, sizeof(value))); - TEST_ASSERT_EQUAL_INT(value, netifs[0]->ipv6_mtu); + TEST_ASSERT_EQUAL_INT(value, netifs[0]->ipv6.mtu); TEST_ASSERT_EQUAL_INT(-ENOTSUP, gnrc_netapi_set(netifs[0]->pid, NETOPT_MAX_PACKET_SIZE, 0, From 36287f59777efd12b87e05184dc35fb49020aded Mon Sep 17 00:00:00 2001 From: Martine Lenders Date: Fri, 28 Jul 2017 16:24:18 +0200 Subject: [PATCH 16/31] fixup! fixup! gnrc_netif2: Introduction of a new GNRC network interface API --- sys/include/net/gnrc/netif2.h | 17 ++++++++- sys/include/net/gnrc/netif2/6lo.h | 44 ++++++++++++++++++++++ sys/include/net/gnrc/netif2/conf.h | 4 ++ sys/include/net/gnrc/netif2/ipv6.h | 2 + sys/net/gnrc/netif2/gnrc_netif2.c | 14 ++++--- sys/net/gnrc/netif2/gnrc_netif2_ethernet.c | 1 - 6 files changed, 73 insertions(+), 9 deletions(-) create mode 100644 sys/include/net/gnrc/netif2/6lo.h diff --git a/sys/include/net/gnrc/netif2.h b/sys/include/net/gnrc/netif2.h index e8b3de40256f1..d990b2ec2446e 100644 --- a/sys/include/net/gnrc/netif2.h +++ b/sys/include/net/gnrc/netif2.h @@ -30,10 +30,9 @@ #include "kernel_types.h" #include "msg.h" -#include "net/ieee802154.h" -#include "net/ethernet/hdr.h" #include "net/gnrc/netapi.h" #include "net/gnrc/pkt.h" +#include "net/gnrc/netif2/conf.h" #ifdef MODULE_GNRC_SIXLOWPAN #include "net/gnrc/netif2/6lo.h" #endif @@ -103,6 +102,20 @@ typedef struct { * @see gnrc_netif2_ops_t */ struct gnrc_netif2_ops { + /** + * @brief Initializes network interface beyond the default settings + * + * @pre `netif != NULL` + * + * @param[in] netif The network interface. + * + * This is called after the default settings were set, right before the + * interface's thread starts receiving messages. It is not necessary lock + * the interface's mutex gnrc_netif_t::mutex, since the thread will already + * lock it. Leave NULL if you do not need any special initialization. + */ + void (*init)(gnrc_netif2_t *netif); + /** * @brief Send a @ref net_gnrc_pkt "packet" over the network interface * diff --git a/sys/include/net/gnrc/netif2/6lo.h b/sys/include/net/gnrc/netif2/6lo.h new file mode 100644 index 0000000000000..be8a878f72cd0 --- /dev/null +++ b/sys/include/net/gnrc/netif2/6lo.h @@ -0,0 +1,44 @@ +/* + * 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_netif2 + * @{ + * + * @file 6LoWPAN definitions for @ref net_gnrc_netif2 + * + * @author Martine Lenders + */ +#ifndef NET_GNRC_NETIF2_6LO_H +#define NET_GNRC_NETIF2_6LO_H + +#include + +#ifdef __cplusplus +extern "C" { +#endif + +/** + * @brief 6Lo component of @ref gnrc_netif2_t + */ +typedef struct { + /** + * @brief Maximum fragment size for 6Lo fragmentation. + * + * @note Only available with module + * @ref net_gnrc_sixlowpan_frag "gnrc_sixlowpan_frag". + */ + uint8_t max_frag_size; +} gnrc_netif2_6lo_t; + +#ifdef __cplusplus +} +#endif + +#endif /* NET_GNRC_NETIF2_6LO_H */ +/** @} */ diff --git a/sys/include/net/gnrc/netif2/conf.h b/sys/include/net/gnrc/netif2/conf.h index b7d8b8eeeceff..76e62b5fc679a 100644 --- a/sys/include/net/gnrc/netif2/conf.h +++ b/sys/include/net/gnrc/netif2/conf.h @@ -18,6 +18,10 @@ #ifndef NET_GNRC_NETIF2_CONF_H #define NET_GNRC_NETIF2_CONF_H +#include "net/ieee802154.h" +#include "net/ethernet/hdr.h" +#include "thread.h" + #ifdef __cplusplus extern "C" { #endif diff --git a/sys/include/net/gnrc/netif2/ipv6.h b/sys/include/net/gnrc/netif2/ipv6.h index 811e23dac0e06..e1df6be74543e 100644 --- a/sys/include/net/gnrc/netif2/ipv6.h +++ b/sys/include/net/gnrc/netif2/ipv6.h @@ -23,7 +23,9 @@ #include "net/gnrc/ipv6/nib/conf.h" #endif #include "net/gnrc/netif2/conf.h" +#ifdef MODULE_NETSTATS_IPV6 #include "net/netstats.h" +#endif #ifdef __cplusplus extern "C" { diff --git a/sys/net/gnrc/netif2/gnrc_netif2.c b/sys/net/gnrc/netif2/gnrc_netif2.c index b04e5c53f28ac..f4360e8c8d4c8 100644 --- a/sys/net/gnrc/netif2/gnrc_netif2.c +++ b/sys/net/gnrc/netif2/gnrc_netif2.c @@ -19,6 +19,9 @@ #include "net/ethernet.h" #include "net/ipv6.h" #include "net/gnrc.h" +#ifdef MODULE_NETSTATS_IPV6 +#include "net/netstats.h" +#endif #include "log.h" #include "sched.h" @@ -103,18 +106,14 @@ int gnrc_netif2_get_from_netdev(gnrc_netif2_t *netif, gnrc_netapi_opt_t *opt) break; case NETOPT_STATS: /* XXX discussed this with Oleg, it's supposed to be a pointer */ - assert(opt->data_len == sizeof(netstats_t *)); switch ((int16_t)opt->context) { #if defined(MODULE_NETSTATS_IPV6) && defined(MODULE_GNRC_IPV6) case NETSTATS_IPV6: + assert(opt->data_len == sizeof(netstats_t *)); *((netstats_t **)opt->data) = &netif->ipv6.stats; res = sizeof(&netif->ipv6.stats); break; #endif - case NETSTATS_ALL: - /* doesn't make sense */ - res = -EINVAL; - break; default: /* take from device */ break; @@ -1070,7 +1069,7 @@ static void _init_from_device(gnrc_netif2_t *netif) assert(res == sizeof(tmp)); #ifdef MODULE_GNRC_SIXLOWPAN netif->ipv6.mtu = IPV6_MIN_MTU; - netif->max_frag_size = tmp; + netif->sixlo.max_frag_size = tmp; #else netif->ipv6.mtu = tmp; #endif @@ -1120,6 +1119,9 @@ static void *_gnrc_netif2_thread(void *args) #ifdef MODULE_GNRC_IPV6_NIB gnrc_ipv6_nib_init_iface(netif); #endif + if (netif->ops->init) { + netif->ops->init(netif); + } /* now let rest of GNRC use the interface */ gnrc_netif2_release(netif); diff --git a/sys/net/gnrc/netif2/gnrc_netif2_ethernet.c b/sys/net/gnrc/netif2/gnrc_netif2_ethernet.c index 6ceab4280a317..d53c6706383cf 100644 --- a/sys/net/gnrc/netif2/gnrc_netif2_ethernet.c +++ b/sys/net/gnrc/netif2/gnrc_netif2_ethernet.c @@ -33,7 +33,6 @@ static const gnrc_netif2_ops_t ethernet_ops = { .recv = _recv, .get = gnrc_netif2_get_from_netdev, .set = gnrc_netif2_set_from_netdev, - .msg_handler = NULL, }; gnrc_netif2_t *gnrc_netif2_ethernet_create(char *stack, int stacksize, From 9d6cbcd3a4affb83dd0bbbc9f8d9d608b237d3e4 Mon Sep 17 00:00:00 2001 From: Martine Lenders Date: Fri, 28 Jul 2017 16:53:15 +0200 Subject: [PATCH 17/31] fixup! tests: add tests for gnrc_netif2 --- tests/gnrc_netif2/Makefile | 1 + tests/gnrc_netif2/main.c | 10 ++++++++++ 2 files changed, 11 insertions(+) diff --git a/tests/gnrc_netif2/Makefile b/tests/gnrc_netif2/Makefile index fdae4203a1b14..cc57c4f8a7851 100644 --- a/tests/gnrc_netif2/Makefile +++ b/tests/gnrc_netif2/Makefile @@ -7,6 +7,7 @@ BOARD_INSUFFICIENT_MEMORY := USEMODULE += embunit USEMODULE += gnrc_netif2 USEMODULE += gnrc_pktdump +USEMODULE += gnrc_sixlowpan USEMODULE += gnrc_sixlowpan_iphc USEMODULE += gnrc_ipv6 USEMODULE += netdev_eth diff --git a/tests/gnrc_netif2/main.c b/tests/gnrc_netif2/main.c index f6d77613c1dc2..2aec29fe187c0 100644 --- a/tests/gnrc_netif2/main.c +++ b/tests/gnrc_netif2/main.c @@ -42,13 +42,16 @@ static gnrc_netif2_t *ethernet_netif = NULL; static gnrc_netif2_t *netifs[DEFAULT_DEVS_NUMOF]; static char ethernet_netif_stack[ETHERNET_STACKSIZE]; static char netifs_stack[DEFAULT_DEVS_NUMOF][THREAD_STACKSIZE_DEFAULT]; +static bool init_called = false; +static inline void _test_init(gnrc_netif2_t *netif); static inline int _mock_netif_send(gnrc_netif2_t *netif, gnrc_pktsnip_t *pkt); static inline gnrc_pktsnip_t *_mock_netif_recv(gnrc_netif2_t * netif); static int _get_netdev_address(netdev_t *dev, void *value, size_t max_len); static int _set_netdev_address(netdev_t *dev, void *value, size_t value_len); static const gnrc_netif2_ops_t default_ops = { + .init = _test_init, .send = _mock_netif_send, .recv = _mock_netif_recv, .get = gnrc_netif2_get_from_netdev, @@ -80,6 +83,12 @@ static void _set_up(void) while (msg_try_receive(&msg) > 0) {} } +static inline void _test_init(gnrc_netif2_t *netif) +{ + (void)netif; + init_called = true; +} + static void test_creation(void) { char test_stack[4]; @@ -121,6 +130,7 @@ static void test_creation(void) } TEST_ASSERT_NULL((ptr = gnrc_netif2_iter(ptr))); } + TEST_ASSERT(init_called); TEST_ASSERT_NULL(gnrc_netif2_create(test_stack, 4, GNRC_NETIF2_PRIO, "netif", NULL, &default_ops)); } From 6ea16c6297974c196afc4e236e2b55889f9d92df Mon Sep 17 00:00:00 2001 From: Martine Lenders Date: Mon, 31 Jul 2017 17:52:39 +0200 Subject: [PATCH 18/31] fixup! gnrc_netif2: Introduction of a new GNRC network interface API Add missing include --- sys/include/net/gnrc/netif2.h | 1 + 1 file changed, 1 insertion(+) diff --git a/sys/include/net/gnrc/netif2.h b/sys/include/net/gnrc/netif2.h index d990b2ec2446e..d15c687db7e20 100644 --- a/sys/include/net/gnrc/netif2.h +++ b/sys/include/net/gnrc/netif2.h @@ -28,6 +28,7 @@ #include #include +#include "evtimer_msg.h" #include "kernel_types.h" #include "msg.h" #include "net/gnrc/netapi.h" From ec3b300793da7e2406b0e933390c386d4dd90c4a Mon Sep 17 00:00:00 2001 From: Martine Lenders Date: Tue, 1 Aug 2017 11:18:39 +0200 Subject: [PATCH 19/31] fixup! gnrc_netif2: Introduction of a new GNRC network interface API Move missing header to right file --- sys/include/net/gnrc/netif2.h | 1 - sys/include/net/gnrc/netif2/ipv6.h | 1 + 2 files changed, 1 insertion(+), 1 deletion(-) diff --git a/sys/include/net/gnrc/netif2.h b/sys/include/net/gnrc/netif2.h index d15c687db7e20..d990b2ec2446e 100644 --- a/sys/include/net/gnrc/netif2.h +++ b/sys/include/net/gnrc/netif2.h @@ -28,7 +28,6 @@ #include #include -#include "evtimer_msg.h" #include "kernel_types.h" #include "msg.h" #include "net/gnrc/netapi.h" diff --git a/sys/include/net/gnrc/netif2/ipv6.h b/sys/include/net/gnrc/netif2/ipv6.h index e1df6be74543e..37533ea39948d 100644 --- a/sys/include/net/gnrc/netif2/ipv6.h +++ b/sys/include/net/gnrc/netif2/ipv6.h @@ -18,6 +18,7 @@ #ifndef NET_GNRC_NETIF2_IPV6_H #define NET_GNRC_NETIF2_IPV6_H +#include "evtimer_msg.h" #include "net/ipv6/addr.h" #ifdef MODULE_GNRC_IPV6_NIB #include "net/gnrc/ipv6/nib/conf.h" From bead7fbef583b800cbb58db18e6383e13c159caf Mon Sep 17 00:00:00 2001 From: Martine Lenders Date: Tue, 1 Aug 2017 15:39:42 +0200 Subject: [PATCH 20/31] fixup! gnrc_netif2: Introduction of a new GNRC network interface API Some fixes --- sys/include/net/gnrc/netif2/internal.h | 7 ++++--- sys/include/net/gnrc/netif2/ipv6.h | 10 ++++++++-- sys/net/gnrc/netif2/gnrc_netif2.c | 3 +++ 3 files changed, 15 insertions(+), 5 deletions(-) diff --git a/sys/include/net/gnrc/netif2/internal.h b/sys/include/net/gnrc/netif2/internal.h index 952cc2fa492a1..57d0e4451eaf1 100644 --- a/sys/include/net/gnrc/netif2/internal.h +++ b/sys/include/net/gnrc/netif2/internal.h @@ -41,7 +41,7 @@ extern "C" { */ static inline void gnrc_netif2_acquire(gnrc_netif2_t *netif) { - if (netif->ops) { + if (netif && (netif->ops)) { rmutex_lock(&netif->mutex); } } @@ -55,7 +55,7 @@ static inline void gnrc_netif2_acquire(gnrc_netif2_t *netif) */ static inline void gnrc_netif2_release(gnrc_netif2_t *netif) { - if (netif->ops) { + if (netif && (netif->ops)) { rmutex_unlock(&netif->mutex); } } @@ -175,7 +175,8 @@ ipv6_addr_t *gnrc_netif2_ipv6_addr_best_src(gnrc_netif2_t *netif, bool ll_only); /** - * @brief Gets an interface by an address assigned to it. + * @brief Gets an interface by an address (incl. multicast groups) assigned + * to it. * * @pre `addr != NULL` * diff --git a/sys/include/net/gnrc/netif2/ipv6.h b/sys/include/net/gnrc/netif2/ipv6.h index 37533ea39948d..1f93bb2be215e 100644 --- a/sys/include/net/gnrc/netif2/ipv6.h +++ b/sys/include/net/gnrc/netif2/ipv6.h @@ -182,9 +182,15 @@ typedef struct { * @ref net_gnrc_ipv6_nib "NIB" */ uint32_t retrans_time; -#endif /* MODULE_GNRC_IPV6_NIB */ -#if defined(MODULE_GNRC_IPV6_NIB) || DOXYGEN #if GNRC_IPV6_NIB_CONF_ROUTER || DOXYGEN + /** + * @brief (Advertised) Router lifetime (default 1800). + * + * @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_ROUTER != 0 + */ + uint16_t rtr_ltime; /** * @brief number of unsolicited router advertisements sent * diff --git a/sys/net/gnrc/netif2/gnrc_netif2.c b/sys/net/gnrc/netif2/gnrc_netif2.c index f4360e8c8d4c8..bce3e2d7a2567 100644 --- a/sys/net/gnrc/netif2/gnrc_netif2.c +++ b/sys/net/gnrc/netif2/gnrc_netif2.c @@ -610,6 +610,9 @@ gnrc_netif2_t *gnrc_netif2_get_by_ipv6_addr(const ipv6_addr_t *addr) if (_addr_idx(netif, addr) >= 0) { break; } + if (_group_idx(netif, addr) >= 0) { + break; + } } return netif; } From 5dde4f2c3673cc3a70162b6402daafec677803b7 Mon Sep 17 00:00:00 2001 From: Martine Lenders Date: Tue, 1 Aug 2017 17:13:40 +0200 Subject: [PATCH 21/31] fixup! gnrc_netif2: Introduction of a new GNRC network interface API Exclude tentative addresses in source address selection --- sys/include/net/gnrc/netif2/internal.h | 14 ++++++++++++++ sys/net/gnrc/netif2/gnrc_netif2.c | 4 +++- 2 files changed, 17 insertions(+), 1 deletion(-) diff --git a/sys/include/net/gnrc/netif2/internal.h b/sys/include/net/gnrc/netif2/internal.h index 57d0e4451eaf1..029cc1822b40c 100644 --- a/sys/include/net/gnrc/netif2/internal.h +++ b/sys/include/net/gnrc/netif2/internal.h @@ -123,6 +123,20 @@ void gnrc_netif2_ipv6_addr_remove(gnrc_netif2_t *netif, int gnrc_netif2_ipv6_addr_idx(gnrc_netif2_t *netif, const ipv6_addr_t *addr); +/** + * @brief Get state from address flags + * + * @param[in] netif the network interface + * @param[in] idx index of the address flags + * + * @return the state of the address at @p idx + */ +static inline uint8_t gnrc_netif2_ipv6_addr_get_state(gnrc_netif2_t *netif, + int idx) +{ + return netif->ipv6.addrs_flags[i] & GNRC_NETIF2_IPV6_ADDRS_FLAGS_STATE_MASK; +} + /** * @brief Returns the index of an address in gnrc_netif2_t::ipv6_addrs of @p * netif that matches @p addr best diff --git a/sys/net/gnrc/netif2/gnrc_netif2.c b/sys/net/gnrc/netif2/gnrc_netif2.c index bce3e2d7a2567..28c1e16926b80 100644 --- a/sys/net/gnrc/netif2/gnrc_netif2.c +++ b/sys/net/gnrc/netif2/gnrc_netif2.c @@ -871,7 +871,9 @@ static int _create_candidate_set(const gnrc_netif2_t *netif, /* "In any case, multicast addresses and the unspecified address MUST NOT * be included in a candidate set." */ - if (netif->ipv6.addrs_flags[i] == 0) { + if ((netif->ipv6.addrs_flags[i] == 0) || + (gnrc_netif2_ipv6_addr_get_state(netif) == + GNRC_NETIF2_IPV6_ADDRS_FLAGS_STATE_TENTATIVE)) { continue; } /* Check if we only want link local addresses */ From 59b071d6c32e821681529fa874b03328794dc4b1 Mon Sep 17 00:00:00 2001 From: Martine Lenders Date: Fri, 11 Aug 2017 17:53:09 +0200 Subject: [PATCH 22/31] fixup! gnrc_netif2: Introduction of a new GNRC network interface API --- sys/net/gnrc/netif2/gnrc_netif2.c | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/sys/net/gnrc/netif2/gnrc_netif2.c b/sys/net/gnrc/netif2/gnrc_netif2.c index 28c1e16926b80..0b4e2ce0c26f7 100644 --- a/sys/net/gnrc/netif2/gnrc_netif2.c +++ b/sys/net/gnrc/netif2/gnrc_netif2.c @@ -63,6 +63,7 @@ gnrc_netif2_t *gnrc_netif2_create(char *stack, int stacksize, char priority, netif->dev = netdev; res = thread_create(stack, stacksize, priority, THREAD_CREATE_STACKTEST, _gnrc_netif2_thread, (void *)netif, name); + (void)res; assert(res > 0); return netif; } @@ -513,7 +514,7 @@ int gnrc_netif2_ipv6_addr_add(gnrc_netif2_t *netif, const ipv6_addr_t *addr, ipv6_addr_is_loopback(addr))); assert((pfx_len > 0) && (pfx_len <= 128)); gnrc_netif2_acquire(netif); - if ((flags & GNRC_NETIF2_IPV6_ADDRS_FLAGS_STATE_MASK) == 0) { + if (_get_state(netif) == 0) { flags |= GNRC_NETIF2_IPV6_ADDRS_FLAGS_STATE_TENTATIVE; } for (unsigned i = 0; i < GNRC_NETIF2_IPV6_ADDRS_NUMOF; i++) { @@ -1061,6 +1062,7 @@ static void _init_from_device(gnrc_netif2_t *netif) uint16_t tmp; res = dev->driver->get(dev, NETOPT_DEVICE_TYPE, &tmp, sizeof(tmp)); + (void)res; assert(res == sizeof(tmp)); netif->device_type = (uint8_t)tmp; switch (netif->device_type) { From 4036232105ea113883cb2680ab4fa0b3afcc8fae Mon Sep 17 00:00:00 2001 From: Martine Lenders Date: Mon, 14 Aug 2017 14:03:16 +0200 Subject: [PATCH 23/31] fixup! gnrc_netif2: Introduction of a new GNRC network interface API --- sys/net/gnrc/netif2/gnrc_netif2.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/sys/net/gnrc/netif2/gnrc_netif2.c b/sys/net/gnrc/netif2/gnrc_netif2.c index 0b4e2ce0c26f7..28f653e415dfc 100644 --- a/sys/net/gnrc/netif2/gnrc_netif2.c +++ b/sys/net/gnrc/netif2/gnrc_netif2.c @@ -514,7 +514,7 @@ int gnrc_netif2_ipv6_addr_add(gnrc_netif2_t *netif, const ipv6_addr_t *addr, ipv6_addr_is_loopback(addr))); assert((pfx_len > 0) && (pfx_len <= 128)); gnrc_netif2_acquire(netif); - if (_get_state(netif) == 0) { + if ((flags & GNRC_NETIF2_IPV6_ADDRS_FLAGS_STATE_MASK) == 0) { flags |= GNRC_NETIF2_IPV6_ADDRS_FLAGS_STATE_TENTATIVE; } for (unsigned i = 0; i < GNRC_NETIF2_IPV6_ADDRS_NUMOF; i++) { From 72a659b4c36fbefc220e33cb2376239c721c952e Mon Sep 17 00:00:00 2001 From: Martine Lenders Date: Mon, 14 Aug 2017 16:05:33 +0200 Subject: [PATCH 24/31] fixup! gnrc_netif2: Introduction of a new GNRC network interface API --- sys/include/net/gnrc/netif2/flags.h | 17 +++++++++++++---- 1 file changed, 13 insertions(+), 4 deletions(-) diff --git a/sys/include/net/gnrc/netif2/flags.h b/sys/include/net/gnrc/netif2/flags.h index 8ee6799e3e6be..3a1f4120742c1 100644 --- a/sys/include/net/gnrc/netif2/flags.h +++ b/sys/include/net/gnrc/netif2/flags.h @@ -81,23 +81,32 @@ enum { */ #define GNRC_NETIF2_FLAGS_IPV6_ADV_RETRANS_TIMER (0x00000040U) +/** + * @brief If gnrc_netif2_t::ipv6::aac_mode == GNRC_NETIF2_AAC_DHCP then this + * flag indicates that other configuration information is available via + * DHCPv6 (e.g. DNS-related information) + * + * @see [RFC 4861, section 4.2](https://tools.ietf.org/html/rfc4861#section-4.2) + */ +#define GNRC_NETIF2_FLAGS_IPV6_ADV_O_FLAG (0x00000080U) + /** * @brief This interface uses 6Lo header compression * * @see [RFC 6282](https://tools.ietf.org/html/rfc6282) */ -#define GNRC_NETIF2_FLAGS_6LO_HC (0x00000080U) +#define GNRC_NETIF2_FLAGS_6LO_HC (0x00000100U) /** * @brief This interface acts as a 6Lo border router to the LLN */ -#define GNRC_NETIF2_FLAGS_6LO_ABR (0x00000100U) +#define GNRC_NETIF2_FLAGS_6LO_ABR (0x00000200U) /** * @brief This interface acts as a mesh-under node (route-over topology when * unset) */ -#define GNRC_NETIF2_FLAGS_6LO_MESH (0x00000200U) +#define GNRC_NETIF2_FLAGS_6LO_MESH (0x00000400U) /** * @brief Interface supports 6LoWPAN general header compression @@ -105,7 +114,7 @@ enum { * @attention GHC not implemented yet * @see [RFC 7400, section 3.3](https://tools.ietf.org/html/rfc7400#section-3.3) */ -#define GNRC_NETIF2_FLAGS_6LO_BACKBONE (0x00000400U) +#define GNRC_NETIF2_FLAGS_6LO_BACKBONE (0x00000800U) /** * @brief Mask for @ref gnrc_mac_tx_feedback_t From b690dd307bf200cba36fbaa57281b4346bd5960f Mon Sep 17 00:00:00 2001 From: Martine Lenders Date: Tue, 15 Aug 2017 14:24:49 +0200 Subject: [PATCH 25/31] fixup! gnrc_netif2: Introduction of a new GNRC network interface API Add more ifdefs for ARSM --- sys/include/net/gnrc/netif2/ipv6.h | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/sys/include/net/gnrc/netif2/ipv6.h b/sys/include/net/gnrc/netif2/ipv6.h index 1f93bb2be215e..2c9dbb5b40998 100644 --- a/sys/include/net/gnrc/netif2/ipv6.h +++ b/sys/include/net/gnrc/netif2/ipv6.h @@ -204,13 +204,16 @@ 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" + * @ref net_gnrc_ipv6_nib "NIB" and if + * @ref GNRC_IPV6_NIB_CONF_6LN != 0 */ uint8_t rs_sent; +#endif /** * @brief number of unsolicited neighbor advertisements scheduled * @@ -218,7 +221,7 @@ typedef struct { * @ref net_gnrc_ipv6_nib "NIB" */ uint8_t na_sent; -#endif +#endif /* MODULE_GNRC_IPV6_NIB */ /** * @brief IPv6 auto-address configuration mode From 2620aa084447e819dd18ed545d732ef68b98dcf8 Mon Sep 17 00:00:00 2001 From: Martine Lenders Date: Thu, 17 Aug 2017 14:08:24 +0200 Subject: [PATCH 26/31] fixup! gnrc_netif2: Introduction of a new GNRC network interface API --- sys/include/net/gnrc/netif2/flags.h | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/sys/include/net/gnrc/netif2/flags.h b/sys/include/net/gnrc/netif2/flags.h index 3a1f4120742c1..973e675631240 100644 --- a/sys/include/net/gnrc/netif2/flags.h +++ b/sys/include/net/gnrc/netif2/flags.h @@ -116,6 +116,12 @@ enum { */ #define GNRC_NETIF2_FLAGS_6LO_BACKBONE (0x00000800U) +/** + * @brief Marks if the addresses of the interface were already registered + * to an interface or not + */ +#define GNRC_NETIF2_FLAGS_6LO_ADDRS_REG (0x00001000U) + /** * @brief Mask for @ref gnrc_mac_tx_feedback_t */ From 943aab0dd26e7964f278403c6de3ae1cc408c58a Mon Sep 17 00:00:00 2001 From: Martine Lenders Date: Thu, 17 Aug 2017 19:29:40 +0200 Subject: [PATCH 27/31] fixup! gnrc_netif2: Introduction of a new GNRC network interface API Address @aabadie's comments --- sys/include/net/gnrc/netif2.h | 14 +++++++------- sys/include/net/gnrc/netif2/conf.h | 2 +- sys/include/net/gnrc/netif2/internal.h | 8 ++++---- 3 files changed, 12 insertions(+), 12 deletions(-) diff --git a/sys/include/net/gnrc/netif2.h b/sys/include/net/gnrc/netif2.h index d990b2ec2446e..62e93b0a52649 100644 --- a/sys/include/net/gnrc/netif2.h +++ b/sys/include/net/gnrc/netif2.h @@ -131,7 +131,7 @@ struct gnrc_netif2_ops { * * @return The number of bytes actually sent on success * @return -EBADMSG, if the @ref net_gnrc_netif_hdr in @p pkt is missing - * or of an unexpected format. + * or is in an unexpected format. * @return -ENOTSUP, if sending @p pkt in the given format isn't supported * (e.g. empty payload with Ethernet). * @return Any negative error code reported by gnrc_netif2_t::dev. @@ -143,9 +143,9 @@ struct gnrc_netif2_ops { * * @pre `netif != NULL` * - * @note The function takes the bytes received from via - * netdev_driver_t::recv() from gnrc_netif_t::dev and re-formats it to - * a @ref net_gnrc_pkt "packet" containing a @ref net_gnrc_netif_hdr + * @note The function takes the bytes received via netdev_driver_t::recv() + * from gnrc_netif_t::dev and re-formats it to a + * @ref net_gnrc_pkt "packet" containing a @ref net_gnrc_netif_hdr * and a payload header in receive order. * * @param[in] netif The network interface. @@ -157,7 +157,7 @@ struct gnrc_netif2_ops { gnrc_pktsnip_t *(*recv)(gnrc_netif2_t *netif); /** - * @brief Get an option from the network interface + * @brief Gets an option from the network interface * * Use gnrc_netif2_get_from_netdev() to just get options from * gnrc_netif2_t::dev. @@ -173,9 +173,9 @@ struct gnrc_netif2_ops { int (*get)(gnrc_netif2_t *netif, gnrc_netapi_opt_t *opt); /** - * @brief Get an option from the network interface + * @brief Sets an option from the network interface * - * Use gnrc_netif2_set_from_netdev() to just get options from + * Use gnrc_netif2_set_from_netdev() to just set options from * gnrc_netif2_t::dev. * * @param[in] netif The network interface. diff --git a/sys/include/net/gnrc/netif2/conf.h b/sys/include/net/gnrc/netif2/conf.h index 76e62b5fc679a..1987c87eb793e 100644 --- a/sys/include/net/gnrc/netif2/conf.h +++ b/sys/include/net/gnrc/netif2/conf.h @@ -44,7 +44,7 @@ extern "C" { #endif /** - * @brief Number of multicast addressed needed for @ref net_gnrc_rpl "RPL". + * @brief Number of multicast addresses needed for @ref net_gnrc_rpl "RPL". * * @note Used for calculation of @ref GNRC_NETIF2_IPV6_GROUPS_NUMOF */ diff --git a/sys/include/net/gnrc/netif2/internal.h b/sys/include/net/gnrc/netif2/internal.h index 029cc1822b40c..f7c295a38f524 100644 --- a/sys/include/net/gnrc/netif2/internal.h +++ b/sys/include/net/gnrc/netif2/internal.h @@ -33,7 +33,7 @@ extern "C" { #define NETDEV_MSG_TYPE_EVENT (0x1234) /** - * @brief Acquire exclusive access to the interface + * @brief Acquires exclusive access to the interface * * @param[in] netif the network interface * @@ -47,7 +47,7 @@ static inline void gnrc_netif2_acquire(gnrc_netif2_t *netif) } /** - * @brief Release exclusive access to the interface + * @brief Releases exclusive access to the interface * * @param[in] netif the network interface * @@ -124,7 +124,7 @@ int gnrc_netif2_ipv6_addr_idx(gnrc_netif2_t *netif, const ipv6_addr_t *addr); /** - * @brief Get state from address flags + * @brief Gets state from address flags * * @param[in] netif the network interface * @param[in] idx index of the address flags @@ -262,7 +262,7 @@ int gnrc_netif2_ipv6_group_idx(gnrc_netif2_t *netif, const ipv6_addr_t *addr); /** - * @brief Get interface identifier (IID) of an interface's link-layer address + * @brief Gets interface identifier (IID) of an interface's link-layer address * * @param[in] netif the network interface * @param[out] eui64 the IID From dba8093a619e7bd744200cde747ee17897d6a07a Mon Sep 17 00:00:00 2001 From: Martine Lenders Date: Thu, 17 Aug 2017 20:36:31 +0200 Subject: [PATCH 28/31] fixup! gnrc_netif2: Introduction of a new GNRC network interface API Fix typo --- sys/include/net/gnrc/netif2.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/sys/include/net/gnrc/netif2.h b/sys/include/net/gnrc/netif2.h index 62e93b0a52649..894d3606147ad 100644 --- a/sys/include/net/gnrc/netif2.h +++ b/sys/include/net/gnrc/netif2.h @@ -110,7 +110,7 @@ struct gnrc_netif2_ops { * @param[in] netif The network interface. * * This is called after the default settings were set, right before the - * interface's thread starts receiving messages. It is not necessary lock + * interface's thread starts receiving messages. It is not necessary to lock * the interface's mutex gnrc_netif_t::mutex, since the thread will already * lock it. Leave NULL if you do not need any special initialization. */ From 7412f05f3383e10ebd92f4146c93e06ab582dd06 Mon Sep 17 00:00:00 2001 From: Martine Lenders Date: Fri, 18 Aug 2017 14:54:24 +0200 Subject: [PATCH 29/31] fixup! gnrc_netif2: Introduction of a new GNRC network interface API Some more DEBUG output --- sys/net/gnrc/netif2/gnrc_netif2.c | 17 +++++++++++++++++ 1 file changed, 17 insertions(+) diff --git a/sys/net/gnrc/netif2/gnrc_netif2.c b/sys/net/gnrc/netif2/gnrc_netif2.c index 28f653e415dfc..2755050d0c2e6 100644 --- a/sys/net/gnrc/netif2/gnrc_netif2.c +++ b/sys/net/gnrc/netif2/gnrc_netif2.c @@ -31,6 +31,10 @@ #define ENABLE_DEBUG (0) #include "debug.h" +#if ENABLE_DEBUG +static char addr_str[IPV6_ADDR_MAX_STR_LEN]; +#endif + #define _NETIF_NETAPI_MSG_QUEUE_SIZE (8) static gnrc_netif2_t _netifs[GNRC_NETIF_NUMOF]; @@ -563,6 +567,9 @@ int gnrc_netif2_ipv6_addr_idx(gnrc_netif2_t *netif, int idx; assert((netif != NULL) && (addr != NULL)); + DEBUG("gnrc_netif2: get index of %s from inteface %i\n", + ipv6_addr_to_str(addr_str, addr, sizeof(addr_str)), + netif->pid); gnrc_netif2_acquire(netif); idx = _addr_idx(netif, addr); gnrc_netif2_release(netif); @@ -607,6 +614,8 @@ gnrc_netif2_t *gnrc_netif2_get_by_ipv6_addr(const ipv6_addr_t *addr) { gnrc_netif2_t *netif = NULL; + DEBUG("gnrc_netif2: get interface by IPv6 address %s\n", + ipv6_addr_to_str(addr_str, addr, sizeof(addr_str))); while ((netif = gnrc_netif2_iter(netif))) { if (_addr_idx(netif, addr) >= 0) { break; @@ -1154,7 +1163,11 @@ static void *_gnrc_netif2_thread(void *args) case GNRC_NETAPI_MSG_TYPE_SET: opt = msg.content.ptr; DEBUG("gnrc_netif2: GNRC_NETAPI_MSG_TYPE_SET received. opt=%s\n", +#if MODULE_NETOPT netopt2str(opt->opt)); +#else + opt->opt); +#endif /* set option for device driver */ res = netif->ops->set(netif, opt); DEBUG("gnrc_netif2: response of netif->ops->set(): %i\n", res); @@ -1164,7 +1177,11 @@ static void *_gnrc_netif2_thread(void *args) case GNRC_NETAPI_MSG_TYPE_GET: opt = msg.content.ptr; DEBUG("gnrc_netif2: GNRC_NETAPI_MSG_TYPE_GET received. opt=%s\n", +#if MODULE_NETOPT netopt2str(opt->opt)); +#else + opt->opt); +#endif /* get option from device driver */ res = netif->ops->get(netif, opt); DEBUG("gnrc_netif2: response of netif->ops->get(): %i\n", res); From 6d73c34cfba1620891a00e701e6334df8759288c Mon Sep 17 00:00:00 2001 From: Martine Lenders Date: Fri, 18 Aug 2017 15:14:17 +0200 Subject: [PATCH 30/31] fixup! gnrc_netif2: Introduction of a new GNRC network interface API --- sys/include/net/gnrc/netif2/internal.h | 4 ++-- sys/net/gnrc/netif2/gnrc_netif2.c | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/sys/include/net/gnrc/netif2/internal.h b/sys/include/net/gnrc/netif2/internal.h index f7c295a38f524..28803ed3df067 100644 --- a/sys/include/net/gnrc/netif2/internal.h +++ b/sys/include/net/gnrc/netif2/internal.h @@ -131,10 +131,10 @@ int gnrc_netif2_ipv6_addr_idx(gnrc_netif2_t *netif, * * @return the state of the address at @p idx */ -static inline uint8_t gnrc_netif2_ipv6_addr_get_state(gnrc_netif2_t *netif, +static inline uint8_t gnrc_netif2_ipv6_addr_get_state(const gnrc_netif2_t *netif, int idx) { - return netif->ipv6.addrs_flags[i] & GNRC_NETIF2_IPV6_ADDRS_FLAGS_STATE_MASK; + return netif->ipv6.addrs_flags[idx] & GNRC_NETIF2_IPV6_ADDRS_FLAGS_STATE_MASK; } /** diff --git a/sys/net/gnrc/netif2/gnrc_netif2.c b/sys/net/gnrc/netif2/gnrc_netif2.c index 2755050d0c2e6..4b868e12b8336 100644 --- a/sys/net/gnrc/netif2/gnrc_netif2.c +++ b/sys/net/gnrc/netif2/gnrc_netif2.c @@ -882,7 +882,7 @@ static int _create_candidate_set(const gnrc_netif2_t *netif, * be included in a candidate set." */ if ((netif->ipv6.addrs_flags[i] == 0) || - (gnrc_netif2_ipv6_addr_get_state(netif) == + (gnrc_netif2_ipv6_addr_get_state(netif, i) == GNRC_NETIF2_IPV6_ADDRS_FLAGS_STATE_TENTATIVE)) { continue; } From d53ffd3fe364c731733d341a849751f22f692cd0 Mon Sep 17 00:00:00 2001 From: Martine Lenders Date: Fri, 18 Aug 2017 17:31:48 +0200 Subject: [PATCH 31/31] fixup! gnrc_netif2: Introduction of a new GNRC network interface API --- sys/net/gnrc/netif2/gnrc_netif2.c | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/sys/net/gnrc/netif2/gnrc_netif2.c b/sys/net/gnrc/netif2/gnrc_netif2.c index 4b868e12b8336..50c0552952973 100644 --- a/sys/net/gnrc/netif2/gnrc_netif2.c +++ b/sys/net/gnrc/netif2/gnrc_netif2.c @@ -1162,10 +1162,11 @@ static void *_gnrc_netif2_thread(void *args) break; case GNRC_NETAPI_MSG_TYPE_SET: opt = msg.content.ptr; +#ifdef MODULE_NETOPT DEBUG("gnrc_netif2: GNRC_NETAPI_MSG_TYPE_SET received. opt=%s\n", -#if MODULE_NETOPT netopt2str(opt->opt)); #else + DEBUG("gnrc_netif2: GNRC_NETAPI_MSG_TYPE_SET received. opt=%s\n", opt->opt); #endif /* set option for device driver */ @@ -1176,10 +1177,11 @@ static void *_gnrc_netif2_thread(void *args) break; case GNRC_NETAPI_MSG_TYPE_GET: opt = msg.content.ptr; +#ifdef MODULE_NETOPT DEBUG("gnrc_netif2: GNRC_NETAPI_MSG_TYPE_GET received. opt=%s\n", -#if MODULE_NETOPT netopt2str(opt->opt)); #else + DEBUG("gnrc_netif2: GNRC_NETAPI_MSG_TYPE_GET received. opt=%s\n", opt->opt); #endif /* get option from device driver */