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