summaryrefslogtreecommitdiff
path: root/usr/src/cmd/dlutil/dlled.c
diff options
context:
space:
mode:
Diffstat (limited to 'usr/src/cmd/dlutil/dlled.c')
-rw-r--r--usr/src/cmd/dlutil/dlled.c285
1 files changed, 285 insertions, 0 deletions
diff --git a/usr/src/cmd/dlutil/dlled.c b/usr/src/cmd/dlutil/dlled.c
new file mode 100644
index 0000000000..65f2cdc6f7
--- /dev/null
+++ b/usr/src/cmd/dlutil/dlled.c
@@ -0,0 +1,285 @@
+/*
+ * This file and its contents are supplied under the terms of the
+ * Common Development and Distribution License ("CDDL"), version 1.0.
+ * You may only use this file in accordance with the terms of version
+ * 1.0 of the CDDL.
+ *
+ * A full copy of the text of the CDDL should have accompanied this
+ * source. A copy of the CDDL is also available via the Internet at
+ * http://www.illumos.org/license/CDDL.
+ */
+
+/*
+ * Copyright (c) 2017, Joyent, Inc.
+ */
+
+/*
+ * Private utility to get and set LED information on NICs. This should really
+ * all be integrated into FM. Until we have figured out that plumbing, this
+ * allows us to have a little something that we can use to drive work.
+ */
+
+#include <unistd.h>
+#include <stdio.h>
+#include <stdarg.h>
+#include <libgen.h>
+#include <string.h>
+#include <stdlib.h>
+#include <errno.h>
+#include <strings.h>
+
+#include <libdladm.h>
+#include <libdllink.h>
+#include <sys/mac.h>
+#include <sys/dld.h>
+#include <sys/dld_ioc.h>
+
+static const char *dlled_progname;
+static dladm_handle_t dlled_hdl;
+static char dlled_dlerrmsg[DLADM_STRSIZE];
+
+typedef struct dlled_led_map {
+ const char *dlm_name;
+ mac_led_mode_t dlm_bits;
+} dlled_led_map_t;
+
+static dlled_led_map_t dlled_map[] = {
+ { "default", MAC_LED_DEFAULT },
+ { "off", MAC_LED_OFF },
+ { "on", MAC_LED_ON },
+ { "ident", MAC_LED_IDENT }
+};
+
+#define DLLED_MAP_NENTRIES \
+ (sizeof (dlled_map) / sizeof (dlled_led_map_t))
+
+static void
+dlled_usage(const char *fmt, ...)
+{
+ if (fmt != NULL) {
+ va_list ap;
+
+ (void) fprintf(stderr, "%s: ", dlled_progname);
+ va_start(ap, fmt);
+ (void) vfprintf(stderr, fmt, ap);
+ va_end(ap);
+ }
+
+ (void) fprintf(stderr, "Usage: %s [-s mode] [link]\n"
+ "\n"
+ "\t-s mode set LED to mode\n",
+ dlled_progname);
+}
+
+static mac_led_mode_t
+dlled_parse_mode(const char *orig)
+{
+ char *mode;
+ char *part;
+ mac_led_mode_t m = 0;
+
+ mode = strdup(orig);
+ if (orig == NULL) {
+ fprintf(stderr, "failed to allocate memory to dup led "
+ "mode: %s\n", strerror(errno));
+ exit(1);
+ }
+
+ part = strtok(mode, ",");
+ while (part != NULL) {
+ int i;
+
+ for (i = 0; i < DLLED_MAP_NENTRIES; i++) {
+ if (strcmp(dlled_map[i].dlm_name, part) == 0) {
+ m |= dlled_map[i].dlm_bits;
+ break;
+ }
+ }
+
+ if (i == DLLED_MAP_NENTRIES) {
+ fprintf(stderr, "unknown LED mode: %s\n", part);
+ exit(1);
+ }
+
+ part = strtok(NULL, ",");
+ }
+
+ free(mode);
+ if (m == 0) {
+ fprintf(stderr, "failed to parse %s: no valid modes "
+ "specified\n", orig);
+ exit(1);
+ }
+
+ return (m);
+}
+
+static void
+dlled_mode2str(mac_led_mode_t mode, char *buf, size_t len)
+{
+ int i;
+ boolean_t first = B_TRUE;
+ mac_led_mode_t orig = mode;
+
+ for (i = 0; i < DLLED_MAP_NENTRIES; i++) {
+ if ((mode & dlled_map[i].dlm_bits) != 0) {
+ if (first) {
+ first = B_FALSE;
+ } else {
+ (void) strlcat(buf, ",", len);
+ }
+ (void) strlcat(buf, dlled_map[i].dlm_name, len);
+ mode &= ~dlled_map[i].dlm_bits;
+ }
+ }
+
+ if (mode != 0) {
+ (void) snprintf(buf, len, "unknown mode: 0x%x\n", orig);
+ }
+}
+
+
+static int
+dlled_set(const char *link, mac_led_mode_t mode)
+{
+ datalink_id_t linkid;
+ dladm_status_t status;
+ dld_ioc_led_t dil;
+
+ if ((status = dladm_name2info(dlled_hdl, link, &linkid, NULL, NULL,
+ NULL)) != DLADM_STATUS_OK) {
+ (void) fprintf(stderr, "failed to get link "
+ "id for link %s: %s\n", link,
+ dladm_status2str(status, dlled_dlerrmsg));
+ return (1);
+ }
+
+ bzero(&dil, sizeof (dil));
+ dil.dil_linkid = linkid;
+ dil.dil_active = mode;
+
+ if (ioctl(dladm_dld_fd(dlled_hdl), DLDIOC_SETLED, &dil) != 0) {
+ (void) fprintf(stderr, "failed to set LED on "
+ "device %s: %s\n", link, strerror(errno));
+ return (1);
+ }
+
+ return (0);
+}
+
+static int
+dlled_get_led(dladm_handle_t hdl, datalink_id_t linkid, void *arg)
+{
+ dladm_status_t status;
+ char name[MAXLINKNAMELEN];
+ char supported[128], active[128];
+ dld_ioc_led_t dil;
+
+ if ((status = dladm_datalink_id2info(hdl, linkid, NULL, NULL, NULL,
+ name, sizeof (name))) != DLADM_STATUS_OK) {
+ (void) fprintf(stderr, "failed to get datalink name for link "
+ "%d: %s", linkid, dladm_status2str(status,
+ dlled_dlerrmsg));
+ return (DLADM_WALK_CONTINUE);
+ }
+
+
+
+ bzero(&dil, sizeof (dil));
+ dil.dil_linkid = linkid;
+
+ if (ioctl(dladm_dld_fd(hdl), DLDIOC_GETLED, &dil) != 0) {
+ (void) fprintf(stderr, "failed to get LED information for "
+ "device %s: %s\n", name, strerror(errno));
+ return (DLADM_WALK_CONTINUE);
+ }
+
+ active[0] = '\0';
+ supported[0] = '\0';
+ dlled_mode2str(dil.dil_active, active, sizeof (active));
+ dlled_mode2str(dil.dil_supported, supported, sizeof (supported));
+
+ printf("%-20s %-12s %s\n", name, active, supported);
+
+ return (DLADM_WALK_CONTINUE);
+}
+
+int
+main(int argc, char *argv[])
+{
+ int c, ret;
+ boolean_t opt_s = B_FALSE;
+ mac_led_mode_t set_mode = 0;
+ dladm_status_t status;
+
+ dlled_progname = basename(argv[0]);
+
+ while ((c = getopt(argc, argv, ":s:")) != -1) {
+ switch (c) {
+ case 's':
+ opt_s = B_TRUE;
+ set_mode = dlled_parse_mode(optarg);
+ break;
+ case ':':
+ dlled_usage("option -%c requires an operand\n", optopt);
+ return (2);
+ case '?':
+ default:
+ dlled_usage("unknown option: -%c\n", optopt);
+ return (2);
+ }
+ }
+
+ argc -= optind;
+ argv += optind;
+
+ if (opt_s && argc > 1) {
+ dlled_usage("-s only operates on a single datalink\n");
+ return (2);
+ }
+
+ if (opt_s && argc <= 0) {
+ dlled_usage("-s requires a datalink\n");
+ return (2);
+ }
+
+ if ((status = dladm_open(&dlled_hdl)) != DLADM_STATUS_OK) {
+ (void) fprintf(stderr, "failed to open /dev/dld: %s\n",
+ dladm_status2str(status, dlled_dlerrmsg));
+ return (1);
+ }
+
+ if (opt_s) {
+ return (dlled_set(argv[0], set_mode));
+ }
+
+ (void) printf("%-20s %-12s %s\n", "LINK", "ACTIVE", "SUPPORTED");
+
+ ret = 0;
+ if (argc == 0) {
+ (void) dladm_walk_datalink_id(dlled_get_led, dlled_hdl, NULL,
+ DATALINK_CLASS_PHYS, DATALINK_ANY_MEDIATYPE,
+ DLADM_OPT_ACTIVE);
+ } else {
+ int i, dlret;
+ datalink_id_t linkid;
+
+ for (i = 0; i < argc; i++) {
+ if ((status = dladm_name2info(dlled_hdl, argv[i],
+ &linkid, NULL, NULL, NULL)) != DLADM_STATUS_OK) {
+ (void) fprintf(stderr, "failed to get link "
+ "id for link %s: %s\n", link,
+ dladm_status2str(status, dlled_dlerrmsg));
+ return (1);
+ }
+
+ dlret = dlled_get_led(dlled_hdl, linkid, NULL);
+ if (dlret != DLADM_WALK_CONTINUE) {
+ ret = 1;
+ break;
+ }
+ }
+ }
+
+ return (ret);
+}