net/ice/base: support L3 DSCP QoS

The base code support to build configuration TLVs
in DSCP mode has not been implemented before, so
the functions to do so and the flow control to determine
if we are in VLAN or DSCP mode need to be added.

The current value for maximum number of DCB APPs
(ICE_DCBX_MAX_APPS) is not sufficient when supporting
DSCP mode.  Each DSCP->TC mapping will come in as a
single APP value.  So, there can be up to 64 APPs for
DSCP mapping.

Need to keep track of the current DSCP to TC mapping
so that TLVs can be built up to send to the FW.  Add
an u8 array to hold this info.

A u64 is also needed to keep track of the DSCP values
that have had an APP submitted to map its value to a
TC.  Since it would be unwise to allow an APP to be
overwritten by subsequent APPs, reject mappings for a
DSCP value that already has a user mapped value.  This
will allow us to easily track which DSCP values have
been mapped, and when the last one has been deleted.

Signed-off-by: Dave Ertman <david.m.ertman@intel.com>
Signed-off-by: Anirudh Venkataramanan <anirudh.venkataramanan@intel.com>
Signed-off-by: Qi Zhang <qi.z.zhang@intel.com>
Acked-by: Qi Zhang <qi.z.zhang@intel.com>
This commit is contained in:
Qi Zhang 2021-04-29 08:41:41 +08:00
parent daa2ca4217
commit 8ea78b1696
3 changed files with 194 additions and 17 deletions

View File

@ -1207,7 +1207,140 @@ ice_add_ieee_app_pri_tlv(struct ice_lldp_org_tlv *tlv,
}
/**
* ice_add_dcb_tlv - Add all IEEE TLVs
* ice_add_dscp_up_tlv - Prepare DSCP to UP TLV
* @tlv: location to build the TLV data
* @dcbcfg: location of data to convert to TLV
*/
static void
ice_add_dscp_up_tlv(struct ice_lldp_org_tlv *tlv, struct ice_dcbx_cfg *dcbcfg)
{
u8 *buf = tlv->tlvinfo;
u32 ouisubtype;
u16 typelen;
int i;
typelen = ((ICE_TLV_TYPE_ORG << ICE_LLDP_TLV_TYPE_S) |
ICE_DSCP_UP_TLV_LEN);
tlv->typelen = HTONS(typelen);
ouisubtype = (u32)((ICE_DSCP_OUI << ICE_LLDP_TLV_OUI_S) |
ICE_DSCP_SUBTYPE_DSCP2UP);
tlv->ouisubtype = HTONL(ouisubtype);
/* bytes 0 - 63 - IPv4 DSCP2UP LUT */
for (i = 0; i < ICE_DSCP_NUM_VAL; i++) {
/* IPv4 mapping */
buf[i] = dcbcfg->dscp_map[i];
/* IPv6 mapping */
buf[i + ICE_DSCP_IPV6_OFFSET] = dcbcfg->dscp_map[i];
}
/* byte 64 - IPv4 untagged traffic */
buf[i] = 0;
/* byte 144 - IPv6 untagged traffic */
buf[i + ICE_DSCP_IPV6_OFFSET] = 0;
}
#define ICE_BYTES_PER_TC 8
/**
* ice_add_dscp_enf_tlv - Prepare DSCP Enforcement TLV
* @tlv: location to build the TLV data
*/
static void
ice_add_dscp_enf_tlv(struct ice_lldp_org_tlv *tlv)
{
u8 *buf = tlv->tlvinfo;
u32 ouisubtype;
u16 typelen;
typelen = ((ICE_TLV_TYPE_ORG << ICE_LLDP_TLV_TYPE_S) |
ICE_DSCP_ENF_TLV_LEN);
tlv->typelen = HTONS(typelen);
ouisubtype = (u32)((ICE_DSCP_OUI << ICE_LLDP_TLV_OUI_S) |
ICE_DSCP_SUBTYPE_ENFORCE);
tlv->ouisubtype = HTONL(ouisubtype);
/* Allow all DSCP values to be valid for all TC's (IPv4 and IPv6) */
memset(buf, 0, 2 * (ICE_MAX_TRAFFIC_CLASS * ICE_BYTES_PER_TC));
}
/**
* ice_add_dscp_tc_bw_tlv - Prepare DSCP BW for TC TLV
* @tlv: location to build the TLV data
* @dcbcfg: location of the data to convert to TLV
*/
static void
ice_add_dscp_tc_bw_tlv(struct ice_lldp_org_tlv *tlv,
struct ice_dcbx_cfg *dcbcfg)
{
struct ice_dcb_ets_cfg *etscfg;
u8 *buf = tlv->tlvinfo;
u32 ouisubtype;
u8 offset = 0;
u16 typelen;
int i;
typelen = ((ICE_TLV_TYPE_ORG << ICE_LLDP_TLV_TYPE_S) |
ICE_DSCP_TC_BW_TLV_LEN);
tlv->typelen = HTONS(typelen);
ouisubtype = (u32)((ICE_DSCP_OUI << ICE_LLDP_TLV_OUI_S) |
ICE_DSCP_SUBTYPE_TCBW);
tlv->ouisubtype = HTONL(ouisubtype);
/* First Octet after subtype
* ----------------------------
* | RSV | CBS | RSV | Max TCs |
* | 1b | 1b | 3b | 3b |
* ----------------------------
*/
etscfg = &dcbcfg->etscfg;
buf[0] = etscfg->maxtcs & ICE_IEEE_ETS_MAXTC_M;
/* bytes 1 - 4 reserved */
offset = 5;
/* TC BW table
* bytes 0 - 7 for TC 0 - 7
*
* TSA Assignment table
* bytes 8 - 15 for TC 0 - 7
*/
for (i = 0; i < ICE_MAX_TRAFFIC_CLASS; i++) {
buf[offset] = etscfg->tcbwtable[i];
buf[offset + ICE_MAX_TRAFFIC_CLASS] = etscfg->tsatable[i];
offset++;
}
}
/**
* ice_add_dscp_pfc_tlv - Prepare DSCP PFC TLV
* @tlv: Fill PFC TLV in IEEE format
* @dcbcfg: Local store which holds the PFC CFG data
*/
static void
ice_add_dscp_pfc_tlv(struct ice_lldp_org_tlv *tlv, struct ice_dcbx_cfg *dcbcfg)
{
u8 *buf = tlv->tlvinfo;
u32 ouisubtype;
u16 typelen;
typelen = ((ICE_TLV_TYPE_ORG << ICE_LLDP_TLV_TYPE_S) |
ICE_DSCP_PFC_TLV_LEN);
tlv->typelen = HTONS(typelen);
ouisubtype = (u32)((ICE_DSCP_OUI << ICE_LLDP_TLV_OUI_S) |
ICE_DSCP_SUBTYPE_PFC);
tlv->ouisubtype = HTONL(ouisubtype);
buf[0] = dcbcfg->pfc.pfccap & 0xF;
buf[1] = dcbcfg->pfc.pfcena & 0xF;
}
/**
* ice_add_dcb_tlv - Add all IEEE or DSCP TLVs
* @tlv: Fill TLV data in IEEE format
* @dcbcfg: Local store which holds the DCB Config
* @tlvid: Type of IEEE TLV
@ -1218,21 +1351,41 @@ static void
ice_add_dcb_tlv(struct ice_lldp_org_tlv *tlv, struct ice_dcbx_cfg *dcbcfg,
u16 tlvid)
{
switch (tlvid) {
case ICE_IEEE_TLV_ID_ETS_CFG:
ice_add_ieee_ets_tlv(tlv, dcbcfg);
break;
case ICE_IEEE_TLV_ID_ETS_REC:
ice_add_ieee_etsrec_tlv(tlv, dcbcfg);
break;
case ICE_IEEE_TLV_ID_PFC_CFG:
ice_add_ieee_pfc_tlv(tlv, dcbcfg);
break;
case ICE_IEEE_TLV_ID_APP_PRI:
ice_add_ieee_app_pri_tlv(tlv, dcbcfg);
break;
default:
break;
if (dcbcfg->pfc_mode == ICE_QOS_MODE_VLAN) {
switch (tlvid) {
case ICE_IEEE_TLV_ID_ETS_CFG:
ice_add_ieee_ets_tlv(tlv, dcbcfg);
break;
case ICE_IEEE_TLV_ID_ETS_REC:
ice_add_ieee_etsrec_tlv(tlv, dcbcfg);
break;
case ICE_IEEE_TLV_ID_PFC_CFG:
ice_add_ieee_pfc_tlv(tlv, dcbcfg);
break;
case ICE_IEEE_TLV_ID_APP_PRI:
ice_add_ieee_app_pri_tlv(tlv, dcbcfg);
break;
default:
break;
}
} else {
/* pfc_mode == ICE_QOS_MODE_DSCP */
switch (tlvid) {
case ICE_TLV_ID_DSCP_UP:
ice_add_dscp_up_tlv(tlv, dcbcfg);
break;
case ICE_TLV_ID_DSCP_ENF:
ice_add_dscp_enf_tlv(tlv);
break;
case ICE_TLV_ID_DSCP_TC_BW:
ice_add_dscp_tc_bw_tlv(tlv, dcbcfg);
break;
case ICE_TLV_ID_DSCP_TO_PFC:
ice_add_dscp_pfc_tlv(tlv, dcbcfg);
break;
default:
break;
}
}
}

View File

@ -29,6 +29,13 @@
#define ICE_CEE_DCBX_OUI 0x001B21
#define ICE_CEE_DCBX_TYPE 2
#define ICE_DSCP_OUI 0xFFFFFF
#define ICE_DSCP_SUBTYPE_DSCP2UP 0x41
#define ICE_DSCP_SUBTYPE_ENFORCE 0x42
#define ICE_DSCP_SUBTYPE_TCBW 0x43
#define ICE_DSCP_SUBTYPE_PFC 0x44
#define ICE_DSCP_IPV6_OFFSET 80
#define ICE_CEE_SUBTYPE_CTRL 1
#define ICE_CEE_SUBTYPE_PG_CFG 2
#define ICE_CEE_SUBTYPE_PFC_CFG 3
@ -97,11 +104,20 @@
#define ICE_IEEE_TLV_ID_APP_PRI 6
#define ICE_TLV_ID_END_OF_LLDPPDU 7
#define ICE_TLV_ID_START ICE_IEEE_TLV_ID_ETS_CFG
#define ICE_TLV_ID_DSCP_UP 3
#define ICE_TLV_ID_DSCP_ENF 4
#define ICE_TLV_ID_DSCP_TC_BW 5
#define ICE_TLV_ID_DSCP_TO_PFC 6
#define ICE_IEEE_ETS_TLV_LEN 25
#define ICE_IEEE_PFC_TLV_LEN 6
#define ICE_IEEE_APP_TLV_LEN 11
#define ICE_DSCP_UP_TLV_LEN 148
#define ICE_DSCP_ENF_TLV_LEN 132
#define ICE_DSCP_TC_BW_TLV_LEN 25
#define ICE_DSCP_PFC_TLV_LEN 6
#pragma pack(1)
/* IEEE 802.1AB LLDP Organization specific TLV */
struct ice_lldp_org_tlv {

View File

@ -797,7 +797,8 @@ struct ice_dcb_app_priority_table {
};
#define ICE_MAX_USER_PRIORITY 8
#define ICE_DCBX_MAX_APPS 32
#define ICE_DCBX_MAX_APPS 64
#define ICE_DSCP_NUM_VAL 64
#define ICE_LLDPDU_SIZE 1500
#define ICE_TLV_STATUS_OPER 0x1
#define ICE_TLV_STATUS_SYNC 0x2
@ -817,7 +818,14 @@ struct ice_dcbx_cfg {
struct ice_dcb_ets_cfg etscfg;
struct ice_dcb_ets_cfg etsrec;
struct ice_dcb_pfc_cfg pfc;
#define ICE_QOS_MODE_VLAN 0x0
#define ICE_QOS_MODE_DSCP 0x1
u8 pfc_mode;
struct ice_dcb_app_priority_table app[ICE_DCBX_MAX_APPS];
/* when DSCP mapping defined by user set its bit to 1 */
ice_declare_bitmap(dscp_mapped, ICE_DSCP_NUM_VAL);
/* array holding DSCP -> UP/TC values for DSCP L3 QoS mode */
u8 dscp_map[ICE_DSCP_NUM_VAL];
u8 dcbx_mode;
#define ICE_DCBX_MODE_CEE 0x1
#define ICE_DCBX_MODE_IEEE 0x2