xref: /f-stack/dpdk/lib/librte_net/rte_net.c (revision 031be553)
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 	hdr_lens->inner_l2_len = 0;
400 	if (proto == rte_cpu_to_be_16(ETHER_TYPE_TEB)) {
401 		eh = rte_pktmbuf_read(m, off, sizeof(*eh), &eh_copy);
402 		if (unlikely(eh == NULL))
403 			return pkt_type;
404 		pkt_type |= RTE_PTYPE_INNER_L2_ETHER;
405 		proto = eh->ether_type;
406 		off += sizeof(*eh);
407 		hdr_lens->inner_l2_len = sizeof(*eh);
408 	}
409 
410 	if (proto == rte_cpu_to_be_16(ETHER_TYPE_VLAN)) {
411 		const struct vlan_hdr *vh;
412 		struct vlan_hdr vh_copy;
413 
414 		pkt_type &= ~RTE_PTYPE_INNER_L2_MASK;
415 		pkt_type |= RTE_PTYPE_INNER_L2_ETHER_VLAN;
416 		vh = rte_pktmbuf_read(m, off, sizeof(*vh), &vh_copy);
417 		if (unlikely(vh == NULL))
418 			return pkt_type;
419 		off += sizeof(*vh);
420 		hdr_lens->inner_l2_len += sizeof(*vh);
421 		proto = vh->eth_proto;
422 	} else if (proto == rte_cpu_to_be_16(ETHER_TYPE_QINQ)) {
423 		const struct vlan_hdr *vh;
424 		struct vlan_hdr vh_copy;
425 
426 		pkt_type &= ~RTE_PTYPE_INNER_L2_MASK;
427 		pkt_type |= RTE_PTYPE_INNER_L2_ETHER_QINQ;
428 		vh = rte_pktmbuf_read(m, off + sizeof(*vh), sizeof(*vh),
429 			&vh_copy);
430 		if (unlikely(vh == NULL))
431 			return pkt_type;
432 		off += 2 * sizeof(*vh);
433 		hdr_lens->inner_l2_len += 2 * sizeof(*vh);
434 		proto = vh->eth_proto;
435 	}
436 
437 	if ((layers & RTE_PTYPE_INNER_L3_MASK) == 0)
438 		return pkt_type;
439 
440 	if (proto == rte_cpu_to_be_16(ETHER_TYPE_IPv4)) {
441 		const struct ipv4_hdr *ip4h;
442 		struct ipv4_hdr ip4h_copy;
443 
444 		ip4h = rte_pktmbuf_read(m, off, sizeof(*ip4h), &ip4h_copy);
445 		if (unlikely(ip4h == NULL))
446 			return pkt_type;
447 
448 		pkt_type |= ptype_inner_l3_ip(ip4h->version_ihl);
449 		hdr_lens->inner_l3_len = ip4_hlen(ip4h);
450 		off += hdr_lens->inner_l3_len;
451 
452 		if ((layers & RTE_PTYPE_INNER_L4_MASK) == 0)
453 			return pkt_type;
454 		if (ip4h->fragment_offset &
455 				rte_cpu_to_be_16(IPV4_HDR_OFFSET_MASK |
456 					IPV4_HDR_MF_FLAG)) {
457 			pkt_type |= RTE_PTYPE_INNER_L4_FRAG;
458 			hdr_lens->inner_l4_len = 0;
459 			return pkt_type;
460 		}
461 		proto = ip4h->next_proto_id;
462 		pkt_type |= ptype_inner_l4(proto);
463 	} else if (proto == rte_cpu_to_be_16(ETHER_TYPE_IPv6)) {
464 		const struct ipv6_hdr *ip6h;
465 		struct ipv6_hdr ip6h_copy;
466 		int frag = 0;
467 
468 		ip6h = rte_pktmbuf_read(m, off, sizeof(*ip6h), &ip6h_copy);
469 		if (unlikely(ip6h == NULL))
470 			return pkt_type;
471 
472 		proto = ip6h->proto;
473 		hdr_lens->inner_l3_len = sizeof(*ip6h);
474 		off += hdr_lens->inner_l3_len;
475 		pkt_type |= ptype_inner_l3_ip6(proto);
476 		if ((pkt_type & RTE_PTYPE_INNER_L3_MASK) ==
477 				RTE_PTYPE_INNER_L3_IPV6_EXT) {
478 			uint32_t prev_off;
479 
480 			prev_off = off;
481 			proto = skip_ip6_ext(proto, m, &off, &frag);
482 			hdr_lens->inner_l3_len += off - prev_off;
483 		}
484 		if (proto == 0)
485 			return pkt_type;
486 
487 		if ((layers & RTE_PTYPE_INNER_L4_MASK) == 0)
488 			return pkt_type;
489 
490 		if (frag) {
491 			pkt_type |= RTE_PTYPE_INNER_L4_FRAG;
492 			hdr_lens->inner_l4_len = 0;
493 			return pkt_type;
494 		}
495 		pkt_type |= ptype_inner_l4(proto);
496 	}
497 
498 	if ((pkt_type & RTE_PTYPE_INNER_L4_MASK) == RTE_PTYPE_INNER_L4_UDP) {
499 		hdr_lens->inner_l4_len = sizeof(struct udp_hdr);
500 	} else if ((pkt_type & RTE_PTYPE_INNER_L4_MASK) ==
501 			RTE_PTYPE_INNER_L4_TCP) {
502 		const struct tcp_hdr *th;
503 		struct tcp_hdr th_copy;
504 
505 		th = rte_pktmbuf_read(m, off, sizeof(*th), &th_copy);
506 		if (unlikely(th == NULL))
507 			return pkt_type & (RTE_PTYPE_INNER_L2_MASK |
508 				RTE_PTYPE_INNER_L3_MASK);
509 		hdr_lens->inner_l4_len = (th->data_off & 0xf0) >> 2;
510 	} else if ((pkt_type & RTE_PTYPE_INNER_L4_MASK) ==
511 			RTE_PTYPE_INNER_L4_SCTP) {
512 		hdr_lens->inner_l4_len = sizeof(struct sctp_hdr);
513 	} else {
514 		hdr_lens->inner_l4_len = 0;
515 	}
516 
517 	return pkt_type;
518 }
519