diff --git a/drivers/infiniband/hw/mlx5/main.c b/drivers/infiniband/hw/mlx5/main.c index c28b6952b0abf625d0b73409d590276b7209c99f..cca3848a2671666f56ed1d1be951b2cc2fdccfad 100644 --- a/drivers/infiniband/hw/mlx5/main.c +++ b/drivers/infiniband/hw/mlx5/main.c @@ -1727,6 +1727,7 @@ static void set_tos(void *outer_c, void *outer_v, u8 mask, u8 val) #define LAST_TCP_UDP_FIELD src_port #define LAST_TUNNEL_FIELD tunnel_id #define LAST_FLOW_TAG_FIELD tag_id +#define LAST_DROP_FIELD size /* Field is the last supported field */ #define FIELDS_NOT_SUPPORTED(filter, field)\ @@ -1740,7 +1741,7 @@ static void set_tos(void *outer_c, void *outer_v, u8 mask, u8 val) #define IPV6_VERSION 6 static int parse_flow_attr(struct mlx5_core_dev *mdev, u32 *match_c, u32 *match_v, const union ib_flow_spec *ib_spec, - u32 *tag_id) + u32 *tag_id, bool *is_drop) { void *misc_params_c = MLX5_ADDR_OF(fte_match_param, match_c, misc_parameters); @@ -1960,6 +1961,12 @@ static int parse_flow_attr(struct mlx5_core_dev *mdev, u32 *match_c, *tag_id = ib_spec->flow_tag.tag_id; break; + case IB_FLOW_SPEC_ACTION_DROP: + if (FIELDS_NOT_SUPPORTED(ib_spec->drop, + LAST_DROP_FIELD)) + return -EOPNOTSUPP; + *is_drop = true; + break; default: return -EINVAL; } @@ -2181,10 +2188,13 @@ static struct mlx5_ib_flow_handler *create_flow_rule(struct mlx5_ib_dev *dev, struct mlx5_ib_flow_handler *handler; struct mlx5_flow_act flow_act = {0}; struct mlx5_flow_spec *spec; + struct mlx5_flow_destination *rule_dst = dst; const void *ib_flow = (const void *)flow_attr + sizeof(*flow_attr); unsigned int spec_index; u32 flow_tag = MLX5_FS_DEFAULT_FLOW_TAG; + bool is_drop = false; int err = 0; + int dest_num = 1; if (!is_valid_attr(dev->mdev, flow_attr)) return ERR_PTR(-EINVAL); @@ -2200,7 +2210,8 @@ static struct mlx5_ib_flow_handler *create_flow_rule(struct mlx5_ib_dev *dev, for (spec_index = 0; spec_index < flow_attr->num_of_specs; spec_index++) { err = parse_flow_attr(dev->mdev, spec->match_criteria, - spec->match_value, ib_flow, &flow_tag); + spec->match_value, + ib_flow, &flow_tag, &is_drop); if (err < 0) goto free; @@ -2208,8 +2219,14 @@ static struct mlx5_ib_flow_handler *create_flow_rule(struct mlx5_ib_dev *dev, } spec->match_criteria_enable = get_match_criteria_enable(spec->match_criteria); - flow_act.action = dst ? MLX5_FLOW_CONTEXT_ACTION_FWD_DEST : - MLX5_FLOW_CONTEXT_ACTION_FWD_NEXT_PRIO; + if (is_drop) { + flow_act.action = MLX5_FLOW_CONTEXT_ACTION_DROP; + rule_dst = NULL; + dest_num = 0; + } else { + flow_act.action = dst ? MLX5_FLOW_CONTEXT_ACTION_FWD_DEST : + MLX5_FLOW_CONTEXT_ACTION_FWD_NEXT_PRIO; + } if (flow_tag != MLX5_FS_DEFAULT_FLOW_TAG && (flow_attr->type == IB_FLOW_ATTR_ALL_DEFAULT || @@ -2222,7 +2239,7 @@ static struct mlx5_ib_flow_handler *create_flow_rule(struct mlx5_ib_dev *dev, flow_act.flow_tag = flow_tag; handler->rule = mlx5_add_flow_rules(ft, spec, &flow_act, - dst, 1); + rule_dst, dest_num); if (IS_ERR(handler->rule)) { err = PTR_ERR(handler->rule);