Offload the TC action trap_fwd. This is offloaded as a TRAP_ACTION with forward_action of FORWARD (as opposed to NOP for the trap action). Unlike trap, trap_fwd needs to be in an "goto"-typed action set, not "next"-typed one.
Trap_fwd'd traffic is marked with offload_fwd_mark and offload_l3_fwd_mark to prevent second forwarding in the SW datapath. Signed-off-by: Petr Machata <pe...@nvidia.com> Reviewed-by: Ido Schimmel <ido...@nvidia.com> --- .../mellanox/mlxsw/core_acl_flex_actions.c | 23 +++++++++++++++---- .../net/ethernet/mellanox/mlxsw/spectrum.h | 1 + .../ethernet/mellanox/mlxsw/spectrum_acl.c | 6 +++++ .../ethernet/mellanox/mlxsw/spectrum_flower.c | 7 ++++++ .../ethernet/mellanox/mlxsw/spectrum_trap.c | 8 +++++++ drivers/net/ethernet/mellanox/mlxsw/trap.h | 2 ++ 6 files changed, 43 insertions(+), 4 deletions(-) diff --git a/drivers/net/ethernet/mellanox/mlxsw/core_acl_flex_actions.c b/drivers/net/ethernet/mellanox/mlxsw/core_acl_flex_actions.c index faa90cc31376..d7d7e688139f 100644 --- a/drivers/net/ethernet/mellanox/mlxsw/core_acl_flex_actions.c +++ b/drivers/net/ethernet/mellanox/mlxsw/core_acl_flex_actions.c @@ -94,7 +94,8 @@ struct mlxsw_afa_set { * kvdl_index is valid). */ has_trap:1, - has_police:1; + has_police:1, + has_trap_fwd:1; unsigned int ref_count; struct mlxsw_afa_set *next; /* Pointer to the next set. */ struct mlxsw_afa_set *prev; /* Pointer to the previous set, @@ -263,14 +264,23 @@ static void mlxsw_afa_set_goto_set(struct mlxsw_afa_set *set, mlxsw_afa_set_goto_next_binding_set(actions, group_id); } -static void mlxsw_afa_set_next_set(struct mlxsw_afa_set *set, +static int mlxsw_afa_set_next_set(struct mlxsw_afa_set *set, u32 next_set_kvdl_index, struct netlink_ext_ack *extack) { char *actions = set->ht_key.enc_actions; + /* If the forwarding action is not drop, the next/goto record must not + * be a next, it must be a goto. + */ + if (set->has_trap_fwd) { + NL_SET_ERR_MSG_MOD(extack, "Only goto permissible after a trap_fwd action"); + return -EINVAL; + } + mlxsw_afa_set_type_set(actions, MLXSW_AFA_SET_TYPE_NEXT); mlxsw_afa_set_next_action_set_ptr_set(actions, next_set_kvdl_index); + return 0; } static struct mlxsw_afa_set *mlxsw_afa_set_create(bool is_first) @@ -461,6 +471,7 @@ int mlxsw_afa_block_commit(struct mlxsw_afa_block *block, { struct mlxsw_afa_set *set = block->cur_set; struct mlxsw_afa_set *prev_set; + int err; block->cur_set = NULL; block->finished = true; @@ -481,8 +492,10 @@ int mlxsw_afa_block_commit(struct mlxsw_afa_block *block, return PTR_ERR(set); if (prev_set) { prev_set->next = set; - mlxsw_afa_set_next_set(prev_set, set->kvdl_index, - extack); + err = mlxsw_afa_set_next_set(prev_set, set->kvdl_index, + extack); + if (err) + return err; set = prev_set; } } while (prev_set); @@ -1346,6 +1359,8 @@ int mlxsw_afa_block_append_trap_and_forward(struct mlxsw_afa_block *block, if (IS_ERR(act)) return PTR_ERR(act); + + block->cur_set->has_trap_fwd = true; mlxsw_afa_trap_pack(act, MLXSW_AFA_TRAP_TRAP_ACTION_TRAP, MLXSW_AFA_TRAP_FORWARD_ACTION_FORWARD, trap_id); return 0; diff --git a/drivers/net/ethernet/mellanox/mlxsw/spectrum.h b/drivers/net/ethernet/mellanox/mlxsw/spectrum.h index d74fc7ff8083..6067a049dcf2 100644 --- a/drivers/net/ethernet/mellanox/mlxsw/spectrum.h +++ b/drivers/net/ethernet/mellanox/mlxsw/spectrum.h @@ -940,6 +940,7 @@ int mlxsw_sp_acl_rulei_act_drop(struct mlxsw_sp_acl_rule_info *rulei, const struct flow_action_cookie *fa_cookie, struct netlink_ext_ack *extack); int mlxsw_sp_acl_rulei_act_trap(struct mlxsw_sp_acl_rule_info *rulei); +int mlxsw_sp_acl_rulei_act_trap_fwd(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_flow_block *block, diff --git a/drivers/net/ethernet/mellanox/mlxsw/spectrum_acl.c b/drivers/net/ethernet/mellanox/mlxsw/spectrum_acl.c index b9c4c1feba6d..6f7913424bd9 100644 --- a/drivers/net/ethernet/mellanox/mlxsw/spectrum_acl.c +++ b/drivers/net/ethernet/mellanox/mlxsw/spectrum_acl.c @@ -401,6 +401,12 @@ int mlxsw_sp_acl_rulei_act_trap(struct mlxsw_sp_acl_rule_info *rulei) MLXSW_TRAP_ID_ACL0); } +int mlxsw_sp_acl_rulei_act_trap_fwd(struct mlxsw_sp_acl_rule_info *rulei) +{ + return mlxsw_afa_block_append_trap_and_forward(rulei->act_block, + MLXSW_TRAP_ID_ACL3); +} + int mlxsw_sp_acl_rulei_act_fwd(struct mlxsw_sp *mlxsw_sp, struct mlxsw_sp_acl_rule_info *rulei, struct net_device *out_dev, diff --git a/drivers/net/ethernet/mellanox/mlxsw/spectrum_flower.c b/drivers/net/ethernet/mellanox/mlxsw/spectrum_flower.c index 936788f741dd..1f52ea7ba202 100644 --- a/drivers/net/ethernet/mellanox/mlxsw/spectrum_flower.c +++ b/drivers/net/ethernet/mellanox/mlxsw/spectrum_flower.c @@ -86,6 +86,13 @@ static int mlxsw_sp_flower_parse_actions(struct mlxsw_sp *mlxsw_sp, return err; } break; + case FLOW_ACTION_TRAP_FWD: + err = mlxsw_sp_acl_rulei_act_trap_fwd(rulei); + if (err) { + NL_SET_ERR_MSG_MOD(extack, "Cannot append trap_fwd action"); + return err; + } + break; case FLOW_ACTION_GOTO: { u32 chain_index = act->chain_index; struct mlxsw_sp_acl_ruleset *ruleset; diff --git a/drivers/net/ethernet/mellanox/mlxsw/spectrum_trap.c b/drivers/net/ethernet/mellanox/mlxsw/spectrum_trap.c index 26d01adbedad..504fb7440a1f 100644 --- a/drivers/net/ethernet/mellanox/mlxsw/spectrum_trap.c +++ b/drivers/net/ethernet/mellanox/mlxsw/spectrum_trap.c @@ -1154,6 +1154,14 @@ static const struct mlxsw_sp_trap_item mlxsw_sp_trap_items_arr[] = { false), }, }, + { + .trap = MLXSW_SP_TRAP_CONTROL(FLOW_ACTION_TRAP_FWD, + ACL_TRAP, MIRROR), + .listeners_arr = { + MLXSW_SP_RXL_L3_MARK(ACL3, FLOW_LOGGING, MIRROR_TO_CPU, + false), + }, + }, { .trap = MLXSW_SP_TRAP_DROP(BLACKHOLE_NEXTHOP, L3_DROPS), .listeners_arr = { diff --git a/drivers/net/ethernet/mellanox/mlxsw/trap.h b/drivers/net/ethernet/mellanox/mlxsw/trap.h index 9e070ab3ed76..5271d7ad092a 100644 --- a/drivers/net/ethernet/mellanox/mlxsw/trap.h +++ b/drivers/net/ethernet/mellanox/mlxsw/trap.h @@ -108,6 +108,8 @@ enum { MLXSW_TRAP_ID_ACL2 = 0x1C2, MLXSW_TRAP_ID_DISCARD_INGRESS_ACL = 0x1C3, MLXSW_TRAP_ID_DISCARD_EGRESS_ACL = 0x1C4, + /* Packets trapped due to FLOW_ACTION_TRAP_FWD. */ + MLXSW_TRAP_ID_ACL3 = 0x1C5, MLXSW_TRAP_ID_MIRROR_SESSION0 = 0x220, MLXSW_TRAP_ID_MIRROR_SESSION1 = 0x221, MLXSW_TRAP_ID_MIRROR_SESSION2 = 0x222, -- 2.26.2