xref: /titanic_52/usr/src/lib/libfcoe/common/libfcoe.c (revision e6eb57e72471348376359efe9105d50bf487a312)
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
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
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
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
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
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
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(&param, 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)&param;
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
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
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 
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