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 <igor.romanov@oktetlabs.ru>
Signed-off-by: Andrew Rybchenko <andrew.rybchenko@oktetlabs.ru>
Reviewed-by: Andy Moreton <amoreton@xilinx.com>
Reviewed-by: Ivan Malov <ivan.malov@oktetlabs.ru>
This commit is contained in:
Igor Romanov 2021-10-11 17:48:26 +03:00 committed by Ferruh Yigit
parent 3f95dfb9c4
commit 52e80b1b64
5 changed files with 285 additions and 0 deletions

View File

@ -97,4 +97,5 @@ sources = files(
'sfc_ef100_rx.c',
'sfc_ef100_tx.c',
'sfc_service.c',
'sfc_repr_proxy.c',
)

View File

@ -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);

View File

@ -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)

View File

@ -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 <rte_service.h>
#include <rte_service_component.h>
#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");
}

View File

@ -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 <stdint.h>
#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 */