]> git.droids-corp.org - dpdk.git/commitdiff
net/sfc/base: import MCDI proxy authorization
authorAndrew Rybchenko <arybchenko@solarflare.com>
Tue, 29 Nov 2016 16:18:40 +0000 (16:18 +0000)
committerFerruh Yigit <ferruh.yigit@intel.com>
Tue, 17 Jan 2017 18:39:25 +0000 (19:39 +0100)
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>
drivers/net/sfc/base/efx.h
drivers/net/sfc/base/efx_check.h
drivers/net/sfc/base/efx_mcdi.c
drivers/net/sfc/base/efx_mcdi.h

index 9fdfb96d5aa87bd836a3f6f5648961ee34b981a9..d68a36b1f63716ff033ce681688f09a17610fe1f 100644 (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
index 228b42c00284f5d4e63b624b71734aa27edf4175..470f73c692ae71ad6dc23ce1d6c1bb9ba5b78cc4 100644 (file)
 # 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
index a87a22319237661e9fbfa6692fbbb509f0a438b3..474c5053dd9546a833ecf0ec09e5843521fc9cf3 100644 (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,
index a408b5b2eac3a755d73863c4a477211da9e6812d..a62e921d3afde33b43362e4cc28ae2483622c79e 100644 (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,