xref: /titanic_51/usr/src/cmd/dlutil/dlled.c (revision b142f83db07eef31395422eb0514e14b61cb678b)
1*b142f83dSRobert Mustacchi /*
2*b142f83dSRobert Mustacchi  * This file and its contents are supplied under the terms of the
3*b142f83dSRobert Mustacchi  * Common Development and Distribution License ("CDDL"), version 1.0.
4*b142f83dSRobert Mustacchi  * You may only use this file in accordance with the terms of version
5*b142f83dSRobert Mustacchi  * 1.0 of the CDDL.
6*b142f83dSRobert Mustacchi  *
7*b142f83dSRobert Mustacchi  * A full copy of the text of the CDDL should have accompanied this
8*b142f83dSRobert Mustacchi  * source.  A copy of the CDDL is also available via the Internet at
9*b142f83dSRobert Mustacchi  * http://www.illumos.org/license/CDDL.
10*b142f83dSRobert Mustacchi  */
11*b142f83dSRobert Mustacchi 
12*b142f83dSRobert Mustacchi /*
13*b142f83dSRobert Mustacchi  * Copyright (c) 2017, Joyent, Inc.
14*b142f83dSRobert Mustacchi  */
15*b142f83dSRobert Mustacchi 
16*b142f83dSRobert Mustacchi /*
17*b142f83dSRobert Mustacchi  * Private utility to get and set LED information on NICs. This should really
18*b142f83dSRobert Mustacchi  * all be integrated into FM. Until we have figured out that plumbing, this
19*b142f83dSRobert Mustacchi  * allows us to have a little something that we can use to drive work.
20*b142f83dSRobert Mustacchi  */
21*b142f83dSRobert Mustacchi 
22*b142f83dSRobert Mustacchi #include <unistd.h>
23*b142f83dSRobert Mustacchi #include <stdio.h>
24*b142f83dSRobert Mustacchi #include <stdarg.h>
25*b142f83dSRobert Mustacchi #include <libgen.h>
26*b142f83dSRobert Mustacchi #include <string.h>
27*b142f83dSRobert Mustacchi #include <stdlib.h>
28*b142f83dSRobert Mustacchi #include <errno.h>
29*b142f83dSRobert Mustacchi #include <strings.h>
30*b142f83dSRobert Mustacchi 
31*b142f83dSRobert Mustacchi #include <libdladm.h>
32*b142f83dSRobert Mustacchi #include <libdllink.h>
33*b142f83dSRobert Mustacchi #include <sys/mac.h>
34*b142f83dSRobert Mustacchi #include <sys/dld.h>
35*b142f83dSRobert Mustacchi #include <sys/dld_ioc.h>
36*b142f83dSRobert Mustacchi 
37*b142f83dSRobert Mustacchi static const char *dlled_progname;
38*b142f83dSRobert Mustacchi static dladm_handle_t dlled_hdl;
39*b142f83dSRobert Mustacchi static char dlled_dlerrmsg[DLADM_STRSIZE];
40*b142f83dSRobert Mustacchi 
41*b142f83dSRobert Mustacchi typedef struct dlled_led_map {
42*b142f83dSRobert Mustacchi 	const char *dlm_name;
43*b142f83dSRobert Mustacchi 	mac_led_mode_t dlm_bits;
44*b142f83dSRobert Mustacchi } dlled_led_map_t;
45*b142f83dSRobert Mustacchi 
46*b142f83dSRobert Mustacchi static dlled_led_map_t dlled_map[] = {
47*b142f83dSRobert Mustacchi 	{ "default",	MAC_LED_DEFAULT },
48*b142f83dSRobert Mustacchi 	{ "off", 	MAC_LED_OFF },
49*b142f83dSRobert Mustacchi 	{ "on", 	MAC_LED_ON },
50*b142f83dSRobert Mustacchi 	{ "ident",	MAC_LED_IDENT }
51*b142f83dSRobert Mustacchi };
52*b142f83dSRobert Mustacchi 
53*b142f83dSRobert Mustacchi #define	DLLED_MAP_NENTRIES	\
54*b142f83dSRobert Mustacchi 	(sizeof (dlled_map) / sizeof (dlled_led_map_t))
55*b142f83dSRobert Mustacchi 
56*b142f83dSRobert Mustacchi static void
57*b142f83dSRobert Mustacchi dlled_usage(const char *fmt, ...)
58*b142f83dSRobert Mustacchi {
59*b142f83dSRobert Mustacchi 	if (fmt != NULL) {
60*b142f83dSRobert Mustacchi 		va_list ap;
61*b142f83dSRobert Mustacchi 
62*b142f83dSRobert Mustacchi 		(void) fprintf(stderr, "%s: ", dlled_progname);
63*b142f83dSRobert Mustacchi 		va_start(ap, fmt);
64*b142f83dSRobert Mustacchi 		(void) vfprintf(stderr, fmt, ap);
65*b142f83dSRobert Mustacchi 		va_end(ap);
66*b142f83dSRobert Mustacchi 	}
67*b142f83dSRobert Mustacchi 
68*b142f83dSRobert Mustacchi 	(void) fprintf(stderr, "Usage: %s [-s mode] [link]\n"
69*b142f83dSRobert Mustacchi 	    "\n"
70*b142f83dSRobert Mustacchi 	    "\t-s mode   set LED to mode\n",
71*b142f83dSRobert Mustacchi 	    dlled_progname);
72*b142f83dSRobert Mustacchi }
73*b142f83dSRobert Mustacchi 
74*b142f83dSRobert Mustacchi static mac_led_mode_t
75*b142f83dSRobert Mustacchi dlled_parse_mode(const char *orig)
76*b142f83dSRobert Mustacchi {
77*b142f83dSRobert Mustacchi 	char *mode;
78*b142f83dSRobert Mustacchi 	char *part;
79*b142f83dSRobert Mustacchi 	mac_led_mode_t m = 0;
80*b142f83dSRobert Mustacchi 
81*b142f83dSRobert Mustacchi 	mode = strdup(orig);
82*b142f83dSRobert Mustacchi 	if (mode == NULL) {
83*b142f83dSRobert Mustacchi 		fprintf(stderr, "failed to allocate memory to dup led "
84*b142f83dSRobert Mustacchi 		    "mode: %s\n", strerror(errno));
85*b142f83dSRobert Mustacchi 		exit(1);
86*b142f83dSRobert Mustacchi 	}
87*b142f83dSRobert Mustacchi 
88*b142f83dSRobert Mustacchi 	part = strtok(mode, ",");
89*b142f83dSRobert Mustacchi 	while (part != NULL) {
90*b142f83dSRobert Mustacchi 		int i;
91*b142f83dSRobert Mustacchi 
92*b142f83dSRobert Mustacchi 		for (i = 0; i < DLLED_MAP_NENTRIES; i++) {
93*b142f83dSRobert Mustacchi 			if (strcmp(dlled_map[i].dlm_name, part) == 0) {
94*b142f83dSRobert Mustacchi 				m |= dlled_map[i].dlm_bits;
95*b142f83dSRobert Mustacchi 				break;
96*b142f83dSRobert Mustacchi 			}
97*b142f83dSRobert Mustacchi 		}
98*b142f83dSRobert Mustacchi 
99*b142f83dSRobert Mustacchi 		if (i == DLLED_MAP_NENTRIES) {
100*b142f83dSRobert Mustacchi 			fprintf(stderr, "unknown LED mode: %s\n", part);
101*b142f83dSRobert Mustacchi 			exit(1);
102*b142f83dSRobert Mustacchi 		}
103*b142f83dSRobert Mustacchi 
104*b142f83dSRobert Mustacchi 		part = strtok(NULL, ",");
105*b142f83dSRobert Mustacchi 	}
106*b142f83dSRobert Mustacchi 
107*b142f83dSRobert Mustacchi 	free(mode);
108*b142f83dSRobert Mustacchi 	if (m == 0) {
109*b142f83dSRobert Mustacchi 		fprintf(stderr, "failed to parse %s: no valid modes "
110*b142f83dSRobert Mustacchi 		    "specified\n", orig);
111*b142f83dSRobert Mustacchi 		exit(1);
112*b142f83dSRobert Mustacchi 	}
113*b142f83dSRobert Mustacchi 
114*b142f83dSRobert Mustacchi 	return (m);
115*b142f83dSRobert Mustacchi }
116*b142f83dSRobert Mustacchi 
117*b142f83dSRobert Mustacchi static void
118*b142f83dSRobert Mustacchi dlled_mode2str(mac_led_mode_t mode, char *buf, size_t len)
119*b142f83dSRobert Mustacchi {
120*b142f83dSRobert Mustacchi 	int i;
121*b142f83dSRobert Mustacchi 	boolean_t first = B_TRUE;
122*b142f83dSRobert Mustacchi 	mac_led_mode_t orig = mode;
123*b142f83dSRobert Mustacchi 
124*b142f83dSRobert Mustacchi 	for (i = 0; i < DLLED_MAP_NENTRIES; i++) {
125*b142f83dSRobert Mustacchi 		if ((mode & dlled_map[i].dlm_bits) != 0) {
126*b142f83dSRobert Mustacchi 			if (first) {
127*b142f83dSRobert Mustacchi 				first = B_FALSE;
128*b142f83dSRobert Mustacchi 			} else {
129*b142f83dSRobert Mustacchi 				(void) strlcat(buf, ",", len);
130*b142f83dSRobert Mustacchi 			}
131*b142f83dSRobert Mustacchi 			(void) strlcat(buf, dlled_map[i].dlm_name, len);
132*b142f83dSRobert Mustacchi 			mode &= ~dlled_map[i].dlm_bits;
133*b142f83dSRobert Mustacchi 		}
134*b142f83dSRobert Mustacchi 	}
135*b142f83dSRobert Mustacchi 
136*b142f83dSRobert Mustacchi 	if (mode != 0) {
137*b142f83dSRobert Mustacchi 		(void) snprintf(buf, len, "unknown mode: 0x%x\n", orig);
138*b142f83dSRobert Mustacchi 	}
139*b142f83dSRobert Mustacchi }
140*b142f83dSRobert Mustacchi 
141*b142f83dSRobert Mustacchi 
142*b142f83dSRobert Mustacchi static int
143*b142f83dSRobert Mustacchi dlled_set(const char *link, mac_led_mode_t mode)
144*b142f83dSRobert Mustacchi {
145*b142f83dSRobert Mustacchi 	datalink_id_t linkid;
146*b142f83dSRobert Mustacchi 	dladm_status_t status;
147*b142f83dSRobert Mustacchi 	dld_ioc_led_t dil;
148*b142f83dSRobert Mustacchi 
149*b142f83dSRobert Mustacchi 	if ((status = dladm_name2info(dlled_hdl, link, &linkid, NULL, NULL,
150*b142f83dSRobert Mustacchi 	    NULL)) != DLADM_STATUS_OK) {
151*b142f83dSRobert Mustacchi 		(void) fprintf(stderr, "failed to get link "
152*b142f83dSRobert Mustacchi 		    "id for link %s: %s\n", link,
153*b142f83dSRobert Mustacchi 		    dladm_status2str(status, dlled_dlerrmsg));
154*b142f83dSRobert Mustacchi 		return (1);
155*b142f83dSRobert Mustacchi 	}
156*b142f83dSRobert Mustacchi 
157*b142f83dSRobert Mustacchi 	bzero(&dil, sizeof (dil));
158*b142f83dSRobert Mustacchi 	dil.dil_linkid = linkid;
159*b142f83dSRobert Mustacchi 	dil.dil_active = mode;
160*b142f83dSRobert Mustacchi 
161*b142f83dSRobert Mustacchi 	if (ioctl(dladm_dld_fd(dlled_hdl), DLDIOC_SETLED, &dil) != 0) {
162*b142f83dSRobert Mustacchi 		(void) fprintf(stderr, "failed to set LED on "
163*b142f83dSRobert Mustacchi 		    "device %s: %s\n", link, strerror(errno));
164*b142f83dSRobert Mustacchi 		return (1);
165*b142f83dSRobert Mustacchi 	}
166*b142f83dSRobert Mustacchi 
167*b142f83dSRobert Mustacchi 	return (0);
168*b142f83dSRobert Mustacchi }
169*b142f83dSRobert Mustacchi 
170*b142f83dSRobert Mustacchi static int
171*b142f83dSRobert Mustacchi dlled_get_led(dladm_handle_t hdl, datalink_id_t linkid, void *arg)
172*b142f83dSRobert Mustacchi {
173*b142f83dSRobert Mustacchi 	dladm_status_t status;
174*b142f83dSRobert Mustacchi 	char name[MAXLINKNAMELEN];
175*b142f83dSRobert Mustacchi 	char supported[128], active[128];
176*b142f83dSRobert Mustacchi 	dld_ioc_led_t dil;
177*b142f83dSRobert Mustacchi 
178*b142f83dSRobert Mustacchi 	if ((status = dladm_datalink_id2info(hdl, linkid, NULL, NULL, NULL,
179*b142f83dSRobert Mustacchi 	    name, sizeof (name))) != DLADM_STATUS_OK) {
180*b142f83dSRobert Mustacchi 		(void) fprintf(stderr, "failed to get datalink name for link "
181*b142f83dSRobert Mustacchi 		    "%d: %s", linkid, dladm_status2str(status,
182*b142f83dSRobert Mustacchi 		    dlled_dlerrmsg));
183*b142f83dSRobert Mustacchi 		return (DLADM_WALK_CONTINUE);
184*b142f83dSRobert Mustacchi 	}
185*b142f83dSRobert Mustacchi 
186*b142f83dSRobert Mustacchi 
187*b142f83dSRobert Mustacchi 
188*b142f83dSRobert Mustacchi 	bzero(&dil, sizeof (dil));
189*b142f83dSRobert Mustacchi 	dil.dil_linkid = linkid;
190*b142f83dSRobert Mustacchi 
191*b142f83dSRobert Mustacchi 	if (ioctl(dladm_dld_fd(hdl), DLDIOC_GETLED, &dil) != 0) {
192*b142f83dSRobert Mustacchi 		(void) fprintf(stderr, "failed to get LED information for "
193*b142f83dSRobert Mustacchi 		    "device %s: %s\n", name, strerror(errno));
194*b142f83dSRobert Mustacchi 		return (DLADM_WALK_CONTINUE);
195*b142f83dSRobert Mustacchi 	}
196*b142f83dSRobert Mustacchi 
197*b142f83dSRobert Mustacchi 	active[0] = '\0';
198*b142f83dSRobert Mustacchi 	supported[0] = '\0';
199*b142f83dSRobert Mustacchi 	dlled_mode2str(dil.dil_active, active, sizeof (active));
200*b142f83dSRobert Mustacchi 	dlled_mode2str(dil.dil_supported, supported, sizeof (supported));
201*b142f83dSRobert Mustacchi 
202*b142f83dSRobert Mustacchi 	printf("%-20s %-12s %s\n", name, active, supported);
203*b142f83dSRobert Mustacchi 
204*b142f83dSRobert Mustacchi 	return (DLADM_WALK_CONTINUE);
205*b142f83dSRobert Mustacchi }
206*b142f83dSRobert Mustacchi 
207*b142f83dSRobert Mustacchi int
208*b142f83dSRobert Mustacchi main(int argc, char *argv[])
209*b142f83dSRobert Mustacchi {
210*b142f83dSRobert Mustacchi 	int c, ret;
211*b142f83dSRobert Mustacchi 	boolean_t opt_s = B_FALSE;
212*b142f83dSRobert Mustacchi 	mac_led_mode_t set_mode = 0;
213*b142f83dSRobert Mustacchi 	dladm_status_t status;
214*b142f83dSRobert Mustacchi 
215*b142f83dSRobert Mustacchi 	dlled_progname = basename(argv[0]);
216*b142f83dSRobert Mustacchi 
217*b142f83dSRobert Mustacchi 	while ((c = getopt(argc, argv, ":s:")) != -1) {
218*b142f83dSRobert Mustacchi 		switch (c) {
219*b142f83dSRobert Mustacchi 		case 's':
220*b142f83dSRobert Mustacchi 			opt_s = B_TRUE;
221*b142f83dSRobert Mustacchi 			set_mode = dlled_parse_mode(optarg);
222*b142f83dSRobert Mustacchi 			break;
223*b142f83dSRobert Mustacchi 		case ':':
224*b142f83dSRobert Mustacchi 			dlled_usage("option -%c requires an operand\n", optopt);
225*b142f83dSRobert Mustacchi 			return (2);
226*b142f83dSRobert Mustacchi 		case '?':
227*b142f83dSRobert Mustacchi 		default:
228*b142f83dSRobert Mustacchi 			dlled_usage("unknown option: -%c\n", optopt);
229*b142f83dSRobert Mustacchi 			return (2);
230*b142f83dSRobert Mustacchi 		}
231*b142f83dSRobert Mustacchi 	}
232*b142f83dSRobert Mustacchi 
233*b142f83dSRobert Mustacchi 	argc -= optind;
234*b142f83dSRobert Mustacchi 	argv += optind;
235*b142f83dSRobert Mustacchi 
236*b142f83dSRobert Mustacchi 	if (opt_s && argc > 1) {
237*b142f83dSRobert Mustacchi 		dlled_usage("-s only operates on a single datalink\n");
238*b142f83dSRobert Mustacchi 		return (2);
239*b142f83dSRobert Mustacchi 	}
240*b142f83dSRobert Mustacchi 
241*b142f83dSRobert Mustacchi 	if (opt_s && argc <= 0) {
242*b142f83dSRobert Mustacchi 		dlled_usage("-s requires a datalink\n");
243*b142f83dSRobert Mustacchi 		return (2);
244*b142f83dSRobert Mustacchi 	}
245*b142f83dSRobert Mustacchi 
246*b142f83dSRobert Mustacchi 	if ((status = dladm_open(&dlled_hdl)) != DLADM_STATUS_OK) {
247*b142f83dSRobert Mustacchi 		(void) fprintf(stderr, "failed to open /dev/dld: %s\n",
248*b142f83dSRobert Mustacchi 		    dladm_status2str(status, dlled_dlerrmsg));
249*b142f83dSRobert Mustacchi 		return (1);
250*b142f83dSRobert Mustacchi 	}
251*b142f83dSRobert Mustacchi 
252*b142f83dSRobert Mustacchi 	if (opt_s) {
253*b142f83dSRobert Mustacchi 		return (dlled_set(argv[0], set_mode));
254*b142f83dSRobert Mustacchi 	}
255*b142f83dSRobert Mustacchi 
256*b142f83dSRobert Mustacchi 	(void) printf("%-20s %-12s %s\n", "LINK", "ACTIVE", "SUPPORTED");
257*b142f83dSRobert Mustacchi 
258*b142f83dSRobert Mustacchi 	ret = 0;
259*b142f83dSRobert Mustacchi 	if (argc == 0) {
260*b142f83dSRobert Mustacchi 		(void) dladm_walk_datalink_id(dlled_get_led, dlled_hdl, NULL,
261*b142f83dSRobert Mustacchi 		    DATALINK_CLASS_PHYS, DATALINK_ANY_MEDIATYPE,
262*b142f83dSRobert Mustacchi 		    DLADM_OPT_ACTIVE);
263*b142f83dSRobert Mustacchi 	} else {
264*b142f83dSRobert Mustacchi 		int i, dlret;
265*b142f83dSRobert Mustacchi 		datalink_id_t linkid;
266*b142f83dSRobert Mustacchi 
267*b142f83dSRobert Mustacchi 		for (i = 0; i < argc; i++) {
268*b142f83dSRobert Mustacchi 			if ((status = dladm_name2info(dlled_hdl, argv[i],
269*b142f83dSRobert Mustacchi 			    &linkid, NULL, NULL, NULL)) != DLADM_STATUS_OK) {
270*b142f83dSRobert Mustacchi 				(void) fprintf(stderr, "failed to get link "
271*b142f83dSRobert Mustacchi 				    "id for link %s: %s\n", link,
272*b142f83dSRobert Mustacchi 				    dladm_status2str(status, dlled_dlerrmsg));
273*b142f83dSRobert Mustacchi 				return (1);
274*b142f83dSRobert Mustacchi 			}
275*b142f83dSRobert Mustacchi 
276*b142f83dSRobert Mustacchi 			dlret = dlled_get_led(dlled_hdl, linkid, NULL);
277*b142f83dSRobert Mustacchi 			if (dlret != DLADM_WALK_CONTINUE) {
278*b142f83dSRobert Mustacchi 				ret = 1;
279*b142f83dSRobert Mustacchi 				break;
280*b142f83dSRobert Mustacchi 			}
281*b142f83dSRobert Mustacchi 		}
282*b142f83dSRobert Mustacchi 	}
283*b142f83dSRobert Mustacchi 
284*b142f83dSRobert Mustacchi 	return (ret);
285*b142f83dSRobert Mustacchi }
286