From patchwork Wed May 4 07:36:32 2016 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Simon Horman X-Patchwork-Id: 618307 Return-Path: X-Original-To: incoming@patchwork.ozlabs.org Delivered-To: patchwork-incoming@bilbo.ozlabs.org Received: from archives.nicira.com (archives.nicira.com [96.126.127.54]) by ozlabs.org (Postfix) with ESMTP id 3r08yY2ykGz9t5w for ; Wed, 4 May 2016 17:37:41 +1000 (AEST) Authentication-Results: ozlabs.org; dkim=fail reason="signature verification failed" (2048-bit key; unprotected) header.d=netronome-com.20150623.gappssmtp.com header.i=@netronome-com.20150623.gappssmtp.com header.b=LyoJYse9; dkim-atps=neutral Received: from archives.nicira.com (localhost [127.0.0.1]) by archives.nicira.com (Postfix) with ESMTP id 04392106ED; Wed, 4 May 2016 00:37:10 -0700 (PDT) X-Original-To: dev@openvswitch.org Delivered-To: dev@openvswitch.org Received: from mx1e3.cudamail.com (mx1.cudamail.com [69.90.118.67]) by archives.nicira.com (Postfix) with ESMTPS id 46068106E8 for ; Wed, 4 May 2016 00:37:08 -0700 (PDT) Received: from bar5.cudamail.com (localhost [127.0.0.1]) by mx1e3.cudamail.com (Postfix) with ESMTPS id C3718420378 for ; Wed, 4 May 2016 01:37:07 -0600 (MDT) X-ASG-Debug-ID: 1462347427-09eadd6042276360001-byXFYA Received: from mx1-pf2.cudamail.com ([192.168.24.2]) by bar5.cudamail.com with ESMTP id MHvKpx5QoSKszANZ (version=TLSv1 cipher=DHE-RSA-AES256-SHA bits=256 verify=NO) for ; Wed, 04 May 2016 01:37:07 -0600 (MDT) X-Barracuda-Envelope-From: simon.horman@netronome.com X-Barracuda-RBL-Trusted-Forwarder: 192.168.24.2 Received: from unknown (HELO mail-pa0-f43.google.com) (209.85.220.43) by mx1-pf2.cudamail.com with ESMTPS (RC4-SHA encrypted); 4 May 2016 07:37:06 -0000 Received-SPF: neutral (mx1-pf2.cudamail.com: 209.85.220.43 is neither permitted nor denied by SPF record at spf.mandrillapp.com) X-Barracuda-RBL-Trusted-Forwarder: 209.85.220.43 Received: by mail-pa0-f43.google.com with SMTP id iv1so21097446pac.2 for ; Wed, 04 May 2016 00:37:06 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=netronome-com.20150623.gappssmtp.com; s=20150623; h=from:to:cc:subject:date:message-id:in-reply-to:references; bh=FrkON1s2Dpjx5Ul9cTC2d71HsiB7SawH7yveR2O/YyA=; b=LyoJYse9GhNyuUcbNFJIty2tZFjrPxDLRYsjXQuKr1NuhuaZuk4RYBmztQbcg32RMd MIKXmeQeAgCdkzgJlXbphp5oQ6E1pPKl1/MfSgZPIoRv2tt5DsZgIPDxf9wQkBY5O8jE FK5AIVuxgyg/PYUYF1+5mBMMwgAlofbXN//SZcxtAnYpRpfknNP7g8Y4hI5qY3b2K39Q 8MAM/4MrE4yKColT7YdWIhftO8iwQ7xvpUkm5O4Uu8WJgVqgB8j3wTFao3LDHy9qBzLE il19pPokeHfZz1FtUYvb2z7BSnzwY5fAzNIY9821klk7DQRAVub5VPg94yqxugEUU2Q5 Ru6Q== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20130820; h=x-gm-message-state:from:to:cc:subject:date:message-id:in-reply-to :references; bh=FrkON1s2Dpjx5Ul9cTC2d71HsiB7SawH7yveR2O/YyA=; b=dPLvP0vXi6NZ9c4vF2Eku4OymwnGZCD2Pvdr7mwa132KETqs9N74nPDP9in0bP45bi Xutm0dr02nth8qo7feMs6nH/eXim5RRvUe54lAURMP98dlalfUJGdvFMEyMc/QLFxFGx pBJ4J1khWC3XMetmovc44IXp9k7v+LzxNcqteBSbhuso4KkJsXg/mICxiMv7kRQimMHi 9HN5iN5/rY5nPYi7CR49nWoknImWYePPpJNWIaZHlR6WIEtJix7ja/s3DOvkzCM8QtPr U/QS550tgLu72mKjWX6z9nHv9goq0ZbHGi2V1XDTuM8tELMcw9Ck5O/itI+lzlETOswi Pl6Q== X-Gm-Message-State: AOPr4FWYEVUXPKohI01xswHTAxqT0pPMqbZKz8f9cCFw78n6QnvlWcqoxmZTjehROlmn5aoa X-Received: by 10.66.82.8 with SMTP id e8mr10147512pay.124.1462347426035; Wed, 04 May 2016 00:37:06 -0700 (PDT) Received: from penelope.kanocho.kobe.vergenet.net (121-80-211-180f1.hyg1.eonet.ne.jp. [121.80.211.180]) by smtp.gmail.com with ESMTPSA id 1sm3513717pah.7.2016.05.04.00.37.03 (version=TLS1_2 cipher=ECDHE-RSA-AES128-SHA bits=128/128); Wed, 04 May 2016 00:37:04 -0700 (PDT) X-CudaMail-Envelope-Sender: simon.horman@netronome.com X-Barracuda-Apparent-Source-IP: 121.80.211.180 From: Simon Horman To: netdev@vger.kernel.org, dev@openvswitch.org X-CudaMail-MID: CM-E2-503001855 X-CudaMail-DTE: 050416 X-CudaMail-Originating-IP: 209.85.220.43 Date: Wed, 4 May 2016 16:36:32 +0900 X-ASG-Orig-Subj: [##CM-E2-503001855##][PATCH v9 net-next 6/7] openvswitch: extend layer 3 support to cover non-IP packets Message-Id: <1462347393-22354-7-git-send-email-simon.horman@netronome.com> X-Mailer: git-send-email 2.7.0.rc3.207.g0ac5344 In-Reply-To: <1462347393-22354-1-git-send-email-simon.horman@netronome.com> References: <1462347393-22354-1-git-send-email-simon.horman@netronome.com> X-GBUdb-Analysis: 0, 209.85.220.43, Ugly c=0.434822 p=-0.294118 Source Normal X-MessageSniffer-Rules: 0-0-0-14193-c X-Barracuda-Connect: UNKNOWN[192.168.24.2] X-Barracuda-Start-Time: 1462347427 X-Barracuda-Encrypted: DHE-RSA-AES256-SHA X-Barracuda-URL: https://web.cudamail.com:443/cgi-mod/mark.cgi X-Virus-Scanned: by bsmtpd at cudamail.com X-Barracuda-BRTS-Status: 1 X-Barracuda-Spam-Score: 0.60 X-Barracuda-Spam-Status: No, SCORE=0.60 using per-user scores of TAG_LEVEL=3.5 QUARANTINE_LEVEL=1000.0 KILL_LEVEL=4.0 tests=BSF_SC0_MISMATCH_TO, BSF_SC5_MJ1963, DKIM_SIGNED, RDNS_NONE X-Barracuda-Spam-Report: Code version 3.2, rules version 3.2.3.29282 Rule breakdown below pts rule name description ---- ---------------------- -------------------------------------------------- 0.00 BSF_SC0_MISMATCH_TO Envelope rcpt doesn't match header 0.00 DKIM_SIGNED Domain Keys Identified Mail: message has a signature 0.10 RDNS_NONE Delivered to trusted network by a host with no rDNS 0.50 BSF_SC5_MJ1963 Custom Rule MJ1963 Cc: Simon Horman Subject: [ovs-dev] [PATCH v9 net-next 6/7] openvswitch: extend layer 3 support to cover non-IP packets 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" Extend support for layer 3 packets to cover non-IP packets. This removes the assumption that the first octet of a layer 3 packet indicates the IP protocol version - true for IP (v4 and v6), but not for necessarily for other protocols. The key motivation for this is to allow forwarding of MPLS packets which are technically layer 2.5 rather than 3 but the distinction seems unimportant here. This sets OVS_KEY_ATTR_PACKET_ETHERTYPE to the ethernet type corresponding to the protocol of layer 3 packets on a flow miss. Signed-off-by: Simon Horman --- v9 * New patch --- net/openvswitch/flow_netlink.c | 121 ++++++++++++++++++++--------------------- 1 file changed, 59 insertions(+), 62 deletions(-) diff --git a/net/openvswitch/flow_netlink.c b/net/openvswitch/flow_netlink.c index 2bca1e5e9a18..1e1392c3c0ed 100644 --- a/net/openvswitch/flow_netlink.c +++ b/net/openvswitch/flow_netlink.c @@ -817,7 +817,7 @@ static int metadata_from_nlattrs(struct net *net, struct sw_flow_match *match, u64 *attrs, const struct nlattr **a, bool is_mask, bool log) { - bool is_layer3; + bool is_layer3 = false; if (*attrs & (1 << OVS_KEY_ATTR_DP_HASH)) { u32 hash_val = nla_get_u32(a[OVS_KEY_ATTR_DP_HASH]); @@ -906,48 +906,40 @@ static int metadata_from_nlattrs(struct net *net, struct sw_flow_match *match, *attrs &= ~(1ULL << OVS_KEY_ATTR_CT_LABELS); } - /* For full flow keys the layer is determined based on the presence of - * OVS_KEY_ATTR_ETHERNET - */ - if (is_mask) - /* Always exact match is_layer3 */ - is_layer3 = true; - else - is_layer3 = !(*attrs & (1ULL << OVS_KEY_ATTR_ETHERNET)); - /* Packets from user space for execution only have metadata key - * attributes. OVS_KEY_ATTR_PACKET_ETHERTYPE is then used to specify - * the starting layer of the packet. Packets with Ethernet headers - * have this attribute set to 0 + /* For layer 3 packets the ethernet type is provided by by the + * metadata field OVS_KEY_ATTR_PACKET_ETHERTYPE which has a + * non-zero value. Otherwise the ethernet type is provided by the + * packet and reflected by OVS_KEY_ATTR_PACKET_ETHERTYPE. */ if (*attrs & (1ULL << OVS_KEY_ATTR_PACKET_ETHERTYPE)) { + /* This is duplicate code from ovs_key_from_nlattrs*/ __be16 eth_type; - if (is_mask) { + if (is_mask) /* Always exact match packet EtherType */ eth_type = htons(0xffff); - } else { + else eth_type = nla_get_be16(a[OVS_KEY_ATTR_PACKET_ETHERTYPE]); - is_layer3 = ((eth_type == htons(ETH_P_IP)) || - (eth_type == htons(ETH_P_IPV6))); + + if (eth_type != htons(0)) { + is_layer3 = true; + SW_FLOW_KEY_PUT(match, eth.type, eth_type, is_mask); } - SW_FLOW_KEY_PUT(match, eth.type, eth_type, is_mask); + + *attrs &= ~(1ULL << OVS_KEY_ATTR_PACKET_ETHERTYPE); } - SW_FLOW_KEY_PUT(match, phy.is_layer3, is_layer3, is_mask); - return 0; + /* Always exact match is_layer3 */ + SW_FLOW_KEY_PUT(match, phy.is_layer3, is_mask ? true : is_layer3, + is_mask); + return is_layer3; } -static int ovs_key_from_nlattrs(struct net *net, struct sw_flow_match *match, - u64 attrs, const struct nlattr **a, - bool is_mask, bool log) +static int l2_from_nlattrs(struct net *net, struct sw_flow_match *match, + u64 *attrs, const struct nlattr **a, + bool is_mask, bool log) { - int err; - - err = metadata_from_nlattrs(net, match, &attrs, a, is_mask, log); - if (err) - return err; - - if (attrs & (1 << OVS_KEY_ATTR_ETHERNET)) { + if (*attrs & (1 << OVS_KEY_ATTR_ETHERNET)) { const struct ovs_key_ethernet *eth_key; eth_key = nla_data(a[OVS_KEY_ATTR_ETHERNET]); @@ -955,10 +947,10 @@ static int ovs_key_from_nlattrs(struct net *net, struct sw_flow_match *match, eth_key->eth_src, ETH_ALEN, is_mask); SW_FLOW_KEY_MEMCPY(match, eth.dst, eth_key->eth_dst, ETH_ALEN, is_mask); - attrs &= ~(1 << OVS_KEY_ATTR_ETHERNET); + *attrs &= ~(1 << OVS_KEY_ATTR_ETHERNET); } - if (attrs & (1 << OVS_KEY_ATTR_VLAN)) { + if (*attrs & (1 << OVS_KEY_ATTR_VLAN)) { __be16 tci; tci = nla_get_be16(a[OVS_KEY_ATTR_VLAN]); @@ -972,10 +964,10 @@ static int ovs_key_from_nlattrs(struct net *net, struct sw_flow_match *match, } SW_FLOW_KEY_PUT(match, eth.tci, tci, is_mask); - attrs &= ~(1 << OVS_KEY_ATTR_VLAN); + *attrs &= ~(1 << OVS_KEY_ATTR_VLAN); } - if (attrs & (1 << OVS_KEY_ATTR_ETHERTYPE)) { + if (*attrs & (1 << OVS_KEY_ATTR_ETHERTYPE)) { __be16 eth_type; eth_type = nla_get_be16(a[OVS_KEY_ATTR_ETHERTYPE]); @@ -989,24 +981,34 @@ static int ovs_key_from_nlattrs(struct net *net, struct sw_flow_match *match, } SW_FLOW_KEY_PUT(match, eth.type, eth_type, is_mask); - attrs &= ~(1 << OVS_KEY_ATTR_ETHERTYPE); + *attrs &= ~(1 << OVS_KEY_ATTR_ETHERTYPE); } else if (!is_mask) { SW_FLOW_KEY_PUT(match, eth.type, htons(ETH_P_802_2), is_mask); } - if (attrs & (1 << OVS_KEY_ATTR_IPV4)) { - const struct ovs_key_ipv4 *ipv4_key; + return 0; +} - /* Add eth.type value for layer 3 flows */ - if (!(attrs & (1ULL << OVS_KEY_ATTR_ETHERTYPE))) { - __be16 eth_type; +static int ovs_key_from_nlattrs(struct net *net, struct sw_flow_match *match, + u64 attrs, const struct nlattr **a, + bool is_mask, bool log) +{ + int err; + bool is_layer3; - if (is_mask) - eth_type = htons(0xffff); - else - eth_type = htons(ETH_P_IP); - SW_FLOW_KEY_PUT(match, eth.type, eth_type, is_mask); - } + err = metadata_from_nlattrs(net, match, &attrs, a, is_mask, log); + if (err < 0) + return err; + is_layer3 = err != 0; + + if (!is_layer3) { + err = l2_from_nlattrs(net, match, &attrs, a, is_mask, log); + if (err < 0) + return err; + } + + if (attrs & (1 << OVS_KEY_ATTR_IPV4)) { + const struct ovs_key_ipv4 *ipv4_key; ipv4_key = nla_data(a[OVS_KEY_ATTR_IPV4]); if (!is_mask && ipv4_key->ipv4_frag > OVS_FRAG_TYPE_MAX) { @@ -1032,17 +1034,6 @@ static int ovs_key_from_nlattrs(struct net *net, struct sw_flow_match *match, if (attrs & (1 << OVS_KEY_ATTR_IPV6)) { const struct ovs_key_ipv6 *ipv6_key; - /* Add eth.type value for layer 3 flows */ - if (!(attrs & (1ULL << OVS_KEY_ATTR_ETHERTYPE))) { - __be16 eth_type; - - if (is_mask) - eth_type = htons(0xffff); - else - eth_type = htons(ETH_P_IPV6); - SW_FLOW_KEY_PUT(match, eth.type, eth_type, is_mask); - } - ipv6_key = nla_data(a[OVS_KEY_ATTR_IPV6]); if (!is_mask && ipv6_key->ipv6_frag > OVS_FRAG_TYPE_MAX) { OVS_NLERR(log, "IPv6 frag type %d is out of range max %d", @@ -1465,7 +1456,11 @@ int ovs_nla_get_flow_metadata(struct net *net, const struct nlattr *attr, memset(&key->ct, 0, sizeof(key->ct)); key->phy.in_port = DP_MAX_PORTS; - return metadata_from_nlattrs(net, &match, &attrs, a, false, log); + err = metadata_from_nlattrs(net, &match, &attrs, a, false, log); + if (err < 0) + return err; + + return 0; } static int __ovs_nla_put_key(const struct sw_flow_key *swkey, @@ -1551,6 +1546,10 @@ static int __ovs_nla_put_key(const struct sw_flow_key *swkey, if (nla_put_be16(skb, OVS_KEY_ATTR_ETHERTYPE, output->eth.type)) goto nla_put_failure; + } else { + if (nla_put_be16(skb, OVS_KEY_ATTR_PACKET_ETHERTYPE, + output->eth.type)) + goto nla_put_failure; } if (swkey->eth.type == htons(ETH_P_IP)) { @@ -2184,8 +2183,6 @@ static int validate_set(const struct nlattr *a, break; case OVS_KEY_ATTR_MPLS: - if (is_layer3) - return -EINVAL; if (!eth_p_mpls(eth_type)) return -EINVAL; break; @@ -2360,7 +2357,7 @@ static int __ovs_nla_copy_actions(struct net *net, const struct nlattr *attr, case OVS_ACTION_ATTR_PUSH_MPLS: { const struct ovs_action_push_mpls *mpls = nla_data(a); - if (is_layer3 || !eth_p_mpls(mpls->mpls_ethertype)) + if (!eth_p_mpls(mpls->mpls_ethertype)) return -EINVAL; /* Prohibit push MPLS other than to a white list * for packets that have a known tag order. @@ -2377,7 +2374,7 @@ static int __ovs_nla_copy_actions(struct net *net, const struct nlattr *attr, } case OVS_ACTION_ATTR_POP_MPLS: - if (is_layer3 || vlan_tci & htons(VLAN_TAG_PRESENT) || + if (vlan_tci & htons(VLAN_TAG_PRESENT) || !eth_p_mpls(eth_type)) return -EINVAL;