]> git.proxmox.com Git - ceph.git/blame - ceph/src/dpdk/lib/librte_net/rte_net.c
bump version to 12.2.12-pve1
[ceph.git] / ceph / src / dpdk / lib / librte_net / rte_net.c
CommitLineData
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 */
48static uint32_t
49ptype_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 */
64static uint32_t
65ptype_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 */
85static uint32_t
86ptype_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 */
98static uint32_t
99ptype_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 */
121static uint32_t
122ptype_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 */
142static uint32_t
143ptype_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. */
155static uint32_t
156ptype_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 */
203static uint8_t
204ip4_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 */
210static uint16_t
211skip_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 */
256uint32_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}