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 <stdlib.h>
27 #include <stdio.h>
28 #include <wchar.h>
29 #include <strings.h>
30 #include <sys/types.h>
31 #include <sys/stat.h>
32 #include <fcntl.h>
33 #include <unistd.h>
34 #include <libintl.h>
35 #include <errno.h>
36 #include <string.h>
37 #include <assert.h>
38 #include <syslog.h>
39 #include <libfcoe.h>
40 #include <libdllink.h>
41 #include <fcoeio.h>
42 #include <libscf.h>
43 #include <inttypes.h>
44
45 #define FCOE_DEV_PATH "/devices/fcoe:admin"
46
47 #define OPEN_FCOE 0
48 #define OPEN_EXCL_FCOE O_EXCL
49
50 /*
51 * Open for fcoe module
52 *
53 * flag - open flag (OPEN_FCOE, OPEN_EXCL_FCOE)
54 * fd - pointer to integer. On success, contains the fcoe file descriptor
55 */
56 static int
openFcoe(int flag,int * fd)57 openFcoe(int flag, int *fd)
58 {
59 int ret = FCOE_STATUS_ERROR;
60
61 if ((*fd = open(FCOE_DEV_PATH, O_NDELAY | O_RDONLY | flag)) != -1) {
62 ret = FCOE_STATUS_OK;
63 } else {
64 if (errno == EPERM || errno == EACCES) {
65 ret = FCOE_STATUS_ERROR_PERM;
66 } else {
67 ret = FCOE_STATUS_ERROR_OPEN_DEV;
68 }
69 syslog(LOG_DEBUG, "openFcoe:open failure:%s:errno(%d)",
70 FCOE_DEV_PATH, errno);
71 }
72
73 return (ret);
74 }
75
76 static void
WWN2str(char * buf,FCOE_PORT_WWN * wwn)77 WWN2str(char *buf, FCOE_PORT_WWN *wwn) {
78 int j;
79 unsigned char *pc = (unsigned char *)&(wwn->wwn[0]);
80 buf[0] = '\0';
81 for (j = 0; j < 16; j += 2) {
82 (void) sprintf(&buf[j], "%02X", (int)*pc++);
83 }
84 }
85
86 static int
isWWNZero(FCOE_PORT_WWN portwwn)87 isWWNZero(FCOE_PORT_WWN portwwn)
88 {
89 int i;
90 int size = sizeof (FCOE_PORT_WWN);
91
92 for (i = 0; i < size; i++) {
93 if (portwwn.wwn[i] != 0) {
94 return (0);
95 }
96 }
97 return (1);
98 }
99
100 /*
101 * Initialize scf fcoe service access
102 * handle - returned handle
103 * service - returned service handle
104 */
105 static int
fcoe_cfg_scf_init(scf_handle_t ** handle,scf_service_t ** service,int is_target)106 fcoe_cfg_scf_init(scf_handle_t **handle, scf_service_t **service, int is_target)
107 {
108 scf_scope_t *scope = NULL;
109 int ret;
110
111 if ((*handle = scf_handle_create(SCF_VERSION)) == NULL) {
112 syslog(LOG_ERR, "scf_handle_create failed - %s",
113 scf_strerror(scf_error()));
114 ret = FCOE_ERROR;
115 goto err;
116 }
117
118 if (scf_handle_bind(*handle) == -1) {
119 syslog(LOG_ERR, "scf_handle_bind failed - %s",
120 scf_strerror(scf_error()));
121 ret = FCOE_ERROR;
122 goto err;
123 }
124
125 if ((*service = scf_service_create(*handle)) == NULL) {
126 syslog(LOG_ERR, "scf_service_create failed - %s",
127 scf_strerror(scf_error()));
128 ret = FCOE_ERROR;
129 goto err;
130 }
131
132 if ((scope = scf_scope_create(*handle)) == NULL) {
133 syslog(LOG_ERR, "scf_scope_create failed - %s",
134 scf_strerror(scf_error()));
135 ret = FCOE_ERROR;
136 goto err;
137 }
138
139 if (scf_handle_get_scope(*handle, SCF_SCOPE_LOCAL, scope) == -1) {
140 syslog(LOG_ERR, "scf_handle_get_scope failed - %s",
141 scf_strerror(scf_error()));
142 ret = FCOE_ERROR;
143 goto err;
144 }
145
146 if (scf_scope_get_service(scope,
147 is_target ? FCOE_TARGET_SERVICE: FCOE_INITIATOR_SERVICE,
148 *service) == -1) {
149 syslog(LOG_ERR, "scf_scope_get_service failed - %s",
150 scf_strerror(scf_error()));
151 ret = FCOE_ERROR_SERVICE_NOT_FOUND;
152 goto err;
153 }
154
155 scf_scope_destroy(scope);
156
157 return (FCOE_SUCCESS);
158
159 err:
160 if (*handle != NULL) {
161 scf_handle_destroy(*handle);
162 }
163 if (*service != NULL) {
164 scf_service_destroy(*service);
165 *service = NULL;
166 }
167 if (scope != NULL) {
168 scf_scope_destroy(scope);
169 }
170 return (ret);
171 }
172
173 static int
fcoe_add_remove_scf_entry(char * mac_name,char * pwwn,char * nwwn,int is_target,int is_promiscuous,int addRemoveFlag)174 fcoe_add_remove_scf_entry(char *mac_name,
175 char *pwwn, char *nwwn,
176 int is_target, int is_promiscuous, int addRemoveFlag)
177 {
178 scf_handle_t *handle = NULL;
179 scf_service_t *svc = NULL;
180 scf_propertygroup_t *pg = NULL;
181 scf_transaction_t *tran = NULL;
182 scf_transaction_entry_t *entry = NULL;
183 scf_property_t *prop = NULL;
184 scf_value_t *valueLookup = NULL;
185 scf_iter_t *valueIter = NULL;
186 scf_value_t **valueSet = NULL;
187 int ret = FCOE_SUCCESS;
188 boolean_t createProp = B_FALSE;
189 int lastAlloc = 0;
190 char buf[FCOE_PORT_LIST_LENGTH] = {0};
191 char memberName[FCOE_PORT_LIST_LENGTH] = {0};
192 boolean_t found = B_FALSE;
193 int i = 0;
194 int valueArraySize = 0;
195 int commitRet;
196 int portListAlloc = 100;
197
198 (void) snprintf(memberName, FCOE_PORT_LIST_LENGTH,
199 "%s:%s:%s:%d:%d", mac_name, pwwn, nwwn,
200 is_target, is_promiscuous);
201
202 ret = fcoe_cfg_scf_init(&handle, &svc, is_target);
203 if (ret != FCOE_SUCCESS) {
204 goto out;
205 }
206
207 if (((pg = scf_pg_create(handle)) == NULL) ||
208 ((tran = scf_transaction_create(handle)) == NULL) ||
209 ((entry = scf_entry_create(handle)) == NULL) ||
210 ((prop = scf_property_create(handle)) == NULL) ||
211 ((valueIter = scf_iter_create(handle)) == NULL)) {
212 ret = FCOE_ERROR;
213 goto out;
214 }
215
216 /* get property group or create it */
217 if (scf_service_get_pg(svc, FCOE_PG_NAME, pg) == -1) {
218 if ((scf_error() == SCF_ERROR_NOT_FOUND)) {
219 if (scf_service_add_pg(svc, FCOE_PG_NAME,
220 SCF_GROUP_APPLICATION, 0, pg) == -1) {
221 syslog(LOG_ERR, "add pg failed - %s",
222 scf_strerror(scf_error()));
223 ret = FCOE_ERROR;
224 } else {
225 createProp = B_TRUE;
226 }
227 } else {
228 syslog(LOG_ERR, "get pg failed - %s",
229 scf_strerror(scf_error()));
230 ret = FCOE_ERROR;
231 }
232 if (ret != FCOE_SUCCESS) {
233 goto out;
234 }
235 }
236
237 /* to make sure property exists */
238 if (createProp == B_FALSE) {
239 if (scf_pg_get_property(pg, FCOE_PORT_LIST, prop) == -1) {
240 if ((scf_error() == SCF_ERROR_NOT_FOUND)) {
241 createProp = B_TRUE;
242 } else {
243 syslog(LOG_ERR, "get property failed - %s",
244 scf_strerror(scf_error()));
245 ret = FCOE_ERROR;
246 goto out;
247 }
248 }
249 }
250
251 /* Begin the transaction */
252 if (scf_transaction_start(tran, pg) == -1) {
253 syslog(LOG_ERR, "start transaction failed - %s",
254 scf_strerror(scf_error()));
255 ret = FCOE_ERROR;
256 goto out;
257 }
258
259 valueSet = (scf_value_t **)calloc(1, sizeof (*valueSet)
260 * (lastAlloc = portListAlloc));
261 if (valueSet == NULL) {
262 ret = FCOE_ERROR_NOMEM;
263 goto out;
264 }
265
266 if (createProp) {
267 if (scf_transaction_property_new(tran, entry, FCOE_PORT_LIST,
268 SCF_TYPE_USTRING) == -1) {
269 if (scf_error() == SCF_ERROR_EXISTS) {
270 ret = FCOE_ERROR_EXISTS;
271 } else {
272 syslog(LOG_ERR,
273 "transaction property new failed - %s",
274 scf_strerror(scf_error()));
275 ret = FCOE_ERROR;
276 }
277 goto out;
278 }
279 } else {
280 if (scf_transaction_property_change(tran, entry,
281 FCOE_PORT_LIST, SCF_TYPE_USTRING) == -1) {
282 syslog(LOG_ERR,
283 "transaction property change failed - %s",
284 scf_strerror(scf_error()));
285 ret = FCOE_ERROR;
286 goto out;
287 }
288
289 if (scf_pg_get_property(pg, FCOE_PORT_LIST, prop) == -1) {
290 syslog(LOG_ERR, "get property failed - %s",
291 scf_strerror(scf_error()));
292 ret = FCOE_ERROR;
293 goto out;
294 }
295
296 valueLookup = scf_value_create(handle);
297 if (valueLookup == NULL) {
298 syslog(LOG_ERR, "scf value alloc failed - %s",
299 scf_strerror(scf_error()));
300 ret = FCOE_ERROR;
301 goto out;
302 }
303
304 if (scf_iter_property_values(valueIter, prop) == -1) {
305 syslog(LOG_ERR, "iter value failed - %s",
306 scf_strerror(scf_error()));
307 ret = FCOE_ERROR;
308 goto out;
309 }
310
311 while (scf_iter_next_value(valueIter, valueLookup) == 1) {
312 char *macnameIter = NULL;
313 char buftmp[FCOE_PORT_LIST_LENGTH] = {0};
314
315 bzero(buf, sizeof (buf));
316 if (scf_value_get_ustring(valueLookup,
317 buf, MAXNAMELEN) == -1) {
318 syslog(LOG_ERR, "iter value failed- %s",
319 scf_strerror(scf_error()));
320 ret = FCOE_ERROR;
321 break;
322 }
323 (void) strcpy(buftmp, buf);
324 macnameIter = strtok(buftmp, ":");
325 if (strcmp(macnameIter, mac_name) == 0) {
326 if (addRemoveFlag == FCOE_SCF_ADD) {
327 ret = FCOE_ERROR_EXISTS;
328 break;
329 } else {
330 found = B_TRUE;
331 continue;
332 }
333 }
334
335 valueSet[i] = scf_value_create(handle);
336 if (valueSet[i] == NULL) {
337 syslog(LOG_ERR, "scf value alloc failed - %s",
338 scf_strerror(scf_error()));
339 ret = FCOE_ERROR;
340 break;
341 }
342
343 if (scf_value_set_ustring(valueSet[i], buf) == -1) {
344 syslog(LOG_ERR, "set value failed 1- %s",
345 scf_strerror(scf_error()));
346 ret = FCOE_ERROR;
347 break;
348 }
349
350 if (scf_entry_add_value(entry, valueSet[i]) == -1) {
351 syslog(LOG_ERR, "add value failed - %s",
352 scf_strerror(scf_error()));
353 ret = FCOE_ERROR;
354 break;
355 }
356
357 i++;
358
359 if (i >= lastAlloc) {
360 lastAlloc += portListAlloc;
361 valueSet = realloc(valueSet,
362 sizeof (*valueSet) * lastAlloc);
363 if (valueSet == NULL) {
364 ret = FCOE_ERROR;
365 break;
366 }
367 }
368 }
369 }
370
371 valueArraySize = i;
372 if (!found && (addRemoveFlag == FCOE_SCF_REMOVE)) {
373 ret = FCOE_ERROR_MEMBER_NOT_FOUND;
374 }
375 if (ret != FCOE_SUCCESS) {
376 goto out;
377 }
378
379 if (addRemoveFlag == FCOE_SCF_ADD) {
380 /*
381 * Now create the new entry
382 */
383 valueSet[i] = scf_value_create(handle);
384 if (valueSet[i] == NULL) {
385 syslog(LOG_ERR, "scf value alloc failed - %s",
386 scf_strerror(scf_error()));
387 ret = FCOE_ERROR;
388 goto out;
389 } else {
390 valueArraySize++;
391 }
392
393 /*
394 * Set the new member name
395 */
396 if (scf_value_set_ustring(valueSet[i], memberName) == -1) {
397 syslog(LOG_ERR, "set value failed 2- %s",
398 scf_strerror(scf_error()));
399 ret = FCOE_ERROR;
400 goto out;
401 }
402
403 /*
404 * Add the new member
405 */
406 if (scf_entry_add_value(entry, valueSet[i]) == -1) {
407 syslog(LOG_ERR, "add value failed - %s",
408 scf_strerror(scf_error()));
409 ret = FCOE_ERROR;
410 goto out;
411 }
412 }
413
414 if ((commitRet = scf_transaction_commit(tran)) != 1) {
415 syslog(LOG_ERR, "transaction commit failed - %s",
416 scf_strerror(scf_error()));
417 if (commitRet == 0) {
418 ret = FCOE_ERROR_BUSY;
419 } else {
420 ret = FCOE_ERROR;
421 }
422 goto out;
423 }
424
425 out:
426 /*
427 * Free resources
428 */
429 if (handle != NULL) {
430 scf_handle_destroy(handle);
431 }
432 if (svc != NULL) {
433 scf_service_destroy(svc);
434 }
435 if (pg != NULL) {
436 scf_pg_destroy(pg);
437 }
438 if (tran != NULL) {
439 scf_transaction_destroy(tran);
440 }
441 if (entry != NULL) {
442 scf_entry_destroy(entry);
443 }
444 if (prop != NULL) {
445 scf_property_destroy(prop);
446 }
447 if (valueIter != NULL) {
448 scf_iter_destroy(valueIter);
449 }
450 if (valueLookup != NULL) {
451 scf_value_destroy(valueLookup);
452 }
453
454 /*
455 * Free valueSet scf resources
456 */
457 if (valueArraySize > 0) {
458 for (i = 0; i < valueArraySize; i++) {
459 scf_value_destroy(valueSet[i]);
460 }
461 }
462 /*
463 * Now free the pointer array to the resources
464 */
465 if (valueSet != NULL) {
466 free(valueSet);
467 }
468
469 return (ret);
470 }
471
472 FCOE_STATUS
FCOE_CreatePort(const FCOE_UINT8 * macLinkName,FCOE_UINT8 portType,FCOE_PORT_WWN pwwn,FCOE_PORT_WWN nwwn,FCOE_UINT8 promiscuous)473 FCOE_CreatePort(
474 const FCOE_UINT8 *macLinkName,
475 FCOE_UINT8 portType,
476 FCOE_PORT_WWN pwwn,
477 FCOE_PORT_WWN nwwn,
478 FCOE_UINT8 promiscuous)
479 {
480 FCOE_STATUS status;
481 int fcoe_fd;
482 fcoeio_t fcoeio;
483 fcoeio_create_port_param_t param;
484 dladm_handle_t handle;
485 datalink_id_t linkid;
486 datalink_class_t class;
487
488 bzero(¶m, sizeof (fcoeio_create_port_param_t));
489
490 if (macLinkName == NULL) {
491 return (FCOE_STATUS_ERROR_INVAL_ARG);
492 }
493
494 if (strlen((char *)macLinkName) > MAXLINKNAMELEN-1) {
495 return (FCOE_STATUS_ERROR_MAC_LEN);
496 }
497
498 if (dladm_open(&handle) != DLADM_STATUS_OK) {
499 return (FCOE_STATUS_ERROR);
500 }
501
502 if (dladm_name2info(handle, (const char *)macLinkName,
503 &linkid, NULL, &class, NULL) != DLADM_STATUS_OK) {
504 dladm_close(handle);
505 (void) fcoe_add_remove_scf_entry((char *)macLinkName,
506 "",
507 "",
508 portType,
509 0,
510 FCOE_SCF_REMOVE);
511 return (FCOE_STATUS_ERROR_GET_LINKINFO);
512 }
513 dladm_close(handle);
514
515 if (class != DATALINK_CLASS_PHYS) {
516 return (FCOE_STATUS_ERROR_CLASS_UNSUPPORT);
517 }
518
519 if (portType != FCOE_PORTTYPE_INITIATOR &&
520 portType != FCOE_PORTTYPE_TARGET) {
521 return (FCOE_STATUS_ERROR_INVAL_ARG);
522 }
523
524 if (!isWWNZero(pwwn)) {
525 param.fcp_pwwn_provided = 1;
526 bcopy(pwwn.wwn, param.fcp_pwwn, 8);
527 }
528
529 if (!isWWNZero(nwwn)) {
530 param.fcp_nwwn_provided = 1;
531 bcopy(nwwn.wwn, param.fcp_nwwn, 8);
532 }
533
534 if (param.fcp_pwwn_provided == 1 &&
535 param.fcp_nwwn_provided == 1 &&
536 bcmp(&pwwn, &nwwn, 8) == 0) {
537 return (FCOE_STATUS_ERROR_WWN_SAME);
538 }
539
540 param.fcp_force_promisc = promiscuous;
541 param.fcp_mac_linkid = linkid;
542 param.fcp_port_type = (fcoe_cli_type_t)portType;
543
544 if ((status = openFcoe(OPEN_FCOE, &fcoe_fd)) != FCOE_STATUS_OK) {
545 return (status);
546 }
547
548 (void) memset(&fcoeio, 0, sizeof (fcoeio));
549 fcoeio.fcoeio_cmd = FCOEIO_CREATE_FCOE_PORT;
550
551 fcoeio.fcoeio_ilen = sizeof (param);
552 fcoeio.fcoeio_xfer = FCOEIO_XFER_WRITE;
553 fcoeio.fcoeio_ibuf = (uintptr_t)¶m;
554
555 if (ioctl(fcoe_fd, FCOEIO_CMD, &fcoeio) != 0) {
556 switch (fcoeio.fcoeio_status) {
557 case FCOEIOE_INVAL_ARG:
558 status = FCOE_STATUS_ERROR_INVAL_ARG;
559 break;
560
561 case FCOEIOE_BUSY:
562 status = FCOE_STATUS_ERROR_BUSY;
563 break;
564
565 case FCOEIOE_ALREADY:
566 status = FCOE_STATUS_ERROR_ALREADY;
567 break;
568
569 case FCOEIOE_PWWN_CONFLICTED:
570 status = FCOE_STATUS_ERROR_PWWN_CONFLICTED;
571 break;
572
573 case FCOEIOE_NWWN_CONFLICTED:
574 status = FCOE_STATUS_ERROR_NWWN_CONFLICTED;
575 break;
576
577 case FCOEIOE_CREATE_MAC:
578 status = FCOE_STATUS_ERROR_CREATE_MAC;
579 break;
580
581 case FCOEIOE_OPEN_MAC:
582 status = FCOE_STATUS_ERROR_OPEN_MAC;
583 break;
584
585 case FCOEIOE_CREATE_PORT:
586 status = FCOE_STATUS_ERROR_CREATE_PORT;
587 break;
588
589 case FCOEIOE_NEED_JUMBO_FRAME:
590 status = FCOE_STATUS_ERROR_NEED_JUMBO_FRAME;
591 break;
592
593 default:
594 status = FCOE_STATUS_ERROR;
595 }
596 } else {
597 char cpwwn[17], cnwwn[17];
598
599 WWN2str(cpwwn, &pwwn);
600 WWN2str(cnwwn, &nwwn);
601
602 (void) fcoe_add_remove_scf_entry((char *)macLinkName,
603 cpwwn,
604 cnwwn,
605 portType,
606 promiscuous,
607 FCOE_SCF_ADD);
608 status = FCOE_STATUS_OK;
609 }
610 (void) close(fcoe_fd);
611 return (status);
612 }
613
614 FCOE_STATUS
FCOE_DeletePort(const FCOE_UINT8 * macLinkName)615 FCOE_DeletePort(const FCOE_UINT8 *macLinkName)
616 {
617 FCOE_STATUS status = FCOE_STATUS_OK;
618 int fcoe_fd;
619 fcoeio_t fcoeio;
620 dladm_handle_t handle;
621 datalink_id_t linkid;
622 fcoeio_delete_port_param_t fc_del_port;
623 uint64_t is_target = 0;
624 int io_ret = 0;
625
626 if (macLinkName == NULL) {
627 return (FCOE_STATUS_ERROR_INVAL_ARG);
628 }
629
630 if (strlen((char *)macLinkName) > MAXLINKNAMELEN-1) {
631 return (FCOE_STATUS_ERROR_MAC_LEN);
632 }
633 if (dladm_open(&handle) != DLADM_STATUS_OK) {
634 return (FCOE_STATUS_ERROR);
635 }
636
637 if (dladm_name2info(handle, (const char *)macLinkName,
638 &linkid, NULL, NULL, NULL) != DLADM_STATUS_OK) {
639 dladm_close(handle);
640 return (FCOE_STATUS_ERROR_GET_LINKINFO);
641 }
642 dladm_close(handle);
643
644 if ((status = openFcoe(OPEN_FCOE, &fcoe_fd)) != FCOE_STATUS_OK) {
645 return (status);
646 }
647
648 fc_del_port.fdp_mac_linkid = linkid;
649
650 (void) memset(&fcoeio, 0, sizeof (fcoeio));
651 fcoeio.fcoeio_cmd = FCOEIO_DELETE_FCOE_PORT;
652
653 /* only 4 bytes here, need to change */
654 fcoeio.fcoeio_ilen = sizeof (fcoeio_delete_port_param_t);
655 fcoeio.fcoeio_olen = sizeof (uint64_t);
656 fcoeio.fcoeio_xfer = FCOEIO_XFER_RW;
657 fcoeio.fcoeio_ibuf = (uintptr_t)&fc_del_port;
658 fcoeio.fcoeio_obuf = (uintptr_t)&is_target;
659
660 io_ret = ioctl(fcoe_fd, FCOEIO_CMD, &fcoeio);
661 if (io_ret != 0) {
662 switch (fcoeio.fcoeio_status) {
663 case FCOEIOE_INVAL_ARG:
664 status = FCOE_STATUS_ERROR_INVAL_ARG;
665 break;
666
667 case FCOEIOE_BUSY:
668 status = FCOE_STATUS_ERROR_BUSY;
669 break;
670
671 case FCOEIOE_ALREADY:
672 status = FCOE_STATUS_ERROR_ALREADY;
673 break;
674
675 case FCOEIOE_MAC_NOT_FOUND:
676 status = FCOE_STATUS_ERROR_MAC_NOT_FOUND;
677 break;
678
679 case FCOEIOE_OFFLINE_FAILURE:
680 status = FCOE_STATUS_ERROR_OFFLINE_DEV;
681 break;
682
683 default:
684 status = FCOE_STATUS_ERROR;
685 }
686 } else {
687 (void) fcoe_add_remove_scf_entry((char *)macLinkName,
688 "",
689 "",
690 is_target,
691 0,
692 FCOE_SCF_REMOVE);
693 status = FCOE_STATUS_OK;
694 }
695
696 if (io_ret == FCOEIOE_MAC_NOT_FOUND) {
697 (void) fcoe_add_remove_scf_entry((char *)macLinkName,
698 "",
699 "",
700 0,
701 0,
702 FCOE_SCF_REMOVE);
703 (void) fcoe_add_remove_scf_entry((char *)macLinkName,
704 "",
705 "",
706 1,
707 0,
708 FCOE_SCF_REMOVE);
709 }
710 (void) close(fcoe_fd);
711 return (status);
712 }
713
714 FCOE_STATUS
FCOE_GetPortList(FCOE_UINT32 * port_num,FCOE_PORT_ATTRIBUTE ** portlist)715 FCOE_GetPortList(
716 FCOE_UINT32 *port_num,
717 FCOE_PORT_ATTRIBUTE **portlist)
718 {
719 FCOE_STATUS status = FCOE_STATUS_OK;
720 int fcoe_fd;
721 fcoeio_t fcoeio;
722 fcoe_port_list_t *inportlist = NULL;
723 FCOE_PORT_ATTRIBUTE *outportlist = NULL;
724 int i;
725 int size = 64; /* default first attempt */
726 int retry = 0;
727 int bufsize;
728 dladm_handle_t handle;
729 char mac_name[MAXLINKNAMELEN];
730
731 if (port_num == NULL || portlist == NULL) {
732 return (FCOE_STATUS_ERROR_INVAL_ARG);
733 }
734 *port_num = 0;
735
736 if ((status = openFcoe(OPEN_FCOE, &fcoe_fd)) != FCOE_STATUS_OK) {
737 return (status);
738 }
739
740 /* Get fcoe port list */
741 (void) memset(&fcoeio, 0, sizeof (fcoeio));
742 retry = 0;
743
744 do {
745 bufsize = sizeof (fcoe_port_instance_t) * (size - 1) +
746 sizeof (fcoe_port_list_t);
747 inportlist = (fcoe_port_list_t *)malloc(bufsize);
748 fcoeio.fcoeio_cmd = FCOEIO_GET_FCOE_PORT_LIST;
749 fcoeio.fcoeio_olen = bufsize;
750 fcoeio.fcoeio_xfer = FCOEIO_XFER_READ;
751 fcoeio.fcoeio_obuf = (uintptr_t)inportlist;
752
753 if (ioctl(fcoe_fd, FCOEIO_CMD, &fcoeio) != 0) {
754 if (fcoeio.fcoeio_status == FCOEIOE_MORE_DATA) {
755 size = inportlist->numPorts;
756 }
757 free(inportlist);
758 switch (fcoeio.fcoeio_status) {
759 case FCOEIOE_INVAL_ARG:
760 status = FCOE_STATUS_ERROR_INVAL_ARG;
761 (void) close(fcoe_fd);
762 return (status);
763
764 case FCOEIOE_BUSY:
765 status = FCOE_STATUS_ERROR_BUSY;
766 retry++;
767 break;
768
769 case FCOEIOE_MORE_DATA:
770 status = FCOE_STATUS_ERROR_MORE_DATA;
771 retry++;
772 default:
773 status = FCOE_STATUS_ERROR;
774 (void) close(fcoe_fd);
775 return (status);
776 }
777 } else {
778 status = FCOE_STATUS_OK;
779 break;
780 }
781 } while (retry <= 3 && status != FCOE_STATUS_OK);
782
783 if (status == FCOE_STATUS_OK && inportlist->numPorts > 0) {
784 if (dladm_open(&handle) != DLADM_STATUS_OK) {
785 handle = NULL;
786 }
787
788 outportlist = (PFCOE_PORT_ATTRIBUTE)
789 malloc(sizeof (FCOE_PORT_ATTRIBUTE) * inportlist->numPorts);
790
791 for (i = 0; i < inportlist->numPorts; i++) {
792 fcoe_port_instance_t *pi = &inportlist->ports[i];
793 FCOE_PORT_ATTRIBUTE *po = &outportlist[i];
794 bcopy(pi->fpi_pwwn, &po->port_wwn, 8);
795
796 if (handle == NULL ||
797 dladm_datalink_id2info(handle, pi->fpi_mac_linkid,
798 NULL, NULL, NULL, mac_name, sizeof (mac_name))
799 != DLADM_STATUS_OK) {
800 (void) strcpy((char *)po->mac_link_name,
801 "<unknown>");
802 } else {
803 (void) strcpy((char *)po->mac_link_name,
804 mac_name);
805 }
806 bcopy(pi->fpi_mac_factory_addr,
807 po->mac_factory_addr, 6);
808 bcopy(pi->fpi_mac_current_addr,
809 po->mac_current_addr, 6);
810 po->port_type = (FCOE_UINT8)pi->fpi_port_type;
811 po->mtu_size = pi->fpi_mtu_size;
812 po->mac_promisc = pi->fpi_mac_promisc;
813 }
814
815 if (handle != NULL) {
816 dladm_close(handle);
817 }
818 *port_num = inportlist->numPorts;
819 *portlist = outportlist;
820 free(inportlist);
821 } else {
822 *port_num = 0;
823 *portlist = NULL;
824 }
825 (void) close(fcoe_fd);
826 return (status);
827 }
828
FCOE_LoadConfig(FCOE_UINT8 portType,FCOE_SMF_PORT_LIST ** portlist)829 FCOE_STATUS FCOE_LoadConfig(
830 FCOE_UINT8 portType,
831 FCOE_SMF_PORT_LIST **portlist)
832 {
833 scf_handle_t *handle = NULL;
834 scf_service_t *svc = NULL;
835 scf_propertygroup_t *pg = NULL;
836 scf_transaction_t *tran = NULL;
837 scf_transaction_entry_t *entry = NULL;
838 scf_property_t *prop = NULL;
839 scf_value_t *valueLookup = NULL;
840 scf_iter_t *valueIter = NULL;
841 char buf[FCOE_PORT_LIST_LENGTH] = {0};
842 int commitRet;
843 FCOE_UINT32 portIndex;
844 int bufsize, retry;
845 int size = 10; /* default first attempt */
846 int pg_or_prop_not_found = 0;
847
848 commitRet = fcoe_cfg_scf_init(&handle, &svc, portType);
849 if (commitRet != FCOE_SUCCESS) {
850 goto out;
851 }
852
853 if (((pg = scf_pg_create(handle)) == NULL) ||
854 ((tran = scf_transaction_create(handle)) == NULL) ||
855 ((entry = scf_entry_create(handle)) == NULL) ||
856 ((prop = scf_property_create(handle)) == NULL) ||
857 ((valueIter = scf_iter_create(handle)) == NULL)) {
858 goto out;
859 }
860
861 if (scf_service_get_pg(svc, FCOE_PG_NAME, pg) == -1) {
862 pg_or_prop_not_found = 1;
863 goto out;
864 }
865
866 if (scf_pg_get_property(pg, FCOE_PORT_LIST, prop) == -1) {
867 pg_or_prop_not_found = 1;
868 goto out;
869 }
870
871 valueLookup = scf_value_create(handle);
872 if (valueLookup == NULL) {
873 syslog(LOG_ERR, "scf value alloc failed - %s",
874 scf_strerror(scf_error()));
875 goto out;
876 }
877
878 portIndex = 0;
879
880 do {
881 if (scf_iter_property_values(valueIter, prop) == -1) {
882 syslog(LOG_ERR, "iter value failed - %s",
883 scf_strerror(scf_error()));
884 goto out;
885 }
886
887 retry = 0;
888 bufsize = sizeof (FCOE_SMF_PORT_INSTANCE) * (size - 1) +
889 sizeof (FCOE_SMF_PORT_LIST);
890 *portlist = (PFCOE_SMF_PORT_LIST)malloc(bufsize);
891
892 while (scf_iter_next_value(valueIter, valueLookup) == 1) {
893 uint8_t *macLinkName = NULL;
894 char *remainder = NULL;
895 uint64_t nodeWWN, portWWN;
896 int is_target, is_promiscuous;
897
898 bzero(buf, sizeof (buf));
899 if (scf_value_get_ustring(valueLookup, buf,
900 MAXNAMELEN) == -1) {
901 syslog(LOG_ERR, "iter value failed - %s",
902 scf_strerror(scf_error()));
903 break;
904 }
905 macLinkName = (uint8_t *)strtok(buf, ":");
906 remainder = strtok(NULL, "#");
907 (void) sscanf(remainder,
908 "%016" PRIx64 ":%016" PRIx64 ":%d:%d",
909 &portWWN, &nodeWWN, &is_target, &is_promiscuous);
910
911 if (portIndex >= size) {
912 free(*portlist);
913 retry = 1;
914 size *= 2;
915 break;
916 } else {
917 PFCOE_SMF_PORT_INSTANCE pi =
918 &(*portlist)->ports[portIndex++];
919 (void) strcpy((char *)pi->mac_link_name,
920 (char *)macLinkName);
921 pi->port_type = is_target ?
922 FCOE_PORTTYPE_TARGET:
923 FCOE_PORTTYPE_INITIATOR;
924 portWWN = htonll(portWWN);
925 nodeWWN = htonll(nodeWWN);
926 (void) memcpy(&pi->port_pwwn, &portWWN,
927 sizeof (FCOE_PORT_WWN));
928 (void) memcpy(&pi->port_nwwn, &nodeWWN,
929 sizeof (FCOE_PORT_WWN));
930 pi->mac_promisc = is_promiscuous;
931 }
932 }
933
934 (*portlist)->port_num = portIndex;
935 } while (retry == 1);
936
937 return (FCOE_STATUS_OK);
938 out:
939 /*
940 * Free resources
941 */
942 if (handle != NULL) {
943 scf_handle_destroy(handle);
944 }
945 if (svc != NULL) {
946 scf_service_destroy(svc);
947 }
948 if (pg != NULL) {
949 scf_pg_destroy(pg);
950 }
951 if (tran != NULL) {
952 scf_transaction_destroy(tran);
953 }
954 if (entry != NULL) {
955 scf_entry_destroy(entry);
956 }
957 if (prop != NULL) {
958 scf_property_destroy(prop);
959 }
960 if (valueIter != NULL) {
961 scf_iter_destroy(valueIter);
962 }
963 if (valueLookup != NULL) {
964 scf_value_destroy(valueLookup);
965 }
966
967 if (pg_or_prop_not_found == 1) {
968 return (FCOE_STATUS_OK);
969 } else {
970 return (FCOE_STATUS_ERROR);
971 }
972 }
973