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