From 9863627f52b87f71351c01a6040cf3c68cae8a33 Mon Sep 17 00:00:00 2001 From: Michael Pfeiffer Date: Mon, 12 Oct 2020 16:55:46 +0200 Subject: [PATCH] net: add function to calculate IPv4 header length 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 Signed-off-by: Michael Pfeiffer Reviewed-by: Ferruh Yigit --- 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 3cf1692eab..e8cef9623b 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 8f2f840690..3d7d244d1e 100644 --- a/app/test-pmd/csumonly.c +++ b/app/test-pmd/csumonly.c @@ -105,7 +105,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 d9f251a32d..2dd4fe184c 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 b127ce62dc..e592a469b3 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 73e270f30f..e10f9ee870 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 c529dcd3e5..9996bfba34 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 8382d0fac7..5463276e66 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(). @@ -272,7 +287,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; } @@ -306,7 +321,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; @@ -316,8 +330,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)); } @@ -342,7 +356,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 6f45b1339e..bfe5003976 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 @@ l3: 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 @@ l3: 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 1b233279ca..513428e5e1 100644 --- a/lib/librte_vhost/virtio_net.c +++ b/lib/librte_vhost/virtio_net.c @@ -1847,7 +1847,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.20.1