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