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 <xiazh...@nvidia.com> Acked-by: Viacheslav Ovsiienko <viachesl...@nvidia.com> --- v2 -- add missing doc --- doc/guides/nics/features/mlx5.ini | 1 + doc/guides/nics/mlx5.rst | 1 + doc/guides/rel_notes/release_22_07.rst | 1 + drivers/net/mlx5/mlx5_flow.h | 4 + drivers/net/mlx5/mlx5_flow_dv.c | 160 ++++++++++++++++++++++++++++++++- 5 files changed, 166 insertions(+), 1 deletion(-) diff --git a/doc/guides/nics/features/mlx5.ini b/doc/guides/nics/features/mlx5.ini index 5738f35..e056516 100644 --- a/doc/guides/nics/features/mlx5.ini +++ b/doc/guides/nics/features/mlx5.ini @@ -84,6 +84,7 @@ udp = Y vlan = Y vxlan = Y vxlan_gpe = Y +represented_port = Y [rte_flow actions] age = I diff --git a/doc/guides/nics/mlx5.rst b/doc/guides/nics/mlx5.rst index d83c56d..1e13a93 100644 --- a/doc/guides/nics/mlx5.rst +++ b/doc/guides/nics/mlx5.rst @@ -93,6 +93,7 @@ Features - Connection tracking. - Sub-Function representors. - Sub-Function. +- Matching on represented port. Limitations diff --git a/doc/guides/rel_notes/release_22_07.rst b/doc/guides/rel_notes/release_22_07.rst index d46f773..28f25b1 100644 --- a/doc/guides/rel_notes/release_22_07.rst +++ b/doc/guides/rel_notes/release_22_07.rst @@ -116,6 +116,7 @@ New Features * Added support for promiscuous mode on Windows. * Added support for MTU on Windows. * Added matching and RSS on IPsec ESP. + * Added matching on represented port. * **Updated VMware vmxnet3 networking driver.** diff --git a/drivers/net/mlx5/mlx5_flow.h b/drivers/net/mlx5/mlx5_flow.h index eb13365..85e55eb 100644 --- a/drivers/net/mlx5/mlx5_flow.h +++ b/drivers/net/mlx5/mlx5_flow.h @@ -189,6 +189,10 @@ enum mlx5_feature_name { /* ESP item */ #define MLX5_FLOW_ITEM_ESP (UINT64_C(1) << 40) +/* Port Representor/Represented Port item */ +#define MLX5_FLOW_ITEM_PORT_REPRESENTOR (UINT64_C(1) << 41) +#define MLX5_FLOW_ITEM_REPRESENTED_PORT (UINT64_C(1) << 42) + /* 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 a575e31..ee0a4bd 100644 --- a/drivers/net/mlx5/mlx5_flow_dv.c +++ b/drivers/net/mlx5/mlx5_flow_dv.c @@ -2211,6 +2211,80 @@ struct field_modify_info modify_tcp[] = { } /** + * 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. * * @param[in] item @@ -6972,6 +7046,13 @@ struct mlx5_list_entry * 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); @@ -9980,6 +10061,77 @@ struct mlx5_list_entry * } /** + * 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. * * @param[in, out] matcher @@ -13615,6 +13767,11 @@ struct mlx5_list_entry * (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, @@ -13873,7 +14030,8 @@ struct mlx5_list_entry * * 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)) -- 1.8.3.1