[PATCH net-next 07/14] net: enetc: add support for "Add" and "Delete" operations to IPFT

Wei Fang
2026-03-16T09:41:38Z

The ingress port filter table (IPFT )contains a set of filters each
capable of classifying incoming traffic using a mix of L2, L3, and L4
parsed and arbitrary field data. As a result of a filter match, several
actions can be specified such as on whether to deny or allow a frame,
overriding internal QoS attributes associated with the frame and setting
parameters for the subsequent frame processing functions, such as stream
identification, policing, ingress mirroring. Each entry corresponds to a
filter. The ingress port filter entries are added using a precedence
value. If a frame matches multiple entries, the entry with the higher
precedence is used. Currently, this patch only adds "Add" and "Delete"
operations to the ingress port filter table. These two interfaces will
be used by both ENETC driver and NETC switch driver.

Signed-off-by: Wei Fang <wei.fang@nxp.com>
---
drivers/net/ethernet/freescale/enetc/ntmp.c | 76 +++++++++++++
.../ethernet/freescale/enetc/ntmp_private.h | 36 ++++++
include/linux/fsl/ntmp.h | 104 ++++++++++++++++++
3 files changed, 216 insertions(+)

diff --git a/drivers/net/ethernet/freescale/enetc/ntmp.c b/drivers/net/ethernet/freescale/enetc/ntmp.c
index ef38ebe94da8..9fc3422137fc 100644
--- a/drivers/net/ethernet/freescale/enetc/ntmp.c
+++ b/drivers/net/ethernet/freescale/enetc/ntmp.c
@@ -20,6 +20,7 @@
/* Define NTMP Table ID */
#define NTMP_MAFT_ID 1
#define NTMP_RSST_ID 3
+#define NTMP_IPFT_ID 13
#define NTMP_FDBT_ID 15
#define NTMP_VFT_ID 18
#define NTMP_BPT_ID 41
@@ -234,6 +235,8 @@ static const char *ntmp_table_name(int tbl_id)
return "MAC Address Filter Table";
case NTMP_RSST_ID:
return "RSS Table";
+ case NTMP_IPFT_ID:
+ return "Ingress Port Filter Table";
case NTMP_FDBT_ID:
return "FDB Table";
case NTMP_VFT_ID:
@@ -468,6 +471,79 @@ int ntmp_rsst_query_entry(struct ntmp_user *user, u32 *table, int count)
}
EXPORT_SYMBOL_GPL(ntmp_rsst_query_entry);

+/**
+ * ntmp_ipft_add_entry - add an entry into the ingress port filter table
+ * @user: target ntmp_user struct
+ * @entry: the entry data, entry->cfge (configuration element data) and
+ * entry->keye (key element data) are used as input. Since the entry ID
+ * is assigned by the hardware, so entry->entry_id is a returned value
+ * for the driver to use, the driver can update/delete/query the entry
+ * based on the entry_id.
+ *
+ * Return: 0 on success, otherwise a negative error code
+ */
+int ntmp_ipft_add_entry(struct ntmp_user *user,
+ struct ipft_entry_data *entry)
+{
+ struct ntmp_dma_buf data = {
+ .dev = user->dev,
+ .size = sizeof(struct ipft_resp_query),
+ };
+ struct ipft_resp_query *resp;
+ struct ipft_req_ua *req;
+ union netc_cbd cbd;
+ u32 len;
+ int err;
+
+ err = ntmp_alloc_data_mem(&data, (void **)&req);
+ if (err)
+ return err;
+
+ ntmp_fill_crd(&req->crd, user->tbl.ipft_ver, NTMP_QA_ENTRY_ID,
+ NTMP_GEN_UA_CFGEU | NTMP_GEN_UA_STSEU);
+ req->ak.keye = entry->keye;
+ req->cfge = entry->cfge;
+
+ len = NTMP_LEN(sizeof(*req), data.size);
+ ntmp_fill_request_hdr(&cbd, data.dma, len, NTMP_IPFT_ID,
+ NTMP_CMD_AQ, NTMP_AM_TERNARY_KEY);
+
+ err = netc_xmit_ntmp_cmd(user, &cbd);
+ if (err) {
+ dev_err(user->dev, "Failed to add %s entry, err: %pe\n",
+ ntmp_table_name(NTMP_IPFT_ID), ERR_PTR(err));
+
+ goto end;
+ }
+
+ resp = (struct ipft_resp_query *)req;
+ entry->entry_id = le32_to_cpu(resp->entry_id);
+
+end:
+ ntmp_free_data_mem(&data);
+
+ return err;
+}
+EXPORT_SYMBOL_GPL(ntmp_ipft_add_entry);
+
+/**
+ * ntmp_ipft_delete_entry - delete a specified ingress port filter table entry
+ * @user: target ntmp_user struct
+ * @entry_id: the specified ID of the ingress port filter table entry
+ *
+ * Return: 0 on success, otherwise a negative error code
+ */
+int ntmp_ipft_delete_entry(struct ntmp_user *user, u32 entry_id)
+{
+ u32 req_len = sizeof(struct ipft_req_qd);
+
+ return ntmp_delete_entry_by_id(user, NTMP_IPFT_ID,
+ user->tbl.ipft_ver,
+ entry_id, req_len,
+ NTMP_STATUS_RESP_LEN);
+}
+EXPORT_SYMBOL_GPL(ntmp_ipft_delete_entry);
+
/**
* ntmp_fdbt_add_entry - add an entry into the FDB table
* @user: target ntmp_user struct
diff --git a/drivers/net/ethernet/freescale/enetc/ntmp_private.h b/drivers/net/ethernet/freescale/enetc/ntmp_private.h
index c5f6dca7b660..9411ec9f1777 100644
--- a/drivers/net/ethernet/freescale/enetc/ntmp_private.h
+++ b/drivers/net/ethernet/freescale/enetc/ntmp_private.h
@@ -103,6 +103,42 @@ struct rsst_req_update {
u8 groups[];
};

+/* Ingress Port Filter Table Response Data Buffer Format of Query action */
+struct ipft_resp_query {
+ __le32 status;
+ __le32 entry_id;
+ struct ipft_keye_data keye;
+ __le64 match_count; /* STSE_DATA */
+ struct ipft_cfge_data cfge;
+} __packed;
+
+struct ipft_ak_eid {
+ __le32 entry_id;
+ __le32 resv[52];
+};
+
+union ipft_access_key {
+ struct ipft_ak_eid eid;
+ struct ipft_keye_data keye;
+};
+
+/* Ingress Port Filter Table Request Data Buffer Format of Update and
+ * Add actions
+ */
+struct ipft_req_ua {
+ struct ntmp_cmn_req_data crd;
+ union ipft_access_key ak;
+ struct ipft_cfge_data cfge;
+};
+
+/* Ingress Port Filter Table Request Data Buffer Format of Query and
+ * Delete actions
+ */
+struct ipft_req_qd {
+ struct ntmp_req_by_eid rbe;
+ __le32 resv[52];
+};
+
/* Access Key Format of FDB Table */
struct fdbt_ak_eid {
__le32 entry_id;
diff --git a/include/linux/fsl/ntmp.h b/include/linux/fsl/ntmp.h
index 925a455935b0..f6d3bb2e318d 100644
--- a/include/linux/fsl/ntmp.h
+++ b/include/linux/fsl/ntmp.h
@@ -7,6 +7,7 @@
#include <linux/if_ether.h>

#define NTMP_NULL_ENTRY_ID 0xffffffffU
+#define IPFT_MAX_PLD_LEN 24

struct maft_keye_data {
u8 mac_addr[ETH_ALEN];
@@ -34,6 +35,7 @@ struct netc_tbl_vers {
u8 fdbt_ver;
u8 vft_ver;
u8 bpt_ver;
+ u8 ipft_ver;
};

struct netc_cbdr {
@@ -66,6 +68,94 @@ struct maft_entry_data {
struct maft_cfge_data cfge;
};

+struct ipft_pld_byte {
+ u8 data;
+ u8 mask;
+};
+
+struct ipft_keye_data {
+ __le16 precedence;
+ __le16 resv0[3];
+ __le16 frm_attr_flags;
+#define IPFT_FAF_OVLAN BIT(2)
+#define IPFT_FAF_IVLAN BIT(3)
+#define IPFT_FAF_IP_HDR BIT(7)
+#define IPFT_FAF_IP_VER6 BIT(8)
+#define IPFT_FAF_L4_CODE GENMASK(11, 10)
+#define IPFT_FAF_TCP_HDR 1
+#define IPFT_FAF_UDP_HDR 2
+#define IPFT_FAF_SCTP_HDR 3
+#define IPFT_FAF_WOL_MAGIC BIT(12)
+ __le16 frm_attr_flags_mask;
+ __le16 dscp;
+#define IPFT_DSCP GENMASK(5, 0)
+#define IPFT_DSCP_MASK GENMASK(11, 0)
+#define IPFT_DSCP_MASK_ALL 0x3f
+ __le16 src_port; /* This field is reserved for ENETC */
+#define IPFT_SRC_PORT GENMASK(4, 0)
+#define IPFT_SRC_PORT_MASK GENMASK(9, 5)
+#define IPFT_SRC_PORT_MASK_ALL 0x1f
+ __be16 outer_vlan_tci;
+ __be16 outer_vlan_tci_mask;
+ u8 dmac[ETH_ALEN];
+ u8 dmac_mask[ETH_ALEN];
+ u8 smac[ETH_ALEN];
+ u8 smac_mask[ETH_ALEN];
+ __be16 inner_vlan_tci;
+ __be16 inner_vlan_tci_mask;
+ __be16 ethertype;
+ __be16 ethertype_mask;
+ u8 ip_protocol;
+ u8 ip_protocol_mask;
+ __le16 resv1[7];
+ __be32 ip_src[4];
+ __le32 resv2[2];
+ __be32 ip_src_mask[4];
+ __be16 l4_src_port;
+ __be16 l4_src_port_mask;
+ __le32 resv3;
+ __be32 ip_dst[4];
+ __le32 resv4[2];
+ __be32 ip_dst_mask[4];
+ __be16 l4_dst_port;
+ __be16 l4_dst_port_mask;
+ __le32 resv5;
+ struct ipft_pld_byte byte[IPFT_MAX_PLD_LEN];
+};
+
+struct ipft_cfge_data {
+ __le32 cfg;
+#define IPFT_IPV GENMASK(3, 0)
+#define IPFT_OIPV BIT(4)
+#define IPFT_DR GENMASK(6, 5)
+#define IPFT_ODR BIT(7)
+#define IPFT_FLTFA GENMASK(10, 8)
+#define IPFT_FLTFA_DISCARD 0
+#define IPFT_FLTFA_PERMIT 1
+/* Redirect is only for switch */
+#define IPFT_FLTFA_REDIRECT 2
+#define IPFT_IMIRE BIT(11)
+#define IPFT_WOLTE BIT(12)
+#define IPFT_FLTA GENMASK(14, 13)
+#define IPFT_FLTA_RP 1
+#define IPFT_FLTA_IS 2
+#define IPFT_FLTA_SI_BITMAP 3
+#define IPFT_RPR GENMASK(16, 15)
+#define IPFT_CTD BIT(17)
+#define IPFT_HR GENMASK(21, 18)
+#define IPFT_TIMECAPE BIT(22)
+#define IPFT_RRT BIT(23)
+#define IPFT_BL2F BIT(24)
+#define IPFT_EVMEID GENMASK(31, 28)
+ __le32 flta_tgt;
+};
+
+struct ipft_entry_data {
+ u32 entry_id; /* hardware assigns entry ID */
+ struct ipft_keye_data keye;
+ struct ipft_cfge_data cfge;
+};
+
struct fdbt_keye_data {
u8 mac_addr[ETH_ALEN]; /* big-endian */
__le16 resv0;
@@ -155,6 +245,9 @@ int ntmp_rsst_update_entry(struct ntmp_user *user, const u32 *table,
int count);
int ntmp_rsst_query_entry(struct ntmp_user *user,
u32 *table, int count);
+int ntmp_ipft_add_entry(struct ntmp_user *user,
+ struct ipft_entry_data *entry);
+int ntmp_ipft_delete_entry(struct ntmp_user *user, u32 entry_id);
int ntmp_fdbt_add_entry(struct ntmp_user *user, u32 *entry_id,
const struct fdbt_keye_data *keye,
const struct fdbt_cfge_data *cfge);
@@ -208,6 +301,17 @@ static inline int ntmp_rsst_query_entry(struct ntmp_user *user,
return 0;
}

+static inline int ntmp_ipft_add_entry(struct ntmp_user *user,
+ struct ipft_entry_data *entry)
+{
+ return 0;
+}
+
+static inline int ntmp_ipft_delete_entry(struct ntmp_user *user, u32 entry_id)
+{
+ return 0;
+}
+
static inline int ntmp_fdbt_add_entry(struct ntmp_user *user, u32 *entry_id,
const struct fdbt_keye_data *keye,
const struct fdbt_cfge_data *data)
--
2.34.1