]> git.baikalelectronics.ru Git - kernel.git/commitdiff
octeontx2-pf: Add vlan-etype to ntuple filters
authorSubbaraya Sundeep <sbhatta@marvell.com>
Fri, 27 Aug 2021 13:30:55 +0000 (19:00 +0530)
committerDavid S. Miller <davem@davemloft.net>
Sun, 29 Aug 2021 09:48:32 +0000 (10:48 +0100)
NPC extraction profile marks layer types
NPC_LT_LB_CTAG for CTAG and NPC_LT_LB_STAG_QINQ for
STAG after parsing input packet. Those layer types
can be used to install ntuple filters using
vlan-etype option. Below are the commands and
corresponding behavior with this patch in place.

> alias nt "ethtool -U eth0 flow-type ether"

> nt vlan 5 m 0xf000 action 0
Input packets with outer VLAN id as 5 i.e,
stag packets with VLAN id 5 and ctag packets with
VLAN id as 5 are hit.

> nt vlan-etype 0x8100 action 0
All input ctag packets with any VLAN id are hit.

> nt vlan-etype 0x88A8 action 0
All input stag packets with any VLAN id are hit.

> nt vlan-etype 0x8100 vlan 5 m 0xf000 action 0
All input ctag packets with VLAN id 5 are hit.

> nt vlan-etype 0x88A8 vlan 5 m 0xf000 action 0
All input stag packets with VLAN id 5 are hit.

Signed-off-by: Subbaraya Sundeep <sbhatta@marvell.com>
Signed-off-by: Sunil Goutham <sgoutham@marvell.com>
Signed-off-by: David S. Miller <davem@davemloft.net>
drivers/net/ethernet/marvell/octeontx2/af/npc.h
drivers/net/ethernet/marvell/octeontx2/af/rvu_npc_fs.c
drivers/net/ethernet/marvell/octeontx2/nic/otx2_common.h
drivers/net/ethernet/marvell/octeontx2/nic/otx2_flows.c

index 999ee9d2055f7e363a26a5773526fa36ff03099f..3a819b24accc66aa42cefb845a10f37249a74ed8 100644 (file)
@@ -169,6 +169,8 @@ enum key_fields {
        NPC_DMAC,
        NPC_SMAC,
        NPC_ETYPE,
+       NPC_VLAN_ETYPE_CTAG, /* 0x8100 */
+       NPC_VLAN_ETYPE_STAG, /* 0x88A8 */
        NPC_OUTER_VID,
        NPC_TOS,
        NPC_SIP_IPV4,
index ceb666a84890ae84dff5f203d6f448e5997fedf5..51ddc7b81d0bd5b1ad16b57b2b02e115e3aa1cfb 100644 (file)
@@ -20,6 +20,8 @@ static const char * const npc_flow_names[] = {
        [NPC_DMAC]      = "dmac",
        [NPC_SMAC]      = "smac",
        [NPC_ETYPE]     = "ether type",
+       [NPC_VLAN_ETYPE_CTAG] = "vlan ether type ctag",
+       [NPC_VLAN_ETYPE_STAG] = "vlan ether type stag",
        [NPC_OUTER_VID] = "outer vlan id",
        [NPC_TOS]       = "tos",
        [NPC_SIP_IPV4]  = "ipv4 source ip",
@@ -492,6 +494,11 @@ static void npc_set_features(struct rvu *rvu, int blkaddr, u8 intf)
        if (*features & BIT_ULL(NPC_OUTER_VID))
                if (!npc_check_field(rvu, blkaddr, NPC_LB, intf))
                        *features &= ~BIT_ULL(NPC_OUTER_VID);
+
+       /* for vlan ethertypes corresponding layer type should be in the key */
+       if (npc_check_field(rvu, blkaddr, NPC_LB, intf))
+               *features |= BIT_ULL(NPC_VLAN_ETYPE_CTAG) |
+                            BIT_ULL(NPC_VLAN_ETYPE_STAG);
 }
 
 /* Scan key extraction profile and record how fields of our interest
@@ -747,6 +754,28 @@ static void npc_update_ipv6_flow(struct rvu *rvu, struct mcam_entry *entry,
        }
 }
 
+static void npc_update_vlan_features(struct rvu *rvu, struct mcam_entry *entry,
+                                    u64 features, u8 intf)
+{
+       bool ctag = !!(features & BIT_ULL(NPC_VLAN_ETYPE_CTAG));
+       bool stag = !!(features & BIT_ULL(NPC_VLAN_ETYPE_STAG));
+       bool vid = !!(features & BIT_ULL(NPC_OUTER_VID));
+
+       /* If only VLAN id is given then always match outer VLAN id */
+       if (vid && !ctag && !stag) {
+               npc_update_entry(rvu, NPC_LB, entry,
+                                NPC_LT_LB_STAG_QINQ | NPC_LT_LB_CTAG, 0,
+                                NPC_LT_LB_STAG_QINQ & NPC_LT_LB_CTAG, 0, intf);
+               return;
+       }
+       if (ctag)
+               npc_update_entry(rvu, NPC_LB, entry, NPC_LT_LB_CTAG, 0,
+                                ~0ULL, 0, intf);
+       if (stag)
+               npc_update_entry(rvu, NPC_LB, entry, NPC_LT_LB_STAG_QINQ, 0,
+                                ~0ULL, 0, intf);
+}
+
 static void npc_update_flow(struct rvu *rvu, struct mcam_entry *entry,
                            u64 features, struct flow_msg *pkt,
                            struct flow_msg *mask,
@@ -779,11 +808,6 @@ static void npc_update_flow(struct rvu *rvu, struct mcam_entry *entry,
                npc_update_entry(rvu, NPC_LD, entry, NPC_LT_LD_ICMP6,
                                 0, ~0ULL, 0, intf);
 
-       if (features & BIT_ULL(NPC_OUTER_VID))
-               npc_update_entry(rvu, NPC_LB, entry,
-                                NPC_LT_LB_STAG_QINQ | NPC_LT_LB_CTAG, 0,
-                                NPC_LT_LB_STAG_QINQ & NPC_LT_LB_CTAG, 0, intf);
-
        /* For AH, LTYPE should be present in entry */
        if (features & BIT_ULL(NPC_IPPROTO_AH))
                npc_update_entry(rvu, NPC_LD, entry, NPC_LT_LD_AH,
@@ -829,6 +853,7 @@ do {                                                                              \
                       ntohs(mask->vlan_tci), 0);
 
        npc_update_ipv6_flow(rvu, entry, features, pkt, mask, output, intf);
+       npc_update_vlan_features(rvu, entry, features, intf);
 }
 
 static struct rvu_npc_mcam_rule *rvu_mcam_find_rule(struct npc_mcam *mcam,
index 6229399fb694d7bc56ee3388949b999dc2fd97d1..48227cec06eefd0f8cc96930949dc9de441c2219 100644 (file)
@@ -835,8 +835,6 @@ int otx2_get_all_flows(struct otx2_nic *pfvf,
 int otx2_add_flow(struct otx2_nic *pfvf,
                  struct ethtool_rxnfc *nfc);
 int otx2_remove_flow(struct otx2_nic *pfvf, u32 location);
-int otx2_prepare_flow_request(struct ethtool_rx_flow_spec *fsp,
-                             struct npc_install_flow_req *req);
 int otx2_get_maxflows(struct otx2_flow_config *flow_cfg);
 void otx2_rss_ctx_flow_del(struct otx2_nic *pfvf, int ctx_id);
 int otx2_del_macfilter(struct net_device *netdev, const u8 *mac);
index e33491927207d9eb9058a0dd2786309cdb493eaf..77a13fb555fb64631e5e862070abcff4aec81339 100644 (file)
@@ -763,7 +763,7 @@ static int otx2_prepare_ipv6_flow(struct ethtool_rx_flow_spec *fsp,
        return 0;
 }
 
-int otx2_prepare_flow_request(struct ethtool_rx_flow_spec *fsp,
+static int otx2_prepare_flow_request(struct ethtool_rx_flow_spec *fsp,
                              struct npc_install_flow_req *req)
 {
        struct ethhdr *eth_mask = &fsp->m_u.ether_spec;
@@ -819,8 +819,30 @@ int otx2_prepare_flow_request(struct ethtool_rx_flow_spec *fsp,
                return -EOPNOTSUPP;
        }
        if (fsp->flow_type & FLOW_EXT) {
-               if (fsp->m_ext.vlan_etype)
-                       return -EINVAL;
+               u16 vlan_etype;
+
+               if (fsp->m_ext.vlan_etype) {
+                       /* Partial masks not supported */
+                       if (be16_to_cpu(fsp->m_ext.vlan_etype) != 0xFFFF)
+                               return -EINVAL;
+
+                       vlan_etype = be16_to_cpu(fsp->h_ext.vlan_etype);
+                       /* Only ETH_P_8021Q and ETH_P_802AD types supported */
+                       if (vlan_etype != ETH_P_8021Q &&
+                           vlan_etype != ETH_P_8021AD)
+                               return -EINVAL;
+
+                       memcpy(&pkt->vlan_etype, &fsp->h_ext.vlan_etype,
+                              sizeof(pkt->vlan_etype));
+                       memcpy(&pmask->vlan_etype, &fsp->m_ext.vlan_etype,
+                              sizeof(pmask->vlan_etype));
+
+                       if (vlan_etype == ETH_P_8021Q)
+                               req->features |= BIT_ULL(NPC_VLAN_ETYPE_CTAG);
+                       else
+                               req->features |= BIT_ULL(NPC_VLAN_ETYPE_STAG);
+               }
+
                if (fsp->m_ext.vlan_tci) {
                        memcpy(&pkt->vlan_tci, &fsp->h_ext.vlan_tci,
                               sizeof(pkt->vlan_tci));
@@ -996,6 +1018,7 @@ int otx2_add_flow(struct otx2_nic *pfvf, struct ethtool_rxnfc *nfc)
                if (!flow)
                        return -ENOMEM;
                flow->location = fsp->location;
+               flow->entry = flow_cfg->flow_ent[flow->location];
                new = true;
        }
        /* struct copy */
@@ -1047,7 +1070,6 @@ int otx2_add_flow(struct otx2_nic *pfvf, struct ethtool_rxnfc *nfc)
                                    flow_cfg->max_flows - 1);
                        err = -EINVAL;
                } else {
-                       flow->entry = flow_cfg->flow_ent[flow->location];
                        err = otx2_add_flow_msg(pfvf, flow);
                }
        }