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