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>
339107Sjames.d.carlson@sun.com #include <sys/dld_ioc.h>
348275SEric Cheng #include <fcntl.h>
358275SEric Cheng #include <unistd.h>
368275SEric Cheng #include <libdevinfo.h>
378275SEric Cheng #include <libdladm_impl.h>
388275SEric Cheng #include <libdlflow.h>
398275SEric Cheng #include <libdlflow_impl.h>
408275SEric Cheng #include <libintl.h>
418275SEric Cheng 
428275SEric Cheng #include <dlfcn.h>
438275SEric Cheng #include <link.h>
448275SEric Cheng 
458275SEric Cheng /*
468275SEric Cheng  * XXX duplicate define
478275SEric Cheng  */
488275SEric Cheng #define	DLADM_PROP_VAL_MAX	32
498275SEric Cheng 
508453SAnurag.Maskey@Sun.COM static dladm_status_t	i_dladm_set_flowprop_db(dladm_handle_t, const char *,
518453SAnurag.Maskey@Sun.COM 			    const char *, char **, uint_t);
528453SAnurag.Maskey@Sun.COM static dladm_status_t	i_dladm_get_flowprop_db(dladm_handle_t, const char *,
538453SAnurag.Maskey@Sun.COM 			    const char *, char **, uint_t *);
548275SEric Cheng 
558275SEric Cheng static fpd_getf_t	do_get_maxbw;
568275SEric Cheng static fpd_setf_t	do_set_maxbw;
578275SEric Cheng static fpd_checkf_t	do_check_maxbw;
588275SEric Cheng 
598275SEric Cheng static fpd_getf_t	do_get_priority;
608275SEric Cheng static fpd_setf_t	do_set_priority;
618275SEric Cheng static fpd_checkf_t	do_check_priority;
628275SEric Cheng 
638275SEric Cheng static fprop_desc_t	prop_table[] = {
648275SEric Cheng 	{ "maxbw",	{ "", NULL }, NULL, 0, B_FALSE,
658275SEric Cheng 	    do_set_maxbw, NULL,
668275SEric Cheng 	    do_get_maxbw, do_check_maxbw},
678275SEric Cheng 	{ "priority",	{ "", NULL }, NULL, 0, B_FALSE,
688275SEric Cheng 	    do_set_priority, NULL,
698275SEric Cheng 	    do_get_priority, do_check_priority}
708275SEric Cheng };
718275SEric Cheng 
728275SEric Cheng #define	DLADM_MAX_FLOWPROPS	(sizeof (prop_table) / sizeof (fprop_desc_t))
738275SEric Cheng 
748275SEric Cheng static prop_table_t	prop_tbl = {
758275SEric Cheng 	prop_table,
768275SEric Cheng 	DLADM_MAX_FLOWPROPS
778275SEric Cheng };
788275SEric Cheng 
798275SEric Cheng static resource_prop_t rsrc_prop_table[] = {
808275SEric Cheng 	{"maxbw",	do_extract_maxbw},
818275SEric Cheng 	{"priority",	do_extract_priority}
828275SEric Cheng };
838275SEric Cheng #define	DLADM_MAX_RSRC_PROP (sizeof (rsrc_prop_table) / \
848275SEric Cheng 	sizeof (resource_prop_t))
858275SEric Cheng 
868275SEric Cheng static dladm_status_t	flow_proplist_check(dladm_arg_list_t *);
878275SEric Cheng 
888275SEric Cheng dladm_status_t
898453SAnurag.Maskey@Sun.COM dladm_set_flowprop(dladm_handle_t handle, const char *flow,
908453SAnurag.Maskey@Sun.COM     const char *prop_name, char **prop_val, uint_t val_cnt, uint_t flags,
918453SAnurag.Maskey@Sun.COM     char **errprop)
928275SEric Cheng {
938275SEric Cheng 	dladm_status_t		status = DLADM_STATUS_BADARG;
948275SEric Cheng 
958275SEric Cheng 	if (flow == NULL || (prop_val == NULL && val_cnt > 0) ||
968275SEric Cheng 	    (prop_val != NULL && val_cnt == 0) || flags == 0)
978275SEric Cheng 		return (DLADM_STATUS_BADARG);
988275SEric Cheng 
998275SEric Cheng 	if ((flags & DLADM_OPT_ACTIVE) != 0) {
1008453SAnurag.Maskey@Sun.COM 		status = i_dladm_set_prop_temp(handle, flow, prop_name,
1018453SAnurag.Maskey@Sun.COM 		    prop_val, val_cnt, flags, errprop, &prop_tbl);
1028275SEric Cheng 		if (status == DLADM_STATUS_TEMPONLY &&
1038275SEric Cheng 		    (flags & DLADM_OPT_PERSIST) != 0)
1048275SEric Cheng 			return (DLADM_STATUS_TEMPONLY);
1058275SEric Cheng 		if (status != DLADM_STATUS_OK)
1068275SEric Cheng 			return (status);
1078275SEric Cheng 	}
1088275SEric Cheng 	if ((flags & DLADM_OPT_PERSIST) != 0) {
1098275SEric Cheng 		if (i_dladm_is_prop_temponly(prop_name, errprop, &prop_tbl))
1108275SEric Cheng 			return (DLADM_STATUS_TEMPONLY);
1118275SEric Cheng 
1128453SAnurag.Maskey@Sun.COM 		status = i_dladm_set_flowprop_db(handle, flow, prop_name,
1138275SEric Cheng 		    prop_val, val_cnt);
1148275SEric Cheng 	}
1158275SEric Cheng 	return (status);
1168275SEric Cheng }
1178275SEric Cheng 
1188275SEric Cheng dladm_status_t
1198275SEric Cheng dladm_walk_flowprop(int (*func)(void *, const char *), const char *flow,
1208275SEric Cheng     void *arg)
1218275SEric Cheng {
1228275SEric Cheng 	int	i;
1238275SEric Cheng 
1248275SEric Cheng 	if (flow == NULL || func == NULL)
1258275SEric Cheng 		return (DLADM_STATUS_BADARG);
1268275SEric Cheng 
1278275SEric Cheng 	/* Then show data-flow properties if there are any */
1288275SEric Cheng 	for (i = 0; i < DLADM_MAX_FLOWPROPS; i++) {
1298275SEric Cheng 		if (func(arg, prop_table[i].pd_name) != DLADM_WALK_CONTINUE)
1308275SEric Cheng 			break;
1318275SEric Cheng 	}
1328275SEric Cheng 	return (DLADM_STATUS_OK);
1338275SEric Cheng }
1348275SEric Cheng 
1358275SEric Cheng dladm_status_t
1368453SAnurag.Maskey@Sun.COM dladm_get_flowprop(dladm_handle_t handle, const char *flow, uint32_t type,
1378275SEric Cheng     const char *prop_name, char **prop_val, uint_t *val_cntp)
1388275SEric Cheng {
1398275SEric Cheng 	dladm_status_t status;
1408275SEric Cheng 
1418275SEric Cheng 	if (flow == NULL || prop_name == NULL || prop_val == NULL ||
1428275SEric Cheng 	    val_cntp == NULL || *val_cntp == 0)
1438275SEric Cheng 		return (DLADM_STATUS_BADARG);
1448275SEric Cheng 
1458275SEric Cheng 	if (type == DLADM_PROP_VAL_PERSISTENT) {
1468275SEric Cheng 		if (i_dladm_is_prop_temponly(prop_name, NULL, &prop_tbl))
1478275SEric Cheng 			return (DLADM_STATUS_TEMPONLY);
1488453SAnurag.Maskey@Sun.COM 		return (i_dladm_get_flowprop_db(handle, flow, prop_name,
1498275SEric Cheng 		    prop_val, val_cntp));
1508275SEric Cheng 	}
1518275SEric Cheng 
1528453SAnurag.Maskey@Sun.COM 	status = i_dladm_get_prop_temp(handle, flow, type, prop_name,
1538275SEric Cheng 	    prop_val, val_cntp, &prop_tbl);
1548275SEric Cheng 	if (status != DLADM_STATUS_NOTFOUND)
1558275SEric Cheng 		return (status);
1568275SEric Cheng 
1578275SEric Cheng 	return (DLADM_STATUS_BADARG);
1588275SEric Cheng }
1598275SEric Cheng 
1608453SAnurag.Maskey@Sun.COM #define	FLOWPROP_RW_DB(handle, statep, writeop)			\
1618453SAnurag.Maskey@Sun.COM 	(i_dladm_rw_db(handle, "/etc/dladm/flowprop.conf",	\
1628275SEric Cheng 	S_IRUSR | S_IWUSR | S_IRGRP | S_IROTH, process_prop_db, \
1638275SEric Cheng 	(statep), (writeop)))
1648275SEric Cheng 
1658275SEric Cheng static dladm_status_t
1668453SAnurag.Maskey@Sun.COM i_dladm_set_flowprop_db(dladm_handle_t handle, const char *flow,
1678453SAnurag.Maskey@Sun.COM     const char *prop_name, char **prop_val, uint_t val_cnt)
1688275SEric Cheng {
1698275SEric Cheng 	prop_db_state_t	state;
1708275SEric Cheng 
1718275SEric Cheng 	state.ls_op = process_prop_set;
1728275SEric Cheng 	state.ls_name = flow;
1738275SEric Cheng 	state.ls_propname = prop_name;
1748275SEric Cheng 	state.ls_propval = prop_val;
1758275SEric Cheng 	state.ls_valcntp = &val_cnt;
1768275SEric Cheng 	state.ls_initop = NULL;
1778275SEric Cheng 
1788453SAnurag.Maskey@Sun.COM 	return (FLOWPROP_RW_DB(handle, &state, B_TRUE));
1798275SEric Cheng }
1808275SEric Cheng 
1818275SEric Cheng static dladm_status_t
1828453SAnurag.Maskey@Sun.COM i_dladm_get_flowprop_db(dladm_handle_t handle, const char *flow,
1838453SAnurag.Maskey@Sun.COM     const char *prop_name, char **prop_val, uint_t *val_cntp)
1848275SEric Cheng {
1858275SEric Cheng 	prop_db_state_t	state;
1868275SEric Cheng 
1878275SEric Cheng 	state.ls_op = process_prop_get;
1888275SEric Cheng 	state.ls_name = flow;
1898275SEric Cheng 	state.ls_propname = prop_name;
1908275SEric Cheng 	state.ls_propval = prop_val;
1918275SEric Cheng 	state.ls_valcntp = val_cntp;
1928275SEric Cheng 	state.ls_initop = NULL;
1938275SEric Cheng 
1948453SAnurag.Maskey@Sun.COM 	return (FLOWPROP_RW_DB(handle, &state, B_FALSE));
1958275SEric Cheng }
1968275SEric Cheng 
1978275SEric Cheng dladm_status_t
1988453SAnurag.Maskey@Sun.COM i_dladm_init_flowprop_db(dladm_handle_t handle)
1998275SEric Cheng {
2008275SEric Cheng 	prop_db_state_t	state;
2018275SEric Cheng 
2028275SEric Cheng 	state.ls_op = process_prop_init;
2038275SEric Cheng 	state.ls_name = NULL;
2048275SEric Cheng 	state.ls_propname = NULL;
2058275SEric Cheng 	state.ls_propval = NULL;
2068275SEric Cheng 	state.ls_valcntp = NULL;
2078275SEric Cheng 	state.ls_initop = dladm_set_flowprop;
2088275SEric Cheng 
2098453SAnurag.Maskey@Sun.COM 	return (FLOWPROP_RW_DB(handle, &state, B_FALSE));
2108275SEric Cheng }
2118275SEric Cheng 
2128275SEric Cheng #define	MIN_INFO_SIZE (4 * 1024)
2138275SEric Cheng 
2148275SEric Cheng dladm_status_t
2158453SAnurag.Maskey@Sun.COM dladm_flow_info(dladm_handle_t handle, const char *flow,
2168453SAnurag.Maskey@Sun.COM     dladm_flow_attr_t *attr)
2178275SEric Cheng {
2188275SEric Cheng 	dld_ioc_walkflow_t	*ioc;
2198453SAnurag.Maskey@Sun.COM 	int			bufsize;
2208275SEric Cheng 	dld_flowinfo_t		*flowinfo;
2218275SEric Cheng 
2228275SEric Cheng 	if ((flow == NULL) || (attr == NULL))
2238275SEric Cheng 		return (DLADM_STATUS_BADARG);
2248275SEric Cheng 
2258453SAnurag.Maskey@Sun.COM 	bufsize = MIN_INFO_SIZE;
2268453SAnurag.Maskey@Sun.COM 	if ((ioc = calloc(1, bufsize)) == NULL)
2278275SEric Cheng 		return (dladm_errno2status(errno));
2288275SEric Cheng 
2298275SEric Cheng 	(void) strlcpy(ioc->wf_name, flow, sizeof (ioc->wf_name));
2308275SEric Cheng 	ioc->wf_len = bufsize - sizeof (*ioc);
2318275SEric Cheng 
2328453SAnurag.Maskey@Sun.COM 	while (ioctl(dladm_dld_fd(handle), DLDIOC_WALKFLOW, ioc) < 0) {
2338275SEric Cheng 		if (errno == ENOSPC) {
2348275SEric Cheng 			bufsize *= 2;
2358275SEric Cheng 			ioc = realloc(ioc, bufsize);
2368275SEric Cheng 			if (ioc != NULL) {
2378275SEric Cheng 				(void) strlcpy(ioc->wf_name, flow,
2388558SGirish.Moodalbail@Sun.COM 				    MAXFLOWNAMELEN);
2398275SEric Cheng 				ioc->wf_len = bufsize - sizeof (*ioc);
2408275SEric Cheng 				continue;
2418275SEric Cheng 			}
2428275SEric Cheng 		}
2438275SEric Cheng 		free(ioc);
2448275SEric Cheng 		return (dladm_errno2status(errno));
2458275SEric Cheng 	}
2468275SEric Cheng 
2478275SEric Cheng 	bzero(attr, sizeof (*attr));
2488275SEric Cheng 
2498275SEric Cheng 	flowinfo = (dld_flowinfo_t *)(void *)(ioc + 1);
2508275SEric Cheng 
2518275SEric Cheng 	attr->fa_linkid = flowinfo->fi_linkid;
2528275SEric Cheng 	bcopy(&flowinfo->fi_flowname, &attr->fa_flowname,
2538275SEric Cheng 	    sizeof (attr->fa_flowname));
2548275SEric Cheng 	bcopy(&flowinfo->fi_flow_desc, &attr->fa_flow_desc,
2558275SEric Cheng 	    sizeof (attr->fa_flow_desc));
2568275SEric Cheng 	bcopy(&flowinfo->fi_resource_props, &attr->fa_resource_props,
2578275SEric Cheng 	    sizeof (attr->fa_resource_props));
2588275SEric Cheng 
2598275SEric Cheng 	free(ioc);
2608275SEric Cheng 	return (DLADM_STATUS_OK);
2618275SEric Cheng }
2628275SEric Cheng 
2638275SEric Cheng /* ARGSUSED */
2648275SEric Cheng static dladm_status_t
2658453SAnurag.Maskey@Sun.COM do_get_maxbw(dladm_handle_t handle, const char *flow, char **prop_val,
2668453SAnurag.Maskey@Sun.COM     uint_t *val_cnt)
2678275SEric Cheng {
2688275SEric Cheng 	mac_resource_props_t	*mrp;
2698275SEric Cheng 	char 			buf[DLADM_STRSIZE];
2708275SEric Cheng 	dladm_flow_attr_t	fa;
2718275SEric Cheng 	dladm_status_t		status;
2728275SEric Cheng 
2738453SAnurag.Maskey@Sun.COM 	status = dladm_flow_info(handle, flow, &fa);
2748275SEric Cheng 	if (status != DLADM_STATUS_OK)
2758275SEric Cheng 		return (status);
2768275SEric Cheng 	mrp = &(fa.fa_resource_props);
2778275SEric Cheng 
2788275SEric Cheng 	*val_cnt = 1;
2798275SEric Cheng 	if (mrp->mrp_mask & MRP_MAXBW) {
2808275SEric Cheng 		(void) snprintf(prop_val[0], DLADM_STRSIZE, "%s",
2818275SEric Cheng 		    dladm_bw2str(mrp->mrp_maxbw, buf));
2828275SEric Cheng 	} else {
2838275SEric Cheng 		return (DLADM_STATUS_NOTSUP);
2848275SEric Cheng 	}
2858275SEric Cheng 	return (DLADM_STATUS_OK);
2868275SEric Cheng }
2878275SEric Cheng 
2888275SEric Cheng /* ARGSUSED */
2898275SEric Cheng static dladm_status_t
2908453SAnurag.Maskey@Sun.COM do_set_maxbw(dladm_handle_t handle, const char *flow, val_desc_t *vdp,
2918453SAnurag.Maskey@Sun.COM     uint_t val_cnt)
2928275SEric Cheng {
2938275SEric Cheng 	dld_ioc_modifyflow_t	attr;
2948275SEric Cheng 	mac_resource_props_t	mrp;
2958275SEric Cheng 	void			*val;
2968275SEric Cheng 
2978275SEric Cheng 	if (val_cnt != 1)
2988275SEric Cheng 		return (DLADM_STATUS_BADVALCNT);
2998275SEric Cheng 
3008275SEric Cheng 	bzero(&mrp, sizeof (mrp));
3018275SEric Cheng 	if (vdp != NULL && (val = (void *)vdp->vd_val) != NULL) {
3028275SEric Cheng 		bcopy(val, &mrp.mrp_maxbw, sizeof (int64_t));
3038275SEric Cheng 		free(val);
3048275SEric Cheng 	} else {
3058275SEric Cheng 		mrp.mrp_maxbw = MRP_MAXBW_RESETVAL;
3068275SEric Cheng 	}
3078275SEric Cheng 	mrp.mrp_mask = MRP_MAXBW;
3088275SEric Cheng 
3098275SEric Cheng 	bzero(&attr, sizeof (attr));
3108275SEric Cheng 	(void) strlcpy(attr.mf_name, flow, sizeof (attr.mf_name));
3118275SEric Cheng 	bcopy(&mrp, &attr.mf_resource_props, sizeof (mac_resource_props_t));
3128275SEric Cheng 
3138453SAnurag.Maskey@Sun.COM 	if (ioctl(dladm_dld_fd(handle), DLDIOC_MODIFYFLOW, &attr) < 0)
3148275SEric Cheng 		return (dladm_errno2status(errno));
3158275SEric Cheng 
3168275SEric Cheng 	return (DLADM_STATUS_OK);
3178275SEric Cheng }
3188275SEric Cheng 
3198275SEric Cheng /* ARGSUSED */
3208275SEric Cheng static dladm_status_t
3218275SEric Cheng do_check_maxbw(fprop_desc_t *pdp, char **prop_val, uint_t val_cnt,
3228275SEric Cheng     val_desc_t **vdpp)
3238275SEric Cheng {
3248275SEric Cheng 	uint64_t	*maxbw;
3258275SEric Cheng 	val_desc_t	*vdp = NULL;
3268275SEric Cheng 	dladm_status_t	status = DLADM_STATUS_OK;
3278275SEric Cheng 
3288275SEric Cheng 	if (val_cnt != 1)
3298275SEric Cheng 		return (DLADM_STATUS_BADVALCNT);
3308275SEric Cheng 
3318275SEric Cheng 	maxbw = malloc(sizeof (uint64_t));
3328275SEric Cheng 	if (maxbw == NULL)
3338275SEric Cheng 		return (DLADM_STATUS_NOMEM);
3348275SEric Cheng 
3358275SEric Cheng 	status = dladm_str2bw(*prop_val, maxbw);
3368275SEric Cheng 	if (status != DLADM_STATUS_OK) {
3378275SEric Cheng 		free(maxbw);
3388275SEric Cheng 		return (status);
3398275SEric Cheng 	}
3408275SEric Cheng 
3418275SEric Cheng 	if ((*maxbw < MRP_MAXBW_MINVAL) && (*maxbw != 0)) {
3428275SEric Cheng 		free(maxbw);
3438275SEric Cheng 		return (DLADM_STATUS_MINMAXBW);
3448275SEric Cheng 	}
3458275SEric Cheng 
3468275SEric Cheng 	vdp = malloc(sizeof (val_desc_t));
3478275SEric Cheng 	if (vdp == NULL) {
3488275SEric Cheng 		free(maxbw);
3498275SEric Cheng 		return (DLADM_STATUS_NOMEM);
3508275SEric Cheng 	}
3518275SEric Cheng 
3528275SEric Cheng 	vdp->vd_val = (uintptr_t)maxbw;
3538275SEric Cheng 	*vdpp = vdp;
3548275SEric Cheng 	return (DLADM_STATUS_OK);
3558275SEric Cheng }
3568275SEric Cheng 
3578275SEric Cheng /* ARGSUSED */
3588275SEric Cheng static dladm_status_t
3598453SAnurag.Maskey@Sun.COM do_get_priority(dladm_handle_t handle, const char *flow, char **prop_val,
3608453SAnurag.Maskey@Sun.COM     uint_t *val_cnt)
3618275SEric Cheng {
3628275SEric Cheng 	mac_resource_props_t	*mrp;
3638275SEric Cheng 	char 			buf[DLADM_STRSIZE];
3648275SEric Cheng 	dladm_flow_attr_t	fa;
3658275SEric Cheng 	dladm_status_t		status;
3668275SEric Cheng 
3678275SEric Cheng 	bzero(&fa, sizeof (dladm_flow_attr_t));
3688453SAnurag.Maskey@Sun.COM 	status = dladm_flow_info(handle, flow, &fa);
3698275SEric Cheng 	if (status != DLADM_STATUS_OK)
3708275SEric Cheng 		return (status);
3718275SEric Cheng 	mrp = &(fa.fa_resource_props);
3728275SEric Cheng 
3738275SEric Cheng 	*val_cnt = 1;
3748275SEric Cheng 	if (mrp->mrp_mask & MRP_PRIORITY) {
3758275SEric Cheng 		(void) snprintf(prop_val[0], DLADM_STRSIZE, "%s",
3768275SEric Cheng 		    dladm_pri2str(mrp->mrp_priority, buf));
3778275SEric Cheng 	} else {
3788275SEric Cheng 		return (DLADM_STATUS_NOTSUP);
3798275SEric Cheng 	}
3808275SEric Cheng 	return (DLADM_STATUS_OK);
3818275SEric Cheng }
3828275SEric Cheng 
3838275SEric Cheng /* ARGSUSED */
3848275SEric Cheng static dladm_status_t
3858453SAnurag.Maskey@Sun.COM do_set_priority(dladm_handle_t handle, const char *flow, val_desc_t *vdp,
3868453SAnurag.Maskey@Sun.COM     uint_t val_cnt)
3878275SEric Cheng {
3888275SEric Cheng 	dld_ioc_modifyflow_t	attr;
3898275SEric Cheng 	mac_resource_props_t	mrp;
3908275SEric Cheng 	void			*val;
3918275SEric Cheng 
3928275SEric Cheng 	if (val_cnt != 1)
3938275SEric Cheng 		return (DLADM_STATUS_BADVALCNT);
3948275SEric Cheng 
3958275SEric Cheng 	bzero(&mrp, sizeof (mrp));
3968275SEric Cheng 	if (vdp != NULL && (val = (void *)vdp->vd_val) != NULL) {
3978275SEric Cheng 		bcopy(val, &mrp.mrp_priority, sizeof (mac_priority_level_t));
3988275SEric Cheng 		free(val);
3998275SEric Cheng 	} else {
4008275SEric Cheng 		mrp.mrp_priority = MPL_RESET;
4018275SEric Cheng 	}
4028275SEric Cheng 	mrp.mrp_mask = MRP_PRIORITY;
4038275SEric Cheng 
4048275SEric Cheng 	bzero(&attr, sizeof (attr));
4058275SEric Cheng 	(void) strlcpy(attr.mf_name, flow, sizeof (attr.mf_name));
4068275SEric Cheng 	bcopy(&mrp, &attr.mf_resource_props, sizeof (mac_resource_props_t));
4078275SEric Cheng 
4088453SAnurag.Maskey@Sun.COM 	if (ioctl(dladm_dld_fd(handle), DLDIOC_MODIFYFLOW, &attr) < 0)
4098275SEric Cheng 		return (dladm_errno2status(errno));
4108275SEric Cheng 
4118275SEric Cheng 	return (DLADM_STATUS_OK);
4128275SEric Cheng }
4138275SEric Cheng 
4148275SEric Cheng /* ARGSUSED */
4158275SEric Cheng static dladm_status_t
4168275SEric Cheng do_check_priority(fprop_desc_t *pdp, char **prop_val, uint_t val_cnt,
4178275SEric Cheng     val_desc_t **vdpp)
4188275SEric Cheng {
4198275SEric Cheng 	mac_priority_level_t	*pri;
4208275SEric Cheng 	val_desc_t	*vdp = NULL;
4218275SEric Cheng 	dladm_status_t	status = DLADM_STATUS_OK;
4228275SEric Cheng 
4238275SEric Cheng 	if (val_cnt != 1)
4248275SEric Cheng 		return (DLADM_STATUS_BADVALCNT);
4258275SEric Cheng 
4268275SEric Cheng 	pri = malloc(sizeof (mac_priority_level_t));
4278275SEric Cheng 	if (pri == NULL)
4288275SEric Cheng 		return (DLADM_STATUS_NOMEM);
4298275SEric Cheng 
4308275SEric Cheng 	status = dladm_str2pri(*prop_val, pri);
4318275SEric Cheng 	if (status != DLADM_STATUS_OK) {
4328275SEric Cheng 		free(pri);
4338275SEric Cheng 		return (status);
4348275SEric Cheng 	}
4358275SEric Cheng 
4368275SEric Cheng 	if (*pri == -1) {
4378275SEric Cheng 		free(pri);
4388275SEric Cheng 		return (DLADM_STATUS_BADVAL);
4398275SEric Cheng 	}
4408275SEric Cheng 
4418275SEric Cheng 	vdp = malloc(sizeof (val_desc_t));
4428275SEric Cheng 	if (vdp == NULL) {
4438275SEric Cheng 		free(pri);
4448275SEric Cheng 		return (DLADM_STATUS_NOMEM);
4458275SEric Cheng 	}
4468275SEric Cheng 
4478275SEric Cheng 	vdp->vd_val = (uintptr_t)pri;
4488275SEric Cheng 	*vdpp = vdp;
4498275SEric Cheng 	return (DLADM_STATUS_OK);
4508275SEric Cheng }
4518275SEric Cheng 
4528275SEric Cheng static dladm_status_t
4538275SEric Cheng flow_proplist_check(dladm_arg_list_t *proplist)
4548275SEric Cheng {
4558275SEric Cheng 	int		i, j;
4568275SEric Cheng 	boolean_t	matched;
4578275SEric Cheng 
4588275SEric Cheng 	for (i = 0; i < proplist->al_count; i++) {
4598275SEric Cheng 		matched = B_FALSE;
4608275SEric Cheng 		for (j = 0; j < DLADM_MAX_FLOWPROPS; j++) {
4618275SEric Cheng 			if (strcmp(proplist->al_info[i].ai_name,
4628275SEric Cheng 			    prop_table[j].pd_name) == 0)
4638275SEric Cheng 				matched = B_TRUE;
4648275SEric Cheng 			}
4658275SEric Cheng 		if (!matched)
4668275SEric Cheng 			return (DLADM_STATUS_BADPROP);
4678275SEric Cheng 	}
4688275SEric Cheng 	return (DLADM_STATUS_OK);
4698275SEric Cheng 
4708275SEric Cheng }
4718275SEric Cheng 
4728275SEric Cheng dladm_status_t
4738275SEric Cheng dladm_parse_flow_props(char *str, dladm_arg_list_t **listp, boolean_t novalues)
4748275SEric Cheng {
4758275SEric Cheng 	dladm_status_t	status;
4768275SEric Cheng 
4778275SEric Cheng 	status = dladm_parse_args(str, listp, novalues);
4788275SEric Cheng 	if (status != DLADM_STATUS_OK)
4798275SEric Cheng 		return (status);
4808275SEric Cheng 
4819055SMichael.Lim@Sun.COM 	if (*listp != NULL && (status = flow_proplist_check(*listp)
4829055SMichael.Lim@Sun.COM 	    != DLADM_STATUS_OK)) {
4838275SEric Cheng 		dladm_free_props(*listp);
4848275SEric Cheng 		return (status);
4858275SEric Cheng 	}
4868275SEric Cheng 
4878275SEric Cheng 	return (DLADM_STATUS_OK);
4888275SEric Cheng }
4898275SEric Cheng 
4908275SEric Cheng /*
4918275SEric Cheng  * Retrieve the named property from a proplist, check the value and
4928275SEric Cheng  * convert to a kernel structure.
4938275SEric Cheng  */
4948275SEric Cheng static dladm_status_t
4958275SEric Cheng i_dladm_flow_proplist_extract_one(dladm_arg_list_t *proplist,
496*10734SEric Cheng     const char *name, void *arg)
4978275SEric Cheng {
4988275SEric Cheng 	dladm_status_t		status;
4998275SEric Cheng 	dladm_arg_info_t	*aip = NULL;
5008275SEric Cheng 	int			i, j;
5018275SEric Cheng 
5028275SEric Cheng 	/* Find named property in proplist */
5038275SEric Cheng 	for (i = 0; i < proplist->al_count; i++) {
5048275SEric Cheng 		aip = &proplist->al_info[i];
5058275SEric Cheng 		if (strcasecmp(aip->ai_name, name) == 0)
5068275SEric Cheng 			break;
5078275SEric Cheng 	}
5088275SEric Cheng 
5098275SEric Cheng 	/* Property not in list */
5108275SEric Cheng 	if (i == proplist->al_count)
5118275SEric Cheng 		return (DLADM_STATUS_OK);
5128275SEric Cheng 
5138275SEric Cheng 	for (i = 0; i < DLADM_MAX_FLOWPROPS; i++) {
5148275SEric Cheng 		fprop_desc_t	*pdp = &prop_table[i];
5158275SEric Cheng 		val_desc_t	*vdp;
5168275SEric Cheng 
5178275SEric Cheng 		vdp = malloc(sizeof (val_desc_t) * aip->ai_count);
5188275SEric Cheng 		if (vdp == NULL)
5198275SEric Cheng 			return (DLADM_STATUS_NOMEM);
5208275SEric Cheng 
5218275SEric Cheng 		if (strcasecmp(aip->ai_name, pdp->pd_name) != 0)
5228275SEric Cheng 			continue;
5238275SEric Cheng 
5248275SEric Cheng 		if (aip->ai_val == NULL)
5258275SEric Cheng 			return (DLADM_STATUS_BADARG);
5268275SEric Cheng 
5278275SEric Cheng 		/* Check property value */
5288275SEric Cheng 		if (pdp->pd_check != NULL) {
5298275SEric Cheng 			status = pdp->pd_check(pdp, aip->ai_val,
5308275SEric Cheng 			    aip->ai_count, &vdp);
5318275SEric Cheng 		} else {
5328275SEric Cheng 			status = DLADM_STATUS_BADARG;
5338275SEric Cheng 		}
5348275SEric Cheng 
5358275SEric Cheng 		if (status != DLADM_STATUS_OK)
5368275SEric Cheng 			return (status);
5378275SEric Cheng 
5388275SEric Cheng 		for (j = 0; j < DLADM_MAX_RSRC_PROP; j++) {
5398275SEric Cheng 			resource_prop_t	*rpp = &rsrc_prop_table[j];
5408275SEric Cheng 
5418275SEric Cheng 			if (strcasecmp(aip->ai_name, rpp->rp_name) != 0)
5428275SEric Cheng 				continue;
5438275SEric Cheng 
5448275SEric Cheng 			/* Extract kernel structure */
5458275SEric Cheng 			if (rpp->rp_extract != NULL) {
546*10734SEric Cheng 				status = rpp->rp_extract(vdp,
547*10734SEric Cheng 				    aip->ai_count, arg);
5488275SEric Cheng 			} else {
5498275SEric Cheng 				status = DLADM_STATUS_BADARG;
5508275SEric Cheng 			}
5518275SEric Cheng 			break;
5528275SEric Cheng 		}
5538275SEric Cheng 
5548275SEric Cheng 		if (status != DLADM_STATUS_OK)
5558275SEric Cheng 			return (status);
5568275SEric Cheng 
5578275SEric Cheng 		break;
5588275SEric Cheng 	}
5598275SEric Cheng 	return (status);
5608275SEric Cheng }
5618275SEric Cheng 
5628275SEric Cheng /*
5638275SEric Cheng  * Extract properties from a proplist and convert to mac_resource_props_t.
5648275SEric Cheng  */
5658275SEric Cheng dladm_status_t
5668275SEric Cheng dladm_flow_proplist_extract(dladm_arg_list_t *proplist,
5678275SEric Cheng     mac_resource_props_t *mrp)
5688275SEric Cheng {
5698275SEric Cheng 	dladm_status_t	status = DLADM_STATUS_OK;
5708275SEric Cheng 
5718275SEric Cheng 	status = i_dladm_flow_proplist_extract_one(proplist, "maxbw", mrp);
5728275SEric Cheng 	if (status != DLADM_STATUS_OK)
5738275SEric Cheng 		return (status);
5748275SEric Cheng 	status = i_dladm_flow_proplist_extract_one(proplist, "priority", mrp);
5758275SEric Cheng 	if (status != DLADM_STATUS_OK)
5768275SEric Cheng 		return (status);
5778275SEric Cheng 	return (status);
5788275SEric Cheng }
5798275SEric Cheng 
5808275SEric Cheng dladm_status_t
5818453SAnurag.Maskey@Sun.COM i_dladm_set_flow_proplist_db(dladm_handle_t handle, char *flow,
5828453SAnurag.Maskey@Sun.COM     dladm_arg_list_t *proplist)
5838275SEric Cheng {
5848275SEric Cheng 	dladm_status_t		status, ssave = DLADM_STATUS_OK;
5858275SEric Cheng 	dladm_arg_info_t	ai;
5868275SEric Cheng 	int			i;
5878275SEric Cheng 
5888275SEric Cheng 	for (i = 0; i < proplist->al_count; i++) {
5898275SEric Cheng 		ai = proplist->al_info[i];
5908453SAnurag.Maskey@Sun.COM 		status = i_dladm_set_flowprop_db(handle, flow, ai.ai_name,
5918275SEric Cheng 		    ai.ai_val, ai.ai_count);
5928275SEric Cheng 		if (status != DLADM_STATUS_OK)
5938275SEric Cheng 			ssave = status;
5948275SEric Cheng 	}
5958275SEric Cheng 	return (ssave);
5968275SEric Cheng }
597