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 #include <zephyr/net/ethernet.h>
15
16 #include <zephyr/net/socket.h>
17 #include <stdlib.h>
18
19 #include "net_shell_private.h"
20
21 #if defined(CONFIG_NET_VLAN)
iface_vlan_del_cb(struct net_if * iface,void * user_data)22 static void iface_vlan_del_cb(struct net_if *iface, void *user_data)
23 {
24 struct net_shell_user_data *data = user_data;
25 const struct shell *sh = data->sh;
26 uint16_t vlan_tag = POINTER_TO_UINT(data->user_data);
27 int ret;
28
29 ret = net_eth_vlan_disable(iface, vlan_tag);
30 if (ret < 0) {
31 if (ret != -ESRCH) {
32 PR_WARNING("Cannot delete VLAN tag %d from "
33 "interface %d (%p)\n",
34 vlan_tag,
35 net_if_get_by_iface(iface),
36 iface);
37 }
38
39 return;
40 }
41
42 PR("VLAN tag %d removed from interface %d (%p)\n", vlan_tag,
43 net_if_get_by_iface(iface), iface);
44 }
45
iface_vlan_cb(struct net_if * iface,void * user_data)46 static void iface_vlan_cb(struct net_if *iface, void *user_data)
47 {
48 struct virtual_interface_context *ctx;
49 struct net_shell_user_data *data = user_data;
50 const struct shell *sh = data->sh;
51 int *count = data->user_data;
52 char name[NET_IFNAMSIZ];
53
54 if (!net_eth_is_vlan_interface(iface)) {
55 return;
56 }
57
58
59 if (*count == 0) {
60 PR(" Interface Name \tTag\tAttached\n");
61 }
62
63 (void)net_if_get_name(iface, name, sizeof(name));
64
65 ctx = net_if_l2_data(iface);
66 if (ctx->iface != NULL) {
67 PR("[%d] %p %-12s\t%d\t%d\n", net_if_get_by_iface(iface), iface,
68 name, net_eth_get_vlan_tag(iface),
69 net_if_get_by_iface(net_eth_get_vlan_main(iface)));
70 } else {
71 PR("[%d] %p %-12s\n", net_if_get_by_iface(iface), iface, name);
72 }
73
74 (*count)++;
75 }
76 #endif /* CONFIG_NET_VLAN */
77
cmd_net_vlan(const struct shell * sh,size_t argc,char * argv[])78 static int cmd_net_vlan(const struct shell *sh, size_t argc, char *argv[])
79 {
80 #if defined(CONFIG_NET_VLAN)
81 struct net_shell_user_data user_data;
82 int count = 0;
83
84 user_data.sh = sh;
85 user_data.user_data = &count;
86
87 net_if_foreach(iface_vlan_cb, &user_data);
88 #else
89 PR_INFO("Set %s to enable %s support.\n", "CONFIG_NET_VLAN", "VLAN");
90 #endif /* CONFIG_NET_VLAN */
91
92 return 0;
93 }
94
cmd_net_vlan_add(const struct shell * sh,size_t argc,char * argv[])95 static int cmd_net_vlan_add(const struct shell *sh, size_t argc, char *argv[])
96 {
97 #if defined(CONFIG_NET_VLAN)
98 int arg = 0;
99 int ret;
100 uint16_t tag;
101 struct net_if *iface;
102 char *endptr;
103 uint32_t iface_idx;
104
105 /* vlan add <tag> <interface index> */
106 if (!argv[++arg]) {
107 PR_WARNING("VLAN tag missing.\n");
108 goto usage;
109 }
110
111 tag = strtol(argv[arg], &endptr, 10);
112 if (*endptr != '\0') {
113 PR_WARNING("Invalid tag %s\n", argv[arg]);
114 return -ENOEXEC;
115 }
116
117 if (!argv[++arg]) {
118 PR_WARNING("Network interface index missing.\n");
119 goto usage;
120 }
121
122 iface_idx = strtol(argv[arg], &endptr, 10);
123 if (*endptr != '\0') {
124 PR_WARNING("Invalid index %s\n", argv[arg]);
125 goto usage;
126 }
127
128 iface = net_if_get_by_index(iface_idx);
129 if (!iface) {
130 PR_WARNING("Network interface index %d is invalid.\n",
131 iface_idx);
132 goto usage;
133 }
134
135 if (net_if_l2(iface) != &NET_L2_GET_NAME(ETHERNET)) {
136 PR_WARNING("Network interface %d (%p) is not ethernet interface\n",
137 net_if_get_by_iface(iface), iface);
138 return -ENOEXEC;
139 }
140
141 ret = net_eth_vlan_enable(iface, tag);
142 if (ret < 0) {
143 if (ret == -ENOENT) {
144 PR_WARNING("No IP address configured.\n");
145 }
146
147 PR_WARNING("Cannot set VLAN tag (%d)\n", ret);
148
149 return -ENOEXEC;
150 }
151
152 iface = net_eth_get_vlan_iface(iface, tag);
153
154 PR("VLAN tag %d set to interface %d (%p)\n", tag,
155 net_if_get_by_iface(iface), iface);
156
157 return 0;
158
159 usage:
160 PR("Usage:\n");
161 PR("\tvlan add <tag> <interface index>\n");
162 #else
163 PR_INFO("Set %s to enable %s support.\n", "CONFIG_NET_VLAN", "VLAN");
164 #endif /* CONFIG_NET_VLAN */
165
166 return 0;
167 }
168
cmd_net_vlan_del(const struct shell * sh,size_t argc,char * argv[])169 static int cmd_net_vlan_del(const struct shell *sh, size_t argc, char *argv[])
170 {
171 #if defined(CONFIG_NET_VLAN)
172 int arg = 0;
173 struct net_shell_user_data user_data;
174 char *endptr;
175 uint16_t tag;
176
177 /* vlan del <tag> */
178 if (!argv[++arg]) {
179 PR_WARNING("VLAN tag missing.\n");
180 goto usage;
181 }
182
183 tag = strtol(argv[arg], &endptr, 10);
184 if (*endptr != '\0') {
185 PR_WARNING("Invalid tag %s\n", argv[arg]);
186 return -ENOEXEC;
187 }
188
189 user_data.sh = sh;
190 user_data.user_data = UINT_TO_POINTER((uint32_t)tag);
191
192 net_if_foreach(iface_vlan_del_cb, &user_data);
193
194 return 0;
195
196 usage:
197 PR("Usage:\n");
198 PR("\tvlan del <tag>\n");
199 #else
200 PR_INFO("Set %s to enable %s support.\n", "CONFIG_NET_VLAN", "VLAN");
201 #endif /* CONFIG_NET_VLAN */
202
203 return 0;
204 }
205
206 SHELL_STATIC_SUBCMD_SET_CREATE(net_cmd_vlan,
207 SHELL_CMD_ARG(add, NULL,
208 "'net vlan add <tag> <index>' adds VLAN tag to the "
209 "network interface.",
210 cmd_net_vlan_add, 3, 0),
211 SHELL_CMD_ARG(del, NULL,
212 "'net vlan del <tag>' deletes VLAN tag from the network "
213 "interface.",
214 cmd_net_vlan_del, 2, 0),
215 SHELL_SUBCMD_SET_END
216 );
217
218 SHELL_SUBCMD_ADD((net), vlan, &net_cmd_vlan,
219 "Show VLAN information.",
220 cmd_net_vlan, 1, 0);
221