summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorRobert Mustacchi <rm@joyent.com>2015-10-13 16:51:06 +0000
committerRobert Mustacchi <rm@joyent.com>2015-10-15 16:04:14 +0000
commit5dccc1e9cb4177b448cdb81f0cce0b80b9446853 (patch)
treeb90f8862a268de345c6d7fc2fd2f3dd3456d9301
parent6157f50c211d531034b9f3b3229f3285df23cb32 (diff)
downloadillumos-joyent-5dccc1e9cb4177b448cdb81f0cce0b80b9446853.tar.gz
OS-4840 Want system event for datalink state changes
OS-4839 Want ability to toggle etherstub link state Reviewed by: Jerry Jelinek <jerry.jelinek@joyent.com>
-rw-r--r--manifest1
-rw-r--r--usr/src/uts/common/io/dls/dls_link.c71
-rw-r--r--usr/src/uts/common/io/dls/dls_mgmt.c41
-rw-r--r--usr/src/uts/common/io/vnic/vnic_dev.c69
-rw-r--r--usr/src/uts/common/sys/Makefile1
-rw-r--r--usr/src/uts/common/sys/dls.h3
-rw-r--r--usr/src/uts/common/sys/dls_impl.h7
-rw-r--r--usr/src/uts/common/sys/dls_mgmt.h1
-rw-r--r--usr/src/uts/common/sys/sysevent.h3
-rw-r--r--usr/src/uts/common/sys/sysevent/datalink.h54
-rw-r--r--usr/src/uts/common/sys/sysevent/eventdefs.h4
-rw-r--r--usr/src/uts/common/sys/vnic_impl.h3
12 files changed, 246 insertions, 12 deletions
diff --git a/manifest b/manifest
index ce2f6dd8d1..e532e69fe6 100644
--- a/manifest
+++ b/manifest
@@ -4257,6 +4257,7 @@ f usr/include/sys/sysdc_impl.h 0644 root bin
d usr/include/sys/sysevent 0755 root bin
f usr/include/sys/sysevent.h 0644 root bin
f usr/include/sys/sysevent/ap_driver.h 0644 root bin
+f usr/include/sys/sysevent/datalink.h 0644 root bin
f usr/include/sys/sysevent/dev.h 0644 root bin
f usr/include/sys/sysevent/domain.h 0644 root bin
f usr/include/sys/sysevent/dr.h 0644 root bin
diff --git a/usr/src/uts/common/io/dls/dls_link.c b/usr/src/uts/common/io/dls/dls_link.c
index c5363e8194..4a735d870e 100644
--- a/usr/src/uts/common/io/dls/dls_link.c
+++ b/usr/src/uts/common/io/dls/dls_link.c
@@ -21,6 +21,7 @@
/*
* Copyright 2009 Sun Microsystems, Inc. All rights reserved.
* Use is subject to license terms.
+ * Copyright 2015 Joyent, Inc.
*/
/*
@@ -34,6 +35,9 @@
#include <sys/dld_impl.h>
#include <sys/sdt.h>
#include <sys/atomic.h>
+#include <sys/sysevent.h>
+#include <sys/sysevent/eventdefs.h>
+#include <sys/sysevent/datalink.h>
static kmem_cache_t *i_dls_link_cachep;
mod_hash_t *i_dls_link_hash;
@@ -579,6 +583,67 @@ drop:
freemsg(mp);
}
+/*
+ * We'd like to notify via sysevents that a link state change has occurred.
+ * There are a couple of challenges associated with this. The first is that if
+ * the link is flapping a lot, we may not see an accurate state when we launch
+ * the notification, we're told it changed, not what it changed to.
+ *
+ * The next problem is that all of the information that a user has associated
+ * with this device is the exact opposite of what we have on the dls_link_t. We
+ * have the name of the mac device, which has no bearing on what users see.
+ * Likewise, we don't have the datalink id either. So we're going to have to get
+ * this from dls.
+ *
+ * This is all further complicated by the fact that this could be going on in
+ * another thread at the same time as someone is tearing down the dls_link_t
+ * that we're associated with. We need to be careful not to grab the mac
+ * perimeter, otherwise we stand a good chance of deadlock.
+ */
+static void
+dls_link_notify(void *arg, mac_notify_type_t type)
+{
+ dls_link_t *dlp = arg;
+ dls_dl_handle_t dhp;
+ nvlist_t *nvp;
+ sysevent_t *event;
+ sysevent_id_t eid;
+
+ if (type != MAC_NOTE_LINK && type != MAC_NOTE_LOWLINK)
+ return;
+
+ /*
+ * If we can't find a devnet handle for this link, then there is no user
+ * knowable device for this at the moment and there's nothing we can
+ * really share with them that will make sense.
+ */
+ if (dls_devnet_hold_tmp_by_link(dlp, &dhp) != 0)
+ return;
+
+ /*
+ * Because we're attaching this nvlist_t to the sysevent, it'll get
+ * cleaned up when we call sysevent_free.
+ */
+ VERIFY(nvlist_alloc(&nvp, NV_UNIQUE_NAME, KM_SLEEP) == 0);
+ VERIFY(nvlist_add_int32(nvp, DATALINK_EV_LINK_ID,
+ dls_devnet_linkid(dhp)) == 0);
+ VERIFY(nvlist_add_string(nvp, DATALINK_EV_LINK_NAME,
+ dls_devnet_link(dhp)) == 0);
+ VERIFY(nvlist_add_int32(nvp, DATALINK_EV_ZONE_ID,
+ dls_devnet_getzid(dhp)) == 0);
+
+ dls_devnet_rele_tmp(dhp);
+
+ event = sysevent_alloc(EC_DATALINK, ESC_DATALINK_LINK_STATE,
+ ILLUMOS_KERN_PUB"dls", SE_SLEEP);
+ VERIFY(event != NULL);
+ (void) sysevent_attach_attributes(event, (sysevent_attr_list_t *)nvp);
+
+ (void) log_sysevent(event, SE_SLEEP, &eid);
+ sysevent_free(event);
+
+}
+
static void
i_dls_link_destroy(dls_link_t *dlp)
{
@@ -589,6 +654,9 @@ i_dls_link_destroy(dls_link_t *dlp)
/*
* Free the structure back to the cache.
*/
+ if (dlp->dl_mnh != NULL)
+ mac_notify_remove(dlp->dl_mnh, B_TRUE);
+
if (dlp->dl_mch != NULL)
mac_client_close(dlp->dl_mch, 0);
@@ -600,6 +668,7 @@ i_dls_link_destroy(dls_link_t *dlp)
dlp->dl_mh = NULL;
dlp->dl_mch = NULL;
dlp->dl_mip = NULL;
+ dlp->dl_mnh = NULL;
dlp->dl_unknowns = 0;
dlp->dl_nonip_cnt = 0;
dlp->dl_exclusive = B_FALSE;
@@ -641,6 +710,8 @@ i_dls_link_create(const char *name, dls_link_t **dlpp)
if (err != 0)
goto bail;
+ dlp->dl_mnh = mac_notify_add(dlp->dl_mh, dls_link_notify, dlp);
+
DTRACE_PROBE2(dls__primary__client, char *, dlp->dl_name, void *,
dlp->dl_mch);
diff --git a/usr/src/uts/common/io/dls/dls_mgmt.c b/usr/src/uts/common/io/dls/dls_mgmt.c
index 6111d62475..105c55c7ce 100644
--- a/usr/src/uts/common/io/dls/dls_mgmt.c
+++ b/usr/src/uts/common/io/dls/dls_mgmt.c
@@ -21,7 +21,7 @@
/*
* Copyright 2009 Sun Microsystems, Inc. All rights reserved.
* Use is subject to license terms.
- * Copyright (c) 2013 Joyent, Inc. All rights reserved.
+ * Copyright 2015 Joyent, Inc.
*/
/*
@@ -1091,6 +1091,39 @@ dls_devnet_unset(const char *macname, datalink_id_t *id, boolean_t wait)
return (0);
}
+/*
+ * This is a private hold routine used when we already have the dls_link_t, thus
+ * we know that it cannot go away.
+ */
+int
+dls_devnet_hold_tmp_by_link(dls_link_t *dlp, dls_dl_handle_t *ddhp)
+{
+ int err;
+ dls_devnet_t *ddp = NULL;
+
+ rw_enter(&i_dls_devnet_lock, RW_WRITER);
+ if ((err = mod_hash_find(i_dls_devnet_hash,
+ (mod_hash_key_t)dlp->dl_name, (mod_hash_val_t *)&ddp)) != 0) {
+ ASSERT(err == MH_ERR_NOTFOUND);
+ rw_exit(&i_dls_devnet_lock);
+ return (ENOENT);
+ }
+
+ mutex_enter(&ddp->dd_mutex);
+ ASSERT(ddp->dd_ref > 0);
+ if (ddp->dd_flags & DD_CONDEMNED) {
+ mutex_exit(&ddp->dd_mutex);
+ rw_exit(&i_dls_devnet_lock);
+ return (ENOENT);
+ }
+ ddp->dd_tref++;
+ mutex_exit(&ddp->dd_mutex);
+ rw_exit(&i_dls_devnet_lock);
+
+ *ddhp = ddp;
+ return (0);
+}
+
static int
dls_devnet_hold_common(datalink_id_t linkid, dls_devnet_t **ddpp,
boolean_t tmp_hold)
@@ -1913,6 +1946,12 @@ i_dls_devnet_destroy_iptun(datalink_id_t linkid)
}
const char *
+dls_devnet_link(dls_dl_handle_t ddh)
+{
+ return (ddh->dd_linkname);
+}
+
+const char *
dls_devnet_mac(dls_dl_handle_t ddh)
{
return (ddh->dd_mac);
diff --git a/usr/src/uts/common/io/vnic/vnic_dev.c b/usr/src/uts/common/io/vnic/vnic_dev.c
index c32d7f154b..045eea2829 100644
--- a/usr/src/uts/common/io/vnic/vnic_dev.c
+++ b/usr/src/uts/common/io/vnic/vnic_dev.c
@@ -369,6 +369,7 @@ vnic_dev_create(datalink_id_t vnic_id, datalink_id_t linkid,
bzero(vnic, sizeof (*vnic));
+ vnic->vn_ls = LINK_STATE_UNKNOWN;
vnic->vn_id = vnic_id;
vnic->vn_link_id = linkid;
vnic->vn_vrid = vrid;
@@ -579,11 +580,12 @@ vnic_dev_create(datalink_id_t vnic_id, datalink_id_t linkid,
vnic->vn_enabled = B_TRUE;
if (is_anchor) {
- mac_link_update(vnic->vn_mh, LINK_STATE_UP);
+ vnic->vn_ls = LINK_STATE_UP;
} else {
- mac_link_update(vnic->vn_mh,
- mac_client_stat_get(vnic->vn_mch, MAC_STAT_LINK_STATE));
+ vnic->vn_ls = mac_client_stat_get(vnic->vn_mch,
+ MAC_STAT_LINK_STATE);
}
+ mac_link_update(vnic->vn_mh, vnic->vn_ls);
rw_exit(&vnic_lock);
@@ -1091,6 +1093,35 @@ vnic_m_setprop(void *m_driver, const char *pr_name, mac_prop_id_t pr_num,
err = vnic_set_secondary_macs(vn, &msa);
break;
}
+ case MAC_PROP_PRIVATE: {
+ link_state_t ls;
+ long val, i;
+ const char *v;
+
+ if (vn->vn_link_id != DATALINK_INVALID_LINKID ||
+ strcmp(pr_name, "_linkstate") != 0) {
+ err = ENOTSUP;
+ break;
+ }
+
+ for (v = pr_val, i = 0; i < pr_valsize; i++, v++) {
+ if (*v == '\0')
+ break;
+ }
+ if (i == pr_valsize) {
+ err = EINVAL;
+ break;
+ }
+
+ (void) ddi_strtol(pr_val, (char **)NULL, 0, &val);
+ if (val != LINK_STATE_UP && val != LINK_STATE_DOWN) {
+ err = EINVAL;
+ break;
+ }
+ vn->vn_ls = val;
+ mac_link_update(vn->vn_mh, vn->vn_ls);
+ break;
+ }
default:
err = ENOTSUP;
break;
@@ -1116,6 +1147,18 @@ vnic_m_getprop(void *arg, const char *pr_name, mac_prop_id_t pr_num,
case MAC_PROP_SECONDARY_ADDRS:
ret = vnic_get_secondary_macs(vn, pr_valsize, pr_val);
break;
+ case MAC_PROP_PRIVATE:
+ if (vn->vn_link_id != DATALINK_INVALID_LINKID) {
+ ret = EINVAL;
+ break;
+ }
+
+ if (strcmp(pr_name, "_linkstate") != 0) {
+ ret = EINVAL;
+ break;
+ }
+ (void) snprintf(pr_val, pr_valsize, "%d", vn->vn_ls);
+ break;
default:
ret = EINVAL;
break;
@@ -1125,7 +1168,8 @@ vnic_m_getprop(void *arg, const char *pr_name, mac_prop_id_t pr_num,
}
/* ARGSUSED */
-static void vnic_m_propinfo(void *m_driver, const char *pr_name,
+static void
+vnic_m_propinfo(void *m_driver, const char *pr_name,
mac_prop_id_t pr_num, mac_prop_info_handle_t prh)
{
vnic_t *vn = m_driver;
@@ -1168,6 +1212,18 @@ static void vnic_m_propinfo(void *m_driver, const char *pr_name,
mac_perim_exit(mph);
}
break;
+ case MAC_PROP_PRIVATE:
+ if (vn->vn_link_id != DATALINK_INVALID_LINKID)
+ break;
+
+ if (strcmp(pr_name, "_linkstate") == 0) {
+ char buf[16];
+
+ mac_prop_info_set_perm(prh, MAC_PROP_PERM_RW);
+ (void) snprintf(buf, sizeof (buf), "%d", vn->vn_ls);
+ mac_prop_info_set_default_str(prh, buf);
+ }
+ break;
}
}
@@ -1240,8 +1296,9 @@ vnic_notify_cb(void *arg, mac_notify_type_t type)
break;
case MAC_NOTE_LINK:
- mac_link_update(vnic->vn_mh,
- mac_client_stat_get(vnic->vn_mch, MAC_STAT_LINK_STATE));
+ vnic->vn_ls = mac_client_stat_get(vnic->vn_mch,
+ MAC_STAT_LINK_STATE);
+ mac_link_update(vnic->vn_mh, vnic->vn_ls);
break;
default:
diff --git a/usr/src/uts/common/sys/Makefile b/usr/src/uts/common/sys/Makefile
index 67084249d6..95af828014 100644
--- a/usr/src/uts/common/sys/Makefile
+++ b/usr/src/uts/common/sys/Makefile
@@ -1006,6 +1006,7 @@ SATAGENHDRS= \
SYSEVENTHDRS= \
ap_driver.h \
+ datalink.h \
dev.h \
domain.h \
dr.h \
diff --git a/usr/src/uts/common/sys/dls.h b/usr/src/uts/common/sys/dls.h
index 8e99d0e9d8..155cad8bc9 100644
--- a/usr/src/uts/common/sys/dls.h
+++ b/usr/src/uts/common/sys/dls.h
@@ -21,7 +21,7 @@
/*
* Copyright 2009 Sun Microsystems, Inc. All rights reserved.
* Use is subject to license terms.
- * Copyright 2011 Joyent, Inc. All rights reserved.
+ * Copyright 2015 Joyent, Inc.
*/
#ifndef _SYS_DLS_H
@@ -126,6 +126,7 @@ extern int dls_devnet_hold_by_dev(dev_t, dls_dl_handle_t *);
extern void dls_devnet_rele(dls_dl_handle_t);
extern void dls_devnet_prop_task_wait(dls_dl_handle_t);
+extern const char *dls_devnet_link(dls_dl_handle_t);
extern const char *dls_devnet_mac(dls_dl_handle_t);
extern uint16_t dls_devnet_vid(dls_dl_handle_t);
extern datalink_id_t dls_devnet_linkid(dls_dl_handle_t);
diff --git a/usr/src/uts/common/sys/dls_impl.h b/usr/src/uts/common/sys/dls_impl.h
index d502b36a2d..329f8dd08e 100644
--- a/usr/src/uts/common/sys/dls_impl.h
+++ b/usr/src/uts/common/sys/dls_impl.h
@@ -21,7 +21,7 @@
/*
* Copyright 2009 Sun Microsystems, Inc. All rights reserved.
* Use is subject to license terms.
- * Copyright 2011 Joyent, Inc. All rights reserved.
+ * Copyright 2015 Joyent, Inc.
*/
#ifndef _SYS_DLS_IMPL_H
@@ -47,11 +47,12 @@ typedef struct dls_multicst_addr_s {
} dls_multicst_addr_t;
struct dls_link_s { /* Protected by */
- char dl_name[MAXNAMELEN]; /* SL */
+ char dl_name[MAXNAMELEN]; /* RO */
uint_t dl_ddi_instance; /* SL */
mac_handle_t dl_mh; /* SL */
mac_client_handle_t dl_mch; /* SL */
mac_unicast_handle_t dl_mah; /* SL */
+ mac_notify_handle_t dl_mnh; /* SL */
const mac_info_t *dl_mip; /* SL */
uint_t dl_ref; /* SL */
mod_hash_t *dl_str_hash; /* SL, modhash lock */
@@ -106,6 +107,8 @@ extern int dls_devnet_open_by_dev(dev_t, dls_link_t **,
extern int dls_devnet_hold_link(datalink_id_t, dls_dl_handle_t *,
dls_link_t **);
extern void dls_devnet_rele_link(dls_dl_handle_t, dls_link_t *);
+extern int dls_devnet_hold_tmp_by_link(dls_link_t *,
+ dls_dl_handle_t *);
extern void dls_init(void);
extern int dls_fini(void);
diff --git a/usr/src/uts/common/sys/dls_mgmt.h b/usr/src/uts/common/sys/dls_mgmt.h
index f747e29def..214e225ac9 100644
--- a/usr/src/uts/common/sys/dls_mgmt.h
+++ b/usr/src/uts/common/sys/dls_mgmt.h
@@ -229,6 +229,7 @@ typedef struct dlmgmt_getattr_retval_s {
char lr_attrval[MAXLINKATTRVALLEN];
} dlmgmt_getattr_retval_t;
+
#ifdef __cplusplus
}
#endif
diff --git a/usr/src/uts/common/sys/sysevent.h b/usr/src/uts/common/sys/sysevent.h
index 2b26441973..5dcaa69c6d 100644
--- a/usr/src/uts/common/sys/sysevent.h
+++ b/usr/src/uts/common/sys/sysevent.h
@@ -21,6 +21,7 @@
/*
* Copyright (c) 2000, 2010, Oracle and/or its affiliates. All rights reserved.
+ * Copyright 2015 Joyent, Inc.
*/
#ifndef _SYS_SYSEVENT_H
@@ -74,10 +75,12 @@ extern "C" {
#define SE_KERN_PID 0
#define SUNW_VENDOR "SUNW"
+#define ILLUMOS_VENDOR "ILLUMOS"
#define SE_USR_PUB "usr:"
#define SE_KERN_PUB "kern:"
#define SUNW_KERN_PUB SUNW_VENDOR":"SE_KERN_PUB
#define SUNW_USR_PUB SUNW_VENDOR":"SE_USR_PUB
+#define ILLUMOS_KERN_PUB ILLUMOS_VENDOR":"SE_KERN_PUB
/*
* Event header and attribute value limits
diff --git a/usr/src/uts/common/sys/sysevent/datalink.h b/usr/src/uts/common/sys/sysevent/datalink.h
new file mode 100644
index 0000000000..592ef5bdde
--- /dev/null
+++ b/usr/src/uts/common/sys/sysevent/datalink.h
@@ -0,0 +1,54 @@
+/*
+ * 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 2015 Joyent, Inc.
+ */
+
+#ifndef _SYS_SYSEVENT_DATALINK_H
+#define _SYS_SYSEVENT_DATALINK_H
+
+/*
+ * Datalink System Event payloads
+ */
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/*
+ * Event schema for EC_DATALINK_LINK_STATE
+ *
+ * Event Class - EC_DATALINK
+ * Event Sub-Class - EC_DATALINK_LINK_STATE
+ *
+ * Attribute Name - DATALINK_EV_LINK_NAME
+ * Attribute Type - SE_DATA_TYPE_STRING
+ * Attribute Value - [Name of the datalink]
+ *
+ * Attribute Name - DATALINK_EV_LINK_ID
+ * Attribute Type - SE_DATA_TYPE_INT32
+ * Attribute Value - [datalink_id_t for the device]
+ *
+ * Attribute Name - DATALINK_EV_ZONE_ID
+ * Attribute Type - SE_DATA_TYPE_INT32
+ * Attribute Value - [zoneid_t of the zone the datalink is in]
+ */
+
+#define DATALINK_EV_LINK_NAME "link"
+#define DATALINK_EV_LINK_ID "linkid"
+#define DATALINK_EV_ZONE_ID "zone"
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* _SYS_SYSEVENT_DATALINK_H */
diff --git a/usr/src/uts/common/sys/sysevent/eventdefs.h b/usr/src/uts/common/sys/sysevent/eventdefs.h
index 9c6907a08a..b47b5e2545 100644
--- a/usr/src/uts/common/sys/sysevent/eventdefs.h
+++ b/usr/src/uts/common/sys/sysevent/eventdefs.h
@@ -265,9 +265,11 @@ extern "C" {
#define ESC_ZFS_POOL_REGUID "ESC_ZFS_pool_reguid"
/*
- * datalink subclass definitions.
+ * datalink subclass definitions. Supporting attributes for datalink state found
+ * in sys/sysevent/datalink.h.
*/
#define ESC_DATALINK_PHYS_ADD "ESC_datalink_phys_add" /* new physical link */
+#define ESC_DATALINK_LINK_STATE "ESC_datalink_link_state" /* link state */
/*
* VRRP subclass definitions. Supporting attributes (name/value paris) are
diff --git a/usr/src/uts/common/sys/vnic_impl.h b/usr/src/uts/common/sys/vnic_impl.h
index 7e50091347..1a91158da6 100644
--- a/usr/src/uts/common/sys/vnic_impl.h
+++ b/usr/src/uts/common/sys/vnic_impl.h
@@ -21,7 +21,7 @@
/*
* Copyright 2010 Sun Microsystems, Inc. All rights reserved.
* Use is subject to license terms.
- * Copyright 2014 Joyent, Inc. All rights reserved.
+ * Copyright 2015 Joyent, Inc.
*/
#ifndef _SYS_VNIC_IMPL_H
@@ -65,6 +65,7 @@ typedef struct vnic_s {
uint32_t vn_hcksum_txflags;
uint32_t vn_mtu;
+ link_state_t vn_ls;
} vnic_t;
#define vn_mch vn_mc_handles[0]