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