diff options
author | Luc Provoost <luc.provoost@intel.com> | 2021-02-01 14:04:01 +0100 |
---|---|---|
committer | Luc Provoost <luc.provoost@intel.com> | 2021-02-10 11:02:06 +0100 |
commit | b7541865102edde8377d3965df658da8bd638a62 (patch) | |
tree | 801fd0920f854c1f89f18591615474495ff2d66f | |
parent | c6e1493ced84fa82f689dfe88485a300dfb59183 (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.c | 43 | ||||
-rw-r--r-- | VNFs/DPPD-PROX/prox_args.c | 46 | ||||
-rw-r--r-- | VNFs/DPPD-PROX/task_init.h | 2 |
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 |