19087SZhong.Wang@Sun.COM /* 29087SZhong.Wang@Sun.COM * CDDL HEADER START 39087SZhong.Wang@Sun.COM * 49087SZhong.Wang@Sun.COM * The contents of this file are subject to the terms of the 59087SZhong.Wang@Sun.COM * Common Development and Distribution License (the "License"). 69087SZhong.Wang@Sun.COM * You may not use this file except in compliance with the License. 79087SZhong.Wang@Sun.COM * 89087SZhong.Wang@Sun.COM * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE 99087SZhong.Wang@Sun.COM * or http://www.opensolaris.org/os/licensing. 109087SZhong.Wang@Sun.COM * See the License for the specific language governing permissions 119087SZhong.Wang@Sun.COM * and limitations under the License. 129087SZhong.Wang@Sun.COM * 139087SZhong.Wang@Sun.COM * When distributing Covered Code, include this CDDL HEADER in each 149087SZhong.Wang@Sun.COM * file and include the License file at usr/src/OPENSOLARIS.LICENSE. 159087SZhong.Wang@Sun.COM * If applicable, add the following below this CDDL HEADER, with the 169087SZhong.Wang@Sun.COM * fields enclosed by brackets "[]" replaced with your own identifying 179087SZhong.Wang@Sun.COM * information: Portions Copyright [yyyy] [name of copyright owner] 189087SZhong.Wang@Sun.COM * 199087SZhong.Wang@Sun.COM * CDDL HEADER END 209087SZhong.Wang@Sun.COM */ 219087SZhong.Wang@Sun.COM /* 229087SZhong.Wang@Sun.COM * Copyright 2009 Sun Microsystems, Inc. All rights reserved. 239087SZhong.Wang@Sun.COM * Use is subject to license terms. 249087SZhong.Wang@Sun.COM */ 259087SZhong.Wang@Sun.COM 269087SZhong.Wang@Sun.COM #include <stdlib.h> 279087SZhong.Wang@Sun.COM #include <stdio.h> 289087SZhong.Wang@Sun.COM #include <wchar.h> 299087SZhong.Wang@Sun.COM #include <strings.h> 309087SZhong.Wang@Sun.COM #include <sys/types.h> 319087SZhong.Wang@Sun.COM #include <sys/stat.h> 329087SZhong.Wang@Sun.COM #include <fcntl.h> 339087SZhong.Wang@Sun.COM #include <unistd.h> 349087SZhong.Wang@Sun.COM #include <libintl.h> 359087SZhong.Wang@Sun.COM #include <errno.h> 369087SZhong.Wang@Sun.COM #include <string.h> 379087SZhong.Wang@Sun.COM #include <assert.h> 389087SZhong.Wang@Sun.COM #include <syslog.h> 399087SZhong.Wang@Sun.COM #include <libfcoe.h> 409307Skelly.hu@Sun.COM #include <libdllink.h> 419087SZhong.Wang@Sun.COM #include <fcoeio.h> 42*9895SKevin.Yu@Sun.COM #include <libscf.h> 43*9895SKevin.Yu@Sun.COM #include <inttypes.h> 449087SZhong.Wang@Sun.COM 459087SZhong.Wang@Sun.COM #define FCOE_DEV_PATH "/devices/fcoe:admin" 469087SZhong.Wang@Sun.COM 479087SZhong.Wang@Sun.COM #define OPEN_FCOE 0 489087SZhong.Wang@Sun.COM #define OPEN_EXCL_FCOE O_EXCL 499087SZhong.Wang@Sun.COM 509087SZhong.Wang@Sun.COM /* 519087SZhong.Wang@Sun.COM * Open for fcoe module 529087SZhong.Wang@Sun.COM * 539087SZhong.Wang@Sun.COM * flag - open flag (OPEN_FCOE, OPEN_EXCL_FCOE) 549087SZhong.Wang@Sun.COM * fd - pointer to integer. On success, contains the fcoe file descriptor 559087SZhong.Wang@Sun.COM */ 569087SZhong.Wang@Sun.COM static int 579087SZhong.Wang@Sun.COM openFcoe(int flag, int *fd) 589087SZhong.Wang@Sun.COM { 599087SZhong.Wang@Sun.COM int ret = FCOE_STATUS_ERROR; 609087SZhong.Wang@Sun.COM 619087SZhong.Wang@Sun.COM if ((*fd = open(FCOE_DEV_PATH, O_NDELAY | O_RDONLY | flag)) != -1) { 629087SZhong.Wang@Sun.COM ret = FCOE_STATUS_OK; 639087SZhong.Wang@Sun.COM } else { 649087SZhong.Wang@Sun.COM if (errno == EPERM || errno == EACCES) { 659087SZhong.Wang@Sun.COM ret = FCOE_STATUS_ERROR_PERM; 669087SZhong.Wang@Sun.COM } else { 679087SZhong.Wang@Sun.COM ret = FCOE_STATUS_ERROR_OPEN_DEV; 689087SZhong.Wang@Sun.COM } 699087SZhong.Wang@Sun.COM syslog(LOG_DEBUG, "openFcoe:open failure:%s:errno(%d)", 709087SZhong.Wang@Sun.COM FCOE_DEV_PATH, errno); 719087SZhong.Wang@Sun.COM } 729087SZhong.Wang@Sun.COM 739087SZhong.Wang@Sun.COM return (ret); 749087SZhong.Wang@Sun.COM } 759087SZhong.Wang@Sun.COM 76*9895SKevin.Yu@Sun.COM static void 77*9895SKevin.Yu@Sun.COM WWN2str(char *buf, FCOE_PORT_WWN *wwn) { 78*9895SKevin.Yu@Sun.COM int j; 79*9895SKevin.Yu@Sun.COM unsigned char *pc = (unsigned char *)&(wwn->wwn[0]); 80*9895SKevin.Yu@Sun.COM buf[0] = '\0'; 81*9895SKevin.Yu@Sun.COM for (j = 0; j < 16; j += 2) { 82*9895SKevin.Yu@Sun.COM (void) sprintf(&buf[j], "%02X", (int)*pc++); 83*9895SKevin.Yu@Sun.COM } 84*9895SKevin.Yu@Sun.COM } 85*9895SKevin.Yu@Sun.COM 869087SZhong.Wang@Sun.COM static int 879087SZhong.Wang@Sun.COM isWWNZero(FCOE_PORT_WWN portwwn) 889087SZhong.Wang@Sun.COM { 899087SZhong.Wang@Sun.COM int i; 909087SZhong.Wang@Sun.COM int size = sizeof (FCOE_PORT_WWN); 919087SZhong.Wang@Sun.COM 929087SZhong.Wang@Sun.COM for (i = 0; i < size; i++) { 939087SZhong.Wang@Sun.COM if (portwwn.wwn[i] != 0) { 949087SZhong.Wang@Sun.COM return (0); 959087SZhong.Wang@Sun.COM } 969087SZhong.Wang@Sun.COM } 979087SZhong.Wang@Sun.COM return (1); 989087SZhong.Wang@Sun.COM } 999087SZhong.Wang@Sun.COM 100*9895SKevin.Yu@Sun.COM /* 101*9895SKevin.Yu@Sun.COM * Initialize scf fcoe service access 102*9895SKevin.Yu@Sun.COM * handle - returned handle 103*9895SKevin.Yu@Sun.COM * service - returned service handle 104*9895SKevin.Yu@Sun.COM */ 105*9895SKevin.Yu@Sun.COM static int 106*9895SKevin.Yu@Sun.COM fcoe_cfg_scf_init(scf_handle_t **handle, scf_service_t **service, int is_target) 107*9895SKevin.Yu@Sun.COM { 108*9895SKevin.Yu@Sun.COM scf_scope_t *scope = NULL; 109*9895SKevin.Yu@Sun.COM int ret; 110*9895SKevin.Yu@Sun.COM 111*9895SKevin.Yu@Sun.COM if ((*handle = scf_handle_create(SCF_VERSION)) == NULL) { 112*9895SKevin.Yu@Sun.COM syslog(LOG_ERR, "scf_handle_create failed - %s", 113*9895SKevin.Yu@Sun.COM scf_strerror(scf_error())); 114*9895SKevin.Yu@Sun.COM ret = FCOE_ERROR; 115*9895SKevin.Yu@Sun.COM goto err; 116*9895SKevin.Yu@Sun.COM } 117*9895SKevin.Yu@Sun.COM 118*9895SKevin.Yu@Sun.COM if (scf_handle_bind(*handle) == -1) { 119*9895SKevin.Yu@Sun.COM syslog(LOG_ERR, "scf_handle_bind failed - %s", 120*9895SKevin.Yu@Sun.COM scf_strerror(scf_error())); 121*9895SKevin.Yu@Sun.COM ret = FCOE_ERROR; 122*9895SKevin.Yu@Sun.COM goto err; 123*9895SKevin.Yu@Sun.COM } 124*9895SKevin.Yu@Sun.COM 125*9895SKevin.Yu@Sun.COM if ((*service = scf_service_create(*handle)) == NULL) { 126*9895SKevin.Yu@Sun.COM syslog(LOG_ERR, "scf_service_create failed - %s", 127*9895SKevin.Yu@Sun.COM scf_strerror(scf_error())); 128*9895SKevin.Yu@Sun.COM ret = FCOE_ERROR; 129*9895SKevin.Yu@Sun.COM goto err; 130*9895SKevin.Yu@Sun.COM } 131*9895SKevin.Yu@Sun.COM 132*9895SKevin.Yu@Sun.COM if ((scope = scf_scope_create(*handle)) == NULL) { 133*9895SKevin.Yu@Sun.COM syslog(LOG_ERR, "scf_scope_create failed - %s", 134*9895SKevin.Yu@Sun.COM scf_strerror(scf_error())); 135*9895SKevin.Yu@Sun.COM ret = FCOE_ERROR; 136*9895SKevin.Yu@Sun.COM goto err; 137*9895SKevin.Yu@Sun.COM } 138*9895SKevin.Yu@Sun.COM 139*9895SKevin.Yu@Sun.COM if (scf_handle_get_scope(*handle, SCF_SCOPE_LOCAL, scope) == -1) { 140*9895SKevin.Yu@Sun.COM syslog(LOG_ERR, "scf_handle_get_scope failed - %s", 141*9895SKevin.Yu@Sun.COM scf_strerror(scf_error())); 142*9895SKevin.Yu@Sun.COM ret = FCOE_ERROR; 143*9895SKevin.Yu@Sun.COM goto err; 144*9895SKevin.Yu@Sun.COM } 145*9895SKevin.Yu@Sun.COM 146*9895SKevin.Yu@Sun.COM if (scf_scope_get_service(scope, 147*9895SKevin.Yu@Sun.COM is_target ? FCOE_TARGET_SERVICE: FCOE_INITIATOR_SERVICE, 148*9895SKevin.Yu@Sun.COM *service) == -1) { 149*9895SKevin.Yu@Sun.COM syslog(LOG_ERR, "scf_scope_get_service failed - %s", 150*9895SKevin.Yu@Sun.COM scf_strerror(scf_error())); 151*9895SKevin.Yu@Sun.COM ret = FCOE_ERROR_SERVICE_NOT_FOUND; 152*9895SKevin.Yu@Sun.COM goto err; 153*9895SKevin.Yu@Sun.COM } 154*9895SKevin.Yu@Sun.COM 155*9895SKevin.Yu@Sun.COM scf_scope_destroy(scope); 156*9895SKevin.Yu@Sun.COM 157*9895SKevin.Yu@Sun.COM return (FCOE_SUCCESS); 158*9895SKevin.Yu@Sun.COM 159*9895SKevin.Yu@Sun.COM err: 160*9895SKevin.Yu@Sun.COM if (*handle != NULL) { 161*9895SKevin.Yu@Sun.COM scf_handle_destroy(*handle); 162*9895SKevin.Yu@Sun.COM } 163*9895SKevin.Yu@Sun.COM if (*service != NULL) { 164*9895SKevin.Yu@Sun.COM scf_service_destroy(*service); 165*9895SKevin.Yu@Sun.COM *service = NULL; 166*9895SKevin.Yu@Sun.COM } 167*9895SKevin.Yu@Sun.COM if (scope != NULL) { 168*9895SKevin.Yu@Sun.COM scf_scope_destroy(scope); 169*9895SKevin.Yu@Sun.COM } 170*9895SKevin.Yu@Sun.COM return (ret); 171*9895SKevin.Yu@Sun.COM } 172*9895SKevin.Yu@Sun.COM 173*9895SKevin.Yu@Sun.COM static int 174*9895SKevin.Yu@Sun.COM fcoe_add_remove_scf_entry(char *mac_name, 175*9895SKevin.Yu@Sun.COM char *pwwn, char *nwwn, 176*9895SKevin.Yu@Sun.COM int is_target, int is_promiscuous, int addRemoveFlag) 177*9895SKevin.Yu@Sun.COM { 178*9895SKevin.Yu@Sun.COM scf_handle_t *handle = NULL; 179*9895SKevin.Yu@Sun.COM scf_service_t *svc = NULL; 180*9895SKevin.Yu@Sun.COM scf_propertygroup_t *pg = NULL; 181*9895SKevin.Yu@Sun.COM scf_transaction_t *tran = NULL; 182*9895SKevin.Yu@Sun.COM scf_transaction_entry_t *entry = NULL; 183*9895SKevin.Yu@Sun.COM scf_property_t *prop = NULL; 184*9895SKevin.Yu@Sun.COM scf_value_t *valueLookup = NULL; 185*9895SKevin.Yu@Sun.COM scf_iter_t *valueIter = NULL; 186*9895SKevin.Yu@Sun.COM scf_value_t **valueSet = NULL; 187*9895SKevin.Yu@Sun.COM int ret = FCOE_SUCCESS; 188*9895SKevin.Yu@Sun.COM boolean_t createProp = B_FALSE; 189*9895SKevin.Yu@Sun.COM int lastAlloc = 0; 190*9895SKevin.Yu@Sun.COM char buf[FCOE_PORT_LIST_LENGTH] = {0}; 191*9895SKevin.Yu@Sun.COM char memberName[FCOE_PORT_LIST_LENGTH] = {0}; 192*9895SKevin.Yu@Sun.COM boolean_t found = B_FALSE; 193*9895SKevin.Yu@Sun.COM int i = 0; 194*9895SKevin.Yu@Sun.COM int valueArraySize = 0; 195*9895SKevin.Yu@Sun.COM int commitRet; 196*9895SKevin.Yu@Sun.COM int portListAlloc = 100; 197*9895SKevin.Yu@Sun.COM 198*9895SKevin.Yu@Sun.COM (void) snprintf(memberName, FCOE_PORT_LIST_LENGTH, 199*9895SKevin.Yu@Sun.COM "%s:%s:%s:%d:%d", mac_name, pwwn, nwwn, 200*9895SKevin.Yu@Sun.COM is_target, is_promiscuous); 201*9895SKevin.Yu@Sun.COM 202*9895SKevin.Yu@Sun.COM ret = fcoe_cfg_scf_init(&handle, &svc, is_target); 203*9895SKevin.Yu@Sun.COM if (ret != FCOE_SUCCESS) { 204*9895SKevin.Yu@Sun.COM goto out; 205*9895SKevin.Yu@Sun.COM } 206*9895SKevin.Yu@Sun.COM 207*9895SKevin.Yu@Sun.COM if (((pg = scf_pg_create(handle)) == NULL) || 208*9895SKevin.Yu@Sun.COM ((tran = scf_transaction_create(handle)) == NULL) || 209*9895SKevin.Yu@Sun.COM ((entry = scf_entry_create(handle)) == NULL) || 210*9895SKevin.Yu@Sun.COM ((prop = scf_property_create(handle)) == NULL) || 211*9895SKevin.Yu@Sun.COM ((valueIter = scf_iter_create(handle)) == NULL)) { 212*9895SKevin.Yu@Sun.COM ret = FCOE_ERROR; 213*9895SKevin.Yu@Sun.COM goto out; 214*9895SKevin.Yu@Sun.COM } 215*9895SKevin.Yu@Sun.COM 216*9895SKevin.Yu@Sun.COM /* get property group or create it */ 217*9895SKevin.Yu@Sun.COM if (scf_service_get_pg(svc, FCOE_PG_NAME, pg) == -1) { 218*9895SKevin.Yu@Sun.COM if ((scf_error() == SCF_ERROR_NOT_FOUND)) { 219*9895SKevin.Yu@Sun.COM if (scf_service_add_pg(svc, FCOE_PG_NAME, 220*9895SKevin.Yu@Sun.COM SCF_GROUP_APPLICATION, 0, pg) == -1) { 221*9895SKevin.Yu@Sun.COM syslog(LOG_ERR, "add pg failed - %s", 222*9895SKevin.Yu@Sun.COM scf_strerror(scf_error())); 223*9895SKevin.Yu@Sun.COM ret = FCOE_ERROR; 224*9895SKevin.Yu@Sun.COM } else { 225*9895SKevin.Yu@Sun.COM createProp = B_TRUE; 226*9895SKevin.Yu@Sun.COM } 227*9895SKevin.Yu@Sun.COM } else { 228*9895SKevin.Yu@Sun.COM syslog(LOG_ERR, "get pg failed - %s", 229*9895SKevin.Yu@Sun.COM scf_strerror(scf_error())); 230*9895SKevin.Yu@Sun.COM ret = FCOE_ERROR; 231*9895SKevin.Yu@Sun.COM } 232*9895SKevin.Yu@Sun.COM if (ret != FCOE_SUCCESS) { 233*9895SKevin.Yu@Sun.COM goto out; 234*9895SKevin.Yu@Sun.COM } 235*9895SKevin.Yu@Sun.COM } 236*9895SKevin.Yu@Sun.COM 237*9895SKevin.Yu@Sun.COM /* to make sure property exists */ 238*9895SKevin.Yu@Sun.COM if (createProp == B_FALSE) { 239*9895SKevin.Yu@Sun.COM if (scf_pg_get_property(pg, FCOE_PORT_LIST, prop) == -1) { 240*9895SKevin.Yu@Sun.COM if ((scf_error() == SCF_ERROR_NOT_FOUND)) { 241*9895SKevin.Yu@Sun.COM createProp = B_TRUE; 242*9895SKevin.Yu@Sun.COM } else { 243*9895SKevin.Yu@Sun.COM syslog(LOG_ERR, "get property failed - %s", 244*9895SKevin.Yu@Sun.COM scf_strerror(scf_error())); 245*9895SKevin.Yu@Sun.COM ret = FCOE_ERROR; 246*9895SKevin.Yu@Sun.COM goto out; 247*9895SKevin.Yu@Sun.COM } 248*9895SKevin.Yu@Sun.COM } 249*9895SKevin.Yu@Sun.COM } 250*9895SKevin.Yu@Sun.COM 251*9895SKevin.Yu@Sun.COM /* Begin the transaction */ 252*9895SKevin.Yu@Sun.COM if (scf_transaction_start(tran, pg) == -1) { 253*9895SKevin.Yu@Sun.COM syslog(LOG_ERR, "start transaction failed - %s", 254*9895SKevin.Yu@Sun.COM scf_strerror(scf_error())); 255*9895SKevin.Yu@Sun.COM ret = FCOE_ERROR; 256*9895SKevin.Yu@Sun.COM goto out; 257*9895SKevin.Yu@Sun.COM } 258*9895SKevin.Yu@Sun.COM 259*9895SKevin.Yu@Sun.COM valueSet = (scf_value_t **)calloc(1, sizeof (*valueSet) 260*9895SKevin.Yu@Sun.COM * (lastAlloc = portListAlloc)); 261*9895SKevin.Yu@Sun.COM if (valueSet == NULL) { 262*9895SKevin.Yu@Sun.COM ret = FCOE_ERROR_NOMEM; 263*9895SKevin.Yu@Sun.COM goto out; 264*9895SKevin.Yu@Sun.COM } 265*9895SKevin.Yu@Sun.COM 266*9895SKevin.Yu@Sun.COM if (createProp) { 267*9895SKevin.Yu@Sun.COM if (scf_transaction_property_new(tran, entry, FCOE_PORT_LIST, 268*9895SKevin.Yu@Sun.COM SCF_TYPE_USTRING) == -1) { 269*9895SKevin.Yu@Sun.COM if (scf_error() == SCF_ERROR_EXISTS) { 270*9895SKevin.Yu@Sun.COM ret = FCOE_ERROR_EXISTS; 271*9895SKevin.Yu@Sun.COM } else { 272*9895SKevin.Yu@Sun.COM syslog(LOG_ERR, 273*9895SKevin.Yu@Sun.COM "transaction property new failed - %s", 274*9895SKevin.Yu@Sun.COM scf_strerror(scf_error())); 275*9895SKevin.Yu@Sun.COM ret = FCOE_ERROR; 276*9895SKevin.Yu@Sun.COM } 277*9895SKevin.Yu@Sun.COM goto out; 278*9895SKevin.Yu@Sun.COM } 279*9895SKevin.Yu@Sun.COM } else { 280*9895SKevin.Yu@Sun.COM if (scf_transaction_property_change(tran, entry, 281*9895SKevin.Yu@Sun.COM FCOE_PORT_LIST, SCF_TYPE_USTRING) == -1) { 282*9895SKevin.Yu@Sun.COM syslog(LOG_ERR, 283*9895SKevin.Yu@Sun.COM "transaction property change failed - %s", 284*9895SKevin.Yu@Sun.COM scf_strerror(scf_error())); 285*9895SKevin.Yu@Sun.COM ret = FCOE_ERROR; 286*9895SKevin.Yu@Sun.COM goto out; 287*9895SKevin.Yu@Sun.COM } 288*9895SKevin.Yu@Sun.COM 289*9895SKevin.Yu@Sun.COM if (scf_pg_get_property(pg, FCOE_PORT_LIST, prop) == -1) { 290*9895SKevin.Yu@Sun.COM syslog(LOG_ERR, "get property failed - %s", 291*9895SKevin.Yu@Sun.COM scf_strerror(scf_error())); 292*9895SKevin.Yu@Sun.COM ret = FCOE_ERROR; 293*9895SKevin.Yu@Sun.COM goto out; 294*9895SKevin.Yu@Sun.COM } 295*9895SKevin.Yu@Sun.COM 296*9895SKevin.Yu@Sun.COM valueLookup = scf_value_create(handle); 297*9895SKevin.Yu@Sun.COM if (valueLookup == NULL) { 298*9895SKevin.Yu@Sun.COM syslog(LOG_ERR, "scf value alloc failed - %s", 299*9895SKevin.Yu@Sun.COM scf_strerror(scf_error())); 300*9895SKevin.Yu@Sun.COM ret = FCOE_ERROR; 301*9895SKevin.Yu@Sun.COM goto out; 302*9895SKevin.Yu@Sun.COM } 303*9895SKevin.Yu@Sun.COM 304*9895SKevin.Yu@Sun.COM if (scf_iter_property_values(valueIter, prop) == -1) { 305*9895SKevin.Yu@Sun.COM syslog(LOG_ERR, "iter value failed - %s", 306*9895SKevin.Yu@Sun.COM scf_strerror(scf_error())); 307*9895SKevin.Yu@Sun.COM ret = FCOE_ERROR; 308*9895SKevin.Yu@Sun.COM goto out; 309*9895SKevin.Yu@Sun.COM } 310*9895SKevin.Yu@Sun.COM 311*9895SKevin.Yu@Sun.COM while (scf_iter_next_value(valueIter, valueLookup) == 1) { 312*9895SKevin.Yu@Sun.COM char *macnameIter = NULL; 313*9895SKevin.Yu@Sun.COM char buftmp[FCOE_PORT_LIST_LENGTH] = {0}; 314*9895SKevin.Yu@Sun.COM 315*9895SKevin.Yu@Sun.COM bzero(buf, sizeof (buf)); 316*9895SKevin.Yu@Sun.COM if (scf_value_get_ustring(valueLookup, 317*9895SKevin.Yu@Sun.COM buf, MAXNAMELEN) == -1) { 318*9895SKevin.Yu@Sun.COM syslog(LOG_ERR, "iter value failed- %s", 319*9895SKevin.Yu@Sun.COM scf_strerror(scf_error())); 320*9895SKevin.Yu@Sun.COM ret = FCOE_ERROR; 321*9895SKevin.Yu@Sun.COM break; 322*9895SKevin.Yu@Sun.COM } 323*9895SKevin.Yu@Sun.COM (void) strcpy(buftmp, buf); 324*9895SKevin.Yu@Sun.COM macnameIter = strtok(buftmp, ":"); 325*9895SKevin.Yu@Sun.COM if (strcmp(macnameIter, mac_name) == 0) { 326*9895SKevin.Yu@Sun.COM if (addRemoveFlag == FCOE_SCF_ADD) { 327*9895SKevin.Yu@Sun.COM ret = FCOE_ERROR_EXISTS; 328*9895SKevin.Yu@Sun.COM break; 329*9895SKevin.Yu@Sun.COM } else { 330*9895SKevin.Yu@Sun.COM found = B_TRUE; 331*9895SKevin.Yu@Sun.COM continue; 332*9895SKevin.Yu@Sun.COM } 333*9895SKevin.Yu@Sun.COM } 334*9895SKevin.Yu@Sun.COM 335*9895SKevin.Yu@Sun.COM valueSet[i] = scf_value_create(handle); 336*9895SKevin.Yu@Sun.COM if (valueSet[i] == NULL) { 337*9895SKevin.Yu@Sun.COM syslog(LOG_ERR, "scf value alloc failed - %s", 338*9895SKevin.Yu@Sun.COM scf_strerror(scf_error())); 339*9895SKevin.Yu@Sun.COM ret = FCOE_ERROR; 340*9895SKevin.Yu@Sun.COM break; 341*9895SKevin.Yu@Sun.COM } 342*9895SKevin.Yu@Sun.COM 343*9895SKevin.Yu@Sun.COM if (scf_value_set_ustring(valueSet[i], buf) == -1) { 344*9895SKevin.Yu@Sun.COM syslog(LOG_ERR, "set value failed 1- %s", 345*9895SKevin.Yu@Sun.COM scf_strerror(scf_error())); 346*9895SKevin.Yu@Sun.COM ret = FCOE_ERROR; 347*9895SKevin.Yu@Sun.COM break; 348*9895SKevin.Yu@Sun.COM } 349*9895SKevin.Yu@Sun.COM 350*9895SKevin.Yu@Sun.COM if (scf_entry_add_value(entry, valueSet[i]) == -1) { 351*9895SKevin.Yu@Sun.COM syslog(LOG_ERR, "add value failed - %s", 352*9895SKevin.Yu@Sun.COM scf_strerror(scf_error())); 353*9895SKevin.Yu@Sun.COM ret = FCOE_ERROR; 354*9895SKevin.Yu@Sun.COM break; 355*9895SKevin.Yu@Sun.COM } 356*9895SKevin.Yu@Sun.COM 357*9895SKevin.Yu@Sun.COM i++; 358*9895SKevin.Yu@Sun.COM 359*9895SKevin.Yu@Sun.COM if (i >= lastAlloc) { 360*9895SKevin.Yu@Sun.COM lastAlloc += portListAlloc; 361*9895SKevin.Yu@Sun.COM valueSet = realloc(valueSet, 362*9895SKevin.Yu@Sun.COM sizeof (*valueSet) * lastAlloc); 363*9895SKevin.Yu@Sun.COM if (valueSet == NULL) { 364*9895SKevin.Yu@Sun.COM ret = FCOE_ERROR; 365*9895SKevin.Yu@Sun.COM break; 366*9895SKevin.Yu@Sun.COM } 367*9895SKevin.Yu@Sun.COM } 368*9895SKevin.Yu@Sun.COM } 369*9895SKevin.Yu@Sun.COM } 370*9895SKevin.Yu@Sun.COM 371*9895SKevin.Yu@Sun.COM valueArraySize = i; 372*9895SKevin.Yu@Sun.COM if (!found && (addRemoveFlag == FCOE_SCF_REMOVE)) { 373*9895SKevin.Yu@Sun.COM ret = FCOE_ERROR_MEMBER_NOT_FOUND; 374*9895SKevin.Yu@Sun.COM } 375*9895SKevin.Yu@Sun.COM if (ret != FCOE_SUCCESS) { 376*9895SKevin.Yu@Sun.COM goto out; 377*9895SKevin.Yu@Sun.COM } 378*9895SKevin.Yu@Sun.COM 379*9895SKevin.Yu@Sun.COM if (addRemoveFlag == FCOE_SCF_ADD) { 380*9895SKevin.Yu@Sun.COM /* 381*9895SKevin.Yu@Sun.COM * Now create the new entry 382*9895SKevin.Yu@Sun.COM */ 383*9895SKevin.Yu@Sun.COM valueSet[i] = scf_value_create(handle); 384*9895SKevin.Yu@Sun.COM if (valueSet[i] == NULL) { 385*9895SKevin.Yu@Sun.COM syslog(LOG_ERR, "scf value alloc failed - %s", 386*9895SKevin.Yu@Sun.COM scf_strerror(scf_error())); 387*9895SKevin.Yu@Sun.COM ret = FCOE_ERROR; 388*9895SKevin.Yu@Sun.COM goto out; 389*9895SKevin.Yu@Sun.COM } else { 390*9895SKevin.Yu@Sun.COM valueArraySize++; 391*9895SKevin.Yu@Sun.COM } 392*9895SKevin.Yu@Sun.COM 393*9895SKevin.Yu@Sun.COM /* 394*9895SKevin.Yu@Sun.COM * Set the new member name 395*9895SKevin.Yu@Sun.COM */ 396*9895SKevin.Yu@Sun.COM if (scf_value_set_ustring(valueSet[i], memberName) == -1) { 397*9895SKevin.Yu@Sun.COM syslog(LOG_ERR, "set value failed 2- %s", 398*9895SKevin.Yu@Sun.COM scf_strerror(scf_error())); 399*9895SKevin.Yu@Sun.COM ret = FCOE_ERROR; 400*9895SKevin.Yu@Sun.COM goto out; 401*9895SKevin.Yu@Sun.COM } 402*9895SKevin.Yu@Sun.COM 403*9895SKevin.Yu@Sun.COM /* 404*9895SKevin.Yu@Sun.COM * Add the new member 405*9895SKevin.Yu@Sun.COM */ 406*9895SKevin.Yu@Sun.COM if (scf_entry_add_value(entry, valueSet[i]) == -1) { 407*9895SKevin.Yu@Sun.COM syslog(LOG_ERR, "add value failed - %s", 408*9895SKevin.Yu@Sun.COM scf_strerror(scf_error())); 409*9895SKevin.Yu@Sun.COM ret = FCOE_ERROR; 410*9895SKevin.Yu@Sun.COM goto out; 411*9895SKevin.Yu@Sun.COM } 412*9895SKevin.Yu@Sun.COM } 413*9895SKevin.Yu@Sun.COM 414*9895SKevin.Yu@Sun.COM if ((commitRet = scf_transaction_commit(tran)) != 1) { 415*9895SKevin.Yu@Sun.COM syslog(LOG_ERR, "transaction commit failed - %s", 416*9895SKevin.Yu@Sun.COM scf_strerror(scf_error())); 417*9895SKevin.Yu@Sun.COM if (commitRet == 0) { 418*9895SKevin.Yu@Sun.COM ret = FCOE_ERROR_BUSY; 419*9895SKevin.Yu@Sun.COM } else { 420*9895SKevin.Yu@Sun.COM ret = FCOE_ERROR; 421*9895SKevin.Yu@Sun.COM } 422*9895SKevin.Yu@Sun.COM goto out; 423*9895SKevin.Yu@Sun.COM } 424*9895SKevin.Yu@Sun.COM 425*9895SKevin.Yu@Sun.COM out: 426*9895SKevin.Yu@Sun.COM /* 427*9895SKevin.Yu@Sun.COM * Free resources 428*9895SKevin.Yu@Sun.COM */ 429*9895SKevin.Yu@Sun.COM if (handle != NULL) { 430*9895SKevin.Yu@Sun.COM scf_handle_destroy(handle); 431*9895SKevin.Yu@Sun.COM } 432*9895SKevin.Yu@Sun.COM if (svc != NULL) { 433*9895SKevin.Yu@Sun.COM scf_service_destroy(svc); 434*9895SKevin.Yu@Sun.COM } 435*9895SKevin.Yu@Sun.COM if (pg != NULL) { 436*9895SKevin.Yu@Sun.COM scf_pg_destroy(pg); 437*9895SKevin.Yu@Sun.COM } 438*9895SKevin.Yu@Sun.COM if (tran != NULL) { 439*9895SKevin.Yu@Sun.COM scf_transaction_destroy(tran); 440*9895SKevin.Yu@Sun.COM } 441*9895SKevin.Yu@Sun.COM if (entry != NULL) { 442*9895SKevin.Yu@Sun.COM scf_entry_destroy(entry); 443*9895SKevin.Yu@Sun.COM } 444*9895SKevin.Yu@Sun.COM if (prop != NULL) { 445*9895SKevin.Yu@Sun.COM scf_property_destroy(prop); 446*9895SKevin.Yu@Sun.COM } 447*9895SKevin.Yu@Sun.COM if (valueIter != NULL) { 448*9895SKevin.Yu@Sun.COM scf_iter_destroy(valueIter); 449*9895SKevin.Yu@Sun.COM } 450*9895SKevin.Yu@Sun.COM if (valueLookup != NULL) { 451*9895SKevin.Yu@Sun.COM scf_value_destroy(valueLookup); 452*9895SKevin.Yu@Sun.COM } 453*9895SKevin.Yu@Sun.COM 454*9895SKevin.Yu@Sun.COM /* 455*9895SKevin.Yu@Sun.COM * Free valueSet scf resources 456*9895SKevin.Yu@Sun.COM */ 457*9895SKevin.Yu@Sun.COM if (valueArraySize > 0) { 458*9895SKevin.Yu@Sun.COM for (i = 0; i < valueArraySize; i++) { 459*9895SKevin.Yu@Sun.COM scf_value_destroy(valueSet[i]); 460*9895SKevin.Yu@Sun.COM } 461*9895SKevin.Yu@Sun.COM } 462*9895SKevin.Yu@Sun.COM /* 463*9895SKevin.Yu@Sun.COM * Now free the pointer array to the resources 464*9895SKevin.Yu@Sun.COM */ 465*9895SKevin.Yu@Sun.COM if (valueSet != NULL) { 466*9895SKevin.Yu@Sun.COM free(valueSet); 467*9895SKevin.Yu@Sun.COM } 468*9895SKevin.Yu@Sun.COM 469*9895SKevin.Yu@Sun.COM return (ret); 470*9895SKevin.Yu@Sun.COM } 471*9895SKevin.Yu@Sun.COM 4729087SZhong.Wang@Sun.COM FCOE_STATUS 4739087SZhong.Wang@Sun.COM FCOE_CreatePort( 4749087SZhong.Wang@Sun.COM const FCOE_UINT8 *macLinkName, 4759087SZhong.Wang@Sun.COM FCOE_UINT8 portType, 4769087SZhong.Wang@Sun.COM FCOE_PORT_WWN pwwn, 4779087SZhong.Wang@Sun.COM FCOE_PORT_WWN nwwn, 4789087SZhong.Wang@Sun.COM FCOE_UINT8 promiscuous) 4799087SZhong.Wang@Sun.COM { 480*9895SKevin.Yu@Sun.COM FCOE_STATUS status; 4819307Skelly.hu@Sun.COM int fcoe_fd; 4829307Skelly.hu@Sun.COM fcoeio_t fcoeio; 4839087SZhong.Wang@Sun.COM fcoeio_create_port_param_t param; 4849307Skelly.hu@Sun.COM dladm_handle_t handle; 4859307Skelly.hu@Sun.COM datalink_id_t linkid; 4869307Skelly.hu@Sun.COM datalink_class_t class; 4879087SZhong.Wang@Sun.COM 4889087SZhong.Wang@Sun.COM bzero(¶m, sizeof (fcoeio_create_port_param_t)); 4899087SZhong.Wang@Sun.COM 4909087SZhong.Wang@Sun.COM if (macLinkName == NULL) { 4919087SZhong.Wang@Sun.COM return (FCOE_STATUS_ERROR_INVAL_ARG); 4929087SZhong.Wang@Sun.COM } 4939087SZhong.Wang@Sun.COM 4949307Skelly.hu@Sun.COM if (strlen((char *)macLinkName) > MAXLINKNAMELEN-1) { 4959307Skelly.hu@Sun.COM return (FCOE_STATUS_ERROR_MAC_LEN); 4969307Skelly.hu@Sun.COM } 4979307Skelly.hu@Sun.COM 4989307Skelly.hu@Sun.COM if (dladm_open(&handle) != DLADM_STATUS_OK) { 4999307Skelly.hu@Sun.COM return (FCOE_STATUS_ERROR); 5009307Skelly.hu@Sun.COM } 5019307Skelly.hu@Sun.COM 5029307Skelly.hu@Sun.COM if (dladm_name2info(handle, (const char *)macLinkName, 5039307Skelly.hu@Sun.COM &linkid, NULL, &class, NULL) != DLADM_STATUS_OK) { 5049307Skelly.hu@Sun.COM dladm_close(handle); 505*9895SKevin.Yu@Sun.COM (void) fcoe_add_remove_scf_entry((char *)macLinkName, 506*9895SKevin.Yu@Sun.COM "", 507*9895SKevin.Yu@Sun.COM "", 508*9895SKevin.Yu@Sun.COM portType, 509*9895SKevin.Yu@Sun.COM 0, 510*9895SKevin.Yu@Sun.COM FCOE_SCF_REMOVE); 5119307Skelly.hu@Sun.COM return (FCOE_STATUS_ERROR_GET_LINKINFO); 5129307Skelly.hu@Sun.COM } 5139307Skelly.hu@Sun.COM dladm_close(handle); 5149307Skelly.hu@Sun.COM 5159307Skelly.hu@Sun.COM if (class != DATALINK_CLASS_PHYS) { 5169307Skelly.hu@Sun.COM return (FCOE_STATUS_ERROR_CLASS_UNSUPPORT); 5179307Skelly.hu@Sun.COM } 5189307Skelly.hu@Sun.COM 5199087SZhong.Wang@Sun.COM if (portType != FCOE_PORTTYPE_INITIATOR && 5209087SZhong.Wang@Sun.COM portType != FCOE_PORTTYPE_TARGET) { 5219087SZhong.Wang@Sun.COM return (FCOE_STATUS_ERROR_INVAL_ARG); 5229087SZhong.Wang@Sun.COM } 5239087SZhong.Wang@Sun.COM 5249087SZhong.Wang@Sun.COM if (!isWWNZero(pwwn)) { 5259087SZhong.Wang@Sun.COM param.fcp_pwwn_provided = 1; 5269087SZhong.Wang@Sun.COM bcopy(pwwn.wwn, param.fcp_pwwn, 8); 5279087SZhong.Wang@Sun.COM } 5289087SZhong.Wang@Sun.COM 5299087SZhong.Wang@Sun.COM if (!isWWNZero(nwwn)) { 5309087SZhong.Wang@Sun.COM param.fcp_nwwn_provided = 1; 5319087SZhong.Wang@Sun.COM bcopy(nwwn.wwn, param.fcp_nwwn, 8); 5329087SZhong.Wang@Sun.COM } 5339087SZhong.Wang@Sun.COM 5349087SZhong.Wang@Sun.COM if (param.fcp_pwwn_provided == 1 && 5359087SZhong.Wang@Sun.COM param.fcp_nwwn_provided == 1 && 5369087SZhong.Wang@Sun.COM bcmp(&pwwn, &nwwn, 8) == 0) { 5379087SZhong.Wang@Sun.COM return (FCOE_STATUS_ERROR_WWN_SAME); 5389087SZhong.Wang@Sun.COM } 5399087SZhong.Wang@Sun.COM 5409087SZhong.Wang@Sun.COM param.fcp_force_promisc = promiscuous; 5419307Skelly.hu@Sun.COM param.fcp_mac_linkid = linkid; 5429087SZhong.Wang@Sun.COM param.fcp_port_type = (fcoe_cli_type_t)portType; 5439087SZhong.Wang@Sun.COM 5449087SZhong.Wang@Sun.COM if ((status = openFcoe(OPEN_FCOE, &fcoe_fd)) != FCOE_STATUS_OK) { 5459087SZhong.Wang@Sun.COM return (status); 5469087SZhong.Wang@Sun.COM } 5479087SZhong.Wang@Sun.COM 5489087SZhong.Wang@Sun.COM (void) memset(&fcoeio, 0, sizeof (fcoeio)); 5499087SZhong.Wang@Sun.COM fcoeio.fcoeio_cmd = FCOEIO_CREATE_FCOE_PORT; 5509087SZhong.Wang@Sun.COM 5519087SZhong.Wang@Sun.COM fcoeio.fcoeio_ilen = sizeof (param); 5529087SZhong.Wang@Sun.COM fcoeio.fcoeio_xfer = FCOEIO_XFER_WRITE; 5539087SZhong.Wang@Sun.COM fcoeio.fcoeio_ibuf = (uintptr_t)¶m; 5549087SZhong.Wang@Sun.COM 5559087SZhong.Wang@Sun.COM if (ioctl(fcoe_fd, FCOEIO_CMD, &fcoeio) != 0) { 5569087SZhong.Wang@Sun.COM switch (fcoeio.fcoeio_status) { 5579087SZhong.Wang@Sun.COM case FCOEIOE_INVAL_ARG: 5589087SZhong.Wang@Sun.COM status = FCOE_STATUS_ERROR_INVAL_ARG; 5599087SZhong.Wang@Sun.COM break; 5609087SZhong.Wang@Sun.COM 5619087SZhong.Wang@Sun.COM case FCOEIOE_BUSY: 5629087SZhong.Wang@Sun.COM status = FCOE_STATUS_ERROR_BUSY; 5639087SZhong.Wang@Sun.COM break; 5649087SZhong.Wang@Sun.COM 5659087SZhong.Wang@Sun.COM case FCOEIOE_ALREADY: 5669087SZhong.Wang@Sun.COM status = FCOE_STATUS_ERROR_ALREADY; 5679087SZhong.Wang@Sun.COM break; 5689087SZhong.Wang@Sun.COM 5699087SZhong.Wang@Sun.COM case FCOEIOE_PWWN_CONFLICTED: 5709087SZhong.Wang@Sun.COM status = FCOE_STATUS_ERROR_PWWN_CONFLICTED; 5719087SZhong.Wang@Sun.COM break; 5729087SZhong.Wang@Sun.COM 5739087SZhong.Wang@Sun.COM case FCOEIOE_NWWN_CONFLICTED: 5749087SZhong.Wang@Sun.COM status = FCOE_STATUS_ERROR_NWWN_CONFLICTED; 5759087SZhong.Wang@Sun.COM break; 5769087SZhong.Wang@Sun.COM 5779087SZhong.Wang@Sun.COM case FCOEIOE_CREATE_MAC: 5789087SZhong.Wang@Sun.COM status = FCOE_STATUS_ERROR_CREATE_MAC; 5799087SZhong.Wang@Sun.COM break; 5809087SZhong.Wang@Sun.COM 5819087SZhong.Wang@Sun.COM case FCOEIOE_OPEN_MAC: 5829087SZhong.Wang@Sun.COM status = FCOE_STATUS_ERROR_OPEN_MAC; 5839087SZhong.Wang@Sun.COM break; 5849087SZhong.Wang@Sun.COM 5859087SZhong.Wang@Sun.COM case FCOEIOE_CREATE_PORT: 5869087SZhong.Wang@Sun.COM status = FCOE_STATUS_ERROR_CREATE_PORT; 5879087SZhong.Wang@Sun.COM break; 5889087SZhong.Wang@Sun.COM 5899087SZhong.Wang@Sun.COM case FCOEIOE_NEED_JUMBO_FRAME: 5909087SZhong.Wang@Sun.COM status = FCOE_STATUS_ERROR_NEED_JUMBO_FRAME; 5919087SZhong.Wang@Sun.COM break; 5929087SZhong.Wang@Sun.COM 5939087SZhong.Wang@Sun.COM default: 5949087SZhong.Wang@Sun.COM status = FCOE_STATUS_ERROR; 5959087SZhong.Wang@Sun.COM } 5969087SZhong.Wang@Sun.COM } else { 597*9895SKevin.Yu@Sun.COM char cpwwn[17], cnwwn[17]; 598*9895SKevin.Yu@Sun.COM 599*9895SKevin.Yu@Sun.COM WWN2str(cpwwn, &pwwn); 600*9895SKevin.Yu@Sun.COM WWN2str(cnwwn, &nwwn); 601*9895SKevin.Yu@Sun.COM 602*9895SKevin.Yu@Sun.COM (void) fcoe_add_remove_scf_entry((char *)macLinkName, 603*9895SKevin.Yu@Sun.COM cpwwn, 604*9895SKevin.Yu@Sun.COM cnwwn, 605*9895SKevin.Yu@Sun.COM portType, 606*9895SKevin.Yu@Sun.COM promiscuous, 607*9895SKevin.Yu@Sun.COM FCOE_SCF_ADD); 6089087SZhong.Wang@Sun.COM status = FCOE_STATUS_OK; 6099087SZhong.Wang@Sun.COM } 6109087SZhong.Wang@Sun.COM (void) close(fcoe_fd); 6119087SZhong.Wang@Sun.COM return (status); 6129087SZhong.Wang@Sun.COM } 6139087SZhong.Wang@Sun.COM 6149087SZhong.Wang@Sun.COM FCOE_STATUS 6159087SZhong.Wang@Sun.COM FCOE_DeletePort(const FCOE_UINT8 *macLinkName) 6169087SZhong.Wang@Sun.COM { 6179087SZhong.Wang@Sun.COM FCOE_STATUS status = FCOE_STATUS_OK; 6189087SZhong.Wang@Sun.COM int fcoe_fd; 6199087SZhong.Wang@Sun.COM fcoeio_t fcoeio; 6209307Skelly.hu@Sun.COM dladm_handle_t handle; 6219307Skelly.hu@Sun.COM datalink_id_t linkid; 6229307Skelly.hu@Sun.COM fcoeio_delete_port_param_t fc_del_port; 623*9895SKevin.Yu@Sun.COM uint64_t is_target = 0; 624*9895SKevin.Yu@Sun.COM int io_ret = 0; 6259087SZhong.Wang@Sun.COM 6269087SZhong.Wang@Sun.COM if (macLinkName == NULL) { 6279087SZhong.Wang@Sun.COM return (FCOE_STATUS_ERROR_INVAL_ARG); 6289087SZhong.Wang@Sun.COM } 6299087SZhong.Wang@Sun.COM 6309307Skelly.hu@Sun.COM if (strlen((char *)macLinkName) > MAXLINKNAMELEN-1) { 6319087SZhong.Wang@Sun.COM return (FCOE_STATUS_ERROR_MAC_LEN); 6329087SZhong.Wang@Sun.COM } 6339307Skelly.hu@Sun.COM if (dladm_open(&handle) != DLADM_STATUS_OK) { 6349307Skelly.hu@Sun.COM return (FCOE_STATUS_ERROR); 6359307Skelly.hu@Sun.COM } 6369307Skelly.hu@Sun.COM 6379307Skelly.hu@Sun.COM if (dladm_name2info(handle, (const char *)macLinkName, 6389307Skelly.hu@Sun.COM &linkid, NULL, NULL, NULL) != DLADM_STATUS_OK) { 6399307Skelly.hu@Sun.COM dladm_close(handle); 6409307Skelly.hu@Sun.COM return (FCOE_STATUS_ERROR_GET_LINKINFO); 6419307Skelly.hu@Sun.COM } 6429307Skelly.hu@Sun.COM dladm_close(handle); 6439087SZhong.Wang@Sun.COM 6449087SZhong.Wang@Sun.COM if ((status = openFcoe(OPEN_FCOE, &fcoe_fd)) != FCOE_STATUS_OK) { 6459087SZhong.Wang@Sun.COM return (status); 6469087SZhong.Wang@Sun.COM } 6479087SZhong.Wang@Sun.COM 6489307Skelly.hu@Sun.COM fc_del_port.fdp_mac_linkid = linkid; 6499307Skelly.hu@Sun.COM 6509087SZhong.Wang@Sun.COM (void) memset(&fcoeio, 0, sizeof (fcoeio)); 6519087SZhong.Wang@Sun.COM fcoeio.fcoeio_cmd = FCOEIO_DELETE_FCOE_PORT; 6529087SZhong.Wang@Sun.COM 6539307Skelly.hu@Sun.COM /* only 4 bytes here, need to change */ 6549307Skelly.hu@Sun.COM fcoeio.fcoeio_ilen = sizeof (fcoeio_delete_port_param_t); 655*9895SKevin.Yu@Sun.COM fcoeio.fcoeio_olen = sizeof (uint64_t); 656*9895SKevin.Yu@Sun.COM fcoeio.fcoeio_xfer = FCOEIO_XFER_RW; 6579307Skelly.hu@Sun.COM fcoeio.fcoeio_ibuf = (uintptr_t)&fc_del_port; 658*9895SKevin.Yu@Sun.COM fcoeio.fcoeio_obuf = (uintptr_t)&is_target; 6599087SZhong.Wang@Sun.COM 660*9895SKevin.Yu@Sun.COM io_ret = ioctl(fcoe_fd, FCOEIO_CMD, &fcoeio); 661*9895SKevin.Yu@Sun.COM if (io_ret != 0) { 6629087SZhong.Wang@Sun.COM switch (fcoeio.fcoeio_status) { 6639087SZhong.Wang@Sun.COM case FCOEIOE_INVAL_ARG: 6649087SZhong.Wang@Sun.COM status = FCOE_STATUS_ERROR_INVAL_ARG; 6659087SZhong.Wang@Sun.COM break; 6669087SZhong.Wang@Sun.COM 6679087SZhong.Wang@Sun.COM case FCOEIOE_BUSY: 6689087SZhong.Wang@Sun.COM status = FCOE_STATUS_ERROR_BUSY; 6699087SZhong.Wang@Sun.COM break; 6709087SZhong.Wang@Sun.COM 6719087SZhong.Wang@Sun.COM case FCOEIOE_ALREADY: 6729087SZhong.Wang@Sun.COM status = FCOE_STATUS_ERROR_ALREADY; 6739087SZhong.Wang@Sun.COM break; 6749087SZhong.Wang@Sun.COM 6759087SZhong.Wang@Sun.COM case FCOEIOE_MAC_NOT_FOUND: 6769087SZhong.Wang@Sun.COM status = FCOE_STATUS_ERROR_MAC_NOT_FOUND; 6779087SZhong.Wang@Sun.COM break; 6789087SZhong.Wang@Sun.COM 6799087SZhong.Wang@Sun.COM case FCOEIOE_OFFLINE_FAILURE: 6809087SZhong.Wang@Sun.COM status = FCOE_STATUS_ERROR_OFFLINE_DEV; 6819087SZhong.Wang@Sun.COM break; 6829087SZhong.Wang@Sun.COM 6839087SZhong.Wang@Sun.COM default: 6849087SZhong.Wang@Sun.COM status = FCOE_STATUS_ERROR; 6859087SZhong.Wang@Sun.COM } 6869087SZhong.Wang@Sun.COM } else { 687*9895SKevin.Yu@Sun.COM (void) fcoe_add_remove_scf_entry((char *)macLinkName, 688*9895SKevin.Yu@Sun.COM "", 689*9895SKevin.Yu@Sun.COM "", 690*9895SKevin.Yu@Sun.COM is_target, 691*9895SKevin.Yu@Sun.COM 0, 692*9895SKevin.Yu@Sun.COM FCOE_SCF_REMOVE); 6939087SZhong.Wang@Sun.COM status = FCOE_STATUS_OK; 6949087SZhong.Wang@Sun.COM } 695*9895SKevin.Yu@Sun.COM 696*9895SKevin.Yu@Sun.COM if (io_ret == FCOEIOE_MAC_NOT_FOUND) { 697*9895SKevin.Yu@Sun.COM (void) fcoe_add_remove_scf_entry((char *)macLinkName, 698*9895SKevin.Yu@Sun.COM "", 699*9895SKevin.Yu@Sun.COM "", 700*9895SKevin.Yu@Sun.COM 0, 701*9895SKevin.Yu@Sun.COM 0, 702*9895SKevin.Yu@Sun.COM FCOE_SCF_REMOVE); 703*9895SKevin.Yu@Sun.COM (void) fcoe_add_remove_scf_entry((char *)macLinkName, 704*9895SKevin.Yu@Sun.COM "", 705*9895SKevin.Yu@Sun.COM "", 706*9895SKevin.Yu@Sun.COM 1, 707*9895SKevin.Yu@Sun.COM 0, 708*9895SKevin.Yu@Sun.COM FCOE_SCF_REMOVE); 709*9895SKevin.Yu@Sun.COM } 7109087SZhong.Wang@Sun.COM (void) close(fcoe_fd); 7119087SZhong.Wang@Sun.COM return (status); 7129087SZhong.Wang@Sun.COM } 7139087SZhong.Wang@Sun.COM 7149087SZhong.Wang@Sun.COM FCOE_STATUS 7159087SZhong.Wang@Sun.COM FCOE_GetPortList( 7169087SZhong.Wang@Sun.COM FCOE_UINT32 *port_num, 7179087SZhong.Wang@Sun.COM FCOE_PORT_ATTRIBUTE **portlist) 7189087SZhong.Wang@Sun.COM { 7199087SZhong.Wang@Sun.COM FCOE_STATUS status = FCOE_STATUS_OK; 7209307Skelly.hu@Sun.COM int fcoe_fd; 7219087SZhong.Wang@Sun.COM fcoeio_t fcoeio; 7229307Skelly.hu@Sun.COM fcoe_port_list_t *inportlist = NULL; 7239087SZhong.Wang@Sun.COM FCOE_PORT_ATTRIBUTE *outportlist = NULL; 7249307Skelly.hu@Sun.COM int i; 7259307Skelly.hu@Sun.COM int size = 64; /* default first attempt */ 7269307Skelly.hu@Sun.COM int retry = 0; 7279307Skelly.hu@Sun.COM int bufsize; 7289307Skelly.hu@Sun.COM dladm_handle_t handle; 7299307Skelly.hu@Sun.COM char mac_name[MAXLINKNAMELEN]; 7309087SZhong.Wang@Sun.COM 7319087SZhong.Wang@Sun.COM if (port_num == NULL || portlist == NULL) { 7329087SZhong.Wang@Sun.COM return (FCOE_STATUS_ERROR_INVAL_ARG); 7339087SZhong.Wang@Sun.COM } 7349087SZhong.Wang@Sun.COM *port_num = 0; 7359087SZhong.Wang@Sun.COM 7369087SZhong.Wang@Sun.COM if ((status = openFcoe(OPEN_FCOE, &fcoe_fd)) != FCOE_STATUS_OK) { 7379087SZhong.Wang@Sun.COM return (status); 7389087SZhong.Wang@Sun.COM } 7399087SZhong.Wang@Sun.COM 7409087SZhong.Wang@Sun.COM /* Get fcoe port list */ 7419087SZhong.Wang@Sun.COM (void) memset(&fcoeio, 0, sizeof (fcoeio)); 7429087SZhong.Wang@Sun.COM retry = 0; 7439087SZhong.Wang@Sun.COM 7449087SZhong.Wang@Sun.COM do { 7459087SZhong.Wang@Sun.COM bufsize = sizeof (fcoe_port_instance_t) * (size - 1) + 7469087SZhong.Wang@Sun.COM sizeof (fcoe_port_list_t); 7479087SZhong.Wang@Sun.COM inportlist = (fcoe_port_list_t *)malloc(bufsize); 7489087SZhong.Wang@Sun.COM fcoeio.fcoeio_cmd = FCOEIO_GET_FCOE_PORT_LIST; 7499087SZhong.Wang@Sun.COM fcoeio.fcoeio_olen = bufsize; 7509087SZhong.Wang@Sun.COM fcoeio.fcoeio_xfer = FCOEIO_XFER_READ; 7519087SZhong.Wang@Sun.COM fcoeio.fcoeio_obuf = (uintptr_t)inportlist; 7529087SZhong.Wang@Sun.COM 7539087SZhong.Wang@Sun.COM if (ioctl(fcoe_fd, FCOEIO_CMD, &fcoeio) != 0) { 7549087SZhong.Wang@Sun.COM if (fcoeio.fcoeio_status == FCOEIOE_MORE_DATA) { 7559087SZhong.Wang@Sun.COM size = inportlist->numPorts; 7569087SZhong.Wang@Sun.COM } 7579087SZhong.Wang@Sun.COM free(inportlist); 7589087SZhong.Wang@Sun.COM switch (fcoeio.fcoeio_status) { 7599087SZhong.Wang@Sun.COM case FCOEIOE_INVAL_ARG: 7609087SZhong.Wang@Sun.COM status = FCOE_STATUS_ERROR_INVAL_ARG; 7619087SZhong.Wang@Sun.COM (void) close(fcoe_fd); 7629087SZhong.Wang@Sun.COM return (status); 7639087SZhong.Wang@Sun.COM 7649087SZhong.Wang@Sun.COM case FCOEIOE_BUSY: 7659087SZhong.Wang@Sun.COM status = FCOE_STATUS_ERROR_BUSY; 7669087SZhong.Wang@Sun.COM retry++; 7679087SZhong.Wang@Sun.COM break; 7689087SZhong.Wang@Sun.COM 7699087SZhong.Wang@Sun.COM case FCOEIOE_MORE_DATA: 7709087SZhong.Wang@Sun.COM status = FCOE_STATUS_ERROR_MORE_DATA; 7719087SZhong.Wang@Sun.COM retry++; 7729087SZhong.Wang@Sun.COM default: 7739087SZhong.Wang@Sun.COM status = FCOE_STATUS_ERROR; 774*9895SKevin.Yu@Sun.COM (void) close(fcoe_fd); 775*9895SKevin.Yu@Sun.COM return (status); 7769087SZhong.Wang@Sun.COM } 7779087SZhong.Wang@Sun.COM } else { 7789087SZhong.Wang@Sun.COM status = FCOE_STATUS_OK; 7799087SZhong.Wang@Sun.COM break; 7809087SZhong.Wang@Sun.COM } 7819087SZhong.Wang@Sun.COM } while (retry <= 3 && status != FCOE_STATUS_OK); 7829087SZhong.Wang@Sun.COM 7839307Skelly.hu@Sun.COM if (status == FCOE_STATUS_OK && inportlist->numPorts > 0) { 7849307Skelly.hu@Sun.COM if (dladm_open(&handle) != DLADM_STATUS_OK) { 7859307Skelly.hu@Sun.COM handle = NULL; 7869307Skelly.hu@Sun.COM } 7879307Skelly.hu@Sun.COM 7889087SZhong.Wang@Sun.COM outportlist = (PFCOE_PORT_ATTRIBUTE) 7899087SZhong.Wang@Sun.COM malloc(sizeof (FCOE_PORT_ATTRIBUTE) * inportlist->numPorts); 7909087SZhong.Wang@Sun.COM 7919087SZhong.Wang@Sun.COM for (i = 0; i < inportlist->numPorts; i++) { 7929087SZhong.Wang@Sun.COM fcoe_port_instance_t *pi = &inportlist->ports[i]; 7939087SZhong.Wang@Sun.COM FCOE_PORT_ATTRIBUTE *po = &outportlist[i]; 7949087SZhong.Wang@Sun.COM bcopy(pi->fpi_pwwn, &po->port_wwn, 8); 7959307Skelly.hu@Sun.COM 7969307Skelly.hu@Sun.COM if (handle == NULL || 7979307Skelly.hu@Sun.COM dladm_datalink_id2info(handle, pi->fpi_mac_linkid, 7989307Skelly.hu@Sun.COM NULL, NULL, NULL, mac_name, sizeof (mac_name)) 7999307Skelly.hu@Sun.COM != DLADM_STATUS_OK) { 8009307Skelly.hu@Sun.COM (void) strcpy((char *)po->mac_link_name, 8019307Skelly.hu@Sun.COM "<unknown>"); 8029307Skelly.hu@Sun.COM } else { 8039307Skelly.hu@Sun.COM (void) strcpy((char *)po->mac_link_name, 8049307Skelly.hu@Sun.COM mac_name); 8059307Skelly.hu@Sun.COM } 8069087SZhong.Wang@Sun.COM bcopy(pi->fpi_mac_factory_addr, 8079087SZhong.Wang@Sun.COM po->mac_factory_addr, 6); 8089087SZhong.Wang@Sun.COM bcopy(pi->fpi_mac_current_addr, 8099087SZhong.Wang@Sun.COM po->mac_current_addr, 6); 8109087SZhong.Wang@Sun.COM po->port_type = (FCOE_UINT8)pi->fpi_port_type; 8119087SZhong.Wang@Sun.COM po->mtu_size = pi->fpi_mtu_size; 8129087SZhong.Wang@Sun.COM po->mac_promisc = pi->fpi_mac_promisc; 8139087SZhong.Wang@Sun.COM } 8149307Skelly.hu@Sun.COM 8159307Skelly.hu@Sun.COM if (handle != NULL) { 8169307Skelly.hu@Sun.COM dladm_close(handle); 8179307Skelly.hu@Sun.COM } 8189087SZhong.Wang@Sun.COM *port_num = inportlist->numPorts; 8199087SZhong.Wang@Sun.COM *portlist = outportlist; 8209087SZhong.Wang@Sun.COM free(inportlist); 8219087SZhong.Wang@Sun.COM } else { 8229087SZhong.Wang@Sun.COM *port_num = 0; 8239087SZhong.Wang@Sun.COM *portlist = NULL; 8249087SZhong.Wang@Sun.COM } 8259087SZhong.Wang@Sun.COM (void) close(fcoe_fd); 8269087SZhong.Wang@Sun.COM return (status); 8279087SZhong.Wang@Sun.COM } 828*9895SKevin.Yu@Sun.COM 829*9895SKevin.Yu@Sun.COM FCOE_STATUS FCOE_LoadConfig( 830*9895SKevin.Yu@Sun.COM FCOE_UINT8 portType, 831*9895SKevin.Yu@Sun.COM FCOE_SMF_PORT_LIST **portlist) 832*9895SKevin.Yu@Sun.COM { 833*9895SKevin.Yu@Sun.COM scf_handle_t *handle = NULL; 834*9895SKevin.Yu@Sun.COM scf_service_t *svc = NULL; 835*9895SKevin.Yu@Sun.COM scf_propertygroup_t *pg = NULL; 836*9895SKevin.Yu@Sun.COM scf_transaction_t *tran = NULL; 837*9895SKevin.Yu@Sun.COM scf_transaction_entry_t *entry = NULL; 838*9895SKevin.Yu@Sun.COM scf_property_t *prop = NULL; 839*9895SKevin.Yu@Sun.COM scf_value_t *valueLookup = NULL; 840*9895SKevin.Yu@Sun.COM scf_iter_t *valueIter = NULL; 841*9895SKevin.Yu@Sun.COM char buf[FCOE_PORT_LIST_LENGTH] = {0}; 842*9895SKevin.Yu@Sun.COM int commitRet; 843*9895SKevin.Yu@Sun.COM FCOE_UINT32 portIndex; 844*9895SKevin.Yu@Sun.COM int bufsize, retry; 845*9895SKevin.Yu@Sun.COM int size = 10; /* default first attempt */ 846*9895SKevin.Yu@Sun.COM int pg_or_prop_not_found = 0; 847*9895SKevin.Yu@Sun.COM 848*9895SKevin.Yu@Sun.COM commitRet = fcoe_cfg_scf_init(&handle, &svc, portType); 849*9895SKevin.Yu@Sun.COM if (commitRet != FCOE_SUCCESS) { 850*9895SKevin.Yu@Sun.COM goto out; 851*9895SKevin.Yu@Sun.COM } 852*9895SKevin.Yu@Sun.COM 853*9895SKevin.Yu@Sun.COM if (((pg = scf_pg_create(handle)) == NULL) || 854*9895SKevin.Yu@Sun.COM ((tran = scf_transaction_create(handle)) == NULL) || 855*9895SKevin.Yu@Sun.COM ((entry = scf_entry_create(handle)) == NULL) || 856*9895SKevin.Yu@Sun.COM ((prop = scf_property_create(handle)) == NULL) || 857*9895SKevin.Yu@Sun.COM ((valueIter = scf_iter_create(handle)) == NULL)) { 858*9895SKevin.Yu@Sun.COM goto out; 859*9895SKevin.Yu@Sun.COM } 860*9895SKevin.Yu@Sun.COM 861*9895SKevin.Yu@Sun.COM if (scf_service_get_pg(svc, FCOE_PG_NAME, pg) == -1) { 862*9895SKevin.Yu@Sun.COM pg_or_prop_not_found = 1; 863*9895SKevin.Yu@Sun.COM goto out; 864*9895SKevin.Yu@Sun.COM } 865*9895SKevin.Yu@Sun.COM 866*9895SKevin.Yu@Sun.COM if (scf_pg_get_property(pg, FCOE_PORT_LIST, prop) == -1) { 867*9895SKevin.Yu@Sun.COM pg_or_prop_not_found = 1; 868*9895SKevin.Yu@Sun.COM goto out; 869*9895SKevin.Yu@Sun.COM } 870*9895SKevin.Yu@Sun.COM 871*9895SKevin.Yu@Sun.COM valueLookup = scf_value_create(handle); 872*9895SKevin.Yu@Sun.COM if (valueLookup == NULL) { 873*9895SKevin.Yu@Sun.COM syslog(LOG_ERR, "scf value alloc failed - %s", 874*9895SKevin.Yu@Sun.COM scf_strerror(scf_error())); 875*9895SKevin.Yu@Sun.COM goto out; 876*9895SKevin.Yu@Sun.COM } 877*9895SKevin.Yu@Sun.COM 878*9895SKevin.Yu@Sun.COM portIndex = 0; 879*9895SKevin.Yu@Sun.COM 880*9895SKevin.Yu@Sun.COM do { 881*9895SKevin.Yu@Sun.COM if (scf_iter_property_values(valueIter, prop) == -1) { 882*9895SKevin.Yu@Sun.COM syslog(LOG_ERR, "iter value failed - %s", 883*9895SKevin.Yu@Sun.COM scf_strerror(scf_error())); 884*9895SKevin.Yu@Sun.COM goto out; 885*9895SKevin.Yu@Sun.COM } 886*9895SKevin.Yu@Sun.COM 887*9895SKevin.Yu@Sun.COM retry = 0; 888*9895SKevin.Yu@Sun.COM bufsize = sizeof (FCOE_SMF_PORT_INSTANCE) * (size - 1) + 889*9895SKevin.Yu@Sun.COM sizeof (FCOE_SMF_PORT_LIST); 890*9895SKevin.Yu@Sun.COM *portlist = (PFCOE_SMF_PORT_LIST)malloc(bufsize); 891*9895SKevin.Yu@Sun.COM 892*9895SKevin.Yu@Sun.COM while (scf_iter_next_value(valueIter, valueLookup) == 1) { 893*9895SKevin.Yu@Sun.COM uint8_t *macLinkName = NULL; 894*9895SKevin.Yu@Sun.COM char *remainder = NULL; 895*9895SKevin.Yu@Sun.COM uint64_t nodeWWN, portWWN; 896*9895SKevin.Yu@Sun.COM int is_target, is_promiscuous; 897*9895SKevin.Yu@Sun.COM 898*9895SKevin.Yu@Sun.COM bzero(buf, sizeof (buf)); 899*9895SKevin.Yu@Sun.COM if (scf_value_get_ustring(valueLookup, buf, 900*9895SKevin.Yu@Sun.COM MAXNAMELEN) == -1) { 901*9895SKevin.Yu@Sun.COM syslog(LOG_ERR, "iter value failed - %s", 902*9895SKevin.Yu@Sun.COM scf_strerror(scf_error())); 903*9895SKevin.Yu@Sun.COM break; 904*9895SKevin.Yu@Sun.COM } 905*9895SKevin.Yu@Sun.COM macLinkName = (uint8_t *)strtok(buf, ":"); 906*9895SKevin.Yu@Sun.COM remainder = strtok(NULL, "#"); 907*9895SKevin.Yu@Sun.COM (void) sscanf(remainder, 908*9895SKevin.Yu@Sun.COM "%016" PRIx64 ":%016" PRIx64 ":%d:%d", 909*9895SKevin.Yu@Sun.COM &portWWN, &nodeWWN, &is_target, &is_promiscuous); 910*9895SKevin.Yu@Sun.COM 911*9895SKevin.Yu@Sun.COM if (portIndex >= size) { 912*9895SKevin.Yu@Sun.COM free(*portlist); 913*9895SKevin.Yu@Sun.COM retry = 1; 914*9895SKevin.Yu@Sun.COM size *= 2; 915*9895SKevin.Yu@Sun.COM break; 916*9895SKevin.Yu@Sun.COM } else { 917*9895SKevin.Yu@Sun.COM PFCOE_SMF_PORT_INSTANCE pi = 918*9895SKevin.Yu@Sun.COM &(*portlist)->ports[portIndex++]; 919*9895SKevin.Yu@Sun.COM (void) strcpy((char *)pi->mac_link_name, 920*9895SKevin.Yu@Sun.COM (char *)macLinkName); 921*9895SKevin.Yu@Sun.COM pi->port_type = is_target ? 922*9895SKevin.Yu@Sun.COM FCOE_PORTTYPE_TARGET: 923*9895SKevin.Yu@Sun.COM FCOE_PORTTYPE_INITIATOR; 924*9895SKevin.Yu@Sun.COM portWWN = htonll(portWWN); 925*9895SKevin.Yu@Sun.COM nodeWWN = htonll(nodeWWN); 926*9895SKevin.Yu@Sun.COM (void) memcpy(&pi->port_pwwn, &portWWN, 927*9895SKevin.Yu@Sun.COM sizeof (FCOE_PORT_WWN)); 928*9895SKevin.Yu@Sun.COM (void) memcpy(&pi->port_nwwn, &nodeWWN, 929*9895SKevin.Yu@Sun.COM sizeof (FCOE_PORT_WWN)); 930*9895SKevin.Yu@Sun.COM pi->mac_promisc = is_promiscuous; 931*9895SKevin.Yu@Sun.COM } 932*9895SKevin.Yu@Sun.COM } 933*9895SKevin.Yu@Sun.COM 934*9895SKevin.Yu@Sun.COM (*portlist)->port_num = portIndex; 935*9895SKevin.Yu@Sun.COM } while (retry == 1); 936*9895SKevin.Yu@Sun.COM 937*9895SKevin.Yu@Sun.COM return (FCOE_STATUS_OK); 938*9895SKevin.Yu@Sun.COM out: 939*9895SKevin.Yu@Sun.COM /* 940*9895SKevin.Yu@Sun.COM * Free resources 941*9895SKevin.Yu@Sun.COM */ 942*9895SKevin.Yu@Sun.COM if (handle != NULL) { 943*9895SKevin.Yu@Sun.COM scf_handle_destroy(handle); 944*9895SKevin.Yu@Sun.COM } 945*9895SKevin.Yu@Sun.COM if (svc != NULL) { 946*9895SKevin.Yu@Sun.COM scf_service_destroy(svc); 947*9895SKevin.Yu@Sun.COM } 948*9895SKevin.Yu@Sun.COM if (pg != NULL) { 949*9895SKevin.Yu@Sun.COM scf_pg_destroy(pg); 950*9895SKevin.Yu@Sun.COM } 951*9895SKevin.Yu@Sun.COM if (tran != NULL) { 952*9895SKevin.Yu@Sun.COM scf_transaction_destroy(tran); 953*9895SKevin.Yu@Sun.COM } 954*9895SKevin.Yu@Sun.COM if (entry != NULL) { 955*9895SKevin.Yu@Sun.COM scf_entry_destroy(entry); 956*9895SKevin.Yu@Sun.COM } 957*9895SKevin.Yu@Sun.COM if (prop != NULL) { 958*9895SKevin.Yu@Sun.COM scf_property_destroy(prop); 959*9895SKevin.Yu@Sun.COM } 960*9895SKevin.Yu@Sun.COM if (valueIter != NULL) { 961*9895SKevin.Yu@Sun.COM scf_iter_destroy(valueIter); 962*9895SKevin.Yu@Sun.COM } 963*9895SKevin.Yu@Sun.COM if (valueLookup != NULL) { 964*9895SKevin.Yu@Sun.COM scf_value_destroy(valueLookup); 965*9895SKevin.Yu@Sun.COM } 966*9895SKevin.Yu@Sun.COM 967*9895SKevin.Yu@Sun.COM if (pg_or_prop_not_found == 1) { 968*9895SKevin.Yu@Sun.COM return (FCOE_STATUS_OK); 969*9895SKevin.Yu@Sun.COM } else { 970*9895SKevin.Yu@Sun.COM return (FCOE_STATUS_ERROR); 971*9895SKevin.Yu@Sun.COM } 972*9895SKevin.Yu@Sun.COM } 973