From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: Received: from mga03.intel.com (mga03.intel.com [134.134.136.65]) by dpdk.org (Postfix) with ESMTP id 479891B608 for ; Fri, 29 Jun 2018 18:58:19 +0200 (CEST) X-Amp-Result: SKIPPED(no attachment in message) X-Amp-File-Uploaded: False Received: from orsmga002.jf.intel.com ([10.7.209.21]) by orsmga103.jf.intel.com with ESMTP/TLS/DHE-RSA-AES256-GCM-SHA384; 29 Jun 2018 09:58:18 -0700 X-ExtLoop1: 1 X-IronPort-AV: E=Sophos;i="5.51,286,1526367600"; d="scan'208";a="71051434" Received: from irsmsx154.ger.corp.intel.com ([163.33.192.96]) by orsmga002.jf.intel.com with ESMTP; 29 Jun 2018 09:58:14 -0700 Received: from irsmsx111.ger.corp.intel.com (10.108.20.4) by IRSMSX154.ger.corp.intel.com (163.33.192.96) with Microsoft SMTP Server (TLS) id 14.3.319.2; Fri, 29 Jun 2018 17:58:13 +0100 Received: from irsmsx105.ger.corp.intel.com ([169.254.7.126]) by irsmsx111.ger.corp.intel.com ([169.254.2.230]) with mapi id 14.03.0319.002; Fri, 29 Jun 2018 17:58:13 +0100 From: "Ananyev, Konstantin" To: Cody Doucette , "Dumitrescu, Cristian" CC: "dev@dpdk.org" , "michel@digirati.com.br" , Qiaobin Fu Thread-Topic: [PATCH] ip_frag: extend rte_ipv6_frag_get_ipv6_fragment_header() Thread-Index: AQHUDbilYm9ryW6X9EyCTqi6lBk+QqR3eFYA Date: Fri, 29 Jun 2018 16:58:12 +0000 Message-ID: <2601191342CEEE43887BDE71AB977258C0C45010@irsmsx105.ger.corp.intel.com> References: <20180627014417.84133-1-doucette@bu.edu> In-Reply-To: <20180627014417.84133-1-doucette@bu.edu> Accept-Language: en-IE, en-US Content-Language: en-US X-MS-Has-Attach: X-MS-TNEF-Correlator: x-titus-metadata-40: eyJDYXRlZ29yeUxhYmVscyI6IiIsIk1ldGFkYXRhIjp7Im5zIjoiaHR0cDpcL1wvd3d3LnRpdHVzLmNvbVwvbnNcL0ludGVsMyIsImlkIjoiMDBkNGJmY2QtYmI4Mi00ZTZjLTg3NDMtYWU4ZGY1OTJiOTdhIiwicHJvcHMiOlt7Im4iOiJDVFBDbGFzc2lmaWNhdGlvbiIsInZhbHMiOlt7InZhbHVlIjoiQ1RQX05UIn1dfV19LCJTdWJqZWN0TGFiZWxzIjpbXSwiVE1DVmVyc2lvbiI6IjE3LjEwLjE4MDQuNDkiLCJUcnVzdGVkTGFiZWxIYXNoIjoiOVZtcnVoNVlJV1AzUnVZXC91Y2JcLzMzYW1JN3FFeGJcL20rWkE5bVkrazc0ZWlKMjU0WjNSdWxad2VsdjNKRGlUdyJ9 x-ctpclassification: CTP_NT dlp-product: dlpe-windows dlp-version: 11.0.200.100 dlp-reaction: no-action x-originating-ip: [163.33.239.180] Content-Type: text/plain; charset="us-ascii" Content-Transfer-Encoding: quoted-printable MIME-Version: 1.0 Subject: Re: [dpdk-dev] [PATCH] ip_frag: extend rte_ipv6_frag_get_ipv6_fragment_header() X-BeenThere: dev@dpdk.org X-Mailman-Version: 2.1.15 Precedence: list List-Id: DPDK patches and discussions List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , X-List-Received-Date: Fri, 29 Jun 2018 16:58:21 -0000 Hi,=20 >=20 > Extend rte_ipv6_frag_get_ipv6_fragment_header() to skip over any > other IPv6 extension headers when finding the fragment header. >=20 > According to RFC 8200, there is no guarantee that the IPv6 > Fragment extension header will come before any other extension > header, even though it is recommended. >=20 > Signed-off-by: Cody Doucette > Signed-off-by: Qiaobin Fu > Reviewed-by: Michel Machado > --- > examples/ip_reassembly/main.c | 6 ++- > lib/librte_ip_frag/rte_ip_frag.h | 41 ++++++++++++++------- > lib/librte_ip_frag/rte_ip_frag_version.map | 1 + > lib/librte_ip_frag/rte_ipv6_fragmentation.c | 38 +++++++++++++++++++ > lib/librte_ip_frag/rte_ipv6_reassembly.c | 4 +- > lib/librte_port/rte_port_ras.c | 6 ++- > 6 files changed, 77 insertions(+), 19 deletions(-) >=20 > diff --git a/examples/ip_reassembly/main.c b/examples/ip_reassembly/main.= c > index 3e8e79c21..13f2b04f1 100644 > --- a/examples/ip_reassembly/main.c > +++ b/examples/ip_reassembly/main.c > @@ -367,12 +367,14 @@ reassemble(struct rte_mbuf *m, uint16_t portid, uin= t32_t queue, > eth_hdr->ether_type =3D rte_be_to_cpu_16(ETHER_TYPE_IPv4); > } else if (RTE_ETH_IS_IPV6_HDR(m->packet_type)) { > /* if packet is IPv6 */ > - struct ipv6_extension_fragment *frag_hdr; > + const struct ipv6_extension_fragment *frag_hdr; > + struct ipv6_extension_fragment frag_hdr_buf; > struct ipv6_hdr *ip_hdr; >=20 > ip_hdr =3D (struct ipv6_hdr *)(eth_hdr + 1); >=20 > - frag_hdr =3D rte_ipv6_frag_get_ipv6_fragment_header(ip_hdr); > + frag_hdr =3D rte_ipv6_frag_get_ipv6_fragment_header(m, > + ip_hdr, &frag_hdr_buf); >=20 > if (frag_hdr !=3D NULL) { > struct rte_mbuf *mo; > diff --git a/lib/librte_ip_frag/rte_ip_frag.h b/lib/librte_ip_frag/rte_ip= _frag.h > index b3f3f78df..8884c8b31 100644 > --- a/lib/librte_ip_frag/rte_ip_frag.h > +++ b/lib/librte_ip_frag/rte_ip_frag.h > @@ -99,6 +99,12 @@ struct rte_ip_frag_tbl { > __extension__ struct ip_frag_pkt pkt[0]; /**< hash table. */ > }; >=20 > +/** IPv6 extension header */ > +struct ipv6_opt_hdr { > + uint8_t nexthdr; > + uint8_t hdrlen; > +} __attribute__((packed)); > + > /** IPv6 fragment extension header */ > #define RTE_IPV6_EHDR_MF_SHIFT 0 > #define RTE_IPV6_EHDR_MF_MASK 1 > @@ -208,28 +214,37 @@ rte_ipv6_fragment_packet(struct rte_mbuf *pkt_in, > struct rte_mbuf *rte_ipv6_frag_reassemble_packet(struct rte_ip_frag_tbl = *tbl, > struct rte_ip_frag_death_row *dr, > struct rte_mbuf *mb, uint64_t tms, struct ipv6_hdr *ip_hdr, > - struct ipv6_extension_fragment *frag_hdr); > + const struct ipv6_extension_fragment *frag_hdr); > + > +static inline int > +ipv6_ext_hdr(uint8_t nexthdr) > +{ > + /* Find out if nexthdr is an extension header or a protocol. */ > + return (nexthdr =3D=3D IPPROTO_HOPOPTS) || > + (nexthdr =3D=3D IPPROTO_ROUTING) || > + (nexthdr =3D=3D IPPROTO_FRAGMENT) || > + (nexthdr =3D=3D IPPROTO_AH) || > + (nexthdr =3D=3D IPPROTO_NONE) || > + (nexthdr =3D=3D IPPROTO_DSTOPTS); > +} >=20 > /** > * Return a pointer to the packet's fragment header, if found. > - * It only looks at the extension header that's right after the fixed IP= v6 > - * header, and doesn't follow the whole chain of extension headers. > * > - * @param hdr > + * @param pkt > + * Pointer to the mbuf of the packet. > + * @param ip_hdr > * Pointer to the IPv6 header. > + * @param frag_hdr > + * A pointer to the buffer where the fragment header > + * will be copied if it is not contiguous in mbuf data. > * @return > * Pointer to the IPv6 fragment extension header, or NULL if it's not > * present. > */ > -static inline struct ipv6_extension_fragment * > -rte_ipv6_frag_get_ipv6_fragment_header(struct ipv6_hdr *hdr) > -{ > - if (hdr->proto =3D=3D IPPROTO_FRAGMENT) { > - return (struct ipv6_extension_fragment *) ++hdr; > - } > - else > - return NULL; > -} > +const struct ipv6_extension_fragment *rte_ipv6_frag_get_ipv6_fragment_he= ader( > + struct rte_mbuf *pkt, const struct ipv6_hdr *ip_hdr, > + struct ipv6_extension_fragment *frag_hdr); >=20 > /** > * IPv4 fragmentation. > diff --git a/lib/librte_ip_frag/rte_ip_frag_version.map b/lib/librte_ip_f= rag/rte_ip_frag_version.map > index d1acf07cb..98fe4f2d4 100644 > --- a/lib/librte_ip_frag/rte_ip_frag_version.map > +++ b/lib/librte_ip_frag/rte_ip_frag_version.map > @@ -8,6 +8,7 @@ DPDK_2.0 { > rte_ipv4_fragment_packet; > rte_ipv6_frag_reassemble_packet; > rte_ipv6_fragment_packet; > + rte_ipv6_frag_get_ipv6_fragment_header; >=20 > local: *; > }; > diff --git a/lib/librte_ip_frag/rte_ipv6_fragmentation.c b/lib/librte_ip_= frag/rte_ipv6_fragmentation.c > index 62a7e4e83..bd847dd3d 100644 > --- a/lib/librte_ip_frag/rte_ipv6_fragmentation.c > +++ b/lib/librte_ip_frag/rte_ipv6_fragmentation.c > @@ -176,3 +176,41 @@ rte_ipv6_fragment_packet(struct rte_mbuf *pkt_in, >=20 > return out_pkt_pos; > } > + Just a generic thought - might be worse to move functions that parse ipv6 h= eader extentions and related strcutures into rte_net. I am sure they might be reused by some other code. > +const struct ipv6_extension_fragment * > +rte_ipv6_frag_get_ipv6_fragment_header(struct rte_mbuf *pkt, > + const struct ipv6_hdr *ip_hdr, > + struct ipv6_extension_fragment *frag_hdr) > +{ > + size_t offset =3D sizeof(struct ipv6_hdr); > + uint8_t nexthdr =3D ip_hdr->proto; > + > + while (ipv6_ext_hdr(nexthdr)) { > + struct ipv6_opt_hdr opt; > + const struct ipv6_opt_hdr *popt =3D rte_pktmbuf_read(pkt, > + offset, sizeof(opt), &opt); pktmbuf_read() is quite heavy-weight one. Do we really need it here? >>From my perspective - add an assumption that all whole IPv6 header will be = inside one segment seems reasonable enough. Konstantin=20 > + if (popt =3D=3D NULL) > + return NULL; > + > + switch (nexthdr) { > + case IPPROTO_NONE: > + return NULL; > + > + case IPPROTO_FRAGMENT: > + return rte_pktmbuf_read(pkt, offset, > + sizeof(*frag_hdr), frag_hdr); > + > + case IPPROTO_AH: > + offset +=3D (popt->hdrlen + 2) << 2; > + break; > + > + default: > + offset +=3D (popt->hdrlen + 1) << 3; > + break; > + } > + > + nexthdr =3D popt->nexthdr; > + } > + > + return NULL; > +} > diff --git a/lib/librte_ip_frag/rte_ipv6_reassembly.c b/lib/librte_ip_fra= g/rte_ipv6_reassembly.c > index db249fe60..b2d67a3f0 100644 > --- a/lib/librte_ip_frag/rte_ipv6_reassembly.c > +++ b/lib/librte_ip_frag/rte_ipv6_reassembly.c > @@ -135,8 +135,8 @@ ipv6_frag_reassemble(struct ip_frag_pkt *fp) > #define FRAG_OFFSET(x) (rte_cpu_to_be_16(x) >> 3) > struct rte_mbuf * > rte_ipv6_frag_reassemble_packet(struct rte_ip_frag_tbl *tbl, > - struct rte_ip_frag_death_row *dr, struct rte_mbuf *mb, uint64_t tms, > - struct ipv6_hdr *ip_hdr, struct ipv6_extension_fragment *frag_hdr) > + struct rte_ip_frag_death_row *dr, struct rte_mbuf *mb, uint64_t tms, > + struct ipv6_hdr *ip_hdr, const struct ipv6_extension_fragment *frag_hdr= ) > { > struct ip_frag_pkt *fp; > struct ip_frag_key key; > diff --git a/lib/librte_port/rte_port_ras.c b/lib/librte_port/rte_port_ra= s.c > index c8b2e19bf..28764f744 100644 > --- a/lib/librte_port/rte_port_ras.c > +++ b/lib/librte_port/rte_port_ras.c > @@ -184,9 +184,11 @@ process_ipv6(struct rte_port_ring_writer_ras *p, str= uct rte_mbuf *pkt) > /* Assume there is no ethernet header */ > struct ipv6_hdr *pkt_hdr =3D rte_pktmbuf_mtod(pkt, struct ipv6_hdr *); >=20 > - struct ipv6_extension_fragment *frag_hdr; > + const struct ipv6_extension_fragment *frag_hdr; > + struct ipv6_extension_fragment frag_hdr_buf; > uint16_t frag_data =3D 0; > - frag_hdr =3D rte_ipv6_frag_get_ipv6_fragment_header(pkt_hdr); > + frag_hdr =3D rte_ipv6_frag_get_ipv6_fragment_header(pkt, pkt_hdr, > + &frag_hdr_buf); > if (frag_hdr !=3D NULL) > frag_data =3D rte_be_to_cpu_16(frag_hdr->frag_data); >=20 > -- > 2.17.1