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