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