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