IB/mlx5: Add support for don't trap rules
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>
This commit is contained in:
parent
b3638e1a76
commit
35d1901134
|
@ -1369,11 +1369,20 @@ static int mlx5_ib_destroy_flow(struct ib_flow *flow_id)
|
||||||
return 0;
|
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_TYPES 10
|
||||||
#define MLX5_FS_MAX_ENTRIES 32000UL
|
#define MLX5_FS_MAX_ENTRIES 32000UL
|
||||||
static struct mlx5_ib_flow_prio *get_flow_table(struct mlx5_ib_dev *dev,
|
static struct mlx5_ib_flow_prio *get_flow_table(struct mlx5_ib_dev *dev,
|
||||||
struct ib_flow_attr *flow_attr)
|
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_flow_namespace *ns = NULL;
|
||||||
struct mlx5_ib_flow_prio *prio;
|
struct mlx5_ib_flow_prio *prio;
|
||||||
struct mlx5_flow_table *ft;
|
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;
|
int err = 0;
|
||||||
|
|
||||||
if (flow_attr->type == IB_FLOW_ATTR_NORMAL) {
|
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;
|
priority = MLX5_IB_FLOW_MCAST_PRIO;
|
||||||
else
|
else
|
||||||
priority = flow_attr->priority;
|
priority = ib_prio_to_core_prio(flow_attr->priority,
|
||||||
|
dont_trap);
|
||||||
ns = mlx5_get_flow_namespace(dev->mdev,
|
ns = mlx5_get_flow_namespace(dev->mdev,
|
||||||
MLX5_FLOW_NAMESPACE_BYPASS);
|
MLX5_FLOW_NAMESPACE_BYPASS);
|
||||||
num_entries = MLX5_FS_MAX_ENTRIES;
|
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;
|
unsigned int spec_index;
|
||||||
u32 *match_c;
|
u32 *match_c;
|
||||||
u32 *match_v;
|
u32 *match_v;
|
||||||
|
u32 action;
|
||||||
int err = 0;
|
int err = 0;
|
||||||
|
|
||||||
if (!is_valid_attr(flow_attr))
|
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 */
|
/* Outer header support only */
|
||||||
match_criteria_enable = (!outer_header_zero(match_c)) << 0;
|
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,
|
handler->rule = mlx5_add_flow_rule(ft, match_criteria_enable,
|
||||||
match_c, match_v,
|
match_c, match_v,
|
||||||
MLX5_FLOW_CONTEXT_ACTION_FWD_DEST,
|
action,
|
||||||
MLX5_FS_DEFAULT_FLOW_TAG,
|
MLX5_FS_DEFAULT_FLOW_TAG,
|
||||||
dst);
|
dst);
|
||||||
|
|
||||||
|
@ -1481,6 +1495,29 @@ free:
|
||||||
return err ? ERR_PTR(err) : handler;
|
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 {
|
enum {
|
||||||
LEFTOVERS_MC,
|
LEFTOVERS_MC,
|
||||||
LEFTOVERS_UC,
|
LEFTOVERS_UC,
|
||||||
|
@ -1558,7 +1595,7 @@ static struct ib_flow *mlx5_ib_create_flow(struct ib_qp *qp,
|
||||||
|
|
||||||
if (domain != IB_FLOW_DOMAIN_USER ||
|
if (domain != IB_FLOW_DOMAIN_USER ||
|
||||||
flow_attr->port > MLX5_CAP_GEN(dev->mdev, num_ports) ||
|
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);
|
return ERR_PTR(-EINVAL);
|
||||||
|
|
||||||
dst = kzalloc(sizeof(*dst), GFP_KERNEL);
|
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;
|
dst->tir_num = to_mqp(qp)->raw_packet_qp.rq.tirn;
|
||||||
|
|
||||||
if (flow_attr->type == IB_FLOW_ATTR_NORMAL) {
|
if (flow_attr->type == IB_FLOW_ATTR_NORMAL) {
|
||||||
handler = create_flow_rule(dev, ft_prio, flow_attr,
|
if (flow_attr->flags & IB_FLOW_ATTR_FLAGS_DONT_TRAP) {
|
||||||
dst);
|
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 ||
|
} else if (flow_attr->type == IB_FLOW_ATTR_ALL_DEFAULT ||
|
||||||
flow_attr->type == IB_FLOW_ATTR_MC_DEFAULT) {
|
flow_attr->type == IB_FLOW_ATTR_MC_DEFAULT) {
|
||||||
handler = create_leftovers_rule(dev, ft_prio, flow_attr,
|
handler = create_leftovers_rule(dev, ft_prio, flow_attr,
|
||||||
|
|
|
@ -126,7 +126,7 @@ struct mlx5_ib_pd {
|
||||||
};
|
};
|
||||||
|
|
||||||
#define MLX5_IB_FLOW_MCAST_PRIO (MLX5_BY_PASS_NUM_PRIOS - 1)
|
#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)
|
#if (MLX5_IB_FLOW_LAST_PRIO <= 0)
|
||||||
#error "Invalid number of bypass priorities"
|
#error "Invalid number of bypass priorities"
|
||||||
#endif
|
#endif
|
||||||
|
|
|
@ -1294,6 +1294,11 @@ static inline u16 mlx5_to_sw_pkey_sz(int pkey_sz)
|
||||||
return MLX5_MIN_PKEY_TABLE_SIZE << 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 */
|
#endif /* MLX5_DEVICE_H */
|
||||||
|
|
Loading…
Reference in New Issue