1 /*- 2 * BSD LICENSE 3 * 4 * Copyright(c) 2010-2016 Intel Corporation. All rights reserved. 5 * All rights reserved. 6 * 7 * Redistribution and use in source and binary forms, with or without 8 * modification, are permitted provided that the following conditions 9 * are met: 10 * 11 * * Redistributions of source code must retain the above copyright 12 * notice, this list of conditions and the following disclaimer. 13 * * Redistributions in binary form must reproduce the above copyright 14 * notice, this list of conditions and the following disclaimer in 15 * the documentation and/or other materials provided with the 16 * distribution. 17 * * Neither the name of Intel Corporation nor the names of its 18 * contributors may be used to endorse or promote products derived 19 * from this software without specific prior written permission. 20 * 21 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 22 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 23 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR 24 * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 25 * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 26 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 27 * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 28 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 29 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 30 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 31 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 32 */ 33 /* BSD LICENSE 34 * 35 * Copyright 2013-2014 6WIND S.A. 36 * 37 * Redistribution and use in source and binary forms, with or without 38 * modification, are permitted provided that the following conditions 39 * are met: 40 * 41 * * Redistributions of source code must retain the above copyright 42 * notice, this list of conditions and the following disclaimer. 43 * * Redistributions in binary form must reproduce the above copyright 44 * notice, this list of conditions and the following disclaimer in 45 * the documentation and/or other materials provided with the 46 * distribution. 47 * * Neither the name of 6WIND S.A. nor the names of its 48 * contributors may be used to endorse or promote products derived 49 * from this software without specific prior written permission. 50 * 51 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 52 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 53 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR 54 * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 55 * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 56 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 57 * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 58 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 59 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 60 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 61 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 62 */ 63 64 #include <stdarg.h> 65 #include <errno.h> 66 #include <stdio.h> 67 #include <string.h> 68 #include <stdarg.h> 69 #include <stdint.h> 70 #include <inttypes.h> 71 72 #include <sys/queue.h> 73 74 #include <rte_common.h> 75 #include <rte_byteorder.h> 76 #include <rte_debug.h> 77 #include <rte_log.h> 78 #include <rte_memory.h> 79 #include <rte_memcpy.h> 80 #include <rte_memzone.h> 81 #include <rte_launch.h> 82 #include <rte_eal.h> 83 #include <rte_per_lcore.h> 84 #include <rte_lcore.h> 85 #include <rte_atomic.h> 86 #include <rte_branch_prediction.h> 87 #include <rte_ring.h> 88 #include <rte_mempool.h> 89 #include <rte_mbuf.h> 90 #include <rte_interrupts.h> 91 #include <rte_pci.h> 92 #include <rte_ether.h> 93 #include <rte_ethdev.h> 94 #include <rte_string_fns.h> 95 #include <rte_cycles.h> 96 97 #include "testpmd.h" 98 99 static char *flowtype_to_str(uint16_t flow_type); 100 101 static const struct { 102 enum tx_pkt_split split; 103 const char *name; 104 } tx_split_name[] = { 105 { 106 .split = TX_PKT_SPLIT_OFF, 107 .name = "off", 108 }, 109 { 110 .split = TX_PKT_SPLIT_ON, 111 .name = "on", 112 }, 113 { 114 .split = TX_PKT_SPLIT_RND, 115 .name = "rand", 116 }, 117 }; 118 119 struct rss_type_info { 120 char str[32]; 121 uint64_t rss_type; 122 }; 123 124 static const struct rss_type_info rss_type_table[] = { 125 { "ipv4", ETH_RSS_IPV4 }, 126 { "ipv4-frag", ETH_RSS_FRAG_IPV4 }, 127 { "ipv4-tcp", ETH_RSS_NONFRAG_IPV4_TCP }, 128 { "ipv4-udp", ETH_RSS_NONFRAG_IPV4_UDP }, 129 { "ipv4-sctp", ETH_RSS_NONFRAG_IPV4_SCTP }, 130 { "ipv4-other", ETH_RSS_NONFRAG_IPV4_OTHER }, 131 { "ipv6", ETH_RSS_IPV6 }, 132 { "ipv6-frag", ETH_RSS_FRAG_IPV6 }, 133 { "ipv6-tcp", ETH_RSS_NONFRAG_IPV6_TCP }, 134 { "ipv6-udp", ETH_RSS_NONFRAG_IPV6_UDP }, 135 { "ipv6-sctp", ETH_RSS_NONFRAG_IPV6_SCTP }, 136 { "ipv6-other", ETH_RSS_NONFRAG_IPV6_OTHER }, 137 { "l2-payload", ETH_RSS_L2_PAYLOAD }, 138 { "ipv6-ex", ETH_RSS_IPV6_EX }, 139 { "ipv6-tcp-ex", ETH_RSS_IPV6_TCP_EX }, 140 { "ipv6-udp-ex", ETH_RSS_IPV6_UDP_EX }, 141 { "port", ETH_RSS_PORT }, 142 { "vxlan", ETH_RSS_VXLAN }, 143 { "geneve", ETH_RSS_GENEVE }, 144 { "nvgre", ETH_RSS_NVGRE }, 145 146 }; 147 148 static void 149 print_ethaddr(const char *name, struct ether_addr *eth_addr) 150 { 151 char buf[ETHER_ADDR_FMT_SIZE]; 152 ether_format_addr(buf, ETHER_ADDR_FMT_SIZE, eth_addr); 153 printf("%s%s", name, buf); 154 } 155 156 void 157 nic_stats_display(portid_t port_id) 158 { 159 static uint64_t prev_pkts_rx[RTE_MAX_ETHPORTS]; 160 static uint64_t prev_pkts_tx[RTE_MAX_ETHPORTS]; 161 static uint64_t prev_cycles[RTE_MAX_ETHPORTS]; 162 uint64_t diff_pkts_rx, diff_pkts_tx, diff_cycles; 163 uint64_t mpps_rx, mpps_tx; 164 struct rte_eth_stats stats; 165 struct rte_port *port = &ports[port_id]; 166 uint8_t i; 167 portid_t pid; 168 169 static const char *nic_stats_border = "########################"; 170 171 if (port_id_is_invalid(port_id, ENABLED_WARN)) { 172 printf("Valid port range is [0"); 173 FOREACH_PORT(pid, ports) 174 printf(", %d", pid); 175 printf("]\n"); 176 return; 177 } 178 rte_eth_stats_get(port_id, &stats); 179 printf("\n %s NIC statistics for port %-2d %s\n", 180 nic_stats_border, port_id, nic_stats_border); 181 182 if ((!port->rx_queue_stats_mapping_enabled) && (!port->tx_queue_stats_mapping_enabled)) { 183 printf(" RX-packets: %-10"PRIu64" RX-missed: %-10"PRIu64" RX-bytes: " 184 "%-"PRIu64"\n", 185 stats.ipackets, stats.imissed, stats.ibytes); 186 printf(" RX-errors: %-"PRIu64"\n", stats.ierrors); 187 printf(" RX-nombuf: %-10"PRIu64"\n", 188 stats.rx_nombuf); 189 printf(" TX-packets: %-10"PRIu64" TX-errors: %-10"PRIu64" TX-bytes: " 190 "%-"PRIu64"\n", 191 stats.opackets, stats.oerrors, stats.obytes); 192 } 193 else { 194 printf(" RX-packets: %10"PRIu64" RX-errors: %10"PRIu64 195 " RX-bytes: %10"PRIu64"\n", 196 stats.ipackets, stats.ierrors, stats.ibytes); 197 printf(" RX-errors: %10"PRIu64"\n", stats.ierrors); 198 printf(" RX-nombuf: %10"PRIu64"\n", 199 stats.rx_nombuf); 200 printf(" TX-packets: %10"PRIu64" TX-errors: %10"PRIu64 201 " TX-bytes: %10"PRIu64"\n", 202 stats.opackets, stats.oerrors, stats.obytes); 203 } 204 205 if (port->rx_queue_stats_mapping_enabled) { 206 printf("\n"); 207 for (i = 0; i < RTE_ETHDEV_QUEUE_STAT_CNTRS; i++) { 208 printf(" Stats reg %2d RX-packets: %10"PRIu64 209 " RX-errors: %10"PRIu64 210 " RX-bytes: %10"PRIu64"\n", 211 i, stats.q_ipackets[i], stats.q_errors[i], stats.q_ibytes[i]); 212 } 213 } 214 if (port->tx_queue_stats_mapping_enabled) { 215 printf("\n"); 216 for (i = 0; i < RTE_ETHDEV_QUEUE_STAT_CNTRS; i++) { 217 printf(" Stats reg %2d TX-packets: %10"PRIu64 218 " TX-bytes: %10"PRIu64"\n", 219 i, stats.q_opackets[i], stats.q_obytes[i]); 220 } 221 } 222 223 diff_cycles = prev_cycles[port_id]; 224 prev_cycles[port_id] = rte_rdtsc(); 225 if (diff_cycles > 0) 226 diff_cycles = prev_cycles[port_id] - diff_cycles; 227 228 diff_pkts_rx = stats.ipackets - prev_pkts_rx[port_id]; 229 diff_pkts_tx = stats.opackets - prev_pkts_tx[port_id]; 230 prev_pkts_rx[port_id] = stats.ipackets; 231 prev_pkts_tx[port_id] = stats.opackets; 232 mpps_rx = diff_cycles > 0 ? 233 diff_pkts_rx * rte_get_tsc_hz() / diff_cycles : 0; 234 mpps_tx = diff_cycles > 0 ? 235 diff_pkts_tx * rte_get_tsc_hz() / diff_cycles : 0; 236 printf("\n Throughput (since last show)\n"); 237 printf(" Rx-pps: %12"PRIu64"\n Tx-pps: %12"PRIu64"\n", 238 mpps_rx, mpps_tx); 239 240 printf(" %s############################%s\n", 241 nic_stats_border, nic_stats_border); 242 } 243 244 void 245 nic_stats_clear(portid_t port_id) 246 { 247 portid_t pid; 248 249 if (port_id_is_invalid(port_id, ENABLED_WARN)) { 250 printf("Valid port range is [0"); 251 FOREACH_PORT(pid, ports) 252 printf(", %d", pid); 253 printf("]\n"); 254 return; 255 } 256 rte_eth_stats_reset(port_id); 257 printf("\n NIC statistics for port %d cleared\n", port_id); 258 } 259 260 void 261 nic_xstats_display(portid_t port_id) 262 { 263 struct rte_eth_xstat *xstats; 264 int cnt_xstats, idx_xstat; 265 struct rte_eth_xstat_name *xstats_names; 266 267 printf("###### NIC extended statistics for port %-2d\n", port_id); 268 if (!rte_eth_dev_is_valid_port(port_id)) { 269 printf("Error: Invalid port number %i\n", port_id); 270 return; 271 } 272 273 /* Get count */ 274 cnt_xstats = rte_eth_xstats_get_names(port_id, NULL, 0); 275 if (cnt_xstats < 0) { 276 printf("Error: Cannot get count of xstats\n"); 277 return; 278 } 279 280 /* Get id-name lookup table */ 281 xstats_names = malloc(sizeof(struct rte_eth_xstat_name) * cnt_xstats); 282 if (xstats_names == NULL) { 283 printf("Cannot allocate memory for xstats lookup\n"); 284 return; 285 } 286 if (cnt_xstats != rte_eth_xstats_get_names( 287 port_id, xstats_names, cnt_xstats)) { 288 printf("Error: Cannot get xstats lookup\n"); 289 free(xstats_names); 290 return; 291 } 292 293 /* Get stats themselves */ 294 xstats = malloc(sizeof(struct rte_eth_xstat) * cnt_xstats); 295 if (xstats == NULL) { 296 printf("Cannot allocate memory for xstats\n"); 297 free(xstats_names); 298 return; 299 } 300 if (cnt_xstats != rte_eth_xstats_get(port_id, xstats, cnt_xstats)) { 301 printf("Error: Unable to get xstats\n"); 302 free(xstats_names); 303 free(xstats); 304 return; 305 } 306 307 /* Display xstats */ 308 for (idx_xstat = 0; idx_xstat < cnt_xstats; idx_xstat++) 309 printf("%s: %"PRIu64"\n", 310 xstats_names[idx_xstat].name, 311 xstats[idx_xstat].value); 312 free(xstats_names); 313 free(xstats); 314 } 315 316 void 317 nic_xstats_clear(portid_t port_id) 318 { 319 rte_eth_xstats_reset(port_id); 320 } 321 322 void 323 nic_stats_mapping_display(portid_t port_id) 324 { 325 struct rte_port *port = &ports[port_id]; 326 uint16_t i; 327 portid_t pid; 328 329 static const char *nic_stats_mapping_border = "########################"; 330 331 if (port_id_is_invalid(port_id, ENABLED_WARN)) { 332 printf("Valid port range is [0"); 333 FOREACH_PORT(pid, ports) 334 printf(", %d", pid); 335 printf("]\n"); 336 return; 337 } 338 339 if ((!port->rx_queue_stats_mapping_enabled) && (!port->tx_queue_stats_mapping_enabled)) { 340 printf("Port id %d - either does not support queue statistic mapping or" 341 " no queue statistic mapping set\n", port_id); 342 return; 343 } 344 345 printf("\n %s NIC statistics mapping for port %-2d %s\n", 346 nic_stats_mapping_border, port_id, nic_stats_mapping_border); 347 348 if (port->rx_queue_stats_mapping_enabled) { 349 for (i = 0; i < nb_rx_queue_stats_mappings; i++) { 350 if (rx_queue_stats_mappings[i].port_id == port_id) { 351 printf(" RX-queue %2d mapped to Stats Reg %2d\n", 352 rx_queue_stats_mappings[i].queue_id, 353 rx_queue_stats_mappings[i].stats_counter_id); 354 } 355 } 356 printf("\n"); 357 } 358 359 360 if (port->tx_queue_stats_mapping_enabled) { 361 for (i = 0; i < nb_tx_queue_stats_mappings; i++) { 362 if (tx_queue_stats_mappings[i].port_id == port_id) { 363 printf(" TX-queue %2d mapped to Stats Reg %2d\n", 364 tx_queue_stats_mappings[i].queue_id, 365 tx_queue_stats_mappings[i].stats_counter_id); 366 } 367 } 368 } 369 370 printf(" %s####################################%s\n", 371 nic_stats_mapping_border, nic_stats_mapping_border); 372 } 373 374 void 375 rx_queue_infos_display(portid_t port_id, uint16_t queue_id) 376 { 377 struct rte_eth_rxq_info qinfo; 378 int32_t rc; 379 static const char *info_border = "*********************"; 380 381 rc = rte_eth_rx_queue_info_get(port_id, queue_id, &qinfo); 382 if (rc != 0) { 383 printf("Failed to retrieve information for port: %hhu, " 384 "RX queue: %hu\nerror desc: %s(%d)\n", 385 port_id, queue_id, strerror(-rc), rc); 386 return; 387 } 388 389 printf("\n%s Infos for port %-2u, RX queue %-2u %s", 390 info_border, port_id, queue_id, info_border); 391 392 printf("\nMempool: %s", (qinfo.mp == NULL) ? "NULL" : qinfo.mp->name); 393 printf("\nRX prefetch threshold: %hhu", qinfo.conf.rx_thresh.pthresh); 394 printf("\nRX host threshold: %hhu", qinfo.conf.rx_thresh.hthresh); 395 printf("\nRX writeback threshold: %hhu", qinfo.conf.rx_thresh.wthresh); 396 printf("\nRX free threshold: %hu", qinfo.conf.rx_free_thresh); 397 printf("\nRX drop packets: %s", 398 (qinfo.conf.rx_drop_en != 0) ? "on" : "off"); 399 printf("\nRX deferred start: %s", 400 (qinfo.conf.rx_deferred_start != 0) ? "on" : "off"); 401 printf("\nRX scattered packets: %s", 402 (qinfo.scattered_rx != 0) ? "on" : "off"); 403 printf("\nNumber of RXDs: %hu", qinfo.nb_desc); 404 printf("\n"); 405 } 406 407 void 408 tx_queue_infos_display(portid_t port_id, uint16_t queue_id) 409 { 410 struct rte_eth_txq_info qinfo; 411 int32_t rc; 412 static const char *info_border = "*********************"; 413 414 rc = rte_eth_tx_queue_info_get(port_id, queue_id, &qinfo); 415 if (rc != 0) { 416 printf("Failed to retrieve information for port: %hhu, " 417 "TX queue: %hu\nerror desc: %s(%d)\n", 418 port_id, queue_id, strerror(-rc), rc); 419 return; 420 } 421 422 printf("\n%s Infos for port %-2u, TX queue %-2u %s", 423 info_border, port_id, queue_id, info_border); 424 425 printf("\nTX prefetch threshold: %hhu", qinfo.conf.tx_thresh.pthresh); 426 printf("\nTX host threshold: %hhu", qinfo.conf.tx_thresh.hthresh); 427 printf("\nTX writeback threshold: %hhu", qinfo.conf.tx_thresh.wthresh); 428 printf("\nTX RS threshold: %hu", qinfo.conf.tx_rs_thresh); 429 printf("\nTX free threshold: %hu", qinfo.conf.tx_free_thresh); 430 printf("\nTX flags: %#x", qinfo.conf.txq_flags); 431 printf("\nTX deferred start: %s", 432 (qinfo.conf.tx_deferred_start != 0) ? "on" : "off"); 433 printf("\nNumber of TXDs: %hu", qinfo.nb_desc); 434 printf("\n"); 435 } 436 437 void 438 port_infos_display(portid_t port_id) 439 { 440 struct rte_port *port; 441 struct ether_addr mac_addr; 442 struct rte_eth_link link; 443 struct rte_eth_dev_info dev_info; 444 int vlan_offload; 445 struct rte_mempool * mp; 446 static const char *info_border = "*********************"; 447 portid_t pid; 448 449 if (port_id_is_invalid(port_id, ENABLED_WARN)) { 450 printf("Valid port range is [0"); 451 FOREACH_PORT(pid, ports) 452 printf(", %d", pid); 453 printf("]\n"); 454 return; 455 } 456 port = &ports[port_id]; 457 rte_eth_link_get_nowait(port_id, &link); 458 printf("\n%s Infos for port %-2d %s\n", 459 info_border, port_id, info_border); 460 rte_eth_macaddr_get(port_id, &mac_addr); 461 print_ethaddr("MAC address: ", &mac_addr); 462 printf("\nConnect to socket: %u", port->socket_id); 463 464 if (port_numa[port_id] != NUMA_NO_CONFIG) { 465 mp = mbuf_pool_find(port_numa[port_id]); 466 if (mp) 467 printf("\nmemory allocation on the socket: %d", 468 port_numa[port_id]); 469 } else 470 printf("\nmemory allocation on the socket: %u",port->socket_id); 471 472 printf("\nLink status: %s\n", (link.link_status) ? ("up") : ("down")); 473 printf("Link speed: %u Mbps\n", (unsigned) link.link_speed); 474 printf("Link duplex: %s\n", (link.link_duplex == ETH_LINK_FULL_DUPLEX) ? 475 ("full-duplex") : ("half-duplex")); 476 printf("Promiscuous mode: %s\n", 477 rte_eth_promiscuous_get(port_id) ? "enabled" : "disabled"); 478 printf("Allmulticast mode: %s\n", 479 rte_eth_allmulticast_get(port_id) ? "enabled" : "disabled"); 480 printf("Maximum number of MAC addresses: %u\n", 481 (unsigned int)(port->dev_info.max_mac_addrs)); 482 printf("Maximum number of MAC addresses of hash filtering: %u\n", 483 (unsigned int)(port->dev_info.max_hash_mac_addrs)); 484 485 vlan_offload = rte_eth_dev_get_vlan_offload(port_id); 486 if (vlan_offload >= 0){ 487 printf("VLAN offload: \n"); 488 if (vlan_offload & ETH_VLAN_STRIP_OFFLOAD) 489 printf(" strip on \n"); 490 else 491 printf(" strip off \n"); 492 493 if (vlan_offload & ETH_VLAN_FILTER_OFFLOAD) 494 printf(" filter on \n"); 495 else 496 printf(" filter off \n"); 497 498 if (vlan_offload & ETH_VLAN_EXTEND_OFFLOAD) 499 printf(" qinq(extend) on \n"); 500 else 501 printf(" qinq(extend) off \n"); 502 } 503 504 memset(&dev_info, 0, sizeof(dev_info)); 505 rte_eth_dev_info_get(port_id, &dev_info); 506 if (dev_info.hash_key_size > 0) 507 printf("Hash key size in bytes: %u\n", dev_info.hash_key_size); 508 if (dev_info.reta_size > 0) 509 printf("Redirection table size: %u\n", dev_info.reta_size); 510 if (!dev_info.flow_type_rss_offloads) 511 printf("No flow type is supported.\n"); 512 else { 513 uint16_t i; 514 char *p; 515 516 printf("Supported flow types:\n"); 517 for (i = RTE_ETH_FLOW_UNKNOWN + 1; i < RTE_ETH_FLOW_MAX; 518 i++) { 519 if (!(dev_info.flow_type_rss_offloads & (1ULL << i))) 520 continue; 521 p = flowtype_to_str(i); 522 printf(" %s\n", (p ? p : "unknown")); 523 } 524 } 525 526 printf("Max possible RX queues: %u\n", dev_info.max_rx_queues); 527 printf("Max possible number of RXDs per queue: %hu\n", 528 dev_info.rx_desc_lim.nb_max); 529 printf("Min possible number of RXDs per queue: %hu\n", 530 dev_info.rx_desc_lim.nb_min); 531 printf("RXDs number alignment: %hu\n", dev_info.rx_desc_lim.nb_align); 532 533 printf("Max possible TX queues: %u\n", dev_info.max_tx_queues); 534 printf("Max possible number of TXDs per queue: %hu\n", 535 dev_info.tx_desc_lim.nb_max); 536 printf("Min possible number of TXDs per queue: %hu\n", 537 dev_info.tx_desc_lim.nb_min); 538 printf("TXDs number alignment: %hu\n", dev_info.tx_desc_lim.nb_align); 539 } 540 541 int 542 port_id_is_invalid(portid_t port_id, enum print_warning warning) 543 { 544 if (port_id == (portid_t)RTE_PORT_ALL) 545 return 0; 546 547 if (port_id < RTE_MAX_ETHPORTS && ports[port_id].enabled) 548 return 0; 549 550 if (warning == ENABLED_WARN) 551 printf("Invalid port %d\n", port_id); 552 553 return 1; 554 } 555 556 static int 557 vlan_id_is_invalid(uint16_t vlan_id) 558 { 559 if (vlan_id < 4096) 560 return 0; 561 printf("Invalid vlan_id %d (must be < 4096)\n", vlan_id); 562 return 1; 563 } 564 565 static int 566 port_reg_off_is_invalid(portid_t port_id, uint32_t reg_off) 567 { 568 uint64_t pci_len; 569 570 if (reg_off & 0x3) { 571 printf("Port register offset 0x%X not aligned on a 4-byte " 572 "boundary\n", 573 (unsigned)reg_off); 574 return 1; 575 } 576 pci_len = ports[port_id].dev_info.pci_dev->mem_resource[0].len; 577 if (reg_off >= pci_len) { 578 printf("Port %d: register offset %u (0x%X) out of port PCI " 579 "resource (length=%"PRIu64")\n", 580 port_id, (unsigned)reg_off, (unsigned)reg_off, pci_len); 581 return 1; 582 } 583 return 0; 584 } 585 586 static int 587 reg_bit_pos_is_invalid(uint8_t bit_pos) 588 { 589 if (bit_pos <= 31) 590 return 0; 591 printf("Invalid bit position %d (must be <= 31)\n", bit_pos); 592 return 1; 593 } 594 595 #define display_port_and_reg_off(port_id, reg_off) \ 596 printf("port %d PCI register at offset 0x%X: ", (port_id), (reg_off)) 597 598 static inline void 599 display_port_reg_value(portid_t port_id, uint32_t reg_off, uint32_t reg_v) 600 { 601 display_port_and_reg_off(port_id, (unsigned)reg_off); 602 printf("0x%08X (%u)\n", (unsigned)reg_v, (unsigned)reg_v); 603 } 604 605 void 606 port_reg_bit_display(portid_t port_id, uint32_t reg_off, uint8_t bit_x) 607 { 608 uint32_t reg_v; 609 610 611 if (port_id_is_invalid(port_id, ENABLED_WARN)) 612 return; 613 if (port_reg_off_is_invalid(port_id, reg_off)) 614 return; 615 if (reg_bit_pos_is_invalid(bit_x)) 616 return; 617 reg_v = port_id_pci_reg_read(port_id, reg_off); 618 display_port_and_reg_off(port_id, (unsigned)reg_off); 619 printf("bit %d=%d\n", bit_x, (int) ((reg_v & (1 << bit_x)) >> bit_x)); 620 } 621 622 void 623 port_reg_bit_field_display(portid_t port_id, uint32_t reg_off, 624 uint8_t bit1_pos, uint8_t bit2_pos) 625 { 626 uint32_t reg_v; 627 uint8_t l_bit; 628 uint8_t h_bit; 629 630 if (port_id_is_invalid(port_id, ENABLED_WARN)) 631 return; 632 if (port_reg_off_is_invalid(port_id, reg_off)) 633 return; 634 if (reg_bit_pos_is_invalid(bit1_pos)) 635 return; 636 if (reg_bit_pos_is_invalid(bit2_pos)) 637 return; 638 if (bit1_pos > bit2_pos) 639 l_bit = bit2_pos, h_bit = bit1_pos; 640 else 641 l_bit = bit1_pos, h_bit = bit2_pos; 642 643 reg_v = port_id_pci_reg_read(port_id, reg_off); 644 reg_v >>= l_bit; 645 if (h_bit < 31) 646 reg_v &= ((1 << (h_bit - l_bit + 1)) - 1); 647 display_port_and_reg_off(port_id, (unsigned)reg_off); 648 printf("bits[%d, %d]=0x%0*X (%u)\n", l_bit, h_bit, 649 ((h_bit - l_bit) / 4) + 1, (unsigned)reg_v, (unsigned)reg_v); 650 } 651 652 void 653 port_reg_display(portid_t port_id, uint32_t reg_off) 654 { 655 uint32_t reg_v; 656 657 if (port_id_is_invalid(port_id, ENABLED_WARN)) 658 return; 659 if (port_reg_off_is_invalid(port_id, reg_off)) 660 return; 661 reg_v = port_id_pci_reg_read(port_id, reg_off); 662 display_port_reg_value(port_id, reg_off, reg_v); 663 } 664 665 void 666 port_reg_bit_set(portid_t port_id, uint32_t reg_off, uint8_t bit_pos, 667 uint8_t bit_v) 668 { 669 uint32_t reg_v; 670 671 if (port_id_is_invalid(port_id, ENABLED_WARN)) 672 return; 673 if (port_reg_off_is_invalid(port_id, reg_off)) 674 return; 675 if (reg_bit_pos_is_invalid(bit_pos)) 676 return; 677 if (bit_v > 1) { 678 printf("Invalid bit value %d (must be 0 or 1)\n", (int) bit_v); 679 return; 680 } 681 reg_v = port_id_pci_reg_read(port_id, reg_off); 682 if (bit_v == 0) 683 reg_v &= ~(1 << bit_pos); 684 else 685 reg_v |= (1 << bit_pos); 686 port_id_pci_reg_write(port_id, reg_off, reg_v); 687 display_port_reg_value(port_id, reg_off, reg_v); 688 } 689 690 void 691 port_reg_bit_field_set(portid_t port_id, uint32_t reg_off, 692 uint8_t bit1_pos, uint8_t bit2_pos, uint32_t value) 693 { 694 uint32_t max_v; 695 uint32_t reg_v; 696 uint8_t l_bit; 697 uint8_t h_bit; 698 699 if (port_id_is_invalid(port_id, ENABLED_WARN)) 700 return; 701 if (port_reg_off_is_invalid(port_id, reg_off)) 702 return; 703 if (reg_bit_pos_is_invalid(bit1_pos)) 704 return; 705 if (reg_bit_pos_is_invalid(bit2_pos)) 706 return; 707 if (bit1_pos > bit2_pos) 708 l_bit = bit2_pos, h_bit = bit1_pos; 709 else 710 l_bit = bit1_pos, h_bit = bit2_pos; 711 712 if ((h_bit - l_bit) < 31) 713 max_v = (1 << (h_bit - l_bit + 1)) - 1; 714 else 715 max_v = 0xFFFFFFFF; 716 717 if (value > max_v) { 718 printf("Invalid value %u (0x%x) must be < %u (0x%x)\n", 719 (unsigned)value, (unsigned)value, 720 (unsigned)max_v, (unsigned)max_v); 721 return; 722 } 723 reg_v = port_id_pci_reg_read(port_id, reg_off); 724 reg_v &= ~(max_v << l_bit); /* Keep unchanged bits */ 725 reg_v |= (value << l_bit); /* Set changed bits */ 726 port_id_pci_reg_write(port_id, reg_off, reg_v); 727 display_port_reg_value(port_id, reg_off, reg_v); 728 } 729 730 void 731 port_reg_set(portid_t port_id, uint32_t reg_off, uint32_t reg_v) 732 { 733 if (port_id_is_invalid(port_id, ENABLED_WARN)) 734 return; 735 if (port_reg_off_is_invalid(port_id, reg_off)) 736 return; 737 port_id_pci_reg_write(port_id, reg_off, reg_v); 738 display_port_reg_value(port_id, reg_off, reg_v); 739 } 740 741 void 742 port_mtu_set(portid_t port_id, uint16_t mtu) 743 { 744 int diag; 745 746 if (port_id_is_invalid(port_id, ENABLED_WARN)) 747 return; 748 diag = rte_eth_dev_set_mtu(port_id, mtu); 749 if (diag == 0) 750 return; 751 printf("Set MTU failed. diag=%d\n", diag); 752 } 753 754 /* 755 * RX/TX ring descriptors display functions. 756 */ 757 int 758 rx_queue_id_is_invalid(queueid_t rxq_id) 759 { 760 if (rxq_id < nb_rxq) 761 return 0; 762 printf("Invalid RX queue %d (must be < nb_rxq=%d)\n", rxq_id, nb_rxq); 763 return 1; 764 } 765 766 int 767 tx_queue_id_is_invalid(queueid_t txq_id) 768 { 769 if (txq_id < nb_txq) 770 return 0; 771 printf("Invalid TX queue %d (must be < nb_rxq=%d)\n", txq_id, nb_txq); 772 return 1; 773 } 774 775 static int 776 rx_desc_id_is_invalid(uint16_t rxdesc_id) 777 { 778 if (rxdesc_id < nb_rxd) 779 return 0; 780 printf("Invalid RX descriptor %d (must be < nb_rxd=%d)\n", 781 rxdesc_id, nb_rxd); 782 return 1; 783 } 784 785 static int 786 tx_desc_id_is_invalid(uint16_t txdesc_id) 787 { 788 if (txdesc_id < nb_txd) 789 return 0; 790 printf("Invalid TX descriptor %d (must be < nb_txd=%d)\n", 791 txdesc_id, nb_txd); 792 return 1; 793 } 794 795 static const struct rte_memzone * 796 ring_dma_zone_lookup(const char *ring_name, uint8_t port_id, uint16_t q_id) 797 { 798 char mz_name[RTE_MEMZONE_NAMESIZE]; 799 const struct rte_memzone *mz; 800 801 snprintf(mz_name, sizeof(mz_name), "%s_%s_%d_%d", 802 ports[port_id].dev_info.driver_name, ring_name, port_id, q_id); 803 mz = rte_memzone_lookup(mz_name); 804 if (mz == NULL) 805 printf("%s ring memory zoneof (port %d, queue %d) not" 806 "found (zone name = %s\n", 807 ring_name, port_id, q_id, mz_name); 808 return mz; 809 } 810 811 union igb_ring_dword { 812 uint64_t dword; 813 struct { 814 #if RTE_BYTE_ORDER == RTE_BIG_ENDIAN 815 uint32_t lo; 816 uint32_t hi; 817 #else 818 uint32_t hi; 819 uint32_t lo; 820 #endif 821 } words; 822 }; 823 824 struct igb_ring_desc_32_bytes { 825 union igb_ring_dword lo_dword; 826 union igb_ring_dword hi_dword; 827 union igb_ring_dword resv1; 828 union igb_ring_dword resv2; 829 }; 830 831 struct igb_ring_desc_16_bytes { 832 union igb_ring_dword lo_dword; 833 union igb_ring_dword hi_dword; 834 }; 835 836 static void 837 ring_rxd_display_dword(union igb_ring_dword dword) 838 { 839 printf(" 0x%08X - 0x%08X\n", (unsigned)dword.words.lo, 840 (unsigned)dword.words.hi); 841 } 842 843 static void 844 ring_rx_descriptor_display(const struct rte_memzone *ring_mz, 845 #ifndef RTE_LIBRTE_I40E_16BYTE_RX_DESC 846 uint8_t port_id, 847 #else 848 __rte_unused uint8_t port_id, 849 #endif 850 uint16_t desc_id) 851 { 852 struct igb_ring_desc_16_bytes *ring = 853 (struct igb_ring_desc_16_bytes *)ring_mz->addr; 854 #ifndef RTE_LIBRTE_I40E_16BYTE_RX_DESC 855 struct rte_eth_dev_info dev_info; 856 857 memset(&dev_info, 0, sizeof(dev_info)); 858 rte_eth_dev_info_get(port_id, &dev_info); 859 if (strstr(dev_info.driver_name, "i40e") != NULL) { 860 /* 32 bytes RX descriptor, i40e only */ 861 struct igb_ring_desc_32_bytes *ring = 862 (struct igb_ring_desc_32_bytes *)ring_mz->addr; 863 ring[desc_id].lo_dword.dword = 864 rte_le_to_cpu_64(ring[desc_id].lo_dword.dword); 865 ring_rxd_display_dword(ring[desc_id].lo_dword); 866 ring[desc_id].hi_dword.dword = 867 rte_le_to_cpu_64(ring[desc_id].hi_dword.dword); 868 ring_rxd_display_dword(ring[desc_id].hi_dword); 869 ring[desc_id].resv1.dword = 870 rte_le_to_cpu_64(ring[desc_id].resv1.dword); 871 ring_rxd_display_dword(ring[desc_id].resv1); 872 ring[desc_id].resv2.dword = 873 rte_le_to_cpu_64(ring[desc_id].resv2.dword); 874 ring_rxd_display_dword(ring[desc_id].resv2); 875 876 return; 877 } 878 #endif 879 /* 16 bytes RX descriptor */ 880 ring[desc_id].lo_dword.dword = 881 rte_le_to_cpu_64(ring[desc_id].lo_dword.dword); 882 ring_rxd_display_dword(ring[desc_id].lo_dword); 883 ring[desc_id].hi_dword.dword = 884 rte_le_to_cpu_64(ring[desc_id].hi_dword.dword); 885 ring_rxd_display_dword(ring[desc_id].hi_dword); 886 } 887 888 static void 889 ring_tx_descriptor_display(const struct rte_memzone *ring_mz, uint16_t desc_id) 890 { 891 struct igb_ring_desc_16_bytes *ring; 892 struct igb_ring_desc_16_bytes txd; 893 894 ring = (struct igb_ring_desc_16_bytes *)ring_mz->addr; 895 txd.lo_dword.dword = rte_le_to_cpu_64(ring[desc_id].lo_dword.dword); 896 txd.hi_dword.dword = rte_le_to_cpu_64(ring[desc_id].hi_dword.dword); 897 printf(" 0x%08X - 0x%08X / 0x%08X - 0x%08X\n", 898 (unsigned)txd.lo_dword.words.lo, 899 (unsigned)txd.lo_dword.words.hi, 900 (unsigned)txd.hi_dword.words.lo, 901 (unsigned)txd.hi_dword.words.hi); 902 } 903 904 void 905 rx_ring_desc_display(portid_t port_id, queueid_t rxq_id, uint16_t rxd_id) 906 { 907 const struct rte_memzone *rx_mz; 908 909 if (port_id_is_invalid(port_id, ENABLED_WARN)) 910 return; 911 if (rx_queue_id_is_invalid(rxq_id)) 912 return; 913 if (rx_desc_id_is_invalid(rxd_id)) 914 return; 915 rx_mz = ring_dma_zone_lookup("rx_ring", port_id, rxq_id); 916 if (rx_mz == NULL) 917 return; 918 ring_rx_descriptor_display(rx_mz, port_id, rxd_id); 919 } 920 921 void 922 tx_ring_desc_display(portid_t port_id, queueid_t txq_id, uint16_t txd_id) 923 { 924 const struct rte_memzone *tx_mz; 925 926 if (port_id_is_invalid(port_id, ENABLED_WARN)) 927 return; 928 if (tx_queue_id_is_invalid(txq_id)) 929 return; 930 if (tx_desc_id_is_invalid(txd_id)) 931 return; 932 tx_mz = ring_dma_zone_lookup("tx_ring", port_id, txq_id); 933 if (tx_mz == NULL) 934 return; 935 ring_tx_descriptor_display(tx_mz, txd_id); 936 } 937 938 void 939 fwd_lcores_config_display(void) 940 { 941 lcoreid_t lc_id; 942 943 printf("List of forwarding lcores:"); 944 for (lc_id = 0; lc_id < nb_cfg_lcores; lc_id++) 945 printf(" %2u", fwd_lcores_cpuids[lc_id]); 946 printf("\n"); 947 } 948 void 949 rxtx_config_display(void) 950 { 951 printf(" %s packet forwarding%s - CRC stripping %s - " 952 "packets/burst=%d\n", cur_fwd_eng->fwd_mode_name, 953 retry_enabled == 0 ? "" : " with retry", 954 rx_mode.hw_strip_crc ? "enabled" : "disabled", 955 nb_pkt_per_burst); 956 957 if (cur_fwd_eng == &tx_only_engine) 958 printf(" packet len=%u - nb packet segments=%d\n", 959 (unsigned)tx_pkt_length, (int) tx_pkt_nb_segs); 960 961 struct rte_eth_rxconf *rx_conf = &ports[0].rx_conf; 962 struct rte_eth_txconf *tx_conf = &ports[0].tx_conf; 963 964 printf(" nb forwarding cores=%d - nb forwarding ports=%d\n", 965 nb_fwd_lcores, nb_fwd_ports); 966 printf(" RX queues=%d - RX desc=%d - RX free threshold=%d\n", 967 nb_rxq, nb_rxd, rx_conf->rx_free_thresh); 968 printf(" RX threshold registers: pthresh=%d hthresh=%d wthresh=%d\n", 969 rx_conf->rx_thresh.pthresh, rx_conf->rx_thresh.hthresh, 970 rx_conf->rx_thresh.wthresh); 971 printf(" TX queues=%d - TX desc=%d - TX free threshold=%d\n", 972 nb_txq, nb_txd, tx_conf->tx_free_thresh); 973 printf(" TX threshold registers: pthresh=%d hthresh=%d wthresh=%d\n", 974 tx_conf->tx_thresh.pthresh, tx_conf->tx_thresh.hthresh, 975 tx_conf->tx_thresh.wthresh); 976 printf(" TX RS bit threshold=%d - TXQ flags=0x%"PRIx32"\n", 977 tx_conf->tx_rs_thresh, tx_conf->txq_flags); 978 } 979 980 void 981 port_rss_reta_info(portid_t port_id, 982 struct rte_eth_rss_reta_entry64 *reta_conf, 983 uint16_t nb_entries) 984 { 985 uint16_t i, idx, shift; 986 int ret; 987 988 if (port_id_is_invalid(port_id, ENABLED_WARN)) 989 return; 990 991 ret = rte_eth_dev_rss_reta_query(port_id, reta_conf, nb_entries); 992 if (ret != 0) { 993 printf("Failed to get RSS RETA info, return code = %d\n", ret); 994 return; 995 } 996 997 for (i = 0; i < nb_entries; i++) { 998 idx = i / RTE_RETA_GROUP_SIZE; 999 shift = i % RTE_RETA_GROUP_SIZE; 1000 if (!(reta_conf[idx].mask & (1ULL << shift))) 1001 continue; 1002 printf("RSS RETA configuration: hash index=%u, queue=%u\n", 1003 i, reta_conf[idx].reta[shift]); 1004 } 1005 } 1006 1007 /* 1008 * Displays the RSS hash functions of a port, and, optionaly, the RSS hash 1009 * key of the port. 1010 */ 1011 void 1012 port_rss_hash_conf_show(portid_t port_id, char rss_info[], int show_rss_key) 1013 { 1014 struct rte_eth_rss_conf rss_conf; 1015 uint8_t rss_key[10 * 4] = ""; 1016 uint64_t rss_hf; 1017 uint8_t i; 1018 int diag; 1019 1020 if (port_id_is_invalid(port_id, ENABLED_WARN)) 1021 return; 1022 1023 rss_conf.rss_hf = 0; 1024 for (i = 0; i < RTE_DIM(rss_type_table); i++) { 1025 if (!strcmp(rss_info, rss_type_table[i].str)) 1026 rss_conf.rss_hf = rss_type_table[i].rss_type; 1027 } 1028 1029 /* Get RSS hash key if asked to display it */ 1030 rss_conf.rss_key = (show_rss_key) ? rss_key : NULL; 1031 rss_conf.rss_key_len = sizeof(rss_key); 1032 diag = rte_eth_dev_rss_hash_conf_get(port_id, &rss_conf); 1033 if (diag != 0) { 1034 switch (diag) { 1035 case -ENODEV: 1036 printf("port index %d invalid\n", port_id); 1037 break; 1038 case -ENOTSUP: 1039 printf("operation not supported by device\n"); 1040 break; 1041 default: 1042 printf("operation failed - diag=%d\n", diag); 1043 break; 1044 } 1045 return; 1046 } 1047 rss_hf = rss_conf.rss_hf; 1048 if (rss_hf == 0) { 1049 printf("RSS disabled\n"); 1050 return; 1051 } 1052 printf("RSS functions:\n "); 1053 for (i = 0; i < RTE_DIM(rss_type_table); i++) { 1054 if (rss_hf & rss_type_table[i].rss_type) 1055 printf("%s ", rss_type_table[i].str); 1056 } 1057 printf("\n"); 1058 if (!show_rss_key) 1059 return; 1060 printf("RSS key:\n"); 1061 for (i = 0; i < sizeof(rss_key); i++) 1062 printf("%02X", rss_key[i]); 1063 printf("\n"); 1064 } 1065 1066 void 1067 port_rss_hash_key_update(portid_t port_id, char rss_type[], uint8_t *hash_key, 1068 uint hash_key_len) 1069 { 1070 struct rte_eth_rss_conf rss_conf; 1071 int diag; 1072 unsigned int i; 1073 1074 rss_conf.rss_key = NULL; 1075 rss_conf.rss_key_len = hash_key_len; 1076 rss_conf.rss_hf = 0; 1077 for (i = 0; i < RTE_DIM(rss_type_table); i++) { 1078 if (!strcmp(rss_type_table[i].str, rss_type)) 1079 rss_conf.rss_hf = rss_type_table[i].rss_type; 1080 } 1081 diag = rte_eth_dev_rss_hash_conf_get(port_id, &rss_conf); 1082 if (diag == 0) { 1083 rss_conf.rss_key = hash_key; 1084 diag = rte_eth_dev_rss_hash_update(port_id, &rss_conf); 1085 } 1086 if (diag == 0) 1087 return; 1088 1089 switch (diag) { 1090 case -ENODEV: 1091 printf("port index %d invalid\n", port_id); 1092 break; 1093 case -ENOTSUP: 1094 printf("operation not supported by device\n"); 1095 break; 1096 default: 1097 printf("operation failed - diag=%d\n", diag); 1098 break; 1099 } 1100 } 1101 1102 /* 1103 * Setup forwarding configuration for each logical core. 1104 */ 1105 static void 1106 setup_fwd_config_of_each_lcore(struct fwd_config *cfg) 1107 { 1108 streamid_t nb_fs_per_lcore; 1109 streamid_t nb_fs; 1110 streamid_t sm_id; 1111 lcoreid_t nb_extra; 1112 lcoreid_t nb_fc; 1113 lcoreid_t nb_lc; 1114 lcoreid_t lc_id; 1115 1116 nb_fs = cfg->nb_fwd_streams; 1117 nb_fc = cfg->nb_fwd_lcores; 1118 if (nb_fs <= nb_fc) { 1119 nb_fs_per_lcore = 1; 1120 nb_extra = 0; 1121 } else { 1122 nb_fs_per_lcore = (streamid_t) (nb_fs / nb_fc); 1123 nb_extra = (lcoreid_t) (nb_fs % nb_fc); 1124 } 1125 1126 nb_lc = (lcoreid_t) (nb_fc - nb_extra); 1127 sm_id = 0; 1128 for (lc_id = 0; lc_id < nb_lc; lc_id++) { 1129 fwd_lcores[lc_id]->stream_idx = sm_id; 1130 fwd_lcores[lc_id]->stream_nb = nb_fs_per_lcore; 1131 sm_id = (streamid_t) (sm_id + nb_fs_per_lcore); 1132 } 1133 1134 /* 1135 * Assign extra remaining streams, if any. 1136 */ 1137 nb_fs_per_lcore = (streamid_t) (nb_fs_per_lcore + 1); 1138 for (lc_id = 0; lc_id < nb_extra; lc_id++) { 1139 fwd_lcores[nb_lc + lc_id]->stream_idx = sm_id; 1140 fwd_lcores[nb_lc + lc_id]->stream_nb = nb_fs_per_lcore; 1141 sm_id = (streamid_t) (sm_id + nb_fs_per_lcore); 1142 } 1143 } 1144 1145 static void 1146 simple_fwd_config_setup(void) 1147 { 1148 portid_t i; 1149 portid_t j; 1150 portid_t inc = 2; 1151 1152 if (port_topology == PORT_TOPOLOGY_CHAINED || 1153 port_topology == PORT_TOPOLOGY_LOOP) { 1154 inc = 1; 1155 } else if (nb_fwd_ports % 2) { 1156 printf("\nWarning! Cannot handle an odd number of ports " 1157 "with the current port topology. Configuration " 1158 "must be changed to have an even number of ports, " 1159 "or relaunch application with " 1160 "--port-topology=chained\n\n"); 1161 } 1162 1163 cur_fwd_config.nb_fwd_ports = (portid_t) nb_fwd_ports; 1164 cur_fwd_config.nb_fwd_streams = 1165 (streamid_t) cur_fwd_config.nb_fwd_ports; 1166 1167 /* reinitialize forwarding streams */ 1168 init_fwd_streams(); 1169 1170 /* 1171 * In the simple forwarding test, the number of forwarding cores 1172 * must be lower or equal to the number of forwarding ports. 1173 */ 1174 cur_fwd_config.nb_fwd_lcores = (lcoreid_t) nb_fwd_lcores; 1175 if (cur_fwd_config.nb_fwd_lcores > cur_fwd_config.nb_fwd_ports) 1176 cur_fwd_config.nb_fwd_lcores = 1177 (lcoreid_t) cur_fwd_config.nb_fwd_ports; 1178 setup_fwd_config_of_each_lcore(&cur_fwd_config); 1179 1180 for (i = 0; i < cur_fwd_config.nb_fwd_ports; i = (portid_t) (i + inc)) { 1181 if (port_topology != PORT_TOPOLOGY_LOOP) 1182 j = (portid_t) ((i + 1) % cur_fwd_config.nb_fwd_ports); 1183 else 1184 j = i; 1185 fwd_streams[i]->rx_port = fwd_ports_ids[i]; 1186 fwd_streams[i]->rx_queue = 0; 1187 fwd_streams[i]->tx_port = fwd_ports_ids[j]; 1188 fwd_streams[i]->tx_queue = 0; 1189 fwd_streams[i]->peer_addr = j; 1190 fwd_streams[i]->retry_enabled = retry_enabled; 1191 1192 if (port_topology == PORT_TOPOLOGY_PAIRED) { 1193 fwd_streams[j]->rx_port = fwd_ports_ids[j]; 1194 fwd_streams[j]->rx_queue = 0; 1195 fwd_streams[j]->tx_port = fwd_ports_ids[i]; 1196 fwd_streams[j]->tx_queue = 0; 1197 fwd_streams[j]->peer_addr = i; 1198 fwd_streams[j]->retry_enabled = retry_enabled; 1199 } 1200 } 1201 } 1202 1203 /** 1204 * For the RSS forwarding test all streams distributed over lcores. Each stream 1205 * being composed of a RX queue to poll on a RX port for input messages, 1206 * associated with a TX queue of a TX port where to send forwarded packets. 1207 * All packets received on the RX queue of index "RxQj" of the RX port "RxPi" 1208 * are sent on the TX queue "TxQl" of the TX port "TxPk" according to the two 1209 * following rules: 1210 * - TxPk = (RxPi + 1) if RxPi is even, (RxPi - 1) if RxPi is odd 1211 * - TxQl = RxQj 1212 */ 1213 static void 1214 rss_fwd_config_setup(void) 1215 { 1216 portid_t rxp; 1217 portid_t txp; 1218 queueid_t rxq; 1219 queueid_t nb_q; 1220 streamid_t sm_id; 1221 1222 nb_q = nb_rxq; 1223 if (nb_q > nb_txq) 1224 nb_q = nb_txq; 1225 cur_fwd_config.nb_fwd_lcores = (lcoreid_t) nb_fwd_lcores; 1226 cur_fwd_config.nb_fwd_ports = nb_fwd_ports; 1227 cur_fwd_config.nb_fwd_streams = 1228 (streamid_t) (nb_q * cur_fwd_config.nb_fwd_ports); 1229 1230 if (cur_fwd_config.nb_fwd_streams < cur_fwd_config.nb_fwd_lcores) 1231 cur_fwd_config.nb_fwd_lcores = 1232 (lcoreid_t)cur_fwd_config.nb_fwd_streams; 1233 1234 /* reinitialize forwarding streams */ 1235 init_fwd_streams(); 1236 1237 setup_fwd_config_of_each_lcore(&cur_fwd_config); 1238 rxp = 0; rxq = 0; 1239 for (sm_id = 0; sm_id < cur_fwd_config.nb_fwd_streams; sm_id++) { 1240 struct fwd_stream *fs; 1241 1242 fs = fwd_streams[sm_id]; 1243 1244 if ((rxp & 0x1) == 0) 1245 txp = (portid_t) (rxp + 1); 1246 else 1247 txp = (portid_t) (rxp - 1); 1248 /* 1249 * if we are in loopback, simply send stuff out through the 1250 * ingress port 1251 */ 1252 if (port_topology == PORT_TOPOLOGY_LOOP) 1253 txp = rxp; 1254 1255 fs->rx_port = fwd_ports_ids[rxp]; 1256 fs->rx_queue = rxq; 1257 fs->tx_port = fwd_ports_ids[txp]; 1258 fs->tx_queue = rxq; 1259 fs->peer_addr = fs->tx_port; 1260 fs->retry_enabled = retry_enabled; 1261 rxq = (queueid_t) (rxq + 1); 1262 if (rxq < nb_q) 1263 continue; 1264 /* 1265 * rxq == nb_q 1266 * Restart from RX queue 0 on next RX port 1267 */ 1268 rxq = 0; 1269 if (numa_support && (nb_fwd_ports <= (nb_ports >> 1))) 1270 rxp = (portid_t) 1271 (rxp + ((nb_ports >> 1) / nb_fwd_ports)); 1272 else 1273 rxp = (portid_t) (rxp + 1); 1274 } 1275 } 1276 1277 /** 1278 * For the DCB forwarding test, each core is assigned on each traffic class. 1279 * 1280 * Each core is assigned a multi-stream, each stream being composed of 1281 * a RX queue to poll on a RX port for input messages, associated with 1282 * a TX queue of a TX port where to send forwarded packets. All RX and 1283 * TX queues are mapping to the same traffic class. 1284 * If VMDQ and DCB co-exist, each traffic class on different POOLs share 1285 * the same core 1286 */ 1287 static void 1288 dcb_fwd_config_setup(void) 1289 { 1290 struct rte_eth_dcb_info rxp_dcb_info, txp_dcb_info; 1291 portid_t txp, rxp = 0; 1292 queueid_t txq, rxq = 0; 1293 lcoreid_t lc_id; 1294 uint16_t nb_rx_queue, nb_tx_queue; 1295 uint16_t i, j, k, sm_id = 0; 1296 uint8_t tc = 0; 1297 1298 cur_fwd_config.nb_fwd_lcores = (lcoreid_t) nb_fwd_lcores; 1299 cur_fwd_config.nb_fwd_ports = nb_fwd_ports; 1300 cur_fwd_config.nb_fwd_streams = 1301 (streamid_t) (nb_rxq * cur_fwd_config.nb_fwd_ports); 1302 1303 /* reinitialize forwarding streams */ 1304 init_fwd_streams(); 1305 sm_id = 0; 1306 txp = 1; 1307 /* get the dcb info on the first RX and TX ports */ 1308 (void)rte_eth_dev_get_dcb_info(fwd_ports_ids[rxp], &rxp_dcb_info); 1309 (void)rte_eth_dev_get_dcb_info(fwd_ports_ids[txp], &txp_dcb_info); 1310 1311 for (lc_id = 0; lc_id < cur_fwd_config.nb_fwd_lcores; lc_id++) { 1312 fwd_lcores[lc_id]->stream_nb = 0; 1313 fwd_lcores[lc_id]->stream_idx = sm_id; 1314 for (i = 0; i < ETH_MAX_VMDQ_POOL; i++) { 1315 /* if the nb_queue is zero, means this tc is 1316 * not enabled on the POOL 1317 */ 1318 if (rxp_dcb_info.tc_queue.tc_rxq[i][tc].nb_queue == 0) 1319 break; 1320 k = fwd_lcores[lc_id]->stream_nb + 1321 fwd_lcores[lc_id]->stream_idx; 1322 rxq = rxp_dcb_info.tc_queue.tc_rxq[i][tc].base; 1323 txq = txp_dcb_info.tc_queue.tc_txq[i][tc].base; 1324 nb_rx_queue = txp_dcb_info.tc_queue.tc_rxq[i][tc].nb_queue; 1325 nb_tx_queue = txp_dcb_info.tc_queue.tc_txq[i][tc].nb_queue; 1326 for (j = 0; j < nb_rx_queue; j++) { 1327 struct fwd_stream *fs; 1328 1329 fs = fwd_streams[k + j]; 1330 fs->rx_port = fwd_ports_ids[rxp]; 1331 fs->rx_queue = rxq + j; 1332 fs->tx_port = fwd_ports_ids[txp]; 1333 fs->tx_queue = txq + j % nb_tx_queue; 1334 fs->peer_addr = fs->tx_port; 1335 fs->retry_enabled = retry_enabled; 1336 } 1337 fwd_lcores[lc_id]->stream_nb += 1338 rxp_dcb_info.tc_queue.tc_rxq[i][tc].nb_queue; 1339 } 1340 sm_id = (streamid_t) (sm_id + fwd_lcores[lc_id]->stream_nb); 1341 1342 tc++; 1343 if (tc < rxp_dcb_info.nb_tcs) 1344 continue; 1345 /* Restart from TC 0 on next RX port */ 1346 tc = 0; 1347 if (numa_support && (nb_fwd_ports <= (nb_ports >> 1))) 1348 rxp = (portid_t) 1349 (rxp + ((nb_ports >> 1) / nb_fwd_ports)); 1350 else 1351 rxp++; 1352 if (rxp >= nb_fwd_ports) 1353 return; 1354 /* get the dcb information on next RX and TX ports */ 1355 if ((rxp & 0x1) == 0) 1356 txp = (portid_t) (rxp + 1); 1357 else 1358 txp = (portid_t) (rxp - 1); 1359 rte_eth_dev_get_dcb_info(fwd_ports_ids[rxp], &rxp_dcb_info); 1360 rte_eth_dev_get_dcb_info(fwd_ports_ids[txp], &txp_dcb_info); 1361 } 1362 } 1363 1364 static void 1365 icmp_echo_config_setup(void) 1366 { 1367 portid_t rxp; 1368 queueid_t rxq; 1369 lcoreid_t lc_id; 1370 uint16_t sm_id; 1371 1372 if ((nb_txq * nb_fwd_ports) < nb_fwd_lcores) 1373 cur_fwd_config.nb_fwd_lcores = (lcoreid_t) 1374 (nb_txq * nb_fwd_ports); 1375 else 1376 cur_fwd_config.nb_fwd_lcores = (lcoreid_t) nb_fwd_lcores; 1377 cur_fwd_config.nb_fwd_ports = nb_fwd_ports; 1378 cur_fwd_config.nb_fwd_streams = 1379 (streamid_t) (nb_rxq * cur_fwd_config.nb_fwd_ports); 1380 if (cur_fwd_config.nb_fwd_streams < cur_fwd_config.nb_fwd_lcores) 1381 cur_fwd_config.nb_fwd_lcores = 1382 (lcoreid_t)cur_fwd_config.nb_fwd_streams; 1383 if (verbose_level > 0) { 1384 printf("%s fwd_cores=%d fwd_ports=%d fwd_streams=%d\n", 1385 __FUNCTION__, 1386 cur_fwd_config.nb_fwd_lcores, 1387 cur_fwd_config.nb_fwd_ports, 1388 cur_fwd_config.nb_fwd_streams); 1389 } 1390 1391 /* reinitialize forwarding streams */ 1392 init_fwd_streams(); 1393 setup_fwd_config_of_each_lcore(&cur_fwd_config); 1394 rxp = 0; rxq = 0; 1395 for (lc_id = 0; lc_id < cur_fwd_config.nb_fwd_lcores; lc_id++) { 1396 if (verbose_level > 0) 1397 printf(" core=%d: \n", lc_id); 1398 for (sm_id = 0; sm_id < fwd_lcores[lc_id]->stream_nb; sm_id++) { 1399 struct fwd_stream *fs; 1400 fs = fwd_streams[fwd_lcores[lc_id]->stream_idx + sm_id]; 1401 fs->rx_port = fwd_ports_ids[rxp]; 1402 fs->rx_queue = rxq; 1403 fs->tx_port = fs->rx_port; 1404 fs->tx_queue = rxq; 1405 fs->peer_addr = fs->tx_port; 1406 fs->retry_enabled = retry_enabled; 1407 if (verbose_level > 0) 1408 printf(" stream=%d port=%d rxq=%d txq=%d\n", 1409 sm_id, fs->rx_port, fs->rx_queue, 1410 fs->tx_queue); 1411 rxq = (queueid_t) (rxq + 1); 1412 if (rxq == nb_rxq) { 1413 rxq = 0; 1414 rxp = (portid_t) (rxp + 1); 1415 } 1416 } 1417 } 1418 } 1419 1420 void 1421 fwd_config_setup(void) 1422 { 1423 cur_fwd_config.fwd_eng = cur_fwd_eng; 1424 if (strcmp(cur_fwd_eng->fwd_mode_name, "icmpecho") == 0) { 1425 icmp_echo_config_setup(); 1426 return; 1427 } 1428 if ((nb_rxq > 1) && (nb_txq > 1)){ 1429 if (dcb_config) 1430 dcb_fwd_config_setup(); 1431 else 1432 rss_fwd_config_setup(); 1433 } 1434 else 1435 simple_fwd_config_setup(); 1436 } 1437 1438 void 1439 pkt_fwd_config_display(struct fwd_config *cfg) 1440 { 1441 struct fwd_stream *fs; 1442 lcoreid_t lc_id; 1443 streamid_t sm_id; 1444 1445 printf("%s packet forwarding%s - ports=%d - cores=%d - streams=%d - " 1446 "NUMA support %s, MP over anonymous pages %s\n", 1447 cfg->fwd_eng->fwd_mode_name, 1448 retry_enabled == 0 ? "" : " with retry", 1449 cfg->nb_fwd_ports, cfg->nb_fwd_lcores, cfg->nb_fwd_streams, 1450 numa_support == 1 ? "enabled" : "disabled", 1451 mp_anon != 0 ? "enabled" : "disabled"); 1452 1453 if (retry_enabled) 1454 printf("TX retry num: %u, delay between TX retries: %uus\n", 1455 burst_tx_retry_num, burst_tx_delay_time); 1456 for (lc_id = 0; lc_id < cfg->nb_fwd_lcores; lc_id++) { 1457 printf("Logical Core %u (socket %u) forwards packets on " 1458 "%d streams:", 1459 fwd_lcores_cpuids[lc_id], 1460 rte_lcore_to_socket_id(fwd_lcores_cpuids[lc_id]), 1461 fwd_lcores[lc_id]->stream_nb); 1462 for (sm_id = 0; sm_id < fwd_lcores[lc_id]->stream_nb; sm_id++) { 1463 fs = fwd_streams[fwd_lcores[lc_id]->stream_idx + sm_id]; 1464 printf("\n RX P=%d/Q=%d (socket %u) -> TX " 1465 "P=%d/Q=%d (socket %u) ", 1466 fs->rx_port, fs->rx_queue, 1467 ports[fs->rx_port].socket_id, 1468 fs->tx_port, fs->tx_queue, 1469 ports[fs->tx_port].socket_id); 1470 print_ethaddr("peer=", 1471 &peer_eth_addrs[fs->peer_addr]); 1472 } 1473 printf("\n"); 1474 } 1475 printf("\n"); 1476 } 1477 1478 int 1479 set_fwd_lcores_list(unsigned int *lcorelist, unsigned int nb_lc) 1480 { 1481 unsigned int i; 1482 unsigned int lcore_cpuid; 1483 int record_now; 1484 1485 record_now = 0; 1486 again: 1487 for (i = 0; i < nb_lc; i++) { 1488 lcore_cpuid = lcorelist[i]; 1489 if (! rte_lcore_is_enabled(lcore_cpuid)) { 1490 printf("lcore %u not enabled\n", lcore_cpuid); 1491 return -1; 1492 } 1493 if (lcore_cpuid == rte_get_master_lcore()) { 1494 printf("lcore %u cannot be masked on for running " 1495 "packet forwarding, which is the master lcore " 1496 "and reserved for command line parsing only\n", 1497 lcore_cpuid); 1498 return -1; 1499 } 1500 if (record_now) 1501 fwd_lcores_cpuids[i] = lcore_cpuid; 1502 } 1503 if (record_now == 0) { 1504 record_now = 1; 1505 goto again; 1506 } 1507 nb_cfg_lcores = (lcoreid_t) nb_lc; 1508 if (nb_fwd_lcores != (lcoreid_t) nb_lc) { 1509 printf("previous number of forwarding cores %u - changed to " 1510 "number of configured cores %u\n", 1511 (unsigned int) nb_fwd_lcores, nb_lc); 1512 nb_fwd_lcores = (lcoreid_t) nb_lc; 1513 } 1514 1515 return 0; 1516 } 1517 1518 int 1519 set_fwd_lcores_mask(uint64_t lcoremask) 1520 { 1521 unsigned int lcorelist[64]; 1522 unsigned int nb_lc; 1523 unsigned int i; 1524 1525 if (lcoremask == 0) { 1526 printf("Invalid NULL mask of cores\n"); 1527 return -1; 1528 } 1529 nb_lc = 0; 1530 for (i = 0; i < 64; i++) { 1531 if (! ((uint64_t)(1ULL << i) & lcoremask)) 1532 continue; 1533 lcorelist[nb_lc++] = i; 1534 } 1535 return set_fwd_lcores_list(lcorelist, nb_lc); 1536 } 1537 1538 void 1539 set_fwd_lcores_number(uint16_t nb_lc) 1540 { 1541 if (nb_lc > nb_cfg_lcores) { 1542 printf("nb fwd cores %u > %u (max. number of configured " 1543 "lcores) - ignored\n", 1544 (unsigned int) nb_lc, (unsigned int) nb_cfg_lcores); 1545 return; 1546 } 1547 nb_fwd_lcores = (lcoreid_t) nb_lc; 1548 printf("Number of forwarding cores set to %u\n", 1549 (unsigned int) nb_fwd_lcores); 1550 } 1551 1552 void 1553 set_fwd_ports_list(unsigned int *portlist, unsigned int nb_pt) 1554 { 1555 unsigned int i; 1556 portid_t port_id; 1557 int record_now; 1558 1559 record_now = 0; 1560 again: 1561 for (i = 0; i < nb_pt; i++) { 1562 port_id = (portid_t) portlist[i]; 1563 if (port_id_is_invalid(port_id, ENABLED_WARN)) 1564 return; 1565 if (record_now) 1566 fwd_ports_ids[i] = port_id; 1567 } 1568 if (record_now == 0) { 1569 record_now = 1; 1570 goto again; 1571 } 1572 nb_cfg_ports = (portid_t) nb_pt; 1573 if (nb_fwd_ports != (portid_t) nb_pt) { 1574 printf("previous number of forwarding ports %u - changed to " 1575 "number of configured ports %u\n", 1576 (unsigned int) nb_fwd_ports, nb_pt); 1577 nb_fwd_ports = (portid_t) nb_pt; 1578 } 1579 } 1580 1581 void 1582 set_fwd_ports_mask(uint64_t portmask) 1583 { 1584 unsigned int portlist[64]; 1585 unsigned int nb_pt; 1586 unsigned int i; 1587 1588 if (portmask == 0) { 1589 printf("Invalid NULL mask of ports\n"); 1590 return; 1591 } 1592 nb_pt = 0; 1593 for (i = 0; i < (unsigned)RTE_MIN(64, RTE_MAX_ETHPORTS); i++) { 1594 if (! ((uint64_t)(1ULL << i) & portmask)) 1595 continue; 1596 portlist[nb_pt++] = i; 1597 } 1598 set_fwd_ports_list(portlist, nb_pt); 1599 } 1600 1601 void 1602 set_fwd_ports_number(uint16_t nb_pt) 1603 { 1604 if (nb_pt > nb_cfg_ports) { 1605 printf("nb fwd ports %u > %u (number of configured " 1606 "ports) - ignored\n", 1607 (unsigned int) nb_pt, (unsigned int) nb_cfg_ports); 1608 return; 1609 } 1610 nb_fwd_ports = (portid_t) nb_pt; 1611 printf("Number of forwarding ports set to %u\n", 1612 (unsigned int) nb_fwd_ports); 1613 } 1614 1615 int 1616 port_is_forwarding(portid_t port_id) 1617 { 1618 unsigned int i; 1619 1620 if (port_id_is_invalid(port_id, ENABLED_WARN)) 1621 return -1; 1622 1623 for (i = 0; i < nb_fwd_ports; i++) { 1624 if (fwd_ports_ids[i] == port_id) 1625 return 1; 1626 } 1627 1628 return 0; 1629 } 1630 1631 void 1632 set_nb_pkt_per_burst(uint16_t nb) 1633 { 1634 if (nb > MAX_PKT_BURST) { 1635 printf("nb pkt per burst: %u > %u (maximum packet per burst) " 1636 " ignored\n", 1637 (unsigned int) nb, (unsigned int) MAX_PKT_BURST); 1638 return; 1639 } 1640 nb_pkt_per_burst = nb; 1641 printf("Number of packets per burst set to %u\n", 1642 (unsigned int) nb_pkt_per_burst); 1643 } 1644 1645 static const char * 1646 tx_split_get_name(enum tx_pkt_split split) 1647 { 1648 uint32_t i; 1649 1650 for (i = 0; i != RTE_DIM(tx_split_name); i++) { 1651 if (tx_split_name[i].split == split) 1652 return tx_split_name[i].name; 1653 } 1654 return NULL; 1655 } 1656 1657 void 1658 set_tx_pkt_split(const char *name) 1659 { 1660 uint32_t i; 1661 1662 for (i = 0; i != RTE_DIM(tx_split_name); i++) { 1663 if (strcmp(tx_split_name[i].name, name) == 0) { 1664 tx_pkt_split = tx_split_name[i].split; 1665 return; 1666 } 1667 } 1668 printf("unknown value: \"%s\"\n", name); 1669 } 1670 1671 void 1672 show_tx_pkt_segments(void) 1673 { 1674 uint32_t i, n; 1675 const char *split; 1676 1677 n = tx_pkt_nb_segs; 1678 split = tx_split_get_name(tx_pkt_split); 1679 1680 printf("Number of segments: %u\n", n); 1681 printf("Segment sizes: "); 1682 for (i = 0; i != n - 1; i++) 1683 printf("%hu,", tx_pkt_seg_lengths[i]); 1684 printf("%hu\n", tx_pkt_seg_lengths[i]); 1685 printf("Split packet: %s\n", split); 1686 } 1687 1688 void 1689 set_tx_pkt_segments(unsigned *seg_lengths, unsigned nb_segs) 1690 { 1691 uint16_t tx_pkt_len; 1692 unsigned i; 1693 1694 if (nb_segs >= (unsigned) nb_txd) { 1695 printf("nb segments per TX packets=%u >= nb_txd=%u - ignored\n", 1696 nb_segs, (unsigned int) nb_txd); 1697 return; 1698 } 1699 1700 /* 1701 * Check that each segment length is greater or equal than 1702 * the mbuf data sise. 1703 * Check also that the total packet length is greater or equal than the 1704 * size of an empty UDP/IP packet (sizeof(struct ether_hdr) + 20 + 8). 1705 */ 1706 tx_pkt_len = 0; 1707 for (i = 0; i < nb_segs; i++) { 1708 if (seg_lengths[i] > (unsigned) mbuf_data_size) { 1709 printf("length[%u]=%u > mbuf_data_size=%u - give up\n", 1710 i, seg_lengths[i], (unsigned) mbuf_data_size); 1711 return; 1712 } 1713 tx_pkt_len = (uint16_t)(tx_pkt_len + seg_lengths[i]); 1714 } 1715 if (tx_pkt_len < (sizeof(struct ether_hdr) + 20 + 8)) { 1716 printf("total packet length=%u < %d - give up\n", 1717 (unsigned) tx_pkt_len, 1718 (int)(sizeof(struct ether_hdr) + 20 + 8)); 1719 return; 1720 } 1721 1722 for (i = 0; i < nb_segs; i++) 1723 tx_pkt_seg_lengths[i] = (uint16_t) seg_lengths[i]; 1724 1725 tx_pkt_length = tx_pkt_len; 1726 tx_pkt_nb_segs = (uint8_t) nb_segs; 1727 } 1728 1729 char* 1730 list_pkt_forwarding_modes(void) 1731 { 1732 static char fwd_modes[128] = ""; 1733 const char *separator = "|"; 1734 struct fwd_engine *fwd_eng; 1735 unsigned i = 0; 1736 1737 if (strlen (fwd_modes) == 0) { 1738 while ((fwd_eng = fwd_engines[i++]) != NULL) { 1739 strncat(fwd_modes, fwd_eng->fwd_mode_name, 1740 sizeof(fwd_modes) - strlen(fwd_modes) - 1); 1741 strncat(fwd_modes, separator, 1742 sizeof(fwd_modes) - strlen(fwd_modes) - 1); 1743 } 1744 fwd_modes[strlen(fwd_modes) - strlen(separator)] = '\0'; 1745 } 1746 1747 return fwd_modes; 1748 } 1749 1750 char* 1751 list_pkt_forwarding_retry_modes(void) 1752 { 1753 static char fwd_modes[128] = ""; 1754 const char *separator = "|"; 1755 struct fwd_engine *fwd_eng; 1756 unsigned i = 0; 1757 1758 if (strlen(fwd_modes) == 0) { 1759 while ((fwd_eng = fwd_engines[i++]) != NULL) { 1760 if (fwd_eng == &rx_only_engine) 1761 continue; 1762 strncat(fwd_modes, fwd_eng->fwd_mode_name, 1763 sizeof(fwd_modes) - 1764 strlen(fwd_modes) - 1); 1765 strncat(fwd_modes, separator, 1766 sizeof(fwd_modes) - 1767 strlen(fwd_modes) - 1); 1768 } 1769 fwd_modes[strlen(fwd_modes) - strlen(separator)] = '\0'; 1770 } 1771 1772 return fwd_modes; 1773 } 1774 1775 void 1776 set_pkt_forwarding_mode(const char *fwd_mode_name) 1777 { 1778 struct fwd_engine *fwd_eng; 1779 unsigned i; 1780 1781 i = 0; 1782 while ((fwd_eng = fwd_engines[i]) != NULL) { 1783 if (! strcmp(fwd_eng->fwd_mode_name, fwd_mode_name)) { 1784 printf("Set %s packet forwarding mode%s\n", 1785 fwd_mode_name, 1786 retry_enabled == 0 ? "" : " with retry"); 1787 cur_fwd_eng = fwd_eng; 1788 return; 1789 } 1790 i++; 1791 } 1792 printf("Invalid %s packet forwarding mode\n", fwd_mode_name); 1793 } 1794 1795 void 1796 set_verbose_level(uint16_t vb_level) 1797 { 1798 printf("Change verbose level from %u to %u\n", 1799 (unsigned int) verbose_level, (unsigned int) vb_level); 1800 verbose_level = vb_level; 1801 } 1802 1803 void 1804 vlan_extend_set(portid_t port_id, int on) 1805 { 1806 int diag; 1807 int vlan_offload; 1808 1809 if (port_id_is_invalid(port_id, ENABLED_WARN)) 1810 return; 1811 1812 vlan_offload = rte_eth_dev_get_vlan_offload(port_id); 1813 1814 if (on) 1815 vlan_offload |= ETH_VLAN_EXTEND_OFFLOAD; 1816 else 1817 vlan_offload &= ~ETH_VLAN_EXTEND_OFFLOAD; 1818 1819 diag = rte_eth_dev_set_vlan_offload(port_id, vlan_offload); 1820 if (diag < 0) 1821 printf("rx_vlan_extend_set(port_pi=%d, on=%d) failed " 1822 "diag=%d\n", port_id, on, diag); 1823 } 1824 1825 void 1826 rx_vlan_strip_set(portid_t port_id, int on) 1827 { 1828 int diag; 1829 int vlan_offload; 1830 1831 if (port_id_is_invalid(port_id, ENABLED_WARN)) 1832 return; 1833 1834 vlan_offload = rte_eth_dev_get_vlan_offload(port_id); 1835 1836 if (on) 1837 vlan_offload |= ETH_VLAN_STRIP_OFFLOAD; 1838 else 1839 vlan_offload &= ~ETH_VLAN_STRIP_OFFLOAD; 1840 1841 diag = rte_eth_dev_set_vlan_offload(port_id, vlan_offload); 1842 if (diag < 0) 1843 printf("rx_vlan_strip_set(port_pi=%d, on=%d) failed " 1844 "diag=%d\n", port_id, on, diag); 1845 } 1846 1847 void 1848 rx_vlan_strip_set_on_queue(portid_t port_id, uint16_t queue_id, int on) 1849 { 1850 int diag; 1851 1852 if (port_id_is_invalid(port_id, ENABLED_WARN)) 1853 return; 1854 1855 diag = rte_eth_dev_set_vlan_strip_on_queue(port_id, queue_id, on); 1856 if (diag < 0) 1857 printf("rx_vlan_strip_set_on_queue(port_pi=%d, queue_id=%d, on=%d) failed " 1858 "diag=%d\n", port_id, queue_id, on, diag); 1859 } 1860 1861 void 1862 rx_vlan_filter_set(portid_t port_id, int on) 1863 { 1864 int diag; 1865 int vlan_offload; 1866 1867 if (port_id_is_invalid(port_id, ENABLED_WARN)) 1868 return; 1869 1870 vlan_offload = rte_eth_dev_get_vlan_offload(port_id); 1871 1872 if (on) 1873 vlan_offload |= ETH_VLAN_FILTER_OFFLOAD; 1874 else 1875 vlan_offload &= ~ETH_VLAN_FILTER_OFFLOAD; 1876 1877 diag = rte_eth_dev_set_vlan_offload(port_id, vlan_offload); 1878 if (diag < 0) 1879 printf("rx_vlan_filter_set(port_pi=%d, on=%d) failed " 1880 "diag=%d\n", port_id, on, diag); 1881 } 1882 1883 int 1884 rx_vft_set(portid_t port_id, uint16_t vlan_id, int on) 1885 { 1886 int diag; 1887 1888 if (port_id_is_invalid(port_id, ENABLED_WARN)) 1889 return 1; 1890 if (vlan_id_is_invalid(vlan_id)) 1891 return 1; 1892 diag = rte_eth_dev_vlan_filter(port_id, vlan_id, on); 1893 if (diag == 0) 1894 return 0; 1895 printf("rte_eth_dev_vlan_filter(port_pi=%d, vlan_id=%d, on=%d) failed " 1896 "diag=%d\n", 1897 port_id, vlan_id, on, diag); 1898 return -1; 1899 } 1900 1901 void 1902 rx_vlan_all_filter_set(portid_t port_id, int on) 1903 { 1904 uint16_t vlan_id; 1905 1906 if (port_id_is_invalid(port_id, ENABLED_WARN)) 1907 return; 1908 for (vlan_id = 0; vlan_id < 4096; vlan_id++) { 1909 if (rx_vft_set(port_id, vlan_id, on)) 1910 break; 1911 } 1912 } 1913 1914 void 1915 vlan_tpid_set(portid_t port_id, enum rte_vlan_type vlan_type, uint16_t tp_id) 1916 { 1917 int diag; 1918 1919 if (port_id_is_invalid(port_id, ENABLED_WARN)) 1920 return; 1921 1922 diag = rte_eth_dev_set_vlan_ether_type(port_id, vlan_type, tp_id); 1923 if (diag == 0) 1924 return; 1925 1926 printf("tx_vlan_tpid_set(port_pi=%d, vlan_type=%d, tpid=%d) failed " 1927 "diag=%d\n", 1928 port_id, vlan_type, tp_id, diag); 1929 } 1930 1931 void 1932 tx_vlan_set(portid_t port_id, uint16_t vlan_id) 1933 { 1934 int vlan_offload; 1935 if (port_id_is_invalid(port_id, ENABLED_WARN)) 1936 return; 1937 if (vlan_id_is_invalid(vlan_id)) 1938 return; 1939 1940 vlan_offload = rte_eth_dev_get_vlan_offload(port_id); 1941 if (vlan_offload & ETH_VLAN_EXTEND_OFFLOAD) { 1942 printf("Error, as QinQ has been enabled.\n"); 1943 return; 1944 } 1945 1946 tx_vlan_reset(port_id); 1947 ports[port_id].tx_ol_flags |= TESTPMD_TX_OFFLOAD_INSERT_VLAN; 1948 ports[port_id].tx_vlan_id = vlan_id; 1949 } 1950 1951 void 1952 tx_qinq_set(portid_t port_id, uint16_t vlan_id, uint16_t vlan_id_outer) 1953 { 1954 int vlan_offload; 1955 if (port_id_is_invalid(port_id, ENABLED_WARN)) 1956 return; 1957 if (vlan_id_is_invalid(vlan_id)) 1958 return; 1959 if (vlan_id_is_invalid(vlan_id_outer)) 1960 return; 1961 1962 vlan_offload = rte_eth_dev_get_vlan_offload(port_id); 1963 if (!(vlan_offload & ETH_VLAN_EXTEND_OFFLOAD)) { 1964 printf("Error, as QinQ hasn't been enabled.\n"); 1965 return; 1966 } 1967 1968 tx_vlan_reset(port_id); 1969 ports[port_id].tx_ol_flags |= TESTPMD_TX_OFFLOAD_INSERT_QINQ; 1970 ports[port_id].tx_vlan_id = vlan_id; 1971 ports[port_id].tx_vlan_id_outer = vlan_id_outer; 1972 } 1973 1974 void 1975 tx_vlan_reset(portid_t port_id) 1976 { 1977 if (port_id_is_invalid(port_id, ENABLED_WARN)) 1978 return; 1979 ports[port_id].tx_ol_flags &= ~(TESTPMD_TX_OFFLOAD_INSERT_VLAN | 1980 TESTPMD_TX_OFFLOAD_INSERT_QINQ); 1981 ports[port_id].tx_vlan_id = 0; 1982 ports[port_id].tx_vlan_id_outer = 0; 1983 } 1984 1985 void 1986 tx_vlan_pvid_set(portid_t port_id, uint16_t vlan_id, int on) 1987 { 1988 if (port_id_is_invalid(port_id, ENABLED_WARN)) 1989 return; 1990 1991 rte_eth_dev_set_vlan_pvid(port_id, vlan_id, on); 1992 } 1993 1994 void 1995 set_qmap(portid_t port_id, uint8_t is_rx, uint16_t queue_id, uint8_t map_value) 1996 { 1997 uint16_t i; 1998 uint8_t existing_mapping_found = 0; 1999 2000 if (port_id_is_invalid(port_id, ENABLED_WARN)) 2001 return; 2002 2003 if (is_rx ? (rx_queue_id_is_invalid(queue_id)) : (tx_queue_id_is_invalid(queue_id))) 2004 return; 2005 2006 if (map_value >= RTE_ETHDEV_QUEUE_STAT_CNTRS) { 2007 printf("map_value not in required range 0..%d\n", 2008 RTE_ETHDEV_QUEUE_STAT_CNTRS - 1); 2009 return; 2010 } 2011 2012 if (!is_rx) { /*then tx*/ 2013 for (i = 0; i < nb_tx_queue_stats_mappings; i++) { 2014 if ((tx_queue_stats_mappings[i].port_id == port_id) && 2015 (tx_queue_stats_mappings[i].queue_id == queue_id)) { 2016 tx_queue_stats_mappings[i].stats_counter_id = map_value; 2017 existing_mapping_found = 1; 2018 break; 2019 } 2020 } 2021 if (!existing_mapping_found) { /* A new additional mapping... */ 2022 tx_queue_stats_mappings[nb_tx_queue_stats_mappings].port_id = port_id; 2023 tx_queue_stats_mappings[nb_tx_queue_stats_mappings].queue_id = queue_id; 2024 tx_queue_stats_mappings[nb_tx_queue_stats_mappings].stats_counter_id = map_value; 2025 nb_tx_queue_stats_mappings++; 2026 } 2027 } 2028 else { /*rx*/ 2029 for (i = 0; i < nb_rx_queue_stats_mappings; i++) { 2030 if ((rx_queue_stats_mappings[i].port_id == port_id) && 2031 (rx_queue_stats_mappings[i].queue_id == queue_id)) { 2032 rx_queue_stats_mappings[i].stats_counter_id = map_value; 2033 existing_mapping_found = 1; 2034 break; 2035 } 2036 } 2037 if (!existing_mapping_found) { /* A new additional mapping... */ 2038 rx_queue_stats_mappings[nb_rx_queue_stats_mappings].port_id = port_id; 2039 rx_queue_stats_mappings[nb_rx_queue_stats_mappings].queue_id = queue_id; 2040 rx_queue_stats_mappings[nb_rx_queue_stats_mappings].stats_counter_id = map_value; 2041 nb_rx_queue_stats_mappings++; 2042 } 2043 } 2044 } 2045 2046 static inline void 2047 print_fdir_mask(struct rte_eth_fdir_masks *mask) 2048 { 2049 printf("\n vlan_tci: 0x%04x, ", mask->vlan_tci_mask); 2050 2051 if (fdir_conf.mode == RTE_FDIR_MODE_PERFECT_MAC_VLAN) 2052 printf("mac_addr: 0x%02x", mask->mac_addr_byte_mask); 2053 else if (fdir_conf.mode == RTE_FDIR_MODE_PERFECT_TUNNEL) 2054 printf("mac_addr: 0x%02x, tunnel_type: 0x%01x, tunnel_id: 0x%08x", 2055 mask->mac_addr_byte_mask, mask->tunnel_type_mask, 2056 mask->tunnel_id_mask); 2057 else { 2058 printf("src_ipv4: 0x%08x, dst_ipv4: 0x%08x," 2059 " src_port: 0x%04x, dst_port: 0x%04x", 2060 mask->ipv4_mask.src_ip, mask->ipv4_mask.dst_ip, 2061 mask->src_port_mask, mask->dst_port_mask); 2062 2063 printf("\n src_ipv6: 0x%08x,0x%08x,0x%08x,0x%08x," 2064 " dst_ipv6: 0x%08x,0x%08x,0x%08x,0x%08x", 2065 mask->ipv6_mask.src_ip[0], mask->ipv6_mask.src_ip[1], 2066 mask->ipv6_mask.src_ip[2], mask->ipv6_mask.src_ip[3], 2067 mask->ipv6_mask.dst_ip[0], mask->ipv6_mask.dst_ip[1], 2068 mask->ipv6_mask.dst_ip[2], mask->ipv6_mask.dst_ip[3]); 2069 } 2070 2071 printf("\n"); 2072 } 2073 2074 static inline void 2075 print_fdir_flex_payload(struct rte_eth_fdir_flex_conf *flex_conf, uint32_t num) 2076 { 2077 struct rte_eth_flex_payload_cfg *cfg; 2078 uint32_t i, j; 2079 2080 for (i = 0; i < flex_conf->nb_payloads; i++) { 2081 cfg = &flex_conf->flex_set[i]; 2082 if (cfg->type == RTE_ETH_RAW_PAYLOAD) 2083 printf("\n RAW: "); 2084 else if (cfg->type == RTE_ETH_L2_PAYLOAD) 2085 printf("\n L2_PAYLOAD: "); 2086 else if (cfg->type == RTE_ETH_L3_PAYLOAD) 2087 printf("\n L3_PAYLOAD: "); 2088 else if (cfg->type == RTE_ETH_L4_PAYLOAD) 2089 printf("\n L4_PAYLOAD: "); 2090 else 2091 printf("\n UNKNOWN PAYLOAD(%u): ", cfg->type); 2092 for (j = 0; j < num; j++) 2093 printf(" %-5u", cfg->src_offset[j]); 2094 } 2095 printf("\n"); 2096 } 2097 2098 static char * 2099 flowtype_to_str(uint16_t flow_type) 2100 { 2101 struct flow_type_info { 2102 char str[32]; 2103 uint16_t ftype; 2104 }; 2105 2106 uint8_t i; 2107 static struct flow_type_info flowtype_str_table[] = { 2108 {"raw", RTE_ETH_FLOW_RAW}, 2109 {"ipv4", RTE_ETH_FLOW_IPV4}, 2110 {"ipv4-frag", RTE_ETH_FLOW_FRAG_IPV4}, 2111 {"ipv4-tcp", RTE_ETH_FLOW_NONFRAG_IPV4_TCP}, 2112 {"ipv4-udp", RTE_ETH_FLOW_NONFRAG_IPV4_UDP}, 2113 {"ipv4-sctp", RTE_ETH_FLOW_NONFRAG_IPV4_SCTP}, 2114 {"ipv4-other", RTE_ETH_FLOW_NONFRAG_IPV4_OTHER}, 2115 {"ipv6", RTE_ETH_FLOW_IPV6}, 2116 {"ipv6-frag", RTE_ETH_FLOW_FRAG_IPV6}, 2117 {"ipv6-tcp", RTE_ETH_FLOW_NONFRAG_IPV6_TCP}, 2118 {"ipv6-udp", RTE_ETH_FLOW_NONFRAG_IPV6_UDP}, 2119 {"ipv6-sctp", RTE_ETH_FLOW_NONFRAG_IPV6_SCTP}, 2120 {"ipv6-other", RTE_ETH_FLOW_NONFRAG_IPV6_OTHER}, 2121 {"l2_payload", RTE_ETH_FLOW_L2_PAYLOAD}, 2122 {"port", RTE_ETH_FLOW_PORT}, 2123 {"vxlan", RTE_ETH_FLOW_VXLAN}, 2124 {"geneve", RTE_ETH_FLOW_GENEVE}, 2125 {"nvgre", RTE_ETH_FLOW_NVGRE}, 2126 }; 2127 2128 for (i = 0; i < RTE_DIM(flowtype_str_table); i++) { 2129 if (flowtype_str_table[i].ftype == flow_type) 2130 return flowtype_str_table[i].str; 2131 } 2132 2133 return NULL; 2134 } 2135 2136 static inline void 2137 print_fdir_flex_mask(struct rte_eth_fdir_flex_conf *flex_conf, uint32_t num) 2138 { 2139 struct rte_eth_fdir_flex_mask *mask; 2140 uint32_t i, j; 2141 char *p; 2142 2143 for (i = 0; i < flex_conf->nb_flexmasks; i++) { 2144 mask = &flex_conf->flex_mask[i]; 2145 p = flowtype_to_str(mask->flow_type); 2146 printf("\n %s:\t", p ? p : "unknown"); 2147 for (j = 0; j < num; j++) 2148 printf(" %02x", mask->mask[j]); 2149 } 2150 printf("\n"); 2151 } 2152 2153 static inline void 2154 print_fdir_flow_type(uint32_t flow_types_mask) 2155 { 2156 int i; 2157 char *p; 2158 2159 for (i = RTE_ETH_FLOW_UNKNOWN; i < RTE_ETH_FLOW_MAX; i++) { 2160 if (!(flow_types_mask & (1 << i))) 2161 continue; 2162 p = flowtype_to_str(i); 2163 if (p) 2164 printf(" %s", p); 2165 else 2166 printf(" unknown"); 2167 } 2168 printf("\n"); 2169 } 2170 2171 void 2172 fdir_get_infos(portid_t port_id) 2173 { 2174 struct rte_eth_fdir_stats fdir_stat; 2175 struct rte_eth_fdir_info fdir_info; 2176 int ret; 2177 2178 static const char *fdir_stats_border = "########################"; 2179 2180 if (port_id_is_invalid(port_id, ENABLED_WARN)) 2181 return; 2182 ret = rte_eth_dev_filter_supported(port_id, RTE_ETH_FILTER_FDIR); 2183 if (ret < 0) { 2184 printf("\n FDIR is not supported on port %-2d\n", 2185 port_id); 2186 return; 2187 } 2188 2189 memset(&fdir_info, 0, sizeof(fdir_info)); 2190 rte_eth_dev_filter_ctrl(port_id, RTE_ETH_FILTER_FDIR, 2191 RTE_ETH_FILTER_INFO, &fdir_info); 2192 memset(&fdir_stat, 0, sizeof(fdir_stat)); 2193 rte_eth_dev_filter_ctrl(port_id, RTE_ETH_FILTER_FDIR, 2194 RTE_ETH_FILTER_STATS, &fdir_stat); 2195 printf("\n %s FDIR infos for port %-2d %s\n", 2196 fdir_stats_border, port_id, fdir_stats_border); 2197 printf(" MODE: "); 2198 if (fdir_info.mode == RTE_FDIR_MODE_PERFECT) 2199 printf(" PERFECT\n"); 2200 else if (fdir_info.mode == RTE_FDIR_MODE_PERFECT_MAC_VLAN) 2201 printf(" PERFECT-MAC-VLAN\n"); 2202 else if (fdir_info.mode == RTE_FDIR_MODE_PERFECT_TUNNEL) 2203 printf(" PERFECT-TUNNEL\n"); 2204 else if (fdir_info.mode == RTE_FDIR_MODE_SIGNATURE) 2205 printf(" SIGNATURE\n"); 2206 else 2207 printf(" DISABLE\n"); 2208 if (fdir_info.mode != RTE_FDIR_MODE_PERFECT_MAC_VLAN 2209 && fdir_info.mode != RTE_FDIR_MODE_PERFECT_TUNNEL) { 2210 printf(" SUPPORTED FLOW TYPE: "); 2211 print_fdir_flow_type(fdir_info.flow_types_mask[0]); 2212 } 2213 printf(" FLEX PAYLOAD INFO:\n"); 2214 printf(" max_len: %-10"PRIu32" payload_limit: %-10"PRIu32"\n" 2215 " payload_unit: %-10"PRIu32" payload_seg: %-10"PRIu32"\n" 2216 " bitmask_unit: %-10"PRIu32" bitmask_num: %-10"PRIu32"\n", 2217 fdir_info.max_flexpayload, fdir_info.flex_payload_limit, 2218 fdir_info.flex_payload_unit, 2219 fdir_info.max_flex_payload_segment_num, 2220 fdir_info.flex_bitmask_unit, fdir_info.max_flex_bitmask_num); 2221 printf(" MASK: "); 2222 print_fdir_mask(&fdir_info.mask); 2223 if (fdir_info.flex_conf.nb_payloads > 0) { 2224 printf(" FLEX PAYLOAD SRC OFFSET:"); 2225 print_fdir_flex_payload(&fdir_info.flex_conf, fdir_info.max_flexpayload); 2226 } 2227 if (fdir_info.flex_conf.nb_flexmasks > 0) { 2228 printf(" FLEX MASK CFG:"); 2229 print_fdir_flex_mask(&fdir_info.flex_conf, fdir_info.max_flexpayload); 2230 } 2231 printf(" guarant_count: %-10"PRIu32" best_count: %"PRIu32"\n", 2232 fdir_stat.guarant_cnt, fdir_stat.best_cnt); 2233 printf(" guarant_space: %-10"PRIu32" best_space: %"PRIu32"\n", 2234 fdir_info.guarant_spc, fdir_info.best_spc); 2235 printf(" collision: %-10"PRIu32" free: %"PRIu32"\n" 2236 " maxhash: %-10"PRIu32" maxlen: %"PRIu32"\n" 2237 " add: %-10"PRIu64" remove: %"PRIu64"\n" 2238 " f_add: %-10"PRIu64" f_remove: %"PRIu64"\n", 2239 fdir_stat.collision, fdir_stat.free, 2240 fdir_stat.maxhash, fdir_stat.maxlen, 2241 fdir_stat.add, fdir_stat.remove, 2242 fdir_stat.f_add, fdir_stat.f_remove); 2243 printf(" %s############################%s\n", 2244 fdir_stats_border, fdir_stats_border); 2245 } 2246 2247 void 2248 fdir_set_flex_mask(portid_t port_id, struct rte_eth_fdir_flex_mask *cfg) 2249 { 2250 struct rte_port *port; 2251 struct rte_eth_fdir_flex_conf *flex_conf; 2252 int i, idx = 0; 2253 2254 port = &ports[port_id]; 2255 flex_conf = &port->dev_conf.fdir_conf.flex_conf; 2256 for (i = 0; i < RTE_ETH_FLOW_MAX; i++) { 2257 if (cfg->flow_type == flex_conf->flex_mask[i].flow_type) { 2258 idx = i; 2259 break; 2260 } 2261 } 2262 if (i >= RTE_ETH_FLOW_MAX) { 2263 if (flex_conf->nb_flexmasks < RTE_DIM(flex_conf->flex_mask)) { 2264 idx = flex_conf->nb_flexmasks; 2265 flex_conf->nb_flexmasks++; 2266 } else { 2267 printf("The flex mask table is full. Can not set flex" 2268 " mask for flow_type(%u).", cfg->flow_type); 2269 return; 2270 } 2271 } 2272 (void)rte_memcpy(&flex_conf->flex_mask[idx], 2273 cfg, 2274 sizeof(struct rte_eth_fdir_flex_mask)); 2275 } 2276 2277 void 2278 fdir_set_flex_payload(portid_t port_id, struct rte_eth_flex_payload_cfg *cfg) 2279 { 2280 struct rte_port *port; 2281 struct rte_eth_fdir_flex_conf *flex_conf; 2282 int i, idx = 0; 2283 2284 port = &ports[port_id]; 2285 flex_conf = &port->dev_conf.fdir_conf.flex_conf; 2286 for (i = 0; i < RTE_ETH_PAYLOAD_MAX; i++) { 2287 if (cfg->type == flex_conf->flex_set[i].type) { 2288 idx = i; 2289 break; 2290 } 2291 } 2292 if (i >= RTE_ETH_PAYLOAD_MAX) { 2293 if (flex_conf->nb_payloads < RTE_DIM(flex_conf->flex_set)) { 2294 idx = flex_conf->nb_payloads; 2295 flex_conf->nb_payloads++; 2296 } else { 2297 printf("The flex payload table is full. Can not set" 2298 " flex payload for type(%u).", cfg->type); 2299 return; 2300 } 2301 } 2302 (void)rte_memcpy(&flex_conf->flex_set[idx], 2303 cfg, 2304 sizeof(struct rte_eth_flex_payload_cfg)); 2305 2306 } 2307 2308 void 2309 set_vf_traffic(portid_t port_id, uint8_t is_rx, uint16_t vf, uint8_t on) 2310 { 2311 int diag; 2312 2313 if (port_id_is_invalid(port_id, ENABLED_WARN)) 2314 return; 2315 if (is_rx) 2316 diag = rte_eth_dev_set_vf_rx(port_id,vf,on); 2317 else 2318 diag = rte_eth_dev_set_vf_tx(port_id,vf,on); 2319 if (diag == 0) 2320 return; 2321 if(is_rx) 2322 printf("rte_eth_dev_set_vf_rx for port_id=%d failed " 2323 "diag=%d\n", port_id, diag); 2324 else 2325 printf("rte_eth_dev_set_vf_tx for port_id=%d failed " 2326 "diag=%d\n", port_id, diag); 2327 2328 } 2329 2330 void 2331 set_vf_rx_vlan(portid_t port_id, uint16_t vlan_id, uint64_t vf_mask, uint8_t on) 2332 { 2333 int diag; 2334 2335 if (port_id_is_invalid(port_id, ENABLED_WARN)) 2336 return; 2337 if (vlan_id_is_invalid(vlan_id)) 2338 return; 2339 diag = rte_eth_dev_set_vf_vlan_filter(port_id, vlan_id, vf_mask, on); 2340 if (diag == 0) 2341 return; 2342 printf("rte_eth_dev_set_vf_vlan_filter for port_id=%d failed " 2343 "diag=%d\n", port_id, diag); 2344 } 2345 2346 int 2347 set_queue_rate_limit(portid_t port_id, uint16_t queue_idx, uint16_t rate) 2348 { 2349 int diag; 2350 struct rte_eth_link link; 2351 2352 if (port_id_is_invalid(port_id, ENABLED_WARN)) 2353 return 1; 2354 rte_eth_link_get_nowait(port_id, &link); 2355 if (rate > link.link_speed) { 2356 printf("Invalid rate value:%u bigger than link speed: %u\n", 2357 rate, link.link_speed); 2358 return 1; 2359 } 2360 diag = rte_eth_set_queue_rate_limit(port_id, queue_idx, rate); 2361 if (diag == 0) 2362 return diag; 2363 printf("rte_eth_set_queue_rate_limit for port_id=%d failed diag=%d\n", 2364 port_id, diag); 2365 return diag; 2366 } 2367 2368 int 2369 set_vf_rate_limit(portid_t port_id, uint16_t vf, uint16_t rate, uint64_t q_msk) 2370 { 2371 int diag; 2372 struct rte_eth_link link; 2373 2374 if (q_msk == 0) 2375 return 0; 2376 2377 if (port_id_is_invalid(port_id, ENABLED_WARN)) 2378 return 1; 2379 rte_eth_link_get_nowait(port_id, &link); 2380 if (rate > link.link_speed) { 2381 printf("Invalid rate value:%u bigger than link speed: %u\n", 2382 rate, link.link_speed); 2383 return 1; 2384 } 2385 diag = rte_eth_set_vf_rate_limit(port_id, vf, rate, q_msk); 2386 if (diag == 0) 2387 return diag; 2388 printf("rte_eth_set_vf_rate_limit for port_id=%d failed diag=%d\n", 2389 port_id, diag); 2390 return diag; 2391 } 2392 2393 /* 2394 * Functions to manage the set of filtered Multicast MAC addresses. 2395 * 2396 * A pool of filtered multicast MAC addresses is associated with each port. 2397 * The pool is allocated in chunks of MCAST_POOL_INC multicast addresses. 2398 * The address of the pool and the number of valid multicast MAC addresses 2399 * recorded in the pool are stored in the fields "mc_addr_pool" and 2400 * "mc_addr_nb" of the "rte_port" data structure. 2401 * 2402 * The function "rte_eth_dev_set_mc_addr_list" of the PMDs API imposes 2403 * to be supplied a contiguous array of multicast MAC addresses. 2404 * To comply with this constraint, the set of multicast addresses recorded 2405 * into the pool are systematically compacted at the beginning of the pool. 2406 * Hence, when a multicast address is removed from the pool, all following 2407 * addresses, if any, are copied back to keep the set contiguous. 2408 */ 2409 #define MCAST_POOL_INC 32 2410 2411 static int 2412 mcast_addr_pool_extend(struct rte_port *port) 2413 { 2414 struct ether_addr *mc_pool; 2415 size_t mc_pool_size; 2416 2417 /* 2418 * If a free entry is available at the end of the pool, just 2419 * increment the number of recorded multicast addresses. 2420 */ 2421 if ((port->mc_addr_nb % MCAST_POOL_INC) != 0) { 2422 port->mc_addr_nb++; 2423 return 0; 2424 } 2425 2426 /* 2427 * [re]allocate a pool with MCAST_POOL_INC more entries. 2428 * The previous test guarantees that port->mc_addr_nb is a multiple 2429 * of MCAST_POOL_INC. 2430 */ 2431 mc_pool_size = sizeof(struct ether_addr) * (port->mc_addr_nb + 2432 MCAST_POOL_INC); 2433 mc_pool = (struct ether_addr *) realloc(port->mc_addr_pool, 2434 mc_pool_size); 2435 if (mc_pool == NULL) { 2436 printf("allocation of pool of %u multicast addresses failed\n", 2437 port->mc_addr_nb + MCAST_POOL_INC); 2438 return -ENOMEM; 2439 } 2440 2441 port->mc_addr_pool = mc_pool; 2442 port->mc_addr_nb++; 2443 return 0; 2444 2445 } 2446 2447 static void 2448 mcast_addr_pool_remove(struct rte_port *port, uint32_t addr_idx) 2449 { 2450 port->mc_addr_nb--; 2451 if (addr_idx == port->mc_addr_nb) { 2452 /* No need to recompact the set of multicast addressses. */ 2453 if (port->mc_addr_nb == 0) { 2454 /* free the pool of multicast addresses. */ 2455 free(port->mc_addr_pool); 2456 port->mc_addr_pool = NULL; 2457 } 2458 return; 2459 } 2460 memmove(&port->mc_addr_pool[addr_idx], 2461 &port->mc_addr_pool[addr_idx + 1], 2462 sizeof(struct ether_addr) * (port->mc_addr_nb - addr_idx)); 2463 } 2464 2465 static void 2466 eth_port_multicast_addr_list_set(uint8_t port_id) 2467 { 2468 struct rte_port *port; 2469 int diag; 2470 2471 port = &ports[port_id]; 2472 diag = rte_eth_dev_set_mc_addr_list(port_id, port->mc_addr_pool, 2473 port->mc_addr_nb); 2474 if (diag == 0) 2475 return; 2476 printf("rte_eth_dev_set_mc_addr_list(port=%d, nb=%u) failed. diag=%d\n", 2477 port->mc_addr_nb, port_id, -diag); 2478 } 2479 2480 void 2481 mcast_addr_add(uint8_t port_id, struct ether_addr *mc_addr) 2482 { 2483 struct rte_port *port; 2484 uint32_t i; 2485 2486 if (port_id_is_invalid(port_id, ENABLED_WARN)) 2487 return; 2488 2489 port = &ports[port_id]; 2490 2491 /* 2492 * Check that the added multicast MAC address is not already recorded 2493 * in the pool of multicast addresses. 2494 */ 2495 for (i = 0; i < port->mc_addr_nb; i++) { 2496 if (is_same_ether_addr(mc_addr, &port->mc_addr_pool[i])) { 2497 printf("multicast address already filtered by port\n"); 2498 return; 2499 } 2500 } 2501 2502 if (mcast_addr_pool_extend(port) != 0) 2503 return; 2504 ether_addr_copy(mc_addr, &port->mc_addr_pool[i]); 2505 eth_port_multicast_addr_list_set(port_id); 2506 } 2507 2508 void 2509 mcast_addr_remove(uint8_t port_id, struct ether_addr *mc_addr) 2510 { 2511 struct rte_port *port; 2512 uint32_t i; 2513 2514 if (port_id_is_invalid(port_id, ENABLED_WARN)) 2515 return; 2516 2517 port = &ports[port_id]; 2518 2519 /* 2520 * Search the pool of multicast MAC addresses for the removed address. 2521 */ 2522 for (i = 0; i < port->mc_addr_nb; i++) { 2523 if (is_same_ether_addr(mc_addr, &port->mc_addr_pool[i])) 2524 break; 2525 } 2526 if (i == port->mc_addr_nb) { 2527 printf("multicast address not filtered by port %d\n", port_id); 2528 return; 2529 } 2530 2531 mcast_addr_pool_remove(port, i); 2532 eth_port_multicast_addr_list_set(port_id); 2533 } 2534 2535 void 2536 port_dcb_info_display(uint8_t port_id) 2537 { 2538 struct rte_eth_dcb_info dcb_info; 2539 uint16_t i; 2540 int ret; 2541 static const char *border = "================"; 2542 2543 if (port_id_is_invalid(port_id, ENABLED_WARN)) 2544 return; 2545 2546 ret = rte_eth_dev_get_dcb_info(port_id, &dcb_info); 2547 if (ret) { 2548 printf("\n Failed to get dcb infos on port %-2d\n", 2549 port_id); 2550 return; 2551 } 2552 printf("\n %s DCB infos for port %-2d %s\n", border, port_id, border); 2553 printf(" TC NUMBER: %d\n", dcb_info.nb_tcs); 2554 printf("\n TC : "); 2555 for (i = 0; i < dcb_info.nb_tcs; i++) 2556 printf("\t%4d", i); 2557 printf("\n Priority : "); 2558 for (i = 0; i < dcb_info.nb_tcs; i++) 2559 printf("\t%4d", dcb_info.prio_tc[i]); 2560 printf("\n BW percent :"); 2561 for (i = 0; i < dcb_info.nb_tcs; i++) 2562 printf("\t%4d%%", dcb_info.tc_bws[i]); 2563 printf("\n RXQ base : "); 2564 for (i = 0; i < dcb_info.nb_tcs; i++) 2565 printf("\t%4d", dcb_info.tc_queue.tc_rxq[0][i].base); 2566 printf("\n RXQ number :"); 2567 for (i = 0; i < dcb_info.nb_tcs; i++) 2568 printf("\t%4d", dcb_info.tc_queue.tc_rxq[0][i].nb_queue); 2569 printf("\n TXQ base : "); 2570 for (i = 0; i < dcb_info.nb_tcs; i++) 2571 printf("\t%4d", dcb_info.tc_queue.tc_txq[0][i].base); 2572 printf("\n TXQ number :"); 2573 for (i = 0; i < dcb_info.nb_tcs; i++) 2574 printf("\t%4d", dcb_info.tc_queue.tc_txq[0][i].nb_queue); 2575 printf("\n"); 2576 } 2577