From: Prashant Gupta <prashant.gupta_3@nxp.com>
To: stephen@networkplumber.org, dev@dpdk.org
Cc: Hemant Agrawal <hemant.agrawal@nxp.com>
Subject: [PATCH 37/45] net/dpaa2: rework flow engine
Date: Thu, 3 Sep 2026 19:23:45 +0530 [thread overview]
Message-ID: <20260903135353.3358303-38-prashant.gupta_3@nxp.com> (raw)
In-Reply-To: <20260903135353.3358303-1-prashant.gupta_3@nxp.com>
From: Hemant Agrawal <hemant.agrawal@nxp.com>
Rework the dpaa2 flow engine so that flow rules are programmed through
the updated QoS and flow steering (FS) table interface.
The distribution helpers in base/dpaa2_hw_dpni.c are removed and folded
into the ethdev and flow code, which removes a layer of indirection and
keeps the key extraction, RSS distribution and QoS/FS entry programming
together in one place.
Signed-off-by: Hemant Agrawal <hemant.agrawal@nxp.com>
---
drivers/net/dpaa2/base/dpaa2_hw_dpni.c | 546 --
drivers/net/dpaa2/dpaa2_ethdev.c | 457 +-
drivers/net/dpaa2/dpaa2_ethdev.h | 478 +-
drivers/net/dpaa2/dpaa2_flow.c | 6906 ++++++++++++++----------
drivers/net/dpaa2/meson.build | 3 +-
5 files changed, 4719 insertions(+), 3671 deletions(-)
delete mode 100644 drivers/net/dpaa2/base/dpaa2_hw_dpni.c
diff --git a/drivers/net/dpaa2/base/dpaa2_hw_dpni.c b/drivers/net/dpaa2/base/dpaa2_hw_dpni.c
deleted file mode 100644
index fee96b3529..0000000000
--- a/drivers/net/dpaa2/base/dpaa2_hw_dpni.c
+++ /dev/null
@@ -1,546 +0,0 @@
-/* SPDX-License-Identifier: BSD-3-Clause
- *
- * Copyright (c) 2016 Freescale Semiconductor, Inc. All rights reserved.
- * Copyright 2016-2021,2023-2025 NXP
- *
- */
-
-#include <time.h>
-#include <net/if.h>
-
-#include <eal_export.h>
-#include <rte_mbuf.h>
-#include <ethdev_driver.h>
-#include <rte_malloc.h>
-#include <rte_memcpy.h>
-#include <rte_string_fns.h>
-#include <rte_cycles.h>
-#include <rte_kvargs.h>
-#include <dev_driver.h>
-
-#include <dpaa2_pmd_logs.h>
-#include <dpaa2_hw_pvt.h>
-#include <dpaa2_hw_mempool.h>
-
-#include "../dpaa2_ethdev.h"
-
-int
-dpaa2_distset_to_dpkg_profile_cfg(
- uint64_t req_dist_set,
- struct dpkg_profile_cfg *kg_cfg);
-
-RTE_EXPORT_SYMBOL(rte_pmd_dpaa2_set_custom_hash)
-int
-rte_pmd_dpaa2_set_custom_hash(uint16_t port_id,
- uint16_t offset, uint8_t size)
-{
- struct rte_eth_dev *eth_dev = &rte_eth_devices[port_id];
- struct dpaa2_dev_priv *priv = eth_dev->data->dev_private;
- struct fsl_mc_io *dpni = priv->hw;
- struct dpni_rx_tc_dist_cfg tc_cfg;
- struct dpkg_profile_cfg kg_cfg;
- void *p_params;
- int ret, tc_index = 0;
-
- if (!rte_eth_dev_is_valid_port(port_id)) {
- DPAA2_PMD_WARN("Invalid port id %u", port_id);
- return -EINVAL;
- }
-
- if (strcmp(eth_dev->device->driver->name,
- RTE_STR(NET_DPAA2_PMD_DRIVER_NAME))) {
- DPAA2_PMD_WARN("Not a valid dpaa2 port");
- return -EINVAL;
- }
-
- p_params = rte_zmalloc(NULL,
- DIST_PARAM_IOVA_SIZE, RTE_CACHE_LINE_SIZE);
- if (!p_params) {
- DPAA2_PMD_ERR("Unable to allocate flow-dist parameters");
- return -ENOMEM;
- }
-
- memset(&kg_cfg, 0, sizeof(struct dpkg_profile_cfg));
- kg_cfg.extracts[0].type = DPKG_EXTRACT_FROM_DATA;
- kg_cfg.extracts[0].extract.from_data.offset = offset;
- kg_cfg.extracts[0].extract.from_data.size = size;
- kg_cfg.extracts[0].num_of_byte_masks = 0;
- kg_cfg.num_extracts = 1;
-
- ret = dpkg_prepare_key_cfg(&kg_cfg, p_params);
- if (ret) {
- DPAA2_PMD_ERR("Unable to prepare extract parameters");
- rte_free(p_params);
- return ret;
- }
-
- memset(&tc_cfg, 0, sizeof(struct dpni_rx_tc_dist_cfg));
- tc_cfg.key_cfg_iova = DPAA2_VADDR_TO_IOVA_AND_CHECK(p_params,
- DIST_PARAM_IOVA_SIZE);
- if (tc_cfg.key_cfg_iova == RTE_BAD_IOVA) {
- DPAA2_PMD_ERR("%s: No IOMMU map for key cfg(%p)",
- __func__, p_params);
- rte_free(p_params);
- return -ENOBUFS;
- }
-
- tc_cfg.dist_size = eth_dev->data->nb_rx_queues;
- tc_cfg.dist_mode = DPNI_DIST_MODE_HASH;
-
- ret = dpni_set_rx_tc_dist(dpni, CMD_PRI_LOW, priv->token, tc_index,
- &tc_cfg);
- rte_free(p_params);
- if (ret) {
- DPAA2_PMD_ERR("Set RX TC dist failed(err=%d)", ret);
- return ret;
- }
-
- return 0;
-}
-
-int
-dpaa2_setup_flow_dist(struct rte_eth_dev *eth_dev,
- uint64_t req_dist_set, int tc_index)
-{
- struct dpaa2_dev_priv *priv = eth_dev->data->dev_private;
- int tc_dist_queues;
-
- /* TC distribution size is set with dist_queues or
- * (nb_rx_queues - tc_index*dist_queues) in order of TC priority index.
- */
- tc_dist_queues = eth_dev->data->nb_rx_queues -
- tc_index * priv->dist_queues;
- if (tc_dist_queues <= 0) {
- DPAA2_PMD_INFO("No distribution on TC%d", tc_index);
- return 0;
- }
-
- if (tc_dist_queues > priv->dist_queues)
- tc_dist_queues = priv->dist_queues;
-
- return dpaa2_setup_flow_dist_size(eth_dev, req_dist_set,
- tc_index, tc_dist_queues);
-}
-
-int
-dpaa2_setup_flow_dist_size(struct rte_eth_dev *eth_dev,
- uint64_t req_dist_set, int tc_index, uint16_t dist_size)
-{
- struct dpaa2_dev_priv *priv = eth_dev->data->dev_private;
- struct fsl_mc_io *dpni = eth_dev->process_private;
- struct dpni_rx_dist_cfg tc_cfg;
- struct dpkg_profile_cfg kg_cfg;
- void *p_params;
- int ret;
-
- if (dist_size == 0)
- return 0;
-
- p_params = rte_malloc(NULL,
- DIST_PARAM_IOVA_SIZE, RTE_CACHE_LINE_SIZE);
- if (!p_params) {
- DPAA2_PMD_ERR("Unable to allocate flow-dist parameters");
- return -ENOMEM;
- }
-
- memset(p_params, 0, DIST_PARAM_IOVA_SIZE);
- memset(&tc_cfg, 0, sizeof(struct dpni_rx_dist_cfg));
-
- ret = dpaa2_distset_to_dpkg_profile_cfg(req_dist_set, &kg_cfg);
- if (ret) {
- DPAA2_PMD_ERR("Given RSS Hash (%" PRIx64 ") not supported",
- req_dist_set);
- rte_free(p_params);
- return ret;
- }
-
- tc_cfg.key_cfg_iova = DPAA2_VADDR_TO_IOVA_AND_CHECK(p_params,
- DIST_PARAM_IOVA_SIZE);
- if (tc_cfg.key_cfg_iova == RTE_BAD_IOVA) {
- DPAA2_PMD_ERR("%s: No IOMMU map for key cfg(%p)",
- __func__, p_params);
- rte_free(p_params);
- return -ENOBUFS;
- }
-
- tc_cfg.dist_size = dist_size;
- tc_cfg.enable = true;
- tc_cfg.tc = tc_index;
-
- ret = dpkg_prepare_key_cfg(&kg_cfg, p_params);
- if (ret) {
- DPAA2_PMD_ERR("Unable to prepare extract parameters");
- rte_free(p_params);
- return ret;
- }
-
- ret = dpni_set_rx_hash_dist(dpni, CMD_PRI_LOW, priv->token, &tc_cfg);
- rte_free(p_params);
- if (ret) {
- DPAA2_PMD_ERR("RX Hash dist for failed(err=%d)", ret);
- return ret;
- }
-
- if (tc_index < MAX_TCS)
- priv->dist_size_cur[tc_index] = dist_size;
-
- return 0;
-}
-
-int
-dpaa2_remove_flow_dist(struct rte_eth_dev *eth_dev,
- uint8_t tc_index)
-{
- struct dpaa2_dev_priv *priv = eth_dev->data->dev_private;
- struct fsl_mc_io *dpni = priv->hw;
- struct dpni_rx_dist_cfg tc_cfg;
- struct dpkg_profile_cfg kg_cfg;
- void *p_params;
- int ret;
-
- p_params = rte_malloc(NULL,
- DIST_PARAM_IOVA_SIZE, RTE_CACHE_LINE_SIZE);
- if (!p_params) {
- DPAA2_PMD_ERR("Unable to allocate flow-dist parameters");
- return -ENOMEM;
- }
-
- memset(&tc_cfg, 0, sizeof(struct dpni_rx_dist_cfg));
- tc_cfg.dist_size = 0;
- tc_cfg.key_cfg_iova = DPAA2_VADDR_TO_IOVA_AND_CHECK(p_params,
- DIST_PARAM_IOVA_SIZE);
- if (tc_cfg.key_cfg_iova == RTE_BAD_IOVA) {
- DPAA2_PMD_ERR("%s: No IOMMU map for key cfg(%p)",
- __func__, p_params);
- rte_free(p_params);
- return -ENOBUFS;
- }
-
- tc_cfg.enable = true;
- tc_cfg.tc = tc_index;
-
- memset(p_params, 0, DIST_PARAM_IOVA_SIZE);
- kg_cfg.num_extracts = 0;
- ret = dpkg_prepare_key_cfg(&kg_cfg, p_params);
- if (ret) {
- DPAA2_PMD_ERR("Unable to prepare extract parameters");
- rte_free(p_params);
- return ret;
- }
-
- ret = dpni_set_rx_hash_dist(dpni, CMD_PRI_LOW, priv->token,
- &tc_cfg);
- rte_free(p_params);
- if (ret)
- DPAA2_PMD_ERR("RX hash dist failed(err=%d)", ret);
- return ret;
-}
-
-int
-dpaa2_distset_to_dpkg_profile_cfg(
- uint64_t req_dist_set,
- struct dpkg_profile_cfg *kg_cfg)
-{
- uint32_t loop = 0, i = 0;
- uint64_t dist_field = 0;
- int l2_configured = 0, l3_configured = 0;
- int l4_configured = 0;
- int mpls_configured = 0;
- int vlan_configured = 0;
- int esp_configured = 0;
- int ah_configured = 0;
- int pppoe_configured = 0;
-
- memset(kg_cfg, 0, sizeof(struct dpkg_profile_cfg));
- while (req_dist_set) {
- if (req_dist_set % 2 != 0) {
- dist_field = 1ULL << loop;
- switch (dist_field) {
- case RTE_ETH_RSS_L2_PAYLOAD:
- case RTE_ETH_RSS_ETH:
- if (l2_configured)
- break;
- l2_configured = 1;
-
- kg_cfg->extracts[i].extract.from_hdr.prot =
- NET_PROT_ETH;
- kg_cfg->extracts[i].extract.from_hdr.field =
- NH_FLD_ETH_TYPE;
- kg_cfg->extracts[i].type =
- DPKG_EXTRACT_FROM_HDR;
- kg_cfg->extracts[i].extract.from_hdr.type =
- DPKG_FULL_FIELD;
- i++;
- break;
-
- case RTE_ETH_RSS_PPPOE:
- if (pppoe_configured)
- break;
- pppoe_configured = 1;
-
- kg_cfg->extracts[i].extract.from_hdr.prot =
- NET_PROT_PPPOE;
- kg_cfg->extracts[i].extract.from_hdr.field =
- NH_FLD_PPPOE_SID;
- kg_cfg->extracts[i].type =
- DPKG_EXTRACT_FROM_HDR;
- kg_cfg->extracts[i].extract.from_hdr.type =
- DPKG_FULL_FIELD;
- i++;
- break;
-
- case RTE_ETH_RSS_ESP:
- if (esp_configured)
- break;
- esp_configured = 1;
-
- kg_cfg->extracts[i].extract.from_hdr.prot =
- NET_PROT_IPSEC_ESP;
- kg_cfg->extracts[i].extract.from_hdr.field =
- NH_FLD_IPSEC_ESP_SPI;
- kg_cfg->extracts[i].type =
- DPKG_EXTRACT_FROM_HDR;
- kg_cfg->extracts[i].extract.from_hdr.type =
- DPKG_FULL_FIELD;
- i++;
- break;
-
- case RTE_ETH_RSS_AH:
- if (ah_configured)
- break;
- ah_configured = 1;
-
- kg_cfg->extracts[i].extract.from_hdr.prot =
- NET_PROT_IPSEC_AH;
- kg_cfg->extracts[i].extract.from_hdr.field =
- NH_FLD_IPSEC_AH_SPI;
- kg_cfg->extracts[i].type =
- DPKG_EXTRACT_FROM_HDR;
- kg_cfg->extracts[i].extract.from_hdr.type =
- DPKG_FULL_FIELD;
- i++;
- break;
-
- case RTE_ETH_RSS_C_VLAN:
- case RTE_ETH_RSS_S_VLAN:
- if (vlan_configured)
- break;
- vlan_configured = 1;
-
- kg_cfg->extracts[i].extract.from_hdr.prot =
- NET_PROT_VLAN;
- kg_cfg->extracts[i].extract.from_hdr.field =
- NH_FLD_VLAN_TCI;
- kg_cfg->extracts[i].type =
- DPKG_EXTRACT_FROM_HDR;
- kg_cfg->extracts[i].extract.from_hdr.type =
- DPKG_FULL_FIELD;
- i++;
- break;
-
- case RTE_ETH_RSS_MPLS:
-
- if (mpls_configured)
- break;
- mpls_configured = 1;
-
- kg_cfg->extracts[i].extract.from_hdr.prot =
- NET_PROT_MPLS;
- kg_cfg->extracts[i].extract.from_hdr.field =
- NH_FLD_MPLS_MPLSL_1;
- kg_cfg->extracts[i].type =
- DPKG_EXTRACT_FROM_HDR;
- kg_cfg->extracts[i].extract.from_hdr.type =
- DPKG_FULL_FIELD;
- i++;
-
- kg_cfg->extracts[i].extract.from_hdr.prot =
- NET_PROT_MPLS;
- kg_cfg->extracts[i].extract.from_hdr.field =
- NH_FLD_MPLS_MPLSL_2;
- kg_cfg->extracts[i].type =
- DPKG_EXTRACT_FROM_HDR;
- kg_cfg->extracts[i].extract.from_hdr.type =
- DPKG_FULL_FIELD;
- i++;
-
- kg_cfg->extracts[i].extract.from_hdr.prot =
- NET_PROT_MPLS;
- kg_cfg->extracts[i].extract.from_hdr.field =
- NH_FLD_MPLS_MPLSL_N;
- kg_cfg->extracts[i].type =
- DPKG_EXTRACT_FROM_HDR;
- kg_cfg->extracts[i].extract.from_hdr.type =
- DPKG_FULL_FIELD;
- i++;
- break;
-
- case RTE_ETH_RSS_IPV4:
- case RTE_ETH_RSS_FRAG_IPV4:
- case RTE_ETH_RSS_NONFRAG_IPV4_OTHER:
- case RTE_ETH_RSS_IPV6:
- case RTE_ETH_RSS_FRAG_IPV6:
- case RTE_ETH_RSS_NONFRAG_IPV6_OTHER:
- case RTE_ETH_RSS_IPV6_EX:
-
- if (l3_configured)
- break;
- l3_configured = 1;
-
- kg_cfg->extracts[i].extract.from_hdr.prot =
- NET_PROT_IP;
- kg_cfg->extracts[i].extract.from_hdr.field =
- NH_FLD_IP_SRC;
- kg_cfg->extracts[i].type =
- DPKG_EXTRACT_FROM_HDR;
- kg_cfg->extracts[i].extract.from_hdr.type =
- DPKG_FULL_FIELD;
- i++;
-
- kg_cfg->extracts[i].extract.from_hdr.prot =
- NET_PROT_IP;
- kg_cfg->extracts[i].extract.from_hdr.field =
- NH_FLD_IP_DST;
- kg_cfg->extracts[i].type =
- DPKG_EXTRACT_FROM_HDR;
- kg_cfg->extracts[i].extract.from_hdr.type =
- DPKG_FULL_FIELD;
- i++;
-
- kg_cfg->extracts[i].extract.from_hdr.prot =
- NET_PROT_IP;
- kg_cfg->extracts[i].extract.from_hdr.field =
- NH_FLD_IP_PROTO;
- kg_cfg->extracts[i].type =
- DPKG_EXTRACT_FROM_HDR;
- kg_cfg->extracts[i].extract.from_hdr.type =
- DPKG_FULL_FIELD;
- i++;
- break;
-
- case RTE_ETH_RSS_NONFRAG_IPV4_TCP:
- case RTE_ETH_RSS_NONFRAG_IPV6_TCP:
- case RTE_ETH_RSS_NONFRAG_IPV4_UDP:
- case RTE_ETH_RSS_NONFRAG_IPV6_UDP:
- case RTE_ETH_RSS_IPV6_TCP_EX:
- case RTE_ETH_RSS_IPV6_UDP_EX:
- case RTE_ETH_RSS_NONFRAG_IPV4_SCTP:
- case RTE_ETH_RSS_NONFRAG_IPV6_SCTP:
-
- if (l4_configured)
- break;
- l4_configured = 1;
-
- kg_cfg->extracts[i].extract.from_hdr.prot =
- NET_PROT_TCP;
- kg_cfg->extracts[i].extract.from_hdr.field =
- NH_FLD_TCP_PORT_SRC;
- kg_cfg->extracts[i].type =
- DPKG_EXTRACT_FROM_HDR;
- kg_cfg->extracts[i].extract.from_hdr.type =
- DPKG_FULL_FIELD;
- i++;
-
- kg_cfg->extracts[i].extract.from_hdr.prot =
- NET_PROT_TCP;
- kg_cfg->extracts[i].extract.from_hdr.field =
- NH_FLD_TCP_PORT_DST;
- kg_cfg->extracts[i].type =
- DPKG_EXTRACT_FROM_HDR;
- kg_cfg->extracts[i].extract.from_hdr.type =
- DPKG_FULL_FIELD;
- i++;
- break;
-
- default:
- DPAA2_PMD_WARN(
- "unsupported flow dist option 0x%" PRIx64,
- dist_field);
- return -EINVAL;
- }
- }
- req_dist_set = req_dist_set >> 1;
- loop++;
- }
- kg_cfg->num_extracts = i;
- return 0;
-}
-
-int
-dpaa2_attach_bp_list(struct dpaa2_dev_priv *priv,
- struct fsl_mc_io *dpni, void *blist)
-{
- /* Function to attach a DPNI with a buffer pool list. Buffer pool list
- * handle is passed in blist.
- */
- int32_t retcode;
- struct dpni_pools_cfg bpool_cfg;
- struct dpaa2_bp_list *bp_list = (struct dpaa2_bp_list *)blist;
- struct dpni_buffer_layout layout;
- int tot_size;
-
- /* ... rx buffer layout .
- * Check alignment for buffer layouts first
- */
-
- /* ... rx buffer layout ... */
- if (priv->flags & DPAA2_TX_PREFETCH_DYNAMIC_CONF) {
- int out_min_hdr_room, in_min_hdr_room;
- /** Additional headroom layout for IPSec with TX configure
- * dynamic enabled.
- */
- in_min_hdr_room = DPAA2_RX_MIN_FD_OFFSET +
- DPAA2_SEC_SIMPLE_FD_IB_MIN;
- out_min_hdr_room = DPAA2_DYN_TX_MIN_FD_OFFSET +
- DPAA2_SEC_SIMPLE_FD_OB_MIN;
- tot_size = RTE_MAX(in_min_hdr_room, out_min_hdr_room);
- if (tot_size < RTE_PKTMBUF_HEADROOM)
- tot_size = RTE_PKTMBUF_HEADROOM;
- } else {
- tot_size = RTE_PKTMBUF_HEADROOM;
- }
- tot_size = RTE_ALIGN_CEIL(tot_size, DPAA2_PACKET_LAYOUT_ALIGN);
-
- memset(&layout, 0, sizeof(struct dpni_buffer_layout));
- layout.options = DPNI_BUF_LAYOUT_OPT_DATA_HEAD_ROOM |
- DPNI_BUF_LAYOUT_OPT_FRAME_STATUS |
- DPNI_BUF_LAYOUT_OPT_PARSER_RESULT |
- DPNI_BUF_LAYOUT_OPT_DATA_ALIGN |
- DPNI_BUF_LAYOUT_OPT_TIMESTAMP |
- DPNI_BUF_LAYOUT_OPT_PRIVATE_DATA_SIZE;
-
- layout.pass_timestamp = true;
- layout.pass_frame_status = 1;
- layout.private_data_size = DPAA2_FD_PTA_SIZE;
- layout.pass_parser_result = 1;
- layout.data_align = DPAA2_PACKET_LAYOUT_ALIGN;
- layout.data_head_room = tot_size - DPAA2_FD_PTA_SIZE -
- DPAA2_MBUF_HW_ANNOTATION;
- retcode = dpni_set_buffer_layout(dpni, CMD_PRI_LOW, priv->token,
- DPNI_QUEUE_RX, &layout);
- if (retcode) {
- DPAA2_PMD_ERR("Error configuring buffer pool Rx layout (%d)",
- retcode);
- return retcode;
- }
-
- /*Attach buffer pool to the network interface as described by the user*/
- memset(&bpool_cfg, 0, sizeof(struct dpni_pools_cfg));
- bpool_cfg.num_dpbp = 1;
- bpool_cfg.pools[0].dpbp_id = bp_list->buf_pool.dpbp_node->dpbp_id;
- bpool_cfg.pools[0].backup_pool = 0;
- bpool_cfg.pools[0].buffer_size = RTE_ALIGN_CEIL(bp_list->buf_pool.size,
- DPAA2_PACKET_LAYOUT_ALIGN);
- bpool_cfg.pools[0].priority_mask = 0;
-
- retcode = dpni_set_pools(dpni, CMD_PRI_LOW, priv->token, &bpool_cfg);
- if (retcode != 0) {
- DPAA2_PMD_ERR("Error configuring buffer pool on interface."
- " bpid = %d error code = %d",
- bpool_cfg.pools[0].dpbp_id, retcode);
- return retcode;
- }
-
- priv->bp_list = bp_list;
- return 0;
-}
diff --git a/drivers/net/dpaa2/dpaa2_ethdev.c b/drivers/net/dpaa2/dpaa2_ethdev.c
index 1836226706..a7c9bb678e 100644
--- a/drivers/net/dpaa2/dpaa2_ethdev.c
+++ b/drivers/net/dpaa2/dpaa2_ethdev.c
@@ -73,8 +73,6 @@ static uint64_t dev_tx_offloads_sup =
static uint64_t dev_tx_offloads_nodis =
RTE_ETH_TX_OFFLOAD_MULTI_SEGS;
-bool dpaa2_print_parser_result;
-
/* Rx descriptor limit when DPNI loads PFDRs in PEB */
#define MAX_NB_RX_DESC_IN_PEB 11264
static int total_nb_rx_desc;
@@ -85,27 +83,6 @@ static int total_nb_rx_desc;
* patterns are inspected by dpaa2_dev_rss_reta_update().
*/
#define DPAA2_RETA_SIZE 64
-
-/* Values of dist_size accepted by the DPNI 'dpni_set_rx_hash_dist' MC command.
- * Source: fsl_dpni.h, "struct dpni_rx_dist_cfg::dist_size" documentation.
- * Used by dpaa2_dev_rss_reta_update() to validate user-requested patterns.
- */
-static const uint16_t dpaa2_dist_size_allowed[] = {
- 1, 2, 3, 4, 6, 7, 8, 12, 14, 16, 24, 28, 32, 48, 56, 64,
- 96, 112, 128, 192, 224, 256, 384, 448, 512, 768, 896, 1024,
-};
-
-static bool
-dpaa2_dist_size_is_supported(uint16_t n)
-{
- size_t i;
- for (i = 0; i < RTE_DIM(dpaa2_dist_size_allowed); i++) {
- if (dpaa2_dist_size_allowed[i] == n)
- return true;
- }
- return false;
-}
-
int dpaa2_valid_dev;
struct rte_mempool *dpaa2_tx_sg_pool;
@@ -396,6 +373,197 @@ static int dpaa2_dev_link_update(struct rte_eth_dev *dev,
static int dpaa2_dev_set_link_up(struct rte_eth_dev *dev);
static int dpaa2_dev_set_link_down(struct rte_eth_dev *dev);
static int dpaa2_dev_mtu_set(struct rte_eth_dev *dev, uint16_t mtu);
+static int
+dpaa2_setup_table_miss_action(struct rte_eth_dev *eth_dev,
+ uint8_t tc_index)
+{
+ struct dpaa2_dev_priv *priv = eth_dev->data->dev_private;
+ struct rte_flow_group_attr attr;
+ struct rte_flow_action actions[2];
+ struct dpaa2_flow_tbl_profile *tbl_profile;
+
+ memset(&attr, 0, sizeof(attr));
+ attr.ingress = 1;
+ if (tc_index < priv->num_rx_tc) {
+ tbl_profile = &priv->flow_profile.tc_profile[tc_index];
+ if (tbl_profile->default_drop) {
+ actions[0].type = RTE_FLOW_ACTION_TYPE_DROP;
+ } else if (tbl_profile->default_queue.index >= eth_dev->data->nb_rx_queues) {
+ DPAA2_PMD_DEBUG("%s-tc%d-default-rxq(%d) >= max rxq(%d), Force to drop.",
+ eth_dev->data->name, tc_index, tbl_profile->default_queue.index,
+ eth_dev->data->nb_rx_queues);
+ tbl_profile->default_drop = true;
+ actions[0].type = RTE_FLOW_ACTION_TYPE_DROP;
+ } else {
+ actions[0].type = RTE_FLOW_ACTION_TYPE_QUEUE;
+ actions[0].conf = &tbl_profile->default_queue;
+ }
+ } else {
+ tbl_profile = &priv->flow_profile.qos_profile;
+ if (tbl_profile->default_drop) {
+ actions[0].type = RTE_FLOW_ACTION_TYPE_DROP;
+ } else if (tbl_profile->default_jump.group >= priv->num_rx_tc) {
+ DPAA2_PMD_DEBUG("%s-default-tc(%d) >= max tc(%d), Force to drop.",
+ eth_dev->data->name, tbl_profile->default_jump.group,
+ priv->num_rx_tc);
+ tbl_profile->default_drop = true;
+ actions[0].type = RTE_FLOW_ACTION_TYPE_DROP;
+ } else {
+ actions[0].type = RTE_FLOW_ACTION_TYPE_JUMP;
+ actions[0].conf = &tbl_profile->default_jump;
+ }
+ }
+ actions[1].type = RTE_FLOW_ACTION_TYPE_END;
+
+ return rte_flow_group_set_miss_actions(eth_dev->data->port_id,
+ tc_index, &attr, actions, NULL);
+}
+
+static int
+dpaa2_setup_flow_rss_dist(struct rte_eth_dev *eth_dev,
+ uint64_t req_dist_set, int tc_index)
+{
+ struct dpaa2_dev_priv *priv = eth_dev->data->dev_private;
+ int tc_dist_queues;
+ struct rte_flow_attr attr;
+ struct rte_flow_action_rss action_rss;
+ struct rte_flow_action actions[2];
+ struct rte_flow *rss_flow;
+
+ /*TC distribution size is set with dist_queues or
+ * nb_rx_queues % dist_queues in order of TC priority index.
+ * Calculating dist size for this tc_index:-
+ */
+ tc_dist_queues = eth_dev->data->nb_rx_queues -
+ tc_index * priv->dist_queues;
+ if (tc_dist_queues <= 0) {
+ DPAA2_PMD_DEBUG("No distribution on TC%d", tc_index);
+ return 0;
+ }
+
+ if (tc_dist_queues > priv->dist_queues)
+ tc_dist_queues = priv->dist_queues;
+
+ memset(&attr, 0, sizeof(attr));
+ action_rss.func = RTE_ETH_HASH_FUNCTION_DEFAULT;
+ action_rss.level = 0;
+ action_rss.types = req_dist_set;
+ action_rss.key_len = 0;
+ action_rss.key = NULL;
+ action_rss.queue = NULL;
+ action_rss.queue_num = tc_dist_queues;
+
+ actions[0].type = RTE_FLOW_ACTION_TYPE_RSS;
+ actions[0].conf = &action_rss;
+ actions[1].type = RTE_FLOW_ACTION_TYPE_END;
+ attr.group = tc_index;
+ attr.ingress = 1;
+ rss_flow = rte_flow_create(eth_dev->data->port_id, &attr, NULL, actions, NULL);
+ if (!rss_flow) {
+ DPAA2_PMD_WARN("%s: Set RSS flow dist on tc%d failed",
+ __func__, tc_index);
+ return -EIO;
+ }
+
+ return 0;
+}
+
+static int
+dpaa2_setup_flow_dcb_dist(struct rte_eth_dev *eth_dev,
+ uint8_t prio, uint8_t tc)
+{
+ struct dpaa2_dev_priv *priv = eth_dev->data->dev_private;
+ struct rte_flow_attr attr;
+ struct rte_flow_action actions[2];
+ struct rte_flow_item_vlan vlan_item;
+ struct rte_flow_item_vlan vlan_mask;
+ struct rte_flow_item items[2];
+ struct rte_flow_action_jump action_jump;
+ struct rte_flow *qos_flow;
+
+ memset(&attr, 0, sizeof(struct rte_flow_attr));
+ attr.ingress = 1;
+
+ attr.group = priv->num_rx_tc;
+ attr.priority = prio;
+ memset(&vlan_item, 0, sizeof(struct rte_flow_item_vlan));
+ memset(&vlan_mask, 0, sizeof(struct rte_flow_item_vlan));
+ vlan_item.hdr.vlan_tci = rte_cpu_to_be_16(RTE_VLAN_TCI_MAKE(0, prio, 0));
+ vlan_mask.hdr.vlan_tci = rte_cpu_to_be_16(RTE_VLAN_PRI_MASK);
+ items[0].spec = &vlan_item;
+ items[0].mask = &vlan_mask;
+ items[0].type = RTE_FLOW_ITEM_TYPE_VLAN;
+ items[1].type = RTE_FLOW_ITEM_TYPE_END;
+
+ actions[0].type = RTE_FLOW_ACTION_TYPE_JUMP;
+ action_jump.group = tc;
+ actions[0].conf = &action_jump;
+ actions[1].type = RTE_FLOW_ACTION_TYPE_END;
+
+ qos_flow = rte_flow_create(eth_dev->data->port_id,
+ &attr, items, actions, NULL);
+ if (!qos_flow) {
+ DPAA2_PMD_WARN("Failed to direct vlan with prio(%d) to tc%d", prio, tc);
+ return -EIO;
+ }
+ priv->dcb_flow[prio] = qos_flow;
+
+ return 0;
+}
+
+static int
+dpaa2_remove_flow_rss_dist(struct rte_eth_dev *eth_dev,
+ uint8_t tc_index)
+{
+ struct dpaa2_dev_priv *priv = eth_dev->data->dev_private;
+ struct dpaa2_flow_tbl_profile *tbl_profile;
+ int ret;
+
+ tbl_profile = &priv->flow_profile.tc_profile[tc_index];
+ if (!tbl_profile->rss_flow || !tbl_profile->is_rss) {
+ DPAA2_PMD_WARN("%s'TC[%d] is not RSS distributed",
+ eth_dev->data->name, tc_index);
+ return 0;
+ }
+ ret = rte_flow_destroy(eth_dev->data->port_id, tbl_profile->rss_flow, NULL);
+ if (ret)
+ return ret;
+ tbl_profile->rss_flow = NULL;
+
+ return 0;
+}
+
+static int
+dpaa2_update_flow_rss_dist(struct rte_eth_dev *eth_dev,
+ uint64_t req_dist_set, int tc_index)
+{
+ struct dpaa2_dev_priv *priv = eth_dev->data->dev_private;
+ struct dpaa2_flow_tbl_profile *tbl_profile;
+ struct rte_flow_action_rss action_rss;
+ struct rte_flow_action actions[2];
+ int ret;
+
+ tbl_profile = &priv->flow_profile.tc_profile[tc_index];
+ if (!tbl_profile->rss_flow || !tbl_profile->is_rss) {
+ DPAA2_PMD_WARN("%s'TC[%d] is not RSS distributed",
+ eth_dev->data->name, tc_index);
+ return 0;
+ }
+ action_rss.func = RTE_ETH_HASH_FUNCTION_DEFAULT;
+ action_rss.level = 0;
+ action_rss.types = req_dist_set;
+ action_rss.key_len = 0;
+ action_rss.queue_num = tbl_profile->tc_cfg.dist_size;
+ action_rss.key = NULL;
+ action_rss.queue = NULL;
+ actions[0].type = RTE_FLOW_ACTION_TYPE_RSS;
+ actions[0].conf = &action_rss;
+ actions[1].type = RTE_FLOW_ACTION_TYPE_END;
+ ret = rte_flow_actions_update(eth_dev->data->port_id, tbl_profile->rss_flow,
+ actions, NULL);
+
+ return ret;
+}
static int
dpaa2_vlan_filter_set(struct rte_eth_dev *dev, uint16_t vlan_id, int on)
@@ -613,7 +781,7 @@ dpaa2_dev_info_get(struct rte_eth_dev *dev,
dev_rx_offloads_nodis;
dev_info->tx_offload_capa = dev_tx_offloads_sup |
dev_tx_offloads_nodis;
- dev_info->dev_capa &= ~RTE_ETH_DEV_CAPA_FLOW_RULE_KEEP;
+ dev_info->dev_capa = 0;
dev_info->max_hash_mac_addrs = 0;
dev_info->max_vfs = 0;
@@ -883,6 +1051,28 @@ dpaa2_free_rx_tx_queues(struct rte_eth_dev *dev)
}
}
+static int
+dpaa2_dev_dcb_info(struct rte_eth_dev *dev,
+ struct rte_eth_dcb_info *dcb_info)
+{
+ struct dpaa2_dev_priv *priv = dev->data->dev_private;
+ int i;
+
+ if (!priv->nb_dcb_tcs)
+ return -ENOTSUP;
+
+ memset(dcb_info, 0, sizeof(struct rte_eth_dcb_info));
+ dcb_info->nb_tcs = priv->nb_dcb_tcs;
+ rte_memcpy(dcb_info->prio_tc, priv->prio_dcb_tc,
+ sizeof(uint8_t) * RTE_ETH_DCB_NUM_USER_PRIORITIES);
+ for (i = 0; i < dcb_info->nb_tcs; i++) {
+ dcb_info->tc_queue.tc_rxq[0][i].base = priv->dist_queues * i;
+ dcb_info->tc_queue.tc_rxq[0][i].nb_queue = priv->dist_queues;
+ }
+
+ return 0;
+}
+
static int
dpaa2_eth_dev_configure(struct rte_eth_dev *dev)
{
@@ -895,8 +1085,12 @@ dpaa2_eth_dev_configure(struct rte_eth_dev *dev)
int rx_l4_csum_offload = false;
int tx_l3_csum_offload = false;
int tx_l4_csum_offload = false;
- int ret, tc_index;
- uint32_t max_rx_pktlen;
+ int ret, tc_index, nb_tcs;
+ uint32_t max_rx_pktlen, base;
+ struct rte_eth_rss_conf *rss_conf;
+ struct rte_eth_dcb_rx_conf *dcb_rx_conf;
+ struct rte_dpaa2_default_action_conf *def_act_conf;
+ struct dpaa2_flow_tbl_profile *tbl_profile;
PMD_INIT_FUNC_TRACE();
@@ -942,15 +1136,64 @@ dpaa2_eth_dev_configure(struct rte_eth_dev *dev)
return -1;
}
- if (eth_conf->rxmode.mq_mode == RTE_ETH_MQ_RX_RSS) {
+ rss_conf = ð_conf->rx_adv_conf.rss_conf;
+ dcb_rx_conf = ð_conf->rx_adv_conf.dcb_rx_conf;
+ def_act_conf = eth_conf->rxmode.reserved_ptrs[0];
+
+ for (tc_index = 0; tc_index < priv->num_rx_tc; tc_index++) {
+ tbl_profile = &priv->flow_profile.tc_profile[tc_index];
+ base = priv->dist_queues * tc_index;
+ if (def_act_conf && tc_index < def_act_conf->max_tc) {
+ if (def_act_conf->default_flows[tc_index] >= priv->dist_queues) {
+ tbl_profile->default_drop = true;
+ } else {
+ tbl_profile->default_drop = false;
+ tbl_profile->default_queue.index = base +
+ def_act_conf->default_flows[tc_index];
+ }
+ }
+ if (priv->fs_entries) {
+ ret = dpaa2_setup_table_miss_action(dev, tc_index);
+ if (ret) {
+ DPAA2_PMD_ERR("Error(%d) to set miss action of %s-tc%d table",
+ ret, dev->data->name, tc_index);
+ }
+ }
+ }
+ if (def_act_conf) {
+ tbl_profile = &priv->flow_profile.qos_profile;
+ if (def_act_conf->default_tc >= priv->num_rx_tc) {
+ tbl_profile->default_drop = true;
+ } else {
+ tbl_profile->default_drop = false;
+ tbl_profile->default_jump.group = def_act_conf->default_tc;
+ }
+ }
+ ret = dpaa2_setup_table_miss_action(dev, priv->num_rx_tc);
+ if (ret) {
+ DPAA2_PMD_ERR("Error(%d) to set miss action of %s-QoS table",
+ ret, dev->data->name);
+ }
+
+ if (eth_conf->rxmode.mq_mode & RTE_ETH_MQ_RX_RSS) {
for (tc_index = 0; tc_index < priv->num_rx_tc; tc_index++) {
- ret = dpaa2_setup_flow_dist(dev,
- eth_conf->rx_adv_conf.rss_conf.rss_hf,
- tc_index);
+ ret = dpaa2_setup_flow_rss_dist(dev, rss_conf->rss_hf, tc_index);
if (ret) {
- DPAA2_PMD_ERR(
- "Unable to set flow distribution on tc%d."
- "Check queue config", tc_index);
+ DPAA2_PMD_ERR("RSS dist on tc%d err(%d)", tc_index, ret);
+ return ret;
+ }
+ }
+ }
+
+ if ((eth_conf->rxmode.mq_mode & RTE_ETH_MQ_RX_DCB) && priv->qos_entries) {
+ nb_tcs = dcb_rx_conf->nb_tcs;
+ for (tc_index = 0; tc_index < nb_tcs; tc_index++) {
+ if (tc_index >= priv->num_rx_tc)
+ break;
+ ret = dpaa2_setup_flow_dcb_dist(dev, dcb_rx_conf->dcb_tc[tc_index],
+ tc_index);
+ if (ret) {
+ DPAA2_PMD_ERR("DCB direct to tc%d err(%d)", tc_index, ret);
return ret;
}
}
@@ -1097,7 +1340,6 @@ dpaa2_dev_rx_queue_setup(struct rte_eth_dev *dev,
struct dpni_taildrop taildrop;
uint8_t qopt = 0;
uint16_t flow_id;
- uint32_t bpid;
int ret;
PMD_INIT_FUNC_TRACE();
@@ -1116,18 +1358,6 @@ dpaa2_dev_rx_queue_setup(struct rte_eth_dev *dev,
nb_rx_desc);
}
- if (!priv->bp_list || priv->bp_list->mp != mb_pool) {
- if (rte_eal_process_type() != RTE_PROC_PRIMARY) {
- ret = rte_dpaa2_bpid_info_init(mb_pool);
- if (ret)
- return ret;
- }
- bpid = mempool_to_bpid(mb_pool);
- ret = dpaa2_attach_bp_list(priv, dpni,
- rte_dpaa2_bpid_info[bpid].bp_list);
- if (ret)
- return ret;
- }
dpaa2_q = priv->rx_vq[rx_queue_id];
if (dpaa2_q->fqid != DPAA2_INVALID_FQ_ID) {
DPAA2_PMD_WARN("%s: RXQ[%d] has been setup",
@@ -1797,6 +2027,7 @@ dpaa2_dev_close(struct rte_eth_dev *dev)
struct fsl_mc_io *dpni = dev->process_private;
int i, ret;
struct rte_eth_link link;
+ struct dpaa2_flow_tbl_profile *tbl_profile;
PMD_INIT_FUNC_TRACE();
@@ -1809,7 +2040,9 @@ dpaa2_dev_close(struct rte_eth_dev *dev)
}
dpaa2_tm_deinit(dev);
- dpaa2_flow_clean(dev);
+ dpaa2_flow_clean(dev, MAX_TCS);
+ /** No matter dcb flows are created or not, they are destroyed in flow clean.*/
+ memset(priv->dcb_flow, 0, sizeof(void *) * RTE_ETH_DCB_NUM_USER_PRIORITIES);
/* Clean the device first */
ret = dpni_reset(dpni, CMD_PRI_LOW, priv->token);
if (ret) {
@@ -1843,10 +2076,16 @@ dpaa2_dev_close(struct rte_eth_dev *dev)
dev->process_private = NULL;
rte_free(dpni);
- for (i = 0; i < MAX_TCS; i++)
- rte_free(priv->extract.tc_extract_param[i]);
-
- rte_free(priv->extract.qos_extract_param);
+ for (i = 0; i < (MAX_TCS + 1); i++) {
+ if (i < MAX_TCS)
+ tbl_profile = &priv->flow_profile.tc_profile[i];
+ else
+ tbl_profile = &priv->flow_profile.qos_profile;
+ rte_free(tbl_profile->extract_param);
+ tbl_profile->extract_param = NULL;
+ rte_free(tbl_profile->entry_map);
+ tbl_profile->entry_map = NULL;
+ }
rte_free(priv->cnt_idx_dma_mem);
rte_free(priv->cnt_values_dma_mem);
@@ -2746,25 +2985,25 @@ dpaa2_dev_rss_hash_update(struct rte_eth_dev *dev,
if (rss_conf->rss_hf) {
for (tc_index = 0; tc_index < priv->num_rx_tc; tc_index++) {
- ret = dpaa2_setup_flow_dist(dev, rss_conf->rss_hf,
+ ret = dpaa2_update_flow_rss_dist(dev, rss_conf->rss_hf,
tc_index);
- if (ret) {
- DPAA2_PMD_ERR("Unable to set flow dist on tc%d",
- tc_index);
- return ret;
- }
+ if (ret)
+ break;
}
} else {
for (tc_index = 0; tc_index < priv->num_rx_tc; tc_index++) {
- ret = dpaa2_remove_flow_dist(dev, tc_index);
- if (ret) {
- DPAA2_PMD_ERR(
- "Unable to remove flow dist on tc%d",
- tc_index);
- return ret;
- }
+ ret = dpaa2_remove_flow_rss_dist(dev, tc_index);
+ if (ret)
+ break;
}
}
+ if (ret) {
+ DPAA2_PMD_ERR("%s: %s flow dist on tc%d err(%d)",
+ data->name, rss_conf->rss_hf ? "set" : "remove",
+ tc_index, ret);
+
+ return ret;
+ }
eth_conf->rx_adv_conf.rss_conf.rss_hf = rss_conf->rss_hf;
return 0;
}
@@ -2879,23 +3118,34 @@ dpaa2_dev_rss_reta_update(struct rte_eth_dev *dev,
}
}
- if (!dpaa2_dist_size_is_supported(n)) {
- DPAA2_PMD_ERR("dist_size %u not supported by HW. Allowed: "
- "1,2,3,4,6,7,8,12,14,16,24,28,32,48,56,64,...",
- n);
+ /* The requested distribution size cannot exceed the number of
+ * distribution queues provisioned per TC. Any HW-specific limitation
+ * on the exact value is enforced later by the rte_flow update.
+ */
+ if (n > priv->dist_queues) {
+ DPAA2_PMD_ERR("dist_size %u exceeds max distribution queues %u",
+ n, priv->dist_queues);
return -ENOTSUP;
}
- /* Apply on every configured RX TC, matching rss_hash_update behavior. */
+ /* Apply on every configured RX TC, matching rss_hash_update behavior.
+ * Program the new dist_size into each TC's RSS flow profile and push
+ * it to the live flow via rte_flow_actions_update().
+ */
for (tc_index = 0; tc_index < priv->num_rx_tc; tc_index++) {
- ret = dpaa2_setup_flow_dist_size(dev,
+ struct dpaa2_flow_tbl_profile *tbl_profile =
+ &priv->flow_profile.tc_profile[tc_index];
+
+ tbl_profile->tc_cfg.dist_size = n;
+ ret = dpaa2_update_flow_rss_dist(dev,
eth_conf->rx_adv_conf.rss_conf.rss_hf,
- tc_index, n);
+ tc_index);
if (ret) {
DPAA2_PMD_ERR("Failed to apply dist_size=%u on tc%d (err=%d)",
n, tc_index, ret);
return ret;
}
+ priv->dist_size_cur[tc_index] = n;
}
DPAA2_PMD_DEBUG("RETA updated: dist_size now %u on %u TC(s)",
@@ -3453,7 +3703,8 @@ static struct eth_dev_ops dpaa2_ethdev_ops = {
.timesync_adjust_time = dpaa2_timesync_adjust_time,
.timesync_read_rx_timestamp = dpaa2_timesync_read_rx_timestamp,
.timesync_read_tx_timestamp = dpaa2_timesync_read_tx_timestamp,
- .mtr_ops_get = dpaa2_mtr_ops_get,
+ .mtr_ops_get = dpaa2_mtr_ops_get,
+ .get_dcb_info = dpaa2_dev_dcb_info
};
/* Populate the mac address from physically available (u-boot/firmware) and/or
@@ -3570,7 +3821,9 @@ dpaa2_dev_init(struct rte_eth_dev *eth_dev)
struct dpni_attr attr;
struct dpaa2_dev_priv *priv = eth_dev->data->dev_private;
struct dpni_buffer_layout layout;
- int ret, hw_id, i;
+ int ret, hw_id, i, entry_num;
+ struct dpaa2_flow_tbl_profile *tbl_profile;
+ uint64_t iova;
PMD_INIT_FUNC_TRACE();
@@ -3668,8 +3921,6 @@ dpaa2_dev_init(struct rte_eth_dev *eth_dev)
priv->dist_queues = attr.num_queues;
priv->num_channels = attr.num_channels;
priv->channel_inuse = 0;
- priv->default_flow = RTE_MIN(priv->fs_entries,
- priv->dist_queues) - 1;
rte_spinlock_init(&priv->lpbk_qp_lock);
/* only if the custom CG is enabled */
@@ -3830,27 +4081,51 @@ dpaa2_dev_init(struct rte_eth_dev *eth_dev)
eth_dev->tx_pkt_burst = dpaa2_dev_tx;
/* Init fields w.r.t. classification */
- memset(&priv->extract.qos_key_extract, 0,
- sizeof(struct dpaa2_key_extract));
- priv->extract.qos_extract_param = rte_zmalloc(NULL,
- DPAA2_EXTRACT_PARAM_MAX_SIZE,
- RTE_CACHE_LINE_SIZE);
- if (!priv->extract.qos_extract_param) {
- DPAA2_PMD_ERR("Memory alloc failed");
- goto init_err;
- }
-
- for (i = 0; i < MAX_TCS; i++) {
- memset(&priv->extract.tc_key_extract[i], 0,
- sizeof(struct dpaa2_key_extract));
- priv->extract.tc_extract_param[i] = rte_zmalloc(NULL,
+ for (i = 0; i < (MAX_TCS + 1); i++) {
+ if (i < MAX_TCS) {
+ tbl_profile = &priv->flow_profile.tc_profile[i];
+ entry_num = priv->fs_entries;
+ } else {
+ tbl_profile = &priv->flow_profile.qos_profile;
+ entry_num = priv->qos_entries;
+ }
+ memset(tbl_profile, 0, sizeof(struct dpaa2_flow_tbl_profile));
+ tbl_profile->extract_param = rte_zmalloc(NULL,
DPAA2_EXTRACT_PARAM_MAX_SIZE,
RTE_CACHE_LINE_SIZE);
- if (!priv->extract.tc_extract_param[i]) {
- DPAA2_PMD_ERR("Memory alloc failed");
+ if (!tbl_profile->extract_param)
goto init_err;
+ iova = DPAA2_VADDR_TO_IOVA_AND_CHECK(tbl_profile->extract_param,
+ DPAA2_EXTRACT_PARAM_MAX_SIZE);
+ tbl_profile->default_drop = false;
+ if (i < MAX_TCS) {
+ tbl_profile->tc_cfg.dist_size = priv->dist_queues;
+ tbl_profile->tc_cfg.key_cfg_iova = iova;
+ tbl_profile->tc_cfg.tc = i;
+ /** First flow of TC as default flow, otherwise, may be dropped.*/
+ tbl_profile->default_queue.index = priv->dist_queues * i;
+ } else {
+ tbl_profile->qos_cfg.key_cfg_iova = iova;
+ tbl_profile->qos_cfg.keep_entries = true;
+ /** First TC as default TC, otherwise, may be dropped.*/
+ tbl_profile->default_jump.group = 0;
}
+ if (!entry_num)
+ continue;
+
+ tbl_profile->entry_map = rte_zmalloc(NULL, entry_num / 8 + 1, 0);
+ if (!tbl_profile->entry_map)
+ goto init_err;
+ }
+
+ for (i = 0; i < priv->num_rx_tc; i++) {
+ if (i >= RTE_ETH_DCB_NUM_USER_PRIORITIES)
+ break;
+ if (i >= priv->qos_entries)
+ break;
+ priv->prio_dcb_tc[i] = i;
}
+ priv->nb_dcb_tcs = i;
ret = dpni_set_max_frame_length(dpni_dev, CMD_PRI_LOW, priv->token,
RTE_ETHER_MAX_LEN - RTE_ETHER_CRC_LEN
diff --git a/drivers/net/dpaa2/dpaa2_ethdev.h b/drivers/net/dpaa2/dpaa2_ethdev.h
index 523c420c51..5659abcd51 100644
--- a/drivers/net/dpaa2/dpaa2_ethdev.h
+++ b/drivers/net/dpaa2/dpaa2_ethdev.h
@@ -1,7 +1,7 @@
/* SPDX-License-Identifier: BSD-3-Clause
*
* Copyright (c) 2015-2016 Freescale Semiconductor, Inc. All rights reserved.
- * Copyright 2016-2025 NXP
+ * Copyright 2016-2026 NXP
*
*/
@@ -12,6 +12,7 @@
#include <rte_compat.h>
#include <rte_event_eth_rx_adapter.h>
#include <rte_pmd_dpaa2.h>
+#include <rte_string_fns.h>
#include <bus_fslmc_driver.h>
#include <dpaa2_hw_pvt.h>
@@ -24,6 +25,13 @@
#include "base/dpaa2_hw_dpni_annot.h"
#include "dpaa2_parser_decode.h"
+#define DPAA2_FLOW_FRM_REPLICATION_ACTION_MC_REV RTE_FSL_MC_REV(10, 39, 106)
+#define DPAA2_FS_FLOW_HW_ACTION_UPDATE_MC_REV RTE_FSL_MC_REV(10, 39, 106)
+#define DPAA2_QOS_FLOW_HW_ACTION_UPDATE_MC_REV RTE_FSL_MC_REV(10, 39, 109)
+#define DPAA2_POLICER_SET_V2_MC_REV RTE_FSL_MC_REV(10, 39, 109)
+#define DPAA2_POLICER_NOT_RESET_COUNTER_MC_REV DPAA2_POLICER_SET_V2_MC_REV
+#define DPAA2_QOS_FLOW_TABLE_MISS_FLOW_ACTION_MC_REV RTE_FSL_MC_REV(10, 39, 109)
+#define DPAA2_QOS_FLOW_TABLE_SET_V3_MC_REV RTE_FSL_MC_REV(10, 39, 109)
#define DPAA2_MIN_RX_BUF_SIZE 512
#define DPAA2_MAX_RX_PKT_LEN 10240 /*WRIOP support*/
@@ -35,6 +43,10 @@
#define MAX_DPNI 8
#define DPAA2_MAX_CHANNELS 16
+#define DPAA2_DEV_PRIV_TO_DPAA2_DEV(priv) \
+ container_of((((struct dpaa2_dev_priv *)priv)->eth_dev->device), \
+ struct rte_dpaa2_device, device)
+
#define DPAA2_EXTRACT_PARAM_MAX_SIZE \
RTE_ALIGN(sizeof(struct dpni_ext_set_rx_tc_dist), 256)
@@ -254,125 +266,9 @@ struct dpaa2_dyn_rx_protocol_pos {
#define DPAA2_FS_FLC_FLOW_OFFSET \
(DPAA2_FS_FLC_TC_OFFSET + DPAA2_FS_FLC_TC_BIT_SIZE)
-#define DPAA2_FAPR_SIZE \
- (sizeof(struct dpaa2_annot_hdr) - \
- offsetof(struct dpaa2_annot_hdr, word3))
-
-#define DPAA2_PR_NXTHDR_OFFSET 0
-
-#define DPAA2_FAFE_PSR_OFFSET 2
-#define DPAA2_FAFE_PSR_SIZE 2
-
-#define DPAA2_FAF_PSR_OFFSET 4
-#define DPAA2_FAF_PSR_SIZE 12
-
-#define DPAA2_FAF_TOTAL_SIZE \
- (DPAA2_FAFE_PSR_SIZE + DPAA2_FAF_PSR_SIZE)
-
-/* Just most popular Frame attribute flags (FAF) here.*/
-enum dpaa2_rx_faf_offset {
- /* Set by SP start*/
- FAFE_VXLAN_IN_VLAN_FRAM = 0,
- FAFE_VXLAN_IN_IPV4_FRAM = 1,
- FAFE_VXLAN_IN_IPV6_FRAM = 2,
- FAFE_VXLAN_IN_UDP_FRAM = 3,
- FAFE_VXLAN_IN_TCP_FRAM = 4,
-
- FAFE_ECPRI_FRAM = 7,
- /* Set by SP end*/
-
- FAF_GTP_PRIMED_FRAM = 1 + DPAA2_FAFE_PSR_SIZE * 8,
- FAF_PTP_FRAM = 3 + DPAA2_FAFE_PSR_SIZE * 8,
- FAF_VXLAN_FRAM = 4 + DPAA2_FAFE_PSR_SIZE * 8,
- FAF_ETH_FRAM = 10 + DPAA2_FAFE_PSR_SIZE * 8,
- FAF_LLC_SNAP_FRAM = 18 + DPAA2_FAFE_PSR_SIZE * 8,
- FAF_VLAN_FRAM = 21 + DPAA2_FAFE_PSR_SIZE * 8,
- FAF_PPPOE_PPP_FRAM = 25 + DPAA2_FAFE_PSR_SIZE * 8,
- FAF_MPLS_FRAM = 27 + DPAA2_FAFE_PSR_SIZE * 8,
- FAF_ARP_FRAM = 30 + DPAA2_FAFE_PSR_SIZE * 8,
- FAF_IPV4_FRAM = 34 + DPAA2_FAFE_PSR_SIZE * 8,
- FAF_IPV6_FRAM = 42 + DPAA2_FAFE_PSR_SIZE * 8,
- FAF_IP_FRAM = 48 + DPAA2_FAFE_PSR_SIZE * 8,
- FAF_IP_FRAG_FRAM = 50 + DPAA2_FAFE_PSR_SIZE * 8,
- FAF_ICMP_FRAM = 57 + DPAA2_FAFE_PSR_SIZE * 8,
- FAF_IGMP_FRAM = 58 + DPAA2_FAFE_PSR_SIZE * 8,
- FAF_GRE_FRAM = 65 + DPAA2_FAFE_PSR_SIZE * 8,
- FAF_UDP_FRAM = 70 + DPAA2_FAFE_PSR_SIZE * 8,
- FAF_TCP_FRAM = 72 + DPAA2_FAFE_PSR_SIZE * 8,
- FAF_IPSEC_FRAM = 77 + DPAA2_FAFE_PSR_SIZE * 8,
- FAF_IPSEC_ESP_FRAM = 78 + DPAA2_FAFE_PSR_SIZE * 8,
- FAF_IPSEC_AH_FRAM = 79 + DPAA2_FAFE_PSR_SIZE * 8,
- FAF_SCTP_FRAM = 81 + DPAA2_FAFE_PSR_SIZE * 8,
- FAF_DCCP_FRAM = 83 + DPAA2_FAFE_PSR_SIZE * 8,
- FAF_GTP_FRAM = 87 + DPAA2_FAFE_PSR_SIZE * 8,
- FAF_ESP_FRAM = 89 + DPAA2_FAFE_PSR_SIZE * 8,
-};
-
-enum dpaa2_ecpri_fafe_type {
- ECPRI_FAFE_TYPE_0 = (8 - FAFE_ECPRI_FRAM),
- ECPRI_FAFE_TYPE_1 = (8 - FAFE_ECPRI_FRAM) | (1 << 1),
- ECPRI_FAFE_TYPE_2 = (8 - FAFE_ECPRI_FRAM) | (2 << 1),
- ECPRI_FAFE_TYPE_3 = (8 - FAFE_ECPRI_FRAM) | (3 << 1),
- ECPRI_FAFE_TYPE_4 = (8 - FAFE_ECPRI_FRAM) | (4 << 1),
- ECPRI_FAFE_TYPE_5 = (8 - FAFE_ECPRI_FRAM) | (5 << 1),
- ECPRI_FAFE_TYPE_6 = (8 - FAFE_ECPRI_FRAM) | (6 << 1),
- ECPRI_FAFE_TYPE_7 = (8 - FAFE_ECPRI_FRAM) | (7 << 1)
-};
-
-#define DPAA2_PR_ETH_OFF_OFFSET 19
-#define DPAA2_PR_TCI_OFF_OFFSET 21
-#define DPAA2_PR_LAST_ETYPE_OFFSET 23
-#define DPAA2_PR_L3_OFF_OFFSET 27
-#define DPAA2_PR_L4_OFF_OFFSET 30
-#define DPAA2_PR_L5_OFF_OFFSET 31
-#define DPAA2_PR_NXTHDR_OFF_OFFSET 34
-
#define DPAA2_ECPRI_MAX_EXTRACT_NB 8
-struct ipv4_sd_addr_extract_rule {
- uint32_t ipv4_src;
- uint32_t ipv4_dst;
-};
-
-struct ipv6_sd_addr_extract_rule {
- uint8_t ipv6_src[NH_FLD_IPV6_ADDR_SIZE];
- uint8_t ipv6_dst[NH_FLD_IPV6_ADDR_SIZE];
-};
-
-struct ipv4_ds_addr_extract_rule {
- uint32_t ipv4_dst;
- uint32_t ipv4_src;
-};
-
-struct ipv6_ds_addr_extract_rule {
- uint8_t ipv6_dst[NH_FLD_IPV6_ADDR_SIZE];
- uint8_t ipv6_src[NH_FLD_IPV6_ADDR_SIZE];
-};
-
-union ip_addr_extract_rule {
- struct ipv4_sd_addr_extract_rule ipv4_sd_addr;
- struct ipv6_sd_addr_extract_rule ipv6_sd_addr;
- struct ipv4_ds_addr_extract_rule ipv4_ds_addr;
- struct ipv6_ds_addr_extract_rule ipv6_ds_addr;
-};
-
-union ip_src_addr_extract_rule {
- uint32_t ipv4_src;
- uint8_t ipv6_src[NH_FLD_IPV6_ADDR_SIZE];
-};
-
-union ip_dst_addr_extract_rule {
- uint32_t ipv4_dst;
- uint8_t ipv6_dst[NH_FLD_IPV6_ADDR_SIZE];
-};
-
-enum ip_addr_extract_type {
- IP_NONE_ADDR_EXTRACT,
- IP_SRC_EXTRACT,
- IP_DST_EXTRACT,
- IP_SRC_DST_EXTRACT,
- IP_DST_SRC_EXTRACT
-};
+#define DPAA2_IBTH_MAX_EXTRACT_NB 4
enum key_prot_type {
/* HW extracts from standard protocol fields*/
@@ -389,9 +285,9 @@ struct key_prot_field {
uint32_t key_field;
};
-struct dpaa2_raw_region {
- uint8_t raw_start;
- uint8_t raw_size;
+struct dpaa2_ip_addr_extract {
+ uint32_t field;
+ uint8_t max_size;
};
struct dpaa2_key_profile {
@@ -399,35 +295,52 @@ struct dpaa2_key_profile {
uint8_t key_offset[DPKG_MAX_NUM_OF_EXTRACTS];
uint8_t key_size[DPKG_MAX_NUM_OF_EXTRACTS];
- enum ip_addr_extract_type ip_addr_type;
- uint8_t ip_addr_extract_pos;
- uint8_t ip_addr_extract_off;
-
- uint8_t raw_extract_pos;
- uint8_t raw_extract_off;
- uint8_t raw_extract_num;
+ struct dpaa2_ip_addr_extract ip_addr_extracts[2];
- uint8_t l4_src_port_present;
- uint8_t l4_src_port_pos;
- uint8_t l4_src_port_offset;
- uint8_t l4_dst_port_present;
- uint8_t l4_dst_port_pos;
- uint8_t l4_dst_port_offset;
+ uint8_t l4_sp_present;
+ uint8_t l4_sp_extract_idx;
+ uint8_t l4_sp_key_offset;
+ uint8_t l4_dp_present;
+ uint8_t l4_dp_extract_idx;
+ uint8_t l4_dp_key_offset;
struct key_prot_field prot_field[DPKG_MAX_NUM_OF_EXTRACTS];
uint16_t key_max_size;
- struct dpaa2_raw_region raw_region;
};
-struct dpaa2_key_extract {
+struct dpaa2_flow_tbl_profile {
struct dpkg_profile_cfg dpkg;
struct dpaa2_key_profile key_profile;
+ uint8_t *extract_param;
+ int entry_num;
+ uint8_t *entry_map;
+ int enabled;
+ int is_rss;
+ void *rss_flow;
+ union {
+ struct dpni_qos_tbl_cfg qos_cfg;
+ struct dpni_rx_dist_cfg tc_cfg;
+ };
+ int default_drop;
+ union {
+ struct rte_flow_action_jump default_jump;
+ struct rte_flow_action_queue default_queue;
+ };
};
-struct extract_s {
- struct dpaa2_key_extract qos_key_extract;
- struct dpaa2_key_extract tc_key_extract[MAX_TCS];
- uint8_t *qos_extract_param;
- uint8_t *tc_extract_param[MAX_TCS];
+struct dpaa2_flow_profile {
+ struct dpaa2_flow_tbl_profile qos_profile;
+ struct dpaa2_flow_tbl_profile tc_profile[MAX_TCS];
+ /** Meter per TC.*/
+ struct dpaa2_dev_meter_profile *tc_mtr_profile[MAX_TCS];
+ void *mtr_flow[MAX_TCS];
+ void *mempool[MAX_TCS];
+ uint8_t bp_idx[MAX_TCS];
+};
+
+struct rte_dpaa2_default_action_conf {
+ uint8_t default_tc;
+ uint8_t max_tc;
+ uint16_t default_flows[];
};
struct dpaa2_dev_meter_profile {
@@ -491,15 +404,12 @@ struct dpaa2_dev_priv {
/** RXQs in same TC share same cgid.*/
uint8_t cgid_in_use[MAX_TCS];
rte_spinlock_t meter_lock;
- /* Lowest priority FS flow id to receive flow steering miss frames. */
- uint16_t default_flow;
/* Current hash distribution size per RX TC, written by
* dpaa2_setup_flow_dist_size() and read by reta_query / reta_update.
* Zero means "use default" (= nb_rx_queues clamped to dist_queues).
*/
uint16_t dist_size_cur[MAX_TCS];
-
uint16_t dpni_ver_major;
uint16_t dpni_ver_minor;
uint32_t speed_capa;
@@ -508,7 +418,10 @@ struct dpaa2_dev_priv {
uint16_t ep_object_id; /**< Endpoint DPAA2 Object ID */
char ep_name[RTE_DEV_NAME_MAX_LEN];
- struct extract_s extract;
+ struct dpaa2_flow_profile flow_profile;
+ uint8_t nb_dcb_tcs;
+ uint8_t prio_dcb_tc[RTE_ETH_DCB_NUM_USER_PRIORITIES];
+ void *dcb_flow[RTE_ETH_DCB_NUM_USER_PRIORITIES];
uint16_t ss_offset;
uint64_t ss_iova;
@@ -528,6 +441,7 @@ struct dpaa2_dev_priv {
struct rte_eth_dev *eth_dev; /**< Pointer back to holding ethdev */
rte_spinlock_t lpbk_qp_lock;
+ bool enable_bp_flow_ctrl;
bool sp_protocol;
uint8_t channel_inuse;
/* Rx-interrupt mode latched at the first dev_configure */
@@ -549,7 +463,7 @@ struct dpaa2_dev_priv {
struct rte_mempool *tx_sg_pool;
- struct dpaa2_dev_flow *curr;
+ struct dpaa2_generic_flow *cur_flow;
LIST_HEAD(, dpaa2_dev_flow) flows;
LIST_HEAD(, dpaa2_dev_meter_profile) profiles;
LIST_HEAD(, dpaa2_dev_meter_policy) policies;
@@ -569,6 +483,8 @@ static inline int dpaa2_dev_cmp_dpni_ver(struct dpaa2_dev_priv *priv,
return priv->dpni_ver_major - ver_major;
}
+#define DPAA2_FLOW_DUMP dpaa2_dump_print
+
static inline void
dpaa2_dev_rx_print_parser_result(struct dpaa2_dev_priv *priv,
const struct qbman_fd *fd, const struct rte_mbuf *m)
@@ -619,21 +535,269 @@ dpaa2_timestamp_debug(struct dpaa2_dev_priv *priv,
prefix, timestamp, (int64_t)ts.tv_sec, (int64_t)ts.tv_nsec);
}
-int dpaa2_distset_to_dpkg_profile_cfg(uint64_t req_dist_set,
- struct dpkg_profile_cfg *kg_cfg);
+static inline void
+dpaa2_prot_field_string(uint32_t prot, uint32_t field,
+ char *string, size_t size)
+{
+ if (prot == NET_PROT_ETH) {
+ strlcpy(string, "eth", size);
+ if (field == NH_FLD_ETH_DA)
+ strlcat(string, ".dst", size);
+ else if (field == NH_FLD_ETH_SA)
+ strlcat(string, ".src", size);
+ else if (field == NH_FLD_ETH_TYPE)
+ strlcat(string, ".type", size);
+ else
+ strlcat(string, ".unknown field", size);
+ } else if (prot == NET_PROT_VLAN) {
+ strlcpy(string, "vlan", size);
+ if (field == NH_FLD_VLAN_TCI)
+ strlcat(string, ".tci", size);
+ else
+ strlcat(string, ".unknown field", size);
+ } else if (prot == NET_PROT_IP) {
+ strlcpy(string, "ip", size);
+ if (field == NH_FLD_IP_SRC)
+ strlcat(string, ".src", size);
+ else if (field == NH_FLD_IP_DST)
+ strlcat(string, ".dst", size);
+ else if (field == NH_FLD_IP_PROTO)
+ strlcat(string, ".proto", size);
+ else
+ strlcat(string, ".unknown field", size);
+ } else if (prot == NET_PROT_TCP) {
+ strlcpy(string, "tcp", size);
+ if (field == NH_FLD_TCP_PORT_SRC)
+ strlcat(string, ".src", size);
+ else if (field == NH_FLD_TCP_PORT_DST)
+ strlcat(string, ".dst", size);
+ else
+ strlcat(string, ".unknown field", size);
+ } else if (prot == NET_PROT_UDP) {
+ strlcpy(string, "udp", size);
+ if (field == NH_FLD_UDP_PORT_SRC)
+ strlcat(string, ".src", size);
+ else if (field == NH_FLD_UDP_PORT_DST)
+ strlcat(string, ".dst", size);
+ else
+ strlcat(string, ".unknown field", size);
+ } else if (prot == NET_PROT_ICMP) {
+ strlcpy(string, "icmp", size);
+ if (field == NH_FLD_ICMP_TYPE)
+ strlcat(string, ".type", size);
+ else if (field == NH_FLD_ICMP_CODE)
+ strlcat(string, ".code", size);
+ else
+ strlcat(string, ".unknown field", size);
+ } else if (prot == NET_PROT_SCTP) {
+ strlcpy(string, "sctp", size);
+ if (field == NH_FLD_SCTP_PORT_SRC)
+ strlcat(string, ".src", size);
+ else if (field == NH_FLD_SCTP_PORT_DST)
+ strlcat(string, ".dst", size);
+ else
+ strlcat(string, ".unknown field", size);
+ } else if (prot == NET_PROT_GRE) {
+ strlcpy(string, "gre", size);
+ if (field == NH_FLD_GRE_TYPE)
+ strlcat(string, ".type", size);
+ else
+ strlcat(string, ".unknown field", size);
+ } else if (prot == NET_PROT_GTP) {
+ strlcpy(string, "gtp", size);
+ if (field == NH_FLD_GTP_TEID)
+ strlcat(string, ".teid", size);
+ else
+ strlcat(string, ".unknown field", size);
+ } else if (prot == NET_PROT_IPSEC_ESP) {
+ strlcpy(string, "esp", size);
+ if (field == NH_FLD_IPSEC_ESP_SPI)
+ strlcat(string, ".spi", size);
+ else if (field == NH_FLD_IPSEC_ESP_SEQUENCE_NUM)
+ strlcat(string, ".seq", size);
+ else
+ strlcat(string, ".unknown field", size);
+ } else {
+ snprintf(string, size, "unknown protocol(%d)", prot);
+ }
+}
+
+static inline void
+dpaa2_dump_dpkg(const struct dpkg_profile_cfg *dpkg)
+{
+ int idx;
+ char string[32];
+ const struct dpkg_extract *extract;
+ enum dpkg_extract_type type;
+ enum net_prot prot;
+ uint32_t field;
+
+ for (idx = 0; idx < dpkg->num_extracts; idx++) {
+ extract = &dpkg->extracts[idx];
+ type = extract->type;
+ if (type == DPKG_EXTRACT_FROM_HDR) {
+ prot = extract->extract.from_hdr.prot;
+ field = extract->extract.from_hdr.field;
+ dpaa2_prot_field_string(prot, field, string, sizeof(string));
+ } else if (type == DPKG_EXTRACT_FROM_DATA) {
+ snprintf(string, sizeof(string), "raw offset/len: %d/%d",
+ extract->extract.from_data.offset,
+ extract->extract.from_data.size);
+ } else if (type == DPKG_EXTRACT_FROM_PARSE) {
+ snprintf(string, sizeof(string), "parse offset/len: %d/%d",
+ extract->extract.from_parse.offset,
+ extract->extract.from_parse.size);
+ }
+ DPAA2_FLOW_DUMP("%s", string);
+ if ((idx + 1) < dpkg->num_extracts)
+ DPAA2_FLOW_DUMP(" / ");
+ else
+ DPAA2_FLOW_DUMP("\r\n\n");
+ }
+}
+
+static inline int
+dpaa2_extract_prev_ip_addr_pos(const struct dpaa2_key_profile *profile)
+{
+ int idx = -ENXIO;
+
+ if (!profile->num)
+ return -ENXIO;
+
+ for (idx = profile->num - 1; idx >= 0; idx--) {
+ if (!(profile->prot_field[idx].type == DPAA2_NET_PROT_KEY &&
+ profile->prot_field[idx].prot == NET_PROT_IP &&
+ (profile->prot_field[idx].key_field == NH_FLD_IP_SRC ||
+ profile->prot_field[idx].key_field == NH_FLD_IP_DST)))
+ break;
+ }
+
+ if (idx >= 0)
+ return idx;
+ return -ENXIO;
+}
+
+static inline int
+dpaa2_extract_ip_addr_add(uint32_t field,
+ struct dpaa2_key_profile *key_profile, uint8_t size,
+ int *update, int *pos)
+{
+ struct dpaa2_ip_addr_extract *ip_addr_extracts;
+ uint8_t i = 0;
+ uint16_t max_size_save = key_profile->key_max_size;
+ char log_buf[128];
+
+ if (field != NH_FLD_IP_SRC && field != NH_FLD_IP_DST)
+ return -EINVAL;
+
+ max_size_save -= key_profile->ip_addr_extracts[0].max_size;
+ max_size_save -= key_profile->ip_addr_extracts[1].max_size;
+ ip_addr_extracts = key_profile->ip_addr_extracts;
+ while (i < 2) {
+ if (ip_addr_extracts[i].field == field) {
+ if (size > ip_addr_extracts[i].max_size)
+ ip_addr_extracts[i].max_size = size;
+ break;
+ }
+ if (!ip_addr_extracts[i].field) {
+ ip_addr_extracts[i].field = field;
+ ip_addr_extracts[i].max_size = size;
+ if (update)
+ *update = 1;
+ break;
+ }
+ i++;
+ }
+ if (i > 1) {
+ snprintf(log_buf, sizeof(log_buf),
+ "field[0](%d)/size[0](%d)/field[1](%d)/size[1](%d)",
+ ip_addr_extracts[0].field,
+ ip_addr_extracts[0].max_size,
+ ip_addr_extracts[1].field,
+ ip_addr_extracts[1].max_size);
+ DPAA2_FLOW_DUMP("Invalid IP address extracts:%s\n",
+ log_buf);
+ return -EINVAL;
+ }
+
+ if (pos)
+ *pos = i;
+
+ max_size_save += key_profile->ip_addr_extracts[0].max_size;
+ max_size_save += key_profile->ip_addr_extracts[1].max_size;
+ key_profile->key_max_size = max_size_save;
+
+ return 0;
+}
+
+static inline uint8_t
+dpaa2_profile_insert_no_ipaddr_extract(struct dpaa2_key_profile *profile,
+ uint8_t size, uint8_t *poffset, int *ppos,
+ const struct key_prot_field *prot)
+{
+ uint8_t idx, ip_addr_num = 0, offset;
+
+ if (profile->ip_addr_extracts[0].field &&
+ profile->ip_addr_extracts[1].field) {
+ idx = profile->num - 2;
+ ip_addr_num = 2;
+ } else if (profile->ip_addr_extracts[0].field) {
+ idx = profile->num - 1;
+ ip_addr_num = 1;
+ } else {
+ idx = profile->num;
+ }
-int dpaa2_setup_flow_dist(struct rte_eth_dev *eth_dev,
- uint64_t req_dist_set, int tc_index);
+ if (idx > 0)
+ offset = profile->key_offset[idx - 1] + profile->key_size[idx - 1];
+ else
+ offset = 0;
-int dpaa2_setup_flow_dist_size(struct rte_eth_dev *eth_dev,
- uint64_t req_dist_set, int tc_index, uint16_t dist_size);
+ if (idx > 0) {
+ profile->key_offset[idx] =
+ profile->key_offset[idx - 1] + profile->key_size[idx - 1];
+ } else {
+ profile->key_offset[idx] = 0;
+ }
+ if (ppos)
+ *ppos = profile->key_offset[idx];
+ profile->key_size[idx] = size;
+ profile->key_max_size += size;
+ profile->num++;
+
+ if (ip_addr_num > 0) {
+ memmove(&profile->prot_field[idx + 1],
+ &profile->prot_field[idx],
+ sizeof(struct key_prot_field) * ip_addr_num);
+ }
+ if (poffset)
+ *poffset = offset;
-int dpaa2_remove_flow_dist(struct rte_eth_dev *eth_dev,
- uint8_t tc_index);
+ if (prot) {
+ rte_memcpy(&profile->prot_field[idx], prot,
+ sizeof(struct key_prot_field));
+ }
-int dpaa2_attach_bp_list(struct dpaa2_dev_priv *priv,
- struct fsl_mc_io *dpni, void *blist);
+ return idx;
+}
+
+static inline void
+dpaa2_dpkg_insert_extract(struct dpkg_profile_cfg *kg_cfg,
+ int idx, const struct dpkg_extract *extract)
+{
+ int i;
+ if (idx != kg_cfg->num_extracts) {
+ /* Not the last extract index, must have IP address extract.*/
+ for (i = kg_cfg->num_extracts - 1; i >= idx; i--) {
+ rte_memcpy(&kg_cfg->extracts[i + 1],
+ &kg_cfg->extracts[i], sizeof(struct dpkg_extract));
+ }
+ }
+
+ rte_memcpy(&kg_cfg->extracts[idx], extract, sizeof(struct dpkg_extract));
+ kg_cfg->num_extracts++;
+}
__rte_internal
int dpaa2_eth_eventq_attach(const struct rte_eth_dev *dev,
int eth_rx_queue_id,
@@ -678,7 +842,7 @@ uint16_t dpaa2_dev_tx_multi_txq_ordered(void **queue,
struct rte_mbuf **bufs, uint16_t nb_pkts);
void dpaa2_dev_free_eqresp_buf(uint16_t eqresp_ci, struct dpaa2_queue *dpaa2_q);
-void dpaa2_flow_clean(struct rte_eth_dev *dev);
+void dpaa2_flow_clean(struct rte_eth_dev *dev, uint8_t tc_id);
uint16_t dpaa2_dev_tx_conf(void *txq, int drain);
void
diff --git a/drivers/net/dpaa2/dpaa2_flow.c b/drivers/net/dpaa2/dpaa2_flow.c
index c616857e98..8456b3b80d 100644
--- a/drivers/net/dpaa2/dpaa2_flow.c
+++ b/drivers/net/dpaa2/dpaa2_flow.c
@@ -1,5 +1,5 @@
/* SPDX-License-Identifier: BSD-3-Clause
- * Copyright 2018-2022 NXP
+ * Copyright 2018-2026 NXP
*/
#include <sys/queue.h>
@@ -16,6 +16,7 @@
#include <rte_flow_driver.h>
#include <rte_tailq.h>
+#include <eal_export.h>
#include <fsl_dpni.h>
#include <fsl_dpkg.h>
@@ -23,7 +24,28 @@
#include <dpaa2_pmd_logs.h>
#include "dpaa2_parser_decode.h"
-static char *dpaa2_flow_control_log;
+#ifndef RTE_DPAA2_ONE_LEVEL_GROUP_FLOW
+#define RTE_DPAA2_ONE_LEVEL_GROUP_FLOW 0
+#endif
+#ifndef RTE_DPAA2_QOS_GROUP_FLOW
+#define RTE_DPAA2_QOS_GROUP_FLOW 1
+#endif
+#ifndef RTE_DPAA2_FS_GROUP_FLOW
+#define RTE_DPAA2_FS_GROUP_FLOW 2
+#endif
+
+#ifndef RTE_DPAA2_FLOW_GROUP_TYPE_GET
+#define RTE_DPAA2_FLOW_GROUP_TYPE_GET(group) \
+ ((void)(group), RTE_DPAA2_ONE_LEVEL_GROUP_FLOW)
+#endif
+
+#ifndef RTE_DPAA2_FLOW_GROUP_ID_GET
+#define RTE_DPAA2_FLOW_GROUP_ID_GET(group) (group)
+#endif
+
+static bool dpaa2_flow_control_log;
+
+#define DPAA2_FLOW_QOS_GROUP_ID 0xff
/* Default size of a key */
#define DPNI_DEFAULT_KEY_SIZE 24
@@ -34,31 +56,61 @@ enum dpaa2_flow_entry_size {
};
enum dpaa2_flow_dist_type {
- DPAA2_FLOW_QOS_TYPE = 1 << 0,
- DPAA2_FLOW_FS_TYPE = 1 << 1
+ DPAA2_FLOW_NULL_TYPE,
+ DPAA2_FLOW_QOS_TYPE,
+ DPAA2_FLOW_FS_TYPE
};
#define DPAA2_FLOW_RAW_OFFSET_FIELD_SHIFT 16
#define DPAA2_FLOW_MAX_KEY_SIZE 16
-#define DPAA2_PROT_FIELD_STRING_SIZE 16
+
#define VXLAN_HF_VNI 0x08
+#define DPAA2_MAX_ACTION_PER_FLOW_NUM 4
-struct dpaa2_dev_flow {
- LIST_ENTRY(dpaa2_dev_flow) next;
- struct dpni_rule_cfg qos_rule;
- uint8_t *qos_key_addr;
- uint8_t *qos_mask_addr;
- uint16_t qos_rule_size;
- struct dpni_rule_cfg fs_rule;
- uint8_t qos_real_key_size;
- uint8_t fs_real_key_size;
- uint8_t *fs_key_addr;
- uint8_t *fs_mask_addr;
- uint16_t fs_rule_size;
- uint8_t tc_id; /** Traffic Class ID. */
- uint8_t tc_index; /** index within this Traffic Class. */
+struct dpaa2_dev_flow_qos_action {
+ enum rte_flow_action_type action_jump_type;
+ struct rte_flow_action_jump action_jump_cfg;
+};
+
+struct dpaa2_dev_flow_fs_action {
enum rte_flow_action_type action_type;
struct dpni_fs_action_cfg fs_action_cfg;
+ char dst_name[DPNI_FS_REDIR_MAX_NUM][RTE_ETH_NAME_MAX_LEN];
+};
+
+union dpaa2_dev_flow_action {
+ struct dpaa2_dev_flow_qos_action qos_action;
+ struct dpaa2_dev_flow_fs_action fs_action;
+};
+
+struct dpaa2_generic_flow {
+ struct dpni_rule_cfg rule_cfg;
+ uint8_t *key_addr;
+ uint8_t *mask_addr;
+ uint16_t rule_size;
+ uint16_t entry_index;
+ /** This flow has IPv4 or IPv6 extracts.*/
+ enum net_prot ip_key;
+ /** This flow has IPv4 or IPv6 source extract.*/
+ enum net_prot ip_src;
+ /** This flow has IPv4 or IPv6 destination extract.*/
+ enum net_prot ip_dst;
+ struct dpaa2_dev_priv *priv;
+ union {
+ uint8_t tc_id; /** For FS flow only.*/
+ uint8_t flow_id; /** For QoS flow with direct_queue.*/
+ };
+ union dpaa2_dev_flow_action flow_action;
+ int is_rss;
+ int direct_queue;
+};
+
+struct dpaa2_dev_flow {
+ LIST_ENTRY(dpaa2_dev_flow) next;
+ struct dpaa2_generic_flow *qos_flow;
+ struct dpaa2_generic_flow *fs_flow;
+ struct dpaa2_dev_priv *priv;
+ int is_meter_flow;
};
struct rte_dpaa2_flow_item {
@@ -81,20 +133,18 @@ enum rte_flow_item_type dpaa2_hp_supported_pattern_type[] = {
RTE_FLOW_ITEM_TYPE_GTP,
RTE_FLOW_ITEM_TYPE_ESP,
RTE_FLOW_ITEM_TYPE_AH,
- RTE_FLOW_ITEM_TYPE_MPLS,
- RTE_FLOW_ITEM_TYPE_PPPOES,
- RTE_FLOW_ITEM_TYPE_RAW
+ RTE_FLOW_ITEM_TYPE_RAW,
+ /** Hardware parser supports vlan protocol only.*/
+ RTE_FLOW_ITEM_TYPE_VXLAN
};
static const
enum rte_flow_item_type dpaa2_sp_supported_pattern_type[] = {
- RTE_FLOW_ITEM_TYPE_VXLAN,
- RTE_FLOW_ITEM_TYPE_ECPRI
+ RTE_FLOW_ITEM_TYPE_ECPRI,
+ RTE_FLOW_ITEM_TYPE_GENEVE
};
-static const
-enum rte_flow_action_type dpaa2_supported_action_type[] = {
- RTE_FLOW_ACTION_TYPE_END,
+static const enum rte_flow_action_type dpaa2_supported_fs_action_type[] = {
RTE_FLOW_ACTION_TYPE_QUEUE,
RTE_FLOW_ACTION_TYPE_PORT_ID,
RTE_FLOW_ACTION_TYPE_REPRESENTED_PORT,
@@ -102,27 +152,63 @@ enum rte_flow_action_type dpaa2_supported_action_type[] = {
RTE_FLOW_ACTION_TYPE_DROP
};
+static const enum rte_flow_action_type dpaa2_supported_qos_action_type[] = {
+ RTE_FLOW_ACTION_TYPE_QUEUE,
+ RTE_FLOW_ACTION_TYPE_JUMP,
+ RTE_FLOW_ACTION_TYPE_DROP
+};
+
+static const enum rte_flow_action_type dpaa2_supported_meter_action_type[] = {
+ RTE_FLOW_ACTION_TYPE_METER_MARK,
+ RTE_FLOW_ACTION_TYPE_METER
+};
+
+#define DPAA2_FLOW_HDR_HEX_DUMP_SIZE \
+ (RTE_MAX(sizeof(struct rte_flow_item_eth), \
+ RTE_MAX(sizeof(struct rte_flow_item_vlan), \
+ RTE_MAX(sizeof(struct rte_flow_item_ipv4), \
+ RTE_MAX(sizeof(struct rte_flow_item_ipv6), \
+ RTE_MAX(sizeof(struct rte_flow_item_icmp), \
+ RTE_MAX(sizeof(struct rte_flow_item_udp), \
+ RTE_MAX(sizeof(struct rte_flow_item_tcp), \
+ RTE_MAX(sizeof(struct rte_flow_item_sctp), \
+ RTE_MAX(sizeof(struct rte_flow_item_gre), \
+ RTE_MAX(sizeof(struct rte_flow_item_ah), \
+ RTE_MAX(sizeof(struct rte_flow_item_esp), \
+ RTE_MAX(sizeof(struct rte_flow_item_vxlan), \
+ RTE_MAX(sizeof(struct rte_flow_item_ecpri), \
+ sizeof(struct rte_flow_item_gtp)))))))))))))) * 10)
+
+
#ifndef __cplusplus
static const struct rte_flow_item_eth dpaa2_flow_item_eth_mask = {
- .hdr.dst_addr.addr_bytes = { 0xff, 0xff, 0xff, 0xff, 0xff, 0xff },
- .hdr.src_addr.addr_bytes = { 0xff, 0xff, 0xff, 0xff, 0xff, 0xff },
- .hdr.ether_type = RTE_BE16(0xffff),
+ .dst.addr_bytes = "\xff\xff\xff\xff\xff\xff",
+ .src.addr_bytes = "\xff\xff\xff\xff\xff\xff",
+ .type = RTE_BE16(0xffff),
};
static const struct rte_flow_item_vlan dpaa2_flow_item_vlan_mask = {
- .hdr.vlan_tci = RTE_BE16(0xffff),
+ .tci = RTE_BE16(0xffff),
};
static const struct rte_flow_item_ipv4 dpaa2_flow_item_ipv4_mask = {
.hdr.src_addr = RTE_BE32(0xffffffff),
.hdr.dst_addr = RTE_BE32(0xffffffff),
.hdr.next_proto_id = 0xff,
+ .hdr.packet_id = 0xffff,
+ .hdr.fragment_offset = 0xffff,
};
static const struct rte_flow_item_ipv6 dpaa2_flow_item_ipv6_mask = {
.hdr = {
- .src_addr = RTE_IPV6_MASK_FULL,
- .dst_addr = RTE_IPV6_MASK_FULL,
+ .src_addr = {
+ "\xff\xff\xff\xff\xff\xff\xff\xff"
+ "\xff\xff\xff\xff\xff\xff\xff\xff"
+ },
+ .dst_addr = {
+ "\xff\xff\xff\xff\xff\xff\xff\xff"
+ "\xff\xff\xff\xff\xff\xff\xff\xff"
+ },
.proto = 0xff
},
};
@@ -170,7 +256,12 @@ static const struct rte_flow_item_gre dpaa2_flow_item_gre_mask = {
static const struct rte_flow_item_vxlan dpaa2_flow_item_vxlan_mask = {
.flags = 0xff,
- .vni = { 0xff, 0xff, 0xff },
+ .vni = "\xff\xff\xff",
+};
+
+static const struct rte_flow_item_geneve dpaa2_flow_item_geneve_mask = {
+ .protocol = RTE_BE16(0xffff),
+ .vni = "\xff\xff\xff",
};
static const struct rte_flow_item_ecpri dpaa2_flow_item_ecpri_mask = {
@@ -184,253 +275,182 @@ static const struct rte_flow_item_gtp dpaa2_flow_item_gtp_mask = {
.teid = RTE_BE32(0xffffffff),
};
-static const struct rte_flow_item_mpls dpaa2_flow_item_mpls_mask = {
- .label_tc_s = { 0xff, 0xff, 0xff },
-};
-
-static const struct rte_flow_item_pppoe dpaa2_flow_item_pppoe_mask = {
- .session_id = RTE_BE16(0xffff),
-};
-
#endif
+static inline uint8_t
+dpaa2_flow_entry_map_get(const uint8_t *entry_map,
+ uint16_t index)
+{
+ uint16_t byte_pos = index / 8;
+ uint16_t bit_pos = index % 8;
-#define DPAA2_FLOW_DUMP printf
+ return entry_map[byte_pos] & (1 << bit_pos);
+}
static inline void
-dpaa2_prot_field_string(uint32_t prot, uint32_t field,
- char *string)
+dpaa2_flow_entry_map_set(uint8_t *entry_map,
+ uint16_t index, int set)
{
- if (!dpaa2_flow_control_log)
- return;
+ uint16_t byte_pos = index / 8;
+ uint16_t bit_pos = index % 8;
- if (prot == NET_PROT_ETH) {
- strcpy(string, "eth");
- if (field == NH_FLD_ETH_DA)
- strcat(string, ".dst");
- else if (field == NH_FLD_ETH_SA)
- strcat(string, ".src");
- else if (field == NH_FLD_ETH_TYPE)
- strcat(string, ".type");
- else
- strcat(string, ".unknown field");
- } else if (prot == NET_PROT_VLAN) {
- strcpy(string, "vlan");
- if (field == NH_FLD_VLAN_TCI)
- strcat(string, ".tci");
- else
- strcat(string, ".unknown field");
- } else if (prot == NET_PROT_IP) {
- strcpy(string, "ip");
- if (field == NH_FLD_IP_SRC)
- strcat(string, ".src");
- else if (field == NH_FLD_IP_DST)
- strcat(string, ".dst");
- else if (field == NH_FLD_IP_PROTO)
- strcat(string, ".proto");
- else
- strcat(string, ".unknown field");
- } else if (prot == NET_PROT_TCP) {
- strcpy(string, "tcp");
- if (field == NH_FLD_TCP_PORT_SRC)
- strcat(string, ".src");
- else if (field == NH_FLD_TCP_PORT_DST)
- strcat(string, ".dst");
- else
- strcat(string, ".unknown field");
- } else if (prot == NET_PROT_UDP) {
- strcpy(string, "udp");
- if (field == NH_FLD_UDP_PORT_SRC)
- strcat(string, ".src");
- else if (field == NH_FLD_UDP_PORT_DST)
- strcat(string, ".dst");
- else
- strcat(string, ".unknown field");
- } else if (prot == NET_PROT_ICMP) {
- strcpy(string, "icmp");
- if (field == NH_FLD_ICMP_TYPE)
- strcat(string, ".type");
- else if (field == NH_FLD_ICMP_CODE)
- strcat(string, ".code");
- else
- strcat(string, ".unknown field");
- } else if (prot == NET_PROT_SCTP) {
- strcpy(string, "sctp");
- if (field == NH_FLD_SCTP_PORT_SRC)
- strcat(string, ".src");
- else if (field == NH_FLD_SCTP_PORT_DST)
- strcat(string, ".dst");
- else
- strcat(string, ".unknown field");
- } else if (prot == NET_PROT_GRE) {
- strcpy(string, "gre");
- if (field == NH_FLD_GRE_TYPE)
- strcat(string, ".type");
- else
- strcat(string, ".unknown field");
- } else if (prot == NET_PROT_GTP) {
- rte_strscpy(string, "gtp", DPAA2_PROT_FIELD_STRING_SIZE);
- if (field == NH_FLD_GTP_TEID)
- strcat(string, ".teid");
- else
- strcat(string, ".unknown field");
- } else if (prot == NET_PROT_IPSEC_ESP) {
- rte_strscpy(string, "esp", DPAA2_PROT_FIELD_STRING_SIZE);
- if (field == NH_FLD_IPSEC_ESP_SPI)
- strcat(string, ".spi");
- else if (field == NH_FLD_IPSEC_ESP_SEQUENCE_NUM)
- strcat(string, ".seq");
- else
- strcat(string, ".unknown field");
- } else {
- sprintf(string, "unknown protocol(%d)", prot);
- }
+ if (set)
+ entry_map[byte_pos] |= (1 << bit_pos);
+ else
+ entry_map[byte_pos] &= ~(((uint8_t)1) << bit_pos);
}
static inline void
-dpaa2_flow_qos_extracts_log(const struct dpaa2_dev_priv *priv)
+dpaa2_flow_extracts_log(const struct dpaa2_dev_priv *priv,
+ const char *prefix, uint8_t tc_id)
{
- int idx;
- char string[32];
- const struct dpkg_profile_cfg *dpkg =
- &priv->extract.qos_key_extract.dpkg;
- const struct dpkg_extract *extract;
- enum dpkg_extract_type type;
- enum net_prot prot;
- uint32_t field;
+ char string[1024];
+ const struct dpaa2_flow_tbl_profile *tbl_profile;
+ int offset = 0;
if (!dpaa2_flow_control_log)
return;
- DPAA2_FLOW_DUMP("QoS table: %d extracts\r\n",
- dpkg->num_extracts);
- for (idx = 0; idx < dpkg->num_extracts; idx++) {
- extract = &dpkg->extracts[idx];
- type = extract->type;
- if (type == DPKG_EXTRACT_FROM_HDR) {
- prot = extract->extract.from_hdr.prot;
- field = extract->extract.from_hdr.field;
- dpaa2_prot_field_string(prot, field,
- string);
- } else if (type == DPKG_EXTRACT_FROM_DATA) {
- sprintf(string, "raw offset/len: %d/%d",
- extract->extract.from_data.offset,
- extract->extract.from_data.size);
- } else if (type == DPKG_EXTRACT_FROM_PARSE) {
- sprintf(string, "parse offset/len: %d/%d",
- extract->extract.from_parse.offset,
- extract->extract.from_parse.size);
- }
- DPAA2_FLOW_DUMP("%s", string);
- if ((idx + 1) < dpkg->num_extracts)
- DPAA2_FLOW_DUMP(" / ");
- }
- DPAA2_FLOW_DUMP("\r\n");
+ offset += sprintf(&string[offset],
+ "%s's", priv->eth_dev->data->name);
+ if (tc_id >= MAX_TCS) {
+ tbl_profile = &priv->flow_profile.qos_profile;
+ offset += sprintf(&string[offset], " QoS");
+ } else {
+ tbl_profile = &priv->flow_profile.tc_profile[tc_id];
+ offset += sprintf(&string[offset], " FS[%d]", tc_id);
+ }
+ offset += sprintf(&string[offset],
+ " table: %d extracts/%d entries\n",
+ tbl_profile->dpkg.num_extracts, tbl_profile->entry_num);
+ DPAA2_FLOW_DUMP("\n%s %s", prefix, string);
+ dpaa2_dump_dpkg(&tbl_profile->dpkg);
}
static inline void
-dpaa2_flow_fs_extracts_log(const struct dpaa2_dev_priv *priv,
- int tc_id)
+dpaa2_flow_qos_entry_log(const char *log_info,
+ const struct dpaa2_generic_flow *flow)
{
int idx;
- char string[32];
- const struct dpkg_profile_cfg *dpkg =
- &priv->extract.tc_key_extract[tc_id].dpkg;
- const struct dpkg_extract *extract;
- enum dpkg_extract_type type;
- enum net_prot prot;
- uint32_t field;
+ struct rte_eth_dev *dev = flow->priv->eth_dev;
if (!dpaa2_flow_control_log)
return;
- DPAA2_FLOW_DUMP("FS table: %d extracts in TC[%d]\r\n",
- dpkg->num_extracts, tc_id);
- for (idx = 0; idx < dpkg->num_extracts; idx++) {
- extract = &dpkg->extracts[idx];
- type = extract->type;
- if (type == DPKG_EXTRACT_FROM_HDR) {
- prot = extract->extract.from_hdr.prot;
- field = extract->extract.from_hdr.field;
- dpaa2_prot_field_string(prot, field,
- string);
- } else if (type == DPKG_EXTRACT_FROM_DATA) {
- sprintf(string, "raw offset/len: %d/%d",
- extract->extract.from_data.offset,
- extract->extract.from_data.size);
- } else if (type == DPKG_EXTRACT_FROM_PARSE) {
- sprintf(string, "parse offset/len: %d/%d",
- extract->extract.from_parse.offset,
- extract->extract.from_parse.size);
- }
- DPAA2_FLOW_DUMP("%s", string);
- if ((idx + 1) < dpkg->num_extracts)
- DPAA2_FLOW_DUMP(" / ");
- }
- DPAA2_FLOW_DUMP("\r\n");
+ DPAA2_FLOW_DUMP("%s: %s QoS entry[%d](size %d/%d) to select TC[%d]\n",
+ dev->data->name, log_info, flow->entry_index, flow->rule_size,
+ flow->rule_cfg.key_size,
+ flow->flow_action.qos_action.action_jump_cfg.group);
+
+ DPAA2_FLOW_DUMP("key:\r\n");
+ for (idx = 0; idx < flow->rule_size; idx++)
+ DPAA2_FLOW_DUMP("%02x ", flow->key_addr[idx]);
+
+ DPAA2_FLOW_DUMP("\r\nmask:\r\n");
+ for (idx = 0; idx < flow->rule_size; idx++)
+ DPAA2_FLOW_DUMP("%02x ", flow->mask_addr[idx]);
+ DPAA2_FLOW_DUMP("\r\n\n");
}
static inline void
-dpaa2_flow_qos_entry_log(const char *log_info,
- const struct dpaa2_dev_flow *flow, int qos_index)
+dpaa2_flow_fs_entry_log(const char *log_info,
+ const struct dpaa2_generic_flow *flow)
{
int idx;
- uint8_t *key, *mask;
+ struct rte_eth_dev *dev = flow->priv->eth_dev;
+ const struct dpaa2_dev_flow_fs_action *fs_action;
if (!dpaa2_flow_control_log)
return;
- if (qos_index >= 0) {
- DPAA2_FLOW_DUMP("%s QoS entry[%d](size %d/%d) for TC[%d]\r\n",
- log_info, qos_index, flow->qos_rule_size,
- flow->qos_rule.key_size,
- flow->tc_id);
- } else {
- DPAA2_FLOW_DUMP("%s QoS entry(size %d/%d) for TC[%d]\r\n",
- log_info, flow->qos_rule_size,
- flow->qos_rule.key_size,
- flow->tc_id);
- }
+ DPAA2_FLOW_DUMP("%s: %s FS[%d]/entry[%d](size %d/%d)\r\n",
+ dev->data->name, log_info, flow->tc_id,
+ flow->entry_index, flow->rule_size,
+ flow->rule_cfg.key_size);
- key = flow->qos_key_addr;
- mask = flow->qos_mask_addr;
+ fs_action = &flow->flow_action.fs_action;
DPAA2_FLOW_DUMP("key:\r\n");
- for (idx = 0; idx < flow->qos_rule_size; idx++)
- DPAA2_FLOW_DUMP("%02x ", key[idx]);
+ for (idx = 0; idx < flow->rule_size; idx++)
+ DPAA2_FLOW_DUMP("%02x ", flow->key_addr[idx]);
DPAA2_FLOW_DUMP("\r\nmask:\r\n");
- for (idx = 0; idx < flow->qos_rule_size; idx++)
- DPAA2_FLOW_DUMP("%02x ", mask[idx]);
- DPAA2_FLOW_DUMP("\r\n");
+ for (idx = 0; idx < flow->rule_size; idx++)
+ DPAA2_FLOW_DUMP("%02x ", flow->mask_addr[idx]);
+ DPAA2_FLOW_DUMP("\r\nAction: ");
+ if (fs_action->action_type == RTE_FLOW_ACTION_TYPE_QUEUE) {
+ DPAA2_FLOW_DUMP("Receive to flow%d\r\n\n",
+ fs_action->fs_action_cfg.flow_id);
+ } else if (fs_action->action_type == RTE_FLOW_ACTION_TYPE_PORT_ID ||
+ fs_action->action_type == RTE_FLOW_ACTION_TYPE_REPRESENTED_PORT) {
+ DPAA2_FLOW_DUMP("Re-direct to port(s): ");
+ for (idx = 0; idx < fs_action->fs_action_cfg.num_tokens; idx++) {
+ DPAA2_FLOW_DUMP("%s", fs_action->dst_name[idx]);
+ if ((idx + 1) < fs_action->fs_action_cfg.num_tokens)
+ DPAA2_FLOW_DUMP(", ");
+ }
+ DPAA2_FLOW_DUMP("\r\n");
+ } else if (fs_action->action_type == RTE_FLOW_ACTION_TYPE_DROP) {
+ DPAA2_FLOW_DUMP("Drop\r\n\n");
+ } else {
+ DPAA2_FLOW_DUMP("Un-supported action type(%d)\r\n\n",
+ fs_action->action_type);
+ }
}
static inline void
-dpaa2_flow_fs_entry_log(const char *log_info,
- const struct dpaa2_dev_flow *flow)
+dpaa2_dump_extract_map(const struct dpaa2_dev_priv *priv,
+ const char *prefix, enum dpaa2_flow_dist_type dist_type,
+ uint8_t group)
{
- int idx;
- uint8_t *key, *mask;
+ int idx, offset = 0;
+ char string[2048];
+ const struct dpaa2_flow_tbl_profile *tbl_profile;
if (!dpaa2_flow_control_log)
return;
- DPAA2_FLOW_DUMP("%s FS/TC entry[%d](size %d/%d) of TC[%d]\r\n",
- log_info, flow->tc_index,
- flow->fs_rule_size, flow->fs_rule.key_size,
- flow->tc_id);
+ DPAA2_FLOW_DUMP("%s: %s\n", priv->eth_dev->data->name, prefix);
- key = flow->fs_key_addr;
- mask = flow->fs_mask_addr;
+ if (dist_type == DPAA2_FLOW_QOS_TYPE) {
+ tbl_profile = &priv->flow_profile.qos_profile;
+ offset += sprintf(&string[offset], "QoS entry map:");
+ if (!tbl_profile->entry_num) {
+ offset += sprintf(&string[offset], " empty\n");
+ goto qos_dump_end;
+ } else {
+ offset += sprintf(&string[offset], "\n");
+ }
+ for (idx = 0; idx < priv->qos_entries; idx++) {
+ offset += sprintf(&string[offset], "%d ",
+ dpaa2_flow_entry_map_get(tbl_profile->entry_map, idx) ?
+ 1 : 0);
+ if (!((idx + 1) % 16) || (idx + 1) == priv->qos_entries)
+ offset += sprintf(&string[offset], "\n");
+ }
- DPAA2_FLOW_DUMP("key:\r\n");
- for (idx = 0; idx < flow->fs_rule_size; idx++)
- DPAA2_FLOW_DUMP("%02x ", key[idx]);
+qos_dump_end:
+ DPAA2_FLOW_DUMP("%s\n", string);
- DPAA2_FLOW_DUMP("\r\nmask:\r\n");
- for (idx = 0; idx < flow->fs_rule_size; idx++)
- DPAA2_FLOW_DUMP("%02x ", mask[idx]);
- DPAA2_FLOW_DUMP("\r\n");
+ return;
+ }
+
+ tbl_profile = &priv->flow_profile.tc_profile[group];
+ if (!tbl_profile->entry_num) {
+ DPAA2_FLOW_DUMP("FS[%d] table is empty\n\n", group);
+ return;
+ }
+
+ offset = sprintf(&string[offset],
+ "FS[%d] %d entries:\n", group, tbl_profile->entry_num);
+ for (idx = 0; idx < priv->fs_entries; idx++) {
+ offset += sprintf(&string[offset], "%d ",
+ dpaa2_flow_entry_map_get(tbl_profile->entry_map, idx) ?
+ 1 : 0);
+ if (!((idx + 1) % 16) || (idx + 1) == priv->fs_entries)
+ offset += sprintf(&string[offset], "\n");
+ }
+ DPAA2_FLOW_DUMP("%s\n", string);
}
static int
@@ -487,272 +507,481 @@ dpaa2_flow_l4_dst_port_extract(enum net_prot prot,
return false;
}
+static int
+dpaa2_flow_rss_conf_to_item(uint64_t req_dist_set,
+ struct rte_flow_item *items, uint8_t *spec_buf,
+ uint32_t buf_max)
+{
+ uint32_t i = 0, offset = 0;
+ uint64_t l2_mask, vlan_mask, ipv4_mask, ipv6_mask;
+ uint64_t dist_supported, udp_mask, tcp_mask, sctp_mask;
+ struct rte_flow_item_eth *eth = NULL;
+ struct rte_flow_item_pppoe *pppoe = NULL;
+ struct rte_flow_item_esp *esp = NULL;
+ struct rte_flow_item_ah *ah = NULL;
+ struct rte_flow_item_vlan *vlan = NULL;
+ struct rte_flow_item_mpls *mpls = NULL;
+ struct rte_flow_item_gtp *gtpu = NULL;
+ struct rte_flow_item_udp *udp = NULL;
+ struct rte_flow_item_tcp *tcp = NULL;
+ struct rte_flow_item_sctp *sctp = NULL;
+ struct rte_flow_item_ipv4 *ipv4 = NULL;
+
+ l2_mask = RTE_ETH_RSS_L2_PAYLOAD | RTE_ETH_RSS_ETH;
+ vlan_mask = RTE_ETH_RSS_C_VLAN | RTE_ETH_RSS_S_VLAN;
+ ipv4_mask = RTE_ETH_RSS_IPV4 | RTE_ETH_RSS_FRAG_IPV4 |
+ RTE_ETH_RSS_NONFRAG_IPV4_OTHER;
+ ipv6_mask = RTE_ETH_RSS_IPV6 | RTE_ETH_RSS_FRAG_IPV6 |
+ RTE_ETH_RSS_IPV6_EX | RTE_ETH_RSS_NONFRAG_IPV6_OTHER;
+ udp_mask = RTE_ETH_RSS_NONFRAG_IPV4_UDP |
+ RTE_ETH_RSS_NONFRAG_IPV6_UDP |
+ RTE_ETH_RSS_IPV6_UDP_EX;
+ tcp_mask = RTE_ETH_RSS_NONFRAG_IPV4_TCP |
+ RTE_ETH_RSS_NONFRAG_IPV6_TCP |
+ RTE_ETH_RSS_IPV6_TCP_EX;
+ sctp_mask = RTE_ETH_RSS_NONFRAG_IPV4_SCTP |
+ RTE_ETH_RSS_NONFRAG_IPV6_SCTP;
+ dist_supported = l2_mask | vlan_mask | ipv4_mask |
+ ipv6_mask | udp_mask | tcp_mask | sctp_mask |
+ RTE_ETH_RSS_GTPU | RTE_ETH_RSS_PPPOE |
+ RTE_ETH_RSS_ESP | RTE_ETH_RSS_AH | RTE_ETH_RSS_MPLS;
+ if (~dist_supported & req_dist_set) {
+ DPAA2_PMD_ERR("%s: Unsupported dist type:0x%" PRIx64,
+ __func__, (~dist_supported) & req_dist_set);
+ return -ENOTSUP;
+ }
+
+ if (req_dist_set & l2_mask) {
+ items[i].type = RTE_FLOW_ITEM_TYPE_ETH;
+ eth = (void *)(spec_buf + offset);
+ memset(eth, 0, sizeof(struct rte_flow_item_eth));
+ memset(eth->dst.addr_bytes, 0xff, RTE_ETHER_ADDR_LEN);
+ memset(eth->src.addr_bytes, 0xff, RTE_ETHER_ADDR_LEN);
+ eth->type = RTE_BE16(0xffff);
+ items[i].spec = eth;
+ items[i].mask = eth;
+ i++;
+ offset += sizeof(struct rte_flow_item_eth);
+ offset = RTE_CACHE_LINE_ROUNDUP(offset);
+ if (offset > buf_max)
+ return -ENOMEM;
+ }
+
+ if (req_dist_set & RTE_ETH_RSS_PPPOE) {
+ items[i].type = RTE_FLOW_ITEM_TYPE_PPPOES;
+ pppoe = (void *)(spec_buf + offset);
+ memset(pppoe, 0, sizeof(struct rte_flow_item_pppoe));
+ pppoe->session_id = RTE_BE16(0xffff);
+ items[i].spec = pppoe;
+ items[i].mask = pppoe;
+ i++;
+ offset += sizeof(struct rte_flow_item_pppoe);
+ offset = RTE_CACHE_LINE_ROUNDUP(offset);
+ if (offset > buf_max)
+ return -ENOMEM;
+ }
+
+ if (req_dist_set & RTE_ETH_RSS_ESP) {
+ items[i].type = RTE_FLOW_ITEM_TYPE_ESP;
+ esp = (void *)(spec_buf + offset);
+ memset(esp, 0, sizeof(struct rte_flow_item_esp));
+ esp->hdr.spi = RTE_BE32(0xffffffff);
+ items[i].spec = esp;
+ items[i].mask = esp;
+ i++;
+ offset += sizeof(struct rte_flow_item_esp);
+ offset = RTE_CACHE_LINE_ROUNDUP(offset);
+ if (offset > buf_max)
+ return -ENOMEM;
+ }
+
+ if (req_dist_set & RTE_ETH_RSS_AH) {
+ items[i].type = RTE_FLOW_ITEM_TYPE_AH;
+ ah = (void *)(spec_buf + offset);
+ memset(ah, 0, sizeof(struct rte_flow_item_ah));
+ ah->spi = RTE_BE32(0xffffffff);
+ items[i].spec = ah;
+ items[i].mask = ah;
+ i++;
+ offset += sizeof(struct rte_flow_item_ah);
+ offset = RTE_CACHE_LINE_ROUNDUP(offset);
+ if (offset > buf_max)
+ return -ENOMEM;
+ }
+
+ if (req_dist_set & vlan_mask) {
+ items[i].type = RTE_FLOW_ITEM_TYPE_VLAN;
+ vlan = (void *)(spec_buf + offset);
+ memset(vlan, 0, sizeof(struct rte_flow_item_vlan));
+ vlan->tci = RTE_BE16(0xffff);
+ items[i].spec = vlan;
+ items[i].mask = vlan;
+ i++;
+ offset += sizeof(struct rte_flow_item_vlan);
+ offset = RTE_CACHE_LINE_ROUNDUP(offset);
+ if (offset > buf_max)
+ return -ENOMEM;
+ }
+
+ if (req_dist_set & RTE_ETH_RSS_MPLS) {
+ items[i].type = RTE_FLOW_ITEM_TYPE_MPLS;
+ mpls = (void *)(spec_buf + offset);
+ memset(mpls, 0, sizeof(struct rte_flow_item_mpls));
+ memset(mpls->label_tc_s, 0xff, 3);
+ items[i].spec = mpls;
+ items[i].mask = mpls;
+ i++;
+ offset += sizeof(struct rte_flow_item_mpls);
+ offset = RTE_CACHE_LINE_ROUNDUP(offset);
+ if (offset > buf_max)
+ return -ENOMEM;
+ }
+
+ if (req_dist_set & RTE_ETH_RSS_GTPU) {
+ items[i].type = RTE_FLOW_ITEM_TYPE_GTPU;
+ gtpu = (void *)(spec_buf + offset);
+ memset(gtpu, 0, sizeof(struct rte_flow_item_gtp));
+ gtpu->teid = RTE_BE32(0xffffffff);
+ items[i].spec = gtpu;
+ items[i].mask = gtpu;
+ i++;
+ offset += sizeof(struct rte_flow_item_gtp);
+ offset = RTE_CACHE_LINE_ROUNDUP(offset);
+ if (offset > buf_max)
+ return -ENOMEM;
+ }
+
+ if (req_dist_set & udp_mask) {
+ items[i].type = RTE_FLOW_ITEM_TYPE_UDP;
+ udp = (void *)(spec_buf + offset);
+ memset(udp, 0, sizeof(struct rte_flow_item_udp));
+ udp->hdr.src_port = RTE_BE16(0xffff);
+ udp->hdr.dst_port = RTE_BE16(0xffff);
+ items[i].spec = udp;
+ items[i].mask = udp;
+ i++;
+ offset += sizeof(struct rte_flow_item_udp);
+ offset = RTE_CACHE_LINE_ROUNDUP(offset);
+ if (offset > buf_max)
+ return -ENOMEM;
+ }
+
+ if (req_dist_set & tcp_mask) {
+ items[i].type = RTE_FLOW_ITEM_TYPE_TCP;
+ tcp = (void *)(spec_buf + offset);
+ memset(tcp, 0, sizeof(struct rte_flow_item_tcp));
+ tcp->hdr.src_port = RTE_BE16(0xffff);
+ tcp->hdr.dst_port = RTE_BE16(0xffff);
+ items[i].spec = tcp;
+ items[i].mask = tcp;
+ i++;
+ offset += sizeof(struct rte_flow_item_tcp);
+ offset = RTE_CACHE_LINE_ROUNDUP(offset);
+ if (offset > buf_max)
+ return -ENOMEM;
+ }
+
+ if (req_dist_set & sctp_mask) {
+ items[i].type = RTE_FLOW_ITEM_TYPE_SCTP;
+ sctp = (void *)(spec_buf + offset);
+ memset(sctp, 0, sizeof(struct rte_flow_item_sctp));
+ sctp->hdr.src_port = RTE_BE16(0xffff);
+ sctp->hdr.dst_port = RTE_BE16(0xffff);
+ items[i].spec = sctp;
+ items[i].mask = sctp;
+ i++;
+ offset += sizeof(struct rte_flow_item_sctp);
+ offset = RTE_CACHE_LINE_ROUNDUP(offset);
+ if (offset > buf_max)
+ return -ENOMEM;
+ }
+
+ if (req_dist_set & ipv4_mask) {
+ items[i].type = RTE_FLOW_ITEM_TYPE_IPV4;
+ ipv4 = (void *)(spec_buf + offset);
+ memset(ipv4, 0, sizeof(struct rte_flow_item_ipv4));
+ ipv4->hdr.src_addr = RTE_BE32(0xffffffff);
+ ipv4->hdr.dst_addr = RTE_BE32(0xffffffff);
+ ipv4->hdr.next_proto_id = 0xff;
+ items[i].spec = ipv4;
+ items[i].mask = ipv4;
+ i++;
+ offset += sizeof(struct rte_flow_item_ipv4);
+ offset = RTE_CACHE_LINE_ROUNDUP(offset);
+ if (offset > buf_max)
+ return -ENOMEM;
+ }
+
+ items[i].type = RTE_FLOW_ITEM_TYPE_END;
+
+ return i;
+}
+
static int
dpaa2_flow_add_qos_rule(struct dpaa2_dev_priv *priv,
- struct dpaa2_dev_flow *flow)
+ struct dpaa2_generic_flow *flow)
{
- uint16_t qos_index;
+ struct dpaa2_flow_tbl_profile *tbl_profile;
int ret;
struct fsl_mc_io *dpni = priv->hw;
+ uint8_t flags = DPNI_QOS_OPT_SET_TC_ONLY, flow_id = 0;
- if (priv->num_rx_tc <= 1 &&
- flow->action_type != RTE_FLOW_ACTION_TYPE_RSS) {
- DPAA2_PMD_WARN("No QoS Table for FS");
+ if (flow->entry_index >= priv->qos_entries) {
+ DPAA2_PMD_ERR("QoS table full(%d >= %d)",
+ flow->entry_index, priv->qos_entries);
+ return -EINVAL;
+ }
+ tbl_profile = &priv->flow_profile.qos_profile;
+ if (dpaa2_flow_entry_map_get(tbl_profile->entry_map,
+ flow->entry_index)) {
+ DPAA2_PMD_ERR("QoS entry[%d] has been occupied",
+ flow->entry_index);
return -EINVAL;
}
- /* QoS entry added is only effective for multiple TCs.*/
- qos_index = flow->tc_id * priv->fs_entries + flow->tc_index;
- if (qos_index >= priv->qos_entries) {
- DPAA2_PMD_ERR("QoS table full(%d >= %d)",
- qos_index, priv->qos_entries);
+ if (flow->flow_action.qos_action.action_jump_type !=
+ RTE_FLOW_ACTION_TYPE_JUMP) {
+ DPAA2_PMD_ERR("QoS entry[%d]'jump action not set(%d)",
+ flow->entry_index,
+ flow->flow_action.qos_action.action_jump_type);
+ return -EINVAL;
+ }
+ if (flow->flow_action.qos_action.action_jump_cfg.group >=
+ priv->num_rx_tc) {
+ DPAA2_PMD_ERR("QoS entry[%d]'dest table ID(%d) >= max(%d)",
+ flow->entry_index,
+ flow->flow_action.qos_action.action_jump_cfg.group,
+ priv->num_rx_tc);
return -EINVAL;
}
- dpaa2_flow_qos_entry_log("Start add", flow, qos_index);
+ dpaa2_flow_qos_entry_log("Add", flow);
+ if (flow->direct_queue) {
+ flags |= DPNI_QOS_OPT_SET_FLOW_ID;
+ flow_id = flow->flow_id;
+ }
ret = dpni_add_qos_entry(dpni, CMD_PRI_LOW,
- priv->token, &flow->qos_rule,
- flow->tc_id, qos_index,
- 0, 0);
+ priv->token, &flow->rule_cfg,
+ flow->flow_action.qos_action.action_jump_cfg.group,
+ flow->entry_index, flags, flow_id);
if (ret < 0) {
DPAA2_PMD_ERR("Add entry(%d) to table(%d) failed",
- qos_index, flow->tc_id);
+ flow->entry_index,
+ flow->flow_action.qos_action.action_jump_cfg.group);
return ret;
}
+ dpaa2_flow_entry_map_set(tbl_profile->entry_map, flow->entry_index, 1);
+ tbl_profile->entry_num++;
return 0;
}
static int
dpaa2_flow_add_fs_rule(struct dpaa2_dev_priv *priv,
- struct dpaa2_dev_flow *flow)
+ struct dpaa2_generic_flow *flow)
{
+ struct rte_dpaa2_device *dpaa2_dev;
+ struct dpaa2_flow_tbl_profile *tbl_profile;
int ret;
struct fsl_mc_io *dpni = priv->hw;
- if (flow->tc_index >= priv->fs_entries) {
- DPAA2_PMD_ERR("FS table full(%d >= %d)",
- flow->tc_index, priv->fs_entries);
+ dpaa2_dev = DPAA2_DEV_PRIV_TO_DPAA2_DEV(priv);
+
+ tbl_profile = &priv->flow_profile.tc_profile[flow->tc_id];
+ if (dpaa2_flow_entry_map_get(tbl_profile->entry_map,
+ flow->entry_index)) {
+ DPAA2_PMD_ERR("FS[%d].entry[%d] has been occupied",
+ flow->tc_id, flow->entry_index);
return -EINVAL;
}
- dpaa2_flow_fs_entry_log("Start add", flow);
+ dpaa2_flow_fs_entry_log("Add", flow);
- ret = dpni_add_fs_entry(dpni, CMD_PRI_LOW,
- priv->token, flow->tc_id,
- flow->tc_index, &flow->fs_rule,
- &flow->fs_action_cfg);
+ if (dpaa2_dev->bus_info->mc_rev >= DPAA2_FLOW_FRM_REPLICATION_ACTION_MC_REV) {
+ ret = dpni_add_fs_entry(dpni, CMD_PRI_LOW,
+ priv->token, flow->tc_id, flow->entry_index,
+ &flow->rule_cfg, &flow->flow_action.fs_action.fs_action_cfg);
+ } else {
+ ret = dpni_add_fs_entry_legacy(dpni, CMD_PRI_LOW,
+ priv->token, flow->tc_id, flow->entry_index,
+ &flow->rule_cfg, &flow->flow_action.fs_action.fs_action_cfg);
+ }
if (ret < 0) {
DPAA2_PMD_ERR("Add rule(%d) to FS table(%d) failed",
- flow->tc_index, flow->tc_id);
+ flow->entry_index, flow->tc_id);
return ret;
}
+ dpaa2_flow_entry_map_set(tbl_profile->entry_map, flow->entry_index, 1);
+ tbl_profile->entry_num++;
+
return 0;
}
static int
-dpaa2_flow_rule_insert_hole(struct dpaa2_dev_flow *flow,
- int offset, int size,
- enum dpaa2_flow_dist_type dist_type)
+dpaa2_flow_update_qos_rule_action(struct dpaa2_dev_priv *priv,
+ struct dpaa2_generic_flow *flow)
{
- if (dist_type & DPAA2_FLOW_QOS_TYPE) {
- if (offset < flow->qos_rule_size) {
- memmove(flow->qos_key_addr + offset + size,
- flow->qos_key_addr + offset,
- flow->qos_rule_size - offset);
- memset(flow->qos_key_addr + offset,
- 0, size);
-
- memmove(flow->qos_mask_addr + offset + size,
- flow->qos_mask_addr + offset,
- flow->qos_rule_size - offset);
- memset(flow->qos_mask_addr + offset,
- 0, size);
- flow->qos_rule_size += size;
- } else {
- flow->qos_rule_size = offset + size;
- }
+ int ret;
+ struct fsl_mc_io *dpni = priv->hw;
+ uint8_t flags = DPNI_QOS_OPT_UPDATE_IF_EXISTS, flow_id = 0;
+
+ dpaa2_flow_qos_entry_log("Update action", flow);
+
+ if (flow->direct_queue) {
+ flags |= DPNI_QOS_OPT_SET_FLOW_ID;
+ flow_id = flow->flow_id;
}
- if (dist_type & DPAA2_FLOW_FS_TYPE) {
- if (offset < flow->fs_rule_size) {
- memmove(flow->fs_key_addr + offset + size,
- flow->fs_key_addr + offset,
- flow->fs_rule_size - offset);
- memset(flow->fs_key_addr + offset,
- 0, size);
-
- memmove(flow->fs_mask_addr + offset + size,
- flow->fs_mask_addr + offset,
- flow->fs_rule_size - offset);
- memset(flow->fs_mask_addr + offset,
- 0, size);
- flow->fs_rule_size += size;
- } else {
- flow->fs_rule_size = offset + size;
- }
+ /** This option doesn't support legacy operation.*/
+ ret = dpni_add_qos_entry(dpni, CMD_PRI_LOW,
+ priv->token, &flow->rule_cfg,
+ flow->flow_action.qos_action.action_jump_cfg.group,
+ flow->entry_index,
+ flags, flow_id);
+ if (ret < 0) {
+ DPAA2_PMD_ERR("Update rule(%d) in QOS table failed(%d)",
+ flow->entry_index, ret);
+ return ret;
}
return 0;
}
static int
-dpaa2_flow_rule_add_all(struct dpaa2_dev_priv *priv,
- enum dpaa2_flow_dist_type dist_type,
- uint16_t entry_size, uint8_t tc_id)
+dpaa2_flow_update_fs_rule_action(struct dpaa2_dev_priv *priv,
+ struct dpaa2_generic_flow *flow)
{
- struct dpaa2_dev_flow *curr = LIST_FIRST(&priv->flows);
int ret;
+ struct fsl_mc_io *dpni = priv->hw;
+ struct dpni_fs_action_cfg *cfg;
- while (curr) {
- if (dist_type & DPAA2_FLOW_QOS_TYPE) {
- if (priv->num_rx_tc > 1 ||
- curr->action_type ==
- RTE_FLOW_ACTION_TYPE_RSS) {
- curr->qos_rule.key_size = entry_size;
- ret = dpaa2_flow_add_qos_rule(priv, curr);
- if (ret)
- return ret;
- }
- }
- if (dist_type & DPAA2_FLOW_FS_TYPE &&
- curr->tc_id == tc_id) {
- curr->fs_rule.key_size = entry_size;
- ret = dpaa2_flow_add_fs_rule(priv, curr);
- if (ret)
- return ret;
- }
- curr = LIST_NEXT(curr, next);
+ dpaa2_flow_fs_entry_log("Update action", flow);
+
+ cfg = &flow->flow_action.fs_action.fs_action_cfg;
+ cfg->options |= DPNI_FS_OPT_UPDATE_IF_EXISTS;
+ /** This option doesn't support legacy operation.*/
+ ret = dpni_add_fs_entry(dpni, CMD_PRI_LOW,
+ priv->token, flow->tc_id, flow->entry_index,
+ &flow->rule_cfg, cfg);
+ if (ret < 0) {
+ DPAA2_PMD_ERR("Update rule(%d) in FS table(%d) failed",
+ flow->entry_index, flow->tc_id);
+ return ret;
}
return 0;
}
static int
-dpaa2_flow_qos_rule_insert_hole(struct dpaa2_dev_priv *priv,
+_dpaa2_flow_rule_insert_hole(struct dpaa2_generic_flow *flow,
int offset, int size)
{
- struct dpaa2_dev_flow *curr;
- int ret;
-
- curr = priv->curr;
- if (!curr) {
- DPAA2_PMD_ERR("Current qos flow insert hole failed.");
- return -EINVAL;
+ if (offset < flow->rule_size) {
+ memmove(flow->key_addr + offset + size,
+ flow->key_addr + offset,
+ flow->rule_size - offset);
+ memset(flow->key_addr + offset, 0, size);
+
+ memmove(flow->mask_addr + offset + size,
+ flow->mask_addr + offset,
+ flow->rule_size - offset);
+ memset(flow->mask_addr + offset, 0, size);
+ flow->rule_size += size;
} else {
- ret = dpaa2_flow_rule_insert_hole(curr, offset, size,
- DPAA2_FLOW_QOS_TYPE);
- if (ret)
- return ret;
- }
-
- curr = LIST_FIRST(&priv->flows);
- while (curr) {
- ret = dpaa2_flow_rule_insert_hole(curr, offset, size,
- DPAA2_FLOW_QOS_TYPE);
- if (ret)
- return ret;
- curr = LIST_NEXT(curr, next);
+ flow->rule_size = offset + size;
}
return 0;
}
static int
-dpaa2_flow_fs_rule_insert_hole(struct dpaa2_dev_priv *priv,
- int offset, int size, int tc_id)
+dpaa2_flow_rule_add_all(struct dpaa2_dev_priv *priv,
+ enum dpaa2_flow_dist_type dist_type,
+ uint16_t entry_size, uint8_t tc_id)
{
- struct dpaa2_dev_flow *curr;
+ struct dpaa2_dev_flow *curr = LIST_FIRST(&priv->flows);
+ struct dpaa2_generic_flow *qos_flow;
+ struct dpaa2_generic_flow *fs_flow;
int ret;
- curr = priv->curr;
- if (!curr || curr->tc_id != tc_id) {
- DPAA2_PMD_ERR("Current flow insert hole failed.");
- return -EINVAL;
- } else {
- ret = dpaa2_flow_rule_insert_hole(curr, offset, size,
- DPAA2_FLOW_FS_TYPE);
- if (ret)
- return ret;
- }
-
- curr = LIST_FIRST(&priv->flows);
-
while (curr) {
- if (curr->tc_id != tc_id) {
- curr = LIST_NEXT(curr, next);
- continue;
+ qos_flow = curr->qos_flow;
+ fs_flow = curr->fs_flow;
+ if (qos_flow && dist_type == DPAA2_FLOW_QOS_TYPE) {
+ qos_flow->rule_cfg.key_size = entry_size;
+ ret = dpaa2_flow_add_qos_rule(priv, qos_flow);
+ if (ret)
+ return ret;
+ } else if (dist_type == DPAA2_FLOW_FS_TYPE &&
+ fs_flow && fs_flow->tc_id == tc_id) {
+ fs_flow->rule_cfg.key_size = entry_size;
+ ret = dpaa2_flow_add_fs_rule(priv, fs_flow);
+ if (ret)
+ return ret;
}
- ret = dpaa2_flow_rule_insert_hole(curr, offset, size,
- DPAA2_FLOW_FS_TYPE);
- if (ret)
- return ret;
curr = LIST_NEXT(curr, next);
}
return 0;
}
+static void
+dpaa2_flow_rule_insert_hole(struct dpaa2_dev_priv *priv,
+ int offset, int size, int tc_id,
+ enum dpaa2_flow_dist_type dist_type)
+{
+ struct dpaa2_dev_flow *flow;
+ struct dpaa2_generic_flow *curr;
+
+ curr = priv->cur_flow;
+ if (curr)
+ _dpaa2_flow_rule_insert_hole(curr, offset, size);
+
+ flow = LIST_FIRST(&priv->flows);
+ while (flow) {
+ if (dist_type == DPAA2_FLOW_QOS_TYPE)
+ curr = flow->qos_flow;
+ else
+ curr = flow->fs_flow;
+ flow = LIST_NEXT(flow, next);
+ if (!curr)
+ continue;
+ if (dist_type == DPAA2_FLOW_FS_TYPE &&
+ curr->tc_id != tc_id)
+ continue;
+ if (curr->ip_src || curr->ip_dst)
+ _dpaa2_flow_rule_insert_hole(curr, offset, size);
+ }
+}
+
static int
dpaa2_flow_faf_advance(struct dpaa2_dev_priv *priv,
int faf_byte, enum dpaa2_flow_dist_type dist_type, int tc_id,
int *insert_offset)
{
- int offset, ret;
struct dpaa2_key_profile *key_profile;
- int num, pos;
+ uint8_t idx, offset = 0xff;
+ struct key_prot_field prot = {0};
if (dist_type == DPAA2_FLOW_QOS_TYPE)
- key_profile = &priv->extract.qos_key_extract.key_profile;
+ key_profile = &priv->flow_profile.qos_profile.key_profile;
else
- key_profile = &priv->extract.tc_key_extract[tc_id].key_profile;
-
- num = key_profile->num;
+ key_profile = &priv->flow_profile.tc_profile[tc_id].key_profile;
- if (num >= DPKG_MAX_NUM_OF_EXTRACTS) {
+ if (key_profile->num >= DPKG_MAX_NUM_OF_EXTRACTS) {
DPAA2_PMD_ERR("Number of extracts overflows");
return -EINVAL;
}
- if (key_profile->ip_addr_type != IP_NONE_ADDR_EXTRACT) {
- offset = key_profile->ip_addr_extract_off;
- pos = key_profile->ip_addr_extract_pos;
- key_profile->ip_addr_extract_pos++;
- key_profile->ip_addr_extract_off++;
- if (dist_type == DPAA2_FLOW_QOS_TYPE) {
- ret = dpaa2_flow_qos_rule_insert_hole(priv,
- offset, 1);
- } else {
- ret = dpaa2_flow_fs_rule_insert_hole(priv,
- offset, 1, tc_id);
- }
- if (ret)
- return ret;
- } else {
- pos = num;
- }
-
- if (pos > 0) {
- key_profile->key_offset[pos] =
- key_profile->key_offset[pos - 1] +
- key_profile->key_size[pos - 1];
- } else {
- key_profile->key_offset[pos] = 0;
- }
-
- key_profile->key_size[pos] = 1;
- key_profile->prot_field[pos].type = DPAA2_FAF_KEY;
- key_profile->prot_field[pos].key_field = faf_byte;
- key_profile->num++;
+ prot.type = DPAA2_FAF_KEY;
+ prot.key_field = faf_byte;
+ idx = dpaa2_profile_insert_no_ipaddr_extract(key_profile,
+ 1, &offset, insert_offset, &prot);
+ dpaa2_flow_rule_insert_hole(priv, offset, 1, tc_id, dist_type);
- if (insert_offset)
- *insert_offset = key_profile->key_offset[pos];
-
- key_profile->key_max_size++;
-
- return pos;
+ return idx;
}
static int
@@ -761,60 +990,27 @@ dpaa2_flow_pr_advance(struct dpaa2_dev_priv *priv,
enum dpaa2_flow_dist_type dist_type, int tc_id,
int *insert_offset)
{
- int offset, ret;
struct dpaa2_key_profile *key_profile;
- int num, pos;
+ uint8_t idx, offset = 0xff;
+ struct key_prot_field prot = {0};
if (dist_type == DPAA2_FLOW_QOS_TYPE)
- key_profile = &priv->extract.qos_key_extract.key_profile;
+ key_profile = &priv->flow_profile.qos_profile.key_profile;
else
- key_profile = &priv->extract.tc_key_extract[tc_id].key_profile;
-
- num = key_profile->num;
+ key_profile = &priv->flow_profile.tc_profile[tc_id].key_profile;
- if (num >= DPKG_MAX_NUM_OF_EXTRACTS) {
+ if (key_profile->num >= DPKG_MAX_NUM_OF_EXTRACTS) {
DPAA2_PMD_ERR("Number of extracts overflows");
return -EINVAL;
}
- if (key_profile->ip_addr_type != IP_NONE_ADDR_EXTRACT) {
- offset = key_profile->ip_addr_extract_off;
- pos = key_profile->ip_addr_extract_pos;
- key_profile->ip_addr_extract_pos++;
- key_profile->ip_addr_extract_off += pr_size;
- if (dist_type == DPAA2_FLOW_QOS_TYPE) {
- ret = dpaa2_flow_qos_rule_insert_hole(priv,
- offset, pr_size);
- } else {
- ret = dpaa2_flow_fs_rule_insert_hole(priv,
- offset, pr_size, tc_id);
- }
- if (ret)
- return ret;
- } else {
- pos = num;
- }
-
- if (pos > 0) {
- key_profile->key_offset[pos] =
- key_profile->key_offset[pos - 1] +
- key_profile->key_size[pos - 1];
- } else {
- key_profile->key_offset[pos] = 0;
- }
-
- key_profile->key_size[pos] = pr_size;
- key_profile->prot_field[pos].type = DPAA2_PR_KEY;
- key_profile->prot_field[pos].key_field =
- (pr_offset << 16) | pr_size;
- key_profile->num++;
-
- if (insert_offset)
- *insert_offset = key_profile->key_offset[pos];
+ prot.type = DPAA2_PR_KEY;
+ prot.key_field = (pr_offset << 16) | pr_size;
+ idx = dpaa2_profile_insert_no_ipaddr_extract(key_profile,
+ pr_size, &offset, insert_offset, &prot);
+ dpaa2_flow_rule_insert_hole(priv, offset, pr_size, tc_id, dist_type);
- key_profile->key_max_size += pr_size;
-
- return pos;
+ return idx;
}
/* Move IPv4/IPv6 addresses to fill new extract previous IP address.
@@ -829,9 +1025,9 @@ dpaa2_flow_key_profile_advance(enum net_prot prot,
enum dpaa2_flow_dist_type dist_type, int tc_id,
int *insert_offset)
{
- int offset, ret;
struct dpaa2_key_profile *key_profile;
- int num, pos;
+ uint8_t idx, offset = 0xff;
+ struct key_prot_field prot_field;
if (dpaa2_flow_ip_address_extract(prot, field)) {
DPAA2_PMD_ERR("%s only for none IP address extract",
@@ -840,66 +1036,35 @@ dpaa2_flow_key_profile_advance(enum net_prot prot,
}
if (dist_type == DPAA2_FLOW_QOS_TYPE)
- key_profile = &priv->extract.qos_key_extract.key_profile;
+ key_profile = &priv->flow_profile.qos_profile.key_profile;
else
- key_profile = &priv->extract.tc_key_extract[tc_id].key_profile;
-
- num = key_profile->num;
+ key_profile = &priv->flow_profile.tc_profile[tc_id].key_profile;
- if (num >= DPKG_MAX_NUM_OF_EXTRACTS) {
+ if (key_profile->num >= DPKG_MAX_NUM_OF_EXTRACTS) {
DPAA2_PMD_ERR("Number of extracts overflows");
return -EINVAL;
}
- if (key_profile->ip_addr_type != IP_NONE_ADDR_EXTRACT) {
- offset = key_profile->ip_addr_extract_off;
- pos = key_profile->ip_addr_extract_pos;
- key_profile->ip_addr_extract_pos++;
- key_profile->ip_addr_extract_off += field_size;
- if (dist_type == DPAA2_FLOW_QOS_TYPE) {
- ret = dpaa2_flow_qos_rule_insert_hole(priv,
- offset, field_size);
- } else {
- ret = dpaa2_flow_fs_rule_insert_hole(priv,
- offset, field_size, tc_id);
- }
- if (ret)
- return ret;
- } else {
- pos = num;
- }
-
- if (pos > 0) {
- key_profile->key_offset[pos] =
- key_profile->key_offset[pos - 1] +
- key_profile->key_size[pos - 1];
- } else {
- key_profile->key_offset[pos] = 0;
- }
-
- key_profile->key_size[pos] = field_size;
- key_profile->prot_field[pos].type = DPAA2_NET_PROT_KEY;
- key_profile->prot_field[pos].prot = prot;
- key_profile->prot_field[pos].key_field = field;
- key_profile->num++;
-
- if (insert_offset)
- *insert_offset = key_profile->key_offset[pos];
+ prot_field.type = DPAA2_NET_PROT_KEY;
+ prot_field.prot = prot;
+ prot_field.key_field = field;
+ idx = dpaa2_profile_insert_no_ipaddr_extract(key_profile,
+ field_size, &offset, insert_offset, &prot_field);
+ dpaa2_flow_rule_insert_hole(priv, offset, field_size, tc_id, dist_type);
if (dpaa2_flow_l4_src_port_extract(prot, field)) {
- key_profile->l4_src_port_present = 1;
- key_profile->l4_src_port_pos = pos;
- key_profile->l4_src_port_offset =
- key_profile->key_offset[pos];
+ key_profile->l4_sp_present = 1;
+ key_profile->l4_sp_extract_idx = idx;
+ key_profile->l4_sp_key_offset =
+ key_profile->key_offset[idx];
} else if (dpaa2_flow_l4_dst_port_extract(prot, field)) {
- key_profile->l4_dst_port_present = 1;
- key_profile->l4_dst_port_pos = pos;
- key_profile->l4_dst_port_offset =
- key_profile->key_offset[pos];
+ key_profile->l4_dp_present = 1;
+ key_profile->l4_dp_extract_idx = idx;
+ key_profile->l4_dp_key_offset =
+ key_profile->key_offset[idx];
}
- key_profile->key_max_size += field_size;
- return pos;
+ return idx;
}
static int
@@ -908,44 +1073,34 @@ dpaa2_flow_faf_add_hdr(int faf_byte,
enum dpaa2_flow_dist_type dist_type, int tc_id,
int *insert_offset)
{
- int pos, i, offset;
- struct dpaa2_key_extract *key_extract;
+ int extract_idx;
+ struct dpaa2_flow_tbl_profile *tbl_profile;
struct dpkg_profile_cfg *dpkg;
- struct dpkg_extract *extracts;
+ struct dpkg_extract extract;
if (dist_type == DPAA2_FLOW_QOS_TYPE)
- key_extract = &priv->extract.qos_key_extract;
+ tbl_profile = &priv->flow_profile.qos_profile;
else
- key_extract = &priv->extract.tc_key_extract[tc_id];
+ tbl_profile = &priv->flow_profile.tc_profile[tc_id];
- dpkg = &key_extract->dpkg;
- extracts = dpkg->extracts;
+ dpkg = &tbl_profile->dpkg;
if (dpkg->num_extracts >= DPKG_MAX_NUM_OF_EXTRACTS) {
DPAA2_PMD_ERR("Number of extracts overflows");
return -EINVAL;
}
- pos = dpaa2_flow_faf_advance(priv,
+ extract_idx = dpaa2_flow_faf_advance(priv,
faf_byte, dist_type, tc_id,
insert_offset);
- if (pos < 0)
- return pos;
-
- if (pos != dpkg->num_extracts) {
- /* Not the last pos, must have IP address extract.*/
- for (i = dpkg->num_extracts - 1; i >= pos; i--) {
- extracts[i + 1] = extracts[i];
- }
- }
-
- offset = DPAA2_FAFE_PSR_OFFSET + faf_byte;
-
- extracts[pos].type = DPKG_EXTRACT_FROM_PARSE;
- extracts[pos].extract.from_parse.offset = offset;
- extracts[pos].extract.from_parse.size = 1;
+ if (extract_idx < 0)
+ return extract_idx;
- dpkg->num_extracts++;
+ memset(&extract, 0, sizeof(extract));
+ extract.type = DPKG_EXTRACT_FROM_PARSE;
+ extract.extract.from_parse.offset = faf_byte;
+ extract.extract.from_parse.size = 1;
+ dpaa2_dpkg_insert_extract(dpkg, extract_idx, &extract);
return 0;
}
@@ -956,48 +1111,40 @@ dpaa2_flow_pr_add_hdr(uint32_t pr_offset,
enum dpaa2_flow_dist_type dist_type, int tc_id,
int *insert_offset)
{
- int pos, i;
- struct dpaa2_key_extract *key_extract;
+ int extract_idx;
+ struct dpaa2_flow_tbl_profile *tbl_profile;
struct dpkg_profile_cfg *dpkg;
- struct dpkg_extract *extracts;
+ struct dpkg_extract extract;
- if ((pr_offset + pr_size) > DPAA2_FAPR_SIZE) {
+ if ((pr_offset + pr_size) > DPAA2_PSR_RESULT_SIZE) {
DPAA2_PMD_ERR("PR extracts(%d:%d) overflow",
pr_offset, pr_size);
return -EINVAL;
}
if (dist_type == DPAA2_FLOW_QOS_TYPE)
- key_extract = &priv->extract.qos_key_extract;
+ tbl_profile = &priv->flow_profile.qos_profile;
else
- key_extract = &priv->extract.tc_key_extract[tc_id];
+ tbl_profile = &priv->flow_profile.tc_profile[tc_id];
- dpkg = &key_extract->dpkg;
- extracts = dpkg->extracts;
+ dpkg = &tbl_profile->dpkg;
if (dpkg->num_extracts >= DPKG_MAX_NUM_OF_EXTRACTS) {
DPAA2_PMD_ERR("Number of extracts overflows");
return -EINVAL;
}
- pos = dpaa2_flow_pr_advance(priv,
+ extract_idx = dpaa2_flow_pr_advance(priv,
pr_offset, pr_size, dist_type, tc_id,
insert_offset);
- if (pos < 0)
- return pos;
+ if (extract_idx < 0)
+ return extract_idx;
- if (pos != dpkg->num_extracts) {
- /* Not the last pos, must have IP address extract.*/
- for (i = dpkg->num_extracts - 1; i >= pos; i--) {
- extracts[i + 1] = extracts[i];
- }
- }
-
- extracts[pos].type = DPKG_EXTRACT_FROM_PARSE;
- extracts[pos].extract.from_parse.offset = pr_offset;
- extracts[pos].extract.from_parse.size = pr_size;
-
- dpkg->num_extracts++;
+ memset(&extract, 0, sizeof(extract));
+ extract.type = DPKG_EXTRACT_FROM_PARSE;
+ extract.extract.from_parse.offset = pr_offset;
+ extract.extract.from_parse.size = pr_size;
+ dpaa2_dpkg_insert_extract(dpkg, extract_idx, &extract);
return 0;
}
@@ -1009,18 +1156,17 @@ dpaa2_flow_extract_add_hdr(enum net_prot prot,
enum dpaa2_flow_dist_type dist_type, int tc_id,
int *insert_offset)
{
- int pos, i;
- struct dpaa2_key_extract *key_extract;
+ int extract_idx;
+ struct dpaa2_flow_tbl_profile *tbl_profile;
struct dpkg_profile_cfg *dpkg;
- struct dpkg_extract *extracts;
+ struct dpkg_extract extract;
if (dist_type == DPAA2_FLOW_QOS_TYPE)
- key_extract = &priv->extract.qos_key_extract;
+ tbl_profile = &priv->flow_profile.qos_profile;
else
- key_extract = &priv->extract.tc_key_extract[tc_id];
+ tbl_profile = &priv->flow_profile.tc_profile[tc_id];
- dpkg = &key_extract->dpkg;
- extracts = dpkg->extracts;
+ dpkg = &tbl_profile->dpkg;
if (dpaa2_flow_ip_address_extract(prot, field)) {
DPAA2_PMD_ERR("%s only for none IP address extract",
@@ -1033,52 +1179,86 @@ dpaa2_flow_extract_add_hdr(enum net_prot prot,
return -EINVAL;
}
- pos = dpaa2_flow_key_profile_advance(prot,
+ extract_idx = dpaa2_flow_key_profile_advance(prot,
field, field_size, priv,
dist_type, tc_id,
insert_offset);
- if (pos < 0)
- return pos;
+ if (extract_idx < 0)
+ return extract_idx;
- if (pos != dpkg->num_extracts) {
- /* Not the last pos, must have IP address extract.*/
- for (i = dpkg->num_extracts - 1; i >= pos; i--) {
- extracts[i + 1] = extracts[i];
- }
+ memset(&extract, 0, sizeof(extract));
+ extract.type = DPKG_EXTRACT_FROM_HDR;
+ extract.extract.from_hdr.prot = prot;
+ extract.extract.from_hdr.type = DPKG_FULL_FIELD;
+ extract.extract.from_hdr.field = field;
+ dpaa2_dpkg_insert_extract(dpkg, extract_idx, &extract);
+
+ return 0;
+}
+
+static inline int
+dpaa2_flow_extract_search(struct dpaa2_key_profile *key_profile,
+ enum key_prot_type type, enum net_prot prot, uint32_t key_field)
+{
+ int extract_idx;
+ struct key_prot_field *prot_field;
+
+ if (dpaa2_flow_ip_address_extract(prot, key_field)) {
+ DPAA2_PMD_ERR("%s only for none IP address extract",
+ __func__);
+ return -EINVAL;
}
- extracts[pos].type = DPKG_EXTRACT_FROM_HDR;
- extracts[pos].extract.from_hdr.prot = prot;
- extracts[pos].extract.from_hdr.type = DPKG_FULL_FIELD;
- extracts[pos].extract.from_hdr.field = field;
+ prot_field = key_profile->prot_field;
+ for (extract_idx = 0; extract_idx < key_profile->num; extract_idx++) {
+ if (type == DPAA2_NET_PROT_KEY &&
+ prot_field[extract_idx].prot == prot &&
+ prot_field[extract_idx].key_field == key_field &&
+ prot_field[extract_idx].type == type)
+ return extract_idx;
+ else if (type == DPAA2_FAF_KEY &&
+ prot_field[extract_idx].key_field == key_field &&
+ prot_field[extract_idx].type == type)
+ return extract_idx;
+ else if (type == DPAA2_PR_KEY &&
+ prot_field[extract_idx].key_field == key_field &&
+ prot_field[extract_idx].type == type)
+ return extract_idx;
+ }
- dpkg->num_extracts++;
+ if (type == DPAA2_NET_PROT_KEY &&
+ dpaa2_flow_l4_src_port_extract(prot, key_field)) {
+ if (key_profile->l4_sp_present)
+ return key_profile->l4_sp_extract_idx;
+ } else if (type == DPAA2_NET_PROT_KEY &&
+ dpaa2_flow_l4_dst_port_extract(prot, key_field)) {
+ if (key_profile->l4_dp_present)
+ return key_profile->l4_dp_extract_idx;
+ }
- return 0;
+ return -ENXIO;
}
static int
-dpaa2_flow_extract_new_raw(struct dpaa2_dev_priv *priv,
+_dpaa2_flow_extract_add_raw(struct dpaa2_dev_priv *priv,
int offset, int size,
enum dpaa2_flow_dist_type dist_type, int tc_id)
{
- struct dpaa2_key_extract *key_extract;
+ struct dpaa2_flow_tbl_profile *tbl_profile;
struct dpkg_profile_cfg *dpkg;
struct dpaa2_key_profile *key_profile;
- int last_extract_size, index, pos, item_size;
+ int last_extract_size, index, raw_idx, item_size;
uint8_t num_extracts;
uint32_t field;
+ int ret;
if (dist_type == DPAA2_FLOW_QOS_TYPE)
- key_extract = &priv->extract.qos_key_extract;
+ tbl_profile = &priv->flow_profile.qos_profile;
else
- key_extract = &priv->extract.tc_key_extract[tc_id];
+ tbl_profile = &priv->flow_profile.tc_profile[tc_id];
- dpkg = &key_extract->dpkg;
- key_profile = &key_extract->key_profile;
-
- key_profile->raw_region.raw_start = 0;
- key_profile->raw_region.raw_size = 0;
+ dpkg = &tbl_profile->dpkg;
+ key_profile = &tbl_profile->key_profile;
last_extract_size = (size % DPAA2_FLOW_MAX_KEY_SIZE);
num_extracts = (size / DPAA2_FLOW_MAX_KEY_SIZE);
@@ -1087,6 +1267,13 @@ dpaa2_flow_extract_new_raw(struct dpaa2_dev_priv *priv,
else
last_extract_size = DPAA2_FLOW_MAX_KEY_SIZE;
+ if ((key_profile->num + num_extracts) >
+ DPKG_MAX_NUM_OF_EXTRACTS) {
+ DPAA2_PMD_ERR("%s Failed to expand raw extracts",
+ __func__);
+ return -EINVAL;
+ }
+
for (index = 0; index < num_extracts; index++) {
if (index == num_extracts - 1)
item_size = last_extract_size;
@@ -1095,25 +1282,22 @@ dpaa2_flow_extract_new_raw(struct dpaa2_dev_priv *priv,
field = offset << DPAA2_FLOW_RAW_OFFSET_FIELD_SHIFT;
field |= item_size;
- pos = dpaa2_flow_key_profile_advance(NET_PROT_PAYLOAD,
+ ret = dpaa2_flow_extract_search(key_profile,
+ DPAA2_NET_PROT_KEY, NET_PROT_PAYLOAD, field);
+ if (ret >= 0) {
+ offset += item_size;
+ continue;
+ }
+
+ raw_idx = dpaa2_flow_key_profile_advance(NET_PROT_PAYLOAD,
field, item_size, priv, dist_type,
tc_id, NULL);
- if (pos < 0)
- return pos;
-
- dpkg->extracts[pos].type = DPKG_EXTRACT_FROM_DATA;
- dpkg->extracts[pos].extract.from_data.size = item_size;
- dpkg->extracts[pos].extract.from_data.offset = offset;
-
- if (index == 0) {
- key_profile->raw_extract_pos = pos;
- key_profile->raw_extract_off =
- key_profile->key_offset[pos];
- key_profile->raw_region.raw_start = offset;
- }
- key_profile->raw_extract_num++;
- key_profile->raw_region.raw_size +=
- key_profile->key_size[pos];
+ if (raw_idx < 0)
+ return raw_idx;
+
+ dpkg->extracts[raw_idx].type = DPKG_EXTRACT_FROM_DATA;
+ dpkg->extracts[raw_idx].extract.from_data.size = item_size;
+ dpkg->extracts[raw_idx].extract.from_data.offset = offset;
offset += item_size;
dpkg->num_extracts++;
@@ -1127,247 +1311,16 @@ dpaa2_flow_extract_add_raw(struct dpaa2_dev_priv *priv,
int offset, int size, enum dpaa2_flow_dist_type dist_type,
int tc_id, int *recfg)
{
- struct dpaa2_key_profile *key_profile;
- struct dpaa2_raw_region *raw_region;
- int end = offset + size, ret = 0, extract_extended, sz_extend;
- int start_cmp, end_cmp, new_size, index, pos, end_pos;
- int last_extract_size, item_size, num_extracts, bk_num = 0;
- struct dpkg_extract extract_bk[DPKG_MAX_NUM_OF_EXTRACTS];
- uint8_t key_offset_bk[DPKG_MAX_NUM_OF_EXTRACTS];
- uint8_t key_size_bk[DPKG_MAX_NUM_OF_EXTRACTS];
- struct key_prot_field prot_field_bk[DPKG_MAX_NUM_OF_EXTRACTS];
- struct dpaa2_raw_region raw_hole;
- struct dpkg_profile_cfg *dpkg;
- enum net_prot prot;
- uint32_t field;
-
- if (dist_type == DPAA2_FLOW_QOS_TYPE) {
- key_profile = &priv->extract.qos_key_extract.key_profile;
- dpkg = &priv->extract.qos_key_extract.dpkg;
- } else {
- key_profile = &priv->extract.tc_key_extract[tc_id].key_profile;
- dpkg = &priv->extract.tc_key_extract[tc_id].dpkg;
- }
+ int ret;
- raw_region = &key_profile->raw_region;
- if (!raw_region->raw_size) {
- /* New RAW region*/
- ret = dpaa2_flow_extract_new_raw(priv, offset, size,
+ ret = _dpaa2_flow_extract_add_raw(priv, offset, size,
dist_type, tc_id);
- if (!ret && recfg)
- (*recfg) |= dist_type;
-
- return ret;
- }
- start_cmp = raw_region->raw_start;
- end_cmp = raw_region->raw_start + raw_region->raw_size;
-
- if (offset >= start_cmp && end <= end_cmp)
- return 0;
-
- sz_extend = 0;
- new_size = raw_region->raw_size;
- if (offset < start_cmp) {
- sz_extend += start_cmp - offset;
- new_size += (start_cmp - offset);
- }
- if (end > end_cmp) {
- sz_extend += end - end_cmp;
- new_size += (end - end_cmp);
- }
-
- last_extract_size = (new_size % DPAA2_FLOW_MAX_KEY_SIZE);
- num_extracts = (new_size / DPAA2_FLOW_MAX_KEY_SIZE);
- if (last_extract_size)
- num_extracts++;
- else
- last_extract_size = DPAA2_FLOW_MAX_KEY_SIZE;
-
- if ((key_profile->num + num_extracts -
- key_profile->raw_extract_num) >=
- DPKG_MAX_NUM_OF_EXTRACTS) {
- DPAA2_PMD_ERR("%s Failed to expand raw extracts",
- __func__);
- return -EINVAL;
- }
-
- if (offset < start_cmp) {
- raw_hole.raw_start = key_profile->raw_extract_off;
- raw_hole.raw_size = start_cmp - offset;
- raw_region->raw_start = offset;
- raw_region->raw_size += start_cmp - offset;
-
- if (dist_type & DPAA2_FLOW_QOS_TYPE) {
- ret = dpaa2_flow_qos_rule_insert_hole(priv,
- raw_hole.raw_start,
- raw_hole.raw_size);
- if (ret)
- return ret;
- }
- if (dist_type & DPAA2_FLOW_FS_TYPE) {
- ret = dpaa2_flow_fs_rule_insert_hole(priv,
- raw_hole.raw_start,
- raw_hole.raw_size, tc_id);
- if (ret)
- return ret;
- }
- }
-
- if (end > end_cmp) {
- raw_hole.raw_start =
- key_profile->raw_extract_off +
- raw_region->raw_size;
- raw_hole.raw_size = end - end_cmp;
- raw_region->raw_size += end - end_cmp;
-
- if (dist_type & DPAA2_FLOW_QOS_TYPE) {
- ret = dpaa2_flow_qos_rule_insert_hole(priv,
- raw_hole.raw_start,
- raw_hole.raw_size);
- if (ret)
- return ret;
- }
- if (dist_type & DPAA2_FLOW_FS_TYPE) {
- ret = dpaa2_flow_fs_rule_insert_hole(priv,
- raw_hole.raw_start,
- raw_hole.raw_size, tc_id);
- if (ret)
- return ret;
- }
- }
-
- end_pos = key_profile->raw_extract_pos +
- key_profile->raw_extract_num;
- if (key_profile->num > end_pos) {
- bk_num = key_profile->num - end_pos;
- memcpy(extract_bk, &dpkg->extracts[end_pos],
- bk_num * sizeof(struct dpkg_extract));
- memcpy(key_offset_bk, &key_profile->key_offset[end_pos],
- bk_num * sizeof(uint8_t));
- memcpy(key_size_bk, &key_profile->key_size[end_pos],
- bk_num * sizeof(uint8_t));
- memcpy(prot_field_bk, &key_profile->prot_field[end_pos],
- bk_num * sizeof(struct key_prot_field));
-
- for (index = 0; index < bk_num; index++) {
- key_offset_bk[index] += sz_extend;
- prot = prot_field_bk[index].prot;
- field = prot_field_bk[index].key_field;
- if (dpaa2_flow_l4_src_port_extract(prot,
- field)) {
- key_profile->l4_src_port_present = 1;
- key_profile->l4_src_port_pos = end_pos + index;
- key_profile->l4_src_port_offset =
- key_offset_bk[index];
- } else if (dpaa2_flow_l4_dst_port_extract(prot,
- field)) {
- key_profile->l4_dst_port_present = 1;
- key_profile->l4_dst_port_pos = end_pos + index;
- key_profile->l4_dst_port_offset =
- key_offset_bk[index];
- }
- }
- }
-
- pos = key_profile->raw_extract_pos;
-
- for (index = 0; index < num_extracts; index++) {
- if (index == num_extracts - 1)
- item_size = last_extract_size;
- else
- item_size = DPAA2_FLOW_MAX_KEY_SIZE;
- field = offset << DPAA2_FLOW_RAW_OFFSET_FIELD_SHIFT;
- field |= item_size;
-
- if (pos > 0) {
- key_profile->key_offset[pos] =
- key_profile->key_offset[pos - 1] +
- key_profile->key_size[pos - 1];
- } else {
- key_profile->key_offset[pos] = 0;
- }
- key_profile->key_size[pos] = item_size;
- key_profile->prot_field[pos].type = DPAA2_NET_PROT_KEY;
- key_profile->prot_field[pos].prot = NET_PROT_PAYLOAD;
- key_profile->prot_field[pos].key_field = field;
-
- dpkg->extracts[pos].type = DPKG_EXTRACT_FROM_DATA;
- dpkg->extracts[pos].extract.from_data.size = item_size;
- dpkg->extracts[pos].extract.from_data.offset = offset;
- offset += item_size;
- pos++;
- }
-
- if (bk_num) {
- memcpy(&dpkg->extracts[pos], extract_bk,
- bk_num * sizeof(struct dpkg_extract));
- memcpy(&key_profile->key_offset[end_pos],
- key_offset_bk, bk_num * sizeof(uint8_t));
- memcpy(&key_profile->key_size[end_pos],
- key_size_bk, bk_num * sizeof(uint8_t));
- memcpy(&key_profile->prot_field[end_pos],
- prot_field_bk, bk_num * sizeof(struct key_prot_field));
- }
-
- extract_extended = num_extracts - key_profile->raw_extract_num;
- if (key_profile->ip_addr_type != IP_NONE_ADDR_EXTRACT) {
- key_profile->ip_addr_extract_pos += extract_extended;
- key_profile->ip_addr_extract_off += sz_extend;
- }
- key_profile->raw_extract_num = num_extracts;
- key_profile->num += extract_extended;
- key_profile->key_max_size += sz_extend;
-
- dpkg->num_extracts += extract_extended;
if (!ret && recfg)
- (*recfg) |= dist_type;
+ (*recfg) |= true;
return ret;
}
-static inline int
-dpaa2_flow_extract_search(struct dpaa2_key_profile *key_profile,
- enum key_prot_type type, enum net_prot prot, uint32_t key_field)
-{
- int pos;
- struct key_prot_field *prot_field;
-
- if (dpaa2_flow_ip_address_extract(prot, key_field)) {
- DPAA2_PMD_ERR("%s only for none IP address extract",
- __func__);
- return -EINVAL;
- }
-
- prot_field = key_profile->prot_field;
- for (pos = 0; pos < key_profile->num; pos++) {
- if (type == DPAA2_NET_PROT_KEY &&
- prot_field[pos].prot == prot &&
- prot_field[pos].key_field == key_field &&
- prot_field[pos].type == type)
- return pos;
- else if (type == DPAA2_FAF_KEY &&
- prot_field[pos].key_field == key_field &&
- prot_field[pos].type == type)
- return pos;
- else if (type == DPAA2_PR_KEY &&
- prot_field[pos].key_field == key_field &&
- prot_field[pos].type == type)
- return pos;
- }
-
- if (type == DPAA2_NET_PROT_KEY &&
- dpaa2_flow_l4_src_port_extract(prot, key_field)) {
- if (key_profile->l4_src_port_present)
- return key_profile->l4_src_port_pos;
- } else if (type == DPAA2_NET_PROT_KEY &&
- dpaa2_flow_l4_dst_port_extract(prot, key_field)) {
- if (key_profile->l4_dst_port_present)
- return key_profile->l4_dst_port_pos;
- }
-
- return -ENXIO;
-}
-
static inline int
dpaa2_flow_extract_key_offset(struct dpaa2_key_profile *key_profile,
enum key_prot_type type, enum net_prot prot, uint32_t key_field)
@@ -1383,71 +1336,45 @@ dpaa2_flow_extract_key_offset(struct dpaa2_key_profile *key_profile,
static int
dpaa2_flow_faf_add_rule(struct dpaa2_dev_priv *priv,
- struct dpaa2_dev_flow *flow,
- enum dpaa2_rx_faf_offset faf_bit_off,
- int group,
- enum dpaa2_flow_dist_type dist_type)
+ struct dpaa2_generic_flow *flow, uint32_t faf_bit_off,
+ int group, enum dpaa2_flow_dist_type dist_type)
{
int offset;
uint8_t *key_addr;
uint8_t *mask_addr;
- struct dpaa2_key_extract *key_extract;
+ struct dpaa2_flow_tbl_profile *tbl_profile;
struct dpaa2_key_profile *key_profile;
uint8_t faf_byte = faf_bit_off / 8;
uint8_t faf_bit_in_byte = faf_bit_off % 8;
faf_bit_in_byte = 7 - faf_bit_in_byte;
-
- if (dist_type & DPAA2_FLOW_QOS_TYPE) {
- key_extract = &priv->extract.qos_key_extract;
- key_profile = &key_extract->key_profile;
-
- offset = dpaa2_flow_extract_key_offset(key_profile,
- DPAA2_FAF_KEY, NET_PROT_NONE, faf_byte);
- if (offset < 0) {
- DPAA2_PMD_ERR("%s QoS key extract failed", __func__);
- return -EINVAL;
- }
- key_addr = flow->qos_key_addr + offset;
- mask_addr = flow->qos_mask_addr + offset;
-
- if (!(*key_addr) &&
- key_profile->ip_addr_type == IP_NONE_ADDR_EXTRACT &&
- offset >= flow->qos_rule_size)
- flow->qos_rule_size = offset + sizeof(uint8_t);
-
- *key_addr |= (1 << faf_bit_in_byte);
- *mask_addr |= (1 << faf_bit_in_byte);
+ if (dist_type == DPAA2_FLOW_QOS_TYPE)
+ tbl_profile = &priv->flow_profile.qos_profile;
+ else
+ tbl_profile = &priv->flow_profile.tc_profile[group];
+ key_profile = &tbl_profile->key_profile;
+ offset = dpaa2_flow_extract_key_offset(key_profile,
+ DPAA2_FAF_KEY, NET_PROT_NONE, faf_byte);
+ if (offset < 0) {
+ DPAA2_PMD_ERR("%s QoS key extract failed", __func__);
+ return -EINVAL;
}
+ key_addr = flow->key_addr + offset;
+ mask_addr = flow->mask_addr + offset;
- if (dist_type & DPAA2_FLOW_FS_TYPE) {
- key_extract = &priv->extract.tc_key_extract[group];
- key_profile = &key_extract->key_profile;
-
- offset = dpaa2_flow_extract_key_offset(key_profile,
- DPAA2_FAF_KEY, NET_PROT_NONE, faf_byte);
- if (offset < 0) {
- DPAA2_PMD_ERR("%s TC[%d] key extract failed",
- __func__, group);
- return -EINVAL;
- }
- key_addr = flow->fs_key_addr + offset;
- mask_addr = flow->fs_mask_addr + offset;
-
- if (!(*key_addr) &&
- key_profile->ip_addr_type == IP_NONE_ADDR_EXTRACT &&
- offset >= flow->fs_rule_size)
- flow->fs_rule_size = offset + sizeof(uint8_t);
+ if (!(*key_addr) &&
+ !(flow->ip_src || flow->ip_dst) &&
+ offset >= flow->rule_size)
+ flow->rule_size = offset + sizeof(uint8_t);
- *key_addr |= (1 << faf_bit_in_byte);
- *mask_addr |= (1 << faf_bit_in_byte);
- }
+ *key_addr |= (1 << faf_bit_in_byte);
+ *mask_addr |= (1 << faf_bit_in_byte);
return 0;
}
static inline int
-dpaa2_flow_pr_rule_data_set(struct dpaa2_dev_flow *flow,
+dpaa2_flow_pr_rule_data_set(struct dpaa2_generic_flow *flow,
struct dpaa2_key_profile *key_profile,
uint32_t pr_offset, uint32_t pr_size,
const void *key, const void *mask,
@@ -1467,39 +1394,20 @@ dpaa2_flow_pr_rule_data_set(struct dpaa2_dev_flow *flow,
sprintf(offset_info, "offset(%d)", offset);
sprintf(size_info, "size(%d)", pr_size);
- if (dist_type & DPAA2_FLOW_QOS_TYPE) {
- sprintf(rule_size_info, "qos rule size(%d)",
- flow->qos_rule_size);
- memcpy((flow->qos_key_addr + offset), key, pr_size);
- memcpy((flow->qos_mask_addr + offset), mask, pr_size);
- if (key_profile->ip_addr_type == IP_NONE_ADDR_EXTRACT) {
- if (offset >= flow->qos_rule_size) {
- flow->qos_rule_size = offset + pr_size;
- } else if ((offset + pr_size) > flow->qos_rule_size) {
- DPAA2_PMD_ERR("%s < %s, but %s + %s > %s",
- offset_info, rule_size_info,
- offset_info, size_info,
- rule_size_info);
- return -EINVAL;
- }
- }
- }
-
- if (dist_type & DPAA2_FLOW_FS_TYPE) {
- sprintf(rule_size_info, "fs rule size(%d)",
- flow->fs_rule_size);
- memcpy((flow->fs_key_addr + offset), key, pr_size);
- memcpy((flow->fs_mask_addr + offset), mask, pr_size);
- if (key_profile->ip_addr_type == IP_NONE_ADDR_EXTRACT) {
- if (offset >= flow->fs_rule_size) {
- flow->fs_rule_size = offset + pr_size;
- } else if ((offset + pr_size) > flow->fs_rule_size) {
- DPAA2_PMD_ERR("%s < %s, but %s + %s > %s",
- offset_info, rule_size_info,
- offset_info, size_info,
- rule_size_info);
- return -EINVAL;
- }
+ sprintf(rule_size_info, "%s rule size(%d)",
+ dist_type == DPAA2_FLOW_QOS_TYPE ?
+ "QoS" : "FS", flow->rule_size);
+ memcpy((flow->key_addr + offset), key, pr_size);
+ memcpy((flow->mask_addr + offset), mask, pr_size);
+ if (!(flow->ip_src || flow->ip_dst)) {
+ if (offset >= flow->rule_size) {
+ flow->rule_size = offset + pr_size;
+ } else if ((offset + pr_size) > flow->rule_size) {
+ DPAA2_PMD_ERR("%s < %s, but %s + %s > %s",
+ offset_info, rule_size_info,
+ offset_info, size_info,
+ rule_size_info);
+ return -EINVAL;
}
}
@@ -1507,13 +1415,13 @@ dpaa2_flow_pr_rule_data_set(struct dpaa2_dev_flow *flow,
}
static inline int
-dpaa2_flow_hdr_rule_data_set(struct dpaa2_dev_flow *flow,
+dpaa2_flow_hdr_rule_data_set(struct dpaa2_generic_flow *flow,
struct dpaa2_key_profile *key_profile,
enum net_prot prot, uint32_t field, int size,
const void *key, const void *mask,
enum dpaa2_flow_dist_type dist_type)
{
- int offset;
+ int offset, i;
char offset_info[64], size_info[64], rule_size_info[64];
if (dpaa2_flow_ip_address_extract(prot, field)) {
@@ -1532,37 +1440,22 @@ dpaa2_flow_hdr_rule_data_set(struct dpaa2_dev_flow *flow,
sprintf(offset_info, "offset(%d)", offset);
sprintf(size_info, "size(%d)", size);
- if (dist_type & DPAA2_FLOW_QOS_TYPE) {
- sprintf(rule_size_info, "qos rule size(%d)",
- flow->qos_rule_size);
- memcpy((flow->qos_key_addr + offset), key, size);
- memcpy((flow->qos_mask_addr + offset), mask, size);
- if (key_profile->ip_addr_type == IP_NONE_ADDR_EXTRACT) {
- if (offset >= flow->qos_rule_size) {
- flow->qos_rule_size = offset + size;
- } else if ((offset + size) > flow->qos_rule_size) {
- DPAA2_PMD_ERR("%s: %s < %s, but %s + %s > %s",
- __func__, offset_info, rule_size_info,
- offset_info, size_info, rule_size_info);
- return -EINVAL;
- }
- }
- }
+ sprintf(rule_size_info, "%s rule size(%d)",
+ dist_type == DPAA2_FLOW_QOS_TYPE ? "QoS" : "FS",
+ flow->rule_size);
- if (dist_type & DPAA2_FLOW_FS_TYPE) {
- sprintf(rule_size_info, "fs rule size(%d)",
- flow->fs_rule_size);
- memcpy((flow->fs_key_addr + offset), key, size);
- memcpy((flow->fs_mask_addr + offset), mask, size);
- if (key_profile->ip_addr_type == IP_NONE_ADDR_EXTRACT) {
- if (offset >= flow->fs_rule_size) {
- flow->fs_rule_size = offset + size;
- } else if ((offset + size) > flow->fs_rule_size) {
- DPAA2_PMD_ERR("%s: %s < %s, but %s + %s > %s",
- __func__, offset_info, rule_size_info,
- offset_info, size_info, rule_size_info);
- return -EINVAL;
- }
+ for (i = 0; i < size; i++) {
+ *(flow->key_addr + offset + i) |= *((const uint8_t *)key + i);
+ *(flow->mask_addr + offset + i) |= *((const uint8_t *)mask + i);
+ }
+ if (!(flow->ip_src || flow->ip_dst)) {
+ if (offset >= flow->rule_size) {
+ flow->rule_size = offset + size;
+ } else if ((offset + size) > flow->rule_size) {
+ DPAA2_PMD_ERR("%s: %s < %s, but %s + %s > %s",
+ __func__, offset_info, rule_size_info,
+ offset_info, size_info, rule_size_info);
+ return -EINVAL;
}
}
@@ -1570,7 +1463,7 @@ dpaa2_flow_hdr_rule_data_set(struct dpaa2_dev_flow *flow,
}
static inline int
-dpaa2_flow_raw_rule_data_set(struct dpaa2_dev_flow *flow,
+dpaa2_flow_raw_rule_data_set(struct dpaa2_generic_flow *flow,
struct dpaa2_key_profile *key_profile,
uint32_t extract_offset, int size,
const void *key, const void *mask,
@@ -1593,34 +1486,19 @@ dpaa2_flow_raw_rule_data_set(struct dpaa2_dev_flow *flow,
sprintf(offset_info, "offset(%d)", offset);
sprintf(size_info, "size(%d)", size);
- if (dist_type & DPAA2_FLOW_QOS_TYPE) {
- sprintf(rule_size_info, "qos rule size(%d)",
- flow->qos_rule_size);
- memcpy((flow->qos_key_addr + offset), key, size);
- memcpy((flow->qos_mask_addr + offset), mask, size);
- if (offset >= flow->qos_rule_size) {
- flow->qos_rule_size = offset + size;
- } else if ((offset + size) > flow->qos_rule_size) {
- DPAA2_PMD_ERR("%s: %s < %s, but %s + %s > %s",
- __func__, offset_info, rule_size_info,
- offset_info, size_info, rule_size_info);
- return -EINVAL;
- }
- }
-
- if (dist_type & DPAA2_FLOW_FS_TYPE) {
- sprintf(rule_size_info, "fs rule size(%d)",
- flow->fs_rule_size);
- memcpy((flow->fs_key_addr + offset), key, size);
- memcpy((flow->fs_mask_addr + offset), mask, size);
- if (offset >= flow->fs_rule_size) {
- flow->fs_rule_size = offset + size;
- } else if ((offset + size) > flow->fs_rule_size) {
- DPAA2_PMD_ERR("%s: %s < %s, but %s + %s > %s",
- __func__, offset_info, rule_size_info,
- offset_info, size_info, rule_size_info);
- return -EINVAL;
- }
+ sprintf(rule_size_info, "%s rule size(%d)",
+ dist_type == DPAA2_FLOW_QOS_TYPE ?
+ "QoS" : "FS", flow->rule_size);
+
+ memcpy((flow->key_addr + offset), key, size);
+ memcpy((flow->mask_addr + offset), mask, size);
+ if (offset >= flow->rule_size) {
+ flow->rule_size = offset + size;
+ } else if ((offset + size) > flow->rule_size) {
+ DPAA2_PMD_ERR("%s: %s < %s, but %s + %s > %s",
+ __func__, offset_info, rule_size_info,
+ offset_info, size_info, rule_size_info);
+ return -EINVAL;
}
return 0;
@@ -1691,13 +1569,9 @@ dpaa2_flow_extract_support(const uint8_t *mask_src,
mask_support = (const char *)&dpaa2_flow_item_gtp_mask;
size = sizeof(struct rte_flow_item_gtp);
break;
- case RTE_FLOW_ITEM_TYPE_MPLS:
- mask_support = (const char *)&dpaa2_flow_item_mpls_mask;
- size = sizeof(struct rte_flow_item_mpls);
- break;
- case RTE_FLOW_ITEM_TYPE_PPPOES:
- mask_support = (const char *)&dpaa2_flow_item_pppoe_mask;
- size = sizeof(struct rte_flow_item_pppoe);
+ case RTE_FLOW_ITEM_TYPE_GENEVE:
+ mask_support = (const char *)&dpaa2_flow_item_geneve_mask;
+ size = sizeof(struct rte_flow_item_geneve);
break;
default:
return -EINVAL;
@@ -1716,19 +1590,17 @@ dpaa2_flow_extract_support(const uint8_t *mask_src,
static int
dpaa2_flow_identify_by_faf(struct dpaa2_dev_priv *priv,
- struct dpaa2_dev_flow *flow,
- enum dpaa2_rx_faf_offset faf_off,
- enum dpaa2_flow_dist_type dist_type,
- int group, int *recfg)
+ struct dpaa2_generic_flow *flow, uint32_t faf_bit_off,
+ enum dpaa2_flow_dist_type dist_type, int group, int *recfg)
{
- int ret, index, local_cfg = 0;
- struct dpaa2_key_extract *extract;
+ int ret, index, local_cfg = false;
+ struct dpaa2_flow_tbl_profile *tbl_profile;
struct dpaa2_key_profile *key_profile;
- uint8_t faf_byte = faf_off / 8;
+ uint8_t faf_byte = faf_bit_off / 8;
- if (dist_type & DPAA2_FLOW_QOS_TYPE) {
- extract = &priv->extract.qos_key_extract;
- key_profile = &extract->key_profile;
+ if (dist_type == DPAA2_FLOW_QOS_TYPE) {
+ tbl_profile = &priv->flow_profile.qos_profile;
+ key_profile = &tbl_profile->key_profile;
index = dpaa2_flow_extract_search(key_profile,
DPAA2_FAF_KEY, NET_PROT_NONE, faf_byte);
@@ -1741,20 +1613,18 @@ dpaa2_flow_identify_by_faf(struct dpaa2_dev_priv *priv,
return -EINVAL;
}
- local_cfg |= DPAA2_FLOW_QOS_TYPE;
+ local_cfg = true;
}
- ret = dpaa2_flow_faf_add_rule(priv, flow, faf_off, group,
+ ret = dpaa2_flow_faf_add_rule(priv, flow, faf_bit_off, group,
DPAA2_FLOW_QOS_TYPE);
if (ret) {
DPAA2_PMD_ERR("QoS faf rule set failed");
- return -EINVAL;
+ return ret;
}
- }
-
- if (dist_type & DPAA2_FLOW_FS_TYPE) {
- extract = &priv->extract.tc_key_extract[group];
- key_profile = &extract->key_profile;
+ } else if (dist_type == DPAA2_FLOW_FS_TYPE) {
+ tbl_profile = &priv->flow_profile.tc_profile[group];
+ key_profile = &tbl_profile->key_profile;
index = dpaa2_flow_extract_search(key_profile,
DPAA2_FAF_KEY, NET_PROT_NONE, faf_byte);
@@ -1768,10 +1638,10 @@ dpaa2_flow_identify_by_faf(struct dpaa2_dev_priv *priv,
return -EINVAL;
}
- local_cfg |= DPAA2_FLOW_FS_TYPE;
+ local_cfg = true;
}
- ret = dpaa2_flow_faf_add_rule(priv, flow, faf_off, group,
+ ret = dpaa2_flow_faf_add_rule(priv, flow, faf_bit_off, group,
DPAA2_FLOW_FS_TYPE);
if (ret) {
DPAA2_PMD_ERR("FS[%d] faf rule set failed",
@@ -1781,29 +1651,29 @@ dpaa2_flow_identify_by_faf(struct dpaa2_dev_priv *priv,
}
if (recfg)
- *recfg |= local_cfg;
+ (*recfg) |= local_cfg;
return 0;
}
static int
-dpaa2_flow_add_pr_extract_rule(struct dpaa2_dev_flow *flow,
+dpaa2_flow_add_pr_extract_rule(struct dpaa2_generic_flow *flow,
uint32_t pr_offset, uint32_t pr_size,
const void *key, const void *mask,
struct dpaa2_dev_priv *priv, int tc_id, int *recfg,
enum dpaa2_flow_dist_type dist_type)
{
- int index, ret, local_cfg = 0;
- struct dpaa2_key_extract *key_extract;
+ int index, ret, local_cfg = false;
+ struct dpaa2_flow_tbl_profile *tbl_profile;
struct dpaa2_key_profile *key_profile;
uint32_t pr_field = pr_offset << 16 | pr_size;
if (dist_type == DPAA2_FLOW_QOS_TYPE)
- key_extract = &priv->extract.qos_key_extract;
+ tbl_profile = &priv->flow_profile.qos_profile;
else
- key_extract = &priv->extract.tc_key_extract[tc_id];
+ tbl_profile = &priv->flow_profile.tc_profile[tc_id];
- key_profile = &key_extract->key_profile;
+ key_profile = &tbl_profile->key_profile;
index = dpaa2_flow_extract_search(key_profile,
DPAA2_PR_KEY, NET_PROT_NONE, pr_field);
@@ -1817,7 +1687,7 @@ dpaa2_flow_add_pr_extract_rule(struct dpaa2_dev_flow *flow,
return ret;
}
- local_cfg |= dist_type;
+ local_cfg = true;
}
ret = dpaa2_flow_pr_rule_data_set(flow, key_profile,
@@ -1830,31 +1700,31 @@ dpaa2_flow_add_pr_extract_rule(struct dpaa2_dev_flow *flow,
}
if (recfg)
- *recfg |= local_cfg;
+ (*recfg) |= local_cfg;
return 0;
}
static int
-dpaa2_flow_add_hdr_extract_rule(struct dpaa2_dev_flow *flow,
+dpaa2_flow_add_hdr_extract_rule(struct dpaa2_generic_flow *flow,
enum net_prot prot, uint32_t field,
const void *key, const void *mask, int size,
struct dpaa2_dev_priv *priv, int tc_id, int *recfg,
enum dpaa2_flow_dist_type dist_type)
{
- int index, ret, local_cfg = 0;
- struct dpaa2_key_extract *key_extract;
+ int index, ret, local_cfg = false;
+ struct dpaa2_flow_tbl_profile *tbl_profile;
struct dpaa2_key_profile *key_profile;
if (dpaa2_flow_ip_address_extract(prot, field))
return -EINVAL;
if (dist_type == DPAA2_FLOW_QOS_TYPE)
- key_extract = &priv->extract.qos_key_extract;
+ tbl_profile = &priv->flow_profile.qos_profile;
else
- key_extract = &priv->extract.tc_key_extract[tc_id];
+ tbl_profile = &priv->flow_profile.tc_profile[tc_id];
- key_profile = &key_extract->key_profile;
+ key_profile = &tbl_profile->key_profile;
index = dpaa2_flow_extract_search(key_profile,
DPAA2_NET_PROT_KEY, prot, field);
@@ -1868,7 +1738,7 @@ dpaa2_flow_add_hdr_extract_rule(struct dpaa2_dev_flow *flow,
return ret;
}
- local_cfg |= dist_type;
+ local_cfg = true;
}
ret = dpaa2_flow_hdr_rule_data_set(flow, key_profile,
@@ -1881,44 +1751,57 @@ dpaa2_flow_add_hdr_extract_rule(struct dpaa2_dev_flow *flow,
}
if (recfg)
- *recfg |= local_cfg;
+ (*recfg) |= local_cfg;
return 0;
}
static int
-dpaa2_flow_add_ipaddr_extract_rule(struct dpaa2_dev_flow *flow,
+dpaa2_flow_add_ipaddr_extract_rule(struct dpaa2_generic_flow *flow,
enum net_prot prot, uint32_t field,
const void *key, const void *mask, int size,
struct dpaa2_dev_priv *priv, int tc_id, int *recfg,
enum dpaa2_flow_dist_type dist_type)
{
- int local_cfg = 0, num, ipaddr_extract_len = 0;
- struct dpaa2_key_extract *key_extract;
+ int local_cfg = false, update = 0, ret, pos = 0;
+ struct dpaa2_flow_tbl_profile *tbl_profile;
struct dpaa2_key_profile *key_profile;
struct dpkg_profile_cfg *dpkg;
- uint8_t *key_addr, *mask_addr;
- union ip_addr_extract_rule *ip_addr_data;
- union ip_addr_extract_rule *ip_addr_mask;
- enum net_prot orig_prot;
- uint32_t orig_field;
-
- if (prot != NET_PROT_IPV4 && prot != NET_PROT_IPV6)
- return -EINVAL;
+ uint8_t *key_addr, *mask_addr, num;
+ uint8_t ip_addr_offset = 0;
- if (prot == NET_PROT_IPV4 && field != NH_FLD_IPV4_SRC_IP &&
- field != NH_FLD_IPV4_DST_IP) {
+ if (prot != NET_PROT_IPV4 && prot != NET_PROT_IPV6) {
+ DPAA2_PMD_ERR("%s: Invalid protocol(%d)",
+ __func__, prot);
return -EINVAL;
}
- if (prot == NET_PROT_IPV6 && field != NH_FLD_IPV6_SRC_IP &&
- field != NH_FLD_IPV6_DST_IP) {
- return -EINVAL;
+ if (prot == NET_PROT_IPV4) {
+ if (field != NH_FLD_IPV4_SRC_IP &&
+ field != NH_FLD_IPV4_DST_IP) {
+ DPAA2_PMD_ERR("%s: Invalid ipv4 filed(%d)",
+ __func__, field);
+ return -EINVAL;
+ }
+ if (size != sizeof(rte_be32_t)) {
+ DPAA2_PMD_ERR("%s: Invalid ipv4 address size(%d)",
+ __func__, size);
+ return -EINVAL;
+ }
+ } else {
+ if (field != NH_FLD_IPV6_SRC_IP &&
+ field != NH_FLD_IPV6_DST_IP) {
+ DPAA2_PMD_ERR("%s: Invalid ipv6 filed(%d)",
+ __func__, field);
+ return -EINVAL;
+ }
+ if (size != NH_FLD_IPV6_ADDR_SIZE) {
+ DPAA2_PMD_ERR("%s: Invalid ipv6 address size(%d)",
+ __func__, size);
+ return -EINVAL;
+ }
}
- orig_prot = prot;
- orig_field = field;
-
if (prot == NET_PROT_IPV4 &&
field == NH_FLD_IPV4_SRC_IP) {
prot = NET_PROT_IP;
@@ -1941,182 +1824,111 @@ dpaa2_flow_add_ipaddr_extract_rule(struct dpaa2_dev_flow *flow,
return -EINVAL;
}
- if (dist_type == DPAA2_FLOW_QOS_TYPE) {
- key_extract = &priv->extract.qos_key_extract;
- key_profile = &key_extract->key_profile;
- dpkg = &key_extract->dpkg;
- num = key_profile->num;
- key_addr = flow->qos_key_addr;
- mask_addr = flow->qos_mask_addr;
- } else {
- key_extract = &priv->extract.tc_key_extract[tc_id];
- key_profile = &key_extract->key_profile;
- dpkg = &key_extract->dpkg;
- num = key_profile->num;
- key_addr = flow->fs_key_addr;
- mask_addr = flow->fs_mask_addr;
- }
+ if (dist_type == DPAA2_FLOW_QOS_TYPE)
+ tbl_profile = &priv->flow_profile.qos_profile;
+ else
+ tbl_profile = &priv->flow_profile.tc_profile[tc_id];
+
+ key_profile = &tbl_profile->key_profile;
+ dpkg = &tbl_profile->dpkg;
+ num = key_profile->num;
+ key_addr = flow->key_addr;
+ mask_addr = flow->mask_addr;
if (num >= DPKG_MAX_NUM_OF_EXTRACTS) {
DPAA2_PMD_ERR("Number of extracts overflows");
return -EINVAL;
}
- if (key_profile->ip_addr_type == IP_NONE_ADDR_EXTRACT) {
- if (field == NH_FLD_IP_SRC)
- key_profile->ip_addr_type = IP_SRC_EXTRACT;
- else
- key_profile->ip_addr_type = IP_DST_EXTRACT;
- ipaddr_extract_len = size;
-
- key_profile->ip_addr_extract_pos = num;
- if (num > 0) {
- key_profile->ip_addr_extract_off =
- key_profile->key_offset[num - 1] +
- key_profile->key_size[num - 1];
- } else {
- key_profile->ip_addr_extract_off = 0;
- }
- key_profile->key_max_size += NH_FLD_IPV6_ADDR_SIZE;
- } else if (key_profile->ip_addr_type == IP_SRC_EXTRACT) {
- if (field == NH_FLD_IP_SRC) {
- ipaddr_extract_len = size;
- goto rule_configure;
- }
- key_profile->ip_addr_type = IP_SRC_DST_EXTRACT;
- ipaddr_extract_len = size * 2;
- key_profile->key_max_size += NH_FLD_IPV6_ADDR_SIZE;
- } else if (key_profile->ip_addr_type == IP_DST_EXTRACT) {
- if (field == NH_FLD_IP_DST) {
- ipaddr_extract_len = size;
- goto rule_configure;
- }
- key_profile->ip_addr_type = IP_DST_SRC_EXTRACT;
- ipaddr_extract_len = size * 2;
- key_profile->key_max_size += NH_FLD_IPV6_ADDR_SIZE;
+ pos = dpaa2_extract_prev_ip_addr_pos(key_profile);
+ if (pos >= 0) {
+ ip_addr_offset = key_profile->key_offset[pos] +
+ key_profile->key_size[pos];
}
- key_profile->num++;
- key_profile->prot_field[num].type = DPAA2_NET_PROT_KEY;
- dpkg->extracts[num].extract.from_hdr.prot = prot;
- dpkg->extracts[num].extract.from_hdr.field = field;
- dpkg->extracts[num].extract.from_hdr.type = DPKG_FULL_FIELD;
- dpkg->num_extracts++;
+ ret = dpaa2_extract_ip_addr_add(field,
+ key_profile, size, &update, &pos);
+ if (ret) {
+ DPAA2_PMD_ERR("Add IP address extract failed(%d)", ret);
+ return ret;
+ }
+ if (pos > 1) {
+ DPAA2_PMD_ERR("Invalid IP address extract position(%d)", pos);
+ return -EINVAL;
+ }
+ if (update) {
+ key_profile->num++;
+ key_profile->prot_field[num].type = DPAA2_NET_PROT_KEY;
+ key_profile->prot_field[num].prot = prot;
+ key_profile->prot_field[num].key_field = field;
- if (dist_type == DPAA2_FLOW_QOS_TYPE)
- local_cfg = DPAA2_FLOW_QOS_TYPE;
- else
- local_cfg = DPAA2_FLOW_FS_TYPE;
-
-rule_configure:
- key_addr += key_profile->ip_addr_extract_off;
- ip_addr_data = (union ip_addr_extract_rule *)key_addr;
- mask_addr += key_profile->ip_addr_extract_off;
- ip_addr_mask = (union ip_addr_extract_rule *)mask_addr;
-
- if (orig_prot == NET_PROT_IPV4 &&
- orig_field == NH_FLD_IPV4_SRC_IP) {
- if (key_profile->ip_addr_type == IP_SRC_EXTRACT ||
- key_profile->ip_addr_type == IP_SRC_DST_EXTRACT) {
- memcpy(&ip_addr_data->ipv4_sd_addr.ipv4_src,
- key, size);
- memcpy(&ip_addr_mask->ipv4_sd_addr.ipv4_src,
- mask, size);
- } else {
- memcpy(&ip_addr_data->ipv4_ds_addr.ipv4_src,
- key, size);
- memcpy(&ip_addr_mask->ipv4_ds_addr.ipv4_src,
- mask, size);
- }
- } else if (orig_prot == NET_PROT_IPV4 &&
- orig_field == NH_FLD_IPV4_DST_IP) {
- if (key_profile->ip_addr_type == IP_DST_EXTRACT ||
- key_profile->ip_addr_type == IP_DST_SRC_EXTRACT) {
- memcpy(&ip_addr_data->ipv4_ds_addr.ipv4_dst,
- key, size);
- memcpy(&ip_addr_mask->ipv4_ds_addr.ipv4_dst,
- mask, size);
- } else {
- memcpy(&ip_addr_data->ipv4_sd_addr.ipv4_dst,
- key, size);
- memcpy(&ip_addr_mask->ipv4_sd_addr.ipv4_dst,
- mask, size);
- }
- } else if (orig_prot == NET_PROT_IPV6 &&
- orig_field == NH_FLD_IPV6_SRC_IP) {
- if (key_profile->ip_addr_type == IP_SRC_EXTRACT ||
- key_profile->ip_addr_type == IP_SRC_DST_EXTRACT) {
- memcpy(ip_addr_data->ipv6_sd_addr.ipv6_src,
- key, size);
- memcpy(ip_addr_mask->ipv6_sd_addr.ipv6_src,
- mask, size);
- } else {
- memcpy(ip_addr_data->ipv6_ds_addr.ipv6_src,
- key, size);
- memcpy(ip_addr_mask->ipv6_ds_addr.ipv6_src,
- mask, size);
- }
- } else if (orig_prot == NET_PROT_IPV6 &&
- orig_field == NH_FLD_IPV6_DST_IP) {
- if (key_profile->ip_addr_type == IP_DST_EXTRACT ||
- key_profile->ip_addr_type == IP_DST_SRC_EXTRACT) {
- memcpy(ip_addr_data->ipv6_ds_addr.ipv6_dst,
- key, size);
- memcpy(ip_addr_mask->ipv6_ds_addr.ipv6_dst,
- mask, size);
- } else {
- memcpy(ip_addr_data->ipv6_sd_addr.ipv6_dst,
- key, size);
- memcpy(ip_addr_mask->ipv6_sd_addr.ipv6_dst,
- mask, size);
- }
+ dpkg->extracts[num].type = DPKG_EXTRACT_FROM_HDR;
+ dpkg->extracts[num].extract.from_hdr.prot = prot;
+ dpkg->extracts[num].extract.from_hdr.field = field;
+ dpkg->extracts[num].extract.from_hdr.type = DPKG_FULL_FIELD;
+ dpkg->num_extracts++;
+
+ local_cfg = true;
}
- if (dist_type == DPAA2_FLOW_QOS_TYPE) {
- flow->qos_rule_size =
- key_profile->ip_addr_extract_off + ipaddr_extract_len;
+ key_addr += ip_addr_offset;
+ mask_addr += ip_addr_offset;
+
+ if (pos == 0) {
+ rte_memcpy(key_addr, key, size);
+ rte_memcpy(mask_addr, mask, size);
} else {
- flow->fs_rule_size =
- key_profile->ip_addr_extract_off + ipaddr_extract_len;
+ rte_memcpy(key_addr + size, key, size);
+ rte_memcpy(mask_addr + size, mask, size);
}
+ flow->rule_size = ip_addr_offset + size * (pos + 1);
+
if (recfg)
- *recfg |= local_cfg;
+ (*recfg) |= local_cfg;
return 0;
}
+static void dpaa2_flow_hdr_hexdump(char *dump_buf,
+ const uint8_t *hdr, uint32_t size)
+{
+ uint32_t i;
+
+ for (i = 0; i < size; i++)
+ sprintf(&dump_buf[i], "%02x ", hdr[i]);
+}
+
static int
-dpaa2_configure_flow_tunnel_eth(struct dpaa2_dev_flow *flow,
- struct rte_eth_dev *dev,
+dpaa2_flow_tunnel_eth_extract_rule_set(struct dpaa2_generic_flow *flow,
const struct rte_flow_attr *attr,
- const struct rte_flow_item *pattern,
- int *device_configured)
+ const struct rte_flow_item *pattern, int *extract_cfg,
+ enum dpaa2_flow_dist_type dist_type)
{
- int ret, local_cfg = 0;
+ int ret, local_cfg = false;
uint32_t group;
const struct rte_flow_item_eth *spec, *mask;
- struct dpaa2_dev_priv *priv = dev->data->dev_private;
+ struct dpaa2_dev_priv *priv = flow->priv;
const char zero_cmp[RTE_ETHER_ADDR_LEN] = {0};
+ char hex_dump[DPAA2_FLOW_HDR_HEX_DUMP_SIZE];
+
+ if (!pattern->spec)
+ return 0;
group = attr->group;
/* Parse pattern list to get the matching parameters */
spec = pattern->spec;
mask = pattern->mask ?
- pattern->mask : &dpaa2_flow_item_eth_mask;
-
- /* Get traffic class index and flow id to be configured */
- flow->tc_id = group;
- flow->tc_index = attr->priority;
-
- if (!spec)
- return 0;
+ pattern->mask : &dpaa2_flow_item_eth_mask;
ret = dpaa2_flow_extract_support((const uint8_t *)mask,
RTE_FLOW_ITEM_TYPE_ETH);
if (ret) {
- DPAA2_PMD_WARN("Extract field(s) of ethernet failed");
+ dpaa2_flow_hdr_hexdump(hex_dump, (const uint8_t *)mask,
+ sizeof(struct rte_flow_item_eth));
+ DPAA2_PMD_WARN("Extract ethernet(%s) failed(%d)",
+ hex_dump, ret);
return ret;
}
@@ -2128,40 +1940,7 @@ dpaa2_configure_flow_tunnel_eth(struct dpaa2_dev_flow *flow,
DPAA2_VXLAN_IN_SADDR0_OFFSET,
1, &spec->src.addr_bytes[0],
&mask->src.addr_bytes[0],
- priv, group, &local_cfg, DPAA2_FLOW_QOS_TYPE);
- if (ret)
- return ret;
- /*SRC[1:2]*/
- ret = dpaa2_flow_add_pr_extract_rule(flow,
- DPAA2_VXLAN_IN_SADDR1_OFFSET,
- 2, &spec->src.addr_bytes[1],
- &mask->src.addr_bytes[1],
- priv, group, &local_cfg, DPAA2_FLOW_QOS_TYPE);
- if (ret)
- return ret;
- /*SRC[3:1]*/
- ret = dpaa2_flow_add_pr_extract_rule(flow,
- DPAA2_VXLAN_IN_SADDR3_OFFSET,
- 1, &spec->src.addr_bytes[3],
- &mask->src.addr_bytes[3],
- priv, group, &local_cfg, DPAA2_FLOW_QOS_TYPE);
- if (ret)
- return ret;
- /*SRC[4:2]*/
- ret = dpaa2_flow_add_pr_extract_rule(flow,
- DPAA2_VXLAN_IN_SADDR4_OFFSET,
- 2, &spec->src.addr_bytes[4],
- &mask->src.addr_bytes[4],
- priv, group, &local_cfg, DPAA2_FLOW_QOS_TYPE);
- if (ret)
- return ret;
-
- /*SRC[0:1]*/
- ret = dpaa2_flow_add_pr_extract_rule(flow,
- DPAA2_VXLAN_IN_SADDR0_OFFSET,
- 1, &spec->src.addr_bytes[0],
- &mask->src.addr_bytes[0],
- priv, group, &local_cfg, DPAA2_FLOW_FS_TYPE);
+ priv, group, &local_cfg, dist_type);
if (ret)
return ret;
/*SRC[1:2]*/
@@ -2169,7 +1948,7 @@ dpaa2_configure_flow_tunnel_eth(struct dpaa2_dev_flow *flow,
DPAA2_VXLAN_IN_SADDR1_OFFSET,
2, &spec->src.addr_bytes[1],
&mask->src.addr_bytes[1],
- priv, group, &local_cfg, DPAA2_FLOW_FS_TYPE);
+ priv, group, &local_cfg, dist_type);
if (ret)
return ret;
/*SRC[3:1]*/
@@ -2177,7 +1956,7 @@ dpaa2_configure_flow_tunnel_eth(struct dpaa2_dev_flow *flow,
DPAA2_VXLAN_IN_SADDR3_OFFSET,
1, &spec->src.addr_bytes[3],
&mask->src.addr_bytes[3],
- priv, group, &local_cfg, DPAA2_FLOW_FS_TYPE);
+ priv, group, &local_cfg, dist_type);
if (ret)
return ret;
/*SRC[4:2]*/
@@ -2185,7 +1964,7 @@ dpaa2_configure_flow_tunnel_eth(struct dpaa2_dev_flow *flow,
DPAA2_VXLAN_IN_SADDR4_OFFSET,
2, &spec->src.addr_bytes[4],
&mask->src.addr_bytes[4],
- priv, group, &local_cfg, DPAA2_FLOW_FS_TYPE);
+ priv, group, &local_cfg, dist_type);
if (ret)
return ret;
}
@@ -2197,40 +1976,7 @@ dpaa2_configure_flow_tunnel_eth(struct dpaa2_dev_flow *flow,
DPAA2_VXLAN_IN_DADDR0_OFFSET,
1, &spec->dst.addr_bytes[0],
&mask->dst.addr_bytes[0],
- priv, group, &local_cfg, DPAA2_FLOW_QOS_TYPE);
- if (ret)
- return ret;
- /*DST[1:1]*/
- ret = dpaa2_flow_add_pr_extract_rule(flow,
- DPAA2_VXLAN_IN_DADDR1_OFFSET,
- 1, &spec->dst.addr_bytes[1],
- &mask->dst.addr_bytes[1],
- priv, group, &local_cfg, DPAA2_FLOW_QOS_TYPE);
- if (ret)
- return ret;
- /*DST[2:3]*/
- ret = dpaa2_flow_add_pr_extract_rule(flow,
- DPAA2_VXLAN_IN_DADDR2_OFFSET,
- 3, &spec->dst.addr_bytes[2],
- &mask->dst.addr_bytes[2],
- priv, group, &local_cfg, DPAA2_FLOW_QOS_TYPE);
- if (ret)
- return ret;
- /*DST[5:1]*/
- ret = dpaa2_flow_add_pr_extract_rule(flow,
- DPAA2_VXLAN_IN_DADDR5_OFFSET,
- 1, &spec->dst.addr_bytes[5],
- &mask->dst.addr_bytes[5],
- priv, group, &local_cfg, DPAA2_FLOW_QOS_TYPE);
- if (ret)
- return ret;
-
- /*DST[0:1]*/
- ret = dpaa2_flow_add_pr_extract_rule(flow,
- DPAA2_VXLAN_IN_DADDR0_OFFSET,
- 1, &spec->dst.addr_bytes[0],
- &mask->dst.addr_bytes[0],
- priv, group, &local_cfg, DPAA2_FLOW_FS_TYPE);
+ priv, group, &local_cfg, dist_type);
if (ret)
return ret;
/*DST[1:1]*/
@@ -2238,7 +1984,7 @@ dpaa2_configure_flow_tunnel_eth(struct dpaa2_dev_flow *flow,
DPAA2_VXLAN_IN_DADDR1_OFFSET,
1, &spec->dst.addr_bytes[1],
&mask->dst.addr_bytes[1],
- priv, group, &local_cfg, DPAA2_FLOW_FS_TYPE);
+ priv, group, &local_cfg, dist_type);
if (ret)
return ret;
/*DST[2:3]*/
@@ -2246,7 +1992,7 @@ dpaa2_configure_flow_tunnel_eth(struct dpaa2_dev_flow *flow,
DPAA2_VXLAN_IN_DADDR2_OFFSET,
3, &spec->dst.addr_bytes[2],
&mask->dst.addr_bytes[2],
- priv, group, &local_cfg, DPAA2_FLOW_FS_TYPE);
+ priv, group, &local_cfg, dist_type);
if (ret)
return ret;
/*DST[5:1]*/
@@ -2254,7 +2000,7 @@ dpaa2_configure_flow_tunnel_eth(struct dpaa2_dev_flow *flow,
DPAA2_VXLAN_IN_DADDR5_OFFSET,
1, &spec->dst.addr_bytes[5],
&mask->dst.addr_bytes[5],
- priv, group, &local_cfg, DPAA2_FLOW_FS_TYPE);
+ priv, group, &local_cfg, dist_type);
if (ret)
return ret;
}
@@ -2264,76 +2010,65 @@ dpaa2_configure_flow_tunnel_eth(struct dpaa2_dev_flow *flow,
ret = dpaa2_flow_add_pr_extract_rule(flow,
DPAA2_VXLAN_IN_TYPE_OFFSET,
sizeof(rte_be16_t), &spec->type, &mask->type,
- priv, group, &local_cfg, DPAA2_FLOW_QOS_TYPE);
- if (ret)
- return ret;
- ret = dpaa2_flow_add_pr_extract_rule(flow,
- DPAA2_VXLAN_IN_TYPE_OFFSET,
- sizeof(rte_be16_t), &spec->type, &mask->type,
- priv, group, &local_cfg, DPAA2_FLOW_FS_TYPE);
+ priv, group, &local_cfg, dist_type);
if (ret)
return ret;
}
- (*device_configured) |= local_cfg;
+ if (extract_cfg)
+ (*extract_cfg) |= local_cfg;
return 0;
}
static int
-dpaa2_configure_flow_eth(struct dpaa2_dev_flow *flow,
- struct rte_eth_dev *dev,
+dpaa2_flow_eth_extract_rule_set(struct dpaa2_generic_flow *flow,
const struct rte_flow_attr *attr,
const struct rte_dpaa2_flow_item *dpaa2_pattern,
- const struct rte_flow_action actions[] __rte_unused,
- struct rte_flow_error *error __rte_unused,
- int *device_configured)
+ int *extract_cfg, enum dpaa2_flow_dist_type dist_type)
{
int ret, local_cfg = 0;
- uint32_t group;
+ uint32_t bit_offset;
const struct rte_flow_item_eth *spec, *mask;
- struct dpaa2_dev_priv *priv = dev->data->dev_private;
+ struct dpaa2_dev_priv *priv = flow->priv;
const char zero_cmp[RTE_ETHER_ADDR_LEN] = {0};
const struct rte_flow_item *pattern =
&dpaa2_pattern->generic_item;
+ char hex_dump[DPAA2_FLOW_HDR_HEX_DUMP_SIZE];
if (dpaa2_pattern->in_tunnel) {
- return dpaa2_configure_flow_tunnel_eth(flow,
- dev, attr, pattern, device_configured);
+ return dpaa2_flow_tunnel_eth_extract_rule_set(flow,
+ attr, pattern, extract_cfg,
+ dist_type);
}
- group = attr->group;
-
/* Parse pattern list to get the matching parameters */
spec = pattern->spec;
mask = pattern->mask ?
- pattern->mask : &dpaa2_flow_item_eth_mask;
-
- /* Get traffic class index and flow id to be configured */
- flow->tc_id = group;
- flow->tc_index = attr->priority;
+ pattern->mask : &dpaa2_flow_item_eth_mask;
if (!spec) {
- ret = dpaa2_flow_identify_by_faf(priv, flow,
- FAF_ETH_FRAM, DPAA2_FLOW_QOS_TYPE,
- group, &local_cfg);
+ ret = dpaa2_protocol_psr_bit_offset(&bit_offset,
+ DPAA2_PARSER_MAC_ID);
if (ret)
return ret;
ret = dpaa2_flow_identify_by_faf(priv, flow,
- FAF_ETH_FRAM, DPAA2_FLOW_FS_TYPE,
- group, &local_cfg);
- if (ret)
- return ret;
+ bit_offset, dist_type,
+ attr->group, &local_cfg);
+ if (extract_cfg && !ret)
+ (*extract_cfg) |= local_cfg;
- (*device_configured) |= local_cfg;
- return 0;
+ return ret;
}
ret = dpaa2_flow_extract_support((const uint8_t *)mask,
RTE_FLOW_ITEM_TYPE_ETH);
if (ret) {
- DPAA2_PMD_WARN("Extract field(s) of ethernet failed");
+ dpaa2_flow_hdr_hexdump(hex_dump, (const uint8_t *)mask,
+ sizeof(struct rte_flow_item_eth));
+ DPAA2_PMD_WARN("Extract ethernet(%s) failed(%d)",
+ hex_dump, ret);
return ret;
}
@@ -2343,14 +2078,7 @@ dpaa2_configure_flow_eth(struct dpaa2_dev_flow *flow,
ret = dpaa2_flow_add_hdr_extract_rule(flow, NET_PROT_ETH,
NH_FLD_ETH_SA, &spec->src.addr_bytes,
&mask->src.addr_bytes, RTE_ETHER_ADDR_LEN,
- priv, group, &local_cfg, DPAA2_FLOW_QOS_TYPE);
- if (ret)
- return ret;
-
- ret = dpaa2_flow_add_hdr_extract_rule(flow, NET_PROT_ETH,
- NH_FLD_ETH_SA, &spec->src.addr_bytes,
- &mask->src.addr_bytes, RTE_ETHER_ADDR_LEN,
- priv, group, &local_cfg, DPAA2_FLOW_FS_TYPE);
+ priv, attr->group, &local_cfg, dist_type);
if (ret)
return ret;
}
@@ -2360,14 +2088,7 @@ dpaa2_configure_flow_eth(struct dpaa2_dev_flow *flow,
ret = dpaa2_flow_add_hdr_extract_rule(flow, NET_PROT_ETH,
NH_FLD_ETH_DA, &spec->dst.addr_bytes,
&mask->dst.addr_bytes, RTE_ETHER_ADDR_LEN,
- priv, group, &local_cfg, DPAA2_FLOW_QOS_TYPE);
- if (ret)
- return ret;
-
- ret = dpaa2_flow_add_hdr_extract_rule(flow, NET_PROT_ETH,
- NH_FLD_ETH_DA, &spec->dst.addr_bytes,
- &mask->dst.addr_bytes, RTE_ETHER_ADDR_LEN,
- priv, group, &local_cfg, DPAA2_FLOW_FS_TYPE);
+ priv, attr->group, &local_cfg, dist_type);
if (ret)
return ret;
}
@@ -2377,34 +2098,28 @@ dpaa2_configure_flow_eth(struct dpaa2_dev_flow *flow,
ret = dpaa2_flow_add_hdr_extract_rule(flow, NET_PROT_ETH,
NH_FLD_ETH_TYPE, &spec->type,
&mask->type, sizeof(rte_be16_t),
- priv, group, &local_cfg, DPAA2_FLOW_QOS_TYPE);
- if (ret)
- return ret;
-
- ret = dpaa2_flow_add_hdr_extract_rule(flow, NET_PROT_ETH,
- NH_FLD_ETH_TYPE, &spec->type,
- &mask->type, sizeof(rte_be16_t),
- priv, group, &local_cfg, DPAA2_FLOW_FS_TYPE);
+ priv, attr->group, &local_cfg, dist_type);
if (ret)
return ret;
}
- (*device_configured) |= local_cfg;
+ if (extract_cfg)
+ (*extract_cfg) |= local_cfg;
return 0;
}
static int
-dpaa2_configure_flow_tunnel_vlan(struct dpaa2_dev_flow *flow,
- struct rte_eth_dev *dev,
+dpaa2_flow_tunnel_vlan_extract_rule_set(struct dpaa2_generic_flow *flow,
const struct rte_flow_attr *attr,
- const struct rte_flow_item *pattern,
- int *device_configured)
+ const struct rte_flow_item *pattern, int *extract_cfg,
+ enum dpaa2_flow_dist_type dist_type)
{
- int ret, local_cfg = 0;
- uint32_t group;
+ int ret, local_cfg = false;
+ uint32_t group, bit_offset;
const struct rte_flow_item_vlan *spec, *mask;
- struct dpaa2_dev_priv *priv = dev->data->dev_private;
+ struct dpaa2_dev_priv *priv = flow->priv;
+ char hex_dump[DPAA2_FLOW_HDR_HEX_DUMP_SIZE];
group = attr->group;
@@ -2413,33 +2128,30 @@ dpaa2_configure_flow_tunnel_vlan(struct dpaa2_dev_flow *flow,
mask = pattern->mask ?
pattern->mask : &dpaa2_flow_item_vlan_mask;
- /* Get traffic class index and flow id to be configured */
- flow->tc_id = group;
- flow->tc_index = attr->priority;
-
if (!spec) {
- ret = dpaa2_flow_identify_by_faf(priv, flow,
- FAFE_VXLAN_IN_VLAN_FRAM,
- DPAA2_FLOW_QOS_TYPE,
- group, &local_cfg);
+ ret = dpaa2_protocol_psr_bit_offset(&bit_offset,
+ DPAA2_PARSER_TUNNEL_VLAN_ID);
if (ret)
return ret;
ret = dpaa2_flow_identify_by_faf(priv, flow,
- FAFE_VXLAN_IN_VLAN_FRAM,
- DPAA2_FLOW_FS_TYPE,
- group, &local_cfg);
+ bit_offset, dist_type,
+ attr->group, &local_cfg);
if (ret)
return ret;
- (*device_configured) |= local_cfg;
+ if (extract_cfg)
+ (*extract_cfg) |= local_cfg;
return 0;
}
ret = dpaa2_flow_extract_support((const uint8_t *)mask,
RTE_FLOW_ITEM_TYPE_VLAN);
if (ret) {
- DPAA2_PMD_WARN("Extract field(s) of vlan not support.");
+ dpaa2_flow_hdr_hexdump(hex_dump, (const uint8_t *)mask,
+ sizeof(struct rte_flow_item_vlan));
+ DPAA2_PMD_WARN("Extract vlan(%s) failed(%d)",
+ hex_dump, ret);
return ret;
}
@@ -2450,74 +2162,64 @@ dpaa2_configure_flow_tunnel_vlan(struct dpaa2_dev_flow *flow,
ret = dpaa2_flow_add_pr_extract_rule(flow,
DPAA2_VXLAN_IN_TCI_OFFSET,
sizeof(rte_be16_t), &spec->tci, &mask->tci,
- priv, group, &local_cfg, DPAA2_FLOW_QOS_TYPE);
- if (ret)
- return ret;
-
- ret = dpaa2_flow_add_pr_extract_rule(flow,
- DPAA2_VXLAN_IN_TCI_OFFSET,
- sizeof(rte_be16_t), &spec->tci, &mask->tci,
- priv, group, &local_cfg, DPAA2_FLOW_FS_TYPE);
+ priv, group, &local_cfg, dist_type);
if (ret)
return ret;
- (*device_configured) |= local_cfg;
+ if (extract_cfg)
+ (*extract_cfg) |= local_cfg;
return 0;
}
static int
-dpaa2_configure_flow_vlan(struct dpaa2_dev_flow *flow,
- struct rte_eth_dev *dev,
+dpaa2_flow_vlan_extract_rule_set(struct dpaa2_generic_flow *flow,
const struct rte_flow_attr *attr,
const struct rte_dpaa2_flow_item *dpaa2_pattern,
- const struct rte_flow_action actions[] __rte_unused,
- struct rte_flow_error *error __rte_unused,
- int *device_configured)
+ int *extract_cfg, enum dpaa2_flow_dist_type dist_type)
{
int ret, local_cfg = 0;
- uint32_t group;
+ uint32_t bit_offset;
const struct rte_flow_item_vlan *spec, *mask;
- struct dpaa2_dev_priv *priv = dev->data->dev_private;
+ struct dpaa2_dev_priv *priv = flow->priv;
const struct rte_flow_item *pattern =
&dpaa2_pattern->generic_item;
+ char hex_dump[DPAA2_FLOW_HDR_HEX_DUMP_SIZE];
if (dpaa2_pattern->in_tunnel) {
- return dpaa2_configure_flow_tunnel_vlan(flow,
- dev, attr, pattern, device_configured);
+ return dpaa2_flow_tunnel_vlan_extract_rule_set(flow,
+ attr, pattern, extract_cfg,
+ dist_type);
}
- group = attr->group;
-
/* Parse pattern list to get the matching parameters */
spec = pattern->spec;
mask = pattern->mask ? pattern->mask : &dpaa2_flow_item_vlan_mask;
- /* Get traffic class index and flow id to be configured */
- flow->tc_id = group;
- flow->tc_index = attr->priority;
-
- if (!spec) {
- ret = dpaa2_flow_identify_by_faf(priv, flow, FAF_VLAN_FRAM,
- DPAA2_FLOW_QOS_TYPE, group,
- &local_cfg);
- if (ret)
- return ret;
+ ret = dpaa2_protocol_psr_bit_offset(&bit_offset,
+ DPAA2_PARSER_VLAN_ID);
+ if (ret)
+ return ret;
- ret = dpaa2_flow_identify_by_faf(priv, flow, FAF_VLAN_FRAM,
- DPAA2_FLOW_FS_TYPE, group,
- &local_cfg);
- if (ret)
- return ret;
+ ret = dpaa2_flow_identify_by_faf(priv, flow,
+ bit_offset, dist_type, attr->group, &local_cfg);
+ if (ret)
+ return ret;
- (*device_configured) |= local_cfg;
+ if (!spec) {
+ if (extract_cfg)
+ (*extract_cfg) |= local_cfg;
return 0;
}
ret = dpaa2_flow_extract_support((const uint8_t *)mask,
RTE_FLOW_ITEM_TYPE_VLAN);
if (ret) {
- DPAA2_PMD_WARN("Extract field(s) of vlan not support.");
+ dpaa2_flow_hdr_hexdump(hex_dump, (const uint8_t *)mask,
+ sizeof(struct rte_flow_item_vlan));
+ DPAA2_PMD_WARN("Extract vlan(%s) failed(%d)",
+ hex_dump, ret);
+
return ret;
}
@@ -2527,45 +2229,34 @@ dpaa2_configure_flow_vlan(struct dpaa2_dev_flow *flow,
ret = dpaa2_flow_add_hdr_extract_rule(flow, NET_PROT_VLAN,
NH_FLD_VLAN_TCI, &spec->tci,
&mask->tci, sizeof(rte_be16_t),
- priv, group, &local_cfg, DPAA2_FLOW_QOS_TYPE);
- if (ret)
- return ret;
-
- ret = dpaa2_flow_add_hdr_extract_rule(flow, NET_PROT_VLAN,
- NH_FLD_VLAN_TCI, &spec->tci,
- &mask->tci, sizeof(rte_be16_t),
- priv, group, &local_cfg,
- DPAA2_FLOW_FS_TYPE);
+ priv, attr->group, &local_cfg, dist_type);
if (ret)
return ret;
- (*device_configured) |= local_cfg;
+ if (extract_cfg)
+ (*extract_cfg) |= local_cfg;
return 0;
}
static int
-dpaa2_configure_flow_ipv4(struct dpaa2_dev_flow *flow,
- struct rte_eth_dev *dev,
+dpaa2_flow_ipv4_extract_rule_set(struct dpaa2_generic_flow *flow,
const struct rte_flow_attr *attr,
const struct rte_dpaa2_flow_item *dpaa2_pattern,
- const struct rte_flow_action actions[] __rte_unused,
- struct rte_flow_error *error __rte_unused,
- int *device_configured)
+ int *extract_cfg, enum dpaa2_flow_dist_type dist_type)
{
int ret, local_cfg = 0;
- uint32_t group;
+ uint32_t bit_offset;
const struct rte_flow_item_ipv4 *spec_ipv4 = 0, *mask_ipv4 = 0;
const void *key, *mask;
- struct dpaa2_dev_priv *priv = dev->data->dev_private;
+ struct dpaa2_dev_priv *priv = flow->priv;
int size;
const struct rte_flow_item *pattern = &dpaa2_pattern->generic_item;
-
- group = attr->group;
+ char hex_dump[DPAA2_FLOW_HDR_HEX_DUMP_SIZE];
/* Parse pattern list to get the matching parameters */
spec_ipv4 = pattern->spec;
mask_ipv4 = pattern->mask ?
- pattern->mask : &dpaa2_flow_item_ipv4_mask;
+ pattern->mask : &dpaa2_flow_item_ipv4_mask;
if (dpaa2_pattern->in_tunnel) {
if (spec_ipv4) {
@@ -2573,44 +2264,48 @@ dpaa2_configure_flow_ipv4(struct dpaa2_dev_flow *flow,
return -ENOTSUP;
}
- ret = dpaa2_flow_identify_by_faf(priv, flow,
- FAFE_VXLAN_IN_IPV4_FRAM,
- DPAA2_FLOW_QOS_TYPE, group,
- &local_cfg);
+ ret = dpaa2_protocol_psr_bit_offset(&bit_offset,
+ DPAA2_PARSER_TUNNEL_IPV4_ID);
if (ret)
return ret;
ret = dpaa2_flow_identify_by_faf(priv, flow,
- FAFE_VXLAN_IN_IPV4_FRAM,
- DPAA2_FLOW_FS_TYPE, group,
- &local_cfg);
- return ret;
+ bit_offset, dist_type,
+ attr->group, &local_cfg);
+ if (ret)
+ return ret;
}
- /* Get traffic class index and flow id to be configured */
- flow->tc_id = group;
- flow->tc_index = attr->priority;
-
- ret = dpaa2_flow_identify_by_faf(priv, flow, FAF_IPV4_FRAM,
- DPAA2_FLOW_QOS_TYPE, group,
- &local_cfg);
+ ret = dpaa2_protocol_psr_bit_offset(&bit_offset,
+ DPAA2_PARSER_IPV4_ID);
if (ret)
return ret;
- ret = dpaa2_flow_identify_by_faf(priv, flow, FAF_IPV4_FRAM,
- DPAA2_FLOW_FS_TYPE, group, &local_cfg);
+ ret = dpaa2_flow_identify_by_faf(priv, flow,
+ bit_offset, dist_type,
+ attr->group, &local_cfg);
if (ret)
return ret;
if (!spec_ipv4) {
- (*device_configured) |= local_cfg;
+ if (flow->ip_key == NET_PROT_IPV6) {
+ DPAA2_PMD_ERR("IPv6 flow has been configured");
+ return -EINVAL;
+ }
+ flow->ip_key = NET_PROT_IPV4;
+ if (extract_cfg)
+ (*extract_cfg) |= local_cfg;
return 0;
}
ret = dpaa2_flow_extract_support((const uint8_t *)mask_ipv4,
RTE_FLOW_ITEM_TYPE_IPV4);
if (ret) {
- DPAA2_PMD_WARN("Extract field(s) of IPv4 not support.");
+ dpaa2_flow_hdr_hexdump(hex_dump, (const uint8_t *)mask_ipv4,
+ sizeof(struct rte_flow_item_ipv4));
+ DPAA2_PMD_WARN("Extract IPv4(%s) failed(%d)",
+ hex_dump, ret);
+
return ret;
}
@@ -2620,20 +2315,11 @@ dpaa2_configure_flow_ipv4(struct dpaa2_dev_flow *flow,
size = sizeof(rte_be32_t);
ret = dpaa2_flow_add_ipaddr_extract_rule(flow, NET_PROT_IPV4,
- NH_FLD_IPV4_SRC_IP,
- key, mask, size, priv,
- group, &local_cfg,
- DPAA2_FLOW_QOS_TYPE);
- if (ret)
- return ret;
-
- ret = dpaa2_flow_add_ipaddr_extract_rule(flow, NET_PROT_IPV4,
- NH_FLD_IPV4_SRC_IP,
- key, mask, size, priv,
- group, &local_cfg,
- DPAA2_FLOW_FS_TYPE);
+ NH_FLD_IPV4_SRC_IP, key, mask, size, priv,
+ attr->group, &local_cfg, dist_type);
if (ret)
return ret;
+ flow->ip_src = NET_PROT_IPV4;
}
if (mask_ipv4->hdr.dst_addr) {
@@ -2642,19 +2328,41 @@ dpaa2_configure_flow_ipv4(struct dpaa2_dev_flow *flow,
size = sizeof(rte_be32_t);
ret = dpaa2_flow_add_ipaddr_extract_rule(flow, NET_PROT_IPV4,
- NH_FLD_IPV4_DST_IP,
- key, mask, size, priv,
- group, &local_cfg,
- DPAA2_FLOW_QOS_TYPE);
+ NH_FLD_IPV4_DST_IP, key, mask, size, priv,
+ attr->group, &local_cfg, dist_type);
if (ret)
return ret;
- ret = dpaa2_flow_add_ipaddr_extract_rule(flow, NET_PROT_IPV4,
- NH_FLD_IPV4_DST_IP,
- key, mask, size, priv,
- group, &local_cfg,
- DPAA2_FLOW_FS_TYPE);
+ flow->ip_dst = NET_PROT_IPV4;
+ }
+
+ if (mask_ipv4->hdr.packet_id) {
+ key = &spec_ipv4->hdr.packet_id;
+ mask = &mask_ipv4->hdr.packet_id;
+ size = sizeof(rte_be16_t);
+ ret = dpaa2_flow_add_hdr_extract_rule(flow, NET_PROT_IP,
+ NH_FLD_IP_ID, key, mask, size,
+ priv, attr->group, &local_cfg, dist_type);
+ if (ret)
+ return ret;
+ }
+
+ if (mask_ipv4->hdr.fragment_offset) {
+ key = &spec_ipv4->hdr.fragment_offset;
+ mask = &mask_ipv4->hdr.fragment_offset;
+ size = sizeof(rte_be16_t);
+
+ ret = dpaa2_protocol_psr_bit_offset(&bit_offset,
+ DPAA2_PARSER_IP_FRAG_ID);
+ if (ret)
+ return ret;
+
+ ret = dpaa2_flow_identify_by_faf(priv, flow,
+ bit_offset, dist_type, attr->group, &local_cfg);
if (ret)
return ret;
+
+ if (spec_ipv4->hdr.fragment_offset)
+ DPAA2_PMD_WARN("Unsupport Extract of frag offset");
}
if (mask_ipv4->hdr.next_proto_id) {
@@ -2663,139 +2371,117 @@ dpaa2_configure_flow_ipv4(struct dpaa2_dev_flow *flow,
size = sizeof(uint8_t);
ret = dpaa2_flow_add_hdr_extract_rule(flow, NET_PROT_IP,
- NH_FLD_IP_PROTO, key,
- mask, size, priv, group,
- &local_cfg,
- DPAA2_FLOW_QOS_TYPE);
- if (ret)
- return ret;
-
- ret = dpaa2_flow_add_hdr_extract_rule(flow, NET_PROT_IP,
- NH_FLD_IP_PROTO, key,
- mask, size, priv, group,
- &local_cfg,
- DPAA2_FLOW_FS_TYPE);
+ NH_FLD_IP_PROTO, key, mask, size, priv, attr->group,
+ &local_cfg, dist_type);
if (ret)
return ret;
}
+ if (flow->ip_key == NET_PROT_IPV6) {
+ DPAA2_PMD_ERR("IPv6 flow has been configured");
+ return -EINVAL;
+ }
+ flow->ip_key = NET_PROT_IPV4;
- (*device_configured) |= local_cfg;
+ if (extract_cfg)
+ (*extract_cfg) |= local_cfg;
return 0;
}
static int
-dpaa2_configure_flow_ipv6(struct dpaa2_dev_flow *flow,
- struct rte_eth_dev *dev,
+dpaa2_flow_ipv6_extract_rule_set(struct dpaa2_generic_flow *flow,
const struct rte_flow_attr *attr,
const struct rte_dpaa2_flow_item *dpaa2_pattern,
- const struct rte_flow_action actions[] __rte_unused,
- struct rte_flow_error *error __rte_unused,
- int *device_configured)
+ int *extract_cfg, enum dpaa2_flow_dist_type dist_type)
{
int ret, local_cfg = 0;
- uint32_t group;
+ uint32_t bit_offset;
const struct rte_flow_item_ipv6 *spec_ipv6 = 0, *mask_ipv6 = 0;
const void *key, *mask;
- struct dpaa2_dev_priv *priv = dev->data->dev_private;
+ struct dpaa2_dev_priv *priv = flow->priv;
const char zero_cmp[NH_FLD_IPV6_ADDR_SIZE] = {0};
int size;
const struct rte_flow_item *pattern = &dpaa2_pattern->generic_item;
-
- group = attr->group;
+ char hex_dump[DPAA2_FLOW_HDR_HEX_DUMP_SIZE];
/* Parse pattern list to get the matching parameters */
spec_ipv6 = pattern->spec;
mask_ipv6 = pattern->mask ? pattern->mask : &dpaa2_flow_item_ipv6_mask;
- /* Get traffic class index and flow id to be configured */
- flow->tc_id = group;
- flow->tc_index = attr->priority;
-
if (dpaa2_pattern->in_tunnel) {
if (spec_ipv6) {
DPAA2_PMD_ERR("Tunnel-IPv6 distribution not support");
return -ENOTSUP;
}
- ret = dpaa2_flow_identify_by_faf(priv, flow,
- FAFE_VXLAN_IN_IPV6_FRAM,
- DPAA2_FLOW_QOS_TYPE, group,
- &local_cfg);
+ ret = dpaa2_protocol_psr_bit_offset(&bit_offset,
+ DPAA2_PARSER_TUNNEL_IPV6_ID);
if (ret)
return ret;
ret = dpaa2_flow_identify_by_faf(priv, flow,
- FAFE_VXLAN_IN_IPV6_FRAM,
- DPAA2_FLOW_FS_TYPE, group,
- &local_cfg);
- return ret;
+ bit_offset, dist_type,
+ attr->group, &local_cfg);
+ if (ret)
+ return ret;
}
- ret = dpaa2_flow_identify_by_faf(priv, flow, FAF_IPV6_FRAM,
- DPAA2_FLOW_QOS_TYPE, group,
- &local_cfg);
+ ret = dpaa2_protocol_psr_bit_offset(&bit_offset,
+ DPAA2_PARSER_IPV6_ID);
if (ret)
return ret;
- ret = dpaa2_flow_identify_by_faf(priv, flow, FAF_IPV6_FRAM,
- DPAA2_FLOW_FS_TYPE, group, &local_cfg);
+ ret = dpaa2_flow_identify_by_faf(priv, flow,
+ bit_offset, dist_type, attr->group, &local_cfg);
if (ret)
return ret;
if (!spec_ipv6) {
- (*device_configured) |= local_cfg;
+ if (flow->ip_key == NET_PROT_IPV4) {
+ DPAA2_PMD_ERR("IPv4 flow has been configured");
+ return -EINVAL;
+ }
+ flow->ip_key = NET_PROT_IPV6;
+
+ if (extract_cfg)
+ (*extract_cfg) |= local_cfg;
return 0;
}
ret = dpaa2_flow_extract_support((const uint8_t *)mask_ipv6,
RTE_FLOW_ITEM_TYPE_IPV6);
if (ret) {
- DPAA2_PMD_WARN("Extract field(s) of IPv6 not support.");
+ dpaa2_flow_hdr_hexdump(hex_dump, (const uint8_t *)mask_ipv6,
+ sizeof(struct rte_flow_item_ipv6));
+ DPAA2_PMD_WARN("Extract IPv6(%s) failed(%d)",
+ hex_dump, ret);
+
return ret;
}
- if (memcmp((const char *)&mask_ipv6->hdr.src_addr, zero_cmp, NH_FLD_IPV6_ADDR_SIZE)) {
+ if (memcmp((const void *)&mask_ipv6->hdr.src_addr, zero_cmp, NH_FLD_IPV6_ADDR_SIZE)) {
key = &spec_ipv6->hdr.src_addr;
mask = &mask_ipv6->hdr.src_addr;
size = NH_FLD_IPV6_ADDR_SIZE;
ret = dpaa2_flow_add_ipaddr_extract_rule(flow, NET_PROT_IPV6,
- NH_FLD_IPV6_SRC_IP,
- key, mask, size, priv,
- group, &local_cfg,
- DPAA2_FLOW_QOS_TYPE);
- if (ret)
- return ret;
-
- ret = dpaa2_flow_add_ipaddr_extract_rule(flow, NET_PROT_IPV6,
- NH_FLD_IPV6_SRC_IP,
- key, mask, size, priv,
- group, &local_cfg,
- DPAA2_FLOW_FS_TYPE);
+ NH_FLD_IPV6_SRC_IP, key, mask, size, priv,
+ attr->group, &local_cfg, dist_type);
if (ret)
return ret;
+ flow->ip_src = NET_PROT_IPV6;
}
- if (memcmp((const char *)&mask_ipv6->hdr.dst_addr, zero_cmp, NH_FLD_IPV6_ADDR_SIZE)) {
+ if (memcmp((const void *)&mask_ipv6->hdr.dst_addr, zero_cmp, NH_FLD_IPV6_ADDR_SIZE)) {
key = &spec_ipv6->hdr.dst_addr;
mask = &mask_ipv6->hdr.dst_addr;
size = NH_FLD_IPV6_ADDR_SIZE;
ret = dpaa2_flow_add_ipaddr_extract_rule(flow, NET_PROT_IPV6,
- NH_FLD_IPV6_DST_IP,
- key, mask, size, priv,
- group, &local_cfg,
- DPAA2_FLOW_QOS_TYPE);
- if (ret)
- return ret;
-
- ret = dpaa2_flow_add_ipaddr_extract_rule(flow, NET_PROT_IPV6,
- NH_FLD_IPV6_DST_IP,
- key, mask, size, priv,
- group, &local_cfg,
- DPAA2_FLOW_FS_TYPE);
+ NH_FLD_IPV6_DST_IP, key, mask, size, priv,
+ attr->group, &local_cfg, dist_type);
if (ret)
return ret;
+ flow->ip_dst = NET_PROT_IPV6;
}
if (mask_ipv6->hdr.proto) {
@@ -2804,78 +2490,68 @@ dpaa2_configure_flow_ipv6(struct dpaa2_dev_flow *flow,
size = sizeof(uint8_t);
ret = dpaa2_flow_add_hdr_extract_rule(flow, NET_PROT_IP,
- NH_FLD_IP_PROTO, key,
- mask, size, priv, group,
- &local_cfg,
- DPAA2_FLOW_QOS_TYPE);
- if (ret)
- return ret;
-
- ret = dpaa2_flow_add_hdr_extract_rule(flow, NET_PROT_IP,
- NH_FLD_IP_PROTO, key,
- mask, size, priv, group,
- &local_cfg,
- DPAA2_FLOW_FS_TYPE);
+ NH_FLD_IP_PROTO, key, mask, size, priv, attr->group,
+ &local_cfg, dist_type);
if (ret)
return ret;
}
+ if (flow->ip_key == NET_PROT_IPV4) {
+ DPAA2_PMD_ERR("IPv4 flow has been configured");
+ return -EINVAL;
+ }
+ flow->ip_key = NET_PROT_IPV6;
- (*device_configured) |= local_cfg;
+ if (extract_cfg)
+ (*extract_cfg) |= local_cfg;
return 0;
}
static int
-dpaa2_configure_flow_icmp(struct dpaa2_dev_flow *flow,
- struct rte_eth_dev *dev,
+dpaa2_flow_icmp_extract_rule_set(struct dpaa2_generic_flow *flow,
const struct rte_flow_attr *attr,
const struct rte_dpaa2_flow_item *dpaa2_pattern,
- const struct rte_flow_action actions[] __rte_unused,
- struct rte_flow_error *error __rte_unused,
- int *device_configured)
+ int *extract_cfg, enum dpaa2_flow_dist_type dist_type)
{
int ret, local_cfg = 0;
- uint32_t group;
+ uint32_t bit_offset;
const struct rte_flow_item_icmp *spec, *mask;
- struct dpaa2_dev_priv *priv = dev->data->dev_private;
+ struct dpaa2_dev_priv *priv = flow->priv;
const struct rte_flow_item *pattern = &dpaa2_pattern->generic_item;
-
- group = attr->group;
+ char hex_dump[DPAA2_FLOW_HDR_HEX_DUMP_SIZE];
/* Parse pattern list to get the matching parameters */
spec = pattern->spec;
mask = pattern->mask ?
pattern->mask : &dpaa2_flow_item_icmp_mask;
- /* Get traffic class index and flow id to be configured */
- flow->tc_id = group;
- flow->tc_index = attr->priority;
-
if (dpaa2_pattern->in_tunnel) {
DPAA2_PMD_ERR("Tunnel-ICMP distribution not support");
return -ENOTSUP;
}
if (!spec) {
- ret = dpaa2_flow_identify_by_faf(priv, flow,
- FAF_ICMP_FRAM, DPAA2_FLOW_QOS_TYPE,
- group, &local_cfg);
+ ret = dpaa2_protocol_psr_bit_offset(&bit_offset,
+ DPAA2_PARSER_ICMP_ID);
if (ret)
return ret;
ret = dpaa2_flow_identify_by_faf(priv, flow,
- FAF_ICMP_FRAM, DPAA2_FLOW_FS_TYPE,
- group, &local_cfg);
+ bit_offset, dist_type, attr->group, &local_cfg);
if (ret)
return ret;
- (*device_configured) |= local_cfg;
+ if (extract_cfg)
+ (*extract_cfg) |= local_cfg;
return 0;
}
ret = dpaa2_flow_extract_support((const uint8_t *)mask,
RTE_FLOW_ITEM_TYPE_ICMP);
if (ret) {
- DPAA2_PMD_WARN("Extract field(s) of ICMP not support.");
+ dpaa2_flow_hdr_hexdump(hex_dump, (const uint8_t *)mask,
+ sizeof(struct rte_flow_item_icmp));
+ DPAA2_PMD_WARN("Extract ICMP(%s) failed(%d)",
+ hex_dump, ret);
return ret;
}
@@ -2884,14 +2560,7 @@ dpaa2_configure_flow_icmp(struct dpaa2_dev_flow *flow,
ret = dpaa2_flow_add_hdr_extract_rule(flow, NET_PROT_ICMP,
NH_FLD_ICMP_TYPE, &spec->hdr.icmp_type,
&mask->hdr.icmp_type, sizeof(uint8_t),
- priv, group, &local_cfg, DPAA2_FLOW_QOS_TYPE);
- if (ret)
- return ret;
-
- ret = dpaa2_flow_add_hdr_extract_rule(flow, NET_PROT_ICMP,
- NH_FLD_ICMP_TYPE, &spec->hdr.icmp_type,
- &mask->hdr.icmp_type, sizeof(uint8_t),
- priv, group, &local_cfg, DPAA2_FLOW_FS_TYPE);
+ priv, attr->group, &local_cfg, dist_type);
if (ret)
return ret;
}
@@ -2900,90 +2569,75 @@ dpaa2_configure_flow_icmp(struct dpaa2_dev_flow *flow,
ret = dpaa2_flow_add_hdr_extract_rule(flow, NET_PROT_ICMP,
NH_FLD_ICMP_CODE, &spec->hdr.icmp_code,
&mask->hdr.icmp_code, sizeof(uint8_t),
- priv, group, &local_cfg, DPAA2_FLOW_QOS_TYPE);
- if (ret)
- return ret;
-
- ret = dpaa2_flow_add_hdr_extract_rule(flow, NET_PROT_ICMP,
- NH_FLD_ICMP_CODE, &spec->hdr.icmp_code,
- &mask->hdr.icmp_code, sizeof(uint8_t),
- priv, group, &local_cfg, DPAA2_FLOW_FS_TYPE);
+ priv, attr->group, &local_cfg, dist_type);
if (ret)
return ret;
}
- (*device_configured) |= local_cfg;
+ if (extract_cfg)
+ (*extract_cfg) |= local_cfg;
return 0;
}
static int
-dpaa2_configure_flow_udp(struct dpaa2_dev_flow *flow,
- struct rte_eth_dev *dev,
+dpaa2_flow_udp_extract_rule_set(struct dpaa2_generic_flow *flow,
const struct rte_flow_attr *attr,
const struct rte_dpaa2_flow_item *dpaa2_pattern,
- const struct rte_flow_action actions[] __rte_unused,
- struct rte_flow_error *error __rte_unused,
- int *device_configured)
+ int *extract_cfg, enum dpaa2_flow_dist_type dist_type)
{
int ret, local_cfg = 0;
- uint32_t group;
+ uint32_t bit_offset;
const struct rte_flow_item_udp *spec, *mask;
- struct dpaa2_dev_priv *priv = dev->data->dev_private;
+ struct dpaa2_dev_priv *priv = flow->priv;
const struct rte_flow_item *pattern = &dpaa2_pattern->generic_item;
-
- group = attr->group;
+ char hex_dump[DPAA2_FLOW_HDR_HEX_DUMP_SIZE];
/* Parse pattern list to get the matching parameters */
spec = pattern->spec;
mask = pattern->mask ?
pattern->mask : &dpaa2_flow_item_udp_mask;
- /* Get traffic class index and flow id to be configured */
- flow->tc_id = group;
- flow->tc_index = attr->priority;
-
if (dpaa2_pattern->in_tunnel) {
if (spec) {
DPAA2_PMD_ERR("Tunnel-UDP distribution not support");
return -ENOTSUP;
}
- ret = dpaa2_flow_identify_by_faf(priv, flow,
- FAFE_VXLAN_IN_UDP_FRAM,
- DPAA2_FLOW_QOS_TYPE, group,
- &local_cfg);
+ ret = dpaa2_protocol_psr_bit_offset(&bit_offset,
+ DPAA2_PARSER_TUNNEL_UDP_ID);
if (ret)
return ret;
ret = dpaa2_flow_identify_by_faf(priv, flow,
- FAFE_VXLAN_IN_UDP_FRAM,
- DPAA2_FLOW_FS_TYPE, group,
- &local_cfg);
- return ret;
+ bit_offset, dist_type, attr->group, &local_cfg);
+ if (ret)
+ return ret;
}
- ret = dpaa2_flow_identify_by_faf(priv, flow,
- FAF_UDP_FRAM, DPAA2_FLOW_QOS_TYPE,
- group, &local_cfg);
+ ret = dpaa2_protocol_psr_bit_offset(&bit_offset,
+ DPAA2_PARSER_UDP_ID);
if (ret)
return ret;
ret = dpaa2_flow_identify_by_faf(priv, flow,
- FAF_UDP_FRAM, DPAA2_FLOW_FS_TYPE,
- group, &local_cfg);
+ bit_offset, dist_type, attr->group, &local_cfg);
if (ret)
return ret;
if (!spec) {
- (*device_configured) |= local_cfg;
+ if (extract_cfg)
+ (*extract_cfg) |= local_cfg;
return 0;
}
ret = dpaa2_flow_extract_support((const uint8_t *)mask,
RTE_FLOW_ITEM_TYPE_UDP);
if (ret) {
- DPAA2_PMD_WARN("Extract field(s) of UDP not support.");
+ dpaa2_flow_hdr_hexdump(hex_dump, (const uint8_t *)mask,
+ sizeof(struct rte_flow_item_udp));
+ DPAA2_PMD_ERR("Extract UDP(%s) failed(%d)",
+ hex_dump, ret);
return ret;
}
@@ -2992,14 +2646,7 @@ dpaa2_configure_flow_udp(struct dpaa2_dev_flow *flow,
ret = dpaa2_flow_add_hdr_extract_rule(flow, NET_PROT_UDP,
NH_FLD_UDP_PORT_SRC, &spec->hdr.src_port,
&mask->hdr.src_port, sizeof(rte_be16_t),
- priv, group, &local_cfg, DPAA2_FLOW_QOS_TYPE);
- if (ret)
- return ret;
-
- ret = dpaa2_flow_add_hdr_extract_rule(flow, NET_PROT_UDP,
- NH_FLD_UDP_PORT_SRC, &spec->hdr.src_port,
- &mask->hdr.src_port, sizeof(rte_be16_t),
- priv, group, &local_cfg, DPAA2_FLOW_FS_TYPE);
+ priv, attr->group, &local_cfg, dist_type);
if (ret)
return ret;
}
@@ -3008,90 +2655,75 @@ dpaa2_configure_flow_udp(struct dpaa2_dev_flow *flow,
ret = dpaa2_flow_add_hdr_extract_rule(flow, NET_PROT_UDP,
NH_FLD_UDP_PORT_DST, &spec->hdr.dst_port,
&mask->hdr.dst_port, sizeof(rte_be16_t),
- priv, group, &local_cfg, DPAA2_FLOW_QOS_TYPE);
- if (ret)
- return ret;
-
- ret = dpaa2_flow_add_hdr_extract_rule(flow, NET_PROT_UDP,
- NH_FLD_UDP_PORT_DST, &spec->hdr.dst_port,
- &mask->hdr.dst_port, sizeof(rte_be16_t),
- priv, group, &local_cfg, DPAA2_FLOW_FS_TYPE);
+ priv, attr->group, &local_cfg, dist_type);
if (ret)
return ret;
}
- (*device_configured) |= local_cfg;
+ if (extract_cfg)
+ (*extract_cfg) |= local_cfg;
return 0;
}
static int
-dpaa2_configure_flow_tcp(struct dpaa2_dev_flow *flow,
- struct rte_eth_dev *dev,
+dpaa2_flow_tcp_extract_rule_set(struct dpaa2_generic_flow *flow,
const struct rte_flow_attr *attr,
const struct rte_dpaa2_flow_item *dpaa2_pattern,
- const struct rte_flow_action actions[] __rte_unused,
- struct rte_flow_error *error __rte_unused,
- int *device_configured)
+ int *extract_cfg, enum dpaa2_flow_dist_type dist_type)
{
int ret, local_cfg = 0;
- uint32_t group;
+ uint32_t bit_offset;
const struct rte_flow_item_tcp *spec, *mask;
- struct dpaa2_dev_priv *priv = dev->data->dev_private;
+ struct dpaa2_dev_priv *priv = flow->priv;
const struct rte_flow_item *pattern = &dpaa2_pattern->generic_item;
-
- group = attr->group;
+ char hex_dump[DPAA2_FLOW_HDR_HEX_DUMP_SIZE];
/* Parse pattern list to get the matching parameters */
spec = pattern->spec;
mask = pattern->mask ?
pattern->mask : &dpaa2_flow_item_tcp_mask;
- /* Get traffic class index and flow id to be configured */
- flow->tc_id = group;
- flow->tc_index = attr->priority;
-
if (dpaa2_pattern->in_tunnel) {
if (spec) {
DPAA2_PMD_ERR("Tunnel-TCP distribution not support");
return -ENOTSUP;
}
- ret = dpaa2_flow_identify_by_faf(priv, flow,
- FAFE_VXLAN_IN_TCP_FRAM,
- DPAA2_FLOW_QOS_TYPE, group,
- &local_cfg);
+ ret = dpaa2_protocol_psr_bit_offset(&bit_offset,
+ DPAA2_PARSER_TUNNEL_TCP_ID);
if (ret)
return ret;
ret = dpaa2_flow_identify_by_faf(priv, flow,
- FAFE_VXLAN_IN_TCP_FRAM,
- DPAA2_FLOW_FS_TYPE, group,
- &local_cfg);
- return ret;
+ bit_offset, dist_type, attr->group, &local_cfg);
+ if (ret)
+ return ret;
}
- ret = dpaa2_flow_identify_by_faf(priv, flow,
- FAF_TCP_FRAM, DPAA2_FLOW_QOS_TYPE,
- group, &local_cfg);
+ ret = dpaa2_protocol_psr_bit_offset(&bit_offset,
+ DPAA2_PARSER_TCP_ID);
if (ret)
return ret;
ret = dpaa2_flow_identify_by_faf(priv, flow,
- FAF_TCP_FRAM, DPAA2_FLOW_FS_TYPE,
- group, &local_cfg);
+ bit_offset, dist_type, attr->group, &local_cfg);
if (ret)
return ret;
if (!spec) {
- (*device_configured) |= local_cfg;
+ if (extract_cfg)
+ (*extract_cfg) |= local_cfg;
return 0;
}
ret = dpaa2_flow_extract_support((const uint8_t *)mask,
RTE_FLOW_ITEM_TYPE_TCP);
if (ret) {
- DPAA2_PMD_WARN("Extract field(s) of TCP not support.");
+ dpaa2_flow_hdr_hexdump(hex_dump, (const uint8_t *)mask,
+ sizeof(struct rte_flow_item_tcp));
+ DPAA2_PMD_ERR("Extract TCP(%s) failed(%d)",
+ hex_dump, ret);
return ret;
}
@@ -3100,14 +2732,7 @@ dpaa2_configure_flow_tcp(struct dpaa2_dev_flow *flow,
ret = dpaa2_flow_add_hdr_extract_rule(flow, NET_PROT_TCP,
NH_FLD_TCP_PORT_SRC, &spec->hdr.src_port,
&mask->hdr.src_port, sizeof(rte_be16_t),
- priv, group, &local_cfg, DPAA2_FLOW_QOS_TYPE);
- if (ret)
- return ret;
-
- ret = dpaa2_flow_add_hdr_extract_rule(flow, NET_PROT_TCP,
- NH_FLD_TCP_PORT_SRC, &spec->hdr.src_port,
- &mask->hdr.src_port, sizeof(rte_be16_t),
- priv, group, &local_cfg, DPAA2_FLOW_FS_TYPE);
+ priv, attr->group, &local_cfg, dist_type);
if (ret)
return ret;
}
@@ -3116,76 +2741,64 @@ dpaa2_configure_flow_tcp(struct dpaa2_dev_flow *flow,
ret = dpaa2_flow_add_hdr_extract_rule(flow, NET_PROT_TCP,
NH_FLD_TCP_PORT_DST, &spec->hdr.dst_port,
&mask->hdr.dst_port, sizeof(rte_be16_t),
- priv, group, &local_cfg, DPAA2_FLOW_QOS_TYPE);
- if (ret)
- return ret;
-
- ret = dpaa2_flow_add_hdr_extract_rule(flow, NET_PROT_TCP,
- NH_FLD_TCP_PORT_DST, &spec->hdr.dst_port,
- &mask->hdr.dst_port, sizeof(rte_be16_t),
- priv, group, &local_cfg, DPAA2_FLOW_FS_TYPE);
+ priv, attr->group, &local_cfg, dist_type);
if (ret)
return ret;
}
- (*device_configured) |= local_cfg;
+ if (extract_cfg)
+ (*extract_cfg) |= local_cfg;
return 0;
}
static int
-dpaa2_configure_flow_esp(struct dpaa2_dev_flow *flow,
- struct rte_eth_dev *dev,
+dpaa2_flow_esp_extract_rule_set(struct dpaa2_generic_flow *flow,
const struct rte_flow_attr *attr,
const struct rte_dpaa2_flow_item *dpaa2_pattern,
- const struct rte_flow_action actions[] __rte_unused,
- struct rte_flow_error *error __rte_unused,
- int *device_configured)
+ int *extract_cfg, enum dpaa2_flow_dist_type dist_type)
{
int ret, local_cfg = 0;
- uint32_t group;
+ uint32_t bit_offset;
const struct rte_flow_item_esp *spec, *mask;
- struct dpaa2_dev_priv *priv = dev->data->dev_private;
+ struct dpaa2_dev_priv *priv = flow->priv;
const struct rte_flow_item *pattern =
&dpaa2_pattern->generic_item;
-
- group = attr->group;
+ char hex_dump[DPAA2_FLOW_HDR_HEX_DUMP_SIZE];
/* Parse pattern list to get the matching parameters */
spec = pattern->spec;
mask = pattern->mask ?
pattern->mask : &dpaa2_flow_item_esp_mask;
- /* Get traffic class index and flow id to be configured */
- flow->tc_id = group;
- flow->tc_index = attr->priority;
-
if (dpaa2_pattern->in_tunnel) {
DPAA2_PMD_ERR("Tunnel-ESP distribution not support");
return -ENOTSUP;
}
- ret = dpaa2_flow_identify_by_faf(priv, flow,
- FAF_IPSEC_ESP_FRAM, DPAA2_FLOW_QOS_TYPE,
- group, &local_cfg);
+ ret = dpaa2_protocol_psr_bit_offset(&bit_offset,
+ DPAA2_PARSER_IPSEC_ESP_ID);
if (ret)
return ret;
ret = dpaa2_flow_identify_by_faf(priv, flow,
- FAF_IPSEC_ESP_FRAM, DPAA2_FLOW_FS_TYPE,
- group, &local_cfg);
+ bit_offset, dist_type, attr->group, &local_cfg);
if (ret)
return ret;
if (!spec) {
- (*device_configured) |= local_cfg;
+ if (extract_cfg)
+ (*extract_cfg) |= local_cfg;
return 0;
}
ret = dpaa2_flow_extract_support((const uint8_t *)mask,
RTE_FLOW_ITEM_TYPE_ESP);
if (ret) {
- DPAA2_PMD_WARN("Extract field(s) of ESP not support.");
+ dpaa2_flow_hdr_hexdump(hex_dump, (const uint8_t *)mask,
+ sizeof(struct rte_flow_item_esp));
+ DPAA2_PMD_ERR("Extract IPSEC ESP(%s) failed(%d)",
+ hex_dump, ret);
return ret;
}
@@ -3194,14 +2807,7 @@ dpaa2_configure_flow_esp(struct dpaa2_dev_flow *flow,
ret = dpaa2_flow_add_hdr_extract_rule(flow, NET_PROT_IPSEC_ESP,
NH_FLD_IPSEC_ESP_SPI, &spec->hdr.spi,
&mask->hdr.spi, sizeof(rte_be32_t),
- priv, group, &local_cfg, DPAA2_FLOW_QOS_TYPE);
- if (ret)
- return ret;
-
- ret = dpaa2_flow_add_hdr_extract_rule(flow, NET_PROT_IPSEC_ESP,
- NH_FLD_IPSEC_ESP_SPI, &spec->hdr.spi,
- &mask->hdr.spi, sizeof(rte_be32_t),
- priv, group, &local_cfg, DPAA2_FLOW_FS_TYPE);
+ priv, attr->group, &local_cfg, dist_type);
if (ret)
return ret;
}
@@ -3210,76 +2816,64 @@ dpaa2_configure_flow_esp(struct dpaa2_dev_flow *flow,
ret = dpaa2_flow_add_hdr_extract_rule(flow, NET_PROT_IPSEC_ESP,
NH_FLD_IPSEC_ESP_SEQUENCE_NUM, &spec->hdr.seq,
&mask->hdr.seq, sizeof(rte_be32_t),
- priv, group, &local_cfg, DPAA2_FLOW_QOS_TYPE);
- if (ret)
- return ret;
-
- ret = dpaa2_flow_add_hdr_extract_rule(flow, NET_PROT_IPSEC_ESP,
- NH_FLD_IPSEC_ESP_SEQUENCE_NUM, &spec->hdr.seq,
- &mask->hdr.seq, sizeof(rte_be32_t),
- priv, group, &local_cfg, DPAA2_FLOW_FS_TYPE);
+ priv, attr->group, &local_cfg, dist_type);
if (ret)
return ret;
}
- (*device_configured) |= local_cfg;
+ if (extract_cfg)
+ (*extract_cfg) |= local_cfg;
return 0;
}
static int
-dpaa2_configure_flow_ah(struct dpaa2_dev_flow *flow,
- struct rte_eth_dev *dev,
+dpaa2_flow_ah_extract_rule_set(struct dpaa2_generic_flow *flow,
const struct rte_flow_attr *attr,
const struct rte_dpaa2_flow_item *dpaa2_pattern,
- const struct rte_flow_action actions[] __rte_unused,
- struct rte_flow_error *error __rte_unused,
- int *device_configured)
+ int *extract_cfg, enum dpaa2_flow_dist_type dist_type)
{
int ret, local_cfg = 0;
- uint32_t group;
+ uint32_t bit_offset;
const struct rte_flow_item_ah *spec, *mask;
- struct dpaa2_dev_priv *priv = dev->data->dev_private;
+ struct dpaa2_dev_priv *priv = flow->priv;
const struct rte_flow_item *pattern =
&dpaa2_pattern->generic_item;
-
- group = attr->group;
+ char hex_dump[DPAA2_FLOW_HDR_HEX_DUMP_SIZE];
/* Parse pattern list to get the matching parameters */
spec = pattern->spec;
mask = pattern->mask ?
pattern->mask : &dpaa2_flow_item_ah_mask;
- /* Get traffic class index and flow id to be configured */
- flow->tc_id = group;
- flow->tc_index = attr->priority;
-
if (dpaa2_pattern->in_tunnel) {
DPAA2_PMD_ERR("Tunnel-AH distribution not support");
return -ENOTSUP;
}
- ret = dpaa2_flow_identify_by_faf(priv, flow,
- FAF_IPSEC_AH_FRAM, DPAA2_FLOW_QOS_TYPE,
- group, &local_cfg);
+ ret = dpaa2_protocol_psr_bit_offset(&bit_offset,
+ DPAA2_PARSER_IPSEC_AH_ID);
if (ret)
return ret;
ret = dpaa2_flow_identify_by_faf(priv, flow,
- FAF_IPSEC_AH_FRAM, DPAA2_FLOW_FS_TYPE,
- group, &local_cfg);
+ bit_offset, dist_type, attr->group, &local_cfg);
if (ret)
return ret;
if (!spec) {
- (*device_configured) |= local_cfg;
+ if (extract_cfg)
+ (*extract_cfg) |= local_cfg;
return 0;
}
ret = dpaa2_flow_extract_support((const uint8_t *)mask,
RTE_FLOW_ITEM_TYPE_AH);
if (ret) {
- DPAA2_PMD_WARN("Extract field(s) of AH not support.");
+ dpaa2_flow_hdr_hexdump(hex_dump, (const uint8_t *)mask,
+ sizeof(struct rte_flow_item_ah));
+ DPAA2_PMD_ERR("Extract IPSEC AH(%s) failed(%d)",
+ hex_dump, ret);
return ret;
}
@@ -3288,14 +2882,7 @@ dpaa2_configure_flow_ah(struct dpaa2_dev_flow *flow,
ret = dpaa2_flow_add_hdr_extract_rule(flow, NET_PROT_IPSEC_AH,
NH_FLD_IPSEC_AH_SPI, &spec->spi,
&mask->spi, sizeof(rte_be32_t),
- priv, group, &local_cfg, DPAA2_FLOW_QOS_TYPE);
- if (ret)
- return ret;
-
- ret = dpaa2_flow_add_hdr_extract_rule(flow, NET_PROT_IPSEC_AH,
- NH_FLD_IPSEC_AH_SPI, &spec->spi,
- &mask->spi, sizeof(rte_be32_t),
- priv, group, &local_cfg, DPAA2_FLOW_FS_TYPE);
+ priv, attr->group, &local_cfg, dist_type);
if (ret)
return ret;
}
@@ -3305,63 +2892,58 @@ dpaa2_configure_flow_ah(struct dpaa2_dev_flow *flow,
return -ENOTSUP;
}
- (*device_configured) |= local_cfg;
+ if (extract_cfg)
+ (*extract_cfg) |= local_cfg;
return 0;
}
static int
-dpaa2_configure_flow_sctp(struct dpaa2_dev_flow *flow,
- struct rte_eth_dev *dev,
+dpaa2_flow_sctp_extract_rule_set(struct dpaa2_generic_flow *flow,
const struct rte_flow_attr *attr,
const struct rte_dpaa2_flow_item *dpaa2_pattern,
- const struct rte_flow_action actions[] __rte_unused,
- struct rte_flow_error *error __rte_unused,
- int *device_configured)
+ int *extract_cfg, enum dpaa2_flow_dist_type dist_type)
{
int ret, local_cfg = 0;
- uint32_t group;
+ uint32_t bit_offset;
const struct rte_flow_item_sctp *spec, *mask;
- struct dpaa2_dev_priv *priv = dev->data->dev_private;
+ struct dpaa2_dev_priv *priv = flow->priv;
const struct rte_flow_item *pattern = &dpaa2_pattern->generic_item;
-
- group = attr->group;
+ char hex_dump[DPAA2_FLOW_HDR_HEX_DUMP_SIZE];
/* Parse pattern list to get the matching parameters */
spec = pattern->spec;
mask = pattern->mask ?
pattern->mask : &dpaa2_flow_item_sctp_mask;
- /* Get traffic class index and flow id to be configured */
- flow->tc_id = group;
- flow->tc_index = attr->priority;
-
if (dpaa2_pattern->in_tunnel) {
DPAA2_PMD_ERR("Tunnel-SCTP distribution not support");
return -ENOTSUP;
}
- ret = dpaa2_flow_identify_by_faf(priv, flow,
- FAF_SCTP_FRAM, DPAA2_FLOW_QOS_TYPE,
- group, &local_cfg);
+ ret = dpaa2_protocol_psr_bit_offset(&bit_offset,
+ DPAA2_PARSER_SCTP_ID);
if (ret)
return ret;
ret = dpaa2_flow_identify_by_faf(priv, flow,
- FAF_SCTP_FRAM, DPAA2_FLOW_FS_TYPE,
- group, &local_cfg);
+ bit_offset, dist_type, attr->group, &local_cfg);
if (ret)
return ret;
if (!spec) {
- (*device_configured) |= local_cfg;
+ if (extract_cfg)
+ (*extract_cfg) |= local_cfg;
return 0;
}
ret = dpaa2_flow_extract_support((const uint8_t *)mask,
RTE_FLOW_ITEM_TYPE_SCTP);
if (ret) {
- DPAA2_PMD_WARN("Extract field(s) of SCTP not support.");
+ dpaa2_flow_hdr_hexdump(hex_dump, (const uint8_t *)mask,
+ sizeof(struct rte_flow_item_sctp));
+ DPAA2_PMD_ERR("Extract SCTP(%s) failed(%d)",
+ hex_dump, ret);
return ret;
}
@@ -3370,14 +2952,7 @@ dpaa2_configure_flow_sctp(struct dpaa2_dev_flow *flow,
ret = dpaa2_flow_add_hdr_extract_rule(flow, NET_PROT_SCTP,
NH_FLD_SCTP_PORT_SRC, &spec->hdr.src_port,
&mask->hdr.src_port, sizeof(rte_be16_t),
- priv, group, &local_cfg, DPAA2_FLOW_QOS_TYPE);
- if (ret)
- return ret;
-
- ret = dpaa2_flow_add_hdr_extract_rule(flow, NET_PROT_SCTP,
- NH_FLD_SCTP_PORT_SRC, &spec->hdr.src_port,
- &mask->hdr.src_port, sizeof(rte_be16_t),
- priv, group, &local_cfg, DPAA2_FLOW_FS_TYPE);
+ priv, attr->group, &local_cfg, dist_type);
if (ret)
return ret;
}
@@ -3386,80 +2961,63 @@ dpaa2_configure_flow_sctp(struct dpaa2_dev_flow *flow,
ret = dpaa2_flow_add_hdr_extract_rule(flow, NET_PROT_SCTP,
NH_FLD_SCTP_PORT_DST, &spec->hdr.dst_port,
&mask->hdr.dst_port, sizeof(rte_be16_t),
- priv, group, &local_cfg, DPAA2_FLOW_QOS_TYPE);
- if (ret)
- return ret;
-
- ret = dpaa2_flow_add_hdr_extract_rule(flow, NET_PROT_SCTP,
- NH_FLD_SCTP_PORT_DST, &spec->hdr.dst_port,
- &mask->hdr.dst_port, sizeof(rte_be16_t),
- priv, group, &local_cfg, DPAA2_FLOW_FS_TYPE);
+ priv, attr->group, &local_cfg, dist_type);
if (ret)
return ret;
}
- (*device_configured) |= local_cfg;
+ if (extract_cfg)
+ (*extract_cfg) |= local_cfg;
return 0;
}
static int
-dpaa2_configure_flow_gre(struct dpaa2_dev_flow *flow,
- struct rte_eth_dev *dev,
+dpaa2_flow_gre_extract_rule_set(struct dpaa2_generic_flow *flow,
const struct rte_flow_attr *attr,
const struct rte_dpaa2_flow_item *dpaa2_pattern,
- const struct rte_flow_action actions[] __rte_unused,
- struct rte_flow_error *error __rte_unused,
- int *device_configured)
+ int *extract_cfg, enum dpaa2_flow_dist_type dist_type)
{
int ret, local_cfg = 0;
- uint32_t group;
+ uint32_t bit_offset;
const struct rte_flow_item_gre *spec, *mask;
- struct dpaa2_dev_priv *priv = dev->data->dev_private;
+ struct dpaa2_dev_priv *priv = flow->priv;
const struct rte_flow_item *pattern = &dpaa2_pattern->generic_item;
-
- group = attr->group;
+ char hex_dump[DPAA2_FLOW_HDR_HEX_DUMP_SIZE];
/* Parse pattern list to get the matching parameters */
spec = pattern->spec;
mask = pattern->mask ?
pattern->mask : &dpaa2_flow_item_gre_mask;
- /* Get traffic class index and flow id to be configured */
- flow->tc_id = group;
- flow->tc_index = attr->priority;
-
if (dpaa2_pattern->in_tunnel) {
DPAA2_PMD_ERR("Tunnel-GRE distribution not support");
return -ENOTSUP;
}
if (!spec) {
- ret = dpaa2_flow_identify_by_faf(priv, flow,
- FAF_GRE_FRAM, DPAA2_FLOW_QOS_TYPE,
- group, &local_cfg);
+ ret = dpaa2_protocol_psr_bit_offset(&bit_offset,
+ DPAA2_PARSER_GRE_ID);
if (ret)
return ret;
ret = dpaa2_flow_identify_by_faf(priv, flow,
- FAF_GRE_FRAM, DPAA2_FLOW_FS_TYPE,
- group, &local_cfg);
+ bit_offset, dist_type, attr->group, &local_cfg);
if (ret)
return ret;
- (*device_configured) |= local_cfg;
+ if (extract_cfg)
+ (*extract_cfg) |= local_cfg;
return 0;
}
- if (!priv->sp_protocol) {
- DPAA2_PMD_ERR("vXLAN flow with spec is not supported without SP.");
- return -ENOTSUP;
- }
-
ret = dpaa2_flow_extract_support((const uint8_t *)mask,
RTE_FLOW_ITEM_TYPE_GRE);
if (ret) {
- DPAA2_PMD_WARN("Extract field(s) of GRE not support.");
+ dpaa2_flow_hdr_hexdump(hex_dump, (const uint8_t *)mask,
+ sizeof(struct rte_flow_item_gre));
+ DPAA2_PMD_ERR("Extract GRE(%s) failed(%d)",
+ hex_dump, ret);
return ret;
}
@@ -3468,81 +3026,65 @@ dpaa2_configure_flow_gre(struct dpaa2_dev_flow *flow,
return 0;
ret = dpaa2_flow_add_hdr_extract_rule(flow, NET_PROT_GRE,
- NH_FLD_GRE_TYPE, &spec->protocol,
- &mask->protocol, sizeof(rte_be16_t),
- priv, group, &local_cfg, DPAA2_FLOW_QOS_TYPE);
- if (ret)
- return ret;
-
- ret = dpaa2_flow_add_hdr_extract_rule(flow, NET_PROT_GRE,
- NH_FLD_GRE_TYPE, &spec->protocol,
- &mask->protocol, sizeof(rte_be16_t),
- priv, group, &local_cfg, DPAA2_FLOW_FS_TYPE);
+ NH_FLD_GRE_TYPE, &spec->protocol, &mask->protocol,
+ sizeof(rte_be16_t), priv, attr->group, &local_cfg, dist_type);
if (ret)
return ret;
- (*device_configured) |= local_cfg;
+ if (extract_cfg)
+ (*extract_cfg) |= local_cfg;
return 0;
}
static int
-dpaa2_configure_flow_vxlan(struct dpaa2_dev_flow *flow,
- struct rte_eth_dev *dev,
+dpaa2_flow_vxlan_extract_rule_set(struct dpaa2_generic_flow *flow,
const struct rte_flow_attr *attr,
const struct rte_dpaa2_flow_item *dpaa2_pattern,
- const struct rte_flow_action actions[] __rte_unused,
- struct rte_flow_error *error __rte_unused,
- int *device_configured)
+ int *extract_cfg, enum dpaa2_flow_dist_type dist_type)
{
int ret, local_cfg = 0;
- uint32_t group;
+ uint32_t bit_offset;
const struct rte_flow_item_vxlan *spec, *mask;
- struct dpaa2_dev_priv *priv = dev->data->dev_private;
+ struct dpaa2_dev_priv *priv = flow->priv;
const struct rte_flow_item *pattern = &dpaa2_pattern->generic_item;
-
- if (!priv->sp_protocol) {
- DPAA2_PMD_ERR("eCPRI flow is not supported without SP.");
- return -ENOTSUP;
- }
-
- group = attr->group;
+ char hex_dump[DPAA2_FLOW_HDR_HEX_DUMP_SIZE];
/* Parse pattern list to get the matching parameters */
spec = pattern->spec;
mask = pattern->mask ?
pattern->mask : &dpaa2_flow_item_vxlan_mask;
- /* Get traffic class index and flow id to be configured */
- flow->tc_id = group;
- flow->tc_index = attr->priority;
-
if (dpaa2_pattern->in_tunnel) {
DPAA2_PMD_ERR("Tunnel-VXLAN distribution not support");
return -ENOTSUP;
}
- if (!spec) {
- ret = dpaa2_flow_identify_by_faf(priv, flow,
- FAF_VXLAN_FRAM, DPAA2_FLOW_QOS_TYPE,
- group, &local_cfg);
- if (ret)
- return ret;
+ ret = dpaa2_protocol_psr_bit_offset(&bit_offset,
+ DPAA2_PARSER_VXLAN_ID);
+ if (ret)
+ return ret;
- ret = dpaa2_flow_identify_by_faf(priv, flow,
- FAF_VXLAN_FRAM, DPAA2_FLOW_FS_TYPE,
- group, &local_cfg);
- if (ret)
- return ret;
+ ret = dpaa2_flow_identify_by_faf(priv, flow,
+ bit_offset, dist_type, attr->group, &local_cfg);
+ if (ret)
+ return ret;
- (*device_configured) |= local_cfg;
- return 0;
+ if (!spec)
+ goto quit;
+
+ if (!priv->sp_protocol) {
+ DPAA2_PMD_ERR("vXLAN flow with spec is not supported without SP.");
+ return -ENOTSUP;
}
ret = dpaa2_flow_extract_support((const uint8_t *)mask,
RTE_FLOW_ITEM_TYPE_VXLAN);
if (ret) {
- DPAA2_PMD_WARN("Extract field(s) of VXLAN not support.");
+ dpaa2_flow_hdr_hexdump(hex_dump, (const uint8_t *)mask,
+ sizeof(struct rte_flow_item_vxlan));
+ DPAA2_PMD_ERR("Extract vXLAN(%s) failed(%d)",
+ hex_dump, ret);
return ret;
}
@@ -3562,55 +3104,45 @@ dpaa2_configure_flow_vxlan(struct dpaa2_dev_flow *flow,
if (mask->vni[0] || mask->vni[1] || mask->vni[2]) {
ret = dpaa2_flow_add_pr_extract_rule(flow,
DPAA2_VXLAN_VNI_OFFSET,
- sizeof(mask->vni), spec->vni,
- mask->vni,
- priv, group, &local_cfg, DPAA2_FLOW_QOS_TYPE);
- if (ret)
- return ret;
-
- ret = dpaa2_flow_add_pr_extract_rule(flow,
- DPAA2_VXLAN_VNI_OFFSET,
- sizeof(mask->vni), spec->vni,
- mask->vni,
- priv, group, &local_cfg, DPAA2_FLOW_FS_TYPE);
+ sizeof(mask->vni), spec->vni, mask->vni,
+ priv, attr->group, &local_cfg, dist_type);
if (ret)
return ret;
}
- (*device_configured) |= local_cfg;
+quit:
+ if (extract_cfg)
+ (*extract_cfg) |= local_cfg;
return 0;
}
static int
-dpaa2_configure_flow_ecpri(struct dpaa2_dev_flow *flow,
- struct rte_eth_dev *dev,
+dpaa2_flow_ecpri_extract_rule_set(struct dpaa2_generic_flow *flow,
const struct rte_flow_attr *attr,
const struct rte_dpaa2_flow_item *dpaa2_pattern,
- const struct rte_flow_action actions[] __rte_unused,
- struct rte_flow_error *error __rte_unused,
- int *device_configured)
+ int *extract_cfg, enum dpaa2_flow_dist_type dist_type)
{
int ret, local_cfg = 0;
- uint32_t group;
+ uint32_t bit_offset;
const struct rte_flow_item_ecpri *spec, *mask;
struct rte_flow_item_ecpri local_mask;
- struct dpaa2_dev_priv *priv = dev->data->dev_private;
+ struct dpaa2_dev_priv *priv = flow->priv;
const struct rte_flow_item *pattern =
&dpaa2_pattern->generic_item;
- uint8_t extract_nb = 0, i;
+ int extract_nb, i;
uint64_t rule_data[DPAA2_ECPRI_MAX_EXTRACT_NB];
uint64_t mask_data[DPAA2_ECPRI_MAX_EXTRACT_NB];
uint8_t extract_size[DPAA2_ECPRI_MAX_EXTRACT_NB];
uint8_t extract_off[DPAA2_ECPRI_MAX_EXTRACT_NB];
+ union dpaa2_sp_fafe_parse fafe;
+ char hex_dump[DPAA2_FLOW_HDR_HEX_DUMP_SIZE];
if (!priv->sp_protocol) {
- DPAA2_PMD_ERR("ROCEV2 flow is not supported without SP.");
+ DPAA2_PMD_ERR("eCPRI flow is not supported without SP.");
return -ENOTSUP;
}
- group = attr->group;
-
/* Parse pattern list to get the matching parameters */
spec = pattern->spec;
if (pattern->mask) {
@@ -3623,353 +3155,111 @@ dpaa2_configure_flow_ecpri(struct dpaa2_dev_flow *flow,
mask = &dpaa2_flow_item_ecpri_mask;
}
- /* Get traffic class index and flow id to be configured */
- flow->tc_id = group;
- flow->tc_index = attr->priority;
-
if (dpaa2_pattern->in_tunnel) {
DPAA2_PMD_ERR("Tunnel-ECPRI distribution not support");
return -ENOTSUP;
}
- if (!spec) {
- ret = dpaa2_flow_identify_by_faf(priv, flow,
- FAFE_ECPRI_FRAM, DPAA2_FLOW_QOS_TYPE,
- group, &local_cfg);
- if (ret)
- return ret;
+ ret = dpaa2_protocol_psr_bit_offset(&bit_offset,
+ DPAA2_PARSER_ECPRI_ID);
+ if (ret)
+ return ret;
- ret = dpaa2_flow_identify_by_faf(priv, flow,
- FAFE_ECPRI_FRAM, DPAA2_FLOW_FS_TYPE,
- group, &local_cfg);
- if (ret)
- return ret;
+ ret = dpaa2_flow_identify_by_faf(priv, flow,
+ bit_offset, dist_type,
+ attr->group, &local_cfg);
+ if (ret)
+ return ret;
- (*device_configured) |= local_cfg;
- return 0;
- }
+ if (!spec)
+ goto quit;
ret = dpaa2_flow_extract_support((const uint8_t *)mask,
RTE_FLOW_ITEM_TYPE_ECPRI);
if (ret) {
- DPAA2_PMD_WARN("Extract field(s) of ECPRI not support.");
+ dpaa2_flow_hdr_hexdump(hex_dump, (const uint8_t *)mask,
+ sizeof(struct rte_flow_item_ecpri));
+ DPAA2_PMD_ERR("Extract eCPRI(%s) failed(%d)",
+ hex_dump, ret);
return ret;
}
- if (mask->hdr.common.type != 0xff) {
- DPAA2_PMD_WARN("ECPRI header type not specified.");
-
- return -EINVAL;
- }
+ memset(&fafe, 0, sizeof(union dpaa2_sp_fafe_parse));
+ extract_nb = dpaa2_parser_ecpri_extract(spec, mask,
+ rule_data, mask_data, extract_size, extract_off,
+ &fafe, DPAA2_ECPRI_MAX_EXTRACT_NB);
+ if (extract_nb < 0) {
+ DPAA2_PMD_ERR("Extract eCPRI from spec/mask failed(%d)",
+ extract_nb);
- if (spec->hdr.common.type == RTE_ECPRI_MSG_TYPE_IQ_DATA) {
- rule_data[extract_nb] = ECPRI_FAFE_TYPE_0;
- mask_data[extract_nb] = 0xff;
- extract_size[extract_nb] = sizeof(uint8_t);
- extract_off[extract_nb] = DPAA2_FAFE_PSR_OFFSET;
- extract_nb++;
-
- if (mask->hdr.type0.pc_id) {
- rule_data[extract_nb] = spec->hdr.type0.pc_id;
- mask_data[extract_nb] = mask->hdr.type0.pc_id;
- extract_size[extract_nb] = sizeof(rte_be16_t);
- extract_off[extract_nb] =
- DPAA2_ECPRI_MSG_OFFSET +
- offsetof(struct rte_ecpri_msg_iq_data, pc_id);
- extract_nb++;
- }
- if (mask->hdr.type0.seq_id) {
- rule_data[extract_nb] = spec->hdr.type0.seq_id;
- mask_data[extract_nb] = mask->hdr.type0.seq_id;
- extract_size[extract_nb] = sizeof(rte_be16_t);
- extract_off[extract_nb] =
- DPAA2_ECPRI_MSG_OFFSET +
- offsetof(struct rte_ecpri_msg_iq_data, seq_id);
- extract_nb++;
- }
- } else if (spec->hdr.common.type == RTE_ECPRI_MSG_TYPE_BIT_SEQ) {
- rule_data[extract_nb] = ECPRI_FAFE_TYPE_1;
- mask_data[extract_nb] = 0xff;
- extract_size[extract_nb] = sizeof(uint8_t);
- extract_off[extract_nb] = DPAA2_FAFE_PSR_OFFSET;
- extract_nb++;
-
- if (mask->hdr.type1.pc_id) {
- rule_data[extract_nb] = spec->hdr.type1.pc_id;
- mask_data[extract_nb] = mask->hdr.type1.pc_id;
- extract_size[extract_nb] = sizeof(rte_be16_t);
- extract_off[extract_nb] =
- DPAA2_ECPRI_MSG_OFFSET +
- offsetof(struct rte_ecpri_msg_bit_seq, pc_id);
- extract_nb++;
- }
- if (mask->hdr.type1.seq_id) {
- rule_data[extract_nb] = spec->hdr.type1.seq_id;
- mask_data[extract_nb] = mask->hdr.type1.seq_id;
- extract_size[extract_nb] = sizeof(rte_be16_t);
- extract_off[extract_nb] =
- DPAA2_ECPRI_MSG_OFFSET +
- offsetof(struct rte_ecpri_msg_bit_seq, seq_id);
- extract_nb++;
- }
- } else if (spec->hdr.common.type == RTE_ECPRI_MSG_TYPE_RTC_CTRL) {
- rule_data[extract_nb] = ECPRI_FAFE_TYPE_2;
- mask_data[extract_nb] = 0xff;
- extract_size[extract_nb] = sizeof(uint8_t);
- extract_off[extract_nb] = DPAA2_FAFE_PSR_OFFSET;
- extract_nb++;
-
- if (mask->hdr.type2.rtc_id) {
- rule_data[extract_nb] = spec->hdr.type2.rtc_id;
- mask_data[extract_nb] = mask->hdr.type2.rtc_id;
- extract_size[extract_nb] = sizeof(rte_be16_t);
- extract_off[extract_nb] =
- DPAA2_ECPRI_MSG_OFFSET +
- offsetof(struct rte_ecpri_msg_rtc_ctrl, rtc_id);
- extract_nb++;
- }
- if (mask->hdr.type2.seq_id) {
- rule_data[extract_nb] = spec->hdr.type2.seq_id;
- mask_data[extract_nb] = mask->hdr.type2.seq_id;
- extract_size[extract_nb] = sizeof(rte_be16_t);
- extract_off[extract_nb] =
- DPAA2_ECPRI_MSG_OFFSET +
- offsetof(struct rte_ecpri_msg_rtc_ctrl, seq_id);
- extract_nb++;
- }
- } else if (spec->hdr.common.type == RTE_ECPRI_MSG_TYPE_GEN_DATA) {
- rule_data[extract_nb] = ECPRI_FAFE_TYPE_3;
- mask_data[extract_nb] = 0xff;
- extract_size[extract_nb] = sizeof(uint8_t);
- extract_off[extract_nb] = DPAA2_FAFE_PSR_OFFSET;
- extract_nb++;
-
- if (mask->hdr.type3.pc_id || mask->hdr.type3.seq_id)
- DPAA2_PMD_WARN("Extract type3 msg not support.");
- } else if (spec->hdr.common.type == RTE_ECPRI_MSG_TYPE_RM_ACC) {
- rule_data[extract_nb] = ECPRI_FAFE_TYPE_4;
- mask_data[extract_nb] = 0xff;
- extract_size[extract_nb] = sizeof(uint8_t);
- extract_off[extract_nb] = DPAA2_FAFE_PSR_OFFSET;
- extract_nb++;
-
- if (mask->hdr.type4.rma_id) {
- rule_data[extract_nb] = spec->hdr.type4.rma_id;
- mask_data[extract_nb] = mask->hdr.type4.rma_id;
- extract_size[extract_nb] = sizeof(uint8_t);
- extract_off[extract_nb] =
- DPAA2_ECPRI_MSG_OFFSET + 0;
- /** Compiler not support to take address
- * of bit-field
- * offsetof(struct rte_ecpri_msg_rm_access,
- * rma_id);
- */
- extract_nb++;
- }
- if (mask->hdr.type4.ele_id) {
- rule_data[extract_nb] = spec->hdr.type4.ele_id;
- mask_data[extract_nb] = mask->hdr.type4.ele_id;
- extract_size[extract_nb] = sizeof(rte_be16_t);
- extract_off[extract_nb] =
- DPAA2_ECPRI_MSG_OFFSET + 2;
- /** Compiler not support to take address
- * of bit-field
- * offsetof(struct rte_ecpri_msg_rm_access,
- * ele_id);
- */
- extract_nb++;
- }
- } else if (spec->hdr.common.type == RTE_ECPRI_MSG_TYPE_DLY_MSR) {
- rule_data[extract_nb] = ECPRI_FAFE_TYPE_5;
- mask_data[extract_nb] = 0xff;
- extract_size[extract_nb] = sizeof(uint8_t);
- extract_off[extract_nb] = DPAA2_FAFE_PSR_OFFSET;
- extract_nb++;
-
- if (mask->hdr.type5.msr_id) {
- rule_data[extract_nb] = spec->hdr.type5.msr_id;
- mask_data[extract_nb] = mask->hdr.type5.msr_id;
- extract_size[extract_nb] = sizeof(uint8_t);
- extract_off[extract_nb] =
- DPAA2_ECPRI_MSG_OFFSET +
- offsetof(struct rte_ecpri_msg_delay_measure,
- msr_id);
- extract_nb++;
- }
- if (mask->hdr.type5.act_type) {
- rule_data[extract_nb] = spec->hdr.type5.act_type;
- mask_data[extract_nb] = mask->hdr.type5.act_type;
- extract_size[extract_nb] = sizeof(uint8_t);
- extract_off[extract_nb] =
- DPAA2_ECPRI_MSG_OFFSET +
- offsetof(struct rte_ecpri_msg_delay_measure,
- act_type);
- extract_nb++;
- }
- } else if (spec->hdr.common.type == RTE_ECPRI_MSG_TYPE_RMT_RST) {
- rule_data[extract_nb] = ECPRI_FAFE_TYPE_6;
- mask_data[extract_nb] = 0xff;
- extract_size[extract_nb] = sizeof(uint8_t);
- extract_off[extract_nb] = DPAA2_FAFE_PSR_OFFSET;
- extract_nb++;
-
- if (mask->hdr.type6.rst_id) {
- rule_data[extract_nb] = spec->hdr.type6.rst_id;
- mask_data[extract_nb] = mask->hdr.type6.rst_id;
- extract_size[extract_nb] = sizeof(rte_be16_t);
- extract_off[extract_nb] =
- DPAA2_ECPRI_MSG_OFFSET +
- offsetof(struct rte_ecpri_msg_remote_reset,
- rst_id);
- extract_nb++;
- }
- if (mask->hdr.type6.rst_op) {
- rule_data[extract_nb] = spec->hdr.type6.rst_op;
- mask_data[extract_nb] = mask->hdr.type6.rst_op;
- extract_size[extract_nb] = sizeof(uint8_t);
- extract_off[extract_nb] =
- DPAA2_ECPRI_MSG_OFFSET +
- offsetof(struct rte_ecpri_msg_remote_reset,
- rst_op);
- extract_nb++;
- }
- } else if (spec->hdr.common.type == RTE_ECPRI_MSG_TYPE_EVT_IND) {
- rule_data[extract_nb] = ECPRI_FAFE_TYPE_7;
- mask_data[extract_nb] = 0xff;
- extract_size[extract_nb] = sizeof(uint8_t);
- extract_off[extract_nb] = DPAA2_FAFE_PSR_OFFSET;
- extract_nb++;
-
- if (mask->hdr.type7.evt_id) {
- rule_data[extract_nb] = spec->hdr.type7.evt_id;
- mask_data[extract_nb] = mask->hdr.type7.evt_id;
- extract_size[extract_nb] = sizeof(uint8_t);
- extract_off[extract_nb] =
- DPAA2_ECPRI_MSG_OFFSET +
- offsetof(struct rte_ecpri_msg_event_ind,
- evt_id);
- extract_nb++;
- }
- if (mask->hdr.type7.evt_type) {
- rule_data[extract_nb] = spec->hdr.type7.evt_type;
- mask_data[extract_nb] = mask->hdr.type7.evt_type;
- extract_size[extract_nb] = sizeof(uint8_t);
- extract_off[extract_nb] =
- DPAA2_ECPRI_MSG_OFFSET +
- offsetof(struct rte_ecpri_msg_event_ind,
- evt_type);
- extract_nb++;
- }
- if (mask->hdr.type7.seq) {
- rule_data[extract_nb] = spec->hdr.type7.seq;
- mask_data[extract_nb] = mask->hdr.type7.seq;
- extract_size[extract_nb] = sizeof(uint8_t);
- extract_off[extract_nb] =
- DPAA2_ECPRI_MSG_OFFSET +
- offsetof(struct rte_ecpri_msg_event_ind,
- seq);
- extract_nb++;
- }
- if (mask->hdr.type7.number) {
- rule_data[extract_nb] = spec->hdr.type7.number;
- mask_data[extract_nb] = mask->hdr.type7.number;
- extract_size[extract_nb] = sizeof(uint8_t);
- extract_off[extract_nb] =
- DPAA2_ECPRI_MSG_OFFSET +
- offsetof(struct rte_ecpri_msg_event_ind,
- number);
- extract_nb++;
- }
- } else {
- DPAA2_PMD_ERR("Invalid ecpri header type(%d)",
- spec->hdr.common.type);
- return -EINVAL;
+ return extract_nb;
}
for (i = 0; i < extract_nb; i++) {
ret = dpaa2_flow_add_pr_extract_rule(flow,
- extract_off[i],
- extract_size[i], &rule_data[i], &mask_data[i],
- priv, group,
- device_configured,
- DPAA2_FLOW_QOS_TYPE);
- if (ret)
- return ret;
-
- ret = dpaa2_flow_add_pr_extract_rule(flow,
- extract_off[i],
- extract_size[i], &rule_data[i], &mask_data[i],
- priv, group,
- device_configured,
- DPAA2_FLOW_FS_TYPE);
+ extract_off[i], extract_size[i],
+ &rule_data[i], &mask_data[i],
+ priv, attr->group, extract_cfg,
+ dist_type);
if (ret)
return ret;
}
- (*device_configured) |= local_cfg;
+quit:
+ if (extract_cfg)
+ (*extract_cfg) |= local_cfg;
return 0;
}
static int
-dpaa2_configure_flow_gtp(struct dpaa2_dev_flow *flow,
- struct rte_eth_dev *dev,
+dpaa2_flow_gtp_extract_rule_set(struct dpaa2_generic_flow *flow,
const struct rte_flow_attr *attr,
const struct rte_dpaa2_flow_item *dpaa2_pattern,
- const struct rte_flow_action actions[] __rte_unused,
- struct rte_flow_error *error __rte_unused,
- int *device_configured)
+ int *extract_cfg, enum dpaa2_flow_dist_type dist_type)
{
int ret, local_cfg = 0;
- uint32_t group;
+ uint32_t bit_offset;
const struct rte_flow_item_gtp *spec, *mask;
- struct dpaa2_dev_priv *priv = dev->data->dev_private;
+ struct dpaa2_dev_priv *priv = flow->priv;
const struct rte_flow_item *pattern =
&dpaa2_pattern->generic_item;
-
- if (!priv->sp_protocol) {
- DPAA2_PMD_ERR("GENEVE flow is not supported without SP.");
- return -ENOTSUP;
- }
-
- group = attr->group;
+ char hex_dump[DPAA2_FLOW_HDR_HEX_DUMP_SIZE];
/* Parse pattern list to get the matching parameters */
spec = pattern->spec;
mask = pattern->mask ?
pattern->mask : &dpaa2_flow_item_gtp_mask;
- /* Get traffic class index and flow id to be configured */
- flow->tc_id = group;
- flow->tc_index = attr->priority;
-
if (dpaa2_pattern->in_tunnel) {
DPAA2_PMD_ERR("Tunnel-GTP distribution not support");
return -ENOTSUP;
}
if (!spec) {
- ret = dpaa2_flow_identify_by_faf(priv, flow,
- FAF_GTP_FRAM, DPAA2_FLOW_QOS_TYPE,
- group, &local_cfg);
+ ret = dpaa2_protocol_psr_bit_offset(&bit_offset,
+ DPAA2_PARSER_GTP_ID);
if (ret)
return ret;
ret = dpaa2_flow_identify_by_faf(priv, flow,
- FAF_GTP_FRAM, DPAA2_FLOW_FS_TYPE,
- group, &local_cfg);
+ bit_offset, dist_type, attr->group, &local_cfg);
if (ret)
return ret;
- (*device_configured) |= local_cfg;
+ if (extract_cfg)
+ (*extract_cfg) |= local_cfg;
return 0;
}
ret = dpaa2_flow_extract_support((const uint8_t *)mask,
RTE_FLOW_ITEM_TYPE_GTP);
if (ret) {
- DPAA2_PMD_WARN("Extract field(s) of GTP not support.");
+ dpaa2_flow_hdr_hexdump(hex_dump, (const uint8_t *)mask,
+ sizeof(struct rte_flow_item_gtp));
+ DPAA2_PMD_ERR("Extract GTP(%s) failed(%d)",
+ hex_dump, ret);
return ret;
}
@@ -3978,298 +3268,236 @@ dpaa2_configure_flow_gtp(struct dpaa2_dev_flow *flow,
return 0;
ret = dpaa2_flow_add_hdr_extract_rule(flow, NET_PROT_GTP,
- NH_FLD_GTP_TEID, &spec->teid,
- &mask->teid, sizeof(rte_be32_t),
- priv, group, &local_cfg, DPAA2_FLOW_QOS_TYPE);
- if (ret)
- return ret;
-
- ret = dpaa2_flow_add_hdr_extract_rule(flow, NET_PROT_GTP,
- NH_FLD_GTP_TEID, &spec->teid,
- &mask->teid, sizeof(rte_be32_t),
- priv, group, &local_cfg, DPAA2_FLOW_FS_TYPE);
+ NH_FLD_GTP_TEID, &spec->teid, &mask->teid,
+ sizeof(rte_be32_t), priv, attr->group,
+ &local_cfg, dist_type);
if (ret)
return ret;
- (*device_configured) |= local_cfg;
+ if (extract_cfg)
+ (*extract_cfg) |= local_cfg;
return 0;
}
static int
-dpaa2_configure_flow_mpls(struct dpaa2_dev_flow *flow,
- struct rte_eth_dev *dev,
+dpaa2_flow_raw_extract_rule_set(struct dpaa2_generic_flow *flow,
const struct rte_flow_attr *attr,
const struct rte_dpaa2_flow_item *dpaa2_pattern,
- const struct rte_flow_action actions[] __rte_unused,
- struct rte_flow_error *error __rte_unused,
- int *device_configured)
+ int *extract_cfg, enum dpaa2_flow_dist_type dist_type)
{
- int ret, local_cfg = 0;
- uint32_t group;
- const struct rte_flow_item_mpls *spec, *mask;
- struct dpaa2_dev_priv *priv = dev->data->dev_private;
- const struct rte_flow_item *pattern =
- &dpaa2_pattern->generic_item;
-
- group = attr->group;
-
- /* Parse pattern list to get the matching parameters */
- spec = pattern->spec;
- mask = pattern->mask ?
- pattern->mask : &dpaa2_flow_item_mpls_mask;
-
- /* Get traffic class index and flow id to be configured */
- flow->tc_id = group;
- flow->tc_index = attr->priority;
+ struct dpaa2_dev_priv *priv = flow->priv;
+ int local_cfg = 0, ret;
+ struct dpaa2_flow_tbl_profile *tbl_profile;
+ const struct rte_flow_item *pattern = &dpaa2_pattern->generic_item;
+ const struct rte_flow_item_raw *spec = pattern->spec;
+ const struct rte_flow_item_raw *mask = pattern->mask;
- if (dpaa2_pattern->in_tunnel) {
- DPAA2_PMD_ERR("Tunnel-MPLS distribution not support");
- return -ENOTSUP;
+ /* Need both spec and mask */
+ if (!spec || !mask) {
+ DPAA2_PMD_ERR("spec or mask not present.");
+ return -EINVAL;
}
- if (!spec) {
- ret = dpaa2_flow_identify_by_faf(priv, flow,
- FAF_MPLS_FRAM, DPAA2_FLOW_QOS_TYPE,
- group, &local_cfg);
- if (ret)
- return ret;
-
- ret = dpaa2_flow_identify_by_faf(priv, flow,
- FAF_MPLS_FRAM, DPAA2_FLOW_FS_TYPE,
- group, &local_cfg);
- if (ret)
- return ret;
+ if (spec->relative) {
+ /* TBD: relative offset support.
+ * To support relative offset of previous L3 protocol item,
+ * extracts should be expanded to identify if the frame is:
+ * vlan or none-vlan.
+ *
+ * To support relative offset of previous L4 protocol item,
+ * extracts should be expanded to identify if the frame is:
+ * vlan/IPv4 or vlan/IPv6 or none-vlan/IPv4 or none-vlan/IPv6.
+ */
+ DPAA2_PMD_ERR("relative not supported.");
+ return -EINVAL;
+ }
- (*device_configured) |= local_cfg;
- return 0;
+ if (spec->search) {
+ DPAA2_PMD_ERR("search not supported.");
+ return -EINVAL;
}
- ret = dpaa2_flow_extract_support((const uint8_t *)mask,
- RTE_FLOW_ITEM_TYPE_MPLS);
- if (ret) {
- DPAA2_PMD_WARN("Extract field(s) of MPLS not support.");
- return ret;
+ /* Spec len and mask len should be same */
+ if (spec->length != mask->length) {
+ DPAA2_PMD_ERR("Spec len and mask len mismatch.");
+ return -EINVAL;
}
- if (!mask->label_tc_s[0] && !mask->label_tc_s[1] &&
- !mask->label_tc_s[2])
- return 0;
+ if (dist_type == DPAA2_FLOW_QOS_TYPE)
+ tbl_profile = &priv->flow_profile.qos_profile;
+ else
+ tbl_profile = &priv->flow_profile.tc_profile[attr->group];
- ret = dpaa2_flow_add_hdr_extract_rule(flow, NET_PROT_MPLS,
- NH_FLD_MPLS_MPLSL_1, spec->label_tc_s,
- mask->label_tc_s, sizeof(mask->label_tc_s),
- priv, group, &local_cfg, DPAA2_FLOW_QOS_TYPE);
- if (ret)
+ ret = dpaa2_flow_extract_add_raw(priv,
+ spec->offset, spec->length, dist_type,
+ attr->group, &local_cfg);
+ if (ret) {
+ DPAA2_PMD_ERR("QoS Extract RAW add failed(%d).", ret);
return ret;
+ }
- ret = dpaa2_flow_add_hdr_extract_rule(flow, NET_PROT_MPLS,
- NH_FLD_MPLS_MPLSL_1, spec->label_tc_s,
- mask->label_tc_s, sizeof(mask->label_tc_s),
- priv, group, &local_cfg, DPAA2_FLOW_FS_TYPE);
- if (ret)
- return ret;
+ if (dist_type == DPAA2_FLOW_QOS_TYPE ||
+ dist_type == DPAA2_FLOW_FS_TYPE) {
+ ret = dpaa2_flow_raw_rule_data_set(flow,
+ &tbl_profile->key_profile,
+ spec->offset, spec->length,
+ spec->pattern, mask->pattern,
+ dist_type);
+ if (ret) {
+ DPAA2_PMD_ERR("QoS RAW rule data set failed(%d)", ret);
+ return ret;
+ }
+ }
- (*device_configured) |= local_cfg;
+ if (extract_cfg)
+ (*extract_cfg) |= local_cfg;
return 0;
}
static int
-dpaa2_configure_flow_pppoe(struct dpaa2_dev_flow *flow,
- struct rte_eth_dev *dev,
+dpaa2_flow_geneve_extract_rule_set(struct dpaa2_generic_flow *flow,
const struct rte_flow_attr *attr,
const struct rte_dpaa2_flow_item *dpaa2_pattern,
- const struct rte_flow_action actions[] __rte_unused,
- struct rte_flow_error *error __rte_unused,
- int *device_configured)
+ int *extract_cfg, enum dpaa2_flow_dist_type dist_type)
{
int ret, local_cfg = 0;
- uint32_t group;
- const struct rte_flow_item_pppoe *spec, *mask;
- struct dpaa2_dev_priv *priv = dev->data->dev_private;
- const struct rte_flow_item *pattern =
- &dpaa2_pattern->generic_item;
+ uint32_t bit_offset;
+ const struct rte_flow_item_geneve *spec, *mask;
+ struct dpaa2_dev_priv *priv = flow->priv;
+ const struct rte_flow_item *pattern = &dpaa2_pattern->generic_item;
+ char hex_dump[DPAA2_FLOW_HDR_HEX_DUMP_SIZE];
- group = attr->group;
+ if (!priv->sp_protocol) {
+ DPAA2_PMD_ERR("GENEVE flow is not supported without SP.");
+ return -ENOTSUP;
+ }
/* Parse pattern list to get the matching parameters */
spec = pattern->spec;
mask = pattern->mask ?
- pattern->mask : &dpaa2_flow_item_pppoe_mask;
-
- /* Get traffic class index and flow id to be configured */
- flow->tc_id = group;
- flow->tc_index = attr->priority;
+ pattern->mask : &dpaa2_flow_item_geneve_mask;
if (dpaa2_pattern->in_tunnel) {
- DPAA2_PMD_ERR("Tunnel-PPPoE distribution not support");
+ DPAA2_PMD_ERR("Tunnel-GENEVE distribution not support");
return -ENOTSUP;
}
- if (!spec) {
- ret = dpaa2_flow_identify_by_faf(priv, flow,
- FAF_PPPOE_PPP_FRAM, DPAA2_FLOW_QOS_TYPE,
- group, &local_cfg);
- if (ret)
- return ret;
-
- ret = dpaa2_flow_identify_by_faf(priv, flow,
- FAF_PPPOE_PPP_FRAM, DPAA2_FLOW_FS_TYPE,
- group, &local_cfg);
- if (ret)
- return ret;
-
- (*device_configured) |= local_cfg;
- return 0;
- }
-
- ret = dpaa2_flow_extract_support((const uint8_t *)mask,
- RTE_FLOW_ITEM_TYPE_PPPOES);
- if (ret) {
- DPAA2_PMD_WARN("Extract field(s) of PPPoE not support.");
- return ret;
- }
-
- if (!mask->session_id)
- return 0;
-
- ret = dpaa2_flow_add_hdr_extract_rule(flow, NET_PROT_PPPOE,
- NH_FLD_PPPOE_SID, &spec->session_id,
- &mask->session_id, sizeof(rte_be16_t),
- priv, group, &local_cfg, DPAA2_FLOW_QOS_TYPE);
+ ret = dpaa2_protocol_psr_bit_offset(&bit_offset,
+ DPAA2_PARSER_GENEVE_ID);
if (ret)
return ret;
- ret = dpaa2_flow_add_hdr_extract_rule(flow, NET_PROT_PPPOE,
- NH_FLD_PPPOE_SID, &spec->session_id,
- &mask->session_id, sizeof(rte_be16_t),
- priv, group, &local_cfg, DPAA2_FLOW_FS_TYPE);
+ ret = dpaa2_flow_identify_by_faf(priv, flow,
+ bit_offset, dist_type, attr->group, &local_cfg);
if (ret)
return ret;
- (*device_configured) |= local_cfg;
-
- return 0;
-}
+ if (!spec)
+ goto quit;
-static int
-dpaa2_configure_flow_raw(struct dpaa2_dev_flow *flow,
- struct rte_eth_dev *dev,
- const struct rte_flow_attr *attr,
- const struct rte_dpaa2_flow_item *dpaa2_pattern,
- const struct rte_flow_action actions[] __rte_unused,
- struct rte_flow_error *error __rte_unused,
- int *device_configured)
-{
- struct dpaa2_dev_priv *priv = dev->data->dev_private;
- int local_cfg = 0, ret;
- uint32_t group;
- struct dpaa2_key_extract *qos_key_extract;
- struct dpaa2_key_extract *tc_key_extract;
- const struct rte_flow_item *pattern = &dpaa2_pattern->generic_item;
- const struct rte_flow_item_raw *spec = pattern->spec;
- const struct rte_flow_item_raw *mask = pattern->mask;
+ ret = dpaa2_flow_extract_support((const uint8_t *)mask,
+ RTE_FLOW_ITEM_TYPE_GENEVE);
+ if (ret) {
+ dpaa2_flow_hdr_hexdump(hex_dump, (const uint8_t *)mask,
+ sizeof(struct rte_flow_item_geneve));
+ DPAA2_PMD_ERR("Extract GENEVE(%s) failed(%d)",
+ hex_dump, ret);
- /* Need both spec and mask */
- if (!spec || !mask) {
- DPAA2_PMD_ERR("spec or mask not present.");
- return -EINVAL;
+ return ret;
}
- if (spec->relative) {
- /* TBD: relative offset support.
- * To support relative offset of previous L3 protocol item,
- * extracts should be expanded to identify if the frame is:
- * vlan or none-vlan.
- *
- * To support relative offset of previous L4 protocol item,
- * extracts should be expanded to identify if the frame is:
- * vlan/IPv4 or vlan/IPv6 or none-vlan/IPv4 or none-vlan/IPv6.
- */
- DPAA2_PMD_ERR("relative not supported.");
+ if (mask->protocol && mask->protocol != 0xffff) {
+ DPAA2_PMD_ERR("Not support to extract geneve protocol.");
return -EINVAL;
}
- if (spec->search) {
- DPAA2_PMD_ERR("search not supported.");
- return -EINVAL;
+ if (mask->protocol) {
+ ret = dpaa2_flow_add_pr_extract_rule(flow,
+ DPAA2_GENEVE_PROTOCOL_OFFSET,
+ sizeof(mask->protocol), &spec->protocol,
+ &mask->protocol, priv, attr->group, &local_cfg,
+ dist_type);
+ if (ret)
+ return ret;
}
- /* Spec len and mask len should be same */
- if (spec->length != mask->length) {
- DPAA2_PMD_ERR("Spec len and mask len mismatch.");
- return -EINVAL;
+ if (mask->vni[0] || mask->vni[1] || mask->vni[2]) {
+ ret = dpaa2_flow_add_pr_extract_rule(flow,
+ DPAA2_GENEVE_VNI_OFFSET,
+ sizeof(mask->vni), spec->vni,
+ mask->vni,
+ priv, attr->group, &local_cfg, dist_type);
+ if (ret)
+ return ret;
}
- /* Get traffic class index and flow id to be configured */
- group = attr->group;
- flow->tc_id = group;
- flow->tc_index = attr->priority;
-
- qos_key_extract = &priv->extract.qos_key_extract;
- tc_key_extract = &priv->extract.tc_key_extract[group];
-
- ret = dpaa2_flow_extract_add_raw(priv,
- spec->offset, spec->length,
- DPAA2_FLOW_QOS_TYPE, 0, &local_cfg);
- if (ret) {
- DPAA2_PMD_ERR("QoS Extract RAW add failed.");
- return -EINVAL;
- }
+quit:
+ if (extract_cfg)
+ (*extract_cfg) |= local_cfg;
- ret = dpaa2_flow_extract_add_raw(priv,
- spec->offset, spec->length,
- DPAA2_FLOW_FS_TYPE, group, &local_cfg);
- if (ret) {
- DPAA2_PMD_ERR("FS[%d] Extract RAW add failed.",
- group);
- return -EINVAL;
- }
+ return 0;
+}
- ret = dpaa2_flow_raw_rule_data_set(flow,
- &qos_key_extract->key_profile,
- spec->offset, spec->length,
- spec->pattern, mask->pattern,
- DPAA2_FLOW_QOS_TYPE);
- if (ret) {
- DPAA2_PMD_ERR("QoS RAW rule data set failed");
- return -EINVAL;
- }
+static inline int
+dpaa2_flow_verify_entry(struct dpaa2_dev_priv *priv,
+ uint16_t tc, uint16_t entry_idx,
+ enum dpaa2_flow_dist_type dist_type)
+{
+ struct dpaa2_dev_flow *curr = LIST_FIRST(&priv->flows);
- ret = dpaa2_flow_raw_rule_data_set(flow,
- &tc_key_extract->key_profile,
- spec->offset, spec->length,
- spec->pattern, mask->pattern,
- DPAA2_FLOW_FS_TYPE);
- if (ret) {
- DPAA2_PMD_ERR("FS RAW rule data set failed");
- return -EINVAL;
+ while (curr) {
+ if (dist_type == DPAA2_FLOW_QOS_TYPE &&
+ curr->qos_flow &&
+ curr->qos_flow->entry_index == entry_idx) {
+ DPAA2_PMD_ERR("Flow QoS.entry[%d] exists",
+ curr->qos_flow->entry_index);
+ return -EEXIST;
+ }
+ if (dist_type == DPAA2_FLOW_FS_TYPE &&
+ curr->fs_flow && curr->fs_flow->tc_id == tc &&
+ curr->fs_flow->entry_index == entry_idx) {
+ DPAA2_PMD_ERR("Flow TC[%d].entry[%d] exists",
+ tc, curr->fs_flow->entry_index);
+ return -EEXIST;
+ }
+ curr = LIST_NEXT(curr, next);
}
- (*device_configured) |= local_cfg;
-
return 0;
}
static inline int
-dpaa2_flow_verify_attr(struct dpaa2_dev_priv *priv,
- const struct rte_flow_attr *attr)
+dpaa2_flow_acquire_entry_idx(struct dpaa2_dev_priv *priv,
+ uint16_t idx, enum dpaa2_flow_dist_type dist_type,
+ uint8_t group)
{
- struct dpaa2_dev_flow *curr = LIST_FIRST(&priv->flows);
+ int occupied = -1;
+ uint16_t max_entries;
+ struct dpaa2_flow_tbl_profile *tbl_profile;
- while (curr) {
- if (curr->tc_id == attr->group &&
- curr->tc_index == attr->priority) {
- DPAA2_PMD_ERR("Flow(TC[%d].entry[%d] exists",
- attr->group, attr->priority);
+ if (dist_type == DPAA2_FLOW_QOS_TYPE) {
+ tbl_profile = &priv->flow_profile.qos_profile;
+ max_entries = priv->qos_entries;
+ } else {
+ tbl_profile = &priv->flow_profile.tc_profile[group];
+ max_entries = priv->fs_entries;
+ }
- return -EINVAL;
+ if (!dpaa2_flow_entry_map_get(tbl_profile->entry_map, idx))
+ return idx;
+
+ idx = 0;
+ while (idx < max_entries) {
+ if (!dpaa2_flow_entry_map_get(tbl_profile->entry_map, idx)) {
+ occupied = idx;
+ break;
}
- curr = LIST_NEXT(curr, next);
+ idx++;
}
- return 0;
+ return occupied;
}
static inline struct rte_eth_dev *
@@ -4306,7 +3534,7 @@ dpaa2_flow_redirect_dev(struct dpaa2_dev_priv *priv,
}
static inline int
-dpaa2_flow_verify_action(struct dpaa2_dev_priv *priv,
+dpaa2_flow_verify_fs_action(struct dpaa2_dev_priv *priv,
const struct rte_flow_attr *attr,
const struct rte_flow_action actions[])
{
@@ -4332,46 +3560,51 @@ dpaa2_flow_verify_action(struct dpaa2_dev_priv *priv,
rxq->tc_index, rxq->flow_id,
attr->group);
- return -ENOTSUP;
+ return -EINVAL;
}
break;
case RTE_FLOW_ACTION_TYPE_REPRESENTED_PORT:
case RTE_FLOW_ACTION_TYPE_PORT_ID:
if (!dpaa2_flow_redirect_dev(priv, &actions[j])) {
DPAA2_PMD_ERR("Invalid port id of action");
- return -ENOTSUP;
+ return -EINVAL;
}
break;
case RTE_FLOW_ACTION_TYPE_RSS:
- rss_conf = (const struct rte_flow_action_rss *)
- (actions[j].conf);
+ rss_conf = actions[j].conf;
if (rss_conf->queue_num > priv->dist_queues) {
DPAA2_PMD_ERR("RSS number too large");
- return -ENOTSUP;
+ return -EINVAL;
}
- for (i = 0; i < (int)rss_conf->queue_num; i++) {
- if (rss_conf->queue[i] >= priv->nb_rx_queues) {
- DPAA2_PMD_ERR("RSS queue not in range");
- return -ENOTSUP;
- }
- rxq = priv->rx_vq[rss_conf->queue[i]];
- if (rxq->tc_index != attr->group) {
- DPAA2_PMD_ERR("RSS queue not in group");
- return -ENOTSUP;
+ if (rss_conf->queue) {
+ for (i = 0; i < (int)rss_conf->queue_num; i++) {
+ if (rss_conf->queue[i] >= priv->nb_rx_queues) {
+ DPAA2_PMD_ERR("RSS queue not in range");
+ return -EINVAL;
+ }
+ rxq = priv->rx_vq[rss_conf->queue[i]];
+ if (rxq->tc_index != attr->group) {
+ DPAA2_PMD_ERR("RSS queue not in group");
+ return -EINVAL;
+ }
}
}
break;
case RTE_FLOW_ACTION_TYPE_PF:
- /* Skip this action, have to add for vxlan */
+ /* Skip this action, have to add for vxlan*/
case RTE_FLOW_ACTION_TYPE_DROP:
break;
+ case RTE_FLOW_ACTION_TYPE_METER_MARK:
+ break;
+ case RTE_FLOW_ACTION_TYPE_METER:
+ break;
case RTE_FLOW_ACTION_TYPE_END:
end_of_list = 1;
break;
default:
DPAA2_PMD_ERR("Invalid action type");
- return -ENOTSUP;
+ return -EINVAL;
}
j++;
}
@@ -4379,40 +3612,74 @@ dpaa2_flow_verify_action(struct dpaa2_dev_priv *priv,
return 0;
}
+static struct dpaa2_queue *
+dpaa2_flow_queue_action_to_queue(struct dpaa2_dev_priv *priv,
+ uint8_t tc_id, uint16_t queue_id)
+{
+ struct dpaa2_queue *dest_q;
+
+ if (queue_id >= MAX_RX_QUEUES ||
+ !priv->rx_vq[queue_id]) {
+ DPAA2_PMD_ERR("Invalid FSQ index(%d)", queue_id);
+
+ return NULL;
+ }
+ dest_q = priv->rx_vq[queue_id];
+ if (tc_id != dest_q->tc_index) {
+ DPAA2_PMD_ERR("RXQ[%d](%d.%d) not in TC[%d]",
+ queue_id,
+ dest_q->tc_index, dest_q->flow_id,
+ tc_id);
+
+ return NULL;
+ }
+
+ return dest_q;
+}
+
static int
-dpaa2_configure_flow_fs_action(struct dpaa2_dev_priv *priv,
- struct dpaa2_dev_flow *flow,
+dpaa2_flow_fs_action_config(struct dpaa2_dev_priv *priv,
+ struct dpaa2_generic_flow *flow,
const struct rte_flow_action *rte_action)
{
+ struct rte_dpaa2_device *dpaa2_dev;
struct rte_eth_dev *dest_dev;
struct dpaa2_dev_priv *dest_priv;
const struct rte_flow_action_queue *dest_queue;
struct dpaa2_queue *dest_q;
uint64_t flc = 0;
-
- memset(&flow->fs_action_cfg, 0,
- sizeof(struct dpni_fs_action_cfg));
- flow->action_type = rte_action->type;
-
- if (flow->action_type == RTE_FLOW_ACTION_TYPE_QUEUE) {
- dest_queue = rte_action->conf;
- if (dest_queue->index >= MAX_RX_QUEUES ||
- !priv->rx_vq[dest_queue->index]) {
- DPAA2_PMD_ERR("Invalid FSQ index(%d)",
- dest_queue->index);
-
+ uint16_t num_tokens;
+ struct dpaa2_dev_flow_fs_action *fs_action;
+
+ dpaa2_dev = DPAA2_DEV_PRIV_TO_DPAA2_DEV(priv);
+
+ fs_action = &flow->flow_action.fs_action;
+ if (fs_action->action_type != RTE_FLOW_ACTION_TYPE_END) {
+ if (dpaa2_dev->bus_info->mc_rev >= DPAA2_FLOW_FRM_REPLICATION_ACTION_MC_REV &&
+ (fs_action->action_type == RTE_FLOW_ACTION_TYPE_PORT_ID ||
+ fs_action->action_type == RTE_FLOW_ACTION_TYPE_PORT_REPRESENTOR)) {
+ if (rte_action->type != RTE_FLOW_ACTION_TYPE_PORT_ID &&
+ rte_action->type != RTE_FLOW_ACTION_TYPE_PORT_REPRESENTOR) {
+ DPAA2_PMD_ERR("Redirect action can't mix with other action(%d)",
+ rte_action->type);
+ return -EINVAL;
+ }
+ } else {
+ DPAA2_PMD_ERR("Single action support only with action(%d)",
+ fs_action->action_type);
return -EINVAL;
}
- dest_q = priv->rx_vq[dest_queue->index];
- if (flow->tc_id != dest_q->tc_index) {
- DPAA2_PMD_ERR("RXQ[%d](%d.%d) not in TC[%d]",
- dest_queue->index,
- dest_q->tc_index, dest_q->flow_id,
- flow->tc_id);
+ }
+ fs_action->action_type = rte_action->type;
+ if (fs_action->action_type == RTE_FLOW_ACTION_TYPE_QUEUE) {
+ dest_queue = rte_action->conf;
+ dest_q = dpaa2_flow_queue_action_to_queue(priv,
+ flow->tc_id, dest_queue->index);
+ if (!dest_q)
return -EINVAL;
- }
- flow->fs_action_cfg.options =
+
+ fs_action->fs_action_cfg.options =
DPNI_FS_OPT_SET_FLC | DPNI_FS_OPT_SET_STASH_CONTROL;
if (dest_q->data_stashing_off) {
@@ -4430,10 +3697,10 @@ dpaa2_configure_flow_fs_action(struct dpaa2_dev_priv *priv,
flc |= ((uint64_t)1) << DPAA2_FS_FLC_FS_MARK_OFFSET;
flc |= ((uint64_t)dest_q->tc_index) << DPAA2_FS_FLC_TC_OFFSET;
flc |= ((uint64_t)dest_q->flow_id) << DPAA2_FS_FLC_FLOW_OFFSET;
- flow->fs_action_cfg.flc = flc;
- flow->fs_action_cfg.flow_id = dest_q->flow_id;
- } else if (flow->action_type == RTE_FLOW_ACTION_TYPE_PORT_ID ||
- flow->action_type == RTE_FLOW_ACTION_TYPE_REPRESENTED_PORT) {
+ fs_action->fs_action_cfg.flc = flc;
+ fs_action->fs_action_cfg.flow_id = dest_q->flow_id;
+ } else if (fs_action->action_type == RTE_FLOW_ACTION_TYPE_PORT_ID ||
+ fs_action->action_type == RTE_FLOW_ACTION_TYPE_REPRESENTED_PORT) {
dest_dev = dpaa2_flow_redirect_dev(priv, rte_action);
if (!dest_dev) {
DPAA2_PMD_ERR("Invalid device to redirect");
@@ -4441,15 +3708,34 @@ dpaa2_configure_flow_fs_action(struct dpaa2_dev_priv *priv,
}
dest_priv = dest_dev->data->dev_private;
- dest_q = dest_priv->tx_vq[0];
- flow->fs_action_cfg.options =
- DPNI_FS_OPT_REDIRECT_TO_DPNI_TX;
- flow->fs_action_cfg.num_tokens = 1;
- flow->fs_action_cfg.redir_tokens[0] =
- dest_priv->token;
- flow->fs_action_cfg.flow_id = dest_q->flow_id;
- } else if (flow->action_type == RTE_FLOW_ACTION_TYPE_DROP) {
- flow->fs_action_cfg.options = DPNI_FS_OPT_DISCARD;
+ num_tokens = fs_action->fs_action_cfg.num_tokens;
+ if (num_tokens >= DPNI_FS_REDIR_MAX_NUM)
+ return -EINVAL;
+ fs_action->fs_action_cfg.redir_tokens[num_tokens] = dest_priv->token;
+ strlcpy(fs_action->dst_name[num_tokens],
+ dest_priv->eth_dev->data->name,
+ sizeof(fs_action->dst_name[num_tokens]));
+ fs_action->fs_action_cfg.num_tokens++;
+ if (fs_action->fs_action_cfg.num_tokens > 1) {
+ if (!(priv->options & DPNI_OPT_V8_HAS_REPLICATION)) {
+ DPAA2_PMD_ERR("0x%08x missed in DPNI creating options(0x%08x)",
+ DPNI_OPT_V8_HAS_REPLICATION, priv->options);
+ return -ENOTSUP;
+ }
+ fs_action->fs_action_cfg.options =
+ DPNI_FS_OPT_REDIRECT_TO_MULTIPLE_DPNI_TX;
+ } else {
+ fs_action->fs_action_cfg.options =
+ DPNI_FS_OPT_REDIRECT_TO_DPNI_TX;
+ }
+ } else if (fs_action->action_type == RTE_FLOW_ACTION_TYPE_DROP) {
+ fs_action->fs_action_cfg.options = DPNI_FS_OPT_DISCARD;
+ } else if (fs_action->action_type == RTE_FLOW_ACTION_TYPE_RSS) {
+ /** Do nothing...*/
+ } else {
+ DPAA2_PMD_ERR("Flow action(%d) not supported!",
+ fs_action->action_type);
+ return -ENOTSUP;
}
return 0;
@@ -4477,41 +3763,104 @@ dpaa2_flow_clear_fs_table(struct dpaa2_dev_priv *priv,
uint8_t tc_id)
{
struct dpaa2_dev_flow *curr = LIST_FIRST(&priv->flows);
- int need_clear = 0, ret;
+ int fs_num = 0, ret, rss_num = 0;
struct fsl_mc_io *dpni = priv->hw;
while (curr) {
- if (curr->tc_id == tc_id) {
- need_clear = 1;
- break;
+ if (curr->fs_flow && curr->fs_flow->tc_id == tc_id) {
+ if (curr->fs_flow->is_rss)
+ rss_num++;
+ else
+ fs_num++;
}
curr = LIST_NEXT(curr, next);
}
- if (need_clear) {
+ if (rss_num > 1) {
+ DPAA2_PMD_ERR("TC[%d] should have one RSS flow at most!",
+ tc_id);
+ return -EINVAL;
+ }
+ if (rss_num && fs_num) {
+ DPAA2_PMD_ERR("TC[%d] has RSS flow and %d FS flow(s)!",
+ tc_id, fs_num);
+ return -EINVAL;
+ }
+
+ if (fs_num) {
ret = dpni_clear_fs_entries(dpni, CMD_PRI_LOW,
priv->token, tc_id);
if (ret) {
DPAA2_PMD_ERR("TC[%d] clear failed", tc_id);
return ret;
}
+ priv->flow_profile.tc_profile[tc_id].entry_num = 0;
+ memset(priv->flow_profile.tc_profile[tc_id].entry_map,
+ 0, priv->fs_entries);
+ }
+
+ return 0;
+}
+
+static int
+dpaa2_flow_fs_table_set_default(struct dpaa2_dev_priv *priv,
+ uint8_t tc_id, int discard, uint16_t default_queue)
+{
+ int ret;
+ struct rte_dpaa2_device *dpaa2_dev;
+ struct dpni_rx_dist_cfg *tc_cfg;
+ struct fsl_mc_io *dpni = priv->hw;
+ struct dpaa2_flow_tbl_profile *tbl_profile;
+ struct dpaa2_queue *queue;
+ char mc_rev[1024];
+
+ dpaa2_dev = DPAA2_DEV_PRIV_TO_DPAA2_DEV(priv);
+ tbl_profile = &priv->flow_profile.tc_profile[tc_id];
+ snprintf(mc_rev, 1024, "MC rev(%d.%d.%d)",
+ RTE_FSL_MC_REV_MAJOR(dpaa2_dev->bus_info->mc_rev),
+ RTE_FSL_MC_REV_MINOR(dpaa2_dev->bus_info->mc_rev),
+ RTE_FSL_MC_REV_REVISION(dpaa2_dev->bus_info->mc_rev));
+ if (!tbl_profile->dpkg.num_extracts &&
+ dpaa2_dev->bus_info->mc_rev < DPAA2_QOS_FLOW_TABLE_SET_V3_MC_REV) {
+ DPAA2_PMD_DEBUG("%s can't set miss action of FS table indepentently.",
+ mc_rev);
+ return 0;
+ }
+ tc_cfg = &tbl_profile->tc_cfg;
+ tc_cfg->enable = true;
+ if (discard) {
+ tbl_profile->default_drop = true;
+ tc_cfg->fs_miss_flow_id = DPNI_FS_MISS_ACTION_DROP;
+ } else {
+ queue = dpaa2_flow_queue_action_to_queue(priv, tc_id, default_queue);
+ if (!queue)
+ return -EINVAL;
+ tbl_profile->default_drop = false;
+ tbl_profile->default_queue.index = default_queue;
+ tc_cfg->fs_miss_flow_id = queue->flow_id;
+ }
+ ret = dpni_set_rx_fs_dist(dpni, CMD_PRI_LOW, priv->token, tc_cfg);
+ if (ret < 0) {
+ DPAA2_PMD_ERR("%s: Failed(%d) to set default action of TC[%d]",
+ __func__, ret, tc_id);
+ return ret;
}
return 0;
}
static int
-dpaa2_configure_fs_rss_table(struct dpaa2_dev_priv *priv,
- uint8_t tc_id, uint16_t dist_size, int rss_dist)
+dpaa2_flow_fs_rss_table_config(struct dpaa2_dev_priv *priv,
+ uint8_t tc_id, int rss_dist)
{
- struct dpaa2_key_extract *tc_extract;
+ struct dpaa2_flow_tbl_profile *tbl_profile;
uint8_t *key_cfg_buf;
- uint64_t key_cfg_iova;
int ret;
- struct dpni_rx_dist_cfg tc_cfg;
+ struct dpni_rx_dist_cfg *tc_cfg;
struct fsl_mc_io *dpni = priv->hw;
uint16_t entry_size;
uint16_t key_max_size;
+ struct dpaa2_queue *queue;
ret = dpaa2_flow_clear_fs_table(priv, tc_id);
if (ret < 0) {
@@ -4519,38 +3868,30 @@ dpaa2_configure_fs_rss_table(struct dpaa2_dev_priv *priv,
return ret;
}
- tc_extract = &priv->extract.tc_key_extract[tc_id];
- key_cfg_buf = priv->extract.tc_extract_param[tc_id];
- key_cfg_iova = DPAA2_VADDR_TO_IOVA_AND_CHECK(key_cfg_buf,
- DPAA2_EXTRACT_PARAM_MAX_SIZE);
- if (key_cfg_iova == RTE_BAD_IOVA) {
- DPAA2_PMD_ERR("%s: No IOMMU map for key cfg(%p)",
- __func__, key_cfg_buf);
+ tbl_profile = &priv->flow_profile.tc_profile[tc_id];
+ if (!tbl_profile->dpkg.num_extracts)
+ return 0;
- return -ENOBUFS;
- }
+ key_cfg_buf = priv->flow_profile.tc_profile[tc_id].extract_param;
- key_max_size = tc_extract->key_profile.key_max_size;
+ key_max_size = tbl_profile->key_profile.key_max_size;
entry_size = dpaa2_flow_entry_size(key_max_size);
- dpaa2_flow_fs_extracts_log(priv, tc_id);
- ret = dpkg_prepare_key_cfg(&tc_extract->dpkg,
+ dpaa2_flow_extracts_log(priv, "Configure", tc_id);
+ ret = dpkg_prepare_key_cfg(&tbl_profile->dpkg,
key_cfg_buf);
if (ret < 0) {
DPAA2_PMD_ERR("TC[%d] prepare key failed", tc_id);
return ret;
}
- memset(&tc_cfg, 0, sizeof(struct dpni_rx_dist_cfg));
- tc_cfg.dist_size = dist_size;
- tc_cfg.key_cfg_iova = key_cfg_iova;
+ tc_cfg = &tbl_profile->tc_cfg;
if (rss_dist)
- tc_cfg.enable = true;
+ tc_cfg->enable = true;
else
- tc_cfg.enable = false;
- tc_cfg.tc = tc_id;
+ tc_cfg->enable = false;
ret = dpni_set_rx_hash_dist(dpni, CMD_PRI_LOW,
- priv->token, &tc_cfg);
+ priv->token, tc_cfg);
if (ret < 0) {
if (rss_dist) {
DPAA2_PMD_ERR("RSS TC[%d] set failed",
@@ -4563,13 +3904,27 @@ dpaa2_configure_fs_rss_table(struct dpaa2_dev_priv *priv,
return ret;
}
- if (rss_dist)
- return 0;
+ if (rss_dist) {
+ tbl_profile->is_rss = true;
+ goto successful_config;
+ }
- tc_cfg.enable = true;
- tc_cfg.fs_miss_flow_id = priv->default_flow;
- ret = dpni_set_rx_fs_dist(dpni, CMD_PRI_LOW,
- priv->token, &tc_cfg);
+ tbl_profile->is_rss = false;
+
+ tc_cfg->enable = true;
+ if (tbl_profile->default_drop) {
+ tc_cfg->fs_miss_flow_id = DPNI_FS_MISS_ACTION_DROP;
+ } else {
+ queue = dpaa2_flow_queue_action_to_queue(priv, tc_id,
+ tbl_profile->default_queue.index);
+ if (!queue) {
+ DPAA2_PMD_ERR("TC[%d] invalid default queue(%d)",
+ tc_id, tbl_profile->default_queue.index);
+ return -EINVAL;
+ }
+ tc_cfg->fs_miss_flow_id = queue->flow_id;
+ }
+ ret = dpni_set_rx_fs_dist(dpni, CMD_PRI_LOW, priv->token, tc_cfg);
if (ret < 0) {
DPAA2_PMD_ERR("TC[%d] FS configured failed", tc_id);
return ret;
@@ -4580,74 +3935,145 @@ dpaa2_configure_fs_rss_table(struct dpaa2_dev_priv *priv,
if (ret)
return ret;
+successful_config:
+ tbl_profile->enabled = true;
+
+ return 0;
+}
+
+static int
+dpaa2_flow_qos_table_set_default(struct dpaa2_dev_priv *priv,
+ int discard, uint8_t default_tc, uint16_t default_flow)
+{
+ int ret;
+ struct rte_dpaa2_device *dpaa2_dev;
+ struct dpni_qos_tbl_cfg qos_cfg;
+ struct fsl_mc_io *dpni = priv->hw;
+ struct dpaa2_flow_tbl_profile *tbl_profile;
+ char mc_rev[1024];
+
+ dpaa2_dev = DPAA2_DEV_PRIV_TO_DPAA2_DEV(priv);
+ tbl_profile = &priv->flow_profile.qos_profile;
+ snprintf(mc_rev, 1024, "MC rev(%d.%d.%d)",
+ RTE_FSL_MC_REV_MAJOR(dpaa2_dev->bus_info->mc_rev),
+ RTE_FSL_MC_REV_MINOR(dpaa2_dev->bus_info->mc_rev),
+ RTE_FSL_MC_REV_REVISION(dpaa2_dev->bus_info->mc_rev));
+ if (!tbl_profile->dpkg.num_extracts &&
+ dpaa2_dev->bus_info->mc_rev < DPAA2_QOS_FLOW_TABLE_SET_V3_MC_REV) {
+ DPAA2_PMD_DEBUG("%s can't set miss action of QoS table indepentently.",
+ mc_rev);
+ return 0;
+ }
+ if (default_flow < priv->dist_queues &&
+ dpaa2_dev->bus_info->mc_rev < DPAA2_QOS_FLOW_TABLE_MISS_FLOW_ACTION_MC_REV) {
+ DPAA2_PMD_WARN("%s can't direct miss traffic to TC%d-flow%d by QoS table only.",
+ mc_rev, default_tc, default_flow);
+ return 0;
+ }
+
+ rte_memcpy(&qos_cfg, &tbl_profile->qos_cfg, sizeof(struct dpni_qos_tbl_cfg));
+ qos_cfg.key_cfg_iova = 0;
+ qos_cfg.default_tc = default_tc;
+ qos_cfg.default_flow_id = default_flow;
+ qos_cfg.discard_on_miss = discard ? true : false;
+ qos_cfg.set_default_flow_id = default_flow < priv->dist_queues ? true : false;
+
+ ret = dpni_set_qos_table(dpni, CMD_PRI_LOW, priv->token, &qos_cfg);
+ if (ret < 0) {
+ DPAA2_PMD_ERR("%s: Failed(%d) to set default action of QoS",
+ __func__, ret);
+ return ret;
+ }
+ if (discard) {
+ tbl_profile->default_drop = true;
+ } else {
+ tbl_profile->default_drop = false;
+ tbl_profile->default_jump.group = default_tc;
+ }
+ rte_memcpy(&tbl_profile->qos_cfg.discard_on_miss,
+ &qos_cfg.discard_on_miss,
+ sizeof(struct dpni_qos_tbl_cfg) -
+ offsetof(struct dpni_qos_tbl_cfg, discard_on_miss));
+
return 0;
}
static int
-dpaa2_configure_qos_table(struct dpaa2_dev_priv *priv,
+dpaa2_flow_qos_table_config(struct dpaa2_dev_priv *priv,
int rss_dist)
{
- struct dpaa2_key_extract *qos_extract;
+ struct rte_dpaa2_device *dpaa2_dev;
+ struct dpaa2_flow_tbl_profile *tbl_profile;
uint8_t *key_cfg_buf;
- uint64_t key_cfg_iova;
int ret;
- struct dpni_qos_tbl_cfg qos_cfg;
+ struct dpni_qos_tbl_cfg *qos_cfg;
struct fsl_mc_io *dpni = priv->hw;
uint16_t entry_size;
uint16_t key_max_size;
+ struct dpaa2_dev_flow *flow;
if (!rss_dist && priv->num_rx_tc <= 1) {
/* QoS table is effecitive for FS multiple TCs or RSS.*/
return 0;
}
- if (LIST_FIRST(&priv->flows)) {
+ flow = LIST_FIRST(&priv->flows);
+ while (flow) {
+ if (!flow->qos_flow) {
+ flow = LIST_NEXT(flow, next);
+ continue;
+ }
+ /** Clear existing QoS table if there is qos flow configured.*/
ret = dpni_clear_qos_table(dpni, CMD_PRI_LOW,
priv->token);
if (ret < 0) {
- DPAA2_PMD_ERR("QoS table clear failed");
+ DPAA2_PMD_ERR("QoS table clear failed(%d)", ret);
return ret;
}
+ priv->flow_profile.qos_profile.entry_num = 0;
+ memset(priv->flow_profile.qos_profile.entry_map,
+ 0, priv->qos_entries);
+ break;
}
- qos_extract = &priv->extract.qos_key_extract;
- key_cfg_buf = priv->extract.qos_extract_param;
- key_cfg_iova = DPAA2_VADDR_TO_IOVA_AND_CHECK(key_cfg_buf,
- DPAA2_EXTRACT_PARAM_MAX_SIZE);
- if (key_cfg_iova == RTE_BAD_IOVA) {
- DPAA2_PMD_ERR("%s: No IOMMU map for key cfg(%p)",
- __func__, key_cfg_buf);
+ tbl_profile = &priv->flow_profile.qos_profile;
+ if (!tbl_profile->dpkg.num_extracts)
+ return 0;
- return -ENOBUFS;
- }
+ key_cfg_buf = priv->flow_profile.qos_profile.extract_param;
- key_max_size = qos_extract->key_profile.key_max_size;
+ key_max_size = tbl_profile->key_profile.key_max_size;
entry_size = dpaa2_flow_entry_size(key_max_size);
- dpaa2_flow_qos_extracts_log(priv);
+ dpaa2_flow_extracts_log(priv, "Configure", MAX_TCS);
- ret = dpkg_prepare_key_cfg(&qos_extract->dpkg,
+ ret = dpkg_prepare_key_cfg(&tbl_profile->dpkg,
key_cfg_buf);
if (ret < 0) {
DPAA2_PMD_ERR("QoS prepare extract failed");
return ret;
}
- memset(&qos_cfg, 0, sizeof(struct dpni_qos_tbl_cfg));
- qos_cfg.keep_entries = true;
- qos_cfg.key_cfg_iova = key_cfg_iova;
+ qos_cfg = &tbl_profile->qos_cfg;
if (rss_dist) {
- qos_cfg.discard_on_miss = true;
+ qos_cfg->discard_on_miss = true;
} else {
- qos_cfg.discard_on_miss = false;
- qos_cfg.default_tc = 0;
+ qos_cfg->default_tc = tbl_profile->default_jump.group;
+ if (tbl_profile->default_drop)
+ qos_cfg->discard_on_miss = true;
+ else
+ qos_cfg->discard_on_miss = false;
}
- ret = dpni_set_qos_table(dpni, CMD_PRI_LOW,
- priv->token, &qos_cfg);
+ dpaa2_dev = DPAA2_DEV_PRIV_TO_DPAA2_DEV(priv);
+ if (dpaa2_dev->bus_info->mc_rev < DPAA2_QOS_FLOW_TABLE_SET_V3_MC_REV)
+ ret = dpni_set_qos_table_v2(dpni, CMD_PRI_LOW, priv->token, qos_cfg);
+ else
+ ret = dpni_set_qos_table(dpni, CMD_PRI_LOW, priv->token, qos_cfg);
if (ret < 0) {
- DPAA2_PMD_ERR("QoS table set failed");
+ DPAA2_PMD_ERR("QoS table set failed(%d)", ret);
return ret;
}
+ tbl_profile->enabled = true;
ret = dpaa2_flow_rule_add_all(priv, DPAA2_FLOW_QOS_TYPE,
entry_size, 0);
@@ -4697,207 +4123,468 @@ dpaa2_flow_item_convert(const struct rte_flow_item pattern[],
}
static int
-dpaa2_generic_flow_set(struct dpaa2_dev_flow *flow,
- struct rte_eth_dev *dev,
- const struct rte_flow_attr *attr,
- const struct rte_flow_item pattern[],
- const struct rte_flow_action actions[],
- struct rte_flow_error *error)
+dpaa2_flow_table_update(struct dpaa2_dev_priv *priv,
+ enum dpaa2_flow_dist_type dist_type, uint8_t tc_id, int is_rss)
{
- const struct rte_flow_action_rss *rss_conf;
- int is_keycfg_configured = 0, end_of_list = 0;
- int ret = 0, i = 0, j = 0;
- struct dpaa2_dev_priv *priv = dev->data->dev_private;
- struct dpaa2_dev_flow *curr = LIST_FIRST(&priv->flows);
- uint16_t dist_size, key_size;
- struct dpaa2_key_extract *qos_key_extract;
- struct dpaa2_key_extract *tc_key_extract;
- struct rte_dpaa2_flow_item *dpaa2_pattern = NULL;
-
- ret = dpaa2_flow_verify_attr(priv, attr);
- if (ret)
- return ret;
+ int ret;
- ret = dpaa2_flow_verify_action(priv, attr, actions);
- if (ret)
- return ret;
+ if (dist_type == DPAA2_FLOW_FS_TYPE) {
+ ret = dpaa2_flow_fs_rss_table_config(priv, tc_id, is_rss);
+ if (ret)
+ return ret;
+ } else if (dist_type == DPAA2_FLOW_QOS_TYPE) {
+ ret = dpaa2_flow_qos_table_config(priv, false);
+ if (ret)
+ return ret;
+ } else {
+ DPAA2_PMD_ERR("Invalid dist type(%d)!", dist_type);
+ return -EINVAL;
+ }
- ret = dpaa2_flow_item_convert(pattern, &dpaa2_pattern,
- priv->sp_protocol);
- if (ret)
- return ret;
+ return 0;
+}
- /* Parse pattern list to get the matching parameters */
- while (!end_of_list) {
- switch (pattern[i].type) {
+static int
+dpaa2_flow_action_meter_mark_init(struct dpaa2_dev_priv *priv,
+ uint32_t mtr_id, struct rte_flow_action_meter_mark *meter_mark)
+{
+ struct dpaa2_dev_meter *meter;
+ struct dpaa2_dev_meter_profile *profile;
+ struct dpaa2_dev_meter_policy *policy;
+ int found = 0;
+
+ meter = LIST_FIRST(&priv->meters);
+ while (meter) {
+ if (meter->meter_id == mtr_id) {
+ found = 1;
+ break;
+ }
+ meter = LIST_NEXT(meter, next);
+ }
+
+ if (!found) {
+ DPAA2_PMD_ERR("Meter ID(%d) is not found!", mtr_id);
+ return -ENXIO;
+ }
+
+ found = 0;
+ profile = LIST_FIRST(&priv->profiles);
+ while (profile) {
+ if (profile->profile_id == meter->profile_id) {
+ found = 1;
+ break;
+ }
+ profile = LIST_NEXT(profile, next);
+ }
+ if (!found) {
+ DPAA2_PMD_ERR("Meter ID(%d)'s profile(%d) not exist!",
+ mtr_id, meter->profile_id);
+ return -ENXIO;
+ }
+
+ found = 0;
+ policy = LIST_FIRST(&priv->policies);
+ while (policy) {
+ if (policy->policy_id == meter->policy_id) {
+ found = 1;
+ break;
+ }
+ policy = LIST_NEXT(policy, next);
+ }
+ if (!found) {
+ /** Option.*/
+ DPAA2_PMD_WARN("Meter ID(%d)'s policy(%d) not exist!",
+ mtr_id, meter->policy_id);
+ policy = NULL;
+ }
+
+ meter_mark->profile = (void *)profile;
+ meter_mark->policy = (void *)policy;
+ meter_mark->color_mode = 1;
+
+ return 0;
+}
+
+static int
+dpaa2_flow_set_police_action(struct dpaa2_dev_priv *priv,
+ uint8_t tc_id, const struct rte_flow_action_meter_mark *meter_mark)
+{
+ struct rte_dpaa2_device *dpaa2_dev;
+ struct dpni_rx_tc_policing_cfg policing_cfg = {0};
+ const struct dpaa2_dev_meter_profile *dpaa2_profile;
+ const struct dpaa2_dev_meter_policy *dpaa2_policy = NULL;
+ int ret;
+
+ if (!(priv->options & DPNI_OPT_HAS_POLICING)) {
+ DPAA2_PMD_ERR("POLICING(0x%08x) was not added in DPNI creating options(0x%08x)",
+ DPNI_OPT_HAS_POLICING, priv->options);
+ return -ENOTSUP;
+ }
+
+ dpaa2_dev = DPAA2_DEV_PRIV_TO_DPAA2_DEV(priv);
+
+ dpaa2_profile = (void *)meter_mark->profile;
+ if (!dpaa2_profile) {
+ DPAA2_PMD_ERR("Meter profile not specified!");
+ return -EINVAL;
+ }
+
+ /** Blind as default.*/
+ policing_cfg.options = 0;
+ if (meter_mark->color_mode)
+ policing_cfg.options = DPNI_POLICER_OPT_COLOR_AWARE;
+ if (meter_mark->policy)
+ dpaa2_policy = (void *)meter_mark->policy;
+ if (dpaa2_policy && dpaa2_policy->red_drop) {
+ policing_cfg.options |= DPNI_POLICER_OPT_DISCARD_RED;
+ } else if (!dpaa2_policy) {
+ /** Default: Red is discarded if no policy specified.*/
+ policing_cfg.options |= DPNI_POLICER_OPT_DISCARD_RED;
+ }
+
+ if (priv->flow_profile.mtr_flow[tc_id]) {
+ /** Update existing policer.*/
+ dpaa2_dev = DPAA2_DEV_PRIV_TO_DPAA2_DEV(priv);
+ policing_cfg.options |= DPNI_POLICER_OPT_DO_NOT_RESET_COUNTERS;
+ if (dpaa2_dev->bus_info->mc_rev < DPAA2_POLICER_NOT_RESET_COUNTER_MC_REV)
+ DPAA2_PMD_WARN("The existing policer's counters will be cleaned.");
+ }
+
+ policing_cfg.mode = dpaa2_profile->mode;
+ if (policing_cfg.mode < DPNI_POLICER_MODE_NONE ||
+ policing_cfg.mode > DPNI_POLICER_MODE_RFC_4115) {
+ DPAA2_PMD_ERR("Invalid policer mode(%d)",
+ policing_cfg.mode);
+ return -EINVAL;
+ }
+ policing_cfg.units = dpaa2_profile->policer_unit;
+ if (policing_cfg.units < DPNI_POLICER_UNIT_BYTES_L3 ||
+ policing_cfg.units > DPNI_POLICER_UNIT_BYTES_L2_WITHOUT_FCS) {
+ DPAA2_PMD_ERR("Invalid policer units(%d)",
+ policing_cfg.units);
+ return -EINVAL;
+ }
+ policing_cfg.cir = dpaa2_profile->cir;
+ policing_cfg.cbs = dpaa2_profile->cbs;
+ policing_cfg.eir = dpaa2_profile->pir;
+ policing_cfg.ebs = dpaa2_profile->pbs;
+
+ if (dpaa2_dev->bus_info->mc_rev < DPAA2_POLICER_SET_V2_MC_REV) {
+ ret = dpni_set_rx_tc_policing_v1(priv->hw, CMD_PRI_LOW,
+ priv->token, tc_id, &policing_cfg);
+ } else {
+ ret = dpni_set_rx_tc_policing(priv->hw, CMD_PRI_LOW,
+ priv->token, tc_id, &policing_cfg);
+ }
+ DPAA2_PMD_INFO("%s RX TC%d policer configure %s.",
+ priv->eth_dev->data->name, tc_id,
+ ret ? "failed" : "successfully");
+ if (!ret)
+ priv->flow_profile.tc_mtr_profile[tc_id] = (void *)meter_mark->profile;
+
+ return ret;
+}
+
+static int
+dpaa2_flow_action_single_type_check(const struct rte_flow_action actions[],
+ enum rte_flow_action_type type)
+{
+ if (actions[0].type == type &&
+ actions[1].type == RTE_FLOW_ACTION_TYPE_END)
+ return true;
+
+ return false;
+}
+
+static int
+dpaa2_flow_qos_action_update(struct dpaa2_dev_priv *priv,
+ struct dpaa2_generic_flow *flow,
+ const struct rte_flow_action actions[], int new_flow)
+{
+ int end_of_list = 0, ret = 0, i = 0, set_jump = 0;
+ struct dpaa2_dev_flow_qos_action *qos_action;
+
+ RTE_SET_USED(priv);
+ qos_action = &flow->flow_action.qos_action;
+
+ while (!end_of_list) {
+ switch (actions[i].type) {
+ case RTE_FLOW_ACTION_TYPE_JUMP:
+ qos_action->action_jump_type = actions[i].type;
+ rte_memcpy(&qos_action->action_jump_cfg, actions[i].conf,
+ sizeof(struct rte_flow_action_jump));
+ set_jump++;
+ break;
+ case RTE_FLOW_ACTION_TYPE_END:
+ end_of_list = 1;
+ break;
+ default:
+ DPAA2_PMD_ERR("Invalid action[%d]'s type(%d)",
+ i, actions[i].type);
+ ret = -ENOTSUP;
+ goto end_action_set;
+ }
+ i++;
+ }
+
+end_action_set:
+ if (!set_jump && !ret && new_flow)
+ return -EINVAL;
+
+ return ret;
+}
+
+static int
+dpaa2_flow_fs_action_update(struct dpaa2_dev_priv *priv,
+ struct dpaa2_generic_flow *fs_flow,
+ const struct rte_flow_action actions[])
+{
+ int end_of_list = 0, ret = 0, i = 0;
+ const struct rte_flow_action_meter *meter;
+ struct rte_flow_action_meter_mark meter_mark;
+ union dpaa2_dev_flow_action flow_action_rollback;
+
+ rte_memcpy(&flow_action_rollback, &fs_flow->flow_action,
+ sizeof(union dpaa2_dev_flow_action));
+ memset(&fs_flow->flow_action, 0, sizeof(union dpaa2_dev_flow_action));
+
+ while (!end_of_list) {
+ switch (actions[i].type) {
+ case RTE_FLOW_ACTION_TYPE_QUEUE:
+ case RTE_FLOW_ACTION_TYPE_REPRESENTED_PORT:
+ case RTE_FLOW_ACTION_TYPE_PORT_ID:
+ case RTE_FLOW_ACTION_TYPE_DROP:
+ case RTE_FLOW_ACTION_TYPE_RSS:
+ ret = dpaa2_flow_fs_action_config(priv, fs_flow, &actions[i]);
+ if (ret)
+ goto end_action_set;
+
+ break;
+ case RTE_FLOW_ACTION_TYPE_METER_MARK:
+ rte_memcpy(&meter_mark, actions[i].conf,
+ sizeof(meter_mark));
+ ret = dpaa2_flow_set_police_action(priv,
+ fs_flow->tc_id, &meter_mark);
+ if (ret)
+ goto end_action_set;
+ break;
+ case RTE_FLOW_ACTION_TYPE_METER:
+ meter = actions[i].conf;
+ ret = dpaa2_flow_action_meter_mark_init(priv,
+ meter->mtr_id, &meter_mark);
+ if (ret)
+ goto end_action_set;
+ ret = dpaa2_flow_set_police_action(priv,
+ fs_flow->tc_id, &meter_mark);
+ if (ret)
+ goto end_action_set;
+
+ break;
+ case RTE_FLOW_ACTION_TYPE_PF:
+ /* Skip this action, have to add for vxlan*/
+ break;
+ case RTE_FLOW_ACTION_TYPE_END:
+ end_of_list = 1;
+ break;
+ default:
+ DPAA2_PMD_ERR("Invalid action[%d]'s type(%d)",
+ i, actions[i].type);
+ ret = -ENOTSUP;
+ goto end_action_set;
+ }
+ i++;
+ }
+
+end_action_set:
+ if (ret || i < 1) {
+ rte_memcpy(&fs_flow->flow_action, &flow_action_rollback,
+ sizeof(union dpaa2_dev_flow_action));
+ }
+ if (ret)
+ return ret;
+
+ if (i < 1) {
+ DPAA2_PMD_ERR("No action is set!");
+ return -EINVAL;
+ }
+ if (i > 2) {
+ DPAA2_PMD_WARN("Only last of %d actions is applied",
+ i - 1);
+ }
+
+ return 0;
+}
+
+static int
+dpaa2_flow_generic_extract_rule_set(struct dpaa2_generic_flow *flow,
+ const struct rte_flow_attr *attr,
+ const struct rte_flow_item pattern[], int is_rss,
+ enum dpaa2_flow_dist_type dist_type, int update)
+{
+ int extract_cfg = 0, end_of_list = 0;
+ int ret = 0, i = 0;
+ struct dpaa2_dev_priv *priv = flow->priv;
+ uint16_t key_size;
+ struct dpaa2_flow_tbl_profile *tbl_profile;
+ struct rte_dpaa2_flow_item *dpaa2_pattern = NULL;
+
+ ret = dpaa2_flow_item_convert(pattern, &dpaa2_pattern,
+ priv->sp_protocol);
+ if (ret)
+ return ret;
+
+ flow->ip_key = NET_PROT_NONE;
+ flow->ip_src = NET_PROT_NONE;
+ flow->ip_dst = NET_PROT_NONE;
+
+ if (dist_type == DPAA2_FLOW_QOS_TYPE)
+ tbl_profile = &priv->flow_profile.qos_profile;
+ else
+ tbl_profile = &priv->flow_profile.tc_profile[attr->group];
+
+ if (is_rss || (!is_rss && tbl_profile->is_rss)) {
+ RTE_ASSERT(dist_type == DPAA2_FLOW_FS_TYPE);
+ if (!update) {
+ dpaa2_flow_clean(priv->eth_dev, attr->group);
+ tbl_profile->rss_flow = NULL;
+ }
+ if (!is_rss)
+ tbl_profile->tc_cfg.dist_size = priv->dist_queues;
+ memset(&tbl_profile->dpkg, 0,
+ sizeof(struct dpkg_profile_cfg));
+ memset(&tbl_profile->key_profile, 0,
+ sizeof(struct dpaa2_key_profile));
+ }
+
+ /* Parse pattern list to get the matching parameters */
+ while (!end_of_list) {
+ switch (pattern[i].type) {
case RTE_FLOW_ITEM_TYPE_ETH:
- ret = dpaa2_configure_flow_eth(flow, dev, attr,
- &dpaa2_pattern[i],
- actions, error,
- &is_keycfg_configured);
+ ret = dpaa2_flow_eth_extract_rule_set(flow, attr,
+ &dpaa2_pattern[i], &extract_cfg, dist_type);
if (ret) {
DPAA2_PMD_ERR("ETH flow config failed!");
- goto end_flow_set;
+ goto end_extract_set;
}
break;
case RTE_FLOW_ITEM_TYPE_VLAN:
- ret = dpaa2_configure_flow_vlan(flow, dev, attr,
- &dpaa2_pattern[i],
- actions, error,
- &is_keycfg_configured);
+ ret = dpaa2_flow_vlan_extract_rule_set(flow, attr,
+ &dpaa2_pattern[i], &extract_cfg, dist_type);
if (ret) {
DPAA2_PMD_ERR("vLan flow config failed!");
- goto end_flow_set;
+ goto end_extract_set;
}
break;
case RTE_FLOW_ITEM_TYPE_IPV4:
- ret = dpaa2_configure_flow_ipv4(flow, dev, attr,
- &dpaa2_pattern[i],
- actions, error,
- &is_keycfg_configured);
+ ret = dpaa2_flow_ipv4_extract_rule_set(flow, attr,
+ &dpaa2_pattern[i], &extract_cfg, dist_type);
if (ret) {
DPAA2_PMD_ERR("IPV4 flow config failed!");
- goto end_flow_set;
+ goto end_extract_set;
}
break;
case RTE_FLOW_ITEM_TYPE_IPV6:
- ret = dpaa2_configure_flow_ipv6(flow, dev, attr,
- &dpaa2_pattern[i],
- actions, error,
- &is_keycfg_configured);
+ ret = dpaa2_flow_ipv6_extract_rule_set(flow, attr,
+ &dpaa2_pattern[i], &extract_cfg, dist_type);
if (ret) {
DPAA2_PMD_ERR("IPV6 flow config failed!");
- goto end_flow_set;
+ goto end_extract_set;
}
break;
case RTE_FLOW_ITEM_TYPE_ICMP:
- ret = dpaa2_configure_flow_icmp(flow, dev, attr,
- &dpaa2_pattern[i],
- actions, error,
- &is_keycfg_configured);
+ ret = dpaa2_flow_icmp_extract_rule_set(flow, attr,
+ &dpaa2_pattern[i], &extract_cfg, dist_type);
if (ret) {
DPAA2_PMD_ERR("ICMP flow config failed!");
- goto end_flow_set;
+ goto end_extract_set;
}
break;
case RTE_FLOW_ITEM_TYPE_UDP:
- ret = dpaa2_configure_flow_udp(flow, dev, attr,
- &dpaa2_pattern[i],
- actions, error,
- &is_keycfg_configured);
+ ret = dpaa2_flow_udp_extract_rule_set(flow, attr,
+ &dpaa2_pattern[i], &extract_cfg, dist_type);
if (ret) {
DPAA2_PMD_ERR("UDP flow config failed!");
- goto end_flow_set;
+ goto end_extract_set;
}
break;
case RTE_FLOW_ITEM_TYPE_TCP:
- ret = dpaa2_configure_flow_tcp(flow, dev, attr,
- &dpaa2_pattern[i],
- actions, error,
- &is_keycfg_configured);
+ ret = dpaa2_flow_tcp_extract_rule_set(flow, attr,
+ &dpaa2_pattern[i], &extract_cfg, dist_type);
if (ret) {
DPAA2_PMD_ERR("TCP flow config failed!");
- goto end_flow_set;
+ goto end_extract_set;
}
break;
case RTE_FLOW_ITEM_TYPE_SCTP:
- ret = dpaa2_configure_flow_sctp(flow, dev, attr,
- &dpaa2_pattern[i],
- actions, error,
- &is_keycfg_configured);
+ ret = dpaa2_flow_sctp_extract_rule_set(flow, attr,
+ &dpaa2_pattern[i], &extract_cfg, dist_type);
if (ret) {
DPAA2_PMD_ERR("SCTP flow config failed!");
- goto end_flow_set;
+ goto end_extract_set;
}
break;
case RTE_FLOW_ITEM_TYPE_ESP:
- ret = dpaa2_configure_flow_esp(flow,
- dev, attr, &dpaa2_pattern[i],
- actions, error,
- &is_keycfg_configured);
+ ret = dpaa2_flow_esp_extract_rule_set(flow, attr,
+ &dpaa2_pattern[i], &extract_cfg, dist_type);
if (ret) {
DPAA2_PMD_ERR("ESP flow config failed!");
- goto end_flow_set;
+ goto end_extract_set;
}
break;
case RTE_FLOW_ITEM_TYPE_AH:
- ret = dpaa2_configure_flow_ah(flow,
- dev, attr, &dpaa2_pattern[i],
- actions, error,
- &is_keycfg_configured);
+ ret = dpaa2_flow_ah_extract_rule_set(flow, attr,
+ &dpaa2_pattern[i], &extract_cfg, dist_type);
if (ret) {
DPAA2_PMD_ERR("AH flow config failed!");
- goto end_flow_set;
+ goto end_extract_set;
}
break;
case RTE_FLOW_ITEM_TYPE_GRE:
- ret = dpaa2_configure_flow_gre(flow, dev, attr,
- &dpaa2_pattern[i],
- actions, error,
- &is_keycfg_configured);
+ ret = dpaa2_flow_gre_extract_rule_set(flow, attr,
+ &dpaa2_pattern[i], &extract_cfg, dist_type);
if (ret) {
DPAA2_PMD_ERR("GRE flow config failed!");
- goto end_flow_set;
+ goto end_extract_set;
}
break;
case RTE_FLOW_ITEM_TYPE_VXLAN:
- ret = dpaa2_configure_flow_vxlan(flow, dev, attr,
- &dpaa2_pattern[i],
- actions, error,
- &is_keycfg_configured);
+ ret = dpaa2_flow_vxlan_extract_rule_set(flow, attr,
+ &dpaa2_pattern[i], &extract_cfg, dist_type);
if (ret) {
DPAA2_PMD_ERR("VXLAN flow config failed!");
- goto end_flow_set;
+ goto end_extract_set;
}
break;
case RTE_FLOW_ITEM_TYPE_ECPRI:
- ret = dpaa2_configure_flow_ecpri(flow,
- dev, attr, &dpaa2_pattern[i],
- actions, error,
- &is_keycfg_configured);
+ ret = dpaa2_flow_ecpri_extract_rule_set(flow, attr,
+ &dpaa2_pattern[i], &extract_cfg, dist_type);
if (ret) {
DPAA2_PMD_ERR("ECPRI flow config failed!");
- goto end_flow_set;
+ goto end_extract_set;
}
break;
case RTE_FLOW_ITEM_TYPE_GTP:
- ret = dpaa2_configure_flow_gtp(flow,
- dev, attr, &dpaa2_pattern[i],
- actions, error,
- &is_keycfg_configured);
+ ret = dpaa2_flow_gtp_extract_rule_set(flow, attr,
+ &dpaa2_pattern[i], &extract_cfg, dist_type);
if (ret) {
DPAA2_PMD_ERR("GTP flow config failed!");
- goto end_flow_set;
- }
- break;
- case RTE_FLOW_ITEM_TYPE_MPLS:
- ret = dpaa2_configure_flow_mpls(flow,
- dev, attr, &dpaa2_pattern[i],
- actions, error,
- &is_keycfg_configured);
- if (ret) {
- DPAA2_PMD_ERR("MPLS flow config failed!");
- goto end_flow_set;
+ goto end_extract_set;
}
break;
- case RTE_FLOW_ITEM_TYPE_PPPOES:
- ret = dpaa2_configure_flow_pppoe(flow,
- dev, attr, &dpaa2_pattern[i],
- actions, error,
- &is_keycfg_configured);
+ case RTE_FLOW_ITEM_TYPE_GENEVE:
+ ret = dpaa2_flow_geneve_extract_rule_set(flow, attr,
+ &dpaa2_pattern[i], &extract_cfg, dist_type);
if (ret) {
- DPAA2_PMD_ERR("PPPoE flow config failed!");
- goto end_flow_set;
+ DPAA2_PMD_ERR("GENEVE flow config failed!");
+ goto end_extract_set;
}
break;
case RTE_FLOW_ITEM_TYPE_RAW:
- ret = dpaa2_configure_flow_raw(flow, dev, attr,
- &dpaa2_pattern[i],
- actions, error,
- &is_keycfg_configured);
+ ret = dpaa2_flow_raw_extract_rule_set(flow, attr,
+ &dpaa2_pattern[i], &extract_cfg, dist_type);
if (ret) {
DPAA2_PMD_ERR("RAW flow config failed!");
- goto end_flow_set;
+ goto end_extract_set;
}
break;
case RTE_FLOW_ITEM_TYPE_END:
@@ -4907,164 +4594,104 @@ dpaa2_generic_flow_set(struct dpaa2_dev_flow *flow,
DPAA2_PMD_ERR("Invalid flow item[%d] type(%d)",
i, pattern[i].type);
ret = -ENOTSUP;
- break;
+ goto end_extract_set;
}
i++;
}
- qos_key_extract = &priv->extract.qos_key_extract;
- key_size = qos_key_extract->key_profile.key_max_size;
- flow->qos_rule.key_size = dpaa2_flow_entry_size(key_size);
-
- tc_key_extract = &priv->extract.tc_key_extract[flow->tc_id];
- key_size = tc_key_extract->key_profile.key_max_size;
- flow->fs_rule.key_size = dpaa2_flow_entry_size(key_size);
-
- /* Let's parse action on matching traffic */
- end_of_list = 0;
- while (!end_of_list) {
- switch (actions[j].type) {
- case RTE_FLOW_ACTION_TYPE_QUEUE:
- case RTE_FLOW_ACTION_TYPE_REPRESENTED_PORT:
- case RTE_FLOW_ACTION_TYPE_PORT_ID:
- case RTE_FLOW_ACTION_TYPE_DROP:
- ret = dpaa2_configure_flow_fs_action(priv, flow,
- &actions[j]);
- if (ret)
- goto end_flow_set;
-
- /* Configure FS table first*/
- dist_size = priv->nb_rx_queues / priv->num_rx_tc;
- if (is_keycfg_configured & DPAA2_FLOW_FS_TYPE) {
- ret = dpaa2_configure_fs_rss_table(priv,
- flow->tc_id,
- dist_size,
- false);
- if (ret)
- goto end_flow_set;
- }
-
- /* Configure QoS table then.*/
- if (is_keycfg_configured & DPAA2_FLOW_QOS_TYPE) {
- ret = dpaa2_configure_qos_table(priv, false);
- if (ret)
- goto end_flow_set;
- }
-
- if (priv->num_rx_tc > 1) {
- ret = dpaa2_flow_add_qos_rule(priv, flow);
- if (ret)
- goto end_flow_set;
- }
+ key_size = tbl_profile->key_profile.key_max_size;
+ flow->rule_cfg.key_size = dpaa2_flow_entry_size(key_size);
- if (flow->tc_index >= priv->fs_entries) {
- DPAA2_PMD_ERR("FS table with %d entries full",
- priv->fs_entries);
- return -1;
- }
+ if (!extract_cfg)
+ goto end_extract_set;
- ret = dpaa2_flow_add_fs_rule(priv, flow);
- if (ret)
- goto end_flow_set;
+ ret = dpaa2_flow_table_update(priv, dist_type, attr->group, is_rss);
- break;
- case RTE_FLOW_ACTION_TYPE_RSS:
- rss_conf = actions[j].conf;
- flow->action_type = RTE_FLOW_ACTION_TYPE_RSS;
-
- ret = dpaa2_distset_to_dpkg_profile_cfg(rss_conf->types,
- &tc_key_extract->dpkg);
- if (ret < 0) {
- DPAA2_PMD_ERR("TC[%d] distset RSS failed",
- flow->tc_id);
- goto end_flow_set;
- }
+end_extract_set:
+ if (dpaa2_pattern)
+ rte_free(dpaa2_pattern);
- dist_size = rss_conf->queue_num;
- if (is_keycfg_configured & DPAA2_FLOW_FS_TYPE) {
- ret = dpaa2_configure_fs_rss_table(priv,
- flow->tc_id,
- dist_size,
- true);
- if (ret)
- goto end_flow_set;
- }
+ return ret;
+}
- if (is_keycfg_configured & DPAA2_FLOW_QOS_TYPE) {
- ret = dpaa2_configure_qos_table(priv, true);
- if (ret)
- goto end_flow_set;
- }
+static inline int
+dpaa2_flow_verify_attr(struct dpaa2_dev_priv *priv,
+ const struct rte_flow_attr *attr, uint32_t *pgroup_type,
+ uint32_t *pgroup_id)
+{
+ int ret = 0;
+ uint32_t group_id, group_type;
- ret = dpaa2_flow_add_qos_rule(priv, flow);
- if (ret)
- goto end_flow_set;
+ group_type = RTE_DPAA2_FLOW_GROUP_TYPE_GET(attr->group);
+ group_id = RTE_DPAA2_FLOW_GROUP_ID_GET(attr->group);
+ if (group_id >= priv->num_rx_tc &&
+ group_type == RTE_DPAA2_ONE_LEVEL_GROUP_FLOW) {
+ group_type = RTE_DPAA2_QOS_GROUP_FLOW;
+ group_id = DPAA2_FLOW_QOS_GROUP_ID;
+ }
- ret = dpaa2_flow_add_fs_rule(priv, flow);
- if (ret)
- goto end_flow_set;
+ if (group_type == RTE_DPAA2_FS_GROUP_FLOW && !priv->fs_entries) {
+ DPAA2_PMD_ERR("No FS table created to support FS flow!");
+ ret = -EINVAL;
+ goto complete_verify;
+ }
- break;
- case RTE_FLOW_ACTION_TYPE_PF:
- /* Skip this action, have to add for vxlan */
- break;
- case RTE_FLOW_ACTION_TYPE_END:
- end_of_list = 1;
- break;
- default:
- DPAA2_PMD_ERR("Invalid action type");
+ if (group_type == RTE_DPAA2_QOS_GROUP_FLOW) {
+ if (attr->priority >= priv->qos_entries) {
+ DPAA2_PMD_ERR("Prior(%d) is out of range(%d)",
+ attr->priority, priv->qos_entries);
ret = -ENOTSUP;
- break;
+ goto complete_verify;
}
- j++;
+ goto complete_verify_group;
}
-end_flow_set:
- if (!ret) {
- /* New rules are inserted. */
- if (!curr) {
- LIST_INSERT_HEAD(&priv->flows, flow, next);
- } else {
- while (LIST_NEXT(curr, next))
- curr = LIST_NEXT(curr, next);
- LIST_INSERT_AFTER(curr, flow, next);
+ if (group_type == RTE_DPAA2_ONE_LEVEL_GROUP_FLOW ||
+ group_type == RTE_DPAA2_FS_GROUP_FLOW) {
+ if (group_id >= priv->num_rx_tc) {
+ DPAA2_PMD_ERR("Group(%d) is out of range(%d)",
+ group_id, priv->num_rx_tc);
+ ret = -ENOTSUP;
+ goto complete_verify;
+ }
+ if (group_type == RTE_DPAA2_ONE_LEVEL_GROUP_FLOW &&
+ (attr->priority + priv->fs_entries * group_id) >= priv->qos_entries) {
+ DPAA2_PMD_ERR("Prior(%d) + fs entries(%d) * group(%d) is out of range(%d)",
+ attr->priority, priv->fs_entries, group_id,
+ priv->qos_entries);
+ ret = -ENOTSUP;
+ goto complete_verify;
}
+ } else {
+ DPAA2_PMD_ERR("Invalid group type(%d)", group_type);
+ ret = -EINVAL;
+ goto complete_verify;
}
- rte_free(dpaa2_pattern);
-
- return ret;
-}
-
-static inline int
-dpaa2_dev_verify_attr(struct dpni_attr *dpni_attr,
- const struct rte_flow_attr *attr)
-{
- int ret = 0;
-
- if (unlikely(attr->group >= dpni_attr->num_rx_tcs)) {
- DPAA2_PMD_ERR("Group/TC(%d) is out of range(%d)",
- attr->group, dpni_attr->num_rx_tcs);
- ret = -ENOTSUP;
- }
- if (unlikely(attr->priority >= dpni_attr->fs_entries)) {
- DPAA2_PMD_ERR("Priority(%d) within group is out of range(%d)",
- attr->priority, dpni_attr->fs_entries);
- ret = -ENOTSUP;
- }
+complete_verify_group:
if (unlikely(attr->egress)) {
DPAA2_PMD_ERR("Egress flow configuration is not supported");
ret = -ENOTSUP;
+ goto complete_verify;
}
if (unlikely(!attr->ingress)) {
DPAA2_PMD_ERR("Ingress flag must be configured");
ret = -EINVAL;
}
+
+complete_verify:
+ if (!ret) {
+ if (pgroup_type)
+ *pgroup_type = group_type;
+ if (pgroup_id)
+ *pgroup_id = group_id;
+ }
+
return ret;
}
static inline int
-dpaa2_dev_verify_patterns(const struct rte_flow_item pattern[],
+dpaa2_flow_verify_patterns(const struct rte_flow_item pattern[],
int sp_support)
{
unsigned int i, j, is_found = 0;
@@ -5109,29 +4736,32 @@ dpaa2_dev_verify_patterns(const struct rte_flow_item pattern[],
}
static inline int
-dpaa2_dev_verify_actions(const struct rte_flow_action actions[])
+dpaa2_flow_check_actions_support(const struct rte_flow_action actions[],
+ const enum rte_flow_action_type supported[], uint16_t len)
{
unsigned int i, j, is_found = 0;
- int ret = 0;
for (j = 0; actions[j].type != RTE_FLOW_ACTION_TYPE_END; j++) {
- for (i = 0; i < RTE_DIM(dpaa2_supported_action_type); i++) {
- if (dpaa2_supported_action_type[i] == actions[j].type) {
+ is_found = 0;
+ for (i = 0; i < len; i++) {
+ if (supported[i] == actions[j].type) {
is_found = 1;
break;
}
}
- if (!is_found) {
- ret = -ENOTSUP;
- break;
- }
+ if (!is_found)
+ return false;
}
for (j = 0; actions[j].type != RTE_FLOW_ACTION_TYPE_END; j++) {
if (actions[j].type != RTE_FLOW_ACTION_TYPE_DROP &&
- !actions[j].conf)
- ret = -EINVAL;
+ !actions[j].conf) {
+ DPAA2_PMD_ERR("No config for actions[%d].type(%d)",
+ j, actions[j].type);
+ return false;
+ }
}
- return ret;
+
+ return true;
}
static int
@@ -5142,238 +4772,1649 @@ dpaa2_flow_validate(struct rte_eth_dev *dev,
struct rte_flow_error *error)
{
struct dpaa2_dev_priv *priv = dev->data->dev_private;
- struct dpni_attr dpni_attr;
- struct fsl_mc_io *dpni = (struct fsl_mc_io *)priv->hw;
- uint16_t token = priv->token;
+ uint16_t supported_len = 0;
int ret = 0;
+ uint32_t group_type;
+ const enum rte_flow_action_type *supported = NULL;
+ const char *err_str = NULL;
+ const void *cause = NULL;
+ enum rte_flow_error_type err_type = RTE_FLOW_ERROR_TYPE_NONE;
- memset(&dpni_attr, 0, sizeof(struct dpni_attr));
- ret = dpni_get_attributes(dpni, CMD_PRI_LOW, token, &dpni_attr);
- if (ret < 0) {
- DPAA2_PMD_ERR("Get dpni@%d attribute failed(%d)",
- priv->hw_id, ret);
- rte_flow_error_set(error, EPERM,
- RTE_FLOW_ERROR_TYPE_ATTR,
- flow_attr, "invalid");
- return ret;
+ /* Verify input attributes */
+ ret = dpaa2_flow_verify_attr(priv, flow_attr, &group_type, NULL);
+ if (ret) {
+ err_str = "Invalid attributes are given";
+ cause = flow_attr;
+ err_type = RTE_FLOW_ERROR_TYPE_ATTR;
+ goto invalid_params;
}
- /* Verify input attributes */
- ret = dpaa2_dev_verify_attr(&dpni_attr, flow_attr);
- if (ret < 0) {
- DPAA2_PMD_ERR("Invalid attributes are given");
- rte_flow_error_set(error, EPERM,
- RTE_FLOW_ERROR_TYPE_ATTR,
- flow_attr, "invalid");
- goto not_valid_params;
- }
- /* Verify input pattern list */
- ret = dpaa2_dev_verify_patterns(pattern, priv->sp_protocol);
- if (ret < 0) {
- DPAA2_PMD_ERR("Invalid pattern list is given");
- rte_flow_error_set(error, EPERM,
- RTE_FLOW_ERROR_TYPE_ITEM,
- pattern, "invalid");
- goto not_valid_params;
+ if (pattern) {
+ /* Verify input pattern list */
+ ret = dpaa2_flow_verify_patterns(pattern, priv->sp_protocol);
+ if (ret) {
+ err_str = "Invalid pattern list is given";
+ cause = pattern;
+ err_type = RTE_FLOW_ERROR_TYPE_ITEM;
+ goto invalid_params;
+ }
+ }
+
+ supported = dpaa2_supported_meter_action_type;
+ supported_len = RTE_DIM(dpaa2_supported_meter_action_type);
+ if (dpaa2_flow_check_actions_support(actions, supported, supported_len)) {
+ DPAA2_PMD_DEBUG("This is meter flow.");
+ if (group_type == RTE_DPAA2_QOS_GROUP_FLOW) {
+ err_str = "Meter flow's type can't be QoS flow.";
+ cause = actions;
+ err_type = RTE_FLOW_ERROR_TYPE_ACTION;
+ ret = -EPERM;
+ goto invalid_params;
+ }
+ if (actions[1].type != RTE_FLOW_ACTION_TYPE_END) {
+ err_str = "Meter flow can't support multi-actions.";
+ cause = actions;
+ err_type = RTE_FLOW_ERROR_TYPE_ACTION_NUM;
+ ret = -EPERM;
+ goto invalid_params;
+ }
+ if (pattern)
+ DPAA2_PMD_WARN("Meter flow ingores flow items!");
+ return 0;
}
+
/* Verify input action list */
- ret = dpaa2_dev_verify_actions(actions);
- if (ret < 0) {
- DPAA2_PMD_ERR("Invalid action list is given");
- rte_flow_error_set(error, EPERM,
- RTE_FLOW_ERROR_TYPE_ACTION,
- actions, "invalid");
- goto not_valid_params;
+ if (group_type == RTE_DPAA2_ONE_LEVEL_GROUP_FLOW ||
+ group_type == RTE_DPAA2_FS_GROUP_FLOW) {
+ supported = dpaa2_supported_fs_action_type;
+ supported_len = RTE_DIM(dpaa2_supported_fs_action_type);
+ } else {
+ supported = dpaa2_supported_qos_action_type;
+ supported_len = RTE_DIM(dpaa2_supported_qos_action_type);
+ }
+ if (!dpaa2_flow_check_actions_support(actions, supported, supported_len)) {
+ err_str = "Invalid action list is given";
+ cause = actions;
+ err_type = RTE_FLOW_ERROR_TYPE_ACTION;
+ ret = -ENOTSUP;
+ goto invalid_params;
}
-not_valid_params:
+
+invalid_params:
+ if (err_str)
+ DPAA2_PMD_ERR("%s: %s", __func__, err_str);
+ rte_flow_error_set(error, -ret, err_type, cause, err_str);
+
return ret;
}
-static struct rte_flow *
-dpaa2_flow_create(struct rte_eth_dev *dev, const struct rte_flow_attr *attr,
- const struct rte_flow_item pattern[],
- const struct rte_flow_action actions[],
- struct rte_flow_error *error)
+static int
+dpaa2_flow_is_ip_addr_extract(const struct dpkg_extract *extract)
{
- struct dpaa2_dev_flow *flow = NULL;
- struct dpaa2_dev_priv *priv = dev->data->dev_private;
- int ret;
- uint64_t iova;
+ enum dpkg_extract_type type = extract->type;
+ enum net_prot prot = extract->extract.from_hdr.prot;
+ uint32_t field = extract->extract.from_hdr.field;
- dpaa2_flow_control_log =
- getenv("DPAA2_FLOW_CONTROL_LOG");
+ if (type == DPKG_EXTRACT_FROM_HDR && prot == NET_PROT_IP &&
+ (field == NH_FLD_IP_SRC || field == NH_FLD_IP_DST))
+ return true;
- flow = rte_zmalloc(NULL, sizeof(struct dpaa2_dev_flow),
- RTE_CACHE_LINE_SIZE);
- if (!flow) {
- DPAA2_PMD_ERR("Failure to allocate memory for flow");
- goto mem_failure;
- }
+ return false;
+}
- /* Allocate DMA'ble memory to write the qos rules */
- flow->qos_key_addr = rte_zmalloc(NULL,
- DPAA2_EXTRACT_ALLOC_KEY_MAX_SIZE, RTE_CACHE_LINE_SIZE);
- if (!flow->qos_key_addr) {
- DPAA2_PMD_ERR("Memory allocation failed");
- goto mem_failure;
- }
- iova = DPAA2_VADDR_TO_IOVA_AND_CHECK(flow->qos_key_addr,
- DPAA2_EXTRACT_ALLOC_KEY_MAX_SIZE);
- if (iova == RTE_BAD_IOVA) {
- DPAA2_PMD_ERR("%s: No IOMMU map for qos key(%p)",
- __func__, flow->qos_key_addr);
- goto mem_failure;
+static int
+dpaa2_flow_ip_addr_extract_pos(uint32_t field,
+ const struct dpaa2_key_profile *profile)
+{
+ if (field != NH_FLD_IP_SRC && field != NH_FLD_IP_DST)
+ return -EINVAL;
+ if (profile->ip_addr_extracts[0].field == field)
+ return 0;
+ else if (profile->ip_addr_extracts[1].field == field)
+ return 1;
+ else
+ return -ENXIO;
+}
+
+static int
+dpaa2_flow_key_offset_size(struct dpaa2_dev_flow *flow,
+ struct dpaa2_flow_tbl_profile *tbl_profile, uint8_t idx,
+ uint8_t *offset, uint8_t *size,
+ enum dpaa2_flow_dist_type type)
+{
+ struct dpkg_profile_cfg *dpkg = &tbl_profile->dpkg;
+ struct dpaa2_key_profile *profile = &tbl_profile->key_profile;
+ int pos, prev_ip_addr_pos;
+ uint32_t field;
+ uint8_t ip_addr_size = 0, ip_addr_offset = 0;
+ struct dpaa2_generic_flow *_flow;
+
+ _flow = type == DPAA2_FLOW_QOS_TYPE ? flow->qos_flow : flow->fs_flow;
+
+ if (_flow->ip_key == NET_PROT_IPV4)
+ ip_addr_size = NH_FLD_IPV4_ADDR_SIZE;
+ else if (_flow->ip_key == NET_PROT_IPV6)
+ ip_addr_size = NH_FLD_IPV6_ADDR_SIZE;
+
+ field = dpkg->extracts[idx].extract.from_hdr.field;
+ prev_ip_addr_pos = dpaa2_extract_prev_ip_addr_pos(profile);
+ if (prev_ip_addr_pos >= 0) {
+ ip_addr_offset =
+ profile->key_offset[prev_ip_addr_pos] +
+ profile->key_size[prev_ip_addr_pos];
}
- flow->qos_rule.key_iova = iova;
- flow->qos_mask_addr = rte_zmalloc(NULL,
- DPAA2_EXTRACT_ALLOC_KEY_MAX_SIZE, RTE_CACHE_LINE_SIZE);
- if (!flow->qos_mask_addr) {
- DPAA2_PMD_ERR("Memory allocation failed");
- goto mem_failure;
+ if (dpaa2_flow_is_ip_addr_extract(&dpkg->extracts[idx])) {
+ pos = dpaa2_flow_ip_addr_extract_pos(field, profile);
+ if (!ip_addr_size)
+ return -EINVAL;
+ *offset = ip_addr_offset + ip_addr_size * pos;
+ *size = ip_addr_size;
+ } else {
+ *offset = profile->key_offset[idx];
+ *size = profile->key_size[idx];
}
- iova = DPAA2_VADDR_TO_IOVA_AND_CHECK(flow->qos_mask_addr,
- DPAA2_EXTRACT_ALLOC_KEY_MAX_SIZE);
- if (iova == RTE_BAD_IOVA) {
- DPAA2_PMD_ERR("%s: No IOMMU map for qos mask(%p)",
- __func__, flow->qos_mask_addr);
+
+ return 0;
+}
+
+static int
+dpaa2_flow_rule_data_valid(struct dpaa2_dev_flow *flow,
+ uint8_t key_offset, uint8_t key_size,
+ enum dpaa2_flow_dist_type type)
+{
+ uint8_t *mask, i;
+ int valid = 0;
+ struct dpaa2_generic_flow *_flow;
+
+ _flow = type == DPAA2_FLOW_QOS_TYPE ? flow->qos_flow : flow->fs_flow;
+ mask = _flow->mask_addr + key_offset;
+
+ for (i = 0; i < key_size; i++) {
+ if (mask[i]) {
+ valid = 1;
+ break;
+ }
+ }
+
+ return valid;
+}
+
+static void
+dpaa2_flow_remove_invalid_rule_data(struct dpaa2_dev_priv *priv,
+ enum dpaa2_flow_dist_type type, uint8_t tc_id,
+ uint8_t key_offset, uint8_t key_size)
+{
+ struct dpaa2_dev_flow *flow, *next;
+ struct dpaa2_generic_flow *_flow;
+
+ flow = LIST_FIRST(&priv->flows);
+ while (flow) {
+ next = LIST_NEXT(flow, next);
+ if (type == DPAA2_FLOW_QOS_TYPE) {
+ _flow = flow->qos_flow;
+ if (!_flow)
+ goto skip_update_flow;
+ } else {
+ _flow = flow->fs_flow;
+ if (!_flow)
+ goto skip_update_flow;
+ if (_flow->tc_id != tc_id)
+ goto skip_update_flow;
+ }
+
+ if (key_offset < _flow->rule_size) {
+ memmove(_flow->key_addr + key_offset,
+ _flow->key_addr + key_offset + key_size,
+ _flow->rule_size - (key_offset + key_size));
+ memmove(_flow->mask_addr + key_offset,
+ _flow->mask_addr + key_offset + key_size,
+ _flow->rule_size - (key_offset + key_size));
+ _flow->rule_size -= key_size;
+ }
+ if (_flow->rule_cfg.key_size > _flow->rule_size) {
+ memset(_flow->key_addr + _flow->rule_size, 0,
+ _flow->rule_cfg.key_size - _flow->rule_size);
+ memset(_flow->mask_addr + _flow->rule_size, 0,
+ _flow->rule_cfg.key_size - _flow->rule_size);
+ }
+
+skip_update_flow:
+ flow = next;
+ }
+}
+
+static int
+dpaa2_flow_remove_invalid_extract(struct rte_eth_dev *dev,
+ enum dpaa2_flow_dist_type type, uint8_t tc_id)
+{
+ struct dpaa2_dev_priv *priv = dev->data->dev_private;
+ struct dpaa2_dev_flow *flow, *next;
+ uint8_t i, key_offset, key_size, j, remove_conut = 0;
+ struct dpaa2_flow_tbl_profile *tbl_profile;
+ struct dpkg_profile_cfg *dpkg;
+ struct dpaa2_key_profile *key_profile;
+ int valid[DPKG_MAX_NUM_OF_EXTRACTS], update = 0, ret, ipaddr;
+ enum net_prot prot;
+ uint32_t field, start, end;
+ uint32_t ip_src_size, ip_dst_size;
+ struct dpaa2_generic_flow *_flow;
+
+ if (type == DPAA2_FLOW_QOS_TYPE &&
+ priv->num_rx_tc <= 1) {
+ /** No QoS table.*/
+ return 0;
+ }
+
+ if (type == DPAA2_FLOW_QOS_TYPE)
+ tbl_profile = &priv->flow_profile.qos_profile;
+ else
+ tbl_profile = &priv->flow_profile.tc_profile[tc_id];
+
+ dpkg = &tbl_profile->dpkg;
+ key_profile = &tbl_profile->key_profile;
+ for (i = 0; i < key_profile->num; i++) {
+ valid[i] = 0;
+ flow = LIST_FIRST(&priv->flows);
+ while (flow) {
+ next = LIST_NEXT(flow, next);
+ _flow = type == DPAA2_FLOW_QOS_TYPE ?
+ flow->qos_flow : flow->fs_flow;
+ if (!_flow)
+ goto skip_validation;
+
+ if (type == DPAA2_FLOW_FS_TYPE &&
+ _flow->tc_id != tc_id)
+ goto skip_validation;
+
+ key_offset = 0;
+ key_size = 0;
+
+ ret = dpaa2_flow_key_offset_size(flow, tbl_profile, i,
+ &key_offset, &key_size, type);
+ if (ret)
+ goto skip_validation;
+
+ if (dpaa2_flow_rule_data_valid(flow,
+ key_offset, key_size, type)) {
+ valid[i] = 1;
+ break;
+ }
+skip_validation:
+ flow = next;
+ }
+ if (!valid[i])
+ remove_conut++;
+ }
+
+ if (remove_conut > 0) {
+ if (type == DPAA2_FLOW_QOS_TYPE) {
+ dpaa2_flow_extracts_log(priv,
+ "Before removing extract(s)", MAX_TCS);
+ } else {
+ dpaa2_flow_extracts_log(priv,
+ "Before removing extract(s)", tc_id);
+ }
+ } else {
+ return 0;
+ }
+
+ i = key_profile->num - 1;
+ while (remove_conut) {
+ if (valid[i]) {
+ if (i == 0) {
+ DPAA2_PMD_ERR("Fatal: %d key(s) not removed!",
+ remove_conut);
+ return -EINVAL;
+ }
+ i--;
+ continue;
+ }
+ key_size = key_profile->key_size[i];
+ key_offset = key_profile->key_offset[i];
+
+ for (j = i + 1; j < key_profile->num; j++)
+ key_profile->key_offset[j] -= key_size;
+
+ ipaddr = 0;
+ if (dpkg->extracts[i].type == DPKG_EXTRACT_FROM_HDR) {
+ prot = dpkg->extracts[i].extract.from_hdr.prot;
+ field = dpkg->extracts[i].extract.from_hdr.field;
+ ipaddr = dpaa2_flow_ip_address_extract(prot, field);
+ }
+ if (!ipaddr)
+ update += key_size;
+
+ if ((i + 1) < key_profile->num) {
+ memmove(&key_profile->key_offset[i],
+ &key_profile->key_offset[i + 1],
+ key_profile->num - i - 1);
+ memmove(&key_profile->key_size[i],
+ &key_profile->key_size[i + 1],
+ key_profile->num - i - 1);
+ memmove(&key_profile->prot_field[i],
+ &key_profile->prot_field[i + 1],
+ (key_profile->num - i - 1) *
+ sizeof(struct key_prot_field));
+
+ memmove(&dpkg->extracts[i], &dpkg->extracts[i + 1],
+ (key_profile->num - i - 1) *
+ sizeof(struct dpkg_extract));
+ }
+
+ dpaa2_flow_remove_invalid_rule_data(priv, type, tc_id,
+ key_offset, key_size);
+
+ key_profile->num--;
+ dpkg->num_extracts--;
+ i--;
+ remove_conut--;
+ };
+
+ key_profile->key_max_size -= update;
+ key_profile->key_max_size -=
+ (key_profile->ip_addr_extracts[0].max_size +
+ key_profile->ip_addr_extracts[1].max_size);
+
+ key_profile->l4_sp_present = 0;
+ key_profile->l4_dp_present = 0;
+ memset(key_profile->ip_addr_extracts, 0,
+ sizeof(struct dpaa2_ip_addr_extract) * 2);
+
+ if (key_profile->num >= 2)
+ start = key_profile->num - 2;
+ else if (key_profile->num >= 1)
+ start = key_profile->num - 1;
+ else
+ goto skip_ip_addr_extract;
+ end = key_profile->num;
+
+ j = 0;
+ for (i = start; i < end; i++) {
+ if (dpaa2_flow_is_ip_addr_extract(&dpkg->extracts[i])) {
+ key_profile->ip_addr_extracts[j].field =
+ dpkg->extracts[i].extract.from_hdr.field;
+ key_profile->ip_addr_extracts[j].max_size =
+ sizeof(rte_be32_t);
+ j++;
+ }
+ }
+
+ ip_src_size = sizeof(rte_be32_t);
+ ip_dst_size = sizeof(rte_be32_t);
+ flow = LIST_FIRST(&priv->flows);
+ while (flow) {
+ next = LIST_NEXT(flow, next);
+ _flow = type == DPAA2_FLOW_QOS_TYPE ?
+ flow->qos_flow : flow->fs_flow;
+ if (!_flow)
+ goto next_flow;
+
+ if (type == DPAA2_FLOW_FS_TYPE &&
+ _flow->tc_id != tc_id)
+ goto next_flow;
+
+ if (_flow->ip_key == NET_PROT_IPV6) {
+ if (_flow->ip_src == NET_PROT_IPV6)
+ ip_src_size = NH_FLD_IPV6_ADDR_SIZE;
+ if (_flow->ip_dst == NET_PROT_IPV6)
+ ip_dst_size = NH_FLD_IPV6_ADDR_SIZE;
+ }
+
+next_flow:
+ flow = next;
+ }
+ if (key_profile->ip_addr_extracts[0].field == NH_FLD_IP_SRC)
+ key_profile->ip_addr_extracts[0].max_size = ip_src_size;
+ else if (key_profile->ip_addr_extracts[0].field == NH_FLD_IP_DST)
+ key_profile->ip_addr_extracts[0].max_size = ip_dst_size;
+
+ if (key_profile->ip_addr_extracts[1].field == NH_FLD_IP_SRC)
+ key_profile->ip_addr_extracts[1].max_size = ip_src_size;
+ else if (key_profile->ip_addr_extracts[1].field == NH_FLD_IP_DST)
+ key_profile->ip_addr_extracts[1].max_size = ip_dst_size;
+
+ key_profile->key_max_size +=
+ (key_profile->ip_addr_extracts[0].max_size +
+ key_profile->ip_addr_extracts[1].max_size);
+
+skip_ip_addr_extract:
+ for (i = 0; i < dpkg->num_extracts; i++) {
+ if ((dpkg->extracts[i].type == DPKG_EXTRACT_FROM_HDR &&
+ dpkg->extracts[i].extract.from_hdr.prot ==
+ NET_PROT_TCP &&
+ dpkg->extracts[i].extract.from_hdr.field ==
+ NH_FLD_TCP_PORT_SRC) ||
+ (dpkg->extracts[i].type == DPKG_EXTRACT_FROM_HDR &&
+ dpkg->extracts[i].extract.from_hdr.prot ==
+ NET_PROT_UDP &&
+ dpkg->extracts[i].extract.from_hdr.field ==
+ NH_FLD_UDP_PORT_SRC) ||
+ (dpkg->extracts[i].type == DPKG_EXTRACT_FROM_HDR &&
+ dpkg->extracts[i].extract.from_hdr.prot ==
+ NET_PROT_SCTP &&
+ dpkg->extracts[i].extract.from_hdr.field ==
+ NH_FLD_SCTP_PORT_SRC)) {
+ key_profile->l4_sp_present = 1;
+ key_profile->l4_sp_extract_idx = i;
+ key_profile->l4_sp_key_offset =
+ key_profile->key_offset[i];
+ } else if ((dpkg->extracts[i].type == DPKG_EXTRACT_FROM_HDR &&
+ dpkg->extracts[i].extract.from_hdr.prot ==
+ NET_PROT_TCP &&
+ dpkg->extracts[i].extract.from_hdr.field ==
+ NH_FLD_TCP_PORT_DST) ||
+ (dpkg->extracts[i].type == DPKG_EXTRACT_FROM_HDR &&
+ dpkg->extracts[i].extract.from_hdr.prot ==
+ NET_PROT_UDP &&
+ dpkg->extracts[i].extract.from_hdr.field ==
+ NH_FLD_UDP_PORT_DST) ||
+ (dpkg->extracts[i].type == DPKG_EXTRACT_FROM_HDR &&
+ dpkg->extracts[i].extract.from_hdr.prot ==
+ NET_PROT_SCTP &&
+ dpkg->extracts[i].extract.from_hdr.field ==
+ NH_FLD_SCTP_PORT_DST)) {
+ key_profile->l4_dp_present = 1;
+ key_profile->l4_dp_extract_idx = i;
+ key_profile->l4_dp_key_offset =
+ key_profile->key_offset[i];
+ }
+ }
+
+ if (type == DPAA2_FLOW_QOS_TYPE) {
+ dpaa2_flow_extracts_log(priv,
+ "After removing extract(s)", MAX_TCS);
+ } else {
+ dpaa2_flow_extracts_log(priv,
+ "After removing extract(s)", tc_id);
+ }
+
+ return update;
+}
+
+static int
+dpaa2_flow_remove_generic_entry(struct rte_eth_dev *dev,
+ struct dpaa2_generic_flow *flow, enum dpaa2_flow_dist_type type)
+{
+ int ret = 0;
+ struct dpaa2_dev_priv *priv = dev->data->dev_private;
+ struct fsl_mc_io *dpni = priv->hw;
+ struct dpaa2_flow_tbl_profile *tbl_profile;
+ struct dpaa2_dev_flow_fs_action *fs_action;
+ uint8_t tc_id;
+
+ if (type == DPAA2_FLOW_QOS_TYPE)
+ goto remove_qos_flow;
+
+ fs_action = &flow->flow_action.fs_action;
+ tc_id = flow->tc_id;
+ switch (fs_action->action_type) {
+ case RTE_FLOW_ACTION_TYPE_QUEUE:
+ case RTE_FLOW_ACTION_TYPE_REPRESENTED_PORT:
+ case RTE_FLOW_ACTION_TYPE_PORT_ID:
+ case RTE_FLOW_ACTION_TYPE_DROP:
+ /* Then remove entry from FS table */
+ ret = dpni_remove_fs_entry(dpni, CMD_PRI_LOW, priv->token,
+ flow->tc_id, &flow->rule_cfg);
+ if (ret) {
+ DPAA2_PMD_ERR("Remove entry from FS[%d] failed(%d)",
+ flow->tc_id, ret);
+ dpaa2_flow_fs_entry_log("Delete failed", flow);
+ } else {
+ dpaa2_flow_fs_entry_log("Delete success", flow);
+ tbl_profile = &priv->flow_profile.tc_profile[tc_id];
+ tbl_profile->entry_num--;
+ dpaa2_flow_entry_map_set(tbl_profile->entry_map,
+ flow->entry_index, 0);
+ }
+ break;
+ case RTE_FLOW_ACTION_TYPE_RSS:
+ /** Remove QoS entry later.*/
+ break;
+ default:
+ DPAA2_PMD_ERR("Action(%d) not supported",
+ fs_action->action_type);
+ ret = -ENOTSUP;
+ break;
+ }
+
+ return ret;
+
+remove_qos_flow:
+ if (priv->num_rx_tc > 1) {
+ /* Remove entry from QoS table first */
+ ret = dpni_remove_qos_entry(dpni, CMD_PRI_LOW,
+ priv->token, &flow->rule_cfg);
+ if (ret) {
+ DPAA2_PMD_ERR("Remove QoS entry failed(%d)", ret);
+ dpaa2_flow_qos_entry_log("Delete failed", flow);
+ /** Will not remove FS entry.*/
+ } else {
+ dpaa2_flow_qos_entry_log("Delete success", flow);
+ tbl_profile = &priv->flow_profile.qos_profile;
+ tbl_profile->entry_num--;
+ dpaa2_flow_entry_map_set(tbl_profile->entry_map,
+ flow->entry_index, 0);
+ }
+ }
+
+ return ret;
+}
+
+static int
+dpaa2_flow_generic_flow_destroy(struct rte_eth_dev *dev,
+ struct dpaa2_generic_flow *flow, enum dpaa2_flow_dist_type type)
+{
+ int ret = 0, update;
+ uint8_t tc_id = 0;
+ struct dpaa2_dev_priv *priv = dev->data->dev_private;
+
+ dpaa2_dump_extract_map(priv, "Start destroying flow", type,
+ type == DPAA2_FLOW_FS_TYPE ? flow->tc_id : 0);
+
+ ret = dpaa2_flow_remove_generic_entry(dev, flow, type);
+ if (ret)
+ return ret;
+
+ if (type == DPAA2_FLOW_FS_TYPE)
+ tc_id = flow->tc_id;
+
+ update = dpaa2_flow_remove_invalid_extract(dev, type, tc_id);
+ if (update > 0) {
+ if (type == DPAA2_FLOW_FS_TYPE) {
+ ret = dpaa2_flow_fs_rss_table_config(priv,
+ flow->tc_id, false);
+ if (ret)
+ DPAA2_PMD_ERR("Re-configure FS table failed(%d)", ret);
+ } else {
+ ret = dpaa2_flow_qos_table_config(priv, false);
+ if (ret)
+ DPAA2_PMD_ERR("Re-configure QoS table failed(%d)", ret);
+ }
+ }
+
+ if (!ret) {
+ dpaa2_dump_extract_map(priv, "End destroying flow",
+ type, tc_id);
+ }
+
+ return ret;
+}
+
+static int
+dpaa2_flow_qos_fs_action_set(const struct rte_flow_action actions[],
+ struct rte_flow_action qos_actions[],
+ struct rte_flow_action fs_actions[],
+ uint8_t *qos_action_num, uint8_t *fs_action_num)
+{
+ uint8_t qos_act_num = 0, fs_act_num = 0;
+ int end_of_list = 0, i = 0, is_qos_act, is_fs_act;
+ struct rte_flow_action action_check[2];
+
+ action_check[1].type = RTE_FLOW_ACTION_TYPE_END;
+ while (!end_of_list) {
+ if (actions[i].type == RTE_FLOW_ACTION_TYPE_END) {
+ if (qos_action_num)
+ *qos_action_num = qos_act_num;
+ if (fs_action_num)
+ *fs_action_num = fs_act_num;
+ qos_actions[qos_act_num].type = actions[i].type;
+ fs_actions[fs_act_num].type = actions[i].type;
+ end_of_list = 1;
+ continue;
+ }
+ action_check[0].type = actions[i].type;
+ action_check[0].conf = actions[i].conf;
+ is_qos_act = dpaa2_flow_check_actions_support(action_check,
+ dpaa2_supported_qos_action_type,
+ RTE_DIM(dpaa2_supported_qos_action_type));
+ is_fs_act = dpaa2_flow_check_actions_support(action_check,
+ dpaa2_supported_fs_action_type,
+ RTE_DIM(dpaa2_supported_fs_action_type));
+ if (!is_qos_act && !is_fs_act)
+ return -EINVAL;
+ if (is_qos_act && is_fs_act)
+ is_qos_act = false;
+ if (is_qos_act) {
+ qos_actions[qos_act_num].type = actions[i].type;
+ qos_actions[qos_act_num].conf = actions[i].conf;
+ qos_act_num++;
+ }
+ if (is_fs_act) {
+ fs_actions[fs_act_num].type = actions[i].type;
+ fs_actions[fs_act_num].conf = actions[i].conf;
+ fs_act_num++;
+ }
+ i++;
+ }
+
+ return 0;
+}
+
+static struct dpaa2_generic_flow *
+dpaa2_flow_generic_flow_create(struct rte_eth_dev *dev,
+ const struct rte_flow_attr *attr,
+ const struct rte_flow_item pattern[],
+ const struct rte_flow_action actions[],
+ struct rte_flow_error *error, enum dpaa2_flow_dist_type type,
+ int mix_extract, int is_rss)
+{
+ struct dpaa2_generic_flow *flow = NULL;
+ struct rte_dpaa2_device *dpaa2_dev;
+ struct dpaa2_dev_priv *priv = dev->data->dev_private;
+ int ret, idx = -1;
+ uint64_t iova, mc_rev;
+ uint8_t qos_action_num = 0, fs_action_num = 0;
+ struct rte_flow_action qos_actions[DPAA2_MAX_ACTION_PER_FLOW_NUM];
+ struct rte_flow_action fs_actions[DPAA2_MAX_ACTION_PER_FLOW_NUM];
+ struct rte_flow_action_jump action_jump;
+ const struct rte_flow_action_rss *action_rss;
+ const struct rte_flow_action_queue *action_q;
+ struct dpaa2_flow_tbl_profile *tbl_profile;
+ struct dpaa2_queue *dir_rxq = NULL;
+
+ if (type != DPAA2_FLOW_QOS_TYPE && type != DPAA2_FLOW_FS_TYPE)
+ return NULL;
+
+ dpaa2_dev = DPAA2_DEV_PRIV_TO_DPAA2_DEV(priv);
+ mc_rev = dpaa2_dev->bus_info->mc_rev;
+
+ if (actions) {
+ ret = dpaa2_flow_qos_fs_action_set(actions, qos_actions,
+ fs_actions, &qos_action_num, &fs_action_num);
+ if (ret) {
+ DPAA2_PMD_ERR("Failed(%d) to set qos/fs actions!", ret);
+ goto creation_error;
+ }
+ if (type == DPAA2_FLOW_QOS_TYPE &&
+ dpaa2_flow_action_single_type_check(fs_actions,
+ RTE_FLOW_ACTION_TYPE_QUEUE)) {
+ action_q = fs_actions[0].conf;
+ if (action_q->index >= dev->data->nb_rx_queues) {
+ DPAA2_PMD_ERR("direct queue index(%d) >= max(%d)",
+ action_q->index,
+ dev->data->nb_rx_queues);
+ ret = -EINVAL;
+ goto creation_error;
+ }
+ if ((mc_rev < DPAA2_QOS_FLOW_HW_ACTION_UPDATE_MC_REV ||
+ mc_rev < DPAA2_QOS_FLOW_TABLE_MISS_FLOW_ACTION_MC_REV) &&
+ mix_extract) {
+ /** We don't recommend steering flow by QoS table here
+ * because this version doesn't support QoS flow HW update
+ * and QoS table miss flow.
+ */
+ dir_rxq = NULL;
+ } else {
+ dir_rxq = dev->data->rx_queues[action_q->index];
+ }
+ }
+ }
+
+ if (type == DPAA2_FLOW_FS_TYPE && attr) {
+ if (attr->group >= priv->num_rx_tc) {
+ DPAA2_PMD_ERR("Flow group(%d) >= max(%d)",
+ attr->group, priv->num_rx_tc);
+ return NULL;
+ }
+ if (attr->priority >= priv->fs_entries && !is_rss) {
+ DPAA2_PMD_ERR("FS[%d].entry(%d) >= max(%d)",
+ attr->group, attr->priority, priv->fs_entries);
+ return NULL;
+ }
+ }
+
+ if (dir_rxq) {
+ qos_actions[0].type = RTE_FLOW_ACTION_TYPE_JUMP;
+ qos_actions[0].conf = &action_jump;
+ qos_actions[1].type = RTE_FLOW_ACTION_TYPE_END;
+ /** Ignore attr->group*/
+ if ((mix_extract || type == DPAA2_FLOW_FS_TYPE) &&
+ attr->group < priv->num_rx_tc &&
+ attr->group != dir_rxq->tc_index) {
+ DPAA2_PMD_ERR("Attribute group(%d) conflicts with dest queue's TC(%d)",
+ attr->group, dir_rxq->tc_index);
+ return NULL;
+ }
+ action_jump.group = dir_rxq->tc_index;
+ if (attr->group >= priv->num_rx_tc)
+ idx = attr->priority;
+ else if (!priv->fs_entries)
+ idx = action_jump.group * priv->dist_queues + attr->priority;
+ else
+ idx = action_jump.group * priv->fs_entries + attr->priority;
+ } else if (mix_extract && type == DPAA2_FLOW_QOS_TYPE) {
+ /** Move end action.*/
+ rte_memcpy(&qos_actions[qos_action_num + 1],
+ &qos_actions[qos_action_num],
+ sizeof(struct rte_flow_action));
+ /** Jump to FS[group]*/
+ qos_actions[qos_action_num].type = RTE_FLOW_ACTION_TYPE_JUMP;
+ qos_actions[qos_action_num].conf = &action_jump;
+ action_jump.group = attr->group;
+ idx = action_jump.group * priv->fs_entries + attr->priority;
+ qos_action_num++;
+ } else if (!mix_extract && type == DPAA2_FLOW_QOS_TYPE) {
+ if (!qos_action_num) {
+ DPAA2_PMD_ERR("No QoS flow's action!");
+ return NULL;
+ }
+ if (!is_rss) {
+ idx = dpaa2_flow_acquire_entry_idx(priv, attr->priority,
+ DPAA2_FLOW_QOS_TYPE, attr->group);
+ }
+ } else if (type == DPAA2_FLOW_FS_TYPE) {
+ ret = dpaa2_flow_verify_fs_action(priv, attr, actions);
+ if (ret)
+ return NULL;
+ if (!is_rss) {
+ idx = dpaa2_flow_acquire_entry_idx(priv, attr->priority,
+ DPAA2_FLOW_FS_TYPE, attr->group);
+ }
+ } else {
+ DPAA2_PMD_ERR("Invalid flow type(%d) or extract type(%d)",
+ type, mix_extract);
+ return NULL;
+ }
+ if (idx < 0 && !is_rss)
+ return NULL;
+ if (idx >= 0 && idx < RTE_ETH_DCB_NUM_USER_PRIORITIES && !is_rss &&
+ type == DPAA2_FLOW_QOS_TYPE && priv->dcb_flow[idx]) {
+ DPAA2_PMD_ERR("QoS flow[%d] added conflicts with dcb flow", idx);
+ return NULL;
+ }
+
+ if (!is_rss) {
+ ret = dpaa2_flow_verify_entry(priv, attr->group, idx, type);
+ if (ret)
+ return NULL;
+ if ((type == DPAA2_FLOW_QOS_TYPE && idx >= priv->qos_entries) ||
+ (type == DPAA2_FLOW_FS_TYPE && idx >= priv->fs_entries)) {
+ DPAA2_PMD_ERR("%s flow[%d] added more than max entries(%d)",
+ type == DPAA2_FLOW_QOS_TYPE ? "QoS" : "FS", idx,
+ type == DPAA2_FLOW_QOS_TYPE ? priv->qos_entries : priv->fs_entries);
+ return NULL;
+ }
+ }
+
+ dpaa2_dump_extract_map(priv, "Start creating flow",
+ type, attr->group);
+
+ flow = rte_zmalloc(NULL, sizeof(struct dpaa2_generic_flow),
+ RTE_CACHE_LINE_SIZE);
+ if (!flow) {
+ DPAA2_PMD_ERR("Failure to allocate memory for flow");
goto mem_failure;
}
- flow->qos_rule.mask_iova = iova;
+ flow->priv = priv;
- /* Allocate DMA'ble memory to write the FS rules */
- flow->fs_key_addr = rte_zmalloc(NULL,
+ /* Allocate DMA'ble memory to write the qos rules */
+ flow->key_addr = rte_zmalloc(NULL,
DPAA2_EXTRACT_ALLOC_KEY_MAX_SIZE, RTE_CACHE_LINE_SIZE);
- if (!flow->fs_key_addr) {
+ if (!flow->key_addr) {
DPAA2_PMD_ERR("Memory allocation failed");
goto mem_failure;
}
- iova = DPAA2_VADDR_TO_IOVA_AND_CHECK(flow->fs_key_addr,
+ iova = DPAA2_VADDR_TO_IOVA_AND_CHECK(flow->key_addr,
DPAA2_EXTRACT_ALLOC_KEY_MAX_SIZE);
if (iova == RTE_BAD_IOVA) {
- DPAA2_PMD_ERR("%s: No IOMMU map for fs key(%p)",
- __func__, flow->fs_key_addr);
+ DPAA2_PMD_ERR("%s: No IOMMU map for key(%p)",
+ __func__, flow->key_addr);
goto mem_failure;
}
- flow->fs_rule.key_iova = iova;
+ flow->rule_cfg.key_iova = iova;
- flow->fs_mask_addr = rte_zmalloc(NULL,
+ flow->mask_addr = rte_zmalloc(NULL,
DPAA2_EXTRACT_ALLOC_KEY_MAX_SIZE, RTE_CACHE_LINE_SIZE);
- if (!flow->fs_mask_addr) {
+ if (!flow->mask_addr) {
DPAA2_PMD_ERR("Memory allocation failed");
goto mem_failure;
}
- iova = DPAA2_VADDR_TO_IOVA_AND_CHECK(flow->fs_mask_addr,
- DPAA2_EXTRACT_ALLOC_KEY_MAX_SIZE);
+ iova = DPAA2_VADDR_TO_IOVA_AND_CHECK(flow->mask_addr,
+ DPAA2_EXTRACT_ALLOC_KEY_MAX_SIZE);
if (iova == RTE_BAD_IOVA) {
- DPAA2_PMD_ERR("%s: No IOMMU map for fs mask(%p)",
- __func__, flow->fs_mask_addr);
+ DPAA2_PMD_ERR("%s: No IOMMU map for mask(%p)",
+ __func__, flow->mask_addr);
goto mem_failure;
}
- flow->fs_rule.mask_iova = iova;
+ flow->rule_cfg.mask_iova = iova;
- priv->curr = flow;
+ flow->ip_key = NET_PROT_NONE;
- ret = dpaa2_generic_flow_set(flow, dev, attr, pattern, actions, error);
+ priv->cur_flow = flow;
+ if (is_rss) {
+ action_rss = actions[0].conf;
+ tbl_profile = &priv->flow_profile.tc_profile[attr->group];
+ tbl_profile->tc_cfg.dist_size = action_rss->queue_num;
+ }
+ ret = dpaa2_flow_generic_extract_rule_set(flow,
+ attr, pattern, is_rss, type, false);
if (ret < 0) {
- if (error && error->type > RTE_FLOW_ERROR_TYPE_ACTION)
+ if (error && error->type > RTE_FLOW_ERROR_TYPE_ACTION) {
rte_flow_error_set(error, EPERM,
- RTE_FLOW_ERROR_TYPE_UNSPECIFIED,
- attr, "unknown");
- DPAA2_PMD_ERR("Create flow failed (%d)", ret);
+ RTE_FLOW_ERROR_TYPE_UNSPECIFIED,
+ attr, "unknown");
+ }
+ DPAA2_PMD_ERR("Create %s flow failed (%d)",
+ type == DPAA2_FLOW_QOS_TYPE ?
+ "QoS" : "FS", ret);
goto creation_error;
}
- priv->curr = NULL;
- return (struct rte_flow *)flow;
+ flow->entry_index = idx;
+ if (type == DPAA2_FLOW_QOS_TYPE) {
+ ret = dpaa2_flow_qos_action_update(priv, flow, qos_actions, true);
+ if (ret)
+ goto creation_error;
+ if (dir_rxq) {
+ flow->direct_queue = true;
+ flow->flow_id = dir_rxq->flow_id;
+ }
+ ret = dpaa2_flow_add_qos_rule(priv, flow);
+ if (ret)
+ goto creation_error;
+ } else {
+ flow->tc_id = attr->group;
+ ret = dpaa2_flow_fs_action_update(priv, flow, fs_actions);
+ if (ret)
+ goto creation_error;
+ if (!is_rss) {
+ ret = dpaa2_flow_add_fs_rule(priv, flow);
+ if (ret)
+ goto creation_error;
+ } else {
+ flow->is_rss = true;
+ }
+ }
+ priv->cur_flow = NULL;
+
+ dpaa2_dump_extract_map(priv, "Complete creating flow",
+ type, attr->group);
+
+ return flow;
mem_failure:
rte_flow_error_set(error, EPERM, RTE_FLOW_ERROR_TYPE_UNSPECIFIED, NULL,
- "memory alloc");
+ "memory alloc");
creation_error:
if (flow) {
- rte_free(flow->qos_key_addr);
- rte_free(flow->qos_mask_addr);
- rte_free(flow->fs_key_addr);
- rte_free(flow->fs_mask_addr);
+ if (flow->key_addr)
+ rte_free(flow->key_addr);
+ if (flow->mask_addr)
+ rte_free(flow->mask_addr);
rte_free(flow);
}
- priv->curr = NULL;
+
+ return NULL;
+}
+
+static struct rte_flow *
+dpaa2_flow_create_meter_flow(struct rte_eth_dev *dev,
+ const struct rte_flow_attr *attr,
+ const struct rte_flow_action meter_action[])
+{
+ struct dpaa2_dev_priv *priv = dev->data->dev_private;
+ struct dpaa2_dev_flow *flow = NULL;
+ struct dpaa2_generic_flow *fs_flow = NULL;
+ int ret;
+
+ if (attr->group >= priv->num_rx_tc)
+ return NULL;
+
+ if (priv->flow_profile.mtr_flow[attr->group])
+ return NULL;
+
+ fs_flow = rte_zmalloc(NULL, sizeof(struct dpaa2_generic_flow),
+ RTE_CACHE_LINE_SIZE);
+ if (!fs_flow) {
+ DPAA2_PMD_ERR("Failure to allocate memory for flow");
+ return NULL;
+ }
+ flow = rte_zmalloc(NULL, sizeof(struct dpaa2_dev_flow),
+ RTE_CACHE_LINE_SIZE);
+ if (!flow) {
+ rte_free(fs_flow);
+ DPAA2_PMD_ERR("Failure to allocate memory for flow");
+ return NULL;
+ }
+ fs_flow->tc_id = attr->group;
+ fs_flow->priv = priv;
+ flow->fs_flow = fs_flow;
+ flow->priv = priv;
+
+ ret = dpaa2_flow_fs_action_update(priv, fs_flow, meter_action);
+ if (ret) {
+ rte_free(fs_flow);
+ rte_free(flow);
+ return NULL;
+ }
+ flow->is_meter_flow = true;
+ priv->flow_profile.mtr_flow[fs_flow->tc_id] = flow;
+
+ return (struct rte_flow *)flow;
+}
+
+static struct rte_flow *
+dpaa2_flow_create(struct rte_eth_dev *dev,
+ const struct rte_flow_attr *attr,
+ const struct rte_flow_item pattern[],
+ const struct rte_flow_action actions[],
+ struct rte_flow_error *error)
+{
+ struct dpaa2_dev_flow *flow = NULL, *curr;
+ struct dpaa2_dev_priv *priv = dev->data->dev_private;
+ int ret, is_rss = false;
+ struct dpaa2_generic_flow *qos_flow = NULL;
+ struct dpaa2_generic_flow *fs_flow = NULL;
+ uint32_t group_id, group_type;
+ const struct rte_flow_action_rss *rss_conf;
+ struct rte_flow_item items[DPKG_MAX_NUM_OF_EXTRACTS + 1];
+ int rss_item = false, err_code = 0;
+ uint8_t spec_buf[1024];
+ enum rte_flow_error_type error_type = RTE_FLOW_ERROR_TYPE_NONE;
+ const char *err_str = NULL;
+ struct rte_flow_attr local_attr;
+
+ if (getenv("DPAA2_FLOW_CONTROL_LOG"))
+ dpaa2_flow_control_log = 1;
+
+ group_type = RTE_DPAA2_FLOW_GROUP_TYPE_GET(attr->group);
+ group_id = RTE_DPAA2_FLOW_GROUP_ID_GET(attr->group);
+ if (group_id >= priv->num_rx_tc &&
+ group_type == RTE_DPAA2_ONE_LEVEL_GROUP_FLOW) {
+ group_type = RTE_DPAA2_QOS_GROUP_FLOW;
+ group_id = DPAA2_FLOW_QOS_GROUP_ID;
+ }
+ rte_memcpy(&local_attr, attr, sizeof(struct rte_flow_attr));
+ local_attr.group = group_id;
+
+ if (actions) {
+ is_rss = dpaa2_flow_action_single_type_check(actions,
+ RTE_FLOW_ACTION_TYPE_RSS);
+ }
+ if (is_rss && group_type == RTE_DPAA2_QOS_GROUP_FLOW) {
+ err_str = "RSS doesn't supports QoS table!";
+ error_type = RTE_FLOW_ERROR_TYPE_ATTR;
+ err_code = -EINVAL;
+ goto flow_failure;
+ }
+ if (is_rss && group_type != RTE_DPAA2_FS_GROUP_FLOW) {
+ DPAA2_PMD_WARN("RSS distribution in TC%d.", group_id);
+ group_type = RTE_DPAA2_FS_GROUP_FLOW;
+ }
+ if (is_rss && !pattern) {
+ rss_conf = actions[0].conf;
+ ret = dpaa2_flow_rss_conf_to_item(rss_conf->types, items,
+ spec_buf, 1024);
+ if (ret < 0) {
+ DPAA2_PMD_ERR("TC[%d] converts to RSS items failed(%d)",
+ group_id, ret);
+ error_type = RTE_FLOW_ERROR_TYPE_ITEM;
+ err_code = ret;
+ err_str = "Failed to converts RSS config type to RSS items!";
+ goto flow_failure;
+ }
+ rss_item = true;
+ }
+
+ if (dpaa2_flow_check_actions_support(actions,
+ dpaa2_supported_meter_action_type,
+ RTE_DIM(dpaa2_supported_meter_action_type))) {
+ /** Assume it's meter flow per TC.*/
+ if (group_type == RTE_DPAA2_QOS_GROUP_FLOW) {
+ error_type = RTE_FLOW_ERROR_TYPE_ATTR_GROUP;
+ err_code = -EINVAL;
+ err_str = "Failed to converts RSS config type to RSS items!";
+ goto flow_failure;
+ }
+ if (actions[1].type != RTE_FLOW_ACTION_TYPE_END) {
+ error_type = RTE_FLOW_ERROR_TYPE_ACTION_NUM;
+ err_code = -EPERM;
+ err_str = "Meter flow can't support multi-actions.";
+ goto flow_failure;
+ }
+ flow = (void *)dpaa2_flow_create_meter_flow(dev, &local_attr, actions);
+ if (flow)
+ return (struct rte_flow *)flow;
+ error_type = RTE_FLOW_ERROR_TYPE_ACTION;
+ err_code = -EINVAL;
+ err_str = "Failed to create meter flow!";
+ goto flow_failure;
+ }
+
+ DPAA2_PMD_DEBUG("Port %s-%s: group type:%d, group id:%d, total RX TCs:%d",
+ dev->data->name, __func__, group_type, group_id, priv->num_rx_tc);
+ if (group_type == RTE_DPAA2_ONE_LEVEL_GROUP_FLOW) {
+ if (priv->qos_entries > 0) {
+ qos_flow = dpaa2_flow_generic_flow_create(dev, &local_attr, pattern,
+ actions, error, DPAA2_FLOW_QOS_TYPE, true, is_rss);
+ if (!qos_flow) {
+ err_str = "Failed to create QoS flow!";
+ error_type = RTE_FLOW_ERROR_TYPE_UNSPECIFIED;
+ err_code = -EINVAL;
+ goto flow_failure;
+ }
+ }
+ if (priv->fs_entries > 0 && !(qos_flow && qos_flow->direct_queue)) {
+ fs_flow = dpaa2_flow_generic_flow_create(dev, &local_attr, pattern,
+ actions, error, DPAA2_FLOW_FS_TYPE, true, is_rss);
+ if (!fs_flow) {
+ if (qos_flow) {
+ ret = dpaa2_flow_generic_flow_destroy(dev, qos_flow,
+ DPAA2_FLOW_QOS_TYPE);
+ if (ret) {
+ DPAA2_PMD_ERR("%s: QoS flow destroy failed(%d)!",
+ __func__, ret);
+ }
+ }
+ err_str = "Failed to create FS flow!";
+ error_type = RTE_FLOW_ERROR_TYPE_UNSPECIFIED;
+ err_code = -EINVAL;
+ goto flow_failure;
+ }
+ }
+ } else if (group_type == RTE_DPAA2_QOS_GROUP_FLOW) {
+ if (!priv->qos_entries) {
+ err_str = "No QoS entry available!";
+ error_type = RTE_FLOW_ERROR_TYPE_UNSPECIFIED;
+ err_code = -EINVAL;
+ goto flow_failure;
+ }
+ qos_flow = dpaa2_flow_generic_flow_create(dev, &local_attr, pattern,
+ actions, error, DPAA2_FLOW_QOS_TYPE, false, is_rss);
+ if (!qos_flow) {
+ err_str = "QoS flow create failed!";
+ error_type = RTE_FLOW_ERROR_TYPE_UNSPECIFIED;
+ err_code = -EINVAL;
+ goto flow_failure;
+ }
+ } else if (group_type == RTE_DPAA2_FS_GROUP_FLOW) {
+ if (!priv->fs_entries && !is_rss) {
+ err_str = "No FS entry available!";
+ error_type = RTE_FLOW_ERROR_TYPE_UNSPECIFIED;
+ err_code = -EINVAL;
+ goto flow_failure;
+ }
+ fs_flow = dpaa2_flow_generic_flow_create(dev, &local_attr,
+ rss_item ? items : pattern,
+ actions, error, DPAA2_FLOW_FS_TYPE, false, is_rss);
+ if (!fs_flow) {
+ err_str = "FS flow create failed!";
+ error_type = RTE_FLOW_ERROR_TYPE_UNSPECIFIED;
+ err_code = -EINVAL;
+ goto flow_failure;
+ }
+ } else {
+ err_str = "Invalid flow attribut parameter!";
+ error_type = RTE_FLOW_ERROR_TYPE_ATTR;
+ err_code = -EINVAL;
+ goto flow_failure;
+ }
+ if (!qos_flow && !fs_flow) {
+ err_str = "Both QoS flow and FS flow are NULL!";
+ error_type = RTE_FLOW_ERROR_TYPE_UNSPECIFIED;
+ err_code = -EINVAL;
+ goto flow_failure;
+ }
+ flow = rte_zmalloc(NULL, sizeof(struct dpaa2_dev_flow),
+ RTE_CACHE_LINE_SIZE);
+ if (!flow) {
+ err_str = "Failure to allocate memory for flow!";
+ error_type = RTE_FLOW_ERROR_TYPE_UNSPECIFIED;
+ err_code = -ENOMEM;
+ goto flow_failure;
+ }
+ flow->qos_flow = qos_flow;
+ flow->fs_flow = fs_flow;
+ flow->priv = priv;
+ if (fs_flow && fs_flow->is_rss)
+ priv->flow_profile.tc_profile[group_id].rss_flow = flow;
+
+ /* New rules are inserted. */
+ curr = LIST_FIRST(&priv->flows);
+ if (!curr) {
+ LIST_INSERT_HEAD(&priv->flows, flow, next);
+ } else {
+ while (LIST_NEXT(curr, next))
+ curr = LIST_NEXT(curr, next);
+ LIST_INSERT_AFTER(curr, flow, next);
+ }
+
+ return (struct rte_flow *)flow;
+
+flow_failure:
+ if (err_str)
+ DPAA2_PMD_ERR("%s: %s", __func__, err_str);
+ rte_flow_error_set(error, -err_code, error_type, NULL, err_str);
+
+ if (flow) {
+ if (flow->qos_flow && flow->qos_flow->key_addr)
+ rte_free(flow->qos_flow->key_addr);
+ if (flow->qos_flow && flow->qos_flow->mask_addr)
+ rte_free(flow->qos_flow->mask_addr);
+ if (flow->fs_flow && flow->fs_flow->key_addr)
+ rte_free(flow->fs_flow->key_addr);
+ if (flow->fs_flow && flow->fs_flow->mask_addr)
+ rte_free(flow->fs_flow->mask_addr);
+ if (flow->qos_flow)
+ rte_free(flow->qos_flow);
+ if (flow->fs_flow)
+ rte_free(flow->fs_flow);
+ rte_free(flow);
+ }
+ priv->cur_flow = NULL;
return NULL;
}
static int
-dpaa2_flow_destroy(struct rte_eth_dev *dev, struct rte_flow *_flow,
- struct rte_flow_error *error)
+dpaa2_flow_destroy_meter_flow(struct rte_eth_dev *dev,
+ struct dpaa2_dev_flow *flow)
{
- int ret = 0;
+ struct rte_dpaa2_device *dpaa2_dev;
+ struct dpaa2_dev_priv *priv = dev->data->dev_private;
+ struct dpni_rx_tc_policing_cfg cfg;
+ int ret;
+ uint8_t tc_id;
+
+ RTE_ASSERT(!flow->qos_flow && flow->fs_flow);
+ dpaa2_dev = DPAA2_DEV_PRIV_TO_DPAA2_DEV(priv);
+ tc_id = flow->fs_flow->tc_id;
+ RTE_ASSERT(priv->flow_profile.mtr_flow[tc_id] == flow);
+ memset(&cfg, 0, sizeof(cfg));
+ cfg.mode = DPNI_POLICER_MODE_NONE;
+ if (dpaa2_dev->bus_info->mc_rev < DPAA2_POLICER_SET_V2_MC_REV) {
+ ret = dpni_set_rx_tc_policing_v1(priv->hw, CMD_PRI_LOW,
+ priv->token, tc_id, &cfg);
+ } else {
+ ret = dpni_set_rx_tc_policing(priv->hw, CMD_PRI_LOW,
+ priv->token, tc_id, &cfg);
+ }
+ if (ret)
+ return ret;
+ priv->flow_profile.tc_mtr_profile[tc_id] = NULL;
+ priv->flow_profile.mtr_flow[tc_id] = NULL;
+ rte_free(flow->fs_flow);
+ rte_free(flow);
+
+ return 0;
+}
+
+static int
+dpaa2_flow_destroy(struct rte_eth_dev *dev,
+ struct rte_flow *_flow, struct rte_flow_error *error)
+{
+ int qos_ret = 0, fs_ret = 0;
struct dpaa2_dev_flow *flow;
struct dpaa2_dev_priv *priv = dev->data->dev_private;
- struct fsl_mc_io *dpni = priv->hw;
+ struct dpaa2_flow_tbl_profile *tbl_profile;
+ uint8_t tc_id;
+
+ RTE_SET_USED(error);
flow = (struct dpaa2_dev_flow *)_flow;
+ if (flow->is_meter_flow)
+ return dpaa2_flow_destroy_meter_flow(dev, flow);
- switch (flow->action_type) {
- case RTE_FLOW_ACTION_TYPE_QUEUE:
- case RTE_FLOW_ACTION_TYPE_REPRESENTED_PORT:
- case RTE_FLOW_ACTION_TYPE_PORT_ID:
- case RTE_FLOW_ACTION_TYPE_DROP:
- if (priv->num_rx_tc > 1) {
- /* Remove entry from QoS table first */
- ret = dpni_remove_qos_entry(dpni, CMD_PRI_LOW,
- priv->token,
- &flow->qos_rule);
- if (ret < 0) {
- DPAA2_PMD_ERR("Remove FS QoS entry failed");
- dpaa2_flow_qos_entry_log("Delete failed", flow,
- -1);
- abort();
- goto error;
+ LIST_REMOVE(flow, next);
+
+ if (flow->qos_flow) {
+ qos_ret = dpaa2_flow_generic_flow_destroy(dev, flow->qos_flow,
+ DPAA2_FLOW_QOS_TYPE);
+ if (qos_ret) {
+ DPAA2_PMD_ERR("%s: destroy QoS flow failed(%d)",
+ __func__, qos_ret);
+ }
+ if (flow->qos_flow->key_addr)
+ rte_free(flow->qos_flow->key_addr);
+ if (flow->qos_flow->mask_addr)
+ rte_free(flow->qos_flow->mask_addr);
+ rte_free(flow->qos_flow);
+ flow->qos_flow = NULL;
+ }
+ if (flow->fs_flow) {
+ fs_ret = dpaa2_flow_generic_flow_destroy(dev, flow->fs_flow,
+ DPAA2_FLOW_FS_TYPE);
+ if (fs_ret) {
+ DPAA2_PMD_ERR("%s: destroy FS flow failed(%d)",
+ __func__, fs_ret);
+ }
+ if (flow->fs_flow->key_addr)
+ rte_free(flow->fs_flow->key_addr);
+ if (flow->fs_flow->mask_addr)
+ rte_free(flow->fs_flow->mask_addr);
+ if (flow->fs_flow->is_rss) {
+ tc_id = flow->fs_flow->tc_id;
+ tbl_profile = &priv->flow_profile.tc_profile[tc_id];
+ tbl_profile->rss_flow = NULL;
+ }
+ rte_free(flow->fs_flow);
+ flow->fs_flow = NULL;
+ }
+ rte_free(flow);
+
+ if (!qos_ret && !fs_ret)
+ return 0;
+
+ return qos_ret ? qos_ret : fs_ret;
+}
+
+static int
+dpaa2_flow_set_miss_actions(struct rte_eth_dev *dev,
+ uint32_t group, const struct rte_flow_group_attr *attr,
+ const struct rte_flow_action actions[], struct rte_flow_error *err)
+{
+ struct dpaa2_dev_priv *priv = dev->data->dev_private;
+ enum dpaa2_flow_dist_type flow_type = DPAA2_FLOW_NULL_TYPE;
+ int end_of_list = 0, i = 0, discard = false, err_code = 0;
+ const struct rte_flow_action_jump *action_jump = NULL;
+ const struct rte_flow_action_queue *dest_queue = NULL;
+ uint32_t group_id, group_type;
+ enum rte_flow_error_type error_type = RTE_FLOW_ERROR_TYPE_NONE;
+ const char *err_str = NULL;
+ struct dpaa2_queue *miss_rxq = NULL;
+ uint8_t qos_tc = 0xff;
+ uint16_t qos_flow = 0xffff;
+
+ RTE_SET_USED(attr);
+
+ group_type = RTE_DPAA2_FLOW_GROUP_TYPE_GET(group);
+ group_id = RTE_DPAA2_FLOW_GROUP_ID_GET(group);
+ if (group_id >= priv->num_rx_tc &&
+ group_type == RTE_DPAA2_ONE_LEVEL_GROUP_FLOW) {
+ group_type = RTE_DPAA2_QOS_GROUP_FLOW;
+ group_id = 0;
+ }
+ if (group_type == RTE_DPAA2_QOS_GROUP_FLOW)
+ flow_type = DPAA2_FLOW_QOS_TYPE;
+ else if (group_type == RTE_DPAA2_FS_GROUP_FLOW)
+ flow_type = DPAA2_FLOW_FS_TYPE;
+ else if (group >= priv->num_rx_tc)
+ flow_type = DPAA2_FLOW_QOS_TYPE;
+ else
+ flow_type = DPAA2_FLOW_FS_TYPE;
+
+ while (!end_of_list) {
+ switch (actions[i].type) {
+ case RTE_FLOW_ACTION_TYPE_QUEUE:
+ dest_queue = actions[i].conf;
+ if (dest_queue->index >= dev->data->nb_rx_queues) {
+ error_type = RTE_FLOW_ERROR_TYPE_ACTION_CONF;
+ err_code = -EINVAL;
+ err_str = "Queue index overflows";
+ goto failure_to_set_miss_actions;
}
+ miss_rxq = priv->rx_vq[dest_queue->index];
+ break;
+ case RTE_FLOW_ACTION_TYPE_JUMP:
+ action_jump = actions[i].conf;
+ break;
+ case RTE_FLOW_ACTION_TYPE_DROP:
+ discard = true;
+ break;
+ case RTE_FLOW_ACTION_TYPE_END:
+ end_of_list = 1;
+ break;
+ default:
+ DPAA2_PMD_WARN("Invalid default action type[%d]:(%d)",
+ i, actions[i].type);
+ break;
}
+ i++;
+ }
- /* Then remove entry from FS table */
- ret = dpni_remove_fs_entry(dpni, CMD_PRI_LOW, priv->token,
- flow->tc_id, &flow->fs_rule);
- if (ret < 0) {
- DPAA2_PMD_ERR("Remove entry from FS[%d] failed",
- flow->tc_id);
- goto error;
+ if (flow_type == DPAA2_FLOW_QOS_TYPE) {
+ if (!priv->qos_entries) {
+ error_type = RTE_FLOW_ERROR_TYPE_ACTION;
+ err_code = -EINVAL;
+ err_str = "No QoS table available!";
+ goto failure_to_set_miss_actions;
}
- break;
- case RTE_FLOW_ACTION_TYPE_RSS:
- if (priv->num_rx_tc > 1) {
- ret = dpni_remove_qos_entry(dpni, CMD_PRI_LOW,
- priv->token,
- &flow->qos_rule);
- if (ret < 0) {
- DPAA2_PMD_ERR("Remove RSS QoS entry failed");
- goto error;
+ if (action_jump && miss_rxq) {
+ if (action_jump->group != miss_rxq->tc_index) {
+ error_type = RTE_FLOW_ERROR_TYPE_ACTION;
+ err_code = -EINVAL;
+ err_str = "Jump group conflicts to miss queue's TC";
+ goto failure_to_set_miss_actions;
}
}
- break;
- default:
- DPAA2_PMD_ERR("Action(%d) not supported", flow->action_type);
- ret = -ENOTSUP;
- break;
+ if (action_jump)
+ qos_tc = action_jump->group;
+ if (miss_rxq) {
+ qos_tc = miss_rxq->tc_index;
+ qos_flow = miss_rxq->flow_id;
+ }
+ if ((!discard && qos_tc == 0xff) ||
+ (discard && qos_tc != 0xff)) {
+ error_type = RTE_FLOW_ERROR_TYPE_ACTION;
+ err_code = -EINVAL;
+ err_str = "Invalid miss action set for QoS table";
+ goto failure_to_set_miss_actions;
+ }
+ err_code = dpaa2_flow_qos_table_set_default(priv, discard, qos_tc, qos_flow);
+ if (err_code) {
+ error_type = RTE_FLOW_ERROR_TYPE_UNSPECIFIED;
+ err_str = "Failed to set miss action for QoS table";
+ goto failure_to_set_miss_actions;
+ }
+
+ return 0;
}
- LIST_REMOVE(flow, next);
- rte_free(flow->qos_key_addr);
- rte_free(flow->qos_mask_addr);
- rte_free(flow->fs_key_addr);
- rte_free(flow->fs_mask_addr);
- /* Now free the flow */
- rte_free(flow);
+ if (!priv->fs_entries) {
+ error_type = RTE_FLOW_ERROR_TYPE_ACTION;
+ err_code = -EINVAL;
+ err_str = "No FS table available!";
+ goto failure_to_set_miss_actions;
+ }
+ if (!discard && !miss_rxq) {
+ error_type = RTE_FLOW_ERROR_TYPE_ACTION;
+ err_code = -EINVAL;
+ err_str = "Invalid miss action set for FS table";
+ goto failure_to_set_miss_actions;
+ }
+ if (miss_rxq && miss_rxq->tc_index != group_id) {
+ error_type = RTE_FLOW_ERROR_TYPE_ATTR_GROUP;
+ err_code = -EINVAL;
+ err_str = "Group conflicts with dest queue's TC ID";
+ goto failure_to_set_miss_actions;
+ }
+ err_code = dpaa2_flow_fs_table_set_default(priv, group_id, discard,
+ dest_queue ? dest_queue->index : 0);
+ if (err_code) {
+ error_type = RTE_FLOW_ERROR_TYPE_UNSPECIFIED;
+ err_str = "Failed to set miss action for FS table";
+ }
-error:
- if (ret)
- rte_flow_error_set(error, EPERM,
- RTE_FLOW_ERROR_TYPE_UNSPECIFIED,
- NULL, "unknown");
- return ret;
+failure_to_set_miss_actions:
+ if (err_str)
+ DPAA2_PMD_ERR("%s: %s", __func__, err_str);
+ rte_flow_error_set(err, -err_code, error_type, NULL, err_str);
+
+ return err_code;
+}
+
+static int
+dpaa2_flow_actions_update(struct rte_eth_dev *dev,
+ struct rte_flow *_flow,
+ const struct rte_flow_action actions[],
+ struct rte_flow_error *error)
+{
+ struct rte_dpaa2_device *dpaa2_dev;
+ struct dpaa2_dev_priv *priv = dev->data->dev_private;
+ struct dpaa2_dev_flow *flow;
+ struct dpaa2_flow_tbl_profile *tbl_profile = NULL;
+ int ret = 0, is_rss = false, hw_update = false, err_code = 0, qos_direct;
+ struct dpaa2_dev_flow_fs_action *fs_action;
+ uint8_t qos_action_num = 0, fs_action_num = 0, tc_id;
+ struct rte_flow_action qos_actions[DPAA2_MAX_ACTION_PER_FLOW_NUM];
+ struct rte_flow_action fs_actions[DPAA2_MAX_ACTION_PER_FLOW_NUM];
+ const struct rte_flow_action_rss *rss_conf;
+ struct rte_flow_action_jump jump_conf;
+ struct rte_flow_item items[DPKG_MAX_NUM_OF_EXTRACTS + 1];
+ uint8_t spec_buf[1024];
+ struct rte_flow_attr attr;
+ const enum rte_flow_action_type *supported = NULL;
+ uint16_t supported_len = 0;
+ enum rte_flow_error_type error_type = RTE_FLOW_ERROR_TYPE_NONE;
+ const char *err_str = NULL;
+ const struct rte_flow_action_queue *action_q;
+ struct dpaa2_queue *rxq = NULL;
+
+ dpaa2_dev = DPAA2_DEV_PRIV_TO_DPAA2_DEV(priv);
+
+ /* check for the valid flow */
+ flow = (void *)_flow;
+ if (flow->is_meter_flow) {
+ RTE_ASSERT(flow->fs_flow);
+ tc_id = flow->fs_flow->tc_id;
+ RTE_ASSERT(priv->flow_profile.mtr_flow[tc_id] == flow);
+ supported = dpaa2_supported_meter_action_type;
+ supported_len = RTE_DIM(dpaa2_supported_meter_action_type);
+ if (!dpaa2_flow_check_actions_support(actions, supported, supported_len)) {
+ error_type = RTE_FLOW_ERROR_TYPE_ACTION;
+ err_str = "Failed to verify meter action!";
+ err_code = -ENOTSUP;
+ goto quit;
+ }
+ ret = dpaa2_flow_fs_action_update(priv, flow->fs_flow, actions);
+ if (ret) {
+ error_type = RTE_FLOW_ERROR_TYPE_ACTION;
+ err_str = "Failed to update meter action!";
+ err_code = ret;
+ }
+ goto quit;
+ }
+ LIST_FOREACH(flow, &priv->flows, next) {
+ if ((struct rte_flow *)flow == _flow)
+ goto action_update;
+ }
+ DPAA2_PMD_ERR("%s: Flow(%p) is not in %s's flow list",
+ __func__, flow, dev->data->name);
+ error_type = RTE_FLOW_ERROR_TYPE_UNSPECIFIED;
+ err_str = "Invalid flow for action update!";
+ err_code = -EINVAL;
+
+ goto quit;
+
+action_update:
+ if (flow->fs_flow) {
+ supported = dpaa2_supported_fs_action_type;
+ supported_len = RTE_DIM(dpaa2_supported_fs_action_type);
+ } else {
+ supported = dpaa2_supported_qos_action_type;
+ supported_len = RTE_DIM(dpaa2_supported_qos_action_type);
+ }
+ if (!dpaa2_flow_check_actions_support(actions, supported, supported_len)) {
+ error_type = RTE_FLOW_ERROR_TYPE_ACTION;
+ err_str = "Failed to verify QoS/FS action!";
+ err_code = -ENOTSUP;
+ goto quit;
+ }
+ ret = dpaa2_flow_qos_fs_action_set(actions, qos_actions, fs_actions,
+ &qos_action_num, &fs_action_num);
+ if (ret) {
+ error_type = RTE_FLOW_ERROR_TYPE_ACTION;
+ err_str = "Failed to set QoS/FS action!";
+ err_code = ret;
+ goto quit;
+ }
+ flow = (struct dpaa2_dev_flow *)_flow;
+ qos_direct = false;
+ if (flow->qos_flow && flow->qos_flow->direct_queue)
+ qos_direct = true;
+ if (flow->fs_flow && flow->qos_flow && qos_action_num > 0) {
+ error_type = RTE_FLOW_ERROR_TYPE_ACTION_NUM;
+ err_str = "One-level flow can't update QoS action!";
+ err_code = -ENOTSUP;
+ goto quit;
+ }
+ if ((!flow->fs_flow && fs_action_num > 0 && !qos_direct) ||
+ (!flow->qos_flow && qos_action_num > 0)) {
+ error_type = RTE_FLOW_ERROR_TYPE_ACTION;
+ err_str = "Flow type and flow action don't match!";
+ err_code = -EINVAL;
+ goto quit;
+ }
+ if (fs_action_num > 0 &&
+ dpaa2_flow_action_single_type_check(fs_actions,
+ RTE_FLOW_ACTION_TYPE_QUEUE)) {
+ action_q = fs_actions[0].conf;
+ if (action_q->index >= dev->data->nb_rx_queues) {
+ error_type = RTE_FLOW_ERROR_TYPE_ACTION;
+ err_str = "Queue index is too large!";
+ err_code = -EINVAL;
+ goto quit;
+ }
+ rxq = dev->data->rx_queues[action_q->index];
+ if (flow->fs_flow && flow->fs_flow->tc_id != rxq->tc_index) {
+ error_type = RTE_FLOW_ERROR_TYPE_ACTION;
+ err_str = "Update queue is not in this TC!";
+ err_code = -EINVAL;
+ goto quit;
+ }
+ }
+
+ if (!flow->fs_flow)
+ goto qos_action_update;
+ fs_action = &flow->fs_flow->flow_action.fs_action;
+ if (fs_action->action_type == RTE_FLOW_ACTION_TYPE_RSS) {
+ is_rss = true;
+ tc_id = flow->fs_flow->tc_id;
+ tbl_profile = &priv->flow_profile.tc_profile[tc_id];
+ if (tbl_profile->rss_flow != flow) {
+ DPAA2_PMD_ERR("%s: RSS flow(%p) != TC[%d]'s rss flow(%p)",
+ __func__, flow, flow->fs_flow->tc_id, tbl_profile->rss_flow);
+ error_type = RTE_FLOW_ERROR_TYPE_ACTION;
+ err_str = "The flow to update is not specified TC's RSS flow!";
+ err_code = -EINVAL;
+ goto quit;
+ }
+ }
+ if (fs_action_num > 0 &&
+ fs_actions[0].type != RTE_FLOW_ACTION_TYPE_PORT_ID &&
+ fs_actions[0].type != RTE_FLOW_ACTION_TYPE_REPRESENTED_PORT &&
+ dpaa2_dev->bus_info->mc_rev >= DPAA2_FS_FLOW_HW_ACTION_UPDATE_MC_REV) {
+ /** Action HW update doesn't support redirecting frames to other DPNIs.*/
+ hw_update = true;
+ goto skip_remove_fs_entry;
+ }
+
+ if (!is_rss) {
+ ret = dpaa2_flow_remove_generic_entry(dev, flow->fs_flow,
+ DPAA2_FLOW_FS_TYPE);
+ if (ret) {
+ DPAA2_PMD_ERR("%s: remove flow fs entry failed(%d)",
+ __func__, ret);
+ error_type = RTE_FLOW_ERROR_TYPE_UNSPECIFIED;
+ err_str = "Failed to remove flow in flow action update!";
+ err_code = ret;
+
+ goto quit;
+ }
+ }
+
+skip_remove_fs_entry:
+ if (is_rss) {
+ rss_conf = fs_actions[0].conf;
+ ret = dpaa2_flow_rss_conf_to_item(rss_conf->types, items,
+ spec_buf, 1024);
+ if (ret < 0) {
+ DPAA2_PMD_ERR("TC[%d] converts to RSS items failed(%d)",
+ flow->fs_flow->tc_id, ret);
+ error_type = RTE_FLOW_ERROR_TYPE_UNSPECIFIED;
+ err_str = "Failed to gen rss items in flow action update!";
+ err_code = ret;
+ goto quit;
+ } else if (!ret) {
+ DPAA2_PMD_ERR("No item is generated by rss type(0x%" PRIx64 ")",
+ rss_conf->types);
+ error_type = RTE_FLOW_ERROR_TYPE_ITEM;
+ err_str = "No item is generated by rss type!";
+ err_code = -ENOTSUP;
+ goto quit;
+ }
+ memset(&attr, 0, sizeof(attr));
+ attr.group = flow->fs_flow->tc_id;
+ attr.ingress = 1;
+ tbl_profile->tc_cfg.dist_size = rss_conf->queue_num;
+ memset(&flow->fs_flow->rule_cfg, 0, sizeof(struct dpni_rule_cfg));
+ memset(flow->fs_flow->key_addr, 0, DPAA2_EXTRACT_ALLOC_KEY_MAX_SIZE);
+ memset(flow->fs_flow->mask_addr, 0, DPAA2_EXTRACT_ALLOC_KEY_MAX_SIZE);
+ flow->fs_flow->rule_size = 0;
+ flow->fs_flow->ip_key = NET_PROT_NONE;
+ flow->fs_flow->ip_src = NET_PROT_NONE;
+ flow->fs_flow->ip_dst = NET_PROT_NONE;
+ ret = dpaa2_flow_generic_extract_rule_set(flow->fs_flow, &attr,
+ items, true, DPAA2_FLOW_FS_TYPE, true);
+ if (ret) {
+ error_type = RTE_FLOW_ERROR_TYPE_ACTION;
+ err_str = "RSS action update failed!";
+ err_code = ret;
+ goto quit;
+ }
+ } else {
+ ret = dpaa2_flow_fs_action_update(priv, flow->fs_flow, fs_actions);
+ if (ret) {
+ error_type = RTE_FLOW_ERROR_TYPE_ACTION;
+ err_str = "FS action update failed!";
+ err_code = ret;
+ goto quit;
+ }
+ if (hw_update)
+ ret = dpaa2_flow_update_fs_rule_action(priv, flow->fs_flow);
+ else
+ ret = dpaa2_flow_add_fs_rule(priv, flow->fs_flow);
+ if (ret) {
+ error_type = RTE_FLOW_ERROR_TYPE_ACTION;
+ err_str = "FS rule action update failed!";
+ err_code = ret;
+ goto quit;
+ }
+ }
+qos_action_update:
+ if (!flow->qos_flow)
+ goto quit;
+
+ if (rxq) {
+ jump_conf.group = rxq->tc_index;
+ qos_actions[qos_action_num].type = RTE_FLOW_ACTION_TYPE_JUMP;
+ qos_actions[qos_action_num].conf = &jump_conf;
+ qos_actions[qos_action_num + 1].type = RTE_FLOW_ACTION_TYPE_END;
+ }
+
+ hw_update = false;
+ if (dpaa2_dev->bus_info->mc_rev >= DPAA2_QOS_FLOW_HW_ACTION_UPDATE_MC_REV) {
+ /** Action HW update doesn't support redirecting frames to other DPNIs.*/
+ hw_update = true;
+ goto skip_remove_qos_entry;
+ }
+
+ ret = dpaa2_flow_remove_generic_entry(dev, flow->qos_flow,
+ DPAA2_FLOW_QOS_TYPE);
+ if (ret) {
+ DPAA2_PMD_ERR("%s: remove flow qos entry failed(%d)",
+ __func__, ret);
+ error_type = RTE_FLOW_ERROR_TYPE_ACTION;
+ err_str = "Failed to remove QoS entry in action update!";
+ err_code = ret;
+
+ goto quit;
+ }
+
+skip_remove_qos_entry:
+ ret = dpaa2_flow_qos_action_update(priv, flow->qos_flow, qos_actions,
+ false);
+ if (ret) {
+ DPAA2_PMD_ERR("%s: QoS action update failed(%d)",
+ __func__, ret);
+ error_type = RTE_FLOW_ERROR_TYPE_ACTION;
+ err_str = "Failed to QoS action update!";
+ err_code = ret;
+
+ goto quit;
+ }
+ if (rxq) {
+ flow->qos_flow->direct_queue = true;
+ flow->qos_flow->flow_id = rxq->flow_id;
+ }
+ if (hw_update)
+ ret = dpaa2_flow_update_qos_rule_action(priv, flow->qos_flow);
+ else
+ ret = dpaa2_flow_add_qos_rule(priv, flow->qos_flow);
+ if (ret) {
+ DPAA2_PMD_ERR("%s: %s qos flow entry failed(%d)",
+ __func__, hw_update ? "update" : "add", ret);
+ error_type = RTE_FLOW_ERROR_TYPE_ACTION;
+ err_str = "Failed to update QoS entry action to HW!";
+ err_code = ret;
+ }
+
+quit:
+ if (err_str)
+ DPAA2_PMD_ERR("%s: %s", __func__, err_str);
+ return rte_flow_error_set(error, -err_code, error_type, NULL, err_str);
}
/**
@@ -5390,24 +6431,113 @@ dpaa2_flow_flush(struct rte_eth_dev *dev,
{
struct dpaa2_dev_priv *priv = dev->data->dev_private;
struct dpaa2_dev_flow *flow = LIST_FIRST(&priv->flows);
+ int ret = 0;
while (flow) {
struct dpaa2_dev_flow *next = LIST_NEXT(flow, next);
- dpaa2_flow_destroy(dev, (struct rte_flow *)flow, error);
+ ret = dpaa2_flow_destroy(dev, (struct rte_flow *)flow, error);
+ if (ret) {
+ DPAA2_PMD_ERR("%s: Remove flow failed(%d)",
+ __func__, ret);
+ }
+
flow = next;
}
- return 0;
+
+ return ret;
}
static int
-dpaa2_flow_query(struct rte_eth_dev *dev __rte_unused,
- struct rte_flow *_flow __rte_unused,
- const struct rte_flow_action *actions __rte_unused,
- void *data __rte_unused,
- struct rte_flow_error *error __rte_unused)
+dpaa2_flow_query(struct rte_eth_dev *dev,
+ struct rte_flow *_flow, const struct rte_flow_action *actions,
+ void *data, struct rte_flow_error *error)
{
- return 0;
+ struct dpaa2_dev_flow *flow;
+ struct dpaa2_dev_priv *priv = dev->data->dev_private;
+ uint16_t num = 0, num_rsp, i, tc_id = 0;
+ int ret = 0, found = false;
+ size_t size, iova;
+ struct dpni_dump_table_rsp *rsp = NULL;
+
+ RTE_SET_USED(actions);
+ RTE_SET_USED(data);
+ RTE_SET_USED(error);
+
+ flow = LIST_FIRST(&priv->flows);
+ while (flow) {
+ num++;
+ if (flow == (struct dpaa2_dev_flow *)_flow)
+ found = true;
+ flow = LIST_NEXT(flow, next);
+ }
+ if (!num || !found)
+ return -ENXIO;
+ num = num * 2;/** Max: FS entry + QoS entry.*/
+ flow = (void *)_flow;
+ size = sizeof(struct dpni_dump_table_header) +
+ num * sizeof(struct dpni_dump_table_entry);
+ rsp = rte_zmalloc(NULL, size, RTE_CACHE_LINE_SIZE);
+ if (!rsp)
+ return -ENOMEM;
+ iova = DPAA2_VADDR_TO_IOVA_AND_CHECK(rsp, size);
+ if (iova == RTE_BAD_IOVA) {
+ DPAA2_PMD_ERR("%s: No IOMMU map for dump table result!",
+ __func__);
+ ret = -EIO;
+ goto quit;
+ }
+
+ if (priv->num_rx_tc <= 1)
+ goto dump_fs;
+
+ ret = dpni_dump_table(priv->hw, CMD_PRI_LOW,
+ priv->token, DPNI_QOS_TABLE, 0/**Any*/,
+ iova, size, &num_rsp);
+ if (ret) {
+ DPAA2_PMD_ERR("dump %s's QoS table failed(%d)",
+ dev->data->name, ret);
+ goto quit;
+ }
+
+ if (!flow->qos_flow)
+ goto dump_fs;
+
+ for (i = 0; i < num_rsp; i++) {
+ if (!memcmp(rsp->entry[i].key, flow->qos_flow->key_addr,
+ flow->qos_flow->rule_size) &&
+ !memcmp(rsp->entry[i].mask,
+ flow->qos_flow->mask_addr, flow->qos_flow->rule_size))
+ break;
+ }
+
+dump_fs:
+ if (!flow->fs_flow)
+ goto quit;
+
+ tc_id = flow->fs_flow->tc_id;
+ ret = dpni_dump_table(priv->hw, CMD_PRI_LOW,
+ priv->token, DPNI_FS_TABLE, tc_id,
+ iova, size, &num_rsp);
+ if (ret) {
+ DPAA2_PMD_ERR("dump %s's FS%d table failed(%d)",
+ dev->data->name, tc_id, ret);
+ goto quit;
+ }
+ for (i = 0; i < num_rsp; i++) {
+ if (!memcmp(rsp->entry[i].key, flow->fs_flow->key_addr,
+ flow->fs_flow->rule_size) &&
+ !memcmp(rsp->entry[i].mask,
+ flow->fs_flow->mask_addr, flow->fs_flow->rule_size)) {
+ break;
+ }
+ }
+
+quit:
+ if (rsp)
+ rte_free(rsp);
+
+ return ret;
}
/**
@@ -5420,19 +6550,45 @@ dpaa2_flow_query(struct rte_eth_dev *dev __rte_unused,
* Pointer to private structure.
*/
void
-dpaa2_flow_clean(struct rte_eth_dev *dev)
+dpaa2_flow_clean(struct rte_eth_dev *dev, uint8_t tc_id)
{
- struct dpaa2_dev_flow *flow;
+ struct dpaa2_dev_flow *flow, *next_flow;
struct dpaa2_dev_priv *priv = dev->data->dev_private;
+ int ret;
- while ((flow = LIST_FIRST(&priv->flows)))
- dpaa2_flow_destroy(dev, (struct rte_flow *)flow, NULL);
+ flow = LIST_FIRST(&priv->flows);
+ if (tc_id >= MAX_TCS)
+ goto clean_all;
+ while (flow) {
+ next_flow = LIST_NEXT(flow, next);
+ if (flow->fs_flow && flow->fs_flow->tc_id == tc_id) {
+ ret = dpaa2_flow_destroy(dev, (struct rte_flow *)flow, NULL);
+ if (ret) {
+ DPAA2_PMD_ERR("%s: Remove flow failed(%d)",
+ __func__, ret);
+ }
+ }
+ flow = next_flow;
+ }
+ return;
+
+clean_all:
+ while (flow) {
+ ret = dpaa2_flow_destroy(dev, (struct rte_flow *)flow, NULL);
+ if (ret) {
+ DPAA2_PMD_ERR("%s: Remove flow failed(%d)",
+ __func__, ret);
+ }
+ flow = LIST_FIRST(&priv->flows);
+ }
}
const struct rte_flow_ops dpaa2_flow_ops = {
.create = dpaa2_flow_create,
.validate = dpaa2_flow_validate,
.destroy = dpaa2_flow_destroy,
+ .group_set_miss_actions = dpaa2_flow_set_miss_actions,
+ .actions_update = dpaa2_flow_actions_update,
.flush = dpaa2_flow_flush,
.query = dpaa2_flow_query,
};
diff --git a/drivers/net/dpaa2/meson.build b/drivers/net/dpaa2/meson.build
index 4f774f7c82..3f8bee9146 100644
--- a/drivers/net/dpaa2/meson.build
+++ b/drivers/net/dpaa2/meson.build
@@ -1,5 +1,5 @@
# SPDX-License-Identifier: BSD-3-Clause
-# Copyright 2018-2021 NXP
+# Copyright 2018-2026 NXP
if not is_linux
build = false
@@ -8,7 +8,6 @@ endif
deps += ['mempool_dpaa2']
sources = files(
- 'base/dpaa2_hw_dpni.c',
'base/dpaa2_tlu_hash.c',
'dpaa2_tm.c',
'dpaa2_meter.c',
--
2.43.0
next prev parent reply other threads:[~2026-09-03 13:58 UTC|newest]
Thread overview: 47+ messages / expand[flat|nested] mbox.gz Atom feed top
2026-09-03 13:53 [PATCH 00/45] net/dpaa2: features and fixes for NXP DPAA2 drivers Prashant Gupta
2026-09-03 13:53 ` [PATCH 01/45] crypto/dpaa2_sec: fix buffer overflow in GCM decrypt Prashant Gupta
2026-09-03 13:53 ` [PATCH 02/45] crypto/dpaa2_sec: fix FLE pool leak on sec FD build failure Prashant Gupta
2026-09-03 13:53 ` [PATCH 03/45] crypto/dpaa2_sec: support AES-GMAC Prashant Gupta
2026-09-03 13:53 ` [PATCH 04/45] crypto/dpaa2_sec: increase ivsize range for AES-CTR Prashant Gupta
2026-09-03 13:53 ` [PATCH 05/45] crypto/dpaa2_sec: add missing ECN capability Prashant Gupta
2026-09-03 13:53 ` [PATCH 06/45] crypto/dpaa2_sec: add support for env variables Prashant Gupta
2026-09-03 13:53 ` [PATCH 07/45] drivers: fix double free of dpaa2 device on uninit Prashant Gupta
2026-09-03 14:05 ` David Marchand
2026-09-03 13:53 ` [PATCH 08/45] net/dpaa2: fix integer overflow in CCSR region mapping Prashant Gupta
2026-09-03 13:53 ` [PATCH 09/45] dma/dpaa2: fix array-bounds warning in dequeue path Prashant Gupta
2026-09-03 13:53 ` [PATCH 10/45] bus/fslmc: defer bus initialization to probe Prashant Gupta
2026-09-03 13:53 ` [PATCH 11/45] dma/dpaa2: validate IOVA in pre-populate helpers Prashant Gupta
2026-09-03 13:53 ` [PATCH 12/45] dma/dpaa2: optimize context index ring enqueue Prashant Gupta
2026-09-03 13:53 ` [PATCH 13/45] drivers: add dpaa2 DMA bypass memory translation option Prashant Gupta
2026-09-03 13:53 ` [PATCH 14/45] mempool/dpaa2: support ops index from primary in secondary Prashant Gupta
2026-09-03 13:53 ` [PATCH 15/45] net/dpaa2: set Tx confirmation on device init Prashant Gupta
2026-09-03 13:53 ` [PATCH 16/45] drivers: optimize dpaa2 Tx queue and channel mapping Prashant Gupta
2026-09-03 13:53 ` [PATCH 17/45] net/dpaa2: support larger burst size Prashant Gupta
2026-09-03 13:53 ` [PATCH 18/45] net/dpaa2: support MPLS and PPPoE flow distribution Prashant Gupta
2026-09-03 13:53 ` [PATCH 19/45] net/dpaa2: support meter and policing Prashant Gupta
2026-09-03 13:53 ` [PATCH 20/45] net/dpaa2: support flow drop action Prashant Gupta
2026-09-03 13:53 ` [PATCH 21/45] net/dpaa2: set default flow miss action per device Prashant Gupta
2026-09-03 13:53 ` [PATCH 22/45] net/dpaa2: identify Rx mbuf hash information by FLC Prashant Gupta
2026-09-03 13:53 ` [PATCH 23/45] net/dpaa2: add minimum key size support Prashant Gupta
2026-09-03 13:53 ` [PATCH 24/45] net/dpaa2: restructure dpaa2 parser processing Prashant Gupta
2026-09-03 13:53 ` [PATCH 25/45] net/dpaa2: parse tunnel and fragmented packet types Prashant Gupta
2026-09-03 13:53 ` [PATCH 26/45] net/dpaa2: remove unused soft parser driver Prashant Gupta
2026-09-03 13:53 ` [PATCH 27/45] drivers: refresh dpaa2 MC and SoC version info Prashant Gupta
2026-09-03 13:53 ` [PATCH 28/45] drivers: identify dpaa2 soft parser protocol Prashant Gupta
2026-09-03 13:53 ` [PATCH 29/45] drivers: assign dpaa2 Rx CGID per traffic class Prashant Gupta
2026-09-03 13:53 ` [PATCH 30/45] drivers: inherit dpaa2 rxq config for event queue Prashant Gupta
2026-09-03 13:53 ` [PATCH 31/45] net/dpaa2: rename Rx queue flags Prashant Gupta
2026-09-03 13:53 ` [PATCH 32/45] drivers: rework dpaa2 Tx confirmation Prashant Gupta
2026-09-03 13:53 ` [PATCH 33/45] net/dpaa2: ptp enhancements Prashant Gupta
2026-09-03 13:53 ` [PATCH 34/45] net/dpaa2: remove unused soft parser Tx code Prashant Gupta
2026-09-03 13:53 ` [PATCH 35/45] net/dpaa2: update MC dpni QoS and flow steering API Prashant Gupta
2026-09-03 13:53 ` [PATCH 36/45] net/dpaa2: enhance xstat implementation Prashant Gupta
2026-09-03 13:53 ` Prashant Gupta [this message]
2026-09-03 13:53 ` [PATCH 38/45] net/dpaa2: support Rx mempool per traffic class Prashant Gupta
2026-09-03 13:53 ` [PATCH 39/45] drivers: consume dpaa2 DQRR entries in batches Prashant Gupta
2026-09-03 13:53 ` [PATCH 40/45] drivers: resolve dpaa2 endpoint in the net driver Prashant Gupta
2026-09-03 13:53 ` [PATCH 41/45] drivers: align dpaa2 event port depths with hardware rings Prashant Gupta
2026-09-03 13:53 ` [PATCH 42/45] net/dpaa2: read MC version from device private data Prashant Gupta
2026-09-03 13:53 ` [PATCH 43/45] net/dpaa2: do not overwrite mbuf hash with drop priority Prashant Gupta
2026-09-03 13:53 ` [PATCH 44/45] bus/fslmc: reduce probe-time logging and MC traffic Prashant Gupta
2026-09-03 13:53 ` [PATCH 45/45] net/dpaa2: reject Rx queue deferred start Prashant Gupta
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=20260903135353.3358303-38-prashant.gupta_3@nxp.com \
--to=prashant.gupta_3@nxp.com \
--cc=dev@dpdk.org \
--cc=hemant.agrawal@nxp.com \
--cc=stephen@networkplumber.org \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox