1*0Sstevel@tonic-gate /*
2*0Sstevel@tonic-gate  * CDDL HEADER START
3*0Sstevel@tonic-gate  *
4*0Sstevel@tonic-gate  * The contents of this file are subject to the terms of the
5*0Sstevel@tonic-gate  * Common Development and Distribution License, Version 1.0 only
6*0Sstevel@tonic-gate  * (the "License").  You may not use this file except in compliance
7*0Sstevel@tonic-gate  * with the License.
8*0Sstevel@tonic-gate  *
9*0Sstevel@tonic-gate  * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
10*0Sstevel@tonic-gate  * or http://www.opensolaris.org/os/licensing.
11*0Sstevel@tonic-gate  * See the License for the specific language governing permissions
12*0Sstevel@tonic-gate  * and limitations under the License.
13*0Sstevel@tonic-gate  *
14*0Sstevel@tonic-gate  * When distributing Covered Code, include this CDDL HEADER in each
15*0Sstevel@tonic-gate  * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
16*0Sstevel@tonic-gate  * If applicable, add the following below this CDDL HEADER, with the
17*0Sstevel@tonic-gate  * fields enclosed by brackets "[]" replaced with your own identifying
18*0Sstevel@tonic-gate  * information: Portions Copyright [yyyy] [name of copyright owner]
19*0Sstevel@tonic-gate  *
20*0Sstevel@tonic-gate  * CDDL HEADER END
21*0Sstevel@tonic-gate  */
22*0Sstevel@tonic-gate /*
23*0Sstevel@tonic-gate  * Copyright 2004 Sun Microsystems, Inc.  All rights reserved.
24*0Sstevel@tonic-gate  * Use is subject to license terms.
25*0Sstevel@tonic-gate  */
26*0Sstevel@tonic-gate 
27*0Sstevel@tonic-gate #pragma ident	"%Z%%M%	%I%	%E% SMI"
28*0Sstevel@tonic-gate 
29*0Sstevel@tonic-gate /*
30*0Sstevel@tonic-gate  * xdr_rdma.c, XDR implementation using RDMA to move large chunks
31*0Sstevel@tonic-gate  */
32*0Sstevel@tonic-gate 
33*0Sstevel@tonic-gate #include <sys/param.h>
34*0Sstevel@tonic-gate #include <sys/types.h>
35*0Sstevel@tonic-gate #include <sys/systm.h>
36*0Sstevel@tonic-gate #include <sys/kmem.h>
37*0Sstevel@tonic-gate 
38*0Sstevel@tonic-gate #include <rpc/types.h>
39*0Sstevel@tonic-gate #include <rpc/xdr.h>
40*0Sstevel@tonic-gate #include <sys/cmn_err.h>
41*0Sstevel@tonic-gate #include <rpc/rpc_sztypes.h>
42*0Sstevel@tonic-gate #include <rpc/rpc_rdma.h>
43*0Sstevel@tonic-gate 
44*0Sstevel@tonic-gate static struct xdr_ops *xdrrdma_ops(void);
45*0Sstevel@tonic-gate 
46*0Sstevel@tonic-gate /*
47*0Sstevel@tonic-gate  * A chunk list entry identifies a chunk
48*0Sstevel@tonic-gate  * of opaque data to be moved separately
49*0Sstevel@tonic-gate  * from the rest of the RPC message.
50*0Sstevel@tonic-gate  * xp_min_chunk = 0, is a special case for ENCODING, which means
51*0Sstevel@tonic-gate  * do not chunk the incoming stream of data.
52*0Sstevel@tonic-gate  */
53*0Sstevel@tonic-gate 
54*0Sstevel@tonic-gate struct private {
55*0Sstevel@tonic-gate 	caddr_t		xp_offp;
56*0Sstevel@tonic-gate 	int		xp_min_chunk;
57*0Sstevel@tonic-gate 	uint_t		xp_flags;	/* Controls setting for rdma xdr */
58*0Sstevel@tonic-gate 	int		xp_buf_size;		/* size of xdr buffer */
59*0Sstevel@tonic-gate 	struct clist	*xp_cl;			/* head of chunk list */
60*0Sstevel@tonic-gate 	struct clist	**xp_cl_next;	/* location to place/find next chunk */
61*0Sstevel@tonic-gate 	CONN		*xp_conn;	/* connection for chunk data xfer */
62*0Sstevel@tonic-gate };
63*0Sstevel@tonic-gate 
64*0Sstevel@tonic-gate 
65*0Sstevel@tonic-gate /*
66*0Sstevel@tonic-gate  * The procedure xdrrdma_create initializes a stream descriptor for a
67*0Sstevel@tonic-gate  * memory buffer.
68*0Sstevel@tonic-gate  */
69*0Sstevel@tonic-gate void
70*0Sstevel@tonic-gate xdrrdma_create(XDR *xdrs, caddr_t addr, uint_t size,
71*0Sstevel@tonic-gate 	int min_chunk, struct clist *cl, enum xdr_op op, CONN *conn)
72*0Sstevel@tonic-gate {
73*0Sstevel@tonic-gate 	struct private *xdrp;
74*0Sstevel@tonic-gate 	struct clist *cle;
75*0Sstevel@tonic-gate 
76*0Sstevel@tonic-gate 	xdrs->x_op = op;
77*0Sstevel@tonic-gate 	xdrs->x_ops = xdrrdma_ops();
78*0Sstevel@tonic-gate 	xdrs->x_base = addr;
79*0Sstevel@tonic-gate 	xdrs->x_handy = size;
80*0Sstevel@tonic-gate 	xdrs->x_public = NULL;
81*0Sstevel@tonic-gate 
82*0Sstevel@tonic-gate 	xdrp = (struct private *)kmem_zalloc(sizeof (struct private), KM_SLEEP);
83*0Sstevel@tonic-gate 	xdrs->x_private = (caddr_t)xdrp;
84*0Sstevel@tonic-gate 	xdrp->xp_offp = addr;
85*0Sstevel@tonic-gate 	xdrp->xp_min_chunk = min_chunk;
86*0Sstevel@tonic-gate 	xdrp->xp_flags = 0;
87*0Sstevel@tonic-gate 	xdrp->xp_buf_size = size;
88*0Sstevel@tonic-gate 	xdrp->xp_cl = cl;
89*0Sstevel@tonic-gate 	if (op == XDR_ENCODE && cl != NULL) {
90*0Sstevel@tonic-gate 		/* Find last element in chunk list and set xp_cl_next */
91*0Sstevel@tonic-gate 		for (cle = cl; cle->c_next != NULL; cle = cle->c_next);
92*0Sstevel@tonic-gate 		xdrp->xp_cl_next = &(cle->c_next);
93*0Sstevel@tonic-gate 	} else
94*0Sstevel@tonic-gate 		xdrp->xp_cl_next = &(xdrp->xp_cl);
95*0Sstevel@tonic-gate 	xdrp->xp_conn = conn;
96*0Sstevel@tonic-gate 	if (xdrp->xp_min_chunk == 0)
97*0Sstevel@tonic-gate 		xdrp->xp_flags |= RDMA_NOCHUNK;
98*0Sstevel@tonic-gate }
99*0Sstevel@tonic-gate 
100*0Sstevel@tonic-gate /* ARGSUSED */
101*0Sstevel@tonic-gate void
102*0Sstevel@tonic-gate xdrrdma_destroy(XDR *xdrs)
103*0Sstevel@tonic-gate {
104*0Sstevel@tonic-gate 	(void) kmem_free(xdrs->x_private, sizeof (struct private));
105*0Sstevel@tonic-gate }
106*0Sstevel@tonic-gate 
107*0Sstevel@tonic-gate struct clist *
108*0Sstevel@tonic-gate xdrrdma_clist(XDR *xdrs) {
109*0Sstevel@tonic-gate 	return (((struct private *)(xdrs->x_private))->xp_cl);
110*0Sstevel@tonic-gate }
111*0Sstevel@tonic-gate 
112*0Sstevel@tonic-gate static bool_t
113*0Sstevel@tonic-gate xdrrdma_getint32(XDR *xdrs, int32_t *int32p)
114*0Sstevel@tonic-gate {
115*0Sstevel@tonic-gate 	struct private *xdrp = (struct private *)(xdrs->x_private);
116*0Sstevel@tonic-gate 
117*0Sstevel@tonic-gate 	if ((xdrs->x_handy -= (int)sizeof (int32_t)) < 0)
118*0Sstevel@tonic-gate 		return (FALSE);
119*0Sstevel@tonic-gate 
120*0Sstevel@tonic-gate 	/* LINTED pointer alignment */
121*0Sstevel@tonic-gate 	*int32p = (int32_t)ntohl((uint32_t)(*((int32_t *)(xdrp->xp_offp))));
122*0Sstevel@tonic-gate 	xdrp->xp_offp += sizeof (int32_t);
123*0Sstevel@tonic-gate 
124*0Sstevel@tonic-gate 	return (TRUE);
125*0Sstevel@tonic-gate }
126*0Sstevel@tonic-gate 
127*0Sstevel@tonic-gate static bool_t
128*0Sstevel@tonic-gate xdrrdma_putint32(XDR *xdrs, int32_t *int32p)
129*0Sstevel@tonic-gate {
130*0Sstevel@tonic-gate 	struct private *xdrp = (struct private *)(xdrs->x_private);
131*0Sstevel@tonic-gate 
132*0Sstevel@tonic-gate 	if ((xdrs->x_handy -= (int)sizeof (int32_t)) < 0)
133*0Sstevel@tonic-gate 		return (FALSE);
134*0Sstevel@tonic-gate 
135*0Sstevel@tonic-gate 	/* LINTED pointer alignment */
136*0Sstevel@tonic-gate 	*(int32_t *)xdrp->xp_offp = (int32_t)htonl((uint32_t)(*int32p));
137*0Sstevel@tonic-gate 	xdrp->xp_offp += sizeof (int32_t);
138*0Sstevel@tonic-gate 
139*0Sstevel@tonic-gate 	return (TRUE);
140*0Sstevel@tonic-gate }
141*0Sstevel@tonic-gate 
142*0Sstevel@tonic-gate /*
143*0Sstevel@tonic-gate  * DECODE some bytes from an XDR stream
144*0Sstevel@tonic-gate  */
145*0Sstevel@tonic-gate static bool_t
146*0Sstevel@tonic-gate xdrrdma_getbytes(XDR *xdrs, caddr_t addr, int len)
147*0Sstevel@tonic-gate {
148*0Sstevel@tonic-gate 	struct private *xdrp = (struct private *)(xdrs->x_private);
149*0Sstevel@tonic-gate 	struct clist *cle = *(xdrp->xp_cl_next);
150*0Sstevel@tonic-gate 	struct clist cl;
151*0Sstevel@tonic-gate 	bool_t  retval = TRUE;
152*0Sstevel@tonic-gate 
153*0Sstevel@tonic-gate 	/*
154*0Sstevel@tonic-gate 	 * If there was a chunk at the current offset
155*0Sstevel@tonic-gate 	 * first record the destination address and length
156*0Sstevel@tonic-gate 	 * in the chunk list that came with the message, then
157*0Sstevel@tonic-gate 	 * RDMA READ the chunk data.
158*0Sstevel@tonic-gate 	 */
159*0Sstevel@tonic-gate 	if (cle != NULL &&
160*0Sstevel@tonic-gate 		cle->c_xdroff == (xdrp->xp_offp - xdrs->x_base)) {
161*0Sstevel@tonic-gate 		cle->c_daddr = (uint64)(uintptr_t)addr;
162*0Sstevel@tonic-gate 		cle->c_len  = len;
163*0Sstevel@tonic-gate 		xdrp->xp_cl_next = &cle->c_next;
164*0Sstevel@tonic-gate 
165*0Sstevel@tonic-gate 		/*
166*0Sstevel@tonic-gate 		 * RDMA READ the chunk data from the remote end.
167*0Sstevel@tonic-gate 		 * First prep the destination buffer by registering
168*0Sstevel@tonic-gate 		 * it, then RDMA READ the chunk data. Since we are
169*0Sstevel@tonic-gate 		 * doing streaming memory, sync the destination buffer
170*0Sstevel@tonic-gate 		 * to CPU and deregister the buffer.
171*0Sstevel@tonic-gate 		 */
172*0Sstevel@tonic-gate 		if (xdrp->xp_conn == NULL) {
173*0Sstevel@tonic-gate 			return (FALSE);
174*0Sstevel@tonic-gate 		}
175*0Sstevel@tonic-gate 
176*0Sstevel@tonic-gate 		cl = *cle;
177*0Sstevel@tonic-gate 		cl.c_next = NULL;
178*0Sstevel@tonic-gate 		if (clist_register(xdrp->xp_conn, &cl, 0) != RDMA_SUCCESS) {
179*0Sstevel@tonic-gate 			return (FALSE);
180*0Sstevel@tonic-gate 		}
181*0Sstevel@tonic-gate 
182*0Sstevel@tonic-gate 		/*
183*0Sstevel@tonic-gate 		 * Now read the chunk in
184*0Sstevel@tonic-gate 		 */
185*0Sstevel@tonic-gate 		if (RDMA_READ(xdrp->xp_conn, &cl, WAIT) != RDMA_SUCCESS) {
186*0Sstevel@tonic-gate #ifdef DEBUG
187*0Sstevel@tonic-gate 			cmn_err(CE_WARN,
188*0Sstevel@tonic-gate 				"xdrrdma_getbytes: RDMA_READ failed\n");
189*0Sstevel@tonic-gate #endif
190*0Sstevel@tonic-gate 			retval = FALSE;
191*0Sstevel@tonic-gate 			goto out;
192*0Sstevel@tonic-gate 		}
193*0Sstevel@tonic-gate 		/*
194*0Sstevel@tonic-gate 		 * sync the memory for cpu
195*0Sstevel@tonic-gate 		 */
196*0Sstevel@tonic-gate 		if (clist_syncmem(xdrp->xp_conn, &cl, 0) != RDMA_SUCCESS) {
197*0Sstevel@tonic-gate 			retval = FALSE;
198*0Sstevel@tonic-gate 			goto out;
199*0Sstevel@tonic-gate 		}
200*0Sstevel@tonic-gate 
201*0Sstevel@tonic-gate out:
202*0Sstevel@tonic-gate 		/*
203*0Sstevel@tonic-gate 		 * Deregister the chunks
204*0Sstevel@tonic-gate 		 */
205*0Sstevel@tonic-gate 		(void) clist_deregister(xdrp->xp_conn, &cl, 0);
206*0Sstevel@tonic-gate 		return (retval);
207*0Sstevel@tonic-gate 	}
208*0Sstevel@tonic-gate 
209*0Sstevel@tonic-gate 	if ((xdrs->x_handy -= len) < 0)
210*0Sstevel@tonic-gate 		return (FALSE);
211*0Sstevel@tonic-gate 
212*0Sstevel@tonic-gate 	bcopy(xdrp->xp_offp, addr, len);
213*0Sstevel@tonic-gate 	xdrp->xp_offp += len;
214*0Sstevel@tonic-gate 
215*0Sstevel@tonic-gate 	return (TRUE);
216*0Sstevel@tonic-gate }
217*0Sstevel@tonic-gate 
218*0Sstevel@tonic-gate /*
219*0Sstevel@tonic-gate  * ENCODE some bytes into an XDR stream
220*0Sstevel@tonic-gate  * xp_min_chunk = 0, means the stream of bytes contain no chunks
221*0Sstevel@tonic-gate  * to seperate out, and if the bytes do not fit in the supplied
222*0Sstevel@tonic-gate  * buffer, grow the buffer and free the old buffer.
223*0Sstevel@tonic-gate  */
224*0Sstevel@tonic-gate static bool_t
225*0Sstevel@tonic-gate xdrrdma_putbytes(XDR *xdrs, caddr_t addr, int len)
226*0Sstevel@tonic-gate {
227*0Sstevel@tonic-gate 	struct private *xdrp = (struct private *)(xdrs->x_private);
228*0Sstevel@tonic-gate 	struct clist *clzero = xdrp->xp_cl;
229*0Sstevel@tonic-gate 
230*0Sstevel@tonic-gate 	/*
231*0Sstevel@tonic-gate 	 * If this chunk meets the minimum chunk size
232*0Sstevel@tonic-gate 	 * then don't encode it.  Just record its address
233*0Sstevel@tonic-gate 	 * and length in a chunk list entry so that it
234*0Sstevel@tonic-gate 	 * can be moved separately via RDMA.
235*0Sstevel@tonic-gate 	 */
236*0Sstevel@tonic-gate 	if (!(xdrp->xp_flags & RDMA_NOCHUNK) && xdrp->xp_min_chunk != 0 &&
237*0Sstevel@tonic-gate 	    len >= xdrp->xp_min_chunk) {
238*0Sstevel@tonic-gate 		struct clist *cle;
239*0Sstevel@tonic-gate 		int offset = xdrp->xp_offp - xdrs->x_base;
240*0Sstevel@tonic-gate 
241*0Sstevel@tonic-gate 		cle = (struct clist *)kmem_zalloc(sizeof (struct clist),
242*0Sstevel@tonic-gate 				KM_SLEEP);
243*0Sstevel@tonic-gate 		cle->c_xdroff = offset;
244*0Sstevel@tonic-gate 		cle->c_len  = len;
245*0Sstevel@tonic-gate 		cle->c_saddr = (uint64)(uintptr_t)addr;
246*0Sstevel@tonic-gate 		cle->c_next = NULL;
247*0Sstevel@tonic-gate 
248*0Sstevel@tonic-gate 		*(xdrp->xp_cl_next) = cle;
249*0Sstevel@tonic-gate 		xdrp->xp_cl_next = &(cle->c_next);
250*0Sstevel@tonic-gate 
251*0Sstevel@tonic-gate 		return (TRUE);
252*0Sstevel@tonic-gate 	}
253*0Sstevel@tonic-gate 
254*0Sstevel@tonic-gate 	if ((xdrs->x_handy -= len) < 0) {
255*0Sstevel@tonic-gate 		if (xdrp->xp_min_chunk == 0) {
256*0Sstevel@tonic-gate 			int  newbuflen, encodelen;
257*0Sstevel@tonic-gate 			caddr_t newbuf;
258*0Sstevel@tonic-gate 
259*0Sstevel@tonic-gate 			xdrs->x_handy += len;
260*0Sstevel@tonic-gate 			encodelen = xdrp->xp_offp - xdrs->x_base;
261*0Sstevel@tonic-gate 			newbuflen = xdrp->xp_buf_size + len;
262*0Sstevel@tonic-gate 			newbuf = kmem_zalloc(newbuflen, KM_SLEEP);
263*0Sstevel@tonic-gate 			bcopy(xdrs->x_base, newbuf, encodelen);
264*0Sstevel@tonic-gate 			(void) kmem_free(xdrs->x_base, xdrp->xp_buf_size);
265*0Sstevel@tonic-gate 			xdrs->x_base = newbuf;
266*0Sstevel@tonic-gate 			xdrp->xp_offp = newbuf + encodelen;
267*0Sstevel@tonic-gate 			xdrp->xp_buf_size = newbuflen;
268*0Sstevel@tonic-gate 			if (xdrp->xp_min_chunk == 0 && clzero->c_xdroff == 0) {
269*0Sstevel@tonic-gate 				clzero->c_len = newbuflen;
270*0Sstevel@tonic-gate 				clzero->c_saddr = (uint64)(uintptr_t)newbuf;
271*0Sstevel@tonic-gate 			}
272*0Sstevel@tonic-gate 		} else
273*0Sstevel@tonic-gate 			return (FALSE);
274*0Sstevel@tonic-gate 	}
275*0Sstevel@tonic-gate 
276*0Sstevel@tonic-gate 	bcopy(addr, xdrp->xp_offp, len);
277*0Sstevel@tonic-gate 	xdrp->xp_offp += len;
278*0Sstevel@tonic-gate 
279*0Sstevel@tonic-gate 	return (TRUE);
280*0Sstevel@tonic-gate }
281*0Sstevel@tonic-gate 
282*0Sstevel@tonic-gate uint_t
283*0Sstevel@tonic-gate xdrrdma_getpos(XDR *xdrs)
284*0Sstevel@tonic-gate {
285*0Sstevel@tonic-gate 	struct private *xdrp = (struct private *)(xdrs->x_private);
286*0Sstevel@tonic-gate 
287*0Sstevel@tonic-gate 	return ((uint_t)((uintptr_t)xdrp->xp_offp - (uintptr_t)xdrs->x_base));
288*0Sstevel@tonic-gate }
289*0Sstevel@tonic-gate 
290*0Sstevel@tonic-gate bool_t
291*0Sstevel@tonic-gate xdrrdma_setpos(XDR *xdrs, uint_t pos)
292*0Sstevel@tonic-gate {
293*0Sstevel@tonic-gate 	struct private *xdrp = (struct private *)(xdrs->x_private);
294*0Sstevel@tonic-gate 
295*0Sstevel@tonic-gate 	caddr_t newaddr = xdrs->x_base + pos;
296*0Sstevel@tonic-gate 	caddr_t lastaddr = xdrp->xp_offp + xdrs->x_handy;
297*0Sstevel@tonic-gate 	ptrdiff_t diff;
298*0Sstevel@tonic-gate 
299*0Sstevel@tonic-gate 	if (newaddr > lastaddr)
300*0Sstevel@tonic-gate 		return (FALSE);
301*0Sstevel@tonic-gate 
302*0Sstevel@tonic-gate 	xdrp->xp_offp = newaddr;
303*0Sstevel@tonic-gate 	diff = lastaddr - newaddr;
304*0Sstevel@tonic-gate 	xdrs->x_handy = (int)diff;
305*0Sstevel@tonic-gate 
306*0Sstevel@tonic-gate 	return (TRUE);
307*0Sstevel@tonic-gate }
308*0Sstevel@tonic-gate 
309*0Sstevel@tonic-gate /* ARGSUSED */
310*0Sstevel@tonic-gate static rpc_inline_t *
311*0Sstevel@tonic-gate xdrrdma_inline(XDR *xdrs, int len)
312*0Sstevel@tonic-gate {
313*0Sstevel@tonic-gate 	rpc_inline_t *buf = NULL;
314*0Sstevel@tonic-gate 	struct private *xdrp = (struct private *)(xdrs->x_private);
315*0Sstevel@tonic-gate 	struct clist *cle = *(xdrp->xp_cl_next);
316*0Sstevel@tonic-gate 
317*0Sstevel@tonic-gate 	if (xdrs->x_op == XDR_DECODE) {
318*0Sstevel@tonic-gate 		/*
319*0Sstevel@tonic-gate 		 * Since chunks aren't in-line, check to see whether
320*0Sstevel@tonic-gate 		 * there is a chunk in the inline range.
321*0Sstevel@tonic-gate 		 */
322*0Sstevel@tonic-gate 		if (cle != NULL &&
323*0Sstevel@tonic-gate 			cle->c_xdroff <= (xdrp->xp_offp - xdrs->x_base + len))
324*0Sstevel@tonic-gate 		return (NULL);
325*0Sstevel@tonic-gate 	}
326*0Sstevel@tonic-gate 
327*0Sstevel@tonic-gate 	if ((xdrs->x_handy < len) || (xdrp->xp_min_chunk != 0 &&
328*0Sstevel@tonic-gate 	    len >= xdrp->xp_min_chunk)) {
329*0Sstevel@tonic-gate 		return (NULL);
330*0Sstevel@tonic-gate 	} else {
331*0Sstevel@tonic-gate 		xdrs->x_handy -= len;
332*0Sstevel@tonic-gate 		/* LINTED pointer alignment */
333*0Sstevel@tonic-gate 		buf = (rpc_inline_t *)xdrp->xp_offp;
334*0Sstevel@tonic-gate 		xdrp->xp_offp += len;
335*0Sstevel@tonic-gate 		return (buf);
336*0Sstevel@tonic-gate 	}
337*0Sstevel@tonic-gate }
338*0Sstevel@tonic-gate 
339*0Sstevel@tonic-gate static bool_t
340*0Sstevel@tonic-gate xdrrdma_control(XDR *xdrs, int request, void *info)
341*0Sstevel@tonic-gate {
342*0Sstevel@tonic-gate 	int32_t *int32p;
343*0Sstevel@tonic-gate 	int len;
344*0Sstevel@tonic-gate 	uint_t in_flags;
345*0Sstevel@tonic-gate 	struct private *xdrp = (struct private *)(xdrs->x_private);
346*0Sstevel@tonic-gate 
347*0Sstevel@tonic-gate 	switch (request) {
348*0Sstevel@tonic-gate 	case XDR_PEEK:
349*0Sstevel@tonic-gate 		/*
350*0Sstevel@tonic-gate 		 * Return the next 4 byte unit in the XDR stream.
351*0Sstevel@tonic-gate 		 */
352*0Sstevel@tonic-gate 		if (xdrs->x_handy < sizeof (int32_t))
353*0Sstevel@tonic-gate 			return (FALSE);
354*0Sstevel@tonic-gate 
355*0Sstevel@tonic-gate 		int32p = (int32_t *)info;
356*0Sstevel@tonic-gate 		*int32p = (int32_t)ntohl((uint32_t)
357*0Sstevel@tonic-gate 		    (*((int32_t *)(xdrp->xp_offp))));
358*0Sstevel@tonic-gate 
359*0Sstevel@tonic-gate 		return (TRUE);
360*0Sstevel@tonic-gate 
361*0Sstevel@tonic-gate 	case XDR_SKIPBYTES:
362*0Sstevel@tonic-gate 		/*
363*0Sstevel@tonic-gate 		 * Skip the next N bytes in the XDR stream.
364*0Sstevel@tonic-gate 		 */
365*0Sstevel@tonic-gate 		int32p = (int32_t *)info;
366*0Sstevel@tonic-gate 		len = RNDUP((int)(*int32p));
367*0Sstevel@tonic-gate 		if ((xdrs->x_handy -= len) < 0)
368*0Sstevel@tonic-gate 			return (FALSE);
369*0Sstevel@tonic-gate 		xdrp->xp_offp += len;
370*0Sstevel@tonic-gate 
371*0Sstevel@tonic-gate 		return (TRUE);
372*0Sstevel@tonic-gate 
373*0Sstevel@tonic-gate 	case XDR_RDMASET:
374*0Sstevel@tonic-gate 		/*
375*0Sstevel@tonic-gate 		 * Set the flags provided in the *info in xp_flags for rdma xdr
376*0Sstevel@tonic-gate 		 * stream control.
377*0Sstevel@tonic-gate 		 */
378*0Sstevel@tonic-gate 		int32p = (int32_t *)info;
379*0Sstevel@tonic-gate 		in_flags = (uint_t)(*int32p);
380*0Sstevel@tonic-gate 
381*0Sstevel@tonic-gate 		xdrp->xp_flags |= in_flags;
382*0Sstevel@tonic-gate 		return (TRUE);
383*0Sstevel@tonic-gate 
384*0Sstevel@tonic-gate 	case XDR_RDMAGET:
385*0Sstevel@tonic-gate 		/*
386*0Sstevel@tonic-gate 		 * Get the flags provided in xp_flags return through *info
387*0Sstevel@tonic-gate 		 */
388*0Sstevel@tonic-gate 		int32p = (int32_t *)info;
389*0Sstevel@tonic-gate 
390*0Sstevel@tonic-gate 		*int32p = (int32_t)xdrp->xp_flags;
391*0Sstevel@tonic-gate 		return (TRUE);
392*0Sstevel@tonic-gate 
393*0Sstevel@tonic-gate 	default:
394*0Sstevel@tonic-gate 		return (FALSE);
395*0Sstevel@tonic-gate 	}
396*0Sstevel@tonic-gate }
397*0Sstevel@tonic-gate 
398*0Sstevel@tonic-gate static struct xdr_ops *
399*0Sstevel@tonic-gate xdrrdma_ops(void)
400*0Sstevel@tonic-gate {
401*0Sstevel@tonic-gate 	static struct xdr_ops ops;
402*0Sstevel@tonic-gate 
403*0Sstevel@tonic-gate 	if (ops.x_getint32 == NULL) {
404*0Sstevel@tonic-gate 		ops.x_getbytes = xdrrdma_getbytes;
405*0Sstevel@tonic-gate 		ops.x_putbytes = xdrrdma_putbytes;
406*0Sstevel@tonic-gate 		ops.x_getpostn = xdrrdma_getpos;
407*0Sstevel@tonic-gate 		ops.x_setpostn = xdrrdma_setpos;
408*0Sstevel@tonic-gate 		ops.x_inline = xdrrdma_inline;
409*0Sstevel@tonic-gate 		ops.x_destroy = xdrrdma_destroy;
410*0Sstevel@tonic-gate 		ops.x_control = xdrrdma_control;
411*0Sstevel@tonic-gate 		ops.x_getint32 = xdrrdma_getint32;
412*0Sstevel@tonic-gate 		ops.x_putint32 = xdrrdma_putint32;
413*0Sstevel@tonic-gate 	}
414*0Sstevel@tonic-gate 	return (&ops);
415*0Sstevel@tonic-gate }
416*0Sstevel@tonic-gate 
417*0Sstevel@tonic-gate /*
418*0Sstevel@tonic-gate  * Not all fields in struct clist are interesting to the
419*0Sstevel@tonic-gate  * RPC over RDMA protocol. Only XDR the interesting fields.
420*0Sstevel@tonic-gate  */
421*0Sstevel@tonic-gate bool_t
422*0Sstevel@tonic-gate xdr_clist(XDR *xdrs, clist *objp)
423*0Sstevel@tonic-gate {
424*0Sstevel@tonic-gate 
425*0Sstevel@tonic-gate 	if (!xdr_uint32(xdrs, &objp->c_xdroff))
426*0Sstevel@tonic-gate 		return (FALSE);
427*0Sstevel@tonic-gate 	if (!xdr_uint32(xdrs, &objp->c_len))
428*0Sstevel@tonic-gate 		return (FALSE);
429*0Sstevel@tonic-gate 	if (!xdr_uint32(xdrs, &objp->c_smemhandle.mrc_rmr))
430*0Sstevel@tonic-gate 		return (FALSE);
431*0Sstevel@tonic-gate 	if (!xdr_uint64(xdrs, &objp->c_saddr))
432*0Sstevel@tonic-gate 		return (FALSE);
433*0Sstevel@tonic-gate 	if (!xdr_pointer(xdrs, (char **)&objp->c_next, sizeof (clist),
434*0Sstevel@tonic-gate 		(xdrproc_t)xdr_clist))
435*0Sstevel@tonic-gate 		return (FALSE);
436*0Sstevel@tonic-gate 	return (TRUE);
437*0Sstevel@tonic-gate }
438*0Sstevel@tonic-gate 
439*0Sstevel@tonic-gate bool_t
440*0Sstevel@tonic-gate xdr_do_clist(XDR *xdrs, clist **clp)
441*0Sstevel@tonic-gate {
442*0Sstevel@tonic-gate 	return (xdr_pointer(xdrs, (char **)clp,
443*0Sstevel@tonic-gate 		sizeof (clist), (xdrproc_t)xdr_clist));
444*0Sstevel@tonic-gate }
445*0Sstevel@tonic-gate 
446*0Sstevel@tonic-gate uint_t
447*0Sstevel@tonic-gate xdr_getbufsize(XDR *xdrs)
448*0Sstevel@tonic-gate {
449*0Sstevel@tonic-gate 	struct private *xdrp = (struct private *)(xdrs->x_private);
450*0Sstevel@tonic-gate 
451*0Sstevel@tonic-gate 	return ((uint_t)xdrp->xp_buf_size);
452*0Sstevel@tonic-gate }
453