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 "fcinfo.h" 27 #include <libintl.h> 28 #include <fcntl.h> 29 #include <errno.h> 30 #include <assert.h> 31 #include <ctype.h> 32 #include <sys/list.h> 33 #include <stddef.h> 34 #include <strings.h> 35 #include <libfcoe.h> 36 #include <syslog.h> 37 38 static const char *FCOE_DRIVER_PATH = "/devices/fcoe:admin"; 39 40 static int 41 isValidWWN(char *wwn) 42 { 43 int index; 44 45 if (wwn == NULL) { 46 return (0); 47 } 48 49 if (strlen(wwn) != 16) { 50 return (0); 51 } 52 53 for (index = 0; index < 16; index++) { 54 if (isxdigit(wwn[index])) { 55 continue; 56 } 57 return (0); 58 } 59 return (1); 60 } 61 62 static uint64_t wwnconvert(uchar_t *wwn) 63 { 64 uint64_t tmp; 65 memcpy(&tmp, wwn, sizeof (uint64_t)); 66 return (ntohll(tmp)); 67 } 68 69 /* 70 * prints out all the HBA port information 71 */ 72 void 73 printFCOEPortInfo(FCOE_PORT_ATTRIBUTE *attr) 74 { 75 int i; 76 if (attr == NULL) { 77 return; 78 } 79 fprintf(stdout, gettext("HBA Port WWN: %016llx\n"), 80 wwnconvert((unsigned char *)&attr->port_wwn)); 81 82 fprintf(stdout, gettext("\tPort Type: %s\n"), 83 (attr->port_type == 0) ? "Initiator" : "Target"); 84 85 fprintf(stdout, gettext("\tMAC Name: %s\n"), attr->mac_link_name); 86 87 fprintf(stdout, gettext("\tMTU Size: %d\n"), attr->mtu_size); 88 89 fprintf(stdout, gettext("\tMAC Factory Address: ")); 90 for (i = 0; i < 6; i++) { 91 fprintf(stdout, gettext("%02x"), attr->mac_factory_addr[i]); 92 } 93 fprintf(stdout, gettext("\n\tMAC Current Address: ")); 94 for (i = 0; i < 6; i++) { 95 fprintf(stdout, gettext("%02x"), attr->mac_current_addr[i]); 96 } 97 fprintf(stdout, gettext("\n\tPromiscuous Mode: %s\n"), 98 attr->mac_promisc == 1 ? "On" : "Off"); 99 } 100 101 102 int 103 fcoe_adm_create_port(int objects, char *argv[], 104 cmdOptions_t *options) 105 { 106 FCOE_STATUS status = FCOE_STATUS_OK; 107 uint64_t nodeWWN, portWWN; 108 FCOE_PORT_WWN pwwn, nwwn; 109 FCOE_UINT8 macLinkName[FCOE_MAX_MAC_NAME_LEN]; 110 FCOE_UINT8 promiscuous = 0; 111 int createini = 0, createtgt = 0; 112 113 /* check the mac name operand */ 114 assert(objects == 1); 115 116 strcpy((char *)macLinkName, argv[0]); 117 bzero(&pwwn, 8); 118 bzero(&nwwn, 8); 119 120 for (; options->optval; options++) { 121 switch (options->optval) { 122 case 'i': 123 createini = 1; 124 break; 125 126 case 't': 127 createtgt = 1; 128 break; 129 case 'p': 130 if (!isValidWWN(options->optarg)) { 131 fprintf(stderr, 132 gettext("Error: Invalid Port WWN\n")); 133 return (1); 134 } 135 sscanf(options->optarg, "%016llx", &portWWN); 136 portWWN = htonll(portWWN); 137 memcpy(&pwwn, &portWWN, sizeof (portWWN)); 138 break; 139 140 case 'n': 141 if (!isValidWWN(options->optarg)) { 142 fprintf(stderr, 143 gettext("Error: Invalid Node WWN\n")); 144 return (1); 145 } 146 sscanf(options->optarg, "%016llx", &nodeWWN); 147 nodeWWN = htonll(nodeWWN); 148 memcpy(&nwwn, &nodeWWN, sizeof (nodeWWN)); 149 break; 150 case 'f': 151 promiscuous = 1; 152 break; 153 154 default: 155 fprintf(stderr, gettext("Error: Illegal option: %c\n"), 156 options->optval); 157 return (1); 158 } 159 } 160 161 if (createini == 1 && createtgt == 1) { 162 fprintf(stderr, "Error: Option -i and -t should " 163 "not be both specified\n"); 164 return (1); 165 } 166 status = FCOE_CreatePort(macLinkName, 167 createtgt == 1 ? FCOE_PORTTYPE_TARGET : 168 FCOE_PORTTYPE_INITIATOR, pwwn, nwwn, promiscuous); 169 170 if (status != FCOE_STATUS_OK) { 171 switch (status) { 172 case FCOE_STATUS_ERROR_BUSY: 173 fprintf(stderr, 174 gettext("Error: fcoe driver is busy\n")); 175 break; 176 177 case FCOE_STATUS_ERROR_ALREADY: 178 fprintf(stderr, 179 gettext("Error: Existing FCoE port " 180 "found on the specified MAC link\n")); 181 break; 182 183 case FCOE_STATUS_ERROR_PERM: 184 fprintf(stderr, 185 gettext("Error: Not enough permission to " 186 "open fcoe device\n")); 187 break; 188 189 case FCOE_STATUS_ERROR_OPEN_DEV: 190 fprintf(stderr, 191 gettext("Error: Failed to open fcoe device\n")); 192 break; 193 194 case FCOE_STATUS_ERROR_WWN_SAME: 195 fprintf(stderr, 196 gettext("Error: Port WWN is same as Node " 197 "WWN\n")); 198 break; 199 200 case FCOE_STATUS_ERROR_MAC_LEN: 201 fprintf(stderr, 202 gettext("Error: MAC name exceeds maximum " 203 "length\n")); 204 break; 205 206 case FCOE_STATUS_ERROR_PWWN_CONFLICTED: 207 fprintf(stderr, 208 gettext("Error: The specified Port WWN " 209 "is already in use\n")); 210 break; 211 212 case FCOE_STATUS_ERROR_NWWN_CONFLICTED: 213 fprintf(stderr, 214 gettext("Error: The specified Node WWN " 215 "is already in use\n")); 216 break; 217 218 case FCOE_STATUS_ERROR_NEED_JUMBO_FRAME: 219 fprintf(stderr, 220 gettext("Error: MTU size of the specified " 221 "MAC link needs to be increased to 2500 " 222 "or above\n")); 223 break; 224 225 case FCOE_STATUS_ERROR_CREATE_MAC: 226 fprintf(stderr, 227 gettext("Error: Out of memory\n")); 228 break; 229 230 231 case FCOE_STATUS_ERROR_OPEN_MAC: 232 fprintf(stderr, 233 gettext("Error: Failed to open the " 234 "specified MAC link\n")); 235 break; 236 237 case FCOE_STATUS_ERROR_CREATE_PORT: 238 fprintf(stderr, 239 gettext("Error: Failed to create FCoE " 240 "port on the specified MAC link\n")); 241 break; 242 243 case FCOE_STATUS_ERROR_CLASS_UNSUPPORT: 244 fprintf(stderr, 245 gettext("Error: Link class other than physical " 246 "link is not supported\n")); 247 break; 248 249 case FCOE_STATUS_ERROR_GET_LINKINFO: 250 fprintf(stderr, 251 gettext("Error: Failed to get link information " 252 "for %s\n"), macLinkName); 253 break; 254 255 case FCOE_STATUS_ERROR: 256 default: 257 fprintf(stderr, 258 gettext("Error: Due to reason code %d\n"), status); 259 } 260 return (1); 261 } else { 262 return (0); 263 } 264 } 265 266 int 267 fcoe_adm_delete_port(int objects, char *argv[]) 268 { 269 FCOE_STATUS status; 270 FCOE_UINT8 *macLinkName; 271 272 /* check the mac name operand */ 273 assert(objects == 1); 274 275 macLinkName = (FCOE_UINT8 *) argv[0]; 276 277 status = FCOE_DeletePort(macLinkName); 278 if (status != FCOE_STATUS_OK) { 279 switch (status) { 280 case FCOE_STATUS_ERROR_BUSY: 281 fprintf(stderr, 282 gettext("Error: fcoe driver is busy\n")); 283 break; 284 285 case FCOE_STATUS_ERROR_ALREADY: 286 fprintf(stderr, 287 gettext("Error: FCoE port not found on the " 288 "specified MAC link\n")); 289 break; 290 291 case FCOE_STATUS_ERROR_PERM: 292 fprintf(stderr, 293 gettext("Error: Not enough permission to " 294 "open fcoe device\n")); 295 break; 296 297 case FCOE_STATUS_ERROR_MAC_LEN: 298 fprintf(stderr, 299 gettext("Failed: MAC name exceeds maximum " 300 "length 32\n")); 301 break; 302 303 case FCOE_STATUS_ERROR_OPEN_DEV: 304 fprintf(stderr, 305 gettext("Error: Failed to open fcoe device\n")); 306 break; 307 308 case FCOE_STATUS_ERROR_MAC_NOT_FOUND: 309 fprintf(stderr, 310 gettext("Error: FCoE port not found on the " 311 "specified MAC link\n")); 312 break; 313 314 case FCOE_STATUS_ERROR_OFFLINE_DEV: 315 fprintf(stderr, 316 gettext("Error: Please use stmfadm to offline " 317 "the FCoE target first\n")); 318 break; 319 320 case FCOE_STATUS_ERROR_GET_LINKINFO: 321 fprintf(stderr, 322 gettext("Error: Failed to get link information " 323 "for %s\n"), macLinkName); 324 break; 325 326 case FCOE_STATUS_ERROR: 327 default: 328 fprintf(stderr, 329 gettext("Error: Due to reason code %d\n"), status); 330 } 331 return (1); 332 } else { 333 return (0); 334 } 335 } 336 337 int 338 fcoe_adm_list_ports(cmdOptions_t *options) 339 { 340 FCOE_STATUS status; 341 int showini = 0, showtgt = 0; 342 FCOE_UINT32 port_num; 343 FCOE_PORT_ATTRIBUTE *portlist = NULL; 344 int i; 345 int ret; 346 347 for (; options->optval; options++) { 348 switch (options->optval) { 349 case 'i': 350 showini = 1; 351 break; 352 353 case 't': 354 showtgt = 1; 355 break; 356 357 default: 358 fprintf(stderr, gettext("Error: Illegal option: %c\n"), 359 options->optval); 360 return (1); 361 } 362 } 363 if (showini == 0 && showtgt == 0) { 364 showini = 1; 365 showtgt = 1; 366 } 367 368 status = FCOE_GetPortList(&port_num, &portlist); 369 370 if (status != FCOE_STATUS_OK) { 371 switch (status) { 372 case FCOE_STATUS_ERROR_BUSY: 373 fprintf(stderr, 374 gettext("Error: fcoe driver is busy\n")); 375 break; 376 377 case FCOE_STATUS_ERROR_PERM: 378 fprintf(stderr, 379 gettext("Error: Not enough permission to " 380 "open fcoe device\n")); 381 break; 382 383 case FCOE_STATUS_ERROR_OPEN_DEV: 384 fprintf(stderr, 385 gettext("Error: Failed to open fcoe device\n")); 386 break; 387 388 case FCOE_STATUS_ERROR_INVAL_ARG: 389 fprintf(stderr, 390 gettext("Error: Invalid argument\n")); 391 break; 392 393 case FCOE_STATUS_ERROR_MORE_DATA: 394 fprintf(stderr, 395 gettext("Error: More data\n")); 396 break; 397 398 case FCOE_STATUS_ERROR: 399 default: 400 fprintf(stderr, 401 gettext("Error: Due to reason code %d\n"), status); 402 } 403 ret = 1; 404 } else { 405 if (port_num == 0) { 406 fprintf(stdout, gettext("No FCoE Ports Found!\n")); 407 } else { 408 for (i = 0; i < port_num; i++) { 409 if ((portlist[i].port_type == 410 FCOE_PORTTYPE_INITIATOR && 411 showini == 1) || (showtgt == 1 && 412 portlist[i].port_type == 413 FCOE_PORTTYPE_TARGET)) { 414 printFCOEPortInfo(&portlist[i]); 415 } 416 } 417 } 418 ret = 0; 419 } 420 421 if (portlist != NULL) { 422 free(portlist); 423 } 424 return (ret); 425 426 } 427