From patchwork Wed Jan 12 09:42:37 2022 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: "Finn, Emma" X-Patchwork-Id: 1578951 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=FtJ9uFV1; dkim-atps=neutral Authentication-Results: ozlabs.org; spf=pass (sender SPF authorized) smtp.mailfrom=openvswitch.org (client-ip=2605:bc80:3010::138; helo=smtp1.osuosl.org; envelope-from=ovs-dev-bounces@openvswitch.org; receiver=) Received: from smtp1.osuosl.org (smtp1.osuosl.org [IPv6:2605:bc80:3010::138]) (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 4JYjL82Y9Sz9sXM for ; Wed, 12 Jan 2022 20:43:28 +1100 (AEDT) Received: from localhost (localhost [127.0.0.1]) by smtp1.osuosl.org (Postfix) with ESMTP id 8311783F99; Wed, 12 Jan 2022 09:43:23 +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 Nljf088oclEv; Wed, 12 Jan 2022 09:43:22 +0000 (UTC) Received: from lists.linuxfoundation.org (lf-lists.osuosl.org [IPv6:2605:bc80:3010:104::8cd3:938]) by smtp1.osuosl.org (Postfix) with ESMTPS id E536983F2E; Wed, 12 Jan 2022 09:43:20 +0000 (UTC) Received: from lf-lists.osuosl.org (localhost [127.0.0.1]) by lists.linuxfoundation.org (Postfix) with ESMTP id 2A24DC0074; Wed, 12 Jan 2022 09:43:19 +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 1C013C002F for ; Wed, 12 Jan 2022 09:43:17 +0000 (UTC) Received: from localhost (localhost [127.0.0.1]) by smtp1.osuosl.org (Postfix) with ESMTP id 33C7883F7B for ; Wed, 12 Jan 2022 09:43:16 +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 DC-gnz5rPDWB for ; Wed, 12 Jan 2022 09:43:15 +0000 (UTC) X-Greylist: domain auto-whitelisted by SQLgrey-1.8.0 Received: from mga17.intel.com (mga17.intel.com [192.55.52.151]) by smtp1.osuosl.org (Postfix) with ESMTPS id 0DA3883F7C for ; Wed, 12 Jan 2022 09:43:14 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=intel.com; i=@intel.com; q=dns/txt; s=Intel; t=1641980595; x=1673516595; h=from:to:cc:subject:date:message-id:in-reply-to: references:mime-version:content-transfer-encoding; bh=pDHKtTnfGJ9NrSr+CGvU12zvEwYMu5mWgYRphq+ZTdQ=; b=FtJ9uFV1KQsziSrOeAHDDya30tWHn7iz0cyQVhB2rdcnwolwNR3S16CX tVa3Aez6s9FoV6IohbsE9XVLUm2mVZRrIRbeJXwosW4/mNomPGpJCu1ai 9P7PdNlYdoRNy1WFy+T7dik2VdkoltxcavonUyvoH489G4BUsbt4BjgoP N5gjlda8h+0hcOpHS1OpdswLnld3FJ9CpNwtw5h6LP5MZqOHgqTPTCxqA TDinDHwDqoHccPCr8M9aw49VATDyneWrVwphA7o6jXMg9VdRAJaeTDfLZ IpeCYSNPYzGXYm7OgEy3RBZotX6TcMXWAwk5e/9nKgKD/ZNIS+shiUc8y w==; X-IronPort-AV: E=McAfee;i="6200,9189,10224"; a="224394744" X-IronPort-AV: E=Sophos;i="5.88,282,1635231600"; d="scan'208";a="224394744" Received: from orsmga002.jf.intel.com ([10.7.209.21]) by fmsmga107.fm.intel.com with ESMTP/TLS/ECDHE-RSA-AES256-GCM-SHA384; 12 Jan 2022 01:43:09 -0800 X-ExtLoop1: 1 X-IronPort-AV: E=Sophos;i="5.88,282,1635231600"; d="scan'208";a="490688267" Received: from silpixa00400899.ir.intel.com ([10.243.23.110]) by orsmga002.jf.intel.com with ESMTP; 12 Jan 2022 01:43:07 -0800 From: Emma Finn To: dev@openvswitch.org, harry.van.haaren@intel.com, kumar.amber@intel.com, ian.stokes@intel.com, i.maximets@ovn.org Date: Wed, 12 Jan 2022 09:42:37 +0000 Message-Id: <20220112094244.81402-2-emma.finn@intel.com> X-Mailer: git-send-email 2.25.1 In-Reply-To: <20220112094244.81402-1-emma.finn@intel.com> References: <20220105165349.3447695-1-emma.finn@intel.com> <20220112094244.81402-1-emma.finn@intel.com> MIME-Version: 1.0 Subject: [ovs-dev] [PATCH v5 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 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 649c700cb..eada4fcd7 100644 --- a/lib/dpif-netdev.c +++ b/lib/dpif-netdev.c @@ -1618,6 +1618,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);