xref: /dpdk/lib/net/rte_net.c (revision 99a2dd955fba6e4cc23b77d590a033650ced9c45)
1*99a2dd95SBruce Richardson /* SPDX-License-Identifier: BSD-3-Clause
2*99a2dd95SBruce Richardson  * Copyright 2016 6WIND S.A.
3*99a2dd95SBruce Richardson  */
4*99a2dd95SBruce Richardson 
5*99a2dd95SBruce Richardson #include <stdint.h>
6*99a2dd95SBruce Richardson 
7*99a2dd95SBruce Richardson #include <rte_mbuf.h>
8*99a2dd95SBruce Richardson #include <rte_mbuf_ptype.h>
9*99a2dd95SBruce Richardson #include <rte_byteorder.h>
10*99a2dd95SBruce Richardson #include <rte_ether.h>
11*99a2dd95SBruce Richardson #include <rte_ip.h>
12*99a2dd95SBruce Richardson #include <rte_tcp.h>
13*99a2dd95SBruce Richardson #include <rte_udp.h>
14*99a2dd95SBruce Richardson #include <rte_sctp.h>
15*99a2dd95SBruce Richardson #include <rte_gre.h>
16*99a2dd95SBruce Richardson #include <rte_mpls.h>
17*99a2dd95SBruce Richardson #include <rte_net.h>
18*99a2dd95SBruce Richardson #include <rte_os_shim.h>
19*99a2dd95SBruce Richardson 
20*99a2dd95SBruce Richardson /* get l3 packet type from ip6 next protocol */
21*99a2dd95SBruce Richardson static uint32_t
ptype_l3_ip6(uint8_t ip6_proto)22*99a2dd95SBruce Richardson ptype_l3_ip6(uint8_t ip6_proto)
23*99a2dd95SBruce Richardson {
24*99a2dd95SBruce Richardson 	static const uint32_t ip6_ext_proto_map[256] = {
25*99a2dd95SBruce Richardson 		[IPPROTO_HOPOPTS] = RTE_PTYPE_L3_IPV6_EXT - RTE_PTYPE_L3_IPV6,
26*99a2dd95SBruce Richardson 		[IPPROTO_ROUTING] = RTE_PTYPE_L3_IPV6_EXT - RTE_PTYPE_L3_IPV6,
27*99a2dd95SBruce Richardson 		[IPPROTO_FRAGMENT] = RTE_PTYPE_L3_IPV6_EXT - RTE_PTYPE_L3_IPV6,
28*99a2dd95SBruce Richardson 		[IPPROTO_ESP] = RTE_PTYPE_L3_IPV6_EXT - RTE_PTYPE_L3_IPV6,
29*99a2dd95SBruce Richardson 		[IPPROTO_AH] = RTE_PTYPE_L3_IPV6_EXT - RTE_PTYPE_L3_IPV6,
30*99a2dd95SBruce Richardson 		[IPPROTO_DSTOPTS] = RTE_PTYPE_L3_IPV6_EXT - RTE_PTYPE_L3_IPV6,
31*99a2dd95SBruce Richardson 	};
32*99a2dd95SBruce Richardson 
33*99a2dd95SBruce Richardson 	return RTE_PTYPE_L3_IPV6 + ip6_ext_proto_map[ip6_proto];
34*99a2dd95SBruce Richardson }
35*99a2dd95SBruce Richardson 
36*99a2dd95SBruce Richardson /* get l3 packet type from ip version and header length */
37*99a2dd95SBruce Richardson static uint32_t
ptype_l3_ip(uint8_t ipv_ihl)38*99a2dd95SBruce Richardson ptype_l3_ip(uint8_t ipv_ihl)
39*99a2dd95SBruce Richardson {
40*99a2dd95SBruce Richardson 	static const uint32_t ptype_l3_ip_proto_map[256] = {
41*99a2dd95SBruce Richardson 		[0x45] = RTE_PTYPE_L3_IPV4,
42*99a2dd95SBruce Richardson 		[0x46] = RTE_PTYPE_L3_IPV4_EXT,
43*99a2dd95SBruce Richardson 		[0x47] = RTE_PTYPE_L3_IPV4_EXT,
44*99a2dd95SBruce Richardson 		[0x48] = RTE_PTYPE_L3_IPV4_EXT,
45*99a2dd95SBruce Richardson 		[0x49] = RTE_PTYPE_L3_IPV4_EXT,
46*99a2dd95SBruce Richardson 		[0x4A] = RTE_PTYPE_L3_IPV4_EXT,
47*99a2dd95SBruce Richardson 		[0x4B] = RTE_PTYPE_L3_IPV4_EXT,
48*99a2dd95SBruce Richardson 		[0x4C] = RTE_PTYPE_L3_IPV4_EXT,
49*99a2dd95SBruce Richardson 		[0x4D] = RTE_PTYPE_L3_IPV4_EXT,
50*99a2dd95SBruce Richardson 		[0x4E] = RTE_PTYPE_L3_IPV4_EXT,
51*99a2dd95SBruce Richardson 		[0x4F] = RTE_PTYPE_L3_IPV4_EXT,
52*99a2dd95SBruce Richardson 	};
53*99a2dd95SBruce Richardson 
54*99a2dd95SBruce Richardson 	return ptype_l3_ip_proto_map[ipv_ihl];
55*99a2dd95SBruce Richardson }
56*99a2dd95SBruce Richardson 
57*99a2dd95SBruce Richardson /* get l4 packet type from proto */
58*99a2dd95SBruce Richardson static uint32_t
ptype_l4(uint8_t proto)59*99a2dd95SBruce Richardson ptype_l4(uint8_t proto)
60*99a2dd95SBruce Richardson {
61*99a2dd95SBruce Richardson 	static const uint32_t ptype_l4_proto[256] = {
62*99a2dd95SBruce Richardson 		[IPPROTO_UDP] = RTE_PTYPE_L4_UDP,
63*99a2dd95SBruce Richardson 		[IPPROTO_TCP] = RTE_PTYPE_L4_TCP,
64*99a2dd95SBruce Richardson 		[IPPROTO_SCTP] = RTE_PTYPE_L4_SCTP,
65*99a2dd95SBruce Richardson 	};
66*99a2dd95SBruce Richardson 
67*99a2dd95SBruce Richardson 	return ptype_l4_proto[proto];
68*99a2dd95SBruce Richardson }
69*99a2dd95SBruce Richardson 
70*99a2dd95SBruce Richardson /* get inner l3 packet type from ip6 next protocol */
71*99a2dd95SBruce Richardson static uint32_t
ptype_inner_l3_ip6(uint8_t ip6_proto)72*99a2dd95SBruce Richardson ptype_inner_l3_ip6(uint8_t ip6_proto)
73*99a2dd95SBruce Richardson {
74*99a2dd95SBruce Richardson 	static const uint32_t ptype_inner_ip6_ext_proto_map[256] = {
75*99a2dd95SBruce Richardson 		[IPPROTO_HOPOPTS] = RTE_PTYPE_INNER_L3_IPV6_EXT -
76*99a2dd95SBruce Richardson 			RTE_PTYPE_INNER_L3_IPV6,
77*99a2dd95SBruce Richardson 		[IPPROTO_ROUTING] = RTE_PTYPE_INNER_L3_IPV6_EXT -
78*99a2dd95SBruce Richardson 			RTE_PTYPE_INNER_L3_IPV6,
79*99a2dd95SBruce Richardson 		[IPPROTO_FRAGMENT] = RTE_PTYPE_INNER_L3_IPV6_EXT -
80*99a2dd95SBruce Richardson 			RTE_PTYPE_INNER_L3_IPV6,
81*99a2dd95SBruce Richardson 		[IPPROTO_ESP] = RTE_PTYPE_INNER_L3_IPV6_EXT -
82*99a2dd95SBruce Richardson 			RTE_PTYPE_INNER_L3_IPV6,
83*99a2dd95SBruce Richardson 		[IPPROTO_AH] = RTE_PTYPE_INNER_L3_IPV6_EXT -
84*99a2dd95SBruce Richardson 			RTE_PTYPE_INNER_L3_IPV6,
85*99a2dd95SBruce Richardson 		[IPPROTO_DSTOPTS] = RTE_PTYPE_INNER_L3_IPV6_EXT -
86*99a2dd95SBruce Richardson 			RTE_PTYPE_INNER_L3_IPV6,
87*99a2dd95SBruce Richardson 	};
88*99a2dd95SBruce Richardson 
89*99a2dd95SBruce Richardson 	return RTE_PTYPE_INNER_L3_IPV6 +
90*99a2dd95SBruce Richardson 		ptype_inner_ip6_ext_proto_map[ip6_proto];
91*99a2dd95SBruce Richardson }
92*99a2dd95SBruce Richardson 
93*99a2dd95SBruce Richardson /* get inner l3 packet type from ip version and header length */
94*99a2dd95SBruce Richardson static uint32_t
ptype_inner_l3_ip(uint8_t ipv_ihl)95*99a2dd95SBruce Richardson ptype_inner_l3_ip(uint8_t ipv_ihl)
96*99a2dd95SBruce Richardson {
97*99a2dd95SBruce Richardson 	static const uint32_t ptype_inner_l3_ip_proto_map[256] = {
98*99a2dd95SBruce Richardson 		[0x45] = RTE_PTYPE_INNER_L3_IPV4,
99*99a2dd95SBruce Richardson 		[0x46] = RTE_PTYPE_INNER_L3_IPV4_EXT,
100*99a2dd95SBruce Richardson 		[0x47] = RTE_PTYPE_INNER_L3_IPV4_EXT,
101*99a2dd95SBruce Richardson 		[0x48] = RTE_PTYPE_INNER_L3_IPV4_EXT,
102*99a2dd95SBruce Richardson 		[0x49] = RTE_PTYPE_INNER_L3_IPV4_EXT,
103*99a2dd95SBruce Richardson 		[0x4A] = RTE_PTYPE_INNER_L3_IPV4_EXT,
104*99a2dd95SBruce Richardson 		[0x4B] = RTE_PTYPE_INNER_L3_IPV4_EXT,
105*99a2dd95SBruce Richardson 		[0x4C] = RTE_PTYPE_INNER_L3_IPV4_EXT,
106*99a2dd95SBruce Richardson 		[0x4D] = RTE_PTYPE_INNER_L3_IPV4_EXT,
107*99a2dd95SBruce Richardson 		[0x4E] = RTE_PTYPE_INNER_L3_IPV4_EXT,
108*99a2dd95SBruce Richardson 		[0x4F] = RTE_PTYPE_INNER_L3_IPV4_EXT,
109*99a2dd95SBruce Richardson 	};
110*99a2dd95SBruce Richardson 
111*99a2dd95SBruce Richardson 	return ptype_inner_l3_ip_proto_map[ipv_ihl];
112*99a2dd95SBruce Richardson }
113*99a2dd95SBruce Richardson 
114*99a2dd95SBruce Richardson /* get inner l4 packet type from proto */
115*99a2dd95SBruce Richardson static uint32_t
ptype_inner_l4(uint8_t proto)116*99a2dd95SBruce Richardson ptype_inner_l4(uint8_t proto)
117*99a2dd95SBruce Richardson {
118*99a2dd95SBruce Richardson 	static const uint32_t ptype_inner_l4_proto[256] = {
119*99a2dd95SBruce Richardson 		[IPPROTO_UDP] = RTE_PTYPE_INNER_L4_UDP,
120*99a2dd95SBruce Richardson 		[IPPROTO_TCP] = RTE_PTYPE_INNER_L4_TCP,
121*99a2dd95SBruce Richardson 		[IPPROTO_SCTP] = RTE_PTYPE_INNER_L4_SCTP,
122*99a2dd95SBruce Richardson 	};
123*99a2dd95SBruce Richardson 
124*99a2dd95SBruce Richardson 	return ptype_inner_l4_proto[proto];
125*99a2dd95SBruce Richardson }
126*99a2dd95SBruce Richardson 
127*99a2dd95SBruce Richardson /* get the tunnel packet type if any, update proto and off. */
128*99a2dd95SBruce Richardson static uint32_t
ptype_tunnel(uint16_t * proto,const struct rte_mbuf * m,uint32_t * off)129*99a2dd95SBruce Richardson ptype_tunnel(uint16_t *proto, const struct rte_mbuf *m,
130*99a2dd95SBruce Richardson 	uint32_t *off)
131*99a2dd95SBruce Richardson {
132*99a2dd95SBruce Richardson 	switch (*proto) {
133*99a2dd95SBruce Richardson 	case IPPROTO_GRE: {
134*99a2dd95SBruce Richardson 		static const uint8_t opt_len[16] = {
135*99a2dd95SBruce Richardson 			[0x0] = 4,
136*99a2dd95SBruce Richardson 			[0x1] = 8,
137*99a2dd95SBruce Richardson 			[0x2] = 8,
138*99a2dd95SBruce Richardson 			[0x8] = 8,
139*99a2dd95SBruce Richardson 			[0x3] = 12,
140*99a2dd95SBruce Richardson 			[0x9] = 12,
141*99a2dd95SBruce Richardson 			[0xa] = 12,
142*99a2dd95SBruce Richardson 			[0xb] = 16,
143*99a2dd95SBruce Richardson 		};
144*99a2dd95SBruce Richardson 		const struct rte_gre_hdr *gh;
145*99a2dd95SBruce Richardson 		struct rte_gre_hdr gh_copy;
146*99a2dd95SBruce Richardson 		uint16_t flags;
147*99a2dd95SBruce Richardson 
148*99a2dd95SBruce Richardson 		gh = rte_pktmbuf_read(m, *off, sizeof(*gh), &gh_copy);
149*99a2dd95SBruce Richardson 		if (unlikely(gh == NULL))
150*99a2dd95SBruce Richardson 			return 0;
151*99a2dd95SBruce Richardson 
152*99a2dd95SBruce Richardson 		flags = rte_be_to_cpu_16(*(const uint16_t *)gh);
153*99a2dd95SBruce Richardson 		flags >>= 12;
154*99a2dd95SBruce Richardson 		if (opt_len[flags] == 0)
155*99a2dd95SBruce Richardson 			return 0;
156*99a2dd95SBruce Richardson 
157*99a2dd95SBruce Richardson 		*off += opt_len[flags];
158*99a2dd95SBruce Richardson 		*proto = gh->proto;
159*99a2dd95SBruce Richardson 		if (*proto == rte_cpu_to_be_16(RTE_ETHER_TYPE_TEB))
160*99a2dd95SBruce Richardson 			return RTE_PTYPE_TUNNEL_NVGRE;
161*99a2dd95SBruce Richardson 		else
162*99a2dd95SBruce Richardson 			return RTE_PTYPE_TUNNEL_GRE;
163*99a2dd95SBruce Richardson 	}
164*99a2dd95SBruce Richardson 	case IPPROTO_IPIP:
165*99a2dd95SBruce Richardson 		*proto = rte_cpu_to_be_16(RTE_ETHER_TYPE_IPV4);
166*99a2dd95SBruce Richardson 		return RTE_PTYPE_TUNNEL_IP;
167*99a2dd95SBruce Richardson 	case IPPROTO_IPV6:
168*99a2dd95SBruce Richardson 		*proto = rte_cpu_to_be_16(RTE_ETHER_TYPE_IPV6);
169*99a2dd95SBruce Richardson 		return RTE_PTYPE_TUNNEL_IP; /* IP is also valid for IPv6 */
170*99a2dd95SBruce Richardson 	default:
171*99a2dd95SBruce Richardson 		return 0;
172*99a2dd95SBruce Richardson 	}
173*99a2dd95SBruce Richardson }
174*99a2dd95SBruce Richardson 
175*99a2dd95SBruce Richardson /* parse ipv6 extended headers, update offset and return next proto */
176*99a2dd95SBruce Richardson int
rte_net_skip_ip6_ext(uint16_t proto,const struct rte_mbuf * m,uint32_t * off,int * frag)177*99a2dd95SBruce Richardson rte_net_skip_ip6_ext(uint16_t proto, const struct rte_mbuf *m, uint32_t *off,
178*99a2dd95SBruce Richardson 	int *frag)
179*99a2dd95SBruce Richardson {
180*99a2dd95SBruce Richardson 	struct ext_hdr {
181*99a2dd95SBruce Richardson 		uint8_t next_hdr;
182*99a2dd95SBruce Richardson 		uint8_t len;
183*99a2dd95SBruce Richardson 	};
184*99a2dd95SBruce Richardson 	const struct ext_hdr *xh;
185*99a2dd95SBruce Richardson 	struct ext_hdr xh_copy;
186*99a2dd95SBruce Richardson 	unsigned int i;
187*99a2dd95SBruce Richardson 
188*99a2dd95SBruce Richardson 	*frag = 0;
189*99a2dd95SBruce Richardson 
190*99a2dd95SBruce Richardson #define MAX_EXT_HDRS 5
191*99a2dd95SBruce Richardson 	for (i = 0; i < MAX_EXT_HDRS; i++) {
192*99a2dd95SBruce Richardson 		switch (proto) {
193*99a2dd95SBruce Richardson 		case IPPROTO_HOPOPTS:
194*99a2dd95SBruce Richardson 		case IPPROTO_ROUTING:
195*99a2dd95SBruce Richardson 		case IPPROTO_DSTOPTS:
196*99a2dd95SBruce Richardson 			xh = rte_pktmbuf_read(m, *off, sizeof(*xh),
197*99a2dd95SBruce Richardson 				&xh_copy);
198*99a2dd95SBruce Richardson 			if (xh == NULL)
199*99a2dd95SBruce Richardson 				return -1;
200*99a2dd95SBruce Richardson 			*off += (xh->len + 1) * 8;
201*99a2dd95SBruce Richardson 			proto = xh->next_hdr;
202*99a2dd95SBruce Richardson 			break;
203*99a2dd95SBruce Richardson 		case IPPROTO_FRAGMENT:
204*99a2dd95SBruce Richardson 			xh = rte_pktmbuf_read(m, *off, sizeof(*xh),
205*99a2dd95SBruce Richardson 				&xh_copy);
206*99a2dd95SBruce Richardson 			if (xh == NULL)
207*99a2dd95SBruce Richardson 				return -1;
208*99a2dd95SBruce Richardson 			*off += 8;
209*99a2dd95SBruce Richardson 			proto = xh->next_hdr;
210*99a2dd95SBruce Richardson 			*frag = 1;
211*99a2dd95SBruce Richardson 			return proto; /* this is always the last ext hdr */
212*99a2dd95SBruce Richardson 		case IPPROTO_NONE:
213*99a2dd95SBruce Richardson 			return 0;
214*99a2dd95SBruce Richardson 		default:
215*99a2dd95SBruce Richardson 			return proto;
216*99a2dd95SBruce Richardson 		}
217*99a2dd95SBruce Richardson 	}
218*99a2dd95SBruce Richardson 	return -1;
219*99a2dd95SBruce Richardson }
220*99a2dd95SBruce Richardson 
221*99a2dd95SBruce Richardson /* parse mbuf data to get packet type */
rte_net_get_ptype(const struct rte_mbuf * m,struct rte_net_hdr_lens * hdr_lens,uint32_t layers)222*99a2dd95SBruce Richardson uint32_t rte_net_get_ptype(const struct rte_mbuf *m,
223*99a2dd95SBruce Richardson 	struct rte_net_hdr_lens *hdr_lens, uint32_t layers)
224*99a2dd95SBruce Richardson {
225*99a2dd95SBruce Richardson 	struct rte_net_hdr_lens local_hdr_lens;
226*99a2dd95SBruce Richardson 	const struct rte_ether_hdr *eh;
227*99a2dd95SBruce Richardson 	struct rte_ether_hdr eh_copy;
228*99a2dd95SBruce Richardson 	uint32_t pkt_type = RTE_PTYPE_L2_ETHER;
229*99a2dd95SBruce Richardson 	uint32_t off = 0;
230*99a2dd95SBruce Richardson 	uint16_t proto;
231*99a2dd95SBruce Richardson 	int ret;
232*99a2dd95SBruce Richardson 
233*99a2dd95SBruce Richardson 	if (hdr_lens == NULL)
234*99a2dd95SBruce Richardson 		hdr_lens = &local_hdr_lens;
235*99a2dd95SBruce Richardson 
236*99a2dd95SBruce Richardson 	eh = rte_pktmbuf_read(m, off, sizeof(*eh), &eh_copy);
237*99a2dd95SBruce Richardson 	if (unlikely(eh == NULL))
238*99a2dd95SBruce Richardson 		return 0;
239*99a2dd95SBruce Richardson 	proto = eh->ether_type;
240*99a2dd95SBruce Richardson 	off = sizeof(*eh);
241*99a2dd95SBruce Richardson 	hdr_lens->l2_len = off;
242*99a2dd95SBruce Richardson 
243*99a2dd95SBruce Richardson 	if ((layers & RTE_PTYPE_L2_MASK) == 0)
244*99a2dd95SBruce Richardson 		return 0;
245*99a2dd95SBruce Richardson 
246*99a2dd95SBruce Richardson 	if (proto == rte_cpu_to_be_16(RTE_ETHER_TYPE_IPV4))
247*99a2dd95SBruce Richardson 		goto l3; /* fast path if packet is IPv4 */
248*99a2dd95SBruce Richardson 
249*99a2dd95SBruce Richardson 	if (proto == rte_cpu_to_be_16(RTE_ETHER_TYPE_VLAN)) {
250*99a2dd95SBruce Richardson 		const struct rte_vlan_hdr *vh;
251*99a2dd95SBruce Richardson 		struct rte_vlan_hdr vh_copy;
252*99a2dd95SBruce Richardson 
253*99a2dd95SBruce Richardson 		pkt_type = RTE_PTYPE_L2_ETHER_VLAN;
254*99a2dd95SBruce Richardson 		vh = rte_pktmbuf_read(m, off, sizeof(*vh), &vh_copy);
255*99a2dd95SBruce Richardson 		if (unlikely(vh == NULL))
256*99a2dd95SBruce Richardson 			return pkt_type;
257*99a2dd95SBruce Richardson 		off += sizeof(*vh);
258*99a2dd95SBruce Richardson 		hdr_lens->l2_len += sizeof(*vh);
259*99a2dd95SBruce Richardson 		proto = vh->eth_proto;
260*99a2dd95SBruce Richardson 	} else if (proto == rte_cpu_to_be_16(RTE_ETHER_TYPE_QINQ)) {
261*99a2dd95SBruce Richardson 		const struct rte_vlan_hdr *vh;
262*99a2dd95SBruce Richardson 		struct rte_vlan_hdr vh_copy;
263*99a2dd95SBruce Richardson 
264*99a2dd95SBruce Richardson 		pkt_type = RTE_PTYPE_L2_ETHER_QINQ;
265*99a2dd95SBruce Richardson 		vh = rte_pktmbuf_read(m, off + sizeof(*vh), sizeof(*vh),
266*99a2dd95SBruce Richardson 			&vh_copy);
267*99a2dd95SBruce Richardson 		if (unlikely(vh == NULL))
268*99a2dd95SBruce Richardson 			return pkt_type;
269*99a2dd95SBruce Richardson 		off += 2 * sizeof(*vh);
270*99a2dd95SBruce Richardson 		hdr_lens->l2_len += 2 * sizeof(*vh);
271*99a2dd95SBruce Richardson 		proto = vh->eth_proto;
272*99a2dd95SBruce Richardson 	} else if ((proto == rte_cpu_to_be_16(RTE_ETHER_TYPE_MPLS)) ||
273*99a2dd95SBruce Richardson 		(proto == rte_cpu_to_be_16(RTE_ETHER_TYPE_MPLSM))) {
274*99a2dd95SBruce Richardson 		unsigned int i;
275*99a2dd95SBruce Richardson 		const struct rte_mpls_hdr *mh;
276*99a2dd95SBruce Richardson 		struct rte_mpls_hdr mh_copy;
277*99a2dd95SBruce Richardson 
278*99a2dd95SBruce Richardson #define MAX_MPLS_HDR 5
279*99a2dd95SBruce Richardson 		for (i = 0; i < MAX_MPLS_HDR; i++) {
280*99a2dd95SBruce Richardson 			mh = rte_pktmbuf_read(m, off + (i * sizeof(*mh)),
281*99a2dd95SBruce Richardson 				sizeof(*mh), &mh_copy);
282*99a2dd95SBruce Richardson 			if (unlikely(mh == NULL))
283*99a2dd95SBruce Richardson 				return pkt_type;
284*99a2dd95SBruce Richardson 		}
285*99a2dd95SBruce Richardson 		if (i == MAX_MPLS_HDR)
286*99a2dd95SBruce Richardson 			return pkt_type;
287*99a2dd95SBruce Richardson 		pkt_type = RTE_PTYPE_L2_ETHER_MPLS;
288*99a2dd95SBruce Richardson 		hdr_lens->l2_len += (sizeof(*mh) * i);
289*99a2dd95SBruce Richardson 		return pkt_type;
290*99a2dd95SBruce Richardson 	}
291*99a2dd95SBruce Richardson 
292*99a2dd95SBruce Richardson l3:
293*99a2dd95SBruce Richardson 	if ((layers & RTE_PTYPE_L3_MASK) == 0)
294*99a2dd95SBruce Richardson 		return pkt_type;
295*99a2dd95SBruce Richardson 
296*99a2dd95SBruce Richardson 	if (proto == rte_cpu_to_be_16(RTE_ETHER_TYPE_IPV4)) {
297*99a2dd95SBruce Richardson 		const struct rte_ipv4_hdr *ip4h;
298*99a2dd95SBruce Richardson 		struct rte_ipv4_hdr ip4h_copy;
299*99a2dd95SBruce Richardson 
300*99a2dd95SBruce Richardson 		ip4h = rte_pktmbuf_read(m, off, sizeof(*ip4h), &ip4h_copy);
301*99a2dd95SBruce Richardson 		if (unlikely(ip4h == NULL))
302*99a2dd95SBruce Richardson 			return pkt_type;
303*99a2dd95SBruce Richardson 
304*99a2dd95SBruce Richardson 		pkt_type |= ptype_l3_ip(ip4h->version_ihl);
305*99a2dd95SBruce Richardson 		hdr_lens->l3_len = rte_ipv4_hdr_len(ip4h);
306*99a2dd95SBruce Richardson 		off += hdr_lens->l3_len;
307*99a2dd95SBruce Richardson 
308*99a2dd95SBruce Richardson 		if ((layers & RTE_PTYPE_L4_MASK) == 0)
309*99a2dd95SBruce Richardson 			return pkt_type;
310*99a2dd95SBruce Richardson 
311*99a2dd95SBruce Richardson 		if (ip4h->fragment_offset & rte_cpu_to_be_16(
312*99a2dd95SBruce Richardson 				RTE_IPV4_HDR_OFFSET_MASK | RTE_IPV4_HDR_MF_FLAG)) {
313*99a2dd95SBruce Richardson 			pkt_type |= RTE_PTYPE_L4_FRAG;
314*99a2dd95SBruce Richardson 			hdr_lens->l4_len = 0;
315*99a2dd95SBruce Richardson 			return pkt_type;
316*99a2dd95SBruce Richardson 		}
317*99a2dd95SBruce Richardson 		proto = ip4h->next_proto_id;
318*99a2dd95SBruce Richardson 		pkt_type |= ptype_l4(proto);
319*99a2dd95SBruce Richardson 	} else if (proto == rte_cpu_to_be_16(RTE_ETHER_TYPE_IPV6)) {
320*99a2dd95SBruce Richardson 		const struct rte_ipv6_hdr *ip6h;
321*99a2dd95SBruce Richardson 		struct rte_ipv6_hdr ip6h_copy;
322*99a2dd95SBruce Richardson 		int frag = 0;
323*99a2dd95SBruce Richardson 
324*99a2dd95SBruce Richardson 		ip6h = rte_pktmbuf_read(m, off, sizeof(*ip6h), &ip6h_copy);
325*99a2dd95SBruce Richardson 		if (unlikely(ip6h == NULL))
326*99a2dd95SBruce Richardson 			return pkt_type;
327*99a2dd95SBruce Richardson 
328*99a2dd95SBruce Richardson 		proto = ip6h->proto;
329*99a2dd95SBruce Richardson 		hdr_lens->l3_len = sizeof(*ip6h);
330*99a2dd95SBruce Richardson 		off += hdr_lens->l3_len;
331*99a2dd95SBruce Richardson 		pkt_type |= ptype_l3_ip6(proto);
332*99a2dd95SBruce Richardson 		if ((pkt_type & RTE_PTYPE_L3_MASK) == RTE_PTYPE_L3_IPV6_EXT) {
333*99a2dd95SBruce Richardson 			ret = rte_net_skip_ip6_ext(proto, m, &off, &frag);
334*99a2dd95SBruce Richardson 			if (ret < 0)
335*99a2dd95SBruce Richardson 				return pkt_type;
336*99a2dd95SBruce Richardson 			proto = ret;
337*99a2dd95SBruce Richardson 			hdr_lens->l3_len = off - hdr_lens->l2_len;
338*99a2dd95SBruce Richardson 		}
339*99a2dd95SBruce Richardson 		if (proto == 0)
340*99a2dd95SBruce Richardson 			return pkt_type;
341*99a2dd95SBruce Richardson 
342*99a2dd95SBruce Richardson 		if ((layers & RTE_PTYPE_L4_MASK) == 0)
343*99a2dd95SBruce Richardson 			return pkt_type;
344*99a2dd95SBruce Richardson 
345*99a2dd95SBruce Richardson 		if (frag) {
346*99a2dd95SBruce Richardson 			pkt_type |= RTE_PTYPE_L4_FRAG;
347*99a2dd95SBruce Richardson 			hdr_lens->l4_len = 0;
348*99a2dd95SBruce Richardson 			return pkt_type;
349*99a2dd95SBruce Richardson 		}
350*99a2dd95SBruce Richardson 		pkt_type |= ptype_l4(proto);
351*99a2dd95SBruce Richardson 	}
352*99a2dd95SBruce Richardson 
353*99a2dd95SBruce Richardson 	if ((pkt_type & RTE_PTYPE_L4_MASK) == RTE_PTYPE_L4_UDP) {
354*99a2dd95SBruce Richardson 		hdr_lens->l4_len = sizeof(struct rte_udp_hdr);
355*99a2dd95SBruce Richardson 		return pkt_type;
356*99a2dd95SBruce Richardson 	} else if ((pkt_type & RTE_PTYPE_L4_MASK) == RTE_PTYPE_L4_TCP) {
357*99a2dd95SBruce Richardson 		const struct rte_tcp_hdr *th;
358*99a2dd95SBruce Richardson 		struct rte_tcp_hdr th_copy;
359*99a2dd95SBruce Richardson 
360*99a2dd95SBruce Richardson 		th = rte_pktmbuf_read(m, off, sizeof(*th), &th_copy);
361*99a2dd95SBruce Richardson 		if (unlikely(th == NULL))
362*99a2dd95SBruce Richardson 			return pkt_type & (RTE_PTYPE_L2_MASK |
363*99a2dd95SBruce Richardson 				RTE_PTYPE_L3_MASK);
364*99a2dd95SBruce Richardson 		hdr_lens->l4_len = (th->data_off & 0xf0) >> 2;
365*99a2dd95SBruce Richardson 		return pkt_type;
366*99a2dd95SBruce Richardson 	} else if ((pkt_type & RTE_PTYPE_L4_MASK) == RTE_PTYPE_L4_SCTP) {
367*99a2dd95SBruce Richardson 		hdr_lens->l4_len = sizeof(struct rte_sctp_hdr);
368*99a2dd95SBruce Richardson 		return pkt_type;
369*99a2dd95SBruce Richardson 	} else {
370*99a2dd95SBruce Richardson 		uint32_t prev_off = off;
371*99a2dd95SBruce Richardson 
372*99a2dd95SBruce Richardson 		hdr_lens->l4_len = 0;
373*99a2dd95SBruce Richardson 
374*99a2dd95SBruce Richardson 		if ((layers & RTE_PTYPE_TUNNEL_MASK) == 0)
375*99a2dd95SBruce Richardson 			return pkt_type;
376*99a2dd95SBruce Richardson 
377*99a2dd95SBruce Richardson 		pkt_type |= ptype_tunnel(&proto, m, &off);
378*99a2dd95SBruce Richardson 		hdr_lens->tunnel_len = off - prev_off;
379*99a2dd95SBruce Richardson 	}
380*99a2dd95SBruce Richardson 
381*99a2dd95SBruce Richardson 	/* same job for inner header: we need to duplicate the code
382*99a2dd95SBruce Richardson 	 * because the packet types do not have the same value.
383*99a2dd95SBruce Richardson 	 */
384*99a2dd95SBruce Richardson 	if ((layers & RTE_PTYPE_INNER_L2_MASK) == 0)
385*99a2dd95SBruce Richardson 		return pkt_type;
386*99a2dd95SBruce Richardson 
387*99a2dd95SBruce Richardson 	hdr_lens->inner_l2_len = 0;
388*99a2dd95SBruce Richardson 	if (proto == rte_cpu_to_be_16(RTE_ETHER_TYPE_TEB)) {
389*99a2dd95SBruce Richardson 		eh = rte_pktmbuf_read(m, off, sizeof(*eh), &eh_copy);
390*99a2dd95SBruce Richardson 		if (unlikely(eh == NULL))
391*99a2dd95SBruce Richardson 			return pkt_type;
392*99a2dd95SBruce Richardson 		pkt_type |= RTE_PTYPE_INNER_L2_ETHER;
393*99a2dd95SBruce Richardson 		proto = eh->ether_type;
394*99a2dd95SBruce Richardson 		off += sizeof(*eh);
395*99a2dd95SBruce Richardson 		hdr_lens->inner_l2_len = sizeof(*eh);
396*99a2dd95SBruce Richardson 	}
397*99a2dd95SBruce Richardson 
398*99a2dd95SBruce Richardson 	if (proto == rte_cpu_to_be_16(RTE_ETHER_TYPE_VLAN)) {
399*99a2dd95SBruce Richardson 		const struct rte_vlan_hdr *vh;
400*99a2dd95SBruce Richardson 		struct rte_vlan_hdr vh_copy;
401*99a2dd95SBruce Richardson 
402*99a2dd95SBruce Richardson 		pkt_type &= ~RTE_PTYPE_INNER_L2_MASK;
403*99a2dd95SBruce Richardson 		pkt_type |= RTE_PTYPE_INNER_L2_ETHER_VLAN;
404*99a2dd95SBruce Richardson 		vh = rte_pktmbuf_read(m, off, sizeof(*vh), &vh_copy);
405*99a2dd95SBruce Richardson 		if (unlikely(vh == NULL))
406*99a2dd95SBruce Richardson 			return pkt_type;
407*99a2dd95SBruce Richardson 		off += sizeof(*vh);
408*99a2dd95SBruce Richardson 		hdr_lens->inner_l2_len += sizeof(*vh);
409*99a2dd95SBruce Richardson 		proto = vh->eth_proto;
410*99a2dd95SBruce Richardson 	} else if (proto == rte_cpu_to_be_16(RTE_ETHER_TYPE_QINQ)) {
411*99a2dd95SBruce Richardson 		const struct rte_vlan_hdr *vh;
412*99a2dd95SBruce Richardson 		struct rte_vlan_hdr vh_copy;
413*99a2dd95SBruce Richardson 
414*99a2dd95SBruce Richardson 		pkt_type &= ~RTE_PTYPE_INNER_L2_MASK;
415*99a2dd95SBruce Richardson 		pkt_type |= RTE_PTYPE_INNER_L2_ETHER_QINQ;
416*99a2dd95SBruce Richardson 		vh = rte_pktmbuf_read(m, off + sizeof(*vh), sizeof(*vh),
417*99a2dd95SBruce Richardson 			&vh_copy);
418*99a2dd95SBruce Richardson 		if (unlikely(vh == NULL))
419*99a2dd95SBruce Richardson 			return pkt_type;
420*99a2dd95SBruce Richardson 		off += 2 * sizeof(*vh);
421*99a2dd95SBruce Richardson 		hdr_lens->inner_l2_len += 2 * sizeof(*vh);
422*99a2dd95SBruce Richardson 		proto = vh->eth_proto;
423*99a2dd95SBruce Richardson 	}
424*99a2dd95SBruce Richardson 
425*99a2dd95SBruce Richardson 	if ((layers & RTE_PTYPE_INNER_L3_MASK) == 0)
426*99a2dd95SBruce Richardson 		return pkt_type;
427*99a2dd95SBruce Richardson 
428*99a2dd95SBruce Richardson 	if (proto == rte_cpu_to_be_16(RTE_ETHER_TYPE_IPV4)) {
429*99a2dd95SBruce Richardson 		const struct rte_ipv4_hdr *ip4h;
430*99a2dd95SBruce Richardson 		struct rte_ipv4_hdr ip4h_copy;
431*99a2dd95SBruce Richardson 
432*99a2dd95SBruce Richardson 		ip4h = rte_pktmbuf_read(m, off, sizeof(*ip4h), &ip4h_copy);
433*99a2dd95SBruce Richardson 		if (unlikely(ip4h == NULL))
434*99a2dd95SBruce Richardson 			return pkt_type;
435*99a2dd95SBruce Richardson 
436*99a2dd95SBruce Richardson 		pkt_type |= ptype_inner_l3_ip(ip4h->version_ihl);
437*99a2dd95SBruce Richardson 		hdr_lens->inner_l3_len = rte_ipv4_hdr_len(ip4h);
438*99a2dd95SBruce Richardson 		off += hdr_lens->inner_l3_len;
439*99a2dd95SBruce Richardson 
440*99a2dd95SBruce Richardson 		if ((layers & RTE_PTYPE_INNER_L4_MASK) == 0)
441*99a2dd95SBruce Richardson 			return pkt_type;
442*99a2dd95SBruce Richardson 		if (ip4h->fragment_offset &
443*99a2dd95SBruce Richardson 				rte_cpu_to_be_16(RTE_IPV4_HDR_OFFSET_MASK |
444*99a2dd95SBruce Richardson 					RTE_IPV4_HDR_MF_FLAG)) {
445*99a2dd95SBruce Richardson 			pkt_type |= RTE_PTYPE_INNER_L4_FRAG;
446*99a2dd95SBruce Richardson 			hdr_lens->inner_l4_len = 0;
447*99a2dd95SBruce Richardson 			return pkt_type;
448*99a2dd95SBruce Richardson 		}
449*99a2dd95SBruce Richardson 		proto = ip4h->next_proto_id;
450*99a2dd95SBruce Richardson 		pkt_type |= ptype_inner_l4(proto);
451*99a2dd95SBruce Richardson 	} else if (proto == rte_cpu_to_be_16(RTE_ETHER_TYPE_IPV6)) {
452*99a2dd95SBruce Richardson 		const struct rte_ipv6_hdr *ip6h;
453*99a2dd95SBruce Richardson 		struct rte_ipv6_hdr ip6h_copy;
454*99a2dd95SBruce Richardson 		int frag = 0;
455*99a2dd95SBruce Richardson 
456*99a2dd95SBruce Richardson 		ip6h = rte_pktmbuf_read(m, off, sizeof(*ip6h), &ip6h_copy);
457*99a2dd95SBruce Richardson 		if (unlikely(ip6h == NULL))
458*99a2dd95SBruce Richardson 			return pkt_type;
459*99a2dd95SBruce Richardson 
460*99a2dd95SBruce Richardson 		proto = ip6h->proto;
461*99a2dd95SBruce Richardson 		hdr_lens->inner_l3_len = sizeof(*ip6h);
462*99a2dd95SBruce Richardson 		off += hdr_lens->inner_l3_len;
463*99a2dd95SBruce Richardson 		pkt_type |= ptype_inner_l3_ip6(proto);
464*99a2dd95SBruce Richardson 		if ((pkt_type & RTE_PTYPE_INNER_L3_MASK) ==
465*99a2dd95SBruce Richardson 				RTE_PTYPE_INNER_L3_IPV6_EXT) {
466*99a2dd95SBruce Richardson 			uint32_t prev_off;
467*99a2dd95SBruce Richardson 
468*99a2dd95SBruce Richardson 			prev_off = off;
469*99a2dd95SBruce Richardson 			ret = rte_net_skip_ip6_ext(proto, m, &off, &frag);
470*99a2dd95SBruce Richardson 			if (ret < 0)
471*99a2dd95SBruce Richardson 				return pkt_type;
472*99a2dd95SBruce Richardson 			proto = ret;
473*99a2dd95SBruce Richardson 			hdr_lens->inner_l3_len += off - prev_off;
474*99a2dd95SBruce Richardson 		}
475*99a2dd95SBruce Richardson 		if (proto == 0)
476*99a2dd95SBruce Richardson 			return pkt_type;
477*99a2dd95SBruce Richardson 
478*99a2dd95SBruce Richardson 		if ((layers & RTE_PTYPE_INNER_L4_MASK) == 0)
479*99a2dd95SBruce Richardson 			return pkt_type;
480*99a2dd95SBruce Richardson 
481*99a2dd95SBruce Richardson 		if (frag) {
482*99a2dd95SBruce Richardson 			pkt_type |= RTE_PTYPE_INNER_L4_FRAG;
483*99a2dd95SBruce Richardson 			hdr_lens->inner_l4_len = 0;
484*99a2dd95SBruce Richardson 			return pkt_type;
485*99a2dd95SBruce Richardson 		}
486*99a2dd95SBruce Richardson 		pkt_type |= ptype_inner_l4(proto);
487*99a2dd95SBruce Richardson 	}
488*99a2dd95SBruce Richardson 
489*99a2dd95SBruce Richardson 	if ((pkt_type & RTE_PTYPE_INNER_L4_MASK) == RTE_PTYPE_INNER_L4_UDP) {
490*99a2dd95SBruce Richardson 		hdr_lens->inner_l4_len = sizeof(struct rte_udp_hdr);
491*99a2dd95SBruce Richardson 	} else if ((pkt_type & RTE_PTYPE_INNER_L4_MASK) ==
492*99a2dd95SBruce Richardson 			RTE_PTYPE_INNER_L4_TCP) {
493*99a2dd95SBruce Richardson 		const struct rte_tcp_hdr *th;
494*99a2dd95SBruce Richardson 		struct rte_tcp_hdr th_copy;
495*99a2dd95SBruce Richardson 
496*99a2dd95SBruce Richardson 		th = rte_pktmbuf_read(m, off, sizeof(*th), &th_copy);
497*99a2dd95SBruce Richardson 		if (unlikely(th == NULL))
498*99a2dd95SBruce Richardson 			return pkt_type & (RTE_PTYPE_INNER_L2_MASK |
499*99a2dd95SBruce Richardson 				RTE_PTYPE_INNER_L3_MASK);
500*99a2dd95SBruce Richardson 		hdr_lens->inner_l4_len = (th->data_off & 0xf0) >> 2;
501*99a2dd95SBruce Richardson 	} else if ((pkt_type & RTE_PTYPE_INNER_L4_MASK) ==
502*99a2dd95SBruce Richardson 			RTE_PTYPE_INNER_L4_SCTP) {
503*99a2dd95SBruce Richardson 		hdr_lens->inner_l4_len = sizeof(struct rte_sctp_hdr);
504*99a2dd95SBruce Richardson 	} else {
505*99a2dd95SBruce Richardson 		hdr_lens->inner_l4_len = 0;
506*99a2dd95SBruce Richardson 	}
507*99a2dd95SBruce Richardson 
508*99a2dd95SBruce Richardson 	return pkt_type;
509*99a2dd95SBruce Richardson }
510