// SPDX-License-Identifier: GPL-2.0 OR Linux-OpenIB // Copyright (c) 2021, NVIDIA CORPORATION & AFFILIATES. All rights reserved. #include "act.h" #include "en/tc/post_act.h" #include "en/tc_priv.h" #include "mlx5_core.h" /* Must be aligned with enum flow_action_id. */ static struct mlx5e_tc_act *tc_acts_fdb[NUM_FLOW_ACTIONS] = { &mlx5e_tc_act_accept, &mlx5e_tc_act_drop, &mlx5e_tc_act_trap, &mlx5e_tc_act_goto, &mlx5e_tc_act_mirred, &mlx5e_tc_act_mirred, &mlx5e_tc_act_redirect_ingress, NULL, /* FLOW_ACTION_MIRRED_INGRESS, */ &mlx5e_tc_act_vlan, &mlx5e_tc_act_vlan, &mlx5e_tc_act_vlan_mangle, &mlx5e_tc_act_tun_encap, &mlx5e_tc_act_tun_decap, &mlx5e_tc_act_pedit, &mlx5e_tc_act_pedit, &mlx5e_tc_act_csum, NULL, /* FLOW_ACTION_MARK, */ &mlx5e_tc_act_ptype, NULL, /* FLOW_ACTION_PRIORITY, */ NULL, /* FLOW_ACTION_WAKE, */ NULL, /* FLOW_ACTION_QUEUE, */ &mlx5e_tc_act_sample, NULL, /* FLOW_ACTION_POLICE, */ &mlx5e_tc_act_ct, NULL, /* FLOW_ACTION_CT_METADATA, */ &mlx5e_tc_act_mpls_push, &mlx5e_tc_act_mpls_pop, NULL, /* FLOW_ACTION_MPLS_MANGLE, */ NULL, /* FLOW_ACTION_GATE, */ NULL, /* FLOW_ACTION_PPPOE_PUSH, */ NULL, /* FLOW_ACTION_JUMP, */ NULL, /* FLOW_ACTION_PIPE, */ &mlx5e_tc_act_vlan, &mlx5e_tc_act_vlan, }; /* Must be aligned with enum flow_action_id. */ static struct mlx5e_tc_act *tc_acts_nic[NUM_FLOW_ACTIONS] = { &mlx5e_tc_act_accept, &mlx5e_tc_act_drop, NULL, /* FLOW_ACTION_TRAP, */ &mlx5e_tc_act_goto, &mlx5e_tc_act_mirred_nic, NULL, /* FLOW_ACTION_MIRRED, */ NULL, /* FLOW_ACTION_REDIRECT_INGRESS, */ NULL, /* FLOW_ACTION_MIRRED_INGRESS, */ NULL, /* FLOW_ACTION_VLAN_PUSH, */ NULL, /* FLOW_ACTION_VLAN_POP, */ NULL, /* FLOW_ACTION_VLAN_MANGLE, */ NULL, /* FLOW_ACTION_TUNNEL_ENCAP, */ NULL, /* FLOW_ACTION_TUNNEL_DECAP, */ &mlx5e_tc_act_pedit, &mlx5e_tc_act_pedit, &mlx5e_tc_act_csum, &mlx5e_tc_act_mark, NULL, /* FLOW_ACTION_PTYPE, */ NULL, /* FLOW_ACTION_PRIORITY, */ NULL, /* FLOW_ACTION_WAKE, */ NULL, /* FLOW_ACTION_QUEUE, */ NULL, /* FLOW_ACTION_SAMPLE, */ NULL, /* FLOW_ACTION_POLICE, */ &mlx5e_tc_act_ct, }; /** * mlx5e_tc_act_get() - Get an action parser for an action id. * @act_id: Flow action id. * @ns_type: flow namespace type. */ struct mlx5e_tc_act * mlx5e_tc_act_get(enum flow_action_id act_id, enum mlx5_flow_namespace_type ns_type) { struct mlx5e_tc_act **tc_acts; tc_acts = ns_type == MLX5_FLOW_NAMESPACE_FDB ? tc_acts_fdb : tc_acts_nic; return tc_acts[act_id]; } /** * mlx5e_tc_act_init_parse_state() - Init a new parse_state. * @parse_state: Parsing state. * @flow: mlx5e tc flow being handled. * @flow_action: flow action to parse. * @extack: to set an error msg. * * The same parse_state should be passed to action parsers * for tracking the current parsing state. */ void mlx5e_tc_act_init_parse_state(struct mlx5e_tc_act_parse_state *parse_state, struct mlx5e_tc_flow *flow, struct flow_action *flow_action, struct netlink_ext_ack *extack) { memset(parse_state, 0, sizeof(*parse_state)); parse_state->flow = flow; parse_state->num_actions = flow_action->num_entries; parse_state->extack = extack; } void mlx5e_tc_act_reorder_flow_actions(struct flow_action *flow_action, struct mlx5e_tc_flow_action *flow_action_reorder) { struct flow_action_entry *act; int i, j = 0; flow_action_for_each(i, act, flow_action) { /* Add CT action to be first. */ if (act->id == FLOW_ACTION_CT) flow_action_reorder->entries[j++] = act; } flow_action_for_each(i, act, flow_action) { if (act->id == FLOW_ACTION_CT) continue; flow_action_reorder->entries[j++] = act; } } int mlx5e_tc_act_post_parse(struct mlx5e_tc_act_parse_state *parse_state, struct flow_action *flow_action, struct mlx5_flow_attr *attr, enum mlx5_flow_namespace_type ns_type) { struct flow_action_entry *act; struct mlx5e_tc_act *tc_act; struct mlx5e_priv *priv; int err = 0, i; priv = parse_state->flow->priv; flow_action_for_each(i, act, flow_action) { tc_act = mlx5e_tc_act_get(act->id, ns_type); if (!tc_act || !tc_act->post_parse) continue; err = tc_act->post_parse(parse_state, priv, attr); if (err) goto out; } out: return err; } int mlx5e_tc_act_set_next_post_act(struct mlx5e_tc_flow *flow, struct mlx5_flow_attr *attr, struct mlx5_flow_attr *next_attr) { struct mlx5_core_dev *mdev = flow->priv->mdev; struct mlx5e_tc_mod_hdr_acts *mod_acts; int err; mod_acts = &attr->parse_attr->mod_hdr_acts; /* Set handle on current post act rule to next post act rule. */ err = mlx5e_tc_post_act_set_handle(mdev, next_attr->post_act_handle, mod_acts); if (err) { mlx5_core_warn(mdev, "Failed setting post action handle"); return err; } attr->action |= MLX5_FLOW_CONTEXT_ACTION_FWD_DEST | MLX5_FLOW_CONTEXT_ACTION_MOD_HDR; return 0; }