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