xref: /dpdk/examples/vm_power_manager/main.c (revision 20c78ac9ee23666a0db12fff7a5bd44d7b0a4db0)
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