Branch data Line data Source code
1 : : /* SPDX-License-Identifier: BSD-3-Clause
2 : : * Copyright 2016 6WIND S.A.
3 : : */
4 : :
5 : : #include <stdint.h>
6 : :
7 : : #include <eal_export.h>
8 : : #include <rte_mbuf.h>
9 : : #include <rte_mbuf_ptype.h>
10 : : #include <rte_byteorder.h>
11 : : #include <rte_ether.h>
12 : : #include <rte_ip.h>
13 : : #include <rte_tcp.h>
14 : : #include <rte_udp.h>
15 : : #include <rte_sctp.h>
16 : : #include <rte_gre.h>
17 : : #include <rte_mpls.h>
18 : : #include <rte_geneve.h>
19 : : #include <rte_vxlan.h>
20 : : #include <rte_gtp.h>
21 : : #include <rte_net.h>
22 : : #include <rte_os_shim.h>
23 : :
24 : : /* get l3 packet type from ip6 next protocol */
25 : : static uint32_t
26 : : ptype_l3_ip6(uint8_t ip6_proto)
27 : : {
28 : : static const uint32_t ip6_ext_proto_map[256] = {
29 : : [IPPROTO_HOPOPTS] = RTE_PTYPE_L3_IPV6_EXT - RTE_PTYPE_L3_IPV6,
30 : : [IPPROTO_ROUTING] = RTE_PTYPE_L3_IPV6_EXT - RTE_PTYPE_L3_IPV6,
31 : : [IPPROTO_FRAGMENT] = RTE_PTYPE_L3_IPV6_EXT - RTE_PTYPE_L3_IPV6,
32 : : [IPPROTO_ESP] = RTE_PTYPE_L3_IPV6_EXT - RTE_PTYPE_L3_IPV6,
33 : : [IPPROTO_AH] = RTE_PTYPE_L3_IPV6_EXT - RTE_PTYPE_L3_IPV6,
34 : : [IPPROTO_DSTOPTS] = RTE_PTYPE_L3_IPV6_EXT - RTE_PTYPE_L3_IPV6,
35 : : };
36 : :
37 : 1 : return RTE_PTYPE_L3_IPV6 + ip6_ext_proto_map[ip6_proto];
38 : : }
39 : :
40 : : /* get l3 packet type from ip version and header length */
41 : : static uint32_t
42 : : ptype_l3_ip(uint8_t ipv_ihl)
43 : : {
44 : : static const uint32_t ptype_l3_ip_proto_map[256] = {
45 : : [0x45] = RTE_PTYPE_L3_IPV4,
46 : : [0x46] = RTE_PTYPE_L3_IPV4_EXT,
47 : : [0x47] = RTE_PTYPE_L3_IPV4_EXT,
48 : : [0x48] = RTE_PTYPE_L3_IPV4_EXT,
49 : : [0x49] = RTE_PTYPE_L3_IPV4_EXT,
50 : : [0x4A] = RTE_PTYPE_L3_IPV4_EXT,
51 : : [0x4B] = RTE_PTYPE_L3_IPV4_EXT,
52 : : [0x4C] = RTE_PTYPE_L3_IPV4_EXT,
53 : : [0x4D] = RTE_PTYPE_L3_IPV4_EXT,
54 : : [0x4E] = RTE_PTYPE_L3_IPV4_EXT,
55 : : [0x4F] = RTE_PTYPE_L3_IPV4_EXT,
56 : : };
57 : :
58 : 10 : return ptype_l3_ip_proto_map[ipv_ihl];
59 : : }
60 : :
61 : : /* get l4 packet type from proto */
62 : : static uint32_t
63 : : ptype_l4(uint8_t proto)
64 : : {
65 : : static const uint32_t ptype_l4_proto[256] = {
66 : : [IPPROTO_UDP] = RTE_PTYPE_L4_UDP,
67 : : [IPPROTO_TCP] = RTE_PTYPE_L4_TCP,
68 : : [IPPROTO_SCTP] = RTE_PTYPE_L4_SCTP,
69 : : };
70 : :
71 : 10 : return ptype_l4_proto[proto];
72 : : }
73 : :
74 : : /* get inner l3 packet type from ip6 next protocol */
75 : : static uint32_t
76 : : ptype_inner_l3_ip6(uint8_t ip6_proto)
77 : : {
78 : : static const uint32_t ptype_inner_ip6_ext_proto_map[256] = {
79 : : [IPPROTO_HOPOPTS] = RTE_PTYPE_INNER_L3_IPV6_EXT -
80 : : RTE_PTYPE_INNER_L3_IPV6,
81 : : [IPPROTO_ROUTING] = RTE_PTYPE_INNER_L3_IPV6_EXT -
82 : : RTE_PTYPE_INNER_L3_IPV6,
83 : : [IPPROTO_FRAGMENT] = RTE_PTYPE_INNER_L3_IPV6_EXT -
84 : : RTE_PTYPE_INNER_L3_IPV6,
85 : : [IPPROTO_ESP] = RTE_PTYPE_INNER_L3_IPV6_EXT -
86 : : RTE_PTYPE_INNER_L3_IPV6,
87 : : [IPPROTO_AH] = RTE_PTYPE_INNER_L3_IPV6_EXT -
88 : : RTE_PTYPE_INNER_L3_IPV6,
89 : : [IPPROTO_DSTOPTS] = RTE_PTYPE_INNER_L3_IPV6_EXT -
90 : : RTE_PTYPE_INNER_L3_IPV6,
91 : : };
92 : :
93 : 0 : return RTE_PTYPE_INNER_L3_IPV6 +
94 : 0 : ptype_inner_ip6_ext_proto_map[ip6_proto];
95 : : }
96 : :
97 : : /* get inner l3 packet type from ip version and header length */
98 : : static uint32_t
99 : : ptype_inner_l3_ip(uint8_t ipv_ihl)
100 : : {
101 : : static const uint32_t ptype_inner_l3_ip_proto_map[256] = {
102 : : [0x45] = RTE_PTYPE_INNER_L3_IPV4,
103 : : [0x46] = RTE_PTYPE_INNER_L3_IPV4_EXT,
104 : : [0x47] = RTE_PTYPE_INNER_L3_IPV4_EXT,
105 : : [0x48] = RTE_PTYPE_INNER_L3_IPV4_EXT,
106 : : [0x49] = RTE_PTYPE_INNER_L3_IPV4_EXT,
107 : : [0x4A] = RTE_PTYPE_INNER_L3_IPV4_EXT,
108 : : [0x4B] = RTE_PTYPE_INNER_L3_IPV4_EXT,
109 : : [0x4C] = RTE_PTYPE_INNER_L3_IPV4_EXT,
110 : : [0x4D] = RTE_PTYPE_INNER_L3_IPV4_EXT,
111 : : [0x4E] = RTE_PTYPE_INNER_L3_IPV4_EXT,
112 : : [0x4F] = RTE_PTYPE_INNER_L3_IPV4_EXT,
113 : : };
114 : :
115 : 0 : return ptype_inner_l3_ip_proto_map[ipv_ihl];
116 : : }
117 : :
118 : : /* get inner l4 packet type from proto */
119 : : static uint32_t
120 : : ptype_inner_l4(uint8_t proto)
121 : : {
122 : : static const uint32_t ptype_inner_l4_proto[256] = {
123 : : [IPPROTO_UDP] = RTE_PTYPE_INNER_L4_UDP,
124 : : [IPPROTO_TCP] = RTE_PTYPE_INNER_L4_TCP,
125 : : [IPPROTO_SCTP] = RTE_PTYPE_INNER_L4_SCTP,
126 : : };
127 : :
128 : 0 : return ptype_inner_l4_proto[proto];
129 : : }
130 : :
131 : : /* get the tunnel packet type if any, update proto and off. */
132 : : static uint32_t
133 : 6 : ptype_tunnel_without_udp(uint16_t *proto, const struct rte_mbuf *m,
134 : : uint32_t *off)
135 : : {
136 [ - - - + ]: 6 : switch (*proto) {
137 : 0 : case IPPROTO_GRE: {
138 : : static const uint8_t opt_len[16] = {
139 : : [0x0] = 4,
140 : : [0x1] = 8,
141 : : [0x2] = 8,
142 : : [0x8] = 8,
143 : : [0x3] = 12,
144 : : [0x9] = 12,
145 : : [0xa] = 12,
146 : : [0xb] = 16,
147 : : };
148 : : const struct rte_gre_hdr *gh;
149 : : struct rte_gre_hdr gh_copy;
150 : : uint16_t flags;
151 : :
152 [ # # ]: 0 : gh = rte_pktmbuf_read(m, *off, sizeof(*gh), &gh_copy);
153 [ # # ]: 0 : if (unlikely(gh == NULL))
154 : : return 0;
155 : :
156 [ # # ]: 0 : flags = rte_be_to_cpu_16(*(const uint16_t *)gh);
157 : 0 : flags >>= 12;
158 [ # # ]: 0 : if (opt_len[flags] == 0)
159 : : return 0;
160 : :
161 : 0 : *off += opt_len[flags];
162 : 0 : *proto = gh->proto;
163 [ # # ]: 0 : if (*proto == rte_cpu_to_be_16(RTE_ETHER_TYPE_TEB))
164 : : return RTE_PTYPE_TUNNEL_NVGRE;
165 : : else
166 : 0 : return RTE_PTYPE_TUNNEL_GRE;
167 : : }
168 : : case IPPROTO_IPIP:
169 : 0 : *proto = rte_cpu_to_be_16(RTE_ETHER_TYPE_IPV4);
170 : 0 : return RTE_PTYPE_TUNNEL_IP;
171 : : case IPPROTO_IPV6:
172 : 0 : *proto = rte_cpu_to_be_16(RTE_ETHER_TYPE_IPV6);
173 : 0 : return RTE_PTYPE_TUNNEL_IP; /* IP is also valid for IPv6 */
174 : : default:
175 : : return 0;
176 : : }
177 : : }
178 : :
179 : : /* get the tunnel packet type with UDP port if any, update proto and off. */
180 : : static uint32_t
181 : 3 : ptype_tunnel_with_udp(uint16_t *proto, const struct rte_mbuf *m,
182 : : uint32_t *off, struct rte_net_hdr_lens *hdr_lens)
183 : : {
184 : : const struct rte_udp_hdr *uh;
185 : : struct rte_udp_hdr uh_copy;
186 : : uint16_t port_no;
187 : :
188 [ + - ]: 3 : uh = rte_pktmbuf_read(m, *off, sizeof(*uh), &uh_copy);
189 [ + - ]: 3 : if (unlikely(uh == NULL))
190 : : return 0;
191 : :
192 : 3 : *off += sizeof(*uh);
193 [ - + - + ]: 6 : if (rte_be_to_cpu_16(uh->src_port) == RTE_GTPC_UDP_PORT)
194 [ # # ]: 0 : port_no = rte_be_to_cpu_16(uh->src_port);
195 : : else
196 [ - + ]: 3 : port_no = rte_be_to_cpu_16(uh->dst_port);
197 [ - - - - : 3 : switch (port_no) {
+ ]
198 : 0 : case RTE_VXLAN_DEFAULT_PORT: {
199 : 0 : *off += sizeof(struct rte_vxlan_hdr);
200 : 0 : hdr_lens->tunnel_len = sizeof(struct rte_vxlan_hdr);
201 : 0 : hdr_lens->inner_l2_len = RTE_ETHER_VXLAN_HLEN;
202 : 0 : *proto = RTE_VXLAN_GPE_TYPE_ETH; /* just for eth header parse. */
203 : 0 : return RTE_PTYPE_TUNNEL_VXLAN;
204 : : }
205 [ # # ]: 0 : case RTE_VXLAN_GPE_DEFAULT_PORT: {
206 : : const struct rte_vxlan_gpe_hdr *vgh;
207 : : struct rte_vxlan_gpe_hdr vgh_copy;
208 : : vgh = rte_pktmbuf_read(m, *off, sizeof(*vgh), &vgh_copy);
209 [ # # ]: 0 : if (unlikely(vgh == NULL))
210 : : return 0;
211 : 0 : *off += sizeof(struct rte_vxlan_gpe_hdr);
212 : 0 : hdr_lens->tunnel_len = sizeof(struct rte_vxlan_gpe_hdr);
213 : 0 : hdr_lens->inner_l2_len = RTE_ETHER_VXLAN_GPE_HLEN;
214 : 0 : *proto = vgh->proto;
215 : :
216 : 0 : return RTE_PTYPE_TUNNEL_VXLAN_GPE;
217 : : }
218 [ # # ]: 0 : case RTE_GTPC_UDP_PORT:
219 : : case RTE_GTPU_UDP_PORT: {
220 : : const struct rte_gtp_hdr *gh;
221 : : struct rte_gtp_hdr gh_copy;
222 : : uint32_t gtp_len;
223 : : gh = rte_pktmbuf_read(m, *off, sizeof(*gh), &gh_copy);
224 [ # # ]: 0 : if (unlikely(gh == NULL))
225 : : return 0;
226 : : gtp_len = sizeof(*gh);
227 [ # # ]: 0 : if (gh->e || gh->s || gh->pn)
228 : : gtp_len += sizeof(struct rte_gtp_hdr_ext_word);
229 : : /*
230 : : * Check message type. If message type is 0xff, it is
231 : : * a GTP data packet. If not, it is a GTP control packet
232 : : */
233 : 0 : *off += gtp_len;
234 [ # # ]: 0 : if (gh->msg_type == 0xff) {
235 : : const uint8_t *l3_byte;
236 : : uint8_t l3_copy, ip_ver;
237 : :
238 : : /* read first byte of l3 header */
239 : : l3_byte = rte_pktmbuf_read(m, *off, sizeof(uint8_t), &l3_copy);
240 [ # # ]: 0 : if (unlikely(l3_byte == NULL))
241 : 0 : return 0;
242 : :
243 : 0 : ip_ver = *l3_byte & 0xf0;
244 [ # # ]: 0 : if (ip_ver == RTE_GTP_TYPE_IPV4)
245 : 0 : *proto = rte_cpu_to_be_16(RTE_ETHER_TYPE_IPV4);
246 [ # # ]: 0 : else if (ip_ver == RTE_GTP_TYPE_IPV6)
247 : 0 : *proto = rte_cpu_to_be_16(RTE_ETHER_TYPE_IPV6);
248 : : else
249 : 0 : *proto = 0;
250 : : } else {
251 : 0 : *proto = 0;
252 : : }
253 : 0 : hdr_lens->inner_l2_len = gtp_len + sizeof(struct rte_udp_hdr);
254 : 0 : hdr_lens->tunnel_len = gtp_len;
255 [ # # ]: 0 : if (port_no == RTE_GTPC_UDP_PORT)
256 : : return RTE_PTYPE_TUNNEL_GTPC;
257 : : else if (port_no == RTE_GTPU_UDP_PORT)
258 : 0 : return RTE_PTYPE_TUNNEL_GTPU;
259 : : return 0;
260 : : }
261 [ # # ]: 0 : case RTE_GENEVE_DEFAULT_PORT: {
262 : : const struct rte_geneve_hdr *gnh;
263 : : struct rte_geneve_hdr gnh_copy;
264 : : uint16_t geneve_len;
265 : : gnh = rte_pktmbuf_read(m, *off, sizeof(*gnh), &gnh_copy);
266 [ # # ]: 0 : if (unlikely(gnh == NULL))
267 : : return 0;
268 : 0 : geneve_len = sizeof(*gnh) + gnh->opt_len * 4;
269 : 0 : *off += geneve_len;
270 : 0 : hdr_lens->tunnel_len = geneve_len;
271 : 0 : hdr_lens->inner_l2_len = sizeof(struct rte_udp_hdr) + geneve_len;
272 : 0 : *proto = gnh->proto;
273 [ # # ]: 0 : if (gnh->proto == 0)
274 : 0 : *proto = rte_cpu_to_be_16(RTE_ETHER_TYPE_IPV4);
275 : : return RTE_PTYPE_TUNNEL_GENEVE;
276 : : }
277 : : default:
278 : : return 0;
279 : : }
280 : : }
281 : :
282 : : /* parse ipv6 extended headers, update offset and return next proto */
283 : : RTE_EXPORT_SYMBOL(rte_net_skip_ip6_ext)
284 : : int
285 : 0 : rte_net_skip_ip6_ext(uint16_t proto, const struct rte_mbuf *m, uint32_t *off,
286 : : int *frag)
287 : : {
288 : : struct ext_hdr {
289 : : uint8_t next_hdr;
290 : : uint8_t len;
291 : : };
292 : : const struct ext_hdr *xh;
293 : : struct ext_hdr xh_copy;
294 : : unsigned int i;
295 : :
296 : 0 : *frag = 0;
297 : :
298 : : #define MAX_EXT_HDRS 5
299 [ # # ]: 0 : for (i = 0; i < MAX_EXT_HDRS; i++) {
300 [ # # # # ]: 0 : switch (proto) {
301 : 0 : case IPPROTO_HOPOPTS:
302 : : case IPPROTO_ROUTING:
303 : : case IPPROTO_DSTOPTS:
304 [ # # ]: 0 : xh = rte_pktmbuf_read(m, *off, sizeof(*xh),
305 : : &xh_copy);
306 [ # # ]: 0 : if (xh == NULL)
307 : : return -1;
308 : 0 : *off += (xh->len + 1) * 8;
309 : 0 : proto = xh->next_hdr;
310 : : break;
311 : 0 : case IPPROTO_FRAGMENT:
312 [ # # ]: 0 : xh = rte_pktmbuf_read(m, *off, sizeof(*xh),
313 : : &xh_copy);
314 [ # # ]: 0 : if (xh == NULL)
315 : : return -1;
316 : 0 : *off += 8;
317 : 0 : proto = xh->next_hdr;
318 : 0 : *frag = 1;
319 : 0 : return proto; /* this is always the last ext hdr */
320 : : case IPPROTO_NONE:
321 : : return 0;
322 : : default:
323 : : return proto;
324 : : }
325 : : }
326 : : return -1;
327 : : }
328 : :
329 : : /* limit number of supported VLAN headers */
330 : : #define RTE_NET_VLAN_MAX_DEPTH 8
331 : :
332 : : /* parse mbuf data to get packet type */
333 : : RTE_EXPORT_SYMBOL(rte_net_get_ptype)
334 : 11 : uint32_t rte_net_get_ptype(const struct rte_mbuf *m,
335 : : struct rte_net_hdr_lens *hdr_lens, uint32_t layers)
336 : : {
337 : : struct rte_net_hdr_lens local_hdr_lens;
338 : : const struct rte_ether_hdr *eh;
339 : : struct rte_ether_hdr eh_copy;
340 : : uint32_t pkt_type = RTE_PTYPE_L2_ETHER;
341 : 11 : uint32_t off = 0, vlan_depth = 0;
342 : : uint16_t proto;
343 : : int ret;
344 : :
345 [ - + ]: 11 : if (hdr_lens == NULL)
346 : : hdr_lens = &local_hdr_lens;
347 : :
348 : : eh = rte_pktmbuf_read(m, off, sizeof(*eh), &eh_copy);
349 [ + - ]: 11 : if (unlikely(eh == NULL))
350 : : return 0;
351 : 11 : proto = eh->ether_type;
352 : 11 : off = sizeof(*eh);
353 : 11 : hdr_lens->l2_len = off;
354 : :
355 [ + - ]: 11 : if ((layers & RTE_PTYPE_L2_MASK) == 0)
356 : : return 0;
357 : :
358 [ + + ]: 11 : if (proto == rte_cpu_to_be_16(RTE_ETHER_TYPE_IPV4))
359 : 10 : goto l3; /* fast path if packet is IPv4 */
360 : :
361 [ - + - + ]: 1 : while (proto == rte_cpu_to_be_16(RTE_ETHER_TYPE_VLAN) ||
362 : : proto == rte_cpu_to_be_16(RTE_ETHER_TYPE_QINQ)) {
363 : : const struct rte_vlan_hdr *vh;
364 : : struct rte_vlan_hdr vh_copy;
365 : :
366 [ # # ]: 0 : if (++vlan_depth > RTE_NET_VLAN_MAX_DEPTH)
367 : 0 : return 0;
368 : : pkt_type |=
369 : : proto == rte_cpu_to_be_16(RTE_ETHER_TYPE_VLAN) ?
370 : : RTE_PTYPE_L2_ETHER_VLAN :
371 : : RTE_PTYPE_L2_ETHER_QINQ;
372 [ # # ]: 0 : vh = rte_pktmbuf_read(m, off, sizeof(*vh), &vh_copy);
373 [ # # ]: 0 : if (unlikely(vh == NULL))
374 : : return pkt_type;
375 : 0 : off += sizeof(*vh);
376 : 0 : hdr_lens->l2_len += sizeof(*vh);
377 : 0 : proto = vh->eth_proto;
378 : : }
379 : :
380 [ + - - + ]: 1 : if ((proto == rte_cpu_to_be_16(RTE_ETHER_TYPE_MPLS)) ||
381 : : (proto == rte_cpu_to_be_16(RTE_ETHER_TYPE_MPLSM))) {
382 : : unsigned int i;
383 : : const struct rte_mpls_hdr *mh;
384 : : struct rte_mpls_hdr mh_copy;
385 : :
386 : : #define MAX_MPLS_HDR 5
387 [ # # ]: 0 : for (i = 0; i < MAX_MPLS_HDR; i++) {
388 [ # # ]: 0 : mh = rte_pktmbuf_read(m, off + (i * sizeof(*mh)),
389 : : sizeof(*mh), &mh_copy);
390 [ # # ]: 0 : if (unlikely(mh == NULL))
391 : : return pkt_type;
392 : : }
393 : : if (i == MAX_MPLS_HDR)
394 : : return pkt_type;
395 : : pkt_type = RTE_PTYPE_L2_ETHER_MPLS;
396 : : hdr_lens->l2_len += (sizeof(*mh) * i);
397 : : return pkt_type;
398 : : }
399 : :
400 : 1 : l3:
401 [ + - ]: 11 : if ((layers & RTE_PTYPE_L3_MASK) == 0)
402 : : return pkt_type;
403 : :
404 [ + + ]: 11 : if (proto == rte_cpu_to_be_16(RTE_ETHER_TYPE_IPV4)) {
405 : : const struct rte_ipv4_hdr *ip4h;
406 : : struct rte_ipv4_hdr ip4h_copy;
407 : :
408 [ + - ]: 10 : ip4h = rte_pktmbuf_read(m, off, sizeof(*ip4h), &ip4h_copy);
409 [ + - ]: 10 : if (unlikely(ip4h == NULL))
410 : 1 : return pkt_type;
411 : :
412 [ + - ]: 10 : pkt_type |= ptype_l3_ip(ip4h->version_ihl);
413 : 10 : hdr_lens->l3_len = rte_ipv4_hdr_len(ip4h);
414 : 10 : off += hdr_lens->l3_len;
415 : :
416 [ + - ]: 10 : if ((layers & RTE_PTYPE_L4_MASK) == 0)
417 : : return pkt_type;
418 : :
419 [ + + ]: 10 : if (ip4h->fragment_offset & rte_cpu_to_be_16(
420 : : RTE_IPV4_HDR_OFFSET_MASK | RTE_IPV4_HDR_MF_FLAG)) {
421 : 1 : pkt_type |= RTE_PTYPE_L4_FRAG;
422 : 1 : hdr_lens->l4_len = 0;
423 : 1 : return pkt_type;
424 : : }
425 : 9 : proto = ip4h->next_proto_id;
426 : 9 : pkt_type |= ptype_l4(proto);
427 [ + - ]: 1 : } else if (proto == rte_cpu_to_be_16(RTE_ETHER_TYPE_IPV6)) {
428 : : const struct rte_ipv6_hdr *ip6h;
429 : : struct rte_ipv6_hdr ip6h_copy;
430 : 1 : int frag = 0;
431 : :
432 [ + - ]: 1 : ip6h = rte_pktmbuf_read(m, off, sizeof(*ip6h), &ip6h_copy);
433 [ + - ]: 1 : if (unlikely(ip6h == NULL))
434 : 0 : return pkt_type;
435 : :
436 : 1 : proto = ip6h->proto;
437 : 1 : hdr_lens->l3_len = sizeof(*ip6h);
438 : 1 : off += hdr_lens->l3_len;
439 : 1 : pkt_type |= ptype_l3_ip6(proto);
440 [ - + ]: 1 : if ((pkt_type & RTE_PTYPE_L3_MASK) == RTE_PTYPE_L3_IPV6_EXT) {
441 : 0 : ret = rte_net_skip_ip6_ext(proto, m, &off, &frag);
442 [ # # ]: 0 : if (ret < 0)
443 : : return pkt_type;
444 : 0 : proto = ret;
445 : 0 : hdr_lens->l3_len = off - hdr_lens->l2_len;
446 : : }
447 [ + - ]: 1 : if (proto == 0)
448 : : return pkt_type;
449 : :
450 [ + - ]: 1 : if ((layers & RTE_PTYPE_L4_MASK) == 0)
451 : : return pkt_type;
452 : :
453 [ - + ]: 1 : if (frag) {
454 : 0 : pkt_type |= RTE_PTYPE_L4_FRAG;
455 : 0 : hdr_lens->l4_len = 0;
456 : 0 : return pkt_type;
457 : : }
458 : 1 : pkt_type |= ptype_l4(proto);
459 : : }
460 : :
461 [ + + ]: 10 : if ((pkt_type & RTE_PTYPE_L4_MASK) == RTE_PTYPE_L4_UDP) {
462 : 3 : hdr_lens->l4_len = sizeof(struct rte_udp_hdr);
463 [ + - ]: 3 : if ((layers & RTE_PTYPE_TUNNEL_MASK) == 0)
464 : : return pkt_type;
465 : 3 : pkt_type |= ptype_tunnel_with_udp(&proto, m, &off, hdr_lens);
466 [ + + ]: 7 : } else if ((pkt_type & RTE_PTYPE_L4_MASK) == RTE_PTYPE_L4_TCP) {
467 : : const struct rte_tcp_hdr *th;
468 : : struct rte_tcp_hdr th_copy;
469 : :
470 [ + - ]: 1 : th = rte_pktmbuf_read(m, off, sizeof(*th), &th_copy);
471 [ - + ]: 1 : if (unlikely(th == NULL))
472 : 0 : return pkt_type & (RTE_PTYPE_L2_MASK |
473 : : RTE_PTYPE_L3_MASK);
474 : 1 : hdr_lens->l4_len = (th->data_off & 0xf0) >> 2;
475 : 1 : return pkt_type;
476 [ - + ]: 6 : } else if ((pkt_type & RTE_PTYPE_L4_MASK) == RTE_PTYPE_L4_SCTP) {
477 : 0 : hdr_lens->l4_len = sizeof(struct rte_sctp_hdr);
478 : 0 : return pkt_type;
479 : : } else {
480 : 6 : uint32_t prev_off = off;
481 : :
482 : 6 : hdr_lens->l4_len = 0;
483 : :
484 [ + - ]: 6 : if ((layers & RTE_PTYPE_TUNNEL_MASK) == 0)
485 : : return pkt_type;
486 : :
487 : 6 : pkt_type |= ptype_tunnel_without_udp(&proto, m, &off);
488 : 6 : hdr_lens->tunnel_len = off - prev_off;
489 : 6 : hdr_lens->inner_l2_len = off - prev_off;
490 : : }
491 : :
492 : : /* same job for inner header: we need to duplicate the code
493 : : * because the packet types do not have the same value.
494 : : */
495 [ + - ]: 9 : if ((layers & RTE_PTYPE_INNER_L2_MASK) == 0)
496 : : return pkt_type;
497 : :
498 [ + - ]: 9 : if (proto == rte_cpu_to_be_16(RTE_ETHER_TYPE_TEB) ||
499 [ - + ]: 9 : proto == rte_cpu_to_be_16(RTE_GENEVE_TYPE_ETH) ||
500 : : proto == RTE_VXLAN_GPE_TYPE_ETH) {
501 [ # # ]: 0 : eh = rte_pktmbuf_read(m, off, sizeof(*eh), &eh_copy);
502 [ # # ]: 0 : if (unlikely(eh == NULL))
503 : : return pkt_type;
504 : 0 : pkt_type |= RTE_PTYPE_INNER_L2_ETHER;
505 : 0 : proto = eh->ether_type;
506 : 0 : off += sizeof(*eh);
507 : 0 : hdr_lens->inner_l2_len += sizeof(*eh);
508 : : }
509 : :
510 [ - + ]: 9 : if (proto == rte_cpu_to_be_16(RTE_ETHER_TYPE_VLAN)) {
511 : : const struct rte_vlan_hdr *vh;
512 : : struct rte_vlan_hdr vh_copy;
513 : :
514 : 0 : pkt_type &= ~RTE_PTYPE_INNER_L2_MASK;
515 : 0 : pkt_type |= RTE_PTYPE_INNER_L2_ETHER_VLAN;
516 [ # # ]: 0 : vh = rte_pktmbuf_read(m, off, sizeof(*vh), &vh_copy);
517 [ # # ]: 0 : if (unlikely(vh == NULL))
518 : 0 : return pkt_type;
519 : 0 : off += sizeof(*vh);
520 : 0 : hdr_lens->inner_l2_len += sizeof(*vh);
521 : 0 : proto = vh->eth_proto;
522 [ - + ]: 9 : } else if (proto == rte_cpu_to_be_16(RTE_ETHER_TYPE_QINQ)) {
523 : : const struct rte_vlan_hdr *vh;
524 : : struct rte_vlan_hdr vh_copy;
525 : :
526 : 0 : pkt_type &= ~RTE_PTYPE_INNER_L2_MASK;
527 : 0 : pkt_type |= RTE_PTYPE_INNER_L2_ETHER_QINQ;
528 [ # # ]: 0 : vh = rte_pktmbuf_read(m, off + sizeof(*vh), sizeof(*vh),
529 : : &vh_copy);
530 [ # # ]: 0 : if (unlikely(vh == NULL))
531 : 0 : return pkt_type;
532 : 0 : off += 2 * sizeof(*vh);
533 : 0 : hdr_lens->inner_l2_len += 2 * sizeof(*vh);
534 : 0 : proto = vh->eth_proto;
535 : : }
536 : :
537 [ + - ]: 9 : if ((layers & RTE_PTYPE_INNER_L3_MASK) == 0)
538 : : return pkt_type;
539 : :
540 [ + - - + ]: 9 : if (proto == rte_cpu_to_be_16(RTE_ETHER_TYPE_IPV4) ||
541 : 0 : proto == RTE_VXLAN_GPE_TYPE_IPV4) {
542 : : const struct rte_ipv4_hdr *ip4h;
543 : : struct rte_ipv4_hdr ip4h_copy;
544 : :
545 [ # # ]: 0 : ip4h = rte_pktmbuf_read(m, off, sizeof(*ip4h), &ip4h_copy);
546 [ # # ]: 0 : if (unlikely(ip4h == NULL))
547 : 0 : return pkt_type;
548 : :
549 [ # # ]: 0 : pkt_type |= ptype_inner_l3_ip(ip4h->version_ihl);
550 : 0 : hdr_lens->inner_l3_len = rte_ipv4_hdr_len(ip4h);
551 : 0 : off += hdr_lens->inner_l3_len;
552 : :
553 [ # # ]: 0 : if ((layers & RTE_PTYPE_INNER_L4_MASK) == 0)
554 : : return pkt_type;
555 [ # # ]: 0 : if (ip4h->fragment_offset &
556 : : rte_cpu_to_be_16(RTE_IPV4_HDR_OFFSET_MASK |
557 : : RTE_IPV4_HDR_MF_FLAG)) {
558 : 0 : pkt_type |= RTE_PTYPE_INNER_L4_FRAG;
559 : 0 : hdr_lens->inner_l4_len = 0;
560 : 0 : return pkt_type;
561 : : }
562 : 0 : proto = ip4h->next_proto_id;
563 : 0 : pkt_type |= ptype_inner_l4(proto);
564 [ + - - + ]: 9 : } else if (proto == rte_cpu_to_be_16(RTE_ETHER_TYPE_IPV6) ||
565 : : proto == RTE_VXLAN_GPE_TYPE_IPV6) {
566 : : const struct rte_ipv6_hdr *ip6h;
567 : : struct rte_ipv6_hdr ip6h_copy;
568 : 0 : int frag = 0;
569 : :
570 [ # # ]: 0 : ip6h = rte_pktmbuf_read(m, off, sizeof(*ip6h), &ip6h_copy);
571 [ # # ]: 0 : if (unlikely(ip6h == NULL))
572 : 0 : return pkt_type;
573 : :
574 : 0 : proto = ip6h->proto;
575 : 0 : hdr_lens->inner_l3_len = sizeof(*ip6h);
576 : 0 : off += hdr_lens->inner_l3_len;
577 : 0 : pkt_type |= ptype_inner_l3_ip6(proto);
578 [ # # ]: 0 : if ((pkt_type & RTE_PTYPE_INNER_L3_MASK) ==
579 : : RTE_PTYPE_INNER_L3_IPV6_EXT) {
580 : : uint32_t prev_off;
581 : :
582 : : prev_off = off;
583 : 0 : ret = rte_net_skip_ip6_ext(proto, m, &off, &frag);
584 [ # # ]: 0 : if (ret < 0)
585 : : return pkt_type;
586 : 0 : proto = ret;
587 : 0 : hdr_lens->inner_l3_len += off - prev_off;
588 : : }
589 [ # # ]: 0 : if (proto == 0)
590 : : return pkt_type;
591 : :
592 [ # # ]: 0 : if ((layers & RTE_PTYPE_INNER_L4_MASK) == 0)
593 : : return pkt_type;
594 : :
595 [ # # ]: 0 : if (frag) {
596 : 0 : pkt_type |= RTE_PTYPE_INNER_L4_FRAG;
597 : 0 : hdr_lens->inner_l4_len = 0;
598 : 0 : return pkt_type;
599 : : }
600 : 0 : pkt_type |= ptype_inner_l4(proto);
601 : : }
602 : :
603 [ - + ]: 9 : if ((pkt_type & RTE_PTYPE_INNER_L4_MASK) == RTE_PTYPE_INNER_L4_UDP) {
604 : 0 : hdr_lens->inner_l4_len = sizeof(struct rte_udp_hdr);
605 [ - + ]: 9 : } else if ((pkt_type & RTE_PTYPE_INNER_L4_MASK) ==
606 : : RTE_PTYPE_INNER_L4_TCP) {
607 : : const struct rte_tcp_hdr *th;
608 : : struct rte_tcp_hdr th_copy;
609 : :
610 [ # # ]: 0 : th = rte_pktmbuf_read(m, off, sizeof(*th), &th_copy);
611 [ # # ]: 0 : if (unlikely(th == NULL))
612 : 0 : return pkt_type & (RTE_PTYPE_INNER_L2_MASK |
613 : : RTE_PTYPE_INNER_L3_MASK);
614 : 0 : hdr_lens->inner_l4_len = (th->data_off & 0xf0) >> 2;
615 [ - + ]: 9 : } else if ((pkt_type & RTE_PTYPE_INNER_L4_MASK) ==
616 : : RTE_PTYPE_INNER_L4_SCTP) {
617 : 0 : hdr_lens->inner_l4_len = sizeof(struct rte_sctp_hdr);
618 : : } else {
619 : 9 : hdr_lens->inner_l4_len = 0;
620 : : }
621 : :
622 : : return pkt_type;
623 : : }
|