1 /*
2  * Copyright (c) 2016 Intel Corporation
3  * Copyright (c) 2023 Nordic Semiconductor ASA
4  *
5  * SPDX-License-Identifier: Apache-2.0
6  */
7 
8 #include <zephyr/logging/log.h>
9 LOG_MODULE_DECLARE(net_shell);
10 
11 #if defined(CONFIG_NET_L2_VIRTUAL)
12 #include <zephyr/net/virtual.h>
13 #endif
14 
15 #include "net_shell_private.h"
16 
17 #if defined(CONFIG_NET_L2_VIRTUAL)
virtual_iface_cb(struct net_if * iface,void * user_data)18 static void virtual_iface_cb(struct net_if *iface, void *user_data)
19 {
20 	struct net_shell_user_data *data = user_data;
21 	const struct shell *sh = data->sh;
22 	int *count = data->user_data;
23 	char *name, buf[CONFIG_NET_L2_VIRTUAL_MAX_NAME_LEN];
24 	struct net_if *orig_iface;
25 
26 	if (net_if_l2(iface) != &NET_L2_GET_NAME(VIRTUAL)) {
27 		return;
28 	}
29 
30 	if (*count == 0) {
31 		PR("Interface  Attached-To  Description\n");
32 		(*count)++;
33 	}
34 
35 	orig_iface = net_virtual_get_iface(iface);
36 
37 	name = net_virtual_get_name(iface, buf, sizeof(buf));
38 
39 	PR("%d          %c            %s\n",
40 	   net_if_get_by_iface(iface),
41 	   orig_iface ? net_if_get_by_iface(orig_iface) + '0' : '-',
42 	   name);
43 
44 	(*count)++;
45 }
46 
attached_iface_cb(struct net_if * iface,void * user_data)47 static void attached_iface_cb(struct net_if *iface, void *user_data)
48 {
49 	struct net_shell_user_data *data = user_data;
50 	const struct shell *sh = data->sh;
51 	int *count = data->user_data;
52 	char buf[CONFIG_NET_L2_VIRTUAL_MAX_NAME_LEN];
53 	const char *name;
54 	struct virtual_interface_context *ctx, *tmp;
55 
56 	if (sys_slist_is_empty(&iface->config.virtual_interfaces)) {
57 		return;
58 	}
59 
60 	if (*count == 0) {
61 		PR("Interface  Below-of  Description\n");
62 		(*count)++;
63 	}
64 
65 	PR("%d          ", net_if_get_by_iface(iface));
66 
67 	SYS_SLIST_FOR_EACH_CONTAINER_SAFE(&iface->config.virtual_interfaces,
68 					  ctx, tmp, node) {
69 		if (ctx->virtual_iface == iface) {
70 			continue;
71 		}
72 
73 		PR("%d ", net_if_get_by_iface(ctx->virtual_iface));
74 	}
75 
76 	name = net_virtual_get_name(iface, buf, sizeof(buf));
77 	if (name == NULL) {
78 		name = iface2str(iface, NULL);
79 	}
80 
81 	PR("        %s\n", name);
82 
83 	(*count)++;
84 }
85 #endif /* CONFIG_NET_L2_VIRTUAL */
86 
cmd_net_virtual(const struct shell * sh,size_t argc,char * argv[])87 static int cmd_net_virtual(const struct shell *sh, size_t argc, char *argv[])
88 {
89 	ARG_UNUSED(argc);
90 	ARG_UNUSED(argv);
91 
92 #if defined(CONFIG_NET_L2_VIRTUAL)
93 	struct net_shell_user_data user_data;
94 	int count = 0;
95 
96 	user_data.sh = sh;
97 	user_data.user_data = &count;
98 
99 	net_if_foreach(virtual_iface_cb, &user_data);
100 
101 	if (count == 0) {
102 		PR("No virtual interfaces found.");
103 	}
104 
105 	count = 0;
106 	PR("\n");
107 
108 	net_if_foreach(attached_iface_cb, &user_data);
109 #else
110 	PR_INFO("Set %s to enable %s support.\n", "CONFIG_NET_L2_VIRTUAL",
111 		"virtual network interface");
112 #endif
113 	return 0;
114 }
115 
116 SHELL_SUBCMD_ADD((net), virtual, NULL,
117 		 "Show virtual network interfaces.",
118 		 cmd_net_virtual, 1, 0);
119