1 /*
2 * This file and its contents are supplied under the terms of the
3 * Common Development and Distribution License ("CDDL"), version 1.0.
4 * You may only use this file in accordance with the terms of version
5 * 1.0 of the CDDL.
6 *
7 * A full copy of the text of the CDDL should have accompanied this
8 * source. A copy of the CDDL is also available via the Internet at
9 * http://www.illumos.org/license/CDDL.
10 */
11
12 /*
13 * Copyright 2012 Nexenta Systems, Inc. All rights reserved.
14 */
15
16 #include <sys/aoe.h>
17
18 #include <libaoe.h>
19 #include <libdllink.h>
20 #include <libintl.h>
21 #include <libscf.h>
22 #include <locale.h>
23 #include <stddef.h>
24 #include <stdlib.h>
25 #include <string.h>
26 #include <strings.h>
27 #include <syslog.h>
28 #include <wchar.h>
29
30 /* Define an abbreviation for gettext to save typing */
31 #define _(s) gettext(s)
32
33 static int aoeadm_create_port(int, char **);
34 static int aoeadm_delete_port(int, char **);
35 static int aoeadm_list_ports(int, char **);
36 static void print_port_info(aoe_port_instance_t *, char *, int);
37 static void usage(void);
38
39 typedef struct aoeadm_command {
40 const char *name;
41 int (*func)(int argc, char **argv);
42 } aoeadm_command_t;
43
44 static aoeadm_command_t cmdtable[] = {
45 { "create-initiator", aoeadm_create_port },
46 { "create-target", aoeadm_create_port },
47 { "delete-initiator", aoeadm_delete_port },
48 { "delete-target", aoeadm_delete_port },
49 { "list-initiator", aoeadm_list_ports },
50 { "list-target", aoeadm_list_ports }
51 };
52 /* Note: Update this value if necessary when cmdtable is updated */
53 #define MAX_AOEADM_CMDLEN 16
54
55 static const char *cmdname;
56
57 extern const char *__progname;
58
59
60 int
61 main(int argc, char **argv)
62 {
63 int i;
64
65 (void) setlocale(LC_ALL, "");
66 #if !defined(TEXT_DOMAIN)
67 #define TEXT_DOMAIN "SYS_TEST"
68 #endif
69 (void) textdomain(TEXT_DOMAIN);
70
71 if (argc < 2)
72 usage();
73
74 if (strnlen(argv[1], MAX_AOEADM_CMDLEN+1) > MAX_AOEADM_CMDLEN) {
75 (void) fprintf(stderr, _("Invalid argument.\n"));
76 usage();
77 return (1);
78 }
79 for (i = 0; i < sizeof (cmdtable) / sizeof (cmdtable[0]); i++) {
80 /*
81 * The following strcmp is safe because we've
82 * already validated the size of argv[1].
83 */
84 if (strcmp(argv[1], cmdtable[i].name) == 0) {
85 cmdname = argv[1];
86 return (cmdtable[i].func(argc - 1, argv + 1));
87 }
88 };
89
90 usage();
91 /* NOTREACHED */
92 return (0);
93 }
94
95 static int
96 aoeadm_create_port(int argc, char **argv)
97 {
98 AOE_STATUS ret;
99 aoe_cli_policy_t policy = AOE_POLICY_NONE;
100 char c;
101 char *linknames;
102 char *module = NULL;
103 int portid;
104 int promisc = 0;
105
106 while ((c = getopt(argc, argv, "fm:p:")) != -1) {
107 switch (c) {
108 case 'f':
109 promisc = 1;
110 break;
111 case 'm':
112 module = optarg;
113 break;
114 case 'p':
115 if (strcmp(optarg, "failover") == 0)
116 policy = AOE_POLICY_FAILOVER;
117 else if (strcmp(optarg, "loadbalance") == 0)
118 policy = AOE_POLICY_LOADBALANCE;
119 else if (strcmp(optarg, "roundrobin") == 0)
120 policy = AOE_POLICY_ROUNDROBIN;
121 else
122 usage();
123 break;
124 default:
125 usage();
126 }
127 }
128
129 argc -= optind;
130 argv += optind;
131
132 if (argc < 2)
133 usage();
134
135 errno = 0;
136 portid = strtol(argv[0], (char **)NULL, 10);
137 if (errno != 0 || portid < 0)
138 usage();
139 linknames = argv[1];
140
141 if (strcmp(cmdname, "create-initiator") == 0)
142 ret = aoe_create_port(portid, linknames, promisc,
143 AOE_CLIENT_INITIATOR, policy, module);
144 else
145 ret = aoe_create_port(portid, linknames, promisc,
146 AOE_CLIENT_TARGET, policy, module);
147
148 if (ret != AOE_STATUS_OK) {
149 (void) fprintf(stderr, _("Failed to create port: %s\n"),
150 aoe_strerror(ret));
151 }
152
153 return (ret);
154 }
155
156 static int
157 aoeadm_delete_port(int argc, char **argv)
158 {
159 AOE_STATUS ret;
160 int portid;
161
162 if (argc < 2)
163 usage();
164
165 errno = 0;
166 portid = strtol(argv[1], (char **)NULL, 10);
167 if (errno != 0 || portid < 0)
168 usage();
169
170 ret = aoe_delete_port(portid);
171
172 if (ret != AOE_STATUS_OK) {
173 (void) fprintf(stderr, _("Failed to delete port: %s\n"),
174 aoe_strerror(ret));
175 }
176
177 return (ret);
178 }
179
180 static int
181 aoeadm_list_ports(int argc, char **argv)
182 {
183 AOE_STATUS ret;
184 aoe_port_list_t *portlist = NULL;
185 char c;
186 dladm_handle_t handle;
187 int i;
188 int portid = -1;
189 int verbose = 0;
190 uint32_t nports;
191
192 while ((c = getopt(argc, argv, "v")) != -1) {
193 switch (c) {
194 case 'v':
195 verbose = 1;
196 break;
197 default:
198 usage();
199 }
200 }
201
202 argc -= optind;
203 argv += optind;
204
205 if (argc == 1) {
206 errno = 0;
207 portid = strtol(argv[0], (char **)NULL, 10);
208 if (errno != 0 || portid < 0)
209 usage();
210 }
211
212 ret = aoe_get_port_list(&nports, &portlist);
213
214 if (ret != AOE_STATUS_OK) {
215 (void) fprintf(stderr, _("Failed to list ports: %s\n"),
216 aoe_strerror(ret));
217 return (ret);
218 }
219
220 if (nports == 0) {
221 free(portlist);
222 return (0);
223 }
224
225 if (dladm_open(&handle) != DLADM_STATUS_OK)
226 handle = NULL;
227
228 for (i = 0; i < nports; i++) {
229 aoe_port_instance_t *pi = &portlist->ports[i];
230 char linknames[AOE_MAX_MACOBJ * MAXLINKNAMELEN];
231 int j;
232
233 if (portid >= 0 && pi->api_port_id != portid)
234 continue;
235
236 if ((pi->api_port_type == AOE_CLIENT_INITIATOR &&
237 strcmp(cmdname, "list-target") == 0) ||
238 (pi->api_port_type == AOE_CLIENT_TARGET &&
239 strcmp(cmdname, "list-initiator") == 0))
240 continue;
241
242 /* Convert linkid to interface name */
243 for (j = 0; j < pi->api_mac_cnt; j++) {
244 aoe_mac_instance_t *mi = &pi->api_mac[j];
245 char *linkname = linknames + j * MAXLINKNAMELEN;
246
247 if (handle == NULL ||
248 dladm_datalink_id2info(handle, mi->ami_mac_linkid,
249 NULL, NULL, NULL, linkname, MAXLINKNAMELEN - 1) !=
250 DLADM_STATUS_OK)
251 (void) strcpy(linkname, "<unknown>");
252 }
253
254 print_port_info(pi, linknames, verbose);
255
256 if (portid >= 0) {
257 if (handle != NULL)
258 dladm_close(handle);
259 free(portlist);
260 return (0);
261 }
262 }
263
264 if (handle != NULL)
265 dladm_close(handle);
266 free(portlist);
267
268 return (portid >= 0 ? 1 : 0);
269 }
270
271 static void
272 print_port_info(aoe_port_instance_t *pi, char *linknames, int verbose)
273 {
274 int i;
275
276 if (pi == NULL)
277 return;
278
279 if (pi->api_port_type == AOE_CLIENT_INITIATOR)
280 (void) printf(_("Initiator: aoe.port"));
281 else
282 (void) printf(_("Target: aoe.shelf"));
283 (void) printf("%d\n", pi->api_port_id);
284
285 if (!verbose)
286 return;
287
288 (void) printf(_(" State\t\t: %s\n"),
289 (pi->api_port_state == AOE_PORT_STATE_ONLINE) ?
290 _("Online") : _("Offline"));
291 (void) printf(_(" Multipath Policy\t: %s\n"),
292 (pi->api_port_policy == AOE_POLICY_NONE) ? _("Disabled") :
293 (pi->api_port_policy == AOE_POLICY_FAILOVER ? _("Fail-Over") :
294 (pi->api_port_policy == AOE_POLICY_ROUNDROBIN ?
295 _("Round-Robin") : _("Load-Balance"))));
296 (void) printf(_(" Maxxfer\t\t: %d bytes\n"), pi->api_maxxfer);
297 (void) printf(_(" Interfaces\t\t: %d\n"), pi->api_mac_cnt);
298
299 for (i = 0; i < pi->api_mac_cnt; i++) {
300 aoe_mac_instance_t *mi = &pi->api_mac[i];
301 int j;
302
303 (void) printf(_("\tInterface: %s\n"),
304 linknames + i * MAXLINKNAMELEN);
305 (void) printf(_("\t Link Id\t\t: %d\n"), mi->ami_mac_linkid);
306 (void) printf(_("\t Link State\t\t: %s\n"),
307 mi->ami_mac_link_state == AOE_MAC_LINK_STATE_UP ?
308 _("Up") : _("Down"));
309 (void) printf(_("\t Link MTU\t\t: %d\n"), mi->ami_mtu_size);
310 (void) printf(_("\t Primary MAC Address\t: "));
311 for (j = 0; j < 6; j++)
312 (void) printf("%02x", mi->ami_mac_factory_addr[j]);
313 (void) printf(_("\n\t Current MAC Address\t: "));
314 for (j = 0; j < 6; j++)
315 (void) printf("%02x", mi->ami_mac_current_addr[j]);
316 (void) printf(_("\n\t Promiscuous Mode\t: %s\n"),
317 mi->ami_mac_promisc == 1 ? _("On") : _("Off"));
318 (void) printf(_("\t TX frames\t\t: %ld\n"),
319 mi->ami_mac_tx_frames);
320 (void) printf(_("\t RX frames\t\t: %ld\n"),
321 mi->ami_mac_rx_frames);
322 }
323 }
324
325 static void
326 usage(void)
327 {
328
329 (void) fprintf(stderr, _(
330 "Usage:\n"
331 "\t%s create-initiator [-f] [-p policy] port link[,link,...]\n"
332 "\t%s create-target [-f] [-m module] [-p policy] shelf link[,link,...]\n"
333 "\t%s delete-initiator port\n"
334 "\t%s delete-target shelf\n"
335 "\t%s list-initiator [-v]\n"
336 "\t%s list-target [-v]\n"),
337 __progname, __progname, __progname,
338 __progname, __progname, __progname);
339
340 exit(1);
341 }