10Sstevel@tonic-gate /*
20Sstevel@tonic-gate * CDDL HEADER START
30Sstevel@tonic-gate *
40Sstevel@tonic-gate * The contents of this file are subject to the terms of the
57387SRobert.Gordon@Sun.COM * Common Development and Distribution License (the "License").
67387SRobert.Gordon@Sun.COM * You may not use this file except in compliance with the License.
70Sstevel@tonic-gate *
80Sstevel@tonic-gate * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
90Sstevel@tonic-gate * or http://www.opensolaris.org/os/licensing.
100Sstevel@tonic-gate * See the License for the specific language governing permissions
110Sstevel@tonic-gate * and limitations under the License.
120Sstevel@tonic-gate *
130Sstevel@tonic-gate * When distributing Covered Code, include this CDDL HEADER in each
140Sstevel@tonic-gate * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
150Sstevel@tonic-gate * If applicable, add the following below this CDDL HEADER, with the
160Sstevel@tonic-gate * fields enclosed by brackets "[]" replaced with your own identifying
170Sstevel@tonic-gate * information: Portions Copyright [yyyy] [name of copyright owner]
180Sstevel@tonic-gate *
190Sstevel@tonic-gate * CDDL HEADER END
200Sstevel@tonic-gate */
210Sstevel@tonic-gate /*
2211551SSiddheshwar.Mahesh@Sun.COM * Copyright 2010 Sun Microsystems, Inc. All rights reserved.
230Sstevel@tonic-gate * Use is subject to license terms.
240Sstevel@tonic-gate */
250Sstevel@tonic-gate /* Copyright (c) 1983, 1984, 1985, 1986, 1987, 1988, 1989 AT&T */
260Sstevel@tonic-gate /* All Rights Reserved */
270Sstevel@tonic-gate /*
280Sstevel@tonic-gate * Portions of this source code were derived from Berkeley
290Sstevel@tonic-gate * 4.3 BSD under license from the Regents of the University of
300Sstevel@tonic-gate * California.
310Sstevel@tonic-gate */
320Sstevel@tonic-gate
330Sstevel@tonic-gate #include <sys/param.h>
340Sstevel@tonic-gate #include <sys/types.h>
350Sstevel@tonic-gate #include <sys/user.h>
360Sstevel@tonic-gate #include <sys/systm.h>
370Sstevel@tonic-gate #include <sys/sysmacros.h>
380Sstevel@tonic-gate #include <sys/errno.h>
390Sstevel@tonic-gate #include <sys/kmem.h>
400Sstevel@tonic-gate #include <sys/debug.h>
410Sstevel@tonic-gate #include <sys/systm.h>
420Sstevel@tonic-gate #include <sys/kstat.h>
430Sstevel@tonic-gate #include <sys/t_lock.h>
440Sstevel@tonic-gate #include <sys/ddi.h>
450Sstevel@tonic-gate #include <sys/cmn_err.h>
460Sstevel@tonic-gate #include <sys/time.h>
470Sstevel@tonic-gate #include <sys/isa_defs.h>
480Sstevel@tonic-gate #include <sys/zone.h>
497387SRobert.Gordon@Sun.COM #include <sys/sdt.h>
500Sstevel@tonic-gate
510Sstevel@tonic-gate #include <rpc/types.h>
520Sstevel@tonic-gate #include <rpc/xdr.h>
530Sstevel@tonic-gate #include <rpc/auth.h>
540Sstevel@tonic-gate #include <rpc/clnt.h>
550Sstevel@tonic-gate #include <rpc/rpc_msg.h>
560Sstevel@tonic-gate #include <rpc/rpc_rdma.h>
577387SRobert.Gordon@Sun.COM #include <nfs/nfs.h>
587387SRobert.Gordon@Sun.COM #include <nfs/nfs4_kprot.h>
590Sstevel@tonic-gate
607387SRobert.Gordon@Sun.COM static uint32_t rdma_bufs_rqst = RDMA_BUFS_RQST;
617387SRobert.Gordon@Sun.COM
627387SRobert.Gordon@Sun.COM static int clnt_compose_rpcmsg(CLIENT *, rpcproc_t, rdma_buf_t *,
637387SRobert.Gordon@Sun.COM XDR *, xdrproc_t, caddr_t);
647387SRobert.Gordon@Sun.COM static int clnt_compose_rdma_header(CONN *, CLIENT *, rdma_buf_t *,
657387SRobert.Gordon@Sun.COM XDR **, uint_t *);
667387SRobert.Gordon@Sun.COM static int clnt_setup_rlist(CONN *, XDR *, XDR *);
679348SSiddheshwar.Mahesh@Sun.COM static int clnt_setup_wlist(CONN *, XDR *, XDR *, rdma_buf_t *);
687387SRobert.Gordon@Sun.COM static int clnt_setup_long_reply(CONN *, struct clist **, uint_t);
697387SRobert.Gordon@Sun.COM static void clnt_check_credit(CONN *);
707387SRobert.Gordon@Sun.COM static void clnt_return_credit(CONN *);
717387SRobert.Gordon@Sun.COM static void clnt_decode_long_reply(CONN *, struct clist *,
727387SRobert.Gordon@Sun.COM struct clist *, XDR *, XDR **, struct clist *,
737387SRobert.Gordon@Sun.COM struct clist *, uint_t, uint_t);
747387SRobert.Gordon@Sun.COM
757387SRobert.Gordon@Sun.COM static void clnt_update_credit(CONN *, uint32_t);
760Sstevel@tonic-gate
770Sstevel@tonic-gate static enum clnt_stat clnt_rdma_kcallit(CLIENT *, rpcproc_t, xdrproc_t,
780Sstevel@tonic-gate caddr_t, xdrproc_t, caddr_t, struct timeval);
790Sstevel@tonic-gate static void clnt_rdma_kabort(CLIENT *);
800Sstevel@tonic-gate static void clnt_rdma_kerror(CLIENT *, struct rpc_err *);
810Sstevel@tonic-gate static bool_t clnt_rdma_kfreeres(CLIENT *, xdrproc_t, caddr_t);
820Sstevel@tonic-gate static void clnt_rdma_kdestroy(CLIENT *);
830Sstevel@tonic-gate static bool_t clnt_rdma_kcontrol(CLIENT *, int, char *);
840Sstevel@tonic-gate static int clnt_rdma_ksettimers(CLIENT *, struct rpc_timers *,
850Sstevel@tonic-gate struct rpc_timers *, int, void(*)(int, int, caddr_t), caddr_t, uint32_t);
860Sstevel@tonic-gate
870Sstevel@tonic-gate /*
880Sstevel@tonic-gate * Operations vector for RDMA based RPC
890Sstevel@tonic-gate */
900Sstevel@tonic-gate static struct clnt_ops rdma_clnt_ops = {
910Sstevel@tonic-gate clnt_rdma_kcallit, /* do rpc call */
920Sstevel@tonic-gate clnt_rdma_kabort, /* abort call */
930Sstevel@tonic-gate clnt_rdma_kerror, /* return error status */
940Sstevel@tonic-gate clnt_rdma_kfreeres, /* free results */
950Sstevel@tonic-gate clnt_rdma_kdestroy, /* destroy rpc handle */
960Sstevel@tonic-gate clnt_rdma_kcontrol, /* the ioctl() of rpc */
970Sstevel@tonic-gate clnt_rdma_ksettimers, /* set retry timers */
980Sstevel@tonic-gate };
990Sstevel@tonic-gate
1000Sstevel@tonic-gate /*
1010Sstevel@tonic-gate * The size of the preserialized RPC header information.
1020Sstevel@tonic-gate */
1030Sstevel@tonic-gate #define CKU_HDRSIZE 20
1047387SRobert.Gordon@Sun.COM #define CLNT_RDMA_SUCCESS 0
1057387SRobert.Gordon@Sun.COM #define CLNT_RDMA_FAIL (-1)
1067387SRobert.Gordon@Sun.COM
1077387SRobert.Gordon@Sun.COM #define AUTH_REFRESH_COUNT 2
1087387SRobert.Gordon@Sun.COM
1097387SRobert.Gordon@Sun.COM #define IS_RPCSEC_GSS(authh) \
1107387SRobert.Gordon@Sun.COM (authh->cl_auth->ah_cred.oa_flavor == RPCSEC_GSS)
1110Sstevel@tonic-gate
1120Sstevel@tonic-gate /*
1130Sstevel@tonic-gate * Per RPC RDMA endpoint details
1140Sstevel@tonic-gate */
1150Sstevel@tonic-gate typedef struct cku_private {
1160Sstevel@tonic-gate CLIENT cku_client; /* client handle */
1170Sstevel@tonic-gate rdma_mod_t *cku_rd_mod; /* underlying RDMA mod */
1180Sstevel@tonic-gate void *cku_rd_handle; /* underlying RDMA device */
1199733SFaramarz.Jalalian@Sun.COM struct netbuf cku_srcaddr; /* source address for retries */
1200Sstevel@tonic-gate struct netbuf cku_addr; /* remote netbuf address */
1210Sstevel@tonic-gate int cku_addrfmly; /* for finding addr_type */
1220Sstevel@tonic-gate struct rpc_err cku_err; /* error status */
1230Sstevel@tonic-gate struct cred *cku_cred; /* credentials */
1240Sstevel@tonic-gate XDR cku_outxdr; /* xdr stream for output */
1250Sstevel@tonic-gate uint32_t cku_outsz;
1260Sstevel@tonic-gate XDR cku_inxdr; /* xdr stream for input */
1270Sstevel@tonic-gate char cku_rpchdr[CKU_HDRSIZE+4]; /* rpc header */
1280Sstevel@tonic-gate uint32_t cku_xid; /* current XID */
1290Sstevel@tonic-gate } cku_private_t;
1300Sstevel@tonic-gate
1310Sstevel@tonic-gate #define CLNT_RDMA_DELAY 10 /* secs to delay after a connection failure */
1320Sstevel@tonic-gate static int clnt_rdma_min_delay = CLNT_RDMA_DELAY;
1330Sstevel@tonic-gate
1340Sstevel@tonic-gate struct {
1350Sstevel@tonic-gate kstat_named_t rccalls;
1360Sstevel@tonic-gate kstat_named_t rcbadcalls;
1370Sstevel@tonic-gate kstat_named_t rcbadxids;
1380Sstevel@tonic-gate kstat_named_t rctimeouts;
1390Sstevel@tonic-gate kstat_named_t rcnewcreds;
1400Sstevel@tonic-gate kstat_named_t rcbadverfs;
1410Sstevel@tonic-gate kstat_named_t rctimers;
1420Sstevel@tonic-gate kstat_named_t rccantconn;
1430Sstevel@tonic-gate kstat_named_t rcnomem;
1440Sstevel@tonic-gate kstat_named_t rcintrs;
1450Sstevel@tonic-gate kstat_named_t rclongrpcs;
1460Sstevel@tonic-gate } rdmarcstat = {
1470Sstevel@tonic-gate { "calls", KSTAT_DATA_UINT64 },
1480Sstevel@tonic-gate { "badcalls", KSTAT_DATA_UINT64 },
1490Sstevel@tonic-gate { "badxids", KSTAT_DATA_UINT64 },
1500Sstevel@tonic-gate { "timeouts", KSTAT_DATA_UINT64 },
1510Sstevel@tonic-gate { "newcreds", KSTAT_DATA_UINT64 },
1520Sstevel@tonic-gate { "badverfs", KSTAT_DATA_UINT64 },
1530Sstevel@tonic-gate { "timers", KSTAT_DATA_UINT64 },
1540Sstevel@tonic-gate { "cantconn", KSTAT_DATA_UINT64 },
1550Sstevel@tonic-gate { "nomem", KSTAT_DATA_UINT64 },
1560Sstevel@tonic-gate { "interrupts", KSTAT_DATA_UINT64 },
1570Sstevel@tonic-gate { "longrpc", KSTAT_DATA_UINT64 }
1580Sstevel@tonic-gate };
1590Sstevel@tonic-gate
1600Sstevel@tonic-gate kstat_named_t *rdmarcstat_ptr = (kstat_named_t *)&rdmarcstat;
1610Sstevel@tonic-gate uint_t rdmarcstat_ndata = sizeof (rdmarcstat) / sizeof (kstat_named_t);
1620Sstevel@tonic-gate
1630Sstevel@tonic-gate #ifdef DEBUG
1640Sstevel@tonic-gate int rdma_clnt_debug = 0;
1650Sstevel@tonic-gate #endif
1660Sstevel@tonic-gate
1670Sstevel@tonic-gate #ifdef accurate_stats
1680Sstevel@tonic-gate extern kmutex_t rdmarcstat_lock; /* mutex for rcstat updates */
1690Sstevel@tonic-gate
1700Sstevel@tonic-gate #define RCSTAT_INCR(x) \
1710Sstevel@tonic-gate mutex_enter(&rdmarcstat_lock); \
1720Sstevel@tonic-gate rdmarcstat.x.value.ui64++; \
1730Sstevel@tonic-gate mutex_exit(&rdmarcstat_lock);
1740Sstevel@tonic-gate #else
1750Sstevel@tonic-gate #define RCSTAT_INCR(x) \
1760Sstevel@tonic-gate rdmarcstat.x.value.ui64++;
1770Sstevel@tonic-gate #endif
1780Sstevel@tonic-gate
1790Sstevel@tonic-gate #define ptoh(p) (&((p)->cku_client))
1800Sstevel@tonic-gate #define htop(h) ((cku_private_t *)((h)->cl_private))
1810Sstevel@tonic-gate
1827387SRobert.Gordon@Sun.COM uint_t
calc_length(uint_t len)1837387SRobert.Gordon@Sun.COM calc_length(uint_t len)
1847387SRobert.Gordon@Sun.COM {
1857387SRobert.Gordon@Sun.COM len = RNDUP(len);
1867387SRobert.Gordon@Sun.COM
1877387SRobert.Gordon@Sun.COM if (len <= 64 * 1024) {
1887387SRobert.Gordon@Sun.COM if (len > 32 * 1024) {
1897387SRobert.Gordon@Sun.COM len = 64 * 1024;
1907387SRobert.Gordon@Sun.COM } else {
1917387SRobert.Gordon@Sun.COM if (len > 16 * 1024) {
1927387SRobert.Gordon@Sun.COM len = 32 * 1024;
1937387SRobert.Gordon@Sun.COM } else {
1947387SRobert.Gordon@Sun.COM if (len > 8 * 1024) {
1957387SRobert.Gordon@Sun.COM len = 16 * 1024;
1967387SRobert.Gordon@Sun.COM } else {
1977387SRobert.Gordon@Sun.COM len = 8 * 1024;
1987387SRobert.Gordon@Sun.COM }
1997387SRobert.Gordon@Sun.COM }
2007387SRobert.Gordon@Sun.COM }
2017387SRobert.Gordon@Sun.COM }
2027387SRobert.Gordon@Sun.COM return (len);
2037387SRobert.Gordon@Sun.COM }
2040Sstevel@tonic-gate int
clnt_rdma_kcreate(char * proto,void * handle,struct netbuf * raddr,int family,rpcprog_t pgm,rpcvers_t vers,struct cred * cred,CLIENT ** cl)2050Sstevel@tonic-gate clnt_rdma_kcreate(char *proto, void *handle, struct netbuf *raddr, int family,
2060Sstevel@tonic-gate rpcprog_t pgm, rpcvers_t vers, struct cred *cred, CLIENT **cl)
2070Sstevel@tonic-gate {
2080Sstevel@tonic-gate CLIENT *h;
2090Sstevel@tonic-gate struct cku_private *p;
2100Sstevel@tonic-gate struct rpc_msg call_msg;
2110Sstevel@tonic-gate rdma_registry_t *rp;
2120Sstevel@tonic-gate
2130Sstevel@tonic-gate ASSERT(INGLOBALZONE(curproc));
2140Sstevel@tonic-gate
2150Sstevel@tonic-gate if (cl == NULL)
2160Sstevel@tonic-gate return (EINVAL);
2170Sstevel@tonic-gate *cl = NULL;
2180Sstevel@tonic-gate
2190Sstevel@tonic-gate p = kmem_zalloc(sizeof (*p), KM_SLEEP);
2200Sstevel@tonic-gate
2210Sstevel@tonic-gate /*
2220Sstevel@tonic-gate * Find underlying RDMATF plugin
2230Sstevel@tonic-gate */
2240Sstevel@tonic-gate rw_enter(&rdma_lock, RW_READER);
2250Sstevel@tonic-gate rp = rdma_mod_head;
2260Sstevel@tonic-gate while (rp != NULL) {
2270Sstevel@tonic-gate if (strcmp(rp->r_mod->rdma_api, proto))
2280Sstevel@tonic-gate rp = rp->r_next;
2290Sstevel@tonic-gate else {
2300Sstevel@tonic-gate p->cku_rd_mod = rp->r_mod;
2310Sstevel@tonic-gate p->cku_rd_handle = handle;
2320Sstevel@tonic-gate break;
2330Sstevel@tonic-gate }
2340Sstevel@tonic-gate }
2350Sstevel@tonic-gate rw_exit(&rdma_lock);
2360Sstevel@tonic-gate
2370Sstevel@tonic-gate if (p->cku_rd_mod == NULL) {
2380Sstevel@tonic-gate /*
2390Sstevel@tonic-gate * Should not happen.
2400Sstevel@tonic-gate * No matching RDMATF plugin.
2410Sstevel@tonic-gate */
2420Sstevel@tonic-gate kmem_free(p, sizeof (struct cku_private));
2430Sstevel@tonic-gate return (EINVAL);
2440Sstevel@tonic-gate }
2450Sstevel@tonic-gate
2460Sstevel@tonic-gate h = ptoh(p);
2470Sstevel@tonic-gate h->cl_ops = &rdma_clnt_ops;
2480Sstevel@tonic-gate h->cl_private = (caddr_t)p;
2490Sstevel@tonic-gate h->cl_auth = authkern_create();
2500Sstevel@tonic-gate
2510Sstevel@tonic-gate /* call message, just used to pre-serialize below */
2520Sstevel@tonic-gate call_msg.rm_xid = 0;
2530Sstevel@tonic-gate call_msg.rm_direction = CALL;
2540Sstevel@tonic-gate call_msg.rm_call.cb_rpcvers = RPC_MSG_VERSION;
2550Sstevel@tonic-gate call_msg.rm_call.cb_prog = pgm;
2560Sstevel@tonic-gate call_msg.rm_call.cb_vers = vers;
2570Sstevel@tonic-gate
2580Sstevel@tonic-gate xdrmem_create(&p->cku_outxdr, p->cku_rpchdr, CKU_HDRSIZE, XDR_ENCODE);
2590Sstevel@tonic-gate /* pre-serialize call message header */
2600Sstevel@tonic-gate if (!xdr_callhdr(&p->cku_outxdr, &call_msg)) {
2610Sstevel@tonic-gate XDR_DESTROY(&p->cku_outxdr);
2620Sstevel@tonic-gate auth_destroy(h->cl_auth);
2630Sstevel@tonic-gate kmem_free(p, sizeof (struct cku_private));
2640Sstevel@tonic-gate return (EINVAL);
2650Sstevel@tonic-gate }
2660Sstevel@tonic-gate
2670Sstevel@tonic-gate /*
2680Sstevel@tonic-gate * Set up the rpc information
2690Sstevel@tonic-gate */
2700Sstevel@tonic-gate p->cku_cred = cred;
2719733SFaramarz.Jalalian@Sun.COM p->cku_srcaddr.buf = kmem_zalloc(raddr->maxlen, KM_SLEEP);
2729733SFaramarz.Jalalian@Sun.COM p->cku_srcaddr.maxlen = raddr->maxlen;
2739733SFaramarz.Jalalian@Sun.COM p->cku_srcaddr.len = 0;
2740Sstevel@tonic-gate p->cku_addr.buf = kmem_zalloc(raddr->maxlen, KM_SLEEP);
2750Sstevel@tonic-gate p->cku_addr.maxlen = raddr->maxlen;
2760Sstevel@tonic-gate p->cku_addr.len = raddr->len;
2770Sstevel@tonic-gate bcopy(raddr->buf, p->cku_addr.buf, raddr->len);
2780Sstevel@tonic-gate p->cku_addrfmly = family;
2790Sstevel@tonic-gate
2800Sstevel@tonic-gate *cl = h;
2810Sstevel@tonic-gate return (0);
2820Sstevel@tonic-gate }
2830Sstevel@tonic-gate
2840Sstevel@tonic-gate static void
clnt_rdma_kdestroy(CLIENT * h)2850Sstevel@tonic-gate clnt_rdma_kdestroy(CLIENT *h)
2860Sstevel@tonic-gate {
2870Sstevel@tonic-gate struct cku_private *p = htop(h);
2880Sstevel@tonic-gate
2899733SFaramarz.Jalalian@Sun.COM kmem_free(p->cku_srcaddr.buf, p->cku_srcaddr.maxlen);
2900Sstevel@tonic-gate kmem_free(p->cku_addr.buf, p->cku_addr.maxlen);
2910Sstevel@tonic-gate kmem_free(p, sizeof (*p));
2920Sstevel@tonic-gate }
2930Sstevel@tonic-gate
2940Sstevel@tonic-gate void
clnt_rdma_kinit(CLIENT * h,char * proto,void * handle,struct netbuf * raddr,struct cred * cred)2950Sstevel@tonic-gate clnt_rdma_kinit(CLIENT *h, char *proto, void *handle, struct netbuf *raddr,
2960Sstevel@tonic-gate struct cred *cred)
2970Sstevel@tonic-gate {
2980Sstevel@tonic-gate struct cku_private *p = htop(h);
2990Sstevel@tonic-gate rdma_registry_t *rp;
3000Sstevel@tonic-gate
3010Sstevel@tonic-gate ASSERT(INGLOBALZONE(curproc));
3020Sstevel@tonic-gate /*
3030Sstevel@tonic-gate * Find underlying RDMATF plugin
3040Sstevel@tonic-gate */
3050Sstevel@tonic-gate p->cku_rd_mod = NULL;
3060Sstevel@tonic-gate rw_enter(&rdma_lock, RW_READER);
3070Sstevel@tonic-gate rp = rdma_mod_head;
3080Sstevel@tonic-gate while (rp != NULL) {
3090Sstevel@tonic-gate if (strcmp(rp->r_mod->rdma_api, proto))
3100Sstevel@tonic-gate rp = rp->r_next;
3110Sstevel@tonic-gate else {
3120Sstevel@tonic-gate p->cku_rd_mod = rp->r_mod;
3130Sstevel@tonic-gate p->cku_rd_handle = handle;
3140Sstevel@tonic-gate break;
3150Sstevel@tonic-gate }
3160Sstevel@tonic-gate
3170Sstevel@tonic-gate }
3180Sstevel@tonic-gate rw_exit(&rdma_lock);
3190Sstevel@tonic-gate
3200Sstevel@tonic-gate /*
3210Sstevel@tonic-gate * Set up the rpc information
3220Sstevel@tonic-gate */
3230Sstevel@tonic-gate p->cku_cred = cred;
3240Sstevel@tonic-gate p->cku_xid = 0;
3250Sstevel@tonic-gate
3260Sstevel@tonic-gate if (p->cku_addr.maxlen < raddr->len) {
3270Sstevel@tonic-gate if (p->cku_addr.maxlen != 0 && p->cku_addr.buf != NULL)
3280Sstevel@tonic-gate kmem_free(p->cku_addr.buf, p->cku_addr.maxlen);
3290Sstevel@tonic-gate p->cku_addr.buf = kmem_zalloc(raddr->maxlen, KM_SLEEP);
3300Sstevel@tonic-gate p->cku_addr.maxlen = raddr->maxlen;
3310Sstevel@tonic-gate }
3320Sstevel@tonic-gate
3339733SFaramarz.Jalalian@Sun.COM p->cku_srcaddr.len = 0;
3349733SFaramarz.Jalalian@Sun.COM
3350Sstevel@tonic-gate p->cku_addr.len = raddr->len;
3360Sstevel@tonic-gate bcopy(raddr->buf, p->cku_addr.buf, raddr->len);
3370Sstevel@tonic-gate h->cl_ops = &rdma_clnt_ops;
3380Sstevel@tonic-gate }
3390Sstevel@tonic-gate
3407387SRobert.Gordon@Sun.COM static int
clnt_compose_rpcmsg(CLIENT * h,rpcproc_t procnum,rdma_buf_t * rpcmsg,XDR * xdrs,xdrproc_t xdr_args,caddr_t argsp)3417387SRobert.Gordon@Sun.COM clnt_compose_rpcmsg(CLIENT *h, rpcproc_t procnum,
3427387SRobert.Gordon@Sun.COM rdma_buf_t *rpcmsg, XDR *xdrs,
3437387SRobert.Gordon@Sun.COM xdrproc_t xdr_args, caddr_t argsp)
3447387SRobert.Gordon@Sun.COM {
3457387SRobert.Gordon@Sun.COM cku_private_t *p = htop(h);
3467387SRobert.Gordon@Sun.COM
3477387SRobert.Gordon@Sun.COM if (h->cl_auth->ah_cred.oa_flavor != RPCSEC_GSS) {
3487387SRobert.Gordon@Sun.COM /*
3497387SRobert.Gordon@Sun.COM * Copy in the preserialized RPC header
3507387SRobert.Gordon@Sun.COM * information.
3517387SRobert.Gordon@Sun.COM */
3527387SRobert.Gordon@Sun.COM bcopy(p->cku_rpchdr, rpcmsg->addr, CKU_HDRSIZE);
3537387SRobert.Gordon@Sun.COM
3547387SRobert.Gordon@Sun.COM /*
3557387SRobert.Gordon@Sun.COM * transaction id is the 1st thing in the output
3567387SRobert.Gordon@Sun.COM * buffer.
3577387SRobert.Gordon@Sun.COM */
3587387SRobert.Gordon@Sun.COM /* LINTED pointer alignment */
3597387SRobert.Gordon@Sun.COM (*(uint32_t *)(rpcmsg->addr)) = p->cku_xid;
3607387SRobert.Gordon@Sun.COM
3617387SRobert.Gordon@Sun.COM /* Skip the preserialized stuff. */
3627387SRobert.Gordon@Sun.COM XDR_SETPOS(xdrs, CKU_HDRSIZE);
3637387SRobert.Gordon@Sun.COM
3647387SRobert.Gordon@Sun.COM /* Serialize dynamic stuff into the output buffer. */
3657387SRobert.Gordon@Sun.COM if ((!XDR_PUTINT32(xdrs, (int32_t *)&procnum)) ||
3667387SRobert.Gordon@Sun.COM (!AUTH_MARSHALL(h->cl_auth, xdrs, p->cku_cred)) ||
3677387SRobert.Gordon@Sun.COM (!(*xdr_args)(xdrs, argsp))) {
3687387SRobert.Gordon@Sun.COM DTRACE_PROBE(krpc__e__clntrdma__rpcmsg__dynargs);
3697387SRobert.Gordon@Sun.COM return (CLNT_RDMA_FAIL);
3707387SRobert.Gordon@Sun.COM }
3717387SRobert.Gordon@Sun.COM p->cku_outsz = XDR_GETPOS(xdrs);
3727387SRobert.Gordon@Sun.COM } else {
3737387SRobert.Gordon@Sun.COM uint32_t *uproc = (uint32_t *)&p->cku_rpchdr[CKU_HDRSIZE];
3747387SRobert.Gordon@Sun.COM IXDR_PUT_U_INT32(uproc, procnum);
3757387SRobert.Gordon@Sun.COM (*(uint32_t *)(&p->cku_rpchdr[0])) = p->cku_xid;
3767387SRobert.Gordon@Sun.COM XDR_SETPOS(xdrs, 0);
3777387SRobert.Gordon@Sun.COM
3787387SRobert.Gordon@Sun.COM /* Serialize the procedure number and the arguments. */
3797387SRobert.Gordon@Sun.COM if (!AUTH_WRAP(h->cl_auth, (caddr_t)p->cku_rpchdr,
3807387SRobert.Gordon@Sun.COM CKU_HDRSIZE+4, xdrs, xdr_args, argsp)) {
3817387SRobert.Gordon@Sun.COM if (rpcmsg->addr != xdrs->x_base) {
3827387SRobert.Gordon@Sun.COM rpcmsg->addr = xdrs->x_base;
3837387SRobert.Gordon@Sun.COM rpcmsg->len = xdr_getbufsize(xdrs);
3847387SRobert.Gordon@Sun.COM }
3857387SRobert.Gordon@Sun.COM DTRACE_PROBE(krpc__e__clntrdma__rpcmsg__procnum);
3867387SRobert.Gordon@Sun.COM return (CLNT_RDMA_FAIL);
3877387SRobert.Gordon@Sun.COM }
3887387SRobert.Gordon@Sun.COM /*
3897387SRobert.Gordon@Sun.COM * If we had to allocate a new buffer while encoding
3907387SRobert.Gordon@Sun.COM * then update the addr and len.
3917387SRobert.Gordon@Sun.COM */
3927387SRobert.Gordon@Sun.COM if (rpcmsg->addr != xdrs->x_base) {
3937387SRobert.Gordon@Sun.COM rpcmsg->addr = xdrs->x_base;
3947387SRobert.Gordon@Sun.COM rpcmsg->len = xdr_getbufsize(xdrs);
3957387SRobert.Gordon@Sun.COM }
3967387SRobert.Gordon@Sun.COM
3977387SRobert.Gordon@Sun.COM p->cku_outsz = XDR_GETPOS(xdrs);
3987387SRobert.Gordon@Sun.COM DTRACE_PROBE1(krpc__i__compose__size__sec, int, p->cku_outsz)
3997387SRobert.Gordon@Sun.COM }
4007387SRobert.Gordon@Sun.COM
4017387SRobert.Gordon@Sun.COM return (CLNT_RDMA_SUCCESS);
4027387SRobert.Gordon@Sun.COM }
4037387SRobert.Gordon@Sun.COM
4047387SRobert.Gordon@Sun.COM static int
clnt_compose_rdma_header(CONN * conn,CLIENT * h,rdma_buf_t * clmsg,XDR ** xdrs,uint_t * op)4057387SRobert.Gordon@Sun.COM clnt_compose_rdma_header(CONN *conn, CLIENT *h, rdma_buf_t *clmsg,
4067387SRobert.Gordon@Sun.COM XDR **xdrs, uint_t *op)
4077387SRobert.Gordon@Sun.COM {
4087387SRobert.Gordon@Sun.COM cku_private_t *p = htop(h);
4097387SRobert.Gordon@Sun.COM uint_t vers;
4107387SRobert.Gordon@Sun.COM uint32_t rdma_credit = rdma_bufs_rqst;
4117387SRobert.Gordon@Sun.COM
4127387SRobert.Gordon@Sun.COM vers = RPCRDMA_VERS;
4137387SRobert.Gordon@Sun.COM clmsg->type = SEND_BUFFER;
4147387SRobert.Gordon@Sun.COM
4157387SRobert.Gordon@Sun.COM if (rdma_buf_alloc(conn, clmsg)) {
4167387SRobert.Gordon@Sun.COM return (CLNT_RDMA_FAIL);
4177387SRobert.Gordon@Sun.COM }
4187387SRobert.Gordon@Sun.COM
4197387SRobert.Gordon@Sun.COM *xdrs = &p->cku_outxdr;
4207387SRobert.Gordon@Sun.COM xdrmem_create(*xdrs, clmsg->addr, clmsg->len, XDR_ENCODE);
4217387SRobert.Gordon@Sun.COM
4227387SRobert.Gordon@Sun.COM (*(uint32_t *)clmsg->addr) = p->cku_xid;
4237387SRobert.Gordon@Sun.COM XDR_SETPOS(*xdrs, sizeof (uint32_t));
4247387SRobert.Gordon@Sun.COM (void) xdr_u_int(*xdrs, &vers);
4257387SRobert.Gordon@Sun.COM (void) xdr_u_int(*xdrs, &rdma_credit);
4267387SRobert.Gordon@Sun.COM (void) xdr_u_int(*xdrs, op);
4277387SRobert.Gordon@Sun.COM
4287387SRobert.Gordon@Sun.COM return (CLNT_RDMA_SUCCESS);
4297387SRobert.Gordon@Sun.COM }
4307387SRobert.Gordon@Sun.COM
4317387SRobert.Gordon@Sun.COM /*
4327387SRobert.Gordon@Sun.COM * If xp_cl is NULL value, then the RPC payload will NOT carry
4337387SRobert.Gordon@Sun.COM * an RDMA READ chunk list, in this case we insert FALSE into
4347387SRobert.Gordon@Sun.COM * the XDR stream. Otherwise we use the clist and RDMA register
4357387SRobert.Gordon@Sun.COM * the memory and encode the clist into the outbound XDR stream.
4367387SRobert.Gordon@Sun.COM */
4377387SRobert.Gordon@Sun.COM static int
clnt_setup_rlist(CONN * conn,XDR * xdrs,XDR * call_xdrp)4387387SRobert.Gordon@Sun.COM clnt_setup_rlist(CONN *conn, XDR *xdrs, XDR *call_xdrp)
4397387SRobert.Gordon@Sun.COM {
4407387SRobert.Gordon@Sun.COM int status;
4417387SRobert.Gordon@Sun.COM struct clist *rclp;
4427387SRobert.Gordon@Sun.COM int32_t xdr_flag = XDR_RDMA_RLIST_REG;
4437387SRobert.Gordon@Sun.COM
4447387SRobert.Gordon@Sun.COM XDR_CONTROL(call_xdrp, XDR_RDMA_GET_RLIST, &rclp);
4457387SRobert.Gordon@Sun.COM
4467387SRobert.Gordon@Sun.COM if (rclp != NULL) {
4477387SRobert.Gordon@Sun.COM status = clist_register(conn, rclp, CLIST_REG_SOURCE);
4487387SRobert.Gordon@Sun.COM if (status != RDMA_SUCCESS) {
4497387SRobert.Gordon@Sun.COM return (CLNT_RDMA_FAIL);
4507387SRobert.Gordon@Sun.COM }
4517387SRobert.Gordon@Sun.COM XDR_CONTROL(call_xdrp, XDR_RDMA_SET_FLAGS, &xdr_flag);
4527387SRobert.Gordon@Sun.COM }
4537387SRobert.Gordon@Sun.COM (void) xdr_do_clist(xdrs, &rclp);
4547387SRobert.Gordon@Sun.COM
4557387SRobert.Gordon@Sun.COM return (CLNT_RDMA_SUCCESS);
4567387SRobert.Gordon@Sun.COM }
4577387SRobert.Gordon@Sun.COM
4587387SRobert.Gordon@Sun.COM /*
4597387SRobert.Gordon@Sun.COM * If xp_wcl is NULL value, then the RPC payload will NOT carry
4607387SRobert.Gordon@Sun.COM * an RDMA WRITE chunk list, in this case we insert FALSE into
4617387SRobert.Gordon@Sun.COM * the XDR stream. Otherwise we use the clist and RDMA register
4627387SRobert.Gordon@Sun.COM * the memory and encode the clist into the outbound XDR stream.
4637387SRobert.Gordon@Sun.COM */
4647387SRobert.Gordon@Sun.COM static int
clnt_setup_wlist(CONN * conn,XDR * xdrs,XDR * call_xdrp,rdma_buf_t * rndbuf)4659348SSiddheshwar.Mahesh@Sun.COM clnt_setup_wlist(CONN *conn, XDR *xdrs, XDR *call_xdrp, rdma_buf_t *rndbuf)
4667387SRobert.Gordon@Sun.COM {
4677387SRobert.Gordon@Sun.COM int status;
4689348SSiddheshwar.Mahesh@Sun.COM struct clist *wlist, *rndcl;
4699348SSiddheshwar.Mahesh@Sun.COM int wlen, rndlen;
4707387SRobert.Gordon@Sun.COM int32_t xdr_flag = XDR_RDMA_WLIST_REG;
4717387SRobert.Gordon@Sun.COM
4727387SRobert.Gordon@Sun.COM XDR_CONTROL(call_xdrp, XDR_RDMA_GET_WLIST, &wlist);
4737387SRobert.Gordon@Sun.COM
4747387SRobert.Gordon@Sun.COM if (wlist != NULL) {
4759348SSiddheshwar.Mahesh@Sun.COM /*
4769348SSiddheshwar.Mahesh@Sun.COM * If we are sending a non 4-byte alligned length
4779348SSiddheshwar.Mahesh@Sun.COM * the server will roundup the length to 4-byte
4789348SSiddheshwar.Mahesh@Sun.COM * boundary. In such a case, a trailing chunk is
4799348SSiddheshwar.Mahesh@Sun.COM * added to take any spill over roundup bytes.
4809348SSiddheshwar.Mahesh@Sun.COM */
4819348SSiddheshwar.Mahesh@Sun.COM wlen = clist_len(wlist);
4829348SSiddheshwar.Mahesh@Sun.COM rndlen = (roundup(wlen, BYTES_PER_XDR_UNIT) - wlen);
4839348SSiddheshwar.Mahesh@Sun.COM if (rndlen) {
4849348SSiddheshwar.Mahesh@Sun.COM rndcl = clist_alloc();
4859348SSiddheshwar.Mahesh@Sun.COM /*
4869348SSiddheshwar.Mahesh@Sun.COM * calc_length() will allocate a PAGESIZE
4879348SSiddheshwar.Mahesh@Sun.COM * buffer below.
4889348SSiddheshwar.Mahesh@Sun.COM */
4899348SSiddheshwar.Mahesh@Sun.COM rndcl->c_len = calc_length(rndlen);
4909348SSiddheshwar.Mahesh@Sun.COM rndcl->rb_longbuf.type = RDMA_LONG_BUFFER;
4919348SSiddheshwar.Mahesh@Sun.COM rndcl->rb_longbuf.len = rndcl->c_len;
4929348SSiddheshwar.Mahesh@Sun.COM if (rdma_buf_alloc(conn, &rndcl->rb_longbuf)) {
4939348SSiddheshwar.Mahesh@Sun.COM clist_free(rndcl);
4949348SSiddheshwar.Mahesh@Sun.COM return (CLNT_RDMA_FAIL);
4959348SSiddheshwar.Mahesh@Sun.COM }
4969348SSiddheshwar.Mahesh@Sun.COM
4979348SSiddheshwar.Mahesh@Sun.COM /* Roundup buffer freed back in caller */
4989348SSiddheshwar.Mahesh@Sun.COM *rndbuf = rndcl->rb_longbuf;
4999348SSiddheshwar.Mahesh@Sun.COM
5009348SSiddheshwar.Mahesh@Sun.COM rndcl->u.c_daddr3 = rndcl->rb_longbuf.addr;
5019348SSiddheshwar.Mahesh@Sun.COM rndcl->c_next = NULL;
5029348SSiddheshwar.Mahesh@Sun.COM rndcl->c_dmemhandle = rndcl->rb_longbuf.handle;
5039348SSiddheshwar.Mahesh@Sun.COM wlist->c_next = rndcl;
5049348SSiddheshwar.Mahesh@Sun.COM }
5059348SSiddheshwar.Mahesh@Sun.COM
5067387SRobert.Gordon@Sun.COM status = clist_register(conn, wlist, CLIST_REG_DST);
5077387SRobert.Gordon@Sun.COM if (status != RDMA_SUCCESS) {
5089348SSiddheshwar.Mahesh@Sun.COM rdma_buf_free(conn, rndbuf);
5099348SSiddheshwar.Mahesh@Sun.COM bzero(rndbuf, sizeof (rdma_buf_t));
5107387SRobert.Gordon@Sun.COM return (CLNT_RDMA_FAIL);
5117387SRobert.Gordon@Sun.COM }
5127387SRobert.Gordon@Sun.COM XDR_CONTROL(call_xdrp, XDR_RDMA_SET_FLAGS, &xdr_flag);
5137387SRobert.Gordon@Sun.COM }
5147387SRobert.Gordon@Sun.COM
5159348SSiddheshwar.Mahesh@Sun.COM if (!xdr_encode_wlist(xdrs, wlist)) {
5169348SSiddheshwar.Mahesh@Sun.COM if (rndlen) {
5179348SSiddheshwar.Mahesh@Sun.COM rdma_buf_free(conn, rndbuf);
5189348SSiddheshwar.Mahesh@Sun.COM bzero(rndbuf, sizeof (rdma_buf_t));
5199348SSiddheshwar.Mahesh@Sun.COM }
5207387SRobert.Gordon@Sun.COM return (CLNT_RDMA_FAIL);
5219348SSiddheshwar.Mahesh@Sun.COM }
5227387SRobert.Gordon@Sun.COM
5237387SRobert.Gordon@Sun.COM return (CLNT_RDMA_SUCCESS);
5247387SRobert.Gordon@Sun.COM }
5257387SRobert.Gordon@Sun.COM
5267387SRobert.Gordon@Sun.COM static int
clnt_setup_long_reply(CONN * conn,struct clist ** clpp,uint_t length)5277387SRobert.Gordon@Sun.COM clnt_setup_long_reply(CONN *conn, struct clist **clpp, uint_t length)
5287387SRobert.Gordon@Sun.COM {
5297387SRobert.Gordon@Sun.COM if (length == 0) {
5307387SRobert.Gordon@Sun.COM *clpp = NULL;
5317387SRobert.Gordon@Sun.COM return (CLNT_RDMA_SUCCESS);
5327387SRobert.Gordon@Sun.COM }
5337387SRobert.Gordon@Sun.COM
5347387SRobert.Gordon@Sun.COM *clpp = clist_alloc();
5357387SRobert.Gordon@Sun.COM
5367387SRobert.Gordon@Sun.COM (*clpp)->rb_longbuf.len = calc_length(length);
5377387SRobert.Gordon@Sun.COM (*clpp)->rb_longbuf.type = RDMA_LONG_BUFFER;
5387387SRobert.Gordon@Sun.COM
5397387SRobert.Gordon@Sun.COM if (rdma_buf_alloc(conn, &((*clpp)->rb_longbuf))) {
5407387SRobert.Gordon@Sun.COM clist_free(*clpp);
5417387SRobert.Gordon@Sun.COM *clpp = NULL;
5427387SRobert.Gordon@Sun.COM return (CLNT_RDMA_FAIL);
5437387SRobert.Gordon@Sun.COM }
5447387SRobert.Gordon@Sun.COM
5457387SRobert.Gordon@Sun.COM (*clpp)->u.c_daddr3 = (*clpp)->rb_longbuf.addr;
5467387SRobert.Gordon@Sun.COM (*clpp)->c_len = (*clpp)->rb_longbuf.len;
5477387SRobert.Gordon@Sun.COM (*clpp)->c_next = NULL;
5487387SRobert.Gordon@Sun.COM (*clpp)->c_dmemhandle = (*clpp)->rb_longbuf.handle;
5497387SRobert.Gordon@Sun.COM
5507387SRobert.Gordon@Sun.COM if (clist_register(conn, *clpp, CLIST_REG_DST)) {
5517387SRobert.Gordon@Sun.COM DTRACE_PROBE(krpc__e__clntrdma__longrep_regbuf);
5527387SRobert.Gordon@Sun.COM rdma_buf_free(conn, &((*clpp)->rb_longbuf));
5537387SRobert.Gordon@Sun.COM clist_free(*clpp);
55411551SSiddheshwar.Mahesh@Sun.COM *clpp = NULL;
5557387SRobert.Gordon@Sun.COM return (CLNT_RDMA_FAIL);
5567387SRobert.Gordon@Sun.COM }
5577387SRobert.Gordon@Sun.COM
5587387SRobert.Gordon@Sun.COM return (CLNT_RDMA_SUCCESS);
5597387SRobert.Gordon@Sun.COM }
5607387SRobert.Gordon@Sun.COM
5610Sstevel@tonic-gate /* ARGSUSED */
5620Sstevel@tonic-gate static enum clnt_stat
clnt_rdma_kcallit(CLIENT * h,rpcproc_t procnum,xdrproc_t xdr_args,caddr_t argsp,xdrproc_t xdr_results,caddr_t resultsp,struct timeval wait)5630Sstevel@tonic-gate clnt_rdma_kcallit(CLIENT *h, rpcproc_t procnum, xdrproc_t xdr_args,
5647387SRobert.Gordon@Sun.COM caddr_t argsp, xdrproc_t xdr_results, caddr_t resultsp,
5657387SRobert.Gordon@Sun.COM struct timeval wait)
5660Sstevel@tonic-gate {
5670Sstevel@tonic-gate cku_private_t *p = htop(h);
5687387SRobert.Gordon@Sun.COM
5697387SRobert.Gordon@Sun.COM int try_call_again;
5707387SRobert.Gordon@Sun.COM int refresh_attempt = AUTH_REFRESH_COUNT;
5710Sstevel@tonic-gate int status;
5727387SRobert.Gordon@Sun.COM int msglen;
5737387SRobert.Gordon@Sun.COM
5747387SRobert.Gordon@Sun.COM XDR *call_xdrp, callxdr; /* for xdrrdma encoding the RPC call */
5757387SRobert.Gordon@Sun.COM XDR *reply_xdrp, replyxdr; /* for xdrrdma decoding the RPC reply */
5767387SRobert.Gordon@Sun.COM XDR *rdmahdr_o_xdrs, *rdmahdr_i_xdrs;
5777387SRobert.Gordon@Sun.COM
5780Sstevel@tonic-gate struct rpc_msg reply_msg;
5798695SRajkumar.Sivaprakasam@Sun.COM rdma_registry_t *m;
5807387SRobert.Gordon@Sun.COM
5817387SRobert.Gordon@Sun.COM struct clist *cl_sendlist;
5827387SRobert.Gordon@Sun.COM struct clist *cl_recvlist;
5837387SRobert.Gordon@Sun.COM struct clist *cl;
5847387SRobert.Gordon@Sun.COM struct clist *cl_rpcmsg;
5857387SRobert.Gordon@Sun.COM struct clist *cl_rdma_reply;
5867387SRobert.Gordon@Sun.COM struct clist *cl_rpcreply_wlist;
5877387SRobert.Gordon@Sun.COM struct clist *cl_long_reply;
5889348SSiddheshwar.Mahesh@Sun.COM rdma_buf_t rndup;
5897387SRobert.Gordon@Sun.COM
5907387SRobert.Gordon@Sun.COM uint_t vers;
5917387SRobert.Gordon@Sun.COM uint_t op;
5920Sstevel@tonic-gate uint_t off;
5937387SRobert.Gordon@Sun.COM uint32_t seg_array_len;
5947387SRobert.Gordon@Sun.COM uint_t long_reply_len;
5957387SRobert.Gordon@Sun.COM uint_t rpcsec_gss;
5967387SRobert.Gordon@Sun.COM uint_t gss_i_or_p;
5977387SRobert.Gordon@Sun.COM
5980Sstevel@tonic-gate CONN *conn = NULL;
5997387SRobert.Gordon@Sun.COM rdma_buf_t clmsg;
6007387SRobert.Gordon@Sun.COM rdma_buf_t rpcmsg;
6017387SRobert.Gordon@Sun.COM rdma_chunkinfo_lengths_t rcil;
6027387SRobert.Gordon@Sun.COM
6030Sstevel@tonic-gate clock_t ticks;
6047387SRobert.Gordon@Sun.COM bool_t wlist_exists_reply;
6057387SRobert.Gordon@Sun.COM
6067387SRobert.Gordon@Sun.COM uint32_t rdma_credit = rdma_bufs_rqst;
6070Sstevel@tonic-gate
6080Sstevel@tonic-gate RCSTAT_INCR(rccalls);
6097387SRobert.Gordon@Sun.COM
6107387SRobert.Gordon@Sun.COM call_again:
6117387SRobert.Gordon@Sun.COM
6127387SRobert.Gordon@Sun.COM bzero(&clmsg, sizeof (clmsg));
6137387SRobert.Gordon@Sun.COM bzero(&rpcmsg, sizeof (rpcmsg));
6149348SSiddheshwar.Mahesh@Sun.COM bzero(&rndup, sizeof (rndup));
6157387SRobert.Gordon@Sun.COM try_call_again = 0;
6167387SRobert.Gordon@Sun.COM cl_sendlist = NULL;
6177387SRobert.Gordon@Sun.COM cl_recvlist = NULL;
6187387SRobert.Gordon@Sun.COM cl = NULL;
6197387SRobert.Gordon@Sun.COM cl_rpcmsg = NULL;
6207387SRobert.Gordon@Sun.COM cl_rdma_reply = NULL;
6217387SRobert.Gordon@Sun.COM call_xdrp = NULL;
6227387SRobert.Gordon@Sun.COM reply_xdrp = NULL;
6237387SRobert.Gordon@Sun.COM wlist_exists_reply = FALSE;
6247387SRobert.Gordon@Sun.COM cl_rpcreply_wlist = NULL;
6257387SRobert.Gordon@Sun.COM cl_long_reply = NULL;
6267387SRobert.Gordon@Sun.COM rcil.rcil_len = 0;
6277387SRobert.Gordon@Sun.COM rcil.rcil_len_alt = 0;
6287387SRobert.Gordon@Sun.COM long_reply_len = 0;
6297387SRobert.Gordon@Sun.COM
6308695SRajkumar.Sivaprakasam@Sun.COM rw_enter(&rdma_lock, RW_READER);
6318695SRajkumar.Sivaprakasam@Sun.COM m = (rdma_registry_t *)p->cku_rd_handle;
6328695SRajkumar.Sivaprakasam@Sun.COM if (m->r_mod_state == RDMA_MOD_INACTIVE) {
6338695SRajkumar.Sivaprakasam@Sun.COM /*
6348695SRajkumar.Sivaprakasam@Sun.COM * If we didn't find a matching RDMA module in the registry
6358695SRajkumar.Sivaprakasam@Sun.COM * then there is no transport.
6368695SRajkumar.Sivaprakasam@Sun.COM */
6378695SRajkumar.Sivaprakasam@Sun.COM rw_exit(&rdma_lock);
6388695SRajkumar.Sivaprakasam@Sun.COM p->cku_err.re_status = RPC_CANTSEND;
6398695SRajkumar.Sivaprakasam@Sun.COM p->cku_err.re_errno = EIO;
6408695SRajkumar.Sivaprakasam@Sun.COM ticks = clnt_rdma_min_delay * drv_usectohz(1000000);
6418695SRajkumar.Sivaprakasam@Sun.COM if (h->cl_nosignal == TRUE) {
6428695SRajkumar.Sivaprakasam@Sun.COM delay(ticks);
6438695SRajkumar.Sivaprakasam@Sun.COM } else {
6448695SRajkumar.Sivaprakasam@Sun.COM if (delay_sig(ticks) == EINTR) {
6458695SRajkumar.Sivaprakasam@Sun.COM p->cku_err.re_status = RPC_INTR;
6468695SRajkumar.Sivaprakasam@Sun.COM p->cku_err.re_errno = EINTR;
6478695SRajkumar.Sivaprakasam@Sun.COM }
6488695SRajkumar.Sivaprakasam@Sun.COM }
6498695SRajkumar.Sivaprakasam@Sun.COM return (RPC_CANTSEND);
6508695SRajkumar.Sivaprakasam@Sun.COM }
6510Sstevel@tonic-gate /*
6520Sstevel@tonic-gate * Get unique xid
6530Sstevel@tonic-gate */
6540Sstevel@tonic-gate if (p->cku_xid == 0)
6550Sstevel@tonic-gate p->cku_xid = alloc_xid();
6560Sstevel@tonic-gate
6579733SFaramarz.Jalalian@Sun.COM status = RDMA_GET_CONN(p->cku_rd_mod->rdma_ops, &p->cku_srcaddr,
6589733SFaramarz.Jalalian@Sun.COM &p->cku_addr, p->cku_addrfmly, p->cku_rd_handle, &conn);
6598695SRajkumar.Sivaprakasam@Sun.COM rw_exit(&rdma_lock);
6600Sstevel@tonic-gate
6617387SRobert.Gordon@Sun.COM /*
6627387SRobert.Gordon@Sun.COM * If there is a problem with the connection reflect the issue
6637387SRobert.Gordon@Sun.COM * back to the higher level to address, we MAY delay for a short
6647387SRobert.Gordon@Sun.COM * period so that we are kind to the transport.
6657387SRobert.Gordon@Sun.COM */
6660Sstevel@tonic-gate if (conn == NULL) {
6670Sstevel@tonic-gate /*
6680Sstevel@tonic-gate * Connect failed to server. Could be because of one
6690Sstevel@tonic-gate * of several things. In some cases we don't want
6700Sstevel@tonic-gate * the caller to retry immediately - delay before
6710Sstevel@tonic-gate * returning to caller.
6720Sstevel@tonic-gate */
6730Sstevel@tonic-gate switch (status) {
6740Sstevel@tonic-gate case RDMA_TIMEDOUT:
6750Sstevel@tonic-gate /*
6760Sstevel@tonic-gate * Already timed out. No need to delay
6770Sstevel@tonic-gate * some more.
6780Sstevel@tonic-gate */
6790Sstevel@tonic-gate p->cku_err.re_status = RPC_TIMEDOUT;
6800Sstevel@tonic-gate p->cku_err.re_errno = ETIMEDOUT;
6810Sstevel@tonic-gate break;
6820Sstevel@tonic-gate case RDMA_INTR:
6830Sstevel@tonic-gate /*
6840Sstevel@tonic-gate * Failed because of an signal. Very likely
6850Sstevel@tonic-gate * the caller will not retry.
6860Sstevel@tonic-gate */
6870Sstevel@tonic-gate p->cku_err.re_status = RPC_INTR;
6880Sstevel@tonic-gate p->cku_err.re_errno = EINTR;
6890Sstevel@tonic-gate break;
6900Sstevel@tonic-gate default:
6910Sstevel@tonic-gate /*
6920Sstevel@tonic-gate * All other failures - server down or service
6930Sstevel@tonic-gate * down or temporary resource failure. Delay before
6940Sstevel@tonic-gate * returning to caller.
6950Sstevel@tonic-gate */
6960Sstevel@tonic-gate ticks = clnt_rdma_min_delay * drv_usectohz(1000000);
6970Sstevel@tonic-gate p->cku_err.re_status = RPC_CANTCONNECT;
6980Sstevel@tonic-gate p->cku_err.re_errno = EIO;
6990Sstevel@tonic-gate
7000Sstevel@tonic-gate if (h->cl_nosignal == TRUE) {
7010Sstevel@tonic-gate delay(ticks);
7020Sstevel@tonic-gate } else {
7030Sstevel@tonic-gate if (delay_sig(ticks) == EINTR) {
7040Sstevel@tonic-gate p->cku_err.re_status = RPC_INTR;
7050Sstevel@tonic-gate p->cku_err.re_errno = EINTR;
7060Sstevel@tonic-gate }
7070Sstevel@tonic-gate }
7080Sstevel@tonic-gate break;
7090Sstevel@tonic-gate }
7100Sstevel@tonic-gate
7110Sstevel@tonic-gate return (p->cku_err.re_status);
7120Sstevel@tonic-gate }
7137387SRobert.Gordon@Sun.COM
7149733SFaramarz.Jalalian@Sun.COM if (p->cku_srcaddr.maxlen < conn->c_laddr.len) {
7159733SFaramarz.Jalalian@Sun.COM if ((p->cku_srcaddr.maxlen != 0) &&
7169733SFaramarz.Jalalian@Sun.COM (p->cku_srcaddr.buf != NULL))
7179733SFaramarz.Jalalian@Sun.COM kmem_free(p->cku_srcaddr.buf, p->cku_srcaddr.maxlen);
7189733SFaramarz.Jalalian@Sun.COM p->cku_srcaddr.buf = kmem_zalloc(conn->c_laddr.maxlen,
7199733SFaramarz.Jalalian@Sun.COM KM_SLEEP);
7209733SFaramarz.Jalalian@Sun.COM p->cku_srcaddr.maxlen = conn->c_laddr.maxlen;
7219733SFaramarz.Jalalian@Sun.COM }
7229733SFaramarz.Jalalian@Sun.COM
7239733SFaramarz.Jalalian@Sun.COM p->cku_srcaddr.len = conn->c_laddr.len;
7249733SFaramarz.Jalalian@Sun.COM bcopy(conn->c_laddr.buf, p->cku_srcaddr.buf, conn->c_laddr.len);
7259733SFaramarz.Jalalian@Sun.COM
7267387SRobert.Gordon@Sun.COM clnt_check_credit(conn);
7270Sstevel@tonic-gate
7287387SRobert.Gordon@Sun.COM status = CLNT_RDMA_FAIL;
7297387SRobert.Gordon@Sun.COM
7307387SRobert.Gordon@Sun.COM rpcsec_gss = gss_i_or_p = FALSE;
7310Sstevel@tonic-gate
7327387SRobert.Gordon@Sun.COM if (IS_RPCSEC_GSS(h)) {
7337387SRobert.Gordon@Sun.COM rpcsec_gss = TRUE;
7347387SRobert.Gordon@Sun.COM if (rpc_gss_get_service_type(h->cl_auth) ==
7357387SRobert.Gordon@Sun.COM rpc_gss_svc_integrity ||
7367387SRobert.Gordon@Sun.COM rpc_gss_get_service_type(h->cl_auth) ==
7377387SRobert.Gordon@Sun.COM rpc_gss_svc_privacy)
7387387SRobert.Gordon@Sun.COM gss_i_or_p = TRUE;
7390Sstevel@tonic-gate }
7400Sstevel@tonic-gate
7417387SRobert.Gordon@Sun.COM /*
7427387SRobert.Gordon@Sun.COM * Try a regular RDMA message if RPCSEC_GSS is not being used
7437387SRobert.Gordon@Sun.COM * or if RPCSEC_GSS is being used for authentication only.
7447387SRobert.Gordon@Sun.COM */
7457387SRobert.Gordon@Sun.COM if (rpcsec_gss == FALSE ||
7467387SRobert.Gordon@Sun.COM (rpcsec_gss == TRUE && gss_i_or_p == FALSE)) {
7470Sstevel@tonic-gate /*
7487387SRobert.Gordon@Sun.COM * Grab a send buffer for the request. Try to
7497387SRobert.Gordon@Sun.COM * encode it to see if it fits. If not, then it
7507387SRobert.Gordon@Sun.COM * needs to be sent in a chunk.
7510Sstevel@tonic-gate */
7527387SRobert.Gordon@Sun.COM rpcmsg.type = SEND_BUFFER;
7537387SRobert.Gordon@Sun.COM if (rdma_buf_alloc(conn, &rpcmsg)) {
7547387SRobert.Gordon@Sun.COM DTRACE_PROBE(krpc__e__clntrdma__callit_nobufs);
7550Sstevel@tonic-gate goto done;
7560Sstevel@tonic-gate }
7577387SRobert.Gordon@Sun.COM
7587387SRobert.Gordon@Sun.COM /* First try to encode into regular send buffer */
7597387SRobert.Gordon@Sun.COM op = RDMA_MSG;
7600Sstevel@tonic-gate
7617387SRobert.Gordon@Sun.COM call_xdrp = &callxdr;
7627387SRobert.Gordon@Sun.COM
7637387SRobert.Gordon@Sun.COM xdrrdma_create(call_xdrp, rpcmsg.addr, rpcmsg.len,
7647387SRobert.Gordon@Sun.COM rdma_minchunk, NULL, XDR_ENCODE, conn);
7650Sstevel@tonic-gate
7667387SRobert.Gordon@Sun.COM status = clnt_compose_rpcmsg(h, procnum, &rpcmsg, call_xdrp,
7677387SRobert.Gordon@Sun.COM xdr_args, argsp);
7687387SRobert.Gordon@Sun.COM
7697387SRobert.Gordon@Sun.COM if (status != CLNT_RDMA_SUCCESS) {
7707387SRobert.Gordon@Sun.COM /* Clean up from previous encode attempt */
7717387SRobert.Gordon@Sun.COM rdma_buf_free(conn, &rpcmsg);
7727387SRobert.Gordon@Sun.COM XDR_DESTROY(call_xdrp);
7730Sstevel@tonic-gate } else {
7747387SRobert.Gordon@Sun.COM XDR_CONTROL(call_xdrp, XDR_RDMA_GET_CHUNK_LEN, &rcil);
7750Sstevel@tonic-gate }
7760Sstevel@tonic-gate }
7770Sstevel@tonic-gate
7787387SRobert.Gordon@Sun.COM /* If the encode didn't work, then try a NOMSG */
7797387SRobert.Gordon@Sun.COM if (status != CLNT_RDMA_SUCCESS) {
7807387SRobert.Gordon@Sun.COM
7817387SRobert.Gordon@Sun.COM msglen = CKU_HDRSIZE + BYTES_PER_XDR_UNIT + MAX_AUTH_BYTES +
7827387SRobert.Gordon@Sun.COM xdr_sizeof(xdr_args, argsp);
7837387SRobert.Gordon@Sun.COM
7847387SRobert.Gordon@Sun.COM msglen = calc_length(msglen);
7857387SRobert.Gordon@Sun.COM
7867387SRobert.Gordon@Sun.COM /* pick up the lengths for the reply buffer needed */
7877387SRobert.Gordon@Sun.COM (void) xdrrdma_sizeof(xdr_args, argsp, 0,
7887387SRobert.Gordon@Sun.COM &rcil.rcil_len, &rcil.rcil_len_alt);
7897387SRobert.Gordon@Sun.COM
7907387SRobert.Gordon@Sun.COM /*
7917387SRobert.Gordon@Sun.COM * Construct a clist to describe the CHUNK_BUFFER
7927387SRobert.Gordon@Sun.COM * for the rpcmsg.
7937387SRobert.Gordon@Sun.COM */
7947387SRobert.Gordon@Sun.COM cl_rpcmsg = clist_alloc();
7957387SRobert.Gordon@Sun.COM cl_rpcmsg->c_len = msglen;
7967387SRobert.Gordon@Sun.COM cl_rpcmsg->rb_longbuf.type = RDMA_LONG_BUFFER;
7977387SRobert.Gordon@Sun.COM cl_rpcmsg->rb_longbuf.len = msglen;
7987387SRobert.Gordon@Sun.COM if (rdma_buf_alloc(conn, &cl_rpcmsg->rb_longbuf)) {
7997387SRobert.Gordon@Sun.COM clist_free(cl_rpcmsg);
8007387SRobert.Gordon@Sun.COM goto done;
8017387SRobert.Gordon@Sun.COM }
8027387SRobert.Gordon@Sun.COM cl_rpcmsg->w.c_saddr3 = cl_rpcmsg->rb_longbuf.addr;
8037387SRobert.Gordon@Sun.COM
8047387SRobert.Gordon@Sun.COM op = RDMA_NOMSG;
8057387SRobert.Gordon@Sun.COM call_xdrp = &callxdr;
8067387SRobert.Gordon@Sun.COM
8077387SRobert.Gordon@Sun.COM xdrrdma_create(call_xdrp, cl_rpcmsg->rb_longbuf.addr,
8087387SRobert.Gordon@Sun.COM cl_rpcmsg->rb_longbuf.len, 0,
8097387SRobert.Gordon@Sun.COM cl_rpcmsg, XDR_ENCODE, conn);
8107387SRobert.Gordon@Sun.COM
811*11591SFaramarz.Jalalian@Sun.COM status = clnt_compose_rpcmsg(h, procnum, &cl_rpcmsg->rb_longbuf,
812*11591SFaramarz.Jalalian@Sun.COM call_xdrp, xdr_args, argsp);
8137387SRobert.Gordon@Sun.COM
814*11591SFaramarz.Jalalian@Sun.COM DTRACE_PROBE2(krpc__i__clntrdma__callit__longbuf, int, status,
815*11591SFaramarz.Jalalian@Sun.COM int, msglen);
8167387SRobert.Gordon@Sun.COM if (status != CLNT_RDMA_SUCCESS) {
8177387SRobert.Gordon@Sun.COM p->cku_err.re_status = RPC_CANTENCODEARGS;
8187387SRobert.Gordon@Sun.COM p->cku_err.re_errno = EIO;
8197387SRobert.Gordon@Sun.COM DTRACE_PROBE(krpc__e__clntrdma__callit__composemsg);
8207387SRobert.Gordon@Sun.COM goto done;
8217387SRobert.Gordon@Sun.COM }
8227387SRobert.Gordon@Sun.COM }
8237387SRobert.Gordon@Sun.COM
8247387SRobert.Gordon@Sun.COM /*
8257387SRobert.Gordon@Sun.COM * During the XDR_ENCODE we may have "allocated" an RDMA READ or
8267387SRobert.Gordon@Sun.COM * RDMA WRITE clist.
8277387SRobert.Gordon@Sun.COM *
8287387SRobert.Gordon@Sun.COM * First pull the RDMA READ chunk list from the XDR private
8297387SRobert.Gordon@Sun.COM * area to keep it handy.
8307387SRobert.Gordon@Sun.COM */
8317387SRobert.Gordon@Sun.COM XDR_CONTROL(call_xdrp, XDR_RDMA_GET_RLIST, &cl);
8327387SRobert.Gordon@Sun.COM
8337387SRobert.Gordon@Sun.COM if (gss_i_or_p) {
8347387SRobert.Gordon@Sun.COM long_reply_len = rcil.rcil_len + rcil.rcil_len_alt;
8357387SRobert.Gordon@Sun.COM long_reply_len += MAX_AUTH_BYTES;
8367387SRobert.Gordon@Sun.COM } else {
8377387SRobert.Gordon@Sun.COM long_reply_len = rcil.rcil_len;
8387387SRobert.Gordon@Sun.COM }
8390Sstevel@tonic-gate
8400Sstevel@tonic-gate /*
8410Sstevel@tonic-gate * Update the chunk size information for the Long RPC msg.
8420Sstevel@tonic-gate */
8430Sstevel@tonic-gate if (cl && op == RDMA_NOMSG)
8440Sstevel@tonic-gate cl->c_len = p->cku_outsz;
8450Sstevel@tonic-gate
8460Sstevel@tonic-gate /*
8477387SRobert.Gordon@Sun.COM * Prepare the RDMA header. On success xdrs will hold the result
8487387SRobert.Gordon@Sun.COM * of xdrmem_create() for a SEND_BUFFER.
8490Sstevel@tonic-gate */
8507387SRobert.Gordon@Sun.COM status = clnt_compose_rdma_header(conn, h, &clmsg,
8517387SRobert.Gordon@Sun.COM &rdmahdr_o_xdrs, &op);
8527387SRobert.Gordon@Sun.COM
8537387SRobert.Gordon@Sun.COM if (status != CLNT_RDMA_SUCCESS) {
8540Sstevel@tonic-gate p->cku_err.re_status = RPC_CANTSEND;
8550Sstevel@tonic-gate p->cku_err.re_errno = EIO;
8560Sstevel@tonic-gate RCSTAT_INCR(rcnomem);
8577387SRobert.Gordon@Sun.COM DTRACE_PROBE(krpc__e__clntrdma__callit__nobufs2);
8580Sstevel@tonic-gate goto done;
8590Sstevel@tonic-gate }
8607387SRobert.Gordon@Sun.COM
8610Sstevel@tonic-gate /*
8627387SRobert.Gordon@Sun.COM * Now insert the RDMA READ list iff present
8630Sstevel@tonic-gate */
8647387SRobert.Gordon@Sun.COM status = clnt_setup_rlist(conn, rdmahdr_o_xdrs, call_xdrp);
8657387SRobert.Gordon@Sun.COM if (status != CLNT_RDMA_SUCCESS) {
8667387SRobert.Gordon@Sun.COM DTRACE_PROBE(krpc__e__clntrdma__callit__clistreg);
8677387SRobert.Gordon@Sun.COM rdma_buf_free(conn, &clmsg);
8687387SRobert.Gordon@Sun.COM p->cku_err.re_status = RPC_CANTSEND;
8697387SRobert.Gordon@Sun.COM p->cku_err.re_errno = EIO;
8707387SRobert.Gordon@Sun.COM goto done;
8717387SRobert.Gordon@Sun.COM }
8727387SRobert.Gordon@Sun.COM
8737387SRobert.Gordon@Sun.COM /*
8747387SRobert.Gordon@Sun.COM * Setup RDMA WRITE chunk list for nfs read operation
8757387SRobert.Gordon@Sun.COM * other operations will have a NULL which will result
8767387SRobert.Gordon@Sun.COM * as a NULL list in the XDR stream.
8777387SRobert.Gordon@Sun.COM */
8789348SSiddheshwar.Mahesh@Sun.COM status = clnt_setup_wlist(conn, rdmahdr_o_xdrs, call_xdrp, &rndup);
8797387SRobert.Gordon@Sun.COM if (status != CLNT_RDMA_SUCCESS) {
8807387SRobert.Gordon@Sun.COM rdma_buf_free(conn, &clmsg);
8817387SRobert.Gordon@Sun.COM p->cku_err.re_status = RPC_CANTSEND;
8827387SRobert.Gordon@Sun.COM p->cku_err.re_errno = EIO;
8837387SRobert.Gordon@Sun.COM goto done;
8847387SRobert.Gordon@Sun.COM }
8850Sstevel@tonic-gate
8860Sstevel@tonic-gate /*
8877387SRobert.Gordon@Sun.COM * If NULL call and RPCSEC_GSS, provide a chunk such that
8887387SRobert.Gordon@Sun.COM * large responses can flow back to the client.
8897387SRobert.Gordon@Sun.COM * If RPCSEC_GSS with integrity or privacy is in use, get chunk.
8900Sstevel@tonic-gate */
8917387SRobert.Gordon@Sun.COM if ((procnum == 0 && rpcsec_gss == TRUE) ||
8927387SRobert.Gordon@Sun.COM (rpcsec_gss == TRUE && gss_i_or_p == TRUE))
8937387SRobert.Gordon@Sun.COM long_reply_len += 1024;
8940Sstevel@tonic-gate
8957387SRobert.Gordon@Sun.COM status = clnt_setup_long_reply(conn, &cl_long_reply, long_reply_len);
8960Sstevel@tonic-gate
897*11591SFaramarz.Jalalian@Sun.COM DTRACE_PROBE2(krpc__i__clntrdma__callit__longreply, int, status,
898*11591SFaramarz.Jalalian@Sun.COM int, long_reply_len);
899*11591SFaramarz.Jalalian@Sun.COM
9007387SRobert.Gordon@Sun.COM if (status != CLNT_RDMA_SUCCESS) {
9017387SRobert.Gordon@Sun.COM rdma_buf_free(conn, &clmsg);
9027387SRobert.Gordon@Sun.COM p->cku_err.re_status = RPC_CANTSEND;
9037387SRobert.Gordon@Sun.COM p->cku_err.re_errno = EIO;
9047387SRobert.Gordon@Sun.COM goto done;
9050Sstevel@tonic-gate }
9060Sstevel@tonic-gate
9070Sstevel@tonic-gate /*
9087387SRobert.Gordon@Sun.COM * XDR encode the RDMA_REPLY write chunk
9097387SRobert.Gordon@Sun.COM */
9107387SRobert.Gordon@Sun.COM seg_array_len = (cl_long_reply ? 1 : 0);
9117387SRobert.Gordon@Sun.COM (void) xdr_encode_reply_wchunk(rdmahdr_o_xdrs, cl_long_reply,
9127387SRobert.Gordon@Sun.COM seg_array_len);
9137387SRobert.Gordon@Sun.COM
9147387SRobert.Gordon@Sun.COM /*
9157387SRobert.Gordon@Sun.COM * Construct a clist in "sendlist" that represents what we
9167387SRobert.Gordon@Sun.COM * will push over the wire.
9177387SRobert.Gordon@Sun.COM *
9180Sstevel@tonic-gate * Start with the RDMA header and clist (if any)
9190Sstevel@tonic-gate */
9207387SRobert.Gordon@Sun.COM clist_add(&cl_sendlist, 0, XDR_GETPOS(rdmahdr_o_xdrs), &clmsg.handle,
9217387SRobert.Gordon@Sun.COM clmsg.addr, NULL, NULL);
9220Sstevel@tonic-gate
9230Sstevel@tonic-gate /*
9247387SRobert.Gordon@Sun.COM * Put the RPC call message in sendlist if small RPC
9250Sstevel@tonic-gate */
9260Sstevel@tonic-gate if (op == RDMA_MSG) {
9277387SRobert.Gordon@Sun.COM clist_add(&cl_sendlist, 0, p->cku_outsz, &rpcmsg.handle,
9287387SRobert.Gordon@Sun.COM rpcmsg.addr, NULL, NULL);
9290Sstevel@tonic-gate } else {
9300Sstevel@tonic-gate /* Long RPC already in chunk list */
9310Sstevel@tonic-gate RCSTAT_INCR(rclongrpcs);
9320Sstevel@tonic-gate }
9330Sstevel@tonic-gate
9340Sstevel@tonic-gate /*
9350Sstevel@tonic-gate * Set up a reply buffer ready for the reply
9360Sstevel@tonic-gate */
9370Sstevel@tonic-gate status = rdma_clnt_postrecv(conn, p->cku_xid);
9380Sstevel@tonic-gate if (status != RDMA_SUCCESS) {
9390Sstevel@tonic-gate rdma_buf_free(conn, &clmsg);
9400Sstevel@tonic-gate p->cku_err.re_status = RPC_CANTSEND;
9410Sstevel@tonic-gate p->cku_err.re_errno = EIO;
9420Sstevel@tonic-gate goto done;
9430Sstevel@tonic-gate }
9447387SRobert.Gordon@Sun.COM
9450Sstevel@tonic-gate /*
9460Sstevel@tonic-gate * sync the memory for dma
9470Sstevel@tonic-gate */
9480Sstevel@tonic-gate if (cl != NULL) {
9497387SRobert.Gordon@Sun.COM status = clist_syncmem(conn, cl, CLIST_REG_SOURCE);
9500Sstevel@tonic-gate if (status != RDMA_SUCCESS) {
9517387SRobert.Gordon@Sun.COM (void) rdma_clnt_postrecv_remove(conn, p->cku_xid);
9520Sstevel@tonic-gate rdma_buf_free(conn, &clmsg);
9530Sstevel@tonic-gate p->cku_err.re_status = RPC_CANTSEND;
9540Sstevel@tonic-gate p->cku_err.re_errno = EIO;
9550Sstevel@tonic-gate goto done;
9560Sstevel@tonic-gate }
9570Sstevel@tonic-gate }
9580Sstevel@tonic-gate
9590Sstevel@tonic-gate /*
9607387SRobert.Gordon@Sun.COM * Send the RDMA Header and RPC call message to the server
9610Sstevel@tonic-gate */
9627387SRobert.Gordon@Sun.COM status = RDMA_SEND(conn, cl_sendlist, p->cku_xid);
9630Sstevel@tonic-gate if (status != RDMA_SUCCESS) {
9647387SRobert.Gordon@Sun.COM (void) rdma_clnt_postrecv_remove(conn, p->cku_xid);
9650Sstevel@tonic-gate p->cku_err.re_status = RPC_CANTSEND;
9660Sstevel@tonic-gate p->cku_err.re_errno = EIO;
9670Sstevel@tonic-gate goto done;
9680Sstevel@tonic-gate }
9697387SRobert.Gordon@Sun.COM
9707387SRobert.Gordon@Sun.COM /*
9717387SRobert.Gordon@Sun.COM * RDMA plugin now owns the send msg buffers.
9727387SRobert.Gordon@Sun.COM * Clear them out and don't free them.
9737387SRobert.Gordon@Sun.COM */
9747387SRobert.Gordon@Sun.COM clmsg.addr = NULL;
9757387SRobert.Gordon@Sun.COM if (rpcmsg.type == SEND_BUFFER)
9767387SRobert.Gordon@Sun.COM rpcmsg.addr = NULL;
9770Sstevel@tonic-gate
9780Sstevel@tonic-gate /*
9790Sstevel@tonic-gate * Recv rpc reply
9800Sstevel@tonic-gate */
9817387SRobert.Gordon@Sun.COM status = RDMA_RECV(conn, &cl_recvlist, p->cku_xid);
9820Sstevel@tonic-gate
9830Sstevel@tonic-gate /*
9840Sstevel@tonic-gate * Now check recv status
9850Sstevel@tonic-gate */
9860Sstevel@tonic-gate if (status != 0) {
9870Sstevel@tonic-gate if (status == RDMA_INTR) {
9880Sstevel@tonic-gate p->cku_err.re_status = RPC_INTR;
9890Sstevel@tonic-gate p->cku_err.re_errno = EINTR;
9900Sstevel@tonic-gate RCSTAT_INCR(rcintrs);
9910Sstevel@tonic-gate } else if (status == RPC_TIMEDOUT) {
9920Sstevel@tonic-gate p->cku_err.re_status = RPC_TIMEDOUT;
9930Sstevel@tonic-gate p->cku_err.re_errno = ETIMEDOUT;
9940Sstevel@tonic-gate RCSTAT_INCR(rctimeouts);
9950Sstevel@tonic-gate } else {
9960Sstevel@tonic-gate p->cku_err.re_status = RPC_CANTRECV;
9970Sstevel@tonic-gate p->cku_err.re_errno = EIO;
9980Sstevel@tonic-gate }
9990Sstevel@tonic-gate goto done;
10000Sstevel@tonic-gate }
10017387SRobert.Gordon@Sun.COM
10020Sstevel@tonic-gate /*
10030Sstevel@tonic-gate * Process the reply message.
10040Sstevel@tonic-gate *
10050Sstevel@tonic-gate * First the chunk list (if any)
10060Sstevel@tonic-gate */
10077387SRobert.Gordon@Sun.COM rdmahdr_i_xdrs = &(p->cku_inxdr);
10087387SRobert.Gordon@Sun.COM xdrmem_create(rdmahdr_i_xdrs,
10097387SRobert.Gordon@Sun.COM (caddr_t)(uintptr_t)cl_recvlist->w.c_saddr3,
10107387SRobert.Gordon@Sun.COM cl_recvlist->c_len, XDR_DECODE);
10117387SRobert.Gordon@Sun.COM
10120Sstevel@tonic-gate /*
10130Sstevel@tonic-gate * Treat xid as opaque (xid is the first entity
10140Sstevel@tonic-gate * in the rpc rdma message).
10157387SRobert.Gordon@Sun.COM * Skip xid and set the xdr position accordingly.
10160Sstevel@tonic-gate */
10177387SRobert.Gordon@Sun.COM XDR_SETPOS(rdmahdr_i_xdrs, sizeof (uint32_t));
10187387SRobert.Gordon@Sun.COM (void) xdr_u_int(rdmahdr_i_xdrs, &vers);
10197387SRobert.Gordon@Sun.COM (void) xdr_u_int(rdmahdr_i_xdrs, &rdma_credit);
10207387SRobert.Gordon@Sun.COM (void) xdr_u_int(rdmahdr_i_xdrs, &op);
10217387SRobert.Gordon@Sun.COM (void) xdr_do_clist(rdmahdr_i_xdrs, &cl);
10227387SRobert.Gordon@Sun.COM
10237387SRobert.Gordon@Sun.COM clnt_update_credit(conn, rdma_credit);
10247387SRobert.Gordon@Sun.COM
10257387SRobert.Gordon@Sun.COM wlist_exists_reply = FALSE;
10267387SRobert.Gordon@Sun.COM if (! xdr_decode_wlist(rdmahdr_i_xdrs, &cl_rpcreply_wlist,
10277387SRobert.Gordon@Sun.COM &wlist_exists_reply)) {
10287387SRobert.Gordon@Sun.COM DTRACE_PROBE(krpc__e__clntrdma__callit__wlist_decode);
10297387SRobert.Gordon@Sun.COM p->cku_err.re_status = RPC_CANTDECODERES;
10307387SRobert.Gordon@Sun.COM p->cku_err.re_errno = EIO;
10317387SRobert.Gordon@Sun.COM goto done;
10327387SRobert.Gordon@Sun.COM }
10330Sstevel@tonic-gate
10340Sstevel@tonic-gate /*
10357387SRobert.Gordon@Sun.COM * The server shouldn't have sent a RDMA_SEND that
10367387SRobert.Gordon@Sun.COM * the client needs to RDMA_WRITE a reply back to
10377387SRobert.Gordon@Sun.COM * the server. So silently ignoring what the
10387387SRobert.Gordon@Sun.COM * server returns in the rdma_reply section of the
10397387SRobert.Gordon@Sun.COM * header.
10400Sstevel@tonic-gate */
10417387SRobert.Gordon@Sun.COM (void) xdr_decode_reply_wchunk(rdmahdr_i_xdrs, &cl_rdma_reply);
10427387SRobert.Gordon@Sun.COM off = xdr_getpos(rdmahdr_i_xdrs);
10430Sstevel@tonic-gate
10447387SRobert.Gordon@Sun.COM clnt_decode_long_reply(conn, cl_long_reply,
10457387SRobert.Gordon@Sun.COM cl_rdma_reply, &replyxdr, &reply_xdrp,
10467387SRobert.Gordon@Sun.COM cl, cl_recvlist, op, off);
10470Sstevel@tonic-gate
10487387SRobert.Gordon@Sun.COM if (reply_xdrp == NULL)
10497387SRobert.Gordon@Sun.COM goto done;
10500Sstevel@tonic-gate
10517387SRobert.Gordon@Sun.COM if (wlist_exists_reply) {
10527387SRobert.Gordon@Sun.COM XDR_CONTROL(reply_xdrp, XDR_RDMA_SET_WLIST, cl_rpcreply_wlist);
10530Sstevel@tonic-gate }
10540Sstevel@tonic-gate
10550Sstevel@tonic-gate reply_msg.rm_direction = REPLY;
10560Sstevel@tonic-gate reply_msg.rm_reply.rp_stat = MSG_ACCEPTED;
10570Sstevel@tonic-gate reply_msg.acpted_rply.ar_stat = SUCCESS;
10580Sstevel@tonic-gate reply_msg.acpted_rply.ar_verf = _null_auth;
10597387SRobert.Gordon@Sun.COM
10600Sstevel@tonic-gate /*
10610Sstevel@tonic-gate * xdr_results will be done in AUTH_UNWRAP.
10620Sstevel@tonic-gate */
10630Sstevel@tonic-gate reply_msg.acpted_rply.ar_results.where = NULL;
10640Sstevel@tonic-gate reply_msg.acpted_rply.ar_results.proc = xdr_void;
10650Sstevel@tonic-gate
10660Sstevel@tonic-gate /*
10670Sstevel@tonic-gate * Decode and validate the response.
10680Sstevel@tonic-gate */
10697387SRobert.Gordon@Sun.COM if (xdr_replymsg(reply_xdrp, &reply_msg)) {
10700Sstevel@tonic-gate enum clnt_stat re_status;
10710Sstevel@tonic-gate
10720Sstevel@tonic-gate _seterr_reply(&reply_msg, &(p->cku_err));
10730Sstevel@tonic-gate
10740Sstevel@tonic-gate re_status = p->cku_err.re_status;
10750Sstevel@tonic-gate if (re_status == RPC_SUCCESS) {
10760Sstevel@tonic-gate /*
10770Sstevel@tonic-gate * Reply is good, check auth.
10780Sstevel@tonic-gate */
10790Sstevel@tonic-gate if (!AUTH_VALIDATE(h->cl_auth,
10800Sstevel@tonic-gate &reply_msg.acpted_rply.ar_verf)) {
10810Sstevel@tonic-gate p->cku_err.re_status = RPC_AUTHERROR;
10820Sstevel@tonic-gate p->cku_err.re_why = AUTH_INVALIDRESP;
10830Sstevel@tonic-gate RCSTAT_INCR(rcbadverfs);
10847387SRobert.Gordon@Sun.COM DTRACE_PROBE(
10857387SRobert.Gordon@Sun.COM krpc__e__clntrdma__callit__authvalidate);
10867387SRobert.Gordon@Sun.COM } else if (!AUTH_UNWRAP(h->cl_auth, reply_xdrp,
10870Sstevel@tonic-gate xdr_results, resultsp)) {
10880Sstevel@tonic-gate p->cku_err.re_status = RPC_CANTDECODERES;
10890Sstevel@tonic-gate p->cku_err.re_errno = EIO;
10907387SRobert.Gordon@Sun.COM DTRACE_PROBE(
10917387SRobert.Gordon@Sun.COM krpc__e__clntrdma__callit__authunwrap);
10920Sstevel@tonic-gate }
10930Sstevel@tonic-gate } else {
10940Sstevel@tonic-gate /* set errno in case we can't recover */
10950Sstevel@tonic-gate if (re_status != RPC_VERSMISMATCH &&
10960Sstevel@tonic-gate re_status != RPC_AUTHERROR &&
10970Sstevel@tonic-gate re_status != RPC_PROGVERSMISMATCH)
10980Sstevel@tonic-gate p->cku_err.re_errno = EIO;
10990Sstevel@tonic-gate
11000Sstevel@tonic-gate if (re_status == RPC_AUTHERROR) {
11017387SRobert.Gordon@Sun.COM if ((refresh_attempt > 0) &&
11027387SRobert.Gordon@Sun.COM AUTH_REFRESH(h->cl_auth, &reply_msg,
11037387SRobert.Gordon@Sun.COM p->cku_cred)) {
11047387SRobert.Gordon@Sun.COM refresh_attempt--;
11057387SRobert.Gordon@Sun.COM try_call_again = 1;
11067387SRobert.Gordon@Sun.COM goto done;
11077387SRobert.Gordon@Sun.COM }
11087387SRobert.Gordon@Sun.COM
11097387SRobert.Gordon@Sun.COM try_call_again = 0;
11107387SRobert.Gordon@Sun.COM
11117387SRobert.Gordon@Sun.COM /*
11127387SRobert.Gordon@Sun.COM * We have used the client handle to
11137387SRobert.Gordon@Sun.COM * do an AUTH_REFRESH and the RPC status may
11147387SRobert.Gordon@Sun.COM * be set to RPC_SUCCESS; Let's make sure to
11157387SRobert.Gordon@Sun.COM * set it to RPC_AUTHERROR.
11167387SRobert.Gordon@Sun.COM */
11177387SRobert.Gordon@Sun.COM p->cku_err.re_status = RPC_AUTHERROR;
11187387SRobert.Gordon@Sun.COM
11190Sstevel@tonic-gate /*
11200Sstevel@tonic-gate * Map recoverable and unrecoverable
11210Sstevel@tonic-gate * authentication errors to appropriate
11220Sstevel@tonic-gate * errno
11230Sstevel@tonic-gate */
11240Sstevel@tonic-gate switch (p->cku_err.re_why) {
11250Sstevel@tonic-gate case AUTH_BADCRED:
11260Sstevel@tonic-gate case AUTH_BADVERF:
11270Sstevel@tonic-gate case AUTH_INVALIDRESP:
11280Sstevel@tonic-gate case AUTH_TOOWEAK:
11290Sstevel@tonic-gate case AUTH_FAILED:
11300Sstevel@tonic-gate case RPCSEC_GSS_NOCRED:
11310Sstevel@tonic-gate case RPCSEC_GSS_FAILED:
11320Sstevel@tonic-gate p->cku_err.re_errno = EACCES;
11330Sstevel@tonic-gate break;
11340Sstevel@tonic-gate case AUTH_REJECTEDCRED:
11350Sstevel@tonic-gate case AUTH_REJECTEDVERF:
11360Sstevel@tonic-gate default:
11370Sstevel@tonic-gate p->cku_err.re_errno = EIO;
11380Sstevel@tonic-gate break;
11390Sstevel@tonic-gate }
11400Sstevel@tonic-gate }
11417387SRobert.Gordon@Sun.COM DTRACE_PROBE1(krpc__e__clntrdma__callit__rpcfailed,
11427387SRobert.Gordon@Sun.COM int, p->cku_err.re_why);
11430Sstevel@tonic-gate }
11440Sstevel@tonic-gate } else {
11450Sstevel@tonic-gate p->cku_err.re_status = RPC_CANTDECODERES;
11460Sstevel@tonic-gate p->cku_err.re_errno = EIO;
11477387SRobert.Gordon@Sun.COM DTRACE_PROBE(krpc__e__clntrdma__callit__replymsg);
11480Sstevel@tonic-gate }
11490Sstevel@tonic-gate
11507387SRobert.Gordon@Sun.COM done:
11517387SRobert.Gordon@Sun.COM clnt_return_credit(conn);
11527387SRobert.Gordon@Sun.COM
11537387SRobert.Gordon@Sun.COM if (cl_sendlist != NULL)
11547387SRobert.Gordon@Sun.COM clist_free(cl_sendlist);
11557387SRobert.Gordon@Sun.COM
11560Sstevel@tonic-gate /*
11570Sstevel@tonic-gate * If rpc reply is in a chunk, free it now.
11580Sstevel@tonic-gate */
11597387SRobert.Gordon@Sun.COM if (cl_long_reply) {
11609348SSiddheshwar.Mahesh@Sun.COM (void) clist_deregister(conn, cl_long_reply);
11617387SRobert.Gordon@Sun.COM rdma_buf_free(conn, &cl_long_reply->rb_longbuf);
11627387SRobert.Gordon@Sun.COM clist_free(cl_long_reply);
11637387SRobert.Gordon@Sun.COM }
11640Sstevel@tonic-gate
11657387SRobert.Gordon@Sun.COM if (call_xdrp)
11667387SRobert.Gordon@Sun.COM XDR_DESTROY(call_xdrp);
11670Sstevel@tonic-gate
11689348SSiddheshwar.Mahesh@Sun.COM if (rndup.rb_private) {
11699348SSiddheshwar.Mahesh@Sun.COM rdma_buf_free(conn, &rndup);
11709348SSiddheshwar.Mahesh@Sun.COM }
11719348SSiddheshwar.Mahesh@Sun.COM
11727387SRobert.Gordon@Sun.COM if (reply_xdrp) {
11737387SRobert.Gordon@Sun.COM (void) xdr_rpc_free_verifier(reply_xdrp, &reply_msg);
11747387SRobert.Gordon@Sun.COM XDR_DESTROY(reply_xdrp);
11750Sstevel@tonic-gate }
11760Sstevel@tonic-gate
11777387SRobert.Gordon@Sun.COM if (cl_rdma_reply) {
11787387SRobert.Gordon@Sun.COM clist_free(cl_rdma_reply);
11790Sstevel@tonic-gate }
11800Sstevel@tonic-gate
11817387SRobert.Gordon@Sun.COM if (cl_recvlist) {
11827387SRobert.Gordon@Sun.COM rdma_buf_t recvmsg = {0};
11837387SRobert.Gordon@Sun.COM recvmsg.addr = (caddr_t)(uintptr_t)cl_recvlist->w.c_saddr3;
11840Sstevel@tonic-gate recvmsg.type = RECV_BUFFER;
11850Sstevel@tonic-gate RDMA_BUF_FREE(conn, &recvmsg);
11867387SRobert.Gordon@Sun.COM clist_free(cl_recvlist);
11870Sstevel@tonic-gate }
11887387SRobert.Gordon@Sun.COM
11890Sstevel@tonic-gate RDMA_REL_CONN(conn);
11907387SRobert.Gordon@Sun.COM
11917387SRobert.Gordon@Sun.COM if (try_call_again)
11927387SRobert.Gordon@Sun.COM goto call_again;
11937387SRobert.Gordon@Sun.COM
11940Sstevel@tonic-gate if (p->cku_err.re_status != RPC_SUCCESS) {
11950Sstevel@tonic-gate RCSTAT_INCR(rcbadcalls);
11960Sstevel@tonic-gate }
11970Sstevel@tonic-gate return (p->cku_err.re_status);
11980Sstevel@tonic-gate }
11990Sstevel@tonic-gate
12007387SRobert.Gordon@Sun.COM
12017387SRobert.Gordon@Sun.COM static void
clnt_decode_long_reply(CONN * conn,struct clist * cl_long_reply,struct clist * cl_rdma_reply,XDR * xdrs,XDR ** rxdrp,struct clist * cl,struct clist * cl_recvlist,uint_t op,uint_t off)12027387SRobert.Gordon@Sun.COM clnt_decode_long_reply(CONN *conn,
12037387SRobert.Gordon@Sun.COM struct clist *cl_long_reply,
12047387SRobert.Gordon@Sun.COM struct clist *cl_rdma_reply, XDR *xdrs,
12057387SRobert.Gordon@Sun.COM XDR **rxdrp, struct clist *cl,
12067387SRobert.Gordon@Sun.COM struct clist *cl_recvlist,
12077387SRobert.Gordon@Sun.COM uint_t op, uint_t off)
12087387SRobert.Gordon@Sun.COM {
12097387SRobert.Gordon@Sun.COM if (op != RDMA_NOMSG) {
12107387SRobert.Gordon@Sun.COM DTRACE_PROBE1(krpc__i__longrepl__rdmamsg__len,
12117387SRobert.Gordon@Sun.COM int, cl_recvlist->c_len - off);
12127387SRobert.Gordon@Sun.COM xdrrdma_create(xdrs,
12137387SRobert.Gordon@Sun.COM (caddr_t)(uintptr_t)(cl_recvlist->w.c_saddr3 + off),
12147387SRobert.Gordon@Sun.COM cl_recvlist->c_len - off, 0, cl, XDR_DECODE, conn);
12157387SRobert.Gordon@Sun.COM *rxdrp = xdrs;
12167387SRobert.Gordon@Sun.COM return;
12177387SRobert.Gordon@Sun.COM }
12187387SRobert.Gordon@Sun.COM
12197387SRobert.Gordon@Sun.COM /* op must be RDMA_NOMSG */
12207387SRobert.Gordon@Sun.COM if (cl) {
12217387SRobert.Gordon@Sun.COM DTRACE_PROBE(krpc__e__clntrdma__declongreply__serverreadlist);
12227387SRobert.Gordon@Sun.COM return;
12237387SRobert.Gordon@Sun.COM }
12247387SRobert.Gordon@Sun.COM
12257387SRobert.Gordon@Sun.COM if (cl_long_reply->u.c_daddr) {
12267387SRobert.Gordon@Sun.COM DTRACE_PROBE1(krpc__i__longrepl__rdmanomsg__len,
12277387SRobert.Gordon@Sun.COM int, cl_rdma_reply->c_len);
12287387SRobert.Gordon@Sun.COM
12297387SRobert.Gordon@Sun.COM xdrrdma_create(xdrs, (caddr_t)cl_long_reply->u.c_daddr3,
12307387SRobert.Gordon@Sun.COM cl_rdma_reply->c_len, 0, NULL, XDR_DECODE, conn);
12317387SRobert.Gordon@Sun.COM
12327387SRobert.Gordon@Sun.COM *rxdrp = xdrs;
12337387SRobert.Gordon@Sun.COM }
12347387SRobert.Gordon@Sun.COM }
12357387SRobert.Gordon@Sun.COM
12367387SRobert.Gordon@Sun.COM static void
clnt_return_credit(CONN * conn)12377387SRobert.Gordon@Sun.COM clnt_return_credit(CONN *conn)
12387387SRobert.Gordon@Sun.COM {
12397387SRobert.Gordon@Sun.COM rdma_clnt_cred_ctrl_t *cc_info = &conn->rdma_conn_cred_ctrl_u.c_clnt_cc;
12407387SRobert.Gordon@Sun.COM
12417387SRobert.Gordon@Sun.COM mutex_enter(&conn->c_lock);
12427387SRobert.Gordon@Sun.COM cc_info->clnt_cc_in_flight_ops--;
12437387SRobert.Gordon@Sun.COM cv_signal(&cc_info->clnt_cc_cv);
12447387SRobert.Gordon@Sun.COM mutex_exit(&conn->c_lock);
12457387SRobert.Gordon@Sun.COM }
12467387SRobert.Gordon@Sun.COM
12477387SRobert.Gordon@Sun.COM static void
clnt_update_credit(CONN * conn,uint32_t rdma_credit)12487387SRobert.Gordon@Sun.COM clnt_update_credit(CONN *conn, uint32_t rdma_credit)
12497387SRobert.Gordon@Sun.COM {
12507387SRobert.Gordon@Sun.COM rdma_clnt_cred_ctrl_t *cc_info = &conn->rdma_conn_cred_ctrl_u.c_clnt_cc;
12517387SRobert.Gordon@Sun.COM
12527387SRobert.Gordon@Sun.COM /*
12537387SRobert.Gordon@Sun.COM * If the granted has not altered, avoid taking the
12547387SRobert.Gordon@Sun.COM * mutex, to essentially do nothing..
12557387SRobert.Gordon@Sun.COM */
12567387SRobert.Gordon@Sun.COM if (cc_info->clnt_cc_granted_ops == rdma_credit)
12577387SRobert.Gordon@Sun.COM return;
12587387SRobert.Gordon@Sun.COM /*
12597387SRobert.Gordon@Sun.COM * Get the granted number of buffers for credit control.
12607387SRobert.Gordon@Sun.COM */
12617387SRobert.Gordon@Sun.COM mutex_enter(&conn->c_lock);
12627387SRobert.Gordon@Sun.COM cc_info->clnt_cc_granted_ops = rdma_credit;
12637387SRobert.Gordon@Sun.COM mutex_exit(&conn->c_lock);
12647387SRobert.Gordon@Sun.COM }
12657387SRobert.Gordon@Sun.COM
12667387SRobert.Gordon@Sun.COM static void
clnt_check_credit(CONN * conn)12677387SRobert.Gordon@Sun.COM clnt_check_credit(CONN *conn)
12687387SRobert.Gordon@Sun.COM {
12697387SRobert.Gordon@Sun.COM rdma_clnt_cred_ctrl_t *cc_info = &conn->rdma_conn_cred_ctrl_u.c_clnt_cc;
12707387SRobert.Gordon@Sun.COM
12717387SRobert.Gordon@Sun.COM /*
12727387SRobert.Gordon@Sun.COM * Make sure we are not going over our allowed buffer use
12737387SRobert.Gordon@Sun.COM * (and make sure we have gotten a granted value before).
12747387SRobert.Gordon@Sun.COM */
12757387SRobert.Gordon@Sun.COM mutex_enter(&conn->c_lock);
12767387SRobert.Gordon@Sun.COM while (cc_info->clnt_cc_in_flight_ops >= cc_info->clnt_cc_granted_ops &&
12777387SRobert.Gordon@Sun.COM cc_info->clnt_cc_granted_ops != 0) {
12787387SRobert.Gordon@Sun.COM /*
12797387SRobert.Gordon@Sun.COM * Client has maxed out its granted buffers due to
12807387SRobert.Gordon@Sun.COM * credit control. Current handling is to block and wait.
12817387SRobert.Gordon@Sun.COM */
12827387SRobert.Gordon@Sun.COM cv_wait(&cc_info->clnt_cc_cv, &conn->c_lock);
12837387SRobert.Gordon@Sun.COM }
12847387SRobert.Gordon@Sun.COM cc_info->clnt_cc_in_flight_ops++;
12857387SRobert.Gordon@Sun.COM mutex_exit(&conn->c_lock);
12867387SRobert.Gordon@Sun.COM }
12877387SRobert.Gordon@Sun.COM
12880Sstevel@tonic-gate /* ARGSUSED */
12890Sstevel@tonic-gate static void
clnt_rdma_kabort(CLIENT * h)12900Sstevel@tonic-gate clnt_rdma_kabort(CLIENT *h)
12910Sstevel@tonic-gate {
12920Sstevel@tonic-gate }
12930Sstevel@tonic-gate
12940Sstevel@tonic-gate static void
clnt_rdma_kerror(CLIENT * h,struct rpc_err * err)12950Sstevel@tonic-gate clnt_rdma_kerror(CLIENT *h, struct rpc_err *err)
12960Sstevel@tonic-gate {
12970Sstevel@tonic-gate struct cku_private *p = htop(h);
12980Sstevel@tonic-gate *err = p->cku_err;
12990Sstevel@tonic-gate }
13000Sstevel@tonic-gate
13010Sstevel@tonic-gate static bool_t
clnt_rdma_kfreeres(CLIENT * h,xdrproc_t xdr_res,caddr_t res_ptr)13020Sstevel@tonic-gate clnt_rdma_kfreeres(CLIENT *h, xdrproc_t xdr_res, caddr_t res_ptr)
13030Sstevel@tonic-gate {
13040Sstevel@tonic-gate struct cku_private *p = htop(h);
13050Sstevel@tonic-gate XDR *xdrs;
13060Sstevel@tonic-gate
13070Sstevel@tonic-gate xdrs = &(p->cku_outxdr);
13080Sstevel@tonic-gate xdrs->x_op = XDR_FREE;
13090Sstevel@tonic-gate return ((*xdr_res)(xdrs, res_ptr));
13100Sstevel@tonic-gate }
13110Sstevel@tonic-gate
13120Sstevel@tonic-gate /* ARGSUSED */
13130Sstevel@tonic-gate static bool_t
clnt_rdma_kcontrol(CLIENT * h,int cmd,char * arg)13140Sstevel@tonic-gate clnt_rdma_kcontrol(CLIENT *h, int cmd, char *arg)
13150Sstevel@tonic-gate {
13160Sstevel@tonic-gate return (TRUE);
13170Sstevel@tonic-gate }
13180Sstevel@tonic-gate
13190Sstevel@tonic-gate /* ARGSUSED */
13200Sstevel@tonic-gate static int
clnt_rdma_ksettimers(CLIENT * h,struct rpc_timers * t,struct rpc_timers * all,int minimum,void (* feedback)(int,int,caddr_t),caddr_t arg,uint32_t xid)13210Sstevel@tonic-gate clnt_rdma_ksettimers(CLIENT *h, struct rpc_timers *t, struct rpc_timers *all,
13220Sstevel@tonic-gate int minimum, void(*feedback)(int, int, caddr_t), caddr_t arg,
13230Sstevel@tonic-gate uint32_t xid)
13240Sstevel@tonic-gate {
13250Sstevel@tonic-gate RCSTAT_INCR(rctimers);
13260Sstevel@tonic-gate return (0);
13270Sstevel@tonic-gate }
13280Sstevel@tonic-gate
13290Sstevel@tonic-gate int
rdma_reachable(int addr_type,struct netbuf * addr,struct knetconfig ** knconf)13300Sstevel@tonic-gate rdma_reachable(int addr_type, struct netbuf *addr, struct knetconfig **knconf)
13310Sstevel@tonic-gate {
13320Sstevel@tonic-gate rdma_registry_t *rp;
13330Sstevel@tonic-gate void *handle = NULL;
13340Sstevel@tonic-gate struct knetconfig *knc;
13350Sstevel@tonic-gate char *pf, *p;
13360Sstevel@tonic-gate rdma_stat status;
13370Sstevel@tonic-gate int error = 0;
13380Sstevel@tonic-gate
13390Sstevel@tonic-gate if (!INGLOBALZONE(curproc))
13400Sstevel@tonic-gate return (-1);
13417387SRobert.Gordon@Sun.COM
13420Sstevel@tonic-gate /*
13430Sstevel@tonic-gate * modload the RDMA plugins if not already done.
13440Sstevel@tonic-gate */
13450Sstevel@tonic-gate if (!rdma_modloaded) {
13460Sstevel@tonic-gate mutex_enter(&rdma_modload_lock);
13470Sstevel@tonic-gate if (!rdma_modloaded) {
13480Sstevel@tonic-gate error = rdma_modload();
13490Sstevel@tonic-gate }
13500Sstevel@tonic-gate mutex_exit(&rdma_modload_lock);
13510Sstevel@tonic-gate if (error)
13520Sstevel@tonic-gate return (-1);
13530Sstevel@tonic-gate }
13540Sstevel@tonic-gate
13550Sstevel@tonic-gate if (!rdma_dev_available)
13560Sstevel@tonic-gate return (-1);
13570Sstevel@tonic-gate
13580Sstevel@tonic-gate rw_enter(&rdma_lock, RW_READER);
13590Sstevel@tonic-gate rp = rdma_mod_head;
13600Sstevel@tonic-gate while (rp != NULL) {
13618695SRajkumar.Sivaprakasam@Sun.COM if (rp->r_mod_state == RDMA_MOD_INACTIVE) {
13628695SRajkumar.Sivaprakasam@Sun.COM rp = rp->r_next;
13638695SRajkumar.Sivaprakasam@Sun.COM continue;
13648695SRajkumar.Sivaprakasam@Sun.COM }
13650Sstevel@tonic-gate status = RDMA_REACHABLE(rp->r_mod->rdma_ops, addr_type, addr,
13660Sstevel@tonic-gate &handle);
13670Sstevel@tonic-gate if (status == RDMA_SUCCESS) {
13680Sstevel@tonic-gate knc = kmem_zalloc(sizeof (struct knetconfig),
13697387SRobert.Gordon@Sun.COM KM_SLEEP);
13700Sstevel@tonic-gate knc->knc_semantics = NC_TPI_RDMA;
13710Sstevel@tonic-gate pf = kmem_alloc(KNC_STRSIZE, KM_SLEEP);
13720Sstevel@tonic-gate p = kmem_alloc(KNC_STRSIZE, KM_SLEEP);
13730Sstevel@tonic-gate if (addr_type == AF_INET)
13740Sstevel@tonic-gate (void) strncpy(pf, NC_INET, KNC_STRSIZE);
13750Sstevel@tonic-gate else if (addr_type == AF_INET6)
13760Sstevel@tonic-gate (void) strncpy(pf, NC_INET6, KNC_STRSIZE);
13770Sstevel@tonic-gate pf[KNC_STRSIZE - 1] = '\0';
13780Sstevel@tonic-gate
13790Sstevel@tonic-gate (void) strncpy(p, rp->r_mod->rdma_api, KNC_STRSIZE);
13800Sstevel@tonic-gate p[KNC_STRSIZE - 1] = '\0';
13810Sstevel@tonic-gate
13820Sstevel@tonic-gate knc->knc_protofmly = pf;
13830Sstevel@tonic-gate knc->knc_proto = p;
13848695SRajkumar.Sivaprakasam@Sun.COM knc->knc_rdev = (dev_t)rp;
13850Sstevel@tonic-gate *knconf = knc;
13860Sstevel@tonic-gate rw_exit(&rdma_lock);
13870Sstevel@tonic-gate return (0);
13880Sstevel@tonic-gate }
13890Sstevel@tonic-gate rp = rp->r_next;
13900Sstevel@tonic-gate }
13910Sstevel@tonic-gate rw_exit(&rdma_lock);
13920Sstevel@tonic-gate return (-1);
13930Sstevel@tonic-gate }
1394