net/sfc/base: import MCDI proxy authorization

MCDI proxy authorization may be used if privileged PCI
function (physical function) would like to intercept and
authorize MCDI requests done by unprivileged (e.g. virtual)
PCI function. It may be used to control unprivileged
function Rx mode (e.g. promiscuous, all-multicast), MTU
and default MAC address change requests etc.

Current libefx support is limited to client-side which
is required to work when function requests need to be
authorized.

Server side support required to request and do the
authorization is not implemented yet.

EFSYS_OPT_MCDI_PROXY_AUTH should be enabled to use it.

From Solarflare Communications Inc.

Signed-off-by: Andrew Rybchenko <arybchenko@solarflare.com>
Reviewed-by: Ferruh Yigit <ferruh.yigit@intel.com>
This commit is contained in:
Andrew Rybchenko 2016-11-29 16:18:40 +00:00 committed by Ferruh Yigit
parent 5858cccf68
commit 099c33bef3
4 changed files with 101 additions and 0 deletions

View File

@ -209,6 +209,9 @@ typedef struct efx_mcdi_transport_s {
void (*emt_logger)(void *, efx_log_msg_t,
void *, size_t, void *, size_t);
#endif /* EFSYS_OPT_MCDI_LOGGING */
#if EFSYS_OPT_MCDI_PROXY_AUTH
void (*emt_ev_proxy_response)(void *, uint32_t, efx_rc_t);
#endif /* EFSYS_OPT_MCDI_PROXY_AUTH */
} efx_mcdi_transport_t;
extern __checkReturn efx_rc_t

View File

@ -84,6 +84,13 @@
# endif
#endif /* EFSYS_OPT_MCDI_LOGGING */
#if EFSYS_OPT_MCDI_PROXY_AUTH
/* Support MCDI proxy authorization */
# if !EFSYS_OPT_MCDI
# error "MCDI_PROXY_AUTH requires MCDI"
# endif
#endif /* EFSYS_OPT_MCDI_PROXY_AUTH */
#ifdef EFSYS_OPT_MON_LM87
# error "MON_LM87 is obsolete and is not supported."
#endif

View File

@ -352,6 +352,21 @@ efx_mcdi_read_response_header(
emrp->emr_err_code = err_code;
emrp->emr_err_arg = err_arg;
#if EFSYS_OPT_MCDI_PROXY_AUTH
if ((err_code == MC_CMD_ERR_PROXY_PENDING) &&
(err_len == sizeof (err))) {
/*
* The MCDI request would normally fail with EPERM, but
* firmware has forwarded it to an authorization agent
* attached to a privileged PF.
*
* Save the authorization request handle. The client
* must wait for a PROXY_RESPONSE event, or timeout.
*/
emrp->emr_proxy_handle = err_arg;
}
#endif /* EFSYS_OPT_MCDI_PROXY_AUTH */
#if EFSYS_OPT_MCDI_LOGGING
if (emtp->emt_logger != NULL) {
emtp->emt_logger(emtp->emt_context,
@ -372,6 +387,9 @@ efx_mcdi_read_response_header(
emrp->emr_rc = 0;
emrp->emr_out_length_used = data_len;
#if EFSYS_OPT_MCDI_PROXY_AUTH
emrp->emr_proxy_handle = 0;
#endif /* EFSYS_OPT_MCDI_PROXY_AUTH */
return;
fail3:
@ -732,6 +750,62 @@ efx_mcdi_ev_cpl(
emtp->emt_ev_cpl(emtp->emt_context);
}
#if EFSYS_OPT_MCDI_PROXY_AUTH
__checkReturn efx_rc_t
efx_mcdi_get_proxy_handle(
__in efx_nic_t *enp,
__in efx_mcdi_req_t *emrp,
__out uint32_t *handlep)
{
efx_rc_t rc;
/*
* Return proxy handle from MCDI request that returned with error
* MC_MCD_ERR_PROXY_PENDING. This handle is used to wait for a matching
* PROXY_RESPONSE event.
*/
if ((emrp == NULL) || (handlep == NULL)) {
rc = EINVAL;
goto fail1;
}
if ((emrp->emr_rc != 0) &&
(emrp->emr_err_code == MC_CMD_ERR_PROXY_PENDING)) {
*handlep = emrp->emr_proxy_handle;
rc = 0;
} else {
*handlep = 0;
rc = ENOENT;
}
return (rc);
fail1:
EFSYS_PROBE1(fail1, efx_rc_t, rc);
return (rc);
}
void
efx_mcdi_ev_proxy_response(
__in efx_nic_t *enp,
__in unsigned int handle,
__in unsigned int status)
{
const efx_mcdi_transport_t *emtp = enp->en_mcdi.em_emtp;
efx_rc_t rc;
/*
* Handle results of an authorization request for a privileged MCDI
* command. If authorization was granted then we must re-issue the
* original MCDI request. If authorization failed or timed out,
* then the original MCDI request should be completed with the
* result code from this event.
*/
rc = (status == 0) ? 0 : efx_mcdi_request_errcode(status);
emtp->emt_ev_proxy_response(emtp->emt_context, handle, rc);
}
#endif /* EFSYS_OPT_MCDI_PROXY_AUTH */
void
efx_mcdi_ev_death(
__in efx_nic_t *enp,

View File

@ -59,6 +59,9 @@ struct efx_mcdi_req_s {
/* Internals: low level transport details */
unsigned int emr_err_code;
unsigned int emr_err_arg;
#if EFSYS_OPT_MCDI_PROXY_AUTH
uint32_t emr_proxy_handle;
#endif
};
typedef struct efx_mcdi_iface_s {
@ -90,6 +93,20 @@ efx_mcdi_ev_cpl(
__in unsigned int outlen,
__in int errcode);
#if EFSYS_OPT_MCDI_PROXY_AUTH
extern __checkReturn efx_rc_t
efx_mcdi_get_proxy_handle(
__in efx_nic_t *enp,
__in efx_mcdi_req_t *emrp,
__out uint32_t *handlep);
extern void
efx_mcdi_ev_proxy_response(
__in efx_nic_t *enp,
__in unsigned int handle,
__in unsigned int status);
#endif
extern void
efx_mcdi_ev_death(
__in efx_nic_t *enp,