]>
Commit | Line | Data |
---|---|---|
7c673cae FG |
1 | /*- |
2 | * BSD LICENSE | |
3 | * | |
4 | * Copyright 2016 6WIND S.A. | |
5 | * All rights reserved. | |
6 | * | |
7 | * Redistribution and use in source and binary forms, with or without | |
8 | * modification, are permitted provided that the following conditions | |
9 | * are met: | |
10 | * | |
11 | * * Redistributions of source code must retain the above copyright | |
12 | * notice, this list of conditions and the following disclaimer. | |
13 | * * Redistributions in binary form must reproduce the above copyright | |
14 | * notice, this list of conditions and the following disclaimer in | |
15 | * the documentation and/or other materials provided with the | |
16 | * distribution. | |
17 | * * Neither the name of 6WIND S.A. nor the names of its | |
18 | * contributors may be used to endorse or promote products derived | |
19 | * from this software without specific prior written permission. | |
20 | * | |
21 | * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS | |
22 | * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT | |
23 | * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR | |
24 | * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT | |
25 | * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, | |
26 | * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT | |
27 | * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, | |
28 | * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY | |
29 | * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT | |
30 | * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE | |
31 | * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. | |
32 | */ | |
33 | ||
34 | #include <stdint.h> | |
35 | ||
36 | #include <rte_mbuf.h> | |
37 | #include <rte_mbuf_ptype.h> | |
38 | #include <rte_byteorder.h> | |
39 | #include <rte_ether.h> | |
40 | #include <rte_ip.h> | |
41 | #include <rte_tcp.h> | |
42 | #include <rte_udp.h> | |
43 | #include <rte_sctp.h> | |
44 | #include <rte_gre.h> | |
45 | #include <rte_net.h> | |
46 | ||
47 | /* get l3 packet type from ip6 next protocol */ | |
48 | static uint32_t | |
49 | ptype_l3_ip6(uint8_t ip6_proto) | |
50 | { | |
51 | static const uint32_t ip6_ext_proto_map[256] = { | |
52 | [IPPROTO_HOPOPTS] = RTE_PTYPE_L3_IPV6_EXT - RTE_PTYPE_L3_IPV6, | |
53 | [IPPROTO_ROUTING] = RTE_PTYPE_L3_IPV6_EXT - RTE_PTYPE_L3_IPV6, | |
54 | [IPPROTO_FRAGMENT] = RTE_PTYPE_L3_IPV6_EXT - RTE_PTYPE_L3_IPV6, | |
55 | [IPPROTO_ESP] = RTE_PTYPE_L3_IPV6_EXT - RTE_PTYPE_L3_IPV6, | |
56 | [IPPROTO_AH] = RTE_PTYPE_L3_IPV6_EXT - RTE_PTYPE_L3_IPV6, | |
57 | [IPPROTO_DSTOPTS] = RTE_PTYPE_L3_IPV6_EXT - RTE_PTYPE_L3_IPV6, | |
58 | }; | |
59 | ||
60 | return RTE_PTYPE_L3_IPV6 + ip6_ext_proto_map[ip6_proto]; | |
61 | } | |
62 | ||
63 | /* get l3 packet type from ip version and header length */ | |
64 | static uint32_t | |
65 | ptype_l3_ip(uint8_t ipv_ihl) | |
66 | { | |
67 | static const uint32_t ptype_l3_ip_proto_map[256] = { | |
68 | [0x45] = RTE_PTYPE_L3_IPV4, | |
69 | [0x46] = RTE_PTYPE_L3_IPV4_EXT, | |
70 | [0x47] = RTE_PTYPE_L3_IPV4_EXT, | |
71 | [0x48] = RTE_PTYPE_L3_IPV4_EXT, | |
72 | [0x49] = RTE_PTYPE_L3_IPV4_EXT, | |
73 | [0x4A] = RTE_PTYPE_L3_IPV4_EXT, | |
74 | [0x4B] = RTE_PTYPE_L3_IPV4_EXT, | |
75 | [0x4C] = RTE_PTYPE_L3_IPV4_EXT, | |
76 | [0x4D] = RTE_PTYPE_L3_IPV4_EXT, | |
77 | [0x4E] = RTE_PTYPE_L3_IPV4_EXT, | |
78 | [0x4F] = RTE_PTYPE_L3_IPV4_EXT, | |
79 | }; | |
80 | ||
81 | return ptype_l3_ip_proto_map[ipv_ihl]; | |
82 | } | |
83 | ||
84 | /* get l4 packet type from proto */ | |
85 | static uint32_t | |
86 | ptype_l4(uint8_t proto) | |
87 | { | |
88 | static const uint32_t ptype_l4_proto[256] = { | |
89 | [IPPROTO_UDP] = RTE_PTYPE_L4_UDP, | |
90 | [IPPROTO_TCP] = RTE_PTYPE_L4_TCP, | |
91 | [IPPROTO_SCTP] = RTE_PTYPE_L4_SCTP, | |
92 | }; | |
93 | ||
94 | return ptype_l4_proto[proto]; | |
95 | } | |
96 | ||
97 | /* get inner l3 packet type from ip6 next protocol */ | |
98 | static uint32_t | |
99 | ptype_inner_l3_ip6(uint8_t ip6_proto) | |
100 | { | |
101 | static const uint32_t ptype_inner_ip6_ext_proto_map[256] = { | |
102 | [IPPROTO_HOPOPTS] = RTE_PTYPE_INNER_L3_IPV6_EXT - | |
103 | RTE_PTYPE_INNER_L3_IPV6, | |
104 | [IPPROTO_ROUTING] = RTE_PTYPE_INNER_L3_IPV6_EXT - | |
105 | RTE_PTYPE_INNER_L3_IPV6, | |
106 | [IPPROTO_FRAGMENT] = RTE_PTYPE_INNER_L3_IPV6_EXT - | |
107 | RTE_PTYPE_INNER_L3_IPV6, | |
108 | [IPPROTO_ESP] = RTE_PTYPE_INNER_L3_IPV6_EXT - | |
109 | RTE_PTYPE_INNER_L3_IPV6, | |
110 | [IPPROTO_AH] = RTE_PTYPE_INNER_L3_IPV6_EXT - | |
111 | RTE_PTYPE_INNER_L3_IPV6, | |
112 | [IPPROTO_DSTOPTS] = RTE_PTYPE_INNER_L3_IPV6_EXT - | |
113 | RTE_PTYPE_INNER_L3_IPV6, | |
114 | }; | |
115 | ||
116 | return RTE_PTYPE_INNER_L3_IPV6 + | |
117 | ptype_inner_ip6_ext_proto_map[ip6_proto]; | |
118 | } | |
119 | ||
120 | /* get inner l3 packet type from ip version and header length */ | |
121 | static uint32_t | |
122 | ptype_inner_l3_ip(uint8_t ipv_ihl) | |
123 | { | |
124 | static const uint32_t ptype_inner_l3_ip_proto_map[256] = { | |
125 | [0x45] = RTE_PTYPE_INNER_L3_IPV4, | |
126 | [0x46] = RTE_PTYPE_INNER_L3_IPV4_EXT, | |
127 | [0x47] = RTE_PTYPE_INNER_L3_IPV4_EXT, | |
128 | [0x48] = RTE_PTYPE_INNER_L3_IPV4_EXT, | |
129 | [0x49] = RTE_PTYPE_INNER_L3_IPV4_EXT, | |
130 | [0x4A] = RTE_PTYPE_INNER_L3_IPV4_EXT, | |
131 | [0x4B] = RTE_PTYPE_INNER_L3_IPV4_EXT, | |
132 | [0x4C] = RTE_PTYPE_INNER_L3_IPV4_EXT, | |
133 | [0x4D] = RTE_PTYPE_INNER_L3_IPV4_EXT, | |
134 | [0x4E] = RTE_PTYPE_INNER_L3_IPV4_EXT, | |
135 | [0x4F] = RTE_PTYPE_INNER_L3_IPV4_EXT, | |
136 | }; | |
137 | ||
138 | return ptype_inner_l3_ip_proto_map[ipv_ihl]; | |
139 | } | |
140 | ||
141 | /* get inner l4 packet type from proto */ | |
142 | static uint32_t | |
143 | ptype_inner_l4(uint8_t proto) | |
144 | { | |
145 | static const uint32_t ptype_inner_l4_proto[256] = { | |
146 | [IPPROTO_UDP] = RTE_PTYPE_INNER_L4_UDP, | |
147 | [IPPROTO_TCP] = RTE_PTYPE_INNER_L4_TCP, | |
148 | [IPPROTO_SCTP] = RTE_PTYPE_INNER_L4_SCTP, | |
149 | }; | |
150 | ||
151 | return ptype_inner_l4_proto[proto]; | |
152 | } | |
153 | ||
154 | /* get the tunnel packet type if any, update proto and off. */ | |
155 | static uint32_t | |
156 | ptype_tunnel(uint16_t *proto, const struct rte_mbuf *m, | |
157 | uint32_t *off) | |
158 | { | |
159 | switch (*proto) { | |
160 | case IPPROTO_GRE: { | |
161 | static const uint8_t opt_len[16] = { | |
162 | [0x0] = 4, | |
163 | [0x1] = 8, | |
164 | [0x2] = 8, | |
165 | [0x8] = 8, | |
166 | [0x3] = 12, | |
167 | [0x9] = 12, | |
168 | [0xa] = 12, | |
169 | [0xb] = 16, | |
170 | }; | |
171 | const struct gre_hdr *gh; | |
172 | struct gre_hdr gh_copy; | |
173 | uint16_t flags; | |
174 | ||
175 | gh = rte_pktmbuf_read(m, *off, sizeof(*gh), &gh_copy); | |
176 | if (unlikely(gh == NULL)) | |
177 | return 0; | |
178 | ||
179 | flags = rte_be_to_cpu_16(*(const uint16_t *)gh); | |
180 | flags >>= 12; | |
181 | if (opt_len[flags] == 0) | |
182 | return 0; | |
183 | ||
184 | *off += opt_len[flags]; | |
185 | *proto = gh->proto; | |
186 | if (*proto == rte_cpu_to_be_16(ETHER_TYPE_TEB)) | |
187 | return RTE_PTYPE_TUNNEL_NVGRE; | |
188 | else | |
189 | return RTE_PTYPE_TUNNEL_GRE; | |
190 | } | |
191 | case IPPROTO_IPIP: | |
192 | *proto = rte_cpu_to_be_16(ETHER_TYPE_IPv4); | |
193 | return RTE_PTYPE_TUNNEL_IP; | |
194 | case IPPROTO_IPV6: | |
195 | *proto = rte_cpu_to_be_16(ETHER_TYPE_IPv6); | |
196 | return RTE_PTYPE_TUNNEL_IP; /* IP is also valid for IPv6 */ | |
197 | default: | |
198 | return 0; | |
199 | } | |
200 | } | |
201 | ||
202 | /* get the ipv4 header length */ | |
203 | static uint8_t | |
204 | ip4_hlen(const struct ipv4_hdr *hdr) | |
205 | { | |
206 | return (hdr->version_ihl & 0xf) * 4; | |
207 | } | |
208 | ||
209 | /* parse ipv6 extended headers, update offset and return next proto */ | |
210 | static uint16_t | |
211 | skip_ip6_ext(uint16_t proto, const struct rte_mbuf *m, uint32_t *off, | |
212 | int *frag) | |
213 | { | |
214 | struct ext_hdr { | |
215 | uint8_t next_hdr; | |
216 | uint8_t len; | |
217 | }; | |
218 | const struct ext_hdr *xh; | |
219 | struct ext_hdr xh_copy; | |
220 | unsigned int i; | |
221 | ||
222 | *frag = 0; | |
223 | ||
224 | #define MAX_EXT_HDRS 5 | |
225 | for (i = 0; i < MAX_EXT_HDRS; i++) { | |
226 | switch (proto) { | |
227 | case IPPROTO_HOPOPTS: | |
228 | case IPPROTO_ROUTING: | |
229 | case IPPROTO_DSTOPTS: | |
230 | xh = rte_pktmbuf_read(m, *off, sizeof(*xh), | |
231 | &xh_copy); | |
232 | if (xh == NULL) | |
233 | return 0; | |
234 | *off += (xh->len + 1) * 8; | |
235 | proto = xh->next_hdr; | |
236 | break; | |
237 | case IPPROTO_FRAGMENT: | |
238 | xh = rte_pktmbuf_read(m, *off, sizeof(*xh), | |
239 | &xh_copy); | |
240 | if (xh == NULL) | |
241 | return 0; | |
242 | *off += 8; | |
243 | proto = xh->next_hdr; | |
244 | *frag = 1; | |
245 | return proto; /* this is always the last ext hdr */ | |
246 | case IPPROTO_NONE: | |
247 | return 0; | |
248 | default: | |
249 | return proto; | |
250 | } | |
251 | } | |
252 | return 0; | |
253 | } | |
254 | ||
255 | /* parse mbuf data to get packet type */ | |
256 | uint32_t rte_net_get_ptype(const struct rte_mbuf *m, | |
257 | struct rte_net_hdr_lens *hdr_lens, uint32_t layers) | |
258 | { | |
259 | struct rte_net_hdr_lens local_hdr_lens; | |
260 | const struct ether_hdr *eh; | |
261 | struct ether_hdr eh_copy; | |
262 | uint32_t pkt_type = RTE_PTYPE_L2_ETHER; | |
263 | uint32_t off = 0; | |
264 | uint16_t proto; | |
265 | ||
266 | if (hdr_lens == NULL) | |
267 | hdr_lens = &local_hdr_lens; | |
268 | ||
269 | eh = rte_pktmbuf_read(m, off, sizeof(*eh), &eh_copy); | |
270 | if (unlikely(eh == NULL)) | |
271 | return 0; | |
272 | proto = eh->ether_type; | |
273 | off = sizeof(*eh); | |
274 | hdr_lens->l2_len = off; | |
275 | ||
276 | if ((layers & RTE_PTYPE_L2_MASK) == 0) | |
277 | return 0; | |
278 | ||
279 | if (proto == rte_cpu_to_be_16(ETHER_TYPE_IPv4)) | |
280 | goto l3; /* fast path if packet is IPv4 */ | |
281 | ||
282 | if (proto == rte_cpu_to_be_16(ETHER_TYPE_VLAN)) { | |
283 | const struct vlan_hdr *vh; | |
284 | struct vlan_hdr vh_copy; | |
285 | ||
286 | pkt_type = RTE_PTYPE_L2_ETHER_VLAN; | |
287 | vh = rte_pktmbuf_read(m, off, sizeof(*vh), &vh_copy); | |
288 | if (unlikely(vh == NULL)) | |
289 | return pkt_type; | |
290 | off += sizeof(*vh); | |
291 | hdr_lens->l2_len += sizeof(*vh); | |
292 | proto = vh->eth_proto; | |
293 | } else if (proto == rte_cpu_to_be_16(ETHER_TYPE_QINQ)) { | |
294 | const struct vlan_hdr *vh; | |
295 | struct vlan_hdr vh_copy; | |
296 | ||
297 | pkt_type = RTE_PTYPE_L2_ETHER_QINQ; | |
298 | vh = rte_pktmbuf_read(m, off + sizeof(*vh), sizeof(*vh), | |
299 | &vh_copy); | |
300 | if (unlikely(vh == NULL)) | |
301 | return pkt_type; | |
302 | off += 2 * sizeof(*vh); | |
303 | hdr_lens->l2_len += 2 * sizeof(*vh); | |
304 | proto = vh->eth_proto; | |
305 | } | |
306 | ||
307 | l3: | |
308 | if ((layers & RTE_PTYPE_L3_MASK) == 0) | |
309 | return pkt_type; | |
310 | ||
311 | if (proto == rte_cpu_to_be_16(ETHER_TYPE_IPv4)) { | |
312 | const struct ipv4_hdr *ip4h; | |
313 | struct ipv4_hdr ip4h_copy; | |
314 | ||
315 | ip4h = rte_pktmbuf_read(m, off, sizeof(*ip4h), &ip4h_copy); | |
316 | if (unlikely(ip4h == NULL)) | |
317 | return pkt_type; | |
318 | ||
319 | pkt_type |= ptype_l3_ip(ip4h->version_ihl); | |
320 | hdr_lens->l3_len = ip4_hlen(ip4h); | |
321 | off += hdr_lens->l3_len; | |
322 | ||
323 | if ((layers & RTE_PTYPE_L4_MASK) == 0) | |
324 | return pkt_type; | |
325 | ||
326 | if (ip4h->fragment_offset & rte_cpu_to_be_16( | |
327 | IPV4_HDR_OFFSET_MASK | IPV4_HDR_MF_FLAG)) { | |
328 | pkt_type |= RTE_PTYPE_L4_FRAG; | |
329 | hdr_lens->l4_len = 0; | |
330 | return pkt_type; | |
331 | } | |
332 | proto = ip4h->next_proto_id; | |
333 | pkt_type |= ptype_l4(proto); | |
334 | } else if (proto == rte_cpu_to_be_16(ETHER_TYPE_IPv6)) { | |
335 | const struct ipv6_hdr *ip6h; | |
336 | struct ipv6_hdr ip6h_copy; | |
337 | int frag = 0; | |
338 | ||
339 | ip6h = rte_pktmbuf_read(m, off, sizeof(*ip6h), &ip6h_copy); | |
340 | if (unlikely(ip6h == NULL)) | |
341 | return pkt_type; | |
342 | ||
343 | proto = ip6h->proto; | |
344 | hdr_lens->l3_len = sizeof(*ip6h); | |
345 | off += hdr_lens->l3_len; | |
346 | pkt_type |= ptype_l3_ip6(proto); | |
347 | if ((pkt_type & RTE_PTYPE_L3_MASK) == RTE_PTYPE_L3_IPV6_EXT) { | |
348 | proto = skip_ip6_ext(proto, m, &off, &frag); | |
349 | hdr_lens->l3_len = off - hdr_lens->l2_len; | |
350 | } | |
351 | if (proto == 0) | |
352 | return pkt_type; | |
353 | ||
354 | if ((layers & RTE_PTYPE_L4_MASK) == 0) | |
355 | return pkt_type; | |
356 | ||
357 | if (frag) { | |
358 | pkt_type |= RTE_PTYPE_L4_FRAG; | |
359 | hdr_lens->l4_len = 0; | |
360 | return pkt_type; | |
361 | } | |
362 | pkt_type |= ptype_l4(proto); | |
363 | } | |
364 | ||
365 | if ((pkt_type & RTE_PTYPE_L4_MASK) == RTE_PTYPE_L4_UDP) { | |
366 | hdr_lens->l4_len = sizeof(struct udp_hdr); | |
367 | return pkt_type; | |
368 | } else if ((pkt_type & RTE_PTYPE_L4_MASK) == RTE_PTYPE_L4_TCP) { | |
369 | const struct tcp_hdr *th; | |
370 | struct tcp_hdr th_copy; | |
371 | ||
372 | th = rte_pktmbuf_read(m, off, sizeof(*th), &th_copy); | |
373 | if (unlikely(th == NULL)) | |
374 | return pkt_type & (RTE_PTYPE_L2_MASK | | |
375 | RTE_PTYPE_L3_MASK); | |
376 | hdr_lens->l4_len = (th->data_off & 0xf0) >> 2; | |
377 | return pkt_type; | |
378 | } else if ((pkt_type & RTE_PTYPE_L4_MASK) == RTE_PTYPE_L4_SCTP) { | |
379 | hdr_lens->l4_len = sizeof(struct sctp_hdr); | |
380 | return pkt_type; | |
381 | } else { | |
382 | uint32_t prev_off = off; | |
383 | ||
384 | hdr_lens->l4_len = 0; | |
385 | ||
386 | if ((layers & RTE_PTYPE_TUNNEL_MASK) == 0) | |
387 | return pkt_type; | |
388 | ||
389 | pkt_type |= ptype_tunnel(&proto, m, &off); | |
390 | hdr_lens->tunnel_len = off - prev_off; | |
391 | } | |
392 | ||
393 | /* same job for inner header: we need to duplicate the code | |
394 | * because the packet types do not have the same value. | |
395 | */ | |
396 | if ((layers & RTE_PTYPE_INNER_L2_MASK) == 0) | |
397 | return pkt_type; | |
398 | ||
399 | if (proto == rte_cpu_to_be_16(ETHER_TYPE_TEB)) { | |
400 | eh = rte_pktmbuf_read(m, off, sizeof(*eh), &eh_copy); | |
401 | if (unlikely(eh == NULL)) | |
402 | return pkt_type; | |
403 | pkt_type |= RTE_PTYPE_INNER_L2_ETHER; | |
404 | proto = eh->ether_type; | |
405 | off += sizeof(*eh); | |
406 | hdr_lens->inner_l2_len = sizeof(*eh); | |
407 | } | |
408 | ||
409 | if (proto == rte_cpu_to_be_16(ETHER_TYPE_VLAN)) { | |
410 | const struct vlan_hdr *vh; | |
411 | struct vlan_hdr vh_copy; | |
412 | ||
413 | pkt_type &= ~RTE_PTYPE_INNER_L2_MASK; | |
414 | pkt_type |= RTE_PTYPE_INNER_L2_ETHER_VLAN; | |
415 | vh = rte_pktmbuf_read(m, off, sizeof(*vh), &vh_copy); | |
416 | if (unlikely(vh == NULL)) | |
417 | return pkt_type; | |
418 | off += sizeof(*vh); | |
419 | hdr_lens->inner_l2_len += sizeof(*vh); | |
420 | proto = vh->eth_proto; | |
421 | } else if (proto == rte_cpu_to_be_16(ETHER_TYPE_QINQ)) { | |
422 | const struct vlan_hdr *vh; | |
423 | struct vlan_hdr vh_copy; | |
424 | ||
425 | pkt_type &= ~RTE_PTYPE_INNER_L2_MASK; | |
426 | pkt_type |= RTE_PTYPE_INNER_L2_ETHER_QINQ; | |
427 | vh = rte_pktmbuf_read(m, off + sizeof(*vh), sizeof(*vh), | |
428 | &vh_copy); | |
429 | if (unlikely(vh == NULL)) | |
430 | return pkt_type; | |
431 | off += 2 * sizeof(*vh); | |
432 | hdr_lens->inner_l2_len += 2 * sizeof(*vh); | |
433 | proto = vh->eth_proto; | |
434 | } | |
435 | ||
436 | if ((layers & RTE_PTYPE_INNER_L3_MASK) == 0) | |
437 | return pkt_type; | |
438 | ||
439 | if (proto == rte_cpu_to_be_16(ETHER_TYPE_IPv4)) { | |
440 | const struct ipv4_hdr *ip4h; | |
441 | struct ipv4_hdr ip4h_copy; | |
442 | ||
443 | ip4h = rte_pktmbuf_read(m, off, sizeof(*ip4h), &ip4h_copy); | |
444 | if (unlikely(ip4h == NULL)) | |
445 | return pkt_type; | |
446 | ||
447 | pkt_type |= ptype_inner_l3_ip(ip4h->version_ihl); | |
448 | hdr_lens->inner_l3_len = ip4_hlen(ip4h); | |
449 | off += hdr_lens->inner_l3_len; | |
450 | ||
451 | if ((layers & RTE_PTYPE_INNER_L4_MASK) == 0) | |
452 | return pkt_type; | |
453 | if (ip4h->fragment_offset & | |
454 | rte_cpu_to_be_16(IPV4_HDR_OFFSET_MASK | | |
455 | IPV4_HDR_MF_FLAG)) { | |
456 | pkt_type |= RTE_PTYPE_INNER_L4_FRAG; | |
457 | hdr_lens->inner_l4_len = 0; | |
458 | return pkt_type; | |
459 | } | |
460 | proto = ip4h->next_proto_id; | |
461 | pkt_type |= ptype_inner_l4(proto); | |
462 | } else if (proto == rte_cpu_to_be_16(ETHER_TYPE_IPv6)) { | |
463 | const struct ipv6_hdr *ip6h; | |
464 | struct ipv6_hdr ip6h_copy; | |
465 | int frag = 0; | |
466 | ||
467 | ip6h = rte_pktmbuf_read(m, off, sizeof(*ip6h), &ip6h_copy); | |
468 | if (unlikely(ip6h == NULL)) | |
469 | return pkt_type; | |
470 | ||
471 | proto = ip6h->proto; | |
472 | hdr_lens->inner_l3_len = sizeof(*ip6h); | |
473 | off += hdr_lens->inner_l3_len; | |
474 | pkt_type |= ptype_inner_l3_ip6(proto); | |
475 | if ((pkt_type & RTE_PTYPE_INNER_L3_MASK) == | |
476 | RTE_PTYPE_INNER_L3_IPV6_EXT) { | |
477 | uint32_t prev_off; | |
478 | ||
479 | prev_off = off; | |
480 | proto = skip_ip6_ext(proto, m, &off, &frag); | |
481 | hdr_lens->inner_l3_len += off - prev_off; | |
482 | } | |
483 | if (proto == 0) | |
484 | return pkt_type; | |
485 | ||
486 | if ((layers & RTE_PTYPE_INNER_L4_MASK) == 0) | |
487 | return pkt_type; | |
488 | ||
489 | if (frag) { | |
490 | pkt_type |= RTE_PTYPE_INNER_L4_FRAG; | |
491 | hdr_lens->inner_l4_len = 0; | |
492 | return pkt_type; | |
493 | } | |
494 | pkt_type |= ptype_inner_l4(proto); | |
495 | } | |
496 | ||
497 | if ((pkt_type & RTE_PTYPE_INNER_L4_MASK) == RTE_PTYPE_INNER_L4_UDP) { | |
498 | hdr_lens->inner_l4_len = sizeof(struct udp_hdr); | |
499 | } else if ((pkt_type & RTE_PTYPE_INNER_L4_MASK) == | |
500 | RTE_PTYPE_INNER_L4_TCP) { | |
501 | const struct tcp_hdr *th; | |
502 | struct tcp_hdr th_copy; | |
503 | ||
504 | th = rte_pktmbuf_read(m, off, sizeof(*th), &th_copy); | |
505 | if (unlikely(th == NULL)) | |
506 | return pkt_type & (RTE_PTYPE_INNER_L2_MASK | | |
507 | RTE_PTYPE_INNER_L3_MASK); | |
508 | hdr_lens->inner_l4_len = (th->data_off & 0xf0) >> 2; | |
509 | } else if ((pkt_type & RTE_PTYPE_INNER_L4_MASK) == | |
510 | RTE_PTYPE_INNER_L4_SCTP) { | |
511 | hdr_lens->inner_l4_len = sizeof(struct sctp_hdr); | |
512 | } else { | |
513 | hdr_lens->inner_l4_len = 0; | |
514 | } | |
515 | ||
516 | return pkt_type; | |
517 | } |