From patchwork Wed Feb 10 14:57:20 2021 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Gaetan Rivet X-Patchwork-Id: 1439006 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=) Authentication-Results: ozlabs.org; dkim=fail reason="signature verification failed" (2048-bit key; unprotected) header.d=u256.net header.i=@u256.net header.a=rsa-sha256 header.s=fm1 header.b=MylS5HCj; dkim=fail reason="signature verification failed" (2048-bit key; unprotected) header.d=messagingengine.com header.i=@messagingengine.com header.a=rsa-sha256 header.s=fm2 header.b=JQUV8BR6; dkim-atps=neutral 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 ozlabs.org (Postfix) with ESMTPS id 4DbNQn21pgz9sB4 for ; Thu, 11 Feb 2021 02:07:13 +1100 (AEDT) Received: from localhost (localhost [127.0.0.1]) by smtp3.osuosl.org (Postfix) with ESMTP id 5CAD06F79C for ; Wed, 10 Feb 2021 15:07:11 +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 PZT6T7yjlaxE for ; Wed, 10 Feb 2021 15:07:09 +0000 (UTC) Received: by smtp3.osuosl.org (Postfix, from userid 1001) id 90DC96F6DE; Wed, 10 Feb 2021 15:07:09 +0000 (UTC) Received: from lists.linuxfoundation.org (lf-lists.osuosl.org [140.211.9.56]) by smtp3.osuosl.org (Postfix) with ESMTP id D005F6F62B; Wed, 10 Feb 2021 15:06:46 +0000 (UTC) Received: from lf-lists.osuosl.org (localhost [127.0.0.1]) by lists.linuxfoundation.org (Postfix) with ESMTP id 82AAEC1DA9; Wed, 10 Feb 2021 15:06:46 +0000 (UTC) X-Original-To: dev@openvswitch.org Delivered-To: ovs-dev@lists.linuxfoundation.org Received: from fraxinus.osuosl.org (smtp4.osuosl.org [140.211.166.137]) by lists.linuxfoundation.org (Postfix) with ESMTP id 4EAF7C013A for ; Wed, 10 Feb 2021 15:06:44 +0000 (UTC) Received: from localhost (localhost [127.0.0.1]) by fraxinus.osuosl.org (Postfix) with ESMTP id 3E8A986892 for ; Wed, 10 Feb 2021 15:06:44 +0000 (UTC) X-Virus-Scanned: amavisd-new at osuosl.org Received: from fraxinus.osuosl.org ([127.0.0.1]) by localhost (.osuosl.org [127.0.0.1]) (amavisd-new, port 10024) with ESMTP id d--OdaH-wG8a for ; Wed, 10 Feb 2021 15:06:43 +0000 (UTC) X-Greylist: from auto-whitelisted by SQLgrey-1.7.6 Received: from wnew4-smtp.messagingengine.com (wnew4-smtp.messagingengine.com [64.147.123.18]) by fraxinus.osuosl.org (Postfix) with ESMTPS id 0FE7C86521 for ; Wed, 10 Feb 2021 15:06:43 +0000 (UTC) Received: from compute1.internal (compute1.nyi.internal [10.202.2.41]) by mailnew.west.internal (Postfix) with ESMTP id 26397C89; Wed, 10 Feb 2021 09:57:50 -0500 (EST) Received: from mailfrontend1 ([10.202.2.162]) by compute1.internal (MEProxy); Wed, 10 Feb 2021 09:57:50 -0500 DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=u256.net; h=from :to:cc:subject:date:message-id:in-reply-to:references :mime-version:content-transfer-encoding; s=fm1; bh=0jH5ZRgvVDRqY xCdZw6rWVpGOq9a655iIyHUK3sekDc=; b=MylS5HCjASf4Rw9ixaZlWMXssU/j5 z/icUpw/gfY3kmu1o3v/9t4xsyphD1RPOVfG6kvFllM4TTl5ITtWDXyV43WKFLGr xaeAVV7Vy3mMwWzkG04G3Gl8MzwHeuizixEBCyWCh2CaktrZ5E4LZRBAKqZST4zF R8uyaFTqHZwdH4jk9vsr3qL593rMmOl1AkoLLPVWbRv9P3/sRDFAGvGOQtfQCiN5 J1xIDqEvFHMzQWf/OIEtEtgSoXwZjA+Pepovb3Lz03Tr4WjeD89OuPIJVumnkcwS 6xKPaNJZg/PiTQiHMKJyOSrL9YTTc46M1zHFZPeEuQIJ+bimixRMnFUiw== DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d= messagingengine.com; h=cc:content-transfer-encoding:date:from :in-reply-to:message-id:mime-version:references:subject:to :x-me-proxy:x-me-proxy:x-me-sender:x-me-sender:x-sasl-enc; s= fm2; bh=0jH5ZRgvVDRqYxCdZw6rWVpGOq9a655iIyHUK3sekDc=; b=JQUV8BR6 cC5G5Q0L4ceuC3sWUsQF63EPEOQ9Mqb7KtCEhm+gV2FNFmODZxCqEKgZRlnMM3sw +1cVcILhMK1kEHkKhTZBUhziEr7MQMFay6iaf7Jix6q9kjhbugKmaUo83EV20CRY n9+47nrkEuIRB9wsr6bJ3RjzuTTeai3gqU9t3xecQsGbh9OGxe5H0rHH6cMC2Cpj pEM79e+0DEUj2hVaYNZglkZ7v7fn61D27+P5D5aBJr9zq9k1L8rSTa7SJxfUAq4Y +IkjgBcr7TrEFzTX1bNmqACckSW4jjTXow6medcHEot3hqipwSR95pXaOtGQtWZ8 UBUSBP7H29xdIg== X-ME-Sender: X-ME-Proxy-Cause: gggruggvucftvghtrhhoucdtuddrgeduledrheejgdejtdcutefuodetggdotefrodftvf curfhrohhfihhlvgemucfhrghsthforghilhdpqfgfvfdpuffrtefokffrpgfnqfghnecu uegrihhlohhuthemuceftddtnecunecujfgurhephffvufffkffojghfggfgsedtkeertd ertddtnecuhfhrohhmpefirggvthgrnhcutfhivhgvthcuoehgrhhivhgvsehuvdehiedr nhgvtheqnecuggftrfgrthhtvghrnhephefgveffkeetheetfeeifedvheelfeejfeehve duteejhfekuedtkeeiuedvteehnecukfhppeekiedrvdehgedrudeigedrudejgeenucev lhhushhtvghrufhiiigvpedtnecurfgrrhgrmhepmhgrihhlfhhrohhmpehgrhhivhgvse huvdehiedrnhgvth X-ME-Proxy: Received: from inocybe.home (lfbn-poi-1-842-174.w86-254.abo.wanadoo.fr [86.254.164.174]) by mail.messagingengine.com (Postfix) with ESMTPA id 88F0D240065; Wed, 10 Feb 2021 09:57:48 -0500 (EST) From: Gaetan Rivet To: dev@openvswitch.org Date: Wed, 10 Feb 2021 15:57:20 +0100 Message-Id: <6c66b5bb17c5be666b555b1ee47968b4e15dff2a.1612968146.git.grive@u256.net> X-Mailer: git-send-email 2.30.0 In-Reply-To: References: MIME-Version: 1.0 Cc: elibr@nvidia.com, ameerm@nvidia.com, i.maximets@ovn.org, majd@nvidia.com Subject: [ovs-dev] [PATCH v1 02/23] netdev-offload-dpdk: Use per-netdev offload metadata 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" Add a per-netdev offload data field as part of netdev hw_info structure. Use this field in netdev-offload-dpdk to map offload metadata (ufid to rte_flow). Use flow API deinit ops to destroy the per-netdev metadata when deallocating a netdev. Use RCU primitives to ensure coherency during port deletion. Signed-off-by: Gaetan Rivet Reviewed-by: Eli Britstein --- lib/netdev-offload-dpdk.c | 131 ++++++++++++++++++++++++++++++++------ lib/netdev-offload.h | 2 + 2 files changed, 114 insertions(+), 19 deletions(-) diff --git a/lib/netdev-offload-dpdk.c b/lib/netdev-offload-dpdk.c index f2413f5be..47e56af23 100644 --- a/lib/netdev-offload-dpdk.c +++ b/lib/netdev-offload-dpdk.c @@ -26,6 +26,7 @@ #include "netdev-provider.h" #include "openvswitch/match.h" #include "openvswitch/vlog.h" +#include "ovs-rcu.h" #include "packets.h" #include "uuid.h" @@ -52,7 +53,6 @@ static struct vlog_rate_limit rl = VLOG_RATE_LIMIT_INIT(100, 5); /* * A mapping from ufid to dpdk rte_flow. */ -static struct cmap ufid_to_rte_flow = CMAP_INITIALIZER; struct ufid_to_rte_flow_data { struct cmap_node node; @@ -63,14 +63,81 @@ struct ufid_to_rte_flow_data { struct dpif_flow_stats stats; }; +struct netdev_offload_dpdk_data { + struct cmap ufid_to_rte_flow; +}; + +static int +offload_data_init(struct netdev *netdev) +{ + struct netdev_offload_dpdk_data *data; + + data = xzalloc(sizeof *data); + cmap_init(&data->ufid_to_rte_flow); + + ovsrcu_set(&netdev->hw_info.offload_data, (void *) data); + + return 0; +} + +static void +offload_data_destroy__(struct netdev_offload_dpdk_data *data) +{ + free(data); +} + +static void +offload_data_destroy(struct netdev *netdev) +{ + struct netdev_offload_dpdk_data *data; + struct ufid_to_rte_flow_data *node; + + data = (struct netdev_offload_dpdk_data *) + ovsrcu_get(void *, &netdev->hw_info.offload_data); + if (data == NULL) { + return; + } + + if (!cmap_is_empty(&data->ufid_to_rte_flow)) { + VLOG_ERR("Incomplete flush: %s contains rte_flow elements", + netdev_get_name(netdev)); + } + + CMAP_FOR_EACH (node, node, &data->ufid_to_rte_flow) { + ovsrcu_postpone(free, node); + } + + cmap_destroy(&data->ufid_to_rte_flow); + ovsrcu_postpone(offload_data_destroy__, data); + + ovsrcu_set(&netdev->hw_info.offload_data, NULL); +} + +static struct cmap * +offload_data_map(struct netdev *netdev) +{ + struct netdev_offload_dpdk_data *data; + + data = (struct netdev_offload_dpdk_data *) + ovsrcu_get(void *, &netdev->hw_info.offload_data); + + return data ? &data->ufid_to_rte_flow : NULL; +} + /* Find rte_flow with @ufid. */ static struct ufid_to_rte_flow_data * -ufid_to_rte_flow_data_find(const ovs_u128 *ufid, bool warn) +ufid_to_rte_flow_data_find(struct netdev *netdev, + const ovs_u128 *ufid, bool warn) { size_t hash = hash_bytes(ufid, sizeof *ufid, 0); struct ufid_to_rte_flow_data *data; + struct cmap *map = offload_data_map(netdev); + + if (!map) { + return NULL; + } - CMAP_FOR_EACH_WITH_HASH (data, node, hash, &ufid_to_rte_flow) { + CMAP_FOR_EACH_WITH_HASH (data, node, hash, map) { if (ovs_u128_equals(*ufid, data->ufid)) { return data; } @@ -85,12 +152,19 @@ ufid_to_rte_flow_data_find(const ovs_u128 *ufid, bool warn) } static inline struct ufid_to_rte_flow_data * -ufid_to_rte_flow_associate(const ovs_u128 *ufid, struct netdev *netdev, +ufid_to_rte_flow_associate(struct netdev *netdev, const ovs_u128 *ufid, struct rte_flow *rte_flow, bool actions_offloaded) { size_t hash = hash_bytes(ufid, sizeof *ufid, 0); - struct ufid_to_rte_flow_data *data = xzalloc(sizeof *data); + struct cmap *map = offload_data_map(netdev); struct ufid_to_rte_flow_data *data_prev; + struct ufid_to_rte_flow_data *data; + + if (!map) { + return NULL; + } + + data = xzalloc(sizeof *data); /* * We should not simply overwrite an existing rte flow. @@ -98,7 +172,7 @@ ufid_to_rte_flow_associate(const ovs_u128 *ufid, struct netdev *netdev, * Thus, if following assert triggers, something is wrong: * the rte_flow is not destroyed. */ - data_prev = ufid_to_rte_flow_data_find(ufid, false); + data_prev = ufid_to_rte_flow_data_find(netdev, ufid, false); if (data_prev) { ovs_assert(data_prev->rte_flow == NULL); } @@ -108,8 +182,7 @@ ufid_to_rte_flow_associate(const ovs_u128 *ufid, struct netdev *netdev, data->rte_flow = rte_flow; data->actions_offloaded = actions_offloaded; - cmap_insert(&ufid_to_rte_flow, - CONST_CAST(struct cmap_node *, &data->node), hash); + cmap_insert(map, CONST_CAST(struct cmap_node *, &data->node), hash); return data; } @@ -117,9 +190,13 @@ static inline void ufid_to_rte_flow_disassociate(struct ufid_to_rte_flow_data *data) { size_t hash = hash_bytes(&data->ufid, sizeof data->ufid, 0); + struct cmap *map = offload_data_map(data->netdev); + + if (!map) { + return; + } - cmap_remove(&ufid_to_rte_flow, - CONST_CAST(struct cmap_node *, &data->node), hash); + cmap_remove(map, CONST_CAST(struct cmap_node *, &data->node), hash); netdev_close(data->netdev); ovsrcu_postpone(free, data); } @@ -1421,7 +1498,7 @@ netdev_offload_dpdk_add_flow(struct netdev *netdev, if (!flow) { goto out; } - flows_data = ufid_to_rte_flow_associate(ufid, netdev, flow, + flows_data = ufid_to_rte_flow_associate(netdev, ufid, flow, actions_offloaded); VLOG_DBG("%s: installed flow %p by ufid "UUID_FMT, netdev_get_name(netdev), flow, UUID_ARGS((struct uuid *)ufid)); @@ -1478,7 +1555,7 @@ netdev_offload_dpdk_flow_put(struct netdev *netdev, struct match *match, * Here destroy the old rte flow first before adding a new one. * Keep the stats for the newly created rule. */ - rte_flow_data = ufid_to_rte_flow_data_find(ufid, false); + rte_flow_data = ufid_to_rte_flow_data_find(netdev, ufid, false); if (rte_flow_data && rte_flow_data->rte_flow) { old_stats = rte_flow_data->stats; modification = true; @@ -1509,7 +1586,7 @@ netdev_offload_dpdk_flow_del(struct netdev *netdev OVS_UNUSED, { struct ufid_to_rte_flow_data *rte_flow_data; - rte_flow_data = ufid_to_rte_flow_data_find(ufid, true); + rte_flow_data = ufid_to_rte_flow_data_find(netdev, ufid, true); if (!rte_flow_data || !rte_flow_data->rte_flow) { return -1; } @@ -1523,7 +1600,21 @@ netdev_offload_dpdk_flow_del(struct netdev *netdev OVS_UNUSED, static int netdev_offload_dpdk_init_flow_api(struct netdev *netdev) { - return netdev_dpdk_flow_api_supported(netdev) ? 0 : EOPNOTSUPP; + int ret = EOPNOTSUPP; + + if (netdev_dpdk_flow_api_supported(netdev)) { + ret = offload_data_init(netdev); + } + + return ret; +} + +static void +netdev_offload_dpdk_deinit_flow_api(struct netdev *netdev) +{ + if (netdev_dpdk_flow_api_supported(netdev)) { + offload_data_destroy(netdev); + } } static int @@ -1540,7 +1631,7 @@ netdev_offload_dpdk_flow_get(struct netdev *netdev, struct rte_flow_error error; int ret = 0; - rte_flow_data = ufid_to_rte_flow_data_find(ufid, false); + rte_flow_data = ufid_to_rte_flow_data_find(netdev, ufid, false); if (!rte_flow_data || !rte_flow_data->rte_flow) { ret = -1; goto out; @@ -1575,13 +1666,14 @@ out: static int netdev_offload_dpdk_flow_flush(struct netdev *netdev) { + struct cmap *map = offload_data_map(netdev); struct ufid_to_rte_flow_data *data; - CMAP_FOR_EACH (data, node, &ufid_to_rte_flow) { - if (data->netdev != netdev) { - continue; - } + if (!map) { + return -1; + } + CMAP_FOR_EACH (data, node, map) { netdev_offload_dpdk_flow_destroy(data); } @@ -1593,6 +1685,7 @@ const struct netdev_flow_api netdev_offload_dpdk = { .flow_put = netdev_offload_dpdk_flow_put, .flow_del = netdev_offload_dpdk_flow_del, .init_flow_api = netdev_offload_dpdk_init_flow_api, + .deinit_flow_api = netdev_offload_dpdk_deinit_flow_api, .flow_get = netdev_offload_dpdk_flow_get, .flow_flush = netdev_offload_dpdk_flow_flush, }; diff --git a/lib/netdev-offload.h b/lib/netdev-offload.h index 18b48790f..d820e23ed 100644 --- a/lib/netdev-offload.h +++ b/lib/netdev-offload.h @@ -20,6 +20,7 @@ #include "openvswitch/netdev.h" #include "openvswitch/types.h" +#include "ovs-rcu.h" #include "packets.h" #include "flow.h" @@ -45,6 +46,7 @@ struct netdev_hw_info { bool oor; /* Out of Offload Resources ? */ int offload_count; /* Pending (non-offloaded) flow count */ int pending_count; /* Offloaded flow count */ + OVSRCU_TYPE(void *) offload_data; /* Offload metadata. */ }; enum hw_info_type {