From 49c958ccd2433114ca8a96c996b5016aa89c7ba5 Mon Sep 17 00:00:00 2001 From: Jiri Pirko Date: Mon, 27 Apr 2020 18:12:58 +0300 Subject: mlxsw: spectrum_acl: Move block helpers into inline header functions The struct is defined in the header, no need to have the helpers in the c file. Move the helpers to the header. Signed-off-by: Jiri Pirko Signed-off-by: Ido Schimmel Signed-off-by: David S. Miller --- drivers/net/ethernet/mellanox/mlxsw/spectrum.h | 60 ++++++++++++++++++---- drivers/net/ethernet/mellanox/mlxsw/spectrum_acl.c | 43 ---------------- 2 files changed, 51 insertions(+), 52 deletions(-) diff --git a/drivers/net/ethernet/mellanox/mlxsw/spectrum.h b/drivers/net/ethernet/mellanox/mlxsw/spectrum.h index ca56e72cb4b7..f158cd98f8d8 100644 --- a/drivers/net/ethernet/mellanox/mlxsw/spectrum.h +++ b/drivers/net/ethernet/mellanox/mlxsw/spectrum.h @@ -677,12 +677,57 @@ struct mlxsw_sp_acl_block { }; struct mlxsw_afk *mlxsw_sp_acl_afk(struct mlxsw_sp_acl *acl); -struct mlxsw_sp *mlxsw_sp_acl_block_mlxsw_sp(struct mlxsw_sp_acl_block *block); -unsigned int -mlxsw_sp_acl_block_rule_count(const struct mlxsw_sp_acl_block *block); -void mlxsw_sp_acl_block_disable_inc(struct mlxsw_sp_acl_block *block); -void mlxsw_sp_acl_block_disable_dec(struct mlxsw_sp_acl_block *block); -bool mlxsw_sp_acl_block_disabled(const struct mlxsw_sp_acl_block *block); + +static inline struct mlxsw_sp * +mlxsw_sp_acl_block_mlxsw_sp(struct mlxsw_sp_acl_block *block) +{ + return block->mlxsw_sp; +} + +static inline unsigned int +mlxsw_sp_acl_block_rule_count(const struct mlxsw_sp_acl_block *block) +{ + return block ? block->rule_count : 0; +} + +static inline void +mlxsw_sp_acl_block_disable_inc(struct mlxsw_sp_acl_block *block) +{ + if (block) + block->disable_count++; +} + +static inline void +mlxsw_sp_acl_block_disable_dec(struct mlxsw_sp_acl_block *block) +{ + if (block) + block->disable_count--; +} + +static inline bool +mlxsw_sp_acl_block_disabled(const struct mlxsw_sp_acl_block *block) +{ + return block->disable_count; +} + +static inline bool +mlxsw_sp_acl_block_is_egress_bound(const struct mlxsw_sp_acl_block *block) +{ + return block->egress_binding_count; +} + +static inline bool +mlxsw_sp_acl_block_is_ingress_bound(const struct mlxsw_sp_acl_block *block) +{ + return block->ingress_binding_count; +} + +static inline bool +mlxsw_sp_acl_block_is_mixed_bound(const struct mlxsw_sp_acl_block *block) +{ + return block->ingress_binding_count && block->egress_binding_count; +} + struct mlxsw_sp_acl_block *mlxsw_sp_acl_block_create(struct mlxsw_sp *mlxsw_sp, struct net *net); void mlxsw_sp_acl_block_destroy(struct mlxsw_sp_acl_block *block); @@ -695,9 +740,6 @@ int mlxsw_sp_acl_block_unbind(struct mlxsw_sp *mlxsw_sp, struct mlxsw_sp_acl_block *block, struct mlxsw_sp_port *mlxsw_sp_port, bool ingress); -bool mlxsw_sp_acl_block_is_egress_bound(const struct mlxsw_sp_acl_block *block); -bool mlxsw_sp_acl_block_is_ingress_bound(const struct mlxsw_sp_acl_block *block); -bool mlxsw_sp_acl_block_is_mixed_bound(const struct mlxsw_sp_acl_block *block); struct mlxsw_sp_acl_ruleset * mlxsw_sp_acl_ruleset_lookup(struct mlxsw_sp *mlxsw_sp, struct mlxsw_sp_acl_block *block, u32 chain_index, diff --git a/drivers/net/ethernet/mellanox/mlxsw/spectrum_acl.c b/drivers/net/ethernet/mellanox/mlxsw/spectrum_acl.c index 01cff711bbd2..bb06c007b3f2 100644 --- a/drivers/net/ethernet/mellanox/mlxsw/spectrum_acl.c +++ b/drivers/net/ethernet/mellanox/mlxsw/spectrum_acl.c @@ -94,49 +94,6 @@ struct mlxsw_sp_fid *mlxsw_sp_acl_dummy_fid(struct mlxsw_sp *mlxsw_sp) return mlxsw_sp->acl->dummy_fid; } -struct mlxsw_sp *mlxsw_sp_acl_block_mlxsw_sp(struct mlxsw_sp_acl_block *block) -{ - return block->mlxsw_sp; -} - -unsigned int -mlxsw_sp_acl_block_rule_count(const struct mlxsw_sp_acl_block *block) -{ - return block ? block->rule_count : 0; -} - -void mlxsw_sp_acl_block_disable_inc(struct mlxsw_sp_acl_block *block) -{ - if (block) - block->disable_count++; -} - -void mlxsw_sp_acl_block_disable_dec(struct mlxsw_sp_acl_block *block) -{ - if (block) - block->disable_count--; -} - -bool mlxsw_sp_acl_block_disabled(const struct mlxsw_sp_acl_block *block) -{ - return block->disable_count; -} - -bool mlxsw_sp_acl_block_is_egress_bound(const struct mlxsw_sp_acl_block *block) -{ - return block->egress_binding_count; -} - -bool mlxsw_sp_acl_block_is_ingress_bound(const struct mlxsw_sp_acl_block *block) -{ - return block->ingress_binding_count; -} - -bool mlxsw_sp_acl_block_is_mixed_bound(const struct mlxsw_sp_acl_block *block) -{ - return block->ingress_binding_count && block->egress_binding_count; -} - static bool mlxsw_sp_acl_ruleset_is_singular(const struct mlxsw_sp_acl_ruleset *ruleset) { -- cgit From 3bc3ffb6e911f9de099d81187ae99b45966cbd05 Mon Sep 17 00:00:00 2001 From: Jiri Pirko Date: Mon, 27 Apr 2020 18:12:59 +0300 Subject: mlxsw: spectrum: Rename acl_block to flow_block The acl_block structure is going to be used for non-acl case - matchall offload. So rename it accordingly. Signed-off-by: Jiri Pirko Signed-off-by: Ido Schimmel Signed-off-by: David S. Miller --- drivers/net/ethernet/mellanox/mlxsw/spectrum.c | 71 ++++++++++--------- drivers/net/ethernet/mellanox/mlxsw/spectrum.h | 64 ++++++++--------- .../ethernet/mellanox/mlxsw/spectrum2_mr_tcam.c | 14 ++-- drivers/net/ethernet/mellanox/mlxsw/spectrum_acl.c | 82 +++++++++++----------- .../net/ethernet/mellanox/mlxsw/spectrum_flower.c | 24 +++---- 5 files changed, 128 insertions(+), 127 deletions(-) diff --git a/drivers/net/ethernet/mellanox/mlxsw/spectrum.c b/drivers/net/ethernet/mellanox/mlxsw/spectrum.c index 24ca8d5bc564..f64e8da21d4a 100644 --- a/drivers/net/ethernet/mellanox/mlxsw/spectrum.c +++ b/drivers/net/ethernet/mellanox/mlxsw/spectrum.c @@ -1544,23 +1544,23 @@ static int mlxsw_sp_setup_tc_cls_matchall(struct mlxsw_sp_port *mlxsw_sp_port, } static int -mlxsw_sp_setup_tc_cls_flower(struct mlxsw_sp_acl_block *acl_block, +mlxsw_sp_setup_tc_cls_flower(struct mlxsw_sp_flow_block *flow_block, struct flow_cls_offload *f) { - struct mlxsw_sp *mlxsw_sp = mlxsw_sp_acl_block_mlxsw_sp(acl_block); + struct mlxsw_sp *mlxsw_sp = mlxsw_sp_flow_block_mlxsw_sp(flow_block); switch (f->command) { case FLOW_CLS_REPLACE: - return mlxsw_sp_flower_replace(mlxsw_sp, acl_block, f); + return mlxsw_sp_flower_replace(mlxsw_sp, flow_block, f); case FLOW_CLS_DESTROY: - mlxsw_sp_flower_destroy(mlxsw_sp, acl_block, f); + mlxsw_sp_flower_destroy(mlxsw_sp, flow_block, f); return 0; case FLOW_CLS_STATS: - return mlxsw_sp_flower_stats(mlxsw_sp, acl_block, f); + return mlxsw_sp_flower_stats(mlxsw_sp, flow_block, f); case FLOW_CLS_TMPLT_CREATE: - return mlxsw_sp_flower_tmplt_create(mlxsw_sp, acl_block, f); + return mlxsw_sp_flower_tmplt_create(mlxsw_sp, flow_block, f); case FLOW_CLS_TMPLT_DESTROY: - mlxsw_sp_flower_tmplt_destroy(mlxsw_sp, acl_block, f); + mlxsw_sp_flower_tmplt_destroy(mlxsw_sp, flow_block, f); return 0; default: return -EOPNOTSUPP; @@ -1607,16 +1607,16 @@ static int mlxsw_sp_setup_tc_block_cb_matchall_eg(enum tc_setup_type type, static int mlxsw_sp_setup_tc_block_cb_flower(enum tc_setup_type type, void *type_data, void *cb_priv) { - struct mlxsw_sp_acl_block *acl_block = cb_priv; + struct mlxsw_sp_flow_block *flow_block = cb_priv; switch (type) { case TC_SETUP_CLSMATCHALL: return 0; case TC_SETUP_CLSFLOWER: - if (mlxsw_sp_acl_block_disabled(acl_block)) + if (mlxsw_sp_flow_block_disabled(flow_block)) return -EOPNOTSUPP; - return mlxsw_sp_setup_tc_cls_flower(acl_block, type_data); + return mlxsw_sp_setup_tc_cls_flower(flow_block, type_data); default: return -EOPNOTSUPP; } @@ -1624,9 +1624,9 @@ static int mlxsw_sp_setup_tc_block_cb_flower(enum tc_setup_type type, static void mlxsw_sp_tc_block_flower_release(void *cb_priv) { - struct mlxsw_sp_acl_block *acl_block = cb_priv; + struct mlxsw_sp_flow_block *flow_block = cb_priv; - mlxsw_sp_acl_block_destroy(acl_block); + mlxsw_sp_flow_block_destroy(flow_block); } static LIST_HEAD(mlxsw_sp_block_cb_list); @@ -1636,7 +1636,7 @@ mlxsw_sp_setup_tc_block_flower_bind(struct mlxsw_sp_port *mlxsw_sp_port, struct flow_block_offload *f, bool ingress) { struct mlxsw_sp *mlxsw_sp = mlxsw_sp_port->mlxsw_sp; - struct mlxsw_sp_acl_block *acl_block; + struct mlxsw_sp_flow_block *flow_block; struct flow_block_cb *block_cb; bool register_block = false; int err; @@ -1645,31 +1645,31 @@ mlxsw_sp_setup_tc_block_flower_bind(struct mlxsw_sp_port *mlxsw_sp_port, mlxsw_sp_setup_tc_block_cb_flower, mlxsw_sp); if (!block_cb) { - acl_block = mlxsw_sp_acl_block_create(mlxsw_sp, f->net); - if (!acl_block) + flow_block = mlxsw_sp_flow_block_create(mlxsw_sp, f->net); + if (!flow_block) return -ENOMEM; block_cb = flow_block_cb_alloc(mlxsw_sp_setup_tc_block_cb_flower, - mlxsw_sp, acl_block, + mlxsw_sp, flow_block, mlxsw_sp_tc_block_flower_release); if (IS_ERR(block_cb)) { - mlxsw_sp_acl_block_destroy(acl_block); + mlxsw_sp_flow_block_destroy(flow_block); err = PTR_ERR(block_cb); goto err_cb_register; } register_block = true; } else { - acl_block = flow_block_cb_priv(block_cb); + flow_block = flow_block_cb_priv(block_cb); } flow_block_cb_incref(block_cb); - err = mlxsw_sp_acl_block_bind(mlxsw_sp, acl_block, - mlxsw_sp_port, ingress, f->extack); + err = mlxsw_sp_flow_block_bind(mlxsw_sp, flow_block, + mlxsw_sp_port, ingress, f->extack); if (err) goto err_block_bind; if (ingress) - mlxsw_sp_port->ing_acl_block = acl_block; + mlxsw_sp_port->ing_flow_block = flow_block; else - mlxsw_sp_port->eg_acl_block = acl_block; + mlxsw_sp_port->eg_flow_block = flow_block; if (register_block) { flow_block_cb_add(block_cb, f); @@ -1687,10 +1687,11 @@ err_cb_register: static void mlxsw_sp_setup_tc_block_flower_unbind(struct mlxsw_sp_port *mlxsw_sp_port, - struct flow_block_offload *f, bool ingress) + struct flow_block_offload *f, + bool ingress) { struct mlxsw_sp *mlxsw_sp = mlxsw_sp_port->mlxsw_sp; - struct mlxsw_sp_acl_block *acl_block; + struct mlxsw_sp_flow_block *flow_block; struct flow_block_cb *block_cb; int err; @@ -1701,13 +1702,13 @@ mlxsw_sp_setup_tc_block_flower_unbind(struct mlxsw_sp_port *mlxsw_sp_port, return; if (ingress) - mlxsw_sp_port->ing_acl_block = NULL; + mlxsw_sp_port->ing_flow_block = NULL; else - mlxsw_sp_port->eg_acl_block = NULL; + mlxsw_sp_port->eg_flow_block = NULL; - acl_block = flow_block_cb_priv(block_cb); - err = mlxsw_sp_acl_block_unbind(mlxsw_sp, acl_block, - mlxsw_sp_port, ingress); + flow_block = flow_block_cb_priv(block_cb); + err = mlxsw_sp_flow_block_unbind(mlxsw_sp, flow_block, + mlxsw_sp_port, ingress); if (!err && !flow_block_cb_decref(block_cb)) { flow_block_cb_remove(block_cb, f); list_del(&block_cb->driver_list); @@ -1797,17 +1798,17 @@ static int mlxsw_sp_feature_hw_tc(struct net_device *dev, bool enable) struct mlxsw_sp_port *mlxsw_sp_port = netdev_priv(dev); if (!enable) { - if (mlxsw_sp_acl_block_rule_count(mlxsw_sp_port->ing_acl_block) || - mlxsw_sp_acl_block_rule_count(mlxsw_sp_port->eg_acl_block) || + if (mlxsw_sp_flow_block_rule_count(mlxsw_sp_port->ing_flow_block) || + mlxsw_sp_flow_block_rule_count(mlxsw_sp_port->eg_flow_block) || !list_empty(&mlxsw_sp_port->mall_tc_list)) { netdev_err(dev, "Active offloaded tc filters, can't turn hw_tc_offload off\n"); return -EINVAL; } - mlxsw_sp_acl_block_disable_inc(mlxsw_sp_port->ing_acl_block); - mlxsw_sp_acl_block_disable_inc(mlxsw_sp_port->eg_acl_block); + mlxsw_sp_flow_block_disable_inc(mlxsw_sp_port->ing_flow_block); + mlxsw_sp_flow_block_disable_inc(mlxsw_sp_port->eg_flow_block); } else { - mlxsw_sp_acl_block_disable_dec(mlxsw_sp_port->ing_acl_block); - mlxsw_sp_acl_block_disable_dec(mlxsw_sp_port->eg_acl_block); + mlxsw_sp_flow_block_disable_dec(mlxsw_sp_port->ing_flow_block); + mlxsw_sp_flow_block_disable_dec(mlxsw_sp_port->eg_flow_block); } return 0; } diff --git a/drivers/net/ethernet/mellanox/mlxsw/spectrum.h b/drivers/net/ethernet/mellanox/mlxsw/spectrum.h index f158cd98f8d8..65b1a2d87c2d 100644 --- a/drivers/net/ethernet/mellanox/mlxsw/spectrum.h +++ b/drivers/net/ethernet/mellanox/mlxsw/spectrum.h @@ -287,8 +287,8 @@ struct mlxsw_sp_port { struct mlxsw_sp_port_vlan *default_vlan; struct mlxsw_sp_qdisc_state *qdisc; unsigned acl_rule_count; - struct mlxsw_sp_acl_block *ing_acl_block; - struct mlxsw_sp_acl_block *eg_acl_block; + struct mlxsw_sp_flow_block *ing_flow_block; + struct mlxsw_sp_flow_block *eg_flow_block; struct { struct delayed_work shaper_dw; struct hwtstamp_config hwtstamp_config; @@ -654,7 +654,7 @@ struct mlxsw_sp_acl_rule_info { unsigned int counter_index; }; -struct mlxsw_sp_acl_block; +struct mlxsw_sp_flow_block; struct mlxsw_sp_acl_ruleset; /* spectrum_acl.c */ @@ -663,7 +663,7 @@ enum mlxsw_sp_acl_profile { MLXSW_SP_ACL_PROFILE_MR, }; -struct mlxsw_sp_acl_block { +struct mlxsw_sp_flow_block { struct list_head binding_list; struct mlxsw_sp_acl_ruleset *ruleset_zero; struct mlxsw_sp *mlxsw_sp; @@ -679,74 +679,74 @@ struct mlxsw_sp_acl_block { struct mlxsw_afk *mlxsw_sp_acl_afk(struct mlxsw_sp_acl *acl); static inline struct mlxsw_sp * -mlxsw_sp_acl_block_mlxsw_sp(struct mlxsw_sp_acl_block *block) +mlxsw_sp_flow_block_mlxsw_sp(struct mlxsw_sp_flow_block *block) { return block->mlxsw_sp; } static inline unsigned int -mlxsw_sp_acl_block_rule_count(const struct mlxsw_sp_acl_block *block) +mlxsw_sp_flow_block_rule_count(const struct mlxsw_sp_flow_block *block) { return block ? block->rule_count : 0; } static inline void -mlxsw_sp_acl_block_disable_inc(struct mlxsw_sp_acl_block *block) +mlxsw_sp_flow_block_disable_inc(struct mlxsw_sp_flow_block *block) { if (block) block->disable_count++; } static inline void -mlxsw_sp_acl_block_disable_dec(struct mlxsw_sp_acl_block *block) +mlxsw_sp_flow_block_disable_dec(struct mlxsw_sp_flow_block *block) { if (block) block->disable_count--; } static inline bool -mlxsw_sp_acl_block_disabled(const struct mlxsw_sp_acl_block *block) +mlxsw_sp_flow_block_disabled(const struct mlxsw_sp_flow_block *block) { return block->disable_count; } static inline bool -mlxsw_sp_acl_block_is_egress_bound(const struct mlxsw_sp_acl_block *block) +mlxsw_sp_flow_block_is_egress_bound(const struct mlxsw_sp_flow_block *block) { return block->egress_binding_count; } static inline bool -mlxsw_sp_acl_block_is_ingress_bound(const struct mlxsw_sp_acl_block *block) +mlxsw_sp_flow_block_is_ingress_bound(const struct mlxsw_sp_flow_block *block) { return block->ingress_binding_count; } static inline bool -mlxsw_sp_acl_block_is_mixed_bound(const struct mlxsw_sp_acl_block *block) +mlxsw_sp_flow_block_is_mixed_bound(const struct mlxsw_sp_flow_block *block) { return block->ingress_binding_count && block->egress_binding_count; } -struct mlxsw_sp_acl_block *mlxsw_sp_acl_block_create(struct mlxsw_sp *mlxsw_sp, - struct net *net); -void mlxsw_sp_acl_block_destroy(struct mlxsw_sp_acl_block *block); -int mlxsw_sp_acl_block_bind(struct mlxsw_sp *mlxsw_sp, - struct mlxsw_sp_acl_block *block, - struct mlxsw_sp_port *mlxsw_sp_port, - bool ingress, - struct netlink_ext_ack *extack); -int mlxsw_sp_acl_block_unbind(struct mlxsw_sp *mlxsw_sp, - struct mlxsw_sp_acl_block *block, - struct mlxsw_sp_port *mlxsw_sp_port, - bool ingress); +struct mlxsw_sp_flow_block *mlxsw_sp_flow_block_create(struct mlxsw_sp *mlxsw_sp, + struct net *net); +void mlxsw_sp_flow_block_destroy(struct mlxsw_sp_flow_block *block); +int mlxsw_sp_flow_block_bind(struct mlxsw_sp *mlxsw_sp, + struct mlxsw_sp_flow_block *block, + struct mlxsw_sp_port *mlxsw_sp_port, + bool ingress, + struct netlink_ext_ack *extack); +int mlxsw_sp_flow_block_unbind(struct mlxsw_sp *mlxsw_sp, + struct mlxsw_sp_flow_block *block, + struct mlxsw_sp_port *mlxsw_sp_port, + bool ingress); struct mlxsw_sp_acl_ruleset * mlxsw_sp_acl_ruleset_lookup(struct mlxsw_sp *mlxsw_sp, - struct mlxsw_sp_acl_block *block, u32 chain_index, + struct mlxsw_sp_flow_block *block, u32 chain_index, enum mlxsw_sp_acl_profile profile); struct mlxsw_sp_acl_ruleset * mlxsw_sp_acl_ruleset_get(struct mlxsw_sp *mlxsw_sp, - struct mlxsw_sp_acl_block *block, u32 chain_index, + struct mlxsw_sp_flow_block *block, u32 chain_index, enum mlxsw_sp_acl_profile profile, struct mlxsw_afk_element_usage *tmplt_elusage); void mlxsw_sp_acl_ruleset_put(struct mlxsw_sp *mlxsw_sp, @@ -778,7 +778,7 @@ int mlxsw_sp_acl_rulei_act_drop(struct mlxsw_sp_acl_rule_info *rulei, int mlxsw_sp_acl_rulei_act_trap(struct mlxsw_sp_acl_rule_info *rulei); int mlxsw_sp_acl_rulei_act_mirror(struct mlxsw_sp *mlxsw_sp, struct mlxsw_sp_acl_rule_info *rulei, - struct mlxsw_sp_acl_block *block, + struct mlxsw_sp_flow_block *block, struct net_device *out_dev, struct netlink_ext_ack *extack); int mlxsw_sp_acl_rulei_act_fwd(struct mlxsw_sp *mlxsw_sp, @@ -901,19 +901,19 @@ extern const struct mlxsw_afk_ops mlxsw_sp2_afk_ops; /* spectrum_flower.c */ int mlxsw_sp_flower_replace(struct mlxsw_sp *mlxsw_sp, - struct mlxsw_sp_acl_block *block, + struct mlxsw_sp_flow_block *block, struct flow_cls_offload *f); void mlxsw_sp_flower_destroy(struct mlxsw_sp *mlxsw_sp, - struct mlxsw_sp_acl_block *block, + struct mlxsw_sp_flow_block *block, struct flow_cls_offload *f); int mlxsw_sp_flower_stats(struct mlxsw_sp *mlxsw_sp, - struct mlxsw_sp_acl_block *block, + struct mlxsw_sp_flow_block *block, struct flow_cls_offload *f); int mlxsw_sp_flower_tmplt_create(struct mlxsw_sp *mlxsw_sp, - struct mlxsw_sp_acl_block *block, + struct mlxsw_sp_flow_block *block, struct flow_cls_offload *f); void mlxsw_sp_flower_tmplt_destroy(struct mlxsw_sp *mlxsw_sp, - struct mlxsw_sp_acl_block *block, + struct mlxsw_sp_flow_block *block, struct flow_cls_offload *f); /* spectrum_qdisc.c */ diff --git a/drivers/net/ethernet/mellanox/mlxsw/spectrum2_mr_tcam.c b/drivers/net/ethernet/mellanox/mlxsw/spectrum2_mr_tcam.c index e31ec75ac035..a11d911302f1 100644 --- a/drivers/net/ethernet/mellanox/mlxsw/spectrum2_mr_tcam.c +++ b/drivers/net/ethernet/mellanox/mlxsw/spectrum2_mr_tcam.c @@ -9,7 +9,7 @@ struct mlxsw_sp2_mr_tcam { struct mlxsw_sp *mlxsw_sp; - struct mlxsw_sp_acl_block *acl_block; + struct mlxsw_sp_flow_block *flow_block; struct mlxsw_sp_acl_ruleset *ruleset4; struct mlxsw_sp_acl_ruleset *ruleset6; }; @@ -61,7 +61,7 @@ static int mlxsw_sp2_mr_tcam_ipv4_init(struct mlxsw_sp2_mr_tcam *mr_tcam) mlxsw_sp2_mr_tcam_usage_ipv4, ARRAY_SIZE(mlxsw_sp2_mr_tcam_usage_ipv4)); mr_tcam->ruleset4 = mlxsw_sp_acl_ruleset_get(mr_tcam->mlxsw_sp, - mr_tcam->acl_block, + mr_tcam->flow_block, MLXSW_SP_L3_PROTO_IPV4, MLXSW_SP_ACL_PROFILE_MR, &elusage); @@ -111,7 +111,7 @@ static int mlxsw_sp2_mr_tcam_ipv6_init(struct mlxsw_sp2_mr_tcam *mr_tcam) mlxsw_sp2_mr_tcam_usage_ipv6, ARRAY_SIZE(mlxsw_sp2_mr_tcam_usage_ipv6)); mr_tcam->ruleset6 = mlxsw_sp_acl_ruleset_get(mr_tcam->mlxsw_sp, - mr_tcam->acl_block, + mr_tcam->flow_block, MLXSW_SP_L3_PROTO_IPV6, MLXSW_SP_ACL_PROFILE_MR, &elusage); @@ -289,8 +289,8 @@ static int mlxsw_sp2_mr_tcam_init(struct mlxsw_sp *mlxsw_sp, void *priv) int err; mr_tcam->mlxsw_sp = mlxsw_sp; - mr_tcam->acl_block = mlxsw_sp_acl_block_create(mlxsw_sp, NULL); - if (!mr_tcam->acl_block) + mr_tcam->flow_block = mlxsw_sp_flow_block_create(mlxsw_sp, NULL); + if (!mr_tcam->flow_block) return -ENOMEM; err = mlxsw_sp2_mr_tcam_ipv4_init(mr_tcam); @@ -306,7 +306,7 @@ static int mlxsw_sp2_mr_tcam_init(struct mlxsw_sp *mlxsw_sp, void *priv) err_ipv6_init: mlxsw_sp2_mr_tcam_ipv4_fini(mr_tcam); err_ipv4_init: - mlxsw_sp_acl_block_destroy(mr_tcam->acl_block); + mlxsw_sp_flow_block_destroy(mr_tcam->flow_block); return err; } @@ -316,7 +316,7 @@ static void mlxsw_sp2_mr_tcam_fini(void *priv) mlxsw_sp2_mr_tcam_ipv6_fini(mr_tcam); mlxsw_sp2_mr_tcam_ipv4_fini(mr_tcam); - mlxsw_sp_acl_block_destroy(mr_tcam->acl_block); + mlxsw_sp_flow_block_destroy(mr_tcam->flow_block); } const struct mlxsw_sp_mr_tcam_ops mlxsw_sp2_mr_tcam_ops = { diff --git a/drivers/net/ethernet/mellanox/mlxsw/spectrum_acl.c b/drivers/net/ethernet/mellanox/mlxsw/spectrum_acl.c index bb06c007b3f2..f9524cb95e9f 100644 --- a/drivers/net/ethernet/mellanox/mlxsw/spectrum_acl.c +++ b/drivers/net/ethernet/mellanox/mlxsw/spectrum_acl.c @@ -40,7 +40,7 @@ struct mlxsw_afk *mlxsw_sp_acl_afk(struct mlxsw_sp_acl *acl) return acl->afk; } -struct mlxsw_sp_acl_block_binding { +struct mlxsw_sp_flow_block_binding { struct list_head list; struct net_device *dev; struct mlxsw_sp_port *mlxsw_sp_port; @@ -48,7 +48,7 @@ struct mlxsw_sp_acl_block_binding { }; struct mlxsw_sp_acl_ruleset_ht_key { - struct mlxsw_sp_acl_block *block; + struct mlxsw_sp_flow_block *block; u32 chain_index; const struct mlxsw_sp_acl_profile_ops *ops; }; @@ -103,8 +103,8 @@ mlxsw_sp_acl_ruleset_is_singular(const struct mlxsw_sp_acl_ruleset *ruleset) static int mlxsw_sp_acl_ruleset_bind(struct mlxsw_sp *mlxsw_sp, - struct mlxsw_sp_acl_block *block, - struct mlxsw_sp_acl_block_binding *binding) + struct mlxsw_sp_flow_block *block, + struct mlxsw_sp_flow_block_binding *binding) { struct mlxsw_sp_acl_ruleset *ruleset = block->ruleset_zero; const struct mlxsw_sp_acl_profile_ops *ops = ruleset->ht_key.ops; @@ -115,8 +115,8 @@ mlxsw_sp_acl_ruleset_bind(struct mlxsw_sp *mlxsw_sp, static void mlxsw_sp_acl_ruleset_unbind(struct mlxsw_sp *mlxsw_sp, - struct mlxsw_sp_acl_block *block, - struct mlxsw_sp_acl_block_binding *binding) + struct mlxsw_sp_flow_block *block, + struct mlxsw_sp_flow_block_binding *binding) { struct mlxsw_sp_acl_ruleset *ruleset = block->ruleset_zero; const struct mlxsw_sp_acl_profile_ops *ops = ruleset->ht_key.ops; @@ -126,7 +126,7 @@ mlxsw_sp_acl_ruleset_unbind(struct mlxsw_sp *mlxsw_sp, } static bool -mlxsw_sp_acl_ruleset_block_bound(const struct mlxsw_sp_acl_block *block) +mlxsw_sp_acl_ruleset_block_bound(const struct mlxsw_sp_flow_block *block) { return block->ruleset_zero; } @@ -134,9 +134,9 @@ mlxsw_sp_acl_ruleset_block_bound(const struct mlxsw_sp_acl_block *block) static int mlxsw_sp_acl_ruleset_block_bind(struct mlxsw_sp *mlxsw_sp, struct mlxsw_sp_acl_ruleset *ruleset, - struct mlxsw_sp_acl_block *block) + struct mlxsw_sp_flow_block *block) { - struct mlxsw_sp_acl_block_binding *binding; + struct mlxsw_sp_flow_block_binding *binding; int err; block->ruleset_zero = ruleset; @@ -159,19 +159,19 @@ rollback: static void mlxsw_sp_acl_ruleset_block_unbind(struct mlxsw_sp *mlxsw_sp, struct mlxsw_sp_acl_ruleset *ruleset, - struct mlxsw_sp_acl_block *block) + struct mlxsw_sp_flow_block *block) { - struct mlxsw_sp_acl_block_binding *binding; + struct mlxsw_sp_flow_block_binding *binding; list_for_each_entry(binding, &block->binding_list, list) mlxsw_sp_acl_ruleset_unbind(mlxsw_sp, block, binding); block->ruleset_zero = NULL; } -struct mlxsw_sp_acl_block *mlxsw_sp_acl_block_create(struct mlxsw_sp *mlxsw_sp, - struct net *net) +struct mlxsw_sp_flow_block * +mlxsw_sp_flow_block_create(struct mlxsw_sp *mlxsw_sp, struct net *net) { - struct mlxsw_sp_acl_block *block; + struct mlxsw_sp_flow_block *block; block = kzalloc(sizeof(*block), GFP_KERNEL); if (!block) @@ -182,17 +182,17 @@ struct mlxsw_sp_acl_block *mlxsw_sp_acl_block_create(struct mlxsw_sp *mlxsw_sp, return block; } -void mlxsw_sp_acl_block_destroy(struct mlxsw_sp_acl_block *block) +void mlxsw_sp_flow_block_destroy(struct mlxsw_sp_flow_block *block) { WARN_ON(!list_empty(&block->binding_list)); kfree(block); } -static struct mlxsw_sp_acl_block_binding * -mlxsw_sp_acl_block_lookup(struct mlxsw_sp_acl_block *block, - struct mlxsw_sp_port *mlxsw_sp_port, bool ingress) +static struct mlxsw_sp_flow_block_binding * +mlxsw_sp_flow_block_lookup(struct mlxsw_sp_flow_block *block, + struct mlxsw_sp_port *mlxsw_sp_port, bool ingress) { - struct mlxsw_sp_acl_block_binding *binding; + struct mlxsw_sp_flow_block_binding *binding; list_for_each_entry(binding, &block->binding_list, list) if (binding->mlxsw_sp_port == mlxsw_sp_port && @@ -201,16 +201,16 @@ mlxsw_sp_acl_block_lookup(struct mlxsw_sp_acl_block *block, return NULL; } -int mlxsw_sp_acl_block_bind(struct mlxsw_sp *mlxsw_sp, - struct mlxsw_sp_acl_block *block, - struct mlxsw_sp_port *mlxsw_sp_port, - bool ingress, - struct netlink_ext_ack *extack) +int mlxsw_sp_flow_block_bind(struct mlxsw_sp *mlxsw_sp, + struct mlxsw_sp_flow_block *block, + struct mlxsw_sp_port *mlxsw_sp_port, + bool ingress, + struct netlink_ext_ack *extack) { - struct mlxsw_sp_acl_block_binding *binding; + struct mlxsw_sp_flow_block_binding *binding; int err; - if (WARN_ON(mlxsw_sp_acl_block_lookup(block, mlxsw_sp_port, ingress))) + if (WARN_ON(mlxsw_sp_flow_block_lookup(block, mlxsw_sp_port, ingress))) return -EEXIST; if (ingress && block->ingress_blocker_rule_count) { @@ -247,14 +247,14 @@ err_ruleset_bind: return err; } -int mlxsw_sp_acl_block_unbind(struct mlxsw_sp *mlxsw_sp, - struct mlxsw_sp_acl_block *block, - struct mlxsw_sp_port *mlxsw_sp_port, - bool ingress) +int mlxsw_sp_flow_block_unbind(struct mlxsw_sp *mlxsw_sp, + struct mlxsw_sp_flow_block *block, + struct mlxsw_sp_port *mlxsw_sp_port, + bool ingress) { - struct mlxsw_sp_acl_block_binding *binding; + struct mlxsw_sp_flow_block_binding *binding; - binding = mlxsw_sp_acl_block_lookup(block, mlxsw_sp_port, ingress); + binding = mlxsw_sp_flow_block_lookup(block, mlxsw_sp_port, ingress); if (!binding) return -ENOENT; @@ -274,7 +274,7 @@ int mlxsw_sp_acl_block_unbind(struct mlxsw_sp *mlxsw_sp, static struct mlxsw_sp_acl_ruleset * mlxsw_sp_acl_ruleset_create(struct mlxsw_sp *mlxsw_sp, - struct mlxsw_sp_acl_block *block, u32 chain_index, + struct mlxsw_sp_flow_block *block, u32 chain_index, const struct mlxsw_sp_acl_profile_ops *ops, struct mlxsw_afk_element_usage *tmplt_elusage) { @@ -345,7 +345,7 @@ static void mlxsw_sp_acl_ruleset_ref_dec(struct mlxsw_sp *mlxsw_sp, static struct mlxsw_sp_acl_ruleset * __mlxsw_sp_acl_ruleset_lookup(struct mlxsw_sp_acl *acl, - struct mlxsw_sp_acl_block *block, u32 chain_index, + struct mlxsw_sp_flow_block *block, u32 chain_index, const struct mlxsw_sp_acl_profile_ops *ops) { struct mlxsw_sp_acl_ruleset_ht_key ht_key; @@ -360,7 +360,7 @@ __mlxsw_sp_acl_ruleset_lookup(struct mlxsw_sp_acl *acl, struct mlxsw_sp_acl_ruleset * mlxsw_sp_acl_ruleset_lookup(struct mlxsw_sp *mlxsw_sp, - struct mlxsw_sp_acl_block *block, u32 chain_index, + struct mlxsw_sp_flow_block *block, u32 chain_index, enum mlxsw_sp_acl_profile profile) { const struct mlxsw_sp_acl_profile_ops *ops; @@ -378,7 +378,7 @@ mlxsw_sp_acl_ruleset_lookup(struct mlxsw_sp *mlxsw_sp, struct mlxsw_sp_acl_ruleset * mlxsw_sp_acl_ruleset_get(struct mlxsw_sp *mlxsw_sp, - struct mlxsw_sp_acl_block *block, u32 chain_index, + struct mlxsw_sp_flow_block *block, u32 chain_index, enum mlxsw_sp_acl_profile profile, struct mlxsw_afk_element_usage *tmplt_elusage) { @@ -541,11 +541,11 @@ int mlxsw_sp_acl_rulei_act_fwd(struct mlxsw_sp *mlxsw_sp, int mlxsw_sp_acl_rulei_act_mirror(struct mlxsw_sp *mlxsw_sp, struct mlxsw_sp_acl_rule_info *rulei, - struct mlxsw_sp_acl_block *block, + struct mlxsw_sp_flow_block *block, struct net_device *out_dev, struct netlink_ext_ack *extack) { - struct mlxsw_sp_acl_block_binding *binding; + struct mlxsw_sp_flow_block_binding *binding; struct mlxsw_sp_port *in_port; if (!list_is_singular(&block->binding_list)) { @@ -553,7 +553,7 @@ int mlxsw_sp_acl_rulei_act_mirror(struct mlxsw_sp *mlxsw_sp, return -EOPNOTSUPP; } binding = list_first_entry(&block->binding_list, - struct mlxsw_sp_acl_block_binding, list); + struct mlxsw_sp_flow_block_binding, list); in_port = binding->mlxsw_sp_port; return mlxsw_afa_block_append_mirror(rulei->act_block, @@ -775,7 +775,7 @@ int mlxsw_sp_acl_rule_add(struct mlxsw_sp *mlxsw_sp, { struct mlxsw_sp_acl_ruleset *ruleset = rule->ruleset; const struct mlxsw_sp_acl_profile_ops *ops = ruleset->ht_key.ops; - struct mlxsw_sp_acl_block *block = ruleset->ht_key.block; + struct mlxsw_sp_flow_block *block = ruleset->ht_key.block; int err; err = ops->rule_add(mlxsw_sp, ruleset->priv, rule->priv, rule->rulei); @@ -819,7 +819,7 @@ void mlxsw_sp_acl_rule_del(struct mlxsw_sp *mlxsw_sp, { struct mlxsw_sp_acl_ruleset *ruleset = rule->ruleset; const struct mlxsw_sp_acl_profile_ops *ops = ruleset->ht_key.ops; - struct mlxsw_sp_acl_block *block = ruleset->ht_key.block; + struct mlxsw_sp_flow_block *block = ruleset->ht_key.block; block->egress_blocker_rule_count -= rule->rulei->egress_bind_blocker; block->ingress_blocker_rule_count -= rule->rulei->ingress_bind_blocker; diff --git a/drivers/net/ethernet/mellanox/mlxsw/spectrum_flower.c b/drivers/net/ethernet/mellanox/mlxsw/spectrum_flower.c index 51117a5a6bbf..89c2e9820e95 100644 --- a/drivers/net/ethernet/mellanox/mlxsw/spectrum_flower.c +++ b/drivers/net/ethernet/mellanox/mlxsw/spectrum_flower.c @@ -15,7 +15,7 @@ #include "core_acl_flex_keys.h" static int mlxsw_sp_flower_parse_actions(struct mlxsw_sp *mlxsw_sp, - struct mlxsw_sp_acl_block *block, + struct mlxsw_sp_flow_block *block, struct mlxsw_sp_acl_rule_info *rulei, struct flow_action *flow_action, struct netlink_ext_ack *extack) @@ -53,11 +53,11 @@ static int mlxsw_sp_flower_parse_actions(struct mlxsw_sp *mlxsw_sp, case FLOW_ACTION_DROP: { bool ingress; - if (mlxsw_sp_acl_block_is_mixed_bound(block)) { + if (mlxsw_sp_flow_block_is_mixed_bound(block)) { NL_SET_ERR_MSG_MOD(extack, "Drop action is not supported when block is bound to ingress and egress"); return -EOPNOTSUPP; } - ingress = mlxsw_sp_acl_block_is_ingress_bound(block); + ingress = mlxsw_sp_flow_block_is_ingress_bound(block); err = mlxsw_sp_acl_rulei_act_drop(rulei, ingress, act->cookie, extack); if (err) { @@ -106,7 +106,7 @@ static int mlxsw_sp_flower_parse_actions(struct mlxsw_sp *mlxsw_sp, struct mlxsw_sp_fid *fid; u16 fid_index; - if (mlxsw_sp_acl_block_is_egress_bound(block)) { + if (mlxsw_sp_flow_block_is_egress_bound(block)) { NL_SET_ERR_MSG_MOD(extack, "Redirect action is not supported on egress"); return -EOPNOTSUPP; } @@ -190,7 +190,7 @@ static int mlxsw_sp_flower_parse_actions(struct mlxsw_sp *mlxsw_sp, static int mlxsw_sp_flower_parse_meta(struct mlxsw_sp_acl_rule_info *rulei, struct flow_cls_offload *f, - struct mlxsw_sp_acl_block *block) + struct mlxsw_sp_flow_block *block) { struct flow_rule *rule = flow_cls_offload_flow_rule(f); struct mlxsw_sp_port *mlxsw_sp_port; @@ -371,7 +371,7 @@ static int mlxsw_sp_flower_parse_ip(struct mlxsw_sp *mlxsw_sp, } static int mlxsw_sp_flower_parse(struct mlxsw_sp *mlxsw_sp, - struct mlxsw_sp_acl_block *block, + struct mlxsw_sp_flow_block *block, struct mlxsw_sp_acl_rule_info *rulei, struct flow_cls_offload *f) { @@ -460,7 +460,7 @@ static int mlxsw_sp_flower_parse(struct mlxsw_sp *mlxsw_sp, struct flow_match_vlan match; flow_rule_match_vlan(rule, &match); - if (mlxsw_sp_acl_block_is_egress_bound(block)) { + if (mlxsw_sp_flow_block_is_egress_bound(block)) { NL_SET_ERR_MSG_MOD(f->common.extack, "vlan_id key is not supported on egress"); return -EOPNOTSUPP; } @@ -505,7 +505,7 @@ static int mlxsw_sp_flower_parse(struct mlxsw_sp *mlxsw_sp, } int mlxsw_sp_flower_replace(struct mlxsw_sp *mlxsw_sp, - struct mlxsw_sp_acl_block *block, + struct mlxsw_sp_flow_block *block, struct flow_cls_offload *f) { struct mlxsw_sp_acl_rule_info *rulei; @@ -552,7 +552,7 @@ err_rule_create: } void mlxsw_sp_flower_destroy(struct mlxsw_sp *mlxsw_sp, - struct mlxsw_sp_acl_block *block, + struct mlxsw_sp_flow_block *block, struct flow_cls_offload *f) { struct mlxsw_sp_acl_ruleset *ruleset; @@ -574,7 +574,7 @@ void mlxsw_sp_flower_destroy(struct mlxsw_sp *mlxsw_sp, } int mlxsw_sp_flower_stats(struct mlxsw_sp *mlxsw_sp, - struct mlxsw_sp_acl_block *block, + struct mlxsw_sp_flow_block *block, struct flow_cls_offload *f) { enum flow_action_hw_stats used_hw_stats = FLOW_ACTION_HW_STATS_DISABLED; @@ -611,7 +611,7 @@ err_rule_get_stats: } int mlxsw_sp_flower_tmplt_create(struct mlxsw_sp *mlxsw_sp, - struct mlxsw_sp_acl_block *block, + struct mlxsw_sp_flow_block *block, struct flow_cls_offload *f) { struct mlxsw_sp_acl_ruleset *ruleset; @@ -632,7 +632,7 @@ int mlxsw_sp_flower_tmplt_create(struct mlxsw_sp *mlxsw_sp, } void mlxsw_sp_flower_tmplt_destroy(struct mlxsw_sp *mlxsw_sp, - struct mlxsw_sp_acl_block *block, + struct mlxsw_sp_flow_block *block, struct flow_cls_offload *f) { struct mlxsw_sp_acl_ruleset *ruleset; -- cgit From d52238eb7bcf53225841217af12fe1383205fcaa Mon Sep 17 00:00:00 2001 From: Jiri Pirko Date: Mon, 27 Apr 2020 18:13:00 +0300 Subject: mlxsw: spectrum: Push flow_block related functions into a separate file The code around flow_block is currently mixed in spectrum_acl.c. However, as it really does not directly relate to ACL part only, push the bits into a separate file. Signed-off-by: Jiri Pirko Signed-off-by: Ido Schimmel Signed-off-by: David S. Miller --- drivers/net/ethernet/mellanox/mlxsw/Makefile | 1 + drivers/net/ethernet/mellanox/mlxsw/spectrum.h | 34 ++++-- drivers/net/ethernet/mellanox/mlxsw/spectrum_acl.c | 131 +-------------------- .../net/ethernet/mellanox/mlxsw/spectrum_flow.c | 120 +++++++++++++++++++ 4 files changed, 151 insertions(+), 135 deletions(-) create mode 100644 drivers/net/ethernet/mellanox/mlxsw/spectrum_flow.c diff --git a/drivers/net/ethernet/mellanox/mlxsw/Makefile b/drivers/net/ethernet/mellanox/mlxsw/Makefile index 0e86a581d45b..59cbf02d6731 100644 --- a/drivers/net/ethernet/mellanox/mlxsw/Makefile +++ b/drivers/net/ethernet/mellanox/mlxsw/Makefile @@ -21,6 +21,7 @@ mlxsw_spectrum-objs := spectrum.o spectrum_buffers.o \ spectrum_acl_atcam.o spectrum_acl_erp.o \ spectrum1_acl_tcam.o spectrum2_acl_tcam.o \ spectrum_acl_bloom_filter.o spectrum_acl.o \ + spectrum_flow.o \ spectrum_flower.o spectrum_cnt.o \ spectrum_fid.o spectrum_ipip.o \ spectrum_acl_flex_actions.o \ diff --git a/drivers/net/ethernet/mellanox/mlxsw/spectrum.h b/drivers/net/ethernet/mellanox/mlxsw/spectrum.h index 65b1a2d87c2d..d4ef079aab4b 100644 --- a/drivers/net/ethernet/mellanox/mlxsw/spectrum.h +++ b/drivers/net/ethernet/mellanox/mlxsw/spectrum.h @@ -654,15 +654,7 @@ struct mlxsw_sp_acl_rule_info { unsigned int counter_index; }; -struct mlxsw_sp_flow_block; -struct mlxsw_sp_acl_ruleset; - -/* spectrum_acl.c */ -enum mlxsw_sp_acl_profile { - MLXSW_SP_ACL_PROFILE_FLOWER, - MLXSW_SP_ACL_PROFILE_MR, -}; - +/* spectrum_flow.c */ struct mlxsw_sp_flow_block { struct list_head binding_list; struct mlxsw_sp_acl_ruleset *ruleset_zero; @@ -676,7 +668,12 @@ struct mlxsw_sp_flow_block { struct net *net; }; -struct mlxsw_afk *mlxsw_sp_acl_afk(struct mlxsw_sp_acl *acl); +struct mlxsw_sp_flow_block_binding { + struct list_head list; + struct net_device *dev; + struct mlxsw_sp_port *mlxsw_sp_port; + bool ingress; +}; static inline struct mlxsw_sp * mlxsw_sp_flow_block_mlxsw_sp(struct mlxsw_sp_flow_block *block) @@ -740,6 +737,23 @@ int mlxsw_sp_flow_block_unbind(struct mlxsw_sp *mlxsw_sp, struct mlxsw_sp_flow_block *block, struct mlxsw_sp_port *mlxsw_sp_port, bool ingress); + +/* spectrum_acl.c */ +struct mlxsw_sp_acl_ruleset; + +enum mlxsw_sp_acl_profile { + MLXSW_SP_ACL_PROFILE_FLOWER, + MLXSW_SP_ACL_PROFILE_MR, +}; + +struct mlxsw_afk *mlxsw_sp_acl_afk(struct mlxsw_sp_acl *acl); + +int mlxsw_sp_acl_ruleset_bind(struct mlxsw_sp *mlxsw_sp, + struct mlxsw_sp_flow_block *block, + struct mlxsw_sp_flow_block_binding *binding); +void mlxsw_sp_acl_ruleset_unbind(struct mlxsw_sp *mlxsw_sp, + struct mlxsw_sp_flow_block *block, + struct mlxsw_sp_flow_block_binding *binding); struct mlxsw_sp_acl_ruleset * mlxsw_sp_acl_ruleset_lookup(struct mlxsw_sp *mlxsw_sp, struct mlxsw_sp_flow_block *block, u32 chain_index, diff --git a/drivers/net/ethernet/mellanox/mlxsw/spectrum_acl.c b/drivers/net/ethernet/mellanox/mlxsw/spectrum_acl.c index f9524cb95e9f..800eaa6be3c0 100644 --- a/drivers/net/ethernet/mellanox/mlxsw/spectrum_acl.c +++ b/drivers/net/ethernet/mellanox/mlxsw/spectrum_acl.c @@ -40,13 +40,6 @@ struct mlxsw_afk *mlxsw_sp_acl_afk(struct mlxsw_sp_acl *acl) return acl->afk; } -struct mlxsw_sp_flow_block_binding { - struct list_head list; - struct net_device *dev; - struct mlxsw_sp_port *mlxsw_sp_port; - bool ingress; -}; - struct mlxsw_sp_acl_ruleset_ht_key { struct mlxsw_sp_flow_block *block; u32 chain_index; @@ -101,10 +94,9 @@ mlxsw_sp_acl_ruleset_is_singular(const struct mlxsw_sp_acl_ruleset *ruleset) return ruleset->ref_count == 2; } -static int -mlxsw_sp_acl_ruleset_bind(struct mlxsw_sp *mlxsw_sp, - struct mlxsw_sp_flow_block *block, - struct mlxsw_sp_flow_block_binding *binding) +int mlxsw_sp_acl_ruleset_bind(struct mlxsw_sp *mlxsw_sp, + struct mlxsw_sp_flow_block *block, + struct mlxsw_sp_flow_block_binding *binding) { struct mlxsw_sp_acl_ruleset *ruleset = block->ruleset_zero; const struct mlxsw_sp_acl_profile_ops *ops = ruleset->ht_key.ops; @@ -113,10 +105,9 @@ mlxsw_sp_acl_ruleset_bind(struct mlxsw_sp *mlxsw_sp, binding->mlxsw_sp_port, binding->ingress); } -static void -mlxsw_sp_acl_ruleset_unbind(struct mlxsw_sp *mlxsw_sp, - struct mlxsw_sp_flow_block *block, - struct mlxsw_sp_flow_block_binding *binding) +void mlxsw_sp_acl_ruleset_unbind(struct mlxsw_sp *mlxsw_sp, + struct mlxsw_sp_flow_block *block, + struct mlxsw_sp_flow_block_binding *binding) { struct mlxsw_sp_acl_ruleset *ruleset = block->ruleset_zero; const struct mlxsw_sp_acl_profile_ops *ops = ruleset->ht_key.ops; @@ -125,12 +116,6 @@ mlxsw_sp_acl_ruleset_unbind(struct mlxsw_sp *mlxsw_sp, binding->mlxsw_sp_port, binding->ingress); } -static bool -mlxsw_sp_acl_ruleset_block_bound(const struct mlxsw_sp_flow_block *block) -{ - return block->ruleset_zero; -} - static int mlxsw_sp_acl_ruleset_block_bind(struct mlxsw_sp *mlxsw_sp, struct mlxsw_sp_acl_ruleset *ruleset, @@ -168,110 +153,6 @@ mlxsw_sp_acl_ruleset_block_unbind(struct mlxsw_sp *mlxsw_sp, block->ruleset_zero = NULL; } -struct mlxsw_sp_flow_block * -mlxsw_sp_flow_block_create(struct mlxsw_sp *mlxsw_sp, struct net *net) -{ - struct mlxsw_sp_flow_block *block; - - block = kzalloc(sizeof(*block), GFP_KERNEL); - if (!block) - return NULL; - INIT_LIST_HEAD(&block->binding_list); - block->mlxsw_sp = mlxsw_sp; - block->net = net; - return block; -} - -void mlxsw_sp_flow_block_destroy(struct mlxsw_sp_flow_block *block) -{ - WARN_ON(!list_empty(&block->binding_list)); - kfree(block); -} - -static struct mlxsw_sp_flow_block_binding * -mlxsw_sp_flow_block_lookup(struct mlxsw_sp_flow_block *block, - struct mlxsw_sp_port *mlxsw_sp_port, bool ingress) -{ - struct mlxsw_sp_flow_block_binding *binding; - - list_for_each_entry(binding, &block->binding_list, list) - if (binding->mlxsw_sp_port == mlxsw_sp_port && - binding->ingress == ingress) - return binding; - return NULL; -} - -int mlxsw_sp_flow_block_bind(struct mlxsw_sp *mlxsw_sp, - struct mlxsw_sp_flow_block *block, - struct mlxsw_sp_port *mlxsw_sp_port, - bool ingress, - struct netlink_ext_ack *extack) -{ - struct mlxsw_sp_flow_block_binding *binding; - int err; - - if (WARN_ON(mlxsw_sp_flow_block_lookup(block, mlxsw_sp_port, ingress))) - return -EEXIST; - - if (ingress && block->ingress_blocker_rule_count) { - NL_SET_ERR_MSG_MOD(extack, "Block cannot be bound to ingress because it contains unsupported rules"); - return -EOPNOTSUPP; - } - - if (!ingress && block->egress_blocker_rule_count) { - NL_SET_ERR_MSG_MOD(extack, "Block cannot be bound to egress because it contains unsupported rules"); - return -EOPNOTSUPP; - } - - binding = kzalloc(sizeof(*binding), GFP_KERNEL); - if (!binding) - return -ENOMEM; - binding->mlxsw_sp_port = mlxsw_sp_port; - binding->ingress = ingress; - - if (mlxsw_sp_acl_ruleset_block_bound(block)) { - err = mlxsw_sp_acl_ruleset_bind(mlxsw_sp, block, binding); - if (err) - goto err_ruleset_bind; - } - - if (ingress) - block->ingress_binding_count++; - else - block->egress_binding_count++; - list_add(&binding->list, &block->binding_list); - return 0; - -err_ruleset_bind: - kfree(binding); - return err; -} - -int mlxsw_sp_flow_block_unbind(struct mlxsw_sp *mlxsw_sp, - struct mlxsw_sp_flow_block *block, - struct mlxsw_sp_port *mlxsw_sp_port, - bool ingress) -{ - struct mlxsw_sp_flow_block_binding *binding; - - binding = mlxsw_sp_flow_block_lookup(block, mlxsw_sp_port, ingress); - if (!binding) - return -ENOENT; - - list_del(&binding->list); - - if (ingress) - block->ingress_binding_count--; - else - block->egress_binding_count--; - - if (mlxsw_sp_acl_ruleset_block_bound(block)) - mlxsw_sp_acl_ruleset_unbind(mlxsw_sp, block, binding); - - kfree(binding); - return 0; -} - static struct mlxsw_sp_acl_ruleset * mlxsw_sp_acl_ruleset_create(struct mlxsw_sp *mlxsw_sp, struct mlxsw_sp_flow_block *block, u32 chain_index, diff --git a/drivers/net/ethernet/mellanox/mlxsw/spectrum_flow.c b/drivers/net/ethernet/mellanox/mlxsw/spectrum_flow.c new file mode 100644 index 000000000000..655e1df5c95a --- /dev/null +++ b/drivers/net/ethernet/mellanox/mlxsw/spectrum_flow.c @@ -0,0 +1,120 @@ +// SPDX-License-Identifier: BSD-3-Clause OR GPL-2.0 +/* Copyright (c) 2017-2020 Mellanox Technologies. All rights reserved */ + +#include +#include +#include +#include +#include + +#include "spectrum.h" + +struct mlxsw_sp_flow_block * +mlxsw_sp_flow_block_create(struct mlxsw_sp *mlxsw_sp, struct net *net) +{ + struct mlxsw_sp_flow_block *block; + + block = kzalloc(sizeof(*block), GFP_KERNEL); + if (!block) + return NULL; + INIT_LIST_HEAD(&block->binding_list); + block->mlxsw_sp = mlxsw_sp; + block->net = net; + return block; +} + +void mlxsw_sp_flow_block_destroy(struct mlxsw_sp_flow_block *block) +{ + WARN_ON(!list_empty(&block->binding_list)); + kfree(block); +} + +static struct mlxsw_sp_flow_block_binding * +mlxsw_sp_flow_block_lookup(struct mlxsw_sp_flow_block *block, + struct mlxsw_sp_port *mlxsw_sp_port, bool ingress) +{ + struct mlxsw_sp_flow_block_binding *binding; + + list_for_each_entry(binding, &block->binding_list, list) + if (binding->mlxsw_sp_port == mlxsw_sp_port && + binding->ingress == ingress) + return binding; + return NULL; +} + +static bool +mlxsw_sp_flow_block_ruleset_bound(const struct mlxsw_sp_flow_block *block) +{ + return block->ruleset_zero; +} + +int mlxsw_sp_flow_block_bind(struct mlxsw_sp *mlxsw_sp, + struct mlxsw_sp_flow_block *block, + struct mlxsw_sp_port *mlxsw_sp_port, + bool ingress, + struct netlink_ext_ack *extack) +{ + struct mlxsw_sp_flow_block_binding *binding; + int err; + + if (WARN_ON(mlxsw_sp_flow_block_lookup(block, mlxsw_sp_port, ingress))) + return -EEXIST; + + if (ingress && block->ingress_blocker_rule_count) { + NL_SET_ERR_MSG_MOD(extack, "Block cannot be bound to ingress because it contains unsupported rules"); + return -EOPNOTSUPP; + } + + if (!ingress && block->egress_blocker_rule_count) { + NL_SET_ERR_MSG_MOD(extack, "Block cannot be bound to egress because it contains unsupported rules"); + return -EOPNOTSUPP; + } + + binding = kzalloc(sizeof(*binding), GFP_KERNEL); + if (!binding) + return -ENOMEM; + binding->mlxsw_sp_port = mlxsw_sp_port; + binding->ingress = ingress; + + if (mlxsw_sp_flow_block_ruleset_bound(block)) { + err = mlxsw_sp_acl_ruleset_bind(mlxsw_sp, block, binding); + if (err) + goto err_ruleset_bind; + } + + if (ingress) + block->ingress_binding_count++; + else + block->egress_binding_count++; + list_add(&binding->list, &block->binding_list); + return 0; + +err_ruleset_bind: + kfree(binding); + return err; +} + +int mlxsw_sp_flow_block_unbind(struct mlxsw_sp *mlxsw_sp, + struct mlxsw_sp_flow_block *block, + struct mlxsw_sp_port *mlxsw_sp_port, + bool ingress) +{ + struct mlxsw_sp_flow_block_binding *binding; + + binding = mlxsw_sp_flow_block_lookup(block, mlxsw_sp_port, ingress); + if (!binding) + return -ENOENT; + + list_del(&binding->list); + + if (ingress) + block->ingress_binding_count--; + else + block->egress_binding_count--; + + if (mlxsw_sp_flow_block_ruleset_bound(block)) + mlxsw_sp_acl_ruleset_unbind(mlxsw_sp, block, binding); + + kfree(binding); + return 0; +} -- cgit From d7fcc986224d77c4ab66f436e7eaa11170c509af Mon Sep 17 00:00:00 2001 From: Jiri Pirko Date: Mon, 27 Apr 2020 18:13:01 +0300 Subject: mlxsw: spectrum: Push matchall bits into a separate file Similar to flower, have matchall related code in a separate file. Do some small renaming on the way (consistent "mall" prefixes, dropped "_tc_", dropped "_port_" where suitable). Signed-off-by: Jiri Pirko Signed-off-by: Ido Schimmel Signed-off-by: David S. Miller --- drivers/net/ethernet/mellanox/mlxsw/Makefile | 2 +- drivers/net/ethernet/mellanox/mlxsw/spectrum.c | 186 +------------------ drivers/net/ethernet/mellanox/mlxsw/spectrum.h | 28 +-- .../ethernet/mellanox/mlxsw/spectrum_matchall.c | 202 +++++++++++++++++++++ 4 files changed, 214 insertions(+), 204 deletions(-) create mode 100644 drivers/net/ethernet/mellanox/mlxsw/spectrum_matchall.c diff --git a/drivers/net/ethernet/mellanox/mlxsw/Makefile b/drivers/net/ethernet/mellanox/mlxsw/Makefile index 59cbf02d6731..4aeabb35c943 100644 --- a/drivers/net/ethernet/mellanox/mlxsw/Makefile +++ b/drivers/net/ethernet/mellanox/mlxsw/Makefile @@ -21,7 +21,7 @@ mlxsw_spectrum-objs := spectrum.o spectrum_buffers.o \ spectrum_acl_atcam.o spectrum_acl_erp.o \ spectrum1_acl_tcam.o spectrum2_acl_tcam.o \ spectrum_acl_bloom_filter.o spectrum_acl.o \ - spectrum_flow.o \ + spectrum_flow.o spectrum_matchall.o \ spectrum_flower.o spectrum_cnt.o \ spectrum_fid.o spectrum_ipip.o \ spectrum_acl_flex_actions.o \ diff --git a/drivers/net/ethernet/mellanox/mlxsw/spectrum.c b/drivers/net/ethernet/mellanox/mlxsw/spectrum.c index f64e8da21d4a..ff25f8fc55e9 100644 --- a/drivers/net/ethernet/mellanox/mlxsw/spectrum.c +++ b/drivers/net/ethernet/mellanox/mlxsw/spectrum.c @@ -25,9 +25,7 @@ #include #include #include -#include #include -#include #include #include "spectrum.h" @@ -582,16 +580,6 @@ static int mlxsw_sp_base_mac_get(struct mlxsw_sp *mlxsw_sp) return 0; } -static int mlxsw_sp_port_sample_set(struct mlxsw_sp_port *mlxsw_sp_port, - bool enable, u32 rate) -{ - struct mlxsw_sp *mlxsw_sp = mlxsw_sp_port->mlxsw_sp; - char mpsc_pl[MLXSW_REG_MPSC_LEN]; - - mlxsw_reg_mpsc_pack(mpsc_pl, mlxsw_sp_port->local_port, enable, rate); - return mlxsw_reg_write(mlxsw_sp->core, MLXSW_REG(mpsc), mpsc_pl); -} - static int mlxsw_sp_port_admin_status_set(struct mlxsw_sp_port *mlxsw_sp_port, bool is_up) { @@ -1362,181 +1350,15 @@ static int mlxsw_sp_port_kill_vid(struct net_device *dev, return 0; } -static struct mlxsw_sp_port_mall_tc_entry * -mlxsw_sp_port_mall_tc_entry_find(struct mlxsw_sp_port *port, - unsigned long cookie) { - struct mlxsw_sp_port_mall_tc_entry *mall_tc_entry; - - list_for_each_entry(mall_tc_entry, &port->mall_tc_list, list) - if (mall_tc_entry->cookie == cookie) - return mall_tc_entry; - - return NULL; -} - -static int -mlxsw_sp_port_add_cls_matchall_mirror(struct mlxsw_sp_port *mlxsw_sp_port, - struct mlxsw_sp_port_mall_mirror_tc_entry *mirror, - const struct flow_action_entry *act, - bool ingress) -{ - enum mlxsw_sp_span_type span_type; - - if (!act->dev) { - netdev_err(mlxsw_sp_port->dev, "Could not find requested device\n"); - return -EINVAL; - } - - mirror->ingress = ingress; - span_type = ingress ? MLXSW_SP_SPAN_INGRESS : MLXSW_SP_SPAN_EGRESS; - return mlxsw_sp_span_mirror_add(mlxsw_sp_port, act->dev, span_type, - true, &mirror->span_id); -} - -static void -mlxsw_sp_port_del_cls_matchall_mirror(struct mlxsw_sp_port *mlxsw_sp_port, - struct mlxsw_sp_port_mall_mirror_tc_entry *mirror) -{ - enum mlxsw_sp_span_type span_type; - - span_type = mirror->ingress ? - MLXSW_SP_SPAN_INGRESS : MLXSW_SP_SPAN_EGRESS; - mlxsw_sp_span_mirror_del(mlxsw_sp_port, mirror->span_id, - span_type, true); -} - -static int -mlxsw_sp_port_add_cls_matchall_sample(struct mlxsw_sp_port *mlxsw_sp_port, - struct tc_cls_matchall_offload *cls, - const struct flow_action_entry *act, - bool ingress) -{ - int err; - - if (!mlxsw_sp_port->sample) - return -EOPNOTSUPP; - if (rtnl_dereference(mlxsw_sp_port->sample->psample_group)) { - netdev_err(mlxsw_sp_port->dev, "sample already active\n"); - return -EEXIST; - } - if (act->sample.rate > MLXSW_REG_MPSC_RATE_MAX) { - netdev_err(mlxsw_sp_port->dev, "sample rate not supported\n"); - return -EOPNOTSUPP; - } - - rcu_assign_pointer(mlxsw_sp_port->sample->psample_group, - act->sample.psample_group); - mlxsw_sp_port->sample->truncate = act->sample.truncate; - mlxsw_sp_port->sample->trunc_size = act->sample.trunc_size; - mlxsw_sp_port->sample->rate = act->sample.rate; - - err = mlxsw_sp_port_sample_set(mlxsw_sp_port, true, act->sample.rate); - if (err) - goto err_port_sample_set; - return 0; - -err_port_sample_set: - RCU_INIT_POINTER(mlxsw_sp_port->sample->psample_group, NULL); - return err; -} - -static void -mlxsw_sp_port_del_cls_matchall_sample(struct mlxsw_sp_port *mlxsw_sp_port) -{ - if (!mlxsw_sp_port->sample) - return; - - mlxsw_sp_port_sample_set(mlxsw_sp_port, false, 1); - RCU_INIT_POINTER(mlxsw_sp_port->sample->psample_group, NULL); -} - -static int mlxsw_sp_port_add_cls_matchall(struct mlxsw_sp_port *mlxsw_sp_port, - struct tc_cls_matchall_offload *f, - bool ingress) -{ - struct mlxsw_sp_port_mall_tc_entry *mall_tc_entry; - __be16 protocol = f->common.protocol; - struct flow_action_entry *act; - int err; - - if (!flow_offload_has_one_action(&f->rule->action)) { - netdev_err(mlxsw_sp_port->dev, "only singular actions are supported\n"); - return -EOPNOTSUPP; - } - - mall_tc_entry = kzalloc(sizeof(*mall_tc_entry), GFP_KERNEL); - if (!mall_tc_entry) - return -ENOMEM; - mall_tc_entry->cookie = f->cookie; - - act = &f->rule->action.entries[0]; - - if (act->id == FLOW_ACTION_MIRRED && protocol == htons(ETH_P_ALL)) { - struct mlxsw_sp_port_mall_mirror_tc_entry *mirror; - - mall_tc_entry->type = MLXSW_SP_PORT_MALL_MIRROR; - mirror = &mall_tc_entry->mirror; - err = mlxsw_sp_port_add_cls_matchall_mirror(mlxsw_sp_port, - mirror, act, - ingress); - } else if (act->id == FLOW_ACTION_SAMPLE && - protocol == htons(ETH_P_ALL)) { - mall_tc_entry->type = MLXSW_SP_PORT_MALL_SAMPLE; - err = mlxsw_sp_port_add_cls_matchall_sample(mlxsw_sp_port, f, - act, ingress); - } else { - err = -EOPNOTSUPP; - } - - if (err) - goto err_add_action; - - list_add_tail(&mall_tc_entry->list, &mlxsw_sp_port->mall_tc_list); - return 0; - -err_add_action: - kfree(mall_tc_entry); - return err; -} - -static void mlxsw_sp_port_del_cls_matchall(struct mlxsw_sp_port *mlxsw_sp_port, - struct tc_cls_matchall_offload *f) -{ - struct mlxsw_sp_port_mall_tc_entry *mall_tc_entry; - - mall_tc_entry = mlxsw_sp_port_mall_tc_entry_find(mlxsw_sp_port, - f->cookie); - if (!mall_tc_entry) { - netdev_dbg(mlxsw_sp_port->dev, "tc entry not found on port\n"); - return; - } - list_del(&mall_tc_entry->list); - - switch (mall_tc_entry->type) { - case MLXSW_SP_PORT_MALL_MIRROR: - mlxsw_sp_port_del_cls_matchall_mirror(mlxsw_sp_port, - &mall_tc_entry->mirror); - break; - case MLXSW_SP_PORT_MALL_SAMPLE: - mlxsw_sp_port_del_cls_matchall_sample(mlxsw_sp_port); - break; - default: - WARN_ON(1); - } - - kfree(mall_tc_entry); -} - static int mlxsw_sp_setup_tc_cls_matchall(struct mlxsw_sp_port *mlxsw_sp_port, struct tc_cls_matchall_offload *f, bool ingress) { switch (f->command) { case TC_CLSMATCHALL_REPLACE: - return mlxsw_sp_port_add_cls_matchall(mlxsw_sp_port, f, - ingress); + return mlxsw_sp_mall_replace(mlxsw_sp_port, f, ingress); case TC_CLSMATCHALL_DESTROY: - mlxsw_sp_port_del_cls_matchall(mlxsw_sp_port, f); + mlxsw_sp_mall_destroy(mlxsw_sp_port, f); return 0; default: return -EOPNOTSUPP; @@ -1800,7 +1622,7 @@ static int mlxsw_sp_feature_hw_tc(struct net_device *dev, bool enable) if (!enable) { if (mlxsw_sp_flow_block_rule_count(mlxsw_sp_port->ing_flow_block) || mlxsw_sp_flow_block_rule_count(mlxsw_sp_port->eg_flow_block) || - !list_empty(&mlxsw_sp_port->mall_tc_list)) { + !list_empty(&mlxsw_sp_port->mall_list)) { netdev_err(dev, "Active offloaded tc filters, can't turn hw_tc_offload off\n"); return -EINVAL; } @@ -3696,7 +3518,7 @@ static int mlxsw_sp_port_create(struct mlxsw_sp *mlxsw_sp, u8 local_port, mlxsw_sp_port->mapping = *port_mapping; mlxsw_sp_port->link.autoneg = 1; INIT_LIST_HEAD(&mlxsw_sp_port->vlans_list); - INIT_LIST_HEAD(&mlxsw_sp_port->mall_tc_list); + INIT_LIST_HEAD(&mlxsw_sp_port->mall_list); mlxsw_sp_port->pcpu_stats = netdev_alloc_pcpu_stats(struct mlxsw_sp_port_pcpu_stats); diff --git a/drivers/net/ethernet/mellanox/mlxsw/spectrum.h b/drivers/net/ethernet/mellanox/mlxsw/spectrum.h index d4ef079aab4b..5c2f1af53e53 100644 --- a/drivers/net/ethernet/mellanox/mlxsw/spectrum.h +++ b/drivers/net/ethernet/mellanox/mlxsw/spectrum.h @@ -109,25 +109,6 @@ struct mlxsw_sp_mid { unsigned long *ports_in_mid; /* bits array */ }; -enum mlxsw_sp_port_mall_action_type { - MLXSW_SP_PORT_MALL_MIRROR, - MLXSW_SP_PORT_MALL_SAMPLE, -}; - -struct mlxsw_sp_port_mall_mirror_tc_entry { - int span_id; - bool ingress; -}; - -struct mlxsw_sp_port_mall_tc_entry { - struct list_head list; - unsigned long cookie; - enum mlxsw_sp_port_mall_action_type type; - union { - struct mlxsw_sp_port_mall_mirror_tc_entry mirror; - }; -}; - struct mlxsw_sp_sb; struct mlxsw_sp_bridge; struct mlxsw_sp_router; @@ -274,8 +255,7 @@ struct mlxsw_sp_port { * the same localport can have * different mapping. */ - /* TC handles */ - struct list_head mall_tc_list; + struct list_head mall_list; struct { #define MLXSW_HW_STATS_UPDATE_TIME HZ struct rtnl_link_stats64 stats; @@ -913,6 +893,12 @@ extern const struct mlxsw_afa_ops mlxsw_sp2_act_afa_ops; extern const struct mlxsw_afk_ops mlxsw_sp1_afk_ops; extern const struct mlxsw_afk_ops mlxsw_sp2_afk_ops; +/* spectrum_matchall.c */ +int mlxsw_sp_mall_replace(struct mlxsw_sp_port *mlxsw_sp_port, + struct tc_cls_matchall_offload *f, bool ingress); +void mlxsw_sp_mall_destroy(struct mlxsw_sp_port *mlxsw_sp_port, + struct tc_cls_matchall_offload *f); + /* spectrum_flower.c */ int mlxsw_sp_flower_replace(struct mlxsw_sp *mlxsw_sp, struct mlxsw_sp_flow_block *block, diff --git a/drivers/net/ethernet/mellanox/mlxsw/spectrum_matchall.c b/drivers/net/ethernet/mellanox/mlxsw/spectrum_matchall.c new file mode 100644 index 000000000000..56f21cfdb48e --- /dev/null +++ b/drivers/net/ethernet/mellanox/mlxsw/spectrum_matchall.c @@ -0,0 +1,202 @@ +// SPDX-License-Identifier: BSD-3-Clause OR GPL-2.0 +/* Copyright (c) 2017-2020 Mellanox Technologies. All rights reserved */ + +#include +#include +#include +#include + +#include "spectrum.h" +#include "spectrum_span.h" +#include "reg.h" + +enum mlxsw_sp_mall_action_type { + MLXSW_SP_MALL_ACTION_TYPE_MIRROR, + MLXSW_SP_MALL_ACTION_TYPE_SAMPLE, +}; + +struct mlxsw_sp_mall_mirror_entry { + int span_id; + bool ingress; +}; + +struct mlxsw_sp_mall_entry { + struct list_head list; + unsigned long cookie; + enum mlxsw_sp_mall_action_type type; + union { + struct mlxsw_sp_mall_mirror_entry mirror; + }; +}; + +static struct mlxsw_sp_mall_entry * +mlxsw_sp_mall_entry_find(struct mlxsw_sp_port *port, unsigned long cookie) +{ + struct mlxsw_sp_mall_entry *mall_entry; + + list_for_each_entry(mall_entry, &port->mall_list, list) + if (mall_entry->cookie == cookie) + return mall_entry; + + return NULL; +} + +static int +mlxsw_sp_mall_port_mirror_add(struct mlxsw_sp_port *mlxsw_sp_port, + struct mlxsw_sp_mall_mirror_entry *mirror, + const struct flow_action_entry *act, + bool ingress) +{ + enum mlxsw_sp_span_type span_type; + + if (!act->dev) { + netdev_err(mlxsw_sp_port->dev, "Could not find requested device\n"); + return -EINVAL; + } + + mirror->ingress = ingress; + span_type = ingress ? MLXSW_SP_SPAN_INGRESS : MLXSW_SP_SPAN_EGRESS; + return mlxsw_sp_span_mirror_add(mlxsw_sp_port, act->dev, span_type, + true, &mirror->span_id); +} + +static void +mlxsw_sp_mall_port_mirror_del(struct mlxsw_sp_port *mlxsw_sp_port, + struct mlxsw_sp_mall_mirror_entry *mirror) +{ + enum mlxsw_sp_span_type span_type; + + span_type = mirror->ingress ? MLXSW_SP_SPAN_INGRESS : + MLXSW_SP_SPAN_EGRESS; + mlxsw_sp_span_mirror_del(mlxsw_sp_port, mirror->span_id, + span_type, true); +} + +static int mlxsw_sp_mall_port_sample_set(struct mlxsw_sp_port *mlxsw_sp_port, + bool enable, u32 rate) +{ + struct mlxsw_sp *mlxsw_sp = mlxsw_sp_port->mlxsw_sp; + char mpsc_pl[MLXSW_REG_MPSC_LEN]; + + mlxsw_reg_mpsc_pack(mpsc_pl, mlxsw_sp_port->local_port, enable, rate); + return mlxsw_reg_write(mlxsw_sp->core, MLXSW_REG(mpsc), mpsc_pl); +} + +static int +mlxsw_sp_mall_port_sample_add(struct mlxsw_sp_port *mlxsw_sp_port, + struct tc_cls_matchall_offload *cls, + const struct flow_action_entry *act, bool ingress) +{ + int err; + + if (!mlxsw_sp_port->sample) + return -EOPNOTSUPP; + if (rtnl_dereference(mlxsw_sp_port->sample->psample_group)) { + netdev_err(mlxsw_sp_port->dev, "sample already active\n"); + return -EEXIST; + } + if (act->sample.rate > MLXSW_REG_MPSC_RATE_MAX) { + netdev_err(mlxsw_sp_port->dev, "sample rate not supported\n"); + return -EOPNOTSUPP; + } + + rcu_assign_pointer(mlxsw_sp_port->sample->psample_group, + act->sample.psample_group); + mlxsw_sp_port->sample->truncate = act->sample.truncate; + mlxsw_sp_port->sample->trunc_size = act->sample.trunc_size; + mlxsw_sp_port->sample->rate = act->sample.rate; + + err = mlxsw_sp_mall_port_sample_set(mlxsw_sp_port, true, + act->sample.rate); + if (err) + goto err_port_sample_set; + return 0; + +err_port_sample_set: + RCU_INIT_POINTER(mlxsw_sp_port->sample->psample_group, NULL); + return err; +} + +static void +mlxsw_sp_mall_port_sample_del(struct mlxsw_sp_port *mlxsw_sp_port) +{ + if (!mlxsw_sp_port->sample) + return; + + mlxsw_sp_mall_port_sample_set(mlxsw_sp_port, false, 1); + RCU_INIT_POINTER(mlxsw_sp_port->sample->psample_group, NULL); +} + +int mlxsw_sp_mall_replace(struct mlxsw_sp_port *mlxsw_sp_port, + struct tc_cls_matchall_offload *f, bool ingress) +{ + struct mlxsw_sp_mall_entry *mall_entry; + __be16 protocol = f->common.protocol; + struct flow_action_entry *act; + int err; + + if (!flow_offload_has_one_action(&f->rule->action)) { + netdev_err(mlxsw_sp_port->dev, "only singular actions are supported\n"); + return -EOPNOTSUPP; + } + + mall_entry = kzalloc(sizeof(*mall_entry), GFP_KERNEL); + if (!mall_entry) + return -ENOMEM; + mall_entry->cookie = f->cookie; + + act = &f->rule->action.entries[0]; + + if (act->id == FLOW_ACTION_MIRRED && protocol == htons(ETH_P_ALL)) { + struct mlxsw_sp_mall_mirror_entry *mirror; + + mall_entry->type = MLXSW_SP_MALL_ACTION_TYPE_MIRROR; + mirror = &mall_entry->mirror; + err = mlxsw_sp_mall_port_mirror_add(mlxsw_sp_port, mirror, act, + ingress); + } else if (act->id == FLOW_ACTION_SAMPLE && + protocol == htons(ETH_P_ALL)) { + mall_entry->type = MLXSW_SP_MALL_ACTION_TYPE_SAMPLE; + err = mlxsw_sp_mall_port_sample_add(mlxsw_sp_port, f, act, + ingress); + } else { + err = -EOPNOTSUPP; + } + + if (err) + goto err_add_action; + + list_add_tail(&mall_entry->list, &mlxsw_sp_port->mall_list); + return 0; + +err_add_action: + kfree(mall_entry); + return err; +} + +void mlxsw_sp_mall_destroy(struct mlxsw_sp_port *mlxsw_sp_port, + struct tc_cls_matchall_offload *f) +{ + struct mlxsw_sp_mall_entry *mall_entry; + + mall_entry = mlxsw_sp_mall_entry_find(mlxsw_sp_port, f->cookie); + if (!mall_entry) { + netdev_dbg(mlxsw_sp_port->dev, "tc entry not found on port\n"); + return; + } + list_del(&mall_entry->list); + + switch (mall_entry->type) { + case MLXSW_SP_MALL_ACTION_TYPE_MIRROR: + mlxsw_sp_mall_port_mirror_del(mlxsw_sp_port, + &mall_entry->mirror); + break; + case MLXSW_SP_MALL_ACTION_TYPE_SAMPLE: + mlxsw_sp_mall_port_sample_del(mlxsw_sp_port); + break; + default: + WARN_ON(1); + } + + kfree(mall_entry); +} -- cgit From 6c8cd435b58780ded6e3e06d722249ec181efb36 Mon Sep 17 00:00:00 2001 From: Jiri Pirko Date: Mon, 27 Apr 2020 18:13:02 +0300 Subject: mlxsw: spectrum_acl: Use block variable in mlxsw_sp_acl_rule_del() On couple of places in mlxsw_sp_acl_rule_del(), block variable is not used directly as it could be. So do it. Signed-off-by: Jiri Pirko Signed-off-by: Ido Schimmel Signed-off-by: David S. Miller --- drivers/net/ethernet/mellanox/mlxsw/spectrum_acl.c | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/drivers/net/ethernet/mellanox/mlxsw/spectrum_acl.c b/drivers/net/ethernet/mellanox/mlxsw/spectrum_acl.c index 800eaa6be3c0..c61f78e30397 100644 --- a/drivers/net/ethernet/mellanox/mlxsw/spectrum_acl.c +++ b/drivers/net/ethernet/mellanox/mlxsw/spectrum_acl.c @@ -704,14 +704,13 @@ void mlxsw_sp_acl_rule_del(struct mlxsw_sp *mlxsw_sp, block->egress_blocker_rule_count -= rule->rulei->egress_bind_blocker; block->ingress_blocker_rule_count -= rule->rulei->ingress_bind_blocker; - ruleset->ht_key.block->rule_count--; + block->rule_count--; mutex_lock(&mlxsw_sp->acl->rules_lock); list_del(&rule->list); mutex_unlock(&mlxsw_sp->acl->rules_lock); if (!ruleset->ht_key.chain_index && mlxsw_sp_acl_ruleset_is_singular(ruleset)) - mlxsw_sp_acl_ruleset_block_unbind(mlxsw_sp, ruleset, - ruleset->ht_key.block); + mlxsw_sp_acl_ruleset_block_unbind(mlxsw_sp, ruleset, block); rhashtable_remove_fast(&ruleset->rule_ht, &rule->ht_node, mlxsw_sp_acl_rule_ht_params); ops->rule_del(mlxsw_sp, rule->priv); -- cgit From 780ba878a1b024e176dc27c980e1600a23d7b5c5 Mon Sep 17 00:00:00 2001 From: Jiri Pirko Date: Mon, 27 Apr 2020 18:13:03 +0300 Subject: mlxsw: spectrum_matchall: Pass mall_entry as arg to mlxsw_sp_mall_port_mirror_add() In the preparation for future changes, have the mlxsw_sp_mall_port_mirror_add() function to accept mall_entry including the "to_dev" originally obtained from act pointer. Signed-off-by: Jiri Pirko Signed-off-by: Ido Schimmel Signed-off-by: David S. Miller --- .../ethernet/mellanox/mlxsw/spectrum_matchall.c | 34 +++++++++++----------- 1 file changed, 17 insertions(+), 17 deletions(-) diff --git a/drivers/net/ethernet/mellanox/mlxsw/spectrum_matchall.c b/drivers/net/ethernet/mellanox/mlxsw/spectrum_matchall.c index 56f21cfdb48e..b57267f0c9a1 100644 --- a/drivers/net/ethernet/mellanox/mlxsw/spectrum_matchall.c +++ b/drivers/net/ethernet/mellanox/mlxsw/spectrum_matchall.c @@ -16,6 +16,7 @@ enum mlxsw_sp_mall_action_type { }; struct mlxsw_sp_mall_mirror_entry { + const struct net_device *to_dev; int span_id; bool ingress; }; @@ -43,32 +44,34 @@ mlxsw_sp_mall_entry_find(struct mlxsw_sp_port *port, unsigned long cookie) static int mlxsw_sp_mall_port_mirror_add(struct mlxsw_sp_port *mlxsw_sp_port, - struct mlxsw_sp_mall_mirror_entry *mirror, - const struct flow_action_entry *act, + struct mlxsw_sp_mall_entry *mall_entry, bool ingress) { enum mlxsw_sp_span_type span_type; - if (!act->dev) { + if (!mall_entry->mirror.to_dev) { netdev_err(mlxsw_sp_port->dev, "Could not find requested device\n"); return -EINVAL; } - mirror->ingress = ingress; - span_type = ingress ? MLXSW_SP_SPAN_INGRESS : MLXSW_SP_SPAN_EGRESS; - return mlxsw_sp_span_mirror_add(mlxsw_sp_port, act->dev, span_type, - true, &mirror->span_id); + mall_entry->mirror.ingress = ingress; + span_type = mall_entry->mirror.ingress ? MLXSW_SP_SPAN_INGRESS : + MLXSW_SP_SPAN_EGRESS; + return mlxsw_sp_span_mirror_add(mlxsw_sp_port, + mall_entry->mirror.to_dev, + span_type, true, + &mall_entry->mirror.span_id); } static void mlxsw_sp_mall_port_mirror_del(struct mlxsw_sp_port *mlxsw_sp_port, - struct mlxsw_sp_mall_mirror_entry *mirror) + struct mlxsw_sp_mall_entry *mall_entry) { enum mlxsw_sp_span_type span_type; - span_type = mirror->ingress ? MLXSW_SP_SPAN_INGRESS : - MLXSW_SP_SPAN_EGRESS; - mlxsw_sp_span_mirror_del(mlxsw_sp_port, mirror->span_id, + span_type = mall_entry->mirror.ingress ? MLXSW_SP_SPAN_INGRESS : + MLXSW_SP_SPAN_EGRESS; + mlxsw_sp_span_mirror_del(mlxsw_sp_port, mall_entry->mirror.span_id, span_type, true); } @@ -148,11 +151,9 @@ int mlxsw_sp_mall_replace(struct mlxsw_sp_port *mlxsw_sp_port, act = &f->rule->action.entries[0]; if (act->id == FLOW_ACTION_MIRRED && protocol == htons(ETH_P_ALL)) { - struct mlxsw_sp_mall_mirror_entry *mirror; - mall_entry->type = MLXSW_SP_MALL_ACTION_TYPE_MIRROR; - mirror = &mall_entry->mirror; - err = mlxsw_sp_mall_port_mirror_add(mlxsw_sp_port, mirror, act, + mall_entry->mirror.to_dev = act->dev; + err = mlxsw_sp_mall_port_mirror_add(mlxsw_sp_port, mall_entry, ingress); } else if (act->id == FLOW_ACTION_SAMPLE && protocol == htons(ETH_P_ALL)) { @@ -188,8 +189,7 @@ void mlxsw_sp_mall_destroy(struct mlxsw_sp_port *mlxsw_sp_port, switch (mall_entry->type) { case MLXSW_SP_MALL_ACTION_TYPE_MIRROR: - mlxsw_sp_mall_port_mirror_del(mlxsw_sp_port, - &mall_entry->mirror); + mlxsw_sp_mall_port_mirror_del(mlxsw_sp_port, mall_entry); break; case MLXSW_SP_MALL_ACTION_TYPE_SAMPLE: mlxsw_sp_mall_port_sample_del(mlxsw_sp_port); -- cgit From c7ea0e162fc84602fde67d41edf72ae3f4f4a14f Mon Sep 17 00:00:00 2001 From: Jiri Pirko Date: Mon, 27 Apr 2020 18:13:04 +0300 Subject: mlxsw: spectrum_matchall: Pass mall_entry as arg to mlxsw_sp_mall_port_sample_add() In the preparation for future changes, have the mlxsw_sp_mall_port_sample_add() function to accept mall_entry including all needed info originally obtained from cls and act pointers. Signed-off-by: Jiri Pirko Signed-off-by: Ido Schimmel Signed-off-by: David S. Miller --- .../ethernet/mellanox/mlxsw/spectrum_matchall.c | 35 ++++++++++++---------- 1 file changed, 19 insertions(+), 16 deletions(-) diff --git a/drivers/net/ethernet/mellanox/mlxsw/spectrum_matchall.c b/drivers/net/ethernet/mellanox/mlxsw/spectrum_matchall.c index b57267f0c9a1..adaaee208655 100644 --- a/drivers/net/ethernet/mellanox/mlxsw/spectrum_matchall.c +++ b/drivers/net/ethernet/mellanox/mlxsw/spectrum_matchall.c @@ -27,6 +27,7 @@ struct mlxsw_sp_mall_entry { enum mlxsw_sp_mall_action_type type; union { struct mlxsw_sp_mall_mirror_entry mirror; + struct mlxsw_sp_port_sample sample; }; }; @@ -87,8 +88,7 @@ static int mlxsw_sp_mall_port_sample_set(struct mlxsw_sp_port *mlxsw_sp_port, static int mlxsw_sp_mall_port_sample_add(struct mlxsw_sp_port *mlxsw_sp_port, - struct tc_cls_matchall_offload *cls, - const struct flow_action_entry *act, bool ingress) + struct mlxsw_sp_mall_entry *mall_entry) { int err; @@ -98,19 +98,14 @@ mlxsw_sp_mall_port_sample_add(struct mlxsw_sp_port *mlxsw_sp_port, netdev_err(mlxsw_sp_port->dev, "sample already active\n"); return -EEXIST; } - if (act->sample.rate > MLXSW_REG_MPSC_RATE_MAX) { - netdev_err(mlxsw_sp_port->dev, "sample rate not supported\n"); - return -EOPNOTSUPP; - } - rcu_assign_pointer(mlxsw_sp_port->sample->psample_group, - act->sample.psample_group); - mlxsw_sp_port->sample->truncate = act->sample.truncate; - mlxsw_sp_port->sample->trunc_size = act->sample.trunc_size; - mlxsw_sp_port->sample->rate = act->sample.rate; + mall_entry->sample.psample_group); + mlxsw_sp_port->sample->truncate = mall_entry->sample.truncate; + mlxsw_sp_port->sample->trunc_size = mall_entry->sample.trunc_size; + mlxsw_sp_port->sample->rate = mall_entry->sample.rate; err = mlxsw_sp_mall_port_sample_set(mlxsw_sp_port, true, - act->sample.rate); + mall_entry->sample.rate); if (err) goto err_port_sample_set; return 0; @@ -157,20 +152,28 @@ int mlxsw_sp_mall_replace(struct mlxsw_sp_port *mlxsw_sp_port, ingress); } else if (act->id == FLOW_ACTION_SAMPLE && protocol == htons(ETH_P_ALL)) { + if (act->sample.rate > MLXSW_REG_MPSC_RATE_MAX) { + netdev_err(mlxsw_sp_port->dev, "sample rate not supported\n"); + err = -EOPNOTSUPP; + goto errout; + } mall_entry->type = MLXSW_SP_MALL_ACTION_TYPE_SAMPLE; - err = mlxsw_sp_mall_port_sample_add(mlxsw_sp_port, f, act, - ingress); + mall_entry->sample.psample_group = act->sample.psample_group; + mall_entry->sample.truncate = act->sample.truncate; + mall_entry->sample.trunc_size = act->sample.trunc_size; + mall_entry->sample.rate = act->sample.rate; + err = mlxsw_sp_mall_port_sample_add(mlxsw_sp_port, mall_entry); } else { err = -EOPNOTSUPP; } if (err) - goto err_add_action; + goto errout; list_add_tail(&mall_entry->list, &mlxsw_sp_port->mall_list); return 0; -err_add_action: +errout: kfree(mall_entry); return err; } -- cgit From 47fa15eae487f3f454d004894671ebea53e77bde Mon Sep 17 00:00:00 2001 From: Jiri Pirko Date: Mon, 27 Apr 2020 18:13:05 +0300 Subject: mlxsw: spectrum_matchall: Move ingress indication into mall_entry Instead of having it in mirror_entry structure, move it to mall_entry and set it during rule insertion. Signed-off-by: Jiri Pirko Signed-off-by: Ido Schimmel Signed-off-by: David S. Miller --- .../net/ethernet/mellanox/mlxsw/spectrum_matchall.c | 18 ++++++++---------- 1 file changed, 8 insertions(+), 10 deletions(-) diff --git a/drivers/net/ethernet/mellanox/mlxsw/spectrum_matchall.c b/drivers/net/ethernet/mellanox/mlxsw/spectrum_matchall.c index adaaee208655..c05e28971d06 100644 --- a/drivers/net/ethernet/mellanox/mlxsw/spectrum_matchall.c +++ b/drivers/net/ethernet/mellanox/mlxsw/spectrum_matchall.c @@ -18,13 +18,13 @@ enum mlxsw_sp_mall_action_type { struct mlxsw_sp_mall_mirror_entry { const struct net_device *to_dev; int span_id; - bool ingress; }; struct mlxsw_sp_mall_entry { struct list_head list; unsigned long cookie; enum mlxsw_sp_mall_action_type type; + bool ingress; union { struct mlxsw_sp_mall_mirror_entry mirror; struct mlxsw_sp_port_sample sample; @@ -45,8 +45,7 @@ mlxsw_sp_mall_entry_find(struct mlxsw_sp_port *port, unsigned long cookie) static int mlxsw_sp_mall_port_mirror_add(struct mlxsw_sp_port *mlxsw_sp_port, - struct mlxsw_sp_mall_entry *mall_entry, - bool ingress) + struct mlxsw_sp_mall_entry *mall_entry) { enum mlxsw_sp_span_type span_type; @@ -55,9 +54,8 @@ mlxsw_sp_mall_port_mirror_add(struct mlxsw_sp_port *mlxsw_sp_port, return -EINVAL; } - mall_entry->mirror.ingress = ingress; - span_type = mall_entry->mirror.ingress ? MLXSW_SP_SPAN_INGRESS : - MLXSW_SP_SPAN_EGRESS; + span_type = mall_entry->ingress ? MLXSW_SP_SPAN_INGRESS : + MLXSW_SP_SPAN_EGRESS; return mlxsw_sp_span_mirror_add(mlxsw_sp_port, mall_entry->mirror.to_dev, span_type, true, @@ -70,8 +68,8 @@ mlxsw_sp_mall_port_mirror_del(struct mlxsw_sp_port *mlxsw_sp_port, { enum mlxsw_sp_span_type span_type; - span_type = mall_entry->mirror.ingress ? MLXSW_SP_SPAN_INGRESS : - MLXSW_SP_SPAN_EGRESS; + span_type = mall_entry->ingress ? MLXSW_SP_SPAN_INGRESS : + MLXSW_SP_SPAN_EGRESS; mlxsw_sp_span_mirror_del(mlxsw_sp_port, mall_entry->mirror.span_id, span_type, true); } @@ -142,14 +140,14 @@ int mlxsw_sp_mall_replace(struct mlxsw_sp_port *mlxsw_sp_port, if (!mall_entry) return -ENOMEM; mall_entry->cookie = f->cookie; + mall_entry->ingress = ingress; act = &f->rule->action.entries[0]; if (act->id == FLOW_ACTION_MIRRED && protocol == htons(ETH_P_ALL)) { mall_entry->type = MLXSW_SP_MALL_ACTION_TYPE_MIRROR; mall_entry->mirror.to_dev = act->dev; - err = mlxsw_sp_mall_port_mirror_add(mlxsw_sp_port, mall_entry, - ingress); + err = mlxsw_sp_mall_port_mirror_add(mlxsw_sp_port, mall_entry); } else if (act->id == FLOW_ACTION_SAMPLE && protocol == htons(ETH_P_ALL)) { if (act->sample.rate > MLXSW_REG_MPSC_RATE_MAX) { -- cgit From dd0fbc89d274e392a077c5dc9a21d581de3252d1 Mon Sep 17 00:00:00 2001 From: Jiri Pirko Date: Mon, 27 Apr 2020 18:13:06 +0300 Subject: mlxsw: spectrum_matchall: Push per-port rule add/del into separate functions As the replace/destroy is going to be used later on per-block, push the per-port rule addition/deletion into separate functions. Signed-off-by: Jiri Pirko Signed-off-by: Ido Schimmel Signed-off-by: David S. Miller --- .../ethernet/mellanox/mlxsw/spectrum_matchall.c | 48 ++++++++++++++++------ 1 file changed, 35 insertions(+), 13 deletions(-) diff --git a/drivers/net/ethernet/mellanox/mlxsw/spectrum_matchall.c b/drivers/net/ethernet/mellanox/mlxsw/spectrum_matchall.c index c05e28971d06..41301027a47c 100644 --- a/drivers/net/ethernet/mellanox/mlxsw/spectrum_matchall.c +++ b/drivers/net/ethernet/mellanox/mlxsw/spectrum_matchall.c @@ -123,6 +123,37 @@ mlxsw_sp_mall_port_sample_del(struct mlxsw_sp_port *mlxsw_sp_port) RCU_INIT_POINTER(mlxsw_sp_port->sample->psample_group, NULL); } +static int +mlxsw_sp_mall_port_rule_add(struct mlxsw_sp_port *mlxsw_sp_port, + struct mlxsw_sp_mall_entry *mall_entry) +{ + switch (mall_entry->type) { + case MLXSW_SP_MALL_ACTION_TYPE_MIRROR: + return mlxsw_sp_mall_port_mirror_add(mlxsw_sp_port, mall_entry); + case MLXSW_SP_MALL_ACTION_TYPE_SAMPLE: + return mlxsw_sp_mall_port_sample_add(mlxsw_sp_port, mall_entry); + default: + WARN_ON(1); + return -EINVAL; + } +} + +static void +mlxsw_sp_mall_port_rule_del(struct mlxsw_sp_port *mlxsw_sp_port, + struct mlxsw_sp_mall_entry *mall_entry) +{ + switch (mall_entry->type) { + case MLXSW_SP_MALL_ACTION_TYPE_MIRROR: + mlxsw_sp_mall_port_mirror_del(mlxsw_sp_port, mall_entry); + break; + case MLXSW_SP_MALL_ACTION_TYPE_SAMPLE: + mlxsw_sp_mall_port_sample_del(mlxsw_sp_port); + break; + default: + WARN_ON(1); + } +} + int mlxsw_sp_mall_replace(struct mlxsw_sp_port *mlxsw_sp_port, struct tc_cls_matchall_offload *f, bool ingress) { @@ -147,7 +178,6 @@ int mlxsw_sp_mall_replace(struct mlxsw_sp_port *mlxsw_sp_port, if (act->id == FLOW_ACTION_MIRRED && protocol == htons(ETH_P_ALL)) { mall_entry->type = MLXSW_SP_MALL_ACTION_TYPE_MIRROR; mall_entry->mirror.to_dev = act->dev; - err = mlxsw_sp_mall_port_mirror_add(mlxsw_sp_port, mall_entry); } else if (act->id == FLOW_ACTION_SAMPLE && protocol == htons(ETH_P_ALL)) { if (act->sample.rate > MLXSW_REG_MPSC_RATE_MAX) { @@ -160,11 +190,12 @@ int mlxsw_sp_mall_replace(struct mlxsw_sp_port *mlxsw_sp_port, mall_entry->sample.truncate = act->sample.truncate; mall_entry->sample.trunc_size = act->sample.trunc_size; mall_entry->sample.rate = act->sample.rate; - err = mlxsw_sp_mall_port_sample_add(mlxsw_sp_port, mall_entry); } else { err = -EOPNOTSUPP; + goto errout; } + err = mlxsw_sp_mall_port_rule_add(mlxsw_sp_port, mall_entry); if (err) goto errout; @@ -186,18 +217,9 @@ void mlxsw_sp_mall_destroy(struct mlxsw_sp_port *mlxsw_sp_port, netdev_dbg(mlxsw_sp_port->dev, "tc entry not found on port\n"); return; } - list_del(&mall_entry->list); - switch (mall_entry->type) { - case MLXSW_SP_MALL_ACTION_TYPE_MIRROR: - mlxsw_sp_mall_port_mirror_del(mlxsw_sp_port, mall_entry); - break; - case MLXSW_SP_MALL_ACTION_TYPE_SAMPLE: - mlxsw_sp_mall_port_sample_del(mlxsw_sp_port); - break; - default: - WARN_ON(1); - } + mlxsw_sp_mall_port_rule_del(mlxsw_sp_port, mall_entry); + list_del(&mall_entry->list); kfree(mall_entry); } -- cgit From 481ff57aadf5ea36bb3c5a9e659a2e1c5ecc6725 Mon Sep 17 00:00:00 2001 From: Jiri Pirko Date: Mon, 27 Apr 2020 18:13:07 +0300 Subject: mlxsw: spectrum: Avoid copying sample values and use RCU pointer direcly instead Currently, only the psample_group is accessed using RCU on RX path. However, it is possible (unlikely) that other sample values get change during RX processing. Fix this by having the port->sample struct accessed as RCU pointer, containing all sample values including psample_group pointer. That avoids extra alloc per-port, copying the values and the race condition described above. Signed-off-by: Jiri Pirko Signed-off-by: Ido Schimmel Signed-off-by: David S. Miller --- drivers/net/ethernet/mellanox/mlxsw/spectrum.c | 30 +++++----------------- drivers/net/ethernet/mellanox/mlxsw/spectrum.h | 4 +-- .../ethernet/mellanox/mlxsw/spectrum_matchall.c | 17 +++++------- 3 files changed, 14 insertions(+), 37 deletions(-) diff --git a/drivers/net/ethernet/mellanox/mlxsw/spectrum.c b/drivers/net/ethernet/mellanox/mlxsw/spectrum.c index ff25f8fc55e9..5952ec26c169 100644 --- a/drivers/net/ethernet/mellanox/mlxsw/spectrum.c +++ b/drivers/net/ethernet/mellanox/mlxsw/spectrum.c @@ -3527,13 +3527,6 @@ static int mlxsw_sp_port_create(struct mlxsw_sp *mlxsw_sp, u8 local_port, goto err_alloc_stats; } - mlxsw_sp_port->sample = kzalloc(sizeof(*mlxsw_sp_port->sample), - GFP_KERNEL); - if (!mlxsw_sp_port->sample) { - err = -ENOMEM; - goto err_alloc_sample; - } - INIT_DELAYED_WORK(&mlxsw_sp_port->periodic_hw_stats.update_dw, &update_stats_cache); @@ -3720,8 +3713,6 @@ err_dev_addr_init: err_port_swid_set: mlxsw_sp_port_module_unmap(mlxsw_sp_port); err_port_module_map: - kfree(mlxsw_sp_port->sample); -err_alloc_sample: free_percpu(mlxsw_sp_port->pcpu_stats); err_alloc_stats: free_netdev(dev); @@ -3749,7 +3740,6 @@ static void mlxsw_sp_port_remove(struct mlxsw_sp *mlxsw_sp, u8 local_port) mlxsw_sp_port_tc_mc_mode_set(mlxsw_sp_port, false); mlxsw_sp_port_swid_set(mlxsw_sp_port, MLXSW_PORT_SWID_DISABLED_PORT); mlxsw_sp_port_module_unmap(mlxsw_sp_port); - kfree(mlxsw_sp_port->sample); free_percpu(mlxsw_sp_port->pcpu_stats); WARN_ON_ONCE(!list_empty(&mlxsw_sp_port->vlans_list)); free_netdev(mlxsw_sp_port->dev); @@ -4236,7 +4226,7 @@ static void mlxsw_sp_rx_listener_sample_func(struct sk_buff *skb, u8 local_port, { struct mlxsw_sp *mlxsw_sp = priv; struct mlxsw_sp_port *mlxsw_sp_port = mlxsw_sp->ports[local_port]; - struct psample_group *psample_group; + struct mlxsw_sp_port_sample *sample; u32 size; if (unlikely(!mlxsw_sp_port)) { @@ -4244,22 +4234,14 @@ static void mlxsw_sp_rx_listener_sample_func(struct sk_buff *skb, u8 local_port, local_port); goto out; } - if (unlikely(!mlxsw_sp_port->sample)) { - dev_warn_ratelimited(mlxsw_sp->bus_info->dev, "Port %d: sample skb received on unsupported port\n", - local_port); - goto out; - } - - size = mlxsw_sp_port->sample->truncate ? - mlxsw_sp_port->sample->trunc_size : skb->len; rcu_read_lock(); - psample_group = rcu_dereference(mlxsw_sp_port->sample->psample_group); - if (!psample_group) + sample = rcu_dereference(mlxsw_sp_port->sample); + if (!sample) goto out_unlock; - psample_sample_packet(psample_group, skb, size, - mlxsw_sp_port->dev->ifindex, 0, - mlxsw_sp_port->sample->rate); + size = sample->truncate ? sample->trunc_size : skb->len; + psample_sample_packet(sample->psample_group, skb, size, + mlxsw_sp_port->dev->ifindex, 0, sample->rate); out_unlock: rcu_read_unlock(); out: diff --git a/drivers/net/ethernet/mellanox/mlxsw/spectrum.h b/drivers/net/ethernet/mellanox/mlxsw/spectrum.h index 5c2f1af53e53..4cdb7f1d7436 100644 --- a/drivers/net/ethernet/mellanox/mlxsw/spectrum.h +++ b/drivers/net/ethernet/mellanox/mlxsw/spectrum.h @@ -192,7 +192,7 @@ struct mlxsw_sp_port_pcpu_stats { }; struct mlxsw_sp_port_sample { - struct psample_group __rcu *psample_group; + struct psample_group *psample_group; u32 trunc_size; u32 rate; bool truncate; @@ -262,7 +262,7 @@ struct mlxsw_sp_port { struct mlxsw_sp_port_xstats xstats; struct delayed_work update_dw; } periodic_hw_stats; - struct mlxsw_sp_port_sample *sample; + struct mlxsw_sp_port_sample __rcu *sample; struct list_head vlans_list; struct mlxsw_sp_port_vlan *default_vlan; struct mlxsw_sp_qdisc_state *qdisc; diff --git a/drivers/net/ethernet/mellanox/mlxsw/spectrum_matchall.c b/drivers/net/ethernet/mellanox/mlxsw/spectrum_matchall.c index 41301027a47c..bda5fb34162a 100644 --- a/drivers/net/ethernet/mellanox/mlxsw/spectrum_matchall.c +++ b/drivers/net/ethernet/mellanox/mlxsw/spectrum_matchall.c @@ -29,6 +29,7 @@ struct mlxsw_sp_mall_entry { struct mlxsw_sp_mall_mirror_entry mirror; struct mlxsw_sp_port_sample sample; }; + struct rcu_head rcu; }; static struct mlxsw_sp_mall_entry * @@ -90,17 +91,11 @@ mlxsw_sp_mall_port_sample_add(struct mlxsw_sp_port *mlxsw_sp_port, { int err; - if (!mlxsw_sp_port->sample) - return -EOPNOTSUPP; - if (rtnl_dereference(mlxsw_sp_port->sample->psample_group)) { + if (rtnl_dereference(mlxsw_sp_port->sample)) { netdev_err(mlxsw_sp_port->dev, "sample already active\n"); return -EEXIST; } - rcu_assign_pointer(mlxsw_sp_port->sample->psample_group, - mall_entry->sample.psample_group); - mlxsw_sp_port->sample->truncate = mall_entry->sample.truncate; - mlxsw_sp_port->sample->trunc_size = mall_entry->sample.trunc_size; - mlxsw_sp_port->sample->rate = mall_entry->sample.rate; + rcu_assign_pointer(mlxsw_sp_port->sample, &mall_entry->sample); err = mlxsw_sp_mall_port_sample_set(mlxsw_sp_port, true, mall_entry->sample.rate); @@ -109,7 +104,7 @@ mlxsw_sp_mall_port_sample_add(struct mlxsw_sp_port *mlxsw_sp_port, return 0; err_port_sample_set: - RCU_INIT_POINTER(mlxsw_sp_port->sample->psample_group, NULL); + RCU_INIT_POINTER(mlxsw_sp_port->sample, NULL); return err; } @@ -120,7 +115,7 @@ mlxsw_sp_mall_port_sample_del(struct mlxsw_sp_port *mlxsw_sp_port) return; mlxsw_sp_mall_port_sample_set(mlxsw_sp_port, false, 1); - RCU_INIT_POINTER(mlxsw_sp_port->sample->psample_group, NULL); + RCU_INIT_POINTER(mlxsw_sp_port->sample, NULL); } static int @@ -221,5 +216,5 @@ void mlxsw_sp_mall_destroy(struct mlxsw_sp_port *mlxsw_sp_port, mlxsw_sp_mall_port_rule_del(mlxsw_sp_port, mall_entry); list_del(&mall_entry->list); - kfree(mall_entry); + kfree_rcu(mall_entry, rcu); /* sample RX packets may be in-flight */ } -- cgit From 3c650136afba8233e738849149b578d0ad6d2023 Mon Sep 17 00:00:00 2001 From: Jiri Pirko Date: Mon, 27 Apr 2020 18:13:08 +0300 Subject: mlxsw: spectrum_matchall: Process matchall events from the same cb as flower Currently there are two callbacks registered: one for matchall, one for flower. This causes the user to see "in_hw_count 2" in TC filter dump. Because of this and also as a preparation for future matchall offload for rules equivalent to flower-all-match, move the processing of shared block into matchall.c. Leave only one cb for mlxsw driver per-block. Signed-off-by: Jiri Pirko Signed-off-by: Ido Schimmel Signed-off-by: David S. Miller --- drivers/net/ethernet/mellanox/mlxsw/spectrum.c | 125 +++++---------------- drivers/net/ethernet/mellanox/mlxsw/spectrum.h | 12 +- .../net/ethernet/mellanox/mlxsw/spectrum_flow.c | 17 ++- .../ethernet/mellanox/mlxsw/spectrum_matchall.c | 90 ++++++++++++--- 4 files changed, 124 insertions(+), 120 deletions(-) diff --git a/drivers/net/ethernet/mellanox/mlxsw/spectrum.c b/drivers/net/ethernet/mellanox/mlxsw/spectrum.c index 5952ec26c169..ceaf73ac2008 100644 --- a/drivers/net/ethernet/mellanox/mlxsw/spectrum.c +++ b/drivers/net/ethernet/mellanox/mlxsw/spectrum.c @@ -1350,15 +1350,15 @@ static int mlxsw_sp_port_kill_vid(struct net_device *dev, return 0; } -static int mlxsw_sp_setup_tc_cls_matchall(struct mlxsw_sp_port *mlxsw_sp_port, - struct tc_cls_matchall_offload *f, - bool ingress) +static int +mlxsw_sp_setup_tc_cls_matchall(struct mlxsw_sp_flow_block *flow_block, + struct tc_cls_matchall_offload *f) { switch (f->command) { case TC_CLSMATCHALL_REPLACE: - return mlxsw_sp_mall_replace(mlxsw_sp_port, f, ingress); + return mlxsw_sp_mall_replace(flow_block, f); case TC_CLSMATCHALL_DESTROY: - mlxsw_sp_mall_destroy(mlxsw_sp_port, f); + mlxsw_sp_mall_destroy(flow_block, f); return 0; default: return -EOPNOTSUPP; @@ -1389,62 +1389,25 @@ mlxsw_sp_setup_tc_cls_flower(struct mlxsw_sp_flow_block *flow_block, } } -static int mlxsw_sp_setup_tc_block_cb_matchall(enum tc_setup_type type, - void *type_data, - void *cb_priv, bool ingress) +static int mlxsw_sp_setup_tc_block_cb(enum tc_setup_type type, + void *type_data, void *cb_priv) { - struct mlxsw_sp_port *mlxsw_sp_port = cb_priv; - - switch (type) { - case TC_SETUP_CLSMATCHALL: - if (!tc_cls_can_offload_and_chain0(mlxsw_sp_port->dev, - type_data)) - return -EOPNOTSUPP; + struct mlxsw_sp_flow_block *flow_block = cb_priv; - return mlxsw_sp_setup_tc_cls_matchall(mlxsw_sp_port, type_data, - ingress); - case TC_SETUP_CLSFLOWER: - return 0; - default: + if (mlxsw_sp_flow_block_disabled(flow_block)) return -EOPNOTSUPP; - } -} - -static int mlxsw_sp_setup_tc_block_cb_matchall_ig(enum tc_setup_type type, - void *type_data, - void *cb_priv) -{ - return mlxsw_sp_setup_tc_block_cb_matchall(type, type_data, - cb_priv, true); -} - -static int mlxsw_sp_setup_tc_block_cb_matchall_eg(enum tc_setup_type type, - void *type_data, - void *cb_priv) -{ - return mlxsw_sp_setup_tc_block_cb_matchall(type, type_data, - cb_priv, false); -} - -static int mlxsw_sp_setup_tc_block_cb_flower(enum tc_setup_type type, - void *type_data, void *cb_priv) -{ - struct mlxsw_sp_flow_block *flow_block = cb_priv; switch (type) { case TC_SETUP_CLSMATCHALL: - return 0; + return mlxsw_sp_setup_tc_cls_matchall(flow_block, type_data); case TC_SETUP_CLSFLOWER: - if (mlxsw_sp_flow_block_disabled(flow_block)) - return -EOPNOTSUPP; - return mlxsw_sp_setup_tc_cls_flower(flow_block, type_data); default: return -EOPNOTSUPP; } } -static void mlxsw_sp_tc_block_flower_release(void *cb_priv) +static void mlxsw_sp_tc_block_release(void *cb_priv) { struct mlxsw_sp_flow_block *flow_block = cb_priv; @@ -1453,9 +1416,9 @@ static void mlxsw_sp_tc_block_flower_release(void *cb_priv) static LIST_HEAD(mlxsw_sp_block_cb_list); -static int -mlxsw_sp_setup_tc_block_flower_bind(struct mlxsw_sp_port *mlxsw_sp_port, - struct flow_block_offload *f, bool ingress) +static int mlxsw_sp_setup_tc_block_bind(struct mlxsw_sp_port *mlxsw_sp_port, + struct flow_block_offload *f, + bool ingress) { struct mlxsw_sp *mlxsw_sp = mlxsw_sp_port->mlxsw_sp; struct mlxsw_sp_flow_block *flow_block; @@ -1463,16 +1426,15 @@ mlxsw_sp_setup_tc_block_flower_bind(struct mlxsw_sp_port *mlxsw_sp_port, bool register_block = false; int err; - block_cb = flow_block_cb_lookup(f->block, - mlxsw_sp_setup_tc_block_cb_flower, + block_cb = flow_block_cb_lookup(f->block, mlxsw_sp_setup_tc_block_cb, mlxsw_sp); if (!block_cb) { flow_block = mlxsw_sp_flow_block_create(mlxsw_sp, f->net); if (!flow_block) return -ENOMEM; - block_cb = flow_block_cb_alloc(mlxsw_sp_setup_tc_block_cb_flower, + block_cb = flow_block_cb_alloc(mlxsw_sp_setup_tc_block_cb, mlxsw_sp, flow_block, - mlxsw_sp_tc_block_flower_release); + mlxsw_sp_tc_block_release); if (IS_ERR(block_cb)) { mlxsw_sp_flow_block_destroy(flow_block); err = PTR_ERR(block_cb); @@ -1507,18 +1469,16 @@ err_cb_register: return err; } -static void -mlxsw_sp_setup_tc_block_flower_unbind(struct mlxsw_sp_port *mlxsw_sp_port, - struct flow_block_offload *f, - bool ingress) +static void mlxsw_sp_setup_tc_block_unbind(struct mlxsw_sp_port *mlxsw_sp_port, + struct flow_block_offload *f, + bool ingress) { struct mlxsw_sp *mlxsw_sp = mlxsw_sp_port->mlxsw_sp; struct mlxsw_sp_flow_block *flow_block; struct flow_block_cb *block_cb; int err; - block_cb = flow_block_cb_lookup(f->block, - mlxsw_sp_setup_tc_block_cb_flower, + block_cb = flow_block_cb_lookup(f->block, mlxsw_sp_setup_tc_block_cb, mlxsw_sp); if (!block_cb) return; @@ -1540,51 +1500,22 @@ mlxsw_sp_setup_tc_block_flower_unbind(struct mlxsw_sp_port *mlxsw_sp_port, static int mlxsw_sp_setup_tc_block(struct mlxsw_sp_port *mlxsw_sp_port, struct flow_block_offload *f) { - struct flow_block_cb *block_cb; - flow_setup_cb_t *cb; bool ingress; - int err; - if (f->binder_type == FLOW_BLOCK_BINDER_TYPE_CLSACT_INGRESS) { - cb = mlxsw_sp_setup_tc_block_cb_matchall_ig; + if (f->binder_type == FLOW_BLOCK_BINDER_TYPE_CLSACT_INGRESS) ingress = true; - } else if (f->binder_type == FLOW_BLOCK_BINDER_TYPE_CLSACT_EGRESS) { - cb = mlxsw_sp_setup_tc_block_cb_matchall_eg; + else if (f->binder_type == FLOW_BLOCK_BINDER_TYPE_CLSACT_EGRESS) ingress = false; - } else { + else return -EOPNOTSUPP; - } f->driver_block_list = &mlxsw_sp_block_cb_list; switch (f->command) { case FLOW_BLOCK_BIND: - if (flow_block_cb_is_busy(cb, mlxsw_sp_port, - &mlxsw_sp_block_cb_list)) - return -EBUSY; - - block_cb = flow_block_cb_alloc(cb, mlxsw_sp_port, - mlxsw_sp_port, NULL); - if (IS_ERR(block_cb)) - return PTR_ERR(block_cb); - err = mlxsw_sp_setup_tc_block_flower_bind(mlxsw_sp_port, f, - ingress); - if (err) { - flow_block_cb_free(block_cb); - return err; - } - flow_block_cb_add(block_cb, f); - list_add_tail(&block_cb->driver_list, &mlxsw_sp_block_cb_list); - return 0; + return mlxsw_sp_setup_tc_block_bind(mlxsw_sp_port, f, ingress); case FLOW_BLOCK_UNBIND: - mlxsw_sp_setup_tc_block_flower_unbind(mlxsw_sp_port, - f, ingress); - block_cb = flow_block_cb_lookup(f->block, cb, mlxsw_sp_port); - if (!block_cb) - return -ENOENT; - - flow_block_cb_remove(block_cb, f); - list_del(&block_cb->driver_list); + mlxsw_sp_setup_tc_block_unbind(mlxsw_sp_port, f, ingress); return 0; default: return -EOPNOTSUPP; @@ -1621,8 +1552,7 @@ static int mlxsw_sp_feature_hw_tc(struct net_device *dev, bool enable) if (!enable) { if (mlxsw_sp_flow_block_rule_count(mlxsw_sp_port->ing_flow_block) || - mlxsw_sp_flow_block_rule_count(mlxsw_sp_port->eg_flow_block) || - !list_empty(&mlxsw_sp_port->mall_list)) { + mlxsw_sp_flow_block_rule_count(mlxsw_sp_port->eg_flow_block)) { netdev_err(dev, "Active offloaded tc filters, can't turn hw_tc_offload off\n"); return -EINVAL; } @@ -3518,7 +3448,6 @@ static int mlxsw_sp_port_create(struct mlxsw_sp *mlxsw_sp, u8 local_port, mlxsw_sp_port->mapping = *port_mapping; mlxsw_sp_port->link.autoneg = 1; INIT_LIST_HEAD(&mlxsw_sp_port->vlans_list); - INIT_LIST_HEAD(&mlxsw_sp_port->mall_list); mlxsw_sp_port->pcpu_stats = netdev_alloc_pcpu_stats(struct mlxsw_sp_port_pcpu_stats); diff --git a/drivers/net/ethernet/mellanox/mlxsw/spectrum.h b/drivers/net/ethernet/mellanox/mlxsw/spectrum.h index 4cdb7f1d7436..57d320728914 100644 --- a/drivers/net/ethernet/mellanox/mlxsw/spectrum.h +++ b/drivers/net/ethernet/mellanox/mlxsw/spectrum.h @@ -255,7 +255,6 @@ struct mlxsw_sp_port { * the same localport can have * different mapping. */ - struct list_head mall_list; struct { #define MLXSW_HW_STATS_UPDATE_TIME HZ struct rtnl_link_stats64 stats; @@ -637,6 +636,7 @@ struct mlxsw_sp_acl_rule_info { /* spectrum_flow.c */ struct mlxsw_sp_flow_block { struct list_head binding_list; + struct list_head mall_list; struct mlxsw_sp_acl_ruleset *ruleset_zero; struct mlxsw_sp *mlxsw_sp; unsigned int rule_count; @@ -894,10 +894,14 @@ extern const struct mlxsw_afk_ops mlxsw_sp1_afk_ops; extern const struct mlxsw_afk_ops mlxsw_sp2_afk_ops; /* spectrum_matchall.c */ -int mlxsw_sp_mall_replace(struct mlxsw_sp_port *mlxsw_sp_port, - struct tc_cls_matchall_offload *f, bool ingress); -void mlxsw_sp_mall_destroy(struct mlxsw_sp_port *mlxsw_sp_port, +int mlxsw_sp_mall_replace(struct mlxsw_sp_flow_block *block, + struct tc_cls_matchall_offload *f); +void mlxsw_sp_mall_destroy(struct mlxsw_sp_flow_block *block, struct tc_cls_matchall_offload *f); +int mlxsw_sp_mall_port_bind(struct mlxsw_sp_flow_block *block, + struct mlxsw_sp_port *mlxsw_sp_port); +void mlxsw_sp_mall_port_unbind(struct mlxsw_sp_flow_block *block, + struct mlxsw_sp_port *mlxsw_sp_port); /* spectrum_flower.c */ int mlxsw_sp_flower_replace(struct mlxsw_sp *mlxsw_sp, diff --git a/drivers/net/ethernet/mellanox/mlxsw/spectrum_flow.c b/drivers/net/ethernet/mellanox/mlxsw/spectrum_flow.c index 655e1df5c95a..51de6aca1930 100644 --- a/drivers/net/ethernet/mellanox/mlxsw/spectrum_flow.c +++ b/drivers/net/ethernet/mellanox/mlxsw/spectrum_flow.c @@ -18,6 +18,7 @@ mlxsw_sp_flow_block_create(struct mlxsw_sp *mlxsw_sp, struct net *net) if (!block) return NULL; INIT_LIST_HEAD(&block->binding_list); + INIT_LIST_HEAD(&block->mall_list); block->mlxsw_sp = mlxsw_sp; block->net = net; return block; @@ -70,9 +71,15 @@ int mlxsw_sp_flow_block_bind(struct mlxsw_sp *mlxsw_sp, return -EOPNOTSUPP; } + err = mlxsw_sp_mall_port_bind(block, mlxsw_sp_port); + if (err) + return err; + binding = kzalloc(sizeof(*binding), GFP_KERNEL); - if (!binding) - return -ENOMEM; + if (!binding) { + err = -ENOMEM; + goto err_binding_alloc; + } binding->mlxsw_sp_port = mlxsw_sp_port; binding->ingress = ingress; @@ -91,6 +98,9 @@ int mlxsw_sp_flow_block_bind(struct mlxsw_sp *mlxsw_sp, err_ruleset_bind: kfree(binding); +err_binding_alloc: + mlxsw_sp_mall_port_unbind(block, mlxsw_sp_port); + return err; } @@ -116,5 +126,8 @@ int mlxsw_sp_flow_block_unbind(struct mlxsw_sp *mlxsw_sp, mlxsw_sp_acl_ruleset_unbind(mlxsw_sp, block, binding); kfree(binding); + + mlxsw_sp_mall_port_unbind(block, mlxsw_sp_port); + return 0; } diff --git a/drivers/net/ethernet/mellanox/mlxsw/spectrum_matchall.c b/drivers/net/ethernet/mellanox/mlxsw/spectrum_matchall.c index bda5fb34162a..889da63072be 100644 --- a/drivers/net/ethernet/mellanox/mlxsw/spectrum_matchall.c +++ b/drivers/net/ethernet/mellanox/mlxsw/spectrum_matchall.c @@ -33,11 +33,11 @@ struct mlxsw_sp_mall_entry { }; static struct mlxsw_sp_mall_entry * -mlxsw_sp_mall_entry_find(struct mlxsw_sp_port *port, unsigned long cookie) +mlxsw_sp_mall_entry_find(struct mlxsw_sp_flow_block *block, unsigned long cookie) { struct mlxsw_sp_mall_entry *mall_entry; - list_for_each_entry(mall_entry, &port->mall_list, list) + list_for_each_entry(mall_entry, &block->mall_list, list) if (mall_entry->cookie == cookie) return mall_entry; @@ -149,16 +149,27 @@ mlxsw_sp_mall_port_rule_del(struct mlxsw_sp_port *mlxsw_sp_port, } } -int mlxsw_sp_mall_replace(struct mlxsw_sp_port *mlxsw_sp_port, - struct tc_cls_matchall_offload *f, bool ingress) +int mlxsw_sp_mall_replace(struct mlxsw_sp_flow_block *block, + struct tc_cls_matchall_offload *f) { + struct mlxsw_sp_flow_block_binding *binding; struct mlxsw_sp_mall_entry *mall_entry; __be16 protocol = f->common.protocol; struct flow_action_entry *act; int err; if (!flow_offload_has_one_action(&f->rule->action)) { - netdev_err(mlxsw_sp_port->dev, "only singular actions are supported\n"); + NL_SET_ERR_MSG(f->common.extack, "Only singular actions are supported"); + return -EOPNOTSUPP; + } + + if (f->common.chain_index) { + NL_SET_ERR_MSG(f->common.extack, "Only chain 0 is supported"); + return -EOPNOTSUPP; + } + + if (mlxsw_sp_flow_block_is_mixed_bound(block)) { + NL_SET_ERR_MSG(f->common.extack, "Only not mixed bound blocks are supported"); return -EOPNOTSUPP; } @@ -166,7 +177,7 @@ int mlxsw_sp_mall_replace(struct mlxsw_sp_port *mlxsw_sp_port, if (!mall_entry) return -ENOMEM; mall_entry->cookie = f->cookie; - mall_entry->ingress = ingress; + mall_entry->ingress = mlxsw_sp_flow_block_is_ingress_bound(block); act = &f->rule->action.entries[0]; @@ -176,7 +187,7 @@ int mlxsw_sp_mall_replace(struct mlxsw_sp_port *mlxsw_sp_port, } else if (act->id == FLOW_ACTION_SAMPLE && protocol == htons(ETH_P_ALL)) { if (act->sample.rate > MLXSW_REG_MPSC_RATE_MAX) { - netdev_err(mlxsw_sp_port->dev, "sample rate not supported\n"); + NL_SET_ERR_MSG(f->common.extack, "Sample rate not supported"); err = -EOPNOTSUPP; goto errout; } @@ -190,31 +201,78 @@ int mlxsw_sp_mall_replace(struct mlxsw_sp_port *mlxsw_sp_port, goto errout; } - err = mlxsw_sp_mall_port_rule_add(mlxsw_sp_port, mall_entry); - if (err) - goto errout; + list_for_each_entry(binding, &block->binding_list, list) { + err = mlxsw_sp_mall_port_rule_add(binding->mlxsw_sp_port, + mall_entry); + if (err) + goto rollback; + } - list_add_tail(&mall_entry->list, &mlxsw_sp_port->mall_list); + block->rule_count++; + if (mall_entry->ingress) + block->egress_blocker_rule_count++; + else + block->ingress_blocker_rule_count++; + list_add_tail(&mall_entry->list, &block->mall_list); return 0; +rollback: + list_for_each_entry_continue_reverse(binding, &block->binding_list, + list) + mlxsw_sp_mall_port_rule_del(binding->mlxsw_sp_port, mall_entry); errout: kfree(mall_entry); return err; } -void mlxsw_sp_mall_destroy(struct mlxsw_sp_port *mlxsw_sp_port, +void mlxsw_sp_mall_destroy(struct mlxsw_sp_flow_block *block, struct tc_cls_matchall_offload *f) { + struct mlxsw_sp_flow_block_binding *binding; struct mlxsw_sp_mall_entry *mall_entry; - mall_entry = mlxsw_sp_mall_entry_find(mlxsw_sp_port, f->cookie); + mall_entry = mlxsw_sp_mall_entry_find(block, f->cookie); if (!mall_entry) { - netdev_dbg(mlxsw_sp_port->dev, "tc entry not found on port\n"); + NL_SET_ERR_MSG(f->common.extack, "Entry not found"); return; } - mlxsw_sp_mall_port_rule_del(mlxsw_sp_port, mall_entry); - list_del(&mall_entry->list); + if (mall_entry->ingress) + block->egress_blocker_rule_count--; + else + block->ingress_blocker_rule_count--; + block->rule_count--; + list_for_each_entry(binding, &block->binding_list, list) + mlxsw_sp_mall_port_rule_del(binding->mlxsw_sp_port, mall_entry); kfree_rcu(mall_entry, rcu); /* sample RX packets may be in-flight */ } + +int mlxsw_sp_mall_port_bind(struct mlxsw_sp_flow_block *block, + struct mlxsw_sp_port *mlxsw_sp_port) +{ + struct mlxsw_sp_mall_entry *mall_entry; + int err; + + list_for_each_entry(mall_entry, &block->mall_list, list) { + err = mlxsw_sp_mall_port_rule_add(mlxsw_sp_port, mall_entry); + if (err) + goto rollback; + } + return 0; + +rollback: + list_for_each_entry_continue_reverse(mall_entry, &block->mall_list, + list) + mlxsw_sp_mall_port_rule_del(mlxsw_sp_port, mall_entry); + return err; +} + +void mlxsw_sp_mall_port_unbind(struct mlxsw_sp_flow_block *block, + struct mlxsw_sp_port *mlxsw_sp_port) +{ + struct mlxsw_sp_mall_entry *mall_entry; + + list_for_each_entry(mall_entry, &block->mall_list, list) + mlxsw_sp_mall_port_rule_del(mlxsw_sp_port, mall_entry); +} -- cgit From 19f06771ca3dd8346972bc7627f9bcb7b6a8ce0b Mon Sep 17 00:00:00 2001 From: Jiri Pirko Date: Mon, 27 Apr 2020 18:13:09 +0300 Subject: mlxsw: spectrum: Move flow offload binding into spectrum_flow.c Move the code taking case of setup of flow offload into spectrum_flow.c Do small renaming of callbacks on the way. Signed-off-by: Jiri Pirko Signed-off-by: Ido Schimmel Signed-off-by: David S. Miller --- drivers/net/ethernet/mellanox/mlxsw/spectrum.c | 173 ------------------- drivers/net/ethernet/mellanox/mlxsw/spectrum.h | 11 +- .../net/ethernet/mellanox/mlxsw/spectrum_flow.c | 188 ++++++++++++++++++++- 3 files changed, 181 insertions(+), 191 deletions(-) diff --git a/drivers/net/ethernet/mellanox/mlxsw/spectrum.c b/drivers/net/ethernet/mellanox/mlxsw/spectrum.c index ceaf73ac2008..f78bde8bc16e 100644 --- a/drivers/net/ethernet/mellanox/mlxsw/spectrum.c +++ b/drivers/net/ethernet/mellanox/mlxsw/spectrum.c @@ -1350,178 +1350,6 @@ static int mlxsw_sp_port_kill_vid(struct net_device *dev, return 0; } -static int -mlxsw_sp_setup_tc_cls_matchall(struct mlxsw_sp_flow_block *flow_block, - struct tc_cls_matchall_offload *f) -{ - switch (f->command) { - case TC_CLSMATCHALL_REPLACE: - return mlxsw_sp_mall_replace(flow_block, f); - case TC_CLSMATCHALL_DESTROY: - mlxsw_sp_mall_destroy(flow_block, f); - return 0; - default: - return -EOPNOTSUPP; - } -} - -static int -mlxsw_sp_setup_tc_cls_flower(struct mlxsw_sp_flow_block *flow_block, - struct flow_cls_offload *f) -{ - struct mlxsw_sp *mlxsw_sp = mlxsw_sp_flow_block_mlxsw_sp(flow_block); - - switch (f->command) { - case FLOW_CLS_REPLACE: - return mlxsw_sp_flower_replace(mlxsw_sp, flow_block, f); - case FLOW_CLS_DESTROY: - mlxsw_sp_flower_destroy(mlxsw_sp, flow_block, f); - return 0; - case FLOW_CLS_STATS: - return mlxsw_sp_flower_stats(mlxsw_sp, flow_block, f); - case FLOW_CLS_TMPLT_CREATE: - return mlxsw_sp_flower_tmplt_create(mlxsw_sp, flow_block, f); - case FLOW_CLS_TMPLT_DESTROY: - mlxsw_sp_flower_tmplt_destroy(mlxsw_sp, flow_block, f); - return 0; - default: - return -EOPNOTSUPP; - } -} - -static int mlxsw_sp_setup_tc_block_cb(enum tc_setup_type type, - void *type_data, void *cb_priv) -{ - struct mlxsw_sp_flow_block *flow_block = cb_priv; - - if (mlxsw_sp_flow_block_disabled(flow_block)) - return -EOPNOTSUPP; - - switch (type) { - case TC_SETUP_CLSMATCHALL: - return mlxsw_sp_setup_tc_cls_matchall(flow_block, type_data); - case TC_SETUP_CLSFLOWER: - return mlxsw_sp_setup_tc_cls_flower(flow_block, type_data); - default: - return -EOPNOTSUPP; - } -} - -static void mlxsw_sp_tc_block_release(void *cb_priv) -{ - struct mlxsw_sp_flow_block *flow_block = cb_priv; - - mlxsw_sp_flow_block_destroy(flow_block); -} - -static LIST_HEAD(mlxsw_sp_block_cb_list); - -static int mlxsw_sp_setup_tc_block_bind(struct mlxsw_sp_port *mlxsw_sp_port, - struct flow_block_offload *f, - bool ingress) -{ - struct mlxsw_sp *mlxsw_sp = mlxsw_sp_port->mlxsw_sp; - struct mlxsw_sp_flow_block *flow_block; - struct flow_block_cb *block_cb; - bool register_block = false; - int err; - - block_cb = flow_block_cb_lookup(f->block, mlxsw_sp_setup_tc_block_cb, - mlxsw_sp); - if (!block_cb) { - flow_block = mlxsw_sp_flow_block_create(mlxsw_sp, f->net); - if (!flow_block) - return -ENOMEM; - block_cb = flow_block_cb_alloc(mlxsw_sp_setup_tc_block_cb, - mlxsw_sp, flow_block, - mlxsw_sp_tc_block_release); - if (IS_ERR(block_cb)) { - mlxsw_sp_flow_block_destroy(flow_block); - err = PTR_ERR(block_cb); - goto err_cb_register; - } - register_block = true; - } else { - flow_block = flow_block_cb_priv(block_cb); - } - flow_block_cb_incref(block_cb); - err = mlxsw_sp_flow_block_bind(mlxsw_sp, flow_block, - mlxsw_sp_port, ingress, f->extack); - if (err) - goto err_block_bind; - - if (ingress) - mlxsw_sp_port->ing_flow_block = flow_block; - else - mlxsw_sp_port->eg_flow_block = flow_block; - - if (register_block) { - flow_block_cb_add(block_cb, f); - list_add_tail(&block_cb->driver_list, &mlxsw_sp_block_cb_list); - } - - return 0; - -err_block_bind: - if (!flow_block_cb_decref(block_cb)) - flow_block_cb_free(block_cb); -err_cb_register: - return err; -} - -static void mlxsw_sp_setup_tc_block_unbind(struct mlxsw_sp_port *mlxsw_sp_port, - struct flow_block_offload *f, - bool ingress) -{ - struct mlxsw_sp *mlxsw_sp = mlxsw_sp_port->mlxsw_sp; - struct mlxsw_sp_flow_block *flow_block; - struct flow_block_cb *block_cb; - int err; - - block_cb = flow_block_cb_lookup(f->block, mlxsw_sp_setup_tc_block_cb, - mlxsw_sp); - if (!block_cb) - return; - - if (ingress) - mlxsw_sp_port->ing_flow_block = NULL; - else - mlxsw_sp_port->eg_flow_block = NULL; - - flow_block = flow_block_cb_priv(block_cb); - err = mlxsw_sp_flow_block_unbind(mlxsw_sp, flow_block, - mlxsw_sp_port, ingress); - if (!err && !flow_block_cb_decref(block_cb)) { - flow_block_cb_remove(block_cb, f); - list_del(&block_cb->driver_list); - } -} - -static int mlxsw_sp_setup_tc_block(struct mlxsw_sp_port *mlxsw_sp_port, - struct flow_block_offload *f) -{ - bool ingress; - - if (f->binder_type == FLOW_BLOCK_BINDER_TYPE_CLSACT_INGRESS) - ingress = true; - else if (f->binder_type == FLOW_BLOCK_BINDER_TYPE_CLSACT_EGRESS) - ingress = false; - else - return -EOPNOTSUPP; - - f->driver_block_list = &mlxsw_sp_block_cb_list; - - switch (f->command) { - case FLOW_BLOCK_BIND: - return mlxsw_sp_setup_tc_block_bind(mlxsw_sp_port, f, ingress); - case FLOW_BLOCK_UNBIND: - mlxsw_sp_setup_tc_block_unbind(mlxsw_sp_port, f, ingress); - return 0; - default: - return -EOPNOTSUPP; - } -} - static int mlxsw_sp_setup_tc(struct net_device *dev, enum tc_setup_type type, void *type_data) { @@ -1545,7 +1373,6 @@ static int mlxsw_sp_setup_tc(struct net_device *dev, enum tc_setup_type type, } } - static int mlxsw_sp_feature_hw_tc(struct net_device *dev, bool enable) { struct mlxsw_sp_port *mlxsw_sp_port = netdev_priv(dev); diff --git a/drivers/net/ethernet/mellanox/mlxsw/spectrum.h b/drivers/net/ethernet/mellanox/mlxsw/spectrum.h index 57d320728914..a12ca673c224 100644 --- a/drivers/net/ethernet/mellanox/mlxsw/spectrum.h +++ b/drivers/net/ethernet/mellanox/mlxsw/spectrum.h @@ -708,15 +708,8 @@ mlxsw_sp_flow_block_is_mixed_bound(const struct mlxsw_sp_flow_block *block) struct mlxsw_sp_flow_block *mlxsw_sp_flow_block_create(struct mlxsw_sp *mlxsw_sp, struct net *net); void mlxsw_sp_flow_block_destroy(struct mlxsw_sp_flow_block *block); -int mlxsw_sp_flow_block_bind(struct mlxsw_sp *mlxsw_sp, - struct mlxsw_sp_flow_block *block, - struct mlxsw_sp_port *mlxsw_sp_port, - bool ingress, - struct netlink_ext_ack *extack); -int mlxsw_sp_flow_block_unbind(struct mlxsw_sp *mlxsw_sp, - struct mlxsw_sp_flow_block *block, - struct mlxsw_sp_port *mlxsw_sp_port, - bool ingress); +int mlxsw_sp_setup_tc_block(struct mlxsw_sp_port *mlxsw_sp_port, + struct flow_block_offload *f); /* spectrum_acl.c */ struct mlxsw_sp_acl_ruleset; diff --git a/drivers/net/ethernet/mellanox/mlxsw/spectrum_flow.c b/drivers/net/ethernet/mellanox/mlxsw/spectrum_flow.c index 51de6aca1930..ecab581ff956 100644 --- a/drivers/net/ethernet/mellanox/mlxsw/spectrum_flow.c +++ b/drivers/net/ethernet/mellanox/mlxsw/spectrum_flow.c @@ -49,11 +49,11 @@ mlxsw_sp_flow_block_ruleset_bound(const struct mlxsw_sp_flow_block *block) return block->ruleset_zero; } -int mlxsw_sp_flow_block_bind(struct mlxsw_sp *mlxsw_sp, - struct mlxsw_sp_flow_block *block, - struct mlxsw_sp_port *mlxsw_sp_port, - bool ingress, - struct netlink_ext_ack *extack) +static int mlxsw_sp_flow_block_bind(struct mlxsw_sp *mlxsw_sp, + struct mlxsw_sp_flow_block *block, + struct mlxsw_sp_port *mlxsw_sp_port, + bool ingress, + struct netlink_ext_ack *extack) { struct mlxsw_sp_flow_block_binding *binding; int err; @@ -104,10 +104,10 @@ err_binding_alloc: return err; } -int mlxsw_sp_flow_block_unbind(struct mlxsw_sp *mlxsw_sp, - struct mlxsw_sp_flow_block *block, - struct mlxsw_sp_port *mlxsw_sp_port, - bool ingress) +static int mlxsw_sp_flow_block_unbind(struct mlxsw_sp *mlxsw_sp, + struct mlxsw_sp_flow_block *block, + struct mlxsw_sp_port *mlxsw_sp_port, + bool ingress) { struct mlxsw_sp_flow_block_binding *binding; @@ -131,3 +131,173 @@ int mlxsw_sp_flow_block_unbind(struct mlxsw_sp *mlxsw_sp, return 0; } + +static int mlxsw_sp_flow_block_mall_cb(struct mlxsw_sp_flow_block *flow_block, + struct tc_cls_matchall_offload *f) +{ + switch (f->command) { + case TC_CLSMATCHALL_REPLACE: + return mlxsw_sp_mall_replace(flow_block, f); + case TC_CLSMATCHALL_DESTROY: + mlxsw_sp_mall_destroy(flow_block, f); + return 0; + default: + return -EOPNOTSUPP; + } +} + +static int mlxsw_sp_flow_block_flower_cb(struct mlxsw_sp_flow_block *flow_block, + struct flow_cls_offload *f) +{ + struct mlxsw_sp *mlxsw_sp = mlxsw_sp_flow_block_mlxsw_sp(flow_block); + + switch (f->command) { + case FLOW_CLS_REPLACE: + return mlxsw_sp_flower_replace(mlxsw_sp, flow_block, f); + case FLOW_CLS_DESTROY: + mlxsw_sp_flower_destroy(mlxsw_sp, flow_block, f); + return 0; + case FLOW_CLS_STATS: + return mlxsw_sp_flower_stats(mlxsw_sp, flow_block, f); + case FLOW_CLS_TMPLT_CREATE: + return mlxsw_sp_flower_tmplt_create(mlxsw_sp, flow_block, f); + case FLOW_CLS_TMPLT_DESTROY: + mlxsw_sp_flower_tmplt_destroy(mlxsw_sp, flow_block, f); + return 0; + default: + return -EOPNOTSUPP; + } +} + +static int mlxsw_sp_flow_block_cb(enum tc_setup_type type, + void *type_data, void *cb_priv) +{ + struct mlxsw_sp_flow_block *flow_block = cb_priv; + + if (mlxsw_sp_flow_block_disabled(flow_block)) + return -EOPNOTSUPP; + + switch (type) { + case TC_SETUP_CLSMATCHALL: + return mlxsw_sp_flow_block_mall_cb(flow_block, type_data); + case TC_SETUP_CLSFLOWER: + return mlxsw_sp_flow_block_flower_cb(flow_block, type_data); + default: + return -EOPNOTSUPP; + } +} + +static void mlxsw_sp_tc_block_release(void *cb_priv) +{ + struct mlxsw_sp_flow_block *flow_block = cb_priv; + + mlxsw_sp_flow_block_destroy(flow_block); +} + +static LIST_HEAD(mlxsw_sp_block_cb_list); + +static int mlxsw_sp_setup_tc_block_bind(struct mlxsw_sp_port *mlxsw_sp_port, + struct flow_block_offload *f, + bool ingress) +{ + struct mlxsw_sp *mlxsw_sp = mlxsw_sp_port->mlxsw_sp; + struct mlxsw_sp_flow_block *flow_block; + struct flow_block_cb *block_cb; + bool register_block = false; + int err; + + block_cb = flow_block_cb_lookup(f->block, mlxsw_sp_flow_block_cb, + mlxsw_sp); + if (!block_cb) { + flow_block = mlxsw_sp_flow_block_create(mlxsw_sp, f->net); + if (!flow_block) + return -ENOMEM; + block_cb = flow_block_cb_alloc(mlxsw_sp_flow_block_cb, + mlxsw_sp, flow_block, + mlxsw_sp_tc_block_release); + if (IS_ERR(block_cb)) { + mlxsw_sp_flow_block_destroy(flow_block); + err = PTR_ERR(block_cb); + goto err_cb_register; + } + register_block = true; + } else { + flow_block = flow_block_cb_priv(block_cb); + } + flow_block_cb_incref(block_cb); + err = mlxsw_sp_flow_block_bind(mlxsw_sp, flow_block, + mlxsw_sp_port, ingress, f->extack); + if (err) + goto err_block_bind; + + if (ingress) + mlxsw_sp_port->ing_flow_block = flow_block; + else + mlxsw_sp_port->eg_flow_block = flow_block; + + if (register_block) { + flow_block_cb_add(block_cb, f); + list_add_tail(&block_cb->driver_list, &mlxsw_sp_block_cb_list); + } + + return 0; + +err_block_bind: + if (!flow_block_cb_decref(block_cb)) + flow_block_cb_free(block_cb); +err_cb_register: + return err; +} + +static void mlxsw_sp_setup_tc_block_unbind(struct mlxsw_sp_port *mlxsw_sp_port, + struct flow_block_offload *f, + bool ingress) +{ + struct mlxsw_sp *mlxsw_sp = mlxsw_sp_port->mlxsw_sp; + struct mlxsw_sp_flow_block *flow_block; + struct flow_block_cb *block_cb; + int err; + + block_cb = flow_block_cb_lookup(f->block, mlxsw_sp_flow_block_cb, + mlxsw_sp); + if (!block_cb) + return; + + if (ingress) + mlxsw_sp_port->ing_flow_block = NULL; + else + mlxsw_sp_port->eg_flow_block = NULL; + + flow_block = flow_block_cb_priv(block_cb); + err = mlxsw_sp_flow_block_unbind(mlxsw_sp, flow_block, + mlxsw_sp_port, ingress); + if (!err && !flow_block_cb_decref(block_cb)) { + flow_block_cb_remove(block_cb, f); + list_del(&block_cb->driver_list); + } +} + +int mlxsw_sp_setup_tc_block(struct mlxsw_sp_port *mlxsw_sp_port, + struct flow_block_offload *f) +{ + bool ingress; + + if (f->binder_type == FLOW_BLOCK_BINDER_TYPE_CLSACT_INGRESS) + ingress = true; + else if (f->binder_type == FLOW_BLOCK_BINDER_TYPE_CLSACT_EGRESS) + ingress = false; + else + return -EOPNOTSUPP; + + f->driver_block_list = &mlxsw_sp_block_cb_list; + + switch (f->command) { + case FLOW_BLOCK_BIND: + return mlxsw_sp_setup_tc_block_bind(mlxsw_sp_port, f, ingress); + case FLOW_BLOCK_UNBIND: + mlxsw_sp_setup_tc_block_unbind(mlxsw_sp_port, f, ingress); + return 0; + default: + return -EOPNOTSUPP; + } +} -- cgit From 075c8aa79d541ea08c67a2e6d955f6457e98c21c Mon Sep 17 00:00:00 2001 From: Jiri Pirko Date: Mon, 27 Apr 2020 18:13:10 +0300 Subject: selftests: forwarding: tc_actions.sh: add matchall mirror test Add test for matchall classifier with mirred egress mirror action. Signed-off-by: Jiri Pirko Signed-off-by: Ido Schimmel Signed-off-by: David S. Miller --- .../testing/selftests/net/forwarding/tc_actions.sh | 26 +++++++++++++++------- 1 file changed, 18 insertions(+), 8 deletions(-) diff --git a/tools/testing/selftests/net/forwarding/tc_actions.sh b/tools/testing/selftests/net/forwarding/tc_actions.sh index 813d02d1939d..d9eca227136b 100755 --- a/tools/testing/selftests/net/forwarding/tc_actions.sh +++ b/tools/testing/selftests/net/forwarding/tc_actions.sh @@ -2,7 +2,8 @@ # SPDX-License-Identifier: GPL-2.0 ALL_TESTS="gact_drop_and_ok_test mirred_egress_redirect_test \ - mirred_egress_mirror_test gact_trap_test" + mirred_egress_mirror_test matchall_mirred_egress_mirror_test \ + gact_trap_test" NUM_NETIFS=4 source tc_common.sh source lib.sh @@ -50,6 +51,9 @@ switch_destroy() mirred_egress_test() { local action=$1 + local protocol=$2 + local classifier=$3 + local classifier_args=$4 RET=0 @@ -62,9 +66,9 @@ mirred_egress_test() tc_check_packets "dev $h2 ingress" 101 1 check_fail $? "Matched without redirect rule inserted" - tc filter add dev $swp1 ingress protocol ip pref 1 handle 101 flower \ - $tcflags dst_ip 192.0.2.2 action mirred egress $action \ - dev $swp2 + tc filter add dev $swp1 ingress protocol $protocol pref 1 handle 101 \ + $classifier $tcflags $classifier_args \ + action mirred egress $action dev $swp2 $MZ $h1 -c 1 -p 64 -a $h1mac -b $h2mac -A 192.0.2.1 -B 192.0.2.2 \ -t ip -q @@ -72,10 +76,11 @@ mirred_egress_test() tc_check_packets "dev $h2 ingress" 101 1 check_err $? "Did not match incoming $action packet" - tc filter del dev $swp1 ingress protocol ip pref 1 handle 101 flower + tc filter del dev $swp1 ingress protocol $protocol pref 1 handle 101 \ + $classifier tc filter del dev $h2 ingress protocol ip pref 1 handle 101 flower - log_test "mirred egress $action ($tcflags)" + log_test "mirred egress $classifier $action ($tcflags)" } gact_drop_and_ok_test() @@ -187,12 +192,17 @@ cleanup() mirred_egress_redirect_test() { - mirred_egress_test "redirect" + mirred_egress_test "redirect" "ip" "flower" "dst_ip 192.0.2.2" } mirred_egress_mirror_test() { - mirred_egress_test "mirror" + mirred_egress_test "mirror" "ip" "flower" "dst_ip 192.0.2.2" +} + +matchall_mirred_egress_mirror_test() +{ + mirred_egress_test "mirror" "all" "matchall" "" } trap cleanup EXIT -- cgit