1 /* SPDX-License-Identifier: BSD-3-Clause 2 * Copyright(c) 2010-2014 Intel Corporation 3 */ 4 5 #include <stdio.h> 6 #include <stdlib.h> 7 #include <stdint.h> 8 #include <inttypes.h> 9 #include <string.h> 10 #include <sys/queue.h> 11 #include <stdarg.h> 12 #include <errno.h> 13 #include <getopt.h> 14 15 #include <netinet/in.h> 16 #include <linux/if.h> 17 #include <linux/if_tun.h> 18 #include <fcntl.h> 19 #include <sys/ioctl.h> 20 #include <unistd.h> 21 #include <signal.h> 22 23 #include <rte_common.h> 24 #include <rte_log.h> 25 #include <rte_memory.h> 26 #include <rte_memcpy.h> 27 #include <rte_eal.h> 28 #include <rte_per_lcore.h> 29 #include <rte_launch.h> 30 #include <rte_lcore.h> 31 #include <rte_branch_prediction.h> 32 #include <rte_interrupts.h> 33 #include <rte_bus_pci.h> 34 #include <rte_debug.h> 35 #include <rte_ether.h> 36 #include <rte_ethdev.h> 37 #include <rte_mempool.h> 38 #include <rte_mbuf.h> 39 #include <rte_string_fns.h> 40 #include <rte_cycles.h> 41 #include <rte_malloc.h> 42 #include <rte_kni.h> 43 44 /* Macros for printing using RTE_LOG */ 45 #define RTE_LOGTYPE_APP RTE_LOGTYPE_USER1 46 47 /* Max size of a single packet */ 48 #define MAX_PACKET_SZ 2048 49 50 /* Size of the data buffer in each mbuf */ 51 #define MBUF_DATA_SZ (MAX_PACKET_SZ + RTE_PKTMBUF_HEADROOM) 52 53 /* Number of mbufs in mempool that is created */ 54 #define NB_MBUF (8192 * 16) 55 56 /* How many packets to attempt to read from NIC in one go */ 57 #define PKT_BURST_SZ 32 58 59 /* How many objects (mbufs) to keep in per-lcore mempool cache */ 60 #define MEMPOOL_CACHE_SZ PKT_BURST_SZ 61 62 /* Number of RX ring descriptors */ 63 #define NB_RXD 1024 64 65 /* Number of TX ring descriptors */ 66 #define NB_TXD 1024 67 68 /* Total octets in ethernet header */ 69 #define KNI_ENET_HEADER_SIZE 14 70 71 /* Total octets in the FCS */ 72 #define KNI_ENET_FCS_SIZE 4 73 74 #define KNI_US_PER_SECOND 1000000 75 #define KNI_SECOND_PER_DAY 86400 76 77 #define KNI_MAX_KTHREAD 32 78 /* 79 * Structure of port parameters 80 */ 81 struct kni_port_params { 82 uint16_t port_id;/* Port ID */ 83 unsigned lcore_rx; /* lcore ID for RX */ 84 unsigned lcore_tx; /* lcore ID for TX */ 85 uint32_t nb_lcore_k; /* Number of lcores for KNI multi kernel threads */ 86 uint32_t nb_kni; /* Number of KNI devices to be created */ 87 unsigned lcore_k[KNI_MAX_KTHREAD]; /* lcore ID list for kthreads */ 88 struct rte_kni *kni[KNI_MAX_KTHREAD]; /* KNI context pointers */ 89 } __rte_cache_aligned; 90 91 static struct kni_port_params *kni_port_params_array[RTE_MAX_ETHPORTS]; 92 93 94 /* Options for configuring ethernet port */ 95 static struct rte_eth_conf port_conf = { 96 .txmode = { 97 .mq_mode = RTE_ETH_MQ_TX_NONE, 98 }, 99 }; 100 101 /* Mempool for mbufs */ 102 static struct rte_mempool * pktmbuf_pool = NULL; 103 104 /* Mask of enabled ports */ 105 static uint32_t ports_mask = 0; 106 /* Ports set in promiscuous mode off by default. */ 107 static int promiscuous_on = 0; 108 /* Monitor link status continually. off by default. */ 109 static int monitor_links; 110 111 /* Structure type for recording kni interface specific stats */ 112 struct kni_interface_stats { 113 /* number of pkts received from NIC, and sent to KNI */ 114 uint64_t rx_packets; 115 116 /* number of pkts received from NIC, but failed to send to KNI */ 117 uint64_t rx_dropped; 118 119 /* number of pkts received from KNI, and sent to NIC */ 120 uint64_t tx_packets; 121 122 /* number of pkts received from KNI, but failed to send to NIC */ 123 uint64_t tx_dropped; 124 }; 125 126 /* kni device statistics array */ 127 static struct kni_interface_stats kni_stats[RTE_MAX_ETHPORTS]; 128 129 static int kni_change_mtu(uint16_t port_id, unsigned int new_mtu); 130 static int kni_config_network_interface(uint16_t port_id, uint8_t if_up); 131 static int kni_config_mac_address(uint16_t port_id, uint8_t mac_addr[]); 132 133 static uint32_t kni_stop; 134 static uint32_t kni_pause; 135 136 /* Print out statistics on packets handled */ 137 static void 138 print_stats(void) 139 { 140 uint16_t i; 141 142 printf("\n**KNI example application statistics**\n" 143 "====== ============== ============ ============ ============ ============\n" 144 " Port Lcore(RX/TX) rx_packets rx_dropped tx_packets tx_dropped\n" 145 "------ -------------- ------------ ------------ ------------ ------------\n"); 146 for (i = 0; i < RTE_MAX_ETHPORTS; i++) { 147 if (!kni_port_params_array[i]) 148 continue; 149 150 printf("%7d %10u/%2u %13"PRIu64" %13"PRIu64" %13"PRIu64" " 151 "%13"PRIu64"\n", i, 152 kni_port_params_array[i]->lcore_rx, 153 kni_port_params_array[i]->lcore_tx, 154 kni_stats[i].rx_packets, 155 kni_stats[i].rx_dropped, 156 kni_stats[i].tx_packets, 157 kni_stats[i].tx_dropped); 158 } 159 printf("====== ============== ============ ============ ============ ============\n"); 160 161 fflush(stdout); 162 } 163 164 /* Custom handling of signals to handle stats and kni processing */ 165 static void 166 signal_handler(int signum) 167 { 168 /* When we receive a USR1 signal, print stats */ 169 if (signum == SIGUSR1) { 170 print_stats(); 171 } 172 173 /* When we receive a USR2 signal, reset stats */ 174 if (signum == SIGUSR2) { 175 memset(&kni_stats, 0, sizeof(kni_stats)); 176 printf("\n** Statistics have been reset **\n"); 177 return; 178 } 179 180 /* 181 * When we receive a RTMIN or SIGINT or SIGTERM signal, 182 * stop kni processing 183 */ 184 if (signum == SIGRTMIN || signum == SIGINT || signum == SIGTERM) { 185 printf("\nSIGRTMIN/SIGINT/SIGTERM received. " 186 "KNI processing stopping.\n"); 187 __atomic_fetch_add(&kni_stop, 1, __ATOMIC_RELAXED); 188 return; 189 } 190 } 191 192 static void 193 kni_burst_free_mbufs(struct rte_mbuf **pkts, unsigned num) 194 { 195 unsigned i; 196 197 if (pkts == NULL) 198 return; 199 200 for (i = 0; i < num; i++) { 201 rte_pktmbuf_free(pkts[i]); 202 pkts[i] = NULL; 203 } 204 } 205 206 /** 207 * Interface to burst rx and enqueue mbufs into rx_q 208 */ 209 static void 210 kni_ingress(struct kni_port_params *p) 211 { 212 uint8_t i; 213 uint16_t port_id; 214 unsigned nb_rx, num; 215 uint32_t nb_kni; 216 struct rte_mbuf *pkts_burst[PKT_BURST_SZ]; 217 218 if (p == NULL) 219 return; 220 221 nb_kni = p->nb_kni; 222 port_id = p->port_id; 223 for (i = 0; i < nb_kni; i++) { 224 /* Burst rx from eth */ 225 nb_rx = rte_eth_rx_burst(port_id, 0, pkts_burst, PKT_BURST_SZ); 226 if (unlikely(nb_rx > PKT_BURST_SZ)) { 227 RTE_LOG(ERR, APP, "Error receiving from eth\n"); 228 return; 229 } 230 /* Burst tx to kni */ 231 num = rte_kni_tx_burst(p->kni[i], pkts_burst, nb_rx); 232 if (num) 233 kni_stats[port_id].rx_packets += num; 234 235 rte_kni_handle_request(p->kni[i]); 236 if (unlikely(num < nb_rx)) { 237 /* Free mbufs not tx to kni interface */ 238 kni_burst_free_mbufs(&pkts_burst[num], nb_rx - num); 239 kni_stats[port_id].rx_dropped += nb_rx - num; 240 } 241 } 242 } 243 244 /** 245 * Interface to dequeue mbufs from tx_q and burst tx 246 */ 247 static void 248 kni_egress(struct kni_port_params *p) 249 { 250 uint8_t i; 251 uint16_t port_id; 252 unsigned nb_tx, num; 253 uint32_t nb_kni; 254 struct rte_mbuf *pkts_burst[PKT_BURST_SZ]; 255 256 if (p == NULL) 257 return; 258 259 nb_kni = p->nb_kni; 260 port_id = p->port_id; 261 for (i = 0; i < nb_kni; i++) { 262 /* Burst rx from kni */ 263 num = rte_kni_rx_burst(p->kni[i], pkts_burst, PKT_BURST_SZ); 264 if (unlikely(num > PKT_BURST_SZ)) { 265 RTE_LOG(ERR, APP, "Error receiving from KNI\n"); 266 return; 267 } 268 /* Burst tx to eth */ 269 nb_tx = rte_eth_tx_burst(port_id, 0, pkts_burst, (uint16_t)num); 270 if (nb_tx) 271 kni_stats[port_id].tx_packets += nb_tx; 272 if (unlikely(nb_tx < num)) { 273 /* Free mbufs not tx to NIC */ 274 kni_burst_free_mbufs(&pkts_burst[nb_tx], num - nb_tx); 275 kni_stats[port_id].tx_dropped += num - nb_tx; 276 } 277 } 278 } 279 280 static int 281 main_loop(__rte_unused void *arg) 282 { 283 uint16_t i; 284 int32_t f_stop; 285 int32_t f_pause; 286 const unsigned lcore_id = rte_lcore_id(); 287 enum lcore_rxtx { 288 LCORE_NONE, 289 LCORE_RX, 290 LCORE_TX, 291 LCORE_MAX 292 }; 293 enum lcore_rxtx flag = LCORE_NONE; 294 295 RTE_ETH_FOREACH_DEV(i) { 296 if (!kni_port_params_array[i]) 297 continue; 298 if (kni_port_params_array[i]->lcore_rx == (uint8_t)lcore_id) { 299 flag = LCORE_RX; 300 break; 301 } else if (kni_port_params_array[i]->lcore_tx == 302 (uint8_t)lcore_id) { 303 flag = LCORE_TX; 304 break; 305 } 306 } 307 308 if (flag == LCORE_RX) { 309 RTE_LOG(INFO, APP, "Lcore %u is reading from port %d\n", 310 kni_port_params_array[i]->lcore_rx, 311 kni_port_params_array[i]->port_id); 312 while (1) { 313 f_stop = __atomic_load_n(&kni_stop, __ATOMIC_RELAXED); 314 f_pause = __atomic_load_n(&kni_pause, __ATOMIC_RELAXED); 315 if (f_stop) 316 break; 317 if (f_pause) 318 continue; 319 kni_ingress(kni_port_params_array[i]); 320 } 321 } else if (flag == LCORE_TX) { 322 RTE_LOG(INFO, APP, "Lcore %u is writing to port %d\n", 323 kni_port_params_array[i]->lcore_tx, 324 kni_port_params_array[i]->port_id); 325 while (1) { 326 f_stop = __atomic_load_n(&kni_stop, __ATOMIC_RELAXED); 327 f_pause = __atomic_load_n(&kni_pause, __ATOMIC_RELAXED); 328 if (f_stop) 329 break; 330 if (f_pause) 331 continue; 332 kni_egress(kni_port_params_array[i]); 333 } 334 } else 335 RTE_LOG(INFO, APP, "Lcore %u has nothing to do\n", lcore_id); 336 337 return 0; 338 } 339 340 /* Display usage instructions */ 341 static void 342 print_usage(const char *prgname) 343 { 344 RTE_LOG(INFO, APP, "\nUsage: %s [EAL options] -- -p PORTMASK -P -m " 345 "[--config (port,lcore_rx,lcore_tx,lcore_kthread...)" 346 "[,(port,lcore_rx,lcore_tx,lcore_kthread...)]]\n" 347 " -p PORTMASK: hex bitmask of ports to use\n" 348 " -P : enable promiscuous mode\n" 349 " -m : enable monitoring of port carrier state\n" 350 " --config (port,lcore_rx,lcore_tx,lcore_kthread...): " 351 "port and lcore configurations\n", 352 prgname); 353 } 354 355 /* Convert string to unsigned number. 0 is returned if error occurs */ 356 static uint32_t 357 parse_unsigned(const char *portmask) 358 { 359 char *end = NULL; 360 unsigned long num; 361 362 num = strtoul(portmask, &end, 16); 363 if ((portmask[0] == '\0') || (end == NULL) || (*end != '\0')) 364 return 0; 365 366 return (uint32_t)num; 367 } 368 369 static void 370 print_config(void) 371 { 372 uint32_t i, j; 373 struct kni_port_params **p = kni_port_params_array; 374 375 for (i = 0; i < RTE_MAX_ETHPORTS; i++) { 376 if (!p[i]) 377 continue; 378 RTE_LOG(DEBUG, APP, "Port ID: %d\n", p[i]->port_id); 379 RTE_LOG(DEBUG, APP, "Rx lcore ID: %u, Tx lcore ID: %u\n", 380 p[i]->lcore_rx, p[i]->lcore_tx); 381 for (j = 0; j < p[i]->nb_lcore_k; j++) 382 RTE_LOG(DEBUG, APP, "Kernel thread lcore ID: %u\n", 383 p[i]->lcore_k[j]); 384 } 385 } 386 387 static int 388 parse_config(const char *arg) 389 { 390 const char *p, *p0 = arg; 391 char s[256], *end; 392 unsigned size; 393 enum fieldnames { 394 FLD_PORT = 0, 395 FLD_LCORE_RX, 396 FLD_LCORE_TX, 397 _NUM_FLD = KNI_MAX_KTHREAD + 3, 398 }; 399 int i, j, nb_token; 400 char *str_fld[_NUM_FLD]; 401 unsigned long int_fld[_NUM_FLD]; 402 uint16_t port_id, nb_kni_port_params = 0; 403 404 memset(&kni_port_params_array, 0, sizeof(kni_port_params_array)); 405 while (((p = strchr(p0, '(')) != NULL) && 406 nb_kni_port_params < RTE_MAX_ETHPORTS) { 407 p++; 408 if ((p0 = strchr(p, ')')) == NULL) 409 goto fail; 410 size = p0 - p; 411 if (size >= sizeof(s)) { 412 printf("Invalid config parameters\n"); 413 goto fail; 414 } 415 snprintf(s, sizeof(s), "%.*s", size, p); 416 nb_token = rte_strsplit(s, sizeof(s), str_fld, _NUM_FLD, ','); 417 if (nb_token <= FLD_LCORE_TX) { 418 printf("Invalid config parameters\n"); 419 goto fail; 420 } 421 for (i = 0; i < nb_token; i++) { 422 errno = 0; 423 int_fld[i] = strtoul(str_fld[i], &end, 0); 424 if (errno != 0 || end == str_fld[i]) { 425 printf("Invalid config parameters\n"); 426 goto fail; 427 } 428 } 429 430 i = 0; 431 port_id = int_fld[i++]; 432 if (port_id >= RTE_MAX_ETHPORTS) { 433 printf("Port ID %d could not exceed the maximum %d\n", 434 port_id, RTE_MAX_ETHPORTS); 435 goto fail; 436 } 437 if (kni_port_params_array[port_id]) { 438 printf("Port %d has been configured\n", port_id); 439 goto fail; 440 } 441 kni_port_params_array[port_id] = 442 rte_zmalloc("KNI_port_params", 443 sizeof(struct kni_port_params), RTE_CACHE_LINE_SIZE); 444 kni_port_params_array[port_id]->port_id = port_id; 445 kni_port_params_array[port_id]->lcore_rx = 446 (uint8_t)int_fld[i++]; 447 kni_port_params_array[port_id]->lcore_tx = 448 (uint8_t)int_fld[i++]; 449 if (kni_port_params_array[port_id]->lcore_rx >= RTE_MAX_LCORE || 450 kni_port_params_array[port_id]->lcore_tx >= RTE_MAX_LCORE) { 451 printf("lcore_rx %u or lcore_tx %u ID could not " 452 "exceed the maximum %u\n", 453 kni_port_params_array[port_id]->lcore_rx, 454 kni_port_params_array[port_id]->lcore_tx, 455 (unsigned)RTE_MAX_LCORE); 456 goto fail; 457 } 458 for (j = 0; i < nb_token && j < KNI_MAX_KTHREAD; i++, j++) 459 kni_port_params_array[port_id]->lcore_k[j] = 460 (uint8_t)int_fld[i]; 461 kni_port_params_array[port_id]->nb_lcore_k = j; 462 } 463 print_config(); 464 465 return 0; 466 467 fail: 468 for (i = 0; i < RTE_MAX_ETHPORTS; i++) { 469 if (kni_port_params_array[i]) { 470 rte_free(kni_port_params_array[i]); 471 kni_port_params_array[i] = NULL; 472 } 473 } 474 475 return -1; 476 } 477 478 static int 479 validate_parameters(uint32_t portmask) 480 { 481 uint32_t i; 482 483 if (!portmask) { 484 printf("No port configured in port mask\n"); 485 return -1; 486 } 487 488 for (i = 0; i < RTE_MAX_ETHPORTS; i++) { 489 if (((portmask & (1 << i)) && !kni_port_params_array[i]) || 490 (!(portmask & (1 << i)) && kni_port_params_array[i])) 491 rte_exit(EXIT_FAILURE, "portmask is not consistent " 492 "to port ids specified in --config\n"); 493 494 if (kni_port_params_array[i] && !rte_lcore_is_enabled(\ 495 (unsigned)(kni_port_params_array[i]->lcore_rx))) 496 rte_exit(EXIT_FAILURE, "lcore id %u for " 497 "port %d receiving not enabled\n", 498 kni_port_params_array[i]->lcore_rx, 499 kni_port_params_array[i]->port_id); 500 501 if (kni_port_params_array[i] && !rte_lcore_is_enabled(\ 502 (unsigned)(kni_port_params_array[i]->lcore_tx))) 503 rte_exit(EXIT_FAILURE, "lcore id %u for " 504 "port %d transmitting not enabled\n", 505 kni_port_params_array[i]->lcore_tx, 506 kni_port_params_array[i]->port_id); 507 508 } 509 510 return 0; 511 } 512 513 #define CMDLINE_OPT_CONFIG "config" 514 515 /* Parse the arguments given in the command line of the application */ 516 static int 517 parse_args(int argc, char **argv) 518 { 519 int opt, longindex, ret = 0; 520 const char *prgname = argv[0]; 521 static struct option longopts[] = { 522 {CMDLINE_OPT_CONFIG, required_argument, NULL, 0}, 523 {NULL, 0, NULL, 0} 524 }; 525 526 /* Disable printing messages within getopt() */ 527 opterr = 0; 528 529 /* Parse command line */ 530 while ((opt = getopt_long(argc, argv, "p:Pm", longopts, 531 &longindex)) != EOF) { 532 switch (opt) { 533 case 'p': 534 ports_mask = parse_unsigned(optarg); 535 break; 536 case 'P': 537 promiscuous_on = 1; 538 break; 539 case 'm': 540 monitor_links = 1; 541 break; 542 case 0: 543 if (!strncmp(longopts[longindex].name, 544 CMDLINE_OPT_CONFIG, 545 sizeof(CMDLINE_OPT_CONFIG))) { 546 ret = parse_config(optarg); 547 if (ret) { 548 printf("Invalid config\n"); 549 print_usage(prgname); 550 return -1; 551 } 552 } 553 break; 554 default: 555 print_usage(prgname); 556 rte_exit(EXIT_FAILURE, "Invalid option specified\n"); 557 } 558 } 559 560 /* Check that options were parsed ok */ 561 if (validate_parameters(ports_mask) < 0) { 562 print_usage(prgname); 563 rte_exit(EXIT_FAILURE, "Invalid parameters\n"); 564 } 565 566 return ret; 567 } 568 569 /* Initialize KNI subsystem */ 570 static void 571 init_kni(void) 572 { 573 unsigned int num_of_kni_ports = 0, i; 574 struct kni_port_params **params = kni_port_params_array; 575 576 /* Calculate the maximum number of KNI interfaces that will be used */ 577 for (i = 0; i < RTE_MAX_ETHPORTS; i++) { 578 if (kni_port_params_array[i]) { 579 num_of_kni_ports += (params[i]->nb_lcore_k ? 580 params[i]->nb_lcore_k : 1); 581 } 582 } 583 584 /* Invoke rte KNI init to preallocate the ports */ 585 rte_kni_init(num_of_kni_ports); 586 } 587 588 /* Initialise a single port on an Ethernet device */ 589 static void 590 init_port(uint16_t port) 591 { 592 int ret; 593 uint16_t nb_rxd = NB_RXD; 594 uint16_t nb_txd = NB_TXD; 595 struct rte_eth_dev_info dev_info; 596 struct rte_eth_rxconf rxq_conf; 597 struct rte_eth_txconf txq_conf; 598 struct rte_eth_conf local_port_conf = port_conf; 599 600 /* Initialise device and RX/TX queues */ 601 RTE_LOG(INFO, APP, "Initialising port %u ...\n", (unsigned)port); 602 fflush(stdout); 603 604 ret = rte_eth_dev_info_get(port, &dev_info); 605 if (ret != 0) 606 rte_exit(EXIT_FAILURE, 607 "Error during getting device (port %u) info: %s\n", 608 port, strerror(-ret)); 609 610 if (dev_info.tx_offload_capa & RTE_ETH_TX_OFFLOAD_MBUF_FAST_FREE) 611 local_port_conf.txmode.offloads |= 612 RTE_ETH_TX_OFFLOAD_MBUF_FAST_FREE; 613 ret = rte_eth_dev_configure(port, 1, 1, &local_port_conf); 614 if (ret < 0) 615 rte_exit(EXIT_FAILURE, "Could not configure port%u (%d)\n", 616 (unsigned)port, ret); 617 618 ret = rte_eth_dev_adjust_nb_rx_tx_desc(port, &nb_rxd, &nb_txd); 619 if (ret < 0) 620 rte_exit(EXIT_FAILURE, "Could not adjust number of descriptors " 621 "for port%u (%d)\n", (unsigned)port, ret); 622 623 rxq_conf = dev_info.default_rxconf; 624 rxq_conf.offloads = local_port_conf.rxmode.offloads; 625 ret = rte_eth_rx_queue_setup(port, 0, nb_rxd, 626 rte_eth_dev_socket_id(port), &rxq_conf, pktmbuf_pool); 627 if (ret < 0) 628 rte_exit(EXIT_FAILURE, "Could not setup up RX queue for " 629 "port%u (%d)\n", (unsigned)port, ret); 630 631 txq_conf = dev_info.default_txconf; 632 txq_conf.offloads = local_port_conf.txmode.offloads; 633 ret = rte_eth_tx_queue_setup(port, 0, nb_txd, 634 rte_eth_dev_socket_id(port), &txq_conf); 635 if (ret < 0) 636 rte_exit(EXIT_FAILURE, "Could not setup up TX queue for " 637 "port%u (%d)\n", (unsigned)port, ret); 638 639 ret = rte_eth_dev_start(port); 640 if (ret < 0) 641 rte_exit(EXIT_FAILURE, "Could not start port%u (%d)\n", 642 (unsigned)port, ret); 643 644 if (promiscuous_on) { 645 ret = rte_eth_promiscuous_enable(port); 646 if (ret != 0) 647 rte_exit(EXIT_FAILURE, 648 "Could not enable promiscuous mode for port%u: %s\n", 649 port, rte_strerror(-ret)); 650 } 651 } 652 653 /* Check the link status of all ports in up to 9s, and print them finally */ 654 static void 655 check_all_ports_link_status(uint32_t port_mask) 656 { 657 #define CHECK_INTERVAL 100 /* 100ms */ 658 #define MAX_CHECK_TIME 90 /* 9s (90 * 100ms) in total */ 659 uint16_t portid; 660 uint8_t count, all_ports_up, print_flag = 0; 661 struct rte_eth_link link; 662 int ret; 663 char link_status_text[RTE_ETH_LINK_MAX_STR_LEN]; 664 665 printf("\nChecking link status\n"); 666 fflush(stdout); 667 for (count = 0; count <= MAX_CHECK_TIME; count++) { 668 all_ports_up = 1; 669 RTE_ETH_FOREACH_DEV(portid) { 670 if ((port_mask & (1 << portid)) == 0) 671 continue; 672 memset(&link, 0, sizeof(link)); 673 ret = rte_eth_link_get_nowait(portid, &link); 674 if (ret < 0) { 675 all_ports_up = 0; 676 if (print_flag == 1) 677 printf("Port %u link get failed: %s\n", 678 portid, rte_strerror(-ret)); 679 continue; 680 } 681 /* print link status if flag set */ 682 if (print_flag == 1) { 683 rte_eth_link_to_str(link_status_text, 684 sizeof(link_status_text), &link); 685 printf("Port %d %s\n", portid, 686 link_status_text); 687 continue; 688 } 689 /* clear all_ports_up flag if any link down */ 690 if (link.link_status == RTE_ETH_LINK_DOWN) { 691 all_ports_up = 0; 692 break; 693 } 694 } 695 /* after finally printing all link status, get out */ 696 if (print_flag == 1) 697 break; 698 699 if (all_ports_up == 0) { 700 printf("."); 701 fflush(stdout); 702 rte_delay_ms(CHECK_INTERVAL); 703 } 704 705 /* set the print_flag if all ports up or timeout */ 706 if (all_ports_up == 1 || count == (MAX_CHECK_TIME - 1)) { 707 print_flag = 1; 708 printf("done\n"); 709 } 710 } 711 } 712 713 static void 714 log_link_state(struct rte_kni *kni, int prev, struct rte_eth_link *link) 715 { 716 char link_status_text[RTE_ETH_LINK_MAX_STR_LEN]; 717 if (kni == NULL || link == NULL) 718 return; 719 720 rte_eth_link_to_str(link_status_text, sizeof(link_status_text), link); 721 if (prev != link->link_status) 722 RTE_LOG(INFO, APP, "%s NIC %s\n", 723 rte_kni_get_name(kni), 724 link_status_text); 725 } 726 727 /* 728 * Monitor the link status of all ports and update the 729 * corresponding KNI interface(s) 730 */ 731 static void * 732 monitor_all_ports_link_status(void *arg) 733 { 734 uint16_t portid; 735 struct rte_eth_link link; 736 unsigned int i; 737 struct kni_port_params **p = kni_port_params_array; 738 int prev; 739 (void) arg; 740 int ret; 741 742 while (monitor_links) { 743 rte_delay_ms(500); 744 RTE_ETH_FOREACH_DEV(portid) { 745 if ((ports_mask & (1 << portid)) == 0) 746 continue; 747 memset(&link, 0, sizeof(link)); 748 ret = rte_eth_link_get_nowait(portid, &link); 749 if (ret < 0) { 750 RTE_LOG(ERR, APP, 751 "Get link failed (port %u): %s\n", 752 portid, rte_strerror(-ret)); 753 continue; 754 } 755 for (i = 0; i < p[portid]->nb_kni; i++) { 756 prev = rte_kni_update_link(p[portid]->kni[i], 757 link.link_status); 758 log_link_state(p[portid]->kni[i], prev, &link); 759 } 760 } 761 } 762 return NULL; 763 } 764 765 static int 766 kni_change_mtu_(uint16_t port_id, unsigned int new_mtu) 767 { 768 int ret; 769 uint16_t nb_rxd = NB_RXD; 770 uint16_t nb_txd = NB_TXD; 771 struct rte_eth_conf conf; 772 struct rte_eth_dev_info dev_info; 773 struct rte_eth_rxconf rxq_conf; 774 struct rte_eth_txconf txq_conf; 775 776 if (!rte_eth_dev_is_valid_port(port_id)) { 777 RTE_LOG(ERR, APP, "Invalid port id %d\n", port_id); 778 return -EINVAL; 779 } 780 781 RTE_LOG(INFO, APP, "Change MTU of port %d to %u\n", port_id, new_mtu); 782 783 /* Stop specific port */ 784 ret = rte_eth_dev_stop(port_id); 785 if (ret != 0) { 786 RTE_LOG(ERR, APP, "Failed to stop port %d: %s\n", 787 port_id, rte_strerror(-ret)); 788 return ret; 789 } 790 791 memcpy(&conf, &port_conf, sizeof(conf)); 792 793 conf.rxmode.mtu = new_mtu; 794 ret = rte_eth_dev_configure(port_id, 1, 1, &conf); 795 if (ret < 0) { 796 RTE_LOG(ERR, APP, "Fail to reconfigure port %d\n", port_id); 797 return ret; 798 } 799 800 ret = rte_eth_dev_adjust_nb_rx_tx_desc(port_id, &nb_rxd, &nb_txd); 801 if (ret < 0) 802 rte_exit(EXIT_FAILURE, "Could not adjust number of descriptors " 803 "for port%u (%d)\n", (unsigned int)port_id, 804 ret); 805 806 ret = rte_eth_dev_info_get(port_id, &dev_info); 807 if (ret != 0) { 808 RTE_LOG(ERR, APP, 809 "Error during getting device (port %u) info: %s\n", 810 port_id, strerror(-ret)); 811 812 return ret; 813 } 814 815 rxq_conf = dev_info.default_rxconf; 816 rxq_conf.offloads = conf.rxmode.offloads; 817 ret = rte_eth_rx_queue_setup(port_id, 0, nb_rxd, 818 rte_eth_dev_socket_id(port_id), &rxq_conf, pktmbuf_pool); 819 if (ret < 0) { 820 RTE_LOG(ERR, APP, "Fail to setup Rx queue of port %d\n", 821 port_id); 822 return ret; 823 } 824 825 txq_conf = dev_info.default_txconf; 826 txq_conf.offloads = conf.txmode.offloads; 827 ret = rte_eth_tx_queue_setup(port_id, 0, nb_txd, 828 rte_eth_dev_socket_id(port_id), &txq_conf); 829 if (ret < 0) { 830 RTE_LOG(ERR, APP, "Fail to setup Tx queue of port %d\n", 831 port_id); 832 return ret; 833 } 834 835 /* Restart specific port */ 836 ret = rte_eth_dev_start(port_id); 837 if (ret < 0) { 838 RTE_LOG(ERR, APP, "Fail to restart port %d\n", port_id); 839 return ret; 840 } 841 842 return 0; 843 } 844 845 /* Callback for request of changing MTU */ 846 static int 847 kni_change_mtu(uint16_t port_id, unsigned int new_mtu) 848 { 849 int ret; 850 851 __atomic_fetch_add(&kni_pause, 1, __ATOMIC_RELAXED); 852 ret = kni_change_mtu_(port_id, new_mtu); 853 __atomic_fetch_sub(&kni_pause, 1, __ATOMIC_RELAXED); 854 855 return ret; 856 } 857 858 /* Callback for request of configuring network interface up/down */ 859 static int 860 kni_config_network_interface(uint16_t port_id, uint8_t if_up) 861 { 862 int ret = 0; 863 864 if (!rte_eth_dev_is_valid_port(port_id)) { 865 RTE_LOG(ERR, APP, "Invalid port id %d\n", port_id); 866 return -EINVAL; 867 } 868 869 RTE_LOG(INFO, APP, "Configure network interface of %d %s\n", 870 port_id, if_up ? "up" : "down"); 871 872 __atomic_fetch_add(&kni_pause, 1, __ATOMIC_RELAXED); 873 874 if (if_up != 0) { /* Configure network interface up */ 875 ret = rte_eth_dev_stop(port_id); 876 if (ret != 0) { 877 RTE_LOG(ERR, APP, "Failed to stop port %d: %s\n", 878 port_id, rte_strerror(-ret)); 879 __atomic_fetch_sub(&kni_pause, 1, __ATOMIC_RELAXED); 880 return ret; 881 } 882 ret = rte_eth_dev_start(port_id); 883 } else { /* Configure network interface down */ 884 ret = rte_eth_dev_stop(port_id); 885 if (ret != 0) { 886 RTE_LOG(ERR, APP, "Failed to stop port %d: %s\n", 887 port_id, rte_strerror(-ret)); 888 __atomic_fetch_sub(&kni_pause, 1, __ATOMIC_RELAXED); 889 return ret; 890 } 891 } 892 893 __atomic_fetch_sub(&kni_pause, 1, __ATOMIC_RELAXED); 894 895 if (ret < 0) 896 RTE_LOG(ERR, APP, "Failed to start port %d\n", port_id); 897 898 return ret; 899 } 900 901 static void 902 print_ethaddr(const char *name, struct rte_ether_addr *mac_addr) 903 { 904 char buf[RTE_ETHER_ADDR_FMT_SIZE]; 905 rte_ether_format_addr(buf, RTE_ETHER_ADDR_FMT_SIZE, mac_addr); 906 RTE_LOG(INFO, APP, "\t%s%s\n", name, buf); 907 } 908 909 /* Callback for request of configuring mac address */ 910 static int 911 kni_config_mac_address(uint16_t port_id, uint8_t mac_addr[]) 912 { 913 int ret = 0; 914 915 if (!rte_eth_dev_is_valid_port(port_id)) { 916 RTE_LOG(ERR, APP, "Invalid port id %d\n", port_id); 917 return -EINVAL; 918 } 919 920 RTE_LOG(INFO, APP, "Configure mac address of %d\n", port_id); 921 print_ethaddr("Address:", (struct rte_ether_addr *)mac_addr); 922 923 ret = rte_eth_dev_default_mac_addr_set(port_id, 924 (struct rte_ether_addr *)mac_addr); 925 if (ret < 0) 926 RTE_LOG(ERR, APP, "Failed to config mac_addr for port %d\n", 927 port_id); 928 929 return ret; 930 } 931 932 static int 933 kni_alloc(uint16_t port_id) 934 { 935 uint8_t i; 936 struct rte_kni *kni; 937 struct rte_kni_conf conf; 938 struct kni_port_params **params = kni_port_params_array; 939 int ret; 940 941 if (port_id >= RTE_MAX_ETHPORTS || !params[port_id]) 942 return -1; 943 944 params[port_id]->nb_kni = params[port_id]->nb_lcore_k ? 945 params[port_id]->nb_lcore_k : 1; 946 947 for (i = 0; i < params[port_id]->nb_kni; i++) { 948 /* Clear conf at first */ 949 memset(&conf, 0, sizeof(conf)); 950 if (params[port_id]->nb_lcore_k) { 951 snprintf(conf.name, RTE_KNI_NAMESIZE, 952 "vEth%u_%u", port_id, i); 953 conf.core_id = params[port_id]->lcore_k[i]; 954 conf.force_bind = 1; 955 } else 956 snprintf(conf.name, RTE_KNI_NAMESIZE, 957 "vEth%u", port_id); 958 conf.group_id = port_id; 959 conf.mbuf_size = MAX_PACKET_SZ; 960 /* 961 * The first KNI device associated to a port 962 * is the main, for multiple kernel thread 963 * environment. 964 */ 965 if (i == 0) { 966 struct rte_kni_ops ops; 967 struct rte_eth_dev_info dev_info; 968 969 ret = rte_eth_dev_info_get(port_id, &dev_info); 970 if (ret != 0) 971 rte_exit(EXIT_FAILURE, 972 "Error during getting device (port %u) info: %s\n", 973 port_id, strerror(-ret)); 974 975 /* Get the interface default mac address */ 976 ret = rte_eth_macaddr_get(port_id, 977 (struct rte_ether_addr *)&conf.mac_addr); 978 if (ret != 0) 979 rte_exit(EXIT_FAILURE, 980 "Failed to get MAC address (port %u): %s\n", 981 port_id, rte_strerror(-ret)); 982 983 rte_eth_dev_get_mtu(port_id, &conf.mtu); 984 985 conf.min_mtu = dev_info.min_mtu; 986 conf.max_mtu = dev_info.max_mtu; 987 988 memset(&ops, 0, sizeof(ops)); 989 ops.port_id = port_id; 990 ops.change_mtu = kni_change_mtu; 991 ops.config_network_if = kni_config_network_interface; 992 ops.config_mac_address = kni_config_mac_address; 993 994 kni = rte_kni_alloc(pktmbuf_pool, &conf, &ops); 995 } else 996 kni = rte_kni_alloc(pktmbuf_pool, &conf, NULL); 997 998 if (!kni) 999 rte_exit(EXIT_FAILURE, "Fail to create kni for " 1000 "port: %d\n", port_id); 1001 params[port_id]->kni[i] = kni; 1002 } 1003 1004 return 0; 1005 } 1006 1007 static int 1008 kni_free_kni(uint16_t port_id) 1009 { 1010 uint8_t i; 1011 int ret; 1012 struct kni_port_params **p = kni_port_params_array; 1013 1014 if (port_id >= RTE_MAX_ETHPORTS || !p[port_id]) 1015 return -1; 1016 1017 for (i = 0; i < p[port_id]->nb_kni; i++) { 1018 if (rte_kni_release(p[port_id]->kni[i])) 1019 printf("Fail to release kni\n"); 1020 p[port_id]->kni[i] = NULL; 1021 } 1022 ret = rte_eth_dev_stop(port_id); 1023 if (ret != 0) 1024 RTE_LOG(ERR, APP, "Failed to stop port %d: %s\n", 1025 port_id, rte_strerror(-ret)); 1026 rte_eth_dev_close(port_id); 1027 1028 return 0; 1029 } 1030 1031 /* Initialise ports/queues etc. and start main loop on each core */ 1032 int 1033 main(int argc, char** argv) 1034 { 1035 int ret; 1036 uint16_t nb_sys_ports, port; 1037 unsigned i; 1038 void *retval; 1039 pthread_t kni_link_tid; 1040 int pid; 1041 1042 /* Associate signal_handler function with USR signals */ 1043 signal(SIGUSR1, signal_handler); 1044 signal(SIGUSR2, signal_handler); 1045 signal(SIGRTMIN, signal_handler); 1046 signal(SIGINT, signal_handler); 1047 signal(SIGTERM, signal_handler); 1048 1049 /* Initialise EAL */ 1050 ret = rte_eal_init(argc, argv); 1051 if (ret < 0) 1052 rte_exit(EXIT_FAILURE, "Could not initialise EAL (%d)\n", ret); 1053 argc -= ret; 1054 argv += ret; 1055 1056 /* Parse application arguments (after the EAL ones) */ 1057 ret = parse_args(argc, argv); 1058 if (ret < 0) 1059 rte_exit(EXIT_FAILURE, "Could not parse input parameters\n"); 1060 1061 /* Create the mbuf pool */ 1062 pktmbuf_pool = rte_pktmbuf_pool_create("mbuf_pool", NB_MBUF, 1063 MEMPOOL_CACHE_SZ, 0, MBUF_DATA_SZ, rte_socket_id()); 1064 if (pktmbuf_pool == NULL) { 1065 rte_exit(EXIT_FAILURE, "Could not initialise mbuf pool\n"); 1066 return -1; 1067 } 1068 1069 /* Get number of ports found in scan */ 1070 nb_sys_ports = rte_eth_dev_count_avail(); 1071 if (nb_sys_ports == 0) 1072 rte_exit(EXIT_FAILURE, "No supported Ethernet device found\n"); 1073 1074 /* Check if the configured port ID is valid */ 1075 for (i = 0; i < RTE_MAX_ETHPORTS; i++) 1076 if (kni_port_params_array[i] && !rte_eth_dev_is_valid_port(i)) 1077 rte_exit(EXIT_FAILURE, "Configured invalid " 1078 "port ID %u\n", i); 1079 1080 /* Initialize KNI subsystem */ 1081 init_kni(); 1082 1083 /* Initialise each port */ 1084 RTE_ETH_FOREACH_DEV(port) { 1085 /* Skip ports that are not enabled */ 1086 if (!(ports_mask & (1 << port))) 1087 continue; 1088 init_port(port); 1089 1090 if (port >= RTE_MAX_ETHPORTS) 1091 rte_exit(EXIT_FAILURE, "Can not use more than " 1092 "%d ports for kni\n", RTE_MAX_ETHPORTS); 1093 1094 kni_alloc(port); 1095 } 1096 check_all_ports_link_status(ports_mask); 1097 1098 pid = getpid(); 1099 RTE_LOG(INFO, APP, "========================\n"); 1100 RTE_LOG(INFO, APP, "KNI Running\n"); 1101 RTE_LOG(INFO, APP, "kill -SIGUSR1 %d\n", pid); 1102 RTE_LOG(INFO, APP, " Show KNI Statistics.\n"); 1103 RTE_LOG(INFO, APP, "kill -SIGUSR2 %d\n", pid); 1104 RTE_LOG(INFO, APP, " Zero KNI Statistics.\n"); 1105 RTE_LOG(INFO, APP, "========================\n"); 1106 fflush(stdout); 1107 1108 ret = rte_ctrl_thread_create(&kni_link_tid, 1109 "KNI link status check", NULL, 1110 monitor_all_ports_link_status, NULL); 1111 if (ret < 0) 1112 rte_exit(EXIT_FAILURE, 1113 "Could not create link status thread!\n"); 1114 1115 /* Launch per-lcore function on every lcore */ 1116 rte_eal_mp_remote_launch(main_loop, NULL, CALL_MAIN); 1117 RTE_LCORE_FOREACH_WORKER(i) { 1118 if (rte_eal_wait_lcore(i) < 0) 1119 return -1; 1120 } 1121 monitor_links = 0; 1122 pthread_join(kni_link_tid, &retval); 1123 1124 /* Release resources */ 1125 RTE_ETH_FOREACH_DEV(port) { 1126 if (!(ports_mask & (1 << port))) 1127 continue; 1128 kni_free_kni(port); 1129 } 1130 for (i = 0; i < RTE_MAX_ETHPORTS; i++) 1131 if (kni_port_params_array[i]) { 1132 rte_free(kni_port_params_array[i]); 1133 kni_port_params_array[i] = NULL; 1134 } 1135 1136 /* clean up the EAL */ 1137 rte_eal_cleanup(); 1138 1139 return 0; 1140 } 1141