From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: Received: from mga06.intel.com (mga06.intel.com [134.134.136.31]) by dpdk.org (Postfix) with ESMTP id 4541AB62 for ; Wed, 31 Oct 2018 20:56:32 +0100 (CET) X-Amp-Result: SKIPPED(no attachment in message) X-Amp-File-Uploaded: False Received: from orsmga003.jf.intel.com ([10.7.209.27]) by orsmga104.jf.intel.com with ESMTP/TLS/DHE-RSA-AES256-GCM-SHA384; 31 Oct 2018 12:56:31 -0700 X-ExtLoop1: 1 X-IronPort-AV: E=Sophos;i="5.54,449,1534834800"; d="scan'208";a="96662478" Received: from irsmsx152.ger.corp.intel.com ([163.33.192.66]) by orsmga003.jf.intel.com with ESMTP; 31 Oct 2018 12:56:29 -0700 Received: from irsmsx105.ger.corp.intel.com ([169.254.7.144]) by IRSMSX152.ger.corp.intel.com ([169.254.6.64]) with mapi id 14.03.0415.000; Wed, 31 Oct 2018 19:56:29 +0000 From: "Ananyev, Konstantin" To: Cody Doucette , "Dumitrescu, Cristian" CC: "dev@dpdk.org" , Qiaobin Fu Thread-Topic: [PATCH v5 3/3] ip_frag: extend IPv6 fragment header retrieval Thread-Index: AQHUcMAKYvREPrZaCEWDMkZ0tcY8MKU5rYLA Date: Wed, 31 Oct 2018 19:56:28 +0000 Message-ID: <2601191342CEEE43887BDE71AB9772580103067027@irsmsx105.ger.corp.intel.com> References: <20181031021758.66752-1-doucette@bu.edu> <20181031021758.66752-4-doucette@bu.edu> In-Reply-To: <20181031021758.66752-4-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: eyJDYXRlZ29yeUxhYmVscyI6IiIsIk1ldGFkYXRhIjp7Im5zIjoiaHR0cDpcL1wvd3d3LnRpdHVzLmNvbVwvbnNcL0ludGVsMyIsImlkIjoiMGY5YjZkNDYtNTlkOS00ZjRhLTk0OWEtMzYxNmU3NDg0Yzk1IiwicHJvcHMiOlt7Im4iOiJDVFBDbGFzc2lmaWNhdGlvbiIsInZhbHMiOlt7InZhbHVlIjoiQ1RQX05UIn1dfV19LCJTdWJqZWN0TGFiZWxzIjpbXSwiVE1DVmVyc2lvbiI6IjE3LjEwLjE4MDQuNDkiLCJUcnVzdGVkTGFiZWxIYXNoIjoiRGxKZktXMlZPNFVGMkhaNHhxYjlWdzMwalZvc1RVRmdqd1wvRm1FU0dkV3VTU3JENmtla01kZHBNN1V3VzlDR3oifQ== x-ctpclassification: CTP_NT dlp-product: dlpe-windows dlp-version: 11.0.400.15 dlp-reaction: no-action x-originating-ip: [163.33.239.181] Content-Type: text/plain; charset="us-ascii" Content-Transfer-Encoding: quoted-printable MIME-Version: 1.0 Subject: Re: [dpdk-dev] [PATCH v5 3/3] ip_frag: extend IPv6 fragment header retrieval 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: Wed, 31 Oct 2018 19:56:33 -0000 Hi Cody, >=20 > Add the ability to parse IPv6 extenders to find the > IPv6 fragment header, and update callers. >=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 | 23 ++++++------- > 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, 59 insertions(+), 19 deletions(-) >=20 > diff --git a/examples/ip_reassembly/main.c b/examples/ip_reassembly/main.= c > index 17b55d4c7..3a827bd6c 100644 > --- a/examples/ip_reassembly/main.c > +++ b/examples/ip_reassembly/main.c > @@ -365,12 +365,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); I looked at the patch once again, and it seems incomplete to me. Sorry for late comments. Yes, right now te_ipv6_frag_get_ipv6_fragment_header can properly retrieve ipv6 fragment info, but it is not enough to make things work for situation when we have packet with frag header not the first and only extension header. In the same function, few lines below, we setup l3_len based on that assump= tion: m->l3_len =3D sizeof(*ip_hdr) + sizeof(*frag_hdr); mo =3D rte_ipv6_frag_reassemble_packet(tbl, dr, m, tms, ip_hdr, frag_hdr); And inside rte_ipv6_frag_reassemble_packet() we still assume the same: ... frag_hdr =3D (struct ipv6_extension_fragment *) (ip_hdr + 1); ip_hdr->proto =3D frag_hdr->next_header; I think we need a function that would allow us to get offset of frag_hdr.=20 Actually probably we can have a generic one here, that can return offset fo= r any requested ext header or total length of ipv6 header. Something like that: struct rte_ipv6_get_xhdr_ofs { uint16_t find_proto; /* header proto to find */ uint16_t next_proto; /* next header proto */ uint32_t next_ofs; /* offset to start search */ }; struct int=20 rte_ipv6_get_xhdr_ofs(struct rte_mbuf *pkt, rte_ipv6_get_xhdr_ofs *find);=20 that would go through ipv6 ext headers till either requested proto is found= , or end of IPv6 header.=20 Then user can do something like that: /* find fragment extention */ ipv6_get_xhdr_ofs ofs =3D { .find_proto =3D IPPROTO_FRAGMENT, .next_proto =3D ipv6_hdr->proto, .ofs =3D sizeof(struct ipv6_hdr), }; rc =3D rte_ipv6_get_xhdr_ofs(pkt, &ofs); if(rc =3D=3D 0)=20 frag_hdr =3D rte_pktmbuf_mtod_offset(m, .., ofs.ofs); ... =20 /* get size of IPv6 header plus all known extensions */ ipv6_get_xhdr_ofs ofs =3D { .find_proto =3D IPPROTO_MAX, .next_proto =3D ipv6_hdr->proto, .ofs =3D sizeof(struct ipv6_hdr), }; rc =3D rte_ipv6_get_xhdr_ofs(pkt, &ofs); =20 >=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 7f425f610..6fc8106bc 100644 > --- a/lib/librte_ip_frag/rte_ip_frag.h > +++ b/lib/librte_ip_frag/rte_ip_frag.h > @@ -211,28 +211,25 @@ 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); >=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); Another thing - wouldn't it be ab API/ABI breakage? One more question - making it non-inline - how much it would affect perfor= mance? My guess - no big difference, but did you check? Konstantin >=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 d40d5515f..8b4c82d08 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; > } > + > +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); > + 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