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
isValidWWN(char * wwn)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
wwnconvert(uchar_t * wwn)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
printFCOEPortInfo(FCOE_PORT_ATTRIBUTE * attr)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
fcoe_adm_create_port(int objects,char * argv[],cmdOptions_t * options)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
fcoe_adm_delete_port(int objects,char * argv[])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
fcoe_adm_list_ports(cmdOptions_t * options)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