Commit 34800178 authored by Martyna Szapar-Mudlaw's avatar Martyna Szapar-Mudlaw Committed by Tony Nguyen

ice: Add support for VLAN priority filters in switchdev

Enable support for adding TC rules that filter on the VLAN priority
in switchdev mode.

VLAN priority are the first 3 bits of 16b switch field vector word
which contain also vlan id value within its last 12 bits.
When getting vlan priority value from tc match.key it
has to be shifted first to proper bits positions (by VLAN_PRIO_SHIFT)
and then can be added to the joint 'vlan' field in ice_vlan_hdr
in lookup element.

The mask of lookup changes accordingly.
0x0FFF - when only vlan id is added in filter
0xE000 - when only vlan priority is added in filter
0xEFFF - when both these values are specified
Signed-off-by: default avatarMartyna Szapar-Mudlaw <martyna.szapar-mudlaw@linux.intel.com>
Tested-by: default avatarSujai Buvaneswaran <sujai.buvaneswaran@intel.com>
Signed-off-by: default avatarTony Nguyen <anthony.l.nguyen@intel.com>
parent 793189a2
...@@ -51,11 +51,11 @@ ice_tc_count_lkups(u32 flags, struct ice_tc_flower_lyr_2_4_hdrs *headers, ...@@ -51,11 +51,11 @@ ice_tc_count_lkups(u32 flags, struct ice_tc_flower_lyr_2_4_hdrs *headers,
lkups_cnt++; lkups_cnt++;
/* is VLAN specified? */ /* is VLAN specified? */
if (flags & ICE_TC_FLWR_FIELD_VLAN) if (flags & (ICE_TC_FLWR_FIELD_VLAN | ICE_TC_FLWR_FIELD_VLAN_PRIO))
lkups_cnt++; lkups_cnt++;
/* is CVLAN specified? */ /* is CVLAN specified? */
if (flags & ICE_TC_FLWR_FIELD_CVLAN) if (flags & (ICE_TC_FLWR_FIELD_CVLAN | ICE_TC_FLWR_FIELD_CVLAN_PRIO))
lkups_cnt++; lkups_cnt++;
/* are PPPoE options specified? */ /* are PPPoE options specified? */
...@@ -389,7 +389,7 @@ ice_tc_fill_rules(struct ice_hw *hw, u32 flags, ...@@ -389,7 +389,7 @@ ice_tc_fill_rules(struct ice_hw *hw, u32 flags,
} }
/* copy VLAN info */ /* copy VLAN info */
if (flags & ICE_TC_FLWR_FIELD_VLAN) { if (flags & (ICE_TC_FLWR_FIELD_VLAN | ICE_TC_FLWR_FIELD_VLAN_PRIO)) {
vlan_tpid = be16_to_cpu(headers->vlan_hdr.vlan_tpid); vlan_tpid = be16_to_cpu(headers->vlan_hdr.vlan_tpid);
rule_info->vlan_type = rule_info->vlan_type =
ice_check_supported_vlan_tpid(vlan_tpid); ice_check_supported_vlan_tpid(vlan_tpid);
...@@ -398,15 +398,45 @@ ice_tc_fill_rules(struct ice_hw *hw, u32 flags, ...@@ -398,15 +398,45 @@ ice_tc_fill_rules(struct ice_hw *hw, u32 flags,
list[i].type = ICE_VLAN_EX; list[i].type = ICE_VLAN_EX;
else else
list[i].type = ICE_VLAN_OFOS; list[i].type = ICE_VLAN_OFOS;
list[i].h_u.vlan_hdr.vlan = headers->vlan_hdr.vlan_id;
list[i].m_u.vlan_hdr.vlan = cpu_to_be16(0xFFFF); if (flags & ICE_TC_FLWR_FIELD_VLAN) {
list[i].h_u.vlan_hdr.vlan = headers->vlan_hdr.vlan_id;
list[i].m_u.vlan_hdr.vlan = cpu_to_be16(0x0FFF);
}
if (flags & ICE_TC_FLWR_FIELD_VLAN_PRIO) {
if (flags & ICE_TC_FLWR_FIELD_VLAN) {
list[i].m_u.vlan_hdr.vlan = cpu_to_be16(0xEFFF);
} else {
list[i].m_u.vlan_hdr.vlan = cpu_to_be16(0xE000);
list[i].h_u.vlan_hdr.vlan = 0;
}
list[i].h_u.vlan_hdr.vlan |=
headers->vlan_hdr.vlan_prio;
}
i++; i++;
} }
if (flags & ICE_TC_FLWR_FIELD_CVLAN) { if (flags & (ICE_TC_FLWR_FIELD_CVLAN | ICE_TC_FLWR_FIELD_CVLAN_PRIO)) {
list[i].type = ICE_VLAN_IN; list[i].type = ICE_VLAN_IN;
list[i].h_u.vlan_hdr.vlan = headers->cvlan_hdr.vlan_id;
list[i].m_u.vlan_hdr.vlan = cpu_to_be16(0xFFFF); if (flags & ICE_TC_FLWR_FIELD_CVLAN) {
list[i].h_u.vlan_hdr.vlan = headers->cvlan_hdr.vlan_id;
list[i].m_u.vlan_hdr.vlan = cpu_to_be16(0x0FFF);
}
if (flags & ICE_TC_FLWR_FIELD_CVLAN_PRIO) {
if (flags & ICE_TC_FLWR_FIELD_CVLAN) {
list[i].m_u.vlan_hdr.vlan = cpu_to_be16(0xEFFF);
} else {
list[i].m_u.vlan_hdr.vlan = cpu_to_be16(0xE000);
list[i].h_u.vlan_hdr.vlan = 0;
}
list[i].h_u.vlan_hdr.vlan |=
headers->cvlan_hdr.vlan_prio;
}
i++; i++;
} }
...@@ -1280,16 +1310,22 @@ ice_parse_cls_flower(struct net_device *filter_dev, struct ice_vsi *vsi, ...@@ -1280,16 +1310,22 @@ ice_parse_cls_flower(struct net_device *filter_dev, struct ice_vsi *vsi,
if (match.mask->vlan_id) { if (match.mask->vlan_id) {
if (match.mask->vlan_id == VLAN_VID_MASK) { if (match.mask->vlan_id == VLAN_VID_MASK) {
fltr->flags |= ICE_TC_FLWR_FIELD_VLAN; fltr->flags |= ICE_TC_FLWR_FIELD_VLAN;
headers->vlan_hdr.vlan_id =
cpu_to_be16(match.key->vlan_id &
VLAN_VID_MASK);
} else { } else {
NL_SET_ERR_MSG_MOD(fltr->extack, "Bad VLAN mask"); NL_SET_ERR_MSG_MOD(fltr->extack, "Bad VLAN mask");
return -EINVAL; return -EINVAL;
} }
} }
headers->vlan_hdr.vlan_id = if (match.mask->vlan_priority) {
cpu_to_be16(match.key->vlan_id & VLAN_VID_MASK); fltr->flags |= ICE_TC_FLWR_FIELD_VLAN_PRIO;
if (match.mask->vlan_priority) headers->vlan_hdr.vlan_prio =
headers->vlan_hdr.vlan_prio = match.key->vlan_priority; cpu_to_be16((match.key->vlan_priority <<
VLAN_PRIO_SHIFT) & VLAN_PRIO_MASK);
}
if (match.mask->vlan_tpid) if (match.mask->vlan_tpid)
headers->vlan_hdr.vlan_tpid = match.key->vlan_tpid; headers->vlan_hdr.vlan_tpid = match.key->vlan_tpid;
} }
...@@ -1307,6 +1343,9 @@ ice_parse_cls_flower(struct net_device *filter_dev, struct ice_vsi *vsi, ...@@ -1307,6 +1343,9 @@ ice_parse_cls_flower(struct net_device *filter_dev, struct ice_vsi *vsi,
if (match.mask->vlan_id) { if (match.mask->vlan_id) {
if (match.mask->vlan_id == VLAN_VID_MASK) { if (match.mask->vlan_id == VLAN_VID_MASK) {
fltr->flags |= ICE_TC_FLWR_FIELD_CVLAN; fltr->flags |= ICE_TC_FLWR_FIELD_CVLAN;
headers->cvlan_hdr.vlan_id =
cpu_to_be16(match.key->vlan_id &
VLAN_VID_MASK);
} else { } else {
NL_SET_ERR_MSG_MOD(fltr->extack, NL_SET_ERR_MSG_MOD(fltr->extack,
"Bad CVLAN mask"); "Bad CVLAN mask");
...@@ -1314,10 +1353,12 @@ ice_parse_cls_flower(struct net_device *filter_dev, struct ice_vsi *vsi, ...@@ -1314,10 +1353,12 @@ ice_parse_cls_flower(struct net_device *filter_dev, struct ice_vsi *vsi,
} }
} }
headers->cvlan_hdr.vlan_id = if (match.mask->vlan_priority) {
cpu_to_be16(match.key->vlan_id & VLAN_VID_MASK); fltr->flags |= ICE_TC_FLWR_FIELD_CVLAN_PRIO;
if (match.mask->vlan_priority) headers->cvlan_hdr.vlan_prio =
headers->cvlan_hdr.vlan_prio = match.key->vlan_priority; cpu_to_be16((match.key->vlan_priority <<
VLAN_PRIO_SHIFT) & VLAN_PRIO_MASK);
}
} }
if (flow_rule_match_key(rule, FLOW_DISSECTOR_KEY_PPPOE)) { if (flow_rule_match_key(rule, FLOW_DISSECTOR_KEY_PPPOE)) {
......
...@@ -31,6 +31,8 @@ ...@@ -31,6 +31,8 @@
#define ICE_TC_FLWR_FIELD_ENC_IP_TOS BIT(24) #define ICE_TC_FLWR_FIELD_ENC_IP_TOS BIT(24)
#define ICE_TC_FLWR_FIELD_ENC_IP_TTL BIT(25) #define ICE_TC_FLWR_FIELD_ENC_IP_TTL BIT(25)
#define ICE_TC_FLWR_FIELD_L2TPV3_SESSID BIT(26) #define ICE_TC_FLWR_FIELD_L2TPV3_SESSID BIT(26)
#define ICE_TC_FLWR_FIELD_VLAN_PRIO BIT(27)
#define ICE_TC_FLWR_FIELD_CVLAN_PRIO BIT(28)
#define ICE_TC_FLOWER_MASK_32 0xFFFFFFFF #define ICE_TC_FLOWER_MASK_32 0xFFFFFFFF
...@@ -49,7 +51,7 @@ struct ice_tc_flower_action { ...@@ -49,7 +51,7 @@ struct ice_tc_flower_action {
struct ice_tc_vlan_hdr { struct ice_tc_vlan_hdr {
__be16 vlan_id; /* Only last 12 bits valid */ __be16 vlan_id; /* Only last 12 bits valid */
u16 vlan_prio; /* Only last 3 bits valid (valid values: 0..7) */ __be16 vlan_prio; /* Only last 3 bits valid (valid values: 0..7) */
__be16 vlan_tpid; __be16 vlan_tpid;
}; };
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment