xref: /illumos-gate/usr/src/uts/common/io/ib/clients/rds/rds_opt.c (revision a69cdccdf9a647a09c204a49f998caff672138e5)
1b86efd96Sagiri /*
2b86efd96Sagiri  * CDDL HEADER START
3b86efd96Sagiri  *
4b86efd96Sagiri  * The contents of this file are subject to the terms of the
5b86efd96Sagiri  * Common Development and Distribution License (the "License").
6b86efd96Sagiri  * You may not use this file except in compliance with the License.
7b86efd96Sagiri  *
8b86efd96Sagiri  * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
9b86efd96Sagiri  * or http://www.opensolaris.org/os/licensing.
10b86efd96Sagiri  * See the License for the specific language governing permissions
11b86efd96Sagiri  * and limitations under the License.
12b86efd96Sagiri  *
13b86efd96Sagiri  * When distributing Covered Code, include this CDDL HEADER in each
14b86efd96Sagiri  * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
15b86efd96Sagiri  * If applicable, add the following below this CDDL HEADER, with the
16b86efd96Sagiri  * fields enclosed by brackets "[]" replaced with your own identifying
17b86efd96Sagiri  * information: Portions Copyright [yyyy] [name of copyright owner]
18b86efd96Sagiri  *
19b86efd96Sagiri  * CDDL HEADER END
20b86efd96Sagiri  */
21b86efd96Sagiri /*
22*a69cdccdSRavi Chandra Nallan  * Copyright (c) 1991, 2010, Oracle and/or its affiliates. All rights reserved.
23*a69cdccdSRavi Chandra Nallan  * Copyright (c) 1990 Mentat Inc.
24b86efd96Sagiri  */
25b86efd96Sagiri 
26b86efd96Sagiri #include <sys/ib/clients/rds/rds.h>
270f1702c5SYu Xiangning #include <inet/proto_set.h>
28b86efd96Sagiri 
29b86efd96Sagiri #define	rds_max_buf 2097152
30b86efd96Sagiri opdes_t rds_opt_arr[] = {
31b86efd96Sagiri 
32bd670b35SErik Nordmark { SO_TYPE,	SOL_SOCKET, OA_R, OA_R, OP_NP, 0, sizeof (int), 0 },
33bd670b35SErik Nordmark { SO_SNDBUF,	SOL_SOCKET, OA_RW, OA_RW, OP_NP, 0, sizeof (int), 0 },
34bd670b35SErik Nordmark { SO_RCVBUF,	SOL_SOCKET, OA_RW, OA_RW, OP_NP, 0, sizeof (int), 0 },
35b86efd96Sagiri };
36b86efd96Sagiri 
37b86efd96Sagiri /* ARGSUSED */
38b86efd96Sagiri int
rds_opt_default(queue_t * q,t_scalar_t level,t_scalar_t name,uchar_t * ptr)39b86efd96Sagiri rds_opt_default(queue_t *q, t_scalar_t level, t_scalar_t name, uchar_t *ptr)
40b86efd96Sagiri {
41b86efd96Sagiri 	/* no default value processed by protocol specific code currently */
42b86efd96Sagiri 	return (-1);
43b86efd96Sagiri }
44b86efd96Sagiri 
45b86efd96Sagiri /*
46b86efd96Sagiri  * This routine retrieves the current status of socket options.
47b86efd96Sagiri  * It returns the size of the option retrieved.
48b86efd96Sagiri  */
49b86efd96Sagiri int
rds_opt_get(queue_t * q,t_scalar_t level,t_scalar_t name,uchar_t * ptr)50b86efd96Sagiri rds_opt_get(queue_t *q, t_scalar_t level, t_scalar_t name, uchar_t *ptr)
51b86efd96Sagiri {
52b86efd96Sagiri 	int	*i1 = (int *)(uintptr_t)ptr;
53b86efd96Sagiri 
54b86efd96Sagiri 	switch (level) {
55b86efd96Sagiri 	case SOL_SOCKET:
56b86efd96Sagiri 		switch (name) {
57b86efd96Sagiri 		case SO_TYPE:
58b86efd96Sagiri 			*i1 = SOCK_DGRAM;
59b86efd96Sagiri 			break;	/* goto sizeof (int) option return */
60b86efd96Sagiri 
61b86efd96Sagiri 		case SO_SNDBUF:
62b86efd96Sagiri 			*i1 = q->q_hiwat;
63b86efd96Sagiri 			break;	/* goto sizeof (int) option return */
64b86efd96Sagiri 		case SO_RCVBUF:
65b86efd96Sagiri 			*i1 = RD(q)->q_hiwat;
66b86efd96Sagiri 			break;	/* goto sizeof (int) option return */
67b86efd96Sagiri 		default:
68b86efd96Sagiri 			return (-1);
69b86efd96Sagiri 		}
70b86efd96Sagiri 		break;
71b86efd96Sagiri 	default:
72b86efd96Sagiri 		return (-1);
73b86efd96Sagiri 	}
74b86efd96Sagiri 	return (sizeof (int));
75b86efd96Sagiri }
76b86efd96Sagiri 
77b86efd96Sagiri /* This routine sets socket options. */
78b86efd96Sagiri /* ARGSUSED */
79b86efd96Sagiri int
rds_opt_set(queue_t * q,uint_t optset_context,int level,int name,uint_t inlen,uchar_t * invalp,uint_t * outlenp,uchar_t * outvalp,void * thisdg_attrs,cred_t * cr)80b86efd96Sagiri rds_opt_set(queue_t *q, uint_t optset_context, int level,
81b86efd96Sagiri     int name, uint_t inlen, uchar_t *invalp, uint_t *outlenp,
82bd670b35SErik Nordmark     uchar_t *outvalp, void *thisdg_attrs, cred_t *cr)
83b86efd96Sagiri {
84b86efd96Sagiri 	int	*i1 = (int *)(uintptr_t)invalp;
85b86efd96Sagiri 	boolean_t checkonly;
86b86efd96Sagiri 
87b86efd96Sagiri 	switch (optset_context) {
88b86efd96Sagiri 	case SETFN_OPTCOM_CHECKONLY:
89b86efd96Sagiri 		checkonly = B_TRUE;
90b86efd96Sagiri 		/*
91b86efd96Sagiri 		 * Note: Implies T_CHECK semantics for T_OPTCOM_REQ
92b86efd96Sagiri 		 * inlen != 0 implies value supplied and
93b86efd96Sagiri 		 * 	we have to "pretend" to set it.
94b86efd96Sagiri 		 * inlen == 0 implies that there is no
95b86efd96Sagiri 		 * 	value part in T_CHECK request and just validation
96b86efd96Sagiri 		 * done elsewhere should be enough, we just return here.
97b86efd96Sagiri 		 */
98b86efd96Sagiri 		if (inlen == 0) {
99b86efd96Sagiri 			*outlenp = 0;
100b86efd96Sagiri 			return (0);
101b86efd96Sagiri 		}
102b86efd96Sagiri 		break;
103b86efd96Sagiri 	case SETFN_OPTCOM_NEGOTIATE:
104b86efd96Sagiri 		checkonly = B_FALSE;
105b86efd96Sagiri 		break;
106b86efd96Sagiri 	default:
107b86efd96Sagiri 		/*
108b86efd96Sagiri 		 * We should never get here
109b86efd96Sagiri 		 */
110b86efd96Sagiri 		*outlenp = 0;
111b86efd96Sagiri 		return (EINVAL);
112b86efd96Sagiri 	}
113b86efd96Sagiri 
114b86efd96Sagiri 	ASSERT((optset_context != SETFN_OPTCOM_CHECKONLY) ||
115b86efd96Sagiri 	    (optset_context == SETFN_OPTCOM_CHECKONLY && inlen != 0));
116b86efd96Sagiri 
117b86efd96Sagiri 	/*
118b86efd96Sagiri 	 * For fixed length options, no sanity check
119b86efd96Sagiri 	 * of passed in length is done. It is assumed *_optcom_req()
120b86efd96Sagiri 	 * routines do the right thing.
121b86efd96Sagiri 	 */
122b86efd96Sagiri 
123b86efd96Sagiri 	switch (level) {
124b86efd96Sagiri 	case SOL_SOCKET:
125b86efd96Sagiri 		switch (name) {
126b86efd96Sagiri 
127b86efd96Sagiri 		case SO_SNDBUF:
128b86efd96Sagiri 			if (*i1 > rds_max_buf) {
129b86efd96Sagiri 				*outlenp = 0;
130b86efd96Sagiri 				return (ENOBUFS);
131b86efd96Sagiri 			}
132b86efd96Sagiri 			if (!checkonly) {
133b86efd96Sagiri 				q->q_hiwat = *i1;
134b86efd96Sagiri 			}
135b86efd96Sagiri 			break;
136b86efd96Sagiri 		case SO_RCVBUF:
137b86efd96Sagiri 			if (*i1 > rds_max_buf) {
138b86efd96Sagiri 				*outlenp = 0;
139b86efd96Sagiri 				return (ENOBUFS);
140b86efd96Sagiri 			}
141b86efd96Sagiri 			if (!checkonly) {
142b86efd96Sagiri 				RD(q)->q_hiwat = *i1;
1430f1702c5SYu Xiangning 				(void) proto_set_rx_hiwat(RD(q), NULL, *i1);
144b86efd96Sagiri 			}
145b86efd96Sagiri 			break;
146b86efd96Sagiri 		default:
147b86efd96Sagiri 			*outlenp = 0;
148b86efd96Sagiri 			return (EINVAL);
149b86efd96Sagiri 		}
150b86efd96Sagiri 		break;
151b86efd96Sagiri 	default:
152b86efd96Sagiri 		*outlenp = 0;
153b86efd96Sagiri 		return (EINVAL);
154b86efd96Sagiri 	}
155b86efd96Sagiri 	/*
156b86efd96Sagiri 	 * Common case of OK return with outval same as inval.
157b86efd96Sagiri 	 */
158b86efd96Sagiri 	if (invalp != outvalp) {
159b86efd96Sagiri 		/* don't trust bcopy for identical src/dst */
160b86efd96Sagiri 		(void) bcopy(invalp, outvalp, inlen);
161b86efd96Sagiri 	}
162b86efd96Sagiri 	*outlenp = inlen;
163b86efd96Sagiri 	return (0);
164b86efd96Sagiri }
165b86efd96Sagiri 
166b86efd96Sagiri uint_t rds_max_optsize; /* initialized when RDS driver is loaded */
167b86efd96Sagiri 
168b86efd96Sagiri #define	RDS_VALID_LEVELS_CNT	A_CNT(rds_valid_levels_arr)
169b86efd96Sagiri 
170b86efd96Sagiri #define	RDS_OPT_ARR_CNT		A_CNT(rds_opt_arr)
171b86efd96Sagiri 
172b86efd96Sagiri 
173b86efd96Sagiri optlevel_t rds_valid_levels_arr[] = {
174b86efd96Sagiri 	SOL_SOCKET,
175b86efd96Sagiri };
176b86efd96Sagiri 
177b86efd96Sagiri /*
178b86efd96Sagiri  * Initialize option database object for RDS
179b86efd96Sagiri  *
180b86efd96Sagiri  * This object represents database of options to search passed to
181b86efd96Sagiri  * {sock,tpi}optcom_req() interface routine to take care of option
182b86efd96Sagiri  * management and associated methods.
183b86efd96Sagiri  */
184b86efd96Sagiri 
185b86efd96Sagiri optdb_obj_t rds_opt_obj = {
186b86efd96Sagiri 	rds_opt_default,	/* RDS default value function pointer */
187b86efd96Sagiri 	rds_opt_get,		/* RDS get function pointer */
188b86efd96Sagiri 	rds_opt_set,		/* RDS set function pointer */
189b86efd96Sagiri 	RDS_OPT_ARR_CNT,	/* RDS option database count of entries */
190b86efd96Sagiri 	rds_opt_arr,		/* RDS option database */
191b86efd96Sagiri 	RDS_VALID_LEVELS_CNT,	/* RDS valid level count of entries */
192b86efd96Sagiri 	rds_valid_levels_arr	/* RDS valid level array */
193b86efd96Sagiri };
194