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