diff options
author | Martyna Szapar-Mudlaw <martyna.szapar-mudlaw@intel.com> | 2022-03-26 13:35:36 +0100 |
---|---|---|
committer | Tony Nguyen <anthony.l.nguyen@intel.com> | 2022-06-30 13:53:25 -0700 |
commit | 06bca7c2685a9ab129ede0272de00d92c40347ac (patch) | |
tree | 5555d21f94bace036fc3678ff8bf861ea58948ee /drivers/net/ethernet/intel/ice/ice_tc_lib.c | |
parent | bf48c3fae6d78d6418f62bd3259cd62dd16f83ec (diff) | |
download | lwn-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.c | 43 |
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; |