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