Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add support for network interface user friendly name #61876

Merged
merged 4 commits into from Aug 31, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
48 changes: 48 additions & 0 deletions include/zephyr/net/net_if.h
Expand Up @@ -424,6 +424,14 @@ struct net_if_config {
*/
sys_slist_t virtual_interfaces;
#endif /* CONFIG_NET_L2_VIRTUAL */

#if defined(CONFIG_NET_INTERFACE_NAME)
/**
* Network interface can have a name and it is possible
* to search a network interface using this name.
*/
char name[CONFIG_NET_INTERFACE_NAME_LEN + 1];
#endif
};

/**
Expand Down Expand Up @@ -2575,6 +2583,46 @@ bool net_if_is_wifi(struct net_if *iface);
*/
struct net_if *net_if_get_first_wifi(void);

/**
* @brief Get network interface name.
*
* @details If interface name support is not enabled, empty string is returned.
*
* @param iface Pointer to network interface
* @param buf User supplied buffer
jukkar marked this conversation as resolved.
Show resolved Hide resolved
* @param len Length of the user supplied buffer
*
* @return Length of the interface name copied to buf,
* -EINVAL if invalid parameters,
* -ERANGE if name cannot be copied to the user supplied buffer,
* -ENOTSUP if interface name support is disabled,
*/
int net_if_get_name(struct net_if *iface, char *buf, int len);

/**
* @brief Set network interface name.
*
* @details Normally this function is not needed to call as the system
* will automatically assign a name to the network interface.
*
* @param iface Pointer to network interface
* @param buf User supplied name
*
* @return 0 name is set correctly
* -ENOTSUP interface name support is disabled
* -EINVAL if invalid parameters are given,
* -ENAMETOOLONG if name is too long
*/
int net_if_set_name(struct net_if *iface, const char *buf);

/**
* @brief Get interface index according to its name
*
* @param name Name of the network interface
*
* @return Interface index
*/
int net_if_get_by_name(const char *name);

/** @cond INTERNAL_HIDDEN */
struct net_if_api {
Expand Down
15 changes: 15 additions & 0 deletions subsys/net/ip/Kconfig
Expand Up @@ -859,6 +859,21 @@ config NET_DEFAULT_IF_WIFI

endchoice

config NET_INTERFACE_NAME
bool "Allow setting a name to a network interface"
default y
help
Allow application to set a name to the network interface in order
to simplify network interface management.

config NET_INTERFACE_NAME_LEN
int "Network interface max name length"
default 8
jukkar marked this conversation as resolved.
Show resolved Hide resolved
range 1 15
depends on NET_INTERFACE_NAME
help
Maximum length of the network interface name.

config NET_PKT_TIMESTAMP
bool "Network packet timestamp support"
help
Expand Down
146 changes: 146 additions & 0 deletions subsys/net/ip/net_if.c
@@ -1,5 +1,6 @@
/*
* Copyright (c) 2016 Intel Corporation.
* Copyright (c) 2023 Nordic Semiconductor ASA
*
* SPDX-License-Identifier: Apache-2.0
*/
Expand Down Expand Up @@ -4732,6 +4733,144 @@ struct net_if *net_if_get_first_wifi(void)
return NULL;
}

int net_if_get_name(struct net_if *iface, char *buf, int len)
{
#if defined(CONFIG_NET_INTERFACE_NAME)
int name_len;

if (iface == NULL || buf == NULL || len <= 0) {
return -EINVAL;
}

name_len = strlen(net_if_get_config(iface)->name);
if (name_len >= len) {
return -ERANGE;
}

strncpy(buf, net_if_get_config(iface)->name, name_len);
jukkar marked this conversation as resolved.
Show resolved Hide resolved

return name_len;
#else
return -ENOTSUP;
#endif
}

int net_if_set_name(struct net_if *iface, const char *buf)
{
#if defined(CONFIG_NET_INTERFACE_NAME)
int name_len;

if (iface == NULL || buf == NULL) {
return -EINVAL;
}

name_len = strlen(buf);
if (name_len >= sizeof(iface->config.name)) {
return -ENAMETOOLONG;
}

strncpy(net_if_get_config(iface)->name, buf, name_len);
jukkar marked this conversation as resolved.
Show resolved Hide resolved

return 0;
#else
return -ENOTSUP;
#endif
}

int net_if_get_by_name(const char *name)
{
#if defined(CONFIG_NET_INTERFACE_NAME)
if (name == NULL) {
return -EINVAL;
}

STRUCT_SECTION_FOREACH(net_if, iface) {
if (strncmp(net_if_get_config(iface)->name, name, strlen(name)) == 0) {
return net_if_get_by_iface(iface);
}
}

return -ENOENT;
#else
return -ENOTSUP;
#endif
}

#if defined(CONFIG_NET_INTERFACE_NAME)
static void set_default_name(struct net_if *iface)
{
char name[CONFIG_NET_INTERFACE_NAME_LEN + 1] = { 0 };
int ret;

if (net_if_is_wifi(iface)) {
static int count;

snprintk(name, sizeof(name) - 1, "wlan%d", count++);

} else if (IS_ENABLED(CONFIG_NET_L2_ETHERNET)) {
#if defined(CONFIG_NET_L2_ETHERNET)
if (net_if_l2(iface) == &NET_L2_GET_NAME(ETHERNET)) {
static int count;

snprintk(name, sizeof(name) - 1, "eth%d", count++);
}
#endif /* CONFIG_NET_L2_ETHERNET */
}

if (IS_ENABLED(CONFIG_NET_L2_IEEE802154)) {
#if defined(CONFIG_NET_L2_IEEE802154)
if (net_if_l2(iface) == &NET_L2_GET_NAME(IEEE802154)) {
static int count;

snprintk(name, sizeof(name) - 1, "ieee%d", count++);
}
#endif /* CONFIG_NET_L2_IEEE802154 */
}

if (IS_ENABLED(CONFIG_NET_L2_DUMMY)) {
#if defined(CONFIG_NET_L2_DUMMY)
if (net_if_l2(iface) == &NET_L2_GET_NAME(DUMMY)) {
static int count;

snprintk(name, sizeof(name) - 1, "dummy%d", count++);
}
#endif /* CONFIG_NET_L2_DUMMY */
}

if (IS_ENABLED(CONFIG_NET_L2_CANBUS_RAW)) {
#if defined(CONFIG_NET_L2_CANBUS_RAW)
if (net_if_l2(iface) == &NET_L2_GET_NAME(CANBUS_RAW)) {
static int count;

snprintk(name, sizeof(name) - 1, "can%d", count++);
}
#endif /* CONFIG_NET_L2_CANBUS_RAW */
}

if (IS_ENABLED(CONFIG_NET_L2_PPP)) {
#if defined(CONFIG_NET_L2_PPP)
if (net_if_l2(iface) == &NET_L2_GET_NAME(PPP)) {
static int count;

snprintk(name, sizeof(name) - 1, "ppp%d", count++);
}
#endif /* CONFIG_NET_L2_PPP */
}

if (name[0] == '\0') {
static int count;

snprintk(name, sizeof(name) - 1, "net%d", count++);
}

ret = net_if_set_name(iface, name);
if (ret < 0) {
NET_WARN("Cannot set default name for interface %d (%p) (%d)",
net_if_get_by_iface(iface), iface, ret);
}
}
#endif /* CONFIG_NET_INTERFACE_NAME */

void net_if_init(void)
{
int if_count = 0;
Expand All @@ -4745,6 +4884,13 @@ void net_if_init(void)
STRUCT_SECTION_FOREACH(net_if, iface) {
init_iface(iface);
if_count++;

#if defined(CONFIG_NET_INTERFACE_NAME)
memset(net_if_get_config(iface)->name, 0,
sizeof(iface->config.name));

set_default_name(iface);
#endif
}

if (if_count == 0) {
Expand Down
14 changes: 14 additions & 0 deletions subsys/net/ip/net_shell.c
Expand Up @@ -6,6 +6,7 @@

/*
* Copyright (c) 2016 Intel Corporation
* Copyright (c) 2023 Nordic Semiconductor ASA
*
* SPDX-License-Identifier: Apache-2.0
*/
Expand Down Expand Up @@ -378,8 +379,21 @@ static void iface_cb(struct net_if *iface, void *user_data)
return;
}

#if defined(CONFIG_NET_INTERFACE_NAME)
char ifname[CONFIG_NET_INTERFACE_NAME_LEN + 1] = { 0 };
int ret_name;

ret_name = net_if_get_name(iface, ifname, sizeof(ifname) - 1);
if (ret_name < 1 || ifname[0] == '\0') {
snprintk(ifname, sizeof(ifname), "?");
}

PR("\nInterface %s (%p) (%s) [%d]\n", ifname, iface, iface2str(iface, &extra),
net_if_get_by_iface(iface));
#else
PR("\nInterface %p (%s) [%d]\n", iface, iface2str(iface, &extra),
net_if_get_by_iface(iface));
#endif
PR("===========================%s\n", extra);

if (!net_if_is_up(iface)) {
Expand Down
37 changes: 27 additions & 10 deletions subsys/net/lib/sockets/socket_dispatcher.c
Expand Up @@ -318,24 +318,41 @@ static int sock_dispatch_setsockopt_vmeth(void *obj, int level, int optname,

if ((level == SOL_SOCKET) && (optname == SO_BINDTODEVICE)) {
struct net_if *iface;
const struct device *dev;
const struct ifreq *ifreq = optval;

if ((ifreq == NULL) || (optlen != sizeof(*ifreq))) {
errno = EINVAL;
return -1;
}

dev = device_get_binding(ifreq->ifr_name);
if (dev == NULL) {
errno = ENODEV;
return -1;
}
if (IS_ENABLED(CONFIG_NET_INTERFACE_NAME)) {
int ret;

iface = net_if_lookup_by_dev(dev);
if (iface == NULL) {
errno = ENODEV;
return -1;
ret = net_if_get_by_name(ifreq->ifr_name);
if (ret < 0) {
errno = -ret;
return -1;
}

iface = net_if_get_by_index(ret);
if (iface == NULL) {
errno = ENODEV;
return -1;
}
} else {
const struct device *dev;

dev = device_get_binding(ifreq->ifr_name);
if (dev == NULL) {
errno = ENODEV;
return -1;
}

iface = net_if_lookup_by_dev(dev);
if (iface == NULL) {
errno = ENODEV;
return -1;
}
}

if (net_if_socket_offload(iface) != NULL) {
Expand Down
35 changes: 25 additions & 10 deletions subsys/net/lib/sockets/sockets.c
Expand Up @@ -2265,7 +2265,6 @@ int zsock_setsockopt_ctx(struct net_context *ctx, int level, int optname,

case SO_BINDTODEVICE: {
struct net_if *iface;
const struct device *dev;
const struct ifreq *ifreq = optval;

if (net_context_get_family(ctx) != AF_INET &&
Expand All @@ -2288,16 +2287,32 @@ int zsock_setsockopt_ctx(struct net_context *ctx, int level, int optname,
return -1;
}

dev = device_get_binding(ifreq->ifr_name);
if (dev == NULL) {
errno = ENODEV;
return -1;
}
if (IS_ENABLED(CONFIG_NET_INTERFACE_NAME)) {
ret = net_if_get_by_name(ifreq->ifr_name);
if (ret < 0) {
errno = -ret;
return -1;
}

iface = net_if_lookup_by_dev(dev);
if (iface == NULL) {
errno = ENODEV;
return -1;
iface = net_if_get_by_index(ret);
if (iface == NULL) {
errno = ENODEV;
return -1;
}
} else {
const struct device *dev;

dev = device_get_binding(ifreq->ifr_name);
if (dev == NULL) {
errno = ENODEV;
return -1;
}

iface = net_if_lookup_by_dev(dev);
if (iface == NULL) {
errno = ENODEV;
return -1;
}
}

net_context_set_iface(ctx, iface);
Expand Down