[dpdk-dev] [PATCH] net: add rte_ipv4_hdr_len()

Michael Pfeiffer michael.pfeiffer at tu-ilmenau.de
Mon Oct 12 16:55:46 CEST 2020


Add a function to calculate the length of an IPv4 header as suggested
on the mailing list [1]. Call where appropriate.

[1] https://mails.dpdk.org/archives/dev/2020-October/184471.html

Suggested-by: Thomas Monjalon <thomas at monjalon.net>
Signed-off-by: Michael Pfeiffer <michael.pfeiffer at tu-ilmenau.de>
---
 app/test-pmd/5tswap.c              |  2 +-
 app/test-pmd/csumonly.c            |  2 +-
 drivers/net/hinic/hinic_pmd_tx.c   | 11 ++---------
 drivers/net/tap/rte_eth_tap.c      |  3 +--
 drivers/net/vmxnet3/vmxnet3_rxtx.c |  3 +--
 examples/l3fwd/l3fwd_em.c          |  3 +--
 lib/librte_net/rte_ip.h            | 24 +++++++++++++++++++-----
 lib/librte_net/rte_net.c           | 11 ++---------
 lib/librte_vhost/virtio_net.c      |  2 +-
 9 files changed, 29 insertions(+), 32 deletions(-)

diff --git a/app/test-pmd/5tswap.c b/app/test-pmd/5tswap.c
index 3cf1692ea..e8cef9623 100644
--- a/app/test-pmd/5tswap.c
+++ b/app/test-pmd/5tswap.c
@@ -142,7 +142,7 @@ pkt_burst_5tuple_swap(struct fwd_stream *fs)
 		if (proto == RTE_BE16(RTE_ETHER_TYPE_IPV4)) {
 			swap_ipv4(h.ipv4);
 			next_proto = h.ipv4->next_proto_id;
-			mb->l3_len = (h.ipv4->version_ihl & 0x0f) * 4;
+			mb->l3_len = rte_ipv4_hdr_len(h.ipv4);
 			h.byte += mb->l3_len;
 		} else if (proto == RTE_BE16(RTE_ETHER_TYPE_IPV6)) {
 			swap_ipv6(h.ipv6);
diff --git a/app/test-pmd/csumonly.c b/app/test-pmd/csumonly.c
index 7ece398bd..49943121a 100644
--- a/app/test-pmd/csumonly.c
+++ b/app/test-pmd/csumonly.c
@@ -103,7 +103,7 @@ parse_ipv4(struct rte_ipv4_hdr *ipv4_hdr, struct testpmd_offload_info *info)
 {
 	struct rte_tcp_hdr *tcp_hdr;
 
-	info->l3_len = (ipv4_hdr->version_ihl & 0x0f) * 4;
+	info->l3_len = rte_ipv4_hdr_len(ipv4_hdr);
 	info->l4_proto = ipv4_hdr->next_proto_id;
 
 	/* only fill l4_len for TCP, it's useful for TSO */
diff --git a/drivers/net/hinic/hinic_pmd_tx.c b/drivers/net/hinic/hinic_pmd_tx.c
index d9f251a32..2dd4fe184 100644
--- a/drivers/net/hinic/hinic_pmd_tx.c
+++ b/drivers/net/hinic/hinic_pmd_tx.c
@@ -23,7 +23,6 @@
 /* packet header and tx offload info */
 #define ETHER_LEN_NO_VLAN		14
 #define ETHER_LEN_WITH_VLAN		18
-#define HEADER_LEN_OFFSET		2
 #define VXLANLEN			8
 #define MAX_PLD_OFFSET			221
 #define MAX_SINGLE_SGE_SIZE		65536
@@ -714,7 +713,6 @@ hinic_ipv4_phdr_cksum(const struct rte_ipv4_hdr *ipv4_hdr, uint64_t ol_flags)
 		uint8_t  proto;    /* L4 protocol type. */
 		uint16_t len;      /* L4 length. */
 	} psd_hdr;
-	uint8_t ihl;
 
 	psd_hdr.src_addr = ipv4_hdr->src_addr;
 	psd_hdr.dst_addr = ipv4_hdr->dst_addr;
@@ -723,13 +721,9 @@ hinic_ipv4_phdr_cksum(const struct rte_ipv4_hdr *ipv4_hdr, uint64_t ol_flags)
 	if (ol_flags & PKT_TX_TCP_SEG) {
 		psd_hdr.len = 0;
 	} else {
-		/* ipv4_hdr->version_ihl is uint8_t big endian, ihl locates
-		 * lower 4 bits and unit is 4 bytes
-		 */
-		ihl = (ipv4_hdr->version_ihl & 0xF) << 2;
 		psd_hdr.len =
 		rte_cpu_to_be_16(rte_be_to_cpu_16(ipv4_hdr->total_length) -
-				 ihl);
+				 rte_ipv4_hdr_len(ipv4_hdr));
 	}
 	return rte_raw_cksum(&psd_hdr, sizeof(psd_hdr));
 }
@@ -803,8 +797,7 @@ static inline void hinic_analyze_tx_info(struct rte_mbuf *mbuf,
 
 	if (pkt_type == RTE_ETHER_TYPE_IPV4) {
 		ip4h = (struct rte_ipv4_hdr *)(hdr + off_info->outer_l2_len);
-		off_info->outer_l3_len = (ip4h->version_ihl & 0xf) <<
-					HEADER_LEN_OFFSET;
+		off_info->outer_l3_len = rte_ipv4_hdr_len(ip4h);
 	} else if (pkt_type == RTE_ETHER_TYPE_IPV6) {
 		/* not support ipv6 extension header */
 		off_info->outer_l3_len = sizeof(struct rte_ipv6_hdr);
diff --git a/drivers/net/tap/rte_eth_tap.c b/drivers/net/tap/rte_eth_tap.c
index b127ce62d..e592a469b 100644
--- a/drivers/net/tap/rte_eth_tap.c
+++ b/drivers/net/tap/rte_eth_tap.c
@@ -316,8 +316,7 @@ tap_verify_csum(struct rte_mbuf *mbuf)
 	if (l3 == RTE_PTYPE_L3_IPV4 || l3 == RTE_PTYPE_L3_IPV4_EXT) {
 		struct rte_ipv4_hdr *iph = l3_hdr;
 
-		/* ihl contains the number of 4-byte words in the header */
-		l3_len = 4 * (iph->version_ihl & 0xf);
+		l3_len = rte_ipv4_hdr_len(iph);
 		if (unlikely(l2_len + l3_len > rte_pktmbuf_data_len(mbuf)))
 			return;
 		/* check that the total length reported by header is not
diff --git a/drivers/net/vmxnet3/vmxnet3_rxtx.c b/drivers/net/vmxnet3/vmxnet3_rxtx.c
index 73e270f30..e10f9ee87 100644
--- a/drivers/net/vmxnet3/vmxnet3_rxtx.c
+++ b/drivers/net/vmxnet3/vmxnet3_rxtx.c
@@ -687,8 +687,7 @@ vmxnet3_guess_mss(struct vmxnet3_hw *hw, const Vmxnet3_RxCompDesc *rcd,
 					- sizeof(struct rte_tcp_hdr);
 
 		ipv4_hdr = (struct rte_ipv4_hdr *)(ptr + hlen);
-		hlen += (ipv4_hdr->version_ihl & RTE_IPV4_HDR_IHL_MASK) *
-				RTE_IPV4_IHL_MULTIPLIER;
+		hlen += rte_ipv4_hdr_len(ipv4_hdr);
 	} else if (rcd->v6) {
 		if (unlikely(slen < hlen + sizeof(struct rte_ipv6_hdr)))
 			return hw->mtu - sizeof(struct rte_ipv6_hdr) -
diff --git a/examples/l3fwd/l3fwd_em.c b/examples/l3fwd/l3fwd_em.c
index c529dcd3e..9996bfba3 100644
--- a/examples/l3fwd/l3fwd_em.c
+++ b/examples/l3fwd/l3fwd_em.c
@@ -579,8 +579,7 @@ em_parse_ptype(struct rte_mbuf *m)
 	l3 = (uint8_t *)eth_hdr + sizeof(struct rte_ether_hdr);
 	if (ether_type == rte_cpu_to_be_16(RTE_ETHER_TYPE_IPV4)) {
 		ipv4_hdr = (struct rte_ipv4_hdr *)l3;
-		hdr_len = (ipv4_hdr->version_ihl & RTE_IPV4_HDR_IHL_MASK) *
-			  RTE_IPV4_IHL_MULTIPLIER;
+		hdr_len = rte_ipv4_hdr_len(ipv4_hdr);
 		if (hdr_len == sizeof(struct rte_ipv4_hdr)) {
 			packet_type |= RTE_PTYPE_L3_IPV4;
 			if (ipv4_hdr->next_proto_id == IPPROTO_TCP)
diff --git a/lib/librte_net/rte_ip.h b/lib/librte_net/rte_ip.h
index bb55ebb6f..a5f241f33 100644
--- a/lib/librte_net/rte_ip.h
+++ b/lib/librte_net/rte_ip.h
@@ -103,6 +103,21 @@ struct rte_ipv4_hdr {
 #define RTE_IPV4_MIN_IHL    (0x5)
 #define RTE_IPV4_VHL_DEF    ((IPVERSION << 4) | RTE_IPV4_MIN_IHL)
 
+/**
+ * Get the length of an IPv4 header.
+ *
+ * @param ipv4_hdr
+ *   Pointer to the IPv4 header.
+ * @return
+ *   The length of the IPv4 header (with options if present) in bytes.
+ */
+static inline uint8_t
+rte_ipv4_hdr_len(const struct rte_ipv4_hdr *ipv4_hdr)
+{
+	return (uint8_t)((ipv4_hdr->version_ihl & RTE_IPV4_HDR_IHL_MASK) *
+		RTE_IPV4_IHL_MULTIPLIER);
+}
+
 /**
  * @internal Calculate a sum of all words in the buffer.
  * Helper routine for the rte_raw_cksum().
@@ -269,7 +284,7 @@ static inline uint16_t
 rte_ipv4_cksum(const struct rte_ipv4_hdr *ipv4_hdr)
 {
 	uint16_t cksum;
-	cksum = rte_raw_cksum(ipv4_hdr, (ipv4_hdr->version_ihl & 0xf) * 4);
+	cksum = rte_raw_cksum(ipv4_hdr, rte_ipv4_hdr_len(ipv4_hdr));
 	return (uint16_t)~cksum;
 }
 
@@ -303,7 +318,6 @@ rte_ipv4_phdr_cksum(const struct rte_ipv4_hdr *ipv4_hdr, uint64_t ol_flags)
 	} psd_hdr;
 
 	uint32_t l3_len;
-	uint8_t ip_hdr_len;
 
 	psd_hdr.src_addr = ipv4_hdr->src_addr;
 	psd_hdr.dst_addr = ipv4_hdr->dst_addr;
@@ -313,8 +327,8 @@ rte_ipv4_phdr_cksum(const struct rte_ipv4_hdr *ipv4_hdr, uint64_t ol_flags)
 		psd_hdr.len = 0;
 	} else {
 		l3_len = rte_be_to_cpu_16(ipv4_hdr->total_length);
-		ip_hdr_len = (ipv4_hdr->version_ihl & 0xf) * 4;
-		psd_hdr.len = rte_cpu_to_be_16((uint16_t)(l3_len - ip_hdr_len));
+		psd_hdr.len = rte_cpu_to_be_16((uint16_t)(l3_len -
+			rte_ipv4_hdr_len(ipv4_hdr)));
 	}
 	return rte_raw_cksum(&psd_hdr, sizeof(psd_hdr));
 }
@@ -339,7 +353,7 @@ rte_ipv4_udptcp_cksum(const struct rte_ipv4_hdr *ipv4_hdr, const void *l4_hdr)
 	uint32_t l3_len, l4_len;
 	uint8_t ip_hdr_len;
 
-	ip_hdr_len = (ipv4_hdr->version_ihl & 0xf) * 4;
+	ip_hdr_len = rte_ipv4_hdr_len(ipv4_hdr);
 	l3_len = rte_be_to_cpu_16(ipv4_hdr->total_length);
 	if (l3_len < ip_hdr_len)
 		return 0;
diff --git a/lib/librte_net/rte_net.c b/lib/librte_net/rte_net.c
index 6f45b1339..bfe500397 100644
--- a/lib/librte_net/rte_net.c
+++ b/lib/librte_net/rte_net.c
@@ -171,13 +171,6 @@ ptype_tunnel(uint16_t *proto, const struct rte_mbuf *m,
 	}
 }
 
-/* get the ipv4 header length */
-static uint8_t
-ip4_hlen(const struct rte_ipv4_hdr *hdr)
-{
-	return (hdr->version_ihl & 0xf) * 4;
-}
-
 /* parse ipv6 extended headers, update offset and return next proto */
 int
 rte_net_skip_ip6_ext(uint16_t proto, const struct rte_mbuf *m, uint32_t *off,
@@ -308,7 +301,7 @@ uint32_t rte_net_get_ptype(const struct rte_mbuf *m,
 			return pkt_type;
 
 		pkt_type |= ptype_l3_ip(ip4h->version_ihl);
-		hdr_lens->l3_len = ip4_hlen(ip4h);
+		hdr_lens->l3_len = rte_ipv4_hdr_len(ip4h);
 		off += hdr_lens->l3_len;
 
 		if ((layers & RTE_PTYPE_L4_MASK) == 0)
@@ -440,7 +433,7 @@ uint32_t rte_net_get_ptype(const struct rte_mbuf *m,
 			return pkt_type;
 
 		pkt_type |= ptype_inner_l3_ip(ip4h->version_ihl);
-		hdr_lens->inner_l3_len = ip4_hlen(ip4h);
+		hdr_lens->inner_l3_len = rte_ipv4_hdr_len(ip4h);
 		off += hdr_lens->inner_l3_len;
 
 		if ((layers & RTE_PTYPE_INNER_L4_MASK) == 0)
diff --git a/lib/librte_vhost/virtio_net.c b/lib/librte_vhost/virtio_net.c
index 0a0bea1a5..867e87bde 100644
--- a/lib/librte_vhost/virtio_net.c
+++ b/lib/librte_vhost/virtio_net.c
@@ -1846,7 +1846,7 @@ parse_ethernet(struct rte_mbuf *m, uint16_t *l4_proto, void **l4_hdr)
 	case RTE_ETHER_TYPE_IPV4:
 		ipv4_hdr = l3_hdr;
 		*l4_proto = ipv4_hdr->next_proto_id;
-		m->l3_len = (ipv4_hdr->version_ihl & 0x0f) * 4;
+		m->l3_len = rte_ipv4_hdr_len(ipv4_hdr);
 		*l4_hdr = (char *)l3_hdr + m->l3_len;
 		m->ol_flags |= PKT_TX_IPV4;
 		break;
-- 
2.28.0



More information about the dev mailing list