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