Merge tag 'arm64-upstream' of git://git.kernel.org/pub/scm/linux/kernel/git/arm64...
[linux-2.6-microblaze.git] / drivers / net / ethernet / mellanox / mlx5 / core / en / tc / act / act.c
1 // SPDX-License-Identifier: GPL-2.0 OR Linux-OpenIB
2 // Copyright (c) 2021, NVIDIA CORPORATION & AFFILIATES. All rights reserved.
3
4 #include "act.h"
5 #include "en/tc/post_act.h"
6 #include "en/tc_priv.h"
7 #include "mlx5_core.h"
8
9 /* Must be aligned with enum flow_action_id. */
10 static struct mlx5e_tc_act *tc_acts_fdb[NUM_FLOW_ACTIONS] = {
11         &mlx5e_tc_act_accept,
12         &mlx5e_tc_act_drop,
13         &mlx5e_tc_act_trap,
14         &mlx5e_tc_act_goto,
15         &mlx5e_tc_act_mirred,
16         &mlx5e_tc_act_mirred,
17         &mlx5e_tc_act_redirect_ingress,
18         NULL, /* FLOW_ACTION_MIRRED_INGRESS, */
19         &mlx5e_tc_act_vlan,
20         &mlx5e_tc_act_vlan,
21         &mlx5e_tc_act_vlan_mangle,
22         &mlx5e_tc_act_tun_encap,
23         &mlx5e_tc_act_tun_decap,
24         &mlx5e_tc_act_pedit,
25         &mlx5e_tc_act_pedit,
26         &mlx5e_tc_act_csum,
27         NULL, /* FLOW_ACTION_MARK, */
28         &mlx5e_tc_act_ptype,
29         NULL, /* FLOW_ACTION_PRIORITY, */
30         NULL, /* FLOW_ACTION_WAKE, */
31         NULL, /* FLOW_ACTION_QUEUE, */
32         &mlx5e_tc_act_sample,
33         NULL, /* FLOW_ACTION_POLICE, */
34         &mlx5e_tc_act_ct,
35         NULL, /* FLOW_ACTION_CT_METADATA, */
36         &mlx5e_tc_act_mpls_push,
37         &mlx5e_tc_act_mpls_pop,
38         NULL, /* FLOW_ACTION_MPLS_MANGLE, */
39         NULL, /* FLOW_ACTION_GATE, */
40         NULL, /* FLOW_ACTION_PPPOE_PUSH, */
41         NULL, /* FLOW_ACTION_JUMP, */
42         NULL, /* FLOW_ACTION_PIPE, */
43         &mlx5e_tc_act_vlan,
44         &mlx5e_tc_act_vlan,
45 };
46
47 /* Must be aligned with enum flow_action_id. */
48 static struct mlx5e_tc_act *tc_acts_nic[NUM_FLOW_ACTIONS] = {
49         &mlx5e_tc_act_accept,
50         &mlx5e_tc_act_drop,
51         NULL, /* FLOW_ACTION_TRAP, */
52         &mlx5e_tc_act_goto,
53         &mlx5e_tc_act_mirred_nic,
54         NULL, /* FLOW_ACTION_MIRRED, */
55         NULL, /* FLOW_ACTION_REDIRECT_INGRESS, */
56         NULL, /* FLOW_ACTION_MIRRED_INGRESS, */
57         NULL, /* FLOW_ACTION_VLAN_PUSH, */
58         NULL, /* FLOW_ACTION_VLAN_POP, */
59         NULL, /* FLOW_ACTION_VLAN_MANGLE, */
60         NULL, /* FLOW_ACTION_TUNNEL_ENCAP, */
61         NULL, /* FLOW_ACTION_TUNNEL_DECAP, */
62         &mlx5e_tc_act_pedit,
63         &mlx5e_tc_act_pedit,
64         &mlx5e_tc_act_csum,
65         &mlx5e_tc_act_mark,
66         NULL, /* FLOW_ACTION_PTYPE, */
67         NULL, /* FLOW_ACTION_PRIORITY, */
68         NULL, /* FLOW_ACTION_WAKE, */
69         NULL, /* FLOW_ACTION_QUEUE, */
70         NULL, /* FLOW_ACTION_SAMPLE, */
71         NULL, /* FLOW_ACTION_POLICE, */
72         &mlx5e_tc_act_ct,
73 };
74
75 /**
76  * mlx5e_tc_act_get() - Get an action parser for an action id.
77  * @act_id: Flow action id.
78  * @ns_type: flow namespace type.
79  */
80 struct mlx5e_tc_act *
81 mlx5e_tc_act_get(enum flow_action_id act_id,
82                  enum mlx5_flow_namespace_type ns_type)
83 {
84         struct mlx5e_tc_act **tc_acts;
85
86         tc_acts = ns_type == MLX5_FLOW_NAMESPACE_FDB ? tc_acts_fdb : tc_acts_nic;
87
88         return tc_acts[act_id];
89 }
90
91 /**
92  * mlx5e_tc_act_init_parse_state() - Init a new parse_state.
93  * @parse_state: Parsing state.
94  * @flow:        mlx5e tc flow being handled.
95  * @flow_action: flow action to parse.
96  * @extack:      to set an error msg.
97  *
98  * The same parse_state should be passed to action parsers
99  * for tracking the current parsing state.
100  */
101 void
102 mlx5e_tc_act_init_parse_state(struct mlx5e_tc_act_parse_state *parse_state,
103                               struct mlx5e_tc_flow *flow,
104                               struct flow_action *flow_action,
105                               struct netlink_ext_ack *extack)
106 {
107         memset(parse_state, 0, sizeof(*parse_state));
108         parse_state->flow = flow;
109         parse_state->num_actions = flow_action->num_entries;
110         parse_state->extack = extack;
111 }
112
113 void
114 mlx5e_tc_act_reorder_flow_actions(struct flow_action *flow_action,
115                                   struct mlx5e_tc_flow_action *flow_action_reorder)
116 {
117         struct flow_action_entry *act;
118         int i, j = 0;
119
120         flow_action_for_each(i, act, flow_action) {
121                 /* Add CT action to be first. */
122                 if (act->id == FLOW_ACTION_CT)
123                         flow_action_reorder->entries[j++] = act;
124         }
125
126         flow_action_for_each(i, act, flow_action) {
127                 if (act->id == FLOW_ACTION_CT)
128                         continue;
129                 flow_action_reorder->entries[j++] = act;
130         }
131 }
132
133 int
134 mlx5e_tc_act_post_parse(struct mlx5e_tc_act_parse_state *parse_state,
135                         struct flow_action *flow_action,
136                         struct mlx5_flow_attr *attr,
137                         enum mlx5_flow_namespace_type ns_type)
138 {
139         struct flow_action_entry *act;
140         struct mlx5e_tc_act *tc_act;
141         struct mlx5e_priv *priv;
142         int err = 0, i;
143
144         priv = parse_state->flow->priv;
145
146         flow_action_for_each(i, act, flow_action) {
147                 tc_act = mlx5e_tc_act_get(act->id, ns_type);
148                 if (!tc_act || !tc_act->post_parse)
149                         continue;
150
151                 err = tc_act->post_parse(parse_state, priv, attr);
152                 if (err)
153                         goto out;
154         }
155
156 out:
157         return err;
158 }
159
160 int
161 mlx5e_tc_act_set_next_post_act(struct mlx5e_tc_flow *flow,
162                                struct mlx5_flow_attr *attr,
163                                struct mlx5_flow_attr *next_attr)
164 {
165         struct mlx5_core_dev *mdev = flow->priv->mdev;
166         struct mlx5e_tc_mod_hdr_acts *mod_acts;
167         int err;
168
169         mod_acts = &attr->parse_attr->mod_hdr_acts;
170
171         /* Set handle on current post act rule to next post act rule. */
172         err = mlx5e_tc_post_act_set_handle(mdev, next_attr->post_act_handle, mod_acts);
173         if (err) {
174                 mlx5_core_warn(mdev, "Failed setting post action handle");
175                 return err;
176         }
177
178         attr->action |= MLX5_FLOW_CONTEXT_ACTION_FWD_DEST |
179                         MLX5_FLOW_CONTEXT_ACTION_MOD_HDR;
180
181         return 0;
182 }