IB/mlx5: Add support for don't trap rules
authorMaor Gottlieb <maorg@mellanox.com>
Mon, 7 Mar 2016 16:51:47 +0000 (18:51 +0200)
committerDoug Ledford <dledford@redhat.com>
Thu, 10 Mar 2016 14:22:06 +0000 (09:22 -0500)
Each bypass flow steering priority will be split into two priorities:
1. Priority for don't trap rules.
2. Priority for normal rules.

When user creates a flow using IB_FLOW_ATTR_FLAGS_DONT_TRAP flag, the
driver creates two flow rules, one used for receiving the traffic and
the other one for forwarding the packet to continue matching in lower
or equal priorities.

Signed-off-by: Maor Gottlieb <maorg@mellanox.com>
Reviewed-by: Matan Barak <matanb@mellanox.com>
Signed-off-by: Doug Ledford <dledford@redhat.com>
drivers/infiniband/hw/mlx5/main.c
drivers/infiniband/hw/mlx5/mlx5_ib.h
include/linux/mlx5/device.h

index 03c418ccbc982e4114681044798c075a65357b28..5863644f0872ed68b83056252a65ba382f87f9b2 100644 (file)
@@ -1369,11 +1369,20 @@ static int mlx5_ib_destroy_flow(struct ib_flow *flow_id)
        return 0;
 }
 
+static int ib_prio_to_core_prio(unsigned int priority, bool dont_trap)
+{
+       priority *= 2;
+       if (!dont_trap)
+               priority++;
+       return priority;
+}
+
 #define MLX5_FS_MAX_TYPES       10
 #define MLX5_FS_MAX_ENTRIES     32000UL
 static struct mlx5_ib_flow_prio *get_flow_table(struct mlx5_ib_dev *dev,
                                                struct ib_flow_attr *flow_attr)
 {
+       bool dont_trap = flow_attr->flags & IB_FLOW_ATTR_FLAGS_DONT_TRAP;
        struct mlx5_flow_namespace *ns = NULL;
        struct mlx5_ib_flow_prio *prio;
        struct mlx5_flow_table *ft;
@@ -1383,10 +1392,12 @@ static struct mlx5_ib_flow_prio *get_flow_table(struct mlx5_ib_dev *dev,
        int err = 0;
 
        if (flow_attr->type == IB_FLOW_ATTR_NORMAL) {
-               if (flow_is_multicast_only(flow_attr))
+               if (flow_is_multicast_only(flow_attr) &&
+                   !dont_trap)
                        priority = MLX5_IB_FLOW_MCAST_PRIO;
                else
-                       priority = flow_attr->priority;
+                       priority = ib_prio_to_core_prio(flow_attr->priority,
+                                                       dont_trap);
                ns = mlx5_get_flow_namespace(dev->mdev,
                                             MLX5_FLOW_NAMESPACE_BYPASS);
                num_entries = MLX5_FS_MAX_ENTRIES;
@@ -1434,6 +1445,7 @@ static struct mlx5_ib_flow_handler *create_flow_rule(struct mlx5_ib_dev *dev,
        unsigned int spec_index;
        u32 *match_c;
        u32 *match_v;
+       u32 action;
        int err = 0;
 
        if (!is_valid_attr(flow_attr))
@@ -1459,9 +1471,11 @@ static struct mlx5_ib_flow_handler *create_flow_rule(struct mlx5_ib_dev *dev,
 
        /* Outer header support only */
        match_criteria_enable = (!outer_header_zero(match_c)) << 0;
+       action = dst ? MLX5_FLOW_CONTEXT_ACTION_FWD_DEST :
+               MLX5_FLOW_CONTEXT_ACTION_FWD_NEXT_PRIO;
        handler->rule = mlx5_add_flow_rule(ft, match_criteria_enable,
                                           match_c, match_v,
-                                          MLX5_FLOW_CONTEXT_ACTION_FWD_DEST,
+                                          action,
                                           MLX5_FS_DEFAULT_FLOW_TAG,
                                           dst);
 
@@ -1481,6 +1495,29 @@ free:
        return err ? ERR_PTR(err) : handler;
 }
 
+static struct mlx5_ib_flow_handler *create_dont_trap_rule(struct mlx5_ib_dev *dev,
+                                                         struct mlx5_ib_flow_prio *ft_prio,
+                                                         struct ib_flow_attr *flow_attr,
+                                                         struct mlx5_flow_destination *dst)
+{
+       struct mlx5_ib_flow_handler *handler_dst = NULL;
+       struct mlx5_ib_flow_handler *handler = NULL;
+
+       handler = create_flow_rule(dev, ft_prio, flow_attr, NULL);
+       if (!IS_ERR(handler)) {
+               handler_dst = create_flow_rule(dev, ft_prio,
+                                              flow_attr, dst);
+               if (IS_ERR(handler_dst)) {
+                       mlx5_del_flow_rule(handler->rule);
+                       kfree(handler);
+                       handler = handler_dst;
+               } else {
+                       list_add(&handler_dst->list, &handler->list);
+               }
+       }
+
+       return handler;
+}
 enum {
        LEFTOVERS_MC,
        LEFTOVERS_UC,
@@ -1558,7 +1595,7 @@ static struct ib_flow *mlx5_ib_create_flow(struct ib_qp *qp,
 
        if (domain != IB_FLOW_DOMAIN_USER ||
            flow_attr->port > MLX5_CAP_GEN(dev->mdev, num_ports) ||
-           flow_attr->flags)
+           (flow_attr->flags & ~IB_FLOW_ATTR_FLAGS_DONT_TRAP))
                return ERR_PTR(-EINVAL);
 
        dst = kzalloc(sizeof(*dst), GFP_KERNEL);
@@ -1577,8 +1614,13 @@ static struct ib_flow *mlx5_ib_create_flow(struct ib_qp *qp,
        dst->tir_num = to_mqp(qp)->raw_packet_qp.rq.tirn;
 
        if (flow_attr->type == IB_FLOW_ATTR_NORMAL) {
-               handler = create_flow_rule(dev, ft_prio, flow_attr,
-                                          dst);
+               if (flow_attr->flags & IB_FLOW_ATTR_FLAGS_DONT_TRAP)  {
+                       handler = create_dont_trap_rule(dev, ft_prio,
+                                                       flow_attr, dst);
+               } else {
+                       handler = create_flow_rule(dev, ft_prio, flow_attr,
+                                                  dst);
+               }
        } else if (flow_attr->type == IB_FLOW_ATTR_ALL_DEFAULT ||
                   flow_attr->type == IB_FLOW_ATTR_MC_DEFAULT) {
                handler = create_leftovers_rule(dev, ft_prio, flow_attr,
index d2b9737baa3675b1dc9ced794767f1790ada35ee..bd84b1fbb7875920db88e9cf43855c8e63b11bd3 100644 (file)
@@ -126,7 +126,7 @@ struct mlx5_ib_pd {
 };
 
 #define MLX5_IB_FLOW_MCAST_PRIO                (MLX5_BY_PASS_NUM_PRIOS - 1)
-#define MLX5_IB_FLOW_LAST_PRIO         (MLX5_IB_FLOW_MCAST_PRIO - 1)
+#define MLX5_IB_FLOW_LAST_PRIO         (MLX5_BY_PASS_NUM_REGULAR_PRIOS - 1)
 #if (MLX5_IB_FLOW_LAST_PRIO <= 0)
 #error "Invalid number of bypass priorities"
 #endif
index 987764afa65c2344d5a85328f9f35a419e21db64..2bf222e65e6b433d19d6c1225448df8316d93b23 100644 (file)
@@ -1294,6 +1294,11 @@ static inline u16 mlx5_to_sw_pkey_sz(int pkey_sz)
        return MLX5_MIN_PKEY_TABLE_SIZE << pkey_sz;
 }
 
-#define MLX5_BY_PASS_NUM_PRIOS 9
+#define MLX5_BY_PASS_NUM_REGULAR_PRIOS 8
+#define MLX5_BY_PASS_NUM_DONT_TRAP_PRIOS 8
+#define MLX5_BY_PASS_NUM_MULTICAST_PRIOS 1
+#define MLX5_BY_PASS_NUM_PRIOS (MLX5_BY_PASS_NUM_REGULAR_PRIOS +\
+                               MLX5_BY_PASS_NUM_DONT_TRAP_PRIOS +\
+                               MLX5_BY_PASS_NUM_MULTICAST_PRIOS)
 
 #endif /* MLX5_DEVICE_H */