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