From patchwork Thu Dec 2 10:41:11 2021 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: "Finn, Emma" X-Patchwork-Id: 1562625 Return-Path: X-Original-To: incoming@patchwork.ozlabs.org Delivered-To: patchwork-incoming@bilbo.ozlabs.org Authentication-Results: ozlabs.org; spf=pass (sender SPF authorized) smtp.mailfrom=openvswitch.org (client-ip=140.211.166.136; helo=smtp3.osuosl.org; envelope-from=ovs-dev-bounces@openvswitch.org; receiver=) Received: from smtp3.osuosl.org (smtp3.osuosl.org [140.211.166.136]) (using TLSv1.3 with cipher TLS_AES_256_GCM_SHA384 (256/256 bits) key-exchange X25519 server-signature RSA-PSS (4096 bits) server-digest SHA256) (No client certificate requested) by bilbo.ozlabs.org (Postfix) with ESMTPS id 4J4XZC5BQFz9s0r for ; Thu, 2 Dec 2021 21:41:39 +1100 (AEDT) Received: from localhost (localhost [127.0.0.1]) by smtp3.osuosl.org (Postfix) with ESMTP id 850F361CE6; Thu, 2 Dec 2021 10:41:37 +0000 (UTC) X-Virus-Scanned: amavisd-new at osuosl.org Received: from smtp3.osuosl.org ([127.0.0.1]) by localhost (smtp3.osuosl.org [127.0.0.1]) (amavisd-new, port 10024) with ESMTP id vp0KgvUOv8p3; Thu, 2 Dec 2021 10:41:36 +0000 (UTC) Received: from lists.linuxfoundation.org (lf-lists.osuosl.org [140.211.9.56]) by smtp3.osuosl.org (Postfix) with ESMTPS id 5BD8B61CE0; Thu, 2 Dec 2021 10:41:35 +0000 (UTC) Received: from lf-lists.osuosl.org (localhost [127.0.0.1]) by lists.linuxfoundation.org (Postfix) with ESMTP id 40597C0012; Thu, 2 Dec 2021 10:41:35 +0000 (UTC) X-Original-To: dev@openvswitch.org Delivered-To: ovs-dev@lists.linuxfoundation.org Received: from smtp1.osuosl.org (smtp1.osuosl.org [IPv6:2605:bc80:3010::138]) by lists.linuxfoundation.org (Postfix) with ESMTP id 5B39CC000A for ; Thu, 2 Dec 2021 10:41:34 +0000 (UTC) Received: from localhost (localhost [127.0.0.1]) by smtp1.osuosl.org (Postfix) with ESMTP id 3DA8583422 for ; Thu, 2 Dec 2021 10:41:34 +0000 (UTC) X-Virus-Scanned: amavisd-new at osuosl.org Received: from smtp1.osuosl.org ([127.0.0.1]) by localhost (smtp1.osuosl.org [127.0.0.1]) (amavisd-new, port 10024) with ESMTP id H8Ic2RWwjuAX for ; Thu, 2 Dec 2021 10:41:33 +0000 (UTC) X-Greylist: domain auto-whitelisted by SQLgrey-1.8.0 Received: from mga04.intel.com (mga04.intel.com [192.55.52.120]) by smtp1.osuosl.org (Postfix) with ESMTPS id 18C05833B7 for ; Thu, 2 Dec 2021 10:41:33 +0000 (UTC) X-IronPort-AV: E=McAfee;i="6200,9189,10185"; a="235416560" X-IronPort-AV: E=Sophos;i="5.87,281,1631602800"; d="scan'208";a="235416560" Received: from orsmga003.jf.intel.com ([10.7.209.27]) by fmsmga104.fm.intel.com with ESMTP/TLS/ECDHE-RSA-AES256-GCM-SHA384; 02 Dec 2021 02:41:32 -0800 X-ExtLoop1: 1 X-IronPort-AV: E=Sophos;i="5.87,281,1631602800"; d="scan'208";a="459607544" Received: from silpixa00400899.ir.intel.com ([10.243.23.110]) by orsmga003.jf.intel.com with ESMTP; 02 Dec 2021 02:41:31 -0800 From: Emma Finn To: dev@openvswitch.org, harry.van.haaren@intel.com, kumar.amber@intel.com Date: Thu, 2 Dec 2021 10:41:11 +0000 Message-Id: <20211202104118.4159929-2-emma.finn@intel.com> X-Mailer: git-send-email 2.25.1 In-Reply-To: <20211202104118.4159929-1-emma.finn@intel.com> References: <20211202104118.4159929-1-emma.finn@intel.com> MIME-Version: 1.0 Subject: [ovs-dev] [PATCH v1 1/8] odp-execute: Add function pointers to odp-execute for different action implementations. X-BeenThere: ovs-dev@openvswitch.org X-Mailman-Version: 2.1.15 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Errors-To: ovs-dev-bounces@openvswitch.org Sender: "dev" This commit introduces the initial infrastructure required to allow different implementations for OvS actions. The patch introduces action function pointers which allows user to switch between different action implementations available. This will allow for more performance and flexibility so the user can choose the action implementation to best suite their use case. Signed-off-by: Emma Finn --- lib/automake.mk | 2 + lib/dpif-netdev.c | 2 + lib/odp-execute-private.c | 87 ++++++++++++++++++++++++++++++++++ lib/odp-execute-private.h | 98 +++++++++++++++++++++++++++++++++++++++ lib/odp-execute.c | 40 ++++++++++++++-- lib/odp-execute.h | 4 ++ 6 files changed, 228 insertions(+), 5 deletions(-) create mode 100644 lib/odp-execute-private.c create mode 100644 lib/odp-execute-private.h diff --git a/lib/automake.mk b/lib/automake.mk index 46f869a33..16087031f 100644 --- a/lib/automake.mk +++ b/lib/automake.mk @@ -201,6 +201,8 @@ lib_libopenvswitch_la_SOURCES = \ lib/nx-match.h \ lib/object-collection.c \ lib/object-collection.h \ + lib/odp-execute-private.c \ + lib/odp-execute-private.h \ lib/odp-execute.c \ lib/odp-execute.h \ lib/odp-util.c \ diff --git a/lib/dpif-netdev.c b/lib/dpif-netdev.c index 69d7ec26e..277e0d6c3 100644 --- a/lib/dpif-netdev.c +++ b/lib/dpif-netdev.c @@ -1598,6 +1598,8 @@ create_dpif_netdev(struct dp_netdev *dp) dpif->dp = dp; dpif->last_port_seq = seq_read(dp->port_seq); + odp_execute_init(); + return &dpif->dpif; } diff --git a/lib/odp-execute-private.c b/lib/odp-execute-private.c new file mode 100644 index 000000000..1b02be223 --- /dev/null +++ b/lib/odp-execute-private.c @@ -0,0 +1,87 @@ +/* + * Copyright (c) 2021 Intel. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at: + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include +#include +#include +#include +#include "dpdk.h" + +#include "openvswitch/vlog.h" +#include "odp-execute-private.h" +#include "odp-netlink.h" +#include "dp-packet.h" +#include "odp-util.h" + + +int32_t action_autoval_init(struct odp_execute_action_impl *self); +VLOG_DEFINE_THIS_MODULE(odp_execute_private); +static struct vlog_rate_limit rl = VLOG_RATE_LIMIT_INIT(1, 1); + +static struct odp_execute_action_impl action_impls[] = { + [ACTION_IMPL_SCALAR] = { + .available = 1, + .name = "scalar", + .probe = NULL, + .init_func = odp_action_scalar_init, + }, +}; + +static uint32_t active_action_impl_index; + +static void +action_impl_copy_funcs(struct odp_execute_action_impl *to, + const struct odp_execute_action_impl *from) +{ + for (uint32_t i = 0; i < __OVS_KEY_ATTR_MAX; i++) { + atomic_uintptr_t *func = (void *) &to->funcs[i]; + atomic_store_relaxed(func, (uintptr_t) from->funcs[i]); + } +} + +void +odp_execute_action_init(void) +{ + /* Call probe on each impl, and cache the result. */ + for (int i = 0; i < ACTION_IMPL_MAX; i++) { + bool avail = true; + if (action_impls[i].probe) { + /* Return zero is success, non-zero means error. */ + avail = (action_impls[i].probe() == 0); + } + VLOG_INFO("Action implementation %s (available: %s)\n", + action_impls[i].name, avail ? "available" : "not available"); + action_impls[i].available = avail; + } + + uint32_t i; + for (i = 0; i < ACTION_IMPL_MAX; i++) { + /* Each impl's function array is initialized to reflect the scalar + * implementation. This simplifies adding optimized implementations, + * as the autovalidator can always compare all actions. + * + * Below copies the scalar functions to all other implementations. + */ + if (i != ACTION_IMPL_SCALAR) { + action_impl_copy_funcs(&action_impls[i], + &action_impls[ACTION_IMPL_SCALAR]); + } + + if (action_impls[i].init_func) { + action_impls[i].init_func(&action_impls[i]); + } + } +} \ No newline at end of file diff --git a/lib/odp-execute-private.h b/lib/odp-execute-private.h new file mode 100644 index 000000000..c2e86bbee --- /dev/null +++ b/lib/odp-execute-private.h @@ -0,0 +1,98 @@ +/* + * Copyright (c) 2021 Intel. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at: + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef ODP_EXTRACT_PRIVATE +#define ODP_EXTRACT_PRIVATE 1 + +#include "odp-execute.h" + +/* For __OVS_KEY_ATTR_MAX. */ +#include "odp-netlink.h" +#include "dp-packet.h" +#include "ovs-atomic.h" + +/* Forward declaration for typedef. */ +struct odp_execute_action_impl; + +/* Typedef for an initialization function that can initialize each + * implementation, checking requirements such as CPU ISA. + */ +typedef int32_t (*odp_execute_action_init_func) + (struct odp_execute_action_impl *self); + +/* Probe function is used to detect if this CPU has the ISA required + * to run the optimized action implementation. + * returns one on successful probe. + * returns negative errno on failure. + */ +typedef int (*odp_execute_action_probe)(void); + +/* Structure represents an implementation of the odp actions. */ +struct odp_execute_action_impl { + /* When set, the CPU ISA required for this implementation is available + * and the implementation can be used. + */ + bool available; + + /* Name of the implementation. */ + const char *name; + + /* Probe function is used to detect if this CPU has the ISA required + * to run the optimized miniflow implementation. It is optional and + * if it is not used, then it must be null. + */ + odp_execute_action_probe probe; + + /* Called to check requirements and if usable, initializes the + * implementation for use. + */ + odp_execute_action_init_func init_func; + + /* An array of callback functions, one for each action. */ + ATOMIC(odp_execute_cb) funcs[__OVS_KEY_ATTR_MAX]; +}; + +/* Order of Actions implementations. */ +enum odp_execute_action_impl_idx { + ACTION_IMPL_SCALAR, + /* See ACTION_IMPL_BEGIN below, for "first to-be-validated" impl. + * Do not change the autovalidator position in this list without updating + * the define below. + */ + + ACTION_IMPL_MAX, +}; + +/* Index to start verifying implementations from. */ +BUILD_ASSERT_DECL(ACTION_IMPL_SCALAR == 0); + +/* Odp execute init handles setting up the state of the actions functions at + * initialization time. It cannot return errors, as it must always succeed in + * initializing the scalar/generic codepath. + */ +void odp_execute_action_init(void); + +/* Update the current active functions to those requested in name. */ +void odp_execute_action_get(struct ds *name); +int32_t odp_execute_action_set(const char *name, + struct odp_execute_action_impl *active); + +/* Init function for the scalar implementation. Calls into the odp-execute.c + * file, and initializes the function pointers for optimized action types. + */ +int32_t odp_action_scalar_init(struct odp_execute_action_impl *self); + +#endif /* ODP_EXTRACT_PRIVATE */ diff --git a/lib/odp-execute.c b/lib/odp-execute.c index 6eeda2a61..94adebd4c 100644 --- a/lib/odp-execute.c +++ b/lib/odp-execute.c @@ -17,6 +17,7 @@ #include #include "odp-execute.h" +#include "odp-execute-private.h" #include #include #include @@ -830,6 +831,24 @@ requires_datapath_assistance(const struct nlattr *a) return false; } +/* The active function pointers on the datapath. ISA optimized implementations + * are enabled by plugging them into this static arary, which is consulted when + * applying actions on the datapath. + */ +static struct odp_execute_action_impl actions_active_impl; + +void +odp_execute_init(void) +{ + static struct ovsthread_once once = OVSTHREAD_ONCE_INITIALIZER; + if (ovsthread_once_start(&once)) { + odp_execute_action_init(); + odp_actions_impl_set("scalar"); + ovsthread_once_done(&once); + } +} + + /* Executes all of the 'actions_len' bytes of datapath actions in 'actions' on * the packets in 'batch'. If 'steal' is true, possibly modifies and * definitely free the packets in 'batch', otherwise leaves 'batch' unchanged. @@ -855,13 +874,12 @@ odp_execute_actions(void *dp, struct dp_packet_batch *batch, bool steal, NL_ATTR_FOR_EACH_UNSAFE (a, left, actions, actions_len) { int type = nl_attr_type(a); bool last_action = (left <= NLA_ALIGN(a->nla_len)); + /* Allow 'dp_execute_action' to steal the packet data if we do + * not need it any more. */ + bool should_steal = steal && last_action; if (requires_datapath_assistance(a)) { if (dp_execute_action) { - /* Allow 'dp_execute_action' to steal the packet data if we do - * not need it any more. */ - bool should_steal = steal && last_action; - dp_execute_action(dp, batch, a, should_steal); if (last_action || dp_packet_batch_is_empty(batch)) { @@ -876,8 +894,20 @@ odp_execute_actions(void *dp, struct dp_packet_batch *batch, bool steal, continue; } - switch ((enum ovs_action_attr) type) { + /* If type is set in the active actions implementation, call the + * function-pointer and an continue to the next action. + */ + enum ovs_action_attr attr_type = (enum ovs_action_attr) type; + if (actions_active_impl.funcs[attr_type]) { + actions_active_impl.funcs[attr_type](NULL, batch, a, should_steal); + continue; + } + + /* If the action was not handled by the active function pointers above, + * process them by switching on the type below. + */ + switch (attr_type) { case OVS_ACTION_ATTR_HASH: { const struct ovs_action_hash *hash_act = nl_attr_get(a); diff --git a/lib/odp-execute.h b/lib/odp-execute.h index a3578a575..c4f5303e7 100644 --- a/lib/odp-execute.h +++ b/lib/odp-execute.h @@ -28,6 +28,10 @@ struct dp_packet; struct pkt_metadata; struct dp_packet_batch; + +/* Called once at initialization time. */ +void odp_execute_init(void); + typedef void (*odp_execute_cb)(void *dp, struct dp_packet_batch *batch, const struct nlattr *action, bool should_steal);