summaryrefslogtreecommitdiffstats
path: root/VNFs/DPPD-PROX/main.c
diff options
context:
space:
mode:
Diffstat (limited to 'VNFs/DPPD-PROX/main.c')
-rw-r--r--VNFs/DPPD-PROX/main.c423
1 files changed, 312 insertions, 111 deletions
diff --git a/VNFs/DPPD-PROX/main.c b/VNFs/DPPD-PROX/main.c
index 2c8517f0..61abe6e6 100644
--- a/VNFs/DPPD-PROX/main.c
+++ b/VNFs/DPPD-PROX/main.c
@@ -1,5 +1,5 @@
/*
-// Copyright (c) 2010-2017 Intel Corporation
+// Copyright (c) 2010-2020 Intel Corporation
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
@@ -18,6 +18,7 @@
#include <locale.h>
#include <unistd.h>
#include <signal.h>
+#include <curses.h>
#include <rte_cycles.h>
#include <rte_atomic.h>
@@ -53,6 +54,7 @@
#endif
uint8_t lb_nb_txrings = 0xff;
+extern const char *git_version;
struct rte_ring *ctrl_rings[RTE_MAX_LCORE*MAX_TASKS_PER_CORE];
static void __attribute__((noreturn)) prox_usage(const char *prgname)
@@ -114,7 +116,7 @@ static void check_mixed_normal_pipeline(void)
}
}
-static void check_zero_rx(void)
+static void check_no_rx(void)
{
struct lcore_cfg *lconf = NULL;
struct task_args *targ;
@@ -127,12 +129,34 @@ static void check_zero_rx(void)
}
}
+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;
+ uint8_t port_id, rx_port_id, ok, l3, ndp;
while (core_targ_next(&lconf, &targ, 0) == 0) {
PROX_PANIC((targ->flags & TASK_ARG_RX_RING) && targ->rx_rings[0] == 0 && !targ->tx_opt_ring_task,
@@ -145,12 +169,17 @@ static void check_missing_rx(void)
lconf = NULL;
while (core_targ_next(&lconf, &targ, 0) == 0) {
- if (strcmp(targ->sub_mode_str, "l3") != 0)
+ l3 = ndp = 0;
+ if (strcmp(targ->sub_mode_str, "l3") == 0)
+ l3 = 1;
+ else if (strcmp(targ->sub_mode_str, "ndp") == 0)
+ ndp = 1;
+ else
continue;
- PROX_PANIC((targ->nb_rxports == 0) && (targ->nb_txports == 0), "L3 task must have a RX or a TX port\n");
- // If the L3 sub_mode receives from a port, check that there is at least one core/task
- // transmitting to this port in L3 sub_mode
+ PROX_PANIC((targ->nb_rxports == 0) && (targ->nb_txports == 0), "L3/NDP task must have a RX or a TX port\n");
+ // If the L3/NDP sub_mode receives from a port, check that there is at least one core/task
+ // transmitting to this port in L3/NDP sub_mode
for (uint8_t i = 0; i < targ->nb_rxports; ++i) {
rx_port_id = targ->rx_port_queue[i].port;
ok = 0;
@@ -158,42 +187,48 @@ static void check_missing_rx(void)
while (core_targ_next(&tx_lconf, &tx_targ, 0) == 0) {
if ((port_id = tx_targ->tx_port_queue[0].port) == OUT_DISCARD)
continue;
- if ((rx_port_id == port_id) && (tx_targ->flags & TASK_ARG_L3)){
+ if ((rx_port_id == port_id) &&
+ ( ((tx_targ->flags & TASK_ARG_L3) && l3) ||
+ ((tx_targ->flags & TASK_ARG_NDP) && ndp) ) ) {
ok = 1;
break;
}
}
- PROX_PANIC(ok == 0, "RX L3 sub mode for port %d on core %d task %d, but no core/task transmitting on that port\n", rx_port_id, lconf->id, targ->id);
+ PROX_PANIC(ok == 0, "RX %s sub mode for port %d on core %d task %d, but no core/task transmitting on that port\n", l3 ? "l3":"ndp", rx_port_id, lconf->id, targ->id);
}
- // If the L3 sub_mode transmits to a port, check that there is at least one core/task
- // receiving from that port in L3 sub_mode.
+ // If the L3/NDP sub_mode transmits to a port, check that there is at least one core/task
+ // receiving from that port in L3/NDP sub_mode.
if ((port_id = targ->tx_port_queue[0].port) == OUT_DISCARD)
continue;
rx_lconf = NULL;
ok = 0;
- plog_info("\tCore %d task %d transmitting to port %d in L3 mode\n", lconf->id, targ->id, port_id);
+ plog_info("\tCore %d task %d transmitting to port %d in %s submode\n", lconf->id, targ->id, port_id, l3 ? "l3":"ndp");
while (core_targ_next(&rx_lconf, &rx_targ, 0) == 0) {
for (uint8_t i = 0; i < rx_targ->nb_rxports; ++i) {
rx_port_id = rx_targ->rx_port_queue[i].port;
- if ((rx_port_id == port_id) && (rx_targ->flags & TASK_ARG_L3)){
+ if ((rx_port_id == port_id) &&
+ ( ((rx_targ->flags & TASK_ARG_L3) && l3) ||
+ ((rx_targ->flags & TASK_ARG_NDP) && ndp) ) ){
ok = 1;
break;
}
}
if (ok == 1) {
- plog_info("\tCore %d task %d has found core %d task %d receiving from port %d\n", lconf->id, targ->id, rx_lconf->id, rx_targ->id, port_id);
+ plog_info("\tCore %d task %d has found core %d task %d receiving from port %d in %s submode\n", lconf->id, targ->id, rx_lconf->id, rx_targ->id, port_id,
+ ((rx_targ->flags & TASK_ARG_L3) && l3) ? "l3":"ndp");
break;
}
}
- PROX_PANIC(ok == 0, "L3 sub mode for port %d on core %d task %d, but no core/task receiving on that port\n", port_id, lconf->id, targ->id);
+ PROX_PANIC(ok == 0, "%s sub mode for port %d on core %d task %d, but no core/task receiving on that port\n", l3 ? "l3":"ndp", port_id, lconf->id, targ->id);
}
}
static void check_cfg_consistent(void)
{
+ check_nb_mbuf();
check_missing_rx();
- check_zero_rx();
+ check_no_rx();
check_mixed_normal_pipeline();
}
@@ -224,6 +259,21 @@ static int chain_flag_state(struct task_args *targ, uint64_t flag, int is_set)
return 0;
}
+static int chain_flag_always_set(struct task_args *targ, uint64_t flag)
+{
+ return (!chain_flag_state(targ, flag, 0));
+}
+
+static int chain_flag_never_set(struct task_args *targ, uint64_t flag)
+{
+ return (!chain_flag_state(targ, flag, 1));
+}
+
+static int chain_flag_sometimes_set(struct task_args *targ, uint64_t flag)
+{
+ return (chain_flag_state(targ, flag, 1));
+}
+
static void configure_if_tx_queues(struct task_args *targ, uint8_t socket)
{
uint8_t if_port;
@@ -247,44 +297,68 @@ static void configure_if_tx_queues(struct task_args *targ, uint8_t socket)
prox_port_cfg[if_port].n_txq = 1;
targ->tx_port_queue[i].queue = 0;
}
- /* Set the ETH_TXQ_FLAGS_NOREFCOUNT flag if none of
- the tasks up to the task transmitting to the port
- does not use refcnt. */
- if (!chain_flag_state(targ, TASK_FEATURE_TXQ_FLAGS_REFCOUNT, 1)) {
- prox_port_cfg[if_port].tx_conf.txq_flags |= ETH_TXQ_FLAGS_NOREFCOUNT;
- plog_info("\t\tEnabling No refcnt on port %d\n", if_port);
- }
- else {
- plog_info("\t\tRefcnt used on port %d\n", if_port);
- }
-
/* By default OFFLOAD is enabled, but if the whole
chain has NOOFFLOADS set all the way until the
first task that receives from a port, it will be
disabled for the destination port. */
- if (chain_flag_state(targ, TASK_FEATURE_TXQ_FLAGS_NOOFFLOADS, 1)) {
+#if RTE_VERSION < RTE_VERSION_NUM(18,8,0,1)
+ if (chain_flag_always_set(targ, TASK_FEATURE_TXQ_FLAGS_NOOFFLOADS)) {
prox_port_cfg[if_port].tx_conf.txq_flags |= ETH_TXQ_FLAGS_NOOFFLOADS;
- plog_info("\t\tDisabling TX offloads on port %d\n", if_port);
- } else {
- plog_info("\t\tEnabling TX offloads on port %d\n", if_port);
}
-
- /* By default NOMULTSEGS is disabled, as drivers/NIC might split packets on RX
- It should only be enabled when we know for sure that the RX does not split packets.
- Set the ETH_TXQ_FLAGS_NOMULTSEGS flag if none of the tasks up to the task
- transmitting to the port does not use multsegs. */
- if (!chain_flag_state(targ, TASK_FEATURE_TXQ_FLAGS_NOMULTSEGS, 0)) {
- prox_port_cfg[if_port].tx_conf.txq_flags |= ETH_TXQ_FLAGS_NOMULTSEGS;
- plog_info("\t\tEnabling No MultiSegs on port %d\n", if_port);
- }
- else {
- plog_info("\t\tMultiSegs used on port %d\n", if_port);
+#else
+ if (chain_flag_always_set(targ, TASK_FEATURE_TXQ_FLAGS_NOOFFLOADS)) {
+ prox_port_cfg[if_port].requested_tx_offload &= ~(RTE_ETH_TX_OFFLOAD_IPV4_CKSUM | RTE_ETH_TX_OFFLOAD_UDP_CKSUM);
}
+#endif
}
}
static void configure_if_rx_queues(struct task_args *targ, uint8_t socket)
{
+ struct prox_port_cfg *port;
+ uint8_t port_used_counter[PROX_MAX_PORTS] = {0};
+ bool multiple_port_reference = false;
+ uint8_t total_number_of_queues = 0;
+ // Check how many times a port is referenced for this task
+ for (uint8_t i = 0; i < targ->nb_rxports; i++) {
+ uint8_t if_port = targ->rx_port_queue[i].port;
+ port_used_counter[if_port]++;
+ if (port_used_counter[if_port] > 1) {
+ multiple_port_reference = true;
+ port = &prox_port_cfg[if_port];
+ PROX_PANIC((port->all_rx_queues), "Multiple queues defined in rx port, but all_rx_queues also set for port %s\n", port->names[0]);
+ }
+ }
+ // If only referenced once, it is possible that we want to use all queues
+ // Therefore we will check all_rx_queues for that port
+ if (!multiple_port_reference) {
+ for (uint8_t i = 0; i < PROX_MAX_PORTS; i++) {
+ uint8_t if_port = targ->rx_port_queue[i].port;
+ if (port_used_counter[if_port]) {
+ port = &prox_port_cfg[if_port];
+ if (port->all_rx_queues) {
+ port_used_counter[if_port] = port->max_rxq;
+ total_number_of_queues += port->max_rxq;
+ plog_info("\tall_rx_queues for Port %s: %u rx_queues will be applied\n", port->names[0], port_used_counter[if_port]);
+ }
+ }
+ }
+ }
+ if (total_number_of_queues) {
+ PROX_PANIC((total_number_of_queues > PROX_MAX_PORTS), "%u queues using the all_rx_queues. PROX_MAX_PORTS is set to %u\n", total_number_of_queues, PROX_MAX_PORTS);
+ uint8_t index = 0;
+ for (uint8_t i = 0; i < PROX_MAX_PORTS; i++) {
+ if (port_used_counter[i]) {
+ for (uint8_t j = 0; j < port_used_counter[i]; j++) {
+ targ->rx_port_queue[index].port = i;
+ index ++;
+ }
+ port = &prox_port_cfg[i];
+ plog_info("\t\tConfiguring task to use port %s with %u rx_queues\n", port->names[0], port_used_counter[i]);
+ }
+ }
+ targ->nb_rxports = index;
+ }
for (int i = 0; i < targ->nb_rxports; i++) {
uint8_t if_port = targ->rx_port_queue[i].port;
@@ -292,18 +366,26 @@ static void configure_if_rx_queues(struct task_args *targ, uint8_t socket)
return;
}
- PROX_PANIC(!prox_port_cfg[if_port].active, "Port %u not used, aborting...\n", if_port);
+ port = &prox_port_cfg[if_port];
+ PROX_PANIC(!port->active, "Port %u not used, aborting...\n", if_port);
- if(prox_port_cfg[if_port].rx_ring[0] != '\0') {
- prox_port_cfg[if_port].n_rxq = 0;
+ if(port->rx_ring[0] != '\0') {
+ port->n_rxq = 0;
}
- targ->rx_port_queue[i].queue = prox_port_cfg[if_port].n_rxq;
- prox_port_cfg[if_port].pool[targ->rx_port_queue[i].queue] = targ->pool;
- prox_port_cfg[if_port].pool_size[targ->rx_port_queue[i].queue] = targ->nb_mbuf - 1;
- prox_port_cfg[if_port].n_rxq++;
+ // 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 + 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;
+ }
+ targ->rx_port_queue[i].queue = port->n_rxq;
+ port->pool[targ->rx_port_queue[i].queue] = targ->pool;
+ port->pool_size[targ->rx_port_queue[i].queue] = targ->nb_mbuf - 1;
+ port->n_rxq++;
- int dsocket = prox_port_cfg[if_port].socket;
+ int dsocket = port->socket;
if (dsocket != -1 && dsocket != socket) {
plog_warn("RX core on socket %d while device on socket %d\n", socket, dsocket);
}
@@ -319,8 +401,64 @@ static void configure_if_queues(void)
while (core_targ_next(&lconf, &targ, 0) == 0) {
socket = rte_lcore_to_socket_id(lconf->id);
- configure_if_tx_queues(targ, socket);
configure_if_rx_queues(targ, socket);
+ configure_if_tx_queues(targ, socket);
+ }
+}
+
+static void configure_tx_queue_flags(void)
+{
+ struct lcore_cfg *lconf = NULL;
+ struct task_args *targ;
+ uint8_t socket;
+ uint8_t if_port;
+
+ while (core_targ_next(&lconf, &targ, 0) == 0) {
+ socket = rte_lcore_to_socket_id(lconf->id);
+ for (uint8_t i = 0; i < targ->nb_txports; ++i) {
+ if_port = targ->tx_port_queue[i].port;
+#if RTE_VERSION < RTE_VERSION_NUM(18,8,0,1)
+ /* Set the ETH_TXQ_FLAGS_NOREFCOUNT flag if none of
+ the tasks up to the task transmitting to the port
+ use refcnt. */
+ if (chain_flag_never_set(targ, TASK_FEATURE_TXQ_FLAGS_REFCOUNT)) {
+ prox_port_cfg[if_port].tx_conf.txq_flags |= ETH_TXQ_FLAGS_NOREFCOUNT;
+ }
+#else
+ /* Set the RTE_ETH_TX_OFFLOAD_MBUF_FAST_FREE flag if none of
+ the tasks up to the task transmitting to the port
+ use refcnt and per-queue all mbufs comes from the same mempool. */
+ if (chain_flag_never_set(targ, TASK_FEATURE_TXQ_FLAGS_REFCOUNT)) {
+ if (chain_flag_never_set(targ, TASK_FEATURE_TXQ_FLAGS_MULTIPLE_MEMPOOL))
+ prox_port_cfg[if_port].requested_tx_offload |= RTE_ETH_TX_OFFLOAD_MBUF_FAST_FREE;
+ }
+#endif
+ }
+ }
+}
+
+static void configure_multi_segments(void)
+{
+ struct lcore_cfg *lconf = NULL;
+ struct task_args *targ;
+ uint8_t if_port;
+
+ while (core_targ_next(&lconf, &targ, 0) == 0) {
+ for (uint8_t i = 0; i < targ->nb_txports; ++i) {
+ if_port = targ->tx_port_queue[i].port;
+ // Multi segment is disabled for most tasks. It is only enabled for tasks requiring big packets.
+#if RTE_VERSION < RTE_VERSION_NUM(18,8,0,1)
+ // We can only enable "no multi segment" if no such task exists in the chain of tasks.
+ if (chain_flag_never_set(targ, TASK_FEATURE_TXQ_FLAGS_MULTSEGS)) {
+ prox_port_cfg[if_port].tx_conf.txq_flags |= ETH_TXQ_FLAGS_NOMULTSEGS;
+ }
+#else
+ // We enable "multi segment" if at least one task requires it in the chain of tasks.
+ if (chain_flag_sometimes_set(targ, TASK_FEATURE_TXQ_FLAGS_MULTSEGS)) {
+ prox_port_cfg[if_port].requested_tx_offload |= RTE_ETH_TX_OFFLOAD_MULTI_SEGS;
+ }
+#endif
+ }
}
}
@@ -441,7 +579,7 @@ static struct rte_ring *init_ring_between_tasks(struct lcore_cfg *lconf, struct
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++;
@@ -500,6 +638,8 @@ static struct rte_ring *init_ring_between_tasks(struct lcore_cfg *lconf, struct
PROX_ASSERT(dtarg->nb_rxrings < MAX_RINGS_PER_TASK);
dtarg->rx_rings[dtarg->nb_rxrings] = ring;
++dtarg->nb_rxrings;
+ if (dtarg->nb_rxrings > 1)
+ dtarg->task_init->flag_features |= TASK_FEATURE_TXQ_FLAGS_MULTIPLE_MEMPOOL;
}
dtarg->nb_slave_threads = starg->core_task_set[idx].n_elems;
dtarg->lb_friend_core = lconf->id;
@@ -543,7 +683,7 @@ static void init_rings(void)
lconf = NULL;
struct prox_port_cfg *port;
while (core_targ_next(&lconf, &starg, 1) == 0) {
- if ((starg->task_init) && (starg->flags & TASK_ARG_L3)) {
+ if ((starg->task_init) && (starg->flags & (TASK_ARG_L3|TASK_ARG_NDP))) {
struct core_task ct;
ct.core = prox_cfg.master;
ct.task = 0;
@@ -552,7 +692,7 @@ static void init_rings(void)
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);
}
}
}
@@ -562,13 +702,14 @@ static void shuffle_mempool(struct rte_mempool* mempool, uint32_t nb_mbuf)
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);
@@ -578,6 +719,50 @@ static void shuffle_mempool(struct rte_mempool* mempool, uint32_t nb_mbuf)
prox_free(pkts);
}
+static void set_mbuf_size(struct task_args *targ)
+{
+ /* mbuf size can be set
+ * - from config file (highest priority, overwriting any other config) - should only be used as workaround
+ * - defaulted to MBUF_SIZE.
+ * Except if set explicitely, ensure that size is big enough for vmxnet3 driver
+ */
+ if (targ->mbuf_size)
+ return;
+
+ targ->mbuf_size = MBUF_SIZE;
+ struct prox_port_cfg *port;
+ uint16_t max_frame_size = 0, min_buffer_size = 0;
+ int i40e = 0;
+ for (int i = 0; i < targ->nb_rxports; i++) {
+ uint8_t if_port = targ->rx_port_queue[i].port;
+
+ if (if_port == OUT_DISCARD) {
+ continue;
+ }
+ port = &prox_port_cfg[if_port];
+ 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;
+
+ // Check whether we receive from i40e. This driver have extra mbuf size requirements
+ if (strcmp(port->short_name, "i40e") == 0)
+ i40e = 1;
+ }
+ if (i40e) {
+ // i40e supports a maximum of 5 descriptors chained
+ uint16_t required_mbuf_size = RTE_ALIGN(max_frame_size / 5, 128) + sizeof(struct rte_mbuf) + RTE_PKTMBUF_HEADROOM;
+ if (required_mbuf_size > targ->mbuf_size) {
+ targ->mbuf_size = required_mbuf_size;
+ plog_info("\t\tSetting mbuf_size to %u to support frame_size %u\n", targ->mbuf_size, max_frame_size);
+ }
+ }
+ if (min_buffer_size > targ->mbuf_size) {
+ plog_warn("Mbuf size might be too small. This might result in packet segmentation and memory leak\n");
+ }
+
+}
+
static void setup_mempools_unique_per_socket(void)
{
uint32_t flags = 0;
@@ -595,11 +780,7 @@ static void setup_mempools_unique_per_socket(void)
uint8_t socket = rte_lcore_to_socket_id(lconf->id);
PROX_ASSERT(socket < MAX_SOCKETS);
- if (targ->mbuf_size_set_explicitely)
- flags = MEMPOOL_F_NO_SPREAD;
- if ((!targ->mbuf_size_set_explicitely) && (targ->task_init->mbuf_size != 0)) {
- targ->mbuf_size = targ->task_init->mbuf_size;
- }
+ set_mbuf_size(targ);
if (targ->rx_port_queue[0].port != OUT_DISCARD) {
struct prox_port_cfg* port_cfg = &prox_port_cfg[targ->rx_port_queue[0].port];
PROX_ASSERT(targ->nb_mbuf != 0);
@@ -616,28 +797,26 @@ static void setup_mempools_unique_per_socket(void)
PROX_PANIC(mbuf_size[socket] != targ->mbuf_size,
"all mbuf_size must have the same size if using a unique mempool per socket\n");
}
- if ((!targ->mbuf_size_set_explicitely) && (strcmp(port_cfg->short_name, "vmxnet3") == 0)) {
- if (mbuf_size[socket] < MBUF_SIZE + RTE_PKTMBUF_HEADROOM)
- mbuf_size[socket] = MBUF_SIZE + RTE_PKTMBUF_HEADROOM;
- }
}
}
for (int i = 0 ; i < MAX_SOCKETS; i++) {
if (mbuf_count[i] != 0) {
sprintf(name, "socket_%u_pool", i);
- pool[i] = rte_mempool_create(name,
- mbuf_count[i] - 1, mbuf_size[i],
- nb_cache_mbuf[i],
- sizeof(struct rte_pktmbuf_pool_private),
- rte_pktmbuf_pool_init, NULL,
- prox_pktmbuf_init, NULL,
- i, flags);
- PROX_PANIC(pool[i] == NULL, "\t\tError: cannot create mempool for socket %u\n", i);
- plog_info("\t\tMempool %p size = %u * %u cache %u, socket %d\n", pool[i],
- mbuf_count[i], mbuf_size[i], nb_cache_mbuf[i], i);
-
- if (prox_cfg.flags & DSF_SHUFFLE) {
- shuffle_mempool(pool[i], mbuf_count[i]);
+ if ((pool[i] = rte_mempool_lookup(name)) == NULL) {
+ pool[i] = rte_mempool_create(name,
+ mbuf_count[i] - 1, mbuf_size[i],
+ nb_cache_mbuf[i],
+ sizeof(struct rte_pktmbuf_pool_private),
+ rte_pktmbuf_pool_init, NULL,
+ prox_pktmbuf_init, NULL,
+ i, flags);
+ PROX_PANIC(pool[i] == NULL, "\t\tError: cannot create mempool for socket %u\n", i);
+ plog_info("\tMempool %p size = %u * %u cache %u, socket %d\n", pool[i],
+ mbuf_count[i], mbuf_size[i], nb_cache_mbuf[i], i);
+
+ if (prox_cfg.flags & DSF_SHUFFLE) {
+ shuffle_mempool(pool[i], mbuf_count[i]);
+ }
}
}
}
@@ -652,7 +831,7 @@ static void setup_mempools_unique_per_socket(void)
targ->pool = pool[socket];
/* Set the number of mbuf to the number of the unique mempool, so that the used and free work */
targ->nb_mbuf = mbuf_count[socket];
- plog_info("\t\tMempool %p size = %u * %u cache %u, socket %d\n", targ->pool,
+ plog_info("\tMempool %p size = %u * %u cache %u, socket %d\n", targ->pool,
targ->nb_mbuf, mbuf_size[socket], targ->nb_cache_mbuf, socket);
}
}
@@ -668,33 +847,16 @@ static void setup_mempool_for_rx_task(struct lcore_cfg *lconf, struct task_args
char memzone_name[64];
char name[64];
- /* mbuf size can be set
- * - from config file (highest priority, overwriting any other config) - should only be used as workaround
- * - through each 'mode', overwriting the default mbuf_size
- * - defaulted to MBUF_SIZE i.e. 1518 Bytes
- * Except is set expliciteky, ensure that size is big enough for vmxnet3 driver
- */
- if (targ->mbuf_size_set_explicitely) {
- flags = MEMPOOL_F_NO_SPREAD;
- /* targ->mbuf_size already set */
- }
- else if (targ->task_init->mbuf_size != 0) {
- /* mbuf_size not set through config file but set through mode */
- targ->mbuf_size = targ->task_init->mbuf_size;
- }
- else if (strcmp(port_cfg->short_name, "vmxnet3") == 0) {
- if (targ->mbuf_size < MBUF_SIZE + RTE_PKTMBUF_HEADROOM)
- targ->mbuf_size = MBUF_SIZE + RTE_PKTMBUF_HEADROOM;
- }
+ set_mbuf_size(targ);
/* allocate memory pool for packets */
PROX_ASSERT(targ->nb_mbuf != 0);
if (targ->pool_name[0] == '\0') {
- sprintf(name, "core_%u_port_%u_pool", lconf->id, targ->id);
+ sprintf(name, "core_%u_task_%u_pool", lconf->id, targ->id);
}
- snprintf(memzone_name, sizeof(memzone_name)-1, "MP_%s", targ->pool_name);
+ snprintf(memzone_name, sizeof(memzone_name), "MP_%.*s", (int)(sizeof(memzone_name)-4), targ->pool_name);
mz = rte_memzone_lookup(memzone_name);
if (mz != NULL) {
@@ -724,7 +886,7 @@ static void setup_mempool_for_rx_task(struct lcore_cfg *lconf, struct task_args
receiving from if one core receives from multiple
ports, all the ports use the same mempool */
if (targ->pool == NULL) {
- plog_info("\t\tCreating mempool with name '%s'\n", name);
+ plog_info("\tCreating mempool with name '%s' on socket %d\n", name, socket);
targ->pool = rte_mempool_create(name,
targ->nb_mbuf - 1, targ->mbuf_size,
targ->nb_cache_mbuf,
@@ -735,9 +897,9 @@ static void setup_mempool_for_rx_task(struct lcore_cfg *lconf, struct task_args
}
PROX_PANIC(targ->pool == NULL,
- "\t\tError: cannot create mempool for core %u port %u: %s\n", lconf->id, targ->id, rte_strerror(rte_errno));
+ "\tError: cannot create mempool for core %u port %u: %s\n", lconf->id, targ->id, rte_strerror(rte_errno));
- plog_info("\t\tMempool %p size = %u * %u cache %u, socket %d\n", targ->pool,
+ plog_info("\tMempool %p size = %u * %u cache %u, socket %d\n", targ->pool,
targ->nb_mbuf, targ->mbuf_size, targ->nb_cache_mbuf, socket);
if (prox_cfg.flags & DSF_SHUFFLE) {
shuffle_mempool(targ->pool, targ->nb_mbuf);
@@ -829,10 +991,10 @@ static void setup_all_task_structs(void)
while(prox_core_next(&lcore_id, 1) == 0) {
lconf = &lcore_cfg[lcore_id];
- plog_info("\tInitializing struct for core %d with %d task\n", lcore_id, lconf->n_tasks_all);
+ plog_info("\t*** Initializing core %d (%d task) ***\n", lcore_id, lconf->n_tasks_all);
for (uint8_t task_id = 0; task_id < lconf->n_tasks_all; ++task_id) {
if (!task_is_master(&lconf->targs[task_id])) {
- plog_info("\tInitializing struct for core %d task %d\n", lcore_id, task_id);
+ plog_info("\t\tInitializing struct for core %d task %d\n", lcore_id, task_id);
lconf->targs[task_id].tmaster = tmaster;
lconf->tasks_all[task_id] = init_task_struct(&lconf->targs[task_id]);
}
@@ -888,14 +1050,13 @@ static void init_lcores(void)
plog_info("=== Initializing rings on cores ===\n");
init_rings();
+ configure_multi_segments();
+ configure_tx_queue_flags();
+
plog_info("=== Checking configuration consistency ===\n");
check_cfg_consistent();
plog_all_rings();
-
- setup_all_task_structs_early_init();
- plog_info("=== Initializing tasks ===\n");
- setup_all_task_structs();
}
static int setup_prox(int argc, char **argv)
@@ -923,6 +1084,10 @@ static int setup_prox(int argc, char **argv)
plog_info("=== Initializing ports ===\n");
init_port_all();
+ setup_all_task_structs_early_init();
+ plog_info("=== Initializing tasks ===\n");
+ setup_all_task_structs();
+
if (prox_cfg.logbuf_size) {
prox_cfg.logbuf = prox_zmalloc(prox_cfg.logbuf_size, rte_socket_id());
PROX_PANIC(prox_cfg.logbuf == NULL, "Failed to allocate memory for logbuf with size = %d\n", prox_cfg.logbuf_size);
@@ -1009,6 +1174,40 @@ static void sigterm_handler(int signum)
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 ((old_value) && ((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 ',' */
@@ -1017,10 +1216,11 @@ int main(int argc, char **argv)
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));
+ plog_info("\tgit version %s\n", git_version);
+ set_term_env();
read_rdt_info();
if (prox_cfg.flags & DSF_LIST_TASK_MODES) {
@@ -1087,5 +1287,6 @@ int main(int argc, char **argv)
if (setup_prox(argc, argv) != 0)
return EXIT_FAILURE;
run(prox_cfg.flags);
+
return EXIT_SUCCESS;
}