1*67d62ee7SRoi Dayan // SPDX-License-Identifier: GPL-2.0 OR Linux-OpenIB 2*67d62ee7SRoi Dayan // Copyright (c) 2021, NVIDIA CORPORATION & AFFILIATES. All rights reserved. 3*67d62ee7SRoi Dayan 4*67d62ee7SRoi Dayan #include "act.h" 5*67d62ee7SRoi Dayan #include "en/tc_priv.h" 6*67d62ee7SRoi Dayan #include "eswitch.h" 7*67d62ee7SRoi Dayan 8*67d62ee7SRoi Dayan static int 9*67d62ee7SRoi Dayan validate_goto_chain(struct mlx5e_priv *priv, 10*67d62ee7SRoi Dayan struct mlx5e_tc_flow *flow, 11*67d62ee7SRoi Dayan const struct flow_action_entry *act, 12*67d62ee7SRoi Dayan struct netlink_ext_ack *extack) 13*67d62ee7SRoi Dayan { 14*67d62ee7SRoi Dayan bool is_esw = mlx5e_is_eswitch_flow(flow); 15*67d62ee7SRoi Dayan bool ft_flow = mlx5e_is_ft_flow(flow); 16*67d62ee7SRoi Dayan u32 dest_chain = act->chain_index; 17*67d62ee7SRoi Dayan struct mlx5_fs_chains *chains; 18*67d62ee7SRoi Dayan struct mlx5_eswitch *esw; 19*67d62ee7SRoi Dayan u32 reformat_and_fwd; 20*67d62ee7SRoi Dayan u32 max_chain; 21*67d62ee7SRoi Dayan 22*67d62ee7SRoi Dayan esw = priv->mdev->priv.eswitch; 23*67d62ee7SRoi Dayan chains = is_esw ? esw_chains(esw) : mlx5e_nic_chains(priv); 24*67d62ee7SRoi Dayan max_chain = mlx5_chains_get_chain_range(chains); 25*67d62ee7SRoi Dayan reformat_and_fwd = is_esw ? 26*67d62ee7SRoi Dayan MLX5_CAP_ESW_FLOWTABLE_FDB(priv->mdev, reformat_and_fwd_to_table) : 27*67d62ee7SRoi Dayan MLX5_CAP_FLOWTABLE_NIC_RX(priv->mdev, reformat_and_fwd_to_table); 28*67d62ee7SRoi Dayan 29*67d62ee7SRoi Dayan if (ft_flow) { 30*67d62ee7SRoi Dayan NL_SET_ERR_MSG_MOD(extack, "Goto action is not supported"); 31*67d62ee7SRoi Dayan return -EOPNOTSUPP; 32*67d62ee7SRoi Dayan } 33*67d62ee7SRoi Dayan 34*67d62ee7SRoi Dayan if (!mlx5_chains_backwards_supported(chains) && 35*67d62ee7SRoi Dayan dest_chain <= flow->attr->chain) { 36*67d62ee7SRoi Dayan NL_SET_ERR_MSG_MOD(extack, "Goto lower numbered chain isn't supported"); 37*67d62ee7SRoi Dayan return -EOPNOTSUPP; 38*67d62ee7SRoi Dayan } 39*67d62ee7SRoi Dayan 40*67d62ee7SRoi Dayan if (dest_chain > max_chain) { 41*67d62ee7SRoi Dayan NL_SET_ERR_MSG_MOD(extack, 42*67d62ee7SRoi Dayan "Requested destination chain is out of supported range"); 43*67d62ee7SRoi Dayan return -EOPNOTSUPP; 44*67d62ee7SRoi Dayan } 45*67d62ee7SRoi Dayan 46*67d62ee7SRoi Dayan if (flow->attr->action & (MLX5_FLOW_CONTEXT_ACTION_PACKET_REFORMAT | 47*67d62ee7SRoi Dayan MLX5_FLOW_CONTEXT_ACTION_DECAP) && 48*67d62ee7SRoi Dayan !reformat_and_fwd) { 49*67d62ee7SRoi Dayan NL_SET_ERR_MSG_MOD(extack, 50*67d62ee7SRoi Dayan "Goto chain is not allowed if action has reformat or decap"); 51*67d62ee7SRoi Dayan return -EOPNOTSUPP; 52*67d62ee7SRoi Dayan } 53*67d62ee7SRoi Dayan 54*67d62ee7SRoi Dayan return 0; 55*67d62ee7SRoi Dayan } 56*67d62ee7SRoi Dayan 57*67d62ee7SRoi Dayan static bool 58*67d62ee7SRoi Dayan tc_act_can_offload_goto(struct mlx5e_tc_act_parse_state *parse_state, 59*67d62ee7SRoi Dayan const struct flow_action_entry *act, 60*67d62ee7SRoi Dayan int act_index) 61*67d62ee7SRoi Dayan { 62*67d62ee7SRoi Dayan struct netlink_ext_ack *extack = parse_state->extack; 63*67d62ee7SRoi Dayan struct mlx5e_tc_flow *flow = parse_state->flow; 64*67d62ee7SRoi Dayan 65*67d62ee7SRoi Dayan if (validate_goto_chain(flow->priv, flow, act, extack)) 66*67d62ee7SRoi Dayan return false; 67*67d62ee7SRoi Dayan 68*67d62ee7SRoi Dayan return true; 69*67d62ee7SRoi Dayan } 70*67d62ee7SRoi Dayan 71*67d62ee7SRoi Dayan static int 72*67d62ee7SRoi Dayan tc_act_parse_goto(struct mlx5e_tc_act_parse_state *parse_state, 73*67d62ee7SRoi Dayan const struct flow_action_entry *act, 74*67d62ee7SRoi Dayan struct mlx5e_priv *priv, 75*67d62ee7SRoi Dayan struct mlx5_flow_attr *attr) 76*67d62ee7SRoi Dayan { 77*67d62ee7SRoi Dayan attr->action |= MLX5_FLOW_CONTEXT_ACTION_FWD_DEST | 78*67d62ee7SRoi Dayan MLX5_FLOW_CONTEXT_ACTION_COUNT; 79*67d62ee7SRoi Dayan attr->dest_chain = act->chain_index; 80*67d62ee7SRoi Dayan 81*67d62ee7SRoi Dayan return 0; 82*67d62ee7SRoi Dayan } 83*67d62ee7SRoi Dayan 84*67d62ee7SRoi Dayan struct mlx5e_tc_act mlx5e_tc_act_goto = { 85*67d62ee7SRoi Dayan .can_offload = tc_act_can_offload_goto, 86*67d62ee7SRoi Dayan .parse_action = tc_act_parse_goto, 87*67d62ee7SRoi Dayan }; 88