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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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