From: Igor Romanov Date: Mon, 11 Oct 2021 14:48:26 +0000 (+0300) Subject: net/sfc: add representors proxy infrastructure X-Git-Url: http://git.droids-corp.org/?a=commitdiff_plain;h=52e80b1b64bdd28e88bbad98cfae96d7345f4da0;p=dpdk.git net/sfc: add representors proxy infrastructure 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 --- 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 @@ fail_sriov_vswitch_create: 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 bb582d3aff..47a3122b07 100644 --- a/drivers/net/sfc/sfc.h +++ b/drivers/net/sfc/sfc.h @@ -31,6 +31,8 @@ #include "sfc_mae.h" #include "sfc_dp.h" #include "sfc_sw_stats.h" +#include "sfc_repr_proxy.h" +#include "sfc_service.h" #ifdef __cplusplus extern "C" { @@ -282,6 +284,7 @@ struct sfc_adapter { struct sfc_sw_stats sw_stats; struct sfc_filter filter; struct sfc_mae mae; + struct sfc_repr_proxy repr_proxy; struct sfc_flow_list flow_list; @@ -410,6 +413,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 */