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 TAILQ_FOREACH(port, ð_node, next) { 73 if (port->config.port_id == port_id) 74 return port; 75 } 76 return NULL; 77 } 78 79 int16_t 80 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 if (port) 87 portid = port->tx_port_id; 88 89 return portid; 90 } 91 92 void * 93 ethdev_mempool_list_by_portid(uint16_t portid) 94 { 95 struct ethdev *port; 96 97 if (portid >= RTE_MAX_ETHPORTS) 98 return NULL; 99 100 port = ethdev_port_by_id(portid); 101 if (port) 102 return &(port->config.rx.mp); 103 else 104 return NULL; 105 } 106 107 int16_t 108 ethdev_portid_by_ip4(uint32_t ip, uint32_t mask) 109 { 110 int portid = -EINVAL; 111 struct ethdev *port; 112 113 TAILQ_FOREACH(port, ð_node, next) { 114 if (mask == 0) { 115 if ((port->ip4_addr.ip & port->ip4_addr.mask) == (ip & port->ip4_addr.mask)) 116 return port->config.port_id; 117 } else { 118 if ((port->ip4_addr.ip & port->ip4_addr.mask) == (ip & mask)) 119 return port->config.port_id; 120 } 121 } 122 123 return portid; 124 } 125 126 int16_t 127 ethdev_portid_by_ip6(uint8_t *ip, uint8_t *mask) 128 { 129 int portid = -EINVAL; 130 struct ethdev *port; 131 int j; 132 133 TAILQ_FOREACH(port, ð_node, next) { 134 for (j = 0; j < ETHDEV_IPV6_ADDR_LEN; j++) { 135 if (mask == NULL) { 136 if ((port->ip6_addr.ip[j] & port->ip6_addr.mask[j]) != 137 (ip[j] & port->ip6_addr.mask[j])) 138 break; 139 140 } else { 141 if ((port->ip6_addr.ip[j] & port->ip6_addr.mask[j]) != 142 (ip[j] & mask[j])) 143 break; 144 } 145 } 146 if (j == ETHDEV_IPV6_ADDR_LEN) 147 return port->config.port_id; 148 } 149 150 return portid; 151 } 152 153 void 154 ethdev_list_clean(void) 155 { 156 struct ethdev *port; 157 158 while (!TAILQ_EMPTY(ð_node)) { 159 port = TAILQ_FIRST(ð_node); 160 TAILQ_REMOVE(ð_node, port, next); 161 } 162 } 163 164 void 165 ethdev_stop(void) 166 { 167 uint16_t portid; 168 int rc; 169 170 RTE_ETH_FOREACH_DEV(portid) { 171 if ((enabled_port_mask & (1 << portid)) == 0) 172 continue; 173 printf("Closing port %d...", portid); 174 rc = rte_eth_dev_stop(portid); 175 if (rc != 0) 176 printf("Failed to stop port %u: %s\n", 177 portid, rte_strerror(-rc)); 178 rte_eth_dev_close(portid); 179 printf(" Done\n"); 180 } 181 182 ethdev_list_clean(); 183 route_ip4_list_clean(); 184 route_ip6_list_clean(); 185 neigh4_list_clean(); 186 neigh6_list_clean(); 187 printf("Bye...\n"); 188 } 189 190 void 191 ethdev_start(void) 192 { 193 uint16_t portid; 194 int rc; 195 196 RTE_ETH_FOREACH_DEV(portid) 197 { 198 if ((enabled_port_mask & (1 << portid)) == 0) 199 continue; 200 201 rc = rte_eth_dev_start(portid); 202 if (rc < 0) 203 rte_exit(EXIT_FAILURE, "rte_eth_dev_start: err=%d, port=%d\n", rc, portid); 204 } 205 } 206 207 208 static int 209 ethdev_show(const char *name) 210 { 211 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 rc = rte_eth_dev_get_port_by_name(name, &port_id); 220 if (rc < 0) 221 return rc; 222 223 rte_eth_dev_info_get(port_id, &info); 224 rte_eth_stats_get(port_id, &stats); 225 rte_eth_macaddr_get(port_id, &addr); 226 rte_eth_link_get(port_id, &link); 227 rte_eth_dev_get_mtu(port_id, &mtu); 228 229 length = strlen(conn->msg_out); 230 conn->msg_out += length; 231 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 link.link_status ? "UP" : "DOWN", 241 mtu, 242 RTE_ETHER_ADDR_BYTES(&addr), 243 info.nb_rx_queues, 244 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 length = strlen(conn->msg_out); 257 conn->msg_out_len_max -= length; 258 return 0; 259 } 260 261 static int 262 ethdev_ip4_addr_add(const char *name, struct ipv4_addr_config *config) 263 { 264 struct ethdev *eth_hdl; 265 uint16_t portid = 0; 266 int rc; 267 268 rc = rte_eth_dev_get_port_by_name(name, &portid); 269 if (rc < 0) 270 return rc; 271 272 eth_hdl = ethdev_port_by_id(portid); 273 274 if (eth_hdl) { 275 eth_hdl->ip4_addr.ip = config->ip; 276 eth_hdl->ip4_addr.mask = config->mask; 277 return 0; 278 } 279 280 rc = -EINVAL; 281 return rc; 282 } 283 284 static int 285 ethdev_ip6_addr_add(const char *name, struct ipv6_addr_config *config) 286 { 287 struct ethdev *eth_hdl; 288 uint16_t portid = 0; 289 int rc, i; 290 291 rc = rte_eth_dev_get_port_by_name(name, &portid); 292 if (rc < 0) 293 return rc; 294 295 eth_hdl = ethdev_port_by_id(portid); 296 297 if (eth_hdl) { 298 for (i = 0; i < ETHDEV_IPV6_ADDR_LEN; i++) { 299 eth_hdl->ip6_addr.ip[i] = config->ip[i]; 300 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 ethdev_prom_mode_config(const char *name, bool enable) 310 { 311 struct ethdev *eth_hdl; 312 uint16_t portid = 0; 313 int rc; 314 315 rc = rte_eth_dev_get_port_by_name(name, &portid); 316 if (rc < 0) 317 return rc; 318 319 eth_hdl = ethdev_port_by_id(portid); 320 321 if (eth_hdl) { 322 if (enable) 323 rc = rte_eth_promiscuous_enable(portid); 324 else 325 rc = rte_eth_promiscuous_disable(portid); 326 if (rc < 0) 327 return rc; 328 329 eth_hdl->config.promiscuous = enable; 330 return 0; 331 } 332 333 rc = -EINVAL; 334 return rc; 335 } 336 337 static int 338 ethdev_mtu_config(const char *name, uint32_t mtu) 339 { 340 struct ethdev *eth_hdl; 341 uint16_t portid = 0; 342 int rc; 343 344 rc = rte_eth_dev_get_port_by_name(name, &portid); 345 if (rc < 0) 346 return rc; 347 348 eth_hdl = ethdev_port_by_id(portid); 349 350 if (eth_hdl) { 351 rc = rte_eth_dev_set_mtu(portid, mtu); 352 if (rc < 0) 353 return rc; 354 355 eth_hdl->config.mtu = mtu; 356 return 0; 357 } 358 359 rc = -EINVAL; 360 return rc; 361 } 362 363 364 static int 365 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 uint16_t port_id = 0; 374 int numa_node, rc; 375 uint32_t i; 376 377 /* Check input params */ 378 if (!name || !name[0] || !params || !params->rx.n_queues || !params->rx.queue_size || 379 !params->tx.n_queues || !params->tx.queue_size) 380 return -EINVAL; 381 382 rc = rte_eth_dev_get_port_by_name(name, &port_id); 383 if (rc) 384 return -EINVAL; 385 386 if (!ethdev_port_by_id(port_id)) { 387 ethdev_port = malloc(sizeof(struct ethdev)); 388 if (!ethdev_port) 389 return -EINVAL; 390 } else { 391 return 0; 392 } 393 394 rc = rte_eth_dev_info_get(port_id, &port_info); 395 if (rc) { 396 rc = -EINVAL; 397 goto exit; 398 } 399 400 mempool = rte_mempool_lookup(params->rx.mempool_name); 401 if (!mempool) { 402 rc = -EINVAL; 403 goto exit; 404 } 405 406 params->rx.mp = mempool; 407 408 rss = params->rx.rss; 409 if (rss) { 410 if (!port_info.reta_size || port_info.reta_size > RTE_ETH_RSS_RETA_SIZE_512) { 411 rc = -EINVAL; 412 goto exit; 413 } 414 415 if (!rss->n_queues || rss->n_queues >= ETHDEV_RXQ_RSS_MAX) { 416 rc = -EINVAL; 417 goto exit; 418 } 419 420 for (i = 0; i < rss->n_queues; i++) 421 if (rss->queue_id[i] >= port_info.max_rx_queues) { 422 rc = -EINVAL; 423 goto exit; 424 } 425 } 426 427 /* Port */ 428 memcpy(&port_conf, &port_conf_default, sizeof(struct rte_eth_conf)); 429 if (rss) { 430 uint64_t rss_hf = RTE_ETH_RSS_IP | RTE_ETH_RSS_TCP | RTE_ETH_RSS_UDP; 431 432 port_conf.rxmode.mq_mode = RTE_ETH_MQ_RX_RSS; 433 port_conf.rx_adv_conf.rss_conf.rss_hf = rss_hf & port_info.flow_type_rss_offloads; 434 } 435 436 numa_node = rte_eth_dev_socket_id(port_id); 437 if (numa_node == SOCKET_ID_ANY) 438 numa_node = 0; 439 440 if (params->mtu) 441 port_conf.rxmode.mtu = params->mtu; 442 443 rc = rte_eth_dev_configure(port_id, params->rx.n_queues, params->tx.n_queues, 444 &port_conf); 445 if (rc < 0) { 446 rc = -EINVAL; 447 goto exit; 448 } 449 450 rc = rte_eth_macaddr_get(port_id, &smac); 451 if (rc < 0) { 452 rc = -EINVAL; 453 goto exit; 454 } 455 456 printf("Port_id = %d srcmac = %x:%x:%x:%x:%x:%x\n", port_id, 457 smac.addr_bytes[0], smac.addr_bytes[1], 458 smac.addr_bytes[2], smac.addr_bytes[3], 459 smac.addr_bytes[4], smac.addr_bytes[5]); 460 461 /* Port RX */ 462 for (i = 0; i < params->rx.n_queues; i++) { 463 rc = rte_eth_rx_queue_setup(port_id, i, params->rx.queue_size, numa_node, NULL, 464 mempool); 465 if (rc < 0) { 466 rc = -EINVAL; 467 goto exit; 468 } 469 } 470 471 /* Port TX */ 472 for (i = 0; i < params->tx.n_queues; i++) { 473 rc = rte_eth_tx_queue_setup(port_id, i, params->tx.queue_size, numa_node, NULL); 474 if (rc < 0) { 475 rc = -EINVAL; 476 goto exit; 477 } 478 } 479 480 memcpy(ðdev_port->config, params, sizeof(struct ethdev_config)); 481 memcpy(ethdev_port->config.dev_name, name, strlen(name)); 482 ethdev_port->config.port_id = port_id; 483 enabled_port_mask |= RTE_BIT32(port_id); 484 485 TAILQ_INSERT_TAIL(ð_node, ethdev_port, next); 486 return 0; 487 exit: 488 free(ethdev_port); 489 return rc; 490 491 } 492 493 static int 494 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 rc = rte_eth_dev_get_port_by_name(name, &port_id); 510 if (rc < 0) 511 return rc; 512 513 rc = rte_eth_stats_get(port_id, &stats); 514 if (rc != 0) { 515 fprintf(stderr, 516 "%s: Error: failed to get stats (port %u): %d", 517 __func__, port_id, rc); 518 return rc; 519 } 520 521 len = strlen(conn->msg_out); 522 conn->msg_out += len; 523 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 len = strlen(conn->msg_out) - len; 534 conn->msg_out_len_max -= len; 535 536 diff_ns = 0; 537 diff_cycles = 0; 538 539 curr_cycles = rte_rdtsc(); 540 if (prev_cycles[port_id] != 0) 541 diff_cycles = curr_cycles - prev_cycles[port_id]; 542 543 prev_cycles[port_id] = curr_cycles; 544 diff_ns = diff_cycles > 0 ? 545 diff_cycles * (1 / (double)rte_get_tsc_hz()) * NS_PER_SEC : 0; 546 547 diff_pkts_rx = (stats.ipackets > prev_pkts_rx[port_id]) ? 548 (stats.ipackets - prev_pkts_rx[port_id]) : 0; 549 diff_pkts_tx = (stats.opackets > prev_pkts_tx[port_id]) ? 550 (stats.opackets - prev_pkts_tx[port_id]) : 0; 551 prev_pkts_rx[port_id] = stats.ipackets; 552 prev_pkts_tx[port_id] = stats.opackets; 553 mpps_rx = diff_ns > 0 ? 554 (double)diff_pkts_rx / diff_ns * NS_PER_SEC : 0; 555 mpps_tx = diff_ns > 0 ? 556 (double)diff_pkts_tx / diff_ns * NS_PER_SEC : 0; 557 558 diff_bytes_rx = (stats.ibytes > prev_bytes_rx[port_id]) ? 559 (stats.ibytes - prev_bytes_rx[port_id]) : 0; 560 diff_bytes_tx = (stats.obytes > prev_bytes_tx[port_id]) ? 561 (stats.obytes - prev_bytes_tx[port_id]) : 0; 562 prev_bytes_rx[port_id] = stats.ibytes; 563 prev_bytes_tx[port_id] = stats.obytes; 564 mbps_rx = diff_ns > 0 ? 565 (double)diff_bytes_rx / diff_ns * NS_PER_SEC : 0; 566 mbps_tx = diff_ns > 0 ? 567 (double)diff_bytes_tx / diff_ns * NS_PER_SEC : 0; 568 569 len = strlen(conn->msg_out); 570 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 return 0; 577 } 578 579 static void 580 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 rc = ethdev_mtu_config(res->dev, res->size); 586 if (rc < 0) 587 printf(MSG_CMD_FAIL, res->cmd); 588 } 589 590 static void 591 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 if (!strcmp(res->enable, "on")) 598 enable = true; 599 600 rc = ethdev_prom_mode_config(res->dev, enable); 601 if (rc < 0) 602 printf(MSG_CMD_FAIL, res->cmd); 603 } 604 605 static void 606 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 if (parser_ip4_read(&config.ip, res->ip)) { 613 printf(MSG_ARG_INVALID, "ip"); 614 return; 615 } 616 617 if (parser_ip4_read(&config.mask, res->mask)) { 618 printf(MSG_ARG_INVALID, "netmask"); 619 return; 620 } 621 622 rc = ethdev_ip4_addr_add(res->dev, &config); 623 if (rc < 0) 624 printf(MSG_CMD_FAIL, res->cmd); 625 } 626 627 static void 628 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 if (parser_ip6_read(config.ip, res->ip)) { 635 printf(MSG_ARG_INVALID, "ip"); 636 return; 637 } 638 639 if (parser_ip6_read(config.mask, res->mask)) { 640 printf(MSG_ARG_INVALID, "netmask"); 641 return; 642 } 643 644 rc = ethdev_ip6_addr_add(res->dev, &config); 645 if (rc < 0) 646 printf(MSG_CMD_FAIL, res->cmd); 647 } 648 649 static void 650 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 rc = ethdev_show(res->dev); 656 if (rc < 0) 657 printf(MSG_ARG_INVALID, res->dev); 658 } 659 660 static void 661 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 rc = ethdev_stats_show(res->dev); 667 if (rc < 0) 668 printf(MSG_ARG_INVALID, res->dev); 669 } 670 671 static void 672 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 config.rx.n_queues = res->nb_rxq; 680 config.rx.queue_size = ETHDEV_RX_DESC_DEFAULT; 681 memcpy(config.rx.mempool_name, res->mempool, strlen(res->mempool)); 682 683 config.tx.n_queues = res->nb_txq; 684 config.tx.queue_size = ETHDEV_TX_DESC_DEFAULT; 685 686 config.mtu = port_conf_default.rxmode.mtu; 687 688 rc = ethdev_process(res->dev, &config); 689 if (rc < 0) 690 printf(MSG_CMD_FAIL, res->cmd); 691 } 692 693 static void 694 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 len = strlen(conn->msg_out); 700 conn->msg_out += len; 701 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 len = strlen(conn->msg_out); 708 conn->msg_out_len_max -= len; 709 } 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 ethdev_forward_config(char *tx_dev, char *rx_dev) 910 { 911 uint16_t portid_rx = 0; 912 uint16_t portid_tx = 0; 913 struct ethdev *port; 914 int rc = -EINVAL; 915 916 rc = rte_eth_dev_get_port_by_name(tx_dev, &portid_tx); 917 if (rc < 0) 918 return rc; 919 920 rc = rte_eth_dev_get_port_by_name(rx_dev, &portid_rx); 921 if (rc < 0) 922 return rc; 923 924 port = ethdev_port_by_id(portid_rx); 925 if (port) { 926 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 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 rc = ethdev_forward_config(res->tx_dev, res->rx_dev); 942 if (rc < 0) 943 printf(MSG_CMD_FAIL, res->cmd); 944 } 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 }; 967