summaryrefslogtreecommitdiff
path: root/drivers/net/ethernet/intel/ice/ice_tc_lib.c
diff options
context:
space:
mode:
authorMartyna Szapar-Mudlaw <martyna.szapar-mudlaw@intel.com>2022-03-26 13:35:36 +0100
committerTony Nguyen <anthony.l.nguyen@intel.com>2022-06-30 13:53:25 -0700
commit06bca7c2685a9ab129ede0272de00d92c40347ac (patch)
tree5555d21f94bace036fc3678ff8bf861ea58948ee /drivers/net/ethernet/intel/ice/ice_tc_lib.c
parentbf48c3fae6d78d6418f62bd3259cd62dd16f83ec (diff)
downloadlwn-06bca7c2685a9ab129ede0272de00d92c40347ac.tar.gz
lwn-06bca7c2685a9ab129ede0272de00d92c40347ac.zip
ice: Add support for double VLAN in switchdev
Enable support for adding TC rules with both C-tag and S-tag that can filter on the inner and outer VLAN in QinQ for basic packets (not tunneled cases). Signed-off-by: Wiktor Pilarczyk <wiktor.pilarczyk@intel.com> Signed-off-by: Martyna Szapar-Mudlaw <martyna.szapar-mudlaw@intel.com> Reviewed-by: Alexander Lobakin <alexandr.lobakin@intel.com> Tested-by: Sandeep Penigalapati <sandeep.penigalapati@intel.com> Signed-off-by: Tony Nguyen <anthony.l.nguyen@intel.com>
Diffstat (limited to 'drivers/net/ethernet/intel/ice/ice_tc_lib.c')
-rw-r--r--drivers/net/ethernet/intel/ice/ice_tc_lib.c43
1 files changed, 42 insertions, 1 deletions
diff --git a/drivers/net/ethernet/intel/ice/ice_tc_lib.c b/drivers/net/ethernet/intel/ice/ice_tc_lib.c
index b803f2ab3cc7..faf5bfd8d157 100644
--- a/drivers/net/ethernet/intel/ice/ice_tc_lib.c
+++ b/drivers/net/ethernet/intel/ice/ice_tc_lib.c
@@ -50,6 +50,10 @@ ice_tc_count_lkups(u32 flags, struct ice_tc_flower_lyr_2_4_hdrs *headers,
if (flags & ICE_TC_FLWR_FIELD_VLAN)
lkups_cnt++;
+ /* is CVLAN specified? */
+ if (flags & ICE_TC_FLWR_FIELD_CVLAN)
+ lkups_cnt++;
+
/* are IPv[4|6] fields specified? */
if (flags & (ICE_TC_FLWR_FIELD_DEST_IPV4 | ICE_TC_FLWR_FIELD_SRC_IPV4 |
ICE_TC_FLWR_FIELD_DEST_IPV6 | ICE_TC_FLWR_FIELD_SRC_IPV6))
@@ -311,12 +315,22 @@ ice_tc_fill_rules(struct ice_hw *hw, u32 flags,
/* copy VLAN info */
if (flags & ICE_TC_FLWR_FIELD_VLAN) {
- list[i].type = ICE_VLAN_OFOS;
+ if (flags & ICE_TC_FLWR_FIELD_CVLAN)
+ list[i].type = ICE_VLAN_EX;
+ else
+ 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);
i++;
}
+ if (flags & ICE_TC_FLWR_FIELD_CVLAN) {
+ 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);
+ i++;
+ }
+
/* copy L3 (IPv[4|6]: src, dest) address */
if (flags & (ICE_TC_FLWR_FIELD_DEST_IPV4 |
ICE_TC_FLWR_FIELD_SRC_IPV4)) {
@@ -945,6 +959,7 @@ ice_parse_cls_flower(struct net_device *filter_dev, struct ice_vsi *vsi,
BIT(FLOW_DISSECTOR_KEY_BASIC) |
BIT(FLOW_DISSECTOR_KEY_ETH_ADDRS) |
BIT(FLOW_DISSECTOR_KEY_VLAN) |
+ BIT(FLOW_DISSECTOR_KEY_CVLAN) |
BIT(FLOW_DISSECTOR_KEY_IPV4_ADDRS) |
BIT(FLOW_DISSECTOR_KEY_IPV6_ADDRS) |
BIT(FLOW_DISSECTOR_KEY_ENC_CONTROL) |
@@ -1062,6 +1077,32 @@ ice_parse_cls_flower(struct net_device *filter_dev, struct ice_vsi *vsi,
headers->vlan_hdr.vlan_prio = match.key->vlan_priority;
}
+ if (flow_rule_match_key(rule, FLOW_DISSECTOR_KEY_CVLAN)) {
+ struct flow_match_vlan match;
+
+ if (!ice_is_dvm_ena(&vsi->back->hw)) {
+ NL_SET_ERR_MSG_MOD(fltr->extack, "Double VLAN mode is not enabled");
+ return -EINVAL;
+ }
+
+ flow_rule_match_cvlan(rule, &match);
+
+ if (match.mask->vlan_id) {
+ if (match.mask->vlan_id == VLAN_VID_MASK) {
+ fltr->flags |= ICE_TC_FLWR_FIELD_CVLAN;
+ } else {
+ NL_SET_ERR_MSG_MOD(fltr->extack,
+ "Bad CVLAN mask");
+ return -EINVAL;
+ }
+ }
+
+ headers->cvlan_hdr.vlan_id =
+ cpu_to_be16(match.key->vlan_id & VLAN_VID_MASK);
+ if (match.mask->vlan_priority)
+ headers->cvlan_hdr.vlan_prio = match.key->vlan_priority;
+ }
+
if (flow_rule_match_key(rule, FLOW_DISSECTOR_KEY_CONTROL)) {
struct flow_match_control match;