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 : 4 : 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 : 4 : 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 : 0 : ptype_tunnel_without_udp(uint16_t *proto, const struct rte_mbuf *m,
134 : : uint32_t *off)
135 : : {
136 [ # # # # ]: 0 : 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->inner_l2_len = RTE_ETHER_VXLAN_HLEN;
201 : 0 : *proto = RTE_VXLAN_GPE_TYPE_ETH; /* just for eth header parse. */
202 : 0 : return RTE_PTYPE_TUNNEL_VXLAN;
203 : : }
204 [ # # ]: 0 : case RTE_VXLAN_GPE_DEFAULT_PORT: {
205 : : const struct rte_vxlan_gpe_hdr *vgh;
206 : : struct rte_vxlan_gpe_hdr vgh_copy;
207 : : vgh = rte_pktmbuf_read(m, *off, sizeof(*vgh), &vgh_copy);
208 [ # # ]: 0 : if (unlikely(vgh == NULL))
209 : : return 0;
210 : 0 : *off += sizeof(struct rte_vxlan_gpe_hdr);
211 : 0 : hdr_lens->inner_l2_len = RTE_ETHER_VXLAN_GPE_HLEN;
212 : 0 : *proto = vgh->proto;
213 : :
214 : 0 : return RTE_PTYPE_TUNNEL_VXLAN_GPE;
215 : : }
216 [ # # ]: 0 : case RTE_GTPC_UDP_PORT:
217 : : case RTE_GTPU_UDP_PORT: {
218 : : const struct rte_gtp_hdr *gh;
219 : : struct rte_gtp_hdr gh_copy;
220 : : uint8_t gtp_len;
221 : : uint8_t ip_ver;
222 : : gh = rte_pktmbuf_read(m, *off, sizeof(*gh), &gh_copy);
223 [ # # ]: 0 : if (unlikely(gh == NULL))
224 : : return 0;
225 : : gtp_len = sizeof(*gh);
226 [ # # ]: 0 : if (gh->e || gh->s || gh->pn)
227 : : gtp_len += sizeof(struct rte_gtp_hdr_ext_word);
228 : : /*
229 : : * Check message type. If message type is 0xff, it is
230 : : * a GTP data packet. If not, it is a GTP control packet
231 : : */
232 [ # # ]: 0 : if (gh->msg_type == 0xff) {
233 : 0 : ip_ver = *(const uint8_t *)((const char *)gh + gtp_len);
234 : 0 : *proto = (ip_ver) & 0xf0;
235 : : } else {
236 : 0 : *proto = 0;
237 : : }
238 : 0 : *off += gtp_len;
239 : 0 : hdr_lens->inner_l2_len = gtp_len + sizeof(struct rte_udp_hdr);
240 [ # # ]: 0 : if (port_no == RTE_GTPC_UDP_PORT)
241 : : return RTE_PTYPE_TUNNEL_GTPC;
242 : : else if (port_no == RTE_GTPU_UDP_PORT)
243 : 0 : return RTE_PTYPE_TUNNEL_GTPU;
244 : : return 0;
245 : : }
246 [ # # ]: 0 : case RTE_GENEVE_DEFAULT_PORT: {
247 : : const struct rte_geneve_hdr *gnh;
248 : : struct rte_geneve_hdr gnh_copy;
249 : : uint16_t geneve_len;
250 : : gnh = rte_pktmbuf_read(m, *off, sizeof(*gnh), &gnh_copy);
251 [ # # ]: 0 : if (unlikely(gnh == NULL))
252 : : return 0;
253 : 0 : geneve_len = sizeof(*gnh) + gnh->opt_len * 4;
254 : 0 : *off = geneve_len;
255 : 0 : *proto = gnh->proto;
256 [ # # ]: 0 : if (gnh->proto == 0)
257 : 0 : *proto = rte_cpu_to_be_16(RTE_ETHER_TYPE_IPV4);
258 : : return RTE_PTYPE_TUNNEL_GENEVE;
259 : : }
260 : : default:
261 : : return 0;
262 : : }
263 : : }
264 : :
265 : : /* parse ipv6 extended headers, update offset and return next proto */
266 : : RTE_EXPORT_SYMBOL(rte_net_skip_ip6_ext)
267 : : int
268 : 0 : rte_net_skip_ip6_ext(uint16_t proto, const struct rte_mbuf *m, uint32_t *off,
269 : : int *frag)
270 : : {
271 : : struct ext_hdr {
272 : : uint8_t next_hdr;
273 : : uint8_t len;
274 : : };
275 : : const struct ext_hdr *xh;
276 : : struct ext_hdr xh_copy;
277 : : unsigned int i;
278 : :
279 : 0 : *frag = 0;
280 : :
281 : : #define MAX_EXT_HDRS 5
282 [ # # ]: 0 : for (i = 0; i < MAX_EXT_HDRS; i++) {
283 [ # # # # ]: 0 : switch (proto) {
284 : 0 : case IPPROTO_HOPOPTS:
285 : : case IPPROTO_ROUTING:
286 : : case IPPROTO_DSTOPTS:
287 [ # # ]: 0 : xh = rte_pktmbuf_read(m, *off, sizeof(*xh),
288 : : &xh_copy);
289 [ # # ]: 0 : if (xh == NULL)
290 : : return -1;
291 : 0 : *off += (xh->len + 1) * 8;
292 : 0 : proto = xh->next_hdr;
293 : : break;
294 : 0 : case IPPROTO_FRAGMENT:
295 [ # # ]: 0 : xh = rte_pktmbuf_read(m, *off, sizeof(*xh),
296 : : &xh_copy);
297 [ # # ]: 0 : if (xh == NULL)
298 : : return -1;
299 : 0 : *off += 8;
300 : 0 : proto = xh->next_hdr;
301 : 0 : *frag = 1;
302 : 0 : return proto; /* this is always the last ext hdr */
303 : : case IPPROTO_NONE:
304 : : return 0;
305 : : default:
306 : : return proto;
307 : : }
308 : : }
309 : : return -1;
310 : : }
311 : :
312 : : /* parse mbuf data to get packet type */
313 : : RTE_EXPORT_SYMBOL(rte_net_get_ptype)
314 : 5 : uint32_t rte_net_get_ptype(const struct rte_mbuf *m,
315 : : struct rte_net_hdr_lens *hdr_lens, uint32_t layers)
316 : : {
317 : : struct rte_net_hdr_lens local_hdr_lens;
318 : : const struct rte_ether_hdr *eh;
319 : : struct rte_ether_hdr eh_copy;
320 : : uint32_t pkt_type = RTE_PTYPE_L2_ETHER;
321 : 5 : uint32_t off = 0;
322 : : uint16_t proto;
323 : : int ret;
324 : :
325 [ - + ]: 5 : if (hdr_lens == NULL)
326 : : hdr_lens = &local_hdr_lens;
327 : :
328 : : eh = rte_pktmbuf_read(m, off, sizeof(*eh), &eh_copy);
329 [ + - ]: 5 : if (unlikely(eh == NULL))
330 : : return 0;
331 : 5 : proto = eh->ether_type;
332 : 5 : off = sizeof(*eh);
333 : 5 : hdr_lens->l2_len = off;
334 : :
335 [ + - ]: 5 : if ((layers & RTE_PTYPE_L2_MASK) == 0)
336 : : return 0;
337 : :
338 [ + + ]: 5 : if (proto == rte_cpu_to_be_16(RTE_ETHER_TYPE_IPV4))
339 : 4 : goto l3; /* fast path if packet is IPv4 */
340 : :
341 [ - + ]: 1 : if (proto == rte_cpu_to_be_16(RTE_ETHER_TYPE_VLAN)) {
342 : : const struct rte_vlan_hdr *vh;
343 : : struct rte_vlan_hdr vh_copy;
344 : :
345 : : pkt_type = RTE_PTYPE_L2_ETHER_VLAN;
346 : : vh = rte_pktmbuf_read(m, off, sizeof(*vh), &vh_copy);
347 [ # # ]: 0 : if (unlikely(vh == NULL))
348 : 0 : return pkt_type;
349 : 0 : off += sizeof(*vh);
350 : 0 : hdr_lens->l2_len += sizeof(*vh);
351 : 0 : proto = vh->eth_proto;
352 [ - + ]: 1 : } else if (proto == rte_cpu_to_be_16(RTE_ETHER_TYPE_QINQ)) {
353 : : const struct rte_vlan_hdr *vh;
354 : : struct rte_vlan_hdr vh_copy;
355 : :
356 : : pkt_type = RTE_PTYPE_L2_ETHER_QINQ;
357 : : vh = rte_pktmbuf_read(m, off + sizeof(*vh), sizeof(*vh),
358 : : &vh_copy);
359 [ # # ]: 0 : if (unlikely(vh == NULL))
360 : 0 : return pkt_type;
361 : 0 : off += 2 * sizeof(*vh);
362 : 0 : hdr_lens->l2_len += 2 * sizeof(*vh);
363 : 0 : proto = vh->eth_proto;
364 [ + - - + ]: 1 : } else if ((proto == rte_cpu_to_be_16(RTE_ETHER_TYPE_MPLS)) ||
365 : : (proto == rte_cpu_to_be_16(RTE_ETHER_TYPE_MPLSM))) {
366 : : unsigned int i;
367 : : const struct rte_mpls_hdr *mh;
368 : : struct rte_mpls_hdr mh_copy;
369 : :
370 : : #define MAX_MPLS_HDR 5
371 [ # # ]: 0 : for (i = 0; i < MAX_MPLS_HDR; i++) {
372 [ # # ]: 0 : mh = rte_pktmbuf_read(m, off + (i * sizeof(*mh)),
373 : : sizeof(*mh), &mh_copy);
374 [ # # ]: 0 : if (unlikely(mh == NULL))
375 : : return pkt_type;
376 : : }
377 : : if (i == MAX_MPLS_HDR)
378 : : return pkt_type;
379 : : pkt_type = RTE_PTYPE_L2_ETHER_MPLS;
380 : : hdr_lens->l2_len += (sizeof(*mh) * i);
381 : : return pkt_type;
382 : : }
383 : :
384 : 1 : l3:
385 [ + - ]: 5 : if ((layers & RTE_PTYPE_L3_MASK) == 0)
386 : : return pkt_type;
387 : :
388 [ + + ]: 5 : if (proto == rte_cpu_to_be_16(RTE_ETHER_TYPE_IPV4)) {
389 : : const struct rte_ipv4_hdr *ip4h;
390 : : struct rte_ipv4_hdr ip4h_copy;
391 : :
392 [ + - ]: 4 : ip4h = rte_pktmbuf_read(m, off, sizeof(*ip4h), &ip4h_copy);
393 [ + - ]: 4 : if (unlikely(ip4h == NULL))
394 : 1 : return pkt_type;
395 : :
396 [ + - ]: 4 : pkt_type |= ptype_l3_ip(ip4h->version_ihl);
397 : 4 : hdr_lens->l3_len = rte_ipv4_hdr_len(ip4h);
398 : 4 : off += hdr_lens->l3_len;
399 : :
400 [ + - ]: 4 : if ((layers & RTE_PTYPE_L4_MASK) == 0)
401 : : return pkt_type;
402 : :
403 [ + + ]: 4 : if (ip4h->fragment_offset & rte_cpu_to_be_16(
404 : : RTE_IPV4_HDR_OFFSET_MASK | RTE_IPV4_HDR_MF_FLAG)) {
405 : 1 : pkt_type |= RTE_PTYPE_L4_FRAG;
406 : 1 : hdr_lens->l4_len = 0;
407 : 1 : return pkt_type;
408 : : }
409 : 3 : proto = ip4h->next_proto_id;
410 : 3 : pkt_type |= ptype_l4(proto);
411 [ + - ]: 1 : } else if (proto == rte_cpu_to_be_16(RTE_ETHER_TYPE_IPV6)) {
412 : : const struct rte_ipv6_hdr *ip6h;
413 : : struct rte_ipv6_hdr ip6h_copy;
414 : 1 : int frag = 0;
415 : :
416 [ + - ]: 1 : ip6h = rte_pktmbuf_read(m, off, sizeof(*ip6h), &ip6h_copy);
417 [ + - ]: 1 : if (unlikely(ip6h == NULL))
418 : 0 : return pkt_type;
419 : :
420 : 1 : proto = ip6h->proto;
421 : 1 : hdr_lens->l3_len = sizeof(*ip6h);
422 : 1 : off += hdr_lens->l3_len;
423 : 1 : pkt_type |= ptype_l3_ip6(proto);
424 [ - + ]: 1 : if ((pkt_type & RTE_PTYPE_L3_MASK) == RTE_PTYPE_L3_IPV6_EXT) {
425 : 0 : ret = rte_net_skip_ip6_ext(proto, m, &off, &frag);
426 [ # # ]: 0 : if (ret < 0)
427 : : return pkt_type;
428 : 0 : proto = ret;
429 : 0 : hdr_lens->l3_len = off - hdr_lens->l2_len;
430 : : }
431 [ + - ]: 1 : if (proto == 0)
432 : : return pkt_type;
433 : :
434 [ + - ]: 1 : if ((layers & RTE_PTYPE_L4_MASK) == 0)
435 : : return pkt_type;
436 : :
437 [ - + ]: 1 : if (frag) {
438 : 0 : pkt_type |= RTE_PTYPE_L4_FRAG;
439 : 0 : hdr_lens->l4_len = 0;
440 : 0 : return pkt_type;
441 : : }
442 : 1 : pkt_type |= ptype_l4(proto);
443 : : }
444 : :
445 [ + + ]: 4 : if ((pkt_type & RTE_PTYPE_L4_MASK) == RTE_PTYPE_L4_UDP) {
446 : 3 : hdr_lens->l4_len = sizeof(struct rte_udp_hdr);
447 [ + - ]: 3 : if ((layers & RTE_PTYPE_TUNNEL_MASK) == 0)
448 : : return pkt_type;
449 : 3 : pkt_type |= ptype_tunnel_with_udp(&proto, m, &off, hdr_lens);
450 [ + - ]: 1 : } else if ((pkt_type & RTE_PTYPE_L4_MASK) == RTE_PTYPE_L4_TCP) {
451 : : const struct rte_tcp_hdr *th;
452 : : struct rte_tcp_hdr th_copy;
453 : :
454 [ + - ]: 1 : th = rte_pktmbuf_read(m, off, sizeof(*th), &th_copy);
455 [ - + ]: 1 : if (unlikely(th == NULL))
456 : 0 : return pkt_type & (RTE_PTYPE_L2_MASK |
457 : : RTE_PTYPE_L3_MASK);
458 : 1 : hdr_lens->l4_len = (th->data_off & 0xf0) >> 2;
459 : 1 : return pkt_type;
460 [ # # ]: 0 : } else if ((pkt_type & RTE_PTYPE_L4_MASK) == RTE_PTYPE_L4_SCTP) {
461 : 0 : hdr_lens->l4_len = sizeof(struct rte_sctp_hdr);
462 : 0 : return pkt_type;
463 : : } else {
464 : 0 : uint32_t prev_off = off;
465 : :
466 : 0 : hdr_lens->l4_len = 0;
467 : :
468 [ # # ]: 0 : if ((layers & RTE_PTYPE_TUNNEL_MASK) == 0)
469 : : return pkt_type;
470 : :
471 : 0 : pkt_type |= ptype_tunnel_without_udp(&proto, m, &off);
472 : 0 : hdr_lens->tunnel_len = off - prev_off;
473 : : }
474 : :
475 : : /* same job for inner header: we need to duplicate the code
476 : : * because the packet types do not have the same value.
477 : : */
478 [ + - ]: 3 : if ((layers & RTE_PTYPE_INNER_L2_MASK) == 0)
479 : : return pkt_type;
480 : :
481 [ + - ]: 3 : if (proto == rte_cpu_to_be_16(RTE_ETHER_TYPE_TEB) ||
482 [ - + ]: 3 : proto == rte_cpu_to_be_16(RTE_GENEVE_TYPE_ETH) ||
483 : : proto == RTE_VXLAN_GPE_TYPE_ETH) {
484 [ # # ]: 0 : eh = rte_pktmbuf_read(m, off, sizeof(*eh), &eh_copy);
485 [ # # ]: 0 : if (unlikely(eh == NULL))
486 : : return pkt_type;
487 : 0 : pkt_type |= RTE_PTYPE_INNER_L2_ETHER;
488 : 0 : proto = eh->ether_type;
489 : 0 : off += sizeof(*eh);
490 : 0 : hdr_lens->inner_l2_len += sizeof(*eh);
491 : : }
492 : :
493 [ - + ]: 3 : if (proto == rte_cpu_to_be_16(RTE_ETHER_TYPE_VLAN)) {
494 : : const struct rte_vlan_hdr *vh;
495 : : struct rte_vlan_hdr vh_copy;
496 : :
497 : 0 : pkt_type &= ~RTE_PTYPE_INNER_L2_MASK;
498 : 0 : pkt_type |= RTE_PTYPE_INNER_L2_ETHER_VLAN;
499 [ # # ]: 0 : vh = rte_pktmbuf_read(m, off, sizeof(*vh), &vh_copy);
500 [ # # ]: 0 : if (unlikely(vh == NULL))
501 : 0 : return pkt_type;
502 : 0 : off += sizeof(*vh);
503 : 0 : hdr_lens->inner_l2_len += sizeof(*vh);
504 : 0 : proto = vh->eth_proto;
505 [ - + ]: 3 : } else if (proto == rte_cpu_to_be_16(RTE_ETHER_TYPE_QINQ)) {
506 : : const struct rte_vlan_hdr *vh;
507 : : struct rte_vlan_hdr vh_copy;
508 : :
509 : 0 : pkt_type &= ~RTE_PTYPE_INNER_L2_MASK;
510 : 0 : pkt_type |= RTE_PTYPE_INNER_L2_ETHER_QINQ;
511 [ # # ]: 0 : vh = rte_pktmbuf_read(m, off + sizeof(*vh), sizeof(*vh),
512 : : &vh_copy);
513 [ # # ]: 0 : if (unlikely(vh == NULL))
514 : 0 : return pkt_type;
515 : 0 : off += 2 * sizeof(*vh);
516 : 0 : hdr_lens->inner_l2_len += 2 * sizeof(*vh);
517 : 0 : proto = vh->eth_proto;
518 : : }
519 : :
520 [ + - ]: 3 : if ((layers & RTE_PTYPE_INNER_L3_MASK) == 0)
521 : : return pkt_type;
522 : :
523 [ + - - + ]: 3 : if (proto == rte_cpu_to_be_16(RTE_ETHER_TYPE_IPV4) ||
524 : 0 : proto == RTE_VXLAN_GPE_TYPE_IPV4) {
525 : : const struct rte_ipv4_hdr *ip4h;
526 : : struct rte_ipv4_hdr ip4h_copy;
527 : :
528 [ # # ]: 0 : ip4h = rte_pktmbuf_read(m, off, sizeof(*ip4h), &ip4h_copy);
529 [ # # ]: 0 : if (unlikely(ip4h == NULL))
530 : 0 : return pkt_type;
531 : :
532 [ # # ]: 0 : pkt_type |= ptype_inner_l3_ip(ip4h->version_ihl);
533 : 0 : hdr_lens->inner_l3_len = rte_ipv4_hdr_len(ip4h);
534 : 0 : off += hdr_lens->inner_l3_len;
535 : :
536 [ # # ]: 0 : if ((layers & RTE_PTYPE_INNER_L4_MASK) == 0)
537 : : return pkt_type;
538 [ # # ]: 0 : if (ip4h->fragment_offset &
539 : : rte_cpu_to_be_16(RTE_IPV4_HDR_OFFSET_MASK |
540 : : RTE_IPV4_HDR_MF_FLAG)) {
541 : 0 : pkt_type |= RTE_PTYPE_INNER_L4_FRAG;
542 : 0 : hdr_lens->inner_l4_len = 0;
543 : 0 : return pkt_type;
544 : : }
545 : 0 : proto = ip4h->next_proto_id;
546 : 0 : pkt_type |= ptype_inner_l4(proto);
547 [ + - - + ]: 3 : } else if (proto == rte_cpu_to_be_16(RTE_ETHER_TYPE_IPV6) ||
548 : : proto == RTE_VXLAN_GPE_TYPE_IPV6) {
549 : : const struct rte_ipv6_hdr *ip6h;
550 : : struct rte_ipv6_hdr ip6h_copy;
551 : 0 : int frag = 0;
552 : :
553 [ # # ]: 0 : ip6h = rte_pktmbuf_read(m, off, sizeof(*ip6h), &ip6h_copy);
554 [ # # ]: 0 : if (unlikely(ip6h == NULL))
555 : 0 : return pkt_type;
556 : :
557 : 0 : proto = ip6h->proto;
558 : 0 : hdr_lens->inner_l3_len = sizeof(*ip6h);
559 : 0 : off += hdr_lens->inner_l3_len;
560 : 0 : pkt_type |= ptype_inner_l3_ip6(proto);
561 [ # # ]: 0 : if ((pkt_type & RTE_PTYPE_INNER_L3_MASK) ==
562 : : RTE_PTYPE_INNER_L3_IPV6_EXT) {
563 : : uint32_t prev_off;
564 : :
565 : : prev_off = off;
566 : 0 : ret = rte_net_skip_ip6_ext(proto, m, &off, &frag);
567 [ # # ]: 0 : if (ret < 0)
568 : : return pkt_type;
569 : 0 : proto = ret;
570 : 0 : hdr_lens->inner_l3_len += off - prev_off;
571 : : }
572 [ # # ]: 0 : if (proto == 0)
573 : : return pkt_type;
574 : :
575 [ # # ]: 0 : if ((layers & RTE_PTYPE_INNER_L4_MASK) == 0)
576 : : return pkt_type;
577 : :
578 [ # # ]: 0 : if (frag) {
579 : 0 : pkt_type |= RTE_PTYPE_INNER_L4_FRAG;
580 : 0 : hdr_lens->inner_l4_len = 0;
581 : 0 : return pkt_type;
582 : : }
583 : 0 : pkt_type |= ptype_inner_l4(proto);
584 : : }
585 : :
586 [ - + ]: 3 : if ((pkt_type & RTE_PTYPE_INNER_L4_MASK) == RTE_PTYPE_INNER_L4_UDP) {
587 : 0 : hdr_lens->inner_l4_len = sizeof(struct rte_udp_hdr);
588 [ - + ]: 3 : } else if ((pkt_type & RTE_PTYPE_INNER_L4_MASK) ==
589 : : RTE_PTYPE_INNER_L4_TCP) {
590 : : const struct rte_tcp_hdr *th;
591 : : struct rte_tcp_hdr th_copy;
592 : :
593 [ # # ]: 0 : th = rte_pktmbuf_read(m, off, sizeof(*th), &th_copy);
594 [ # # ]: 0 : if (unlikely(th == NULL))
595 : 0 : return pkt_type & (RTE_PTYPE_INNER_L2_MASK |
596 : : RTE_PTYPE_INNER_L3_MASK);
597 : 0 : hdr_lens->inner_l4_len = (th->data_off & 0xf0) >> 2;
598 [ - + ]: 3 : } else if ((pkt_type & RTE_PTYPE_INNER_L4_MASK) ==
599 : : RTE_PTYPE_INNER_L4_SCTP) {
600 : 0 : hdr_lens->inner_l4_len = sizeof(struct rte_sctp_hdr);
601 : : } else {
602 : 3 : hdr_lens->inner_l4_len = 0;
603 : : }
604 : :
605 : : return pkt_type;
606 : : }
|