summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
author <Eric.Cheng@Sun.COM>2009-11-09 20:01:32 -0800
committer <Eric.Cheng@Sun.COM>2009-11-09 20:01:32 -0800
commit8d4cf8d8d2965ea43bccdc838f15c18634fee02d (patch)
tree87ace970c3bc9c66d8b1d5fbe22559f3bc858ba4
parentbd9f6899328e19cbb74e3ad02f5c32002285887e (diff)
downloadillumos-gate-8d4cf8d8d2965ea43bccdc838f15c18634fee02d.tar.gz
6890826 DLPI consumers using IP receive only broadcast messages
6888482 failure to initialize link props should not be ignored
-rw-r--r--usr/src/cmd/dlmgmtd/dlmgmt_door.c14
-rw-r--r--usr/src/lib/libdladm/common/linkprop.c16
-rw-r--r--usr/src/uts/common/io/dld/dld_proto.c13
-rw-r--r--usr/src/uts/common/io/dld/dld_str.c1
-rw-r--r--usr/src/uts/common/io/dls/dls.c11
-rw-r--r--usr/src/uts/common/io/dls/dls_link.c1
-rw-r--r--usr/src/uts/common/io/mac/mac_client.c23
-rw-r--r--usr/src/uts/common/io/mac/mac_sched.c12
-rw-r--r--usr/src/uts/common/sys/dld_impl.h1
-rw-r--r--usr/src/uts/common/sys/dls_impl.h1
-rw-r--r--usr/src/uts/common/sys/mac_client_impl.h1
-rw-r--r--usr/src/uts/common/sys/mac_client_priv.h2
12 files changed, 75 insertions, 21 deletions
diff --git a/usr/src/cmd/dlmgmtd/dlmgmt_door.c b/usr/src/cmd/dlmgmtd/dlmgmt_door.c
index ad59cfe190..904dcbbd98 100644
--- a/usr/src/cmd/dlmgmtd/dlmgmt_door.c
+++ b/usr/src/cmd/dlmgmtd/dlmgmt_door.c
@@ -1053,8 +1053,18 @@ dlmgmt_upcall_linkprop_init(void *argp, void *retp, zoneid_t zoneid,
err = dlmgmt_checkprivs(linkp->ll_class, cred);
dlmgmt_table_unlock();
- if (err == 0)
- err = dladm_init_linkprop(dld_handle, lip->ld_linkid, B_TRUE);
+ if (err == 0) {
+ dladm_status_t s;
+ char buf[DLADM_STRSIZE];
+
+ s = dladm_init_linkprop(dld_handle, lip->ld_linkid, B_TRUE);
+ if (s != DLADM_STATUS_OK) {
+ dlmgmt_log(LOG_WARNING,
+ "linkprop initialization failed on link %d: %s",
+ lip->ld_linkid, dladm_status2str(s, buf));
+ err = EINVAL;
+ }
+ }
retvalp->lr_err = err;
}
diff --git a/usr/src/lib/libdladm/common/linkprop.c b/usr/src/lib/libdladm/common/linkprop.c
index eca1aecd7f..bd4190b159 100644
--- a/usr/src/lib/libdladm/common/linkprop.c
+++ b/usr/src/lib/libdladm/common/linkprop.c
@@ -1211,8 +1211,9 @@ static int
i_dladm_init_one_prop(dladm_handle_t handle, datalink_id_t linkid,
const char *prop_name, void *arg)
{
- char *buf, **propvals;
- uint_t i, valcnt = DLADM_MAX_PROP_VALCNT;
+ char *buf, **propvals;
+ uint_t i, valcnt = DLADM_MAX_PROP_VALCNT;
+ dladm_status_t status, *retval = arg;
if ((buf = malloc((sizeof (char *) + DLADM_PROP_VAL_MAX) *
DLADM_MAX_PROP_VALCNT)) == NULL) {
@@ -1231,8 +1232,10 @@ i_dladm_init_one_prop(dladm_handle_t handle, datalink_id_t linkid,
goto done;
}
- (void) dladm_set_linkprop(handle, linkid, prop_name, propvals, valcnt,
- DLADM_OPT_ACTIVE);
+ status = dladm_set_linkprop(handle, linkid, prop_name, propvals,
+ valcnt, DLADM_OPT_ACTIVE);
+ if (status != DLADM_STATUS_OK)
+ *retval = status;
done:
if (buf != NULL)
@@ -1263,6 +1266,7 @@ dladm_status_t
dladm_init_linkprop(dladm_handle_t handle, datalink_id_t linkid,
boolean_t any_media)
{
+ dladm_status_t status = DLADM_STATUS_OK;
datalink_media_t dmedia;
uint32_t media;
@@ -1275,10 +1279,10 @@ dladm_init_linkprop(dladm_handle_t handle, datalink_id_t linkid,
((dladm_datalink_id2info(handle, linkid, NULL, NULL, &media, NULL,
0) == DLADM_STATUS_OK) &&
DATALINK_MEDIA_ACCEPTED(dmedia, media))) {
- (void) dladm_walk_linkprop(handle, linkid, NULL,
+ (void) dladm_walk_linkprop(handle, linkid, &status,
i_dladm_init_one_prop);
}
- return (DLADM_STATUS_OK);
+ return (status);
}
/* ARGSUSED */
diff --git a/usr/src/uts/common/io/dld/dld_proto.c b/usr/src/uts/common/io/dld/dld_proto.c
index ecf8e27afd..338a1c96d0 100644
--- a/usr/src/uts/common/io/dld/dld_proto.c
+++ b/usr/src/uts/common/io/dld/dld_proto.c
@@ -45,6 +45,7 @@ static proto_reqfunc_t proto_info_req, proto_attach_req, proto_detach_req,
static void proto_capability_advertise(dld_str_t *, mblk_t *);
static int dld_capab_poll_disable(dld_str_t *, dld_capab_poll_t *);
+static boolean_t check_mod_above(queue_t *, const char *);
#define DL_ACK_PENDING(state) \
((state) == DL_ATTACH_PENDING || \
@@ -446,6 +447,9 @@ proto_bind_req(dld_str_t *dsp, mblk_t *mp)
* Bind the channel such that it can receive packets.
*/
sap = dlp->dl_sap;
+ dsp->ds_nonip = !check_mod_above(dsp->ds_rq, "ip") &&
+ !check_mod_above(dsp->ds_rq, "arp");
+
err = dls_bind(dsp, sap);
if (err != 0) {
switch (err) {
@@ -993,14 +997,14 @@ failed:
}
static boolean_t
-check_ip_above(queue_t *q)
+check_mod_above(queue_t *q, const char *mod)
{
queue_t *next_q;
boolean_t ret = B_TRUE;
claimstr(q);
next_q = q->q_next;
- if (strcmp(next_q->q_qinfo->qi_minfo->mi_idname, "ip") != 0)
+ if (strcmp(next_q->q_qinfo->qi_minfo->mi_idname, mod) != 0)
ret = B_FALSE;
releasestr(q);
return (ret);
@@ -1506,7 +1510,8 @@ dld_capab(dld_str_t *dsp, uint_t type, void *data, uint_t flags)
* completes. So we limit the check to DLD_ENABLE case.
*/
if ((flags == DLD_ENABLE && type != DLD_CAPAB_PERIM) &&
- (dsp->ds_sap != ETHERTYPE_IP || !check_ip_above(dsp->ds_rq))) {
+ (dsp->ds_sap != ETHERTYPE_IP ||
+ !check_mod_above(dsp->ds_rq, "ip"))) {
return (ENOTSUP);
}
@@ -1593,7 +1598,7 @@ proto_capability_advertise(dld_str_t *dsp, mblk_t *mp)
/*
* Direct capability negotiation interface between IP and DLD
*/
- if (dsp->ds_sap == ETHERTYPE_IP && check_ip_above(dsp->ds_rq)) {
+ if (dsp->ds_sap == ETHERTYPE_IP && check_mod_above(dsp->ds_rq, "ip")) {
dld_capable = B_TRUE;
subsize += sizeof (dl_capability_sub_t) +
sizeof (dl_capab_dld_t);
diff --git a/usr/src/uts/common/io/dld/dld_str.c b/usr/src/uts/common/io/dld/dld_str.c
index 75845f3df0..63d2bb6511 100644
--- a/usr/src/uts/common/io/dld/dld_str.c
+++ b/usr/src/uts/common/io/dld/dld_str.c
@@ -681,6 +681,7 @@ dld_str_destroy(dld_str_t *dsp)
dsp->ds_passivestate = DLD_UNINITIALIZED;
dsp->ds_mode = DLD_UNITDATA;
dsp->ds_native = B_FALSE;
+ dsp->ds_nonip = B_FALSE;
ASSERT(dsp->ds_datathr_cnt == 0);
ASSERT(dsp->ds_pending_head == NULL);
diff --git a/usr/src/uts/common/io/dls/dls.c b/usr/src/uts/common/io/dls/dls.c
index 4cf2efcccf..e29b1ee6ac 100644
--- a/usr/src/uts/common/io/dls/dls.c
+++ b/usr/src/uts/common/io/dls/dls.c
@@ -188,6 +188,11 @@ dls_bind(dld_str_t *dsp, uint32_t sap)
err = mac_promisc_add(dsp->ds_mch,
MAC_CLIENT_PROMISC_ALL, dls_rx_vlan_promisc, dsp,
&dsp->ds_vlan_mph, MAC_PROMISC_FLAGS_NO_PHYS);
+
+ if (err == 0 && dsp->ds_nonip &&
+ dsp->ds_dlp->dl_nonip_cnt++ == 0)
+ mac_rx_bypass_disable(dsp->ds_mch);
+
return (err);
}
@@ -196,6 +201,9 @@ dls_bind(dld_str_t *dsp, uint32_t sap)
* dls_link_t.
*/
dls_link_add(dsp->ds_dlp, dls_sap, dsp);
+ if (dsp->ds_nonip && dsp->ds_dlp->dl_nonip_cnt++ == 0)
+ mac_rx_bypass_disable(dsp->ds_mch);
+
return (0);
}
@@ -204,6 +212,9 @@ dls_unbind(dld_str_t *dsp)
{
ASSERT(MAC_PERIM_HELD(dsp->ds_mh));
+ if (dsp->ds_nonip && --dsp->ds_dlp->dl_nonip_cnt == 0)
+ mac_rx_bypass_enable(dsp->ds_mch);
+
/*
* For VLAN SAP, there was a promisc handle registered when dls_bind.
* When unbind this dls link, we need to remove the promisc handle.
diff --git a/usr/src/uts/common/io/dls/dls_link.c b/usr/src/uts/common/io/dls/dls_link.c
index ed2746954f..d88005d57f 100644
--- a/usr/src/uts/common/io/dls/dls_link.c
+++ b/usr/src/uts/common/io/dls/dls_link.c
@@ -603,6 +603,7 @@ i_dls_link_destroy(dls_link_t *dlp)
dlp->dl_mch = NULL;
dlp->dl_mip = NULL;
dlp->dl_unknowns = 0;
+ dlp->dl_nonip_cnt = 0;
kmem_cache_free(i_dls_link_cachep, dlp);
}
diff --git a/usr/src/uts/common/io/mac/mac_client.c b/usr/src/uts/common/io/mac/mac_client.c
index 0d1669b40e..421c3e9bbd 100644
--- a/usr/src/uts/common/io/mac/mac_client.c
+++ b/usr/src/uts/common/io/mac/mac_client.c
@@ -1394,7 +1394,7 @@ mac_client_close(mac_client_handle_t mch, uint16_t flags)
}
/*
- * Enable bypass for the specified MAC client.
+ * Set the rx bypass receive callback.
*/
boolean_t
mac_rx_bypass_set(mac_client_handle_t mch, mac_direct_rx_t rx_fn, void *arg1)
@@ -1418,11 +1418,25 @@ mac_rx_bypass_set(mac_client_handle_t mch, mac_direct_rx_t rx_fn, void *arg1)
*/
mcip->mci_direct_rx_fn = rx_fn;
mcip->mci_direct_rx_arg = arg1;
- mcip->mci_state_flags |= MCIS_CLIENT_POLL_CAPABLE;
return (B_TRUE);
}
/*
+ * Enable/Disable rx bypass. By default, bypass is assumed to be enabled.
+ */
+void
+mac_rx_bypass_enable(mac_client_handle_t mch)
+{
+ ((mac_client_impl_t *)mch)->mci_state_flags &= ~MCIS_RX_BYPASS_DISABLE;
+}
+
+void
+mac_rx_bypass_disable(mac_client_handle_t mch)
+{
+ ((mac_client_impl_t *)mch)->mci_state_flags |= MCIS_RX_BYPASS_DISABLE;
+}
+
+/*
* Set the receive callback for the specified MAC client. There can be
* at most one such callback per MAC client.
*/
@@ -3141,9 +3155,6 @@ mac_resource_set_common(mac_client_handle_t mch, mac_resource_add_t add,
mcip->mci_resource_restart = restart;
mcip->mci_resource_bind = bind;
mcip->mci_resource_arg = arg;
-
- if (arg == NULL)
- mcip->mci_state_flags &= ~MCIS_CLIENT_POLL_CAPABLE;
}
void
@@ -3168,6 +3179,7 @@ mac_client_poll_enable(mac_client_handle_t mch)
flent = mcip->mci_flent;
ASSERT(flent != NULL);
+ mcip->mci_state_flags |= MCIS_CLIENT_POLL_CAPABLE;
for (i = 0; i < flent->fe_rx_srs_cnt; i++) {
mac_srs = (mac_soft_ring_set_t *)flent->fe_rx_srs[i];
ASSERT(mac_srs->srs_mcip == mcip);
@@ -3190,6 +3202,7 @@ mac_client_poll_disable(mac_client_handle_t mch)
flent = mcip->mci_flent;
ASSERT(flent != NULL);
+ mcip->mci_state_flags &= ~MCIS_CLIENT_POLL_CAPABLE;
for (i = 0; i < flent->fe_rx_srs_cnt; i++) {
mac_srs = (mac_soft_ring_set_t *)flent->fe_rx_srs[i];
ASSERT(mac_srs->srs_mcip == mcip);
diff --git a/usr/src/uts/common/io/mac/mac_sched.c b/usr/src/uts/common/io/mac/mac_sched.c
index 74de880f3d..ff3cba81ed 100644
--- a/usr/src/uts/common/io/mac/mac_sched.c
+++ b/usr/src/uts/common/io/mac/mac_sched.c
@@ -550,9 +550,11 @@ mac_rx_srs_proto_fanout(mac_soft_ring_set_t *mac_srs, mblk_t *head)
/*
* Special clients (eg. VLAN, non ether, etc) need DLS
* processing in the Rx path. SRST_DLS_BYPASS will be clear for
- * such SRSs.
+ * such SRSs. Another way of disabling bypass is to set the
+ * MCIS_RX_BYPASS_DISABLE flag.
*/
- dls_bypass = ((mac_srs->srs_type & SRST_DLS_BYPASS) != 0);
+ dls_bypass = ((mac_srs->srs_type & SRST_DLS_BYPASS) != 0) &&
+ ((mcip->mci_state_flags & MCIS_RX_BYPASS_DISABLE) == 0);
bzero(headmp, MAX_SR_TYPES * sizeof (mblk_t *));
bzero(tailmp, MAX_SR_TYPES * sizeof (mblk_t *));
@@ -933,9 +935,11 @@ mac_rx_srs_fanout(mac_soft_ring_set_t *mac_srs, mblk_t *head)
/*
* Special clients (eg. VLAN, non ether, etc) need DLS
* processing in the Rx path. SRST_DLS_BYPASS will be clear for
- * such SRSs.
+ * such SRSs. Another way of disabling bypass is to set the
+ * MCIS_RX_BYPASS_DISABLE flag.
*/
- dls_bypass = ((mac_srs->srs_type & SRST_DLS_BYPASS) != 0);
+ dls_bypass = ((mac_srs->srs_type & SRST_DLS_BYPASS) != 0) &&
+ ((mcip->mci_state_flags & MCIS_RX_BYPASS_DISABLE) == 0);
/*
* Since the softrings are never destroyed and we always
diff --git a/usr/src/uts/common/sys/dld_impl.h b/usr/src/uts/common/sys/dld_impl.h
index c244204727..b2da85ff31 100644
--- a/usr/src/uts/common/sys/dld_impl.h
+++ b/usr/src/uts/common/sys/dld_impl.h
@@ -219,6 +219,7 @@ struct dld_str_s { /* Protected by */
void *ds_private;
boolean_t ds_lowlink; /* SL */
+ boolean_t ds_nonip; /* SL */
};
diff --git a/usr/src/uts/common/sys/dls_impl.h b/usr/src/uts/common/sys/dls_impl.h
index 8bcc048dd2..7f0a4d9ac9 100644
--- a/usr/src/uts/common/sys/dls_impl.h
+++ b/usr/src/uts/common/sys/dls_impl.h
@@ -62,6 +62,7 @@ struct dls_link_s { /* Protected by */
zoneid_t dl_zid;
uint_t dl_zone_ref;
link_tagmode_t dl_tagmode; /* atomic */
+ uint_t dl_nonip_cnt; /* SL */
};
typedef struct dls_head_s {
diff --git a/usr/src/uts/common/sys/mac_client_impl.h b/usr/src/uts/common/sys/mac_client_impl.h
index 5bd36ad779..bcdeb1da46 100644
--- a/usr/src/uts/common/sys/mac_client_impl.h
+++ b/usr/src/uts/common/sys/mac_client_impl.h
@@ -292,6 +292,7 @@ extern int mac_tx_percpu_cnt;
#define MCIS_USE_DATALINK_NAME 0x0400
#define MCIS_UNICAST_HW 0x0800
#define MCIS_REQ_HWRINGS 0x1000
+#define MCIS_RX_BYPASS_DISABLE 0x2000
/* in mac_client.c */
extern void mac_promisc_client_dispatch(mac_client_impl_t *, mblk_t *);
diff --git a/usr/src/uts/common/sys/mac_client_priv.h b/usr/src/uts/common/sys/mac_client_priv.h
index 6689d20f34..78421a3b80 100644
--- a/usr/src/uts/common/sys/mac_client_priv.h
+++ b/usr/src/uts/common/sys/mac_client_priv.h
@@ -50,6 +50,8 @@ extern "C" {
extern boolean_t mac_rx_bypass_set(mac_client_handle_t, mac_direct_rx_t,
void *);
+extern void mac_rx_bypass_enable(mac_client_handle_t);
+extern void mac_rx_bypass_disable(mac_client_handle_t);
extern const mac_info_t *mac_info(mac_handle_t);
extern boolean_t mac_info_get(const char *, mac_info_t *);