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 /* 228558SGirish.Moodalbail@Sun.COM * Copyright 2009 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> 338275SEric Cheng #include <fcntl.h> 348275SEric Cheng #include <unistd.h> 358275SEric Cheng #include <libdevinfo.h> 368275SEric Cheng #include <libdladm_impl.h> 378275SEric Cheng #include <libdlflow.h> 388275SEric Cheng #include <libdlflow_impl.h> 398275SEric Cheng #include <libintl.h> 408275SEric Cheng 418275SEric Cheng #include <dlfcn.h> 428275SEric Cheng #include <link.h> 438275SEric Cheng 448275SEric Cheng /* 458275SEric Cheng * XXX duplicate define 468275SEric Cheng */ 478275SEric Cheng #define DLADM_PROP_VAL_MAX 32 488275SEric Cheng 498453SAnurag.Maskey@Sun.COM static dladm_status_t i_dladm_set_flowprop_db(dladm_handle_t, const char *, 508453SAnurag.Maskey@Sun.COM const char *, char **, uint_t); 518453SAnurag.Maskey@Sun.COM static dladm_status_t i_dladm_get_flowprop_db(dladm_handle_t, const char *, 528453SAnurag.Maskey@Sun.COM const char *, char **, uint_t *); 538275SEric Cheng 548275SEric Cheng static fpd_getf_t do_get_maxbw; 558275SEric Cheng static fpd_setf_t do_set_maxbw; 568275SEric Cheng static fpd_checkf_t do_check_maxbw; 578275SEric Cheng 588275SEric Cheng static fpd_getf_t do_get_priority; 598275SEric Cheng static fpd_setf_t do_set_priority; 608275SEric Cheng static fpd_checkf_t do_check_priority; 618275SEric Cheng 628275SEric Cheng static fprop_desc_t prop_table[] = { 638275SEric Cheng { "maxbw", { "", NULL }, NULL, 0, B_FALSE, 648275SEric Cheng do_set_maxbw, NULL, 658275SEric Cheng do_get_maxbw, do_check_maxbw}, 668275SEric Cheng { "priority", { "", NULL }, NULL, 0, B_FALSE, 678275SEric Cheng do_set_priority, NULL, 688275SEric Cheng do_get_priority, do_check_priority} 698275SEric Cheng }; 708275SEric Cheng 718275SEric Cheng #define DLADM_MAX_FLOWPROPS (sizeof (prop_table) / sizeof (fprop_desc_t)) 728275SEric Cheng 738275SEric Cheng static prop_table_t prop_tbl = { 748275SEric Cheng prop_table, 758275SEric Cheng DLADM_MAX_FLOWPROPS 768275SEric Cheng }; 778275SEric Cheng 788275SEric Cheng static resource_prop_t rsrc_prop_table[] = { 798275SEric Cheng {"maxbw", do_extract_maxbw}, 808275SEric Cheng {"priority", do_extract_priority} 818275SEric Cheng }; 828275SEric Cheng #define DLADM_MAX_RSRC_PROP (sizeof (rsrc_prop_table) / \ 838275SEric Cheng sizeof (resource_prop_t)) 848275SEric Cheng 858275SEric Cheng static dladm_status_t flow_proplist_check(dladm_arg_list_t *); 868275SEric Cheng 878275SEric Cheng dladm_status_t 888453SAnurag.Maskey@Sun.COM dladm_set_flowprop(dladm_handle_t handle, const char *flow, 898453SAnurag.Maskey@Sun.COM const char *prop_name, char **prop_val, uint_t val_cnt, uint_t flags, 908453SAnurag.Maskey@Sun.COM char **errprop) 918275SEric Cheng { 928275SEric Cheng dladm_status_t status = DLADM_STATUS_BADARG; 938275SEric Cheng 948275SEric Cheng if (flow == NULL || (prop_val == NULL && val_cnt > 0) || 958275SEric Cheng (prop_val != NULL && val_cnt == 0) || flags == 0) 968275SEric Cheng return (DLADM_STATUS_BADARG); 978275SEric Cheng 988275SEric Cheng if ((flags & DLADM_OPT_ACTIVE) != 0) { 998453SAnurag.Maskey@Sun.COM status = i_dladm_set_prop_temp(handle, flow, prop_name, 1008453SAnurag.Maskey@Sun.COM prop_val, val_cnt, flags, errprop, &prop_tbl); 1018275SEric Cheng if (status == DLADM_STATUS_TEMPONLY && 1028275SEric Cheng (flags & DLADM_OPT_PERSIST) != 0) 1038275SEric Cheng return (DLADM_STATUS_TEMPONLY); 1048275SEric Cheng if (status != DLADM_STATUS_OK) 1058275SEric Cheng return (status); 1068275SEric Cheng } 1078275SEric Cheng if ((flags & DLADM_OPT_PERSIST) != 0) { 1088275SEric Cheng if (i_dladm_is_prop_temponly(prop_name, errprop, &prop_tbl)) 1098275SEric Cheng return (DLADM_STATUS_TEMPONLY); 1108275SEric Cheng 1118453SAnurag.Maskey@Sun.COM status = i_dladm_set_flowprop_db(handle, flow, prop_name, 1128275SEric Cheng prop_val, val_cnt); 1138275SEric Cheng } 1148275SEric Cheng return (status); 1158275SEric Cheng } 1168275SEric Cheng 1178275SEric Cheng dladm_status_t 1188275SEric Cheng dladm_walk_flowprop(int (*func)(void *, const char *), const char *flow, 1198275SEric Cheng void *arg) 1208275SEric Cheng { 1218275SEric Cheng int i; 1228275SEric Cheng 1238275SEric Cheng if (flow == NULL || func == NULL) 1248275SEric Cheng return (DLADM_STATUS_BADARG); 1258275SEric Cheng 1268275SEric Cheng /* Then show data-flow properties if there are any */ 1278275SEric Cheng for (i = 0; i < DLADM_MAX_FLOWPROPS; i++) { 1288275SEric Cheng if (func(arg, prop_table[i].pd_name) != DLADM_WALK_CONTINUE) 1298275SEric Cheng break; 1308275SEric Cheng } 1318275SEric Cheng return (DLADM_STATUS_OK); 1328275SEric Cheng } 1338275SEric Cheng 1348275SEric Cheng dladm_status_t 1358453SAnurag.Maskey@Sun.COM dladm_get_flowprop(dladm_handle_t handle, const char *flow, uint32_t type, 1368275SEric Cheng const char *prop_name, char **prop_val, uint_t *val_cntp) 1378275SEric Cheng { 1388275SEric Cheng dladm_status_t status; 1398275SEric Cheng 1408275SEric Cheng if (flow == NULL || prop_name == NULL || prop_val == NULL || 1418275SEric Cheng val_cntp == NULL || *val_cntp == 0) 1428275SEric Cheng return (DLADM_STATUS_BADARG); 1438275SEric Cheng 1448275SEric Cheng if (type == DLADM_PROP_VAL_PERSISTENT) { 1458275SEric Cheng if (i_dladm_is_prop_temponly(prop_name, NULL, &prop_tbl)) 1468275SEric Cheng return (DLADM_STATUS_TEMPONLY); 1478453SAnurag.Maskey@Sun.COM return (i_dladm_get_flowprop_db(handle, flow, prop_name, 1488275SEric Cheng prop_val, val_cntp)); 1498275SEric Cheng } 1508275SEric Cheng 1518453SAnurag.Maskey@Sun.COM status = i_dladm_get_prop_temp(handle, flow, type, prop_name, 1528275SEric Cheng prop_val, val_cntp, &prop_tbl); 1538275SEric Cheng if (status != DLADM_STATUS_NOTFOUND) 1548275SEric Cheng return (status); 1558275SEric Cheng 1568275SEric Cheng return (DLADM_STATUS_BADARG); 1578275SEric Cheng } 1588275SEric Cheng 1598453SAnurag.Maskey@Sun.COM #define FLOWPROP_RW_DB(handle, statep, writeop) \ 1608453SAnurag.Maskey@Sun.COM (i_dladm_rw_db(handle, "/etc/dladm/flowprop.conf", \ 1618275SEric Cheng S_IRUSR | S_IWUSR | S_IRGRP | S_IROTH, process_prop_db, \ 1628275SEric Cheng (statep), (writeop))) 1638275SEric Cheng 1648275SEric Cheng static dladm_status_t 1658453SAnurag.Maskey@Sun.COM i_dladm_set_flowprop_db(dladm_handle_t handle, const char *flow, 1668453SAnurag.Maskey@Sun.COM const char *prop_name, char **prop_val, uint_t val_cnt) 1678275SEric Cheng { 1688275SEric Cheng prop_db_state_t state; 1698275SEric Cheng 1708275SEric Cheng state.ls_op = process_prop_set; 1718275SEric Cheng state.ls_name = flow; 1728275SEric Cheng state.ls_propname = prop_name; 1738275SEric Cheng state.ls_propval = prop_val; 1748275SEric Cheng state.ls_valcntp = &val_cnt; 1758275SEric Cheng state.ls_initop = NULL; 1768275SEric Cheng 1778453SAnurag.Maskey@Sun.COM return (FLOWPROP_RW_DB(handle, &state, B_TRUE)); 1788275SEric Cheng } 1798275SEric Cheng 1808275SEric Cheng static dladm_status_t 1818453SAnurag.Maskey@Sun.COM i_dladm_get_flowprop_db(dladm_handle_t handle, const char *flow, 1828453SAnurag.Maskey@Sun.COM const char *prop_name, char **prop_val, uint_t *val_cntp) 1838275SEric Cheng { 1848275SEric Cheng prop_db_state_t state; 1858275SEric Cheng 1868275SEric Cheng state.ls_op = process_prop_get; 1878275SEric Cheng state.ls_name = flow; 1888275SEric Cheng state.ls_propname = prop_name; 1898275SEric Cheng state.ls_propval = prop_val; 1908275SEric Cheng state.ls_valcntp = val_cntp; 1918275SEric Cheng state.ls_initop = NULL; 1928275SEric Cheng 1938453SAnurag.Maskey@Sun.COM return (FLOWPROP_RW_DB(handle, &state, B_FALSE)); 1948275SEric Cheng } 1958275SEric Cheng 1968275SEric Cheng dladm_status_t 1978453SAnurag.Maskey@Sun.COM i_dladm_init_flowprop_db(dladm_handle_t handle) 1988275SEric Cheng { 1998275SEric Cheng prop_db_state_t state; 2008275SEric Cheng 2018275SEric Cheng state.ls_op = process_prop_init; 2028275SEric Cheng state.ls_name = NULL; 2038275SEric Cheng state.ls_propname = NULL; 2048275SEric Cheng state.ls_propval = NULL; 2058275SEric Cheng state.ls_valcntp = NULL; 2068275SEric Cheng state.ls_initop = dladm_set_flowprop; 2078275SEric Cheng 2088453SAnurag.Maskey@Sun.COM return (FLOWPROP_RW_DB(handle, &state, B_FALSE)); 2098275SEric Cheng } 2108275SEric Cheng 2118275SEric Cheng #define MIN_INFO_SIZE (4 * 1024) 2128275SEric Cheng 2138275SEric Cheng dladm_status_t 2148453SAnurag.Maskey@Sun.COM dladm_flow_info(dladm_handle_t handle, const char *flow, 2158453SAnurag.Maskey@Sun.COM dladm_flow_attr_t *attr) 2168275SEric Cheng { 2178275SEric Cheng dld_ioc_walkflow_t *ioc; 2188453SAnurag.Maskey@Sun.COM int bufsize; 2198275SEric Cheng dld_flowinfo_t *flowinfo; 2208275SEric Cheng 2218275SEric Cheng if ((flow == NULL) || (attr == NULL)) 2228275SEric Cheng return (DLADM_STATUS_BADARG); 2238275SEric Cheng 2248453SAnurag.Maskey@Sun.COM bufsize = MIN_INFO_SIZE; 2258453SAnurag.Maskey@Sun.COM if ((ioc = calloc(1, bufsize)) == NULL) 2268275SEric Cheng return (dladm_errno2status(errno)); 2278275SEric Cheng 2288275SEric Cheng (void) strlcpy(ioc->wf_name, flow, sizeof (ioc->wf_name)); 2298275SEric Cheng ioc->wf_len = bufsize - sizeof (*ioc); 2308275SEric Cheng 2318453SAnurag.Maskey@Sun.COM while (ioctl(dladm_dld_fd(handle), DLDIOC_WALKFLOW, ioc) < 0) { 2328275SEric Cheng if (errno == ENOSPC) { 2338275SEric Cheng bufsize *= 2; 2348275SEric Cheng ioc = realloc(ioc, bufsize); 2358275SEric Cheng if (ioc != NULL) { 2368275SEric Cheng (void) strlcpy(ioc->wf_name, flow, 2378558SGirish.Moodalbail@Sun.COM MAXFLOWNAMELEN); 2388275SEric Cheng ioc->wf_len = bufsize - sizeof (*ioc); 2398275SEric Cheng continue; 2408275SEric Cheng } 2418275SEric Cheng } 2428275SEric Cheng free(ioc); 2438275SEric Cheng return (dladm_errno2status(errno)); 2448275SEric Cheng } 2458275SEric Cheng 2468275SEric Cheng bzero(attr, sizeof (*attr)); 2478275SEric Cheng 2488275SEric Cheng flowinfo = (dld_flowinfo_t *)(void *)(ioc + 1); 2498275SEric Cheng 2508275SEric Cheng attr->fa_linkid = flowinfo->fi_linkid; 2518275SEric Cheng bcopy(&flowinfo->fi_flowname, &attr->fa_flowname, 2528275SEric Cheng sizeof (attr->fa_flowname)); 2538275SEric Cheng bcopy(&flowinfo->fi_flow_desc, &attr->fa_flow_desc, 2548275SEric Cheng sizeof (attr->fa_flow_desc)); 2558275SEric Cheng bcopy(&flowinfo->fi_resource_props, &attr->fa_resource_props, 2568275SEric Cheng sizeof (attr->fa_resource_props)); 2578275SEric Cheng 2588275SEric Cheng free(ioc); 2598275SEric Cheng return (DLADM_STATUS_OK); 2608275SEric Cheng } 2618275SEric Cheng 2628275SEric Cheng /* ARGSUSED */ 2638275SEric Cheng static dladm_status_t 2648453SAnurag.Maskey@Sun.COM do_get_maxbw(dladm_handle_t handle, const char *flow, char **prop_val, 2658453SAnurag.Maskey@Sun.COM uint_t *val_cnt) 2668275SEric Cheng { 2678275SEric Cheng mac_resource_props_t *mrp; 2688275SEric Cheng char buf[DLADM_STRSIZE]; 2698275SEric Cheng dladm_flow_attr_t fa; 2708275SEric Cheng dladm_status_t status; 2718275SEric Cheng 2728453SAnurag.Maskey@Sun.COM status = dladm_flow_info(handle, flow, &fa); 2738275SEric Cheng if (status != DLADM_STATUS_OK) 2748275SEric Cheng return (status); 2758275SEric Cheng mrp = &(fa.fa_resource_props); 2768275SEric Cheng 2778275SEric Cheng *val_cnt = 1; 2788275SEric Cheng if (mrp->mrp_mask & MRP_MAXBW) { 2798275SEric Cheng (void) snprintf(prop_val[0], DLADM_STRSIZE, "%s", 2808275SEric Cheng dladm_bw2str(mrp->mrp_maxbw, buf)); 2818275SEric Cheng } else { 2828275SEric Cheng return (DLADM_STATUS_NOTSUP); 2838275SEric Cheng } 2848275SEric Cheng return (DLADM_STATUS_OK); 2858275SEric Cheng } 2868275SEric Cheng 2878275SEric Cheng /* ARGSUSED */ 2888275SEric Cheng static dladm_status_t 2898453SAnurag.Maskey@Sun.COM do_set_maxbw(dladm_handle_t handle, const char *flow, val_desc_t *vdp, 2908453SAnurag.Maskey@Sun.COM uint_t val_cnt) 2918275SEric Cheng { 2928275SEric Cheng dld_ioc_modifyflow_t attr; 2938275SEric Cheng mac_resource_props_t mrp; 2948275SEric Cheng void *val; 2958275SEric Cheng 2968275SEric Cheng if (val_cnt != 1) 2978275SEric Cheng return (DLADM_STATUS_BADVALCNT); 2988275SEric Cheng 2998275SEric Cheng bzero(&mrp, sizeof (mrp)); 3008275SEric Cheng if (vdp != NULL && (val = (void *)vdp->vd_val) != NULL) { 3018275SEric Cheng bcopy(val, &mrp.mrp_maxbw, sizeof (int64_t)); 3028275SEric Cheng free(val); 3038275SEric Cheng } else { 3048275SEric Cheng mrp.mrp_maxbw = MRP_MAXBW_RESETVAL; 3058275SEric Cheng } 3068275SEric Cheng mrp.mrp_mask = MRP_MAXBW; 3078275SEric Cheng 3088275SEric Cheng bzero(&attr, sizeof (attr)); 3098275SEric Cheng (void) strlcpy(attr.mf_name, flow, sizeof (attr.mf_name)); 3108275SEric Cheng bcopy(&mrp, &attr.mf_resource_props, sizeof (mac_resource_props_t)); 3118275SEric Cheng 3128453SAnurag.Maskey@Sun.COM if (ioctl(dladm_dld_fd(handle), DLDIOC_MODIFYFLOW, &attr) < 0) 3138275SEric Cheng return (dladm_errno2status(errno)); 3148275SEric Cheng 3158275SEric Cheng return (DLADM_STATUS_OK); 3168275SEric Cheng } 3178275SEric Cheng 3188275SEric Cheng /* ARGSUSED */ 3198275SEric Cheng static dladm_status_t 3208275SEric Cheng do_check_maxbw(fprop_desc_t *pdp, char **prop_val, uint_t val_cnt, 3218275SEric Cheng val_desc_t **vdpp) 3228275SEric Cheng { 3238275SEric Cheng uint64_t *maxbw; 3248275SEric Cheng val_desc_t *vdp = NULL; 3258275SEric Cheng dladm_status_t status = DLADM_STATUS_OK; 3268275SEric Cheng 3278275SEric Cheng if (val_cnt != 1) 3288275SEric Cheng return (DLADM_STATUS_BADVALCNT); 3298275SEric Cheng 3308275SEric Cheng maxbw = malloc(sizeof (uint64_t)); 3318275SEric Cheng if (maxbw == NULL) 3328275SEric Cheng return (DLADM_STATUS_NOMEM); 3338275SEric Cheng 3348275SEric Cheng status = dladm_str2bw(*prop_val, maxbw); 3358275SEric Cheng if (status != DLADM_STATUS_OK) { 3368275SEric Cheng free(maxbw); 3378275SEric Cheng return (status); 3388275SEric Cheng } 3398275SEric Cheng 3408275SEric Cheng if ((*maxbw < MRP_MAXBW_MINVAL) && (*maxbw != 0)) { 3418275SEric Cheng free(maxbw); 3428275SEric Cheng return (DLADM_STATUS_MINMAXBW); 3438275SEric Cheng } 3448275SEric Cheng 3458275SEric Cheng vdp = malloc(sizeof (val_desc_t)); 3468275SEric Cheng if (vdp == NULL) { 3478275SEric Cheng free(maxbw); 3488275SEric Cheng return (DLADM_STATUS_NOMEM); 3498275SEric Cheng } 3508275SEric Cheng 3518275SEric Cheng vdp->vd_val = (uintptr_t)maxbw; 3528275SEric Cheng *vdpp = vdp; 3538275SEric Cheng return (DLADM_STATUS_OK); 3548275SEric Cheng } 3558275SEric Cheng 3568275SEric Cheng /* ARGSUSED */ 3578275SEric Cheng static dladm_status_t 3588453SAnurag.Maskey@Sun.COM do_get_priority(dladm_handle_t handle, const char *flow, char **prop_val, 3598453SAnurag.Maskey@Sun.COM uint_t *val_cnt) 3608275SEric Cheng { 3618275SEric Cheng mac_resource_props_t *mrp; 3628275SEric Cheng char buf[DLADM_STRSIZE]; 3638275SEric Cheng dladm_flow_attr_t fa; 3648275SEric Cheng dladm_status_t status; 3658275SEric Cheng 3668275SEric Cheng bzero(&fa, sizeof (dladm_flow_attr_t)); 3678453SAnurag.Maskey@Sun.COM status = dladm_flow_info(handle, flow, &fa); 3688275SEric Cheng if (status != DLADM_STATUS_OK) 3698275SEric Cheng return (status); 3708275SEric Cheng mrp = &(fa.fa_resource_props); 3718275SEric Cheng 3728275SEric Cheng *val_cnt = 1; 3738275SEric Cheng if (mrp->mrp_mask & MRP_PRIORITY) { 3748275SEric Cheng (void) snprintf(prop_val[0], DLADM_STRSIZE, "%s", 3758275SEric Cheng dladm_pri2str(mrp->mrp_priority, buf)); 3768275SEric Cheng } else { 3778275SEric Cheng return (DLADM_STATUS_NOTSUP); 3788275SEric Cheng } 3798275SEric Cheng return (DLADM_STATUS_OK); 3808275SEric Cheng } 3818275SEric Cheng 3828275SEric Cheng /* ARGSUSED */ 3838275SEric Cheng static dladm_status_t 3848453SAnurag.Maskey@Sun.COM do_set_priority(dladm_handle_t handle, const char *flow, val_desc_t *vdp, 3858453SAnurag.Maskey@Sun.COM uint_t val_cnt) 3868275SEric Cheng { 3878275SEric Cheng dld_ioc_modifyflow_t attr; 3888275SEric Cheng mac_resource_props_t mrp; 3898275SEric Cheng void *val; 3908275SEric Cheng 3918275SEric Cheng if (val_cnt != 1) 3928275SEric Cheng return (DLADM_STATUS_BADVALCNT); 3938275SEric Cheng 3948275SEric Cheng bzero(&mrp, sizeof (mrp)); 3958275SEric Cheng if (vdp != NULL && (val = (void *)vdp->vd_val) != NULL) { 3968275SEric Cheng bcopy(val, &mrp.mrp_priority, sizeof (mac_priority_level_t)); 3978275SEric Cheng free(val); 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 4158275SEric Cheng do_check_priority(fprop_desc_t *pdp, char **prop_val, uint_t val_cnt, 4168275SEric Cheng val_desc_t **vdpp) 4178275SEric Cheng { 4188275SEric Cheng 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 4258275SEric Cheng pri = malloc(sizeof (mac_priority_level_t)); 4268275SEric Cheng if (pri == NULL) 4278275SEric Cheng return (DLADM_STATUS_NOMEM); 4288275SEric Cheng 4298275SEric Cheng status = dladm_str2pri(*prop_val, pri); 4308275SEric Cheng if (status != DLADM_STATUS_OK) { 4318275SEric Cheng free(pri); 4328275SEric Cheng return (status); 4338275SEric Cheng } 4348275SEric Cheng 4358275SEric Cheng if (*pri == -1) { 4368275SEric Cheng free(pri); 4378275SEric Cheng return (DLADM_STATUS_BADVAL); 4388275SEric Cheng } 4398275SEric Cheng 4408275SEric Cheng vdp = malloc(sizeof (val_desc_t)); 4418275SEric Cheng if (vdp == NULL) { 4428275SEric Cheng free(pri); 4438275SEric Cheng return (DLADM_STATUS_NOMEM); 4448275SEric Cheng } 4458275SEric Cheng 4468275SEric Cheng vdp->vd_val = (uintptr_t)pri; 4478275SEric Cheng *vdpp = vdp; 4488275SEric Cheng return (DLADM_STATUS_OK); 4498275SEric Cheng } 4508275SEric Cheng 4518275SEric Cheng static dladm_status_t 4528275SEric Cheng flow_proplist_check(dladm_arg_list_t *proplist) 4538275SEric Cheng { 4548275SEric Cheng int i, j; 4558275SEric Cheng boolean_t matched; 4568275SEric Cheng 4578275SEric Cheng for (i = 0; i < proplist->al_count; i++) { 4588275SEric Cheng matched = B_FALSE; 4598275SEric Cheng for (j = 0; j < DLADM_MAX_FLOWPROPS; j++) { 4608275SEric Cheng if (strcmp(proplist->al_info[i].ai_name, 4618275SEric Cheng prop_table[j].pd_name) == 0) 4628275SEric Cheng matched = B_TRUE; 4638275SEric Cheng } 4648275SEric Cheng if (!matched) 4658275SEric Cheng return (DLADM_STATUS_BADPROP); 4668275SEric Cheng } 4678275SEric Cheng return (DLADM_STATUS_OK); 4688275SEric Cheng 4698275SEric Cheng } 4708275SEric Cheng 4718275SEric Cheng dladm_status_t 4728275SEric Cheng dladm_parse_flow_props(char *str, dladm_arg_list_t **listp, boolean_t novalues) 4738275SEric Cheng { 4748275SEric Cheng dladm_status_t status; 4758275SEric Cheng 4768275SEric Cheng status = dladm_parse_args(str, listp, novalues); 4778275SEric Cheng if (status != DLADM_STATUS_OK) 4788275SEric Cheng return (status); 4798275SEric Cheng 480*9055SMichael.Lim@Sun.COM if (*listp != NULL && (status = flow_proplist_check(*listp) 481*9055SMichael.Lim@Sun.COM != DLADM_STATUS_OK)) { 4828275SEric Cheng dladm_free_props(*listp); 4838275SEric Cheng return (status); 4848275SEric Cheng } 4858275SEric Cheng 4868275SEric Cheng return (DLADM_STATUS_OK); 4878275SEric Cheng } 4888275SEric Cheng 4898275SEric Cheng /* 4908275SEric Cheng * Retrieve the named property from a proplist, check the value and 4918275SEric Cheng * convert to a kernel structure. 4928275SEric Cheng */ 4938275SEric Cheng static dladm_status_t 4948275SEric Cheng i_dladm_flow_proplist_extract_one(dladm_arg_list_t *proplist, 4958275SEric Cheng const char *name, void *val) 4968275SEric Cheng { 4978275SEric Cheng dladm_status_t status; 4988275SEric Cheng dladm_arg_info_t *aip = NULL; 4998275SEric Cheng int i, j; 5008275SEric Cheng 5018275SEric Cheng /* Find named property in proplist */ 5028275SEric Cheng for (i = 0; i < proplist->al_count; i++) { 5038275SEric Cheng aip = &proplist->al_info[i]; 5048275SEric Cheng if (strcasecmp(aip->ai_name, name) == 0) 5058275SEric Cheng break; 5068275SEric Cheng } 5078275SEric Cheng 5088275SEric Cheng /* Property not in list */ 5098275SEric Cheng if (i == proplist->al_count) 5108275SEric Cheng return (DLADM_STATUS_OK); 5118275SEric Cheng 5128275SEric Cheng for (i = 0; i < DLADM_MAX_FLOWPROPS; i++) { 5138275SEric Cheng fprop_desc_t *pdp = &prop_table[i]; 5148275SEric Cheng val_desc_t *vdp; 5158275SEric Cheng 5168275SEric Cheng vdp = malloc(sizeof (val_desc_t) * aip->ai_count); 5178275SEric Cheng if (vdp == NULL) 5188275SEric Cheng return (DLADM_STATUS_NOMEM); 5198275SEric Cheng 5208275SEric Cheng if (strcasecmp(aip->ai_name, pdp->pd_name) != 0) 5218275SEric Cheng continue; 5228275SEric Cheng 5238275SEric Cheng if (aip->ai_val == NULL) 5248275SEric Cheng return (DLADM_STATUS_BADARG); 5258275SEric Cheng 5268275SEric Cheng /* Check property value */ 5278275SEric Cheng if (pdp->pd_check != NULL) { 5288275SEric Cheng status = pdp->pd_check(pdp, aip->ai_val, 5298275SEric Cheng aip->ai_count, &vdp); 5308275SEric Cheng } else { 5318275SEric Cheng status = DLADM_STATUS_BADARG; 5328275SEric Cheng } 5338275SEric Cheng 5348275SEric Cheng if (status != DLADM_STATUS_OK) 5358275SEric Cheng return (status); 5368275SEric Cheng 5378275SEric Cheng for (j = 0; j < DLADM_MAX_RSRC_PROP; j++) { 5388275SEric Cheng resource_prop_t *rpp = &rsrc_prop_table[j]; 5398275SEric Cheng 5408275SEric Cheng if (strcasecmp(aip->ai_name, rpp->rp_name) != 0) 5418275SEric Cheng continue; 5428275SEric Cheng 5438275SEric Cheng /* Extract kernel structure */ 5448275SEric Cheng if (rpp->rp_extract != NULL) { 5458275SEric Cheng status = rpp->rp_extract(vdp, val, 5468275SEric Cheng aip->ai_count); 5478275SEric Cheng } else { 5488275SEric Cheng status = DLADM_STATUS_BADARG; 5498275SEric Cheng } 5508275SEric Cheng break; 5518275SEric Cheng } 5528275SEric Cheng 5538275SEric Cheng if (status != DLADM_STATUS_OK) 5548275SEric Cheng return (status); 5558275SEric Cheng 5568275SEric Cheng break; 5578275SEric Cheng } 5588275SEric Cheng return (status); 5598275SEric Cheng } 5608275SEric Cheng 5618275SEric Cheng /* 5628275SEric Cheng * Extract properties from a proplist and convert to mac_resource_props_t. 5638275SEric Cheng */ 5648275SEric Cheng dladm_status_t 5658275SEric Cheng dladm_flow_proplist_extract(dladm_arg_list_t *proplist, 5668275SEric Cheng mac_resource_props_t *mrp) 5678275SEric Cheng { 5688275SEric Cheng dladm_status_t status = DLADM_STATUS_OK; 5698275SEric Cheng 5708275SEric Cheng status = i_dladm_flow_proplist_extract_one(proplist, "maxbw", mrp); 5718275SEric Cheng if (status != DLADM_STATUS_OK) 5728275SEric Cheng return (status); 5738275SEric Cheng status = i_dladm_flow_proplist_extract_one(proplist, "priority", mrp); 5748275SEric Cheng if (status != DLADM_STATUS_OK) 5758275SEric Cheng return (status); 5768275SEric Cheng return (status); 5778275SEric Cheng } 5788275SEric Cheng 5798275SEric Cheng dladm_status_t 5808453SAnurag.Maskey@Sun.COM i_dladm_set_flow_proplist_db(dladm_handle_t handle, char *flow, 5818453SAnurag.Maskey@Sun.COM dladm_arg_list_t *proplist) 5828275SEric Cheng { 5838275SEric Cheng dladm_status_t status, ssave = DLADM_STATUS_OK; 5848275SEric Cheng dladm_arg_info_t ai; 5858275SEric Cheng int i; 5868275SEric Cheng 5878275SEric Cheng for (i = 0; i < proplist->al_count; i++) { 5888275SEric Cheng ai = proplist->al_info[i]; 5898453SAnurag.Maskey@Sun.COM status = i_dladm_set_flowprop_db(handle, flow, ai.ai_name, 5908275SEric Cheng ai.ai_val, ai.ai_count); 5918275SEric Cheng if (status != DLADM_STATUS_OK) 5928275SEric Cheng ssave = status; 5938275SEric Cheng } 5948275SEric Cheng return (ssave); 5958275SEric Cheng } 596