From patchwork Mon Nov 16 06:21:13 2015 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Daniele Di Proietto X-Patchwork-Id: 544904 Return-Path: X-Original-To: incoming@patchwork.ozlabs.org Delivered-To: patchwork-incoming@bilbo.ozlabs.org Received: from archives.nicira.com (unknown [IPv6:2600:3c00::f03c:91ff:fe6e:bdf7]) by ozlabs.org (Postfix) with ESMTP id 060C314144E for ; Mon, 16 Nov 2015 17:21:56 +1100 (AEDT) Received: from archives.nicira.com (localhost [127.0.0.1]) by archives.nicira.com (Postfix) with ESMTP id 14ACE10325; Sun, 15 Nov 2015 22:21:42 -0800 (PST) X-Original-To: dev@openvswitch.org Delivered-To: dev@openvswitch.org Received: from mx1e4.cudamail.com (mx1.cudamail.com [69.90.118.67]) by archives.nicira.com (Postfix) with ESMTPS id E8EE010300 for ; Sun, 15 Nov 2015 22:21:39 -0800 (PST) Received: from bar2.cudamail.com (unknown [192.168.21.12]) by mx1e4.cudamail.com (Postfix) with ESMTPS id 5C95C1E0075 for ; Sun, 15 Nov 2015 23:21:39 -0700 (MST) X-ASG-Debug-ID: 1447654898-03dc530883524440001-byXFYA Received: from mx1-pf1.cudamail.com ([192.168.24.1]) by bar2.cudamail.com with ESMTP id kjI5FTuH0EKGa5Sj (version=TLSv1 cipher=DHE-RSA-AES256-SHA bits=256 verify=NO) for ; Sun, 15 Nov 2015 23:21:38 -0700 (MST) X-Barracuda-Envelope-From: diproiettod@vmware.com X-Barracuda-RBL-Trusted-Forwarder: 192.168.24.1 Received: from unknown (HELO smtp-outbound-1.vmware.com) (208.91.2.12) by mx1-pf1.cudamail.com with ESMTPS (DHE-RSA-AES256-SHA encrypted); 16 Nov 2015 06:21:38 -0000 Received-SPF: error (mx1-pf1.cudamail.com: error in processing during lookup of vmware.com: DNS problem) X-Barracuda-Apparent-Source-IP: 208.91.2.12 X-Barracuda-RBL-IP: 208.91.2.12 Received: from sc9-mailhost2.vmware.com (sc9-mailhost2.vmware.com [10.113.161.72]) by smtp-outbound-1.vmware.com (Postfix) with ESMTP id 95A7D288DF for ; Sun, 15 Nov 2015 22:21:37 -0800 (PST) Received: from sc9-mailhost3.vmware.com (unknown [10.129.192.239]) by sc9-mailhost2.vmware.com (Postfix) with ESMTP id 61764B052C; Sun, 15 Nov 2015 22:21:37 -0800 (PST) X-CudaMail-Envelope-Sender: diproiettod@vmware.com From: Daniele Di Proietto To: dev@openvswitch.org X-CudaMail-Whitelist-To: dev@openvswitch.org X-CudaMail-MID: CM-E1-1114030523 X-CudaMail-DTE: 111515 X-CudaMail-Originating-IP: 208.91.2.12 Date: Sun, 15 Nov 2015 22:21:13 -0800 X-ASG-Orig-Subj: [##CM-E1-1114030523##][PATCH 02/12] flow: Export parse_ipv6_ext_hdrs(). Message-Id: <1447654883-8097-3-git-send-email-diproiettod@vmware.com> X-Mailer: git-send-email 2.1.4 In-Reply-To: <1447654883-8097-1-git-send-email-diproiettod@vmware.com> References: <1447654883-8097-1-git-send-email-diproiettod@vmware.com> X-Barracuda-Connect: UNKNOWN[192.168.24.1] X-Barracuda-Start-Time: 1447654898 X-Barracuda-Encrypted: DHE-RSA-AES256-SHA X-Barracuda-URL: https://web.cudamail.com:443/cgi-mod/mark.cgi X-ASG-Whitelist: Header =?UTF-8?B?eFwtY3VkYW1haWxcLXdoaXRlbGlzdFwtdG8=?= X-Virus-Scanned: by bsmtpd at cudamail.com X-Barracuda-BRTS-Status: 1 X-ASG-Whitelist: EmailCat (corporate) Subject: [ovs-dev] [PATCH 02/12] flow: Export parse_ipv6_ext_hdrs(). X-BeenThere: dev@openvswitch.org X-Mailman-Version: 2.1.16 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , MIME-Version: 1.0 Errors-To: dev-bounces@openvswitch.org Sender: "dev" This will be used by a future commit. Signed-off-by: Daniele Di Proietto --- lib/flow.c | 140 ++++++++++++++++++++++++++++++++++--------------------------- lib/flow.h | 3 ++ 2 files changed, 81 insertions(+), 62 deletions(-) diff --git a/lib/flow.c b/lib/flow.c index d5dcb92..2bdce26 100644 --- a/lib/flow.c +++ b/lib/flow.c @@ -402,6 +402,82 @@ invalid: arp_buf[1] = eth_addr_zero; } +static inline bool +parse_ipv6_ext_hdrs__(const void **datap, size_t *sizep, uint8_t *nw_proto, + uint8_t *nw_frag) +{ + while (1) { + if (OVS_LIKELY((*nw_proto != IPPROTO_HOPOPTS) + && (*nw_proto != IPPROTO_ROUTING) + && (*nw_proto != IPPROTO_DSTOPTS) + && (*nw_proto != IPPROTO_AH) + && (*nw_proto != IPPROTO_FRAGMENT))) { + /* It's either a terminal header (e.g., TCP, UDP) or one we + * don't understand. In either case, we're done with the + * packet, so use it to fill in 'nw_proto'. */ + return true; + } + + /* We only verify that at least 8 bytes of the next header are + * available, but many of these headers are longer. Ensure that + * accesses within the extension header are within those first 8 + * bytes. All extension headers are required to be at least 8 + * bytes. */ + if (OVS_UNLIKELY(*sizep < 8)) { + return false; + } + + if ((*nw_proto == IPPROTO_HOPOPTS) + || (*nw_proto == IPPROTO_ROUTING) + || (*nw_proto == IPPROTO_DSTOPTS)) { + /* These headers, while different, have the fields we care + * about in the same location and with the same + * interpretation. */ + const struct ip6_ext *ext_hdr = *datap; + *nw_proto = ext_hdr->ip6e_nxt; + if (OVS_UNLIKELY(!data_try_pull(datap, sizep, + (ext_hdr->ip6e_len + 1) * 8))) { + return false; + } + } else if (*nw_proto == IPPROTO_AH) { + /* A standard AH definition isn't available, but the fields + * we care about are in the same location as the generic + * option header--only the header length is calculated + * differently. */ + const struct ip6_ext *ext_hdr = *datap; + *nw_proto = ext_hdr->ip6e_nxt; + if (OVS_UNLIKELY(!data_try_pull(datap, sizep, + (ext_hdr->ip6e_len + 2) * 4))) { + return false; + } + } else if (*nw_proto == IPPROTO_FRAGMENT) { + const struct ovs_16aligned_ip6_frag *frag_hdr = *datap; + + *nw_proto = frag_hdr->ip6f_nxt; + if (!data_try_pull(datap, sizep, sizeof *frag_hdr)) { + return false; + } + + /* We only process the first fragment. */ + if (frag_hdr->ip6f_offlg != htons(0)) { + *nw_frag = FLOW_NW_FRAG_ANY; + if ((frag_hdr->ip6f_offlg & IP6F_OFF_MASK) != htons(0)) { + *nw_frag |= FLOW_NW_FRAG_LATER; + *nw_proto = IPPROTO_FRAGMENT; + return false; + } + } + } + } +} + +bool +parse_ipv6_ext_hdrs(const void **datap, size_t *sizep, uint8_t *nw_proto, + uint8_t *nw_frag) +{ + return parse_ipv6_ext_hdrs__(datap, sizep, nw_proto, nw_frag); +} + /* Initializes 'flow' members from 'packet' and 'md' * * Initializes 'packet' header l2 pointer to the start of the Ethernet @@ -604,68 +680,8 @@ miniflow_extract(struct dp_packet *packet, struct miniflow *dst) nw_ttl = nh->ip6_hlim; nw_proto = nh->ip6_nxt; - while (1) { - if (OVS_LIKELY((nw_proto != IPPROTO_HOPOPTS) - && (nw_proto != IPPROTO_ROUTING) - && (nw_proto != IPPROTO_DSTOPTS) - && (nw_proto != IPPROTO_AH) - && (nw_proto != IPPROTO_FRAGMENT))) { - /* It's either a terminal header (e.g., TCP, UDP) or one we - * don't understand. In either case, we're done with the - * packet, so use it to fill in 'nw_proto'. */ - break; - } - - /* We only verify that at least 8 bytes of the next header are - * available, but many of these headers are longer. Ensure that - * accesses within the extension header are within those first 8 - * bytes. All extension headers are required to be at least 8 - * bytes. */ - if (OVS_UNLIKELY(size < 8)) { - goto out; - } - - if ((nw_proto == IPPROTO_HOPOPTS) - || (nw_proto == IPPROTO_ROUTING) - || (nw_proto == IPPROTO_DSTOPTS)) { - /* These headers, while different, have the fields we care - * about in the same location and with the same - * interpretation. */ - const struct ip6_ext *ext_hdr = data; - nw_proto = ext_hdr->ip6e_nxt; - if (OVS_UNLIKELY(!data_try_pull(&data, &size, - (ext_hdr->ip6e_len + 1) * 8))) { - goto out; - } - } else if (nw_proto == IPPROTO_AH) { - /* A standard AH definition isn't available, but the fields - * we care about are in the same location as the generic - * option header--only the header length is calculated - * differently. */ - const struct ip6_ext *ext_hdr = data; - nw_proto = ext_hdr->ip6e_nxt; - if (OVS_UNLIKELY(!data_try_pull(&data, &size, - (ext_hdr->ip6e_len + 2) * 4))) { - goto out; - } - } else if (nw_proto == IPPROTO_FRAGMENT) { - const struct ovs_16aligned_ip6_frag *frag_hdr = data; - - nw_proto = frag_hdr->ip6f_nxt; - if (!data_try_pull(&data, &size, sizeof *frag_hdr)) { - goto out; - } - - /* We only process the first fragment. */ - if (frag_hdr->ip6f_offlg != htons(0)) { - nw_frag = FLOW_NW_FRAG_ANY; - if ((frag_hdr->ip6f_offlg & IP6F_OFF_MASK) != htons(0)) { - nw_frag |= FLOW_NW_FRAG_LATER; - nw_proto = IPPROTO_FRAGMENT; - break; - } - } - } + if (!parse_ipv6_ext_hdrs__(&data, &size, &nw_proto, &nw_frag)) { + goto out; } } else { if (dl_type == htons(ETH_TYPE_ARP) || diff --git a/lib/flow.h b/lib/flow.h index 41397d4..de15a98 100644 --- a/lib/flow.h +++ b/lib/flow.h @@ -235,6 +235,9 @@ void flow_set_mpls_lse(struct flow *, int idx, ovs_be32 lse); void flow_compose(struct dp_packet *, const struct flow *); +bool parse_ipv6_ext_hdrs(const void **datap, size_t *sizep, uint8_t *nw_proto, + uint8_t *nw_frag); + static inline uint64_t flow_get_xreg(const struct flow *flow, int idx) {