]>
Commit | Line | Data |
---|---|---|
9f95a23c TL |
1 | /* SPDX-License-Identifier: BSD-3-Clause |
2 | * Copyright(c) 2010-2014 Intel Corporation | |
7c673cae FG |
3 | */ |
4 | ||
5 | #include <stdio.h> | |
6 | #include <string.h> | |
7 | #include <stdint.h> | |
7c673cae FG |
8 | #include <sys/epoll.h> |
9 | #include <fcntl.h> | |
10 | #include <unistd.h> | |
11 | #include <stdlib.h> | |
7c673cae FG |
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> | |
9f95a23c TL |
23 | #include <rte_ethdev.h> |
24 | #include <getopt.h> | |
25 | #include <rte_cycles.h> | |
7c673cae FG |
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" | |
9f95a23c TL |
32 | #include "oob_monitor.h" |
33 | #include "parse.h" | |
34 | #ifdef RTE_LIBRTE_IXGBE_PMD | |
35 | #include <rte_pmd_ixgbe.h> | |
36 | #endif | |
37 | #ifdef RTE_LIBRTE_I40E_PMD | |
38 | #include <rte_pmd_i40e.h> | |
39 | #endif | |
40 | #ifdef RTE_LIBRTE_BNXT_PMD | |
41 | #include <rte_pmd_bnxt.h> | |
42 | #endif | |
43 | ||
44 | #define RX_RING_SIZE 1024 | |
45 | #define TX_RING_SIZE 1024 | |
46 | ||
47 | #define NUM_MBUFS 8191 | |
48 | #define MBUF_CACHE_SIZE 250 | |
49 | #define BURST_SIZE 32 | |
50 | ||
51 | static uint32_t enabled_port_mask; | |
52 | static volatile bool force_quit; | |
53 | ||
54 | /****************/ | |
55 | static const struct rte_eth_conf port_conf_default = { | |
56 | .rxmode = { | |
57 | .max_rx_pkt_len = ETHER_MAX_LEN, | |
58 | }, | |
59 | }; | |
60 | ||
61 | static inline int | |
62 | port_init(uint16_t port, struct rte_mempool *mbuf_pool) | |
63 | { | |
64 | struct rte_eth_conf port_conf = port_conf_default; | |
65 | const uint16_t rx_rings = 1, tx_rings = 1; | |
66 | int retval; | |
67 | uint16_t q; | |
68 | struct rte_eth_dev_info dev_info; | |
69 | struct rte_eth_txconf txq_conf; | |
70 | ||
71 | if (!rte_eth_dev_is_valid_port(port)) | |
72 | return -1; | |
73 | ||
74 | rte_eth_dev_info_get(port, &dev_info); | |
75 | if (dev_info.tx_offload_capa & DEV_TX_OFFLOAD_MBUF_FAST_FREE) | |
76 | port_conf.txmode.offloads |= | |
77 | DEV_TX_OFFLOAD_MBUF_FAST_FREE; | |
78 | ||
79 | /* Configure the Ethernet device. */ | |
80 | retval = rte_eth_dev_configure(port, rx_rings, tx_rings, &port_conf); | |
81 | if (retval != 0) | |
82 | return retval; | |
83 | ||
84 | /* Allocate and set up 1 RX queue per Ethernet port. */ | |
85 | for (q = 0; q < rx_rings; q++) { | |
86 | retval = rte_eth_rx_queue_setup(port, q, RX_RING_SIZE, | |
87 | rte_eth_dev_socket_id(port), NULL, mbuf_pool); | |
88 | if (retval < 0) | |
89 | return retval; | |
90 | } | |
91 | ||
92 | txq_conf = dev_info.default_txconf; | |
93 | txq_conf.offloads = port_conf.txmode.offloads; | |
94 | /* Allocate and set up 1 TX queue per Ethernet port. */ | |
95 | for (q = 0; q < tx_rings; q++) { | |
96 | retval = rte_eth_tx_queue_setup(port, q, TX_RING_SIZE, | |
97 | rte_eth_dev_socket_id(port), &txq_conf); | |
98 | if (retval < 0) | |
99 | return retval; | |
100 | } | |
101 | ||
102 | /* Start the Ethernet port. */ | |
103 | retval = rte_eth_dev_start(port); | |
104 | if (retval < 0) | |
105 | return retval; | |
106 | ||
107 | /* Display the port MAC address. */ | |
108 | struct ether_addr addr; | |
109 | rte_eth_macaddr_get(port, &addr); | |
110 | printf("Port %u MAC: %02" PRIx8 " %02" PRIx8 " %02" PRIx8 | |
111 | " %02" PRIx8 " %02" PRIx8 " %02" PRIx8 "\n", | |
112 | (unsigned int)port, | |
113 | addr.addr_bytes[0], addr.addr_bytes[1], | |
114 | addr.addr_bytes[2], addr.addr_bytes[3], | |
115 | addr.addr_bytes[4], addr.addr_bytes[5]); | |
116 | ||
117 | /* Enable RX in promiscuous mode for the Ethernet device. */ | |
118 | rte_eth_promiscuous_enable(port); | |
119 | ||
120 | ||
121 | return 0; | |
122 | } | |
123 | ||
124 | static int | |
125 | parse_portmask(const char *portmask) | |
126 | { | |
127 | char *end = NULL; | |
128 | unsigned long pm; | |
129 | ||
130 | /* parse hexadecimal string */ | |
131 | pm = strtoul(portmask, &end, 16); | |
132 | if ((portmask[0] == '\0') || (end == NULL) || (*end != '\0')) | |
133 | return -1; | |
134 | ||
135 | if (pm == 0) | |
136 | return -1; | |
137 | ||
138 | return pm; | |
139 | } | |
140 | /* Parse the argument given in the command line of the application */ | |
141 | static int | |
142 | parse_args(int argc, char **argv) | |
143 | { | |
144 | int opt, ret, cnt, i; | |
145 | char **argvopt; | |
146 | uint16_t *oob_enable; | |
147 | int option_index; | |
148 | char *prgname = argv[0]; | |
149 | struct core_info *ci; | |
150 | float branch_ratio; | |
151 | static struct option lgopts[] = { | |
152 | { "mac-updating", no_argument, 0, 1}, | |
153 | { "no-mac-updating", no_argument, 0, 0}, | |
154 | { "core-list", optional_argument, 0, 'l'}, | |
155 | { "port-list", optional_argument, 0, 'p'}, | |
156 | { "branch-ratio", optional_argument, 0, 'b'}, | |
157 | {NULL, 0, 0, 0} | |
158 | }; | |
159 | argvopt = argv; | |
160 | ci = get_core_info(); | |
161 | ||
162 | while ((opt = getopt_long(argc, argvopt, "l:p:q:T:b:", | |
163 | lgopts, &option_index)) != EOF) { | |
164 | ||
165 | switch (opt) { | |
166 | /* portmask */ | |
167 | case 'p': | |
168 | enabled_port_mask = parse_portmask(optarg); | |
169 | if (enabled_port_mask == 0) { | |
170 | printf("invalid portmask\n"); | |
171 | return -1; | |
172 | } | |
173 | break; | |
174 | case 'l': | |
175 | oob_enable = malloc(ci->core_count * sizeof(uint16_t)); | |
176 | if (oob_enable == NULL) { | |
177 | printf("Error - Unable to allocate memory\n"); | |
178 | return -1; | |
179 | } | |
180 | cnt = parse_set(optarg, oob_enable, ci->core_count); | |
181 | if (cnt < 0) { | |
182 | printf("Invalid core-list - [%s]\n", | |
183 | optarg); | |
184 | free(oob_enable); | |
185 | break; | |
186 | } | |
187 | for (i = 0; i < ci->core_count; i++) { | |
188 | if (oob_enable[i]) { | |
189 | printf("***Using core %d\n", i); | |
190 | ci->cd[i].oob_enabled = 1; | |
191 | ci->cd[i].global_enabled_cpus = 1; | |
192 | } | |
193 | } | |
194 | free(oob_enable); | |
195 | break; | |
196 | case 'b': | |
197 | branch_ratio = 0.0; | |
198 | if (strlen(optarg)) | |
199 | branch_ratio = atof(optarg); | |
200 | if (branch_ratio <= 0.0) { | |
201 | printf("invalid branch ratio specified\n"); | |
202 | return -1; | |
203 | } | |
204 | ci->branch_ratio_threshold = branch_ratio; | |
205 | printf("***Setting branch ratio to %f\n", | |
206 | branch_ratio); | |
207 | break; | |
208 | /* long options */ | |
209 | case 0: | |
210 | break; | |
211 | ||
212 | default: | |
213 | return -1; | |
214 | } | |
215 | } | |
216 | ||
217 | if (optind >= 0) | |
218 | argv[optind-1] = prgname; | |
219 | ||
220 | ret = optind-1; | |
221 | optind = 0; /* reset getopt lib */ | |
222 | return ret; | |
223 | } | |
224 | ||
225 | static void | |
226 | check_all_ports_link_status(uint32_t port_mask) | |
227 | { | |
228 | #define CHECK_INTERVAL 100 /* 100ms */ | |
229 | #define MAX_CHECK_TIME 90 /* 9s (90 * 100ms) in total */ | |
230 | uint16_t portid, count, all_ports_up, print_flag = 0; | |
231 | struct rte_eth_link link; | |
232 | ||
233 | printf("\nChecking link status"); | |
234 | fflush(stdout); | |
235 | for (count = 0; count <= MAX_CHECK_TIME; count++) { | |
236 | if (force_quit) | |
237 | return; | |
238 | all_ports_up = 1; | |
239 | RTE_ETH_FOREACH_DEV(portid) { | |
240 | if (force_quit) | |
241 | return; | |
242 | if ((port_mask & (1 << portid)) == 0) | |
243 | continue; | |
244 | memset(&link, 0, sizeof(link)); | |
245 | rte_eth_link_get_nowait(portid, &link); | |
246 | /* print link status if flag set */ | |
247 | if (print_flag == 1) { | |
248 | if (link.link_status) | |
249 | printf("Port %d Link Up - speed %u " | |
250 | "Mbps - %s\n", (uint16_t)portid, | |
251 | (unsigned int)link.link_speed, | |
252 | (link.link_duplex == ETH_LINK_FULL_DUPLEX) ? | |
253 | ("full-duplex") : ("half-duplex\n")); | |
254 | else | |
255 | printf("Port %d Link Down\n", | |
256 | (uint16_t)portid); | |
257 | continue; | |
258 | } | |
259 | /* clear all_ports_up flag if any link down */ | |
260 | if (link.link_status == ETH_LINK_DOWN) { | |
261 | all_ports_up = 0; | |
262 | break; | |
263 | } | |
264 | } | |
265 | /* after finally printing all link status, get out */ | |
266 | if (print_flag == 1) | |
267 | break; | |
7c673cae | 268 | |
9f95a23c TL |
269 | if (all_ports_up == 0) { |
270 | printf("."); | |
271 | fflush(stdout); | |
272 | rte_delay_ms(CHECK_INTERVAL); | |
273 | } | |
274 | ||
275 | /* set the print_flag if all ports up or timeout */ | |
276 | if (all_ports_up == 1 || count == (MAX_CHECK_TIME - 1)) { | |
277 | print_flag = 1; | |
278 | printf("done\n"); | |
279 | } | |
280 | } | |
281 | } | |
7c673cae FG |
282 | static int |
283 | run_monitor(__attribute__((unused)) void *arg) | |
284 | { | |
285 | if (channel_monitor_init() < 0) { | |
286 | printf("Unable to initialize channel monitor\n"); | |
287 | return -1; | |
288 | } | |
289 | run_channel_monitor(); | |
290 | return 0; | |
291 | } | |
292 | ||
9f95a23c TL |
293 | static int |
294 | run_core_monitor(__attribute__((unused)) void *arg) | |
295 | { | |
296 | if (branch_monitor_init() < 0) { | |
297 | printf("Unable to initialize core monitor\n"); | |
298 | return -1; | |
299 | } | |
300 | run_branch_monitor(); | |
301 | return 0; | |
302 | } | |
303 | ||
7c673cae FG |
304 | static void |
305 | sig_handler(int signo) | |
306 | { | |
307 | printf("Received signal %d, exiting...\n", signo); | |
308 | channel_monitor_exit(); | |
309 | channel_manager_exit(); | |
310 | power_manager_exit(); | |
311 | ||
312 | } | |
313 | ||
314 | int | |
315 | main(int argc, char **argv) | |
316 | { | |
317 | int ret; | |
318 | unsigned lcore_id; | |
9f95a23c TL |
319 | unsigned int nb_ports; |
320 | struct rte_mempool *mbuf_pool; | |
321 | uint16_t portid; | |
322 | struct core_info *ci; | |
323 | ||
324 | ||
325 | ret = core_info_init(); | |
326 | if (ret < 0) | |
327 | rte_panic("Cannot allocate core info\n"); | |
328 | ||
329 | ci = get_core_info(); | |
7c673cae FG |
330 | |
331 | ret = rte_eal_init(argc, argv); | |
332 | if (ret < 0) | |
333 | rte_panic("Cannot init EAL\n"); | |
334 | ||
335 | signal(SIGINT, sig_handler); | |
336 | signal(SIGTERM, sig_handler); | |
337 | ||
9f95a23c TL |
338 | argc -= ret; |
339 | argv += ret; | |
340 | ||
341 | /* parse application arguments (after the EAL ones) */ | |
342 | ret = parse_args(argc, argv); | |
343 | if (ret < 0) | |
344 | rte_exit(EXIT_FAILURE, "Invalid arguments\n"); | |
345 | ||
346 | nb_ports = rte_eth_dev_count_avail(); | |
347 | ||
348 | if (nb_ports > 0) { | |
349 | mbuf_pool = rte_pktmbuf_pool_create("MBUF_POOL", | |
350 | NUM_MBUFS * nb_ports, MBUF_CACHE_SIZE, 0, | |
351 | RTE_MBUF_DEFAULT_BUF_SIZE, rte_socket_id()); | |
352 | ||
353 | if (mbuf_pool == NULL) | |
354 | rte_exit(EXIT_FAILURE, "Cannot create mbuf pool\n"); | |
355 | ||
356 | /* Initialize ports. */ | |
357 | RTE_ETH_FOREACH_DEV(portid) { | |
358 | struct ether_addr eth; | |
359 | int w, j; | |
360 | int ret; | |
361 | ||
362 | if ((enabled_port_mask & (1 << portid)) == 0) | |
363 | continue; | |
364 | ||
365 | eth.addr_bytes[0] = 0xe0; | |
366 | eth.addr_bytes[1] = 0xe0; | |
367 | eth.addr_bytes[2] = 0xe0; | |
368 | eth.addr_bytes[3] = 0xe0; | |
369 | eth.addr_bytes[4] = portid + 0xf0; | |
370 | ||
371 | if (port_init(portid, mbuf_pool) != 0) | |
372 | rte_exit(EXIT_FAILURE, | |
373 | "Cannot init port %"PRIu8 "\n", | |
374 | portid); | |
375 | ||
376 | for (w = 0; w < MAX_VFS; w++) { | |
377 | eth.addr_bytes[5] = w + 0xf0; | |
378 | ||
379 | ret = -ENOTSUP; | |
380 | #ifdef RTE_LIBRTE_IXGBE_PMD | |
381 | ret = rte_pmd_ixgbe_set_vf_mac_addr(portid, | |
382 | w, ð); | |
383 | #endif | |
384 | #ifdef RTE_LIBRTE_I40E_PMD | |
385 | if (ret == -ENOTSUP) | |
386 | ret = rte_pmd_i40e_set_vf_mac_addr( | |
387 | portid, w, ð); | |
388 | #endif | |
389 | #ifdef RTE_LIBRTE_BNXT_PMD | |
390 | if (ret == -ENOTSUP) | |
391 | ret = rte_pmd_bnxt_set_vf_mac_addr( | |
392 | portid, w, ð); | |
393 | #endif | |
394 | ||
395 | switch (ret) { | |
396 | case 0: | |
397 | printf("Port %d VF %d MAC: ", | |
398 | portid, w); | |
399 | for (j = 0; j < 5; j++) { | |
400 | printf("%02x:", | |
401 | eth.addr_bytes[j]); | |
402 | } | |
403 | printf("%02x\n", eth.addr_bytes[5]); | |
404 | break; | |
405 | } | |
406 | printf("\n"); | |
407 | } | |
408 | } | |
409 | } | |
410 | ||
411 | check_all_ports_link_status(enabled_port_mask); | |
412 | ||
7c673cae FG |
413 | lcore_id = rte_get_next_lcore(-1, 1, 0); |
414 | if (lcore_id == RTE_MAX_LCORE) { | |
9f95a23c | 415 | RTE_LOG(ERR, EAL, "A minimum of three cores are required to run " |
7c673cae FG |
416 | "application\n"); |
417 | return 0; | |
418 | } | |
9f95a23c | 419 | printf("Running channel monitor on lcore id %d\n", lcore_id); |
7c673cae FG |
420 | rte_eal_remote_launch(run_monitor, NULL, lcore_id); |
421 | ||
9f95a23c TL |
422 | lcore_id = rte_get_next_lcore(lcore_id, 1, 0); |
423 | if (lcore_id == RTE_MAX_LCORE) { | |
424 | RTE_LOG(ERR, EAL, "A minimum of three cores are required to run " | |
425 | "application\n"); | |
426 | return 0; | |
427 | } | |
7c673cae FG |
428 | if (power_manager_init() < 0) { |
429 | printf("Unable to initialize power manager\n"); | |
430 | return -1; | |
431 | } | |
432 | if (channel_manager_init(CHANNEL_MGR_DEFAULT_HV_PATH) < 0) { | |
433 | printf("Unable to initialize channel manager\n"); | |
434 | return -1; | |
435 | } | |
9f95a23c TL |
436 | |
437 | add_host_channel(); | |
438 | ||
439 | printf("Running core monitor on lcore id %d\n", lcore_id); | |
440 | rte_eal_remote_launch(run_core_monitor, NULL, lcore_id); | |
441 | ||
7c673cae FG |
442 | run_cli(NULL); |
443 | ||
9f95a23c TL |
444 | branch_monitor_exit(); |
445 | ||
7c673cae | 446 | rte_eal_mp_wait_lcore(); |
9f95a23c TL |
447 | |
448 | free(ci->cd); | |
449 | ||
7c673cae FG |
450 | return 0; |
451 | } |