1 /*- 2 * BSD LICENSE 3 * 4 * Copyright(c) 2010-2014 Intel Corporation. All rights reserved. 5 * All rights reserved. 6 * 7 * Redistribution and use in source and binary forms, with or without 8 * modification, are permitted provided that the following conditions 9 * are met: 10 * 11 * * Redistributions of source code must retain the above copyright 12 * notice, this list of conditions and the following disclaimer. 13 * * Redistributions in binary form must reproduce the above copyright 14 * notice, this list of conditions and the following disclaimer in 15 * the documentation and/or other materials provided with the 16 * distribution. 17 * * Neither the name of Intel Corporation nor the names of its 18 * contributors may be used to endorse or promote products derived 19 * from this software without specific prior written permission. 20 * 21 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 22 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 23 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR 24 * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 25 * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 26 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 27 * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 28 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 29 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 30 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 31 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 32 */ 33 34 #include <stdio.h> 35 #include <string.h> 36 #include <stdint.h> 37 #include <sys/epoll.h> 38 #include <fcntl.h> 39 #include <unistd.h> 40 #include <stdlib.h> 41 #include <signal.h> 42 #include <errno.h> 43 44 #include <sys/queue.h> 45 46 #include <rte_common.h> 47 #include <rte_eal.h> 48 #include <rte_launch.h> 49 #include <rte_log.h> 50 #include <rte_per_lcore.h> 51 #include <rte_lcore.h> 52 #include <rte_ethdev.h> 53 #include <getopt.h> 54 #include <rte_cycles.h> 55 #include <rte_debug.h> 56 57 #include "channel_manager.h" 58 #include "channel_monitor.h" 59 #include "power_manager.h" 60 #include "vm_power_cli.h" 61 #include <rte_pmd_ixgbe.h> 62 #include <rte_pmd_i40e.h> 63 #include <rte_pmd_bnxt.h> 64 65 #define RX_RING_SIZE 512 66 #define TX_RING_SIZE 512 67 68 #define NUM_MBUFS 8191 69 #define MBUF_CACHE_SIZE 250 70 #define BURST_SIZE 32 71 72 static uint32_t enabled_port_mask; 73 static volatile bool force_quit; 74 75 /****************/ 76 static const struct rte_eth_conf port_conf_default = { 77 .rxmode = { .max_rx_pkt_len = ETHER_MAX_LEN } 78 }; 79 80 static inline int 81 port_init(uint16_t port, struct rte_mempool *mbuf_pool) 82 { 83 struct rte_eth_conf port_conf = port_conf_default; 84 const uint16_t rx_rings = 1, tx_rings = 1; 85 int retval; 86 uint16_t q; 87 88 if (port >= rte_eth_dev_count()) 89 return -1; 90 91 /* Configure the Ethernet device. */ 92 retval = rte_eth_dev_configure(port, rx_rings, tx_rings, &port_conf); 93 if (retval != 0) 94 return retval; 95 96 /* Allocate and set up 1 RX queue per Ethernet port. */ 97 for (q = 0; q < rx_rings; q++) { 98 retval = rte_eth_rx_queue_setup(port, q, RX_RING_SIZE, 99 rte_eth_dev_socket_id(port), NULL, mbuf_pool); 100 if (retval < 0) 101 return retval; 102 } 103 104 /* Allocate and set up 1 TX queue per Ethernet port. */ 105 for (q = 0; q < tx_rings; q++) { 106 retval = rte_eth_tx_queue_setup(port, q, TX_RING_SIZE, 107 rte_eth_dev_socket_id(port), NULL); 108 if (retval < 0) 109 return retval; 110 } 111 112 /* Start the Ethernet port. */ 113 retval = rte_eth_dev_start(port); 114 if (retval < 0) 115 return retval; 116 117 /* Display the port MAC address. */ 118 struct ether_addr addr; 119 rte_eth_macaddr_get(port, &addr); 120 printf("Port %u MAC: %02" PRIx8 " %02" PRIx8 " %02" PRIx8 121 " %02" PRIx8 " %02" PRIx8 " %02" PRIx8 "\n", 122 (unsigned int)port, 123 addr.addr_bytes[0], addr.addr_bytes[1], 124 addr.addr_bytes[2], addr.addr_bytes[3], 125 addr.addr_bytes[4], addr.addr_bytes[5]); 126 127 /* Enable RX in promiscuous mode for the Ethernet device. */ 128 rte_eth_promiscuous_enable(port); 129 130 131 return 0; 132 } 133 134 static int 135 parse_portmask(const char *portmask) 136 { 137 char *end = NULL; 138 unsigned long pm; 139 140 /* parse hexadecimal string */ 141 pm = strtoul(portmask, &end, 16); 142 if ((portmask[0] == '\0') || (end == NULL) || (*end != '\0')) 143 return -1; 144 145 if (pm == 0) 146 return -1; 147 148 return pm; 149 } 150 /* Parse the argument given in the command line of the application */ 151 static int 152 parse_args(int argc, char **argv) 153 { 154 int opt, ret; 155 char **argvopt; 156 int option_index; 157 char *prgname = argv[0]; 158 static struct option lgopts[] = { 159 { "mac-updating", no_argument, 0, 1}, 160 { "no-mac-updating", no_argument, 0, 0}, 161 {NULL, 0, 0, 0} 162 }; 163 argvopt = argv; 164 165 while ((opt = getopt_long(argc, argvopt, "p:q:T:", 166 lgopts, &option_index)) != EOF) { 167 168 switch (opt) { 169 /* portmask */ 170 case 'p': 171 enabled_port_mask = parse_portmask(optarg); 172 if (enabled_port_mask == 0) { 173 printf("invalid portmask\n"); 174 return -1; 175 } 176 break; 177 /* long options */ 178 case 0: 179 break; 180 181 default: 182 return -1; 183 } 184 } 185 186 if (optind >= 0) 187 argv[optind-1] = prgname; 188 189 ret = optind-1; 190 optind = 0; /* reset getopt lib */ 191 return ret; 192 } 193 194 static void 195 check_all_ports_link_status(uint16_t port_num, uint32_t port_mask) 196 { 197 #define CHECK_INTERVAL 100 /* 100ms */ 198 #define MAX_CHECK_TIME 90 /* 9s (90 * 100ms) in total */ 199 uint16_t portid, count, all_ports_up, print_flag = 0; 200 struct rte_eth_link link; 201 202 printf("\nChecking link status"); 203 fflush(stdout); 204 for (count = 0; count <= MAX_CHECK_TIME; count++) { 205 if (force_quit) 206 return; 207 all_ports_up = 1; 208 for (portid = 0; portid < port_num; portid++) { 209 if (force_quit) 210 return; 211 if ((port_mask & (1 << portid)) == 0) 212 continue; 213 memset(&link, 0, sizeof(link)); 214 rte_eth_link_get_nowait(portid, &link); 215 /* print link status if flag set */ 216 if (print_flag == 1) { 217 if (link.link_status) 218 printf("Port %d Link Up - speed %u " 219 "Mbps - %s\n", (uint16_t)portid, 220 (unsigned int)link.link_speed, 221 (link.link_duplex == ETH_LINK_FULL_DUPLEX) ? 222 ("full-duplex") : ("half-duplex\n")); 223 else 224 printf("Port %d Link Down\n", 225 (uint16_t)portid); 226 continue; 227 } 228 /* clear all_ports_up flag if any link down */ 229 if (link.link_status == ETH_LINK_DOWN) { 230 all_ports_up = 0; 231 break; 232 } 233 } 234 /* after finally printing all link status, get out */ 235 if (print_flag == 1) 236 break; 237 238 if (all_ports_up == 0) { 239 printf("."); 240 fflush(stdout); 241 rte_delay_ms(CHECK_INTERVAL); 242 } 243 244 /* set the print_flag if all ports up or timeout */ 245 if (all_ports_up == 1 || count == (MAX_CHECK_TIME - 1)) { 246 print_flag = 1; 247 printf("done\n"); 248 } 249 } 250 } 251 static int 252 run_monitor(__attribute__((unused)) void *arg) 253 { 254 if (channel_monitor_init() < 0) { 255 printf("Unable to initialize channel monitor\n"); 256 return -1; 257 } 258 run_channel_monitor(); 259 return 0; 260 } 261 262 static void 263 sig_handler(int signo) 264 { 265 printf("Received signal %d, exiting...\n", signo); 266 channel_monitor_exit(); 267 channel_manager_exit(); 268 power_manager_exit(); 269 270 } 271 272 int 273 main(int argc, char **argv) 274 { 275 int ret; 276 unsigned lcore_id; 277 unsigned int nb_ports; 278 struct rte_mempool *mbuf_pool; 279 uint16_t portid; 280 281 282 ret = rte_eal_init(argc, argv); 283 if (ret < 0) 284 rte_panic("Cannot init EAL\n"); 285 286 signal(SIGINT, sig_handler); 287 signal(SIGTERM, sig_handler); 288 289 argc -= ret; 290 argv += ret; 291 292 /* parse application arguments (after the EAL ones) */ 293 ret = parse_args(argc, argv); 294 if (ret < 0) 295 rte_exit(EXIT_FAILURE, "Invalid arguments\n"); 296 297 nb_ports = rte_eth_dev_count(); 298 299 mbuf_pool = rte_pktmbuf_pool_create("MBUF_POOL", NUM_MBUFS * nb_ports, 300 MBUF_CACHE_SIZE, 0, RTE_MBUF_DEFAULT_BUF_SIZE, rte_socket_id()); 301 302 if (mbuf_pool == NULL) 303 rte_exit(EXIT_FAILURE, "Cannot create mbuf pool\n"); 304 305 /* Initialize ports. */ 306 for (portid = 0; portid < nb_ports; portid++) { 307 struct ether_addr eth; 308 int w, j; 309 int ret = -ENOTSUP; 310 311 if ((enabled_port_mask & (1 << portid)) == 0) 312 continue; 313 314 eth.addr_bytes[0] = 0xe0; 315 eth.addr_bytes[1] = 0xe0; 316 eth.addr_bytes[2] = 0xe0; 317 eth.addr_bytes[3] = 0xe0; 318 eth.addr_bytes[4] = portid + 0xf0; 319 320 if (port_init(portid, mbuf_pool) != 0) 321 rte_exit(EXIT_FAILURE, "Cannot init port %"PRIu8 "\n", 322 portid); 323 324 for (w = 0; w < MAX_VFS; w++) { 325 eth.addr_bytes[5] = w + 0xf0; 326 327 if (ret == -ENOTSUP) 328 ret = rte_pmd_ixgbe_set_vf_mac_addr(portid, 329 w, ð); 330 if (ret == -ENOTSUP) 331 ret = rte_pmd_i40e_set_vf_mac_addr(portid, 332 w, ð); 333 if (ret == -ENOTSUP) 334 ret = rte_pmd_bnxt_set_vf_mac_addr(portid, 335 w, ð); 336 337 switch (ret) { 338 case 0: 339 printf("Port %d VF %d MAC: ", 340 portid, w); 341 for (j = 0; j < 6; j++) { 342 printf("%02x", eth.addr_bytes[j]); 343 if (j < 5) 344 printf(":"); 345 } 346 printf("\n"); 347 break; 348 } 349 } 350 } 351 352 lcore_id = rte_get_next_lcore(-1, 1, 0); 353 if (lcore_id == RTE_MAX_LCORE) { 354 RTE_LOG(ERR, EAL, "A minimum of two cores are required to run " 355 "application\n"); 356 return 0; 357 } 358 359 check_all_ports_link_status(nb_ports, enabled_port_mask); 360 rte_eal_remote_launch(run_monitor, NULL, lcore_id); 361 362 if (power_manager_init() < 0) { 363 printf("Unable to initialize power manager\n"); 364 return -1; 365 } 366 if (channel_manager_init(CHANNEL_MGR_DEFAULT_HV_PATH) < 0) { 367 printf("Unable to initialize channel manager\n"); 368 return -1; 369 } 370 run_cli(NULL); 371 372 rte_eal_mp_wait_lcore(); 373 return 0; 374 } 375