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