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 <rte_pmd_ixgbe.h> 33 #include <rte_pmd_i40e.h> 34 #include <rte_pmd_bnxt.h> 35 36 #define RX_RING_SIZE 1024 37 #define TX_RING_SIZE 1024 38 39 #define NUM_MBUFS 8191 40 #define MBUF_CACHE_SIZE 250 41 #define BURST_SIZE 32 42 43 static uint32_t enabled_port_mask; 44 static volatile bool force_quit; 45 46 /****************/ 47 static const struct rte_eth_conf port_conf_default = { 48 .rxmode = { 49 .max_rx_pkt_len = ETHER_MAX_LEN, 50 }, 51 }; 52 53 static inline int 54 port_init(uint16_t port, struct rte_mempool *mbuf_pool) 55 { 56 struct rte_eth_conf port_conf = port_conf_default; 57 const uint16_t rx_rings = 1, tx_rings = 1; 58 int retval; 59 uint16_t q; 60 struct rte_eth_dev_info dev_info; 61 struct rte_eth_txconf txq_conf; 62 63 if (!rte_eth_dev_is_valid_port(port)) 64 return -1; 65 66 rte_eth_dev_info_get(port, &dev_info); 67 if (dev_info.tx_offload_capa & DEV_TX_OFFLOAD_MBUF_FAST_FREE) 68 port_conf.txmode.offloads |= 69 DEV_TX_OFFLOAD_MBUF_FAST_FREE; 70 71 /* Configure the Ethernet device. */ 72 retval = rte_eth_dev_configure(port, rx_rings, tx_rings, &port_conf); 73 if (retval != 0) 74 return retval; 75 76 /* Allocate and set up 1 RX queue per Ethernet port. */ 77 for (q = 0; q < rx_rings; q++) { 78 retval = rte_eth_rx_queue_setup(port, q, RX_RING_SIZE, 79 rte_eth_dev_socket_id(port), NULL, mbuf_pool); 80 if (retval < 0) 81 return retval; 82 } 83 84 txq_conf = dev_info.default_txconf; 85 txq_conf.offloads = port_conf.txmode.offloads; 86 /* Allocate and set up 1 TX queue per Ethernet port. */ 87 for (q = 0; q < tx_rings; q++) { 88 retval = rte_eth_tx_queue_setup(port, q, TX_RING_SIZE, 89 rte_eth_dev_socket_id(port), &txq_conf); 90 if (retval < 0) 91 return retval; 92 } 93 94 /* Start the Ethernet port. */ 95 retval = rte_eth_dev_start(port); 96 if (retval < 0) 97 return retval; 98 99 /* Display the port MAC address. */ 100 struct ether_addr addr; 101 rte_eth_macaddr_get(port, &addr); 102 printf("Port %u MAC: %02" PRIx8 " %02" PRIx8 " %02" PRIx8 103 " %02" PRIx8 " %02" PRIx8 " %02" PRIx8 "\n", 104 (unsigned int)port, 105 addr.addr_bytes[0], addr.addr_bytes[1], 106 addr.addr_bytes[2], addr.addr_bytes[3], 107 addr.addr_bytes[4], addr.addr_bytes[5]); 108 109 /* Enable RX in promiscuous mode for the Ethernet device. */ 110 rte_eth_promiscuous_enable(port); 111 112 113 return 0; 114 } 115 116 static int 117 parse_portmask(const char *portmask) 118 { 119 char *end = NULL; 120 unsigned long pm; 121 122 /* parse hexadecimal string */ 123 pm = strtoul(portmask, &end, 16); 124 if ((portmask[0] == '\0') || (end == NULL) || (*end != '\0')) 125 return -1; 126 127 if (pm == 0) 128 return -1; 129 130 return pm; 131 } 132 /* Parse the argument given in the command line of the application */ 133 static int 134 parse_args(int argc, char **argv) 135 { 136 int opt, ret; 137 char **argvopt; 138 int option_index; 139 char *prgname = argv[0]; 140 static struct option lgopts[] = { 141 { "mac-updating", no_argument, 0, 1}, 142 { "no-mac-updating", no_argument, 0, 0}, 143 {NULL, 0, 0, 0} 144 }; 145 argvopt = argv; 146 147 while ((opt = getopt_long(argc, argvopt, "p:q:T:", 148 lgopts, &option_index)) != EOF) { 149 150 switch (opt) { 151 /* portmask */ 152 case 'p': 153 enabled_port_mask = parse_portmask(optarg); 154 if (enabled_port_mask == 0) { 155 printf("invalid portmask\n"); 156 return -1; 157 } 158 break; 159 /* long options */ 160 case 0: 161 break; 162 163 default: 164 return -1; 165 } 166 } 167 168 if (optind >= 0) 169 argv[optind-1] = prgname; 170 171 ret = optind-1; 172 optind = 0; /* reset getopt lib */ 173 return ret; 174 } 175 176 static void 177 check_all_ports_link_status(uint32_t port_mask) 178 { 179 #define CHECK_INTERVAL 100 /* 100ms */ 180 #define MAX_CHECK_TIME 90 /* 9s (90 * 100ms) in total */ 181 uint16_t portid, count, all_ports_up, print_flag = 0; 182 struct rte_eth_link link; 183 184 printf("\nChecking link status"); 185 fflush(stdout); 186 for (count = 0; count <= MAX_CHECK_TIME; count++) { 187 if (force_quit) 188 return; 189 all_ports_up = 1; 190 RTE_ETH_FOREACH_DEV(portid) { 191 if (force_quit) 192 return; 193 if ((port_mask & (1 << portid)) == 0) 194 continue; 195 memset(&link, 0, sizeof(link)); 196 rte_eth_link_get_nowait(portid, &link); 197 /* print link status if flag set */ 198 if (print_flag == 1) { 199 if (link.link_status) 200 printf("Port %d Link Up - speed %u " 201 "Mbps - %s\n", (uint16_t)portid, 202 (unsigned int)link.link_speed, 203 (link.link_duplex == ETH_LINK_FULL_DUPLEX) ? 204 ("full-duplex") : ("half-duplex\n")); 205 else 206 printf("Port %d Link Down\n", 207 (uint16_t)portid); 208 continue; 209 } 210 /* clear all_ports_up flag if any link down */ 211 if (link.link_status == ETH_LINK_DOWN) { 212 all_ports_up = 0; 213 break; 214 } 215 } 216 /* after finally printing all link status, get out */ 217 if (print_flag == 1) 218 break; 219 220 if (all_ports_up == 0) { 221 printf("."); 222 fflush(stdout); 223 rte_delay_ms(CHECK_INTERVAL); 224 } 225 226 /* set the print_flag if all ports up or timeout */ 227 if (all_ports_up == 1 || count == (MAX_CHECK_TIME - 1)) { 228 print_flag = 1; 229 printf("done\n"); 230 } 231 } 232 } 233 static int 234 run_monitor(__attribute__((unused)) void *arg) 235 { 236 if (channel_monitor_init() < 0) { 237 printf("Unable to initialize channel monitor\n"); 238 return -1; 239 } 240 run_channel_monitor(); 241 return 0; 242 } 243 244 static void 245 sig_handler(int signo) 246 { 247 printf("Received signal %d, exiting...\n", signo); 248 channel_monitor_exit(); 249 channel_manager_exit(); 250 power_manager_exit(); 251 252 } 253 254 int 255 main(int argc, char **argv) 256 { 257 int ret; 258 unsigned lcore_id; 259 unsigned int nb_ports; 260 struct rte_mempool *mbuf_pool; 261 uint16_t portid; 262 263 264 ret = rte_eal_init(argc, argv); 265 if (ret < 0) 266 rte_panic("Cannot init EAL\n"); 267 268 signal(SIGINT, sig_handler); 269 signal(SIGTERM, sig_handler); 270 271 argc -= ret; 272 argv += ret; 273 274 /* parse application arguments (after the EAL ones) */ 275 ret = parse_args(argc, argv); 276 if (ret < 0) 277 rte_exit(EXIT_FAILURE, "Invalid arguments\n"); 278 279 nb_ports = rte_eth_dev_count_avail(); 280 281 mbuf_pool = rte_pktmbuf_pool_create("MBUF_POOL", NUM_MBUFS * nb_ports, 282 MBUF_CACHE_SIZE, 0, RTE_MBUF_DEFAULT_BUF_SIZE, rte_socket_id()); 283 284 if (mbuf_pool == NULL) 285 rte_exit(EXIT_FAILURE, "Cannot create mbuf pool\n"); 286 287 /* Initialize ports. */ 288 RTE_ETH_FOREACH_DEV(portid) { 289 struct ether_addr eth; 290 int w, j; 291 int ret; 292 293 if ((enabled_port_mask & (1 << portid)) == 0) 294 continue; 295 296 eth.addr_bytes[0] = 0xe0; 297 eth.addr_bytes[1] = 0xe0; 298 eth.addr_bytes[2] = 0xe0; 299 eth.addr_bytes[3] = 0xe0; 300 eth.addr_bytes[4] = portid + 0xf0; 301 302 if (port_init(portid, mbuf_pool) != 0) 303 rte_exit(EXIT_FAILURE, "Cannot init port %"PRIu8 "\n", 304 portid); 305 306 for (w = 0; w < MAX_VFS; w++) { 307 eth.addr_bytes[5] = w + 0xf0; 308 309 ret = rte_pmd_ixgbe_set_vf_mac_addr(portid, 310 w, ð); 311 if (ret == -ENOTSUP) 312 ret = rte_pmd_i40e_set_vf_mac_addr(portid, 313 w, ð); 314 if (ret == -ENOTSUP) 315 ret = rte_pmd_bnxt_set_vf_mac_addr(portid, 316 w, ð); 317 318 switch (ret) { 319 case 0: 320 printf("Port %d VF %d MAC: ", 321 portid, w); 322 for (j = 0; j < 6; j++) { 323 printf("%02x", eth.addr_bytes[j]); 324 if (j < 5) 325 printf(":"); 326 } 327 printf("\n"); 328 break; 329 } 330 } 331 } 332 333 lcore_id = rte_get_next_lcore(-1, 1, 0); 334 if (lcore_id == RTE_MAX_LCORE) { 335 RTE_LOG(ERR, EAL, "A minimum of two cores are required to run " 336 "application\n"); 337 return 0; 338 } 339 340 check_all_ports_link_status(enabled_port_mask); 341 rte_eal_remote_launch(run_monitor, NULL, lcore_id); 342 343 if (power_manager_init() < 0) { 344 printf("Unable to initialize power manager\n"); 345 return -1; 346 } 347 if (channel_manager_init(CHANNEL_MGR_DEFAULT_HV_PATH) < 0) { 348 printf("Unable to initialize channel manager\n"); 349 return -1; 350 } 351 run_cli(NULL); 352 353 rte_eal_mp_wait_lcore(); 354 return 0; 355 } 356