There are multiple instances in the DPDK app folder where we set up an
IP header and then compute the checksum field by direct addition of
nine uint16_t values in the header (20 bytes less the cksum field).
The existing rte_ip.h checksum function is more general than necessary
here and requires that the checksum field is already set to zero -
rather than having it skipped.

Fix the code duplication present in the apps by creating a new
rte_ipv4_cksum_simple function - taking the code from the existing
testpmd icmpecho.c file - and using that in app/test, testpmd and
testeventdev.

Within that new function, we can adjust slightly how the typecasting to
uint16_t is done, and thereby ensure that the app can all be compiled
without -Wno-address-of-packed-member compiler flag.

Signed-off-by: Bruce Richardson <bruce.richard...@intel.com>
Acked-by: Stephen Hemminger <step...@networkplumber.org>
Acked-by: Morten Brørup <m...@smartsharesystems.com>
---
 app/test-eventdev/test_pipeline_common.c | 25 +-----------
 app/test-pmd/icmpecho.c                  | 23 +----------
 app/test-pmd/txonly.c                    | 22 +----------
 app/test/packet_burst_generator.c        | 49 +-----------------------
 app/test/test_reassembly_perf.c          | 29 +-------------
 lib/net/rte_ip4.h                        | 32 ++++++++++++++++
 6 files changed, 38 insertions(+), 142 deletions(-)

diff --git a/app/test-eventdev/test_pipeline_common.c 
b/app/test-eventdev/test_pipeline_common.c
index b111690b7c..204117ef7f 100644
--- a/app/test-eventdev/test_pipeline_common.c
+++ b/app/test-eventdev/test_pipeline_common.c
@@ -74,8 +74,6 @@ setup_pkt_udp_ip_headers(struct rte_ipv4_hdr *ip_hdr,
                         struct rte_udp_hdr *udp_hdr, uint16_t pkt_data_len,
                         uint8_t port, uint8_t flow)
 {
-       uint16_t *ptr16;
-       uint32_t ip_cksum;
        uint16_t pkt_len;
 
        /*
@@ -104,28 +102,7 @@ setup_pkt_udp_ip_headers(struct rte_ipv4_hdr *ip_hdr,
        /*
         * Compute IP header checksum.
         */
-       ptr16 = (unaligned_uint16_t *)ip_hdr;
-       ip_cksum = 0;
-       ip_cksum += ptr16[0];
-       ip_cksum += ptr16[1];
-       ip_cksum += ptr16[2];
-       ip_cksum += ptr16[3];
-       ip_cksum += ptr16[4];
-       ip_cksum += ptr16[6];
-       ip_cksum += ptr16[7];
-       ip_cksum += ptr16[8];
-       ip_cksum += ptr16[9];
-
-       /*
-        * Reduce 32 bit checksum to 16 bits and complement it.
-        */
-       ip_cksum = ((ip_cksum & 0xFFFF0000) >> 16) + (ip_cksum & 0x0000FFFF);
-       if (ip_cksum > 65535)
-               ip_cksum -= 65535;
-       ip_cksum = (~ip_cksum) & 0x0000FFFF;
-       if (ip_cksum == 0)
-               ip_cksum = 0xFFFF;
-       ip_hdr->hdr_checksum = (uint16_t)ip_cksum;
+       ip_hdr->hdr_checksum = rte_ipv4_cksum_simple(ip_hdr);
 }
 
 static void
diff --git a/app/test-pmd/icmpecho.c b/app/test-pmd/icmpecho.c
index 4ef23ae67a..c87b7a80df 100644
--- a/app/test-pmd/icmpecho.c
+++ b/app/test-pmd/icmpecho.c
@@ -241,27 +241,6 @@ ipv4_addr_dump(const char *what, uint32_t be_ipv4_addr)
        printf("%s", buf);
 }
 
-static uint16_t
-ipv4_hdr_cksum(struct rte_ipv4_hdr *ip_h)
-{
-       uint16_t *v16_h;
-       uint32_t ip_cksum;
-
-       /*
-        * Compute the sum of successive 16-bit words of the IPv4 header,
-        * skipping the checksum field of the header.
-        */
-       v16_h = (unaligned_uint16_t *) ip_h;
-       ip_cksum = v16_h[0] + v16_h[1] + v16_h[2] + v16_h[3] +
-               v16_h[4] + v16_h[6] + v16_h[7] + v16_h[8] + v16_h[9];
-
-       /* reduce 32 bit checksum to 16 bits and complement it */
-       ip_cksum = (ip_cksum & 0xffff) + (ip_cksum >> 16);
-       ip_cksum = (ip_cksum & 0xffff) + (ip_cksum >> 16);
-       ip_cksum = (~ip_cksum) & 0x0000FFFF;
-       return (ip_cksum == 0) ? 0xFFFF : (uint16_t) ip_cksum;
-}
-
 #define is_multicast_ipv4_addr(ipv4_addr) \
        (((rte_be_to_cpu_32((ipv4_addr)) >> 24) & 0x000000FF) == 0xE0)
 
@@ -458,7 +437,7 @@ reply_to_icmp_echo_rqsts(struct fwd_stream *fs)
                                ip_src = (ip_src & 0xFFFFFFFC) | 0x00000001;
                        ip_h->src_addr = rte_cpu_to_be_32(ip_src);
                        ip_h->dst_addr = ip_addr;
-                       ip_h->hdr_checksum = ipv4_hdr_cksum(ip_h);
+                       ip_h->hdr_checksum = rte_ipv4_cksum_simple(ip_h);
                } else {
                        ip_h->src_addr = ip_h->dst_addr;
                        ip_h->dst_addr = ip_addr;
diff --git a/app/test-pmd/txonly.c b/app/test-pmd/txonly.c
index c2b88764be..59d821a22d 100644
--- a/app/test-pmd/txonly.c
+++ b/app/test-pmd/txonly.c
@@ -106,8 +106,6 @@ setup_pkt_udp_ip_headers(struct rte_ipv4_hdr *ip_hdr,
                         struct rte_udp_hdr *udp_hdr,
                         uint16_t pkt_data_len)
 {
-       uint16_t *ptr16;
-       uint32_t ip_cksum;
        uint16_t pkt_len;
 
        /*
@@ -136,25 +134,7 @@ setup_pkt_udp_ip_headers(struct rte_ipv4_hdr *ip_hdr,
        /*
         * Compute IP header checksum.
         */
-       ptr16 = (unaligned_uint16_t*) ip_hdr;
-       ip_cksum = 0;
-       ip_cksum += ptr16[0]; ip_cksum += ptr16[1];
-       ip_cksum += ptr16[2]; ip_cksum += ptr16[3];
-       ip_cksum += ptr16[4];
-       ip_cksum += ptr16[6]; ip_cksum += ptr16[7];
-       ip_cksum += ptr16[8]; ip_cksum += ptr16[9];
-
-       /*
-        * Reduce 32 bit checksum to 16 bits and complement it.
-        */
-       ip_cksum = ((ip_cksum & 0xFFFF0000) >> 16) +
-               (ip_cksum & 0x0000FFFF);
-       if (ip_cksum > 65535)
-               ip_cksum -= 65535;
-       ip_cksum = (~ip_cksum) & 0x0000FFFF;
-       if (ip_cksum == 0)
-               ip_cksum = 0xFFFF;
-       ip_hdr->hdr_checksum = (uint16_t) ip_cksum;
+       ip_hdr->hdr_checksum = rte_ipv4_cksum_simple(ip_hdr);
 }
 
 static inline void
diff --git a/app/test/packet_burst_generator.c 
b/app/test/packet_burst_generator.c
index c9ff5257f0..4c17737739 100644
--- a/app/test/packet_burst_generator.c
+++ b/app/test/packet_burst_generator.c
@@ -159,8 +159,6 @@ initialize_ipv4_header(struct rte_ipv4_hdr *ip_hdr, 
uint32_t src_addr,
                uint32_t dst_addr, uint16_t pkt_data_len)
 {
        uint16_t pkt_len;
-       unaligned_uint16_t *ptr16;
-       uint32_t ip_cksum;
 
        /*
         * Initialize IP header.
@@ -177,27 +175,7 @@ initialize_ipv4_header(struct rte_ipv4_hdr *ip_hdr, 
uint32_t src_addr,
        ip_hdr->src_addr = rte_cpu_to_be_32(src_addr);
        ip_hdr->dst_addr = rte_cpu_to_be_32(dst_addr);
 
-       /*
-        * Compute IP header checksum.
-        */
-       ptr16 = (unaligned_uint16_t *)ip_hdr;
-       ip_cksum = 0;
-       ip_cksum += ptr16[0]; ip_cksum += ptr16[1];
-       ip_cksum += ptr16[2]; ip_cksum += ptr16[3];
-       ip_cksum += ptr16[4];
-       ip_cksum += ptr16[6]; ip_cksum += ptr16[7];
-       ip_cksum += ptr16[8]; ip_cksum += ptr16[9];
-
-       /*
-        * Reduce 32 bit checksum to 16 bits and complement it.
-        */
-       ip_cksum = ((ip_cksum & 0xFFFF0000) >> 16) +
-               (ip_cksum & 0x0000FFFF);
-       ip_cksum %= 65536;
-       ip_cksum = (~ip_cksum) & 0x0000FFFF;
-       if (ip_cksum == 0)
-               ip_cksum = 0xFFFF;
-       ip_hdr->hdr_checksum = (uint16_t) ip_cksum;
+       ip_hdr->hdr_checksum = rte_ipv4_cksum_simple(ip_hdr);
 
        return pkt_len;
 }
@@ -207,8 +185,6 @@ initialize_ipv4_header_proto(struct rte_ipv4_hdr *ip_hdr, 
uint32_t src_addr,
                uint32_t dst_addr, uint16_t pkt_data_len, uint8_t proto)
 {
        uint16_t pkt_len;
-       unaligned_uint16_t *ptr16;
-       uint32_t ip_cksum;
 
        /*
         * Initialize IP header.
@@ -224,28 +200,7 @@ initialize_ipv4_header_proto(struct rte_ipv4_hdr *ip_hdr, 
uint32_t src_addr,
        ip_hdr->total_length   = rte_cpu_to_be_16(pkt_len);
        ip_hdr->src_addr = rte_cpu_to_be_32(src_addr);
        ip_hdr->dst_addr = rte_cpu_to_be_32(dst_addr);
-
-       /*
-        * Compute IP header checksum.
-        */
-       ptr16 = (unaligned_uint16_t *)ip_hdr;
-       ip_cksum = 0;
-       ip_cksum += ptr16[0]; ip_cksum += ptr16[1];
-       ip_cksum += ptr16[2]; ip_cksum += ptr16[3];
-       ip_cksum += ptr16[4];
-       ip_cksum += ptr16[6]; ip_cksum += ptr16[7];
-       ip_cksum += ptr16[8]; ip_cksum += ptr16[9];
-
-       /*
-        * Reduce 32 bit checksum to 16 bits and complement it.
-        */
-       ip_cksum = ((ip_cksum & 0xFFFF0000) >> 16) +
-               (ip_cksum & 0x0000FFFF);
-       ip_cksum %= 65536;
-       ip_cksum = (~ip_cksum) & 0x0000FFFF;
-       if (ip_cksum == 0)
-               ip_cksum = 0xFFFF;
-       ip_hdr->hdr_checksum = (uint16_t) ip_cksum;
+       ip_hdr->hdr_checksum = rte_ipv4_cksum_simple(ip_hdr);
 
        return pkt_len;
 }
diff --git a/app/test/test_reassembly_perf.c b/app/test/test_reassembly_perf.c
index 245ab3fa7d..69cf029468 100644
--- a/app/test/test_reassembly_perf.c
+++ b/app/test/test_reassembly_perf.c
@@ -136,9 +136,7 @@ ipv4_frag_fill_data(struct rte_mbuf **mbuf, uint8_t 
nb_frags, uint32_t flow_id,
        for (i = 0; i < nb_frags; i++) {
                struct rte_mbuf *frag = mbuf[i];
                uint16_t frag_offset = 0;
-               uint32_t ip_cksum;
                uint16_t pkt_len;
-               uint16_t *ptr16;
 
                frag_offset = i * (frag_len / 8);
 
@@ -189,32 +187,7 @@ ipv4_frag_fill_data(struct rte_mbuf **mbuf, uint8_t 
nb_frags, uint32_t flow_id,
                ip_hdr->src_addr = rte_cpu_to_be_32(IP_SRC_ADDR(flow_id));
                ip_hdr->dst_addr = rte_cpu_to_be_32(IP_DST_ADDR(flow_id));
 
-               /*
-                * Compute IP header checksum.
-                */
-               ptr16 = (unaligned_uint16_t *)ip_hdr;
-               ip_cksum = 0;
-               ip_cksum += ptr16[0];
-               ip_cksum += ptr16[1];
-               ip_cksum += ptr16[2];
-               ip_cksum += ptr16[3];
-               ip_cksum += ptr16[4];
-               ip_cksum += ptr16[6];
-               ip_cksum += ptr16[7];
-               ip_cksum += ptr16[8];
-               ip_cksum += ptr16[9];
-
-               /*
-                * Reduce 32 bit checksum to 16 bits and complement it.
-                */
-               ip_cksum = ((ip_cksum & 0xFFFF0000) >> 16) +
-                          (ip_cksum & 0x0000FFFF);
-               if (ip_cksum > 65535)
-                       ip_cksum -= 65535;
-               ip_cksum = (~ip_cksum) & 0x0000FFFF;
-               if (ip_cksum == 0)
-                       ip_cksum = 0xFFFF;
-               ip_hdr->hdr_checksum = (uint16_t)ip_cksum;
+               ip_hdr->hdr_checksum = (uint16_t)rte_ipv4_cksum_simple(ip_hdr);
 
                frag->data_len = sizeof(struct rte_ether_hdr) + pkt_len;
                frag->pkt_len = frag->data_len;
diff --git a/lib/net/rte_ip4.h b/lib/net/rte_ip4.h
index d9840b3cff..3dc0c5a017 100644
--- a/lib/net/rte_ip4.h
+++ b/lib/net/rte_ip4.h
@@ -163,6 +163,38 @@ rte_ipv4_cksum(const struct rte_ipv4_hdr *ipv4_hdr)
        return (uint16_t)~cksum;
 }
 
+/**
+ * Process the IPv4 checksum of an IPv4 header without any extensions.
+ *
+ * The checksum field does NOT have to be set by the caller, the field
+ * is skipped by the calculation.
+ *
+ * @param ipv4_hdr
+ *   The pointer to the contiguous IPv4 header.
+ * @return
+ *   The complemented checksum to set in the IP packet.
+ */
+__rte_experimental
+static inline uint16_t
+rte_ipv4_cksum_simple(const struct rte_ipv4_hdr *ipv4_hdr)
+{
+       const uint16_t *v16_h;
+       uint32_t ip_cksum;
+
+       /*
+        * Compute the sum of successive 16-bit words of the IPv4 header,
+        * skipping the checksum field of the header.
+        */
+       v16_h = (const unaligned_uint16_t *)&ipv4_hdr->version_ihl;
+       ip_cksum = v16_h[0] + v16_h[1] + v16_h[2] + v16_h[3] +
+               v16_h[4] + v16_h[6] + v16_h[7] + v16_h[8] + v16_h[9];
+
+       /* reduce 32 bit checksum to 16 bits and complement it */
+       ip_cksum = (ip_cksum & 0xffff) + (ip_cksum >> 16);
+       ip_cksum = (ip_cksum & 0xffff) + (ip_cksum >> 16);
+       return (uint16_t)(~ip_cksum);
+}
+
 /**
  * Process the pseudo-header checksum of an IPv4 header.
  *
-- 
2.43.0

Reply via email to