1 /* 2 * CDDL HEADER START 3 * 4 * The contents of this file are subject to the terms of the 5 * Common Development and Distribution License (the "License"). 6 * You may not use this file except in compliance with the License. 7 * 8 * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE 9 * or http://www.opensolaris.org/os/licensing. 10 * See the License for the specific language governing permissions 11 * and limitations under the License. 12 * 13 * When distributing Covered Code, include this CDDL HEADER in each 14 * file and include the License file at usr/src/OPENSOLARIS.LICENSE. 15 * If applicable, add the following below this CDDL HEADER, with the 16 * fields enclosed by brackets "[]" replaced with your own identifying 17 * information: Portions Copyright [yyyy] [name of copyright owner] 18 * 19 * CDDL HEADER END 20 */ 21 /* 22 * Copyright 2009 Sun Microsystems, Inc. All rights reserved. 23 * Use is subject to license terms. 24 */ 25 26 #include <stdlib.h> 27 #include <stdio.h> 28 #include <wchar.h> 29 #include <strings.h> 30 #include <sys/types.h> 31 #include <sys/stat.h> 32 #include <fcntl.h> 33 #include <unistd.h> 34 #include <libintl.h> 35 #include <errno.h> 36 #include <string.h> 37 #include <assert.h> 38 #include <syslog.h> 39 #include <libfcoe.h> 40 #include <fcoeio.h> 41 42 #define FCOE_DEV_PATH "/devices/fcoe:admin" 43 44 #define OPEN_FCOE 0 45 #define OPEN_EXCL_FCOE O_EXCL 46 47 /* 48 * Open for fcoe module 49 * 50 * flag - open flag (OPEN_FCOE, OPEN_EXCL_FCOE) 51 * fd - pointer to integer. On success, contains the fcoe file descriptor 52 */ 53 static int 54 openFcoe(int flag, int *fd) 55 { 56 int ret = FCOE_STATUS_ERROR; 57 58 if ((*fd = open(FCOE_DEV_PATH, O_NDELAY | O_RDONLY | flag)) != -1) { 59 ret = FCOE_STATUS_OK; 60 } else { 61 if (errno == EPERM || errno == EACCES) { 62 ret = FCOE_STATUS_ERROR_PERM; 63 } else { 64 ret = FCOE_STATUS_ERROR_OPEN_DEV; 65 } 66 syslog(LOG_DEBUG, "openFcoe:open failure:%s:errno(%d)", 67 FCOE_DEV_PATH, errno); 68 } 69 70 return (ret); 71 } 72 73 static int 74 isWWNZero(FCOE_PORT_WWN portwwn) 75 { 76 int i; 77 int size = sizeof (FCOE_PORT_WWN); 78 79 for (i = 0; i < size; i++) { 80 if (portwwn.wwn[i] != 0) { 81 return (0); 82 } 83 } 84 return (1); 85 } 86 87 FCOE_STATUS 88 FCOE_CreatePort( 89 const FCOE_UINT8 *macLinkName, 90 FCOE_UINT8 portType, 91 FCOE_PORT_WWN pwwn, 92 FCOE_PORT_WWN nwwn, 93 FCOE_UINT8 promiscuous) 94 { 95 FCOE_STATUS status = FCOE_STATUS_OK; 96 int fcoe_fd; 97 fcoeio_t fcoeio; 98 fcoeio_create_port_param_t param; 99 100 bzero(¶m, sizeof (fcoeio_create_port_param_t)); 101 102 if (macLinkName == NULL) { 103 return (FCOE_STATUS_ERROR_INVAL_ARG); 104 } 105 106 if (portType != FCOE_PORTTYPE_INITIATOR && 107 portType != FCOE_PORTTYPE_TARGET) { 108 return (FCOE_STATUS_ERROR_INVAL_ARG); 109 } 110 111 if (!isWWNZero(pwwn)) { 112 param.fcp_pwwn_provided = 1; 113 bcopy(pwwn.wwn, param.fcp_pwwn, 8); 114 } 115 116 if (!isWWNZero(nwwn)) { 117 param.fcp_nwwn_provided = 1; 118 bcopy(nwwn.wwn, param.fcp_nwwn, 8); 119 } 120 121 if (param.fcp_pwwn_provided == 1 && 122 param.fcp_nwwn_provided == 1 && 123 bcmp(&pwwn, &nwwn, 8) == 0) { 124 return (FCOE_STATUS_ERROR_WWN_SAME); 125 } 126 127 if (strlen((char *)macLinkName) > FCOE_MAX_MAC_NAME_LEN-1) { 128 return (FCOE_STATUS_ERROR_MAC_LEN); 129 } 130 131 param.fcp_force_promisc = promiscuous; 132 (void) strcpy((char *)param.fcp_mac_name, (char *)macLinkName); 133 param.fcp_port_type = (fcoe_cli_type_t)portType; 134 135 if ((status = openFcoe(OPEN_FCOE, &fcoe_fd)) != FCOE_STATUS_OK) { 136 return (status); 137 } 138 139 (void) memset(&fcoeio, 0, sizeof (fcoeio)); 140 fcoeio.fcoeio_cmd = FCOEIO_CREATE_FCOE_PORT; 141 142 fcoeio.fcoeio_ilen = sizeof (param); 143 fcoeio.fcoeio_xfer = FCOEIO_XFER_WRITE; 144 fcoeio.fcoeio_ibuf = (uintptr_t)¶m; 145 146 if (ioctl(fcoe_fd, FCOEIO_CMD, &fcoeio) != 0) { 147 switch (fcoeio.fcoeio_status) { 148 case FCOEIOE_INVAL_ARG: 149 status = FCOE_STATUS_ERROR_INVAL_ARG; 150 break; 151 152 case FCOEIOE_BUSY: 153 status = FCOE_STATUS_ERROR_BUSY; 154 break; 155 156 case FCOEIOE_ALREADY: 157 status = FCOE_STATUS_ERROR_ALREADY; 158 break; 159 160 case FCOEIOE_PWWN_CONFLICTED: 161 status = FCOE_STATUS_ERROR_PWWN_CONFLICTED; 162 break; 163 164 case FCOEIOE_NWWN_CONFLICTED: 165 status = FCOE_STATUS_ERROR_NWWN_CONFLICTED; 166 break; 167 168 case FCOEIOE_CREATE_MAC: 169 status = FCOE_STATUS_ERROR_CREATE_MAC; 170 break; 171 172 case FCOEIOE_OPEN_MAC: 173 status = FCOE_STATUS_ERROR_OPEN_MAC; 174 break; 175 176 case FCOEIOE_CREATE_PORT: 177 status = FCOE_STATUS_ERROR_CREATE_PORT; 178 break; 179 180 case FCOEIOE_NEED_JUMBO_FRAME: 181 status = FCOE_STATUS_ERROR_NEED_JUMBO_FRAME; 182 break; 183 184 case FCOEIOE_VNIC_UNSUPPORT: 185 status = FCOE_STATUS_ERROR_VNIC_UNSUPPORT; 186 break; 187 188 default: 189 status = FCOE_STATUS_ERROR; 190 } 191 } else { 192 status = FCOE_STATUS_OK; 193 } 194 (void) close(fcoe_fd); 195 return (status); 196 } 197 198 FCOE_STATUS 199 FCOE_DeletePort(const FCOE_UINT8 *macLinkName) 200 { 201 FCOE_STATUS status = FCOE_STATUS_OK; 202 int fcoe_fd; 203 fcoeio_t fcoeio; 204 205 if (macLinkName == NULL) { 206 return (FCOE_STATUS_ERROR_INVAL_ARG); 207 } 208 209 if (strlen((char *)macLinkName) > FCOE_MAX_MAC_NAME_LEN-1) { 210 return (FCOE_STATUS_ERROR_MAC_LEN); 211 } 212 213 if ((status = openFcoe(OPEN_FCOE, &fcoe_fd)) != FCOE_STATUS_OK) { 214 return (status); 215 } 216 217 (void) memset(&fcoeio, 0, sizeof (fcoeio)); 218 fcoeio.fcoeio_cmd = FCOEIO_DELETE_FCOE_PORT; 219 220 fcoeio.fcoeio_ilen = strlen((char *)macLinkName)+1; 221 fcoeio.fcoeio_xfer = FCOEIO_XFER_WRITE; 222 fcoeio.fcoeio_ibuf = (uintptr_t)macLinkName; 223 224 if (ioctl(fcoe_fd, FCOEIO_CMD, &fcoeio) != 0) { 225 switch (fcoeio.fcoeio_status) { 226 case FCOEIOE_INVAL_ARG: 227 status = FCOE_STATUS_ERROR_INVAL_ARG; 228 break; 229 230 case FCOEIOE_BUSY: 231 status = FCOE_STATUS_ERROR_BUSY; 232 break; 233 234 case FCOEIOE_ALREADY: 235 status = FCOE_STATUS_ERROR_ALREADY; 236 break; 237 238 case FCOEIOE_MAC_NOT_FOUND: 239 status = FCOE_STATUS_ERROR_MAC_NOT_FOUND; 240 break; 241 242 case FCOEIOE_OFFLINE_FAILURE: 243 status = FCOE_STATUS_ERROR_OFFLINE_DEV; 244 break; 245 246 default: 247 status = FCOE_STATUS_ERROR; 248 } 249 } else { 250 status = FCOE_STATUS_OK; 251 } 252 (void) close(fcoe_fd); 253 return (status); 254 } 255 256 FCOE_STATUS 257 FCOE_GetPortList( 258 FCOE_UINT32 *port_num, 259 FCOE_PORT_ATTRIBUTE **portlist) 260 { 261 FCOE_STATUS status = FCOE_STATUS_OK; 262 int fcoe_fd; 263 fcoeio_t fcoeio; 264 fcoe_port_list_t *inportlist = NULL; 265 FCOE_PORT_ATTRIBUTE *outportlist = NULL; 266 int i; 267 int size = 64; /* default first attempt */ 268 int retry = 0; 269 int bufsize; 270 271 if (port_num == NULL || portlist == NULL) { 272 return (FCOE_STATUS_ERROR_INVAL_ARG); 273 } 274 *port_num = 0; 275 276 if ((status = openFcoe(OPEN_FCOE, &fcoe_fd)) != FCOE_STATUS_OK) { 277 return (status); 278 } 279 280 /* Get fcoe port list */ 281 (void) memset(&fcoeio, 0, sizeof (fcoeio)); 282 retry = 0; 283 284 do { 285 bufsize = sizeof (fcoe_port_instance_t) * (size - 1) + 286 sizeof (fcoe_port_list_t); 287 inportlist = (fcoe_port_list_t *)malloc(bufsize); 288 fcoeio.fcoeio_cmd = FCOEIO_GET_FCOE_PORT_LIST; 289 fcoeio.fcoeio_olen = bufsize; 290 fcoeio.fcoeio_xfer = FCOEIO_XFER_READ; 291 fcoeio.fcoeio_obuf = (uintptr_t)inportlist; 292 293 if (ioctl(fcoe_fd, FCOEIO_CMD, &fcoeio) != 0) { 294 if (fcoeio.fcoeio_status == FCOEIOE_MORE_DATA) { 295 size = inportlist->numPorts; 296 } 297 free(inportlist); 298 switch (fcoeio.fcoeio_status) { 299 case FCOEIOE_INVAL_ARG: 300 status = FCOE_STATUS_ERROR_INVAL_ARG; 301 (void) close(fcoe_fd); 302 return (status); 303 304 case FCOEIOE_BUSY: 305 status = FCOE_STATUS_ERROR_BUSY; 306 retry++; 307 break; 308 309 case FCOEIOE_MORE_DATA: 310 status = FCOE_STATUS_ERROR_MORE_DATA; 311 retry++; 312 default: 313 status = FCOE_STATUS_ERROR; 314 } 315 } else { 316 status = FCOE_STATUS_OK; 317 break; 318 } 319 } while (retry <= 3 && status != FCOE_STATUS_OK); 320 321 if (status == FCOE_STATUS_OK) { 322 outportlist = (PFCOE_PORT_ATTRIBUTE) 323 malloc(sizeof (FCOE_PORT_ATTRIBUTE) * inportlist->numPorts); 324 325 for (i = 0; i < inportlist->numPorts; i++) { 326 fcoe_port_instance_t *pi = &inportlist->ports[i]; 327 FCOE_PORT_ATTRIBUTE *po = &outportlist[i]; 328 bcopy(pi->fpi_pwwn, &po->port_wwn, 8); 329 bcopy(pi->fpi_mac_link_name, po->mac_link_name, 32); 330 bcopy(pi->fpi_mac_factory_addr, 331 po->mac_factory_addr, 6); 332 bcopy(pi->fpi_mac_current_addr, 333 po->mac_current_addr, 6); 334 po->port_type = (FCOE_UINT8)pi->fpi_port_type; 335 po->mtu_size = pi->fpi_mtu_size; 336 po->mac_promisc = pi->fpi_mac_promisc; 337 } 338 *port_num = inportlist->numPorts; 339 *portlist = outportlist; 340 free(inportlist); 341 } else { 342 *port_num = 0; 343 *portlist = NULL; 344 } 345 (void) close(fcoe_fd); 346 return (status); 347 } 348