]> git.droids-corp.org - dpdk.git/commitdiff
net/mlx5: support represented port item in flow rules
authorSean Zhang <xiazhang@nvidia.com>
Tue, 7 Jun 2022 11:17:32 +0000 (14:17 +0300)
committerRaslan Darawsheh <rasland@nvidia.com>
Thu, 23 Jun 2022 15:23:23 +0000 (17:23 +0200)
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>
Acked-by: Viacheslav Ovsiienko <viacheslavo@nvidia.com>
doc/guides/nics/features/mlx5.ini
doc/guides/nics/mlx5.rst
doc/guides/rel_notes/release_22_07.rst
drivers/net/mlx5/mlx5_flow.h
drivers/net/mlx5/mlx5_flow_dv.c

index 5738f35324c5f757df31ebcbbfa6e1e697cd8b5b..e056516deb87ad89eade7086968dd325de2bec1d 100644 (file)
@@ -84,6 +84,7 @@ udp                  = Y
 vlan                 = Y
 vxlan                = Y
 vxlan_gpe            = Y
+represented_port     = Y
 
 [rte_flow actions]
 age                  = I
index d83c56de115f6720b1dfb3d52ee80dec59229845..1e13a9327f074970c40dbcb99bc30b8c6a4b21a6 100644 (file)
@@ -93,6 +93,7 @@ Features
 - Connection tracking.
 - Sub-Function representors.
 - Sub-Function.
+- Matching on represented port.
 
 
 Limitations
index 54fdf7a6719103626b82006f39e748642ab5880a..2162439786b844fcd41ec3563ddedaecf3f38a07 100644 (file)
@@ -168,6 +168,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 Netronome nfp driver.**
 
index eb13365c61077f374de8a0267a00f933415fd7b7..85e55eb5d08531713b136bf3a16c3c4caaeb4745 100644 (file)
@@ -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)
index a575e3182e732513933ebfbc1738ca7fe9677390..ee0a4bdcfcb0b9cca39bb25d6d45d0f090569b0d 100644 (file)
@@ -2210,6 +2210,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.
  *
@@ -6972,6 +7046,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);
@@ -9979,6 +10060,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.
  *
@@ -13615,6 +13767,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,
@@ -13873,7 +14030,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))