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