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("\tPrimary MAC Address: ")); 90 for (i = 0; i < 6; i++) { 91 fprintf(stdout, gettext("%02x"), attr->mac_factory_addr[i]); 92 } 93 fprintf(stdout, gettext("\n\tCurrent MAC 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 FCOE_UINT32 port_num; 272 FCOE_PORT_ATTRIBUTE *portlist = NULL; 273 int i; 274 275 /* check the mac name operand */ 276 assert(objects == 1); 277 278 macLinkName = (FCOE_UINT8 *) argv[0]; 279 280 status = FCOE_DeletePort(macLinkName); 281 if (status != FCOE_STATUS_OK) { 282 switch (status) { 283 case FCOE_STATUS_ERROR_BUSY: 284 fprintf(stderr, 285 gettext("Error: fcoe driver is busy\n")); 286 break; 287 288 case FCOE_STATUS_ERROR_ALREADY: 289 fprintf(stderr, 290 gettext("Error: FCoE port not found on the " 291 "specified MAC link\n")); 292 break; 293 294 case FCOE_STATUS_ERROR_PERM: 295 fprintf(stderr, 296 gettext("Error: Not enough permission to " 297 "open fcoe device\n")); 298 break; 299 300 case FCOE_STATUS_ERROR_MAC_LEN: 301 fprintf(stderr, 302 gettext("Failed: MAC name exceeds maximum " 303 "length 32\n")); 304 break; 305 306 case FCOE_STATUS_ERROR_OPEN_DEV: 307 fprintf(stderr, 308 gettext("Error: Failed to open fcoe device\n")); 309 break; 310 311 case FCOE_STATUS_ERROR_MAC_NOT_FOUND: 312 fprintf(stderr, 313 gettext("Error: FCoE port not found on the " 314 "specified MAC link\n")); 315 break; 316 317 case FCOE_STATUS_ERROR_OFFLINE_DEV: 318 status = FCOE_GetPortList(&port_num, &portlist); 319 if (status != FCOE_STATUS_OK || port_num == 0) { 320 fprintf(stderr, 321 gettext("Error: FCoE port not found on the " 322 "specified MAC link\n")); 323 break; 324 } 325 for (i = 0; i < port_num; i++) { 326 if (strcmp( 327 (char *)portlist[i].mac_link_name, 328 (char *)macLinkName) == 0) { 329 if (portlist[i].port_type == 330 FCOE_PORTTYPE_TARGET) { 331 fprintf(stderr, 332 gettext("Error: Please use " 333 "stmfadm to offline the " 334 "FCoE target first\n")); 335 } else { 336 fprintf(stderr, 337 gettext("Error: Failed to " 338 "delete FCoE port because " 339 "unable to offline the " 340 "device\n")); 341 } 342 break; 343 } 344 } 345 free(portlist); 346 if (i == port_num) { 347 fprintf(stderr, 348 gettext("Error: FCoE port not found on the " 349 "specified MAC link\n")); 350 } 351 break; 352 353 case FCOE_STATUS_ERROR_GET_LINKINFO: 354 fprintf(stderr, 355 gettext("Error: Failed to get link information " 356 "for %s\n"), macLinkName); 357 break; 358 359 case FCOE_STATUS_ERROR: 360 default: 361 fprintf(stderr, 362 gettext("Error: Due to reason code %d\n"), status); 363 } 364 return (1); 365 } else { 366 return (0); 367 } 368 } 369 370 int 371 fcoe_adm_list_ports(cmdOptions_t *options) 372 { 373 FCOE_STATUS status; 374 int showini = 0, showtgt = 0; 375 FCOE_UINT32 port_num; 376 FCOE_PORT_ATTRIBUTE *portlist = NULL; 377 int i; 378 int ret; 379 380 for (; options->optval; options++) { 381 switch (options->optval) { 382 case 'i': 383 showini = 1; 384 break; 385 386 case 't': 387 showtgt = 1; 388 break; 389 390 default: 391 fprintf(stderr, gettext("Error: Illegal option: %c\n"), 392 options->optval); 393 return (1); 394 } 395 } 396 if (showini == 0 && showtgt == 0) { 397 showini = 1; 398 showtgt = 1; 399 } 400 401 status = FCOE_GetPortList(&port_num, &portlist); 402 403 if (status != FCOE_STATUS_OK) { 404 switch (status) { 405 case FCOE_STATUS_ERROR_BUSY: 406 fprintf(stderr, 407 gettext("Error: fcoe driver is busy\n")); 408 break; 409 410 case FCOE_STATUS_ERROR_PERM: 411 fprintf(stderr, 412 gettext("Error: Not enough permission to " 413 "open fcoe device\n")); 414 break; 415 416 case FCOE_STATUS_ERROR_OPEN_DEV: 417 fprintf(stderr, 418 gettext("Error: Failed to open fcoe device\n")); 419 break; 420 421 case FCOE_STATUS_ERROR_INVAL_ARG: 422 fprintf(stderr, 423 gettext("Error: Invalid argument\n")); 424 break; 425 426 case FCOE_STATUS_ERROR_MORE_DATA: 427 fprintf(stderr, 428 gettext("Error: More data\n")); 429 break; 430 431 case FCOE_STATUS_ERROR: 432 default: 433 fprintf(stderr, 434 gettext("Error: Due to reason code %d\n"), status); 435 } 436 ret = 1; 437 } else { 438 if (port_num == 0) { 439 fprintf(stdout, gettext("No FCoE Ports Found!\n")); 440 } else { 441 for (i = 0; i < port_num; i++) { 442 if ((portlist[i].port_type == 443 FCOE_PORTTYPE_INITIATOR && 444 showini == 1) || (showtgt == 1 && 445 portlist[i].port_type == 446 FCOE_PORTTYPE_TARGET)) { 447 printFCOEPortInfo(&portlist[i]); 448 } 449 } 450 } 451 ret = 0; 452 } 453 454 if (portlist != NULL) { 455 free(portlist); 456 } 457 return (ret); 458 459 } 460