From patchwork Sat Dec 5 14:21:57 2020 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Gaetan Rivet X-Patchwork-Id: 1411459 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.138; helo=whitealder.osuosl.org; envelope-from=ovs-dev-bounces@openvswitch.org; receiver=) Authentication-Results: ozlabs.org; dmarc=none (p=none dis=none) header.from=u256.net Received: from whitealder.osuosl.org (smtp1.osuosl.org [140.211.166.138]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by ozlabs.org (Postfix) with ESMTPS id 4CpBdS6pDSz9sVV for ; Sun, 6 Dec 2020 01:23:40 +1100 (AEDT) Received: from localhost (localhost [127.0.0.1]) by whitealder.osuosl.org (Postfix) with ESMTP id 89BBB875E6; Sat, 5 Dec 2020 14:23:39 +0000 (UTC) X-Virus-Scanned: amavisd-new at osuosl.org Received: from whitealder.osuosl.org ([127.0.0.1]) by localhost (.osuosl.org [127.0.0.1]) (amavisd-new, port 10024) with ESMTP id Fi4+f4slhLoV; Sat, 5 Dec 2020 14:23:34 +0000 (UTC) Received: from lists.linuxfoundation.org (lf-lists.osuosl.org [140.211.9.56]) by whitealder.osuosl.org (Postfix) with ESMTP id 5477F87BC8; Sat, 5 Dec 2020 14:22:58 +0000 (UTC) Received: from lf-lists.osuosl.org (localhost [127.0.0.1]) by lists.linuxfoundation.org (Postfix) with ESMTP id 16C69C1DDC; Sat, 5 Dec 2020 14:22:58 +0000 (UTC) X-Original-To: dev@openvswitch.org Delivered-To: ovs-dev@lists.linuxfoundation.org Received: from whitealder.osuosl.org (smtp1.osuosl.org [140.211.166.138]) by lists.linuxfoundation.org (Postfix) with ESMTP id 61EDAC013B for ; Sat, 5 Dec 2020 14:22:41 +0000 (UTC) Received: from localhost (localhost [127.0.0.1]) by whitealder.osuosl.org (Postfix) with ESMTP id 3FE12874DA for ; Sat, 5 Dec 2020 14:22:41 +0000 (UTC) X-Virus-Scanned: amavisd-new at osuosl.org Received: from whitealder.osuosl.org ([127.0.0.1]) by localhost (.osuosl.org [127.0.0.1]) (amavisd-new, port 10024) with ESMTP id KtLP-sGHrkB9 for ; Sat, 5 Dec 2020 14:22:37 +0000 (UTC) X-Greylist: from auto-whitelisted by SQLgrey-1.7.6 Received: from relay2-d.mail.gandi.net (relay2-d.mail.gandi.net [217.70.183.194]) by whitealder.osuosl.org (Postfix) with ESMTPS id E2092874D1 for ; Sat, 5 Dec 2020 14:22:36 +0000 (UTC) X-Originating-IP: 90.78.4.16 Received: from inocybe.home (lfbn-poi-1-1343-16.w90-78.abo.wanadoo.fr [90.78.4.16]) (Authenticated sender: grive@u256.net) by relay2-d.mail.gandi.net (Postfix) with ESMTPSA id 013CB40005 for ; Sat, 5 Dec 2020 14:22:32 +0000 (UTC) From: Gaetan Rivet To: dev@openvswitch.org Date: Sat, 5 Dec 2020 15:21:57 +0100 Message-Id: <0dfe9e77ff913fff36868d851552d411b68ac42c.1607177117.git.grive@u256.net> X-Mailer: git-send-email 2.29.2 In-Reply-To: References: MIME-Version: 1.0 Subject: [ovs-dev] [RFC PATCH 02/26] 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. Signed-off-by: Gaetan Rivet --- lib/netdev-offload-dpdk.c | 100 +++++++++++++++++++++++++++++++------- lib/netdev-offload.h | 1 + 2 files changed, 84 insertions(+), 17 deletions(-) diff --git a/lib/netdev-offload-dpdk.c b/lib/netdev-offload-dpdk.c index 01c52e1de..8d39ab7b4 100644 --- a/lib/netdev-offload-dpdk.c +++ b/lib/netdev-offload-dpdk.c @@ -52,7 +52,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; @@ -62,14 +61,63 @@ 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); + + netdev->hw_info.offload_data = data; + + return 0; +} + +static void +offload_data_destroy(struct netdev *netdev) +{ + struct netdev_offload_dpdk_data *data; + struct ufid_to_rte_flow_data *node; + + data = netdev->hw_info.offload_data; + if (data == NULL) { + return; + } + + CMAP_FOR_EACH (node, node, &data->ufid_to_rte_flow) { + ovsrcu_postpone(free, node); + } + + cmap_destroy(&data->ufid_to_rte_flow); + free(data); + + netdev->hw_info.offload_data = NULL; +} + +static struct cmap * +offload_data_map(struct netdev *netdev) +{ + struct netdev_offload_dpdk_data *data; + + data = netdev->hw_info.offload_data; + return &data->ufid_to_rte_flow; +} + /* Find rte_flow with @ufid. */ static struct ufid_to_rte_flow_data * -ufid_to_rte_flow_data_find(const ovs_u128 *ufid) +ufid_to_rte_flow_data_find(struct netdev *netdev, + const ovs_u128 *ufid) { size_t hash = hash_bytes(ufid, sizeof *ufid, 0); struct ufid_to_rte_flow_data *data; + struct cmap *map = offload_data_map(netdev); - 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; } @@ -79,12 +127,13 @@ ufid_to_rte_flow_data_find(const ovs_u128 *ufid) } static inline struct ufid_to_rte_flow_data * -ufid_to_rte_flow_associate(const ovs_u128 *ufid, +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 ufid_to_rte_flow_data *data_prev; + struct cmap *map = offload_data_map(netdev); /* * We should not simply overwrite an existing rte flow. @@ -92,7 +141,7 @@ ufid_to_rte_flow_associate(const ovs_u128 *ufid, * Thus, if following assert triggers, something is wrong: * the rte_flow is not destroyed. */ - data_prev = ufid_to_rte_flow_data_find(ufid); + data_prev = ufid_to_rte_flow_data_find(netdev, ufid); if (data_prev) { ovs_assert(data_prev->rte_flow == NULL); } @@ -101,21 +150,22 @@ ufid_to_rte_flow_associate(const ovs_u128 *ufid, 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; } static inline void -ufid_to_rte_flow_disassociate(const ovs_u128 *ufid) +ufid_to_rte_flow_disassociate(struct netdev *netdev, + const ovs_u128 *ufid) { + struct cmap *map = offload_data_map(netdev); size_t hash = hash_bytes(ufid, sizeof *ufid, 0); struct ufid_to_rte_flow_data *data; - 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)) { - 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); ovsrcu_postpone(free, data); return; } @@ -1435,7 +1485,8 @@ netdev_offload_dpdk_add_flow(struct netdev *netdev, if (!flow) { goto out; } - flows_data = ufid_to_rte_flow_associate(ufid, flow, actions_offloaded); + 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)); @@ -1453,7 +1504,7 @@ netdev_offload_dpdk_destroy_flow(struct netdev *netdev, int ret = netdev_dpdk_rte_flow_destroy(netdev, rte_flow, &error); if (ret == 0) { - ufid_to_rte_flow_disassociate(ufid); + ufid_to_rte_flow_disassociate(netdev, ufid); VLOG_DBG_RL(&rl, "%s: rte_flow 0x%"PRIxPTR " flow destroy %d ufid " UUID_FMT, netdev_get_name(netdev), (intptr_t) rte_flow, @@ -1484,7 +1535,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); + rte_flow_data = ufid_to_rte_flow_data_find(netdev, ufid); if (rte_flow_data && rte_flow_data->rte_flow) { old_stats = rte_flow_data->stats; modification = true; @@ -1515,7 +1566,7 @@ netdev_offload_dpdk_flow_del(struct netdev *netdev, const ovs_u128 *ufid, { struct ufid_to_rte_flow_data *rte_flow_data; - rte_flow_data = ufid_to_rte_flow_data_find(ufid); + rte_flow_data = ufid_to_rte_flow_data_find(netdev, ufid); if (!rte_flow_data || !rte_flow_data->rte_flow) { return -1; } @@ -1530,7 +1581,21 @@ netdev_offload_dpdk_flow_del(struct netdev *netdev, const ovs_u128 *ufid, 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 @@ -1547,7 +1612,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); + rte_flow_data = ufid_to_rte_flow_data_find(netdev, ufid); if (!rte_flow_data || !rte_flow_data->rte_flow) { ret = -1; goto out; @@ -1584,5 +1649,6 @@ 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, }; diff --git a/lib/netdev-offload.h b/lib/netdev-offload.h index 4c0ed2ae8..49b893190 100644 --- a/lib/netdev-offload.h +++ b/lib/netdev-offload.h @@ -45,6 +45,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 */ + void *offload_data; /* Offload metadata. */ }; enum hw_info_type {