From patchwork Wed Jan 5 16:53:41 2022 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: "Finn, Emma" X-Patchwork-Id: 1575763 Return-Path: X-Original-To: incoming@patchwork.ozlabs.org Delivered-To: patchwork-incoming@bilbo.ozlabs.org Authentication-Results: bilbo.ozlabs.org; dkim=fail reason="signature verification failed" (2048-bit key; unprotected) header.d=intel.com header.i=@intel.com header.a=rsa-sha256 header.s=Intel header.b=hmzuMDu7; dkim-atps=neutral Authentication-Results: ozlabs.org; spf=pass (sender SPF authorized) smtp.mailfrom=openvswitch.org (client-ip=140.211.166.133; helo=smtp2.osuosl.org; envelope-from=ovs-dev-bounces@openvswitch.org; receiver=) Received: from smtp2.osuosl.org (smtp2.osuosl.org [140.211.166.133]) (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 4JTbDS4wcTz9sSs for ; Thu, 6 Jan 2022 03:54:16 +1100 (AEDT) Received: from localhost (localhost [127.0.0.1]) by smtp2.osuosl.org (Postfix) with ESMTP id EF45A409F8; Wed, 5 Jan 2022 16:54:11 +0000 (UTC) X-Virus-Scanned: amavisd-new at osuosl.org Received: from smtp2.osuosl.org ([127.0.0.1]) by localhost (smtp2.osuosl.org [127.0.0.1]) (amavisd-new, port 10024) with ESMTP id Ga5Vi0YNjZNn; Wed, 5 Jan 2022 16:54:09 +0000 (UTC) Received: from lists.linuxfoundation.org (lf-lists.osuosl.org [140.211.9.56]) by smtp2.osuosl.org (Postfix) with ESMTPS id 7079C4091C; Wed, 5 Jan 2022 16:54:08 +0000 (UTC) Received: from lf-lists.osuosl.org (localhost [127.0.0.1]) by lists.linuxfoundation.org (Postfix) with ESMTP id 33F85C0031; Wed, 5 Jan 2022 16:54:08 +0000 (UTC) X-Original-To: dev@openvswitch.org Delivered-To: ovs-dev@lists.linuxfoundation.org Received: from smtp1.osuosl.org (smtp1.osuosl.org [140.211.166.138]) by lists.linuxfoundation.org (Postfix) with ESMTP id 998C8C002F for ; Wed, 5 Jan 2022 16:54:06 +0000 (UTC) Received: from localhost (localhost [127.0.0.1]) by smtp1.osuosl.org (Postfix) with ESMTP id 79D4182D17 for ; Wed, 5 Jan 2022 16:54:06 +0000 (UTC) X-Virus-Scanned: amavisd-new at osuosl.org Authentication-Results: smtp1.osuosl.org (amavisd-new); dkim=pass (2048-bit key) header.d=intel.com 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 W4R18KBueTPj for ; Wed, 5 Jan 2022 16:54:05 +0000 (UTC) X-Greylist: domain auto-whitelisted by SQLgrey-1.8.0 Received: from mga14.intel.com (mga14.intel.com [192.55.52.115]) by smtp1.osuosl.org (Postfix) with ESMTPS id 4721382D57 for ; Wed, 5 Jan 2022 16:54:05 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=intel.com; i=@intel.com; q=dns/txt; s=Intel; t=1641401645; x=1672937645; h=from:to:cc:subject:date:message-id:in-reply-to: references:mime-version:content-transfer-encoding; bh=AHmatPNZVwpMnC0hUzykKASWZPepuzQMEPkfNDs7MAw=; b=hmzuMDu7dNfo0MghKvp+BbVg8G2R5f1HDI3PJD2cn4qNkH6yhOTvaQfa ZMvFVirJfisExoB+/0LFGBOfG0GqVRy4dEvYI/1IlpUtp8DUdIfvPjCEc yC02mqsv9I0Pij/EEA0Brg12OvFQFu3EWm1oGC4o+uNggBvsBAzwGdL4P S7a2NhQH41bxA41zLJPY+RkdhUYjQCzuZ6R/2+Mv+zyulJ4NCttdPBIZf DIACR6tXoL6ZXDdfPV+eU7hsOfIW4PDCGdgmCIq4U6hF7pCMBTHIehIpZ Zqm/rAMQhB4MgcgGUtpPgAkmkponukFQw0taX95UFcDYIDQvy381enTCf A==; X-IronPort-AV: E=McAfee;i="6200,9189,10217"; a="242688509" X-IronPort-AV: E=Sophos;i="5.88,264,1635231600"; d="scan'208";a="242688509" Received: from fmsmga003.fm.intel.com ([10.253.24.29]) by fmsmga103.fm.intel.com with ESMTP/TLS/ECDHE-RSA-AES256-GCM-SHA384; 05 Jan 2022 08:54:05 -0800 X-ExtLoop1: 1 X-IronPort-AV: E=Sophos;i="5.88,264,1635231600"; d="scan'208";a="611525777" Received: from silpixa00400899.ir.intel.com ([10.243.23.110]) by FMSMGA003.fm.intel.com with ESMTP; 05 Jan 2022 08:54:03 -0800 From: Emma Finn To: dev@openvswitch.org, harry.van.haaren@intel.com, kumar.amber@intel.com Date: Wed, 5 Jan 2022 16:53:41 +0000 Message-Id: <20220105165349.3447695-2-emma.finn@intel.com> X-Mailer: git-send-email 2.25.1 In-Reply-To: <20220105165349.3447695-1-emma.finn@intel.com> References: <20211203153301.37692-1-emma.finn@intel.com> <20220105165349.3447695-1-emma.finn@intel.com> MIME-Version: 1.0 Subject: [ovs-dev] [PATCH v4 1/9] 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 Acked-by: Harry van Haaren --- lib/automake.mk | 2 + lib/dpif-netdev.c | 2 + lib/odp-execute-private.c | 84 +++++++++++++++++++++++++++++++++ lib/odp-execute-private.h | 98 +++++++++++++++++++++++++++++++++++++++ lib/odp-execute.c | 39 ++++++++++++++-- lib/odp-execute.h | 4 ++ 6 files changed, 224 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 5224e0856..1bc855a6b 100644 --- a/lib/automake.mk +++ b/lib/automake.mk @@ -203,6 +203,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 a790df5fd..53127ac1a 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..6441c491c --- /dev/null +++ b/lib/odp-execute-private.c @@ -0,0 +1,84 @@ +/* + * 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 odp_execute_action_impl action_impls[] = { + [ACTION_IMPL_SCALAR] = { + .available = 1, + .name = "scalar", + .probe = NULL, + .init_func = NULL, + }, +}; + +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]); + } + } +} 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..49dfa2a74 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,23 @@ 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(); + 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 +873,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 +893,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);