From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: Received: from mails.dpdk.org (mails.dpdk.org [217.70.189.124]) by inbox.dpdk.org (Postfix) with ESMTP id C3CCCA034F; Mon, 11 Oct 2021 16:50:03 +0200 (CEST) Received: from [217.70.189.124] (localhost [127.0.0.1]) by mails.dpdk.org (Postfix) with ESMTP id BB41E4113F; Mon, 11 Oct 2021 16:49:28 +0200 (CEST) Received: from shelob.oktetlabs.ru (shelob.oktetlabs.ru [91.220.146.113]) by mails.dpdk.org (Postfix) with ESMTP id 14BCE41139 for ; Mon, 11 Oct 2021 16:49:27 +0200 (CEST) Received: by shelob.oktetlabs.ru (Postfix, from userid 122) id DE13F7F6F9; Mon, 11 Oct 2021 17:49:26 +0300 (MSK) X-Spam-Checker-Version: SpamAssassin 3.4.2 (2018-09-13) on shelob.oktetlabs.ru X-Spam-Level: X-Spam-Status: No, score=0.8 required=5.0 tests=ALL_TRUSTED, DKIM_ADSP_DISCARD, URIBL_BLOCKED autolearn=no autolearn_force=no version=3.4.2 Received: from aros.oktetlabs.ru (aros.oktetlabs.ru [192.168.38.17]) by shelob.oktetlabs.ru (Postfix) with ESMTP id AB50B7F6FB; Mon, 11 Oct 2021 17:49:07 +0300 (MSK) DKIM-Filter: OpenDKIM Filter v2.11.0 shelob.oktetlabs.ru AB50B7F6FB Authentication-Results: shelob.oktetlabs.ru/AB50B7F6FB; dkim=none; dkim-atps=neutral From: Andrew Rybchenko To: dev@dpdk.org Cc: Igor Romanov , Andy Moreton , Ivan Malov Date: Mon, 11 Oct 2021 17:48:26 +0300 Message-Id: <20211011144857.446802-8-andrew.rybchenko@oktetlabs.ru> X-Mailer: git-send-email 2.30.2 In-Reply-To: <20211011144857.446802-1-andrew.rybchenko@oktetlabs.ru> References: <20210827065717.1838258-1-andrew.rybchenko@oktetlabs.ru> <20211011144857.446802-1-andrew.rybchenko@oktetlabs.ru> MIME-Version: 1.0 Content-Transfer-Encoding: 8bit Subject: [dpdk-dev] [PATCH v2 07/38] net/sfc: add representors proxy infrastructure X-BeenThere: dev@dpdk.org X-Mailman-Version: 2.1.29 Precedence: list List-Id: DPDK patches and discussions List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Errors-To: dev-bounces@dpdk.org Sender: "dev" From: Igor Romanov Representor proxy is a mediator between virtual functions and port representors. It forwards traffic between virtual functions and port representors performing base PF ethdev + VF's representor traffic (de-)multiplexing. The implementation will be provided by later patches. Signed-off-by: Igor Romanov Signed-off-by: Andrew Rybchenko Reviewed-by: Andy Moreton Reviewed-by: Ivan Malov --- drivers/net/sfc/meson.build | 1 + drivers/net/sfc/sfc.c | 35 ++++++ drivers/net/sfc/sfc.h | 5 + drivers/net/sfc/sfc_repr_proxy.c | 210 +++++++++++++++++++++++++++++++ drivers/net/sfc/sfc_repr_proxy.h | 34 +++++ 5 files changed, 285 insertions(+) create mode 100644 drivers/net/sfc/sfc_repr_proxy.c create mode 100644 drivers/net/sfc/sfc_repr_proxy.h diff --git a/drivers/net/sfc/meson.build b/drivers/net/sfc/meson.build index 948c65968a..4fc2063f7a 100644 --- a/drivers/net/sfc/meson.build +++ b/drivers/net/sfc/meson.build @@ -97,4 +97,5 @@ sources = files( 'sfc_ef100_rx.c', 'sfc_ef100_tx.c', 'sfc_service.c', + 'sfc_repr_proxy.c', ) diff --git a/drivers/net/sfc/sfc.c b/drivers/net/sfc/sfc.c index cd2c97f3b2..591b8971b3 100644 --- a/drivers/net/sfc/sfc.c +++ b/drivers/net/sfc/sfc.c @@ -27,6 +27,25 @@ #include "sfc_sw_stats.h" +bool +sfc_repr_supported(const struct sfc_adapter *sa) +{ + if (!sa->switchdev) + return false; + + /* + * Representor proxy should use service lcore on PF's socket + * (sa->socket_id) to be efficient. But the proxy will fall back + * to any socket if it is not possible to get the service core + * on the same socket. Check that at least service core on any + * socket is available. + */ + if (sfc_get_service_lcore(SOCKET_ID_ANY) == RTE_MAX_LCORE) + return false; + + return true; +} + int sfc_dma_alloc(const struct sfc_adapter *sa, const char *name, uint16_t id, size_t len, int socket_id, efsys_mem_t *esmp) @@ -434,9 +453,16 @@ sfc_try_start(struct sfc_adapter *sa) if (rc != 0) goto fail_flows_insert; + rc = sfc_repr_proxy_start(sa); + if (rc != 0) + goto fail_repr_proxy_start; + sfc_log_init(sa, "done"); return 0; +fail_repr_proxy_start: + sfc_flow_stop(sa); + fail_flows_insert: sfc_tx_stop(sa); @@ -540,6 +566,7 @@ sfc_stop(struct sfc_adapter *sa) sa->state = SFC_ADAPTER_STOPPING; + sfc_repr_proxy_stop(sa); sfc_flow_stop(sa); sfc_tx_stop(sa); sfc_rx_stop(sa); @@ -899,6 +926,10 @@ sfc_attach(struct sfc_adapter *sa) if (rc != 0) goto fail_mae_switchdev_init; + rc = sfc_repr_proxy_attach(sa); + if (rc != 0) + goto fail_repr_proxy_attach; + sfc_log_init(sa, "fini nic"); efx_nic_fini(enp); @@ -927,6 +958,9 @@ sfc_attach(struct sfc_adapter *sa) fail_sw_xstats_init: sfc_flow_fini(sa); + sfc_repr_proxy_detach(sa); + +fail_repr_proxy_attach: sfc_mae_switchdev_fini(sa); fail_mae_switchdev_init: @@ -976,6 +1010,7 @@ sfc_detach(struct sfc_adapter *sa) sfc_flow_fini(sa); + sfc_repr_proxy_detach(sa); sfc_mae_switchdev_fini(sa); sfc_mae_detach(sa); sfc_mae_counter_rxq_detach(sa); diff --git a/drivers/net/sfc/sfc.h b/drivers/net/sfc/sfc.h index b045baca9e..8f65857f65 100644 --- a/drivers/net/sfc/sfc.h +++ b/drivers/net/sfc/sfc.h @@ -30,6 +30,8 @@ #include "sfc_sriov.h" #include "sfc_mae.h" #include "sfc_dp.h" +#include "sfc_repr_proxy.h" +#include "sfc_service.h" #ifdef __cplusplus extern "C" { @@ -260,6 +262,7 @@ struct sfc_adapter { struct sfc_sw_xstats sw_xstats; struct sfc_filter filter; struct sfc_mae mae; + struct sfc_repr_proxy repr_proxy; struct sfc_flow_list flow_list; @@ -388,6 +391,8 @@ sfc_nb_counter_rxq(const struct sfc_adapter_shared *sas) return sas->counters_rxq_allocated ? 1 : 0; } +bool sfc_repr_supported(const struct sfc_adapter *sa); + /** Get the number of milliseconds since boot from the default timer */ static inline uint64_t sfc_get_system_msecs(void) diff --git a/drivers/net/sfc/sfc_repr_proxy.c b/drivers/net/sfc/sfc_repr_proxy.c new file mode 100644 index 0000000000..eb29376988 --- /dev/null +++ b/drivers/net/sfc/sfc_repr_proxy.c @@ -0,0 +1,210 @@ +/* SPDX-License-Identifier: BSD-3-Clause + * + * Copyright(c) 2019-2021 Xilinx, Inc. + * Copyright(c) 2019 Solarflare Communications Inc. + * + * This software was jointly developed between OKTET Labs (under contract + * for Solarflare) and Solarflare Communications, Inc. + */ + +#include +#include + +#include "sfc_log.h" +#include "sfc_service.h" +#include "sfc_repr_proxy.h" +#include "sfc.h" + +static int32_t +sfc_repr_proxy_routine(void *arg) +{ + struct sfc_repr_proxy *rp = arg; + + /* Representor proxy boilerplate will be here */ + RTE_SET_USED(rp); + + return 0; +} + +int +sfc_repr_proxy_attach(struct sfc_adapter *sa) +{ + struct sfc_repr_proxy *rp = &sa->repr_proxy; + struct rte_service_spec service; + uint32_t cid; + uint32_t sid; + int rc; + + sfc_log_init(sa, "entry"); + + if (!sfc_repr_supported(sa)) { + sfc_log_init(sa, "representors not supported - skip"); + return 0; + } + + cid = sfc_get_service_lcore(sa->socket_id); + if (cid == RTE_MAX_LCORE && sa->socket_id != SOCKET_ID_ANY) { + /* Warn and try to allocate on any NUMA node */ + sfc_warn(sa, + "repr proxy: unable to get service lcore at socket %d", + sa->socket_id); + + cid = sfc_get_service_lcore(SOCKET_ID_ANY); + } + if (cid == RTE_MAX_LCORE) { + rc = ENOTSUP; + sfc_err(sa, "repr proxy: failed to get service lcore"); + goto fail_get_service_lcore; + } + + memset(&service, 0, sizeof(service)); + snprintf(service.name, sizeof(service.name), + "net_sfc_%hu_repr_proxy", sfc_sa2shared(sa)->port_id); + service.socket_id = rte_lcore_to_socket_id(cid); + service.callback = sfc_repr_proxy_routine; + service.callback_userdata = rp; + + rc = rte_service_component_register(&service, &sid); + if (rc != 0) { + rc = ENOEXEC; + sfc_err(sa, "repr proxy: failed to register service component"); + goto fail_register; + } + + rc = rte_service_map_lcore_set(sid, cid, 1); + if (rc != 0) { + rc = -rc; + sfc_err(sa, "repr proxy: failed to map lcore"); + goto fail_map_lcore; + } + + rp->service_core_id = cid; + rp->service_id = sid; + + sfc_log_init(sa, "done"); + + return 0; + +fail_map_lcore: + rte_service_component_unregister(sid); + +fail_register: + /* + * No need to rollback service lcore get since + * it just makes socket_id based search and remembers it. + */ + +fail_get_service_lcore: + sfc_log_init(sa, "failed: %s", rte_strerror(rc)); + return rc; +} + +void +sfc_repr_proxy_detach(struct sfc_adapter *sa) +{ + struct sfc_repr_proxy *rp = &sa->repr_proxy; + + sfc_log_init(sa, "entry"); + + if (!sfc_repr_supported(sa)) { + sfc_log_init(sa, "representors not supported - skip"); + return; + } + + rte_service_map_lcore_set(rp->service_id, rp->service_core_id, 0); + rte_service_component_unregister(rp->service_id); + + sfc_log_init(sa, "done"); +} + +int +sfc_repr_proxy_start(struct sfc_adapter *sa) +{ + struct sfc_repr_proxy *rp = &sa->repr_proxy; + int rc; + + sfc_log_init(sa, "entry"); + + /* + * The condition to start the proxy is insufficient. It will be + * complemented with representor port start/stop support. + */ + if (!sfc_repr_supported(sa)) { + sfc_log_init(sa, "representors not supported - skip"); + return 0; + } + + /* Service core may be in "stopped" state, start it */ + rc = rte_service_lcore_start(rp->service_core_id); + if (rc != 0 && rc != -EALREADY) { + rc = -rc; + sfc_err(sa, "failed to start service core for %s: %s", + rte_service_get_name(rp->service_id), + rte_strerror(rc)); + goto fail_start_core; + } + + /* Run the service */ + rc = rte_service_component_runstate_set(rp->service_id, 1); + if (rc < 0) { + rc = -rc; + sfc_err(sa, "failed to run %s component: %s", + rte_service_get_name(rp->service_id), + rte_strerror(rc)); + goto fail_component_runstate_set; + } + rc = rte_service_runstate_set(rp->service_id, 1); + if (rc < 0) { + rc = -rc; + sfc_err(sa, "failed to run %s: %s", + rte_service_get_name(rp->service_id), + rte_strerror(rc)); + goto fail_runstate_set; + } + + sfc_log_init(sa, "done"); + + return 0; + +fail_runstate_set: + rte_service_component_runstate_set(rp->service_id, 0); + +fail_component_runstate_set: + /* Service lcore may be shared and we never stop it */ + +fail_start_core: + sfc_log_init(sa, "failed: %s", rte_strerror(rc)); + return rc; +} + +void +sfc_repr_proxy_stop(struct sfc_adapter *sa) +{ + struct sfc_repr_proxy *rp = &sa->repr_proxy; + int rc; + + sfc_log_init(sa, "entry"); + + if (!sfc_repr_supported(sa)) { + sfc_log_init(sa, "representors not supported - skip"); + return; + } + + rc = rte_service_runstate_set(rp->service_id, 0); + if (rc < 0) { + sfc_err(sa, "failed to stop %s: %s", + rte_service_get_name(rp->service_id), + rte_strerror(-rc)); + } + + rc = rte_service_component_runstate_set(rp->service_id, 0); + if (rc < 0) { + sfc_err(sa, "failed to stop %s component: %s", + rte_service_get_name(rp->service_id), + rte_strerror(-rc)); + } + + /* Service lcore may be shared and we never stop it */ + + sfc_log_init(sa, "done"); +} diff --git a/drivers/net/sfc/sfc_repr_proxy.h b/drivers/net/sfc/sfc_repr_proxy.h new file mode 100644 index 0000000000..40ce352335 --- /dev/null +++ b/drivers/net/sfc/sfc_repr_proxy.h @@ -0,0 +1,34 @@ +/* SPDX-License-Identifier: BSD-3-Clause + * + * Copyright(c) 2019-2021 Xilinx, Inc. + * Copyright(c) 2019 Solarflare Communications Inc. + * + * This software was jointly developed between OKTET Labs (under contract + * for Solarflare) and Solarflare Communications, Inc. + */ + +#ifndef _SFC_REPR_PROXY_H +#define _SFC_REPR_PROXY_H + +#include + +#ifdef __cplusplus +extern "C" { +#endif + +struct sfc_repr_proxy { + uint32_t service_core_id; + uint32_t service_id; +}; + +struct sfc_adapter; + +int sfc_repr_proxy_attach(struct sfc_adapter *sa); +void sfc_repr_proxy_detach(struct sfc_adapter *sa); +int sfc_repr_proxy_start(struct sfc_adapter *sa); +void sfc_repr_proxy_stop(struct sfc_adapter *sa); + +#ifdef __cplusplus +} +#endif +#endif /* _SFC_REPR_PROXY_H */ -- 2.30.2