1
0
mirror of https://github.com/RIOT-OS/RIOT.git synced 2025-12-25 06:23:53 +01:00

Merge pull request #14770 from benpicco/netif_addr_to_str

net/netif: move gnrc_netif_addr_to/from_str() to netif
This commit is contained in:
benpicco 2020-08-25 18:52:55 +02:00 committed by GitHub
commit 2eb6d752df
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
9 changed files with 442 additions and 82 deletions

View File

@ -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.

View File

@ -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

View File

@ -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)) {

View File

@ -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 <m.lenders@fu-berlin.de>
*/
#include <assert.h>
#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;
}
/** @} */

7
tests/netif/Makefile Normal file
View File

@ -0,0 +1,7 @@
include ../Makefile.tests_common
USEMODULE += embunit
USEMODULE += netif
USEMODULE += od
include $(RIOTBASE)/Makefile.include

57
tests/netif/Makefile.ci Normal file
View File

@ -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 \
#

109
tests/netif/common.h Normal file
View File

@ -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 <m.lenders@fu-berlin.de>
*/
#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 */
/** @} */

101
tests/netif/main.c Normal file
View File

@ -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 <m.lenders@fu-berlin.de>
*
* @}
*/
#include <errno.h>
#include <stdio.h>
#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;
}

20
tests/netif/tests/01-run.py Executable file
View File

@ -0,0 +1,20 @@
#!/usr/bin/env python3
# Copyright (C) 2016 Kaspar Schleiser <kaspar@schleiser.de>
# Copyright (C) 2016 Takuo Yonezawa <Yonezawa-T2@mail.dnp.co.jp>
#
# 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))