xref: /illumos-gate/usr/src/cmd/fcinfo/fcoeadm.c (revision e23347b1b88ce2c0847fad6e9467a1f953597aa7)
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