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