diff --git a/drivers/include/net/netdev.h b/drivers/include/net/netdev.h index 3f9d6d68fea2f44dda7de0f507d0d88eac63fd9b..2d4135b973b23848b19e39fd564e571634b80186 100644 --- a/drivers/include/net/netdev.h +++ b/drivers/include/net/netdev.h @@ -206,6 +206,7 @@ extern "C" { enum { NETDEV_TYPE_UNKNOWN, + NETDEV_TYPE_TEST, NETDEV_TYPE_RAW, NETDEV_TYPE_ETHERNET, NETDEV_TYPE_IEEE802154, diff --git a/sys/net/gnrc/netif/gnrc_netif.c b/sys/net/gnrc/netif/gnrc_netif.c index e226b26e9920d927284c53d52970fc6824d02195..33e6b90f9066259e6d5d0fc9a0ad83d111062c0e 100644 --- a/sys/net/gnrc/netif/gnrc_netif.c +++ b/sys/net/gnrc/netif/gnrc_netif.c @@ -1161,6 +1161,110 @@ static void _configure_netdev(netdev_t *dev) #endif } +#ifdef DEVELHELP +/* checks if a device supports all required options and functions */ +static void _test_options(gnrc_netif_t *netif) +{ + uint8_t dummy_addr[GNRC_NETIF_L2ADDR_MAXLEN] = { 0 }; + ndp_opt_t dummy_opt = { .len = 1U }; + uint64_t tmp64 = 0ULL; + + (void)dummy_addr; + (void)dummy_opt; + (void)tmp64; +#if (GNRC_NETIF_L2ADDR_MAXLEN > 0) + /* check if address was set in _update_l2addr_from_dev() + * (NETOPT_DEVICE_TYPE already tested in _configure_netdev()) and + * if MTU and max. fragment size was set properly by + * gnrc_netif_ipv6_init_mtu() + * all checked types below have link-layer addresses so we don't need to + * check `GNRC_NETIF_FLAGS_HAS_L2ADDR` */ + switch (netif->device_type) { +#ifdef TEST_SUITES + case NETDEV_TYPE_TEST: + /* make no assumptions about test devices */ + break; +#endif + case NETDEV_TYPE_BLE: + case NETDEV_TYPE_ETHERNET: + case NETDEV_TYPE_ESP_NOW: + assert(netif->flags & GNRC_NETIF_FLAGS_HAS_L2ADDR); + assert(ETHERNET_ADDR_LEN == netif->l2addr_len); +#ifdef MODULE_GNRC_IPV6 + switch (netif->device_type) { + case NETDEV_TYPE_BLE: + assert(netif->ipv6.mtu == IPV6_MIN_MTU); + break; + case NETDEV_TYPE_ETHERNET: + assert(netif->ipv6.mtu == ETHERNET_DATA_LEN); + break; + case NETDEV_TYPE_ESP_NOW: + assert(netif->ipv6.mtu <= ETHERNET_DATA_LEN); + } +#endif /* MODULE GNRC_IPV6 */ + break; + case NETDEV_TYPE_IEEE802154: + case NETDEV_TYPE_NRFMIN: { + gnrc_nettype_t tmp; + + /* in case assert() evaluates to NOP */ + (void)tmp; + assert(netif->flags & GNRC_NETIF_FLAGS_HAS_L2ADDR); + assert((IEEE802154_SHORT_ADDRESS_LEN == netif->l2addr_len) || + (IEEE802154_LONG_ADDRESS_LEN == netif->l2addr_len)); + assert(-ENOTSUP != netif->dev->driver->get(netif->dev, NETOPT_PROTO, + &tmp, sizeof(tmp))); +#ifdef MODULE_GNRC_IPV6 +#ifdef MODULE_GNRC_SIXLOWPAN + assert(netif->ipv6.mtu == IPV6_MIN_MTU); + assert(netif->sixlo.max_frag_size > 0); +#else /* MODULE_GNRC_SIXLOWPAN */ + assert(netif->ipv6.mtu < UINT16_MAX); +#endif /* MODULE_GNRC_SIXLOWPAN */ +#endif /* MODULE_GNRC_IPV6 */ +#ifdef MODULE_GNRC_SIXLOWPAN_ND + assert((netif->device_type != NETDEV_TYPE_IEEE802154) || + (-ENOTSUP != netif->dev->driver->get(netif->dev, + NETOPT_ADDRESS_LONG, + &dummy_addr, + sizeof(dummy_addr)))); +#endif /* MODULE_GNRC_SIXLOWPAN_ND */ + break; + } + case NETDEV_TYPE_CC110X: + assert(netif->flags & GNRC_NETIF_FLAGS_HAS_L2ADDR); + assert(1U == netif->l2addr_len); +#ifdef MODULE_GNRC_IPV6 + assert(netif->ipv6.mtu < UINT16_MAX); +#endif /* MODULE_GNRC_IPV6 */ + break; + case NETDEV_TYPE_SLIP: + assert(!(netif->flags & GNRC_NETIF_FLAGS_HAS_L2ADDR)); + assert(0U == netif->l2addr_len); + /* don't check MTU here for now since I'm not sure the current + * one is correct ^^" "*/ + break; + default: + /* device type not supported yet, please amend case above when + * porting new device type */ + assert(false); + } + /* These functions only apply to network devices having link-layers */ + if (netif->flags & GNRC_NETIF_FLAGS_HAS_L2ADDR) { +#ifdef MODULE_GNRC_IPV6 + assert(-ENOTSUP != gnrc_netif_ipv6_get_iid(netif, (eui64_t *)&tmp64)); + assert(-ENOTSUP != gnrc_netif_ndp_addr_len_from_l2ao(netif, + &dummy_opt)); +#endif /* MODULE_GNRC_IPV6 */ +#if GNRC_IPV6_NIB_CONF_6LN + assert(-ENOTSUP != gnrc_netif_ipv6_iid_to_addr(netif, (eui64_t *)&tmp64, + dummy_addr)); +#endif /* GNRC_IPV6_NIB_CONF_6LN */ + } +#endif /* (GNRC_NETIF_L2ADDR_MAXLEN > 0) */ +} +#endif /* DEVELHELP */ + static void *_gnrc_netif_thread(void *args) { gnrc_netapi_opt_t *opt; @@ -1194,6 +1298,9 @@ static void *_gnrc_netif_thread(void *args) } _configure_netdev(dev); _init_from_device(netif); +#ifdef DEVELHELP + _test_options(netif); +#endif netif->cur_hl = GNRC_NETIF_DEFAULT_HL; #ifdef MODULE_GNRC_IPV6_NIB gnrc_ipv6_nib_init_iface(netif); diff --git a/sys/net/gnrc/netif/gnrc_netif_device_type.c b/sys/net/gnrc/netif/gnrc_netif_device_type.c index d63bfe46781252fc4477388e1b194365f96633f2..b4575b2094e3f130b98f760026fc6b5aedaa93b7 100644 --- a/sys/net/gnrc/netif/gnrc_netif_device_type.c +++ b/sys/net/gnrc/netif/gnrc_netif_device_type.c @@ -298,9 +298,11 @@ int gnrc_netif_ndp_addr_len_from_l2ao(gnrc_netif_t *netif, (void)opt; return sizeof(uint8_t); #endif /* MODULE_CC110X */ -#if defined(MODULE_NETDEV_ETH) || defined(MODULE_ESP_NOW) +#if defined(MODULE_NETDEV_ETH) || defined(MODULE_ESP_NOW) || \ + defined(MODULE_NORDIC_SOFTDEVICE_BLE) case NETDEV_TYPE_ETHERNET: case NETDEV_TYPE_ESP_NOW: + case NETDEV_TYPE_BLE: /* see https://tools.ietf.org/html/rfc2464#section-6*/ if (opt->len == 1U) { return ETHERNET_ADDR_LEN; diff --git a/tests/gnrc_ipv6_nib_6ln/mockup_netif.c b/tests/gnrc_ipv6_nib_6ln/mockup_netif.c index 53996d932add432e1a44a28504170498436d7efe..c5eb558fb2c62864a55bee2b2912b3fba2323383 100644 --- a/tests/gnrc_ipv6_nib_6ln/mockup_netif.c +++ b/tests/gnrc_ipv6_nib_6ln/mockup_netif.c @@ -77,6 +77,14 @@ int _get_address_long(netdev_t *dev, void *value, size_t max_len) return sizeof(addr); } +int _get_proto(netdev_t *dev, void *value, size_t max_len) +{ + (void)dev; + assert(max_len == sizeof(gnrc_nettype_t)); + *((gnrc_nettype_t *)value) = GNRC_NETTYPE_SIXLOWPAN; + return sizeof(gnrc_nettype_t); +} + void _tests_init(void) { msg_init_queue(_main_msg_queue, _MSG_QUEUE_SIZE); @@ -89,6 +97,8 @@ void _tests_init(void) _get_src_len); netdev_test_set_get_cb(&_mock_netdev, NETOPT_ADDRESS_LONG, _get_address_long); + netdev_test_set_get_cb(&_mock_netdev, NETOPT_PROTO, + _get_proto); _mock_netif = gnrc_netif_ieee802154_create( _mock_netif_stack, THREAD_STACKSIZE_DEFAULT, GNRC_NETIF_PRIO, "mockup_wpan", &_mock_netdev.netdev.netdev diff --git a/tests/gnrc_ndp/Makefile b/tests/gnrc_ndp/Makefile index 4688899dc931bafab4eecd7798567731ff0aa2d3..259e3b3e0e9ac23c60352fbd4c75eca6282cfdda 100644 --- a/tests/gnrc_ndp/Makefile +++ b/tests/gnrc_ndp/Makefile @@ -1,13 +1,15 @@ include ../Makefile.tests_common BOARD_INSUFFICIENT_MEMORY := arduino-duemilanove arduino-mega2560 arduino-uno \ - chronos nucleo-f031k6 nucleo-f042k6 nucleo-l031k6 \ + chronos nucleo-f030r8 nucleo-f031k6 nucleo-f042k6 \ + nucleo-l031k6 nucleo-l053r8 stm32f0discovery \ telosb waspmote-pro wsn430-v1_3b wsn430-v1_4 USEMODULE += gnrc_ipv6_nib_router USEMODULE += gnrc_ndp USEMODULE += gnrc_netif USEMODULE += embunit +USEMODULE += netdev_ieee802154 USEMODULE += netdev_test CFLAGS += -DGNRC_NETTYPE_NDP=GNRC_NETTYPE_TEST diff --git a/tests/gnrc_ndp/main.c b/tests/gnrc_ndp/main.c index 224f5c8cdde7505dc43310a29a4f1bd77eb21c5b..7355a8c7ae817a0c23db65af3e9e67e78cbee446 100644 --- a/tests/gnrc_ndp/main.c +++ b/tests/gnrc_ndp/main.c @@ -436,6 +436,9 @@ static void test_nbr_sol_send(const ipv6_addr_t *src) gnrc_pktsnip_t *pkt; ndp_nbr_sol_t *nbr_sol; + while (msg_try_receive(&msg) == 1) { + /* empty message queue */ + } TEST_ASSERT_NOT_NULL(test_netif); gnrc_ndp_nbr_sol_send(&test_tgt, test_netif, src, &test_dst, NULL); msg_receive(&msg); @@ -947,45 +950,6 @@ static gnrc_pktsnip_t *_test_netif_recv(gnrc_netif_t *netif) return NULL; } -static int _test_netif_get(gnrc_netif_t *netif, gnrc_netapi_opt_t *opt) -{ - (void)netif; - switch (opt->opt) { - case NETOPT_ADDRESS_LONG: - if (opt->data_len < sizeof(test_src_l2)) { - return -EOVERFLOW; - } - memcpy(opt->data, test_src_l2, sizeof(test_src_l2)); - return sizeof(test_src_l2); - case NETOPT_SRC_LEN: { - uint16_t *val = opt->data; - if (opt->data_len != sizeof(uint16_t)) { - return -EOVERFLOW; - } - *val = sizeof(test_src_l2); - return sizeof(uint16_t); - } - case NETOPT_IPV6_IID: - if (opt->data_len < sizeof(uint64_t)) { - return -EOVERFLOW; - } - memcpy(opt->data, &test_src.u64[1], sizeof(uint64_t)); - return sizeof(uint64_t); - case NETOPT_IS_WIRED: - return 1; - case NETOPT_MAX_PDU_SIZE: { - uint16_t *val = opt->data; - if (opt->data_len != sizeof(uint16_t)) { - return -EOVERFLOW; - } - *val = 100U; - return sizeof(uint16_t); - } - default: - return -ENOTSUP; - } -} - static int _test_netif_set(gnrc_netif_t *netif, const gnrc_netapi_opt_t *opt) { (void)netif; @@ -996,11 +960,43 @@ static int _test_netif_set(gnrc_netif_t *netif, const gnrc_netapi_opt_t *opt) static const gnrc_netif_ops_t _test_netif_ops = { .send = _test_netif_send, .recv = _test_netif_recv, - .get = _test_netif_get, + .get = gnrc_netif_get_from_netdev, .set = _test_netif_set, }; -int _netdev_test_device_type_get(netdev_t *dev, void *value, size_t max_len) +static int _netdev_test_address_long(netdev_t *dev, void *value, size_t max_len) +{ + (void)dev; + assert(max_len >= sizeof(test_src_l2)); + memcpy(value, test_src_l2, sizeof(test_src_l2)); + return sizeof(test_src_l2); +} + +static int _netdev_test_proto(netdev_t *dev, void *value, size_t max_len) +{ + (void)dev; + assert(max_len == sizeof(gnrc_nettype_t)); + *((gnrc_nettype_t *)value) = GNRC_NETTYPE_UNDEF; + return sizeof(gnrc_nettype_t); +} + +static int _netdev_test_src_len(netdev_t *dev, void *value, size_t max_len) +{ + (void)dev; + assert(max_len == sizeof(uint16_t)); + *((uint16_t *)value) = sizeof(test_src_l2); + return sizeof(uint16_t); +} + +static int _netdev_test_max_pdu_size(netdev_t *dev, void *value, size_t max_len) +{ + (void)dev; + assert(max_len == sizeof(uint16_t)); + *((uint16_t *)value) = 100U; + return sizeof(uint16_t); +} + +static int _netdev_test_device_type(netdev_t *dev, void *value, size_t max_len) { (void)dev; assert(max_len == sizeof(uint16_t)); @@ -1015,10 +1011,16 @@ static void init_pkt_handler(void) sched_active_pid); gnrc_netreg_register(GNRC_NETTYPE_NDP, &netreg_entry); netdev_test_setup(&dev, NULL); - netdev_test_set_get_cb(&dev, NETOPT_DEVICE_TYPE, _netdev_test_device_type_get); + netdev_test_set_get_cb(&dev, NETOPT_ADDRESS_LONG, + _netdev_test_address_long); + netdev_test_set_get_cb(&dev, NETOPT_PROTO, _netdev_test_proto); + netdev_test_set_get_cb(&dev, NETOPT_SRC_LEN, _netdev_test_src_len); + netdev_test_set_get_cb(&dev, NETOPT_MAX_PDU_SIZE, + _netdev_test_max_pdu_size); + netdev_test_set_get_cb(&dev, NETOPT_DEVICE_TYPE, _netdev_test_device_type); test_netif = gnrc_netif_create(test_netif_stack, sizeof(test_netif_stack), GNRC_NETIF_PRIO, "test-netif", - &dev.netdev, &_test_netif_ops); + &dev.netdev.netdev, &_test_netif_ops); TEST_ASSERT_MESSAGE(test_netif != NULL, "Unable to start test interface"); memcpy(&test_netif->ipv6.addrs[0], &test_src, diff --git a/tests/gnrc_netif/common.c b/tests/gnrc_netif/common.c index 629dc58fdde08c227cea000c2e94f1ec39da692c..6e84f62ee3abcdd482dcd50e45751a4032ef4e9b 100644 --- a/tests/gnrc_netif/common.c +++ b/tests/gnrc_netif/common.c @@ -124,11 +124,19 @@ static int _get_netdev_device_type(netdev_t *netdev, void *value, size_t max_len *((uint16_t *)value) = NETDEV_TYPE_IEEE802154; } else { - *((uint16_t *)value) = NETDEV_TYPE_UNKNOWN; + *((uint16_t *)value) = NETDEV_TYPE_TEST; } return sizeof(uint16_t); } +static int _get_netdev_proto(netdev_t *dev, void *value, size_t max_len) +{ + assert(dev == ieee802154_dev); + assert(max_len == sizeof(gnrc_nettype_t)); + *((gnrc_nettype_t *)value) = GNRC_NETTYPE_UNDEF; + return sizeof(gnrc_nettype_t); +} + static int _get_netdev_max_packet_size(netdev_t *netdev, void *value, size_t max_len) { assert(max_len == sizeof(uint16_t)); @@ -166,6 +174,8 @@ void _tests_init(void) netdev_test_set_isr_cb((netdev_test_t *)ieee802154_dev, _netdev_isr); netdev_test_set_get_cb((netdev_test_t *)ieee802154_dev, NETOPT_DEVICE_TYPE, _get_netdev_device_type); + netdev_test_set_get_cb((netdev_test_t *)ieee802154_dev, NETOPT_PROTO, + _get_netdev_proto); netdev_test_set_get_cb((netdev_test_t *)ieee802154_dev, NETOPT_MAX_PDU_SIZE, _get_netdev_max_packet_size); for (intptr_t i = SPECIAL_DEVS; i < GNRC_NETIF_NUMOF; i++) { diff --git a/tests/gnrc_netif/main.c b/tests/gnrc_netif/main.c index 07ed7fc28d31f9c25f61108f986de49ff723249e..aa4b557a8792a1a0a04006741f8f6d1a249b6af1 100644 --- a/tests/gnrc_netif/main.c +++ b/tests/gnrc_netif/main.c @@ -163,7 +163,7 @@ static void test_creation(void) TEST_ASSERT_NOT_NULL(netifs[i]->ops); TEST_ASSERT_NOT_NULL(netifs[i]->dev); TEST_ASSERT_EQUAL_INT(GNRC_NETIF_DEFAULT_HL, netifs[i]->cur_hl); - TEST_ASSERT_EQUAL_INT(NETDEV_TYPE_UNKNOWN, netifs[i]->device_type); + TEST_ASSERT_EQUAL_INT(NETDEV_TYPE_TEST, netifs[i]->device_type); TEST_ASSERT(netifs[i]->pid > KERNEL_PID_UNDEF); TEST_ASSERT(thread_has_msg_queue(sched_threads[netifs[i]->pid])); TEST_ASSERT_EQUAL_INT(i + SPECIAL_DEVS + 1, gnrc_netif_numof()); diff --git a/tests/gnrc_sixlowpan/main.c b/tests/gnrc_sixlowpan/main.c index 171d0dd624b7dbfcaa23ac108339e823e1680557..6a327333a83fd2cc82c7c2ed38d4565ae3fbc7af 100644 --- a/tests/gnrc_sixlowpan/main.c +++ b/tests/gnrc_sixlowpan/main.c @@ -57,6 +57,15 @@ static int _get_netdev_device_type(netdev_t *netdev, void *value, size_t max_len return sizeof(uint16_t); } +static int _get_netdev_proto(netdev_t *netdev, void *value, size_t max_len) +{ + assert(max_len == sizeof(gnrc_nettype_t)); + (void)netdev; + + *((gnrc_nettype_t *)value) = GNRC_NETTYPE_SIXLOWPAN; + return sizeof(gnrc_nettype_t); +} + static int _get_netdev_max_packet_size(netdev_t *netdev, void *value, size_t max_len) { @@ -91,6 +100,8 @@ static void _init_interface(void) netdev_test_setup(&_ieee802154_dev, NULL); netdev_test_set_get_cb(&_ieee802154_dev, NETOPT_DEVICE_TYPE, _get_netdev_device_type); + netdev_test_set_get_cb(&_ieee802154_dev, NETOPT_PROTO, + _get_netdev_proto); netdev_test_set_get_cb(&_ieee802154_dev, NETOPT_MAX_PDU_SIZE, _get_netdev_max_packet_size); netdev_test_set_get_cb(&_ieee802154_dev, NETOPT_SRC_LEN,