[v3,09/12] net/enic: support meta flow actions to overrule destinations

Message ID 20211010143930.4985-10-ivan.malov@oktetlabs.ru (mailing list archive)
State Superseded, archived
Delegated to: Ferruh Yigit
Headers
Series ethdev: rework transfer flow API |

Checks

Context Check Description
ci/checkpatch success coding style OK

Commit Message

Ivan Malov Oct. 10, 2021, 2:39 p.m. UTC
  From: Andrew Rybchenko <andrew.rybchenko@oktetlabs.ru>

Add support for actions PORT_REPRESENTOR and REPRESENTED_PORT
based on the existing support for action PORT_ID.

Signed-off-by: Andrew Rybchenko <andrew.rybchenko@oktetlabs.ru>
---
 drivers/net/enic/enic_fm_flow.c | 93 ++++++++++++++++++++++++++-------
 1 file changed, 75 insertions(+), 18 deletions(-)
  

Comments

Hyong Youb Kim (hyonkim) Oct. 12, 2021, 5:03 p.m. UTC | #1
> -----Original Message-----
> From: Ivan Malov <ivan.malov@oktetlabs.ru>
> Sent: Sunday, October 10, 2021 11:39 PM
> To: dev@dpdk.org
> Cc: Thomas Monjalon <thomas@monjalon.net>; Ori Kam
> <orika@nvidia.com>; Andrew Rybchenko
> <andrew.rybchenko@oktetlabs.ru>; John Daley (johndale)
> <johndale@cisco.com>; Hyong Youb Kim (hyonkim) <hyonkim@cisco.com>
> Subject: [PATCH v3 09/12] net/enic: support meta flow actions to overrule
> destinations
> 
> From: Andrew Rybchenko <andrew.rybchenko@oktetlabs.ru>
> 
> Add support for actions PORT_REPRESENTOR and REPRESENTED_PORT
> based on the existing support for action PORT_ID.
> 
> Signed-off-by: Andrew Rybchenko <andrew.rybchenko@oktetlabs.ru>
> ---
>  drivers/net/enic/enic_fm_flow.c | 93 ++++++++++++++++++++++++++-----
> --
>  1 file changed, 75 insertions(+), 18 deletions(-)
> 

Looks good to me. Thanks a lot.

Acked-by: Hyong Youb Kim <hyonkim@cisco.com>

-Hyong

> diff --git a/drivers/net/enic/enic_fm_flow.c
> b/drivers/net/enic/enic_fm_flow.c
> index cd364ee16b..4092ff1f61 100644
> --- a/drivers/net/enic/enic_fm_flow.c
> +++ b/drivers/net/enic/enic_fm_flow.c
> @@ -1242,6 +1242,35 @@ vf_egress_port_id_action(struct enic_flowman
> *fm,
>  	return 0;
>  }
> 
> +static int
> +enic_fm_check_transfer_dst(struct enic *enic, uint16_t dst_port_id,
> +			   struct rte_eth_dev **dst_dev,
> +			   struct rte_flow_error *error)
> +{
> +	struct rte_eth_dev *dev;
> +
> +	ENICPMD_LOG(DEBUG, "port id %u", dst_port_id);
> +	if (!rte_eth_dev_is_valid_port(dst_port_id)) {
> +		return rte_flow_error_set(error, EINVAL,
> +			RTE_FLOW_ERROR_TYPE_ACTION,
> +			NULL, "invalid port_id");
> +	}
> +	dev = &rte_eth_devices[dst_port_id];
> +	if (!dev_is_enic(dev)) {
> +		return rte_flow_error_set(error, EINVAL,
> +			RTE_FLOW_ERROR_TYPE_ACTION,
> +			NULL, "port_id is not enic");
> +	}
> +	if (enic->switch_domain_id != pmd_priv(dev)->switch_domain_id) {
> +		return rte_flow_error_set(error, EINVAL,
> +			RTE_FLOW_ERROR_TYPE_ACTION,
> +			NULL, "destination and source ports are not in the
> same switch domain");
> +	}
> +
> +	*dst_dev = dev;
> +	return 0;
> +}
> +
>  /* Translate flow actions to flowman TCAM entry actions */
>  static int
>  enic_fm_copy_action(struct enic_flowman *fm,
> @@ -1446,24 +1475,10 @@ enic_fm_copy_action(struct enic_flowman *fm,
>  				vnic_h = enic->fm_vnic_handle; /* This port
> */
>  				break;
>  			}
> -			ENICPMD_LOG(DEBUG, "port id %u", port->id);
> -			if (!rte_eth_dev_is_valid_port(port->id)) {
> -				return rte_flow_error_set(error, EINVAL,
> -					RTE_FLOW_ERROR_TYPE_ACTION,
> -					NULL, "invalid port_id");
> -			}
> -			dev = &rte_eth_devices[port->id];
> -			if (!dev_is_enic(dev)) {
> -				return rte_flow_error_set(error, EINVAL,
> -					RTE_FLOW_ERROR_TYPE_ACTION,
> -					NULL, "port_id is not enic");
> -			}
> -			if (enic->switch_domain_id !=
> -			    pmd_priv(dev)->switch_domain_id) {
> -				return rte_flow_error_set(error, EINVAL,
> -					RTE_FLOW_ERROR_TYPE_ACTION,
> -					NULL, "destination and source ports
> are not in the same switch domain");
> -			}
> +			ret = enic_fm_check_transfer_dst(enic, port->id,
> &dev,
> +							 error);
> +			if (ret)
> +				return ret;
>  			vnic_h = pmd_priv(dev)->fm_vnic_handle;
>  			overlap |= PORT_ID;
>  			/*
> @@ -1560,6 +1575,48 @@ enic_fm_copy_action(struct enic_flowman *fm,
>  			ovlan |= rte_be_to_cpu_16(vid->vlan_vid);
>  			break;
>  		}
> +		case RTE_FLOW_ACTION_TYPE_PORT_REPRESENTOR: {
> +			const struct rte_flow_action_ethdev *ethdev;
> +			struct rte_eth_dev *dev;
> +
> +			ethdev = actions->conf;
> +			ret = enic_fm_check_transfer_dst(enic, ethdev-
> >port_id,
> +							 &dev, error);
> +			if (ret)
> +				return ret;
> +			vnic_h = pmd_priv(dev)->fm_vnic_handle;
> +			overlap |= PORT_ID;
> +			/*
> +			 * Action PORT_REPRESENTOR implies ingress
> destination.
> +			 * Noting to do. We add an implicit stree at the
> +			 * end if needed.
> +			 */
> +			ingress = 1;
> +			break;
> +		}
> +		case RTE_FLOW_ACTION_TYPE_REPRESENTED_PORT: {
> +			const struct rte_flow_action_ethdev *ethdev;
> +			struct rte_eth_dev *dev;
> +
> +			if (overlap & PORT_ID) {
> +				ENICPMD_LOG(DEBUG, "cannot have
> multiple egress PORT_ID actions");
> +				goto unsupported;
> +			}
> +			ethdev = actions->conf;
> +			ret = enic_fm_check_transfer_dst(enic, ethdev-
> >port_id,
> +							 &dev, error);
> +			if (ret)
> +				return ret;
> +			vnic_h = pmd_priv(dev)->fm_vnic_handle;
> +			overlap |= PORT_ID;
> +			/* Action REPRESENTED_PORT: always egress
> destination */
> +			ingress = 0;
> +			ret = vf_egress_port_id_action(fm, dev, vnic_h,
> &fm_op,
> +				error);
> +			if (ret)
> +				return ret;
> +			break;
> +		}
>  		default:
>  			goto unsupported;
>  		}
> --
> 2.20.1
  

Patch

diff --git a/drivers/net/enic/enic_fm_flow.c b/drivers/net/enic/enic_fm_flow.c
index cd364ee16b..4092ff1f61 100644
--- a/drivers/net/enic/enic_fm_flow.c
+++ b/drivers/net/enic/enic_fm_flow.c
@@ -1242,6 +1242,35 @@  vf_egress_port_id_action(struct enic_flowman *fm,
 	return 0;
 }
 
+static int
+enic_fm_check_transfer_dst(struct enic *enic, uint16_t dst_port_id,
+			   struct rte_eth_dev **dst_dev,
+			   struct rte_flow_error *error)
+{
+	struct rte_eth_dev *dev;
+
+	ENICPMD_LOG(DEBUG, "port id %u", dst_port_id);
+	if (!rte_eth_dev_is_valid_port(dst_port_id)) {
+		return rte_flow_error_set(error, EINVAL,
+			RTE_FLOW_ERROR_TYPE_ACTION,
+			NULL, "invalid port_id");
+	}
+	dev = &rte_eth_devices[dst_port_id];
+	if (!dev_is_enic(dev)) {
+		return rte_flow_error_set(error, EINVAL,
+			RTE_FLOW_ERROR_TYPE_ACTION,
+			NULL, "port_id is not enic");
+	}
+	if (enic->switch_domain_id != pmd_priv(dev)->switch_domain_id) {
+		return rte_flow_error_set(error, EINVAL,
+			RTE_FLOW_ERROR_TYPE_ACTION,
+			NULL, "destination and source ports are not in the same switch domain");
+	}
+
+	*dst_dev = dev;
+	return 0;
+}
+
 /* Translate flow actions to flowman TCAM entry actions */
 static int
 enic_fm_copy_action(struct enic_flowman *fm,
@@ -1446,24 +1475,10 @@  enic_fm_copy_action(struct enic_flowman *fm,
 				vnic_h = enic->fm_vnic_handle; /* This port */
 				break;
 			}
-			ENICPMD_LOG(DEBUG, "port id %u", port->id);
-			if (!rte_eth_dev_is_valid_port(port->id)) {
-				return rte_flow_error_set(error, EINVAL,
-					RTE_FLOW_ERROR_TYPE_ACTION,
-					NULL, "invalid port_id");
-			}
-			dev = &rte_eth_devices[port->id];
-			if (!dev_is_enic(dev)) {
-				return rte_flow_error_set(error, EINVAL,
-					RTE_FLOW_ERROR_TYPE_ACTION,
-					NULL, "port_id is not enic");
-			}
-			if (enic->switch_domain_id !=
-			    pmd_priv(dev)->switch_domain_id) {
-				return rte_flow_error_set(error, EINVAL,
-					RTE_FLOW_ERROR_TYPE_ACTION,
-					NULL, "destination and source ports are not in the same switch domain");
-			}
+			ret = enic_fm_check_transfer_dst(enic, port->id, &dev,
+							 error);
+			if (ret)
+				return ret;
 			vnic_h = pmd_priv(dev)->fm_vnic_handle;
 			overlap |= PORT_ID;
 			/*
@@ -1560,6 +1575,48 @@  enic_fm_copy_action(struct enic_flowman *fm,
 			ovlan |= rte_be_to_cpu_16(vid->vlan_vid);
 			break;
 		}
+		case RTE_FLOW_ACTION_TYPE_PORT_REPRESENTOR: {
+			const struct rte_flow_action_ethdev *ethdev;
+			struct rte_eth_dev *dev;
+
+			ethdev = actions->conf;
+			ret = enic_fm_check_transfer_dst(enic, ethdev->port_id,
+							 &dev, error);
+			if (ret)
+				return ret;
+			vnic_h = pmd_priv(dev)->fm_vnic_handle;
+			overlap |= PORT_ID;
+			/*
+			 * Action PORT_REPRESENTOR implies ingress destination.
+			 * Noting to do. We add an implicit stree at the
+			 * end if needed.
+			 */
+			ingress = 1;
+			break;
+		}
+		case RTE_FLOW_ACTION_TYPE_REPRESENTED_PORT: {
+			const struct rte_flow_action_ethdev *ethdev;
+			struct rte_eth_dev *dev;
+
+			if (overlap & PORT_ID) {
+				ENICPMD_LOG(DEBUG, "cannot have multiple egress PORT_ID actions");
+				goto unsupported;
+			}
+			ethdev = actions->conf;
+			ret = enic_fm_check_transfer_dst(enic, ethdev->port_id,
+							 &dev, error);
+			if (ret)
+				return ret;
+			vnic_h = pmd_priv(dev)->fm_vnic_handle;
+			overlap |= PORT_ID;
+			/* Action REPRESENTED_PORT: always egress destination */
+			ingress = 0;
+			ret = vf_egress_port_id_action(fm, dev, vnic_h, &fm_op,
+				error);
+			if (ret)
+				return ret;
+			break;
+		}
 		default:
 			goto unsupported;
 		}