summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorSebastien Roy <Sebastien.Roy@Sun.COM>2009-02-20 21:38:08 -0500
committerSebastien Roy <Sebastien.Roy@Sun.COM>2009-02-20 21:38:08 -0500
commite75f0919bf9ec317db5c7166d0aaf1eed11debdb (patch)
treee7537956d00f6d01e125ca0645066eedbec4ce7c
parenta111c49db4e8b7dd3704736578122b73ef4c24fe (diff)
downloadillumos-joyent-e75f0919bf9ec317db5c7166d0aaf1eed11debdb.tar.gz
PSARC 2009/069 802.1Q tag mode link property
6797256 need link property to control 802.1Q priority tagging
-rw-r--r--usr/src/lib/libdladm/common/linkprop.c50
-rw-r--r--usr/src/uts/common/io/dld/dld_drv.c67
-rw-r--r--usr/src/uts/common/io/dld/dld_proto.c54
-rw-r--r--usr/src/uts/common/io/dld/dld_str.c24
-rw-r--r--usr/src/uts/common/io/dls/dls.c22
-rw-r--r--usr/src/uts/common/sys/dls_impl.h1
-rw-r--r--usr/src/uts/common/sys/mac.h6
7 files changed, 150 insertions, 74 deletions
diff --git a/usr/src/lib/libdladm/common/linkprop.c b/usr/src/lib/libdladm/common/linkprop.c
index be308d7c91..7affe07dd2 100644
--- a/usr/src/lib/libdladm/common/linkprop.c
+++ b/usr/src/lib/libdladm/common/linkprop.c
@@ -19,7 +19,7 @@
* CDDL HEADER END
*/
/*
- * Copyright 2008 Sun Microsystems, Inc. All rights reserved.
+ * Copyright 2009 Sun Microsystems, Inc. All rights reserved.
* Use is subject to license terms.
*/
@@ -132,7 +132,8 @@ static pd_getf_t do_get_zone, do_get_autopush, do_get_rate_mod,
i_dladm_duplex_get, i_dladm_status_get,
i_dladm_binary_get, i_dladm_uint32_get,
i_dladm_flowctl_get, i_dladm_maxbw_get,
- i_dladm_cpus_get, i_dladm_priority_get;
+ i_dladm_cpus_get, i_dladm_priority_get,
+ i_dladm_tagmode_get;
static pd_setf_t do_set_zone, do_set_rate_prop,
do_set_powermode_prop, do_set_radio_prop,
@@ -318,6 +319,8 @@ static link_attr_t link_attr[] = {
{ MAC_PROP_BIND_CPU, sizeof (mac_resource_props_t), "cpus"},
+ { MAC_PROP_TAGMODE, sizeof (link_tagmode_t), "tagmode"},
+
{ MAC_PROP_PRIVATE, 0, "driver-private"}
};
@@ -346,6 +349,11 @@ static val_desc_t link_priority_vals[] = {
{ "high", MPL_HIGH }
};
+static val_desc_t link_tagmode_vals[] = {
+ { "normal", LINK_TAGMODE_NORMAL },
+ { "vlanonly", LINK_TAGMODE_VLANONLY }
+};
+
static val_desc_t dladm_wlan_radio_vals[] = {
{ "on", DLADM_WLAN_RADIO_ON },
{ "off", DLADM_WLAN_RADIO_OFF }
@@ -492,6 +500,13 @@ static prop_desc_t prop_table[] = {
link_priority_vals, VALCNT(link_priority_vals), do_set_res, NULL,
i_dladm_priority_get, do_check_priority, PD_CHECK_ALLOC,
DATALINK_CLASS_ALL, DATALINK_ANY_MEDIATYPE },
+
+ { "tagmode", { "vlanonly", LINK_TAGMODE_VLANONLY },
+ link_tagmode_vals, VALCNT(link_tagmode_vals),
+ i_dladm_set_public_prop, NULL, i_dladm_tagmode_get,
+ NULL, 0,
+ DATALINK_CLASS_PHYS | DATALINK_CLASS_AGGR | DATALINK_CLASS_VNIC,
+ DL_ETHER }
};
#define DLADM_MAX_PROPS (sizeof (prop_table) / sizeof (prop_desc_t))
@@ -2495,6 +2510,37 @@ i_dladm_uint32_get(dladm_handle_t handle, prop_desc_t *pdp,
/* ARGSUSED */
static dladm_status_t
+i_dladm_tagmode_get(dladm_handle_t handle, prop_desc_t *pdp,
+ datalink_id_t linkid, char **prop_val, uint_t *val_cnt,
+ datalink_media_t media, uint_t flags, uint_t *perm_flags)
+{
+ dld_ioc_macprop_t *dip;
+ link_tagmode_t mode;
+ dladm_status_t status;
+
+ dip = i_dladm_get_public_prop(handle, linkid, pdp->pd_name, flags,
+ &status, perm_flags);
+ if (dip == NULL)
+ return (status);
+ (void) memcpy(&mode, dip->pr_val, sizeof (mode));
+ free(dip);
+
+ switch (mode) {
+ case LINK_TAGMODE_NORMAL:
+ (void) strlcpy(*prop_val, "normal", DLADM_PROP_VAL_MAX);
+ break;
+ case LINK_TAGMODE_VLANONLY:
+ (void) strlcpy(*prop_val, "vlanonly", DLADM_PROP_VAL_MAX);
+ break;
+ default:
+ (void) strlcpy(*prop_val, "unknown", DLADM_PROP_VAL_MAX);
+ }
+ *val_cnt = 1;
+ return (DLADM_STATUS_OK);
+}
+
+/* ARGSUSED */
+static dladm_status_t
i_dladm_flowctl_get(dladm_handle_t handle, prop_desc_t *pdp,
datalink_id_t linkid, char **prop_val, uint_t *val_cnt,
datalink_media_t media, uint_t flags, uint_t *perm_flags)
diff --git a/usr/src/uts/common/io/dld/dld_drv.c b/usr/src/uts/common/io/dld/dld_drv.c
index 55e4d161db..f833adce01 100644
--- a/usr/src/uts/common/io/dld/dld_drv.c
+++ b/usr/src/uts/common/io/dld/dld_drv.c
@@ -19,7 +19,7 @@
* CDDL HEADER END
*/
/*
- * Copyright 2008 Sun Microsystems, Inc. All rights reserved.
+ * Copyright 2009 Sun Microsystems, Inc. All rights reserved.
* Use is subject to license terms.
*/
@@ -557,56 +557,65 @@ drv_ioc_prop_common(dld_ioc_macprop_t *prop, intptr_t arg, boolean_t set,
goto done;
}
+ if ((err = dls_link_hold(dls_devnet_mac(dlh), &dlp)) != 0)
+ goto done;
+
switch (kprop->pr_num) {
- case MAC_PROP_ZONE: {
+ case MAC_PROP_ZONE:
if (set) {
- dld_ioc_zid_t *dzp = (dld_ioc_zid_t *)kprop->pr_val;
+ dld_ioc_zid_t *dzp = (dld_ioc_zid_t *)kprop->pr_val;
err = dls_devnet_setzid(dzp->diz_link, dzp->diz_zid);
- goto done;
} else {
kprop->pr_perm_flags = MAC_PROP_PERM_RW;
err = dls_devnet_getzid(linkid,
(zoneid_t *)kprop->pr_val);
- goto done;
}
- }
+ break;
case MAC_PROP_AUTOPUSH: {
- struct dlautopush *dlap =
- (struct dlautopush *)kprop->pr_val;
+ struct dlautopush *dlap = (struct dlautopush *)kprop->pr_val;
if (set) {
- if (kprop->pr_valsize != 0) {
+ if (kprop->pr_valsize != 0)
err = drv_ioc_setap(linkid, dlap);
- goto done;
- } else {
+ else
err = drv_ioc_clrap(linkid);
- goto done;
- }
} else {
kprop->pr_perm_flags = MAC_PROP_PERM_RW;
err = drv_ioc_getap(linkid, dlap);
- goto done;
}
- }
- default:
break;
}
+ case MAC_PROP_TAGMODE:
+ if (set) {
+ link_tagmode_t mode = *(link_tagmode_t *)kprop->pr_val;
- if ((err = dls_link_hold(dls_devnet_mac(dlh), &dlp)) != 0)
- goto done;
-
- macprop.mp_name = kprop->pr_name;
- macprop.mp_id = kprop->pr_num;
- macprop.mp_flags = kprop->pr_flags;
+ if (mode != LINK_TAGMODE_VLANONLY &&
+ mode != LINK_TAGMODE_NORMAL) {
+ err = EINVAL;
+ } else {
+ dlp->dl_tagmode = mode;
+ err = 0;
+ }
+ } else {
+ *(link_tagmode_t *)kprop->pr_val = dlp->dl_tagmode;
+ kprop->pr_perm_flags = MAC_PROP_PERM_RW;
+ err = 0;
+ }
+ break;
+ default:
+ macprop.mp_name = kprop->pr_name;
+ macprop.mp_id = kprop->pr_num;
+ macprop.mp_flags = kprop->pr_flags;
- if (set) {
- err = mac_set_prop(dlp->dl_mh, &macprop, kprop->pr_val,
- kprop->pr_valsize);
- } else {
- kprop->pr_perm_flags = MAC_PROP_PERM_RW;
- err = mac_get_prop(dlp->dl_mh, &macprop, kprop->pr_val,
- kprop->pr_valsize, &kprop->pr_perm_flags);
+ if (set) {
+ err = mac_set_prop(dlp->dl_mh, &macprop, kprop->pr_val,
+ kprop->pr_valsize);
+ } else {
+ kprop->pr_perm_flags = MAC_PROP_PERM_RW;
+ err = mac_get_prop(dlp->dl_mh, &macprop, kprop->pr_val,
+ kprop->pr_valsize, &kprop->pr_perm_flags);
+ }
}
done:
diff --git a/usr/src/uts/common/io/dld/dld_proto.c b/usr/src/uts/common/io/dld/dld_proto.c
index 5533b582a0..32b100bb05 100644
--- a/usr/src/uts/common/io/dld/dld_proto.c
+++ b/usr/src/uts/common/io/dld/dld_proto.c
@@ -250,35 +250,39 @@ proto_info_req(dld_str_t *dsp, mblk_t *mp)
dlp->dl_brdcst_addr_length = addr_length;
}
- dlp->dl_qos_range_offset = (uintptr_t)rangep - (uintptr_t)dlp;
- dlp->dl_qos_range_length = sizeof (dl_qos_cl_range1_t);
+ /* Only VLAN links and links that have a normal tag mode support QOS. */
+ if (mac_client_vid(dsp->ds_mch) != VLAN_ID_NONE ||
+ dsp->ds_dlp->dl_tagmode == LINK_TAGMODE_NORMAL) {
+ dlp->dl_qos_range_offset = (uintptr_t)rangep - (uintptr_t)dlp;
+ dlp->dl_qos_range_length = sizeof (dl_qos_cl_range1_t);
+
+ rangep->dl_qos_type = DL_QOS_CL_RANGE1;
+ rangep->dl_trans_delay.dl_target_value = DL_UNKNOWN;
+ rangep->dl_trans_delay.dl_accept_value = DL_UNKNOWN;
+ rangep->dl_protection.dl_min = DL_UNKNOWN;
+ rangep->dl_protection.dl_max = DL_UNKNOWN;
+ rangep->dl_residual_error = DL_UNKNOWN;
- rangep->dl_qos_type = DL_QOS_CL_RANGE1;
- rangep->dl_trans_delay.dl_target_value = DL_UNKNOWN;
- rangep->dl_trans_delay.dl_accept_value = DL_UNKNOWN;
- rangep->dl_protection.dl_min = DL_UNKNOWN;
- rangep->dl_protection.dl_max = DL_UNKNOWN;
- rangep->dl_residual_error = DL_UNKNOWN;
-
- /*
- * Specify the supported range of priorities.
- */
- rangep->dl_priority.dl_min = 0;
- rangep->dl_priority.dl_max = (1 << VLAN_PRI_SIZE) - 1;
+ /*
+ * Specify the supported range of priorities.
+ */
+ rangep->dl_priority.dl_min = 0;
+ rangep->dl_priority.dl_max = (1 << VLAN_PRI_SIZE) - 1;
- dlp->dl_qos_offset = (uintptr_t)selp - (uintptr_t)dlp;
- dlp->dl_qos_length = sizeof (dl_qos_cl_sel1_t);
+ dlp->dl_qos_offset = (uintptr_t)selp - (uintptr_t)dlp;
+ dlp->dl_qos_length = sizeof (dl_qos_cl_sel1_t);
- selp->dl_qos_type = DL_QOS_CL_SEL1;
- selp->dl_trans_delay = DL_UNKNOWN;
- selp->dl_protection = DL_UNKNOWN;
- selp->dl_residual_error = DL_UNKNOWN;
+ selp->dl_qos_type = DL_QOS_CL_SEL1;
+ selp->dl_trans_delay = DL_UNKNOWN;
+ selp->dl_protection = DL_UNKNOWN;
+ selp->dl_residual_error = DL_UNKNOWN;
- /*
- * Specify the current priority (which can be changed by
- * the DL_UDQOS_REQ primitive).
- */
- selp->dl_priority = dsp->ds_pri;
+ /*
+ * Specify the current priority (which can be changed by
+ * the DL_UDQOS_REQ primitive).
+ */
+ selp->dl_priority = dsp->ds_pri;
+ }
dlp->dl_addr_length = addr_length + sizeof (uint16_t);
if (dsp->ds_dlstate == DL_IDLE) {
diff --git a/usr/src/uts/common/io/dld/dld_str.c b/usr/src/uts/common/io/dld/dld_str.c
index cf7e7010dc..e05ce5b1c1 100644
--- a/usr/src/uts/common/io/dld/dld_str.c
+++ b/usr/src/uts/common/io/dld/dld_str.c
@@ -19,7 +19,7 @@
* CDDL HEADER END
*/
/*
- * Copyright 2008 Sun Microsystems, Inc. All rights reserved.
+ * Copyright 2009 Sun Microsystems, Inc. All rights reserved.
* Use is subject to license terms.
*/
@@ -59,7 +59,8 @@ static void dld_ioc(dld_str_t *, mblk_t *);
static void dld_wput_nondata(dld_str_t *, mblk_t *);
static void str_mdata_raw_put(dld_str_t *, mblk_t *);
-static mblk_t *i_dld_ether_header_update_tag(mblk_t *, uint_t, uint16_t);
+static mblk_t *i_dld_ether_header_update_tag(mblk_t *, uint_t, uint16_t,
+ link_tagmode_t);
static mblk_t *i_dld_ether_header_strip_tag(mblk_t *);
static uint32_t str_count;
@@ -694,7 +695,8 @@ str_destructor(void *buf, void *cdrarg)
* If vid is VLAN_ID_NONE, use the VID encoded in the packet.
*/
static mblk_t *
-i_dld_ether_header_update_tag(mblk_t *mp, uint_t pri, uint16_t vid)
+i_dld_ether_header_update_tag(mblk_t *mp, uint_t pri, uint16_t vid,
+ link_tagmode_t tagmode)
{
mblk_t *hmp;
struct ether_vlan_header *evhp;
@@ -731,9 +733,15 @@ i_dld_ether_header_update_tag(mblk_t *mp, uint_t pri, uint16_t vid)
evhp = (struct ether_vlan_header *)mp->b_rptr;
} else {
/*
- * Untagged packet. Insert the special priority tag.
- * First allocate a header mblk.
+ * Untagged packet. Two factors will cause us to insert a
+ * VLAN header:
+ * - This is a VLAN link (vid is specified)
+ * - The link supports user priority tagging and the priority
+ * is non-zero.
*/
+ if (vid == VLAN_ID_NONE && tagmode == LINK_TAGMODE_VLANONLY)
+ return (mp);
+
hmp = allocb(sizeof (struct ether_vlan_header), BPRI_MED);
if (hmp == NULL)
return (NULL);
@@ -792,7 +800,7 @@ str_mdata_fastpath_put(dld_str_t *dsp, mblk_t *mp, uintptr_t f_hint,
if (pri != 0) {
newmp = i_dld_ether_header_update_tag(mp, pri,
- VLAN_ID_NONE);
+ VLAN_ID_NONE, dsp->ds_dlp->dl_tagmode);
if (newmp == NULL)
goto discard;
mp = newmp;
@@ -891,8 +899,8 @@ str_mdata_raw_put(dld_str_t *dsp, mblk_t *mp)
*/
pri = (pri == 0) ? dsp->ds_pri : 0;
if ((pri != 0) || (dvid != VLAN_ID_NONE)) {
- if ((newmp = i_dld_ether_header_update_tag(mp,
- pri, dvid)) == NULL) {
+ if ((newmp = i_dld_ether_header_update_tag(mp, pri,
+ dvid, dsp->ds_dlp->dl_tagmode)) == NULL) {
goto discard;
}
mp = newmp;
diff --git a/usr/src/uts/common/io/dls/dls.c b/usr/src/uts/common/io/dls/dls.c
index 53450a45d1..75e529455c 100644
--- a/usr/src/uts/common/io/dls/dls.c
+++ b/usr/src/uts/common/io/dls/dls.c
@@ -401,18 +401,19 @@ dls_header(dld_str_t *dsp, const uint8_t *addr, uint16_t sap, uint_t pri,
payload = (payloadp == NULL) ? NULL : (*payloadp);
/*
- * If the following conditions are satisfied:
- * - This is not a ETHERTYPE_VLAN listener; and
- * - This is either a VLAN stream or this is a physical stream
- * but the priority is not 0.
+ * In the case of Ethernet, we need to tell mac_header() if we need
+ * extra room beyond the Ethernet header for a VLAN header. We'll
+ * need to add a VLAN header if this isn't an ETHERTYPE_VLAN listener
+ * (because such streams will be handling VLAN headers on their own)
+ * and one of the following conditions is satisfied:
*
- * then we know ahead of time that we'll need to fill in additional
- * VLAN information in the link-layer header. We will tell the MAC
- * layer to pre-allocate some space at the end of the Ethernet
- * header for us.
+ * - This is a VLAN stream
+ * - This is a physical stream, the priority is not 0, and user
+ * priority tagging is allowed.
*/
if (is_ethernet && sap != ETHERTYPE_VLAN &&
- (vid != VLAN_ID_NONE || pri != 0)) {
+ (vid != VLAN_ID_NONE ||
+ (pri != 0 && dsp->ds_dlp->dl_tagmode != LINK_TAGMODE_VLANONLY))) {
extra_len = sizeof (struct ether_vlan_header) -
sizeof (struct ether_header);
mac_sap = ETHERTYPE_VLAN;
@@ -425,7 +426,8 @@ dls_header(dld_str_t *dsp, const uint8_t *addr, uint16_t sap, uint_t pri,
if (mp == NULL)
return (NULL);
- if ((vid == VLAN_ID_NONE && pri == 0) || !is_ethernet)
+ if ((vid == VLAN_ID_NONE && (pri == 0 ||
+ dsp->ds_dlp->dl_tagmode == LINK_TAGMODE_VLANONLY)) || !is_ethernet)
return (mp);
/*
diff --git a/usr/src/uts/common/sys/dls_impl.h b/usr/src/uts/common/sys/dls_impl.h
index 98bec27a8e..33162a4d5c 100644
--- a/usr/src/uts/common/sys/dls_impl.h
+++ b/usr/src/uts/common/sys/dls_impl.h
@@ -59,6 +59,7 @@ struct dls_link_s { /* Protected by */
uint32_t dl_unknowns; /* atomic */
zoneid_t dl_zid;
uint_t dl_zone_ref;
+ link_tagmode_t dl_tagmode; /* atomic */
};
typedef struct dls_head_s {
diff --git a/usr/src/uts/common/sys/mac.h b/usr/src/uts/common/sys/mac.h
index d179e5a2f8..c6dbe35d57 100644
--- a/usr/src/uts/common/sys/mac.h
+++ b/usr/src/uts/common/sys/mac.h
@@ -91,6 +91,11 @@ typedef enum {
LINK_FLOWCTRL_BI
} link_flowctrl_t;
+typedef enum {
+ LINK_TAGMODE_VLANONLY = 0,
+ LINK_TAGMODE_NORMAL
+} link_tagmode_t;
+
/*
* Maximum MAC address length
*/
@@ -162,6 +167,7 @@ typedef enum {
MAC_PROP_MAXBW,
MAC_PROP_PRIO,
MAC_PROP_BIND_CPU,
+ MAC_PROP_TAGMODE,
MAC_PROP_PRIVATE = -1
} mac_prop_id_t;