summaryrefslogtreecommitdiffstats
path: root/VNFs/DPPD-PROX
diff options
context:
space:
mode:
authorPatrice Buriez <patrice.buriez@intel.com>2017-10-25 20:30:34 +0200
committerPatrice Buriez <patrice.buriez@intel.com>2017-10-25 20:30:34 +0200
commitf6abc2e6a02557e82ad0d1e5440653bb8884ecc8 (patch)
treeae36de03e9553cd55300771271576369c7484f9e /VNFs/DPPD-PROX
parent504e70cbb19a3e65b1704ee085cd079d26cf16f8 (diff)
Merge changes from PROX-v041
Change-Id: Ie6d4e7ce22c27967117a446626f5923643397812 Signed-off-by: Patrice Buriez <patrice.buriez@intel.com>
Diffstat (limited to 'VNFs/DPPD-PROX')
-rw-r--r--VNFs/DPPD-PROX/Makefile8
-rw-r--r--VNFs/DPPD-PROX/README2
-rw-r--r--VNFs/DPPD-PROX/arp.h29
-rw-r--r--VNFs/DPPD-PROX/cmd_parser.c47
-rw-r--r--VNFs/DPPD-PROX/commands.c22
-rw-r--r--VNFs/DPPD-PROX/defaults.c2
-rw-r--r--VNFs/DPPD-PROX/defaults.h1
-rw-r--r--VNFs/DPPD-PROX/handle_arp.c4
-rw-r--r--VNFs/DPPD-PROX/handle_gen.c401
-rw-r--r--VNFs/DPPD-PROX/handle_gen.h1
-rw-r--r--VNFs/DPPD-PROX/handle_impair.c58
-rw-r--r--VNFs/DPPD-PROX/handle_irq.c20
-rw-r--r--VNFs/DPPD-PROX/handle_master.c348
-rw-r--r--VNFs/DPPD-PROX/handle_master.h43
-rw-r--r--VNFs/DPPD-PROX/handle_swap.c33
-rw-r--r--VNFs/DPPD-PROX/handle_swap.h1
-rw-r--r--VNFs/DPPD-PROX/input.c27
-rw-r--r--VNFs/DPPD-PROX/input.h1
-rw-r--r--VNFs/DPPD-PROX/lconf.c81
-rw-r--r--VNFs/DPPD-PROX/log.c2
-rw-r--r--VNFs/DPPD-PROX/main.c103
-rw-r--r--VNFs/DPPD-PROX/msr.c2
-rw-r--r--VNFs/DPPD-PROX/packet_utils.c274
-rw-r--r--VNFs/DPPD-PROX/packet_utils.h54
-rw-r--r--VNFs/DPPD-PROX/prox_args.c28
-rw-r--r--VNFs/DPPD-PROX/prox_cfg.h1
-rw-r--r--VNFs/DPPD-PROX/prox_cksum.c15
-rw-r--r--VNFs/DPPD-PROX/prox_port_cfg.c15
-rw-r--r--VNFs/DPPD-PROX/prox_port_cfg.h1
-rw-r--r--VNFs/DPPD-PROX/run.c50
-rw-r--r--VNFs/DPPD-PROX/rx_pkt.c160
-rw-r--r--VNFs/DPPD-PROX/rx_pkt.h8
-rw-r--r--VNFs/DPPD-PROX/stats_core.c2
-rw-r--r--VNFs/DPPD-PROX/task_base.h12
-rw-r--r--VNFs/DPPD-PROX/task_init.c46
-rw-r--r--VNFs/DPPD-PROX/task_init.h7
-rw-r--r--VNFs/DPPD-PROX/tx_pkt.c225
-rw-r--r--VNFs/DPPD-PROX/tx_pkt.h5
-rw-r--r--VNFs/DPPD-PROX/version.h2
39 files changed, 1630 insertions, 511 deletions
diff --git a/VNFs/DPPD-PROX/Makefile b/VNFs/DPPD-PROX/Makefile
index e9a4211b..79bfdef3 100644
--- a/VNFs/DPPD-PROX/Makefile
+++ b/VNFs/DPPD-PROX/Makefile
@@ -78,8 +78,12 @@ endif
endif
endif
+ifeq ($(CONFIG_RTE_BUILD_SHARED_LIB),y)
+LDLIBS += -lrte_pmd_ring -lrte_pmd_null -lrte_pmd_ixgbe -lrte_pmd_i40e -lrte_pmd_e1000 -lrte_pmd_virtio -lrte_pmd_vmxnet3_uio
+endif
+
LD_TINFO = $(shell pkg-config --silence-errors --libs-only-l tinfo)
-LDFLAGS += -lpcap $(LD_TINFO) $(LD_LUA)
+LDFLAGS += -lm -lpcap $(LD_TINFO) $(LD_LUA)
LDFLAGS += -lncurses -lncursesw -ledit
PROX_STATS ?= y
@@ -157,6 +161,8 @@ SRCS-y += handle_swap.c
SRCS-y += handle_police.c
SRCS-y += handle_acl.c
SRCS-y += handle_gen.c
+SRCS-y += handle_master.c
+SRCS-y += packet_utils.c
SRCS-y += handle_mirror.c
SRCS-y += handle_genl4.c
SRCS-y += handle_ipv6_tunnel.c
diff --git a/VNFs/DPPD-PROX/README b/VNFs/DPPD-PROX/README
index a09873cd..1cf857d5 100644
--- a/VNFs/DPPD-PROX/README
+++ b/VNFs/DPPD-PROX/README
@@ -24,7 +24,7 @@ finer grained network functions like QoS, Routing, load-balancing...
Compiling and running this application
--------------------------------------
-This application supports DPDK 16.04, 16.11, 16.11.1, 17.02 and 17.05.
+This application supports DPDK 16.04, 16.11, 16.11.1, 17.02, 17.05 and 17.08.
The following commands assume that the following variables have been set:
export RTE_SDK=/path/to/dpdk
diff --git a/VNFs/DPPD-PROX/arp.h b/VNFs/DPPD-PROX/arp.h
index 279bdada..488008d7 100644
--- a/VNFs/DPPD-PROX/arp.h
+++ b/VNFs/DPPD-PROX/arp.h
@@ -18,6 +18,8 @@
#define _ARP_H_
#include <rte_ether.h>
+#include "etypes.h"
+#include "mbuf_utils.h"
#define ARP_REQUEST 0x100
#define ARP_REPLY 0x200
@@ -49,10 +51,13 @@ static int arp_is_gratuitous(struct ether_hdr_arp *hdr)
return hdr->arp.data.spa == hdr->arp.data.tpa;
}
-static inline void prepare_arp_reply(struct ether_hdr_arp *hdr_arp, struct ether_addr *s_addr)
+static inline void build_arp_reply(struct ether_hdr_arp *hdr_arp, struct ether_addr *s_addr)
{
uint32_t ip_source = hdr_arp->arp.data.spa;
+ memcpy(hdr_arp->ether_hdr.d_addr.addr_bytes, hdr_arp->ether_hdr.s_addr.addr_bytes, sizeof(struct ether_addr));
+ memcpy(hdr_arp->ether_hdr.s_addr.addr_bytes, s_addr, sizeof(struct ether_addr));
+
hdr_arp->arp.data.spa = hdr_arp->arp.data.tpa;
hdr_arp->arp.data.tpa = ip_source;
hdr_arp->arp.oper = 0x200;
@@ -60,6 +65,28 @@ static inline void prepare_arp_reply(struct ether_hdr_arp *hdr_arp, struct ether
memcpy(&hdr_arp->arp.data.sha, s_addr, sizeof(struct ether_addr));
}
+static inline void build_arp_request(struct rte_mbuf *mbuf, struct ether_addr *src_mac, uint32_t ip_dst, uint32_t ip_src)
+{
+ struct ether_hdr_arp *hdr_arp = rte_pktmbuf_mtod(mbuf, struct ether_hdr_arp *);
+ uint64_t mac_bcast = 0xFFFFFFFFFFFF;
+ rte_pktmbuf_pkt_len(mbuf) = 42;
+ rte_pktmbuf_data_len(mbuf) = 42;
+ init_mbuf_seg(mbuf);
+
+ memcpy(&hdr_arp->ether_hdr.d_addr.addr_bytes, &mac_bcast, 6);
+ memcpy(&hdr_arp->ether_hdr.s_addr.addr_bytes, src_mac, 6);
+ hdr_arp->ether_hdr.ether_type = ETYPE_ARP;
+ hdr_arp->arp.htype = 0x100,
+ hdr_arp->arp.ptype = 0x0008;
+ hdr_arp->arp.hlen = 6;
+ hdr_arp->arp.plen = 4;
+ hdr_arp->arp.oper = 0x100;
+ hdr_arp->arp.data.spa = ip_src;
+ hdr_arp->arp.data.tpa = ip_dst;
+ memset(&hdr_arp->arp.data.tha, 0, sizeof(struct ether_addr));
+ memcpy(&hdr_arp->arp.data.sha, src_mac, sizeof(struct ether_addr));
+}
+
static void create_mac(struct ether_hdr_arp *hdr, struct ether_addr *addr)
{
addr->addr_bytes[0] = 0x2;
diff --git a/VNFs/DPPD-PROX/cmd_parser.c b/VNFs/DPPD-PROX/cmd_parser.c
index 95688477..388e3620 100644
--- a/VNFs/DPPD-PROX/cmd_parser.c
+++ b/VNFs/DPPD-PROX/cmd_parser.c
@@ -51,6 +51,7 @@
#include "stats_latency.h"
#include "handle_cgnat.h"
#include "handle_impair.h"
+#include "rx_pkt.h"
static int core_task_is_valid(int lcore_id, int task_id)
{
@@ -235,6 +236,22 @@ static int parse_cmd_dump_rx(const char *str, struct input *input)
if (cores_task_are_valid(lcores, task_id, nb_cores)) {
for (unsigned int i = 0; i < nb_cores; i++) {
+ if (lcores[i] > RTE_MAX_LCORE) {
+ plog_warn("core_id too high, maximum allowed is: %u\n", RTE_MAX_LCORE);
+ return -1;
+ } else if (task_id >= lcore_cfg[lcores[i]].n_tasks_all) {
+ plog_warn("task_id too high, should be in [0, %u]\n", lcore_cfg[lcores[i]].n_tasks_all - 1);
+ return -1;
+ } else {
+ struct lcore_cfg *lconf = &lcore_cfg[lcores[i]];
+ struct task_base *tbase = lconf->tasks_all[task_id];
+ int prev_count = tbase->aux->rx_prev_count;
+ if (((prev_count) && (tbase->aux->rx_pkt_prev[prev_count - 1] == rx_pkt_dummy))
+ || (tbase->rx_pkt == rx_pkt_dummy)) {
+ plog_warn("Unable to dump_rx as rx_pkt_dummy\n");
+ return -1;
+ }
+ }
cmd_dump(lcores[i], task_id, nb_packets, input, 1, 0);
}
}
@@ -375,8 +392,9 @@ static int parse_cmd_set_probability(const char *str, struct input *input)
if (cores_task_are_valid(lcores, task_id, nb_cores)) {
for (unsigned int i = 0; i < nb_cores; i++) {
lcore_id = lcores[i];
- if (!task_is_mode(lcore_id, task_id, "impair", "")) {
+ if ((!task_is_mode(lcore_id, task_id, "impair", "")) && (!task_is_mode(lcore_id, task_id, "impair", "l3"))){
plog_err("Core %u task %u is not impairing packets\n", lcore_id, task_id);
+ return -1;
}
struct task_base *tbase = lcore_cfg[lcore_id].tasks_all[task_id];
task_impair_set_proba(tbase, probability);
@@ -399,8 +417,9 @@ static int parse_cmd_delay_us(const char *str, struct input *input)
if (cores_task_are_valid(lcores, task_id, nb_cores)) {
for (unsigned int i = 0; i < nb_cores; i++) {
lcore_id = lcores[i];
- if (!task_is_mode(lcore_id, task_id, "impair", "")) {
+ if ((!task_is_mode(lcore_id, task_id, "impair", "")) && (!task_is_mode(lcore_id, task_id, "impair", "l3"))){
plog_err("Core %u task %u is not impairing packets\n", lcore_id, task_id);
+ return -1;
}
struct task_base *tbase = lcore_cfg[lcore_id].tasks_all[task_id];
task_impair_set_delay_us(tbase, delay_us, 0);
@@ -423,8 +442,9 @@ static int parse_cmd_random_delay_us(const char *str, struct input *input)
if (cores_task_are_valid(lcores, task_id, nb_cores)) {
for (unsigned int i = 0; i < nb_cores; i++) {
lcore_id = lcores[i];
- if (!task_is_mode(lcore_id, task_id, "impair", "")) {
+ if ((!task_is_mode(lcore_id, task_id, "impair", "")) && (!task_is_mode(lcore_id, task_id, "impair", "l3"))){
plog_err("Core %u task %u is not impairing packets\n", lcore_id, task_id);
+ return -1;
}
struct task_base *tbase = lcore_cfg[lcore_id].tasks_all[task_id];
task_impair_set_delay_us(tbase, 0, delay_us);
@@ -832,14 +852,15 @@ static int parse_cmd_gateway_ip(const char *str, struct input *input)
}
for (i = 0; i < nb_cores; i++) {
lcore_id = lcores[i];
- if ((!task_is_mode(lcore_id, task_id, "gen", "")) && (!task_is_mode(lcore_id, task_id, "gen", "l3"))) {
- plog_err("Core %u task %u is not generating packets\n", lcore_id, task_id);
+
+ if (!task_is_sub_mode(lcore_id, task_id, "l3")) {
+ plog_err("Core %u task %u is not in l3 mode\n", lcore_id, task_id);
}
else {
uint32_t gateway_ip = ((ip[3] & 0xFF) << 24) | ((ip[2] & 0xFF) << 16) | ((ip[1] & 0xFF) << 8) | ((ip[0] & 0xFF) << 0);
struct task_base *tbase = lcore_cfg[lcore_id].tasks_all[task_id];
plog_info("Setting gateway ip to %s\n", str);
- task_gen_set_gateway_ip(tbase, gateway_ip);
+ task_set_gateway_ip(tbase, gateway_ip);
}
}
return 0;
@@ -860,12 +881,16 @@ static int parse_cmd_local_ip(const char *str, struct input *input)
}
for (i = 0; i < nb_cores; i++) {
lcore_id = lcores[i];
+ struct task_base *tbase = lcore_cfg[lcore_id].tasks_all[task_id];
+ uint32_t local_ip = ((ip[3] & 0xFF) << 24) | ((ip[2] & 0xFF) << 16) | ((ip[1] & 0xFF) << 8) | ((ip[0] & 0xFF) << 0);
if (!task_is_mode(lcore_id, task_id, "arp", "local")) {
- plog_err("Core %u task %u is not in arp mode\n", lcore_id, task_id);
- }
- else {
- uint32_t local_ip = ((ip[3] & 0xFF) << 24) | ((ip[2] & 0xFF) << 16) | ((ip[1] & 0xFF) << 8) | ((ip[0] & 0xFF) << 0);
- struct task_base *tbase = lcore_cfg[lcore_id].tasks_all[task_id];
+ if (!task_is_sub_mode(lcore_id, task_id, "l3")) {
+ plog_err("Core %u task %u is not in l3 mode\n", lcore_id, task_id);
+ } else {
+ plog_info("Setting local ip to %s\n", str);
+ task_set_local_ip(tbase, local_ip);
+ }
+ } else {
plog_info("Setting local ip to %s\n", str);
task_arp_set_local_ip(tbase, local_ip);
}
diff --git a/VNFs/DPPD-PROX/commands.c b/VNFs/DPPD-PROX/commands.c
index 93acc62a..adfb690a 100644
--- a/VNFs/DPPD-PROX/commands.c
+++ b/VNFs/DPPD-PROX/commands.c
@@ -101,10 +101,22 @@ static inline int wait_command_handled(struct lcore_cfg *lconf)
}
return 0;
}
+
+static inline void start_l3(struct task_args *targ)
+{
+ if (!task_is_master(targ)) {
+ if ((targ->nb_txrings != 0) || (targ->nb_txports != 0)) {
+ if (targ->task_init->flag_features & TASK_FEATURE_L3)
+ task_start_l3(targ->tbase, targ);
+ }
+ }
+}
+
void start_cores(uint32_t *cores, int count, int task_id)
{
int n_started_cores = 0;
uint32_t started_cores[RTE_MAX_LCORE];
+ struct task_args *targ;
warn_inactive_cores(cores, count, "Can't start core");
@@ -112,7 +124,15 @@ void start_cores(uint32_t *cores, int count, int task_id)
struct lcore_cfg *lconf = &lcore_cfg[cores[i]];
if (lconf->n_tasks_run != lconf->n_tasks_all) {
-
+ if (task_id == -1) {
+ for (uint8_t tid = 0; tid < lconf->n_tasks_all; ++tid) {
+ targ = &lconf->targs[tid];
+ start_l3(targ);
+ }
+ } else {
+ targ = &lconf->targs[task_id];
+ start_l3(targ);
+ }
lconf->msg.type = LCONF_MSG_START;
lconf->msg.task_id = task_id;
lconf_set_req(lconf);
diff --git a/VNFs/DPPD-PROX/defaults.c b/VNFs/DPPD-PROX/defaults.c
index eeb21b2d..6688e8c6 100644
--- a/VNFs/DPPD-PROX/defaults.c
+++ b/VNFs/DPPD-PROX/defaults.c
@@ -26,6 +26,7 @@
#include "prox_port_cfg.h"
#include "etypes.h"
#include "toeplitz.h"
+#include "handle_master.h"
#define TEN_GIGABIT 1250000000
#define QUEUE_SIZES 128
@@ -116,6 +117,7 @@ void set_global_defaults(__attribute__((unused)) struct prox_cfg *prox_cfg)
void set_task_defaults(struct prox_cfg* prox_cfg, struct lcore_cfg* lcore_cfg_init)
{
prox_cfg->master = RTE_MAX_LCORE;
+ handle_ctrl_plane = NULL;
for (uint32_t i = 0; i < RTE_DIM(prox_cfg->cpe_table_ports); ++i) {
prox_cfg->cpe_table_ports[i] = -1;
diff --git a/VNFs/DPPD-PROX/defaults.h b/VNFs/DPPD-PROX/defaults.h
index 5fb31207..573cc9c5 100644
--- a/VNFs/DPPD-PROX/defaults.h
+++ b/VNFs/DPPD-PROX/defaults.h
@@ -28,6 +28,7 @@ void set_port_defaults(void);
#define MAX_PKT_BURST 64
#define MAX_RING_BURST 64
+#define DUMP_PKT_LEN 128
#if MAX_RING_BURST < MAX_PKT_BURST
#error MAX_RING_BURST < MAX_PKT_BURST
diff --git a/VNFs/DPPD-PROX/handle_arp.c b/VNFs/DPPD-PROX/handle_arp.c
index 106e19e5..767cee11 100644
--- a/VNFs/DPPD-PROX/handle_arp.c
+++ b/VNFs/DPPD-PROX/handle_arp.c
@@ -46,9 +46,7 @@ static void task_update_config(struct task_arp *task)
static void handle_arp(struct task_arp *task, struct ether_hdr_arp *hdr, struct ether_addr *s_addr)
{
- prepare_arp_reply(hdr, s_addr);
- memcpy(hdr->ether_hdr.d_addr.addr_bytes, hdr->ether_hdr.s_addr.addr_bytes, 6);
- memcpy(hdr->ether_hdr.s_addr.addr_bytes, s_addr, 6);
+ build_arp_reply(hdr, s_addr);
}
static int handle_arp_bulk(struct task_base *tbase, struct rte_mbuf **mbufs, uint16_t n_pkts)
diff --git a/VNFs/DPPD-PROX/handle_gen.c b/VNFs/DPPD-PROX/handle_gen.c
index e5e43fca..f8c99ee5 100644
--- a/VNFs/DPPD-PROX/handle_gen.c
+++ b/VNFs/DPPD-PROX/handle_gen.c
@@ -22,6 +22,7 @@
#include <rte_version.h>
#include <rte_byteorder.h>
#include <rte_ether.h>
+#include <rte_hash_crc.h>
#include "prox_shared.h"
#include "random.h"
@@ -45,22 +46,15 @@
#include "local_mbuf.h"
#include "arp.h"
#include "tx_pkt.h"
-#include <rte_hash_crc.h>
+#include "handle_master.h"
struct pkt_template {
- uint64_t dst_mac;
- uint32_t ip_src;
- uint32_t ip_dst_pos;
uint16_t len;
uint16_t l2_len;
uint16_t l3_len;
uint8_t buf[ETHER_MAX_LEN];
};
-#define FLAG_DST_MAC_KNOWN 1
-#define FLAG_L3_GEN 2
-#define FLAG_RANDOM_IPS 4
-
#define MAX_TEMPLATE_INDEX 65536
#define TEMPLATE_INDEX_MASK (MAX_TEMPLATE_INDEX - 1)
#define MBUF_ARP MAX_TEMPLATE_INDEX
@@ -125,12 +119,7 @@ struct task_gen {
uint64_t accur[64];
uint64_t pkt_tsc_offset[64];
struct pkt_template *pkt_template_orig; /* packet templates (from inline or from pcap) */
- struct ether_addr gw_mac;
struct ether_addr src_mac;
- struct rte_hash *mac_hash;
- uint64_t *dst_mac;
- uint32_t gw_ip;
- uint32_t src_ip;
uint8_t flags;
uint8_t cksum_offload;
} __rte_cache_aligned;
@@ -207,22 +196,6 @@ static void task_gen_reset_token_time(struct task_gen *task)
token_time_reset(&task->token_time, rte_rdtsc(), 0);
}
-static void start(struct task_base *tbase)
-{
- struct task_gen *task = (struct task_gen *)tbase;
- task->pkt_queue_index = 0;
-
- task_gen_reset_token_time(task);
-}
-
-static void start_pcap(struct task_base *tbase)
-{
- struct task_gen_pcap *task = (struct task_gen_pcap *)tbase;
- /* When we start, the first packet is sent immediately. */
- task->last_tsc = rte_rdtsc() - task->proto_tsc[0];
- task->pkt_idx = 0;
-}
-
static void task_gen_take_count(struct task_gen *task, uint32_t send_bulk)
{
if (task->pkt_count == (uint32_t)-1)
@@ -337,13 +310,7 @@ static uint32_t task_gen_calc_send_bulk(const struct task_gen *task, uint32_t *t
*/
for (uint16_t j = 0; j < max_bulk; ++j) {
struct pkt_template *pktpl = &task->pkt_template[pkt_idx_tmp];
- if (unlikely((task->flags & (FLAG_L3_GEN | FLAG_DST_MAC_KNOWN)) == FLAG_L3_GEN)) {
- // Generator is supposed to get MAC address - MAC is still unknown for this template
- // generate ARP Request to gateway instead of the intended packet
- pkt_size = 60;
- } else {
- pkt_size = pktpl->len;
- }
+ pkt_size = pktpl->len;
uint32_t pkt_len = pkt_len_to_wire_size(pkt_size);
if (pkt_len + would_send_bytes > task->token_time.bytes_now)
break;
@@ -360,106 +327,6 @@ static uint32_t task_gen_calc_send_bulk(const struct task_gen *task, uint32_t *t
return send_bulk;
}
-static inline void create_arp(struct rte_mbuf *mbuf, uint8_t *pkt_hdr, uint64_t *src_mac, uint32_t ip_dst, uint32_t ip_src)
-{
- uint64_t mac_bcast = 0xFFFFFFFFFFFF;
- rte_pktmbuf_pkt_len(mbuf) = 42;
- rte_pktmbuf_data_len(mbuf) = 42;
- init_mbuf_seg(mbuf);
- struct ether_hdr_arp *hdr_arp = (struct ether_hdr_arp *)pkt_hdr;
-
- memcpy(&hdr_arp->ether_hdr.d_addr.addr_bytes, &mac_bcast, 6);
- memcpy(&hdr_arp->ether_hdr.s_addr.addr_bytes, src_mac, 6);
- hdr_arp->ether_hdr.ether_type = ETYPE_ARP;
- hdr_arp->arp.htype = 0x100,
- hdr_arp->arp.ptype = 0x0008;
- hdr_arp->arp.hlen = 6;
- hdr_arp->arp.plen = 4;
- hdr_arp->arp.oper = 0x100;
- hdr_arp->arp.data.spa = ip_src;
- hdr_arp->arp.data.tpa = ip_dst;
- memset(&hdr_arp->arp.data.tha, 0, sizeof(struct ether_addr));
- memcpy(&hdr_arp->arp.data.sha, src_mac, sizeof(struct ether_addr));
-}
-
-static int task_gen_write_dst_mac(struct task_gen *task, struct rte_mbuf **mbufs, uint8_t **pkt_hdr, uint32_t count)
-{
- uint32_t ip_dst_pos, ip_src_pos, ip_dst, ip_src;
- uint16_t i;
- int ret;
-
- if (task->flags & FLAG_L3_GEN) {
- if (task->gw_ip) {
- if (unlikely((task->flags & FLAG_DST_MAC_KNOWN) == 0)) {
- for (i = 0; i < count; ++i) {
- struct pkt_template *pktpl = &task->pkt_template[mbufs[i]->udata64 & TEMPLATE_INDEX_MASK];
- create_arp(mbufs[i], pkt_hdr[i], (uint64_t *)&pktpl->buf[6], task->gw_ip, pktpl->ip_src);
- mbufs[i]->udata64 |= MBUF_ARP;
- }
- } else {
- for (i = 0; i < count; ++i) {
- struct ether_hdr *hdr = (struct ether_hdr *)pkt_hdr[i];
- memcpy(&hdr->d_addr.addr_bytes, &task->gw_mac, 6);
- }
- }
- } else if (unlikely((task->flags & FLAG_RANDOM_IPS) != 0) || (task->n_pkts >= 4)){
- // Find mac in lookup table. Send ARP if not found
- int32_t positions[MAX_PKT_BURST], idx;
- void *keys[MAX_PKT_BURST];
- uint32_t key[MAX_PKT_BURST];
- for (i = 0; i < count; ++i) {
- uint8_t *hdr = (uint8_t *)pkt_hdr[i];
- struct pkt_template *pktpl = &task->pkt_template[mbufs[i]->udata64 & TEMPLATE_INDEX_MASK];
- ip_dst_pos = pktpl->ip_dst_pos;
- ip_dst = *(uint32_t *)(hdr + ip_dst_pos);
- key[i] = ip_dst;
- keys[i] = &key[i];
- }
- ret = rte_hash_lookup_bulk(task->mac_hash, (const void **)&keys, count, positions);
- if (unlikely(ret < 0)) {
- plogx_err("lookup_bulk failed in mac_hash\n");
- tx_pkt_drop_all((struct task_base *)task, mbufs, count, NULL);
- return -1;
- }
- for (i = 0; i < count; ++i) {
- idx = positions[i];
- if (unlikely(idx < 0)) {
- // mac not found for this IP
- struct pkt_template *pktpl = &task->pkt_template[mbufs[i]->udata64 & TEMPLATE_INDEX_MASK];
- uint8_t *hdr = (uint8_t *)pkt_hdr[i];
- ip_src_pos = pktpl->ip_dst_pos - 4;
- ip_src = *(uint32_t *)(hdr + ip_src_pos);
- create_arp(mbufs[i], pkt_hdr[i], (uint64_t *)&hdr[6], key[i], ip_src);
- mbufs[i]->udata64 |= MBUF_ARP;
- } else {
- // mac found for this IP
- struct ether_hdr_arp *hdr_arp = (struct ether_hdr_arp *)pkt_hdr[i];
- memcpy(&hdr_arp->ether_hdr.d_addr.addr_bytes, &task->dst_mac[idx], 6);
- }
- }
- } else {
- for (i = 0; i < count; ++i) {
- uint8_t *hdr = (uint8_t *)pkt_hdr[i];
- struct pkt_template *pktpl = &task->pkt_template[mbufs[i]->udata64 & TEMPLATE_INDEX_MASK];
-
- // Check if packet template already has the mac
- if (unlikely(pktpl->dst_mac == 0)) {
- // no random_ip, can take from from packet template but no mac (yet)
- uint32_t ip_dst_pos = pktpl->ip_dst_pos;
- ip_dst = *(uint32_t *)(hdr + ip_dst_pos);
- create_arp(mbufs[i], pkt_hdr[i], (uint64_t *)&pktpl->buf[6], ip_dst, pktpl->ip_src);
- mbufs[i]->udata64 |= MBUF_ARP;
- } else {
- // no random ip, mac known
- struct ether_hdr_arp *hdr_arp = (struct ether_hdr_arp *)pkt_hdr[i];
- memcpy(&hdr_arp->ether_hdr.d_addr.addr_bytes, &pktpl->dst_mac, 6);
- }
- }
- }
- }
- return 0;
-}
-
static void task_gen_apply_random_fields(struct task_gen *task, uint8_t *hdr)
{
uint32_t ret, ret_tmp;
@@ -690,92 +557,79 @@ static void task_gen_update_config(struct task_gen *task)
task_gen_reset_token_time(task);
}
-static inline void handle_arp_pkts(struct task_gen *task, struct rte_mbuf **mbufs, uint16_t n_pkts)
+static inline void build_value(struct task_gen *task, uint32_t mask, int bit_pos, uint32_t val, uint32_t fixed_bits)
{
- int j;
- int ret;
- struct ether_hdr_arp *hdr;
- uint8_t out[MAX_PKT_BURST];
- static struct my_arp_t arp_reply = {
- .htype = 0x100,
- .ptype = 8,
- .hlen = 6,
- .plen = 4,
- .oper = 0x200
- };
- static struct my_arp_t arp_request = {
- .htype = 0x100,
- .ptype = 8,
- .hlen = 6,
- .plen = 4,
- .oper = 0x100
- };
-
- for (j = 0; j < n_pkts; ++j) {
- PREFETCH0(mbufs[j]);
- }
- for (j = 0; j < n_pkts; ++j) {
- PREFETCH0(rte_pktmbuf_mtod(mbufs[j], void *));
+ struct task_base *tbase = (struct task_base *)task;
+ if (bit_pos < 32) {
+ build_value(task, mask >> 1, bit_pos + 1, val, fixed_bits);
+ if (mask & 1) {
+ build_value(task, mask >> 1, bit_pos + 1, val | (1 << bit_pos), fixed_bits);
+ }
+ } else {
+ register_ip_to_ctrl_plane(tbase->l3.tmaster, rte_cpu_to_be_32(val | fixed_bits), tbase->l3.reachable_port_id, tbase->l3.core_id, tbase->l3.task_id);
}
- for (j = 0; j < n_pkts; ++j) {
- hdr = rte_pktmbuf_mtod(mbufs[j], struct ether_hdr_arp *);
- if (hdr->ether_hdr.ether_type == ETYPE_ARP) {
- if (memcmp(&hdr->arp, &arp_reply, 8) == 0) {
- uint32_t ip = hdr->arp.data.spa;
- // plog_info("Received ARP Reply for IP %x\n",ip);
- if (ip == task->gw_ip) {
- memcpy(&task->gw_mac, &hdr->arp.data.sha, 6);;
- task->flags |= FLAG_DST_MAC_KNOWN;
- out[j] = OUT_HANDLED;
- continue;
- } else if ((task->n_pkts >= 4) || (task->flags & FLAG_RANDOM_IPS)) {
- // Ideally, we should add the key when making the arp request,
- // We should only store the mac address key was created.
- // Here we are storing MAC we did not asked for...
- ret = rte_hash_add_key(task->mac_hash, (const void *)&ip);
- if (ret < 0) {
- plogx_info("Unable add ip %d.%d.%d.%d in mac_hash\n", IP4(ip));
- out[j] = OUT_DISCARD;
- } else {
- task->dst_mac[ret] = *(uint64_t *)&(hdr->arp.data.sha);
- out[j] = OUT_HANDLED;
- }
- continue;
- }
- // Need to find template back...
- // Only try this if there are few templates
- for (unsigned int idx = 0; idx < task->n_pkts; idx++) {
- struct pkt_template *pktpl = &task->pkt_template[idx];
- uint32_t ip_dst_pos = pktpl->ip_dst_pos;
- uint32_t *ip_dst = (uint32_t *)(((uint8_t *)pktpl->buf) + ip_dst_pos);
- if (*ip_dst == ip) {
- pktpl->dst_mac = *(uint64_t *)&(hdr->arp.data.sha);
- }
- out[j] = OUT_HANDLED;
- }
- } else if (memcmp(&hdr->arp, &arp_request, 8) == 0) {
- struct ether_addr s_addr;
- if (!task->src_ip) {
- create_mac(hdr, &s_addr);
- prepare_arp_reply(hdr, &s_addr);
- memcpy(hdr->ether_hdr.d_addr.addr_bytes, hdr->ether_hdr.s_addr.addr_bytes, 6);
- memcpy(hdr->ether_hdr.s_addr.addr_bytes, &s_addr, 6);
- out[j] = 0;
- } else if (hdr->arp.data.tpa == task->src_ip) {
- prepare_arp_reply(hdr, &task->src_mac);
- memcpy(hdr->ether_hdr.d_addr.addr_bytes, hdr->ether_hdr.s_addr.addr_bytes, 6);
- memcpy(hdr->ether_hdr.s_addr.addr_bytes, &task->src_mac, 6);
- out[j] = 0;
+}
+static inline void register_all_ip_to_ctrl_plane(struct task_gen *task)
+{
+ struct task_base *tbase = (struct task_base *)task;
+ int i, len, fixed;
+ unsigned int offset;
+ uint32_t mask;
+
+ for (uint32_t i = 0; i < task->n_pkts; ++i) {
+ struct pkt_template *pktpl = &task->pkt_template[i];
+ unsigned int ip_src_pos = 0;
+ int maybe_ipv4 = 0;
+ unsigned int l2_len = sizeof(struct ether_hdr);
+
+ uint8_t *pkt = pktpl->buf;
+ struct ether_hdr *eth_hdr = (struct ether_hdr*)pkt;
+ uint16_t ether_type = eth_hdr->ether_type;
+ struct vlan_hdr *vlan_hdr;
+
+ // Unstack VLAN tags
+ while (((ether_type == ETYPE_8021ad) || (ether_type == ETYPE_VLAN)) && (l2_len + sizeof(struct vlan_hdr) < pktpl->len)) {
+ vlan_hdr = (struct vlan_hdr *)(pkt + l2_len);
+ l2_len +=4;
+ ether_type = vlan_hdr->eth_proto;
+ }
+ if ((ether_type == ETYPE_MPLSU) || (ether_type == ETYPE_MPLSM)) {
+ l2_len +=4;
+ maybe_ipv4 = 1;
+ }
+ if ((ether_type != ETYPE_IPv4) && !maybe_ipv4)
+ continue;
+
+ struct ipv4_hdr *ip = (struct ipv4_hdr *)(pkt + l2_len);
+ PROX_PANIC(ip->version_ihl >> 4 != 4, "IPv4 ether_type but IP version = %d != 4", ip->version_ihl >> 4);
+
+ // Even if IPv4 header contains options, options are after ip src and dst
+ ip_src_pos = l2_len + sizeof(struct ipv4_hdr) - 2 * sizeof(uint32_t);
+ uint32_t *ip_src = ((uint32_t *)(pktpl->buf + ip_src_pos));
+ plog_info("\tip_src_pos = %d, ip_src = %x\n", ip_src_pos, *ip_src);
+ register_ip_to_ctrl_plane(tbase->l3.tmaster, *ip_src, tbase->l3.reachable_port_id, tbase->l3.core_id, tbase->l3.task_id);
+
+ for (int j = 0; j < task->n_rands; j++) {
+ offset = task->rand[j].rand_offset;
+ len = task->rand[j].rand_len;
+ mask = task->rand[j].rand_mask;
+ fixed = task->rand[j].fixed_bits;
+ plog_info("offset = %d, len = %d, mask = %x, fixed = %x\n", offset, len, mask, fixed);
+ if ((offset < ip_src_pos + 4) && (offset + len >= ip_src_pos)) {
+ if (offset >= ip_src_pos) {
+ int32_t ip_src_mask = (1 << (4 + ip_src_pos - offset) * 8) - 1;
+ mask = mask & ip_src_mask;
+ fixed = (fixed & ip_src_mask) | (rte_be_to_cpu_32(*ip_src) & ~ip_src_mask);
+ build_value(task, mask, 0, 0, fixed);
} else {
- out[j] = OUT_DISCARD;
- plogx_dbg("Received ARP on unexpected IP %x, expecting %x\n", rte_be_to_cpu_32(hdr->arp.data.tpa), rte_be_to_cpu_32(task->src_ip));
+ int32_t bits = ((ip_src_pos + 4 - offset - len) * 8);
+ mask = mask << bits;
+ fixed = (fixed << bits) | (rte_be_to_cpu_32(*ip_src) & ((1 << bits) - 1));
+ build_value(task, mask, 0, 0, fixed);
}
}
- } else {
- out[j] = OUT_DISCARD;
}
}
- ret = task->base.tx_pkt(&task->base, mbufs, n_pkts, out);
}
static int handle_gen_bulk(struct task_base *tbase, struct rte_mbuf **mbufs, uint16_t n_pkts)
@@ -786,10 +640,6 @@ static int handle_gen_bulk(struct task_base *tbase, struct rte_mbuf **mbufs, uin
int i, j;
- if (unlikely((task->flags & FLAG_L3_GEN) && (n_pkts != 0))) {
- handle_arp_pkts(task, mbufs, n_pkts);
- }
-
task_gen_update_config(task);
if (task->pkt_count == 0) {
@@ -802,7 +652,7 @@ static int handle_gen_bulk(struct task_base *tbase, struct rte_mbuf **mbufs, uin
token_time_update(&task->token_time, rte_rdtsc());
uint32_t would_send_bytes;
- const uint32_t send_bulk = task_gen_calc_send_bulk(task, &would_send_bytes);
+ uint32_t send_bulk = task_gen_calc_send_bulk(task, &would_send_bytes);
if (send_bulk == 0)
return 0;
@@ -817,8 +667,6 @@ static int handle_gen_bulk(struct task_base *tbase, struct rte_mbuf **mbufs, uin
task_gen_load_and_prefetch(new_pkts, pkt_hdr, send_bulk);
task_gen_build_packets(task, new_pkts, pkt_hdr, send_bulk);
task_gen_apply_all_random_fields(task, pkt_hdr, send_bulk);
- if (task_gen_write_dst_mac(task, new_pkts, pkt_hdr, send_bulk) < 0)
- return 0;
task_gen_apply_all_accur_pos(task, new_pkts, pkt_hdr, send_bulk);
task_gen_apply_all_sig(task, new_pkts, pkt_hdr, send_bulk);
task_gen_apply_all_unique_id(task, new_pkts, pkt_hdr, send_bulk);
@@ -1135,13 +983,6 @@ int task_gen_set_pkt_size(struct task_base *tbase, uint32_t pkt_size)
return rc;
}
-void task_gen_set_gateway_ip(struct task_base *tbase, uint32_t ip)
-{
- struct task_gen *task = (struct task_gen *)tbase;
- task->gw_ip = ip;
- task->flags &= ~FLAG_DST_MAC_KNOWN;
-}
-
void task_gen_set_rate(struct task_base *tbase, uint64_t bps)
{
struct task_gen *task = (struct task_gen *)tbase;
@@ -1159,7 +1000,6 @@ void task_gen_reset_randoms(struct task_base *tbase)
task->rand[i].rand_offset = 0;
}
task->n_rands = 0;
- task->flags &= ~FLAG_RANDOM_IPS;
}
int task_gen_set_value(struct task_base *tbase, uint32_t value, uint32_t offset, uint32_t len)
@@ -1276,16 +1116,37 @@ int task_gen_add_rand(struct task_base *tbase, const char *rand_str, uint32_t of
task->rand[task->n_rands].rand_mask = mask;
task->rand[task->n_rands].fixed_bits = fixed;
- struct pkt_template *pktpl = &task->pkt_template[0];
- if (!((offset >= pktpl->ip_dst_pos + 4) || (offset + len < pktpl->ip_dst_pos))) {
- plog_info("\tUsing randoms IP destinations\n");
- task->flags |= FLAG_RANDOM_IPS;
- }
-
task->n_rands++;
return 0;
}
+static void start(struct task_base *tbase)
+{
+ struct task_gen *task = (struct task_gen *)tbase;
+ task->pkt_queue_index = 0;
+
+ task_gen_reset_token_time(task);
+ if (tbase->l3.tmaster) {
+ register_all_ip_to_ctrl_plane(task);
+ }
+ /* TODO
+ Handle the case when two tasks transmit to the same port
+ and one of them is stopped. In that case ARP (requests or replies)
+ might not be sent. Master will have to keep a list of rings.
+ stop will have to de-register IP from ctrl plane.
+ un-registration will remove the ring. when having more than
+ one active rings, master can always use the first one
+ */
+}
+
+static void start_pcap(struct task_base *tbase)
+{
+ struct task_gen_pcap *task = (struct task_gen_pcap *)tbase;
+ /* When we start, the first packet is sent immediately. */
+ task->last_tsc = rte_rdtsc() - task->proto_tsc[0];
+ task->pkt_idx = 0;
+}
+
static void init_task_gen_early(struct task_args *targ)
{
uint8_t *generator_count = prox_sh_find_system("generator_count");
@@ -1353,70 +1214,6 @@ static void init_task_gen(struct task_base *tbase, struct task_args *targ)
}
}
memcpy(&task->src_mac, &prox_port_cfg[task->base.tx_params_hw.tx_port_queue->port].eth_addr, sizeof(struct ether_addr));
- if (!strcmp(targ->task_init->sub_mode_str, "l3")) {
- // In L3 GEN, we need to receive ARP replies
- task->flags = FLAG_L3_GEN;
- task->gw_ip = rte_cpu_to_be_32(targ->gateway_ipv4);
- uint32_t n_entries;
-
- if (targ->number_gen_ip == 0)
- n_entries = 1048576;
- else
- n_entries = targ->number_gen_ip;
-
- static char hash_name[30];
- sprintf(hash_name, "A%03d_mac_table", targ->lconf->id);
-
- struct rte_hash_parameters hash_params = {
- .name = hash_name,
- .entries = n_entries,
- .key_len = sizeof(uint32_t),
- .hash_func = rte_hash_crc,
- .hash_func_init_val = 0,
- };
- task->mac_hash = rte_hash_create(&hash_params);
- PROX_PANIC(task->mac_hash == NULL, "Failed to set up mac hash table for %d IP\n", n_entries);
-
- const uint32_t socket = rte_lcore_to_socket_id(targ->lconf->id);
- task->dst_mac = (uint64_t *)prox_zmalloc(n_entries * sizeof(uint64_t), socket);
- PROX_PANIC(task->dst_mac == NULL, "Failed to allocate mac table for %d IP\n", n_entries);
-
- for (uint32_t i = 0; i < task->n_pkts; ++i) {
- // For all destination IP, ARP request will need to be sent
- // Store position of Destination IP in template
- int ip_dst_pos = 0;
- int maybe_ipv4 = 0;
- int l2_len = sizeof(struct ether_hdr);
- struct vlan_hdr *vlan_hdr;
- uint8_t *pkt = task->pkt_template[i].buf;
- struct ether_hdr *eth_hdr = (struct ether_hdr*)pkt;
- struct ipv4_hdr *ip;
- uint16_t ether_type = eth_hdr->ether_type;
-
- // Unstack VLAN tags
- while (((ether_type == ETYPE_8021ad) || (ether_type == ETYPE_VLAN)) && (l2_len + sizeof(struct vlan_hdr) < task->pkt_template[i].len)) {
- vlan_hdr = (struct vlan_hdr *)(pkt + l2_len);
- l2_len +=4;
- ether_type = vlan_hdr->eth_proto;
- }
- if ((ether_type == ETYPE_MPLSU) || (ether_type == ETYPE_MPLSM)) {
- l2_len +=4;
- maybe_ipv4 = 1;
- }
- if ((ether_type == ETYPE_IPv4) || maybe_ipv4) {
- struct ipv4_hdr *ip = (struct ipv4_hdr *)(pkt + l2_len);
- PROX_PANIC(ip->version_ihl >> 4 != 4, "IPv4 ether_type but IP version = %d != 4", ip->version_ihl >> 4);
- // Even if IPv4 header contains options, options are after ip src and dst
- ip_dst_pos = l2_len + sizeof(struct ipv4_hdr) - sizeof(uint32_t);
- uint32_t *p = ((uint32_t *)(task->pkt_template[i].buf + ip_dst_pos - sizeof(uint32_t)));
- task->pkt_template[i].ip_dst_pos = ip_dst_pos;
- task->pkt_template[i].ip_src = *p;
- uint32_t *p1 = ((uint32_t *)(task->pkt_template[i].buf + ip_dst_pos));
- plog_info("\tip_dst_pos = %d, ip_dst = %x\n", ip_dst_pos, *p1);
- }
- }
- task->src_ip = rte_cpu_to_be_32(targ->local_ipv4);
- }
for (uint32_t i = 0; i < targ->n_rand_str; ++i) {
PROX_PANIC(task_gen_add_rand(tbase, targ->rand_str[i], targ->rand_offset[i], UINT32_MAX),
"Failed to add random\n");
@@ -1452,9 +1249,9 @@ static struct task_init task_init_gen_l3 = {
#ifdef SOFT_CRC
// For SOFT_CRC, no offload is needed. If both NOOFFLOADS and NOMULTSEGS flags are set the
// vector mode is used by DPDK, resulting (theoretically) in higher performance.
- .flag_features = TASK_FEATURE_ZERO_RX | TASK_FEATURE_TXQ_FLAGS_NOOFFLOADS | TASK_FEATURE_TXQ_FLAGS_NOMULTSEGS|TASK_FEATURE_ZERO_RX,
+ .flag_features = TASK_FEATURE_NEVER_DISCARDS | TASK_FEATURE_NO_RX | TASK_FEATURE_TXQ_FLAGS_NOOFFLOADS | TASK_FEATURE_TXQ_FLAGS_NOMULTSEGS,
#else
- .flag_features = TASK_FEATURE_ZERO_RX,
+ .flag_features = TASK_FEATURE_NEVER_DISCARDS | TASK_FEATURE_NO_RX,
#endif
.size = sizeof(struct task_gen)
};
diff --git a/VNFs/DPPD-PROX/handle_gen.h b/VNFs/DPPD-PROX/handle_gen.h
index 6f00ca12..5083fea9 100644
--- a/VNFs/DPPD-PROX/handle_gen.h
+++ b/VNFs/DPPD-PROX/handle_gen.h
@@ -39,7 +39,6 @@ struct task_base;
void task_gen_set_pkt_count(struct task_base *tbase, uint32_t count);
int task_gen_set_pkt_size(struct task_base *tbase, uint32_t pkt_size);
void task_gen_set_rate(struct task_base *tbase, uint64_t bps);
-void task_gen_set_gateway_ip(struct task_base *tbase, uint32_t ip);
void task_gen_reset_randoms(struct task_base *tbase);
void task_gen_reset_values(struct task_base *tbase);
int task_gen_set_value(struct task_base *tbase, uint32_t value, uint32_t offset, uint32_t len);
diff --git a/VNFs/DPPD-PROX/handle_impair.c b/VNFs/DPPD-PROX/handle_impair.c
index 3f2ee0eb..78c9e400 100644
--- a/VNFs/DPPD-PROX/handle_impair.c
+++ b/VNFs/DPPD-PROX/handle_impair.c
@@ -25,6 +25,7 @@
#include "random.h"
#include "handle_impair.h"
#include "prefetch.h"
+#include "prox_port_cfg.h"
#if RTE_VERSION < RTE_VERSION_NUM(1,8,0,0)
#define RTE_CACHE_LINE_SIZE CACHE_LINE_SIZE
@@ -60,9 +61,13 @@ struct task_impair {
uint64_t last_idx;
struct queue *buffer;
uint32_t socket_id;
- int need_update;
+ uint32_t flags;
+ uint8_t src_mac[6];
};
+#define IMPAIR_NEED_UPDATE 1
+#define IMPAIR_SET_MAC 2
+
static int handle_bulk_impair(struct task_base *tbase, struct rte_mbuf **mbufs, uint16_t n_pkts);
static int handle_bulk_impair_random(struct task_base *tbase, struct rte_mbuf **mbufs, uint16_t n_pkts);
static int handle_bulk_random_drop(struct task_base *tbase, struct rte_mbuf **mbufs, uint16_t n_pkts);
@@ -76,7 +81,7 @@ void task_impair_set_proba(struct task_base *tbase, float proba)
void task_impair_set_delay_us(struct task_base *tbase, uint32_t delay_us, uint32_t random_delay_us)
{
struct task_impair *task = (struct task_impair *)tbase;
- task->need_update = 1;
+ task->flags |= IMPAIR_NEED_UPDATE;
task->random_delay_us = random_delay_us;
task->delay_us = delay_us;
}
@@ -86,9 +91,9 @@ static void task_impair_update(struct task_base *tbase)
struct task_impair *task = (struct task_impair *)tbase;
uint32_t queue_len = 0;
size_t mem_size;
- if (!task->need_update)
+ if ((task->flags & IMPAIR_NEED_UPDATE) == 0)
return;
- task->need_update = 0;
+ task->flags &= ~IMPAIR_NEED_UPDATE;
uint64_t now = rte_rdtsc();
uint8_t out[MAX_PKT_BURST] = {0};
uint64_t now_idx = (now >> DELAY_ACCURACY) & DELAY_MAX_MASK;
@@ -187,8 +192,23 @@ static int handle_bulk_random_drop(struct task_base *tbase, struct rte_mbuf **mb
{
struct task_impair *task = (struct task_impair *)tbase;
uint8_t out[MAX_PKT_BURST];
+ struct ether_hdr * hdr[MAX_PKT_BURST];
+ for (uint16_t i = 0; i < n_pkts; ++i) {
+ PREFETCH0(mbufs[i]);
+ }
for (uint16_t i = 0; i < n_pkts; ++i) {
- out[i] = rand_r(&task->seed) <= task->tresh? 0 : OUT_DISCARD;
+ hdr[i] = rte_pktmbuf_mtod(mbufs[i], struct ether_hdr *);
+ PREFETCH0(hdr[i]);
+ }
+ if (task->flags & IMPAIR_SET_MAC) {
+ for (uint16_t i = 0; i < n_pkts; ++i) {
+ ether_addr_copy((struct ether_addr *)&task->src_mac[0], &hdr[i]->s_addr);
+ out[i] = rand_r(&task->seed) <= task->tresh? 0 : OUT_DISCARD;
+ }
+ } else {
+ for (uint16_t i = 0; i < n_pkts; ++i) {
+ out[i] = rand_r(&task->seed) <= task->tresh? 0 : OUT_DISCARD;
+ }
}
return task->base.tx_pkt(&task->base, mbufs, n_pkts, out);
task_impair_update(tbase);
@@ -202,11 +222,21 @@ static int handle_bulk_impair(struct task_base *tbase, struct rte_mbuf **mbufs,
uint16_t enqueue_failed;
uint16_t i;
int ret = 0;
+ struct ether_hdr * hdr[MAX_PKT_BURST];
+ for (uint16_t i = 0; i < n_pkts; ++i) {
+ PREFETCH0(mbufs[i]);
+ }
+ for (uint16_t i = 0; i < n_pkts; ++i) {
+ hdr[i] = rte_pktmbuf_mtod(mbufs[i], struct ether_hdr *);
+ PREFETCH0(hdr[i]);
+ }
int nb_empty_slots = (task->queue_tail - task->queue_head + task->queue_mask) & task->queue_mask;
if (likely(nb_empty_slots >= n_pkts)) {
/* We know n_pkts fits, no need to check for every packet */
for (i = 0; i < n_pkts; ++i) {
+ if (task->flags & IMPAIR_SET_MAC)
+ ether_addr_copy((struct ether_addr *)&task->src_mac[0], &hdr[i]->s_addr);
task->queue[task->queue_head].tsc = now + task->delay_time;
task->queue[task->queue_head].mbuf = mbufs[i];
task->queue_head = (task->queue_head + 1) & task->queue_mask;
@@ -214,6 +244,8 @@ static int handle_bulk_impair(struct task_base *tbase, struct rte_mbuf **mbufs,
} else {
for (i = 0; i < n_pkts; ++i) {
if (((task->queue_head + 1) & task->queue_mask) != task->queue_tail) {
+ if (task->flags & IMPAIR_SET_MAC)
+ ether_addr_copy((struct ether_addr *)&task->src_mac[0], &hdr[i]->s_addr);
task->queue[task->queue_head].tsc = now + task->delay_time;
task->queue[task->queue_head].mbuf = mbufs[i];
task->queue_head = (task->queue_head + 1) & task->queue_mask;
@@ -302,6 +334,14 @@ static int handle_bulk_impair_random(struct task_base *tbase, struct rte_mbuf **
int ret = 0;
uint64_t packet_time, idx;
uint64_t now_idx = (now >> DELAY_ACCURACY) & DELAY_MAX_MASK;
+ struct ether_hdr * hdr[MAX_PKT_BURST];
+ for (uint16_t i = 0; i < n_pkts; ++i) {
+ PREFETCH0(mbufs[i]);
+ }
+ for (uint16_t i = 0; i < n_pkts; ++i) {
+ hdr[i] = rte_pktmbuf_mtod(mbufs[i], struct ether_hdr *);
+ PREFETCH0(hdr[i]);
+ }
for (i = 0; i < n_pkts; ++i) {
packet_time = now + random_delay(&task->state, task->delay_time, task->delay_time_mask);
@@ -309,6 +349,8 @@ static int handle_bulk_impair_random(struct task_base *tbase, struct rte_mbuf **
while (idx != ((now_idx - 1) & DELAY_MAX_MASK)) {
struct queue *queue = &task->buffer[idx];
if (((queue->queue_head + 1) & task->queue_mask) != queue->queue_tail) {
+ if (task->flags & IMPAIR_SET_MAC)
+ ether_addr_copy((struct ether_addr *)&task->src_mac[0], &hdr[i]->s_addr);
queue->queue_elem[queue->queue_head].mbuf = mbufs[i];
queue->queue_head = (queue->queue_head + 1) & task->queue_mask;
break;
@@ -405,6 +447,12 @@ static void init_task(struct task_base *tbase, struct task_args *targ)
}
}
random_init_seed(&task->state);
+ if (targ->nb_txports) {
+ memcpy(&task->src_mac[0], &prox_port_cfg[tbase->tx_params_hw.tx_port_queue[0].port].eth_addr, sizeof(struct ether_addr));
+ task->flags = IMPAIR_SET_MAC;
+ } else {
+ task->flags = 0;
+ }
}
static struct task_init tinit = {
diff --git a/VNFs/DPPD-PROX/handle_irq.c b/VNFs/DPPD-PROX/handle_irq.c
index 4abf84a1..86640c69 100644
--- a/VNFs/DPPD-PROX/handle_irq.c
+++ b/VNFs/DPPD-PROX/handle_irq.c
@@ -39,6 +39,7 @@ struct irq_bucket {
struct task_irq {
struct task_base base;
uint64_t start_tsc;
+ uint64_t first_tsc;
uint64_t tsc;
uint64_t max_irq;
uint8_t lcore_id;
@@ -99,9 +100,12 @@ static void irq_stop(struct task_base *tbase)
struct task_irq *task = (struct task_irq *)tbase;
uint32_t i;
uint32_t lcore_id = rte_lcore_id();
+ uint64_t lat, max_lat = 0, tot_lat = 0;
int bucket_id;
+ int n_lat = 0;
plog_info("Stopping core %u\n", lcore_id);
+ sleep(2); // Make sure all cores are stopped before starting to write
plog_info("Core ID; Interrupt (nanosec); Time (msec)\n");
for (int j = 0; j < 2; j++) {
// Start dumping the oldest bucket first
@@ -112,14 +116,19 @@ static void irq_stop(struct task_base *tbase)
struct irq_bucket *bucket = &task->buffer[bucket_id];
for (i=0; i< bucket->index;i++) {
if (bucket->info[i].lat != 0) {
- plog_info("%d; %ld; %ld\n",
- lcore_id,
- bucket->info[i].lat * 1000000000 / rte_get_tsc_hz(),
+ lat = bucket->info[i].lat * 1000000000 / rte_get_tsc_hz();
+ if (max_lat < lat)
+ max_lat = lat;
+ n_lat++;
+ tot_lat += lat;
+ plog_info("%d; %ld; %ld\n", lcore_id, lat,
(bucket->info[i].tsc - task->start_tsc) * 1000 / rte_get_tsc_hz());
}
}
}
- plog_info("Core %u stopped\n", lcore_id);
+ if (n_lat)
+ tot_lat = tot_lat / n_lat;
+ plog_info("Core %u stopped. max lat is %ld and average is %ld\n", lcore_id, max_lat, tot_lat);
}
static inline int handle_irq_bulk(struct task_base *tbase, struct rte_mbuf **mbufs, uint16_t n_pkts)
@@ -133,7 +142,7 @@ static inline int handle_irq_bulk(struct task_base *tbase, struct rte_mbuf **mbu
struct irq_bucket *bucket = &task->buffer[task->task_use_lt];
tsc1 = rte_rdtsc();
- if ((task->tsc != 0) && ((tsc1 - task->tsc) > task->max_irq) && (bucket->index < MAX_INDEX)) {
+ if ((tsc1 > task->first_tsc) && (task->tsc != 0) && ((tsc1 - task->tsc) > task->max_irq) && (bucket->index < MAX_INDEX)) {
bucket->info[bucket->index].tsc = tsc1;
bucket->info[bucket->index++].lat = tsc1 - task->tsc;
}
@@ -148,6 +157,7 @@ static void init_task_irq(struct task_base *tbase,
// max_irq expressed in cycles
task->max_irq = rte_get_tsc_hz() / MAX_INTERRUPT_LENGTH;
task->start_tsc = rte_rdtsc();
+ task->first_tsc = task->start_tsc + 2 * rte_get_tsc_hz();
task->lcore_id = targ->lconf->id;
plog_info("\tusing irq mode with max irq set to %ld cycles\n", task->max_irq);
}
diff --git a/VNFs/DPPD-PROX/handle_master.c b/VNFs/DPPD-PROX/handle_master.c
new file mode 100644
index 00000000..6bd4ea2c
--- /dev/null
+++ b/VNFs/DPPD-PROX/handle_master.c
@@ -0,0 +1,348 @@
+/*
+// Copyright (c) 2010-2017 Intel Corporation
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+*/
+
+#include <rte_hash.h>
+#include <rte_hash_crc.h>
+#include "prox_cfg.h"
+
+#include "prox_globals.h"
+#include "rx_pkt.h"
+#include "arp.h"
+#include "handle_master.h"
+#include "log.h"
+#include "mbuf_utils.h"
+#include "etypes.h"
+#include "defaults.h"
+#include "prox_cfg.h"
+#include "prox_malloc.h"
+#include "quit.h"
+#include "task_init.h"
+#include "prox_port_cfg.h"
+#include "main.h"
+#include "lconf.h"
+#include "input.h"
+#include "tx_pkt.h"
+
+#define IP4(x) x & 0xff, (x >> 8) & 0xff, (x >> 16) & 0xff, x >> 24
+
+const char *actions_string[] = {"UPDATE_FROM_CTRL", "SEND_ARP_REQUEST_FROM_CTRL", "SEND_ARP_REPLY_FROM_CTRL", "HANDLE_ARP_TO_CTRL", "REQ_MAC_TO_CTRL"};
+
+static struct my_arp_t arp_reply = {
+ .htype = 0x100,
+ .ptype = 8,
+ .hlen = 6,
+ .plen = 4,
+ .oper = 0x200
+};
+static struct my_arp_t arp_request = {
+ .htype = 0x100,
+ .ptype = 8,
+ .hlen = 6,
+ .plen = 4,
+ .oper = 0x100
+};
+
+struct ip_table {
+ struct ether_addr mac;
+ struct rte_ring *ring;
+};
+
+struct port_table {
+ struct ether_addr mac;
+ struct rte_ring *ring;
+ uint32_t ip;
+ uint8_t port;
+ uint8_t flags;
+};
+
+struct task_master {
+ struct task_base base;
+ struct rte_ring *ctrl_rx_ring;
+ struct rte_ring **ctrl_tx_rings;
+ struct ip_table *internal_ip_table;
+ struct ip_table *external_ip_table;
+ struct rte_hash *external_ip_hash;
+ struct rte_hash *internal_ip_hash;
+ struct port_table internal_port_table[PROX_MAX_PORTS];
+};
+
+struct ip_port {
+ uint32_t ip;
+ uint8_t port;
+} __attribute__((packed));
+
+static inline uint8_t get_command(struct rte_mbuf *mbuf)
+{
+ return mbuf->udata64 & 0xFF;
+}
+static inline uint8_t get_task(struct rte_mbuf *mbuf)
+{
+ return (mbuf->udata64 >> 8) & 0xFF;
+}
+static inline uint8_t get_core(struct rte_mbuf *mbuf)
+{
+ return (mbuf->udata64 >> 16) & 0xFF;
+}
+static inline uint8_t get_port(struct rte_mbuf *mbuf)
+{
+ return mbuf->port;
+}
+static inline uint32_t get_ip(struct rte_mbuf *mbuf)
+{
+ return (mbuf->udata64 >> 32) & 0xFFFFFFFF;
+}
+
+void register_ip_to_ctrl_plane(struct task_base *tbase, uint32_t ip, uint8_t port_id, uint8_t core_id, uint8_t task_id)
+{
+ struct task_master *task = (struct task_master *)tbase;
+ struct ip_port key;
+ plogx_dbg("\tregistering IP %x.%x.%x.%x with port %d core %d and task %d\n", IP4(ip), port_id, core_id, task_id);
+
+ if (port_id >= PROX_MAX_PORTS) {
+ plog_err("Unable to register ip %x, port %d\n", ip, port_id);
+ return;
+ }
+
+ /* TODO - stoe multiple rings if multiple cores able to handle IP
+ Remove them when such cores are stopped and de-register IP
+ */
+ task->internal_port_table[port_id].ring = task->ctrl_tx_rings[core_id * MAX_TASKS_PER_CORE + task_id];
+ memcpy(&task->internal_port_table[port_id].mac, &prox_port_cfg[port_id].eth_addr, 6);
+ task->internal_port_table[port_id].ip = ip;
+
+ if (ip == RANDOM_IP) {
+ task->internal_port_table[port_id].flags |= HANDLE_RANDOM_IP_FLAG;
+ return;
+ }
+
+ key.ip = ip;
+ key.port = port_id;
+ int ret = rte_hash_add_key(task->internal_ip_hash, (const void *)&key);
+ if (unlikely(ret < 0)) {
+ plog_err("Unable to register ip %x\n", ip);
+ return;
+ }
+ memcpy(&task->internal_ip_table[ret].mac, &prox_port_cfg[port_id].eth_addr, 6);
+ task->internal_ip_table[ret].ring = task->ctrl_tx_rings[core_id * MAX_TASKS_PER_CORE + task_id];
+
+}
+
+static inline void handle_arp_reply(struct task_base *tbase, struct rte_mbuf *mbuf)
+{
+ struct task_master *task = (struct task_master *)tbase;
+ struct ether_hdr_arp *hdr_arp = rte_pktmbuf_mtod(mbuf, struct ether_hdr_arp *);
+ int i, ret;
+ uint32_t key = hdr_arp->arp.data.spa;
+ plogx_dbg("\tMaster handling ARP reply for ip %x\n", key);
+
+ ret = rte_hash_lookup(task->external_ip_hash, (const void *)&key);
+ if (unlikely(ret < 0)) {
+ // entry not found for this IP: we did not ask a request, delete the reply
+ tx_drop(mbuf);
+ } else {
+ // entry found for this IP
+ struct rte_ring *ring = task->external_ip_table[ret].ring;
+ memcpy(&hdr_arp->ether_hdr.d_addr.addr_bytes, &task->external_ip_table[ret].mac, 6);
+ tx_ring_ip(tbase, ring, UPDATE_FROM_CTRL, mbuf, key);
+ }
+}
+
+static inline void handle_arp_request(struct task_base *tbase, struct rte_mbuf *mbuf)
+{
+ struct task_master *task = (struct task_master *)tbase;
+ struct ether_hdr_arp *hdr_arp = rte_pktmbuf_mtod(mbuf, struct ether_hdr_arp *);
+ int i, ret;
+ uint8_t port = get_port(mbuf);
+
+ struct ip_port key;
+ key.ip = hdr_arp->arp.data.tpa;
+ key.port = port;
+ if (task->internal_port_table[port].flags & HANDLE_RANDOM_IP_FLAG) {
+ struct ether_addr mac;
+ plogx_dbg("\tMaster handling ARP request for ip %x on port %d which supports random ip\n", key.ip, key.port);
+ struct rte_ring *ring = task->internal_port_table[port].ring;
+ create_mac(hdr_arp, &mac);
+ mbuf->ol_flags &= ~(PKT_TX_IP_CKSUM|PKT_TX_UDP_CKSUM);
+ build_arp_reply(hdr_arp, &mac);
+ tx_ring(tbase, ring, ARP_REPLY_FROM_CTRL, mbuf);
+ return;
+ }
+
+ plogx_dbg("\tMaster handling ARP request for ip %x\n", key.ip);
+
+ ret = rte_hash_lookup(task->internal_ip_hash, (const void *)&key);
+ if (unlikely(ret < 0)) {
+ // entry not found for this IP.
+ plogx_dbg("Master ignoring ARP REQUEST received on un-registered IP %d.%d.%d.%d on port %d\n", IP4(hdr_arp->arp.data.tpa), port);
+ tx_drop(mbuf);
+ } else {
+ struct rte_ring *ring = task->internal_ip_table[ret].ring;
+ mbuf->ol_flags &= ~(PKT_TX_IP_CKSUM|PKT_TX_UDP_CKSUM);
+ build_arp_reply(hdr_arp, &task->internal_ip_table[ret].mac);
+ tx_ring(tbase, ring, ARP_REPLY_FROM_CTRL, mbuf);
+ }
+}
+
+static inline void handle_unknown_ip(struct task_base *tbase, struct rte_mbuf *mbuf)
+{
+ struct task_master *task = (struct task_master *)tbase;
+ struct ether_hdr_arp *hdr_arp = rte_pktmbuf_mtod(mbuf, struct ether_hdr_arp *);
+ uint8_t port = get_port(mbuf);
+ uint32_t ip_dst = get_ip(mbuf);
+ int ret1, ret2;
+
+ plogx_dbg("\tMaster handling unknown ip %x for port %d\n", ip_dst, port);
+ if (unlikely(port >= PROX_MAX_PORTS)) {
+ plogx_dbg("Port %d not found", port);
+ tx_drop(mbuf);
+ return;
+ }
+ uint32_t ip_src = task->internal_port_table[port].ip;
+ struct rte_ring *ring = task->ctrl_tx_rings[get_core(mbuf) * MAX_TASKS_PER_CORE + get_task(mbuf)];
+
+ if (ring == NULL) {
+ plogx_dbg("Port %d not registered", port);
+ tx_drop(mbuf);
+ return;
+ }
+
+ ret2 = rte_hash_add_key(task->external_ip_hash, (const void *)&ip_dst);
+ if (unlikely(ret2 < 0)) {
+ // entry not found for this IP: delete the reply
+ plogx_dbg("Unable to add IP %x in external_ip_hash\n", rte_be_to_cpu_32(hdr_arp->arp.data.tpa));
+ tx_drop(mbuf);
+ return;
+ }
+ task->external_ip_table[ret2].ring = ring;
+ memcpy(&task->external_ip_table[ret2].mac, &task->internal_port_table[port].mac, 6);
+
+ mbuf->ol_flags &= ~(PKT_TX_IP_CKSUM|PKT_TX_UDP_CKSUM);
+ build_arp_request(mbuf, &task->internal_port_table[port].mac, ip_dst, ip_src);
+ tx_ring(tbase, ring, ARP_REQ_FROM_CTRL, mbuf);
+}
+
+static inline void handle_message(struct task_base *tbase, struct rte_mbuf *mbuf, int ring_id)
+{
+ struct ether_hdr_arp *hdr_arp = rte_pktmbuf_mtod(mbuf, struct ether_hdr_arp *);
+ int command = get_command(mbuf);
+ uint32_t ip;
+ plogx_dbg("\tMaster received %s (%x) from mbuf %p\n", actions_string[command], command, mbuf);
+
+ switch(command) {
+ case ARP_TO_CTRL:
+ if (hdr_arp->ether_hdr.ether_type != ETYPE_ARP) {
+ tx_drop(mbuf);
+ plog_err("\tUnexpected message received: ARP_TO_CTRL with ether_type %x\n", hdr_arp->ether_hdr.ether_type);
+ return;
+ } else if (arp_is_gratuitous(hdr_arp)) {
+ plog_info("\tReceived gratuitous packet \n");
+ tx_drop(mbuf);
+ return;
+ } else if (memcmp(&hdr_arp->arp, &arp_reply, 8) == 0) {
+ uint32_t ip = hdr_arp->arp.data.spa;
+ handle_arp_reply(tbase, mbuf);
+ } else if (memcmp(&hdr_arp->arp, &arp_request, 8) == 0) {
+ handle_arp_request(tbase, mbuf);
+ } else {
+ plog_info("\tReceived unexpected ARP operation %d\n", hdr_arp->arp.oper);
+ tx_drop(mbuf);
+ return;
+ }
+ break;
+ case REQ_MAC_TO_CTRL:
+ handle_unknown_ip(tbase, mbuf);
+ break;
+ default:
+ plogx_dbg("\tMaster received unexpected message\n");
+ tx_drop(mbuf);
+ break;
+ }
+}
+
+void init_ctrl_plane(struct task_base *tbase)
+{
+ prox_cfg.flags |= DSF_CTRL_PLANE_ENABLED;
+ struct task_master *task = (struct task_master *)tbase;
+ int socket = rte_lcore_to_socket_id(prox_cfg.master);
+ uint32_t n_entries = MAX_ARP_ENTRIES * 4;
+ static char hash_name[30];
+ sprintf(hash_name, "A%03d_hash_arp_table", prox_cfg.master);
+ struct rte_hash_parameters hash_params = {
+ .name = hash_name,
+ .entries = n_entries,
+ .key_len = sizeof(uint32_t),
+ .hash_func = rte_hash_crc,
+ .hash_func_init_val = 0,
+ };
+ task->external_ip_hash = rte_hash_create(&hash_params);
+ PROX_PANIC(task->external_ip_hash == NULL, "Failed to set up external ip hash\n");
+ plog_info("\texternal ip hash table allocated, with %d entries of size %d\n", hash_params.entries, hash_params.key_len);
+ task->external_ip_table = (struct ip_table *)prox_zmalloc(n_entries * sizeof(struct ip_table), socket);
+ PROX_PANIC(task->external_ip_table == NULL, "Failed to allocate memory for %u entries in external ip table\n", n_entries);
+ plog_info("\texternal ip table, with %d entries of size %ld\n", n_entries, sizeof(struct ip_table));
+
+ hash_name[0]++;
+ hash_params.key_len = sizeof(struct ip_port);
+ task->internal_ip_hash = rte_hash_create(&hash_params);
+ PROX_PANIC(task->internal_ip_hash == NULL, "Failed to set up internal ip hash\n");
+ plog_info("\tinternal ip hash table allocated, with %d entries of size %d\n", hash_params.entries, hash_params.key_len);
+ task->internal_ip_table = (struct ip_table *)prox_zmalloc(n_entries * sizeof(struct ip_table), socket);
+ PROX_PANIC(task->internal_ip_table == NULL, "Failed to allocate memory for %u entries in internal ip table\n", n_entries);
+ plog_info("\tinternal ip table, with %d entries of size %ld\n", n_entries, sizeof(struct ip_table));
+}
+
+static int handle_ctrl_plane_f(struct task_base *tbase, __attribute__((unused)) struct rte_mbuf **mbuf, uint16_t n_pkts)
+{
+ int ring_id, j, ret = 0;
+ struct rte_mbuf *mbufs[MAX_RING_BURST];
+ struct task_master *task = (struct task_master *)tbase;
+
+ /* Handle_master works differently than other handle functions
+ It is not handled by a DPDK dataplane core
+ It is no thread_generic based, hence do not receive packets the same way
+ */
+
+ ret = ring_deq(task->ctrl_rx_ring, mbufs);
+ for (j = 0; j < ret; j++) {
+ handle_message(tbase, mbufs[j], ring_id);
+ }
+ return ret;
+}
+
+static void init_task_master(struct task_base *tbase, struct task_args *targs)
+{
+ if (prox_cfg.flags & DSF_CTRL_PLANE_ENABLED) {
+ struct task_master *task = (struct task_master *)tbase;
+
+ task->ctrl_rx_ring = targs->lconf->ctrl_rings_p[0];
+ task->ctrl_tx_rings = ctrl_rings;
+ init_ctrl_plane(tbase);
+ handle_ctrl_plane = handle_ctrl_plane_f;
+ }
+}
+
+static struct task_init task_init_master = {
+ .mode_str = "master",
+ .init = init_task_master,
+ .handle = NULL,
+ .flag_features = TASK_FEATURE_NEVER_DISCARDS,
+ .size = sizeof(struct task_master)
+};
+
+__attribute__((constructor)) static void reg_task_gen(void)
+{
+ reg_task(&task_init_master);
+}
diff --git a/VNFs/DPPD-PROX/handle_master.h b/VNFs/DPPD-PROX/handle_master.h
new file mode 100644
index 00000000..bc32182d
--- /dev/null
+++ b/VNFs/DPPD-PROX/handle_master.h
@@ -0,0 +1,43 @@
+/*
+// Copyright (c) 2010-2017 Intel Corporation
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+*/
+
+#include "task_base.h"
+#include "task_init.h"
+
+enum arp_actions {
+ UPDATE_FROM_CTRL,
+ ARP_REQ_FROM_CTRL,
+ ARP_REPLY_FROM_CTRL,
+ ARP_TO_CTRL,
+ REQ_MAC_TO_CTRL,
+ MAX_ACTIONS
+};
+
+#define HANDLE_RANDOM_IP_FLAG 1
+#define RANDOM_IP 0xffffffff
+
+const char *actions_string[MAX_ACTIONS];
+
+void init_ctrl_plane(struct task_base *tbase);
+
+int (*handle_ctrl_plane)(struct task_base *tbase, struct rte_mbuf **mbuf, uint16_t n_pkts);
+
+static inline void tx_drop(struct rte_mbuf *mbuf)
+{
+ rte_pktmbuf_free(mbuf);
+}
+
+void register_ip_to_ctrl_plane(struct task_base *task, uint32_t ip, uint8_t port_id, uint8_t core_id, uint8_t task_id);
diff --git a/VNFs/DPPD-PROX/handle_swap.c b/VNFs/DPPD-PROX/handle_swap.c
index 8e5a94ce..516d3f63 100644
--- a/VNFs/DPPD-PROX/handle_swap.c
+++ b/VNFs/DPPD-PROX/handle_swap.c
@@ -33,16 +33,8 @@ struct task_swap {
struct task_base base;
uint8_t src_dst_mac[12];
uint32_t runtime_flags;
- uint32_t tmp_ip;
- uint32_t ip;
};
-static void task_update_config(struct task_swap *task)
-{
- if (unlikely(task->ip != task->tmp_ip))
- task->ip = task->tmp_ip;
-}
-
static void write_src_and_dst_mac(struct task_swap *task, struct rte_mbuf *mbuf)
{
struct ether_hdr *hdr;
@@ -74,16 +66,12 @@ static void write_src_and_dst_mac(struct task_swap *task, struct rte_mbuf *mbuf)
static inline int handle_arp_request(struct task_swap *task, struct ether_hdr_arp *hdr_arp, struct ether_addr *s_addr, uint32_t ip)
{
if ((hdr_arp->arp.data.tpa == ip) || (ip == 0)) {
- prepare_arp_reply(hdr_arp, s_addr);
- memcpy(hdr_arp->ether_hdr.d_addr.addr_bytes, hdr_arp->ether_hdr.s_addr.addr_bytes, 6);
- memcpy(hdr_arp->ether_hdr.s_addr.addr_bytes, s_addr, 6);
+ build_arp_reply(hdr_arp, s_addr);
return 0;
} else if (task->runtime_flags & TASK_MULTIPLE_MAC) {
struct ether_addr tmp_s_addr;
create_mac(hdr_arp, &tmp_s_addr);
- prepare_arp_reply(hdr_arp, &tmp_s_addr);
- memcpy(hdr_arp->ether_hdr.d_addr.addr_bytes, hdr_arp->ether_hdr.s_addr.addr_bytes, 6);
- memcpy(hdr_arp->ether_hdr.s_addr.addr_bytes, &tmp_s_addr, 6);
+ build_arp_reply(hdr_arp, &tmp_s_addr);
return 0;
} else {
plogx_dbg("Received ARP on unexpected IP %x, expecting %x\n", rte_be_to_cpu_32(hdr_arp->arp.data.tpa), rte_be_to_cpu_32(ip));
@@ -127,20 +115,6 @@ static int handle_swap_bulk(struct task_base *tbase, struct rte_mbuf **mbufs, ui
for (uint16_t j = 0; j < n_pkts; ++j) {
hdr = rte_pktmbuf_mtod(mbufs[j], struct ether_hdr *);
switch (hdr->ether_type) {
- case ETYPE_ARP:
- hdr_arp = rte_pktmbuf_mtod(mbufs[j], struct ether_hdr_arp *);
- if (arp_is_gratuitous(hdr_arp)) {
- plog_info("Received gratuitous packet \n");
- out[j] = OUT_DISCARD;
- } else if (hdr_arp->arp.oper == ARP_REQUEST) {
- out[j] = handle_arp_request(task, hdr_arp, (struct ether_addr *)&task->src_dst_mac[6], task->ip);
- } else if (hdr_arp->arp.oper == ARP_REPLY) {
- out[j] = handle_arp_replies(task, hdr_arp);
- } else {
- plog_info("Received unexpected ARP operation %d\n", hdr_arp->arp.oper);
- out[j] = OUT_DISCARD;
- }
- continue;
case ETYPE_MPLSU:
mpls = (struct mpls_hdr *)(hdr + 1);
while (!(mpls->bytes & 0x00010000)) {
@@ -220,7 +194,6 @@ static int handle_swap_bulk(struct task_base *tbase, struct rte_mbuf **mbufs, ui
}
write_src_and_dst_mac(task, mbufs[j]);
}
- task_update_config(task);
return task->base.tx_pkt(&task->base, mbufs, n_pkts, out);
}
@@ -261,8 +234,6 @@ static void init_task_swap(struct task_base *tbase, struct task_args *targ)
}
}
task->runtime_flags = targ->flags;
- task->ip = rte_cpu_to_be_32(targ->local_ipv4);
- task->tmp_ip = task->ip;
}
static struct task_init task_init_swap = {
diff --git a/VNFs/DPPD-PROX/handle_swap.h b/VNFs/DPPD-PROX/handle_swap.h
index ef2fee04..b589051d 100644
--- a/VNFs/DPPD-PROX/handle_swap.h
+++ b/VNFs/DPPD-PROX/handle_swap.h
@@ -18,6 +18,5 @@
#define _HANDLE_SWAP_H_
struct task_base;
-void task_swap_set_local_ip(struct task_base *tbase, uint32_t ip);
#endif /* _HANDLE_SWAP_H_ */
diff --git a/VNFs/DPPD-PROX/input.c b/VNFs/DPPD-PROX/input.c
index bb956bcd..5eb5e4ce 100644
--- a/VNFs/DPPD-PROX/input.c
+++ b/VNFs/DPPD-PROX/input.c
@@ -74,6 +74,33 @@ static int tsc_diff_to_tv(uint64_t beg, uint64_t end, struct timeval *tv)
return 0;
}
+void input_proc(void)
+{
+ struct timeval tv;
+ fd_set in_fd;
+ int ret = 1;
+
+ tv.tv_sec = 0;
+ tv.tv_usec = 0;
+ while (ret != 0) {
+ FD_ZERO(&in_fd);
+
+ for (int i = 0; i < n_inputs; ++i) {
+ FD_SET(inputs[i]->fd, &in_fd);
+ }
+
+ ret = select(max_input_fd + 1, &in_fd, NULL, NULL, &tv);
+
+ if (ret > 0) {
+ for (int i = 0; i < n_inputs; ++i) {
+ if (FD_ISSET(inputs[i]->fd, &in_fd)) {
+ inputs[i]->proc_input(inputs[i]);
+ }
+ }
+ }
+ }
+}
+
void input_proc_until(uint64_t deadline)
{
struct timeval tv;
diff --git a/VNFs/DPPD-PROX/input.h b/VNFs/DPPD-PROX/input.h
index 06f6b653..51d94986 100644
--- a/VNFs/DPPD-PROX/input.h
+++ b/VNFs/DPPD-PROX/input.h
@@ -31,5 +31,6 @@ int reg_input(struct input *in);
void unreg_input(struct input *in);
void input_proc_until(uint64_t deadline);
+void input_proc(void);
#endif /* _INPUT_H_ */
diff --git a/VNFs/DPPD-PROX/lconf.c b/VNFs/DPPD-PROX/lconf.c
index 88d8f4f9..399c8a7d 100644
--- a/VNFs/DPPD-PROX/lconf.c
+++ b/VNFs/DPPD-PROX/lconf.c
@@ -223,10 +223,17 @@ int lconf_do_flags(struct lcore_cfg *lconf)
if (lconf->msg.type == LCONF_MSG_DUMP ||
lconf->msg.type == LCONF_MSG_DUMP_TX) {
t->aux->task_rt_dump.n_print_tx = lconf->msg.val;
- if (t->aux->tx_pkt_orig)
- t->tx_pkt = t->aux->tx_pkt_orig;
- t->aux->tx_pkt_orig = t->tx_pkt;
- t->tx_pkt = tx_pkt_dump;
+ if (t->tx_pkt == tx_pkt_l3) {
+ if (t->aux->tx_pkt_orig)
+ t->aux->tx_pkt_l2 = t->aux->tx_pkt_orig;
+ t->aux->tx_pkt_orig = t->aux->tx_pkt_l2;
+ t->aux->tx_pkt_l2 = tx_pkt_dump;
+ } else {
+ if (t->aux->tx_pkt_orig)
+ t->tx_pkt = t->aux->tx_pkt_orig;
+ t->aux->tx_pkt_orig = t->tx_pkt;
+ t->tx_pkt = tx_pkt_dump;
+ }
}
}
break;
@@ -238,16 +245,30 @@ int lconf_do_flags(struct lcore_cfg *lconf)
if (task_base_get_original_rx_pkt_function(t) != rx_pkt_dummy) {
task_base_add_rx_pkt_function(t, rx_pkt_trace);
- if (t->aux->tx_pkt_orig)
- t->tx_pkt = t->aux->tx_pkt_orig;
- t->aux->tx_pkt_orig = t->tx_pkt;
- t->tx_pkt = tx_pkt_trace;
+ if (t->tx_pkt == tx_pkt_l3) {
+ if (t->aux->tx_pkt_orig)
+ t->aux->tx_pkt_l2 = t->aux->tx_pkt_orig;
+ t->aux->tx_pkt_orig = t->aux->tx_pkt_l2;
+ t->aux->tx_pkt_l2 = tx_pkt_trace;
+ } else {
+ if (t->aux->tx_pkt_orig)
+ t->tx_pkt = t->aux->tx_pkt_orig;
+ t->aux->tx_pkt_orig = t->tx_pkt;
+ t->tx_pkt = tx_pkt_trace;
+ }
} else {
t->aux->task_rt_dump.n_print_tx = lconf->msg.val;
- if (t->aux->tx_pkt_orig)
- t->tx_pkt = t->aux->tx_pkt_orig;
- t->aux->tx_pkt_orig = t->tx_pkt;
- t->tx_pkt = tx_pkt_dump;
+ if (t->tx_pkt == tx_pkt_l3) {
+ if (t->aux->tx_pkt_orig)
+ t->aux->tx_pkt_l2 = t->aux->tx_pkt_orig;
+ t->aux->tx_pkt_orig = t->aux->tx_pkt_l2;
+ t->aux->tx_pkt_l2 = tx_pkt_dump;
+ } else {
+ if (t->aux->tx_pkt_orig)
+ t->tx_pkt = t->aux->tx_pkt_orig;
+ t->aux->tx_pkt_orig = t->tx_pkt;
+ t->tx_pkt = tx_pkt_dump;
+ }
}
}
break;
@@ -263,8 +284,13 @@ int lconf_do_flags(struct lcore_cfg *lconf)
for (uint8_t task_id = 0; task_id < lconf->n_tasks_all; ++task_id) {
t = lconf->tasks_all[task_id];
- t->aux->tx_pkt_orig = t->tx_pkt;
- t->tx_pkt = tx_pkt_distr;
+ if (t->tx_pkt == tx_pkt_l3) {
+ t->aux->tx_pkt_orig = t->aux->tx_pkt_l2;
+ t->aux->tx_pkt_l2 = tx_pkt_distr;
+ } else {
+ t->aux->tx_pkt_orig = t->tx_pkt;
+ t->tx_pkt = tx_pkt_distr;
+ }
memset(t->aux->tx_bucket, 0, sizeof(t->aux->tx_bucket));
lconf->flags |= LCONF_FLAG_TX_DISTR_ACTIVE;
}
@@ -280,8 +306,13 @@ int lconf_do_flags(struct lcore_cfg *lconf)
for (uint8_t task_id = 0; task_id < lconf->n_tasks_all; ++task_id) {
t = lconf->tasks_all[task_id];
if (t->aux->tx_pkt_orig) {
- t->tx_pkt = t->aux->tx_pkt_orig;
- t->aux->tx_pkt_orig = NULL;
+ if (t->tx_pkt == tx_pkt_l3) {
+ t->tx_pkt = t->aux->tx_pkt_orig;
+ t->aux->tx_pkt_orig = NULL;
+ } else {
+ t->aux->tx_pkt_l2 = t->aux->tx_pkt_orig;
+ t->aux->tx_pkt_orig = NULL;
+ }
lconf->flags &= ~LCONF_FLAG_TX_DISTR_ACTIVE;
}
}
@@ -318,8 +349,13 @@ int lconf_do_flags(struct lcore_cfg *lconf)
for (uint8_t task_id = 0; task_id < lconf->n_tasks_all; ++task_id) {
t = lconf->tasks_all[task_id];
- t->aux->tx_pkt_orig = t->tx_pkt;
- t->tx_pkt = tx_pkt_bw;
+ if (t->tx_pkt == tx_pkt_l3) {
+ t->aux->tx_pkt_orig = t->aux->tx_pkt_l2;
+ t->aux->tx_pkt_l2 = tx_pkt_bw;
+ } else {
+ t->aux->tx_pkt_orig = t->tx_pkt;
+ t->tx_pkt = tx_pkt_bw;
+ }
lconf->flags |= LCONF_FLAG_TX_BW_ACTIVE;
}
break;
@@ -327,8 +363,13 @@ int lconf_do_flags(struct lcore_cfg *lconf)
for (uint8_t task_id = 0; task_id < lconf->n_tasks_all; ++task_id) {
t = lconf->tasks_all[task_id];
if (t->aux->tx_pkt_orig) {
- t->tx_pkt = t->aux->tx_pkt_orig;
- t->aux->tx_pkt_orig = NULL;
+ if (t->tx_pkt == tx_pkt_l3) {
+ t->aux->tx_pkt_l2 = t->aux->tx_pkt_orig;
+ t->aux->tx_pkt_orig = NULL;
+ } else {
+ t->tx_pkt = t->aux->tx_pkt_orig;
+ t->aux->tx_pkt_orig = NULL;
+ }
lconf->flags &= ~LCONF_FLAG_TX_BW_ACTIVE;
}
}
diff --git a/VNFs/DPPD-PROX/log.c b/VNFs/DPPD-PROX/log.c
index cd8ee002..7049a5e3 100644
--- a/VNFs/DPPD-PROX/log.c
+++ b/VNFs/DPPD-PROX/log.c
@@ -26,6 +26,7 @@
#include "log.h"
#include "display.h"
+#include "defaults.h"
#include "etypes.h"
#include "prox_cfg.h"
@@ -140,7 +141,6 @@ static const char* lvl_to_str(int lvl, int always)
}
}
-#define DUMP_PKT_LEN 128
static int dump_pkt(char *dst, size_t dst_size, const struct rte_mbuf *mbuf)
{
const struct ether_hdr *peth = rte_pktmbuf_mtod(mbuf, const struct ether_hdr *);
diff --git a/VNFs/DPPD-PROX/main.c b/VNFs/DPPD-PROX/main.c
index 28533c78..1c4dced9 100644
--- a/VNFs/DPPD-PROX/main.c
+++ b/VNFs/DPPD-PROX/main.c
@@ -46,6 +46,7 @@
#include "thread_generic.h"
#include "thread_pipeline.h"
#include "cqm.h"
+#include "handle_master.h"
#if RTE_VERSION < RTE_VERSION_NUM(1,8,0,0)
#define RTE_CACHE_LINE_SIZE CACHE_LINE_SIZE
@@ -111,12 +112,27 @@ static void check_mixed_normal_pipeline(void)
}
}
-static void check_missing_rx(void)
+static void check_zero_rx(void)
{
struct lcore_cfg *lconf = NULL;
struct task_args *targ;
while (core_targ_next(&lconf, &targ, 0) == 0) {
+ if (targ->nb_rxports != 0) {
+ PROX_PANIC(task_init_flag_set(targ->task_init, TASK_FEATURE_NO_RX),
+ "\tCore %u task %u: rx_ports configured while mode %s does not use it\n", lconf->id, targ->id, targ->task_init->mode_str);
+ }
+ }
+}
+
+static void check_missing_rx(void)
+{
+ struct lcore_cfg *lconf = NULL, *rx_lconf = NULL;
+ struct task_args *targ, *rx_targ = NULL;
+ struct prox_port_cfg *port;
+ uint8_t port_id, rx_port_id, ok;
+
+ 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,
"Configuration Error - Core %u task %u Receiving from ring, but nobody xmitting to this ring\n", lconf->id, targ->id);
if (targ->nb_rxports == 0 && targ->nb_rxrings == 0) {
@@ -124,11 +140,39 @@ static void check_missing_rx(void)
"\tCore %u task %u: no rx_ports and no rx_rings configured while required by mode %s\n", lconf->id, targ->id, targ->task_init->mode_str);
}
}
+
+ lconf = NULL;
+ while (core_targ_next(&lconf, &targ, 0) == 0) {
+ if (strcmp(targ->task_init->sub_mode_str, "l3") != 0)
+ continue;
+ port = find_reachable_port(targ);
+ if (port == NULL)
+ continue;
+ port_id = port - prox_port_cfg;
+ 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);
+ 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->task_init->flag_features & TASK_FEATURE_L3)){
+ 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);
+ 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);
+ }
}
static void check_cfg_consistent(void)
{
check_missing_rx();
+ check_zero_rx();
check_mixed_normal_pipeline();
}
@@ -280,11 +324,6 @@ static const char *gen_ring_name(void)
return retval;
}
-static int task_is_master(struct task_args *targ)
-{
- return !targ->lconf;
-}
-
struct ring_init_stats {
uint32_t n_pkt_rings;
uint32_t n_ctrl_rings;
@@ -332,7 +371,7 @@ static struct rte_ring *get_existing_ring(uint32_t lcore_id, uint32_t task_id)
return lconf->targs[task_id].rx_rings[0];
}
-static void init_ring_between_tasks(struct lcore_cfg *lconf, struct task_args *starg,
+static struct rte_ring *init_ring_between_tasks(struct lcore_cfg *lconf, struct task_args *starg,
const struct core_task ct, uint8_t ring_idx, int idx,
struct ring_init_stats *ris)
{
@@ -377,13 +416,15 @@ static void init_ring_between_tasks(struct lcore_cfg *lconf, struct task_args *s
*dring = ring;
if (lconf->id == prox_cfg.master) {
ctrl_rings[ct.core*MAX_TASKS_PER_CORE + ct.task] = ring;
+ } else if (ct.core == prox_cfg.master) {
+ starg->ctrl_plane_ring = ring;
}
plog_info("\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++;
- return;
+ return ring;
}
dtarg = &lworker->targs[ct.task];
@@ -393,7 +434,7 @@ static void init_ring_between_tasks(struct lcore_cfg *lconf, struct task_args *s
/* If all the following conditions are met, the ring can be
optimized away. */
- if (!task_is_master(starg) && starg->lconf->id == dtarg->lconf->id &&
+ if (!task_is_master(starg) && !task_is_master(dtarg) && starg->lconf->id == dtarg->lconf->id &&
starg->nb_txrings == 1 && idx == 0 && dtarg->task &&
dtarg->tot_rxrings == 1 && starg->task == dtarg->task - 1) {
plog_info("\t\tOptimizing away ring on core %u from task %u to task %u\n",
@@ -405,7 +446,7 @@ static void init_ring_between_tasks(struct lcore_cfg *lconf, struct task_args *s
dtarg->tx_opt_ring_task = starg;
ris->n_opt_rings++;
++dtarg->nb_rxrings;
- return;
+ return NULL;
}
int ring_created = 1;
@@ -447,6 +488,7 @@ static void init_ring_between_tasks(struct lcore_cfg *lconf, struct task_args *s
lconf->id, starg->id, ring_idx, ct.core, ct.task, dtarg->nb_rxrings, ring, ring->name,
dtarg->nb_slave_threads);
++ris->n_pkt_rings;
+ return ring;
}
static void init_rings(void)
@@ -476,6 +518,22 @@ static void init_rings(void)
ris.n_pkt_rings,
ris.n_ctrl_rings,
ris.n_opt_rings);
+
+ lconf = NULL;
+ struct prox_port_cfg *port;
+ while (core_targ_next(&lconf, &starg, 1) == 0) {
+ if ((starg->task_init) && (starg->task_init->flag_features & TASK_FEATURE_L3)) {
+ struct core_task ct;
+ ct.core = prox_cfg.master;
+ ct.task = 0;
+ ct.type = CTRL_TYPE_PKT;
+ struct rte_ring *rx_ring = init_ring_between_tasks(lconf, starg, ct, 0, 0, &ris);
+
+ 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);
+ }
+ }
}
static void shuffle_mempool(struct rte_mempool* mempool, uint32_t nb_mbuf)
@@ -691,7 +749,7 @@ static void set_task_lconf(void)
struct lcore_cfg *lconf;
uint32_t lcore_id = -1;
- while(prox_core_next(&lcore_id, 0) == 0) {
+ while(prox_core_next(&lcore_id, 1) == 0) {
lconf = &lcore_cfg[lcore_id];
for (uint8_t task_id = 0; task_id < lconf->n_tasks_all; ++task_id) {
lconf->targs[task_id].lconf = lconf;
@@ -733,11 +791,30 @@ static void setup_all_task_structs(void)
{
struct lcore_cfg *lconf;
uint32_t lcore_id = -1;
+ struct task_base *tmaster = NULL;
- while(prox_core_next(&lcore_id, 0) == 0) {
+ while(prox_core_next(&lcore_id, 1) == 0) {
lconf = &lcore_cfg[lcore_id];
for (uint8_t task_id = 0; task_id < lconf->n_tasks_all; ++task_id) {
- lconf->tasks_all[task_id] = init_task_struct(&lconf->targs[task_id]);
+ if (task_is_master(&lconf->targs[task_id])) {
+ plog_info("\tInitializing MASTER struct for core %d task %d\n", lcore_id, task_id);
+ lconf->tasks_all[task_id] = init_task_struct(&lconf->targs[task_id]);
+ tmaster = lconf->tasks_all[task_id];
+ }
+ }
+ }
+ PROX_PANIC(tmaster == NULL, "Can't initialize master task\n");
+ lcore_id = -1;
+
+ 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);
+ 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);
+ lconf->targs[task_id].tmaster = tmaster;
+ lconf->tasks_all[task_id] = init_task_struct(&lconf->targs[task_id]);
+ }
}
}
}
diff --git a/VNFs/DPPD-PROX/msr.c b/VNFs/DPPD-PROX/msr.c
index 194d4c75..8aa1e3a3 100644
--- a/VNFs/DPPD-PROX/msr.c
+++ b/VNFs/DPPD-PROX/msr.c
@@ -75,6 +75,6 @@ int msr_write(int lcore_id, uint64_t val, off_t offset)
if (sizeof(uint64_t) != pwrite(msr_fd[lcore_id], &val, sizeof(uint64_t), offset)) {
return -1;
}
- plog_dbg("\t\tmsr_write(core %d, offset %x, val %lx)\n", lcore_id, (int)offset, val);
+ // plogx_dbg("\t\tmsr_write(core %d, offset %x, val %lx)\n", lcore_id, (int)offset, val);
return 0;
}
diff --git a/VNFs/DPPD-PROX/packet_utils.c b/VNFs/DPPD-PROX/packet_utils.c
new file mode 100644
index 00000000..c22183be
--- /dev/null
+++ b/VNFs/DPPD-PROX/packet_utils.c
@@ -0,0 +1,274 @@
+/*
+// Copyright (c) 2010-2017 Intel Corporation
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+*/
+
+#include <rte_lcore.h>
+#include <rte_hash.h>
+#include <rte_hash_crc.h>
+#include "task_base.h"
+#include "lconf.h"
+#include "prefetch.h"
+#include "log.h"
+#include "handle_master.h"
+#include "prox_port_cfg.h"
+
+#define IP4(x) x & 0xff, (x >> 8) & 0xff, (x >> 16) & 0xff, x >> 24
+
+static inline int find_ip(struct ether_hdr_arp *pkt, uint16_t len, uint32_t *ip_dst)
+{
+ struct vlan_hdr *vlan_hdr;
+ struct ether_hdr *eth_hdr = (struct ether_hdr*)pkt;
+ struct ipv4_hdr *ip;
+ uint16_t ether_type = eth_hdr->ether_type;
+ uint16_t l2_len = sizeof(struct ether_hdr);
+
+ // Unstack VLAN tags
+ while (((ether_type == ETYPE_8021ad) || (ether_type == ETYPE_VLAN)) && (l2_len + sizeof(struct vlan_hdr) < len)) {
+ vlan_hdr = (struct vlan_hdr *)((uint8_t *)pkt + l2_len);
+ l2_len +=4;
+ ether_type = vlan_hdr->eth_proto;
+ }
+
+ switch (ether_type) {
+ case ETYPE_MPLSU:
+ case ETYPE_MPLSM:
+ // In case of MPLS, next hop MAC is based on MPLS, not destination IP
+ l2_len = 0;
+ break;
+ case ETYPE_IPv4:
+ break;
+ case ETYPE_EoGRE:
+ case ETYPE_ARP:
+ case ETYPE_IPv6:
+ l2_len = 0;
+ break;
+ default:
+ l2_len = 0;
+ plog_warn("Unsupported packet type %x - CRC might be wrong\n", ether_type);
+ break;
+ }
+
+ if (l2_len && (l2_len + sizeof(struct ipv4_hdr) <= len)) {
+ struct ipv4_hdr *ip = (struct ipv4_hdr *)((uint8_t *)pkt + l2_len);
+ // TODO: implement LPM => replace ip_dst by next hop IP DST
+ *ip_dst = ip->dst_addr;
+ return 0;
+ }
+ return -1;
+}
+
+int write_dst_mac(struct task_base *tbase, struct rte_mbuf *mbuf, uint32_t *ip_dst)
+{
+ const uint64_t hz = rte_get_tsc_hz();
+ struct ether_hdr_arp *packet = rte_pktmbuf_mtod(mbuf, struct ether_hdr_arp *);
+ struct ether_addr *mac = &packet->ether_hdr.d_addr;
+
+ uint64_t tsc = rte_rdtsc();
+ struct l3_base *l3 = &(tbase->l3);
+ if (l3->gw.ip) {
+ if (likely((l3->flags & FLAG_DST_MAC_KNOWN) && (tsc < l3->gw.arp_update_time) && (tsc < l3->gw.arp_timeout))) {
+ memcpy(mac, &l3->gw.mac, sizeof(struct ether_addr));
+ return 0;
+ } else if (tsc > l3->gw.arp_update_time) {
+ // long time since we have sent an arp, send arp
+ l3->gw.arp_update_time = tsc + hz;
+ *ip_dst = l3->gw.ip;
+ return -1;
+ }
+ return -2;
+ }
+
+ uint16_t len = rte_pktmbuf_pkt_len(mbuf);
+ if (find_ip(packet, len, ip_dst) != 0) {
+ return 0;
+ }
+ if (likely(l3->n_pkts < 4)) {
+ for (unsigned int idx = 0; idx < l3->n_pkts; idx++) {
+ if (*ip_dst == l3->optimized_arp_table[idx].ip) {
+ if ((tsc < l3->optimized_arp_table[idx].arp_update_time) && (tsc < l3->optimized_arp_table[idx].arp_timeout)) {
+ memcpy(mac, &l3->optimized_arp_table[idx].mac, sizeof(struct ether_addr));
+ return 0;
+ } else if (tsc > l3->optimized_arp_table[idx].arp_update_time) {
+ l3->optimized_arp_table[idx].arp_update_time = tsc + hz;
+ return -1;
+ } else {
+ return -2;
+ }
+ }
+ }
+ l3->optimized_arp_table[l3->n_pkts].ip = *ip_dst;
+ l3->optimized_arp_table[l3->n_pkts].arp_update_time = tsc + hz;
+ l3->n_pkts++;
+
+ if (l3->n_pkts < 4)
+ return -1;
+
+ // We have ** many ** IP addresses; lets use hash table instead
+ for (uint32_t idx = 0; idx < l3->n_pkts; idx++) {
+ uint32_t ip = l3->optimized_arp_table[idx].ip;
+ int ret = rte_hash_add_key(l3->ip_hash, (const void *)&ip);
+ if (ret < 0) {
+ plogx_info("Unable add ip %d.%d.%d.%d in mac_hash\n", IP4(ip));
+ } else {
+ memcpy(&l3->arp_table[ret], &l3->optimized_arp_table[idx], sizeof(struct arp_table));
+ }
+ }
+ return -1;
+ } else {
+ // Find mac in lookup table. Send ARP if not found
+ int ret = rte_hash_lookup(l3->ip_hash, (const void *)ip_dst);
+ if (unlikely(ret < 0)) {
+ int ret = rte_hash_add_key(l3->ip_hash, (const void *)ip_dst);
+ if (ret < 0) {
+ plogx_info("Unable add ip %d.%d.%d.%d in mac_hash\n", IP4(*ip_dst));
+ return -2;
+ } else {
+ l3->arp_table[ret].ip = *ip_dst;
+ l3->arp_table[ret].arp_update_time = tsc + hz;
+ }
+ return -1;
+ } else {
+ if ((tsc < l3->arp_table[ret].arp_update_time) && (tsc < l3->arp_table[ret].arp_timeout)) {
+ memcpy(mac, &l3->arp_table[ret].mac, sizeof(struct ether_addr));
+ return 0;
+ } else if (tsc > l3->arp_table[ret].arp_update_time) {
+ l3->arp_table[ret].arp_update_time = tsc + hz;
+ return -1;
+ } else {
+ return -2;
+ }
+ }
+ }
+ return 0;
+}
+
+void task_init_l3(struct task_base *tbase, struct task_args *targ)
+{
+ static char hash_name[30];
+ uint32_t n_entries = MAX_ARP_ENTRIES * 4;
+ const int socket_id = rte_lcore_to_socket_id(targ->lconf->id);
+ sprintf(hash_name, "A%03d_mac_table", targ->lconf->id);
+
+ hash_name[0]++;
+
+ struct rte_hash_parameters hash_params = {
+ .name = hash_name,
+ .entries = n_entries,
+ .key_len = sizeof(uint32_t),
+ .hash_func = rte_hash_crc,
+ .hash_func_init_val = 0,
+ };
+ tbase->l3.ip_hash = rte_hash_create(&hash_params);
+ PROX_PANIC(tbase->l3.ip_hash == NULL, "Failed to set up ip hash table\n");
+
+ tbase->l3.arp_table = (struct arp_table *)prox_zmalloc(n_entries * sizeof(struct arp_table), socket_id);
+ PROX_PANIC(tbase->l3.arp_table == NULL, "Failed to allocate memory for %u entries in arp table\n", n_entries);
+ plog_info("\tarp table, with %d entries of size %ld\n", n_entries, sizeof(struct l3_base));
+
+ targ->lconf->ctrl_func_p[targ->task] = handle_ctrl_plane_pkts;
+ targ->lconf->ctrl_timeout = freq_to_tsc(targ->ctrl_freq);
+ tbase->l3.gw.ip = rte_cpu_to_be_32(targ->gateway_ipv4);
+ tbase->flags |= TASK_L3;
+ tbase->l3.core_id = targ->lconf->id;
+ tbase->l3.task_id = targ->id;
+ tbase->l3.tmaster = targ->tmaster;
+}
+
+void task_start_l3(struct task_base *tbase, struct task_args *targ)
+{
+ struct prox_port_cfg *port = find_reachable_port(targ);
+ if (port) {
+ tbase->l3.reachable_port_id = port - prox_port_cfg;
+ if (targ->local_ipv4) {
+ tbase->local_ipv4 = rte_be_to_cpu_32(targ->local_ipv4);
+ register_ip_to_ctrl_plane(tbase->l3.tmaster, tbase->local_ipv4, tbase->l3.reachable_port_id, targ->lconf->id, targ->id);
+ }
+ }
+}
+
+void task_set_gateway_ip(struct task_base *tbase, uint32_t ip)
+{
+ tbase->l3.gw.ip = ip;
+ tbase->flags &= ~FLAG_DST_MAC_KNOWN;
+}
+
+void task_set_local_ip(struct task_base *tbase, uint32_t ip)
+{
+ tbase->local_ipv4 = ip;
+}
+
+void handle_ctrl_plane_pkts(struct task_base *tbase, struct rte_mbuf **mbufs, uint16_t n_pkts)
+{
+ uint8_t out[1];
+ const uint64_t hz = rte_get_tsc_hz();
+ uint32_t ip, ip_dst, idx;
+ int j;
+ uint16_t command;
+ struct ether_hdr_arp *hdr;
+ struct l3_base *l3 = &tbase->l3;
+ uint64_t tsc= rte_rdtsc();
+
+ for (j = 0; j < n_pkts; ++j) {
+ PREFETCH0(mbufs[j]);
+ }
+ for (j = 0; j < n_pkts; ++j) {
+ PREFETCH0(rte_pktmbuf_mtod(mbufs[j], void *));
+ }
+
+ for (j = 0; j < n_pkts; ++j) {
+ out[0] = OUT_HANDLED;
+ command = mbufs[j]->udata64 & 0xFFFF;
+ plogx_dbg("\tReceived %s mbuf %p\n", actions_string[command], mbufs[j]);
+ switch(command) {
+ case UPDATE_FROM_CTRL:
+ hdr = rte_pktmbuf_mtod(mbufs[j], struct ether_hdr_arp *);
+ ip = (mbufs[j]->udata64 >> 32) & 0xFFFFFFFF;
+
+ if (ip == l3->gw.ip) {
+ // MAC address of the gateway
+ memcpy(&l3->gw.mac, &hdr->arp.data.sha, 6);
+ l3->flags |= FLAG_DST_MAC_KNOWN;
+ l3->gw.arp_timeout = tsc + 30 * hz;
+ } else if (l3->n_pkts < 4) {
+ // Few packets tracked - should be faster to loop through them thean using a hash table
+ for (idx = 0; idx < l3->n_pkts; idx++) {
+ ip_dst = l3->optimized_arp_table[idx].ip;
+ if (ip_dst == ip)
+ break;
+ }
+ if (idx < l3->n_pkts) {
+ // IP not found; this is a reply while we never asked for the request!
+ memcpy(&l3->optimized_arp_table[idx].mac, &(hdr->arp.data.sha), sizeof(struct ether_addr));
+ l3->optimized_arp_table[idx].arp_timeout = tsc + 30 * hz;
+ }
+ } else {
+ int ret = rte_hash_add_key(l3->ip_hash, (const void *)&ip);
+ if (ret < 0) {
+ plogx_info("Unable add ip %d.%d.%d.%d in mac_hash\n", IP4(ip));
+ } else {
+ memcpy(&l3->arp_table[ret].mac, &(hdr->arp.data.sha), sizeof(struct ether_addr));
+ l3->arp_table[ret].arp_timeout = tsc + 30 * hz;
+ }
+ }
+ tx_drop(mbufs[j]);
+ break;
+ case ARP_REPLY_FROM_CTRL:
+ case ARP_REQ_FROM_CTRL:
+ out[0] = 0;
+ tbase->aux->tx_pkt_l2(tbase, &mbufs[j], 1, out);
+ break;
+ }
+ }
+}
diff --git a/VNFs/DPPD-PROX/packet_utils.h b/VNFs/DPPD-PROX/packet_utils.h
new file mode 100644
index 00000000..0017a89e
--- /dev/null
+++ b/VNFs/DPPD-PROX/packet_utils.h
@@ -0,0 +1,54 @@
+/*
+// Copyright (c) 2010-2017 Intel Corporation
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+*/
+
+#include "arp.h"
+#include "quit.h"
+#include "prox_malloc.h"
+#include "defaults.h"
+#include "prox_cfg.h"
+#include "etypes.h"
+
+#define FLAG_DST_MAC_KNOWN 1
+#define MAX_ARP_ENTRIES 65536
+
+struct task_base;
+struct task_args;
+struct arp_table {
+ uint64_t arp_update_time;
+ uint64_t arp_timeout;
+ uint32_t ip;
+ struct ether_addr mac;
+};
+struct l3_base {
+ struct rte_ring *ctrl_plane_ring;
+ struct task_base *tmaster;
+ uint32_t flags;
+ uint32_t n_pkts;
+ uint8_t reachable_port_id;
+ uint8_t core_id;
+ uint8_t task_id;
+ struct arp_table gw;
+ struct arp_table optimized_arp_table[4];
+ struct rte_hash *ip_hash;
+ struct arp_table *arp_table;
+};
+
+void task_init_l3(struct task_base *tbase, struct task_args *targ);
+void task_start_l3(struct task_base *tbase, struct task_args *targ);
+int write_dst_mac(struct task_base *tbase, struct rte_mbuf *mbuf, uint32_t *ip_dst);
+void task_set_gateway_ip(struct task_base *tbase, uint32_t ip);
+void task_set_local_ip(struct task_base *tbase, uint32_t ip);
+void handle_ctrl_plane_pkts(struct task_base *tbase, struct rte_mbuf **mbufs, uint16_t n_pkts);
diff --git a/VNFs/DPPD-PROX/prox_args.c b/VNFs/DPPD-PROX/prox_args.c
index 2703c228..fd8ea524 100644
--- a/VNFs/DPPD-PROX/prox_args.c
+++ b/VNFs/DPPD-PROX/prox_args.c
@@ -1063,6 +1063,15 @@ static int get_core_cfg(unsigned sindex, char *str, void *data)
set_errf("Master core can only have one task\n");
return -1;
}
+ // Initialize number of tasks to 1 for master, even if no task specified
+ lconf->n_tasks_all = 1;
+ lconf->active_task = 0;
+ lconf->targs[lconf->active_task].task = 0;
+ struct task_init* task_init = to_task_init(mode, "");
+ if (task_init) {
+ targ->mode = task_init->mode;
+ }
+ targ->task_init = task_init;
return 0;
}
@@ -1231,8 +1240,20 @@ static int get_core_cfg(unsigned sindex, char *str, void *data)
targ->task_init = to_task_init(mode_str, sub_mode_str);
if (!targ->task_init) {
- set_errf("sub mode %s not supported for mode %s", sub_mode_str, mode_str);
- return -1;
+ if (strcmp(sub_mode_str, "l3") != 0) {
+ set_errf("sub mode %s not supported for mode %s", sub_mode_str, mode_str);
+ return -1;
+ }
+ targ->task_init = to_task_init(mode_str, "");
+ if (!targ->task_init) {
+ set_errf("sub mode %s not supported for mode %s", sub_mode_str, mode_str);
+ return -1;
+ }
+ }
+ if (strcmp(sub_mode_str, "l3") == 0) {
+ prox_cfg.flags |= DSF_CTRL_PLANE_ENABLED;
+ targ->task_init->flag_features |= TASK_FEATURE_L3;
+ strcpy(targ->task_init->sub_mode_str, "l3");
}
return 0;
}
@@ -1282,9 +1303,6 @@ static int get_core_cfg(unsigned sindex, char *str, void *data)
if (STR_EQ(str, "gateway ipv4")) { /* Gateway IP address used when generating */
return parse_ip(&targ->gateway_ipv4, pkey);
}
- if (STR_EQ(str, "number of ip")) { /* Gateway IP address used when generating */
- return parse_int(&targ->number_gen_ip, pkey);
- }
if (STR_EQ(str, "local ipv4")) { /* source IP address to be used for packets */
return parse_ip(&targ->local_ipv4, pkey);
}
diff --git a/VNFs/DPPD-PROX/prox_cfg.h b/VNFs/DPPD-PROX/prox_cfg.h
index a7d0e7ea..ed54ecc5 100644
--- a/VNFs/DPPD-PROX/prox_cfg.h
+++ b/VNFs/DPPD-PROX/prox_cfg.h
@@ -40,6 +40,7 @@
#define DSF_DISABLE_CMT 0x00002000 /* CMT disabled */
#define DSF_LIST_TASK_MODES 0x00004000 /* list supported task modes and exit */
#define DSF_ENABLE_BYPASS 0x00008000 /* Use Multi Producer rings to enable ring bypass */
+#define DSF_CTRL_PLANE_ENABLED 0x00010000 /* ctrl plane enabled */
#define MAX_PATH_LEN 1024
diff --git a/VNFs/DPPD-PROX/prox_cksum.c b/VNFs/DPPD-PROX/prox_cksum.c
index b69c06f6..9a05097e 100644
--- a/VNFs/DPPD-PROX/prox_cksum.c
+++ b/VNFs/DPPD-PROX/prox_cksum.c
@@ -83,26 +83,23 @@ void prox_ip_udp_cksum(struct rte_mbuf *mbuf, struct ipv4_hdr *pip, uint16_t l2_
{
prox_ip_cksum(mbuf, pip, l2_len, l3_len, cksum_offload & IPV4_CKSUM);
-#ifndef SOFT_CRC
- if (cksum_offload & UDP_CKSUM)
- mbuf->ol_flags |= PKT_TX_UDP_CKSUM;
-#endif
-
uint32_t l4_len = rte_bswap16(pip->total_length) - l3_len;
if (pip->next_proto_id == IPPROTO_UDP) {
struct udp_hdr *udp = (struct udp_hdr *)(((uint8_t*)pip) + l3_len);
#ifndef SOFT_CRC
- if (cksum_offload & UDP_CKSUM)
+ if (cksum_offload & UDP_CKSUM) {
+ mbuf->ol_flags |= PKT_TX_UDP_CKSUM;
prox_write_udp_pseudo_hdr(udp, l4_len, pip->src_addr, pip->dst_addr);
- else
+ } else
#endif
prox_udp_cksum_sw(udp, l4_len, pip->src_addr, pip->dst_addr);
} else if (pip->next_proto_id == IPPROTO_TCP) {
struct tcp_hdr *tcp = (struct tcp_hdr *)(((uint8_t*)pip) + l3_len);
#ifndef SOFT_CRC
- if (cksum_offload & UDP_CKSUM)
+ if (cksum_offload & UDP_CKSUM) {
prox_write_tcp_pseudo_hdr(tcp, l4_len, pip->src_addr, pip->dst_addr);
- else
+ mbuf->ol_flags |= PKT_TX_UDP_CKSUM;
+ } else
#endif
prox_tcp_cksum_sw(tcp, l4_len, pip->src_addr, pip->dst_addr);
}
diff --git a/VNFs/DPPD-PROX/prox_port_cfg.c b/VNFs/DPPD-PROX/prox_port_cfg.c
index 7e0c2c70..d9ce82d2 100644
--- a/VNFs/DPPD-PROX/prox_port_cfg.c
+++ b/VNFs/DPPD-PROX/prox_port_cfg.c
@@ -55,15 +55,26 @@ int prox_last_port_active(void)
return ret;
}
+#if RTE_VERSION >= RTE_VERSION_NUM(17,8,0,1)
+static int lsc_cb(__attribute__((unused)) uint8_t port_id, enum rte_eth_event_type type, __attribute__((unused)) void *param,
+ __attribute__((unused)) void *ret_param)
+#else
static void lsc_cb(__attribute__((unused)) uint8_t port_id, enum rte_eth_event_type type, __attribute__((unused)) void *param)
+#endif
{
- struct rte_eth_link link;
-
if (RTE_ETH_EVENT_INTR_LSC != type) {
+#if RTE_VERSION >= RTE_VERSION_NUM(17,8,0,1)
+ return -1;
+#else
return;
+#endif
}
rte_atomic32_inc(&lsc);
+
+#if RTE_VERSION >= RTE_VERSION_NUM(17,8,0,1)
+ return 0;
+#endif
}
struct prox_pktmbuf_reinit_args {
diff --git a/VNFs/DPPD-PROX/prox_port_cfg.h b/VNFs/DPPD-PROX/prox_port_cfg.h
index 17616187..370b0456 100644
--- a/VNFs/DPPD-PROX/prox_port_cfg.h
+++ b/VNFs/DPPD-PROX/prox_port_cfg.h
@@ -17,6 +17,7 @@
#ifndef _PROX_PORT_CFG_H
#define _PROX_PORT_CFG_H
+#include <rte_pci.h>
#include <rte_ether.h>
#include <rte_ethdev.h>
diff --git a/VNFs/DPPD-PROX/run.c b/VNFs/DPPD-PROX/run.c
index 971d7148..3abdb819 100644
--- a/VNFs/DPPD-PROX/run.c
+++ b/VNFs/DPPD-PROX/run.c
@@ -37,6 +37,7 @@
#include "input.h"
#include "input_curses.h"
#include "input_conn.h"
+#include "handle_master.h"
static int needs_refresh;
static uint64_t update_interval;
@@ -127,7 +128,10 @@ static void busy_wait_until(uint64_t deadline)
static void multiplexed_input_stats(uint64_t deadline)
{
- input_proc_until(deadline);
+ if (deadline)
+ input_proc_until(deadline);
+ else
+ input_proc();
if (needs_refresh) {
needs_refresh = 0;
@@ -164,6 +168,7 @@ void __attribute__((noreturn)) run(uint32_t flags)
uint64_t cur_tsc;
uint64_t next_update;
uint64_t stop_tsc = 0;
+ int ret = 0;
const uint64_t update_interval_threshold = usec_to_tsc(1);
if (flags & DSF_LISTEN_TCP)
@@ -209,20 +214,43 @@ void __attribute__((noreturn)) run(uint32_t flags)
cmd_rx_tx_info();
print_warnings();
- while (stop_prox == 0) {
+ struct task_master *task = (struct task_master *)lcore_cfg[prox_cfg.master].tasks_all[0];
+ if (handle_ctrl_plane) {
+ while (stop_prox == 0) {
+ ret = 1;
+ // Run ctrl plane for max 10 msec to let screen and keyboard updates
+ if (prox_cfg.flags & DSF_CTRL_PLANE_ENABLED) {
+ uint64_t ctrl_plane_update = rte_rdtsc() + msec_to_tsc(10);
+ while ((ret) && (rte_rdtsc() < ctrl_plane_update))
+ ret = handle_ctrl_plane(lcore_cfg[prox_cfg.master].tasks_all[0], NULL, 0);
+ }
+ multiplexed_input_stats(0);
+ if (rte_rdtsc() < next_update)
+ continue;
+ next_update += update_interval;
+ stats_update(stats_cons_flags);
+ stats_cons_notify();
+
+ if (stop_tsc && rte_rdtsc() >= stop_tsc) {
+ stop_prox = 1;
+ }
+ }
+ } else {
+ while (stop_prox == 0) {
- if (update_interval < update_interval_threshold)
- busy_wait_until(next_update);
- else
- multiplexed_input_stats(next_update);
+ if (update_interval < update_interval_threshold)
+ busy_wait_until(next_update);
+ else
+ multiplexed_input_stats(next_update);
- next_update += update_interval;
+ next_update += update_interval;
- stats_update(stats_cons_flags);
- stats_cons_notify();
+ stats_update(stats_cons_flags);
+ stats_cons_notify();
- if (stop_tsc && rte_rdtsc() >= stop_tsc) {
- stop_prox = 1;
+ if (stop_tsc && rte_rdtsc() >= stop_tsc) {
+ stop_prox = 1;
+ }
}
}
diff --git a/VNFs/DPPD-PROX/rx_pkt.c b/VNFs/DPPD-PROX/rx_pkt.c
index a6c1fd10..ec698d9a 100644
--- a/VNFs/DPPD-PROX/rx_pkt.c
+++ b/VNFs/DPPD-PROX/rx_pkt.c
@@ -24,6 +24,10 @@
#include "stats.h"
#include "log.h"
#include "mbuf_utils.h"
+#include "prefetch.h"
+#include "arp.h"
+#include "tx_pkt.h"
+#include "handle_master.h"
#include "input.h" /* Needed for callback on dump */
/* _param version of the rx_pkt_hw functions are used to create two
@@ -70,56 +74,137 @@ static void next_port_pow2(struct rx_params_hw *rx_params_hw)
rx_params_hw->last_read_portid = (rx_params_hw->last_read_portid + 1) & rx_params_hw->rxport_mask;
}
-static uint16_t rx_pkt_hw_param(struct task_base *tbase, struct rte_mbuf ***mbufs, int multi,
- void (*next)(struct rx_params_hw *rx_param_hw))
+static inline void dump_l3(struct task_base *tbase, struct rte_mbuf *mbuf)
+{
+ if (unlikely(tbase->aux->task_rt_dump.n_print_rx)) {
+ if (tbase->aux->task_rt_dump.input->reply == NULL) {
+ plogdx_info(mbuf, "RX: ");
+ } else {
+ struct input *input = tbase->aux->task_rt_dump.input;
+ char tmp[128];
+ int strlen;
+#if RTE_VERSION >= RTE_VERSION_NUM(1,8,0,0)
+ int port_id = mbuf->port;
+#else
+ int port_id = mbuf->pkt.in_port;
+#endif
+ strlen = snprintf(tmp, sizeof(tmp), "pktdump,%d,%d\n", port_id,
+ rte_pktmbuf_pkt_len(mbuf));
+ input->reply(input, tmp, strlen);
+ input->reply(input, rte_pktmbuf_mtod(mbuf, char *), rte_pktmbuf_pkt_len(mbuf));
+ input->reply(input, "\n", 1);
+ }
+ tbase->aux->task_rt_dump.n_print_rx --;
+ if (0 == tbase->aux->task_rt_dump.n_print_rx) {
+ task_base_del_rx_pkt_function(tbase, rx_pkt_dump);
+ }
+ }
+ if (unlikely(tbase->aux->task_rt_dump.n_trace)) {
+ plogdx_info(mbuf, "RX: ");
+ tbase->aux->task_rt_dump.n_trace--;
+ }
+}
+
+static uint16_t rx_pkt_hw_param(struct task_base *tbase, struct rte_mbuf ***mbufs_ptr, int multi,
+ void (*next)(struct rx_params_hw *rx_param_hw), int l3)
{
uint8_t last_read_portid;
uint16_t nb_rx;
+ int skip = 0;
START_EMPTY_MEASSURE();
- *mbufs = tbase->ws_mbuf->mbuf[0] +
+ *mbufs_ptr = tbase->ws_mbuf->mbuf[0] +
(RTE_ALIGN_CEIL(tbase->ws_mbuf->idx[0].prod, 2) & WS_MBUF_MASK);
last_read_portid = tbase->rx_params_hw.last_read_portid;
struct port_queue *pq = &tbase->rx_params_hw.rx_pq[last_read_portid];
- nb_rx = rx_pkt_hw_port_queue(pq, *mbufs, multi);
+ nb_rx = rx_pkt_hw_port_queue(pq, *mbufs_ptr, multi);
next(&tbase->rx_params_hw);
+ if (l3) {
+ struct rte_mbuf **mbufs = *mbufs_ptr;
+ int i;
+ struct ether_hdr_arp *hdr[MAX_PKT_BURST];
+ for (i = 0; i < nb_rx; i++) {
+ PREFETCH0(mbufs[i]);
+ }
+ for (i = 0; i < nb_rx; i++) {
+ hdr[i] = rte_pktmbuf_mtod(mbufs[i], struct ether_hdr_arp *);
+ PREFETCH0(hdr[i]);
+ }
+ for (i = 0; i < nb_rx; i++) {
+ if (unlikely(hdr[i]->ether_hdr.ether_type == ETYPE_ARP)) {
+ dump_l3(tbase, mbufs[i]);
+ tx_ring(tbase, tbase->l3.ctrl_plane_ring, ARP_TO_CTRL, mbufs[i]);
+ skip++;
+ } else if (unlikely(skip)) {
+ mbufs[i - skip] = mbufs[i];
+ }
+ }
+ }
+
+ if (skip)
+ TASK_STATS_ADD_DROP_HANDLED(&tbase->aux->stats, skip);
if (likely(nb_rx > 0)) {
TASK_STATS_ADD_RX(&tbase->aux->stats, nb_rx);
- return nb_rx;
+ return nb_rx - skip;
}
TASK_STATS_ADD_IDLE(&tbase->aux->stats, rte_rdtsc() - cur_tsc);
return 0;
}
-static inline uint16_t rx_pkt_hw1_param(struct task_base *tbase, struct rte_mbuf ***mbufs, int multi)
+static inline uint16_t rx_pkt_hw1_param(struct task_base *tbase, struct rte_mbuf ***mbufs_ptr, int multi, int l3)
{
uint16_t nb_rx, n;
+ int skip = 0;
START_EMPTY_MEASSURE();
- *mbufs = tbase->ws_mbuf->mbuf[0] +
+ *mbufs_ptr = tbase->ws_mbuf->mbuf[0] +
(RTE_ALIGN_CEIL(tbase->ws_mbuf->idx[0].prod, 2) & WS_MBUF_MASK);
nb_rx = rte_eth_rx_burst(tbase->rx_params_hw1.rx_pq.port,
tbase->rx_params_hw1.rx_pq.queue,
- *mbufs, MAX_PKT_BURST);
+ *mbufs_ptr, MAX_PKT_BURST);
if (multi) {
n = nb_rx;
while ((n != 0) && (MAX_PKT_BURST - nb_rx >= MIN_PMD_RX)) {
n = rte_eth_rx_burst(tbase->rx_params_hw1.rx_pq.port,
tbase->rx_params_hw1.rx_pq.queue,
- *mbufs + nb_rx, MIN_PMD_RX);
+ *mbufs_ptr + nb_rx, MIN_PMD_RX);
nb_rx += n;
PROX_PANIC(nb_rx > 64, "Received %d packets while expecting maximum %d\n", n, MIN_PMD_RX);
}
}
+ if (l3) {
+ struct rte_mbuf **mbufs = *mbufs_ptr;
+ int i;
+ struct ether_hdr_arp *hdr[MAX_PKT_BURST];
+ for (i = 0; i < nb_rx; i++) {
+ PREFETCH0(mbufs[i]);
+ }
+ for (i = 0; i < nb_rx; i++) {
+ hdr[i] = rte_pktmbuf_mtod(mbufs[i], struct ether_hdr_arp *);
+ PREFETCH0(hdr[i]);
+ }
+ for (i = 0; i < nb_rx; i++) {
+ if (unlikely(hdr[i]->ether_hdr.ether_type == ETYPE_ARP)) {
+ dump_l3(tbase, mbufs[i]);
+ tx_ring(tbase, tbase->l3.ctrl_plane_ring, ARP_TO_CTRL, mbufs[i]);
+ skip++;
+ } else if (unlikely(skip)) {
+ mbufs[i - skip] = mbufs[i];
+ }
+ }
+ }
+
+ if (skip)
+ TASK_STATS_ADD_DROP_HANDLED(&tbase->aux->stats, skip);
if (likely(nb_rx > 0)) {
TASK_STATS_ADD_RX(&tbase->aux->stats, nb_rx);
- return nb_rx;
+ return nb_rx - skip;
}
TASK_STATS_ADD_IDLE(&tbase->aux->stats, rte_rdtsc() - cur_tsc);
return 0;
@@ -127,36 +212,66 @@ static inline uint16_t rx_pkt_hw1_param(struct task_base *tbase, struct rte_mbuf
uint16_t rx_pkt_hw(struct task_base *tbase, struct rte_mbuf ***mbufs)
{
- return rx_pkt_hw_param(tbase, mbufs, 0, next_port);
+ return rx_pkt_hw_param(tbase, mbufs, 0, next_port, 0);
}
uint16_t rx_pkt_hw_pow2(struct task_base *tbase, struct rte_mbuf ***mbufs)
{
- return rx_pkt_hw_param(tbase, mbufs, 0, next_port_pow2);
+ return rx_pkt_hw_param(tbase, mbufs, 0, next_port_pow2, 0);
}
uint16_t rx_pkt_hw1(struct task_base *tbase, struct rte_mbuf ***mbufs)
{
- return rx_pkt_hw1_param(tbase, mbufs, 0);
+ return rx_pkt_hw1_param(tbase, mbufs, 0, 0);
}
uint16_t rx_pkt_hw_multi(struct task_base *tbase, struct rte_mbuf ***mbufs)
{
- return rx_pkt_hw_param(tbase, mbufs, 1, next_port);
+ return rx_pkt_hw_param(tbase, mbufs, 1, next_port, 0);
}
uint16_t rx_pkt_hw_pow2_multi(struct task_base *tbase, struct rte_mbuf ***mbufs)
{
- return rx_pkt_hw_param(tbase, mbufs, 1, next_port_pow2);
+ return rx_pkt_hw_param(tbase, mbufs, 1, next_port_pow2, 0);
}
uint16_t rx_pkt_hw1_multi(struct task_base *tbase, struct rte_mbuf ***mbufs)
{
- return rx_pkt_hw1_param(tbase, mbufs, 1);
+ return rx_pkt_hw1_param(tbase, mbufs, 1, 0);
+}
+
+uint16_t rx_pkt_hw_l3(struct task_base *tbase, struct rte_mbuf ***mbufs)
+{
+ return rx_pkt_hw_param(tbase, mbufs, 0, next_port, 1);
+}
+
+uint16_t rx_pkt_hw_pow2_l3(struct task_base *tbase, struct rte_mbuf ***mbufs)
+{
+ return rx_pkt_hw_param(tbase, mbufs, 0, next_port_pow2, 1);
+}
+
+uint16_t rx_pkt_hw1_l3(struct task_base *tbase, struct rte_mbuf ***mbufs)
+{
+ return rx_pkt_hw1_param(tbase, mbufs, 0, 1);
+}
+
+uint16_t rx_pkt_hw_multi_l3(struct task_base *tbase, struct rte_mbuf ***mbufs)
+{
+ return rx_pkt_hw_param(tbase, mbufs, 1, next_port, 1);
+}
+
+uint16_t rx_pkt_hw_pow2_multi_l3(struct task_base *tbase, struct rte_mbuf ***mbufs)
+{
+ return rx_pkt_hw_param(tbase, mbufs, 1, next_port_pow2, 1);
+}
+
+uint16_t rx_pkt_hw1_multi_l3(struct task_base *tbase, struct rte_mbuf ***mbufs)
+{
+ return rx_pkt_hw1_param(tbase, mbufs, 1, 1);
}
/* The following functions implement ring access */
-static uint16_t ring_deq(struct rte_ring *r, struct rte_mbuf **mbufs)
+uint16_t ring_deq(struct rte_ring *r, struct rte_mbuf **mbufs)
{
void **v_mbufs = (void **)mbufs;
#ifdef BRAS_RX_BULK
@@ -299,7 +414,7 @@ uint16_t rx_pkt_dump(struct task_base *tbase, struct rte_mbuf ***mbufs)
if (tbase->aux->task_rt_dump.input->reply == NULL) {
for (uint32_t i = 0; i < n_dump; ++i) {
- plogd_info((*mbufs)[i], "RX: ");
+ plogdx_info((*mbufs)[i], "RX: ");
}
}
else {
@@ -336,19 +451,20 @@ uint16_t rx_pkt_dump(struct task_base *tbase, struct rte_mbuf ***mbufs)
uint16_t rx_pkt_trace(struct task_base *tbase, struct rte_mbuf ***mbufs)
{
+ tbase->aux->task_rt_dump.cur_trace = 0;
uint16_t ret = call_prev_rx_pkt(tbase, mbufs);
if (ret) {
uint32_t n_trace = tbase->aux->task_rt_dump.n_trace;
n_trace = ret < n_trace? ret : n_trace;
- tbase->aux->task_rt_dump.cur_trace = n_trace;
for (uint32_t i = 0; i < n_trace; ++i) {
uint8_t *pkt = rte_pktmbuf_mtod((*mbufs)[i], uint8_t *);
- rte_memcpy(tbase->aux->task_rt_dump.pkt_cpy[i], pkt, sizeof(tbase->aux->task_rt_dump.pkt_cpy[i]));
- tbase->aux->task_rt_dump.pkt_cpy_len[i] = rte_pktmbuf_pkt_len((*mbufs)[i]);
- tbase->aux->task_rt_dump.pkt_mbuf_addr[i] = (*mbufs)[i];
+ rte_memcpy(tbase->aux->task_rt_dump.pkt_cpy[tbase->aux->task_rt_dump.cur_trace + i], pkt, sizeof(tbase->aux->task_rt_dump.pkt_cpy[i]));
+ tbase->aux->task_rt_dump.pkt_cpy_len[tbase->aux->task_rt_dump.cur_trace + i] = rte_pktmbuf_pkt_len((*mbufs)[i]);
+ tbase->aux->task_rt_dump.pkt_mbuf_addr[tbase->aux->task_rt_dump.cur_trace + i] = (*mbufs)[i];
}
+ tbase->aux->task_rt_dump.cur_trace += n_trace;
tbase->aux->task_rt_dump.n_trace -= n_trace;
/* Unset by TX when n_trace = 0 */
diff --git a/VNFs/DPPD-PROX/rx_pkt.h b/VNFs/DPPD-PROX/rx_pkt.h
index 57b948e2..6d8f412c 100644
--- a/VNFs/DPPD-PROX/rx_pkt.h
+++ b/VNFs/DPPD-PROX/rx_pkt.h
@@ -21,10 +21,14 @@
struct rte_mbuf;
struct task_base;
+struct rte_ring;
uint16_t rx_pkt_hw(struct task_base *tbase, struct rte_mbuf ***mbufs);
uint16_t rx_pkt_hw_pow2(struct task_base *tbase, struct rte_mbuf ***mbufs);
uint16_t rx_pkt_hw1(struct task_base *tbase, struct rte_mbuf ***mbufs);
+uint16_t rx_pkt_hw_l3(struct task_base *tbase, struct rte_mbuf ***mbufs);
+uint16_t rx_pkt_hw_pow2_l3(struct task_base *tbase, struct rte_mbuf ***mbufs);
+uint16_t rx_pkt_hw1_l3(struct task_base *tbase, struct rte_mbuf ***mbufs);
/* The _multi variation of the function is used to work-around the
problem with QoS, multi-seg mbufs and vector PMD. When vector
@@ -33,6 +37,9 @@ uint16_t rx_pkt_hw1(struct task_base *tbase, struct rte_mbuf ***mbufs);
uint16_t rx_pkt_hw_multi(struct task_base *tbase, struct rte_mbuf ***mbufs);
uint16_t rx_pkt_hw_pow2_multi(struct task_base *tbase, struct rte_mbuf ***mbufs);
uint16_t rx_pkt_hw1_multi(struct task_base *tbase, struct rte_mbuf ***mbufs);
+uint16_t rx_pkt_hw_multi_l3(struct task_base *tbase, struct rte_mbuf ***mbufs);
+uint16_t rx_pkt_hw_pow2_multi_l3(struct task_base *tbase, struct rte_mbuf ***mbufs);
+uint16_t rx_pkt_hw1_multi_l3(struct task_base *tbase, struct rte_mbuf ***mbufs);
uint16_t rx_pkt_sw(struct task_base *tbase, struct rte_mbuf ***mbufs);
uint16_t rx_pkt_sw_pow2(struct task_base *tbase, struct rte_mbuf ***mbufs);
@@ -45,5 +52,6 @@ uint16_t rx_pkt_distr(struct task_base *tbase, struct rte_mbuf ***mbufs);
uint16_t rx_pkt_bw(struct task_base *tbase, struct rte_mbuf ***mbufs);
uint16_t rx_pkt_tsc(struct task_base *tbase, struct rte_mbuf ***mbufs);
uint16_t rx_pkt_all(struct task_base *tbase, struct rte_mbuf ***mbufs);
+uint16_t ring_deq(struct rte_ring *r, struct rte_mbuf **mbufs);
#endif /* _RX_PKT_H_ */
diff --git a/VNFs/DPPD-PROX/stats_core.c b/VNFs/DPPD-PROX/stats_core.c
index 845399e3..34a9f747 100644
--- a/VNFs/DPPD-PROX/stats_core.c
+++ b/VNFs/DPPD-PROX/stats_core.c
@@ -262,7 +262,7 @@ void stats_lcore_post_proc(void)
ls->cmt_bytes = ls->cmt_data * scm->rdt_features.upscaling_factor;
lss->mbm_tot_bytes = ls->mbm_tot * scm->rdt_features.upscaling_factor;
lss->mbm_loc_bytes = ls->mbm_loc * scm->rdt_features.upscaling_factor;
- plogx_dbg("cache[core %d] = %ld\n", ls->lcore_id, ls->cmt_bytes);
+ //plogx_dbg("cache[core %d] = %ld\n", ls->lcore_id, ls->cmt_bytes);
}
}
for (uint8_t i = 0; i < scm->n_lcore_stats; ++i) {
diff --git a/VNFs/DPPD-PROX/task_base.h b/VNFs/DPPD-PROX/task_base.h
index b2fab2fc..62841e96 100644
--- a/VNFs/DPPD-PROX/task_base.h
+++ b/VNFs/DPPD-PROX/task_base.h
@@ -25,8 +25,9 @@
#include "defaults.h"
#include "prox_globals.h"
#include "stats_task.h"
+#include "packet_utils.h"
-// runtime_flags 8 bits only
+// runtime_flags 16 bits only
#define TASK_MPLS_TAGGING 0x0001
#define TASK_ROUTING 0x0002
#define TASK_CLASSIFY 0x0004
@@ -34,6 +35,7 @@
#define TASK_MARK 0x0020
#define TASK_FP_HANDLE_ARP 0x0040
#define TASK_TX_CRC 0x0080
+#define TASK_L3 0x0100
// flag_features 64 bits
#define TASK_FEATURE_ROUTING 0x0001
@@ -52,6 +54,7 @@
#define TASK_FEATURE_LUT_QINQ_HASH 0x4000
#define TASK_FEATURE_RX_ALL 0x8000
#define TASK_MULTIPLE_MAC 0x10000
+#define TASK_FEATURE_L3 0x20000
#define FLAG_TX_FLUSH 0x01
#define FLAG_NEVER_FLUSH 0x02
@@ -133,7 +136,7 @@ struct task_rt_dump {
uint32_t n_trace;
uint32_t cur_trace;
void *pkt_mbuf_addr[MAX_RING_BURST]; /* To track reordering */
- uint8_t pkt_cpy[MAX_RING_BURST][128];
+ uint8_t pkt_cpy[MAX_RING_BURST][DUMP_PKT_LEN];
uint16_t pkt_cpy_len[MAX_RING_BURST];
};
@@ -164,6 +167,7 @@ struct task_base_aux {
uint32_t rx_bucket[MAX_RING_BURST + 1];
uint32_t tx_bucket[MAX_RING_BURST + 1];
+ int (*tx_pkt_l2)(struct task_base *tbase, struct rte_mbuf **mbufs, const uint16_t n_pkts, uint8_t *out);
int (*tx_pkt_orig)(struct task_base *tbase, struct rte_mbuf **mbufs, const uint16_t n_pkts, uint8_t *out);
int (*tx_pkt_hw)(struct task_base *tbase, struct rte_mbuf **mbufs, const uint16_t n_pkts, uint8_t *out);
uint16_t (*tx_pkt_try)(struct task_base *tbase, struct rte_mbuf **mbufs, const uint16_t n_pkts);
@@ -174,7 +178,7 @@ struct task_base_aux {
};
/* The task_base is accessed for _all_ task types. In case
- no debugging is needed, it has been optimized to fit
+ no debugging or l3 is needed, it has been optimized to fit
into a single cache line to minimize cache pollution */
struct task_base {
int (*handle_bulk)(struct task_base *tbase, struct rte_mbuf **mbufs, const uint16_t n_pkts);
@@ -200,6 +204,8 @@ struct task_base {
struct tx_params_sw tx_params_sw;
struct tx_params_hw_sw tx_params_hw_sw;
};
+ struct l3_base l3;
+ uint32_t local_ipv4;
} __attribute__((packed)) __rte_cache_aligned;
static void task_base_add_rx_pkt_function(struct task_base *tbase, rx_pkt_func to_add)
diff --git a/VNFs/DPPD-PROX/task_init.c b/VNFs/DPPD-PROX/task_init.c
index 6d9c7b3d..3af0db2a 100644
--- a/VNFs/DPPD-PROX/task_init.c
+++ b/VNFs/DPPD-PROX/task_init.c
@@ -38,7 +38,7 @@ LIST_HEAD(,task_init) head;
void reg_task(struct task_init* t)
{
- PROX_PANIC(t->handle == NULL, "No handle function specified for task with name %d\n", t->mode);
+ // PROX_PANIC(t->handle == NULL, "No handle function specified for task with name %d\n", t->mode);
if (t->thread_x == NULL)
t->thread_x = thread_generic;
@@ -70,6 +70,11 @@ static int compare_strcmp(const void *a, const void *b)
return strcmp(*(const char * const *)a, *(const char * const *)b);
}
+int task_is_master(struct task_args *targ)
+{
+ return (targ->lconf->id == prox_cfg.master);
+}
+
void tasks_list(void)
{
struct task_init *cur_t;
@@ -169,13 +174,19 @@ static size_t init_rx_tx_rings_ports(struct task_args *targ, struct task_base *t
}
else {
if (targ->nb_rxports == 1) {
- tbase->rx_pkt = (targ->task_init->flag_features & TASK_FEATURE_MULTI_RX)? rx_pkt_hw1_multi : rx_pkt_hw1;
+ if (targ->task_init->flag_features & TASK_FEATURE_L3)
+ tbase->rx_pkt = (targ->task_init->flag_features & TASK_FEATURE_MULTI_RX)? rx_pkt_hw1_multi_l3 : rx_pkt_hw1_l3;
+ else
+ tbase->rx_pkt = (targ->task_init->flag_features & TASK_FEATURE_MULTI_RX)? rx_pkt_hw1_multi : rx_pkt_hw1;
tbase->rx_params_hw1.rx_pq.port = targ->rx_port_queue[0].port;
tbase->rx_params_hw1.rx_pq.queue = targ->rx_port_queue[0].queue;
}
else {
PROX_ASSERT((targ->nb_rxports != 0) || (targ->task_init->flag_features & TASK_FEATURE_NO_RX));
- tbase->rx_pkt = (targ->task_init->flag_features & TASK_FEATURE_MULTI_RX)? rx_pkt_hw_multi : rx_pkt_hw;
+ if (targ->task_init->flag_features & TASK_FEATURE_L3)
+ tbase->rx_pkt = (targ->task_init->flag_features & TASK_FEATURE_MULTI_RX)? rx_pkt_hw_multi_l3 : rx_pkt_hw_l3;
+ else
+ tbase->rx_pkt = (targ->task_init->flag_features & TASK_FEATURE_MULTI_RX)? rx_pkt_hw_multi : rx_pkt_hw;
tbase->rx_params_hw.nb_rxports = targ->nb_rxports;
tbase->rx_params_hw.rx_pq = (struct port_queue *)(((uint8_t *)tbase) + offset);
offset += sizeof(struct port_queue) * tbase->rx_params_hw.nb_rxports;
@@ -185,7 +196,10 @@ static size_t init_rx_tx_rings_ports(struct task_args *targ, struct task_base *t
}
if (rte_is_power_of_2(targ->nb_rxports)) {
- tbase->rx_pkt = (targ->task_init->flag_features & TASK_FEATURE_MULTI_RX)? rx_pkt_hw_pow2_multi : rx_pkt_hw_pow2;
+ if (targ->task_init->flag_features & TASK_FEATURE_L3)
+ tbase->rx_pkt = (targ->task_init->flag_features & TASK_FEATURE_MULTI_RX)? rx_pkt_hw_pow2_multi_l3 : rx_pkt_hw_pow2_l3;
+ else
+ tbase->rx_pkt = (targ->task_init->flag_features & TASK_FEATURE_MULTI_RX)? rx_pkt_hw_pow2_multi : rx_pkt_hw_pow2;
tbase->rx_params_hw.rxport_mask = targ->nb_rxports - 1;
}
}
@@ -336,6 +350,13 @@ struct task_base *init_task_struct(struct task_args *targ)
offset = init_rx_tx_rings_ports(targ, tbase, offset);
tbase->aux = (struct task_base_aux *)(((uint8_t *)tbase) + offset);
+ if ((targ->nb_txrings != 0) || (targ->nb_txports != 0)) {
+ if (targ->task_init->flag_features & TASK_FEATURE_L3) {
+ tbase->aux->tx_pkt_l2 = tbase->tx_pkt;
+ tbase->tx_pkt = tx_pkt_l3;
+ }
+ }
+
if (targ->task_init->flag_features & TASK_FEATURE_RX_ALL) {
task_base_add_rx_pkt_function(tbase, rx_pkt_all);
tbase->aux->all_mbufs = prox_zmalloc(MAX_RX_PKT_ALL * sizeof(* tbase->aux->all_mbufs), task_socket);
@@ -348,6 +369,15 @@ struct task_base *init_task_struct(struct task_args *targ)
tbase->handle_bulk = t->handle;
+ if (targ->task_init->flag_features & TASK_FEATURE_L3) {
+ plog_info("\tTask configured in L3 mode\n");
+ tbase->l3.ctrl_plane_ring = targ->ctrl_plane_ring;
+ }
+ if ((targ->nb_txrings != 0) || (targ->nb_txports != 0)) {
+ if (targ->task_init->flag_features & TASK_FEATURE_L3)
+ task_init_l3(tbase, targ);
+ }
+
targ->tbase = tbase;
if (t->init) {
t->init(tbase, targ);
@@ -372,8 +402,12 @@ struct task_base *init_task_struct(struct task_args *targ)
struct task_args *find_reachable_task_sending_to_port(struct task_args *from)
{
- if (!from->nb_txrings)
- return from;
+ if (!from->nb_txrings) {
+ if (from->tx_port_queue[0].port != OUT_DISCARD)
+ return from;
+ else
+ return NULL;
+ }
struct core_task ct;
struct task_args *dtarg, *ret;
diff --git a/VNFs/DPPD-PROX/task_init.h b/VNFs/DPPD-PROX/task_init.h
index e1f5ce1c..86a9521c 100644
--- a/VNFs/DPPD-PROX/task_init.h
+++ b/VNFs/DPPD-PROX/task_init.h
@@ -124,12 +124,12 @@ struct task_args {
uint8_t nb_rxports;
uint32_t byte_offset;
uint32_t gateway_ipv4;
- uint32_t number_gen_ip;
uint32_t local_ipv4;
uint32_t remote_ipv4;
struct ipv6_addr local_ipv6; /* For IPv6 Tunnel, it's the local tunnel endpoint address */
struct rte_ring *rx_rings[MAX_RINGS_PER_TASK];
struct rte_ring *tx_rings[MAX_RINGS_PER_TASK];
+ struct rte_ring *ctrl_plane_ring;
uint32_t tot_n_txrings_inited;
struct ether_addr edaddr;
struct ether_addr esaddr;
@@ -223,6 +223,10 @@ struct task_args {
struct rte_hash *private_ip_port_hash;
struct rte_hash *private_ip_hash;
struct private_ip_info *private_ip_info;
+ struct rte_ring **ctrl_rx_rings;
+ struct rte_ring **ctrl_tx_rings;
+ int n_ctrl_rings;
+ struct task_base *tmaster;
};
/* Return the first port that is reachable through the task. If the
@@ -234,6 +238,7 @@ struct prox_port_cfg *find_reachable_port(struct task_args *from);
struct task_base *init_task_struct(struct task_args *targ);
struct task_init *to_task_init(const char *mode_str, const char *sub_mode_str);
void tasks_list(void);
+int task_is_master(struct task_args *targ);
void reg_task(struct task_init* t);
diff --git a/VNFs/DPPD-PROX/tx_pkt.c b/VNFs/DPPD-PROX/tx_pkt.c
index c6f6010c..9ada51ca 100644
--- a/VNFs/DPPD-PROX/tx_pkt.c
+++ b/VNFs/DPPD-PROX/tx_pkt.c
@@ -25,6 +25,7 @@
#include "prox_assert.h"
#include "log.h"
#include "mbuf_utils.h"
+#include "handle_master.h"
static void buf_pkt_single(struct task_base *tbase, struct rte_mbuf *mbuf, const uint8_t out)
{
@@ -49,9 +50,40 @@ static inline void buf_pkt_all(struct task_base *tbase, struct rte_mbuf **mbufs,
}
#define MAX_PMD_TX 32
+int tx_pkt_l3(struct task_base *tbase, struct rte_mbuf **mbufs, uint16_t n_pkts, uint8_t *out)
+{
+ uint32_t ip_dst;
+ int first = 0, ret, ok = 0, rc;
+ const struct port_queue *port_queue = &tbase->tx_params_hw.tx_port_queue[0];
+
+ for (int j = 0; j < n_pkts; j++) {
+ if ((out) && (out[j] >= OUT_HANDLED))
+ continue;
+ if (unlikely((rc = write_dst_mac(tbase, mbufs[j], &ip_dst)) < 0)) {
+ if (j - first) {
+ ret = tbase->aux->tx_pkt_l2(tbase, mbufs + first, j - first, out);
+ ok += ret;
+ }
+ first = j + 1;
+ if (rc == -1) {
+ mbufs[j]->port = tbase->l3.reachable_port_id;
+ tx_ring_cti(tbase, tbase->l3.ctrl_plane_ring, REQ_MAC_TO_CTRL, mbufs[j], tbase->l3.core_id, tbase->l3.task_id, ip_dst);
+ } else if (rc == -2) {
+ tx_drop(mbufs[j]);
+ TASK_STATS_ADD_DROP_DISCARD(&tbase->aux->stats, 1);
+ }
+ }
+ }
+ if (n_pkts - first) {
+ ret = tbase->aux->tx_pkt_l2(tbase, mbufs + first, n_pkts - first, out);
+ ok += ret;
+ }
+ return ok;
+}
+
/* The following help functions also report stats. Therefore we need
to pass the task_base struct. */
-static inline int txhw_drop(const struct port_queue *port_queue, struct rte_mbuf **mbufs, uint16_t n_pkts, __attribute__((unused)) struct task_base *tbase)
+static inline int txhw_drop(const struct port_queue *port_queue, struct rte_mbuf **mbufs, uint16_t n_pkts, struct task_base *tbase)
{
uint16_t ntx;
int ret;
@@ -63,10 +95,11 @@ static inline int txhw_drop(const struct port_queue *port_queue, struct rte_mbuf
} else {
ntx = rte_eth_tx_burst(port_queue->port, port_queue->queue, mbufs, n_pkts);
}
-
TASK_STATS_ADD_TX(&tbase->aux->stats, ntx);
+
ret = n_pkts - ntx;
if (ntx < n_pkts) {
+ plog_dbg("Failed to send %d packets from %p\n", ret, mbufs[0]);
TASK_STATS_ADD_DROP_TX_FAIL(&tbase->aux->stats, n_pkts - ntx);
if (tbase->tx_pkt == tx_pkt_bw) {
uint32_t drop_bytes = 0;
@@ -85,13 +118,12 @@ static inline int txhw_drop(const struct port_queue *port_queue, struct rte_mbuf
return ret;
}
-static inline int txhw_no_drop(const struct port_queue *port_queue, struct rte_mbuf **mbufs, uint16_t n_pkts, __attribute__((unused)) struct task_base *tbase)
+static inline int txhw_no_drop(const struct port_queue *port_queue, struct rte_mbuf **mbufs, uint16_t n_pkts, struct task_base *tbase)
{
uint16_t ret;
uint16_t n = n_pkts;
TASK_STATS_ADD_TX(&tbase->aux->stats, n_pkts);
-
do {
ret = rte_eth_tx_burst(port_queue->port, port_queue->queue, mbufs, n_pkts);
mbufs += ret;
@@ -265,11 +297,11 @@ uint16_t tx_try_sw1(struct task_base *tbase, struct rte_mbuf **mbufs, uint16_t n
uint16_t tx_try_hw1(struct task_base *tbase, struct rte_mbuf **mbufs, uint16_t n_pkts)
{
- const struct port_queue *port_queue = &tbase->tx_params_hw.tx_port_queue[0];
const int bulk_size = 64;
uint16_t ret = bulk_size, n_bulks, sent = 0;
n_bulks = n_pkts >> __builtin_ctz(bulk_size);
+ const struct port_queue *port_queue = &tbase->tx_params_hw.tx_port_queue[0];
for (int i = 0; i < n_bulks; i++) {
ret = rte_eth_tx_burst(port_queue->port, port_queue->queue, mbufs, bulk_size);
mbufs += ret;
@@ -541,59 +573,91 @@ int tx_pkt_sw(struct task_base *tbase, struct rte_mbuf **mbufs, uint16_t n_pkts,
return ret;
}
+static inline void trace_one_rx_pkt(struct task_base *tbase, struct rte_mbuf *mbuf)
+{
+ struct rte_mbuf tmp;
+ /* For each packet being transmitted, find which
+ buffer represent the packet as it was before
+ processing. */
+ uint32_t j = 0;
+ uint32_t len = sizeof(tbase->aux->task_rt_dump.pkt_mbuf_addr)/sizeof(tbase->aux->task_rt_dump.pkt_mbuf_addr[0]);
+ for (;j < len; ++j) {
+ if (tbase->aux->task_rt_dump.pkt_mbuf_addr[j] == mbuf)
+ break;
+ }
+ if (j != len) {
+#if RTE_VERSION >= RTE_VERSION_NUM(1,8,0,0)
+ tmp.data_off = 0;
+#endif
+ rte_pktmbuf_data_len(&tmp) = tbase->aux->task_rt_dump.pkt_cpy_len[j];
+ rte_pktmbuf_pkt_len(&tmp) = tbase->aux->task_rt_dump.pkt_cpy_len[j];
+ tmp.buf_addr = tbase->aux->task_rt_dump.pkt_cpy[j];
+ plogdx_info(&tmp, "Trace RX: ");
+ }
+}
+
+static inline void trace_one_tx_pkt(struct task_base *tbase, struct rte_mbuf *mbuf, uint8_t *out, uint32_t i)
+{
+ if (out) {
+ switch(out[i]) {
+ case 0xFE:
+ plogdx_info(mbuf, "Handled: ");
+ break;
+ case 0xFF:
+ plogdx_info(mbuf, "Dropped: ");
+ break;
+ default:
+ plogdx_info(mbuf, "TX[%d]: ", out[i]);
+ break;
+ }
+ } else if (tbase->aux->tx_pkt_orig == tx_pkt_drop_all) {
+ plogdx_info(mbuf, "Dropped: ");
+ } else
+ plogdx_info(mbuf, "TX[0]: ");
+}
+
+static void unset_trace(struct task_base *tbase)
+{
+ if (0 == tbase->aux->task_rt_dump.n_trace) {
+ if (tbase->tx_pkt == tx_pkt_l3) {
+ tbase->aux->tx_pkt_l2 = tbase->aux->tx_pkt_orig;
+ tbase->aux->tx_pkt_orig = NULL;
+ } else {
+ tbase->tx_pkt = tbase->aux->tx_pkt_orig;
+ tbase->aux->tx_pkt_orig = NULL;
+ }
+ tbase->aux->task_rt_dump.cur_trace = 0;
+ task_base_del_rx_pkt_function(tbase, rx_pkt_trace);
+ }
+}
+
int tx_pkt_trace(struct task_base *tbase, struct rte_mbuf **mbufs, uint16_t n_pkts, uint8_t *out)
{
int ret = 0;
if (tbase->aux->task_rt_dump.cur_trace == 0) {
// No packet received since dumping...
- // So the transmitted packets should not be linked to received packets
tbase->aux->task_rt_dump.n_print_tx = tbase->aux->task_rt_dump.n_trace;
- tbase->aux->task_rt_dump.n_trace = 0;
- task_base_del_rx_pkt_function(tbase, rx_pkt_trace);
- return tx_pkt_dump(tbase, mbufs, n_pkts, out);
+ if (tbase->aux->task_rt_dump.n_trace < n_pkts) {
+ tbase->aux->task_rt_dump.n_trace = 0;
+ tbase->aux->task_rt_dump.cur_trace = 0;
+ task_base_del_rx_pkt_function(tbase, rx_pkt_trace);
+ } else {
+ tbase->aux->task_rt_dump.n_trace -= n_pkts;
+ }
+ ret = tx_pkt_dump(tbase, mbufs, n_pkts, out);
+ tbase->aux->task_rt_dump.n_print_tx = 0;
+ return ret;
}
plog_info("Tracing %d pkts\n", tbase->aux->task_rt_dump.cur_trace);
+ uint32_t cur_trace = (n_pkts < tbase->aux->task_rt_dump.cur_trace) ? n_pkts: tbase->aux->task_rt_dump.cur_trace;
+ for (uint32_t i = 0; i < cur_trace; ++i) {
+ trace_one_rx_pkt(tbase, mbufs[i]);
+ trace_one_tx_pkt(tbase, mbufs[i], out, i);
- for (uint32_t i = 0; i < tbase->aux->task_rt_dump.cur_trace; ++i) {
- struct rte_mbuf tmp;
- /* For each packet being transmitted, find which
- buffer represent the packet as it was before
- processing. */
- uint32_t j = 0;
- uint32_t len = sizeof(tbase->aux->task_rt_dump.pkt_mbuf_addr)/sizeof(tbase->aux->task_rt_dump.pkt_mbuf_addr[0]);
- for (;j < len; ++j) {
- if (tbase->aux->task_rt_dump.pkt_mbuf_addr[j] == mbufs[i])
- break;
- }
- if (j == len) {
- plog_info("Trace RX: missing!\n");
- }
- else {
-#if RTE_VERSION >= RTE_VERSION_NUM(1,8,0,0)
- tmp.data_off = 0;
-#endif
- rte_pktmbuf_data_len(&tmp) = tbase->aux->task_rt_dump.pkt_cpy_len[j];
- rte_pktmbuf_pkt_len(&tmp) = tbase->aux->task_rt_dump.pkt_cpy_len[j];
- tmp.buf_addr = tbase->aux->task_rt_dump.pkt_cpy[j];
- plogd_info(&tmp, "Trace RX: ");
- }
-
- if (out) {
- if (out[i] != 0xFF)
- plogd_info(mbufs[i], "Trace TX[%d]: ", out[i]);
- else
- plogd_info(mbufs[i], "Trace Dropped: ");
- } else
- plogd_info(mbufs[i], "Trace TX: ");
}
ret = tbase->aux->tx_pkt_orig(tbase, mbufs, n_pkts, out);
- /* Unset by TX when n_trace = 0 */
- if (0 == tbase->aux->task_rt_dump.n_trace) {
- tbase->tx_pkt = tbase->aux->tx_pkt_orig;
- tbase->aux->tx_pkt_orig = NULL;
- task_base_del_rx_pkt_function(tbase, rx_pkt_trace);
- }
+ unset_trace(tbase);
return ret;
}
@@ -604,18 +668,33 @@ int tx_pkt_dump(struct task_base *tbase, struct rte_mbuf **mbufs, uint16_t n_pkt
n_dump = n_pkts < n_dump? n_pkts : n_dump;
for (uint32_t i = 0; i < n_dump; ++i) {
- if (out)
- plogd_info(mbufs[i], "TX[%d]: ", out[i]);
- else
- plogd_info(mbufs[i], "TX: ");
+ if (out) {
+ switch (out[i]) {
+ case 0xFE:
+ plogdx_info(mbufs[i], "Handled: ");
+ break;
+ case 0xFF:
+ plogdx_info(mbufs[i], "Dropped: ");
+ break;
+ default:
+ plogdx_info(mbufs[i], "TX[%d]: ", out[i]);
+ break;
+ }
+ } else
+ plogdx_info(mbufs[i], "TX: ");
}
tbase->aux->task_rt_dump.n_print_tx -= n_dump;
ret = tbase->aux->tx_pkt_orig(tbase, mbufs, n_pkts, out);
if (0 == tbase->aux->task_rt_dump.n_print_tx) {
- tbase->tx_pkt = tbase->aux->tx_pkt_orig;
- tbase->aux->tx_pkt_orig = NULL;
+ if (tbase->tx_pkt == tx_pkt_l3) {
+ tbase->aux->tx_pkt_l2 = tbase->aux->tx_pkt_orig;
+ tbase->aux->tx_pkt_orig = NULL;
+ } else {
+ tbase->tx_pkt = tbase->aux->tx_pkt_orig;
+ tbase->aux->tx_pkt_orig = NULL;
+ }
}
return ret;
}
@@ -663,3 +742,45 @@ int tx_pkt_drop_all(struct task_base *tbase, struct rte_mbuf **mbufs, uint16_t n
}
return n_pkts;
}
+
+static inline int tx_ring_all(struct task_base *tbase, struct rte_ring *ring, uint16_t command, struct rte_mbuf *mbuf, uint8_t core_id, uint8_t task_id, uint32_t ip)
+{
+ if (tbase->aux->task_rt_dump.cur_trace) {
+ trace_one_rx_pkt(tbase, mbuf);
+ }
+ mbuf->udata64 = ((uint64_t)ip << 32) | (core_id << 16) | (task_id << 8) | command;
+ return rte_ring_enqueue(ring, mbuf);
+}
+
+void tx_ring_cti(struct task_base *tbase, struct rte_ring *ring, uint16_t command, struct rte_mbuf *mbuf, uint8_t core_id, uint8_t task_id, uint32_t ip)
+{
+ plogx_dbg("\tSending command %s with ip %x to ring %p using mbuf %p, core %d and task %d - ring size now %d\n", actions_string[command], ip, ring, mbuf, core_id, task_id, rte_ring_free_count(ring));
+ int ret = tx_ring_all(tbase, ring, command, mbuf, core_id, task_id, ip);
+ if (unlikely(ret != 0)) {
+ plogx_dbg("\tFail to send command %s with ip %x to ring %p using mbuf %p, core %d and task %d - ring size now %d\n", actions_string[command], ip, ring, mbuf, core_id, task_id, rte_ring_free_count(ring));
+ TASK_STATS_ADD_DROP_DISCARD(&tbase->aux->stats, 1);
+ rte_pktmbuf_free(mbuf);
+ }
+}
+
+void tx_ring_ip(struct task_base *tbase, struct rte_ring *ring, uint16_t command, struct rte_mbuf *mbuf, uint32_t ip)
+{
+ plogx_dbg("\tSending command %s with ip %x to ring %p using mbuf %p - ring size now %d\n", actions_string[command], ip, ring, mbuf, rte_ring_free_count(ring));
+ int ret = tx_ring_all(tbase, ring, command, mbuf, 0, 0, ip);
+ if (unlikely(ret != 0)) {
+ plogx_dbg("\tFail to send command %s with ip %x to ring %p using mbuf %p - ring size now %d\n", actions_string[command], ip, ring, mbuf, rte_ring_free_count(ring));
+ TASK_STATS_ADD_DROP_DISCARD(&tbase->aux->stats, 1);
+ rte_pktmbuf_free(mbuf);
+ }
+}
+
+void tx_ring(struct task_base *tbase, struct rte_ring *ring, uint16_t command, struct rte_mbuf *mbuf)
+{
+ plogx_dbg("\tSending command %s to ring %p using mbuf %p - ring size now %d\n", actions_string[command], ring, mbuf, rte_ring_free_count(ring));
+ int ret = tx_ring_all(tbase, ring, command, mbuf, 0, 0, 0);
+ if (unlikely(ret != 0)) {
+ plogx_dbg("\tFail to send command %s to ring %p using mbuf %p - ring size now %d\n", actions_string[command], ring, mbuf, rte_ring_free_count(ring));
+ TASK_STATS_ADD_DROP_DISCARD(&tbase->aux->stats, 1);
+ rte_pktmbuf_free(mbuf);
+ }
+}
diff --git a/VNFs/DPPD-PROX/tx_pkt.h b/VNFs/DPPD-PROX/tx_pkt.h
index 798797ab..e8caed52 100644
--- a/VNFs/DPPD-PROX/tx_pkt.h
+++ b/VNFs/DPPD-PROX/tx_pkt.h
@@ -78,5 +78,10 @@ uint16_t tx_try_self(struct task_base *tbase, struct rte_mbuf **mbufs, uint16_t
tx function. This tx function can be used to make each task a
sink. */
int tx_pkt_drop_all(struct task_base *tbase, struct rte_mbuf **mbufs, uint16_t n_pkts, uint8_t *out);
+int tx_pkt_l3(struct task_base *tbase, struct rte_mbuf **mbufs, uint16_t n_pkts, uint8_t *out);
+
+void tx_ring_cti(struct task_base *tbase, struct rte_ring *ring, uint16_t command, struct rte_mbuf *mbuf, uint8_t core_id, uint8_t task_id, uint32_t ip);
+void tx_ring_ip(struct task_base *tbase, struct rte_ring *ring, uint16_t command, struct rte_mbuf *mbuf, uint32_t ip);
+void tx_ring(struct task_base *tbase, struct rte_ring *ring, uint16_t command, struct rte_mbuf *mbuf);
#endif /* _TX_PKT_H_ */
diff --git a/VNFs/DPPD-PROX/version.h b/VNFs/DPPD-PROX/version.h
index b906b14b..a1d01235 100644
--- a/VNFs/DPPD-PROX/version.h
+++ b/VNFs/DPPD-PROX/version.h
@@ -22,7 +22,7 @@
/* PROGRAM_NAME defined through Makefile */
#define VERSION_MAJOR 0
-#define VERSION_MINOR 39
+#define VERSION_MINOR 41
#define VERSION_REV 0
#if VERSION_REV > 0