diff options
author | Sebastien Roy <Sebastien.Roy@Sun.COM> | 2009-02-20 21:38:08 -0500 |
---|---|---|
committer | Sebastien Roy <Sebastien.Roy@Sun.COM> | 2009-02-20 21:38:08 -0500 |
commit | e75f0919bf9ec317db5c7166d0aaf1eed11debdb (patch) | |
tree | e7537956d00f6d01e125ca0645066eedbec4ce7c | |
parent | a111c49db4e8b7dd3704736578122b73ef4c24fe (diff) | |
download | illumos-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.c | 50 | ||||
-rw-r--r-- | usr/src/uts/common/io/dld/dld_drv.c | 67 | ||||
-rw-r--r-- | usr/src/uts/common/io/dld/dld_proto.c | 54 | ||||
-rw-r--r-- | usr/src/uts/common/io/dld/dld_str.c | 24 | ||||
-rw-r--r-- | usr/src/uts/common/io/dls/dls.c | 22 | ||||
-rw-r--r-- | usr/src/uts/common/sys/dls_impl.h | 1 | ||||
-rw-r--r-- | usr/src/uts/common/sys/mac.h | 6 |
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; |