ice: Add support for double VLAN in switchdev
authorMartyna Szapar-Mudlaw <martyna.szapar-mudlaw@intel.com>
Sat, 26 Mar 2022 12:35:36 +0000 (13:35 +0100)
committerTony Nguyen <anthony.l.nguyen@intel.com>
Thu, 30 Jun 2022 20:53:25 +0000 (13:53 -0700)
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>
drivers/net/ethernet/intel/ice/ice_protocol_type.h
drivers/net/ethernet/intel/ice/ice_switch.c
drivers/net/ethernet/intel/ice/ice_tc_lib.c
drivers/net/ethernet/intel/ice/ice_tc_lib.h

index 3f64300b0e14a71a5cd26d2a210a906ceca760e5..f8bd0990641b91e724573aa193e08cf12279c3fb 100644 (file)
@@ -43,6 +43,8 @@ enum ice_protocol_type {
        ICE_NVGRE,
        ICE_GTP,
        ICE_GTP_NO_PAY,
+       ICE_VLAN_EX,
+       ICE_VLAN_IN,
        ICE_VXLAN_GPE,
        ICE_SCTP_IL,
        ICE_PROTOCOL_LAST
index 8d8f3eec79eebabe85d486eddfa413f810b451da..85816a73f09f19294d04f28b701663020456f47d 100644 (file)
@@ -41,6 +41,7 @@ enum {
        ICE_PKT_INNER_TCP       = BIT(7),
        ICE_PKT_INNER_UDP       = BIT(8),
        ICE_PKT_GTP_NOPAY       = BIT(9),
+       ICE_PKT_CVLAN           = BIT(10),
 };
 
 struct ice_dummy_pkt_offsets {
@@ -1233,7 +1234,225 @@ ICE_DECLARE_PKT_TEMPLATE(ipv6_gtp) = {
        0x00, 0x00,
 };
 
+ICE_DECLARE_PKT_OFFSETS(qinq_ipv4) = {
+       { ICE_MAC_OFOS,         0 },
+       { ICE_VLAN_EX,          12 },
+       { ICE_VLAN_IN,          16 },
+       { ICE_ETYPE_OL,         20 },
+       { ICE_IPV4_OFOS,        22 },
+       { ICE_PROTOCOL_LAST,    0 },
+};
+
+ICE_DECLARE_PKT_TEMPLATE(qinq_ipv4) = {
+       0x00, 0x00, 0x00, 0x00, /* ICE_MAC_OFOS 0 */
+       0x00, 0x00, 0x00, 0x00,
+       0x00, 0x00, 0x00, 0x00,
+
+       0x91, 0x00, 0x00, 0x00, /* ICE_VLAN_EX 12 */
+       0x81, 0x00, 0x00, 0x00, /* ICE_VLAN_IN 16 */
+       0x08, 0x00,             /* ICE_ETYPE_OL 20 */
+
+       0x45, 0x00, 0x00, 0x14, /* ICE_IPV4_OFOS 22 */
+       0x00, 0x01, 0x00, 0x00,
+       0x00, 0x00, 0x00, 0x00,
+       0x00, 0x00, 0x00, 0x00,
+       0x00, 0x00, 0x00, 0x00,
+
+       0x00, 0x00,             /* 2 bytes for 4 byte alignment */
+};
+
+ICE_DECLARE_PKT_OFFSETS(qinq_ipv4_udp) = {
+       { ICE_MAC_OFOS,         0 },
+       { ICE_VLAN_EX,          12 },
+       { ICE_VLAN_IN,          16 },
+       { ICE_ETYPE_OL,         20 },
+       { ICE_IPV4_OFOS,        22 },
+       { ICE_UDP_ILOS,         42 },
+       { ICE_PROTOCOL_LAST,    0 },
+};
+
+ICE_DECLARE_PKT_TEMPLATE(qinq_ipv4_udp) = {
+       0x00, 0x00, 0x00, 0x00, /* ICE_MAC_OFOS 0 */
+       0x00, 0x00, 0x00, 0x00,
+       0x00, 0x00, 0x00, 0x00,
+
+       0x91, 0x00, 0x00, 0x00, /* ICE_VLAN_EX 12 */
+       0x81, 0x00, 0x00, 0x00, /* ICE_VLAN_IN 16 */
+       0x08, 0x00,             /* ICE_ETYPE_OL 20 */
+
+       0x45, 0x00, 0x00, 0x1c, /* ICE_IPV4_OFOS 22 */
+       0x00, 0x01, 0x00, 0x00,
+       0x00, 0x11, 0x00, 0x00,
+       0x00, 0x00, 0x00, 0x00,
+       0x00, 0x00, 0x00, 0x00,
+
+       0x00, 0x00, 0x00, 0x00, /* ICE_UDP_ILOS 42 */
+       0x00, 0x08, 0x00, 0x00,
+
+       0x00, 0x00,             /* 2 bytes for 4 byte alignment */
+};
+
+ICE_DECLARE_PKT_OFFSETS(qinq_ipv4_tcp) = {
+       { ICE_MAC_OFOS,         0 },
+       { ICE_VLAN_EX,          12 },
+       { ICE_VLAN_IN,          16 },
+       { ICE_ETYPE_OL,         20 },
+       { ICE_IPV4_OFOS,        22 },
+       { ICE_TCP_IL,           42 },
+       { ICE_PROTOCOL_LAST,    0 },
+};
+
+ICE_DECLARE_PKT_TEMPLATE(qinq_ipv4_tcp) = {
+       0x00, 0x00, 0x00, 0x00, /* ICE_MAC_OFOS 0 */
+       0x00, 0x00, 0x00, 0x00,
+       0x00, 0x00, 0x00, 0x00,
+
+       0x91, 0x00, 0x00, 0x00, /* ICE_VLAN_EX 12 */
+       0x81, 0x00, 0x00, 0x00, /* ICE_VLAN_IN 16 */
+       0x08, 0x00,             /* ICE_ETYPE_OL 20 */
+
+       0x45, 0x00, 0x00, 0x28, /* ICE_IPV4_OFOS 22 */
+       0x00, 0x01, 0x00, 0x00,
+       0x00, 0x06, 0x00, 0x00,
+       0x00, 0x00, 0x00, 0x00,
+       0x00, 0x00, 0x00, 0x00,
+
+       0x00, 0x00, 0x00, 0x00, /* ICE_TCP_IL 42 */
+       0x00, 0x00, 0x00, 0x00,
+       0x00, 0x00, 0x00, 0x00,
+       0x50, 0x00, 0x00, 0x00,
+       0x00, 0x00, 0x00, 0x00,
+
+       0x00, 0x00,             /* 2 bytes for 4 byte alignment */
+};
+
+ICE_DECLARE_PKT_OFFSETS(qinq_ipv6) = {
+       { ICE_MAC_OFOS,         0 },
+       { ICE_VLAN_EX,          12 },
+       { ICE_VLAN_IN,          16 },
+       { ICE_ETYPE_OL,         20 },
+       { ICE_IPV6_OFOS,        22 },
+       { ICE_PROTOCOL_LAST,    0 },
+};
+
+ICE_DECLARE_PKT_TEMPLATE(qinq_ipv6) = {
+       0x00, 0x00, 0x00, 0x00, /* ICE_MAC_OFOS 0 */
+       0x00, 0x00, 0x00, 0x00,
+       0x00, 0x00, 0x00, 0x00,
+
+       0x91, 0x00, 0x00, 0x00, /* ICE_VLAN_EX 12 */
+       0x81, 0x00, 0x00, 0x00, /* ICE_VLAN_IN 16 */
+       0x86, 0xDD,             /* ICE_ETYPE_OL 20 */
+
+       0x60, 0x00, 0x00, 0x00, /* ICE_IPV6_OFOS 22 */
+       0x00, 0x00, 0x3b, 0x00,
+       0x00, 0x00, 0x00, 0x00,
+       0x00, 0x00, 0x00, 0x00,
+       0x00, 0x00, 0x00, 0x00,
+       0x00, 0x00, 0x00, 0x00,
+       0x00, 0x00, 0x00, 0x00,
+       0x00, 0x00, 0x00, 0x00,
+       0x00, 0x00, 0x00, 0x00,
+       0x00, 0x00, 0x00, 0x00,
+
+       0x00, 0x00,             /* 2 bytes for 4 byte alignment */
+};
+
+ICE_DECLARE_PKT_OFFSETS(qinq_ipv6_udp) = {
+       { ICE_MAC_OFOS,         0 },
+       { ICE_VLAN_EX,          12 },
+       { ICE_VLAN_IN,          16 },
+       { ICE_ETYPE_OL,         20 },
+       { ICE_IPV6_OFOS,        22 },
+       { ICE_UDP_ILOS,         62 },
+       { ICE_PROTOCOL_LAST,    0 },
+};
+
+ICE_DECLARE_PKT_TEMPLATE(qinq_ipv6_udp) = {
+       0x00, 0x00, 0x00, 0x00, /* ICE_MAC_OFOS 0 */
+       0x00, 0x00, 0x00, 0x00,
+       0x00, 0x00, 0x00, 0x00,
+
+       0x91, 0x00, 0x00, 0x00, /* ICE_VLAN_EX 12 */
+       0x81, 0x00, 0x00, 0x00, /* ICE_VLAN_IN 16 */
+       0x86, 0xDD,             /* ICE_ETYPE_OL 20 */
+
+       0x60, 0x00, 0x00, 0x00, /* ICE_IPV6_OFOS 22 */
+       0x00, 0x08, 0x11, 0x00, /* Next header UDP */
+       0x00, 0x00, 0x00, 0x00,
+       0x00, 0x00, 0x00, 0x00,
+       0x00, 0x00, 0x00, 0x00,
+       0x00, 0x00, 0x00, 0x00,
+       0x00, 0x00, 0x00, 0x00,
+       0x00, 0x00, 0x00, 0x00,
+       0x00, 0x00, 0x00, 0x00,
+       0x00, 0x00, 0x00, 0x00,
+
+       0x00, 0x00, 0x00, 0x00, /* ICE_UDP_ILOS 62 */
+       0x00, 0x08, 0x00, 0x00,
+
+       0x00, 0x00,             /* 2 bytes for 4 byte alignment */
+};
+
+ICE_DECLARE_PKT_OFFSETS(qinq_ipv6_tcp) = {
+       { ICE_MAC_OFOS,         0 },
+       { ICE_VLAN_EX,          12 },
+       { ICE_VLAN_IN,          16 },
+       { ICE_ETYPE_OL,         20 },
+       { ICE_IPV6_OFOS,        22 },
+       { ICE_TCP_IL,           62 },
+       { ICE_PROTOCOL_LAST,    0 },
+};
+
+ICE_DECLARE_PKT_TEMPLATE(qinq_ipv6_tcp) = {
+       0x00, 0x00, 0x00, 0x00, /* ICE_MAC_OFOS 0 */
+       0x00, 0x00, 0x00, 0x00,
+       0x00, 0x00, 0x00, 0x00,
+
+       0x91, 0x00, 0x00, 0x00, /* ICE_VLAN_EX 12 */
+       0x81, 0x00, 0x00, 0x00, /* ICE_VLAN_IN 16 */
+       0x86, 0xDD,             /* ICE_ETYPE_OL 20 */
+
+       0x60, 0x00, 0x00, 0x00, /* ICE_IPV6_OFOS 22 */
+       0x00, 0x14, 0x06, 0x00, /* Next header TCP */
+       0x00, 0x00, 0x00, 0x00,
+       0x00, 0x00, 0x00, 0x00,
+       0x00, 0x00, 0x00, 0x00,
+       0x00, 0x00, 0x00, 0x00,
+       0x00, 0x00, 0x00, 0x00,
+       0x00, 0x00, 0x00, 0x00,
+       0x00, 0x00, 0x00, 0x00,
+       0x00, 0x00, 0x00, 0x00,
+
+       0x00, 0x00, 0x00, 0x00, /* ICE_TCP_IL 62 */
+       0x00, 0x00, 0x00, 0x00,
+       0x00, 0x00, 0x00, 0x00,
+       0x50, 0x00, 0x00, 0x00,
+       0x00, 0x00, 0x00, 0x00,
+
+       0x00, 0x00,             /* 2 bytes for 4 byte alignment */
+};
+
 static const struct ice_dummy_pkt_profile ice_dummy_pkt_profiles[] = {
+       ICE_PKT_PROFILE(qinq_ipv6_tcp, ICE_PKT_CVLAN |
+                                      ICE_PKT_VLAN |
+                                      ICE_PKT_OUTER_IPV6 |
+                                      ICE_PKT_INNER_TCP),
+       ICE_PKT_PROFILE(qinq_ipv6_udp, ICE_PKT_CVLAN |
+                                      ICE_PKT_VLAN |
+                                      ICE_PKT_OUTER_IPV6 |
+                                      ICE_PKT_INNER_UDP),
+       ICE_PKT_PROFILE(qinq_ipv6, ICE_PKT_CVLAN |
+                                  ICE_PKT_VLAN |
+                                  ICE_PKT_OUTER_IPV6),
+       ICE_PKT_PROFILE(qinq_ipv4_tcp, ICE_PKT_CVLAN |
+                                      ICE_PKT_VLAN |
+                                      ICE_PKT_INNER_TCP),
+       ICE_PKT_PROFILE(qinq_ipv4_udp, ICE_PKT_CVLAN |
+                                      ICE_PKT_VLAN |
+                                      ICE_PKT_INNER_UDP),
+       ICE_PKT_PROFILE(qinq_ipv4, ICE_PKT_CVLAN |
+                                  ICE_PKT_VLAN),
        ICE_PKT_PROFILE(ipv6_gtp, ICE_PKT_TUN_GTPU | ICE_PKT_OUTER_IPV6 |
                                  ICE_PKT_GTP_NOPAY),
        ICE_PKT_PROFILE(ipv6_gtpu_ipv6_udp, ICE_PKT_TUN_GTPU |
@@ -4609,6 +4828,8 @@ static const struct ice_prot_ext_tbl_entry ice_prot_ext[ICE_PROTOCOL_LAST] = {
        { ICE_NVGRE,            { 0, 2, 4, 6 } },
        { ICE_GTP,              { 8, 10, 12, 14, 16, 18, 20, 22 } },
        { ICE_GTP_NO_PAY,       { 8, 10, 12, 14 } },
+       { ICE_VLAN_EX,          { 2, 0 } },
+       { ICE_VLAN_IN,          { 2, 0 } },
 };
 
 static struct ice_protocol_entry ice_prot_id_tbl[ICE_PROTOCOL_LAST] = {
@@ -4629,6 +4850,8 @@ static struct ice_protocol_entry ice_prot_id_tbl[ICE_PROTOCOL_LAST] = {
        { ICE_NVGRE,            ICE_GRE_OF_HW },
        { ICE_GTP,              ICE_UDP_OF_HW },
        { ICE_GTP_NO_PAY,       ICE_UDP_ILOS_HW },
+       { ICE_VLAN_EX,          ICE_VLAN_OF_HW },
+       { ICE_VLAN_IN,          ICE_VLAN_OL_HW },
 };
 
 /**
@@ -5597,8 +5820,11 @@ ice_find_dummy_packet(struct ice_adv_lkup_elem *lkups, u16 lkups_cnt,
                        match |= ICE_PKT_INNER_TCP;
                else if (lkups[i].type == ICE_IPV6_OFOS)
                        match |= ICE_PKT_OUTER_IPV6;
-               else if (lkups[i].type == ICE_VLAN_OFOS)
+               else if (lkups[i].type == ICE_VLAN_OFOS ||
+                        lkups[i].type == ICE_VLAN_EX)
                        match |= ICE_PKT_VLAN;
+               else if (lkups[i].type == ICE_VLAN_IN)
+                       match |= ICE_PKT_CVLAN;
                else if (lkups[i].type == ICE_ETYPE_OL &&
                         lkups[i].h_u.ethertype.ethtype_id ==
                                cpu_to_be16(ICE_IPV6_ETHER_ID) &&
@@ -5678,6 +5904,8 @@ ice_fill_adv_dummy_packet(struct ice_adv_lkup_elem *lkups, u16 lkups_cnt,
                        len = sizeof(struct ice_ethtype_hdr);
                        break;
                case ICE_VLAN_OFOS:
+               case ICE_VLAN_EX:
+               case ICE_VLAN_IN:
                        len = sizeof(struct ice_vlan_hdr);
                        break;
                case ICE_IPV4_OFOS:
index b803f2ab3cc769f023b596f423564e9b1be9ca6d..faf5bfd8d157873376907a4d83fc32390148a703 100644 (file)
@@ -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;
 
index e25e958f43964bcd6580de3ae5ce49fd00576b84..87acfe5b0e4dddb36e39c06c0e0c23a58068561e 100644 (file)
@@ -23,6 +23,7 @@
 #define ICE_TC_FLWR_FIELD_ENC_DST_MAC          BIT(16)
 #define ICE_TC_FLWR_FIELD_ETH_TYPE_ID          BIT(17)
 #define ICE_TC_FLWR_FIELD_ENC_OPTS             BIT(18)
+#define ICE_TC_FLWR_FIELD_CVLAN                        BIT(19)
 
 #define ICE_TC_FLOWER_MASK_32   0xFFFFFFFF
 
@@ -81,6 +82,7 @@ struct ice_tc_flower_lyr_2_4_hdrs {
        struct ice_tc_l2_hdr l2_key;
        struct ice_tc_l2_hdr l2_mask;
        struct ice_tc_vlan_hdr vlan_hdr;
+       struct ice_tc_vlan_hdr cvlan_hdr;
        /* L3 (IPv4[6]) layer fields with their mask */
        struct ice_tc_l3_hdr l3_key;
        struct ice_tc_l3_hdr l3_mask;