From patchwork Wed Sep 4 17:07:10 2019 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Gregory Rose X-Patchwork-Id: 1157832 Return-Path: X-Original-To: incoming@patchwork.ozlabs.org Delivered-To: patchwork-incoming@bilbo.ozlabs.org Authentication-Results: ozlabs.org; spf=pass (mailfrom) smtp.mailfrom=openvswitch.org (client-ip=140.211.169.12; helo=mail.linuxfoundation.org; envelope-from=ovs-dev-bounces@openvswitch.org; receiver=) Authentication-Results: ozlabs.org; dmarc=fail (p=none dis=none) header.from=gmail.com Authentication-Results: ozlabs.org; dkim=fail reason="signature verification failed" (2048-bit key; unprotected) header.d=gmail.com header.i=@gmail.com header.b="uw5ZOQcI"; dkim-atps=neutral Received: from mail.linuxfoundation.org (mail.linuxfoundation.org [140.211.169.12]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by ozlabs.org (Postfix) with ESMTPS id 46Nqzj2XXDz9s3Z for ; Thu, 5 Sep 2019 03:09:05 +1000 (AEST) Received: from mail.linux-foundation.org (localhost [127.0.0.1]) by mail.linuxfoundation.org (Postfix) with ESMTP id D564E19FD; Wed, 4 Sep 2019 17:07:54 +0000 (UTC) X-Original-To: dev@openvswitch.org Delivered-To: ovs-dev@mail.linuxfoundation.org Received: from smtp1.linuxfoundation.org (smtp1.linux-foundation.org [172.17.192.35]) by mail.linuxfoundation.org (Postfix) with ESMTPS id D4D3419C4 for ; Wed, 4 Sep 2019 17:07:16 +0000 (UTC) X-Greylist: whitelisted by SQLgrey-1.7.6 Received: from mail-pg1-f194.google.com (mail-pg1-f194.google.com [209.85.215.194]) by smtp1.linuxfoundation.org (Postfix) with ESMTPS id 471AD709 for ; Wed, 4 Sep 2019 17:07:16 +0000 (UTC) Received: by mail-pg1-f194.google.com with SMTP id w10so11566059pgj.7 for ; Wed, 04 Sep 2019 10:07:16 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20161025; h=from:to:cc:subject:date:message-id; bh=kUYh9n+gmMhbEHlUbmXjraZqXWOSxsjPjbMiE+ePL+o=; b=uw5ZOQcIKoJZ997ntawwZsxdYOyfZZnU9/XoRnu99xFANI9CNJJP9B6tVNi78XL2o+ 4N/UWPvzYSdmbUCM0PWJ/R11wyIFhccRvyeAf01KzQywD13OyqL6MFXsSQJ+P/Su72LT lT7AhgN0oEYril/kq4UTlK3zFg0GAZ1Saro7H+pSGCjXiyalYccES1olnIWmmcnsxxMH 0peDNXj/Qxem2MgND5haABDnAFACVdQNS++DjZGPTEblMfq+IMgzXzrD74KDuUu9fMdB Jq091A3lFWGGOq/7k0VubYAS7ZMX7db3AdlbzUZpeLcDMOLeINd0BN4R8sAfXMENazti Yb+A== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20161025; h=x-gm-message-state:from:to:cc:subject:date:message-id; bh=kUYh9n+gmMhbEHlUbmXjraZqXWOSxsjPjbMiE+ePL+o=; b=EdzKlyYrK7tVR4dMyy/1Y2wpdOJDMNNo0vMEoXM8XdoAqqgcDx0Yogr271cKQ4jGwk DMS29wUyz33YOExTEkHXN1l/Oil78RLN2g09iEiTxYXbRSRpRRAVT89p7q5xHQohY4ic qEp/qI/1tGFak8I3omIdsz/NHvBiJY1t8ihqEMpxqyVwqH6p6eGB03r7zensR5GR+4FS EcYlZDt7DtwTeTurvLXX/sdBaeUTNl0Sx/eRupMBNqE92naqVcafJmaxwcZFc8XYiggX iILr0vMTS0iaPgzhZRAMPoRBLgwezO33wF4vUAOTu+GnbWHYKQPvFntWHAHfNFvMHXWS 5i7Q== X-Gm-Message-State: APjAAAU4z9osZrwOj4I7FXTaVcS1Njr1WsylZGicmI4Ef7MdAb3fepGl xrmeqc0uLxfNq02JYm04hW/PUPwu X-Google-Smtp-Source: APXvYqwHB+nWB0SgMKHtDOgCOi9v/rBZSh+0IfFuwBaj1qHD4B18CL7JeK8KdyJI3tSVXjSJQFUd9Q== X-Received: by 2002:a62:4e52:: with SMTP id c79mr22391702pfb.28.1567616835484; Wed, 04 Sep 2019 10:07:15 -0700 (PDT) Received: from gizo.domain (97-115-90-227.ptld.qwest.net. [97.115.90.227]) by smtp.gmail.com with ESMTPSA id v12sm20495967pff.40.2019.09.04.10.07.14 (version=TLS1_2 cipher=ECDHE-RSA-AES128-GCM-SHA256 bits=128/128); Wed, 04 Sep 2019 10:07:14 -0700 (PDT) From: Greg Rose To: dev@openvswitch.org Date: Wed, 4 Sep 2019 10:07:10 -0700 Message-Id: <1567616831-5652-1-git-send-email-gvrose8192@gmail.com> X-Mailer: git-send-email 1.8.3.1 X-Spam-Status: No, score=-1.7 required=5.0 tests=BAYES_00,DKIM_SIGNED, DKIM_VALID,DKIM_VALID_AU,FREEMAIL_ENVFROM_END_DIGIT,FREEMAIL_FROM, RCVD_IN_DNSWL_NONE autolearn=no version=3.3.1 X-Spam-Checker-Version: SpamAssassin 3.3.1 (2010-03-16) on smtp1.linux-foundation.org Subject: [ovs-dev] [PATCH V2 branch-2.6 1/2] datapath: Properly set L4 keys on "later" IP fragments X-BeenThere: ovs-dev@openvswitch.org X-Mailman-Version: 2.1.12 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , MIME-Version: 1.0 Sender: ovs-dev-bounces@openvswitch.org Errors-To: ovs-dev-bounces@openvswitch.org Upstream commit: commit ad06a566e118e57b852cab5933dbbbaebb141de3 Author: Greg Rose Date: Tue Aug 27 07:58:09 2019 -0700 openvswitch: Properly set L4 keys on "later" IP fragments When IP fragments are reassembled before being sent to conntrack, the key from the last fragment is used. Unless there are reordering issues, the last fragment received will not contain the L4 ports, so the key for the reassembled datagram won't contain them. This patch updates the key once we have a reassembled datagram. The handle_fragments() function works on L3 headers so we pull the L3/L4 flow key update code from key_extract into a new function 'key_extract_l3l4'. Then we add a another new function ovs_flow_key_update_l3l4() and export it so that it is accessible by handle_fragments() for conntrack packet reassembly. Co-authored-by: Justin Pettit Signed-off-by: Greg Rose Acked-by: Pravin B Shelar Signed-off-by: David S. Miller Signed-off-by: Greg Rose --- V2 - Fix compile error --- datapath/conntrack.c | 5 ++ datapath/flow.c | 130 ++++++++++++++++++++++++++++++--------------------- datapath/flow.h | 1 + 3 files changed, 83 insertions(+), 53 deletions(-) diff --git a/datapath/conntrack.c b/datapath/conntrack.c index 2aa0105..8d33bcd 100644 --- a/datapath/conntrack.c +++ b/datapath/conntrack.c @@ -461,6 +461,11 @@ static int handle_fragments(struct net *net, struct sw_flow_key *key, return -EPFNOSUPPORT; } + /* The key extracted from the fragment that completed this datagram + * likely didn't have an L4 header, so regenerate it. + */ + ovs_flow_key_update_l3l4(skb, key); + key->ip.frag = OVS_FRAG_TYPE_NONE; skb_clear_hash(skb); skb->ignore_df = 1; diff --git a/datapath/flow.c b/datapath/flow.c index 581d1d2..2d44997 100644 --- a/datapath/flow.c +++ b/datapath/flow.c @@ -436,63 +436,14 @@ invalid: } /** - * key_extract - extracts a flow key from an Ethernet frame. + * key_extract_l3l4 - extracts L3/L4 header information. * @skb: sk_buff that contains the frame, with skb->data pointing to the - * Ethernet header + * L3 header * @key: output flow key - * - * The caller must ensure that skb->len >= ETH_HLEN. - * - * Returns 0 if successful, otherwise a negative errno value. - * - * Initializes @skb header pointers as follows: - * - * - skb->mac_header: the Ethernet header. - * - * - skb->network_header: just past the Ethernet header, or just past the - * VLAN header, to the first byte of the Ethernet payload. - * - * - skb->transport_header: If key->eth.type is ETH_P_IP or ETH_P_IPV6 - * on output, then just past the IP header, if one is present and - * of a correct length, otherwise the same as skb->network_header. - * For other key->eth.type values it is left untouched. */ -static int key_extract(struct sk_buff *skb, struct sw_flow_key *key) +static int key_extract_l3l4(struct sk_buff *skb, struct sw_flow_key *key) { - int error; - struct ethhdr *eth; - - /* Flags are always used as part of stats */ - key->tp.flags = 0; - - skb_reset_mac_header(skb); - - /* Link layer. We are guaranteed to have at least the 14 byte Ethernet - * header in the linear data area. - */ - eth = eth_hdr(skb); - ether_addr_copy(key->eth.src, eth->h_source); - ether_addr_copy(key->eth.dst, eth->h_dest); - - __skb_pull(skb, 2 * ETH_ALEN); - /* We are going to push all headers that we pull, so no need to - * update skb->csum here. - */ - - key->eth.tci = 0; - if (skb_vlan_tag_present(skb)) - key->eth.tci = htons(skb->vlan_tci); - else if (eth->h_proto == htons(ETH_P_8021Q)) - if (unlikely(parse_vlan(skb, key))) - return -ENOMEM; - - key->eth.type = parse_ethertype(skb); - if (unlikely(key->eth.type == htons(0))) - return -ENOMEM; - - skb_reset_network_header(skb); - skb_reset_mac_len(skb); - __skb_push(skb, skb->data - skb_mac_header(skb)); + int error; /* Network layer. */ if (key->eth.type == htons(ETH_P_IP)) { @@ -688,6 +639,79 @@ static int key_extract(struct sk_buff *skb, struct sw_flow_key *key) return 0; } +/** + * key_extract - extracts a flow key from an Ethernet frame. + * @skb: sk_buff that contains the frame, with skb->data pointing to the + * Ethernet header + * @key: output flow key + * + * The caller must ensure that skb->len >= ETH_HLEN. + * + * Returns 0 if successful, otherwise a negative errno value. + * + * Initializes @skb header fields as follows: + * + * - skb->mac_header: the L2 header. + * + * - skb->network_header: just past the L2 header, or just past the + * VLAN header, to the first byte of the L2 payload. + * + * - skb->transport_header: If key->eth.type is ETH_P_IP or ETH_P_IPV6 + * on output, then just past the IP header, if one is present and + * of a correct length, otherwise the same as skb->network_header. + * For other key->eth.type values it is left untouched. + * + * - skb->protocol: the type of the data starting at skb->network_header. + * Equals to key->eth.type. + */ +static int key_extract(struct sk_buff *skb, struct sw_flow_key *key) +{ + struct ethhdr *eth; + + /* Flags are always used as part of stats */ + key->tp.flags = 0; + + skb_reset_mac_header(skb); + + /* Link layer. We are guaranteed to have at least the 14 byte Ethernet + * header in the linear data area. + */ + eth = eth_hdr(skb); + ether_addr_copy(key->eth.src, eth->h_source); + ether_addr_copy(key->eth.dst, eth->h_dest); + + __skb_pull(skb, 2 * ETH_ALEN); + /* We are going to push all headers that we pull, so no need to + * update skb->csum here. + */ + + key->eth.tci = 0; + if (skb_vlan_tag_present(skb)) + key->eth.tci = htons(skb->vlan_tci); + else if (eth->h_proto == htons(ETH_P_8021Q)) + if (unlikely(parse_vlan(skb, key))) + return -ENOMEM; + + key->eth.type = parse_ethertype(skb); + if (unlikely(key->eth.type == htons(0))) + return -ENOMEM; + + skb_reset_network_header(skb); + skb_reset_mac_len(skb); + __skb_push(skb, skb->data - skb_mac_header(skb)); + + /* Fill out L3/L4 key info, if any */ + return key_extract_l3l4(skb, key); +} + +/* In the case of conntrack fragment handling it expects L3 headers, + * add a helper. + */ +int ovs_flow_key_update_l3l4(struct sk_buff *skb, struct sw_flow_key *key) +{ + return key_extract_l3l4(skb, key); +} + int ovs_flow_key_update(struct sk_buff *skb, struct sw_flow_key *key) { return key_extract(skb, key); diff --git a/datapath/flow.h b/datapath/flow.h index 2dd0696..79973c1 100644 --- a/datapath/flow.h +++ b/datapath/flow.h @@ -218,6 +218,7 @@ u64 ovs_flow_used_time(unsigned long flow_jiffies); /* Update the non-metadata part of the flow key using skb. */ int ovs_flow_key_update(struct sk_buff *skb, struct sw_flow_key *key); +int ovs_flow_key_update_l3l4(struct sk_buff *skb, struct sw_flow_key *key); int ovs_flow_key_extract(const struct ip_tunnel_info *tun_info, struct sk_buff *skb, struct sw_flow_key *key);