[v3,09/12] net/enic: support meta flow actions to overrule destinations
Checks
Commit Message
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
> -----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
@@ -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;
}