app/testpmd: fix packet header in txonly mode
authorChengchang Tang <tangchengchang@huawei.com>
Fri, 25 Sep 2020 12:47:17 +0000 (20:47 +0800)
committerFerruh Yigit <ferruh.yigit@intel.com>
Wed, 30 Sep 2020 17:19:13 +0000 (19:19 +0200)
In txonly forward mode, the packet header is fixed by the initial
setting, including the packet length and checksum. So when the packets
varies, this may cause a packet header error. Currently, there are two
methods in txonly mode to randomly change the packets.
1. Set txsplit random and txpkts (x[,y]*), the number of segments
   each packets will be a random value between 1 and total number of
   segments determined by txpkts settings.
   The step as follows:
     a) ./testpmd -w xxx -l xx -n 4 -- -i --disable-device-start
     b) port config 0 tx_offload multi_segs on
     c) set fwd txonly
     d) set txsplit rand
     e) set txpkts 2048,2048,2048,2048
     f) start
The nb_segs of the packets sent by testpmd will be 1~4. The real packet
length will be 2048, 4096, 6144 and 8192. But in fact the packet length
in ip header and udp header will be fixed by 8178 and 8158.

2. Set txonly-multi-flow. the ip address will be varied to generate
   multiple flow.
   The step as follows:
     a) ./testpmd -w xxx -l xx -n 4 -- -i --txonly-multi-flow
     b) set fwd txonly
     c) start
The ip address of each pkts will change randomly, but since the header
is fixed, the checksum may be a error value.

Therefore, this patch adds a function to update the packet length and
check sum in the pkts header when the txsplit mode is set to rand or
multi-flow is set.

Fixes: 82010ef55e7c ("app/testpmd: make txonly mode generate multiple flows")
Fixes: 79bec05b32b7 ("app/testpmd: add ability to split outgoing packets")
Cc: stable@dpdk.org
Signed-off-by: Chengchang Tang <tangchengchang@huawei.com>
Signed-off-by: Wei Hu (Xavier) <xavier.huwei@huawei.com>
Reviewed-by: Ferruh Yigit <ferruh.yigit@intel.com>
app/test-pmd/txonly.c

index 45def72..d55ee7c 100644 (file)
@@ -156,6 +156,34 @@ setup_pkt_udp_ip_headers(struct rte_ipv4_hdr *ip_hdr,
        ip_hdr->hdr_checksum = (uint16_t) ip_cksum;
 }
 
+static inline void
+update_pkt_header(struct rte_mbuf *pkt, uint32_t total_pkt_len)
+{
+       struct rte_ipv4_hdr *ip_hdr;
+       struct rte_udp_hdr *udp_hdr;
+       uint16_t pkt_data_len;
+       uint16_t pkt_len;
+
+       pkt_data_len = (uint16_t) (total_pkt_len - (
+                                       sizeof(struct rte_ether_hdr) +
+                                       sizeof(struct rte_ipv4_hdr) +
+                                       sizeof(struct rte_udp_hdr)));
+       /* updata udp pkt length */
+       udp_hdr = rte_pktmbuf_mtod_offset(pkt, struct rte_udp_hdr *,
+                               sizeof(struct rte_ether_hdr) +
+                               sizeof(struct rte_ipv4_hdr));
+       pkt_len = (uint16_t) (pkt_data_len + sizeof(struct rte_udp_hdr));
+       udp_hdr->dgram_len = RTE_CPU_TO_BE_16(pkt_len);
+
+       /* updata ip pkt length and csum */
+       ip_hdr = rte_pktmbuf_mtod_offset(pkt, struct rte_ipv4_hdr *,
+                               sizeof(struct rte_ether_hdr));
+       ip_hdr->hdr_checksum = 0;
+       pkt_len = (uint16_t) (pkt_len + sizeof(struct rte_ipv4_hdr));
+       ip_hdr->total_length = RTE_CPU_TO_BE_16(pkt_len);
+       ip_hdr->hdr_checksum = rte_ipv4_cksum(ip_hdr);
+}
+
 static inline bool
 pkt_burst_prepare(struct rte_mbuf *pkt, struct rte_mempool *mbp,
                struct rte_ether_hdr *eth_hdr, const uint16_t vlan_tci,
@@ -223,6 +251,10 @@ pkt_burst_prepare(struct rte_mbuf *pkt, struct rte_mempool *mbp,
        copy_buf_to_pkt(&pkt_udp_hdr, sizeof(pkt_udp_hdr), pkt,
                        sizeof(struct rte_ether_hdr) +
                        sizeof(struct rte_ipv4_hdr));
+
+       if (unlikely(tx_pkt_split == TX_PKT_SPLIT_RND) || txonly_multi_flow)
+               update_pkt_header(pkt, pkt_len);
+
        if (unlikely(timestamp_enable)) {
                uint64_t skew = RTE_PER_LCORE(timestamp_qskew);
                struct {