zephyr/subsys/net/l2/ethernet/bridge_shell.c

201 lines
4.3 KiB
C

/*
* Copyright (c) 2021 BayLibre SAS
*
* SPDX-License-Identifier: Apache-2.0
*/
#include <stdlib.h>
#include <zephyr/shell/shell.h>
#include <zephyr/net/net_if.h>
#include <zephyr/net/ethernet.h>
#include <zephyr/net/ethernet_bridge.h>
#include <zephyr/sys/slist.h>
static int get_idx(const struct shell *sh, char *index_str)
{
char *endptr;
int idx;
idx = strtol(index_str, &endptr, 10);
if (*endptr != '\0') {
shell_warn(sh, "Invalid index %s\n", index_str);
return -ENOENT;
}
return idx;
}
static int cmd_bridge_addif(const struct shell *sh, size_t argc, char *argv[])
{
int ret = 0, br_idx, if_idx;
struct net_if *iface;
struct net_if *br;
br_idx = get_idx(sh, argv[1]);
if (br_idx < 0) {
return br_idx;
}
br = eth_bridge_get_by_index(br_idx);
if (br == NULL) {
shell_warn(sh, "Bridge %d not found\n", br_idx);
return -ENOENT;
}
for (int i = 2; i < argc; i++) {
if_idx = get_idx(sh, argv[i]);
if (if_idx < 0) {
continue;
}
iface = net_if_get_by_index(if_idx);
if (iface == NULL) {
shell_warn(sh, "Interface %d not found\n", if_idx);
continue;
}
if (net_if_l2(iface) != &NET_L2_GET_NAME(ETHERNET)) {
shell_warn(sh, "Interface %d is not Ethernet\n", if_idx);
continue;
}
if (!(net_eth_get_hw_capabilities(iface) & ETHERNET_PROMISC_MODE)) {
shell_warn(sh, "Interface %d cannot do promiscuous mode\n", if_idx);
continue;
}
ret = eth_bridge_iface_add(br, iface);
if (ret < 0) {
shell_error(sh, "error: bridge iface add (%d)\n", ret);
}
}
return ret;
}
static int cmd_bridge_delif(const struct shell *sh, size_t argc, char *argv[])
{
int ret = 0, br_idx, if_idx;
struct net_if *iface;
struct net_if *br;
br_idx = get_idx(sh, argv[1]);
if (br_idx < 0) {
return br_idx;
}
br = eth_bridge_get_by_index(br_idx);
if (br == NULL) {
shell_warn(sh, "Bridge %d not found\n", br_idx);
return -ENOENT;
}
for (int i = 2; i < argc; i++) {
if_idx = get_idx(sh, argv[i]);
if (if_idx < 0) {
continue;
}
iface = net_if_get_by_index(if_idx);
if (iface == NULL) {
shell_warn(sh, "Interface %d not found\n", if_idx);
continue;
}
ret = eth_bridge_iface_remove(br, iface);
if (ret < 0) {
shell_error(sh, "error: bridge iface remove (%d)\n", ret);
}
}
return ret;
}
static void bridge_show(struct eth_bridge_iface_context *ctx, void *data)
{
int br_idx = eth_bridge_get_index(ctx->iface);
const struct shell *sh = data;
shell_fprintf(sh, SHELL_NORMAL, "%-7d", br_idx);
if (net_if_is_up(ctx->iface)) {
shell_fprintf(sh, SHELL_NORMAL, "%-9s", "up");
} else {
shell_fprintf(sh, SHELL_NORMAL, "%-9s", "down");
}
if (ctx->is_setup) {
shell_fprintf(sh, SHELL_NORMAL, "%-9s", "ok");
} else {
shell_fprintf(sh, SHELL_NORMAL, "%-9s", "no");
}
k_mutex_lock(&ctx->lock, K_FOREVER);
ARRAY_FOR_EACH(ctx->eth_iface, i) {
int if_idx;
if (ctx->eth_iface[i] == NULL) {
continue;
}
if_idx = net_if_get_by_iface(ctx->eth_iface[i]);
shell_fprintf(sh, SHELL_NORMAL, "%-2d", if_idx);
}
shell_fprintf(sh, SHELL_NORMAL, "\n");
k_mutex_unlock(&ctx->lock);
}
static int cmd_bridge_show(const struct shell *sh, size_t argc, char *argv[])
{
struct net_if *br = NULL;
int br_idx;
if (argc == 2) {
br_idx = get_idx(sh, argv[1]);
if (br_idx < 0) {
return br_idx;
}
br = eth_bridge_get_by_index(br_idx);
if (br == NULL) {
shell_warn(sh, "Bridge %d not found\n", br_idx);
return -ENOENT;
}
}
shell_fprintf(sh, SHELL_NORMAL, "Bridge %-9s%-9sInterfaces\n",
"Status", "Config");
if (br != NULL) {
bridge_show(net_if_get_device(br)->data, (void *)sh);
} else {
net_eth_bridge_foreach(bridge_show, (void *)sh);
}
return 0;
}
SHELL_STATIC_SUBCMD_SET_CREATE(bridge_commands,
SHELL_CMD_ARG(addif, NULL,
"Add a network interface to a bridge.\n"
"'bridge addif <bridge_index> <one or more interface index>'",
cmd_bridge_addif, 3, 5),
SHELL_CMD_ARG(delif, NULL,
"Delete a network interface from a bridge.\n"
"'bridge delif <bridge_index> <one or more interface index>'",
cmd_bridge_delif, 3, 5),
SHELL_CMD_ARG(show, NULL,
"Show bridge information.\n"
"'bridge show [<bridge_index>]'",
cmd_bridge_show, 1, 1),
SHELL_SUBCMD_SET_END
);
SHELL_SUBCMD_ADD((net), bridge, &bridge_commands,
"Ethernet bridge commands.",
cmd_bridge_show, 1, 1);