Branch data Line data Source code
1 : : /* SPDX-License-Identifier: BSD-3-Clause
2 : : * Copyright(c) 2023 Marvell.
3 : : */
4 : :
5 : : #include <stdio.h>
6 : : #include <stdlib.h>
7 : : #include <string.h>
8 : :
9 : : #include <cmdline_parse.h>
10 : : #include <cmdline_parse_num.h>
11 : : #include <cmdline_parse_string.h>
12 : : #include <cmdline_socket.h>
13 : : #include <rte_bitops.h>
14 : : #include <rte_ethdev.h>
15 : : #include <rte_mempool.h>
16 : :
17 : : #include "ethdev_priv.h"
18 : : #include "module_api.h"
19 : :
20 : : static const char
21 : : cmd_ethdev_mtu_help[] = "ethdev <ethdev_name> mtu <mtu_sz>";
22 : :
23 : : static const char
24 : : cmd_ethdev_prom_mode_help[] = "ethdev <ethdev_name> promiscuous <on/off>";
25 : :
26 : : static const char
27 : : cmd_ethdev_help[] = "ethdev <ethdev_name> rxq <n_queues> txq <n_queues> <mempool_name>";
28 : :
29 : : static const char
30 : : cmd_ethdev_stats_help[] = "ethdev <ethdev_name> stats";
31 : :
32 : : static const char
33 : : cmd_ethdev_show_help[] = "ethdev <ethdev_name> show";
34 : :
35 : : static const char
36 : : cmd_ethdev_ip4_addr_help[] = "ethdev <ethdev_name> ip4 addr add <ip> netmask <mask>";
37 : :
38 : : static const char
39 : : cmd_ethdev_ip6_addr_help[] = "ethdev <ethdev_name> ip6 addr add <ip> netmask <mask>";
40 : :
41 : : static const char
42 : : cmd_ethdev_forward_help[] = "ethdev forward <tx_dev_name> <rx_dev_name>";
43 : :
44 : : static struct rte_eth_conf port_conf_default = {
45 : : .link_speeds = 0,
46 : : .rxmode = {
47 : : .mq_mode = RTE_ETH_MQ_RX_NONE,
48 : : .mtu = 9000 - (RTE_ETHER_HDR_LEN + RTE_ETHER_CRC_LEN), /* Jumbo frame MTU */
49 : : },
50 : : .rx_adv_conf = {
51 : : .rss_conf = {
52 : : .rss_key = NULL,
53 : : .rss_key_len = 40,
54 : : .rss_hf = 0,
55 : : },
56 : : },
57 : : .txmode = {
58 : : .mq_mode = RTE_ETH_MQ_TX_NONE,
59 : : },
60 : : .lpbk_mode = 0,
61 : : };
62 : :
63 : : uint32_t enabled_port_mask;
64 : : static struct ethdev_head eth_node = TAILQ_HEAD_INITIALIZER(eth_node);
65 : :
66 : :
67 : : static struct ethdev*
68 : : ethdev_port_by_id(uint16_t port_id)
69 : : {
70 : : struct ethdev *port;
71 : :
72 : 0 : TAILQ_FOREACH(port, ð_node, next) {
73 : 0 : if (port->config.port_id == port_id)
74 : : return port;
75 : : }
76 : : return NULL;
77 : : }
78 : :
79 : : int16_t
80 : 0 : ethdev_txport_by_rxport_get(uint16_t portid_rx)
81 : : {
82 : : int portid = -EINVAL;
83 : : struct ethdev *port;
84 : :
85 : : port = ethdev_port_by_id(portid_rx);
86 : 0 : if (port)
87 : 0 : portid = port->tx_port_id;
88 : :
89 : 0 : return portid;
90 : : }
91 : :
92 : : void *
93 : 0 : ethdev_mempool_list_by_portid(uint16_t portid)
94 : : {
95 : : struct ethdev *port;
96 : :
97 : 0 : if (portid >= RTE_MAX_ETHPORTS)
98 : : return NULL;
99 : :
100 : : port = ethdev_port_by_id(portid);
101 : 0 : if (port)
102 : 0 : return &(port->config.rx.mp);
103 : : else
104 : : return NULL;
105 : : }
106 : :
107 : : int16_t
108 : 0 : ethdev_portid_by_ip4(uint32_t ip, uint32_t mask)
109 : : {
110 : : int portid = -EINVAL;
111 : : struct ethdev *port;
112 : :
113 : 0 : TAILQ_FOREACH(port, ð_node, next) {
114 : 0 : if (mask == 0) {
115 : 0 : if ((port->ip4_addr.ip & port->ip4_addr.mask) == (ip & port->ip4_addr.mask))
116 : 0 : return port->config.port_id;
117 : : } else {
118 : 0 : if ((port->ip4_addr.ip & port->ip4_addr.mask) == (ip & mask))
119 : 0 : return port->config.port_id;
120 : : }
121 : : }
122 : :
123 : : return portid;
124 : : }
125 : :
126 : : int16_t
127 : 0 : ethdev_portid_by_ip6(uint8_t *ip, uint8_t *mask)
128 : : {
129 : : int portid = -EINVAL;
130 : : struct ethdev *port;
131 : : int j;
132 : :
133 : 0 : TAILQ_FOREACH(port, ð_node, next) {
134 : 0 : for (j = 0; j < ETHDEV_IPV6_ADDR_LEN; j++) {
135 : 0 : if (mask == NULL) {
136 : 0 : if ((port->ip6_addr.ip[j] & port->ip6_addr.mask[j]) !=
137 : 0 : (ip[j] & port->ip6_addr.mask[j]))
138 : : break;
139 : :
140 : : } else {
141 : 0 : if ((port->ip6_addr.ip[j] & port->ip6_addr.mask[j]) !=
142 : 0 : (ip[j] & mask[j]))
143 : : break;
144 : : }
145 : : }
146 : 0 : if (j == ETHDEV_IPV6_ADDR_LEN)
147 : 0 : return port->config.port_id;
148 : : }
149 : :
150 : : return portid;
151 : : }
152 : :
153 : : void
154 : 0 : ethdev_list_clean(void)
155 : : {
156 : : struct ethdev *port;
157 : :
158 : 0 : while (!TAILQ_EMPTY(ð_node)) {
159 : : port = TAILQ_FIRST(ð_node);
160 : 0 : TAILQ_REMOVE(ð_node, port, next);
161 : : }
162 : 0 : }
163 : :
164 : : void
165 : 0 : ethdev_stop(void)
166 : : {
167 : : uint16_t portid;
168 : : int rc;
169 : :
170 : 0 : RTE_ETH_FOREACH_DEV(portid) {
171 : 0 : if ((enabled_port_mask & (1 << portid)) == 0)
172 : 0 : continue;
173 : : printf("Closing port %d...", portid);
174 : 0 : rc = rte_eth_dev_stop(portid);
175 : 0 : if (rc != 0)
176 : 0 : printf("Failed to stop port %u: %s\n",
177 : : portid, rte_strerror(-rc));
178 : 0 : rte_eth_dev_close(portid);
179 : : printf(" Done\n");
180 : : }
181 : :
182 : : ethdev_list_clean();
183 : 0 : route_ip4_list_clean();
184 : 0 : route_ip6_list_clean();
185 : 0 : neigh4_list_clean();
186 : 0 : neigh6_list_clean();
187 : : printf("Bye...\n");
188 : 0 : }
189 : :
190 : : void
191 : 0 : ethdev_start(void)
192 : : {
193 : : uint16_t portid;
194 : : int rc;
195 : :
196 : 0 : RTE_ETH_FOREACH_DEV(portid)
197 : : {
198 : 0 : if ((enabled_port_mask & (1 << portid)) == 0)
199 : 0 : continue;
200 : :
201 : 0 : rc = rte_eth_dev_start(portid);
202 : 0 : if (rc < 0)
203 : 0 : rte_exit(EXIT_FAILURE, "rte_eth_dev_start: err=%d, port=%d\n", rc, portid);
204 : : }
205 : 0 : }
206 : :
207 : :
208 : : static int
209 : 0 : ethdev_show(const char *name)
210 : : {
211 : 0 : uint16_t mtu = 0, port_id = 0;
212 : : struct rte_eth_dev_info info;
213 : : struct rte_eth_stats stats;
214 : : struct rte_ether_addr addr;
215 : : struct rte_eth_link link;
216 : : uint32_t length;
217 : : int rc;
218 : :
219 : 0 : rc = rte_eth_dev_get_port_by_name(name, &port_id);
220 : 0 : if (rc < 0)
221 : : return rc;
222 : :
223 : 0 : rte_eth_dev_info_get(port_id, &info);
224 : 0 : rte_eth_stats_get(port_id, &stats);
225 : 0 : rte_eth_macaddr_get(port_id, &addr);
226 : 0 : rte_eth_link_get(port_id, &link);
227 : 0 : rte_eth_dev_get_mtu(port_id, &mtu);
228 : :
229 : 0 : length = strlen(conn->msg_out);
230 : 0 : conn->msg_out += length;
231 : 0 : snprintf(conn->msg_out, conn->msg_out_len_max,
232 : : "%s: flags=<%s> mtu %u\n"
233 : : "\tether " RTE_ETHER_ADDR_PRT_FMT " rxqueues %u txqueues %u\n"
234 : : "\tport# %u speed %s\n"
235 : : "\tRX packets %" PRIu64" bytes %" PRIu64"\n"
236 : : "\tRX errors %" PRIu64" missed %" PRIu64" no-mbuf %" PRIu64"\n"
237 : : "\tTX packets %" PRIu64" bytes %" PRIu64"\n"
238 : : "\tTX errors %" PRIu64"\n\n",
239 : : name,
240 : 0 : link.link_status ? "UP" : "DOWN",
241 : : mtu,
242 : 0 : RTE_ETHER_ADDR_BYTES(&addr),
243 : 0 : info.nb_rx_queues,
244 : 0 : info.nb_tx_queues,
245 : : port_id,
246 : : rte_eth_link_speed_to_str(link.link_speed),
247 : : stats.ipackets,
248 : : stats.ibytes,
249 : : stats.ierrors,
250 : : stats.imissed,
251 : : stats.rx_nombuf,
252 : : stats.opackets,
253 : : stats.obytes,
254 : : stats.oerrors);
255 : :
256 : 0 : length = strlen(conn->msg_out);
257 : 0 : conn->msg_out_len_max -= length;
258 : 0 : return 0;
259 : : }
260 : :
261 : : static int
262 : 0 : ethdev_ip4_addr_add(const char *name, struct ipv4_addr_config *config)
263 : : {
264 : : struct ethdev *eth_hdl;
265 : 0 : uint16_t portid = 0;
266 : : int rc;
267 : :
268 : 0 : rc = rte_eth_dev_get_port_by_name(name, &portid);
269 : 0 : if (rc < 0)
270 : : return rc;
271 : :
272 : 0 : eth_hdl = ethdev_port_by_id(portid);
273 : :
274 : 0 : if (eth_hdl) {
275 : 0 : eth_hdl->ip4_addr.ip = config->ip;
276 : 0 : eth_hdl->ip4_addr.mask = config->mask;
277 : 0 : return 0;
278 : : }
279 : :
280 : : rc = -EINVAL;
281 : : return rc;
282 : : }
283 : :
284 : : static int
285 : 0 : ethdev_ip6_addr_add(const char *name, struct ipv6_addr_config *config)
286 : : {
287 : : struct ethdev *eth_hdl;
288 : 0 : uint16_t portid = 0;
289 : : int rc, i;
290 : :
291 : 0 : rc = rte_eth_dev_get_port_by_name(name, &portid);
292 : 0 : if (rc < 0)
293 : : return rc;
294 : :
295 : 0 : eth_hdl = ethdev_port_by_id(portid);
296 : :
297 : 0 : if (eth_hdl) {
298 : 0 : for (i = 0; i < ETHDEV_IPV6_ADDR_LEN; i++) {
299 : 0 : eth_hdl->ip6_addr.ip[i] = config->ip[i];
300 : 0 : eth_hdl->ip6_addr.mask[i] = config->mask[i];
301 : : }
302 : : return 0;
303 : : }
304 : : rc = -EINVAL;
305 : : return rc;
306 : : }
307 : :
308 : : static int
309 : 0 : ethdev_prom_mode_config(const char *name, bool enable)
310 : : {
311 : : struct ethdev *eth_hdl;
312 : 0 : uint16_t portid = 0;
313 : : int rc;
314 : :
315 : 0 : rc = rte_eth_dev_get_port_by_name(name, &portid);
316 : 0 : if (rc < 0)
317 : : return rc;
318 : :
319 : 0 : eth_hdl = ethdev_port_by_id(portid);
320 : :
321 : 0 : if (eth_hdl) {
322 : 0 : if (enable)
323 : 0 : rc = rte_eth_promiscuous_enable(portid);
324 : : else
325 : 0 : rc = rte_eth_promiscuous_disable(portid);
326 : 0 : if (rc < 0)
327 : : return rc;
328 : :
329 : 0 : eth_hdl->config.promiscuous = enable;
330 : 0 : return 0;
331 : : }
332 : :
333 : : rc = -EINVAL;
334 : : return rc;
335 : : }
336 : :
337 : : static int
338 : 0 : ethdev_mtu_config(const char *name, uint32_t mtu)
339 : : {
340 : : struct ethdev *eth_hdl;
341 : 0 : uint16_t portid = 0;
342 : : int rc;
343 : :
344 : 0 : rc = rte_eth_dev_get_port_by_name(name, &portid);
345 : 0 : if (rc < 0)
346 : : return rc;
347 : :
348 : 0 : eth_hdl = ethdev_port_by_id(portid);
349 : :
350 : 0 : if (eth_hdl) {
351 : 0 : rc = rte_eth_dev_set_mtu(portid, mtu);
352 : 0 : if (rc < 0)
353 : : return rc;
354 : :
355 : 0 : eth_hdl->config.mtu = mtu;
356 : 0 : return 0;
357 : : }
358 : :
359 : : rc = -EINVAL;
360 : : return rc;
361 : : }
362 : :
363 : :
364 : : static int
365 : 0 : ethdev_process(const char *name, struct ethdev_config *params)
366 : : {
367 : : struct rte_eth_dev_info port_info;
368 : : struct rte_eth_conf port_conf;
369 : : struct ethdev_rss_config *rss;
370 : : struct rte_mempool *mempool;
371 : : struct ethdev *ethdev_port;
372 : : struct rte_ether_addr smac;
373 : 0 : uint16_t port_id = 0;
374 : : int numa_node, rc;
375 : : uint32_t i;
376 : :
377 : : /* Check input params */
378 : 0 : if (!name || !name[0] || !params || !params->rx.n_queues || !params->rx.queue_size ||
379 : 0 : !params->tx.n_queues || !params->tx.queue_size)
380 : : return -EINVAL;
381 : :
382 : 0 : rc = rte_eth_dev_get_port_by_name(name, &port_id);
383 : 0 : if (rc)
384 : : return -EINVAL;
385 : :
386 : 0 : if (!ethdev_port_by_id(port_id)) {
387 : 0 : ethdev_port = malloc(sizeof(struct ethdev));
388 : 0 : if (!ethdev_port)
389 : : return -EINVAL;
390 : : } else {
391 : : return 0;
392 : : }
393 : :
394 : 0 : rc = rte_eth_dev_info_get(port_id, &port_info);
395 : 0 : if (rc) {
396 : : rc = -EINVAL;
397 : 0 : goto exit;
398 : : }
399 : :
400 : 0 : mempool = rte_mempool_lookup(params->rx.mempool_name);
401 : 0 : if (!mempool) {
402 : : rc = -EINVAL;
403 : 0 : goto exit;
404 : : }
405 : :
406 : 0 : params->rx.mp = mempool;
407 : :
408 : 0 : rss = params->rx.rss;
409 : 0 : if (rss) {
410 : 0 : if (!port_info.reta_size || port_info.reta_size > RTE_ETH_RSS_RETA_SIZE_512) {
411 : : rc = -EINVAL;
412 : 0 : goto exit;
413 : : }
414 : :
415 : 0 : if (!rss->n_queues || rss->n_queues >= ETHDEV_RXQ_RSS_MAX) {
416 : : rc = -EINVAL;
417 : 0 : goto exit;
418 : : }
419 : :
420 : 0 : for (i = 0; i < rss->n_queues; i++)
421 : 0 : if (rss->queue_id[i] >= port_info.max_rx_queues) {
422 : : rc = -EINVAL;
423 : 0 : goto exit;
424 : : }
425 : : }
426 : :
427 : : /* Port */
428 : : memcpy(&port_conf, &port_conf_default, sizeof(struct rte_eth_conf));
429 : 0 : if (rss) {
430 : : uint64_t rss_hf = RTE_ETH_RSS_IP | RTE_ETH_RSS_TCP | RTE_ETH_RSS_UDP;
431 : :
432 : 0 : port_conf.rxmode.mq_mode = RTE_ETH_MQ_RX_RSS;
433 : 0 : port_conf.rx_adv_conf.rss_conf.rss_hf = rss_hf & port_info.flow_type_rss_offloads;
434 : : }
435 : :
436 : 0 : numa_node = rte_eth_dev_socket_id(port_id);
437 : 0 : if (numa_node == SOCKET_ID_ANY)
438 : : numa_node = 0;
439 : :
440 : 0 : if (params->mtu)
441 : 0 : port_conf.rxmode.mtu = params->mtu;
442 : :
443 : 0 : rc = rte_eth_dev_configure(port_id, params->rx.n_queues, params->tx.n_queues,
444 : : &port_conf);
445 : 0 : if (rc < 0) {
446 : : rc = -EINVAL;
447 : 0 : goto exit;
448 : : }
449 : :
450 : 0 : rc = rte_eth_macaddr_get(port_id, &smac);
451 : 0 : if (rc < 0) {
452 : : rc = -EINVAL;
453 : 0 : goto exit;
454 : : }
455 : :
456 : 0 : printf("Port_id = %d srcmac = %x:%x:%x:%x:%x:%x\n", port_id,
457 : 0 : smac.addr_bytes[0], smac.addr_bytes[1],
458 : 0 : smac.addr_bytes[2], smac.addr_bytes[3],
459 : 0 : smac.addr_bytes[4], smac.addr_bytes[5]);
460 : :
461 : : /* Port RX */
462 : 0 : for (i = 0; i < params->rx.n_queues; i++) {
463 : 0 : rc = rte_eth_rx_queue_setup(port_id, i, params->rx.queue_size, numa_node, NULL,
464 : : mempool);
465 : 0 : if (rc < 0) {
466 : : rc = -EINVAL;
467 : 0 : goto exit;
468 : : }
469 : : }
470 : :
471 : : /* Port TX */
472 : 0 : for (i = 0; i < params->tx.n_queues; i++) {
473 : 0 : rc = rte_eth_tx_queue_setup(port_id, i, params->tx.queue_size, numa_node, NULL);
474 : 0 : if (rc < 0) {
475 : : rc = -EINVAL;
476 : 0 : goto exit;
477 : : }
478 : : }
479 : :
480 : 0 : memcpy(ðdev_port->config, params, sizeof(struct ethdev_config));
481 : 0 : memcpy(ethdev_port->config.dev_name, name, strlen(name));
482 : 0 : ethdev_port->config.port_id = port_id;
483 : 0 : enabled_port_mask |= RTE_BIT32(port_id);
484 : :
485 : 0 : TAILQ_INSERT_TAIL(ð_node, ethdev_port, next);
486 : 0 : return 0;
487 : 0 : exit:
488 : 0 : free(ethdev_port);
489 : 0 : return rc;
490 : :
491 : : }
492 : :
493 : : static int
494 : 0 : ethdev_stats_show(const char *name)
495 : : {
496 : : uint64_t diff_pkts_rx, diff_pkts_tx, diff_bytes_rx, diff_bytes_tx;
497 : : static uint64_t prev_pkts_rx[RTE_MAX_ETHPORTS];
498 : : static uint64_t prev_pkts_tx[RTE_MAX_ETHPORTS];
499 : : static uint64_t prev_bytes_rx[RTE_MAX_ETHPORTS];
500 : : static uint64_t prev_bytes_tx[RTE_MAX_ETHPORTS];
501 : : static uint64_t prev_cycles[RTE_MAX_ETHPORTS];
502 : : uint64_t mpps_rx, mpps_tx, mbps_rx, mbps_tx;
503 : : uint64_t diff_ns, diff_cycles, curr_cycles;
504 : : struct rte_eth_stats stats;
505 : : static const char *nic_stats_border = "########################";
506 : : uint16_t port_id, len;
507 : : int rc;
508 : :
509 : 0 : rc = rte_eth_dev_get_port_by_name(name, &port_id);
510 : 0 : if (rc < 0)
511 : : return rc;
512 : :
513 : 0 : rc = rte_eth_stats_get(port_id, &stats);
514 : 0 : if (rc != 0) {
515 : 0 : fprintf(stderr,
516 : : "%s: Error: failed to get stats (port %u): %d",
517 : : __func__, port_id, rc);
518 : 0 : return rc;
519 : : }
520 : :
521 : 0 : len = strlen(conn->msg_out);
522 : 0 : conn->msg_out += len;
523 : 0 : snprintf(conn->msg_out, conn->msg_out_len_max,
524 : : "\n %s NIC statistics for port %-2d %s\n"
525 : : " RX-packets: %-10"PRIu64" RX-missed: %-10"PRIu64" RX-bytes: ""%-"PRIu64"\n"
526 : : " RX-errors: %-"PRIu64"\n"
527 : : " RX-nombuf: %-10"PRIu64"\n"
528 : : " TX-packets: %-10"PRIu64" TX-errors: %-10"PRIu64" TX-bytes: ""%-"PRIu64"\n",
529 : : nic_stats_border, port_id, nic_stats_border, stats.ipackets, stats.imissed,
530 : : stats.ibytes, stats.ierrors, stats.rx_nombuf, stats.opackets, stats.oerrors,
531 : : stats.obytes);
532 : :
533 : 0 : len = strlen(conn->msg_out) - len;
534 : 0 : conn->msg_out_len_max -= len;
535 : :
536 : : diff_ns = 0;
537 : : diff_cycles = 0;
538 : :
539 : : curr_cycles = rte_rdtsc();
540 : 0 : if (prev_cycles[port_id] != 0)
541 : 0 : diff_cycles = curr_cycles - prev_cycles[port_id];
542 : :
543 : 0 : prev_cycles[port_id] = curr_cycles;
544 : 0 : diff_ns = diff_cycles > 0 ?
545 : 0 : diff_cycles * (1 / (double)rte_get_tsc_hz()) * NS_PER_SEC : 0;
546 : :
547 : 0 : diff_pkts_rx = (stats.ipackets > prev_pkts_rx[port_id]) ?
548 : 0 : (stats.ipackets - prev_pkts_rx[port_id]) : 0;
549 : 0 : diff_pkts_tx = (stats.opackets > prev_pkts_tx[port_id]) ?
550 : 0 : (stats.opackets - prev_pkts_tx[port_id]) : 0;
551 : 0 : prev_pkts_rx[port_id] = stats.ipackets;
552 : 0 : prev_pkts_tx[port_id] = stats.opackets;
553 : 0 : mpps_rx = diff_ns > 0 ?
554 : 0 : (double)diff_pkts_rx / diff_ns * NS_PER_SEC : 0;
555 : 0 : mpps_tx = diff_ns > 0 ?
556 : 0 : (double)diff_pkts_tx / diff_ns * NS_PER_SEC : 0;
557 : :
558 : 0 : diff_bytes_rx = (stats.ibytes > prev_bytes_rx[port_id]) ?
559 : 0 : (stats.ibytes - prev_bytes_rx[port_id]) : 0;
560 : 0 : diff_bytes_tx = (stats.obytes > prev_bytes_tx[port_id]) ?
561 : 0 : (stats.obytes - prev_bytes_tx[port_id]) : 0;
562 : 0 : prev_bytes_rx[port_id] = stats.ibytes;
563 : 0 : prev_bytes_tx[port_id] = stats.obytes;
564 : 0 : mbps_rx = diff_ns > 0 ?
565 : 0 : (double)diff_bytes_rx / diff_ns * NS_PER_SEC : 0;
566 : 0 : mbps_tx = diff_ns > 0 ?
567 : 0 : (double)diff_bytes_tx / diff_ns * NS_PER_SEC : 0;
568 : :
569 : 0 : len = strlen(conn->msg_out);
570 : 0 : snprintf(conn->msg_out + len, conn->msg_out_len_max,
571 : : "\n Throughput (since last show)\n"
572 : : " Rx-pps: %12"PRIu64" Rx-bps: %12"PRIu64"\n Tx-pps: %12"
573 : : PRIu64" Tx-bps: %12"PRIu64"\n"
574 : : " %s############################%s\n",
575 : : mpps_rx, mbps_rx * 8, mpps_tx, mbps_tx * 8, nic_stats_border, nic_stats_border);
576 : 0 : return 0;
577 : : }
578 : :
579 : : static void
580 : 0 : cli_ethdev_mtu(void *parsed_result, __rte_unused struct cmdline *cl, void *data __rte_unused)
581 : : {
582 : : struct ethdev_mtu_cmd_tokens *res = parsed_result;
583 : : int rc = -EINVAL;
584 : :
585 : 0 : rc = ethdev_mtu_config(res->dev, res->size);
586 : 0 : if (rc < 0)
587 : 0 : printf(MSG_CMD_FAIL, res->cmd);
588 : 0 : }
589 : :
590 : : static void
591 : 0 : cli_ethdev_prom_mode(void *parsed_result, __rte_unused struct cmdline *cl, void *data __rte_unused)
592 : : {
593 : : struct ethdev_prom_mode_cmd_tokens *res = parsed_result;
594 : : bool enable = false;
595 : : int rc = -EINVAL;
596 : :
597 : 0 : if (!strcmp(res->enable, "on"))
598 : : enable = true;
599 : :
600 : 0 : rc = ethdev_prom_mode_config(res->dev, enable);
601 : 0 : if (rc < 0)
602 : 0 : printf(MSG_CMD_FAIL, res->cmd);
603 : 0 : }
604 : :
605 : : static void
606 : 0 : cli_ip4_addr(void *parsed_result, __rte_unused struct cmdline *cl, void *data __rte_unused)
607 : : {
608 : : struct ethdev_ip4_cmd_tokens *res = parsed_result;
609 : : struct ipv4_addr_config config;
610 : : int rc = -EINVAL;
611 : :
612 : 0 : if (parser_ip4_read(&config.ip, res->ip)) {
613 : : printf(MSG_ARG_INVALID, "ip");
614 : 0 : return;
615 : : }
616 : :
617 : 0 : if (parser_ip4_read(&config.mask, res->mask)) {
618 : : printf(MSG_ARG_INVALID, "netmask");
619 : 0 : return;
620 : : }
621 : :
622 : 0 : rc = ethdev_ip4_addr_add(res->dev, &config);
623 : 0 : if (rc < 0)
624 : 0 : printf(MSG_CMD_FAIL, res->cmd);
625 : : }
626 : :
627 : : static void
628 : 0 : cli_ip6_addr(void *parsed_result, __rte_unused struct cmdline *cl, void *data __rte_unused)
629 : : {
630 : : struct ethdev_ip6_cmd_tokens *res = parsed_result;
631 : : struct ipv6_addr_config config;
632 : : int rc = -EINVAL;
633 : :
634 : 0 : if (parser_ip6_read(config.ip, res->ip)) {
635 : : printf(MSG_ARG_INVALID, "ip");
636 : 0 : return;
637 : : }
638 : :
639 : 0 : if (parser_ip6_read(config.mask, res->mask)) {
640 : : printf(MSG_ARG_INVALID, "netmask");
641 : 0 : return;
642 : : }
643 : :
644 : 0 : rc = ethdev_ip6_addr_add(res->dev, &config);
645 : 0 : if (rc < 0)
646 : 0 : printf(MSG_CMD_FAIL, res->cmd);
647 : : }
648 : :
649 : : static void
650 : 0 : cli_ethdev_show(void *parsed_result, __rte_unused struct cmdline *cl, void *data __rte_unused)
651 : : {
652 : : struct ethdev_show_cmd_tokens *res = parsed_result;
653 : : int rc = -EINVAL;
654 : :
655 : 0 : rc = ethdev_show(res->dev);
656 : 0 : if (rc < 0)
657 : : printf(MSG_ARG_INVALID, res->dev);
658 : 0 : }
659 : :
660 : : static void
661 : 0 : cli_ethdev_stats(void *parsed_result, __rte_unused struct cmdline *cl, void *data __rte_unused)
662 : : {
663 : : struct ethdev_stats_cmd_tokens *res = parsed_result;
664 : : int rc = -EINVAL;
665 : :
666 : 0 : rc = ethdev_stats_show(res->dev);
667 : 0 : if (rc < 0)
668 : : printf(MSG_ARG_INVALID, res->dev);
669 : 0 : }
670 : :
671 : : static void
672 : 0 : cli_ethdev(void *parsed_result, __rte_unused struct cmdline *cl, void *data __rte_unused)
673 : : {
674 : : struct ethdev_cmd_tokens *res = parsed_result;
675 : : struct ethdev_config config;
676 : : int rc;
677 : :
678 : : memset(&config, 0, sizeof(struct ethdev_config));
679 : 0 : config.rx.n_queues = res->nb_rxq;
680 : 0 : config.rx.queue_size = ETHDEV_RX_DESC_DEFAULT;
681 : 0 : memcpy(config.rx.mempool_name, res->mempool, strlen(res->mempool));
682 : :
683 : 0 : config.tx.n_queues = res->nb_txq;
684 : 0 : config.tx.queue_size = ETHDEV_TX_DESC_DEFAULT;
685 : :
686 : 0 : config.mtu = port_conf_default.rxmode.mtu;
687 : :
688 : 0 : rc = ethdev_process(res->dev, &config);
689 : 0 : if (rc < 0)
690 : 0 : printf(MSG_CMD_FAIL, res->cmd);
691 : 0 : }
692 : :
693 : : static void
694 : 0 : cli_ethdev_help(__rte_unused void *parsed_result, __rte_unused struct cmdline *cl,
695 : : __rte_unused void *data)
696 : : {
697 : : size_t len;
698 : :
699 : 0 : len = strlen(conn->msg_out);
700 : 0 : conn->msg_out += len;
701 : 0 : snprintf(conn->msg_out, conn->msg_out_len_max, "\n%s\n%s\n%s\n%s\n%s\n%s\n%s\n%s\n",
702 : : "----------------------------- ethdev command help -----------------------------",
703 : : cmd_ethdev_help, cmd_ethdev_ip4_addr_help, cmd_ethdev_ip6_addr_help,
704 : : cmd_ethdev_prom_mode_help, cmd_ethdev_mtu_help, cmd_ethdev_stats_help,
705 : : cmd_ethdev_show_help);
706 : :
707 : 0 : len = strlen(conn->msg_out);
708 : 0 : conn->msg_out_len_max -= len;
709 : 0 : }
710 : :
711 : : cmdline_parse_token_string_t ethdev_stats_cmd =
712 : : TOKEN_STRING_INITIALIZER(struct ethdev_stats_cmd_tokens, cmd, "ethdev");
713 : : cmdline_parse_token_string_t ethdev_stats_dev =
714 : : TOKEN_STRING_INITIALIZER(struct ethdev_stats_cmd_tokens, dev, NULL);
715 : : cmdline_parse_token_string_t ethdev_stats_stats =
716 : : TOKEN_STRING_INITIALIZER(struct ethdev_stats_cmd_tokens, stats, "stats");
717 : :
718 : : cmdline_parse_inst_t ethdev_stats_cmd_ctx = {
719 : : .f = cli_ethdev_stats,
720 : : .data = NULL,
721 : : .help_str = "",
722 : : .tokens = {
723 : : (void *)ðdev_stats_cmd,
724 : : (void *)ðdev_stats_dev,
725 : : (void *)ðdev_stats_stats,
726 : : NULL,
727 : : },
728 : : };
729 : :
730 : : cmdline_parse_token_string_t ethdev_show_cmd =
731 : : TOKEN_STRING_INITIALIZER(struct ethdev_show_cmd_tokens, cmd, "ethdev");
732 : : cmdline_parse_token_string_t ethdev_show_dev =
733 : : TOKEN_STRING_INITIALIZER(struct ethdev_show_cmd_tokens, dev, NULL);
734 : : cmdline_parse_token_string_t ethdev_show_show =
735 : : TOKEN_STRING_INITIALIZER(struct ethdev_show_cmd_tokens, show, "show");
736 : :
737 : : cmdline_parse_inst_t ethdev_show_cmd_ctx = {
738 : : .f = cli_ethdev_show,
739 : : .data = NULL,
740 : : .help_str = cmd_ethdev_show_help,
741 : : .tokens = {
742 : : (void *)ðdev_show_cmd,
743 : : (void *)ðdev_show_dev,
744 : : (void *)ðdev_show_show,
745 : : NULL,
746 : : },
747 : : };
748 : :
749 : : cmdline_parse_token_string_t ethdev_mtu_cmd =
750 : : TOKEN_STRING_INITIALIZER(struct ethdev_mtu_cmd_tokens, cmd, "ethdev");
751 : : cmdline_parse_token_string_t ethdev_mtu_dev =
752 : : TOKEN_STRING_INITIALIZER(struct ethdev_mtu_cmd_tokens, dev, NULL);
753 : : cmdline_parse_token_string_t ethdev_mtu_mtu =
754 : : TOKEN_STRING_INITIALIZER(struct ethdev_mtu_cmd_tokens, mtu, "mtu");
755 : : cmdline_parse_token_num_t ethdev_mtu_size =
756 : : TOKEN_NUM_INITIALIZER(struct ethdev_mtu_cmd_tokens, size, RTE_UINT16);
757 : :
758 : : cmdline_parse_inst_t ethdev_mtu_cmd_ctx = {
759 : : .f = cli_ethdev_mtu,
760 : : .data = NULL,
761 : : .help_str = cmd_ethdev_mtu_help,
762 : : .tokens = {
763 : : (void *)ðdev_mtu_cmd,
764 : : (void *)ðdev_mtu_dev,
765 : : (void *)ðdev_mtu_mtu,
766 : : (void *)ðdev_mtu_size,
767 : : NULL,
768 : : },
769 : : };
770 : :
771 : : cmdline_parse_token_string_t ethdev_prom_mode_cmd =
772 : : TOKEN_STRING_INITIALIZER(struct ethdev_prom_mode_cmd_tokens, cmd, "ethdev");
773 : : cmdline_parse_token_string_t ethdev_prom_mode_dev =
774 : : TOKEN_STRING_INITIALIZER(struct ethdev_prom_mode_cmd_tokens, dev, NULL);
775 : : cmdline_parse_token_string_t ethdev_prom_mode_prom =
776 : : TOKEN_STRING_INITIALIZER(struct ethdev_prom_mode_cmd_tokens, prom, "promiscuous");
777 : : cmdline_parse_token_string_t ethdev_prom_mode_enable =
778 : : TOKEN_STRING_INITIALIZER(struct ethdev_prom_mode_cmd_tokens, enable, "on#off");
779 : :
780 : : cmdline_parse_inst_t ethdev_prom_mode_cmd_ctx = {
781 : : .f = cli_ethdev_prom_mode,
782 : : .data = NULL,
783 : : .help_str = cmd_ethdev_prom_mode_help,
784 : : .tokens = {
785 : : (void *)ðdev_prom_mode_cmd,
786 : : (void *)ðdev_prom_mode_dev,
787 : : (void *)ðdev_prom_mode_prom,
788 : : (void *)ðdev_prom_mode_enable,
789 : : NULL,
790 : : },
791 : : };
792 : :
793 : : cmdline_parse_token_string_t ethdev_ip4_cmd =
794 : : TOKEN_STRING_INITIALIZER(struct ethdev_ip4_cmd_tokens, cmd, "ethdev");
795 : : cmdline_parse_token_string_t ethdev_ip4_dev =
796 : : TOKEN_STRING_INITIALIZER(struct ethdev_ip4_cmd_tokens, dev, NULL);
797 : : cmdline_parse_token_string_t ethdev_ip4_ip4 =
798 : : TOKEN_STRING_INITIALIZER(struct ethdev_ip4_cmd_tokens, ip4, "ip4");
799 : : cmdline_parse_token_string_t ethdev_ip4_addr =
800 : : TOKEN_STRING_INITIALIZER(struct ethdev_ip4_cmd_tokens, addr, "addr");
801 : : cmdline_parse_token_string_t ethdev_ip4_add =
802 : : TOKEN_STRING_INITIALIZER(struct ethdev_ip4_cmd_tokens, add, "add");
803 : : cmdline_parse_token_string_t ethdev_ip4_ip =
804 : : TOKEN_STRING_INITIALIZER(struct ethdev_ip4_cmd_tokens, ip, NULL);
805 : : cmdline_parse_token_string_t ethdev_ip4_netmask =
806 : : TOKEN_STRING_INITIALIZER(struct ethdev_ip4_cmd_tokens, netmask, "netmask");
807 : : cmdline_parse_token_string_t ethdev_ip4_mask =
808 : : TOKEN_STRING_INITIALIZER(struct ethdev_ip4_cmd_tokens, mask, NULL);
809 : :
810 : : cmdline_parse_inst_t ethdev_ip4_cmd_ctx = {
811 : : .f = cli_ip4_addr,
812 : : .data = NULL,
813 : : .help_str = cmd_ethdev_ip4_addr_help,
814 : : .tokens = {
815 : : (void *)ðdev_ip4_cmd,
816 : : (void *)ðdev_ip4_dev,
817 : : (void *)ðdev_ip4_ip4,
818 : : (void *)ðdev_ip4_addr,
819 : : (void *)ðdev_ip4_add,
820 : : (void *)ðdev_ip4_ip,
821 : : (void *)ðdev_ip4_netmask,
822 : : (void *)ðdev_ip4_mask,
823 : : NULL,
824 : : },
825 : : };
826 : :
827 : : cmdline_parse_token_string_t ethdev_ip6_cmd =
828 : : TOKEN_STRING_INITIALIZER(struct ethdev_ip6_cmd_tokens, cmd, "ethdev");
829 : : cmdline_parse_token_string_t ethdev_ip6_dev =
830 : : TOKEN_STRING_INITIALIZER(struct ethdev_ip6_cmd_tokens, dev, NULL);
831 : : cmdline_parse_token_string_t ethdev_ip6_ip6 =
832 : : TOKEN_STRING_INITIALIZER(struct ethdev_ip6_cmd_tokens, ip6, "ip6");
833 : : cmdline_parse_token_string_t ethdev_ip6_addr =
834 : : TOKEN_STRING_INITIALIZER(struct ethdev_ip6_cmd_tokens, addr, "addr");
835 : : cmdline_parse_token_string_t ethdev_ip6_add =
836 : : TOKEN_STRING_INITIALIZER(struct ethdev_ip6_cmd_tokens, add, "add");
837 : : cmdline_parse_token_string_t ethdev_ip6_ip =
838 : : TOKEN_STRING_INITIALIZER(struct ethdev_ip6_cmd_tokens, ip, NULL);
839 : : cmdline_parse_token_string_t ethdev_ip6_netmask =
840 : : TOKEN_STRING_INITIALIZER(struct ethdev_ip6_cmd_tokens, netmask, "netmask");
841 : : cmdline_parse_token_string_t ethdev_ip6_mask =
842 : : TOKEN_STRING_INITIALIZER(struct ethdev_ip6_cmd_tokens, mask, NULL);
843 : :
844 : : cmdline_parse_inst_t ethdev_ip6_cmd_ctx = {
845 : : .f = cli_ip6_addr,
846 : : .data = NULL,
847 : : .help_str = cmd_ethdev_ip6_addr_help,
848 : : .tokens = {
849 : : (void *)ðdev_ip6_cmd,
850 : : (void *)ðdev_ip6_dev,
851 : : (void *)ðdev_ip6_ip6,
852 : : (void *)ðdev_ip6_addr,
853 : : (void *)ðdev_ip6_add,
854 : : (void *)ðdev_ip6_ip,
855 : : (void *)ðdev_ip6_netmask,
856 : : (void *)ðdev_ip6_mask,
857 : : NULL,
858 : : },
859 : : };
860 : :
861 : : cmdline_parse_token_string_t ethdev_cmd =
862 : : TOKEN_STRING_INITIALIZER(struct ethdev_cmd_tokens, cmd, "ethdev");
863 : : cmdline_parse_token_string_t ethdev_dev =
864 : : TOKEN_STRING_INITIALIZER(struct ethdev_cmd_tokens, dev, NULL);
865 : : cmdline_parse_token_string_t ethdev_rxq =
866 : : TOKEN_STRING_INITIALIZER(struct ethdev_cmd_tokens, rxq, "rxq");
867 : : cmdline_parse_token_num_t ethdev_nb_rxq =
868 : : TOKEN_NUM_INITIALIZER(struct ethdev_cmd_tokens, nb_rxq, RTE_UINT16);
869 : : cmdline_parse_token_string_t ethdev_txq =
870 : : TOKEN_STRING_INITIALIZER(struct ethdev_cmd_tokens, txq, "txq");
871 : : cmdline_parse_token_num_t ethdev_nb_txq =
872 : : TOKEN_NUM_INITIALIZER(struct ethdev_cmd_tokens, nb_txq, RTE_UINT16);
873 : : cmdline_parse_token_string_t ethdev_mempool =
874 : : TOKEN_STRING_INITIALIZER(struct ethdev_cmd_tokens, mempool, NULL);
875 : :
876 : : cmdline_parse_inst_t ethdev_cmd_ctx = {
877 : : .f = cli_ethdev,
878 : : .data = NULL,
879 : : .help_str = cmd_ethdev_help,
880 : : .tokens = {
881 : : (void *)ðdev_cmd,
882 : : (void *)ðdev_dev,
883 : : (void *)ðdev_rxq,
884 : : (void *)ðdev_nb_rxq,
885 : : (void *)ðdev_txq,
886 : : (void *)ðdev_nb_txq,
887 : : (void *)ðdev_mempool,
888 : : NULL,
889 : : },
890 : : };
891 : :
892 : : cmdline_parse_token_string_t ethdev_help_cmd =
893 : : TOKEN_STRING_INITIALIZER(struct ethdev_help_cmd_tokens, help, "help");
894 : : cmdline_parse_token_string_t ethdev_help_ethdev =
895 : : TOKEN_STRING_INITIALIZER(struct ethdev_help_cmd_tokens, ethdev, "ethdev");
896 : :
897 : : cmdline_parse_inst_t ethdev_help_cmd_ctx = {
898 : : .f = cli_ethdev_help,
899 : : .data = NULL,
900 : : .help_str = "",
901 : : .tokens = {
902 : : (void *)ðdev_help_cmd,
903 : : (void *)ðdev_help_ethdev,
904 : : NULL,
905 : : },
906 : : };
907 : :
908 : : static int
909 : 0 : ethdev_forward_config(char *tx_dev, char *rx_dev)
910 : : {
911 : 0 : uint16_t portid_rx = 0;
912 : 0 : uint16_t portid_tx = 0;
913 : : struct ethdev *port;
914 : : int rc = -EINVAL;
915 : :
916 : 0 : rc = rte_eth_dev_get_port_by_name(tx_dev, &portid_tx);
917 : 0 : if (rc < 0)
918 : : return rc;
919 : :
920 : 0 : rc = rte_eth_dev_get_port_by_name(rx_dev, &portid_rx);
921 : 0 : if (rc < 0)
922 : : return rc;
923 : :
924 : 0 : port = ethdev_port_by_id(portid_rx);
925 : 0 : if (port) {
926 : 0 : port->tx_port_id = portid_tx;
927 : : rc = 0;
928 : : } else {
929 : : rc = -EINVAL;
930 : : }
931 : :
932 : : return rc;
933 : : }
934 : :
935 : : static void
936 : 0 : cli_ethdev_forward(void *parsed_result, __rte_unused struct cmdline *cl, void *data __rte_unused)
937 : : {
938 : : struct ethdev_fwd_cmd_tokens *res = parsed_result;
939 : : int rc = -EINVAL;
940 : :
941 : 0 : rc = ethdev_forward_config(res->tx_dev, res->rx_dev);
942 : 0 : if (rc < 0)
943 : 0 : printf(MSG_CMD_FAIL, res->cmd);
944 : 0 : }
945 : :
946 : : cmdline_parse_token_string_t ethdev_fwd_cfg =
947 : : TOKEN_STRING_INITIALIZER(struct ethdev_fwd_cmd_tokens, cmd, "ethdev");
948 : : cmdline_parse_token_string_t ethdev_fwd_cmd =
949 : : TOKEN_STRING_INITIALIZER(struct ethdev_fwd_cmd_tokens, fwd, "forward");
950 : : cmdline_parse_token_string_t ethdev_tx_device =
951 : : TOKEN_STRING_INITIALIZER(struct ethdev_fwd_cmd_tokens, tx_dev, NULL);
952 : : cmdline_parse_token_string_t ethdev_rx_device =
953 : : TOKEN_STRING_INITIALIZER(struct ethdev_fwd_cmd_tokens, rx_dev, NULL);
954 : :
955 : : cmdline_parse_inst_t ethdev_forward_cmd_ctx = {
956 : : .f = cli_ethdev_forward,
957 : : .data = NULL,
958 : : .help_str = cmd_ethdev_forward_help,
959 : : .tokens = {
960 : : (void *)ðdev_fwd_cfg,
961 : : (void *)ðdev_fwd_cmd,
962 : : (void *)ðdev_tx_device,
963 : : (void *)ðdev_rx_device,
964 : : NULL,
965 : : },
966 : : };
|