18275SEric Cheng /*
28275SEric Cheng  * CDDL HEADER START
38275SEric Cheng  *
48275SEric Cheng  * The contents of this file are subject to the terms of the
58275SEric Cheng  * Common Development and Distribution License (the "License").
68275SEric Cheng  * You may not use this file except in compliance with the License.
78275SEric Cheng  *
88275SEric Cheng  * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
98275SEric Cheng  * or http://www.opensolaris.org/os/licensing.
108275SEric Cheng  * See the License for the specific language governing permissions
118275SEric Cheng  * and limitations under the License.
128275SEric Cheng  *
138275SEric Cheng  * When distributing Covered Code, include this CDDL HEADER in each
148275SEric Cheng  * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
158275SEric Cheng  * If applicable, add the following below this CDDL HEADER, with the
168275SEric Cheng  * fields enclosed by brackets "[]" replaced with your own identifying
178275SEric Cheng  * information: Portions Copyright [yyyy] [name of copyright owner]
188275SEric Cheng  *
198275SEric Cheng  * CDDL HEADER END
208275SEric Cheng  */
218275SEric Cheng /*
228558SGirish.Moodalbail@Sun.COM  * Copyright 2009 Sun Microsystems, Inc.  All rights reserved.
238275SEric Cheng  * Use is subject to license terms.
248275SEric Cheng  */
258275SEric Cheng 
268275SEric Cheng #include <stdlib.h>
278275SEric Cheng #include <strings.h>
288275SEric Cheng #include <errno.h>
298275SEric Cheng #include <ctype.h>
308275SEric Cheng #include <sys/types.h>
318275SEric Cheng #include <sys/stat.h>
328275SEric Cheng #include <sys/dld.h>
338275SEric Cheng #include <fcntl.h>
348275SEric Cheng #include <unistd.h>
358275SEric Cheng #include <libdevinfo.h>
368275SEric Cheng #include <libdladm_impl.h>
378275SEric Cheng #include <libdlflow.h>
388275SEric Cheng #include <libdlflow_impl.h>
398275SEric Cheng #include <libintl.h>
408275SEric Cheng 
418275SEric Cheng #include <dlfcn.h>
428275SEric Cheng #include <link.h>
438275SEric Cheng 
448275SEric Cheng /*
458275SEric Cheng  * XXX duplicate define
468275SEric Cheng  */
478275SEric Cheng #define	DLADM_PROP_VAL_MAX	32
488275SEric Cheng 
498453SAnurag.Maskey@Sun.COM static dladm_status_t	i_dladm_set_flowprop_db(dladm_handle_t, const char *,
508453SAnurag.Maskey@Sun.COM 			    const char *, char **, uint_t);
518453SAnurag.Maskey@Sun.COM static dladm_status_t	i_dladm_get_flowprop_db(dladm_handle_t, const char *,
528453SAnurag.Maskey@Sun.COM 			    const char *, char **, uint_t *);
538275SEric Cheng 
548275SEric Cheng static fpd_getf_t	do_get_maxbw;
558275SEric Cheng static fpd_setf_t	do_set_maxbw;
568275SEric Cheng static fpd_checkf_t	do_check_maxbw;
578275SEric Cheng 
588275SEric Cheng static fpd_getf_t	do_get_priority;
598275SEric Cheng static fpd_setf_t	do_set_priority;
608275SEric Cheng static fpd_checkf_t	do_check_priority;
618275SEric Cheng 
628275SEric Cheng static fprop_desc_t	prop_table[] = {
638275SEric Cheng 	{ "maxbw",	{ "", NULL }, NULL, 0, B_FALSE,
648275SEric Cheng 	    do_set_maxbw, NULL,
658275SEric Cheng 	    do_get_maxbw, do_check_maxbw},
668275SEric Cheng 	{ "priority",	{ "", NULL }, NULL, 0, B_FALSE,
678275SEric Cheng 	    do_set_priority, NULL,
688275SEric Cheng 	    do_get_priority, do_check_priority}
698275SEric Cheng };
708275SEric Cheng 
718275SEric Cheng #define	DLADM_MAX_FLOWPROPS	(sizeof (prop_table) / sizeof (fprop_desc_t))
728275SEric Cheng 
738275SEric Cheng static prop_table_t	prop_tbl = {
748275SEric Cheng 	prop_table,
758275SEric Cheng 	DLADM_MAX_FLOWPROPS
768275SEric Cheng };
778275SEric Cheng 
788275SEric Cheng static resource_prop_t rsrc_prop_table[] = {
798275SEric Cheng 	{"maxbw",	do_extract_maxbw},
808275SEric Cheng 	{"priority",	do_extract_priority}
818275SEric Cheng };
828275SEric Cheng #define	DLADM_MAX_RSRC_PROP (sizeof (rsrc_prop_table) / \
838275SEric Cheng 	sizeof (resource_prop_t))
848275SEric Cheng 
858275SEric Cheng static dladm_status_t	flow_proplist_check(dladm_arg_list_t *);
868275SEric Cheng 
878275SEric Cheng dladm_status_t
888453SAnurag.Maskey@Sun.COM dladm_set_flowprop(dladm_handle_t handle, const char *flow,
898453SAnurag.Maskey@Sun.COM     const char *prop_name, char **prop_val, uint_t val_cnt, uint_t flags,
908453SAnurag.Maskey@Sun.COM     char **errprop)
918275SEric Cheng {
928275SEric Cheng 	dladm_status_t		status = DLADM_STATUS_BADARG;
938275SEric Cheng 
948275SEric Cheng 	if (flow == NULL || (prop_val == NULL && val_cnt > 0) ||
958275SEric Cheng 	    (prop_val != NULL && val_cnt == 0) || flags == 0)
968275SEric Cheng 		return (DLADM_STATUS_BADARG);
978275SEric Cheng 
988275SEric Cheng 	if ((flags & DLADM_OPT_ACTIVE) != 0) {
998453SAnurag.Maskey@Sun.COM 		status = i_dladm_set_prop_temp(handle, flow, prop_name,
1008453SAnurag.Maskey@Sun.COM 		    prop_val, val_cnt, flags, errprop, &prop_tbl);
1018275SEric Cheng 		if (status == DLADM_STATUS_TEMPONLY &&
1028275SEric Cheng 		    (flags & DLADM_OPT_PERSIST) != 0)
1038275SEric Cheng 			return (DLADM_STATUS_TEMPONLY);
1048275SEric Cheng 		if (status != DLADM_STATUS_OK)
1058275SEric Cheng 			return (status);
1068275SEric Cheng 	}
1078275SEric Cheng 	if ((flags & DLADM_OPT_PERSIST) != 0) {
1088275SEric Cheng 		if (i_dladm_is_prop_temponly(prop_name, errprop, &prop_tbl))
1098275SEric Cheng 			return (DLADM_STATUS_TEMPONLY);
1108275SEric Cheng 
1118453SAnurag.Maskey@Sun.COM 		status = i_dladm_set_flowprop_db(handle, flow, prop_name,
1128275SEric Cheng 		    prop_val, val_cnt);
1138275SEric Cheng 	}
1148275SEric Cheng 	return (status);
1158275SEric Cheng }
1168275SEric Cheng 
1178275SEric Cheng dladm_status_t
1188275SEric Cheng dladm_walk_flowprop(int (*func)(void *, const char *), const char *flow,
1198275SEric Cheng     void *arg)
1208275SEric Cheng {
1218275SEric Cheng 	int	i;
1228275SEric Cheng 
1238275SEric Cheng 	if (flow == NULL || func == NULL)
1248275SEric Cheng 		return (DLADM_STATUS_BADARG);
1258275SEric Cheng 
1268275SEric Cheng 	/* Then show data-flow properties if there are any */
1278275SEric Cheng 	for (i = 0; i < DLADM_MAX_FLOWPROPS; i++) {
1288275SEric Cheng 		if (func(arg, prop_table[i].pd_name) != DLADM_WALK_CONTINUE)
1298275SEric Cheng 			break;
1308275SEric Cheng 	}
1318275SEric Cheng 	return (DLADM_STATUS_OK);
1328275SEric Cheng }
1338275SEric Cheng 
1348275SEric Cheng dladm_status_t
1358453SAnurag.Maskey@Sun.COM dladm_get_flowprop(dladm_handle_t handle, const char *flow, uint32_t type,
1368275SEric Cheng     const char *prop_name, char **prop_val, uint_t *val_cntp)
1378275SEric Cheng {
1388275SEric Cheng 	dladm_status_t status;
1398275SEric Cheng 
1408275SEric Cheng 	if (flow == NULL || prop_name == NULL || prop_val == NULL ||
1418275SEric Cheng 	    val_cntp == NULL || *val_cntp == 0)
1428275SEric Cheng 		return (DLADM_STATUS_BADARG);
1438275SEric Cheng 
1448275SEric Cheng 	if (type == DLADM_PROP_VAL_PERSISTENT) {
1458275SEric Cheng 		if (i_dladm_is_prop_temponly(prop_name, NULL, &prop_tbl))
1468275SEric Cheng 			return (DLADM_STATUS_TEMPONLY);
1478453SAnurag.Maskey@Sun.COM 		return (i_dladm_get_flowprop_db(handle, flow, prop_name,
1488275SEric Cheng 		    prop_val, val_cntp));
1498275SEric Cheng 	}
1508275SEric Cheng 
1518453SAnurag.Maskey@Sun.COM 	status = i_dladm_get_prop_temp(handle, flow, type, prop_name,
1528275SEric Cheng 	    prop_val, val_cntp, &prop_tbl);
1538275SEric Cheng 	if (status != DLADM_STATUS_NOTFOUND)
1548275SEric Cheng 		return (status);
1558275SEric Cheng 
1568275SEric Cheng 	return (DLADM_STATUS_BADARG);
1578275SEric Cheng }
1588275SEric Cheng 
1598453SAnurag.Maskey@Sun.COM #define	FLOWPROP_RW_DB(handle, statep, writeop)			\
1608453SAnurag.Maskey@Sun.COM 	(i_dladm_rw_db(handle, "/etc/dladm/flowprop.conf",	\
1618275SEric Cheng 	S_IRUSR | S_IWUSR | S_IRGRP | S_IROTH, process_prop_db, \
1628275SEric Cheng 	(statep), (writeop)))
1638275SEric Cheng 
1648275SEric Cheng static dladm_status_t
1658453SAnurag.Maskey@Sun.COM i_dladm_set_flowprop_db(dladm_handle_t handle, const char *flow,
1668453SAnurag.Maskey@Sun.COM     const char *prop_name, char **prop_val, uint_t val_cnt)
1678275SEric Cheng {
1688275SEric Cheng 	prop_db_state_t	state;
1698275SEric Cheng 
1708275SEric Cheng 	state.ls_op = process_prop_set;
1718275SEric Cheng 	state.ls_name = flow;
1728275SEric Cheng 	state.ls_propname = prop_name;
1738275SEric Cheng 	state.ls_propval = prop_val;
1748275SEric Cheng 	state.ls_valcntp = &val_cnt;
1758275SEric Cheng 	state.ls_initop = NULL;
1768275SEric Cheng 
1778453SAnurag.Maskey@Sun.COM 	return (FLOWPROP_RW_DB(handle, &state, B_TRUE));
1788275SEric Cheng }
1798275SEric Cheng 
1808275SEric Cheng static dladm_status_t
1818453SAnurag.Maskey@Sun.COM i_dladm_get_flowprop_db(dladm_handle_t handle, const char *flow,
1828453SAnurag.Maskey@Sun.COM     const char *prop_name, char **prop_val, uint_t *val_cntp)
1838275SEric Cheng {
1848275SEric Cheng 	prop_db_state_t	state;
1858275SEric Cheng 
1868275SEric Cheng 	state.ls_op = process_prop_get;
1878275SEric Cheng 	state.ls_name = flow;
1888275SEric Cheng 	state.ls_propname = prop_name;
1898275SEric Cheng 	state.ls_propval = prop_val;
1908275SEric Cheng 	state.ls_valcntp = val_cntp;
1918275SEric Cheng 	state.ls_initop = NULL;
1928275SEric Cheng 
1938453SAnurag.Maskey@Sun.COM 	return (FLOWPROP_RW_DB(handle, &state, B_FALSE));
1948275SEric Cheng }
1958275SEric Cheng 
1968275SEric Cheng dladm_status_t
1978453SAnurag.Maskey@Sun.COM i_dladm_init_flowprop_db(dladm_handle_t handle)
1988275SEric Cheng {
1998275SEric Cheng 	prop_db_state_t	state;
2008275SEric Cheng 
2018275SEric Cheng 	state.ls_op = process_prop_init;
2028275SEric Cheng 	state.ls_name = NULL;
2038275SEric Cheng 	state.ls_propname = NULL;
2048275SEric Cheng 	state.ls_propval = NULL;
2058275SEric Cheng 	state.ls_valcntp = NULL;
2068275SEric Cheng 	state.ls_initop = dladm_set_flowprop;
2078275SEric Cheng 
2088453SAnurag.Maskey@Sun.COM 	return (FLOWPROP_RW_DB(handle, &state, B_FALSE));
2098275SEric Cheng }
2108275SEric Cheng 
2118275SEric Cheng #define	MIN_INFO_SIZE (4 * 1024)
2128275SEric Cheng 
2138275SEric Cheng dladm_status_t
2148453SAnurag.Maskey@Sun.COM dladm_flow_info(dladm_handle_t handle, const char *flow,
2158453SAnurag.Maskey@Sun.COM     dladm_flow_attr_t *attr)
2168275SEric Cheng {
2178275SEric Cheng 	dld_ioc_walkflow_t	*ioc;
2188453SAnurag.Maskey@Sun.COM 	int			bufsize;
2198275SEric Cheng 	dld_flowinfo_t		*flowinfo;
2208275SEric Cheng 
2218275SEric Cheng 	if ((flow == NULL) || (attr == NULL))
2228275SEric Cheng 		return (DLADM_STATUS_BADARG);
2238275SEric Cheng 
2248453SAnurag.Maskey@Sun.COM 	bufsize = MIN_INFO_SIZE;
2258453SAnurag.Maskey@Sun.COM 	if ((ioc = calloc(1, bufsize)) == NULL)
2268275SEric Cheng 		return (dladm_errno2status(errno));
2278275SEric Cheng 
2288275SEric Cheng 	(void) strlcpy(ioc->wf_name, flow, sizeof (ioc->wf_name));
2298275SEric Cheng 	ioc->wf_len = bufsize - sizeof (*ioc);
2308275SEric Cheng 
2318453SAnurag.Maskey@Sun.COM 	while (ioctl(dladm_dld_fd(handle), DLDIOC_WALKFLOW, ioc) < 0) {
2328275SEric Cheng 		if (errno == ENOSPC) {
2338275SEric Cheng 			bufsize *= 2;
2348275SEric Cheng 			ioc = realloc(ioc, bufsize);
2358275SEric Cheng 			if (ioc != NULL) {
2368275SEric Cheng 				(void) strlcpy(ioc->wf_name, flow,
2378558SGirish.Moodalbail@Sun.COM 				    MAXFLOWNAMELEN);
2388275SEric Cheng 				ioc->wf_len = bufsize - sizeof (*ioc);
2398275SEric Cheng 				continue;
2408275SEric Cheng 			}
2418275SEric Cheng 		}
2428275SEric Cheng 		free(ioc);
2438275SEric Cheng 		return (dladm_errno2status(errno));
2448275SEric Cheng 	}
2458275SEric Cheng 
2468275SEric Cheng 	bzero(attr, sizeof (*attr));
2478275SEric Cheng 
2488275SEric Cheng 	flowinfo = (dld_flowinfo_t *)(void *)(ioc + 1);
2498275SEric Cheng 
2508275SEric Cheng 	attr->fa_linkid = flowinfo->fi_linkid;
2518275SEric Cheng 	bcopy(&flowinfo->fi_flowname, &attr->fa_flowname,
2528275SEric Cheng 	    sizeof (attr->fa_flowname));
2538275SEric Cheng 	bcopy(&flowinfo->fi_flow_desc, &attr->fa_flow_desc,
2548275SEric Cheng 	    sizeof (attr->fa_flow_desc));
2558275SEric Cheng 	bcopy(&flowinfo->fi_resource_props, &attr->fa_resource_props,
2568275SEric Cheng 	    sizeof (attr->fa_resource_props));
2578275SEric Cheng 
2588275SEric Cheng 	free(ioc);
2598275SEric Cheng 	return (DLADM_STATUS_OK);
2608275SEric Cheng }
2618275SEric Cheng 
2628275SEric Cheng /* ARGSUSED */
2638275SEric Cheng static dladm_status_t
2648453SAnurag.Maskey@Sun.COM do_get_maxbw(dladm_handle_t handle, const char *flow, char **prop_val,
2658453SAnurag.Maskey@Sun.COM     uint_t *val_cnt)
2668275SEric Cheng {
2678275SEric Cheng 	mac_resource_props_t	*mrp;
2688275SEric Cheng 	char 			buf[DLADM_STRSIZE];
2698275SEric Cheng 	dladm_flow_attr_t	fa;
2708275SEric Cheng 	dladm_status_t		status;
2718275SEric Cheng 
2728453SAnurag.Maskey@Sun.COM 	status = dladm_flow_info(handle, flow, &fa);
2738275SEric Cheng 	if (status != DLADM_STATUS_OK)
2748275SEric Cheng 		return (status);
2758275SEric Cheng 	mrp = &(fa.fa_resource_props);
2768275SEric Cheng 
2778275SEric Cheng 	*val_cnt = 1;
2788275SEric Cheng 	if (mrp->mrp_mask & MRP_MAXBW) {
2798275SEric Cheng 		(void) snprintf(prop_val[0], DLADM_STRSIZE, "%s",
2808275SEric Cheng 		    dladm_bw2str(mrp->mrp_maxbw, buf));
2818275SEric Cheng 	} else {
2828275SEric Cheng 		return (DLADM_STATUS_NOTSUP);
2838275SEric Cheng 	}
2848275SEric Cheng 	return (DLADM_STATUS_OK);
2858275SEric Cheng }
2868275SEric Cheng 
2878275SEric Cheng /* ARGSUSED */
2888275SEric Cheng static dladm_status_t
2898453SAnurag.Maskey@Sun.COM do_set_maxbw(dladm_handle_t handle, const char *flow, val_desc_t *vdp,
2908453SAnurag.Maskey@Sun.COM     uint_t val_cnt)
2918275SEric Cheng {
2928275SEric Cheng 	dld_ioc_modifyflow_t	attr;
2938275SEric Cheng 	mac_resource_props_t	mrp;
2948275SEric Cheng 	void			*val;
2958275SEric Cheng 
2968275SEric Cheng 	if (val_cnt != 1)
2978275SEric Cheng 		return (DLADM_STATUS_BADVALCNT);
2988275SEric Cheng 
2998275SEric Cheng 	bzero(&mrp, sizeof (mrp));
3008275SEric Cheng 	if (vdp != NULL && (val = (void *)vdp->vd_val) != NULL) {
3018275SEric Cheng 		bcopy(val, &mrp.mrp_maxbw, sizeof (int64_t));
3028275SEric Cheng 		free(val);
3038275SEric Cheng 	} else {
3048275SEric Cheng 		mrp.mrp_maxbw = MRP_MAXBW_RESETVAL;
3058275SEric Cheng 	}
3068275SEric Cheng 	mrp.mrp_mask = MRP_MAXBW;
3078275SEric Cheng 
3088275SEric Cheng 	bzero(&attr, sizeof (attr));
3098275SEric Cheng 	(void) strlcpy(attr.mf_name, flow, sizeof (attr.mf_name));
3108275SEric Cheng 	bcopy(&mrp, &attr.mf_resource_props, sizeof (mac_resource_props_t));
3118275SEric Cheng 
3128453SAnurag.Maskey@Sun.COM 	if (ioctl(dladm_dld_fd(handle), DLDIOC_MODIFYFLOW, &attr) < 0)
3138275SEric Cheng 		return (dladm_errno2status(errno));
3148275SEric Cheng 
3158275SEric Cheng 	return (DLADM_STATUS_OK);
3168275SEric Cheng }
3178275SEric Cheng 
3188275SEric Cheng /* ARGSUSED */
3198275SEric Cheng static dladm_status_t
3208275SEric Cheng do_check_maxbw(fprop_desc_t *pdp, char **prop_val, uint_t val_cnt,
3218275SEric Cheng     val_desc_t **vdpp)
3228275SEric Cheng {
3238275SEric Cheng 	uint64_t	*maxbw;
3248275SEric Cheng 	val_desc_t	*vdp = NULL;
3258275SEric Cheng 	dladm_status_t	status = DLADM_STATUS_OK;
3268275SEric Cheng 
3278275SEric Cheng 	if (val_cnt != 1)
3288275SEric Cheng 		return (DLADM_STATUS_BADVALCNT);
3298275SEric Cheng 
3308275SEric Cheng 	maxbw = malloc(sizeof (uint64_t));
3318275SEric Cheng 	if (maxbw == NULL)
3328275SEric Cheng 		return (DLADM_STATUS_NOMEM);
3338275SEric Cheng 
3348275SEric Cheng 	status = dladm_str2bw(*prop_val, maxbw);
3358275SEric Cheng 	if (status != DLADM_STATUS_OK) {
3368275SEric Cheng 		free(maxbw);
3378275SEric Cheng 		return (status);
3388275SEric Cheng 	}
3398275SEric Cheng 
3408275SEric Cheng 	if ((*maxbw < MRP_MAXBW_MINVAL) && (*maxbw != 0)) {
3418275SEric Cheng 		free(maxbw);
3428275SEric Cheng 		return (DLADM_STATUS_MINMAXBW);
3438275SEric Cheng 	}
3448275SEric Cheng 
3458275SEric Cheng 	vdp = malloc(sizeof (val_desc_t));
3468275SEric Cheng 	if (vdp == NULL) {
3478275SEric Cheng 		free(maxbw);
3488275SEric Cheng 		return (DLADM_STATUS_NOMEM);
3498275SEric Cheng 	}
3508275SEric Cheng 
3518275SEric Cheng 	vdp->vd_val = (uintptr_t)maxbw;
3528275SEric Cheng 	*vdpp = vdp;
3538275SEric Cheng 	return (DLADM_STATUS_OK);
3548275SEric Cheng }
3558275SEric Cheng 
3568275SEric Cheng /* ARGSUSED */
3578275SEric Cheng static dladm_status_t
3588453SAnurag.Maskey@Sun.COM do_get_priority(dladm_handle_t handle, const char *flow, char **prop_val,
3598453SAnurag.Maskey@Sun.COM     uint_t *val_cnt)
3608275SEric Cheng {
3618275SEric Cheng 	mac_resource_props_t	*mrp;
3628275SEric Cheng 	char 			buf[DLADM_STRSIZE];
3638275SEric Cheng 	dladm_flow_attr_t	fa;
3648275SEric Cheng 	dladm_status_t		status;
3658275SEric Cheng 
3668275SEric Cheng 	bzero(&fa, sizeof (dladm_flow_attr_t));
3678453SAnurag.Maskey@Sun.COM 	status = dladm_flow_info(handle, flow, &fa);
3688275SEric Cheng 	if (status != DLADM_STATUS_OK)
3698275SEric Cheng 		return (status);
3708275SEric Cheng 	mrp = &(fa.fa_resource_props);
3718275SEric Cheng 
3728275SEric Cheng 	*val_cnt = 1;
3738275SEric Cheng 	if (mrp->mrp_mask & MRP_PRIORITY) {
3748275SEric Cheng 		(void) snprintf(prop_val[0], DLADM_STRSIZE, "%s",
3758275SEric Cheng 		    dladm_pri2str(mrp->mrp_priority, buf));
3768275SEric Cheng 	} else {
3778275SEric Cheng 		return (DLADM_STATUS_NOTSUP);
3788275SEric Cheng 	}
3798275SEric Cheng 	return (DLADM_STATUS_OK);
3808275SEric Cheng }
3818275SEric Cheng 
3828275SEric Cheng /* ARGSUSED */
3838275SEric Cheng static dladm_status_t
3848453SAnurag.Maskey@Sun.COM do_set_priority(dladm_handle_t handle, const char *flow, val_desc_t *vdp,
3858453SAnurag.Maskey@Sun.COM     uint_t val_cnt)
3868275SEric Cheng {
3878275SEric Cheng 	dld_ioc_modifyflow_t	attr;
3888275SEric Cheng 	mac_resource_props_t	mrp;
3898275SEric Cheng 	void			*val;
3908275SEric Cheng 
3918275SEric Cheng 	if (val_cnt != 1)
3928275SEric Cheng 		return (DLADM_STATUS_BADVALCNT);
3938275SEric Cheng 
3948275SEric Cheng 	bzero(&mrp, sizeof (mrp));
3958275SEric Cheng 	if (vdp != NULL && (val = (void *)vdp->vd_val) != NULL) {
3968275SEric Cheng 		bcopy(val, &mrp.mrp_priority, sizeof (mac_priority_level_t));
3978275SEric Cheng 		free(val);
3988275SEric Cheng 	} else {
3998275SEric Cheng 		mrp.mrp_priority = MPL_RESET;
4008275SEric Cheng 	}
4018275SEric Cheng 	mrp.mrp_mask = MRP_PRIORITY;
4028275SEric Cheng 
4038275SEric Cheng 	bzero(&attr, sizeof (attr));
4048275SEric Cheng 	(void) strlcpy(attr.mf_name, flow, sizeof (attr.mf_name));
4058275SEric Cheng 	bcopy(&mrp, &attr.mf_resource_props, sizeof (mac_resource_props_t));
4068275SEric Cheng 
4078453SAnurag.Maskey@Sun.COM 	if (ioctl(dladm_dld_fd(handle), DLDIOC_MODIFYFLOW, &attr) < 0)
4088275SEric Cheng 		return (dladm_errno2status(errno));
4098275SEric Cheng 
4108275SEric Cheng 	return (DLADM_STATUS_OK);
4118275SEric Cheng }
4128275SEric Cheng 
4138275SEric Cheng /* ARGSUSED */
4148275SEric Cheng static dladm_status_t
4158275SEric Cheng do_check_priority(fprop_desc_t *pdp, char **prop_val, uint_t val_cnt,
4168275SEric Cheng     val_desc_t **vdpp)
4178275SEric Cheng {
4188275SEric Cheng 	mac_priority_level_t	*pri;
4198275SEric Cheng 	val_desc_t	*vdp = NULL;
4208275SEric Cheng 	dladm_status_t	status = DLADM_STATUS_OK;
4218275SEric Cheng 
4228275SEric Cheng 	if (val_cnt != 1)
4238275SEric Cheng 		return (DLADM_STATUS_BADVALCNT);
4248275SEric Cheng 
4258275SEric Cheng 	pri = malloc(sizeof (mac_priority_level_t));
4268275SEric Cheng 	if (pri == NULL)
4278275SEric Cheng 		return (DLADM_STATUS_NOMEM);
4288275SEric Cheng 
4298275SEric Cheng 	status = dladm_str2pri(*prop_val, pri);
4308275SEric Cheng 	if (status != DLADM_STATUS_OK) {
4318275SEric Cheng 		free(pri);
4328275SEric Cheng 		return (status);
4338275SEric Cheng 	}
4348275SEric Cheng 
4358275SEric Cheng 	if (*pri == -1) {
4368275SEric Cheng 		free(pri);
4378275SEric Cheng 		return (DLADM_STATUS_BADVAL);
4388275SEric Cheng 	}
4398275SEric Cheng 
4408275SEric Cheng 	vdp = malloc(sizeof (val_desc_t));
4418275SEric Cheng 	if (vdp == NULL) {
4428275SEric Cheng 		free(pri);
4438275SEric Cheng 		return (DLADM_STATUS_NOMEM);
4448275SEric Cheng 	}
4458275SEric Cheng 
4468275SEric Cheng 	vdp->vd_val = (uintptr_t)pri;
4478275SEric Cheng 	*vdpp = vdp;
4488275SEric Cheng 	return (DLADM_STATUS_OK);
4498275SEric Cheng }
4508275SEric Cheng 
4518275SEric Cheng static dladm_status_t
4528275SEric Cheng flow_proplist_check(dladm_arg_list_t *proplist)
4538275SEric Cheng {
4548275SEric Cheng 	int		i, j;
4558275SEric Cheng 	boolean_t	matched;
4568275SEric Cheng 
4578275SEric Cheng 	for (i = 0; i < proplist->al_count; i++) {
4588275SEric Cheng 		matched = B_FALSE;
4598275SEric Cheng 		for (j = 0; j < DLADM_MAX_FLOWPROPS; j++) {
4608275SEric Cheng 			if (strcmp(proplist->al_info[i].ai_name,
4618275SEric Cheng 			    prop_table[j].pd_name) == 0)
4628275SEric Cheng 				matched = B_TRUE;
4638275SEric Cheng 			}
4648275SEric Cheng 		if (!matched)
4658275SEric Cheng 			return (DLADM_STATUS_BADPROP);
4668275SEric Cheng 	}
4678275SEric Cheng 	return (DLADM_STATUS_OK);
4688275SEric Cheng 
4698275SEric Cheng }
4708275SEric Cheng 
4718275SEric Cheng dladm_status_t
4728275SEric Cheng dladm_parse_flow_props(char *str, dladm_arg_list_t **listp, boolean_t novalues)
4738275SEric Cheng {
4748275SEric Cheng 	dladm_status_t	status;
4758275SEric Cheng 
4768275SEric Cheng 	status = dladm_parse_args(str, listp, novalues);
4778275SEric Cheng 	if (status != DLADM_STATUS_OK)
4788275SEric Cheng 		return (status);
4798275SEric Cheng 
480*9055SMichael.Lim@Sun.COM 	if (*listp != NULL && (status = flow_proplist_check(*listp)
481*9055SMichael.Lim@Sun.COM 	    != DLADM_STATUS_OK)) {
4828275SEric Cheng 		dladm_free_props(*listp);
4838275SEric Cheng 		return (status);
4848275SEric Cheng 	}
4858275SEric Cheng 
4868275SEric Cheng 	return (DLADM_STATUS_OK);
4878275SEric Cheng }
4888275SEric Cheng 
4898275SEric Cheng /*
4908275SEric Cheng  * Retrieve the named property from a proplist, check the value and
4918275SEric Cheng  * convert to a kernel structure.
4928275SEric Cheng  */
4938275SEric Cheng static dladm_status_t
4948275SEric Cheng i_dladm_flow_proplist_extract_one(dladm_arg_list_t *proplist,
4958275SEric Cheng     const char *name, void *val)
4968275SEric Cheng {
4978275SEric Cheng 	dladm_status_t		status;
4988275SEric Cheng 	dladm_arg_info_t	*aip = NULL;
4998275SEric Cheng 	int			i, j;
5008275SEric Cheng 
5018275SEric Cheng 	/* Find named property in proplist */
5028275SEric Cheng 	for (i = 0; i < proplist->al_count; i++) {
5038275SEric Cheng 		aip = &proplist->al_info[i];
5048275SEric Cheng 		if (strcasecmp(aip->ai_name, name) == 0)
5058275SEric Cheng 			break;
5068275SEric Cheng 	}
5078275SEric Cheng 
5088275SEric Cheng 	/* Property not in list */
5098275SEric Cheng 	if (i == proplist->al_count)
5108275SEric Cheng 		return (DLADM_STATUS_OK);
5118275SEric Cheng 
5128275SEric Cheng 	for (i = 0; i < DLADM_MAX_FLOWPROPS; i++) {
5138275SEric Cheng 		fprop_desc_t	*pdp = &prop_table[i];
5148275SEric Cheng 		val_desc_t	*vdp;
5158275SEric Cheng 
5168275SEric Cheng 		vdp = malloc(sizeof (val_desc_t) * aip->ai_count);
5178275SEric Cheng 		if (vdp == NULL)
5188275SEric Cheng 			return (DLADM_STATUS_NOMEM);
5198275SEric Cheng 
5208275SEric Cheng 		if (strcasecmp(aip->ai_name, pdp->pd_name) != 0)
5218275SEric Cheng 			continue;
5228275SEric Cheng 
5238275SEric Cheng 		if (aip->ai_val == NULL)
5248275SEric Cheng 			return (DLADM_STATUS_BADARG);
5258275SEric Cheng 
5268275SEric Cheng 		/* Check property value */
5278275SEric Cheng 		if (pdp->pd_check != NULL) {
5288275SEric Cheng 			status = pdp->pd_check(pdp, aip->ai_val,
5298275SEric Cheng 			    aip->ai_count, &vdp);
5308275SEric Cheng 		} else {
5318275SEric Cheng 			status = DLADM_STATUS_BADARG;
5328275SEric Cheng 		}
5338275SEric Cheng 
5348275SEric Cheng 		if (status != DLADM_STATUS_OK)
5358275SEric Cheng 			return (status);
5368275SEric Cheng 
5378275SEric Cheng 		for (j = 0; j < DLADM_MAX_RSRC_PROP; j++) {
5388275SEric Cheng 			resource_prop_t	*rpp = &rsrc_prop_table[j];
5398275SEric Cheng 
5408275SEric Cheng 			if (strcasecmp(aip->ai_name, rpp->rp_name) != 0)
5418275SEric Cheng 				continue;
5428275SEric Cheng 
5438275SEric Cheng 			/* Extract kernel structure */
5448275SEric Cheng 			if (rpp->rp_extract != NULL) {
5458275SEric Cheng 				status = rpp->rp_extract(vdp, val,
5468275SEric Cheng 				    aip->ai_count);
5478275SEric Cheng 			} else {
5488275SEric Cheng 				status = DLADM_STATUS_BADARG;
5498275SEric Cheng 			}
5508275SEric Cheng 			break;
5518275SEric Cheng 		}
5528275SEric Cheng 
5538275SEric Cheng 		if (status != DLADM_STATUS_OK)
5548275SEric Cheng 			return (status);
5558275SEric Cheng 
5568275SEric Cheng 		break;
5578275SEric Cheng 	}
5588275SEric Cheng 	return (status);
5598275SEric Cheng }
5608275SEric Cheng 
5618275SEric Cheng /*
5628275SEric Cheng  * Extract properties from a proplist and convert to mac_resource_props_t.
5638275SEric Cheng  */
5648275SEric Cheng dladm_status_t
5658275SEric Cheng dladm_flow_proplist_extract(dladm_arg_list_t *proplist,
5668275SEric Cheng     mac_resource_props_t *mrp)
5678275SEric Cheng {
5688275SEric Cheng 	dladm_status_t	status = DLADM_STATUS_OK;
5698275SEric Cheng 
5708275SEric Cheng 	status = i_dladm_flow_proplist_extract_one(proplist, "maxbw", mrp);
5718275SEric Cheng 	if (status != DLADM_STATUS_OK)
5728275SEric Cheng 		return (status);
5738275SEric Cheng 	status = i_dladm_flow_proplist_extract_one(proplist, "priority", mrp);
5748275SEric Cheng 	if (status != DLADM_STATUS_OK)
5758275SEric Cheng 		return (status);
5768275SEric Cheng 	return (status);
5778275SEric Cheng }
5788275SEric Cheng 
5798275SEric Cheng dladm_status_t
5808453SAnurag.Maskey@Sun.COM i_dladm_set_flow_proplist_db(dladm_handle_t handle, char *flow,
5818453SAnurag.Maskey@Sun.COM     dladm_arg_list_t *proplist)
5828275SEric Cheng {
5838275SEric Cheng 	dladm_status_t		status, ssave = DLADM_STATUS_OK;
5848275SEric Cheng 	dladm_arg_info_t	ai;
5858275SEric Cheng 	int			i;
5868275SEric Cheng 
5878275SEric Cheng 	for (i = 0; i < proplist->al_count; i++) {
5888275SEric Cheng 		ai = proplist->al_info[i];
5898453SAnurag.Maskey@Sun.COM 		status = i_dladm_set_flowprop_db(handle, flow, ai.ai_name,
5908275SEric Cheng 		    ai.ai_val, ai.ai_count);
5918275SEric Cheng 		if (status != DLADM_STATUS_OK)
5928275SEric Cheng 			ssave = status;
5938275SEric Cheng 	}
5948275SEric Cheng 	return (ssave);
5958275SEric Cheng }
596