DPDK patches and discussions
 help / color / mirror / Atom feed
From: Sean Zhang <xiazhang@nvidia.com>
To: Matan Azrad <matan@nvidia.com>,
	Viacheslav Ovsiienko <viacheslavo@nvidia.com>
Cc: <dev@dpdk.org>
Subject: [v1] net/mlx5: support represented port item
Date: Sat, 2 Apr 2022 09:40:00 +0300	[thread overview]
Message-ID: <20220402064000.8772-1-xiazhang@nvidia.com> (raw)

Add support for represented_port item in pattern. And if the spec and mask
both are NULL, translate function will not add source vport to matcher.

For example, testpmd starts with PF, VF-rep0 and VF-rep1, below command
will redirect packets from VF0 and VF1 to wire:
testpmd> flow create 0 ingress transfer group 0 pattern eth /
represented_port / end actions represented_port ethdev_id is 0 / end

Signed-off-by: Sean Zhang <xiazhang@nvidia.com>
---
 drivers/net/mlx5/mlx5_flow.h    |   4 +
 drivers/net/mlx5/mlx5_flow_dv.c | 160 +++++++++++++++++++++++++++++++-
 2 files changed, 163 insertions(+), 1 deletion(-)

diff --git a/drivers/net/mlx5/mlx5_flow.h b/drivers/net/mlx5/mlx5_flow.h
index f56115dd11..0740b01de5 100644
--- a/drivers/net/mlx5/mlx5_flow.h
+++ b/drivers/net/mlx5/mlx5_flow.h
@@ -186,6 +186,10 @@ enum mlx5_feature_name {
 #define MLX5_FLOW_ITEM_INNER_FLEX (UINT64_C(1) << 38)
 #define MLX5_FLOW_ITEM_FLEX_TUNNEL (UINT64_C(1) << 39)
 
+/* Port Representor/Represented Port item */
+#define MLX5_FLOW_ITEM_PORT_REPRESENTOR (UINT64_C(1) << 40)
+#define MLX5_FLOW_ITEM_REPRESENTED_PORT (UINT64_C(1) << 41)
+
 /* Outer Masks. */
 #define MLX5_FLOW_LAYER_OUTER_L3 \
 	(MLX5_FLOW_LAYER_OUTER_L3_IPV4 | MLX5_FLOW_LAYER_OUTER_L3_IPV6)
diff --git a/drivers/net/mlx5/mlx5_flow_dv.c b/drivers/net/mlx5/mlx5_flow_dv.c
index 1e9bd63635..f20a64e8e4 100644
--- a/drivers/net/mlx5/mlx5_flow_dv.c
+++ b/drivers/net/mlx5/mlx5_flow_dv.c
@@ -2209,6 +2209,80 @@ flow_dv_validate_item_port_id(struct rte_eth_dev *dev,
 	return 0;
 }
 
+/**
+ * Validate represented port item.
+ *
+ * @param[in] dev
+ *   Pointer to the rte_eth_dev structure.
+ * @param[in] item
+ *   Item specification.
+ * @param[in] attr
+ *   Attributes of flow that includes this item.
+ * @param[in] item_flags
+ *   Bit-fields that holds the items detected until now.
+ * @param[out] error
+ *   Pointer to error structure.
+ *
+ * @return
+ *   0 on success, a negative errno value otherwise and rte_errno is set.
+ */
+static int
+flow_dv_validate_item_represented_port(struct rte_eth_dev *dev,
+				       const struct rte_flow_item *item,
+				       const struct rte_flow_attr *attr,
+				       uint64_t item_flags,
+				       struct rte_flow_error *error)
+{
+	const struct rte_flow_item_ethdev *spec = item->spec;
+	const struct rte_flow_item_ethdev *mask = item->mask;
+	const struct rte_flow_item_ethdev switch_mask = {
+			.port_id = UINT16_MAX,
+	};
+	struct mlx5_priv *esw_priv;
+	struct mlx5_priv *dev_priv;
+	int ret;
+
+	if (!attr->transfer)
+		return rte_flow_error_set(error, EINVAL,
+					  RTE_FLOW_ERROR_TYPE_ITEM, NULL,
+					  "match on port id is valid only when transfer flag is enabled");
+	if (item_flags & MLX5_FLOW_ITEM_REPRESENTED_PORT)
+		return rte_flow_error_set(error, ENOTSUP,
+					  RTE_FLOW_ERROR_TYPE_ITEM, item,
+					  "multiple source ports are not supported");
+	if (!mask)
+		mask = &switch_mask;
+	if (mask->port_id != UINT16_MAX)
+		return rte_flow_error_set(error, ENOTSUP,
+					   RTE_FLOW_ERROR_TYPE_ITEM_MASK, mask,
+					   "no support for partial mask on \"id\" field");
+	ret = mlx5_flow_item_acceptable
+				(item, (const uint8_t *)mask,
+				 (const uint8_t *)&rte_flow_item_ethdev_mask,
+				 sizeof(struct rte_flow_item_ethdev),
+				 MLX5_ITEM_RANGE_NOT_ACCEPTED, error);
+	if (ret)
+		return ret;
+	if (!spec || spec->port_id == UINT16_MAX)
+		return 0;
+	esw_priv = mlx5_port_to_eswitch_info(spec->port_id, false);
+	if (!esw_priv)
+		return rte_flow_error_set(error, rte_errno,
+					  RTE_FLOW_ERROR_TYPE_ITEM_SPEC, spec,
+					  "failed to obtain E-Switch info for port");
+	dev_priv = mlx5_dev_to_eswitch_info(dev);
+	if (!dev_priv)
+		return rte_flow_error_set(error, rte_errno,
+					  RTE_FLOW_ERROR_TYPE_UNSPECIFIED,
+					  NULL,
+					  "failed to obtain E-Switch info");
+	if (esw_priv->domain_id != dev_priv->domain_id)
+		return rte_flow_error_set(error, EINVAL,
+					  RTE_FLOW_ERROR_TYPE_ITEM_SPEC, spec,
+					  "cannot match on a port from a different E-Switch");
+	return 0;
+}
+
 /**
  * Validate VLAN item.
  *
@@ -6963,6 +7037,13 @@ flow_dv_validate(struct rte_eth_dev *dev, const struct rte_flow_attr *attr,
 			last_item = MLX5_FLOW_ITEM_PORT_ID;
 			port_id_item = items;
 			break;
+		case RTE_FLOW_ITEM_TYPE_REPRESENTED_PORT:
+			ret = flow_dv_validate_item_represented_port
+					(dev, items, attr, item_flags, error);
+			if (ret < 0)
+				return ret;
+			last_item = MLX5_FLOW_ITEM_REPRESENTED_PORT;
+			break;
 		case RTE_FLOW_ITEM_TYPE_ETH:
 			ret = mlx5_flow_validate_item_eth(items, item_flags,
 							  true, error);
@@ -9918,6 +9999,77 @@ flow_dv_translate_item_port_id(struct rte_eth_dev *dev, void *matcher,
 	return 0;
 }
 
+/**
+ * Translate represented port item to eswitch match on port id.
+ *
+ * @param[in] dev
+ *   The devich to configure through.
+ * @param[in, out] matcher
+ *   Flow matcher.
+ * @param[in, out] key
+ *   Flow matcher value.
+ * @param[in] item
+ *   Flow pattern to translate.
+ * @param[in]
+ *   Flow attributes.
+ *
+ * @return
+ *   0 on success, a negative errno value otherwise.
+ */
+static int
+flow_dv_translate_item_represented_port(struct rte_eth_dev *dev, void *matcher,
+					void *key,
+					const struct rte_flow_item *item,
+					const struct rte_flow_attr *attr)
+{
+	const struct rte_flow_item_ethdev *pid_m = item ? item->mask : NULL;
+	const struct rte_flow_item_ethdev *pid_v = item ? item->spec : NULL;
+	struct mlx5_priv *priv;
+	uint16_t mask, id;
+
+	if (!pid_m && !pid_v)
+		return 0;
+	if (pid_v && pid_v->port_id == UINT16_MAX) {
+		flow_dv_translate_item_source_vport(matcher, key,
+			flow_dv_get_esw_manager_vport_id(dev), UINT16_MAX);
+		return 0;
+	}
+	mask = pid_m ? pid_m->port_id : UINT16_MAX;
+	id = pid_v ? pid_v->port_id : dev->data->port_id;
+	priv = mlx5_port_to_eswitch_info(id, item == NULL);
+	if (!priv)
+		return -rte_errno;
+	/*
+	 * Translate to vport field or to metadata, depending on mode.
+	 * Kernel can use either misc.source_port or half of C0 metadata
+	 * register.
+	 */
+	if (priv->vport_meta_mask) {
+		/*
+		 * Provide the hint for SW steering library
+		 * to insert the flow into ingress domain and
+		 * save the extra vport match.
+		 */
+		if (mask == UINT16_MAX && priv->vport_id == UINT16_MAX &&
+		    priv->pf_bond < 0 && attr->transfer)
+			flow_dv_translate_item_source_vport
+				(matcher, key, priv->vport_id, mask);
+		/*
+		 * We should always set the vport metadata register,
+		 * otherwise the SW steering library can drop
+		 * the rule if wire vport metadata value is not zero,
+		 * it depends on kernel configuration.
+		 */
+		flow_dv_translate_item_meta_vport(matcher, key,
+						  priv->vport_meta_tag,
+						  priv->vport_meta_mask);
+	} else {
+		flow_dv_translate_item_source_vport(matcher, key,
+						    priv->vport_id, mask);
+	}
+	return 0;
+}
+
 /**
  * Add ICMP6 item to matcher and to the value.
  *
@@ -13543,6 +13695,11 @@ flow_dv_translate(struct rte_eth_dev *dev,
 				(dev, match_mask, match_value, items, attr);
 			last_item = MLX5_FLOW_ITEM_PORT_ID;
 			break;
+		case RTE_FLOW_ITEM_TYPE_REPRESENTED_PORT:
+			flow_dv_translate_item_represented_port
+				(dev, match_mask, match_value, items, attr);
+			last_item = MLX5_FLOW_ITEM_REPRESENTED_PORT;
+			break;
 		case RTE_FLOW_ITEM_TYPE_ETH:
 			flow_dv_translate_item_eth(match_mask, match_value,
 						   items, tunnel,
@@ -13801,7 +13958,8 @@ flow_dv_translate(struct rte_eth_dev *dev,
 	 * In both cases the source port is set according the current port
 	 * in use.
 	 */
-	if (!(item_flags & MLX5_FLOW_ITEM_PORT_ID) && priv->sh->esw_mode &&
+	if (!(item_flags & MLX5_FLOW_ITEM_PORT_ID) &&
+	    !(item_flags & MLX5_FLOW_ITEM_REPRESENTED_PORT) && priv->sh->esw_mode &&
 	    !(attr->egress && !attr->transfer)) {
 		if (flow_dv_translate_item_port_id(dev, match_mask,
 						   match_value, NULL, attr))
-- 
2.21.0


             reply	other threads:[~2022-04-02  6:40 UTC|newest]

Thread overview: 9+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2022-04-02  6:40 Sean Zhang [this message]
2022-06-06  7:21 ` Slava Ovsiienko
2022-06-07 11:17 ` [v2] " Sean Zhang
2022-06-14  7:44   ` Raslan Darawsheh
2022-06-07 11:18 ` [v2 0/3] Add support for modifying ECN in IPv4/IPv6 header Sean Zhang
2022-06-07 11:18   ` [v2 1/3] common/mlx5: add modify ECN capability check Sean Zhang
2022-06-07 11:18   ` [v2 2/3] net/mlx5: add support to modify ECN field Sean Zhang
2022-06-07 11:19   ` [v2 3/3] net/mlx5: add modify field support in meter Sean Zhang
2022-06-14  7:45   ` [v2 0/3] Add support for modifying ECN in IPv4/IPv6 header Raslan Darawsheh

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=20220402064000.8772-1-xiazhang@nvidia.com \
    --to=xiazhang@nvidia.com \
    --cc=dev@dpdk.org \
    --cc=matan@nvidia.com \
    --cc=viacheslavo@nvidia.com \
    /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;
as well as URLs for NNTP newsgroup(s).