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