1 /* SPDX-License-Identifier: BSD-3-Clause 2 * Copyright(c) 2010-2014 Intel Corporation 3 */ 4 5 #include <stdio.h> 6 #include <string.h> 7 #include <stdint.h> 8 #include <sys/epoll.h> 9 #include <fcntl.h> 10 #include <unistd.h> 11 #include <stdlib.h> 12 #include <signal.h> 13 #include <errno.h> 14 15 #include <sys/queue.h> 16 17 #include <rte_common.h> 18 #include <rte_eal.h> 19 #include <rte_launch.h> 20 #include <rte_log.h> 21 #include <rte_per_lcore.h> 22 #include <rte_lcore.h> 23 #include <rte_ethdev.h> 24 #include <getopt.h> 25 #include <rte_cycles.h> 26 #include <rte_debug.h> 27 28 #include "channel_manager.h" 29 #include "channel_monitor.h" 30 #include "power_manager.h" 31 #include "vm_power_cli.h" 32 #include "oob_monitor.h" 33 #include "parse.h" 34 #ifdef RTE_LIBRTE_IXGBE_PMD 35 #include <rte_pmd_ixgbe.h> 36 #endif 37 #ifdef RTE_LIBRTE_I40E_PMD 38 #include <rte_pmd_i40e.h> 39 #endif 40 #ifdef RTE_LIBRTE_BNXT_PMD 41 #include <rte_pmd_bnxt.h> 42 #endif 43 44 #define RX_RING_SIZE 1024 45 #define TX_RING_SIZE 1024 46 47 #define NUM_MBUFS 8191 48 #define MBUF_CACHE_SIZE 250 49 #define BURST_SIZE 32 50 51 static uint32_t enabled_port_mask; 52 static volatile bool force_quit; 53 54 /****************/ 55 static const struct rte_eth_conf port_conf_default = { 56 .rxmode = { 57 .max_rx_pkt_len = RTE_ETHER_MAX_LEN, 58 }, 59 }; 60 61 static inline int 62 port_init(uint16_t port, struct rte_mempool *mbuf_pool) 63 { 64 struct rte_eth_conf port_conf = port_conf_default; 65 const uint16_t rx_rings = 1, tx_rings = 1; 66 int retval; 67 uint16_t q; 68 struct rte_eth_dev_info dev_info; 69 struct rte_eth_txconf txq_conf; 70 71 if (!rte_eth_dev_is_valid_port(port)) 72 return -1; 73 74 retval = rte_eth_dev_info_get(port, &dev_info); 75 if (retval != 0) { 76 printf("Error during getting device (port %u) info: %s\n", 77 port, strerror(-retval)); 78 return retval; 79 } 80 81 if (dev_info.tx_offload_capa & DEV_TX_OFFLOAD_MBUF_FAST_FREE) 82 port_conf.txmode.offloads |= 83 DEV_TX_OFFLOAD_MBUF_FAST_FREE; 84 85 /* Configure the Ethernet device. */ 86 retval = rte_eth_dev_configure(port, rx_rings, tx_rings, &port_conf); 87 if (retval != 0) 88 return retval; 89 90 /* Allocate and set up 1 RX queue per Ethernet port. */ 91 for (q = 0; q < rx_rings; q++) { 92 retval = rte_eth_rx_queue_setup(port, q, RX_RING_SIZE, 93 rte_eth_dev_socket_id(port), NULL, mbuf_pool); 94 if (retval < 0) 95 return retval; 96 } 97 98 txq_conf = dev_info.default_txconf; 99 txq_conf.offloads = port_conf.txmode.offloads; 100 /* Allocate and set up 1 TX queue per Ethernet port. */ 101 for (q = 0; q < tx_rings; q++) { 102 retval = rte_eth_tx_queue_setup(port, q, TX_RING_SIZE, 103 rte_eth_dev_socket_id(port), &txq_conf); 104 if (retval < 0) 105 return retval; 106 } 107 108 /* Start the Ethernet port. */ 109 retval = rte_eth_dev_start(port); 110 if (retval < 0) 111 return retval; 112 113 /* Display the port MAC address. */ 114 struct rte_ether_addr addr; 115 rte_eth_macaddr_get(port, &addr); 116 printf("Port %u MAC: %02" PRIx8 " %02" PRIx8 " %02" PRIx8 117 " %02" PRIx8 " %02" PRIx8 " %02" PRIx8 "\n", 118 (unsigned int)port, 119 addr.addr_bytes[0], addr.addr_bytes[1], 120 addr.addr_bytes[2], addr.addr_bytes[3], 121 addr.addr_bytes[4], addr.addr_bytes[5]); 122 123 /* Enable RX in promiscuous mode for the Ethernet device. */ 124 rte_eth_promiscuous_enable(port); 125 126 127 return 0; 128 } 129 130 static int 131 parse_portmask(const char *portmask) 132 { 133 char *end = NULL; 134 unsigned long pm; 135 136 /* parse hexadecimal string */ 137 pm = strtoul(portmask, &end, 16); 138 if ((portmask[0] == '\0') || (end == NULL) || (*end != '\0')) 139 return -1; 140 141 if (pm == 0) 142 return -1; 143 144 return pm; 145 } 146 /* Parse the argument given in the command line of the application */ 147 static int 148 parse_args(int argc, char **argv) 149 { 150 int opt, ret, cnt, i; 151 char **argvopt; 152 uint16_t *oob_enable; 153 int option_index; 154 char *prgname = argv[0]; 155 struct core_info *ci; 156 float branch_ratio; 157 static struct option lgopts[] = { 158 { "mac-updating", no_argument, 0, 1}, 159 { "no-mac-updating", no_argument, 0, 0}, 160 { "core-list", optional_argument, 0, 'l'}, 161 { "port-list", optional_argument, 0, 'p'}, 162 { "branch-ratio", optional_argument, 0, 'b'}, 163 {NULL, 0, 0, 0} 164 }; 165 argvopt = argv; 166 ci = get_core_info(); 167 168 while ((opt = getopt_long(argc, argvopt, "l:p:q:T:b:", 169 lgopts, &option_index)) != EOF) { 170 171 switch (opt) { 172 /* portmask */ 173 case 'p': 174 enabled_port_mask = parse_portmask(optarg); 175 if (enabled_port_mask == 0) { 176 printf("invalid portmask\n"); 177 return -1; 178 } 179 break; 180 case 'l': 181 oob_enable = malloc(ci->core_count * sizeof(uint16_t)); 182 if (oob_enable == NULL) { 183 printf("Error - Unable to allocate memory\n"); 184 return -1; 185 } 186 cnt = parse_set(optarg, oob_enable, ci->core_count); 187 if (cnt < 0) { 188 printf("Invalid core-list - [%s]\n", 189 optarg); 190 free(oob_enable); 191 break; 192 } 193 for (i = 0; i < ci->core_count; i++) { 194 if (oob_enable[i]) { 195 printf("***Using core %d\n", i); 196 ci->cd[i].oob_enabled = 1; 197 ci->cd[i].global_enabled_cpus = 1; 198 } 199 } 200 free(oob_enable); 201 break; 202 case 'b': 203 branch_ratio = 0.0; 204 if (strlen(optarg)) 205 branch_ratio = atof(optarg); 206 if (branch_ratio <= 0.0) { 207 printf("invalid branch ratio specified\n"); 208 return -1; 209 } 210 ci->branch_ratio_threshold = branch_ratio; 211 printf("***Setting branch ratio to %f\n", 212 branch_ratio); 213 break; 214 /* long options */ 215 case 0: 216 break; 217 218 default: 219 return -1; 220 } 221 } 222 223 if (optind >= 0) 224 argv[optind-1] = prgname; 225 226 ret = optind-1; 227 optind = 0; /* reset getopt lib */ 228 return ret; 229 } 230 231 static void 232 check_all_ports_link_status(uint32_t port_mask) 233 { 234 #define CHECK_INTERVAL 100 /* 100ms */ 235 #define MAX_CHECK_TIME 90 /* 9s (90 * 100ms) in total */ 236 uint16_t portid, count, all_ports_up, print_flag = 0; 237 struct rte_eth_link link; 238 239 printf("\nChecking link status"); 240 fflush(stdout); 241 for (count = 0; count <= MAX_CHECK_TIME; count++) { 242 if (force_quit) 243 return; 244 all_ports_up = 1; 245 RTE_ETH_FOREACH_DEV(portid) { 246 if (force_quit) 247 return; 248 if ((port_mask & (1 << portid)) == 0) 249 continue; 250 memset(&link, 0, sizeof(link)); 251 rte_eth_link_get_nowait(portid, &link); 252 /* print link status if flag set */ 253 if (print_flag == 1) { 254 if (link.link_status) 255 printf("Port %d Link Up - speed %u " 256 "Mbps - %s\n", (uint16_t)portid, 257 (unsigned int)link.link_speed, 258 (link.link_duplex == ETH_LINK_FULL_DUPLEX) ? 259 ("full-duplex") : ("half-duplex\n")); 260 else 261 printf("Port %d Link Down\n", 262 (uint16_t)portid); 263 continue; 264 } 265 /* clear all_ports_up flag if any link down */ 266 if (link.link_status == ETH_LINK_DOWN) { 267 all_ports_up = 0; 268 break; 269 } 270 } 271 /* after finally printing all link status, get out */ 272 if (print_flag == 1) 273 break; 274 275 if (all_ports_up == 0) { 276 printf("."); 277 fflush(stdout); 278 rte_delay_ms(CHECK_INTERVAL); 279 } 280 281 /* set the print_flag if all ports up or timeout */ 282 if (all_ports_up == 1 || count == (MAX_CHECK_TIME - 1)) { 283 print_flag = 1; 284 printf("done\n"); 285 } 286 } 287 } 288 static int 289 run_monitor(__attribute__((unused)) void *arg) 290 { 291 if (channel_monitor_init() < 0) { 292 printf("Unable to initialize channel monitor\n"); 293 return -1; 294 } 295 run_channel_monitor(); 296 return 0; 297 } 298 299 static int 300 run_core_monitor(__attribute__((unused)) void *arg) 301 { 302 if (branch_monitor_init() < 0) { 303 printf("Unable to initialize core monitor\n"); 304 return -1; 305 } 306 run_branch_monitor(); 307 return 0; 308 } 309 310 static void 311 sig_handler(int signo) 312 { 313 printf("Received signal %d, exiting...\n", signo); 314 channel_monitor_exit(); 315 channel_manager_exit(); 316 power_manager_exit(); 317 318 } 319 320 int 321 main(int argc, char **argv) 322 { 323 int ret; 324 unsigned lcore_id; 325 unsigned int nb_ports; 326 struct rte_mempool *mbuf_pool; 327 uint16_t portid; 328 struct core_info *ci; 329 330 331 ret = core_info_init(); 332 if (ret < 0) 333 rte_panic("Cannot allocate core info\n"); 334 335 ci = get_core_info(); 336 337 ret = rte_eal_init(argc, argv); 338 if (ret < 0) 339 rte_panic("Cannot init EAL\n"); 340 341 signal(SIGINT, sig_handler); 342 signal(SIGTERM, sig_handler); 343 344 argc -= ret; 345 argv += ret; 346 347 /* parse application arguments (after the EAL ones) */ 348 ret = parse_args(argc, argv); 349 if (ret < 0) 350 rte_exit(EXIT_FAILURE, "Invalid arguments\n"); 351 352 nb_ports = rte_eth_dev_count_avail(); 353 354 if (nb_ports > 0) { 355 mbuf_pool = rte_pktmbuf_pool_create("MBUF_POOL", 356 NUM_MBUFS * nb_ports, MBUF_CACHE_SIZE, 0, 357 RTE_MBUF_DEFAULT_BUF_SIZE, rte_socket_id()); 358 359 if (mbuf_pool == NULL) 360 rte_exit(EXIT_FAILURE, "Cannot create mbuf pool\n"); 361 362 /* Initialize ports. */ 363 RTE_ETH_FOREACH_DEV(portid) { 364 struct rte_ether_addr eth; 365 int w, j; 366 int ret; 367 368 if ((enabled_port_mask & (1 << portid)) == 0) 369 continue; 370 371 eth.addr_bytes[0] = 0xe0; 372 eth.addr_bytes[1] = 0xe0; 373 eth.addr_bytes[2] = 0xe0; 374 eth.addr_bytes[3] = 0xe0; 375 eth.addr_bytes[4] = portid + 0xf0; 376 377 if (port_init(portid, mbuf_pool) != 0) 378 rte_exit(EXIT_FAILURE, 379 "Cannot init port %"PRIu8 "\n", 380 portid); 381 382 for (w = 0; w < MAX_VFS; w++) { 383 eth.addr_bytes[5] = w + 0xf0; 384 385 ret = -ENOTSUP; 386 #ifdef RTE_LIBRTE_IXGBE_PMD 387 ret = rte_pmd_ixgbe_set_vf_mac_addr(portid, 388 w, ð); 389 #endif 390 #ifdef RTE_LIBRTE_I40E_PMD 391 if (ret == -ENOTSUP) 392 ret = rte_pmd_i40e_set_vf_mac_addr( 393 portid, w, ð); 394 #endif 395 #ifdef RTE_LIBRTE_BNXT_PMD 396 if (ret == -ENOTSUP) 397 ret = rte_pmd_bnxt_set_vf_mac_addr( 398 portid, w, ð); 399 #endif 400 401 switch (ret) { 402 case 0: 403 printf("Port %d VF %d MAC: ", 404 portid, w); 405 for (j = 0; j < 5; j++) { 406 printf("%02x:", 407 eth.addr_bytes[j]); 408 } 409 printf("%02x\n", eth.addr_bytes[5]); 410 break; 411 } 412 printf("\n"); 413 } 414 } 415 } 416 417 check_all_ports_link_status(enabled_port_mask); 418 419 lcore_id = rte_get_next_lcore(-1, 1, 0); 420 if (lcore_id == RTE_MAX_LCORE) { 421 RTE_LOG(ERR, EAL, "A minimum of three cores are required to run " 422 "application\n"); 423 return 0; 424 } 425 printf("Running channel monitor on lcore id %d\n", lcore_id); 426 rte_eal_remote_launch(run_monitor, NULL, lcore_id); 427 428 lcore_id = rte_get_next_lcore(lcore_id, 1, 0); 429 if (lcore_id == RTE_MAX_LCORE) { 430 RTE_LOG(ERR, EAL, "A minimum of three cores are required to run " 431 "application\n"); 432 return 0; 433 } 434 if (power_manager_init() < 0) { 435 printf("Unable to initialize power manager\n"); 436 return -1; 437 } 438 if (channel_manager_init(CHANNEL_MGR_DEFAULT_HV_PATH) < 0) { 439 printf("Unable to initialize channel manager\n"); 440 return -1; 441 } 442 443 add_host_channels(); 444 445 printf("Running core monitor on lcore id %d\n", lcore_id); 446 rte_eal_remote_launch(run_core_monitor, NULL, lcore_id); 447 448 run_cli(NULL); 449 450 branch_monitor_exit(); 451 452 rte_eal_mp_wait_lcore(); 453 454 free(ci->cd); 455 456 return 0; 457 } 458