From patchwork Fri Apr 7 00:18:24 2017 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Andy Zhou X-Patchwork-Id: 748008 Return-Path: X-Original-To: incoming@patchwork.ozlabs.org Delivered-To: patchwork-incoming@bilbo.ozlabs.org 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 3vzgKh5Wwmz9s3w for ; Fri, 7 Apr 2017 10:23:36 +1000 (AEST) Received: from mail.linux-foundation.org (localhost [127.0.0.1]) by mail.linuxfoundation.org (Postfix) with ESMTP id 0C364B7E; Fri, 7 Apr 2017 00:18:57 +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 B1542978 for ; Fri, 7 Apr 2017 00:18:53 +0000 (UTC) X-Greylist: whitelisted by SQLgrey-1.7.6 Received: from mail-pg0-f65.google.com (mail-pg0-f65.google.com [74.125.83.65]) by smtp1.linuxfoundation.org (Postfix) with ESMTPS id ECF09267 for ; Fri, 7 Apr 2017 00:18:52 +0000 (UTC) Received: by mail-pg0-f65.google.com with SMTP id o123so11360791pga.1 for ; Thu, 06 Apr 2017 17:18:52 -0700 (PDT) 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:in-reply-to :references:content-transfer-encoding; bh=FY5gpkbdUZaswm8N5NHXpu7l/OgQ0KpOsUwmycVeGZY=; b=KA6a/4DPzss06Fjdg6z8+19gSh2PuMsZswP8HhDqYZqpvyuviklq160honsKrB8OKi MdbOYQRqW6yP+fkGupVRpz98c4Pa7b7nweBQa5KhETljWJMHkeb4U6Z9f5F9vXusmQVO 3vs/FAp+BTJUj+agUhYWN+gfAlnmzEmE91fa/q0Mk4rKpqZukM7JZ+WLoEvjcB6+3kCK PUnVp+0iiZ5bGKe0IElrT68dzReVT9fdhakHhK3h6Fn7ZAYdv+PoBDkcpyYoiI6gEh5n yuuTnORZ9WvpXUilK05lsUCjShXPcg4LgbLKPRZV+/OswWDRV3EmudfRSGEKgLIcNPv5 3l9g== X-Gm-Message-State: AFeK/H3zWTNPz2gSrZYY7Jwgz8DpwWQdsHIlPaCIYeMkaSakVxLoT3HkbfWs9+HLNXBFQw== X-Received: by 10.99.174.9 with SMTP id q9mr37317827pgf.232.1491524332455; Thu, 06 Apr 2017 17:18:52 -0700 (PDT) Received: from centos.eng.vmware.com ([208.91.1.34]) by smtp.gmail.com with ESMTPSA id p6sm5713090pgn.9.2017.04.06.17.18.51 (version=TLS1_2 cipher=ECDHE-RSA-AES128-GCM-SHA256 bits=128/128); Thu, 06 Apr 2017 17:18:51 -0700 (PDT) From: Andy Zhou To: dev@openvswitch.org Date: Thu, 6 Apr 2017 17:18:24 -0700 Message-Id: <1491524304-1907-10-git-send-email-azhou@ovn.org> X-Mailer: git-send-email 1.8.3.1 In-Reply-To: <1491524304-1907-1-git-send-email-azhou@ovn.org> References: <1491524304-1907-1-git-send-email-azhou@ovn.org> X-Spam-Status: No, score=-1.4 required=5.0 tests=BAYES_00,FREEMAIL_FROM, RCVD_IN_DNSWL_NONE,RCVD_IN_SORBS_SPAM 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] [datapath backport 10/10] datapath: Openvswitch: Refactor sample and recirc actions implementation 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: Openvswitch: Refactor sample and recirc actions implementation Added clone_execute() that both the sample and the recirc action implementation can use. Signed-off-by: Andy Zhou Acked-by: Pravin B Shelar Signed-off-by: David S. Miller Upstream: bef7f7567a10 ("Openvswitch: Refactor sample and recirc actions implementation") Signed-off-by: Andy Zhou Acked-by: Joe Stringer --- datapath/actions.c | 172 +++++++++++++++++++++++++++++------------------------ 1 file changed, 93 insertions(+), 79 deletions(-) diff --git a/datapath/actions.c b/datapath/actions.c index 32c0c10e7c62..1f3b2fe4ab73 100644 --- a/datapath/actions.c +++ b/datapath/actions.c @@ -169,6 +169,12 @@ static bool is_flow_key_valid(const struct sw_flow_key *key) return !(key->mac_proto & SW_FLOW_KEY_INVALID); } +static int clone_execute(struct datapath *dp, struct sk_buff *skb, + struct sw_flow_key *key, + u32 recirc_id, + const struct nlattr *actions, int len, + bool last, bool clone_flow_key); + static void update_ethertype(struct sk_buff *skb, struct ethhdr *hdr, __be16 ethertype) { @@ -927,10 +933,9 @@ static int sample(struct datapath *dp, struct sk_buff *skb, { struct nlattr *actions; struct nlattr *sample_arg; - struct sw_flow_key *orig_key = key; int rem = nla_len(attr); - int err = 0; const struct sample_arg *arg; + bool clone_flow_key; /* The first action is always 'OVS_SAMPLE_ATTR_ARG'. */ sample_arg = nla_data(attr); @@ -944,43 +949,9 @@ static int sample(struct datapath *dp, struct sk_buff *skb, return 0; } - /* Unless the last action, sample works on the clone of SKB. */ - skb = last ? skb : skb_clone(skb, GFP_ATOMIC); - if (!skb) { - /* Out of memory, skip this sample action. - */ - return 0; - } - - /* In case the sample actions won't change 'key', - * it can be used directly to execute sample actions. - * Otherwise, allocate a new key from the - * next recursion level of 'flow_keys'. If - * successful, execute the sample actions without - * deferring. - * - * Defer the sample actions if the recursion - * limit has been reached. - */ - if (!arg->exec) { - __this_cpu_inc(exec_actions_level); - key = clone_key(key); - } - - if (key) { - err = do_execute_actions(dp, skb, key, actions, rem); - } else if (!add_deferred_actions(skb, orig_key, actions, rem)) { - - if (net_ratelimit()) - pr_warn("%s: deferred action limit reached, drop sample action\n", - ovs_dp_name(dp)); - kfree_skb(skb); - } - - if (!arg->exec) - __this_cpu_dec(exec_actions_level); - - return err; + clone_flow_key = !arg->exec; + return clone_execute(dp, skb, key, 0, actions, rem, last, + clone_flow_key); } static void execute_hash(struct sk_buff *skb, struct sw_flow_key *key, @@ -1091,10 +1062,9 @@ static int execute_masked_set_action(struct sk_buff *skb, static int execute_recirc(struct datapath *dp, struct sk_buff *skb, struct sw_flow_key *key, - const struct nlattr *a, int rem) + const struct nlattr *a, bool last) { - struct sw_flow_key *recirc_key; - struct deferred_action *da; + u32 recirc_id; if (!is_flow_key_valid(key)) { int err; @@ -1105,40 +1075,8 @@ static int execute_recirc(struct datapath *dp, struct sk_buff *skb, } BUG_ON(!is_flow_key_valid(key)); - if (!nla_is_last(a, rem)) { - /* Recirc action is the not the last action - * of the action list, need to clone the skb. - */ - skb = skb_clone(skb, GFP_ATOMIC); - - /* Skip the recirc action when out of memory, but - * continue on with the rest of the action list. - */ - if (!skb) - return 0; - } - - /* If within the limit of 'OVS_DEFERRED_ACTION_THRESHOLD', - * recirc immediately, otherwise, defer it for later execution. - */ - recirc_key = clone_key(key); - if (recirc_key) { - recirc_key->recirc_id = nla_get_u32(a); - ovs_dp_process_packet(skb, recirc_key); - } else { - da = add_deferred_actions(skb, key, NULL, 0); - if (da) { - recirc_key = &da->pkt_key; - recirc_key->recirc_id = nla_get_u32(a); - } else { - /* Log an error in case action fifo is full. */ - kfree_skb(skb); - if (net_ratelimit()) - pr_warn("%s: deferred action limit reached, drop recirc action\n", - ovs_dp_name(dp)); - } - } - return 0; + recirc_id = nla_get_u32(a); + return clone_execute(dp, skb, key, recirc_id, NULL, 0, last, true); } /* Execute a list of actions against 'skb'. */ @@ -1210,9 +1148,11 @@ static int do_execute_actions(struct datapath *dp, struct sk_buff *skb, err = pop_vlan(skb, key); break; - case OVS_ACTION_ATTR_RECIRC: - err = execute_recirc(dp, skb, key, a, rem); - if (nla_is_last(a, rem)) { + case OVS_ACTION_ATTR_RECIRC: { + bool last = nla_is_last(a, rem); + + err = execute_recirc(dp, skb, key, a, last); + if (last) { /* If this is the last action, the skb has * been consumed or freed. * Return immediately. @@ -1220,6 +1160,7 @@ static int do_execute_actions(struct datapath *dp, struct sk_buff *skb, return err; } break; + } case OVS_ACTION_ATTR_SET: err = execute_set_action(skb, key, nla_data(a)); @@ -1274,6 +1215,79 @@ static int do_execute_actions(struct datapath *dp, struct sk_buff *skb, return 0; } +/* Execute the actions on the clone of the packet. The effect of the + * execution does not affect the original 'skb' nor the original 'key'. + * + * The execution may be deferred in case the actions can not be executed + * immediately. + */ +static int clone_execute(struct datapath *dp, struct sk_buff *skb, + struct sw_flow_key *key, u32 recirc_id, + const struct nlattr *actions, int len, + bool last, bool clone_flow_key) +{ + struct deferred_action *da; + struct sw_flow_key *clone; + + skb = last ? skb : skb_clone(skb, GFP_ATOMIC); + if (!skb) { + /* Out of memory, skip this action. + */ + return 0; + } + + /* When clone_flow_key is false, the 'key' will not be change + * by the actions, then the 'key' can be used directly. + * Otherwise, try to clone key from the next recursion level of + * 'flow_keys'. If clone is successful, execute the actions + * without deferring. + */ + clone = clone_flow_key ? clone_key(key) : key; + if (clone) { + int err = 0; + + if (actions) { /* Sample action */ + if (clone_flow_key) + __this_cpu_inc(exec_actions_level); + + err = do_execute_actions(dp, skb, clone, + actions, len); + + if (clone_flow_key) + __this_cpu_dec(exec_actions_level); + } else { /* Recirc action */ + clone->recirc_id = recirc_id; + ovs_dp_process_packet(skb, clone); + } + return err; + } + + /* Out of 'flow_keys' space. Defer actions */ + da = add_deferred_actions(skb, key, actions, len); + if (da) { + if (!actions) { /* Recirc action */ + key = &da->pkt_key; + key->recirc_id = recirc_id; + } + } else { + /* Out of per CPU action FIFO space. Drop the 'skb' and + * log an error. + */ + kfree_skb(skb); + + if (net_ratelimit()) { + if (actions) { /* Sample action */ + pr_warn("%s: deferred action limit reached, drop sample action\n", + ovs_dp_name(dp)); + } else { /* Recirc action */ + pr_warn("%s: deferred action limit reached, drop recirc action\n", + ovs_dp_name(dp)); + } + } + } + return 0; +} + static void process_deferred_actions(struct datapath *dp) { struct action_fifo *fifo = this_cpu_ptr(action_fifos);