Merge changes from PROX-v041 31/46331/1
authorPatrice Buriez <patrice.buriez@intel.com>
Wed, 25 Oct 2017 18:30:34 +0000 (20:30 +0200)
committerPatrice Buriez <patrice.buriez@intel.com>
Wed, 25 Oct 2017 18:30:34 +0000 (20:30 +0200)
Change-Id: Ie6d4e7ce22c27967117a446626f5923643397812
Signed-off-by: Patrice Buriez <patrice.buriez@intel.com>
39 files changed:
VNFs/DPPD-PROX/Makefile
VNFs/DPPD-PROX/README
VNFs/DPPD-PROX/arp.h
VNFs/DPPD-PROX/cmd_parser.c
VNFs/DPPD-PROX/commands.c
VNFs/DPPD-PROX/defaults.c
VNFs/DPPD-PROX/defaults.h
VNFs/DPPD-PROX/handle_arp.c
VNFs/DPPD-PROX/handle_gen.c
VNFs/DPPD-PROX/handle_gen.h
VNFs/DPPD-PROX/handle_impair.c
VNFs/DPPD-PROX/handle_irq.c
VNFs/DPPD-PROX/handle_master.c [new file with mode: 0644]
VNFs/DPPD-PROX/handle_master.h [new file with mode: 0644]
VNFs/DPPD-PROX/handle_swap.c
VNFs/DPPD-PROX/handle_swap.h
VNFs/DPPD-PROX/input.c
VNFs/DPPD-PROX/input.h
VNFs/DPPD-PROX/lconf.c
VNFs/DPPD-PROX/log.c
VNFs/DPPD-PROX/main.c
VNFs/DPPD-PROX/msr.c
VNFs/DPPD-PROX/packet_utils.c [new file with mode: 0644]
VNFs/DPPD-PROX/packet_utils.h [new file with mode: 0644]
VNFs/DPPD-PROX/prox_args.c
VNFs/DPPD-PROX/prox_cfg.h
VNFs/DPPD-PROX/prox_cksum.c
VNFs/DPPD-PROX/prox_port_cfg.c
VNFs/DPPD-PROX/prox_port_cfg.h
VNFs/DPPD-PROX/run.c
VNFs/DPPD-PROX/rx_pkt.c
VNFs/DPPD-PROX/rx_pkt.h
VNFs/DPPD-PROX/stats_core.c
VNFs/DPPD-PROX/task_base.h
VNFs/DPPD-PROX/task_init.c
VNFs/DPPD-PROX/task_init.h
VNFs/DPPD-PROX/tx_pkt.c
VNFs/DPPD-PROX/tx_pkt.h
VNFs/DPPD-PROX/version.h

index e9a4211..79bfdef 100644 (file)
@@ -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
index a09873c..1cf857d 100644 (file)
@@ -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
index 279bdad..488008d 100644 (file)
@@ -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;
index 9568847..388e362 100644 (file)
@@ -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);
                }
index 93acc62..adfb690 100644 (file)
@@ -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);
index eeb21b2..6688e8c 100644 (file)
@@ -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;
index 5fb3120..573cc9c 100644 (file)
@@ -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
index 106e19e..767cee1 100644 (file)
@@ -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)
index e5e43fc..f8c99ee 100644 (file)
@@ -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"
 #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)
 };
index 6f00ca1..5083fea 100644 (file)
@@ -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);
index 3f2ee0e..78c9e40 100644 (file)
@@ -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 = {
index 4abf84a..86640c6 100644 (file)
@@ -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 (file)
index 0000000..6bd4ea2
--- /dev/null
@@ -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 (file)
index 0000000..bc32182
--- /dev/null
@@ -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);
index 8e5a94c..516d3f6 100644 (file)
@@ -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 = {
index ef2fee0..b589051 100644 (file)
@@ -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_ */
index bb956bc..5eb5e4c 100644 (file)
@@ -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;
index 06f6b65..51d9498 100644 (file)
@@ -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_ */
index 88d8f4f..399c8a7 100644 (file)
@@ -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;
                        }
                }
index cd8ee00..7049a5e 100644 (file)
@@ -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 *);
index 28533c7..1c4dced 100644 (file)
@@ -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,11 +112,26 @@ 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);
@@ -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]);
+                       }
                }
        }
 }
index 194d4c7..8aa1e3a 100644 (file)
@@ -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 (file)
index 0000000..c22183b
--- /dev/null
@@ -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 (file)
index 0000000..0017a89
--- /dev/null
@@ -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);
index 2703c22..fd8ea52 100644 (file)
@@ -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);
        }
index a7d0e7e..ed54ecc 100644 (file)
@@ -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
 
index b69c06f..9a05097 100644 (file)
@@ -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);
        }
index 7e0c2c7..d9ce82d 100644 (file)
@@ -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 {
index 1761618..370b045 100644 (file)
@@ -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>
 
index 971d714..3abdb81 100644 (file)
@@ -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;
+                       }
                }
        }
 
index a6c1fd1..ec698d9 100644 (file)
 #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 */
index 57b948e..6d8f412 100644 (file)
 
 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_ */
index 845399e..34a9f74 100644 (file)
@@ -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) {
index b2fab2f..62841e9 100644 (file)
@@ -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)
index 6d9c7b3..3af0db2 100644 (file)
@@ -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;
index e1f5ce1..86a9521 100644 (file)
@@ -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);
 
index c6f6010..9ada51c 100644 (file)
@@ -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);
+       }
+}
index 798797a..e8caed5 100644 (file)
@@ -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_ */
index b906b14..a1d0123 100644 (file)
@@ -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