1 /* SPDX-License-Identifier: BSD-3-Clause 2 * Copyright(c) 2010-2016 Intel Corporation. 3 * Copyright 2013-2014 6WIND S.A. 4 */ 5 6 #include <stdarg.h> 7 #include <errno.h> 8 #include <stdio.h> 9 #include <string.h> 10 #include <stdint.h> 11 #include <inttypes.h> 12 13 #include <sys/queue.h> 14 #include <sys/types.h> 15 #include <sys/stat.h> 16 #include <fcntl.h> 17 #include <unistd.h> 18 19 #include <rte_common.h> 20 #include <rte_byteorder.h> 21 #include <rte_debug.h> 22 #include <rte_log.h> 23 #include <rte_memory.h> 24 #include <rte_memcpy.h> 25 #include <rte_memzone.h> 26 #include <rte_launch.h> 27 #include <rte_eal.h> 28 #include <rte_per_lcore.h> 29 #include <rte_lcore.h> 30 #include <rte_atomic.h> 31 #include <rte_branch_prediction.h> 32 #include <rte_mempool.h> 33 #include <rte_mbuf.h> 34 #include <rte_interrupts.h> 35 #include <rte_pci.h> 36 #include <rte_ether.h> 37 #include <rte_ethdev.h> 38 #include <rte_string_fns.h> 39 #include <rte_cycles.h> 40 #include <rte_flow.h> 41 #include <rte_errno.h> 42 #ifdef RTE_NET_IXGBE 43 #include <rte_pmd_ixgbe.h> 44 #endif 45 #ifdef RTE_NET_I40E 46 #include <rte_pmd_i40e.h> 47 #endif 48 #ifdef RTE_NET_BNXT 49 #include <rte_pmd_bnxt.h> 50 #endif 51 #include <rte_gro.h> 52 #include <rte_hexdump.h> 53 54 #include "testpmd.h" 55 56 #define ETHDEV_FWVERS_LEN 32 57 58 #ifdef CLOCK_MONOTONIC_RAW /* Defined in glibc bits/time.h */ 59 #define CLOCK_TYPE_ID CLOCK_MONOTONIC_RAW 60 #else 61 #define CLOCK_TYPE_ID CLOCK_MONOTONIC 62 #endif 63 64 #define NS_PER_SEC 1E9 65 66 static char *flowtype_to_str(uint16_t flow_type); 67 68 static const struct { 69 enum tx_pkt_split split; 70 const char *name; 71 } tx_split_name[] = { 72 { 73 .split = TX_PKT_SPLIT_OFF, 74 .name = "off", 75 }, 76 { 77 .split = TX_PKT_SPLIT_ON, 78 .name = "on", 79 }, 80 { 81 .split = TX_PKT_SPLIT_RND, 82 .name = "rand", 83 }, 84 }; 85 86 const struct rss_type_info rss_type_table[] = { 87 { "all", ETH_RSS_ETH | ETH_RSS_VLAN | ETH_RSS_IP | ETH_RSS_TCP | 88 ETH_RSS_UDP | ETH_RSS_SCTP | ETH_RSS_L2_PAYLOAD | 89 ETH_RSS_L2TPV3 | ETH_RSS_ESP | ETH_RSS_AH | ETH_RSS_PFCP | 90 ETH_RSS_GTPU | ETH_RSS_ECPRI}, 91 { "none", 0 }, 92 { "eth", ETH_RSS_ETH }, 93 { "l2-src-only", ETH_RSS_L2_SRC_ONLY }, 94 { "l2-dst-only", ETH_RSS_L2_DST_ONLY }, 95 { "vlan", ETH_RSS_VLAN }, 96 { "s-vlan", ETH_RSS_S_VLAN }, 97 { "c-vlan", ETH_RSS_C_VLAN }, 98 { "ipv4", ETH_RSS_IPV4 }, 99 { "ipv4-frag", ETH_RSS_FRAG_IPV4 }, 100 { "ipv4-tcp", ETH_RSS_NONFRAG_IPV4_TCP }, 101 { "ipv4-udp", ETH_RSS_NONFRAG_IPV4_UDP }, 102 { "ipv4-sctp", ETH_RSS_NONFRAG_IPV4_SCTP }, 103 { "ipv4-other", ETH_RSS_NONFRAG_IPV4_OTHER }, 104 { "ipv6", ETH_RSS_IPV6 }, 105 { "ipv6-frag", ETH_RSS_FRAG_IPV6 }, 106 { "ipv6-tcp", ETH_RSS_NONFRAG_IPV6_TCP }, 107 { "ipv6-udp", ETH_RSS_NONFRAG_IPV6_UDP }, 108 { "ipv6-sctp", ETH_RSS_NONFRAG_IPV6_SCTP }, 109 { "ipv6-other", ETH_RSS_NONFRAG_IPV6_OTHER }, 110 { "l2-payload", ETH_RSS_L2_PAYLOAD }, 111 { "ipv6-ex", ETH_RSS_IPV6_EX }, 112 { "ipv6-tcp-ex", ETH_RSS_IPV6_TCP_EX }, 113 { "ipv6-udp-ex", ETH_RSS_IPV6_UDP_EX }, 114 { "port", ETH_RSS_PORT }, 115 { "vxlan", ETH_RSS_VXLAN }, 116 { "geneve", ETH_RSS_GENEVE }, 117 { "nvgre", ETH_RSS_NVGRE }, 118 { "ip", ETH_RSS_IP }, 119 { "udp", ETH_RSS_UDP }, 120 { "tcp", ETH_RSS_TCP }, 121 { "sctp", ETH_RSS_SCTP }, 122 { "tunnel", ETH_RSS_TUNNEL }, 123 { "l3-pre32", RTE_ETH_RSS_L3_PRE32 }, 124 { "l3-pre40", RTE_ETH_RSS_L3_PRE40 }, 125 { "l3-pre48", RTE_ETH_RSS_L3_PRE48 }, 126 { "l3-pre56", RTE_ETH_RSS_L3_PRE56 }, 127 { "l3-pre64", RTE_ETH_RSS_L3_PRE64 }, 128 { "l3-pre96", RTE_ETH_RSS_L3_PRE96 }, 129 { "l3-src-only", ETH_RSS_L3_SRC_ONLY }, 130 { "l3-dst-only", ETH_RSS_L3_DST_ONLY }, 131 { "l4-src-only", ETH_RSS_L4_SRC_ONLY }, 132 { "l4-dst-only", ETH_RSS_L4_DST_ONLY }, 133 { "esp", ETH_RSS_ESP }, 134 { "ah", ETH_RSS_AH }, 135 { "l2tpv3", ETH_RSS_L2TPV3 }, 136 { "pfcp", ETH_RSS_PFCP }, 137 { "pppoe", ETH_RSS_PPPOE }, 138 { "gtpu", ETH_RSS_GTPU }, 139 { "ecpri", ETH_RSS_ECPRI }, 140 { NULL, 0 }, 141 }; 142 143 static const struct { 144 enum rte_eth_fec_mode mode; 145 const char *name; 146 } fec_mode_name[] = { 147 { 148 .mode = RTE_ETH_FEC_NOFEC, 149 .name = "off", 150 }, 151 { 152 .mode = RTE_ETH_FEC_AUTO, 153 .name = "auto", 154 }, 155 { 156 .mode = RTE_ETH_FEC_BASER, 157 .name = "baser", 158 }, 159 { 160 .mode = RTE_ETH_FEC_RS, 161 .name = "rs", 162 }, 163 }; 164 165 static void 166 print_ethaddr(const char *name, struct rte_ether_addr *eth_addr) 167 { 168 char buf[RTE_ETHER_ADDR_FMT_SIZE]; 169 rte_ether_format_addr(buf, RTE_ETHER_ADDR_FMT_SIZE, eth_addr); 170 printf("%s%s", name, buf); 171 } 172 173 void 174 nic_stats_display(portid_t port_id) 175 { 176 static uint64_t prev_pkts_rx[RTE_MAX_ETHPORTS]; 177 static uint64_t prev_pkts_tx[RTE_MAX_ETHPORTS]; 178 static uint64_t prev_bytes_rx[RTE_MAX_ETHPORTS]; 179 static uint64_t prev_bytes_tx[RTE_MAX_ETHPORTS]; 180 static uint64_t prev_ns[RTE_MAX_ETHPORTS]; 181 struct timespec cur_time; 182 uint64_t diff_pkts_rx, diff_pkts_tx, diff_bytes_rx, diff_bytes_tx, 183 diff_ns; 184 uint64_t mpps_rx, mpps_tx, mbps_rx, mbps_tx; 185 struct rte_eth_stats stats; 186 187 static const char *nic_stats_border = "########################"; 188 189 if (port_id_is_invalid(port_id, ENABLED_WARN)) { 190 print_valid_ports(); 191 return; 192 } 193 rte_eth_stats_get(port_id, &stats); 194 printf("\n %s NIC statistics for port %-2d %s\n", 195 nic_stats_border, port_id, nic_stats_border); 196 197 printf(" RX-packets: %-10"PRIu64" RX-missed: %-10"PRIu64" RX-bytes: " 198 "%-"PRIu64"\n", stats.ipackets, stats.imissed, stats.ibytes); 199 printf(" RX-errors: %-"PRIu64"\n", stats.ierrors); 200 printf(" RX-nombuf: %-10"PRIu64"\n", stats.rx_nombuf); 201 printf(" TX-packets: %-10"PRIu64" TX-errors: %-10"PRIu64" TX-bytes: " 202 "%-"PRIu64"\n", stats.opackets, stats.oerrors, stats.obytes); 203 204 diff_ns = 0; 205 if (clock_gettime(CLOCK_TYPE_ID, &cur_time) == 0) { 206 uint64_t ns; 207 208 ns = cur_time.tv_sec * NS_PER_SEC; 209 ns += cur_time.tv_nsec; 210 211 if (prev_ns[port_id] != 0) 212 diff_ns = ns - prev_ns[port_id]; 213 prev_ns[port_id] = ns; 214 } 215 216 diff_pkts_rx = (stats.ipackets > prev_pkts_rx[port_id]) ? 217 (stats.ipackets - prev_pkts_rx[port_id]) : 0; 218 diff_pkts_tx = (stats.opackets > prev_pkts_tx[port_id]) ? 219 (stats.opackets - prev_pkts_tx[port_id]) : 0; 220 prev_pkts_rx[port_id] = stats.ipackets; 221 prev_pkts_tx[port_id] = stats.opackets; 222 mpps_rx = diff_ns > 0 ? 223 (double)diff_pkts_rx / diff_ns * NS_PER_SEC : 0; 224 mpps_tx = diff_ns > 0 ? 225 (double)diff_pkts_tx / diff_ns * NS_PER_SEC : 0; 226 227 diff_bytes_rx = (stats.ibytes > prev_bytes_rx[port_id]) ? 228 (stats.ibytes - prev_bytes_rx[port_id]) : 0; 229 diff_bytes_tx = (stats.obytes > prev_bytes_tx[port_id]) ? 230 (stats.obytes - prev_bytes_tx[port_id]) : 0; 231 prev_bytes_rx[port_id] = stats.ibytes; 232 prev_bytes_tx[port_id] = stats.obytes; 233 mbps_rx = diff_ns > 0 ? 234 (double)diff_bytes_rx / diff_ns * NS_PER_SEC : 0; 235 mbps_tx = diff_ns > 0 ? 236 (double)diff_bytes_tx / diff_ns * NS_PER_SEC : 0; 237 238 printf("\n Throughput (since last show)\n"); 239 printf(" Rx-pps: %12"PRIu64" Rx-bps: %12"PRIu64"\n Tx-pps: %12" 240 PRIu64" Tx-bps: %12"PRIu64"\n", mpps_rx, mbps_rx * 8, 241 mpps_tx, mbps_tx * 8); 242 243 printf(" %s############################%s\n", 244 nic_stats_border, nic_stats_border); 245 } 246 247 void 248 nic_stats_clear(portid_t port_id) 249 { 250 int ret; 251 252 if (port_id_is_invalid(port_id, ENABLED_WARN)) { 253 print_valid_ports(); 254 return; 255 } 256 257 ret = rte_eth_stats_reset(port_id); 258 if (ret != 0) { 259 printf("%s: Error: failed to reset stats (port %u): %s", 260 __func__, port_id, strerror(-ret)); 261 return; 262 } 263 264 ret = rte_eth_stats_get(port_id, &ports[port_id].stats); 265 if (ret != 0) { 266 if (ret < 0) 267 ret = -ret; 268 printf("%s: Error: failed to get stats (port %u): %s", 269 __func__, port_id, strerror(ret)); 270 return; 271 } 272 printf("\n NIC statistics for port %d cleared\n", port_id); 273 } 274 275 void 276 nic_xstats_display(portid_t port_id) 277 { 278 struct rte_eth_xstat *xstats; 279 int cnt_xstats, idx_xstat; 280 struct rte_eth_xstat_name *xstats_names; 281 282 if (port_id_is_invalid(port_id, ENABLED_WARN)) { 283 print_valid_ports(); 284 return; 285 } 286 printf("###### NIC extended statistics for port %-2d\n", port_id); 287 if (!rte_eth_dev_is_valid_port(port_id)) { 288 printf("Error: Invalid port number %i\n", port_id); 289 return; 290 } 291 292 /* Get count */ 293 cnt_xstats = rte_eth_xstats_get_names(port_id, NULL, 0); 294 if (cnt_xstats < 0) { 295 printf("Error: Cannot get count of xstats\n"); 296 return; 297 } 298 299 /* Get id-name lookup table */ 300 xstats_names = malloc(sizeof(struct rte_eth_xstat_name) * cnt_xstats); 301 if (xstats_names == NULL) { 302 printf("Cannot allocate memory for xstats lookup\n"); 303 return; 304 } 305 if (cnt_xstats != rte_eth_xstats_get_names( 306 port_id, xstats_names, cnt_xstats)) { 307 printf("Error: Cannot get xstats lookup\n"); 308 free(xstats_names); 309 return; 310 } 311 312 /* Get stats themselves */ 313 xstats = malloc(sizeof(struct rte_eth_xstat) * cnt_xstats); 314 if (xstats == NULL) { 315 printf("Cannot allocate memory for xstats\n"); 316 free(xstats_names); 317 return; 318 } 319 if (cnt_xstats != rte_eth_xstats_get(port_id, xstats, cnt_xstats)) { 320 printf("Error: Unable to get xstats\n"); 321 free(xstats_names); 322 free(xstats); 323 return; 324 } 325 326 /* Display xstats */ 327 for (idx_xstat = 0; idx_xstat < cnt_xstats; idx_xstat++) { 328 if (xstats_hide_zero && !xstats[idx_xstat].value) 329 continue; 330 printf("%s: %"PRIu64"\n", 331 xstats_names[idx_xstat].name, 332 xstats[idx_xstat].value); 333 } 334 free(xstats_names); 335 free(xstats); 336 } 337 338 void 339 nic_xstats_clear(portid_t port_id) 340 { 341 int ret; 342 343 if (port_id_is_invalid(port_id, ENABLED_WARN)) { 344 print_valid_ports(); 345 return; 346 } 347 348 ret = rte_eth_xstats_reset(port_id); 349 if (ret != 0) { 350 printf("%s: Error: failed to reset xstats (port %u): %s", 351 __func__, port_id, strerror(-ret)); 352 return; 353 } 354 355 ret = rte_eth_stats_get(port_id, &ports[port_id].stats); 356 if (ret != 0) { 357 if (ret < 0) 358 ret = -ret; 359 printf("%s: Error: failed to get stats (port %u): %s", 360 __func__, port_id, strerror(ret)); 361 return; 362 } 363 } 364 365 void 366 rx_queue_infos_display(portid_t port_id, uint16_t queue_id) 367 { 368 struct rte_eth_burst_mode mode; 369 struct rte_eth_rxq_info qinfo; 370 int32_t rc; 371 static const char *info_border = "*********************"; 372 373 rc = rte_eth_rx_queue_info_get(port_id, queue_id, &qinfo); 374 if (rc != 0) { 375 printf("Failed to retrieve information for port: %u, " 376 "RX queue: %hu\nerror desc: %s(%d)\n", 377 port_id, queue_id, strerror(-rc), rc); 378 return; 379 } 380 381 printf("\n%s Infos for port %-2u, RX queue %-2u %s", 382 info_border, port_id, queue_id, info_border); 383 384 printf("\nMempool: %s", (qinfo.mp == NULL) ? "NULL" : qinfo.mp->name); 385 printf("\nRX prefetch threshold: %hhu", qinfo.conf.rx_thresh.pthresh); 386 printf("\nRX host threshold: %hhu", qinfo.conf.rx_thresh.hthresh); 387 printf("\nRX writeback threshold: %hhu", qinfo.conf.rx_thresh.wthresh); 388 printf("\nRX free threshold: %hu", qinfo.conf.rx_free_thresh); 389 printf("\nRX drop packets: %s", 390 (qinfo.conf.rx_drop_en != 0) ? "on" : "off"); 391 printf("\nRX deferred start: %s", 392 (qinfo.conf.rx_deferred_start != 0) ? "on" : "off"); 393 printf("\nRX scattered packets: %s", 394 (qinfo.scattered_rx != 0) ? "on" : "off"); 395 if (qinfo.rx_buf_size != 0) 396 printf("\nRX buffer size: %hu", qinfo.rx_buf_size); 397 printf("\nNumber of RXDs: %hu", qinfo.nb_desc); 398 399 if (rte_eth_rx_burst_mode_get(port_id, queue_id, &mode) == 0) 400 printf("\nBurst mode: %s%s", 401 mode.info, 402 mode.flags & RTE_ETH_BURST_FLAG_PER_QUEUE ? 403 " (per queue)" : ""); 404 405 printf("\n"); 406 } 407 408 void 409 tx_queue_infos_display(portid_t port_id, uint16_t queue_id) 410 { 411 struct rte_eth_burst_mode mode; 412 struct rte_eth_txq_info qinfo; 413 int32_t rc; 414 static const char *info_border = "*********************"; 415 416 rc = rte_eth_tx_queue_info_get(port_id, queue_id, &qinfo); 417 if (rc != 0) { 418 printf("Failed to retrieve information for port: %u, " 419 "TX queue: %hu\nerror desc: %s(%d)\n", 420 port_id, queue_id, strerror(-rc), rc); 421 return; 422 } 423 424 printf("\n%s Infos for port %-2u, TX queue %-2u %s", 425 info_border, port_id, queue_id, info_border); 426 427 printf("\nTX prefetch threshold: %hhu", qinfo.conf.tx_thresh.pthresh); 428 printf("\nTX host threshold: %hhu", qinfo.conf.tx_thresh.hthresh); 429 printf("\nTX writeback threshold: %hhu", qinfo.conf.tx_thresh.wthresh); 430 printf("\nTX RS threshold: %hu", qinfo.conf.tx_rs_thresh); 431 printf("\nTX free threshold: %hu", qinfo.conf.tx_free_thresh); 432 printf("\nTX deferred start: %s", 433 (qinfo.conf.tx_deferred_start != 0) ? "on" : "off"); 434 printf("\nNumber of TXDs: %hu", qinfo.nb_desc); 435 436 if (rte_eth_tx_burst_mode_get(port_id, queue_id, &mode) == 0) 437 printf("\nBurst mode: %s%s", 438 mode.info, 439 mode.flags & RTE_ETH_BURST_FLAG_PER_QUEUE ? 440 " (per queue)" : ""); 441 442 printf("\n"); 443 } 444 445 static int bus_match_all(const struct rte_bus *bus, const void *data) 446 { 447 RTE_SET_USED(bus); 448 RTE_SET_USED(data); 449 return 0; 450 } 451 452 static void 453 device_infos_display_speeds(uint32_t speed_capa) 454 { 455 printf("\n\tDevice speed capability:"); 456 if (speed_capa == ETH_LINK_SPEED_AUTONEG) 457 printf(" Autonegotiate (all speeds)"); 458 if (speed_capa & ETH_LINK_SPEED_FIXED) 459 printf(" Disable autonegotiate (fixed speed) "); 460 if (speed_capa & ETH_LINK_SPEED_10M_HD) 461 printf(" 10 Mbps half-duplex "); 462 if (speed_capa & ETH_LINK_SPEED_10M) 463 printf(" 10 Mbps full-duplex "); 464 if (speed_capa & ETH_LINK_SPEED_100M_HD) 465 printf(" 100 Mbps half-duplex "); 466 if (speed_capa & ETH_LINK_SPEED_100M) 467 printf(" 100 Mbps full-duplex "); 468 if (speed_capa & ETH_LINK_SPEED_1G) 469 printf(" 1 Gbps "); 470 if (speed_capa & ETH_LINK_SPEED_2_5G) 471 printf(" 2.5 Gbps "); 472 if (speed_capa & ETH_LINK_SPEED_5G) 473 printf(" 5 Gbps "); 474 if (speed_capa & ETH_LINK_SPEED_10G) 475 printf(" 10 Gbps "); 476 if (speed_capa & ETH_LINK_SPEED_20G) 477 printf(" 20 Gbps "); 478 if (speed_capa & ETH_LINK_SPEED_25G) 479 printf(" 25 Gbps "); 480 if (speed_capa & ETH_LINK_SPEED_40G) 481 printf(" 40 Gbps "); 482 if (speed_capa & ETH_LINK_SPEED_50G) 483 printf(" 50 Gbps "); 484 if (speed_capa & ETH_LINK_SPEED_56G) 485 printf(" 56 Gbps "); 486 if (speed_capa & ETH_LINK_SPEED_100G) 487 printf(" 100 Gbps "); 488 if (speed_capa & ETH_LINK_SPEED_200G) 489 printf(" 200 Gbps "); 490 } 491 492 void 493 device_infos_display(const char *identifier) 494 { 495 static const char *info_border = "*********************"; 496 struct rte_bus *start = NULL, *next; 497 struct rte_dev_iterator dev_iter; 498 char name[RTE_ETH_NAME_MAX_LEN]; 499 struct rte_ether_addr mac_addr; 500 struct rte_device *dev; 501 struct rte_devargs da; 502 portid_t port_id; 503 struct rte_eth_dev_info dev_info; 504 char devstr[128]; 505 506 memset(&da, 0, sizeof(da)); 507 if (!identifier) 508 goto skip_parse; 509 510 if (rte_devargs_parsef(&da, "%s", identifier)) { 511 printf("cannot parse identifier\n"); 512 if (da.args) 513 free(da.args); 514 return; 515 } 516 517 skip_parse: 518 while ((next = rte_bus_find(start, bus_match_all, NULL)) != NULL) { 519 520 start = next; 521 if (identifier && da.bus != next) 522 continue; 523 524 /* Skip buses that don't have iterate method */ 525 if (!next->dev_iterate) 526 continue; 527 528 snprintf(devstr, sizeof(devstr), "bus=%s", next->name); 529 RTE_DEV_FOREACH(dev, devstr, &dev_iter) { 530 531 if (!dev->driver) 532 continue; 533 /* Check for matching device if identifier is present */ 534 if (identifier && 535 strncmp(da.name, dev->name, strlen(dev->name))) 536 continue; 537 printf("\n%s Infos for device %s %s\n", 538 info_border, dev->name, info_border); 539 printf("Bus name: %s", dev->bus->name); 540 printf("\nDriver name: %s", dev->driver->name); 541 printf("\nDevargs: %s", 542 dev->devargs ? dev->devargs->args : ""); 543 printf("\nConnect to socket: %d", dev->numa_node); 544 printf("\n"); 545 546 /* List ports with matching device name */ 547 RTE_ETH_FOREACH_DEV_OF(port_id, dev) { 548 printf("\n\tPort id: %-2d", port_id); 549 if (eth_macaddr_get_print_err(port_id, 550 &mac_addr) == 0) 551 print_ethaddr("\n\tMAC address: ", 552 &mac_addr); 553 rte_eth_dev_get_name_by_port(port_id, name); 554 printf("\n\tDevice name: %s", name); 555 if (rte_eth_dev_info_get(port_id, &dev_info) == 0) 556 device_infos_display_speeds(dev_info.speed_capa); 557 printf("\n"); 558 } 559 } 560 }; 561 } 562 563 void 564 port_infos_display(portid_t port_id) 565 { 566 struct rte_port *port; 567 struct rte_ether_addr mac_addr; 568 struct rte_eth_link link; 569 struct rte_eth_dev_info dev_info; 570 int vlan_offload; 571 struct rte_mempool * mp; 572 static const char *info_border = "*********************"; 573 uint16_t mtu; 574 char name[RTE_ETH_NAME_MAX_LEN]; 575 int ret; 576 char fw_version[ETHDEV_FWVERS_LEN]; 577 578 if (port_id_is_invalid(port_id, ENABLED_WARN)) { 579 print_valid_ports(); 580 return; 581 } 582 port = &ports[port_id]; 583 ret = eth_link_get_nowait_print_err(port_id, &link); 584 if (ret < 0) 585 return; 586 587 ret = eth_dev_info_get_print_err(port_id, &dev_info); 588 if (ret != 0) 589 return; 590 591 printf("\n%s Infos for port %-2d %s\n", 592 info_border, port_id, info_border); 593 if (eth_macaddr_get_print_err(port_id, &mac_addr) == 0) 594 print_ethaddr("MAC address: ", &mac_addr); 595 rte_eth_dev_get_name_by_port(port_id, name); 596 printf("\nDevice name: %s", name); 597 printf("\nDriver name: %s", dev_info.driver_name); 598 599 if (rte_eth_dev_fw_version_get(port_id, fw_version, 600 ETHDEV_FWVERS_LEN) == 0) 601 printf("\nFirmware-version: %s", fw_version); 602 else 603 printf("\nFirmware-version: %s", "not available"); 604 605 if (dev_info.device->devargs && dev_info.device->devargs->args) 606 printf("\nDevargs: %s", dev_info.device->devargs->args); 607 printf("\nConnect to socket: %u", port->socket_id); 608 609 if (port_numa[port_id] != NUMA_NO_CONFIG) { 610 mp = mbuf_pool_find(port_numa[port_id], 0); 611 if (mp) 612 printf("\nmemory allocation on the socket: %d", 613 port_numa[port_id]); 614 } else 615 printf("\nmemory allocation on the socket: %u",port->socket_id); 616 617 printf("\nLink status: %s\n", (link.link_status) ? ("up") : ("down")); 618 printf("Link speed: %s\n", rte_eth_link_speed_to_str(link.link_speed)); 619 printf("Link duplex: %s\n", (link.link_duplex == ETH_LINK_FULL_DUPLEX) ? 620 ("full-duplex") : ("half-duplex")); 621 622 if (!rte_eth_dev_get_mtu(port_id, &mtu)) 623 printf("MTU: %u\n", mtu); 624 625 printf("Promiscuous mode: %s\n", 626 rte_eth_promiscuous_get(port_id) ? "enabled" : "disabled"); 627 printf("Allmulticast mode: %s\n", 628 rte_eth_allmulticast_get(port_id) ? "enabled" : "disabled"); 629 printf("Maximum number of MAC addresses: %u\n", 630 (unsigned int)(port->dev_info.max_mac_addrs)); 631 printf("Maximum number of MAC addresses of hash filtering: %u\n", 632 (unsigned int)(port->dev_info.max_hash_mac_addrs)); 633 634 vlan_offload = rte_eth_dev_get_vlan_offload(port_id); 635 if (vlan_offload >= 0){ 636 printf("VLAN offload: \n"); 637 if (vlan_offload & ETH_VLAN_STRIP_OFFLOAD) 638 printf(" strip on, "); 639 else 640 printf(" strip off, "); 641 642 if (vlan_offload & ETH_VLAN_FILTER_OFFLOAD) 643 printf("filter on, "); 644 else 645 printf("filter off, "); 646 647 if (vlan_offload & ETH_VLAN_EXTEND_OFFLOAD) 648 printf("extend on, "); 649 else 650 printf("extend off, "); 651 652 if (vlan_offload & ETH_QINQ_STRIP_OFFLOAD) 653 printf("qinq strip on\n"); 654 else 655 printf("qinq strip off\n"); 656 } 657 658 if (dev_info.hash_key_size > 0) 659 printf("Hash key size in bytes: %u\n", dev_info.hash_key_size); 660 if (dev_info.reta_size > 0) 661 printf("Redirection table size: %u\n", dev_info.reta_size); 662 if (!dev_info.flow_type_rss_offloads) 663 printf("No RSS offload flow type is supported.\n"); 664 else { 665 uint16_t i; 666 char *p; 667 668 printf("Supported RSS offload flow types:\n"); 669 for (i = RTE_ETH_FLOW_UNKNOWN + 1; 670 i < sizeof(dev_info.flow_type_rss_offloads) * CHAR_BIT; i++) { 671 if (!(dev_info.flow_type_rss_offloads & (1ULL << i))) 672 continue; 673 p = flowtype_to_str(i); 674 if (p) 675 printf(" %s\n", p); 676 else 677 printf(" user defined %d\n", i); 678 } 679 } 680 681 printf("Minimum size of RX buffer: %u\n", dev_info.min_rx_bufsize); 682 printf("Maximum configurable length of RX packet: %u\n", 683 dev_info.max_rx_pktlen); 684 printf("Maximum configurable size of LRO aggregated packet: %u\n", 685 dev_info.max_lro_pkt_size); 686 if (dev_info.max_vfs) 687 printf("Maximum number of VFs: %u\n", dev_info.max_vfs); 688 if (dev_info.max_vmdq_pools) 689 printf("Maximum number of VMDq pools: %u\n", 690 dev_info.max_vmdq_pools); 691 692 printf("Current number of RX queues: %u\n", dev_info.nb_rx_queues); 693 printf("Max possible RX queues: %u\n", dev_info.max_rx_queues); 694 printf("Max possible number of RXDs per queue: %hu\n", 695 dev_info.rx_desc_lim.nb_max); 696 printf("Min possible number of RXDs per queue: %hu\n", 697 dev_info.rx_desc_lim.nb_min); 698 printf("RXDs number alignment: %hu\n", dev_info.rx_desc_lim.nb_align); 699 700 printf("Current number of TX queues: %u\n", dev_info.nb_tx_queues); 701 printf("Max possible TX queues: %u\n", dev_info.max_tx_queues); 702 printf("Max possible number of TXDs per queue: %hu\n", 703 dev_info.tx_desc_lim.nb_max); 704 printf("Min possible number of TXDs per queue: %hu\n", 705 dev_info.tx_desc_lim.nb_min); 706 printf("TXDs number alignment: %hu\n", dev_info.tx_desc_lim.nb_align); 707 printf("Max segment number per packet: %hu\n", 708 dev_info.tx_desc_lim.nb_seg_max); 709 printf("Max segment number per MTU/TSO: %hu\n", 710 dev_info.tx_desc_lim.nb_mtu_seg_max); 711 712 /* Show switch info only if valid switch domain and port id is set */ 713 if (dev_info.switch_info.domain_id != 714 RTE_ETH_DEV_SWITCH_DOMAIN_ID_INVALID) { 715 if (dev_info.switch_info.name) 716 printf("Switch name: %s\n", dev_info.switch_info.name); 717 718 printf("Switch domain Id: %u\n", 719 dev_info.switch_info.domain_id); 720 printf("Switch Port Id: %u\n", 721 dev_info.switch_info.port_id); 722 } 723 } 724 725 void 726 port_summary_header_display(void) 727 { 728 uint16_t port_number; 729 730 port_number = rte_eth_dev_count_avail(); 731 printf("Number of available ports: %i\n", port_number); 732 printf("%-4s %-17s %-12s %-14s %-8s %s\n", "Port", "MAC Address", "Name", 733 "Driver", "Status", "Link"); 734 } 735 736 void 737 port_summary_display(portid_t port_id) 738 { 739 struct rte_ether_addr mac_addr; 740 struct rte_eth_link link; 741 struct rte_eth_dev_info dev_info; 742 char name[RTE_ETH_NAME_MAX_LEN]; 743 int ret; 744 745 if (port_id_is_invalid(port_id, ENABLED_WARN)) { 746 print_valid_ports(); 747 return; 748 } 749 750 ret = eth_link_get_nowait_print_err(port_id, &link); 751 if (ret < 0) 752 return; 753 754 ret = eth_dev_info_get_print_err(port_id, &dev_info); 755 if (ret != 0) 756 return; 757 758 rte_eth_dev_get_name_by_port(port_id, name); 759 ret = eth_macaddr_get_print_err(port_id, &mac_addr); 760 if (ret != 0) 761 return; 762 763 printf("%-4d %02X:%02X:%02X:%02X:%02X:%02X %-12s %-14s %-8s %s\n", 764 port_id, mac_addr.addr_bytes[0], mac_addr.addr_bytes[1], 765 mac_addr.addr_bytes[2], mac_addr.addr_bytes[3], 766 mac_addr.addr_bytes[4], mac_addr.addr_bytes[5], name, 767 dev_info.driver_name, (link.link_status) ? ("up") : ("down"), 768 rte_eth_link_speed_to_str(link.link_speed)); 769 } 770 771 void 772 port_eeprom_display(portid_t port_id) 773 { 774 struct rte_dev_eeprom_info einfo; 775 int ret; 776 if (port_id_is_invalid(port_id, ENABLED_WARN)) { 777 print_valid_ports(); 778 return; 779 } 780 781 int len_eeprom = rte_eth_dev_get_eeprom_length(port_id); 782 if (len_eeprom < 0) { 783 switch (len_eeprom) { 784 case -ENODEV: 785 printf("port index %d invalid\n", port_id); 786 break; 787 case -ENOTSUP: 788 printf("operation not supported by device\n"); 789 break; 790 case -EIO: 791 printf("device is removed\n"); 792 break; 793 default: 794 printf("Unable to get EEPROM: %d\n", len_eeprom); 795 break; 796 } 797 return; 798 } 799 800 char buf[len_eeprom]; 801 einfo.offset = 0; 802 einfo.length = len_eeprom; 803 einfo.data = buf; 804 805 ret = rte_eth_dev_get_eeprom(port_id, &einfo); 806 if (ret != 0) { 807 switch (ret) { 808 case -ENODEV: 809 printf("port index %d invalid\n", port_id); 810 break; 811 case -ENOTSUP: 812 printf("operation not supported by device\n"); 813 break; 814 case -EIO: 815 printf("device is removed\n"); 816 break; 817 default: 818 printf("Unable to get EEPROM: %d\n", ret); 819 break; 820 } 821 return; 822 } 823 rte_hexdump(stdout, "hexdump", einfo.data, einfo.length); 824 printf("Finish -- Port: %d EEPROM length: %d bytes\n", port_id, len_eeprom); 825 } 826 827 void 828 port_module_eeprom_display(portid_t port_id) 829 { 830 struct rte_eth_dev_module_info minfo; 831 struct rte_dev_eeprom_info einfo; 832 int ret; 833 834 if (port_id_is_invalid(port_id, ENABLED_WARN)) { 835 print_valid_ports(); 836 return; 837 } 838 839 840 ret = rte_eth_dev_get_module_info(port_id, &minfo); 841 if (ret != 0) { 842 switch (ret) { 843 case -ENODEV: 844 printf("port index %d invalid\n", port_id); 845 break; 846 case -ENOTSUP: 847 printf("operation not supported by device\n"); 848 break; 849 case -EIO: 850 printf("device is removed\n"); 851 break; 852 default: 853 printf("Unable to get module EEPROM: %d\n", ret); 854 break; 855 } 856 return; 857 } 858 859 char buf[minfo.eeprom_len]; 860 einfo.offset = 0; 861 einfo.length = minfo.eeprom_len; 862 einfo.data = buf; 863 864 ret = rte_eth_dev_get_module_eeprom(port_id, &einfo); 865 if (ret != 0) { 866 switch (ret) { 867 case -ENODEV: 868 printf("port index %d invalid\n", port_id); 869 break; 870 case -ENOTSUP: 871 printf("operation not supported by device\n"); 872 break; 873 case -EIO: 874 printf("device is removed\n"); 875 break; 876 default: 877 printf("Unable to get module EEPROM: %d\n", ret); 878 break; 879 } 880 return; 881 } 882 883 rte_hexdump(stdout, "hexdump", einfo.data, einfo.length); 884 printf("Finish -- Port: %d MODULE EEPROM length: %d bytes\n", port_id, einfo.length); 885 } 886 887 void 888 port_offload_cap_display(portid_t port_id) 889 { 890 struct rte_eth_dev_info dev_info; 891 static const char *info_border = "************"; 892 int ret; 893 894 if (port_id_is_invalid(port_id, ENABLED_WARN)) 895 return; 896 897 ret = eth_dev_info_get_print_err(port_id, &dev_info); 898 if (ret != 0) 899 return; 900 901 printf("\n%s Port %d supported offload features: %s\n", 902 info_border, port_id, info_border); 903 904 if (dev_info.rx_offload_capa & DEV_RX_OFFLOAD_VLAN_STRIP) { 905 printf("VLAN stripped: "); 906 if (ports[port_id].dev_conf.rxmode.offloads & 907 DEV_RX_OFFLOAD_VLAN_STRIP) 908 printf("on\n"); 909 else 910 printf("off\n"); 911 } 912 913 if (dev_info.rx_offload_capa & DEV_RX_OFFLOAD_QINQ_STRIP) { 914 printf("Double VLANs stripped: "); 915 if (ports[port_id].dev_conf.rxmode.offloads & 916 DEV_RX_OFFLOAD_QINQ_STRIP) 917 printf("on\n"); 918 else 919 printf("off\n"); 920 } 921 922 if (dev_info.rx_offload_capa & DEV_RX_OFFLOAD_IPV4_CKSUM) { 923 printf("RX IPv4 checksum: "); 924 if (ports[port_id].dev_conf.rxmode.offloads & 925 DEV_RX_OFFLOAD_IPV4_CKSUM) 926 printf("on\n"); 927 else 928 printf("off\n"); 929 } 930 931 if (dev_info.rx_offload_capa & DEV_RX_OFFLOAD_UDP_CKSUM) { 932 printf("RX UDP checksum: "); 933 if (ports[port_id].dev_conf.rxmode.offloads & 934 DEV_RX_OFFLOAD_UDP_CKSUM) 935 printf("on\n"); 936 else 937 printf("off\n"); 938 } 939 940 if (dev_info.rx_offload_capa & DEV_RX_OFFLOAD_TCP_CKSUM) { 941 printf("RX TCP checksum: "); 942 if (ports[port_id].dev_conf.rxmode.offloads & 943 DEV_RX_OFFLOAD_TCP_CKSUM) 944 printf("on\n"); 945 else 946 printf("off\n"); 947 } 948 949 if (dev_info.rx_offload_capa & DEV_RX_OFFLOAD_SCTP_CKSUM) { 950 printf("RX SCTP checksum: "); 951 if (ports[port_id].dev_conf.rxmode.offloads & 952 DEV_RX_OFFLOAD_SCTP_CKSUM) 953 printf("on\n"); 954 else 955 printf("off\n"); 956 } 957 958 if (dev_info.rx_offload_capa & DEV_RX_OFFLOAD_OUTER_IPV4_CKSUM) { 959 printf("RX Outer IPv4 checksum: "); 960 if (ports[port_id].dev_conf.rxmode.offloads & 961 DEV_RX_OFFLOAD_OUTER_IPV4_CKSUM) 962 printf("on\n"); 963 else 964 printf("off\n"); 965 } 966 967 if (dev_info.rx_offload_capa & DEV_RX_OFFLOAD_OUTER_UDP_CKSUM) { 968 printf("RX Outer UDP checksum: "); 969 if (ports[port_id].dev_conf.rxmode.offloads & 970 DEV_RX_OFFLOAD_OUTER_UDP_CKSUM) 971 printf("on\n"); 972 else 973 printf("off\n"); 974 } 975 976 if (dev_info.rx_offload_capa & DEV_RX_OFFLOAD_TCP_LRO) { 977 printf("Large receive offload: "); 978 if (ports[port_id].dev_conf.rxmode.offloads & 979 DEV_RX_OFFLOAD_TCP_LRO) 980 printf("on\n"); 981 else 982 printf("off\n"); 983 } 984 985 if (dev_info.rx_offload_capa & DEV_RX_OFFLOAD_TIMESTAMP) { 986 printf("HW timestamp: "); 987 if (ports[port_id].dev_conf.rxmode.offloads & 988 DEV_RX_OFFLOAD_TIMESTAMP) 989 printf("on\n"); 990 else 991 printf("off\n"); 992 } 993 994 if (dev_info.rx_offload_capa & DEV_RX_OFFLOAD_KEEP_CRC) { 995 printf("Rx Keep CRC: "); 996 if (ports[port_id].dev_conf.rxmode.offloads & 997 DEV_RX_OFFLOAD_KEEP_CRC) 998 printf("on\n"); 999 else 1000 printf("off\n"); 1001 } 1002 1003 if (dev_info.rx_offload_capa & DEV_RX_OFFLOAD_SECURITY) { 1004 printf("RX offload security: "); 1005 if (ports[port_id].dev_conf.rxmode.offloads & 1006 DEV_RX_OFFLOAD_SECURITY) 1007 printf("on\n"); 1008 else 1009 printf("off\n"); 1010 } 1011 1012 if (dev_info.rx_offload_capa & RTE_ETH_RX_OFFLOAD_BUFFER_SPLIT) { 1013 printf("RX offload buffer split: "); 1014 if (ports[port_id].dev_conf.rxmode.offloads & 1015 RTE_ETH_RX_OFFLOAD_BUFFER_SPLIT) 1016 printf("on\n"); 1017 else 1018 printf("off\n"); 1019 } 1020 1021 if (dev_info.tx_offload_capa & DEV_TX_OFFLOAD_VLAN_INSERT) { 1022 printf("VLAN insert: "); 1023 if (ports[port_id].dev_conf.txmode.offloads & 1024 DEV_TX_OFFLOAD_VLAN_INSERT) 1025 printf("on\n"); 1026 else 1027 printf("off\n"); 1028 } 1029 1030 if (dev_info.tx_offload_capa & DEV_TX_OFFLOAD_QINQ_INSERT) { 1031 printf("Double VLANs insert: "); 1032 if (ports[port_id].dev_conf.txmode.offloads & 1033 DEV_TX_OFFLOAD_QINQ_INSERT) 1034 printf("on\n"); 1035 else 1036 printf("off\n"); 1037 } 1038 1039 if (dev_info.tx_offload_capa & DEV_TX_OFFLOAD_IPV4_CKSUM) { 1040 printf("TX IPv4 checksum: "); 1041 if (ports[port_id].dev_conf.txmode.offloads & 1042 DEV_TX_OFFLOAD_IPV4_CKSUM) 1043 printf("on\n"); 1044 else 1045 printf("off\n"); 1046 } 1047 1048 if (dev_info.tx_offload_capa & DEV_TX_OFFLOAD_UDP_CKSUM) { 1049 printf("TX UDP checksum: "); 1050 if (ports[port_id].dev_conf.txmode.offloads & 1051 DEV_TX_OFFLOAD_UDP_CKSUM) 1052 printf("on\n"); 1053 else 1054 printf("off\n"); 1055 } 1056 1057 if (dev_info.tx_offload_capa & DEV_TX_OFFLOAD_TCP_CKSUM) { 1058 printf("TX TCP checksum: "); 1059 if (ports[port_id].dev_conf.txmode.offloads & 1060 DEV_TX_OFFLOAD_TCP_CKSUM) 1061 printf("on\n"); 1062 else 1063 printf("off\n"); 1064 } 1065 1066 if (dev_info.tx_offload_capa & DEV_TX_OFFLOAD_SCTP_CKSUM) { 1067 printf("TX SCTP checksum: "); 1068 if (ports[port_id].dev_conf.txmode.offloads & 1069 DEV_TX_OFFLOAD_SCTP_CKSUM) 1070 printf("on\n"); 1071 else 1072 printf("off\n"); 1073 } 1074 1075 if (dev_info.tx_offload_capa & DEV_TX_OFFLOAD_OUTER_IPV4_CKSUM) { 1076 printf("TX Outer IPv4 checksum: "); 1077 if (ports[port_id].dev_conf.txmode.offloads & 1078 DEV_TX_OFFLOAD_OUTER_IPV4_CKSUM) 1079 printf("on\n"); 1080 else 1081 printf("off\n"); 1082 } 1083 1084 if (dev_info.tx_offload_capa & DEV_TX_OFFLOAD_TCP_TSO) { 1085 printf("TX TCP segmentation: "); 1086 if (ports[port_id].dev_conf.txmode.offloads & 1087 DEV_TX_OFFLOAD_TCP_TSO) 1088 printf("on\n"); 1089 else 1090 printf("off\n"); 1091 } 1092 1093 if (dev_info.tx_offload_capa & DEV_TX_OFFLOAD_UDP_TSO) { 1094 printf("TX UDP segmentation: "); 1095 if (ports[port_id].dev_conf.txmode.offloads & 1096 DEV_TX_OFFLOAD_UDP_TSO) 1097 printf("on\n"); 1098 else 1099 printf("off\n"); 1100 } 1101 1102 if (dev_info.tx_offload_capa & DEV_TX_OFFLOAD_VXLAN_TNL_TSO) { 1103 printf("TSO for VXLAN tunnel packet: "); 1104 if (ports[port_id].dev_conf.txmode.offloads & 1105 DEV_TX_OFFLOAD_VXLAN_TNL_TSO) 1106 printf("on\n"); 1107 else 1108 printf("off\n"); 1109 } 1110 1111 if (dev_info.tx_offload_capa & DEV_TX_OFFLOAD_GRE_TNL_TSO) { 1112 printf("TSO for GRE tunnel packet: "); 1113 if (ports[port_id].dev_conf.txmode.offloads & 1114 DEV_TX_OFFLOAD_GRE_TNL_TSO) 1115 printf("on\n"); 1116 else 1117 printf("off\n"); 1118 } 1119 1120 if (dev_info.tx_offload_capa & DEV_TX_OFFLOAD_IPIP_TNL_TSO) { 1121 printf("TSO for IPIP tunnel packet: "); 1122 if (ports[port_id].dev_conf.txmode.offloads & 1123 DEV_TX_OFFLOAD_IPIP_TNL_TSO) 1124 printf("on\n"); 1125 else 1126 printf("off\n"); 1127 } 1128 1129 if (dev_info.tx_offload_capa & DEV_TX_OFFLOAD_GENEVE_TNL_TSO) { 1130 printf("TSO for GENEVE tunnel packet: "); 1131 if (ports[port_id].dev_conf.txmode.offloads & 1132 DEV_TX_OFFLOAD_GENEVE_TNL_TSO) 1133 printf("on\n"); 1134 else 1135 printf("off\n"); 1136 } 1137 1138 if (dev_info.tx_offload_capa & DEV_TX_OFFLOAD_IP_TNL_TSO) { 1139 printf("IP tunnel TSO: "); 1140 if (ports[port_id].dev_conf.txmode.offloads & 1141 DEV_TX_OFFLOAD_IP_TNL_TSO) 1142 printf("on\n"); 1143 else 1144 printf("off\n"); 1145 } 1146 1147 if (dev_info.tx_offload_capa & DEV_TX_OFFLOAD_UDP_TNL_TSO) { 1148 printf("UDP tunnel TSO: "); 1149 if (ports[port_id].dev_conf.txmode.offloads & 1150 DEV_TX_OFFLOAD_UDP_TNL_TSO) 1151 printf("on\n"); 1152 else 1153 printf("off\n"); 1154 } 1155 1156 if (dev_info.tx_offload_capa & DEV_TX_OFFLOAD_OUTER_UDP_CKSUM) { 1157 printf("TX Outer UDP checksum: "); 1158 if (ports[port_id].dev_conf.txmode.offloads & 1159 DEV_TX_OFFLOAD_OUTER_UDP_CKSUM) 1160 printf("on\n"); 1161 else 1162 printf("off\n"); 1163 } 1164 1165 if (dev_info.tx_offload_capa & DEV_TX_OFFLOAD_SEND_ON_TIMESTAMP) { 1166 printf("Tx scheduling on timestamp: "); 1167 if (ports[port_id].dev_conf.txmode.offloads & 1168 DEV_TX_OFFLOAD_SEND_ON_TIMESTAMP) 1169 printf("on\n"); 1170 else 1171 printf("off\n"); 1172 } 1173 1174 } 1175 1176 int 1177 port_id_is_invalid(portid_t port_id, enum print_warning warning) 1178 { 1179 uint16_t pid; 1180 1181 if (port_id == (portid_t)RTE_PORT_ALL) 1182 return 0; 1183 1184 RTE_ETH_FOREACH_DEV(pid) 1185 if (port_id == pid) 1186 return 0; 1187 1188 if (warning == ENABLED_WARN) 1189 printf("Invalid port %d\n", port_id); 1190 1191 return 1; 1192 } 1193 1194 void print_valid_ports(void) 1195 { 1196 portid_t pid; 1197 1198 printf("The valid ports array is ["); 1199 RTE_ETH_FOREACH_DEV(pid) { 1200 printf(" %d", pid); 1201 } 1202 printf(" ]\n"); 1203 } 1204 1205 static int 1206 vlan_id_is_invalid(uint16_t vlan_id) 1207 { 1208 if (vlan_id < 4096) 1209 return 0; 1210 printf("Invalid vlan_id %d (must be < 4096)\n", vlan_id); 1211 return 1; 1212 } 1213 1214 static int 1215 port_reg_off_is_invalid(portid_t port_id, uint32_t reg_off) 1216 { 1217 const struct rte_pci_device *pci_dev; 1218 const struct rte_bus *bus; 1219 uint64_t pci_len; 1220 1221 if (reg_off & 0x3) { 1222 printf("Port register offset 0x%X not aligned on a 4-byte " 1223 "boundary\n", 1224 (unsigned)reg_off); 1225 return 1; 1226 } 1227 1228 if (!ports[port_id].dev_info.device) { 1229 printf("Invalid device\n"); 1230 return 0; 1231 } 1232 1233 bus = rte_bus_find_by_device(ports[port_id].dev_info.device); 1234 if (bus && !strcmp(bus->name, "pci")) { 1235 pci_dev = RTE_DEV_TO_PCI(ports[port_id].dev_info.device); 1236 } else { 1237 printf("Not a PCI device\n"); 1238 return 1; 1239 } 1240 1241 pci_len = pci_dev->mem_resource[0].len; 1242 if (reg_off >= pci_len) { 1243 printf("Port %d: register offset %u (0x%X) out of port PCI " 1244 "resource (length=%"PRIu64")\n", 1245 port_id, (unsigned)reg_off, (unsigned)reg_off, pci_len); 1246 return 1; 1247 } 1248 return 0; 1249 } 1250 1251 static int 1252 reg_bit_pos_is_invalid(uint8_t bit_pos) 1253 { 1254 if (bit_pos <= 31) 1255 return 0; 1256 printf("Invalid bit position %d (must be <= 31)\n", bit_pos); 1257 return 1; 1258 } 1259 1260 #define display_port_and_reg_off(port_id, reg_off) \ 1261 printf("port %d PCI register at offset 0x%X: ", (port_id), (reg_off)) 1262 1263 static inline void 1264 display_port_reg_value(portid_t port_id, uint32_t reg_off, uint32_t reg_v) 1265 { 1266 display_port_and_reg_off(port_id, (unsigned)reg_off); 1267 printf("0x%08X (%u)\n", (unsigned)reg_v, (unsigned)reg_v); 1268 } 1269 1270 void 1271 port_reg_bit_display(portid_t port_id, uint32_t reg_off, uint8_t bit_x) 1272 { 1273 uint32_t reg_v; 1274 1275 1276 if (port_id_is_invalid(port_id, ENABLED_WARN)) 1277 return; 1278 if (port_reg_off_is_invalid(port_id, reg_off)) 1279 return; 1280 if (reg_bit_pos_is_invalid(bit_x)) 1281 return; 1282 reg_v = port_id_pci_reg_read(port_id, reg_off); 1283 display_port_and_reg_off(port_id, (unsigned)reg_off); 1284 printf("bit %d=%d\n", bit_x, (int) ((reg_v & (1 << bit_x)) >> bit_x)); 1285 } 1286 1287 void 1288 port_reg_bit_field_display(portid_t port_id, uint32_t reg_off, 1289 uint8_t bit1_pos, uint8_t bit2_pos) 1290 { 1291 uint32_t reg_v; 1292 uint8_t l_bit; 1293 uint8_t h_bit; 1294 1295 if (port_id_is_invalid(port_id, ENABLED_WARN)) 1296 return; 1297 if (port_reg_off_is_invalid(port_id, reg_off)) 1298 return; 1299 if (reg_bit_pos_is_invalid(bit1_pos)) 1300 return; 1301 if (reg_bit_pos_is_invalid(bit2_pos)) 1302 return; 1303 if (bit1_pos > bit2_pos) 1304 l_bit = bit2_pos, h_bit = bit1_pos; 1305 else 1306 l_bit = bit1_pos, h_bit = bit2_pos; 1307 1308 reg_v = port_id_pci_reg_read(port_id, reg_off); 1309 reg_v >>= l_bit; 1310 if (h_bit < 31) 1311 reg_v &= ((1 << (h_bit - l_bit + 1)) - 1); 1312 display_port_and_reg_off(port_id, (unsigned)reg_off); 1313 printf("bits[%d, %d]=0x%0*X (%u)\n", l_bit, h_bit, 1314 ((h_bit - l_bit) / 4) + 1, (unsigned)reg_v, (unsigned)reg_v); 1315 } 1316 1317 void 1318 port_reg_display(portid_t port_id, uint32_t reg_off) 1319 { 1320 uint32_t reg_v; 1321 1322 if (port_id_is_invalid(port_id, ENABLED_WARN)) 1323 return; 1324 if (port_reg_off_is_invalid(port_id, reg_off)) 1325 return; 1326 reg_v = port_id_pci_reg_read(port_id, reg_off); 1327 display_port_reg_value(port_id, reg_off, reg_v); 1328 } 1329 1330 void 1331 port_reg_bit_set(portid_t port_id, uint32_t reg_off, uint8_t bit_pos, 1332 uint8_t bit_v) 1333 { 1334 uint32_t reg_v; 1335 1336 if (port_id_is_invalid(port_id, ENABLED_WARN)) 1337 return; 1338 if (port_reg_off_is_invalid(port_id, reg_off)) 1339 return; 1340 if (reg_bit_pos_is_invalid(bit_pos)) 1341 return; 1342 if (bit_v > 1) { 1343 printf("Invalid bit value %d (must be 0 or 1)\n", (int) bit_v); 1344 return; 1345 } 1346 reg_v = port_id_pci_reg_read(port_id, reg_off); 1347 if (bit_v == 0) 1348 reg_v &= ~(1 << bit_pos); 1349 else 1350 reg_v |= (1 << bit_pos); 1351 port_id_pci_reg_write(port_id, reg_off, reg_v); 1352 display_port_reg_value(port_id, reg_off, reg_v); 1353 } 1354 1355 void 1356 port_reg_bit_field_set(portid_t port_id, uint32_t reg_off, 1357 uint8_t bit1_pos, uint8_t bit2_pos, uint32_t value) 1358 { 1359 uint32_t max_v; 1360 uint32_t reg_v; 1361 uint8_t l_bit; 1362 uint8_t h_bit; 1363 1364 if (port_id_is_invalid(port_id, ENABLED_WARN)) 1365 return; 1366 if (port_reg_off_is_invalid(port_id, reg_off)) 1367 return; 1368 if (reg_bit_pos_is_invalid(bit1_pos)) 1369 return; 1370 if (reg_bit_pos_is_invalid(bit2_pos)) 1371 return; 1372 if (bit1_pos > bit2_pos) 1373 l_bit = bit2_pos, h_bit = bit1_pos; 1374 else 1375 l_bit = bit1_pos, h_bit = bit2_pos; 1376 1377 if ((h_bit - l_bit) < 31) 1378 max_v = (1 << (h_bit - l_bit + 1)) - 1; 1379 else 1380 max_v = 0xFFFFFFFF; 1381 1382 if (value > max_v) { 1383 printf("Invalid value %u (0x%x) must be < %u (0x%x)\n", 1384 (unsigned)value, (unsigned)value, 1385 (unsigned)max_v, (unsigned)max_v); 1386 return; 1387 } 1388 reg_v = port_id_pci_reg_read(port_id, reg_off); 1389 reg_v &= ~(max_v << l_bit); /* Keep unchanged bits */ 1390 reg_v |= (value << l_bit); /* Set changed bits */ 1391 port_id_pci_reg_write(port_id, reg_off, reg_v); 1392 display_port_reg_value(port_id, reg_off, reg_v); 1393 } 1394 1395 void 1396 port_reg_set(portid_t port_id, uint32_t reg_off, uint32_t reg_v) 1397 { 1398 if (port_id_is_invalid(port_id, ENABLED_WARN)) 1399 return; 1400 if (port_reg_off_is_invalid(port_id, reg_off)) 1401 return; 1402 port_id_pci_reg_write(port_id, reg_off, reg_v); 1403 display_port_reg_value(port_id, reg_off, reg_v); 1404 } 1405 1406 void 1407 port_mtu_set(portid_t port_id, uint16_t mtu) 1408 { 1409 int diag; 1410 struct rte_port *rte_port = &ports[port_id]; 1411 struct rte_eth_dev_info dev_info; 1412 uint16_t eth_overhead; 1413 int ret; 1414 1415 if (port_id_is_invalid(port_id, ENABLED_WARN)) 1416 return; 1417 1418 ret = eth_dev_info_get_print_err(port_id, &dev_info); 1419 if (ret != 0) 1420 return; 1421 1422 if (mtu > dev_info.max_mtu || mtu < dev_info.min_mtu) { 1423 printf("Set MTU failed. MTU:%u is not in valid range, min:%u - max:%u\n", 1424 mtu, dev_info.min_mtu, dev_info.max_mtu); 1425 return; 1426 } 1427 diag = rte_eth_dev_set_mtu(port_id, mtu); 1428 if (diag) 1429 printf("Set MTU failed. diag=%d\n", diag); 1430 else if (dev_info.rx_offload_capa & DEV_RX_OFFLOAD_JUMBO_FRAME) { 1431 /* 1432 * Ether overhead in driver is equal to the difference of 1433 * max_rx_pktlen and max_mtu in rte_eth_dev_info when the 1434 * device supports jumbo frame. 1435 */ 1436 eth_overhead = dev_info.max_rx_pktlen - dev_info.max_mtu; 1437 if (mtu > RTE_ETHER_MTU) { 1438 rte_port->dev_conf.rxmode.offloads |= 1439 DEV_RX_OFFLOAD_JUMBO_FRAME; 1440 rte_port->dev_conf.rxmode.max_rx_pkt_len = 1441 mtu + eth_overhead; 1442 } else 1443 rte_port->dev_conf.rxmode.offloads &= 1444 ~DEV_RX_OFFLOAD_JUMBO_FRAME; 1445 } 1446 } 1447 1448 /* Generic flow management functions. */ 1449 1450 static struct port_flow_tunnel * 1451 port_flow_locate_tunnel_id(struct rte_port *port, uint32_t port_tunnel_id) 1452 { 1453 struct port_flow_tunnel *flow_tunnel; 1454 1455 LIST_FOREACH(flow_tunnel, &port->flow_tunnel_list, chain) { 1456 if (flow_tunnel->id == port_tunnel_id) 1457 goto out; 1458 } 1459 flow_tunnel = NULL; 1460 1461 out: 1462 return flow_tunnel; 1463 } 1464 1465 const char * 1466 port_flow_tunnel_type(struct rte_flow_tunnel *tunnel) 1467 { 1468 const char *type; 1469 switch (tunnel->type) { 1470 default: 1471 type = "unknown"; 1472 break; 1473 case RTE_FLOW_ITEM_TYPE_VXLAN: 1474 type = "vxlan"; 1475 break; 1476 } 1477 1478 return type; 1479 } 1480 1481 struct port_flow_tunnel * 1482 port_flow_locate_tunnel(uint16_t port_id, struct rte_flow_tunnel *tun) 1483 { 1484 struct rte_port *port = &ports[port_id]; 1485 struct port_flow_tunnel *flow_tunnel; 1486 1487 LIST_FOREACH(flow_tunnel, &port->flow_tunnel_list, chain) { 1488 if (!memcmp(&flow_tunnel->tunnel, tun, sizeof(*tun))) 1489 goto out; 1490 } 1491 flow_tunnel = NULL; 1492 1493 out: 1494 return flow_tunnel; 1495 } 1496 1497 void port_flow_tunnel_list(portid_t port_id) 1498 { 1499 struct rte_port *port = &ports[port_id]; 1500 struct port_flow_tunnel *flt; 1501 1502 LIST_FOREACH(flt, &port->flow_tunnel_list, chain) { 1503 printf("port %u tunnel #%u type=%s", 1504 port_id, flt->id, port_flow_tunnel_type(&flt->tunnel)); 1505 if (flt->tunnel.tun_id) 1506 printf(" id=%" PRIu64, flt->tunnel.tun_id); 1507 printf("\n"); 1508 } 1509 } 1510 1511 void port_flow_tunnel_destroy(portid_t port_id, uint32_t tunnel_id) 1512 { 1513 struct rte_port *port = &ports[port_id]; 1514 struct port_flow_tunnel *flt; 1515 1516 LIST_FOREACH(flt, &port->flow_tunnel_list, chain) { 1517 if (flt->id == tunnel_id) 1518 break; 1519 } 1520 if (flt) { 1521 LIST_REMOVE(flt, chain); 1522 free(flt); 1523 printf("port %u: flow tunnel #%u destroyed\n", 1524 port_id, tunnel_id); 1525 } 1526 } 1527 1528 void port_flow_tunnel_create(portid_t port_id, const struct tunnel_ops *ops) 1529 { 1530 struct rte_port *port = &ports[port_id]; 1531 enum rte_flow_item_type type; 1532 struct port_flow_tunnel *flt; 1533 1534 if (!strcmp(ops->type, "vxlan")) 1535 type = RTE_FLOW_ITEM_TYPE_VXLAN; 1536 else { 1537 printf("cannot offload \"%s\" tunnel type\n", ops->type); 1538 return; 1539 } 1540 LIST_FOREACH(flt, &port->flow_tunnel_list, chain) { 1541 if (flt->tunnel.type == type) 1542 break; 1543 } 1544 if (!flt) { 1545 flt = calloc(1, sizeof(*flt)); 1546 if (!flt) { 1547 printf("failed to allocate port flt object\n"); 1548 return; 1549 } 1550 flt->tunnel.type = type; 1551 flt->id = LIST_EMPTY(&port->flow_tunnel_list) ? 1 : 1552 LIST_FIRST(&port->flow_tunnel_list)->id + 1; 1553 LIST_INSERT_HEAD(&port->flow_tunnel_list, flt, chain); 1554 } 1555 printf("port %d: flow tunnel #%u type %s\n", 1556 port_id, flt->id, ops->type); 1557 } 1558 1559 /** Generate a port_flow entry from attributes/pattern/actions. */ 1560 static struct port_flow * 1561 port_flow_new(const struct rte_flow_attr *attr, 1562 const struct rte_flow_item *pattern, 1563 const struct rte_flow_action *actions, 1564 struct rte_flow_error *error) 1565 { 1566 const struct rte_flow_conv_rule rule = { 1567 .attr_ro = attr, 1568 .pattern_ro = pattern, 1569 .actions_ro = actions, 1570 }; 1571 struct port_flow *pf; 1572 int ret; 1573 1574 ret = rte_flow_conv(RTE_FLOW_CONV_OP_RULE, NULL, 0, &rule, error); 1575 if (ret < 0) 1576 return NULL; 1577 pf = calloc(1, offsetof(struct port_flow, rule) + ret); 1578 if (!pf) { 1579 rte_flow_error_set 1580 (error, errno, RTE_FLOW_ERROR_TYPE_UNSPECIFIED, NULL, 1581 "calloc() failed"); 1582 return NULL; 1583 } 1584 if (rte_flow_conv(RTE_FLOW_CONV_OP_RULE, &pf->rule, ret, &rule, 1585 error) >= 0) 1586 return pf; 1587 free(pf); 1588 return NULL; 1589 } 1590 1591 /** Print a message out of a flow error. */ 1592 static int 1593 port_flow_complain(struct rte_flow_error *error) 1594 { 1595 static const char *const errstrlist[] = { 1596 [RTE_FLOW_ERROR_TYPE_NONE] = "no error", 1597 [RTE_FLOW_ERROR_TYPE_UNSPECIFIED] = "cause unspecified", 1598 [RTE_FLOW_ERROR_TYPE_HANDLE] = "flow rule (handle)", 1599 [RTE_FLOW_ERROR_TYPE_ATTR_GROUP] = "group field", 1600 [RTE_FLOW_ERROR_TYPE_ATTR_PRIORITY] = "priority field", 1601 [RTE_FLOW_ERROR_TYPE_ATTR_INGRESS] = "ingress field", 1602 [RTE_FLOW_ERROR_TYPE_ATTR_EGRESS] = "egress field", 1603 [RTE_FLOW_ERROR_TYPE_ATTR_TRANSFER] = "transfer field", 1604 [RTE_FLOW_ERROR_TYPE_ATTR] = "attributes structure", 1605 [RTE_FLOW_ERROR_TYPE_ITEM_NUM] = "pattern length", 1606 [RTE_FLOW_ERROR_TYPE_ITEM_SPEC] = "item specification", 1607 [RTE_FLOW_ERROR_TYPE_ITEM_LAST] = "item specification range", 1608 [RTE_FLOW_ERROR_TYPE_ITEM_MASK] = "item specification mask", 1609 [RTE_FLOW_ERROR_TYPE_ITEM] = "specific pattern item", 1610 [RTE_FLOW_ERROR_TYPE_ACTION_NUM] = "number of actions", 1611 [RTE_FLOW_ERROR_TYPE_ACTION_CONF] = "action configuration", 1612 [RTE_FLOW_ERROR_TYPE_ACTION] = "specific action", 1613 }; 1614 const char *errstr; 1615 char buf[32]; 1616 int err = rte_errno; 1617 1618 if ((unsigned int)error->type >= RTE_DIM(errstrlist) || 1619 !errstrlist[error->type]) 1620 errstr = "unknown type"; 1621 else 1622 errstr = errstrlist[error->type]; 1623 printf("%s(): Caught PMD error type %d (%s): %s%s: %s\n", __func__, 1624 error->type, errstr, 1625 error->cause ? (snprintf(buf, sizeof(buf), "cause: %p, ", 1626 error->cause), buf) : "", 1627 error->message ? error->message : "(no stated reason)", 1628 rte_strerror(err)); 1629 return -err; 1630 } 1631 1632 static void 1633 rss_config_display(struct rte_flow_action_rss *rss_conf) 1634 { 1635 uint8_t i; 1636 1637 if (rss_conf == NULL) { 1638 printf("Invalid rule\n"); 1639 return; 1640 } 1641 1642 printf("RSS:\n" 1643 " queues:"); 1644 if (rss_conf->queue_num == 0) 1645 printf(" none"); 1646 for (i = 0; i < rss_conf->queue_num; i++) 1647 printf(" %d", rss_conf->queue[i]); 1648 printf("\n"); 1649 1650 printf(" function: "); 1651 switch (rss_conf->func) { 1652 case RTE_ETH_HASH_FUNCTION_DEFAULT: 1653 printf("default\n"); 1654 break; 1655 case RTE_ETH_HASH_FUNCTION_TOEPLITZ: 1656 printf("toeplitz\n"); 1657 break; 1658 case RTE_ETH_HASH_FUNCTION_SIMPLE_XOR: 1659 printf("simple_xor\n"); 1660 break; 1661 case RTE_ETH_HASH_FUNCTION_SYMMETRIC_TOEPLITZ: 1662 printf("symmetric_toeplitz\n"); 1663 break; 1664 default: 1665 printf("Unknown function\n"); 1666 return; 1667 } 1668 1669 printf(" types:\n"); 1670 if (rss_conf->types == 0) { 1671 printf(" none\n"); 1672 return; 1673 } 1674 for (i = 0; rss_type_table[i].str; i++) { 1675 if ((rss_conf->types & 1676 rss_type_table[i].rss_type) == 1677 rss_type_table[i].rss_type && 1678 rss_type_table[i].rss_type != 0) 1679 printf(" %s\n", rss_type_table[i].str); 1680 } 1681 } 1682 1683 static struct port_shared_action * 1684 action_get_by_id(portid_t port_id, uint32_t id) 1685 { 1686 struct rte_port *port; 1687 struct port_shared_action **ppsa; 1688 struct port_shared_action *psa = NULL; 1689 1690 if (port_id_is_invalid(port_id, ENABLED_WARN) || 1691 port_id == (portid_t)RTE_PORT_ALL) 1692 return NULL; 1693 port = &ports[port_id]; 1694 ppsa = &port->actions_list; 1695 while (*ppsa) { 1696 if ((*ppsa)->id == id) { 1697 psa = *ppsa; 1698 break; 1699 } 1700 ppsa = &(*ppsa)->next; 1701 } 1702 if (!psa) 1703 printf("Failed to find shared action #%u on port %u\n", 1704 id, port_id); 1705 return psa; 1706 } 1707 1708 static int 1709 action_alloc(portid_t port_id, uint32_t id, 1710 struct port_shared_action **action) 1711 { 1712 struct rte_port *port; 1713 struct port_shared_action **ppsa; 1714 struct port_shared_action *psa = NULL; 1715 1716 *action = NULL; 1717 if (port_id_is_invalid(port_id, ENABLED_WARN) || 1718 port_id == (portid_t)RTE_PORT_ALL) 1719 return -EINVAL; 1720 port = &ports[port_id]; 1721 if (id == UINT32_MAX) { 1722 /* taking first available ID */ 1723 if (port->actions_list) { 1724 if (port->actions_list->id == UINT32_MAX - 1) { 1725 printf("Highest shared action ID is already" 1726 " assigned, delete it first\n"); 1727 return -ENOMEM; 1728 } 1729 id = port->actions_list->id + 1; 1730 } else { 1731 id = 0; 1732 } 1733 } 1734 psa = calloc(1, sizeof(*psa)); 1735 if (!psa) { 1736 printf("Allocation of port %u shared action failed\n", 1737 port_id); 1738 return -ENOMEM; 1739 } 1740 ppsa = &port->actions_list; 1741 while (*ppsa && (*ppsa)->id > id) 1742 ppsa = &(*ppsa)->next; 1743 if (*ppsa && (*ppsa)->id == id) { 1744 printf("Shared action #%u is already assigned," 1745 " delete it first\n", id); 1746 free(psa); 1747 return -EINVAL; 1748 } 1749 psa->next = *ppsa; 1750 psa->id = id; 1751 *ppsa = psa; 1752 *action = psa; 1753 return 0; 1754 } 1755 1756 /** Create shared action */ 1757 int 1758 port_shared_action_create(portid_t port_id, uint32_t id, 1759 const struct rte_flow_shared_action_conf *conf, 1760 const struct rte_flow_action *action) 1761 { 1762 struct port_shared_action *psa; 1763 int ret; 1764 struct rte_flow_error error; 1765 1766 ret = action_alloc(port_id, id, &psa); 1767 if (ret) 1768 return ret; 1769 if (action->type == RTE_FLOW_ACTION_TYPE_AGE) { 1770 struct rte_flow_action_age *age = 1771 (struct rte_flow_action_age *)(uintptr_t)(action->conf); 1772 1773 psa->age_type = ACTION_AGE_CONTEXT_TYPE_SHARED_ACTION; 1774 age->context = &psa->age_type; 1775 } 1776 /* Poisoning to make sure PMDs update it in case of error. */ 1777 memset(&error, 0x22, sizeof(error)); 1778 psa->action = rte_flow_shared_action_create(port_id, conf, action, 1779 &error); 1780 if (!psa->action) { 1781 uint32_t destroy_id = psa->id; 1782 port_shared_action_destroy(port_id, 1, &destroy_id); 1783 return port_flow_complain(&error); 1784 } 1785 psa->type = action->type; 1786 printf("Shared action #%u created\n", psa->id); 1787 return 0; 1788 } 1789 1790 /** Destroy shared action */ 1791 int 1792 port_shared_action_destroy(portid_t port_id, 1793 uint32_t n, 1794 const uint32_t *actions) 1795 { 1796 struct rte_port *port; 1797 struct port_shared_action **tmp; 1798 uint32_t c = 0; 1799 int ret = 0; 1800 1801 if (port_id_is_invalid(port_id, ENABLED_WARN) || 1802 port_id == (portid_t)RTE_PORT_ALL) 1803 return -EINVAL; 1804 port = &ports[port_id]; 1805 tmp = &port->actions_list; 1806 while (*tmp) { 1807 uint32_t i; 1808 1809 for (i = 0; i != n; ++i) { 1810 struct rte_flow_error error; 1811 struct port_shared_action *psa = *tmp; 1812 1813 if (actions[i] != psa->id) 1814 continue; 1815 /* 1816 * Poisoning to make sure PMDs update it in case 1817 * of error. 1818 */ 1819 memset(&error, 0x33, sizeof(error)); 1820 1821 if (psa->action && rte_flow_shared_action_destroy( 1822 port_id, psa->action, &error)) { 1823 ret = port_flow_complain(&error); 1824 continue; 1825 } 1826 *tmp = psa->next; 1827 printf("Shared action #%u destroyed\n", psa->id); 1828 free(psa); 1829 break; 1830 } 1831 if (i == n) 1832 tmp = &(*tmp)->next; 1833 ++c; 1834 } 1835 return ret; 1836 } 1837 1838 1839 /** Get shared action by port + id */ 1840 struct rte_flow_shared_action * 1841 port_shared_action_get_by_id(portid_t port_id, uint32_t id) 1842 { 1843 1844 struct port_shared_action *psa = action_get_by_id(port_id, id); 1845 1846 return (psa) ? psa->action : NULL; 1847 } 1848 1849 /** Update shared action */ 1850 int 1851 port_shared_action_update(portid_t port_id, uint32_t id, 1852 const struct rte_flow_action *action) 1853 { 1854 struct rte_flow_error error; 1855 struct rte_flow_shared_action *shared_action; 1856 1857 shared_action = port_shared_action_get_by_id(port_id, id); 1858 if (!shared_action) 1859 return -EINVAL; 1860 if (rte_flow_shared_action_update(port_id, shared_action, action, 1861 &error)) { 1862 return port_flow_complain(&error); 1863 } 1864 printf("Shared action #%u updated\n", id); 1865 return 0; 1866 } 1867 1868 int 1869 port_shared_action_query(portid_t port_id, uint32_t id) 1870 { 1871 struct rte_flow_error error; 1872 struct port_shared_action *psa; 1873 uint64_t default_data; 1874 void *data = NULL; 1875 int ret = 0; 1876 1877 psa = action_get_by_id(port_id, id); 1878 if (!psa) 1879 return -EINVAL; 1880 switch (psa->type) { 1881 case RTE_FLOW_ACTION_TYPE_RSS: 1882 case RTE_FLOW_ACTION_TYPE_AGE: 1883 data = &default_data; 1884 break; 1885 default: 1886 printf("Shared action %u (type: %d) on port %u doesn't support" 1887 " query\n", id, psa->type, port_id); 1888 return -1; 1889 } 1890 if (rte_flow_shared_action_query(port_id, psa->action, data, &error)) 1891 ret = port_flow_complain(&error); 1892 switch (psa->type) { 1893 case RTE_FLOW_ACTION_TYPE_RSS: 1894 if (!ret) 1895 printf("Shared RSS action:\n\trefs:%u\n", 1896 *((uint32_t *)data)); 1897 data = NULL; 1898 break; 1899 case RTE_FLOW_ACTION_TYPE_AGE: 1900 if (!ret) { 1901 struct rte_flow_query_age *resp = data; 1902 1903 printf("AGE:\n" 1904 " aged: %u\n" 1905 " sec_since_last_hit_valid: %u\n" 1906 " sec_since_last_hit: %" PRIu32 "\n", 1907 resp->aged, 1908 resp->sec_since_last_hit_valid, 1909 resp->sec_since_last_hit); 1910 } 1911 data = NULL; 1912 break; 1913 default: 1914 printf("Shared action %u (type: %d) on port %u doesn't support" 1915 " query\n", id, psa->type, port_id); 1916 ret = -1; 1917 } 1918 return ret; 1919 } 1920 1921 static struct port_flow_tunnel * 1922 port_flow_tunnel_offload_cmd_prep(portid_t port_id, 1923 const struct rte_flow_item *pattern, 1924 const struct rte_flow_action *actions, 1925 const struct tunnel_ops *tunnel_ops) 1926 { 1927 int ret; 1928 struct rte_port *port; 1929 struct port_flow_tunnel *pft; 1930 struct rte_flow_error error; 1931 1932 port = &ports[port_id]; 1933 pft = port_flow_locate_tunnel_id(port, tunnel_ops->id); 1934 if (!pft) { 1935 printf("failed to locate port flow tunnel #%u\n", 1936 tunnel_ops->id); 1937 return NULL; 1938 } 1939 if (tunnel_ops->actions) { 1940 uint32_t num_actions; 1941 const struct rte_flow_action *aptr; 1942 1943 ret = rte_flow_tunnel_decap_set(port_id, &pft->tunnel, 1944 &pft->pmd_actions, 1945 &pft->num_pmd_actions, 1946 &error); 1947 if (ret) { 1948 port_flow_complain(&error); 1949 return NULL; 1950 } 1951 for (aptr = actions, num_actions = 1; 1952 aptr->type != RTE_FLOW_ACTION_TYPE_END; 1953 aptr++, num_actions++); 1954 pft->actions = malloc( 1955 (num_actions + pft->num_pmd_actions) * 1956 sizeof(actions[0])); 1957 if (!pft->actions) { 1958 rte_flow_tunnel_action_decap_release( 1959 port_id, pft->actions, 1960 pft->num_pmd_actions, &error); 1961 return NULL; 1962 } 1963 rte_memcpy(pft->actions, pft->pmd_actions, 1964 pft->num_pmd_actions * sizeof(actions[0])); 1965 rte_memcpy(pft->actions + pft->num_pmd_actions, actions, 1966 num_actions * sizeof(actions[0])); 1967 } 1968 if (tunnel_ops->items) { 1969 uint32_t num_items; 1970 const struct rte_flow_item *iptr; 1971 1972 ret = rte_flow_tunnel_match(port_id, &pft->tunnel, 1973 &pft->pmd_items, 1974 &pft->num_pmd_items, 1975 &error); 1976 if (ret) { 1977 port_flow_complain(&error); 1978 return NULL; 1979 } 1980 for (iptr = pattern, num_items = 1; 1981 iptr->type != RTE_FLOW_ITEM_TYPE_END; 1982 iptr++, num_items++); 1983 pft->items = malloc((num_items + pft->num_pmd_items) * 1984 sizeof(pattern[0])); 1985 if (!pft->items) { 1986 rte_flow_tunnel_item_release( 1987 port_id, pft->pmd_items, 1988 pft->num_pmd_items, &error); 1989 return NULL; 1990 } 1991 rte_memcpy(pft->items, pft->pmd_items, 1992 pft->num_pmd_items * sizeof(pattern[0])); 1993 rte_memcpy(pft->items + pft->num_pmd_items, pattern, 1994 num_items * sizeof(pattern[0])); 1995 } 1996 1997 return pft; 1998 } 1999 2000 static void 2001 port_flow_tunnel_offload_cmd_release(portid_t port_id, 2002 const struct tunnel_ops *tunnel_ops, 2003 struct port_flow_tunnel *pft) 2004 { 2005 struct rte_flow_error error; 2006 2007 if (tunnel_ops->actions) { 2008 free(pft->actions); 2009 rte_flow_tunnel_action_decap_release( 2010 port_id, pft->pmd_actions, 2011 pft->num_pmd_actions, &error); 2012 pft->actions = NULL; 2013 pft->pmd_actions = NULL; 2014 } 2015 if (tunnel_ops->items) { 2016 free(pft->items); 2017 rte_flow_tunnel_item_release(port_id, pft->pmd_items, 2018 pft->num_pmd_items, 2019 &error); 2020 pft->items = NULL; 2021 pft->pmd_items = NULL; 2022 } 2023 } 2024 2025 /** Validate flow rule. */ 2026 int 2027 port_flow_validate(portid_t port_id, 2028 const struct rte_flow_attr *attr, 2029 const struct rte_flow_item *pattern, 2030 const struct rte_flow_action *actions, 2031 const struct tunnel_ops *tunnel_ops) 2032 { 2033 struct rte_flow_error error; 2034 struct port_flow_tunnel *pft = NULL; 2035 2036 /* Poisoning to make sure PMDs update it in case of error. */ 2037 memset(&error, 0x11, sizeof(error)); 2038 if (tunnel_ops->enabled) { 2039 pft = port_flow_tunnel_offload_cmd_prep(port_id, pattern, 2040 actions, tunnel_ops); 2041 if (!pft) 2042 return -ENOENT; 2043 if (pft->items) 2044 pattern = pft->items; 2045 if (pft->actions) 2046 actions = pft->actions; 2047 } 2048 if (rte_flow_validate(port_id, attr, pattern, actions, &error)) 2049 return port_flow_complain(&error); 2050 if (tunnel_ops->enabled) 2051 port_flow_tunnel_offload_cmd_release(port_id, tunnel_ops, pft); 2052 printf("Flow rule validated\n"); 2053 return 0; 2054 } 2055 2056 /** Return age action structure if exists, otherwise NULL. */ 2057 static struct rte_flow_action_age * 2058 age_action_get(const struct rte_flow_action *actions) 2059 { 2060 for (; actions->type != RTE_FLOW_ACTION_TYPE_END; actions++) { 2061 switch (actions->type) { 2062 case RTE_FLOW_ACTION_TYPE_AGE: 2063 return (struct rte_flow_action_age *) 2064 (uintptr_t)actions->conf; 2065 default: 2066 break; 2067 } 2068 } 2069 return NULL; 2070 } 2071 2072 /** Create flow rule. */ 2073 int 2074 port_flow_create(portid_t port_id, 2075 const struct rte_flow_attr *attr, 2076 const struct rte_flow_item *pattern, 2077 const struct rte_flow_action *actions, 2078 const struct tunnel_ops *tunnel_ops) 2079 { 2080 struct rte_flow *flow; 2081 struct rte_port *port; 2082 struct port_flow *pf; 2083 uint32_t id = 0; 2084 struct rte_flow_error error; 2085 struct port_flow_tunnel *pft = NULL; 2086 struct rte_flow_action_age *age = age_action_get(actions); 2087 2088 port = &ports[port_id]; 2089 if (port->flow_list) { 2090 if (port->flow_list->id == UINT32_MAX) { 2091 printf("Highest rule ID is already assigned, delete" 2092 " it first"); 2093 return -ENOMEM; 2094 } 2095 id = port->flow_list->id + 1; 2096 } 2097 if (tunnel_ops->enabled) { 2098 pft = port_flow_tunnel_offload_cmd_prep(port_id, pattern, 2099 actions, tunnel_ops); 2100 if (!pft) 2101 return -ENOENT; 2102 if (pft->items) 2103 pattern = pft->items; 2104 if (pft->actions) 2105 actions = pft->actions; 2106 } 2107 pf = port_flow_new(attr, pattern, actions, &error); 2108 if (!pf) 2109 return port_flow_complain(&error); 2110 if (age) { 2111 pf->age_type = ACTION_AGE_CONTEXT_TYPE_FLOW; 2112 age->context = &pf->age_type; 2113 } 2114 /* Poisoning to make sure PMDs update it in case of error. */ 2115 memset(&error, 0x22, sizeof(error)); 2116 flow = rte_flow_create(port_id, attr, pattern, actions, &error); 2117 if (!flow) { 2118 free(pf); 2119 return port_flow_complain(&error); 2120 } 2121 pf->next = port->flow_list; 2122 pf->id = id; 2123 pf->flow = flow; 2124 port->flow_list = pf; 2125 if (tunnel_ops->enabled) 2126 port_flow_tunnel_offload_cmd_release(port_id, tunnel_ops, pft); 2127 printf("Flow rule #%u created\n", pf->id); 2128 return 0; 2129 } 2130 2131 /** Destroy a number of flow rules. */ 2132 int 2133 port_flow_destroy(portid_t port_id, uint32_t n, const uint32_t *rule) 2134 { 2135 struct rte_port *port; 2136 struct port_flow **tmp; 2137 uint32_t c = 0; 2138 int ret = 0; 2139 2140 if (port_id_is_invalid(port_id, ENABLED_WARN) || 2141 port_id == (portid_t)RTE_PORT_ALL) 2142 return -EINVAL; 2143 port = &ports[port_id]; 2144 tmp = &port->flow_list; 2145 while (*tmp) { 2146 uint32_t i; 2147 2148 for (i = 0; i != n; ++i) { 2149 struct rte_flow_error error; 2150 struct port_flow *pf = *tmp; 2151 2152 if (rule[i] != pf->id) 2153 continue; 2154 /* 2155 * Poisoning to make sure PMDs update it in case 2156 * of error. 2157 */ 2158 memset(&error, 0x33, sizeof(error)); 2159 if (rte_flow_destroy(port_id, pf->flow, &error)) { 2160 ret = port_flow_complain(&error); 2161 continue; 2162 } 2163 printf("Flow rule #%u destroyed\n", pf->id); 2164 *tmp = pf->next; 2165 free(pf); 2166 break; 2167 } 2168 if (i == n) 2169 tmp = &(*tmp)->next; 2170 ++c; 2171 } 2172 return ret; 2173 } 2174 2175 /** Remove all flow rules. */ 2176 int 2177 port_flow_flush(portid_t port_id) 2178 { 2179 struct rte_flow_error error; 2180 struct rte_port *port; 2181 int ret = 0; 2182 2183 if (port_id_is_invalid(port_id, ENABLED_WARN) || 2184 port_id == (portid_t)RTE_PORT_ALL) 2185 return -EINVAL; 2186 2187 port = &ports[port_id]; 2188 2189 if (port->flow_list == NULL) 2190 return ret; 2191 2192 /* Poisoning to make sure PMDs update it in case of error. */ 2193 memset(&error, 0x44, sizeof(error)); 2194 if (rte_flow_flush(port_id, &error)) { 2195 port_flow_complain(&error); 2196 } 2197 2198 while (port->flow_list) { 2199 struct port_flow *pf = port->flow_list->next; 2200 2201 free(port->flow_list); 2202 port->flow_list = pf; 2203 } 2204 return ret; 2205 } 2206 2207 /** Dump all flow rules. */ 2208 int 2209 port_flow_dump(portid_t port_id, const char *file_name) 2210 { 2211 int ret = 0; 2212 FILE *file = stdout; 2213 struct rte_flow_error error; 2214 2215 if (file_name && strlen(file_name)) { 2216 file = fopen(file_name, "w"); 2217 if (!file) { 2218 printf("Failed to create file %s: %s\n", file_name, 2219 strerror(errno)); 2220 return -errno; 2221 } 2222 } 2223 ret = rte_flow_dev_dump(port_id, file, &error); 2224 if (ret) { 2225 port_flow_complain(&error); 2226 printf("Failed to dump flow: %s\n", strerror(-ret)); 2227 } else 2228 printf("Flow dump finished\n"); 2229 if (file_name && strlen(file_name)) 2230 fclose(file); 2231 return ret; 2232 } 2233 2234 /** Query a flow rule. */ 2235 int 2236 port_flow_query(portid_t port_id, uint32_t rule, 2237 const struct rte_flow_action *action) 2238 { 2239 struct rte_flow_error error; 2240 struct rte_port *port; 2241 struct port_flow *pf; 2242 const char *name; 2243 union { 2244 struct rte_flow_query_count count; 2245 struct rte_flow_action_rss rss_conf; 2246 struct rte_flow_query_age age; 2247 } query; 2248 int ret; 2249 2250 if (port_id_is_invalid(port_id, ENABLED_WARN) || 2251 port_id == (portid_t)RTE_PORT_ALL) 2252 return -EINVAL; 2253 port = &ports[port_id]; 2254 for (pf = port->flow_list; pf; pf = pf->next) 2255 if (pf->id == rule) 2256 break; 2257 if (!pf) { 2258 printf("Flow rule #%u not found\n", rule); 2259 return -ENOENT; 2260 } 2261 ret = rte_flow_conv(RTE_FLOW_CONV_OP_ACTION_NAME_PTR, 2262 &name, sizeof(name), 2263 (void *)(uintptr_t)action->type, &error); 2264 if (ret < 0) 2265 return port_flow_complain(&error); 2266 switch (action->type) { 2267 case RTE_FLOW_ACTION_TYPE_COUNT: 2268 case RTE_FLOW_ACTION_TYPE_RSS: 2269 case RTE_FLOW_ACTION_TYPE_AGE: 2270 break; 2271 default: 2272 printf("Cannot query action type %d (%s)\n", 2273 action->type, name); 2274 return -ENOTSUP; 2275 } 2276 /* Poisoning to make sure PMDs update it in case of error. */ 2277 memset(&error, 0x55, sizeof(error)); 2278 memset(&query, 0, sizeof(query)); 2279 if (rte_flow_query(port_id, pf->flow, action, &query, &error)) 2280 return port_flow_complain(&error); 2281 switch (action->type) { 2282 case RTE_FLOW_ACTION_TYPE_COUNT: 2283 printf("%s:\n" 2284 " hits_set: %u\n" 2285 " bytes_set: %u\n" 2286 " hits: %" PRIu64 "\n" 2287 " bytes: %" PRIu64 "\n", 2288 name, 2289 query.count.hits_set, 2290 query.count.bytes_set, 2291 query.count.hits, 2292 query.count.bytes); 2293 break; 2294 case RTE_FLOW_ACTION_TYPE_RSS: 2295 rss_config_display(&query.rss_conf); 2296 break; 2297 case RTE_FLOW_ACTION_TYPE_AGE: 2298 printf("%s:\n" 2299 " aged: %u\n" 2300 " sec_since_last_hit_valid: %u\n" 2301 " sec_since_last_hit: %" PRIu32 "\n", 2302 name, 2303 query.age.aged, 2304 query.age.sec_since_last_hit_valid, 2305 query.age.sec_since_last_hit); 2306 break; 2307 default: 2308 printf("Cannot display result for action type %d (%s)\n", 2309 action->type, name); 2310 break; 2311 } 2312 return 0; 2313 } 2314 2315 /** List simply and destroy all aged flows. */ 2316 void 2317 port_flow_aged(portid_t port_id, uint8_t destroy) 2318 { 2319 void **contexts; 2320 int nb_context, total = 0, idx; 2321 struct rte_flow_error error; 2322 enum age_action_context_type *type; 2323 union { 2324 struct port_flow *pf; 2325 struct port_shared_action *psa; 2326 } ctx; 2327 2328 if (port_id_is_invalid(port_id, ENABLED_WARN) || 2329 port_id == (portid_t)RTE_PORT_ALL) 2330 return; 2331 total = rte_flow_get_aged_flows(port_id, NULL, 0, &error); 2332 printf("Port %u total aged flows: %d\n", port_id, total); 2333 if (total < 0) { 2334 port_flow_complain(&error); 2335 return; 2336 } 2337 if (total == 0) 2338 return; 2339 contexts = malloc(sizeof(void *) * total); 2340 if (contexts == NULL) { 2341 printf("Cannot allocate contexts for aged flow\n"); 2342 return; 2343 } 2344 printf("%-20s\tID\tGroup\tPrio\tAttr\n", "Type"); 2345 nb_context = rte_flow_get_aged_flows(port_id, contexts, total, &error); 2346 if (nb_context != total) { 2347 printf("Port:%d get aged flows count(%d) != total(%d)\n", 2348 port_id, nb_context, total); 2349 free(contexts); 2350 return; 2351 } 2352 total = 0; 2353 for (idx = 0; idx < nb_context; idx++) { 2354 if (!contexts[idx]) { 2355 printf("Error: get Null context in port %u\n", port_id); 2356 continue; 2357 } 2358 type = (enum age_action_context_type *)contexts[idx]; 2359 switch (*type) { 2360 case ACTION_AGE_CONTEXT_TYPE_FLOW: 2361 ctx.pf = container_of(type, struct port_flow, age_type); 2362 printf("%-20s\t%" PRIu32 "\t%" PRIu32 "\t%" PRIu32 2363 "\t%c%c%c\t\n", 2364 "Flow", 2365 ctx.pf->id, 2366 ctx.pf->rule.attr->group, 2367 ctx.pf->rule.attr->priority, 2368 ctx.pf->rule.attr->ingress ? 'i' : '-', 2369 ctx.pf->rule.attr->egress ? 'e' : '-', 2370 ctx.pf->rule.attr->transfer ? 't' : '-'); 2371 if (destroy && !port_flow_destroy(port_id, 1, 2372 &ctx.pf->id)) 2373 total++; 2374 break; 2375 case ACTION_AGE_CONTEXT_TYPE_SHARED_ACTION: 2376 ctx.psa = container_of(type, struct port_shared_action, 2377 age_type); 2378 printf("%-20s\t%" PRIu32 "\n", "Shared action", 2379 ctx.psa->id); 2380 break; 2381 default: 2382 printf("Error: invalid context type %u\n", port_id); 2383 break; 2384 } 2385 } 2386 printf("\n%d flows destroyed\n", total); 2387 free(contexts); 2388 } 2389 2390 /** List flow rules. */ 2391 void 2392 port_flow_list(portid_t port_id, uint32_t n, const uint32_t *group) 2393 { 2394 struct rte_port *port; 2395 struct port_flow *pf; 2396 struct port_flow *list = NULL; 2397 uint32_t i; 2398 2399 if (port_id_is_invalid(port_id, ENABLED_WARN) || 2400 port_id == (portid_t)RTE_PORT_ALL) 2401 return; 2402 port = &ports[port_id]; 2403 if (!port->flow_list) 2404 return; 2405 /* Sort flows by group, priority and ID. */ 2406 for (pf = port->flow_list; pf != NULL; pf = pf->next) { 2407 struct port_flow **tmp; 2408 const struct rte_flow_attr *curr = pf->rule.attr; 2409 2410 if (n) { 2411 /* Filter out unwanted groups. */ 2412 for (i = 0; i != n; ++i) 2413 if (curr->group == group[i]) 2414 break; 2415 if (i == n) 2416 continue; 2417 } 2418 for (tmp = &list; *tmp; tmp = &(*tmp)->tmp) { 2419 const struct rte_flow_attr *comp = (*tmp)->rule.attr; 2420 2421 if (curr->group > comp->group || 2422 (curr->group == comp->group && 2423 curr->priority > comp->priority) || 2424 (curr->group == comp->group && 2425 curr->priority == comp->priority && 2426 pf->id > (*tmp)->id)) 2427 continue; 2428 break; 2429 } 2430 pf->tmp = *tmp; 2431 *tmp = pf; 2432 } 2433 printf("ID\tGroup\tPrio\tAttr\tRule\n"); 2434 for (pf = list; pf != NULL; pf = pf->tmp) { 2435 const struct rte_flow_item *item = pf->rule.pattern; 2436 const struct rte_flow_action *action = pf->rule.actions; 2437 const char *name; 2438 2439 printf("%" PRIu32 "\t%" PRIu32 "\t%" PRIu32 "\t%c%c%c\t", 2440 pf->id, 2441 pf->rule.attr->group, 2442 pf->rule.attr->priority, 2443 pf->rule.attr->ingress ? 'i' : '-', 2444 pf->rule.attr->egress ? 'e' : '-', 2445 pf->rule.attr->transfer ? 't' : '-'); 2446 while (item->type != RTE_FLOW_ITEM_TYPE_END) { 2447 if ((uint32_t)item->type > INT_MAX) 2448 name = "PMD_INTERNAL"; 2449 else if (rte_flow_conv(RTE_FLOW_CONV_OP_ITEM_NAME_PTR, 2450 &name, sizeof(name), 2451 (void *)(uintptr_t)item->type, 2452 NULL) <= 0) 2453 name = "[UNKNOWN]"; 2454 if (item->type != RTE_FLOW_ITEM_TYPE_VOID) 2455 printf("%s ", name); 2456 ++item; 2457 } 2458 printf("=>"); 2459 while (action->type != RTE_FLOW_ACTION_TYPE_END) { 2460 if ((uint32_t)action->type > INT_MAX) 2461 name = "PMD_INTERNAL"; 2462 else if (rte_flow_conv(RTE_FLOW_CONV_OP_ACTION_NAME_PTR, 2463 &name, sizeof(name), 2464 (void *)(uintptr_t)action->type, 2465 NULL) <= 0) 2466 name = "[UNKNOWN]"; 2467 if (action->type != RTE_FLOW_ACTION_TYPE_VOID) 2468 printf(" %s", name); 2469 ++action; 2470 } 2471 printf("\n"); 2472 } 2473 } 2474 2475 /** Restrict ingress traffic to the defined flow rules. */ 2476 int 2477 port_flow_isolate(portid_t port_id, int set) 2478 { 2479 struct rte_flow_error error; 2480 2481 /* Poisoning to make sure PMDs update it in case of error. */ 2482 memset(&error, 0x66, sizeof(error)); 2483 if (rte_flow_isolate(port_id, set, &error)) 2484 return port_flow_complain(&error); 2485 printf("Ingress traffic on port %u is %s to the defined flow rules\n", 2486 port_id, 2487 set ? "now restricted" : "not restricted anymore"); 2488 return 0; 2489 } 2490 2491 /* 2492 * RX/TX ring descriptors display functions. 2493 */ 2494 int 2495 rx_queue_id_is_invalid(queueid_t rxq_id) 2496 { 2497 if (rxq_id < nb_rxq) 2498 return 0; 2499 printf("Invalid RX queue %d (must be < nb_rxq=%d)\n", rxq_id, nb_rxq); 2500 return 1; 2501 } 2502 2503 int 2504 tx_queue_id_is_invalid(queueid_t txq_id) 2505 { 2506 if (txq_id < nb_txq) 2507 return 0; 2508 printf("Invalid TX queue %d (must be < nb_txq=%d)\n", txq_id, nb_txq); 2509 return 1; 2510 } 2511 2512 static int 2513 get_rx_ring_size(portid_t port_id, queueid_t rxq_id, uint16_t *ring_size) 2514 { 2515 struct rte_port *port = &ports[port_id]; 2516 struct rte_eth_rxq_info rx_qinfo; 2517 int ret; 2518 2519 ret = rte_eth_rx_queue_info_get(port_id, rxq_id, &rx_qinfo); 2520 if (ret == 0) { 2521 *ring_size = rx_qinfo.nb_desc; 2522 return ret; 2523 } 2524 2525 if (ret != -ENOTSUP) 2526 return ret; 2527 /* 2528 * If the rte_eth_rx_queue_info_get is not support for this PMD, 2529 * ring_size stored in testpmd will be used for validity verification. 2530 * When configure the rxq by rte_eth_rx_queue_setup with nb_rx_desc 2531 * being 0, it will use a default value provided by PMDs to setup this 2532 * rxq. If the default value is 0, it will use the 2533 * RTE_ETH_DEV_FALLBACK_RX_RINGSIZE to setup this rxq. 2534 */ 2535 if (port->nb_rx_desc[rxq_id]) 2536 *ring_size = port->nb_rx_desc[rxq_id]; 2537 else if (port->dev_info.default_rxportconf.ring_size) 2538 *ring_size = port->dev_info.default_rxportconf.ring_size; 2539 else 2540 *ring_size = RTE_ETH_DEV_FALLBACK_RX_RINGSIZE; 2541 return 0; 2542 } 2543 2544 static int 2545 get_tx_ring_size(portid_t port_id, queueid_t txq_id, uint16_t *ring_size) 2546 { 2547 struct rte_port *port = &ports[port_id]; 2548 struct rte_eth_txq_info tx_qinfo; 2549 int ret; 2550 2551 ret = rte_eth_tx_queue_info_get(port_id, txq_id, &tx_qinfo); 2552 if (ret == 0) { 2553 *ring_size = tx_qinfo.nb_desc; 2554 return ret; 2555 } 2556 2557 if (ret != -ENOTSUP) 2558 return ret; 2559 /* 2560 * If the rte_eth_tx_queue_info_get is not support for this PMD, 2561 * ring_size stored in testpmd will be used for validity verification. 2562 * When configure the txq by rte_eth_tx_queue_setup with nb_tx_desc 2563 * being 0, it will use a default value provided by PMDs to setup this 2564 * txq. If the default value is 0, it will use the 2565 * RTE_ETH_DEV_FALLBACK_TX_RINGSIZE to setup this txq. 2566 */ 2567 if (port->nb_tx_desc[txq_id]) 2568 *ring_size = port->nb_tx_desc[txq_id]; 2569 else if (port->dev_info.default_txportconf.ring_size) 2570 *ring_size = port->dev_info.default_txportconf.ring_size; 2571 else 2572 *ring_size = RTE_ETH_DEV_FALLBACK_TX_RINGSIZE; 2573 return 0; 2574 } 2575 2576 static int 2577 rx_desc_id_is_invalid(portid_t port_id, queueid_t rxq_id, uint16_t rxdesc_id) 2578 { 2579 uint16_t ring_size; 2580 int ret; 2581 2582 ret = get_rx_ring_size(port_id, rxq_id, &ring_size); 2583 if (ret) 2584 return 1; 2585 2586 if (rxdesc_id < ring_size) 2587 return 0; 2588 2589 printf("Invalid RX descriptor %u (must be < ring_size=%u)\n", 2590 rxdesc_id, ring_size); 2591 return 1; 2592 } 2593 2594 static int 2595 tx_desc_id_is_invalid(portid_t port_id, queueid_t txq_id, uint16_t txdesc_id) 2596 { 2597 uint16_t ring_size; 2598 int ret; 2599 2600 ret = get_tx_ring_size(port_id, txq_id, &ring_size); 2601 if (ret) 2602 return 1; 2603 2604 if (txdesc_id < ring_size) 2605 return 0; 2606 2607 printf("Invalid TX descriptor %u (must be < ring_size=%u)\n", 2608 txdesc_id, ring_size); 2609 return 1; 2610 } 2611 2612 static const struct rte_memzone * 2613 ring_dma_zone_lookup(const char *ring_name, portid_t port_id, uint16_t q_id) 2614 { 2615 char mz_name[RTE_MEMZONE_NAMESIZE]; 2616 const struct rte_memzone *mz; 2617 2618 snprintf(mz_name, sizeof(mz_name), "eth_p%d_q%d_%s", 2619 port_id, q_id, ring_name); 2620 mz = rte_memzone_lookup(mz_name); 2621 if (mz == NULL) 2622 printf("%s ring memory zoneof (port %d, queue %d) not" 2623 "found (zone name = %s\n", 2624 ring_name, port_id, q_id, mz_name); 2625 return mz; 2626 } 2627 2628 union igb_ring_dword { 2629 uint64_t dword; 2630 struct { 2631 #if RTE_BYTE_ORDER == RTE_BIG_ENDIAN 2632 uint32_t lo; 2633 uint32_t hi; 2634 #else 2635 uint32_t hi; 2636 uint32_t lo; 2637 #endif 2638 } words; 2639 }; 2640 2641 struct igb_ring_desc_32_bytes { 2642 union igb_ring_dword lo_dword; 2643 union igb_ring_dword hi_dword; 2644 union igb_ring_dword resv1; 2645 union igb_ring_dword resv2; 2646 }; 2647 2648 struct igb_ring_desc_16_bytes { 2649 union igb_ring_dword lo_dword; 2650 union igb_ring_dword hi_dword; 2651 }; 2652 2653 static void 2654 ring_rxd_display_dword(union igb_ring_dword dword) 2655 { 2656 printf(" 0x%08X - 0x%08X\n", (unsigned)dword.words.lo, 2657 (unsigned)dword.words.hi); 2658 } 2659 2660 static void 2661 ring_rx_descriptor_display(const struct rte_memzone *ring_mz, 2662 #ifndef RTE_LIBRTE_I40E_16BYTE_RX_DESC 2663 portid_t port_id, 2664 #else 2665 __rte_unused portid_t port_id, 2666 #endif 2667 uint16_t desc_id) 2668 { 2669 struct igb_ring_desc_16_bytes *ring = 2670 (struct igb_ring_desc_16_bytes *)ring_mz->addr; 2671 #ifndef RTE_LIBRTE_I40E_16BYTE_RX_DESC 2672 int ret; 2673 struct rte_eth_dev_info dev_info; 2674 2675 ret = eth_dev_info_get_print_err(port_id, &dev_info); 2676 if (ret != 0) 2677 return; 2678 2679 if (strstr(dev_info.driver_name, "i40e") != NULL) { 2680 /* 32 bytes RX descriptor, i40e only */ 2681 struct igb_ring_desc_32_bytes *ring = 2682 (struct igb_ring_desc_32_bytes *)ring_mz->addr; 2683 ring[desc_id].lo_dword.dword = 2684 rte_le_to_cpu_64(ring[desc_id].lo_dword.dword); 2685 ring_rxd_display_dword(ring[desc_id].lo_dword); 2686 ring[desc_id].hi_dword.dword = 2687 rte_le_to_cpu_64(ring[desc_id].hi_dword.dword); 2688 ring_rxd_display_dword(ring[desc_id].hi_dword); 2689 ring[desc_id].resv1.dword = 2690 rte_le_to_cpu_64(ring[desc_id].resv1.dword); 2691 ring_rxd_display_dword(ring[desc_id].resv1); 2692 ring[desc_id].resv2.dword = 2693 rte_le_to_cpu_64(ring[desc_id].resv2.dword); 2694 ring_rxd_display_dword(ring[desc_id].resv2); 2695 2696 return; 2697 } 2698 #endif 2699 /* 16 bytes RX descriptor */ 2700 ring[desc_id].lo_dword.dword = 2701 rte_le_to_cpu_64(ring[desc_id].lo_dword.dword); 2702 ring_rxd_display_dword(ring[desc_id].lo_dword); 2703 ring[desc_id].hi_dword.dword = 2704 rte_le_to_cpu_64(ring[desc_id].hi_dword.dword); 2705 ring_rxd_display_dword(ring[desc_id].hi_dword); 2706 } 2707 2708 static void 2709 ring_tx_descriptor_display(const struct rte_memzone *ring_mz, uint16_t desc_id) 2710 { 2711 struct igb_ring_desc_16_bytes *ring; 2712 struct igb_ring_desc_16_bytes txd; 2713 2714 ring = (struct igb_ring_desc_16_bytes *)ring_mz->addr; 2715 txd.lo_dword.dword = rte_le_to_cpu_64(ring[desc_id].lo_dword.dword); 2716 txd.hi_dword.dword = rte_le_to_cpu_64(ring[desc_id].hi_dword.dword); 2717 printf(" 0x%08X - 0x%08X / 0x%08X - 0x%08X\n", 2718 (unsigned)txd.lo_dword.words.lo, 2719 (unsigned)txd.lo_dword.words.hi, 2720 (unsigned)txd.hi_dword.words.lo, 2721 (unsigned)txd.hi_dword.words.hi); 2722 } 2723 2724 void 2725 rx_ring_desc_display(portid_t port_id, queueid_t rxq_id, uint16_t rxd_id) 2726 { 2727 const struct rte_memzone *rx_mz; 2728 2729 if (rx_desc_id_is_invalid(port_id, rxq_id, rxd_id)) 2730 return; 2731 rx_mz = ring_dma_zone_lookup("rx_ring", port_id, rxq_id); 2732 if (rx_mz == NULL) 2733 return; 2734 ring_rx_descriptor_display(rx_mz, port_id, rxd_id); 2735 } 2736 2737 void 2738 tx_ring_desc_display(portid_t port_id, queueid_t txq_id, uint16_t txd_id) 2739 { 2740 const struct rte_memzone *tx_mz; 2741 2742 if (tx_desc_id_is_invalid(port_id, txq_id, txd_id)) 2743 return; 2744 tx_mz = ring_dma_zone_lookup("tx_ring", port_id, txq_id); 2745 if (tx_mz == NULL) 2746 return; 2747 ring_tx_descriptor_display(tx_mz, txd_id); 2748 } 2749 2750 void 2751 fwd_lcores_config_display(void) 2752 { 2753 lcoreid_t lc_id; 2754 2755 printf("List of forwarding lcores:"); 2756 for (lc_id = 0; lc_id < nb_cfg_lcores; lc_id++) 2757 printf(" %2u", fwd_lcores_cpuids[lc_id]); 2758 printf("\n"); 2759 } 2760 void 2761 rxtx_config_display(void) 2762 { 2763 portid_t pid; 2764 queueid_t qid; 2765 2766 printf(" %s packet forwarding%s packets/burst=%d\n", 2767 cur_fwd_eng->fwd_mode_name, 2768 retry_enabled == 0 ? "" : " with retry", 2769 nb_pkt_per_burst); 2770 2771 if (cur_fwd_eng == &tx_only_engine || cur_fwd_eng == &flow_gen_engine) 2772 printf(" packet len=%u - nb packet segments=%d\n", 2773 (unsigned)tx_pkt_length, (int) tx_pkt_nb_segs); 2774 2775 printf(" nb forwarding cores=%d - nb forwarding ports=%d\n", 2776 nb_fwd_lcores, nb_fwd_ports); 2777 2778 RTE_ETH_FOREACH_DEV(pid) { 2779 struct rte_eth_rxconf *rx_conf = &ports[pid].rx_conf[0]; 2780 struct rte_eth_txconf *tx_conf = &ports[pid].tx_conf[0]; 2781 uint16_t *nb_rx_desc = &ports[pid].nb_rx_desc[0]; 2782 uint16_t *nb_tx_desc = &ports[pid].nb_tx_desc[0]; 2783 struct rte_eth_rxq_info rx_qinfo; 2784 struct rte_eth_txq_info tx_qinfo; 2785 uint16_t rx_free_thresh_tmp; 2786 uint16_t tx_free_thresh_tmp; 2787 uint16_t tx_rs_thresh_tmp; 2788 uint16_t nb_rx_desc_tmp; 2789 uint16_t nb_tx_desc_tmp; 2790 uint64_t offloads_tmp; 2791 uint8_t pthresh_tmp; 2792 uint8_t hthresh_tmp; 2793 uint8_t wthresh_tmp; 2794 int32_t rc; 2795 2796 /* per port config */ 2797 printf(" port %d: RX queue number: %d Tx queue number: %d\n", 2798 (unsigned int)pid, nb_rxq, nb_txq); 2799 2800 printf(" Rx offloads=0x%"PRIx64" Tx offloads=0x%"PRIx64"\n", 2801 ports[pid].dev_conf.rxmode.offloads, 2802 ports[pid].dev_conf.txmode.offloads); 2803 2804 /* per rx queue config only for first queue to be less verbose */ 2805 for (qid = 0; qid < 1; qid++) { 2806 rc = rte_eth_rx_queue_info_get(pid, qid, &rx_qinfo); 2807 if (rc) { 2808 nb_rx_desc_tmp = nb_rx_desc[qid]; 2809 rx_free_thresh_tmp = 2810 rx_conf[qid].rx_free_thresh; 2811 pthresh_tmp = rx_conf[qid].rx_thresh.pthresh; 2812 hthresh_tmp = rx_conf[qid].rx_thresh.hthresh; 2813 wthresh_tmp = rx_conf[qid].rx_thresh.wthresh; 2814 offloads_tmp = rx_conf[qid].offloads; 2815 } else { 2816 nb_rx_desc_tmp = rx_qinfo.nb_desc; 2817 rx_free_thresh_tmp = 2818 rx_qinfo.conf.rx_free_thresh; 2819 pthresh_tmp = rx_qinfo.conf.rx_thresh.pthresh; 2820 hthresh_tmp = rx_qinfo.conf.rx_thresh.hthresh; 2821 wthresh_tmp = rx_qinfo.conf.rx_thresh.wthresh; 2822 offloads_tmp = rx_qinfo.conf.offloads; 2823 } 2824 2825 printf(" RX queue: %d\n", qid); 2826 printf(" RX desc=%d - RX free threshold=%d\n", 2827 nb_rx_desc_tmp, rx_free_thresh_tmp); 2828 printf(" RX threshold registers: pthresh=%d hthresh=%d " 2829 " wthresh=%d\n", 2830 pthresh_tmp, hthresh_tmp, wthresh_tmp); 2831 printf(" RX Offloads=0x%"PRIx64"\n", offloads_tmp); 2832 } 2833 2834 /* per tx queue config only for first queue to be less verbose */ 2835 for (qid = 0; qid < 1; qid++) { 2836 rc = rte_eth_tx_queue_info_get(pid, qid, &tx_qinfo); 2837 if (rc) { 2838 nb_tx_desc_tmp = nb_tx_desc[qid]; 2839 tx_free_thresh_tmp = 2840 tx_conf[qid].tx_free_thresh; 2841 pthresh_tmp = tx_conf[qid].tx_thresh.pthresh; 2842 hthresh_tmp = tx_conf[qid].tx_thresh.hthresh; 2843 wthresh_tmp = tx_conf[qid].tx_thresh.wthresh; 2844 offloads_tmp = tx_conf[qid].offloads; 2845 tx_rs_thresh_tmp = tx_conf[qid].tx_rs_thresh; 2846 } else { 2847 nb_tx_desc_tmp = tx_qinfo.nb_desc; 2848 tx_free_thresh_tmp = 2849 tx_qinfo.conf.tx_free_thresh; 2850 pthresh_tmp = tx_qinfo.conf.tx_thresh.pthresh; 2851 hthresh_tmp = tx_qinfo.conf.tx_thresh.hthresh; 2852 wthresh_tmp = tx_qinfo.conf.tx_thresh.wthresh; 2853 offloads_tmp = tx_qinfo.conf.offloads; 2854 tx_rs_thresh_tmp = tx_qinfo.conf.tx_rs_thresh; 2855 } 2856 2857 printf(" TX queue: %d\n", qid); 2858 printf(" TX desc=%d - TX free threshold=%d\n", 2859 nb_tx_desc_tmp, tx_free_thresh_tmp); 2860 printf(" TX threshold registers: pthresh=%d hthresh=%d " 2861 " wthresh=%d\n", 2862 pthresh_tmp, hthresh_tmp, wthresh_tmp); 2863 printf(" TX offloads=0x%"PRIx64" - TX RS bit threshold=%d\n", 2864 offloads_tmp, tx_rs_thresh_tmp); 2865 } 2866 } 2867 } 2868 2869 void 2870 port_rss_reta_info(portid_t port_id, 2871 struct rte_eth_rss_reta_entry64 *reta_conf, 2872 uint16_t nb_entries) 2873 { 2874 uint16_t i, idx, shift; 2875 int ret; 2876 2877 if (port_id_is_invalid(port_id, ENABLED_WARN)) 2878 return; 2879 2880 ret = rte_eth_dev_rss_reta_query(port_id, reta_conf, nb_entries); 2881 if (ret != 0) { 2882 printf("Failed to get RSS RETA info, return code = %d\n", ret); 2883 return; 2884 } 2885 2886 for (i = 0; i < nb_entries; i++) { 2887 idx = i / RTE_RETA_GROUP_SIZE; 2888 shift = i % RTE_RETA_GROUP_SIZE; 2889 if (!(reta_conf[idx].mask & (1ULL << shift))) 2890 continue; 2891 printf("RSS RETA configuration: hash index=%u, queue=%u\n", 2892 i, reta_conf[idx].reta[shift]); 2893 } 2894 } 2895 2896 /* 2897 * Displays the RSS hash functions of a port, and, optionaly, the RSS hash 2898 * key of the port. 2899 */ 2900 void 2901 port_rss_hash_conf_show(portid_t port_id, int show_rss_key) 2902 { 2903 struct rte_eth_rss_conf rss_conf = {0}; 2904 uint8_t rss_key[RSS_HASH_KEY_LENGTH]; 2905 uint64_t rss_hf; 2906 uint8_t i; 2907 int diag; 2908 struct rte_eth_dev_info dev_info; 2909 uint8_t hash_key_size; 2910 int ret; 2911 2912 if (port_id_is_invalid(port_id, ENABLED_WARN)) 2913 return; 2914 2915 ret = eth_dev_info_get_print_err(port_id, &dev_info); 2916 if (ret != 0) 2917 return; 2918 2919 if (dev_info.hash_key_size > 0 && 2920 dev_info.hash_key_size <= sizeof(rss_key)) 2921 hash_key_size = dev_info.hash_key_size; 2922 else { 2923 printf("dev_info did not provide a valid hash key size\n"); 2924 return; 2925 } 2926 2927 /* Get RSS hash key if asked to display it */ 2928 rss_conf.rss_key = (show_rss_key) ? rss_key : NULL; 2929 rss_conf.rss_key_len = hash_key_size; 2930 diag = rte_eth_dev_rss_hash_conf_get(port_id, &rss_conf); 2931 if (diag != 0) { 2932 switch (diag) { 2933 case -ENODEV: 2934 printf("port index %d invalid\n", port_id); 2935 break; 2936 case -ENOTSUP: 2937 printf("operation not supported by device\n"); 2938 break; 2939 default: 2940 printf("operation failed - diag=%d\n", diag); 2941 break; 2942 } 2943 return; 2944 } 2945 rss_hf = rss_conf.rss_hf; 2946 if (rss_hf == 0) { 2947 printf("RSS disabled\n"); 2948 return; 2949 } 2950 printf("RSS functions:\n "); 2951 for (i = 0; rss_type_table[i].str; i++) { 2952 if (rss_hf & rss_type_table[i].rss_type) 2953 printf("%s ", rss_type_table[i].str); 2954 } 2955 printf("\n"); 2956 if (!show_rss_key) 2957 return; 2958 printf("RSS key:\n"); 2959 for (i = 0; i < hash_key_size; i++) 2960 printf("%02X", rss_key[i]); 2961 printf("\n"); 2962 } 2963 2964 void 2965 port_rss_hash_key_update(portid_t port_id, char rss_type[], uint8_t *hash_key, 2966 uint hash_key_len) 2967 { 2968 struct rte_eth_rss_conf rss_conf; 2969 int diag; 2970 unsigned int i; 2971 2972 rss_conf.rss_key = NULL; 2973 rss_conf.rss_key_len = hash_key_len; 2974 rss_conf.rss_hf = 0; 2975 for (i = 0; rss_type_table[i].str; i++) { 2976 if (!strcmp(rss_type_table[i].str, rss_type)) 2977 rss_conf.rss_hf = rss_type_table[i].rss_type; 2978 } 2979 diag = rte_eth_dev_rss_hash_conf_get(port_id, &rss_conf); 2980 if (diag == 0) { 2981 rss_conf.rss_key = hash_key; 2982 diag = rte_eth_dev_rss_hash_update(port_id, &rss_conf); 2983 } 2984 if (diag == 0) 2985 return; 2986 2987 switch (diag) { 2988 case -ENODEV: 2989 printf("port index %d invalid\n", port_id); 2990 break; 2991 case -ENOTSUP: 2992 printf("operation not supported by device\n"); 2993 break; 2994 default: 2995 printf("operation failed - diag=%d\n", diag); 2996 break; 2997 } 2998 } 2999 3000 /* 3001 * Setup forwarding configuration for each logical core. 3002 */ 3003 static void 3004 setup_fwd_config_of_each_lcore(struct fwd_config *cfg) 3005 { 3006 streamid_t nb_fs_per_lcore; 3007 streamid_t nb_fs; 3008 streamid_t sm_id; 3009 lcoreid_t nb_extra; 3010 lcoreid_t nb_fc; 3011 lcoreid_t nb_lc; 3012 lcoreid_t lc_id; 3013 3014 nb_fs = cfg->nb_fwd_streams; 3015 nb_fc = cfg->nb_fwd_lcores; 3016 if (nb_fs <= nb_fc) { 3017 nb_fs_per_lcore = 1; 3018 nb_extra = 0; 3019 } else { 3020 nb_fs_per_lcore = (streamid_t) (nb_fs / nb_fc); 3021 nb_extra = (lcoreid_t) (nb_fs % nb_fc); 3022 } 3023 3024 nb_lc = (lcoreid_t) (nb_fc - nb_extra); 3025 sm_id = 0; 3026 for (lc_id = 0; lc_id < nb_lc; lc_id++) { 3027 fwd_lcores[lc_id]->stream_idx = sm_id; 3028 fwd_lcores[lc_id]->stream_nb = nb_fs_per_lcore; 3029 sm_id = (streamid_t) (sm_id + nb_fs_per_lcore); 3030 } 3031 3032 /* 3033 * Assign extra remaining streams, if any. 3034 */ 3035 nb_fs_per_lcore = (streamid_t) (nb_fs_per_lcore + 1); 3036 for (lc_id = 0; lc_id < nb_extra; lc_id++) { 3037 fwd_lcores[nb_lc + lc_id]->stream_idx = sm_id; 3038 fwd_lcores[nb_lc + lc_id]->stream_nb = nb_fs_per_lcore; 3039 sm_id = (streamid_t) (sm_id + nb_fs_per_lcore); 3040 } 3041 } 3042 3043 static portid_t 3044 fwd_topology_tx_port_get(portid_t rxp) 3045 { 3046 static int warning_once = 1; 3047 3048 RTE_ASSERT(rxp < cur_fwd_config.nb_fwd_ports); 3049 3050 switch (port_topology) { 3051 default: 3052 case PORT_TOPOLOGY_PAIRED: 3053 if ((rxp & 0x1) == 0) { 3054 if (rxp + 1 < cur_fwd_config.nb_fwd_ports) 3055 return rxp + 1; 3056 if (warning_once) { 3057 printf("\nWarning! port-topology=paired" 3058 " and odd forward ports number," 3059 " the last port will pair with" 3060 " itself.\n\n"); 3061 warning_once = 0; 3062 } 3063 return rxp; 3064 } 3065 return rxp - 1; 3066 case PORT_TOPOLOGY_CHAINED: 3067 return (rxp + 1) % cur_fwd_config.nb_fwd_ports; 3068 case PORT_TOPOLOGY_LOOP: 3069 return rxp; 3070 } 3071 } 3072 3073 static void 3074 simple_fwd_config_setup(void) 3075 { 3076 portid_t i; 3077 3078 cur_fwd_config.nb_fwd_ports = (portid_t) nb_fwd_ports; 3079 cur_fwd_config.nb_fwd_streams = 3080 (streamid_t) cur_fwd_config.nb_fwd_ports; 3081 3082 /* reinitialize forwarding streams */ 3083 init_fwd_streams(); 3084 3085 /* 3086 * In the simple forwarding test, the number of forwarding cores 3087 * must be lower or equal to the number of forwarding ports. 3088 */ 3089 cur_fwd_config.nb_fwd_lcores = (lcoreid_t) nb_fwd_lcores; 3090 if (cur_fwd_config.nb_fwd_lcores > cur_fwd_config.nb_fwd_ports) 3091 cur_fwd_config.nb_fwd_lcores = 3092 (lcoreid_t) cur_fwd_config.nb_fwd_ports; 3093 setup_fwd_config_of_each_lcore(&cur_fwd_config); 3094 3095 for (i = 0; i < cur_fwd_config.nb_fwd_ports; i++) { 3096 fwd_streams[i]->rx_port = fwd_ports_ids[i]; 3097 fwd_streams[i]->rx_queue = 0; 3098 fwd_streams[i]->tx_port = 3099 fwd_ports_ids[fwd_topology_tx_port_get(i)]; 3100 fwd_streams[i]->tx_queue = 0; 3101 fwd_streams[i]->peer_addr = fwd_streams[i]->tx_port; 3102 fwd_streams[i]->retry_enabled = retry_enabled; 3103 } 3104 } 3105 3106 /** 3107 * For the RSS forwarding test all streams distributed over lcores. Each stream 3108 * being composed of a RX queue to poll on a RX port for input messages, 3109 * associated with a TX queue of a TX port where to send forwarded packets. 3110 */ 3111 static void 3112 rss_fwd_config_setup(void) 3113 { 3114 portid_t rxp; 3115 portid_t txp; 3116 queueid_t rxq; 3117 queueid_t nb_q; 3118 streamid_t sm_id; 3119 3120 nb_q = nb_rxq; 3121 if (nb_q > nb_txq) 3122 nb_q = nb_txq; 3123 cur_fwd_config.nb_fwd_lcores = (lcoreid_t) nb_fwd_lcores; 3124 cur_fwd_config.nb_fwd_ports = nb_fwd_ports; 3125 cur_fwd_config.nb_fwd_streams = 3126 (streamid_t) (nb_q * cur_fwd_config.nb_fwd_ports); 3127 3128 if (cur_fwd_config.nb_fwd_streams < cur_fwd_config.nb_fwd_lcores) 3129 cur_fwd_config.nb_fwd_lcores = 3130 (lcoreid_t)cur_fwd_config.nb_fwd_streams; 3131 3132 /* reinitialize forwarding streams */ 3133 init_fwd_streams(); 3134 3135 setup_fwd_config_of_each_lcore(&cur_fwd_config); 3136 rxp = 0; rxq = 0; 3137 for (sm_id = 0; sm_id < cur_fwd_config.nb_fwd_streams; sm_id++) { 3138 struct fwd_stream *fs; 3139 3140 fs = fwd_streams[sm_id]; 3141 txp = fwd_topology_tx_port_get(rxp); 3142 fs->rx_port = fwd_ports_ids[rxp]; 3143 fs->rx_queue = rxq; 3144 fs->tx_port = fwd_ports_ids[txp]; 3145 fs->tx_queue = rxq; 3146 fs->peer_addr = fs->tx_port; 3147 fs->retry_enabled = retry_enabled; 3148 rxp++; 3149 if (rxp < nb_fwd_ports) 3150 continue; 3151 rxp = 0; 3152 rxq++; 3153 } 3154 } 3155 3156 /** 3157 * For the DCB forwarding test, each core is assigned on each traffic class. 3158 * 3159 * Each core is assigned a multi-stream, each stream being composed of 3160 * a RX queue to poll on a RX port for input messages, associated with 3161 * a TX queue of a TX port where to send forwarded packets. All RX and 3162 * TX queues are mapping to the same traffic class. 3163 * If VMDQ and DCB co-exist, each traffic class on different POOLs share 3164 * the same core 3165 */ 3166 static void 3167 dcb_fwd_config_setup(void) 3168 { 3169 struct rte_eth_dcb_info rxp_dcb_info, txp_dcb_info; 3170 portid_t txp, rxp = 0; 3171 queueid_t txq, rxq = 0; 3172 lcoreid_t lc_id; 3173 uint16_t nb_rx_queue, nb_tx_queue; 3174 uint16_t i, j, k, sm_id = 0; 3175 uint8_t tc = 0; 3176 3177 cur_fwd_config.nb_fwd_lcores = (lcoreid_t) nb_fwd_lcores; 3178 cur_fwd_config.nb_fwd_ports = nb_fwd_ports; 3179 cur_fwd_config.nb_fwd_streams = 3180 (streamid_t) (nb_rxq * cur_fwd_config.nb_fwd_ports); 3181 3182 /* reinitialize forwarding streams */ 3183 init_fwd_streams(); 3184 sm_id = 0; 3185 txp = 1; 3186 /* get the dcb info on the first RX and TX ports */ 3187 (void)rte_eth_dev_get_dcb_info(fwd_ports_ids[rxp], &rxp_dcb_info); 3188 (void)rte_eth_dev_get_dcb_info(fwd_ports_ids[txp], &txp_dcb_info); 3189 3190 for (lc_id = 0; lc_id < cur_fwd_config.nb_fwd_lcores; lc_id++) { 3191 fwd_lcores[lc_id]->stream_nb = 0; 3192 fwd_lcores[lc_id]->stream_idx = sm_id; 3193 for (i = 0; i < ETH_MAX_VMDQ_POOL; i++) { 3194 /* if the nb_queue is zero, means this tc is 3195 * not enabled on the POOL 3196 */ 3197 if (rxp_dcb_info.tc_queue.tc_rxq[i][tc].nb_queue == 0) 3198 break; 3199 k = fwd_lcores[lc_id]->stream_nb + 3200 fwd_lcores[lc_id]->stream_idx; 3201 rxq = rxp_dcb_info.tc_queue.tc_rxq[i][tc].base; 3202 txq = txp_dcb_info.tc_queue.tc_txq[i][tc].base; 3203 nb_rx_queue = txp_dcb_info.tc_queue.tc_rxq[i][tc].nb_queue; 3204 nb_tx_queue = txp_dcb_info.tc_queue.tc_txq[i][tc].nb_queue; 3205 for (j = 0; j < nb_rx_queue; j++) { 3206 struct fwd_stream *fs; 3207 3208 fs = fwd_streams[k + j]; 3209 fs->rx_port = fwd_ports_ids[rxp]; 3210 fs->rx_queue = rxq + j; 3211 fs->tx_port = fwd_ports_ids[txp]; 3212 fs->tx_queue = txq + j % nb_tx_queue; 3213 fs->peer_addr = fs->tx_port; 3214 fs->retry_enabled = retry_enabled; 3215 } 3216 fwd_lcores[lc_id]->stream_nb += 3217 rxp_dcb_info.tc_queue.tc_rxq[i][tc].nb_queue; 3218 } 3219 sm_id = (streamid_t) (sm_id + fwd_lcores[lc_id]->stream_nb); 3220 3221 tc++; 3222 if (tc < rxp_dcb_info.nb_tcs) 3223 continue; 3224 /* Restart from TC 0 on next RX port */ 3225 tc = 0; 3226 if (numa_support && (nb_fwd_ports <= (nb_ports >> 1))) 3227 rxp = (portid_t) 3228 (rxp + ((nb_ports >> 1) / nb_fwd_ports)); 3229 else 3230 rxp++; 3231 if (rxp >= nb_fwd_ports) 3232 return; 3233 /* get the dcb information on next RX and TX ports */ 3234 if ((rxp & 0x1) == 0) 3235 txp = (portid_t) (rxp + 1); 3236 else 3237 txp = (portid_t) (rxp - 1); 3238 rte_eth_dev_get_dcb_info(fwd_ports_ids[rxp], &rxp_dcb_info); 3239 rte_eth_dev_get_dcb_info(fwd_ports_ids[txp], &txp_dcb_info); 3240 } 3241 } 3242 3243 static void 3244 icmp_echo_config_setup(void) 3245 { 3246 portid_t rxp; 3247 queueid_t rxq; 3248 lcoreid_t lc_id; 3249 uint16_t sm_id; 3250 3251 if ((nb_txq * nb_fwd_ports) < nb_fwd_lcores) 3252 cur_fwd_config.nb_fwd_lcores = (lcoreid_t) 3253 (nb_txq * nb_fwd_ports); 3254 else 3255 cur_fwd_config.nb_fwd_lcores = (lcoreid_t) nb_fwd_lcores; 3256 cur_fwd_config.nb_fwd_ports = nb_fwd_ports; 3257 cur_fwd_config.nb_fwd_streams = 3258 (streamid_t) (nb_rxq * cur_fwd_config.nb_fwd_ports); 3259 if (cur_fwd_config.nb_fwd_streams < cur_fwd_config.nb_fwd_lcores) 3260 cur_fwd_config.nb_fwd_lcores = 3261 (lcoreid_t)cur_fwd_config.nb_fwd_streams; 3262 if (verbose_level > 0) { 3263 printf("%s fwd_cores=%d fwd_ports=%d fwd_streams=%d\n", 3264 __FUNCTION__, 3265 cur_fwd_config.nb_fwd_lcores, 3266 cur_fwd_config.nb_fwd_ports, 3267 cur_fwd_config.nb_fwd_streams); 3268 } 3269 3270 /* reinitialize forwarding streams */ 3271 init_fwd_streams(); 3272 setup_fwd_config_of_each_lcore(&cur_fwd_config); 3273 rxp = 0; rxq = 0; 3274 for (lc_id = 0; lc_id < cur_fwd_config.nb_fwd_lcores; lc_id++) { 3275 if (verbose_level > 0) 3276 printf(" core=%d: \n", lc_id); 3277 for (sm_id = 0; sm_id < fwd_lcores[lc_id]->stream_nb; sm_id++) { 3278 struct fwd_stream *fs; 3279 fs = fwd_streams[fwd_lcores[lc_id]->stream_idx + sm_id]; 3280 fs->rx_port = fwd_ports_ids[rxp]; 3281 fs->rx_queue = rxq; 3282 fs->tx_port = fs->rx_port; 3283 fs->tx_queue = rxq; 3284 fs->peer_addr = fs->tx_port; 3285 fs->retry_enabled = retry_enabled; 3286 if (verbose_level > 0) 3287 printf(" stream=%d port=%d rxq=%d txq=%d\n", 3288 sm_id, fs->rx_port, fs->rx_queue, 3289 fs->tx_queue); 3290 rxq = (queueid_t) (rxq + 1); 3291 if (rxq == nb_rxq) { 3292 rxq = 0; 3293 rxp = (portid_t) (rxp + 1); 3294 } 3295 } 3296 } 3297 } 3298 3299 void 3300 fwd_config_setup(void) 3301 { 3302 cur_fwd_config.fwd_eng = cur_fwd_eng; 3303 if (strcmp(cur_fwd_eng->fwd_mode_name, "icmpecho") == 0) { 3304 icmp_echo_config_setup(); 3305 return; 3306 } 3307 3308 if ((nb_rxq > 1) && (nb_txq > 1)){ 3309 if (dcb_config) 3310 dcb_fwd_config_setup(); 3311 else 3312 rss_fwd_config_setup(); 3313 } 3314 else 3315 simple_fwd_config_setup(); 3316 } 3317 3318 static const char * 3319 mp_alloc_to_str(uint8_t mode) 3320 { 3321 switch (mode) { 3322 case MP_ALLOC_NATIVE: 3323 return "native"; 3324 case MP_ALLOC_ANON: 3325 return "anon"; 3326 case MP_ALLOC_XMEM: 3327 return "xmem"; 3328 case MP_ALLOC_XMEM_HUGE: 3329 return "xmemhuge"; 3330 case MP_ALLOC_XBUF: 3331 return "xbuf"; 3332 default: 3333 return "invalid"; 3334 } 3335 } 3336 3337 void 3338 pkt_fwd_config_display(struct fwd_config *cfg) 3339 { 3340 struct fwd_stream *fs; 3341 lcoreid_t lc_id; 3342 streamid_t sm_id; 3343 3344 printf("%s packet forwarding%s - ports=%d - cores=%d - streams=%d - " 3345 "NUMA support %s, MP allocation mode: %s\n", 3346 cfg->fwd_eng->fwd_mode_name, 3347 retry_enabled == 0 ? "" : " with retry", 3348 cfg->nb_fwd_ports, cfg->nb_fwd_lcores, cfg->nb_fwd_streams, 3349 numa_support == 1 ? "enabled" : "disabled", 3350 mp_alloc_to_str(mp_alloc_type)); 3351 3352 if (retry_enabled) 3353 printf("TX retry num: %u, delay between TX retries: %uus\n", 3354 burst_tx_retry_num, burst_tx_delay_time); 3355 for (lc_id = 0; lc_id < cfg->nb_fwd_lcores; lc_id++) { 3356 printf("Logical Core %u (socket %u) forwards packets on " 3357 "%d streams:", 3358 fwd_lcores_cpuids[lc_id], 3359 rte_lcore_to_socket_id(fwd_lcores_cpuids[lc_id]), 3360 fwd_lcores[lc_id]->stream_nb); 3361 for (sm_id = 0; sm_id < fwd_lcores[lc_id]->stream_nb; sm_id++) { 3362 fs = fwd_streams[fwd_lcores[lc_id]->stream_idx + sm_id]; 3363 printf("\n RX P=%d/Q=%d (socket %u) -> TX " 3364 "P=%d/Q=%d (socket %u) ", 3365 fs->rx_port, fs->rx_queue, 3366 ports[fs->rx_port].socket_id, 3367 fs->tx_port, fs->tx_queue, 3368 ports[fs->tx_port].socket_id); 3369 print_ethaddr("peer=", 3370 &peer_eth_addrs[fs->peer_addr]); 3371 } 3372 printf("\n"); 3373 } 3374 printf("\n"); 3375 } 3376 3377 void 3378 set_fwd_eth_peer(portid_t port_id, char *peer_addr) 3379 { 3380 struct rte_ether_addr new_peer_addr; 3381 if (!rte_eth_dev_is_valid_port(port_id)) { 3382 printf("Error: Invalid port number %i\n", port_id); 3383 return; 3384 } 3385 if (rte_ether_unformat_addr(peer_addr, &new_peer_addr) < 0) { 3386 printf("Error: Invalid ethernet address: %s\n", peer_addr); 3387 return; 3388 } 3389 peer_eth_addrs[port_id] = new_peer_addr; 3390 } 3391 3392 int 3393 set_fwd_lcores_list(unsigned int *lcorelist, unsigned int nb_lc) 3394 { 3395 unsigned int i; 3396 unsigned int lcore_cpuid; 3397 int record_now; 3398 3399 record_now = 0; 3400 again: 3401 for (i = 0; i < nb_lc; i++) { 3402 lcore_cpuid = lcorelist[i]; 3403 if (! rte_lcore_is_enabled(lcore_cpuid)) { 3404 printf("lcore %u not enabled\n", lcore_cpuid); 3405 return -1; 3406 } 3407 if (lcore_cpuid == rte_get_main_lcore()) { 3408 printf("lcore %u cannot be masked on for running " 3409 "packet forwarding, which is the main lcore " 3410 "and reserved for command line parsing only\n", 3411 lcore_cpuid); 3412 return -1; 3413 } 3414 if (record_now) 3415 fwd_lcores_cpuids[i] = lcore_cpuid; 3416 } 3417 if (record_now == 0) { 3418 record_now = 1; 3419 goto again; 3420 } 3421 nb_cfg_lcores = (lcoreid_t) nb_lc; 3422 if (nb_fwd_lcores != (lcoreid_t) nb_lc) { 3423 printf("previous number of forwarding cores %u - changed to " 3424 "number of configured cores %u\n", 3425 (unsigned int) nb_fwd_lcores, nb_lc); 3426 nb_fwd_lcores = (lcoreid_t) nb_lc; 3427 } 3428 3429 return 0; 3430 } 3431 3432 int 3433 set_fwd_lcores_mask(uint64_t lcoremask) 3434 { 3435 unsigned int lcorelist[64]; 3436 unsigned int nb_lc; 3437 unsigned int i; 3438 3439 if (lcoremask == 0) { 3440 printf("Invalid NULL mask of cores\n"); 3441 return -1; 3442 } 3443 nb_lc = 0; 3444 for (i = 0; i < 64; i++) { 3445 if (! ((uint64_t)(1ULL << i) & lcoremask)) 3446 continue; 3447 lcorelist[nb_lc++] = i; 3448 } 3449 return set_fwd_lcores_list(lcorelist, nb_lc); 3450 } 3451 3452 void 3453 set_fwd_lcores_number(uint16_t nb_lc) 3454 { 3455 if (test_done == 0) { 3456 printf("Please stop forwarding first\n"); 3457 return; 3458 } 3459 if (nb_lc > nb_cfg_lcores) { 3460 printf("nb fwd cores %u > %u (max. number of configured " 3461 "lcores) - ignored\n", 3462 (unsigned int) nb_lc, (unsigned int) nb_cfg_lcores); 3463 return; 3464 } 3465 nb_fwd_lcores = (lcoreid_t) nb_lc; 3466 printf("Number of forwarding cores set to %u\n", 3467 (unsigned int) nb_fwd_lcores); 3468 } 3469 3470 void 3471 set_fwd_ports_list(unsigned int *portlist, unsigned int nb_pt) 3472 { 3473 unsigned int i; 3474 portid_t port_id; 3475 int record_now; 3476 3477 record_now = 0; 3478 again: 3479 for (i = 0; i < nb_pt; i++) { 3480 port_id = (portid_t) portlist[i]; 3481 if (port_id_is_invalid(port_id, ENABLED_WARN)) 3482 return; 3483 if (record_now) 3484 fwd_ports_ids[i] = port_id; 3485 } 3486 if (record_now == 0) { 3487 record_now = 1; 3488 goto again; 3489 } 3490 nb_cfg_ports = (portid_t) nb_pt; 3491 if (nb_fwd_ports != (portid_t) nb_pt) { 3492 printf("previous number of forwarding ports %u - changed to " 3493 "number of configured ports %u\n", 3494 (unsigned int) nb_fwd_ports, nb_pt); 3495 nb_fwd_ports = (portid_t) nb_pt; 3496 } 3497 } 3498 3499 /** 3500 * Parse the user input and obtain the list of forwarding ports 3501 * 3502 * @param[in] list 3503 * String containing the user input. User can specify 3504 * in these formats 1,3,5 or 1-3 or 1-2,5 or 3,5-6. 3505 * For example, if the user wants to use all the available 3506 * 4 ports in his system, then the input can be 0-3 or 0,1,2,3. 3507 * If the user wants to use only the ports 1,2 then the input 3508 * is 1,2. 3509 * valid characters are '-' and ',' 3510 * @param[out] values 3511 * This array will be filled with a list of port IDs 3512 * based on the user input 3513 * Note that duplicate entries are discarded and only the first 3514 * count entries in this array are port IDs and all the rest 3515 * will contain default values 3516 * @param[in] maxsize 3517 * This parameter denotes 2 things 3518 * 1) Number of elements in the values array 3519 * 2) Maximum value of each element in the values array 3520 * @return 3521 * On success, returns total count of parsed port IDs 3522 * On failure, returns 0 3523 */ 3524 static unsigned int 3525 parse_port_list(const char *list, unsigned int *values, unsigned int maxsize) 3526 { 3527 unsigned int count = 0; 3528 char *end = NULL; 3529 int min, max; 3530 int value, i; 3531 unsigned int marked[maxsize]; 3532 3533 if (list == NULL || values == NULL) 3534 return 0; 3535 3536 for (i = 0; i < (int)maxsize; i++) 3537 marked[i] = 0; 3538 3539 min = INT_MAX; 3540 3541 do { 3542 /*Remove the blank spaces if any*/ 3543 while (isblank(*list)) 3544 list++; 3545 if (*list == '\0') 3546 break; 3547 errno = 0; 3548 value = strtol(list, &end, 10); 3549 if (errno || end == NULL) 3550 return 0; 3551 if (value < 0 || value >= (int)maxsize) 3552 return 0; 3553 while (isblank(*end)) 3554 end++; 3555 if (*end == '-' && min == INT_MAX) { 3556 min = value; 3557 } else if ((*end == ',') || (*end == '\0')) { 3558 max = value; 3559 if (min == INT_MAX) 3560 min = value; 3561 for (i = min; i <= max; i++) { 3562 if (count < maxsize) { 3563 if (marked[i]) 3564 continue; 3565 values[count] = i; 3566 marked[i] = 1; 3567 count++; 3568 } 3569 } 3570 min = INT_MAX; 3571 } else 3572 return 0; 3573 list = end + 1; 3574 } while (*end != '\0'); 3575 3576 return count; 3577 } 3578 3579 void 3580 parse_fwd_portlist(const char *portlist) 3581 { 3582 unsigned int portcount; 3583 unsigned int portindex[RTE_MAX_ETHPORTS]; 3584 unsigned int i, valid_port_count = 0; 3585 3586 portcount = parse_port_list(portlist, portindex, RTE_MAX_ETHPORTS); 3587 if (!portcount) 3588 rte_exit(EXIT_FAILURE, "Invalid fwd port list\n"); 3589 3590 /* 3591 * Here we verify the validity of the ports 3592 * and thereby calculate the total number of 3593 * valid ports 3594 */ 3595 for (i = 0; i < portcount && i < RTE_DIM(portindex); i++) { 3596 if (rte_eth_dev_is_valid_port(portindex[i])) { 3597 portindex[valid_port_count] = portindex[i]; 3598 valid_port_count++; 3599 } 3600 } 3601 3602 set_fwd_ports_list(portindex, valid_port_count); 3603 } 3604 3605 void 3606 set_fwd_ports_mask(uint64_t portmask) 3607 { 3608 unsigned int portlist[64]; 3609 unsigned int nb_pt; 3610 unsigned int i; 3611 3612 if (portmask == 0) { 3613 printf("Invalid NULL mask of ports\n"); 3614 return; 3615 } 3616 nb_pt = 0; 3617 RTE_ETH_FOREACH_DEV(i) { 3618 if (! ((uint64_t)(1ULL << i) & portmask)) 3619 continue; 3620 portlist[nb_pt++] = i; 3621 } 3622 set_fwd_ports_list(portlist, nb_pt); 3623 } 3624 3625 void 3626 set_fwd_ports_number(uint16_t nb_pt) 3627 { 3628 if (nb_pt > nb_cfg_ports) { 3629 printf("nb fwd ports %u > %u (number of configured " 3630 "ports) - ignored\n", 3631 (unsigned int) nb_pt, (unsigned int) nb_cfg_ports); 3632 return; 3633 } 3634 nb_fwd_ports = (portid_t) nb_pt; 3635 printf("Number of forwarding ports set to %u\n", 3636 (unsigned int) nb_fwd_ports); 3637 } 3638 3639 int 3640 port_is_forwarding(portid_t port_id) 3641 { 3642 unsigned int i; 3643 3644 if (port_id_is_invalid(port_id, ENABLED_WARN)) 3645 return -1; 3646 3647 for (i = 0; i < nb_fwd_ports; i++) { 3648 if (fwd_ports_ids[i] == port_id) 3649 return 1; 3650 } 3651 3652 return 0; 3653 } 3654 3655 void 3656 set_nb_pkt_per_burst(uint16_t nb) 3657 { 3658 if (nb > MAX_PKT_BURST) { 3659 printf("nb pkt per burst: %u > %u (maximum packet per burst) " 3660 " ignored\n", 3661 (unsigned int) nb, (unsigned int) MAX_PKT_BURST); 3662 return; 3663 } 3664 nb_pkt_per_burst = nb; 3665 printf("Number of packets per burst set to %u\n", 3666 (unsigned int) nb_pkt_per_burst); 3667 } 3668 3669 static const char * 3670 tx_split_get_name(enum tx_pkt_split split) 3671 { 3672 uint32_t i; 3673 3674 for (i = 0; i != RTE_DIM(tx_split_name); i++) { 3675 if (tx_split_name[i].split == split) 3676 return tx_split_name[i].name; 3677 } 3678 return NULL; 3679 } 3680 3681 void 3682 set_tx_pkt_split(const char *name) 3683 { 3684 uint32_t i; 3685 3686 for (i = 0; i != RTE_DIM(tx_split_name); i++) { 3687 if (strcmp(tx_split_name[i].name, name) == 0) { 3688 tx_pkt_split = tx_split_name[i].split; 3689 return; 3690 } 3691 } 3692 printf("unknown value: \"%s\"\n", name); 3693 } 3694 3695 int 3696 parse_fec_mode(const char *name, uint32_t *mode) 3697 { 3698 uint8_t i; 3699 3700 for (i = 0; i < RTE_DIM(fec_mode_name); i++) { 3701 if (strcmp(fec_mode_name[i].name, name) == 0) { 3702 *mode = RTE_ETH_FEC_MODE_TO_CAPA(fec_mode_name[i].mode); 3703 return 0; 3704 } 3705 } 3706 return -1; 3707 } 3708 3709 void 3710 show_fec_capability(unsigned int num, struct rte_eth_fec_capa *speed_fec_capa) 3711 { 3712 unsigned int i, j; 3713 3714 printf("FEC capabilities:\n"); 3715 3716 for (i = 0; i < num; i++) { 3717 printf("%s : ", 3718 rte_eth_link_speed_to_str(speed_fec_capa[i].speed)); 3719 3720 for (j = 0; j < RTE_DIM(fec_mode_name); j++) { 3721 if (RTE_ETH_FEC_MODE_TO_CAPA(j) & 3722 speed_fec_capa[i].capa) 3723 printf("%s ", fec_mode_name[j].name); 3724 } 3725 printf("\n"); 3726 } 3727 } 3728 3729 void 3730 show_rx_pkt_offsets(void) 3731 { 3732 uint32_t i, n; 3733 3734 n = rx_pkt_nb_offs; 3735 printf("Number of offsets: %u\n", n); 3736 if (n) { 3737 printf("Segment offsets: "); 3738 for (i = 0; i != n - 1; i++) 3739 printf("%hu,", rx_pkt_seg_offsets[i]); 3740 printf("%hu\n", rx_pkt_seg_lengths[i]); 3741 } 3742 } 3743 3744 void 3745 set_rx_pkt_offsets(unsigned int *seg_offsets, unsigned int nb_offs) 3746 { 3747 unsigned int i; 3748 3749 if (nb_offs >= MAX_SEGS_BUFFER_SPLIT) { 3750 printf("nb segments per RX packets=%u >= " 3751 "MAX_SEGS_BUFFER_SPLIT - ignored\n", nb_offs); 3752 return; 3753 } 3754 3755 /* 3756 * No extra check here, the segment length will be checked by PMD 3757 * in the extended queue setup. 3758 */ 3759 for (i = 0; i < nb_offs; i++) { 3760 if (seg_offsets[i] >= UINT16_MAX) { 3761 printf("offset[%u]=%u > UINT16_MAX - give up\n", 3762 i, seg_offsets[i]); 3763 return; 3764 } 3765 } 3766 3767 for (i = 0; i < nb_offs; i++) 3768 rx_pkt_seg_offsets[i] = (uint16_t) seg_offsets[i]; 3769 3770 rx_pkt_nb_offs = (uint8_t) nb_offs; 3771 } 3772 3773 void 3774 show_rx_pkt_segments(void) 3775 { 3776 uint32_t i, n; 3777 3778 n = rx_pkt_nb_segs; 3779 printf("Number of segments: %u\n", n); 3780 if (n) { 3781 printf("Segment sizes: "); 3782 for (i = 0; i != n - 1; i++) 3783 printf("%hu,", rx_pkt_seg_lengths[i]); 3784 printf("%hu\n", rx_pkt_seg_lengths[i]); 3785 } 3786 } 3787 3788 void 3789 set_rx_pkt_segments(unsigned int *seg_lengths, unsigned int nb_segs) 3790 { 3791 unsigned int i; 3792 3793 if (nb_segs >= MAX_SEGS_BUFFER_SPLIT) { 3794 printf("nb segments per RX packets=%u >= " 3795 "MAX_SEGS_BUFFER_SPLIT - ignored\n", nb_segs); 3796 return; 3797 } 3798 3799 /* 3800 * No extra check here, the segment length will be checked by PMD 3801 * in the extended queue setup. 3802 */ 3803 for (i = 0; i < nb_segs; i++) { 3804 if (seg_lengths[i] >= UINT16_MAX) { 3805 printf("length[%u]=%u > UINT16_MAX - give up\n", 3806 i, seg_lengths[i]); 3807 return; 3808 } 3809 } 3810 3811 for (i = 0; i < nb_segs; i++) 3812 rx_pkt_seg_lengths[i] = (uint16_t) seg_lengths[i]; 3813 3814 rx_pkt_nb_segs = (uint8_t) nb_segs; 3815 } 3816 3817 void 3818 show_tx_pkt_segments(void) 3819 { 3820 uint32_t i, n; 3821 const char *split; 3822 3823 n = tx_pkt_nb_segs; 3824 split = tx_split_get_name(tx_pkt_split); 3825 3826 printf("Number of segments: %u\n", n); 3827 printf("Segment sizes: "); 3828 for (i = 0; i != n - 1; i++) 3829 printf("%hu,", tx_pkt_seg_lengths[i]); 3830 printf("%hu\n", tx_pkt_seg_lengths[i]); 3831 printf("Split packet: %s\n", split); 3832 } 3833 3834 static bool 3835 nb_segs_is_invalid(unsigned int nb_segs) 3836 { 3837 uint16_t ring_size; 3838 uint16_t queue_id; 3839 uint16_t port_id; 3840 int ret; 3841 3842 RTE_ETH_FOREACH_DEV(port_id) { 3843 for (queue_id = 0; queue_id < nb_txq; queue_id++) { 3844 ret = get_tx_ring_size(port_id, queue_id, &ring_size); 3845 3846 if (ret) 3847 return true; 3848 3849 if (ring_size < nb_segs) { 3850 printf("nb segments per TX packets=%u >= " 3851 "TX queue(%u) ring_size=%u - ignored\n", 3852 nb_segs, queue_id, ring_size); 3853 return true; 3854 } 3855 } 3856 } 3857 3858 return false; 3859 } 3860 3861 void 3862 set_tx_pkt_segments(unsigned int *seg_lengths, unsigned int nb_segs) 3863 { 3864 uint16_t tx_pkt_len; 3865 unsigned int i; 3866 3867 if (nb_segs_is_invalid(nb_segs)) 3868 return; 3869 3870 /* 3871 * Check that each segment length is greater or equal than 3872 * the mbuf data sise. 3873 * Check also that the total packet length is greater or equal than the 3874 * size of an empty UDP/IP packet (sizeof(struct rte_ether_hdr) + 3875 * 20 + 8). 3876 */ 3877 tx_pkt_len = 0; 3878 for (i = 0; i < nb_segs; i++) { 3879 if (seg_lengths[i] > mbuf_data_size[0]) { 3880 printf("length[%u]=%u > mbuf_data_size=%u - give up\n", 3881 i, seg_lengths[i], mbuf_data_size[0]); 3882 return; 3883 } 3884 tx_pkt_len = (uint16_t)(tx_pkt_len + seg_lengths[i]); 3885 } 3886 if (tx_pkt_len < (sizeof(struct rte_ether_hdr) + 20 + 8)) { 3887 printf("total packet length=%u < %d - give up\n", 3888 (unsigned) tx_pkt_len, 3889 (int)(sizeof(struct rte_ether_hdr) + 20 + 8)); 3890 return; 3891 } 3892 3893 for (i = 0; i < nb_segs; i++) 3894 tx_pkt_seg_lengths[i] = (uint16_t) seg_lengths[i]; 3895 3896 tx_pkt_length = tx_pkt_len; 3897 tx_pkt_nb_segs = (uint8_t) nb_segs; 3898 } 3899 3900 void 3901 show_tx_pkt_times(void) 3902 { 3903 printf("Interburst gap: %u\n", tx_pkt_times_inter); 3904 printf("Intraburst gap: %u\n", tx_pkt_times_intra); 3905 } 3906 3907 void 3908 set_tx_pkt_times(unsigned int *tx_times) 3909 { 3910 tx_pkt_times_inter = tx_times[0]; 3911 tx_pkt_times_intra = tx_times[1]; 3912 } 3913 3914 void 3915 setup_gro(const char *onoff, portid_t port_id) 3916 { 3917 if (!rte_eth_dev_is_valid_port(port_id)) { 3918 printf("invalid port id %u\n", port_id); 3919 return; 3920 } 3921 if (test_done == 0) { 3922 printf("Before enable/disable GRO," 3923 " please stop forwarding first\n"); 3924 return; 3925 } 3926 if (strcmp(onoff, "on") == 0) { 3927 if (gro_ports[port_id].enable != 0) { 3928 printf("Port %u has enabled GRO. Please" 3929 " disable GRO first\n", port_id); 3930 return; 3931 } 3932 if (gro_flush_cycles == GRO_DEFAULT_FLUSH_CYCLES) { 3933 gro_ports[port_id].param.gro_types = RTE_GRO_TCP_IPV4; 3934 gro_ports[port_id].param.max_flow_num = 3935 GRO_DEFAULT_FLOW_NUM; 3936 gro_ports[port_id].param.max_item_per_flow = 3937 GRO_DEFAULT_ITEM_NUM_PER_FLOW; 3938 } 3939 gro_ports[port_id].enable = 1; 3940 } else { 3941 if (gro_ports[port_id].enable == 0) { 3942 printf("Port %u has disabled GRO\n", port_id); 3943 return; 3944 } 3945 gro_ports[port_id].enable = 0; 3946 } 3947 } 3948 3949 void 3950 setup_gro_flush_cycles(uint8_t cycles) 3951 { 3952 if (test_done == 0) { 3953 printf("Before change flush interval for GRO," 3954 " please stop forwarding first.\n"); 3955 return; 3956 } 3957 3958 if (cycles > GRO_MAX_FLUSH_CYCLES || cycles < 3959 GRO_DEFAULT_FLUSH_CYCLES) { 3960 printf("The flushing cycle be in the range" 3961 " of 1 to %u. Revert to the default" 3962 " value %u.\n", 3963 GRO_MAX_FLUSH_CYCLES, 3964 GRO_DEFAULT_FLUSH_CYCLES); 3965 cycles = GRO_DEFAULT_FLUSH_CYCLES; 3966 } 3967 3968 gro_flush_cycles = cycles; 3969 } 3970 3971 void 3972 show_gro(portid_t port_id) 3973 { 3974 struct rte_gro_param *param; 3975 uint32_t max_pkts_num; 3976 3977 param = &gro_ports[port_id].param; 3978 3979 if (!rte_eth_dev_is_valid_port(port_id)) { 3980 printf("Invalid port id %u.\n", port_id); 3981 return; 3982 } 3983 if (gro_ports[port_id].enable) { 3984 printf("GRO type: TCP/IPv4\n"); 3985 if (gro_flush_cycles == GRO_DEFAULT_FLUSH_CYCLES) { 3986 max_pkts_num = param->max_flow_num * 3987 param->max_item_per_flow; 3988 } else 3989 max_pkts_num = MAX_PKT_BURST * GRO_MAX_FLUSH_CYCLES; 3990 printf("Max number of packets to perform GRO: %u\n", 3991 max_pkts_num); 3992 printf("Flushing cycles: %u\n", gro_flush_cycles); 3993 } else 3994 printf("Port %u doesn't enable GRO.\n", port_id); 3995 } 3996 3997 void 3998 setup_gso(const char *mode, portid_t port_id) 3999 { 4000 if (!rte_eth_dev_is_valid_port(port_id)) { 4001 printf("invalid port id %u\n", port_id); 4002 return; 4003 } 4004 if (strcmp(mode, "on") == 0) { 4005 if (test_done == 0) { 4006 printf("before enabling GSO," 4007 " please stop forwarding first\n"); 4008 return; 4009 } 4010 gso_ports[port_id].enable = 1; 4011 } else if (strcmp(mode, "off") == 0) { 4012 if (test_done == 0) { 4013 printf("before disabling GSO," 4014 " please stop forwarding first\n"); 4015 return; 4016 } 4017 gso_ports[port_id].enable = 0; 4018 } 4019 } 4020 4021 char* 4022 list_pkt_forwarding_modes(void) 4023 { 4024 static char fwd_modes[128] = ""; 4025 const char *separator = "|"; 4026 struct fwd_engine *fwd_eng; 4027 unsigned i = 0; 4028 4029 if (strlen (fwd_modes) == 0) { 4030 while ((fwd_eng = fwd_engines[i++]) != NULL) { 4031 strncat(fwd_modes, fwd_eng->fwd_mode_name, 4032 sizeof(fwd_modes) - strlen(fwd_modes) - 1); 4033 strncat(fwd_modes, separator, 4034 sizeof(fwd_modes) - strlen(fwd_modes) - 1); 4035 } 4036 fwd_modes[strlen(fwd_modes) - strlen(separator)] = '\0'; 4037 } 4038 4039 return fwd_modes; 4040 } 4041 4042 char* 4043 list_pkt_forwarding_retry_modes(void) 4044 { 4045 static char fwd_modes[128] = ""; 4046 const char *separator = "|"; 4047 struct fwd_engine *fwd_eng; 4048 unsigned i = 0; 4049 4050 if (strlen(fwd_modes) == 0) { 4051 while ((fwd_eng = fwd_engines[i++]) != NULL) { 4052 if (fwd_eng == &rx_only_engine) 4053 continue; 4054 strncat(fwd_modes, fwd_eng->fwd_mode_name, 4055 sizeof(fwd_modes) - 4056 strlen(fwd_modes) - 1); 4057 strncat(fwd_modes, separator, 4058 sizeof(fwd_modes) - 4059 strlen(fwd_modes) - 1); 4060 } 4061 fwd_modes[strlen(fwd_modes) - strlen(separator)] = '\0'; 4062 } 4063 4064 return fwd_modes; 4065 } 4066 4067 void 4068 set_pkt_forwarding_mode(const char *fwd_mode_name) 4069 { 4070 struct fwd_engine *fwd_eng; 4071 unsigned i; 4072 4073 i = 0; 4074 while ((fwd_eng = fwd_engines[i]) != NULL) { 4075 if (! strcmp(fwd_eng->fwd_mode_name, fwd_mode_name)) { 4076 printf("Set %s packet forwarding mode%s\n", 4077 fwd_mode_name, 4078 retry_enabled == 0 ? "" : " with retry"); 4079 cur_fwd_eng = fwd_eng; 4080 return; 4081 } 4082 i++; 4083 } 4084 printf("Invalid %s packet forwarding mode\n", fwd_mode_name); 4085 } 4086 4087 void 4088 add_rx_dump_callbacks(portid_t portid) 4089 { 4090 struct rte_eth_dev_info dev_info; 4091 uint16_t queue; 4092 int ret; 4093 4094 if (port_id_is_invalid(portid, ENABLED_WARN)) 4095 return; 4096 4097 ret = eth_dev_info_get_print_err(portid, &dev_info); 4098 if (ret != 0) 4099 return; 4100 4101 for (queue = 0; queue < dev_info.nb_rx_queues; queue++) 4102 if (!ports[portid].rx_dump_cb[queue]) 4103 ports[portid].rx_dump_cb[queue] = 4104 rte_eth_add_rx_callback(portid, queue, 4105 dump_rx_pkts, NULL); 4106 } 4107 4108 void 4109 add_tx_dump_callbacks(portid_t portid) 4110 { 4111 struct rte_eth_dev_info dev_info; 4112 uint16_t queue; 4113 int ret; 4114 4115 if (port_id_is_invalid(portid, ENABLED_WARN)) 4116 return; 4117 4118 ret = eth_dev_info_get_print_err(portid, &dev_info); 4119 if (ret != 0) 4120 return; 4121 4122 for (queue = 0; queue < dev_info.nb_tx_queues; queue++) 4123 if (!ports[portid].tx_dump_cb[queue]) 4124 ports[portid].tx_dump_cb[queue] = 4125 rte_eth_add_tx_callback(portid, queue, 4126 dump_tx_pkts, NULL); 4127 } 4128 4129 void 4130 remove_rx_dump_callbacks(portid_t portid) 4131 { 4132 struct rte_eth_dev_info dev_info; 4133 uint16_t queue; 4134 int ret; 4135 4136 if (port_id_is_invalid(portid, ENABLED_WARN)) 4137 return; 4138 4139 ret = eth_dev_info_get_print_err(portid, &dev_info); 4140 if (ret != 0) 4141 return; 4142 4143 for (queue = 0; queue < dev_info.nb_rx_queues; queue++) 4144 if (ports[portid].rx_dump_cb[queue]) { 4145 rte_eth_remove_rx_callback(portid, queue, 4146 ports[portid].rx_dump_cb[queue]); 4147 ports[portid].rx_dump_cb[queue] = NULL; 4148 } 4149 } 4150 4151 void 4152 remove_tx_dump_callbacks(portid_t portid) 4153 { 4154 struct rte_eth_dev_info dev_info; 4155 uint16_t queue; 4156 int ret; 4157 4158 if (port_id_is_invalid(portid, ENABLED_WARN)) 4159 return; 4160 4161 ret = eth_dev_info_get_print_err(portid, &dev_info); 4162 if (ret != 0) 4163 return; 4164 4165 for (queue = 0; queue < dev_info.nb_tx_queues; queue++) 4166 if (ports[portid].tx_dump_cb[queue]) { 4167 rte_eth_remove_tx_callback(portid, queue, 4168 ports[portid].tx_dump_cb[queue]); 4169 ports[portid].tx_dump_cb[queue] = NULL; 4170 } 4171 } 4172 4173 void 4174 configure_rxtx_dump_callbacks(uint16_t verbose) 4175 { 4176 portid_t portid; 4177 4178 #ifndef RTE_ETHDEV_RXTX_CALLBACKS 4179 TESTPMD_LOG(ERR, "setting rxtx callbacks is not enabled\n"); 4180 return; 4181 #endif 4182 4183 RTE_ETH_FOREACH_DEV(portid) 4184 { 4185 if (verbose == 1 || verbose > 2) 4186 add_rx_dump_callbacks(portid); 4187 else 4188 remove_rx_dump_callbacks(portid); 4189 if (verbose >= 2) 4190 add_tx_dump_callbacks(portid); 4191 else 4192 remove_tx_dump_callbacks(portid); 4193 } 4194 } 4195 4196 void 4197 set_verbose_level(uint16_t vb_level) 4198 { 4199 printf("Change verbose level from %u to %u\n", 4200 (unsigned int) verbose_level, (unsigned int) vb_level); 4201 verbose_level = vb_level; 4202 configure_rxtx_dump_callbacks(verbose_level); 4203 } 4204 4205 void 4206 vlan_extend_set(portid_t port_id, int on) 4207 { 4208 int diag; 4209 int vlan_offload; 4210 uint64_t port_rx_offloads = ports[port_id].dev_conf.rxmode.offloads; 4211 4212 if (port_id_is_invalid(port_id, ENABLED_WARN)) 4213 return; 4214 4215 vlan_offload = rte_eth_dev_get_vlan_offload(port_id); 4216 4217 if (on) { 4218 vlan_offload |= ETH_VLAN_EXTEND_OFFLOAD; 4219 port_rx_offloads |= DEV_RX_OFFLOAD_VLAN_EXTEND; 4220 } else { 4221 vlan_offload &= ~ETH_VLAN_EXTEND_OFFLOAD; 4222 port_rx_offloads &= ~DEV_RX_OFFLOAD_VLAN_EXTEND; 4223 } 4224 4225 diag = rte_eth_dev_set_vlan_offload(port_id, vlan_offload); 4226 if (diag < 0) { 4227 printf("rx_vlan_extend_set(port_pi=%d, on=%d) failed " 4228 "diag=%d\n", port_id, on, diag); 4229 return; 4230 } 4231 ports[port_id].dev_conf.rxmode.offloads = port_rx_offloads; 4232 } 4233 4234 void 4235 rx_vlan_strip_set(portid_t port_id, int on) 4236 { 4237 int diag; 4238 int vlan_offload; 4239 uint64_t port_rx_offloads = ports[port_id].dev_conf.rxmode.offloads; 4240 4241 if (port_id_is_invalid(port_id, ENABLED_WARN)) 4242 return; 4243 4244 vlan_offload = rte_eth_dev_get_vlan_offload(port_id); 4245 4246 if (on) { 4247 vlan_offload |= ETH_VLAN_STRIP_OFFLOAD; 4248 port_rx_offloads |= DEV_RX_OFFLOAD_VLAN_STRIP; 4249 } else { 4250 vlan_offload &= ~ETH_VLAN_STRIP_OFFLOAD; 4251 port_rx_offloads &= ~DEV_RX_OFFLOAD_VLAN_STRIP; 4252 } 4253 4254 diag = rte_eth_dev_set_vlan_offload(port_id, vlan_offload); 4255 if (diag < 0) { 4256 printf("rx_vlan_strip_set(port_pi=%d, on=%d) failed " 4257 "diag=%d\n", port_id, on, diag); 4258 return; 4259 } 4260 ports[port_id].dev_conf.rxmode.offloads = port_rx_offloads; 4261 } 4262 4263 void 4264 rx_vlan_strip_set_on_queue(portid_t port_id, uint16_t queue_id, int on) 4265 { 4266 int diag; 4267 4268 if (port_id_is_invalid(port_id, ENABLED_WARN)) 4269 return; 4270 4271 diag = rte_eth_dev_set_vlan_strip_on_queue(port_id, queue_id, on); 4272 if (diag < 0) 4273 printf("rx_vlan_strip_set_on_queue(port_pi=%d, queue_id=%d, on=%d) failed " 4274 "diag=%d\n", port_id, queue_id, on, diag); 4275 } 4276 4277 void 4278 rx_vlan_filter_set(portid_t port_id, int on) 4279 { 4280 int diag; 4281 int vlan_offload; 4282 uint64_t port_rx_offloads = ports[port_id].dev_conf.rxmode.offloads; 4283 4284 if (port_id_is_invalid(port_id, ENABLED_WARN)) 4285 return; 4286 4287 vlan_offload = rte_eth_dev_get_vlan_offload(port_id); 4288 4289 if (on) { 4290 vlan_offload |= ETH_VLAN_FILTER_OFFLOAD; 4291 port_rx_offloads |= DEV_RX_OFFLOAD_VLAN_FILTER; 4292 } else { 4293 vlan_offload &= ~ETH_VLAN_FILTER_OFFLOAD; 4294 port_rx_offloads &= ~DEV_RX_OFFLOAD_VLAN_FILTER; 4295 } 4296 4297 diag = rte_eth_dev_set_vlan_offload(port_id, vlan_offload); 4298 if (diag < 0) { 4299 printf("rx_vlan_filter_set(port_pi=%d, on=%d) failed " 4300 "diag=%d\n", port_id, on, diag); 4301 return; 4302 } 4303 ports[port_id].dev_conf.rxmode.offloads = port_rx_offloads; 4304 } 4305 4306 void 4307 rx_vlan_qinq_strip_set(portid_t port_id, int on) 4308 { 4309 int diag; 4310 int vlan_offload; 4311 uint64_t port_rx_offloads = ports[port_id].dev_conf.rxmode.offloads; 4312 4313 if (port_id_is_invalid(port_id, ENABLED_WARN)) 4314 return; 4315 4316 vlan_offload = rte_eth_dev_get_vlan_offload(port_id); 4317 4318 if (on) { 4319 vlan_offload |= ETH_QINQ_STRIP_OFFLOAD; 4320 port_rx_offloads |= DEV_RX_OFFLOAD_QINQ_STRIP; 4321 } else { 4322 vlan_offload &= ~ETH_QINQ_STRIP_OFFLOAD; 4323 port_rx_offloads &= ~DEV_RX_OFFLOAD_QINQ_STRIP; 4324 } 4325 4326 diag = rte_eth_dev_set_vlan_offload(port_id, vlan_offload); 4327 if (diag < 0) { 4328 printf("%s(port_pi=%d, on=%d) failed " 4329 "diag=%d\n", __func__, port_id, on, diag); 4330 return; 4331 } 4332 ports[port_id].dev_conf.rxmode.offloads = port_rx_offloads; 4333 } 4334 4335 int 4336 rx_vft_set(portid_t port_id, uint16_t vlan_id, int on) 4337 { 4338 int diag; 4339 4340 if (port_id_is_invalid(port_id, ENABLED_WARN)) 4341 return 1; 4342 if (vlan_id_is_invalid(vlan_id)) 4343 return 1; 4344 diag = rte_eth_dev_vlan_filter(port_id, vlan_id, on); 4345 if (diag == 0) 4346 return 0; 4347 printf("rte_eth_dev_vlan_filter(port_pi=%d, vlan_id=%d, on=%d) failed " 4348 "diag=%d\n", 4349 port_id, vlan_id, on, diag); 4350 return -1; 4351 } 4352 4353 void 4354 rx_vlan_all_filter_set(portid_t port_id, int on) 4355 { 4356 uint16_t vlan_id; 4357 4358 if (port_id_is_invalid(port_id, ENABLED_WARN)) 4359 return; 4360 for (vlan_id = 0; vlan_id < 4096; vlan_id++) { 4361 if (rx_vft_set(port_id, vlan_id, on)) 4362 break; 4363 } 4364 } 4365 4366 void 4367 vlan_tpid_set(portid_t port_id, enum rte_vlan_type vlan_type, uint16_t tp_id) 4368 { 4369 int diag; 4370 4371 if (port_id_is_invalid(port_id, ENABLED_WARN)) 4372 return; 4373 4374 diag = rte_eth_dev_set_vlan_ether_type(port_id, vlan_type, tp_id); 4375 if (diag == 0) 4376 return; 4377 4378 printf("tx_vlan_tpid_set(port_pi=%d, vlan_type=%d, tpid=%d) failed " 4379 "diag=%d\n", 4380 port_id, vlan_type, tp_id, diag); 4381 } 4382 4383 void 4384 tx_vlan_set(portid_t port_id, uint16_t vlan_id) 4385 { 4386 struct rte_eth_dev_info dev_info; 4387 int ret; 4388 4389 if (vlan_id_is_invalid(vlan_id)) 4390 return; 4391 4392 if (ports[port_id].dev_conf.txmode.offloads & 4393 DEV_TX_OFFLOAD_QINQ_INSERT) { 4394 printf("Error, as QinQ has been enabled.\n"); 4395 return; 4396 } 4397 4398 ret = eth_dev_info_get_print_err(port_id, &dev_info); 4399 if (ret != 0) 4400 return; 4401 4402 if ((dev_info.tx_offload_capa & DEV_TX_OFFLOAD_VLAN_INSERT) == 0) { 4403 printf("Error: vlan insert is not supported by port %d\n", 4404 port_id); 4405 return; 4406 } 4407 4408 tx_vlan_reset(port_id); 4409 ports[port_id].dev_conf.txmode.offloads |= DEV_TX_OFFLOAD_VLAN_INSERT; 4410 ports[port_id].tx_vlan_id = vlan_id; 4411 } 4412 4413 void 4414 tx_qinq_set(portid_t port_id, uint16_t vlan_id, uint16_t vlan_id_outer) 4415 { 4416 struct rte_eth_dev_info dev_info; 4417 int ret; 4418 4419 if (vlan_id_is_invalid(vlan_id)) 4420 return; 4421 if (vlan_id_is_invalid(vlan_id_outer)) 4422 return; 4423 4424 ret = eth_dev_info_get_print_err(port_id, &dev_info); 4425 if (ret != 0) 4426 return; 4427 4428 if ((dev_info.tx_offload_capa & DEV_TX_OFFLOAD_QINQ_INSERT) == 0) { 4429 printf("Error: qinq insert not supported by port %d\n", 4430 port_id); 4431 return; 4432 } 4433 4434 tx_vlan_reset(port_id); 4435 ports[port_id].dev_conf.txmode.offloads |= (DEV_TX_OFFLOAD_VLAN_INSERT | 4436 DEV_TX_OFFLOAD_QINQ_INSERT); 4437 ports[port_id].tx_vlan_id = vlan_id; 4438 ports[port_id].tx_vlan_id_outer = vlan_id_outer; 4439 } 4440 4441 void 4442 tx_vlan_reset(portid_t port_id) 4443 { 4444 ports[port_id].dev_conf.txmode.offloads &= 4445 ~(DEV_TX_OFFLOAD_VLAN_INSERT | 4446 DEV_TX_OFFLOAD_QINQ_INSERT); 4447 ports[port_id].tx_vlan_id = 0; 4448 ports[port_id].tx_vlan_id_outer = 0; 4449 } 4450 4451 void 4452 tx_vlan_pvid_set(portid_t port_id, uint16_t vlan_id, int on) 4453 { 4454 if (port_id_is_invalid(port_id, ENABLED_WARN)) 4455 return; 4456 4457 rte_eth_dev_set_vlan_pvid(port_id, vlan_id, on); 4458 } 4459 4460 void 4461 set_qmap(portid_t port_id, uint8_t is_rx, uint16_t queue_id, uint8_t map_value) 4462 { 4463 int ret; 4464 4465 if (port_id_is_invalid(port_id, ENABLED_WARN)) 4466 return; 4467 4468 if (is_rx ? (rx_queue_id_is_invalid(queue_id)) : (tx_queue_id_is_invalid(queue_id))) 4469 return; 4470 4471 if (map_value >= RTE_ETHDEV_QUEUE_STAT_CNTRS) { 4472 printf("map_value not in required range 0..%d\n", 4473 RTE_ETHDEV_QUEUE_STAT_CNTRS - 1); 4474 return; 4475 } 4476 4477 if (!is_rx) { /* tx */ 4478 ret = rte_eth_dev_set_tx_queue_stats_mapping(port_id, queue_id, 4479 map_value); 4480 if (ret) { 4481 printf("failed to set tx queue stats mapping.\n"); 4482 return; 4483 } 4484 } else { /* rx */ 4485 ret = rte_eth_dev_set_rx_queue_stats_mapping(port_id, queue_id, 4486 map_value); 4487 if (ret) { 4488 printf("failed to set rx queue stats mapping.\n"); 4489 return; 4490 } 4491 } 4492 } 4493 4494 void 4495 set_xstats_hide_zero(uint8_t on_off) 4496 { 4497 xstats_hide_zero = on_off; 4498 } 4499 4500 void 4501 set_record_core_cycles(uint8_t on_off) 4502 { 4503 record_core_cycles = on_off; 4504 } 4505 4506 void 4507 set_record_burst_stats(uint8_t on_off) 4508 { 4509 record_burst_stats = on_off; 4510 } 4511 4512 static inline void 4513 print_fdir_mask(struct rte_eth_fdir_masks *mask) 4514 { 4515 printf("\n vlan_tci: 0x%04x", rte_be_to_cpu_16(mask->vlan_tci_mask)); 4516 4517 if (fdir_conf.mode == RTE_FDIR_MODE_PERFECT_TUNNEL) 4518 printf(", mac_addr: 0x%02x, tunnel_type: 0x%01x," 4519 " tunnel_id: 0x%08x", 4520 mask->mac_addr_byte_mask, mask->tunnel_type_mask, 4521 rte_be_to_cpu_32(mask->tunnel_id_mask)); 4522 else if (fdir_conf.mode != RTE_FDIR_MODE_PERFECT_MAC_VLAN) { 4523 printf(", src_ipv4: 0x%08x, dst_ipv4: 0x%08x", 4524 rte_be_to_cpu_32(mask->ipv4_mask.src_ip), 4525 rte_be_to_cpu_32(mask->ipv4_mask.dst_ip)); 4526 4527 printf("\n src_port: 0x%04x, dst_port: 0x%04x", 4528 rte_be_to_cpu_16(mask->src_port_mask), 4529 rte_be_to_cpu_16(mask->dst_port_mask)); 4530 4531 printf("\n src_ipv6: 0x%08x,0x%08x,0x%08x,0x%08x", 4532 rte_be_to_cpu_32(mask->ipv6_mask.src_ip[0]), 4533 rte_be_to_cpu_32(mask->ipv6_mask.src_ip[1]), 4534 rte_be_to_cpu_32(mask->ipv6_mask.src_ip[2]), 4535 rte_be_to_cpu_32(mask->ipv6_mask.src_ip[3])); 4536 4537 printf("\n dst_ipv6: 0x%08x,0x%08x,0x%08x,0x%08x", 4538 rte_be_to_cpu_32(mask->ipv6_mask.dst_ip[0]), 4539 rte_be_to_cpu_32(mask->ipv6_mask.dst_ip[1]), 4540 rte_be_to_cpu_32(mask->ipv6_mask.dst_ip[2]), 4541 rte_be_to_cpu_32(mask->ipv6_mask.dst_ip[3])); 4542 } 4543 4544 printf("\n"); 4545 } 4546 4547 static inline void 4548 print_fdir_flex_payload(struct rte_eth_fdir_flex_conf *flex_conf, uint32_t num) 4549 { 4550 struct rte_eth_flex_payload_cfg *cfg; 4551 uint32_t i, j; 4552 4553 for (i = 0; i < flex_conf->nb_payloads; i++) { 4554 cfg = &flex_conf->flex_set[i]; 4555 if (cfg->type == RTE_ETH_RAW_PAYLOAD) 4556 printf("\n RAW: "); 4557 else if (cfg->type == RTE_ETH_L2_PAYLOAD) 4558 printf("\n L2_PAYLOAD: "); 4559 else if (cfg->type == RTE_ETH_L3_PAYLOAD) 4560 printf("\n L3_PAYLOAD: "); 4561 else if (cfg->type == RTE_ETH_L4_PAYLOAD) 4562 printf("\n L4_PAYLOAD: "); 4563 else 4564 printf("\n UNKNOWN PAYLOAD(%u): ", cfg->type); 4565 for (j = 0; j < num; j++) 4566 printf(" %-5u", cfg->src_offset[j]); 4567 } 4568 printf("\n"); 4569 } 4570 4571 static char * 4572 flowtype_to_str(uint16_t flow_type) 4573 { 4574 struct flow_type_info { 4575 char str[32]; 4576 uint16_t ftype; 4577 }; 4578 4579 uint8_t i; 4580 static struct flow_type_info flowtype_str_table[] = { 4581 {"raw", RTE_ETH_FLOW_RAW}, 4582 {"ipv4", RTE_ETH_FLOW_IPV4}, 4583 {"ipv4-frag", RTE_ETH_FLOW_FRAG_IPV4}, 4584 {"ipv4-tcp", RTE_ETH_FLOW_NONFRAG_IPV4_TCP}, 4585 {"ipv4-udp", RTE_ETH_FLOW_NONFRAG_IPV4_UDP}, 4586 {"ipv4-sctp", RTE_ETH_FLOW_NONFRAG_IPV4_SCTP}, 4587 {"ipv4-other", RTE_ETH_FLOW_NONFRAG_IPV4_OTHER}, 4588 {"ipv6", RTE_ETH_FLOW_IPV6}, 4589 {"ipv6-frag", RTE_ETH_FLOW_FRAG_IPV6}, 4590 {"ipv6-tcp", RTE_ETH_FLOW_NONFRAG_IPV6_TCP}, 4591 {"ipv6-udp", RTE_ETH_FLOW_NONFRAG_IPV6_UDP}, 4592 {"ipv6-sctp", RTE_ETH_FLOW_NONFRAG_IPV6_SCTP}, 4593 {"ipv6-other", RTE_ETH_FLOW_NONFRAG_IPV6_OTHER}, 4594 {"l2_payload", RTE_ETH_FLOW_L2_PAYLOAD}, 4595 {"port", RTE_ETH_FLOW_PORT}, 4596 {"vxlan", RTE_ETH_FLOW_VXLAN}, 4597 {"geneve", RTE_ETH_FLOW_GENEVE}, 4598 {"nvgre", RTE_ETH_FLOW_NVGRE}, 4599 {"vxlan-gpe", RTE_ETH_FLOW_VXLAN_GPE}, 4600 }; 4601 4602 for (i = 0; i < RTE_DIM(flowtype_str_table); i++) { 4603 if (flowtype_str_table[i].ftype == flow_type) 4604 return flowtype_str_table[i].str; 4605 } 4606 4607 return NULL; 4608 } 4609 4610 #if defined(RTE_NET_I40E) || defined(RTE_NET_IXGBE) 4611 4612 static inline void 4613 print_fdir_flex_mask(struct rte_eth_fdir_flex_conf *flex_conf, uint32_t num) 4614 { 4615 struct rte_eth_fdir_flex_mask *mask; 4616 uint32_t i, j; 4617 char *p; 4618 4619 for (i = 0; i < flex_conf->nb_flexmasks; i++) { 4620 mask = &flex_conf->flex_mask[i]; 4621 p = flowtype_to_str(mask->flow_type); 4622 printf("\n %s:\t", p ? p : "unknown"); 4623 for (j = 0; j < num; j++) 4624 printf(" %02x", mask->mask[j]); 4625 } 4626 printf("\n"); 4627 } 4628 4629 static inline void 4630 print_fdir_flow_type(uint32_t flow_types_mask) 4631 { 4632 int i; 4633 char *p; 4634 4635 for (i = RTE_ETH_FLOW_UNKNOWN; i < RTE_ETH_FLOW_MAX; i++) { 4636 if (!(flow_types_mask & (1 << i))) 4637 continue; 4638 p = flowtype_to_str(i); 4639 if (p) 4640 printf(" %s", p); 4641 else 4642 printf(" unknown"); 4643 } 4644 printf("\n"); 4645 } 4646 4647 static int 4648 get_fdir_info(portid_t port_id, struct rte_eth_fdir_info *fdir_info, 4649 struct rte_eth_fdir_stats *fdir_stat) 4650 { 4651 int ret = -ENOTSUP; 4652 4653 #ifdef RTE_NET_I40E 4654 if (ret == -ENOTSUP) { 4655 ret = rte_pmd_i40e_get_fdir_info(port_id, fdir_info); 4656 if (!ret) 4657 ret = rte_pmd_i40e_get_fdir_stats(port_id, fdir_stat); 4658 } 4659 #endif 4660 #ifdef RTE_NET_IXGBE 4661 if (ret == -ENOTSUP) { 4662 ret = rte_pmd_ixgbe_get_fdir_info(port_id, fdir_info); 4663 if (!ret) 4664 ret = rte_pmd_ixgbe_get_fdir_stats(port_id, fdir_stat); 4665 } 4666 #endif 4667 switch (ret) { 4668 case 0: 4669 break; 4670 case -ENOTSUP: 4671 printf("\n FDIR is not supported on port %-2d\n", 4672 port_id); 4673 break; 4674 default: 4675 printf("programming error: (%s)\n", strerror(-ret)); 4676 break; 4677 } 4678 return ret; 4679 } 4680 4681 void 4682 fdir_get_infos(portid_t port_id) 4683 { 4684 struct rte_eth_fdir_stats fdir_stat; 4685 struct rte_eth_fdir_info fdir_info; 4686 4687 static const char *fdir_stats_border = "########################"; 4688 4689 if (port_id_is_invalid(port_id, ENABLED_WARN)) 4690 return; 4691 4692 memset(&fdir_info, 0, sizeof(fdir_info)); 4693 memset(&fdir_stat, 0, sizeof(fdir_stat)); 4694 if (get_fdir_info(port_id, &fdir_info, &fdir_stat)) 4695 return; 4696 4697 printf("\n %s FDIR infos for port %-2d %s\n", 4698 fdir_stats_border, port_id, fdir_stats_border); 4699 printf(" MODE: "); 4700 if (fdir_info.mode == RTE_FDIR_MODE_PERFECT) 4701 printf(" PERFECT\n"); 4702 else if (fdir_info.mode == RTE_FDIR_MODE_PERFECT_MAC_VLAN) 4703 printf(" PERFECT-MAC-VLAN\n"); 4704 else if (fdir_info.mode == RTE_FDIR_MODE_PERFECT_TUNNEL) 4705 printf(" PERFECT-TUNNEL\n"); 4706 else if (fdir_info.mode == RTE_FDIR_MODE_SIGNATURE) 4707 printf(" SIGNATURE\n"); 4708 else 4709 printf(" DISABLE\n"); 4710 if (fdir_info.mode != RTE_FDIR_MODE_PERFECT_MAC_VLAN 4711 && fdir_info.mode != RTE_FDIR_MODE_PERFECT_TUNNEL) { 4712 printf(" SUPPORTED FLOW TYPE: "); 4713 print_fdir_flow_type(fdir_info.flow_types_mask[0]); 4714 } 4715 printf(" FLEX PAYLOAD INFO:\n"); 4716 printf(" max_len: %-10"PRIu32" payload_limit: %-10"PRIu32"\n" 4717 " payload_unit: %-10"PRIu32" payload_seg: %-10"PRIu32"\n" 4718 " bitmask_unit: %-10"PRIu32" bitmask_num: %-10"PRIu32"\n", 4719 fdir_info.max_flexpayload, fdir_info.flex_payload_limit, 4720 fdir_info.flex_payload_unit, 4721 fdir_info.max_flex_payload_segment_num, 4722 fdir_info.flex_bitmask_unit, fdir_info.max_flex_bitmask_num); 4723 printf(" MASK: "); 4724 print_fdir_mask(&fdir_info.mask); 4725 if (fdir_info.flex_conf.nb_payloads > 0) { 4726 printf(" FLEX PAYLOAD SRC OFFSET:"); 4727 print_fdir_flex_payload(&fdir_info.flex_conf, fdir_info.max_flexpayload); 4728 } 4729 if (fdir_info.flex_conf.nb_flexmasks > 0) { 4730 printf(" FLEX MASK CFG:"); 4731 print_fdir_flex_mask(&fdir_info.flex_conf, fdir_info.max_flexpayload); 4732 } 4733 printf(" guarant_count: %-10"PRIu32" best_count: %"PRIu32"\n", 4734 fdir_stat.guarant_cnt, fdir_stat.best_cnt); 4735 printf(" guarant_space: %-10"PRIu32" best_space: %"PRIu32"\n", 4736 fdir_info.guarant_spc, fdir_info.best_spc); 4737 printf(" collision: %-10"PRIu32" free: %"PRIu32"\n" 4738 " maxhash: %-10"PRIu32" maxlen: %"PRIu32"\n" 4739 " add: %-10"PRIu64" remove: %"PRIu64"\n" 4740 " f_add: %-10"PRIu64" f_remove: %"PRIu64"\n", 4741 fdir_stat.collision, fdir_stat.free, 4742 fdir_stat.maxhash, fdir_stat.maxlen, 4743 fdir_stat.add, fdir_stat.remove, 4744 fdir_stat.f_add, fdir_stat.f_remove); 4745 printf(" %s############################%s\n", 4746 fdir_stats_border, fdir_stats_border); 4747 } 4748 4749 #endif /* RTE_NET_I40E || RTE_NET_IXGBE */ 4750 4751 void 4752 fdir_set_flex_mask(portid_t port_id, struct rte_eth_fdir_flex_mask *cfg) 4753 { 4754 struct rte_port *port; 4755 struct rte_eth_fdir_flex_conf *flex_conf; 4756 int i, idx = 0; 4757 4758 port = &ports[port_id]; 4759 flex_conf = &port->dev_conf.fdir_conf.flex_conf; 4760 for (i = 0; i < RTE_ETH_FLOW_MAX; i++) { 4761 if (cfg->flow_type == flex_conf->flex_mask[i].flow_type) { 4762 idx = i; 4763 break; 4764 } 4765 } 4766 if (i >= RTE_ETH_FLOW_MAX) { 4767 if (flex_conf->nb_flexmasks < RTE_DIM(flex_conf->flex_mask)) { 4768 idx = flex_conf->nb_flexmasks; 4769 flex_conf->nb_flexmasks++; 4770 } else { 4771 printf("The flex mask table is full. Can not set flex" 4772 " mask for flow_type(%u).", cfg->flow_type); 4773 return; 4774 } 4775 } 4776 rte_memcpy(&flex_conf->flex_mask[idx], 4777 cfg, 4778 sizeof(struct rte_eth_fdir_flex_mask)); 4779 } 4780 4781 void 4782 fdir_set_flex_payload(portid_t port_id, struct rte_eth_flex_payload_cfg *cfg) 4783 { 4784 struct rte_port *port; 4785 struct rte_eth_fdir_flex_conf *flex_conf; 4786 int i, idx = 0; 4787 4788 port = &ports[port_id]; 4789 flex_conf = &port->dev_conf.fdir_conf.flex_conf; 4790 for (i = 0; i < RTE_ETH_PAYLOAD_MAX; i++) { 4791 if (cfg->type == flex_conf->flex_set[i].type) { 4792 idx = i; 4793 break; 4794 } 4795 } 4796 if (i >= RTE_ETH_PAYLOAD_MAX) { 4797 if (flex_conf->nb_payloads < RTE_DIM(flex_conf->flex_set)) { 4798 idx = flex_conf->nb_payloads; 4799 flex_conf->nb_payloads++; 4800 } else { 4801 printf("The flex payload table is full. Can not set" 4802 " flex payload for type(%u).", cfg->type); 4803 return; 4804 } 4805 } 4806 rte_memcpy(&flex_conf->flex_set[idx], 4807 cfg, 4808 sizeof(struct rte_eth_flex_payload_cfg)); 4809 4810 } 4811 4812 void 4813 set_vf_traffic(portid_t port_id, uint8_t is_rx, uint16_t vf, uint8_t on) 4814 { 4815 #ifdef RTE_NET_IXGBE 4816 int diag; 4817 4818 if (is_rx) 4819 diag = rte_pmd_ixgbe_set_vf_rx(port_id, vf, on); 4820 else 4821 diag = rte_pmd_ixgbe_set_vf_tx(port_id, vf, on); 4822 4823 if (diag == 0) 4824 return; 4825 printf("rte_pmd_ixgbe_set_vf_%s for port_id=%d failed diag=%d\n", 4826 is_rx ? "rx" : "tx", port_id, diag); 4827 return; 4828 #endif 4829 printf("VF %s setting not supported for port %d\n", 4830 is_rx ? "Rx" : "Tx", port_id); 4831 RTE_SET_USED(vf); 4832 RTE_SET_USED(on); 4833 } 4834 4835 int 4836 set_queue_rate_limit(portid_t port_id, uint16_t queue_idx, uint16_t rate) 4837 { 4838 int diag; 4839 struct rte_eth_link link; 4840 int ret; 4841 4842 if (port_id_is_invalid(port_id, ENABLED_WARN)) 4843 return 1; 4844 ret = eth_link_get_nowait_print_err(port_id, &link); 4845 if (ret < 0) 4846 return 1; 4847 if (link.link_speed != ETH_SPEED_NUM_UNKNOWN && 4848 rate > link.link_speed) { 4849 printf("Invalid rate value:%u bigger than link speed: %u\n", 4850 rate, link.link_speed); 4851 return 1; 4852 } 4853 diag = rte_eth_set_queue_rate_limit(port_id, queue_idx, rate); 4854 if (diag == 0) 4855 return diag; 4856 printf("rte_eth_set_queue_rate_limit for port_id=%d failed diag=%d\n", 4857 port_id, diag); 4858 return diag; 4859 } 4860 4861 int 4862 set_vf_rate_limit(portid_t port_id, uint16_t vf, uint16_t rate, uint64_t q_msk) 4863 { 4864 int diag = -ENOTSUP; 4865 4866 RTE_SET_USED(vf); 4867 RTE_SET_USED(rate); 4868 RTE_SET_USED(q_msk); 4869 4870 #ifdef RTE_NET_IXGBE 4871 if (diag == -ENOTSUP) 4872 diag = rte_pmd_ixgbe_set_vf_rate_limit(port_id, vf, rate, 4873 q_msk); 4874 #endif 4875 #ifdef RTE_NET_BNXT 4876 if (diag == -ENOTSUP) 4877 diag = rte_pmd_bnxt_set_vf_rate_limit(port_id, vf, rate, q_msk); 4878 #endif 4879 if (diag == 0) 4880 return diag; 4881 4882 printf("set_vf_rate_limit for port_id=%d failed diag=%d\n", 4883 port_id, diag); 4884 return diag; 4885 } 4886 4887 /* 4888 * Functions to manage the set of filtered Multicast MAC addresses. 4889 * 4890 * A pool of filtered multicast MAC addresses is associated with each port. 4891 * The pool is allocated in chunks of MCAST_POOL_INC multicast addresses. 4892 * The address of the pool and the number of valid multicast MAC addresses 4893 * recorded in the pool are stored in the fields "mc_addr_pool" and 4894 * "mc_addr_nb" of the "rte_port" data structure. 4895 * 4896 * The function "rte_eth_dev_set_mc_addr_list" of the PMDs API imposes 4897 * to be supplied a contiguous array of multicast MAC addresses. 4898 * To comply with this constraint, the set of multicast addresses recorded 4899 * into the pool are systematically compacted at the beginning of the pool. 4900 * Hence, when a multicast address is removed from the pool, all following 4901 * addresses, if any, are copied back to keep the set contiguous. 4902 */ 4903 #define MCAST_POOL_INC 32 4904 4905 static int 4906 mcast_addr_pool_extend(struct rte_port *port) 4907 { 4908 struct rte_ether_addr *mc_pool; 4909 size_t mc_pool_size; 4910 4911 /* 4912 * If a free entry is available at the end of the pool, just 4913 * increment the number of recorded multicast addresses. 4914 */ 4915 if ((port->mc_addr_nb % MCAST_POOL_INC) != 0) { 4916 port->mc_addr_nb++; 4917 return 0; 4918 } 4919 4920 /* 4921 * [re]allocate a pool with MCAST_POOL_INC more entries. 4922 * The previous test guarantees that port->mc_addr_nb is a multiple 4923 * of MCAST_POOL_INC. 4924 */ 4925 mc_pool_size = sizeof(struct rte_ether_addr) * (port->mc_addr_nb + 4926 MCAST_POOL_INC); 4927 mc_pool = (struct rte_ether_addr *) realloc(port->mc_addr_pool, 4928 mc_pool_size); 4929 if (mc_pool == NULL) { 4930 printf("allocation of pool of %u multicast addresses failed\n", 4931 port->mc_addr_nb + MCAST_POOL_INC); 4932 return -ENOMEM; 4933 } 4934 4935 port->mc_addr_pool = mc_pool; 4936 port->mc_addr_nb++; 4937 return 0; 4938 4939 } 4940 4941 static void 4942 mcast_addr_pool_append(struct rte_port *port, struct rte_ether_addr *mc_addr) 4943 { 4944 if (mcast_addr_pool_extend(port) != 0) 4945 return; 4946 rte_ether_addr_copy(mc_addr, &port->mc_addr_pool[port->mc_addr_nb - 1]); 4947 } 4948 4949 static void 4950 mcast_addr_pool_remove(struct rte_port *port, uint32_t addr_idx) 4951 { 4952 port->mc_addr_nb--; 4953 if (addr_idx == port->mc_addr_nb) { 4954 /* No need to recompact the set of multicast addressses. */ 4955 if (port->mc_addr_nb == 0) { 4956 /* free the pool of multicast addresses. */ 4957 free(port->mc_addr_pool); 4958 port->mc_addr_pool = NULL; 4959 } 4960 return; 4961 } 4962 memmove(&port->mc_addr_pool[addr_idx], 4963 &port->mc_addr_pool[addr_idx + 1], 4964 sizeof(struct rte_ether_addr) * (port->mc_addr_nb - addr_idx)); 4965 } 4966 4967 static int 4968 eth_port_multicast_addr_list_set(portid_t port_id) 4969 { 4970 struct rte_port *port; 4971 int diag; 4972 4973 port = &ports[port_id]; 4974 diag = rte_eth_dev_set_mc_addr_list(port_id, port->mc_addr_pool, 4975 port->mc_addr_nb); 4976 if (diag < 0) 4977 printf("rte_eth_dev_set_mc_addr_list(port=%d, nb=%u) failed. diag=%d\n", 4978 port_id, port->mc_addr_nb, diag); 4979 4980 return diag; 4981 } 4982 4983 void 4984 mcast_addr_add(portid_t port_id, struct rte_ether_addr *mc_addr) 4985 { 4986 struct rte_port *port; 4987 uint32_t i; 4988 4989 if (port_id_is_invalid(port_id, ENABLED_WARN)) 4990 return; 4991 4992 port = &ports[port_id]; 4993 4994 /* 4995 * Check that the added multicast MAC address is not already recorded 4996 * in the pool of multicast addresses. 4997 */ 4998 for (i = 0; i < port->mc_addr_nb; i++) { 4999 if (rte_is_same_ether_addr(mc_addr, &port->mc_addr_pool[i])) { 5000 printf("multicast address already filtered by port\n"); 5001 return; 5002 } 5003 } 5004 5005 mcast_addr_pool_append(port, mc_addr); 5006 if (eth_port_multicast_addr_list_set(port_id) < 0) 5007 /* Rollback on failure, remove the address from the pool */ 5008 mcast_addr_pool_remove(port, i); 5009 } 5010 5011 void 5012 mcast_addr_remove(portid_t port_id, struct rte_ether_addr *mc_addr) 5013 { 5014 struct rte_port *port; 5015 uint32_t i; 5016 5017 if (port_id_is_invalid(port_id, ENABLED_WARN)) 5018 return; 5019 5020 port = &ports[port_id]; 5021 5022 /* 5023 * Search the pool of multicast MAC addresses for the removed address. 5024 */ 5025 for (i = 0; i < port->mc_addr_nb; i++) { 5026 if (rte_is_same_ether_addr(mc_addr, &port->mc_addr_pool[i])) 5027 break; 5028 } 5029 if (i == port->mc_addr_nb) { 5030 printf("multicast address not filtered by port %d\n", port_id); 5031 return; 5032 } 5033 5034 mcast_addr_pool_remove(port, i); 5035 if (eth_port_multicast_addr_list_set(port_id) < 0) 5036 /* Rollback on failure, add the address back into the pool */ 5037 mcast_addr_pool_append(port, mc_addr); 5038 } 5039 5040 void 5041 port_dcb_info_display(portid_t port_id) 5042 { 5043 struct rte_eth_dcb_info dcb_info; 5044 uint16_t i; 5045 int ret; 5046 static const char *border = "================"; 5047 5048 if (port_id_is_invalid(port_id, ENABLED_WARN)) 5049 return; 5050 5051 ret = rte_eth_dev_get_dcb_info(port_id, &dcb_info); 5052 if (ret) { 5053 printf("\n Failed to get dcb infos on port %-2d\n", 5054 port_id); 5055 return; 5056 } 5057 printf("\n %s DCB infos for port %-2d %s\n", border, port_id, border); 5058 printf(" TC NUMBER: %d\n", dcb_info.nb_tcs); 5059 printf("\n TC : "); 5060 for (i = 0; i < dcb_info.nb_tcs; i++) 5061 printf("\t%4d", i); 5062 printf("\n Priority : "); 5063 for (i = 0; i < dcb_info.nb_tcs; i++) 5064 printf("\t%4d", dcb_info.prio_tc[i]); 5065 printf("\n BW percent :"); 5066 for (i = 0; i < dcb_info.nb_tcs; i++) 5067 printf("\t%4d%%", dcb_info.tc_bws[i]); 5068 printf("\n RXQ base : "); 5069 for (i = 0; i < dcb_info.nb_tcs; i++) 5070 printf("\t%4d", dcb_info.tc_queue.tc_rxq[0][i].base); 5071 printf("\n RXQ number :"); 5072 for (i = 0; i < dcb_info.nb_tcs; i++) 5073 printf("\t%4d", dcb_info.tc_queue.tc_rxq[0][i].nb_queue); 5074 printf("\n TXQ base : "); 5075 for (i = 0; i < dcb_info.nb_tcs; i++) 5076 printf("\t%4d", dcb_info.tc_queue.tc_txq[0][i].base); 5077 printf("\n TXQ number :"); 5078 for (i = 0; i < dcb_info.nb_tcs; i++) 5079 printf("\t%4d", dcb_info.tc_queue.tc_txq[0][i].nb_queue); 5080 printf("\n"); 5081 } 5082 5083 uint8_t * 5084 open_file(const char *file_path, uint32_t *size) 5085 { 5086 int fd = open(file_path, O_RDONLY); 5087 off_t pkg_size; 5088 uint8_t *buf = NULL; 5089 int ret = 0; 5090 struct stat st_buf; 5091 5092 if (size) 5093 *size = 0; 5094 5095 if (fd == -1) { 5096 printf("%s: Failed to open %s\n", __func__, file_path); 5097 return buf; 5098 } 5099 5100 if ((fstat(fd, &st_buf) != 0) || (!S_ISREG(st_buf.st_mode))) { 5101 close(fd); 5102 printf("%s: File operations failed\n", __func__); 5103 return buf; 5104 } 5105 5106 pkg_size = st_buf.st_size; 5107 if (pkg_size < 0) { 5108 close(fd); 5109 printf("%s: File operations failed\n", __func__); 5110 return buf; 5111 } 5112 5113 buf = (uint8_t *)malloc(pkg_size); 5114 if (!buf) { 5115 close(fd); 5116 printf("%s: Failed to malloc memory\n", __func__); 5117 return buf; 5118 } 5119 5120 ret = read(fd, buf, pkg_size); 5121 if (ret < 0) { 5122 close(fd); 5123 printf("%s: File read operation failed\n", __func__); 5124 close_file(buf); 5125 return NULL; 5126 } 5127 5128 if (size) 5129 *size = pkg_size; 5130 5131 close(fd); 5132 5133 return buf; 5134 } 5135 5136 int 5137 save_file(const char *file_path, uint8_t *buf, uint32_t size) 5138 { 5139 FILE *fh = fopen(file_path, "wb"); 5140 5141 if (fh == NULL) { 5142 printf("%s: Failed to open %s\n", __func__, file_path); 5143 return -1; 5144 } 5145 5146 if (fwrite(buf, 1, size, fh) != size) { 5147 fclose(fh); 5148 printf("%s: File write operation failed\n", __func__); 5149 return -1; 5150 } 5151 5152 fclose(fh); 5153 5154 return 0; 5155 } 5156 5157 int 5158 close_file(uint8_t *buf) 5159 { 5160 if (buf) { 5161 free((void *)buf); 5162 return 0; 5163 } 5164 5165 return -1; 5166 } 5167 5168 void 5169 port_queue_region_info_display(portid_t port_id, void *buf) 5170 { 5171 #ifdef RTE_NET_I40E 5172 uint16_t i, j; 5173 struct rte_pmd_i40e_queue_regions *info = 5174 (struct rte_pmd_i40e_queue_regions *)buf; 5175 static const char *queue_region_info_stats_border = "-------"; 5176 5177 if (!info->queue_region_number) 5178 printf("there is no region has been set before"); 5179 5180 printf("\n %s All queue region info for port=%2d %s", 5181 queue_region_info_stats_border, port_id, 5182 queue_region_info_stats_border); 5183 printf("\n queue_region_number: %-14u \n", 5184 info->queue_region_number); 5185 5186 for (i = 0; i < info->queue_region_number; i++) { 5187 printf("\n region_id: %-14u queue_number: %-14u " 5188 "queue_start_index: %-14u \n", 5189 info->region[i].region_id, 5190 info->region[i].queue_num, 5191 info->region[i].queue_start_index); 5192 5193 printf(" user_priority_num is %-14u :", 5194 info->region[i].user_priority_num); 5195 for (j = 0; j < info->region[i].user_priority_num; j++) 5196 printf(" %-14u ", info->region[i].user_priority[j]); 5197 5198 printf("\n flowtype_num is %-14u :", 5199 info->region[i].flowtype_num); 5200 for (j = 0; j < info->region[i].flowtype_num; j++) 5201 printf(" %-14u ", info->region[i].hw_flowtype[j]); 5202 } 5203 #else 5204 RTE_SET_USED(port_id); 5205 RTE_SET_USED(buf); 5206 #endif 5207 5208 printf("\n\n"); 5209 } 5210 5211 void 5212 show_macs(portid_t port_id) 5213 { 5214 char buf[RTE_ETHER_ADDR_FMT_SIZE]; 5215 struct rte_eth_dev_info dev_info; 5216 struct rte_ether_addr *addr; 5217 uint32_t i, num_macs = 0; 5218 struct rte_eth_dev *dev; 5219 5220 dev = &rte_eth_devices[port_id]; 5221 5222 rte_eth_dev_info_get(port_id, &dev_info); 5223 5224 for (i = 0; i < dev_info.max_mac_addrs; i++) { 5225 addr = &dev->data->mac_addrs[i]; 5226 5227 /* skip zero address */ 5228 if (rte_is_zero_ether_addr(addr)) 5229 continue; 5230 5231 num_macs++; 5232 } 5233 5234 printf("Number of MAC address added: %d\n", num_macs); 5235 5236 for (i = 0; i < dev_info.max_mac_addrs; i++) { 5237 addr = &dev->data->mac_addrs[i]; 5238 5239 /* skip zero address */ 5240 if (rte_is_zero_ether_addr(addr)) 5241 continue; 5242 5243 rte_ether_format_addr(buf, RTE_ETHER_ADDR_FMT_SIZE, addr); 5244 printf(" %s\n", buf); 5245 } 5246 } 5247 5248 void 5249 show_mcast_macs(portid_t port_id) 5250 { 5251 char buf[RTE_ETHER_ADDR_FMT_SIZE]; 5252 struct rte_ether_addr *addr; 5253 struct rte_port *port; 5254 uint32_t i; 5255 5256 port = &ports[port_id]; 5257 5258 printf("Number of Multicast MAC address added: %d\n", port->mc_addr_nb); 5259 5260 for (i = 0; i < port->mc_addr_nb; i++) { 5261 addr = &port->mc_addr_pool[i]; 5262 5263 rte_ether_format_addr(buf, RTE_ETHER_ADDR_FMT_SIZE, addr); 5264 printf(" %s\n", buf); 5265 } 5266 } 5267