From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: Received: from relay61.bu.edu (relay61.bu.edu [128.197.228.61]) by dpdk.org (Postfix) with ESMTP id EF9303DC for ; Mon, 20 Aug 2018 21:32:12 +0200 (CEST) X-Envelope-From: doucette@bu.edu Received: from mail-wr1-f72.google.com (mail-wr1-f72.google.com [209.85.221.72]) by relay61.bu.edu (8.14.3/8.14.3) with ESMTP id w7KJVYAU032732 for ; Mon, 20 Aug 2018 15:31:35 -0400 Received: by mail-wr1-f72.google.com with SMTP id y22-v6so4334065wrd.13 for ; Mon, 20 Aug 2018 12:31:35 -0700 (PDT) X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20161025; h=x-gm-message-state:mime-version:in-reply-to:references:from:date :message-id:subject:to:cc; bh=4A7+S0xuVo6jQ1Un5vifM/0Bo3+esWm9h5RLcZDriow=; b=UBKgYAi8/8riLFAXTukE6sZRKzM/H8ELGaa4sSeHcxPx2OGs/1eb/EhwURKxi2pKNu vWDBXSfmOk/WjzoeUaayXQyPVbgzhJEP49PWp3bA0mz0ualO8jNv4Dn2U9goP+azLd0/ bVdhpwXMYpnrzDQpRlg4aFaEJZ+mvz/CTGkD92w6EJf6BVMD80RjTuZ+XJj1LRFBl5ON KWWC/qdhwfEvdmAATMUQLPYsGap8zOTblQThYRdAjAOV3J3/Bvk97EW1fc/rSXU8W6LA rTfFlZA8B2k55cBpQ7seol7WdGdEmb+rVAkSgLngJRkc8X+yzFz6j0GWiOArJAK3jbUi 1Nqg== X-Gm-Message-State: AOUpUlFmaRZUR6kydIJSEJaNkQime7ZEQ0T2t43In8ltbN1AM0LCtJE2 0Mn7/hZtOcJ4FNGCH0LSlqRHz14EmbOmWDR7AJyfuPtEMvZB4rxFuerFzjsxwJMyiMrJBSO9wEc dj6H/Rjt7aYHaI/MPBa2q X-Received: by 2002:a1c:8f50:: with SMTP id r77-v6mr27473420wmd.44.1534793494380; Mon, 20 Aug 2018 12:31:34 -0700 (PDT) X-Google-Smtp-Source: AA+uWPwJ5agJsb5WgFOAY4HlntGoogkL4qjICxXSF0xZwrgvAcj26LL19sx2TZUlDyzJixEWDmTTmsEEhvfIAlmYZM4= X-Received: by 2002:a1c:8f50:: with SMTP id r77-v6mr27473408wmd.44.1534793493929; Mon, 20 Aug 2018 12:31:33 -0700 (PDT) MIME-Version: 1.0 Received: by 2002:a1c:b92:0:0:0:0:0 with HTTP; Mon, 20 Aug 2018 12:31:33 -0700 (PDT) In-Reply-To: <20180727135243.147744-1-doucette@bu.edu> References: <20180727135243.147744-1-doucette@bu.edu> From: Cody Doucette Date: Mon, 20 Aug 2018 15:31:33 -0400 Message-ID: To: Gaetan Rivet , Konstantin Ananyev , Olivier Matz , Cristian Dumitrescu Cc: dev@dpdk.org, Michel Machado , Cody Doucette , Qiaobin Fu Content-Type: text/plain; charset="UTF-8" X-Content-Filtered-By: Mailman/MimeDel 2.1.15 Subject: Re: [dpdk-dev] [PATCH v3] 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: Mon, 20 Aug 2018 19:32:13 -0000 Re-upping for review. Thanks, Cody On Fri, Jul 27, 2018 at 9:52 AM, Cody Doucette wrote: > Extend rte_ipv6_frag_get_ipv6_fragment_header() to skip over any > other IPv6 extension headers when finding the fragment header. > > 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. > > Signed-off-by: Cody Doucette > Signed-off-by: Qiaobin Fu > Reviewed-by: Michel Machado > --- > v3: > * Removed compilation flag D_XOPEN_SOURCE=700 from the > failsafe driver to allow compilation on freebsd. > > v2: > * Moved IPv6 extension header definitions to lib_net. > > drivers/net/failsafe/Makefile | 1 - > drivers/net/failsafe/meson.build | 1 - > 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_net/rte_ip.h | 27 +++++++++++++++ > lib/librte_port/rte_port_ras.c | 6 ++-- > 9 files changed, 86 insertions(+), 21 deletions(-) > > diff --git a/drivers/net/failsafe/Makefile b/drivers/net/failsafe/Makefile > index 81802d092..eb9292425 100644 > --- a/drivers/net/failsafe/Makefile > +++ b/drivers/net/failsafe/Makefile > @@ -34,7 +34,6 @@ CFLAGS += -std=gnu99 -Wextra > CFLAGS += -O3 > CFLAGS += -I. > CFLAGS += -D_DEFAULT_SOURCE > -CFLAGS += -D_XOPEN_SOURCE=700 > CFLAGS += $(WERROR_FLAGS) > CFLAGS += -Wno-strict-prototypes > CFLAGS += -pedantic > diff --git a/drivers/net/failsafe/meson.build > b/drivers/net/failsafe/meson.build > index a249ff4af..d47a52acd 100644 > --- a/drivers/net/failsafe/meson.build > +++ b/drivers/net/failsafe/meson.build > @@ -3,7 +3,6 @@ > > cflags += '-std=gnu99' > cflags += '-D_DEFAULT_SOURCE' > -cflags += '-D_XOPEN_SOURCE=700' > cflags += '-pedantic' > if host_machine.system() == 'linux' > cflags += '-DLINUX' > diff --git a/examples/ip_reassembly/main.c b/examples/ip_reassembly/main.c > index b830f67a5..58c388708 100644 > --- a/examples/ip_reassembly/main.c > +++ b/examples/ip_reassembly/main.c > @@ -366,12 +366,14 @@ reassemble(struct rte_mbuf *m, uint16_t portid, > uint32_t queue, > eth_hdr->ether_type = 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; > > ip_hdr = (struct ipv6_hdr *)(eth_hdr + 1); > > - frag_hdr = rte_ipv6_frag_get_ipv6_fragment_header(ip_hdr); > + frag_hdr = rte_ipv6_frag_get_ipv6_fragment_header(m, > + ip_hdr, &frag_hdr_buf); > > if (frag_hdr != 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..bd6f02a16 100644 > --- a/lib/librte_ip_frag/rte_ip_frag.h > +++ b/lib/librte_ip_frag/rte_ip_frag.h > @@ -208,28 +208,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); > > /** > * Return a pointer to the packet's fragment header, if found. > - * It only looks at the extension header that's right after the fixed IPv6 > - * 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 == IPPROTO_FRAGMENT) { > - return (struct ipv6_extension_fragment *) ++hdr; > - } > - else > - return NULL; > -} > +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); > > /** > * IPv4 fragmentation. > diff --git a/lib/librte_ip_frag/rte_ip_frag_version.map > b/lib/librte_ip_frag/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; > > 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, > > 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 = sizeof(struct ipv6_hdr); > + uint8_t nexthdr = ip_hdr->proto; > + > + while (ipv6_ext_hdr(nexthdr)) { > + struct ipv6_opt_hdr opt; > + const struct ipv6_opt_hdr *popt = rte_pktmbuf_read(pkt, > + offset, sizeof(opt), &opt); > + if (popt == 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 += (popt->hdrlen + 2) << 2; > + break; > + > + default: > + offset += (popt->hdrlen + 1) << 3; > + break; > + } > + > + nexthdr = popt->nexthdr; > + } > + > + return NULL; > +} > diff --git a/lib/librte_ip_frag/rte_ipv6_reassembly.c > b/lib/librte_ip_frag/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_net/rte_ip.h b/lib/librte_net/rte_ip.h > index f2a8904a2..edcbdb67a 100644 > --- a/lib/librte_net/rte_ip.h > +++ b/lib/librte_net/rte_ip.h > @@ -350,6 +350,14 @@ struct ipv6_hdr { > #define IPV6_HDR_FL_MASK ((1u << IPV6_HDR_TC_SHIFT) - 1) > #define IPV6_HDR_TC_MASK (0xf << IPV6_HDR_TC_SHIFT) > > +/** > + * IPv6 extension header > + */ > +struct ipv6_opt_hdr { > + uint8_t nexthdr; > + uint8_t hdrlen; > +} __attribute__((packed)); > + > /** > * Process the pseudo-header checksum of an IPv6 header. > * > @@ -421,6 +429,25 @@ rte_ipv6_udptcp_cksum(const struct ipv6_hdr > *ipv6_hdr, const void *l4_hdr) > return (uint16_t)cksum; > } > > +/** > + * Check whether an IPv6 nexthdr value is for an IPv6 extension header. > + * > + * @param nexthdr > + * The protocol/next header field from an IPv6 (extension) header. > + * @return > + * Whether the nexthdr field is for an IPv6 extension header. > + */ > +static inline int > +ipv6_ext_hdr(uint8_t nexthdr) > +{ > + return (nexthdr == IPPROTO_HOPOPTS) || > + (nexthdr == IPPROTO_ROUTING) || > + (nexthdr == IPPROTO_FRAGMENT) || > + (nexthdr == IPPROTO_AH) || > + (nexthdr == IPPROTO_NONE) || > + (nexthdr == IPPROTO_DSTOPTS); > +} > + > #ifdef __cplusplus > } > #endif > diff --git a/lib/librte_port/rte_port_ras.c b/lib/librte_port/rte_port_ > ras.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, > struct rte_mbuf *pkt) > /* Assume there is no ethernet header */ > struct ipv6_hdr *pkt_hdr = rte_pktmbuf_mtod(pkt, struct ipv6_hdr > *); > > - struct ipv6_extension_fragment *frag_hdr; > + const struct ipv6_extension_fragment *frag_hdr; > + struct ipv6_extension_fragment frag_hdr_buf; > uint16_t frag_data = 0; > - frag_hdr = rte_ipv6_frag_get_ipv6_fragment_header(pkt_hdr); > + frag_hdr = rte_ipv6_frag_get_ipv6_fragment_header(pkt, pkt_hdr, > + &frag_hdr_buf); > if (frag_hdr != NULL) > frag_data = rte_be_to_cpu_16(frag_hdr->frag_data); > > -- > 2.17.1 > >