octeontx2-af: TC flower offload support for inner VLAN
authorSuman Ghosh <sumang@marvell.com>
Fri, 4 Aug 2023 04:59:35 +0000 (10:29 +0530)
committerJakub Kicinski <kuba@kernel.org>
Tue, 8 Aug 2023 02:15:59 +0000 (19:15 -0700)
Extend the current TC flower offload support to enable filters matching
inner VLAN, and support offload of those filters to hardware.

Signed-off-by: Suman Ghosh <sumang@marvell.com>
Reviewed-by: Simon Horman <horms@kernel.org>
Link: https://lore.kernel.org/r/20230804045935.3010554-3-sumang@marvell.com
Signed-off-by: Jakub Kicinski <kuba@kernel.org>
drivers/net/ethernet/marvell/octeontx2/af/mbox.h
drivers/net/ethernet/marvell/octeontx2/af/npc.h
drivers/net/ethernet/marvell/octeontx2/af/rvu_debugfs.c
drivers/net/ethernet/marvell/octeontx2/af/rvu_npc_fs.c
drivers/net/ethernet/marvell/octeontx2/nic/otx2_tc.c

index a8f3c8f..e2f2b21 100644 (file)
@@ -1465,6 +1465,7 @@ struct flow_msg {
                u8 ip_flag;
                u8 next_header;
        };
+       __be16 vlan_itci;
 };
 
 struct npc_install_flow_req {
index 534f20c..de9fbd9 100644 (file)
@@ -184,6 +184,7 @@ enum key_fields {
        NPC_VLAN_ETYPE_CTAG, /* 0x8100 */
        NPC_VLAN_ETYPE_STAG, /* 0x88A8 */
        NPC_OUTER_VID,
+       NPC_INNER_VID,
        NPC_TOS,
        NPC_IPFRAG_IPV4,
        NPC_SIP_IPV4,
@@ -230,6 +231,8 @@ enum key_fields {
        NPC_VLAN_TAG1,
        /* outer vlan tci for double tagged frame */
        NPC_VLAN_TAG2,
+       /* inner vlan tci for double tagged frame */
+       NPC_VLAN_TAG3,
        /* other header fields programmed to extract but not of our interest */
        NPC_UNKNOWN,
        NPC_KEY_FIELDS_MAX,
index 7cd33ed..d30e848 100644 (file)
@@ -2787,6 +2787,11 @@ static void rvu_dbg_npc_mcam_show_flows(struct seq_file *s,
                        seq_printf(s, "mask 0x%x\n",
                                   ntohs(rule->mask.vlan_tci));
                        break;
+               case NPC_INNER_VID:
+                       seq_printf(s, "0x%x ", ntohs(rule->packet.vlan_itci));
+                       seq_printf(s, "mask 0x%x\n",
+                                  ntohs(rule->mask.vlan_itci));
+                       break;
                case NPC_TOS:
                        seq_printf(s, "%d ", rule->packet.tos);
                        seq_printf(s, "mask 0x%x\n", rule->mask.tos);
index bb715e6..5c8f9fc 100644 (file)
@@ -20,6 +20,7 @@ static const char * const npc_flow_names[] = {
        [NPC_VLAN_ETYPE_CTAG] = "vlan ether type ctag",
        [NPC_VLAN_ETYPE_STAG] = "vlan ether type stag",
        [NPC_OUTER_VID] = "outer vlan id",
+       [NPC_INNER_VID] = "inner vlan id",
        [NPC_TOS]       = "tos",
        [NPC_IPFRAG_IPV4] = "fragmented IPv4 header ",
        [NPC_SIP_IPV4]  = "ipv4 source ip",
@@ -328,6 +329,8 @@ static void npc_handle_multi_layer_fields(struct rvu *rvu, int blkaddr, u8 intf)
         */
        struct npc_key_field *vlan_tag1;
        struct npc_key_field *vlan_tag2;
+       /* Inner VLAN TCI for double tagged frames */
+       struct npc_key_field *vlan_tag3;
        u64 *features;
        u8 start_lid;
        int i;
@@ -350,6 +353,7 @@ static void npc_handle_multi_layer_fields(struct rvu *rvu, int blkaddr, u8 intf)
        etype_tag2 = &key_fields[NPC_ETYPE_TAG2];
        vlan_tag1 = &key_fields[NPC_VLAN_TAG1];
        vlan_tag2 = &key_fields[NPC_VLAN_TAG2];
+       vlan_tag3 = &key_fields[NPC_VLAN_TAG3];
 
        /* if key profile programmed does not extract Ethertype at all */
        if (!etype_ether->nr_kws && !etype_tag1->nr_kws && !etype_tag2->nr_kws) {
@@ -431,6 +435,12 @@ vlan_tci:
                goto done;
        }
        *features |= BIT_ULL(NPC_OUTER_VID);
+
+       /* If key profile extracts inner vlan tci */
+       if (vlan_tag3->nr_kws) {
+               key_fields[NPC_INNER_VID] = *vlan_tag3;
+               *features |= BIT_ULL(NPC_INNER_VID);
+       }
 done:
        return;
 }
@@ -513,6 +523,7 @@ do {                                                                               \
        NPC_SCAN_HDR(NPC_ETYPE_TAG2, NPC_LID_LB, NPC_LT_LB_STAG_QINQ, 8, 2);
        NPC_SCAN_HDR(NPC_VLAN_TAG1, NPC_LID_LB, NPC_LT_LB_CTAG, 2, 2);
        NPC_SCAN_HDR(NPC_VLAN_TAG2, NPC_LID_LB, NPC_LT_LB_STAG_QINQ, 2, 2);
+       NPC_SCAN_HDR(NPC_VLAN_TAG3, NPC_LID_LB, NPC_LT_LB_STAG_QINQ, 6, 2);
        NPC_SCAN_HDR(NPC_DMAC, NPC_LID_LA, la_ltype, la_start, 6);
 
        NPC_SCAN_HDR(NPC_IPSEC_SPI, NPC_LID_LD, NPC_LT_LD_AH, 4, 4);
@@ -943,6 +954,8 @@ do {                                                                              \
 
        NPC_WRITE_FLOW(NPC_OUTER_VID, vlan_tci, ntohs(pkt->vlan_tci), 0,
                       ntohs(mask->vlan_tci), 0);
+       NPC_WRITE_FLOW(NPC_INNER_VID, vlan_itci, ntohs(pkt->vlan_itci), 0,
+                      ntohs(mask->vlan_itci), 0);
 
        NPC_WRITE_FLOW(NPC_IPFRAG_IPV6, next_header, pkt->next_header, 0,
                       mask->next_header, 0);
index c535e81..fab9d85 100644 (file)
@@ -447,10 +447,11 @@ static int otx2_tc_process_vlan(struct otx2_nic *nic, struct flow_msg *flow_spec
        u16 vlan_tci, vlan_tci_mask;
 
        if (is_inner)
-               return -EOPNOTSUPP;
+               flow_rule_match_cvlan(rule, &match);
+       else
+               flow_rule_match_vlan(rule, &match);
 
-       flow_rule_match_vlan(rule, &match);
-       if (ntohs(match.key->vlan_tpid) != ETH_P_8021Q) {
+       if (!eth_type_vlan(match.key->vlan_tpid)) {
                netdev_err(nic->netdev, "vlan tpid 0x%x not supported\n",
                           ntohs(match.key->vlan_tpid));
                return -EOPNOTSUPP;
@@ -480,9 +481,15 @@ static int otx2_tc_process_vlan(struct otx2_nic *nic, struct flow_msg *flow_spec
                vlan_tci_mask = match.mask->vlan_id |
                                match.mask->vlan_dei << 12 |
                                match.mask->vlan_priority << 13;
-               flow_spec->vlan_tci = htons(vlan_tci);
-               flow_mask->vlan_tci = htons(vlan_tci_mask);
-               req->features |= BIT_ULL(NPC_OUTER_VID);
+               if (is_inner) {
+                       flow_spec->vlan_itci = htons(vlan_tci);
+                       flow_mask->vlan_itci = htons(vlan_tci_mask);
+                       req->features |= BIT_ULL(NPC_INNER_VID);
+               } else {
+                       flow_spec->vlan_tci = htons(vlan_tci);
+                       flow_mask->vlan_tci = htons(vlan_tci_mask);
+                       req->features |= BIT_ULL(NPC_OUTER_VID);
+               }
        }
 
        return 0;
@@ -507,6 +514,7 @@ static int otx2_tc_prepare_flow(struct otx2_nic *nic, struct otx2_tc_flow *node,
              BIT_ULL(FLOW_DISSECTOR_KEY_BASIC) |
              BIT_ULL(FLOW_DISSECTOR_KEY_ETH_ADDRS) |
              BIT_ULL(FLOW_DISSECTOR_KEY_VLAN) |
+             BIT(FLOW_DISSECTOR_KEY_CVLAN) |
              BIT_ULL(FLOW_DISSECTOR_KEY_IPV4_ADDRS) |
              BIT_ULL(FLOW_DISSECTOR_KEY_IPV6_ADDRS) |
              BIT_ULL(FLOW_DISSECTOR_KEY_PORTS) |
@@ -647,6 +655,14 @@ static int otx2_tc_prepare_flow(struct otx2_nic *nic, struct otx2_tc_flow *node,
                        return ret;
        }
 
+       if (flow_rule_match_key(rule, FLOW_DISSECTOR_KEY_CVLAN)) {
+               int ret;
+
+               ret = otx2_tc_process_vlan(nic, flow_spec, flow_mask, rule, req, true);
+               if (ret)
+                       return ret;
+       }
+
        if (flow_rule_match_key(rule, FLOW_DISSECTOR_KEY_IPV4_ADDRS)) {
                struct flow_match_ipv4_addrs match;