4 * The contents of this file are subject to the terms of the
5 * Common Development and Distribution License (the "License").
6 * You may not use this file except in compliance with the License.
8 * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
9 * or http://www.opensolaris.org/os/licensing.
10 * See the License for the specific language governing permissions
11 * and limitations under the License.
13 * When distributing Covered Code, include this CDDL HEADER in each
14 * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
15 * If applicable, add the following below this CDDL HEADER, with the
16 * fields enclosed by brackets "[]" replaced with your own identifying
17 * information: Portions Copyright [yyyy] [name of copyright owner]
22 * Copyright 2010 Sun Microsystems, Inc. All rights reserved.
23 * Use is subject to license terms.
30 #include <sys/types.h>
33 #include <sys/dld_ioc.h>
36 #include <libdevinfo.h>
37 #include <libdladm_impl.h>
38 #include <libdlflow.h>
39 #include <libdlflow_impl.h>
46 * XXX duplicate define
48 #define DLADM_PROP_VAL_MAX 32
50 static dladm_status_t
i_dladm_set_flowprop_db(dladm_handle_t
, const char *,
51 const char *, char **, uint_t
);
52 static dladm_status_t
i_dladm_get_flowprop_db(dladm_handle_t
, const char *,
53 const char *, char **, uint_t
*);
55 static fpd_getf_t do_get_maxbw
;
56 static fpd_setf_t do_set_maxbw
;
57 static fpd_checkf_t do_check_maxbw
;
59 static fpd_getf_t do_get_priority
;
60 static fpd_setf_t do_set_priority
;
61 static fpd_checkf_t do_check_priority
;
63 static fprop_desc_t prop_table
[] = {
64 { "maxbw", { "", 0 }, NULL
, 0, B_FALSE
,
66 do_get_maxbw
, do_check_maxbw
},
67 { "priority", { "", MPL_RESET
}, NULL
, 0, B_FALSE
,
68 do_set_priority
, NULL
,
69 do_get_priority
, do_check_priority
}
72 #define DLADM_MAX_FLOWPROPS (sizeof (prop_table) / sizeof (fprop_desc_t))
74 static prop_table_t prop_tbl
= {
79 static resource_prop_t rsrc_prop_table
[] = {
80 {"maxbw", extract_maxbw
},
81 {"priority", extract_priority
}
83 #define DLADM_MAX_RSRC_PROP (sizeof (rsrc_prop_table) / \
84 sizeof (resource_prop_t))
86 static dladm_status_t
flow_proplist_check(dladm_arg_list_t
*);
89 dladm_set_flowprop(dladm_handle_t handle
, const char *flow
,
90 const char *prop_name
, char **prop_val
, uint_t val_cnt
, uint_t flags
,
93 dladm_status_t status
= DLADM_STATUS_BADARG
;
95 if (flow
== NULL
|| (prop_val
== NULL
&& val_cnt
> 0) ||
96 (prop_val
!= NULL
&& val_cnt
== 0) || flags
== 0)
97 return (DLADM_STATUS_BADARG
);
99 if ((flags
& DLADM_OPT_ACTIVE
) != 0) {
100 status
= i_dladm_set_prop_temp(handle
, flow
, prop_name
,
101 prop_val
, val_cnt
, flags
, errprop
, &prop_tbl
);
102 if (status
== DLADM_STATUS_TEMPONLY
&&
103 (flags
& DLADM_OPT_PERSIST
) != 0)
104 return (DLADM_STATUS_TEMPONLY
);
105 if (status
!= DLADM_STATUS_OK
)
108 if ((flags
& DLADM_OPT_PERSIST
) != 0) {
109 if (i_dladm_is_prop_temponly(prop_name
, errprop
, &prop_tbl
))
110 return (DLADM_STATUS_TEMPONLY
);
112 status
= i_dladm_set_flowprop_db(handle
, flow
, prop_name
,
119 dladm_walk_flowprop(int (*func
)(void *, const char *), const char *flow
,
124 if (flow
== NULL
|| func
== NULL
)
125 return (DLADM_STATUS_BADARG
);
127 /* Then show data-flow properties if there are any */
128 for (i
= 0; i
< DLADM_MAX_FLOWPROPS
; i
++) {
129 if (func(arg
, prop_table
[i
].pd_name
) != DLADM_WALK_CONTINUE
)
132 return (DLADM_STATUS_OK
);
136 dladm_get_flowprop(dladm_handle_t handle
, const char *flow
, uint32_t type
,
137 const char *prop_name
, char **prop_val
, uint_t
*val_cntp
)
139 dladm_status_t status
;
141 if (flow
== NULL
|| prop_name
== NULL
|| prop_val
== NULL
||
142 val_cntp
== NULL
|| *val_cntp
== 0)
143 return (DLADM_STATUS_BADARG
);
145 if (type
== DLADM_PROP_VAL_PERSISTENT
) {
146 if (i_dladm_is_prop_temponly(prop_name
, NULL
, &prop_tbl
))
147 return (DLADM_STATUS_TEMPONLY
);
148 return (i_dladm_get_flowprop_db(handle
, flow
, prop_name
,
149 prop_val
, val_cntp
));
152 status
= i_dladm_get_prop_temp(handle
, flow
, type
, prop_name
,
153 prop_val
, val_cntp
, &prop_tbl
);
154 if (status
!= DLADM_STATUS_NOTFOUND
)
157 return (DLADM_STATUS_BADARG
);
160 #define FLOWPROP_RW_DB(handle, statep, writeop) \
161 (i_dladm_rw_db(handle, "/etc/dladm/flowprop.conf", \
162 S_IRUSR | S_IWUSR | S_IRGRP | S_IROTH, process_prop_db, \
163 (statep), (writeop)))
165 static dladm_status_t
166 i_dladm_set_flowprop_db(dladm_handle_t handle
, const char *flow
,
167 const char *prop_name
, char **prop_val
, uint_t val_cnt
)
169 prop_db_state_t state
;
171 state
.ls_op
= process_prop_set
;
172 state
.ls_name
= flow
;
173 state
.ls_propname
= prop_name
;
174 state
.ls_propval
= prop_val
;
175 state
.ls_valcntp
= &val_cnt
;
176 state
.ls_initop
= NULL
;
178 return (FLOWPROP_RW_DB(handle
, &state
, B_TRUE
));
181 static dladm_status_t
182 i_dladm_get_flowprop_db(dladm_handle_t handle
, const char *flow
,
183 const char *prop_name
, char **prop_val
, uint_t
*val_cntp
)
185 prop_db_state_t state
;
187 state
.ls_op
= process_prop_get
;
188 state
.ls_name
= flow
;
189 state
.ls_propname
= prop_name
;
190 state
.ls_propval
= prop_val
;
191 state
.ls_valcntp
= val_cntp
;
192 state
.ls_initop
= NULL
;
194 return (FLOWPROP_RW_DB(handle
, &state
, B_FALSE
));
198 i_dladm_init_flowprop_db(dladm_handle_t handle
)
200 prop_db_state_t state
;
202 state
.ls_op
= process_prop_init
;
203 state
.ls_name
= NULL
;
204 state
.ls_propname
= NULL
;
205 state
.ls_propval
= NULL
;
206 state
.ls_valcntp
= NULL
;
207 state
.ls_initop
= dladm_set_flowprop
;
209 return (FLOWPROP_RW_DB(handle
, &state
, B_FALSE
));
212 #define MIN_INFO_SIZE (4 * 1024)
215 dladm_flow_info(dladm_handle_t handle
, const char *flow
,
216 dladm_flow_attr_t
*attr
)
218 dld_ioc_walkflow_t
*ioc
;
220 dld_flowinfo_t
*flowinfo
;
222 if ((flow
== NULL
) || (attr
== NULL
))
223 return (DLADM_STATUS_BADARG
);
225 bufsize
= MIN_INFO_SIZE
;
226 if ((ioc
= calloc(1, bufsize
)) == NULL
)
227 return (dladm_errno2status(errno
));
229 (void) strlcpy(ioc
->wf_name
, flow
, sizeof (ioc
->wf_name
));
230 ioc
->wf_len
= bufsize
- sizeof (*ioc
);
232 while (ioctl(dladm_dld_fd(handle
), DLDIOC_WALKFLOW
, ioc
) < 0) {
233 if (errno
== ENOSPC
) {
235 ioc
= realloc(ioc
, bufsize
);
237 (void) strlcpy(ioc
->wf_name
, flow
,
239 ioc
->wf_len
= bufsize
- sizeof (*ioc
);
244 return (dladm_errno2status(errno
));
247 bzero(attr
, sizeof (*attr
));
249 flowinfo
= (dld_flowinfo_t
*)(void *)(ioc
+ 1);
251 attr
->fa_linkid
= flowinfo
->fi_linkid
;
252 bcopy(&flowinfo
->fi_flowname
, &attr
->fa_flowname
,
253 sizeof (attr
->fa_flowname
));
254 bcopy(&flowinfo
->fi_flow_desc
, &attr
->fa_flow_desc
,
255 sizeof (attr
->fa_flow_desc
));
256 bcopy(&flowinfo
->fi_resource_props
, &attr
->fa_resource_props
,
257 sizeof (attr
->fa_resource_props
));
260 return (DLADM_STATUS_OK
);
264 static dladm_status_t
265 do_get_maxbw(dladm_handle_t handle
, const char *flow
, char **prop_val
,
268 mac_resource_props_t
*mrp
;
269 char buf
[DLADM_STRSIZE
];
270 dladm_flow_attr_t fa
;
271 dladm_status_t status
;
273 status
= dladm_flow_info(handle
, flow
, &fa
);
274 if (status
!= DLADM_STATUS_OK
)
276 mrp
= &(fa
.fa_resource_props
);
279 if (mrp
->mrp_mask
& MRP_MAXBW
) {
280 (void) snprintf(prop_val
[0], DLADM_STRSIZE
, "%s",
281 dladm_bw2str(mrp
->mrp_maxbw
, buf
));
283 return (DLADM_STATUS_NOTSUP
);
285 return (DLADM_STATUS_OK
);
289 static dladm_status_t
290 do_set_maxbw(dladm_handle_t handle
, const char *flow
, val_desc_t
*vdp
,
293 dld_ioc_modifyflow_t attr
;
294 mac_resource_props_t mrp
;
298 return (DLADM_STATUS_BADVALCNT
);
300 bzero(&mrp
, sizeof (mrp
));
301 if (vdp
!= NULL
&& (val
= (void *)vdp
->vd_val
) != NULL
) {
302 bcopy(val
, &mrp
.mrp_maxbw
, sizeof (int64_t));
305 mrp
.mrp_maxbw
= MRP_MAXBW_RESETVAL
;
307 mrp
.mrp_mask
= MRP_MAXBW
;
309 bzero(&attr
, sizeof (attr
));
310 (void) strlcpy(attr
.mf_name
, flow
, sizeof (attr
.mf_name
));
311 bcopy(&mrp
, &attr
.mf_resource_props
, sizeof (mac_resource_props_t
));
313 if (ioctl(dladm_dld_fd(handle
), DLDIOC_MODIFYFLOW
, &attr
) < 0)
314 return (dladm_errno2status(errno
));
316 return (DLADM_STATUS_OK
);
320 static dladm_status_t
321 do_check_maxbw(fprop_desc_t
*pdp
, char **prop_val
, uint_t val_cnt
,
325 val_desc_t
*vdp
= NULL
;
326 dladm_status_t status
= DLADM_STATUS_OK
;
329 return (DLADM_STATUS_BADVALCNT
);
331 maxbw
= malloc(sizeof (uint64_t));
333 return (DLADM_STATUS_NOMEM
);
335 status
= dladm_str2bw(*prop_val
, maxbw
);
336 if (status
!= DLADM_STATUS_OK
) {
341 if ((*maxbw
< MRP_MAXBW_MINVAL
) && (*maxbw
!= 0)) {
343 return (DLADM_STATUS_MINMAXBW
);
346 vdp
= malloc(sizeof (val_desc_t
));
349 return (DLADM_STATUS_NOMEM
);
352 vdp
->vd_val
= (uintptr_t)maxbw
;
354 return (DLADM_STATUS_OK
);
358 static dladm_status_t
359 do_get_priority(dladm_handle_t handle
, const char *flow
, char **prop_val
,
362 mac_resource_props_t
*mrp
;
363 char buf
[DLADM_STRSIZE
];
364 dladm_flow_attr_t fa
;
365 dladm_status_t status
;
367 bzero(&fa
, sizeof (dladm_flow_attr_t
));
368 status
= dladm_flow_info(handle
, flow
, &fa
);
369 if (status
!= DLADM_STATUS_OK
)
371 mrp
= &(fa
.fa_resource_props
);
374 if (mrp
->mrp_mask
& MRP_PRIORITY
) {
375 (void) snprintf(prop_val
[0], DLADM_STRSIZE
, "%s",
376 dladm_pri2str(mrp
->mrp_priority
, buf
));
378 return (DLADM_STATUS_NOTSUP
);
380 return (DLADM_STATUS_OK
);
384 static dladm_status_t
385 do_set_priority(dladm_handle_t handle
, const char *flow
, val_desc_t
*vdp
,
388 dld_ioc_modifyflow_t attr
;
389 mac_resource_props_t mrp
;
392 return (DLADM_STATUS_BADVALCNT
);
394 bzero(&mrp
, sizeof (mrp
));
396 bcopy(&vdp
->vd_val
, &mrp
.mrp_priority
,
397 sizeof (mac_priority_level_t
));
399 mrp
.mrp_priority
= MPL_RESET
;
401 mrp
.mrp_mask
= MRP_PRIORITY
;
403 bzero(&attr
, sizeof (attr
));
404 (void) strlcpy(attr
.mf_name
, flow
, sizeof (attr
.mf_name
));
405 bcopy(&mrp
, &attr
.mf_resource_props
, sizeof (mac_resource_props_t
));
407 if (ioctl(dladm_dld_fd(handle
), DLDIOC_MODIFYFLOW
, &attr
) < 0)
408 return (dladm_errno2status(errno
));
410 return (DLADM_STATUS_OK
);
414 static dladm_status_t
415 do_check_priority(fprop_desc_t
*pdp
, char **prop_val
, uint_t val_cnt
,
418 mac_priority_level_t pri
;
419 val_desc_t
*vdp
= NULL
;
420 dladm_status_t status
= DLADM_STATUS_OK
;
423 return (DLADM_STATUS_BADVALCNT
);
425 status
= dladm_str2pri(*prop_val
, &pri
);
426 if (status
!= DLADM_STATUS_OK
)
430 return (DLADM_STATUS_BADVAL
);
432 vdp
= malloc(sizeof (val_desc_t
));
434 return (DLADM_STATUS_NOMEM
);
436 vdp
->vd_val
= (uint_t
)pri
;
438 return (DLADM_STATUS_OK
);
441 static dladm_status_t
442 flow_proplist_check(dladm_arg_list_t
*proplist
)
447 for (i
= 0; i
< proplist
->al_count
; i
++) {
449 for (j
= 0; j
< DLADM_MAX_FLOWPROPS
; j
++) {
450 if (strcmp(proplist
->al_info
[i
].ai_name
,
451 prop_table
[j
].pd_name
) == 0)
455 return (DLADM_STATUS_BADPROP
);
457 return (DLADM_STATUS_OK
);
462 dladm_parse_flow_props(char *str
, dladm_arg_list_t
**listp
, boolean_t novalues
)
464 dladm_status_t status
;
466 status
= dladm_parse_args(str
, listp
, novalues
);
467 if (status
!= DLADM_STATUS_OK
)
470 if (*listp
!= NULL
&& (status
= flow_proplist_check(*listp
)
471 != DLADM_STATUS_OK
)) {
472 dladm_free_props(*listp
);
476 return (DLADM_STATUS_OK
);
480 * Retrieve the named property from a proplist, check the value and
481 * convert to a kernel structure.
483 static dladm_status_t
484 i_dladm_flow_proplist_extract_one(dladm_arg_list_t
*proplist
,
485 const char *name
, void *arg
)
487 dladm_status_t status
;
488 dladm_arg_info_t
*aip
= NULL
;
491 /* Find named property in proplist */
492 for (i
= 0; i
< proplist
->al_count
; i
++) {
493 aip
= &proplist
->al_info
[i
];
494 if (strcasecmp(aip
->ai_name
, name
) == 0)
498 /* Property not in list */
499 if (i
== proplist
->al_count
)
500 return (DLADM_STATUS_OK
);
502 for (i
= 0; i
< DLADM_MAX_FLOWPROPS
; i
++) {
503 fprop_desc_t
*pdp
= &prop_table
[i
];
506 vdp
= malloc(sizeof (val_desc_t
) * aip
->ai_count
);
508 return (DLADM_STATUS_NOMEM
);
510 if (strcasecmp(aip
->ai_name
, pdp
->pd_name
) != 0)
513 if (aip
->ai_val
== NULL
)
514 return (DLADM_STATUS_BADARG
);
516 /* Check property value */
517 if (pdp
->pd_check
!= NULL
) {
518 status
= pdp
->pd_check(pdp
, aip
->ai_val
,
519 aip
->ai_count
, &vdp
);
521 status
= DLADM_STATUS_BADARG
;
524 if (status
!= DLADM_STATUS_OK
)
527 for (j
= 0; j
< DLADM_MAX_RSRC_PROP
; j
++) {
528 resource_prop_t
*rpp
= &rsrc_prop_table
[j
];
530 if (strcasecmp(aip
->ai_name
, rpp
->rp_name
) != 0)
533 /* Extract kernel structure */
534 if (rpp
->rp_extract
!= NULL
) {
535 status
= rpp
->rp_extract(vdp
,
538 status
= DLADM_STATUS_BADARG
;
543 if (status
!= DLADM_STATUS_OK
)
552 * Extract properties from a proplist and convert to mac_resource_props_t.
555 dladm_flow_proplist_extract(dladm_arg_list_t
*proplist
,
556 mac_resource_props_t
*mrp
)
558 dladm_status_t status
= DLADM_STATUS_OK
;
560 status
= i_dladm_flow_proplist_extract_one(proplist
, "maxbw", mrp
);
561 if (status
!= DLADM_STATUS_OK
)
563 status
= i_dladm_flow_proplist_extract_one(proplist
, "priority", mrp
);
564 if (status
!= DLADM_STATUS_OK
)
570 i_dladm_set_flow_proplist_db(dladm_handle_t handle
, char *flow
,
571 dladm_arg_list_t
*proplist
)
573 dladm_status_t status
, ssave
= DLADM_STATUS_OK
;
577 for (i
= 0; i
< proplist
->al_count
; i
++) {
578 ai
= proplist
->al_info
[i
];
579 status
= i_dladm_set_flowprop_db(handle
, flow
, ai
.ai_name
,
580 ai
.ai_val
, ai
.ai_count
);
581 if (status
!= DLADM_STATUS_OK
)