12a8164dfSZhong Wang /* 22a8164dfSZhong Wang * CDDL HEADER START 32a8164dfSZhong Wang * 42a8164dfSZhong Wang * The contents of this file are subject to the terms of the 52a8164dfSZhong Wang * Common Development and Distribution License (the "License"). 62a8164dfSZhong Wang * You may not use this file except in compliance with the License. 72a8164dfSZhong Wang * 82a8164dfSZhong Wang * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE 92a8164dfSZhong Wang * or http://www.opensolaris.org/os/licensing. 102a8164dfSZhong Wang * See the License for the specific language governing permissions 112a8164dfSZhong Wang * and limitations under the License. 122a8164dfSZhong Wang * 132a8164dfSZhong Wang * When distributing Covered Code, include this CDDL HEADER in each 142a8164dfSZhong Wang * file and include the License file at usr/src/OPENSOLARIS.LICENSE. 152a8164dfSZhong Wang * If applicable, add the following below this CDDL HEADER, with the 162a8164dfSZhong Wang * fields enclosed by brackets "[]" replaced with your own identifying 172a8164dfSZhong Wang * information: Portions Copyright [yyyy] [name of copyright owner] 182a8164dfSZhong Wang * 192a8164dfSZhong Wang * CDDL HEADER END 202a8164dfSZhong Wang */ 212a8164dfSZhong Wang /* 222a8164dfSZhong Wang * Copyright 2009 Sun Microsystems, Inc. All rights reserved. 232a8164dfSZhong Wang * Use is subject to license terms. 242a8164dfSZhong Wang */ 252a8164dfSZhong Wang 262a8164dfSZhong Wang #include <stdlib.h> 272a8164dfSZhong Wang #include <stdio.h> 282a8164dfSZhong Wang #include <wchar.h> 292a8164dfSZhong Wang #include <strings.h> 302a8164dfSZhong Wang #include <sys/types.h> 312a8164dfSZhong Wang #include <sys/stat.h> 322a8164dfSZhong Wang #include <fcntl.h> 332a8164dfSZhong Wang #include <unistd.h> 342a8164dfSZhong Wang #include <libintl.h> 352a8164dfSZhong Wang #include <errno.h> 362a8164dfSZhong Wang #include <string.h> 372a8164dfSZhong Wang #include <assert.h> 382a8164dfSZhong Wang #include <syslog.h> 392a8164dfSZhong Wang #include <libfcoe.h> 40d4401b99SKelly Hu #include <libdllink.h> 412a8164dfSZhong Wang #include <fcoeio.h> 42*e6eb57e7SKevin Yu #include <libscf.h> 43*e6eb57e7SKevin Yu #include <inttypes.h> 442a8164dfSZhong Wang 452a8164dfSZhong Wang #define FCOE_DEV_PATH "/devices/fcoe:admin" 462a8164dfSZhong Wang 472a8164dfSZhong Wang #define OPEN_FCOE 0 482a8164dfSZhong Wang #define OPEN_EXCL_FCOE O_EXCL 492a8164dfSZhong Wang 502a8164dfSZhong Wang /* 512a8164dfSZhong Wang * Open for fcoe module 522a8164dfSZhong Wang * 532a8164dfSZhong Wang * flag - open flag (OPEN_FCOE, OPEN_EXCL_FCOE) 542a8164dfSZhong Wang * fd - pointer to integer. On success, contains the fcoe file descriptor 552a8164dfSZhong Wang */ 562a8164dfSZhong Wang static int 572a8164dfSZhong Wang openFcoe(int flag, int *fd) 582a8164dfSZhong Wang { 592a8164dfSZhong Wang int ret = FCOE_STATUS_ERROR; 602a8164dfSZhong Wang 612a8164dfSZhong Wang if ((*fd = open(FCOE_DEV_PATH, O_NDELAY | O_RDONLY | flag)) != -1) { 622a8164dfSZhong Wang ret = FCOE_STATUS_OK; 632a8164dfSZhong Wang } else { 642a8164dfSZhong Wang if (errno == EPERM || errno == EACCES) { 652a8164dfSZhong Wang ret = FCOE_STATUS_ERROR_PERM; 662a8164dfSZhong Wang } else { 672a8164dfSZhong Wang ret = FCOE_STATUS_ERROR_OPEN_DEV; 682a8164dfSZhong Wang } 692a8164dfSZhong Wang syslog(LOG_DEBUG, "openFcoe:open failure:%s:errno(%d)", 702a8164dfSZhong Wang FCOE_DEV_PATH, errno); 712a8164dfSZhong Wang } 722a8164dfSZhong Wang 732a8164dfSZhong Wang return (ret); 742a8164dfSZhong Wang } 752a8164dfSZhong Wang 76*e6eb57e7SKevin Yu static void 77*e6eb57e7SKevin Yu WWN2str(char *buf, FCOE_PORT_WWN *wwn) { 78*e6eb57e7SKevin Yu int j; 79*e6eb57e7SKevin Yu unsigned char *pc = (unsigned char *)&(wwn->wwn[0]); 80*e6eb57e7SKevin Yu buf[0] = '\0'; 81*e6eb57e7SKevin Yu for (j = 0; j < 16; j += 2) { 82*e6eb57e7SKevin Yu (void) sprintf(&buf[j], "%02X", (int)*pc++); 83*e6eb57e7SKevin Yu } 84*e6eb57e7SKevin Yu } 85*e6eb57e7SKevin Yu 862a8164dfSZhong Wang static int 872a8164dfSZhong Wang isWWNZero(FCOE_PORT_WWN portwwn) 882a8164dfSZhong Wang { 892a8164dfSZhong Wang int i; 902a8164dfSZhong Wang int size = sizeof (FCOE_PORT_WWN); 912a8164dfSZhong Wang 922a8164dfSZhong Wang for (i = 0; i < size; i++) { 932a8164dfSZhong Wang if (portwwn.wwn[i] != 0) { 942a8164dfSZhong Wang return (0); 952a8164dfSZhong Wang } 962a8164dfSZhong Wang } 972a8164dfSZhong Wang return (1); 982a8164dfSZhong Wang } 992a8164dfSZhong Wang 100*e6eb57e7SKevin Yu /* 101*e6eb57e7SKevin Yu * Initialize scf fcoe service access 102*e6eb57e7SKevin Yu * handle - returned handle 103*e6eb57e7SKevin Yu * service - returned service handle 104*e6eb57e7SKevin Yu */ 105*e6eb57e7SKevin Yu static int 106*e6eb57e7SKevin Yu fcoe_cfg_scf_init(scf_handle_t **handle, scf_service_t **service, int is_target) 107*e6eb57e7SKevin Yu { 108*e6eb57e7SKevin Yu scf_scope_t *scope = NULL; 109*e6eb57e7SKevin Yu int ret; 110*e6eb57e7SKevin Yu 111*e6eb57e7SKevin Yu if ((*handle = scf_handle_create(SCF_VERSION)) == NULL) { 112*e6eb57e7SKevin Yu syslog(LOG_ERR, "scf_handle_create failed - %s", 113*e6eb57e7SKevin Yu scf_strerror(scf_error())); 114*e6eb57e7SKevin Yu ret = FCOE_ERROR; 115*e6eb57e7SKevin Yu goto err; 116*e6eb57e7SKevin Yu } 117*e6eb57e7SKevin Yu 118*e6eb57e7SKevin Yu if (scf_handle_bind(*handle) == -1) { 119*e6eb57e7SKevin Yu syslog(LOG_ERR, "scf_handle_bind failed - %s", 120*e6eb57e7SKevin Yu scf_strerror(scf_error())); 121*e6eb57e7SKevin Yu ret = FCOE_ERROR; 122*e6eb57e7SKevin Yu goto err; 123*e6eb57e7SKevin Yu } 124*e6eb57e7SKevin Yu 125*e6eb57e7SKevin Yu if ((*service = scf_service_create(*handle)) == NULL) { 126*e6eb57e7SKevin Yu syslog(LOG_ERR, "scf_service_create failed - %s", 127*e6eb57e7SKevin Yu scf_strerror(scf_error())); 128*e6eb57e7SKevin Yu ret = FCOE_ERROR; 129*e6eb57e7SKevin Yu goto err; 130*e6eb57e7SKevin Yu } 131*e6eb57e7SKevin Yu 132*e6eb57e7SKevin Yu if ((scope = scf_scope_create(*handle)) == NULL) { 133*e6eb57e7SKevin Yu syslog(LOG_ERR, "scf_scope_create failed - %s", 134*e6eb57e7SKevin Yu scf_strerror(scf_error())); 135*e6eb57e7SKevin Yu ret = FCOE_ERROR; 136*e6eb57e7SKevin Yu goto err; 137*e6eb57e7SKevin Yu } 138*e6eb57e7SKevin Yu 139*e6eb57e7SKevin Yu if (scf_handle_get_scope(*handle, SCF_SCOPE_LOCAL, scope) == -1) { 140*e6eb57e7SKevin Yu syslog(LOG_ERR, "scf_handle_get_scope failed - %s", 141*e6eb57e7SKevin Yu scf_strerror(scf_error())); 142*e6eb57e7SKevin Yu ret = FCOE_ERROR; 143*e6eb57e7SKevin Yu goto err; 144*e6eb57e7SKevin Yu } 145*e6eb57e7SKevin Yu 146*e6eb57e7SKevin Yu if (scf_scope_get_service(scope, 147*e6eb57e7SKevin Yu is_target ? FCOE_TARGET_SERVICE: FCOE_INITIATOR_SERVICE, 148*e6eb57e7SKevin Yu *service) == -1) { 149*e6eb57e7SKevin Yu syslog(LOG_ERR, "scf_scope_get_service failed - %s", 150*e6eb57e7SKevin Yu scf_strerror(scf_error())); 151*e6eb57e7SKevin Yu ret = FCOE_ERROR_SERVICE_NOT_FOUND; 152*e6eb57e7SKevin Yu goto err; 153*e6eb57e7SKevin Yu } 154*e6eb57e7SKevin Yu 155*e6eb57e7SKevin Yu scf_scope_destroy(scope); 156*e6eb57e7SKevin Yu 157*e6eb57e7SKevin Yu return (FCOE_SUCCESS); 158*e6eb57e7SKevin Yu 159*e6eb57e7SKevin Yu err: 160*e6eb57e7SKevin Yu if (*handle != NULL) { 161*e6eb57e7SKevin Yu scf_handle_destroy(*handle); 162*e6eb57e7SKevin Yu } 163*e6eb57e7SKevin Yu if (*service != NULL) { 164*e6eb57e7SKevin Yu scf_service_destroy(*service); 165*e6eb57e7SKevin Yu *service = NULL; 166*e6eb57e7SKevin Yu } 167*e6eb57e7SKevin Yu if (scope != NULL) { 168*e6eb57e7SKevin Yu scf_scope_destroy(scope); 169*e6eb57e7SKevin Yu } 170*e6eb57e7SKevin Yu return (ret); 171*e6eb57e7SKevin Yu } 172*e6eb57e7SKevin Yu 173*e6eb57e7SKevin Yu static int 174*e6eb57e7SKevin Yu fcoe_add_remove_scf_entry(char *mac_name, 175*e6eb57e7SKevin Yu char *pwwn, char *nwwn, 176*e6eb57e7SKevin Yu int is_target, int is_promiscuous, int addRemoveFlag) 177*e6eb57e7SKevin Yu { 178*e6eb57e7SKevin Yu scf_handle_t *handle = NULL; 179*e6eb57e7SKevin Yu scf_service_t *svc = NULL; 180*e6eb57e7SKevin Yu scf_propertygroup_t *pg = NULL; 181*e6eb57e7SKevin Yu scf_transaction_t *tran = NULL; 182*e6eb57e7SKevin Yu scf_transaction_entry_t *entry = NULL; 183*e6eb57e7SKevin Yu scf_property_t *prop = NULL; 184*e6eb57e7SKevin Yu scf_value_t *valueLookup = NULL; 185*e6eb57e7SKevin Yu scf_iter_t *valueIter = NULL; 186*e6eb57e7SKevin Yu scf_value_t **valueSet = NULL; 187*e6eb57e7SKevin Yu int ret = FCOE_SUCCESS; 188*e6eb57e7SKevin Yu boolean_t createProp = B_FALSE; 189*e6eb57e7SKevin Yu int lastAlloc = 0; 190*e6eb57e7SKevin Yu char buf[FCOE_PORT_LIST_LENGTH] = {0}; 191*e6eb57e7SKevin Yu char memberName[FCOE_PORT_LIST_LENGTH] = {0}; 192*e6eb57e7SKevin Yu boolean_t found = B_FALSE; 193*e6eb57e7SKevin Yu int i = 0; 194*e6eb57e7SKevin Yu int valueArraySize = 0; 195*e6eb57e7SKevin Yu int commitRet; 196*e6eb57e7SKevin Yu int portListAlloc = 100; 197*e6eb57e7SKevin Yu 198*e6eb57e7SKevin Yu (void) snprintf(memberName, FCOE_PORT_LIST_LENGTH, 199*e6eb57e7SKevin Yu "%s:%s:%s:%d:%d", mac_name, pwwn, nwwn, 200*e6eb57e7SKevin Yu is_target, is_promiscuous); 201*e6eb57e7SKevin Yu 202*e6eb57e7SKevin Yu ret = fcoe_cfg_scf_init(&handle, &svc, is_target); 203*e6eb57e7SKevin Yu if (ret != FCOE_SUCCESS) { 204*e6eb57e7SKevin Yu goto out; 205*e6eb57e7SKevin Yu } 206*e6eb57e7SKevin Yu 207*e6eb57e7SKevin Yu if (((pg = scf_pg_create(handle)) == NULL) || 208*e6eb57e7SKevin Yu ((tran = scf_transaction_create(handle)) == NULL) || 209*e6eb57e7SKevin Yu ((entry = scf_entry_create(handle)) == NULL) || 210*e6eb57e7SKevin Yu ((prop = scf_property_create(handle)) == NULL) || 211*e6eb57e7SKevin Yu ((valueIter = scf_iter_create(handle)) == NULL)) { 212*e6eb57e7SKevin Yu ret = FCOE_ERROR; 213*e6eb57e7SKevin Yu goto out; 214*e6eb57e7SKevin Yu } 215*e6eb57e7SKevin Yu 216*e6eb57e7SKevin Yu /* get property group or create it */ 217*e6eb57e7SKevin Yu if (scf_service_get_pg(svc, FCOE_PG_NAME, pg) == -1) { 218*e6eb57e7SKevin Yu if ((scf_error() == SCF_ERROR_NOT_FOUND)) { 219*e6eb57e7SKevin Yu if (scf_service_add_pg(svc, FCOE_PG_NAME, 220*e6eb57e7SKevin Yu SCF_GROUP_APPLICATION, 0, pg) == -1) { 221*e6eb57e7SKevin Yu syslog(LOG_ERR, "add pg failed - %s", 222*e6eb57e7SKevin Yu scf_strerror(scf_error())); 223*e6eb57e7SKevin Yu ret = FCOE_ERROR; 224*e6eb57e7SKevin Yu } else { 225*e6eb57e7SKevin Yu createProp = B_TRUE; 226*e6eb57e7SKevin Yu } 227*e6eb57e7SKevin Yu } else { 228*e6eb57e7SKevin Yu syslog(LOG_ERR, "get pg failed - %s", 229*e6eb57e7SKevin Yu scf_strerror(scf_error())); 230*e6eb57e7SKevin Yu ret = FCOE_ERROR; 231*e6eb57e7SKevin Yu } 232*e6eb57e7SKevin Yu if (ret != FCOE_SUCCESS) { 233*e6eb57e7SKevin Yu goto out; 234*e6eb57e7SKevin Yu } 235*e6eb57e7SKevin Yu } 236*e6eb57e7SKevin Yu 237*e6eb57e7SKevin Yu /* to make sure property exists */ 238*e6eb57e7SKevin Yu if (createProp == B_FALSE) { 239*e6eb57e7SKevin Yu if (scf_pg_get_property(pg, FCOE_PORT_LIST, prop) == -1) { 240*e6eb57e7SKevin Yu if ((scf_error() == SCF_ERROR_NOT_FOUND)) { 241*e6eb57e7SKevin Yu createProp = B_TRUE; 242*e6eb57e7SKevin Yu } else { 243*e6eb57e7SKevin Yu syslog(LOG_ERR, "get property failed - %s", 244*e6eb57e7SKevin Yu scf_strerror(scf_error())); 245*e6eb57e7SKevin Yu ret = FCOE_ERROR; 246*e6eb57e7SKevin Yu goto out; 247*e6eb57e7SKevin Yu } 248*e6eb57e7SKevin Yu } 249*e6eb57e7SKevin Yu } 250*e6eb57e7SKevin Yu 251*e6eb57e7SKevin Yu /* Begin the transaction */ 252*e6eb57e7SKevin Yu if (scf_transaction_start(tran, pg) == -1) { 253*e6eb57e7SKevin Yu syslog(LOG_ERR, "start transaction failed - %s", 254*e6eb57e7SKevin Yu scf_strerror(scf_error())); 255*e6eb57e7SKevin Yu ret = FCOE_ERROR; 256*e6eb57e7SKevin Yu goto out; 257*e6eb57e7SKevin Yu } 258*e6eb57e7SKevin Yu 259*e6eb57e7SKevin Yu valueSet = (scf_value_t **)calloc(1, sizeof (*valueSet) 260*e6eb57e7SKevin Yu * (lastAlloc = portListAlloc)); 261*e6eb57e7SKevin Yu if (valueSet == NULL) { 262*e6eb57e7SKevin Yu ret = FCOE_ERROR_NOMEM; 263*e6eb57e7SKevin Yu goto out; 264*e6eb57e7SKevin Yu } 265*e6eb57e7SKevin Yu 266*e6eb57e7SKevin Yu if (createProp) { 267*e6eb57e7SKevin Yu if (scf_transaction_property_new(tran, entry, FCOE_PORT_LIST, 268*e6eb57e7SKevin Yu SCF_TYPE_USTRING) == -1) { 269*e6eb57e7SKevin Yu if (scf_error() == SCF_ERROR_EXISTS) { 270*e6eb57e7SKevin Yu ret = FCOE_ERROR_EXISTS; 271*e6eb57e7SKevin Yu } else { 272*e6eb57e7SKevin Yu syslog(LOG_ERR, 273*e6eb57e7SKevin Yu "transaction property new failed - %s", 274*e6eb57e7SKevin Yu scf_strerror(scf_error())); 275*e6eb57e7SKevin Yu ret = FCOE_ERROR; 276*e6eb57e7SKevin Yu } 277*e6eb57e7SKevin Yu goto out; 278*e6eb57e7SKevin Yu } 279*e6eb57e7SKevin Yu } else { 280*e6eb57e7SKevin Yu if (scf_transaction_property_change(tran, entry, 281*e6eb57e7SKevin Yu FCOE_PORT_LIST, SCF_TYPE_USTRING) == -1) { 282*e6eb57e7SKevin Yu syslog(LOG_ERR, 283*e6eb57e7SKevin Yu "transaction property change failed - %s", 284*e6eb57e7SKevin Yu scf_strerror(scf_error())); 285*e6eb57e7SKevin Yu ret = FCOE_ERROR; 286*e6eb57e7SKevin Yu goto out; 287*e6eb57e7SKevin Yu } 288*e6eb57e7SKevin Yu 289*e6eb57e7SKevin Yu if (scf_pg_get_property(pg, FCOE_PORT_LIST, prop) == -1) { 290*e6eb57e7SKevin Yu syslog(LOG_ERR, "get property failed - %s", 291*e6eb57e7SKevin Yu scf_strerror(scf_error())); 292*e6eb57e7SKevin Yu ret = FCOE_ERROR; 293*e6eb57e7SKevin Yu goto out; 294*e6eb57e7SKevin Yu } 295*e6eb57e7SKevin Yu 296*e6eb57e7SKevin Yu valueLookup = scf_value_create(handle); 297*e6eb57e7SKevin Yu if (valueLookup == NULL) { 298*e6eb57e7SKevin Yu syslog(LOG_ERR, "scf value alloc failed - %s", 299*e6eb57e7SKevin Yu scf_strerror(scf_error())); 300*e6eb57e7SKevin Yu ret = FCOE_ERROR; 301*e6eb57e7SKevin Yu goto out; 302*e6eb57e7SKevin Yu } 303*e6eb57e7SKevin Yu 304*e6eb57e7SKevin Yu if (scf_iter_property_values(valueIter, prop) == -1) { 305*e6eb57e7SKevin Yu syslog(LOG_ERR, "iter value failed - %s", 306*e6eb57e7SKevin Yu scf_strerror(scf_error())); 307*e6eb57e7SKevin Yu ret = FCOE_ERROR; 308*e6eb57e7SKevin Yu goto out; 309*e6eb57e7SKevin Yu } 310*e6eb57e7SKevin Yu 311*e6eb57e7SKevin Yu while (scf_iter_next_value(valueIter, valueLookup) == 1) { 312*e6eb57e7SKevin Yu char *macnameIter = NULL; 313*e6eb57e7SKevin Yu char buftmp[FCOE_PORT_LIST_LENGTH] = {0}; 314*e6eb57e7SKevin Yu 315*e6eb57e7SKevin Yu bzero(buf, sizeof (buf)); 316*e6eb57e7SKevin Yu if (scf_value_get_ustring(valueLookup, 317*e6eb57e7SKevin Yu buf, MAXNAMELEN) == -1) { 318*e6eb57e7SKevin Yu syslog(LOG_ERR, "iter value failed- %s", 319*e6eb57e7SKevin Yu scf_strerror(scf_error())); 320*e6eb57e7SKevin Yu ret = FCOE_ERROR; 321*e6eb57e7SKevin Yu break; 322*e6eb57e7SKevin Yu } 323*e6eb57e7SKevin Yu (void) strcpy(buftmp, buf); 324*e6eb57e7SKevin Yu macnameIter = strtok(buftmp, ":"); 325*e6eb57e7SKevin Yu if (strcmp(macnameIter, mac_name) == 0) { 326*e6eb57e7SKevin Yu if (addRemoveFlag == FCOE_SCF_ADD) { 327*e6eb57e7SKevin Yu ret = FCOE_ERROR_EXISTS; 328*e6eb57e7SKevin Yu break; 329*e6eb57e7SKevin Yu } else { 330*e6eb57e7SKevin Yu found = B_TRUE; 331*e6eb57e7SKevin Yu continue; 332*e6eb57e7SKevin Yu } 333*e6eb57e7SKevin Yu } 334*e6eb57e7SKevin Yu 335*e6eb57e7SKevin Yu valueSet[i] = scf_value_create(handle); 336*e6eb57e7SKevin Yu if (valueSet[i] == NULL) { 337*e6eb57e7SKevin Yu syslog(LOG_ERR, "scf value alloc failed - %s", 338*e6eb57e7SKevin Yu scf_strerror(scf_error())); 339*e6eb57e7SKevin Yu ret = FCOE_ERROR; 340*e6eb57e7SKevin Yu break; 341*e6eb57e7SKevin Yu } 342*e6eb57e7SKevin Yu 343*e6eb57e7SKevin Yu if (scf_value_set_ustring(valueSet[i], buf) == -1) { 344*e6eb57e7SKevin Yu syslog(LOG_ERR, "set value failed 1- %s", 345*e6eb57e7SKevin Yu scf_strerror(scf_error())); 346*e6eb57e7SKevin Yu ret = FCOE_ERROR; 347*e6eb57e7SKevin Yu break; 348*e6eb57e7SKevin Yu } 349*e6eb57e7SKevin Yu 350*e6eb57e7SKevin Yu if (scf_entry_add_value(entry, valueSet[i]) == -1) { 351*e6eb57e7SKevin Yu syslog(LOG_ERR, "add value failed - %s", 352*e6eb57e7SKevin Yu scf_strerror(scf_error())); 353*e6eb57e7SKevin Yu ret = FCOE_ERROR; 354*e6eb57e7SKevin Yu break; 355*e6eb57e7SKevin Yu } 356*e6eb57e7SKevin Yu 357*e6eb57e7SKevin Yu i++; 358*e6eb57e7SKevin Yu 359*e6eb57e7SKevin Yu if (i >= lastAlloc) { 360*e6eb57e7SKevin Yu lastAlloc += portListAlloc; 361*e6eb57e7SKevin Yu valueSet = realloc(valueSet, 362*e6eb57e7SKevin Yu sizeof (*valueSet) * lastAlloc); 363*e6eb57e7SKevin Yu if (valueSet == NULL) { 364*e6eb57e7SKevin Yu ret = FCOE_ERROR; 365*e6eb57e7SKevin Yu break; 366*e6eb57e7SKevin Yu } 367*e6eb57e7SKevin Yu } 368*e6eb57e7SKevin Yu } 369*e6eb57e7SKevin Yu } 370*e6eb57e7SKevin Yu 371*e6eb57e7SKevin Yu valueArraySize = i; 372*e6eb57e7SKevin Yu if (!found && (addRemoveFlag == FCOE_SCF_REMOVE)) { 373*e6eb57e7SKevin Yu ret = FCOE_ERROR_MEMBER_NOT_FOUND; 374*e6eb57e7SKevin Yu } 375*e6eb57e7SKevin Yu if (ret != FCOE_SUCCESS) { 376*e6eb57e7SKevin Yu goto out; 377*e6eb57e7SKevin Yu } 378*e6eb57e7SKevin Yu 379*e6eb57e7SKevin Yu if (addRemoveFlag == FCOE_SCF_ADD) { 380*e6eb57e7SKevin Yu /* 381*e6eb57e7SKevin Yu * Now create the new entry 382*e6eb57e7SKevin Yu */ 383*e6eb57e7SKevin Yu valueSet[i] = scf_value_create(handle); 384*e6eb57e7SKevin Yu if (valueSet[i] == NULL) { 385*e6eb57e7SKevin Yu syslog(LOG_ERR, "scf value alloc failed - %s", 386*e6eb57e7SKevin Yu scf_strerror(scf_error())); 387*e6eb57e7SKevin Yu ret = FCOE_ERROR; 388*e6eb57e7SKevin Yu goto out; 389*e6eb57e7SKevin Yu } else { 390*e6eb57e7SKevin Yu valueArraySize++; 391*e6eb57e7SKevin Yu } 392*e6eb57e7SKevin Yu 393*e6eb57e7SKevin Yu /* 394*e6eb57e7SKevin Yu * Set the new member name 395*e6eb57e7SKevin Yu */ 396*e6eb57e7SKevin Yu if (scf_value_set_ustring(valueSet[i], memberName) == -1) { 397*e6eb57e7SKevin Yu syslog(LOG_ERR, "set value failed 2- %s", 398*e6eb57e7SKevin Yu scf_strerror(scf_error())); 399*e6eb57e7SKevin Yu ret = FCOE_ERROR; 400*e6eb57e7SKevin Yu goto out; 401*e6eb57e7SKevin Yu } 402*e6eb57e7SKevin Yu 403*e6eb57e7SKevin Yu /* 404*e6eb57e7SKevin Yu * Add the new member 405*e6eb57e7SKevin Yu */ 406*e6eb57e7SKevin Yu if (scf_entry_add_value(entry, valueSet[i]) == -1) { 407*e6eb57e7SKevin Yu syslog(LOG_ERR, "add value failed - %s", 408*e6eb57e7SKevin Yu scf_strerror(scf_error())); 409*e6eb57e7SKevin Yu ret = FCOE_ERROR; 410*e6eb57e7SKevin Yu goto out; 411*e6eb57e7SKevin Yu } 412*e6eb57e7SKevin Yu } 413*e6eb57e7SKevin Yu 414*e6eb57e7SKevin Yu if ((commitRet = scf_transaction_commit(tran)) != 1) { 415*e6eb57e7SKevin Yu syslog(LOG_ERR, "transaction commit failed - %s", 416*e6eb57e7SKevin Yu scf_strerror(scf_error())); 417*e6eb57e7SKevin Yu if (commitRet == 0) { 418*e6eb57e7SKevin Yu ret = FCOE_ERROR_BUSY; 419*e6eb57e7SKevin Yu } else { 420*e6eb57e7SKevin Yu ret = FCOE_ERROR; 421*e6eb57e7SKevin Yu } 422*e6eb57e7SKevin Yu goto out; 423*e6eb57e7SKevin Yu } 424*e6eb57e7SKevin Yu 425*e6eb57e7SKevin Yu out: 426*e6eb57e7SKevin Yu /* 427*e6eb57e7SKevin Yu * Free resources 428*e6eb57e7SKevin Yu */ 429*e6eb57e7SKevin Yu if (handle != NULL) { 430*e6eb57e7SKevin Yu scf_handle_destroy(handle); 431*e6eb57e7SKevin Yu } 432*e6eb57e7SKevin Yu if (svc != NULL) { 433*e6eb57e7SKevin Yu scf_service_destroy(svc); 434*e6eb57e7SKevin Yu } 435*e6eb57e7SKevin Yu if (pg != NULL) { 436*e6eb57e7SKevin Yu scf_pg_destroy(pg); 437*e6eb57e7SKevin Yu } 438*e6eb57e7SKevin Yu if (tran != NULL) { 439*e6eb57e7SKevin Yu scf_transaction_destroy(tran); 440*e6eb57e7SKevin Yu } 441*e6eb57e7SKevin Yu if (entry != NULL) { 442*e6eb57e7SKevin Yu scf_entry_destroy(entry); 443*e6eb57e7SKevin Yu } 444*e6eb57e7SKevin Yu if (prop != NULL) { 445*e6eb57e7SKevin Yu scf_property_destroy(prop); 446*e6eb57e7SKevin Yu } 447*e6eb57e7SKevin Yu if (valueIter != NULL) { 448*e6eb57e7SKevin Yu scf_iter_destroy(valueIter); 449*e6eb57e7SKevin Yu } 450*e6eb57e7SKevin Yu if (valueLookup != NULL) { 451*e6eb57e7SKevin Yu scf_value_destroy(valueLookup); 452*e6eb57e7SKevin Yu } 453*e6eb57e7SKevin Yu 454*e6eb57e7SKevin Yu /* 455*e6eb57e7SKevin Yu * Free valueSet scf resources 456*e6eb57e7SKevin Yu */ 457*e6eb57e7SKevin Yu if (valueArraySize > 0) { 458*e6eb57e7SKevin Yu for (i = 0; i < valueArraySize; i++) { 459*e6eb57e7SKevin Yu scf_value_destroy(valueSet[i]); 460*e6eb57e7SKevin Yu } 461*e6eb57e7SKevin Yu } 462*e6eb57e7SKevin Yu /* 463*e6eb57e7SKevin Yu * Now free the pointer array to the resources 464*e6eb57e7SKevin Yu */ 465*e6eb57e7SKevin Yu if (valueSet != NULL) { 466*e6eb57e7SKevin Yu free(valueSet); 467*e6eb57e7SKevin Yu } 468*e6eb57e7SKevin Yu 469*e6eb57e7SKevin Yu return (ret); 470*e6eb57e7SKevin Yu } 471*e6eb57e7SKevin Yu 4722a8164dfSZhong Wang FCOE_STATUS 4732a8164dfSZhong Wang FCOE_CreatePort( 4742a8164dfSZhong Wang const FCOE_UINT8 *macLinkName, 4752a8164dfSZhong Wang FCOE_UINT8 portType, 4762a8164dfSZhong Wang FCOE_PORT_WWN pwwn, 4772a8164dfSZhong Wang FCOE_PORT_WWN nwwn, 4782a8164dfSZhong Wang FCOE_UINT8 promiscuous) 4792a8164dfSZhong Wang { 480*e6eb57e7SKevin Yu FCOE_STATUS status; 4812a8164dfSZhong Wang int fcoe_fd; 4822a8164dfSZhong Wang fcoeio_t fcoeio; 4832a8164dfSZhong Wang fcoeio_create_port_param_t param; 484d4401b99SKelly Hu dladm_handle_t handle; 485d4401b99SKelly Hu datalink_id_t linkid; 486d4401b99SKelly Hu datalink_class_t class; 4872a8164dfSZhong Wang 4882a8164dfSZhong Wang bzero(¶m, sizeof (fcoeio_create_port_param_t)); 4892a8164dfSZhong Wang 4902a8164dfSZhong Wang if (macLinkName == NULL) { 4912a8164dfSZhong Wang return (FCOE_STATUS_ERROR_INVAL_ARG); 4922a8164dfSZhong Wang } 4932a8164dfSZhong Wang 494d4401b99SKelly Hu if (strlen((char *)macLinkName) > MAXLINKNAMELEN-1) { 495d4401b99SKelly Hu return (FCOE_STATUS_ERROR_MAC_LEN); 496d4401b99SKelly Hu } 497d4401b99SKelly Hu 498d4401b99SKelly Hu if (dladm_open(&handle) != DLADM_STATUS_OK) { 499d4401b99SKelly Hu return (FCOE_STATUS_ERROR); 500d4401b99SKelly Hu } 501d4401b99SKelly Hu 502d4401b99SKelly Hu if (dladm_name2info(handle, (const char *)macLinkName, 503d4401b99SKelly Hu &linkid, NULL, &class, NULL) != DLADM_STATUS_OK) { 504d4401b99SKelly Hu dladm_close(handle); 505*e6eb57e7SKevin Yu (void) fcoe_add_remove_scf_entry((char *)macLinkName, 506*e6eb57e7SKevin Yu "", 507*e6eb57e7SKevin Yu "", 508*e6eb57e7SKevin Yu portType, 509*e6eb57e7SKevin Yu 0, 510*e6eb57e7SKevin Yu FCOE_SCF_REMOVE); 511d4401b99SKelly Hu return (FCOE_STATUS_ERROR_GET_LINKINFO); 512d4401b99SKelly Hu } 513d4401b99SKelly Hu dladm_close(handle); 514d4401b99SKelly Hu 515d4401b99SKelly Hu if (class != DATALINK_CLASS_PHYS) { 516d4401b99SKelly Hu return (FCOE_STATUS_ERROR_CLASS_UNSUPPORT); 517d4401b99SKelly Hu } 518d4401b99SKelly Hu 5192a8164dfSZhong Wang if (portType != FCOE_PORTTYPE_INITIATOR && 5202a8164dfSZhong Wang portType != FCOE_PORTTYPE_TARGET) { 5212a8164dfSZhong Wang return (FCOE_STATUS_ERROR_INVAL_ARG); 5222a8164dfSZhong Wang } 5232a8164dfSZhong Wang 5242a8164dfSZhong Wang if (!isWWNZero(pwwn)) { 5252a8164dfSZhong Wang param.fcp_pwwn_provided = 1; 5262a8164dfSZhong Wang bcopy(pwwn.wwn, param.fcp_pwwn, 8); 5272a8164dfSZhong Wang } 5282a8164dfSZhong Wang 5292a8164dfSZhong Wang if (!isWWNZero(nwwn)) { 5302a8164dfSZhong Wang param.fcp_nwwn_provided = 1; 5312a8164dfSZhong Wang bcopy(nwwn.wwn, param.fcp_nwwn, 8); 5322a8164dfSZhong Wang } 5332a8164dfSZhong Wang 5342a8164dfSZhong Wang if (param.fcp_pwwn_provided == 1 && 5352a8164dfSZhong Wang param.fcp_nwwn_provided == 1 && 5362a8164dfSZhong Wang bcmp(&pwwn, &nwwn, 8) == 0) { 5372a8164dfSZhong Wang return (FCOE_STATUS_ERROR_WWN_SAME); 5382a8164dfSZhong Wang } 5392a8164dfSZhong Wang 5402a8164dfSZhong Wang param.fcp_force_promisc = promiscuous; 541d4401b99SKelly Hu param.fcp_mac_linkid = linkid; 5422a8164dfSZhong Wang param.fcp_port_type = (fcoe_cli_type_t)portType; 5432a8164dfSZhong Wang 5442a8164dfSZhong Wang if ((status = openFcoe(OPEN_FCOE, &fcoe_fd)) != FCOE_STATUS_OK) { 5452a8164dfSZhong Wang return (status); 5462a8164dfSZhong Wang } 5472a8164dfSZhong Wang 5482a8164dfSZhong Wang (void) memset(&fcoeio, 0, sizeof (fcoeio)); 5492a8164dfSZhong Wang fcoeio.fcoeio_cmd = FCOEIO_CREATE_FCOE_PORT; 5502a8164dfSZhong Wang 5512a8164dfSZhong Wang fcoeio.fcoeio_ilen = sizeof (param); 5522a8164dfSZhong Wang fcoeio.fcoeio_xfer = FCOEIO_XFER_WRITE; 5532a8164dfSZhong Wang fcoeio.fcoeio_ibuf = (uintptr_t)¶m; 5542a8164dfSZhong Wang 5552a8164dfSZhong Wang if (ioctl(fcoe_fd, FCOEIO_CMD, &fcoeio) != 0) { 5562a8164dfSZhong Wang switch (fcoeio.fcoeio_status) { 5572a8164dfSZhong Wang case FCOEIOE_INVAL_ARG: 5582a8164dfSZhong Wang status = FCOE_STATUS_ERROR_INVAL_ARG; 5592a8164dfSZhong Wang break; 5602a8164dfSZhong Wang 5612a8164dfSZhong Wang case FCOEIOE_BUSY: 5622a8164dfSZhong Wang status = FCOE_STATUS_ERROR_BUSY; 5632a8164dfSZhong Wang break; 5642a8164dfSZhong Wang 5652a8164dfSZhong Wang case FCOEIOE_ALREADY: 5662a8164dfSZhong Wang status = FCOE_STATUS_ERROR_ALREADY; 5672a8164dfSZhong Wang break; 5682a8164dfSZhong Wang 5692a8164dfSZhong Wang case FCOEIOE_PWWN_CONFLICTED: 5702a8164dfSZhong Wang status = FCOE_STATUS_ERROR_PWWN_CONFLICTED; 5712a8164dfSZhong Wang break; 5722a8164dfSZhong Wang 5732a8164dfSZhong Wang case FCOEIOE_NWWN_CONFLICTED: 5742a8164dfSZhong Wang status = FCOE_STATUS_ERROR_NWWN_CONFLICTED; 5752a8164dfSZhong Wang break; 5762a8164dfSZhong Wang 5772a8164dfSZhong Wang case FCOEIOE_CREATE_MAC: 5782a8164dfSZhong Wang status = FCOE_STATUS_ERROR_CREATE_MAC; 5792a8164dfSZhong Wang break; 5802a8164dfSZhong Wang 5812a8164dfSZhong Wang case FCOEIOE_OPEN_MAC: 5822a8164dfSZhong Wang status = FCOE_STATUS_ERROR_OPEN_MAC; 5832a8164dfSZhong Wang break; 5842a8164dfSZhong Wang 5852a8164dfSZhong Wang case FCOEIOE_CREATE_PORT: 5862a8164dfSZhong Wang status = FCOE_STATUS_ERROR_CREATE_PORT; 5872a8164dfSZhong Wang break; 5882a8164dfSZhong Wang 5892a8164dfSZhong Wang case FCOEIOE_NEED_JUMBO_FRAME: 5902a8164dfSZhong Wang status = FCOE_STATUS_ERROR_NEED_JUMBO_FRAME; 5912a8164dfSZhong Wang break; 5922a8164dfSZhong Wang 5932a8164dfSZhong Wang default: 5942a8164dfSZhong Wang status = FCOE_STATUS_ERROR; 5952a8164dfSZhong Wang } 5962a8164dfSZhong Wang } else { 597*e6eb57e7SKevin Yu char cpwwn[17], cnwwn[17]; 598*e6eb57e7SKevin Yu 599*e6eb57e7SKevin Yu WWN2str(cpwwn, &pwwn); 600*e6eb57e7SKevin Yu WWN2str(cnwwn, &nwwn); 601*e6eb57e7SKevin Yu 602*e6eb57e7SKevin Yu (void) fcoe_add_remove_scf_entry((char *)macLinkName, 603*e6eb57e7SKevin Yu cpwwn, 604*e6eb57e7SKevin Yu cnwwn, 605*e6eb57e7SKevin Yu portType, 606*e6eb57e7SKevin Yu promiscuous, 607*e6eb57e7SKevin Yu FCOE_SCF_ADD); 6082a8164dfSZhong Wang status = FCOE_STATUS_OK; 6092a8164dfSZhong Wang } 6102a8164dfSZhong Wang (void) close(fcoe_fd); 6112a8164dfSZhong Wang return (status); 6122a8164dfSZhong Wang } 6132a8164dfSZhong Wang 6142a8164dfSZhong Wang FCOE_STATUS 6152a8164dfSZhong Wang FCOE_DeletePort(const FCOE_UINT8 *macLinkName) 6162a8164dfSZhong Wang { 6172a8164dfSZhong Wang FCOE_STATUS status = FCOE_STATUS_OK; 6182a8164dfSZhong Wang int fcoe_fd; 6192a8164dfSZhong Wang fcoeio_t fcoeio; 620d4401b99SKelly Hu dladm_handle_t handle; 621d4401b99SKelly Hu datalink_id_t linkid; 622d4401b99SKelly Hu fcoeio_delete_port_param_t fc_del_port; 623*e6eb57e7SKevin Yu uint64_t is_target = 0; 624*e6eb57e7SKevin Yu int io_ret = 0; 6252a8164dfSZhong Wang 6262a8164dfSZhong Wang if (macLinkName == NULL) { 6272a8164dfSZhong Wang return (FCOE_STATUS_ERROR_INVAL_ARG); 6282a8164dfSZhong Wang } 6292a8164dfSZhong Wang 630d4401b99SKelly Hu if (strlen((char *)macLinkName) > MAXLINKNAMELEN-1) { 6312a8164dfSZhong Wang return (FCOE_STATUS_ERROR_MAC_LEN); 6322a8164dfSZhong Wang } 633d4401b99SKelly Hu if (dladm_open(&handle) != DLADM_STATUS_OK) { 634d4401b99SKelly Hu return (FCOE_STATUS_ERROR); 635d4401b99SKelly Hu } 636d4401b99SKelly Hu 637d4401b99SKelly Hu if (dladm_name2info(handle, (const char *)macLinkName, 638d4401b99SKelly Hu &linkid, NULL, NULL, NULL) != DLADM_STATUS_OK) { 639d4401b99SKelly Hu dladm_close(handle); 640d4401b99SKelly Hu return (FCOE_STATUS_ERROR_GET_LINKINFO); 641d4401b99SKelly Hu } 642d4401b99SKelly Hu dladm_close(handle); 6432a8164dfSZhong Wang 6442a8164dfSZhong Wang if ((status = openFcoe(OPEN_FCOE, &fcoe_fd)) != FCOE_STATUS_OK) { 6452a8164dfSZhong Wang return (status); 6462a8164dfSZhong Wang } 6472a8164dfSZhong Wang 648d4401b99SKelly Hu fc_del_port.fdp_mac_linkid = linkid; 649d4401b99SKelly Hu 6502a8164dfSZhong Wang (void) memset(&fcoeio, 0, sizeof (fcoeio)); 6512a8164dfSZhong Wang fcoeio.fcoeio_cmd = FCOEIO_DELETE_FCOE_PORT; 6522a8164dfSZhong Wang 653d4401b99SKelly Hu /* only 4 bytes here, need to change */ 654d4401b99SKelly Hu fcoeio.fcoeio_ilen = sizeof (fcoeio_delete_port_param_t); 655*e6eb57e7SKevin Yu fcoeio.fcoeio_olen = sizeof (uint64_t); 656*e6eb57e7SKevin Yu fcoeio.fcoeio_xfer = FCOEIO_XFER_RW; 657d4401b99SKelly Hu fcoeio.fcoeio_ibuf = (uintptr_t)&fc_del_port; 658*e6eb57e7SKevin Yu fcoeio.fcoeio_obuf = (uintptr_t)&is_target; 6592a8164dfSZhong Wang 660*e6eb57e7SKevin Yu io_ret = ioctl(fcoe_fd, FCOEIO_CMD, &fcoeio); 661*e6eb57e7SKevin Yu if (io_ret != 0) { 6622a8164dfSZhong Wang switch (fcoeio.fcoeio_status) { 6632a8164dfSZhong Wang case FCOEIOE_INVAL_ARG: 6642a8164dfSZhong Wang status = FCOE_STATUS_ERROR_INVAL_ARG; 6652a8164dfSZhong Wang break; 6662a8164dfSZhong Wang 6672a8164dfSZhong Wang case FCOEIOE_BUSY: 6682a8164dfSZhong Wang status = FCOE_STATUS_ERROR_BUSY; 6692a8164dfSZhong Wang break; 6702a8164dfSZhong Wang 6712a8164dfSZhong Wang case FCOEIOE_ALREADY: 6722a8164dfSZhong Wang status = FCOE_STATUS_ERROR_ALREADY; 6732a8164dfSZhong Wang break; 6742a8164dfSZhong Wang 6752a8164dfSZhong Wang case FCOEIOE_MAC_NOT_FOUND: 6762a8164dfSZhong Wang status = FCOE_STATUS_ERROR_MAC_NOT_FOUND; 6772a8164dfSZhong Wang break; 6782a8164dfSZhong Wang 6792a8164dfSZhong Wang case FCOEIOE_OFFLINE_FAILURE: 6802a8164dfSZhong Wang status = FCOE_STATUS_ERROR_OFFLINE_DEV; 6812a8164dfSZhong Wang break; 6822a8164dfSZhong Wang 6832a8164dfSZhong Wang default: 6842a8164dfSZhong Wang status = FCOE_STATUS_ERROR; 6852a8164dfSZhong Wang } 6862a8164dfSZhong Wang } else { 687*e6eb57e7SKevin Yu (void) fcoe_add_remove_scf_entry((char *)macLinkName, 688*e6eb57e7SKevin Yu "", 689*e6eb57e7SKevin Yu "", 690*e6eb57e7SKevin Yu is_target, 691*e6eb57e7SKevin Yu 0, 692*e6eb57e7SKevin Yu FCOE_SCF_REMOVE); 6932a8164dfSZhong Wang status = FCOE_STATUS_OK; 6942a8164dfSZhong Wang } 695*e6eb57e7SKevin Yu 696*e6eb57e7SKevin Yu if (io_ret == FCOEIOE_MAC_NOT_FOUND) { 697*e6eb57e7SKevin Yu (void) fcoe_add_remove_scf_entry((char *)macLinkName, 698*e6eb57e7SKevin Yu "", 699*e6eb57e7SKevin Yu "", 700*e6eb57e7SKevin Yu 0, 701*e6eb57e7SKevin Yu 0, 702*e6eb57e7SKevin Yu FCOE_SCF_REMOVE); 703*e6eb57e7SKevin Yu (void) fcoe_add_remove_scf_entry((char *)macLinkName, 704*e6eb57e7SKevin Yu "", 705*e6eb57e7SKevin Yu "", 706*e6eb57e7SKevin Yu 1, 707*e6eb57e7SKevin Yu 0, 708*e6eb57e7SKevin Yu FCOE_SCF_REMOVE); 709*e6eb57e7SKevin Yu } 7102a8164dfSZhong Wang (void) close(fcoe_fd); 7112a8164dfSZhong Wang return (status); 7122a8164dfSZhong Wang } 7132a8164dfSZhong Wang 7142a8164dfSZhong Wang FCOE_STATUS 7152a8164dfSZhong Wang FCOE_GetPortList( 7162a8164dfSZhong Wang FCOE_UINT32 *port_num, 7172a8164dfSZhong Wang FCOE_PORT_ATTRIBUTE **portlist) 7182a8164dfSZhong Wang { 7192a8164dfSZhong Wang FCOE_STATUS status = FCOE_STATUS_OK; 7202a8164dfSZhong Wang int fcoe_fd; 7212a8164dfSZhong Wang fcoeio_t fcoeio; 7222a8164dfSZhong Wang fcoe_port_list_t *inportlist = NULL; 7232a8164dfSZhong Wang FCOE_PORT_ATTRIBUTE *outportlist = NULL; 7242a8164dfSZhong Wang int i; 7252a8164dfSZhong Wang int size = 64; /* default first attempt */ 7262a8164dfSZhong Wang int retry = 0; 7272a8164dfSZhong Wang int bufsize; 728d4401b99SKelly Hu dladm_handle_t handle; 729d4401b99SKelly Hu char mac_name[MAXLINKNAMELEN]; 7302a8164dfSZhong Wang 7312a8164dfSZhong Wang if (port_num == NULL || portlist == NULL) { 7322a8164dfSZhong Wang return (FCOE_STATUS_ERROR_INVAL_ARG); 7332a8164dfSZhong Wang } 7342a8164dfSZhong Wang *port_num = 0; 7352a8164dfSZhong Wang 7362a8164dfSZhong Wang if ((status = openFcoe(OPEN_FCOE, &fcoe_fd)) != FCOE_STATUS_OK) { 7372a8164dfSZhong Wang return (status); 7382a8164dfSZhong Wang } 7392a8164dfSZhong Wang 7402a8164dfSZhong Wang /* Get fcoe port list */ 7412a8164dfSZhong Wang (void) memset(&fcoeio, 0, sizeof (fcoeio)); 7422a8164dfSZhong Wang retry = 0; 7432a8164dfSZhong Wang 7442a8164dfSZhong Wang do { 7452a8164dfSZhong Wang bufsize = sizeof (fcoe_port_instance_t) * (size - 1) + 7462a8164dfSZhong Wang sizeof (fcoe_port_list_t); 7472a8164dfSZhong Wang inportlist = (fcoe_port_list_t *)malloc(bufsize); 7482a8164dfSZhong Wang fcoeio.fcoeio_cmd = FCOEIO_GET_FCOE_PORT_LIST; 7492a8164dfSZhong Wang fcoeio.fcoeio_olen = bufsize; 7502a8164dfSZhong Wang fcoeio.fcoeio_xfer = FCOEIO_XFER_READ; 7512a8164dfSZhong Wang fcoeio.fcoeio_obuf = (uintptr_t)inportlist; 7522a8164dfSZhong Wang 7532a8164dfSZhong Wang if (ioctl(fcoe_fd, FCOEIO_CMD, &fcoeio) != 0) { 7542a8164dfSZhong Wang if (fcoeio.fcoeio_status == FCOEIOE_MORE_DATA) { 7552a8164dfSZhong Wang size = inportlist->numPorts; 7562a8164dfSZhong Wang } 7572a8164dfSZhong Wang free(inportlist); 7582a8164dfSZhong Wang switch (fcoeio.fcoeio_status) { 7592a8164dfSZhong Wang case FCOEIOE_INVAL_ARG: 7602a8164dfSZhong Wang status = FCOE_STATUS_ERROR_INVAL_ARG; 7612a8164dfSZhong Wang (void) close(fcoe_fd); 7622a8164dfSZhong Wang return (status); 7632a8164dfSZhong Wang 7642a8164dfSZhong Wang case FCOEIOE_BUSY: 7652a8164dfSZhong Wang status = FCOE_STATUS_ERROR_BUSY; 7662a8164dfSZhong Wang retry++; 7672a8164dfSZhong Wang break; 7682a8164dfSZhong Wang 7692a8164dfSZhong Wang case FCOEIOE_MORE_DATA: 7702a8164dfSZhong Wang status = FCOE_STATUS_ERROR_MORE_DATA; 7712a8164dfSZhong Wang retry++; 7722a8164dfSZhong Wang default: 7732a8164dfSZhong Wang status = FCOE_STATUS_ERROR; 774*e6eb57e7SKevin Yu (void) close(fcoe_fd); 775*e6eb57e7SKevin Yu return (status); 7762a8164dfSZhong Wang } 7772a8164dfSZhong Wang } else { 7782a8164dfSZhong Wang status = FCOE_STATUS_OK; 7792a8164dfSZhong Wang break; 7802a8164dfSZhong Wang } 7812a8164dfSZhong Wang } while (retry <= 3 && status != FCOE_STATUS_OK); 7822a8164dfSZhong Wang 783d4401b99SKelly Hu if (status == FCOE_STATUS_OK && inportlist->numPorts > 0) { 784d4401b99SKelly Hu if (dladm_open(&handle) != DLADM_STATUS_OK) { 785d4401b99SKelly Hu handle = NULL; 786d4401b99SKelly Hu } 787d4401b99SKelly Hu 7882a8164dfSZhong Wang outportlist = (PFCOE_PORT_ATTRIBUTE) 7892a8164dfSZhong Wang malloc(sizeof (FCOE_PORT_ATTRIBUTE) * inportlist->numPorts); 7902a8164dfSZhong Wang 7912a8164dfSZhong Wang for (i = 0; i < inportlist->numPorts; i++) { 7922a8164dfSZhong Wang fcoe_port_instance_t *pi = &inportlist->ports[i]; 7932a8164dfSZhong Wang FCOE_PORT_ATTRIBUTE *po = &outportlist[i]; 7942a8164dfSZhong Wang bcopy(pi->fpi_pwwn, &po->port_wwn, 8); 795d4401b99SKelly Hu 796d4401b99SKelly Hu if (handle == NULL || 797d4401b99SKelly Hu dladm_datalink_id2info(handle, pi->fpi_mac_linkid, 798d4401b99SKelly Hu NULL, NULL, NULL, mac_name, sizeof (mac_name)) 799d4401b99SKelly Hu != DLADM_STATUS_OK) { 800d4401b99SKelly Hu (void) strcpy((char *)po->mac_link_name, 801d4401b99SKelly Hu "<unknown>"); 802d4401b99SKelly Hu } else { 803d4401b99SKelly Hu (void) strcpy((char *)po->mac_link_name, 804d4401b99SKelly Hu mac_name); 805d4401b99SKelly Hu } 8062a8164dfSZhong Wang bcopy(pi->fpi_mac_factory_addr, 8072a8164dfSZhong Wang po->mac_factory_addr, 6); 8082a8164dfSZhong Wang bcopy(pi->fpi_mac_current_addr, 8092a8164dfSZhong Wang po->mac_current_addr, 6); 8102a8164dfSZhong Wang po->port_type = (FCOE_UINT8)pi->fpi_port_type; 8112a8164dfSZhong Wang po->mtu_size = pi->fpi_mtu_size; 8122a8164dfSZhong Wang po->mac_promisc = pi->fpi_mac_promisc; 8132a8164dfSZhong Wang } 814d4401b99SKelly Hu 815d4401b99SKelly Hu if (handle != NULL) { 816d4401b99SKelly Hu dladm_close(handle); 817d4401b99SKelly Hu } 8182a8164dfSZhong Wang *port_num = inportlist->numPorts; 8192a8164dfSZhong Wang *portlist = outportlist; 8202a8164dfSZhong Wang free(inportlist); 8212a8164dfSZhong Wang } else { 8222a8164dfSZhong Wang *port_num = 0; 8232a8164dfSZhong Wang *portlist = NULL; 8242a8164dfSZhong Wang } 8252a8164dfSZhong Wang (void) close(fcoe_fd); 8262a8164dfSZhong Wang return (status); 8272a8164dfSZhong Wang } 828*e6eb57e7SKevin Yu 829*e6eb57e7SKevin Yu FCOE_STATUS FCOE_LoadConfig( 830*e6eb57e7SKevin Yu FCOE_UINT8 portType, 831*e6eb57e7SKevin Yu FCOE_SMF_PORT_LIST **portlist) 832*e6eb57e7SKevin Yu { 833*e6eb57e7SKevin Yu scf_handle_t *handle = NULL; 834*e6eb57e7SKevin Yu scf_service_t *svc = NULL; 835*e6eb57e7SKevin Yu scf_propertygroup_t *pg = NULL; 836*e6eb57e7SKevin Yu scf_transaction_t *tran = NULL; 837*e6eb57e7SKevin Yu scf_transaction_entry_t *entry = NULL; 838*e6eb57e7SKevin Yu scf_property_t *prop = NULL; 839*e6eb57e7SKevin Yu scf_value_t *valueLookup = NULL; 840*e6eb57e7SKevin Yu scf_iter_t *valueIter = NULL; 841*e6eb57e7SKevin Yu char buf[FCOE_PORT_LIST_LENGTH] = {0}; 842*e6eb57e7SKevin Yu int commitRet; 843*e6eb57e7SKevin Yu FCOE_UINT32 portIndex; 844*e6eb57e7SKevin Yu int bufsize, retry; 845*e6eb57e7SKevin Yu int size = 10; /* default first attempt */ 846*e6eb57e7SKevin Yu int pg_or_prop_not_found = 0; 847*e6eb57e7SKevin Yu 848*e6eb57e7SKevin Yu commitRet = fcoe_cfg_scf_init(&handle, &svc, portType); 849*e6eb57e7SKevin Yu if (commitRet != FCOE_SUCCESS) { 850*e6eb57e7SKevin Yu goto out; 851*e6eb57e7SKevin Yu } 852*e6eb57e7SKevin Yu 853*e6eb57e7SKevin Yu if (((pg = scf_pg_create(handle)) == NULL) || 854*e6eb57e7SKevin Yu ((tran = scf_transaction_create(handle)) == NULL) || 855*e6eb57e7SKevin Yu ((entry = scf_entry_create(handle)) == NULL) || 856*e6eb57e7SKevin Yu ((prop = scf_property_create(handle)) == NULL) || 857*e6eb57e7SKevin Yu ((valueIter = scf_iter_create(handle)) == NULL)) { 858*e6eb57e7SKevin Yu goto out; 859*e6eb57e7SKevin Yu } 860*e6eb57e7SKevin Yu 861*e6eb57e7SKevin Yu if (scf_service_get_pg(svc, FCOE_PG_NAME, pg) == -1) { 862*e6eb57e7SKevin Yu pg_or_prop_not_found = 1; 863*e6eb57e7SKevin Yu goto out; 864*e6eb57e7SKevin Yu } 865*e6eb57e7SKevin Yu 866*e6eb57e7SKevin Yu if (scf_pg_get_property(pg, FCOE_PORT_LIST, prop) == -1) { 867*e6eb57e7SKevin Yu pg_or_prop_not_found = 1; 868*e6eb57e7SKevin Yu goto out; 869*e6eb57e7SKevin Yu } 870*e6eb57e7SKevin Yu 871*e6eb57e7SKevin Yu valueLookup = scf_value_create(handle); 872*e6eb57e7SKevin Yu if (valueLookup == NULL) { 873*e6eb57e7SKevin Yu syslog(LOG_ERR, "scf value alloc failed - %s", 874*e6eb57e7SKevin Yu scf_strerror(scf_error())); 875*e6eb57e7SKevin Yu goto out; 876*e6eb57e7SKevin Yu } 877*e6eb57e7SKevin Yu 878*e6eb57e7SKevin Yu portIndex = 0; 879*e6eb57e7SKevin Yu 880*e6eb57e7SKevin Yu do { 881*e6eb57e7SKevin Yu if (scf_iter_property_values(valueIter, prop) == -1) { 882*e6eb57e7SKevin Yu syslog(LOG_ERR, "iter value failed - %s", 883*e6eb57e7SKevin Yu scf_strerror(scf_error())); 884*e6eb57e7SKevin Yu goto out; 885*e6eb57e7SKevin Yu } 886*e6eb57e7SKevin Yu 887*e6eb57e7SKevin Yu retry = 0; 888*e6eb57e7SKevin Yu bufsize = sizeof (FCOE_SMF_PORT_INSTANCE) * (size - 1) + 889*e6eb57e7SKevin Yu sizeof (FCOE_SMF_PORT_LIST); 890*e6eb57e7SKevin Yu *portlist = (PFCOE_SMF_PORT_LIST)malloc(bufsize); 891*e6eb57e7SKevin Yu 892*e6eb57e7SKevin Yu while (scf_iter_next_value(valueIter, valueLookup) == 1) { 893*e6eb57e7SKevin Yu uint8_t *macLinkName = NULL; 894*e6eb57e7SKevin Yu char *remainder = NULL; 895*e6eb57e7SKevin Yu uint64_t nodeWWN, portWWN; 896*e6eb57e7SKevin Yu int is_target, is_promiscuous; 897*e6eb57e7SKevin Yu 898*e6eb57e7SKevin Yu bzero(buf, sizeof (buf)); 899*e6eb57e7SKevin Yu if (scf_value_get_ustring(valueLookup, buf, 900*e6eb57e7SKevin Yu MAXNAMELEN) == -1) { 901*e6eb57e7SKevin Yu syslog(LOG_ERR, "iter value failed - %s", 902*e6eb57e7SKevin Yu scf_strerror(scf_error())); 903*e6eb57e7SKevin Yu break; 904*e6eb57e7SKevin Yu } 905*e6eb57e7SKevin Yu macLinkName = (uint8_t *)strtok(buf, ":"); 906*e6eb57e7SKevin Yu remainder = strtok(NULL, "#"); 907*e6eb57e7SKevin Yu (void) sscanf(remainder, 908*e6eb57e7SKevin Yu "%016" PRIx64 ":%016" PRIx64 ":%d:%d", 909*e6eb57e7SKevin Yu &portWWN, &nodeWWN, &is_target, &is_promiscuous); 910*e6eb57e7SKevin Yu 911*e6eb57e7SKevin Yu if (portIndex >= size) { 912*e6eb57e7SKevin Yu free(*portlist); 913*e6eb57e7SKevin Yu retry = 1; 914*e6eb57e7SKevin Yu size *= 2; 915*e6eb57e7SKevin Yu break; 916*e6eb57e7SKevin Yu } else { 917*e6eb57e7SKevin Yu PFCOE_SMF_PORT_INSTANCE pi = 918*e6eb57e7SKevin Yu &(*portlist)->ports[portIndex++]; 919*e6eb57e7SKevin Yu (void) strcpy((char *)pi->mac_link_name, 920*e6eb57e7SKevin Yu (char *)macLinkName); 921*e6eb57e7SKevin Yu pi->port_type = is_target ? 922*e6eb57e7SKevin Yu FCOE_PORTTYPE_TARGET: 923*e6eb57e7SKevin Yu FCOE_PORTTYPE_INITIATOR; 924*e6eb57e7SKevin Yu portWWN = htonll(portWWN); 925*e6eb57e7SKevin Yu nodeWWN = htonll(nodeWWN); 926*e6eb57e7SKevin Yu (void) memcpy(&pi->port_pwwn, &portWWN, 927*e6eb57e7SKevin Yu sizeof (FCOE_PORT_WWN)); 928*e6eb57e7SKevin Yu (void) memcpy(&pi->port_nwwn, &nodeWWN, 929*e6eb57e7SKevin Yu sizeof (FCOE_PORT_WWN)); 930*e6eb57e7SKevin Yu pi->mac_promisc = is_promiscuous; 931*e6eb57e7SKevin Yu } 932*e6eb57e7SKevin Yu } 933*e6eb57e7SKevin Yu 934*e6eb57e7SKevin Yu (*portlist)->port_num = portIndex; 935*e6eb57e7SKevin Yu } while (retry == 1); 936*e6eb57e7SKevin Yu 937*e6eb57e7SKevin Yu return (FCOE_STATUS_OK); 938*e6eb57e7SKevin Yu out: 939*e6eb57e7SKevin Yu /* 940*e6eb57e7SKevin Yu * Free resources 941*e6eb57e7SKevin Yu */ 942*e6eb57e7SKevin Yu if (handle != NULL) { 943*e6eb57e7SKevin Yu scf_handle_destroy(handle); 944*e6eb57e7SKevin Yu } 945*e6eb57e7SKevin Yu if (svc != NULL) { 946*e6eb57e7SKevin Yu scf_service_destroy(svc); 947*e6eb57e7SKevin Yu } 948*e6eb57e7SKevin Yu if (pg != NULL) { 949*e6eb57e7SKevin Yu scf_pg_destroy(pg); 950*e6eb57e7SKevin Yu } 951*e6eb57e7SKevin Yu if (tran != NULL) { 952*e6eb57e7SKevin Yu scf_transaction_destroy(tran); 953*e6eb57e7SKevin Yu } 954*e6eb57e7SKevin Yu if (entry != NULL) { 955*e6eb57e7SKevin Yu scf_entry_destroy(entry); 956*e6eb57e7SKevin Yu } 957*e6eb57e7SKevin Yu if (prop != NULL) { 958*e6eb57e7SKevin Yu scf_property_destroy(prop); 959*e6eb57e7SKevin Yu } 960*e6eb57e7SKevin Yu if (valueIter != NULL) { 961*e6eb57e7SKevin Yu scf_iter_destroy(valueIter); 962*e6eb57e7SKevin Yu } 963*e6eb57e7SKevin Yu if (valueLookup != NULL) { 964*e6eb57e7SKevin Yu scf_value_destroy(valueLookup); 965*e6eb57e7SKevin Yu } 966*e6eb57e7SKevin Yu 967*e6eb57e7SKevin Yu if (pg_or_prop_not_found == 1) { 968*e6eb57e7SKevin Yu return (FCOE_STATUS_OK); 969*e6eb57e7SKevin Yu } else { 970*e6eb57e7SKevin Yu return (FCOE_STATUS_ERROR); 971*e6eb57e7SKevin Yu } 972*e6eb57e7SKevin Yu } 973