2020-11-11 07:23:18

by Naveen Mamindlapalli

[permalink] [raw]
Subject: [PATCH v3 net-next 00/13] Add ethtool ntuple filters support

This patch series adds support for ethtool ntuple filters, unicast
address filtering, VLAN offload and SR-IOV ndo handlers. All of the
above features are based on the Admin Function(AF) driver support to
install and delete the low level MCAM entries. Each MCAM entry is
programmed with the packet fields to match and what actions to take
if the match succeeds. The PF driver requests AF driver to allocate
set of MCAM entries to be used to install the flows by that PF. The
entries will be freed when the PF driver is unloaded.

* The patches 1 to 4 adds AF driver infrastructure to install and
delete the low level MCAM flow entries.
* Patch 5 adds ethtool ntuple filter support.
* Patch 6 adds unicast MAC address filtering.
* Patch 7 adds support for dumping the MCAM entries via debugfs.
* Patches 8 to 10 adds support for VLAN offload.
* Patch 10 to 11 adds support for SR-IOV ndo handlers.
* Patch 12 adds support to read the MCAM entries.

Misc:
* Removed redundant mailbox NIX_RXVLAN_ALLOC.

Change-log:
v3:
- Fixed Saeed's review comments on v2.
- Fixed modifying the netdev->flags from driver.
- Fixed modifying the netdev features and hw_features after register_netdev.
- Removed unwanted ndo_features_check callback.
v2:
- Fixed the sparse issues reported by Jakub.

Hariprasad Kelam (3):
octeontx2-pf: Add support for unicast MAC address filtering
octeontx2-pf: Implement ingress/egress VLAN offload
octeontx2-af: Handle PF-VF mac address changes

Naveen Mamindlapalli (2):
octeontx2-pf: Add support for SR-IOV management functions
octeontx2-af: Add new mbox messages to retrieve MCAM entries

Stanislaw Kardach (1):
octeontx2-af: Modify default KEX profile to extract TX packet fields

Subbaraya Sundeep (6):
octeontx2-af: Verify MCAM entry channel and PF_FUNC
octeontx2-af: Generate key field bit mask from KEX profile
octeontx2-af: Add mbox messages to install and delete MCAM rules
octeontx2-pf: Add support for ethtool ntuple filters
octeontx2-af: Add debugfs entry to dump the MCAM rules
octeontx2-af: Delete NIX_RXVLAN_ALLOC mailbox message

Vamsi Attunuru (1):
octeontx2-af: Modify nix_vtag_cfg mailbox to support TX VTAG entries

drivers/net/ethernet/marvell/octeontx2/af/Makefile | 2 +-
drivers/net/ethernet/marvell/octeontx2/af/common.h | 2 +
drivers/net/ethernet/marvell/octeontx2/af/mbox.h | 170 ++-
drivers/net/ethernet/marvell/octeontx2/af/npc.h | 106 +-
.../ethernet/marvell/octeontx2/af/npc_profile.h | 71 +-
drivers/net/ethernet/marvell/octeontx2/af/rvu.c | 16 +-
drivers/net/ethernet/marvell/octeontx2/af/rvu.h | 71 +-
.../ethernet/marvell/octeontx2/af/rvu_debugfs.c | 197 +++
.../net/ethernet/marvell/octeontx2/af/rvu_nix.c | 305 ++++-
.../net/ethernet/marvell/octeontx2/af/rvu_npc.c | 462 ++++++-
.../net/ethernet/marvell/octeontx2/af/rvu_npc_fs.c | 1334 ++++++++++++++++++++
.../net/ethernet/marvell/octeontx2/af/rvu_struct.h | 11 +
.../net/ethernet/marvell/octeontx2/nic/Makefile | 2 +-
.../ethernet/marvell/octeontx2/nic/otx2_common.c | 8 +-
.../ethernet/marvell/octeontx2/nic/otx2_common.h | 59 +
.../ethernet/marvell/octeontx2/nic/otx2_ethtool.c | 58 +-
.../ethernet/marvell/octeontx2/nic/otx2_flows.c | 820 ++++++++++++
.../net/ethernet/marvell/octeontx2/nic/otx2_pf.c | 307 ++++-
.../net/ethernet/marvell/octeontx2/nic/otx2_txrx.c | 16 +
.../net/ethernet/marvell/octeontx2/nic/otx2_vf.c | 5 +
20 files changed, 3862 insertions(+), 160 deletions(-)
create mode 100644 drivers/net/ethernet/marvell/octeontx2/af/rvu_npc_fs.c
create mode 100644 drivers/net/ethernet/marvell/octeontx2/nic/otx2_flows.c

--
2.16.5


2020-11-11 07:24:01

by Naveen Mamindlapalli

[permalink] [raw]
Subject: [PATCH v3 net-next 06/13] octeontx2-pf: Add support for unicast MAC address filtering

From: Hariprasad Kelam <[email protected]>

Add unicast MAC address filtering support using install flow
message. Total of 8 MCAM entries are allocated for adding
unicast mac filtering rules. If the MCAM allocation fails,
the unicast filtering support will not be advertised.

Signed-off-by: Hariprasad Kelam <[email protected]>
Signed-off-by: Sunil Goutham <[email protected]>
Signed-off-by: Naveen Mamindlapalli <[email protected]>
---
.../ethernet/marvell/octeontx2/nic/otx2_common.h | 15 ++-
.../ethernet/marvell/octeontx2/nic/otx2_flows.c | 120 ++++++++++++++++++++-
.../net/ethernet/marvell/octeontx2/nic/otx2_pf.c | 15 ++-
3 files changed, 143 insertions(+), 7 deletions(-)

diff --git a/drivers/net/ethernet/marvell/octeontx2/nic/otx2_common.h b/drivers/net/ethernet/marvell/octeontx2/nic/otx2_common.h
index 2387c40a2a8f..f959688e14a3 100644
--- a/drivers/net/ethernet/marvell/octeontx2/nic/otx2_common.h
+++ b/drivers/net/ethernet/marvell/octeontx2/nic/otx2_common.h
@@ -229,12 +229,21 @@ struct otx2_ptp {

#define OTX2_HW_TIMESTAMP_LEN 8

+struct otx2_mac_table {
+ u8 addr[ETH_ALEN];
+ u16 mcam_entry;
+ bool inuse;
+};
+
struct otx2_flow_config {
u16 entry[NPC_MAX_NONCONTIG_ENTRIES];
u32 nr_flows;
#define OTX2_MAX_NTUPLE_FLOWS 32
-#define OTX2_MCAM_COUNT OTX2_MAX_NTUPLE_FLOWS
+#define OTX2_MAX_UNICAST_FLOWS 8
+#define OTX2_MCAM_COUNT (OTX2_MAX_NTUPLE_FLOWS + \
+ OTX2_MAX_UNICAST_FLOWS)
u32 ntuple_offset;
+ u32 unicast_offset;
u32 ntuple_max_flows;
struct list_head flow_list;
};
@@ -251,6 +260,7 @@ struct otx2_nic {
#define OTX2_FLAG_INTF_DOWN BIT_ULL(2)
#define OTX2_FLAG_MCAM_ENTRIES_ALLOC BIT_ULL(3)
#define OTX2_FLAG_NTUPLE_SUPPORT BIT_ULL(4)
+#define OTX2_FLAG_UCAST_FLTR_SUPPORT BIT_ULL(5)
#define OTX2_FLAG_RX_PAUSE_ENABLED BIT_ULL(9)
#define OTX2_FLAG_TX_PAUSE_ENABLED BIT_ULL(10)
u64 flags;
@@ -279,6 +289,7 @@ struct otx2_nic {
struct refill_work *refill_wrk;
struct workqueue_struct *otx2_wq;
struct work_struct rx_mode_work;
+ struct otx2_mac_table *mac_table;

/* Ethtool stuff */
u32 msg_enable;
@@ -674,5 +685,7 @@ int otx2_add_flow(struct otx2_nic *pfvf,
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_del_macfilter(struct net_device *netdev, const u8 *mac);
+int otx2_add_macfilter(struct net_device *netdev, const u8 *mac);

#endif /* OTX2_COMMON_H */
diff --git a/drivers/net/ethernet/marvell/octeontx2/nic/otx2_flows.c b/drivers/net/ethernet/marvell/octeontx2/nic/otx2_flows.c
index 094f547c9889..7da80aa3f063 100644
--- a/drivers/net/ethernet/marvell/octeontx2/nic/otx2_flows.c
+++ b/drivers/net/ethernet/marvell/octeontx2/nic/otx2_flows.c
@@ -46,14 +46,21 @@ int otx2_alloc_mcam_entries(struct otx2_nic *pfvf)
rsp = (struct npc_mcam_alloc_entry_rsp *)otx2_mbox_get_rsp
(&pfvf->mbox.mbox, 0, &req->hdr);

- if (rsp->count != req->count)
+ if (rsp->count != req->count) {
netdev_info(pfvf->netdev,
"Unable to allocate %d MCAM entries, got %d\n",
req->count, rsp->count);
-
- flow_cfg->ntuple_max_flows = rsp->count;
- flow_cfg->ntuple_offset = 0;
- pfvf->flags |= OTX2_FLAG_NTUPLE_SUPPORT;
+ /* support only ntuples here */
+ flow_cfg->ntuple_max_flows = rsp->count;
+ flow_cfg->ntuple_offset = 0;
+ pfvf->flags |= OTX2_FLAG_NTUPLE_SUPPORT;
+ } else {
+ flow_cfg->ntuple_offset = 0;
+ flow_cfg->unicast_offset = flow_cfg->ntuple_offset +
+ OTX2_MAX_NTUPLE_FLOWS;
+ pfvf->flags |= OTX2_FLAG_NTUPLE_SUPPORT;
+ pfvf->flags |= OTX2_FLAG_UCAST_FLTR_SUPPORT;
+ }

for (i = 0; i < rsp->count; i++)
flow_cfg->entry[i] = rsp->entry_list[i];
@@ -82,6 +89,11 @@ int otx2_mcam_flow_init(struct otx2_nic *pf)
if (err)
return err;

+ pf->mac_table = devm_kzalloc(pf->dev, sizeof(struct otx2_mac_table)
+ * OTX2_MAX_UNICAST_FLOWS, GFP_KERNEL);
+ if (!pf->mac_table)
+ return -ENOMEM;
+
return 0;
}

@@ -90,6 +102,104 @@ void otx2_mcam_flow_del(struct otx2_nic *pf)
otx2_destroy_mcam_flows(pf);
}

+/* On success adds mcam entry
+ * On failure enable promisous mode
+ */
+static int otx2_do_add_macfilter(struct otx2_nic *pf, const u8 *mac)
+{
+ struct otx2_flow_config *flow_cfg = pf->flow_cfg;
+ struct npc_install_flow_req *req;
+ int err, i;
+
+ if (!(pf->flags & OTX2_FLAG_UCAST_FLTR_SUPPORT))
+ return -ENOMEM;
+
+ /* dont have free mcam entries or uc list is greater than alloted */
+ if (netdev_uc_count(pf->netdev) > OTX2_MAX_UNICAST_FLOWS)
+ return -ENOMEM;
+
+ mutex_lock(&pf->mbox.lock);
+ req = otx2_mbox_alloc_msg_npc_install_flow(&pf->mbox);
+ if (!req) {
+ mutex_unlock(&pf->mbox.lock);
+ return -ENOMEM;
+ }
+
+ /* unicast offset starts with 32 0..31 for ntuple */
+ for (i = 0; i < OTX2_MAX_UNICAST_FLOWS; i++) {
+ if (pf->mac_table[i].inuse)
+ continue;
+ ether_addr_copy(pf->mac_table[i].addr, mac);
+ pf->mac_table[i].inuse = true;
+ pf->mac_table[i].mcam_entry =
+ flow_cfg->entry[i + flow_cfg->unicast_offset];
+ req->entry = pf->mac_table[i].mcam_entry;
+ break;
+ }
+
+ ether_addr_copy(req->packet.dmac, mac);
+ eth_broadcast_addr((u8 *)&req->mask.dmac);
+ req->features = BIT_ULL(NPC_DMAC);
+ req->channel = pf->hw.rx_chan_base;
+ req->intf = NIX_INTF_RX;
+ req->op = NIX_RX_ACTION_DEFAULT;
+ req->set_cntr = 1;
+
+ err = otx2_sync_mbox_msg(&pf->mbox);
+ mutex_unlock(&pf->mbox.lock);
+
+ return err;
+}
+
+int otx2_add_macfilter(struct net_device *netdev, const u8 *mac)
+{
+ struct otx2_nic *pf = netdev_priv(netdev);
+
+ return otx2_do_add_macfilter(pf, mac);
+}
+
+static bool otx2_get_mcamentry_for_mac(struct otx2_nic *pf, const u8 *mac,
+ int *mcam_entry)
+{
+ int i;
+
+ for (i = 0; i < OTX2_MAX_UNICAST_FLOWS; i++) {
+ if (!pf->mac_table[i].inuse)
+ continue;
+
+ if (ether_addr_equal(pf->mac_table[i].addr, mac)) {
+ *mcam_entry = pf->mac_table[i].mcam_entry;
+ pf->mac_table[i].inuse = false;
+ return true;
+ }
+ }
+ return false;
+}
+
+int otx2_del_macfilter(struct net_device *netdev, const u8 *mac)
+{
+ struct otx2_nic *pf = netdev_priv(netdev);
+ struct npc_delete_flow_req *req;
+ int err, mcam_entry;
+
+ /* check does mcam entry exists for given mac */
+ if (!otx2_get_mcamentry_for_mac(pf, mac, &mcam_entry))
+ return 0;
+
+ mutex_lock(&pf->mbox.lock);
+ req = otx2_mbox_alloc_msg_npc_delete_flow(&pf->mbox);
+ if (!req) {
+ mutex_unlock(&pf->mbox.lock);
+ return -ENOMEM;
+ }
+ req->entry = mcam_entry;
+ /* Send message to AF */
+ err = otx2_sync_mbox_msg(&pf->mbox);
+ mutex_unlock(&pf->mbox.lock);
+
+ return err;
+}
+
static struct otx2_flow *otx2_find_flow(struct otx2_nic *pfvf, u32 location)
{
struct otx2_flow *iter;
diff --git a/drivers/net/ethernet/marvell/octeontx2/nic/otx2_pf.c b/drivers/net/ethernet/marvell/octeontx2/nic/otx2_pf.c
index 9cf3e19cf1d8..ac90302b1d81 100644
--- a/drivers/net/ethernet/marvell/octeontx2/nic/otx2_pf.c
+++ b/drivers/net/ethernet/marvell/octeontx2/nic/otx2_pf.c
@@ -1720,10 +1720,20 @@ static void otx2_do_set_rx_mode(struct work_struct *work)
struct otx2_nic *pf = container_of(work, struct otx2_nic, rx_mode_work);
struct net_device *netdev = pf->netdev;
struct nix_rx_mode *req;
+ bool promisc = false;

if (!(netdev->flags & IFF_UP))
return;

+ if ((netdev->flags & IFF_PROMISC) ||
+ (netdev_uc_count(netdev) > OTX2_MAX_UNICAST_FLOWS)) {
+ promisc = true;
+ }
+
+ /* Write unicast address to mcam entries or del from mcam */
+ if (!promisc && netdev->priv_flags & IFF_UNICAST_FLT)
+ __dev_uc_sync(netdev, otx2_add_macfilter, otx2_del_macfilter);
+
mutex_lock(&pf->mbox.lock);
req = otx2_mbox_alloc_msg_nix_set_rx_mode(&pf->mbox);
if (!req) {
@@ -1733,7 +1743,7 @@ static void otx2_do_set_rx_mode(struct work_struct *work)

req->mode = NIX_RX_MODE_UCAST;

- if (netdev->flags & IFF_PROMISC)
+ if (promisc)
req->mode |= NIX_RX_MODE_PROMISC;
else if (netdev->flags & (IFF_ALLMULTI | IFF_MULTICAST))
req->mode |= NIX_RX_MODE_ALLMULTI;
@@ -2125,6 +2135,9 @@ static int otx2_probe(struct pci_dev *pdev, const struct pci_device_id *id)
if (pf->flags & OTX2_FLAG_NTUPLE_SUPPORT)
netdev->hw_features |= NETIF_F_NTUPLE;

+ if (pf->flags & OTX2_FLAG_UCAST_FLTR_SUPPORT)
+ netdev->priv_flags |= IFF_UNICAST_FLT;
+
netdev->gso_max_segs = OTX2_MAX_GSO_SEGS;
netdev->watchdog_timeo = OTX2_TX_TIMEOUT;

--
2.16.5

2020-11-11 07:25:24

by Naveen Mamindlapalli

[permalink] [raw]
Subject: [PATCH v3 net-next 05/13] octeontx2-pf: Add support for ethtool ntuple filters

From: Subbaraya Sundeep <[email protected]>

This patch adds support for adding and deleting ethtool ntuple
filters. The filters for ether, ipv4, ipv6, tcp, udp and sctp
are supported. The mask is also supported. The supported actions
are drop and direct to a queue. Additionally we support FLOW_EXT
field vlan_tci and FLOW_MAC_EXT.

The NIX PF will allocate total 32 MCAM entries for the use of
ethtool ntuple filters. The Administrative Function(AF) will
install/delete the MCAM rules when NIX PF sends mailbox message
to install/delete the ntuple filters.

Ethtool ntuple filters support is restricted to PFs as of now
and PF can install ntuple filters to direct the traffic to its
VFs. Hence added a separate callback for VFs to get/set RSS
configuration.

Signed-off-by: Subbaraya Sundeep <[email protected]>
Signed-off-by: Sunil Goutham <[email protected]>
Signed-off-by: Naveen Mamindlapalli <[email protected]>
---
.../net/ethernet/marvell/octeontx2/nic/Makefile | 2 +-
.../ethernet/marvell/octeontx2/nic/otx2_common.h | 31 ++
.../ethernet/marvell/octeontx2/nic/otx2_ethtool.c | 58 +-
.../ethernet/marvell/octeontx2/nic/otx2_flows.c | 603 +++++++++++++++++++++
.../net/ethernet/marvell/octeontx2/nic/otx2_pf.c | 18 +-
5 files changed, 707 insertions(+), 5 deletions(-)
create mode 100644 drivers/net/ethernet/marvell/octeontx2/nic/otx2_flows.c

diff --git a/drivers/net/ethernet/marvell/octeontx2/nic/Makefile b/drivers/net/ethernet/marvell/octeontx2/nic/Makefile
index b2c6385707c9..4193ae3bde6b 100644
--- a/drivers/net/ethernet/marvell/octeontx2/nic/Makefile
+++ b/drivers/net/ethernet/marvell/octeontx2/nic/Makefile
@@ -7,7 +7,7 @@ obj-$(CONFIG_OCTEONTX2_PF) += octeontx2_nicpf.o
obj-$(CONFIG_OCTEONTX2_VF) += octeontx2_nicvf.o

octeontx2_nicpf-y := otx2_pf.o otx2_common.o otx2_txrx.o otx2_ethtool.o \
- otx2_ptp.o
+ otx2_ptp.o otx2_flows.o
octeontx2_nicvf-y := otx2_vf.o

ccflags-y += -I$(srctree)/drivers/net/ethernet/marvell/octeontx2/af
diff --git a/drivers/net/ethernet/marvell/octeontx2/nic/otx2_common.h b/drivers/net/ethernet/marvell/octeontx2/nic/otx2_common.h
index 386cb08497e4..2387c40a2a8f 100644
--- a/drivers/net/ethernet/marvell/octeontx2/nic/otx2_common.h
+++ b/drivers/net/ethernet/marvell/octeontx2/nic/otx2_common.h
@@ -18,6 +18,7 @@
#include <linux/timecounter.h>

#include <mbox.h>
+#include <npc.h>
#include "otx2_reg.h"
#include "otx2_txrx.h"
#include <rvu_trace.h>
@@ -228,6 +229,16 @@ struct otx2_ptp {

#define OTX2_HW_TIMESTAMP_LEN 8

+struct otx2_flow_config {
+ u16 entry[NPC_MAX_NONCONTIG_ENTRIES];
+ u32 nr_flows;
+#define OTX2_MAX_NTUPLE_FLOWS 32
+#define OTX2_MCAM_COUNT OTX2_MAX_NTUPLE_FLOWS
+ u32 ntuple_offset;
+ u32 ntuple_max_flows;
+ struct list_head flow_list;
+};
+
struct otx2_nic {
void __iomem *reg_base;
struct net_device *netdev;
@@ -238,6 +249,8 @@ struct otx2_nic {
#define OTX2_FLAG_RX_TSTAMP_ENABLED BIT_ULL(0)
#define OTX2_FLAG_TX_TSTAMP_ENABLED BIT_ULL(1)
#define OTX2_FLAG_INTF_DOWN BIT_ULL(2)
+#define OTX2_FLAG_MCAM_ENTRIES_ALLOC BIT_ULL(3)
+#define OTX2_FLAG_NTUPLE_SUPPORT BIT_ULL(4)
#define OTX2_FLAG_RX_PAUSE_ENABLED BIT_ULL(9)
#define OTX2_FLAG_TX_PAUSE_ENABLED BIT_ULL(10)
u64 flags;
@@ -275,6 +288,8 @@ struct otx2_nic {

struct otx2_ptp *ptp;
struct hwtstamp_config tstamp;
+
+ struct otx2_flow_config *flow_cfg;
};

static inline bool is_otx2_lbkvf(struct pci_dev *pdev)
@@ -644,4 +659,20 @@ int otx2_open(struct net_device *netdev);
int otx2_stop(struct net_device *netdev);
int otx2_set_real_num_queues(struct net_device *netdev,
int tx_queues, int rx_queues);
+/* MCAM filter related APIs */
+int otx2_mcam_flow_init(struct otx2_nic *pf);
+int otx2_alloc_mcam_entries(struct otx2_nic *pfvf);
+void otx2_mcam_flow_del(struct otx2_nic *pf);
+int otx2_destroy_ntuple_flows(struct otx2_nic *pf);
+int otx2_destroy_mcam_flows(struct otx2_nic *pfvf);
+int otx2_get_flow(struct otx2_nic *pfvf,
+ struct ethtool_rxnfc *nfc, u32 location);
+int otx2_get_all_flows(struct otx2_nic *pfvf,
+ struct ethtool_rxnfc *nfc, u32 *rule_locs);
+int otx2_add_flow(struct otx2_nic *pfvf,
+ struct ethtool_rx_flow_spec *fsp);
+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);
+
#endif /* OTX2_COMMON_H */
diff --git a/drivers/net/ethernet/marvell/octeontx2/nic/otx2_ethtool.c b/drivers/net/ethernet/marvell/octeontx2/nic/otx2_ethtool.c
index 662fb80dbb9d..67171b66a56c 100644
--- a/drivers/net/ethernet/marvell/octeontx2/nic/otx2_ethtool.c
+++ b/drivers/net/ethernet/marvell/octeontx2/nic/otx2_ethtool.c
@@ -551,6 +551,16 @@ static int otx2_get_rxnfc(struct net_device *dev,
nfc->data = pfvf->hw.rx_queues;
ret = 0;
break;
+ case ETHTOOL_GRXCLSRLCNT:
+ nfc->rule_cnt = pfvf->flow_cfg->nr_flows;
+ ret = 0;
+ break;
+ case ETHTOOL_GRXCLSRULE:
+ ret = otx2_get_flow(pfvf, nfc, nfc->fs.location);
+ break;
+ case ETHTOOL_GRXCLSRLALL:
+ ret = otx2_get_all_flows(pfvf, nfc, rules);
+ break;
case ETHTOOL_GRXFH:
return otx2_get_rss_hash_opts(pfvf, nfc);
default:
@@ -560,6 +570,50 @@ static int otx2_get_rxnfc(struct net_device *dev,
}

static int otx2_set_rxnfc(struct net_device *dev, struct ethtool_rxnfc *nfc)
+{
+ bool ntuple = !!(dev->features & NETIF_F_NTUPLE);
+ struct otx2_nic *pfvf = netdev_priv(dev);
+ int ret = -EOPNOTSUPP;
+
+ switch (nfc->cmd) {
+ case ETHTOOL_SRXFH:
+ ret = otx2_set_rss_hash_opts(pfvf, nfc);
+ break;
+ case ETHTOOL_SRXCLSRLINS:
+ if (netif_running(dev) && ntuple)
+ ret = otx2_add_flow(pfvf, &nfc->fs);
+ break;
+ case ETHTOOL_SRXCLSRLDEL:
+ if (netif_running(dev) && ntuple)
+ ret = otx2_remove_flow(pfvf, nfc->fs.location);
+ break;
+ default:
+ break;
+ }
+
+ return ret;
+}
+
+static int otx2vf_get_rxnfc(struct net_device *dev,
+ struct ethtool_rxnfc *nfc, u32 *rules)
+{
+ struct otx2_nic *pfvf = netdev_priv(dev);
+ int ret = -EOPNOTSUPP;
+
+ switch (nfc->cmd) {
+ case ETHTOOL_GRXRINGS:
+ nfc->data = pfvf->hw.rx_queues;
+ ret = 0;
+ break;
+ case ETHTOOL_GRXFH:
+ return otx2_get_rss_hash_opts(pfvf, nfc);
+ default:
+ break;
+ }
+ return ret;
+}
+
+static int otx2vf_set_rxnfc(struct net_device *dev, struct ethtool_rxnfc *nfc)
{
struct otx2_nic *pfvf = netdev_priv(dev);
int ret = -EOPNOTSUPP;
@@ -806,8 +860,8 @@ static const struct ethtool_ops otx2vf_ethtool_ops = {
.get_sset_count = otx2vf_get_sset_count,
.set_channels = otx2_set_channels,
.get_channels = otx2_get_channels,
- .get_rxnfc = otx2_get_rxnfc,
- .set_rxnfc = otx2_set_rxnfc,
+ .get_rxnfc = otx2vf_get_rxnfc,
+ .set_rxnfc = otx2vf_set_rxnfc,
.get_rxfh_key_size = otx2_get_rxfh_key_size,
.get_rxfh_indir_size = otx2_get_rxfh_indir_size,
.get_rxfh = otx2_get_rxfh,
diff --git a/drivers/net/ethernet/marvell/octeontx2/nic/otx2_flows.c b/drivers/net/ethernet/marvell/octeontx2/nic/otx2_flows.c
new file mode 100644
index 000000000000..094f547c9889
--- /dev/null
+++ b/drivers/net/ethernet/marvell/octeontx2/nic/otx2_flows.c
@@ -0,0 +1,603 @@
+// SPDX-License-Identifier: GPL-2.0
+/* Marvell OcteonTx2 RVU Physcial Function ethernet driver
+ *
+ * Copyright (C) 2020 Marvell International Ltd.
+ */
+
+#include <net/ipv6.h>
+
+#include "otx2_common.h"
+
+#define OTX2_DEFAULT_ACTION 0x1
+
+struct otx2_flow {
+ struct ethtool_rx_flow_spec flow_spec;
+ struct list_head list;
+ u32 location;
+ u16 entry;
+ bool is_vf;
+ int vf;
+};
+
+int otx2_alloc_mcam_entries(struct otx2_nic *pfvf)
+{
+ struct otx2_flow_config *flow_cfg = pfvf->flow_cfg;
+ struct npc_mcam_alloc_entry_req *req;
+ struct npc_mcam_alloc_entry_rsp *rsp;
+ int i;
+
+ mutex_lock(&pfvf->mbox.lock);
+
+ req = otx2_mbox_alloc_msg_npc_mcam_alloc_entry(&pfvf->mbox);
+ if (!req) {
+ mutex_unlock(&pfvf->mbox.lock);
+ return -ENOMEM;
+ }
+
+ req->contig = false;
+ req->count = OTX2_MCAM_COUNT;
+
+ /* Send message to AF */
+ if (otx2_sync_mbox_msg(&pfvf->mbox)) {
+ mutex_unlock(&pfvf->mbox.lock);
+ return -EINVAL;
+ }
+
+ rsp = (struct npc_mcam_alloc_entry_rsp *)otx2_mbox_get_rsp
+ (&pfvf->mbox.mbox, 0, &req->hdr);
+
+ if (rsp->count != req->count)
+ netdev_info(pfvf->netdev,
+ "Unable to allocate %d MCAM entries, got %d\n",
+ req->count, rsp->count);
+
+ flow_cfg->ntuple_max_flows = rsp->count;
+ flow_cfg->ntuple_offset = 0;
+ pfvf->flags |= OTX2_FLAG_NTUPLE_SUPPORT;
+
+ for (i = 0; i < rsp->count; i++)
+ flow_cfg->entry[i] = rsp->entry_list[i];
+
+ pfvf->flags |= OTX2_FLAG_MCAM_ENTRIES_ALLOC;
+
+ mutex_unlock(&pfvf->mbox.lock);
+
+ return 0;
+}
+
+int otx2_mcam_flow_init(struct otx2_nic *pf)
+{
+ int err;
+
+ pf->flow_cfg = devm_kzalloc(pf->dev, sizeof(struct otx2_flow_config),
+ GFP_KERNEL);
+ if (!pf->flow_cfg)
+ return -ENOMEM;
+
+ INIT_LIST_HEAD(&pf->flow_cfg->flow_list);
+
+ pf->flow_cfg->ntuple_max_flows = OTX2_MAX_NTUPLE_FLOWS;
+
+ err = otx2_alloc_mcam_entries(pf);
+ if (err)
+ return err;
+
+ return 0;
+}
+
+void otx2_mcam_flow_del(struct otx2_nic *pf)
+{
+ otx2_destroy_mcam_flows(pf);
+}
+
+static struct otx2_flow *otx2_find_flow(struct otx2_nic *pfvf, u32 location)
+{
+ struct otx2_flow *iter;
+
+ list_for_each_entry(iter, &pfvf->flow_cfg->flow_list, list) {
+ if (iter->location == location)
+ return iter;
+ }
+
+ return NULL;
+}
+
+static void otx2_add_flow_to_list(struct otx2_nic *pfvf, struct otx2_flow *flow)
+{
+ struct list_head *head = &pfvf->flow_cfg->flow_list;
+ struct otx2_flow *iter;
+
+ list_for_each_entry(iter, &pfvf->flow_cfg->flow_list, list) {
+ if (iter->location > flow->location)
+ break;
+ head = &iter->list;
+ }
+
+ list_add(&flow->list, head);
+}
+
+int otx2_get_flow(struct otx2_nic *pfvf, struct ethtool_rxnfc *nfc,
+ u32 location)
+{
+ struct otx2_flow *iter;
+
+ if (location >= pfvf->flow_cfg->ntuple_max_flows)
+ return -EINVAL;
+
+ list_for_each_entry(iter, &pfvf->flow_cfg->flow_list, list) {
+ if (iter->location == location) {
+ nfc->fs = iter->flow_spec;
+ return 0;
+ }
+ }
+
+ return -ENOENT;
+}
+
+int otx2_get_all_flows(struct otx2_nic *pfvf, struct ethtool_rxnfc *nfc,
+ u32 *rule_locs)
+{
+ u32 location = 0;
+ int idx = 0;
+ int err = 0;
+
+ nfc->data = pfvf->flow_cfg->ntuple_max_flows;
+ while ((!err || err == -ENOENT) && idx < nfc->rule_cnt) {
+ err = otx2_get_flow(pfvf, nfc, location);
+ if (!err)
+ rule_locs[idx++] = location;
+ location++;
+ }
+
+ return err;
+}
+
+static void otx2_prepare_ipv4_flow(struct ethtool_rx_flow_spec *fsp,
+ struct npc_install_flow_req *req,
+ u32 flow_type)
+{
+ struct ethtool_usrip4_spec *ipv4_usr_mask = &fsp->m_u.usr_ip4_spec;
+ struct ethtool_usrip4_spec *ipv4_usr_hdr = &fsp->h_u.usr_ip4_spec;
+ struct ethtool_tcpip4_spec *ipv4_l4_mask = &fsp->m_u.tcp_ip4_spec;
+ struct ethtool_tcpip4_spec *ipv4_l4_hdr = &fsp->h_u.tcp_ip4_spec;
+ struct flow_msg *pmask = &req->mask;
+ struct flow_msg *pkt = &req->packet;
+
+ switch (flow_type) {
+ case IP_USER_FLOW:
+ if (ipv4_usr_mask->ip4src) {
+ memcpy(&pkt->ip4src, &ipv4_usr_hdr->ip4src,
+ sizeof(pkt->ip4src));
+ memcpy(&pmask->ip4src, &ipv4_usr_mask->ip4src,
+ sizeof(pmask->ip4src));
+ req->features |= BIT_ULL(NPC_SIP_IPV4);
+ }
+ if (ipv4_usr_mask->ip4dst) {
+ memcpy(&pkt->ip4dst, &ipv4_usr_hdr->ip4dst,
+ sizeof(pkt->ip4dst));
+ memcpy(&pmask->ip4dst, &ipv4_usr_mask->ip4dst,
+ sizeof(pmask->ip4dst));
+ req->features |= BIT_ULL(NPC_DIP_IPV4);
+ }
+ break;
+ case TCP_V4_FLOW:
+ case UDP_V4_FLOW:
+ case SCTP_V4_FLOW:
+ if (ipv4_l4_mask->ip4src) {
+ memcpy(&pkt->ip4src, &ipv4_l4_hdr->ip4src,
+ sizeof(pkt->ip4src));
+ memcpy(&pmask->ip4src, &ipv4_l4_mask->ip4src,
+ sizeof(pmask->ip4src));
+ req->features |= BIT_ULL(NPC_SIP_IPV4);
+ }
+ if (ipv4_l4_mask->ip4dst) {
+ memcpy(&pkt->ip4dst, &ipv4_l4_hdr->ip4dst,
+ sizeof(pkt->ip4dst));
+ memcpy(&pmask->ip4dst, &ipv4_l4_mask->ip4dst,
+ sizeof(pmask->ip4dst));
+ req->features |= BIT_ULL(NPC_DIP_IPV4);
+ }
+ if (ipv4_l4_mask->psrc) {
+ memcpy(&pkt->sport, &ipv4_l4_hdr->psrc,
+ sizeof(pkt->sport));
+ memcpy(&pmask->sport, &ipv4_l4_mask->psrc,
+ sizeof(pmask->sport));
+ if (flow_type == UDP_V4_FLOW)
+ req->features |= BIT_ULL(NPC_SPORT_UDP);
+ else if (flow_type == TCP_V4_FLOW)
+ req->features |= BIT_ULL(NPC_SPORT_TCP);
+ else
+ req->features |= BIT_ULL(NPC_SPORT_SCTP);
+ }
+ if (ipv4_l4_mask->pdst) {
+ memcpy(&pkt->dport, &ipv4_l4_hdr->pdst,
+ sizeof(pkt->dport));
+ memcpy(&pmask->dport, &ipv4_l4_mask->pdst,
+ sizeof(pmask->dport));
+ if (flow_type == UDP_V4_FLOW)
+ req->features |= BIT_ULL(NPC_DPORT_UDP);
+ else if (flow_type == TCP_V4_FLOW)
+ req->features |= BIT_ULL(NPC_DPORT_TCP);
+ else
+ req->features |= BIT_ULL(NPC_DPORT_SCTP);
+ }
+ break;
+ default:
+ break;
+ }
+}
+
+static void otx2_prepare_ipv6_flow(struct ethtool_rx_flow_spec *fsp,
+ struct npc_install_flow_req *req,
+ u32 flow_type)
+{
+ struct ethtool_usrip6_spec *ipv6_usr_mask = &fsp->m_u.usr_ip6_spec;
+ struct ethtool_usrip6_spec *ipv6_usr_hdr = &fsp->h_u.usr_ip6_spec;
+ struct ethtool_tcpip6_spec *ipv6_l4_mask = &fsp->m_u.tcp_ip6_spec;
+ struct ethtool_tcpip6_spec *ipv6_l4_hdr = &fsp->h_u.tcp_ip6_spec;
+ struct flow_msg *pmask = &req->mask;
+ struct flow_msg *pkt = &req->packet;
+
+ switch (flow_type) {
+ case IPV6_USER_FLOW:
+ if (!ipv6_addr_any((struct in6_addr *)ipv6_usr_mask->ip6src)) {
+ memcpy(&pkt->ip6src, &ipv6_usr_hdr->ip6src,
+ sizeof(pkt->ip6src));
+ memcpy(&pmask->ip6src, &ipv6_usr_mask->ip6src,
+ sizeof(pmask->ip6src));
+ req->features |= BIT_ULL(NPC_SIP_IPV6);
+ }
+ if (!ipv6_addr_any((struct in6_addr *)ipv6_usr_mask->ip6dst)) {
+ memcpy(&pkt->ip6dst, &ipv6_usr_hdr->ip6dst,
+ sizeof(pkt->ip6dst));
+ memcpy(&pmask->ip6dst, &ipv6_usr_mask->ip6dst,
+ sizeof(pmask->ip6dst));
+ req->features |= BIT_ULL(NPC_DIP_IPV6);
+ }
+ break;
+ case TCP_V6_FLOW:
+ case UDP_V6_FLOW:
+ case SCTP_V6_FLOW:
+ if (!ipv6_addr_any((struct in6_addr *)ipv6_l4_mask->ip6src)) {
+ memcpy(&pkt->ip6src, &ipv6_l4_hdr->ip6src,
+ sizeof(pkt->ip6src));
+ memcpy(&pmask->ip6src, &ipv6_l4_mask->ip6src,
+ sizeof(pmask->ip6src));
+ req->features |= BIT_ULL(NPC_SIP_IPV6);
+ }
+ if (!ipv6_addr_any((struct in6_addr *)ipv6_l4_mask->ip6dst)) {
+ memcpy(&pkt->ip6dst, &ipv6_l4_hdr->ip6dst,
+ sizeof(pkt->ip6dst));
+ memcpy(&pmask->ip6dst, &ipv6_l4_mask->ip6dst,
+ sizeof(pmask->ip6dst));
+ req->features |= BIT_ULL(NPC_DIP_IPV6);
+ }
+ if (ipv6_l4_mask->psrc) {
+ memcpy(&pkt->sport, &ipv6_l4_hdr->psrc,
+ sizeof(pkt->sport));
+ memcpy(&pmask->sport, &ipv6_l4_mask->psrc,
+ sizeof(pmask->sport));
+ if (flow_type == UDP_V6_FLOW)
+ req->features |= BIT_ULL(NPC_SPORT_UDP);
+ else if (flow_type == TCP_V6_FLOW)
+ req->features |= BIT_ULL(NPC_SPORT_TCP);
+ else
+ req->features |= BIT_ULL(NPC_SPORT_SCTP);
+ }
+ if (ipv6_l4_mask->pdst) {
+ memcpy(&pkt->dport, &ipv6_l4_hdr->pdst,
+ sizeof(pkt->dport));
+ memcpy(&pmask->dport, &ipv6_l4_mask->pdst,
+ sizeof(pmask->dport));
+ if (flow_type == UDP_V6_FLOW)
+ req->features |= BIT_ULL(NPC_DPORT_UDP);
+ else if (flow_type == TCP_V6_FLOW)
+ req->features |= BIT_ULL(NPC_DPORT_TCP);
+ else
+ req->features |= BIT_ULL(NPC_DPORT_SCTP);
+ }
+ break;
+ default:
+ break;
+ }
+}
+
+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;
+ struct ethhdr *eth_hdr = &fsp->h_u.ether_spec;
+ struct flow_msg *pmask = &req->mask;
+ struct flow_msg *pkt = &req->packet;
+ u32 flow_type;
+
+ flow_type = fsp->flow_type & ~(FLOW_EXT | FLOW_MAC_EXT);
+ switch (flow_type) {
+ /* bits not set in mask are don't care */
+ case ETHER_FLOW:
+ if (!is_zero_ether_addr(eth_mask->h_source)) {
+ ether_addr_copy(pkt->smac, eth_hdr->h_source);
+ ether_addr_copy(pmask->smac, eth_mask->h_source);
+ req->features |= BIT_ULL(NPC_SMAC);
+ }
+ if (!is_zero_ether_addr(eth_mask->h_dest)) {
+ ether_addr_copy(pkt->dmac, eth_hdr->h_dest);
+ ether_addr_copy(pmask->dmac, eth_mask->h_dest);
+ req->features |= BIT_ULL(NPC_DMAC);
+ }
+ if (eth_mask->h_proto) {
+ memcpy(&pkt->etype, &eth_hdr->h_proto,
+ sizeof(pkt->etype));
+ memcpy(&pmask->etype, &eth_mask->h_proto,
+ sizeof(pmask->etype));
+ req->features |= BIT_ULL(NPC_ETYPE);
+ }
+ break;
+ case IP_USER_FLOW:
+ case TCP_V4_FLOW:
+ case UDP_V4_FLOW:
+ case SCTP_V4_FLOW:
+ otx2_prepare_ipv4_flow(fsp, req, flow_type);
+ break;
+ case IPV6_USER_FLOW:
+ case TCP_V6_FLOW:
+ case UDP_V6_FLOW:
+ case SCTP_V6_FLOW:
+ otx2_prepare_ipv6_flow(fsp, req, flow_type);
+ break;
+ default:
+ return -EOPNOTSUPP;
+ }
+ if (fsp->flow_type & FLOW_EXT) {
+ if (fsp->m_ext.vlan_etype)
+ return -EINVAL;
+ if (fsp->m_ext.vlan_tci) {
+ if (fsp->m_ext.vlan_tci != cpu_to_be16(VLAN_VID_MASK))
+ return -EINVAL;
+ if (be16_to_cpu(fsp->h_ext.vlan_tci) >= VLAN_N_VID)
+ return -EINVAL;
+
+ memcpy(&pkt->vlan_tci, &fsp->h_ext.vlan_tci,
+ sizeof(pkt->vlan_tci));
+ memcpy(&pmask->vlan_tci, &fsp->m_ext.vlan_tci,
+ sizeof(pmask->vlan_tci));
+ req->features |= BIT_ULL(NPC_OUTER_VID);
+ }
+
+ /* Not Drop/Direct to queue but use action in default entry */
+ if (fsp->m_ext.data[1] &&
+ fsp->h_ext.data[1] == cpu_to_be32(OTX2_DEFAULT_ACTION))
+ req->op = NIX_RX_ACTION_DEFAULT;
+ }
+
+ if (fsp->flow_type & FLOW_MAC_EXT &&
+ !is_zero_ether_addr(fsp->m_ext.h_dest)) {
+ ether_addr_copy(pkt->dmac, fsp->h_ext.h_dest);
+ ether_addr_copy(pmask->dmac, fsp->m_ext.h_dest);
+ req->features |= BIT_ULL(NPC_DMAC);
+ }
+
+ if (!req->features)
+ return -EOPNOTSUPP;
+
+ return 0;
+}
+
+static int otx2_add_flow_msg(struct otx2_nic *pfvf, struct otx2_flow *flow)
+{
+ u64 ring_cookie = flow->flow_spec.ring_cookie;
+ struct npc_install_flow_req *req;
+ int err, vf = 0;
+
+ mutex_lock(&pfvf->mbox.lock);
+ req = otx2_mbox_alloc_msg_npc_install_flow(&pfvf->mbox);
+ if (!req) {
+ mutex_unlock(&pfvf->mbox.lock);
+ return -ENOMEM;
+ }
+
+ err = otx2_prepare_flow_request(&flow->flow_spec, req);
+ if (err) {
+ /* free the allocated msg above */
+ otx2_mbox_reset(&pfvf->mbox.mbox, 0);
+ mutex_unlock(&pfvf->mbox.lock);
+ return err;
+ }
+
+ req->entry = flow->entry;
+ req->intf = NIX_INTF_RX;
+ req->set_cntr = 1;
+ req->channel = pfvf->hw.rx_chan_base;
+ if (ring_cookie == RX_CLS_FLOW_DISC) {
+ req->op = NIX_RX_ACTIONOP_DROP;
+ } else {
+ /* change to unicast only if action of default entry is not
+ * requested by user
+ */
+ if (req->op != NIX_RX_ACTION_DEFAULT)
+ req->op = NIX_RX_ACTIONOP_UCAST;
+ req->index = ethtool_get_flow_spec_ring(ring_cookie);
+ vf = ethtool_get_flow_spec_ring_vf(ring_cookie);
+ if (vf > pci_num_vf(pfvf->pdev)) {
+ mutex_unlock(&pfvf->mbox.lock);
+ return -EINVAL;
+ }
+ }
+
+ /* ethtool ring_cookie has (VF + 1) for VF */
+ if (vf) {
+ req->vf = vf;
+ flow->is_vf = true;
+ flow->vf = vf;
+ }
+
+ /* Send message to AF */
+ err = otx2_sync_mbox_msg(&pfvf->mbox);
+ mutex_unlock(&pfvf->mbox.lock);
+ return err;
+}
+
+int otx2_add_flow(struct otx2_nic *pfvf, struct ethtool_rx_flow_spec *fsp)
+{
+ struct otx2_flow_config *flow_cfg = pfvf->flow_cfg;
+ u32 ring = ethtool_get_flow_spec_ring(fsp->ring_cookie);
+ struct otx2_flow *flow;
+ bool new = false;
+ int err;
+
+ if (!(pfvf->flags & OTX2_FLAG_NTUPLE_SUPPORT))
+ return -ENOMEM;
+
+ if (ring >= pfvf->hw.rx_queues && fsp->ring_cookie != RX_CLS_FLOW_DISC)
+ return -EINVAL;
+
+ if (fsp->location >= flow_cfg->ntuple_max_flows)
+ return -EINVAL;
+
+ flow = otx2_find_flow(pfvf, fsp->location);
+ if (!flow) {
+ flow = kzalloc(sizeof(*flow), GFP_ATOMIC);
+ if (!flow)
+ return -ENOMEM;
+ flow->location = fsp->location;
+ flow->entry = flow_cfg->entry[flow_cfg->ntuple_offset +
+ flow->location];
+ new = true;
+ }
+ /* struct copy */
+ flow->flow_spec = *fsp;
+
+ err = otx2_add_flow_msg(pfvf, flow);
+ if (err) {
+ if (new)
+ kfree(flow);
+ return err;
+ }
+
+ /* add the new flow installed to list */
+ if (new) {
+ otx2_add_flow_to_list(pfvf, flow);
+ flow_cfg->nr_flows++;
+ }
+
+ return 0;
+}
+
+static int otx2_remove_flow_msg(struct otx2_nic *pfvf, u16 entry, bool all)
+{
+ struct npc_delete_flow_req *req;
+ int err;
+
+ mutex_lock(&pfvf->mbox.lock);
+ req = otx2_mbox_alloc_msg_npc_delete_flow(&pfvf->mbox);
+ if (!req) {
+ mutex_unlock(&pfvf->mbox.lock);
+ return -ENOMEM;
+ }
+
+ req->entry = entry;
+ if (all)
+ req->all = 1;
+
+ /* Send message to AF */
+ err = otx2_sync_mbox_msg(&pfvf->mbox);
+ mutex_unlock(&pfvf->mbox.lock);
+ return err;
+}
+
+int otx2_remove_flow(struct otx2_nic *pfvf, u32 location)
+{
+ struct otx2_flow_config *flow_cfg = pfvf->flow_cfg;
+ struct otx2_flow *flow;
+ int err;
+
+ if (location >= flow_cfg->ntuple_max_flows)
+ return -EINVAL;
+
+ flow = otx2_find_flow(pfvf, location);
+ if (!flow)
+ return -ENOENT;
+
+ err = otx2_remove_flow_msg(pfvf, flow->entry, false);
+ if (err)
+ return err;
+
+ list_del(&flow->list);
+ kfree(flow);
+ flow_cfg->nr_flows--;
+
+ return 0;
+}
+
+int otx2_destroy_ntuple_flows(struct otx2_nic *pfvf)
+{
+ struct otx2_flow_config *flow_cfg = pfvf->flow_cfg;
+ struct npc_delete_flow_req *req;
+ struct otx2_flow *iter, *tmp;
+ int err;
+
+ if (!(pfvf->flags & OTX2_FLAG_NTUPLE_SUPPORT))
+ return 0;
+
+ mutex_lock(&pfvf->mbox.lock);
+ req = otx2_mbox_alloc_msg_npc_delete_flow(&pfvf->mbox);
+ if (!req) {
+ mutex_unlock(&pfvf->mbox.lock);
+ return -ENOMEM;
+ }
+
+ req->start = flow_cfg->entry[flow_cfg->ntuple_offset];
+ req->end = flow_cfg->entry[flow_cfg->ntuple_offset +
+ flow_cfg->ntuple_max_flows - 1];
+ err = otx2_sync_mbox_msg(&pfvf->mbox);
+ mutex_unlock(&pfvf->mbox.lock);
+
+ list_for_each_entry_safe(iter, tmp, &flow_cfg->flow_list, list) {
+ list_del(&iter->list);
+ kfree(iter);
+ flow_cfg->nr_flows--;
+ }
+ return err;
+}
+
+int otx2_destroy_mcam_flows(struct otx2_nic *pfvf)
+{
+ struct otx2_flow_config *flow_cfg = pfvf->flow_cfg;
+ struct npc_mcam_free_entry_req *req;
+ struct otx2_flow *iter, *tmp;
+ int err;
+
+ if (!(pfvf->flags & OTX2_FLAG_MCAM_ENTRIES_ALLOC))
+ return 0;
+
+ /* remove all flows */
+ err = otx2_remove_flow_msg(pfvf, 0, true);
+ if (err)
+ return err;
+
+ list_for_each_entry_safe(iter, tmp, &flow_cfg->flow_list, list) {
+ list_del(&iter->list);
+ kfree(iter);
+ flow_cfg->nr_flows--;
+ }
+
+ mutex_lock(&pfvf->mbox.lock);
+ req = otx2_mbox_alloc_msg_npc_mcam_free_entry(&pfvf->mbox);
+ if (!req) {
+ mutex_unlock(&pfvf->mbox.lock);
+ return -ENOMEM;
+ }
+
+ req->all = 1;
+ /* Send message to AF to free MCAM entries */
+ err = otx2_sync_mbox_msg(&pfvf->mbox);
+ if (err) {
+ mutex_unlock(&pfvf->mbox.lock);
+ return err;
+ }
+
+ pfvf->flags &= ~OTX2_FLAG_MCAM_ENTRIES_ALLOC;
+ mutex_unlock(&pfvf->mbox.lock);
+
+ return 0;
+}
diff --git a/drivers/net/ethernet/marvell/octeontx2/nic/otx2_pf.c b/drivers/net/ethernet/marvell/octeontx2/nic/otx2_pf.c
index 672768630557..9cf3e19cf1d8 100644
--- a/drivers/net/ethernet/marvell/octeontx2/nic/otx2_pf.c
+++ b/drivers/net/ethernet/marvell/octeontx2/nic/otx2_pf.c
@@ -1733,7 +1733,6 @@ static void otx2_do_set_rx_mode(struct work_struct *work)

req->mode = NIX_RX_MODE_UCAST;

- /* We don't support MAC address filtering yet */
if (netdev->flags & IFF_PROMISC)
req->mode |= NIX_RX_MODE_PROMISC;
else if (netdev->flags & (IFF_ALLMULTI | IFF_MULTICAST))
@@ -1747,11 +1746,16 @@ static int otx2_set_features(struct net_device *netdev,
netdev_features_t features)
{
netdev_features_t changed = features ^ netdev->features;
+ bool ntuple = !!(features & NETIF_F_NTUPLE);
struct otx2_nic *pf = netdev_priv(netdev);

if ((changed & NETIF_F_LOOPBACK) && netif_running(netdev))
return otx2_cgx_config_loopback(pf,
features & NETIF_F_LOOPBACK);
+
+ if ((changed & NETIF_F_NTUPLE) && !ntuple)
+ otx2_destroy_ntuple_flows(pf);
+
return 0;
}

@@ -2114,6 +2118,13 @@ static int otx2_probe(struct pci_dev *pdev, const struct pci_device_id *id)

netdev->hw_features |= NETIF_F_LOOPBACK | NETIF_F_RXALL;

+ err = otx2_mcam_flow_init(pf);
+ if (err)
+ goto err_ptp_destroy;
+
+ if (pf->flags & OTX2_FLAG_NTUPLE_SUPPORT)
+ netdev->hw_features |= NETIF_F_NTUPLE;
+
netdev->gso_max_segs = OTX2_MAX_GSO_SEGS;
netdev->watchdog_timeo = OTX2_TX_TIMEOUT;

@@ -2126,7 +2137,7 @@ static int otx2_probe(struct pci_dev *pdev, const struct pci_device_id *id)
err = register_netdev(netdev);
if (err) {
dev_err(dev, "Failed to register netdevice\n");
- goto err_ptp_destroy;
+ goto err_del_mcam_entries;
}

err = otx2_wq_init(pf);
@@ -2146,6 +2157,8 @@ static int otx2_probe(struct pci_dev *pdev, const struct pci_device_id *id)

err_unreg_netdev:
unregister_netdev(netdev);
+err_del_mcam_entries:
+ otx2_mcam_flow_del(pf);
err_ptp_destroy:
otx2_ptp_destroy(pf);
err_detach_rsrc:
@@ -2304,6 +2317,7 @@ static void otx2_remove(struct pci_dev *pdev)
destroy_workqueue(pf->otx2_wq);

otx2_ptp_destroy(pf);
+ otx2_mcam_flow_del(pf);
otx2_detach_resources(&pf->mbox);
otx2_disable_mbox_intr(pf);
otx2_pfaf_mbox_destroy(pf);
--
2.16.5

2020-11-11 07:25:47

by Naveen Mamindlapalli

[permalink] [raw]
Subject: [PATCH v3 net-next 01/13] octeontx2-af: Modify default KEX profile to extract TX packet fields

From: Stanislaw Kardach <[email protected]>

The current default Key Extraction(KEX) profile can only use RX
packet fields while generating the MCAM search key. The profile
can't be used for matching TX packet fields. This patch modifies
the default KEX profile to add support for extracting TX packet
fields into MCAM search key. Enabled Tx KPU packet parsing by
configuring TX PKIND in tx_parse_cfg.

Also modified the default KEX profile to extract VLAN TCI from
the LB_PTR and exact byte offset of VLAN header. The NPC KPU
parser was modified to point LB_PTR to the starting byte offset
of VLAN header which points to the tpid field.

Signed-off-by: Stanislaw Kardach <[email protected]>
Signed-off-by: Sunil Goutham <[email protected]>
Signed-off-by: Naveen Mamindlapalli <[email protected]>
---
.../ethernet/marvell/octeontx2/af/npc_profile.h | 71 ++++++++++++++++++++--
.../net/ethernet/marvell/octeontx2/af/rvu_nix.c | 6 ++
2 files changed, 72 insertions(+), 5 deletions(-)

diff --git a/drivers/net/ethernet/marvell/octeontx2/af/npc_profile.h b/drivers/net/ethernet/marvell/octeontx2/af/npc_profile.h
index 199448610e3e..c5b13385c81d 100644
--- a/drivers/net/ethernet/marvell/octeontx2/af/npc_profile.h
+++ b/drivers/net/ethernet/marvell/octeontx2/af/npc_profile.h
@@ -13386,8 +13386,8 @@ static struct npc_mcam_kex npc_mkex_default = {
.kpu_version = NPC_KPU_PROFILE_VER,
.keyx_cfg = {
/* nibble: LA..LE (ltype only) + Channel */
- [NIX_INTF_RX] = ((u64)NPC_MCAM_KEY_X2 << 32) | 0x49247,
- [NIX_INTF_TX] = ((u64)NPC_MCAM_KEY_X2 << 32) | ((1ULL << 19) - 1),
+ [NIX_INTF_RX] = ((u64)NPC_MCAM_KEY_X2 << 32) | 0x249207,
+ [NIX_INTF_TX] = ((u64)NPC_MCAM_KEY_X2 << 32) | 0x249200,
},
.intf_lid_lt_ld = {
/* Default RX MCAM KEX profile */
@@ -13405,12 +13405,14 @@ static struct npc_mcam_kex npc_mkex_default = {
/* Layer B: Single VLAN (CTAG) */
/* CTAG VLAN[2..3] + Ethertype, 4 bytes, KW0[63:32] */
[NPC_LT_LB_CTAG] = {
- KEX_LD_CFG(0x03, 0x0, 0x1, 0x0, 0x4),
+ KEX_LD_CFG(0x03, 0x2, 0x1, 0x0, 0x4),
},
/* Layer B: Stacked VLAN (STAG|QinQ) */
[NPC_LT_LB_STAG_QINQ] = {
- /* CTAG VLAN[2..3] + Ethertype, 4 bytes, KW0[63:32] */
- KEX_LD_CFG(0x03, 0x4, 0x1, 0x0, 0x4),
+ /* Outer VLAN: 2 bytes, KW0[63:48] */
+ KEX_LD_CFG(0x01, 0x2, 0x1, 0x0, 0x6),
+ /* Ethertype: 2 bytes, KW0[47:32] */
+ KEX_LD_CFG(0x01, 0x8, 0x1, 0x0, 0x4),
},
[NPC_LT_LB_FDSA] = {
/* SWITCH PORT: 1 byte, KW0[63:48] */
@@ -13450,6 +13452,65 @@ static struct npc_mcam_kex npc_mkex_default = {
},
},
},
+
+ /* Default TX MCAM KEX profile */
+ [NIX_INTF_TX] = {
+ [NPC_LID_LA] = {
+ /* Layer A: Ethernet: */
+ [NPC_LT_LA_IH_NIX_ETHER] = {
+ /* PF_FUNC: 2B , KW0 [47:32] */
+ KEX_LD_CFG(0x01, 0x0, 0x1, 0x0, 0x4),
+ /* DMAC: 6 bytes, KW1[63:16] */
+ KEX_LD_CFG(0x05, 0x8, 0x1, 0x0, 0xa),
+ },
+ },
+ [NPC_LID_LB] = {
+ /* Layer B: Single VLAN (CTAG) */
+ [NPC_LT_LB_CTAG] = {
+ /* CTAG VLAN[2..3] KW0[63:48] */
+ KEX_LD_CFG(0x01, 0x2, 0x1, 0x0, 0x6),
+ /* CTAG VLAN[2..3] KW1[15:0] */
+ KEX_LD_CFG(0x01, 0x4, 0x1, 0x0, 0x8),
+ },
+ /* Layer B: Stacked VLAN (STAG|QinQ) */
+ [NPC_LT_LB_STAG_QINQ] = {
+ /* Outer VLAN: 2 bytes, KW0[63:48] */
+ KEX_LD_CFG(0x01, 0x2, 0x1, 0x0, 0x6),
+ /* Outer VLAN: 2 Bytes, KW1[15:0] */
+ KEX_LD_CFG(0x01, 0x8, 0x1, 0x0, 0x8),
+ },
+ },
+ [NPC_LID_LC] = {
+ /* Layer C: IPv4 */
+ [NPC_LT_LC_IP] = {
+ /* SIP+DIP: 8 bytes, KW2[63:0] */
+ KEX_LD_CFG(0x07, 0xc, 0x1, 0x0, 0x10),
+ /* TOS: 1 byte, KW1[63:56] */
+ KEX_LD_CFG(0x0, 0x1, 0x1, 0x0, 0xf),
+ },
+ /* Layer C: IPv6 */
+ [NPC_LT_LC_IP6] = {
+ /* Everything up to SADDR: 8 bytes, KW2[63:0] */
+ KEX_LD_CFG(0x07, 0x0, 0x1, 0x0, 0x10),
+ },
+ },
+ [NPC_LID_LD] = {
+ /* Layer D:UDP */
+ [NPC_LT_LD_UDP] = {
+ /* SPORT: 2 bytes, KW3[15:0] */
+ KEX_LD_CFG(0x1, 0x0, 0x1, 0x0, 0x18),
+ /* DPORT: 2 bytes, KW3[31:16] */
+ KEX_LD_CFG(0x1, 0x2, 0x1, 0x0, 0x1a),
+ },
+ /* Layer D:TCP */
+ [NPC_LT_LD_TCP] = {
+ /* SPORT: 2 bytes, KW3[15:0] */
+ KEX_LD_CFG(0x1, 0x0, 0x1, 0x0, 0x18),
+ /* DPORT: 2 bytes, KW3[31:16] */
+ KEX_LD_CFG(0x1, 0x2, 0x1, 0x0, 0x1a),
+ },
+ },
+ },
},
};

diff --git a/drivers/net/ethernet/marvell/octeontx2/af/rvu_nix.c b/drivers/net/ethernet/marvell/octeontx2/af/rvu_nix.c
index 8bac1dd3a1c2..8c11abdbd9d1 100644
--- a/drivers/net/ethernet/marvell/octeontx2/af/rvu_nix.c
+++ b/drivers/net/ethernet/marvell/octeontx2/af/rvu_nix.c
@@ -57,6 +57,8 @@ enum nix_makr_fmt_indexes {
NIX_MARK_CFG_MAX,
};

+#define NIX_TX_PKIND 63ULL
+
/* For now considering MC resources needed for broadcast
* pkt replication only. i.e 256 HWVFs + 12 PFs.
*/
@@ -1182,6 +1184,10 @@ int rvu_mbox_handler_nix_lf_alloc(struct rvu *rvu,
/* Config Rx pkt length, csum checks and apad enable / disable */
rvu_write64(rvu, blkaddr, NIX_AF_LFX_RX_CFG(nixlf), req->rx_cfg);

+ /* Configure pkind for TX parse config, 63 from npc_profile */
+ cfg = NIX_TX_PKIND;
+ rvu_write64(rvu, blkaddr, NIX_AF_LFX_TX_PARSE_CFG(nixlf), cfg);
+
intf = is_afvf(pcifunc) ? NIX_INTF_TYPE_LBK : NIX_INTF_TYPE_CGX;
err = nix_interface_init(rvu, pcifunc, intf, nixlf);
if (err)
--
2.16.5

2020-11-12 19:59:12

by Saeed Mahameed

[permalink] [raw]
Subject: Re: [PATCH v3 net-next 01/13] octeontx2-af: Modify default KEX profile to extract TX packet fields

On Wed, 2020-11-11 at 12:43 +0530, Naveen Mamindlapalli wrote:
> From: Stanislaw Kardach <[email protected]>
>
> The current default Key Extraction(KEX) profile can only use RX
> packet fields while generating the MCAM search key. The profile
> can't be used for matching TX packet fields. This patch modifies
> the default KEX profile to add support for extracting TX packet
> fields into MCAM search key. Enabled Tx KPU packet parsing by
> configuring TX PKIND in tx_parse_cfg.
>
> Also modified the default KEX profile to extract VLAN TCI from
> the LB_PTR and exact byte offset of VLAN header. The NPC KPU
> parser was modified to point LB_PTR to the starting byte offset
> of VLAN header which points to the tpid field.
>
> Signed-off-by: Stanislaw Kardach <[email protected]>
> Signed-off-by: Sunil Goutham <[email protected]>
> Signed-off-by: Naveen Mamindlapalli <[email protected]>
>

Reviewed-by: Saeed Mahameed <[email protected]>


2020-11-12 20:04:39

by Alexander Duyck

[permalink] [raw]
Subject: Re: [PATCH v3 net-next 01/13] octeontx2-af: Modify default KEX profile to extract TX packet fields

On Tue, Nov 10, 2020 at 11:22 PM Naveen Mamindlapalli
<[email protected]> wrote:
>
> From: Stanislaw Kardach <[email protected]>
>
> The current default Key Extraction(KEX) profile can only use RX
> packet fields while generating the MCAM search key. The profile
> can't be used for matching TX packet fields. This patch modifies
> the default KEX profile to add support for extracting TX packet
> fields into MCAM search key. Enabled Tx KPU packet parsing by
> configuring TX PKIND in tx_parse_cfg.
>
> Also modified the default KEX profile to extract VLAN TCI from
> the LB_PTR and exact byte offset of VLAN header. The NPC KPU
> parser was modified to point LB_PTR to the starting byte offset
> of VLAN header which points to the tpid field.
>
> Signed-off-by: Stanislaw Kardach <[email protected]>
> Signed-off-by: Sunil Goutham <[email protected]>
> Signed-off-by: Naveen Mamindlapalli <[email protected]>

A bit more documentation would be useful. However other than that the
code itself appears to make sense.

Reviewed-by: Alexander Duyck <[email protected]>

> ---
> .../ethernet/marvell/octeontx2/af/npc_profile.h | 71 ++++++++++++++++++++--
> .../net/ethernet/marvell/octeontx2/af/rvu_nix.c | 6 ++
> 2 files changed, 72 insertions(+), 5 deletions(-)
>
> diff --git a/drivers/net/ethernet/marvell/octeontx2/af/npc_profile.h b/drivers/net/ethernet/marvell/octeontx2/af/npc_profile.h
> index 199448610e3e..c5b13385c81d 100644
> --- a/drivers/net/ethernet/marvell/octeontx2/af/npc_profile.h
> +++ b/drivers/net/ethernet/marvell/octeontx2/af/npc_profile.h
> @@ -13386,8 +13386,8 @@ static struct npc_mcam_kex npc_mkex_default = {
> .kpu_version = NPC_KPU_PROFILE_VER,
> .keyx_cfg = {
> /* nibble: LA..LE (ltype only) + Channel */
> - [NIX_INTF_RX] = ((u64)NPC_MCAM_KEY_X2 << 32) | 0x49247,
> - [NIX_INTF_TX] = ((u64)NPC_MCAM_KEY_X2 << 32) | ((1ULL << 19) - 1),
> + [NIX_INTF_RX] = ((u64)NPC_MCAM_KEY_X2 << 32) | 0x249207,
> + [NIX_INTF_TX] = ((u64)NPC_MCAM_KEY_X2 << 32) | 0x249200,
> },
> .intf_lid_lt_ld = {
> /* Default RX MCAM KEX profile */
//
Any sort of explanation for what some of these magic numbers means
might be useful. I'm left wondering if the lower 32b is a bitfield or
a fixed value. I am guessing bit field based on the fact that it was
originally being set using ((1ULL << X) - 1) however if there were
macros defined for each bit explaining what each bit was that would be
useful.

> @@ -13405,12 +13405,14 @@ static struct npc_mcam_kex npc_mkex_default = {
> /* Layer B: Single VLAN (CTAG) */
> /* CTAG VLAN[2..3] + Ethertype, 4 bytes, KW0[63:32] */
> [NPC_LT_LB_CTAG] = {
> - KEX_LD_CFG(0x03, 0x0, 0x1, 0x0, 0x4),
> + KEX_LD_CFG(0x03, 0x2, 0x1, 0x0, 0x4),
> },

Similarly here some explanation for KEX_LD_CFG would be useful. From
what I can tell it seems like this may be some sort of fix as you are
adjusting the "hdr_ofs" field from 0 to 2.

> /* Layer B: Stacked VLAN (STAG|QinQ) */
> [NPC_LT_LB_STAG_QINQ] = {
> - /* CTAG VLAN[2..3] + Ethertype, 4 bytes, KW0[63:32] */
> - KEX_LD_CFG(0x03, 0x4, 0x1, 0x0, 0x4),
> + /* Outer VLAN: 2 bytes, KW0[63:48] */
> + KEX_LD_CFG(0x01, 0x2, 0x1, 0x0, 0x6),
> + /* Ethertype: 2 bytes, KW0[47:32] */
> + KEX_LD_CFG(0x01, 0x8, 0x1, 0x0, 0x4),

Just to confirm, are you matching up the outer VLAN with the inner
Ethertype here? It seems like an odd combination. I assume you need
the inner ethertype in order to identify the L3 traffic?

> },
> [NPC_LT_LB_FDSA] = {
> /* SWITCH PORT: 1 byte, KW0[63:48] */
> @@ -13450,6 +13452,65 @@ static struct npc_mcam_kex npc_mkex_default = {
> },
> },
> },
> +
> + /* Default TX MCAM KEX profile */
> + [NIX_INTF_TX] = {
> + [NPC_LID_LA] = {
> + /* Layer A: Ethernet: */
> + [NPC_LT_LA_IH_NIX_ETHER] = {
> + /* PF_FUNC: 2B , KW0 [47:32] */
> + KEX_LD_CFG(0x01, 0x0, 0x1, 0x0, 0x4),

I'm assuming you have an 8B internal header that is being parsed? A
comment explaining that this is parsing a preamble that is at the
start of things might be useful.

> + /* DMAC: 6 bytes, KW1[63:16] */
> + KEX_LD_CFG(0x05, 0x8, 0x1, 0x0, 0xa),
> + },
> + },
> + [NPC_LID_LB] = {
> + /* Layer B: Single VLAN (CTAG) */
> + [NPC_LT_LB_CTAG] = {
> + /* CTAG VLAN[2..3] KW0[63:48] */
> + KEX_LD_CFG(0x01, 0x2, 0x1, 0x0, 0x6),
> + /* CTAG VLAN[2..3] KW1[15:0] */
> + KEX_LD_CFG(0x01, 0x4, 0x1, 0x0, 0x8),
> + },
> + /* Layer B: Stacked VLAN (STAG|QinQ) */
> + [NPC_LT_LB_STAG_QINQ] = {
> + /* Outer VLAN: 2 bytes, KW0[63:48] */
> + KEX_LD_CFG(0x01, 0x2, 0x1, 0x0, 0x6),
> + /* Outer VLAN: 2 Bytes, KW1[15:0] */
> + KEX_LD_CFG(0x01, 0x8, 0x1, 0x0, 0x8),
> + },
> + },
> + [NPC_LID_LC] = {
> + /* Layer C: IPv4 */
> + [NPC_LT_LC_IP] = {
> + /* SIP+DIP: 8 bytes, KW2[63:0] */
> + KEX_LD_CFG(0x07, 0xc, 0x1, 0x0, 0x10),
> + /* TOS: 1 byte, KW1[63:56] */
> + KEX_LD_CFG(0x0, 0x1, 0x1, 0x0, 0xf),
> + },
> + /* Layer C: IPv6 */
> + [NPC_LT_LC_IP6] = {
> + /* Everything up to SADDR: 8 bytes, KW2[63:0] */
> + KEX_LD_CFG(0x07, 0x0, 0x1, 0x0, 0x10),
> + },
> + },
> + [NPC_LID_LD] = {
> + /* Layer D:UDP */
> + [NPC_LT_LD_UDP] = {
> + /* SPORT: 2 bytes, KW3[15:0] */
> + KEX_LD_CFG(0x1, 0x0, 0x1, 0x0, 0x18),
> + /* DPORT: 2 bytes, KW3[31:16] */
> + KEX_LD_CFG(0x1, 0x2, 0x1, 0x0, 0x1a),

I am curious why this is being done as two pieces instead of just one.
From what I can tell you could just have a single rule that copies the
4 bytes for both ports in one shot and they would end up in the same
place wouldn't they?

> + },
> + /* Layer D:TCP */
> + [NPC_LT_LD_TCP] = {
> + /* SPORT: 2 bytes, KW3[15:0] */
> + KEX_LD_CFG(0x1, 0x0, 0x1, 0x0, 0x18),
> + /* DPORT: 2 bytes, KW3[31:16] */
> + KEX_LD_CFG(0x1, 0x2, 0x1, 0x0, 0x1a),
> + },
> + },
> + },
> },
> };
>
> diff --git a/drivers/net/ethernet/marvell/octeontx2/af/rvu_nix.c b/drivers/net/ethernet/marvell/octeontx2/af/rvu_nix.c
> index 8bac1dd3a1c2..8c11abdbd9d1 100644
> --- a/drivers/net/ethernet/marvell/octeontx2/af/rvu_nix.c
> +++ b/drivers/net/ethernet/marvell/octeontx2/af/rvu_nix.c
> @@ -57,6 +57,8 @@ enum nix_makr_fmt_indexes {
> NIX_MARK_CFG_MAX,
> };
>
> +#define NIX_TX_PKIND 63ULL
> +

A comment explaining the magic number would be useful. From what I can
tell this looks like a "just turn everything on" sort of config where
you are enabling bit flags 0 - 5.


> /* For now considering MC resources needed for broadcast
> * pkt replication only. i.e 256 HWVFs + 12 PFs.
> */
> @@ -1182,6 +1184,10 @@ int rvu_mbox_handler_nix_lf_alloc(struct rvu *rvu,
> /* Config Rx pkt length, csum checks and apad enable / disable */
> rvu_write64(rvu, blkaddr, NIX_AF_LFX_RX_CFG(nixlf), req->rx_cfg);
>
> + /* Configure pkind for TX parse config, 63 from npc_profile */
> + cfg = NIX_TX_PKIND;
> + rvu_write64(rvu, blkaddr, NIX_AF_LFX_TX_PARSE_CFG(nixlf), cfg);
> +
> intf = is_afvf(pcifunc) ? NIX_INTF_TYPE_LBK : NIX_INTF_TYPE_CGX;
> err = nix_interface_init(rvu, pcifunc, intf, nixlf);
> if (err)
> --
> 2.16.5
>

2020-11-12 20:19:03

by Saeed Mahameed

[permalink] [raw]
Subject: Re: [PATCH v3 net-next 00/13] Add ethtool ntuple filters support

On Wed, 2020-11-11 at 12:43 +0530, Naveen Mamindlapalli wrote:
> This patch series adds support for ethtool ntuple filters, unicast
> address filtering, VLAN offload and SR-IOV ndo handlers. All of the
> above features are based on the Admin Function(AF) driver support to
> install and delete the low level MCAM entries. Each MCAM entry is
> programmed with the packet fields to match and what actions to take
> if the match succeeds. The PF driver requests AF driver to allocate
> set of MCAM entries to be used to install the flows by that PF. The
> entries will be freed when the PF driver is unloaded.
>
> * The patches 1 to 4 adds AF driver infrastructure to install and
> delete the low level MCAM flow entries.
> * Patch 5 adds ethtool ntuple filter support.
> * Patch 6 adds unicast MAC address filtering.
> * Patch 7 adds support for dumping the MCAM entries via debugfs.
> * Patches 8 to 10 adds support for VLAN offload.
> * Patch 10 to 11 adds support for SR-IOV ndo handlers.
> * Patch 12 adds support to read the MCAM entries.
>
> Misc:
> * Removed redundant mailbox NIX_RXVLAN_ALLOC.
>
> Change-log:
> v3:
> - Fixed Saeed's review comments on v2.
> - Fixed modifying the netdev->flags from driver.
> - Fixed modifying the netdev features and hw_features after
> register_netdev.
> - Removed unwanted ndo_features_check callback.
> v2:
> - Fixed the sparse issues reported by Jakub.
>

Reviewed-by: Saeed Mahameed <[email protected]>

2020-11-14 18:37:01

by Naveen Mamindlapalli

[permalink] [raw]
Subject: Re: [PATCH v3 net-next 01/13] octeontx2-af: Modify default KEX profile to extract TX packet fields

Hi Alexander,

Thanks for the review.

> -----Original Message-----
> From: Alexander Duyck <[email protected]>
> Sent: Friday, November 13, 2020 1:32 AM
> To: Naveen Mamindlapalli <[email protected]>
> Cc: Netdev <[email protected]>; LKML <[email protected]>;
> Jakub Kicinski <[email protected]>; David Miller <[email protected]>;
> [email protected]; Sunil Kovvuri Goutham <[email protected]>; Linu
> Cherian <[email protected]>; Geethasowjanya Akula
> <[email protected]>; Jerin Jacob Kollanukkaran <[email protected]>;
> Subbaraya Sundeep Bhatta <[email protected]>; Hariprasad Kelam
> <[email protected]>
> Subject: Re: [PATCH v3 net-next 01/13] octeontx2-af: Modify default KEX
> profile to extract TX packet fields
>
> On Tue, Nov 10, 2020 at 11:22 PM Naveen Mamindlapalli
> <[email protected]> wrote:
> >
> > From: Stanislaw Kardach <[email protected]>
> >
> > The current default Key Extraction(KEX) profile can only use RX packet
> > fields while generating the MCAM search key. The profile can't be used
> > for matching TX packet fields. This patch modifies the default KEX
> > profile to add support for extracting TX packet fields into MCAM
> > search key. Enabled Tx KPU packet parsing by configuring TX PKIND in
> > tx_parse_cfg.
> >
> > Also modified the default KEX profile to extract VLAN TCI from the
> > LB_PTR and exact byte offset of VLAN header. The NPC KPU parser was
> > modified to point LB_PTR to the starting byte offset of VLAN header
> > which points to the tpid field.
> >
> > Signed-off-by: Stanislaw Kardach <[email protected]>
> > Signed-off-by: Sunil Goutham <[email protected]>
> > Signed-off-by: Naveen Mamindlapalli <[email protected]>
>
> A bit more documentation would be useful. However other than that the code
> itself appears to make sense.
>
> Reviewed-by: Alexander Duyck <[email protected]>
>
> > ---
> > .../ethernet/marvell/octeontx2/af/npc_profile.h | 71
> ++++++++++++++++++++--
> > .../net/ethernet/marvell/octeontx2/af/rvu_nix.c | 6 ++
> > 2 files changed, 72 insertions(+), 5 deletions(-)
> >
> > diff --git a/drivers/net/ethernet/marvell/octeontx2/af/npc_profile.h
> > b/drivers/net/ethernet/marvell/octeontx2/af/npc_profile.h
> > index 199448610e3e..c5b13385c81d 100644
> > --- a/drivers/net/ethernet/marvell/octeontx2/af/npc_profile.h
> > +++ b/drivers/net/ethernet/marvell/octeontx2/af/npc_profile.h
> > @@ -13386,8 +13386,8 @@ static struct npc_mcam_kex npc_mkex_default =
> {
> > .kpu_version = NPC_KPU_PROFILE_VER,
> > .keyx_cfg = {
> > /* nibble: LA..LE (ltype only) + Channel */
> > - [NIX_INTF_RX] = ((u64)NPC_MCAM_KEY_X2 << 32) | 0x49247,
> > - [NIX_INTF_TX] = ((u64)NPC_MCAM_KEY_X2 << 32) | ((1ULL << 19) -
> 1),
> > + [NIX_INTF_RX] = ((u64)NPC_MCAM_KEY_X2 << 32) | 0x249207,
> > + [NIX_INTF_TX] = ((u64)NPC_MCAM_KEY_X2 << 32) |
> > + 0x249200,
> > },
> > .intf_lid_lt_ld = {
> > /* Default RX MCAM KEX profile */
> //
> Any sort of explanation for what some of these magic numbers means might be
> useful. I'm left wondering if the lower 32b is a bitfield or a fixed value. I am
> guessing bit field based on the fact that it was originally being set using ((1ULL
> << X) - 1) however if there were macros defined for each bit explaining what
> each bit was that would be useful.

I will add the macros for each bit in v4.

>
> > @@ -13405,12 +13405,14 @@ static struct npc_mcam_kex npc_mkex_default
> = {
> > /* Layer B: Single VLAN (CTAG) */
> > /* CTAG VLAN[2..3] + Ethertype, 4 bytes, KW0[63:32] */
> > [NPC_LT_LB_CTAG] = {
> > - KEX_LD_CFG(0x03, 0x0, 0x1, 0x0, 0x4),
> > + KEX_LD_CFG(0x03, 0x2, 0x1, 0x0, 0x4),
> > },
>
> Similarly here some explanation for KEX_LD_CFG would be useful. From what I
> can tell it seems like this may be some sort of fix as you are adjusting the
> "hdr_ofs" field from 0 to 2.

The fix description is added in the commit msg. I will try to clarify a bit more in v4 commit description about the fix.

>
> > /* Layer B: Stacked VLAN (STAG|QinQ) */
> > [NPC_LT_LB_STAG_QINQ] = {
> > - /* CTAG VLAN[2..3] + Ethertype, 4 bytes, KW0[63:32] */
> > - KEX_LD_CFG(0x03, 0x4, 0x1, 0x0, 0x4),
> > + /* Outer VLAN: 2 bytes, KW0[63:48] */
> > + KEX_LD_CFG(0x01, 0x2, 0x1, 0x0, 0x6),
> > + /* Ethertype: 2 bytes, KW0[47:32] */
> > + KEX_LD_CFG(0x01, 0x8, 0x1, 0x0, 0x4),
>
> Just to confirm, are you matching up the outer VLAN with the inner Ethertype
> here? It seems like an odd combination. I assume you need the inner ethertype
> in order to identify the L3 traffic?

In case of Q-in-Q, we are going to extract outer VLAN TCI 2 bytes and Ethertype (Ex: 0x0800 in case of IPv4) after CTAG Header. We don't support inner VLAN TCI match, so we don't extract.

>
> > },
> > [NPC_LT_LB_FDSA] = {
> > /* SWITCH PORT: 1 byte, KW0[63:48] */
> > @@ -13450,6 +13452,65 @@ static struct npc_mcam_kex npc_mkex_default
> = {
> > },
> > },
> > },
> > +
> > + /* Default TX MCAM KEX profile */
> > + [NIX_INTF_TX] = {
> > + [NPC_LID_LA] = {
> > + /* Layer A: Ethernet: */
> > + [NPC_LT_LA_IH_NIX_ETHER] = {
> > + /* PF_FUNC: 2B , KW0 [47:32] */
> > + KEX_LD_CFG(0x01, 0x0, 0x1, 0x0, 0x4),
>
> I'm assuming you have an 8B internal header that is being parsed? A comment
> explaining that this is parsing a preamble that is at the start of things might be
> useful.

Will add in v4.

>
> > + /* DMAC: 6 bytes, KW1[63:16] */
> > + KEX_LD_CFG(0x05, 0x8, 0x1, 0x0, 0xa),
> > + },
> > + },
> > + [NPC_LID_LB] = {
> > + /* Layer B: Single VLAN (CTAG) */
> > + [NPC_LT_LB_CTAG] = {
> > + /* CTAG VLAN[2..3] KW0[63:48] */
> > + KEX_LD_CFG(0x01, 0x2, 0x1, 0x0, 0x6),
> > + /* CTAG VLAN[2..3] KW1[15:0] */
> > + KEX_LD_CFG(0x01, 0x4, 0x1, 0x0, 0x8),
> > + },
> > + /* Layer B: Stacked VLAN (STAG|QinQ) */
> > + [NPC_LT_LB_STAG_QINQ] = {
> > + /* Outer VLAN: 2 bytes, KW0[63:48] */
> > + KEX_LD_CFG(0x01, 0x2, 0x1, 0x0, 0x6),
> > + /* Outer VLAN: 2 Bytes, KW1[15:0] */
> > + KEX_LD_CFG(0x01, 0x8, 0x1, 0x0, 0x8),
> > + },
> > + },
> > + [NPC_LID_LC] = {
> > + /* Layer C: IPv4 */
> > + [NPC_LT_LC_IP] = {
> > + /* SIP+DIP: 8 bytes, KW2[63:0] */
> > + KEX_LD_CFG(0x07, 0xc, 0x1, 0x0, 0x10),
> > + /* TOS: 1 byte, KW1[63:56] */
> > + KEX_LD_CFG(0x0, 0x1, 0x1, 0x0, 0xf),
> > + },
> > + /* Layer C: IPv6 */
> > + [NPC_LT_LC_IP6] = {
> > + /* Everything up to SADDR: 8 bytes, KW2[63:0] */
> > + KEX_LD_CFG(0x07, 0x0, 0x1, 0x0, 0x10),
> > + },
> > + },
> > + [NPC_LID_LD] = {
> > + /* Layer D:UDP */
> > + [NPC_LT_LD_UDP] = {
> > + /* SPORT: 2 bytes, KW3[15:0] */
> > + KEX_LD_CFG(0x1, 0x0, 0x1, 0x0, 0x18),
> > + /* DPORT: 2 bytes, KW3[31:16] */
> > + KEX_LD_CFG(0x1, 0x2, 0x1, 0x0, 0x1a),
>
> I am curious why this is being done as two pieces instead of just one.
> From what I can tell you could just have a single rule that copies the
> 4 bytes for both ports in one shot and they would end up in the same place
> wouldn't they?

Yes correct, the will work. I will modify and push the changes in v4.

>
> > + },
> > + /* Layer D:TCP */
> > + [NPC_LT_LD_TCP] = {
> > + /* SPORT: 2 bytes, KW3[15:0] */
> > + KEX_LD_CFG(0x1, 0x0, 0x1, 0x0, 0x18),
> > + /* DPORT: 2 bytes, KW3[31:16] */
> > + KEX_LD_CFG(0x1, 0x2, 0x1, 0x0, 0x1a),
> > + },
> > + },
> > + },
> > },
> > };
> >
> > diff --git a/drivers/net/ethernet/marvell/octeontx2/af/rvu_nix.c
> > b/drivers/net/ethernet/marvell/octeontx2/af/rvu_nix.c
> > index 8bac1dd3a1c2..8c11abdbd9d1 100644
> > --- a/drivers/net/ethernet/marvell/octeontx2/af/rvu_nix.c
> > +++ b/drivers/net/ethernet/marvell/octeontx2/af/rvu_nix.c
> > @@ -57,6 +57,8 @@ enum nix_makr_fmt_indexes {
> > NIX_MARK_CFG_MAX,
> > };
> >
> > +#define NIX_TX_PKIND 63ULL
> > +
>
> A comment explaining the magic number would be useful. From what I can tell
> this looks like a "just turn everything on" sort of config where you are enabling
> bit flags 0 - 5.

Sure, will add in v4.

>
>
> > /* For now considering MC resources needed for broadcast
> > * pkt replication only. i.e 256 HWVFs + 12 PFs.
> > */
> > @@ -1182,6 +1184,10 @@ int rvu_mbox_handler_nix_lf_alloc(struct rvu *rvu,
> > /* Config Rx pkt length, csum checks and apad enable / disable */
> > rvu_write64(rvu, blkaddr, NIX_AF_LFX_RX_CFG(nixlf),
> > req->rx_cfg);
> >
> > + /* Configure pkind for TX parse config, 63 from npc_profile */
> > + cfg = NIX_TX_PKIND;
> > + rvu_write64(rvu, blkaddr, NIX_AF_LFX_TX_PARSE_CFG(nixlf),
> > + cfg);
> > +
> > intf = is_afvf(pcifunc) ? NIX_INTF_TYPE_LBK : NIX_INTF_TYPE_CGX;
> > err = nix_interface_init(rvu, pcifunc, intf, nixlf);
> > if (err)
> > --
> > 2.16.5
> >

2020-11-14 19:03:48

by Naveen Mamindlapalli

[permalink] [raw]
Subject: RE: [EXT] Re: [PATCH v3 net-next 01/13] octeontx2-af: Modify default KEX profile to extract TX packet fields

Hi Saeed,
Thanks for the review.

> -----Original Message-----
> From: Saeed Mahameed <[email protected]>
> Sent: Friday, November 13, 2020 1:27 AM
> To: Naveen Mamindlapalli <[email protected]>; [email protected];
> [email protected]
> Cc: [email protected]; [email protected]; Sunil Kovvuri Goutham
> <[email protected]>; Linu Cherian <[email protected]>;
> Geethasowjanya Akula <[email protected]>; Jerin Jacob Kollanukkaran
> <[email protected]>; Subbaraya Sundeep Bhatta <[email protected]>;
> Hariprasad Kelam <[email protected]>
> Subject: [EXT] Re: [PATCH v3 net-next 01/13] octeontx2-af: Modify default KEX
> profile to extract TX packet fields
>
> External Email
>
> ----------------------------------------------------------------------
> On Wed, 2020-11-11 at 12:43 +0530, Naveen Mamindlapalli wrote:
> > From: Stanislaw Kardach <[email protected]>
> >
> > The current default Key Extraction(KEX) profile can only use RX packet
> > fields while generating the MCAM search key. The profile can't be used
> > for matching TX packet fields. This patch modifies the default KEX
> > profile to add support for extracting TX packet fields into MCAM
> > search key. Enabled Tx KPU packet parsing by configuring TX PKIND in
> > tx_parse_cfg.
> >
> > Also modified the default KEX profile to extract VLAN TCI from the
> > LB_PTR and exact byte offset of VLAN header. The NPC KPU parser was
> > modified to point LB_PTR to the starting byte offset of VLAN header
> > which points to the tpid field.
> >
> > Signed-off-by: Stanislaw Kardach <[email protected]>
> > Signed-off-by: Sunil Goutham <[email protected]>
> > Signed-off-by: Naveen Mamindlapalli <[email protected]>
> >
>
> Reviewed-by: Saeed Mahameed <[email protected]>
>

2020-11-14 19:05:03

by Naveen Mamindlapalli

[permalink] [raw]
Subject: RE: [EXT] Re: [PATCH v3 net-next 00/13] Add ethtool ntuple filters support

Hi Saeed,
Thanks for the review.

> -----Original Message-----
> From: Saeed Mahameed <[email protected]>
> Sent: Friday, November 13, 2020 1:47 AM
> To: Naveen Mamindlapalli <[email protected]>; [email protected];
> [email protected]
> Cc: [email protected]; [email protected]; Sunil Kovvuri Goutham
> <[email protected]>; Linu Cherian <[email protected]>;
> Geethasowjanya Akula <[email protected]>; Jerin Jacob Kollanukkaran
> <[email protected]>; Subbaraya Sundeep Bhatta <[email protected]>;
> Hariprasad Kelam <[email protected]>
> Subject: [EXT] Re: [PATCH v3 net-next 00/13] Add ethtool ntuple filters support
>
> External Email
>
> ----------------------------------------------------------------------
> On Wed, 2020-11-11 at 12:43 +0530, Naveen Mamindlapalli wrote:
> > This patch series adds support for ethtool ntuple filters, unicast
> > address filtering, VLAN offload and SR-IOV ndo handlers. All of the
> > above features are based on the Admin Function(AF) driver support to
> > install and delete the low level MCAM entries. Each MCAM entry is
> > programmed with the packet fields to match and what actions to take if
> > the match succeeds. The PF driver requests AF driver to allocate set
> > of MCAM entries to be used to install the flows by that PF. The
> > entries will be freed when the PF driver is unloaded.
> >
> > * The patches 1 to 4 adds AF driver infrastructure to install and
> > delete the low level MCAM flow entries.
> > * Patch 5 adds ethtool ntuple filter support.
> > * Patch 6 adds unicast MAC address filtering.
> > * Patch 7 adds support for dumping the MCAM entries via debugfs.
> > * Patches 8 to 10 adds support for VLAN offload.
> > * Patch 10 to 11 adds support for SR-IOV ndo handlers.
> > * Patch 12 adds support to read the MCAM entries.
> >
> > Misc:
> > * Removed redundant mailbox NIX_RXVLAN_ALLOC.
> >
> > Change-log:
> > v3:
> > - Fixed Saeed's review comments on v2.
> > - Fixed modifying the netdev->flags from driver.
> > - Fixed modifying the netdev features and hw_features after
> > register_netdev.
> > - Removed unwanted ndo_features_check callback.
> > v2:
> > - Fixed the sparse issues reported by Jakub.
> >
>
> Reviewed-by: Saeed Mahameed <[email protected]>

2020-11-14 19:08:04

by Naveen Mamindlapalli

[permalink] [raw]
Subject: Re: [PATCH v3 net-next 00/13] Add ethtool ntuple filters support

Hi Saeed,

Thanks for the review.

> -----Original Message-----
> From: Saeed Mahameed <[email protected]>
> Sent: Friday, November 13, 2020 1:47 AM
> To: Naveen Mamindlapalli <[email protected]>; [email protected];
> [email protected]
> Cc: [email protected]; [email protected]; Sunil Kovvuri Goutham
> <[email protected]>; Linu Cherian <[email protected]>;
> Geethasowjanya Akula <[email protected]>; Jerin Jacob Kollanukkaran
> <[email protected]>; Subbaraya Sundeep Bhatta <[email protected]>;
> Hariprasad Kelam <[email protected]>
> Subject: Re: [PATCH v3 net-next 00/13] Add ethtool ntuple filters support
>
> On Wed, 2020-11-11 at 12:43 +0530, Naveen Mamindlapalli wrote:
> > This patch series adds support for ethtool ntuple filters, unicast
> > address filtering, VLAN offload and SR-IOV ndo handlers. All of the
> > above features are based on the Admin Function(AF) driver support to
> > install and delete the low level MCAM entries. Each MCAM entry is
> > programmed with the packet fields to match and what actions to take if
> > the match succeeds. The PF driver requests AF driver to allocate set
> > of MCAM entries to be used to install the flows by that PF. The
> > entries will be freed when the PF driver is unloaded.
> >
> > * The patches 1 to 4 adds AF driver infrastructure to install and
> > delete the low level MCAM flow entries.
> > * Patch 5 adds ethtool ntuple filter support.
> > * Patch 6 adds unicast MAC address filtering.
> > * Patch 7 adds support for dumping the MCAM entries via debugfs.
> > * Patches 8 to 10 adds support for VLAN offload.
> > * Patch 10 to 11 adds support for SR-IOV ndo handlers.
> > * Patch 12 adds support to read the MCAM entries.
> >
> > Misc:
> > * Removed redundant mailbox NIX_RXVLAN_ALLOC.
> >
> > Change-log:
> > v3:
> > - Fixed Saeed's review comments on v2.
> > - Fixed modifying the netdev->flags from driver.
> > - Fixed modifying the netdev features and hw_features after
> > register_netdev.
> > - Removed unwanted ndo_features_check callback.
> > v2:
> > - Fixed the sparse issues reported by Jakub.
> >
>
> Reviewed-by: Saeed Mahameed <[email protected]>