1 /*- 2 * BSD LICENSE 3 * 4 * Copyright(c) 2010-2014 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_tailq.h> 83 #include <rte_eal.h> 84 #include <rte_per_lcore.h> 85 #include <rte_lcore.h> 86 #include <rte_atomic.h> 87 #include <rte_branch_prediction.h> 88 #include <rte_ring.h> 89 #include <rte_mempool.h> 90 #include <rte_mbuf.h> 91 #include <rte_interrupts.h> 92 #include <rte_pci.h> 93 #include <rte_ether.h> 94 #include <rte_ethdev.h> 95 #include <rte_string_fns.h> 96 97 #include "testpmd.h" 98 99 static char *flowtype_to_str(uint16_t flow_type); 100 101 static void 102 print_ethaddr(const char *name, struct ether_addr *eth_addr) 103 { 104 char buf[ETHER_ADDR_FMT_SIZE]; 105 ether_format_addr(buf, ETHER_ADDR_FMT_SIZE, eth_addr); 106 printf("%s%s", name, buf); 107 } 108 109 void 110 nic_stats_display(portid_t port_id) 111 { 112 struct rte_eth_stats stats; 113 struct rte_port *port = &ports[port_id]; 114 uint8_t i; 115 portid_t pid; 116 117 static const char *nic_stats_border = "########################"; 118 119 if (port_id_is_invalid(port_id, ENABLED_WARN)) { 120 printf("Valid port range is [0"); 121 FOREACH_PORT(pid, ports) 122 printf(", %d", pid); 123 printf("]\n"); 124 return; 125 } 126 rte_eth_stats_get(port_id, &stats); 127 printf("\n %s NIC statistics for port %-2d %s\n", 128 nic_stats_border, port_id, nic_stats_border); 129 130 if ((!port->rx_queue_stats_mapping_enabled) && (!port->tx_queue_stats_mapping_enabled)) { 131 printf(" RX-packets: %-10"PRIu64" RX-missed: %-10"PRIu64" RX-bytes: " 132 "%-"PRIu64"\n", 133 stats.ipackets, stats.imissed, stats.ibytes); 134 printf(" RX-badcrc: %-10"PRIu64" RX-badlen: %-10"PRIu64" RX-errors: " 135 "%-"PRIu64"\n", 136 stats.ibadcrc, stats.ibadlen, stats.ierrors); 137 printf(" RX-nombuf: %-10"PRIu64"\n", 138 stats.rx_nombuf); 139 printf(" TX-packets: %-10"PRIu64" TX-errors: %-10"PRIu64" TX-bytes: " 140 "%-"PRIu64"\n", 141 stats.opackets, stats.oerrors, stats.obytes); 142 } 143 else { 144 printf(" RX-packets: %10"PRIu64" RX-errors: %10"PRIu64 145 " RX-bytes: %10"PRIu64"\n", 146 stats.ipackets, stats.ierrors, stats.ibytes); 147 printf(" RX-badcrc: %10"PRIu64" RX-badlen: %10"PRIu64 148 " RX-errors: %10"PRIu64"\n", 149 stats.ibadcrc, stats.ibadlen, stats.ierrors); 150 printf(" RX-nombuf: %10"PRIu64"\n", 151 stats.rx_nombuf); 152 printf(" TX-packets: %10"PRIu64" TX-errors: %10"PRIu64 153 " TX-bytes: %10"PRIu64"\n", 154 stats.opackets, stats.oerrors, stats.obytes); 155 } 156 157 /* stats fdir */ 158 if (fdir_conf.mode != RTE_FDIR_MODE_NONE) 159 printf(" Fdirmiss: %-10"PRIu64" Fdirmatch: %-10"PRIu64"\n", 160 stats.fdirmiss, 161 stats.fdirmatch); 162 163 if (port->rx_queue_stats_mapping_enabled) { 164 printf("\n"); 165 for (i = 0; i < RTE_ETHDEV_QUEUE_STAT_CNTRS; i++) { 166 printf(" Stats reg %2d RX-packets: %10"PRIu64 167 " RX-errors: %10"PRIu64 168 " RX-bytes: %10"PRIu64"\n", 169 i, stats.q_ipackets[i], stats.q_errors[i], stats.q_ibytes[i]); 170 } 171 } 172 if (port->tx_queue_stats_mapping_enabled) { 173 printf("\n"); 174 for (i = 0; i < RTE_ETHDEV_QUEUE_STAT_CNTRS; i++) { 175 printf(" Stats reg %2d TX-packets: %10"PRIu64 176 " TX-bytes: %10"PRIu64"\n", 177 i, stats.q_opackets[i], stats.q_obytes[i]); 178 } 179 } 180 181 /* Display statistics of XON/XOFF pause frames, if any. */ 182 if ((stats.tx_pause_xon | stats.rx_pause_xon | 183 stats.tx_pause_xoff | stats.rx_pause_xoff) > 0) { 184 printf(" RX-XOFF: %-10"PRIu64" RX-XON: %-10"PRIu64"\n", 185 stats.rx_pause_xoff, stats.rx_pause_xon); 186 printf(" TX-XOFF: %-10"PRIu64" TX-XON: %-10"PRIu64"\n", 187 stats.tx_pause_xoff, stats.tx_pause_xon); 188 } 189 printf(" %s############################%s\n", 190 nic_stats_border, nic_stats_border); 191 } 192 193 void 194 nic_stats_clear(portid_t port_id) 195 { 196 portid_t pid; 197 198 if (port_id_is_invalid(port_id, ENABLED_WARN)) { 199 printf("Valid port range is [0"); 200 FOREACH_PORT(pid, ports) 201 printf(", %d", pid); 202 printf("]\n"); 203 return; 204 } 205 rte_eth_stats_reset(port_id); 206 printf("\n NIC statistics for port %d cleared\n", port_id); 207 } 208 209 void 210 nic_xstats_display(portid_t port_id) 211 { 212 struct rte_eth_xstats *xstats; 213 int len, ret, i; 214 215 printf("###### NIC extended statistics for port %-2d\n", port_id); 216 217 len = rte_eth_xstats_get(port_id, NULL, 0); 218 if (len < 0) { 219 printf("Cannot get xstats count\n"); 220 return; 221 } 222 xstats = malloc(sizeof(xstats[0]) * len); 223 if (xstats == NULL) { 224 printf("Cannot allocate memory for xstats\n"); 225 return; 226 } 227 ret = rte_eth_xstats_get(port_id, xstats, len); 228 if (ret < 0 || ret > len) { 229 printf("Cannot get xstats\n"); 230 free(xstats); 231 return; 232 } 233 for (i = 0; i < len; i++) 234 printf("%s: %"PRIu64"\n", xstats[i].name, xstats[i].value); 235 free(xstats); 236 } 237 238 void 239 nic_xstats_clear(portid_t port_id) 240 { 241 rte_eth_xstats_reset(port_id); 242 } 243 244 void 245 nic_stats_mapping_display(portid_t port_id) 246 { 247 struct rte_port *port = &ports[port_id]; 248 uint16_t i; 249 portid_t pid; 250 251 static const char *nic_stats_mapping_border = "########################"; 252 253 if (port_id_is_invalid(port_id, ENABLED_WARN)) { 254 printf("Valid port range is [0"); 255 FOREACH_PORT(pid, ports) 256 printf(", %d", pid); 257 printf("]\n"); 258 return; 259 } 260 261 if ((!port->rx_queue_stats_mapping_enabled) && (!port->tx_queue_stats_mapping_enabled)) { 262 printf("Port id %d - either does not support queue statistic mapping or" 263 " no queue statistic mapping set\n", port_id); 264 return; 265 } 266 267 printf("\n %s NIC statistics mapping for port %-2d %s\n", 268 nic_stats_mapping_border, port_id, nic_stats_mapping_border); 269 270 if (port->rx_queue_stats_mapping_enabled) { 271 for (i = 0; i < nb_rx_queue_stats_mappings; i++) { 272 if (rx_queue_stats_mappings[i].port_id == port_id) { 273 printf(" RX-queue %2d mapped to Stats Reg %2d\n", 274 rx_queue_stats_mappings[i].queue_id, 275 rx_queue_stats_mappings[i].stats_counter_id); 276 } 277 } 278 printf("\n"); 279 } 280 281 282 if (port->tx_queue_stats_mapping_enabled) { 283 for (i = 0; i < nb_tx_queue_stats_mappings; i++) { 284 if (tx_queue_stats_mappings[i].port_id == port_id) { 285 printf(" TX-queue %2d mapped to Stats Reg %2d\n", 286 tx_queue_stats_mappings[i].queue_id, 287 tx_queue_stats_mappings[i].stats_counter_id); 288 } 289 } 290 } 291 292 printf(" %s####################################%s\n", 293 nic_stats_mapping_border, nic_stats_mapping_border); 294 } 295 296 void 297 port_infos_display(portid_t port_id) 298 { 299 struct rte_port *port; 300 struct ether_addr mac_addr; 301 struct rte_eth_link link; 302 struct rte_eth_dev_info dev_info; 303 int vlan_offload; 304 struct rte_mempool * mp; 305 static const char *info_border = "*********************"; 306 portid_t pid; 307 308 if (port_id_is_invalid(port_id, ENABLED_WARN)) { 309 printf("Valid port range is [0"); 310 FOREACH_PORT(pid, ports) 311 printf(", %d", pid); 312 printf("]\n"); 313 return; 314 } 315 port = &ports[port_id]; 316 rte_eth_link_get_nowait(port_id, &link); 317 printf("\n%s Infos for port %-2d %s\n", 318 info_border, port_id, info_border); 319 rte_eth_macaddr_get(port_id, &mac_addr); 320 print_ethaddr("MAC address: ", &mac_addr); 321 printf("\nConnect to socket: %u", port->socket_id); 322 323 if (port_numa[port_id] != NUMA_NO_CONFIG) { 324 mp = mbuf_pool_find(port_numa[port_id]); 325 if (mp) 326 printf("\nmemory allocation on the socket: %d", 327 port_numa[port_id]); 328 } else 329 printf("\nmemory allocation on the socket: %u",port->socket_id); 330 331 printf("\nLink status: %s\n", (link.link_status) ? ("up") : ("down")); 332 printf("Link speed: %u Mbps\n", (unsigned) link.link_speed); 333 printf("Link duplex: %s\n", (link.link_duplex == ETH_LINK_FULL_DUPLEX) ? 334 ("full-duplex") : ("half-duplex")); 335 printf("Promiscuous mode: %s\n", 336 rte_eth_promiscuous_get(port_id) ? "enabled" : "disabled"); 337 printf("Allmulticast mode: %s\n", 338 rte_eth_allmulticast_get(port_id) ? "enabled" : "disabled"); 339 printf("Maximum number of MAC addresses: %u\n", 340 (unsigned int)(port->dev_info.max_mac_addrs)); 341 printf("Maximum number of MAC addresses of hash filtering: %u\n", 342 (unsigned int)(port->dev_info.max_hash_mac_addrs)); 343 344 vlan_offload = rte_eth_dev_get_vlan_offload(port_id); 345 if (vlan_offload >= 0){ 346 printf("VLAN offload: \n"); 347 if (vlan_offload & ETH_VLAN_STRIP_OFFLOAD) 348 printf(" strip on \n"); 349 else 350 printf(" strip off \n"); 351 352 if (vlan_offload & ETH_VLAN_FILTER_OFFLOAD) 353 printf(" filter on \n"); 354 else 355 printf(" filter off \n"); 356 357 if (vlan_offload & ETH_VLAN_EXTEND_OFFLOAD) 358 printf(" qinq(extend) on \n"); 359 else 360 printf(" qinq(extend) off \n"); 361 } 362 363 memset(&dev_info, 0, sizeof(dev_info)); 364 rte_eth_dev_info_get(port_id, &dev_info); 365 if (dev_info.reta_size > 0) 366 printf("Redirection table size: %u\n", dev_info.reta_size); 367 if (!dev_info.flow_type_rss_offloads) 368 printf("No flow type is supported.\n"); 369 else { 370 uint16_t i; 371 char *p; 372 373 printf("Supported flow types:\n"); 374 for (i = RTE_ETH_FLOW_UNKNOWN + 1; i < RTE_ETH_FLOW_MAX; 375 i++) { 376 if (!(dev_info.flow_type_rss_offloads & (1ULL << i))) 377 continue; 378 p = flowtype_to_str(i); 379 printf(" %s\n", (p ? p : "unknown")); 380 } 381 } 382 } 383 384 int 385 port_id_is_invalid(portid_t port_id, enum print_warning warning) 386 { 387 if (ports[port_id].enabled) 388 return 0; 389 390 if (warning == ENABLED_WARN) 391 printf("Invalid port %d\n", port_id); 392 393 return 1; 394 } 395 396 static int 397 vlan_id_is_invalid(uint16_t vlan_id) 398 { 399 if (vlan_id < 4096) 400 return 0; 401 printf("Invalid vlan_id %d (must be < 4096)\n", vlan_id); 402 return 1; 403 } 404 405 static int 406 port_reg_off_is_invalid(portid_t port_id, uint32_t reg_off) 407 { 408 uint64_t pci_len; 409 410 if (reg_off & 0x3) { 411 printf("Port register offset 0x%X not aligned on a 4-byte " 412 "boundary\n", 413 (unsigned)reg_off); 414 return 1; 415 } 416 pci_len = ports[port_id].dev_info.pci_dev->mem_resource[0].len; 417 if (reg_off >= pci_len) { 418 printf("Port %d: register offset %u (0x%X) out of port PCI " 419 "resource (length=%"PRIu64")\n", 420 port_id, (unsigned)reg_off, (unsigned)reg_off, pci_len); 421 return 1; 422 } 423 return 0; 424 } 425 426 static int 427 reg_bit_pos_is_invalid(uint8_t bit_pos) 428 { 429 if (bit_pos <= 31) 430 return 0; 431 printf("Invalid bit position %d (must be <= 31)\n", bit_pos); 432 return 1; 433 } 434 435 #define display_port_and_reg_off(port_id, reg_off) \ 436 printf("port %d PCI register at offset 0x%X: ", (port_id), (reg_off)) 437 438 static inline void 439 display_port_reg_value(portid_t port_id, uint32_t reg_off, uint32_t reg_v) 440 { 441 display_port_and_reg_off(port_id, (unsigned)reg_off); 442 printf("0x%08X (%u)\n", (unsigned)reg_v, (unsigned)reg_v); 443 } 444 445 void 446 port_reg_bit_display(portid_t port_id, uint32_t reg_off, uint8_t bit_x) 447 { 448 uint32_t reg_v; 449 450 451 if (port_id_is_invalid(port_id, ENABLED_WARN)) 452 return; 453 if (port_reg_off_is_invalid(port_id, reg_off)) 454 return; 455 if (reg_bit_pos_is_invalid(bit_x)) 456 return; 457 reg_v = port_id_pci_reg_read(port_id, reg_off); 458 display_port_and_reg_off(port_id, (unsigned)reg_off); 459 printf("bit %d=%d\n", bit_x, (int) ((reg_v & (1 << bit_x)) >> bit_x)); 460 } 461 462 void 463 port_reg_bit_field_display(portid_t port_id, uint32_t reg_off, 464 uint8_t bit1_pos, uint8_t bit2_pos) 465 { 466 uint32_t reg_v; 467 uint8_t l_bit; 468 uint8_t h_bit; 469 470 if (port_id_is_invalid(port_id, ENABLED_WARN)) 471 return; 472 if (port_reg_off_is_invalid(port_id, reg_off)) 473 return; 474 if (reg_bit_pos_is_invalid(bit1_pos)) 475 return; 476 if (reg_bit_pos_is_invalid(bit2_pos)) 477 return; 478 if (bit1_pos > bit2_pos) 479 l_bit = bit2_pos, h_bit = bit1_pos; 480 else 481 l_bit = bit1_pos, h_bit = bit2_pos; 482 483 reg_v = port_id_pci_reg_read(port_id, reg_off); 484 reg_v >>= l_bit; 485 if (h_bit < 31) 486 reg_v &= ((1 << (h_bit - l_bit + 1)) - 1); 487 display_port_and_reg_off(port_id, (unsigned)reg_off); 488 printf("bits[%d, %d]=0x%0*X (%u)\n", l_bit, h_bit, 489 ((h_bit - l_bit) / 4) + 1, (unsigned)reg_v, (unsigned)reg_v); 490 } 491 492 void 493 port_reg_display(portid_t port_id, uint32_t reg_off) 494 { 495 uint32_t reg_v; 496 497 if (port_id_is_invalid(port_id, ENABLED_WARN)) 498 return; 499 if (port_reg_off_is_invalid(port_id, reg_off)) 500 return; 501 reg_v = port_id_pci_reg_read(port_id, reg_off); 502 display_port_reg_value(port_id, reg_off, reg_v); 503 } 504 505 void 506 port_reg_bit_set(portid_t port_id, uint32_t reg_off, uint8_t bit_pos, 507 uint8_t bit_v) 508 { 509 uint32_t reg_v; 510 511 if (port_id_is_invalid(port_id, ENABLED_WARN)) 512 return; 513 if (port_reg_off_is_invalid(port_id, reg_off)) 514 return; 515 if (reg_bit_pos_is_invalid(bit_pos)) 516 return; 517 if (bit_v > 1) { 518 printf("Invalid bit value %d (must be 0 or 1)\n", (int) bit_v); 519 return; 520 } 521 reg_v = port_id_pci_reg_read(port_id, reg_off); 522 if (bit_v == 0) 523 reg_v &= ~(1 << bit_pos); 524 else 525 reg_v |= (1 << bit_pos); 526 port_id_pci_reg_write(port_id, reg_off, reg_v); 527 display_port_reg_value(port_id, reg_off, reg_v); 528 } 529 530 void 531 port_reg_bit_field_set(portid_t port_id, uint32_t reg_off, 532 uint8_t bit1_pos, uint8_t bit2_pos, uint32_t value) 533 { 534 uint32_t max_v; 535 uint32_t reg_v; 536 uint8_t l_bit; 537 uint8_t h_bit; 538 539 if (port_id_is_invalid(port_id, ENABLED_WARN)) 540 return; 541 if (port_reg_off_is_invalid(port_id, reg_off)) 542 return; 543 if (reg_bit_pos_is_invalid(bit1_pos)) 544 return; 545 if (reg_bit_pos_is_invalid(bit2_pos)) 546 return; 547 if (bit1_pos > bit2_pos) 548 l_bit = bit2_pos, h_bit = bit1_pos; 549 else 550 l_bit = bit1_pos, h_bit = bit2_pos; 551 552 if ((h_bit - l_bit) < 31) 553 max_v = (1 << (h_bit - l_bit + 1)) - 1; 554 else 555 max_v = 0xFFFFFFFF; 556 557 if (value > max_v) { 558 printf("Invalid value %u (0x%x) must be < %u (0x%x)\n", 559 (unsigned)value, (unsigned)value, 560 (unsigned)max_v, (unsigned)max_v); 561 return; 562 } 563 reg_v = port_id_pci_reg_read(port_id, reg_off); 564 reg_v &= ~(max_v << l_bit); /* Keep unchanged bits */ 565 reg_v |= (value << l_bit); /* Set changed bits */ 566 port_id_pci_reg_write(port_id, reg_off, reg_v); 567 display_port_reg_value(port_id, reg_off, reg_v); 568 } 569 570 void 571 port_reg_set(portid_t port_id, uint32_t reg_off, uint32_t reg_v) 572 { 573 if (port_id_is_invalid(port_id, ENABLED_WARN)) 574 return; 575 if (port_reg_off_is_invalid(port_id, reg_off)) 576 return; 577 port_id_pci_reg_write(port_id, reg_off, reg_v); 578 display_port_reg_value(port_id, reg_off, reg_v); 579 } 580 581 void 582 port_mtu_set(portid_t port_id, uint16_t mtu) 583 { 584 int diag; 585 586 if (port_id_is_invalid(port_id, ENABLED_WARN)) 587 return; 588 diag = rte_eth_dev_set_mtu(port_id, mtu); 589 if (diag == 0) 590 return; 591 printf("Set MTU failed. diag=%d\n", diag); 592 } 593 594 /* 595 * RX/TX ring descriptors display functions. 596 */ 597 int 598 rx_queue_id_is_invalid(queueid_t rxq_id) 599 { 600 if (rxq_id < nb_rxq) 601 return 0; 602 printf("Invalid RX queue %d (must be < nb_rxq=%d)\n", rxq_id, nb_rxq); 603 return 1; 604 } 605 606 int 607 tx_queue_id_is_invalid(queueid_t txq_id) 608 { 609 if (txq_id < nb_txq) 610 return 0; 611 printf("Invalid TX queue %d (must be < nb_rxq=%d)\n", txq_id, nb_txq); 612 return 1; 613 } 614 615 static int 616 rx_desc_id_is_invalid(uint16_t rxdesc_id) 617 { 618 if (rxdesc_id < nb_rxd) 619 return 0; 620 printf("Invalid RX descriptor %d (must be < nb_rxd=%d)\n", 621 rxdesc_id, nb_rxd); 622 return 1; 623 } 624 625 static int 626 tx_desc_id_is_invalid(uint16_t txdesc_id) 627 { 628 if (txdesc_id < nb_txd) 629 return 0; 630 printf("Invalid TX descriptor %d (must be < nb_txd=%d)\n", 631 txdesc_id, nb_txd); 632 return 1; 633 } 634 635 static const struct rte_memzone * 636 ring_dma_zone_lookup(const char *ring_name, uint8_t port_id, uint16_t q_id) 637 { 638 char mz_name[RTE_MEMZONE_NAMESIZE]; 639 const struct rte_memzone *mz; 640 641 snprintf(mz_name, sizeof(mz_name), "%s_%s_%d_%d", 642 ports[port_id].dev_info.driver_name, ring_name, port_id, q_id); 643 mz = rte_memzone_lookup(mz_name); 644 if (mz == NULL) 645 printf("%s ring memory zoneof (port %d, queue %d) not" 646 "found (zone name = %s\n", 647 ring_name, port_id, q_id, mz_name); 648 return (mz); 649 } 650 651 union igb_ring_dword { 652 uint64_t dword; 653 struct { 654 #if RTE_BYTE_ORDER == RTE_BIG_ENDIAN 655 uint32_t lo; 656 uint32_t hi; 657 #else 658 uint32_t hi; 659 uint32_t lo; 660 #endif 661 } words; 662 }; 663 664 struct igb_ring_desc_32_bytes { 665 union igb_ring_dword lo_dword; 666 union igb_ring_dword hi_dword; 667 union igb_ring_dword resv1; 668 union igb_ring_dword resv2; 669 }; 670 671 struct igb_ring_desc_16_bytes { 672 union igb_ring_dword lo_dword; 673 union igb_ring_dword hi_dword; 674 }; 675 676 static void 677 ring_rxd_display_dword(union igb_ring_dword dword) 678 { 679 printf(" 0x%08X - 0x%08X\n", (unsigned)dword.words.lo, 680 (unsigned)dword.words.hi); 681 } 682 683 static void 684 ring_rx_descriptor_display(const struct rte_memzone *ring_mz, 685 #ifndef RTE_LIBRTE_I40E_16BYTE_RX_DESC 686 uint8_t port_id, 687 #else 688 __rte_unused uint8_t port_id, 689 #endif 690 uint16_t desc_id) 691 { 692 struct igb_ring_desc_16_bytes *ring = 693 (struct igb_ring_desc_16_bytes *)ring_mz->addr; 694 #ifndef RTE_LIBRTE_I40E_16BYTE_RX_DESC 695 struct rte_eth_dev_info dev_info; 696 697 memset(&dev_info, 0, sizeof(dev_info)); 698 rte_eth_dev_info_get(port_id, &dev_info); 699 if (strstr(dev_info.driver_name, "i40e") != NULL) { 700 /* 32 bytes RX descriptor, i40e only */ 701 struct igb_ring_desc_32_bytes *ring = 702 (struct igb_ring_desc_32_bytes *)ring_mz->addr; 703 ring[desc_id].lo_dword.dword = 704 rte_le_to_cpu_64(ring[desc_id].lo_dword.dword); 705 ring_rxd_display_dword(ring[desc_id].lo_dword); 706 ring[desc_id].hi_dword.dword = 707 rte_le_to_cpu_64(ring[desc_id].hi_dword.dword); 708 ring_rxd_display_dword(ring[desc_id].hi_dword); 709 ring[desc_id].resv1.dword = 710 rte_le_to_cpu_64(ring[desc_id].resv1.dword); 711 ring_rxd_display_dword(ring[desc_id].resv1); 712 ring[desc_id].resv2.dword = 713 rte_le_to_cpu_64(ring[desc_id].resv2.dword); 714 ring_rxd_display_dword(ring[desc_id].resv2); 715 716 return; 717 } 718 #endif 719 /* 16 bytes RX descriptor */ 720 ring[desc_id].lo_dword.dword = 721 rte_le_to_cpu_64(ring[desc_id].lo_dword.dword); 722 ring_rxd_display_dword(ring[desc_id].lo_dword); 723 ring[desc_id].hi_dword.dword = 724 rte_le_to_cpu_64(ring[desc_id].hi_dword.dword); 725 ring_rxd_display_dword(ring[desc_id].hi_dword); 726 } 727 728 static void 729 ring_tx_descriptor_display(const struct rte_memzone *ring_mz, uint16_t desc_id) 730 { 731 struct igb_ring_desc_16_bytes *ring; 732 struct igb_ring_desc_16_bytes txd; 733 734 ring = (struct igb_ring_desc_16_bytes *)ring_mz->addr; 735 txd.lo_dword.dword = rte_le_to_cpu_64(ring[desc_id].lo_dword.dword); 736 txd.hi_dword.dword = rte_le_to_cpu_64(ring[desc_id].hi_dword.dword); 737 printf(" 0x%08X - 0x%08X / 0x%08X - 0x%08X\n", 738 (unsigned)txd.lo_dword.words.lo, 739 (unsigned)txd.lo_dword.words.hi, 740 (unsigned)txd.hi_dword.words.lo, 741 (unsigned)txd.hi_dword.words.hi); 742 } 743 744 void 745 rx_ring_desc_display(portid_t port_id, queueid_t rxq_id, uint16_t rxd_id) 746 { 747 const struct rte_memzone *rx_mz; 748 749 if (port_id_is_invalid(port_id, ENABLED_WARN)) 750 return; 751 if (rx_queue_id_is_invalid(rxq_id)) 752 return; 753 if (rx_desc_id_is_invalid(rxd_id)) 754 return; 755 rx_mz = ring_dma_zone_lookup("rx_ring", port_id, rxq_id); 756 if (rx_mz == NULL) 757 return; 758 ring_rx_descriptor_display(rx_mz, port_id, rxd_id); 759 } 760 761 void 762 tx_ring_desc_display(portid_t port_id, queueid_t txq_id, uint16_t txd_id) 763 { 764 const struct rte_memzone *tx_mz; 765 766 if (port_id_is_invalid(port_id, ENABLED_WARN)) 767 return; 768 if (tx_queue_id_is_invalid(txq_id)) 769 return; 770 if (tx_desc_id_is_invalid(txd_id)) 771 return; 772 tx_mz = ring_dma_zone_lookup("tx_ring", port_id, txq_id); 773 if (tx_mz == NULL) 774 return; 775 ring_tx_descriptor_display(tx_mz, txd_id); 776 } 777 778 void 779 fwd_lcores_config_display(void) 780 { 781 lcoreid_t lc_id; 782 783 printf("List of forwarding lcores:"); 784 for (lc_id = 0; lc_id < nb_cfg_lcores; lc_id++) 785 printf(" %2u", fwd_lcores_cpuids[lc_id]); 786 printf("\n"); 787 } 788 void 789 rxtx_config_display(void) 790 { 791 printf(" %s packet forwarding - CRC stripping %s - " 792 "packets/burst=%d\n", cur_fwd_eng->fwd_mode_name, 793 rx_mode.hw_strip_crc ? "enabled" : "disabled", 794 nb_pkt_per_burst); 795 796 if (cur_fwd_eng == &tx_only_engine) 797 printf(" packet len=%u - nb packet segments=%d\n", 798 (unsigned)tx_pkt_length, (int) tx_pkt_nb_segs); 799 800 struct rte_eth_rxconf *rx_conf = &ports[0].rx_conf; 801 struct rte_eth_txconf *tx_conf = &ports[0].tx_conf; 802 803 printf(" nb forwarding cores=%d - nb forwarding ports=%d\n", 804 nb_fwd_lcores, nb_fwd_ports); 805 printf(" RX queues=%d - RX desc=%d - RX free threshold=%d\n", 806 nb_rxq, nb_rxd, rx_conf->rx_free_thresh); 807 printf(" RX threshold registers: pthresh=%d hthresh=%d wthresh=%d\n", 808 rx_conf->rx_thresh.pthresh, rx_conf->rx_thresh.hthresh, 809 rx_conf->rx_thresh.wthresh); 810 printf(" TX queues=%d - TX desc=%d - TX free threshold=%d\n", 811 nb_txq, nb_txd, tx_conf->tx_free_thresh); 812 printf(" TX threshold registers: pthresh=%d hthresh=%d wthresh=%d\n", 813 tx_conf->tx_thresh.pthresh, tx_conf->tx_thresh.hthresh, 814 tx_conf->tx_thresh.wthresh); 815 printf(" TX RS bit threshold=%d - TXQ flags=0x%"PRIx32"\n", 816 tx_conf->tx_rs_thresh, tx_conf->txq_flags); 817 } 818 819 void 820 port_rss_reta_info(portid_t port_id, 821 struct rte_eth_rss_reta_entry64 *reta_conf, 822 uint16_t nb_entries) 823 { 824 uint16_t i, idx, shift; 825 int ret; 826 827 if (port_id_is_invalid(port_id, ENABLED_WARN)) 828 return; 829 830 ret = rte_eth_dev_rss_reta_query(port_id, reta_conf, nb_entries); 831 if (ret != 0) { 832 printf("Failed to get RSS RETA info, return code = %d\n", ret); 833 return; 834 } 835 836 for (i = 0; i < nb_entries; i++) { 837 idx = i / RTE_RETA_GROUP_SIZE; 838 shift = i % RTE_RETA_GROUP_SIZE; 839 if (!(reta_conf[idx].mask & (1ULL << shift))) 840 continue; 841 printf("RSS RETA configuration: hash index=%u, queue=%u\n", 842 i, reta_conf[idx].reta[shift]); 843 } 844 } 845 846 /* 847 * Displays the RSS hash functions of a port, and, optionaly, the RSS hash 848 * key of the port. 849 */ 850 void 851 port_rss_hash_conf_show(portid_t port_id, int show_rss_key) 852 { 853 struct rss_type_info { 854 char str[32]; 855 uint64_t rss_type; 856 }; 857 static const struct rss_type_info rss_type_table[] = { 858 {"ipv4", ETH_RSS_IPV4}, 859 {"ipv4-frag", ETH_RSS_FRAG_IPV4}, 860 {"ipv4-tcp", ETH_RSS_NONFRAG_IPV4_TCP}, 861 {"ipv4-udp", ETH_RSS_NONFRAG_IPV4_UDP}, 862 {"ipv4-sctp", ETH_RSS_NONFRAG_IPV4_SCTP}, 863 {"ipv4-other", ETH_RSS_NONFRAG_IPV4_OTHER}, 864 {"ipv6", ETH_RSS_IPV6}, 865 {"ipv6-frag", ETH_RSS_FRAG_IPV6}, 866 {"ipv6-tcp", ETH_RSS_NONFRAG_IPV6_TCP}, 867 {"ipv6-udp", ETH_RSS_NONFRAG_IPV6_UDP}, 868 {"ipv6-sctp", ETH_RSS_NONFRAG_IPV6_SCTP}, 869 {"ipv6-other", ETH_RSS_NONFRAG_IPV6_OTHER}, 870 {"l2-payload", ETH_RSS_L2_PAYLOAD}, 871 {"ipv6-ex", ETH_RSS_IPV6_EX}, 872 {"ipv6-tcp-ex", ETH_RSS_IPV6_TCP_EX}, 873 {"ipv6-udp-ex", ETH_RSS_IPV6_UDP_EX}, 874 }; 875 876 struct rte_eth_rss_conf rss_conf; 877 uint8_t rss_key[10 * 4]; 878 uint64_t rss_hf; 879 uint8_t i; 880 int diag; 881 882 if (port_id_is_invalid(port_id, ENABLED_WARN)) 883 return; 884 /* Get RSS hash key if asked to display it */ 885 rss_conf.rss_key = (show_rss_key) ? rss_key : NULL; 886 diag = rte_eth_dev_rss_hash_conf_get(port_id, &rss_conf); 887 if (diag != 0) { 888 switch (diag) { 889 case -ENODEV: 890 printf("port index %d invalid\n", port_id); 891 break; 892 case -ENOTSUP: 893 printf("operation not supported by device\n"); 894 break; 895 default: 896 printf("operation failed - diag=%d\n", diag); 897 break; 898 } 899 return; 900 } 901 rss_hf = rss_conf.rss_hf; 902 if (rss_hf == 0) { 903 printf("RSS disabled\n"); 904 return; 905 } 906 printf("RSS functions:\n "); 907 for (i = 0; i < RTE_DIM(rss_type_table); i++) { 908 if (rss_hf & rss_type_table[i].rss_type) 909 printf("%s ", rss_type_table[i].str); 910 } 911 printf("\n"); 912 if (!show_rss_key) 913 return; 914 printf("RSS key:\n"); 915 for (i = 0; i < sizeof(rss_key); i++) 916 printf("%02X", rss_key[i]); 917 printf("\n"); 918 } 919 920 void 921 port_rss_hash_key_update(portid_t port_id, uint8_t *hash_key) 922 { 923 struct rte_eth_rss_conf rss_conf; 924 int diag; 925 926 rss_conf.rss_key = NULL; 927 diag = rte_eth_dev_rss_hash_conf_get(port_id, &rss_conf); 928 if (diag == 0) { 929 rss_conf.rss_key = hash_key; 930 diag = rte_eth_dev_rss_hash_update(port_id, &rss_conf); 931 } 932 if (diag == 0) 933 return; 934 935 switch (diag) { 936 case -ENODEV: 937 printf("port index %d invalid\n", port_id); 938 break; 939 case -ENOTSUP: 940 printf("operation not supported by device\n"); 941 break; 942 default: 943 printf("operation failed - diag=%d\n", diag); 944 break; 945 } 946 } 947 948 /* 949 * Setup forwarding configuration for each logical core. 950 */ 951 static void 952 setup_fwd_config_of_each_lcore(struct fwd_config *cfg) 953 { 954 streamid_t nb_fs_per_lcore; 955 streamid_t nb_fs; 956 streamid_t sm_id; 957 lcoreid_t nb_extra; 958 lcoreid_t nb_fc; 959 lcoreid_t nb_lc; 960 lcoreid_t lc_id; 961 962 nb_fs = cfg->nb_fwd_streams; 963 nb_fc = cfg->nb_fwd_lcores; 964 if (nb_fs <= nb_fc) { 965 nb_fs_per_lcore = 1; 966 nb_extra = 0; 967 } else { 968 nb_fs_per_lcore = (streamid_t) (nb_fs / nb_fc); 969 nb_extra = (lcoreid_t) (nb_fs % nb_fc); 970 } 971 972 nb_lc = (lcoreid_t) (nb_fc - nb_extra); 973 sm_id = 0; 974 for (lc_id = 0; lc_id < nb_lc; lc_id++) { 975 fwd_lcores[lc_id]->stream_idx = sm_id; 976 fwd_lcores[lc_id]->stream_nb = nb_fs_per_lcore; 977 sm_id = (streamid_t) (sm_id + nb_fs_per_lcore); 978 } 979 980 /* 981 * Assign extra remaining streams, if any. 982 */ 983 nb_fs_per_lcore = (streamid_t) (nb_fs_per_lcore + 1); 984 for (lc_id = 0; lc_id < nb_extra; lc_id++) { 985 fwd_lcores[nb_lc + lc_id]->stream_idx = sm_id; 986 fwd_lcores[nb_lc + lc_id]->stream_nb = nb_fs_per_lcore; 987 sm_id = (streamid_t) (sm_id + nb_fs_per_lcore); 988 } 989 } 990 991 static void 992 simple_fwd_config_setup(void) 993 { 994 portid_t i; 995 portid_t j; 996 portid_t inc = 2; 997 998 if (port_topology == PORT_TOPOLOGY_CHAINED || 999 port_topology == PORT_TOPOLOGY_LOOP) { 1000 inc = 1; 1001 } else if (nb_fwd_ports % 2) { 1002 printf("\nWarning! Cannot handle an odd number of ports " 1003 "with the current port topology. Configuration " 1004 "must be changed to have an even number of ports, " 1005 "or relaunch application with " 1006 "--port-topology=chained\n\n"); 1007 } 1008 1009 cur_fwd_config.nb_fwd_ports = (portid_t) nb_fwd_ports; 1010 cur_fwd_config.nb_fwd_streams = 1011 (streamid_t) cur_fwd_config.nb_fwd_ports; 1012 1013 /* reinitialize forwarding streams */ 1014 init_fwd_streams(); 1015 1016 /* 1017 * In the simple forwarding test, the number of forwarding cores 1018 * must be lower or equal to the number of forwarding ports. 1019 */ 1020 cur_fwd_config.nb_fwd_lcores = (lcoreid_t) nb_fwd_lcores; 1021 if (cur_fwd_config.nb_fwd_lcores > cur_fwd_config.nb_fwd_ports) 1022 cur_fwd_config.nb_fwd_lcores = 1023 (lcoreid_t) cur_fwd_config.nb_fwd_ports; 1024 setup_fwd_config_of_each_lcore(&cur_fwd_config); 1025 1026 for (i = 0; i < cur_fwd_config.nb_fwd_ports; i = (portid_t) (i + inc)) { 1027 if (port_topology != PORT_TOPOLOGY_LOOP) 1028 j = (portid_t) ((i + 1) % cur_fwd_config.nb_fwd_ports); 1029 else 1030 j = i; 1031 fwd_streams[i]->rx_port = fwd_ports_ids[i]; 1032 fwd_streams[i]->rx_queue = 0; 1033 fwd_streams[i]->tx_port = fwd_ports_ids[j]; 1034 fwd_streams[i]->tx_queue = 0; 1035 fwd_streams[i]->peer_addr = j; 1036 1037 if (port_topology == PORT_TOPOLOGY_PAIRED) { 1038 fwd_streams[j]->rx_port = fwd_ports_ids[j]; 1039 fwd_streams[j]->rx_queue = 0; 1040 fwd_streams[j]->tx_port = fwd_ports_ids[i]; 1041 fwd_streams[j]->tx_queue = 0; 1042 fwd_streams[j]->peer_addr = i; 1043 } 1044 } 1045 } 1046 1047 /** 1048 * For the RSS forwarding test, each core is assigned on every port a transmit 1049 * queue whose index is the index of the core itself. This approach limits the 1050 * maximumm number of processing cores of the RSS test to the maximum number of 1051 * TX queues supported by the devices. 1052 * 1053 * Each core is assigned a single stream, each stream being composed of 1054 * a RX queue to poll on a RX port for input messages, associated with 1055 * a TX queue of a TX port where to send forwarded packets. 1056 * All packets received on the RX queue of index "RxQj" of the RX port "RxPi" 1057 * are sent on the TX queue "TxQl" of the TX port "TxPk" according to the two 1058 * following rules: 1059 * - TxPk = (RxPi + 1) if RxPi is even, (RxPi - 1) if RxPi is odd 1060 * - TxQl = RxQj 1061 */ 1062 static void 1063 rss_fwd_config_setup(void) 1064 { 1065 portid_t rxp; 1066 portid_t txp; 1067 queueid_t rxq; 1068 queueid_t nb_q; 1069 lcoreid_t lc_id; 1070 1071 nb_q = nb_rxq; 1072 if (nb_q > nb_txq) 1073 nb_q = nb_txq; 1074 cur_fwd_config.nb_fwd_lcores = (lcoreid_t) nb_fwd_lcores; 1075 cur_fwd_config.nb_fwd_ports = nb_fwd_ports; 1076 cur_fwd_config.nb_fwd_streams = 1077 (streamid_t) (nb_q * cur_fwd_config.nb_fwd_ports); 1078 if (cur_fwd_config.nb_fwd_streams > cur_fwd_config.nb_fwd_lcores) 1079 cur_fwd_config.nb_fwd_streams = 1080 (streamid_t)cur_fwd_config.nb_fwd_lcores; 1081 else 1082 cur_fwd_config.nb_fwd_lcores = 1083 (lcoreid_t)cur_fwd_config.nb_fwd_streams; 1084 1085 /* reinitialize forwarding streams */ 1086 init_fwd_streams(); 1087 1088 setup_fwd_config_of_each_lcore(&cur_fwd_config); 1089 rxp = 0; rxq = 0; 1090 for (lc_id = 0; lc_id < cur_fwd_config.nb_fwd_lcores; lc_id++) { 1091 struct fwd_stream *fs; 1092 1093 fs = fwd_streams[lc_id]; 1094 1095 if ((rxp & 0x1) == 0) 1096 txp = (portid_t) (rxp + 1); 1097 else 1098 txp = (portid_t) (rxp - 1); 1099 /* 1100 * if we are in loopback, simply send stuff out through the 1101 * ingress port 1102 */ 1103 if (port_topology == PORT_TOPOLOGY_LOOP) 1104 txp = rxp; 1105 1106 fs->rx_port = fwd_ports_ids[rxp]; 1107 fs->rx_queue = rxq; 1108 fs->tx_port = fwd_ports_ids[txp]; 1109 fs->tx_queue = rxq; 1110 fs->peer_addr = fs->tx_port; 1111 rxq = (queueid_t) (rxq + 1); 1112 if (rxq < nb_q) 1113 continue; 1114 /* 1115 * rxq == nb_q 1116 * Restart from RX queue 0 on next RX port 1117 */ 1118 rxq = 0; 1119 if (numa_support && (nb_fwd_ports <= (nb_ports >> 1))) 1120 rxp = (portid_t) 1121 (rxp + ((nb_ports >> 1) / nb_fwd_ports)); 1122 else 1123 rxp = (portid_t) (rxp + 1); 1124 } 1125 } 1126 1127 /* 1128 * In DCB and VT on,the mapping of 128 receive queues to 128 transmit queues. 1129 */ 1130 static void 1131 dcb_rxq_2_txq_mapping(queueid_t rxq, queueid_t *txq) 1132 { 1133 if(dcb_q_mapping == DCB_4_TCS_Q_MAPPING) { 1134 1135 if (rxq < 32) 1136 /* tc0: 0-31 */ 1137 *txq = rxq; 1138 else if (rxq < 64) { 1139 /* tc1: 64-95 */ 1140 *txq = (uint16_t)(rxq + 32); 1141 } 1142 else { 1143 /* tc2: 96-111;tc3:112-127 */ 1144 *txq = (uint16_t)(rxq/2 + 64); 1145 } 1146 } 1147 else { 1148 if (rxq < 16) 1149 /* tc0 mapping*/ 1150 *txq = rxq; 1151 else if (rxq < 32) { 1152 /* tc1 mapping*/ 1153 *txq = (uint16_t)(rxq + 16); 1154 } 1155 else if (rxq < 64) { 1156 /*tc2,tc3 mapping */ 1157 *txq = (uint16_t)(rxq + 32); 1158 } 1159 else { 1160 /* tc4,tc5,tc6 and tc7 mapping */ 1161 *txq = (uint16_t)(rxq/2 + 64); 1162 } 1163 } 1164 } 1165 1166 /** 1167 * For the DCB forwarding test, each core is assigned on every port multi-transmit 1168 * queue. 1169 * 1170 * Each core is assigned a multi-stream, each stream being composed of 1171 * a RX queue to poll on a RX port for input messages, associated with 1172 * a TX queue of a TX port where to send forwarded packets. 1173 * All packets received on the RX queue of index "RxQj" of the RX port "RxPi" 1174 * are sent on the TX queue "TxQl" of the TX port "TxPk" according to the two 1175 * following rules: 1176 * In VT mode, 1177 * - TxPk = (RxPi + 1) if RxPi is even, (RxPi - 1) if RxPi is odd 1178 * - TxQl = RxQj 1179 * In non-VT mode, 1180 * - TxPk = (RxPi + 1) if RxPi is even, (RxPi - 1) if RxPi is odd 1181 * There is a mapping of RxQj to TxQl to be required,and the mapping was implemented 1182 * in dcb_rxq_2_txq_mapping function. 1183 */ 1184 static void 1185 dcb_fwd_config_setup(void) 1186 { 1187 portid_t rxp; 1188 portid_t txp; 1189 queueid_t rxq; 1190 queueid_t nb_q; 1191 lcoreid_t lc_id; 1192 uint16_t sm_id; 1193 1194 nb_q = nb_rxq; 1195 1196 cur_fwd_config.nb_fwd_lcores = (lcoreid_t) nb_fwd_lcores; 1197 cur_fwd_config.nb_fwd_ports = nb_fwd_ports; 1198 cur_fwd_config.nb_fwd_streams = 1199 (streamid_t) (nb_q * cur_fwd_config.nb_fwd_ports); 1200 1201 /* reinitialize forwarding streams */ 1202 init_fwd_streams(); 1203 1204 setup_fwd_config_of_each_lcore(&cur_fwd_config); 1205 rxp = 0; rxq = 0; 1206 for (lc_id = 0; lc_id < cur_fwd_config.nb_fwd_lcores; lc_id++) { 1207 /* a fwd core can run multi-streams */ 1208 for (sm_id = 0; sm_id < fwd_lcores[lc_id]->stream_nb; sm_id++) 1209 { 1210 struct fwd_stream *fs; 1211 fs = fwd_streams[fwd_lcores[lc_id]->stream_idx + sm_id]; 1212 if ((rxp & 0x1) == 0) 1213 txp = (portid_t) (rxp + 1); 1214 else 1215 txp = (portid_t) (rxp - 1); 1216 fs->rx_port = fwd_ports_ids[rxp]; 1217 fs->rx_queue = rxq; 1218 fs->tx_port = fwd_ports_ids[txp]; 1219 if (dcb_q_mapping == DCB_VT_Q_MAPPING) 1220 fs->tx_queue = rxq; 1221 else 1222 dcb_rxq_2_txq_mapping(rxq, &fs->tx_queue); 1223 fs->peer_addr = fs->tx_port; 1224 rxq = (queueid_t) (rxq + 1); 1225 if (rxq < nb_q) 1226 continue; 1227 rxq = 0; 1228 if (numa_support && (nb_fwd_ports <= (nb_ports >> 1))) 1229 rxp = (portid_t) 1230 (rxp + ((nb_ports >> 1) / nb_fwd_ports)); 1231 else 1232 rxp = (portid_t) (rxp + 1); 1233 } 1234 } 1235 } 1236 1237 static void 1238 icmp_echo_config_setup(void) 1239 { 1240 portid_t rxp; 1241 queueid_t rxq; 1242 lcoreid_t lc_id; 1243 uint16_t sm_id; 1244 1245 if ((nb_txq * nb_fwd_ports) < nb_fwd_lcores) 1246 cur_fwd_config.nb_fwd_lcores = (lcoreid_t) 1247 (nb_txq * nb_fwd_ports); 1248 else 1249 cur_fwd_config.nb_fwd_lcores = (lcoreid_t) nb_fwd_lcores; 1250 cur_fwd_config.nb_fwd_ports = nb_fwd_ports; 1251 cur_fwd_config.nb_fwd_streams = 1252 (streamid_t) (nb_rxq * cur_fwd_config.nb_fwd_ports); 1253 if (cur_fwd_config.nb_fwd_streams < cur_fwd_config.nb_fwd_lcores) 1254 cur_fwd_config.nb_fwd_lcores = 1255 (lcoreid_t)cur_fwd_config.nb_fwd_streams; 1256 if (verbose_level > 0) { 1257 printf("%s fwd_cores=%d fwd_ports=%d fwd_streams=%d\n", 1258 __FUNCTION__, 1259 cur_fwd_config.nb_fwd_lcores, 1260 cur_fwd_config.nb_fwd_ports, 1261 cur_fwd_config.nb_fwd_streams); 1262 } 1263 1264 /* reinitialize forwarding streams */ 1265 init_fwd_streams(); 1266 setup_fwd_config_of_each_lcore(&cur_fwd_config); 1267 rxp = 0; rxq = 0; 1268 for (lc_id = 0; lc_id < cur_fwd_config.nb_fwd_lcores; lc_id++) { 1269 if (verbose_level > 0) 1270 printf(" core=%d: \n", lc_id); 1271 for (sm_id = 0; sm_id < fwd_lcores[lc_id]->stream_nb; sm_id++) { 1272 struct fwd_stream *fs; 1273 fs = fwd_streams[fwd_lcores[lc_id]->stream_idx + sm_id]; 1274 fs->rx_port = fwd_ports_ids[rxp]; 1275 fs->rx_queue = rxq; 1276 fs->tx_port = fs->rx_port; 1277 fs->tx_queue = lc_id; 1278 fs->peer_addr = fs->tx_port; 1279 if (verbose_level > 0) 1280 printf(" stream=%d port=%d rxq=%d txq=%d\n", 1281 sm_id, fs->rx_port, fs->rx_queue, 1282 fs->tx_queue); 1283 rxq = (queueid_t) (rxq + 1); 1284 if (rxq == nb_rxq) { 1285 rxq = 0; 1286 rxp = (portid_t) (rxp + 1); 1287 } 1288 } 1289 } 1290 } 1291 1292 void 1293 fwd_config_setup(void) 1294 { 1295 cur_fwd_config.fwd_eng = cur_fwd_eng; 1296 if (strcmp(cur_fwd_eng->fwd_mode_name, "icmpecho") == 0) { 1297 icmp_echo_config_setup(); 1298 return; 1299 } 1300 if ((nb_rxq > 1) && (nb_txq > 1)){ 1301 if (dcb_config) 1302 dcb_fwd_config_setup(); 1303 else 1304 rss_fwd_config_setup(); 1305 } 1306 else 1307 simple_fwd_config_setup(); 1308 } 1309 1310 static void 1311 pkt_fwd_config_display(struct fwd_config *cfg) 1312 { 1313 struct fwd_stream *fs; 1314 lcoreid_t lc_id; 1315 streamid_t sm_id; 1316 1317 printf("%s packet forwarding - ports=%d - cores=%d - streams=%d - " 1318 "NUMA support %s, MP over anonymous pages %s\n", 1319 cfg->fwd_eng->fwd_mode_name, 1320 cfg->nb_fwd_ports, cfg->nb_fwd_lcores, cfg->nb_fwd_streams, 1321 numa_support == 1 ? "enabled" : "disabled", 1322 mp_anon != 0 ? "enabled" : "disabled"); 1323 1324 if (strcmp(cfg->fwd_eng->fwd_mode_name, "mac_retry") == 0) 1325 printf("TX retry num: %u, delay between TX retries: %uus\n", 1326 burst_tx_retry_num, burst_tx_delay_time); 1327 for (lc_id = 0; lc_id < cfg->nb_fwd_lcores; lc_id++) { 1328 printf("Logical Core %u (socket %u) forwards packets on " 1329 "%d streams:", 1330 fwd_lcores_cpuids[lc_id], 1331 rte_lcore_to_socket_id(fwd_lcores_cpuids[lc_id]), 1332 fwd_lcores[lc_id]->stream_nb); 1333 for (sm_id = 0; sm_id < fwd_lcores[lc_id]->stream_nb; sm_id++) { 1334 fs = fwd_streams[fwd_lcores[lc_id]->stream_idx + sm_id]; 1335 printf("\n RX P=%d/Q=%d (socket %u) -> TX " 1336 "P=%d/Q=%d (socket %u) ", 1337 fs->rx_port, fs->rx_queue, 1338 ports[fs->rx_port].socket_id, 1339 fs->tx_port, fs->tx_queue, 1340 ports[fs->tx_port].socket_id); 1341 print_ethaddr("peer=", 1342 &peer_eth_addrs[fs->peer_addr]); 1343 } 1344 printf("\n"); 1345 } 1346 printf("\n"); 1347 } 1348 1349 1350 void 1351 fwd_config_display(void) 1352 { 1353 if((dcb_config) && (nb_fwd_lcores == 1)) { 1354 printf("In DCB mode,the nb forwarding cores should be larger than 1\n"); 1355 return; 1356 } 1357 fwd_config_setup(); 1358 pkt_fwd_config_display(&cur_fwd_config); 1359 } 1360 1361 int 1362 set_fwd_lcores_list(unsigned int *lcorelist, unsigned int nb_lc) 1363 { 1364 unsigned int i; 1365 unsigned int lcore_cpuid; 1366 int record_now; 1367 1368 record_now = 0; 1369 again: 1370 for (i = 0; i < nb_lc; i++) { 1371 lcore_cpuid = lcorelist[i]; 1372 if (! rte_lcore_is_enabled(lcore_cpuid)) { 1373 printf("lcore %u not enabled\n", lcore_cpuid); 1374 return -1; 1375 } 1376 if (lcore_cpuid == rte_get_master_lcore()) { 1377 printf("lcore %u cannot be masked on for running " 1378 "packet forwarding, which is the master lcore " 1379 "and reserved for command line parsing only\n", 1380 lcore_cpuid); 1381 return -1; 1382 } 1383 if (record_now) 1384 fwd_lcores_cpuids[i] = lcore_cpuid; 1385 } 1386 if (record_now == 0) { 1387 record_now = 1; 1388 goto again; 1389 } 1390 nb_cfg_lcores = (lcoreid_t) nb_lc; 1391 if (nb_fwd_lcores != (lcoreid_t) nb_lc) { 1392 printf("previous number of forwarding cores %u - changed to " 1393 "number of configured cores %u\n", 1394 (unsigned int) nb_fwd_lcores, nb_lc); 1395 nb_fwd_lcores = (lcoreid_t) nb_lc; 1396 } 1397 1398 return 0; 1399 } 1400 1401 int 1402 set_fwd_lcores_mask(uint64_t lcoremask) 1403 { 1404 unsigned int lcorelist[64]; 1405 unsigned int nb_lc; 1406 unsigned int i; 1407 1408 if (lcoremask == 0) { 1409 printf("Invalid NULL mask of cores\n"); 1410 return -1; 1411 } 1412 nb_lc = 0; 1413 for (i = 0; i < 64; i++) { 1414 if (! ((uint64_t)(1ULL << i) & lcoremask)) 1415 continue; 1416 lcorelist[nb_lc++] = i; 1417 } 1418 return set_fwd_lcores_list(lcorelist, nb_lc); 1419 } 1420 1421 void 1422 set_fwd_lcores_number(uint16_t nb_lc) 1423 { 1424 if (nb_lc > nb_cfg_lcores) { 1425 printf("nb fwd cores %u > %u (max. number of configured " 1426 "lcores) - ignored\n", 1427 (unsigned int) nb_lc, (unsigned int) nb_cfg_lcores); 1428 return; 1429 } 1430 nb_fwd_lcores = (lcoreid_t) nb_lc; 1431 printf("Number of forwarding cores set to %u\n", 1432 (unsigned int) nb_fwd_lcores); 1433 } 1434 1435 void 1436 set_fwd_ports_list(unsigned int *portlist, unsigned int nb_pt) 1437 { 1438 unsigned int i; 1439 portid_t port_id; 1440 int record_now; 1441 1442 record_now = 0; 1443 again: 1444 for (i = 0; i < nb_pt; i++) { 1445 port_id = (portid_t) portlist[i]; 1446 if (port_id_is_invalid(port_id, ENABLED_WARN)) 1447 return; 1448 if (record_now) 1449 fwd_ports_ids[i] = port_id; 1450 } 1451 if (record_now == 0) { 1452 record_now = 1; 1453 goto again; 1454 } 1455 nb_cfg_ports = (portid_t) nb_pt; 1456 if (nb_fwd_ports != (portid_t) nb_pt) { 1457 printf("previous number of forwarding ports %u - changed to " 1458 "number of configured ports %u\n", 1459 (unsigned int) nb_fwd_ports, nb_pt); 1460 nb_fwd_ports = (portid_t) nb_pt; 1461 } 1462 } 1463 1464 void 1465 set_fwd_ports_mask(uint64_t portmask) 1466 { 1467 unsigned int portlist[64]; 1468 unsigned int nb_pt; 1469 unsigned int i; 1470 1471 if (portmask == 0) { 1472 printf("Invalid NULL mask of ports\n"); 1473 return; 1474 } 1475 nb_pt = 0; 1476 for (i = 0; i < (unsigned)RTE_MIN(64, RTE_MAX_ETHPORTS); i++) { 1477 if (! ((uint64_t)(1ULL << i) & portmask)) 1478 continue; 1479 portlist[nb_pt++] = i; 1480 } 1481 set_fwd_ports_list(portlist, nb_pt); 1482 } 1483 1484 void 1485 set_fwd_ports_number(uint16_t nb_pt) 1486 { 1487 if (nb_pt > nb_cfg_ports) { 1488 printf("nb fwd ports %u > %u (number of configured " 1489 "ports) - ignored\n", 1490 (unsigned int) nb_pt, (unsigned int) nb_cfg_ports); 1491 return; 1492 } 1493 nb_fwd_ports = (portid_t) nb_pt; 1494 printf("Number of forwarding ports set to %u\n", 1495 (unsigned int) nb_fwd_ports); 1496 } 1497 1498 void 1499 set_nb_pkt_per_burst(uint16_t nb) 1500 { 1501 if (nb > MAX_PKT_BURST) { 1502 printf("nb pkt per burst: %u > %u (maximum packet per burst) " 1503 " ignored\n", 1504 (unsigned int) nb, (unsigned int) MAX_PKT_BURST); 1505 return; 1506 } 1507 nb_pkt_per_burst = nb; 1508 printf("Number of packets per burst set to %u\n", 1509 (unsigned int) nb_pkt_per_burst); 1510 } 1511 1512 void 1513 set_tx_pkt_segments(unsigned *seg_lengths, unsigned nb_segs) 1514 { 1515 uint16_t tx_pkt_len; 1516 unsigned i; 1517 1518 if (nb_segs >= (unsigned) nb_txd) { 1519 printf("nb segments per TX packets=%u >= nb_txd=%u - ignored\n", 1520 nb_segs, (unsigned int) nb_txd); 1521 return; 1522 } 1523 1524 /* 1525 * Check that each segment length is greater or equal than 1526 * the mbuf data sise. 1527 * Check also that the total packet length is greater or equal than the 1528 * size of an empty UDP/IP packet (sizeof(struct ether_hdr) + 20 + 8). 1529 */ 1530 tx_pkt_len = 0; 1531 for (i = 0; i < nb_segs; i++) { 1532 if (seg_lengths[i] > (unsigned) mbuf_data_size) { 1533 printf("length[%u]=%u > mbuf_data_size=%u - give up\n", 1534 i, seg_lengths[i], (unsigned) mbuf_data_size); 1535 return; 1536 } 1537 tx_pkt_len = (uint16_t)(tx_pkt_len + seg_lengths[i]); 1538 } 1539 if (tx_pkt_len < (sizeof(struct ether_hdr) + 20 + 8)) { 1540 printf("total packet length=%u < %d - give up\n", 1541 (unsigned) tx_pkt_len, 1542 (int)(sizeof(struct ether_hdr) + 20 + 8)); 1543 return; 1544 } 1545 1546 for (i = 0; i < nb_segs; i++) 1547 tx_pkt_seg_lengths[i] = (uint16_t) seg_lengths[i]; 1548 1549 tx_pkt_length = tx_pkt_len; 1550 tx_pkt_nb_segs = (uint8_t) nb_segs; 1551 } 1552 1553 char* 1554 list_pkt_forwarding_modes(void) 1555 { 1556 static char fwd_modes[128] = ""; 1557 const char *separator = "|"; 1558 struct fwd_engine *fwd_eng; 1559 unsigned i = 0; 1560 1561 if (strlen (fwd_modes) == 0) { 1562 while ((fwd_eng = fwd_engines[i++]) != NULL) { 1563 strcat(fwd_modes, fwd_eng->fwd_mode_name); 1564 strcat(fwd_modes, separator); 1565 } 1566 fwd_modes[strlen(fwd_modes) - strlen(separator)] = '\0'; 1567 } 1568 1569 return fwd_modes; 1570 } 1571 1572 void 1573 set_pkt_forwarding_mode(const char *fwd_mode_name) 1574 { 1575 struct fwd_engine *fwd_eng; 1576 unsigned i; 1577 1578 i = 0; 1579 while ((fwd_eng = fwd_engines[i]) != NULL) { 1580 if (! strcmp(fwd_eng->fwd_mode_name, fwd_mode_name)) { 1581 printf("Set %s packet forwarding mode\n", 1582 fwd_mode_name); 1583 cur_fwd_eng = fwd_eng; 1584 return; 1585 } 1586 i++; 1587 } 1588 printf("Invalid %s packet forwarding mode\n", fwd_mode_name); 1589 } 1590 1591 void 1592 set_verbose_level(uint16_t vb_level) 1593 { 1594 printf("Change verbose level from %u to %u\n", 1595 (unsigned int) verbose_level, (unsigned int) vb_level); 1596 verbose_level = vb_level; 1597 } 1598 1599 void 1600 vlan_extend_set(portid_t port_id, int on) 1601 { 1602 int diag; 1603 int vlan_offload; 1604 1605 if (port_id_is_invalid(port_id, ENABLED_WARN)) 1606 return; 1607 1608 vlan_offload = rte_eth_dev_get_vlan_offload(port_id); 1609 1610 if (on) 1611 vlan_offload |= ETH_VLAN_EXTEND_OFFLOAD; 1612 else 1613 vlan_offload &= ~ETH_VLAN_EXTEND_OFFLOAD; 1614 1615 diag = rte_eth_dev_set_vlan_offload(port_id, vlan_offload); 1616 if (diag < 0) 1617 printf("rx_vlan_extend_set(port_pi=%d, on=%d) failed " 1618 "diag=%d\n", port_id, on, diag); 1619 } 1620 1621 void 1622 rx_vlan_strip_set(portid_t port_id, int on) 1623 { 1624 int diag; 1625 int vlan_offload; 1626 1627 if (port_id_is_invalid(port_id, ENABLED_WARN)) 1628 return; 1629 1630 vlan_offload = rte_eth_dev_get_vlan_offload(port_id); 1631 1632 if (on) 1633 vlan_offload |= ETH_VLAN_STRIP_OFFLOAD; 1634 else 1635 vlan_offload &= ~ETH_VLAN_STRIP_OFFLOAD; 1636 1637 diag = rte_eth_dev_set_vlan_offload(port_id, vlan_offload); 1638 if (diag < 0) 1639 printf("rx_vlan_strip_set(port_pi=%d, on=%d) failed " 1640 "diag=%d\n", port_id, on, diag); 1641 } 1642 1643 void 1644 rx_vlan_strip_set_on_queue(portid_t port_id, uint16_t queue_id, int on) 1645 { 1646 int diag; 1647 1648 if (port_id_is_invalid(port_id, ENABLED_WARN)) 1649 return; 1650 1651 diag = rte_eth_dev_set_vlan_strip_on_queue(port_id, queue_id, on); 1652 if (diag < 0) 1653 printf("rx_vlan_strip_set_on_queue(port_pi=%d, queue_id=%d, on=%d) failed " 1654 "diag=%d\n", port_id, queue_id, on, diag); 1655 } 1656 1657 void 1658 rx_vlan_filter_set(portid_t port_id, int on) 1659 { 1660 int diag; 1661 int vlan_offload; 1662 1663 if (port_id_is_invalid(port_id, ENABLED_WARN)) 1664 return; 1665 1666 vlan_offload = rte_eth_dev_get_vlan_offload(port_id); 1667 1668 if (on) 1669 vlan_offload |= ETH_VLAN_FILTER_OFFLOAD; 1670 else 1671 vlan_offload &= ~ETH_VLAN_FILTER_OFFLOAD; 1672 1673 diag = rte_eth_dev_set_vlan_offload(port_id, vlan_offload); 1674 if (diag < 0) 1675 printf("rx_vlan_filter_set(port_pi=%d, on=%d) failed " 1676 "diag=%d\n", port_id, on, diag); 1677 } 1678 1679 void 1680 rx_vft_set(portid_t port_id, uint16_t vlan_id, int on) 1681 { 1682 int diag; 1683 1684 if (port_id_is_invalid(port_id, ENABLED_WARN)) 1685 return; 1686 if (vlan_id_is_invalid(vlan_id)) 1687 return; 1688 diag = rte_eth_dev_vlan_filter(port_id, vlan_id, on); 1689 if (diag == 0) 1690 return; 1691 printf("rte_eth_dev_vlan_filter(port_pi=%d, vlan_id=%d, on=%d) failed " 1692 "diag=%d\n", 1693 port_id, vlan_id, on, diag); 1694 } 1695 1696 void 1697 rx_vlan_all_filter_set(portid_t port_id, int on) 1698 { 1699 uint16_t vlan_id; 1700 1701 if (port_id_is_invalid(port_id, ENABLED_WARN)) 1702 return; 1703 for (vlan_id = 0; vlan_id < 4096; vlan_id++) 1704 rx_vft_set(port_id, vlan_id, on); 1705 } 1706 1707 void 1708 vlan_tpid_set(portid_t port_id, uint16_t tp_id) 1709 { 1710 int diag; 1711 if (port_id_is_invalid(port_id, ENABLED_WARN)) 1712 return; 1713 1714 diag = rte_eth_dev_set_vlan_ether_type(port_id, tp_id); 1715 if (diag == 0) 1716 return; 1717 1718 printf("tx_vlan_tpid_set(port_pi=%d, tpid=%d) failed " 1719 "diag=%d\n", 1720 port_id, tp_id, diag); 1721 } 1722 1723 void 1724 tx_vlan_set(portid_t port_id, uint16_t vlan_id) 1725 { 1726 if (port_id_is_invalid(port_id, ENABLED_WARN)) 1727 return; 1728 if (vlan_id_is_invalid(vlan_id)) 1729 return; 1730 ports[port_id].tx_ol_flags |= TESTPMD_TX_OFFLOAD_INSERT_VLAN; 1731 ports[port_id].tx_vlan_id = vlan_id; 1732 } 1733 1734 void 1735 tx_vlan_reset(portid_t port_id) 1736 { 1737 if (port_id_is_invalid(port_id, ENABLED_WARN)) 1738 return; 1739 ports[port_id].tx_ol_flags &= ~TESTPMD_TX_OFFLOAD_INSERT_VLAN; 1740 } 1741 1742 void 1743 tx_vlan_pvid_set(portid_t port_id, uint16_t vlan_id, int on) 1744 { 1745 if (port_id_is_invalid(port_id, ENABLED_WARN)) 1746 return; 1747 1748 rte_eth_dev_set_vlan_pvid(port_id, vlan_id, on); 1749 } 1750 1751 void 1752 set_qmap(portid_t port_id, uint8_t is_rx, uint16_t queue_id, uint8_t map_value) 1753 { 1754 uint16_t i; 1755 uint8_t existing_mapping_found = 0; 1756 1757 if (port_id_is_invalid(port_id, ENABLED_WARN)) 1758 return; 1759 1760 if (is_rx ? (rx_queue_id_is_invalid(queue_id)) : (tx_queue_id_is_invalid(queue_id))) 1761 return; 1762 1763 if (map_value >= RTE_ETHDEV_QUEUE_STAT_CNTRS) { 1764 printf("map_value not in required range 0..%d\n", 1765 RTE_ETHDEV_QUEUE_STAT_CNTRS - 1); 1766 return; 1767 } 1768 1769 if (!is_rx) { /*then tx*/ 1770 for (i = 0; i < nb_tx_queue_stats_mappings; i++) { 1771 if ((tx_queue_stats_mappings[i].port_id == port_id) && 1772 (tx_queue_stats_mappings[i].queue_id == queue_id)) { 1773 tx_queue_stats_mappings[i].stats_counter_id = map_value; 1774 existing_mapping_found = 1; 1775 break; 1776 } 1777 } 1778 if (!existing_mapping_found) { /* A new additional mapping... */ 1779 tx_queue_stats_mappings[nb_tx_queue_stats_mappings].port_id = port_id; 1780 tx_queue_stats_mappings[nb_tx_queue_stats_mappings].queue_id = queue_id; 1781 tx_queue_stats_mappings[nb_tx_queue_stats_mappings].stats_counter_id = map_value; 1782 nb_tx_queue_stats_mappings++; 1783 } 1784 } 1785 else { /*rx*/ 1786 for (i = 0; i < nb_rx_queue_stats_mappings; i++) { 1787 if ((rx_queue_stats_mappings[i].port_id == port_id) && 1788 (rx_queue_stats_mappings[i].queue_id == queue_id)) { 1789 rx_queue_stats_mappings[i].stats_counter_id = map_value; 1790 existing_mapping_found = 1; 1791 break; 1792 } 1793 } 1794 if (!existing_mapping_found) { /* A new additional mapping... */ 1795 rx_queue_stats_mappings[nb_rx_queue_stats_mappings].port_id = port_id; 1796 rx_queue_stats_mappings[nb_rx_queue_stats_mappings].queue_id = queue_id; 1797 rx_queue_stats_mappings[nb_rx_queue_stats_mappings].stats_counter_id = map_value; 1798 nb_rx_queue_stats_mappings++; 1799 } 1800 } 1801 } 1802 1803 static inline void 1804 print_fdir_mask(struct rte_eth_fdir_masks *mask) 1805 { 1806 printf("\n vlan_tci: 0x%04x, src_ipv4: 0x%08x, dst_ipv4: 0x%08x," 1807 " src_port: 0x%04x, dst_port: 0x%04x", 1808 mask->vlan_tci_mask, mask->ipv4_mask.src_ip, 1809 mask->ipv4_mask.dst_ip, 1810 mask->src_port_mask, mask->dst_port_mask); 1811 1812 printf("\n src_ipv6: 0x%08x,0x%08x,0x%08x,0x%08x," 1813 " dst_ipv6: 0x%08x,0x%08x,0x%08x,0x%08x", 1814 mask->ipv6_mask.src_ip[0], mask->ipv6_mask.src_ip[1], 1815 mask->ipv6_mask.src_ip[2], mask->ipv6_mask.src_ip[3], 1816 mask->ipv6_mask.dst_ip[0], mask->ipv6_mask.dst_ip[1], 1817 mask->ipv6_mask.dst_ip[2], mask->ipv6_mask.dst_ip[3]); 1818 printf("\n"); 1819 } 1820 1821 static inline void 1822 print_fdir_flex_payload(struct rte_eth_fdir_flex_conf *flex_conf, uint32_t num) 1823 { 1824 struct rte_eth_flex_payload_cfg *cfg; 1825 uint32_t i, j; 1826 1827 for (i = 0; i < flex_conf->nb_payloads; i++) { 1828 cfg = &flex_conf->flex_set[i]; 1829 if (cfg->type == RTE_ETH_RAW_PAYLOAD) 1830 printf("\n RAW: "); 1831 else if (cfg->type == RTE_ETH_L2_PAYLOAD) 1832 printf("\n L2_PAYLOAD: "); 1833 else if (cfg->type == RTE_ETH_L3_PAYLOAD) 1834 printf("\n L3_PAYLOAD: "); 1835 else if (cfg->type == RTE_ETH_L4_PAYLOAD) 1836 printf("\n L4_PAYLOAD: "); 1837 else 1838 printf("\n UNKNOWN PAYLOAD(%u): ", cfg->type); 1839 for (j = 0; j < num; j++) 1840 printf(" %-5u", cfg->src_offset[j]); 1841 } 1842 printf("\n"); 1843 } 1844 1845 static char * 1846 flowtype_to_str(uint16_t flow_type) 1847 { 1848 struct flow_type_info { 1849 char str[32]; 1850 uint16_t ftype; 1851 }; 1852 1853 uint8_t i; 1854 static struct flow_type_info flowtype_str_table[] = { 1855 {"raw", RTE_ETH_FLOW_RAW}, 1856 {"ipv4", RTE_ETH_FLOW_IPV4}, 1857 {"ipv4-frag", RTE_ETH_FLOW_FRAG_IPV4}, 1858 {"ipv4-tcp", RTE_ETH_FLOW_NONFRAG_IPV4_TCP}, 1859 {"ipv4-udp", RTE_ETH_FLOW_NONFRAG_IPV4_UDP}, 1860 {"ipv4-sctp", RTE_ETH_FLOW_NONFRAG_IPV4_SCTP}, 1861 {"ipv4-other", RTE_ETH_FLOW_NONFRAG_IPV4_OTHER}, 1862 {"ipv6", RTE_ETH_FLOW_IPV6}, 1863 {"ipv6-frag", RTE_ETH_FLOW_FRAG_IPV6}, 1864 {"ipv6-tcp", RTE_ETH_FLOW_NONFRAG_IPV6_TCP}, 1865 {"ipv6-udp", RTE_ETH_FLOW_NONFRAG_IPV6_UDP}, 1866 {"ipv6-sctp", RTE_ETH_FLOW_NONFRAG_IPV6_SCTP}, 1867 {"ipv6-other", RTE_ETH_FLOW_NONFRAG_IPV6_OTHER}, 1868 {"l2_payload", RTE_ETH_FLOW_L2_PAYLOAD}, 1869 }; 1870 1871 for (i = 0; i < RTE_DIM(flowtype_str_table); i++) { 1872 if (flowtype_str_table[i].ftype == flow_type) 1873 return flowtype_str_table[i].str; 1874 } 1875 1876 return NULL; 1877 } 1878 1879 static inline void 1880 print_fdir_flex_mask(struct rte_eth_fdir_flex_conf *flex_conf, uint32_t num) 1881 { 1882 struct rte_eth_fdir_flex_mask *mask; 1883 uint32_t i, j; 1884 char *p; 1885 1886 for (i = 0; i < flex_conf->nb_flexmasks; i++) { 1887 mask = &flex_conf->flex_mask[i]; 1888 p = flowtype_to_str(mask->flow_type); 1889 printf("\n %s:\t", p ? p : "unknown"); 1890 for (j = 0; j < num; j++) 1891 printf(" %02x", mask->mask[j]); 1892 } 1893 printf("\n"); 1894 } 1895 1896 static inline void 1897 print_fdir_flow_type(uint32_t flow_types_mask) 1898 { 1899 int i; 1900 char *p; 1901 1902 for (i = RTE_ETH_FLOW_UNKNOWN; i < RTE_ETH_FLOW_MAX; i++) { 1903 if (!(flow_types_mask & (1 << i))) 1904 continue; 1905 p = flowtype_to_str(i); 1906 if (p) 1907 printf(" %s", p); 1908 else 1909 printf(" unknown"); 1910 } 1911 printf("\n"); 1912 } 1913 1914 void 1915 fdir_get_infos(portid_t port_id) 1916 { 1917 struct rte_eth_fdir_stats fdir_stat; 1918 struct rte_eth_fdir_info fdir_info; 1919 int ret; 1920 1921 static const char *fdir_stats_border = "########################"; 1922 1923 if (port_id_is_invalid(port_id, ENABLED_WARN)) 1924 return; 1925 ret = rte_eth_dev_filter_supported(port_id, RTE_ETH_FILTER_FDIR); 1926 if (ret < 0) { 1927 printf("\n FDIR is not supported on port %-2d\n", 1928 port_id); 1929 return; 1930 } 1931 1932 memset(&fdir_info, 0, sizeof(fdir_info)); 1933 rte_eth_dev_filter_ctrl(port_id, RTE_ETH_FILTER_FDIR, 1934 RTE_ETH_FILTER_INFO, &fdir_info); 1935 memset(&fdir_stat, 0, sizeof(fdir_stat)); 1936 rte_eth_dev_filter_ctrl(port_id, RTE_ETH_FILTER_FDIR, 1937 RTE_ETH_FILTER_STATS, &fdir_stat); 1938 printf("\n %s FDIR infos for port %-2d %s\n", 1939 fdir_stats_border, port_id, fdir_stats_border); 1940 printf(" MODE: "); 1941 if (fdir_info.mode == RTE_FDIR_MODE_PERFECT) 1942 printf(" PERFECT\n"); 1943 else if (fdir_info.mode == RTE_FDIR_MODE_SIGNATURE) 1944 printf(" SIGNATURE\n"); 1945 else 1946 printf(" DISABLE\n"); 1947 printf(" SUPPORTED FLOW TYPE: "); 1948 print_fdir_flow_type(fdir_info.flow_types_mask[0]); 1949 printf(" FLEX PAYLOAD INFO:\n"); 1950 printf(" max_len: %-10"PRIu32" payload_limit: %-10"PRIu32"\n" 1951 " payload_unit: %-10"PRIu32" payload_seg: %-10"PRIu32"\n" 1952 " bitmask_unit: %-10"PRIu32" bitmask_num: %-10"PRIu32"\n", 1953 fdir_info.max_flexpayload, fdir_info.flex_payload_limit, 1954 fdir_info.flex_payload_unit, 1955 fdir_info.max_flex_payload_segment_num, 1956 fdir_info.flex_bitmask_unit, fdir_info.max_flex_bitmask_num); 1957 printf(" MASK: "); 1958 print_fdir_mask(&fdir_info.mask); 1959 if (fdir_info.flex_conf.nb_payloads > 0) { 1960 printf(" FLEX PAYLOAD SRC OFFSET:"); 1961 print_fdir_flex_payload(&fdir_info.flex_conf, fdir_info.max_flexpayload); 1962 } 1963 if (fdir_info.flex_conf.nb_flexmasks > 0) { 1964 printf(" FLEX MASK CFG:"); 1965 print_fdir_flex_mask(&fdir_info.flex_conf, fdir_info.max_flexpayload); 1966 } 1967 printf(" guarant_count: %-10"PRIu32" best_count: %"PRIu32"\n", 1968 fdir_stat.guarant_cnt, fdir_stat.best_cnt); 1969 printf(" guarant_space: %-10"PRIu32" best_space: %"PRIu32"\n", 1970 fdir_info.guarant_spc, fdir_info.best_spc); 1971 printf(" collision: %-10"PRIu32" free: %"PRIu32"\n" 1972 " maxhash: %-10"PRIu32" maxlen: %"PRIu32"\n" 1973 " add: %-10"PRIu64" remove: %"PRIu64"\n" 1974 " f_add: %-10"PRIu64" f_remove: %"PRIu64"\n", 1975 fdir_stat.collision, fdir_stat.free, 1976 fdir_stat.maxhash, fdir_stat.maxlen, 1977 fdir_stat.add, fdir_stat.remove, 1978 fdir_stat.f_add, fdir_stat.f_remove); 1979 printf(" %s############################%s\n", 1980 fdir_stats_border, fdir_stats_border); 1981 } 1982 1983 void 1984 fdir_set_flex_mask(portid_t port_id, struct rte_eth_fdir_flex_mask *cfg) 1985 { 1986 struct rte_port *port; 1987 struct rte_eth_fdir_flex_conf *flex_conf; 1988 int i, idx = 0; 1989 1990 port = &ports[port_id]; 1991 flex_conf = &port->dev_conf.fdir_conf.flex_conf; 1992 for (i = 0; i < RTE_ETH_FLOW_MAX; i++) { 1993 if (cfg->flow_type == flex_conf->flex_mask[i].flow_type) { 1994 idx = i; 1995 break; 1996 } 1997 } 1998 if (i >= RTE_ETH_FLOW_MAX) { 1999 if (flex_conf->nb_flexmasks < RTE_DIM(flex_conf->flex_mask)) { 2000 idx = flex_conf->nb_flexmasks; 2001 flex_conf->nb_flexmasks++; 2002 } else { 2003 printf("The flex mask table is full. Can not set flex" 2004 " mask for flow_type(%u).", cfg->flow_type); 2005 return; 2006 } 2007 } 2008 (void)rte_memcpy(&flex_conf->flex_mask[idx], 2009 cfg, 2010 sizeof(struct rte_eth_fdir_flex_mask)); 2011 } 2012 2013 void 2014 fdir_set_flex_payload(portid_t port_id, struct rte_eth_flex_payload_cfg *cfg) 2015 { 2016 struct rte_port *port; 2017 struct rte_eth_fdir_flex_conf *flex_conf; 2018 int i, idx = 0; 2019 2020 port = &ports[port_id]; 2021 flex_conf = &port->dev_conf.fdir_conf.flex_conf; 2022 for (i = 0; i < RTE_ETH_PAYLOAD_MAX; i++) { 2023 if (cfg->type == flex_conf->flex_set[i].type) { 2024 idx = i; 2025 break; 2026 } 2027 } 2028 if (i >= RTE_ETH_PAYLOAD_MAX) { 2029 if (flex_conf->nb_payloads < RTE_DIM(flex_conf->flex_set)) { 2030 idx = flex_conf->nb_payloads; 2031 flex_conf->nb_payloads++; 2032 } else { 2033 printf("The flex payload table is full. Can not set" 2034 " flex payload for type(%u).", cfg->type); 2035 return; 2036 } 2037 } 2038 (void)rte_memcpy(&flex_conf->flex_set[idx], 2039 cfg, 2040 sizeof(struct rte_eth_flex_payload_cfg)); 2041 2042 } 2043 2044 void 2045 set_vf_traffic(portid_t port_id, uint8_t is_rx, uint16_t vf, uint8_t on) 2046 { 2047 int diag; 2048 2049 if (port_id_is_invalid(port_id, ENABLED_WARN)) 2050 return; 2051 if (is_rx) 2052 diag = rte_eth_dev_set_vf_rx(port_id,vf,on); 2053 else 2054 diag = rte_eth_dev_set_vf_tx(port_id,vf,on); 2055 if (diag == 0) 2056 return; 2057 if(is_rx) 2058 printf("rte_eth_dev_set_vf_rx for port_id=%d failed " 2059 "diag=%d\n", port_id, diag); 2060 else 2061 printf("rte_eth_dev_set_vf_tx for port_id=%d failed " 2062 "diag=%d\n", port_id, diag); 2063 2064 } 2065 2066 void 2067 set_vf_rx_vlan(portid_t port_id, uint16_t vlan_id, uint64_t vf_mask, uint8_t on) 2068 { 2069 int diag; 2070 2071 if (port_id_is_invalid(port_id, ENABLED_WARN)) 2072 return; 2073 if (vlan_id_is_invalid(vlan_id)) 2074 return; 2075 diag = rte_eth_dev_set_vf_vlan_filter(port_id, vlan_id, vf_mask, on); 2076 if (diag == 0) 2077 return; 2078 printf("rte_eth_dev_set_vf_vlan_filter for port_id=%d failed " 2079 "diag=%d\n", port_id, diag); 2080 } 2081 2082 int 2083 set_queue_rate_limit(portid_t port_id, uint16_t queue_idx, uint16_t rate) 2084 { 2085 int diag; 2086 struct rte_eth_link link; 2087 2088 if (port_id_is_invalid(port_id, ENABLED_WARN)) 2089 return 1; 2090 rte_eth_link_get_nowait(port_id, &link); 2091 if (rate > link.link_speed) { 2092 printf("Invalid rate value:%u bigger than link speed: %u\n", 2093 rate, link.link_speed); 2094 return 1; 2095 } 2096 diag = rte_eth_set_queue_rate_limit(port_id, queue_idx, rate); 2097 if (diag == 0) 2098 return diag; 2099 printf("rte_eth_set_queue_rate_limit for port_id=%d failed diag=%d\n", 2100 port_id, diag); 2101 return diag; 2102 } 2103 2104 int 2105 set_vf_rate_limit(portid_t port_id, uint16_t vf, uint16_t rate, uint64_t q_msk) 2106 { 2107 int diag; 2108 struct rte_eth_link link; 2109 2110 if (q_msk == 0) 2111 return 0; 2112 2113 if (port_id_is_invalid(port_id, ENABLED_WARN)) 2114 return 1; 2115 rte_eth_link_get_nowait(port_id, &link); 2116 if (rate > link.link_speed) { 2117 printf("Invalid rate value:%u bigger than link speed: %u\n", 2118 rate, link.link_speed); 2119 return 1; 2120 } 2121 diag = rte_eth_set_vf_rate_limit(port_id, vf, rate, q_msk); 2122 if (diag == 0) 2123 return diag; 2124 printf("rte_eth_set_vf_rate_limit for port_id=%d failed diag=%d\n", 2125 port_id, diag); 2126 return diag; 2127 } 2128