18275SEric Cheng /*
28275SEric Cheng * CDDL HEADER START
38275SEric Cheng *
48275SEric Cheng * The contents of this file are subject to the terms of the
58275SEric Cheng * Common Development and Distribution License (the "License").
68275SEric Cheng * You may not use this file except in compliance with the License.
78275SEric Cheng *
88275SEric Cheng * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
98275SEric Cheng * or http://www.opensolaris.org/os/licensing.
108275SEric Cheng * See the License for the specific language governing permissions
118275SEric Cheng * and limitations under the License.
128275SEric Cheng *
138275SEric Cheng * When distributing Covered Code, include this CDDL HEADER in each
148275SEric Cheng * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
158275SEric Cheng * If applicable, add the following below this CDDL HEADER, with the
168275SEric Cheng * fields enclosed by brackets "[]" replaced with your own identifying
178275SEric Cheng * information: Portions Copyright [yyyy] [name of copyright owner]
188275SEric Cheng *
198275SEric Cheng * CDDL HEADER END
208275SEric Cheng */
218275SEric Cheng /*
22*11878SVenu.Iyer@Sun.COM * Copyright 2010 Sun Microsystems, Inc. All rights reserved.
238275SEric Cheng * Use is subject to license terms.
248275SEric Cheng */
258275SEric Cheng
268275SEric Cheng #include <stdlib.h>
278275SEric Cheng #include <strings.h>
288275SEric Cheng #include <errno.h>
298275SEric Cheng #include <ctype.h>
308275SEric Cheng #include <sys/types.h>
318275SEric Cheng #include <sys/stat.h>
328275SEric Cheng #include <sys/dld.h>
339107Sjames.d.carlson@sun.com #include <sys/dld_ioc.h>
348275SEric Cheng #include <fcntl.h>
358275SEric Cheng #include <unistd.h>
368275SEric Cheng #include <libdevinfo.h>
378275SEric Cheng #include <libdladm_impl.h>
388275SEric Cheng #include <libdlflow.h>
398275SEric Cheng #include <libdlflow_impl.h>
408275SEric Cheng #include <libintl.h>
418275SEric Cheng
428275SEric Cheng #include <dlfcn.h>
438275SEric Cheng #include <link.h>
448275SEric Cheng
458275SEric Cheng /*
468275SEric Cheng * XXX duplicate define
478275SEric Cheng */
488275SEric Cheng #define DLADM_PROP_VAL_MAX 32
498275SEric Cheng
508453SAnurag.Maskey@Sun.COM static dladm_status_t i_dladm_set_flowprop_db(dladm_handle_t, const char *,
518453SAnurag.Maskey@Sun.COM const char *, char **, uint_t);
528453SAnurag.Maskey@Sun.COM static dladm_status_t i_dladm_get_flowprop_db(dladm_handle_t, const char *,
538453SAnurag.Maskey@Sun.COM const char *, char **, uint_t *);
548275SEric Cheng
558275SEric Cheng static fpd_getf_t do_get_maxbw;
568275SEric Cheng static fpd_setf_t do_set_maxbw;
578275SEric Cheng static fpd_checkf_t do_check_maxbw;
588275SEric Cheng
598275SEric Cheng static fpd_getf_t do_get_priority;
608275SEric Cheng static fpd_setf_t do_set_priority;
618275SEric Cheng static fpd_checkf_t do_check_priority;
628275SEric Cheng
638275SEric Cheng static fprop_desc_t prop_table[] = {
648275SEric Cheng { "maxbw", { "", NULL }, NULL, 0, B_FALSE,
658275SEric Cheng do_set_maxbw, NULL,
668275SEric Cheng do_get_maxbw, do_check_maxbw},
67*11878SVenu.Iyer@Sun.COM { "priority", { "", MPL_RESET }, NULL, 0, B_FALSE,
688275SEric Cheng do_set_priority, NULL,
698275SEric Cheng do_get_priority, do_check_priority}
708275SEric Cheng };
718275SEric Cheng
728275SEric Cheng #define DLADM_MAX_FLOWPROPS (sizeof (prop_table) / sizeof (fprop_desc_t))
738275SEric Cheng
748275SEric Cheng static prop_table_t prop_tbl = {
758275SEric Cheng prop_table,
768275SEric Cheng DLADM_MAX_FLOWPROPS
778275SEric Cheng };
788275SEric Cheng
798275SEric Cheng static resource_prop_t rsrc_prop_table[] = {
80*11878SVenu.Iyer@Sun.COM {"maxbw", extract_maxbw},
81*11878SVenu.Iyer@Sun.COM {"priority", extract_priority}
828275SEric Cheng };
838275SEric Cheng #define DLADM_MAX_RSRC_PROP (sizeof (rsrc_prop_table) / \
848275SEric Cheng sizeof (resource_prop_t))
858275SEric Cheng
868275SEric Cheng static dladm_status_t flow_proplist_check(dladm_arg_list_t *);
878275SEric Cheng
888275SEric Cheng dladm_status_t
dladm_set_flowprop(dladm_handle_t handle,const char * flow,const char * prop_name,char ** prop_val,uint_t val_cnt,uint_t flags,char ** errprop)898453SAnurag.Maskey@Sun.COM dladm_set_flowprop(dladm_handle_t handle, const char *flow,
908453SAnurag.Maskey@Sun.COM const char *prop_name, char **prop_val, uint_t val_cnt, uint_t flags,
918453SAnurag.Maskey@Sun.COM char **errprop)
928275SEric Cheng {
938275SEric Cheng dladm_status_t status = DLADM_STATUS_BADARG;
948275SEric Cheng
958275SEric Cheng if (flow == NULL || (prop_val == NULL && val_cnt > 0) ||
968275SEric Cheng (prop_val != NULL && val_cnt == 0) || flags == 0)
978275SEric Cheng return (DLADM_STATUS_BADARG);
988275SEric Cheng
998275SEric Cheng if ((flags & DLADM_OPT_ACTIVE) != 0) {
1008453SAnurag.Maskey@Sun.COM status = i_dladm_set_prop_temp(handle, flow, prop_name,
1018453SAnurag.Maskey@Sun.COM prop_val, val_cnt, flags, errprop, &prop_tbl);
1028275SEric Cheng if (status == DLADM_STATUS_TEMPONLY &&
1038275SEric Cheng (flags & DLADM_OPT_PERSIST) != 0)
1048275SEric Cheng return (DLADM_STATUS_TEMPONLY);
1058275SEric Cheng if (status != DLADM_STATUS_OK)
1068275SEric Cheng return (status);
1078275SEric Cheng }
1088275SEric Cheng if ((flags & DLADM_OPT_PERSIST) != 0) {
1098275SEric Cheng if (i_dladm_is_prop_temponly(prop_name, errprop, &prop_tbl))
1108275SEric Cheng return (DLADM_STATUS_TEMPONLY);
1118275SEric Cheng
1128453SAnurag.Maskey@Sun.COM status = i_dladm_set_flowprop_db(handle, flow, prop_name,
1138275SEric Cheng prop_val, val_cnt);
1148275SEric Cheng }
1158275SEric Cheng return (status);
1168275SEric Cheng }
1178275SEric Cheng
1188275SEric Cheng dladm_status_t
dladm_walk_flowprop(int (* func)(void *,const char *),const char * flow,void * arg)1198275SEric Cheng dladm_walk_flowprop(int (*func)(void *, const char *), const char *flow,
1208275SEric Cheng void *arg)
1218275SEric Cheng {
1228275SEric Cheng int i;
1238275SEric Cheng
1248275SEric Cheng if (flow == NULL || func == NULL)
1258275SEric Cheng return (DLADM_STATUS_BADARG);
1268275SEric Cheng
1278275SEric Cheng /* Then show data-flow properties if there are any */
1288275SEric Cheng for (i = 0; i < DLADM_MAX_FLOWPROPS; i++) {
1298275SEric Cheng if (func(arg, prop_table[i].pd_name) != DLADM_WALK_CONTINUE)
1308275SEric Cheng break;
1318275SEric Cheng }
1328275SEric Cheng return (DLADM_STATUS_OK);
1338275SEric Cheng }
1348275SEric Cheng
1358275SEric Cheng dladm_status_t
dladm_get_flowprop(dladm_handle_t handle,const char * flow,uint32_t type,const char * prop_name,char ** prop_val,uint_t * val_cntp)1368453SAnurag.Maskey@Sun.COM dladm_get_flowprop(dladm_handle_t handle, const char *flow, uint32_t type,
1378275SEric Cheng const char *prop_name, char **prop_val, uint_t *val_cntp)
1388275SEric Cheng {
1398275SEric Cheng dladm_status_t status;
1408275SEric Cheng
1418275SEric Cheng if (flow == NULL || prop_name == NULL || prop_val == NULL ||
1428275SEric Cheng val_cntp == NULL || *val_cntp == 0)
1438275SEric Cheng return (DLADM_STATUS_BADARG);
1448275SEric Cheng
1458275SEric Cheng if (type == DLADM_PROP_VAL_PERSISTENT) {
1468275SEric Cheng if (i_dladm_is_prop_temponly(prop_name, NULL, &prop_tbl))
1478275SEric Cheng return (DLADM_STATUS_TEMPONLY);
1488453SAnurag.Maskey@Sun.COM return (i_dladm_get_flowprop_db(handle, flow, prop_name,
1498275SEric Cheng prop_val, val_cntp));
1508275SEric Cheng }
1518275SEric Cheng
1528453SAnurag.Maskey@Sun.COM status = i_dladm_get_prop_temp(handle, flow, type, prop_name,
1538275SEric Cheng prop_val, val_cntp, &prop_tbl);
1548275SEric Cheng if (status != DLADM_STATUS_NOTFOUND)
1558275SEric Cheng return (status);
1568275SEric Cheng
1578275SEric Cheng return (DLADM_STATUS_BADARG);
1588275SEric Cheng }
1598275SEric Cheng
1608453SAnurag.Maskey@Sun.COM #define FLOWPROP_RW_DB(handle, statep, writeop) \
1618453SAnurag.Maskey@Sun.COM (i_dladm_rw_db(handle, "/etc/dladm/flowprop.conf", \
1628275SEric Cheng S_IRUSR | S_IWUSR | S_IRGRP | S_IROTH, process_prop_db, \
1638275SEric Cheng (statep), (writeop)))
1648275SEric Cheng
1658275SEric Cheng static dladm_status_t
i_dladm_set_flowprop_db(dladm_handle_t handle,const char * flow,const char * prop_name,char ** prop_val,uint_t val_cnt)1668453SAnurag.Maskey@Sun.COM i_dladm_set_flowprop_db(dladm_handle_t handle, const char *flow,
1678453SAnurag.Maskey@Sun.COM const char *prop_name, char **prop_val, uint_t val_cnt)
1688275SEric Cheng {
1698275SEric Cheng prop_db_state_t state;
1708275SEric Cheng
1718275SEric Cheng state.ls_op = process_prop_set;
1728275SEric Cheng state.ls_name = flow;
1738275SEric Cheng state.ls_propname = prop_name;
1748275SEric Cheng state.ls_propval = prop_val;
1758275SEric Cheng state.ls_valcntp = &val_cnt;
1768275SEric Cheng state.ls_initop = NULL;
1778275SEric Cheng
1788453SAnurag.Maskey@Sun.COM return (FLOWPROP_RW_DB(handle, &state, B_TRUE));
1798275SEric Cheng }
1808275SEric Cheng
1818275SEric Cheng static dladm_status_t
i_dladm_get_flowprop_db(dladm_handle_t handle,const char * flow,const char * prop_name,char ** prop_val,uint_t * val_cntp)1828453SAnurag.Maskey@Sun.COM i_dladm_get_flowprop_db(dladm_handle_t handle, const char *flow,
1838453SAnurag.Maskey@Sun.COM const char *prop_name, char **prop_val, uint_t *val_cntp)
1848275SEric Cheng {
1858275SEric Cheng prop_db_state_t state;
1868275SEric Cheng
1878275SEric Cheng state.ls_op = process_prop_get;
1888275SEric Cheng state.ls_name = flow;
1898275SEric Cheng state.ls_propname = prop_name;
1908275SEric Cheng state.ls_propval = prop_val;
1918275SEric Cheng state.ls_valcntp = val_cntp;
1928275SEric Cheng state.ls_initop = NULL;
1938275SEric Cheng
1948453SAnurag.Maskey@Sun.COM return (FLOWPROP_RW_DB(handle, &state, B_FALSE));
1958275SEric Cheng }
1968275SEric Cheng
1978275SEric Cheng dladm_status_t
i_dladm_init_flowprop_db(dladm_handle_t handle)1988453SAnurag.Maskey@Sun.COM i_dladm_init_flowprop_db(dladm_handle_t handle)
1998275SEric Cheng {
2008275SEric Cheng prop_db_state_t state;
2018275SEric Cheng
2028275SEric Cheng state.ls_op = process_prop_init;
2038275SEric Cheng state.ls_name = NULL;
2048275SEric Cheng state.ls_propname = NULL;
2058275SEric Cheng state.ls_propval = NULL;
2068275SEric Cheng state.ls_valcntp = NULL;
2078275SEric Cheng state.ls_initop = dladm_set_flowprop;
2088275SEric Cheng
2098453SAnurag.Maskey@Sun.COM return (FLOWPROP_RW_DB(handle, &state, B_FALSE));
2108275SEric Cheng }
2118275SEric Cheng
2128275SEric Cheng #define MIN_INFO_SIZE (4 * 1024)
2138275SEric Cheng
2148275SEric Cheng dladm_status_t
dladm_flow_info(dladm_handle_t handle,const char * flow,dladm_flow_attr_t * attr)2158453SAnurag.Maskey@Sun.COM dladm_flow_info(dladm_handle_t handle, const char *flow,
2168453SAnurag.Maskey@Sun.COM dladm_flow_attr_t *attr)
2178275SEric Cheng {
2188275SEric Cheng dld_ioc_walkflow_t *ioc;
2198453SAnurag.Maskey@Sun.COM int bufsize;
2208275SEric Cheng dld_flowinfo_t *flowinfo;
2218275SEric Cheng
2228275SEric Cheng if ((flow == NULL) || (attr == NULL))
2238275SEric Cheng return (DLADM_STATUS_BADARG);
2248275SEric Cheng
2258453SAnurag.Maskey@Sun.COM bufsize = MIN_INFO_SIZE;
2268453SAnurag.Maskey@Sun.COM if ((ioc = calloc(1, bufsize)) == NULL)
2278275SEric Cheng return (dladm_errno2status(errno));
2288275SEric Cheng
2298275SEric Cheng (void) strlcpy(ioc->wf_name, flow, sizeof (ioc->wf_name));
2308275SEric Cheng ioc->wf_len = bufsize - sizeof (*ioc);
2318275SEric Cheng
2328453SAnurag.Maskey@Sun.COM while (ioctl(dladm_dld_fd(handle), DLDIOC_WALKFLOW, ioc) < 0) {
2338275SEric Cheng if (errno == ENOSPC) {
2348275SEric Cheng bufsize *= 2;
2358275SEric Cheng ioc = realloc(ioc, bufsize);
2368275SEric Cheng if (ioc != NULL) {
2378275SEric Cheng (void) strlcpy(ioc->wf_name, flow,
2388558SGirish.Moodalbail@Sun.COM MAXFLOWNAMELEN);
2398275SEric Cheng ioc->wf_len = bufsize - sizeof (*ioc);
2408275SEric Cheng continue;
2418275SEric Cheng }
2428275SEric Cheng }
2438275SEric Cheng free(ioc);
2448275SEric Cheng return (dladm_errno2status(errno));
2458275SEric Cheng }
2468275SEric Cheng
2478275SEric Cheng bzero(attr, sizeof (*attr));
2488275SEric Cheng
2498275SEric Cheng flowinfo = (dld_flowinfo_t *)(void *)(ioc + 1);
2508275SEric Cheng
2518275SEric Cheng attr->fa_linkid = flowinfo->fi_linkid;
2528275SEric Cheng bcopy(&flowinfo->fi_flowname, &attr->fa_flowname,
2538275SEric Cheng sizeof (attr->fa_flowname));
2548275SEric Cheng bcopy(&flowinfo->fi_flow_desc, &attr->fa_flow_desc,
2558275SEric Cheng sizeof (attr->fa_flow_desc));
2568275SEric Cheng bcopy(&flowinfo->fi_resource_props, &attr->fa_resource_props,
2578275SEric Cheng sizeof (attr->fa_resource_props));
2588275SEric Cheng
2598275SEric Cheng free(ioc);
2608275SEric Cheng return (DLADM_STATUS_OK);
2618275SEric Cheng }
2628275SEric Cheng
2638275SEric Cheng /* ARGSUSED */
2648275SEric Cheng static dladm_status_t
do_get_maxbw(dladm_handle_t handle,const char * flow,char ** prop_val,uint_t * val_cnt)2658453SAnurag.Maskey@Sun.COM do_get_maxbw(dladm_handle_t handle, const char *flow, char **prop_val,
2668453SAnurag.Maskey@Sun.COM uint_t *val_cnt)
2678275SEric Cheng {
2688275SEric Cheng mac_resource_props_t *mrp;
2698275SEric Cheng char buf[DLADM_STRSIZE];
2708275SEric Cheng dladm_flow_attr_t fa;
2718275SEric Cheng dladm_status_t status;
2728275SEric Cheng
2738453SAnurag.Maskey@Sun.COM status = dladm_flow_info(handle, flow, &fa);
2748275SEric Cheng if (status != DLADM_STATUS_OK)
2758275SEric Cheng return (status);
2768275SEric Cheng mrp = &(fa.fa_resource_props);
2778275SEric Cheng
2788275SEric Cheng *val_cnt = 1;
2798275SEric Cheng if (mrp->mrp_mask & MRP_MAXBW) {
2808275SEric Cheng (void) snprintf(prop_val[0], DLADM_STRSIZE, "%s",
2818275SEric Cheng dladm_bw2str(mrp->mrp_maxbw, buf));
2828275SEric Cheng } else {
2838275SEric Cheng return (DLADM_STATUS_NOTSUP);
2848275SEric Cheng }
2858275SEric Cheng return (DLADM_STATUS_OK);
2868275SEric Cheng }
2878275SEric Cheng
2888275SEric Cheng /* ARGSUSED */
2898275SEric Cheng static dladm_status_t
do_set_maxbw(dladm_handle_t handle,const char * flow,val_desc_t * vdp,uint_t val_cnt)2908453SAnurag.Maskey@Sun.COM do_set_maxbw(dladm_handle_t handle, const char *flow, val_desc_t *vdp,
2918453SAnurag.Maskey@Sun.COM uint_t val_cnt)
2928275SEric Cheng {
2938275SEric Cheng dld_ioc_modifyflow_t attr;
2948275SEric Cheng mac_resource_props_t mrp;
2958275SEric Cheng void *val;
2968275SEric Cheng
2978275SEric Cheng if (val_cnt != 1)
2988275SEric Cheng return (DLADM_STATUS_BADVALCNT);
2998275SEric Cheng
3008275SEric Cheng bzero(&mrp, sizeof (mrp));
3018275SEric Cheng if (vdp != NULL && (val = (void *)vdp->vd_val) != NULL) {
3028275SEric Cheng bcopy(val, &mrp.mrp_maxbw, sizeof (int64_t));
3038275SEric Cheng free(val);
3048275SEric Cheng } else {
3058275SEric Cheng mrp.mrp_maxbw = MRP_MAXBW_RESETVAL;
3068275SEric Cheng }
3078275SEric Cheng mrp.mrp_mask = MRP_MAXBW;
3088275SEric Cheng
3098275SEric Cheng bzero(&attr, sizeof (attr));
3108275SEric Cheng (void) strlcpy(attr.mf_name, flow, sizeof (attr.mf_name));
3118275SEric Cheng bcopy(&mrp, &attr.mf_resource_props, sizeof (mac_resource_props_t));
3128275SEric Cheng
3138453SAnurag.Maskey@Sun.COM if (ioctl(dladm_dld_fd(handle), DLDIOC_MODIFYFLOW, &attr) < 0)
3148275SEric Cheng return (dladm_errno2status(errno));
3158275SEric Cheng
3168275SEric Cheng return (DLADM_STATUS_OK);
3178275SEric Cheng }
3188275SEric Cheng
3198275SEric Cheng /* ARGSUSED */
3208275SEric Cheng static dladm_status_t
do_check_maxbw(fprop_desc_t * pdp,char ** prop_val,uint_t val_cnt,val_desc_t ** vdpp)3218275SEric Cheng do_check_maxbw(fprop_desc_t *pdp, char **prop_val, uint_t val_cnt,
3228275SEric Cheng val_desc_t **vdpp)
3238275SEric Cheng {
3248275SEric Cheng uint64_t *maxbw;
3258275SEric Cheng val_desc_t *vdp = NULL;
3268275SEric Cheng dladm_status_t status = DLADM_STATUS_OK;
3278275SEric Cheng
3288275SEric Cheng if (val_cnt != 1)
3298275SEric Cheng return (DLADM_STATUS_BADVALCNT);
3308275SEric Cheng
3318275SEric Cheng maxbw = malloc(sizeof (uint64_t));
3328275SEric Cheng if (maxbw == NULL)
3338275SEric Cheng return (DLADM_STATUS_NOMEM);
3348275SEric Cheng
3358275SEric Cheng status = dladm_str2bw(*prop_val, maxbw);
3368275SEric Cheng if (status != DLADM_STATUS_OK) {
3378275SEric Cheng free(maxbw);
3388275SEric Cheng return (status);
3398275SEric Cheng }
3408275SEric Cheng
3418275SEric Cheng if ((*maxbw < MRP_MAXBW_MINVAL) && (*maxbw != 0)) {
3428275SEric Cheng free(maxbw);
3438275SEric Cheng return (DLADM_STATUS_MINMAXBW);
3448275SEric Cheng }
3458275SEric Cheng
3468275SEric Cheng vdp = malloc(sizeof (val_desc_t));
3478275SEric Cheng if (vdp == NULL) {
3488275SEric Cheng free(maxbw);
3498275SEric Cheng return (DLADM_STATUS_NOMEM);
3508275SEric Cheng }
3518275SEric Cheng
3528275SEric Cheng vdp->vd_val = (uintptr_t)maxbw;
3538275SEric Cheng *vdpp = vdp;
3548275SEric Cheng return (DLADM_STATUS_OK);
3558275SEric Cheng }
3568275SEric Cheng
3578275SEric Cheng /* ARGSUSED */
3588275SEric Cheng static dladm_status_t
do_get_priority(dladm_handle_t handle,const char * flow,char ** prop_val,uint_t * val_cnt)3598453SAnurag.Maskey@Sun.COM do_get_priority(dladm_handle_t handle, const char *flow, char **prop_val,
3608453SAnurag.Maskey@Sun.COM uint_t *val_cnt)
3618275SEric Cheng {
3628275SEric Cheng mac_resource_props_t *mrp;
3638275SEric Cheng char buf[DLADM_STRSIZE];
3648275SEric Cheng dladm_flow_attr_t fa;
3658275SEric Cheng dladm_status_t status;
3668275SEric Cheng
3678275SEric Cheng bzero(&fa, sizeof (dladm_flow_attr_t));
3688453SAnurag.Maskey@Sun.COM status = dladm_flow_info(handle, flow, &fa);
3698275SEric Cheng if (status != DLADM_STATUS_OK)
3708275SEric Cheng return (status);
3718275SEric Cheng mrp = &(fa.fa_resource_props);
3728275SEric Cheng
3738275SEric Cheng *val_cnt = 1;
3748275SEric Cheng if (mrp->mrp_mask & MRP_PRIORITY) {
3758275SEric Cheng (void) snprintf(prop_val[0], DLADM_STRSIZE, "%s",
3768275SEric Cheng dladm_pri2str(mrp->mrp_priority, buf));
3778275SEric Cheng } else {
3788275SEric Cheng return (DLADM_STATUS_NOTSUP);
3798275SEric Cheng }
3808275SEric Cheng return (DLADM_STATUS_OK);
3818275SEric Cheng }
3828275SEric Cheng
3838275SEric Cheng /* ARGSUSED */
3848275SEric Cheng static dladm_status_t
do_set_priority(dladm_handle_t handle,const char * flow,val_desc_t * vdp,uint_t val_cnt)3858453SAnurag.Maskey@Sun.COM do_set_priority(dladm_handle_t handle, const char *flow, val_desc_t *vdp,
3868453SAnurag.Maskey@Sun.COM uint_t val_cnt)
3878275SEric Cheng {
3888275SEric Cheng dld_ioc_modifyflow_t attr;
3898275SEric Cheng mac_resource_props_t mrp;
3908275SEric Cheng
3918275SEric Cheng if (val_cnt != 1)
3928275SEric Cheng return (DLADM_STATUS_BADVALCNT);
3938275SEric Cheng
3948275SEric Cheng bzero(&mrp, sizeof (mrp));
395*11878SVenu.Iyer@Sun.COM if (vdp != NULL) {
396*11878SVenu.Iyer@Sun.COM bcopy(&vdp->vd_val, &mrp.mrp_priority,
397*11878SVenu.Iyer@Sun.COM sizeof (mac_priority_level_t));
3988275SEric Cheng } else {
3998275SEric Cheng mrp.mrp_priority = MPL_RESET;
4008275SEric Cheng }
4018275SEric Cheng mrp.mrp_mask = MRP_PRIORITY;
4028275SEric Cheng
4038275SEric Cheng bzero(&attr, sizeof (attr));
4048275SEric Cheng (void) strlcpy(attr.mf_name, flow, sizeof (attr.mf_name));
4058275SEric Cheng bcopy(&mrp, &attr.mf_resource_props, sizeof (mac_resource_props_t));
4068275SEric Cheng
4078453SAnurag.Maskey@Sun.COM if (ioctl(dladm_dld_fd(handle), DLDIOC_MODIFYFLOW, &attr) < 0)
4088275SEric Cheng return (dladm_errno2status(errno));
4098275SEric Cheng
4108275SEric Cheng return (DLADM_STATUS_OK);
4118275SEric Cheng }
4128275SEric Cheng
4138275SEric Cheng /* ARGSUSED */
4148275SEric Cheng static dladm_status_t
do_check_priority(fprop_desc_t * pdp,char ** prop_val,uint_t val_cnt,val_desc_t ** vdpp)4158275SEric Cheng do_check_priority(fprop_desc_t *pdp, char **prop_val, uint_t val_cnt,
4168275SEric Cheng val_desc_t **vdpp)
4178275SEric Cheng {
418*11878SVenu.Iyer@Sun.COM mac_priority_level_t pri;
4198275SEric Cheng val_desc_t *vdp = NULL;
4208275SEric Cheng dladm_status_t status = DLADM_STATUS_OK;
4218275SEric Cheng
4228275SEric Cheng if (val_cnt != 1)
4238275SEric Cheng return (DLADM_STATUS_BADVALCNT);
4248275SEric Cheng
425*11878SVenu.Iyer@Sun.COM status = dladm_str2pri(*prop_val, &pri);
426*11878SVenu.Iyer@Sun.COM if (status != DLADM_STATUS_OK)
427*11878SVenu.Iyer@Sun.COM return (status);
428*11878SVenu.Iyer@Sun.COM
429*11878SVenu.Iyer@Sun.COM if (pri == -1)
430*11878SVenu.Iyer@Sun.COM return (DLADM_STATUS_BADVAL);
431*11878SVenu.Iyer@Sun.COM
432*11878SVenu.Iyer@Sun.COM vdp = malloc(sizeof (val_desc_t));
433*11878SVenu.Iyer@Sun.COM if (vdp == NULL)
4348275SEric Cheng return (DLADM_STATUS_NOMEM);
4358275SEric Cheng
436*11878SVenu.Iyer@Sun.COM vdp->vd_val = (uint_t)pri;
4378275SEric Cheng *vdpp = vdp;
4388275SEric Cheng return (DLADM_STATUS_OK);
4398275SEric Cheng }
4408275SEric Cheng
4418275SEric Cheng static dladm_status_t
flow_proplist_check(dladm_arg_list_t * proplist)4428275SEric Cheng flow_proplist_check(dladm_arg_list_t *proplist)
4438275SEric Cheng {
4448275SEric Cheng int i, j;
4458275SEric Cheng boolean_t matched;
4468275SEric Cheng
4478275SEric Cheng for (i = 0; i < proplist->al_count; i++) {
4488275SEric Cheng matched = B_FALSE;
4498275SEric Cheng for (j = 0; j < DLADM_MAX_FLOWPROPS; j++) {
4508275SEric Cheng if (strcmp(proplist->al_info[i].ai_name,
4518275SEric Cheng prop_table[j].pd_name) == 0)
4528275SEric Cheng matched = B_TRUE;
4538275SEric Cheng }
4548275SEric Cheng if (!matched)
4558275SEric Cheng return (DLADM_STATUS_BADPROP);
4568275SEric Cheng }
4578275SEric Cheng return (DLADM_STATUS_OK);
4588275SEric Cheng
4598275SEric Cheng }
4608275SEric Cheng
4618275SEric Cheng dladm_status_t
dladm_parse_flow_props(char * str,dladm_arg_list_t ** listp,boolean_t novalues)4628275SEric Cheng dladm_parse_flow_props(char *str, dladm_arg_list_t **listp, boolean_t novalues)
4638275SEric Cheng {
4648275SEric Cheng dladm_status_t status;
4658275SEric Cheng
4668275SEric Cheng status = dladm_parse_args(str, listp, novalues);
4678275SEric Cheng if (status != DLADM_STATUS_OK)
4688275SEric Cheng return (status);
4698275SEric Cheng
4709055SMichael.Lim@Sun.COM if (*listp != NULL && (status = flow_proplist_check(*listp)
4719055SMichael.Lim@Sun.COM != DLADM_STATUS_OK)) {
4728275SEric Cheng dladm_free_props(*listp);
4738275SEric Cheng return (status);
4748275SEric Cheng }
4758275SEric Cheng
4768275SEric Cheng return (DLADM_STATUS_OK);
4778275SEric Cheng }
4788275SEric Cheng
4798275SEric Cheng /*
4808275SEric Cheng * Retrieve the named property from a proplist, check the value and
4818275SEric Cheng * convert to a kernel structure.
4828275SEric Cheng */
4838275SEric Cheng static dladm_status_t
i_dladm_flow_proplist_extract_one(dladm_arg_list_t * proplist,const char * name,void * arg)4848275SEric Cheng i_dladm_flow_proplist_extract_one(dladm_arg_list_t *proplist,
48510734SEric Cheng const char *name, void *arg)
4868275SEric Cheng {
4878275SEric Cheng dladm_status_t status;
4888275SEric Cheng dladm_arg_info_t *aip = NULL;
4898275SEric Cheng int i, j;
4908275SEric Cheng
4918275SEric Cheng /* Find named property in proplist */
4928275SEric Cheng for (i = 0; i < proplist->al_count; i++) {
4938275SEric Cheng aip = &proplist->al_info[i];
4948275SEric Cheng if (strcasecmp(aip->ai_name, name) == 0)
4958275SEric Cheng break;
4968275SEric Cheng }
4978275SEric Cheng
4988275SEric Cheng /* Property not in list */
4998275SEric Cheng if (i == proplist->al_count)
5008275SEric Cheng return (DLADM_STATUS_OK);
5018275SEric Cheng
5028275SEric Cheng for (i = 0; i < DLADM_MAX_FLOWPROPS; i++) {
5038275SEric Cheng fprop_desc_t *pdp = &prop_table[i];
5048275SEric Cheng val_desc_t *vdp;
5058275SEric Cheng
5068275SEric Cheng vdp = malloc(sizeof (val_desc_t) * aip->ai_count);
5078275SEric Cheng if (vdp == NULL)
5088275SEric Cheng return (DLADM_STATUS_NOMEM);
5098275SEric Cheng
5108275SEric Cheng if (strcasecmp(aip->ai_name, pdp->pd_name) != 0)
5118275SEric Cheng continue;
5128275SEric Cheng
5138275SEric Cheng if (aip->ai_val == NULL)
5148275SEric Cheng return (DLADM_STATUS_BADARG);
5158275SEric Cheng
5168275SEric Cheng /* Check property value */
5178275SEric Cheng if (pdp->pd_check != NULL) {
5188275SEric Cheng status = pdp->pd_check(pdp, aip->ai_val,
5198275SEric Cheng aip->ai_count, &vdp);
5208275SEric Cheng } else {
5218275SEric Cheng status = DLADM_STATUS_BADARG;
5228275SEric Cheng }
5238275SEric Cheng
5248275SEric Cheng if (status != DLADM_STATUS_OK)
5258275SEric Cheng return (status);
5268275SEric Cheng
5278275SEric Cheng for (j = 0; j < DLADM_MAX_RSRC_PROP; j++) {
5288275SEric Cheng resource_prop_t *rpp = &rsrc_prop_table[j];
5298275SEric Cheng
5308275SEric Cheng if (strcasecmp(aip->ai_name, rpp->rp_name) != 0)
5318275SEric Cheng continue;
5328275SEric Cheng
5338275SEric Cheng /* Extract kernel structure */
5348275SEric Cheng if (rpp->rp_extract != NULL) {
53510734SEric Cheng status = rpp->rp_extract(vdp,
53610734SEric Cheng aip->ai_count, arg);
5378275SEric Cheng } else {
5388275SEric Cheng status = DLADM_STATUS_BADARG;
5398275SEric Cheng }
5408275SEric Cheng break;
5418275SEric Cheng }
5428275SEric Cheng
5438275SEric Cheng if (status != DLADM_STATUS_OK)
5448275SEric Cheng return (status);
5458275SEric Cheng
5468275SEric Cheng break;
5478275SEric Cheng }
5488275SEric Cheng return (status);
5498275SEric Cheng }
5508275SEric Cheng
5518275SEric Cheng /*
5528275SEric Cheng * Extract properties from a proplist and convert to mac_resource_props_t.
5538275SEric Cheng */
5548275SEric Cheng dladm_status_t
dladm_flow_proplist_extract(dladm_arg_list_t * proplist,mac_resource_props_t * mrp)5558275SEric Cheng dladm_flow_proplist_extract(dladm_arg_list_t *proplist,
5568275SEric Cheng mac_resource_props_t *mrp)
5578275SEric Cheng {
5588275SEric Cheng dladm_status_t status = DLADM_STATUS_OK;
5598275SEric Cheng
5608275SEric Cheng status = i_dladm_flow_proplist_extract_one(proplist, "maxbw", mrp);
5618275SEric Cheng if (status != DLADM_STATUS_OK)
5628275SEric Cheng return (status);
5638275SEric Cheng status = i_dladm_flow_proplist_extract_one(proplist, "priority", mrp);
5648275SEric Cheng if (status != DLADM_STATUS_OK)
5658275SEric Cheng return (status);
5668275SEric Cheng return (status);
5678275SEric Cheng }
5688275SEric Cheng
5698275SEric Cheng dladm_status_t
i_dladm_set_flow_proplist_db(dladm_handle_t handle,char * flow,dladm_arg_list_t * proplist)5708453SAnurag.Maskey@Sun.COM i_dladm_set_flow_proplist_db(dladm_handle_t handle, char *flow,
5718453SAnurag.Maskey@Sun.COM dladm_arg_list_t *proplist)
5728275SEric Cheng {
5738275SEric Cheng dladm_status_t status, ssave = DLADM_STATUS_OK;
5748275SEric Cheng dladm_arg_info_t ai;
5758275SEric Cheng int i;
5768275SEric Cheng
5778275SEric Cheng for (i = 0; i < proplist->al_count; i++) {
5788275SEric Cheng ai = proplist->al_info[i];
5798453SAnurag.Maskey@Sun.COM status = i_dladm_set_flowprop_db(handle, flow, ai.ai_name,
5808275SEric Cheng ai.ai_val, ai.ai_count);
5818275SEric Cheng if (status != DLADM_STATUS_OK)
5828275SEric Cheng ssave = status;
5838275SEric Cheng }
5848275SEric Cheng return (ssave);
5858275SEric Cheng }
586