#include <locale.h>
#include <unistd.h>
#include <signal.h>
+#include <curses.h>
#include <rte_cycles.h>
#include <rte_atomic.h>
}
}
+static void check_nb_mbuf(void)
+{
+ struct lcore_cfg *lconf = NULL;
+ struct task_args *targ = NULL;
+ uint8_t port_id;
+ int n_txd = 0, n_rxd = 0;
+
+ while (core_targ_next(&lconf, &targ, 0) == 0) {
+ for (uint8_t i = 0; i < targ->nb_txports; ++i) {
+ port_id = targ->tx_port_queue[i].port;
+ n_txd = prox_port_cfg[port_id].n_txd;
+ }
+ for (uint8_t i = 0; i < targ->nb_rxports; ++i) {
+ port_id = targ->rx_port_queue[i].port;
+ n_rxd = prox_port_cfg[port_id].n_rxd;
+ }
+ if (targ->nb_mbuf <= n_rxd + n_txd + targ->nb_cache_mbuf + MAX_PKT_BURST) {
+ plog_warn("Core %d, task %d might not have enough mbufs (%d) to support %d txd, %d rxd and %d cache_mbuf\n",
+ lconf->id, targ->id, targ->nb_mbuf, n_txd, n_rxd, targ->nb_cache_mbuf);
+ }
+ }
+}
+
static void check_missing_rx(void)
{
struct lcore_cfg *lconf = NULL, *rx_lconf = NULL, *tx_lconf = NULL;
struct task_args *targ, *rx_targ = NULL, *tx_targ = NULL;
- struct prox_port_cfg *port;
uint8_t port_id, rx_port_id, ok;
while (core_targ_next(&lconf, &targ, 0) == 0) {
static void check_cfg_consistent(void)
{
+ check_nb_mbuf();
check_missing_rx();
check_zero_rx();
check_mixed_normal_pipeline();
// If the mbuf size (of the rx task) is not big enough, we might receive multiple segments
// This is usually the case when setting a big mtu size i.e. enabling jumbo frames.
// If the packets get transmitted, then multi segments will have to be enabled on the TX port
- uint16_t max_frame_size = port->mtu + ETHER_HDR_LEN + ETHER_CRC_LEN + 2 * PROX_VLAN_TAG_SIZE;
+ uint16_t max_frame_size = port->mtu + PROX_RTE_ETHER_HDR_LEN + PROX_RTE_ETHER_CRC_LEN + 2 * PROX_VLAN_TAG_SIZE;
if (max_frame_size + sizeof(struct rte_mbuf) + RTE_PKTMBUF_HEADROOM > targ->mbuf_size) {
targ->task_init->flag_features |= TASK_FEATURE_TXQ_FLAGS_MULTSEGS;
}
starg->ctrl_plane_ring = ring;
}
- plog_info("\t\tCore %u task %u to -> core %u task %u ctrl_ring %s %p %s\n",
+ plog_info("\t\t\tCore %u task %u to -> core %u task %u ctrl_ring %s %p %s\n",
lconf->id, starg->id, ct.core, ct.task, ct.type == CTRL_TYPE_PKT?
"pkt" : "msg", ring, ring->name);
ris->n_ctrl_rings++;
ct.core = lconf->id;
ct.task = starg->id;;
- struct rte_ring *tx_ring = init_ring_between_tasks(lcore_cfg, lcore_cfg[prox_cfg.master].targs, ct, 0, 0, &ris);
+ struct rte_ring *tx_ring = init_ring_between_tasks(&lcore_cfg[prox_cfg.master], lcore_cfg[prox_cfg.master].targs, ct, 0, 0, &ris);
}
}
}
struct rte_mbuf** pkts = prox_zmalloc(nb_mbuf * sizeof(*pkts), rte_socket_id());
uint64_t got = 0;
- while (rte_mempool_get_bulk(mempool, (void**)(pkts + got), 1) == 0)
+ while ((got < nb_mbuf) && (rte_mempool_get_bulk(mempool, (void**)(pkts + got), 1) == 0))
++got;
+ nb_mbuf = got;
while (got) {
int idx;
do {
- idx = rand() % nb_mbuf - 1;
+ idx = rand() % nb_mbuf;
} while (pkts[idx] == 0);
rte_mempool_put_bulk(mempool, (void**)&pkts[idx], 1);
continue;
}
port = &prox_port_cfg[if_port];
- if (max_frame_size < port->mtu + ETHER_HDR_LEN + ETHER_CRC_LEN + 2 * PROX_VLAN_TAG_SIZE)
- max_frame_size = port->mtu + ETHER_HDR_LEN + ETHER_CRC_LEN + 2 * PROX_VLAN_TAG_SIZE;
+ if (max_frame_size < port->mtu + PROX_RTE_ETHER_HDR_LEN + PROX_RTE_ETHER_CRC_LEN + 2 * PROX_VLAN_TAG_SIZE)
+ max_frame_size = port->mtu + PROX_RTE_ETHER_HDR_LEN + PROX_RTE_ETHER_CRC_LEN + 2 * PROX_VLAN_TAG_SIZE;
if (min_buffer_size < port->min_rx_bufsize)
min_buffer_size = port->min_rx_bufsize;
quit();
}
+static void set_term_env(void)
+{
+ static const char var[] = "TERM";
+ static char str[] = "TERM=putty";
+ char *old_value, *new_value;
+ int max_ver = 0, min_ver = 0, n;
+
+ old_value = getenv(var);
+
+ const char *ncurses_version = curses_version();
+ n = sscanf(ncurses_version, "ncurses %d.%d", &max_ver, &min_ver);
+ if (n != 2) {
+ plog_info("\tUnable to extract ncurses version from %s. TERM left unchanged to %s\n", ncurses_version, old_value);
+ return;
+ } else {
+ plog_info("\tncurses version = %d.%d (%s)\n", max_ver, min_ver, ncurses_version);
+ }
+
+ if (((max_ver > 6) || ((max_ver == 6) && (min_ver >= 1))) && (strcmp(old_value, "xterm") == 0)) {
+ // On recent OSes such as RHEL 8.0, ncurses(6.1) introduced support
+ // for ECMA-48 repeat character control.
+ // Some terminal emulators use TERM=xterm but do not support this feature.
+ // In this case, printing repeating character such as "22000000 Hz" might
+ // display as 220 Hz.
+ // Other emulattors, such as tmux, use TERM=screen, and do not exhibit the issue.
+ plog_info("\tChanged TERM from %s ", old_value);
+ putenv(str);
+ new_value = getenv(var);
+ plog_info("to %s\n", new_value);
+ } else {
+ plog_info("\tTERM left unchanged to %s\n", old_value);
+ }
+}
+
int main(int argc, char **argv)
{
/* set en_US locale to print big numbers with ',' */
if (prox_parse_args(argc, argv) != 0){
prox_usage(argv[0]);
}
-
plog_init(prox_cfg.log_name, prox_cfg.log_name_pid);
- plog_info("=== " PROGRAM_NAME " " VERSION_STR " ===\n");
+ plog_info("=== " PROGRAM_NAME " %s ===\n", VERSION_STR());
plog_info("\tUsing DPDK %s\n", rte_version() + sizeof(RTE_VER_PREFIX));
+ set_term_env();
read_rdt_info();
if (prox_cfg.flags & DSF_LIST_TASK_MODES) {