[PATCH v4-S3 26/65] net/dpaa2: program flow table miss actions via rte_flow

Prashant Gupta prashant.gupta_3 at nxp.com
Fri Oct 23 15:43:06 CEST 2026


From: Jun Yang <jun.yang at nxp.com>

Push the per-table "miss" behavior for the DPAA2 QoS and FS tables
through the standard rte_flow_group_set_miss_actions() API instead
of leaving it implicit, and tidy up the surrounding dev-ops code.

Signed-off-by: Jun Yang <jun.yang at nxp.com>
---
 drivers/net/dpaa2/dpaa2_ethdev.c | 440 +++++++++++++++++--------------
 1 file changed, 243 insertions(+), 197 deletions(-)

diff --git a/drivers/net/dpaa2/dpaa2_ethdev.c b/drivers/net/dpaa2/dpaa2_ethdev.c
index 7cd83149dd..9f92789d4e 100644
--- a/drivers/net/dpaa2/dpaa2_ethdev.c
+++ b/drivers/net/dpaa2/dpaa2_ethdev.c
@@ -459,11 +459,52 @@ static const struct rte_eth_stats dpaa2_stats_xstat_ids = {
 #define DPAA2_MAC_XSTATS_START_ID DPAA2_DPNI_XSTAT_MAX_NUM
 
 static struct rte_dpaa2_driver rte_dpaa2_pmd;
-static int dpaa2_dev_link_update(struct rte_eth_dev *dev,
-				 int wait_to_complete);
-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_dist(struct rte_eth_dev *eth_dev,
@@ -1162,18 +1203,14 @@ dpaa2_eth_dev_configure(struct rte_eth_dev *dev)
 
 	/* Rx offloads which are enabled by default */
 	if (dev_rx_offloads_nodis & ~rx_offloads) {
-		DPAA2_PMD_INFO(
-		"Some of rx offloads enabled by default - requested 0x%" PRIx64
-		" fixed are 0x%" PRIx64,
-		rx_offloads, dev_rx_offloads_nodis);
+		DPAA2_PMD_INFO("RX offloads requested/fixed: 0x%" PRIx64 "/0x%" PRIx64,
+			rx_offloads, dev_rx_offloads_nodis);
 	}
 
 	/* Tx offloads which are enabled by default */
 	if (dev_tx_offloads_nodis & ~tx_offloads) {
-		DPAA2_PMD_INFO(
-		"Some of tx offloads enabled by default - requested 0x%" PRIx64
-		" fixed are 0x%" PRIx64,
-		tx_offloads, dev_tx_offloads_nodis);
+		DPAA2_PMD_INFO("TX offloads requested/fixed: 0x%" PRIx64 "/0x%" PRIx64,
+			tx_offloads, dev_tx_offloads_nodis);
 	}
 
 	max_rx_pktlen = eth_conf->rxmode.mtu + RTE_ETHER_HDR_LEN +
@@ -1181,16 +1218,31 @@ dpaa2_eth_dev_configure(struct rte_eth_dev *dev)
 	if (max_rx_pktlen <= DPAA2_MAX_RX_PKT_LEN) {
 		ret = dpni_set_max_frame_length(dpni, CMD_PRI_LOW,
 			priv->token, max_rx_pktlen - RTE_ETHER_CRC_LEN);
-		if (ret != 0) {
+		if (ret) {
 			DPAA2_PMD_ERR("Unable to set mtu. check config");
 			return ret;
 		}
 		DPAA2_PMD_DEBUG("MTU configured for the device: %d",
 				dev->data->mtu);
 	} else {
-		DPAA2_PMD_ERR("Configured mtu %d and calculated max-pkt-len is %d which should be <= %d",
-			eth_conf->rxmode.mtu, max_rx_pktlen, DPAA2_MAX_RX_PKT_LEN);
-		return -1;
+		DPAA2_PMD_ERR("MAX MTU(%d) to configure > %d",
+			max_rx_pktlen, DPAA2_MAX_RX_PKT_LEN);
+		return -ENOTSUP;
+	}
+
+	if (priv->fs_entries) {
+		for (tc_index = 0; tc_index < priv->num_rx_tc; tc_index++) {
+			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);
+			}
+		}
+	}
+	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) {
@@ -1784,6 +1836,171 @@ dpaa2_supported_ptypes_get(struct rte_eth_dev *dev, size_t *no_of_elements)
 	return NULL;
 }
 
+/* return 0 means link status changed, -1 means not changed */
+static int
+dpaa2_dev_link_update(struct rte_eth_dev *dev,
+	int wait_to_complete)
+{
+	int ret;
+	struct dpaa2_dev_priv *priv = dev->data->dev_private;
+	struct fsl_mc_io *dpni = dev->process_private;
+	struct rte_eth_link link;
+	struct dpni_link_state state = {0};
+	uint8_t count;
+
+	if (!dpni) {
+		DPAA2_PMD_ERR("dpni is NULL");
+		return 0;
+	}
+
+	for (count = 0; count <= MAX_REPEAT_TIME; count++) {
+		ret = dpni_get_link_state(dpni, CMD_PRI_LOW, priv->token, &state);
+		if (ret < 0) {
+			DPAA2_PMD_DEBUG("error: dpni_get_link_state %d", ret);
+			return ret;
+		}
+		if (state.up == RTE_ETH_LINK_DOWN &&
+		    wait_to_complete)
+			rte_delay_ms(CHECK_INTERVAL);
+		else
+			break;
+	}
+
+	memset(&link, 0, sizeof(struct rte_eth_link));
+	link.link_status = state.up;
+	link.link_speed = state.rate;
+
+	if (state.options & DPNI_LINK_OPT_HALF_DUPLEX)
+		link.link_duplex = RTE_ETH_LINK_HALF_DUPLEX;
+	else
+		link.link_duplex = RTE_ETH_LINK_FULL_DUPLEX;
+
+	ret = rte_eth_linkstatus_set(dev, &link);
+	if (ret < 0) {
+		DPAA2_PMD_DEBUG("No change in status");
+	} else {
+		DPAA2_PMD_INFO("Port %d Link is %s", dev->data->port_id,
+			link.link_status ? "Up" : "Down");
+	}
+
+	return ret;
+}
+
+/**
+ * Toggle the DPNI to enable, if not already enabled.
+ * This is not strictly PHY up/down - it is more of logical toggling.
+ */
+static int
+dpaa2_dev_set_link_up(struct rte_eth_dev *dev)
+{
+	int ret, en = 0;
+	struct dpaa2_dev_priv *priv;
+	struct fsl_mc_io *dpni;
+	struct dpni_link_state state = {0};
+
+	priv = dev->data->dev_private;
+	dpni = dev->process_private;
+
+	if (!dpni) {
+		DPAA2_PMD_ERR("dpni is NULL");
+		return -ENODEV;
+	}
+
+	/* Check if DPNI is currently enabled */
+	ret = dpni_is_enabled(dpni, CMD_PRI_LOW, priv->token, &en);
+	if (ret) {
+		/* Unable to obtain dpni status; Not continuing */
+		DPAA2_PMD_ERR("Interface Link UP failed (%d)", ret);
+		return ret;
+	}
+
+	/* Enable link if not already enabled */
+	if (!en) {
+		ret = dpni_enable(dpni, CMD_PRI_LOW, priv->token);
+		if (ret) {
+			DPAA2_PMD_ERR("Interface Link UP failed (%d)", ret);
+			return ret;
+		}
+	}
+	ret = dpni_get_link_state(dpni, CMD_PRI_LOW, priv->token, &state);
+	if (ret < 0) {
+		DPAA2_PMD_DEBUG("Unable to get link state (%d)", ret);
+		return ret;
+	}
+
+	/* changing tx burst function to start enqueues */
+	dev->tx_pkt_burst = dpaa2_dev_tx;
+	dev->data->dev_link.link_status = state.up;
+	dev->data->dev_link.link_speed = state.rate;
+
+	if (state.options & DPNI_LINK_OPT_HALF_DUPLEX)
+		dev->data->dev_link.link_duplex = RTE_ETH_LINK_HALF_DUPLEX;
+	else
+		dev->data->dev_link.link_duplex = RTE_ETH_LINK_FULL_DUPLEX;
+
+	if (state.up)
+		DPAA2_PMD_DEBUG("Port %d Link is Up", dev->data->port_id);
+	else
+		DPAA2_PMD_DEBUG("Port %d Link is Down", dev->data->port_id);
+	return ret;
+}
+
+/**
+ * Toggle the DPNI to disable, if not already disabled.
+ * This is not strictly PHY up/down - it is more of logical toggling.
+ */
+static int
+dpaa2_dev_set_link_down(struct rte_eth_dev *dev)
+{
+	int ret, dpni_enabled = 0, retries = 10;
+	struct dpaa2_dev_priv *priv;
+	struct fsl_mc_io *dpni;
+
+	PMD_INIT_FUNC_TRACE();
+
+	priv = dev->data->dev_private;
+	dpni = dev->process_private;
+
+	if (!dpni) {
+		DPAA2_PMD_ERR("Device has not yet been configured");
+		return -ENODEV;
+	}
+
+	/*changing  tx burst function to avoid any more enqueues */
+	dev->tx_pkt_burst = rte_eth_pkt_burst_dummy;
+
+	/* Loop while dpni_disable() attempts to drain the egress FQs
+	 * and confirm them back to us.
+	 */
+	do {
+		ret = dpni_disable(dpni, 0, priv->token);
+		if (ret) {
+			DPAA2_PMD_ERR("dpni disable failed (%d)", ret);
+			return ret;
+		}
+		ret = dpni_is_enabled(dpni, 0, priv->token, &dpni_enabled);
+		if (ret) {
+			DPAA2_PMD_ERR("dpni enable check failed (%d)", ret);
+			return ret;
+		}
+		if (dpni_enabled)
+			/* Allow the MC some slack */
+			rte_delay_ms(CHECK_INTERVAL);
+	} while (dpni_enabled && --retries);
+
+	if (!retries) {
+		DPAA2_PMD_WARN("Retry count exceeded disabling dpni");
+		/* todo- we may have to manually cleanup queues.
+		 */
+	} else {
+		DPAA2_PMD_INFO("Port %d Link DOWN successful", dev->data->port_id);
+	}
+
+	dev->data->dev_link.link_status = 0;
+
+	return ret;
+}
+
 /**
  * Dpaa2 link Interrupt handler
  *
@@ -1842,19 +2059,18 @@ dpaa2_eth_setup_irqs(struct rte_eth_dev *dev, int enable)
 
 	PMD_INIT_FUNC_TRACE();
 
-	err = dpni_set_irq_mask(dpni, CMD_PRI_LOW, priv->token,
-				irq_index, mask);
+	err = dpni_set_irq_mask(dpni, CMD_PRI_LOW, priv->token, irq_index, mask);
 	if (err < 0) {
 		DPAA2_PMD_ERR("Error: dpni_set_irq_mask():%d (%s)", err,
-			      strerror(-err));
+			strerror(-err));
 		return err;
 	}
 
-	err = dpni_set_irq_enable(dpni, CMD_PRI_LOW, priv->token,
-				  irq_index, enable);
-	if (err < 0)
+	err = dpni_set_irq_enable(dpni, CMD_PRI_LOW, priv->token, irq_index, enable);
+	if (err < 0) {
 		DPAA2_PMD_ERR("Error: dpni_set_irq_enable():%d (%s)", err,
-			      strerror(-err));
+			strerror(-err));
+	}
 
 	return err;
 }
@@ -2021,8 +2237,7 @@ dpaa2_dev_stop(struct rte_eth_dev *dev)
 
 		/* Unregistering LSC interrupt handler */
 		rte_intr_callback_unregister(intr_handle,
-					     dpaa2_interrupt_handler,
-					     (void *)dev);
+			dpaa2_interrupt_handler, (void *)dev);
 	}
 
 	dpaa2_dev_set_link_down(dev);
@@ -2233,14 +2448,14 @@ dpaa2_dev_mtu_set(struct rte_eth_dev *dev, uint16_t mtu)
 
 	if (!dpni) {
 		DPAA2_PMD_ERR("dpni is NULL");
-		return -EINVAL;
+		return -ENODEV;
 	}
 
 	/* Set the Max Rx frame length as 'mtu' +
 	 * Maximum Ethernet header length
 	 */
 	ret = dpni_set_max_frame_length(dpni, CMD_PRI_LOW, priv->token,
-					frame_size - RTE_ETHER_CRC_LEN);
+			frame_size - RTE_ETHER_CRC_LEN);
 	if (ret) {
 		DPAA2_PMD_ERR("Setting the max frame length failed");
 		return ret;
@@ -2676,175 +2891,6 @@ dpaa2_dev_stats_reset(struct rte_eth_dev *dev)
 	return retcode;
 };
 
-/* return 0 means link status changed, -1 means not changed */
-static int
-dpaa2_dev_link_update(struct rte_eth_dev *dev,
-		      int wait_to_complete)
-{
-	int ret;
-	struct dpaa2_dev_priv *priv = dev->data->dev_private;
-	struct fsl_mc_io *dpni = dev->process_private;
-	struct rte_eth_link link;
-	struct dpni_link_state state = {0};
-	uint8_t count;
-
-	if (!dpni) {
-		DPAA2_PMD_ERR("dpni is NULL");
-		return 0;
-	}
-
-	for (count = 0; count <= MAX_REPEAT_TIME; count++) {
-		ret = dpni_get_link_state(dpni, CMD_PRI_LOW, priv->token,
-					  &state);
-		if (ret < 0) {
-			DPAA2_PMD_DEBUG("error: dpni_get_link_state %d", ret);
-			return ret;
-		}
-		if (state.up == RTE_ETH_LINK_DOWN &&
-		    wait_to_complete)
-			rte_delay_ms(CHECK_INTERVAL);
-		else
-			break;
-	}
-
-	memset(&link, 0, sizeof(struct rte_eth_link));
-	link.link_status = state.up;
-	link.link_speed = state.rate;
-
-	if (state.options & DPNI_LINK_OPT_HALF_DUPLEX)
-		link.link_duplex = RTE_ETH_LINK_HALF_DUPLEX;
-	else
-		link.link_duplex = RTE_ETH_LINK_FULL_DUPLEX;
-
-	ret = rte_eth_linkstatus_set(dev, &link);
-	if (ret < 0)
-		DPAA2_PMD_DEBUG("No change in status");
-	else
-		DPAA2_PMD_INFO("Port %d Link is %s", dev->data->port_id,
-			       link.link_status ? "Up" : "Down");
-
-	return ret;
-}
-
-/**
- * Toggle the DPNI to enable, if not already enabled.
- * This is not strictly PHY up/down - it is more of logical toggling.
- */
-static int
-dpaa2_dev_set_link_up(struct rte_eth_dev *dev)
-{
-	int ret = -EINVAL;
-	struct dpaa2_dev_priv *priv;
-	struct fsl_mc_io *dpni;
-	int en = 0;
-	struct dpni_link_state state = {0};
-
-	priv = dev->data->dev_private;
-	dpni = dev->process_private;
-
-	if (!dpni) {
-		DPAA2_PMD_ERR("dpni is NULL");
-		return ret;
-	}
-
-	/* Check if DPNI is currently enabled */
-	ret = dpni_is_enabled(dpni, CMD_PRI_LOW, priv->token, &en);
-	if (ret) {
-		/* Unable to obtain dpni status; Not continuing */
-		DPAA2_PMD_ERR("Interface Link UP failed (%d)", ret);
-		return ret;
-	}
-
-	/* Enable link if not already enabled */
-	if (!en) {
-		ret = dpni_enable(dpni, CMD_PRI_LOW, priv->token);
-		if (ret) {
-			DPAA2_PMD_ERR("Interface Link UP failed (%d)", ret);
-			return ret;
-		}
-	}
-	ret = dpni_get_link_state(dpni, CMD_PRI_LOW, priv->token, &state);
-	if (ret < 0) {
-		DPAA2_PMD_DEBUG("Unable to get link state (%d)", ret);
-		return ret;
-	}
-
-	/* changing tx burst function to start enqueues */
-	dev->tx_pkt_burst = dpaa2_dev_tx;
-	dev->data->dev_link.link_status = state.up;
-	dev->data->dev_link.link_speed = state.rate;
-
-	if (state.options & DPNI_LINK_OPT_HALF_DUPLEX)
-		dev->data->dev_link.link_duplex = RTE_ETH_LINK_HALF_DUPLEX;
-	else
-		dev->data->dev_link.link_duplex = RTE_ETH_LINK_FULL_DUPLEX;
-
-	if (state.up)
-		DPAA2_PMD_DEBUG("Port %d Link is Up", dev->data->port_id);
-	else
-		DPAA2_PMD_DEBUG("Port %d Link is Down", dev->data->port_id);
-	return ret;
-}
-
-/**
- * Toggle the DPNI to disable, if not already disabled.
- * This is not strictly PHY up/down - it is more of logical toggling.
- */
-static int
-dpaa2_dev_set_link_down(struct rte_eth_dev *dev)
-{
-	int ret = -EINVAL;
-	struct dpaa2_dev_priv *priv;
-	struct fsl_mc_io *dpni;
-	int dpni_enabled = 0;
-	int retries = 10;
-
-	PMD_INIT_FUNC_TRACE();
-
-	priv = dev->data->dev_private;
-	dpni = dev->process_private;
-
-	if (!dpni) {
-		DPAA2_PMD_ERR("Device has not yet been configured");
-		return ret;
-	}
-
-	/*changing  tx burst function to avoid any more enqueues */
-	dev->tx_pkt_burst = rte_eth_pkt_burst_dummy;
-
-	/* Loop while dpni_disable() attempts to drain the egress FQs
-	 * and confirm them back to us.
-	 */
-	do {
-		ret = dpni_disable(dpni, 0, priv->token);
-		if (ret) {
-			DPAA2_PMD_ERR("dpni disable failed (%d)", ret);
-			return ret;
-		}
-		ret = dpni_is_enabled(dpni, 0, priv->token, &dpni_enabled);
-		if (ret) {
-			DPAA2_PMD_ERR("dpni enable check failed (%d)", ret);
-			return ret;
-		}
-		if (dpni_enabled)
-			/* Allow the MC some slack */
-			rte_delay_ms(CHECK_INTERVAL);
-	} while (dpni_enabled && --retries);
-
-	if (!retries) {
-		DPAA2_PMD_WARN("Retry count exceeded disabling dpni");
-		/* todo- we may have to manually cleanup queues.
-		 */
-	} else {
-		DPAA2_PMD_INFO("Port %d Link DOWN successful",
-			       dev->data->port_id);
-	}
-
-	dev->data->dev_link.link_status = 0;
-
-	return ret;
-}
-
 static int
 dpaa2_flow_ctrl_get(struct rte_eth_dev *dev, struct rte_eth_fc_conf *fc_conf)
 {
-- 
2.43.0



More information about the dev mailing list