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