xref: /titanic_51/usr/src/lib/libfcoe/common/libfcoe.c (revision d4401b99a36e5170ccaa7defc0d2ac65b23f08c6)
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>
40*d4401b99SKelly Hu #include <libdllink.h>
412a8164dfSZhong Wang #include <fcoeio.h>
422a8164dfSZhong Wang 
432a8164dfSZhong Wang #define	FCOE_DEV_PATH	 "/devices/fcoe:admin"
442a8164dfSZhong Wang 
452a8164dfSZhong Wang #define	OPEN_FCOE 0
462a8164dfSZhong Wang #define	OPEN_EXCL_FCOE O_EXCL
472a8164dfSZhong Wang 
482a8164dfSZhong Wang /*
492a8164dfSZhong Wang  * Open for fcoe module
502a8164dfSZhong Wang  *
512a8164dfSZhong Wang  * flag - open flag (OPEN_FCOE, OPEN_EXCL_FCOE)
522a8164dfSZhong Wang  * fd - pointer to integer. On success, contains the fcoe file descriptor
532a8164dfSZhong Wang  */
542a8164dfSZhong Wang static int
552a8164dfSZhong Wang openFcoe(int flag, int *fd)
562a8164dfSZhong Wang {
572a8164dfSZhong Wang 	int ret = FCOE_STATUS_ERROR;
582a8164dfSZhong Wang 
592a8164dfSZhong Wang 	if ((*fd = open(FCOE_DEV_PATH, O_NDELAY | O_RDONLY | flag)) != -1) {
602a8164dfSZhong Wang 		ret = FCOE_STATUS_OK;
612a8164dfSZhong Wang 	} else {
622a8164dfSZhong Wang 		if (errno == EPERM || errno == EACCES) {
632a8164dfSZhong Wang 			ret = FCOE_STATUS_ERROR_PERM;
642a8164dfSZhong Wang 		} else {
652a8164dfSZhong Wang 			ret = FCOE_STATUS_ERROR_OPEN_DEV;
662a8164dfSZhong Wang 		}
672a8164dfSZhong Wang 		syslog(LOG_DEBUG, "openFcoe:open failure:%s:errno(%d)",
682a8164dfSZhong Wang 		    FCOE_DEV_PATH, errno);
692a8164dfSZhong Wang 	}
702a8164dfSZhong Wang 
712a8164dfSZhong Wang 	return (ret);
722a8164dfSZhong Wang }
732a8164dfSZhong Wang 
742a8164dfSZhong Wang static int
752a8164dfSZhong Wang isWWNZero(FCOE_PORT_WWN portwwn)
762a8164dfSZhong Wang {
772a8164dfSZhong Wang 	int i;
782a8164dfSZhong Wang 	int size = sizeof (FCOE_PORT_WWN);
792a8164dfSZhong Wang 
802a8164dfSZhong Wang 	for (i = 0; i < size; i++) {
812a8164dfSZhong Wang 		if (portwwn.wwn[i] != 0) {
822a8164dfSZhong Wang 			return (0);
832a8164dfSZhong Wang 		}
842a8164dfSZhong Wang 	}
852a8164dfSZhong Wang 	return (1);
862a8164dfSZhong Wang }
872a8164dfSZhong Wang 
882a8164dfSZhong Wang FCOE_STATUS
892a8164dfSZhong Wang FCOE_CreatePort(
902a8164dfSZhong Wang 	const FCOE_UINT8		*macLinkName,
912a8164dfSZhong Wang 	FCOE_UINT8		portType,
922a8164dfSZhong Wang 	FCOE_PORT_WWN		pwwn,
932a8164dfSZhong Wang 	FCOE_PORT_WWN		nwwn,
942a8164dfSZhong Wang 	FCOE_UINT8		promiscuous)
952a8164dfSZhong Wang {
962a8164dfSZhong Wang 	FCOE_STATUS		status = FCOE_STATUS_OK;
972a8164dfSZhong Wang 	int			fcoe_fd;
982a8164dfSZhong Wang 	fcoeio_t		fcoeio;
992a8164dfSZhong Wang 	fcoeio_create_port_param_t	param;
100*d4401b99SKelly Hu 	dladm_handle_t		handle;
101*d4401b99SKelly Hu 	datalink_id_t		linkid;
102*d4401b99SKelly Hu 	datalink_class_t	class;
1032a8164dfSZhong Wang 
1042a8164dfSZhong Wang 	bzero(&param, sizeof (fcoeio_create_port_param_t));
1052a8164dfSZhong Wang 
1062a8164dfSZhong Wang 	if (macLinkName == NULL) {
1072a8164dfSZhong Wang 		return (FCOE_STATUS_ERROR_INVAL_ARG);
1082a8164dfSZhong Wang 	}
1092a8164dfSZhong Wang 
110*d4401b99SKelly Hu 	if (strlen((char *)macLinkName) > MAXLINKNAMELEN-1) {
111*d4401b99SKelly Hu 		return (FCOE_STATUS_ERROR_MAC_LEN);
112*d4401b99SKelly Hu 	}
113*d4401b99SKelly Hu 
114*d4401b99SKelly Hu 	if (dladm_open(&handle) != DLADM_STATUS_OK) {
115*d4401b99SKelly Hu 		return (FCOE_STATUS_ERROR);
116*d4401b99SKelly Hu 	}
117*d4401b99SKelly Hu 
118*d4401b99SKelly Hu 	if (dladm_name2info(handle, (const char *)macLinkName,
119*d4401b99SKelly Hu 	    &linkid, NULL, &class, NULL) != DLADM_STATUS_OK) {
120*d4401b99SKelly Hu 		dladm_close(handle);
121*d4401b99SKelly Hu 		return (FCOE_STATUS_ERROR_GET_LINKINFO);
122*d4401b99SKelly Hu 	}
123*d4401b99SKelly Hu 	dladm_close(handle);
124*d4401b99SKelly Hu 
125*d4401b99SKelly Hu 	if (class != DATALINK_CLASS_PHYS) {
126*d4401b99SKelly Hu 		return (FCOE_STATUS_ERROR_CLASS_UNSUPPORT);
127*d4401b99SKelly Hu 	}
128*d4401b99SKelly Hu 
1292a8164dfSZhong Wang 	if (portType != FCOE_PORTTYPE_INITIATOR &&
1302a8164dfSZhong Wang 	    portType != FCOE_PORTTYPE_TARGET) {
1312a8164dfSZhong Wang 		return (FCOE_STATUS_ERROR_INVAL_ARG);
1322a8164dfSZhong Wang 	}
1332a8164dfSZhong Wang 
1342a8164dfSZhong Wang 	if (!isWWNZero(pwwn)) {
1352a8164dfSZhong Wang 		param.fcp_pwwn_provided = 1;
1362a8164dfSZhong Wang 		bcopy(pwwn.wwn, param.fcp_pwwn, 8);
1372a8164dfSZhong Wang 	}
1382a8164dfSZhong Wang 
1392a8164dfSZhong Wang 	if (!isWWNZero(nwwn)) {
1402a8164dfSZhong Wang 		param.fcp_nwwn_provided = 1;
1412a8164dfSZhong Wang 		bcopy(nwwn.wwn, param.fcp_nwwn, 8);
1422a8164dfSZhong Wang 	}
1432a8164dfSZhong Wang 
1442a8164dfSZhong Wang 	if (param.fcp_pwwn_provided == 1 &&
1452a8164dfSZhong Wang 	    param.fcp_nwwn_provided == 1 &&
1462a8164dfSZhong Wang 	    bcmp(&pwwn, &nwwn, 8) == 0) {
1472a8164dfSZhong Wang 		return (FCOE_STATUS_ERROR_WWN_SAME);
1482a8164dfSZhong Wang 	}
1492a8164dfSZhong Wang 
1502a8164dfSZhong Wang 	param.fcp_force_promisc = promiscuous;
151*d4401b99SKelly Hu 	param.fcp_mac_linkid = linkid;
1522a8164dfSZhong Wang 	param.fcp_port_type = (fcoe_cli_type_t)portType;
1532a8164dfSZhong Wang 
1542a8164dfSZhong Wang 	if ((status = openFcoe(OPEN_FCOE, &fcoe_fd)) != FCOE_STATUS_OK) {
1552a8164dfSZhong Wang 		return (status);
1562a8164dfSZhong Wang 	}
1572a8164dfSZhong Wang 
1582a8164dfSZhong Wang 	(void) memset(&fcoeio, 0, sizeof (fcoeio));
1592a8164dfSZhong Wang 	fcoeio.fcoeio_cmd = FCOEIO_CREATE_FCOE_PORT;
1602a8164dfSZhong Wang 
1612a8164dfSZhong Wang 	fcoeio.fcoeio_ilen = sizeof (param);
1622a8164dfSZhong Wang 	fcoeio.fcoeio_xfer = FCOEIO_XFER_WRITE;
1632a8164dfSZhong Wang 	fcoeio.fcoeio_ibuf = (uintptr_t)&param;
1642a8164dfSZhong Wang 
1652a8164dfSZhong Wang 	if (ioctl(fcoe_fd, FCOEIO_CMD, &fcoeio) != 0) {
1662a8164dfSZhong Wang 		switch (fcoeio.fcoeio_status) {
1672a8164dfSZhong Wang 		case FCOEIOE_INVAL_ARG:
1682a8164dfSZhong Wang 			status = FCOE_STATUS_ERROR_INVAL_ARG;
1692a8164dfSZhong Wang 			break;
1702a8164dfSZhong Wang 
1712a8164dfSZhong Wang 		case FCOEIOE_BUSY:
1722a8164dfSZhong Wang 			status = FCOE_STATUS_ERROR_BUSY;
1732a8164dfSZhong Wang 			break;
1742a8164dfSZhong Wang 
1752a8164dfSZhong Wang 		case FCOEIOE_ALREADY:
1762a8164dfSZhong Wang 			status = FCOE_STATUS_ERROR_ALREADY;
1772a8164dfSZhong Wang 			break;
1782a8164dfSZhong Wang 
1792a8164dfSZhong Wang 		case FCOEIOE_PWWN_CONFLICTED:
1802a8164dfSZhong Wang 			status = FCOE_STATUS_ERROR_PWWN_CONFLICTED;
1812a8164dfSZhong Wang 			break;
1822a8164dfSZhong Wang 
1832a8164dfSZhong Wang 		case FCOEIOE_NWWN_CONFLICTED:
1842a8164dfSZhong Wang 			status = FCOE_STATUS_ERROR_NWWN_CONFLICTED;
1852a8164dfSZhong Wang 			break;
1862a8164dfSZhong Wang 
1872a8164dfSZhong Wang 		case FCOEIOE_CREATE_MAC:
1882a8164dfSZhong Wang 			status = FCOE_STATUS_ERROR_CREATE_MAC;
1892a8164dfSZhong Wang 			break;
1902a8164dfSZhong Wang 
1912a8164dfSZhong Wang 		case FCOEIOE_OPEN_MAC:
1922a8164dfSZhong Wang 			status = FCOE_STATUS_ERROR_OPEN_MAC;
1932a8164dfSZhong Wang 			break;
1942a8164dfSZhong Wang 
1952a8164dfSZhong Wang 		case FCOEIOE_CREATE_PORT:
1962a8164dfSZhong Wang 			status = FCOE_STATUS_ERROR_CREATE_PORT;
1972a8164dfSZhong Wang 			break;
1982a8164dfSZhong Wang 
1992a8164dfSZhong Wang 		case FCOEIOE_NEED_JUMBO_FRAME:
2002a8164dfSZhong Wang 			status = FCOE_STATUS_ERROR_NEED_JUMBO_FRAME;
2012a8164dfSZhong Wang 			break;
2022a8164dfSZhong Wang 
2032a8164dfSZhong Wang 		default:
2042a8164dfSZhong Wang 			status = FCOE_STATUS_ERROR;
2052a8164dfSZhong Wang 		}
2062a8164dfSZhong Wang 	} else {
2072a8164dfSZhong Wang 		status = FCOE_STATUS_OK;
2082a8164dfSZhong Wang 	}
2092a8164dfSZhong Wang 	(void) close(fcoe_fd);
2102a8164dfSZhong Wang 	return (status);
2112a8164dfSZhong Wang }
2122a8164dfSZhong Wang 
2132a8164dfSZhong Wang FCOE_STATUS
2142a8164dfSZhong Wang FCOE_DeletePort(const FCOE_UINT8 *macLinkName)
2152a8164dfSZhong Wang {
2162a8164dfSZhong Wang 	FCOE_STATUS status = FCOE_STATUS_OK;
2172a8164dfSZhong Wang 	int fcoe_fd;
2182a8164dfSZhong Wang 	fcoeio_t	fcoeio;
219*d4401b99SKelly Hu 	dladm_handle_t		handle;
220*d4401b99SKelly Hu 	datalink_id_t		linkid;
221*d4401b99SKelly Hu 	fcoeio_delete_port_param_t fc_del_port;
2222a8164dfSZhong Wang 
2232a8164dfSZhong Wang 	if (macLinkName == NULL) {
2242a8164dfSZhong Wang 		return (FCOE_STATUS_ERROR_INVAL_ARG);
2252a8164dfSZhong Wang 	}
2262a8164dfSZhong Wang 
227*d4401b99SKelly Hu 	if (strlen((char *)macLinkName) > MAXLINKNAMELEN-1) {
2282a8164dfSZhong Wang 		return (FCOE_STATUS_ERROR_MAC_LEN);
2292a8164dfSZhong Wang 	}
230*d4401b99SKelly Hu 	if (dladm_open(&handle) != DLADM_STATUS_OK) {
231*d4401b99SKelly Hu 		return (FCOE_STATUS_ERROR);
232*d4401b99SKelly Hu 	}
233*d4401b99SKelly Hu 
234*d4401b99SKelly Hu 	if (dladm_name2info(handle, (const char *)macLinkName,
235*d4401b99SKelly Hu 	    &linkid, NULL, NULL, NULL) != DLADM_STATUS_OK) {
236*d4401b99SKelly Hu 		dladm_close(handle);
237*d4401b99SKelly Hu 		return (FCOE_STATUS_ERROR_GET_LINKINFO);
238*d4401b99SKelly Hu 	}
239*d4401b99SKelly Hu 	dladm_close(handle);
2402a8164dfSZhong Wang 
2412a8164dfSZhong Wang 	if ((status = openFcoe(OPEN_FCOE, &fcoe_fd)) != FCOE_STATUS_OK) {
2422a8164dfSZhong Wang 		return (status);
2432a8164dfSZhong Wang 	}
2442a8164dfSZhong Wang 
245*d4401b99SKelly Hu 	fc_del_port.fdp_mac_linkid = linkid;
246*d4401b99SKelly Hu 
2472a8164dfSZhong Wang 	(void) memset(&fcoeio, 0, sizeof (fcoeio));
2482a8164dfSZhong Wang 	fcoeio.fcoeio_cmd = FCOEIO_DELETE_FCOE_PORT;
2492a8164dfSZhong Wang 
250*d4401b99SKelly Hu 	/* only 4 bytes here, need to change */
251*d4401b99SKelly Hu 	fcoeio.fcoeio_ilen = sizeof (fcoeio_delete_port_param_t);
2522a8164dfSZhong Wang 	fcoeio.fcoeio_xfer = FCOEIO_XFER_WRITE;
253*d4401b99SKelly Hu 	fcoeio.fcoeio_ibuf = (uintptr_t)&fc_del_port;
2542a8164dfSZhong Wang 
2552a8164dfSZhong Wang 	if (ioctl(fcoe_fd, FCOEIO_CMD, &fcoeio) != 0) {
2562a8164dfSZhong Wang 		switch (fcoeio.fcoeio_status) {
2572a8164dfSZhong Wang 		case FCOEIOE_INVAL_ARG:
2582a8164dfSZhong Wang 			status = FCOE_STATUS_ERROR_INVAL_ARG;
2592a8164dfSZhong Wang 			break;
2602a8164dfSZhong Wang 
2612a8164dfSZhong Wang 		case FCOEIOE_BUSY:
2622a8164dfSZhong Wang 			status = FCOE_STATUS_ERROR_BUSY;
2632a8164dfSZhong Wang 			break;
2642a8164dfSZhong Wang 
2652a8164dfSZhong Wang 		case FCOEIOE_ALREADY:
2662a8164dfSZhong Wang 			status = FCOE_STATUS_ERROR_ALREADY;
2672a8164dfSZhong Wang 			break;
2682a8164dfSZhong Wang 
2692a8164dfSZhong Wang 		case FCOEIOE_MAC_NOT_FOUND:
2702a8164dfSZhong Wang 			status = FCOE_STATUS_ERROR_MAC_NOT_FOUND;
2712a8164dfSZhong Wang 			break;
2722a8164dfSZhong Wang 
2732a8164dfSZhong Wang 		case FCOEIOE_OFFLINE_FAILURE:
2742a8164dfSZhong Wang 			status = FCOE_STATUS_ERROR_OFFLINE_DEV;
2752a8164dfSZhong Wang 			break;
2762a8164dfSZhong Wang 
2772a8164dfSZhong Wang 		default:
2782a8164dfSZhong Wang 			status = FCOE_STATUS_ERROR;
2792a8164dfSZhong Wang 		}
2802a8164dfSZhong Wang 	} else {
2812a8164dfSZhong Wang 		status = FCOE_STATUS_OK;
2822a8164dfSZhong Wang 	}
2832a8164dfSZhong Wang 	(void) close(fcoe_fd);
2842a8164dfSZhong Wang 	return (status);
2852a8164dfSZhong Wang }
2862a8164dfSZhong Wang 
2872a8164dfSZhong Wang FCOE_STATUS
2882a8164dfSZhong Wang FCOE_GetPortList(
2892a8164dfSZhong Wang 	FCOE_UINT32		*port_num,
2902a8164dfSZhong Wang 	FCOE_PORT_ATTRIBUTE	**portlist)
2912a8164dfSZhong Wang {
2922a8164dfSZhong Wang 	FCOE_STATUS	status = FCOE_STATUS_OK;
2932a8164dfSZhong Wang 	int		fcoe_fd;
2942a8164dfSZhong Wang 	fcoeio_t	fcoeio;
2952a8164dfSZhong Wang 	fcoe_port_list_t	*inportlist = NULL;
2962a8164dfSZhong Wang 	FCOE_PORT_ATTRIBUTE	*outportlist = NULL;
2972a8164dfSZhong Wang 	int		i;
2982a8164dfSZhong Wang 	int		size = 64; /* default first attempt */
2992a8164dfSZhong Wang 	int		retry = 0;
3002a8164dfSZhong Wang 	int		bufsize;
301*d4401b99SKelly Hu 	dladm_handle_t	handle;
302*d4401b99SKelly Hu 	char		mac_name[MAXLINKNAMELEN];
3032a8164dfSZhong Wang 
3042a8164dfSZhong Wang 	if (port_num == NULL || portlist == NULL) {
3052a8164dfSZhong Wang 		return (FCOE_STATUS_ERROR_INVAL_ARG);
3062a8164dfSZhong Wang 	}
3072a8164dfSZhong Wang 	*port_num = 0;
3082a8164dfSZhong Wang 
3092a8164dfSZhong Wang 	if ((status = openFcoe(OPEN_FCOE, &fcoe_fd)) != FCOE_STATUS_OK) {
3102a8164dfSZhong Wang 		return (status);
3112a8164dfSZhong Wang 	}
3122a8164dfSZhong Wang 
3132a8164dfSZhong Wang 	/* Get fcoe port list */
3142a8164dfSZhong Wang 	(void) memset(&fcoeio, 0, sizeof (fcoeio));
3152a8164dfSZhong Wang 	retry = 0;
3162a8164dfSZhong Wang 
3172a8164dfSZhong Wang 	do {
3182a8164dfSZhong Wang 		bufsize = sizeof (fcoe_port_instance_t) * (size - 1) +
3192a8164dfSZhong Wang 		    sizeof (fcoe_port_list_t);
3202a8164dfSZhong Wang 		inportlist = (fcoe_port_list_t *)malloc(bufsize);
3212a8164dfSZhong Wang 		fcoeio.fcoeio_cmd = FCOEIO_GET_FCOE_PORT_LIST;
3222a8164dfSZhong Wang 		fcoeio.fcoeio_olen = bufsize;
3232a8164dfSZhong Wang 		fcoeio.fcoeio_xfer = FCOEIO_XFER_READ;
3242a8164dfSZhong Wang 		fcoeio.fcoeio_obuf = (uintptr_t)inportlist;
3252a8164dfSZhong Wang 
3262a8164dfSZhong Wang 		if (ioctl(fcoe_fd, FCOEIO_CMD, &fcoeio) != 0) {
3272a8164dfSZhong Wang 			if (fcoeio.fcoeio_status == FCOEIOE_MORE_DATA) {
3282a8164dfSZhong Wang 				size = inportlist->numPorts;
3292a8164dfSZhong Wang 			}
3302a8164dfSZhong Wang 			free(inportlist);
3312a8164dfSZhong Wang 			switch (fcoeio.fcoeio_status) {
3322a8164dfSZhong Wang 			case FCOEIOE_INVAL_ARG:
3332a8164dfSZhong Wang 				status = FCOE_STATUS_ERROR_INVAL_ARG;
3342a8164dfSZhong Wang 				(void) close(fcoe_fd);
3352a8164dfSZhong Wang 				return (status);
3362a8164dfSZhong Wang 
3372a8164dfSZhong Wang 			case FCOEIOE_BUSY:
3382a8164dfSZhong Wang 				status = FCOE_STATUS_ERROR_BUSY;
3392a8164dfSZhong Wang 				retry++;
3402a8164dfSZhong Wang 				break;
3412a8164dfSZhong Wang 
3422a8164dfSZhong Wang 			case FCOEIOE_MORE_DATA:
3432a8164dfSZhong Wang 				status = FCOE_STATUS_ERROR_MORE_DATA;
3442a8164dfSZhong Wang 				retry++;
3452a8164dfSZhong Wang 			default:
3462a8164dfSZhong Wang 				status = FCOE_STATUS_ERROR;
3472a8164dfSZhong Wang 			}
3482a8164dfSZhong Wang 		} else {
3492a8164dfSZhong Wang 			status = FCOE_STATUS_OK;
3502a8164dfSZhong Wang 			break;
3512a8164dfSZhong Wang 		}
3522a8164dfSZhong Wang 	} while (retry <= 3 && status != FCOE_STATUS_OK);
3532a8164dfSZhong Wang 
354*d4401b99SKelly Hu 	if (status == FCOE_STATUS_OK && inportlist->numPorts > 0) {
355*d4401b99SKelly Hu 		if (dladm_open(&handle) != DLADM_STATUS_OK) {
356*d4401b99SKelly Hu 			handle = NULL;
357*d4401b99SKelly Hu 		}
358*d4401b99SKelly Hu 
3592a8164dfSZhong Wang 		outportlist = (PFCOE_PORT_ATTRIBUTE)
3602a8164dfSZhong Wang 		    malloc(sizeof (FCOE_PORT_ATTRIBUTE) * inportlist->numPorts);
3612a8164dfSZhong Wang 
3622a8164dfSZhong Wang 		for (i = 0; i < inportlist->numPorts; i++) {
3632a8164dfSZhong Wang 			fcoe_port_instance_t *pi = &inportlist->ports[i];
3642a8164dfSZhong Wang 			FCOE_PORT_ATTRIBUTE *po = &outportlist[i];
3652a8164dfSZhong Wang 			bcopy(pi->fpi_pwwn, &po->port_wwn, 8);
366*d4401b99SKelly Hu 
367*d4401b99SKelly Hu 			if (handle == NULL ||
368*d4401b99SKelly Hu 			    dladm_datalink_id2info(handle, pi->fpi_mac_linkid,
369*d4401b99SKelly Hu 			    NULL, NULL, NULL, mac_name, sizeof (mac_name))
370*d4401b99SKelly Hu 			    != DLADM_STATUS_OK) {
371*d4401b99SKelly Hu 				(void) strcpy((char *)po->mac_link_name,
372*d4401b99SKelly Hu 				    "<unknown>");
373*d4401b99SKelly Hu 			} else {
374*d4401b99SKelly Hu 				(void) strcpy((char *)po->mac_link_name,
375*d4401b99SKelly Hu 				    mac_name);
376*d4401b99SKelly Hu 			}
3772a8164dfSZhong Wang 			bcopy(pi->fpi_mac_factory_addr,
3782a8164dfSZhong Wang 			    po->mac_factory_addr, 6);
3792a8164dfSZhong Wang 			bcopy(pi->fpi_mac_current_addr,
3802a8164dfSZhong Wang 			    po->mac_current_addr, 6);
3812a8164dfSZhong Wang 			po->port_type = (FCOE_UINT8)pi->fpi_port_type;
3822a8164dfSZhong Wang 			po->mtu_size = pi->fpi_mtu_size;
3832a8164dfSZhong Wang 			po->mac_promisc = pi->fpi_mac_promisc;
3842a8164dfSZhong Wang 		}
385*d4401b99SKelly Hu 
386*d4401b99SKelly Hu 		if (handle != NULL) {
387*d4401b99SKelly Hu 			dladm_close(handle);
388*d4401b99SKelly Hu 		}
3892a8164dfSZhong Wang 		*port_num = inportlist->numPorts;
3902a8164dfSZhong Wang 		*portlist = outportlist;
3912a8164dfSZhong Wang 		free(inportlist);
3922a8164dfSZhong Wang 	} else {
3932a8164dfSZhong Wang 		*port_num = 0;
3942a8164dfSZhong Wang 		*portlist = NULL;
3952a8164dfSZhong Wang 	}
3962a8164dfSZhong Wang 	(void) close(fcoe_fd);
3972a8164dfSZhong Wang 	return (status);
3982a8164dfSZhong Wang }
399