examples: use SPDX tag for Intel copyright files
[dpdk.git] / examples / vm_power_manager / main.c
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, &eth);
301                         if (ret == -ENOTSUP)
302                                 ret = rte_pmd_i40e_set_vf_mac_addr(portid,
303                                                 w, &eth);
304                         if (ret == -ENOTSUP)
305                                 ret = rte_pmd_bnxt_set_vf_mac_addr(portid,
306                                                 w, &eth);
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 }