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