1 /* 2 * CDDL HEADER START 3 * 4 * The contents of this file are subject to the terms of the 5 * Common Development and Distribution License (the "License"). 6 * You may not use this file except in compliance with the License. 7 * 8 * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE 9 * or http://www.opensolaris.org/os/licensing. 10 * See the License for the specific language governing permissions 11 * and limitations under the License. 12 * 13 * When distributing Covered Code, include this CDDL HEADER in each 14 * file and include the License file at usr/src/OPENSOLARIS.LICENSE. 15 * If applicable, add the following below this CDDL HEADER, with the 16 * fields enclosed by brackets "[]" replaced with your own identifying 17 * information: Portions Copyright [yyyy] [name of copyright owner] 18 * 19 * CDDL HEADER END 20 */ 21 /* 22 * Copyright 2008 Sun Microsystems, Inc. All rights reserved. 23 * Use is subject to license terms. 24 */ 25 26 #include <libscf.h> 27 #include <stdio.h> 28 #include <stdlib.h> 29 #include <errno.h> 30 #include <syslog.h> 31 #include <strings.h> 32 #include <ctype.h> 33 #include <fcinfo.h> 34 35 36 #define FCADM_RETRY_TIMES 10 37 #define FCADM_SLEEP_TIME 1 38 39 static char * 40 WWN2str(char *buf, HBA_WWN *wwn) { 41 int j; 42 unsigned char *pc = (unsigned char *)&(wwn->wwn[0]); 43 buf[0] = '\0'; 44 for (j = 0; j < 16; j += 2) { 45 sprintf(&buf[j], "%02X", (int)*pc++); 46 } 47 return (buf); 48 } 49 50 static int 51 isValidWWN(char *wwn) 52 { 53 int index; 54 55 if (wwn == NULL) { 56 return (0); 57 } 58 59 if (strlen(wwn) != 16) { 60 return (0); 61 } 62 63 for (index = 0; index < 16; index++) { 64 if (isxdigit(wwn[index])) { 65 continue; 66 } 67 return (0); 68 } 69 return (1); 70 } 71 72 73 /* 74 * Initialize scf stmf service access 75 * handle - returned handle 76 * service - returned service handle 77 */ 78 static int 79 cfgInit(scf_handle_t **handle, scf_service_t **service) 80 { 81 scf_scope_t *scope = NULL; 82 int ret; 83 84 if ((*handle = scf_handle_create(SCF_VERSION)) == NULL) { 85 /* log error */ 86 ret = NPIV_ERROR; 87 goto err; 88 } 89 90 if (scf_handle_bind(*handle) == -1) { 91 /* log error */ 92 ret = NPIV_ERROR; 93 goto err; 94 } 95 96 if ((*service = scf_service_create(*handle)) == NULL) { 97 /* log error */ 98 ret = NPIV_ERROR; 99 goto err; 100 } 101 102 if ((scope = scf_scope_create(*handle)) == NULL) { 103 /* log error */ 104 ret = NPIV_ERROR; 105 goto err; 106 } 107 108 if (scf_handle_get_scope(*handle, SCF_SCOPE_LOCAL, scope) == -1) { 109 /* log error */ 110 ret = NPIV_ERROR; 111 goto err; 112 } 113 114 if (scf_scope_get_service(scope, NPIV_SERVICE, *service) == -1) { 115 /* log error */ 116 ret = NPIV_ERROR_SERVICE_NOT_FOUND; 117 goto err; 118 } 119 120 scf_scope_destroy(scope); 121 122 return (NPIV_SUCCESS); 123 124 err: 125 if (*handle != NULL) { 126 scf_handle_destroy(*handle); 127 } 128 if (*service != NULL) { 129 scf_service_destroy(*service); 130 *service = NULL; 131 } 132 if (scope != NULL) { 133 scf_scope_destroy(scope); 134 } 135 return (ret); 136 } 137 138 static int 139 npivAddRemoveNPIVEntry(char *ppwwn, char *vnwwn, 140 char *vpwwn, int vindex, int addRemoveFlag) { 141 scf_handle_t *handle = NULL; 142 scf_service_t *svc = NULL; 143 scf_propertygroup_t *pg = NULL; 144 scf_transaction_t *tran = NULL; 145 scf_transaction_entry_t *entry = NULL; 146 scf_property_t *prop = NULL; 147 scf_value_t *valueLookup = NULL; 148 scf_iter_t *valueIter = NULL; 149 scf_value_t **valueSet = NULL; 150 int ret = NPIV_SUCCESS; 151 boolean_t createProp = B_FALSE; 152 int lastAlloc = 0; 153 char buf[NPIV_PORT_LIST_LENGTH] = {0}; 154 char memberName[NPIV_PORT_LIST_LENGTH] = {0}; 155 boolean_t found = B_FALSE; 156 int i = 0; 157 int valueArraySize = 0; 158 int commitRet; 159 160 if (vnwwn) { 161 sprintf(memberName, "%s:%s:%s:%d", ppwwn, vpwwn, vnwwn, vindex); 162 } else { 163 sprintf(memberName, "%s:%s", ppwwn, vpwwn); 164 } 165 166 ret = cfgInit(&handle, &svc); 167 if (ret != NPIV_SUCCESS) { 168 goto out; 169 } 170 171 if (((pg = scf_pg_create(handle)) == NULL) || 172 ((tran = scf_transaction_create(handle)) == NULL) || 173 ((entry = scf_entry_create(handle)) == NULL) || 174 ((prop = scf_property_create(handle)) == NULL) || 175 ((valueIter = scf_iter_create(handle)) == NULL)) { 176 ret = NPIV_ERROR; 177 goto out; 178 } 179 180 /* get property group or create it */ 181 if (scf_service_get_pg(svc, NPIV_PG_NAME, pg) == -1) { 182 if ((scf_error() == SCF_ERROR_NOT_FOUND) && 183 (addRemoveFlag == NPIV_ADD)) { 184 if (scf_service_add_pg(svc, NPIV_PG_NAME, 185 SCF_GROUP_APPLICATION, 0, pg) == -1) { 186 syslog(LOG_ERR, "add pg failed - %s", 187 scf_strerror(scf_error())); 188 ret = NPIV_ERROR; 189 } else { 190 createProp = B_TRUE; 191 } 192 } else if (scf_error() == SCF_ERROR_NOT_FOUND) { 193 ret = NPIV_ERROR_NOT_FOUND; 194 } else { 195 syslog(LOG_ERR, "get pg failed - %s", 196 scf_strerror(scf_error())); 197 ret = NPIV_ERROR; 198 } 199 if (ret != NPIV_SUCCESS) { 200 goto out; 201 } 202 } 203 204 /* Begin the transaction */ 205 if (scf_transaction_start(tran, pg) == -1) { 206 syslog(LOG_ERR, "start transaction failed - %s", 207 scf_strerror(scf_error())); 208 ret = NPIV_ERROR; 209 goto out; 210 } 211 212 valueSet = (scf_value_t **)calloc(1, sizeof (*valueSet) 213 * (lastAlloc = PORT_LIST_ALLOC)); 214 if (valueSet == NULL) { 215 ret = NPIV_ERROR_NOMEM; 216 goto out; 217 } 218 219 if (createProp) { 220 if (scf_transaction_property_new(tran, entry, NPIV_PORT_LIST, 221 SCF_TYPE_USTRING) == -1) { 222 if (scf_error() == SCF_ERROR_EXISTS) { 223 ret = NPIV_ERROR_EXISTS; 224 } else { 225 syslog(LOG_ERR, 226 "transaction property new failed - %s", 227 scf_strerror(scf_error())); 228 ret = NPIV_ERROR; 229 } 230 goto out; 231 } 232 } else { 233 if (scf_transaction_property_change(tran, entry, 234 NPIV_PORT_LIST, SCF_TYPE_USTRING) == -1) { 235 syslog(LOG_ERR, 236 "transaction property change failed - %s", 237 scf_strerror(scf_error())); 238 ret = NPIV_ERROR; 239 goto out; 240 } 241 242 if (scf_pg_get_property(pg, NPIV_PORT_LIST, prop) == -1) { 243 syslog(LOG_ERR, "get property failed - %s", 244 scf_strerror(scf_error())); 245 ret = NPIV_ERROR; 246 goto out; 247 } 248 249 valueLookup = scf_value_create(handle); 250 if (valueLookup == NULL) { 251 syslog(LOG_ERR, "scf value alloc failed - %s", 252 scf_strerror(scf_error())); 253 ret = NPIV_ERROR; 254 goto out; 255 } 256 257 if (scf_iter_property_values(valueIter, prop) == -1) { 258 syslog(LOG_ERR, "iter value failed - %s", 259 scf_strerror(scf_error())); 260 ret = NPIV_ERROR; 261 goto out; 262 } 263 264 while (scf_iter_next_value(valueIter, valueLookup) == 1) { 265 bzero(buf, sizeof (buf)); 266 if (scf_value_get_ustring(valueLookup, 267 buf, MAXNAMELEN) == -1) { 268 syslog(LOG_ERR, "iter value failed - %s", 269 scf_strerror(scf_error())); 270 ret = NPIV_ERROR; 271 break; 272 } 273 274 if ((strlen(buf) >= strlen(memberName)) && 275 bcmp(buf, memberName, strlen(memberName)) == 0) { 276 if (addRemoveFlag == NPIV_ADD) { 277 ret = NPIV_ERROR_EXISTS; 278 break; 279 } else { 280 found = B_TRUE; 281 continue; 282 } 283 } 284 285 valueSet[i] = scf_value_create(handle); 286 if (valueSet[i] == NULL) { 287 syslog(LOG_ERR, "scf value alloc failed - %s", 288 scf_strerror(scf_error())); 289 ret = NPIV_ERROR; 290 break; 291 } 292 293 if (scf_value_set_ustring(valueSet[i], buf) == -1) { 294 syslog(LOG_ERR, "set value failed - %s", 295 scf_strerror(scf_error())); 296 ret = NPIV_ERROR; 297 break; 298 } 299 300 if (scf_entry_add_value(entry, valueSet[i]) == -1) { 301 syslog(LOG_ERR, "add value failed - %s", 302 scf_strerror(scf_error())); 303 ret = NPIV_ERROR; 304 break; 305 } 306 307 i++; 308 309 if (i >= lastAlloc) { 310 lastAlloc += PORT_LIST_ALLOC; 311 valueSet = realloc(valueSet, 312 sizeof (*valueSet) * lastAlloc); 313 if (valueSet == NULL) { 314 ret = NPIV_ERROR; 315 break; 316 } 317 } 318 } 319 } 320 321 valueArraySize = i; 322 if (!found && (addRemoveFlag == NPIV_REMOVE)) { 323 ret = NPIV_ERROR_MEMBER_NOT_FOUND; 324 } 325 if (ret != NPIV_SUCCESS) { 326 goto out; 327 } 328 329 if (addRemoveFlag == NPIV_ADD) { 330 /* 331 * Now create the new entry 332 */ 333 valueSet[i] = scf_value_create(handle); 334 if (valueSet[i] == NULL) { 335 syslog(LOG_ERR, "scf value alloc failed - %s", 336 scf_strerror(scf_error())); 337 ret = NPIV_ERROR; 338 goto out; 339 } else { 340 valueArraySize++; 341 } 342 343 /* 344 * Set the new member name 345 */ 346 if (scf_value_set_ustring(valueSet[i], memberName) == -1) { 347 syslog(LOG_ERR, "set value failed - %s", 348 scf_strerror(scf_error())); 349 ret = NPIV_ERROR; 350 goto out; 351 } 352 353 /* 354 * Add the new member 355 */ 356 if (scf_entry_add_value(entry, valueSet[i]) == -1) { 357 syslog(LOG_ERR, "add value failed - %s", 358 scf_strerror(scf_error())); 359 ret = NPIV_ERROR; 360 goto out; 361 } 362 } 363 364 if ((commitRet = scf_transaction_commit(tran)) != 1) { 365 syslog(LOG_ERR, "transaction commit failed - %s", 366 scf_strerror(scf_error())); 367 if (commitRet == 0) { 368 ret = NPIV_ERROR_BUSY; 369 } else { 370 ret = NPIV_ERROR; 371 } 372 goto out; 373 } 374 375 out: 376 /* 377 * Free resources 378 */ 379 if (handle != NULL) { 380 scf_handle_destroy(handle); 381 } 382 if (svc != NULL) { 383 scf_service_destroy(svc); 384 } 385 if (pg != NULL) { 386 scf_pg_destroy(pg); 387 } 388 if (tran != NULL) { 389 scf_transaction_destroy(tran); 390 } 391 if (entry != NULL) { 392 scf_entry_destroy(entry); 393 } 394 if (prop != NULL) { 395 scf_property_destroy(prop); 396 } 397 if (valueIter != NULL) { 398 scf_iter_destroy(valueIter); 399 } 400 if (valueLookup != NULL) { 401 scf_value_destroy(valueLookup); 402 } 403 404 /* 405 * Free valueSet scf resources 406 */ 407 if (valueArraySize > 0) { 408 for (i = 0; i < valueArraySize; i++) { 409 scf_value_destroy(valueSet[i]); 410 } 411 } 412 /* 413 * Now free the pointer array to the resources 414 */ 415 if (valueSet != NULL) { 416 free(valueSet); 417 } 418 419 return (ret); 420 } 421 422 static int 423 retrieveNPIVAttrs(HBA_HANDLE handle, HBA_WWN portWWN, 424 HBA_PORTNPIVATTRIBUTES *npivattrs, HBA_UINT32 *portIndex) { 425 HBA_STATUS status; 426 HBA_ADAPTERATTRIBUTES attrs; 427 HBA_PORTATTRIBUTES portattrs; 428 int portCtr; 429 int times = 0; 430 431 /* argument checking */ 432 if (npivattrs == NULL || portIndex == NULL) { 433 return (1); 434 } 435 436 memset(&attrs, 0, sizeof (HBA_ADAPTERATTRIBUTES)); 437 status = HBA_GetAdapterAttributes(handle, &attrs); 438 while ((status == HBA_STATUS_ERROR_TRY_AGAIN || 439 status == HBA_STATUS_ERROR_BUSY) && 440 times++ < 130) { 441 status = HBA_GetAdapterAttributes(handle, &attrs); 442 if (status == HBA_STATUS_OK) { 443 break; 444 } 445 (void) sleep(1); 446 } 447 if (status != HBA_STATUS_OK) { 448 return (1); 449 } 450 451 memset(&portattrs, 0, sizeof (HBA_PORTATTRIBUTES)); 452 for (portCtr = 0; portCtr < attrs.NumberOfPorts; portCtr++) { 453 status = HBA_GetAdapterPortAttributes(handle, 454 portCtr, &portattrs); 455 times = 0; 456 while ((status == HBA_STATUS_ERROR_TRY_AGAIN || 457 status == HBA_STATUS_ERROR_BUSY) && 458 times++ < HBA_MAX_RETRIES) { 459 status = HBA_GetAdapterPortAttributes(handle, 460 portCtr, &portattrs); 461 if (status == HBA_STATUS_OK) { 462 break; 463 } 464 (void) sleep(1); 465 } 466 467 if (status != HBA_STATUS_OK) { 468 return (1); 469 } 470 471 if (memcmp(portWWN.wwn, portattrs.PortWWN.wwn, 472 sizeof (portattrs.PortWWN.wwn)) == 0) { 473 break; 474 } 475 } 476 if (portCtr >= attrs.NumberOfPorts) { 477 *portIndex = 0; 478 return (1); 479 } 480 *portIndex = portCtr; 481 482 status = Sun_HBA_GetPortNPIVAttributes(handle, portCtr, npivattrs); 483 times = 0; 484 while ((status == HBA_STATUS_ERROR_TRY_AGAIN || 485 status == HBA_STATUS_ERROR_BUSY) && 486 times++ < HBA_MAX_RETRIES) { 487 status = Sun_HBA_GetPortNPIVAttributes(handle, 488 portCtr, npivattrs); 489 if (status == HBA_STATUS_OK) { 490 break; 491 } 492 (void) sleep(1); 493 } 494 if (status != HBA_STATUS_OK) { 495 return (1); 496 } 497 498 return (0); 499 } 500 501 502 int 503 fc_util_delete_npivport(int wwnCount, char **wwn_argv, 504 cmdOptions_t *options) 505 { 506 uint64_t physicalportWWN, virtualportWWN; 507 HBA_WWN portWWN, vportWWN; 508 HBA_STATUS status; 509 HBA_HANDLE handle; 510 HBA_PORTNPIVATTRIBUTES npivattrs; 511 HBA_UINT32 portIndex; 512 char pwwn[17]; 513 int times; 514 515 if (wwnCount != 1) { 516 fprintf(stderr, 517 gettext("Invalid Parameter\n")); 518 return (1); 519 } 520 521 for (; options->optval; options++) { 522 switch (options->optval) { 523 case 'p': 524 if (!isValidWWN(options->optarg)) { 525 fprintf(stderr, 526 gettext("Invalid Port WWN\n")); 527 return (1); 528 } 529 sscanf(options->optarg, "%016llx", &virtualportWWN); 530 break; 531 default: 532 return (1); 533 } 534 } 535 536 if (!isValidWWN(wwn_argv[0])) { 537 fprintf(stderr, 538 gettext("Invalid Physical Port WWN\n")); 539 return (1); 540 } 541 542 if ((status = HBA_LoadLibrary()) != HBA_STATUS_OK) { 543 fprintf(stderr, 544 gettext("Failed to load FC-HBA common library\n")); 545 printStatus(status); 546 fprintf(stderr, "\n"); 547 return (1); 548 } 549 sscanf(wwn_argv[0], "%016llx", &physicalportWWN); 550 physicalportWWN = htonll(physicalportWWN); 551 memcpy(portWWN.wwn, &physicalportWWN, sizeof (physicalportWWN)); 552 553 virtualportWWN = htonll(virtualportWWN); 554 memcpy(vportWWN.wwn, &virtualportWWN, sizeof (virtualportWWN)); 555 556 status = HBA_OpenAdapterByWWN(&handle, portWWN); 557 if (status != HBA_STATUS_OK) { 558 fprintf(stderr, 559 gettext("Error: HBA port %s: not found\n"), 560 wwn_argv[0]); 561 HBA_FreeLibrary(); 562 return (1); 563 } 564 565 /* Get physical port NPIV attributes */ 566 if (retrieveNPIVAttrs(handle, portWWN, &npivattrs, &portIndex) == 0) { 567 /* Check port NPIV attributes */ 568 if (npivattrs.MaxNumberOfNPIVPorts == 0) { 569 fprintf(stderr, 570 gettext("Error: NPIV not Supported\n")); 571 HBA_CloseAdapter(handle); 572 HBA_FreeLibrary(); 573 return (1); 574 } 575 576 /* Delete a virtual port */ 577 status = Sun_HBA_DeleteNPIVPort(handle, portIndex, 578 vportWWN); 579 times = 0; 580 while ((status == HBA_STATUS_ERROR_TRY_AGAIN || 581 status == HBA_STATUS_ERROR_BUSY) && 582 times++ < HBA_MAX_RETRIES) { 583 (void) sleep(1); 584 status = Sun_HBA_DeleteNPIVPort(handle, portIndex, 585 vportWWN); 586 if (status == HBA_STATUS_OK) { 587 break; 588 } 589 } 590 if (status != HBA_STATUS_OK) { 591 fprintf(stderr, 592 gettext("Error: failed to delete a npiv port\n")); 593 HBA_CloseAdapter(handle); 594 HBA_FreeLibrary(); 595 return (1); 596 } 597 } else { 598 fprintf(stderr, 599 gettext("Error: failed to get port NPIV attributes\n")); 600 HBA_CloseAdapter(handle); 601 HBA_FreeLibrary(); 602 return (1); 603 } 604 605 HBA_CloseAdapter(handle); 606 HBA_FreeLibrary(); 607 608 WWN2str(pwwn, &vportWWN); 609 npivAddRemoveNPIVEntry(wwn_argv[0], 610 NULL, pwwn, 0, NPIV_REMOVE); 611 612 return (0); 613 } 614 615 int 616 fc_util_create_npivport(int wwnCount, 617 char **wwn_argv, cmdOptions_t *options) 618 { 619 uint64_t physicalportWWN, virtualnodeWWN, virtualportWWN; 620 HBA_WWN portWWN, vnodeWWN, vportWWN; 621 HBA_STATUS status; 622 HBA_HANDLE handle; 623 HBA_PORTNPIVATTRIBUTES npivattrs; 624 HBA_UINT32 portIndex; 625 HBA_UINT32 npivportIndex = 0; 626 char nwwn[17], pwwn[17]; 627 int randomflag = 0; 628 int times; 629 630 if (wwnCount != 1) { 631 fprintf(stderr, 632 gettext("Invalid Parameter\n")); 633 return (1); 634 } 635 636 for (; options->optval; options++) { 637 switch (options->optval) { 638 case 'p': 639 if (!isValidWWN(options->optarg)) { 640 fprintf(stderr, 641 gettext("Invalid Port WWN\n")); 642 return (1); 643 } 644 sscanf(options->optarg, "%016llx", &virtualportWWN); 645 randomflag++; 646 break; 647 case 'n': 648 if (!isValidWWN(options->optarg)) { 649 fprintf(stderr, 650 gettext("Invalid Node WWN\n")); 651 return (1); 652 } 653 sscanf(options->optarg, "%016llx", &virtualnodeWWN); 654 randomflag++; 655 break; 656 default: 657 return (1); 658 } 659 } 660 661 if (!isValidWWN(wwn_argv[0])) { 662 fprintf(stderr, 663 gettext("Invalid Physical Port WWN\n")); 664 wwnCount = 0; 665 return (1); 666 } 667 668 if ((status = HBA_LoadLibrary()) != HBA_STATUS_OK) { 669 fprintf(stderr, 670 gettext("Failed to load FC-HBA common library\n")); 671 printStatus(status); 672 fprintf(stderr, "\n"); 673 return (1); 674 } 675 676 sscanf(wwn_argv[0], "%016llx", &physicalportWWN); 677 physicalportWWN = htonll(physicalportWWN); 678 memcpy(portWWN.wwn, &physicalportWWN, sizeof (physicalportWWN)); 679 680 status = HBA_OpenAdapterByWWN(&handle, portWWN); 681 if (status != HBA_STATUS_OK) { 682 fprintf(stderr, 683 gettext("Error: HBA port %s: not found\n"), 684 wwn_argv[0]); 685 HBA_FreeLibrary(); 686 return (1); 687 } 688 689 if (randomflag != 2) { 690 status = Sun_HBA_AdapterCreateWWN(handle, 0, 691 &vnodeWWN, &vportWWN, NULL, HBA_CREATE_WWN_RANDOM); 692 if (status != HBA_STATUS_OK) { 693 fprintf(stderr, 694 gettext("Error: Fail to get Random WWN\n")); 695 HBA_CloseAdapter(handle); 696 HBA_FreeLibrary(); 697 return (1); 698 } 699 } else { 700 virtualnodeWWN = htonll(virtualnodeWWN); 701 memcpy(vnodeWWN.wwn, &virtualnodeWWN, sizeof (virtualnodeWWN)); 702 virtualportWWN = htonll(virtualportWWN); 703 memcpy(vportWWN.wwn, &virtualportWWN, sizeof (virtualportWWN)); 704 } 705 706 if (memcmp(vnodeWWN.wwn, vportWWN.wwn, 8) == 0) { 707 fprintf(stderr, 708 gettext("Error: Port WWN is same as Node WWN\n")); 709 HBA_CloseAdapter(handle); 710 HBA_FreeLibrary(); 711 return (1); 712 } 713 714 /* Get physical port NPIV attributes */ 715 if (retrieveNPIVAttrs(handle, portWWN, &npivattrs, &portIndex) == 0) { 716 /* Check port NPIV attributes */ 717 if (npivattrs.MaxNumberOfNPIVPorts == 0) { 718 fprintf(stderr, 719 gettext("Error: NPIV not Supported\n")); 720 HBA_CloseAdapter(handle); 721 HBA_FreeLibrary(); 722 return (1); 723 } 724 if (npivattrs.MaxNumberOfNPIVPorts == 725 npivattrs.NumberOfNPIVPorts) { 726 fprintf(stderr, 727 gettext("Error: Can not create more NPIV port\n")); 728 HBA_CloseAdapter(handle); 729 HBA_FreeLibrary(); 730 return (1); 731 } 732 733 /* Create a virtual port */ 734 status = Sun_HBA_CreateNPIVPort(handle, portIndex, 735 vnodeWWN, vportWWN, &npivportIndex); 736 times = 0; 737 while ((status == HBA_STATUS_ERROR_TRY_AGAIN || 738 status == HBA_STATUS_ERROR_BUSY) && 739 times++ < HBA_MAX_RETRIES) { 740 (void) sleep(1); 741 status = Sun_HBA_CreateNPIVPort(handle, portIndex, 742 vnodeWWN, vportWWN, &npivportIndex); 743 if (status == HBA_STATUS_OK) { 744 break; 745 } 746 } 747 748 if (status != HBA_STATUS_OK) { 749 fprintf(stderr, 750 gettext("Error: failed to create a npiv port\n")); 751 HBA_CloseAdapter(handle); 752 HBA_FreeLibrary(); 753 return (1); 754 } 755 } else { 756 fprintf(stderr, 757 gettext("Error: failed to get port NPIV attributes\n")); 758 HBA_CloseAdapter(handle); 759 HBA_FreeLibrary(); 760 return (1); 761 } 762 763 HBA_CloseAdapter(handle); 764 HBA_FreeLibrary(); 765 766 WWN2str(nwwn, &vnodeWWN); 767 WWN2str(pwwn, &vportWWN); 768 npivAddRemoveNPIVEntry(wwn_argv[0], 769 nwwn, pwwn, npivportIndex, NPIV_ADD); 770 771 return (0); 772 } 773 774 int 775 create_npivport(char *ppwwn_str, char *vnwwn_str, 776 char *vpwwn_str, int vindex) 777 { 778 uint64_t physicalportWWN, virtualnodeWWN, virtualportWWN; 779 HBA_WWN portWWN, vnodeWWN, vportWWN; 780 HBA_STATUS status; 781 HBA_HANDLE handle; 782 HBA_PORTNPIVATTRIBUTES npivattrs; 783 HBA_UINT32 portIndex; 784 HBA_UINT32 npivportIndex; 785 int times = 0; 786 787 sscanf(ppwwn_str, "%016llx", &physicalportWWN); 788 physicalportWWN = htonll(physicalportWWN); 789 memcpy(portWWN.wwn, &physicalportWWN, sizeof (physicalportWWN)); 790 sscanf(vnwwn_str, "%016llx", &virtualnodeWWN); 791 virtualnodeWWN = htonll(virtualnodeWWN); 792 memcpy(vnodeWWN.wwn, &virtualnodeWWN, sizeof (virtualnodeWWN)); 793 sscanf(vpwwn_str, "%016llx", &virtualportWWN); 794 virtualportWWN = htonll(virtualportWWN); 795 memcpy(vportWWN.wwn, &virtualportWWN, sizeof (virtualportWWN)); 796 npivportIndex = vindex; 797 798 status = HBA_OpenAdapterByWWN(&handle, portWWN); 799 while (status == HBA_STATUS_ERROR_TRY_AGAIN || 800 status == HBA_STATUS_ERROR_BUSY) { 801 (void) sleep(FCADM_SLEEP_TIME); 802 status = HBA_OpenAdapterByWWN(&handle, portWWN); 803 if (times++ > FCADM_RETRY_TIMES) { 804 return (1); 805 } 806 } 807 808 /* Get physical port NPIV attributes */ 809 if (retrieveNPIVAttrs(handle, portWWN, 810 &npivattrs, &portIndex) == 0) { 811 /* Check port NPIV attributes */ 812 if (npivattrs.MaxNumberOfNPIVPorts == 0) { 813 goto failed; 814 } 815 if (npivattrs.MaxNumberOfNPIVPorts == 816 npivattrs.NumberOfNPIVPorts) { 817 goto failed; 818 } 819 820 /* Create a virtual port */ 821 status = Sun_HBA_CreateNPIVPort(handle, portIndex, 822 vnodeWWN, vportWWN, &npivportIndex); 823 times = 0; 824 while (status == HBA_STATUS_ERROR_TRY_AGAIN || 825 status == HBA_STATUS_ERROR_BUSY) { 826 (void) sleep(FCADM_SLEEP_TIME); 827 status = Sun_HBA_CreateNPIVPort(handle, portIndex, 828 vnodeWWN, vportWWN, &npivportIndex); 829 if (times++ > FCADM_RETRY_TIMES) { 830 goto failed; 831 } 832 } 833 } 834 835 failed: 836 HBA_CloseAdapter(handle); 837 838 return (0); 839 } 840 841 int 842 fc_util_create_portlist() 843 { 844 scf_handle_t *handle = NULL; 845 scf_service_t *svc = NULL; 846 scf_propertygroup_t *pg = NULL; 847 scf_transaction_t *tran = NULL; 848 scf_transaction_entry_t *entry = NULL; 849 scf_property_t *prop = NULL; 850 scf_value_t *valueLookup = NULL; 851 scf_iter_t *valueIter = NULL; 852 char buf[NPIV_PORT_LIST_LENGTH] = {0}; 853 int commitRet; 854 855 commitRet = cfgInit(&handle, &svc); 856 if (commitRet != NPIV_SUCCESS) { 857 goto out; 858 } 859 860 if (((pg = scf_pg_create(handle)) == NULL) || 861 ((tran = scf_transaction_create(handle)) == NULL) || 862 ((entry = scf_entry_create(handle)) == NULL) || 863 ((prop = scf_property_create(handle)) == NULL) || 864 ((valueIter = scf_iter_create(handle)) == NULL)) { 865 goto out; 866 } 867 868 /* get property group or create it */ 869 if (scf_service_get_pg(svc, NPIV_PG_NAME, pg) == -1) { 870 goto out; 871 } 872 873 if (scf_pg_get_property(pg, NPIV_PORT_LIST, prop) == -1) { 874 syslog(LOG_ERR, "get property failed - %s", 875 scf_strerror(scf_error())); 876 goto out; 877 } 878 879 valueLookup = scf_value_create(handle); 880 if (valueLookup == NULL) { 881 syslog(LOG_ERR, "scf value alloc failed - %s", 882 scf_strerror(scf_error())); 883 goto out; 884 } 885 886 if (scf_iter_property_values(valueIter, prop) == -1) { 887 syslog(LOG_ERR, "iter value failed - %s", 888 scf_strerror(scf_error())); 889 goto out; 890 } 891 892 if (HBA_LoadLibrary() != HBA_STATUS_OK) { 893 goto out; 894 } 895 HBA_GetNumberOfAdapters(); 896 897 while (scf_iter_next_value(valueIter, valueLookup) == 1) { 898 char ppwwn[17] = {0}; 899 char vnwwn[17] = {0}; 900 char vpwwn[17] = {0}; 901 int vindex = 0; 902 903 bzero(buf, sizeof (buf)); 904 if (scf_value_get_ustring(valueLookup, buf, MAXNAMELEN) == -1) { 905 syslog(LOG_ERR, "iter value failed - %s", 906 scf_strerror(scf_error())); 907 break; 908 } 909 910 sscanf(buf, "%16s:%16s:%16s:%d", ppwwn, vpwwn, vnwwn, &vindex); 911 create_npivport(ppwwn, vnwwn, vpwwn, vindex); 912 } 913 914 HBA_FreeLibrary(); 915 out: 916 /* 917 * Free resources 918 */ 919 if (handle != NULL) { 920 scf_handle_destroy(handle); 921 } 922 if (svc != NULL) { 923 scf_service_destroy(svc); 924 } 925 if (pg != NULL) { 926 scf_pg_destroy(pg); 927 } 928 if (tran != NULL) { 929 scf_transaction_destroy(tran); 930 } 931 if (entry != NULL) { 932 scf_entry_destroy(entry); 933 } 934 if (prop != NULL) { 935 scf_property_destroy(prop); 936 } 937 if (valueIter != NULL) { 938 scf_iter_destroy(valueIter); 939 } 940 if (valueLookup != NULL) { 941 scf_value_destroy(valueLookup); 942 } 943 944 return (0); 945 } 946