diff --git a/sys/include/net/gnrc/netif.h b/sys/include/net/gnrc/netif.h index 633821a3a7..63bb39fb52 100644 --- a/sys/include/net/gnrc/netif.h +++ b/sys/include/net/gnrc/netif.h @@ -557,6 +557,8 @@ int gnrc_netif_set_from_netdev(gnrc_netif_t *netif, /** * @brief Converts a hardware address to a human readable string. * + * @note Compatibility wrapper for @see netif_addr_to_str + * * @details The format will be like `xx:xx:xx:xx` where `xx` are the bytes * of @p addr in hexadecimal representation. * @@ -570,12 +572,17 @@ int gnrc_netif_set_from_netdev(gnrc_netif_t *netif, * * @return @p out. */ -char *gnrc_netif_addr_to_str(const uint8_t *addr, size_t addr_len, char *out); +static inline char *gnrc_netif_addr_to_str(const uint8_t *addr, size_t addr_len, char *out) +{ + return netif_addr_to_str(addr, addr_len, out); +} /** * @brief Parses a string of colon-separated hexadecimals to a hardware * address. * + * @note Compatibility wrapper for @see netif_addr_from_str + * * @details The input format must be like `xx:xx:xx:xx` where `xx` will be the * bytes of @p addr in hexadecimal representation. * @@ -590,7 +597,10 @@ char *gnrc_netif_addr_to_str(const uint8_t *addr, size_t addr_len, char *out); * @return Actual length of @p out on success. * @return 0, on failure. */ -size_t gnrc_netif_addr_from_str(const char *str, uint8_t *out); +static inline size_t gnrc_netif_addr_from_str(const char *str, uint8_t *out) +{ + return netif_addr_from_str(str, out); +} /** * @brief Send a GNRC packet via a given @ref gnrc_netif_t interface. diff --git a/sys/include/net/netif.h b/sys/include/net/netif.h index a3fddc6fb3..cb81463e39 100644 --- a/sys/include/net/netif.h +++ b/sys/include/net/netif.h @@ -176,6 +176,44 @@ int netif_set_opt(netif_t *netif, netopt_t opt, uint16_t context, */ int netif_register(netif_t *netif); +/** + * @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 *netif_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_NETIF_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_NETIF_L2ADDR_MAXLEN bytes allocated. + * + * @return Actual length of @p out on success. + * @return 0, on failure. + */ +size_t netif_addr_from_str(const char *str, uint8_t *out); + #ifdef __cplusplus } #endif diff --git a/sys/net/gnrc/netif/gnrc_netif.c b/sys/net/gnrc/netif/gnrc_netif.c index c7115143ff..184ba17962 100644 --- a/sys/net/gnrc/netif/gnrc_netif.c +++ b/sys/net/gnrc/netif/gnrc_netif.c @@ -408,86 +408,6 @@ gnrc_netif_t *gnrc_netif_get_by_pid(kernel_pid_t pid) return NULL; } -char *gnrc_netif_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 += fmt_byte_hex((out), *(addr++)); - *(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_netif_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; -} - void gnrc_netif_acquire(gnrc_netif_t *netif) { if (netif && (netif->ops)) { diff --git a/sys/net/netif/netif_util.c b/sys/net/netif/netif_util.c new file mode 100644 index 0000000000..af6bf0eac1 --- /dev/null +++ b/sys/net/netif/netif_util.c @@ -0,0 +1,98 @@ +/* + * 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 "fmt.h" + +char *netif_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 += fmt_byte_hex((out), *(addr++)); + *(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 netif_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; +} +/** @} */ diff --git a/tests/netif/Makefile b/tests/netif/Makefile new file mode 100644 index 0000000000..73f001a0aa --- /dev/null +++ b/tests/netif/Makefile @@ -0,0 +1,7 @@ +include ../Makefile.tests_common + +USEMODULE += embunit +USEMODULE += netif +USEMODULE += od + +include $(RIOTBASE)/Makefile.include diff --git a/tests/netif/Makefile.ci b/tests/netif/Makefile.ci new file mode 100644 index 0000000000..75436958ec --- /dev/null +++ b/tests/netif/Makefile.ci @@ -0,0 +1,57 @@ +BOARD_INSUFFICIENT_MEMORY := \ + airfy-beacon \ + arduino-duemilanove \ + arduino-leonardo \ + arduino-mega2560 \ + arduino-nano \ + arduino-uno \ + atmega1284p \ + atmega328p \ + b-l072z-lrwan1 \ + blackpill \ + blackpill-128kib \ + bluepill \ + bluepill-128kib \ + calliope-mini \ + cc2650-launchpad \ + cc2650stk \ + derfmega128 \ + hifive1 \ + hifive1b \ + i-nucleo-lrwan1 \ + im880b \ + lsn50 \ + maple-mini \ + mega-xplained \ + microbit \ + microduino-corerf \ + msb-430 \ + msb-430h \ + nrf51dk \ + nrf51dongle \ + nrf6310 \ + nucleo-f030r8 \ + nucleo-f031k6 \ + nucleo-f042k6 \ + nucleo-f070rb \ + nucleo-f072rb \ + nucleo-f103rb \ + nucleo-f302r8 \ + nucleo-f303k8 \ + nucleo-f334r8 \ + nucleo-l031k6 \ + nucleo-l053r8 \ + nucleo-l073rz \ + olimexino-stm32 \ + opencm904 \ + saml10-xpro \ + saml11-xpro \ + spark-core \ + stm32f030f4-demo \ + stm32f0discovery \ + stm32l0538-disco \ + telosb \ + waspmote-pro \ + yunjia-nrf51822 \ + z1 \ + # diff --git a/tests/netif/common.h b/tests/netif/common.h new file mode 100644 index 0000000000..34ac806aad --- /dev/null +++ b/tests/netif/common.h @@ -0,0 +1,109 @@ +/* + * 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/netif.h" + +#ifdef __cplusplus +extern "C" { +#endif + +#define NETIF_NUMOF (4) +#define SPECIAL_DEVS (2) +#define DEFAULT_DEVS_NUMOF (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 ULA1 (0xfdU) +#define ULA2 (0x01U) +#define ULA3 (0x0dU) +#define ULA4 (0xb8U) +#define ULA5 (0x00U) +#define ULA6 (0x00U) +#define ULA7 (0x5aU) +#define ULA8 (0x1aU) + +#define TEST_IEEE802154_MAX_FRAG_SIZE (102) + +#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 IEEE802154_LONG_SRC { LA1, LA2, LA3, LA4, LA5, LA6, LA7, LA8 } +#define IEEE802154_SHORT_SRC { LA7, LA8 } +#define IEEE802154_IPV6_LL { LP1, LP2, LP3, LP4, LP5, LP6, LP7, LP8, \ + LA1 ^ 0x2, LA2, LA3, LA4, LA5, LA6, LA7, LA8 } +#define IEEE802154_IPV6_G { GP1, GP2, GP3, GP4, GP5, GP6, GP7, GP8, \ + LA1 ^ 0x2, LA2, LA3, LA4, LA5, 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_ULA { ULA1, ULA2, ULA3, ULA4, ULA5, ULA6, ULA7, ULA8, \ + 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 *ieee802154_dev; +extern netdev_t *devs[DEFAULT_DEVS_NUMOF]; + +void _tests_init(void); +void _test_trigger_recv(gnrc_netif_t *netif, const uint8_t *data, + size_t data_len); + +#ifdef __cplusplus +} +#endif + +#endif /* COMMON_H */ +/** @} */ diff --git a/tests/netif/main.c b/tests/netif/main.c new file mode 100644 index 0000000000..6eb64deffb --- /dev/null +++ b/tests/netif/main.c @@ -0,0 +1,101 @@ +/* + * 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 common netif functions + * + * @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/netif.h" +#include "test_utils/expect.h" + +static void test_netif_addr_to_str(void) +{ + static const uint8_t ethernet_l2addr[] = ETHERNET_SRC; + static const uint8_t ieee802154_l2addr_long[] = IEEE802154_LONG_SRC; + static const uint8_t ieee802154_l2addr_short[] = IEEE802154_SHORT_SRC; + static const uint8_t netif0_l2addr[] = NETIF0_SRC; + char out[sizeof(netif0_l2addr) * 3]; + + TEST_ASSERT(out == netif_addr_to_str(NULL, 0, out)); + TEST_ASSERT_EQUAL_STRING("", &out[0]); + TEST_ASSERT(out == netif_addr_to_str(ethernet_l2addr, + sizeof(ethernet_l2addr), out)); + TEST_ASSERT_EQUAL_STRING("3E:E6:B5:22:FD:0A", &out[0]); + TEST_ASSERT(out == netif_addr_to_str(ieee802154_l2addr_long, + sizeof(ieee802154_l2addr_long), + out)); + TEST_ASSERT_EQUAL_STRING("3E:E6:B5:0F:19:22:FD:0A", &out[0]); + TEST_ASSERT(out == netif_addr_to_str(ieee802154_l2addr_short, + sizeof(ieee802154_l2addr_short), + out)); + TEST_ASSERT_EQUAL_STRING("FD:0A", &out[0]); + TEST_ASSERT(out == netif_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_netif_addr_from_str(void) +{ + static const uint8_t ethernet_l2addr[] = ETHERNET_SRC; + static const uint8_t ieee802154_l2addr_long[] = IEEE802154_LONG_SRC; + static const uint8_t ieee802154_l2addr_short[] = IEEE802154_SHORT_SRC; + uint8_t out[GNRC_NETIF_L2ADDR_MAXLEN]; + + TEST_ASSERT_EQUAL_INT(0, netif_addr_from_str("", out)); + TEST_ASSERT_EQUAL_INT(sizeof(ethernet_l2addr), + netif_addr_from_str("3E:E6:B5:22:FD:0A", out)); + TEST_ASSERT_EQUAL_INT(0, memcmp(ethernet_l2addr, out, + sizeof(ethernet_l2addr))); + TEST_ASSERT_EQUAL_INT(sizeof(ieee802154_l2addr_long), + netif_addr_from_str("3E:E6:B5:0F:19:22:FD:0A", + out)); + TEST_ASSERT_EQUAL_INT(0, memcmp(ieee802154_l2addr_long, out, + sizeof(ieee802154_l2addr_long))); + TEST_ASSERT_EQUAL_INT(sizeof(ieee802154_l2addr_short), + netif_addr_from_str("FD:0A", out)); + TEST_ASSERT_EQUAL_INT(0, memcmp(ieee802154_l2addr_short, out, + sizeof(ieee802154_l2addr_short))); +} + +static Test *embunit_tests_netif(void) +{ + EMB_UNIT_TESTFIXTURES(fixtures) { + new_TestFixture(test_netif_addr_to_str), + new_TestFixture(test_netif_addr_from_str), + /* only add tests not involving output here */ + }; + EMB_UNIT_TESTCALLER(tests, NULL, NULL, fixtures); + + return (Test *)&tests; +} + +int main(void) +{ + TESTS_START(); + TESTS_RUN(embunit_tests_netif()); + TESTS_END(); + + return 0; +} diff --git a/tests/netif/tests/01-run.py b/tests/netif/tests/01-run.py new file mode 100755 index 0000000000..dbc82ccd83 --- /dev/null +++ b/tests/netif/tests/01-run.py @@ -0,0 +1,20 @@ +#!/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 sys +from testrunner import run, check_unittests + + +def testfunc(child): + # embUnit tests + check_unittests(child) + + +if __name__ == "__main__": + sys.exit(run(testfunc, timeout=1, traceback=True))