]> git.proxmox.com Git - mirror_ubuntu-jammy-kernel.git/blame - drivers/net/ethernet/mellanox/mlx5/core/en_tc.c
net/mlx5e: Support accept action
[mirror_ubuntu-jammy-kernel.git] / drivers / net / ethernet / mellanox / mlx5 / core / en_tc.c
CommitLineData
e8f887ac
AV
1/*
2 * Copyright (c) 2016, Mellanox Technologies. All rights reserved.
3 *
4 * This software is available to you under a choice of one of two
5 * licenses. You may choose to be licensed under the terms of the GNU
6 * General Public License (GPL) Version 2, available from the file
7 * COPYING in the main directory of this source tree, or the
8 * OpenIB.org BSD license below:
9 *
10 * Redistribution and use in source and binary forms, with or
11 * without modification, are permitted provided that the following
12 * conditions are met:
13 *
14 * - Redistributions of source code must retain the above
15 * copyright notice, this list of conditions and the following
16 * disclaimer.
17 *
18 * - Redistributions in binary form must reproduce the above
19 * copyright notice, this list of conditions and the following
20 * disclaimer in the documentation and/or other materials
21 * provided with the distribution.
22 *
23 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
24 * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
25 * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
26 * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
27 * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
28 * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
29 * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
30 * SOFTWARE.
31 */
32
e3a2b7ed 33#include <net/flow_dissector.h>
e2394a61 34#include <net/flow_offload.h>
3f7d0eb4 35#include <net/sch_generic.h>
e3a2b7ed 36#include <net/pkt_cls.h>
e8f887ac
AV
37#include <linux/mlx5/fs.h>
38#include <linux/mlx5/device.h>
39#include <linux/rhashtable.h>
5a7e5bcb 40#include <linux/refcount.h>
db76ca24 41#include <linux/completion.h>
d79b6df6 42#include <net/tc_act/tc_pedit.h>
26c02749 43#include <net/tc_act/tc_csum.h>
41c2fd94 44#include <net/psample.h>
f6dfb4c3 45#include <net/arp.h>
3616d08b 46#include <net/ipv6_stubs.h>
f828ca6a 47#include <net/bareudp.h>
d34eb2fc 48#include <net/bonding.h>
e8f887ac 49#include "en.h"
f0da4daa 50#include "en/tc/post_act.h"
1d447a39 51#include "en_rep.h"
768c3667 52#include "en/rep/tc.h"
e2394a61 53#include "en/rep/neigh.h"
232c0013 54#include "en_tc.h"
03a9d11e 55#include "eswitch.h"
3f6d08d1 56#include "fs_core.h"
2c81bfd5 57#include "en/port.h"
101f4de9 58#include "en/tc_tun.h"
0a7fcb78 59#include "en/mapping.h"
4c3844d9 60#include "en/tc_ct.h"
b2fdf3d0 61#include "en/mod_hdr.h"
0d9f9647 62#include "en/tc_tun_encap.h"
0027d70c 63#include "en/tc/sample.h"
04de7dda 64#include "lib/devcom.h"
9272e3df 65#include "lib/geneve.h"
ae430332 66#include "lib/fs_chains.h"
7a978759 67#include "diag/en_tc_tracepoint.h"
1fe3e316 68#include <asm/div64.h>
14fe2471
MD
69#include "lag.h"
70#include "lag_mp.h"
e8f887ac 71
6a064674 72#define nic_chains(priv) ((priv)->fs.tc.chains)
d65dbedf 73#define MLX5_MH_ACT_SZ MLX5_UN_SZ_BYTES(set_add_copy_action_in_auto)
17091853 74
acff797c 75#define MLX5E_TC_TABLE_NUM_GROUPS 4
6a064674 76#define MLX5E_TC_TABLE_MAX_GROUP_SIZE BIT(18)
e8f887ac 77
8f1e0b97
PB
78struct mlx5e_tc_attr_to_reg_mapping mlx5e_tc_attr_to_reg_mappings[] = {
79 [CHAIN_TO_REG] = {
80 .mfield = MLX5_ACTION_IN_FIELD_METADATA_REG_C_0,
81 .moffset = 0,
ed2fe7ba 82 .mlen = 16,
8f1e0b97 83 },
10742efc
VB
84 [VPORT_TO_REG] = {
85 .mfield = MLX5_ACTION_IN_FIELD_METADATA_REG_C_0,
ed2fe7ba
PB
86 .moffset = 16,
87 .mlen = 16,
10742efc 88 },
0a7fcb78
PB
89 [TUNNEL_TO_REG] = {
90 .mfield = MLX5_ACTION_IN_FIELD_METADATA_REG_C_1,
ed2fe7ba
PB
91 .moffset = 8,
92 .mlen = ESW_TUN_OPTS_BITS + ESW_TUN_ID_BITS,
0a7fcb78
PB
93 .soffset = MLX5_BYTE_OFF(fte_match_param,
94 misc_parameters_2.metadata_reg_c_1),
95 },
4c3844d9 96 [ZONE_TO_REG] = zone_to_reg_ct,
a8eb919b 97 [ZONE_RESTORE_TO_REG] = zone_restore_to_reg_ct,
4c3844d9
PB
98 [CTSTATE_TO_REG] = ctstate_to_reg_ct,
99 [MARK_TO_REG] = mark_to_reg_ct,
100 [LABELS_TO_REG] = labels_to_reg_ct,
101 [FTEID_TO_REG] = fteid_to_reg_ct,
39c538d6 102 /* For NIC rules we store the restore metadata directly
c7569097
AL
103 * into reg_b that is passed to SW since we don't
104 * jump between steering domains.
105 */
106 [NIC_CHAIN_TO_REG] = {
107 .mfield = MLX5_ACTION_IN_FIELD_METADATA_REG_B,
108 .moffset = 0,
ed2fe7ba 109 .mlen = 16,
c7569097 110 },
aedd133d 111 [NIC_ZONE_RESTORE_TO_REG] = nic_zone_restore_to_reg_ct,
8f1e0b97
PB
112};
113
9ba33339
RD
114/* To avoid false lock dependency warning set the tc_ht lock
115 * class different than the lock class of the ht being used when deleting
116 * last flow from a group and then deleting a group, we get into del_sw_flow_group()
117 * which call rhashtable_destroy on fg->ftes_hash which will take ht->mutex but
118 * it's different than the ht->mutex here.
119 */
120static struct lock_class_key tc_ht_lock_key;
121
0a7fcb78
PB
122static void mlx5e_put_flow_tunnel_id(struct mlx5e_tc_flow *flow);
123
124void
125mlx5e_tc_match_to_reg_match(struct mlx5_flow_spec *spec,
126 enum mlx5e_tc_attr_to_reg type,
ed2fe7ba 127 u32 val,
0a7fcb78
PB
128 u32 mask)
129{
ed2fe7ba 130 void *headers_c = spec->match_criteria, *headers_v = spec->match_value, *fmask, *fval;
0a7fcb78 131 int soffset = mlx5e_tc_attr_to_reg_mappings[type].soffset;
ed2fe7ba 132 int moffset = mlx5e_tc_attr_to_reg_mappings[type].moffset;
0a7fcb78 133 int match_len = mlx5e_tc_attr_to_reg_mappings[type].mlen;
ed2fe7ba
PB
134 u32 max_mask = GENMASK(match_len - 1, 0);
135 __be32 curr_mask_be, curr_val_be;
136 u32 curr_mask, curr_val;
0a7fcb78
PB
137
138 fmask = headers_c + soffset;
139 fval = headers_v + soffset;
140
ed2fe7ba
PB
141 memcpy(&curr_mask_be, fmask, 4);
142 memcpy(&curr_val_be, fval, 4);
143
144 curr_mask = be32_to_cpu(curr_mask_be);
145 curr_val = be32_to_cpu(curr_val_be);
146
147 //move to correct offset
148 WARN_ON(mask > max_mask);
149 mask <<= moffset;
150 val <<= moffset;
151 max_mask <<= moffset;
152
153 //zero val and mask
154 curr_mask &= ~max_mask;
155 curr_val &= ~max_mask;
0a7fcb78 156
ed2fe7ba
PB
157 //add current to mask
158 curr_mask |= mask;
159 curr_val |= val;
160
161 //back to be32 and write
162 curr_mask_be = cpu_to_be32(curr_mask);
163 curr_val_be = cpu_to_be32(curr_val);
164
165 memcpy(fmask, &curr_mask_be, 4);
166 memcpy(fval, &curr_val_be, 4);
0a7fcb78
PB
167
168 spec->match_criteria_enable |= MLX5_MATCH_MISC_PARAMETERS_2;
169}
170
7e36feeb
PB
171void
172mlx5e_tc_match_to_reg_get_match(struct mlx5_flow_spec *spec,
173 enum mlx5e_tc_attr_to_reg type,
ed2fe7ba 174 u32 *val,
7e36feeb
PB
175 u32 *mask)
176{
ed2fe7ba 177 void *headers_c = spec->match_criteria, *headers_v = spec->match_value, *fmask, *fval;
7e36feeb 178 int soffset = mlx5e_tc_attr_to_reg_mappings[type].soffset;
ed2fe7ba 179 int moffset = mlx5e_tc_attr_to_reg_mappings[type].moffset;
7e36feeb 180 int match_len = mlx5e_tc_attr_to_reg_mappings[type].mlen;
ed2fe7ba
PB
181 u32 max_mask = GENMASK(match_len - 1, 0);
182 __be32 curr_mask_be, curr_val_be;
183 u32 curr_mask, curr_val;
7e36feeb
PB
184
185 fmask = headers_c + soffset;
186 fval = headers_v + soffset;
187
ed2fe7ba
PB
188 memcpy(&curr_mask_be, fmask, 4);
189 memcpy(&curr_val_be, fval, 4);
190
191 curr_mask = be32_to_cpu(curr_mask_be);
192 curr_val = be32_to_cpu(curr_val_be);
7e36feeb 193
ed2fe7ba
PB
194 *mask = (curr_mask >> moffset) & max_mask;
195 *val = (curr_val >> moffset) & max_mask;
7e36feeb
PB
196}
197
0a7fcb78 198int
c7b9038d
VB
199mlx5e_tc_match_to_reg_set_and_get_id(struct mlx5_core_dev *mdev,
200 struct mlx5e_tc_mod_hdr_acts *mod_hdr_acts,
201 enum mlx5_flow_namespace_type ns,
202 enum mlx5e_tc_attr_to_reg type,
203 u32 data)
0a7fcb78
PB
204{
205 int moffset = mlx5e_tc_attr_to_reg_mappings[type].moffset;
206 int mfield = mlx5e_tc_attr_to_reg_mappings[type].mfield;
207 int mlen = mlx5e_tc_attr_to_reg_mappings[type].mlen;
208 char *modact;
209 int err;
210
aedd133d 211 err = alloc_mod_hdr_actions(mdev, ns, mod_hdr_acts);
0a7fcb78
PB
212 if (err)
213 return err;
214
215 modact = mod_hdr_acts->actions +
216 (mod_hdr_acts->num_actions * MLX5_MH_ACT_SZ);
217
218 /* Firmware has 5bit length field and 0 means 32bits */
ed2fe7ba 219 if (mlen == 32)
0a7fcb78
PB
220 mlen = 0;
221
222 MLX5_SET(set_action_in, modact, action_type, MLX5_ACTION_TYPE_SET);
223 MLX5_SET(set_action_in, modact, field, mfield);
ed2fe7ba
PB
224 MLX5_SET(set_action_in, modact, offset, moffset);
225 MLX5_SET(set_action_in, modact, length, mlen);
0a7fcb78 226 MLX5_SET(set_action_in, modact, data, data);
c7b9038d 227 err = mod_hdr_acts->num_actions;
0a7fcb78
PB
228 mod_hdr_acts->num_actions++;
229
c7b9038d 230 return err;
0a7fcb78
PB
231}
232
aedd133d
AL
233static struct mlx5_tc_ct_priv *
234get_ct_priv(struct mlx5e_priv *priv)
235{
236 struct mlx5_eswitch *esw = priv->mdev->priv.eswitch;
237 struct mlx5_rep_uplink_priv *uplink_priv;
238 struct mlx5e_rep_priv *uplink_rpriv;
239
e8711402 240 if (is_mdev_switchdev_mode(priv->mdev)) {
aedd133d
AL
241 uplink_rpriv = mlx5_eswitch_get_uplink_priv(esw, REP_ETH);
242 uplink_priv = &uplink_rpriv->uplink_priv;
243
244 return uplink_priv->ct_priv;
245 }
246
247 return priv->fs.tc.ct;
248}
249
0027d70c 250static struct mlx5e_tc_psample *
f94d6389
CM
251get_sample_priv(struct mlx5e_priv *priv)
252{
253 struct mlx5_eswitch *esw = priv->mdev->priv.eswitch;
254 struct mlx5_rep_uplink_priv *uplink_priv;
255 struct mlx5e_rep_priv *uplink_rpriv;
256
257 if (is_mdev_switchdev_mode(priv->mdev)) {
258 uplink_rpriv = mlx5_eswitch_get_uplink_priv(esw, REP_ETH);
259 uplink_priv = &uplink_rpriv->uplink_priv;
260
0027d70c 261 return uplink_priv->tc_psample;
f94d6389
CM
262 }
263
264 return NULL;
265}
f94d6389 266
aedd133d
AL
267struct mlx5_flow_handle *
268mlx5_tc_rule_insert(struct mlx5e_priv *priv,
269 struct mlx5_flow_spec *spec,
270 struct mlx5_flow_attr *attr)
271{
272 struct mlx5_eswitch *esw = priv->mdev->priv.eswitch;
273
e8711402 274 if (is_mdev_switchdev_mode(priv->mdev))
aedd133d
AL
275 return mlx5_eswitch_add_offloaded_rule(esw, spec, attr);
276
277 return mlx5e_add_offloaded_nic_rule(priv, spec, attr);
278}
279
280void
281mlx5_tc_rule_delete(struct mlx5e_priv *priv,
282 struct mlx5_flow_handle *rule,
283 struct mlx5_flow_attr *attr)
284{
285 struct mlx5_eswitch *esw = priv->mdev->priv.eswitch;
286
e8711402 287 if (is_mdev_switchdev_mode(priv->mdev)) {
aedd133d
AL
288 mlx5_eswitch_del_offloaded_rule(esw, rule, attr);
289
290 return;
291 }
292
293 mlx5e_del_offloaded_nic_rule(priv, rule, attr);
294}
295
c7b9038d
VB
296int
297mlx5e_tc_match_to_reg_set(struct mlx5_core_dev *mdev,
298 struct mlx5e_tc_mod_hdr_acts *mod_hdr_acts,
299 enum mlx5_flow_namespace_type ns,
300 enum mlx5e_tc_attr_to_reg type,
301 u32 data)
302{
303 int ret = mlx5e_tc_match_to_reg_set_and_get_id(mdev, mod_hdr_acts, ns, type, data);
304
305 return ret < 0 ? ret : 0;
306}
307
308void mlx5e_tc_match_to_reg_mod_hdr_change(struct mlx5_core_dev *mdev,
309 struct mlx5e_tc_mod_hdr_acts *mod_hdr_acts,
310 enum mlx5e_tc_attr_to_reg type,
311 int act_id, u32 data)
312{
313 int moffset = mlx5e_tc_attr_to_reg_mappings[type].moffset;
314 int mfield = mlx5e_tc_attr_to_reg_mappings[type].mfield;
315 int mlen = mlx5e_tc_attr_to_reg_mappings[type].mlen;
316 char *modact;
317
318 modact = mod_hdr_acts->actions + (act_id * MLX5_MH_ACT_SZ);
319
320 /* Firmware has 5bit length field and 0 means 32bits */
ed2fe7ba 321 if (mlen == 32)
c7b9038d
VB
322 mlen = 0;
323
324 MLX5_SET(set_action_in, modact, action_type, MLX5_ACTION_TYPE_SET);
325 MLX5_SET(set_action_in, modact, field, mfield);
ed2fe7ba
PB
326 MLX5_SET(set_action_in, modact, offset, moffset);
327 MLX5_SET(set_action_in, modact, length, mlen);
c7b9038d
VB
328 MLX5_SET(set_action_in, modact, data, data);
329}
330
77ab67b7
OG
331struct mlx5e_hairpin {
332 struct mlx5_hairpin *pair;
333
334 struct mlx5_core_dev *func_mdev;
3f6d08d1 335 struct mlx5e_priv *func_priv;
77ab67b7 336 u32 tdn;
a6696735 337 struct mlx5e_tir direct_tir;
3f6d08d1
OG
338
339 int num_channels;
340 struct mlx5e_rqt indir_rqt;
a6696735 341 struct mlx5e_tir indir_tir[MLX5E_NUM_INDIR_TIRS];
f4b45940 342 struct mlx5_ttc_table *ttc;
77ab67b7
OG
343};
344
5c65c564
OG
345struct mlx5e_hairpin_entry {
346 /* a node of a hash table which keeps all the hairpin entries */
347 struct hlist_node hairpin_hlist;
348
73edca73
VB
349 /* protects flows list */
350 spinlock_t flows_lock;
5c65c564
OG
351 /* flows sharing the same hairpin */
352 struct list_head flows;
db76ca24
VB
353 /* hpe's that were not fully initialized when dead peer update event
354 * function traversed them.
355 */
356 struct list_head dead_peer_wait_list;
5c65c564 357
d8822868 358 u16 peer_vhca_id;
106be53b 359 u8 prio;
5c65c564 360 struct mlx5e_hairpin *hp;
e4f9abbd 361 refcount_t refcnt;
db76ca24 362 struct completion res_ready;
5c65c564
OG
363};
364
5a7e5bcb
VB
365static void mlx5e_tc_del_flow(struct mlx5e_priv *priv,
366 struct mlx5e_tc_flow *flow);
367
0d9f9647 368struct mlx5e_tc_flow *mlx5e_flow_get(struct mlx5e_tc_flow *flow)
5a7e5bcb
VB
369{
370 if (!flow || !refcount_inc_not_zero(&flow->refcnt))
371 return ERR_PTR(-EINVAL);
372 return flow;
373}
374
0d9f9647 375void mlx5e_flow_put(struct mlx5e_priv *priv, struct mlx5e_tc_flow *flow)
5a7e5bcb
VB
376{
377 if (refcount_dec_and_test(&flow->refcnt)) {
378 mlx5e_tc_del_flow(priv, flow);
c5d326b2 379 kfree_rcu(flow, rcu_head);
5a7e5bcb
VB
380 }
381}
382
aedd133d 383bool mlx5e_is_eswitch_flow(struct mlx5e_tc_flow *flow)
226f2ca3
VB
384{
385 return flow_flag_test(flow, ESWITCH);
386}
387
84179981
PB
388static bool mlx5e_is_ft_flow(struct mlx5e_tc_flow *flow)
389{
390 return flow_flag_test(flow, FT);
391}
392
0d9f9647 393bool mlx5e_is_offloaded_flow(struct mlx5e_tc_flow *flow)
226f2ca3
VB
394{
395 return flow_flag_test(flow, OFFLOADED);
396}
397
b2fdf3d0 398static int get_flow_name_space(struct mlx5e_tc_flow *flow)
11c9c548 399{
b2fdf3d0
PB
400 return mlx5e_is_eswitch_flow(flow) ?
401 MLX5_FLOW_NAMESPACE_FDB : MLX5_FLOW_NAMESPACE_KERNEL;
11c9c548
OG
402}
403
dd58edc3 404static struct mod_hdr_tbl *
b2fdf3d0 405get_mod_hdr_table(struct mlx5e_priv *priv, struct mlx5e_tc_flow *flow)
dd58edc3
VB
406{
407 struct mlx5_eswitch *esw = priv->mdev->priv.eswitch;
408
b2fdf3d0
PB
409 return get_flow_name_space(flow) == MLX5_FLOW_NAMESPACE_FDB ?
410 &esw->offloads.mod_hdr :
dd58edc3
VB
411 &priv->fs.tc.mod_hdr;
412}
413
11c9c548
OG
414static int mlx5e_attach_mod_hdr(struct mlx5e_priv *priv,
415 struct mlx5e_tc_flow *flow,
416 struct mlx5e_tc_flow_parse_attr *parse_attr)
417{
b2fdf3d0
PB
418 struct mlx5_modify_hdr *modify_hdr;
419 struct mlx5e_mod_hdr_handle *mh;
11c9c548 420
b2fdf3d0
PB
421 mh = mlx5e_mod_hdr_attach(priv->mdev, get_mod_hdr_table(priv, flow),
422 get_flow_name_space(flow),
423 &parse_attr->mod_hdr_acts);
424 if (IS_ERR(mh))
425 return PTR_ERR(mh);
11c9c548 426
b2fdf3d0 427 modify_hdr = mlx5e_mod_hdr_get(mh);
c620b772 428 flow->attr->modify_hdr = modify_hdr;
b2fdf3d0 429 flow->mh = mh;
11c9c548
OG
430
431 return 0;
11c9c548
OG
432}
433
434static void mlx5e_detach_mod_hdr(struct mlx5e_priv *priv,
435 struct mlx5e_tc_flow *flow)
436{
5a7e5bcb 437 /* flow wasn't fully initialized */
dd58edc3 438 if (!flow->mh)
5a7e5bcb
VB
439 return;
440
b2fdf3d0
PB
441 mlx5e_mod_hdr_detach(priv->mdev, get_mod_hdr_table(priv, flow),
442 flow->mh);
dd58edc3 443 flow->mh = NULL;
11c9c548
OG
444}
445
77ab67b7
OG
446static
447struct mlx5_core_dev *mlx5e_hairpin_get_mdev(struct net *net, int ifindex)
448{
b1c2f631 449 struct mlx5_core_dev *mdev;
77ab67b7
OG
450 struct net_device *netdev;
451 struct mlx5e_priv *priv;
452
b1c2f631
DC
453 netdev = dev_get_by_index(net, ifindex);
454 if (!netdev)
455 return ERR_PTR(-ENODEV);
456
77ab67b7 457 priv = netdev_priv(netdev);
b1c2f631
DC
458 mdev = priv->mdev;
459 dev_put(netdev);
460
461 /* Mirred tc action holds a refcount on the ifindex net_device (see
462 * net/sched/act_mirred.c:tcf_mirred_get_dev). So, it's okay to continue using mdev
463 * after dev_put(netdev), while we're in the context of adding a tc flow.
464 *
465 * The mdev pointer corresponds to the peer/out net_device of a hairpin. It is then
466 * stored in a hairpin object, which exists until all flows, that refer to it, get
467 * removed.
468 *
469 * On the other hand, after a hairpin object has been created, the peer net_device may
470 * be removed/unbound while there are still some hairpin flows that are using it. This
471 * case is handled by mlx5e_tc_hairpin_update_dead_peer, which is hooked to
472 * NETDEV_UNREGISTER event of the peer net_device.
473 */
474 return mdev;
77ab67b7
OG
475}
476
477static int mlx5e_hairpin_create_transport(struct mlx5e_hairpin *hp)
478{
a6696735 479 struct mlx5e_tir_builder *builder;
77ab67b7
OG
480 int err;
481
a6696735
MM
482 builder = mlx5e_tir_builder_alloc(false);
483 if (!builder)
484 return -ENOMEM;
485
77ab67b7
OG
486 err = mlx5_core_alloc_transport_domain(hp->func_mdev, &hp->tdn);
487 if (err)
a6696735 488 goto out;
77ab67b7 489
a6696735
MM
490 mlx5e_tir_builder_build_inline(builder, hp->tdn, hp->pair->rqn[0]);
491 err = mlx5e_tir_init(&hp->direct_tir, builder, hp->func_mdev, false);
77ab67b7
OG
492 if (err)
493 goto create_tir_err;
494
a6696735
MM
495out:
496 mlx5e_tir_builder_free(builder);
497 return err;
77ab67b7
OG
498
499create_tir_err:
500 mlx5_core_dealloc_transport_domain(hp->func_mdev, hp->tdn);
a6696735
MM
501
502 goto out;
77ab67b7
OG
503}
504
505static void mlx5e_hairpin_destroy_transport(struct mlx5e_hairpin *hp)
506{
a6696735 507 mlx5e_tir_destroy(&hp->direct_tir);
77ab67b7
OG
508 mlx5_core_dealloc_transport_domain(hp->func_mdev, hp->tdn);
509}
510
3f6d08d1
OG
511static int mlx5e_hairpin_create_indirect_rqt(struct mlx5e_hairpin *hp)
512{
3f6d08d1
OG
513 struct mlx5e_priv *priv = hp->func_priv;
514 struct mlx5_core_dev *mdev = priv->mdev;
06e9f13a
MM
515 struct mlx5e_rss_params_indir *indir;
516 int err;
3f6d08d1 517
06e9f13a
MM
518 indir = kvmalloc(sizeof(*indir), GFP_KERNEL);
519 if (!indir)
3f6d08d1
OG
520 return -ENOMEM;
521
43befe99 522 mlx5e_rss_params_indir_init_uniform(indir, hp->num_channels);
06e9f13a 523 err = mlx5e_rqt_init_indir(&hp->indir_rqt, mdev, hp->pair->rqn, hp->num_channels,
43ec0f41
MM
524 mlx5e_rx_res_get_current_hash(priv->rx_res).hfunc,
525 indir);
3f6d08d1 526
06e9f13a 527 kvfree(indir);
3f6d08d1
OG
528 return err;
529}
530
531static int mlx5e_hairpin_create_indirect_tirs(struct mlx5e_hairpin *hp)
532{
533 struct mlx5e_priv *priv = hp->func_priv;
43ec0f41 534 struct mlx5e_rss_params_hash rss_hash;
d443c6f6 535 enum mlx5_traffic_types tt, max_tt;
a6696735
MM
536 struct mlx5e_tir_builder *builder;
537 int err = 0;
538
539 builder = mlx5e_tir_builder_alloc(false);
540 if (!builder)
541 return -ENOMEM;
542
43ec0f41 543 rss_hash = mlx5e_rx_res_get_current_hash(priv->rx_res);
3f6d08d1
OG
544
545 for (tt = 0; tt < MLX5E_NUM_INDIR_TIRS; tt++) {
65d6b6e5 546 struct mlx5e_rss_params_traffic_type rss_tt;
d930ac79 547
65d6b6e5 548 rss_tt = mlx5e_rss_get_default_tt_config(tt);
3f6d08d1 549
a6696735
MM
550 mlx5e_tir_builder_build_rqt(builder, hp->tdn,
551 mlx5e_rqt_get_rqtn(&hp->indir_rqt),
552 false);
43ec0f41 553 mlx5e_tir_builder_build_rss(builder, &rss_hash, &rss_tt, false);
bbeb53b8 554
a6696735 555 err = mlx5e_tir_init(&hp->indir_tir[tt], builder, hp->func_mdev, false);
3f6d08d1
OG
556 if (err) {
557 mlx5_core_warn(hp->func_mdev, "create indirect tirs failed, %d\n", err);
558 goto err_destroy_tirs;
559 }
a6696735
MM
560
561 mlx5e_tir_builder_clear(builder);
3f6d08d1 562 }
3f6d08d1 563
a6696735
MM
564out:
565 mlx5e_tir_builder_free(builder);
3f6d08d1 566 return err;
a6696735
MM
567
568err_destroy_tirs:
569 max_tt = tt;
570 for (tt = 0; tt < max_tt; tt++)
571 mlx5e_tir_destroy(&hp->indir_tir[tt]);
572
573 goto out;
3f6d08d1
OG
574}
575
576static void mlx5e_hairpin_destroy_indirect_tirs(struct mlx5e_hairpin *hp)
577{
578 int tt;
579
580 for (tt = 0; tt < MLX5E_NUM_INDIR_TIRS; tt++)
a6696735 581 mlx5e_tir_destroy(&hp->indir_tir[tt]);
3f6d08d1
OG
582}
583
584static void mlx5e_hairpin_set_ttc_params(struct mlx5e_hairpin *hp,
585 struct ttc_params *ttc_params)
586{
587 struct mlx5_flow_table_attr *ft_attr = &ttc_params->ft_attr;
588 int tt;
589
590 memset(ttc_params, 0, sizeof(*ttc_params));
591
bc29764e
MG
592 ttc_params->ns = mlx5_get_flow_namespace(hp->func_mdev,
593 MLX5_FLOW_NAMESPACE_KERNEL);
594 for (tt = 0; tt < MLX5_NUM_TT; tt++) {
595 ttc_params->dests[tt].type = MLX5_FLOW_DESTINATION_TYPE_TIR;
596 ttc_params->dests[tt].tir_num =
597 tt == MLX5_TT_ANY ?
598 mlx5e_tir_get_tirn(&hp->direct_tir) :
599 mlx5e_tir_get_tirn(&hp->indir_tir[tt]);
600 }
3f6d08d1 601
3f6d08d1
OG
602 ft_attr->level = MLX5E_TC_TTC_FT_LEVEL;
603 ft_attr->prio = MLX5E_TC_PRIO;
604}
605
606static int mlx5e_hairpin_rss_init(struct mlx5e_hairpin *hp)
607{
608 struct mlx5e_priv *priv = hp->func_priv;
609 struct ttc_params ttc_params;
610 int err;
611
612 err = mlx5e_hairpin_create_indirect_rqt(hp);
613 if (err)
614 return err;
615
616 err = mlx5e_hairpin_create_indirect_tirs(hp);
617 if (err)
618 goto err_create_indirect_tirs;
619
620 mlx5e_hairpin_set_ttc_params(hp, &ttc_params);
f4b45940
MG
621 hp->ttc = mlx5_create_ttc_table(priv->mdev, &ttc_params);
622 if (IS_ERR(hp->ttc)) {
623 err = PTR_ERR(hp->ttc);
3f6d08d1 624 goto err_create_ttc_table;
f4b45940 625 }
3f6d08d1
OG
626
627 netdev_dbg(priv->netdev, "add hairpin: using %d channels rss ttc table id %x\n",
f4b45940
MG
628 hp->num_channels,
629 mlx5_get_ttc_flow_table(priv->fs.ttc)->id);
3f6d08d1
OG
630
631 return 0;
632
633err_create_ttc_table:
634 mlx5e_hairpin_destroy_indirect_tirs(hp);
635err_create_indirect_tirs:
06e9f13a 636 mlx5e_rqt_destroy(&hp->indir_rqt);
3f6d08d1
OG
637
638 return err;
639}
640
641static void mlx5e_hairpin_rss_cleanup(struct mlx5e_hairpin *hp)
642{
f4b45940 643 mlx5_destroy_ttc_table(hp->ttc);
3f6d08d1 644 mlx5e_hairpin_destroy_indirect_tirs(hp);
06e9f13a 645 mlx5e_rqt_destroy(&hp->indir_rqt);
3f6d08d1
OG
646}
647
77ab67b7
OG
648static struct mlx5e_hairpin *
649mlx5e_hairpin_create(struct mlx5e_priv *priv, struct mlx5_hairpin_params *params,
650 int peer_ifindex)
651{
652 struct mlx5_core_dev *func_mdev, *peer_mdev;
653 struct mlx5e_hairpin *hp;
654 struct mlx5_hairpin *pair;
655 int err;
656
657 hp = kzalloc(sizeof(*hp), GFP_KERNEL);
658 if (!hp)
659 return ERR_PTR(-ENOMEM);
660
661 func_mdev = priv->mdev;
662 peer_mdev = mlx5e_hairpin_get_mdev(dev_net(priv->netdev), peer_ifindex);
b1c2f631
DC
663 if (IS_ERR(peer_mdev)) {
664 err = PTR_ERR(peer_mdev);
665 goto create_pair_err;
666 }
77ab67b7
OG
667
668 pair = mlx5_core_hairpin_create(func_mdev, peer_mdev, params);
669 if (IS_ERR(pair)) {
670 err = PTR_ERR(pair);
671 goto create_pair_err;
672 }
673 hp->pair = pair;
674 hp->func_mdev = func_mdev;
3f6d08d1
OG
675 hp->func_priv = priv;
676 hp->num_channels = params->num_channels;
77ab67b7
OG
677
678 err = mlx5e_hairpin_create_transport(hp);
679 if (err)
680 goto create_transport_err;
681
3f6d08d1
OG
682 if (hp->num_channels > 1) {
683 err = mlx5e_hairpin_rss_init(hp);
684 if (err)
685 goto rss_init_err;
686 }
687
77ab67b7
OG
688 return hp;
689
3f6d08d1
OG
690rss_init_err:
691 mlx5e_hairpin_destroy_transport(hp);
77ab67b7
OG
692create_transport_err:
693 mlx5_core_hairpin_destroy(hp->pair);
694create_pair_err:
695 kfree(hp);
696 return ERR_PTR(err);
697}
698
699static void mlx5e_hairpin_destroy(struct mlx5e_hairpin *hp)
700{
3f6d08d1
OG
701 if (hp->num_channels > 1)
702 mlx5e_hairpin_rss_cleanup(hp);
77ab67b7
OG
703 mlx5e_hairpin_destroy_transport(hp);
704 mlx5_core_hairpin_destroy(hp->pair);
705 kvfree(hp);
706}
707
106be53b
OG
708static inline u32 hash_hairpin_info(u16 peer_vhca_id, u8 prio)
709{
710 return (peer_vhca_id << 16 | prio);
711}
712
5c65c564 713static struct mlx5e_hairpin_entry *mlx5e_hairpin_get(struct mlx5e_priv *priv,
106be53b 714 u16 peer_vhca_id, u8 prio)
5c65c564
OG
715{
716 struct mlx5e_hairpin_entry *hpe;
106be53b 717 u32 hash_key = hash_hairpin_info(peer_vhca_id, prio);
5c65c564
OG
718
719 hash_for_each_possible(priv->fs.tc.hairpin_tbl, hpe,
106be53b 720 hairpin_hlist, hash_key) {
e4f9abbd
VB
721 if (hpe->peer_vhca_id == peer_vhca_id && hpe->prio == prio) {
722 refcount_inc(&hpe->refcnt);
5c65c564 723 return hpe;
e4f9abbd 724 }
5c65c564
OG
725 }
726
727 return NULL;
728}
729
e4f9abbd
VB
730static void mlx5e_hairpin_put(struct mlx5e_priv *priv,
731 struct mlx5e_hairpin_entry *hpe)
732{
733 /* no more hairpin flows for us, release the hairpin pair */
b32accda 734 if (!refcount_dec_and_mutex_lock(&hpe->refcnt, &priv->fs.tc.hairpin_tbl_lock))
e4f9abbd 735 return;
b32accda
VB
736 hash_del(&hpe->hairpin_hlist);
737 mutex_unlock(&priv->fs.tc.hairpin_tbl_lock);
e4f9abbd 738
db76ca24
VB
739 if (!IS_ERR_OR_NULL(hpe->hp)) {
740 netdev_dbg(priv->netdev, "del hairpin: peer %s\n",
741 dev_name(hpe->hp->pair->peer_mdev->device));
742
743 mlx5e_hairpin_destroy(hpe->hp);
744 }
e4f9abbd
VB
745
746 WARN_ON(!list_empty(&hpe->flows));
e4f9abbd
VB
747 kfree(hpe);
748}
749
106be53b
OG
750#define UNKNOWN_MATCH_PRIO 8
751
752static int mlx5e_hairpin_get_prio(struct mlx5e_priv *priv,
e98bedf5
EB
753 struct mlx5_flow_spec *spec, u8 *match_prio,
754 struct netlink_ext_ack *extack)
106be53b
OG
755{
756 void *headers_c, *headers_v;
757 u8 prio_val, prio_mask = 0;
758 bool vlan_present;
759
760#ifdef CONFIG_MLX5_CORE_EN_DCB
761 if (priv->dcbx_dp.trust_state != MLX5_QPTS_TRUST_PCP) {
e98bedf5
EB
762 NL_SET_ERR_MSG_MOD(extack,
763 "only PCP trust state supported for hairpin");
106be53b
OG
764 return -EOPNOTSUPP;
765 }
766#endif
767 headers_c = MLX5_ADDR_OF(fte_match_param, spec->match_criteria, outer_headers);
768 headers_v = MLX5_ADDR_OF(fte_match_param, spec->match_value, outer_headers);
769
770 vlan_present = MLX5_GET(fte_match_set_lyr_2_4, headers_v, cvlan_tag);
771 if (vlan_present) {
772 prio_mask = MLX5_GET(fte_match_set_lyr_2_4, headers_c, first_prio);
773 prio_val = MLX5_GET(fte_match_set_lyr_2_4, headers_v, first_prio);
774 }
775
776 if (!vlan_present || !prio_mask) {
777 prio_val = UNKNOWN_MATCH_PRIO;
778 } else if (prio_mask != 0x7) {
e98bedf5
EB
779 NL_SET_ERR_MSG_MOD(extack,
780 "masked priority match not supported for hairpin");
106be53b
OG
781 return -EOPNOTSUPP;
782 }
783
784 *match_prio = prio_val;
785 return 0;
786}
787
5c65c564
OG
788static int mlx5e_hairpin_flow_add(struct mlx5e_priv *priv,
789 struct mlx5e_tc_flow *flow,
e98bedf5
EB
790 struct mlx5e_tc_flow_parse_attr *parse_attr,
791 struct netlink_ext_ack *extack)
5c65c564 792{
98b66cb1 793 int peer_ifindex = parse_attr->mirred_ifindex[0];
5c65c564 794 struct mlx5_hairpin_params params;
d8822868 795 struct mlx5_core_dev *peer_mdev;
5c65c564
OG
796 struct mlx5e_hairpin_entry *hpe;
797 struct mlx5e_hairpin *hp;
3f6d08d1
OG
798 u64 link_speed64;
799 u32 link_speed;
106be53b 800 u8 match_prio;
d8822868 801 u16 peer_id;
5c65c564
OG
802 int err;
803
d8822868 804 peer_mdev = mlx5e_hairpin_get_mdev(dev_net(priv->netdev), peer_ifindex);
b1c2f631
DC
805 if (IS_ERR(peer_mdev)) {
806 NL_SET_ERR_MSG_MOD(extack, "invalid ifindex of mirred device");
807 return PTR_ERR(peer_mdev);
808 }
809
d8822868 810 if (!MLX5_CAP_GEN(priv->mdev, hairpin) || !MLX5_CAP_GEN(peer_mdev, hairpin)) {
e98bedf5 811 NL_SET_ERR_MSG_MOD(extack, "hairpin is not supported");
5c65c564
OG
812 return -EOPNOTSUPP;
813 }
814
d8822868 815 peer_id = MLX5_CAP_GEN(peer_mdev, vhca_id);
e98bedf5
EB
816 err = mlx5e_hairpin_get_prio(priv, &parse_attr->spec, &match_prio,
817 extack);
106be53b
OG
818 if (err)
819 return err;
b32accda
VB
820
821 mutex_lock(&priv->fs.tc.hairpin_tbl_lock);
106be53b 822 hpe = mlx5e_hairpin_get(priv, peer_id, match_prio);
db76ca24
VB
823 if (hpe) {
824 mutex_unlock(&priv->fs.tc.hairpin_tbl_lock);
825 wait_for_completion(&hpe->res_ready);
826
827 if (IS_ERR(hpe->hp)) {
828 err = -EREMOTEIO;
829 goto out_err;
830 }
5c65c564 831 goto attach_flow;
db76ca24 832 }
5c65c564
OG
833
834 hpe = kzalloc(sizeof(*hpe), GFP_KERNEL);
b32accda 835 if (!hpe) {
db76ca24
VB
836 mutex_unlock(&priv->fs.tc.hairpin_tbl_lock);
837 return -ENOMEM;
b32accda 838 }
5c65c564 839
73edca73 840 spin_lock_init(&hpe->flows_lock);
5c65c564 841 INIT_LIST_HEAD(&hpe->flows);
db76ca24 842 INIT_LIST_HEAD(&hpe->dead_peer_wait_list);
d8822868 843 hpe->peer_vhca_id = peer_id;
106be53b 844 hpe->prio = match_prio;
e4f9abbd 845 refcount_set(&hpe->refcnt, 1);
db76ca24
VB
846 init_completion(&hpe->res_ready);
847
848 hash_add(priv->fs.tc.hairpin_tbl, &hpe->hairpin_hlist,
849 hash_hairpin_info(peer_id, match_prio));
850 mutex_unlock(&priv->fs.tc.hairpin_tbl_lock);
5c65c564 851
6cdc686a 852 params.log_data_size = 16;
5c65c564
OG
853 params.log_data_size = min_t(u8, params.log_data_size,
854 MLX5_CAP_GEN(priv->mdev, log_max_hairpin_wq_data_sz));
855 params.log_data_size = max_t(u8, params.log_data_size,
856 MLX5_CAP_GEN(priv->mdev, log_min_hairpin_wq_data_sz));
5c65c564 857
eb9180f7
OG
858 params.log_num_packets = params.log_data_size -
859 MLX5_MPWRQ_MIN_LOG_STRIDE_SZ(priv->mdev);
860 params.log_num_packets = min_t(u8, params.log_num_packets,
861 MLX5_CAP_GEN(priv->mdev, log_max_hairpin_num_packets));
862
863 params.q_counter = priv->q_counter;
3f6d08d1 864 /* set hairpin pair per each 50Gbs share of the link */
2c81bfd5 865 mlx5e_port_max_linkspeed(priv->mdev, &link_speed);
3f6d08d1
OG
866 link_speed = max_t(u32, link_speed, 50000);
867 link_speed64 = link_speed;
868 do_div(link_speed64, 50000);
869 params.num_channels = link_speed64;
870
5c65c564 871 hp = mlx5e_hairpin_create(priv, &params, peer_ifindex);
db76ca24
VB
872 hpe->hp = hp;
873 complete_all(&hpe->res_ready);
5c65c564
OG
874 if (IS_ERR(hp)) {
875 err = PTR_ERR(hp);
db76ca24 876 goto out_err;
5c65c564
OG
877 }
878
eb9180f7 879 netdev_dbg(priv->netdev, "add hairpin: tirn %x rqn %x peer %s sqn %x prio %d (log) data %d packets %d\n",
a6696735 880 mlx5e_tir_get_tirn(&hp->direct_tir), hp->pair->rqn[0],
27b942fb 881 dev_name(hp->pair->peer_mdev->device),
eb9180f7 882 hp->pair->sqn[0], match_prio, params.log_data_size, params.log_num_packets);
5c65c564 883
5c65c564 884attach_flow:
3f6d08d1 885 if (hpe->hp->num_channels > 1) {
226f2ca3 886 flow_flag_set(flow, HAIRPIN_RSS);
f4b45940
MG
887 flow->attr->nic_attr->hairpin_ft =
888 mlx5_get_ttc_flow_table(hpe->hp->ttc);
3f6d08d1 889 } else {
a6696735 890 flow->attr->nic_attr->hairpin_tirn = mlx5e_tir_get_tirn(&hpe->hp->direct_tir);
3f6d08d1 891 }
b32accda 892
e4f9abbd 893 flow->hpe = hpe;
73edca73 894 spin_lock(&hpe->flows_lock);
5c65c564 895 list_add(&flow->hairpin, &hpe->flows);
73edca73 896 spin_unlock(&hpe->flows_lock);
3f6d08d1 897
5c65c564
OG
898 return 0;
899
db76ca24
VB
900out_err:
901 mlx5e_hairpin_put(priv, hpe);
5c65c564
OG
902 return err;
903}
904
905static void mlx5e_hairpin_flow_del(struct mlx5e_priv *priv,
906 struct mlx5e_tc_flow *flow)
907{
5a7e5bcb 908 /* flow wasn't fully initialized */
e4f9abbd 909 if (!flow->hpe)
5a7e5bcb
VB
910 return;
911
73edca73 912 spin_lock(&flow->hpe->flows_lock);
5c65c564 913 list_del(&flow->hairpin);
73edca73
VB
914 spin_unlock(&flow->hpe->flows_lock);
915
e4f9abbd
VB
916 mlx5e_hairpin_put(priv, flow->hpe);
917 flow->hpe = NULL;
5c65c564
OG
918}
919
08247066
AL
920struct mlx5_flow_handle *
921mlx5e_add_offloaded_nic_rule(struct mlx5e_priv *priv,
922 struct mlx5_flow_spec *spec,
c620b772 923 struct mlx5_flow_attr *attr)
e8f887ac 924{
08247066 925 struct mlx5_flow_context *flow_context = &spec->flow_context;
c7569097 926 struct mlx5_fs_chains *nic_chains = nic_chains(priv);
c620b772 927 struct mlx5_nic_flow_attr *nic_attr = attr->nic_attr;
6a064674 928 struct mlx5e_tc_table *tc = &priv->fs.tc;
5c65c564 929 struct mlx5_flow_destination dest[2] = {};
66958ed9 930 struct mlx5_flow_act flow_act = {
3bc4b7bf 931 .action = attr->action,
bb0ee7dc 932 .flags = FLOW_ACT_NO_APPEND,
66958ed9 933 };
08247066 934 struct mlx5_flow_handle *rule;
c7569097 935 struct mlx5_flow_table *ft;
08247066 936 int dest_ix = 0;
e8f887ac 937
bb0ee7dc 938 flow_context->flags |= FLOW_CONTEXT_HAS_TAG;
c620b772 939 flow_context->flow_tag = nic_attr->flow_tag;
bb0ee7dc 940
aedd133d
AL
941 if (attr->dest_ft) {
942 dest[dest_ix].type = MLX5_FLOW_DESTINATION_TYPE_FLOW_TABLE;
943 dest[dest_ix].ft = attr->dest_ft;
944 dest_ix++;
945 } else if (nic_attr->hairpin_ft) {
08247066 946 dest[dest_ix].type = MLX5_FLOW_DESTINATION_TYPE_FLOW_TABLE;
c620b772 947 dest[dest_ix].ft = nic_attr->hairpin_ft;
08247066 948 dest_ix++;
c620b772 949 } else if (nic_attr->hairpin_tirn) {
08247066 950 dest[dest_ix].type = MLX5_FLOW_DESTINATION_TYPE_TIR;
c620b772 951 dest[dest_ix].tir_num = nic_attr->hairpin_tirn;
5c65c564 952 dest_ix++;
3f6d08d1
OG
953 } else if (attr->action & MLX5_FLOW_CONTEXT_ACTION_FWD_DEST) {
954 dest[dest_ix].type = MLX5_FLOW_DESTINATION_TYPE_FLOW_TABLE;
c7569097
AL
955 if (attr->dest_chain) {
956 dest[dest_ix].ft = mlx5_chains_get_table(nic_chains,
957 attr->dest_chain, 1,
958 MLX5E_TC_FT_LEVEL);
959 if (IS_ERR(dest[dest_ix].ft))
960 return ERR_CAST(dest[dest_ix].ft);
961 } else {
6783f0a2 962 dest[dest_ix].ft = mlx5e_vlan_get_flowtable(priv->fs.vlan);
c7569097 963 }
3f6d08d1 964 dest_ix++;
5c65c564 965 }
aad7e08d 966
c7569097
AL
967 if (dest[0].type == MLX5_FLOW_DESTINATION_TYPE_FLOW_TABLE &&
968 MLX5_CAP_FLOWTABLE_NIC_RX(priv->mdev, ignore_flow_level))
969 flow_act.flags |= FLOW_ACT_IGNORE_FLOW_LEVEL;
970
08247066 971 if (flow_act.action & MLX5_FLOW_CONTEXT_ACTION_COUNT) {
5c65c564 972 dest[dest_ix].type = MLX5_FLOW_DESTINATION_TYPE_COUNTER;
08247066 973 dest[dest_ix].counter_id = mlx5_fc_id(attr->counter);
5c65c564 974 dest_ix++;
aad7e08d
AV
975 }
976
08247066 977 if (attr->action & MLX5_FLOW_CONTEXT_ACTION_MOD_HDR)
2b688ea5 978 flow_act.modify_hdr = attr->modify_hdr;
2f4fe4ca 979
6a064674
AL
980 mutex_lock(&tc->t_lock);
981 if (IS_ERR_OR_NULL(tc->t)) {
982 /* Create the root table here if doesn't exist yet */
983 tc->t =
c7569097 984 mlx5_chains_get_table(nic_chains, 0, 1, MLX5E_TC_FT_LEVEL);
6a064674
AL
985
986 if (IS_ERR(tc->t)) {
987 mutex_unlock(&tc->t_lock);
e8f887ac
AV
988 netdev_err(priv->netdev,
989 "Failed to create tc offload table\n");
c7569097
AL
990 rule = ERR_CAST(priv->fs.tc.t);
991 goto err_ft_get;
e8f887ac 992 }
e8f887ac 993 }
08247066 994 mutex_unlock(&tc->t_lock);
e8f887ac 995
aedd133d
AL
996 if (attr->chain || attr->prio)
997 ft = mlx5_chains_get_table(nic_chains,
998 attr->chain, attr->prio,
999 MLX5E_TC_FT_LEVEL);
1000 else
1001 ft = attr->ft;
1002
c7569097
AL
1003 if (IS_ERR(ft)) {
1004 rule = ERR_CAST(ft);
1005 goto err_ft_get;
1006 }
1007
c620b772 1008 if (attr->outer_match_level != MLX5_MATCH_NONE)
08247066 1009 spec->match_criteria_enable |= MLX5_MATCH_OUTER_HEADERS;
38aa51c1 1010
c7569097 1011 rule = mlx5_add_flow_rules(ft, spec,
08247066
AL
1012 &flow_act, dest, dest_ix);
1013 if (IS_ERR(rule))
c7569097 1014 goto err_rule;
08247066
AL
1015
1016 return rule;
c7569097
AL
1017
1018err_rule:
aedd133d
AL
1019 if (attr->chain || attr->prio)
1020 mlx5_chains_put_table(nic_chains,
1021 attr->chain, attr->prio,
1022 MLX5E_TC_FT_LEVEL);
c7569097
AL
1023err_ft_get:
1024 if (attr->dest_chain)
1025 mlx5_chains_put_table(nic_chains,
1026 attr->dest_chain, 1,
1027 MLX5E_TC_FT_LEVEL);
1028
1029 return ERR_CAST(rule);
08247066
AL
1030}
1031
1032static int
1033mlx5e_tc_add_nic_flow(struct mlx5e_priv *priv,
08247066
AL
1034 struct mlx5e_tc_flow *flow,
1035 struct netlink_ext_ack *extack)
1036{
c6cfe113 1037 struct mlx5e_tc_flow_parse_attr *parse_attr;
c620b772 1038 struct mlx5_flow_attr *attr = flow->attr;
08247066 1039 struct mlx5_core_dev *dev = priv->mdev;
97a8d29a 1040 struct mlx5_fc *counter;
08247066
AL
1041 int err;
1042
c6cfe113
RD
1043 parse_attr = attr->parse_attr;
1044
08247066
AL
1045 if (flow_flag_test(flow, HAIRPIN)) {
1046 err = mlx5e_hairpin_flow_add(priv, flow, parse_attr, extack);
1047 if (err)
1048 return err;
1049 }
1050
1051 if (attr->action & MLX5_FLOW_CONTEXT_ACTION_COUNT) {
1052 counter = mlx5_fc_create(dev, true);
1053 if (IS_ERR(counter))
1054 return PTR_ERR(counter);
1055
1056 attr->counter = counter;
1057 }
1058
1059 if (attr->action & MLX5_FLOW_CONTEXT_ACTION_MOD_HDR) {
1060 err = mlx5e_attach_mod_hdr(priv, flow, parse_attr);
1061 dealloc_mod_hdr_actions(&parse_attr->mod_hdr_acts);
1062 if (err)
1063 return err;
1064 }
1065
aedd133d
AL
1066 if (flow_flag_test(flow, CT))
1067 flow->rule[0] = mlx5_tc_ct_flow_offload(get_ct_priv(priv), flow, &parse_attr->spec,
1068 attr, &parse_attr->mod_hdr_acts);
1069 else
1070 flow->rule[0] = mlx5e_add_offloaded_nic_rule(priv, &parse_attr->spec,
1071 attr);
aad7e08d 1072
a2b7189b 1073 return PTR_ERR_OR_ZERO(flow->rule[0]);
e8f887ac
AV
1074}
1075
08247066 1076void mlx5e_del_offloaded_nic_rule(struct mlx5e_priv *priv,
c7569097
AL
1077 struct mlx5_flow_handle *rule,
1078 struct mlx5_flow_attr *attr)
08247066 1079{
c7569097
AL
1080 struct mlx5_fs_chains *nic_chains = nic_chains(priv);
1081
08247066 1082 mlx5_del_flow_rules(rule);
c7569097 1083
aedd133d
AL
1084 if (attr->chain || attr->prio)
1085 mlx5_chains_put_table(nic_chains, attr->chain, attr->prio,
1086 MLX5E_TC_FT_LEVEL);
c7569097
AL
1087
1088 if (attr->dest_chain)
1089 mlx5_chains_put_table(nic_chains, attr->dest_chain, 1,
1090 MLX5E_TC_FT_LEVEL);
08247066
AL
1091}
1092
d85cdccb
OG
1093static void mlx5e_tc_del_nic_flow(struct mlx5e_priv *priv,
1094 struct mlx5e_tc_flow *flow)
1095{
c620b772 1096 struct mlx5_flow_attr *attr = flow->attr;
6a064674 1097 struct mlx5e_tc_table *tc = &priv->fs.tc;
d85cdccb 1098
c7569097
AL
1099 flow_flag_clear(flow, OFFLOADED);
1100
aedd133d
AL
1101 if (flow_flag_test(flow, CT))
1102 mlx5_tc_ct_delete_flow(get_ct_priv(flow->priv), flow, attr);
1103 else if (!IS_ERR_OR_NULL(flow->rule[0]))
1104 mlx5e_del_offloaded_nic_rule(priv, flow->rule[0], attr);
1105
c7569097
AL
1106 /* Remove root table if no rules are left to avoid
1107 * extra steering hops.
1108 */
b6fac0b4 1109 mutex_lock(&priv->fs.tc.t_lock);
6a064674
AL
1110 if (!mlx5e_tc_num_filters(priv, MLX5_TC_FLAG(NIC_OFFLOAD)) &&
1111 !IS_ERR_OR_NULL(tc->t)) {
1112 mlx5_chains_put_table(nic_chains(priv), 0, 1, MLX5E_TC_FT_LEVEL);
d85cdccb
OG
1113 priv->fs.tc.t = NULL;
1114 }
b6fac0b4 1115 mutex_unlock(&priv->fs.tc.t_lock);
2f4fe4ca 1116
aedd133d
AL
1117 kvfree(attr->parse_attr);
1118
513f8f7f 1119 if (attr->action & MLX5_FLOW_CONTEXT_ACTION_MOD_HDR)
3099eb5a 1120 mlx5e_detach_mod_hdr(priv, flow);
5c65c564 1121
aedd133d
AL
1122 mlx5_fc_destroy(priv->mdev, attr->counter);
1123
226f2ca3 1124 if (flow_flag_test(flow, HAIRPIN))
5c65c564 1125 mlx5e_hairpin_flow_del(priv, flow);
c620b772
AL
1126
1127 kfree(flow->attr);
d85cdccb
OG
1128}
1129
0d9f9647 1130struct mlx5_flow_handle *
6d2a3ed0
OG
1131mlx5e_tc_offload_fdb_rules(struct mlx5_eswitch *esw,
1132 struct mlx5e_tc_flow *flow,
1133 struct mlx5_flow_spec *spec,
c620b772 1134 struct mlx5_flow_attr *attr)
6d2a3ed0 1135{
1ef3018f 1136 struct mlx5e_tc_mod_hdr_acts *mod_hdr_acts;
6d2a3ed0 1137 struct mlx5_flow_handle *rule;
4c3844d9 1138
89e39467
PB
1139 if (attr->flags & MLX5_ESW_ATTR_FLAG_SLOW_PATH)
1140 return mlx5_eswitch_add_offloaded_rule(esw, spec, attr);
1141
1ef3018f
PB
1142 if (flow_flag_test(flow, CT)) {
1143 mod_hdr_acts = &attr->parse_attr->mod_hdr_acts;
1144
69e2916e 1145 rule = mlx5_tc_ct_flow_offload(get_ct_priv(flow->priv),
aedd133d 1146 flow, spec, attr,
1ef3018f 1147 mod_hdr_acts);
f94d6389 1148 } else if (flow_flag_test(flow, SAMPLE)) {
ee950e5d
CM
1149 rule = mlx5e_tc_sample_offload(get_sample_priv(flow->priv), spec, attr,
1150 mlx5e_tc_get_flow_tun_id(flow));
69e2916e
PB
1151 } else {
1152 rule = mlx5_eswitch_add_offloaded_rule(esw, spec, attr);
1ef3018f 1153 }
6d2a3ed0 1154
6d2a3ed0
OG
1155 if (IS_ERR(rule))
1156 return rule;
1157
c620b772 1158 if (attr->esw_attr->split_count) {
6d2a3ed0
OG
1159 flow->rule[1] = mlx5_eswitch_add_fwd_rule(esw, spec, attr);
1160 if (IS_ERR(flow->rule[1])) {
69e2916e
PB
1161 if (flow_flag_test(flow, CT))
1162 mlx5_tc_ct_delete_flow(get_ct_priv(flow->priv), flow, attr);
1163 else
1164 mlx5_eswitch_del_offloaded_rule(esw, rule, attr);
6d2a3ed0
OG
1165 return flow->rule[1];
1166 }
1167 }
1168
6d2a3ed0
OG
1169 return rule;
1170}
1171
0d9f9647
VB
1172void mlx5e_tc_unoffload_fdb_rules(struct mlx5_eswitch *esw,
1173 struct mlx5e_tc_flow *flow,
1174 struct mlx5_flow_attr *attr)
6d2a3ed0 1175{
226f2ca3 1176 flow_flag_clear(flow, OFFLOADED);
6d2a3ed0 1177
89e39467
PB
1178 if (attr->flags & MLX5_ESW_ATTR_FLAG_SLOW_PATH)
1179 goto offload_rule_0;
1180
c620b772 1181 if (attr->esw_attr->split_count)
6d2a3ed0
OG
1182 mlx5_eswitch_del_fwd_rule(esw, flow->rule[1], attr);
1183
f7a6ab77
CM
1184 if (flow_flag_test(flow, CT))
1185 mlx5_tc_ct_delete_flow(get_ct_priv(flow->priv), flow, attr);
1186 else if (flow_flag_test(flow, SAMPLE))
1187 mlx5e_tc_sample_unoffload(get_sample_priv(flow->priv), flow->rule[0], attr);
1188 else
89e39467 1189offload_rule_0:
f7a6ab77 1190 mlx5_eswitch_del_offloaded_rule(esw, flow->rule[0], attr);
6d2a3ed0
OG
1191}
1192
0d9f9647 1193struct mlx5_flow_handle *
5dbe906f
PB
1194mlx5e_tc_offload_to_slow_path(struct mlx5_eswitch *esw,
1195 struct mlx5e_tc_flow *flow,
178f69b4 1196 struct mlx5_flow_spec *spec)
5dbe906f 1197{
c620b772 1198 struct mlx5_flow_attr *slow_attr;
5dbe906f
PB
1199 struct mlx5_flow_handle *rule;
1200
c620b772
AL
1201 slow_attr = mlx5_alloc_flow_attr(MLX5_FLOW_NAMESPACE_FDB);
1202 if (!slow_attr)
1203 return ERR_PTR(-ENOMEM);
5dbe906f 1204
c620b772
AL
1205 memcpy(slow_attr, flow->attr, ESW_FLOW_ATTR_SZ);
1206 slow_attr->action = MLX5_FLOW_CONTEXT_ACTION_FWD_DEST;
1207 slow_attr->esw_attr->split_count = 0;
1208 slow_attr->flags |= MLX5_ESW_ATTR_FLAG_SLOW_PATH;
1209
1210 rule = mlx5e_tc_offload_fdb_rules(esw, flow, spec, slow_attr);
5dbe906f 1211 if (!IS_ERR(rule))
226f2ca3 1212 flow_flag_set(flow, SLOW);
5dbe906f 1213
c620b772
AL
1214 kfree(slow_attr);
1215
5dbe906f
PB
1216 return rule;
1217}
1218
0d9f9647
VB
1219void mlx5e_tc_unoffload_from_slow_path(struct mlx5_eswitch *esw,
1220 struct mlx5e_tc_flow *flow)
5dbe906f 1221{
c620b772 1222 struct mlx5_flow_attr *slow_attr;
178f69b4 1223
c620b772 1224 slow_attr = mlx5_alloc_flow_attr(MLX5_FLOW_NAMESPACE_FDB);
5efbe617
AL
1225 if (!slow_attr) {
1226 mlx5_core_warn(flow->priv->mdev, "Unable to alloc attr to unoffload slow path rule\n");
1227 return;
1228 }
c620b772
AL
1229
1230 memcpy(slow_attr, flow->attr, ESW_FLOW_ATTR_SZ);
1231 slow_attr->action = MLX5_FLOW_CONTEXT_ACTION_FWD_DEST;
1232 slow_attr->esw_attr->split_count = 0;
1233 slow_attr->flags |= MLX5_ESW_ATTR_FLAG_SLOW_PATH;
1234 mlx5e_tc_unoffload_fdb_rules(esw, flow, slow_attr);
226f2ca3 1235 flow_flag_clear(flow, SLOW);
c620b772 1236 kfree(slow_attr);
5dbe906f
PB
1237}
1238
ad86755b
VB
1239/* Caller must obtain uplink_priv->unready_flows_lock mutex before calling this
1240 * function.
1241 */
1242static void unready_flow_add(struct mlx5e_tc_flow *flow,
1243 struct list_head *unready_flows)
1244{
1245 flow_flag_set(flow, NOT_READY);
1246 list_add_tail(&flow->unready, unready_flows);
1247}
1248
1249/* Caller must obtain uplink_priv->unready_flows_lock mutex before calling this
1250 * function.
1251 */
1252static void unready_flow_del(struct mlx5e_tc_flow *flow)
1253{
1254 list_del(&flow->unready);
1255 flow_flag_clear(flow, NOT_READY);
1256}
1257
b4a23329
RD
1258static void add_unready_flow(struct mlx5e_tc_flow *flow)
1259{
1260 struct mlx5_rep_uplink_priv *uplink_priv;
1261 struct mlx5e_rep_priv *rpriv;
1262 struct mlx5_eswitch *esw;
1263
1264 esw = flow->priv->mdev->priv.eswitch;
1265 rpriv = mlx5_eswitch_get_uplink_priv(esw, REP_ETH);
1266 uplink_priv = &rpriv->uplink_priv;
1267
ad86755b
VB
1268 mutex_lock(&uplink_priv->unready_flows_lock);
1269 unready_flow_add(flow, &uplink_priv->unready_flows);
1270 mutex_unlock(&uplink_priv->unready_flows_lock);
b4a23329
RD
1271}
1272
1273static void remove_unready_flow(struct mlx5e_tc_flow *flow)
1274{
ad86755b
VB
1275 struct mlx5_rep_uplink_priv *uplink_priv;
1276 struct mlx5e_rep_priv *rpriv;
1277 struct mlx5_eswitch *esw;
1278
1279 esw = flow->priv->mdev->priv.eswitch;
1280 rpriv = mlx5_eswitch_get_uplink_priv(esw, REP_ETH);
1281 uplink_priv = &rpriv->uplink_priv;
1282
1283 mutex_lock(&uplink_priv->unready_flows_lock);
1284 unready_flow_del(flow);
1285 mutex_unlock(&uplink_priv->unready_flows_lock);
b4a23329
RD
1286}
1287
10742efc
VB
1288static bool same_hw_devs(struct mlx5e_priv *priv, struct mlx5e_priv *peer_priv);
1289
a508728a 1290bool mlx5e_tc_is_vf_tunnel(struct net_device *out_dev, struct net_device *route_dev)
10742efc
VB
1291{
1292 struct mlx5_core_dev *out_mdev, *route_mdev;
1293 struct mlx5e_priv *out_priv, *route_priv;
1294
1295 out_priv = netdev_priv(out_dev);
1296 out_mdev = out_priv->mdev;
1297 route_priv = netdev_priv(route_dev);
1298 route_mdev = route_priv->mdev;
1299
1300 if (out_mdev->coredev_type != MLX5_COREDEV_PF ||
1301 route_mdev->coredev_type != MLX5_COREDEV_VF)
1302 return false;
1303
1304 return same_hw_devs(out_priv, route_priv);
1305}
1306
a508728a 1307int mlx5e_tc_query_route_vport(struct net_device *out_dev, struct net_device *route_dev, u16 *vport)
10742efc
VB
1308{
1309 struct mlx5e_priv *out_priv, *route_priv;
f9d196bd 1310 struct mlx5_devcom *devcom = NULL;
10742efc
VB
1311 struct mlx5_core_dev *route_mdev;
1312 struct mlx5_eswitch *esw;
1313 u16 vhca_id;
1314 int err;
1315
1316 out_priv = netdev_priv(out_dev);
1317 esw = out_priv->mdev->priv.eswitch;
1318 route_priv = netdev_priv(route_dev);
1319 route_mdev = route_priv->mdev;
1320
1321 vhca_id = MLX5_CAP_GEN(route_mdev, vhca_id);
f9d196bd
DL
1322 if (mlx5_lag_is_active(out_priv->mdev)) {
1323 /* In lag case we may get devices from different eswitch instances.
1324 * If we failed to get vport num, it means, mostly, that we on the wrong
1325 * eswitch.
1326 */
1327 err = mlx5_eswitch_vhca_id_to_vport(esw, vhca_id, vport);
1328 if (err != -ENOENT)
1329 return err;
1330
1331 devcom = out_priv->mdev->priv.devcom;
1332 esw = mlx5_devcom_get_peer_data(devcom, MLX5_DEVCOM_ESW_OFFLOADS);
1333 if (!esw)
1334 return -ENODEV;
1335 }
1336
10742efc 1337 err = mlx5_eswitch_vhca_id_to_vport(esw, vhca_id, vport);
f9d196bd
DL
1338 if (devcom)
1339 mlx5_devcom_release_peer_data(devcom, MLX5_DEVCOM_ESW_OFFLOADS);
10742efc
VB
1340 return err;
1341}
1342
c7b9038d
VB
1343int mlx5e_tc_add_flow_mod_hdr(struct mlx5e_priv *priv,
1344 struct mlx5e_tc_flow_parse_attr *parse_attr,
1345 struct mlx5e_tc_flow *flow)
1346{
1347 struct mlx5e_tc_mod_hdr_acts *mod_hdr_acts = &parse_attr->mod_hdr_acts;
1348 struct mlx5_modify_hdr *mod_hdr;
1349
1350 mod_hdr = mlx5_modify_header_alloc(priv->mdev,
1351 get_flow_name_space(flow),
1352 mod_hdr_acts->num_actions,
1353 mod_hdr_acts->actions);
1354 if (IS_ERR(mod_hdr))
1355 return PTR_ERR(mod_hdr);
1356
1357 WARN_ON(flow->attr->modify_hdr);
1358 flow->attr->modify_hdr = mod_hdr;
1359
1360 return 0;
1361}
1362
c83954ab 1363static int
74491de9 1364mlx5e_tc_add_fdb_flow(struct mlx5e_priv *priv,
e98bedf5
EB
1365 struct mlx5e_tc_flow *flow,
1366 struct netlink_ext_ack *extack)
adb4c123
OG
1367{
1368 struct mlx5_eswitch *esw = priv->mdev->priv.eswitch;
c620b772
AL
1369 struct mlx5e_tc_flow_parse_attr *parse_attr;
1370 struct mlx5_flow_attr *attr = flow->attr;
8914add2 1371 bool vf_tun = false, encap_valid = true;
fe7738eb 1372 struct net_device *encap_dev = NULL;
c620b772 1373 struct mlx5_esw_flow_attr *esw_attr;
3c37745e
OG
1374 struct mlx5e_rep_priv *rpriv;
1375 struct mlx5e_priv *out_priv;
97a8d29a 1376 struct mlx5_fc *counter;
39ac237c 1377 u32 max_prio, max_chain;
0ad060ee 1378 int err = 0;
f493f155 1379 int out_index;
8b32580d 1380
84179981
PB
1381 /* We check chain range only for tc flows.
1382 * For ft flows, we checked attr->chain was originally 0 and set it to
1383 * FDB_FT_CHAIN which is outside tc range.
1384 * See mlx5e_rep_setup_ft_cb().
1385 */
ae430332 1386 max_chain = mlx5_chains_get_chain_range(esw_chains(esw));
84179981 1387 if (!mlx5e_is_ft_flow(flow) && attr->chain > max_chain) {
61644c3d
RD
1388 NL_SET_ERR_MSG_MOD(extack,
1389 "Requested chain is out of supported range");
8914add2
VB
1390 err = -EOPNOTSUPP;
1391 goto err_out;
bf07aa73
PB
1392 }
1393
ae430332 1394 max_prio = mlx5_chains_get_prio_range(esw_chains(esw));
bf07aa73 1395 if (attr->prio > max_prio) {
61644c3d
RD
1396 NL_SET_ERR_MSG_MOD(extack,
1397 "Requested priority is out of supported range");
8914add2
VB
1398 err = -EOPNOTSUPP;
1399 goto err_out;
bf07aa73 1400 }
e52c2802 1401
777bb800
VB
1402 if (flow_flag_test(flow, TUN_RX)) {
1403 err = mlx5e_attach_decap_route(priv, flow);
1404 if (err)
8914add2 1405 goto err_out;
777bb800
VB
1406 }
1407
14e6b038
EC
1408 if (flow_flag_test(flow, L3_TO_L2_DECAP)) {
1409 err = mlx5e_attach_decap(priv, flow, extack);
1410 if (err)
8914add2 1411 goto err_out;
14e6b038
EC
1412 }
1413
c620b772
AL
1414 parse_attr = attr->parse_attr;
1415 esw_attr = attr->esw_attr;
1416
f493f155 1417 for (out_index = 0; out_index < MLX5_MAX_FLOW_FWD_VPORTS; out_index++) {
fe7738eb 1418 struct net_device *out_dev;
8c4dc42b
EB
1419 int mirred_ifindex;
1420
c620b772 1421 if (!(esw_attr->dests[out_index].flags & MLX5_ESW_DEST_ENCAP))
f493f155
EB
1422 continue;
1423
7040632d 1424 mirred_ifindex = parse_attr->mirred_ifindex[out_index];
fe7738eb
DC
1425 out_dev = dev_get_by_index(dev_net(priv->netdev), mirred_ifindex);
1426 if (!out_dev) {
1427 NL_SET_ERR_MSG_MOD(extack, "Requested mirred device not found");
1428 err = -ENODEV;
1429 goto err_out;
1430 }
733d4f36 1431 err = mlx5e_attach_encap(priv, flow, out_dev, out_index,
0ad060ee 1432 extack, &encap_dev, &encap_valid);
fe7738eb 1433 dev_put(out_dev);
0ad060ee 1434 if (err)
8914add2 1435 goto err_out;
0ad060ee 1436
8914add2
VB
1437 if (esw_attr->dests[out_index].flags &
1438 MLX5_ESW_DEST_CHAIN_WITH_SRC_PORT_CHANGE)
1439 vf_tun = true;
3c37745e
OG
1440 out_priv = netdev_priv(encap_dev);
1441 rpriv = out_priv->ppriv;
c620b772
AL
1442 esw_attr->dests[out_index].rep = rpriv->rep;
1443 esw_attr->dests[out_index].mdev = out_priv->mdev;
3c37745e
OG
1444 }
1445
7d1a3d08
VB
1446 if (vf_tun && esw_attr->out_count > 1) {
1447 NL_SET_ERR_MSG_MOD(extack, "VF tunnel encap with mirroring is not supported");
1448 err = -EOPNOTSUPP;
1449 goto err_out;
1450 }
1451
8b32580d 1452 err = mlx5_eswitch_add_vlan_action(esw, attr);
c83954ab 1453 if (err)
8914add2 1454 goto err_out;
adb4c123 1455
d5a3c2b6
RD
1456 if (attr->action & MLX5_FLOW_CONTEXT_ACTION_MOD_HDR &&
1457 !(attr->ct_attr.ct_action & TCA_CT_ACT_CLEAR)) {
8914add2
VB
1458 if (vf_tun) {
1459 err = mlx5e_tc_add_flow_mod_hdr(priv, parse_attr, flow);
1460 if (err)
1461 goto err_out;
1462 } else {
1463 err = mlx5e_attach_mod_hdr(priv, flow, parse_attr);
1464 if (err)
1465 goto err_out;
1466 }
d7e75a32
OG
1467 }
1468
b8aee822 1469 if (attr->action & MLX5_FLOW_CONTEXT_ACTION_COUNT) {
c620b772 1470 counter = mlx5_fc_create(esw_attr->counter_dev, true);
8914add2
VB
1471 if (IS_ERR(counter)) {
1472 err = PTR_ERR(counter);
1473 goto err_out;
1474 }
b8aee822
MB
1475
1476 attr->counter = counter;
1477 }
1478
0ad060ee
RD
1479 /* we get here if one of the following takes place:
1480 * (1) there's no error
1481 * (2) there's an encap action and we don't have valid neigh
3c37745e 1482 */
bc1d75fa 1483 if (!encap_valid)
178f69b4 1484 flow->rule[0] = mlx5e_tc_offload_to_slow_path(esw, flow, &parse_attr->spec);
bc1d75fa 1485 else
6d2a3ed0 1486 flow->rule[0] = mlx5e_tc_offload_fdb_rules(esw, flow, &parse_attr->spec, attr);
c83954ab 1487
8914add2
VB
1488 if (IS_ERR(flow->rule[0])) {
1489 err = PTR_ERR(flow->rule[0]);
1490 goto err_out;
1491 }
1492 flow_flag_set(flow, OFFLOADED);
5dbe906f
PB
1493
1494 return 0;
8914add2
VB
1495
1496err_out:
1497 flow_flag_set(flow, FAILED);
1498 return err;
aa0cbbae 1499}
d85cdccb 1500
9272e3df
YK
1501static bool mlx5_flow_has_geneve_opt(struct mlx5e_tc_flow *flow)
1502{
c620b772 1503 struct mlx5_flow_spec *spec = &flow->attr->parse_attr->spec;
9272e3df
YK
1504 void *headers_v = MLX5_ADDR_OF(fte_match_param,
1505 spec->match_value,
1506 misc_parameters_3);
1507 u32 geneve_tlv_opt_0_data = MLX5_GET(fte_match_set_misc3,
1508 headers_v,
1509 geneve_tlv_option_0_data);
1510
1511 return !!geneve_tlv_opt_0_data;
1512}
1513
d85cdccb
OG
1514static void mlx5e_tc_del_fdb_flow(struct mlx5e_priv *priv,
1515 struct mlx5e_tc_flow *flow)
1516{
1517 struct mlx5_eswitch *esw = priv->mdev->priv.eswitch;
c620b772 1518 struct mlx5_flow_attr *attr = flow->attr;
777bb800 1519 struct mlx5_esw_flow_attr *esw_attr;
8914add2 1520 bool vf_tun = false;
f493f155 1521 int out_index;
d85cdccb 1522
777bb800 1523 esw_attr = attr->esw_attr;
0a7fcb78
PB
1524 mlx5e_put_flow_tunnel_id(flow);
1525
12a240a4 1526 if (flow_flag_test(flow, NOT_READY))
b4a23329 1527 remove_unready_flow(flow);
ef06c9ee 1528
226f2ca3
VB
1529 if (mlx5e_is_offloaded_flow(flow)) {
1530 if (flow_flag_test(flow, SLOW))
178f69b4 1531 mlx5e_tc_unoffload_from_slow_path(esw, flow);
5dbe906f
PB
1532 else
1533 mlx5e_tc_unoffload_fdb_rules(esw, flow, attr);
1534 }
909e615d 1535 complete_all(&flow->del_hw_done);
d85cdccb 1536
9272e3df
YK
1537 if (mlx5_flow_has_geneve_opt(flow))
1538 mlx5_geneve_tlv_option_del(priv->mdev->geneve);
1539
513f8f7f 1540 mlx5_eswitch_del_vlan_action(esw, attr);
d85cdccb 1541
777bb800
VB
1542 if (flow->decap_route)
1543 mlx5e_detach_decap_route(priv, flow);
1544
1545 for (out_index = 0; out_index < MLX5_MAX_FLOW_FWD_VPORTS; out_index++) {
8914add2
VB
1546 if (esw_attr->dests[out_index].flags &
1547 MLX5_ESW_DEST_CHAIN_WITH_SRC_PORT_CHANGE)
1548 vf_tun = true;
777bb800 1549 if (esw_attr->dests[out_index].flags & MLX5_ESW_DEST_ENCAP) {
8c4dc42b 1550 mlx5e_detach_encap(priv, flow, out_index);
2a4b6526
VB
1551 kfree(attr->parse_attr->tun_info[out_index]);
1552 }
777bb800 1553 }
d7e75a32 1554
aedd133d 1555 mlx5_tc_ct_match_del(get_ct_priv(priv), &flow->attr->ct_attr);
4c8594ad 1556
c7b9038d
VB
1557 if (attr->action & MLX5_FLOW_CONTEXT_ACTION_MOD_HDR) {
1558 dealloc_mod_hdr_actions(&attr->parse_attr->mod_hdr_acts);
8914add2
VB
1559 if (vf_tun && attr->modify_hdr)
1560 mlx5_modify_header_dealloc(priv->mdev, attr->modify_hdr);
1561 else
1562 mlx5e_detach_mod_hdr(priv, flow);
c7b9038d 1563 }
bcd6740c 1564 kfree(attr->sample_attr);
8914add2
VB
1565 kvfree(attr->parse_attr);
1566 kvfree(attr->esw_attr->rx_tun_attr);
b8aee822
MB
1567
1568 if (attr->action & MLX5_FLOW_CONTEXT_ACTION_COUNT)
777bb800 1569 mlx5_fc_destroy(esw_attr->counter_dev, attr->counter);
14e6b038
EC
1570
1571 if (flow_flag_test(flow, L3_TO_L2_DECAP))
1572 mlx5e_detach_decap(priv, flow);
c620b772
AL
1573
1574 kfree(flow->attr);
d85cdccb
OG
1575}
1576
0d9f9647 1577struct mlx5_fc *mlx5e_tc_get_counter(struct mlx5e_tc_flow *flow)
b8aee822 1578{
c620b772 1579 return flow->attr->counter;
b8aee822
MB
1580}
1581
6a06c2f7 1582/* Iterate over tmp_list of flows attached to flow_list head. */
021905f8 1583void mlx5e_put_flow_list(struct mlx5e_priv *priv, struct list_head *flow_list)
6a06c2f7
VB
1584{
1585 struct mlx5e_tc_flow *flow, *tmp;
1586
1587 list_for_each_entry_safe(flow, tmp, flow_list, tmp_list)
1588 mlx5e_flow_put(priv, flow);
1589}
1590
04de7dda
RD
1591static void __mlx5e_tc_del_fdb_peer_flow(struct mlx5e_tc_flow *flow)
1592{
1593 struct mlx5_eswitch *esw = flow->priv->mdev->priv.eswitch;
1594
226f2ca3
VB
1595 if (!flow_flag_test(flow, ESWITCH) ||
1596 !flow_flag_test(flow, DUP))
04de7dda
RD
1597 return;
1598
1599 mutex_lock(&esw->offloads.peer_mutex);
1600 list_del(&flow->peer);
1601 mutex_unlock(&esw->offloads.peer_mutex);
1602
226f2ca3 1603 flow_flag_clear(flow, DUP);
04de7dda 1604
eb252c3a
RD
1605 if (refcount_dec_and_test(&flow->peer_flow->refcnt)) {
1606 mlx5e_tc_del_fdb_flow(flow->peer_flow->priv, flow->peer_flow);
1607 kfree(flow->peer_flow);
1608 }
1609
04de7dda
RD
1610 flow->peer_flow = NULL;
1611}
1612
1613static void mlx5e_tc_del_fdb_peer_flow(struct mlx5e_tc_flow *flow)
1614{
1615 struct mlx5_core_dev *dev = flow->priv->mdev;
1616 struct mlx5_devcom *devcom = dev->priv.devcom;
1617 struct mlx5_eswitch *peer_esw;
1618
1619 peer_esw = mlx5_devcom_get_peer_data(devcom, MLX5_DEVCOM_ESW_OFFLOADS);
1620 if (!peer_esw)
1621 return;
1622
1623 __mlx5e_tc_del_fdb_peer_flow(flow);
1624 mlx5_devcom_release_peer_data(devcom, MLX5_DEVCOM_ESW_OFFLOADS);
1625}
1626
e8f887ac 1627static void mlx5e_tc_del_flow(struct mlx5e_priv *priv,
961e8979 1628 struct mlx5e_tc_flow *flow)
e8f887ac 1629{
226f2ca3 1630 if (mlx5e_is_eswitch_flow(flow)) {
04de7dda 1631 mlx5e_tc_del_fdb_peer_flow(flow);
d85cdccb 1632 mlx5e_tc_del_fdb_flow(priv, flow);
04de7dda 1633 } else {
d85cdccb 1634 mlx5e_tc_del_nic_flow(priv, flow);
04de7dda 1635 }
e8f887ac
AV
1636}
1637
ee950e5d 1638static bool flow_requires_tunnel_mapping(u32 chain, struct flow_cls_offload *f)
0a7fcb78
PB
1639{
1640 struct flow_rule *rule = flow_cls_offload_flow_rule(f);
1641 struct flow_action *flow_action = &rule->action;
1642 const struct flow_action_entry *act;
1643 int i;
1644
ee950e5d
CM
1645 if (chain)
1646 return false;
1647
0a7fcb78
PB
1648 flow_action_for_each(i, act, flow_action) {
1649 switch (act->id) {
1650 case FLOW_ACTION_GOTO:
1651 return true;
ee950e5d
CM
1652 case FLOW_ACTION_SAMPLE:
1653 return true;
0a7fcb78
PB
1654 default:
1655 continue;
1656 }
1657 }
1658
1659 return false;
1660}
bbd00f7e 1661
0a7fcb78
PB
1662static int
1663enc_opts_is_dont_care_or_full_match(struct mlx5e_priv *priv,
1664 struct flow_dissector_key_enc_opts *opts,
1665 struct netlink_ext_ack *extack,
1666 bool *dont_care)
1667{
1668 struct geneve_opt *opt;
1669 int off = 0;
1670
1671 *dont_care = true;
1672
1673 while (opts->len > off) {
1674 opt = (struct geneve_opt *)&opts->data[off];
1675
1676 if (!(*dont_care) || opt->opt_class || opt->type ||
1677 memchr_inv(opt->opt_data, 0, opt->length * 4)) {
1678 *dont_care = false;
1679
c51323ee 1680 if (opt->opt_class != htons(U16_MAX) ||
d7a42ad0 1681 opt->type != U8_MAX) {
0a7fcb78
PB
1682 NL_SET_ERR_MSG(extack,
1683 "Partial match of tunnel options in chain > 0 isn't supported");
1684 netdev_warn(priv->netdev,
1685 "Partial match of tunnel options in chain > 0 isn't supported");
1686 return -EOPNOTSUPP;
1687 }
1688 }
1689
1690 off += sizeof(struct geneve_opt) + opt->length * 4;
1691 }
1692
1693 return 0;
1694}
1695
1696#define COPY_DISSECTOR(rule, diss_key, dst)\
1697({ \
1698 struct flow_rule *__rule = (rule);\
1699 typeof(dst) __dst = dst;\
1700\
1701 memcpy(__dst,\
1702 skb_flow_dissector_target(__rule->match.dissector,\
1703 diss_key,\
1704 __rule->match.key),\
1705 sizeof(*__dst));\
1706})
1707
1708static int mlx5e_get_flow_tunnel_id(struct mlx5e_priv *priv,
1709 struct mlx5e_tc_flow *flow,
1710 struct flow_cls_offload *f,
1711 struct net_device *filter_dev)
bbd00f7e 1712{
f9e30088 1713 struct flow_rule *rule = flow_cls_offload_flow_rule(f);
0a7fcb78 1714 struct netlink_ext_ack *extack = f->common.extack;
0a7fcb78
PB
1715 struct mlx5e_tc_mod_hdr_acts *mod_hdr_acts;
1716 struct flow_match_enc_opts enc_opts_match;
d7a42ad0 1717 struct tunnel_match_enc_opts tun_enc_opts;
0a7fcb78 1718 struct mlx5_rep_uplink_priv *uplink_priv;
c620b772 1719 struct mlx5_flow_attr *attr = flow->attr;
0a7fcb78
PB
1720 struct mlx5e_rep_priv *uplink_rpriv;
1721 struct tunnel_match_key tunnel_key;
1722 bool enc_opts_is_dont_care = true;
1723 u32 tun_id, enc_opts_id = 0;
1724 struct mlx5_eswitch *esw;
1725 u32 value, mask;
8f256622 1726 int err;
2e72eb43 1727
0a7fcb78
PB
1728 esw = priv->mdev->priv.eswitch;
1729 uplink_rpriv = mlx5_eswitch_get_uplink_priv(esw, REP_ETH);
1730 uplink_priv = &uplink_rpriv->uplink_priv;
1731
1732 memset(&tunnel_key, 0, sizeof(tunnel_key));
1733 COPY_DISSECTOR(rule, FLOW_DISSECTOR_KEY_ENC_CONTROL,
1734 &tunnel_key.enc_control);
1735 if (tunnel_key.enc_control.addr_type == FLOW_DISSECTOR_KEY_IPV4_ADDRS)
1736 COPY_DISSECTOR(rule, FLOW_DISSECTOR_KEY_ENC_IPV4_ADDRS,
1737 &tunnel_key.enc_ipv4);
1738 else
1739 COPY_DISSECTOR(rule, FLOW_DISSECTOR_KEY_ENC_IPV6_ADDRS,
1740 &tunnel_key.enc_ipv6);
1741 COPY_DISSECTOR(rule, FLOW_DISSECTOR_KEY_ENC_IP, &tunnel_key.enc_ip);
1742 COPY_DISSECTOR(rule, FLOW_DISSECTOR_KEY_ENC_PORTS,
1743 &tunnel_key.enc_tp);
1744 COPY_DISSECTOR(rule, FLOW_DISSECTOR_KEY_ENC_KEYID,
1745 &tunnel_key.enc_key_id);
1746 tunnel_key.filter_ifindex = filter_dev->ifindex;
1747
1748 err = mapping_add(uplink_priv->tunnel_mapping, &tunnel_key, &tun_id);
1749 if (err)
101f4de9 1750 return err;
bbd00f7e 1751
0a7fcb78
PB
1752 flow_rule_match_enc_opts(rule, &enc_opts_match);
1753 err = enc_opts_is_dont_care_or_full_match(priv,
1754 enc_opts_match.mask,
1755 extack,
1756 &enc_opts_is_dont_care);
1757 if (err)
1758 goto err_enc_opts;
fe1587a7 1759
0a7fcb78 1760 if (!enc_opts_is_dont_care) {
d7a42ad0
RD
1761 memset(&tun_enc_opts, 0, sizeof(tun_enc_opts));
1762 memcpy(&tun_enc_opts.key, enc_opts_match.key,
1763 sizeof(*enc_opts_match.key));
1764 memcpy(&tun_enc_opts.mask, enc_opts_match.mask,
1765 sizeof(*enc_opts_match.mask));
1766
0a7fcb78 1767 err = mapping_add(uplink_priv->tunnel_enc_opts_mapping,
d7a42ad0 1768 &tun_enc_opts, &enc_opts_id);
0a7fcb78
PB
1769 if (err)
1770 goto err_enc_opts;
1771 }
fe1587a7 1772
0a7fcb78
PB
1773 value = tun_id << ENC_OPTS_BITS | enc_opts_id;
1774 mask = enc_opts_id ? TUNNEL_ID_MASK :
1775 (TUNNEL_ID_MASK & ~ENC_OPTS_BITS_MASK);
fe1587a7 1776
0a7fcb78
PB
1777 if (attr->chain) {
1778 mlx5e_tc_match_to_reg_match(&attr->parse_attr->spec,
1779 TUNNEL_TO_REG, value, mask);
1780 } else {
1781 mod_hdr_acts = &attr->parse_attr->mod_hdr_acts;
1782 err = mlx5e_tc_match_to_reg_set(priv->mdev,
aedd133d 1783 mod_hdr_acts, MLX5_FLOW_NAMESPACE_FDB,
0a7fcb78
PB
1784 TUNNEL_TO_REG, value);
1785 if (err)
1786 goto err_set;
fe1587a7 1787
0a7fcb78 1788 attr->action |= MLX5_FLOW_CONTEXT_ACTION_MOD_HDR;
2e72eb43 1789 }
bbd00f7e 1790
0a7fcb78
PB
1791 flow->tunnel_id = value;
1792 return 0;
bcef735c 1793
0a7fcb78
PB
1794err_set:
1795 if (enc_opts_id)
1796 mapping_remove(uplink_priv->tunnel_enc_opts_mapping,
1797 enc_opts_id);
1798err_enc_opts:
1799 mapping_remove(uplink_priv->tunnel_mapping, tun_id);
1800 return err;
1801}
bcef735c 1802
0a7fcb78
PB
1803static void mlx5e_put_flow_tunnel_id(struct mlx5e_tc_flow *flow)
1804{
1805 u32 enc_opts_id = flow->tunnel_id & ENC_OPTS_BITS_MASK;
1806 u32 tun_id = flow->tunnel_id >> ENC_OPTS_BITS;
1807 struct mlx5_rep_uplink_priv *uplink_priv;
1808 struct mlx5e_rep_priv *uplink_rpriv;
1809 struct mlx5_eswitch *esw;
bcef735c 1810
0a7fcb78
PB
1811 esw = flow->priv->mdev->priv.eswitch;
1812 uplink_rpriv = mlx5_eswitch_get_uplink_priv(esw, REP_ETH);
1813 uplink_priv = &uplink_rpriv->uplink_priv;
1814
1815 if (tun_id)
1816 mapping_remove(uplink_priv->tunnel_mapping, tun_id);
1817 if (enc_opts_id)
1818 mapping_remove(uplink_priv->tunnel_enc_opts_mapping,
1819 enc_opts_id);
1820}
e98bedf5 1821
4c3844d9
PB
1822u32 mlx5e_tc_get_flow_tun_id(struct mlx5e_tc_flow *flow)
1823{
1824 return flow->tunnel_id;
1825}
1826
fca53304
EB
1827void mlx5e_tc_set_ethertype(struct mlx5_core_dev *mdev,
1828 struct flow_match_basic *match, bool outer,
1829 void *headers_c, void *headers_v)
1830{
1831 bool ip_version_cap;
1832
1833 ip_version_cap = outer ?
1834 MLX5_CAP_FLOWTABLE_NIC_RX(mdev,
1835 ft_field_support.outer_ip_version) :
1836 MLX5_CAP_FLOWTABLE_NIC_RX(mdev,
1837 ft_field_support.inner_ip_version);
1838
1839 if (ip_version_cap && match->mask->n_proto == htons(0xFFFF) &&
1840 (match->key->n_proto == htons(ETH_P_IP) ||
1841 match->key->n_proto == htons(ETH_P_IPV6))) {
1842 MLX5_SET_TO_ONES(fte_match_set_lyr_2_4, headers_c, ip_version);
1843 MLX5_SET(fte_match_set_lyr_2_4, headers_v, ip_version,
1844 match->key->n_proto == htons(ETH_P_IP) ? 4 : 6);
1845 } else {
1846 MLX5_SET(fte_match_set_lyr_2_4, headers_c, ethertype,
1847 ntohs(match->mask->n_proto));
1848 MLX5_SET(fte_match_set_lyr_2_4, headers_v, ethertype,
1849 ntohs(match->key->n_proto));
1850 }
4a5d5d73
EB
1851}
1852
0d9f9647 1853u8 mlx5e_tc_get_ip_version(struct mlx5_flow_spec *spec, bool outer)
a508728a
VB
1854{
1855 void *headers_v;
1856 u16 ethertype;
1857 u8 ip_version;
1858
1859 if (outer)
1860 headers_v = MLX5_ADDR_OF(fte_match_param, spec->match_value, outer_headers);
1861 else
1862 headers_v = MLX5_ADDR_OF(fte_match_param, spec->match_value, inner_headers);
1863
1864 ip_version = MLX5_GET(fte_match_set_lyr_2_4, headers_v, ip_version);
1865 /* Return ip_version converted from ethertype anyway */
1866 if (!ip_version) {
1867 ethertype = MLX5_GET(fte_match_set_lyr_2_4, headers_v, ethertype);
1868 if (ethertype == ETH_P_IP || ethertype == ETH_P_ARP)
1869 ip_version = 4;
1870 else if (ethertype == ETH_P_IPV6)
1871 ip_version = 6;
1872 }
1873 return ip_version;
1874}
1875
9bef4eea
PB
1876/* Tunnel device follows RFC 6040, see include/net/inet_ecn.h.
1877 * And changes inner ip_ecn depending on inner and outer ip_ecn as follows:
1878 * +---------+----------------------------------------+
1879 * |Arriving | Arriving Outer Header |
1880 * | Inner +---------+---------+---------+----------+
1881 * | Header | Not-ECT | ECT(0) | ECT(1) | CE |
1882 * +---------+---------+---------+---------+----------+
1883 * | Not-ECT | Not-ECT | Not-ECT | Not-ECT | <drop> |
1884 * | ECT(0) | ECT(0) | ECT(0) | ECT(1) | CE* |
1885 * | ECT(1) | ECT(1) | ECT(1) | ECT(1)* | CE* |
1886 * | CE | CE | CE | CE | CE |
1887 * +---------+---------+---------+---------+----------+
1888 *
1889 * Tc matches on inner after decapsulation on tunnel device, but hw offload matches
1890 * the inner ip_ecn value before hardware decap action.
1891 *
1892 * Cells marked are changed from original inner packet ip_ecn value during decap, and
1893 * so matching those values on inner ip_ecn before decap will fail.
1894 *
1895 * The following helper allows offload when inner ip_ecn won't be changed by outer ip_ecn,
1896 * except for the outer ip_ecn = CE, where in all cases inner ip_ecn will be changed to CE,
1897 * and such we can drop the inner ip_ecn=CE match.
1898 */
1899
1900static int mlx5e_tc_verify_tunnel_ecn(struct mlx5e_priv *priv,
1901 struct flow_cls_offload *f,
1902 bool *match_inner_ecn)
1903{
1904 u8 outer_ecn_mask = 0, outer_ecn_key = 0, inner_ecn_mask = 0, inner_ecn_key = 0;
1905 struct flow_rule *rule = flow_cls_offload_flow_rule(f);
1906 struct netlink_ext_ack *extack = f->common.extack;
1907 struct flow_match_ip match;
1908
1909 *match_inner_ecn = true;
1910
1911 if (flow_rule_match_key(rule, FLOW_DISSECTOR_KEY_ENC_IP)) {
1912 flow_rule_match_enc_ip(rule, &match);
1913 outer_ecn_key = match.key->tos & INET_ECN_MASK;
1914 outer_ecn_mask = match.mask->tos & INET_ECN_MASK;
1915 }
1916
1917 if (flow_rule_match_key(rule, FLOW_DISSECTOR_KEY_IP)) {
1918 flow_rule_match_ip(rule, &match);
1919 inner_ecn_key = match.key->tos & INET_ECN_MASK;
1920 inner_ecn_mask = match.mask->tos & INET_ECN_MASK;
1921 }
1922
1923 if (outer_ecn_mask != 0 && outer_ecn_mask != INET_ECN_MASK) {
1924 NL_SET_ERR_MSG_MOD(extack, "Partial match on enc_tos ecn bits isn't supported");
1925 netdev_warn(priv->netdev, "Partial match on enc_tos ecn bits isn't supported");
1926 return -EOPNOTSUPP;
1927 }
1928
1929 if (!outer_ecn_mask) {
1930 if (!inner_ecn_mask)
1931 return 0;
1932
1933 NL_SET_ERR_MSG_MOD(extack,
1934 "Matching on tos ecn bits without also matching enc_tos ecn bits isn't supported");
1935 netdev_warn(priv->netdev,
1936 "Matching on tos ecn bits without also matching enc_tos ecn bits isn't supported");
1937 return -EOPNOTSUPP;
1938 }
1939
1940 if (inner_ecn_mask && inner_ecn_mask != INET_ECN_MASK) {
1941 NL_SET_ERR_MSG_MOD(extack,
1942 "Partial match on tos ecn bits with match on enc_tos ecn bits isn't supported");
1943 netdev_warn(priv->netdev,
1944 "Partial match on tos ecn bits with match on enc_tos ecn bits isn't supported");
1945 return -EOPNOTSUPP;
1946 }
1947
1948 if (!inner_ecn_mask)
1949 return 0;
1950
1951 /* Both inner and outer have full mask on ecn */
1952
1953 if (outer_ecn_key == INET_ECN_ECT_1) {
1954 /* inner ecn might change by DECAP action */
1955
1956 NL_SET_ERR_MSG_MOD(extack, "Match on enc_tos ecn = ECT(1) isn't supported");
1957 netdev_warn(priv->netdev, "Match on enc_tos ecn = ECT(1) isn't supported");
1958 return -EOPNOTSUPP;
1959 }
1960
1961 if (outer_ecn_key != INET_ECN_CE)
1962 return 0;
1963
1964 if (inner_ecn_key != INET_ECN_CE) {
1965 /* Can't happen in software, as packet ecn will be changed to CE after decap */
1966 NL_SET_ERR_MSG_MOD(extack,
1967 "Match on tos enc_tos ecn = CE while match on tos ecn != CE isn't supported");
1968 netdev_warn(priv->netdev,
1969 "Match on tos enc_tos ecn = CE while match on tos ecn != CE isn't supported");
1970 return -EOPNOTSUPP;
1971 }
1972
1973 /* outer ecn = CE, inner ecn = CE, as decap will change inner ecn to CE in anycase,
1974 * drop match on inner ecn
1975 */
1976 *match_inner_ecn = false;
1977
1978 return 0;
1979}
1980
bbd00f7e 1981static int parse_tunnel_attr(struct mlx5e_priv *priv,
0a7fcb78 1982 struct mlx5e_tc_flow *flow,
bbd00f7e 1983 struct mlx5_flow_spec *spec,
f9e30088 1984 struct flow_cls_offload *f,
0a7fcb78
PB
1985 struct net_device *filter_dev,
1986 u8 *match_level,
1987 bool *match_inner)
bbd00f7e 1988{
a508728a 1989 struct mlx5e_tc_tunnel *tunnel = mlx5e_get_tc_tun(filter_dev);
0a7fcb78 1990 struct mlx5_eswitch *esw = priv->mdev->priv.eswitch;
e98bedf5 1991 struct netlink_ext_ack *extack = f->common.extack;
0a7fcb78 1992 bool needs_mapping, sets_mapping;
8f256622 1993 int err;
2e72eb43 1994
0a7fcb78
PB
1995 if (!mlx5e_is_eswitch_flow(flow))
1996 return -EOPNOTSUPP;
1997
c620b772 1998 needs_mapping = !!flow->attr->chain;
ee950e5d 1999 sets_mapping = flow_requires_tunnel_mapping(flow->attr->chain, f);
0a7fcb78
PB
2000 *match_inner = !needs_mapping;
2001
2002 if ((needs_mapping || sets_mapping) &&
636bb968 2003 !mlx5_eswitch_reg_c1_loopback_enabled(esw)) {
0a7fcb78 2004 NL_SET_ERR_MSG(extack,
636bb968 2005 "Chains on tunnel devices isn't supported without register loopback support");
0a7fcb78 2006 netdev_warn(priv->netdev,
636bb968 2007 "Chains on tunnel devices isn't supported without register loopback support");
0a7fcb78 2008 return -EOPNOTSUPP;
bbd00f7e
HHZ
2009 }
2010
c620b772 2011 if (!flow->attr->chain) {
0a7fcb78
PB
2012 err = mlx5e_tc_tun_parse(filter_dev, priv, spec, f,
2013 match_level);
2014 if (err) {
e98bedf5 2015 NL_SET_ERR_MSG_MOD(extack,
0a7fcb78
PB
2016 "Failed to parse tunnel attributes");
2017 netdev_warn(priv->netdev,
2018 "Failed to parse tunnel attributes");
2019 return err;
e98bedf5
EB
2020 }
2021
14e6b038
EC
2022 /* With mpls over udp we decapsulate using packet reformat
2023 * object
2024 */
2025 if (!netif_is_bareudp(filter_dev))
c620b772 2026 flow->attr->action |= MLX5_FLOW_CONTEXT_ACTION_DECAP;
a508728a
VB
2027 err = mlx5e_tc_set_attr_rx_tun(flow, spec);
2028 if (err)
2029 return err;
2030 } else if (tunnel && tunnel->tunnel_type == MLX5E_TC_TUNNEL_TYPE_VXLAN) {
2031 struct mlx5_flow_spec *tmp_spec;
2032
2033 tmp_spec = kvzalloc(sizeof(*tmp_spec), GFP_KERNEL);
2034 if (!tmp_spec) {
2035 NL_SET_ERR_MSG_MOD(extack, "Failed to allocate memory for vxlan tmp spec");
2036 netdev_warn(priv->netdev, "Failed to allocate memory for vxlan tmp spec");
2037 return -ENOMEM;
2038 }
2039 memcpy(tmp_spec, spec, sizeof(*tmp_spec));
2040
2041 err = mlx5e_tc_tun_parse(filter_dev, priv, tmp_spec, f, match_level);
2042 if (err) {
2043 kvfree(tmp_spec);
2044 NL_SET_ERR_MSG_MOD(extack, "Failed to parse tunnel attributes");
2045 netdev_warn(priv->netdev, "Failed to parse tunnel attributes");
2046 return err;
2047 }
2048 err = mlx5e_tc_set_attr_rx_tun(flow, tmp_spec);
2049 kvfree(tmp_spec);
2050 if (err)
2051 return err;
bcef735c
OG
2052 }
2053
0a7fcb78
PB
2054 if (!needs_mapping && !sets_mapping)
2055 return 0;
bbd00f7e 2056
0a7fcb78 2057 return mlx5e_get_flow_tunnel_id(priv, flow, f, filter_dev);
bbd00f7e 2058}
bbd00f7e 2059
0a7fcb78 2060static void *get_match_inner_headers_criteria(struct mlx5_flow_spec *spec)
8377629e 2061{
0a7fcb78
PB
2062 return MLX5_ADDR_OF(fte_match_param, spec->match_criteria,
2063 inner_headers);
bbd00f7e
HHZ
2064}
2065
0a7fcb78 2066static void *get_match_inner_headers_value(struct mlx5_flow_spec *spec)
8377629e 2067{
0a7fcb78
PB
2068 return MLX5_ADDR_OF(fte_match_param, spec->match_value,
2069 inner_headers);
2070}
2071
2072static void *get_match_outer_headers_criteria(struct mlx5_flow_spec *spec)
2073{
2074 return MLX5_ADDR_OF(fte_match_param, spec->match_criteria,
2075 outer_headers);
2076}
2077
2078static void *get_match_outer_headers_value(struct mlx5_flow_spec *spec)
2079{
2080 return MLX5_ADDR_OF(fte_match_param, spec->match_value,
2081 outer_headers);
8377629e
EB
2082}
2083
2084static void *get_match_headers_value(u32 flags,
2085 struct mlx5_flow_spec *spec)
2086{
2087 return (flags & MLX5_FLOW_CONTEXT_ACTION_DECAP) ?
0a7fcb78
PB
2088 get_match_inner_headers_value(spec) :
2089 get_match_outer_headers_value(spec);
2090}
2091
2092static void *get_match_headers_criteria(u32 flags,
2093 struct mlx5_flow_spec *spec)
2094{
2095 return (flags & MLX5_FLOW_CONTEXT_ACTION_DECAP) ?
2096 get_match_inner_headers_criteria(spec) :
2097 get_match_outer_headers_criteria(spec);
8377629e
EB
2098}
2099
6d65bc64 2100static int mlx5e_flower_parse_meta(struct net_device *filter_dev,
2101 struct flow_cls_offload *f)
2102{
2103 struct flow_rule *rule = flow_cls_offload_flow_rule(f);
2104 struct netlink_ext_ack *extack = f->common.extack;
2105 struct net_device *ingress_dev;
2106 struct flow_match_meta match;
2107
2108 if (!flow_rule_match_key(rule, FLOW_DISSECTOR_KEY_META))
2109 return 0;
2110
2111 flow_rule_match_meta(rule, &match);
e3e0f9b2 2112 if (!match.mask->ingress_ifindex)
2113 return 0;
2114
6d65bc64 2115 if (match.mask->ingress_ifindex != 0xFFFFFFFF) {
2116 NL_SET_ERR_MSG_MOD(extack, "Unsupported ingress ifindex mask");
a683012a 2117 return -EOPNOTSUPP;
6d65bc64 2118 }
2119
2120 ingress_dev = __dev_get_by_index(dev_net(filter_dev),
2121 match.key->ingress_ifindex);
2122 if (!ingress_dev) {
2123 NL_SET_ERR_MSG_MOD(extack,
2124 "Can't find the ingress port to match on");
a683012a 2125 return -ENOENT;
6d65bc64 2126 }
2127
2128 if (ingress_dev != filter_dev) {
2129 NL_SET_ERR_MSG_MOD(extack,
2130 "Can't match on the ingress filter port");
a683012a 2131 return -EOPNOTSUPP;
6d65bc64 2132 }
2133
2134 return 0;
2135}
2136
72046a91
EC
2137static bool skip_key_basic(struct net_device *filter_dev,
2138 struct flow_cls_offload *f)
2139{
2140 /* When doing mpls over udp decap, the user needs to provide
2141 * MPLS_UC as the protocol in order to be able to match on mpls
2142 * label fields. However, the actual ethertype is IP so we want to
2143 * avoid matching on this, otherwise we'll fail the match.
2144 */
2145 if (netif_is_bareudp(filter_dev) && f->common.chain_index == 0)
2146 return true;
2147
2148 return false;
2149}
2150
de0af0bf 2151static int __parse_cls_flower(struct mlx5e_priv *priv,
0a7fcb78 2152 struct mlx5e_tc_flow *flow,
de0af0bf 2153 struct mlx5_flow_spec *spec,
f9e30088 2154 struct flow_cls_offload *f,
54c177ca 2155 struct net_device *filter_dev,
93b3586e 2156 u8 *inner_match_level, u8 *outer_match_level)
e3a2b7ed 2157{
e98bedf5 2158 struct netlink_ext_ack *extack = f->common.extack;
c5bb1730
MG
2159 void *headers_c = MLX5_ADDR_OF(fte_match_param, spec->match_criteria,
2160 outer_headers);
2161 void *headers_v = MLX5_ADDR_OF(fte_match_param, spec->match_value,
2162 outer_headers);
699e96dd
JL
2163 void *misc_c = MLX5_ADDR_OF(fte_match_param, spec->match_criteria,
2164 misc_parameters);
2165 void *misc_v = MLX5_ADDR_OF(fte_match_param, spec->match_value,
2166 misc_parameters);
a3222a2d
MD
2167 void *misc_c_3 = MLX5_ADDR_OF(fte_match_param, spec->match_criteria,
2168 misc_parameters_3);
2169 void *misc_v_3 = MLX5_ADDR_OF(fte_match_param, spec->match_value,
2170 misc_parameters_3);
f9e30088 2171 struct flow_rule *rule = flow_cls_offload_flow_rule(f);
8f256622 2172 struct flow_dissector *dissector = rule->match.dissector;
afe93f71 2173 enum fs_flow_table_type fs_type;
9bef4eea 2174 bool match_inner_ecn = true;
e3a2b7ed
AV
2175 u16 addr_type = 0;
2176 u8 ip_proto = 0;
93b3586e 2177 u8 *match_level;
6d65bc64 2178 int err;
e3a2b7ed 2179
afe93f71 2180 fs_type = mlx5e_is_eswitch_flow(flow) ? FS_FT_FDB : FS_FT_NIC_RX;
93b3586e 2181 match_level = outer_match_level;
de0af0bf 2182
8f256622 2183 if (dissector->used_keys &
3d144578
VB
2184 ~(BIT(FLOW_DISSECTOR_KEY_META) |
2185 BIT(FLOW_DISSECTOR_KEY_CONTROL) |
e3a2b7ed
AV
2186 BIT(FLOW_DISSECTOR_KEY_BASIC) |
2187 BIT(FLOW_DISSECTOR_KEY_ETH_ADDRS) |
095b6cfd 2188 BIT(FLOW_DISSECTOR_KEY_VLAN) |
699e96dd 2189 BIT(FLOW_DISSECTOR_KEY_CVLAN) |
e3a2b7ed
AV
2190 BIT(FLOW_DISSECTOR_KEY_IPV4_ADDRS) |
2191 BIT(FLOW_DISSECTOR_KEY_IPV6_ADDRS) |
bbd00f7e
HHZ
2192 BIT(FLOW_DISSECTOR_KEY_PORTS) |
2193 BIT(FLOW_DISSECTOR_KEY_ENC_KEYID) |
2194 BIT(FLOW_DISSECTOR_KEY_ENC_IPV4_ADDRS) |
2195 BIT(FLOW_DISSECTOR_KEY_ENC_IPV6_ADDRS) |
2196 BIT(FLOW_DISSECTOR_KEY_ENC_PORTS) |
e77834ec 2197 BIT(FLOW_DISSECTOR_KEY_ENC_CONTROL) |
fd7da28b 2198 BIT(FLOW_DISSECTOR_KEY_TCP) |
bcef735c 2199 BIT(FLOW_DISSECTOR_KEY_IP) |
4c3844d9 2200 BIT(FLOW_DISSECTOR_KEY_CT) |
9272e3df 2201 BIT(FLOW_DISSECTOR_KEY_ENC_IP) |
72046a91 2202 BIT(FLOW_DISSECTOR_KEY_ENC_OPTS) |
a3222a2d 2203 BIT(FLOW_DISSECTOR_KEY_ICMP) |
72046a91 2204 BIT(FLOW_DISSECTOR_KEY_MPLS))) {
e98bedf5 2205 NL_SET_ERR_MSG_MOD(extack, "Unsupported key");
48470a90
MD
2206 netdev_dbg(priv->netdev, "Unsupported key used: 0x%x\n",
2207 dissector->used_keys);
e3a2b7ed
AV
2208 return -EOPNOTSUPP;
2209 }
2210
075973c7 2211 if (mlx5e_get_tc_tun(filter_dev)) {
0a7fcb78 2212 bool match_inner = false;
bbd00f7e 2213
0a7fcb78
PB
2214 err = parse_tunnel_attr(priv, flow, spec, f, filter_dev,
2215 outer_match_level, &match_inner);
2216 if (err)
2217 return err;
2218
2219 if (match_inner) {
2220 /* header pointers should point to the inner headers
2221 * if the packet was decapsulated already.
2222 * outer headers are set by parse_tunnel_attr.
2223 */
2224 match_level = inner_match_level;
2225 headers_c = get_match_inner_headers_criteria(spec);
2226 headers_v = get_match_inner_headers_value(spec);
2227 }
9bef4eea
PB
2228
2229 err = mlx5e_tc_verify_tunnel_ecn(priv, f, &match_inner_ecn);
2230 if (err)
2231 return err;
bbd00f7e
HHZ
2232 }
2233
6d65bc64 2234 err = mlx5e_flower_parse_meta(filter_dev, f);
2235 if (err)
2236 return err;
2237
72046a91
EC
2238 if (flow_rule_match_key(rule, FLOW_DISSECTOR_KEY_BASIC) &&
2239 !skip_key_basic(filter_dev, f)) {
8f256622
PNA
2240 struct flow_match_basic match;
2241
2242 flow_rule_match_basic(rule, &match);
fca53304
EB
2243 mlx5e_tc_set_ethertype(priv->mdev, &match,
2244 match_level == outer_match_level,
2245 headers_c, headers_v);
e3a2b7ed 2246
8f256622 2247 if (match.mask->n_proto)
d708f902 2248 *match_level = MLX5_MATCH_L2;
e3a2b7ed 2249 }
35a605db
EB
2250 if (flow_rule_match_key(rule, FLOW_DISSECTOR_KEY_VLAN) ||
2251 is_vlan_dev(filter_dev)) {
2252 struct flow_dissector_key_vlan filter_dev_mask;
2253 struct flow_dissector_key_vlan filter_dev_key;
8f256622
PNA
2254 struct flow_match_vlan match;
2255
35a605db
EB
2256 if (is_vlan_dev(filter_dev)) {
2257 match.key = &filter_dev_key;
2258 match.key->vlan_id = vlan_dev_vlan_id(filter_dev);
2259 match.key->vlan_tpid = vlan_dev_vlan_proto(filter_dev);
2260 match.key->vlan_priority = 0;
2261 match.mask = &filter_dev_mask;
2262 memset(match.mask, 0xff, sizeof(*match.mask));
2263 match.mask->vlan_priority = 0;
2264 } else {
2265 flow_rule_match_vlan(rule, &match);
2266 }
8f256622
PNA
2267 if (match.mask->vlan_id ||
2268 match.mask->vlan_priority ||
2269 match.mask->vlan_tpid) {
2270 if (match.key->vlan_tpid == htons(ETH_P_8021AD)) {
699e96dd
JL
2271 MLX5_SET(fte_match_set_lyr_2_4, headers_c,
2272 svlan_tag, 1);
2273 MLX5_SET(fte_match_set_lyr_2_4, headers_v,
2274 svlan_tag, 1);
2275 } else {
2276 MLX5_SET(fte_match_set_lyr_2_4, headers_c,
2277 cvlan_tag, 1);
2278 MLX5_SET(fte_match_set_lyr_2_4, headers_v,
2279 cvlan_tag, 1);
2280 }
095b6cfd 2281
8f256622
PNA
2282 MLX5_SET(fte_match_set_lyr_2_4, headers_c, first_vid,
2283 match.mask->vlan_id);
2284 MLX5_SET(fte_match_set_lyr_2_4, headers_v, first_vid,
2285 match.key->vlan_id);
358d79a4 2286
8f256622
PNA
2287 MLX5_SET(fte_match_set_lyr_2_4, headers_c, first_prio,
2288 match.mask->vlan_priority);
2289 MLX5_SET(fte_match_set_lyr_2_4, headers_v, first_prio,
2290 match.key->vlan_priority);
54782900 2291
d708f902 2292 *match_level = MLX5_MATCH_L2;
6182930e
VB
2293
2294 if (!flow_rule_match_key(rule, FLOW_DISSECTOR_KEY_CVLAN) &&
2295 match.mask->vlan_eth_type &&
2296 MLX5_CAP_FLOWTABLE_TYPE(priv->mdev,
2297 ft_field_support.outer_second_vid,
2298 fs_type)) {
2299 MLX5_SET(fte_match_set_misc, misc_c,
2300 outer_second_cvlan_tag, 1);
2301 spec->match_criteria_enable |=
2302 MLX5_MATCH_MISC_PARAMETERS;
2303 }
54782900 2304 }
d3a80bb5 2305 } else if (*match_level != MLX5_MATCH_NONE) {
fc603294
MB
2306 /* cvlan_tag enabled in match criteria and
2307 * disabled in match value means both S & C tags
2308 * don't exist (untagged of both)
2309 */
cee26487 2310 MLX5_SET(fte_match_set_lyr_2_4, headers_c, cvlan_tag, 1);
d3a80bb5 2311 *match_level = MLX5_MATCH_L2;
54782900
OG
2312 }
2313
8f256622
PNA
2314 if (flow_rule_match_key(rule, FLOW_DISSECTOR_KEY_CVLAN)) {
2315 struct flow_match_vlan match;
2316
12d5cbf8 2317 flow_rule_match_cvlan(rule, &match);
8f256622
PNA
2318 if (match.mask->vlan_id ||
2319 match.mask->vlan_priority ||
2320 match.mask->vlan_tpid) {
afe93f71
RD
2321 if (!MLX5_CAP_FLOWTABLE_TYPE(priv->mdev, ft_field_support.outer_second_vid,
2322 fs_type)) {
2323 NL_SET_ERR_MSG_MOD(extack,
2324 "Matching on CVLAN is not supported");
2325 return -EOPNOTSUPP;
2326 }
2327
8f256622 2328 if (match.key->vlan_tpid == htons(ETH_P_8021AD)) {
699e96dd
JL
2329 MLX5_SET(fte_match_set_misc, misc_c,
2330 outer_second_svlan_tag, 1);
2331 MLX5_SET(fte_match_set_misc, misc_v,
2332 outer_second_svlan_tag, 1);
2333 } else {
2334 MLX5_SET(fte_match_set_misc, misc_c,
2335 outer_second_cvlan_tag, 1);
2336 MLX5_SET(fte_match_set_misc, misc_v,
2337 outer_second_cvlan_tag, 1);
2338 }
2339
2340 MLX5_SET(fte_match_set_misc, misc_c, outer_second_vid,
8f256622 2341 match.mask->vlan_id);
699e96dd 2342 MLX5_SET(fte_match_set_misc, misc_v, outer_second_vid,
8f256622 2343 match.key->vlan_id);
699e96dd 2344 MLX5_SET(fte_match_set_misc, misc_c, outer_second_prio,
8f256622 2345 match.mask->vlan_priority);
699e96dd 2346 MLX5_SET(fte_match_set_misc, misc_v, outer_second_prio,
8f256622 2347 match.key->vlan_priority);
699e96dd
JL
2348
2349 *match_level = MLX5_MATCH_L2;
0faddfe6 2350 spec->match_criteria_enable |= MLX5_MATCH_MISC_PARAMETERS;
699e96dd
JL
2351 }
2352 }
2353
8f256622
PNA
2354 if (flow_rule_match_key(rule, FLOW_DISSECTOR_KEY_ETH_ADDRS)) {
2355 struct flow_match_eth_addrs match;
54782900 2356
8f256622 2357 flow_rule_match_eth_addrs(rule, &match);
d3a80bb5
OG
2358 ether_addr_copy(MLX5_ADDR_OF(fte_match_set_lyr_2_4, headers_c,
2359 dmac_47_16),
8f256622 2360 match.mask->dst);
d3a80bb5
OG
2361 ether_addr_copy(MLX5_ADDR_OF(fte_match_set_lyr_2_4, headers_v,
2362 dmac_47_16),
8f256622 2363 match.key->dst);
d3a80bb5
OG
2364
2365 ether_addr_copy(MLX5_ADDR_OF(fte_match_set_lyr_2_4, headers_c,
2366 smac_47_16),
8f256622 2367 match.mask->src);
d3a80bb5
OG
2368 ether_addr_copy(MLX5_ADDR_OF(fte_match_set_lyr_2_4, headers_v,
2369 smac_47_16),
8f256622 2370 match.key->src);
d3a80bb5 2371
8f256622
PNA
2372 if (!is_zero_ether_addr(match.mask->src) ||
2373 !is_zero_ether_addr(match.mask->dst))
d708f902 2374 *match_level = MLX5_MATCH_L2;
54782900
OG
2375 }
2376
8f256622
PNA
2377 if (flow_rule_match_key(rule, FLOW_DISSECTOR_KEY_CONTROL)) {
2378 struct flow_match_control match;
54782900 2379
8f256622
PNA
2380 flow_rule_match_control(rule, &match);
2381 addr_type = match.key->addr_type;
54782900
OG
2382
2383 /* the HW doesn't support frag first/later */
8f256622 2384 if (match.mask->flags & FLOW_DIS_FIRST_FRAG)
54782900
OG
2385 return -EOPNOTSUPP;
2386
8f256622 2387 if (match.mask->flags & FLOW_DIS_IS_FRAGMENT) {
54782900
OG
2388 MLX5_SET(fte_match_set_lyr_2_4, headers_c, frag, 1);
2389 MLX5_SET(fte_match_set_lyr_2_4, headers_v, frag,
8f256622 2390 match.key->flags & FLOW_DIS_IS_FRAGMENT);
54782900
OG
2391
2392 /* the HW doesn't need L3 inline to match on frag=no */
8f256622 2393 if (!(match.key->flags & FLOW_DIS_IS_FRAGMENT))
83621b7d 2394 *match_level = MLX5_MATCH_L2;
54782900
OG
2395 /* *** L2 attributes parsing up to here *** */
2396 else
83621b7d 2397 *match_level = MLX5_MATCH_L3;
095b6cfd
OG
2398 }
2399 }
2400
8f256622
PNA
2401 if (flow_rule_match_key(rule, FLOW_DISSECTOR_KEY_BASIC)) {
2402 struct flow_match_basic match;
2403
2404 flow_rule_match_basic(rule, &match);
2405 ip_proto = match.key->ip_proto;
54782900
OG
2406
2407 MLX5_SET(fte_match_set_lyr_2_4, headers_c, ip_protocol,
8f256622 2408 match.mask->ip_proto);
54782900 2409 MLX5_SET(fte_match_set_lyr_2_4, headers_v, ip_protocol,
8f256622 2410 match.key->ip_proto);
54782900 2411
8f256622 2412 if (match.mask->ip_proto)
d708f902 2413 *match_level = MLX5_MATCH_L3;
54782900
OG
2414 }
2415
e3a2b7ed 2416 if (addr_type == FLOW_DISSECTOR_KEY_IPV4_ADDRS) {
8f256622 2417 struct flow_match_ipv4_addrs match;
e3a2b7ed 2418
8f256622 2419 flow_rule_match_ipv4_addrs(rule, &match);
e3a2b7ed
AV
2420 memcpy(MLX5_ADDR_OF(fte_match_set_lyr_2_4, headers_c,
2421 src_ipv4_src_ipv6.ipv4_layout.ipv4),
8f256622 2422 &match.mask->src, sizeof(match.mask->src));
e3a2b7ed
AV
2423 memcpy(MLX5_ADDR_OF(fte_match_set_lyr_2_4, headers_v,
2424 src_ipv4_src_ipv6.ipv4_layout.ipv4),
8f256622 2425 &match.key->src, sizeof(match.key->src));
e3a2b7ed
AV
2426 memcpy(MLX5_ADDR_OF(fte_match_set_lyr_2_4, headers_c,
2427 dst_ipv4_dst_ipv6.ipv4_layout.ipv4),
8f256622 2428 &match.mask->dst, sizeof(match.mask->dst));
e3a2b7ed
AV
2429 memcpy(MLX5_ADDR_OF(fte_match_set_lyr_2_4, headers_v,
2430 dst_ipv4_dst_ipv6.ipv4_layout.ipv4),
8f256622 2431 &match.key->dst, sizeof(match.key->dst));
de0af0bf 2432
8f256622 2433 if (match.mask->src || match.mask->dst)
d708f902 2434 *match_level = MLX5_MATCH_L3;
e3a2b7ed
AV
2435 }
2436
2437 if (addr_type == FLOW_DISSECTOR_KEY_IPV6_ADDRS) {
8f256622 2438 struct flow_match_ipv6_addrs match;
e3a2b7ed 2439
8f256622 2440 flow_rule_match_ipv6_addrs(rule, &match);
e3a2b7ed
AV
2441 memcpy(MLX5_ADDR_OF(fte_match_set_lyr_2_4, headers_c,
2442 src_ipv4_src_ipv6.ipv6_layout.ipv6),
8f256622 2443 &match.mask->src, sizeof(match.mask->src));
e3a2b7ed
AV
2444 memcpy(MLX5_ADDR_OF(fte_match_set_lyr_2_4, headers_v,
2445 src_ipv4_src_ipv6.ipv6_layout.ipv6),
8f256622 2446 &match.key->src, sizeof(match.key->src));
e3a2b7ed
AV
2447
2448 memcpy(MLX5_ADDR_OF(fte_match_set_lyr_2_4, headers_c,
2449 dst_ipv4_dst_ipv6.ipv6_layout.ipv6),
8f256622 2450 &match.mask->dst, sizeof(match.mask->dst));
e3a2b7ed
AV
2451 memcpy(MLX5_ADDR_OF(fte_match_set_lyr_2_4, headers_v,
2452 dst_ipv4_dst_ipv6.ipv6_layout.ipv6),
8f256622 2453 &match.key->dst, sizeof(match.key->dst));
de0af0bf 2454
8f256622
PNA
2455 if (ipv6_addr_type(&match.mask->src) != IPV6_ADDR_ANY ||
2456 ipv6_addr_type(&match.mask->dst) != IPV6_ADDR_ANY)
d708f902 2457 *match_level = MLX5_MATCH_L3;
e3a2b7ed
AV
2458 }
2459
8f256622
PNA
2460 if (flow_rule_match_key(rule, FLOW_DISSECTOR_KEY_IP)) {
2461 struct flow_match_ip match;
1f97a526 2462
8f256622 2463 flow_rule_match_ip(rule, &match);
9bef4eea
PB
2464 if (match_inner_ecn) {
2465 MLX5_SET(fte_match_set_lyr_2_4, headers_c, ip_ecn,
2466 match.mask->tos & 0x3);
2467 MLX5_SET(fte_match_set_lyr_2_4, headers_v, ip_ecn,
2468 match.key->tos & 0x3);
2469 }
1f97a526 2470
8f256622
PNA
2471 MLX5_SET(fte_match_set_lyr_2_4, headers_c, ip_dscp,
2472 match.mask->tos >> 2);
2473 MLX5_SET(fte_match_set_lyr_2_4, headers_v, ip_dscp,
2474 match.key->tos >> 2);
1f97a526 2475
8f256622
PNA
2476 MLX5_SET(fte_match_set_lyr_2_4, headers_c, ttl_hoplimit,
2477 match.mask->ttl);
2478 MLX5_SET(fte_match_set_lyr_2_4, headers_v, ttl_hoplimit,
2479 match.key->ttl);
1f97a526 2480
8f256622 2481 if (match.mask->ttl &&
a8ade55f 2482 !MLX5_CAP_ESW_FLOWTABLE_FDB(priv->mdev,
e98bedf5
EB
2483 ft_field_support.outer_ipv4_ttl)) {
2484 NL_SET_ERR_MSG_MOD(extack,
2485 "Matching on TTL is not supported");
1f97a526 2486 return -EOPNOTSUPP;
e98bedf5 2487 }
a8ade55f 2488
8f256622 2489 if (match.mask->tos || match.mask->ttl)
d708f902 2490 *match_level = MLX5_MATCH_L3;
1f97a526
OG
2491 }
2492
54782900
OG
2493 /* *** L3 attributes parsing up to here *** */
2494
8f256622
PNA
2495 if (flow_rule_match_key(rule, FLOW_DISSECTOR_KEY_PORTS)) {
2496 struct flow_match_ports match;
2497
2498 flow_rule_match_ports(rule, &match);
e3a2b7ed
AV
2499 switch (ip_proto) {
2500 case IPPROTO_TCP:
2501 MLX5_SET(fte_match_set_lyr_2_4, headers_c,
8f256622 2502 tcp_sport, ntohs(match.mask->src));
e3a2b7ed 2503 MLX5_SET(fte_match_set_lyr_2_4, headers_v,
8f256622 2504 tcp_sport, ntohs(match.key->src));
e3a2b7ed
AV
2505
2506 MLX5_SET(fte_match_set_lyr_2_4, headers_c,
8f256622 2507 tcp_dport, ntohs(match.mask->dst));
e3a2b7ed 2508 MLX5_SET(fte_match_set_lyr_2_4, headers_v,
8f256622 2509 tcp_dport, ntohs(match.key->dst));
e3a2b7ed
AV
2510 break;
2511
2512 case IPPROTO_UDP:
2513 MLX5_SET(fte_match_set_lyr_2_4, headers_c,
8f256622 2514 udp_sport, ntohs(match.mask->src));
e3a2b7ed 2515 MLX5_SET(fte_match_set_lyr_2_4, headers_v,
8f256622 2516 udp_sport, ntohs(match.key->src));
e3a2b7ed
AV
2517
2518 MLX5_SET(fte_match_set_lyr_2_4, headers_c,
8f256622 2519 udp_dport, ntohs(match.mask->dst));
e3a2b7ed 2520 MLX5_SET(fte_match_set_lyr_2_4, headers_v,
8f256622 2521 udp_dport, ntohs(match.key->dst));
e3a2b7ed
AV
2522 break;
2523 default:
e98bedf5
EB
2524 NL_SET_ERR_MSG_MOD(extack,
2525 "Only UDP and TCP transports are supported for L4 matching");
e3a2b7ed
AV
2526 netdev_err(priv->netdev,
2527 "Only UDP and TCP transport are supported\n");
2528 return -EINVAL;
2529 }
de0af0bf 2530
8f256622 2531 if (match.mask->src || match.mask->dst)
d708f902 2532 *match_level = MLX5_MATCH_L4;
e3a2b7ed
AV
2533 }
2534
8f256622
PNA
2535 if (flow_rule_match_key(rule, FLOW_DISSECTOR_KEY_TCP)) {
2536 struct flow_match_tcp match;
e77834ec 2537
8f256622 2538 flow_rule_match_tcp(rule, &match);
e77834ec 2539 MLX5_SET(fte_match_set_lyr_2_4, headers_c, tcp_flags,
8f256622 2540 ntohs(match.mask->flags));
e77834ec 2541 MLX5_SET(fte_match_set_lyr_2_4, headers_v, tcp_flags,
8f256622 2542 ntohs(match.key->flags));
e77834ec 2543
8f256622 2544 if (match.mask->flags)
d708f902 2545 *match_level = MLX5_MATCH_L4;
e77834ec 2546 }
a3222a2d
MD
2547 if (flow_rule_match_key(rule, FLOW_DISSECTOR_KEY_ICMP)) {
2548 struct flow_match_icmp match;
e77834ec 2549
a3222a2d
MD
2550 flow_rule_match_icmp(rule, &match);
2551 switch (ip_proto) {
2552 case IPPROTO_ICMP:
2553 if (!(MLX5_CAP_GEN(priv->mdev, flex_parser_protocols) &
2554 MLX5_FLEX_PROTO_ICMP))
2555 return -EOPNOTSUPP;
2556 MLX5_SET(fte_match_set_misc3, misc_c_3, icmp_type,
2557 match.mask->type);
2558 MLX5_SET(fte_match_set_misc3, misc_v_3, icmp_type,
2559 match.key->type);
2560 MLX5_SET(fte_match_set_misc3, misc_c_3, icmp_code,
2561 match.mask->code);
2562 MLX5_SET(fte_match_set_misc3, misc_v_3, icmp_code,
2563 match.key->code);
2564 break;
2565 case IPPROTO_ICMPV6:
2566 if (!(MLX5_CAP_GEN(priv->mdev, flex_parser_protocols) &
2567 MLX5_FLEX_PROTO_ICMPV6))
2568 return -EOPNOTSUPP;
2569 MLX5_SET(fte_match_set_misc3, misc_c_3, icmpv6_type,
2570 match.mask->type);
2571 MLX5_SET(fte_match_set_misc3, misc_v_3, icmpv6_type,
2572 match.key->type);
2573 MLX5_SET(fte_match_set_misc3, misc_c_3, icmpv6_code,
2574 match.mask->code);
2575 MLX5_SET(fte_match_set_misc3, misc_v_3, icmpv6_code,
2576 match.key->code);
2577 break;
2578 default:
2579 NL_SET_ERR_MSG_MOD(extack,
2580 "Code and type matching only with ICMP and ICMPv6");
2581 netdev_err(priv->netdev,
2582 "Code and type matching only with ICMP and ICMPv6\n");
2583 return -EINVAL;
2584 }
2585 if (match.mask->code || match.mask->type) {
2586 *match_level = MLX5_MATCH_L4;
2587 spec->match_criteria_enable |= MLX5_MATCH_MISC_PARAMETERS_3;
2588 }
2589 }
39c538d6 2590 /* Currently supported only for MPLS over UDP */
7d6c86e3
AH
2591 if (flow_rule_match_key(rule, FLOW_DISSECTOR_KEY_MPLS) &&
2592 !netif_is_bareudp(filter_dev)) {
2593 NL_SET_ERR_MSG_MOD(extack,
2594 "Matching on MPLS is supported only for MPLS over UDP");
2595 netdev_err(priv->netdev,
2596 "Matching on MPLS is supported only for MPLS over UDP\n");
2597 return -EOPNOTSUPP;
2598 }
2599
e3a2b7ed
AV
2600 return 0;
2601}
2602
de0af0bf 2603static int parse_cls_flower(struct mlx5e_priv *priv,
65ba8fb7 2604 struct mlx5e_tc_flow *flow,
de0af0bf 2605 struct mlx5_flow_spec *spec,
f9e30088 2606 struct flow_cls_offload *f,
54c177ca 2607 struct net_device *filter_dev)
de0af0bf 2608{
93b3586e 2609 u8 inner_match_level, outer_match_level, non_tunnel_match_level;
e98bedf5 2610 struct netlink_ext_ack *extack = f->common.extack;
de0af0bf
RD
2611 struct mlx5_core_dev *dev = priv->mdev;
2612 struct mlx5_eswitch *esw = dev->priv.eswitch;
1d447a39
SM
2613 struct mlx5e_rep_priv *rpriv = priv->ppriv;
2614 struct mlx5_eswitch_rep *rep;
226f2ca3 2615 bool is_eswitch_flow;
de0af0bf
RD
2616 int err;
2617
93b3586e
HN
2618 inner_match_level = MLX5_MATCH_NONE;
2619 outer_match_level = MLX5_MATCH_NONE;
2620
0a7fcb78
PB
2621 err = __parse_cls_flower(priv, flow, spec, f, filter_dev,
2622 &inner_match_level, &outer_match_level);
93b3586e
HN
2623 non_tunnel_match_level = (inner_match_level == MLX5_MATCH_NONE) ?
2624 outer_match_level : inner_match_level;
de0af0bf 2625
226f2ca3
VB
2626 is_eswitch_flow = mlx5e_is_eswitch_flow(flow);
2627 if (!err && is_eswitch_flow) {
1d447a39 2628 rep = rpriv->rep;
b05af6aa 2629 if (rep->vport != MLX5_VPORT_UPLINK &&
1d447a39 2630 (esw->offloads.inline_mode != MLX5_INLINE_MODE_NONE &&
93b3586e 2631 esw->offloads.inline_mode < non_tunnel_match_level)) {
e98bedf5
EB
2632 NL_SET_ERR_MSG_MOD(extack,
2633 "Flow is not offloaded due to min inline setting");
de0af0bf
RD
2634 netdev_warn(priv->netdev,
2635 "Flow is not offloaded due to min inline setting, required %d actual %d\n",
93b3586e 2636 non_tunnel_match_level, esw->offloads.inline_mode);
de0af0bf
RD
2637 return -EOPNOTSUPP;
2638 }
2639 }
2640
c620b772
AL
2641 flow->attr->inner_match_level = inner_match_level;
2642 flow->attr->outer_match_level = outer_match_level;
2643
38aa51c1 2644
de0af0bf
RD
2645 return err;
2646}
2647
d79b6df6
OG
2648struct pedit_headers {
2649 struct ethhdr eth;
0eb69bb9 2650 struct vlan_hdr vlan;
d79b6df6
OG
2651 struct iphdr ip4;
2652 struct ipv6hdr ip6;
2653 struct tcphdr tcp;
2654 struct udphdr udp;
2655};
2656
c500c86b
PNA
2657struct pedit_headers_action {
2658 struct pedit_headers vals;
2659 struct pedit_headers masks;
2660 u32 pedits;
2661};
2662
d79b6df6 2663static int pedit_header_offsets[] = {
73867881
PNA
2664 [FLOW_ACT_MANGLE_HDR_TYPE_ETH] = offsetof(struct pedit_headers, eth),
2665 [FLOW_ACT_MANGLE_HDR_TYPE_IP4] = offsetof(struct pedit_headers, ip4),
2666 [FLOW_ACT_MANGLE_HDR_TYPE_IP6] = offsetof(struct pedit_headers, ip6),
2667 [FLOW_ACT_MANGLE_HDR_TYPE_TCP] = offsetof(struct pedit_headers, tcp),
2668 [FLOW_ACT_MANGLE_HDR_TYPE_UDP] = offsetof(struct pedit_headers, udp),
d79b6df6
OG
2669};
2670
2671#define pedit_header(_ph, _htype) ((void *)(_ph) + pedit_header_offsets[_htype])
2672
2673static int set_pedit_val(u8 hdr_type, u32 mask, u32 val, u32 offset,
c500c86b 2674 struct pedit_headers_action *hdrs)
d79b6df6
OG
2675{
2676 u32 *curr_pmask, *curr_pval;
2677
c500c86b
PNA
2678 curr_pmask = (u32 *)(pedit_header(&hdrs->masks, hdr_type) + offset);
2679 curr_pval = (u32 *)(pedit_header(&hdrs->vals, hdr_type) + offset);
d79b6df6
OG
2680
2681 if (*curr_pmask & mask) /* disallow acting twice on the same location */
2682 goto out_err;
2683
2684 *curr_pmask |= mask;
2685 *curr_pval |= (val & mask);
2686
2687 return 0;
2688
2689out_err:
2690 return -EOPNOTSUPP;
2691}
2692
2693struct mlx5_fields {
2694 u8 field;
88f30bbc
DL
2695 u8 field_bsize;
2696 u32 field_mask;
d79b6df6 2697 u32 offset;
27c11b6b 2698 u32 match_offset;
d79b6df6
OG
2699};
2700
88f30bbc
DL
2701#define OFFLOAD(fw_field, field_bsize, field_mask, field, off, match_field) \
2702 {MLX5_ACTION_IN_FIELD_OUT_ ## fw_field, field_bsize, field_mask, \
27c11b6b
EB
2703 offsetof(struct pedit_headers, field) + (off), \
2704 MLX5_BYTE_OFF(fte_match_set_lyr_2_4, match_field)}
2705
2ef86872
EB
2706/* masked values are the same and there are no rewrites that do not have a
2707 * match.
2708 */
2709#define SAME_VAL_MASK(type, valp, maskp, matchvalp, matchmaskp) ({ \
2710 type matchmaskx = *(type *)(matchmaskp); \
2711 type matchvalx = *(type *)(matchvalp); \
2712 type maskx = *(type *)(maskp); \
2713 type valx = *(type *)(valp); \
2714 \
2715 (valx & maskx) == (matchvalx & matchmaskx) && !(maskx & (maskx ^ \
2716 matchmaskx)); \
2717})
2718
27c11b6b 2719static bool cmp_val_mask(void *valp, void *maskp, void *matchvalp,
88f30bbc 2720 void *matchmaskp, u8 bsize)
27c11b6b
EB
2721{
2722 bool same = false;
2723
88f30bbc
DL
2724 switch (bsize) {
2725 case 8:
2ef86872 2726 same = SAME_VAL_MASK(u8, valp, maskp, matchvalp, matchmaskp);
27c11b6b 2727 break;
88f30bbc 2728 case 16:
2ef86872 2729 same = SAME_VAL_MASK(u16, valp, maskp, matchvalp, matchmaskp);
27c11b6b 2730 break;
88f30bbc 2731 case 32:
2ef86872 2732 same = SAME_VAL_MASK(u32, valp, maskp, matchvalp, matchmaskp);
27c11b6b
EB
2733 break;
2734 }
2735
2736 return same;
2737}
a8e4f0c4 2738
d79b6df6 2739static struct mlx5_fields fields[] = {
88f30bbc
DL
2740 OFFLOAD(DMAC_47_16, 32, U32_MAX, eth.h_dest[0], 0, dmac_47_16),
2741 OFFLOAD(DMAC_15_0, 16, U16_MAX, eth.h_dest[4], 0, dmac_15_0),
2742 OFFLOAD(SMAC_47_16, 32, U32_MAX, eth.h_source[0], 0, smac_47_16),
2743 OFFLOAD(SMAC_15_0, 16, U16_MAX, eth.h_source[4], 0, smac_15_0),
2744 OFFLOAD(ETHERTYPE, 16, U16_MAX, eth.h_proto, 0, ethertype),
2745 OFFLOAD(FIRST_VID, 16, U16_MAX, vlan.h_vlan_TCI, 0, first_vid),
2746
ab9341b5 2747 OFFLOAD(IP_DSCP, 8, 0xfc, ip4.tos, 0, ip_dscp),
88f30bbc
DL
2748 OFFLOAD(IP_TTL, 8, U8_MAX, ip4.ttl, 0, ttl_hoplimit),
2749 OFFLOAD(SIPV4, 32, U32_MAX, ip4.saddr, 0, src_ipv4_src_ipv6.ipv4_layout.ipv4),
2750 OFFLOAD(DIPV4, 32, U32_MAX, ip4.daddr, 0, dst_ipv4_dst_ipv6.ipv4_layout.ipv4),
2751
2752 OFFLOAD(SIPV6_127_96, 32, U32_MAX, ip6.saddr.s6_addr32[0], 0,
27c11b6b 2753 src_ipv4_src_ipv6.ipv6_layout.ipv6[0]),
88f30bbc 2754 OFFLOAD(SIPV6_95_64, 32, U32_MAX, ip6.saddr.s6_addr32[1], 0,
27c11b6b 2755 src_ipv4_src_ipv6.ipv6_layout.ipv6[4]),
88f30bbc 2756 OFFLOAD(SIPV6_63_32, 32, U32_MAX, ip6.saddr.s6_addr32[2], 0,
27c11b6b 2757 src_ipv4_src_ipv6.ipv6_layout.ipv6[8]),
88f30bbc 2758 OFFLOAD(SIPV6_31_0, 32, U32_MAX, ip6.saddr.s6_addr32[3], 0,
27c11b6b 2759 src_ipv4_src_ipv6.ipv6_layout.ipv6[12]),
88f30bbc 2760 OFFLOAD(DIPV6_127_96, 32, U32_MAX, ip6.daddr.s6_addr32[0], 0,
27c11b6b 2761 dst_ipv4_dst_ipv6.ipv6_layout.ipv6[0]),
88f30bbc 2762 OFFLOAD(DIPV6_95_64, 32, U32_MAX, ip6.daddr.s6_addr32[1], 0,
27c11b6b 2763 dst_ipv4_dst_ipv6.ipv6_layout.ipv6[4]),
88f30bbc 2764 OFFLOAD(DIPV6_63_32, 32, U32_MAX, ip6.daddr.s6_addr32[2], 0,
27c11b6b 2765 dst_ipv4_dst_ipv6.ipv6_layout.ipv6[8]),
88f30bbc 2766 OFFLOAD(DIPV6_31_0, 32, U32_MAX, ip6.daddr.s6_addr32[3], 0,
27c11b6b 2767 dst_ipv4_dst_ipv6.ipv6_layout.ipv6[12]),
88f30bbc 2768 OFFLOAD(IPV6_HOPLIMIT, 8, U8_MAX, ip6.hop_limit, 0, ttl_hoplimit),
748cde9a 2769 OFFLOAD(IP_DSCP, 16, 0xc00f, ip6, 0, ip_dscp),
27c11b6b 2770
88f30bbc
DL
2771 OFFLOAD(TCP_SPORT, 16, U16_MAX, tcp.source, 0, tcp_sport),
2772 OFFLOAD(TCP_DPORT, 16, U16_MAX, tcp.dest, 0, tcp_dport),
2773 /* in linux iphdr tcp_flags is 8 bits long */
2774 OFFLOAD(TCP_FLAGS, 8, U8_MAX, tcp.ack_seq, 5, tcp_flags),
27c11b6b 2775
88f30bbc
DL
2776 OFFLOAD(UDP_SPORT, 16, U16_MAX, udp.source, 0, udp_sport),
2777 OFFLOAD(UDP_DPORT, 16, U16_MAX, udp.dest, 0, udp_dport),
d79b6df6
OG
2778};
2779
82198d8b
MD
2780static unsigned long mask_to_le(unsigned long mask, int size)
2781{
2782 __be32 mask_be32;
2783 __be16 mask_be16;
2784
2785 if (size == 32) {
2786 mask_be32 = (__force __be32)(mask);
2787 mask = (__force unsigned long)cpu_to_le32(be32_to_cpu(mask_be32));
2788 } else if (size == 16) {
2789 mask_be32 = (__force __be32)(mask);
2790 mask_be16 = *(__be16 *)&mask_be32;
2791 mask = (__force unsigned long)cpu_to_le16(be16_to_cpu(mask_be16));
2792 }
2793
2794 return mask;
2795}
6ae4a6a5
PB
2796static int offload_pedit_fields(struct mlx5e_priv *priv,
2797 int namespace,
2798 struct pedit_headers_action *hdrs,
e98bedf5 2799 struct mlx5e_tc_flow_parse_attr *parse_attr,
27c11b6b 2800 u32 *action_flags,
e98bedf5 2801 struct netlink_ext_ack *extack)
d79b6df6
OG
2802{
2803 struct pedit_headers *set_masks, *add_masks, *set_vals, *add_vals;
6ae4a6a5 2804 int i, action_size, first, last, next_z;
88f30bbc
DL
2805 void *headers_c, *headers_v, *action, *vals_p;
2806 u32 *s_masks_p, *a_masks_p, s_mask, a_mask;
6ae4a6a5 2807 struct mlx5e_tc_mod_hdr_acts *mod_acts;
d79b6df6 2808 struct mlx5_fields *f;
82198d8b 2809 unsigned long mask, field_mask;
6ae4a6a5 2810 int err;
88f30bbc
DL
2811 u8 cmd;
2812
6ae4a6a5 2813 mod_acts = &parse_attr->mod_hdr_acts;
88f30bbc
DL
2814 headers_c = get_match_headers_criteria(*action_flags, &parse_attr->spec);
2815 headers_v = get_match_headers_value(*action_flags, &parse_attr->spec);
d79b6df6 2816
73867881
PNA
2817 set_masks = &hdrs[0].masks;
2818 add_masks = &hdrs[1].masks;
2819 set_vals = &hdrs[0].vals;
2820 add_vals = &hdrs[1].vals;
d79b6df6 2821
d65dbedf 2822 action_size = MLX5_UN_SZ_BYTES(set_add_copy_action_in_auto);
d79b6df6
OG
2823
2824 for (i = 0; i < ARRAY_SIZE(fields); i++) {
27c11b6b
EB
2825 bool skip;
2826
d79b6df6
OG
2827 f = &fields[i];
2828 /* avoid seeing bits set from previous iterations */
e3ca4e05
OG
2829 s_mask = 0;
2830 a_mask = 0;
d79b6df6
OG
2831
2832 s_masks_p = (void *)set_masks + f->offset;
2833 a_masks_p = (void *)add_masks + f->offset;
2834
88f30bbc
DL
2835 s_mask = *s_masks_p & f->field_mask;
2836 a_mask = *a_masks_p & f->field_mask;
d79b6df6
OG
2837
2838 if (!s_mask && !a_mask) /* nothing to offload here */
2839 continue;
2840
2841 if (s_mask && a_mask) {
e98bedf5
EB
2842 NL_SET_ERR_MSG_MOD(extack,
2843 "can't set and add to the same HW field");
61b6a6c3
CH
2844 netdev_warn(priv->netdev,
2845 "mlx5: can't set and add to the same HW field (%x)\n",
2846 f->field);
d79b6df6
OG
2847 return -EOPNOTSUPP;
2848 }
2849
27c11b6b 2850 skip = false;
d79b6df6 2851 if (s_mask) {
27c11b6b
EB
2852 void *match_mask = headers_c + f->match_offset;
2853 void *match_val = headers_v + f->match_offset;
2854
d79b6df6
OG
2855 cmd = MLX5_ACTION_TYPE_SET;
2856 mask = s_mask;
2857 vals_p = (void *)set_vals + f->offset;
27c11b6b
EB
2858 /* don't rewrite if we have a match on the same value */
2859 if (cmp_val_mask(vals_p, s_masks_p, match_val,
88f30bbc 2860 match_mask, f->field_bsize))
27c11b6b 2861 skip = true;
d79b6df6 2862 /* clear to denote we consumed this field */
88f30bbc 2863 *s_masks_p &= ~f->field_mask;
d79b6df6
OG
2864 } else {
2865 cmd = MLX5_ACTION_TYPE_ADD;
2866 mask = a_mask;
2867 vals_p = (void *)add_vals + f->offset;
27c11b6b 2868 /* add 0 is no change */
88f30bbc 2869 if ((*(u32 *)vals_p & f->field_mask) == 0)
27c11b6b 2870 skip = true;
d79b6df6 2871 /* clear to denote we consumed this field */
88f30bbc 2872 *a_masks_p &= ~f->field_mask;
d79b6df6 2873 }
27c11b6b
EB
2874 if (skip)
2875 continue;
d79b6df6 2876
82198d8b 2877 mask = mask_to_le(mask, f->field_bsize);
2b64beba 2878
88f30bbc
DL
2879 first = find_first_bit(&mask, f->field_bsize);
2880 next_z = find_next_zero_bit(&mask, f->field_bsize, first);
2881 last = find_last_bit(&mask, f->field_bsize);
2b64beba 2882 if (first < next_z && next_z < last) {
e98bedf5
EB
2883 NL_SET_ERR_MSG_MOD(extack,
2884 "rewrite of few sub-fields isn't supported");
61b6a6c3
CH
2885 netdev_warn(priv->netdev,
2886 "mlx5: rewrite of few sub-fields (mask %lx) isn't offloaded\n",
2887 mask);
d79b6df6
OG
2888 return -EOPNOTSUPP;
2889 }
2890
6ae4a6a5
PB
2891 err = alloc_mod_hdr_actions(priv->mdev, namespace, mod_acts);
2892 if (err) {
2893 NL_SET_ERR_MSG_MOD(extack,
2894 "too many pedit actions, can't offload");
2895 mlx5_core_warn(priv->mdev,
2896 "mlx5: parsed %d pedit actions, can't do more\n",
2897 mod_acts->num_actions);
2898 return err;
2899 }
2900
2901 action = mod_acts->actions +
2902 (mod_acts->num_actions * action_size);
d79b6df6
OG
2903 MLX5_SET(set_action_in, action, action_type, cmd);
2904 MLX5_SET(set_action_in, action, field, f->field);
2905
2906 if (cmd == MLX5_ACTION_TYPE_SET) {
88f30bbc
DL
2907 int start;
2908
82198d8b
MD
2909 field_mask = mask_to_le(f->field_mask, f->field_bsize);
2910
88f30bbc 2911 /* if field is bit sized it can start not from first bit */
82198d8b 2912 start = find_first_bit(&field_mask, f->field_bsize);
88f30bbc
DL
2913
2914 MLX5_SET(set_action_in, action, offset, first - start);
d79b6df6 2915 /* length is num of bits to be written, zero means length of 32 */
2b64beba 2916 MLX5_SET(set_action_in, action, length, (last - first + 1));
d79b6df6
OG
2917 }
2918
88f30bbc 2919 if (f->field_bsize == 32)
2b64beba 2920 MLX5_SET(set_action_in, action, data, ntohl(*(__be32 *)vals_p) >> first);
88f30bbc 2921 else if (f->field_bsize == 16)
2b64beba 2922 MLX5_SET(set_action_in, action, data, ntohs(*(__be16 *)vals_p) >> first);
88f30bbc 2923 else if (f->field_bsize == 8)
2b64beba 2924 MLX5_SET(set_action_in, action, data, *(u8 *)vals_p >> first);
d79b6df6 2925
6ae4a6a5 2926 ++mod_acts->num_actions;
d79b6df6
OG
2927 }
2928
d79b6df6
OG
2929 return 0;
2930}
2931
2cc1cb1d
TZ
2932static int mlx5e_flow_namespace_max_modify_action(struct mlx5_core_dev *mdev,
2933 int namespace)
2934{
2935 if (namespace == MLX5_FLOW_NAMESPACE_FDB) /* FDB offloading */
2936 return MLX5_CAP_ESW_FLOWTABLE_FDB(mdev, max_modify_header_actions);
2937 else /* namespace is MLX5_FLOW_NAMESPACE_KERNEL - NIC offloading */
2938 return MLX5_CAP_FLOWTABLE_NIC_RX(mdev, max_modify_header_actions);
2939}
2940
6ae4a6a5
PB
2941int alloc_mod_hdr_actions(struct mlx5_core_dev *mdev,
2942 int namespace,
2943 struct mlx5e_tc_mod_hdr_acts *mod_hdr_acts)
d79b6df6 2944{
6ae4a6a5
PB
2945 int action_size, new_num_actions, max_hw_actions;
2946 size_t new_sz, old_sz;
2947 void *ret;
d79b6df6 2948
6ae4a6a5
PB
2949 if (mod_hdr_acts->num_actions < mod_hdr_acts->max_actions)
2950 return 0;
d79b6df6 2951
d65dbedf 2952 action_size = MLX5_UN_SZ_BYTES(set_add_copy_action_in_auto);
d79b6df6 2953
6ae4a6a5
PB
2954 max_hw_actions = mlx5e_flow_namespace_max_modify_action(mdev,
2955 namespace);
2956 new_num_actions = min(max_hw_actions,
2957 mod_hdr_acts->actions ?
2958 mod_hdr_acts->max_actions * 2 : 1);
2959 if (mod_hdr_acts->max_actions == new_num_actions)
2960 return -ENOSPC;
2961
2962 new_sz = action_size * new_num_actions;
2963 old_sz = mod_hdr_acts->max_actions * action_size;
2964 ret = krealloc(mod_hdr_acts->actions, new_sz, GFP_KERNEL);
2965 if (!ret)
d79b6df6
OG
2966 return -ENOMEM;
2967
6ae4a6a5
PB
2968 memset(ret + old_sz, 0, new_sz - old_sz);
2969 mod_hdr_acts->actions = ret;
2970 mod_hdr_acts->max_actions = new_num_actions;
2971
d79b6df6
OG
2972 return 0;
2973}
2974
6ae4a6a5
PB
2975void dealloc_mod_hdr_actions(struct mlx5e_tc_mod_hdr_acts *mod_hdr_acts)
2976{
2977 kfree(mod_hdr_acts->actions);
2978 mod_hdr_acts->actions = NULL;
2979 mod_hdr_acts->num_actions = 0;
2980 mod_hdr_acts->max_actions = 0;
2981}
2982
d79b6df6
OG
2983static const struct pedit_headers zero_masks = {};
2984
582234b4
EC
2985static int
2986parse_pedit_to_modify_hdr(struct mlx5e_priv *priv,
2987 const struct flow_action_entry *act, int namespace,
2988 struct mlx5e_tc_flow_parse_attr *parse_attr,
2989 struct pedit_headers_action *hdrs,
2990 struct netlink_ext_ack *extack)
d79b6df6 2991{
73867881
PNA
2992 u8 cmd = (act->id == FLOW_ACTION_MANGLE) ? 0 : 1;
2993 int err = -EOPNOTSUPP;
d79b6df6 2994 u32 mask, val, offset;
73867881 2995 u8 htype;
d79b6df6 2996
73867881
PNA
2997 htype = act->mangle.htype;
2998 err = -EOPNOTSUPP; /* can't be all optimistic */
d79b6df6 2999
73867881
PNA
3000 if (htype == FLOW_ACT_MANGLE_UNSPEC) {
3001 NL_SET_ERR_MSG_MOD(extack, "legacy pedit isn't offloaded");
3002 goto out_err;
3003 }
d79b6df6 3004
2cc1cb1d
TZ
3005 if (!mlx5e_flow_namespace_max_modify_action(priv->mdev, namespace)) {
3006 NL_SET_ERR_MSG_MOD(extack,
3007 "The pedit offload action is not supported");
3008 goto out_err;
3009 }
3010
73867881
PNA
3011 mask = act->mangle.mask;
3012 val = act->mangle.val;
3013 offset = act->mangle.offset;
d79b6df6 3014
73867881
PNA
3015 err = set_pedit_val(htype, ~mask, val, offset, &hdrs[cmd]);
3016 if (err)
3017 goto out_err;
c500c86b 3018
73867881 3019 hdrs[cmd].pedits++;
d79b6df6 3020
c500c86b
PNA
3021 return 0;
3022out_err:
3023 return err;
3024}
3025
582234b4
EC
3026static int
3027parse_pedit_to_reformat(struct mlx5e_priv *priv,
3028 const struct flow_action_entry *act,
3029 struct mlx5e_tc_flow_parse_attr *parse_attr,
3030 struct netlink_ext_ack *extack)
3031{
3032 u32 mask, val, offset;
3033 u32 *p;
3034
3035 if (act->id != FLOW_ACTION_MANGLE)
3036 return -EOPNOTSUPP;
3037
3038 if (act->mangle.htype != FLOW_ACT_MANGLE_HDR_TYPE_ETH) {
3039 NL_SET_ERR_MSG_MOD(extack, "Only Ethernet modification is supported");
3040 return -EOPNOTSUPP;
3041 }
3042
3043 mask = ~act->mangle.mask;
3044 val = act->mangle.val;
3045 offset = act->mangle.offset;
3046 p = (u32 *)&parse_attr->eth;
3047 *(p + (offset >> 2)) |= (val & mask);
3048
3049 return 0;
3050}
3051
3052static int parse_tc_pedit_action(struct mlx5e_priv *priv,
3053 const struct flow_action_entry *act, int namespace,
3054 struct mlx5e_tc_flow_parse_attr *parse_attr,
3055 struct pedit_headers_action *hdrs,
3056 struct mlx5e_tc_flow *flow,
3057 struct netlink_ext_ack *extack)
3058{
3059 if (flow && flow_flag_test(flow, L3_TO_L2_DECAP))
3060 return parse_pedit_to_reformat(priv, act, parse_attr, extack);
3061
3062 return parse_pedit_to_modify_hdr(priv, act, namespace,
3063 parse_attr, hdrs, extack);
3064}
3065
c500c86b
PNA
3066static int alloc_tc_pedit_action(struct mlx5e_priv *priv, int namespace,
3067 struct mlx5e_tc_flow_parse_attr *parse_attr,
3068 struct pedit_headers_action *hdrs,
27c11b6b 3069 u32 *action_flags,
c500c86b
PNA
3070 struct netlink_ext_ack *extack)
3071{
3072 struct pedit_headers *cmd_masks;
3073 int err;
3074 u8 cmd;
3075
6ae4a6a5
PB
3076 err = offload_pedit_fields(priv, namespace, hdrs, parse_attr,
3077 action_flags, extack);
d79b6df6
OG
3078 if (err < 0)
3079 goto out_dealloc_parsed_actions;
3080
3081 for (cmd = 0; cmd < __PEDIT_CMD_MAX; cmd++) {
c500c86b 3082 cmd_masks = &hdrs[cmd].masks;
d79b6df6 3083 if (memcmp(cmd_masks, &zero_masks, sizeof(zero_masks))) {
e98bedf5
EB
3084 NL_SET_ERR_MSG_MOD(extack,
3085 "attempt to offload an unsupported field");
b3a433de 3086 netdev_warn(priv->netdev, "attempt to offload an unsupported field (cmd %d)\n", cmd);
d79b6df6
OG
3087 print_hex_dump(KERN_WARNING, "mask: ", DUMP_PREFIX_ADDRESS,
3088 16, 1, cmd_masks, sizeof(zero_masks), true);
3089 err = -EOPNOTSUPP;
3090 goto out_dealloc_parsed_actions;
3091 }
3092 }
3093
3094 return 0;
3095
3096out_dealloc_parsed_actions:
6ae4a6a5 3097 dealloc_mod_hdr_actions(&parse_attr->mod_hdr_acts);
d79b6df6
OG
3098 return err;
3099}
3100
e98bedf5
EB
3101static bool csum_offload_supported(struct mlx5e_priv *priv,
3102 u32 action,
3103 u32 update_flags,
3104 struct netlink_ext_ack *extack)
26c02749
OG
3105{
3106 u32 prot_flags = TCA_CSUM_UPDATE_FLAG_IPV4HDR | TCA_CSUM_UPDATE_FLAG_TCP |
3107 TCA_CSUM_UPDATE_FLAG_UDP;
3108
3109 /* The HW recalcs checksums only if re-writing headers */
3110 if (!(action & MLX5_FLOW_CONTEXT_ACTION_MOD_HDR)) {
e98bedf5
EB
3111 NL_SET_ERR_MSG_MOD(extack,
3112 "TC csum action is only offloaded with pedit");
26c02749
OG
3113 netdev_warn(priv->netdev,
3114 "TC csum action is only offloaded with pedit\n");
3115 return false;
3116 }
3117
3118 if (update_flags & ~prot_flags) {
e98bedf5
EB
3119 NL_SET_ERR_MSG_MOD(extack,
3120 "can't offload TC csum action for some header/s");
26c02749
OG
3121 netdev_warn(priv->netdev,
3122 "can't offload TC csum action for some header/s - flags %#x\n",
3123 update_flags);
3124 return false;
3125 }
3126
3127 return true;
3128}
3129
8998576b
DL
3130struct ip_ttl_word {
3131 __u8 ttl;
3132 __u8 protocol;
3133 __sum16 check;
3134};
3135
3136struct ipv6_hoplimit_word {
3137 __be16 payload_len;
3138 __u8 nexthdr;
3139 __u8 hop_limit;
3140};
3141
4c3844d9
PB
3142static int is_action_keys_supported(const struct flow_action_entry *act,
3143 bool ct_flow, bool *modify_ip_header,
7e36feeb 3144 bool *modify_tuple,
4c3844d9 3145 struct netlink_ext_ack *extack)
8998576b
DL
3146{
3147 u32 mask, offset;
3148 u8 htype;
3149
3150 htype = act->mangle.htype;
3151 offset = act->mangle.offset;
3152 mask = ~act->mangle.mask;
3153 /* For IPv4 & IPv6 header check 4 byte word,
3154 * to determine that modified fields
3155 * are NOT ttl & hop_limit only.
3156 */
3157 if (htype == FLOW_ACT_MANGLE_HDR_TYPE_IP4) {
3158 struct ip_ttl_word *ttl_word =
3159 (struct ip_ttl_word *)&mask;
3160
3161 if (offset != offsetof(struct iphdr, ttl) ||
3162 ttl_word->protocol ||
3163 ttl_word->check) {
4c3844d9
PB
3164 *modify_ip_header = true;
3165 }
3166
7e36feeb
PB
3167 if (offset >= offsetof(struct iphdr, saddr))
3168 *modify_tuple = true;
3169
3170 if (ct_flow && *modify_tuple) {
4c3844d9
PB
3171 NL_SET_ERR_MSG_MOD(extack,
3172 "can't offload re-write of ipv4 address with action ct");
3173 return -EOPNOTSUPP;
8998576b
DL
3174 }
3175 } else if (htype == FLOW_ACT_MANGLE_HDR_TYPE_IP6) {
3176 struct ipv6_hoplimit_word *hoplimit_word =
3177 (struct ipv6_hoplimit_word *)&mask;
3178
3179 if (offset != offsetof(struct ipv6hdr, payload_len) ||
3180 hoplimit_word->payload_len ||
3181 hoplimit_word->nexthdr) {
4c3844d9
PB
3182 *modify_ip_header = true;
3183 }
3184
7e36feeb
PB
3185 if (ct_flow && offset >= offsetof(struct ipv6hdr, saddr))
3186 *modify_tuple = true;
3187
3188 if (ct_flow && *modify_tuple) {
4c3844d9
PB
3189 NL_SET_ERR_MSG_MOD(extack,
3190 "can't offload re-write of ipv6 address with action ct");
3191 return -EOPNOTSUPP;
8998576b 3192 }
7e36feeb
PB
3193 } else if (htype == FLOW_ACT_MANGLE_HDR_TYPE_TCP ||
3194 htype == FLOW_ACT_MANGLE_HDR_TYPE_UDP) {
3195 *modify_tuple = true;
3196 if (ct_flow) {
3197 NL_SET_ERR_MSG_MOD(extack,
3198 "can't offload re-write of transport header ports with action ct");
3199 return -EOPNOTSUPP;
3200 }
8998576b 3201 }
4c3844d9
PB
3202
3203 return 0;
8998576b
DL
3204}
3205
96b5b458
DC
3206static bool modify_tuple_supported(bool modify_tuple, bool ct_clear,
3207 bool ct_flow, struct netlink_ext_ack *extack,
3208 struct mlx5e_priv *priv,
3209 struct mlx5_flow_spec *spec)
3210{
3211 if (!modify_tuple || ct_clear)
3212 return true;
3213
3214 if (ct_flow) {
3215 NL_SET_ERR_MSG_MOD(extack,
3216 "can't offload tuple modification with non-clear ct()");
3217 netdev_info(priv->netdev,
3218 "can't offload tuple modification with non-clear ct()");
3219 return false;
3220 }
3221
3222 /* Add ct_state=-trk match so it will be offloaded for non ct flows
3223 * (or after clear action), as otherwise, since the tuple is changed,
3224 * we can't restore ct state
3225 */
3226 if (mlx5_tc_ct_add_no_trk_match(spec)) {
3227 NL_SET_ERR_MSG_MOD(extack,
3228 "can't offload tuple modification with ct matches and no ct(clear) action");
3229 netdev_info(priv->netdev,
3230 "can't offload tuple modification with ct matches and no ct(clear) action");
3231 return false;
3232 }
3233
3234 return true;
3235}
3236
3d486ec4
OS
3237static bool modify_header_match_supported(struct mlx5e_priv *priv,
3238 struct mlx5_flow_spec *spec,
73867881 3239 struct flow_action *flow_action,
4c3844d9 3240 u32 actions, bool ct_flow,
7e36feeb 3241 bool ct_clear,
e98bedf5 3242 struct netlink_ext_ack *extack)
bdd66ac0 3243{
73867881 3244 const struct flow_action_entry *act;
7e36feeb 3245 bool modify_ip_header, modify_tuple;
fca53304 3246 void *headers_c;
bdd66ac0
OG
3247 void *headers_v;
3248 u16 ethertype;
8998576b 3249 u8 ip_proto;
4c3844d9 3250 int i, err;
bdd66ac0 3251
fca53304 3252 headers_c = get_match_headers_criteria(actions, spec);
8377629e 3253 headers_v = get_match_headers_value(actions, spec);
bdd66ac0
OG
3254 ethertype = MLX5_GET(fte_match_set_lyr_2_4, headers_v, ethertype);
3255
3256 /* for non-IP we only re-write MACs, so we're okay */
fca53304
EB
3257 if (MLX5_GET(fte_match_set_lyr_2_4, headers_c, ip_version) == 0 &&
3258 ethertype != ETH_P_IP && ethertype != ETH_P_IPV6)
bdd66ac0
OG
3259 goto out_ok;
3260
3261 modify_ip_header = false;
7e36feeb 3262 modify_tuple = false;
73867881
PNA
3263 flow_action_for_each(i, act, flow_action) {
3264 if (act->id != FLOW_ACTION_MANGLE &&
3265 act->id != FLOW_ACTION_ADD)
bdd66ac0
OG
3266 continue;
3267
4c3844d9 3268 err = is_action_keys_supported(act, ct_flow,
7e36feeb
PB
3269 &modify_ip_header,
3270 &modify_tuple, extack);
4c3844d9
PB
3271 if (err)
3272 return err;
bdd66ac0
OG
3273 }
3274
96b5b458
DC
3275 if (!modify_tuple_supported(modify_tuple, ct_clear, ct_flow, extack,
3276 priv, spec))
7e36feeb 3277 return false;
7e36feeb 3278
bdd66ac0 3279 ip_proto = MLX5_GET(fte_match_set_lyr_2_4, headers_v, ip_protocol);
1ccef350
JL
3280 if (modify_ip_header && ip_proto != IPPROTO_TCP &&
3281 ip_proto != IPPROTO_UDP && ip_proto != IPPROTO_ICMP) {
e98bedf5
EB
3282 NL_SET_ERR_MSG_MOD(extack,
3283 "can't offload re-write of non TCP/UDP");
3d486ec4
OS
3284 netdev_info(priv->netdev, "can't offload re-write of ip proto %d\n",
3285 ip_proto);
bdd66ac0
OG
3286 return false;
3287 }
3288
3289out_ok:
3290 return true;
3291}
3292
3293static bool actions_match_supported(struct mlx5e_priv *priv,
73867881 3294 struct flow_action *flow_action,
bdd66ac0 3295 struct mlx5e_tc_flow_parse_attr *parse_attr,
e98bedf5
EB
3296 struct mlx5e_tc_flow *flow,
3297 struct netlink_ext_ack *extack)
bdd66ac0 3298{
a7c119bd 3299 bool ct_flow = false, ct_clear = false;
bdd66ac0
OG
3300 u32 actions;
3301
c620b772
AL
3302 ct_clear = flow->attr->ct_attr.ct_action &
3303 TCA_CT_ACT_CLEAR;
3304 ct_flow = flow_flag_test(flow, CT) && !ct_clear;
3305 actions = flow->attr->action;
3306
4c3844d9 3307 if (mlx5e_is_eswitch_flow(flow)) {
69e2916e
PB
3308 if (flow->attr->esw_attr->split_count && ct_flow &&
3309 !MLX5_CAP_GEN(flow->attr->esw_attr->in_mdev, reg_c_preserve)) {
4c3844d9
PB
3310 /* All registers used by ct are cleared when using
3311 * split rules.
3312 */
3313 NL_SET_ERR_MSG_MOD(extack,
3314 "Can't offload mirroring with action ct");
49397b80 3315 return false;
4c3844d9 3316 }
4c3844d9 3317 }
bdd66ac0
OG
3318
3319 if (actions & MLX5_FLOW_CONTEXT_ACTION_MOD_HDR)
3d486ec4 3320 return modify_header_match_supported(priv, &parse_attr->spec,
a655fe9f 3321 flow_action, actions,
7e36feeb
PB
3322 ct_flow, ct_clear,
3323 extack);
bdd66ac0
OG
3324
3325 return true;
3326}
3327
32134847
MD
3328static bool same_port_devs(struct mlx5e_priv *priv, struct mlx5e_priv *peer_priv)
3329{
3330 return priv->mdev == peer_priv->mdev;
3331}
3332
5c65c564
OG
3333static bool same_hw_devs(struct mlx5e_priv *priv, struct mlx5e_priv *peer_priv)
3334{
3335 struct mlx5_core_dev *fmdev, *pmdev;
816f6706 3336 u64 fsystem_guid, psystem_guid;
5c65c564
OG
3337
3338 fmdev = priv->mdev;
3339 pmdev = peer_priv->mdev;
3340
59c9d35e
AH
3341 fsystem_guid = mlx5_query_nic_system_image_guid(fmdev);
3342 psystem_guid = mlx5_query_nic_system_image_guid(pmdev);
5c65c564 3343
816f6706 3344 return (fsystem_guid == psystem_guid);
5c65c564
OG
3345}
3346
bb569657
AL
3347static bool same_vf_reps(struct mlx5e_priv *priv,
3348 struct net_device *out_dev)
3349{
3350 return mlx5e_eswitch_vf_rep(priv->netdev) &&
3351 priv->netdev == out_dev;
3352}
3353
bdc837ee
EB
3354static int add_vlan_rewrite_action(struct mlx5e_priv *priv, int namespace,
3355 const struct flow_action_entry *act,
3356 struct mlx5e_tc_flow_parse_attr *parse_attr,
3357 struct pedit_headers_action *hdrs,
3358 u32 *action, struct netlink_ext_ack *extack)
3359{
3360 u16 mask16 = VLAN_VID_MASK;
3361 u16 val16 = act->vlan.vid & VLAN_VID_MASK;
3362 const struct flow_action_entry pedit_act = {
3363 .id = FLOW_ACTION_MANGLE,
3364 .mangle.htype = FLOW_ACT_MANGLE_HDR_TYPE_ETH,
3365 .mangle.offset = offsetof(struct vlan_ethhdr, h_vlan_TCI),
3366 .mangle.mask = ~(u32)be16_to_cpu(*(__be16 *)&mask16),
3367 .mangle.val = (u32)be16_to_cpu(*(__be16 *)&val16),
3368 };
6fca9d1e 3369 u8 match_prio_mask, match_prio_val;
bf2f3bca 3370 void *headers_c, *headers_v;
bdc837ee
EB
3371 int err;
3372
bf2f3bca
EB
3373 headers_c = get_match_headers_criteria(*action, &parse_attr->spec);
3374 headers_v = get_match_headers_value(*action, &parse_attr->spec);
3375
3376 if (!(MLX5_GET(fte_match_set_lyr_2_4, headers_c, cvlan_tag) &&
3377 MLX5_GET(fte_match_set_lyr_2_4, headers_v, cvlan_tag))) {
3378 NL_SET_ERR_MSG_MOD(extack,
3379 "VLAN rewrite action must have VLAN protocol match");
3380 return -EOPNOTSUPP;
3381 }
3382
6fca9d1e
EB
3383 match_prio_mask = MLX5_GET(fte_match_set_lyr_2_4, headers_c, first_prio);
3384 match_prio_val = MLX5_GET(fte_match_set_lyr_2_4, headers_v, first_prio);
3385 if (act->vlan.prio != (match_prio_val & match_prio_mask)) {
3386 NL_SET_ERR_MSG_MOD(extack,
3387 "Changing VLAN prio is not supported");
bdc837ee
EB
3388 return -EOPNOTSUPP;
3389 }
3390
582234b4 3391 err = parse_tc_pedit_action(priv, &pedit_act, namespace, parse_attr, hdrs, NULL, extack);
bdc837ee
EB
3392 *action |= MLX5_FLOW_CONTEXT_ACTION_MOD_HDR;
3393
3394 return err;
3395}
3396
0bac1194
EB
3397static int
3398add_vlan_prio_tag_rewrite_action(struct mlx5e_priv *priv,
3399 struct mlx5e_tc_flow_parse_attr *parse_attr,
3400 struct pedit_headers_action *hdrs,
3401 u32 *action, struct netlink_ext_ack *extack)
3402{
3403 const struct flow_action_entry prio_tag_act = {
3404 .vlan.vid = 0,
3405 .vlan.prio =
3406 MLX5_GET(fte_match_set_lyr_2_4,
3407 get_match_headers_value(*action,
3408 &parse_attr->spec),
3409 first_prio) &
3410 MLX5_GET(fte_match_set_lyr_2_4,
3411 get_match_headers_criteria(*action,
3412 &parse_attr->spec),
3413 first_prio),
3414 };
3415
3416 return add_vlan_rewrite_action(priv, MLX5_FLOW_NAMESPACE_FDB,
3417 &prio_tag_act, parse_attr, hdrs, action,
3418 extack);
3419}
3420
c7569097
AL
3421static int validate_goto_chain(struct mlx5e_priv *priv,
3422 struct mlx5e_tc_flow *flow,
3423 const struct flow_action_entry *act,
3424 u32 actions,
3425 struct netlink_ext_ack *extack)
3426{
3427 bool is_esw = mlx5e_is_eswitch_flow(flow);
3428 struct mlx5_flow_attr *attr = flow->attr;
3429 bool ft_flow = mlx5e_is_ft_flow(flow);
3430 u32 dest_chain = act->chain_index;
3431 struct mlx5_fs_chains *chains;
3432 struct mlx5_eswitch *esw;
3433 u32 reformat_and_fwd;
3434 u32 max_chain;
3435
3436 esw = priv->mdev->priv.eswitch;
3437 chains = is_esw ? esw_chains(esw) : nic_chains(priv);
3438 max_chain = mlx5_chains_get_chain_range(chains);
3439 reformat_and_fwd = is_esw ?
3440 MLX5_CAP_ESW_FLOWTABLE_FDB(priv->mdev, reformat_and_fwd_to_table) :
3441 MLX5_CAP_FLOWTABLE_NIC_RX(priv->mdev, reformat_and_fwd_to_table);
3442
3443 if (ft_flow) {
3444 NL_SET_ERR_MSG_MOD(extack, "Goto action is not supported");
3445 return -EOPNOTSUPP;
3446 }
3447
3448 if (!mlx5_chains_backwards_supported(chains) &&
3449 dest_chain <= attr->chain) {
3450 NL_SET_ERR_MSG_MOD(extack,
3451 "Goto lower numbered chain isn't supported");
3452 return -EOPNOTSUPP;
3453 }
3454
3455 if (dest_chain > max_chain) {
3456 NL_SET_ERR_MSG_MOD(extack,
3457 "Requested destination chain is out of supported range");
3458 return -EOPNOTSUPP;
3459 }
3460
3461 if (actions & (MLX5_FLOW_CONTEXT_ACTION_PACKET_REFORMAT |
3462 MLX5_FLOW_CONTEXT_ACTION_DECAP) &&
3463 !reformat_and_fwd) {
3464 NL_SET_ERR_MSG_MOD(extack,
3465 "Goto chain is not allowed if action has reformat or decap");
3466 return -EOPNOTSUPP;
3467 }
3468
3469 return 0;
3470}
3471
73867881
PNA
3472static int parse_tc_nic_actions(struct mlx5e_priv *priv,
3473 struct flow_action *flow_action,
e98bedf5
EB
3474 struct mlx5e_tc_flow *flow,
3475 struct netlink_ext_ack *extack)
e3a2b7ed 3476{
c6cfe113 3477 struct mlx5e_tc_flow_parse_attr *parse_attr;
c620b772 3478 struct mlx5_flow_attr *attr = flow->attr;
73867881
PNA
3479 struct pedit_headers_action hdrs[2] = {};
3480 const struct flow_action_entry *act;
c620b772 3481 struct mlx5_nic_flow_attr *nic_attr;
1cab1cd7 3482 u32 action = 0;
244cd96a 3483 int err, i;
e3a2b7ed 3484
73867881 3485 if (!flow_action_has_entries(flow_action))
e3a2b7ed
AV
3486 return -EINVAL;
3487
53eca1f3
JK
3488 if (!flow_action_hw_stats_check(flow_action, extack,
3489 FLOW_ACTION_HW_STATS_DELAYED_BIT))
319a1d19
JP
3490 return -EOPNOTSUPP;
3491
c620b772 3492 nic_attr = attr->nic_attr;
c620b772 3493 nic_attr->flow_tag = MLX5_FS_DEFAULT_FLOW_TAG;
c6cfe113 3494 parse_attr = attr->parse_attr;
e3a2b7ed 3495
73867881
PNA
3496 flow_action_for_each(i, act, flow_action) {
3497 switch (act->id) {
15fc92ec
TZ
3498 case FLOW_ACTION_ACCEPT:
3499 action |= MLX5_FLOW_CONTEXT_ACTION_FWD_DEST |
3500 MLX5_FLOW_CONTEXT_ACTION_COUNT;
3501 break;
73867881 3502 case FLOW_ACTION_DROP:
950b4df9
RD
3503 action |= MLX5_FLOW_CONTEXT_ACTION_DROP |
3504 MLX5_FLOW_CONTEXT_ACTION_COUNT;
73867881
PNA
3505 break;
3506 case FLOW_ACTION_MANGLE:
3507 case FLOW_ACTION_ADD:
3508 err = parse_tc_pedit_action(priv, act, MLX5_FLOW_NAMESPACE_KERNEL,
582234b4 3509 parse_attr, hdrs, NULL, extack);
2f4fe4ca
OG
3510 if (err)
3511 return err;
3512
c7569097 3513 action |= MLX5_FLOW_CONTEXT_ACTION_MOD_HDR;
73867881 3514 break;
bdc837ee
EB
3515 case FLOW_ACTION_VLAN_MANGLE:
3516 err = add_vlan_rewrite_action(priv,
3517 MLX5_FLOW_NAMESPACE_KERNEL,
3518 act, parse_attr, hdrs,
3519 &action, extack);
3520 if (err)
3521 return err;
3522
3523 break;
73867881 3524 case FLOW_ACTION_CSUM:
1cab1cd7 3525 if (csum_offload_supported(priv, action,
73867881 3526 act->csum_flags,
e98bedf5 3527 extack))
73867881 3528 break;
26c02749
OG
3529
3530 return -EOPNOTSUPP;
73867881
PNA
3531 case FLOW_ACTION_REDIRECT: {
3532 struct net_device *peer_dev = act->dev;
5c65c564
OG
3533
3534 if (priv->netdev->netdev_ops == peer_dev->netdev_ops &&
3535 same_hw_devs(priv, netdev_priv(peer_dev))) {
98b66cb1 3536 parse_attr->mirred_ifindex[0] = peer_dev->ifindex;
226f2ca3 3537 flow_flag_set(flow, HAIRPIN);
1cab1cd7
OG
3538 action |= MLX5_FLOW_CONTEXT_ACTION_FWD_DEST |
3539 MLX5_FLOW_CONTEXT_ACTION_COUNT;
5c65c564 3540 } else {
e98bedf5
EB
3541 NL_SET_ERR_MSG_MOD(extack,
3542 "device is not on same HW, can't offload");
5c65c564
OG
3543 netdev_warn(priv->netdev, "device %s not on same HW, can't offload\n",
3544 peer_dev->name);
25f150f4 3545 return -EOPNOTSUPP;
5c65c564 3546 }
73867881
PNA
3547 }
3548 break;
3549 case FLOW_ACTION_MARK: {
3550 u32 mark = act->mark;
e3a2b7ed
AV
3551
3552 if (mark & ~MLX5E_TC_FLOW_ID_MASK) {
e98bedf5
EB
3553 NL_SET_ERR_MSG_MOD(extack,
3554 "Bad flow mark - only 16 bit is supported");
25f150f4 3555 return -EOPNOTSUPP;
e3a2b7ed
AV
3556 }
3557
c620b772 3558 nic_attr->flow_tag = mark;
1cab1cd7 3559 action |= MLX5_FLOW_CONTEXT_ACTION_FWD_DEST;
73867881
PNA
3560 }
3561 break;
c7569097
AL
3562 case FLOW_ACTION_GOTO:
3563 err = validate_goto_chain(priv, flow, act, action,
3564 extack);
3565 if (err)
3566 return err;
3567
3568 action |= MLX5_FLOW_CONTEXT_ACTION_COUNT;
3569 attr->dest_chain = act->chain_index;
3570 break;
aedd133d 3571 case FLOW_ACTION_CT:
3cfe4267
RD
3572 err = mlx5_tc_ct_parse_action(get_ct_priv(priv), attr,
3573 &parse_attr->mod_hdr_acts,
3574 act, extack);
aedd133d
AL
3575 if (err)
3576 return err;
3577
3578 flow_flag_set(flow, CT);
3579 break;
73867881 3580 default:
2cc1cb1d
TZ
3581 NL_SET_ERR_MSG_MOD(extack, "The offload action is not supported");
3582 return -EOPNOTSUPP;
e3a2b7ed 3583 }
e3a2b7ed
AV
3584 }
3585
c500c86b
PNA
3586 if (hdrs[TCA_PEDIT_KEY_EX_CMD_SET].pedits ||
3587 hdrs[TCA_PEDIT_KEY_EX_CMD_ADD].pedits) {
3588 err = alloc_tc_pedit_action(priv, MLX5_FLOW_NAMESPACE_KERNEL,
27c11b6b 3589 parse_attr, hdrs, &action, extack);
c500c86b
PNA
3590 if (err)
3591 return err;
27c11b6b
EB
3592 /* in case all pedit actions are skipped, remove the MOD_HDR
3593 * flag.
3594 */
6ae4a6a5 3595 if (parse_attr->mod_hdr_acts.num_actions == 0) {
27c11b6b 3596 action &= ~MLX5_FLOW_CONTEXT_ACTION_MOD_HDR;
6ae4a6a5 3597 dealloc_mod_hdr_actions(&parse_attr->mod_hdr_acts);
e7739a60 3598 }
c500c86b
PNA
3599 }
3600
1cab1cd7 3601 attr->action = action;
c7569097
AL
3602
3603 if (attr->dest_chain) {
3604 if (attr->action & MLX5_FLOW_CONTEXT_ACTION_FWD_DEST) {
3605 NL_SET_ERR_MSG(extack, "Mirroring goto chain rules isn't supported");
3606 return -EOPNOTSUPP;
3607 }
3608 attr->action |= MLX5_FLOW_CONTEXT_ACTION_FWD_DEST;
3609 }
3610
3611 if (attr->action & MLX5_FLOW_CONTEXT_ACTION_MOD_HDR)
3612 attr->action |= MLX5_FLOW_CONTEXT_ACTION_FWD_DEST;
3613
73867881 3614 if (!actions_match_supported(priv, flow_action, parse_attr, flow, extack))
bdd66ac0
OG
3615 return -EOPNOTSUPP;
3616
e3a2b7ed
AV
3617 return 0;
3618}
3619
32134847 3620static bool is_merged_eswitch_vfs(struct mlx5e_priv *priv,
b1d90e6b
RL
3621 struct net_device *peer_netdev)
3622{
3623 struct mlx5e_priv *peer_priv;
3624
3625 peer_priv = netdev_priv(peer_netdev);
3626
3627 return (MLX5_CAP_ESW(priv->mdev, merged_eswitch) &&
32134847
MD
3628 mlx5e_eswitch_vf_rep(priv->netdev) &&
3629 mlx5e_eswitch_vf_rep(peer_netdev) &&
68931c7d 3630 same_hw_devs(priv, peer_priv));
b1d90e6b
RL
3631}
3632
1482bd3d 3633static int parse_tc_vlan_action(struct mlx5e_priv *priv,
73867881 3634 const struct flow_action_entry *act,
1482bd3d
JL
3635 struct mlx5_esw_flow_attr *attr,
3636 u32 *action)
3637{
cc495188
JL
3638 u8 vlan_idx = attr->total_vlan;
3639
3640 if (vlan_idx >= MLX5_FS_VLAN_DEPTH)
3641 return -EOPNOTSUPP;
3642
73867881
PNA
3643 switch (act->id) {
3644 case FLOW_ACTION_VLAN_POP:
cc495188
JL
3645 if (vlan_idx) {
3646 if (!mlx5_eswitch_vlan_actions_supported(priv->mdev,
3647 MLX5_FS_VLAN_DEPTH))
3648 return -EOPNOTSUPP;
3649
3650 *action |= MLX5_FLOW_CONTEXT_ACTION_VLAN_POP_2;
3651 } else {
3652 *action |= MLX5_FLOW_CONTEXT_ACTION_VLAN_POP;
3653 }
73867881
PNA
3654 break;
3655 case FLOW_ACTION_VLAN_PUSH:
3656 attr->vlan_vid[vlan_idx] = act->vlan.vid;
3657 attr->vlan_prio[vlan_idx] = act->vlan.prio;
3658 attr->vlan_proto[vlan_idx] = act->vlan.proto;
cc495188
JL
3659 if (!attr->vlan_proto[vlan_idx])
3660 attr->vlan_proto[vlan_idx] = htons(ETH_P_8021Q);
3661
3662 if (vlan_idx) {
3663 if (!mlx5_eswitch_vlan_actions_supported(priv->mdev,
3664 MLX5_FS_VLAN_DEPTH))
3665 return -EOPNOTSUPP;
3666
3667 *action |= MLX5_FLOW_CONTEXT_ACTION_VLAN_PUSH_2;
3668 } else {
3669 if (!mlx5_eswitch_vlan_actions_supported(priv->mdev, 1) &&
73867881
PNA
3670 (act->vlan.proto != htons(ETH_P_8021Q) ||
3671 act->vlan.prio))
cc495188
JL
3672 return -EOPNOTSUPP;
3673
3674 *action |= MLX5_FLOW_CONTEXT_ACTION_VLAN_PUSH;
1482bd3d 3675 }
73867881
PNA
3676 break;
3677 default:
bdc837ee 3678 return -EINVAL;
1482bd3d
JL
3679 }
3680
cc495188
JL
3681 attr->total_vlan = vlan_idx + 1;
3682
1482bd3d
JL
3683 return 0;
3684}
3685
d34eb2fc
OG
3686static struct net_device *get_fdb_out_dev(struct net_device *uplink_dev,
3687 struct net_device *out_dev)
3688{
3689 struct net_device *fdb_out_dev = out_dev;
3690 struct net_device *uplink_upper;
3691
3692 rcu_read_lock();
3693 uplink_upper = netdev_master_upper_dev_get_rcu(uplink_dev);
3694 if (uplink_upper && netif_is_lag_master(uplink_upper) &&
3695 uplink_upper == out_dev) {
3696 fdb_out_dev = uplink_dev;
3697 } else if (netif_is_lag_master(out_dev)) {
3698 fdb_out_dev = bond_option_active_slave_get_rcu(netdev_priv(out_dev));
3699 if (fdb_out_dev &&
3700 (!mlx5e_eswitch_rep(fdb_out_dev) ||
3701 !netdev_port_same_parent_id(fdb_out_dev, uplink_dev)))
3702 fdb_out_dev = NULL;
3703 }
3704 rcu_read_unlock();
3705 return fdb_out_dev;
3706}
3707
278748a9 3708static int add_vlan_push_action(struct mlx5e_priv *priv,
c620b772 3709 struct mlx5_flow_attr *attr,
278748a9
EB
3710 struct net_device **out_dev,
3711 u32 *action)
3712{
3713 struct net_device *vlan_dev = *out_dev;
3714 struct flow_action_entry vlan_act = {
3715 .id = FLOW_ACTION_VLAN_PUSH,
3716 .vlan.vid = vlan_dev_vlan_id(vlan_dev),
3717 .vlan.proto = vlan_dev_vlan_proto(vlan_dev),
3718 .vlan.prio = 0,
3719 };
3720 int err;
3721
c620b772 3722 err = parse_tc_vlan_action(priv, &vlan_act, attr->esw_attr, action);
278748a9
EB
3723 if (err)
3724 return err;
3725
dca59f4a
DC
3726 rcu_read_lock();
3727 *out_dev = dev_get_by_index_rcu(dev_net(vlan_dev), dev_get_iflink(vlan_dev));
3728 rcu_read_unlock();
3729 if (!*out_dev)
3730 return -ENODEV;
3731
278748a9
EB
3732 if (is_vlan_dev(*out_dev))
3733 err = add_vlan_push_action(priv, attr, out_dev, action);
3734
3735 return err;
3736}
3737
35a605db 3738static int add_vlan_pop_action(struct mlx5e_priv *priv,
c620b772 3739 struct mlx5_flow_attr *attr,
35a605db
EB
3740 u32 *action)
3741{
35a605db
EB
3742 struct flow_action_entry vlan_act = {
3743 .id = FLOW_ACTION_VLAN_POP,
3744 };
70f478ca 3745 int nest_level, err = 0;
35a605db 3746
70f478ca
DL
3747 nest_level = attr->parse_attr->filter_dev->lower_level -
3748 priv->netdev->lower_level;
35a605db 3749 while (nest_level--) {
c620b772 3750 err = parse_tc_vlan_action(priv, &vlan_act, attr->esw_attr, action);
35a605db
EB
3751 if (err)
3752 return err;
3753 }
3754
3755 return err;
3756}
3757
32134847
MD
3758static bool same_hw_reps(struct mlx5e_priv *priv,
3759 struct net_device *peer_netdev)
3760{
3761 struct mlx5e_priv *peer_priv;
3762
3763 peer_priv = netdev_priv(peer_netdev);
3764
3765 return mlx5e_eswitch_rep(priv->netdev) &&
3766 mlx5e_eswitch_rep(peer_netdev) &&
3767 same_hw_devs(priv, peer_priv);
3768}
3769
3770static bool is_lag_dev(struct mlx5e_priv *priv,
3771 struct net_device *peer_netdev)
3772{
3773 return ((mlx5_lag_is_sriov(priv->mdev) ||
3774 mlx5_lag_is_multipath(priv->mdev)) &&
3775 same_hw_reps(priv, peer_netdev));
3776}
3777
f6dc1264
PB
3778bool mlx5e_is_valid_eswitch_fwd_dev(struct mlx5e_priv *priv,
3779 struct net_device *out_dev)
3780{
32134847
MD
3781 if (is_merged_eswitch_vfs(priv, out_dev))
3782 return true;
3783
3784 if (is_lag_dev(priv, out_dev))
f6dc1264
PB
3785 return true;
3786
3787 return mlx5e_eswitch_rep(out_dev) &&
32134847 3788 same_port_devs(priv, netdev_priv(out_dev));
f6dc1264
PB
3789}
3790
554fe75c
DL
3791static bool is_duplicated_output_device(struct net_device *dev,
3792 struct net_device *out_dev,
3793 int *ifindexes, int if_count,
3794 struct netlink_ext_ack *extack)
3795{
3796 int i;
3797
3798 for (i = 0; i < if_count; i++) {
3799 if (ifindexes[i] == out_dev->ifindex) {
3800 NL_SET_ERR_MSG_MOD(extack,
3801 "can't duplicate output to same device");
3802 netdev_err(dev, "can't duplicate output to same device: %s\n",
3803 out_dev->name);
3804 return true;
3805 }
3806 }
3807
3808 return false;
3809}
3810
613f53fe
EC
3811static int verify_uplink_forwarding(struct mlx5e_priv *priv,
3812 struct mlx5e_tc_flow *flow,
3813 struct net_device *out_dev,
3814 struct netlink_ext_ack *extack)
3815{
c620b772 3816 struct mlx5_esw_flow_attr *attr = flow->attr->esw_attr;
613f53fe 3817 struct mlx5_eswitch *esw = priv->mdev->priv.eswitch;
613f53fe
EC
3818 struct mlx5e_rep_priv *rep_priv;
3819
3820 /* Forwarding non encapsulated traffic between
3821 * uplink ports is allowed only if
3822 * termination_table_raw_traffic cap is set.
3823 *
c620b772 3824 * Input vport was stored attr->in_rep.
613f53fe
EC
3825 * In LAG case, *priv* is the private data of
3826 * uplink which may be not the input vport.
3827 */
3828 rep_priv = mlx5e_rep_to_rep_priv(attr->in_rep);
3829
3830 if (!(mlx5e_eswitch_uplink_rep(rep_priv->netdev) &&
3831 mlx5e_eswitch_uplink_rep(out_dev)))
3832 return 0;
3833
3834 if (!MLX5_CAP_ESW_FLOWTABLE_FDB(esw->dev,
3835 termination_table_raw_traffic)) {
3836 NL_SET_ERR_MSG_MOD(extack,
3837 "devices are both uplink, can't offload forwarding");
3838 pr_err("devices %s %s are both uplink, can't offload forwarding\n",
3839 priv->netdev->name, out_dev->name);
3840 return -EOPNOTSUPP;
3841 } else if (out_dev != rep_priv->netdev) {
3842 NL_SET_ERR_MSG_MOD(extack,
3843 "devices are not the same uplink, can't offload forwarding");
3844 pr_err("devices %s %s are both uplink but not the same, can't offload forwarding\n",
3845 priv->netdev->name, out_dev->name);
3846 return -EOPNOTSUPP;
3847 }
3848 return 0;
3849}
3850
73867881
PNA
3851static int parse_tc_fdb_actions(struct mlx5e_priv *priv,
3852 struct flow_action *flow_action,
e98bedf5 3853 struct mlx5e_tc_flow *flow,
70f8019e 3854 struct netlink_ext_ack *extack)
03a9d11e 3855{
73867881 3856 struct pedit_headers_action hdrs[2] = {};
bf07aa73 3857 struct mlx5_eswitch *esw = priv->mdev->priv.eswitch;
c620b772 3858 struct mlx5e_tc_flow_parse_attr *parse_attr;
1d447a39 3859 struct mlx5e_rep_priv *rpriv = priv->ppriv;
bcd6740c 3860 struct mlx5e_sample_attr sample_attr = {};
73867881 3861 const struct ip_tunnel_info *info = NULL;
c620b772 3862 struct mlx5_flow_attr *attr = flow->attr;
554fe75c 3863 int ifindexes[MLX5_MAX_FLOW_FWD_VPORTS];
84179981 3864 bool ft_flow = mlx5e_is_ft_flow(flow);
73867881 3865 const struct flow_action_entry *act;
c620b772 3866 struct mlx5_esw_flow_attr *esw_attr;
0a7fcb78
PB
3867 bool encap = false, decap = false;
3868 u32 action = attr->action;
554fe75c 3869 int err, i, if_count = 0;
f828ca6a 3870 bool mpls_push = false;
03a9d11e 3871
73867881 3872 if (!flow_action_has_entries(flow_action))
03a9d11e
OG
3873 return -EINVAL;
3874
53eca1f3
JK
3875 if (!flow_action_hw_stats_check(flow_action, extack,
3876 FLOW_ACTION_HW_STATS_DELAYED_BIT))
319a1d19
JP
3877 return -EOPNOTSUPP;
3878
c620b772
AL
3879 esw_attr = attr->esw_attr;
3880 parse_attr = attr->parse_attr;
3881
73867881
PNA
3882 flow_action_for_each(i, act, flow_action) {
3883 switch (act->id) {
d557fbbd
VB
3884 case FLOW_ACTION_ACCEPT:
3885 action |= MLX5_FLOW_CONTEXT_ACTION_FWD_DEST |
3886 MLX5_FLOW_CONTEXT_ACTION_COUNT;
3887 attr->flags |= MLX5_ESW_ATTR_FLAG_ACCEPT;
3888 break;
73867881 3889 case FLOW_ACTION_DROP:
1cab1cd7
OG
3890 action |= MLX5_FLOW_CONTEXT_ACTION_DROP |
3891 MLX5_FLOW_CONTEXT_ACTION_COUNT;
73867881 3892 break;
f0288210
EC
3893 case FLOW_ACTION_TRAP:
3894 if (!flow_offload_has_one_action(flow_action)) {
3895 NL_SET_ERR_MSG_MOD(extack,
3896 "action trap is supported as a sole action only");
3897 return -EOPNOTSUPP;
3898 }
3899 action |= (MLX5_FLOW_CONTEXT_ACTION_FWD_DEST |
3900 MLX5_FLOW_CONTEXT_ACTION_COUNT);
3901 attr->flags |= MLX5_ESW_ATTR_FLAG_SLOW_PATH;
3902 break;
f828ca6a
EC
3903 case FLOW_ACTION_MPLS_PUSH:
3904 if (!MLX5_CAP_ESW_FLOWTABLE_FDB(priv->mdev,
3905 reformat_l2_to_l3_tunnel) ||
3906 act->mpls_push.proto != htons(ETH_P_MPLS_UC)) {
3907 NL_SET_ERR_MSG_MOD(extack,
3908 "mpls push is supported only for mpls_uc protocol");
3909 return -EOPNOTSUPP;
3910 }
3911 mpls_push = true;
3912 break;
14e6b038
EC
3913 case FLOW_ACTION_MPLS_POP:
3914 /* we only support mpls pop if it is the first action
3915 * and the filter net device is bareudp. Subsequent
3916 * actions can be pedit and the last can be mirred
3917 * egress redirect.
3918 */
3919 if (i) {
3920 NL_SET_ERR_MSG_MOD(extack,
3921 "mpls pop supported only as first action");
3922 return -EOPNOTSUPP;
3923 }
70f8019e 3924 if (!netif_is_bareudp(parse_attr->filter_dev)) {
14e6b038
EC
3925 NL_SET_ERR_MSG_MOD(extack,
3926 "mpls pop supported only on bareudp devices");
3927 return -EOPNOTSUPP;
3928 }
3929
3930 parse_attr->eth.h_proto = act->mpls_pop.proto;
3931 action |= MLX5_FLOW_CONTEXT_ACTION_PACKET_REFORMAT;
3932 flow_flag_set(flow, L3_TO_L2_DECAP);
3933 break;
73867881
PNA
3934 case FLOW_ACTION_MANGLE:
3935 case FLOW_ACTION_ADD:
3936 err = parse_tc_pedit_action(priv, act, MLX5_FLOW_NAMESPACE_FDB,
582234b4 3937 parse_attr, hdrs, flow, extack);
d7e75a32
OG
3938 if (err)
3939 return err;
3940
582234b4
EC
3941 if (!flow_flag_test(flow, L3_TO_L2_DECAP)) {
3942 action |= MLX5_FLOW_CONTEXT_ACTION_MOD_HDR;
c620b772 3943 esw_attr->split_count = esw_attr->out_count;
582234b4 3944 }
73867881
PNA
3945 break;
3946 case FLOW_ACTION_CSUM:
1cab1cd7 3947 if (csum_offload_supported(priv, action,
73867881
PNA
3948 act->csum_flags, extack))
3949 break;
26c02749
OG
3950
3951 return -EOPNOTSUPP;
73867881
PNA
3952 case FLOW_ACTION_REDIRECT:
3953 case FLOW_ACTION_MIRRED: {
03a9d11e 3954 struct mlx5e_priv *out_priv;
592d3651 3955 struct net_device *out_dev;
03a9d11e 3956
73867881 3957 out_dev = act->dev;
ef381359
OS
3958 if (!out_dev) {
3959 /* out_dev is NULL when filters with
3960 * non-existing mirred device are replayed to
3961 * the driver.
3962 */
3963 return -EINVAL;
3964 }
03a9d11e 3965
f828ca6a
EC
3966 if (mpls_push && !netif_is_bareudp(out_dev)) {
3967 NL_SET_ERR_MSG_MOD(extack,
3968 "mpls is supported only through a bareudp device");
3969 return -EOPNOTSUPP;
3970 }
3971
84179981
PB
3972 if (ft_flow && out_dev == priv->netdev) {
3973 /* Ignore forward to self rules generated
3974 * by adding both mlx5 devs to the flow table
3975 * block on a normal nft offload setup.
3976 */
3977 return -EOPNOTSUPP;
3978 }
3979
c620b772 3980 if (esw_attr->out_count >= MLX5_MAX_FLOW_FWD_VPORTS) {
e98bedf5
EB
3981 NL_SET_ERR_MSG_MOD(extack,
3982 "can't support more output ports, can't offload forwarding");
4ccd83f4
RD
3983 netdev_warn(priv->netdev,
3984 "can't support more than %d output ports, can't offload forwarding\n",
c620b772 3985 esw_attr->out_count);
592d3651
CM
3986 return -EOPNOTSUPP;
3987 }
3988
f493f155
EB
3989 action |= MLX5_FLOW_CONTEXT_ACTION_FWD_DEST |
3990 MLX5_FLOW_CONTEXT_ACTION_COUNT;
b6a4ac24 3991 if (encap) {
c620b772 3992 parse_attr->mirred_ifindex[esw_attr->out_count] =
b6a4ac24 3993 out_dev->ifindex;
0d9f9647
VB
3994 parse_attr->tun_info[esw_attr->out_count] =
3995 mlx5e_dup_tun_info(info);
c620b772 3996 if (!parse_attr->tun_info[esw_attr->out_count])
b6a4ac24
VB
3997 return -ENOMEM;
3998 encap = false;
c620b772 3999 esw_attr->dests[esw_attr->out_count].flags |=
b6a4ac24 4000 MLX5_ESW_DEST_ENCAP;
c620b772 4001 esw_attr->out_count++;
b6a4ac24
VB
4002 /* attr->dests[].rep is resolved when we
4003 * handle encap
4004 */
4005 } else if (netdev_port_same_parent_id(priv->netdev, out_dev)) {
7ba58ba7
RL
4006 struct mlx5_eswitch *esw = priv->mdev->priv.eswitch;
4007 struct net_device *uplink_dev = mlx5_eswitch_uplink_get_proto_dev(esw, REP_ETH);
7ba58ba7 4008
554fe75c
DL
4009 if (is_duplicated_output_device(priv->netdev,
4010 out_dev,
4011 ifindexes,
4012 if_count,
4013 extack))
4014 return -EOPNOTSUPP;
4015
4016 ifindexes[if_count] = out_dev->ifindex;
4017 if_count++;
4018
d34eb2fc
OG
4019 out_dev = get_fdb_out_dev(uplink_dev, out_dev);
4020 if (!out_dev)
4021 return -ENODEV;
7ba58ba7 4022
278748a9
EB
4023 if (is_vlan_dev(out_dev)) {
4024 err = add_vlan_push_action(priv, attr,
4025 &out_dev,
4026 &action);
4027 if (err)
4028 return err;
4029 }
f6dc1264 4030
35a605db
EB
4031 if (is_vlan_dev(parse_attr->filter_dev)) {
4032 err = add_vlan_pop_action(priv, attr,
4033 &action);
4034 if (err)
4035 return err;
4036 }
278748a9 4037
613f53fe
EC
4038 err = verify_uplink_forwarding(priv, flow, out_dev, extack);
4039 if (err)
4040 return err;
ffec9702 4041
f6dc1264
PB
4042 if (!mlx5e_is_valid_eswitch_fwd_dev(priv, out_dev)) {
4043 NL_SET_ERR_MSG_MOD(extack,
4044 "devices are not on same switch HW, can't offload forwarding");
a0646c88 4045 return -EOPNOTSUPP;
f6dc1264 4046 }
a0646c88 4047
bb569657
AL
4048 if (same_vf_reps(priv, out_dev)) {
4049 NL_SET_ERR_MSG_MOD(extack,
4050 "can't forward from a VF to itself");
4051 return -EOPNOTSUPP;
4052 }
4053
a54e20b4 4054 out_priv = netdev_priv(out_dev);
1d447a39 4055 rpriv = out_priv->ppriv;
c620b772
AL
4056 esw_attr->dests[esw_attr->out_count].rep = rpriv->rep;
4057 esw_attr->dests[esw_attr->out_count].mdev = out_priv->mdev;
4058 esw_attr->out_count++;
ef381359
OS
4059 } else if (parse_attr->filter_dev != priv->netdev) {
4060 /* All mlx5 devices are called to configure
4061 * high level device filters. Therefore, the
4062 * *attempt* to install a filter on invalid
4063 * eswitch should not trigger an explicit error
4064 */
4065 return -EINVAL;
a54e20b4 4066 } else {
e98bedf5
EB
4067 NL_SET_ERR_MSG_MOD(extack,
4068 "devices are not on same switch HW, can't offload forwarding");
4ccd83f4
RD
4069 netdev_warn(priv->netdev,
4070 "devices %s %s not on same switch HW, can't offload forwarding\n",
4071 priv->netdev->name,
4072 out_dev->name);
25f150f4 4073 return -EOPNOTSUPP;
03a9d11e 4074 }
73867881
PNA
4075 }
4076 break;
4077 case FLOW_ACTION_TUNNEL_ENCAP:
4078 info = act->tunnel;
a54e20b4
HHZ
4079 if (info)
4080 encap = true;
4081 else
4082 return -EOPNOTSUPP;
1482bd3d 4083
73867881
PNA
4084 break;
4085 case FLOW_ACTION_VLAN_PUSH:
4086 case FLOW_ACTION_VLAN_POP:
76b496b1
EB
4087 if (act->id == FLOW_ACTION_VLAN_PUSH &&
4088 (action & MLX5_FLOW_CONTEXT_ACTION_VLAN_POP)) {
4089 /* Replace vlan pop+push with vlan modify */
4090 action &= ~MLX5_FLOW_CONTEXT_ACTION_VLAN_POP;
4091 err = add_vlan_rewrite_action(priv,
4092 MLX5_FLOW_NAMESPACE_FDB,
4093 act, parse_attr, hdrs,
4094 &action, extack);
4095 } else {
c620b772 4096 err = parse_tc_vlan_action(priv, act, esw_attr, &action);
76b496b1 4097 }
1482bd3d
JL
4098 if (err)
4099 return err;
4100
c620b772 4101 esw_attr->split_count = esw_attr->out_count;
bdc837ee
EB
4102 break;
4103 case FLOW_ACTION_VLAN_MANGLE:
4104 err = add_vlan_rewrite_action(priv,
4105 MLX5_FLOW_NAMESPACE_FDB,
4106 act, parse_attr, hdrs,
4107 &action, extack);
4108 if (err)
4109 return err;
4110
c620b772 4111 esw_attr->split_count = esw_attr->out_count;
73867881
PNA
4112 break;
4113 case FLOW_ACTION_TUNNEL_DECAP:
0a7fcb78 4114 decap = true;
73867881 4115 break;
2fbbc30d 4116 case FLOW_ACTION_GOTO:
c7569097
AL
4117 err = validate_goto_chain(priv, flow, act, action,
4118 extack);
2fbbc30d
EC
4119 if (err)
4120 return err;
bf07aa73 4121
e88afe75 4122 action |= MLX5_FLOW_CONTEXT_ACTION_COUNT;
2fbbc30d 4123 attr->dest_chain = act->chain_index;
73867881 4124 break;
4c3844d9 4125 case FLOW_ACTION_CT:
41c2fd94
CM
4126 if (flow_flag_test(flow, SAMPLE)) {
4127 NL_SET_ERR_MSG_MOD(extack, "Sample action with connection tracking is not supported");
4128 return -EOPNOTSUPP;
4129 }
3cfe4267
RD
4130 err = mlx5_tc_ct_parse_action(get_ct_priv(priv), attr,
4131 &parse_attr->mod_hdr_acts,
4132 act, extack);
4c3844d9
PB
4133 if (err)
4134 return err;
4135
4136 flow_flag_set(flow, CT);
69e2916e 4137 esw_attr->split_count = esw_attr->out_count;
4c3844d9 4138 break;
41c2fd94
CM
4139 case FLOW_ACTION_SAMPLE:
4140 if (flow_flag_test(flow, CT)) {
4141 NL_SET_ERR_MSG_MOD(extack, "Sample action with connection tracking is not supported");
4142 return -EOPNOTSUPP;
4143 }
bcd6740c
CM
4144 sample_attr.rate = act->sample.rate;
4145 sample_attr.group_num = act->sample.psample_group->group_num;
41c2fd94 4146 if (act->sample.truncate)
bcd6740c 4147 sample_attr.trunc_size = act->sample.trunc_size;
41c2fd94
CM
4148 flow_flag_set(flow, SAMPLE);
4149 break;
73867881 4150 default:
2cc1cb1d
TZ
4151 NL_SET_ERR_MSG_MOD(extack, "The offload action is not supported");
4152 return -EOPNOTSUPP;
bf07aa73 4153 }
03a9d11e 4154 }
bdd66ac0 4155
a508728a
VB
4156 /* always set IP version for indirect table handling */
4157 attr->ip_version = mlx5e_tc_get_ip_version(&parse_attr->spec, true);
4158
0bac1194
EB
4159 if (MLX5_CAP_GEN(esw->dev, prio_tag_required) &&
4160 action & MLX5_FLOW_CONTEXT_ACTION_VLAN_POP) {
4161 /* For prio tag mode, replace vlan pop with rewrite vlan prio
4162 * tag rewrite.
4163 */
4164 action &= ~MLX5_FLOW_CONTEXT_ACTION_VLAN_POP;
4165 err = add_vlan_prio_tag_rewrite_action(priv, parse_attr, hdrs,
4166 &action, extack);
4167 if (err)
4168 return err;
4169 }
4170
c500c86b
PNA
4171 if (hdrs[TCA_PEDIT_KEY_EX_CMD_SET].pedits ||
4172 hdrs[TCA_PEDIT_KEY_EX_CMD_ADD].pedits) {
84be899f 4173 err = alloc_tc_pedit_action(priv, MLX5_FLOW_NAMESPACE_FDB,
27c11b6b 4174 parse_attr, hdrs, &action, extack);
c500c86b
PNA
4175 if (err)
4176 return err;
27c11b6b
EB
4177 /* in case all pedit actions are skipped, remove the MOD_HDR
4178 * flag. we might have set split_count either by pedit or
4179 * pop/push. if there is no pop/push either, reset it too.
4180 */
6ae4a6a5 4181 if (parse_attr->mod_hdr_acts.num_actions == 0) {
27c11b6b 4182 action &= ~MLX5_FLOW_CONTEXT_ACTION_MOD_HDR;
6ae4a6a5 4183 dealloc_mod_hdr_actions(&parse_attr->mod_hdr_acts);
27c11b6b
EB
4184 if (!((action & MLX5_FLOW_CONTEXT_ACTION_VLAN_POP) ||
4185 (action & MLX5_FLOW_CONTEXT_ACTION_VLAN_PUSH)))
c620b772 4186 esw_attr->split_count = 0;
27c11b6b 4187 }
c500c86b
PNA
4188 }
4189
1cab1cd7 4190 attr->action = action;
73867881 4191 if (!actions_match_supported(priv, flow_action, parse_attr, flow, extack))
bdd66ac0
OG
4192 return -EOPNOTSUPP;
4193
e88afe75 4194 if (attr->dest_chain) {
0a7fcb78
PB
4195 if (decap) {
4196 /* It can be supported if we'll create a mapping for
4197 * the tunnel device only (without tunnel), and set
4198 * this tunnel id with this decap flow.
4199 *
4200 * On restore (miss), we'll just set this saved tunnel
4201 * device.
4202 */
4203
4204 NL_SET_ERR_MSG(extack,
4205 "Decap with goto isn't supported");
4206 netdev_warn(priv->netdev,
4207 "Decap with goto isn't supported");
4208 return -EOPNOTSUPP;
4209 }
4210
e88afe75
OG
4211 attr->action |= MLX5_FLOW_CONTEXT_ACTION_FWD_DEST;
4212 }
4213
ae2741e2
VB
4214 if (!(attr->action &
4215 (MLX5_FLOW_CONTEXT_ACTION_FWD_DEST | MLX5_FLOW_CONTEXT_ACTION_DROP))) {
61644c3d
RD
4216 NL_SET_ERR_MSG_MOD(extack,
4217 "Rule must have at least one forward/drop action");
ae2741e2
VB
4218 return -EOPNOTSUPP;
4219 }
4220
c620b772 4221 if (esw_attr->split_count > 0 && !mlx5_esw_has_fwd_fdb(priv->mdev)) {
e98bedf5
EB
4222 NL_SET_ERR_MSG_MOD(extack,
4223 "current firmware doesn't support split rule for port mirroring");
592d3651
CM
4224 netdev_warn_once(priv->netdev, "current firmware doesn't support split rule for port mirroring\n");
4225 return -EOPNOTSUPP;
4226 }
4227
41c2fd94
CM
4228 /* Allocate sample attribute only when there is a sample action and
4229 * no errors after parsing.
4230 */
4231 if (flow_flag_test(flow, SAMPLE)) {
bcd6740c
CM
4232 attr->sample_attr = kzalloc(sizeof(*attr->sample_attr), GFP_KERNEL);
4233 if (!attr->sample_attr)
41c2fd94 4234 return -ENOMEM;
bcd6740c 4235 *attr->sample_attr = sample_attr;
41c2fd94
CM
4236 }
4237
31c8eba5 4238 return 0;
03a9d11e
OG
4239}
4240
226f2ca3 4241static void get_flags(int flags, unsigned long *flow_flags)
60bd4af8 4242{
226f2ca3 4243 unsigned long __flow_flags = 0;
60bd4af8 4244
226f2ca3
VB
4245 if (flags & MLX5_TC_FLAG(INGRESS))
4246 __flow_flags |= BIT(MLX5E_TC_FLOW_FLAG_INGRESS);
4247 if (flags & MLX5_TC_FLAG(EGRESS))
4248 __flow_flags |= BIT(MLX5E_TC_FLOW_FLAG_EGRESS);
60bd4af8 4249
226f2ca3
VB
4250 if (flags & MLX5_TC_FLAG(ESW_OFFLOAD))
4251 __flow_flags |= BIT(MLX5E_TC_FLOW_FLAG_ESWITCH);
4252 if (flags & MLX5_TC_FLAG(NIC_OFFLOAD))
4253 __flow_flags |= BIT(MLX5E_TC_FLOW_FLAG_NIC);
84179981
PB
4254 if (flags & MLX5_TC_FLAG(FT_OFFLOAD))
4255 __flow_flags |= BIT(MLX5E_TC_FLOW_FLAG_FT);
d9ee0491 4256
60bd4af8
OG
4257 *flow_flags = __flow_flags;
4258}
4259
05866c82
OG
4260static const struct rhashtable_params tc_ht_params = {
4261 .head_offset = offsetof(struct mlx5e_tc_flow, node),
4262 .key_offset = offsetof(struct mlx5e_tc_flow, cookie),
4263 .key_len = sizeof(((struct mlx5e_tc_flow *)0)->cookie),
4264 .automatic_shrinking = true,
4265};
4266
226f2ca3
VB
4267static struct rhashtable *get_tc_ht(struct mlx5e_priv *priv,
4268 unsigned long flags)
05866c82 4269{
655dc3d2
OG
4270 struct mlx5_eswitch *esw = priv->mdev->priv.eswitch;
4271 struct mlx5e_rep_priv *uplink_rpriv;
4272
226f2ca3 4273 if (flags & MLX5_TC_FLAG(ESW_OFFLOAD)) {
655dc3d2 4274 uplink_rpriv = mlx5_eswitch_get_uplink_priv(esw, REP_ETH);
ec1366c2 4275 return &uplink_rpriv->uplink_priv.tc_ht;
d9ee0491 4276 } else /* NIC offload */
655dc3d2 4277 return &priv->fs.tc.ht;
05866c82
OG
4278}
4279
04de7dda
RD
4280static bool is_peer_flow_needed(struct mlx5e_tc_flow *flow)
4281{
c620b772
AL
4282 struct mlx5_esw_flow_attr *esw_attr = flow->attr->esw_attr;
4283 struct mlx5_flow_attr *attr = flow->attr;
4284 bool is_rep_ingress = esw_attr->in_rep->vport != MLX5_VPORT_UPLINK &&
226f2ca3 4285 flow_flag_test(flow, INGRESS);
1418ddd9
AH
4286 bool act_is_encap = !!(attr->action &
4287 MLX5_FLOW_CONTEXT_ACTION_PACKET_REFORMAT);
c620b772 4288 bool esw_paired = mlx5_devcom_is_paired(esw_attr->in_mdev->priv.devcom,
1418ddd9
AH
4289 MLX5_DEVCOM_ESW_OFFLOADS);
4290
10fbb1cd
RD
4291 if (!esw_paired)
4292 return false;
4293
c620b772
AL
4294 if ((mlx5_lag_is_sriov(esw_attr->in_mdev) ||
4295 mlx5_lag_is_multipath(esw_attr->in_mdev)) &&
10fbb1cd
RD
4296 (is_rep_ingress || act_is_encap))
4297 return true;
4298
4299 return false;
04de7dda
RD
4300}
4301
c620b772
AL
4302struct mlx5_flow_attr *
4303mlx5_alloc_flow_attr(enum mlx5_flow_namespace_type type)
4304{
4305 u32 ex_attr_size = (type == MLX5_FLOW_NAMESPACE_FDB) ?
4306 sizeof(struct mlx5_esw_flow_attr) :
4307 sizeof(struct mlx5_nic_flow_attr);
4308 struct mlx5_flow_attr *attr;
4309
4310 return kzalloc(sizeof(*attr) + ex_attr_size, GFP_KERNEL);
4311}
4312
a88780a9
RD
4313static int
4314mlx5e_alloc_flow(struct mlx5e_priv *priv, int attr_size,
226f2ca3 4315 struct flow_cls_offload *f, unsigned long flow_flags,
a88780a9
RD
4316 struct mlx5e_tc_flow_parse_attr **__parse_attr,
4317 struct mlx5e_tc_flow **__flow)
e3a2b7ed 4318{
17091853 4319 struct mlx5e_tc_flow_parse_attr *parse_attr;
c620b772 4320 struct mlx5_flow_attr *attr;
3bc4b7bf 4321 struct mlx5e_tc_flow *flow;
ff7ea04a
GS
4322 int err = -ENOMEM;
4323 int out_index;
e3a2b7ed 4324
c620b772 4325 flow = kzalloc(sizeof(*flow), GFP_KERNEL);
1b9a07ee 4326 parse_attr = kvzalloc(sizeof(*parse_attr), GFP_KERNEL);
ff7ea04a
GS
4327 if (!parse_attr || !flow)
4328 goto err_free;
c620b772
AL
4329
4330 flow->flags = flow_flags;
4331 flow->cookie = f->cookie;
4332 flow->priv = priv;
4333
4334 attr = mlx5_alloc_flow_attr(get_flow_name_space(flow));
ff7ea04a 4335 if (!attr)
e3a2b7ed 4336 goto err_free;
ff7ea04a 4337
c620b772 4338 flow->attr = attr;
e3a2b7ed 4339
5a7e5bcb
VB
4340 for (out_index = 0; out_index < MLX5_MAX_FLOW_FWD_VPORTS; out_index++)
4341 INIT_LIST_HEAD(&flow->encaps[out_index].list);
5a7e5bcb 4342 INIT_LIST_HEAD(&flow->hairpin);
14e6b038 4343 INIT_LIST_HEAD(&flow->l3_to_l2_reformat);
5a7e5bcb 4344 refcount_set(&flow->refcnt, 1);
95435ad7 4345 init_completion(&flow->init_done);
909e615d 4346 init_completion(&flow->del_hw_done);
e3a2b7ed 4347
a88780a9
RD
4348 *__flow = flow;
4349 *__parse_attr = parse_attr;
4350
4351 return 0;
4352
4353err_free:
4354 kfree(flow);
4355 kvfree(parse_attr);
4356 return err;
4357}
4358
c7569097
AL
4359static void
4360mlx5e_flow_attr_init(struct mlx5_flow_attr *attr,
4361 struct mlx5e_tc_flow_parse_attr *parse_attr,
4362 struct flow_cls_offload *f)
4363{
4364 attr->parse_attr = parse_attr;
4365 attr->chain = f->common.chain_index;
4366 attr->prio = f->common.prio;
4367}
4368
988ab9c7 4369static void
c620b772 4370mlx5e_flow_esw_attr_init(struct mlx5_flow_attr *attr,
988ab9c7
TZ
4371 struct mlx5e_priv *priv,
4372 struct mlx5e_tc_flow_parse_attr *parse_attr,
f9e30088 4373 struct flow_cls_offload *f,
988ab9c7
TZ
4374 struct mlx5_eswitch_rep *in_rep,
4375 struct mlx5_core_dev *in_mdev)
4376{
4377 struct mlx5_eswitch *esw = priv->mdev->priv.eswitch;
c620b772 4378 struct mlx5_esw_flow_attr *esw_attr = attr->esw_attr;
988ab9c7 4379
c7569097 4380 mlx5e_flow_attr_init(attr, parse_attr, f);
988ab9c7
TZ
4381
4382 esw_attr->in_rep = in_rep;
4383 esw_attr->in_mdev = in_mdev;
4384
4385 if (MLX5_CAP_ESW(esw->dev, counter_eswitch_affinity) ==
4386 MLX5_COUNTER_SOURCE_ESWITCH)
4387 esw_attr->counter_dev = in_mdev;
4388 else
4389 esw_attr->counter_dev = priv->mdev;
4390}
4391
71129676 4392static struct mlx5e_tc_flow *
04de7dda 4393__mlx5e_add_fdb_flow(struct mlx5e_priv *priv,
f9e30088 4394 struct flow_cls_offload *f,
226f2ca3 4395 unsigned long flow_flags,
04de7dda
RD
4396 struct net_device *filter_dev,
4397 struct mlx5_eswitch_rep *in_rep,
71129676 4398 struct mlx5_core_dev *in_mdev)
a88780a9 4399{
f9e30088 4400 struct flow_rule *rule = flow_cls_offload_flow_rule(f);
a88780a9
RD
4401 struct netlink_ext_ack *extack = f->common.extack;
4402 struct mlx5e_tc_flow_parse_attr *parse_attr;
4403 struct mlx5e_tc_flow *flow;
4404 int attr_size, err;
e3a2b7ed 4405
226f2ca3 4406 flow_flags |= BIT(MLX5E_TC_FLOW_FLAG_ESWITCH);
a88780a9
RD
4407 attr_size = sizeof(struct mlx5_esw_flow_attr);
4408 err = mlx5e_alloc_flow(priv, attr_size, f, flow_flags,
4409 &parse_attr, &flow);
4410 if (err)
4411 goto out;
988ab9c7 4412
d11afc26 4413 parse_attr->filter_dev = filter_dev;
c620b772 4414 mlx5e_flow_esw_attr_init(flow->attr,
988ab9c7
TZ
4415 priv, parse_attr,
4416 f, in_rep, in_mdev);
4417
54c177ca
OS
4418 err = parse_cls_flower(flow->priv, flow, &parse_attr->spec,
4419 f, filter_dev);
d11afc26
OS
4420 if (err)
4421 goto err_free;
a88780a9 4422
7e36feeb 4423 /* actions validation depends on parsing the ct matches first */
aedd133d 4424 err = mlx5_tc_ct_match_add(get_ct_priv(priv), &parse_attr->spec, f,
c620b772 4425 &flow->attr->ct_attr, extack);
a88780a9
RD
4426 if (err)
4427 goto err_free;
4428
70f8019e 4429 err = parse_tc_fdb_actions(priv, &rule->action, flow, extack);
4c3844d9
PB
4430 if (err)
4431 goto err_free;
4432
7040632d 4433 err = mlx5e_tc_add_fdb_flow(priv, flow, extack);
95435ad7 4434 complete_all(&flow->init_done);
ef06c9ee
RD
4435 if (err) {
4436 if (!(err == -ENETUNREACH && mlx5_lag_is_multipath(in_mdev)))
4437 goto err_free;
4438
b4a23329 4439 add_unready_flow(flow);
ef06c9ee 4440 }
e3a2b7ed 4441
71129676 4442 return flow;
a88780a9
RD
4443
4444err_free:
5a7e5bcb 4445 mlx5e_flow_put(priv, flow);
a88780a9 4446out:
71129676 4447 return ERR_PTR(err);
a88780a9
RD
4448}
4449
f9e30088 4450static int mlx5e_tc_add_fdb_peer_flow(struct flow_cls_offload *f,
95dc1902 4451 struct mlx5e_tc_flow *flow,
226f2ca3 4452 unsigned long flow_flags)
04de7dda
RD
4453{
4454 struct mlx5e_priv *priv = flow->priv, *peer_priv;
4455 struct mlx5_eswitch *esw = priv->mdev->priv.eswitch, *peer_esw;
c620b772 4456 struct mlx5_esw_flow_attr *attr = flow->attr->esw_attr;
04de7dda
RD
4457 struct mlx5_devcom *devcom = priv->mdev->priv.devcom;
4458 struct mlx5e_tc_flow_parse_attr *parse_attr;
4459 struct mlx5e_rep_priv *peer_urpriv;
4460 struct mlx5e_tc_flow *peer_flow;
4461 struct mlx5_core_dev *in_mdev;
4462 int err = 0;
4463
4464 peer_esw = mlx5_devcom_get_peer_data(devcom, MLX5_DEVCOM_ESW_OFFLOADS);
4465 if (!peer_esw)
4466 return -ENODEV;
4467
4468 peer_urpriv = mlx5_eswitch_get_uplink_priv(peer_esw, REP_ETH);
4469 peer_priv = netdev_priv(peer_urpriv->netdev);
4470
4471 /* in_mdev is assigned of which the packet originated from.
4472 * So packets redirected to uplink use the same mdev of the
4473 * original flow and packets redirected from uplink use the
4474 * peer mdev.
4475 */
c620b772 4476 if (attr->in_rep->vport == MLX5_VPORT_UPLINK)
04de7dda
RD
4477 in_mdev = peer_priv->mdev;
4478 else
4479 in_mdev = priv->mdev;
4480
c620b772 4481 parse_attr = flow->attr->parse_attr;
95dc1902 4482 peer_flow = __mlx5e_add_fdb_flow(peer_priv, f, flow_flags,
71129676 4483 parse_attr->filter_dev,
c620b772 4484 attr->in_rep, in_mdev);
71129676
JG
4485 if (IS_ERR(peer_flow)) {
4486 err = PTR_ERR(peer_flow);
04de7dda 4487 goto out;
71129676 4488 }
04de7dda
RD
4489
4490 flow->peer_flow = peer_flow;
226f2ca3 4491 flow_flag_set(flow, DUP);
04de7dda
RD
4492 mutex_lock(&esw->offloads.peer_mutex);
4493 list_add_tail(&flow->peer, &esw->offloads.peer_flows);
4494 mutex_unlock(&esw->offloads.peer_mutex);
4495
4496out:
4497 mlx5_devcom_release_peer_data(devcom, MLX5_DEVCOM_ESW_OFFLOADS);
4498 return err;
4499}
4500
4501static int
4502mlx5e_add_fdb_flow(struct mlx5e_priv *priv,
f9e30088 4503 struct flow_cls_offload *f,
226f2ca3 4504 unsigned long flow_flags,
04de7dda
RD
4505 struct net_device *filter_dev,
4506 struct mlx5e_tc_flow **__flow)
4507{
4508 struct mlx5e_rep_priv *rpriv = priv->ppriv;
4509 struct mlx5_eswitch_rep *in_rep = rpriv->rep;
4510 struct mlx5_core_dev *in_mdev = priv->mdev;
4511 struct mlx5e_tc_flow *flow;
4512 int err;
4513
71129676
JG
4514 flow = __mlx5e_add_fdb_flow(priv, f, flow_flags, filter_dev, in_rep,
4515 in_mdev);
4516 if (IS_ERR(flow))
4517 return PTR_ERR(flow);
04de7dda
RD
4518
4519 if (is_peer_flow_needed(flow)) {
95dc1902 4520 err = mlx5e_tc_add_fdb_peer_flow(f, flow, flow_flags);
04de7dda
RD
4521 if (err) {
4522 mlx5e_tc_del_fdb_flow(priv, flow);
4523 goto out;
4524 }
4525 }
4526
4527 *__flow = flow;
4528
4529 return 0;
4530
4531out:
4532 return err;
4533}
4534
a88780a9
RD
4535static int
4536mlx5e_add_nic_flow(struct mlx5e_priv *priv,
f9e30088 4537 struct flow_cls_offload *f,
226f2ca3 4538 unsigned long flow_flags,
d11afc26 4539 struct net_device *filter_dev,
a88780a9
RD
4540 struct mlx5e_tc_flow **__flow)
4541{
f9e30088 4542 struct flow_rule *rule = flow_cls_offload_flow_rule(f);
a88780a9
RD
4543 struct netlink_ext_ack *extack = f->common.extack;
4544 struct mlx5e_tc_flow_parse_attr *parse_attr;
4545 struct mlx5e_tc_flow *flow;
4546 int attr_size, err;
4547
c7569097
AL
4548 if (!MLX5_CAP_FLOWTABLE_NIC_RX(priv->mdev, ignore_flow_level)) {
4549 if (!tc_cls_can_offload_and_chain0(priv->netdev, &f->common))
4550 return -EOPNOTSUPP;
4551 } else if (!tc_can_offload_extack(priv->netdev, f->common.extack)) {
bf07aa73 4552 return -EOPNOTSUPP;
c7569097 4553 }
bf07aa73 4554
226f2ca3 4555 flow_flags |= BIT(MLX5E_TC_FLOW_FLAG_NIC);
a88780a9
RD
4556 attr_size = sizeof(struct mlx5_nic_flow_attr);
4557 err = mlx5e_alloc_flow(priv, attr_size, f, flow_flags,
4558 &parse_attr, &flow);
4559 if (err)
4560 goto out;
4561
d11afc26 4562 parse_attr->filter_dev = filter_dev;
c7569097
AL
4563 mlx5e_flow_attr_init(flow->attr, parse_attr, f);
4564
54c177ca
OS
4565 err = parse_cls_flower(flow->priv, flow, &parse_attr->spec,
4566 f, filter_dev);
d11afc26
OS
4567 if (err)
4568 goto err_free;
4569
aedd133d
AL
4570 err = mlx5_tc_ct_match_add(get_ct_priv(priv), &parse_attr->spec, f,
4571 &flow->attr->ct_attr, extack);
4572 if (err)
4573 goto err_free;
4574
c6cfe113 4575 err = parse_tc_nic_actions(priv, &rule->action, flow, extack);
a88780a9
RD
4576 if (err)
4577 goto err_free;
4578
c6cfe113 4579 err = mlx5e_tc_add_nic_flow(priv, flow, extack);
a88780a9
RD
4580 if (err)
4581 goto err_free;
4582
226f2ca3 4583 flow_flag_set(flow, OFFLOADED);
a88780a9
RD
4584 *__flow = flow;
4585
4586 return 0;
e3a2b7ed 4587
e3a2b7ed 4588err_free:
8914add2 4589 flow_flag_set(flow, FAILED);
e68e28b4 4590 dealloc_mod_hdr_actions(&parse_attr->mod_hdr_acts);
5a7e5bcb 4591 mlx5e_flow_put(priv, flow);
a88780a9
RD
4592out:
4593 return err;
4594}
4595
4596static int
4597mlx5e_tc_add_flow(struct mlx5e_priv *priv,
f9e30088 4598 struct flow_cls_offload *f,
226f2ca3 4599 unsigned long flags,
d11afc26 4600 struct net_device *filter_dev,
a88780a9
RD
4601 struct mlx5e_tc_flow **flow)
4602{
4603 struct mlx5_eswitch *esw = priv->mdev->priv.eswitch;
226f2ca3 4604 unsigned long flow_flags;
a88780a9
RD
4605 int err;
4606
4607 get_flags(flags, &flow_flags);
4608
bf07aa73
PB
4609 if (!tc_can_offload_extack(priv->netdev, f->common.extack))
4610 return -EOPNOTSUPP;
4611
f6455de0 4612 if (esw && esw->mode == MLX5_ESWITCH_OFFLOADS)
d11afc26
OS
4613 err = mlx5e_add_fdb_flow(priv, f, flow_flags,
4614 filter_dev, flow);
a88780a9 4615 else
d11afc26
OS
4616 err = mlx5e_add_nic_flow(priv, f, flow_flags,
4617 filter_dev, flow);
a88780a9
RD
4618
4619 return err;
4620}
4621
553f9328
VP
4622static bool is_flow_rule_duplicate_allowed(struct net_device *dev,
4623 struct mlx5e_rep_priv *rpriv)
4624{
4625 /* Offloaded flow rule is allowed to duplicate on non-uplink representor
2fb15e72
VB
4626 * sharing tc block with other slaves of a lag device. Rpriv can be NULL if this
4627 * function is called from NIC mode.
553f9328 4628 */
2fb15e72 4629 return netif_is_lag_port(dev) && rpriv && rpriv->rep->vport != MLX5_VPORT_UPLINK;
553f9328
VP
4630}
4631
71d82d2a 4632int mlx5e_configure_flower(struct net_device *dev, struct mlx5e_priv *priv,
226f2ca3 4633 struct flow_cls_offload *f, unsigned long flags)
a88780a9
RD
4634{
4635 struct netlink_ext_ack *extack = f->common.extack;
d9ee0491 4636 struct rhashtable *tc_ht = get_tc_ht(priv, flags);
553f9328 4637 struct mlx5e_rep_priv *rpriv = priv->ppriv;
a88780a9
RD
4638 struct mlx5e_tc_flow *flow;
4639 int err = 0;
4640
7dc84de9
RD
4641 if (!mlx5_esw_hold(priv->mdev))
4642 return -EAGAIN;
4643
4644 mlx5_esw_get(priv->mdev);
4645
c5d326b2
VB
4646 rcu_read_lock();
4647 flow = rhashtable_lookup(tc_ht, &f->cookie, tc_ht_params);
a88780a9 4648 if (flow) {
553f9328
VP
4649 /* Same flow rule offloaded to non-uplink representor sharing tc block,
4650 * just return 0.
4651 */
4652 if (is_flow_rule_duplicate_allowed(dev, rpriv) && flow->orig_dev != dev)
c1aea9e1 4653 goto rcu_unlock;
553f9328 4654
a88780a9
RD
4655 NL_SET_ERR_MSG_MOD(extack,
4656 "flow cookie already exists, ignoring");
4657 netdev_warn_once(priv->netdev,
4658 "flow cookie %lx already exists, ignoring\n",
4659 f->cookie);
0e1c1a2f 4660 err = -EEXIST;
c1aea9e1 4661 goto rcu_unlock;
a88780a9 4662 }
c1aea9e1
VB
4663rcu_unlock:
4664 rcu_read_unlock();
4665 if (flow)
4666 goto out;
a88780a9 4667
7a978759 4668 trace_mlx5e_configure_flower(f);
d11afc26 4669 err = mlx5e_tc_add_flow(priv, f, flags, dev, &flow);
a88780a9
RD
4670 if (err)
4671 goto out;
4672
553f9328
VP
4673 /* Flow rule offloaded to non-uplink representor sharing tc block,
4674 * set the flow's owner dev.
4675 */
4676 if (is_flow_rule_duplicate_allowed(dev, rpriv))
4677 flow->orig_dev = dev;
4678
c5d326b2 4679 err = rhashtable_lookup_insert_fast(tc_ht, &flow->node, tc_ht_params);
a88780a9
RD
4680 if (err)
4681 goto err_free;
4682
7dc84de9 4683 mlx5_esw_release(priv->mdev);
a88780a9
RD
4684 return 0;
4685
4686err_free:
5a7e5bcb 4687 mlx5e_flow_put(priv, flow);
a88780a9 4688out:
7dc84de9
RD
4689 mlx5_esw_put(priv->mdev);
4690 mlx5_esw_release(priv->mdev);
e3a2b7ed
AV
4691 return err;
4692}
4693
8f8ae895
OG
4694static bool same_flow_direction(struct mlx5e_tc_flow *flow, int flags)
4695{
226f2ca3
VB
4696 bool dir_ingress = !!(flags & MLX5_TC_FLAG(INGRESS));
4697 bool dir_egress = !!(flags & MLX5_TC_FLAG(EGRESS));
8f8ae895 4698
226f2ca3
VB
4699 return flow_flag_test(flow, INGRESS) == dir_ingress &&
4700 flow_flag_test(flow, EGRESS) == dir_egress;
8f8ae895
OG
4701}
4702
71d82d2a 4703int mlx5e_delete_flower(struct net_device *dev, struct mlx5e_priv *priv,
226f2ca3 4704 struct flow_cls_offload *f, unsigned long flags)
e3a2b7ed 4705{
d9ee0491 4706 struct rhashtable *tc_ht = get_tc_ht(priv, flags);
e3a2b7ed 4707 struct mlx5e_tc_flow *flow;
c5d326b2 4708 int err;
e3a2b7ed 4709
c5d326b2 4710 rcu_read_lock();
ab818362 4711 flow = rhashtable_lookup(tc_ht, &f->cookie, tc_ht_params);
c5d326b2
VB
4712 if (!flow || !same_flow_direction(flow, flags)) {
4713 err = -EINVAL;
4714 goto errout;
4715 }
e3a2b7ed 4716
c5d326b2
VB
4717 /* Only delete the flow if it doesn't have MLX5E_TC_FLOW_DELETED flag
4718 * set.
4719 */
4720 if (flow_flag_test_and_set(flow, DELETED)) {
4721 err = -EINVAL;
4722 goto errout;
4723 }
05866c82 4724 rhashtable_remove_fast(tc_ht, &flow->node, tc_ht_params);
c5d326b2 4725 rcu_read_unlock();
e3a2b7ed 4726
7a978759 4727 trace_mlx5e_delete_flower(f);
5a7e5bcb 4728 mlx5e_flow_put(priv, flow);
e3a2b7ed 4729
7dc84de9 4730 mlx5_esw_put(priv->mdev);
e3a2b7ed 4731 return 0;
c5d326b2
VB
4732
4733errout:
4734 rcu_read_unlock();
4735 return err;
e3a2b7ed
AV
4736}
4737
71d82d2a 4738int mlx5e_stats_flower(struct net_device *dev, struct mlx5e_priv *priv,
226f2ca3 4739 struct flow_cls_offload *f, unsigned long flags)
aad7e08d 4740{
04de7dda 4741 struct mlx5_devcom *devcom = priv->mdev->priv.devcom;
d9ee0491 4742 struct rhashtable *tc_ht = get_tc_ht(priv, flags);
04de7dda 4743 struct mlx5_eswitch *peer_esw;
aad7e08d 4744 struct mlx5e_tc_flow *flow;
aad7e08d 4745 struct mlx5_fc *counter;
316d5f72
RD
4746 u64 lastuse = 0;
4747 u64 packets = 0;
4748 u64 bytes = 0;
5a7e5bcb 4749 int err = 0;
aad7e08d 4750
c5d326b2
VB
4751 rcu_read_lock();
4752 flow = mlx5e_flow_get(rhashtable_lookup(tc_ht, &f->cookie,
4753 tc_ht_params));
4754 rcu_read_unlock();
5a7e5bcb
VB
4755 if (IS_ERR(flow))
4756 return PTR_ERR(flow);
4757
4758 if (!same_flow_direction(flow, flags)) {
4759 err = -EINVAL;
4760 goto errout;
4761 }
aad7e08d 4762
4c3844d9 4763 if (mlx5e_is_offloaded_flow(flow) || flow_flag_test(flow, CT)) {
316d5f72
RD
4764 counter = mlx5e_tc_get_counter(flow);
4765 if (!counter)
5a7e5bcb 4766 goto errout;
aad7e08d 4767
316d5f72
RD
4768 mlx5_fc_query_cached(counter, &bytes, &packets, &lastuse);
4769 }
aad7e08d 4770
316d5f72
RD
4771 /* Under multipath it's possible for one rule to be currently
4772 * un-offloaded while the other rule is offloaded.
4773 */
04de7dda
RD
4774 peer_esw = mlx5_devcom_get_peer_data(devcom, MLX5_DEVCOM_ESW_OFFLOADS);
4775 if (!peer_esw)
4776 goto out;
4777
226f2ca3
VB
4778 if (flow_flag_test(flow, DUP) &&
4779 flow_flag_test(flow->peer_flow, OFFLOADED)) {
04de7dda
RD
4780 u64 bytes2;
4781 u64 packets2;
4782 u64 lastuse2;
4783
4784 counter = mlx5e_tc_get_counter(flow->peer_flow);
316d5f72
RD
4785 if (!counter)
4786 goto no_peer_counter;
04de7dda
RD
4787 mlx5_fc_query_cached(counter, &bytes2, &packets2, &lastuse2);
4788
4789 bytes += bytes2;
4790 packets += packets2;
4791 lastuse = max_t(u64, lastuse, lastuse2);
4792 }
4793
316d5f72 4794no_peer_counter:
04de7dda 4795 mlx5_devcom_release_peer_data(devcom, MLX5_DEVCOM_ESW_OFFLOADS);
04de7dda 4796out:
4b61d3e8 4797 flow_stats_update(&f->stats, bytes, packets, 0, lastuse,
93a129eb 4798 FLOW_ACTION_HW_STATS_DELAYED);
7a978759 4799 trace_mlx5e_stats_flower(f);
5a7e5bcb
VB
4800errout:
4801 mlx5e_flow_put(priv, flow);
4802 return err;
aad7e08d
AV
4803}
4804
1fe3e316 4805static int apply_police_params(struct mlx5e_priv *priv, u64 rate,
fcb64c0f
EC
4806 struct netlink_ext_ack *extack)
4807{
4808 struct mlx5e_rep_priv *rpriv = priv->ppriv;
4809 struct mlx5_eswitch *esw;
1fe3e316 4810 u32 rate_mbps = 0;
fcb64c0f 4811 u16 vport_num;
fcb64c0f
EC
4812 int err;
4813
e401a184
EC
4814 vport_num = rpriv->rep->vport;
4815 if (vport_num >= MLX5_VPORT_ECPF) {
4816 NL_SET_ERR_MSG_MOD(extack,
4817 "Ingress rate limit is supported only for Eswitch ports connected to VFs");
4818 return -EOPNOTSUPP;
4819 }
4820
fcb64c0f
EC
4821 esw = priv->mdev->priv.eswitch;
4822 /* rate is given in bytes/sec.
4823 * First convert to bits/sec and then round to the nearest mbit/secs.
4824 * mbit means million bits.
4825 * Moreover, if rate is non zero we choose to configure to a minimum of
4826 * 1 mbit/sec.
4827 */
1fe3e316
PP
4828 if (rate) {
4829 rate = (rate * BITS_PER_BYTE) + 500000;
8b90d897
PP
4830 do_div(rate, 1000000);
4831 rate_mbps = max_t(u32, rate, 1);
1fe3e316
PP
4832 }
4833
2d116e3e 4834 err = mlx5_esw_qos_modify_vport_rate(esw, vport_num, rate_mbps);
fcb64c0f
EC
4835 if (err)
4836 NL_SET_ERR_MSG_MOD(extack, "failed applying action to hardware");
4837
4838 return err;
4839}
4840
4841static int scan_tc_matchall_fdb_actions(struct mlx5e_priv *priv,
4842 struct flow_action *flow_action,
4843 struct netlink_ext_ack *extack)
4844{
4845 struct mlx5e_rep_priv *rpriv = priv->ppriv;
4846 const struct flow_action_entry *act;
4847 int err;
4848 int i;
4849
4850 if (!flow_action_has_entries(flow_action)) {
4851 NL_SET_ERR_MSG_MOD(extack, "matchall called with no action");
4852 return -EINVAL;
4853 }
4854
4855 if (!flow_offload_has_one_action(flow_action)) {
4856 NL_SET_ERR_MSG_MOD(extack, "matchall policing support only a single action");
4857 return -EOPNOTSUPP;
4858 }
4859
53eca1f3 4860 if (!flow_action_basic_hw_stats_check(flow_action, extack))
319a1d19
JP
4861 return -EOPNOTSUPP;
4862
fcb64c0f
EC
4863 flow_action_for_each(i, act, flow_action) {
4864 switch (act->id) {
4865 case FLOW_ACTION_POLICE:
6a56e199
BZ
4866 if (act->police.rate_pkt_ps) {
4867 NL_SET_ERR_MSG_MOD(extack, "QoS offload not support packets per second");
4868 return -EOPNOTSUPP;
4869 }
fcb64c0f
EC
4870 err = apply_police_params(priv, act->police.rate_bytes_ps, extack);
4871 if (err)
4872 return err;
4873
4874 rpriv->prev_vf_vport_stats = priv->stats.vf_vport;
4875 break;
4876 default:
4877 NL_SET_ERR_MSG_MOD(extack, "mlx5 supports only police action for matchall");
4878 return -EOPNOTSUPP;
4879 }
4880 }
4881
4882 return 0;
4883}
4884
4885int mlx5e_tc_configure_matchall(struct mlx5e_priv *priv,
4886 struct tc_cls_matchall_offload *ma)
4887{
b5f814cc 4888 struct mlx5_eswitch *esw = priv->mdev->priv.eswitch;
fcb64c0f 4889 struct netlink_ext_ack *extack = ma->common.extack;
fcb64c0f 4890
b5f814cc
EC
4891 if (!mlx5_esw_qos_enabled(esw)) {
4892 NL_SET_ERR_MSG_MOD(extack, "QoS is not supported on this device");
4893 return -EOPNOTSUPP;
4894 }
4895
7b83355f 4896 if (ma->common.prio != 1) {
fcb64c0f
EC
4897 NL_SET_ERR_MSG_MOD(extack, "only priority 1 is supported");
4898 return -EINVAL;
4899 }
4900
4901 return scan_tc_matchall_fdb_actions(priv, &ma->rule->action, extack);
4902}
4903
4904int mlx5e_tc_delete_matchall(struct mlx5e_priv *priv,
4905 struct tc_cls_matchall_offload *ma)
4906{
4907 struct netlink_ext_ack *extack = ma->common.extack;
4908
4909 return apply_police_params(priv, 0, extack);
4910}
4911
4912void mlx5e_tc_stats_matchall(struct mlx5e_priv *priv,
4913 struct tc_cls_matchall_offload *ma)
4914{
4915 struct mlx5e_rep_priv *rpriv = priv->ppriv;
4916 struct rtnl_link_stats64 cur_stats;
4917 u64 dbytes;
4918 u64 dpkts;
4919
4920 cur_stats = priv->stats.vf_vport;
4921 dpkts = cur_stats.rx_packets - rpriv->prev_vf_vport_stats.rx_packets;
4922 dbytes = cur_stats.rx_bytes - rpriv->prev_vf_vport_stats.rx_bytes;
4923 rpriv->prev_vf_vport_stats = cur_stats;
4b61d3e8 4924 flow_stats_update(&ma->stats, dbytes, dpkts, 0, jiffies,
93a129eb 4925 FLOW_ACTION_HW_STATS_DELAYED);
fcb64c0f
EC
4926}
4927
4d8fcf21
AH
4928static void mlx5e_tc_hairpin_update_dead_peer(struct mlx5e_priv *priv,
4929 struct mlx5e_priv *peer_priv)
4930{
4931 struct mlx5_core_dev *peer_mdev = peer_priv->mdev;
db76ca24
VB
4932 struct mlx5e_hairpin_entry *hpe, *tmp;
4933 LIST_HEAD(init_wait_list);
4d8fcf21
AH
4934 u16 peer_vhca_id;
4935 int bkt;
4936
4937 if (!same_hw_devs(priv, peer_priv))
4938 return;
4939
4940 peer_vhca_id = MLX5_CAP_GEN(peer_mdev, vhca_id);
4941
b32accda 4942 mutex_lock(&priv->fs.tc.hairpin_tbl_lock);
db76ca24
VB
4943 hash_for_each(priv->fs.tc.hairpin_tbl, bkt, hpe, hairpin_hlist)
4944 if (refcount_inc_not_zero(&hpe->refcnt))
4945 list_add(&hpe->dead_peer_wait_list, &init_wait_list);
4946 mutex_unlock(&priv->fs.tc.hairpin_tbl_lock);
4947
4948 list_for_each_entry_safe(hpe, tmp, &init_wait_list, dead_peer_wait_list) {
4949 wait_for_completion(&hpe->res_ready);
4950 if (!IS_ERR_OR_NULL(hpe->hp) && hpe->peer_vhca_id == peer_vhca_id)
a3e5fd93 4951 mlx5_core_hairpin_clear_dead_peer(hpe->hp->pair);
db76ca24
VB
4952
4953 mlx5e_hairpin_put(priv, hpe);
4d8fcf21
AH
4954 }
4955}
4956
4957static int mlx5e_tc_netdev_event(struct notifier_block *this,
4958 unsigned long event, void *ptr)
4959{
4960 struct net_device *ndev = netdev_notifier_info_to_dev(ptr);
4961 struct mlx5e_flow_steering *fs;
4962 struct mlx5e_priv *peer_priv;
4963 struct mlx5e_tc_table *tc;
4964 struct mlx5e_priv *priv;
4965
4966 if (ndev->netdev_ops != &mlx5e_netdev_ops ||
4967 event != NETDEV_UNREGISTER ||
4968 ndev->reg_state == NETREG_REGISTERED)
4969 return NOTIFY_DONE;
4970
4971 tc = container_of(this, struct mlx5e_tc_table, netdevice_nb);
4972 fs = container_of(tc, struct mlx5e_flow_steering, tc);
4973 priv = container_of(fs, struct mlx5e_priv, fs);
4974 peer_priv = netdev_priv(ndev);
4975 if (priv == peer_priv ||
4976 !(priv->netdev->features & NETIF_F_HW_TC))
4977 return NOTIFY_DONE;
4978
4979 mlx5e_tc_hairpin_update_dead_peer(priv, peer_priv);
4980
4981 return NOTIFY_DONE;
4982}
4983
6a064674
AL
4984static int mlx5e_tc_nic_get_ft_size(struct mlx5_core_dev *dev)
4985{
4986 int tc_grp_size, tc_tbl_size;
4987 u32 max_flow_counter;
4988
4989 max_flow_counter = (MLX5_CAP_GEN(dev, max_flow_counter_31_16) << 16) |
4990 MLX5_CAP_GEN(dev, max_flow_counter_15_0);
4991
4992 tc_grp_size = min_t(int, max_flow_counter, MLX5E_TC_TABLE_MAX_GROUP_SIZE);
4993
4994 tc_tbl_size = min_t(int, tc_grp_size * MLX5E_TC_TABLE_NUM_GROUPS,
4995 BIT(MLX5_CAP_FLOWTABLE_NIC_RX(dev, log_max_ft_size)));
4996
4997 return tc_tbl_size;
4998}
4999
3b563799
MD
5000static int mlx5e_tc_nic_create_miss_table(struct mlx5e_priv *priv)
5001{
5002 struct mlx5_flow_table **ft = &priv->fs.tc.miss_t;
5003 struct mlx5_flow_table_attr ft_attr = {};
5004 struct mlx5_flow_namespace *ns;
5005 int err = 0;
5006
5007 ft_attr.max_fte = 1;
5008 ft_attr.autogroup.max_num_groups = 1;
5009 ft_attr.level = MLX5E_TC_MISS_LEVEL;
5010 ft_attr.prio = 0;
5011 ns = mlx5_get_flow_namespace(priv->mdev, MLX5_FLOW_NAMESPACE_KERNEL);
5012
5013 *ft = mlx5_create_auto_grouped_flow_table(ns, &ft_attr);
5014 if (IS_ERR(*ft)) {
5015 err = PTR_ERR(*ft);
5016 netdev_err(priv->netdev, "failed to create tc nic miss table err=%d\n", err);
5017 }
5018
5019 return err;
5020}
5021
5022static void mlx5e_tc_nic_destroy_miss_table(struct mlx5e_priv *priv)
5023{
5024 mlx5_destroy_flow_table(priv->fs.tc.miss_t);
5025}
5026
655dc3d2 5027int mlx5e_tc_nic_init(struct mlx5e_priv *priv)
e8f887ac 5028{
acff797c 5029 struct mlx5e_tc_table *tc = &priv->fs.tc;
6a064674 5030 struct mlx5_core_dev *dev = priv->mdev;
c9355682 5031 struct mapping_ctx *chains_mapping;
6a064674 5032 struct mlx5_chains_attr attr = {};
2198b932 5033 u64 mapping_id;
4d8fcf21 5034 int err;
e8f887ac 5035
b2fdf3d0 5036 mlx5e_mod_hdr_tbl_init(&tc->mod_hdr);
b6fac0b4 5037 mutex_init(&tc->t_lock);
b32accda 5038 mutex_init(&tc->hairpin_tbl_lock);
5c65c564 5039 hash_init(tc->hairpin_tbl);
11c9c548 5040
4d8fcf21
AH
5041 err = rhashtable_init(&tc->ht, &tc_ht_params);
5042 if (err)
5043 return err;
5044
9ba33339
RD
5045 lockdep_set_class(&tc->ht.mutex, &tc_ht_lock_key);
5046
2198b932
RD
5047 mapping_id = mlx5_query_nic_system_image_guid(dev);
5048
5049 chains_mapping = mapping_create_for_id(mapping_id, MAPPING_TYPE_CHAIN,
5050 sizeof(struct mlx5_mapped_obj),
5051 MLX5E_TC_TABLE_CHAIN_TAG_MASK, true);
5052
c9355682
CM
5053 if (IS_ERR(chains_mapping)) {
5054 err = PTR_ERR(chains_mapping);
5055 goto err_mapping;
5056 }
5057 tc->mapping = chains_mapping;
5058
3b563799
MD
5059 err = mlx5e_tc_nic_create_miss_table(priv);
5060 if (err)
5061 goto err_chains;
5062
c9355682 5063 if (MLX5_CAP_FLOWTABLE_NIC_RX(priv->mdev, ignore_flow_level))
c7569097
AL
5064 attr.flags = MLX5_CHAINS_AND_PRIOS_SUPPORTED |
5065 MLX5_CHAINS_IGNORE_FLOW_LEVEL_SUPPORTED;
6a064674
AL
5066 attr.ns = MLX5_FLOW_NAMESPACE_KERNEL;
5067 attr.max_ft_sz = mlx5e_tc_nic_get_ft_size(dev);
5068 attr.max_grp_num = MLX5E_TC_TABLE_NUM_GROUPS;
3b563799 5069 attr.default_ft = priv->fs.tc.miss_t;
c9355682 5070 attr.mapping = chains_mapping;
6a064674
AL
5071
5072 tc->chains = mlx5_chains_create(dev, &attr);
5073 if (IS_ERR(tc->chains)) {
5074 err = PTR_ERR(tc->chains);
3b563799 5075 goto err_miss;
6a064674
AL
5076 }
5077
f0da4daa 5078 tc->post_act = mlx5e_tc_post_act_init(priv, tc->chains, MLX5_FLOW_NAMESPACE_KERNEL);
aedd133d 5079 tc->ct = mlx5_tc_ct_init(priv, tc->chains, &priv->fs.tc.mod_hdr,
f0da4daa 5080 MLX5_FLOW_NAMESPACE_KERNEL, tc->post_act);
aedd133d 5081
4d8fcf21 5082 tc->netdevice_nb.notifier_call = mlx5e_tc_netdev_event;
d48834f9
JP
5083 err = register_netdevice_notifier_dev_net(priv->netdev,
5084 &tc->netdevice_nb,
5085 &tc->netdevice_nn);
5086 if (err) {
4d8fcf21
AH
5087 tc->netdevice_nb.notifier_call = NULL;
5088 mlx5_core_warn(priv->mdev, "Failed to register netdev notifier\n");
6a064674 5089 goto err_reg;
4d8fcf21
AH
5090 }
5091
6a064674
AL
5092 return 0;
5093
5094err_reg:
aedd133d 5095 mlx5_tc_ct_clean(tc->ct);
f0da4daa 5096 mlx5e_tc_post_act_destroy(tc->post_act);
6a064674 5097 mlx5_chains_destroy(tc->chains);
3b563799
MD
5098err_miss:
5099 mlx5e_tc_nic_destroy_miss_table(priv);
6a064674 5100err_chains:
c9355682
CM
5101 mapping_destroy(chains_mapping);
5102err_mapping:
6a064674 5103 rhashtable_destroy(&tc->ht);
4d8fcf21 5104 return err;
e8f887ac
AV
5105}
5106
5107static void _mlx5e_tc_del_flow(void *ptr, void *arg)
5108{
5109 struct mlx5e_tc_flow *flow = ptr;
655dc3d2 5110 struct mlx5e_priv *priv = flow->priv;
e8f887ac 5111
961e8979 5112 mlx5e_tc_del_flow(priv, flow);
e8f887ac
AV
5113 kfree(flow);
5114}
5115
655dc3d2 5116void mlx5e_tc_nic_cleanup(struct mlx5e_priv *priv)
e8f887ac 5117{
acff797c 5118 struct mlx5e_tc_table *tc = &priv->fs.tc;
e8f887ac 5119
4d8fcf21 5120 if (tc->netdevice_nb.notifier_call)
d48834f9
JP
5121 unregister_netdevice_notifier_dev_net(priv->netdev,
5122 &tc->netdevice_nb,
5123 &tc->netdevice_nn);
4d8fcf21 5124
b2fdf3d0 5125 mlx5e_mod_hdr_tbl_destroy(&tc->mod_hdr);
b32accda
VB
5126 mutex_destroy(&tc->hairpin_tbl_lock);
5127
6a064674 5128 rhashtable_free_and_destroy(&tc->ht, _mlx5e_tc_del_flow, NULL);
e8f887ac 5129
acff797c 5130 if (!IS_ERR_OR_NULL(tc->t)) {
6a064674 5131 mlx5_chains_put_table(tc->chains, 0, 1, MLX5E_TC_FT_LEVEL);
acff797c 5132 tc->t = NULL;
e8f887ac 5133 }
b6fac0b4 5134 mutex_destroy(&tc->t_lock);
6a064674 5135
aedd133d 5136 mlx5_tc_ct_clean(tc->ct);
f0da4daa 5137 mlx5e_tc_post_act_destroy(tc->post_act);
c9355682 5138 mapping_destroy(tc->mapping);
6a064674 5139 mlx5_chains_destroy(tc->chains);
3b563799 5140 mlx5e_tc_nic_destroy_miss_table(priv);
e8f887ac 5141}
655dc3d2
OG
5142
5143int mlx5e_tc_esw_init(struct rhashtable *tc_ht)
5144{
d7a42ad0 5145 const size_t sz_enc_opts = sizeof(struct tunnel_match_enc_opts);
0a7fcb78 5146 struct mlx5_rep_uplink_priv *uplink_priv;
aedd133d 5147 struct mlx5e_rep_priv *rpriv;
0a7fcb78 5148 struct mapping_ctx *mapping;
aedd133d
AL
5149 struct mlx5_eswitch *esw;
5150 struct mlx5e_priv *priv;
2198b932 5151 u64 mapping_id;
aedd133d 5152 int err = 0;
0a7fcb78
PB
5153
5154 uplink_priv = container_of(tc_ht, struct mlx5_rep_uplink_priv, tc_ht);
aedd133d
AL
5155 rpriv = container_of(uplink_priv, struct mlx5e_rep_priv, uplink_priv);
5156 priv = netdev_priv(rpriv->netdev);
5157 esw = priv->mdev->priv.eswitch;
0a7fcb78 5158
f0da4daa
CM
5159 uplink_priv->post_act = mlx5e_tc_post_act_init(priv, esw_chains(esw),
5160 MLX5_FLOW_NAMESPACE_FDB);
aedd133d
AL
5161 uplink_priv->ct_priv = mlx5_tc_ct_init(netdev_priv(priv->netdev),
5162 esw_chains(esw),
5163 &esw->offloads.mod_hdr,
f0da4daa
CM
5164 MLX5_FLOW_NAMESPACE_FDB,
5165 uplink_priv->post_act);
4c3844d9 5166
3651168c
AL
5167 uplink_priv->int_port_priv = mlx5e_tc_int_port_init(netdev_priv(priv->netdev));
5168
2741f223 5169 uplink_priv->tc_psample = mlx5e_tc_sample_init(esw, uplink_priv->post_act);
2a9ab10a 5170
2198b932
RD
5171 mapping_id = mlx5_query_nic_system_image_guid(esw->dev);
5172
5173 mapping = mapping_create_for_id(mapping_id, MAPPING_TYPE_TUNNEL,
5174 sizeof(struct tunnel_match_key),
5175 TUNNEL_INFO_BITS_MASK, true);
5176
0a7fcb78
PB
5177 if (IS_ERR(mapping)) {
5178 err = PTR_ERR(mapping);
5179 goto err_tun_mapping;
5180 }
5181 uplink_priv->tunnel_mapping = mapping;
5182
8e404fef 5183 /* 0xFFF is reserved for stack devices slow path table mark */
2198b932
RD
5184 mapping = mapping_create_for_id(mapping_id, MAPPING_TYPE_TUNNEL_ENC_OPTS,
5185 sz_enc_opts, ENC_OPTS_BITS_MASK - 1, true);
0a7fcb78
PB
5186 if (IS_ERR(mapping)) {
5187 err = PTR_ERR(mapping);
5188 goto err_enc_opts_mapping;
5189 }
5190 uplink_priv->tunnel_enc_opts_mapping = mapping;
5191
5192 err = rhashtable_init(tc_ht, &tc_ht_params);
5193 if (err)
5194 goto err_ht_init;
5195
9ba33339
RD
5196 lockdep_set_class(&tc_ht->mutex, &tc_ht_lock_key);
5197
8914add2 5198 uplink_priv->encap = mlx5e_tc_tun_init(priv);
2b6c3c1e
WY
5199 if (IS_ERR(uplink_priv->encap)) {
5200 err = PTR_ERR(uplink_priv->encap);
8914add2 5201 goto err_register_fib_notifier;
2b6c3c1e 5202 }
8914add2 5203
2b6c3c1e 5204 return 0;
0a7fcb78 5205
8914add2
VB
5206err_register_fib_notifier:
5207 rhashtable_destroy(tc_ht);
0a7fcb78
PB
5208err_ht_init:
5209 mapping_destroy(uplink_priv->tunnel_enc_opts_mapping);
5210err_enc_opts_mapping:
5211 mapping_destroy(uplink_priv->tunnel_mapping);
5212err_tun_mapping:
0027d70c 5213 mlx5e_tc_sample_cleanup(uplink_priv->tc_psample);
3651168c 5214 mlx5e_tc_int_port_cleanup(uplink_priv->int_port_priv);
aedd133d 5215 mlx5_tc_ct_clean(uplink_priv->ct_priv);
0a7fcb78
PB
5216 netdev_warn(priv->netdev,
5217 "Failed to initialize tc (eswitch), err: %d", err);
f0da4daa 5218 mlx5e_tc_post_act_destroy(uplink_priv->post_act);
0a7fcb78 5219 return err;
655dc3d2
OG
5220}
5221
5222void mlx5e_tc_esw_cleanup(struct rhashtable *tc_ht)
5223{
0a7fcb78
PB
5224 struct mlx5_rep_uplink_priv *uplink_priv;
5225
0a7fcb78 5226 uplink_priv = container_of(tc_ht, struct mlx5_rep_uplink_priv, tc_ht);
aedd133d 5227
8914add2
VB
5228 rhashtable_free_and_destroy(tc_ht, _mlx5e_tc_del_flow, NULL);
5229 mlx5e_tc_tun_cleanup(uplink_priv->encap);
5230
0a7fcb78
PB
5231 mapping_destroy(uplink_priv->tunnel_enc_opts_mapping);
5232 mapping_destroy(uplink_priv->tunnel_mapping);
4c3844d9 5233
0027d70c 5234 mlx5e_tc_sample_cleanup(uplink_priv->tc_psample);
3651168c 5235 mlx5e_tc_int_port_cleanup(uplink_priv->int_port_priv);
aedd133d 5236 mlx5_tc_ct_clean(uplink_priv->ct_priv);
f0da4daa 5237 mlx5e_tc_post_act_destroy(uplink_priv->post_act);
655dc3d2 5238}
01252a27 5239
226f2ca3 5240int mlx5e_tc_num_filters(struct mlx5e_priv *priv, unsigned long flags)
01252a27 5241{
d9ee0491 5242 struct rhashtable *tc_ht = get_tc_ht(priv, flags);
01252a27
OG
5243
5244 return atomic_read(&tc_ht->nelems);
5245}
04de7dda
RD
5246
5247void mlx5e_tc_clean_fdb_peer_flows(struct mlx5_eswitch *esw)
5248{
5249 struct mlx5e_tc_flow *flow, *tmp;
5250
5251 list_for_each_entry_safe(flow, tmp, &esw->offloads.peer_flows, peer)
5252 __mlx5e_tc_del_fdb_peer_flow(flow);
5253}
b4a23329
RD
5254
5255void mlx5e_tc_reoffload_flows_work(struct work_struct *work)
5256{
5257 struct mlx5_rep_uplink_priv *rpriv =
5258 container_of(work, struct mlx5_rep_uplink_priv,
5259 reoffload_flows_work);
5260 struct mlx5e_tc_flow *flow, *tmp;
5261
ad86755b 5262 mutex_lock(&rpriv->unready_flows_lock);
b4a23329
RD
5263 list_for_each_entry_safe(flow, tmp, &rpriv->unready_flows, unready) {
5264 if (!mlx5e_tc_add_fdb_flow(flow->priv, flow, NULL))
ad86755b 5265 unready_flow_del(flow);
b4a23329 5266 }
ad86755b 5267 mutex_unlock(&rpriv->unready_flows_lock);
b4a23329 5268}
e2394a61
VB
5269
5270static int mlx5e_setup_tc_cls_flower(struct mlx5e_priv *priv,
5271 struct flow_cls_offload *cls_flower,
5272 unsigned long flags)
5273{
5274 switch (cls_flower->command) {
5275 case FLOW_CLS_REPLACE:
5276 return mlx5e_configure_flower(priv->netdev, priv, cls_flower,
5277 flags);
5278 case FLOW_CLS_DESTROY:
5279 return mlx5e_delete_flower(priv->netdev, priv, cls_flower,
5280 flags);
5281 case FLOW_CLS_STATS:
5282 return mlx5e_stats_flower(priv->netdev, priv, cls_flower,
5283 flags);
5284 default:
5285 return -EOPNOTSUPP;
5286 }
5287}
5288
5289int mlx5e_setup_tc_block_cb(enum tc_setup_type type, void *type_data,
5290 void *cb_priv)
5291{
ec9457a6 5292 unsigned long flags = MLX5_TC_FLAG(INGRESS);
e2394a61
VB
5293 struct mlx5e_priv *priv = cb_priv;
5294
2ff349c5
RD
5295 if (!priv->netdev || !netif_device_present(priv->netdev))
5296 return -EOPNOTSUPP;
5297
ec9457a6
RD
5298 if (mlx5e_is_uplink_rep(priv))
5299 flags |= MLX5_TC_FLAG(ESW_OFFLOAD);
5300 else
5301 flags |= MLX5_TC_FLAG(NIC_OFFLOAD);
5302
e2394a61
VB
5303 switch (type) {
5304 case TC_SETUP_CLSFLOWER:
5305 return mlx5e_setup_tc_cls_flower(priv, type_data, flags);
5306 default:
5307 return -EOPNOTSUPP;
5308 }
5309}
c7569097
AL
5310
5311bool mlx5e_tc_update_skb(struct mlx5_cqe64 *cqe,
5312 struct sk_buff *skb)
5313{
5314#if IS_ENABLED(CONFIG_NET_TC_SKB_EXT)
aedd133d 5315 u32 chain = 0, chain_tag, reg_b, zone_restore_id;
c7569097 5316 struct mlx5e_priv *priv = netdev_priv(skb->dev);
aedd133d 5317 struct mlx5e_tc_table *tc = &priv->fs.tc;
a91d98a0 5318 struct mlx5_mapped_obj mapped_obj;
c7569097
AL
5319 struct tc_skb_ext *tc_skb_ext;
5320 int err;
5321
5322 reg_b = be32_to_cpu(cqe->ft_metadata);
5323
5324 chain_tag = reg_b & MLX5E_TC_TABLE_CHAIN_TAG_MASK;
5325
c9355682 5326 err = mapping_find(tc->mapping, chain_tag, &mapped_obj);
c7569097
AL
5327 if (err) {
5328 netdev_dbg(priv->netdev,
5329 "Couldn't find chain for chain tag: %d, err: %d\n",
5330 chain_tag, err);
5331 return false;
5332 }
5333
a91d98a0
CM
5334 if (mapped_obj.type == MLX5_MAPPED_OBJ_CHAIN) {
5335 chain = mapped_obj.chain;
9453d45e 5336 tc_skb_ext = tc_skb_ext_alloc(skb);
c7569097
AL
5337 if (WARN_ON(!tc_skb_ext))
5338 return false;
5339
5340 tc_skb_ext->chain = chain;
aedd133d 5341
ed2fe7ba 5342 zone_restore_id = (reg_b >> REG_MAPPING_MOFFSET(NIC_ZONE_RESTORE_TO_REG)) &
48d216e5 5343 ESW_ZONE_ID_MASK;
aedd133d
AL
5344
5345 if (!mlx5e_tc_ct_restore_flow(tc->ct, skb,
5346 zone_restore_id))
5347 return false;
a91d98a0
CM
5348 } else {
5349 netdev_dbg(priv->netdev, "Invalid mapped object type: %d\n", mapped_obj.type);
5350 return false;
c7569097
AL
5351 }
5352#endif /* CONFIG_NET_TC_SKB_EXT */
5353
5354 return true;
5355}