1 /* SPDX-License-Identifier: BSD-3-Clause
2 * Copyright(c) 2010-2014 Intel Corporation
15 #include <sys/queue.h>
17 #include <rte_common.h>
19 #include <rte_launch.h>
21 #include <rte_per_lcore.h>
22 #include <rte_lcore.h>
23 #include <rte_ethdev.h>
25 #include <rte_cycles.h>
26 #include <rte_debug.h>
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>
36 #define RX_RING_SIZE 512
37 #define TX_RING_SIZE 512
39 #define NUM_MBUFS 8191
40 #define MBUF_CACHE_SIZE 250
43 static uint32_t enabled_port_mask;
44 static volatile bool force_quit;
47 static const struct rte_eth_conf port_conf_default = {
48 .rxmode = { .max_rx_pkt_len = ETHER_MAX_LEN }
52 port_init(uint16_t port, struct rte_mempool *mbuf_pool)
54 struct rte_eth_conf port_conf = port_conf_default;
55 const uint16_t rx_rings = 1, tx_rings = 1;
59 if (port >= rte_eth_dev_count())
62 /* Configure the Ethernet device. */
63 retval = rte_eth_dev_configure(port, rx_rings, tx_rings, &port_conf);
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);
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);
83 /* Start the Ethernet port. */
84 retval = rte_eth_dev_start(port);
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",
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]);
98 /* Enable RX in promiscuous mode for the Ethernet device. */
99 rte_eth_promiscuous_enable(port);
106 parse_portmask(const char *portmask)
111 /* parse hexadecimal string */
112 pm = strtoul(portmask, &end, 16);
113 if ((portmask[0] == '\0') || (end == NULL) || (*end != '\0'))
121 /* Parse the argument given in the command line of the application */
123 parse_args(int argc, char **argv)
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},
136 while ((opt = getopt_long(argc, argvopt, "p:q:T:",
137 lgopts, &option_index)) != EOF) {
142 enabled_port_mask = parse_portmask(optarg);
143 if (enabled_port_mask == 0) {
144 printf("invalid portmask\n");
158 argv[optind-1] = prgname;
161 optind = 0; /* reset getopt lib */
166 check_all_ports_link_status(uint16_t port_num, uint32_t port_mask)
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;
173 printf("\nChecking link status");
175 for (count = 0; count <= MAX_CHECK_TIME; count++) {
179 for (portid = 0; portid < port_num; portid++) {
182 if ((port_mask & (1 << portid)) == 0)
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"));
195 printf("Port %d Link Down\n",
199 /* clear all_ports_up flag if any link down */
200 if (link.link_status == ETH_LINK_DOWN) {
205 /* after finally printing all link status, get out */
209 if (all_ports_up == 0) {
212 rte_delay_ms(CHECK_INTERVAL);
215 /* set the print_flag if all ports up or timeout */
216 if (all_ports_up == 1 || count == (MAX_CHECK_TIME - 1)) {
223 run_monitor(__attribute__((unused)) void *arg)
225 if (channel_monitor_init() < 0) {
226 printf("Unable to initialize channel monitor\n");
229 run_channel_monitor();
234 sig_handler(int signo)
236 printf("Received signal %d, exiting...\n", signo);
237 channel_monitor_exit();
238 channel_manager_exit();
239 power_manager_exit();
244 main(int argc, char **argv)
248 unsigned int nb_ports;
249 struct rte_mempool *mbuf_pool;
253 ret = rte_eal_init(argc, argv);
255 rte_panic("Cannot init EAL\n");
257 signal(SIGINT, sig_handler);
258 signal(SIGTERM, sig_handler);
263 /* parse application arguments (after the EAL ones) */
264 ret = parse_args(argc, argv);
266 rte_exit(EXIT_FAILURE, "Invalid arguments\n");
268 nb_ports = rte_eth_dev_count();
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());
273 if (mbuf_pool == NULL)
274 rte_exit(EXIT_FAILURE, "Cannot create mbuf pool\n");
276 /* Initialize ports. */
277 for (portid = 0; portid < nb_ports; portid++) {
278 struct ether_addr eth;
282 if ((enabled_port_mask & (1 << portid)) == 0)
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;
291 if (port_init(portid, mbuf_pool) != 0)
292 rte_exit(EXIT_FAILURE, "Cannot init port %"PRIu8 "\n",
295 for (w = 0; w < MAX_VFS; w++) {
296 eth.addr_bytes[5] = w + 0xf0;
299 ret = rte_pmd_ixgbe_set_vf_mac_addr(portid,
302 ret = rte_pmd_i40e_set_vf_mac_addr(portid,
305 ret = rte_pmd_bnxt_set_vf_mac_addr(portid,
310 printf("Port %d VF %d MAC: ",
312 for (j = 0; j < 6; j++) {
313 printf("%02x", eth.addr_bytes[j]);
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 "
330 check_all_ports_link_status(nb_ports, enabled_port_mask);
331 rte_eal_remote_launch(run_monitor, NULL, lcore_id);
333 if (power_manager_init() < 0) {
334 printf("Unable to initialize power manager\n");
337 if (channel_manager_init(CHANNEL_MGR_DEFAULT_HV_PATH) < 0) {
338 printf("Unable to initialize channel manager\n");
343 rte_eal_mp_wait_lcore();