18db653ffSAlan Carew /*- 28db653ffSAlan Carew * BSD LICENSE 38db653ffSAlan Carew * 48db653ffSAlan Carew * Copyright(c) 2010-2014 Intel Corporation. All rights reserved. 58db653ffSAlan Carew * All rights reserved. 68db653ffSAlan Carew * 78db653ffSAlan Carew * Redistribution and use in source and binary forms, with or without 88db653ffSAlan Carew * modification, are permitted provided that the following conditions 98db653ffSAlan Carew * are met: 108db653ffSAlan Carew * 118db653ffSAlan Carew * * Redistributions of source code must retain the above copyright 128db653ffSAlan Carew * notice, this list of conditions and the following disclaimer. 138db653ffSAlan Carew * * Redistributions in binary form must reproduce the above copyright 148db653ffSAlan Carew * notice, this list of conditions and the following disclaimer in 158db653ffSAlan Carew * the documentation and/or other materials provided with the 168db653ffSAlan Carew * distribution. 178db653ffSAlan Carew * * Neither the name of Intel Corporation nor the names of its 188db653ffSAlan Carew * contributors may be used to endorse or promote products derived 198db653ffSAlan Carew * from this software without specific prior written permission. 208db653ffSAlan Carew * 218db653ffSAlan Carew * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 228db653ffSAlan Carew * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 238db653ffSAlan Carew * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR 248db653ffSAlan Carew * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 258db653ffSAlan Carew * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 268db653ffSAlan Carew * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 278db653ffSAlan Carew * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 288db653ffSAlan Carew * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 298db653ffSAlan Carew * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 308db653ffSAlan Carew * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 318db653ffSAlan Carew * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 328db653ffSAlan Carew */ 338db653ffSAlan Carew 348db653ffSAlan Carew #include <stdio.h> 358db653ffSAlan Carew #include <string.h> 368db653ffSAlan Carew #include <stdint.h> 378db653ffSAlan Carew #include <sys/epoll.h> 388db653ffSAlan Carew #include <fcntl.h> 398db653ffSAlan Carew #include <unistd.h> 408db653ffSAlan Carew #include <stdlib.h> 418db653ffSAlan Carew #include <signal.h> 428db653ffSAlan Carew #include <errno.h> 438db653ffSAlan Carew 448db653ffSAlan Carew #include <sys/queue.h> 458db653ffSAlan Carew 468db653ffSAlan Carew #include <rte_common.h> 478db653ffSAlan Carew #include <rte_eal.h> 488db653ffSAlan Carew #include <rte_launch.h> 498db653ffSAlan Carew #include <rte_log.h> 508db653ffSAlan Carew #include <rte_per_lcore.h> 518db653ffSAlan Carew #include <rte_lcore.h> 52*20c78ac9SDavid Hunt #include <rte_ethdev.h> 53*20c78ac9SDavid Hunt #include <getopt.h> 54*20c78ac9SDavid Hunt #include <rte_cycles.h> 558db653ffSAlan Carew #include <rte_debug.h> 568db653ffSAlan Carew 578db653ffSAlan Carew #include "channel_manager.h" 588db653ffSAlan Carew #include "channel_monitor.h" 598db653ffSAlan Carew #include "power_manager.h" 608db653ffSAlan Carew #include "vm_power_cli.h" 618db653ffSAlan Carew 62*20c78ac9SDavid Hunt #define RX_RING_SIZE 512 63*20c78ac9SDavid Hunt #define TX_RING_SIZE 512 64*20c78ac9SDavid Hunt 65*20c78ac9SDavid Hunt #define NUM_MBUFS 8191 66*20c78ac9SDavid Hunt #define MBUF_CACHE_SIZE 250 67*20c78ac9SDavid Hunt #define BURST_SIZE 32 68*20c78ac9SDavid Hunt 69*20c78ac9SDavid Hunt static uint32_t enabled_port_mask; 70*20c78ac9SDavid Hunt static volatile bool force_quit; 71*20c78ac9SDavid Hunt 72*20c78ac9SDavid Hunt /****************/ 73*20c78ac9SDavid Hunt static const struct rte_eth_conf port_conf_default = { 74*20c78ac9SDavid Hunt .rxmode = { .max_rx_pkt_len = ETHER_MAX_LEN } 75*20c78ac9SDavid Hunt }; 76*20c78ac9SDavid Hunt 77*20c78ac9SDavid Hunt static inline int 78*20c78ac9SDavid Hunt port_init(uint16_t port, struct rte_mempool *mbuf_pool) 79*20c78ac9SDavid Hunt { 80*20c78ac9SDavid Hunt struct rte_eth_conf port_conf = port_conf_default; 81*20c78ac9SDavid Hunt const uint16_t rx_rings = 1, tx_rings = 1; 82*20c78ac9SDavid Hunt int retval; 83*20c78ac9SDavid Hunt uint16_t q; 84*20c78ac9SDavid Hunt 85*20c78ac9SDavid Hunt if (port >= rte_eth_dev_count()) 86*20c78ac9SDavid Hunt return -1; 87*20c78ac9SDavid Hunt 88*20c78ac9SDavid Hunt /* Configure the Ethernet device. */ 89*20c78ac9SDavid Hunt retval = rte_eth_dev_configure(port, rx_rings, tx_rings, &port_conf); 90*20c78ac9SDavid Hunt if (retval != 0) 91*20c78ac9SDavid Hunt return retval; 92*20c78ac9SDavid Hunt 93*20c78ac9SDavid Hunt /* Allocate and set up 1 RX queue per Ethernet port. */ 94*20c78ac9SDavid Hunt for (q = 0; q < rx_rings; q++) { 95*20c78ac9SDavid Hunt retval = rte_eth_rx_queue_setup(port, q, RX_RING_SIZE, 96*20c78ac9SDavid Hunt rte_eth_dev_socket_id(port), NULL, mbuf_pool); 97*20c78ac9SDavid Hunt if (retval < 0) 98*20c78ac9SDavid Hunt return retval; 99*20c78ac9SDavid Hunt } 100*20c78ac9SDavid Hunt 101*20c78ac9SDavid Hunt /* Allocate and set up 1 TX queue per Ethernet port. */ 102*20c78ac9SDavid Hunt for (q = 0; q < tx_rings; q++) { 103*20c78ac9SDavid Hunt retval = rte_eth_tx_queue_setup(port, q, TX_RING_SIZE, 104*20c78ac9SDavid Hunt rte_eth_dev_socket_id(port), NULL); 105*20c78ac9SDavid Hunt if (retval < 0) 106*20c78ac9SDavid Hunt return retval; 107*20c78ac9SDavid Hunt } 108*20c78ac9SDavid Hunt 109*20c78ac9SDavid Hunt /* Start the Ethernet port. */ 110*20c78ac9SDavid Hunt retval = rte_eth_dev_start(port); 111*20c78ac9SDavid Hunt if (retval < 0) 112*20c78ac9SDavid Hunt return retval; 113*20c78ac9SDavid Hunt 114*20c78ac9SDavid Hunt /* Display the port MAC address. */ 115*20c78ac9SDavid Hunt struct ether_addr addr; 116*20c78ac9SDavid Hunt rte_eth_macaddr_get(port, &addr); 117*20c78ac9SDavid Hunt printf("Port %u MAC: %02" PRIx8 " %02" PRIx8 " %02" PRIx8 118*20c78ac9SDavid Hunt " %02" PRIx8 " %02" PRIx8 " %02" PRIx8 "\n", 119*20c78ac9SDavid Hunt (unsigned int)port, 120*20c78ac9SDavid Hunt addr.addr_bytes[0], addr.addr_bytes[1], 121*20c78ac9SDavid Hunt addr.addr_bytes[2], addr.addr_bytes[3], 122*20c78ac9SDavid Hunt addr.addr_bytes[4], addr.addr_bytes[5]); 123*20c78ac9SDavid Hunt 124*20c78ac9SDavid Hunt /* Enable RX in promiscuous mode for the Ethernet device. */ 125*20c78ac9SDavid Hunt rte_eth_promiscuous_enable(port); 126*20c78ac9SDavid Hunt 127*20c78ac9SDavid Hunt 128*20c78ac9SDavid Hunt return 0; 129*20c78ac9SDavid Hunt } 130*20c78ac9SDavid Hunt 131*20c78ac9SDavid Hunt static int 132*20c78ac9SDavid Hunt parse_portmask(const char *portmask) 133*20c78ac9SDavid Hunt { 134*20c78ac9SDavid Hunt char *end = NULL; 135*20c78ac9SDavid Hunt unsigned long pm; 136*20c78ac9SDavid Hunt 137*20c78ac9SDavid Hunt /* parse hexadecimal string */ 138*20c78ac9SDavid Hunt pm = strtoul(portmask, &end, 16); 139*20c78ac9SDavid Hunt if ((portmask[0] == '\0') || (end == NULL) || (*end != '\0')) 140*20c78ac9SDavid Hunt return -1; 141*20c78ac9SDavid Hunt 142*20c78ac9SDavid Hunt if (pm == 0) 143*20c78ac9SDavid Hunt return -1; 144*20c78ac9SDavid Hunt 145*20c78ac9SDavid Hunt return pm; 146*20c78ac9SDavid Hunt } 147*20c78ac9SDavid Hunt /* Parse the argument given in the command line of the application */ 148*20c78ac9SDavid Hunt static int 149*20c78ac9SDavid Hunt parse_args(int argc, char **argv) 150*20c78ac9SDavid Hunt { 151*20c78ac9SDavid Hunt int opt, ret; 152*20c78ac9SDavid Hunt char **argvopt; 153*20c78ac9SDavid Hunt int option_index; 154*20c78ac9SDavid Hunt char *prgname = argv[0]; 155*20c78ac9SDavid Hunt static struct option lgopts[] = { 156*20c78ac9SDavid Hunt { "mac-updating", no_argument, 0, 1}, 157*20c78ac9SDavid Hunt { "no-mac-updating", no_argument, 0, 0}, 158*20c78ac9SDavid Hunt {NULL, 0, 0, 0} 159*20c78ac9SDavid Hunt }; 160*20c78ac9SDavid Hunt argvopt = argv; 161*20c78ac9SDavid Hunt 162*20c78ac9SDavid Hunt while ((opt = getopt_long(argc, argvopt, "p:q:T:", 163*20c78ac9SDavid Hunt lgopts, &option_index)) != EOF) { 164*20c78ac9SDavid Hunt 165*20c78ac9SDavid Hunt switch (opt) { 166*20c78ac9SDavid Hunt /* portmask */ 167*20c78ac9SDavid Hunt case 'p': 168*20c78ac9SDavid Hunt enabled_port_mask = parse_portmask(optarg); 169*20c78ac9SDavid Hunt if (enabled_port_mask == 0) { 170*20c78ac9SDavid Hunt printf("invalid portmask\n"); 171*20c78ac9SDavid Hunt return -1; 172*20c78ac9SDavid Hunt } 173*20c78ac9SDavid Hunt break; 174*20c78ac9SDavid Hunt /* long options */ 175*20c78ac9SDavid Hunt case 0: 176*20c78ac9SDavid Hunt break; 177*20c78ac9SDavid Hunt 178*20c78ac9SDavid Hunt default: 179*20c78ac9SDavid Hunt return -1; 180*20c78ac9SDavid Hunt } 181*20c78ac9SDavid Hunt } 182*20c78ac9SDavid Hunt 183*20c78ac9SDavid Hunt if (optind >= 0) 184*20c78ac9SDavid Hunt argv[optind-1] = prgname; 185*20c78ac9SDavid Hunt 186*20c78ac9SDavid Hunt ret = optind-1; 187*20c78ac9SDavid Hunt optind = 0; /* reset getopt lib */ 188*20c78ac9SDavid Hunt return ret; 189*20c78ac9SDavid Hunt } 190*20c78ac9SDavid Hunt 191*20c78ac9SDavid Hunt static void 192*20c78ac9SDavid Hunt check_all_ports_link_status(uint16_t port_num, uint32_t port_mask) 193*20c78ac9SDavid Hunt { 194*20c78ac9SDavid Hunt #define CHECK_INTERVAL 100 /* 100ms */ 195*20c78ac9SDavid Hunt #define MAX_CHECK_TIME 90 /* 9s (90 * 100ms) in total */ 196*20c78ac9SDavid Hunt uint16_t portid, count, all_ports_up, print_flag = 0; 197*20c78ac9SDavid Hunt struct rte_eth_link link; 198*20c78ac9SDavid Hunt 199*20c78ac9SDavid Hunt printf("\nChecking link status"); 200*20c78ac9SDavid Hunt fflush(stdout); 201*20c78ac9SDavid Hunt for (count = 0; count <= MAX_CHECK_TIME; count++) { 202*20c78ac9SDavid Hunt if (force_quit) 203*20c78ac9SDavid Hunt return; 204*20c78ac9SDavid Hunt all_ports_up = 1; 205*20c78ac9SDavid Hunt for (portid = 0; portid < port_num; portid++) { 206*20c78ac9SDavid Hunt if (force_quit) 207*20c78ac9SDavid Hunt return; 208*20c78ac9SDavid Hunt if ((port_mask & (1 << portid)) == 0) 209*20c78ac9SDavid Hunt continue; 210*20c78ac9SDavid Hunt memset(&link, 0, sizeof(link)); 211*20c78ac9SDavid Hunt rte_eth_link_get_nowait(portid, &link); 212*20c78ac9SDavid Hunt /* print link status if flag set */ 213*20c78ac9SDavid Hunt if (print_flag == 1) { 214*20c78ac9SDavid Hunt if (link.link_status) 215*20c78ac9SDavid Hunt printf("Port %d Link Up - speed %u " 216*20c78ac9SDavid Hunt "Mbps - %s\n", (uint16_t)portid, 217*20c78ac9SDavid Hunt (unsigned int)link.link_speed, 218*20c78ac9SDavid Hunt (link.link_duplex == ETH_LINK_FULL_DUPLEX) ? 219*20c78ac9SDavid Hunt ("full-duplex") : ("half-duplex\n")); 220*20c78ac9SDavid Hunt else 221*20c78ac9SDavid Hunt printf("Port %d Link Down\n", 222*20c78ac9SDavid Hunt (uint16_t)portid); 223*20c78ac9SDavid Hunt continue; 224*20c78ac9SDavid Hunt } 225*20c78ac9SDavid Hunt /* clear all_ports_up flag if any link down */ 226*20c78ac9SDavid Hunt if (link.link_status == ETH_LINK_DOWN) { 227*20c78ac9SDavid Hunt all_ports_up = 0; 228*20c78ac9SDavid Hunt break; 229*20c78ac9SDavid Hunt } 230*20c78ac9SDavid Hunt } 231*20c78ac9SDavid Hunt /* after finally printing all link status, get out */ 232*20c78ac9SDavid Hunt if (print_flag == 1) 233*20c78ac9SDavid Hunt break; 234*20c78ac9SDavid Hunt 235*20c78ac9SDavid Hunt if (all_ports_up == 0) { 236*20c78ac9SDavid Hunt printf("."); 237*20c78ac9SDavid Hunt fflush(stdout); 238*20c78ac9SDavid Hunt rte_delay_ms(CHECK_INTERVAL); 239*20c78ac9SDavid Hunt } 240*20c78ac9SDavid Hunt 241*20c78ac9SDavid Hunt /* set the print_flag if all ports up or timeout */ 242*20c78ac9SDavid Hunt if (all_ports_up == 1 || count == (MAX_CHECK_TIME - 1)) { 243*20c78ac9SDavid Hunt print_flag = 1; 244*20c78ac9SDavid Hunt printf("done\n"); 245*20c78ac9SDavid Hunt } 246*20c78ac9SDavid Hunt } 247*20c78ac9SDavid Hunt } 2488db653ffSAlan Carew static int 2498db653ffSAlan Carew run_monitor(__attribute__((unused)) void *arg) 2508db653ffSAlan Carew { 2518db653ffSAlan Carew if (channel_monitor_init() < 0) { 2528db653ffSAlan Carew printf("Unable to initialize channel monitor\n"); 2538db653ffSAlan Carew return -1; 2548db653ffSAlan Carew } 2558db653ffSAlan Carew run_channel_monitor(); 2568db653ffSAlan Carew return 0; 2578db653ffSAlan Carew } 2588db653ffSAlan Carew 2598db653ffSAlan Carew static void 2608db653ffSAlan Carew sig_handler(int signo) 2618db653ffSAlan Carew { 2628db653ffSAlan Carew printf("Received signal %d, exiting...\n", signo); 2638db653ffSAlan Carew channel_monitor_exit(); 2648db653ffSAlan Carew channel_manager_exit(); 2658db653ffSAlan Carew power_manager_exit(); 2668db653ffSAlan Carew 2678db653ffSAlan Carew } 2688db653ffSAlan Carew 2698db653ffSAlan Carew int 27098a16481SDavid Marchand main(int argc, char **argv) 2718db653ffSAlan Carew { 2728db653ffSAlan Carew int ret; 2738db653ffSAlan Carew unsigned lcore_id; 274*20c78ac9SDavid Hunt unsigned int nb_ports; 275*20c78ac9SDavid Hunt struct rte_mempool *mbuf_pool; 276*20c78ac9SDavid Hunt uint16_t portid; 277*20c78ac9SDavid Hunt 2788db653ffSAlan Carew 2798db653ffSAlan Carew ret = rte_eal_init(argc, argv); 2808db653ffSAlan Carew if (ret < 0) 2818db653ffSAlan Carew rte_panic("Cannot init EAL\n"); 2828db653ffSAlan Carew 2838db653ffSAlan Carew signal(SIGINT, sig_handler); 2848db653ffSAlan Carew signal(SIGTERM, sig_handler); 2858db653ffSAlan Carew 286*20c78ac9SDavid Hunt argc -= ret; 287*20c78ac9SDavid Hunt argv += ret; 288*20c78ac9SDavid Hunt 289*20c78ac9SDavid Hunt /* parse application arguments (after the EAL ones) */ 290*20c78ac9SDavid Hunt ret = parse_args(argc, argv); 291*20c78ac9SDavid Hunt if (ret < 0) 292*20c78ac9SDavid Hunt rte_exit(EXIT_FAILURE, "Invalid arguments\n"); 293*20c78ac9SDavid Hunt 294*20c78ac9SDavid Hunt nb_ports = rte_eth_dev_count(); 295*20c78ac9SDavid Hunt 296*20c78ac9SDavid Hunt mbuf_pool = rte_pktmbuf_pool_create("MBUF_POOL", NUM_MBUFS * nb_ports, 297*20c78ac9SDavid Hunt MBUF_CACHE_SIZE, 0, RTE_MBUF_DEFAULT_BUF_SIZE, rte_socket_id()); 298*20c78ac9SDavid Hunt 299*20c78ac9SDavid Hunt if (mbuf_pool == NULL) 300*20c78ac9SDavid Hunt rte_exit(EXIT_FAILURE, "Cannot create mbuf pool\n"); 301*20c78ac9SDavid Hunt 302*20c78ac9SDavid Hunt /* Initialize ports. */ 303*20c78ac9SDavid Hunt for (portid = 0; portid < nb_ports; portid++) { 304*20c78ac9SDavid Hunt if ((enabled_port_mask & (1 << portid)) == 0) 305*20c78ac9SDavid Hunt continue; 306*20c78ac9SDavid Hunt if (port_init(portid, mbuf_pool) != 0) 307*20c78ac9SDavid Hunt rte_exit(EXIT_FAILURE, "Cannot init port %"PRIu8 "\n", 308*20c78ac9SDavid Hunt portid); 309*20c78ac9SDavid Hunt } 310*20c78ac9SDavid Hunt 3118db653ffSAlan Carew lcore_id = rte_get_next_lcore(-1, 1, 0); 3128db653ffSAlan Carew if (lcore_id == RTE_MAX_LCORE) { 3138db653ffSAlan Carew RTE_LOG(ERR, EAL, "A minimum of two cores are required to run " 3148db653ffSAlan Carew "application\n"); 3158db653ffSAlan Carew return 0; 3168db653ffSAlan Carew } 317*20c78ac9SDavid Hunt 318*20c78ac9SDavid Hunt check_all_ports_link_status(nb_ports, enabled_port_mask); 3198db653ffSAlan Carew rte_eal_remote_launch(run_monitor, NULL, lcore_id); 3208db653ffSAlan Carew 3218db653ffSAlan Carew if (power_manager_init() < 0) { 3228db653ffSAlan Carew printf("Unable to initialize power manager\n"); 3238db653ffSAlan Carew return -1; 3248db653ffSAlan Carew } 3258db653ffSAlan Carew if (channel_manager_init(CHANNEL_MGR_DEFAULT_HV_PATH) < 0) { 3268db653ffSAlan Carew printf("Unable to initialize channel manager\n"); 3278db653ffSAlan Carew return -1; 3288db653ffSAlan Carew } 3298db653ffSAlan Carew run_cli(NULL); 3308db653ffSAlan Carew 3318db653ffSAlan Carew rte_eal_mp_wait_lcore(); 3328db653ffSAlan Carew return 0; 3338db653ffSAlan Carew } 334