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