1 /*
2 * Copyright 2025 NXP
3 *
4 * SPDX-License-Identifier: Apache-2.0
5 */
6
7 #include <zephyr/logging/log.h>
8 LOG_MODULE_DECLARE(net_shell);
9
10 #include <zephyr/shell/shell.h>
11 #include <stdlib.h>
12 #include <string.h>
13 #include <zephyr/sys/util.h>
14 #include <zephyr/devicetree.h>
15 #include <zephyr/net/ethernet.h>
16 #include <zephyr/net/ethernet_mgmt.h>
17
18 #include "net_shell_private.h"
19
20 #if defined(CONFIG_NET_QBV) && defined(CONFIG_NET_L2_ETHERNET_MGMT)
get_iface_from_shell(const struct shell * sh,size_t argc,char ** argv)21 static struct net_if *get_iface_from_shell(const struct shell *sh, size_t argc, char **argv)
22 {
23 int idx;
24 struct net_if *iface;
25
26 idx = get_iface_idx(sh, argv[1]);
27 if (idx < 0) {
28 return NULL;
29 }
30
31 iface = net_if_get_by_index(idx);
32 if (net_if_l2(iface) != &NET_L2_GET_NAME(ETHERNET)) {
33 PR_WARNING("No such interface in index %d\n", idx);
34 return NULL;
35 }
36
37 return iface;
38 }
39 #endif
40
41 /* qbv enable <iface_index> <value(off, on)> */
cmd_net_qbv(const struct shell * sh,size_t argc,char ** argv)42 static int cmd_net_qbv(const struct shell *sh, size_t argc, char **argv)
43 {
44 ARG_UNUSED(argc);
45 ARG_UNUSED(argv);
46
47 #if defined(CONFIG_NET_QBV) && defined(CONFIG_NET_L2_ETHERNET_MGMT)
48 shell_print(sh, "To set Qbv config:");
49 shell_print(sh, " 1. Run enable to on");
50 shell_print(sh, " 2. Run set_config to set base_time/cycle_time/cycle_time_ext/list_len");
51 shell_print(sh, " 3. Run set_gc to set gate control");
52 shell_print(sh, "For example:");
53 shell_print(sh, " 1. net qbv enable 1 on");
54 shell_print(sh, " 2. net qbv set_config 1 200 0 0 10000000 0 2");
55 shell_print(sh, " 3. qbv set_gc 1 0 0x1 5000000");
56 shell_print(sh, " 4. qbv set_gc 1 0 0x2 5000000");
57 #else
58 shell_print(sh, "Set %s to enable %s support.\n", "CONFIG_NET_QBV", "qbv");
59 shell_print(sh, "Set %s to enable %s support.\n", "CONFIG_NET_L2_ETHERNET_MGMT",
60 "Ethernet network management interface");
61 #endif
62
63 return 0;
64 }
65
66 /* qbv enable <iface_index> <value(off, on)> */
cmd_qbv_enable(const struct shell * sh,size_t argc,char ** argv)67 static int cmd_qbv_enable(const struct shell *sh, size_t argc, char **argv)
68 {
69 #if defined(CONFIG_NET_QBV) && defined(CONFIG_NET_L2_ETHERNET_MGMT)
70 struct net_if *iface;
71 struct ethernet_req_params params;
72 int ret;
73 bool enable;
74
75 iface = get_iface_from_shell(sh, argc, argv);
76 if (!iface) {
77 return -ENOEXEC;
78 }
79
80 enable = shell_strtobool(argv[2], 0, &ret);
81 if (ret < 0) {
82 return ret;
83 }
84
85 params.qbv_param.type = ETHERNET_QBV_PARAM_TYPE_STATUS;
86 params.qbv_param.state = ETHERNET_QBV_STATE_TYPE_ADMIN;
87 params.qbv_param.enabled = enable;
88
89 ret = net_mgmt(NET_REQUEST_ETHERNET_SET_QBV_PARAM,
90 iface,
91 ¶ms, sizeof(struct ethernet_req_params));
92 if (ret < 0) {
93 shell_error(sh, "failed to set %s", argv[1]);
94 return ret;
95 }
96 #else
97 ARG_UNUSED(argc);
98 ARG_UNUSED(argv);
99 shell_print(sh, "Set %s to enable %s support.\n", "CONFIG_NET_QBV", "qbv");
100 shell_print(sh, "Set %s to enable %s support.\n", "CONFIG_NET_L2_ETHERNET_MGMT",
101 "Ethernet network management interface");
102 #endif
103
104 return 0;
105 }
106
107 /*
108 * qbv set_config <iface_index> <base_time(s)> <base_time(2*(-16)ns)>
109 * <cycle_time(s)> <cycle_time(ns)> <cycle_time_ext> <list_len>
110 */
cmd_qbv_set_config(const struct shell * sh,size_t argc,char ** argv)111 static int cmd_qbv_set_config(const struct shell *sh, size_t argc, char **argv)
112 {
113 #if defined(CONFIG_NET_QBV) && defined(CONFIG_NET_L2_ETHERNET_MGMT)
114 struct net_if *iface;
115 struct ethernet_req_params params;
116 uint32_t list_len;
117 int ret;
118
119 iface = get_iface_from_shell(sh, argc, argv);
120 if (!iface) {
121 return -ENOEXEC;
122 }
123
124 params.qbv_param.type = ETHERNET_QBV_PARAM_TYPE_TIME;
125 params.qbv_param.state = ETHERNET_QBV_STATE_TYPE_ADMIN;
126
127 params.qbv_param.base_time.second = shell_strtoull(argv[2], 10, &ret);
128 if (ret < 0) {
129 return ret;
130 }
131
132 params.qbv_param.base_time.fract_nsecond = shell_strtoull(argv[3], 10, &ret);
133 if (ret < 0) {
134 return ret;
135 }
136
137 params.qbv_param.cycle_time.second = shell_strtoull(argv[4], 10, &ret);
138 if (ret < 0) {
139 return ret;
140 }
141
142 params.qbv_param.cycle_time.nanosecond = shell_strtoul(argv[5], 10, &ret);
143 if (ret < 0) {
144 return ret;
145 }
146
147 params.qbv_param.extension_time = shell_strtoul(argv[6], 10, &ret);
148 if (ret < 0) {
149 return ret;
150 }
151
152 ret = net_mgmt(NET_REQUEST_ETHERNET_SET_QBV_PARAM,
153 iface,
154 ¶ms, sizeof(struct ethernet_req_params));
155
156 list_len = shell_strtol(argv[7], 10, &ret);
157 if (ret < 0) {
158 shell_print(sh, "failed to set times");
159 return ret;
160 }
161
162 params.qbv_param.type =
163 ETHERNET_QBV_PARAM_TYPE_GATE_CONTROL_LIST_LEN;
164 params.qbv_param.gate_control_list_len = list_len;
165 ret = net_mgmt(NET_REQUEST_ETHERNET_SET_QBV_PARAM,
166 iface,
167 ¶ms, sizeof(struct ethernet_req_params));
168 if (ret < 0) {
169 shell_print(sh, "failed to set list length");
170 return ret;
171 }
172 #else
173 ARG_UNUSED(argc);
174 ARG_UNUSED(argv);
175 shell_print(sh, "Set %s to enable %s support.\n", "CONFIG_NET_QBV", "qbv");
176 shell_print(sh, "Set %s to enable %s support.\n", "CONFIG_NET_L2_ETHERNET_MGMT",
177 "Ethernet network management interface");
178 #endif
179
180 return 0;
181 }
182
183 /* qbv set_config <iface_index> <row> <gate_control> <interval> */
cmd_qbv_set_gc(const struct shell * sh,size_t argc,char ** argv)184 static int cmd_qbv_set_gc(const struct shell *sh, size_t argc, char **argv)
185 {
186 #if defined(CONFIG_NET_QBV) && defined(CONFIG_NET_L2_ETHERNET_MGMT)
187 struct net_if *iface;
188 struct ethernet_req_params params;
189 uint32_t row;
190 uint32_t interval;
191 uint32_t gc;
192 int ret;
193
194 iface = get_iface_from_shell(sh, argc, argv);
195 if (!iface) {
196 return -ENOEXEC;
197 }
198
199 row = shell_strtoul(argv[2], 10, &ret);
200 if (ret < 0) {
201 return ret;
202 }
203
204 gc = shell_strtoul(argv[3], 16, &ret);
205 if (ret < 0) {
206 return ret;
207 }
208
209 interval = shell_strtoul(argv[4], 10, &ret);
210 if (ret < 0) {
211 return ret;
212 }
213 params.qbv_param.type = ETHERNET_QBV_PARAM_TYPE_GATE_CONTROL_LIST;
214 params.qbv_param.state = ETHERNET_QBV_STATE_TYPE_ADMIN;
215
216 params.qbv_param.gate_control.time_interval = interval;
217 params.qbv_param.gate_control.row = row;
218 for (int i = 0; i < CONFIG_NET_TC_TX_COUNT; i++) {
219 params.qbv_param.gate_control.gate_status[i] = ((gc & BIT(i)) != 0);
220 }
221
222 ret = net_mgmt(NET_REQUEST_ETHERNET_SET_QBV_PARAM,
223 iface,
224 ¶ms, sizeof(struct ethernet_req_params));
225 if (ret < 0) {
226 return ret;
227 }
228 #else
229 ARG_UNUSED(argc);
230 ARG_UNUSED(argv);
231 shell_print(sh, "Set %s to enable %s support.\n", "CONFIG_NET_QBV", "qbv");
232 shell_print(sh, "Set %s to enable %s support.\n", "CONFIG_NET_L2_ETHERNET_MGMT",
233 "Ethernet network management interface");
234 #endif
235
236 return 0;
237 }
238
239 /* qbv get_info <iface_index> */
cmd_qbv_get_info(const struct shell * sh,size_t argc,char ** argv)240 static int cmd_qbv_get_info(const struct shell *sh, size_t argc, char **argv)
241 {
242 #if defined(CONFIG_NET_QBV) && defined(CONFIG_NET_L2_ETHERNET_MGMT)
243 struct net_if *iface;
244 struct ethernet_req_params params;
245 int ret;
246 uint32_t list_len;
247 uint32_t gate_status;
248
249 iface = get_iface_from_shell(sh, argc, argv);
250 if (!iface) {
251 return -ENOEXEC;
252 }
253
254 params.qbv_param.type = ETHERNET_QBV_PARAM_TYPE_STATUS;
255 params.qbv_param.state = ETHERNET_QBV_STATE_TYPE_ADMIN;
256
257 ret = net_mgmt(NET_REQUEST_ETHERNET_GET_QBV_PARAM,
258 iface,
259 ¶ms, sizeof(struct ethernet_req_params));
260 if (ret < 0) {
261 shell_error(sh, "failed to get %s status", argv[1]);
262 return ret;
263 }
264 shell_print(sh, "status: %s", (params.qbv_param.enabled ? "on" : "off"));
265
266 params.qbv_param.type = ETHERNET_QBV_PARAM_TYPE_TIME;
267 ret = net_mgmt(NET_REQUEST_ETHERNET_GET_QBV_PARAM,
268 iface,
269 ¶ms, sizeof(struct ethernet_req_params));
270 if (ret < 0) {
271 shell_error(sh, "failed to get %s time", argv[1]);
272 return ret;
273 }
274 shell_print(sh, "base_time(s): %"PRIu64, params.qbv_param.base_time.second);
275 shell_print(sh, "base_time(fract_ns): %"PRIu64, params.qbv_param.base_time.fract_nsecond);
276 shell_print(sh, "cycle_time(s): %"PRIu64, params.qbv_param.cycle_time.second);
277 shell_print(sh, "cycle_time(ns): %"PRIu32, params.qbv_param.cycle_time.nanosecond);
278 shell_print(sh, "extension_time(ns): %"PRIu32, params.qbv_param.extension_time);
279
280 params.qbv_param.type = ETHERNET_QBV_PARAM_TYPE_GATE_CONTROL_LIST_LEN;
281 ret = net_mgmt(NET_REQUEST_ETHERNET_GET_QBV_PARAM,
282 iface,
283 ¶ms, sizeof(struct ethernet_req_params));
284 if (ret < 0) {
285 shell_error(sh, "failed to get %s list length", argv[1]);
286 return ret;
287 }
288 shell_print(sh, "list len: %"PRIu32, params.qbv_param.gate_control_list_len);
289
290 list_len = params.qbv_param.gate_control_list_len;
291 params.qbv_param.type = ETHERNET_QBV_PARAM_TYPE_GATE_CONTROL_LIST;
292 for (uint16_t i = 0; i < list_len; i++) {
293 params.qbv_param.gate_control.row = i;
294 ret = net_mgmt(NET_REQUEST_ETHERNET_GET_QBV_PARAM,
295 iface,
296 ¶ms, sizeof(struct ethernet_req_params));
297 if (ret < 0) {
298 shell_error(sh, "failed to get %s gate control", argv[1]);
299 return ret;
300 }
301 gate_status = 0;
302 for (int j = 0; j < CONFIG_NET_TC_TX_COUNT; j++) {
303 gate_status |= params.qbv_param.gate_control.gate_status[j] << j;
304 }
305 shell_print(sh, "row: %"PRIu16" interval: %"PRIu32" gate_status: 0x%x",
306 i, params.qbv_param.gate_control.time_interval, gate_status);
307 }
308 #else
309 ARG_UNUSED(argc);
310 ARG_UNUSED(argv);
311 shell_print(sh, "Set %s to enable %s support.\n", "CONFIG_NET_QBV", "qbv");
312 shell_print(sh, "Set %s to enable %s support.\n", "CONFIG_NET_L2_ETHERNET_MGMT",
313 "Ethernet network management interface");
314 #endif
315
316 return 0;
317 }
318
319 SHELL_STATIC_SUBCMD_SET_CREATE(net_cmd_qbv,
320 SHELL_CMD_ARG(enable, NULL,
321 "Enable: enable <iface_index> <value(off, on)>",
322 cmd_qbv_enable, 3, 0),
323 SHELL_CMD_ARG(set_config, NULL,
324 "Set config: set <iface_index> <base_time(s)> <base_time(2*(-16)ns)> <cycle_time(s)> <cycle_time(ns)> <cycle_time_ext(ns)> <list_len>",
325 cmd_qbv_set_config, 8, 0),
326 SHELL_CMD_ARG(set_gc, NULL,
327 "Set gate control: set <iface_index> <row> <gate_control> <interval>",
328 cmd_qbv_set_gc, 5, 0),
329 SHELL_CMD_ARG(get_info, NULL,
330 "Get info: get_info <iface_index>",
331 cmd_qbv_get_info, 2, 0),
332 SHELL_SUBCMD_SET_END /* Array terminated. */
333 );
334
335 SHELL_SUBCMD_ADD((net), qbv, &net_cmd_qbv,
336 "Qbv commands",
337 cmd_net_qbv, 1, 0);
338