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