diff options
author | Robert Mustacchi <rm@joyent.com> | 2015-10-13 16:51:06 +0000 |
---|---|---|
committer | Robert Mustacchi <rm@joyent.com> | 2015-10-15 16:04:14 +0000 |
commit | 5dccc1e9cb4177b448cdb81f0cce0b80b9446853 (patch) | |
tree | b90f8862a268de345c6d7fc2fd2f3dd3456d9301 | |
parent | 6157f50c211d531034b9f3b3229f3285df23cb32 (diff) | |
download | illumos-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-- | manifest | 1 | ||||
-rw-r--r-- | usr/src/uts/common/io/dls/dls_link.c | 71 | ||||
-rw-r--r-- | usr/src/uts/common/io/dls/dls_mgmt.c | 41 | ||||
-rw-r--r-- | usr/src/uts/common/io/vnic/vnic_dev.c | 69 | ||||
-rw-r--r-- | usr/src/uts/common/sys/Makefile | 1 | ||||
-rw-r--r-- | usr/src/uts/common/sys/dls.h | 3 | ||||
-rw-r--r-- | usr/src/uts/common/sys/dls_impl.h | 7 | ||||
-rw-r--r-- | usr/src/uts/common/sys/dls_mgmt.h | 1 | ||||
-rw-r--r-- | usr/src/uts/common/sys/sysevent.h | 3 | ||||
-rw-r--r-- | usr/src/uts/common/sys/sysevent/datalink.h | 54 | ||||
-rw-r--r-- | usr/src/uts/common/sys/sysevent/eventdefs.h | 4 | ||||
-rw-r--r-- | usr/src/uts/common/sys/vnic_impl.h | 3 |
12 files changed, 246 insertions, 12 deletions
@@ -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] |