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 2009 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 *
WWN2str(char * buf,HBA_WWN * wwn)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
isValidWWN(char * wwn)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
cfgInit(scf_handle_t ** handle,scf_service_t ** service)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
npivAddRemoveNPIVEntry(char * ppwwn,char * vnwwn,char * vpwwn,int vindex,int addRemoveFlag)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
retrieveNPIVAttrs(HBA_HANDLE handle,HBA_WWN portWWN,HBA_PORTNPIVATTRIBUTES * npivattrs,HBA_UINT32 * portIndex)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
fc_util_delete_npivport(int wwnCount,char ** wwn_argv,cmdOptions_t * options)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
fc_util_create_npivport(int wwnCount,char ** wwn_argv,cmdOptions_t * options)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
create_npivport(char * ppwwn_str,char * vnwwn_str,char * vpwwn_str,int vindex)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
fc_util_create_portlist()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
947 /* ARGSUSED */
948 int
fc_util_force_lip(int objects,char * argv[])949 fc_util_force_lip(int objects, char *argv[])
950 {
951 uint64_t hbaWWN;
952 HBA_WWN myWWN;
953 HBA_HANDLE handle;
954 HBA_STATUS status;
955 int rval = 0;
956
957 if ((status = HBA_LoadLibrary()) != HBA_STATUS_OK) {
958 fprintf(stderr, gettext("Failed to load FC-HBA library\n"));
959 printStatus(status);
960 fprintf(stderr, "\n");
961 return (1);
962 }
963
964 sscanf(argv[0], "%016llx", &hbaWWN);
965 hbaWWN = htonll(hbaWWN);
966 memcpy(myWWN.wwn, &hbaWWN, sizeof (hbaWWN));
967
968 /*
969 * Try target mode first
970 */
971 if ((status = Sun_HBA_OpenTgtAdapterByWWN(&handle, myWWN)) !=
972 HBA_STATUS_OK) {
973 /*
974 * Continue to try initiator mode
975 */
976 if ((status = HBA_OpenAdapterByWWN(&handle, myWWN)) !=
977 HBA_STATUS_OK) {
978 fprintf(stderr, gettext("Error: HBA %s not found\n"),
979 argv[0]);
980 return (0);
981 }
982 }
983
984 status = Sun_HBA_ForceLip(handle, &rval);
985 if ((status != HBA_STATUS_OK) || (rval != 0)) {
986 fprintf(stderr, gettext("Error: Failed to reinitialize the "
987 "link of HBA %s\n"), argv[0]);
988 }
989
990 return (0);
991 }
992