2 // Copyright (c) 2010-2017 Intel Corporation
4 // Licensed under the Apache License, Version 2.0 (the "License");
5 // you may not use this file except in compliance with the License.
6 // You may obtain a copy of the License at
8 // http://www.apache.org/licenses/LICENSE-2.0
10 // Unless required by applicable law or agreed to in writing, software
11 // distributed under the License is distributed on an "AS IS" BASIS,
12 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 // See the License for the specific language governing permissions and
14 // limitations under the License.
20 #include <rte_launch.h>
21 #include <rte_cycles.h>
22 #include <rte_atomic.h>
26 #include "prox_port_cfg.h"
33 #include "stats_cons.h"
34 #include "stats_cons_log.h"
35 #include "stats_cons_cli.h"
38 #include "input_curses.h"
39 #include "input_conn.h"
40 #include "handle_master.h"
42 static int needs_refresh;
43 static uint64_t update_interval;
44 static int stop_prox = 0; /* set to 1 to stop prox */
46 void set_update_interval(uint32_t msec)
48 update_interval = msec_to_tsc(msec);
51 void req_refresh(void)
58 static rte_atomic32_t already_leaving = RTE_ATOMIC32_INIT(0);
59 if (!rte_atomic32_test_and_set(&already_leaving))
62 plog_info("Leaving...\n");
63 if (lcore_cfg == NULL)
69 static void update_link_states(void)
71 struct prox_port_cfg *port_cfg;
72 struct rte_eth_link link;
74 for (uint8_t portid = 0; portid < PROX_MAX_PORTS; ++portid) {
75 if (!prox_port_cfg[portid].active) {
79 port_cfg = &prox_port_cfg[portid];
80 rte_eth_link_get_nowait(portid, &link);
81 port_cfg->link_speed = link.link_speed;
82 if (port_cfg->link_up != link.link_status) {
83 port_cfg->link_up = link.link_status;
84 plog_info("port %d: Link speed now %d Mbps\n", portid, link.link_speed);
89 static struct stats_cons stats_cons[8];
90 static size_t n_stats_cons = 0;
91 static uint16_t stats_cons_flags = 0;
93 static void stats_cons_add(struct stats_cons *sc)
95 if (n_stats_cons == sizeof(stats_cons)/sizeof(stats_cons[0]))
98 stats_cons[n_stats_cons++] = *sc;
100 stats_cons_flags |= sc->flags;
103 static void stats_cons_notify(void)
105 for (size_t i = 0; i < n_stats_cons; ++i) {
106 stats_cons[i].notify();
110 static void stats_cons_refresh(void)
112 for (size_t i = 0; i < n_stats_cons; ++i) {
113 if (stats_cons[i].refresh)
114 stats_cons[i].refresh();
118 static void stats_cons_finish(void)
120 for (size_t i = 0; i < n_stats_cons; ++i) {
121 if (stats_cons[i].finish)
122 stats_cons[i].finish();
126 static void busy_wait_until(uint64_t deadline)
128 while (rte_rdtsc() < deadline)
132 static void multiplexed_input_stats(uint64_t deadline)
135 input_proc_until(deadline);
141 stats_cons_refresh();
144 if (rte_atomic32_read(&lsc)) {
145 rte_atomic32_dec(&lsc);
146 update_link_states();
147 stats_cons_refresh();
151 static void print_warnings(void)
153 if (get_n_warnings() == -1) {
154 plog_info("Warnings disabled\n");
156 else if (get_n_warnings() > 0) {
157 int n_print = get_n_warnings() < 5? get_n_warnings(): 5;
158 plog_info("Started with %d warnings, last %d warnings: \n", get_n_warnings(), n_print);
159 for (int i = -n_print + 1; i <= 0; ++i) {
160 plog_info("%s", get_warning(i));
164 plog_info("Started without warnings\n");
168 /* start main loop */
169 void __attribute__((noreturn)) run(uint32_t flags)
172 uint64_t next_update;
173 uint64_t stop_tsc = 0;
175 const uint64_t update_interval_threshold = usec_to_tsc(1);
177 if (flags & DSF_LISTEN_TCP)
178 PROX_PANIC(reg_input_tcp(), "Failed to start listening on TCP port 8474: %s\n", strerror(errno));
179 if (flags & DSF_LISTEN_UDS)
180 PROX_PANIC(reg_input_uds(), "Failed to start listening on UDS /tmp/prox.sock: %s\n", strerror(errno));
182 if (prox_cfg.use_stats_logger)
183 stats_cons_add(stats_cons_log_get());
185 stats_init(prox_cfg.start_time, prox_cfg.duration_time);
186 stats_update(STATS_CONS_F_ALL);
188 switch (prox_cfg.ui) {
191 stats_cons_add(&display);
194 stats_cons_add(stats_cons_cli_get());
201 if (flags & DSF_AUTOSTART)
206 cur_tsc = rte_rdtsc();
207 if (prox_cfg.duration_time != 0) {
208 stop_tsc = cur_tsc + sec_to_tsc(prox_cfg.start_time + prox_cfg.duration_time);
212 stats_cons_refresh();
214 update_interval = str_to_tsc(prox_cfg.update_interval_str);
215 next_update = cur_tsc + update_interval;
220 struct task_master *task = (struct task_master *)lcore_cfg[prox_cfg.master].tasks_all[0];
221 if (handle_ctrl_plane) {
222 while (stop_prox == 0) {
224 // Run ctrl plane for max 10 msec to let screen and keyboard updates
225 if (prox_cfg.flags & DSF_CTRL_PLANE_ENABLED) {
226 uint64_t ctrl_plane_update = rte_rdtsc() + msec_to_tsc(10);
227 while ((ret) && (rte_rdtsc() < ctrl_plane_update))
228 ret = handle_ctrl_plane(lcore_cfg[prox_cfg.master].tasks_all[0], NULL, 0);
230 multiplexed_input_stats(0);
231 if (rte_rdtsc() < next_update)
233 next_update += update_interval;
234 stats_update(stats_cons_flags);
237 if (stop_tsc && rte_rdtsc() >= stop_tsc) {
242 while (stop_prox == 0) {
244 if (update_interval < update_interval_threshold)
245 busy_wait_until(next_update);
247 multiplexed_input_stats(next_update);
249 next_update += update_interval;
251 stats_update(stats_cons_flags);
254 if (stop_tsc && rte_rdtsc() >= stop_tsc) {
262 if (prox_cfg.flags & DSF_WAIT_ON_QUIT) {
266 if (prox_cfg.logbuf) {
267 file_print(prox_cfg.logbuf);