xprtrdma: No direct data placement with krb5i and krb5p
authorChuck Lever <chuck.lever@oracle.com>
Wed, 29 Jun 2016 17:55:06 +0000 (13:55 -0400)
committerAnna Schumaker <Anna.Schumaker@Netapp.com>
Mon, 11 Jul 2016 19:50:43 +0000 (15:50 -0400)
Direct data placement is not allowed when using flavors that
guarantee integrity or privacy. When such security flavors are in
effect, don't allow the use of Read and Write chunks for moving
individual data items. All messages larger than the inline threshold
are sent via Long Call or Long Reply.

On my systems (CX-3 Pro on FDR), for small I/O operations, the use
of Long messages adds only around 5 usecs of latency in each
direction.

Note that when integrity or encryption is used, the host CPU touches
every byte in these messages. Even if it could be used, data
movement offload doesn't buy much in this case.

Signed-off-by: Chuck Lever <chuck.lever@oracle.com>
Tested-by: Steve Wise <swise@opengridcomputing.com>
Signed-off-by: Anna Schumaker <Anna.Schumaker@Netapp.com>
include/linux/sunrpc/auth.h
include/linux/sunrpc/gss_api.h
net/sunrpc/auth_gss/auth_gss.c
net/sunrpc/auth_gss/gss_krb5_mech.c
net/sunrpc/auth_gss/gss_mech_switch.c
net/sunrpc/xprtrdma/rpc_rdma.c

index 899791573a403ba8434c12a05b4594f23ac6c33b..3a40287b4d27ccb83455fa1f36533989bc569f90 100644 (file)
@@ -107,6 +107,9 @@ struct rpc_auth {
        /* per-flavor data */
 };
 
+/* rpc_auth au_flags */
+#define RPCAUTH_AUTH_DATATOUCH 0x00000002
+
 struct rpc_auth_create_args {
        rpc_authflavor_t pseudoflavor;
        const char *target_name;
index 1f911ccb2a75655bee357d27076b455776d4d377..68ec78c1aa48e1ec3e4b285420a69732a2b05c6a 100644 (file)
@@ -73,6 +73,7 @@ u32 gss_delete_sec_context(
 rpc_authflavor_t gss_svc_to_pseudoflavor(struct gss_api_mech *, u32 qop,
                                        u32 service);
 u32 gss_pseudoflavor_to_service(struct gss_api_mech *, u32 pseudoflavor);
+bool gss_pseudoflavor_to_datatouch(struct gss_api_mech *, u32 pseudoflavor);
 char *gss_service_to_auth_domain_name(struct gss_api_mech *, u32 service);
 
 struct pf_desc {
@@ -81,6 +82,7 @@ struct pf_desc {
        u32     service;
        char    *name;
        char    *auth_domain_name;
+       bool    datatouch;
 };
 
 /* Different mechanisms (e.g., krb5 or spkm3) may implement gss-api, and
index e64ae93d5b4f618e216f2c55070ceef60bd737d5..bca3537efffdf39cd7bdf50bf4469d70d0576d9c 100644 (file)
@@ -1017,6 +1017,8 @@ gss_create_new(struct rpc_auth_create_args *args, struct rpc_clnt *clnt)
        auth->au_rslack = GSS_VERF_SLACK >> 2;
        auth->au_ops = &authgss_ops;
        auth->au_flavor = flavor;
+       if (gss_pseudoflavor_to_datatouch(gss_auth->mech, flavor))
+               auth->au_flags |= RPCAUTH_AUTH_DATATOUCH;
        atomic_set(&auth->au_count, 1);
        kref_init(&gss_auth->kref);
 
index 65427492b1c95f681f79345e7ce29c62d941e147..60595835317afbdd1c2ccc657cd727ed11477a6b 100644 (file)
@@ -745,12 +745,14 @@ static struct pf_desc gss_kerberos_pfs[] = {
                .qop = GSS_C_QOP_DEFAULT,
                .service = RPC_GSS_SVC_INTEGRITY,
                .name = "krb5i",
+               .datatouch = true,
        },
        [2] = {
                .pseudoflavor = RPC_AUTH_GSS_KRB5P,
                .qop = GSS_C_QOP_DEFAULT,
                .service = RPC_GSS_SVC_PRIVACY,
                .name = "krb5p",
+               .datatouch = true,
        },
 };
 
index 7063d856a598e3c4f1201c5df26ce86c6158538d..5fec3abbe19bb640de31bf85bfc9becdeab5f359 100644 (file)
@@ -361,6 +361,18 @@ gss_pseudoflavor_to_service(struct gss_api_mech *gm, u32 pseudoflavor)
 }
 EXPORT_SYMBOL(gss_pseudoflavor_to_service);
 
+bool
+gss_pseudoflavor_to_datatouch(struct gss_api_mech *gm, u32 pseudoflavor)
+{
+       int i;
+
+       for (i = 0; i < gm->gm_pf_num; i++) {
+               if (gm->gm_pfs[i].pseudoflavor == pseudoflavor)
+                       return gm->gm_pfs[i].datatouch;
+       }
+       return false;
+}
+
 char *
 gss_service_to_auth_domain_name(struct gss_api_mech *gm, u32 service)
 {
index dac2990ae2f7de91f91b2f782ebc4d3588977463..a47f170b20ef88d1ebe1f9ca406374dee1b84102 100644 (file)
@@ -570,6 +570,7 @@ rpcrdma_marshal_req(struct rpc_rqst *rqst)
        struct rpcrdma_req *req = rpcr_to_rdmar(rqst);
        enum rpcrdma_chunktype rtype, wtype;
        struct rpcrdma_msg *headerp;
+       bool ddp_allowed;
        ssize_t hdrlen;
        size_t rpclen;
        __be32 *iptr;
@@ -586,6 +587,13 @@ rpcrdma_marshal_req(struct rpc_rqst *rqst)
        headerp->rm_credit = cpu_to_be32(r_xprt->rx_buf.rb_max_requests);
        headerp->rm_type = rdma_msg;
 
+       /* When the ULP employs a GSS flavor that guarantees integrity
+        * or privacy, direct data placement of individual data items
+        * is not allowed.
+        */
+       ddp_allowed = !(rqst->rq_cred->cr_auth->au_flags &
+                                               RPCAUTH_AUTH_DATATOUCH);
+
        /*
         * Chunks needed for results?
         *
@@ -597,7 +605,7 @@ rpcrdma_marshal_req(struct rpc_rqst *rqst)
         */
        if (rpcrdma_results_inline(r_xprt, rqst))
                wtype = rpcrdma_noch;
-       else if (rqst->rq_rcv_buf.flags & XDRBUF_READ)
+       else if (ddp_allowed && rqst->rq_rcv_buf.flags & XDRBUF_READ)
                wtype = rpcrdma_writech;
        else
                wtype = rpcrdma_replych;
@@ -620,7 +628,7 @@ rpcrdma_marshal_req(struct rpc_rqst *rqst)
                rtype = rpcrdma_noch;
                rpcrdma_inline_pullup(rqst);
                rpclen = rqst->rq_svec[0].iov_len;
-       } else if (rqst->rq_snd_buf.flags & XDRBUF_WRITE) {
+       } else if (ddp_allowed && rqst->rq_snd_buf.flags & XDRBUF_WRITE) {
                rtype = rpcrdma_readch;
                rpclen = rqst->rq_svec[0].iov_len;
                rpclen += rpcrdma_tail_pullup(&rqst->rq_snd_buf);