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