summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorLuc Provoost <luc.provoost@intel.com>2021-02-01 14:04:01 +0100
committerLuc Provoost <luc.provoost@intel.com>2021-02-10 11:02:06 +0100
commitb7541865102edde8377d3965df658da8bd638a62 (patch)
tree801fd0920f854c1f89f18591615474495ff2d66f
parentc6e1493ced84fa82f689dfe88485a300dfb59183 (diff)
Expand mirror functionality
In order to deal with non-symmetrical load, the mirror function can now change the packet size of each packet it receives. It can also send the incoming packet multiple times on each of the tx ports. To support this feature, 2 new parameters in the cfg file have been added for the mirror mode: - multiplier: specifies how many times a packet needs to be sent on each tx port. Default is 1. - mirror_size: the size of the packets that need to be sent. This will just change (increase) the packet size of each incoming packet. If not specified or invalid value (e.g. <64), the size will not be changed. The packet size will only be changed for IPv4 UDP and IPv4 TCP. Note that these parameters have no effect on the mirror copy submode. Change-Id: Ic46b52abdd80ed51cffee667bd04ade9ec23ff6d Signed-off-by: Luc Provoost <luc.provoost@intel.com>
-rw-r--r--VNFs/DPPD-PROX/handle_mirror.c43
-rw-r--r--VNFs/DPPD-PROX/prox_args.c46
-rw-r--r--VNFs/DPPD-PROX/task_init.h2
3 files changed, 67 insertions, 24 deletions
diff --git a/VNFs/DPPD-PROX/handle_mirror.c b/VNFs/DPPD-PROX/handle_mirror.c
index 894ea799..8e6eb6d4 100644
--- a/VNFs/DPPD-PROX/handle_mirror.c
+++ b/VNFs/DPPD-PROX/handle_mirror.c
@@ -24,6 +24,8 @@
#include "log.h"
#include "prox_port_cfg.h"
#include "quit.h"
+#include "prox_cksum.h"
+#include "prefetch.h"
/* Task that sends packets to multiple outputs. Note that in case of n
outputs, the output packet rate is n times the input packet
@@ -34,7 +36,9 @@
way to resolve this is to create deep copies of the packet. */
struct task_mirror {
struct task_base base;
- uint32_t n_dests;
+ uint32_t n_dests;
+ uint32_t multiplier;
+ uint32_t mirror_size;
};
struct task_mirror_copy {
@@ -55,14 +59,40 @@ static int handle_mirror_bulk(struct task_base *tbase, struct rte_mbuf **mbufs,
multiple times, the pointers are copied first. This copy is
used in each call to tx_pkt below. */
rte_memcpy(mbufs2, mbufs, sizeof(mbufs[0]) * n_pkts);
-
+ /* prefetch for optimization */
+ prox_rte_ether_hdr * hdr[MAX_PKT_BURST];
+ //for (uint16_t i = 0; i < n_pkts; ++i) {
+ // PREFETCH0(mbufs2[i]);
+ //}
+ for (uint16_t j = 0; j < n_pkts; ++j) {
+ hdr[j] = rte_pktmbuf_mtod(mbufs2[j], prox_rte_ether_hdr *);
+ PREFETCH0(hdr[j]);
+ }
for (uint16_t j = 0; j < n_pkts; ++j) {
- rte_pktmbuf_refcnt_update(mbufs2[j], task->n_dests - 1);
+ rte_pktmbuf_refcnt_update(mbufs2[j], (task->n_dests - 1) * task->multiplier);
+ prox_rte_ipv4_hdr *pip = (prox_rte_ipv4_hdr *) (hdr[j] + 1);
+ if ((task->mirror_size != 0) && (hdr[j]->ether_type == RTE_ETHER_TYPE_IPV4) && ((pip->next_proto_id == IPPROTO_UDP) || (pip->next_proto_id == IPPROTO_TCP))) {
+ rte_pktmbuf_pkt_len(mbufs2[j]) = task->mirror_size;
+ rte_pktmbuf_data_len(mbufs2[j]) = task->mirror_size;
+ pip->total_length = rte_bswap16(task->mirror_size-sizeof(prox_rte_ether_hdr));
+ pip->hdr_checksum = 0;
+ prox_ip_cksum_sw(pip);
+ int l4_len = task->mirror_size - sizeof(prox_rte_ether_hdr) - sizeof(prox_rte_ipv4_hdr);
+ if (pip->next_proto_id == IPPROTO_UDP) {
+ prox_rte_udp_hdr *udp = (prox_rte_udp_hdr *)(((uint8_t *)pip) + sizeof(prox_rte_ipv4_hdr));
+ udp->dgram_len = rte_bswap16(l4_len);
+ prox_udp_cksum_sw(udp, l4_len, pip->src_addr, pip->dst_addr);
+ } else if (pip->next_proto_id == IPPROTO_TCP) {
+ prox_rte_tcp_hdr *tcp = (prox_rte_tcp_hdr *)(((uint8_t *)pip) + sizeof(prox_rte_ipv4_hdr));
+ prox_tcp_cksum_sw(tcp, l4_len, pip->src_addr, pip->dst_addr);
+ }
+ }
}
for (uint16_t j = 0; j < task->n_dests; ++j) {
memset(out, j, n_pkts);
-
- ret+= task->base.tx_pkt(&task->base, mbufs2, n_pkts, out);
+ for (uint16_t i = 0; i < task->multiplier; ++i) {
+ ret += task->base.tx_pkt(&task->base, mbufs2, n_pkts, out);
+ }
}
return ret;
}
@@ -110,8 +140,9 @@ static int handle_mirror_bulk_copy(struct task_base *tbase, struct rte_mbuf **mb
static void init_task_mirror(struct task_base *tbase, struct task_args *targ)
{
struct task_mirror *task = (struct task_mirror *)tbase;
-
task->n_dests = targ->nb_txports? targ->nb_txports : targ->nb_txrings;
+ task->multiplier = targ->multiplier? targ->multiplier : 1;
+ task->mirror_size = targ->mirror_size > 63? targ->mirror_size: 0;
}
static void init_task_mirror_copy(struct task_base *tbase, struct task_args *targ)
diff --git a/VNFs/DPPD-PROX/prox_args.c b/VNFs/DPPD-PROX/prox_args.c
index aa87100a..178126f6 100644
--- a/VNFs/DPPD-PROX/prox_args.c
+++ b/VNFs/DPPD-PROX/prox_args.c
@@ -1836,31 +1836,41 @@ static int get_core_cfg(unsigned sindex, char *str, void *data)
return parse_int(&targ->n_max_rules, pkey);
}
- if (STR_EQ(str, "tunnel hop limit")) {
- uint32_t val;
- int err = parse_int(&val, pkey);
- if (err) {
- return -1;
- }
- targ->tunnel_hop_limit = val;
- return 0;
- }
+ if (STR_EQ(str, "tunnel hop limit")) {
+ uint32_t val;
+ int err = parse_int(&val, pkey);
+ if (err) {
+ return -1;
+ }
+ targ->tunnel_hop_limit = val;
+ return 0;
+ }
- if (STR_EQ(str, "lookup port mask")) {
- uint32_t val;
- int err = parse_int(&val, pkey);
- if (err) {
- return -1;
- }
- targ->lookup_port_mask = val;
- return 0;
- }
+ if (STR_EQ(str, "lookup port mask")) {
+ uint32_t val;
+ int err = parse_int(&val, pkey);
+ if (err) {
+ return -1;
+ }
+ targ->lookup_port_mask = val;
+ return 0;
+ }
if (STR_EQ(str, "irq debug")) {
parse_int(&targ->irq_debug, pkey);
return 0;
}
+ if (STR_EQ(str, "multiplier")) {
+ parse_int(&targ->multiplier, pkey);
+ return 0;
+ }
+
+ if (STR_EQ(str, "mirror size")) {
+ parse_int(&targ->mirror_size, pkey);
+ return 0;
+ }
+
set_errf("Option '%s' is not known", str);
/* fail on unknown keys */
return -1;
diff --git a/VNFs/DPPD-PROX/task_init.h b/VNFs/DPPD-PROX/task_init.h
index d56837d6..54c30304 100644
--- a/VNFs/DPPD-PROX/task_init.h
+++ b/VNFs/DPPD-PROX/task_init.h
@@ -246,6 +246,8 @@ struct task_args {
uint32_t igmp_address;
uint32_t imix_nb_pkts;
uint32_t imix_pkt_sizes[MAX_IMIX_PKTS];
+ uint32_t multiplier;
+ uint32_t mirror_size;
};
/* Return the first port that is reachable through the task. If the