From patchwork Fri Dec 14 22:32:23 2018 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Yifeng Sun X-Patchwork-Id: 1013746 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="OnDMMfHL"; 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 43Gljf5ynyz9s4s for ; Sat, 15 Dec 2018 09:35:02 +1100 (AEDT) Received: from mail.linux-foundation.org (localhost [127.0.0.1]) by mail.linuxfoundation.org (Postfix) with ESMTP id CE395D60; Fri, 14 Dec 2018 22:32:32 +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 7A3D8974 for ; Fri, 14 Dec 2018 22:32:31 +0000 (UTC) X-Greylist: whitelisted by SQLgrey-1.7.6 Received: from mail-pf1-f193.google.com (mail-pf1-f193.google.com [209.85.210.193]) by smtp1.linuxfoundation.org (Postfix) with ESMTPS id B9AA9603 for ; Fri, 14 Dec 2018 22:32:30 +0000 (UTC) Received: by mail-pf1-f193.google.com with SMTP id 64so3463707pfr.9 for ; Fri, 14 Dec 2018 14:32:30 -0800 (PST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20161025; h=from:to:cc:subject:date:message-id; bh=RYGCA+jDSqqxBzP+JQD0xOwveY9VZ+RmyffVPnCMtoU=; b=OnDMMfHLY3eQjolVTWuNLMB9PiPeDH0BM0cDh+PGrGr3/hGeROV6nE35khrPuXL38q U5v+KkexXvPG+OA9caUybyqfGK0dMBvbUCeyPEjfk089fCzY9ZnBEoH7h7fL4DdrHjCJ z6IZwEswXAicMYEj7GXT9baWNyxBjtLc2sr0VrWouhLs4cG3yeamkZiazI1BLVCKOjZj 18Y7amI7den8CimDH4ZnVcWxvi/kfx0NJgulGayMTB3O0eqbPq/s3VuHqPz+va9zpJc+ 4tyLbDXTpLIxRxjQBUm+5guNM2v5HzqHLNdWztS/AzaVIe226g0Sy98H4ECqWhIJw/qn eqNg== 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=RYGCA+jDSqqxBzP+JQD0xOwveY9VZ+RmyffVPnCMtoU=; b=QO1OOe6pON4ZhZroJAewQjsJ81ShovCOglSGDIQ7eqYV/d3wXu6fAinPhc3pkpk+G8 pWOVsbZUrRZh6fUdVK9aEXy024NvtLGrUUYqdv8DjsGgO0ddlZfnvapdmXUg61ymoynf TXFShjlc8jFsNSaDAfxsYpZFpz0bfzmv5NVOPnMmcNVnUrTVTnSI2u2qtK4PZUWzAfqE umrEpblI6c801vaqNj1Gind0DMM5F/QiZOXwHbAlkt1OQ7hmlyhaKYTnIYHzt40IPDcI VMeM8lgb64tovtWT0Q94Cpb6u87Do0Vik5Z6jYFvFfvE5ExYHZ1HAbF1ZNRczMN7QVm2 F4vw== X-Gm-Message-State: AA+aEWbxInFwyF7DjF8Yaq4lFwwiBW46nUBMzr9ymTyQxvubKoO8lqnT Cxn9LdCGcuzhNMFT/W23+Jj1xsqP X-Google-Smtp-Source: AFSGD/UkvUqWBVyk7eqXiB8pMnstrVc470YGyPlDDokZFG5hZv8fWdaiOT5suBm9F28Vcdb/fbK+4g== X-Received: by 2002:a63:d450:: with SMTP id i16mr4237322pgj.246.1544826749945; Fri, 14 Dec 2018 14:32:29 -0800 (PST) Received: from kern417.eng.vmware.com ([66.170.99.1]) by smtp.gmail.com with ESMTPSA id c67sm7028540pfg.170.2018.12.14.14.32.28 (version=TLS1_2 cipher=ECDHE-RSA-AES128-SHA bits=128/128); Fri, 14 Dec 2018 14:32:29 -0800 (PST) From: Yifeng Sun To: dev@openvswitch.org, Greg Rose Date: Fri, 14 Dec 2018 14:32:23 -0800 Message-Id: <1544826743-14826-1-git-send-email-pkusunyifeng@gmail.com> X-Mailer: git-send-email 2.7.4 X-Spam-Status: No, score=-2.0 required=5.0 tests=BAYES_00,DKIM_SIGNED, DKIM_VALID, DKIM_VALID_AU, FREEMAIL_FROM, RCVD_IN_DNSWL_NONE autolearn=ham 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] openvswitch: kernel datapath clone action 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 b233504033dbd65740e59681820ccfd0a2a8ec53 Author: Yifeng Sun Date: Mon Jul 2 08:18:03 2018 -0700 openvswitch: kernel datapath clone action Add 'clone' action to kernel datapath by using existing functions. When actions within clone don't modify the current flow, the flow key is not cloned before executing clone actions. This is a follow up patch for this incomplete work: https://patchwork.ozlabs.org/patch/722096/ v1 -> v2: Refactor as advised by reviewer. Signed-off-by: Yifeng Sun Signed-off-by: Andy Zhou Acked-by: Pravin B Shelar Signed-off-by: David S. Miller Co-authored-by: Andy Zhou Signed-off-by: Yifeng Sun Signed-off-by: Andy Zhou Tested-by: Greg Rose Reviewed-by: Greg Rose --- v1->v2: Use stand format for Linux upstream backports, thanks Greg! datapath/actions.c | 32 ++++++++++ datapath/flow_netlink.c | 73 +++++++++++++++++++++++ datapath/linux/compat/include/linux/openvswitch.h | 11 +++- 3 files changed, 114 insertions(+), 2 deletions(-) diff --git a/datapath/actions.c b/datapath/actions.c index 56b013601393..8abe70aa5109 100644 --- a/datapath/actions.c +++ b/datapath/actions.c @@ -1068,6 +1068,28 @@ static int sample(struct datapath *dp, struct sk_buff *skb, clone_flow_key); } +/* When 'last' is true, clone() should always consume the 'skb'. + * Otherwise, clone() should keep 'skb' intact regardless what + * actions are executed within clone(). + */ +static int clone(struct datapath *dp, struct sk_buff *skb, + struct sw_flow_key *key, const struct nlattr *attr, + bool last) +{ + struct nlattr *actions; + struct nlattr *clone_arg; + int rem = nla_len(attr); + bool dont_clone_flow_key; + + /* The first action is always 'OVS_CLONE_ATTR_ARG'. */ + clone_arg = nla_data(attr); + dont_clone_flow_key = nla_get_u32(clone_arg); + actions = nla_next(clone_arg, &rem); + + return clone_execute(dp, skb, key, 0, actions, rem, last, + !dont_clone_flow_key); +} + static void execute_hash(struct sk_buff *skb, struct sw_flow_key *key, const struct nlattr *attr) { @@ -1347,6 +1369,16 @@ static int do_execute_actions(struct datapath *dp, struct sk_buff *skb, consume_skb(skb); return 0; } + break; + + case OVS_ACTION_ATTR_CLONE: { + bool last = nla_is_last(a, rem); + + err = clone(dp, skb, key, a, last); + if (last) + return err; + break; + } } if (unlikely(err)) { diff --git a/datapath/flow_netlink.c b/datapath/flow_netlink.c index ee0c18422236..a572ed3e7345 100644 --- a/datapath/flow_netlink.c +++ b/datapath/flow_netlink.c @@ -2465,6 +2465,40 @@ static int validate_and_copy_sample(struct net *net, const struct nlattr *attr, return 0; } +static int validate_and_copy_clone(struct net *net, + const struct nlattr *attr, + const struct sw_flow_key *key, + struct sw_flow_actions **sfa, + __be16 eth_type, __be16 vlan_tci, + bool log, bool last) +{ + int start, err; + u32 exec; + + if (nla_len(attr) && nla_len(attr) < NLA_HDRLEN) + return -EINVAL; + + start = add_nested_action_start(sfa, OVS_ACTION_ATTR_CLONE, log); + if (start < 0) + return start; + + exec = last || !actions_may_change_flow(attr); + + err = ovs_nla_add_action(sfa, OVS_CLONE_ATTR_EXEC, &exec, + sizeof(exec), log); + if (err) + return err; + + err = __ovs_nla_copy_actions(net, attr, key, sfa, + eth_type, vlan_tci, log); + if (err) + return err; + + add_nested_action_end(*sfa, start); + + return 0; +} + void ovs_match_init(struct sw_flow_match *match, struct sw_flow_key *key, bool reset_key, @@ -2852,6 +2886,7 @@ static int __ovs_nla_copy_actions(struct net *net, const struct nlattr *attr, [OVS_ACTION_ATTR_PUSH_NSH] = (u32)-1, [OVS_ACTION_ATTR_POP_NSH] = 0, [OVS_ACTION_ATTR_METER] = sizeof(u32), + [OVS_ACTION_ATTR_CLONE] = (u32)-1, }; const struct ovs_action_push_vlan *vlan; int type = nla_type(a); @@ -3041,6 +3076,18 @@ static int __ovs_nla_copy_actions(struct net *net, const struct nlattr *attr, /* Non-existent meters are simply ignored. */ break; + case OVS_ACTION_ATTR_CLONE: { + bool last = nla_is_last(a, rem); + + err = validate_and_copy_clone(net, a, key, sfa, + eth_type, vlan_tci, + log, last); + if (err) + return err; + skip_copy = true; + break; + } + default: OVS_NLERR(log, "Unknown Action type %d", type); return -EINVAL; @@ -3119,6 +3166,26 @@ out: return err; } +static int clone_action_to_attr(const struct nlattr *attr, + struct sk_buff *skb) +{ + struct nlattr *start; + int err = 0, rem = nla_len(attr); + + start = nla_nest_start(skb, OVS_ACTION_ATTR_CLONE); + if (!start) + return -EMSGSIZE; + + err = ovs_nla_put_actions(nla_data(attr), rem, skb); + + if (err) + nla_nest_cancel(skb, start); + else + nla_nest_end(skb, start); + + return err; +} + static int set_action_to_attr(const struct nlattr *a, struct sk_buff *skb) { const struct nlattr *ovs_key = nla_data(a); @@ -3207,6 +3274,12 @@ int ovs_nla_put_actions(const struct nlattr *attr, int len, struct sk_buff *skb) return err; break; + case OVS_ACTION_ATTR_CLONE: + err = clone_action_to_attr(a, skb); + if (err) + return err; + break; + default: if (nla_put(skb, type, nla_len(a), nla_data(a))) return -EMSGSIZE; diff --git a/datapath/linux/compat/include/linux/openvswitch.h b/datapath/linux/compat/include/linux/openvswitch.h index aaeb0341ab51..9b087f1b0620 100644 --- a/datapath/linux/compat/include/linux/openvswitch.h +++ b/datapath/linux/compat/include/linux/openvswitch.h @@ -909,6 +909,8 @@ enum ovs_nat_attr { * tunnel header. * @OVS_ACTION_ATTR_METER: Run packet through a meter, which may drop the * packet, or modify the packet (e.g., change the DSCP field). + * @OVS_ACTION_ATTR_CLONE: make a copy of the packet and execute a list of + * actions without affecting the original packet and key. */ enum ovs_action_attr { @@ -934,12 +936,12 @@ enum ovs_action_attr { OVS_ACTION_ATTR_CT_CLEAR, /* No argument. */ OVS_ACTION_ATTR_PUSH_NSH, /* Nested OVS_NSH_KEY_ATTR_*. */ OVS_ACTION_ATTR_POP_NSH, /* No argument. */ - OVS_ACTION_ATTR_METER, /* u32 meter number. */ + OVS_ACTION_ATTR_METER, /* u32 meter number. */ + OVS_ACTION_ATTR_CLONE, /* Nested OVS_CLONE_ATTR_*. */ #ifndef __KERNEL__ OVS_ACTION_ATTR_TUNNEL_PUSH, /* struct ovs_action_push_tnl*/ OVS_ACTION_ATTR_TUNNEL_POP, /* u32 port number. */ - OVS_ACTION_ATTR_CLONE, /* Nested OVS_CLONE_ATTR_*. */ #endif __OVS_ACTION_ATTR_MAX, /* Nothing past this will be accepted * from userspace. */ @@ -1032,4 +1034,9 @@ struct ovs_zone_limit { __u32 count; }; +#define OVS_CLONE_ATTR_EXEC 0 /* Specify an u32 value. When nonzero, + * actions in clone will not change flow + * keys. False otherwise. + */ + #endif /* _LINUX_OPENVSWITCH_H */