From 970c2eb4d810877fd9f3df7671f8f6771cf48e44 Mon Sep 17 00:00:00 2001 From: Robert Johnson Date: Mon, 25 Jun 2018 21:35:14 +0000 Subject: [PATCH 5/5] app/testpmd: added spp-eni-addr-swap to fwd_engines spp-eni-addr-swap swaps the source and dest Ethernet MAC and IP addresses before forwarding to an ENI. It is currently used for testing the AWS net/spp and net/ena PMDs with the AWS Streaming Data Engine in chained forwarding mode. Signed-off-by: Robert Johnson --- app/test-pmd/Makefile | 1 + app/test-pmd/spp_eni_addr_swap.c | 200 +++++++++++++++++++++++++++++++++++++++ app/test-pmd/testpmd.c | 3 + app/test-pmd/testpmd.h | 3 + 4 files changed, 207 insertions(+) create mode 100644 app/test-pmd/spp_eni_addr_swap.c diff --git a/app/test-pmd/Makefile b/app/test-pmd/Makefile index 886b665..3982374 100644 --- a/app/test-pmd/Makefile +++ b/app/test-pmd/Makefile @@ -36,6 +36,7 @@ SRCS-y += icmpecho.c SRCS-y += noisy_vnf.c SRCS-$(CONFIG_RTE_LIBRTE_IEEE1588) += ieee1588fwd.c SRCS-$(CONFIG_RTE_LIBRTE_BPF) += bpf_cmd.c SRCS-y += util.c SRCS-$(CONFIG_RTE_LIBRTE_SPP_PMD) += spp_loop_fwd.c +SRCS-$(CONFIG_RTE_LIBRTE_SPP_PMD) += spp_eni_addr_swap.c ifeq ($(CONFIG_RTE_LIBRTE_PMD_SOFTNIC), y) SRCS-y += softnicfwd.c diff --git a/app/test-pmd/spp_eni_addr_swap.c b/app/test-pmd/spp_eni_addr_swap.c new file mode 100644 index 0000000..c3f7b97 --- /dev/null +++ b/app/test-pmd/spp_eni_addr_swap.c @@ -0,0 +1,200 @@ +/* + * Copyright 2015-2018 Amazon.com, Inc. or its affiliates. All Rights Reserved. + * + * Licensed under the Apache License, Version 2.0 (the "License"). You may + * not use this file except in compliance with the License. A copy of the + * License is located at + * + * http://aws.amazon.com/apache2.0/ + * + * or in the "license" file accompanying this file. This file 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 +#include +#include +#include +#include +#include +#include + +#include +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include "testpmd.h" + +#define IPV6_ADDR_SIZE 16 + +/* + * SPP-ENI chaining address swap forwarding mode: Swap the source and the + * destination Ethernet addresses and source and destination IP addresses + * of packets before forwarding them. + * + * NOTE: + * The SPP Virtual Ethernet device defaults to a zero mac address. + * We use this fact to know when to swap addresses for ENI (e.g. when + * macaddr[0] != 0, swap addresses). + */ +static inline void +ipv4_addr_swap(struct rte_ipv4_hdr *ipv4_hdr) +{ + uint32_t ipv4_addr_tmp; + + ipv4_addr_tmp = ipv4_hdr->src_addr; + ipv4_hdr->src_addr = ipv4_hdr->dst_addr; + ipv4_hdr->dst_addr = ipv4_addr_tmp; +} + +static inline void +ipv6_addr_swap(struct rte_ipv6_hdr *ipv6_hdr) +{ + uint8_t ipv6_addr_tmp[IPV6_ADDR_SIZE]; + + memcpy(ipv6_addr_tmp, ipv6_hdr->src_addr, IPV6_ADDR_SIZE); + memcpy(ipv6_hdr->src_addr, ipv6_hdr->dst_addr, IPV6_ADDR_SIZE); + memcpy(ipv6_hdr->dst_addr, ipv6_addr_tmp, IPV6_ADDR_SIZE); +} + +static void +pkt_burst_spp_eni_addr_swap(struct fwd_stream *fs) +{ + struct rte_mbuf *pkts_burst[MAX_PKT_BURST]; + struct rte_port *txp; + struct rte_mbuf *mb; + struct rte_ether_hdr *eth_hdr; + struct rte_ether_addr addr; + uint16_t nb_rx; + uint16_t nb_tx; + uint16_t i; + uint32_t retry; + uint64_t ol_flags = 0; + uint64_t tx_offloads; + +#ifdef RTE_TEST_PMD_RECORD_CORE_CYCLES + uint64_t start_tsc; + uint64_t end_tsc; + uint64_t core_cycles; +#endif + struct rte_ipv4_hdr *ipv4_hdr; + struct rte_ipv6_hdr *ipv6_hdr; + +#ifdef RTE_TEST_PMD_RECORD_CORE_CYCLES + start_tsc = rte_rdtsc(); +#endif + + /* + * Receive a burst of packets and forward them. + */ + nb_rx = rte_eth_rx_burst(fs->rx_port, fs->rx_queue, pkts_burst, + nb_pkt_per_burst); + if (unlikely(nb_rx == 0)) + return; + +#ifdef RTE_TEST_PMD_RECORD_BURST_STATS + fs->rx_burst_stats.pkt_burst_spread[nb_rx]++; +#endif + fs->rx_packets += nb_rx; + txp = &ports[fs->tx_port]; + tx_offloads = txp->dev_conf.txmode.offloads; + if (tx_offloads & DEV_TX_OFFLOAD_VLAN_INSERT) + ol_flags = PKT_TX_VLAN_PKT; + if (tx_offloads & DEV_TX_OFFLOAD_QINQ_INSERT) + ol_flags |= PKT_TX_QINQ_PKT; + if (tx_offloads & DEV_TX_OFFLOAD_MACSEC_INSERT) + ol_flags |= PKT_TX_MACSEC; + for (i = 0; i < nb_rx; i++) { + if (likely(i < nb_rx - 1)) + rte_prefetch0(rte_pktmbuf_mtod(pkts_burst[i + 1], + void *)); + mb = pkts_burst[i]; + eth_hdr = rte_pktmbuf_mtod(mb, struct rte_ether_hdr *); + + /* Do not swap for SPP PMD (default MAC addr==0) */ + if (txp->eth_addr.addr_bytes[0] != 0) { + /* Swap dest and src mac addresses. */ + rte_ether_addr_copy(ð_hdr->d_addr, &addr); + rte_ether_addr_copy(ð_hdr->s_addr, ð_hdr->d_addr); + rte_ether_addr_copy(&addr, ð_hdr->s_addr); + + if (likely(eth_hdr->ether_type == + htons(RTE_ETHER_TYPE_IPV4))) { + /* Swap dest and src IPv4 addresses */ + ipv4_hdr = (struct rte_ipv4_hdr *)(eth_hdr + 1); + ipv4_addr_swap(ipv4_hdr); + } else if (eth_hdr->ether_type == + htons(RTE_ETHER_TYPE_IPV6)) { + /* Swap dest and src IPv6 addresses */ + ipv6_hdr = (struct rte_ipv6_hdr *)(eth_hdr + 1); + ipv6_addr_swap(ipv6_hdr); + } + } + + mb->ol_flags &= IND_ATTACHED_MBUF | EXT_ATTACHED_MBUF; + mb->ol_flags |= ol_flags; + mb->l2_len = sizeof(struct rte_ether_hdr); + mb->l3_len = sizeof(struct rte_ipv4_hdr); + mb->vlan_tci = txp->tx_vlan_id; + mb->vlan_tci_outer = txp->tx_vlan_id_outer; + } + nb_tx = rte_eth_tx_burst(fs->tx_port, fs->tx_queue, pkts_burst, nb_rx); + /* + * Retry if necessary + */ + if (unlikely(nb_tx < nb_rx) && fs->retry_enabled) { + retry = 0; + while (nb_tx < nb_rx && retry++ < burst_tx_retry_num) { + rte_delay_us(burst_tx_delay_time); + nb_tx += rte_eth_tx_burst(fs->tx_port, fs->tx_queue, + &pkts_burst[nb_tx], + nb_rx - nb_tx); + } + } + fs->tx_packets += nb_tx; +#ifdef RTE_TEST_PMD_RECORD_BURST_STATS + fs->tx_burst_stats.pkt_burst_spread[nb_tx]++; +#endif + if (unlikely(nb_tx < nb_rx)) { + fs->fwd_dropped += (nb_rx - nb_tx); + do + rte_pktmbuf_free(pkts_burst[nb_tx]); + while (++nb_tx < nb_rx); + } +#ifdef RTE_TEST_PMD_RECORD_CORE_CYCLES + end_tsc = rte_rdtsc(); + core_cycles = (end_tsc - start_tsc); + fs->core_cycles = (uint64_t)(fs->core_cycles + core_cycles); +#endif +} + +struct fwd_engine spp_eni_addr_swap_engine = { + .fwd_mode_name = "spp-eni-addr-swap", + .port_fwd_begin = NULL, + .port_fwd_end = NULL, + .packet_fwd = pkt_burst_spp_eni_addr_swap, +}; diff --git a/app/test-pmd/testpmd.c b/app/test-pmd/testpmd.c index f124f1e..c22b093 100644 --- a/app/test-pmd/testpmd.c +++ b/app/test-pmd/testpmd.c @@ -188,6 +188,9 @@ struct fwd_engine * fwd_engines[] = { #ifdef RTE_LIBRTE_SPP_PMD &spp_loop_fwd_engine, #endif +#ifdef RTE_LIBRTE_SPP_PMD + &spp_eni_addr_swap_engine, +#endif NULL, }; diff --git a/app/test-pmd/testpmd.h b/app/test-pmd/testpmd.h index 9cf0d50dd6..bf7a62b3ba 100644 --- a/app/test-pmd/testpmd.h +++ b/app/test-pmd/testpmd.h @@ -280,6 +280,9 @@ extern struct fwd_engine ieee1588_fwd_engine; #ifdef RTE_LIBRTE_SPP_PMD extern struct fwd_engine spp_loop_fwd_engine; #endif +#ifdef RTE_LIBRTE_SPP_PMD +extern struct fwd_engine spp_eni_addr_swap_engine; +#endif extern struct fwd_engine * fwd_engines[]; /**< NULL terminated array. */ extern cmdline_parse_inst_t cmd_set_raw; -- 1.8.3.1