Add the structures and functions to process flow table, which is used in
the rte_flow offload logics.
This module is used for the CoreNIC firmware.

Signed-off-by: Chaoyong He <chaoyong...@corigine.com>
Reviewed-by: Long Wu <long...@corigine.com>
Reviewed-by: Peng Zhang <peng.zh...@corigine.com>
---
 drivers/common/nfp/nfp_common_ctrl.h |   1 +
 drivers/net/nfp/meson.build          |   1 +
 drivers/net/nfp/nfp_ethdev.c         |  27 ++++-
 drivers/net/nfp/nfp_net_common.h     |  11 ++
 drivers/net/nfp/nfp_net_flow.c       | 166 +++++++++++++++++++++++++++
 drivers/net/nfp/nfp_net_flow.h       |  28 +++++
 6 files changed, 228 insertions(+), 6 deletions(-)
 create mode 100644 drivers/net/nfp/nfp_net_flow.c
 create mode 100644 drivers/net/nfp/nfp_net_flow.h

diff --git a/drivers/common/nfp/nfp_common_ctrl.h 
b/drivers/common/nfp/nfp_common_ctrl.h
index d09fd2b892..cbde987736 100644
--- a/drivers/common/nfp/nfp_common_ctrl.h
+++ b/drivers/common/nfp/nfp_common_ctrl.h
@@ -223,6 +223,7 @@ struct nfp_net_fw_ver {
 #define NFP_NET_CFG_CTRL_IPSEC_SM_LOOKUP  (0x1 << 3) /**< SA short match 
lookup */
 #define NFP_NET_CFG_CTRL_IPSEC_LM_LOOKUP  (0x1 << 4) /**< SA long match lookup 
*/
 #define NFP_NET_CFG_CTRL_MULTI_PF         (0x1 << 5)
+#define NFP_NET_CFG_CTRL_FLOW_STEER       (0x1 << 8) /**< Flow Steering */
 #define NFP_NET_CFG_CTRL_IN_ORDER         (0x1 << 11) /**< Virtio in-order 
flag */
 
 #define NFP_NET_CFG_CAP_WORD1           0x00a4
diff --git a/drivers/net/nfp/meson.build b/drivers/net/nfp/meson.build
index 8407073af8..0d0a0bd8f4 100644
--- a/drivers/net/nfp/meson.build
+++ b/drivers/net/nfp/meson.build
@@ -36,6 +36,7 @@ sources = files(
         'nfp_mtr.c',
         'nfp_net_common.c',
         'nfp_net_ctrl.c',
+        'nfp_net_flow.c',
         'nfp_rxtx.c',
 )
 
diff --git a/drivers/net/nfp/nfp_ethdev.c b/drivers/net/nfp/nfp_ethdev.c
index 537b4fe792..d0a1950ff3 100644
--- a/drivers/net/nfp/nfp_ethdev.c
+++ b/drivers/net/nfp/nfp_ethdev.c
@@ -23,6 +23,7 @@
 #include "nfp_cpp_bridge.h"
 #include "nfp_ipsec.h"
 #include "nfp_logs.h"
+#include "nfp_net_flow.h"
 
 #define NFP_PF_DRIVER_NAME net_nfp_pf
 
@@ -151,6 +152,10 @@ nfp_net_start(struct rte_eth_dev *dev)
                ctrl_extend |= NFP_NET_CFG_CTRL_IPSEC_SM_LOOKUP
                                | NFP_NET_CFG_CTRL_IPSEC_LM_LOOKUP;
 
+       /* Enable flow steer by extend ctrl word1. */
+       if ((cap_extend & NFP_NET_CFG_CTRL_FLOW_STEER) != 0)
+               ctrl_extend |= NFP_NET_CFG_CTRL_FLOW_STEER;
+
        update = NFP_NET_CFG_UPDATE_GEN;
        if (nfp_ext_reconfig(hw, ctrl_extend, update) != 0)
                return -EIO;
@@ -323,6 +328,10 @@ nfp_net_uninit(struct rte_eth_dev *eth_dev)
        struct nfp_net_hw *net_hw;
 
        net_hw = eth_dev->data->dev_private;
+
+       if ((net_hw->super.cap_ext & NFP_NET_CFG_CTRL_FLOW_STEER) != 0)
+               nfp_net_flow_priv_uninit(net_hw->pf_dev, net_hw->idx);
+
        rte_free(net_hw->eth_xstats_base);
        nfp_ipsec_uninit(eth_dev);
        if (net_hw->mac_stats_area != NULL)
@@ -762,6 +771,14 @@ nfp_net_init(struct rte_eth_dev *eth_dev)
        /* Recording current stats counters values */
        nfp_net_stats_reset(eth_dev);
 
+       if ((hw->cap_ext & NFP_NET_CFG_CTRL_FLOW_STEER) != 0) {
+               err = nfp_net_flow_priv_init(pf_dev, port);
+               if (err != 0) {
+                       PMD_INIT_LOG(ERR, "Init net flow priv failed");
+                       goto xstats_free;
+               }
+       }
+
        return 0;
 
 xstats_free:
@@ -1195,13 +1212,11 @@ nfp_init_app_fw_nic(struct nfp_pf_dev *pf_dev,
 port_cleanup:
        for (i = 0; i < app_fw_nic->total_phyports; i++) {
                id = nfp_function_id_get(pf_dev, i);
+               hw = app_fw_nic->ports[id];
 
-               if (app_fw_nic->ports[id] != NULL &&
-                               app_fw_nic->ports[id]->eth_dev != NULL) {
-                       struct rte_eth_dev *tmp_dev;
-                       tmp_dev = app_fw_nic->ports[id]->eth_dev;
-                       nfp_net_uninit(tmp_dev);
-                       rte_eth_dev_release_port(tmp_dev);
+               if (hw != NULL && hw->eth_dev != NULL) {
+                       nfp_net_uninit(hw->eth_dev);
+                       rte_eth_dev_release_port(hw->eth_dev);
                }
        }
        nfp_cpp_area_release_free(pf_dev->ctrl_area);
diff --git a/drivers/net/nfp/nfp_net_common.h b/drivers/net/nfp/nfp_net_common.h
index ded491cbdc..eb668a1505 100644
--- a/drivers/net/nfp/nfp_net_common.h
+++ b/drivers/net/nfp/nfp_net_common.h
@@ -108,6 +108,14 @@ struct nfp_pf_dev {
        struct nfp_multi_pf multi_pf;
 };
 
+#define NFP_NET_FLOW_LIMIT    1024
+
+struct nfp_net_priv {
+       uint32_t hash_seed; /**< Hash seed for hash tables in this structure. */
+       struct rte_hash *flow_table; /**< Hash table to store flow rules. */
+       uint16_t flow_count; /**< Flow count in hash table */
+};
+
 struct nfp_app_fw_nic {
        /** Backpointer to the PF device */
        struct nfp_pf_dev *pf_dev;
@@ -177,6 +185,9 @@ struct nfp_net_hw {
        struct nfp_net_tlv_caps tlv_caps;
 
        struct nfp_net_ipsec_data *ipsec_data;
+
+       /** Used for rte_flow of CoreNIC firmware */
+       struct nfp_net_priv *priv;
 };
 
 static inline uint32_t
diff --git a/drivers/net/nfp/nfp_net_flow.c b/drivers/net/nfp/nfp_net_flow.c
new file mode 100644
index 0000000000..25da9ed8ac
--- /dev/null
+++ b/drivers/net/nfp/nfp_net_flow.c
@@ -0,0 +1,166 @@
+/* SPDX-License-Identifier: BSD-3-Clause
+ * Copyright (c) 2023 Corigine, Inc.
+ * All rights reserved.
+ */
+
+#include "nfp_net_flow.h"
+
+#include <rte_flow_driver.h>
+#include <rte_hash.h>
+#include <rte_jhash.h>
+#include <rte_malloc.h>
+
+#include "nfp_logs.h"
+
+__rte_unused static int
+nfp_net_flow_table_add(struct nfp_net_priv *priv,
+               struct rte_flow *nfp_flow)
+{
+       int ret;
+
+       ret = rte_hash_add_key_data(priv->flow_table, &nfp_flow->hash_key, 
nfp_flow);
+       if (ret != 0) {
+               PMD_DRV_LOG(ERR, "Add to flow table failed.");
+               return ret;
+       }
+
+       return 0;
+}
+
+__rte_unused static int
+nfp_net_flow_table_delete(struct nfp_net_priv *priv,
+               struct rte_flow *nfp_flow)
+{
+       int ret;
+
+       ret = rte_hash_del_key(priv->flow_table, &nfp_flow->hash_key);
+       if (ret < 0) {
+               PMD_DRV_LOG(ERR, "Delete from flow table failed.");
+               return ret;
+       }
+
+       return 0;
+}
+
+__rte_unused static struct rte_flow *
+nfp_net_flow_table_search(struct nfp_net_priv *priv,
+               struct rte_flow *nfp_flow)
+{
+       int index;
+       struct rte_flow *flow_find;
+
+       index = rte_hash_lookup_data(priv->flow_table, &nfp_flow->hash_key,
+                       (void **)&flow_find);
+       if (index < 0) {
+               PMD_DRV_LOG(DEBUG, "Data NOT found in the flow table.");
+               return NULL;
+       }
+
+       return flow_find;
+}
+
+__rte_unused static struct rte_flow *
+nfp_net_flow_alloc(uint32_t match_len,
+               uint32_t action_len,
+               uint32_t port_id)
+{
+       char *data;
+       struct rte_flow *nfp_flow;
+       struct nfp_net_flow_payload *payload;
+
+       nfp_flow = rte_zmalloc("nfp_flow", sizeof(struct rte_flow), 0);
+       if (nfp_flow == NULL)
+               return NULL;
+
+       data = rte_zmalloc("nfp_flow_payload", match_len + action_len, 0);
+       if (data == NULL)
+               goto free_flow;
+
+       nfp_flow->port_id      = port_id;
+       payload                = &nfp_flow->payload;
+       payload->match_len     = match_len;
+       payload->action_len    = action_len;
+       payload->match_data    = data;
+       payload->action_data   = data + match_len;
+
+       return nfp_flow;
+
+free_flow:
+       rte_free(nfp_flow);
+
+       return NULL;
+}
+
+__rte_unused static void
+nfp_net_flow_free(struct rte_flow *nfp_flow)
+{
+       rte_free(nfp_flow->payload.match_data);
+       rte_free(nfp_flow);
+}
+
+int
+nfp_net_flow_priv_init(struct nfp_pf_dev *pf_dev,
+               uint16_t port)
+{
+       int ret = 0;
+       struct nfp_net_priv *priv;
+       char flow_name[RTE_HASH_NAMESIZE];
+       struct nfp_app_fw_nic *app_fw_nic;
+       const char *pci_name = strchr(pf_dev->pci_dev->name, ':') + 1;
+
+       snprintf(flow_name, sizeof(flow_name), "%s_fl_%u", pci_name, port);
+
+       struct rte_hash_parameters flow_hash_params = {
+               .name       = flow_name,
+               .entries    = NFP_NET_FLOW_LIMIT,
+               .hash_func  = rte_jhash,
+               .socket_id  = rte_socket_id(),
+               .key_len    = sizeof(uint32_t),
+               .extra_flag = RTE_HASH_EXTRA_FLAGS_RW_CONCURRENCY,
+       };
+
+       priv = rte_zmalloc("nfp_app_nic_priv", sizeof(struct nfp_net_priv), 0);
+       if (priv == NULL) {
+               PMD_INIT_LOG(ERR, "NFP app nic priv creation failed");
+               ret = -ENOMEM;
+               goto exit;
+       }
+
+       app_fw_nic = NFP_PRIV_TO_APP_FW_NIC(pf_dev->app_fw_priv);
+       app_fw_nic->ports[port]->priv = priv;
+       priv->hash_seed = (uint32_t)rte_rand();
+
+       /* Flow table */
+       flow_hash_params.hash_func_init_val = priv->hash_seed;
+       priv->flow_table = rte_hash_create(&flow_hash_params);
+       if (priv->flow_table == NULL) {
+               PMD_INIT_LOG(ERR, "flow hash table creation failed");
+               ret = -ENOMEM;
+               goto free_priv;
+       }
+
+       return 0;
+
+free_priv:
+       rte_free(priv);
+exit:
+       return ret;
+}
+
+void
+nfp_net_flow_priv_uninit(struct nfp_pf_dev *pf_dev,
+               uint16_t port)
+{
+       struct nfp_net_priv *priv;
+       struct nfp_app_fw_nic *app_fw_nic;
+
+       if (pf_dev == NULL)
+               return;
+
+       app_fw_nic = NFP_PRIV_TO_APP_FW_NIC(pf_dev->app_fw_priv);
+       priv = app_fw_nic->ports[port]->priv;
+       if (priv != NULL)
+               rte_hash_free(priv->flow_table);
+
+       rte_free(priv);
+}
diff --git a/drivers/net/nfp/nfp_net_flow.h b/drivers/net/nfp/nfp_net_flow.h
new file mode 100644
index 0000000000..5ec80ba3b6
--- /dev/null
+++ b/drivers/net/nfp/nfp_net_flow.h
@@ -0,0 +1,28 @@
+/* SPDX-License-Identifier: BSD-3-Clause
+ * Copyright (c) 2023 Corigine, Inc.
+ * All rights reserved.
+ */
+
+#ifndef __NFP_NET_FLOW_H__
+#define __NFP_NET_FLOW_H__
+
+#include "nfp_net_common.h"
+
+struct nfp_net_flow_payload {
+       uint16_t cmsg_type;
+       uint8_t match_len;
+       uint8_t action_len;
+       char *match_data;
+       char *action_data;
+};
+
+struct rte_flow {
+       struct nfp_net_flow_payload payload;
+       uint32_t hash_key;
+       uint32_t port_id;
+};
+
+int nfp_net_flow_priv_init(struct nfp_pf_dev *pf_dev, uint16_t port);
+void nfp_net_flow_priv_uninit(struct nfp_pf_dev *pf_dev, uint16_t port);
+
+#endif /* __NFP_NET_FLOW_H__ */
-- 
2.39.1

Reply via email to