1*8275SEric Cheng /*
2*8275SEric Cheng  * CDDL HEADER START
3*8275SEric Cheng  *
4*8275SEric Cheng  * The contents of this file are subject to the terms of the
5*8275SEric Cheng  * Common Development and Distribution License (the "License").
6*8275SEric Cheng  * You may not use this file except in compliance with the License.
7*8275SEric Cheng  *
8*8275SEric Cheng  * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
9*8275SEric Cheng  * or http://www.opensolaris.org/os/licensing.
10*8275SEric Cheng  * See the License for the specific language governing permissions
11*8275SEric Cheng  * and limitations under the License.
12*8275SEric Cheng  *
13*8275SEric Cheng  * When distributing Covered Code, include this CDDL HEADER in each
14*8275SEric Cheng  * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
15*8275SEric Cheng  * If applicable, add the following below this CDDL HEADER, with the
16*8275SEric Cheng  * fields enclosed by brackets "[]" replaced with your own identifying
17*8275SEric Cheng  * information: Portions Copyright [yyyy] [name of copyright owner]
18*8275SEric Cheng  *
19*8275SEric Cheng  * CDDL HEADER END
20*8275SEric Cheng  */
21*8275SEric Cheng /*
22*8275SEric Cheng  * Copyright 2008 Sun Microsystems, Inc.  All rights reserved.
23*8275SEric Cheng  * Use is subject to license terms.
24*8275SEric Cheng  */
25*8275SEric Cheng 
26*8275SEric Cheng #include <stdlib.h>
27*8275SEric Cheng #include <strings.h>
28*8275SEric Cheng #include <errno.h>
29*8275SEric Cheng #include <ctype.h>
30*8275SEric Cheng #include <sys/types.h>
31*8275SEric Cheng #include <sys/stat.h>
32*8275SEric Cheng #include <sys/dld.h>
33*8275SEric Cheng #include <fcntl.h>
34*8275SEric Cheng #include <unistd.h>
35*8275SEric Cheng #include <libdevinfo.h>
36*8275SEric Cheng #include <libdladm_impl.h>
37*8275SEric Cheng #include <libdlflow.h>
38*8275SEric Cheng #include <libdlflow_impl.h>
39*8275SEric Cheng #include <libintl.h>
40*8275SEric Cheng 
41*8275SEric Cheng #include <dlfcn.h>
42*8275SEric Cheng #include <link.h>
43*8275SEric Cheng 
44*8275SEric Cheng /*
45*8275SEric Cheng  * XXX duplicate define
46*8275SEric Cheng  */
47*8275SEric Cheng #define	DLADM_PROP_VAL_MAX	32
48*8275SEric Cheng 
49*8275SEric Cheng static dladm_status_t	i_dladm_set_flowprop_db(const char *, const char *,
50*8275SEric Cheng 			    char **, uint_t);
51*8275SEric Cheng static dladm_status_t	i_dladm_get_flowprop_db(const char *, const char *,
52*8275SEric Cheng 			    char **, uint_t *);
53*8275SEric Cheng 
54*8275SEric Cheng static fpd_getf_t	do_get_maxbw;
55*8275SEric Cheng static fpd_setf_t	do_set_maxbw;
56*8275SEric Cheng static fpd_checkf_t	do_check_maxbw;
57*8275SEric Cheng 
58*8275SEric Cheng static fpd_getf_t	do_get_priority;
59*8275SEric Cheng static fpd_setf_t	do_set_priority;
60*8275SEric Cheng static fpd_checkf_t	do_check_priority;
61*8275SEric Cheng 
62*8275SEric Cheng static fprop_desc_t	prop_table[] = {
63*8275SEric Cheng 	{ "maxbw",	{ "", NULL }, NULL, 0, B_FALSE,
64*8275SEric Cheng 	    do_set_maxbw, NULL,
65*8275SEric Cheng 	    do_get_maxbw, do_check_maxbw},
66*8275SEric Cheng 	{ "priority",	{ "", NULL }, NULL, 0, B_FALSE,
67*8275SEric Cheng 	    do_set_priority, NULL,
68*8275SEric Cheng 	    do_get_priority, do_check_priority}
69*8275SEric Cheng };
70*8275SEric Cheng 
71*8275SEric Cheng #define	DLADM_MAX_FLOWPROPS	(sizeof (prop_table) / sizeof (fprop_desc_t))
72*8275SEric Cheng 
73*8275SEric Cheng static prop_table_t	prop_tbl = {
74*8275SEric Cheng 	prop_table,
75*8275SEric Cheng 	DLADM_MAX_FLOWPROPS
76*8275SEric Cheng };
77*8275SEric Cheng 
78*8275SEric Cheng static resource_prop_t rsrc_prop_table[] = {
79*8275SEric Cheng 	{"maxbw",	do_extract_maxbw},
80*8275SEric Cheng 	{"priority",	do_extract_priority}
81*8275SEric Cheng };
82*8275SEric Cheng #define	DLADM_MAX_RSRC_PROP (sizeof (rsrc_prop_table) / \
83*8275SEric Cheng 	sizeof (resource_prop_t))
84*8275SEric Cheng 
85*8275SEric Cheng static dladm_status_t	flow_proplist_check(dladm_arg_list_t *);
86*8275SEric Cheng 
87*8275SEric Cheng dladm_status_t
88*8275SEric Cheng dladm_set_flowprop(const char *flow, const char *prop_name, char **prop_val,
89*8275SEric Cheng     uint_t val_cnt, uint_t flags, char **errprop)
90*8275SEric Cheng {
91*8275SEric Cheng 	dladm_status_t		status = DLADM_STATUS_BADARG;
92*8275SEric Cheng 
93*8275SEric Cheng 	if (flow == NULL || (prop_val == NULL && val_cnt > 0) ||
94*8275SEric Cheng 	    (prop_val != NULL && val_cnt == 0) || flags == 0)
95*8275SEric Cheng 		return (DLADM_STATUS_BADARG);
96*8275SEric Cheng 
97*8275SEric Cheng 	if ((flags & DLADM_OPT_ACTIVE) != 0) {
98*8275SEric Cheng 		status = i_dladm_set_prop_temp(flow, prop_name, prop_val,
99*8275SEric Cheng 		    val_cnt, flags, errprop, &prop_tbl);
100*8275SEric Cheng 		if (status == DLADM_STATUS_TEMPONLY &&
101*8275SEric Cheng 		    (flags & DLADM_OPT_PERSIST) != 0)
102*8275SEric Cheng 			return (DLADM_STATUS_TEMPONLY);
103*8275SEric Cheng 		if (status != DLADM_STATUS_OK)
104*8275SEric Cheng 			return (status);
105*8275SEric Cheng 	}
106*8275SEric Cheng 	if ((flags & DLADM_OPT_PERSIST) != 0) {
107*8275SEric Cheng 		if (i_dladm_is_prop_temponly(prop_name, errprop, &prop_tbl))
108*8275SEric Cheng 			return (DLADM_STATUS_TEMPONLY);
109*8275SEric Cheng 
110*8275SEric Cheng 		status = i_dladm_set_flowprop_db(flow, prop_name,
111*8275SEric Cheng 		    prop_val, val_cnt);
112*8275SEric Cheng 	}
113*8275SEric Cheng 	return (status);
114*8275SEric Cheng }
115*8275SEric Cheng 
116*8275SEric Cheng dladm_status_t
117*8275SEric Cheng dladm_walk_flowprop(int (*func)(void *, const char *), const char *flow,
118*8275SEric Cheng     void *arg)
119*8275SEric Cheng {
120*8275SEric Cheng 	int	i;
121*8275SEric Cheng 
122*8275SEric Cheng 	if (flow == NULL || func == NULL)
123*8275SEric Cheng 		return (DLADM_STATUS_BADARG);
124*8275SEric Cheng 
125*8275SEric Cheng 	/* Then show data-flow properties if there are any */
126*8275SEric Cheng 	for (i = 0; i < DLADM_MAX_FLOWPROPS; i++) {
127*8275SEric Cheng 		if (func(arg, prop_table[i].pd_name) != DLADM_WALK_CONTINUE)
128*8275SEric Cheng 			break;
129*8275SEric Cheng 	}
130*8275SEric Cheng 	return (DLADM_STATUS_OK);
131*8275SEric Cheng }
132*8275SEric Cheng 
133*8275SEric Cheng dladm_status_t
134*8275SEric Cheng dladm_get_flowprop(const char *flow, uint32_t type,
135*8275SEric Cheng     const char *prop_name, char **prop_val, uint_t *val_cntp)
136*8275SEric Cheng {
137*8275SEric Cheng 	dladm_status_t status;
138*8275SEric Cheng 
139*8275SEric Cheng 	if (flow == NULL || prop_name == NULL || prop_val == NULL ||
140*8275SEric Cheng 	    val_cntp == NULL || *val_cntp == 0)
141*8275SEric Cheng 		return (DLADM_STATUS_BADARG);
142*8275SEric Cheng 
143*8275SEric Cheng 	if (type == DLADM_PROP_VAL_PERSISTENT) {
144*8275SEric Cheng 		if (i_dladm_is_prop_temponly(prop_name, NULL, &prop_tbl))
145*8275SEric Cheng 			return (DLADM_STATUS_TEMPONLY);
146*8275SEric Cheng 		return (i_dladm_get_flowprop_db(flow, prop_name,
147*8275SEric Cheng 		    prop_val, val_cntp));
148*8275SEric Cheng 	}
149*8275SEric Cheng 
150*8275SEric Cheng 	status = i_dladm_get_prop_temp(flow, type, prop_name,
151*8275SEric Cheng 	    prop_val, val_cntp, &prop_tbl);
152*8275SEric Cheng 	if (status != DLADM_STATUS_NOTFOUND)
153*8275SEric Cheng 		return (status);
154*8275SEric Cheng 
155*8275SEric Cheng 	return (DLADM_STATUS_BADARG);
156*8275SEric Cheng }
157*8275SEric Cheng 
158*8275SEric Cheng #define	FLOWPROP_RW_DB(statep, writeop) \
159*8275SEric Cheng 	(i_dladm_rw_db("/etc/dladm/flowprop.conf", \
160*8275SEric Cheng 	S_IRUSR | S_IWUSR | S_IRGRP | S_IROTH, process_prop_db, \
161*8275SEric Cheng 	(statep), (writeop)))
162*8275SEric Cheng 
163*8275SEric Cheng static dladm_status_t
164*8275SEric Cheng i_dladm_set_flowprop_db(const char *flow, const char *prop_name,
165*8275SEric Cheng     char **prop_val, uint_t val_cnt)
166*8275SEric Cheng {
167*8275SEric Cheng 	prop_db_state_t	state;
168*8275SEric Cheng 
169*8275SEric Cheng 	state.ls_op = process_prop_set;
170*8275SEric Cheng 	state.ls_name = flow;
171*8275SEric Cheng 	state.ls_propname = prop_name;
172*8275SEric Cheng 	state.ls_propval = prop_val;
173*8275SEric Cheng 	state.ls_valcntp = &val_cnt;
174*8275SEric Cheng 	state.ls_initop = NULL;
175*8275SEric Cheng 
176*8275SEric Cheng 	return (FLOWPROP_RW_DB(&state, B_TRUE));
177*8275SEric Cheng }
178*8275SEric Cheng 
179*8275SEric Cheng static dladm_status_t
180*8275SEric Cheng i_dladm_get_flowprop_db(const char *flow, const char *prop_name,
181*8275SEric Cheng     char **prop_val, uint_t *val_cntp)
182*8275SEric Cheng {
183*8275SEric Cheng 	prop_db_state_t	state;
184*8275SEric Cheng 
185*8275SEric Cheng 	state.ls_op = process_prop_get;
186*8275SEric Cheng 	state.ls_name = flow;
187*8275SEric Cheng 	state.ls_propname = prop_name;
188*8275SEric Cheng 	state.ls_propval = prop_val;
189*8275SEric Cheng 	state.ls_valcntp = val_cntp;
190*8275SEric Cheng 	state.ls_initop = NULL;
191*8275SEric Cheng 
192*8275SEric Cheng 	return (FLOWPROP_RW_DB(&state, B_FALSE));
193*8275SEric Cheng }
194*8275SEric Cheng 
195*8275SEric Cheng dladm_status_t
196*8275SEric Cheng i_dladm_init_flowprop_db(void)
197*8275SEric Cheng {
198*8275SEric Cheng 	prop_db_state_t	state;
199*8275SEric Cheng 
200*8275SEric Cheng 	state.ls_op = process_prop_init;
201*8275SEric Cheng 	state.ls_name = NULL;
202*8275SEric Cheng 	state.ls_propname = NULL;
203*8275SEric Cheng 	state.ls_propval = NULL;
204*8275SEric Cheng 	state.ls_valcntp = NULL;
205*8275SEric Cheng 	state.ls_initop = dladm_set_flowprop;
206*8275SEric Cheng 
207*8275SEric Cheng 	return (FLOWPROP_RW_DB(&state, B_FALSE));
208*8275SEric Cheng }
209*8275SEric Cheng 
210*8275SEric Cheng #define	MIN_INFO_SIZE (4 * 1024)
211*8275SEric Cheng 
212*8275SEric Cheng dladm_status_t
213*8275SEric Cheng dladm_flow_info(const char *flow, dladm_flow_attr_t *attr)
214*8275SEric Cheng {
215*8275SEric Cheng 	dld_ioc_walkflow_t	*ioc;
216*8275SEric Cheng 	int			bufsize, fd;
217*8275SEric Cheng 	dld_flowinfo_t		*flowinfo;
218*8275SEric Cheng 
219*8275SEric Cheng 	if ((flow == NULL) || (attr == NULL))
220*8275SEric Cheng 		return (DLADM_STATUS_BADARG);
221*8275SEric Cheng 
222*8275SEric Cheng 	if ((fd = open(DLD_CONTROL_DEV, O_RDWR)) < 0)
223*8275SEric Cheng 		return (dladm_errno2status(errno));
224*8275SEric Cheng 
225*8275SEric Cheng 	bufsize = MIN_INFO_SIZE;
226*8275SEric Cheng 	if ((ioc = calloc(1, bufsize)) == NULL) {
227*8275SEric Cheng 		(void) close(fd);
228*8275SEric Cheng 		return (dladm_errno2status(errno));
229*8275SEric Cheng 	}
230*8275SEric Cheng 
231*8275SEric Cheng 	(void) strlcpy(ioc->wf_name, flow, sizeof (ioc->wf_name));
232*8275SEric Cheng 	ioc->wf_len = bufsize - sizeof (*ioc);
233*8275SEric Cheng 
234*8275SEric Cheng 	while (ioctl(fd, DLDIOC_WALKFLOW, ioc) < 0) {
235*8275SEric Cheng 		if (errno == ENOSPC) {
236*8275SEric Cheng 			bufsize *= 2;
237*8275SEric Cheng 			ioc = realloc(ioc, bufsize);
238*8275SEric Cheng 			if (ioc != NULL) {
239*8275SEric Cheng 				(void) strlcpy(ioc->wf_name, flow,
240*8275SEric Cheng 				    MAXNAMELEN);
241*8275SEric Cheng 				ioc->wf_len = bufsize - sizeof (*ioc);
242*8275SEric Cheng 				continue;
243*8275SEric Cheng 			}
244*8275SEric Cheng 		}
245*8275SEric Cheng 		free(ioc);
246*8275SEric Cheng 		(void) close(fd);
247*8275SEric Cheng 		return (dladm_errno2status(errno));
248*8275SEric Cheng 	}
249*8275SEric Cheng 
250*8275SEric Cheng 	bzero(attr, sizeof (*attr));
251*8275SEric Cheng 
252*8275SEric Cheng 	flowinfo = (dld_flowinfo_t *)(void *)(ioc + 1);
253*8275SEric Cheng 
254*8275SEric Cheng 	attr->fa_linkid = flowinfo->fi_linkid;
255*8275SEric Cheng 	bcopy(&flowinfo->fi_flowname, &attr->fa_flowname,
256*8275SEric Cheng 	    sizeof (attr->fa_flowname));
257*8275SEric Cheng 	bcopy(&flowinfo->fi_flow_desc, &attr->fa_flow_desc,
258*8275SEric Cheng 	    sizeof (attr->fa_flow_desc));
259*8275SEric Cheng 	bcopy(&flowinfo->fi_resource_props, &attr->fa_resource_props,
260*8275SEric Cheng 	    sizeof (attr->fa_resource_props));
261*8275SEric Cheng 
262*8275SEric Cheng 	free(ioc);
263*8275SEric Cheng 	(void) close(fd);
264*8275SEric Cheng 	return (DLADM_STATUS_OK);
265*8275SEric Cheng }
266*8275SEric Cheng 
267*8275SEric Cheng /* ARGSUSED */
268*8275SEric Cheng static dladm_status_t
269*8275SEric Cheng do_get_maxbw(const char *flow, char **prop_val, uint_t *val_cnt)
270*8275SEric Cheng {
271*8275SEric Cheng 	mac_resource_props_t	*mrp;
272*8275SEric Cheng 	char 			buf[DLADM_STRSIZE];
273*8275SEric Cheng 	dladm_flow_attr_t	fa;
274*8275SEric Cheng 	dladm_status_t		status;
275*8275SEric Cheng 
276*8275SEric Cheng 	status = dladm_flow_info(flow, &fa);
277*8275SEric Cheng 	if (status != DLADM_STATUS_OK)
278*8275SEric Cheng 		return (status);
279*8275SEric Cheng 	mrp = &(fa.fa_resource_props);
280*8275SEric Cheng 
281*8275SEric Cheng 	*val_cnt = 1;
282*8275SEric Cheng 	if (mrp->mrp_mask & MRP_MAXBW) {
283*8275SEric Cheng 		(void) snprintf(prop_val[0], DLADM_STRSIZE, "%s",
284*8275SEric Cheng 		    dladm_bw2str(mrp->mrp_maxbw, buf));
285*8275SEric Cheng 	} else {
286*8275SEric Cheng 		return (DLADM_STATUS_NOTSUP);
287*8275SEric Cheng 	}
288*8275SEric Cheng 	return (DLADM_STATUS_OK);
289*8275SEric Cheng }
290*8275SEric Cheng 
291*8275SEric Cheng /* ARGSUSED */
292*8275SEric Cheng static dladm_status_t
293*8275SEric Cheng do_set_maxbw(const char *flow, val_desc_t *vdp, uint_t val_cnt)
294*8275SEric Cheng {
295*8275SEric Cheng 	dld_ioc_modifyflow_t	attr;
296*8275SEric Cheng 	int			fd;
297*8275SEric Cheng 	mac_resource_props_t	mrp;
298*8275SEric Cheng 	void			*val;
299*8275SEric Cheng 
300*8275SEric Cheng 	if (val_cnt != 1)
301*8275SEric Cheng 		return (DLADM_STATUS_BADVALCNT);
302*8275SEric Cheng 
303*8275SEric Cheng 	bzero(&mrp, sizeof (mrp));
304*8275SEric Cheng 	if (vdp != NULL && (val = (void *)vdp->vd_val) != NULL) {
305*8275SEric Cheng 		bcopy(val, &mrp.mrp_maxbw, sizeof (int64_t));
306*8275SEric Cheng 		free(val);
307*8275SEric Cheng 	} else {
308*8275SEric Cheng 		mrp.mrp_maxbw = MRP_MAXBW_RESETVAL;
309*8275SEric Cheng 	}
310*8275SEric Cheng 	mrp.mrp_mask = MRP_MAXBW;
311*8275SEric Cheng 
312*8275SEric Cheng 	bzero(&attr, sizeof (attr));
313*8275SEric Cheng 	(void) strlcpy(attr.mf_name, flow, sizeof (attr.mf_name));
314*8275SEric Cheng 	bcopy(&mrp, &attr.mf_resource_props, sizeof (mac_resource_props_t));
315*8275SEric Cheng 
316*8275SEric Cheng 	fd = open(DLD_CONTROL_DEV, O_RDWR);
317*8275SEric Cheng 	if (fd < 0) {
318*8275SEric Cheng 		return (dladm_errno2status(errno));
319*8275SEric Cheng 	}
320*8275SEric Cheng 
321*8275SEric Cheng 	if (ioctl(fd, DLDIOC_MODIFYFLOW, &attr) < 0) {
322*8275SEric Cheng 		(void) close(fd);
323*8275SEric Cheng 		return (dladm_errno2status(errno));
324*8275SEric Cheng 	}
325*8275SEric Cheng 	(void) close(fd);
326*8275SEric Cheng 	return (DLADM_STATUS_OK);
327*8275SEric Cheng }
328*8275SEric Cheng 
329*8275SEric Cheng /* ARGSUSED */
330*8275SEric Cheng static dladm_status_t
331*8275SEric Cheng do_check_maxbw(fprop_desc_t *pdp, char **prop_val, uint_t val_cnt,
332*8275SEric Cheng     val_desc_t **vdpp)
333*8275SEric Cheng {
334*8275SEric Cheng 	uint64_t	*maxbw;
335*8275SEric Cheng 	val_desc_t	*vdp = NULL;
336*8275SEric Cheng 	dladm_status_t	status = DLADM_STATUS_OK;
337*8275SEric Cheng 
338*8275SEric Cheng 	if (val_cnt != 1)
339*8275SEric Cheng 		return (DLADM_STATUS_BADVALCNT);
340*8275SEric Cheng 
341*8275SEric Cheng 	maxbw = malloc(sizeof (uint64_t));
342*8275SEric Cheng 	if (maxbw == NULL)
343*8275SEric Cheng 		return (DLADM_STATUS_NOMEM);
344*8275SEric Cheng 
345*8275SEric Cheng 	status = dladm_str2bw(*prop_val, maxbw);
346*8275SEric Cheng 	if (status != DLADM_STATUS_OK) {
347*8275SEric Cheng 		free(maxbw);
348*8275SEric Cheng 		return (status);
349*8275SEric Cheng 	}
350*8275SEric Cheng 
351*8275SEric Cheng 	if ((*maxbw < MRP_MAXBW_MINVAL) && (*maxbw != 0)) {
352*8275SEric Cheng 		free(maxbw);
353*8275SEric Cheng 		return (DLADM_STATUS_MINMAXBW);
354*8275SEric Cheng 	}
355*8275SEric Cheng 
356*8275SEric Cheng 	vdp = malloc(sizeof (val_desc_t));
357*8275SEric Cheng 	if (vdp == NULL) {
358*8275SEric Cheng 		free(maxbw);
359*8275SEric Cheng 		return (DLADM_STATUS_NOMEM);
360*8275SEric Cheng 	}
361*8275SEric Cheng 
362*8275SEric Cheng 	vdp->vd_val = (uintptr_t)maxbw;
363*8275SEric Cheng 	*vdpp = vdp;
364*8275SEric Cheng 	return (DLADM_STATUS_OK);
365*8275SEric Cheng }
366*8275SEric Cheng 
367*8275SEric Cheng /* ARGSUSED */
368*8275SEric Cheng static dladm_status_t
369*8275SEric Cheng do_get_priority(const char *flow, char **prop_val, uint_t *val_cnt)
370*8275SEric Cheng {
371*8275SEric Cheng 	mac_resource_props_t	*mrp;
372*8275SEric Cheng 	char 			buf[DLADM_STRSIZE];
373*8275SEric Cheng 	dladm_flow_attr_t	fa;
374*8275SEric Cheng 	dladm_status_t		status;
375*8275SEric Cheng 
376*8275SEric Cheng 	bzero(&fa, sizeof (dladm_flow_attr_t));
377*8275SEric Cheng 	status = dladm_flow_info(flow, &fa);
378*8275SEric Cheng 	if (status != DLADM_STATUS_OK)
379*8275SEric Cheng 		return (status);
380*8275SEric Cheng 	mrp = &(fa.fa_resource_props);
381*8275SEric Cheng 
382*8275SEric Cheng 	*val_cnt = 1;
383*8275SEric Cheng 	if (mrp->mrp_mask & MRP_PRIORITY) {
384*8275SEric Cheng 		(void) snprintf(prop_val[0], DLADM_STRSIZE, "%s",
385*8275SEric Cheng 		    dladm_pri2str(mrp->mrp_priority, buf));
386*8275SEric Cheng 	} else {
387*8275SEric Cheng 		return (DLADM_STATUS_NOTSUP);
388*8275SEric Cheng 	}
389*8275SEric Cheng 	return (DLADM_STATUS_OK);
390*8275SEric Cheng }
391*8275SEric Cheng 
392*8275SEric Cheng /* ARGSUSED */
393*8275SEric Cheng static dladm_status_t
394*8275SEric Cheng do_set_priority(const char *flow, val_desc_t *vdp, uint_t val_cnt)
395*8275SEric Cheng {
396*8275SEric Cheng 	dld_ioc_modifyflow_t	attr;
397*8275SEric Cheng 	int			fd;
398*8275SEric Cheng 	mac_resource_props_t	mrp;
399*8275SEric Cheng 	void			*val;
400*8275SEric Cheng 
401*8275SEric Cheng 	if (val_cnt != 1)
402*8275SEric Cheng 		return (DLADM_STATUS_BADVALCNT);
403*8275SEric Cheng 
404*8275SEric Cheng 	bzero(&mrp, sizeof (mrp));
405*8275SEric Cheng 	if (vdp != NULL && (val = (void *)vdp->vd_val) != NULL) {
406*8275SEric Cheng 		bcopy(val, &mrp.mrp_priority, sizeof (mac_priority_level_t));
407*8275SEric Cheng 		free(val);
408*8275SEric Cheng 	} else {
409*8275SEric Cheng 		mrp.mrp_priority = MPL_RESET;
410*8275SEric Cheng 	}
411*8275SEric Cheng 	mrp.mrp_mask = MRP_PRIORITY;
412*8275SEric Cheng 
413*8275SEric Cheng 	bzero(&attr, sizeof (attr));
414*8275SEric Cheng 	(void) strlcpy(attr.mf_name, flow, sizeof (attr.mf_name));
415*8275SEric Cheng 	bcopy(&mrp, &attr.mf_resource_props, sizeof (mac_resource_props_t));
416*8275SEric Cheng 
417*8275SEric Cheng 	fd = open(DLD_CONTROL_DEV, O_RDWR);
418*8275SEric Cheng 	if (fd < 0) {
419*8275SEric Cheng 		return (dladm_errno2status(errno));
420*8275SEric Cheng 	}
421*8275SEric Cheng 
422*8275SEric Cheng 	if (ioctl(fd, DLDIOC_MODIFYFLOW, &attr) < 0) {
423*8275SEric Cheng 		(void) close(fd);
424*8275SEric Cheng 		return (dladm_errno2status(errno));
425*8275SEric Cheng 	}
426*8275SEric Cheng 	(void) close(fd);
427*8275SEric Cheng 	return (DLADM_STATUS_OK);
428*8275SEric Cheng }
429*8275SEric Cheng 
430*8275SEric Cheng /* ARGSUSED */
431*8275SEric Cheng static dladm_status_t
432*8275SEric Cheng do_check_priority(fprop_desc_t *pdp, char **prop_val, uint_t val_cnt,
433*8275SEric Cheng     val_desc_t **vdpp)
434*8275SEric Cheng {
435*8275SEric Cheng 	mac_priority_level_t	*pri;
436*8275SEric Cheng 	val_desc_t	*vdp = NULL;
437*8275SEric Cheng 	dladm_status_t	status = DLADM_STATUS_OK;
438*8275SEric Cheng 
439*8275SEric Cheng 	if (val_cnt != 1)
440*8275SEric Cheng 		return (DLADM_STATUS_BADVALCNT);
441*8275SEric Cheng 
442*8275SEric Cheng 	pri = malloc(sizeof (mac_priority_level_t));
443*8275SEric Cheng 	if (pri == NULL)
444*8275SEric Cheng 		return (DLADM_STATUS_NOMEM);
445*8275SEric Cheng 
446*8275SEric Cheng 	status = dladm_str2pri(*prop_val, pri);
447*8275SEric Cheng 	if (status != DLADM_STATUS_OK) {
448*8275SEric Cheng 		free(pri);
449*8275SEric Cheng 		return (status);
450*8275SEric Cheng 	}
451*8275SEric Cheng 
452*8275SEric Cheng 	if (*pri == -1) {
453*8275SEric Cheng 		free(pri);
454*8275SEric Cheng 		return (DLADM_STATUS_BADVAL);
455*8275SEric Cheng 	}
456*8275SEric Cheng 
457*8275SEric Cheng 	vdp = malloc(sizeof (val_desc_t));
458*8275SEric Cheng 	if (vdp == NULL) {
459*8275SEric Cheng 		free(pri);
460*8275SEric Cheng 		return (DLADM_STATUS_NOMEM);
461*8275SEric Cheng 	}
462*8275SEric Cheng 
463*8275SEric Cheng 	vdp->vd_val = (uintptr_t)pri;
464*8275SEric Cheng 	*vdpp = vdp;
465*8275SEric Cheng 	return (DLADM_STATUS_OK);
466*8275SEric Cheng }
467*8275SEric Cheng 
468*8275SEric Cheng static dladm_status_t
469*8275SEric Cheng flow_proplist_check(dladm_arg_list_t *proplist)
470*8275SEric Cheng {
471*8275SEric Cheng 	int		i, j;
472*8275SEric Cheng 	boolean_t	matched;
473*8275SEric Cheng 
474*8275SEric Cheng 	for (i = 0; i < proplist->al_count; i++) {
475*8275SEric Cheng 		matched = B_FALSE;
476*8275SEric Cheng 		for (j = 0; j < DLADM_MAX_FLOWPROPS; j++) {
477*8275SEric Cheng 			if (strcmp(proplist->al_info[i].ai_name,
478*8275SEric Cheng 			    prop_table[j].pd_name) == 0)
479*8275SEric Cheng 				matched = B_TRUE;
480*8275SEric Cheng 			}
481*8275SEric Cheng 		if (!matched)
482*8275SEric Cheng 			return (DLADM_STATUS_BADPROP);
483*8275SEric Cheng 	}
484*8275SEric Cheng 	return (DLADM_STATUS_OK);
485*8275SEric Cheng 
486*8275SEric Cheng }
487*8275SEric Cheng 
488*8275SEric Cheng dladm_status_t
489*8275SEric Cheng dladm_parse_flow_props(char *str, dladm_arg_list_t **listp, boolean_t novalues)
490*8275SEric Cheng {
491*8275SEric Cheng 	dladm_status_t	status;
492*8275SEric Cheng 
493*8275SEric Cheng 	status = dladm_parse_args(str, listp, novalues);
494*8275SEric Cheng 	if (status != DLADM_STATUS_OK)
495*8275SEric Cheng 		return (status);
496*8275SEric Cheng 
497*8275SEric Cheng 	status = flow_proplist_check(*listp);
498*8275SEric Cheng 	if (status != DLADM_STATUS_OK) {
499*8275SEric Cheng 		dladm_free_props(*listp);
500*8275SEric Cheng 		return (status);
501*8275SEric Cheng 	}
502*8275SEric Cheng 
503*8275SEric Cheng 	return (DLADM_STATUS_OK);
504*8275SEric Cheng }
505*8275SEric Cheng 
506*8275SEric Cheng /*
507*8275SEric Cheng  * Retrieve the named property from a proplist, check the value and
508*8275SEric Cheng  * convert to a kernel structure.
509*8275SEric Cheng  */
510*8275SEric Cheng static dladm_status_t
511*8275SEric Cheng i_dladm_flow_proplist_extract_one(dladm_arg_list_t *proplist,
512*8275SEric Cheng     const char *name, void *val)
513*8275SEric Cheng {
514*8275SEric Cheng 	dladm_status_t		status;
515*8275SEric Cheng 	dladm_arg_info_t	*aip = NULL;
516*8275SEric Cheng 	int			i, j;
517*8275SEric Cheng 
518*8275SEric Cheng 	/* Find named property in proplist */
519*8275SEric Cheng 	for (i = 0; i < proplist->al_count; i++) {
520*8275SEric Cheng 		aip = &proplist->al_info[i];
521*8275SEric Cheng 		if (strcasecmp(aip->ai_name, name) == 0)
522*8275SEric Cheng 			break;
523*8275SEric Cheng 	}
524*8275SEric Cheng 
525*8275SEric Cheng 	/* Property not in list */
526*8275SEric Cheng 	if (i == proplist->al_count)
527*8275SEric Cheng 		return (DLADM_STATUS_OK);
528*8275SEric Cheng 
529*8275SEric Cheng 	for (i = 0; i < DLADM_MAX_FLOWPROPS; i++) {
530*8275SEric Cheng 		fprop_desc_t	*pdp = &prop_table[i];
531*8275SEric Cheng 		val_desc_t	*vdp;
532*8275SEric Cheng 
533*8275SEric Cheng 		vdp = malloc(sizeof (val_desc_t) * aip->ai_count);
534*8275SEric Cheng 		if (vdp == NULL)
535*8275SEric Cheng 			return (DLADM_STATUS_NOMEM);
536*8275SEric Cheng 
537*8275SEric Cheng 		if (strcasecmp(aip->ai_name, pdp->pd_name) != 0)
538*8275SEric Cheng 			continue;
539*8275SEric Cheng 
540*8275SEric Cheng 		if (aip->ai_val == NULL)
541*8275SEric Cheng 			return (DLADM_STATUS_BADARG);
542*8275SEric Cheng 
543*8275SEric Cheng 		/* Check property value */
544*8275SEric Cheng 		if (pdp->pd_check != NULL) {
545*8275SEric Cheng 			status = pdp->pd_check(pdp, aip->ai_val,
546*8275SEric Cheng 			    aip->ai_count, &vdp);
547*8275SEric Cheng 		} else {
548*8275SEric Cheng 			status = DLADM_STATUS_BADARG;
549*8275SEric Cheng 		}
550*8275SEric Cheng 
551*8275SEric Cheng 		if (status != DLADM_STATUS_OK)
552*8275SEric Cheng 			return (status);
553*8275SEric Cheng 
554*8275SEric Cheng 		for (j = 0; j < DLADM_MAX_RSRC_PROP; j++) {
555*8275SEric Cheng 			resource_prop_t	*rpp = &rsrc_prop_table[j];
556*8275SEric Cheng 
557*8275SEric Cheng 			if (strcasecmp(aip->ai_name, rpp->rp_name) != 0)
558*8275SEric Cheng 				continue;
559*8275SEric Cheng 
560*8275SEric Cheng 			/* Extract kernel structure */
561*8275SEric Cheng 			if (rpp->rp_extract != NULL) {
562*8275SEric Cheng 				status = rpp->rp_extract(vdp, val,
563*8275SEric Cheng 				    aip->ai_count);
564*8275SEric Cheng 			} else {
565*8275SEric Cheng 				status = DLADM_STATUS_BADARG;
566*8275SEric Cheng 			}
567*8275SEric Cheng 			break;
568*8275SEric Cheng 		}
569*8275SEric Cheng 
570*8275SEric Cheng 		if (status != DLADM_STATUS_OK)
571*8275SEric Cheng 			return (status);
572*8275SEric Cheng 
573*8275SEric Cheng 		break;
574*8275SEric Cheng 	}
575*8275SEric Cheng 	return (status);
576*8275SEric Cheng }
577*8275SEric Cheng 
578*8275SEric Cheng /*
579*8275SEric Cheng  * Extract properties from a proplist and convert to mac_resource_props_t.
580*8275SEric Cheng  */
581*8275SEric Cheng dladm_status_t
582*8275SEric Cheng dladm_flow_proplist_extract(dladm_arg_list_t *proplist,
583*8275SEric Cheng     mac_resource_props_t *mrp)
584*8275SEric Cheng {
585*8275SEric Cheng 	dladm_status_t	status = DLADM_STATUS_OK;
586*8275SEric Cheng 
587*8275SEric Cheng 	status = i_dladm_flow_proplist_extract_one(proplist, "maxbw", mrp);
588*8275SEric Cheng 	if (status != DLADM_STATUS_OK)
589*8275SEric Cheng 		return (status);
590*8275SEric Cheng 	status = i_dladm_flow_proplist_extract_one(proplist, "priority", mrp);
591*8275SEric Cheng 	if (status != DLADM_STATUS_OK)
592*8275SEric Cheng 		return (status);
593*8275SEric Cheng 	return (status);
594*8275SEric Cheng }
595*8275SEric Cheng 
596*8275SEric Cheng dladm_status_t
597*8275SEric Cheng i_dladm_set_flow_proplist_db(char *flow, dladm_arg_list_t *proplist)
598*8275SEric Cheng {
599*8275SEric Cheng 	dladm_status_t		status, ssave = DLADM_STATUS_OK;
600*8275SEric Cheng 	dladm_arg_info_t	ai;
601*8275SEric Cheng 	int			i;
602*8275SEric Cheng 
603*8275SEric Cheng 	for (i = 0; i < proplist->al_count; i++) {
604*8275SEric Cheng 		ai = proplist->al_info[i];
605*8275SEric Cheng 		status = i_dladm_set_flowprop_db(flow, ai.ai_name,
606*8275SEric Cheng 		    ai.ai_val, ai.ai_count);
607*8275SEric Cheng 		if (status != DLADM_STATUS_OK)
608*8275SEric Cheng 			ssave = status;
609*8275SEric Cheng 	}
610*8275SEric Cheng 	return (ssave);
611*8275SEric Cheng }
612