Matching source vport without having vport metadata available
requires matching on 2 fields:

- source_gvmi - equal to VHCA ID property of the port,
- functional_lb

There are following cases:

- If packet comes from PF/VF/SF, then it originated on some Tx queue on
  the host. In this case, source_gvmi will be populated with
  the ID of the originating function.
- If packet comes from the wire, then source_gvmi will be set to 0.

There is one edge case - discriminating packets coming from PF0 and
from wire. In this case, both packets will have source_gvmi set to 0.
Distinguishing them requires additional match on functional_lb.
If packet comes from PF, functional_lb will be set to 1.
This only happens when packet was sent from PF to FDB, and
then moved to PF again.

Because of all of the above:

- Unified FDB must be disabled when vport metadata is disabled,
  because packet from PF0 and from wire will not have
  correct functional_lb set yet when flow rules in FDB are processed.
- Without unified FDB, when separate FDB_RX and FDB_TX tables are used
  internally, match on functional_lb is not needed.
  Table type already defines the direction.
- NIC_TX tables belong to a single GVMI and as a result
  vport matching is not needed there.

As a result, functional_lb match is only required on NIC_RX.

This patch adds support for source_gvmi and functional_lb matching
in HWS layer.

Signed-off-by: Dariusz Sosnowski <[email protected]>
---
 drivers/net/mlx5/hws/mlx5dr_definer.c | 65 +++++++++++++++++++++++++--
 drivers/net/mlx5/hws/mlx5dr_definer.h |  2 +
 drivers/net/mlx5/hws/mlx5dr_table.c   |  6 +++
 3 files changed, 69 insertions(+), 4 deletions(-)

diff --git a/drivers/net/mlx5/hws/mlx5dr_definer.c 
b/drivers/net/mlx5/hws/mlx5dr_definer.c
index 3ba69c1001..7400b8f252 100644
--- a/drivers/net/mlx5/hws/mlx5dr_definer.c
+++ b/drivers/net/mlx5/hws/mlx5dr_definer.c
@@ -6,6 +6,8 @@
 
 #include "mlx5dr_internal.h"
 
+#define WIRE_GVMI      0
+#define BAD_GVMI       0xFFFF
 #define GTP_PDU_SC     0x85
 #define BAD_PORT       0xBAD
 #define BAD_SQN                0xBAD
@@ -789,6 +791,49 @@ mlx5dr_definer_vport_set(struct mlx5dr_definer_fc *fc,
        DR_SET(tag, regc_value, fc->byte_off, fc->bit_off, fc->bit_mask);
 }
 
+static void
+mlx5dr_definer_source_gvmi_set(struct mlx5dr_definer_fc *fc,
+                              const void *item_spec,
+                              uint8_t *tag)
+{
+       const struct rte_flow_item_ethdev *v = item_spec;
+       const struct flow_hw_port_info *port_info;
+       uint32_t source_gvmi;
+
+       if (v) {
+               port_info = flow_hw_conv_port_id(fc->dr_ctx, v->port_id);
+               assert(port_info != NULL);
+               if (port_info->is_wire)
+                       source_gvmi = WIRE_GVMI;
+               else
+                       source_gvmi = port_info->vhca_id;
+       } else {
+               source_gvmi = BAD_GVMI;
+       }
+
+       DR_SET(tag, source_gvmi, fc->byte_off, fc->bit_off, fc->bit_mask);
+}
+
+static void
+mlx5dr_definer_functional_lb_set(struct mlx5dr_definer_fc *fc,
+                                const void *item_spec,
+                                uint8_t *tag)
+{
+       const struct rte_flow_item_ethdev *v = item_spec;
+       const struct flow_hw_port_info *port_info;
+       uint32_t functional_lb;
+
+       if (v) {
+               port_info = flow_hw_conv_port_id(fc->dr_ctx, v->port_id);
+               assert(port_info != NULL);
+               functional_lb = !port_info->is_wire;
+       } else {
+               functional_lb = 0;
+       }
+
+       DR_SET(tag, functional_lb, fc->byte_off, fc->bit_off, fc->bit_mask);
+}
+
 static struct mlx5dr_definer_fc *
 mlx5dr_definer_get_mpls_fc(struct mlx5dr_definer_conv_data *cd, bool inner)
 {
@@ -1610,10 +1655,22 @@ mlx5dr_definer_conv_item_port(struct 
mlx5dr_definer_conv_data *cd,
                        fc->bit_mask = caps->wire_regc_mask >> fc->bit_off;
                        fc->dr_ctx = cd->ctx;
                } else {
-                       /* TODO */
-                       DR_LOG(ERR, "Port ID item with legacy vport match is 
not implemented");
-                       rte_errno = ENOTSUP;
-                       return rte_errno;
+                       fc = &cd->fc[MLX5DR_DEFINER_FNAME_SOURCE_GVMI];
+                       fc->item_idx = item_idx;
+                       fc->tag_set = &mlx5dr_definer_source_gvmi_set;
+                       fc->tag_mask_set = &mlx5dr_definer_ones_set;
+                       DR_CALC_SET_HDR(fc, source_qp_gvmi, source_gvmi);
+                       fc->dr_ctx = cd->ctx;
+
+                       if (cd->table_type != MLX5DR_TABLE_TYPE_NIC_RX)
+                               return 0;
+
+                       fc = &cd->fc[MLX5DR_DEFINER_FNAME_FUNCTIONAL_LB];
+                       fc->item_idx = item_idx;
+                       fc->tag_set = &mlx5dr_definer_functional_lb_set;
+                       fc->tag_mask_set = &mlx5dr_definer_ones_set;
+                       DR_CALC_SET_HDR(fc, source_qp_gvmi, functional_lb);
+                       fc->dr_ctx = cd->ctx;
                }
        }
 
diff --git a/drivers/net/mlx5/hws/mlx5dr_definer.h 
b/drivers/net/mlx5/hws/mlx5dr_definer.h
index d0c99399ae..f5d6cce887 100644
--- a/drivers/net/mlx5/hws/mlx5dr_definer.h
+++ b/drivers/net/mlx5/hws/mlx5dr_definer.h
@@ -214,6 +214,8 @@ enum mlx5dr_definer_fname {
        MLX5DR_DEFINER_FNAME_PTYPE_FRAG_O,
        MLX5DR_DEFINER_FNAME_PTYPE_FRAG_I,
        MLX5DR_DEFINER_FNAME_RANDOM_NUM,
+       MLX5DR_DEFINER_FNAME_SOURCE_GVMI,
+       MLX5DR_DEFINER_FNAME_FUNCTIONAL_LB,
        MLX5DR_DEFINER_FNAME_MAX,
 };
 
diff --git a/drivers/net/mlx5/hws/mlx5dr_table.c 
b/drivers/net/mlx5/hws/mlx5dr_table.c
index 41ffaa19e3..14e983a363 100644
--- a/drivers/net/mlx5/hws/mlx5dr_table.c
+++ b/drivers/net/mlx5/hws/mlx5dr_table.c
@@ -468,6 +468,12 @@ struct mlx5dr_table *mlx5dr_table_create(struct 
mlx5dr_context *ctx,
                return NULL;
        }
 
+       if (attr->type == MLX5DR_TABLE_TYPE_FDB_UNIFIED && 
!ctx->caps->vport_metadata_match) {
+               DR_LOG(ERR, "Table type %d requires vport metadata to be 
enabled", attr->type);
+               rte_errno = ENOTSUP;
+               return NULL;
+       }
+
        if ((mlx5dr_table_is_fdb_any(attr->type) && attr->type != 
MLX5DR_TABLE_TYPE_FDB) &&
            !attr->level) {
                DR_LOG(ERR, "Table type %d not supported by root table", 
attr->type);
-- 
2.47.3

Reply via email to