xref: /dpdk/lib/net/rte_net.h (revision 719834a6849e1daf4a70ff7742bbcc3ae7e25607)
199a2dd95SBruce Richardson /* SPDX-License-Identifier: BSD-3-Clause
299a2dd95SBruce Richardson  * Copyright 2016 6WIND S.A.
399a2dd95SBruce Richardson  */
499a2dd95SBruce Richardson 
599a2dd95SBruce Richardson #ifndef _RTE_NET_PTYPE_H_
699a2dd95SBruce Richardson #define _RTE_NET_PTYPE_H_
799a2dd95SBruce Richardson 
899a2dd95SBruce Richardson #include <rte_ip.h>
999a2dd95SBruce Richardson #include <rte_udp.h>
1099a2dd95SBruce Richardson #include <rte_tcp.h>
1199a2dd95SBruce Richardson 
12*719834a6SMattias Rönnblom #ifdef __cplusplus
13*719834a6SMattias Rönnblom extern "C" {
14*719834a6SMattias Rönnblom #endif
15*719834a6SMattias Rönnblom 
1699a2dd95SBruce Richardson /**
1799a2dd95SBruce Richardson  * Structure containing header lengths associated to a packet, filled
1899a2dd95SBruce Richardson  * by rte_net_get_ptype().
1999a2dd95SBruce Richardson  */
2099a2dd95SBruce Richardson struct rte_net_hdr_lens {
2199a2dd95SBruce Richardson 	uint8_t l2_len;
2299a2dd95SBruce Richardson 	uint8_t inner_l2_len;
2399a2dd95SBruce Richardson 	uint16_t l3_len;
2499a2dd95SBruce Richardson 	uint16_t inner_l3_len;
2599a2dd95SBruce Richardson 	uint16_t tunnel_len;
2699a2dd95SBruce Richardson 	uint8_t l4_len;
2799a2dd95SBruce Richardson 	uint8_t inner_l4_len;
2899a2dd95SBruce Richardson };
2999a2dd95SBruce Richardson 
3099a2dd95SBruce Richardson /**
3199a2dd95SBruce Richardson  * Skip IPv6 header extensions.
3299a2dd95SBruce Richardson  *
3399a2dd95SBruce Richardson  * This function skips all IPv6 extensions, returning size of
3499a2dd95SBruce Richardson  * complete header including options and final protocol value.
3599a2dd95SBruce Richardson  *
3699a2dd95SBruce Richardson  * @param proto
3799a2dd95SBruce Richardson  *   Protocol field of IPv6 header.
3899a2dd95SBruce Richardson  * @param m
3999a2dd95SBruce Richardson  *   The packet mbuf to be parsed.
4099a2dd95SBruce Richardson  * @param off
4199a2dd95SBruce Richardson  *   On input, must contain the offset to the first byte following
4299a2dd95SBruce Richardson  *   IPv6 header, on output, contains offset to the first byte
4399a2dd95SBruce Richardson  *   of next layer (after any IPv6 extension header)
4499a2dd95SBruce Richardson  * @param frag
4599a2dd95SBruce Richardson  *   Contains 1 in output if packet is an IPv6 fragment.
4699a2dd95SBruce Richardson  * @return
4799a2dd95SBruce Richardson  *   Protocol that follows IPv6 header.
4899a2dd95SBruce Richardson  *   -1 if an error occurs during mbuf parsing.
4999a2dd95SBruce Richardson  */
5099a2dd95SBruce Richardson int
5199a2dd95SBruce Richardson rte_net_skip_ip6_ext(uint16_t proto, const struct rte_mbuf *m, uint32_t *off,
5299a2dd95SBruce Richardson 	int *frag);
5399a2dd95SBruce Richardson 
5499a2dd95SBruce Richardson /**
5599a2dd95SBruce Richardson  * Parse an Ethernet packet to get its packet type.
5699a2dd95SBruce Richardson  *
5799a2dd95SBruce Richardson  * This function parses the network headers in mbuf data and return its
5899a2dd95SBruce Richardson  * packet type.
5999a2dd95SBruce Richardson  *
6099a2dd95SBruce Richardson  * If it is provided by the user, it also fills a rte_net_hdr_lens
6199a2dd95SBruce Richardson  * structure that contains the lengths of the parsed network
6299a2dd95SBruce Richardson  * headers. Each length field is valid only if the associated packet
6399a2dd95SBruce Richardson  * type is set. For instance, hdr_lens->l2_len is valid only if
6499a2dd95SBruce Richardson  * (retval & RTE_PTYPE_L2_MASK) != RTE_PTYPE_UNKNOWN.
6599a2dd95SBruce Richardson  *
6699a2dd95SBruce Richardson  * Supported packet types are:
6799a2dd95SBruce Richardson  *   L2: Ether, Vlan, QinQ
6899a2dd95SBruce Richardson  *   L3: IPv4, IPv6
6999a2dd95SBruce Richardson  *   L4: TCP, UDP, SCTP
7099a2dd95SBruce Richardson  *   Tunnels: IPv4, IPv6, Gre, Nvgre
7199a2dd95SBruce Richardson  *
7299a2dd95SBruce Richardson  * @param m
7399a2dd95SBruce Richardson  *   The packet mbuf to be parsed.
7499a2dd95SBruce Richardson  * @param hdr_lens
7599a2dd95SBruce Richardson  *   A pointer to a structure where the header lengths will be returned,
7699a2dd95SBruce Richardson  *   or NULL.
7799a2dd95SBruce Richardson  * @param layers
7899a2dd95SBruce Richardson  *   List of layers to parse. The function will stop at the first
7999a2dd95SBruce Richardson  *   empty layer. Examples:
8099a2dd95SBruce Richardson  *   - To parse all known layers, use RTE_PTYPE_ALL_MASK.
8199a2dd95SBruce Richardson  *   - To parse only L2 and L3, use RTE_PTYPE_L2_MASK | RTE_PTYPE_L3_MASK
8299a2dd95SBruce Richardson  * @return
8399a2dd95SBruce Richardson  *   The packet type of the packet.
8499a2dd95SBruce Richardson  */
8599a2dd95SBruce Richardson uint32_t rte_net_get_ptype(const struct rte_mbuf *m,
8699a2dd95SBruce Richardson 	struct rte_net_hdr_lens *hdr_lens, uint32_t layers);
8799a2dd95SBruce Richardson 
8899a2dd95SBruce Richardson /**
8999a2dd95SBruce Richardson  * Prepare pseudo header checksum
9099a2dd95SBruce Richardson  *
9199a2dd95SBruce Richardson  * This function prepares pseudo header checksum for TSO and non-TSO tcp/udp in
9299a2dd95SBruce Richardson  * provided mbufs packet data and based on the requested offload flags.
9399a2dd95SBruce Richardson  *
9499a2dd95SBruce Richardson  * - for non-TSO tcp/udp packets full pseudo-header checksum is counted and set
9599a2dd95SBruce Richardson  *   in packet data,
9699a2dd95SBruce Richardson  * - for TSO the IP payload length is not included in pseudo header.
9799a2dd95SBruce Richardson  *
9899a2dd95SBruce Richardson  * This function expects that used headers are in the first data segment of
9999a2dd95SBruce Richardson  * mbuf, are not fragmented and can be safely modified.
10099a2dd95SBruce Richardson  *
10199a2dd95SBruce Richardson  * @param m
10299a2dd95SBruce Richardson  *   The packet mbuf to be fixed.
10399a2dd95SBruce Richardson  * @param ol_flags
10499a2dd95SBruce Richardson  *   TX offloads flags to use with this packet.
10599a2dd95SBruce Richardson  * @return
10699a2dd95SBruce Richardson  *   0 if checksum is initialized properly
10799a2dd95SBruce Richardson  */
10899a2dd95SBruce Richardson static inline int
10999a2dd95SBruce Richardson rte_net_intel_cksum_flags_prepare(struct rte_mbuf *m, uint64_t ol_flags)
11099a2dd95SBruce Richardson {
111ee86d6e9SDavid Marchand 	const uint64_t inner_requests = RTE_MBUF_F_TX_IP_CKSUM | RTE_MBUF_F_TX_L4_MASK |
112ee86d6e9SDavid Marchand 		RTE_MBUF_F_TX_TCP_SEG | RTE_MBUF_F_TX_UDP_SEG;
113ee86d6e9SDavid Marchand 	const uint64_t outer_requests = RTE_MBUF_F_TX_OUTER_IP_CKSUM |
114ee86d6e9SDavid Marchand 		RTE_MBUF_F_TX_OUTER_UDP_CKSUM;
11599a2dd95SBruce Richardson 	/* Initialise ipv4_hdr to avoid false positive compiler warnings. */
11699a2dd95SBruce Richardson 	struct rte_ipv4_hdr *ipv4_hdr = NULL;
11799a2dd95SBruce Richardson 	struct rte_ipv6_hdr *ipv6_hdr;
11899a2dd95SBruce Richardson 	struct rte_tcp_hdr *tcp_hdr;
11999a2dd95SBruce Richardson 	struct rte_udp_hdr *udp_hdr;
12099a2dd95SBruce Richardson 	uint64_t inner_l3_offset = m->l2_len;
12199a2dd95SBruce Richardson 
12299a2dd95SBruce Richardson 	/*
12399a2dd95SBruce Richardson 	 * Does packet set any of available offloads?
12499a2dd95SBruce Richardson 	 * Mainly it is required to avoid fragmented headers check if
12599a2dd95SBruce Richardson 	 * no offloads are requested.
12699a2dd95SBruce Richardson 	 */
127ee86d6e9SDavid Marchand 	if (!(ol_flags & (inner_requests | outer_requests)))
12899a2dd95SBruce Richardson 		return 0;
12999a2dd95SBruce Richardson 
130daa02b5cSOlivier Matz 	if (ol_flags & (RTE_MBUF_F_TX_OUTER_IPV4 | RTE_MBUF_F_TX_OUTER_IPV6)) {
13199a2dd95SBruce Richardson 		inner_l3_offset += m->outer_l2_len + m->outer_l3_len;
132818ce113SMohsin Kazmi 		/*
133818ce113SMohsin Kazmi 		 * prepare outer IPv4 header checksum by setting it to 0,
134818ce113SMohsin Kazmi 		 * in order to be computed by hardware NICs.
135818ce113SMohsin Kazmi 		 */
136daa02b5cSOlivier Matz 		if (ol_flags & RTE_MBUF_F_TX_OUTER_IP_CKSUM) {
137818ce113SMohsin Kazmi 			ipv4_hdr = rte_pktmbuf_mtod_offset(m,
138818ce113SMohsin Kazmi 					struct rte_ipv4_hdr *, m->outer_l2_len);
139818ce113SMohsin Kazmi 			ipv4_hdr->hdr_checksum = 0;
140818ce113SMohsin Kazmi 		}
141ee86d6e9SDavid Marchand 		if (ol_flags & RTE_MBUF_F_TX_OUTER_UDP_CKSUM || ol_flags & inner_requests) {
142f876dbefSDavid Marchand 			if (ol_flags & RTE_MBUF_F_TX_OUTER_IPV4) {
143f876dbefSDavid Marchand 				ipv4_hdr = rte_pktmbuf_mtod_offset(m, struct rte_ipv4_hdr *,
144f876dbefSDavid Marchand 					m->outer_l2_len);
145f876dbefSDavid Marchand 				udp_hdr = (struct rte_udp_hdr *)((char *)ipv4_hdr +
146f876dbefSDavid Marchand 					m->outer_l3_len);
147ee86d6e9SDavid Marchand 				if (ol_flags & RTE_MBUF_F_TX_OUTER_UDP_CKSUM)
148ee86d6e9SDavid Marchand 					udp_hdr->dgram_cksum = rte_ipv4_phdr_cksum(ipv4_hdr,
149ee86d6e9SDavid Marchand 						m->ol_flags);
150ee86d6e9SDavid Marchand 				else if (ipv4_hdr->next_proto_id == IPPROTO_UDP)
151ee86d6e9SDavid Marchand 					udp_hdr->dgram_cksum = 0;
152f876dbefSDavid Marchand 			} else {
153f876dbefSDavid Marchand 				ipv6_hdr = rte_pktmbuf_mtod_offset(m, struct rte_ipv6_hdr *,
154f876dbefSDavid Marchand 					m->outer_l2_len);
155f876dbefSDavid Marchand 				udp_hdr = rte_pktmbuf_mtod_offset(m, struct rte_udp_hdr *,
156f876dbefSDavid Marchand 					 m->outer_l2_len + m->outer_l3_len);
157ee86d6e9SDavid Marchand 				if (ol_flags & RTE_MBUF_F_TX_OUTER_UDP_CKSUM)
158ee86d6e9SDavid Marchand 					udp_hdr->dgram_cksum = rte_ipv6_phdr_cksum(ipv6_hdr,
159ee86d6e9SDavid Marchand 						m->ol_flags);
160ee86d6e9SDavid Marchand 				else if (ipv6_hdr->proto == IPPROTO_UDP)
161ee86d6e9SDavid Marchand 					udp_hdr->dgram_cksum = 0;
162f876dbefSDavid Marchand 			}
163f876dbefSDavid Marchand 		}
164818ce113SMohsin Kazmi 	}
16599a2dd95SBruce Richardson 
16699a2dd95SBruce Richardson 	/*
16799a2dd95SBruce Richardson 	 * Check if headers are fragmented.
16899a2dd95SBruce Richardson 	 * The check could be less strict depending on which offloads are
16999a2dd95SBruce Richardson 	 * requested and headers to be used, but let's keep it simple.
17099a2dd95SBruce Richardson 	 */
17199a2dd95SBruce Richardson 	if (unlikely(rte_pktmbuf_data_len(m) <
17299a2dd95SBruce Richardson 		     inner_l3_offset + m->l3_len + m->l4_len))
17399a2dd95SBruce Richardson 		return -ENOTSUP;
17499a2dd95SBruce Richardson 
175daa02b5cSOlivier Matz 	if (ol_flags & RTE_MBUF_F_TX_IPV4) {
17699a2dd95SBruce Richardson 		ipv4_hdr = rte_pktmbuf_mtod_offset(m, struct rte_ipv4_hdr *,
17799a2dd95SBruce Richardson 				inner_l3_offset);
17899a2dd95SBruce Richardson 
179daa02b5cSOlivier Matz 		if (ol_flags & RTE_MBUF_F_TX_IP_CKSUM)
18099a2dd95SBruce Richardson 			ipv4_hdr->hdr_checksum = 0;
18199a2dd95SBruce Richardson 	}
18299a2dd95SBruce Richardson 
183103c0ee2SZhichao Zeng 	if ((ol_flags & RTE_MBUF_F_TX_L4_MASK) == RTE_MBUF_F_TX_UDP_CKSUM ||
184103c0ee2SZhichao Zeng 			(ol_flags & RTE_MBUF_F_TX_UDP_SEG)) {
185daa02b5cSOlivier Matz 		if (ol_flags & RTE_MBUF_F_TX_IPV4) {
18699a2dd95SBruce Richardson 			udp_hdr = (struct rte_udp_hdr *)((char *)ipv4_hdr +
18799a2dd95SBruce Richardson 					m->l3_len);
18899a2dd95SBruce Richardson 			udp_hdr->dgram_cksum = rte_ipv4_phdr_cksum(ipv4_hdr,
18999a2dd95SBruce Richardson 					ol_flags);
19099a2dd95SBruce Richardson 		} else {
19199a2dd95SBruce Richardson 			ipv6_hdr = rte_pktmbuf_mtod_offset(m,
19299a2dd95SBruce Richardson 				struct rte_ipv6_hdr *, inner_l3_offset);
19399a2dd95SBruce Richardson 			/* non-TSO udp */
19499a2dd95SBruce Richardson 			udp_hdr = rte_pktmbuf_mtod_offset(m,
19599a2dd95SBruce Richardson 					struct rte_udp_hdr *,
19699a2dd95SBruce Richardson 					inner_l3_offset + m->l3_len);
19799a2dd95SBruce Richardson 			udp_hdr->dgram_cksum = rte_ipv6_phdr_cksum(ipv6_hdr,
19899a2dd95SBruce Richardson 					ol_flags);
19999a2dd95SBruce Richardson 		}
200daa02b5cSOlivier Matz 	} else if ((ol_flags & RTE_MBUF_F_TX_L4_MASK) == RTE_MBUF_F_TX_TCP_CKSUM ||
201daa02b5cSOlivier Matz 			(ol_flags & RTE_MBUF_F_TX_TCP_SEG)) {
202daa02b5cSOlivier Matz 		if (ol_flags & RTE_MBUF_F_TX_IPV4) {
20399a2dd95SBruce Richardson 			/* non-TSO tcp or TSO */
20499a2dd95SBruce Richardson 			tcp_hdr = (struct rte_tcp_hdr *)((char *)ipv4_hdr +
20599a2dd95SBruce Richardson 					m->l3_len);
20699a2dd95SBruce Richardson 			tcp_hdr->cksum = rte_ipv4_phdr_cksum(ipv4_hdr,
20799a2dd95SBruce Richardson 					ol_flags);
20899a2dd95SBruce Richardson 		} else {
20999a2dd95SBruce Richardson 			ipv6_hdr = rte_pktmbuf_mtod_offset(m,
21099a2dd95SBruce Richardson 				struct rte_ipv6_hdr *, inner_l3_offset);
21199a2dd95SBruce Richardson 			/* non-TSO tcp or TSO */
21299a2dd95SBruce Richardson 			tcp_hdr = rte_pktmbuf_mtod_offset(m,
21399a2dd95SBruce Richardson 					struct rte_tcp_hdr *,
21499a2dd95SBruce Richardson 					inner_l3_offset + m->l3_len);
21599a2dd95SBruce Richardson 			tcp_hdr->cksum = rte_ipv6_phdr_cksum(ipv6_hdr,
21699a2dd95SBruce Richardson 					ol_flags);
21799a2dd95SBruce Richardson 		}
21899a2dd95SBruce Richardson 	}
21999a2dd95SBruce Richardson 
22099a2dd95SBruce Richardson 	return 0;
22199a2dd95SBruce Richardson }
22299a2dd95SBruce Richardson 
22399a2dd95SBruce Richardson /**
22499a2dd95SBruce Richardson  * Prepare pseudo header checksum
22599a2dd95SBruce Richardson  *
22699a2dd95SBruce Richardson  * This function prepares pseudo header checksum for TSO and non-TSO tcp/udp in
22799a2dd95SBruce Richardson  * provided mbufs packet data.
22899a2dd95SBruce Richardson  *
22999a2dd95SBruce Richardson  * - for non-TSO tcp/udp packets full pseudo-header checksum is counted and set
23099a2dd95SBruce Richardson  *   in packet data,
23199a2dd95SBruce Richardson  * - for TSO the IP payload length is not included in pseudo header.
23299a2dd95SBruce Richardson  *
23399a2dd95SBruce Richardson  * This function expects that used headers are in the first data segment of
23499a2dd95SBruce Richardson  * mbuf, are not fragmented and can be safely modified.
23599a2dd95SBruce Richardson  *
23699a2dd95SBruce Richardson  * @param m
23799a2dd95SBruce Richardson  *   The packet mbuf to be fixed.
23899a2dd95SBruce Richardson  * @return
23999a2dd95SBruce Richardson  *   0 if checksum is initialized properly
24099a2dd95SBruce Richardson  */
24199a2dd95SBruce Richardson static inline int
24299a2dd95SBruce Richardson rte_net_intel_cksum_prepare(struct rte_mbuf *m)
24399a2dd95SBruce Richardson {
24499a2dd95SBruce Richardson 	return rte_net_intel_cksum_flags_prepare(m, m->ol_flags);
24599a2dd95SBruce Richardson }
24699a2dd95SBruce Richardson 
24799a2dd95SBruce Richardson #ifdef __cplusplus
24899a2dd95SBruce Richardson }
24999a2dd95SBruce Richardson #endif
25099a2dd95SBruce Richardson 
25199a2dd95SBruce Richardson 
25299a2dd95SBruce Richardson #endif /* _RTE_NET_PTYPE_H_ */
253