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