xref: /onnv-gate/usr/src/uts/common/io/ib/clients/rds/rds_opt.c (revision 12599:e591a2c08558)
13302Sagiri /*
23302Sagiri  * CDDL HEADER START
33302Sagiri  *
43302Sagiri  * The contents of this file are subject to the terms of the
53302Sagiri  * Common Development and Distribution License (the "License").
63302Sagiri  * You may not use this file except in compliance with the License.
73302Sagiri  *
83302Sagiri  * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
93302Sagiri  * or http://www.opensolaris.org/os/licensing.
103302Sagiri  * See the License for the specific language governing permissions
113302Sagiri  * and limitations under the License.
123302Sagiri  *
133302Sagiri  * When distributing Covered Code, include this CDDL HEADER in each
143302Sagiri  * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
153302Sagiri  * If applicable, add the following below this CDDL HEADER, with the
163302Sagiri  * fields enclosed by brackets "[]" replaced with your own identifying
173302Sagiri  * information: Portions Copyright [yyyy] [name of copyright owner]
183302Sagiri  *
193302Sagiri  * CDDL HEADER END
203302Sagiri  */
213302Sagiri /*
22*12599SRavichandra.Nallan@Sun.COM  * Copyright (c) 1991, 2010, Oracle and/or its affiliates. All rights reserved.
23*12599SRavichandra.Nallan@Sun.COM  * Copyright (c) 1990 Mentat Inc.
243302Sagiri  */
253302Sagiri 
263302Sagiri #include <sys/ib/clients/rds/rds.h>
278348SEric.Yu@Sun.COM #include <inet/proto_set.h>
283302Sagiri 
293302Sagiri #define	rds_max_buf 2097152
303302Sagiri opdes_t rds_opt_arr[] = {
313302Sagiri 
3211042SErik.Nordmark@Sun.COM { SO_TYPE,	SOL_SOCKET, OA_R, OA_R, OP_NP, 0, sizeof (int), 0 },
3311042SErik.Nordmark@Sun.COM { SO_SNDBUF,	SOL_SOCKET, OA_RW, OA_RW, OP_NP, 0, sizeof (int), 0 },
3411042SErik.Nordmark@Sun.COM { SO_RCVBUF,	SOL_SOCKET, OA_RW, OA_RW, OP_NP, 0, sizeof (int), 0 },
353302Sagiri };
363302Sagiri 
373302Sagiri /* ARGSUSED */
383302Sagiri int
rds_opt_default(queue_t * q,t_scalar_t level,t_scalar_t name,uchar_t * ptr)393302Sagiri rds_opt_default(queue_t *q, t_scalar_t level, t_scalar_t name, uchar_t *ptr)
403302Sagiri {
413302Sagiri 	/* no default value processed by protocol specific code currently */
423302Sagiri 	return (-1);
433302Sagiri }
443302Sagiri 
453302Sagiri /*
463302Sagiri  * This routine retrieves the current status of socket options.
473302Sagiri  * It returns the size of the option retrieved.
483302Sagiri  */
493302Sagiri int
rds_opt_get(queue_t * q,t_scalar_t level,t_scalar_t name,uchar_t * ptr)503302Sagiri rds_opt_get(queue_t *q, t_scalar_t level, t_scalar_t name, uchar_t *ptr)
513302Sagiri {
523302Sagiri 	int	*i1 = (int *)(uintptr_t)ptr;
533302Sagiri 
543302Sagiri 	switch (level) {
553302Sagiri 	case SOL_SOCKET:
563302Sagiri 		switch (name) {
573302Sagiri 		case SO_TYPE:
583302Sagiri 			*i1 = SOCK_DGRAM;
593302Sagiri 			break;	/* goto sizeof (int) option return */
603302Sagiri 
613302Sagiri 		case SO_SNDBUF:
623302Sagiri 			*i1 = q->q_hiwat;
633302Sagiri 			break;	/* goto sizeof (int) option return */
643302Sagiri 		case SO_RCVBUF:
653302Sagiri 			*i1 = RD(q)->q_hiwat;
663302Sagiri 			break;	/* goto sizeof (int) option return */
673302Sagiri 		default:
683302Sagiri 			return (-1);
693302Sagiri 		}
703302Sagiri 		break;
713302Sagiri 	default:
723302Sagiri 		return (-1);
733302Sagiri 	}
743302Sagiri 	return (sizeof (int));
753302Sagiri }
763302Sagiri 
773302Sagiri /* This routine sets socket options. */
783302Sagiri /* ARGSUSED */
793302Sagiri 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)803302Sagiri rds_opt_set(queue_t *q, uint_t optset_context, int level,
813302Sagiri     int name, uint_t inlen, uchar_t *invalp, uint_t *outlenp,
8211042SErik.Nordmark@Sun.COM     uchar_t *outvalp, void *thisdg_attrs, cred_t *cr)
833302Sagiri {
843302Sagiri 	int	*i1 = (int *)(uintptr_t)invalp;
853302Sagiri 	boolean_t checkonly;
863302Sagiri 
873302Sagiri 	switch (optset_context) {
883302Sagiri 	case SETFN_OPTCOM_CHECKONLY:
893302Sagiri 		checkonly = B_TRUE;
903302Sagiri 		/*
913302Sagiri 		 * Note: Implies T_CHECK semantics for T_OPTCOM_REQ
923302Sagiri 		 * inlen != 0 implies value supplied and
933302Sagiri 		 * 	we have to "pretend" to set it.
943302Sagiri 		 * inlen == 0 implies that there is no
953302Sagiri 		 * 	value part in T_CHECK request and just validation
963302Sagiri 		 * done elsewhere should be enough, we just return here.
973302Sagiri 		 */
983302Sagiri 		if (inlen == 0) {
993302Sagiri 			*outlenp = 0;
1003302Sagiri 			return (0);
1013302Sagiri 		}
1023302Sagiri 		break;
1033302Sagiri 	case SETFN_OPTCOM_NEGOTIATE:
1043302Sagiri 		checkonly = B_FALSE;
1053302Sagiri 		break;
1063302Sagiri 	default:
1073302Sagiri 		/*
1083302Sagiri 		 * We should never get here
1093302Sagiri 		 */
1103302Sagiri 		*outlenp = 0;
1113302Sagiri 		return (EINVAL);
1123302Sagiri 	}
1133302Sagiri 
1143302Sagiri 	ASSERT((optset_context != SETFN_OPTCOM_CHECKONLY) ||
1153302Sagiri 	    (optset_context == SETFN_OPTCOM_CHECKONLY && inlen != 0));
1163302Sagiri 
1173302Sagiri 	/*
1183302Sagiri 	 * For fixed length options, no sanity check
1193302Sagiri 	 * of passed in length is done. It is assumed *_optcom_req()
1203302Sagiri 	 * routines do the right thing.
1213302Sagiri 	 */
1223302Sagiri 
1233302Sagiri 	switch (level) {
1243302Sagiri 	case SOL_SOCKET:
1253302Sagiri 		switch (name) {
1263302Sagiri 
1273302Sagiri 		case SO_SNDBUF:
1283302Sagiri 			if (*i1 > rds_max_buf) {
1293302Sagiri 				*outlenp = 0;
1303302Sagiri 				return (ENOBUFS);
1313302Sagiri 			}
1323302Sagiri 			if (!checkonly) {
1333302Sagiri 				q->q_hiwat = *i1;
1343302Sagiri 			}
1353302Sagiri 			break;
1363302Sagiri 		case SO_RCVBUF:
1373302Sagiri 			if (*i1 > rds_max_buf) {
1383302Sagiri 				*outlenp = 0;
1393302Sagiri 				return (ENOBUFS);
1403302Sagiri 			}
1413302Sagiri 			if (!checkonly) {
1423302Sagiri 				RD(q)->q_hiwat = *i1;
1438348SEric.Yu@Sun.COM 				(void) proto_set_rx_hiwat(RD(q), NULL, *i1);
1443302Sagiri 			}
1453302Sagiri 			break;
1463302Sagiri 		default:
1473302Sagiri 			*outlenp = 0;
1483302Sagiri 			return (EINVAL);
1493302Sagiri 		}
1503302Sagiri 		break;
1513302Sagiri 	default:
1523302Sagiri 		*outlenp = 0;
1533302Sagiri 		return (EINVAL);
1543302Sagiri 	}
1553302Sagiri 	/*
1563302Sagiri 	 * Common case of OK return with outval same as inval.
1573302Sagiri 	 */
1583302Sagiri 	if (invalp != outvalp) {
1593302Sagiri 		/* don't trust bcopy for identical src/dst */
1603302Sagiri 		(void) bcopy(invalp, outvalp, inlen);
1613302Sagiri 	}
1623302Sagiri 	*outlenp = inlen;
1633302Sagiri 	return (0);
1643302Sagiri }
1653302Sagiri 
1663302Sagiri uint_t rds_max_optsize; /* initialized when RDS driver is loaded */
1673302Sagiri 
1683302Sagiri #define	RDS_VALID_LEVELS_CNT	A_CNT(rds_valid_levels_arr)
1693302Sagiri 
1703302Sagiri #define	RDS_OPT_ARR_CNT		A_CNT(rds_opt_arr)
1713302Sagiri 
1723302Sagiri 
1733302Sagiri optlevel_t rds_valid_levels_arr[] = {
1743302Sagiri 	SOL_SOCKET,
1753302Sagiri };
1763302Sagiri 
1773302Sagiri /*
1783302Sagiri  * Initialize option database object for RDS
1793302Sagiri  *
1803302Sagiri  * This object represents database of options to search passed to
1813302Sagiri  * {sock,tpi}optcom_req() interface routine to take care of option
1823302Sagiri  * management and associated methods.
1833302Sagiri  */
1843302Sagiri 
1853302Sagiri optdb_obj_t rds_opt_obj = {
1863302Sagiri 	rds_opt_default,	/* RDS default value function pointer */
1873302Sagiri 	rds_opt_get,		/* RDS get function pointer */
1883302Sagiri 	rds_opt_set,		/* RDS set function pointer */
1893302Sagiri 	RDS_OPT_ARR_CNT,	/* RDS option database count of entries */
1903302Sagiri 	rds_opt_arr,		/* RDS option database */
1913302Sagiri 	RDS_VALID_LEVELS_CNT,	/* RDS valid level count of entries */
1923302Sagiri 	rds_valid_levels_arr	/* RDS valid level array */
1933302Sagiri };
194