├── image ├── GRE数据包.png └── 一般TCP数据包.png ├── README.md ├── src ├── ss_parser_pkt.h └── ss_parser_pkt.c └── librte_net ├── rte_gre.h ├── rte_sctp.h ├── rte_udp.h ├── rte_icmp.h ├── rte_tcp.h ├── rte_net.h ├── rte_ether.h ├── rte_ip.h ├── rte_mbuf_ptype.h └── rte_mbuf.h /image/GRE数据包.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/gchs2012/dpdk-parser-packet/HEAD/image/GRE数据包.png -------------------------------------------------------------------------------- /image/一般TCP数据包.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/gchs2012/dpdk-parser-packet/HEAD/image/一般TCP数据包.png -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # 解析数据包 2 | 3 | ## 1、一般TCP数据包 4 | ![](image/一般TCP数据包.png) 5 | 6 | ## 2、GRE数据包 7 | ![](image/GRE数据包.png) 8 | -------------------------------------------------------------------------------- /src/ss_parser_pkt.h: -------------------------------------------------------------------------------- 1 | /****************************************************************************** 2 | 3 | 版权所有 (C), 2017-2018, xxx Co.xxx, Ltd. 4 | 5 | ****************************************************************************** 6 | 文 件 名 : ss_parser_pkt.h 7 | 版 本 号 : V1.0 8 | 作 者 : zc 9 | 生成日期 : 2018年8月21日 10 | 功能描述 : 数据包解析头文件 11 | 修改历史 : 12 | ******************************************************************************/ 13 | #ifndef _SS_PARSER_PKT_H_ 14 | #define _SS_PARSER_PKT_H_ 15 | 16 | int ss_parser_pkt(struct rte_mbuf *m); 17 | 18 | #endif 19 | -------------------------------------------------------------------------------- /librte_net/rte_gre.h: -------------------------------------------------------------------------------- 1 | /*- 2 | * BSD LICENSE 3 | * 4 | * Copyright 2016 6WIND S.A. 5 | * 6 | * Redistribution and use in source and binary forms, with or without 7 | * modification, are permitted provided that the following conditions 8 | * are met: 9 | * 10 | * * Redistributions of source code must retain the above copyright 11 | * notice, this list of conditions and the following disclaimer. 12 | * * Redistributions in binary form must reproduce the above copyright 13 | * notice, this list of conditions and the following disclaimer in 14 | * the documentation and/or other materials provided with the 15 | * distribution. 16 | * * Neither the name of Intel Corporation nor the names of its 17 | * contributors may be used to endorse or promote products derived 18 | * from this software without specific prior written permission. 19 | * 20 | * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 21 | * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 22 | * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR 23 | * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 24 | * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 25 | * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 26 | * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 27 | * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 28 | * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 29 | * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 30 | * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 31 | */ 32 | 33 | #ifndef _RTE_GRE_H_ 34 | #define _RTE_GRE_H_ 35 | 36 | #include 37 | #include 38 | 39 | #ifdef __cplusplus 40 | extern "C" { 41 | #endif 42 | 43 | /** 44 | * GRE Header 45 | */ 46 | struct gre_hdr { 47 | #if RTE_BYTE_ORDER == RTE_LITTLE_ENDIAN 48 | uint16_t res2:4; /**< Reserved */ 49 | uint16_t s:1; /**< Sequence Number Present bit */ 50 | uint16_t k:1; /**< Key Present bit */ 51 | uint16_t res1:1; /**< Reserved */ 52 | uint16_t c:1; /**< Checksum Present bit */ 53 | uint16_t ver:3; /**< Version Number */ 54 | uint16_t res3:5; /**< Reserved */ 55 | #elif RTE_BYTE_ORDER == RTE_BIG_ENDIAN 56 | uint16_t c:1; /**< Checksum Present bit */ 57 | uint16_t res1:1; /**< Reserved */ 58 | uint16_t k:1; /**< Key Present bit */ 59 | uint16_t s:1; /**< Sequence Number Present bit */ 60 | uint16_t res2:4; /**< Reserved */ 61 | uint16_t res3:5; /**< Reserved */ 62 | uint16_t ver:3; /**< Version Number */ 63 | #endif 64 | uint16_t proto; /**< Protocol Type */ 65 | } __attribute__((__packed__)); 66 | 67 | #ifdef __cplusplus 68 | } 69 | #endif 70 | 71 | #endif /* RTE_GRE_H_ */ 72 | -------------------------------------------------------------------------------- /librte_net/rte_sctp.h: -------------------------------------------------------------------------------- 1 | /*- 2 | * BSD LICENSE 3 | * 4 | * Copyright(c) 2010-2014 Intel Corporation. All rights reserved. 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 Intel Corporation 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 | /* 35 | * Copyright (c) 1982, 1986, 1990, 1993 36 | * The Regents of the University of California. All rights reserved. 37 | * 38 | * Redistribution and use in source and binary forms, with or without 39 | * modification, are permitted provided that the following conditions 40 | * are met: 41 | * 1. Redistributions of source code must retain the above copyright 42 | * notice, this list of conditions and the following disclaimer. 43 | * 2. Redistributions in binary form must reproduce the above copyright 44 | * notice, this list of conditions and the following disclaimer in the 45 | * documentation and/or other materials provided with the distribution. 46 | * 3. All advertising materials mentioning features or use of this software 47 | * must display the following acknowledgement: 48 | * This product includes software developed by the University of 49 | * California, Berkeley and its contributors. 50 | * 4. Neither the name of the University nor the names of its contributors 51 | * may be used to endorse or promote products derived from this software 52 | * without specific prior written permission. 53 | * 54 | * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND 55 | * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 56 | * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 57 | * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE 58 | * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 59 | * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 60 | * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 61 | * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 62 | * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 63 | * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 64 | * SUCH DAMAGE. 65 | * 66 | * @(#)in.h 8.3 (Berkeley) 1/3/94 67 | * $FreeBSD: src/sys/netinet/in.h,v 1.82 2003/10/25 09:37:10 ume Exp $ 68 | */ 69 | 70 | /** 71 | * @file 72 | * 73 | * SCTP-related defines 74 | */ 75 | 76 | #ifndef _RTE_SCTP_H_ 77 | #define _RTE_SCTP_H_ 78 | 79 | #ifdef __cplusplus 80 | extern "C" { 81 | #endif 82 | 83 | #include 84 | 85 | /** 86 | * SCTP Header 87 | */ 88 | struct sctp_hdr { 89 | uint16_t src_port; /**< Source port. */ 90 | uint16_t dst_port; /**< Destin port. */ 91 | uint32_t tag; /**< Validation tag. */ 92 | uint32_t cksum; /**< Checksum. */ 93 | } __attribute__((__packed__)); 94 | 95 | #ifdef __cplusplus 96 | } 97 | #endif 98 | 99 | #endif /* RTE_SCTP_H_ */ 100 | -------------------------------------------------------------------------------- /librte_net/rte_udp.h: -------------------------------------------------------------------------------- 1 | /*- 2 | * BSD LICENSE 3 | * 4 | * Copyright(c) 2010-2014 Intel Corporation. All rights reserved. 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 Intel Corporation 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 | /* 35 | * Copyright (c) 1982, 1986, 1990, 1993 36 | * The Regents of the University of California. All rights reserved. 37 | * 38 | * Redistribution and use in source and binary forms, with or without 39 | * modification, are permitted provided that the following conditions 40 | * are met: 41 | * 1. Redistributions of source code must retain the above copyright 42 | * notice, this list of conditions and the following disclaimer. 43 | * 2. Redistributions in binary form must reproduce the above copyright 44 | * notice, this list of conditions and the following disclaimer in the 45 | * documentation and/or other materials provided with the distribution. 46 | * 3. All advertising materials mentioning features or use of this software 47 | * must display the following acknowledgement: 48 | * This product includes software developed by the University of 49 | * California, Berkeley and its contributors. 50 | * 4. Neither the name of the University nor the names of its contributors 51 | * may be used to endorse or promote products derived from this software 52 | * without specific prior written permission. 53 | * 54 | * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND 55 | * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 56 | * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 57 | * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE 58 | * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 59 | * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 60 | * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 61 | * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 62 | * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 63 | * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 64 | * SUCH DAMAGE. 65 | * 66 | * @(#)in.h 8.3 (Berkeley) 1/3/94 67 | * $FreeBSD: src/sys/netinet/in.h,v 1.82 2003/10/25 09:37:10 ume Exp $ 68 | */ 69 | 70 | #ifndef _RTE_UDP_H_ 71 | #define _RTE_UDP_H_ 72 | 73 | /** 74 | * @file 75 | * 76 | * UDP-related defines 77 | */ 78 | 79 | #include 80 | 81 | #ifdef __cplusplus 82 | extern "C" { 83 | #endif 84 | 85 | /** 86 | * UDP Header 87 | */ 88 | struct udp_hdr { 89 | uint16_t src_port; /**< UDP source port. */ 90 | uint16_t dst_port; /**< UDP destination port. */ 91 | uint16_t dgram_len; /**< UDP datagram length */ 92 | uint16_t dgram_cksum; /**< UDP datagram checksum */ 93 | } __attribute__((__packed__)); 94 | 95 | #ifdef __cplusplus 96 | } 97 | #endif 98 | 99 | #endif /* RTE_UDP_H_ */ 100 | -------------------------------------------------------------------------------- /librte_net/rte_icmp.h: -------------------------------------------------------------------------------- 1 | /* BSD LICENSE 2 | * 3 | * Copyright(c) 2013 6WIND. 4 | * 5 | * Redistribution and use in source and binary forms, with or without 6 | * modification, are permitted provided that the following conditions 7 | * are met: 8 | * 9 | * * Redistributions of source code must retain the above copyright 10 | * notice, this list of conditions and the following disclaimer. 11 | * * Redistributions in binary form must reproduce the above copyright 12 | * notice, this list of conditions and the following disclaimer in 13 | * the documentation and/or other materials provided with the 14 | * distribution. 15 | * * Neither the name of 6WIND S.A. nor the names of its 16 | * contributors may be used to endorse or promote products derived 17 | * from this software without specific prior written permission. 18 | * 19 | * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 20 | * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 21 | * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR 22 | * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 23 | * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 24 | * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 25 | * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 26 | * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 27 | * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 28 | * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 29 | * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 30 | */ 31 | /* 32 | * Copyright (c) 1982, 1986, 1990, 1993 33 | * The Regents of the University of California. All rights reserved. 34 | * 35 | * Redistribution and use in source and binary forms, with or without 36 | * modification, are permitted provided that the following conditions 37 | * are met: 38 | * 1. Redistributions of source code must retain the above copyright 39 | * notice, this list of conditions and the following disclaimer. 40 | * 2. Redistributions in binary form must reproduce the above copyright 41 | * notice, this list of conditions and the following disclaimer in the 42 | * documentation and/or other materials provided with the distribution. 43 | * 3. All advertising materials mentioning features or use of this software 44 | * must display the following acknowledgement: 45 | * This product includes software developed by the University of 46 | * California, Berkeley and its contributors. 47 | * 4. Neither the name of the University nor the names of its contributors 48 | * may be used to endorse or promote products derived from this software 49 | * without specific prior written permission. 50 | * 51 | * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND 52 | * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 53 | * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 54 | * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE 55 | * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 56 | * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 57 | * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 58 | * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 59 | * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 60 | * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 61 | * SUCH DAMAGE. 62 | * 63 | * @(#)in.h 8.3 (Berkeley) 1/3/94 64 | * $FreeBSD: src/sys/netinet/in.h,v 1.82 2003/10/25 09:37:10 ume Exp $ 65 | */ 66 | 67 | #ifndef _RTE_ICMP_H_ 68 | #define _RTE_ICMP_H_ 69 | 70 | /** 71 | * @file 72 | * 73 | * ICMP-related defines 74 | */ 75 | 76 | #include 77 | 78 | #ifdef __cplusplus 79 | extern "C" { 80 | #endif 81 | 82 | /** 83 | * ICMP Header 84 | */ 85 | struct icmp_hdr { 86 | uint8_t icmp_type; /* ICMP packet type. */ 87 | uint8_t icmp_code; /* ICMP packet code. */ 88 | uint16_t icmp_cksum; /* ICMP packet checksum. */ 89 | uint16_t icmp_ident; /* ICMP packet identifier. */ 90 | uint16_t icmp_seq_nb; /* ICMP packet sequence number. */ 91 | } __attribute__((__packed__)); 92 | 93 | /* ICMP packet types */ 94 | #define IP_ICMP_ECHO_REPLY 0 95 | #define IP_ICMP_ECHO_REQUEST 8 96 | 97 | #ifdef __cplusplus 98 | } 99 | #endif 100 | 101 | #endif /* RTE_ICMP_H_ */ 102 | -------------------------------------------------------------------------------- /librte_net/rte_tcp.h: -------------------------------------------------------------------------------- 1 | /*- 2 | * BSD LICENSE 3 | * 4 | * Copyright(c) 2010-2014 Intel Corporation. All rights reserved. 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 Intel Corporation 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 | /* 35 | * Copyright (c) 1982, 1986, 1990, 1993 36 | * The Regents of the University of California. All rights reserved. 37 | * 38 | * Redistribution and use in source and binary forms, with or without 39 | * modification, are permitted provided that the following conditions 40 | * are met: 41 | * 1. Redistributions of source code must retain the above copyright 42 | * notice, this list of conditions and the following disclaimer. 43 | * 2. Redistributions in binary form must reproduce the above copyright 44 | * notice, this list of conditions and the following disclaimer in the 45 | * documentation and/or other materials provided with the distribution. 46 | * 3. All advertising materials mentioning features or use of this software 47 | * must display the following acknowledgement: 48 | * This product includes software developed by the University of 49 | * California, Berkeley and its contributors. 50 | * 4. Neither the name of the University nor the names of its contributors 51 | * may be used to endorse or promote products derived from this software 52 | * without specific prior written permission. 53 | * 54 | * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND 55 | * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 56 | * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 57 | * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE 58 | * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 59 | * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 60 | * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 61 | * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 62 | * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 63 | * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 64 | * SUCH DAMAGE. 65 | * 66 | * @(#)in.h 8.3 (Berkeley) 1/3/94 67 | * $FreeBSD: src/sys/netinet/in.h,v 1.82 2003/10/25 09:37:10 ume Exp $ 68 | */ 69 | 70 | #ifndef _RTE_TCP_H_ 71 | #define _RTE_TCP_H_ 72 | 73 | /** 74 | * @file 75 | * 76 | * TCP-related defines 77 | */ 78 | 79 | #include 80 | 81 | #ifdef __cplusplus 82 | extern "C" { 83 | #endif 84 | 85 | /** 86 | * TCP Header 87 | */ 88 | struct tcp_hdr { 89 | uint16_t src_port; /**< TCP source port. */ 90 | uint16_t dst_port; /**< TCP destination port. */ 91 | uint32_t sent_seq; /**< TX data sequence number. */ 92 | uint32_t recv_ack; /**< RX data acknowledgement sequence number. */ 93 | uint8_t data_off; /**< Data offset. */ 94 | uint8_t tcp_flags; /**< TCP flags */ 95 | uint16_t rx_win; /**< RX flow control window. */ 96 | uint16_t cksum; /**< TCP checksum. */ 97 | uint16_t tcp_urp; /**< TCP urgent pointer, if any. */ 98 | } __attribute__((__packed__)); 99 | 100 | #ifdef __cplusplus 101 | } 102 | #endif 103 | 104 | #endif /* RTE_TCP_H_ */ 105 | -------------------------------------------------------------------------------- /librte_net/rte_net.h: -------------------------------------------------------------------------------- 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 Intel Corporation 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 | #ifndef _RTE_NET_PTYPE_H_ 35 | #define _RTE_NET_PTYPE_H_ 36 | 37 | #ifdef __cplusplus 38 | extern "C" { 39 | #endif 40 | 41 | #include 42 | #include 43 | #include 44 | #include 45 | 46 | /** 47 | * Structure containing header lengths associated to a packet, filled 48 | * by rte_net_get_ptype(). 49 | */ 50 | struct rte_net_hdr_lens { 51 | uint8_t l2_len; 52 | uint8_t l3_len; 53 | uint8_t l4_len; 54 | uint8_t tunnel_len; 55 | uint8_t inner_l2_len; 56 | uint8_t inner_l3_len; 57 | uint8_t inner_l4_len; 58 | }; 59 | 60 | /** 61 | * Parse an Ethernet packet to get its packet type. 62 | * 63 | * This function parses the network headers in mbuf data and return its 64 | * packet type. 65 | * 66 | * If it is provided by the user, it also fills a rte_net_hdr_lens 67 | * structure that contains the lengths of the parsed network 68 | * headers. Each length field is valid only if the associated packet 69 | * type is set. For instance, hdr_lens->l2_len is valid only if 70 | * (retval & RTE_PTYPE_L2_MASK) != RTE_PTYPE_UNKNOWN. 71 | * 72 | * Supported packet types are: 73 | * L2: Ether, Vlan, QinQ 74 | * L3: IPv4, IPv6 75 | * L4: TCP, UDP, SCTP 76 | * Tunnels: IPv4, IPv6, Gre, Nvgre 77 | * 78 | * @param m 79 | * The packet mbuf to be parsed. 80 | * @param hdr_lens 81 | * A pointer to a structure where the header lengths will be returned, 82 | * or NULL. 83 | * @param layers 84 | * List of layers to parse. The function will stop at the first 85 | * empty layer. Examples: 86 | * - To parse all known layers, use RTE_PTYPE_ALL_MASK. 87 | * - To parse only L2 and L3, use RTE_PTYPE_L2_MASK | RTE_PTYPE_L3_MASK 88 | * @return 89 | * The packet type of the packet. 90 | */ 91 | uint32_t rte_net_get_ptype(const struct rte_mbuf *m, 92 | struct rte_net_hdr_lens *hdr_lens, uint32_t layers); 93 | 94 | /** 95 | * Prepare pseudo header checksum 96 | * 97 | * This function prepares pseudo header checksum for TSO and non-TSO tcp/udp in 98 | * provided mbufs packet data and based on the requested offload flags. 99 | * 100 | * - for non-TSO tcp/udp packets full pseudo-header checksum is counted and set 101 | * in packet data, 102 | * - for TSO the IP payload length is not included in pseudo header. 103 | * 104 | * This function expects that used headers are in the first data segment of 105 | * mbuf, are not fragmented and can be safely modified. 106 | * 107 | * @param m 108 | * The packet mbuf to be fixed. 109 | * @param ol_flags 110 | * TX offloads flags to use with this packet. 111 | * @return 112 | * 0 if checksum is initialized properly 113 | */ 114 | static inline int 115 | rte_net_intel_cksum_flags_prepare(struct rte_mbuf *m, uint64_t ol_flags) 116 | { 117 | struct ipv4_hdr *ipv4_hdr; 118 | struct ipv6_hdr *ipv6_hdr; 119 | struct tcp_hdr *tcp_hdr; 120 | struct udp_hdr *udp_hdr; 121 | uint64_t inner_l3_offset = m->l2_len; 122 | 123 | if ((ol_flags & PKT_TX_OUTER_IP_CKSUM) || 124 | (ol_flags & PKT_TX_OUTER_IPV6)) 125 | inner_l3_offset += m->outer_l2_len + m->outer_l3_len; 126 | 127 | if ((ol_flags & PKT_TX_UDP_CKSUM) == PKT_TX_UDP_CKSUM) { 128 | if (ol_flags & PKT_TX_IPV4) { 129 | ipv4_hdr = rte_pktmbuf_mtod_offset(m, struct ipv4_hdr *, 130 | inner_l3_offset); 131 | 132 | if (ol_flags & PKT_TX_IP_CKSUM) 133 | ipv4_hdr->hdr_checksum = 0; 134 | 135 | udp_hdr = (struct udp_hdr *)((char *)ipv4_hdr + 136 | m->l3_len); 137 | udp_hdr->dgram_cksum = rte_ipv4_phdr_cksum(ipv4_hdr, 138 | ol_flags); 139 | } else { 140 | ipv6_hdr = rte_pktmbuf_mtod_offset(m, struct ipv6_hdr *, 141 | inner_l3_offset); 142 | /* non-TSO udp */ 143 | udp_hdr = rte_pktmbuf_mtod_offset(m, struct udp_hdr *, 144 | inner_l3_offset + m->l3_len); 145 | udp_hdr->dgram_cksum = rte_ipv6_phdr_cksum(ipv6_hdr, 146 | ol_flags); 147 | } 148 | } else if ((ol_flags & PKT_TX_TCP_CKSUM) || 149 | (ol_flags & PKT_TX_TCP_SEG)) { 150 | if (ol_flags & PKT_TX_IPV4) { 151 | ipv4_hdr = rte_pktmbuf_mtod_offset(m, struct ipv4_hdr *, 152 | inner_l3_offset); 153 | 154 | if (ol_flags & PKT_TX_IP_CKSUM) 155 | ipv4_hdr->hdr_checksum = 0; 156 | 157 | /* non-TSO tcp or TSO */ 158 | tcp_hdr = (struct tcp_hdr *)((char *)ipv4_hdr + 159 | m->l3_len); 160 | tcp_hdr->cksum = rte_ipv4_phdr_cksum(ipv4_hdr, 161 | ol_flags); 162 | } else { 163 | ipv6_hdr = rte_pktmbuf_mtod_offset(m, struct ipv6_hdr *, 164 | inner_l3_offset); 165 | /* non-TSO tcp or TSO */ 166 | tcp_hdr = rte_pktmbuf_mtod_offset(m, struct tcp_hdr *, 167 | inner_l3_offset + m->l3_len); 168 | tcp_hdr->cksum = rte_ipv6_phdr_cksum(ipv6_hdr, 169 | ol_flags); 170 | } 171 | } 172 | 173 | return 0; 174 | } 175 | 176 | /** 177 | * Prepare pseudo header checksum 178 | * 179 | * This function prepares pseudo header checksum for TSO and non-TSO tcp/udp in 180 | * provided mbufs packet data. 181 | * 182 | * - for non-TSO tcp/udp packets full pseudo-header checksum is counted and set 183 | * in packet data, 184 | * - for TSO the IP payload length is not included in pseudo header. 185 | * 186 | * This function expects that used headers are in the first data segment of 187 | * mbuf, are not fragmented and can be safely modified. 188 | * 189 | * @param m 190 | * The packet mbuf to be fixed. 191 | * @return 192 | * 0 if checksum is initialized properly 193 | */ 194 | static inline int 195 | rte_net_intel_cksum_prepare(struct rte_mbuf *m) 196 | { 197 | return rte_net_intel_cksum_flags_prepare(m, m->ol_flags); 198 | } 199 | 200 | #ifdef __cplusplus 201 | } 202 | #endif 203 | 204 | 205 | #endif /* _RTE_NET_PTYPE_H_ */ 206 | -------------------------------------------------------------------------------- /librte_net/rte_ether.h: -------------------------------------------------------------------------------- 1 | /*- 2 | * BSD LICENSE 3 | * 4 | * Copyright(c) 2010-2014 Intel Corporation. All rights reserved. 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 Intel Corporation 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 | #ifndef _RTE_ETHER_H_ 35 | #define _RTE_ETHER_H_ 36 | 37 | /** 38 | * @file 39 | * 40 | * Ethernet Helpers in RTE 41 | */ 42 | 43 | #ifdef __cplusplus 44 | extern "C" { 45 | #endif 46 | 47 | #include 48 | #include 49 | 50 | #include 51 | #include 52 | #include 53 | #include 54 | 55 | #define ETHER_ADDR_LEN 6 /**< Length of Ethernet address. */ 56 | #define ETHER_TYPE_LEN 2 /**< Length of Ethernet type field. */ 57 | #define ETHER_CRC_LEN 4 /**< Length of Ethernet CRC. */ 58 | #define ETHER_HDR_LEN \ 59 | (ETHER_ADDR_LEN * 2 + ETHER_TYPE_LEN) /**< Length of Ethernet header. */ 60 | #define ETHER_MIN_LEN 64 /**< Minimum frame len, including CRC. */ 61 | #define ETHER_MAX_LEN 1518 /**< Maximum frame len, including CRC. */ 62 | #define ETHER_MTU \ 63 | (ETHER_MAX_LEN - ETHER_HDR_LEN - ETHER_CRC_LEN) /**< Ethernet MTU. */ 64 | 65 | #define ETHER_MAX_VLAN_FRAME_LEN \ 66 | (ETHER_MAX_LEN + 4) /**< Maximum VLAN frame length, including CRC. */ 67 | 68 | #define ETHER_MAX_JUMBO_FRAME_LEN \ 69 | 0x3F00 /**< Maximum Jumbo frame length, including CRC. */ 70 | 71 | #define ETHER_MAX_VLAN_ID 4095 /**< Maximum VLAN ID. */ 72 | 73 | #define ETHER_MIN_MTU 68 /**< Minimum MTU for IPv4 packets, see RFC 791. */ 74 | 75 | /** 76 | * Ethernet address: 77 | * A universally administered address is uniquely assigned to a device by its 78 | * manufacturer. The first three octets (in transmission order) contain the 79 | * Organizationally Unique Identifier (OUI). The following three (MAC-48 and 80 | * EUI-48) octets are assigned by that organization with the only constraint 81 | * of uniqueness. 82 | * A locally administered address is assigned to a device by a network 83 | * administrator and does not contain OUIs. 84 | * See http://standards.ieee.org/regauth/groupmac/tutorial.html 85 | */ 86 | struct ether_addr { 87 | uint8_t addr_bytes[ETHER_ADDR_LEN]; /**< Addr bytes in tx order */ 88 | } __attribute__((__packed__)); 89 | 90 | #define ETHER_LOCAL_ADMIN_ADDR 0x02 /**< Locally assigned Eth. address. */ 91 | #define ETHER_GROUP_ADDR 0x01 /**< Multicast or broadcast Eth. address. */ 92 | 93 | /** 94 | * Check if two Ethernet addresses are the same. 95 | * 96 | * @param ea1 97 | * A pointer to the first ether_addr structure containing 98 | * the ethernet address. 99 | * @param ea2 100 | * A pointer to the second ether_addr structure containing 101 | * the ethernet address. 102 | * 103 | * @return 104 | * True (1) if the given two ethernet address are the same; 105 | * False (0) otherwise. 106 | */ 107 | static inline int is_same_ether_addr(const struct ether_addr *ea1, 108 | const struct ether_addr *ea2) 109 | { 110 | int i; 111 | for (i = 0; i < ETHER_ADDR_LEN; i++) 112 | if (ea1->addr_bytes[i] != ea2->addr_bytes[i]) 113 | return 0; 114 | return 1; 115 | } 116 | 117 | /** 118 | * Check if an Ethernet address is filled with zeros. 119 | * 120 | * @param ea 121 | * A pointer to a ether_addr structure containing the ethernet address 122 | * to check. 123 | * @return 124 | * True (1) if the given ethernet address is filled with zeros; 125 | * false (0) otherwise. 126 | */ 127 | static inline int is_zero_ether_addr(const struct ether_addr *ea) 128 | { 129 | int i; 130 | for (i = 0; i < ETHER_ADDR_LEN; i++) 131 | if (ea->addr_bytes[i] != 0x00) 132 | return 0; 133 | return 1; 134 | } 135 | 136 | /** 137 | * Check if an Ethernet address is a unicast address. 138 | * 139 | * @param ea 140 | * A pointer to a ether_addr structure containing the ethernet address 141 | * to check. 142 | * @return 143 | * True (1) if the given ethernet address is a unicast address; 144 | * false (0) otherwise. 145 | */ 146 | static inline int is_unicast_ether_addr(const struct ether_addr *ea) 147 | { 148 | return (ea->addr_bytes[0] & ETHER_GROUP_ADDR) == 0; 149 | } 150 | 151 | /** 152 | * Check if an Ethernet address is a multicast address. 153 | * 154 | * @param ea 155 | * A pointer to a ether_addr structure containing the ethernet address 156 | * to check. 157 | * @return 158 | * True (1) if the given ethernet address is a multicast address; 159 | * false (0) otherwise. 160 | */ 161 | static inline int is_multicast_ether_addr(const struct ether_addr *ea) 162 | { 163 | return ea->addr_bytes[0] & ETHER_GROUP_ADDR; 164 | } 165 | 166 | /** 167 | * Check if an Ethernet address is a broadcast address. 168 | * 169 | * @param ea 170 | * A pointer to a ether_addr structure containing the ethernet address 171 | * to check. 172 | * @return 173 | * True (1) if the given ethernet address is a broadcast address; 174 | * false (0) otherwise. 175 | */ 176 | static inline int is_broadcast_ether_addr(const struct ether_addr *ea) 177 | { 178 | const unaligned_uint16_t *ea_words = (const unaligned_uint16_t *)ea; 179 | 180 | return (ea_words[0] == 0xFFFF && ea_words[1] == 0xFFFF && 181 | ea_words[2] == 0xFFFF); 182 | } 183 | 184 | /** 185 | * Check if an Ethernet address is a universally assigned address. 186 | * 187 | * @param ea 188 | * A pointer to a ether_addr structure containing the ethernet address 189 | * to check. 190 | * @return 191 | * True (1) if the given ethernet address is a universally assigned address; 192 | * false (0) otherwise. 193 | */ 194 | static inline int is_universal_ether_addr(const struct ether_addr *ea) 195 | { 196 | return (ea->addr_bytes[0] & ETHER_LOCAL_ADMIN_ADDR) == 0; 197 | } 198 | 199 | /** 200 | * Check if an Ethernet address is a locally assigned address. 201 | * 202 | * @param ea 203 | * A pointer to a ether_addr structure containing the ethernet address 204 | * to check. 205 | * @return 206 | * True (1) if the given ethernet address is a locally assigned address; 207 | * false (0) otherwise. 208 | */ 209 | static inline int is_local_admin_ether_addr(const struct ether_addr *ea) 210 | { 211 | return (ea->addr_bytes[0] & ETHER_LOCAL_ADMIN_ADDR) != 0; 212 | } 213 | 214 | /** 215 | * Check if an Ethernet address is a valid address. Checks that the address is a 216 | * unicast address and is not filled with zeros. 217 | * 218 | * @param ea 219 | * A pointer to a ether_addr structure containing the ethernet address 220 | * to check. 221 | * @return 222 | * True (1) if the given ethernet address is valid; 223 | * false (0) otherwise. 224 | */ 225 | static inline int is_valid_assigned_ether_addr(const struct ether_addr *ea) 226 | { 227 | return is_unicast_ether_addr(ea) && (!is_zero_ether_addr(ea)); 228 | } 229 | 230 | /** 231 | * Generate a random Ethernet address that is locally administered 232 | * and not multicast. 233 | * @param addr 234 | * A pointer to Ethernet address. 235 | */ 236 | static inline void eth_random_addr(uint8_t *addr) 237 | { 238 | uint64_t rand = rte_rand(); 239 | uint8_t *p = (uint8_t *)&rand; 240 | 241 | rte_memcpy(addr, p, ETHER_ADDR_LEN); 242 | addr[0] &= ~ETHER_GROUP_ADDR; /* clear multicast bit */ 243 | addr[0] |= ETHER_LOCAL_ADMIN_ADDR; /* set local assignment bit */ 244 | } 245 | 246 | /** 247 | * Fast copy an Ethernet address. 248 | * 249 | * @param ea_from 250 | * A pointer to a ether_addr structure holding the Ethernet address to copy. 251 | * @param ea_to 252 | * A pointer to a ether_addr structure where to copy the Ethernet address. 253 | */ 254 | static inline void ether_addr_copy(const struct ether_addr *ea_from, 255 | struct ether_addr *ea_to) 256 | { 257 | #ifdef __INTEL_COMPILER 258 | uint16_t *from_words = (uint16_t *)(ea_from->addr_bytes); 259 | uint16_t *to_words = (uint16_t *)(ea_to->addr_bytes); 260 | 261 | to_words[0] = from_words[0]; 262 | to_words[1] = from_words[1]; 263 | to_words[2] = from_words[2]; 264 | #else 265 | /* 266 | * Use the common way, because of a strange gcc warning. 267 | */ 268 | *ea_to = *ea_from; 269 | #endif 270 | } 271 | 272 | #define ETHER_ADDR_FMT_SIZE 18 273 | /** 274 | * Format 48bits Ethernet address in pattern xx:xx:xx:xx:xx:xx. 275 | * 276 | * @param buf 277 | * A pointer to buffer contains the formatted MAC address. 278 | * @param size 279 | * The format buffer size. 280 | * @param eth_addr 281 | * A pointer to a ether_addr structure. 282 | */ 283 | static inline void 284 | ether_format_addr(char *buf, uint16_t size, 285 | const struct ether_addr *eth_addr) 286 | { 287 | snprintf(buf, size, "%02X:%02X:%02X:%02X:%02X:%02X", 288 | eth_addr->addr_bytes[0], 289 | eth_addr->addr_bytes[1], 290 | eth_addr->addr_bytes[2], 291 | eth_addr->addr_bytes[3], 292 | eth_addr->addr_bytes[4], 293 | eth_addr->addr_bytes[5]); 294 | } 295 | 296 | /** 297 | * Ethernet header: Contains the destination address, source address 298 | * and frame type. 299 | */ 300 | struct ether_hdr { 301 | struct ether_addr d_addr; /**< Destination address. */ 302 | struct ether_addr s_addr; /**< Source address. */ 303 | uint16_t ether_type; /**< Frame type. */ 304 | } __attribute__((__packed__)); 305 | 306 | /** 307 | * Ethernet VLAN Header. 308 | * Contains the 16-bit VLAN Tag Control Identifier and the Ethernet type 309 | * of the encapsulated frame. 310 | */ 311 | struct vlan_hdr { 312 | uint16_t vlan_tci; /**< Priority (3) + CFI (1) + Identifier Code (12) */ 313 | uint16_t eth_proto;/**< Ethernet type of encapsulated frame. */ 314 | } __attribute__((__packed__)); 315 | 316 | /** 317 | * VXLAN protocol header. 318 | * Contains the 8-bit flag, 24-bit VXLAN Network Identifier and 319 | * Reserved fields (24 bits and 8 bits) 320 | */ 321 | struct vxlan_hdr { 322 | uint32_t vx_flags; /**< flag (8) + Reserved (24). */ 323 | uint32_t vx_vni; /**< VNI (24) + Reserved (8). */ 324 | } __attribute__((__packed__)); 325 | 326 | /* Ethernet frame types */ 327 | #define ETHER_TYPE_IPv4 0x0800 /**< IPv4 Protocol. */ 328 | #define ETHER_TYPE_IPv6 0x86DD /**< IPv6 Protocol. */ 329 | #define ETHER_TYPE_ARP 0x0806 /**< Arp Protocol. */ 330 | #define ETHER_TYPE_RARP 0x8035 /**< Reverse Arp Protocol. */ 331 | #define ETHER_TYPE_VLAN 0x8100 /**< IEEE 802.1Q VLAN tagging. */ 332 | #define ETHER_TYPE_QINQ 0x88A8 /**< IEEE 802.1ad QinQ tagging. */ 333 | #define ETHER_TYPE_1588 0x88F7 /**< IEEE 802.1AS 1588 Precise Time Protocol. */ 334 | #define ETHER_TYPE_SLOW 0x8809 /**< Slow protocols (LACP and Marker). */ 335 | #define ETHER_TYPE_TEB 0x6558 /**< Transparent Ethernet Bridging. */ 336 | #define ETHER_TYPE_LLDP 0x88CC /**< LLDP Protocol. */ 337 | 338 | #define ETHER_VXLAN_HLEN (sizeof(struct udp_hdr) + sizeof(struct vxlan_hdr)) 339 | /**< VXLAN tunnel header length. */ 340 | 341 | /** 342 | * Extract VLAN tag information into mbuf 343 | * 344 | * Software version of VLAN stripping 345 | * 346 | * @param m 347 | * The packet mbuf. 348 | * @return 349 | * - 0: Success 350 | * - 1: not a vlan packet 351 | */ 352 | static inline int rte_vlan_strip(struct rte_mbuf *m) 353 | { 354 | struct ether_hdr *eh 355 | = rte_pktmbuf_mtod(m, struct ether_hdr *); 356 | 357 | if (eh->ether_type != rte_cpu_to_be_16(ETHER_TYPE_VLAN)) 358 | return -1; 359 | 360 | struct vlan_hdr *vh = (struct vlan_hdr *)(eh + 1); 361 | m->ol_flags |= PKT_RX_VLAN | PKT_RX_VLAN_STRIPPED; 362 | m->vlan_tci = rte_be_to_cpu_16(vh->vlan_tci); 363 | 364 | /* Copy ether header over rather than moving whole packet */ 365 | memmove(rte_pktmbuf_adj(m, sizeof(struct vlan_hdr)), 366 | eh, 2 * ETHER_ADDR_LEN); 367 | 368 | return 0; 369 | } 370 | 371 | /** 372 | * Insert VLAN tag into mbuf. 373 | * 374 | * Software version of VLAN unstripping 375 | * 376 | * @param m 377 | * The packet mbuf. 378 | * @return 379 | * - 0: On success 380 | * -EPERM: mbuf is is shared overwriting would be unsafe 381 | * -ENOSPC: not enough headroom in mbuf 382 | */ 383 | static inline int rte_vlan_insert(struct rte_mbuf **m) 384 | { 385 | struct ether_hdr *oh, *nh; 386 | struct vlan_hdr *vh; 387 | 388 | /* Can't insert header if mbuf is shared */ 389 | if (rte_mbuf_refcnt_read(*m) > 1) { 390 | struct rte_mbuf *copy; 391 | 392 | copy = rte_pktmbuf_clone(*m, (*m)->pool); 393 | if (unlikely(copy == NULL)) 394 | return -ENOMEM; 395 | rte_pktmbuf_free(*m); 396 | *m = copy; 397 | } 398 | 399 | oh = rte_pktmbuf_mtod(*m, struct ether_hdr *); 400 | nh = (struct ether_hdr *) 401 | rte_pktmbuf_prepend(*m, sizeof(struct vlan_hdr)); 402 | if (nh == NULL) 403 | return -ENOSPC; 404 | 405 | memmove(nh, oh, 2 * ETHER_ADDR_LEN); 406 | nh->ether_type = rte_cpu_to_be_16(ETHER_TYPE_VLAN); 407 | 408 | vh = (struct vlan_hdr *) (nh + 1); 409 | vh->vlan_tci = rte_cpu_to_be_16((*m)->vlan_tci); 410 | 411 | (*m)->ol_flags &= ~PKT_RX_VLAN_STRIPPED; 412 | 413 | return 0; 414 | } 415 | 416 | #ifdef __cplusplus 417 | } 418 | #endif 419 | 420 | #endif /* _RTE_ETHER_H_ */ 421 | -------------------------------------------------------------------------------- /librte_net/rte_ip.h: -------------------------------------------------------------------------------- 1 | /*- 2 | * BSD LICENSE 3 | * 4 | * Copyright(c) 2010-2014 Intel Corporation. All rights reserved. 5 | * Copyright 2014 6WIND S.A. 6 | * All rights reserved. 7 | * 8 | * Redistribution and use in source and binary forms, with or without 9 | * modification, are permitted provided that the following conditions 10 | * are met: 11 | * 12 | * * Redistributions of source code must retain the above copyright 13 | * notice, this list of conditions and the following disclaimer. 14 | * * Redistributions in binary form must reproduce the above copyright 15 | * notice, this list of conditions and the following disclaimer in 16 | * the documentation and/or other materials provided with the 17 | * distribution. 18 | * * Neither the name of Intel Corporation nor the names of its 19 | * contributors may be used to endorse or promote products derived 20 | * from this software without specific prior written permission. 21 | * 22 | * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 23 | * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 24 | * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR 25 | * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 26 | * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 27 | * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 28 | * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 29 | * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 30 | * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 31 | * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 32 | * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 33 | */ 34 | 35 | /* 36 | * Copyright (c) 1982, 1986, 1990, 1993 37 | * The Regents of the University of California. All rights reserved. 38 | * 39 | * Redistribution and use in source and binary forms, with or without 40 | * modification, are permitted provided that the following conditions 41 | * are met: 42 | * 1. Redistributions of source code must retain the above copyright 43 | * notice, this list of conditions and the following disclaimer. 44 | * 2. Redistributions in binary form must reproduce the above copyright 45 | * notice, this list of conditions and the following disclaimer in the 46 | * documentation and/or other materials provided with the distribution. 47 | * 3. All advertising materials mentioning features or use of this software 48 | * must display the following acknowledgement: 49 | * This product includes software developed by the University of 50 | * California, Berkeley and its contributors. 51 | * 4. Neither the name of the University nor the names of its contributors 52 | * may be used to endorse or promote products derived from this software 53 | * without specific prior written permission. 54 | * 55 | * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND 56 | * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 57 | * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 58 | * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE 59 | * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 60 | * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 61 | * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 62 | * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 63 | * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 64 | * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 65 | * SUCH DAMAGE. 66 | * 67 | * @(#)in.h 8.3 (Berkeley) 1/3/94 68 | * $FreeBSD: src/sys/netinet/in.h,v 1.82 2003/10/25 09:37:10 ume Exp $ 69 | */ 70 | 71 | #ifndef _RTE_IP_H_ 72 | #define _RTE_IP_H_ 73 | 74 | /** 75 | * @file 76 | * 77 | * IP-related defines 78 | */ 79 | 80 | #include 81 | #include 82 | 83 | #include 84 | #include 85 | 86 | #ifdef __cplusplus 87 | extern "C" { 88 | #endif 89 | 90 | /** 91 | * IPv4 Header 92 | */ 93 | struct ipv4_hdr { 94 | uint8_t version_ihl; /**< version and header length */ 95 | uint8_t type_of_service; /**< type of service */ 96 | uint16_t total_length; /**< length of packet */ 97 | uint16_t packet_id; /**< packet ID */ 98 | uint16_t fragment_offset; /**< fragmentation offset */ 99 | uint8_t time_to_live; /**< time to live */ 100 | uint8_t next_proto_id; /**< protocol ID */ 101 | uint16_t hdr_checksum; /**< header checksum */ 102 | uint32_t src_addr; /**< source address */ 103 | uint32_t dst_addr; /**< destination address */ 104 | } __attribute__((__packed__)); 105 | 106 | /** Create IPv4 address */ 107 | #define IPv4(a,b,c,d) ((uint32_t)(((a) & 0xff) << 24) | \ 108 | (((b) & 0xff) << 16) | \ 109 | (((c) & 0xff) << 8) | \ 110 | ((d) & 0xff)) 111 | 112 | /** Maximal IPv4 packet length (including a header) */ 113 | #define IPV4_MAX_PKT_LEN 65535 114 | 115 | /** Internet header length mask for version_ihl field */ 116 | #define IPV4_HDR_IHL_MASK (0x0f) 117 | /** 118 | * Internet header length field multiplier (IHL field specifies overall header 119 | * length in number of 4-byte words) 120 | */ 121 | #define IPV4_IHL_MULTIPLIER (4) 122 | 123 | /* Fragment Offset * Flags. */ 124 | #define IPV4_HDR_DF_SHIFT 14 125 | #define IPV4_HDR_MF_SHIFT 13 126 | #define IPV4_HDR_FO_SHIFT 3 127 | 128 | #define IPV4_HDR_DF_FLAG (1 << IPV4_HDR_DF_SHIFT) 129 | #define IPV4_HDR_MF_FLAG (1 << IPV4_HDR_MF_SHIFT) 130 | 131 | #define IPV4_HDR_OFFSET_MASK ((1 << IPV4_HDR_MF_SHIFT) - 1) 132 | 133 | #define IPV4_HDR_OFFSET_UNITS 8 134 | 135 | /* 136 | * IPv4 address types 137 | */ 138 | #define IPV4_ANY ((uint32_t)0x00000000) /**< 0.0.0.0 */ 139 | #define IPV4_LOOPBACK ((uint32_t)0x7f000001) /**< 127.0.0.1 */ 140 | #define IPV4_BROADCAST ((uint32_t)0xe0000000) /**< 224.0.0.0 */ 141 | #define IPV4_ALLHOSTS_GROUP ((uint32_t)0xe0000001) /**< 224.0.0.1 */ 142 | #define IPV4_ALLRTRS_GROUP ((uint32_t)0xe0000002) /**< 224.0.0.2 */ 143 | #define IPV4_MAX_LOCAL_GROUP ((uint32_t)0xe00000ff) /**< 224.0.0.255 */ 144 | 145 | /* 146 | * IPv4 Multicast-related macros 147 | */ 148 | #define IPV4_MIN_MCAST IPv4(224, 0, 0, 0) /**< Minimal IPv4-multicast address */ 149 | #define IPV4_MAX_MCAST IPv4(239, 255, 255, 255) /**< Maximum IPv4 multicast address */ 150 | 151 | #define IS_IPV4_MCAST(x) \ 152 | ((x) >= IPV4_MIN_MCAST && (x) <= IPV4_MAX_MCAST) /**< check if IPv4 address is multicast */ 153 | 154 | /** 155 | * @internal Calculate a sum of all words in the buffer. 156 | * Helper routine for the rte_raw_cksum(). 157 | * 158 | * @param buf 159 | * Pointer to the buffer. 160 | * @param len 161 | * Length of the buffer. 162 | * @param sum 163 | * Initial value of the sum. 164 | * @return 165 | * sum += Sum of all words in the buffer. 166 | */ 167 | static inline uint32_t 168 | __rte_raw_cksum(const void *buf, size_t len, uint32_t sum) 169 | { 170 | /* workaround gcc strict-aliasing warning */ 171 | uintptr_t ptr = (uintptr_t)buf; 172 | typedef uint16_t __attribute__((__may_alias__)) u16_p; 173 | const u16_p *u16 = (const u16_p *)ptr; 174 | 175 | while (len >= (sizeof(*u16) * 4)) { 176 | sum += u16[0]; 177 | sum += u16[1]; 178 | sum += u16[2]; 179 | sum += u16[3]; 180 | len -= sizeof(*u16) * 4; 181 | u16 += 4; 182 | } 183 | while (len >= sizeof(*u16)) { 184 | sum += *u16; 185 | len -= sizeof(*u16); 186 | u16 += 1; 187 | } 188 | 189 | /* if length is in odd bytes */ 190 | if (len == 1) 191 | sum += *((const uint8_t *)u16); 192 | 193 | return sum; 194 | } 195 | 196 | /** 197 | * @internal Reduce a sum to the non-complemented checksum. 198 | * Helper routine for the rte_raw_cksum(). 199 | * 200 | * @param sum 201 | * Value of the sum. 202 | * @return 203 | * The non-complemented checksum. 204 | */ 205 | static inline uint16_t 206 | __rte_raw_cksum_reduce(uint32_t sum) 207 | { 208 | sum = ((sum & 0xffff0000) >> 16) + (sum & 0xffff); 209 | sum = ((sum & 0xffff0000) >> 16) + (sum & 0xffff); 210 | return (uint16_t)sum; 211 | } 212 | 213 | /** 214 | * Process the non-complemented checksum of a buffer. 215 | * 216 | * @param buf 217 | * Pointer to the buffer. 218 | * @param len 219 | * Length of the buffer. 220 | * @return 221 | * The non-complemented checksum. 222 | */ 223 | static inline uint16_t 224 | rte_raw_cksum(const void *buf, size_t len) 225 | { 226 | uint32_t sum; 227 | 228 | sum = __rte_raw_cksum(buf, len, 0); 229 | return __rte_raw_cksum_reduce(sum); 230 | } 231 | 232 | /** 233 | * Compute the raw (non complemented) checksum of a packet. 234 | * 235 | * @param m 236 | * The pointer to the mbuf. 237 | * @param off 238 | * The offset in bytes to start the checksum. 239 | * @param len 240 | * The length in bytes of the data to checksum. 241 | * @param cksum 242 | * A pointer to the checksum, filled on success. 243 | * @return 244 | * 0 on success, -1 on error (bad length or offset). 245 | */ 246 | static inline int 247 | rte_raw_cksum_mbuf(const struct rte_mbuf *m, uint32_t off, uint32_t len, 248 | uint16_t *cksum) 249 | { 250 | const struct rte_mbuf *seg; 251 | const char *buf; 252 | uint32_t sum, tmp; 253 | uint32_t seglen, done; 254 | 255 | /* easy case: all data in the first segment */ 256 | if (off + len <= rte_pktmbuf_data_len(m)) { 257 | *cksum = rte_raw_cksum(rte_pktmbuf_mtod_offset(m, 258 | const char *, off), len); 259 | return 0; 260 | } 261 | 262 | if (unlikely(off + len > rte_pktmbuf_pkt_len(m))) 263 | return -1; /* invalid params, return a dummy value */ 264 | 265 | /* else browse the segment to find offset */ 266 | seglen = 0; 267 | for (seg = m; seg != NULL; seg = seg->next) { 268 | seglen = rte_pktmbuf_data_len(seg); 269 | if (off < seglen) 270 | break; 271 | off -= seglen; 272 | } 273 | seglen -= off; 274 | buf = rte_pktmbuf_mtod_offset(seg, const char *, off); 275 | if (seglen >= len) { 276 | /* all in one segment */ 277 | *cksum = rte_raw_cksum(buf, len); 278 | return 0; 279 | } 280 | 281 | /* hard case: process checksum of several segments */ 282 | sum = 0; 283 | done = 0; 284 | for (;;) { 285 | tmp = __rte_raw_cksum(buf, seglen, 0); 286 | if (done & 1) 287 | tmp = rte_bswap16(tmp); 288 | sum += tmp; 289 | done += seglen; 290 | if (done == len) 291 | break; 292 | seg = seg->next; 293 | buf = rte_pktmbuf_mtod(seg, const char *); 294 | seglen = rte_pktmbuf_data_len(seg); 295 | if (seglen > len - done) 296 | seglen = len - done; 297 | } 298 | 299 | *cksum = __rte_raw_cksum_reduce(sum); 300 | return 0; 301 | } 302 | 303 | /** 304 | * Process the IPv4 checksum of an IPv4 header. 305 | * 306 | * The checksum field must be set to 0 by the caller. 307 | * 308 | * @param ipv4_hdr 309 | * The pointer to the contiguous IPv4 header. 310 | * @return 311 | * The complemented checksum to set in the IP packet. 312 | */ 313 | static inline uint16_t 314 | rte_ipv4_cksum(const struct ipv4_hdr *ipv4_hdr) 315 | { 316 | uint16_t cksum; 317 | cksum = rte_raw_cksum(ipv4_hdr, sizeof(struct ipv4_hdr)); 318 | return (cksum == 0xffff) ? cksum : ~cksum; 319 | } 320 | 321 | /** 322 | * Process the pseudo-header checksum of an IPv4 header. 323 | * 324 | * The checksum field must be set to 0 by the caller. 325 | * 326 | * Depending on the ol_flags, the pseudo-header checksum expected by the 327 | * drivers is not the same. For instance, when TSO is enabled, the IP 328 | * payload length must not be included in the packet. 329 | * 330 | * When ol_flags is 0, it computes the standard pseudo-header checksum. 331 | * 332 | * @param ipv4_hdr 333 | * The pointer to the contiguous IPv4 header. 334 | * @param ol_flags 335 | * The ol_flags of the associated mbuf. 336 | * @return 337 | * The non-complemented checksum to set in the L4 header. 338 | */ 339 | static inline uint16_t 340 | rte_ipv4_phdr_cksum(const struct ipv4_hdr *ipv4_hdr, uint64_t ol_flags) 341 | { 342 | struct ipv4_psd_header { 343 | uint32_t src_addr; /* IP address of source host. */ 344 | uint32_t dst_addr; /* IP address of destination host. */ 345 | uint8_t zero; /* zero. */ 346 | uint8_t proto; /* L4 protocol type. */ 347 | uint16_t len; /* L4 length. */ 348 | } psd_hdr; 349 | 350 | psd_hdr.src_addr = ipv4_hdr->src_addr; 351 | psd_hdr.dst_addr = ipv4_hdr->dst_addr; 352 | psd_hdr.zero = 0; 353 | psd_hdr.proto = ipv4_hdr->next_proto_id; 354 | if (ol_flags & PKT_TX_TCP_SEG) { 355 | psd_hdr.len = 0; 356 | } else { 357 | psd_hdr.len = rte_cpu_to_be_16( 358 | (uint16_t)(rte_be_to_cpu_16(ipv4_hdr->total_length) 359 | - sizeof(struct ipv4_hdr))); 360 | } 361 | return rte_raw_cksum(&psd_hdr, sizeof(psd_hdr)); 362 | } 363 | 364 | /** 365 | * Process the IPv4 UDP or TCP checksum. 366 | * 367 | * The IPv4 header should not contains options. The IP and layer 4 368 | * checksum must be set to 0 in the packet by the caller. 369 | * 370 | * @param ipv4_hdr 371 | * The pointer to the contiguous IPv4 header. 372 | * @param l4_hdr 373 | * The pointer to the beginning of the L4 header. 374 | * @return 375 | * The complemented checksum to set in the IP packet. 376 | */ 377 | static inline uint16_t 378 | rte_ipv4_udptcp_cksum(const struct ipv4_hdr *ipv4_hdr, const void *l4_hdr) 379 | { 380 | uint32_t cksum; 381 | uint32_t l4_len; 382 | 383 | l4_len = rte_be_to_cpu_16(ipv4_hdr->total_length) - 384 | sizeof(struct ipv4_hdr); 385 | 386 | cksum = rte_raw_cksum(l4_hdr, l4_len); 387 | cksum += rte_ipv4_phdr_cksum(ipv4_hdr, 0); 388 | 389 | cksum = ((cksum & 0xffff0000) >> 16) + (cksum & 0xffff); 390 | cksum = (~cksum) & 0xffff; 391 | if (cksum == 0) 392 | cksum = 0xffff; 393 | 394 | return cksum; 395 | } 396 | 397 | /** 398 | * IPv6 Header 399 | */ 400 | struct ipv6_hdr { 401 | uint32_t vtc_flow; /**< IP version, traffic class & flow label. */ 402 | uint16_t payload_len; /**< IP packet length - includes sizeof(ip_header). */ 403 | uint8_t proto; /**< Protocol, next header. */ 404 | uint8_t hop_limits; /**< Hop limits. */ 405 | uint8_t src_addr[16]; /**< IP address of source host. */ 406 | uint8_t dst_addr[16]; /**< IP address of destination host(s). */ 407 | } __attribute__((__packed__)); 408 | 409 | /** 410 | * Process the pseudo-header checksum of an IPv6 header. 411 | * 412 | * Depending on the ol_flags, the pseudo-header checksum expected by the 413 | * drivers is not the same. For instance, when TSO is enabled, the IPv6 414 | * payload length must not be included in the packet. 415 | * 416 | * When ol_flags is 0, it computes the standard pseudo-header checksum. 417 | * 418 | * @param ipv6_hdr 419 | * The pointer to the contiguous IPv6 header. 420 | * @param ol_flags 421 | * The ol_flags of the associated mbuf. 422 | * @return 423 | * The non-complemented checksum to set in the L4 header. 424 | */ 425 | static inline uint16_t 426 | rte_ipv6_phdr_cksum(const struct ipv6_hdr *ipv6_hdr, uint64_t ol_flags) 427 | { 428 | uint32_t sum; 429 | struct { 430 | uint32_t len; /* L4 length. */ 431 | uint32_t proto; /* L4 protocol - top 3 bytes must be zero */ 432 | } psd_hdr; 433 | 434 | psd_hdr.proto = (ipv6_hdr->proto << 24); 435 | if (ol_flags & PKT_TX_TCP_SEG) { 436 | psd_hdr.len = 0; 437 | } else { 438 | psd_hdr.len = ipv6_hdr->payload_len; 439 | } 440 | 441 | sum = __rte_raw_cksum(ipv6_hdr->src_addr, 442 | sizeof(ipv6_hdr->src_addr) + sizeof(ipv6_hdr->dst_addr), 443 | 0); 444 | sum = __rte_raw_cksum(&psd_hdr, sizeof(psd_hdr), sum); 445 | return __rte_raw_cksum_reduce(sum); 446 | } 447 | 448 | /** 449 | * Process the IPv6 UDP or TCP checksum. 450 | * 451 | * The IPv4 header should not contains options. The layer 4 checksum 452 | * must be set to 0 in the packet by the caller. 453 | * 454 | * @param ipv6_hdr 455 | * The pointer to the contiguous IPv6 header. 456 | * @param l4_hdr 457 | * The pointer to the beginning of the L4 header. 458 | * @return 459 | * The complemented checksum to set in the IP packet. 460 | */ 461 | static inline uint16_t 462 | rte_ipv6_udptcp_cksum(const struct ipv6_hdr *ipv6_hdr, const void *l4_hdr) 463 | { 464 | uint32_t cksum; 465 | uint32_t l4_len; 466 | 467 | l4_len = rte_be_to_cpu_16(ipv6_hdr->payload_len); 468 | 469 | cksum = rte_raw_cksum(l4_hdr, l4_len); 470 | cksum += rte_ipv6_phdr_cksum(ipv6_hdr, 0); 471 | 472 | cksum = ((cksum & 0xffff0000) >> 16) + (cksum & 0xffff); 473 | cksum = (~cksum) & 0xffff; 474 | if (cksum == 0) 475 | cksum = 0xffff; 476 | 477 | return cksum; 478 | } 479 | 480 | #ifdef __cplusplus 481 | } 482 | #endif 483 | 484 | #endif /* _RTE_IP_H_ */ 485 | -------------------------------------------------------------------------------- /librte_net/rte_mbuf_ptype.h: -------------------------------------------------------------------------------- 1 | /*- 2 | * BSD LICENSE 3 | * 4 | * Copyright(c) 2010-2016 Intel Corporation. 5 | * Copyright 2014-2016 6WIND S.A. 6 | * All rights reserved. 7 | * 8 | * Redistribution and use in source and binary forms, with or without 9 | * modification, are permitted provided that the following conditions 10 | * are met: 11 | * 12 | * * Redistributions of source code must retain the above copyright 13 | * notice, this list of conditions and the following disclaimer. 14 | * * Redistributions in binary form must reproduce the above copyright 15 | * notice, this list of conditions and the following disclaimer in 16 | * the documentation and/or other materials provided with the 17 | * distribution. 18 | * * Neither the name of Intel Corporation nor the names of its 19 | * contributors may be used to endorse or promote products derived 20 | * from this software without specific prior written permission. 21 | * 22 | * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 23 | * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 24 | * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR 25 | * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 26 | * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 27 | * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 28 | * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 29 | * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 30 | * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 31 | * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 32 | * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 33 | */ 34 | 35 | #ifndef _RTE_MBUF_PTYPE_H_ 36 | #define _RTE_MBUF_PTYPE_H_ 37 | 38 | /** 39 | * @file 40 | * RTE Mbuf Packet Types 41 | * 42 | * This file contains declarations for features related to mbuf packet 43 | * types. The packet type gives information about the data carried by the 44 | * mbuf, and is stored in the mbuf in a 32 bits field. 45 | * 46 | * The 32 bits are divided into several fields to mark packet types. Note that 47 | * each field is indexical. 48 | * - Bit 3:0 is for L2 types. 49 | * - Bit 7:4 is for L3 or outer L3 (for tunneling case) types. 50 | * - Bit 11:8 is for L4 or outer L4 (for tunneling case) types. 51 | * - Bit 15:12 is for tunnel types. 52 | * - Bit 19:16 is for inner L2 types. 53 | * - Bit 23:20 is for inner L3 types. 54 | * - Bit 27:24 is for inner L4 types. 55 | * - Bit 31:28 is reserved. 56 | * 57 | * To be compatible with Vector PMD, RTE_PTYPE_L3_IPV4, RTE_PTYPE_L3_IPV4_EXT, 58 | * RTE_PTYPE_L3_IPV6, RTE_PTYPE_L3_IPV6_EXT, RTE_PTYPE_L4_TCP, RTE_PTYPE_L4_UDP 59 | * and RTE_PTYPE_L4_SCTP should be kept as below in a contiguous 7 bits. 60 | * 61 | * Note that L3 types values are selected for checking IPV4/IPV6 header from 62 | * performance point of view. Reading annotations of RTE_ETH_IS_IPV4_HDR and 63 | * RTE_ETH_IS_IPV6_HDR is needed for any future changes of L3 type values. 64 | * 65 | * Note that the packet types of the same packet recognized by different 66 | * hardware may be different, as different hardware may have different 67 | * capability of packet type recognition. 68 | * 69 | * examples: 70 | * <'ether type'=0x0800 71 | * | 'version'=4, 'protocol'=0x29 72 | * | 'version'=6, 'next header'=0x3A 73 | * | 'ICMPv6 header'> 74 | * will be recognized on i40e hardware as packet type combination of, 75 | * RTE_PTYPE_L2_ETHER | 76 | * RTE_PTYPE_L3_IPV4_EXT_UNKNOWN | 77 | * RTE_PTYPE_TUNNEL_IP | 78 | * RTE_PTYPE_INNER_L3_IPV6_EXT_UNKNOWN | 79 | * RTE_PTYPE_INNER_L4_ICMP. 80 | * 81 | * <'ether type'=0x86DD 82 | * | 'version'=6, 'next header'=0x2F 83 | * | 'GRE header' 84 | * | 'version'=6, 'next header'=0x11 85 | * | 'UDP header'> 86 | * will be recognized on i40e hardware as packet type combination of, 87 | * RTE_PTYPE_L2_ETHER | 88 | * RTE_PTYPE_L3_IPV6_EXT_UNKNOWN | 89 | * RTE_PTYPE_TUNNEL_GRENAT | 90 | * RTE_PTYPE_INNER_L3_IPV6_EXT_UNKNOWN | 91 | * RTE_PTYPE_INNER_L4_UDP. 92 | */ 93 | 94 | #include 95 | #include 96 | 97 | #ifdef __cplusplus 98 | extern "C" { 99 | #endif 100 | 101 | /** 102 | * No packet type information. 103 | */ 104 | #define RTE_PTYPE_UNKNOWN 0x00000000 105 | /** 106 | * Ethernet packet type. 107 | * It is used for outer packet for tunneling cases. 108 | * 109 | * Packet format: 110 | * <'ether type'=[0x0800|0x86DD]> 111 | */ 112 | #define RTE_PTYPE_L2_ETHER 0x00000001 113 | /** 114 | * Ethernet packet type for time sync. 115 | * 116 | * Packet format: 117 | * <'ether type'=0x88F7> 118 | */ 119 | #define RTE_PTYPE_L2_ETHER_TIMESYNC 0x00000002 120 | /** 121 | * ARP (Address Resolution Protocol) packet type. 122 | * 123 | * Packet format: 124 | * <'ether type'=0x0806> 125 | */ 126 | #define RTE_PTYPE_L2_ETHER_ARP 0x00000003 127 | /** 128 | * LLDP (Link Layer Discovery Protocol) packet type. 129 | * 130 | * Packet format: 131 | * <'ether type'=0x88CC> 132 | */ 133 | #define RTE_PTYPE_L2_ETHER_LLDP 0x00000004 134 | /** 135 | * NSH (Network Service Header) packet type. 136 | * 137 | * Packet format: 138 | * <'ether type'=0x894F> 139 | */ 140 | #define RTE_PTYPE_L2_ETHER_NSH 0x00000005 141 | /** 142 | * VLAN packet type. 143 | * 144 | * Packet format: 145 | * <'ether type'=[0x8100]> 146 | */ 147 | #define RTE_PTYPE_L2_ETHER_VLAN 0x00000006 148 | /** 149 | * QinQ packet type. 150 | * 151 | * Packet format: 152 | * <'ether type'=[0x88A8]> 153 | */ 154 | #define RTE_PTYPE_L2_ETHER_QINQ 0x00000007 155 | /** 156 | * Mask of layer 2 packet types. 157 | * It is used for outer packet for tunneling cases. 158 | */ 159 | #define RTE_PTYPE_L2_MASK 0x0000000f 160 | /** 161 | * IP (Internet Protocol) version 4 packet type. 162 | * It is used for outer packet for tunneling cases, and does not contain any 163 | * header option. 164 | * 165 | * Packet format: 166 | * <'ether type'=0x0800 167 | * | 'version'=4, 'ihl'=5> 168 | */ 169 | #define RTE_PTYPE_L3_IPV4 0x00000010 170 | /** 171 | * IP (Internet Protocol) version 4 packet type. 172 | * It is used for outer packet for tunneling cases, and contains header 173 | * options. 174 | * 175 | * Packet format: 176 | * <'ether type'=0x0800 177 | * | 'version'=4, 'ihl'=[6-15], 'options'> 178 | */ 179 | #define RTE_PTYPE_L3_IPV4_EXT 0x00000030 180 | /** 181 | * IP (Internet Protocol) version 6 packet type. 182 | * It is used for outer packet for tunneling cases, and does not contain any 183 | * extension header. 184 | * 185 | * Packet format: 186 | * <'ether type'=0x86DD 187 | * | 'version'=6, 'next header'=0x3B> 188 | */ 189 | #define RTE_PTYPE_L3_IPV6 0x00000040 190 | /** 191 | * IP (Internet Protocol) version 4 packet type. 192 | * It is used for outer packet for tunneling cases, and may or maynot contain 193 | * header options. 194 | * 195 | * Packet format: 196 | * <'ether type'=0x0800 197 | * | 'version'=4, 'ihl'=[5-15], <'options'>> 198 | */ 199 | #define RTE_PTYPE_L3_IPV4_EXT_UNKNOWN 0x00000090 200 | /** 201 | * IP (Internet Protocol) version 6 packet type. 202 | * It is used for outer packet for tunneling cases, and contains extension 203 | * headers. 204 | * 205 | * Packet format: 206 | * <'ether type'=0x86DD 207 | * | 'version'=6, 'next header'=[0x0|0x2B|0x2C|0x32|0x33|0x3C|0x87], 208 | * 'extension headers'> 209 | */ 210 | #define RTE_PTYPE_L3_IPV6_EXT 0x000000c0 211 | /** 212 | * IP (Internet Protocol) version 6 packet type. 213 | * It is used for outer packet for tunneling cases, and may or maynot contain 214 | * extension headers. 215 | * 216 | * Packet format: 217 | * <'ether type'=0x86DD 218 | * | 'version'=6, 'next header'=[0x3B|0x0|0x2B|0x2C|0x32|0x33|0x3C|0x87], 219 | * <'extension headers'>> 220 | */ 221 | #define RTE_PTYPE_L3_IPV6_EXT_UNKNOWN 0x000000e0 222 | /** 223 | * Mask of layer 3 packet types. 224 | * It is used for outer packet for tunneling cases. 225 | */ 226 | #define RTE_PTYPE_L3_MASK 0x000000f0 227 | /** 228 | * TCP (Transmission Control Protocol) packet type. 229 | * It is used for outer packet for tunneling cases. 230 | * 231 | * Packet format: 232 | * <'ether type'=0x0800 233 | * | 'version'=4, 'protocol'=6, 'MF'=0, 'frag_offset'=0> 234 | * or, 235 | * <'ether type'=0x86DD 236 | * | 'version'=6, 'next header'=6> 237 | */ 238 | #define RTE_PTYPE_L4_TCP 0x00000100 239 | /** 240 | * UDP (User Datagram Protocol) packet type. 241 | * It is used for outer packet for tunneling cases. 242 | * 243 | * Packet format: 244 | * <'ether type'=0x0800 245 | * | 'version'=4, 'protocol'=17, 'MF'=0, 'frag_offset'=0> 246 | * or, 247 | * <'ether type'=0x86DD 248 | * | 'version'=6, 'next header'=17> 249 | */ 250 | #define RTE_PTYPE_L4_UDP 0x00000200 251 | /** 252 | * Fragmented IP (Internet Protocol) packet type. 253 | * It is used for outer packet for tunneling cases. 254 | * 255 | * It refers to those packets of any IP types, which can be recognized as 256 | * fragmented. A fragmented packet cannot be recognized as any other L4 types 257 | * (RTE_PTYPE_L4_TCP, RTE_PTYPE_L4_UDP, RTE_PTYPE_L4_SCTP, RTE_PTYPE_L4_ICMP, 258 | * RTE_PTYPE_L4_NONFRAG). 259 | * 260 | * Packet format: 261 | * <'ether type'=0x0800 262 | * | 'version'=4, 'MF'=1> 263 | * or, 264 | * <'ether type'=0x0800 265 | * | 'version'=4, 'frag_offset'!=0> 266 | * or, 267 | * <'ether type'=0x86DD 268 | * | 'version'=6, 'next header'=44> 269 | */ 270 | #define RTE_PTYPE_L4_FRAG 0x00000300 271 | /** 272 | * SCTP (Stream Control Transmission Protocol) packet type. 273 | * It is used for outer packet for tunneling cases. 274 | * 275 | * Packet format: 276 | * <'ether type'=0x0800 277 | * | 'version'=4, 'protocol'=132, 'MF'=0, 'frag_offset'=0> 278 | * or, 279 | * <'ether type'=0x86DD 280 | * | 'version'=6, 'next header'=132> 281 | */ 282 | #define RTE_PTYPE_L4_SCTP 0x00000400 283 | /** 284 | * ICMP (Internet Control Message Protocol) packet type. 285 | * It is used for outer packet for tunneling cases. 286 | * 287 | * Packet format: 288 | * <'ether type'=0x0800 289 | * | 'version'=4, 'protocol'=1, 'MF'=0, 'frag_offset'=0> 290 | * or, 291 | * <'ether type'=0x86DD 292 | * | 'version'=6, 'next header'=1> 293 | */ 294 | #define RTE_PTYPE_L4_ICMP 0x00000500 295 | /** 296 | * Non-fragmented IP (Internet Protocol) packet type. 297 | * It is used for outer packet for tunneling cases. 298 | * 299 | * It refers to those packets of any IP types, while cannot be recognized as 300 | * any of above L4 types (RTE_PTYPE_L4_TCP, RTE_PTYPE_L4_UDP, 301 | * RTE_PTYPE_L4_FRAG, RTE_PTYPE_L4_SCTP, RTE_PTYPE_L4_ICMP). 302 | * 303 | * Packet format: 304 | * <'ether type'=0x0800 305 | * | 'version'=4, 'protocol'!=[6|17|132|1], 'MF'=0, 'frag_offset'=0> 306 | * or, 307 | * <'ether type'=0x86DD 308 | * | 'version'=6, 'next header'!=[6|17|44|132|1]> 309 | */ 310 | #define RTE_PTYPE_L4_NONFRAG 0x00000600 311 | /* BEGIN: Added by zc, 2018/8/23 */ 312 | #define RTE_PTYPE_L4_ICMP6 0x00000700 313 | #define RTE_PTYPE_L4_IGMP 0x00000800 314 | #define RTE_PTYPE_L4_UDPLITE 0x00000900 315 | /* END: Added by zc, 2018/8/23 */ 316 | /** 317 | * Mask of layer 4 packet types. 318 | * It is used for outer packet for tunneling cases. 319 | */ 320 | #define RTE_PTYPE_L4_MASK 0x00000f00 321 | /** 322 | * IP (Internet Protocol) in IP (Internet Protocol) tunneling packet type. 323 | * 324 | * Packet format: 325 | * <'ether type'=0x0800 326 | * | 'version'=4, 'protocol'=[4|41]> 327 | * or, 328 | * <'ether type'=0x86DD 329 | * | 'version'=6, 'next header'=[4|41]> 330 | */ 331 | #define RTE_PTYPE_TUNNEL_IP 0x00001000 332 | /** 333 | * GRE (Generic Routing Encapsulation) tunneling packet type. 334 | * 335 | * Packet format: 336 | * <'ether type'=0x0800 337 | * | 'version'=4, 'protocol'=47> 338 | * or, 339 | * <'ether type'=0x86DD 340 | * | 'version'=6, 'next header'=47> 341 | */ 342 | #define RTE_PTYPE_TUNNEL_GRE 0x00002000 343 | /** 344 | * VXLAN (Virtual eXtensible Local Area Network) tunneling packet type. 345 | * 346 | * Packet format: 347 | * <'ether type'=0x0800 348 | * | 'version'=4, 'protocol'=17 349 | * | 'destination port'=4789> 350 | * or, 351 | * <'ether type'=0x86DD 352 | * | 'version'=6, 'next header'=17 353 | * | 'destination port'=4789> 354 | */ 355 | #define RTE_PTYPE_TUNNEL_VXLAN 0x00003000 356 | /** 357 | * NVGRE (Network Virtualization using Generic Routing Encapsulation) tunneling 358 | * packet type. 359 | * 360 | * Packet format: 361 | * <'ether type'=0x0800 362 | * | 'version'=4, 'protocol'=47 363 | * | 'protocol type'=0x6558> 364 | * or, 365 | * <'ether type'=0x86DD 366 | * | 'version'=6, 'next header'=47 367 | * | 'protocol type'=0x6558'> 368 | */ 369 | #define RTE_PTYPE_TUNNEL_NVGRE 0x00004000 370 | /** 371 | * GENEVE (Generic Network Virtualization Encapsulation) tunneling packet type. 372 | * 373 | * Packet format: 374 | * <'ether type'=0x0800 375 | * | 'version'=4, 'protocol'=17 376 | * | 'destination port'=6081> 377 | * or, 378 | * <'ether type'=0x86DD 379 | * | 'version'=6, 'next header'=17 380 | * | 'destination port'=6081> 381 | */ 382 | #define RTE_PTYPE_TUNNEL_GENEVE 0x00005000 383 | /** 384 | * Tunneling packet type of Teredo, VXLAN (Virtual eXtensible Local Area 385 | * Network) or GRE (Generic Routing Encapsulation) could be recognized as this 386 | * packet type, if they can not be recognized independently as of hardware 387 | * capability. 388 | */ 389 | #define RTE_PTYPE_TUNNEL_GRENAT 0x00006000 390 | /** 391 | * GTP-C (GPRS Tunnelling Protocol) control tunneling packet type. 392 | * Packet format: 393 | * <'ether type'=0x0800 394 | * | 'version'=4, 'protocol'=17 395 | * | 'destination port'=2123> 396 | * or, 397 | * <'ether type'=0x86DD 398 | * | 'version'=6, 'next header'=17 399 | * | 'destination port'=2123> 400 | * or, 401 | * <'ether type'=0x0800 402 | * | 'version'=4, 'protocol'=17 403 | * | 'source port'=2123> 404 | * or, 405 | * <'ether type'=0x86DD 406 | * | 'version'=6, 'next header'=17 407 | * | 'source port'=2123> 408 | */ 409 | #define RTE_PTYPE_TUNNEL_GTPC 0x00007000 410 | /** 411 | * GTP-U (GPRS Tunnelling Protocol) user data tunneling packet type. 412 | * Packet format: 413 | * <'ether type'=0x0800 414 | * | 'version'=4, 'protocol'=17 415 | * | 'destination port'=2152> 416 | * or, 417 | * <'ether type'=0x86DD 418 | * | 'version'=6, 'next header'=17 419 | * | 'destination port'=2152> 420 | */ 421 | #define RTE_PTYPE_TUNNEL_GTPU 0x00008000 422 | /** 423 | * ESP (IP Encapsulating Security Payload) tunneling packet type. 424 | * 425 | * Packet format: 426 | * <'ether type'=0x0800 427 | * | 'version'=4, 'protocol'=51> 428 | * or, 429 | * <'ether type'=0x86DD 430 | * | 'version'=6, 'next header'=51> 431 | */ 432 | #define RTE_PTYPE_TUNNEL_ESP 0x00009000 433 | /** 434 | * Mask of tunneling packet types. 435 | */ 436 | #define RTE_PTYPE_TUNNEL_MASK 0x0000f000 437 | /** 438 | * Ethernet packet type. 439 | * It is used for inner packet type only. 440 | * 441 | * Packet format (inner only): 442 | * <'ether type'=[0x800|0x86DD]> 443 | */ 444 | #define RTE_PTYPE_INNER_L2_ETHER 0x00010000 445 | /** 446 | * Ethernet packet type with VLAN (Virtual Local Area Network) tag. 447 | * 448 | * Packet format (inner only): 449 | * <'ether type'=[0x800|0x86DD], vlan=[1-4095]> 450 | */ 451 | #define RTE_PTYPE_INNER_L2_ETHER_VLAN 0x00020000 452 | /** 453 | * QinQ packet type. 454 | * 455 | * Packet format: 456 | * <'ether type'=[0x88A8]> 457 | */ 458 | #define RTE_PTYPE_INNER_L2_ETHER_QINQ 0x00030000 459 | /** 460 | * Mask of inner layer 2 packet types. 461 | */ 462 | #define RTE_PTYPE_INNER_L2_MASK 0x000f0000 463 | /** 464 | * IP (Internet Protocol) version 4 packet type. 465 | * It is used for inner packet only, and does not contain any header option. 466 | * 467 | * Packet format (inner only): 468 | * <'ether type'=0x0800 469 | * | 'version'=4, 'ihl'=5> 470 | */ 471 | #define RTE_PTYPE_INNER_L3_IPV4 0x00100000 472 | /** 473 | * IP (Internet Protocol) version 4 packet type. 474 | * It is used for inner packet only, and contains header options. 475 | * 476 | * Packet format (inner only): 477 | * <'ether type'=0x0800 478 | * | 'version'=4, 'ihl'=[6-15], 'options'> 479 | */ 480 | #define RTE_PTYPE_INNER_L3_IPV4_EXT 0x00200000 481 | /** 482 | * IP (Internet Protocol) version 6 packet type. 483 | * It is used for inner packet only, and does not contain any extension header. 484 | * 485 | * Packet format (inner only): 486 | * <'ether type'=0x86DD 487 | * | 'version'=6, 'next header'=0x3B> 488 | */ 489 | #define RTE_PTYPE_INNER_L3_IPV6 0x00300000 490 | /** 491 | * IP (Internet Protocol) version 4 packet type. 492 | * It is used for inner packet only, and may or maynot contain header options. 493 | * 494 | * Packet format (inner only): 495 | * <'ether type'=0x0800 496 | * | 'version'=4, 'ihl'=[5-15], <'options'>> 497 | */ 498 | #define RTE_PTYPE_INNER_L3_IPV4_EXT_UNKNOWN 0x00400000 499 | /** 500 | * IP (Internet Protocol) version 6 packet type. 501 | * It is used for inner packet only, and contains extension headers. 502 | * 503 | * Packet format (inner only): 504 | * <'ether type'=0x86DD 505 | * | 'version'=6, 'next header'=[0x0|0x2B|0x2C|0x32|0x33|0x3C|0x87], 506 | * 'extension headers'> 507 | */ 508 | #define RTE_PTYPE_INNER_L3_IPV6_EXT 0x00500000 509 | /** 510 | * IP (Internet Protocol) version 6 packet type. 511 | * It is used for inner packet only, and may or maynot contain extension 512 | * headers. 513 | * 514 | * Packet format (inner only): 515 | * <'ether type'=0x86DD 516 | * | 'version'=6, 'next header'=[0x3B|0x0|0x2B|0x2C|0x32|0x33|0x3C|0x87], 517 | * <'extension headers'>> 518 | */ 519 | #define RTE_PTYPE_INNER_L3_IPV6_EXT_UNKNOWN 0x00600000 520 | /** 521 | * Mask of inner layer 3 packet types. 522 | */ 523 | #define RTE_PTYPE_INNER_L3_MASK 0x00f00000 524 | /** 525 | * TCP (Transmission Control Protocol) packet type. 526 | * It is used for inner packet only. 527 | * 528 | * Packet format (inner only): 529 | * <'ether type'=0x0800 530 | * | 'version'=4, 'protocol'=6, 'MF'=0, 'frag_offset'=0> 531 | * or, 532 | * <'ether type'=0x86DD 533 | * | 'version'=6, 'next header'=6> 534 | */ 535 | #define RTE_PTYPE_INNER_L4_TCP 0x01000000 536 | /** 537 | * UDP (User Datagram Protocol) packet type. 538 | * It is used for inner packet only. 539 | * 540 | * Packet format (inner only): 541 | * <'ether type'=0x0800 542 | * | 'version'=4, 'protocol'=17, 'MF'=0, 'frag_offset'=0> 543 | * or, 544 | * <'ether type'=0x86DD 545 | * | 'version'=6, 'next header'=17> 546 | */ 547 | #define RTE_PTYPE_INNER_L4_UDP 0x02000000 548 | /** 549 | * Fragmented IP (Internet Protocol) packet type. 550 | * It is used for inner packet only, and may or maynot have layer 4 packet. 551 | * 552 | * Packet format (inner only): 553 | * <'ether type'=0x0800 554 | * | 'version'=4, 'MF'=1> 555 | * or, 556 | * <'ether type'=0x0800 557 | * | 'version'=4, 'frag_offset'!=0> 558 | * or, 559 | * <'ether type'=0x86DD 560 | * | 'version'=6, 'next header'=44> 561 | */ 562 | #define RTE_PTYPE_INNER_L4_FRAG 0x03000000 563 | /** 564 | * SCTP (Stream Control Transmission Protocol) packet type. 565 | * It is used for inner packet only. 566 | * 567 | * Packet format (inner only): 568 | * <'ether type'=0x0800 569 | * | 'version'=4, 'protocol'=132, 'MF'=0, 'frag_offset'=0> 570 | * or, 571 | * <'ether type'=0x86DD 572 | * | 'version'=6, 'next header'=132> 573 | */ 574 | #define RTE_PTYPE_INNER_L4_SCTP 0x04000000 575 | /** 576 | * ICMP (Internet Control Message Protocol) packet type. 577 | * It is used for inner packet only. 578 | * 579 | * Packet format (inner only): 580 | * <'ether type'=0x0800 581 | * | 'version'=4, 'protocol'=1, 'MF'=0, 'frag_offset'=0> 582 | * or, 583 | * <'ether type'=0x86DD 584 | * | 'version'=6, 'next header'=1> 585 | */ 586 | #define RTE_PTYPE_INNER_L4_ICMP 0x05000000 587 | /** 588 | * Non-fragmented IP (Internet Protocol) packet type. 589 | * It is used for inner packet only, and may or maynot have other unknown layer 590 | * 4 packet types. 591 | * 592 | * Packet format (inner only): 593 | * <'ether type'=0x0800 594 | * | 'version'=4, 'protocol'!=[6|17|132|1], 'MF'=0, 'frag_offset'=0> 595 | * or, 596 | * <'ether type'=0x86DD 597 | * | 'version'=6, 'next header'!=[6|17|44|132|1]> 598 | */ 599 | #define RTE_PTYPE_INNER_L4_NONFRAG 0x06000000 600 | /* BEGIN: Added by zc, 2018/8/24 */ 601 | #define RTE_PTYPE_INNER_L4_ICMP6 0x07000000 602 | #define RTE_PTYPE_INNER_L4_IGMP 0x08000000 603 | #define RTE_PTYPE_INNER_L4_UDPLITE 0x09000000 604 | /* END: Added by zc, 2018/8/24 */ 605 | /** 606 | * Mask of inner layer 4 packet types. 607 | */ 608 | #define RTE_PTYPE_INNER_L4_MASK 0x0f000000 609 | /** 610 | * All valid layer masks. 611 | */ 612 | #define RTE_PTYPE_ALL_MASK 0x0fffffff 613 | 614 | /** 615 | * Check if the (outer) L3 header is IPv4. To avoid comparing IPv4 types one by 616 | * one, bit 4 is selected to be used for IPv4 only. Then checking bit 4 can 617 | * determine if it is an IPV4 packet. 618 | */ 619 | #define RTE_ETH_IS_IPV4_HDR(ptype) ((ptype) & RTE_PTYPE_L3_IPV4) 620 | 621 | /** 622 | * Check if the (outer) L3 header is IPv4. To avoid comparing IPv4 types one by 623 | * one, bit 6 is selected to be used for IPv4 only. Then checking bit 6 can 624 | * determine if it is an IPV4 packet. 625 | */ 626 | #define RTE_ETH_IS_IPV6_HDR(ptype) ((ptype) & RTE_PTYPE_L3_IPV6) 627 | 628 | /* Check if it is a tunneling packet */ 629 | #define RTE_ETH_IS_TUNNEL_PKT(ptype) ((ptype) & \ 630 | (RTE_PTYPE_TUNNEL_MASK | \ 631 | RTE_PTYPE_INNER_L2_MASK | \ 632 | RTE_PTYPE_INNER_L3_MASK | \ 633 | RTE_PTYPE_INNER_L4_MASK)) 634 | 635 | /** 636 | * Get the name of the l2 packet type 637 | * 638 | * @param ptype 639 | * The packet type value. 640 | * @return 641 | * A non-null string describing the packet type. 642 | */ 643 | const char *rte_get_ptype_l2_name(uint32_t ptype); 644 | 645 | /** 646 | * Get the name of the l3 packet type 647 | * 648 | * @param ptype 649 | * The packet type value. 650 | * @return 651 | * A non-null string describing the packet type. 652 | */ 653 | const char *rte_get_ptype_l3_name(uint32_t ptype); 654 | 655 | /** 656 | * Get the name of the l4 packet type 657 | * 658 | * @param ptype 659 | * The packet type value. 660 | * @return 661 | * A non-null string describing the packet type. 662 | */ 663 | const char *rte_get_ptype_l4_name(uint32_t ptype); 664 | 665 | /** 666 | * Get the name of the tunnel packet type 667 | * 668 | * @param ptype 669 | * The packet type value. 670 | * @return 671 | * A non-null string describing the packet type. 672 | */ 673 | const char *rte_get_ptype_tunnel_name(uint32_t ptype); 674 | 675 | /** 676 | * Get the name of the inner_l2 packet type 677 | * 678 | * @param ptype 679 | * The packet type value. 680 | * @return 681 | * A non-null string describing the packet type. 682 | */ 683 | const char *rte_get_ptype_inner_l2_name(uint32_t ptype); 684 | 685 | /** 686 | * Get the name of the inner_l3 packet type 687 | * 688 | * @param ptype 689 | * The packet type value. 690 | * @return 691 | * A non-null string describing the packet type. 692 | */ 693 | const char *rte_get_ptype_inner_l3_name(uint32_t ptype); 694 | 695 | /** 696 | * Get the name of the inner_l4 packet type 697 | * 698 | * @param ptype 699 | * The packet type value. 700 | * @return 701 | * A non-null string describing the packet type. 702 | */ 703 | const char *rte_get_ptype_inner_l4_name(uint32_t ptype); 704 | 705 | /** 706 | * Write the packet type name into the buffer 707 | * 708 | * @param ptype 709 | * The packet type value. 710 | * @param buf 711 | * The buffer where the string is written. 712 | * @param buflen 713 | * The length of the buffer. 714 | * @return 715 | * - 0 on success 716 | * - (-1) if the buffer is too small 717 | */ 718 | int rte_get_ptype_name(uint32_t ptype, char *buf, size_t buflen); 719 | 720 | #ifdef __cplusplus 721 | } 722 | #endif 723 | 724 | #endif /* _RTE_MBUF_PTYPE_H_ */ 725 | -------------------------------------------------------------------------------- /src/ss_parser_pkt.c: -------------------------------------------------------------------------------- 1 | /****************************************************************************** 2 | 3 | 版权所有 (C), 2017-2018, xxx Co.xxx, Ltd. 4 | 5 | ****************************************************************************** 6 | 文 件 名 : ss_parser_pkt.c 7 | 版 本 号 : V1.0 8 | 作 者 : zc 9 | 生成日期 : 2018年8月21日 10 | 功能描述 : 数据包解析 11 | 修改历史 : 12 | ******************************************************************************/ 13 | #include 14 | #include 15 | #include 16 | #include 17 | #include 18 | #include 19 | #include 20 | #include 21 | #include 22 | 23 | #include "ss_parser_pkt.h" 24 | 25 | #define IPPORT_VXLAN 4789 26 | #define DEFAULT_VXLAN_PORT 4789 27 | #define DEFAULT_DNS_PORT 53 28 | 29 | #define SS_VXLAN_HF_VNI_BE rte_cpu_to_be_32(0x08000000) 30 | #define SS_TCP_HLEN(_hdr) (((_hdr)->data_off & 0xF0) >> 2) 31 | #define SS_IPV4_HLEN(_hdr) (((_hdr)->version_ihl & 0x0F) << 2) 32 | 33 | #define SS_RETURN_RES(_cond, _res) do { \ 34 | if ((_cond)) return (_res); } while (0) 35 | 36 | /***************************************************************************** 37 | 函 数 名 : ss_ptype_l4 38 | 功能描述 : 获取L4包类型 39 | 输入参数 : uint8_t proto 40 | 输出参数 : 无 41 | 返 回 值 : uint32_t 42 | 作 者 : zc 43 | 日 期 : 2018年8月23日 44 | *****************************************************************************/ 45 | static uint32_t 46 | ss_ptype_l4(uint8_t proto) 47 | { 48 | static const uint32_t ptype_l4_proto[256] = { 49 | [IPPROTO_ICMP] = RTE_PTYPE_L4_ICMP, 50 | [IPPROTO_IGMP] = RTE_PTYPE_L4_IGMP, 51 | [IPPROTO_TCP] = RTE_PTYPE_L4_TCP, 52 | [IPPROTO_UDP] = RTE_PTYPE_L4_UDP, 53 | [IPPROTO_ICMPV6] = RTE_PTYPE_L4_ICMP6, 54 | [IPPROTO_SCTP] = RTE_PTYPE_L4_SCTP, 55 | [IPPROTO_UDPLITE] = RTE_PTYPE_L4_UDPLITE, 56 | }; 57 | 58 | return ptype_l4_proto[proto]; 59 | } 60 | 61 | /***************************************************************************** 62 | 函 数 名 : ss_ptype_l3_ipv4 63 | 功能描述 : 获取L3的IPv4类型 64 | 输入参数 : uint8_t ipv_ihl 65 | 输出参数 : 无 66 | 返 回 值 : uint32_t 67 | 作 者 : zc 68 | 日 期 : 2018年8月23日 69 | *****************************************************************************/ 70 | static uint32_t 71 | ss_ptype_l3_ipv4(uint8_t ipv_ihl) 72 | { 73 | static const uint32_t ptype_l3_ip_proto_map[256] = { 74 | [0x45] = RTE_PTYPE_L3_IPV4, 75 | [0x46] = RTE_PTYPE_L3_IPV4_EXT, 76 | [0x47] = RTE_PTYPE_L3_IPV4_EXT, 77 | [0x48] = RTE_PTYPE_L3_IPV4_EXT, 78 | [0x49] = RTE_PTYPE_L3_IPV4_EXT, 79 | [0x4A] = RTE_PTYPE_L3_IPV4_EXT, 80 | [0x4B] = RTE_PTYPE_L3_IPV4_EXT, 81 | [0x4C] = RTE_PTYPE_L3_IPV4_EXT, 82 | [0x4D] = RTE_PTYPE_L3_IPV4_EXT, 83 | [0x4E] = RTE_PTYPE_L3_IPV4_EXT, 84 | [0x4F] = RTE_PTYPE_L3_IPV4_EXT, 85 | }; 86 | 87 | return ptype_l3_ip_proto_map[ipv_ihl]; 88 | } 89 | 90 | /***************************************************************************** 91 | 函 数 名 : ss_ptype_l3_ipv6 92 | 功能描述 : 获取L3的IPv6类型 93 | 输入参数 : uint8_t ip6_proto 94 | 输出参数 : 无 95 | 返 回 值 : uint32_t 96 | 作 者 : zc 97 | 日 期 : 2018年8月23日 98 | *****************************************************************************/ 99 | static uint32_t 100 | ss_ptype_l3_ipv6(uint8_t ip6_proto) 101 | { 102 | static const uint32_t ip6_ext_proto_map[256] = { 103 | [IPPROTO_HOPOPTS] = RTE_PTYPE_L3_IPV6_EXT - RTE_PTYPE_L3_IPV6, 104 | [IPPROTO_ROUTING] = RTE_PTYPE_L3_IPV6_EXT - RTE_PTYPE_L3_IPV6, 105 | [IPPROTO_FRAGMENT] = RTE_PTYPE_L3_IPV6_EXT - RTE_PTYPE_L3_IPV6, 106 | [IPPROTO_Ess] = RTE_PTYPE_L3_IPV6_EXT - RTE_PTYPE_L3_IPV6, 107 | [IPPROTO_AH] = RTE_PTYPE_L3_IPV6_EXT - RTE_PTYPE_L3_IPV6, 108 | [IPPROTO_DSTOPTS] = RTE_PTYPE_L3_IPV6_EXT - RTE_PTYPE_L3_IPV6, 109 | }; 110 | 111 | return RTE_PTYPE_L3_IPV6 + ip6_ext_proto_map[ip6_proto]; 112 | } 113 | 114 | /***************************************************************************** 115 | 函 数 名 : ss_ptype_inner_l4 116 | 功能描述 : 获取内L4包类型 117 | 输入参数 : uint8_t proto 118 | 输出参数 : 无 119 | 返 回 值 : uint32_t 120 | 作 者 : zc 121 | 日 期 : 2018年8月24日 122 | *****************************************************************************/ 123 | static uint32_t 124 | ss_ptype_inner_l4(uint8_t proto) 125 | { 126 | static const uint32_t ptype_inner_l4_proto[256] = { 127 | [IPPROTO_ICMP] = RTE_PTYPE_INNER_L4_ICMP, 128 | [IPPROTO_IGMP] = RTE_PTYPE_INNER_L4_IGMP, 129 | [IPPROTO_TCP] = RTE_PTYPE_INNER_L4_TCP, 130 | [IPPROTO_UDP] = RTE_PTYPE_INNER_L4_UDP, 131 | [IPPROTO_ICMPV6] = RTE_PTYPE_INNER_L4_ICMP6, 132 | [IPPROTO_SCTP] = RTE_PTYPE_INNER_L4_SCTP, 133 | [IPPROTO_UDPLITE] = RTE_PTYPE_INNER_L4_UDPLITE, 134 | }; 135 | 136 | return ptype_inner_l4_proto[proto]; 137 | } 138 | 139 | /***************************************************************************** 140 | 函 数 名 : ss_ptype_inner_l3_ipv4 141 | 功能描述 : 获取内L3的IPv4类型 142 | 输入参数 : uint8_t ipv_ihl 143 | 输出参数 : 无 144 | 返 回 值 : uint32_t 145 | 作 者 : zc 146 | 日 期 : 2018年8月24日 147 | *****************************************************************************/ 148 | static uint32_t 149 | ss_ptype_inner_l3_ipv4(uint8_t ipv_ihl) 150 | { 151 | static const uint32_t ptype_inner_l3_ip_proto_map[256] = { 152 | [0x45] = RTE_PTYPE_INNER_L3_IPV4, 153 | [0x46] = RTE_PTYPE_INNER_L3_IPV4_EXT, 154 | [0x47] = RTE_PTYPE_INNER_L3_IPV4_EXT, 155 | [0x48] = RTE_PTYPE_INNER_L3_IPV4_EXT, 156 | [0x49] = RTE_PTYPE_INNER_L3_IPV4_EXT, 157 | [0x4A] = RTE_PTYPE_INNER_L3_IPV4_EXT, 158 | [0x4B] = RTE_PTYPE_INNER_L3_IPV4_EXT, 159 | [0x4C] = RTE_PTYPE_INNER_L3_IPV4_EXT, 160 | [0x4D] = RTE_PTYPE_INNER_L3_IPV4_EXT, 161 | [0x4E] = RTE_PTYPE_INNER_L3_IPV4_EXT, 162 | [0x4F] = RTE_PTYPE_INNER_L3_IPV4_EXT, 163 | }; 164 | 165 | return ptype_inner_l3_ip_proto_map[ipv_ihl]; 166 | } 167 | 168 | /***************************************************************************** 169 | 函 数 名 : ss_ptype_inner_l3_ipv6 170 | 功能描述 : 获取内L3的IPv6类型 171 | 输入参数 : uint8_t ip6_proto 172 | 输出参数 : 无 173 | 返 回 值 : uint32_t 174 | 作 者 : zc 175 | 日 期 : 2018年8月24日 176 | *****************************************************************************/ 177 | static uint32_t 178 | ss_ptype_inner_l3_ipv6(uint8_t ip6_proto) 179 | { 180 | static const uint32_t ptype_inner_ip6_ext_proto_map[256] = { 181 | [IPPROTO_HOPOPTS] = RTE_PTYPE_INNER_L3_IPV6_EXT - 182 | RTE_PTYPE_INNER_L3_IPV6, 183 | [IPPROTO_ROUTING] = RTE_PTYPE_INNER_L3_IPV6_EXT - 184 | RTE_PTYPE_INNER_L3_IPV6, 185 | [IPPROTO_FRAGMENT] = RTE_PTYPE_INNER_L3_IPV6_EXT - 186 | RTE_PTYPE_INNER_L3_IPV6, 187 | [IPPROTO_Ess] = RTE_PTYPE_INNER_L3_IPV6_EXT - 188 | RTE_PTYPE_INNER_L3_IPV6, 189 | [IPPROTO_AH] = RTE_PTYPE_INNER_L3_IPV6_EXT - 190 | RTE_PTYPE_INNER_L3_IPV6, 191 | [IPPROTO_DSTOPTS] = RTE_PTYPE_INNER_L3_IPV6_EXT - 192 | RTE_PTYPE_INNER_L3_IPV6, 193 | }; 194 | 195 | return RTE_PTYPE_INNER_L3_IPV6 + 196 | ptype_inner_ip6_ext_proto_map[ip6_proto]; 197 | } 198 | 199 | /***************************************************************************** 200 | 函 数 名 : ss_ptype_tunnel 201 | 功能描述 : 获取tunnel数据类型 202 | 输入参数 : const struct rte_mbuf *m 203 | uint16_t *proto 204 | uint32_t *off 205 | 输出参数 : 无 206 | 返 回 值 : uint32_t 207 | 作 者 : zc 208 | 日 期 : 2018年8月24日 209 | *****************************************************************************/ 210 | static uint32_t 211 | ss_ptype_tunnel(const struct rte_mbuf *m, uint16_t *proto, 212 | uint32_t *off) 213 | { 214 | switch (*proto) { 215 | case IPPROTO_GRE: 216 | { 217 | static const uint8_t opt_len[16] = { 218 | [0x0] = 4, 219 | [0x1] = 8, 220 | [0x2] = 8, 221 | [0x8] = 8, 222 | [0x3] = 12, 223 | [0x9] = 12, 224 | [0xa] = 12, 225 | [0xb] = 16, 226 | }; 227 | uint16_t flags; 228 | struct gre_hdr gh_copy; 229 | const struct gre_hdr *gh; 230 | 231 | gh = rte_pktmbuf_read(m, *off, sizeof(*gh), &gh_copy); 232 | SS_RETURN_RES(unlikely(gh == NULL), 0); 233 | 234 | flags = rte_be_to_cpu_16(*(const uint16_t *)gh); 235 | flags >>= 12; 236 | SS_RETURN_RES(opt_len[flags] == 0, 0); 237 | 238 | *off += opt_len[flags]; 239 | *proto = gh->proto; 240 | if (*proto == rte_cpu_to_be_16(ETHER_TYPE_TEB)) { 241 | return RTE_PTYPE_TUNNEL_NVGRE; 242 | } else { 243 | return RTE_PTYPE_TUNNEL_GRE; 244 | } 245 | } 246 | case IPPROTO_IPIP: 247 | { 248 | *proto = rte_cpu_to_be_16(ETHER_TYPE_IPv4); 249 | return RTE_PTYPE_TUNNEL_IP; 250 | } 251 | case IPPROTO_IPV6: 252 | { 253 | *proto = rte_cpu_to_be_16(ETHER_TYPE_IPv6); 254 | return RTE_PTYPE_TUNNEL_IP; /* IP is also valid for IPv6 */ 255 | } 256 | case IPPORT_VXLAN: 257 | { 258 | struct vxlan_hdr *vxh_copy; 259 | const struct vxlan_hdr *vxh; 260 | uint32_t off_len = *off + sizeof(struct udp_hdr); 261 | 262 | vxh = rte_pktmbuf_read(m, off_len, sizeof(*vxh), &vxh_copy); 263 | SS_RETURN_RES(unlikely(vxh == NULL), 0); 264 | SS_RETURN_RES(unlikely(vxh->vx_flags != SS_VXLAN_HF_VNI_BE), 0); 265 | 266 | *off += ETHER_VXLAN_HLEN; 267 | *proto = rte_cpu_to_be_16(ETHER_TYPE_TEB); 268 | return RTE_PTYPE_TUNNEL_VXLAN; 269 | } 270 | default: 271 | return 0; 272 | } 273 | } 274 | 275 | /***************************************************************************** 276 | 函 数 名 : ss_skip_ip6_ext 277 | 功能描述 : 解析IPv6扩展头 278 | 输入参数 : const struct rte_mbuf *m 279 | uint16_t proto 280 | uint32_t *off 281 | int *frag 282 | 输出参数 : 无 283 | 返 回 值 : uint16_t 284 | 作 者 : zc 285 | 日 期 : 2018年8月23日 286 | *****************************************************************************/ 287 | static uint16_t 288 | ss_skip_ip6_ext(const struct rte_mbuf *m, uint16_t proto, 289 | uint32_t *off, int *frag) 290 | { 291 | struct ext_hdr { 292 | uint8_t next_hdr; 293 | uint8_t len; 294 | }; 295 | unsigned int i; 296 | struct ext_hdr exh_copy; 297 | const struct ext_hdr *exh; 298 | 299 | *frag = 0; 300 | 301 | #define SS_MAX_EXT_HDRS 5 302 | for (i = 0; i < SS_MAX_EXT_HDRS; i++) { 303 | switch (proto) { 304 | case IPPROTO_HOPOPTS: 305 | case IPPROTO_ROUTING: 306 | case IPPROTO_DSTOPTS: 307 | { 308 | exh = rte_pktmbuf_read(m, *off, sizeof(*exh), &exh_copy); 309 | SS_RETURN_RES(exh == NULL, 0); 310 | *off += (exh->len + 1) * 8; 311 | proto = exh->next_hdr; 312 | break; 313 | } 314 | case IPPROTO_FRAGMENT: 315 | { 316 | exh = rte_pktmbuf_read(m, *off, sizeof(*exh), &exh_copy); 317 | SS_RETURN_RES(exh == NULL, 0); 318 | *off += 8; 319 | proto = exh->next_hdr; 320 | *frag = 1; 321 | return proto; /* this is always the last ext hdr */ 322 | } 323 | case IPPROTO_NONE: 324 | return 0; 325 | default: 326 | return proto; 327 | } 328 | } 329 | 330 | return 0; 331 | } 332 | 333 | /***************************************************************************** 334 | 函 数 名 : ss_parser_pkt_inner_tcp 335 | 功能描述 : 解析内TCP数据 336 | 输入参数 : struct rte_mbuf *m 337 | uint32_t off_len 338 | 输出参数 : 无 339 | 返 回 值 : int 340 | 作 者 : zc 341 | 日 期 : 2018年8月24日 342 | *****************************************************************************/ 343 | static int 344 | ss_parser_pkt_inner_tcp(struct rte_mbuf *m, uint32_t off_len) 345 | { 346 | struct tcp_hdr th_copy; 347 | const struct tcp_hdr *th; 348 | 349 | th = rte_pktmbuf_read(m, off_len, sizeof(*th), &th_copy); 350 | SS_RETURN_RES(unlikely(th == NULL), 0); 351 | 352 | m->ss.sport = th->src_port; 353 | m->ss.dport = th->dst_port; 354 | m->ss.inner_l4_len = SS_TCP_HLEN(th); 355 | 356 | return 1; 357 | } 358 | 359 | /***************************************************************************** 360 | 函 数 名 : ss_parser_pkt_inner_sctp 361 | 功能描述 : 解析内SCTP数据 362 | 输入参数 : struct rte_mbuf *m 363 | uint32_t off_len 364 | 输出参数 : 无 365 | 返 回 值 : int 366 | 作 者 : zc 367 | 日 期 : 2018年8月24日 368 | *****************************************************************************/ 369 | static int 370 | ss_parser_pkt_inner_sctp(struct rte_mbuf *m, uint32_t off_len) 371 | { 372 | struct sctp_hdr sh_copy; 373 | const struct sctp_hdr *sh; 374 | 375 | sh = rte_pktmbuf_read(m, off_len, sizeof(*sh), &sh_copy); 376 | SS_RETURN_RES(unlikely(sh == NULL), 0); 377 | 378 | m->ss.sport = sh->src_port; 379 | m->ss.dport = sh->dst_port; 380 | m->ss.inner_l4_len = sizeof(*sh); 381 | 382 | return 1; 383 | } 384 | 385 | /***************************************************************************** 386 | 函 数 名 : ss_parser_pkt_inner_l4_proto 387 | 功能描述 : 解析内L4协议 388 | 输入参数 : struct rte_mbuf *m 389 | uint32_t off_len 390 | 输出参数 : 无 391 | 返 回 值 : int 392 | 作 者 : zc 393 | 日 期 : 2018年8月24日 394 | *****************************************************************************/ 395 | static int 396 | ss_parser_pkt_inner_l4_proto(struct rte_mbuf *m, uint32_t off_len) 397 | { 398 | int ret = 0; 399 | uint32_t type = m->ss.packet_type & RTE_PTYPE_INNER_L4_MASK; 400 | 401 | switch (type) { 402 | case RTE_PTYPE_INNER_L4_UDP: 403 | case RTE_PTYPE_INNER_L4_ICMP: 404 | case RTE_PTYPE_INNER_L4_IGMP: 405 | case RTE_PTYPE_INNER_L4_ICMP6: 406 | case RTE_PTYPE_INNER_L4_UDPLITE: 407 | { 408 | break; 409 | } 410 | case RTE_PTYPE_INNER_L4_TCP: 411 | { 412 | ret = ss_parser_pkt_inner_tcp(m, off_len); 413 | break; 414 | } 415 | case RTE_PTYPE_INNER_L4_SCTP: 416 | { 417 | ret = ss_parser_pkt_inner_sctp(m, off_len); 418 | break; 419 | } 420 | default: 421 | break; 422 | } 423 | 424 | return ret; 425 | } 426 | 427 | /***************************************************************************** 428 | 函 数 名 : ss_parser_pkt_inner_ipv4 429 | 功能描述 : 解析内IPv4数据 430 | 输入参数 : struct rte_mbuf *m 431 | uint32_t off_len 432 | 输出参数 : 无 433 | 返 回 值 : int 434 | 作 者 : zc 435 | 日 期 : 2018年8月24日 436 | *****************************************************************************/ 437 | static int 438 | ss_parser_pkt_inner_ipv4(struct rte_mbuf *m, uint32_t off_len) 439 | { 440 | int ret = 0; 441 | uint16_t proto; 442 | uint32_t off = off_len; 443 | struct ipv4_hdr ip4h_copy; 444 | const struct ipv4_hdr *ip4h; 445 | 446 | ip4h = rte_pktmbuf_read(m, off, sizeof(*ip4h), &ip4h_copy); 447 | SS_RETURN_RES(unlikely(ip4h == NULL), 0); 448 | SS_RETURN_RES(ip4h->fragment_offset & rte_cpu_to_be_16( 449 | IPV4_HDR_OFFSET_MASK | IPV4_HDR_MF_FLAG), 0); 450 | 451 | m->ss.packet_type |= ss_ptype_inner_l3_ipv4(ip4h->version_ihl); 452 | m->ss.inner_l3_len = SS_IPV4_HLEN(ip4h); 453 | m->ss.inner_sip[0] = ip4h->src_addr; 454 | m->ss.inner_dip[0] = ip4h->dst_addr; 455 | off += m->ss.inner_l3_len; 456 | proto = ip4h->next_proto_id; 457 | m->ss.packet_type |= ss_ptype_inner_l4(proto); 458 | 459 | return ss_parser_pkt_inner_l4_proto(m, off); 460 | } 461 | 462 | /***************************************************************************** 463 | 函 数 名 : ss_parser_pkt_inner_ipv6 464 | 功能描述 : 解析内IPv6数据 465 | 输入参数 : struct rte_mbuf *m 466 | uint32_t off_len 467 | 输出参数 : 无 468 | 返 回 值 : int 469 | 作 者 : zc 470 | 日 期 : 2018年8月24日 471 | *****************************************************************************/ 472 | static int 473 | ss_parser_pkt_inner_ipv6(struct rte_mbuf *m, uint32_t off_len) 474 | { 475 | int frag = 0; 476 | uint16_t proto; 477 | uint32_t off = off_len; 478 | struct ipv6_hdr ip6h_copy; 479 | const struct ipv6_hdr *ip6h; 480 | 481 | ip6h = rte_pktmbuf_read(m, off, sizeof(*ip6h), &ip6h_copy); 482 | SS_RETURN_RES(unlikely(ip6h == NULL), 0); 483 | 484 | rte_memcpy(m->ss.inner_sip, ip6h->src_addr, 16); 485 | rte_memcpy(m->ss.inner_dip, ip6h->dst_addr, 16); 486 | m->ss.inner_l3_len = sizeof(*ip6h); 487 | off += m->ss.inner_l3_len; 488 | proto = ip6h->proto; 489 | m->ss.packet_type |= ss_ptype_inner_l3_ipv6(proto); 490 | 491 | /* 解析IPv6扩展头 */ 492 | if ((m->ss.packet_type & RTE_PTYPE_L3_MASK) 493 | == RTE_PTYPE_L3_IPV6_EXT) { 494 | uint32_t prev_off = off; 495 | 496 | proto = ss_skip_ip6_ext(m, proto, &off, &frag); 497 | m->ss.inner_l3_len += off - prev_off; 498 | } 499 | SS_RETURN_RES(!proto, 0); 500 | SS_RETURN_RES(frag, 0); 501 | m->ss.packet_type |= ss_ptype_inner_l4(proto); 502 | 503 | return ss_parser_pkt_inner_l4_proto(m, off); 504 | } 505 | 506 | /***************************************************************************** 507 | 函 数 名 : ss_parser_pkt_tunnel 508 | 功能描述 : 解析tunnel数据 509 | 输入参数 : struct rte_mbuf *m 510 | uint16_t proto 511 | uint32_t off_len 512 | 输出参数 : 无 513 | 返 回 值 : int 514 | 作 者 : zc 515 | 日 期 : 2018年8月24日 516 | *****************************************************************************/ 517 | static int 518 | ss_parser_pkt_tunnel(struct rte_mbuf *m, uint16_t proto, 519 | uint32_t off_len) 520 | { 521 | int ret = 0; 522 | uint32_t packet_type; 523 | uint32_t off = off_len; 524 | uint32_t prev_off = off_len; 525 | 526 | m->ss.l4_len = 0; 527 | packet_type = ss_ptype_tunnel(m, &proto, &off); 528 | SS_RETURN_RES(unlikely(packet_type == 0), 0); 529 | m->ss.tunnel_len = off - prev_off; 530 | m->ss.packet_type |= packet_type; 531 | 532 | if (proto == rte_cpu_to_be_16(ETHER_TYPE_TEB)) { 533 | struct ether_hdr eh_copy; 534 | const struct ether_hdr *eh; 535 | 536 | eh = rte_pktmbuf_read(m, off, sizeof(*eh), &eh_copy); 537 | SS_RETURN_RES(unlikely(eh == NULL), 0); 538 | rte_memcpy(m->ss.inner_smac, eh->s_addr.addr_bytes, 539 | ETHER_ADDR_LEN); 540 | rte_memcpy(m->ss.inner_dmac, eh->d_addr.addr_bytes, 541 | ETHER_ADDR_LEN); 542 | m->ss.packet_type |= RTE_PTYPE_INNER_L2_ETHER; 543 | m->ss.inner_l2_len = sizeof(*eh); 544 | proto = eh->ether_type; 545 | off += sizeof(*eh); 546 | } 547 | 548 | if (proto == rte_cpu_to_be_16(ETHER_TYPE_VLAN)) { 549 | struct vlan_hdr vh_copy; 550 | const struct vlan_hdr *vh; 551 | 552 | m->ss.packet_type &= ~RTE_PTYPE_INNER_L2_MASK; 553 | m->ss.packet_type |= RTE_PTYPE_INNER_L2_ETHER_VLAN; 554 | vh = rte_pktmbuf_read(m, off, sizeof(*vh), &vh_copy); 555 | SS_RETURN_RES(unlikely(vh == NULL), 0); 556 | off += sizeof(*vh); 557 | m->ss.inner_l2_len += sizeof(*vh); 558 | proto = vh->eth_proto; 559 | } else if (proto == rte_cpu_to_be_16(ETHER_TYPE_QINQ)) { 560 | struct vlan_hdr vh_copy; 561 | const struct vlan_hdr *vh; 562 | 563 | m->ss.packet_type &= ~RTE_PTYPE_INNER_L2_MASK; 564 | m->ss.packet_type |= RTE_PTYPE_INNER_L2_ETHER_QINQ; 565 | vh = rte_pktmbuf_read(m, off + sizeof(*vh), sizeof(*vh), 566 | &vh_copy); 567 | SS_RETURN_RES(unlikely(vh == NULL), 0); 568 | off += 2 * sizeof(*vh); 569 | m->ss.inner_l2_len += 2 * sizeof(*vh); 570 | proto = vh->eth_proto; 571 | } 572 | 573 | switch (rte_be_to_cpu_16(proto)) { 574 | case ETHER_TYPE_IPv4: 575 | { 576 | ret = ss_parser_pkt_inner_ipv4(m, off); 577 | break; 578 | } 579 | case ETHER_TYPE_IPv6: 580 | { 581 | ret = ss_parser_pkt_inner_ipv6(m, off); 582 | break; 583 | } 584 | default: 585 | break; 586 | } 587 | 588 | return ret; 589 | } 590 | 591 | /***************************************************************************** 592 | 函 数 名 : ss_parser_pkt_udp_port 593 | 功能描述 : 根据UDP端口进行处理 594 | 输入参数 : struct rte_mbuf *m 595 | uint32_t off_len 596 | const struct udp_hdr *uh 597 | uint16_t port 598 | uint8_t *find 599 | 输出参数 : 无 600 | 返 回 值 : int 601 | 作 者 : zc 602 | 日 期 : 2018年9月15日 603 | *****************************************************************************/ 604 | static int 605 | ss_parser_pkt_udp_port(struct rte_mbuf *m, uint32_t off_len, 606 | const struct udp_hdr *uh, uint16_t port, uint8_t *find) 607 | { 608 | int ret = 0; 609 | 610 | switch (rte_be_to_cpu_16(port)) { 611 | case DEFAULT_DNS_PORT: 612 | { 613 | *find = 1; 614 | m->ss.sport = uh->src_port; 615 | m->ss.dport = uh->dst_port; 616 | m->ss.l4_len = sizeof(*uh); 617 | return 1; 618 | } 619 | case DEFAULT_VXLAN_PORT: 620 | { 621 | *find = 1; 622 | ret = ss_parser_pkt_tunnel(m, IPPORT_VXLAN, off_len); 623 | break; 624 | } 625 | default: 626 | break; 627 | } 628 | 629 | return ret; 630 | } 631 | 632 | /***************************************************************************** 633 | 函 数 名 : ss_parser_pkt_udp 634 | 功能描述 : 解析UDP数据 635 | 输入参数 : struct rte_mbuf *m 636 | uint32_t off_len 637 | 输出参数 : 无 638 | 返 回 值 : int 639 | 作 者 : zc 640 | 日 期 : 2018年9月13日 641 | *****************************************************************************/ 642 | static int 643 | ss_parser_pkt_udp(struct rte_mbuf *m, uint32_t off_len) 644 | { 645 | int ret = 0; 646 | uint8_t find = 0; 647 | struct udp_hdr *uh_copy; 648 | const struct udp_hdr *uh; 649 | 650 | uh = rte_pktmbuf_read(m, off_len, sizeof(*uh), &uh_copy); 651 | SS_RETURN_RES(unlikely(uh == NULL), 0); 652 | 653 | ret = ss_parser_pkt_udp_port(m, off_len, uh, uh->dst_port, &find); 654 | SS_RETURN_RES(find, ret); 655 | ret = ss_parser_pkt_udp_port(m, off_len, uh, uh->src_port, &find); 656 | 657 | return ret; 658 | } 659 | 660 | /***************************************************************************** 661 | 函 数 名 : ss_parser_pkt_tcp 662 | 功能描述 : 解析TCP数据 663 | 输入参数 : struct rte_mbuf *m 664 | uint32_t off_len 665 | 输出参数 : 无 666 | 返 回 值 : int 667 | 作 者 : zc 668 | 日 期 : 2018年8月22日 669 | *****************************************************************************/ 670 | static int 671 | ss_parser_pkt_tcp(struct rte_mbuf *m, uint32_t off_len) 672 | { 673 | struct tcp_hdr th_copy; 674 | const struct tcp_hdr *th; 675 | 676 | th = rte_pktmbuf_read(m, off_len, sizeof(*th), &th_copy); 677 | SS_RETURN_RES(unlikely(th == NULL), 0); 678 | 679 | m->ss.sport = th->src_port; 680 | m->ss.dport = th->dst_port; 681 | m->ss.l4_len = SS_TCP_HLEN(th); 682 | 683 | return 1; 684 | } 685 | 686 | /***************************************************************************** 687 | 函 数 名 : ss_parser_pkt_sctp 688 | 功能描述 : 解析SCTP数据 689 | 输入参数 : struct rte_mbuf *m 690 | uint32_t off_len 691 | 输出参数 : 无 692 | 返 回 值 : int 693 | 作 者 : zc 694 | 日 期 : 2018年8月24日 695 | *****************************************************************************/ 696 | static int 697 | ss_parser_pkt_sctp(struct rte_mbuf *m, uint32_t off_len) 698 | { 699 | struct sctp_hdr sh_copy; 700 | const struct sctp_hdr *sh; 701 | 702 | sh = rte_pktmbuf_read(m, off_len, sizeof(*sh), &sh_copy); 703 | SS_RETURN_RES(unlikely(sh == NULL), 0); 704 | 705 | m->ss.sport = sh->src_port; 706 | m->ss.dport = sh->dst_port; 707 | m->ss.l4_len = sizeof(*sh); 708 | 709 | return 1; 710 | } 711 | 712 | /***************************************************************************** 713 | 函 数 名 : ss_parser_pkt_l4_proto 714 | 功能描述 : 解析L4协议 715 | 输入参数 : struct rte_mbuf *m 716 | uint16_t proto 717 | uint32_t off_len 718 | 输出参数 : 无 719 | 返 回 值 : int 720 | 作 者 : zc 721 | 日 期 : 2018年8月24日 722 | *****************************************************************************/ 723 | static int 724 | ss_parser_pkt_l4_proto(struct rte_mbuf *m, uint16_t proto, 725 | uint32_t off_len) 726 | { 727 | int ret = 0; 728 | uint32_t type = m->ss.packet_type & RTE_PTYPE_L4_MASK; 729 | 730 | switch (type) { 731 | case RTE_PTYPE_L4_UDP: 732 | { 733 | ret = ss_parser_pkt_udp(m, off_len); 734 | break; 735 | } 736 | case RTE_PTYPE_L4_ICMP: 737 | case RTE_PTYPE_L4_IGMP: 738 | case RTE_PTYPE_L4_ICMP6: 739 | case RTE_PTYPE_L4_UDPLITE: 740 | { 741 | break; 742 | } 743 | case RTE_PTYPE_L4_TCP: 744 | { 745 | ret = ss_parser_pkt_tcp(m, off_len); 746 | break; 747 | } 748 | case RTE_PTYPE_L4_SCTP: 749 | { 750 | ret = ss_parser_pkt_sctp(m, off_len); 751 | break; 752 | } 753 | default: 754 | ret = ss_parser_pkt_tunnel(m, proto, off_len); 755 | break; 756 | } 757 | 758 | return ret; 759 | } 760 | 761 | /***************************************************************************** 762 | 函 数 名 : ss_parser_pkt_ipv4 763 | 功能描述 : 解析IPv4数据 764 | 输入参数 : struct rte_mbuf *m 765 | uint32_t off_len 766 | 输出参数 : 无 767 | 返 回 值 : int 768 | 作 者 : zc 769 | 日 期 : 2018年8月22日 770 | *****************************************************************************/ 771 | static int 772 | ss_parser_pkt_ipv4(struct rte_mbuf *m, uint32_t off_len) 773 | { 774 | uint16_t proto; 775 | uint32_t off = off_len; 776 | struct ipv4_hdr ip4h_copy; 777 | const struct ipv4_hdr *ip4h; 778 | 779 | ip4h = rte_pktmbuf_read(m, off, sizeof(*ip4h), &ip4h_copy); 780 | SS_RETURN_RES(unlikely(ip4h == NULL), 0); 781 | SS_RETURN_RES(ip4h->fragment_offset & rte_cpu_to_be_16( 782 | IPV4_HDR_OFFSET_MASK | IPV4_HDR_MF_FLAG), 0); 783 | 784 | m->ss.packet_type |= ss_ptype_l3_ipv4(ip4h->version_ihl); 785 | m->ss.sip[0] = ip4h->src_addr; 786 | m->ss.dip[0] = ip4h->dst_addr; 787 | m->ss.l3_len = SS_IPV4_HLEN(ip4h); 788 | off += m->ss.l3_len; 789 | proto = ip4h->next_proto_id; 790 | m->ss.packet_type |= ss_ptype_l4(proto); 791 | 792 | return ss_parser_pkt_l4_proto(m, proto, off); 793 | } 794 | 795 | /***************************************************************************** 796 | 函 数 名 : ss_parser_pkt_ipv6 797 | 功能描述 : 解析IPv6数据 798 | 输入参数 : struct rte_mbuf *m 799 | uint32_t off_len 800 | 输出参数 : 无 801 | 返 回 值 : int 802 | 作 者 : zc 803 | 日 期 : 2018年8月22日 804 | *****************************************************************************/ 805 | static int 806 | ss_parser_pkt_ipv6(struct rte_mbuf *m, uint32_t off_len) 807 | { 808 | int frag = 0; 809 | uint16_t proto; 810 | uint32_t off = off_len; 811 | struct ipv6_hdr ip6h_copy; 812 | const struct ipv6_hdr *ip6h; 813 | 814 | ip6h = rte_pktmbuf_read(m, off, sizeof(*ip6h), &ip6h_copy); 815 | SS_RETURN_RES(unlikely(ip6h == NULL), 0); 816 | 817 | rte_memcpy(m->ss.sip, ip6h->src_addr, 16); 818 | rte_memcpy(m->ss.dip, ip6h->dst_addr, 16); 819 | m->ss.l3_len = sizeof(*ip6h); 820 | off += m->ss.l3_len; 821 | proto = ip6h->proto; 822 | m->ss.packet_type |= ss_ptype_l3_ipv6(proto); 823 | 824 | /* 解析IPv6扩展头 */ 825 | if ((m->ss.packet_type & RTE_PTYPE_L3_MASK) 826 | == RTE_PTYPE_L3_IPV6_EXT) { 827 | proto = ss_skip_ip6_ext(m, proto, &off, &frag); 828 | m->ss.l3_len = off - m->ss.l2_len; 829 | } 830 | SS_RETURN_RES(proto == 0, 0); 831 | SS_RETURN_RES(frag, 0); 832 | m->ss.packet_type |= ss_ptype_l4(proto); 833 | 834 | return ss_parser_pkt_l4_proto(m, proto, off); 835 | } 836 | 837 | /***************************************************************************** 838 | 函 数 名 : ss_parser_pkt_vlan 839 | 功能描述 : 解析VLAN数据 840 | 输入参数 : struct rte_mbuf *m 841 | uint32_t off_len 842 | 输出参数 : 无 843 | 返 回 值 : int 844 | 作 者 : zc 845 | 日 期 : 2018年8月23日 846 | *****************************************************************************/ 847 | static int 848 | ss_parser_pkt_vlan(struct rte_mbuf *m, uint32_t off_len) 849 | { 850 | int ret = 0; 851 | uint16_t proto; 852 | uint32_t off = off_len; 853 | struct vlan_hdr vh_copy; 854 | const struct vlan_hdr *vh; 855 | 856 | vh = rte_pktmbuf_read(m, off, sizeof(*vh), &vh_copy); 857 | SS_RETURN_RES(unlikely(vh == NULL), 0); 858 | proto = vh->eth_proto; 859 | 860 | m->ss.packet_type = RTE_PTYPE_L2_ETHER_VLAN; 861 | m->ss.l2_len += sizeof(*vh); 862 | off += sizeof(*vh); 863 | 864 | switch (rte_be_to_cpu_16(proto)) { 865 | case ETHER_TYPE_IPv4: 866 | { 867 | ret = ss_parser_pkt_ipv4(m, off); 868 | break; 869 | } 870 | case ETHER_TYPE_IPv6: 871 | { 872 | ret = ss_parser_pkt_ipv6(m, off); 873 | break; 874 | } 875 | default: 876 | break; 877 | } 878 | 879 | return ret; 880 | } 881 | 882 | /***************************************************************************** 883 | 函 数 名 : ss_parser_pkt_qinq 884 | 功能描述 : 解析QINQ数据 885 | 输入参数 : struct rte_mbuf *m 886 | uint32_t off_len 887 | 输出参数 : 无 888 | 返 回 值 : int 889 | 作 者 : zc 890 | 日 期 : 2018年8月23日 891 | *****************************************************************************/ 892 | static int 893 | ss_parser_pkt_qinq(struct rte_mbuf *m, uint32_t off_len) 894 | { 895 | int ret = 0; 896 | uint32_t off = off_len; 897 | struct vlan_hdr vh_copy; 898 | const struct vlan_hdr *vh; 899 | 900 | vh = rte_pktmbuf_read(m, off + sizeof(*vh), sizeof(*vh), &vh_copy); 901 | SS_RETURN_RES(unlikely(vh == NULL), 0); 902 | 903 | m->ss.packet_type = RTE_PTYPE_L2_ETHER_QINQ; 904 | m->ss.l2_len += 2 * sizeof(*vh); 905 | off += 2 * sizeof(*vh); 906 | 907 | switch (rte_be_to_cpu_16(vh->eth_proto)) { 908 | case ETHER_TYPE_IPv4: 909 | { 910 | ret = ss_parser_pkt_ipv4(m, off); 911 | break; 912 | } 913 | case ETHER_TYPE_IPv6: 914 | { 915 | ret = ss_parser_pkt_ipv6(m, off); 916 | break; 917 | } 918 | default: 919 | break; 920 | } 921 | 922 | return ret; 923 | } 924 | 925 | /***************************************************************************** 926 | 函 数 名 : ss_parser_pkt_ether 927 | 功能描述 : 解析二层数据 928 | 输入参数 : struct rte_mbuf *m 929 | 输出参数 : 无 930 | 返 回 值 : int 931 | 作 者 : zc 932 | 日 期 : 2018年8月22日 933 | *****************************************************************************/ 934 | static int 935 | ss_parser_pkt_ether(struct rte_mbuf *m) 936 | { 937 | int ret = 0; 938 | uint32_t off = 0; 939 | struct ether_hdr eh_copy; 940 | const struct ether_hdr *eh; 941 | 942 | eh = rte_pktmbuf_read(m, off, sizeof(*eh), &eh_copy); 943 | SS_RETURN_RES(unlikely(eh == NULL), 0); 944 | 945 | rte_memcpy(m->ss.smac, eh->s_addr.addr_bytes, ETHER_ADDR_LEN); 946 | rte_memcpy(m->ss.dmac, eh->d_addr.addr_bytes, ETHER_ADDR_LEN); 947 | m->ss.packet_type = RTE_PTYPE_L2_ETHER; 948 | m->ss.l2_len = sizeof(*eh); 949 | off = m->ss.l2_len; 950 | 951 | switch (rte_be_to_cpu_16(eh->ether_type)) { 952 | case ETHER_TYPE_IPv4: //IPv4 953 | { 954 | ret = ss_parser_pkt_ipv4(m, off); 955 | break; 956 | } 957 | case ETHER_TYPE_IPv6: //IPv6 958 | { 959 | ret = ss_parser_pkt_ipv6(m, off); 960 | break; 961 | } 962 | case ETHER_TYPE_VLAN: //VLAN 963 | { 964 | ret = ss_parser_pkt_vlan(m, off); 965 | break; 966 | } 967 | case ETHER_TYPE_QINQ: //QINQ 968 | { 969 | ret = ss_parser_pkt_qinq(m, off); 970 | break; 971 | } 972 | default: 973 | break; 974 | } 975 | 976 | return ret; 977 | } 978 | 979 | /***************************************************************************** 980 | 函 数 名 : ss_parser_pkt 981 | 功能描述 : 解析数据包 982 | 输入参数 : struct rte_mbuf *m 983 | 输出参数 : 无 984 | 返 回 值 : int 985 | 作 者 : zc 986 | 日 期 : 2018年8月22日 987 | *****************************************************************************/ 988 | int 989 | ss_parser_pkt(struct rte_mbuf *m) 990 | { 991 | SS_RETURN_RES(unlikely(m == NULL), 0); 992 | memset(&m->ss, 0, sizeof(struct ss_mbuf)); 993 | 994 | return ss_parser_pkt_ether(m); 995 | } 996 | 997 | -------------------------------------------------------------------------------- /librte_net/rte_mbuf.h: -------------------------------------------------------------------------------- 1 | /*- 2 | * BSD LICENSE 3 | * 4 | * Copyright(c) 2010-2014 Intel Corporation. All rights reserved. 5 | * Copyright 2014 6WIND S.A. 6 | * All rights reserved. 7 | * 8 | * Redistribution and use in source and binary forms, with or without 9 | * modification, are permitted provided that the following conditions 10 | * are met: 11 | * 12 | * * Redistributions of source code must retain the above copyright 13 | * notice, this list of conditions and the following disclaimer. 14 | * * Redistributions in binary form must reproduce the above copyright 15 | * notice, this list of conditions and the following disclaimer in 16 | * the documentation and/or other materials provided with the 17 | * distribution. 18 | * * Neither the name of Intel Corporation nor the names of its 19 | * contributors may be used to endorse or promote products derived 20 | * from this software without specific prior written permission. 21 | * 22 | * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 23 | * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 24 | * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR 25 | * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 26 | * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 27 | * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 28 | * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 29 | * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 30 | * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 31 | * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 32 | * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 33 | */ 34 | 35 | #ifndef _RTE_MBUF_H_ 36 | #define _RTE_MBUF_H_ 37 | 38 | /** 39 | * @file 40 | * RTE Mbuf 41 | * 42 | * The mbuf library provides the ability to create and destroy buffers 43 | * that may be used by the RTE application to store message 44 | * buffers. The message buffers are stored in a mempool, using the 45 | * RTE mempool library. 46 | * 47 | * The preferred way to create a mbuf pool is to use 48 | * rte_pktmbuf_pool_create(). However, in some situations, an 49 | * application may want to have more control (ex: populate the pool with 50 | * specific memory), in this case it is possible to use functions from 51 | * rte_mempool. See how rte_pktmbuf_pool_create() is implemented for 52 | * details. 53 | * 54 | * This library provides an API to allocate/free packet mbufs, which are 55 | * used to carry network packets. 56 | * 57 | * To understand the concepts of packet buffers or mbufs, you 58 | * should read "TCP/IP Illustrated, Volume 2: The Implementation, 59 | * Addison-Wesley, 1995, ISBN 0-201-63354-X from Richard Stevens" 60 | * http://www.kohala.com/start/tcpipiv2.html 61 | */ 62 | 63 | #include 64 | #include 65 | #include 66 | #include 67 | #include 68 | #include 69 | #include 70 | #include 71 | #include 72 | 73 | #ifdef __cplusplus 74 | extern "C" { 75 | #endif 76 | 77 | /* 78 | * Packet Offload Features Flags. It also carry packet type information. 79 | * Critical resources. Both rx/tx shared these bits. Be cautious on any change 80 | * 81 | * - RX flags start at bit position zero, and get added to the left of previous 82 | * flags. 83 | * - The most-significant 3 bits are reserved for generic mbuf flags 84 | * - TX flags therefore start at bit position 60 (i.e. 63-3), and new flags get 85 | * added to the right of the previously defined flags i.e. they should count 86 | * downwards, not upwards. 87 | * 88 | * Keep these flags synchronized with rte_get_rx_ol_flag_name() and 89 | * rte_get_tx_ol_flag_name(). 90 | */ 91 | 92 | /** 93 | * The RX packet is a 802.1q VLAN packet, and the tci has been 94 | * saved in in mbuf->vlan_tci. 95 | * If the flag PKT_RX_VLAN_STRIPPED is also present, the VLAN 96 | * header has been stripped from mbuf data, else it is still 97 | * present. 98 | */ 99 | #define PKT_RX_VLAN (1ULL << 0) 100 | 101 | #define PKT_RX_RSS_HASH (1ULL << 1) /**< RX packet with RSS hash result. */ 102 | #define PKT_RX_FDIR (1ULL << 2) /**< RX packet with FDIR match indicate. */ 103 | 104 | /** 105 | * Deprecated. 106 | * Checking this flag alone is deprecated: check the 2 bits of 107 | * PKT_RX_L4_CKSUM_MASK. 108 | * This flag was set when the L4 checksum of a packet was detected as 109 | * wrong by the hardware. 110 | */ 111 | #define PKT_RX_L4_CKSUM_BAD (1ULL << 3) 112 | 113 | /** 114 | * Deprecated. 115 | * Checking this flag alone is deprecated: check the 2 bits of 116 | * PKT_RX_IP_CKSUM_MASK. 117 | * This flag was set when the IP checksum of a packet was detected as 118 | * wrong by the hardware. 119 | */ 120 | #define PKT_RX_IP_CKSUM_BAD (1ULL << 4) 121 | 122 | #define PKT_RX_EIP_CKSUM_BAD (1ULL << 5) /**< External IP header checksum error. */ 123 | 124 | /** 125 | * A vlan has been stripped by the hardware and its tci is saved in 126 | * mbuf->vlan_tci. This can only happen if vlan stripping is enabled 127 | * in the RX configuration of the PMD. 128 | * When PKT_RX_VLAN_STRIPPED is set, PKT_RX_VLAN must also be set. 129 | */ 130 | #define PKT_RX_VLAN_STRIPPED (1ULL << 6) 131 | 132 | /** 133 | * Mask of bits used to determine the status of RX IP checksum. 134 | * - PKT_RX_IP_CKSUM_UNKNOWN: no information about the RX IP checksum 135 | * - PKT_RX_IP_CKSUM_BAD: the IP checksum in the packet is wrong 136 | * - PKT_RX_IP_CKSUM_GOOD: the IP checksum in the packet is valid 137 | * - PKT_RX_IP_CKSUM_NONE: the IP checksum is not correct in the packet 138 | * data, but the integrity of the IP header is verified. 139 | */ 140 | #define PKT_RX_IP_CKSUM_MASK ((1ULL << 4) | (1ULL << 7)) 141 | 142 | #define PKT_RX_IP_CKSUM_UNKNOWN 0 143 | #define PKT_RX_IP_CKSUM_BAD (1ULL << 4) 144 | #define PKT_RX_IP_CKSUM_GOOD (1ULL << 7) 145 | #define PKT_RX_IP_CKSUM_NONE ((1ULL << 4) | (1ULL << 7)) 146 | 147 | /** 148 | * Mask of bits used to determine the status of RX L4 checksum. 149 | * - PKT_RX_L4_CKSUM_UNKNOWN: no information about the RX L4 checksum 150 | * - PKT_RX_L4_CKSUM_BAD: the L4 checksum in the packet is wrong 151 | * - PKT_RX_L4_CKSUM_GOOD: the L4 checksum in the packet is valid 152 | * - PKT_RX_L4_CKSUM_NONE: the L4 checksum is not correct in the packet 153 | * data, but the integrity of the L4 data is verified. 154 | */ 155 | #define PKT_RX_L4_CKSUM_MASK ((1ULL << 3) | (1ULL << 8)) 156 | 157 | #define PKT_RX_L4_CKSUM_UNKNOWN 0 158 | #define PKT_RX_L4_CKSUM_BAD (1ULL << 3) 159 | #define PKT_RX_L4_CKSUM_GOOD (1ULL << 8) 160 | #define PKT_RX_L4_CKSUM_NONE ((1ULL << 3) | (1ULL << 8)) 161 | 162 | #define PKT_RX_IEEE1588_PTP (1ULL << 9) /**< RX IEEE1588 L2 Ethernet PT Packet. */ 163 | #define PKT_RX_IEEE1588_TMST (1ULL << 10) /**< RX IEEE1588 L2/L4 timestamped packet.*/ 164 | #define PKT_RX_FDIR_ID (1ULL << 13) /**< FD id reported if FDIR match. */ 165 | #define PKT_RX_FDIR_FLX (1ULL << 14) /**< Flexible bytes reported if FDIR match. */ 166 | 167 | /** 168 | * The 2 vlans have been stripped by the hardware and their tci are 169 | * saved in mbuf->vlan_tci (inner) and mbuf->vlan_tci_outer (outer). 170 | * This can only happen if vlan stripping is enabled in the RX 171 | * configuration of the PMD. If this flag is set, 172 | * When PKT_RX_QINQ_STRIPPED is set, the flags (PKT_RX_VLAN | 173 | * PKT_RX_VLAN_STRIPPED | PKT_RX_QINQ) must also be set. 174 | */ 175 | #define PKT_RX_QINQ_STRIPPED (1ULL << 15) 176 | 177 | /** 178 | * When packets are coalesced by a hardware or virtual driver, this flag 179 | * can be set in the RX mbuf, meaning that the m->tso_segsz field is 180 | * valid and is set to the segment size of original packets. 181 | */ 182 | #define PKT_RX_LRO (1ULL << 16) 183 | 184 | /** 185 | * Indicate that the timestamp field in the mbuf is valid. 186 | */ 187 | #define PKT_RX_TIMESTAMP (1ULL << 17) 188 | 189 | /** 190 | * Indicate that security offload processing was applied on the RX packet. 191 | */ 192 | #define PKT_RX_SEC_OFFLOAD (1ULL << 18) 193 | 194 | /** 195 | * Indicate that security offload processing failed on the RX packet. 196 | */ 197 | #define PKT_RX_SEC_OFFLOAD_FAILED (1ULL << 19) 198 | 199 | /** 200 | * The RX packet is a double VLAN, and the outer tci has been 201 | * saved in in mbuf->vlan_tci_outer. 202 | * If the flag PKT_RX_QINQ_STRIPPED is also present, both VLANs 203 | * headers have been stripped from mbuf data, else they are still 204 | * present. 205 | */ 206 | #define PKT_RX_QINQ (1ULL << 20) 207 | 208 | /* add new RX flags here */ 209 | 210 | /* add new TX flags here */ 211 | 212 | /** 213 | * Request security offload processing on the TX packet. 214 | */ 215 | #define PKT_TX_SEC_OFFLOAD (1ULL << 43) 216 | 217 | /** 218 | * Offload the MACsec. This flag must be set by the application to enable 219 | * this offload feature for a packet to be transmitted. 220 | */ 221 | #define PKT_TX_MACSEC (1ULL << 44) 222 | 223 | /** 224 | * Bits 45:48 used for the tunnel type. 225 | * When doing Tx offload like TSO or checksum, the HW needs to configure the 226 | * tunnel type into the HW descriptors. 227 | */ 228 | #define PKT_TX_TUNNEL_VXLAN (0x1ULL << 45) 229 | #define PKT_TX_TUNNEL_GRE (0x2ULL << 45) 230 | #define PKT_TX_TUNNEL_IPIP (0x3ULL << 45) 231 | #define PKT_TX_TUNNEL_GENEVE (0x4ULL << 45) 232 | /**< TX packet with MPLS-in-UDP RFC 7510 header. */ 233 | #define PKT_TX_TUNNEL_MPLSINUDP (0x5ULL << 45) 234 | /* add new TX TUNNEL type here */ 235 | #define PKT_TX_TUNNEL_MASK (0xFULL << 45) 236 | 237 | /** 238 | * Second VLAN insertion (QinQ) flag. 239 | */ 240 | #define PKT_TX_QINQ_PKT (1ULL << 49) /**< TX packet with double VLAN inserted. */ 241 | 242 | /** 243 | * TCP segmentation offload. To enable this offload feature for a 244 | * packet to be transmitted on hardware supporting TSO: 245 | * - set the PKT_TX_TCP_SEG flag in mbuf->ol_flags (this flag implies 246 | * PKT_TX_TCP_CKSUM) 247 | * - set the flag PKT_TX_IPV4 or PKT_TX_IPV6 248 | * - if it's IPv4, set the PKT_TX_IP_CKSUM flag and write the IP checksum 249 | * to 0 in the packet 250 | * - fill the mbuf offload information: l2_len, l3_len, l4_len, tso_segsz 251 | * - calculate the pseudo header checksum without taking ip_len in account, 252 | * and set it in the TCP header. Refer to rte_ipv4_phdr_cksum() and 253 | * rte_ipv6_phdr_cksum() that can be used as helpers. 254 | */ 255 | #define PKT_TX_TCP_SEG (1ULL << 50) 256 | 257 | #define PKT_TX_IEEE1588_TMST (1ULL << 51) /**< TX IEEE1588 packet to timestamp. */ 258 | 259 | /** 260 | * Bits 52+53 used for L4 packet type with checksum enabled: 00: Reserved, 261 | * 01: TCP checksum, 10: SCTP checksum, 11: UDP checksum. To use hardware 262 | * L4 checksum offload, the user needs to: 263 | * - fill l2_len and l3_len in mbuf 264 | * - set the flags PKT_TX_TCP_CKSUM, PKT_TX_SCTP_CKSUM or PKT_TX_UDP_CKSUM 265 | * - set the flag PKT_TX_IPV4 or PKT_TX_IPV6 266 | * - calculate the pseudo header checksum and set it in the L4 header (only 267 | * for TCP or UDP). See rte_ipv4_phdr_cksum() and rte_ipv6_phdr_cksum(). 268 | * For SCTP, set the crc field to 0. 269 | */ 270 | #define PKT_TX_L4_NO_CKSUM (0ULL << 52) /**< Disable L4 cksum of TX pkt. */ 271 | #define PKT_TX_TCP_CKSUM (1ULL << 52) /**< TCP cksum of TX pkt. computed by NIC. */ 272 | #define PKT_TX_SCTP_CKSUM (2ULL << 52) /**< SCTP cksum of TX pkt. computed by NIC. */ 273 | #define PKT_TX_UDP_CKSUM (3ULL << 52) /**< UDP cksum of TX pkt. computed by NIC. */ 274 | #define PKT_TX_L4_MASK (3ULL << 52) /**< Mask for L4 cksum offload request. */ 275 | 276 | /** 277 | * Offload the IP checksum in the hardware. The flag PKT_TX_IPV4 should 278 | * also be set by the application, although a PMD will only check 279 | * PKT_TX_IP_CKSUM. 280 | * - set the IP checksum field in the packet to 0 281 | * - fill the mbuf offload information: l2_len, l3_len 282 | */ 283 | #define PKT_TX_IP_CKSUM (1ULL << 54) 284 | 285 | /** 286 | * Packet is IPv4. This flag must be set when using any offload feature 287 | * (TSO, L3 or L4 checksum) to tell the NIC that the packet is an IPv4 288 | * packet. If the packet is a tunneled packet, this flag is related to 289 | * the inner headers. 290 | */ 291 | #define PKT_TX_IPV4 (1ULL << 55) 292 | 293 | /** 294 | * Packet is IPv6. This flag must be set when using an offload feature 295 | * (TSO or L4 checksum) to tell the NIC that the packet is an IPv6 296 | * packet. If the packet is a tunneled packet, this flag is related to 297 | * the inner headers. 298 | */ 299 | #define PKT_TX_IPV6 (1ULL << 56) 300 | 301 | #define PKT_TX_VLAN_PKT (1ULL << 57) /**< TX packet is a 802.1q VLAN packet. */ 302 | 303 | /** 304 | * Offload the IP checksum of an external header in the hardware. The 305 | * flag PKT_TX_OUTER_IPV4 should also be set by the application, alto ugh 306 | * a PMD will only check PKT_TX_IP_CKSUM. The IP checksum field in the 307 | * packet must be set to 0. 308 | * - set the outer IP checksum field in the packet to 0 309 | * - fill the mbuf offload information: outer_l2_len, outer_l3_len 310 | */ 311 | #define PKT_TX_OUTER_IP_CKSUM (1ULL << 58) 312 | 313 | /** 314 | * Packet outer header is IPv4. This flag must be set when using any 315 | * outer offload feature (L3 or L4 checksum) to tell the NIC that the 316 | * outer header of the tunneled packet is an IPv4 packet. 317 | */ 318 | #define PKT_TX_OUTER_IPV4 (1ULL << 59) 319 | 320 | /** 321 | * Packet outer header is IPv6. This flag must be set when using any 322 | * outer offload feature (L4 checksum) to tell the NIC that the outer 323 | * header of the tunneled packet is an IPv6 packet. 324 | */ 325 | #define PKT_TX_OUTER_IPV6 (1ULL << 60) 326 | 327 | /** 328 | * Bitmask of all supported packet Tx offload features flags, 329 | * which can be set for packet. 330 | */ 331 | #define PKT_TX_OFFLOAD_MASK ( \ 332 | PKT_TX_IP_CKSUM | \ 333 | PKT_TX_L4_MASK | \ 334 | PKT_TX_OUTER_IP_CKSUM | \ 335 | PKT_TX_TCP_SEG | \ 336 | PKT_TX_IEEE1588_TMST | \ 337 | PKT_TX_QINQ_PKT | \ 338 | PKT_TX_VLAN_PKT | \ 339 | PKT_TX_TUNNEL_MASK | \ 340 | PKT_TX_MACSEC | \ 341 | PKT_TX_SEC_OFFLOAD) 342 | 343 | #define __RESERVED (1ULL << 61) /**< reserved for future mbuf use */ 344 | 345 | #define IND_ATTACHED_MBUF (1ULL << 62) /**< Indirect attached mbuf */ 346 | 347 | /* Use final bit of flags to indicate a control mbuf */ 348 | #define CTRL_MBUF_FLAG (1ULL << 63) /**< Mbuf contains control data */ 349 | 350 | /** Alignment constraint of mbuf private area. */ 351 | #define RTE_MBUF_PRIV_ALIGN 8 352 | 353 | /** 354 | * Get the name of a RX offload flag 355 | * 356 | * @param mask 357 | * The mask describing the flag. 358 | * @return 359 | * The name of this flag, or NULL if it's not a valid RX flag. 360 | */ 361 | const char *rte_get_rx_ol_flag_name(uint64_t mask); 362 | 363 | /** 364 | * Dump the list of RX offload flags in a buffer 365 | * 366 | * @param mask 367 | * The mask describing the RX flags. 368 | * @param buf 369 | * The output buffer. 370 | * @param buflen 371 | * The length of the buffer. 372 | * @return 373 | * 0 on success, (-1) on error. 374 | */ 375 | int rte_get_rx_ol_flag_list(uint64_t mask, char *buf, size_t buflen); 376 | 377 | /** 378 | * Get the name of a TX offload flag 379 | * 380 | * @param mask 381 | * The mask describing the flag. Usually only one bit must be set. 382 | * Several bits can be given if they belong to the same mask. 383 | * Ex: PKT_TX_L4_MASK. 384 | * @return 385 | * The name of this flag, or NULL if it's not a valid TX flag. 386 | */ 387 | const char *rte_get_tx_ol_flag_name(uint64_t mask); 388 | 389 | /** 390 | * Dump the list of TX offload flags in a buffer 391 | * 392 | * @param mask 393 | * The mask describing the TX flags. 394 | * @param buf 395 | * The output buffer. 396 | * @param buflen 397 | * The length of the buffer. 398 | * @return 399 | * 0 on success, (-1) on error. 400 | */ 401 | int rte_get_tx_ol_flag_list(uint64_t mask, char *buf, size_t buflen); 402 | 403 | /** 404 | * Some NICs need at least 2KB buffer to RX standard Ethernet frame without 405 | * splitting it into multiple segments. 406 | * So, for mbufs that planned to be involved into RX/TX, the recommended 407 | * minimal buffer length is 2KB + RTE_PKTMBUF_HEADROOM. 408 | */ 409 | #define RTE_MBUF_DEFAULT_DATAROOM 2048 410 | #define RTE_MBUF_DEFAULT_BUF_SIZE \ 411 | (RTE_MBUF_DEFAULT_DATAROOM + RTE_PKTMBUF_HEADROOM) 412 | 413 | /* define a set of marker types that can be used to refer to set points in the 414 | * mbuf */ 415 | __extension__ 416 | typedef void *MARKER[0]; /**< generic marker for a point in a structure */ 417 | __extension__ 418 | typedef uint8_t MARKER8[0]; /**< generic marker with 1B alignment */ 419 | __extension__ 420 | typedef uint64_t MARKER64[0]; /**< marker that allows us to overwrite 8 bytes 421 | * with a single assignment */ 422 | 423 | /* BEGIN: Added by zc, 2018/8/21 */ 424 | struct ss_mbuf { 425 | uint8_t l2_len; // (Outer) L2 Length 426 | uint8_t l3_len; // (Outer) L3 Length 427 | uint8_t l4_len; // (Outer) L4 Length 428 | uint8_t tunnel_len; // Tunnel Length 429 | uint8_t inner_l2_len; // Inner L2 Length 430 | uint8_t inner_l3_len; // Inner L3 Length 431 | uint8_t inner_l4_len; // Inner L4 Length 432 | uint8_t inner_smac[6]; 433 | uint8_t inner_dmac[6]; 434 | uint32_t inner_sip[4]; 435 | uint32_t inner_dip[4]; 436 | uint8_t smac[6]; 437 | uint8_t dmac[6]; 438 | uint16_t sport; 439 | uint16_t dport; 440 | uint32_t sip[4]; 441 | uint32_t dip[4]; 442 | uint32_t packet_type; 443 | } __rte_cache_aligned; 444 | /* END: Added by zc, 2018/8/21 */ 445 | 446 | /** 447 | * The generic rte_mbuf, containing a packet mbuf. 448 | */ 449 | struct rte_mbuf { 450 | MARKER cacheline0; 451 | 452 | void *buf_addr; /**< Virtual address of segment buffer. */ 453 | /** 454 | * Physical address of segment buffer. 455 | * Force alignment to 8-bytes, so as to ensure we have the exact 456 | * same mbuf cacheline0 layout for 32-bit and 64-bit. This makes 457 | * working on vector drivers easier. 458 | */ 459 | RTE_STD_C11 460 | union { 461 | rte_iova_t buf_iova; 462 | rte_iova_t buf_physaddr; /**< deprecated */ 463 | } __rte_aligned(sizeof(rte_iova_t)); 464 | 465 | /* next 8 bytes are initialised on RX descriptor rearm */ 466 | MARKER64 rearm_data; 467 | uint16_t data_off; 468 | 469 | /** 470 | * Reference counter. Its size should at least equal to the size 471 | * of port field (16 bits), to support zero-copy broadcast. 472 | * It should only be accessed using the following functions: 473 | * rte_mbuf_refcnt_update(), rte_mbuf_refcnt_read(), and 474 | * rte_mbuf_refcnt_set(). The functionality of these functions (atomic, 475 | * or non-atomic) is controlled by the CONFIG_RTE_MBUF_REFCNT_ATOMIC 476 | * config option. 477 | */ 478 | RTE_STD_C11 479 | union { 480 | rte_atomic16_t refcnt_atomic; /**< Atomically accessed refcnt */ 481 | uint16_t refcnt; /**< Non-atomically accessed refcnt */ 482 | }; 483 | uint16_t nb_segs; /**< Number of segments. */ 484 | 485 | /** Input port (16 bits to support more than 256 virtual ports). */ 486 | uint16_t port; 487 | 488 | uint64_t ol_flags; /**< Offload features. */ 489 | 490 | /* remaining bytes are set on RX when pulling packet from descriptor */ 491 | MARKER rx_descriptor_fields1; 492 | 493 | /* 494 | * The packet type, which is the combination of outer/inner L2, L3, L4 495 | * and tunnel types. The packet_type is about data really present in the 496 | * mbuf. Example: if vlan stripping is enabled, a received vlan packet 497 | * would have RTE_PTYPE_L2_ETHER and not RTE_PTYPE_L2_VLAN because the 498 | * vlan is stripped from the data. 499 | */ 500 | RTE_STD_C11 501 | union { 502 | uint32_t packet_type; /**< L2/L3/L4 and tunnel information. */ 503 | struct { 504 | uint32_t l2_type:4; /**< (Outer) L2 type. */ 505 | uint32_t l3_type:4; /**< (Outer) L3 type. */ 506 | uint32_t l4_type:4; /**< (Outer) L4 type. */ 507 | uint32_t tun_type:4; /**< Tunnel type. */ 508 | RTE_STD_C11 509 | union { 510 | uint8_t inner_esp_next_proto; 511 | /**< ESP next protocol type, valid if 512 | * RTE_PTYPE_TUNNEL_ESP tunnel type is set 513 | * on both Tx and Rx. 514 | */ 515 | __extension__ 516 | struct { 517 | uint8_t inner_l2_type:4; 518 | /**< Inner L2 type. */ 519 | uint8_t inner_l3_type:4; 520 | /**< Inner L3 type. */ 521 | }; 522 | }; 523 | uint32_t inner_l4_type:4; /**< Inner L4 type. */ 524 | }; 525 | }; 526 | 527 | uint32_t pkt_len; /**< Total pkt len: sum of all segments. */ 528 | uint16_t data_len; /**< Amount of data in segment buffer. */ 529 | /** VLAN TCI (CPU order), valid if PKT_RX_VLAN_STRIPPED is set. */ 530 | uint16_t vlan_tci; 531 | 532 | union { 533 | uint32_t rss; /**< RSS hash result if RSS enabled */ 534 | struct { 535 | RTE_STD_C11 536 | union { 537 | struct { 538 | uint16_t hash; 539 | uint16_t id; 540 | }; 541 | uint32_t lo; 542 | /**< Second 4 flexible bytes */ 543 | }; 544 | uint32_t hi; 545 | /**< First 4 flexible bytes or FD ID, dependent on 546 | PKT_RX_FDIR_* flag in ol_flags. */ 547 | } fdir; /**< Filter identifier if FDIR enabled */ 548 | struct { 549 | uint32_t lo; 550 | uint32_t hi; 551 | } sched; /**< Hierarchical scheduler */ 552 | uint32_t usr; /**< User defined tags. See rte_distributor_process() */ 553 | } hash; /**< hash information */ 554 | 555 | /** Outer VLAN TCI (CPU order), valid if PKT_RX_QINQ_STRIPPED is set. */ 556 | uint16_t vlan_tci_outer; 557 | 558 | uint16_t buf_len; /**< Length of segment buffer. */ 559 | 560 | /** Valid if PKT_RX_TIMESTAMP is set. The unit and time reference 561 | * are not normalized but are always the same for a given port. 562 | */ 563 | uint64_t timestamp; 564 | 565 | /* second cache line - fields only used in slow path or on TX */ 566 | MARKER cacheline1 __rte_cache_min_aligned; 567 | 568 | RTE_STD_C11 569 | union { 570 | void *userdata; /**< Can be used for external metadata */ 571 | uint64_t udata64; /**< Allow 8-byte userdata on 32-bit */ 572 | }; 573 | 574 | struct rte_mempool *pool; /**< Pool from which mbuf was allocated. */ 575 | struct rte_mbuf *next; /**< Next segment of scattered packet. */ 576 | 577 | /* BEGIN: Added by zc, 2018/8/21 */ 578 | struct ss_mbuf ss; 579 | /* END: Added by zc, 2018/8/21 */ 580 | 581 | /* fields to support TX offloads */ 582 | RTE_STD_C11 583 | union { 584 | uint64_t tx_offload; /**< combined for easy fetch */ 585 | __extension__ 586 | struct { 587 | uint64_t l2_len:7; 588 | /**< L2 (MAC) Header Length for non-tunneling pkt. 589 | * Outer_L4_len + ... + Inner_L2_len for tunneling pkt. 590 | */ 591 | uint64_t l3_len:9; /**< L3 (IP) Header Length. */ 592 | uint64_t l4_len:8; /**< L4 (TCP/UDP) Header Length. */ 593 | uint64_t tso_segsz:16; /**< TCP TSO segment size */ 594 | 595 | /* fields for TX offloading of tunnels */ 596 | uint64_t outer_l3_len:9; /**< Outer L3 (IP) Hdr Length. */ 597 | uint64_t outer_l2_len:7; /**< Outer L2 (MAC) Hdr Length. */ 598 | 599 | /* uint64_t unused:8; */ 600 | }; 601 | }; 602 | 603 | /** Size of the application private data. In case of an indirect 604 | * mbuf, it stores the direct mbuf private data size. */ 605 | uint16_t priv_size; 606 | 607 | /** Timesync flags for use with IEEE1588. */ 608 | uint16_t timesync; 609 | 610 | /** Sequence number. See also rte_reorder_insert(). */ 611 | uint32_t seqn; 612 | 613 | } __rte_cache_aligned; 614 | 615 | /**< Maximum number of nb_segs allowed. */ 616 | #define RTE_MBUF_MAX_NB_SEGS UINT16_MAX 617 | 618 | /** 619 | * Prefetch the first part of the mbuf 620 | * 621 | * The first 64 bytes of the mbuf corresponds to fields that are used early 622 | * in the receive path. If the cache line of the architecture is higher than 623 | * 64B, the second part will also be prefetched. 624 | * 625 | * @param m 626 | * The pointer to the mbuf. 627 | */ 628 | static inline void 629 | rte_mbuf_prefetch_part1(struct rte_mbuf *m) 630 | { 631 | rte_prefetch0(&m->cacheline0); 632 | } 633 | 634 | /** 635 | * Prefetch the second part of the mbuf 636 | * 637 | * The next 64 bytes of the mbuf corresponds to fields that are used in the 638 | * transmit path. If the cache line of the architecture is higher than 64B, 639 | * this function does nothing as it is expected that the full mbuf is 640 | * already in cache. 641 | * 642 | * @param m 643 | * The pointer to the mbuf. 644 | */ 645 | static inline void 646 | rte_mbuf_prefetch_part2(struct rte_mbuf *m) 647 | { 648 | #if RTE_CACHE_LINE_SIZE == 64 649 | rte_prefetch0(&m->cacheline1); 650 | #else 651 | RTE_SET_USED(m); 652 | #endif 653 | } 654 | 655 | 656 | static inline uint16_t rte_pktmbuf_priv_size(struct rte_mempool *mp); 657 | 658 | /** 659 | * Return the IO address of the beginning of the mbuf data 660 | * 661 | * @param mb 662 | * The pointer to the mbuf. 663 | * @return 664 | * The IO address of the beginning of the mbuf data 665 | */ 666 | static inline rte_iova_t 667 | rte_mbuf_data_iova(const struct rte_mbuf *mb) 668 | { 669 | return mb->buf_iova + mb->data_off; 670 | } 671 | 672 | __rte_deprecated 673 | static inline phys_addr_t 674 | rte_mbuf_data_dma_addr(const struct rte_mbuf *mb) 675 | { 676 | return rte_mbuf_data_iova(mb); 677 | } 678 | 679 | /** 680 | * Return the default IO address of the beginning of the mbuf data 681 | * 682 | * This function is used by drivers in their receive function, as it 683 | * returns the location where data should be written by the NIC, taking 684 | * the default headroom in account. 685 | * 686 | * @param mb 687 | * The pointer to the mbuf. 688 | * @return 689 | * The IO address of the beginning of the mbuf data 690 | */ 691 | static inline rte_iova_t 692 | rte_mbuf_data_iova_default(const struct rte_mbuf *mb) 693 | { 694 | return mb->buf_iova + RTE_PKTMBUF_HEADROOM; 695 | } 696 | 697 | __rte_deprecated 698 | static inline phys_addr_t 699 | rte_mbuf_data_dma_addr_default(const struct rte_mbuf *mb) 700 | { 701 | return rte_mbuf_data_iova_default(mb); 702 | } 703 | 704 | /** 705 | * Return the mbuf owning the data buffer address of an indirect mbuf. 706 | * 707 | * @param mi 708 | * The pointer to the indirect mbuf. 709 | * @return 710 | * The address of the direct mbuf corresponding to buffer_addr. 711 | */ 712 | static inline struct rte_mbuf * 713 | rte_mbuf_from_indirect(struct rte_mbuf *mi) 714 | { 715 | return (struct rte_mbuf *)RTE_PTR_SUB(mi->buf_addr, sizeof(*mi) + mi->priv_size); 716 | } 717 | 718 | /** 719 | * Return the buffer address embedded in the given mbuf. 720 | * 721 | * @param md 722 | * The pointer to the mbuf. 723 | * @return 724 | * The address of the data buffer owned by the mbuf. 725 | */ 726 | static inline char * 727 | rte_mbuf_to_baddr(struct rte_mbuf *md) 728 | { 729 | char *buffer_addr; 730 | buffer_addr = (char *)md + sizeof(*md) + rte_pktmbuf_priv_size(md->pool); 731 | return buffer_addr; 732 | } 733 | 734 | /** 735 | * Returns TRUE if given mbuf is indirect, or FALSE otherwise. 736 | */ 737 | #define RTE_MBUF_INDIRECT(mb) ((mb)->ol_flags & IND_ATTACHED_MBUF) 738 | 739 | /** 740 | * Returns TRUE if given mbuf is direct, or FALSE otherwise. 741 | */ 742 | #define RTE_MBUF_DIRECT(mb) (!RTE_MBUF_INDIRECT(mb)) 743 | 744 | /** 745 | * Private data in case of pktmbuf pool. 746 | * 747 | * A structure that contains some pktmbuf_pool-specific data that are 748 | * appended after the mempool structure (in private data). 749 | */ 750 | struct rte_pktmbuf_pool_private { 751 | uint16_t mbuf_data_room_size; /**< Size of data space in each mbuf. */ 752 | uint16_t mbuf_priv_size; /**< Size of private area in each mbuf. */ 753 | }; 754 | 755 | #ifdef RTE_LIBRTE_MBUF_DEBUG 756 | 757 | /** check mbuf type in debug mode */ 758 | #define __rte_mbuf_sanity_check(m, is_h) rte_mbuf_sanity_check(m, is_h) 759 | 760 | #else /* RTE_LIBRTE_MBUF_DEBUG */ 761 | 762 | /** check mbuf type in debug mode */ 763 | #define __rte_mbuf_sanity_check(m, is_h) do { } while (0) 764 | 765 | #endif /* RTE_LIBRTE_MBUF_DEBUG */ 766 | 767 | #ifdef RTE_MBUF_REFCNT_ATOMIC 768 | 769 | /** 770 | * Reads the value of an mbuf's refcnt. 771 | * @param m 772 | * Mbuf to read 773 | * @return 774 | * Reference count number. 775 | */ 776 | static inline uint16_t 777 | rte_mbuf_refcnt_read(const struct rte_mbuf *m) 778 | { 779 | return (uint16_t)(rte_atomic16_read(&m->refcnt_atomic)); 780 | } 781 | 782 | /** 783 | * Sets an mbuf's refcnt to a defined value. 784 | * @param m 785 | * Mbuf to update 786 | * @param new_value 787 | * Value set 788 | */ 789 | static inline void 790 | rte_mbuf_refcnt_set(struct rte_mbuf *m, uint16_t new_value) 791 | { 792 | rte_atomic16_set(&m->refcnt_atomic, new_value); 793 | } 794 | 795 | /* internal */ 796 | static inline uint16_t 797 | __rte_mbuf_refcnt_update(struct rte_mbuf *m, int16_t value) 798 | { 799 | return (uint16_t)(rte_atomic16_add_return(&m->refcnt_atomic, value)); 800 | } 801 | 802 | /** 803 | * Adds given value to an mbuf's refcnt and returns its new value. 804 | * @param m 805 | * Mbuf to update 806 | * @param value 807 | * Value to add/subtract 808 | * @return 809 | * Updated value 810 | */ 811 | static inline uint16_t 812 | rte_mbuf_refcnt_update(struct rte_mbuf *m, int16_t value) 813 | { 814 | /* 815 | * The atomic_add is an expensive operation, so we don't want to 816 | * call it in the case where we know we are the uniq holder of 817 | * this mbuf (i.e. ref_cnt == 1). Otherwise, an atomic 818 | * operation has to be used because concurrent accesses on the 819 | * reference counter can occur. 820 | */ 821 | if (likely(rte_mbuf_refcnt_read(m) == 1)) { 822 | rte_mbuf_refcnt_set(m, 1 + value); 823 | return 1 + value; 824 | } 825 | 826 | return __rte_mbuf_refcnt_update(m, value); 827 | } 828 | 829 | #else /* ! RTE_MBUF_REFCNT_ATOMIC */ 830 | 831 | /* internal */ 832 | static inline uint16_t 833 | __rte_mbuf_refcnt_update(struct rte_mbuf *m, int16_t value) 834 | { 835 | m->refcnt = (uint16_t)(m->refcnt + value); 836 | return m->refcnt; 837 | } 838 | 839 | /** 840 | * Adds given value to an mbuf's refcnt and returns its new value. 841 | */ 842 | static inline uint16_t 843 | rte_mbuf_refcnt_update(struct rte_mbuf *m, int16_t value) 844 | { 845 | return __rte_mbuf_refcnt_update(m, value); 846 | } 847 | 848 | /** 849 | * Reads the value of an mbuf's refcnt. 850 | */ 851 | static inline uint16_t 852 | rte_mbuf_refcnt_read(const struct rte_mbuf *m) 853 | { 854 | return m->refcnt; 855 | } 856 | 857 | /** 858 | * Sets an mbuf's refcnt to the defined value. 859 | */ 860 | static inline void 861 | rte_mbuf_refcnt_set(struct rte_mbuf *m, uint16_t new_value) 862 | { 863 | m->refcnt = new_value; 864 | } 865 | 866 | #endif /* RTE_MBUF_REFCNT_ATOMIC */ 867 | 868 | /** Mbuf prefetch */ 869 | #define RTE_MBUF_PREFETCH_TO_FREE(m) do { \ 870 | if ((m) != NULL) \ 871 | rte_prefetch0(m); \ 872 | } while (0) 873 | 874 | 875 | /** 876 | * Sanity checks on an mbuf. 877 | * 878 | * Check the consistency of the given mbuf. The function will cause a 879 | * panic if corruption is detected. 880 | * 881 | * @param m 882 | * The mbuf to be checked. 883 | * @param is_header 884 | * True if the mbuf is a packet header, false if it is a sub-segment 885 | * of a packet (in this case, some fields like nb_segs are not checked) 886 | */ 887 | void 888 | rte_mbuf_sanity_check(const struct rte_mbuf *m, int is_header); 889 | 890 | #define MBUF_RAW_ALLOC_CHECK(m) do { \ 891 | RTE_ASSERT(rte_mbuf_refcnt_read(m) == 1); \ 892 | RTE_ASSERT((m)->next == NULL); \ 893 | RTE_ASSERT((m)->nb_segs == 1); \ 894 | __rte_mbuf_sanity_check(m, 0); \ 895 | } while (0) 896 | 897 | /** 898 | * Allocate an uninitialized mbuf from mempool *mp*. 899 | * 900 | * This function can be used by PMDs (especially in RX functions) to 901 | * allocate an uninitialized mbuf. The driver is responsible of 902 | * initializing all the required fields. See rte_pktmbuf_reset(). 903 | * For standard needs, prefer rte_pktmbuf_alloc(). 904 | * 905 | * The caller can expect that the following fields of the mbuf structure 906 | * are initialized: buf_addr, buf_iova, buf_len, refcnt=1, nb_segs=1, 907 | * next=NULL, pool, priv_size. The other fields must be initialized 908 | * by the caller. 909 | * 910 | * @param mp 911 | * The mempool from which mbuf is allocated. 912 | * @return 913 | * - The pointer to the new mbuf on success. 914 | * - NULL if allocation failed. 915 | */ 916 | static inline struct rte_mbuf *rte_mbuf_raw_alloc(struct rte_mempool *mp) 917 | { 918 | struct rte_mbuf *m; 919 | void *mb = NULL; 920 | 921 | if (rte_mempool_get(mp, &mb) < 0) 922 | return NULL; 923 | m = (struct rte_mbuf *)mb; 924 | MBUF_RAW_ALLOC_CHECK(m); 925 | return m; 926 | } 927 | 928 | /** 929 | * Put mbuf back into its original mempool. 930 | * 931 | * The caller must ensure that the mbuf is direct and properly 932 | * reinitialized (refcnt=1, next=NULL, nb_segs=1), as done by 933 | * rte_pktmbuf_prefree_seg(). 934 | * 935 | * This function should be used with care, when optimization is 936 | * required. For standard needs, prefer rte_pktmbuf_free() or 937 | * rte_pktmbuf_free_seg(). 938 | * 939 | * @param m 940 | * The mbuf to be freed. 941 | */ 942 | static __rte_always_inline void 943 | rte_mbuf_raw_free(struct rte_mbuf *m) 944 | { 945 | RTE_ASSERT(RTE_MBUF_DIRECT(m)); 946 | RTE_ASSERT(rte_mbuf_refcnt_read(m) == 1); 947 | RTE_ASSERT(m->next == NULL); 948 | RTE_ASSERT(m->nb_segs == 1); 949 | __rte_mbuf_sanity_check(m, 0); 950 | rte_mempool_put(m->pool, m); 951 | } 952 | 953 | /* compat with older versions */ 954 | __rte_deprecated 955 | static inline void 956 | __rte_mbuf_raw_free(struct rte_mbuf *m) 957 | { 958 | rte_mbuf_raw_free(m); 959 | } 960 | 961 | /* Operations on ctrl mbuf */ 962 | 963 | /** 964 | * The control mbuf constructor. 965 | * 966 | * This function initializes some fields in an mbuf structure that are 967 | * not modified by the user once created (mbuf type, origin pool, buffer 968 | * start address, and so on). This function is given as a callback function 969 | * to rte_mempool_obj_iter() or rte_mempool_create() at pool creation time. 970 | * 971 | * @param mp 972 | * The mempool from which the mbuf is allocated. 973 | * @param opaque_arg 974 | * A pointer that can be used by the user to retrieve useful information 975 | * for mbuf initialization. This pointer is the opaque argument passed to 976 | * rte_mempool_obj_iter() or rte_mempool_create(). 977 | * @param m 978 | * The mbuf to initialize. 979 | * @param i 980 | * The index of the mbuf in the pool table. 981 | */ 982 | void rte_ctrlmbuf_init(struct rte_mempool *mp, void *opaque_arg, 983 | void *m, unsigned i); 984 | 985 | /** 986 | * Allocate a new mbuf (type is ctrl) from mempool *mp*. 987 | * 988 | * This new mbuf is initialized with data pointing to the beginning of 989 | * buffer, and with a length of zero. 990 | * 991 | * @param mp 992 | * The mempool from which the mbuf is allocated. 993 | * @return 994 | * - The pointer to the new mbuf on success. 995 | * - NULL if allocation failed. 996 | */ 997 | #define rte_ctrlmbuf_alloc(mp) rte_pktmbuf_alloc(mp) 998 | 999 | /** 1000 | * Free a control mbuf back into its original mempool. 1001 | * 1002 | * @param m 1003 | * The control mbuf to be freed. 1004 | */ 1005 | #define rte_ctrlmbuf_free(m) rte_pktmbuf_free(m) 1006 | 1007 | /** 1008 | * A macro that returns the pointer to the carried data. 1009 | * 1010 | * The value that can be read or assigned. 1011 | * 1012 | * @param m 1013 | * The control mbuf. 1014 | */ 1015 | #define rte_ctrlmbuf_data(m) ((char *)((m)->buf_addr) + (m)->data_off) 1016 | 1017 | /** 1018 | * A macro that returns the length of the carried data. 1019 | * 1020 | * The value that can be read or assigned. 1021 | * 1022 | * @param m 1023 | * The control mbuf. 1024 | */ 1025 | #define rte_ctrlmbuf_len(m) rte_pktmbuf_data_len(m) 1026 | 1027 | /** 1028 | * Tests if an mbuf is a control mbuf 1029 | * 1030 | * @param m 1031 | * The mbuf to be tested 1032 | * @return 1033 | * - True (1) if the mbuf is a control mbuf 1034 | * - False(0) otherwise 1035 | */ 1036 | static inline int 1037 | rte_is_ctrlmbuf(struct rte_mbuf *m) 1038 | { 1039 | return !!(m->ol_flags & CTRL_MBUF_FLAG); 1040 | } 1041 | 1042 | /* Operations on pkt mbuf */ 1043 | 1044 | /** 1045 | * The packet mbuf constructor. 1046 | * 1047 | * This function initializes some fields in the mbuf structure that are 1048 | * not modified by the user once created (origin pool, buffer start 1049 | * address, and so on). This function is given as a callback function to 1050 | * rte_mempool_obj_iter() or rte_mempool_create() at pool creation time. 1051 | * 1052 | * @param mp 1053 | * The mempool from which mbufs originate. 1054 | * @param opaque_arg 1055 | * A pointer that can be used by the user to retrieve useful information 1056 | * for mbuf initialization. This pointer is the opaque argument passed to 1057 | * rte_mempool_obj_iter() or rte_mempool_create(). 1058 | * @param m 1059 | * The mbuf to initialize. 1060 | * @param i 1061 | * The index of the mbuf in the pool table. 1062 | */ 1063 | void rte_pktmbuf_init(struct rte_mempool *mp, void *opaque_arg, 1064 | void *m, unsigned i); 1065 | 1066 | 1067 | /** 1068 | * A packet mbuf pool constructor. 1069 | * 1070 | * This function initializes the mempool private data in the case of a 1071 | * pktmbuf pool. This private data is needed by the driver. The 1072 | * function must be called on the mempool before it is used, or it 1073 | * can be given as a callback function to rte_mempool_create() at 1074 | * pool creation. It can be extended by the user, for example, to 1075 | * provide another packet size. 1076 | * 1077 | * @param mp 1078 | * The mempool from which mbufs originate. 1079 | * @param opaque_arg 1080 | * A pointer that can be used by the user to retrieve useful information 1081 | * for mbuf initialization. This pointer is the opaque argument passed to 1082 | * rte_mempool_create(). 1083 | */ 1084 | void rte_pktmbuf_pool_init(struct rte_mempool *mp, void *opaque_arg); 1085 | 1086 | /** 1087 | * Create a mbuf pool. 1088 | * 1089 | * This function creates and initializes a packet mbuf pool. It is 1090 | * a wrapper to rte_mempool functions. 1091 | * 1092 | * @param name 1093 | * The name of the mbuf pool. 1094 | * @param n 1095 | * The number of elements in the mbuf pool. The optimum size (in terms 1096 | * of memory usage) for a mempool is when n is a power of two minus one: 1097 | * n = (2^q - 1). 1098 | * @param cache_size 1099 | * Size of the per-core object cache. See rte_mempool_create() for 1100 | * details. 1101 | * @param priv_size 1102 | * Size of application private are between the rte_mbuf structure 1103 | * and the data buffer. This value must be aligned to RTE_MBUF_PRIV_ALIGN. 1104 | * @param data_room_size 1105 | * Size of data buffer in each mbuf, including RTE_PKTMBUF_HEADROOM. 1106 | * @param socket_id 1107 | * The socket identifier where the memory should be allocated. The 1108 | * value can be *SOCKET_ID_ANY* if there is no NUMA constraint for the 1109 | * reserved zone. 1110 | * @return 1111 | * The pointer to the new allocated mempool, on success. NULL on error 1112 | * with rte_errno set appropriately. Possible rte_errno values include: 1113 | * - E_RTE_NO_CONFIG - function could not get pointer to rte_config structure 1114 | * - E_RTE_SECONDARY - function was called from a secondary process instance 1115 | * - EINVAL - cache size provided is too large, or priv_size is not aligned. 1116 | * - ENOSPC - the maximum number of memzones has already been allocated 1117 | * - EEXIST - a memzone with the same name already exists 1118 | * - ENOMEM - no appropriate memory area found in which to create memzone 1119 | */ 1120 | struct rte_mempool * 1121 | rte_pktmbuf_pool_create(const char *name, unsigned n, 1122 | unsigned cache_size, uint16_t priv_size, uint16_t data_room_size, 1123 | int socket_id); 1124 | 1125 | /** 1126 | * Get the data room size of mbufs stored in a pktmbuf_pool 1127 | * 1128 | * The data room size is the amount of data that can be stored in a 1129 | * mbuf including the headroom (RTE_PKTMBUF_HEADROOM). 1130 | * 1131 | * @param mp 1132 | * The packet mbuf pool. 1133 | * @return 1134 | * The data room size of mbufs stored in this mempool. 1135 | */ 1136 | static inline uint16_t 1137 | rte_pktmbuf_data_room_size(struct rte_mempool *mp) 1138 | { 1139 | struct rte_pktmbuf_pool_private *mbp_priv; 1140 | 1141 | mbp_priv = (struct rte_pktmbuf_pool_private *)rte_mempool_get_priv(mp); 1142 | return mbp_priv->mbuf_data_room_size; 1143 | } 1144 | 1145 | /** 1146 | * Get the application private size of mbufs stored in a pktmbuf_pool 1147 | * 1148 | * The private size of mbuf is a zone located between the rte_mbuf 1149 | * structure and the data buffer where an application can store data 1150 | * associated to a packet. 1151 | * 1152 | * @param mp 1153 | * The packet mbuf pool. 1154 | * @return 1155 | * The private size of mbufs stored in this mempool. 1156 | */ 1157 | static inline uint16_t 1158 | rte_pktmbuf_priv_size(struct rte_mempool *mp) 1159 | { 1160 | struct rte_pktmbuf_pool_private *mbp_priv; 1161 | 1162 | mbp_priv = (struct rte_pktmbuf_pool_private *)rte_mempool_get_priv(mp); 1163 | return mbp_priv->mbuf_priv_size; 1164 | } 1165 | 1166 | /** 1167 | * Reset the data_off field of a packet mbuf to its default value. 1168 | * 1169 | * The given mbuf must have only one segment, which should be empty. 1170 | * 1171 | * @param m 1172 | * The packet mbuf's data_off field has to be reset. 1173 | */ 1174 | static inline void rte_pktmbuf_reset_headroom(struct rte_mbuf *m) 1175 | { 1176 | m->data_off = RTE_MIN(RTE_PKTMBUF_HEADROOM, (uint16_t)m->buf_len); 1177 | } 1178 | 1179 | /** 1180 | * Reset the fields of a packet mbuf to their default values. 1181 | * 1182 | * The given mbuf must have only one segment. 1183 | * 1184 | * @param m 1185 | * The packet mbuf to be resetted. 1186 | */ 1187 | #define MBUF_INVALID_PORT UINT16_MAX 1188 | 1189 | static inline void rte_pktmbuf_reset(struct rte_mbuf *m) 1190 | { 1191 | m->next = NULL; 1192 | m->pkt_len = 0; 1193 | m->tx_offload = 0; 1194 | m->vlan_tci = 0; 1195 | m->vlan_tci_outer = 0; 1196 | m->nb_segs = 1; 1197 | m->port = MBUF_INVALID_PORT; 1198 | 1199 | m->ol_flags = 0; 1200 | m->packet_type = 0; 1201 | rte_pktmbuf_reset_headroom(m); 1202 | 1203 | m->data_len = 0; 1204 | __rte_mbuf_sanity_check(m, 1); 1205 | } 1206 | 1207 | /** 1208 | * Allocate a new mbuf from a mempool. 1209 | * 1210 | * This new mbuf contains one segment, which has a length of 0. The pointer 1211 | * to data is initialized to have some bytes of headroom in the buffer 1212 | * (if buffer size allows). 1213 | * 1214 | * @param mp 1215 | * The mempool from which the mbuf is allocated. 1216 | * @return 1217 | * - The pointer to the new mbuf on success. 1218 | * - NULL if allocation failed. 1219 | */ 1220 | static inline struct rte_mbuf *rte_pktmbuf_alloc(struct rte_mempool *mp) 1221 | { 1222 | struct rte_mbuf *m; 1223 | if ((m = rte_mbuf_raw_alloc(mp)) != NULL) 1224 | rte_pktmbuf_reset(m); 1225 | return m; 1226 | } 1227 | 1228 | /** 1229 | * Allocate a bulk of mbufs, initialize refcnt and reset the fields to default 1230 | * values. 1231 | * 1232 | * @param pool 1233 | * The mempool from which mbufs are allocated. 1234 | * @param mbufs 1235 | * Array of pointers to mbufs 1236 | * @param count 1237 | * Array size 1238 | * @return 1239 | * - 0: Success 1240 | * - -ENOENT: Not enough entries in the mempool; no mbufs are retrieved. 1241 | */ 1242 | static inline int rte_pktmbuf_alloc_bulk(struct rte_mempool *pool, 1243 | struct rte_mbuf **mbufs, unsigned count) 1244 | { 1245 | unsigned idx = 0; 1246 | int rc; 1247 | 1248 | rc = rte_mempool_get_bulk(pool, (void **)mbufs, count); 1249 | if (unlikely(rc)) 1250 | return rc; 1251 | 1252 | /* To understand duff's device on loop unwinding optimization, see 1253 | * https://en.wikipedia.org/wiki/Duff's_device. 1254 | * Here while() loop is used rather than do() while{} to avoid extra 1255 | * check if count is zero. 1256 | */ 1257 | switch (count % 4) { 1258 | case 0: 1259 | while (idx != count) { 1260 | MBUF_RAW_ALLOC_CHECK(mbufs[idx]); 1261 | rte_pktmbuf_reset(mbufs[idx]); 1262 | idx++; 1263 | /* fall-through */ 1264 | case 3: 1265 | MBUF_RAW_ALLOC_CHECK(mbufs[idx]); 1266 | rte_pktmbuf_reset(mbufs[idx]); 1267 | idx++; 1268 | /* fall-through */ 1269 | case 2: 1270 | MBUF_RAW_ALLOC_CHECK(mbufs[idx]); 1271 | rte_pktmbuf_reset(mbufs[idx]); 1272 | idx++; 1273 | /* fall-through */ 1274 | case 1: 1275 | MBUF_RAW_ALLOC_CHECK(mbufs[idx]); 1276 | rte_pktmbuf_reset(mbufs[idx]); 1277 | idx++; 1278 | /* fall-through */ 1279 | } 1280 | } 1281 | return 0; 1282 | } 1283 | 1284 | /** 1285 | * Attach packet mbuf to another packet mbuf. 1286 | * 1287 | * After attachment we refer the mbuf we attached as 'indirect', 1288 | * while mbuf we attached to as 'direct'. 1289 | * The direct mbuf's reference counter is incremented. 1290 | * 1291 | * Right now, not supported: 1292 | * - attachment for already indirect mbuf (e.g. - mi has to be direct). 1293 | * - mbuf we trying to attach (mi) is used by someone else 1294 | * e.g. it's reference counter is greater then 1. 1295 | * 1296 | * @param mi 1297 | * The indirect packet mbuf. 1298 | * @param m 1299 | * The packet mbuf we're attaching to. 1300 | */ 1301 | static inline void rte_pktmbuf_attach(struct rte_mbuf *mi, struct rte_mbuf *m) 1302 | { 1303 | struct rte_mbuf *md; 1304 | 1305 | RTE_ASSERT(RTE_MBUF_DIRECT(mi) && 1306 | rte_mbuf_refcnt_read(mi) == 1); 1307 | 1308 | /* if m is not direct, get the mbuf that embeds the data */ 1309 | if (RTE_MBUF_DIRECT(m)) 1310 | md = m; 1311 | else 1312 | md = rte_mbuf_from_indirect(m); 1313 | 1314 | rte_mbuf_refcnt_update(md, 1); 1315 | mi->priv_size = m->priv_size; 1316 | mi->buf_iova = m->buf_iova; 1317 | mi->buf_addr = m->buf_addr; 1318 | mi->buf_len = m->buf_len; 1319 | 1320 | mi->data_off = m->data_off; 1321 | mi->data_len = m->data_len; 1322 | mi->port = m->port; 1323 | mi->vlan_tci = m->vlan_tci; 1324 | mi->vlan_tci_outer = m->vlan_tci_outer; 1325 | mi->tx_offload = m->tx_offload; 1326 | mi->hash = m->hash; 1327 | 1328 | mi->next = NULL; 1329 | mi->pkt_len = mi->data_len; 1330 | mi->nb_segs = 1; 1331 | mi->ol_flags = m->ol_flags | IND_ATTACHED_MBUF; 1332 | mi->packet_type = m->packet_type; 1333 | mi->timestamp = m->timestamp; 1334 | 1335 | __rte_mbuf_sanity_check(mi, 1); 1336 | __rte_mbuf_sanity_check(m, 0); 1337 | } 1338 | 1339 | /** 1340 | * Detach an indirect packet mbuf. 1341 | * 1342 | * - restore original mbuf address and length values. 1343 | * - reset pktmbuf data and data_len to their default values. 1344 | * - decrement the direct mbuf's reference counter. When the 1345 | * reference counter becomes 0, the direct mbuf is freed. 1346 | * 1347 | * All other fields of the given packet mbuf will be left intact. 1348 | * 1349 | * @param m 1350 | * The indirect attached packet mbuf. 1351 | */ 1352 | static inline void rte_pktmbuf_detach(struct rte_mbuf *m) 1353 | { 1354 | struct rte_mbuf *md = rte_mbuf_from_indirect(m); 1355 | struct rte_mempool *mp = m->pool; 1356 | uint32_t mbuf_size, buf_len, priv_size; 1357 | 1358 | priv_size = rte_pktmbuf_priv_size(mp); 1359 | mbuf_size = sizeof(struct rte_mbuf) + priv_size; 1360 | buf_len = rte_pktmbuf_data_room_size(mp); 1361 | 1362 | m->priv_size = priv_size; 1363 | m->buf_addr = (char *)m + mbuf_size; 1364 | m->buf_iova = rte_mempool_virt2iova(m) + mbuf_size; 1365 | m->buf_len = (uint16_t)buf_len; 1366 | rte_pktmbuf_reset_headroom(m); 1367 | m->data_len = 0; 1368 | m->ol_flags = 0; 1369 | 1370 | if (rte_mbuf_refcnt_update(md, -1) == 0) { 1371 | md->next = NULL; 1372 | md->nb_segs = 1; 1373 | rte_mbuf_refcnt_set(md, 1); 1374 | rte_mbuf_raw_free(md); 1375 | } 1376 | } 1377 | 1378 | /** 1379 | * Decrease reference counter and unlink a mbuf segment 1380 | * 1381 | * This function does the same than a free, except that it does not 1382 | * return the segment to its pool. 1383 | * It decreases the reference counter, and if it reaches 0, it is 1384 | * detached from its parent for an indirect mbuf. 1385 | * 1386 | * @param m 1387 | * The mbuf to be unlinked 1388 | * @return 1389 | * - (m) if it is the last reference. It can be recycled or freed. 1390 | * - (NULL) if the mbuf still has remaining references on it. 1391 | */ 1392 | static __rte_always_inline struct rte_mbuf * 1393 | rte_pktmbuf_prefree_seg(struct rte_mbuf *m) 1394 | { 1395 | __rte_mbuf_sanity_check(m, 0); 1396 | 1397 | if (likely(rte_mbuf_refcnt_read(m) == 1)) { 1398 | 1399 | if (RTE_MBUF_INDIRECT(m)) 1400 | rte_pktmbuf_detach(m); 1401 | 1402 | if (m->next != NULL) { 1403 | m->next = NULL; 1404 | m->nb_segs = 1; 1405 | } 1406 | 1407 | return m; 1408 | 1409 | } else if (__rte_mbuf_refcnt_update(m, -1) == 0) { 1410 | 1411 | if (RTE_MBUF_INDIRECT(m)) 1412 | rte_pktmbuf_detach(m); 1413 | 1414 | if (m->next != NULL) { 1415 | m->next = NULL; 1416 | m->nb_segs = 1; 1417 | } 1418 | rte_mbuf_refcnt_set(m, 1); 1419 | 1420 | return m; 1421 | } 1422 | return NULL; 1423 | } 1424 | 1425 | /* deprecated, replaced by rte_pktmbuf_prefree_seg() */ 1426 | __rte_deprecated 1427 | static inline struct rte_mbuf * 1428 | __rte_pktmbuf_prefree_seg(struct rte_mbuf *m) 1429 | { 1430 | return rte_pktmbuf_prefree_seg(m); 1431 | } 1432 | 1433 | /** 1434 | * Free a segment of a packet mbuf into its original mempool. 1435 | * 1436 | * Free an mbuf, without parsing other segments in case of chained 1437 | * buffers. 1438 | * 1439 | * @param m 1440 | * The packet mbuf segment to be freed. 1441 | */ 1442 | static __rte_always_inline void 1443 | rte_pktmbuf_free_seg(struct rte_mbuf *m) 1444 | { 1445 | m = rte_pktmbuf_prefree_seg(m); 1446 | if (likely(m != NULL)) 1447 | rte_mbuf_raw_free(m); 1448 | } 1449 | 1450 | /** 1451 | * Free a packet mbuf back into its original mempool. 1452 | * 1453 | * Free an mbuf, and all its segments in case of chained buffers. Each 1454 | * segment is added back into its original mempool. 1455 | * 1456 | * @param m 1457 | * The packet mbuf to be freed. If NULL, the function does nothing. 1458 | */ 1459 | static inline void rte_pktmbuf_free(struct rte_mbuf *m) 1460 | { 1461 | struct rte_mbuf *m_next; 1462 | 1463 | if (m != NULL) 1464 | __rte_mbuf_sanity_check(m, 1); 1465 | 1466 | while (m != NULL) { 1467 | m_next = m->next; 1468 | rte_pktmbuf_free_seg(m); 1469 | m = m_next; 1470 | } 1471 | } 1472 | 1473 | /** 1474 | * Creates a "clone" of the given packet mbuf. 1475 | * 1476 | * Walks through all segments of the given packet mbuf, and for each of them: 1477 | * - Creates a new packet mbuf from the given pool. 1478 | * - Attaches newly created mbuf to the segment. 1479 | * Then updates pkt_len and nb_segs of the "clone" packet mbuf to match values 1480 | * from the original packet mbuf. 1481 | * 1482 | * @param md 1483 | * The packet mbuf to be cloned. 1484 | * @param mp 1485 | * The mempool from which the "clone" mbufs are allocated. 1486 | * @return 1487 | * - The pointer to the new "clone" mbuf on success. 1488 | * - NULL if allocation fails. 1489 | */ 1490 | static inline struct rte_mbuf *rte_pktmbuf_clone(struct rte_mbuf *md, 1491 | struct rte_mempool *mp) 1492 | { 1493 | struct rte_mbuf *mc, *mi, **prev; 1494 | uint32_t pktlen; 1495 | uint16_t nseg; 1496 | 1497 | if (unlikely ((mc = rte_pktmbuf_alloc(mp)) == NULL)) 1498 | return NULL; 1499 | 1500 | mi = mc; 1501 | prev = &mi->next; 1502 | pktlen = md->pkt_len; 1503 | nseg = 0; 1504 | 1505 | do { 1506 | nseg++; 1507 | rte_pktmbuf_attach(mi, md); 1508 | *prev = mi; 1509 | prev = &mi->next; 1510 | } while ((md = md->next) != NULL && 1511 | (mi = rte_pktmbuf_alloc(mp)) != NULL); 1512 | 1513 | *prev = NULL; 1514 | mc->nb_segs = nseg; 1515 | mc->pkt_len = pktlen; 1516 | 1517 | /* Allocation of new indirect segment failed */ 1518 | if (unlikely (mi == NULL)) { 1519 | rte_pktmbuf_free(mc); 1520 | return NULL; 1521 | } 1522 | 1523 | __rte_mbuf_sanity_check(mc, 1); 1524 | return mc; 1525 | } 1526 | 1527 | /** 1528 | * Adds given value to the refcnt of all packet mbuf segments. 1529 | * 1530 | * Walks through all segments of given packet mbuf and for each of them 1531 | * invokes rte_mbuf_refcnt_update(). 1532 | * 1533 | * @param m 1534 | * The packet mbuf whose refcnt to be updated. 1535 | * @param v 1536 | * The value to add to the mbuf's segments refcnt. 1537 | */ 1538 | static inline void rte_pktmbuf_refcnt_update(struct rte_mbuf *m, int16_t v) 1539 | { 1540 | __rte_mbuf_sanity_check(m, 1); 1541 | 1542 | do { 1543 | rte_mbuf_refcnt_update(m, v); 1544 | } while ((m = m->next) != NULL); 1545 | } 1546 | 1547 | /** 1548 | * Get the headroom in a packet mbuf. 1549 | * 1550 | * @param m 1551 | * The packet mbuf. 1552 | * @return 1553 | * The length of the headroom. 1554 | */ 1555 | static inline uint16_t rte_pktmbuf_headroom(const struct rte_mbuf *m) 1556 | { 1557 | __rte_mbuf_sanity_check(m, 0); 1558 | return m->data_off; 1559 | } 1560 | 1561 | /** 1562 | * Get the tailroom of a packet mbuf. 1563 | * 1564 | * @param m 1565 | * The packet mbuf. 1566 | * @return 1567 | * The length of the tailroom. 1568 | */ 1569 | static inline uint16_t rte_pktmbuf_tailroom(const struct rte_mbuf *m) 1570 | { 1571 | __rte_mbuf_sanity_check(m, 0); 1572 | return (uint16_t)(m->buf_len - rte_pktmbuf_headroom(m) - 1573 | m->data_len); 1574 | } 1575 | 1576 | /** 1577 | * Get the last segment of the packet. 1578 | * 1579 | * @param m 1580 | * The packet mbuf. 1581 | * @return 1582 | * The last segment of the given mbuf. 1583 | */ 1584 | static inline struct rte_mbuf *rte_pktmbuf_lastseg(struct rte_mbuf *m) 1585 | { 1586 | struct rte_mbuf *m2 = (struct rte_mbuf *)m; 1587 | 1588 | __rte_mbuf_sanity_check(m, 1); 1589 | while (m2->next != NULL) 1590 | m2 = m2->next; 1591 | return m2; 1592 | } 1593 | 1594 | /** 1595 | * A macro that points to an offset into the data in the mbuf. 1596 | * 1597 | * The returned pointer is cast to type t. Before using this 1598 | * function, the user must ensure that the first segment is large 1599 | * enough to accommodate its data. 1600 | * 1601 | * @param m 1602 | * The packet mbuf. 1603 | * @param o 1604 | * The offset into the mbuf data. 1605 | * @param t 1606 | * The type to cast the result into. 1607 | */ 1608 | #define rte_pktmbuf_mtod_offset(m, t, o) \ 1609 | ((t)((char *)(m)->buf_addr + (m)->data_off + (o))) 1610 | 1611 | /** 1612 | * A macro that points to the start of the data in the mbuf. 1613 | * 1614 | * The returned pointer is cast to type t. Before using this 1615 | * function, the user must ensure that the first segment is large 1616 | * enough to accommodate its data. 1617 | * 1618 | * @param m 1619 | * The packet mbuf. 1620 | * @param t 1621 | * The type to cast the result into. 1622 | */ 1623 | #define rte_pktmbuf_mtod(m, t) rte_pktmbuf_mtod_offset(m, t, 0) 1624 | 1625 | /** 1626 | * A macro that returns the IO address that points to an offset of the 1627 | * start of the data in the mbuf 1628 | * 1629 | * @param m 1630 | * The packet mbuf. 1631 | * @param o 1632 | * The offset into the data to calculate address from. 1633 | */ 1634 | #define rte_pktmbuf_iova_offset(m, o) \ 1635 | (rte_iova_t)((m)->buf_iova + (m)->data_off + (o)) 1636 | 1637 | /* deprecated */ 1638 | #define rte_pktmbuf_mtophys_offset(m, o) \ 1639 | rte_pktmbuf_iova_offset(m, o) 1640 | 1641 | /** 1642 | * A macro that returns the IO address that points to the start of the 1643 | * data in the mbuf 1644 | * 1645 | * @param m 1646 | * The packet mbuf. 1647 | */ 1648 | #define rte_pktmbuf_iova(m) rte_pktmbuf_iova_offset(m, 0) 1649 | 1650 | /* deprecated */ 1651 | #define rte_pktmbuf_mtophys(m) rte_pktmbuf_iova(m) 1652 | 1653 | /** 1654 | * A macro that returns the length of the packet. 1655 | * 1656 | * The value can be read or assigned. 1657 | * 1658 | * @param m 1659 | * The packet mbuf. 1660 | */ 1661 | #define rte_pktmbuf_pkt_len(m) ((m)->pkt_len) 1662 | 1663 | /** 1664 | * A macro that returns the length of the segment. 1665 | * 1666 | * The value can be read or assigned. 1667 | * 1668 | * @param m 1669 | * The packet mbuf. 1670 | */ 1671 | #define rte_pktmbuf_data_len(m) ((m)->data_len) 1672 | 1673 | /** 1674 | * Prepend len bytes to an mbuf data area. 1675 | * 1676 | * Returns a pointer to the new 1677 | * data start address. If there is not enough headroom in the first 1678 | * segment, the function will return NULL, without modifying the mbuf. 1679 | * 1680 | * @param m 1681 | * The pkt mbuf. 1682 | * @param len 1683 | * The amount of data to prepend (in bytes). 1684 | * @return 1685 | * A pointer to the start of the newly prepended data, or 1686 | * NULL if there is not enough headroom space in the first segment 1687 | */ 1688 | static inline char *rte_pktmbuf_prepend(struct rte_mbuf *m, 1689 | uint16_t len) 1690 | { 1691 | __rte_mbuf_sanity_check(m, 1); 1692 | 1693 | if (unlikely(len > rte_pktmbuf_headroom(m))) 1694 | return NULL; 1695 | 1696 | m->data_off -= len; 1697 | m->data_len = (uint16_t)(m->data_len + len); 1698 | m->pkt_len = (m->pkt_len + len); 1699 | 1700 | return (char *)m->buf_addr + m->data_off; 1701 | } 1702 | 1703 | /** 1704 | * Append len bytes to an mbuf. 1705 | * 1706 | * Append len bytes to an mbuf and return a pointer to the start address 1707 | * of the added data. If there is not enough tailroom in the last 1708 | * segment, the function will return NULL, without modifying the mbuf. 1709 | * 1710 | * @param m 1711 | * The packet mbuf. 1712 | * @param len 1713 | * The amount of data to append (in bytes). 1714 | * @return 1715 | * A pointer to the start of the newly appended data, or 1716 | * NULL if there is not enough tailroom space in the last segment 1717 | */ 1718 | static inline char *rte_pktmbuf_append(struct rte_mbuf *m, uint16_t len) 1719 | { 1720 | void *tail; 1721 | struct rte_mbuf *m_last; 1722 | 1723 | __rte_mbuf_sanity_check(m, 1); 1724 | 1725 | m_last = rte_pktmbuf_lastseg(m); 1726 | if (unlikely(len > rte_pktmbuf_tailroom(m_last))) 1727 | return NULL; 1728 | 1729 | tail = (char *)m_last->buf_addr + m_last->data_off + m_last->data_len; 1730 | m_last->data_len = (uint16_t)(m_last->data_len + len); 1731 | m->pkt_len = (m->pkt_len + len); 1732 | return (char*) tail; 1733 | } 1734 | 1735 | /** 1736 | * Remove len bytes at the beginning of an mbuf. 1737 | * 1738 | * Returns a pointer to the start address of the new data area. If the 1739 | * length is greater than the length of the first segment, then the 1740 | * function will fail and return NULL, without modifying the mbuf. 1741 | * 1742 | * @param m 1743 | * The packet mbuf. 1744 | * @param len 1745 | * The amount of data to remove (in bytes). 1746 | * @return 1747 | * A pointer to the new start of the data. 1748 | */ 1749 | static inline char *rte_pktmbuf_adj(struct rte_mbuf *m, uint16_t len) 1750 | { 1751 | __rte_mbuf_sanity_check(m, 1); 1752 | 1753 | if (unlikely(len > m->data_len)) 1754 | return NULL; 1755 | 1756 | m->data_len = (uint16_t)(m->data_len - len); 1757 | m->data_off += len; 1758 | m->pkt_len = (m->pkt_len - len); 1759 | return (char *)m->buf_addr + m->data_off; 1760 | } 1761 | 1762 | /** 1763 | * Remove len bytes of data at the end of the mbuf. 1764 | * 1765 | * If the length is greater than the length of the last segment, the 1766 | * function will fail and return -1 without modifying the mbuf. 1767 | * 1768 | * @param m 1769 | * The packet mbuf. 1770 | * @param len 1771 | * The amount of data to remove (in bytes). 1772 | * @return 1773 | * - 0: On success. 1774 | * - -1: On error. 1775 | */ 1776 | static inline int rte_pktmbuf_trim(struct rte_mbuf *m, uint16_t len) 1777 | { 1778 | struct rte_mbuf *m_last; 1779 | 1780 | __rte_mbuf_sanity_check(m, 1); 1781 | 1782 | m_last = rte_pktmbuf_lastseg(m); 1783 | if (unlikely(len > m_last->data_len)) 1784 | return -1; 1785 | 1786 | m_last->data_len = (uint16_t)(m_last->data_len - len); 1787 | m->pkt_len = (m->pkt_len - len); 1788 | return 0; 1789 | } 1790 | 1791 | /** 1792 | * Test if mbuf data is contiguous. 1793 | * 1794 | * @param m 1795 | * The packet mbuf. 1796 | * @return 1797 | * - 1, if all data is contiguous (one segment). 1798 | * - 0, if there is several segments. 1799 | */ 1800 | static inline int rte_pktmbuf_is_contiguous(const struct rte_mbuf *m) 1801 | { 1802 | __rte_mbuf_sanity_check(m, 1); 1803 | return !!(m->nb_segs == 1); 1804 | } 1805 | 1806 | /** 1807 | * @internal used by rte_pktmbuf_read(). 1808 | */ 1809 | const void *__rte_pktmbuf_read(const struct rte_mbuf *m, uint32_t off, 1810 | uint32_t len, void *buf); 1811 | 1812 | /** 1813 | * Read len data bytes in a mbuf at specified offset. 1814 | * 1815 | * If the data is contiguous, return the pointer in the mbuf data, else 1816 | * copy the data in the buffer provided by the user and return its 1817 | * pointer. 1818 | * 1819 | * @param m 1820 | * The pointer to the mbuf. 1821 | * @param off 1822 | * The offset of the data in the mbuf. 1823 | * @param len 1824 | * The amount of bytes to read. 1825 | * @param buf 1826 | * The buffer where data is copied if it is not contiguous in mbuf 1827 | * data. Its length should be at least equal to the len parameter. 1828 | * @return 1829 | * The pointer to the data, either in the mbuf if it is contiguous, 1830 | * or in the user buffer. If mbuf is too small, NULL is returned. 1831 | */ 1832 | static inline const void *rte_pktmbuf_read(const struct rte_mbuf *m, 1833 | uint32_t off, uint32_t len, void *buf) 1834 | { 1835 | if (likely(off + len <= rte_pktmbuf_data_len(m))) 1836 | return rte_pktmbuf_mtod_offset(m, char *, off); 1837 | else 1838 | return __rte_pktmbuf_read(m, off, len, buf); 1839 | } 1840 | 1841 | /** 1842 | * Chain an mbuf to another, thereby creating a segmented packet. 1843 | * 1844 | * Note: The implementation will do a linear walk over the segments to find 1845 | * the tail entry. For cases when there are many segments, it's better to 1846 | * chain the entries manually. 1847 | * 1848 | * @param head 1849 | * The head of the mbuf chain (the first packet) 1850 | * @param tail 1851 | * The mbuf to put last in the chain 1852 | * 1853 | * @return 1854 | * - 0, on success. 1855 | * - -EOVERFLOW, if the chain segment limit exceeded 1856 | */ 1857 | static inline int rte_pktmbuf_chain(struct rte_mbuf *head, struct rte_mbuf *tail) 1858 | { 1859 | struct rte_mbuf *cur_tail; 1860 | 1861 | /* Check for number-of-segments-overflow */ 1862 | if (head->nb_segs + tail->nb_segs > RTE_MBUF_MAX_NB_SEGS) 1863 | return -EOVERFLOW; 1864 | 1865 | /* Chain 'tail' onto the old tail */ 1866 | cur_tail = rte_pktmbuf_lastseg(head); 1867 | cur_tail->next = tail; 1868 | 1869 | /* accumulate number of segments and total length. */ 1870 | head->nb_segs += tail->nb_segs; 1871 | head->pkt_len += tail->pkt_len; 1872 | 1873 | /* pkt_len is only set in the head */ 1874 | tail->pkt_len = tail->data_len; 1875 | 1876 | return 0; 1877 | } 1878 | 1879 | /** 1880 | * Validate general requirements for Tx offload in mbuf. 1881 | * 1882 | * This function checks correctness and completeness of Tx offload settings. 1883 | * 1884 | * @param m 1885 | * The packet mbuf to be validated. 1886 | * @return 1887 | * 0 if packet is valid 1888 | */ 1889 | static inline int 1890 | rte_validate_tx_offload(const struct rte_mbuf *m) 1891 | { 1892 | uint64_t ol_flags = m->ol_flags; 1893 | uint64_t inner_l3_offset = m->l2_len; 1894 | 1895 | /* Does packet set any of available offloads? */ 1896 | if (!(ol_flags & PKT_TX_OFFLOAD_MASK)) 1897 | return 0; 1898 | 1899 | if (ol_flags & PKT_TX_OUTER_IP_CKSUM) 1900 | inner_l3_offset += m->outer_l2_len + m->outer_l3_len; 1901 | 1902 | /* Headers are fragmented */ 1903 | if (rte_pktmbuf_data_len(m) < inner_l3_offset + m->l3_len + m->l4_len) 1904 | return -ENOTSUP; 1905 | 1906 | /* IP checksum can be counted only for IPv4 packet */ 1907 | if ((ol_flags & PKT_TX_IP_CKSUM) && (ol_flags & PKT_TX_IPV6)) 1908 | return -EINVAL; 1909 | 1910 | /* IP type not set when required */ 1911 | if (ol_flags & (PKT_TX_L4_MASK | PKT_TX_TCP_SEG)) 1912 | if (!(ol_flags & (PKT_TX_IPV4 | PKT_TX_IPV6))) 1913 | return -EINVAL; 1914 | 1915 | /* Check requirements for TSO packet */ 1916 | if (ol_flags & PKT_TX_TCP_SEG) 1917 | if ((m->tso_segsz == 0) || 1918 | ((ol_flags & PKT_TX_IPV4) && 1919 | !(ol_flags & PKT_TX_IP_CKSUM))) 1920 | return -EINVAL; 1921 | 1922 | /* PKT_TX_OUTER_IP_CKSUM set for non outer IPv4 packet. */ 1923 | if ((ol_flags & PKT_TX_OUTER_IP_CKSUM) && 1924 | !(ol_flags & PKT_TX_OUTER_IPV4)) 1925 | return -EINVAL; 1926 | 1927 | return 0; 1928 | } 1929 | 1930 | /** 1931 | * Linearize data in mbuf. 1932 | * 1933 | * This function moves the mbuf data in the first segment if there is enough 1934 | * tailroom. The subsequent segments are unchained and freed. 1935 | * 1936 | * @param mbuf 1937 | * mbuf to linearize 1938 | * @return 1939 | * - 0, on success 1940 | * - -1, on error 1941 | */ 1942 | static inline int 1943 | rte_pktmbuf_linearize(struct rte_mbuf *mbuf) 1944 | { 1945 | int seg_len, copy_len; 1946 | struct rte_mbuf *m; 1947 | struct rte_mbuf *m_next; 1948 | char *buffer; 1949 | 1950 | if (rte_pktmbuf_is_contiguous(mbuf)) 1951 | return 0; 1952 | 1953 | /* Extend first segment to the total packet length */ 1954 | copy_len = rte_pktmbuf_pkt_len(mbuf) - rte_pktmbuf_data_len(mbuf); 1955 | 1956 | if (unlikely(copy_len > rte_pktmbuf_tailroom(mbuf))) 1957 | return -1; 1958 | 1959 | buffer = rte_pktmbuf_mtod_offset(mbuf, char *, mbuf->data_len); 1960 | mbuf->data_len = (uint16_t)(mbuf->pkt_len); 1961 | 1962 | /* Append data from next segments to the first one */ 1963 | m = mbuf->next; 1964 | while (m != NULL) { 1965 | m_next = m->next; 1966 | 1967 | seg_len = rte_pktmbuf_data_len(m); 1968 | rte_memcpy(buffer, rte_pktmbuf_mtod(m, char *), seg_len); 1969 | buffer += seg_len; 1970 | 1971 | rte_pktmbuf_free_seg(m); 1972 | m = m_next; 1973 | } 1974 | 1975 | mbuf->next = NULL; 1976 | mbuf->nb_segs = 1; 1977 | 1978 | return 0; 1979 | } 1980 | 1981 | /** 1982 | * Dump an mbuf structure to a file. 1983 | * 1984 | * Dump all fields for the given packet mbuf and all its associated 1985 | * segments (in the case of a chained buffer). 1986 | * 1987 | * @param f 1988 | * A pointer to a file for output 1989 | * @param m 1990 | * The packet mbuf. 1991 | * @param dump_len 1992 | * If dump_len != 0, also dump the "dump_len" first data bytes of 1993 | * the packet. 1994 | */ 1995 | void rte_pktmbuf_dump(FILE *f, const struct rte_mbuf *m, unsigned dump_len); 1996 | 1997 | #ifdef __cplusplus 1998 | } 1999 | #endif 2000 | 2001 | #endif /* _RTE_MBUF_H_ */ 2002 | --------------------------------------------------------------------------------