]> git.proxmox.com Git - mirror_ubuntu-jammy-kernel.git/blame - drivers/net/ethernet/mellanox/mlx5/core/en_tc.c
net/mlx5e: Extend hairpin entry with reference counter
[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>
3f7d0eb4 34#include <net/sch_generic.h>
e3a2b7ed
AV
35#include <net/pkt_cls.h>
36#include <net/tc_act/tc_gact.h>
12185a9f 37#include <net/tc_act/tc_skbedit.h>
e8f887ac
AV
38#include <linux/mlx5/fs.h>
39#include <linux/mlx5/device.h>
40#include <linux/rhashtable.h>
5a7e5bcb 41#include <linux/refcount.h>
03a9d11e 42#include <net/tc_act/tc_mirred.h>
776b12b6 43#include <net/tc_act/tc_vlan.h>
bbd00f7e 44#include <net/tc_act/tc_tunnel_key.h>
d79b6df6 45#include <net/tc_act/tc_pedit.h>
26c02749 46#include <net/tc_act/tc_csum.h>
f6dfb4c3 47#include <net/arp.h>
3616d08b 48#include <net/ipv6_stubs.h>
e8f887ac 49#include "en.h"
1d447a39 50#include "en_rep.h"
232c0013 51#include "en_tc.h"
03a9d11e 52#include "eswitch.h"
3f6d08d1 53#include "fs_core.h"
2c81bfd5 54#include "en/port.h"
101f4de9 55#include "en/tc_tun.h"
04de7dda 56#include "lib/devcom.h"
9272e3df 57#include "lib/geneve.h"
e8f887ac 58
3bc4b7bf
OG
59struct mlx5_nic_flow_attr {
60 u32 action;
61 u32 flow_tag;
2f4fe4ca 62 u32 mod_hdr_id;
5c65c564 63 u32 hairpin_tirn;
38aa51c1 64 u8 match_level;
3f6d08d1 65 struct mlx5_flow_table *hairpin_ft;
b8aee822 66 struct mlx5_fc *counter;
3bc4b7bf
OG
67};
68
226f2ca3 69#define MLX5E_TC_FLOW_BASE (MLX5E_TC_FLAG_LAST_EXPORTED_BIT + 1)
60bd4af8 70
65ba8fb7 71enum {
226f2ca3
VB
72 MLX5E_TC_FLOW_FLAG_INGRESS = MLX5E_TC_FLAG_INGRESS_BIT,
73 MLX5E_TC_FLOW_FLAG_EGRESS = MLX5E_TC_FLAG_EGRESS_BIT,
74 MLX5E_TC_FLOW_FLAG_ESWITCH = MLX5E_TC_FLAG_ESW_OFFLOAD_BIT,
75 MLX5E_TC_FLOW_FLAG_NIC = MLX5E_TC_FLAG_NIC_OFFLOAD_BIT,
76 MLX5E_TC_FLOW_FLAG_OFFLOADED = MLX5E_TC_FLOW_BASE,
77 MLX5E_TC_FLOW_FLAG_HAIRPIN = MLX5E_TC_FLOW_BASE + 1,
78 MLX5E_TC_FLOW_FLAG_HAIRPIN_RSS = MLX5E_TC_FLOW_BASE + 2,
79 MLX5E_TC_FLOW_FLAG_SLOW = MLX5E_TC_FLOW_BASE + 3,
80 MLX5E_TC_FLOW_FLAG_DUP = MLX5E_TC_FLOW_BASE + 4,
81 MLX5E_TC_FLOW_FLAG_NOT_READY = MLX5E_TC_FLOW_BASE + 5,
c5d326b2 82 MLX5E_TC_FLOW_FLAG_DELETED = MLX5E_TC_FLOW_BASE + 6,
65ba8fb7
OG
83};
84
e4ad91f2
CM
85#define MLX5E_TC_MAX_SPLITS 1
86
79baaec7
EB
87/* Helper struct for accessing a struct containing list_head array.
88 * Containing struct
89 * |- Helper array
90 * [0] Helper item 0
91 * |- list_head item 0
92 * |- index (0)
93 * [1] Helper item 1
94 * |- list_head item 1
95 * |- index (1)
96 * To access the containing struct from one of the list_head items:
97 * 1. Get the helper item from the list_head item using
98 * helper item =
99 * container_of(list_head item, helper struct type, list_head field)
100 * 2. Get the contining struct from the helper item and its index in the array:
101 * containing struct =
102 * container_of(helper item, containing struct type, helper field[index])
103 */
104struct encap_flow_item {
105 struct list_head list;
106 int index;
107};
108
e8f887ac
AV
109struct mlx5e_tc_flow {
110 struct rhash_head node;
655dc3d2 111 struct mlx5e_priv *priv;
e8f887ac 112 u64 cookie;
226f2ca3 113 unsigned long flags;
e4ad91f2 114 struct mlx5_flow_handle *rule[MLX5E_TC_MAX_SPLITS + 1];
79baaec7
EB
115 /* Flow can be associated with multiple encap IDs.
116 * The number of encaps is bounded by the number of supported
117 * destinations.
118 */
119 struct encap_flow_item encaps[MLX5_MAX_FLOW_FWD_VPORTS];
04de7dda 120 struct mlx5e_tc_flow *peer_flow;
11c9c548 121 struct list_head mod_hdr; /* flows sharing the same mod hdr ID */
e4f9abbd 122 struct mlx5e_hairpin_entry *hpe; /* attached hairpin instance */
5c65c564 123 struct list_head hairpin; /* flows sharing the same hairpin */
04de7dda 124 struct list_head peer; /* flows with peer flow */
b4a23329 125 struct list_head unready; /* flows not ready to be offloaded (e.g due to missing route) */
5a7e5bcb 126 refcount_t refcnt;
c5d326b2 127 struct rcu_head rcu_head;
3bc4b7bf
OG
128 union {
129 struct mlx5_esw_flow_attr esw_attr[0];
130 struct mlx5_nic_flow_attr nic_attr[0];
131 };
e8f887ac
AV
132};
133
17091853 134struct mlx5e_tc_flow_parse_attr {
1f6da306 135 const struct ip_tunnel_info *tun_info[MLX5_MAX_FLOW_FWD_VPORTS];
d11afc26 136 struct net_device *filter_dev;
17091853 137 struct mlx5_flow_spec spec;
d79b6df6 138 int num_mod_hdr_actions;
218d05ce 139 int max_mod_hdr_actions;
d79b6df6 140 void *mod_hdr_actions;
98b66cb1 141 int mirred_ifindex[MLX5_MAX_FLOW_FWD_VPORTS];
17091853
OG
142};
143
acff797c 144#define MLX5E_TC_TABLE_NUM_GROUPS 4
b3a433de 145#define MLX5E_TC_TABLE_MAX_GROUP_SIZE BIT(16)
e8f887ac 146
77ab67b7
OG
147struct mlx5e_hairpin {
148 struct mlx5_hairpin *pair;
149
150 struct mlx5_core_dev *func_mdev;
3f6d08d1 151 struct mlx5e_priv *func_priv;
77ab67b7
OG
152 u32 tdn;
153 u32 tirn;
3f6d08d1
OG
154
155 int num_channels;
156 struct mlx5e_rqt indir_rqt;
157 u32 indir_tirn[MLX5E_NUM_INDIR_TIRS];
158 struct mlx5e_ttc_table ttc;
77ab67b7
OG
159};
160
5c65c564
OG
161struct mlx5e_hairpin_entry {
162 /* a node of a hash table which keeps all the hairpin entries */
163 struct hlist_node hairpin_hlist;
164
165 /* flows sharing the same hairpin */
166 struct list_head flows;
167
d8822868 168 u16 peer_vhca_id;
106be53b 169 u8 prio;
5c65c564 170 struct mlx5e_hairpin *hp;
e4f9abbd 171 refcount_t refcnt;
5c65c564
OG
172};
173
11c9c548
OG
174struct mod_hdr_key {
175 int num_actions;
176 void *actions;
177};
178
179struct mlx5e_mod_hdr_entry {
180 /* a node of a hash table which keeps all the mod_hdr entries */
181 struct hlist_node mod_hdr_hlist;
182
183 /* flows sharing the same mod_hdr entry */
184 struct list_head flows;
185
186 struct mod_hdr_key key;
187
188 u32 mod_hdr_id;
189};
190
191#define MLX5_MH_ACT_SZ MLX5_UN_SZ_BYTES(set_action_in_add_action_in_auto)
192
5a7e5bcb
VB
193static void mlx5e_tc_del_flow(struct mlx5e_priv *priv,
194 struct mlx5e_tc_flow *flow);
195
196static struct mlx5e_tc_flow *mlx5e_flow_get(struct mlx5e_tc_flow *flow)
197{
198 if (!flow || !refcount_inc_not_zero(&flow->refcnt))
199 return ERR_PTR(-EINVAL);
200 return flow;
201}
202
203static void mlx5e_flow_put(struct mlx5e_priv *priv,
204 struct mlx5e_tc_flow *flow)
205{
206 if (refcount_dec_and_test(&flow->refcnt)) {
207 mlx5e_tc_del_flow(priv, flow);
c5d326b2 208 kfree_rcu(flow, rcu_head);
5a7e5bcb
VB
209 }
210}
211
226f2ca3
VB
212static void __flow_flag_set(struct mlx5e_tc_flow *flow, unsigned long flag)
213{
214 /* Complete all memory stores before setting bit. */
215 smp_mb__before_atomic();
216 set_bit(flag, &flow->flags);
217}
218
219#define flow_flag_set(flow, flag) __flow_flag_set(flow, MLX5E_TC_FLOW_FLAG_##flag)
220
c5d326b2
VB
221static bool __flow_flag_test_and_set(struct mlx5e_tc_flow *flow,
222 unsigned long flag)
223{
224 /* test_and_set_bit() provides all necessary barriers */
225 return test_and_set_bit(flag, &flow->flags);
226}
227
228#define flow_flag_test_and_set(flow, flag) \
229 __flow_flag_test_and_set(flow, \
230 MLX5E_TC_FLOW_FLAG_##flag)
231
226f2ca3
VB
232static void __flow_flag_clear(struct mlx5e_tc_flow *flow, unsigned long flag)
233{
234 /* Complete all memory stores before clearing bit. */
235 smp_mb__before_atomic();
236 clear_bit(flag, &flow->flags);
237}
238
239#define flow_flag_clear(flow, flag) __flow_flag_clear(flow, \
240 MLX5E_TC_FLOW_FLAG_##flag)
241
242static bool __flow_flag_test(struct mlx5e_tc_flow *flow, unsigned long flag)
243{
244 bool ret = test_bit(flag, &flow->flags);
245
246 /* Read fields of flow structure only after checking flags. */
247 smp_mb__after_atomic();
248 return ret;
249}
250
251#define flow_flag_test(flow, flag) __flow_flag_test(flow, \
252 MLX5E_TC_FLOW_FLAG_##flag)
253
254static bool mlx5e_is_eswitch_flow(struct mlx5e_tc_flow *flow)
255{
256 return flow_flag_test(flow, ESWITCH);
257}
258
259static bool mlx5e_is_offloaded_flow(struct mlx5e_tc_flow *flow)
260{
261 return flow_flag_test(flow, OFFLOADED);
262}
263
11c9c548
OG
264static inline u32 hash_mod_hdr_info(struct mod_hdr_key *key)
265{
266 return jhash(key->actions,
267 key->num_actions * MLX5_MH_ACT_SZ, 0);
268}
269
270static inline int cmp_mod_hdr_info(struct mod_hdr_key *a,
271 struct mod_hdr_key *b)
272{
273 if (a->num_actions != b->num_actions)
274 return 1;
275
276 return memcmp(a->actions, b->actions, a->num_actions * MLX5_MH_ACT_SZ);
277}
278
279static int mlx5e_attach_mod_hdr(struct mlx5e_priv *priv,
280 struct mlx5e_tc_flow *flow,
281 struct mlx5e_tc_flow_parse_attr *parse_attr)
282{
283 struct mlx5_eswitch *esw = priv->mdev->priv.eswitch;
284 int num_actions, actions_size, namespace, err;
226f2ca3 285 bool found = false, is_eswitch_flow;
11c9c548
OG
286 struct mlx5e_mod_hdr_entry *mh;
287 struct mod_hdr_key key;
11c9c548
OG
288 u32 hash_key;
289
290 num_actions = parse_attr->num_mod_hdr_actions;
291 actions_size = MLX5_MH_ACT_SZ * num_actions;
292
293 key.actions = parse_attr->mod_hdr_actions;
294 key.num_actions = num_actions;
295
296 hash_key = hash_mod_hdr_info(&key);
297
226f2ca3
VB
298 is_eswitch_flow = mlx5e_is_eswitch_flow(flow);
299 if (is_eswitch_flow) {
11c9c548
OG
300 namespace = MLX5_FLOW_NAMESPACE_FDB;
301 hash_for_each_possible(esw->offloads.mod_hdr_tbl, mh,
302 mod_hdr_hlist, hash_key) {
303 if (!cmp_mod_hdr_info(&mh->key, &key)) {
304 found = true;
305 break;
306 }
307 }
308 } else {
309 namespace = MLX5_FLOW_NAMESPACE_KERNEL;
310 hash_for_each_possible(priv->fs.tc.mod_hdr_tbl, mh,
311 mod_hdr_hlist, hash_key) {
312 if (!cmp_mod_hdr_info(&mh->key, &key)) {
313 found = true;
314 break;
315 }
316 }
317 }
318
319 if (found)
320 goto attach_flow;
321
322 mh = kzalloc(sizeof(*mh) + actions_size, GFP_KERNEL);
323 if (!mh)
324 return -ENOMEM;
325
326 mh->key.actions = (void *)mh + sizeof(*mh);
327 memcpy(mh->key.actions, key.actions, actions_size);
328 mh->key.num_actions = num_actions;
329 INIT_LIST_HEAD(&mh->flows);
330
331 err = mlx5_modify_header_alloc(priv->mdev, namespace,
332 mh->key.num_actions,
333 mh->key.actions,
334 &mh->mod_hdr_id);
335 if (err)
336 goto out_err;
337
226f2ca3 338 if (is_eswitch_flow)
11c9c548
OG
339 hash_add(esw->offloads.mod_hdr_tbl, &mh->mod_hdr_hlist, hash_key);
340 else
341 hash_add(priv->fs.tc.mod_hdr_tbl, &mh->mod_hdr_hlist, hash_key);
342
343attach_flow:
344 list_add(&flow->mod_hdr, &mh->flows);
226f2ca3 345 if (is_eswitch_flow)
11c9c548
OG
346 flow->esw_attr->mod_hdr_id = mh->mod_hdr_id;
347 else
348 flow->nic_attr->mod_hdr_id = mh->mod_hdr_id;
349
350 return 0;
351
352out_err:
353 kfree(mh);
354 return err;
355}
356
357static void mlx5e_detach_mod_hdr(struct mlx5e_priv *priv,
358 struct mlx5e_tc_flow *flow)
359{
360 struct list_head *next = flow->mod_hdr.next;
361
5a7e5bcb
VB
362 /* flow wasn't fully initialized */
363 if (list_empty(&flow->mod_hdr))
364 return;
365
11c9c548
OG
366 list_del(&flow->mod_hdr);
367
368 if (list_empty(next)) {
369 struct mlx5e_mod_hdr_entry *mh;
370
371 mh = list_entry(next, struct mlx5e_mod_hdr_entry, flows);
372
373 mlx5_modify_header_dealloc(priv->mdev, mh->mod_hdr_id);
374 hash_del(&mh->mod_hdr_hlist);
375 kfree(mh);
376 }
377}
378
77ab67b7
OG
379static
380struct mlx5_core_dev *mlx5e_hairpin_get_mdev(struct net *net, int ifindex)
381{
382 struct net_device *netdev;
383 struct mlx5e_priv *priv;
384
385 netdev = __dev_get_by_index(net, ifindex);
386 priv = netdev_priv(netdev);
387 return priv->mdev;
388}
389
390static int mlx5e_hairpin_create_transport(struct mlx5e_hairpin *hp)
391{
392 u32 in[MLX5_ST_SZ_DW(create_tir_in)] = {0};
393 void *tirc;
394 int err;
395
396 err = mlx5_core_alloc_transport_domain(hp->func_mdev, &hp->tdn);
397 if (err)
398 goto alloc_tdn_err;
399
400 tirc = MLX5_ADDR_OF(create_tir_in, in, ctx);
401
402 MLX5_SET(tirc, tirc, disp_type, MLX5_TIRC_DISP_TYPE_DIRECT);
ddae74ac 403 MLX5_SET(tirc, tirc, inline_rqn, hp->pair->rqn[0]);
77ab67b7
OG
404 MLX5_SET(tirc, tirc, transport_domain, hp->tdn);
405
406 err = mlx5_core_create_tir(hp->func_mdev, in, MLX5_ST_SZ_BYTES(create_tir_in), &hp->tirn);
407 if (err)
408 goto create_tir_err;
409
410 return 0;
411
412create_tir_err:
413 mlx5_core_dealloc_transport_domain(hp->func_mdev, hp->tdn);
414alloc_tdn_err:
415 return err;
416}
417
418static void mlx5e_hairpin_destroy_transport(struct mlx5e_hairpin *hp)
419{
420 mlx5_core_destroy_tir(hp->func_mdev, hp->tirn);
421 mlx5_core_dealloc_transport_domain(hp->func_mdev, hp->tdn);
422}
423
3f6d08d1
OG
424static void mlx5e_hairpin_fill_rqt_rqns(struct mlx5e_hairpin *hp, void *rqtc)
425{
426 u32 indirection_rqt[MLX5E_INDIR_RQT_SIZE], rqn;
427 struct mlx5e_priv *priv = hp->func_priv;
428 int i, ix, sz = MLX5E_INDIR_RQT_SIZE;
429
430 mlx5e_build_default_indir_rqt(indirection_rqt, sz,
431 hp->num_channels);
432
433 for (i = 0; i < sz; i++) {
434 ix = i;
bbeb53b8 435 if (priv->rss_params.hfunc == ETH_RSS_HASH_XOR)
3f6d08d1
OG
436 ix = mlx5e_bits_invert(i, ilog2(sz));
437 ix = indirection_rqt[ix];
438 rqn = hp->pair->rqn[ix];
439 MLX5_SET(rqtc, rqtc, rq_num[i], rqn);
440 }
441}
442
443static int mlx5e_hairpin_create_indirect_rqt(struct mlx5e_hairpin *hp)
444{
445 int inlen, err, sz = MLX5E_INDIR_RQT_SIZE;
446 struct mlx5e_priv *priv = hp->func_priv;
447 struct mlx5_core_dev *mdev = priv->mdev;
448 void *rqtc;
449 u32 *in;
450
451 inlen = MLX5_ST_SZ_BYTES(create_rqt_in) + sizeof(u32) * sz;
452 in = kvzalloc(inlen, GFP_KERNEL);
453 if (!in)
454 return -ENOMEM;
455
456 rqtc = MLX5_ADDR_OF(create_rqt_in, in, rqt_context);
457
458 MLX5_SET(rqtc, rqtc, rqt_actual_size, sz);
459 MLX5_SET(rqtc, rqtc, rqt_max_size, sz);
460
461 mlx5e_hairpin_fill_rqt_rqns(hp, rqtc);
462
463 err = mlx5_core_create_rqt(mdev, in, inlen, &hp->indir_rqt.rqtn);
464 if (!err)
465 hp->indir_rqt.enabled = true;
466
467 kvfree(in);
468 return err;
469}
470
471static int mlx5e_hairpin_create_indirect_tirs(struct mlx5e_hairpin *hp)
472{
473 struct mlx5e_priv *priv = hp->func_priv;
474 u32 in[MLX5_ST_SZ_DW(create_tir_in)];
475 int tt, i, err;
476 void *tirc;
477
478 for (tt = 0; tt < MLX5E_NUM_INDIR_TIRS; tt++) {
d930ac79
AL
479 struct mlx5e_tirc_config ttconfig = mlx5e_tirc_get_default_config(tt);
480
3f6d08d1
OG
481 memset(in, 0, MLX5_ST_SZ_BYTES(create_tir_in));
482 tirc = MLX5_ADDR_OF(create_tir_in, in, ctx);
483
484 MLX5_SET(tirc, tirc, transport_domain, hp->tdn);
485 MLX5_SET(tirc, tirc, disp_type, MLX5_TIRC_DISP_TYPE_INDIRECT);
486 MLX5_SET(tirc, tirc, indirect_table, hp->indir_rqt.rqtn);
bbeb53b8
AL
487 mlx5e_build_indir_tir_ctx_hash(&priv->rss_params, &ttconfig, tirc, false);
488
3f6d08d1
OG
489 err = mlx5_core_create_tir(hp->func_mdev, in,
490 MLX5_ST_SZ_BYTES(create_tir_in), &hp->indir_tirn[tt]);
491 if (err) {
492 mlx5_core_warn(hp->func_mdev, "create indirect tirs failed, %d\n", err);
493 goto err_destroy_tirs;
494 }
495 }
496 return 0;
497
498err_destroy_tirs:
499 for (i = 0; i < tt; i++)
500 mlx5_core_destroy_tir(hp->func_mdev, hp->indir_tirn[i]);
501 return err;
502}
503
504static void mlx5e_hairpin_destroy_indirect_tirs(struct mlx5e_hairpin *hp)
505{
506 int tt;
507
508 for (tt = 0; tt < MLX5E_NUM_INDIR_TIRS; tt++)
509 mlx5_core_destroy_tir(hp->func_mdev, hp->indir_tirn[tt]);
510}
511
512static void mlx5e_hairpin_set_ttc_params(struct mlx5e_hairpin *hp,
513 struct ttc_params *ttc_params)
514{
515 struct mlx5_flow_table_attr *ft_attr = &ttc_params->ft_attr;
516 int tt;
517
518 memset(ttc_params, 0, sizeof(*ttc_params));
519
520 ttc_params->any_tt_tirn = hp->tirn;
521
522 for (tt = 0; tt < MLX5E_NUM_INDIR_TIRS; tt++)
523 ttc_params->indir_tirn[tt] = hp->indir_tirn[tt];
524
525 ft_attr->max_fte = MLX5E_NUM_TT;
526 ft_attr->level = MLX5E_TC_TTC_FT_LEVEL;
527 ft_attr->prio = MLX5E_TC_PRIO;
528}
529
530static int mlx5e_hairpin_rss_init(struct mlx5e_hairpin *hp)
531{
532 struct mlx5e_priv *priv = hp->func_priv;
533 struct ttc_params ttc_params;
534 int err;
535
536 err = mlx5e_hairpin_create_indirect_rqt(hp);
537 if (err)
538 return err;
539
540 err = mlx5e_hairpin_create_indirect_tirs(hp);
541 if (err)
542 goto err_create_indirect_tirs;
543
544 mlx5e_hairpin_set_ttc_params(hp, &ttc_params);
545 err = mlx5e_create_ttc_table(priv, &ttc_params, &hp->ttc);
546 if (err)
547 goto err_create_ttc_table;
548
549 netdev_dbg(priv->netdev, "add hairpin: using %d channels rss ttc table id %x\n",
550 hp->num_channels, hp->ttc.ft.t->id);
551
552 return 0;
553
554err_create_ttc_table:
555 mlx5e_hairpin_destroy_indirect_tirs(hp);
556err_create_indirect_tirs:
557 mlx5e_destroy_rqt(priv, &hp->indir_rqt);
558
559 return err;
560}
561
562static void mlx5e_hairpin_rss_cleanup(struct mlx5e_hairpin *hp)
563{
564 struct mlx5e_priv *priv = hp->func_priv;
565
566 mlx5e_destroy_ttc_table(priv, &hp->ttc);
567 mlx5e_hairpin_destroy_indirect_tirs(hp);
568 mlx5e_destroy_rqt(priv, &hp->indir_rqt);
569}
570
77ab67b7
OG
571static struct mlx5e_hairpin *
572mlx5e_hairpin_create(struct mlx5e_priv *priv, struct mlx5_hairpin_params *params,
573 int peer_ifindex)
574{
575 struct mlx5_core_dev *func_mdev, *peer_mdev;
576 struct mlx5e_hairpin *hp;
577 struct mlx5_hairpin *pair;
578 int err;
579
580 hp = kzalloc(sizeof(*hp), GFP_KERNEL);
581 if (!hp)
582 return ERR_PTR(-ENOMEM);
583
584 func_mdev = priv->mdev;
585 peer_mdev = mlx5e_hairpin_get_mdev(dev_net(priv->netdev), peer_ifindex);
586
587 pair = mlx5_core_hairpin_create(func_mdev, peer_mdev, params);
588 if (IS_ERR(pair)) {
589 err = PTR_ERR(pair);
590 goto create_pair_err;
591 }
592 hp->pair = pair;
593 hp->func_mdev = func_mdev;
3f6d08d1
OG
594 hp->func_priv = priv;
595 hp->num_channels = params->num_channels;
77ab67b7
OG
596
597 err = mlx5e_hairpin_create_transport(hp);
598 if (err)
599 goto create_transport_err;
600
3f6d08d1
OG
601 if (hp->num_channels > 1) {
602 err = mlx5e_hairpin_rss_init(hp);
603 if (err)
604 goto rss_init_err;
605 }
606
77ab67b7
OG
607 return hp;
608
3f6d08d1
OG
609rss_init_err:
610 mlx5e_hairpin_destroy_transport(hp);
77ab67b7
OG
611create_transport_err:
612 mlx5_core_hairpin_destroy(hp->pair);
613create_pair_err:
614 kfree(hp);
615 return ERR_PTR(err);
616}
617
618static void mlx5e_hairpin_destroy(struct mlx5e_hairpin *hp)
619{
3f6d08d1
OG
620 if (hp->num_channels > 1)
621 mlx5e_hairpin_rss_cleanup(hp);
77ab67b7
OG
622 mlx5e_hairpin_destroy_transport(hp);
623 mlx5_core_hairpin_destroy(hp->pair);
624 kvfree(hp);
625}
626
106be53b
OG
627static inline u32 hash_hairpin_info(u16 peer_vhca_id, u8 prio)
628{
629 return (peer_vhca_id << 16 | prio);
630}
631
5c65c564 632static struct mlx5e_hairpin_entry *mlx5e_hairpin_get(struct mlx5e_priv *priv,
106be53b 633 u16 peer_vhca_id, u8 prio)
5c65c564
OG
634{
635 struct mlx5e_hairpin_entry *hpe;
106be53b 636 u32 hash_key = hash_hairpin_info(peer_vhca_id, prio);
5c65c564
OG
637
638 hash_for_each_possible(priv->fs.tc.hairpin_tbl, hpe,
106be53b 639 hairpin_hlist, hash_key) {
e4f9abbd
VB
640 if (hpe->peer_vhca_id == peer_vhca_id && hpe->prio == prio) {
641 refcount_inc(&hpe->refcnt);
5c65c564 642 return hpe;
e4f9abbd 643 }
5c65c564
OG
644 }
645
646 return NULL;
647}
648
e4f9abbd
VB
649static void mlx5e_hairpin_put(struct mlx5e_priv *priv,
650 struct mlx5e_hairpin_entry *hpe)
651{
652 /* no more hairpin flows for us, release the hairpin pair */
653 if (!refcount_dec_and_test(&hpe->refcnt))
654 return;
655
656 netdev_dbg(priv->netdev, "del hairpin: peer %s\n",
657 dev_name(hpe->hp->pair->peer_mdev->device));
658
659 WARN_ON(!list_empty(&hpe->flows));
660 mlx5e_hairpin_destroy(hpe->hp);
661 hash_del(&hpe->hairpin_hlist);
662 kfree(hpe);
663}
664
106be53b
OG
665#define UNKNOWN_MATCH_PRIO 8
666
667static int mlx5e_hairpin_get_prio(struct mlx5e_priv *priv,
e98bedf5
EB
668 struct mlx5_flow_spec *spec, u8 *match_prio,
669 struct netlink_ext_ack *extack)
106be53b
OG
670{
671 void *headers_c, *headers_v;
672 u8 prio_val, prio_mask = 0;
673 bool vlan_present;
674
675#ifdef CONFIG_MLX5_CORE_EN_DCB
676 if (priv->dcbx_dp.trust_state != MLX5_QPTS_TRUST_PCP) {
e98bedf5
EB
677 NL_SET_ERR_MSG_MOD(extack,
678 "only PCP trust state supported for hairpin");
106be53b
OG
679 return -EOPNOTSUPP;
680 }
681#endif
682 headers_c = MLX5_ADDR_OF(fte_match_param, spec->match_criteria, outer_headers);
683 headers_v = MLX5_ADDR_OF(fte_match_param, spec->match_value, outer_headers);
684
685 vlan_present = MLX5_GET(fte_match_set_lyr_2_4, headers_v, cvlan_tag);
686 if (vlan_present) {
687 prio_mask = MLX5_GET(fte_match_set_lyr_2_4, headers_c, first_prio);
688 prio_val = MLX5_GET(fte_match_set_lyr_2_4, headers_v, first_prio);
689 }
690
691 if (!vlan_present || !prio_mask) {
692 prio_val = UNKNOWN_MATCH_PRIO;
693 } else if (prio_mask != 0x7) {
e98bedf5
EB
694 NL_SET_ERR_MSG_MOD(extack,
695 "masked priority match not supported for hairpin");
106be53b
OG
696 return -EOPNOTSUPP;
697 }
698
699 *match_prio = prio_val;
700 return 0;
701}
702
5c65c564
OG
703static int mlx5e_hairpin_flow_add(struct mlx5e_priv *priv,
704 struct mlx5e_tc_flow *flow,
e98bedf5
EB
705 struct mlx5e_tc_flow_parse_attr *parse_attr,
706 struct netlink_ext_ack *extack)
5c65c564 707{
98b66cb1 708 int peer_ifindex = parse_attr->mirred_ifindex[0];
5c65c564 709 struct mlx5_hairpin_params params;
d8822868 710 struct mlx5_core_dev *peer_mdev;
5c65c564
OG
711 struct mlx5e_hairpin_entry *hpe;
712 struct mlx5e_hairpin *hp;
3f6d08d1
OG
713 u64 link_speed64;
714 u32 link_speed;
106be53b 715 u8 match_prio;
d8822868 716 u16 peer_id;
5c65c564
OG
717 int err;
718
d8822868
OG
719 peer_mdev = mlx5e_hairpin_get_mdev(dev_net(priv->netdev), peer_ifindex);
720 if (!MLX5_CAP_GEN(priv->mdev, hairpin) || !MLX5_CAP_GEN(peer_mdev, hairpin)) {
e98bedf5 721 NL_SET_ERR_MSG_MOD(extack, "hairpin is not supported");
5c65c564
OG
722 return -EOPNOTSUPP;
723 }
724
d8822868 725 peer_id = MLX5_CAP_GEN(peer_mdev, vhca_id);
e98bedf5
EB
726 err = mlx5e_hairpin_get_prio(priv, &parse_attr->spec, &match_prio,
727 extack);
106be53b
OG
728 if (err)
729 return err;
730 hpe = mlx5e_hairpin_get(priv, peer_id, match_prio);
5c65c564
OG
731 if (hpe)
732 goto attach_flow;
733
734 hpe = kzalloc(sizeof(*hpe), GFP_KERNEL);
735 if (!hpe)
736 return -ENOMEM;
737
738 INIT_LIST_HEAD(&hpe->flows);
d8822868 739 hpe->peer_vhca_id = peer_id;
106be53b 740 hpe->prio = match_prio;
e4f9abbd 741 refcount_set(&hpe->refcnt, 1);
5c65c564
OG
742
743 params.log_data_size = 15;
744 params.log_data_size = min_t(u8, params.log_data_size,
745 MLX5_CAP_GEN(priv->mdev, log_max_hairpin_wq_data_sz));
746 params.log_data_size = max_t(u8, params.log_data_size,
747 MLX5_CAP_GEN(priv->mdev, log_min_hairpin_wq_data_sz));
5c65c564 748
eb9180f7
OG
749 params.log_num_packets = params.log_data_size -
750 MLX5_MPWRQ_MIN_LOG_STRIDE_SZ(priv->mdev);
751 params.log_num_packets = min_t(u8, params.log_num_packets,
752 MLX5_CAP_GEN(priv->mdev, log_max_hairpin_num_packets));
753
754 params.q_counter = priv->q_counter;
3f6d08d1 755 /* set hairpin pair per each 50Gbs share of the link */
2c81bfd5 756 mlx5e_port_max_linkspeed(priv->mdev, &link_speed);
3f6d08d1
OG
757 link_speed = max_t(u32, link_speed, 50000);
758 link_speed64 = link_speed;
759 do_div(link_speed64, 50000);
760 params.num_channels = link_speed64;
761
5c65c564
OG
762 hp = mlx5e_hairpin_create(priv, &params, peer_ifindex);
763 if (IS_ERR(hp)) {
764 err = PTR_ERR(hp);
765 goto create_hairpin_err;
766 }
767
eb9180f7 768 netdev_dbg(priv->netdev, "add hairpin: tirn %x rqn %x peer %s sqn %x prio %d (log) data %d packets %d\n",
27b942fb
PP
769 hp->tirn, hp->pair->rqn[0],
770 dev_name(hp->pair->peer_mdev->device),
eb9180f7 771 hp->pair->sqn[0], match_prio, params.log_data_size, params.log_num_packets);
5c65c564
OG
772
773 hpe->hp = hp;
106be53b
OG
774 hash_add(priv->fs.tc.hairpin_tbl, &hpe->hairpin_hlist,
775 hash_hairpin_info(peer_id, match_prio));
5c65c564
OG
776
777attach_flow:
3f6d08d1 778 if (hpe->hp->num_channels > 1) {
226f2ca3 779 flow_flag_set(flow, HAIRPIN_RSS);
3f6d08d1
OG
780 flow->nic_attr->hairpin_ft = hpe->hp->ttc.ft.t;
781 } else {
782 flow->nic_attr->hairpin_tirn = hpe->hp->tirn;
783 }
e4f9abbd 784 flow->hpe = hpe;
5c65c564 785 list_add(&flow->hairpin, &hpe->flows);
3f6d08d1 786
5c65c564
OG
787 return 0;
788
789create_hairpin_err:
790 kfree(hpe);
791 return err;
792}
793
794static void mlx5e_hairpin_flow_del(struct mlx5e_priv *priv,
795 struct mlx5e_tc_flow *flow)
796{
5a7e5bcb 797 /* flow wasn't fully initialized */
e4f9abbd 798 if (!flow->hpe)
5a7e5bcb
VB
799 return;
800
5c65c564 801 list_del(&flow->hairpin);
e4f9abbd
VB
802 mlx5e_hairpin_put(priv, flow->hpe);
803 flow->hpe = NULL;
5c65c564
OG
804}
805
c83954ab 806static int
74491de9 807mlx5e_tc_add_nic_flow(struct mlx5e_priv *priv,
17091853 808 struct mlx5e_tc_flow_parse_attr *parse_attr,
e98bedf5
EB
809 struct mlx5e_tc_flow *flow,
810 struct netlink_ext_ack *extack)
e8f887ac 811{
bb0ee7dc 812 struct mlx5_flow_context *flow_context = &parse_attr->spec.flow_context;
aa0cbbae 813 struct mlx5_nic_flow_attr *attr = flow->nic_attr;
aad7e08d 814 struct mlx5_core_dev *dev = priv->mdev;
5c65c564 815 struct mlx5_flow_destination dest[2] = {};
66958ed9 816 struct mlx5_flow_act flow_act = {
3bc4b7bf 817 .action = attr->action,
60786f09 818 .reformat_id = 0,
bb0ee7dc 819 .flags = FLOW_ACT_NO_APPEND,
66958ed9 820 };
aad7e08d 821 struct mlx5_fc *counter = NULL;
5c65c564 822 int err, dest_ix = 0;
e8f887ac 823
bb0ee7dc
JL
824 flow_context->flags |= FLOW_CONTEXT_HAS_TAG;
825 flow_context->flow_tag = attr->flow_tag;
826
226f2ca3 827 if (flow_flag_test(flow, HAIRPIN)) {
e98bedf5 828 err = mlx5e_hairpin_flow_add(priv, flow, parse_attr, extack);
5a7e5bcb
VB
829 if (err)
830 return err;
831
226f2ca3 832 if (flow_flag_test(flow, HAIRPIN_RSS)) {
3f6d08d1
OG
833 dest[dest_ix].type = MLX5_FLOW_DESTINATION_TYPE_FLOW_TABLE;
834 dest[dest_ix].ft = attr->hairpin_ft;
835 } else {
5c65c564
OG
836 dest[dest_ix].type = MLX5_FLOW_DESTINATION_TYPE_TIR;
837 dest[dest_ix].tir_num = attr->hairpin_tirn;
5c65c564
OG
838 }
839 dest_ix++;
3f6d08d1
OG
840 } else if (attr->action & MLX5_FLOW_CONTEXT_ACTION_FWD_DEST) {
841 dest[dest_ix].type = MLX5_FLOW_DESTINATION_TYPE_FLOW_TABLE;
842 dest[dest_ix].ft = priv->fs.vlan.ft.t;
843 dest_ix++;
5c65c564 844 }
aad7e08d 845
5c65c564
OG
846 if (attr->action & MLX5_FLOW_CONTEXT_ACTION_COUNT) {
847 counter = mlx5_fc_create(dev, true);
5a7e5bcb
VB
848 if (IS_ERR(counter))
849 return PTR_ERR(counter);
850
5c65c564 851 dest[dest_ix].type = MLX5_FLOW_DESTINATION_TYPE_COUNTER;
171c7625 852 dest[dest_ix].counter_id = mlx5_fc_id(counter);
5c65c564 853 dest_ix++;
b8aee822 854 attr->counter = counter;
aad7e08d
AV
855 }
856
2f4fe4ca 857 if (attr->action & MLX5_FLOW_CONTEXT_ACTION_MOD_HDR) {
3099eb5a 858 err = mlx5e_attach_mod_hdr(priv, flow, parse_attr);
d7e75a32 859 flow_act.modify_id = attr->mod_hdr_id;
2f4fe4ca 860 kfree(parse_attr->mod_hdr_actions);
c83954ab 861 if (err)
5a7e5bcb 862 return err;
2f4fe4ca
OG
863 }
864
b6fac0b4 865 mutex_lock(&priv->fs.tc.t_lock);
acff797c 866 if (IS_ERR_OR_NULL(priv->fs.tc.t)) {
21b9c144
OG
867 int tc_grp_size, tc_tbl_size;
868 u32 max_flow_counter;
869
870 max_flow_counter = (MLX5_CAP_GEN(dev, max_flow_counter_31_16) << 16) |
871 MLX5_CAP_GEN(dev, max_flow_counter_15_0);
872
873 tc_grp_size = min_t(int, max_flow_counter, MLX5E_TC_TABLE_MAX_GROUP_SIZE);
874
875 tc_tbl_size = min_t(int, tc_grp_size * MLX5E_TC_TABLE_NUM_GROUPS,
876 BIT(MLX5_CAP_FLOWTABLE_NIC_RX(dev, log_max_ft_size)));
877
acff797c
MG
878 priv->fs.tc.t =
879 mlx5_create_auto_grouped_flow_table(priv->fs.ns,
880 MLX5E_TC_PRIO,
21b9c144 881 tc_tbl_size,
acff797c 882 MLX5E_TC_TABLE_NUM_GROUPS,
3f6d08d1 883 MLX5E_TC_FT_LEVEL, 0);
acff797c 884 if (IS_ERR(priv->fs.tc.t)) {
b6fac0b4 885 mutex_unlock(&priv->fs.tc.t_lock);
e98bedf5
EB
886 NL_SET_ERR_MSG_MOD(extack,
887 "Failed to create tc offload table\n");
e8f887ac
AV
888 netdev_err(priv->netdev,
889 "Failed to create tc offload table\n");
5a7e5bcb 890 return PTR_ERR(priv->fs.tc.t);
e8f887ac 891 }
e8f887ac
AV
892 }
893
38aa51c1 894 if (attr->match_level != MLX5_MATCH_NONE)
d4a18e16 895 parse_attr->spec.match_criteria_enable |= MLX5_MATCH_OUTER_HEADERS;
38aa51c1 896
c83954ab
RL
897 flow->rule[0] = mlx5_add_flow_rules(priv->fs.tc.t, &parse_attr->spec,
898 &flow_act, dest, dest_ix);
b6fac0b4 899 mutex_unlock(&priv->fs.tc.t_lock);
aad7e08d 900
5a7e5bcb
VB
901 if (IS_ERR(flow->rule[0]))
902 return PTR_ERR(flow->rule[0]);
aad7e08d 903
c83954ab 904 return 0;
e8f887ac
AV
905}
906
d85cdccb
OG
907static void mlx5e_tc_del_nic_flow(struct mlx5e_priv *priv,
908 struct mlx5e_tc_flow *flow)
909{
513f8f7f 910 struct mlx5_nic_flow_attr *attr = flow->nic_attr;
d85cdccb
OG
911 struct mlx5_fc *counter = NULL;
912
b8aee822 913 counter = attr->counter;
5a7e5bcb
VB
914 if (!IS_ERR_OR_NULL(flow->rule[0]))
915 mlx5_del_flow_rules(flow->rule[0]);
aa0cbbae 916 mlx5_fc_destroy(priv->mdev, counter);
d85cdccb 917
b6fac0b4 918 mutex_lock(&priv->fs.tc.t_lock);
226f2ca3 919 if (!mlx5e_tc_num_filters(priv, MLX5_TC_FLAG(NIC_OFFLOAD)) && priv->fs.tc.t) {
d85cdccb
OG
920 mlx5_destroy_flow_table(priv->fs.tc.t);
921 priv->fs.tc.t = NULL;
922 }
b6fac0b4 923 mutex_unlock(&priv->fs.tc.t_lock);
2f4fe4ca 924
513f8f7f 925 if (attr->action & MLX5_FLOW_CONTEXT_ACTION_MOD_HDR)
3099eb5a 926 mlx5e_detach_mod_hdr(priv, flow);
5c65c564 927
226f2ca3 928 if (flow_flag_test(flow, HAIRPIN))
5c65c564 929 mlx5e_hairpin_flow_del(priv, flow);
d85cdccb
OG
930}
931
aa0cbbae 932static void mlx5e_detach_encap(struct mlx5e_priv *priv,
8c4dc42b 933 struct mlx5e_tc_flow *flow, int out_index);
aa0cbbae 934
3c37745e 935static int mlx5e_attach_encap(struct mlx5e_priv *priv,
e98bedf5 936 struct mlx5e_tc_flow *flow,
733d4f36
RD
937 struct net_device *mirred_dev,
938 int out_index,
8c4dc42b 939 struct netlink_ext_ack *extack,
0ad060ee
RD
940 struct net_device **encap_dev,
941 bool *encap_valid);
3c37745e 942
6d2a3ed0
OG
943static struct mlx5_flow_handle *
944mlx5e_tc_offload_fdb_rules(struct mlx5_eswitch *esw,
945 struct mlx5e_tc_flow *flow,
946 struct mlx5_flow_spec *spec,
947 struct mlx5_esw_flow_attr *attr)
948{
949 struct mlx5_flow_handle *rule;
950
951 rule = mlx5_eswitch_add_offloaded_rule(esw, spec, attr);
952 if (IS_ERR(rule))
953 return rule;
954
e85e02ba 955 if (attr->split_count) {
6d2a3ed0
OG
956 flow->rule[1] = mlx5_eswitch_add_fwd_rule(esw, spec, attr);
957 if (IS_ERR(flow->rule[1])) {
958 mlx5_eswitch_del_offloaded_rule(esw, rule, attr);
959 return flow->rule[1];
960 }
961 }
962
6d2a3ed0
OG
963 return rule;
964}
965
966static void
967mlx5e_tc_unoffload_fdb_rules(struct mlx5_eswitch *esw,
968 struct mlx5e_tc_flow *flow,
969 struct mlx5_esw_flow_attr *attr)
970{
226f2ca3 971 flow_flag_clear(flow, OFFLOADED);
6d2a3ed0 972
e85e02ba 973 if (attr->split_count)
6d2a3ed0
OG
974 mlx5_eswitch_del_fwd_rule(esw, flow->rule[1], attr);
975
976 mlx5_eswitch_del_offloaded_rule(esw, flow->rule[0], attr);
977}
978
5dbe906f
PB
979static struct mlx5_flow_handle *
980mlx5e_tc_offload_to_slow_path(struct mlx5_eswitch *esw,
981 struct mlx5e_tc_flow *flow,
982 struct mlx5_flow_spec *spec,
983 struct mlx5_esw_flow_attr *slow_attr)
984{
985 struct mlx5_flow_handle *rule;
986
987 memcpy(slow_attr, flow->esw_attr, sizeof(*slow_attr));
154e62ab 988 slow_attr->action = MLX5_FLOW_CONTEXT_ACTION_FWD_DEST;
2be09de7 989 slow_attr->split_count = 0;
154e62ab 990 slow_attr->dest_chain = FDB_SLOW_PATH_CHAIN;
5dbe906f
PB
991
992 rule = mlx5e_tc_offload_fdb_rules(esw, flow, spec, slow_attr);
993 if (!IS_ERR(rule))
226f2ca3 994 flow_flag_set(flow, SLOW);
5dbe906f
PB
995
996 return rule;
997}
998
999static void
1000mlx5e_tc_unoffload_from_slow_path(struct mlx5_eswitch *esw,
1001 struct mlx5e_tc_flow *flow,
1002 struct mlx5_esw_flow_attr *slow_attr)
1003{
1004 memcpy(slow_attr, flow->esw_attr, sizeof(*slow_attr));
154e62ab 1005 slow_attr->action = MLX5_FLOW_CONTEXT_ACTION_FWD_DEST;
2be09de7 1006 slow_attr->split_count = 0;
154e62ab 1007 slow_attr->dest_chain = FDB_SLOW_PATH_CHAIN;
5dbe906f 1008 mlx5e_tc_unoffload_fdb_rules(esw, flow, slow_attr);
226f2ca3 1009 flow_flag_clear(flow, SLOW);
5dbe906f
PB
1010}
1011
ad86755b
VB
1012/* Caller must obtain uplink_priv->unready_flows_lock mutex before calling this
1013 * function.
1014 */
1015static void unready_flow_add(struct mlx5e_tc_flow *flow,
1016 struct list_head *unready_flows)
1017{
1018 flow_flag_set(flow, NOT_READY);
1019 list_add_tail(&flow->unready, unready_flows);
1020}
1021
1022/* Caller must obtain uplink_priv->unready_flows_lock mutex before calling this
1023 * function.
1024 */
1025static void unready_flow_del(struct mlx5e_tc_flow *flow)
1026{
1027 list_del(&flow->unready);
1028 flow_flag_clear(flow, NOT_READY);
1029}
1030
b4a23329
RD
1031static void add_unready_flow(struct mlx5e_tc_flow *flow)
1032{
1033 struct mlx5_rep_uplink_priv *uplink_priv;
1034 struct mlx5e_rep_priv *rpriv;
1035 struct mlx5_eswitch *esw;
1036
1037 esw = flow->priv->mdev->priv.eswitch;
1038 rpriv = mlx5_eswitch_get_uplink_priv(esw, REP_ETH);
1039 uplink_priv = &rpriv->uplink_priv;
1040
ad86755b
VB
1041 mutex_lock(&uplink_priv->unready_flows_lock);
1042 unready_flow_add(flow, &uplink_priv->unready_flows);
1043 mutex_unlock(&uplink_priv->unready_flows_lock);
b4a23329
RD
1044}
1045
1046static void remove_unready_flow(struct mlx5e_tc_flow *flow)
1047{
ad86755b
VB
1048 struct mlx5_rep_uplink_priv *uplink_priv;
1049 struct mlx5e_rep_priv *rpriv;
1050 struct mlx5_eswitch *esw;
1051
1052 esw = flow->priv->mdev->priv.eswitch;
1053 rpriv = mlx5_eswitch_get_uplink_priv(esw, REP_ETH);
1054 uplink_priv = &rpriv->uplink_priv;
1055
1056 mutex_lock(&uplink_priv->unready_flows_lock);
1057 unready_flow_del(flow);
1058 mutex_unlock(&uplink_priv->unready_flows_lock);
b4a23329
RD
1059}
1060
c83954ab 1061static int
74491de9 1062mlx5e_tc_add_fdb_flow(struct mlx5e_priv *priv,
e98bedf5
EB
1063 struct mlx5e_tc_flow *flow,
1064 struct netlink_ext_ack *extack)
adb4c123
OG
1065{
1066 struct mlx5_eswitch *esw = priv->mdev->priv.eswitch;
bf07aa73 1067 u32 max_chain = mlx5_eswitch_get_chain_range(esw);
aa0cbbae 1068 struct mlx5_esw_flow_attr *attr = flow->esw_attr;
7040632d 1069 struct mlx5e_tc_flow_parse_attr *parse_attr = attr->parse_attr;
bf07aa73 1070 u16 max_prio = mlx5_eswitch_get_prio_range(esw);
3c37745e 1071 struct net_device *out_dev, *encap_dev = NULL;
b8aee822 1072 struct mlx5_fc *counter = NULL;
3c37745e
OG
1073 struct mlx5e_rep_priv *rpriv;
1074 struct mlx5e_priv *out_priv;
0ad060ee
RD
1075 bool encap_valid = true;
1076 int err = 0;
f493f155 1077 int out_index;
8b32580d 1078
d14f6f2a
OG
1079 if (!mlx5_eswitch_prios_supported(esw) && attr->prio != 1) {
1080 NL_SET_ERR_MSG(extack, "E-switch priorities unsupported, upgrade FW");
1081 return -EOPNOTSUPP;
1082 }
bf07aa73
PB
1083
1084 if (attr->chain > max_chain) {
1085 NL_SET_ERR_MSG(extack, "Requested chain is out of supported range");
5a7e5bcb 1086 return -EOPNOTSUPP;
bf07aa73
PB
1087 }
1088
1089 if (attr->prio > max_prio) {
1090 NL_SET_ERR_MSG(extack, "Requested priority is out of supported range");
5a7e5bcb 1091 return -EOPNOTSUPP;
bf07aa73 1092 }
e52c2802 1093
f493f155 1094 for (out_index = 0; out_index < MLX5_MAX_FLOW_FWD_VPORTS; out_index++) {
8c4dc42b
EB
1095 int mirred_ifindex;
1096
f493f155
EB
1097 if (!(attr->dests[out_index].flags & MLX5_ESW_DEST_ENCAP))
1098 continue;
1099
7040632d 1100 mirred_ifindex = parse_attr->mirred_ifindex[out_index];
3c37745e 1101 out_dev = __dev_get_by_index(dev_net(priv->netdev),
8c4dc42b 1102 mirred_ifindex);
733d4f36 1103 err = mlx5e_attach_encap(priv, flow, out_dev, out_index,
0ad060ee
RD
1104 extack, &encap_dev, &encap_valid);
1105 if (err)
5a7e5bcb 1106 return err;
0ad060ee 1107
3c37745e
OG
1108 out_priv = netdev_priv(encap_dev);
1109 rpriv = out_priv->ppriv;
1cc26d74
EB
1110 attr->dests[out_index].rep = rpriv->rep;
1111 attr->dests[out_index].mdev = out_priv->mdev;
3c37745e
OG
1112 }
1113
8b32580d 1114 err = mlx5_eswitch_add_vlan_action(esw, attr);
c83954ab 1115 if (err)
5a7e5bcb 1116 return err;
adb4c123 1117
d7e75a32 1118 if (attr->action & MLX5_FLOW_CONTEXT_ACTION_MOD_HDR) {
1a9527bb 1119 err = mlx5e_attach_mod_hdr(priv, flow, parse_attr);
d7e75a32 1120 kfree(parse_attr->mod_hdr_actions);
c83954ab 1121 if (err)
5a7e5bcb 1122 return err;
d7e75a32
OG
1123 }
1124
b8aee822 1125 if (attr->action & MLX5_FLOW_CONTEXT_ACTION_COUNT) {
f9392795 1126 counter = mlx5_fc_create(attr->counter_dev, true);
5a7e5bcb
VB
1127 if (IS_ERR(counter))
1128 return PTR_ERR(counter);
b8aee822
MB
1129
1130 attr->counter = counter;
1131 }
1132
0ad060ee
RD
1133 /* we get here if one of the following takes place:
1134 * (1) there's no error
1135 * (2) there's an encap action and we don't have valid neigh
3c37745e 1136 */
0ad060ee 1137 if (!encap_valid) {
5dbe906f
PB
1138 /* continue with goto slow path rule instead */
1139 struct mlx5_esw_flow_attr slow_attr;
1140
1141 flow->rule[0] = mlx5e_tc_offload_to_slow_path(esw, flow, &parse_attr->spec, &slow_attr);
1142 } else {
6d2a3ed0 1143 flow->rule[0] = mlx5e_tc_offload_fdb_rules(esw, flow, &parse_attr->spec, attr);
3c37745e 1144 }
c83954ab 1145
5a7e5bcb
VB
1146 if (IS_ERR(flow->rule[0]))
1147 return PTR_ERR(flow->rule[0]);
226f2ca3
VB
1148 else
1149 flow_flag_set(flow, OFFLOADED);
5dbe906f
PB
1150
1151 return 0;
aa0cbbae 1152}
d85cdccb 1153
9272e3df
YK
1154static bool mlx5_flow_has_geneve_opt(struct mlx5e_tc_flow *flow)
1155{
1156 struct mlx5_flow_spec *spec = &flow->esw_attr->parse_attr->spec;
1157 void *headers_v = MLX5_ADDR_OF(fte_match_param,
1158 spec->match_value,
1159 misc_parameters_3);
1160 u32 geneve_tlv_opt_0_data = MLX5_GET(fte_match_set_misc3,
1161 headers_v,
1162 geneve_tlv_option_0_data);
1163
1164 return !!geneve_tlv_opt_0_data;
1165}
1166
d85cdccb
OG
1167static void mlx5e_tc_del_fdb_flow(struct mlx5e_priv *priv,
1168 struct mlx5e_tc_flow *flow)
1169{
1170 struct mlx5_eswitch *esw = priv->mdev->priv.eswitch;
d7e75a32 1171 struct mlx5_esw_flow_attr *attr = flow->esw_attr;
5dbe906f 1172 struct mlx5_esw_flow_attr slow_attr;
f493f155 1173 int out_index;
d85cdccb 1174
226f2ca3 1175 if (flow_flag_test(flow, NOT_READY)) {
b4a23329 1176 remove_unready_flow(flow);
ef06c9ee
RD
1177 kvfree(attr->parse_attr);
1178 return;
1179 }
1180
226f2ca3
VB
1181 if (mlx5e_is_offloaded_flow(flow)) {
1182 if (flow_flag_test(flow, SLOW))
5dbe906f
PB
1183 mlx5e_tc_unoffload_from_slow_path(esw, flow, &slow_attr);
1184 else
1185 mlx5e_tc_unoffload_fdb_rules(esw, flow, attr);
1186 }
d85cdccb 1187
9272e3df
YK
1188 if (mlx5_flow_has_geneve_opt(flow))
1189 mlx5_geneve_tlv_option_del(priv->mdev->geneve);
1190
513f8f7f 1191 mlx5_eswitch_del_vlan_action(esw, attr);
d85cdccb 1192
f493f155 1193 for (out_index = 0; out_index < MLX5_MAX_FLOW_FWD_VPORTS; out_index++)
8c4dc42b
EB
1194 if (attr->dests[out_index].flags & MLX5_ESW_DEST_ENCAP)
1195 mlx5e_detach_encap(priv, flow, out_index);
f493f155 1196 kvfree(attr->parse_attr);
d7e75a32 1197
513f8f7f 1198 if (attr->action & MLX5_FLOW_CONTEXT_ACTION_MOD_HDR)
1a9527bb 1199 mlx5e_detach_mod_hdr(priv, flow);
b8aee822
MB
1200
1201 if (attr->action & MLX5_FLOW_CONTEXT_ACTION_COUNT)
f9392795 1202 mlx5_fc_destroy(attr->counter_dev, attr->counter);
d85cdccb
OG
1203}
1204
232c0013
HHZ
1205void mlx5e_tc_encap_flows_add(struct mlx5e_priv *priv,
1206 struct mlx5e_encap_entry *e)
1207{
3c37745e 1208 struct mlx5_eswitch *esw = priv->mdev->priv.eswitch;
5dbe906f 1209 struct mlx5_esw_flow_attr slow_attr, *esw_attr;
5a7e5bcb 1210 struct encap_flow_item *efi, *tmp;
6d2a3ed0
OG
1211 struct mlx5_flow_handle *rule;
1212 struct mlx5_flow_spec *spec;
232c0013
HHZ
1213 struct mlx5e_tc_flow *flow;
1214 int err;
1215
54c177ca
OS
1216 err = mlx5_packet_reformat_alloc(priv->mdev,
1217 e->reformat_type,
60786f09 1218 e->encap_size, e->encap_header,
31ca3648 1219 MLX5_FLOW_NAMESPACE_FDB,
60786f09 1220 &e->encap_id);
232c0013
HHZ
1221 if (err) {
1222 mlx5_core_warn(priv->mdev, "Failed to offload cached encapsulation header, %d\n",
1223 err);
1224 return;
1225 }
1226 e->flags |= MLX5_ENCAP_ENTRY_VALID;
f6dfb4c3 1227 mlx5e_rep_queue_neigh_stats_work(priv);
232c0013 1228
5a7e5bcb 1229 list_for_each_entry_safe(efi, tmp, &e->flows, list) {
8c4dc42b
EB
1230 bool all_flow_encaps_valid = true;
1231 int i;
1232
79baaec7 1233 flow = container_of(efi, struct mlx5e_tc_flow, encaps[efi->index]);
5a7e5bcb
VB
1234 if (IS_ERR(mlx5e_flow_get(flow)))
1235 continue;
1236
3c37745e 1237 esw_attr = flow->esw_attr;
6d2a3ed0
OG
1238 spec = &esw_attr->parse_attr->spec;
1239
8c4dc42b
EB
1240 esw_attr->dests[efi->index].encap_id = e->encap_id;
1241 esw_attr->dests[efi->index].flags |= MLX5_ESW_DEST_ENCAP_VALID;
1242 /* Flow can be associated with multiple encap entries.
1243 * Before offloading the flow verify that all of them have
1244 * a valid neighbour.
1245 */
1246 for (i = 0; i < MLX5_MAX_FLOW_FWD_VPORTS; i++) {
1247 if (!(esw_attr->dests[i].flags & MLX5_ESW_DEST_ENCAP))
1248 continue;
1249 if (!(esw_attr->dests[i].flags & MLX5_ESW_DEST_ENCAP_VALID)) {
1250 all_flow_encaps_valid = false;
1251 break;
1252 }
1253 }
1254 /* Do not offload flows with unresolved neighbors */
1255 if (!all_flow_encaps_valid)
5a7e5bcb 1256 goto loop_cont;
5dbe906f 1257 /* update from slow path rule to encap rule */
6d2a3ed0
OG
1258 rule = mlx5e_tc_offload_fdb_rules(esw, flow, spec, esw_attr);
1259 if (IS_ERR(rule)) {
1260 err = PTR_ERR(rule);
232c0013
HHZ
1261 mlx5_core_warn(priv->mdev, "Failed to update cached encapsulation flow, %d\n",
1262 err);
5a7e5bcb 1263 goto loop_cont;
232c0013 1264 }
5dbe906f
PB
1265
1266 mlx5e_tc_unoffload_from_slow_path(esw, flow, &slow_attr);
6d2a3ed0 1267 flow->rule[0] = rule;
226f2ca3
VB
1268 /* was unset when slow path rule removed */
1269 flow_flag_set(flow, OFFLOADED);
5a7e5bcb
VB
1270
1271loop_cont:
1272 mlx5e_flow_put(priv, flow);
232c0013
HHZ
1273 }
1274}
1275
1276void mlx5e_tc_encap_flows_del(struct mlx5e_priv *priv,
1277 struct mlx5e_encap_entry *e)
1278{
3c37745e 1279 struct mlx5_eswitch *esw = priv->mdev->priv.eswitch;
5dbe906f 1280 struct mlx5_esw_flow_attr slow_attr;
5a7e5bcb 1281 struct encap_flow_item *efi, *tmp;
5dbe906f
PB
1282 struct mlx5_flow_handle *rule;
1283 struct mlx5_flow_spec *spec;
232c0013 1284 struct mlx5e_tc_flow *flow;
5dbe906f 1285 int err;
232c0013 1286
5a7e5bcb 1287 list_for_each_entry_safe(efi, tmp, &e->flows, list) {
79baaec7 1288 flow = container_of(efi, struct mlx5e_tc_flow, encaps[efi->index]);
5a7e5bcb
VB
1289 if (IS_ERR(mlx5e_flow_get(flow)))
1290 continue;
1291
5dbe906f
PB
1292 spec = &flow->esw_attr->parse_attr->spec;
1293
1294 /* update from encap rule to slow path rule */
1295 rule = mlx5e_tc_offload_to_slow_path(esw, flow, spec, &slow_attr);
8c4dc42b
EB
1296 /* mark the flow's encap dest as non-valid */
1297 flow->esw_attr->dests[efi->index].flags &= ~MLX5_ESW_DEST_ENCAP_VALID;
5dbe906f
PB
1298
1299 if (IS_ERR(rule)) {
1300 err = PTR_ERR(rule);
1301 mlx5_core_warn(priv->mdev, "Failed to update slow path (encap) flow, %d\n",
1302 err);
5a7e5bcb 1303 goto loop_cont;
5dbe906f
PB
1304 }
1305
1306 mlx5e_tc_unoffload_fdb_rules(esw, flow, flow->esw_attr);
5dbe906f 1307 flow->rule[0] = rule;
226f2ca3
VB
1308 /* was unset when fast path rule removed */
1309 flow_flag_set(flow, OFFLOADED);
5a7e5bcb
VB
1310
1311loop_cont:
1312 mlx5e_flow_put(priv, flow);
232c0013
HHZ
1313 }
1314
61c806da
OG
1315 /* we know that the encap is valid */
1316 e->flags &= ~MLX5_ENCAP_ENTRY_VALID;
1317 mlx5_packet_reformat_dealloc(priv->mdev, e->encap_id);
232c0013
HHZ
1318}
1319
b8aee822
MB
1320static struct mlx5_fc *mlx5e_tc_get_counter(struct mlx5e_tc_flow *flow)
1321{
226f2ca3 1322 if (mlx5e_is_eswitch_flow(flow))
b8aee822
MB
1323 return flow->esw_attr->counter;
1324 else
1325 return flow->nic_attr->counter;
1326}
1327
f6dfb4c3
HHZ
1328void mlx5e_tc_update_neigh_used_value(struct mlx5e_neigh_hash_entry *nhe)
1329{
1330 struct mlx5e_neigh *m_neigh = &nhe->m_neigh;
f6dfb4c3
HHZ
1331 struct mlx5e_tc_flow *flow;
1332 struct mlx5e_encap_entry *e;
1333 struct mlx5_fc *counter;
1334 struct neigh_table *tbl;
1335 bool neigh_used = false;
1336 struct neighbour *n;
90bb7692 1337 u64 lastuse;
f6dfb4c3
HHZ
1338
1339 if (m_neigh->family == AF_INET)
1340 tbl = &arp_tbl;
1341#if IS_ENABLED(CONFIG_IPV6)
1342 else if (m_neigh->family == AF_INET6)
423c9db2 1343 tbl = &nd_tbl;
f6dfb4c3
HHZ
1344#endif
1345 else
1346 return;
1347
1348 list_for_each_entry(e, &nhe->encap_list, encap_list) {
5a7e5bcb 1349 struct encap_flow_item *efi, *tmp;
f6dfb4c3
HHZ
1350 if (!(e->flags & MLX5_ENCAP_ENTRY_VALID))
1351 continue;
5a7e5bcb 1352 list_for_each_entry_safe(efi, tmp, &e->flows, list) {
79baaec7
EB
1353 flow = container_of(efi, struct mlx5e_tc_flow,
1354 encaps[efi->index]);
5a7e5bcb
VB
1355 if (IS_ERR(mlx5e_flow_get(flow)))
1356 continue;
1357
226f2ca3 1358 if (mlx5e_is_offloaded_flow(flow)) {
b8aee822 1359 counter = mlx5e_tc_get_counter(flow);
90bb7692 1360 lastuse = mlx5_fc_query_lastuse(counter);
f6dfb4c3 1361 if (time_after((unsigned long)lastuse, nhe->reported_lastuse)) {
5a7e5bcb 1362 mlx5e_flow_put(netdev_priv(e->out_dev), flow);
f6dfb4c3
HHZ
1363 neigh_used = true;
1364 break;
1365 }
1366 }
5a7e5bcb
VB
1367
1368 mlx5e_flow_put(netdev_priv(e->out_dev), flow);
f6dfb4c3 1369 }
e36d4810
RD
1370 if (neigh_used)
1371 break;
f6dfb4c3
HHZ
1372 }
1373
1374 if (neigh_used) {
1375 nhe->reported_lastuse = jiffies;
1376
1377 /* find the relevant neigh according to the cached device and
1378 * dst ip pair
1379 */
1380 n = neigh_lookup(tbl, &m_neigh->dst_ip, m_neigh->dev);
c7f7ba8d 1381 if (!n)
f6dfb4c3 1382 return;
f6dfb4c3
HHZ
1383
1384 neigh_event_send(n, NULL);
1385 neigh_release(n);
1386 }
1387}
1388
d85cdccb 1389static void mlx5e_detach_encap(struct mlx5e_priv *priv,
8c4dc42b 1390 struct mlx5e_tc_flow *flow, int out_index)
d85cdccb 1391{
8c4dc42b 1392 struct list_head *next = flow->encaps[out_index].list.next;
5067b602 1393
5a7e5bcb
VB
1394 /* flow wasn't fully initialized */
1395 if (list_empty(&flow->encaps[out_index].list))
1396 return;
1397
8c4dc42b 1398 list_del(&flow->encaps[out_index].list);
5067b602 1399 if (list_empty(next)) {
c1ae1152 1400 struct mlx5e_encap_entry *e;
5067b602 1401
c1ae1152 1402 e = list_entry(next, struct mlx5e_encap_entry, flows);
232c0013
HHZ
1403 mlx5e_rep_encap_entry_detach(netdev_priv(e->out_dev), e);
1404
1405 if (e->flags & MLX5_ENCAP_ENTRY_VALID)
60786f09 1406 mlx5_packet_reformat_dealloc(priv->mdev, e->encap_id);
232c0013 1407
cdc5a7f3 1408 hash_del_rcu(&e->encap_hlist);
232c0013 1409 kfree(e->encap_header);
5067b602
RD
1410 kfree(e);
1411 }
1412}
1413
04de7dda
RD
1414static void __mlx5e_tc_del_fdb_peer_flow(struct mlx5e_tc_flow *flow)
1415{
1416 struct mlx5_eswitch *esw = flow->priv->mdev->priv.eswitch;
1417
226f2ca3
VB
1418 if (!flow_flag_test(flow, ESWITCH) ||
1419 !flow_flag_test(flow, DUP))
04de7dda
RD
1420 return;
1421
1422 mutex_lock(&esw->offloads.peer_mutex);
1423 list_del(&flow->peer);
1424 mutex_unlock(&esw->offloads.peer_mutex);
1425
226f2ca3 1426 flow_flag_clear(flow, DUP);
04de7dda
RD
1427
1428 mlx5e_tc_del_fdb_flow(flow->peer_flow->priv, flow->peer_flow);
1429 kvfree(flow->peer_flow);
1430 flow->peer_flow = NULL;
1431}
1432
1433static void mlx5e_tc_del_fdb_peer_flow(struct mlx5e_tc_flow *flow)
1434{
1435 struct mlx5_core_dev *dev = flow->priv->mdev;
1436 struct mlx5_devcom *devcom = dev->priv.devcom;
1437 struct mlx5_eswitch *peer_esw;
1438
1439 peer_esw = mlx5_devcom_get_peer_data(devcom, MLX5_DEVCOM_ESW_OFFLOADS);
1440 if (!peer_esw)
1441 return;
1442
1443 __mlx5e_tc_del_fdb_peer_flow(flow);
1444 mlx5_devcom_release_peer_data(devcom, MLX5_DEVCOM_ESW_OFFLOADS);
1445}
1446
e8f887ac 1447static void mlx5e_tc_del_flow(struct mlx5e_priv *priv,
961e8979 1448 struct mlx5e_tc_flow *flow)
e8f887ac 1449{
226f2ca3 1450 if (mlx5e_is_eswitch_flow(flow)) {
04de7dda 1451 mlx5e_tc_del_fdb_peer_flow(flow);
d85cdccb 1452 mlx5e_tc_del_fdb_flow(priv, flow);
04de7dda 1453 } else {
d85cdccb 1454 mlx5e_tc_del_nic_flow(priv, flow);
04de7dda 1455 }
e8f887ac
AV
1456}
1457
bbd00f7e
HHZ
1458
1459static int parse_tunnel_attr(struct mlx5e_priv *priv,
1460 struct mlx5_flow_spec *spec,
f9e30088 1461 struct flow_cls_offload *f,
6363651d 1462 struct net_device *filter_dev, u8 *match_level)
bbd00f7e 1463{
e98bedf5 1464 struct netlink_ext_ack *extack = f->common.extack;
bbd00f7e
HHZ
1465 void *headers_c = MLX5_ADDR_OF(fte_match_param, spec->match_criteria,
1466 outer_headers);
1467 void *headers_v = MLX5_ADDR_OF(fte_match_param, spec->match_value,
1468 outer_headers);
f9e30088 1469 struct flow_rule *rule = flow_cls_offload_flow_rule(f);
8f256622 1470 int err;
2e72eb43 1471
101f4de9 1472 err = mlx5e_tc_tun_parse(filter_dev, priv, spec, f,
6363651d 1473 headers_c, headers_v, match_level);
54c177ca
OS
1474 if (err) {
1475 NL_SET_ERR_MSG_MOD(extack,
1476 "failed to parse tunnel attributes");
101f4de9 1477 return err;
bbd00f7e
HHZ
1478 }
1479
d1bda7ee 1480 if (flow_rule_match_key(rule, FLOW_DISSECTOR_KEY_ENC_IPV4_ADDRS)) {
8f256622
PNA
1481 struct flow_match_ipv4_addrs match;
1482
1483 flow_rule_match_enc_ipv4_addrs(rule, &match);
bbd00f7e
HHZ
1484 MLX5_SET(fte_match_set_lyr_2_4, headers_c,
1485 src_ipv4_src_ipv6.ipv4_layout.ipv4,
8f256622 1486 ntohl(match.mask->src));
bbd00f7e
HHZ
1487 MLX5_SET(fte_match_set_lyr_2_4, headers_v,
1488 src_ipv4_src_ipv6.ipv4_layout.ipv4,
8f256622 1489 ntohl(match.key->src));
bbd00f7e
HHZ
1490
1491 MLX5_SET(fte_match_set_lyr_2_4, headers_c,
1492 dst_ipv4_dst_ipv6.ipv4_layout.ipv4,
8f256622 1493 ntohl(match.mask->dst));
bbd00f7e
HHZ
1494 MLX5_SET(fte_match_set_lyr_2_4, headers_v,
1495 dst_ipv4_dst_ipv6.ipv4_layout.ipv4,
8f256622 1496 ntohl(match.key->dst));
bbd00f7e 1497
2e72eb43
OG
1498 MLX5_SET_TO_ONES(fte_match_set_lyr_2_4, headers_c, ethertype);
1499 MLX5_SET(fte_match_set_lyr_2_4, headers_v, ethertype, ETH_P_IP);
d1bda7ee 1500 } else if (flow_rule_match_key(rule, FLOW_DISSECTOR_KEY_ENC_IPV6_ADDRS)) {
8f256622 1501 struct flow_match_ipv6_addrs match;
19f44401 1502
8f256622 1503 flow_rule_match_enc_ipv6_addrs(rule, &match);
19f44401
OG
1504 memcpy(MLX5_ADDR_OF(fte_match_set_lyr_2_4, headers_c,
1505 src_ipv4_src_ipv6.ipv6_layout.ipv6),
8f256622 1506 &match.mask->src, MLX5_FLD_SZ_BYTES(ipv6_layout, ipv6));
19f44401
OG
1507 memcpy(MLX5_ADDR_OF(fte_match_set_lyr_2_4, headers_v,
1508 src_ipv4_src_ipv6.ipv6_layout.ipv6),
8f256622 1509 &match.key->src, MLX5_FLD_SZ_BYTES(ipv6_layout, ipv6));
19f44401
OG
1510
1511 memcpy(MLX5_ADDR_OF(fte_match_set_lyr_2_4, headers_c,
1512 dst_ipv4_dst_ipv6.ipv6_layout.ipv6),
8f256622 1513 &match.mask->dst, MLX5_FLD_SZ_BYTES(ipv6_layout, ipv6));
19f44401
OG
1514 memcpy(MLX5_ADDR_OF(fte_match_set_lyr_2_4, headers_v,
1515 dst_ipv4_dst_ipv6.ipv6_layout.ipv6),
8f256622 1516 &match.key->dst, MLX5_FLD_SZ_BYTES(ipv6_layout, ipv6));
19f44401
OG
1517
1518 MLX5_SET_TO_ONES(fte_match_set_lyr_2_4, headers_c, ethertype);
1519 MLX5_SET(fte_match_set_lyr_2_4, headers_v, ethertype, ETH_P_IPV6);
2e72eb43 1520 }
bbd00f7e 1521
8f256622
PNA
1522 if (flow_rule_match_key(rule, FLOW_DISSECTOR_KEY_ENC_IP)) {
1523 struct flow_match_ip match;
bcef735c 1524
8f256622
PNA
1525 flow_rule_match_enc_ip(rule, &match);
1526 MLX5_SET(fte_match_set_lyr_2_4, headers_c, ip_ecn,
1527 match.mask->tos & 0x3);
1528 MLX5_SET(fte_match_set_lyr_2_4, headers_v, ip_ecn,
1529 match.key->tos & 0x3);
bcef735c 1530
8f256622
PNA
1531 MLX5_SET(fte_match_set_lyr_2_4, headers_c, ip_dscp,
1532 match.mask->tos >> 2);
1533 MLX5_SET(fte_match_set_lyr_2_4, headers_v, ip_dscp,
1534 match.key->tos >> 2);
bcef735c 1535
8f256622
PNA
1536 MLX5_SET(fte_match_set_lyr_2_4, headers_c, ttl_hoplimit,
1537 match.mask->ttl);
1538 MLX5_SET(fte_match_set_lyr_2_4, headers_v, ttl_hoplimit,
1539 match.key->ttl);
e98bedf5 1540
8f256622 1541 if (match.mask->ttl &&
e98bedf5
EB
1542 !MLX5_CAP_ESW_FLOWTABLE_FDB
1543 (priv->mdev,
1544 ft_field_support.outer_ipv4_ttl)) {
1545 NL_SET_ERR_MSG_MOD(extack,
1546 "Matching on TTL is not supported");
1547 return -EOPNOTSUPP;
1548 }
1549
bcef735c
OG
1550 }
1551
bbd00f7e
HHZ
1552 /* Enforce DMAC when offloading incoming tunneled flows.
1553 * Flow counters require a match on the DMAC.
1554 */
1555 MLX5_SET_TO_ONES(fte_match_set_lyr_2_4, headers_c, dmac_47_16);
1556 MLX5_SET_TO_ONES(fte_match_set_lyr_2_4, headers_c, dmac_15_0);
1557 ether_addr_copy(MLX5_ADDR_OF(fte_match_set_lyr_2_4, headers_v,
1558 dmac_47_16), priv->netdev->dev_addr);
1559
1560 /* let software handle IP fragments */
1561 MLX5_SET(fte_match_set_lyr_2_4, headers_c, frag, 1);
1562 MLX5_SET(fte_match_set_lyr_2_4, headers_v, frag, 0);
1563
1564 return 0;
1565}
1566
8377629e
EB
1567static void *get_match_headers_criteria(u32 flags,
1568 struct mlx5_flow_spec *spec)
1569{
1570 return (flags & MLX5_FLOW_CONTEXT_ACTION_DECAP) ?
1571 MLX5_ADDR_OF(fte_match_param, spec->match_criteria,
1572 inner_headers) :
1573 MLX5_ADDR_OF(fte_match_param, spec->match_criteria,
1574 outer_headers);
1575}
1576
1577static void *get_match_headers_value(u32 flags,
1578 struct mlx5_flow_spec *spec)
1579{
1580 return (flags & MLX5_FLOW_CONTEXT_ACTION_DECAP) ?
1581 MLX5_ADDR_OF(fte_match_param, spec->match_value,
1582 inner_headers) :
1583 MLX5_ADDR_OF(fte_match_param, spec->match_value,
1584 outer_headers);
1585}
1586
de0af0bf
RD
1587static int __parse_cls_flower(struct mlx5e_priv *priv,
1588 struct mlx5_flow_spec *spec,
f9e30088 1589 struct flow_cls_offload *f,
54c177ca 1590 struct net_device *filter_dev,
6363651d 1591 u8 *match_level, u8 *tunnel_match_level)
e3a2b7ed 1592{
e98bedf5 1593 struct netlink_ext_ack *extack = f->common.extack;
c5bb1730
MG
1594 void *headers_c = MLX5_ADDR_OF(fte_match_param, spec->match_criteria,
1595 outer_headers);
1596 void *headers_v = MLX5_ADDR_OF(fte_match_param, spec->match_value,
1597 outer_headers);
699e96dd
JL
1598 void *misc_c = MLX5_ADDR_OF(fte_match_param, spec->match_criteria,
1599 misc_parameters);
1600 void *misc_v = MLX5_ADDR_OF(fte_match_param, spec->match_value,
1601 misc_parameters);
f9e30088 1602 struct flow_rule *rule = flow_cls_offload_flow_rule(f);
8f256622 1603 struct flow_dissector *dissector = rule->match.dissector;
e3a2b7ed
AV
1604 u16 addr_type = 0;
1605 u8 ip_proto = 0;
1606
d708f902 1607 *match_level = MLX5_MATCH_NONE;
de0af0bf 1608
8f256622 1609 if (dissector->used_keys &
3d144578
VB
1610 ~(BIT(FLOW_DISSECTOR_KEY_META) |
1611 BIT(FLOW_DISSECTOR_KEY_CONTROL) |
e3a2b7ed
AV
1612 BIT(FLOW_DISSECTOR_KEY_BASIC) |
1613 BIT(FLOW_DISSECTOR_KEY_ETH_ADDRS) |
095b6cfd 1614 BIT(FLOW_DISSECTOR_KEY_VLAN) |
699e96dd 1615 BIT(FLOW_DISSECTOR_KEY_CVLAN) |
e3a2b7ed
AV
1616 BIT(FLOW_DISSECTOR_KEY_IPV4_ADDRS) |
1617 BIT(FLOW_DISSECTOR_KEY_IPV6_ADDRS) |
bbd00f7e
HHZ
1618 BIT(FLOW_DISSECTOR_KEY_PORTS) |
1619 BIT(FLOW_DISSECTOR_KEY_ENC_KEYID) |
1620 BIT(FLOW_DISSECTOR_KEY_ENC_IPV4_ADDRS) |
1621 BIT(FLOW_DISSECTOR_KEY_ENC_IPV6_ADDRS) |
1622 BIT(FLOW_DISSECTOR_KEY_ENC_PORTS) |
e77834ec 1623 BIT(FLOW_DISSECTOR_KEY_ENC_CONTROL) |
fd7da28b 1624 BIT(FLOW_DISSECTOR_KEY_TCP) |
bcef735c 1625 BIT(FLOW_DISSECTOR_KEY_IP) |
9272e3df
YK
1626 BIT(FLOW_DISSECTOR_KEY_ENC_IP) |
1627 BIT(FLOW_DISSECTOR_KEY_ENC_OPTS))) {
e98bedf5 1628 NL_SET_ERR_MSG_MOD(extack, "Unsupported key");
e3a2b7ed 1629 netdev_warn(priv->netdev, "Unsupported key used: 0x%x\n",
8f256622 1630 dissector->used_keys);
e3a2b7ed
AV
1631 return -EOPNOTSUPP;
1632 }
1633
075973c7 1634 if (mlx5e_get_tc_tun(filter_dev)) {
d1bda7ee 1635 if (parse_tunnel_attr(priv, spec, f, filter_dev, tunnel_match_level))
bbd00f7e 1636 return -EOPNOTSUPP;
bbd00f7e
HHZ
1637
1638 /* In decap flow, header pointers should point to the inner
1639 * headers, outer header were already set by parse_tunnel_attr
1640 */
8377629e
EB
1641 headers_c = get_match_headers_criteria(MLX5_FLOW_CONTEXT_ACTION_DECAP,
1642 spec);
1643 headers_v = get_match_headers_value(MLX5_FLOW_CONTEXT_ACTION_DECAP,
1644 spec);
bbd00f7e
HHZ
1645 }
1646
8f256622
PNA
1647 if (flow_rule_match_key(rule, FLOW_DISSECTOR_KEY_BASIC)) {
1648 struct flow_match_basic match;
1649
1650 flow_rule_match_basic(rule, &match);
d3a80bb5 1651 MLX5_SET(fte_match_set_lyr_2_4, headers_c, ethertype,
8f256622 1652 ntohs(match.mask->n_proto));
d3a80bb5 1653 MLX5_SET(fte_match_set_lyr_2_4, headers_v, ethertype,
8f256622 1654 ntohs(match.key->n_proto));
e3a2b7ed 1655
8f256622 1656 if (match.mask->n_proto)
d708f902 1657 *match_level = MLX5_MATCH_L2;
e3a2b7ed 1658 }
35a605db
EB
1659 if (flow_rule_match_key(rule, FLOW_DISSECTOR_KEY_VLAN) ||
1660 is_vlan_dev(filter_dev)) {
1661 struct flow_dissector_key_vlan filter_dev_mask;
1662 struct flow_dissector_key_vlan filter_dev_key;
8f256622
PNA
1663 struct flow_match_vlan match;
1664
35a605db
EB
1665 if (is_vlan_dev(filter_dev)) {
1666 match.key = &filter_dev_key;
1667 match.key->vlan_id = vlan_dev_vlan_id(filter_dev);
1668 match.key->vlan_tpid = vlan_dev_vlan_proto(filter_dev);
1669 match.key->vlan_priority = 0;
1670 match.mask = &filter_dev_mask;
1671 memset(match.mask, 0xff, sizeof(*match.mask));
1672 match.mask->vlan_priority = 0;
1673 } else {
1674 flow_rule_match_vlan(rule, &match);
1675 }
8f256622
PNA
1676 if (match.mask->vlan_id ||
1677 match.mask->vlan_priority ||
1678 match.mask->vlan_tpid) {
1679 if (match.key->vlan_tpid == htons(ETH_P_8021AD)) {
699e96dd
JL
1680 MLX5_SET(fte_match_set_lyr_2_4, headers_c,
1681 svlan_tag, 1);
1682 MLX5_SET(fte_match_set_lyr_2_4, headers_v,
1683 svlan_tag, 1);
1684 } else {
1685 MLX5_SET(fte_match_set_lyr_2_4, headers_c,
1686 cvlan_tag, 1);
1687 MLX5_SET(fte_match_set_lyr_2_4, headers_v,
1688 cvlan_tag, 1);
1689 }
095b6cfd 1690
8f256622
PNA
1691 MLX5_SET(fte_match_set_lyr_2_4, headers_c, first_vid,
1692 match.mask->vlan_id);
1693 MLX5_SET(fte_match_set_lyr_2_4, headers_v, first_vid,
1694 match.key->vlan_id);
358d79a4 1695
8f256622
PNA
1696 MLX5_SET(fte_match_set_lyr_2_4, headers_c, first_prio,
1697 match.mask->vlan_priority);
1698 MLX5_SET(fte_match_set_lyr_2_4, headers_v, first_prio,
1699 match.key->vlan_priority);
54782900 1700
d708f902 1701 *match_level = MLX5_MATCH_L2;
54782900 1702 }
d3a80bb5 1703 } else if (*match_level != MLX5_MATCH_NONE) {
cee26487
JL
1704 MLX5_SET(fte_match_set_lyr_2_4, headers_c, svlan_tag, 1);
1705 MLX5_SET(fte_match_set_lyr_2_4, headers_c, cvlan_tag, 1);
d3a80bb5 1706 *match_level = MLX5_MATCH_L2;
54782900
OG
1707 }
1708
8f256622
PNA
1709 if (flow_rule_match_key(rule, FLOW_DISSECTOR_KEY_CVLAN)) {
1710 struct flow_match_vlan match;
1711
12d5cbf8 1712 flow_rule_match_cvlan(rule, &match);
8f256622
PNA
1713 if (match.mask->vlan_id ||
1714 match.mask->vlan_priority ||
1715 match.mask->vlan_tpid) {
1716 if (match.key->vlan_tpid == htons(ETH_P_8021AD)) {
699e96dd
JL
1717 MLX5_SET(fte_match_set_misc, misc_c,
1718 outer_second_svlan_tag, 1);
1719 MLX5_SET(fte_match_set_misc, misc_v,
1720 outer_second_svlan_tag, 1);
1721 } else {
1722 MLX5_SET(fte_match_set_misc, misc_c,
1723 outer_second_cvlan_tag, 1);
1724 MLX5_SET(fte_match_set_misc, misc_v,
1725 outer_second_cvlan_tag, 1);
1726 }
1727
1728 MLX5_SET(fte_match_set_misc, misc_c, outer_second_vid,
8f256622 1729 match.mask->vlan_id);
699e96dd 1730 MLX5_SET(fte_match_set_misc, misc_v, outer_second_vid,
8f256622 1731 match.key->vlan_id);
699e96dd 1732 MLX5_SET(fte_match_set_misc, misc_c, outer_second_prio,
8f256622 1733 match.mask->vlan_priority);
699e96dd 1734 MLX5_SET(fte_match_set_misc, misc_v, outer_second_prio,
8f256622 1735 match.key->vlan_priority);
699e96dd
JL
1736
1737 *match_level = MLX5_MATCH_L2;
1738 }
1739 }
1740
8f256622
PNA
1741 if (flow_rule_match_key(rule, FLOW_DISSECTOR_KEY_ETH_ADDRS)) {
1742 struct flow_match_eth_addrs match;
54782900 1743
8f256622 1744 flow_rule_match_eth_addrs(rule, &match);
d3a80bb5
OG
1745 ether_addr_copy(MLX5_ADDR_OF(fte_match_set_lyr_2_4, headers_c,
1746 dmac_47_16),
8f256622 1747 match.mask->dst);
d3a80bb5
OG
1748 ether_addr_copy(MLX5_ADDR_OF(fte_match_set_lyr_2_4, headers_v,
1749 dmac_47_16),
8f256622 1750 match.key->dst);
d3a80bb5
OG
1751
1752 ether_addr_copy(MLX5_ADDR_OF(fte_match_set_lyr_2_4, headers_c,
1753 smac_47_16),
8f256622 1754 match.mask->src);
d3a80bb5
OG
1755 ether_addr_copy(MLX5_ADDR_OF(fte_match_set_lyr_2_4, headers_v,
1756 smac_47_16),
8f256622 1757 match.key->src);
d3a80bb5 1758
8f256622
PNA
1759 if (!is_zero_ether_addr(match.mask->src) ||
1760 !is_zero_ether_addr(match.mask->dst))
d708f902 1761 *match_level = MLX5_MATCH_L2;
54782900
OG
1762 }
1763
8f256622
PNA
1764 if (flow_rule_match_key(rule, FLOW_DISSECTOR_KEY_CONTROL)) {
1765 struct flow_match_control match;
54782900 1766
8f256622
PNA
1767 flow_rule_match_control(rule, &match);
1768 addr_type = match.key->addr_type;
54782900
OG
1769
1770 /* the HW doesn't support frag first/later */
8f256622 1771 if (match.mask->flags & FLOW_DIS_FIRST_FRAG)
54782900
OG
1772 return -EOPNOTSUPP;
1773
8f256622 1774 if (match.mask->flags & FLOW_DIS_IS_FRAGMENT) {
54782900
OG
1775 MLX5_SET(fte_match_set_lyr_2_4, headers_c, frag, 1);
1776 MLX5_SET(fte_match_set_lyr_2_4, headers_v, frag,
8f256622 1777 match.key->flags & FLOW_DIS_IS_FRAGMENT);
54782900
OG
1778
1779 /* the HW doesn't need L3 inline to match on frag=no */
8f256622 1780 if (!(match.key->flags & FLOW_DIS_IS_FRAGMENT))
83621b7d 1781 *match_level = MLX5_MATCH_L2;
54782900
OG
1782 /* *** L2 attributes parsing up to here *** */
1783 else
83621b7d 1784 *match_level = MLX5_MATCH_L3;
095b6cfd
OG
1785 }
1786 }
1787
8f256622
PNA
1788 if (flow_rule_match_key(rule, FLOW_DISSECTOR_KEY_BASIC)) {
1789 struct flow_match_basic match;
1790
1791 flow_rule_match_basic(rule, &match);
1792 ip_proto = match.key->ip_proto;
54782900
OG
1793
1794 MLX5_SET(fte_match_set_lyr_2_4, headers_c, ip_protocol,
8f256622 1795 match.mask->ip_proto);
54782900 1796 MLX5_SET(fte_match_set_lyr_2_4, headers_v, ip_protocol,
8f256622 1797 match.key->ip_proto);
54782900 1798
8f256622 1799 if (match.mask->ip_proto)
d708f902 1800 *match_level = MLX5_MATCH_L3;
54782900
OG
1801 }
1802
e3a2b7ed 1803 if (addr_type == FLOW_DISSECTOR_KEY_IPV4_ADDRS) {
8f256622 1804 struct flow_match_ipv4_addrs match;
e3a2b7ed 1805
8f256622 1806 flow_rule_match_ipv4_addrs(rule, &match);
e3a2b7ed
AV
1807 memcpy(MLX5_ADDR_OF(fte_match_set_lyr_2_4, headers_c,
1808 src_ipv4_src_ipv6.ipv4_layout.ipv4),
8f256622 1809 &match.mask->src, sizeof(match.mask->src));
e3a2b7ed
AV
1810 memcpy(MLX5_ADDR_OF(fte_match_set_lyr_2_4, headers_v,
1811 src_ipv4_src_ipv6.ipv4_layout.ipv4),
8f256622 1812 &match.key->src, sizeof(match.key->src));
e3a2b7ed
AV
1813 memcpy(MLX5_ADDR_OF(fte_match_set_lyr_2_4, headers_c,
1814 dst_ipv4_dst_ipv6.ipv4_layout.ipv4),
8f256622 1815 &match.mask->dst, sizeof(match.mask->dst));
e3a2b7ed
AV
1816 memcpy(MLX5_ADDR_OF(fte_match_set_lyr_2_4, headers_v,
1817 dst_ipv4_dst_ipv6.ipv4_layout.ipv4),
8f256622 1818 &match.key->dst, sizeof(match.key->dst));
de0af0bf 1819
8f256622 1820 if (match.mask->src || match.mask->dst)
d708f902 1821 *match_level = MLX5_MATCH_L3;
e3a2b7ed
AV
1822 }
1823
1824 if (addr_type == FLOW_DISSECTOR_KEY_IPV6_ADDRS) {
8f256622 1825 struct flow_match_ipv6_addrs match;
e3a2b7ed 1826
8f256622 1827 flow_rule_match_ipv6_addrs(rule, &match);
e3a2b7ed
AV
1828 memcpy(MLX5_ADDR_OF(fte_match_set_lyr_2_4, headers_c,
1829 src_ipv4_src_ipv6.ipv6_layout.ipv6),
8f256622 1830 &match.mask->src, sizeof(match.mask->src));
e3a2b7ed
AV
1831 memcpy(MLX5_ADDR_OF(fte_match_set_lyr_2_4, headers_v,
1832 src_ipv4_src_ipv6.ipv6_layout.ipv6),
8f256622 1833 &match.key->src, sizeof(match.key->src));
e3a2b7ed
AV
1834
1835 memcpy(MLX5_ADDR_OF(fte_match_set_lyr_2_4, headers_c,
1836 dst_ipv4_dst_ipv6.ipv6_layout.ipv6),
8f256622 1837 &match.mask->dst, sizeof(match.mask->dst));
e3a2b7ed
AV
1838 memcpy(MLX5_ADDR_OF(fte_match_set_lyr_2_4, headers_v,
1839 dst_ipv4_dst_ipv6.ipv6_layout.ipv6),
8f256622 1840 &match.key->dst, sizeof(match.key->dst));
de0af0bf 1841
8f256622
PNA
1842 if (ipv6_addr_type(&match.mask->src) != IPV6_ADDR_ANY ||
1843 ipv6_addr_type(&match.mask->dst) != IPV6_ADDR_ANY)
d708f902 1844 *match_level = MLX5_MATCH_L3;
e3a2b7ed
AV
1845 }
1846
8f256622
PNA
1847 if (flow_rule_match_key(rule, FLOW_DISSECTOR_KEY_IP)) {
1848 struct flow_match_ip match;
1f97a526 1849
8f256622
PNA
1850 flow_rule_match_ip(rule, &match);
1851 MLX5_SET(fte_match_set_lyr_2_4, headers_c, ip_ecn,
1852 match.mask->tos & 0x3);
1853 MLX5_SET(fte_match_set_lyr_2_4, headers_v, ip_ecn,
1854 match.key->tos & 0x3);
1f97a526 1855
8f256622
PNA
1856 MLX5_SET(fte_match_set_lyr_2_4, headers_c, ip_dscp,
1857 match.mask->tos >> 2);
1858 MLX5_SET(fte_match_set_lyr_2_4, headers_v, ip_dscp,
1859 match.key->tos >> 2);
1f97a526 1860
8f256622
PNA
1861 MLX5_SET(fte_match_set_lyr_2_4, headers_c, ttl_hoplimit,
1862 match.mask->ttl);
1863 MLX5_SET(fte_match_set_lyr_2_4, headers_v, ttl_hoplimit,
1864 match.key->ttl);
1f97a526 1865
8f256622 1866 if (match.mask->ttl &&
a8ade55f 1867 !MLX5_CAP_ESW_FLOWTABLE_FDB(priv->mdev,
e98bedf5
EB
1868 ft_field_support.outer_ipv4_ttl)) {
1869 NL_SET_ERR_MSG_MOD(extack,
1870 "Matching on TTL is not supported");
1f97a526 1871 return -EOPNOTSUPP;
e98bedf5 1872 }
a8ade55f 1873
8f256622 1874 if (match.mask->tos || match.mask->ttl)
d708f902 1875 *match_level = MLX5_MATCH_L3;
1f97a526
OG
1876 }
1877
54782900
OG
1878 /* *** L3 attributes parsing up to here *** */
1879
8f256622
PNA
1880 if (flow_rule_match_key(rule, FLOW_DISSECTOR_KEY_PORTS)) {
1881 struct flow_match_ports match;
1882
1883 flow_rule_match_ports(rule, &match);
e3a2b7ed
AV
1884 switch (ip_proto) {
1885 case IPPROTO_TCP:
1886 MLX5_SET(fte_match_set_lyr_2_4, headers_c,
8f256622 1887 tcp_sport, ntohs(match.mask->src));
e3a2b7ed 1888 MLX5_SET(fte_match_set_lyr_2_4, headers_v,
8f256622 1889 tcp_sport, ntohs(match.key->src));
e3a2b7ed
AV
1890
1891 MLX5_SET(fte_match_set_lyr_2_4, headers_c,
8f256622 1892 tcp_dport, ntohs(match.mask->dst));
e3a2b7ed 1893 MLX5_SET(fte_match_set_lyr_2_4, headers_v,
8f256622 1894 tcp_dport, ntohs(match.key->dst));
e3a2b7ed
AV
1895 break;
1896
1897 case IPPROTO_UDP:
1898 MLX5_SET(fte_match_set_lyr_2_4, headers_c,
8f256622 1899 udp_sport, ntohs(match.mask->src));
e3a2b7ed 1900 MLX5_SET(fte_match_set_lyr_2_4, headers_v,
8f256622 1901 udp_sport, ntohs(match.key->src));
e3a2b7ed
AV
1902
1903 MLX5_SET(fte_match_set_lyr_2_4, headers_c,
8f256622 1904 udp_dport, ntohs(match.mask->dst));
e3a2b7ed 1905 MLX5_SET(fte_match_set_lyr_2_4, headers_v,
8f256622 1906 udp_dport, ntohs(match.key->dst));
e3a2b7ed
AV
1907 break;
1908 default:
e98bedf5
EB
1909 NL_SET_ERR_MSG_MOD(extack,
1910 "Only UDP and TCP transports are supported for L4 matching");
e3a2b7ed
AV
1911 netdev_err(priv->netdev,
1912 "Only UDP and TCP transport are supported\n");
1913 return -EINVAL;
1914 }
de0af0bf 1915
8f256622 1916 if (match.mask->src || match.mask->dst)
d708f902 1917 *match_level = MLX5_MATCH_L4;
e3a2b7ed
AV
1918 }
1919
8f256622
PNA
1920 if (flow_rule_match_key(rule, FLOW_DISSECTOR_KEY_TCP)) {
1921 struct flow_match_tcp match;
e77834ec 1922
8f256622 1923 flow_rule_match_tcp(rule, &match);
e77834ec 1924 MLX5_SET(fte_match_set_lyr_2_4, headers_c, tcp_flags,
8f256622 1925 ntohs(match.mask->flags));
e77834ec 1926 MLX5_SET(fte_match_set_lyr_2_4, headers_v, tcp_flags,
8f256622 1927 ntohs(match.key->flags));
e77834ec 1928
8f256622 1929 if (match.mask->flags)
d708f902 1930 *match_level = MLX5_MATCH_L4;
e77834ec
OG
1931 }
1932
e3a2b7ed
AV
1933 return 0;
1934}
1935
de0af0bf 1936static int parse_cls_flower(struct mlx5e_priv *priv,
65ba8fb7 1937 struct mlx5e_tc_flow *flow,
de0af0bf 1938 struct mlx5_flow_spec *spec,
f9e30088 1939 struct flow_cls_offload *f,
54c177ca 1940 struct net_device *filter_dev)
de0af0bf 1941{
e98bedf5 1942 struct netlink_ext_ack *extack = f->common.extack;
de0af0bf
RD
1943 struct mlx5_core_dev *dev = priv->mdev;
1944 struct mlx5_eswitch *esw = dev->priv.eswitch;
1d447a39 1945 struct mlx5e_rep_priv *rpriv = priv->ppriv;
6363651d 1946 u8 match_level, tunnel_match_level = MLX5_MATCH_NONE;
1d447a39 1947 struct mlx5_eswitch_rep *rep;
226f2ca3 1948 bool is_eswitch_flow;
de0af0bf
RD
1949 int err;
1950
6363651d 1951 err = __parse_cls_flower(priv, spec, f, filter_dev, &match_level, &tunnel_match_level);
de0af0bf 1952
226f2ca3
VB
1953 is_eswitch_flow = mlx5e_is_eswitch_flow(flow);
1954 if (!err && is_eswitch_flow) {
1d447a39 1955 rep = rpriv->rep;
b05af6aa 1956 if (rep->vport != MLX5_VPORT_UPLINK &&
1d447a39 1957 (esw->offloads.inline_mode != MLX5_INLINE_MODE_NONE &&
d708f902 1958 esw->offloads.inline_mode < match_level)) {
e98bedf5
EB
1959 NL_SET_ERR_MSG_MOD(extack,
1960 "Flow is not offloaded due to min inline setting");
de0af0bf
RD
1961 netdev_warn(priv->netdev,
1962 "Flow is not offloaded due to min inline setting, required %d actual %d\n",
d708f902 1963 match_level, esw->offloads.inline_mode);
de0af0bf
RD
1964 return -EOPNOTSUPP;
1965 }
1966 }
1967
226f2ca3 1968 if (is_eswitch_flow) {
38aa51c1 1969 flow->esw_attr->match_level = match_level;
6363651d
OG
1970 flow->esw_attr->tunnel_match_level = tunnel_match_level;
1971 } else {
38aa51c1 1972 flow->nic_attr->match_level = match_level;
6363651d 1973 }
38aa51c1 1974
de0af0bf
RD
1975 return err;
1976}
1977
d79b6df6
OG
1978struct pedit_headers {
1979 struct ethhdr eth;
0eb69bb9 1980 struct vlan_hdr vlan;
d79b6df6
OG
1981 struct iphdr ip4;
1982 struct ipv6hdr ip6;
1983 struct tcphdr tcp;
1984 struct udphdr udp;
1985};
1986
c500c86b
PNA
1987struct pedit_headers_action {
1988 struct pedit_headers vals;
1989 struct pedit_headers masks;
1990 u32 pedits;
1991};
1992
d79b6df6 1993static int pedit_header_offsets[] = {
73867881
PNA
1994 [FLOW_ACT_MANGLE_HDR_TYPE_ETH] = offsetof(struct pedit_headers, eth),
1995 [FLOW_ACT_MANGLE_HDR_TYPE_IP4] = offsetof(struct pedit_headers, ip4),
1996 [FLOW_ACT_MANGLE_HDR_TYPE_IP6] = offsetof(struct pedit_headers, ip6),
1997 [FLOW_ACT_MANGLE_HDR_TYPE_TCP] = offsetof(struct pedit_headers, tcp),
1998 [FLOW_ACT_MANGLE_HDR_TYPE_UDP] = offsetof(struct pedit_headers, udp),
d79b6df6
OG
1999};
2000
2001#define pedit_header(_ph, _htype) ((void *)(_ph) + pedit_header_offsets[_htype])
2002
2003static int set_pedit_val(u8 hdr_type, u32 mask, u32 val, u32 offset,
c500c86b 2004 struct pedit_headers_action *hdrs)
d79b6df6
OG
2005{
2006 u32 *curr_pmask, *curr_pval;
2007
c500c86b
PNA
2008 curr_pmask = (u32 *)(pedit_header(&hdrs->masks, hdr_type) + offset);
2009 curr_pval = (u32 *)(pedit_header(&hdrs->vals, hdr_type) + offset);
d79b6df6
OG
2010
2011 if (*curr_pmask & mask) /* disallow acting twice on the same location */
2012 goto out_err;
2013
2014 *curr_pmask |= mask;
2015 *curr_pval |= (val & mask);
2016
2017 return 0;
2018
2019out_err:
2020 return -EOPNOTSUPP;
2021}
2022
2023struct mlx5_fields {
2024 u8 field;
2025 u8 size;
2026 u32 offset;
27c11b6b 2027 u32 match_offset;
d79b6df6
OG
2028};
2029
27c11b6b
EB
2030#define OFFLOAD(fw_field, size, field, off, match_field) \
2031 {MLX5_ACTION_IN_FIELD_OUT_ ## fw_field, size, \
2032 offsetof(struct pedit_headers, field) + (off), \
2033 MLX5_BYTE_OFF(fte_match_set_lyr_2_4, match_field)}
2034
2ef86872
EB
2035/* masked values are the same and there are no rewrites that do not have a
2036 * match.
2037 */
2038#define SAME_VAL_MASK(type, valp, maskp, matchvalp, matchmaskp) ({ \
2039 type matchmaskx = *(type *)(matchmaskp); \
2040 type matchvalx = *(type *)(matchvalp); \
2041 type maskx = *(type *)(maskp); \
2042 type valx = *(type *)(valp); \
2043 \
2044 (valx & maskx) == (matchvalx & matchmaskx) && !(maskx & (maskx ^ \
2045 matchmaskx)); \
2046})
2047
27c11b6b
EB
2048static bool cmp_val_mask(void *valp, void *maskp, void *matchvalp,
2049 void *matchmaskp, int size)
2050{
2051 bool same = false;
2052
2053 switch (size) {
2054 case sizeof(u8):
2ef86872 2055 same = SAME_VAL_MASK(u8, valp, maskp, matchvalp, matchmaskp);
27c11b6b
EB
2056 break;
2057 case sizeof(u16):
2ef86872 2058 same = SAME_VAL_MASK(u16, valp, maskp, matchvalp, matchmaskp);
27c11b6b
EB
2059 break;
2060 case sizeof(u32):
2ef86872 2061 same = SAME_VAL_MASK(u32, valp, maskp, matchvalp, matchmaskp);
27c11b6b
EB
2062 break;
2063 }
2064
2065 return same;
2066}
a8e4f0c4 2067
d79b6df6 2068static struct mlx5_fields fields[] = {
27c11b6b
EB
2069 OFFLOAD(DMAC_47_16, 4, eth.h_dest[0], 0, dmac_47_16),
2070 OFFLOAD(DMAC_15_0, 2, eth.h_dest[4], 0, dmac_15_0),
2071 OFFLOAD(SMAC_47_16, 4, eth.h_source[0], 0, smac_47_16),
2072 OFFLOAD(SMAC_15_0, 2, eth.h_source[4], 0, smac_15_0),
2073 OFFLOAD(ETHERTYPE, 2, eth.h_proto, 0, ethertype),
2074 OFFLOAD(FIRST_VID, 2, vlan.h_vlan_TCI, 0, first_vid),
2075
2076 OFFLOAD(IP_TTL, 1, ip4.ttl, 0, ttl_hoplimit),
2077 OFFLOAD(SIPV4, 4, ip4.saddr, 0, src_ipv4_src_ipv6.ipv4_layout.ipv4),
2078 OFFLOAD(DIPV4, 4, ip4.daddr, 0, dst_ipv4_dst_ipv6.ipv4_layout.ipv4),
2079
2080 OFFLOAD(SIPV6_127_96, 4, ip6.saddr.s6_addr32[0], 0,
2081 src_ipv4_src_ipv6.ipv6_layout.ipv6[0]),
2082 OFFLOAD(SIPV6_95_64, 4, ip6.saddr.s6_addr32[1], 0,
2083 src_ipv4_src_ipv6.ipv6_layout.ipv6[4]),
2084 OFFLOAD(SIPV6_63_32, 4, ip6.saddr.s6_addr32[2], 0,
2085 src_ipv4_src_ipv6.ipv6_layout.ipv6[8]),
2086 OFFLOAD(SIPV6_31_0, 4, ip6.saddr.s6_addr32[3], 0,
2087 src_ipv4_src_ipv6.ipv6_layout.ipv6[12]),
2088 OFFLOAD(DIPV6_127_96, 4, ip6.daddr.s6_addr32[0], 0,
2089 dst_ipv4_dst_ipv6.ipv6_layout.ipv6[0]),
2090 OFFLOAD(DIPV6_95_64, 4, ip6.daddr.s6_addr32[1], 0,
2091 dst_ipv4_dst_ipv6.ipv6_layout.ipv6[4]),
2092 OFFLOAD(DIPV6_63_32, 4, ip6.daddr.s6_addr32[2], 0,
2093 dst_ipv4_dst_ipv6.ipv6_layout.ipv6[8]),
2094 OFFLOAD(DIPV6_31_0, 4, ip6.daddr.s6_addr32[3], 0,
2095 dst_ipv4_dst_ipv6.ipv6_layout.ipv6[12]),
2096 OFFLOAD(IPV6_HOPLIMIT, 1, ip6.hop_limit, 0, ttl_hoplimit),
2097
2098 OFFLOAD(TCP_SPORT, 2, tcp.source, 0, tcp_sport),
2099 OFFLOAD(TCP_DPORT, 2, tcp.dest, 0, tcp_dport),
2100 OFFLOAD(TCP_FLAGS, 1, tcp.ack_seq, 5, tcp_flags),
2101
2102 OFFLOAD(UDP_SPORT, 2, udp.source, 0, udp_sport),
2103 OFFLOAD(UDP_DPORT, 2, udp.dest, 0, udp_dport),
d79b6df6
OG
2104};
2105
218d05ce
TZ
2106/* On input attr->max_mod_hdr_actions tells how many HW actions can be parsed at
2107 * max from the SW pedit action. On success, attr->num_mod_hdr_actions
2108 * says how many HW actions were actually parsed.
d79b6df6 2109 */
c500c86b 2110static int offload_pedit_fields(struct pedit_headers_action *hdrs,
e98bedf5 2111 struct mlx5e_tc_flow_parse_attr *parse_attr,
27c11b6b 2112 u32 *action_flags,
e98bedf5 2113 struct netlink_ext_ack *extack)
d79b6df6
OG
2114{
2115 struct pedit_headers *set_masks, *add_masks, *set_vals, *add_vals;
27c11b6b
EB
2116 void *headers_c = get_match_headers_criteria(*action_flags,
2117 &parse_attr->spec);
2118 void *headers_v = get_match_headers_value(*action_flags,
2119 &parse_attr->spec);
2b64beba 2120 int i, action_size, nactions, max_actions, first, last, next_z;
d79b6df6 2121 void *s_masks_p, *a_masks_p, *vals_p;
d79b6df6
OG
2122 struct mlx5_fields *f;
2123 u8 cmd, field_bsize;
e3ca4e05 2124 u32 s_mask, a_mask;
d79b6df6 2125 unsigned long mask;
2b64beba
OG
2126 __be32 mask_be32;
2127 __be16 mask_be16;
d79b6df6
OG
2128 void *action;
2129
73867881
PNA
2130 set_masks = &hdrs[0].masks;
2131 add_masks = &hdrs[1].masks;
2132 set_vals = &hdrs[0].vals;
2133 add_vals = &hdrs[1].vals;
d79b6df6
OG
2134
2135 action_size = MLX5_UN_SZ_BYTES(set_action_in_add_action_in_auto);
218d05ce
TZ
2136 action = parse_attr->mod_hdr_actions +
2137 parse_attr->num_mod_hdr_actions * action_size;
2138
2139 max_actions = parse_attr->max_mod_hdr_actions;
2140 nactions = parse_attr->num_mod_hdr_actions;
d79b6df6
OG
2141
2142 for (i = 0; i < ARRAY_SIZE(fields); i++) {
27c11b6b
EB
2143 bool skip;
2144
d79b6df6
OG
2145 f = &fields[i];
2146 /* avoid seeing bits set from previous iterations */
e3ca4e05
OG
2147 s_mask = 0;
2148 a_mask = 0;
d79b6df6
OG
2149
2150 s_masks_p = (void *)set_masks + f->offset;
2151 a_masks_p = (void *)add_masks + f->offset;
2152
2153 memcpy(&s_mask, s_masks_p, f->size);
2154 memcpy(&a_mask, a_masks_p, f->size);
2155
2156 if (!s_mask && !a_mask) /* nothing to offload here */
2157 continue;
2158
2159 if (s_mask && a_mask) {
e98bedf5
EB
2160 NL_SET_ERR_MSG_MOD(extack,
2161 "can't set and add to the same HW field");
d79b6df6
OG
2162 printk(KERN_WARNING "mlx5: can't set and add to the same HW field (%x)\n", f->field);
2163 return -EOPNOTSUPP;
2164 }
2165
2166 if (nactions == max_actions) {
e98bedf5
EB
2167 NL_SET_ERR_MSG_MOD(extack,
2168 "too many pedit actions, can't offload");
d79b6df6
OG
2169 printk(KERN_WARNING "mlx5: parsed %d pedit actions, can't do more\n", nactions);
2170 return -EOPNOTSUPP;
2171 }
2172
27c11b6b 2173 skip = false;
d79b6df6 2174 if (s_mask) {
27c11b6b
EB
2175 void *match_mask = headers_c + f->match_offset;
2176 void *match_val = headers_v + f->match_offset;
2177
d79b6df6
OG
2178 cmd = MLX5_ACTION_TYPE_SET;
2179 mask = s_mask;
2180 vals_p = (void *)set_vals + f->offset;
27c11b6b
EB
2181 /* don't rewrite if we have a match on the same value */
2182 if (cmp_val_mask(vals_p, s_masks_p, match_val,
2183 match_mask, f->size))
2184 skip = true;
d79b6df6
OG
2185 /* clear to denote we consumed this field */
2186 memset(s_masks_p, 0, f->size);
2187 } else {
27c11b6b
EB
2188 u32 zero = 0;
2189
d79b6df6
OG
2190 cmd = MLX5_ACTION_TYPE_ADD;
2191 mask = a_mask;
2192 vals_p = (void *)add_vals + f->offset;
27c11b6b
EB
2193 /* add 0 is no change */
2194 if (!memcmp(vals_p, &zero, f->size))
2195 skip = true;
d79b6df6
OG
2196 /* clear to denote we consumed this field */
2197 memset(a_masks_p, 0, f->size);
2198 }
27c11b6b
EB
2199 if (skip)
2200 continue;
d79b6df6 2201
d79b6df6 2202 field_bsize = f->size * BITS_PER_BYTE;
e3ca4e05 2203
2b64beba
OG
2204 if (field_bsize == 32) {
2205 mask_be32 = *(__be32 *)&mask;
2206 mask = (__force unsigned long)cpu_to_le32(be32_to_cpu(mask_be32));
2207 } else if (field_bsize == 16) {
2208 mask_be16 = *(__be16 *)&mask;
2209 mask = (__force unsigned long)cpu_to_le16(be16_to_cpu(mask_be16));
2210 }
2211
d79b6df6 2212 first = find_first_bit(&mask, field_bsize);
2b64beba 2213 next_z = find_next_zero_bit(&mask, field_bsize, first);
d79b6df6 2214 last = find_last_bit(&mask, field_bsize);
2b64beba 2215 if (first < next_z && next_z < last) {
e98bedf5
EB
2216 NL_SET_ERR_MSG_MOD(extack,
2217 "rewrite of few sub-fields isn't supported");
2b64beba 2218 printk(KERN_WARNING "mlx5: rewrite of few sub-fields (mask %lx) isn't offloaded\n",
d79b6df6
OG
2219 mask);
2220 return -EOPNOTSUPP;
2221 }
2222
2223 MLX5_SET(set_action_in, action, action_type, cmd);
2224 MLX5_SET(set_action_in, action, field, f->field);
2225
2226 if (cmd == MLX5_ACTION_TYPE_SET) {
2b64beba 2227 MLX5_SET(set_action_in, action, offset, first);
d79b6df6 2228 /* length is num of bits to be written, zero means length of 32 */
2b64beba 2229 MLX5_SET(set_action_in, action, length, (last - first + 1));
d79b6df6
OG
2230 }
2231
2232 if (field_bsize == 32)
2b64beba 2233 MLX5_SET(set_action_in, action, data, ntohl(*(__be32 *)vals_p) >> first);
d79b6df6 2234 else if (field_bsize == 16)
2b64beba 2235 MLX5_SET(set_action_in, action, data, ntohs(*(__be16 *)vals_p) >> first);
d79b6df6 2236 else if (field_bsize == 8)
2b64beba 2237 MLX5_SET(set_action_in, action, data, *(u8 *)vals_p >> first);
d79b6df6
OG
2238
2239 action += action_size;
2240 nactions++;
2241 }
2242
2243 parse_attr->num_mod_hdr_actions = nactions;
2244 return 0;
2245}
2246
2cc1cb1d
TZ
2247static int mlx5e_flow_namespace_max_modify_action(struct mlx5_core_dev *mdev,
2248 int namespace)
2249{
2250 if (namespace == MLX5_FLOW_NAMESPACE_FDB) /* FDB offloading */
2251 return MLX5_CAP_ESW_FLOWTABLE_FDB(mdev, max_modify_header_actions);
2252 else /* namespace is MLX5_FLOW_NAMESPACE_KERNEL - NIC offloading */
2253 return MLX5_CAP_FLOWTABLE_NIC_RX(mdev, max_modify_header_actions);
2254}
2255
d79b6df6 2256static int alloc_mod_hdr_actions(struct mlx5e_priv *priv,
c500c86b
PNA
2257 struct pedit_headers_action *hdrs,
2258 int namespace,
d79b6df6
OG
2259 struct mlx5e_tc_flow_parse_attr *parse_attr)
2260{
2261 int nkeys, action_size, max_actions;
2262
c500c86b
PNA
2263 nkeys = hdrs[TCA_PEDIT_KEY_EX_CMD_SET].pedits +
2264 hdrs[TCA_PEDIT_KEY_EX_CMD_ADD].pedits;
d79b6df6
OG
2265 action_size = MLX5_UN_SZ_BYTES(set_action_in_add_action_in_auto);
2266
2cc1cb1d 2267 max_actions = mlx5e_flow_namespace_max_modify_action(priv->mdev, namespace);
d79b6df6
OG
2268 /* can get up to crazingly 16 HW actions in 32 bits pedit SW key */
2269 max_actions = min(max_actions, nkeys * 16);
2270
2271 parse_attr->mod_hdr_actions = kcalloc(max_actions, action_size, GFP_KERNEL);
2272 if (!parse_attr->mod_hdr_actions)
2273 return -ENOMEM;
2274
218d05ce 2275 parse_attr->max_mod_hdr_actions = max_actions;
d79b6df6
OG
2276 return 0;
2277}
2278
2279static const struct pedit_headers zero_masks = {};
2280
2281static int parse_tc_pedit_action(struct mlx5e_priv *priv,
73867881 2282 const struct flow_action_entry *act, int namespace,
e98bedf5 2283 struct mlx5e_tc_flow_parse_attr *parse_attr,
c500c86b 2284 struct pedit_headers_action *hdrs,
e98bedf5 2285 struct netlink_ext_ack *extack)
d79b6df6 2286{
73867881
PNA
2287 u8 cmd = (act->id == FLOW_ACTION_MANGLE) ? 0 : 1;
2288 int err = -EOPNOTSUPP;
d79b6df6 2289 u32 mask, val, offset;
73867881 2290 u8 htype;
d79b6df6 2291
73867881
PNA
2292 htype = act->mangle.htype;
2293 err = -EOPNOTSUPP; /* can't be all optimistic */
d79b6df6 2294
73867881
PNA
2295 if (htype == FLOW_ACT_MANGLE_UNSPEC) {
2296 NL_SET_ERR_MSG_MOD(extack, "legacy pedit isn't offloaded");
2297 goto out_err;
2298 }
d79b6df6 2299
2cc1cb1d
TZ
2300 if (!mlx5e_flow_namespace_max_modify_action(priv->mdev, namespace)) {
2301 NL_SET_ERR_MSG_MOD(extack,
2302 "The pedit offload action is not supported");
2303 goto out_err;
2304 }
2305
73867881
PNA
2306 mask = act->mangle.mask;
2307 val = act->mangle.val;
2308 offset = act->mangle.offset;
d79b6df6 2309
73867881
PNA
2310 err = set_pedit_val(htype, ~mask, val, offset, &hdrs[cmd]);
2311 if (err)
2312 goto out_err;
c500c86b 2313
73867881 2314 hdrs[cmd].pedits++;
d79b6df6 2315
c500c86b
PNA
2316 return 0;
2317out_err:
2318 return err;
2319}
2320
2321static int alloc_tc_pedit_action(struct mlx5e_priv *priv, int namespace,
2322 struct mlx5e_tc_flow_parse_attr *parse_attr,
2323 struct pedit_headers_action *hdrs,
27c11b6b 2324 u32 *action_flags,
c500c86b
PNA
2325 struct netlink_ext_ack *extack)
2326{
2327 struct pedit_headers *cmd_masks;
2328 int err;
2329 u8 cmd;
2330
218d05ce 2331 if (!parse_attr->mod_hdr_actions) {
a655fe9f 2332 err = alloc_mod_hdr_actions(priv, hdrs, namespace, parse_attr);
218d05ce
TZ
2333 if (err)
2334 goto out_err;
2335 }
d79b6df6 2336
27c11b6b 2337 err = offload_pedit_fields(hdrs, parse_attr, action_flags, extack);
d79b6df6
OG
2338 if (err < 0)
2339 goto out_dealloc_parsed_actions;
2340
2341 for (cmd = 0; cmd < __PEDIT_CMD_MAX; cmd++) {
c500c86b 2342 cmd_masks = &hdrs[cmd].masks;
d79b6df6 2343 if (memcmp(cmd_masks, &zero_masks, sizeof(zero_masks))) {
e98bedf5
EB
2344 NL_SET_ERR_MSG_MOD(extack,
2345 "attempt to offload an unsupported field");
b3a433de 2346 netdev_warn(priv->netdev, "attempt to offload an unsupported field (cmd %d)\n", cmd);
d79b6df6
OG
2347 print_hex_dump(KERN_WARNING, "mask: ", DUMP_PREFIX_ADDRESS,
2348 16, 1, cmd_masks, sizeof(zero_masks), true);
2349 err = -EOPNOTSUPP;
2350 goto out_dealloc_parsed_actions;
2351 }
2352 }
2353
2354 return 0;
2355
2356out_dealloc_parsed_actions:
2357 kfree(parse_attr->mod_hdr_actions);
2358out_err:
2359 return err;
2360}
2361
e98bedf5
EB
2362static bool csum_offload_supported(struct mlx5e_priv *priv,
2363 u32 action,
2364 u32 update_flags,
2365 struct netlink_ext_ack *extack)
26c02749
OG
2366{
2367 u32 prot_flags = TCA_CSUM_UPDATE_FLAG_IPV4HDR | TCA_CSUM_UPDATE_FLAG_TCP |
2368 TCA_CSUM_UPDATE_FLAG_UDP;
2369
2370 /* The HW recalcs checksums only if re-writing headers */
2371 if (!(action & MLX5_FLOW_CONTEXT_ACTION_MOD_HDR)) {
e98bedf5
EB
2372 NL_SET_ERR_MSG_MOD(extack,
2373 "TC csum action is only offloaded with pedit");
26c02749
OG
2374 netdev_warn(priv->netdev,
2375 "TC csum action is only offloaded with pedit\n");
2376 return false;
2377 }
2378
2379 if (update_flags & ~prot_flags) {
e98bedf5
EB
2380 NL_SET_ERR_MSG_MOD(extack,
2381 "can't offload TC csum action for some header/s");
26c02749
OG
2382 netdev_warn(priv->netdev,
2383 "can't offload TC csum action for some header/s - flags %#x\n",
2384 update_flags);
2385 return false;
2386 }
2387
2388 return true;
2389}
2390
8998576b
DL
2391struct ip_ttl_word {
2392 __u8 ttl;
2393 __u8 protocol;
2394 __sum16 check;
2395};
2396
2397struct ipv6_hoplimit_word {
2398 __be16 payload_len;
2399 __u8 nexthdr;
2400 __u8 hop_limit;
2401};
2402
2403static bool is_action_keys_supported(const struct flow_action_entry *act)
2404{
2405 u32 mask, offset;
2406 u8 htype;
2407
2408 htype = act->mangle.htype;
2409 offset = act->mangle.offset;
2410 mask = ~act->mangle.mask;
2411 /* For IPv4 & IPv6 header check 4 byte word,
2412 * to determine that modified fields
2413 * are NOT ttl & hop_limit only.
2414 */
2415 if (htype == FLOW_ACT_MANGLE_HDR_TYPE_IP4) {
2416 struct ip_ttl_word *ttl_word =
2417 (struct ip_ttl_word *)&mask;
2418
2419 if (offset != offsetof(struct iphdr, ttl) ||
2420 ttl_word->protocol ||
2421 ttl_word->check) {
2422 return true;
2423 }
2424 } else if (htype == FLOW_ACT_MANGLE_HDR_TYPE_IP6) {
2425 struct ipv6_hoplimit_word *hoplimit_word =
2426 (struct ipv6_hoplimit_word *)&mask;
2427
2428 if (offset != offsetof(struct ipv6hdr, payload_len) ||
2429 hoplimit_word->payload_len ||
2430 hoplimit_word->nexthdr) {
2431 return true;
2432 }
2433 }
2434 return false;
2435}
2436
bdd66ac0 2437static bool modify_header_match_supported(struct mlx5_flow_spec *spec,
73867881 2438 struct flow_action *flow_action,
1651925d 2439 u32 actions,
e98bedf5 2440 struct netlink_ext_ack *extack)
bdd66ac0 2441{
73867881 2442 const struct flow_action_entry *act;
bdd66ac0 2443 bool modify_ip_header;
bdd66ac0
OG
2444 void *headers_v;
2445 u16 ethertype;
8998576b 2446 u8 ip_proto;
73867881 2447 int i;
bdd66ac0 2448
8377629e 2449 headers_v = get_match_headers_value(actions, spec);
bdd66ac0
OG
2450 ethertype = MLX5_GET(fte_match_set_lyr_2_4, headers_v, ethertype);
2451
2452 /* for non-IP we only re-write MACs, so we're okay */
2453 if (ethertype != ETH_P_IP && ethertype != ETH_P_IPV6)
2454 goto out_ok;
2455
2456 modify_ip_header = false;
73867881
PNA
2457 flow_action_for_each(i, act, flow_action) {
2458 if (act->id != FLOW_ACTION_MANGLE &&
2459 act->id != FLOW_ACTION_ADD)
bdd66ac0
OG
2460 continue;
2461
8998576b 2462 if (is_action_keys_supported(act)) {
73867881
PNA
2463 modify_ip_header = true;
2464 break;
bdd66ac0
OG
2465 }
2466 }
2467
2468 ip_proto = MLX5_GET(fte_match_set_lyr_2_4, headers_v, ip_protocol);
1ccef350
JL
2469 if (modify_ip_header && ip_proto != IPPROTO_TCP &&
2470 ip_proto != IPPROTO_UDP && ip_proto != IPPROTO_ICMP) {
e98bedf5
EB
2471 NL_SET_ERR_MSG_MOD(extack,
2472 "can't offload re-write of non TCP/UDP");
bdd66ac0
OG
2473 pr_info("can't offload re-write of ip proto %d\n", ip_proto);
2474 return false;
2475 }
2476
2477out_ok:
2478 return true;
2479}
2480
2481static bool actions_match_supported(struct mlx5e_priv *priv,
73867881 2482 struct flow_action *flow_action,
bdd66ac0 2483 struct mlx5e_tc_flow_parse_attr *parse_attr,
e98bedf5
EB
2484 struct mlx5e_tc_flow *flow,
2485 struct netlink_ext_ack *extack)
bdd66ac0
OG
2486{
2487 u32 actions;
2488
226f2ca3 2489 if (mlx5e_is_eswitch_flow(flow))
bdd66ac0
OG
2490 actions = flow->esw_attr->action;
2491 else
2492 actions = flow->nic_attr->action;
2493
226f2ca3 2494 if (flow_flag_test(flow, EGRESS) &&
35a605db 2495 !((actions & MLX5_FLOW_CONTEXT_ACTION_DECAP) ||
6830b468
TZ
2496 (actions & MLX5_FLOW_CONTEXT_ACTION_VLAN_POP) ||
2497 (actions & MLX5_FLOW_CONTEXT_ACTION_DROP)))
7e29392e
RD
2498 return false;
2499
bdd66ac0 2500 if (actions & MLX5_FLOW_CONTEXT_ACTION_MOD_HDR)
73867881 2501 return modify_header_match_supported(&parse_attr->spec,
a655fe9f 2502 flow_action, actions,
e98bedf5 2503 extack);
bdd66ac0
OG
2504
2505 return true;
2506}
2507
5c65c564
OG
2508static bool same_hw_devs(struct mlx5e_priv *priv, struct mlx5e_priv *peer_priv)
2509{
2510 struct mlx5_core_dev *fmdev, *pmdev;
816f6706 2511 u64 fsystem_guid, psystem_guid;
5c65c564
OG
2512
2513 fmdev = priv->mdev;
2514 pmdev = peer_priv->mdev;
2515
59c9d35e
AH
2516 fsystem_guid = mlx5_query_nic_system_image_guid(fmdev);
2517 psystem_guid = mlx5_query_nic_system_image_guid(pmdev);
5c65c564 2518
816f6706 2519 return (fsystem_guid == psystem_guid);
5c65c564
OG
2520}
2521
bdc837ee
EB
2522static int add_vlan_rewrite_action(struct mlx5e_priv *priv, int namespace,
2523 const struct flow_action_entry *act,
2524 struct mlx5e_tc_flow_parse_attr *parse_attr,
2525 struct pedit_headers_action *hdrs,
2526 u32 *action, struct netlink_ext_ack *extack)
2527{
2528 u16 mask16 = VLAN_VID_MASK;
2529 u16 val16 = act->vlan.vid & VLAN_VID_MASK;
2530 const struct flow_action_entry pedit_act = {
2531 .id = FLOW_ACTION_MANGLE,
2532 .mangle.htype = FLOW_ACT_MANGLE_HDR_TYPE_ETH,
2533 .mangle.offset = offsetof(struct vlan_ethhdr, h_vlan_TCI),
2534 .mangle.mask = ~(u32)be16_to_cpu(*(__be16 *)&mask16),
2535 .mangle.val = (u32)be16_to_cpu(*(__be16 *)&val16),
2536 };
6fca9d1e 2537 u8 match_prio_mask, match_prio_val;
bf2f3bca 2538 void *headers_c, *headers_v;
bdc837ee
EB
2539 int err;
2540
bf2f3bca
EB
2541 headers_c = get_match_headers_criteria(*action, &parse_attr->spec);
2542 headers_v = get_match_headers_value(*action, &parse_attr->spec);
2543
2544 if (!(MLX5_GET(fte_match_set_lyr_2_4, headers_c, cvlan_tag) &&
2545 MLX5_GET(fte_match_set_lyr_2_4, headers_v, cvlan_tag))) {
2546 NL_SET_ERR_MSG_MOD(extack,
2547 "VLAN rewrite action must have VLAN protocol match");
2548 return -EOPNOTSUPP;
2549 }
2550
6fca9d1e
EB
2551 match_prio_mask = MLX5_GET(fte_match_set_lyr_2_4, headers_c, first_prio);
2552 match_prio_val = MLX5_GET(fte_match_set_lyr_2_4, headers_v, first_prio);
2553 if (act->vlan.prio != (match_prio_val & match_prio_mask)) {
2554 NL_SET_ERR_MSG_MOD(extack,
2555 "Changing VLAN prio is not supported");
bdc837ee
EB
2556 return -EOPNOTSUPP;
2557 }
2558
2559 err = parse_tc_pedit_action(priv, &pedit_act, namespace, parse_attr,
2560 hdrs, NULL);
2561 *action |= MLX5_FLOW_CONTEXT_ACTION_MOD_HDR;
2562
2563 return err;
2564}
2565
0bac1194
EB
2566static int
2567add_vlan_prio_tag_rewrite_action(struct mlx5e_priv *priv,
2568 struct mlx5e_tc_flow_parse_attr *parse_attr,
2569 struct pedit_headers_action *hdrs,
2570 u32 *action, struct netlink_ext_ack *extack)
2571{
2572 const struct flow_action_entry prio_tag_act = {
2573 .vlan.vid = 0,
2574 .vlan.prio =
2575 MLX5_GET(fte_match_set_lyr_2_4,
2576 get_match_headers_value(*action,
2577 &parse_attr->spec),
2578 first_prio) &
2579 MLX5_GET(fte_match_set_lyr_2_4,
2580 get_match_headers_criteria(*action,
2581 &parse_attr->spec),
2582 first_prio),
2583 };
2584
2585 return add_vlan_rewrite_action(priv, MLX5_FLOW_NAMESPACE_FDB,
2586 &prio_tag_act, parse_attr, hdrs, action,
2587 extack);
2588}
2589
73867881
PNA
2590static int parse_tc_nic_actions(struct mlx5e_priv *priv,
2591 struct flow_action *flow_action,
aa0cbbae 2592 struct mlx5e_tc_flow_parse_attr *parse_attr,
e98bedf5
EB
2593 struct mlx5e_tc_flow *flow,
2594 struct netlink_ext_ack *extack)
e3a2b7ed 2595{
aa0cbbae 2596 struct mlx5_nic_flow_attr *attr = flow->nic_attr;
73867881
PNA
2597 struct pedit_headers_action hdrs[2] = {};
2598 const struct flow_action_entry *act;
1cab1cd7 2599 u32 action = 0;
244cd96a 2600 int err, i;
e3a2b7ed 2601
73867881 2602 if (!flow_action_has_entries(flow_action))
e3a2b7ed
AV
2603 return -EINVAL;
2604
3bc4b7bf 2605 attr->flow_tag = MLX5_FS_DEFAULT_FLOW_TAG;
e3a2b7ed 2606
73867881
PNA
2607 flow_action_for_each(i, act, flow_action) {
2608 switch (act->id) {
2609 case FLOW_ACTION_DROP:
1cab1cd7 2610 action |= MLX5_FLOW_CONTEXT_ACTION_DROP;
aad7e08d
AV
2611 if (MLX5_CAP_FLOWTABLE(priv->mdev,
2612 flow_table_properties_nic_receive.flow_counter))
1cab1cd7 2613 action |= MLX5_FLOW_CONTEXT_ACTION_COUNT;
73867881
PNA
2614 break;
2615 case FLOW_ACTION_MANGLE:
2616 case FLOW_ACTION_ADD:
2617 err = parse_tc_pedit_action(priv, act, MLX5_FLOW_NAMESPACE_KERNEL,
c500c86b 2618 parse_attr, hdrs, extack);
2f4fe4ca
OG
2619 if (err)
2620 return err;
2621
1cab1cd7
OG
2622 action |= MLX5_FLOW_CONTEXT_ACTION_MOD_HDR |
2623 MLX5_FLOW_CONTEXT_ACTION_FWD_DEST;
73867881 2624 break;
bdc837ee
EB
2625 case FLOW_ACTION_VLAN_MANGLE:
2626 err = add_vlan_rewrite_action(priv,
2627 MLX5_FLOW_NAMESPACE_KERNEL,
2628 act, parse_attr, hdrs,
2629 &action, extack);
2630 if (err)
2631 return err;
2632
2633 break;
73867881 2634 case FLOW_ACTION_CSUM:
1cab1cd7 2635 if (csum_offload_supported(priv, action,
73867881 2636 act->csum_flags,
e98bedf5 2637 extack))
73867881 2638 break;
26c02749
OG
2639
2640 return -EOPNOTSUPP;
73867881
PNA
2641 case FLOW_ACTION_REDIRECT: {
2642 struct net_device *peer_dev = act->dev;
5c65c564
OG
2643
2644 if (priv->netdev->netdev_ops == peer_dev->netdev_ops &&
2645 same_hw_devs(priv, netdev_priv(peer_dev))) {
98b66cb1 2646 parse_attr->mirred_ifindex[0] = peer_dev->ifindex;
226f2ca3 2647 flow_flag_set(flow, HAIRPIN);
1cab1cd7
OG
2648 action |= MLX5_FLOW_CONTEXT_ACTION_FWD_DEST |
2649 MLX5_FLOW_CONTEXT_ACTION_COUNT;
5c65c564 2650 } else {
e98bedf5
EB
2651 NL_SET_ERR_MSG_MOD(extack,
2652 "device is not on same HW, can't offload");
5c65c564
OG
2653 netdev_warn(priv->netdev, "device %s not on same HW, can't offload\n",
2654 peer_dev->name);
2655 return -EINVAL;
2656 }
73867881
PNA
2657 }
2658 break;
2659 case FLOW_ACTION_MARK: {
2660 u32 mark = act->mark;
e3a2b7ed
AV
2661
2662 if (mark & ~MLX5E_TC_FLOW_ID_MASK) {
e98bedf5
EB
2663 NL_SET_ERR_MSG_MOD(extack,
2664 "Bad flow mark - only 16 bit is supported");
e3a2b7ed
AV
2665 return -EINVAL;
2666 }
2667
3bc4b7bf 2668 attr->flow_tag = mark;
1cab1cd7 2669 action |= MLX5_FLOW_CONTEXT_ACTION_FWD_DEST;
73867881
PNA
2670 }
2671 break;
2672 default:
2cc1cb1d
TZ
2673 NL_SET_ERR_MSG_MOD(extack, "The offload action is not supported");
2674 return -EOPNOTSUPP;
e3a2b7ed 2675 }
e3a2b7ed
AV
2676 }
2677
c500c86b
PNA
2678 if (hdrs[TCA_PEDIT_KEY_EX_CMD_SET].pedits ||
2679 hdrs[TCA_PEDIT_KEY_EX_CMD_ADD].pedits) {
2680 err = alloc_tc_pedit_action(priv, MLX5_FLOW_NAMESPACE_KERNEL,
27c11b6b 2681 parse_attr, hdrs, &action, extack);
c500c86b
PNA
2682 if (err)
2683 return err;
27c11b6b
EB
2684 /* in case all pedit actions are skipped, remove the MOD_HDR
2685 * flag.
2686 */
e7739a60 2687 if (parse_attr->num_mod_hdr_actions == 0) {
27c11b6b 2688 action &= ~MLX5_FLOW_CONTEXT_ACTION_MOD_HDR;
e7739a60
EB
2689 kfree(parse_attr->mod_hdr_actions);
2690 }
c500c86b
PNA
2691 }
2692
1cab1cd7 2693 attr->action = action;
73867881 2694 if (!actions_match_supported(priv, flow_action, parse_attr, flow, extack))
bdd66ac0
OG
2695 return -EOPNOTSUPP;
2696
e3a2b7ed
AV
2697 return 0;
2698}
2699
7f1a546e 2700struct encap_key {
1f6da306 2701 const struct ip_tunnel_key *ip_tun_key;
d386939a 2702 struct mlx5e_tc_tunnel *tc_tunnel;
7f1a546e
EB
2703};
2704
2705static inline int cmp_encap_info(struct encap_key *a,
2706 struct encap_key *b)
a54e20b4 2707{
7f1a546e 2708 return memcmp(a->ip_tun_key, b->ip_tun_key, sizeof(*a->ip_tun_key)) ||
d386939a 2709 a->tc_tunnel->tunnel_type != b->tc_tunnel->tunnel_type;
a54e20b4
HHZ
2710}
2711
7f1a546e 2712static inline int hash_encap_info(struct encap_key *key)
a54e20b4 2713{
7f1a546e 2714 return jhash(key->ip_tun_key, sizeof(*key->ip_tun_key),
d386939a 2715 key->tc_tunnel->tunnel_type);
a54e20b4
HHZ
2716}
2717
a54e20b4 2718
b1d90e6b
RL
2719static bool is_merged_eswitch_dev(struct mlx5e_priv *priv,
2720 struct net_device *peer_netdev)
2721{
2722 struct mlx5e_priv *peer_priv;
2723
2724 peer_priv = netdev_priv(peer_netdev);
2725
2726 return (MLX5_CAP_ESW(priv->mdev, merged_eswitch) &&
68931c7d
RD
2727 mlx5e_eswitch_rep(priv->netdev) &&
2728 mlx5e_eswitch_rep(peer_netdev) &&
2729 same_hw_devs(priv, peer_priv));
b1d90e6b
RL
2730}
2731
32f3671f 2732
f5bc2c5d 2733
a54e20b4 2734static int mlx5e_attach_encap(struct mlx5e_priv *priv,
e98bedf5 2735 struct mlx5e_tc_flow *flow,
733d4f36
RD
2736 struct net_device *mirred_dev,
2737 int out_index,
8c4dc42b 2738 struct netlink_ext_ack *extack,
0ad060ee
RD
2739 struct net_device **encap_dev,
2740 bool *encap_valid)
a54e20b4
HHZ
2741{
2742 struct mlx5_eswitch *esw = priv->mdev->priv.eswitch;
45247bf2 2743 struct mlx5_esw_flow_attr *attr = flow->esw_attr;
733d4f36 2744 struct mlx5e_tc_flow_parse_attr *parse_attr;
1f6da306 2745 const struct ip_tunnel_info *tun_info;
7f1a546e 2746 struct encap_key key, e_key;
c1ae1152 2747 struct mlx5e_encap_entry *e;
733d4f36 2748 unsigned short family;
a54e20b4
HHZ
2749 uintptr_t hash_key;
2750 bool found = false;
54c177ca 2751 int err = 0;
a54e20b4 2752
733d4f36 2753 parse_attr = attr->parse_attr;
1f6da306 2754 tun_info = parse_attr->tun_info[out_index];
733d4f36 2755 family = ip_tunnel_info_af(tun_info);
7f1a546e 2756 key.ip_tun_key = &tun_info->key;
d386939a 2757 key.tc_tunnel = mlx5e_get_tc_tun(mirred_dev);
d71f895c
EC
2758 if (!key.tc_tunnel) {
2759 NL_SET_ERR_MSG_MOD(extack, "Unsupported tunnel");
2760 return -EOPNOTSUPP;
2761 }
733d4f36 2762
7f1a546e 2763 hash_key = hash_encap_info(&key);
a54e20b4
HHZ
2764
2765 hash_for_each_possible_rcu(esw->offloads.encap_tbl, e,
2766 encap_hlist, hash_key) {
1f6da306 2767 e_key.ip_tun_key = &e->tun_info->key;
d386939a 2768 e_key.tc_tunnel = e->tunnel;
7f1a546e 2769 if (!cmp_encap_info(&e_key, &key)) {
a54e20b4
HHZ
2770 found = true;
2771 break;
2772 }
2773 }
2774
b2812089 2775 /* must verify if encap is valid or not */
45247bf2
OG
2776 if (found)
2777 goto attach_flow;
a54e20b4
HHZ
2778
2779 e = kzalloc(sizeof(*e), GFP_KERNEL);
2780 if (!e)
2781 return -ENOMEM;
2782
1f6da306 2783 e->tun_info = tun_info;
101f4de9 2784 err = mlx5e_tc_tun_init_encap_attr(mirred_dev, priv, e, extack);
54c177ca
OS
2785 if (err)
2786 goto out_err;
2787
a54e20b4
HHZ
2788 INIT_LIST_HEAD(&e->flows);
2789
ce99f6b9 2790 if (family == AF_INET)
101f4de9 2791 err = mlx5e_tc_tun_create_header_ipv4(priv, mirred_dev, e);
ce99f6b9 2792 else if (family == AF_INET6)
101f4de9 2793 err = mlx5e_tc_tun_create_header_ipv6(priv, mirred_dev, e);
ce99f6b9 2794
0ad060ee 2795 if (err)
a54e20b4
HHZ
2796 goto out_err;
2797
a54e20b4
HHZ
2798 hash_add_rcu(esw->offloads.encap_tbl, &e->encap_hlist, hash_key);
2799
45247bf2 2800attach_flow:
8c4dc42b
EB
2801 list_add(&flow->encaps[out_index].list, &e->flows);
2802 flow->encaps[out_index].index = out_index;
45247bf2 2803 *encap_dev = e->out_dev;
8c4dc42b
EB
2804 if (e->flags & MLX5_ENCAP_ENTRY_VALID) {
2805 attr->dests[out_index].encap_id = e->encap_id;
2806 attr->dests[out_index].flags |= MLX5_ESW_DEST_ENCAP_VALID;
0ad060ee 2807 *encap_valid = true;
8c4dc42b 2808 } else {
0ad060ee 2809 *encap_valid = false;
8c4dc42b 2810 }
45247bf2 2811
232c0013 2812 return err;
a54e20b4
HHZ
2813
2814out_err:
2815 kfree(e);
2816 return err;
2817}
2818
1482bd3d 2819static int parse_tc_vlan_action(struct mlx5e_priv *priv,
73867881 2820 const struct flow_action_entry *act,
1482bd3d
JL
2821 struct mlx5_esw_flow_attr *attr,
2822 u32 *action)
2823{
cc495188
JL
2824 u8 vlan_idx = attr->total_vlan;
2825
2826 if (vlan_idx >= MLX5_FS_VLAN_DEPTH)
2827 return -EOPNOTSUPP;
2828
73867881
PNA
2829 switch (act->id) {
2830 case FLOW_ACTION_VLAN_POP:
cc495188
JL
2831 if (vlan_idx) {
2832 if (!mlx5_eswitch_vlan_actions_supported(priv->mdev,
2833 MLX5_FS_VLAN_DEPTH))
2834 return -EOPNOTSUPP;
2835
2836 *action |= MLX5_FLOW_CONTEXT_ACTION_VLAN_POP_2;
2837 } else {
2838 *action |= MLX5_FLOW_CONTEXT_ACTION_VLAN_POP;
2839 }
73867881
PNA
2840 break;
2841 case FLOW_ACTION_VLAN_PUSH:
2842 attr->vlan_vid[vlan_idx] = act->vlan.vid;
2843 attr->vlan_prio[vlan_idx] = act->vlan.prio;
2844 attr->vlan_proto[vlan_idx] = act->vlan.proto;
cc495188
JL
2845 if (!attr->vlan_proto[vlan_idx])
2846 attr->vlan_proto[vlan_idx] = htons(ETH_P_8021Q);
2847
2848 if (vlan_idx) {
2849 if (!mlx5_eswitch_vlan_actions_supported(priv->mdev,
2850 MLX5_FS_VLAN_DEPTH))
2851 return -EOPNOTSUPP;
2852
2853 *action |= MLX5_FLOW_CONTEXT_ACTION_VLAN_PUSH_2;
2854 } else {
2855 if (!mlx5_eswitch_vlan_actions_supported(priv->mdev, 1) &&
73867881
PNA
2856 (act->vlan.proto != htons(ETH_P_8021Q) ||
2857 act->vlan.prio))
cc495188
JL
2858 return -EOPNOTSUPP;
2859
2860 *action |= MLX5_FLOW_CONTEXT_ACTION_VLAN_PUSH;
1482bd3d 2861 }
73867881
PNA
2862 break;
2863 default:
bdc837ee 2864 return -EINVAL;
1482bd3d
JL
2865 }
2866
cc495188
JL
2867 attr->total_vlan = vlan_idx + 1;
2868
1482bd3d
JL
2869 return 0;
2870}
2871
278748a9
EB
2872static int add_vlan_push_action(struct mlx5e_priv *priv,
2873 struct mlx5_esw_flow_attr *attr,
2874 struct net_device **out_dev,
2875 u32 *action)
2876{
2877 struct net_device *vlan_dev = *out_dev;
2878 struct flow_action_entry vlan_act = {
2879 .id = FLOW_ACTION_VLAN_PUSH,
2880 .vlan.vid = vlan_dev_vlan_id(vlan_dev),
2881 .vlan.proto = vlan_dev_vlan_proto(vlan_dev),
2882 .vlan.prio = 0,
2883 };
2884 int err;
2885
2886 err = parse_tc_vlan_action(priv, &vlan_act, attr, action);
2887 if (err)
2888 return err;
2889
2890 *out_dev = dev_get_by_index_rcu(dev_net(vlan_dev),
2891 dev_get_iflink(vlan_dev));
2892 if (is_vlan_dev(*out_dev))
2893 err = add_vlan_push_action(priv, attr, out_dev, action);
2894
2895 return err;
2896}
2897
35a605db
EB
2898static int add_vlan_pop_action(struct mlx5e_priv *priv,
2899 struct mlx5_esw_flow_attr *attr,
2900 u32 *action)
2901{
2902 int nest_level = vlan_get_encap_level(attr->parse_attr->filter_dev);
2903 struct flow_action_entry vlan_act = {
2904 .id = FLOW_ACTION_VLAN_POP,
2905 };
2906 int err = 0;
2907
2908 while (nest_level--) {
2909 err = parse_tc_vlan_action(priv, &vlan_act, attr, action);
2910 if (err)
2911 return err;
2912 }
2913
2914 return err;
2915}
2916
f6dc1264
PB
2917bool mlx5e_is_valid_eswitch_fwd_dev(struct mlx5e_priv *priv,
2918 struct net_device *out_dev)
2919{
2920 if (is_merged_eswitch_dev(priv, out_dev))
2921 return true;
2922
2923 return mlx5e_eswitch_rep(out_dev) &&
2924 same_hw_devs(priv, netdev_priv(out_dev));
2925}
2926
73867881
PNA
2927static int parse_tc_fdb_actions(struct mlx5e_priv *priv,
2928 struct flow_action *flow_action,
e98bedf5
EB
2929 struct mlx5e_tc_flow *flow,
2930 struct netlink_ext_ack *extack)
03a9d11e 2931{
73867881 2932 struct pedit_headers_action hdrs[2] = {};
bf07aa73 2933 struct mlx5_eswitch *esw = priv->mdev->priv.eswitch;
ecf5bb79 2934 struct mlx5_esw_flow_attr *attr = flow->esw_attr;
6f9af8ff 2935 struct mlx5e_tc_flow_parse_attr *parse_attr = attr->parse_attr;
1d447a39 2936 struct mlx5e_rep_priv *rpriv = priv->ppriv;
73867881
PNA
2937 const struct ip_tunnel_info *info = NULL;
2938 const struct flow_action_entry *act;
a54e20b4 2939 bool encap = false;
1cab1cd7 2940 u32 action = 0;
244cd96a 2941 int err, i;
03a9d11e 2942
73867881 2943 if (!flow_action_has_entries(flow_action))
03a9d11e
OG
2944 return -EINVAL;
2945
73867881
PNA
2946 flow_action_for_each(i, act, flow_action) {
2947 switch (act->id) {
2948 case FLOW_ACTION_DROP:
1cab1cd7
OG
2949 action |= MLX5_FLOW_CONTEXT_ACTION_DROP |
2950 MLX5_FLOW_CONTEXT_ACTION_COUNT;
73867881
PNA
2951 break;
2952 case FLOW_ACTION_MANGLE:
2953 case FLOW_ACTION_ADD:
2954 err = parse_tc_pedit_action(priv, act, MLX5_FLOW_NAMESPACE_FDB,
c500c86b 2955 parse_attr, hdrs, extack);
d7e75a32
OG
2956 if (err)
2957 return err;
2958
1cab1cd7 2959 action |= MLX5_FLOW_CONTEXT_ACTION_MOD_HDR;
e85e02ba 2960 attr->split_count = attr->out_count;
73867881
PNA
2961 break;
2962 case FLOW_ACTION_CSUM:
1cab1cd7 2963 if (csum_offload_supported(priv, action,
73867881
PNA
2964 act->csum_flags, extack))
2965 break;
26c02749
OG
2966
2967 return -EOPNOTSUPP;
73867881
PNA
2968 case FLOW_ACTION_REDIRECT:
2969 case FLOW_ACTION_MIRRED: {
03a9d11e 2970 struct mlx5e_priv *out_priv;
592d3651 2971 struct net_device *out_dev;
03a9d11e 2972
73867881 2973 out_dev = act->dev;
ef381359
OS
2974 if (!out_dev) {
2975 /* out_dev is NULL when filters with
2976 * non-existing mirred device are replayed to
2977 * the driver.
2978 */
2979 return -EINVAL;
2980 }
03a9d11e 2981
592d3651 2982 if (attr->out_count >= MLX5_MAX_FLOW_FWD_VPORTS) {
e98bedf5
EB
2983 NL_SET_ERR_MSG_MOD(extack,
2984 "can't support more output ports, can't offload forwarding");
592d3651
CM
2985 pr_err("can't support more than %d output ports, can't offload forwarding\n",
2986 attr->out_count);
2987 return -EOPNOTSUPP;
2988 }
2989
f493f155
EB
2990 action |= MLX5_FLOW_CONTEXT_ACTION_FWD_DEST |
2991 MLX5_FLOW_CONTEXT_ACTION_COUNT;
f6dc1264 2992 if (netdev_port_same_parent_id(priv->netdev, out_dev)) {
7ba58ba7
RL
2993 struct mlx5_eswitch *esw = priv->mdev->priv.eswitch;
2994 struct net_device *uplink_dev = mlx5_eswitch_uplink_get_proto_dev(esw, REP_ETH);
fa833bd5 2995 struct net_device *uplink_upper;
7ba58ba7 2996
fa833bd5
VB
2997 rcu_read_lock();
2998 uplink_upper =
2999 netdev_master_upper_dev_get_rcu(uplink_dev);
7ba58ba7
RL
3000 if (uplink_upper &&
3001 netif_is_lag_master(uplink_upper) &&
3002 uplink_upper == out_dev)
3003 out_dev = uplink_dev;
fa833bd5 3004 rcu_read_unlock();
7ba58ba7 3005
278748a9
EB
3006 if (is_vlan_dev(out_dev)) {
3007 err = add_vlan_push_action(priv, attr,
3008 &out_dev,
3009 &action);
3010 if (err)
3011 return err;
3012 }
f6dc1264 3013
35a605db
EB
3014 if (is_vlan_dev(parse_attr->filter_dev)) {
3015 err = add_vlan_pop_action(priv, attr,
3016 &action);
3017 if (err)
3018 return err;
3019 }
278748a9 3020
f6dc1264
PB
3021 if (!mlx5e_is_valid_eswitch_fwd_dev(priv, out_dev)) {
3022 NL_SET_ERR_MSG_MOD(extack,
3023 "devices are not on same switch HW, can't offload forwarding");
3024 pr_err("devices %s %s not on same switch HW, can't offload forwarding\n",
3025 priv->netdev->name, out_dev->name);
a0646c88 3026 return -EOPNOTSUPP;
f6dc1264 3027 }
a0646c88 3028
a54e20b4 3029 out_priv = netdev_priv(out_dev);
1d447a39 3030 rpriv = out_priv->ppriv;
df65a573
EB
3031 attr->dests[attr->out_count].rep = rpriv->rep;
3032 attr->dests[attr->out_count].mdev = out_priv->mdev;
3033 attr->out_count++;
a54e20b4 3034 } else if (encap) {
8c4dc42b
EB
3035 parse_attr->mirred_ifindex[attr->out_count] =
3036 out_dev->ifindex;
1f6da306 3037 parse_attr->tun_info[attr->out_count] = info;
8c4dc42b 3038 encap = false;
f493f155
EB
3039 attr->dests[attr->out_count].flags |=
3040 MLX5_ESW_DEST_ENCAP;
1cc26d74 3041 attr->out_count++;
df65a573
EB
3042 /* attr->dests[].rep is resolved when we
3043 * handle encap
3044 */
ef381359
OS
3045 } else if (parse_attr->filter_dev != priv->netdev) {
3046 /* All mlx5 devices are called to configure
3047 * high level device filters. Therefore, the
3048 * *attempt* to install a filter on invalid
3049 * eswitch should not trigger an explicit error
3050 */
3051 return -EINVAL;
a54e20b4 3052 } else {
e98bedf5
EB
3053 NL_SET_ERR_MSG_MOD(extack,
3054 "devices are not on same switch HW, can't offload forwarding");
03a9d11e
OG
3055 pr_err("devices %s %s not on same switch HW, can't offload forwarding\n",
3056 priv->netdev->name, out_dev->name);
3057 return -EINVAL;
3058 }
73867881
PNA
3059 }
3060 break;
3061 case FLOW_ACTION_TUNNEL_ENCAP:
3062 info = act->tunnel;
a54e20b4
HHZ
3063 if (info)
3064 encap = true;
3065 else
3066 return -EOPNOTSUPP;
1482bd3d 3067
73867881
PNA
3068 break;
3069 case FLOW_ACTION_VLAN_PUSH:
3070 case FLOW_ACTION_VLAN_POP:
76b496b1
EB
3071 if (act->id == FLOW_ACTION_VLAN_PUSH &&
3072 (action & MLX5_FLOW_CONTEXT_ACTION_VLAN_POP)) {
3073 /* Replace vlan pop+push with vlan modify */
3074 action &= ~MLX5_FLOW_CONTEXT_ACTION_VLAN_POP;
3075 err = add_vlan_rewrite_action(priv,
3076 MLX5_FLOW_NAMESPACE_FDB,
3077 act, parse_attr, hdrs,
3078 &action, extack);
3079 } else {
3080 err = parse_tc_vlan_action(priv, act, attr, &action);
3081 }
1482bd3d
JL
3082 if (err)
3083 return err;
3084
bdc837ee
EB
3085 attr->split_count = attr->out_count;
3086 break;
3087 case FLOW_ACTION_VLAN_MANGLE:
3088 err = add_vlan_rewrite_action(priv,
3089 MLX5_FLOW_NAMESPACE_FDB,
3090 act, parse_attr, hdrs,
3091 &action, extack);
3092 if (err)
3093 return err;
3094
e85e02ba 3095 attr->split_count = attr->out_count;
73867881
PNA
3096 break;
3097 case FLOW_ACTION_TUNNEL_DECAP:
1cab1cd7 3098 action |= MLX5_FLOW_CONTEXT_ACTION_DECAP;
73867881
PNA
3099 break;
3100 case FLOW_ACTION_GOTO: {
3101 u32 dest_chain = act->chain_index;
bf07aa73
PB
3102 u32 max_chain = mlx5_eswitch_get_chain_range(esw);
3103
3104 if (dest_chain <= attr->chain) {
3105 NL_SET_ERR_MSG(extack, "Goto earlier chain isn't supported");
3106 return -EOPNOTSUPP;
3107 }
3108 if (dest_chain > max_chain) {
3109 NL_SET_ERR_MSG(extack, "Requested destination chain is out of supported range");
3110 return -EOPNOTSUPP;
3111 }
e88afe75 3112 action |= MLX5_FLOW_CONTEXT_ACTION_COUNT;
bf07aa73 3113 attr->dest_chain = dest_chain;
73867881
PNA
3114 break;
3115 }
3116 default:
2cc1cb1d
TZ
3117 NL_SET_ERR_MSG_MOD(extack, "The offload action is not supported");
3118 return -EOPNOTSUPP;
bf07aa73 3119 }
03a9d11e 3120 }
bdd66ac0 3121
0bac1194
EB
3122 if (MLX5_CAP_GEN(esw->dev, prio_tag_required) &&
3123 action & MLX5_FLOW_CONTEXT_ACTION_VLAN_POP) {
3124 /* For prio tag mode, replace vlan pop with rewrite vlan prio
3125 * tag rewrite.
3126 */
3127 action &= ~MLX5_FLOW_CONTEXT_ACTION_VLAN_POP;
3128 err = add_vlan_prio_tag_rewrite_action(priv, parse_attr, hdrs,
3129 &action, extack);
3130 if (err)
3131 return err;
3132 }
3133
c500c86b
PNA
3134 if (hdrs[TCA_PEDIT_KEY_EX_CMD_SET].pedits ||
3135 hdrs[TCA_PEDIT_KEY_EX_CMD_ADD].pedits) {
84be899f 3136 err = alloc_tc_pedit_action(priv, MLX5_FLOW_NAMESPACE_FDB,
27c11b6b 3137 parse_attr, hdrs, &action, extack);
c500c86b
PNA
3138 if (err)
3139 return err;
27c11b6b
EB
3140 /* in case all pedit actions are skipped, remove the MOD_HDR
3141 * flag. we might have set split_count either by pedit or
3142 * pop/push. if there is no pop/push either, reset it too.
3143 */
3144 if (parse_attr->num_mod_hdr_actions == 0) {
3145 action &= ~MLX5_FLOW_CONTEXT_ACTION_MOD_HDR;
e7739a60 3146 kfree(parse_attr->mod_hdr_actions);
27c11b6b
EB
3147 if (!((action & MLX5_FLOW_CONTEXT_ACTION_VLAN_POP) ||
3148 (action & MLX5_FLOW_CONTEXT_ACTION_VLAN_PUSH)))
3149 attr->split_count = 0;
3150 }
c500c86b
PNA
3151 }
3152
1cab1cd7 3153 attr->action = action;
73867881 3154 if (!actions_match_supported(priv, flow_action, parse_attr, flow, extack))
bdd66ac0
OG
3155 return -EOPNOTSUPP;
3156
e88afe75
OG
3157 if (attr->dest_chain) {
3158 if (attr->action & MLX5_FLOW_CONTEXT_ACTION_FWD_DEST) {
3159 NL_SET_ERR_MSG(extack, "Mirroring goto chain rules isn't supported");
3160 return -EOPNOTSUPP;
3161 }
3162 attr->action |= MLX5_FLOW_CONTEXT_ACTION_FWD_DEST;
3163 }
3164
e85e02ba 3165 if (attr->split_count > 0 && !mlx5_esw_has_fwd_fdb(priv->mdev)) {
e98bedf5
EB
3166 NL_SET_ERR_MSG_MOD(extack,
3167 "current firmware doesn't support split rule for port mirroring");
592d3651
CM
3168 netdev_warn_once(priv->netdev, "current firmware doesn't support split rule for port mirroring\n");
3169 return -EOPNOTSUPP;
3170 }
3171
31c8eba5 3172 return 0;
03a9d11e
OG
3173}
3174
226f2ca3 3175static void get_flags(int flags, unsigned long *flow_flags)
60bd4af8 3176{
226f2ca3 3177 unsigned long __flow_flags = 0;
60bd4af8 3178
226f2ca3
VB
3179 if (flags & MLX5_TC_FLAG(INGRESS))
3180 __flow_flags |= BIT(MLX5E_TC_FLOW_FLAG_INGRESS);
3181 if (flags & MLX5_TC_FLAG(EGRESS))
3182 __flow_flags |= BIT(MLX5E_TC_FLOW_FLAG_EGRESS);
60bd4af8 3183
226f2ca3
VB
3184 if (flags & MLX5_TC_FLAG(ESW_OFFLOAD))
3185 __flow_flags |= BIT(MLX5E_TC_FLOW_FLAG_ESWITCH);
3186 if (flags & MLX5_TC_FLAG(NIC_OFFLOAD))
3187 __flow_flags |= BIT(MLX5E_TC_FLOW_FLAG_NIC);
d9ee0491 3188
60bd4af8
OG
3189 *flow_flags = __flow_flags;
3190}
3191
05866c82
OG
3192static const struct rhashtable_params tc_ht_params = {
3193 .head_offset = offsetof(struct mlx5e_tc_flow, node),
3194 .key_offset = offsetof(struct mlx5e_tc_flow, cookie),
3195 .key_len = sizeof(((struct mlx5e_tc_flow *)0)->cookie),
3196 .automatic_shrinking = true,
3197};
3198
226f2ca3
VB
3199static struct rhashtable *get_tc_ht(struct mlx5e_priv *priv,
3200 unsigned long flags)
05866c82 3201{
655dc3d2
OG
3202 struct mlx5_eswitch *esw = priv->mdev->priv.eswitch;
3203 struct mlx5e_rep_priv *uplink_rpriv;
3204
226f2ca3 3205 if (flags & MLX5_TC_FLAG(ESW_OFFLOAD)) {
655dc3d2 3206 uplink_rpriv = mlx5_eswitch_get_uplink_priv(esw, REP_ETH);
ec1366c2 3207 return &uplink_rpriv->uplink_priv.tc_ht;
d9ee0491 3208 } else /* NIC offload */
655dc3d2 3209 return &priv->fs.tc.ht;
05866c82
OG
3210}
3211
04de7dda
RD
3212static bool is_peer_flow_needed(struct mlx5e_tc_flow *flow)
3213{
1418ddd9 3214 struct mlx5_esw_flow_attr *attr = flow->esw_attr;
b05af6aa 3215 bool is_rep_ingress = attr->in_rep->vport != MLX5_VPORT_UPLINK &&
226f2ca3 3216 flow_flag_test(flow, INGRESS);
1418ddd9
AH
3217 bool act_is_encap = !!(attr->action &
3218 MLX5_FLOW_CONTEXT_ACTION_PACKET_REFORMAT);
3219 bool esw_paired = mlx5_devcom_is_paired(attr->in_mdev->priv.devcom,
3220 MLX5_DEVCOM_ESW_OFFLOADS);
3221
10fbb1cd
RD
3222 if (!esw_paired)
3223 return false;
3224
3225 if ((mlx5_lag_is_sriov(attr->in_mdev) ||
3226 mlx5_lag_is_multipath(attr->in_mdev)) &&
3227 (is_rep_ingress || act_is_encap))
3228 return true;
3229
3230 return false;
04de7dda
RD
3231}
3232
a88780a9
RD
3233static int
3234mlx5e_alloc_flow(struct mlx5e_priv *priv, int attr_size,
226f2ca3 3235 struct flow_cls_offload *f, unsigned long flow_flags,
a88780a9
RD
3236 struct mlx5e_tc_flow_parse_attr **__parse_attr,
3237 struct mlx5e_tc_flow **__flow)
e3a2b7ed 3238{
17091853 3239 struct mlx5e_tc_flow_parse_attr *parse_attr;
3bc4b7bf 3240 struct mlx5e_tc_flow *flow;
5a7e5bcb 3241 int out_index, err;
e3a2b7ed 3242
65ba8fb7 3243 flow = kzalloc(sizeof(*flow) + attr_size, GFP_KERNEL);
1b9a07ee 3244 parse_attr = kvzalloc(sizeof(*parse_attr), GFP_KERNEL);
17091853 3245 if (!parse_attr || !flow) {
e3a2b7ed
AV
3246 err = -ENOMEM;
3247 goto err_free;
3248 }
3249
3250 flow->cookie = f->cookie;
65ba8fb7 3251 flow->flags = flow_flags;
655dc3d2 3252 flow->priv = priv;
5a7e5bcb
VB
3253 for (out_index = 0; out_index < MLX5_MAX_FLOW_FWD_VPORTS; out_index++)
3254 INIT_LIST_HEAD(&flow->encaps[out_index].list);
3255 INIT_LIST_HEAD(&flow->mod_hdr);
3256 INIT_LIST_HEAD(&flow->hairpin);
3257 refcount_set(&flow->refcnt, 1);
e3a2b7ed 3258
a88780a9
RD
3259 *__flow = flow;
3260 *__parse_attr = parse_attr;
3261
3262 return 0;
3263
3264err_free:
3265 kfree(flow);
3266 kvfree(parse_attr);
3267 return err;
3268}
3269
988ab9c7
TZ
3270static void
3271mlx5e_flow_esw_attr_init(struct mlx5_esw_flow_attr *esw_attr,
3272 struct mlx5e_priv *priv,
3273 struct mlx5e_tc_flow_parse_attr *parse_attr,
f9e30088 3274 struct flow_cls_offload *f,
988ab9c7
TZ
3275 struct mlx5_eswitch_rep *in_rep,
3276 struct mlx5_core_dev *in_mdev)
3277{
3278 struct mlx5_eswitch *esw = priv->mdev->priv.eswitch;
3279
3280 esw_attr->parse_attr = parse_attr;
3281 esw_attr->chain = f->common.chain_index;
3282 esw_attr->prio = TC_H_MAJ(f->common.prio) >> 16;
3283
3284 esw_attr->in_rep = in_rep;
3285 esw_attr->in_mdev = in_mdev;
3286
3287 if (MLX5_CAP_ESW(esw->dev, counter_eswitch_affinity) ==
3288 MLX5_COUNTER_SOURCE_ESWITCH)
3289 esw_attr->counter_dev = in_mdev;
3290 else
3291 esw_attr->counter_dev = priv->mdev;
3292}
3293
71129676 3294static struct mlx5e_tc_flow *
04de7dda 3295__mlx5e_add_fdb_flow(struct mlx5e_priv *priv,
f9e30088 3296 struct flow_cls_offload *f,
226f2ca3 3297 unsigned long flow_flags,
04de7dda
RD
3298 struct net_device *filter_dev,
3299 struct mlx5_eswitch_rep *in_rep,
71129676 3300 struct mlx5_core_dev *in_mdev)
a88780a9 3301{
f9e30088 3302 struct flow_rule *rule = flow_cls_offload_flow_rule(f);
a88780a9
RD
3303 struct netlink_ext_ack *extack = f->common.extack;
3304 struct mlx5e_tc_flow_parse_attr *parse_attr;
3305 struct mlx5e_tc_flow *flow;
3306 int attr_size, err;
e3a2b7ed 3307
226f2ca3 3308 flow_flags |= BIT(MLX5E_TC_FLOW_FLAG_ESWITCH);
a88780a9
RD
3309 attr_size = sizeof(struct mlx5_esw_flow_attr);
3310 err = mlx5e_alloc_flow(priv, attr_size, f, flow_flags,
3311 &parse_attr, &flow);
3312 if (err)
3313 goto out;
988ab9c7 3314
d11afc26 3315 parse_attr->filter_dev = filter_dev;
988ab9c7
TZ
3316 mlx5e_flow_esw_attr_init(flow->esw_attr,
3317 priv, parse_attr,
3318 f, in_rep, in_mdev);
3319
54c177ca
OS
3320 err = parse_cls_flower(flow->priv, flow, &parse_attr->spec,
3321 f, filter_dev);
d11afc26
OS
3322 if (err)
3323 goto err_free;
a88780a9 3324
6f9af8ff 3325 err = parse_tc_fdb_actions(priv, &rule->action, flow, extack);
a88780a9
RD
3326 if (err)
3327 goto err_free;
3328
7040632d 3329 err = mlx5e_tc_add_fdb_flow(priv, flow, extack);
ef06c9ee
RD
3330 if (err) {
3331 if (!(err == -ENETUNREACH && mlx5_lag_is_multipath(in_mdev)))
3332 goto err_free;
3333
b4a23329 3334 add_unready_flow(flow);
ef06c9ee 3335 }
e3a2b7ed 3336
71129676 3337 return flow;
a88780a9
RD
3338
3339err_free:
5a7e5bcb 3340 mlx5e_flow_put(priv, flow);
a88780a9 3341out:
71129676 3342 return ERR_PTR(err);
a88780a9
RD
3343}
3344
f9e30088 3345static int mlx5e_tc_add_fdb_peer_flow(struct flow_cls_offload *f,
95dc1902 3346 struct mlx5e_tc_flow *flow,
226f2ca3 3347 unsigned long flow_flags)
04de7dda
RD
3348{
3349 struct mlx5e_priv *priv = flow->priv, *peer_priv;
3350 struct mlx5_eswitch *esw = priv->mdev->priv.eswitch, *peer_esw;
3351 struct mlx5_devcom *devcom = priv->mdev->priv.devcom;
3352 struct mlx5e_tc_flow_parse_attr *parse_attr;
3353 struct mlx5e_rep_priv *peer_urpriv;
3354 struct mlx5e_tc_flow *peer_flow;
3355 struct mlx5_core_dev *in_mdev;
3356 int err = 0;
3357
3358 peer_esw = mlx5_devcom_get_peer_data(devcom, MLX5_DEVCOM_ESW_OFFLOADS);
3359 if (!peer_esw)
3360 return -ENODEV;
3361
3362 peer_urpriv = mlx5_eswitch_get_uplink_priv(peer_esw, REP_ETH);
3363 peer_priv = netdev_priv(peer_urpriv->netdev);
3364
3365 /* in_mdev is assigned of which the packet originated from.
3366 * So packets redirected to uplink use the same mdev of the
3367 * original flow and packets redirected from uplink use the
3368 * peer mdev.
3369 */
b05af6aa 3370 if (flow->esw_attr->in_rep->vport == MLX5_VPORT_UPLINK)
04de7dda
RD
3371 in_mdev = peer_priv->mdev;
3372 else
3373 in_mdev = priv->mdev;
3374
3375 parse_attr = flow->esw_attr->parse_attr;
95dc1902 3376 peer_flow = __mlx5e_add_fdb_flow(peer_priv, f, flow_flags,
71129676
JG
3377 parse_attr->filter_dev,
3378 flow->esw_attr->in_rep, in_mdev);
3379 if (IS_ERR(peer_flow)) {
3380 err = PTR_ERR(peer_flow);
04de7dda 3381 goto out;
71129676 3382 }
04de7dda
RD
3383
3384 flow->peer_flow = peer_flow;
226f2ca3 3385 flow_flag_set(flow, DUP);
04de7dda
RD
3386 mutex_lock(&esw->offloads.peer_mutex);
3387 list_add_tail(&flow->peer, &esw->offloads.peer_flows);
3388 mutex_unlock(&esw->offloads.peer_mutex);
3389
3390out:
3391 mlx5_devcom_release_peer_data(devcom, MLX5_DEVCOM_ESW_OFFLOADS);
3392 return err;
3393}
3394
3395static int
3396mlx5e_add_fdb_flow(struct mlx5e_priv *priv,
f9e30088 3397 struct flow_cls_offload *f,
226f2ca3 3398 unsigned long flow_flags,
04de7dda
RD
3399 struct net_device *filter_dev,
3400 struct mlx5e_tc_flow **__flow)
3401{
3402 struct mlx5e_rep_priv *rpriv = priv->ppriv;
3403 struct mlx5_eswitch_rep *in_rep = rpriv->rep;
3404 struct mlx5_core_dev *in_mdev = priv->mdev;
3405 struct mlx5e_tc_flow *flow;
3406 int err;
3407
71129676
JG
3408 flow = __mlx5e_add_fdb_flow(priv, f, flow_flags, filter_dev, in_rep,
3409 in_mdev);
3410 if (IS_ERR(flow))
3411 return PTR_ERR(flow);
04de7dda
RD
3412
3413 if (is_peer_flow_needed(flow)) {
95dc1902 3414 err = mlx5e_tc_add_fdb_peer_flow(f, flow, flow_flags);
04de7dda
RD
3415 if (err) {
3416 mlx5e_tc_del_fdb_flow(priv, flow);
3417 goto out;
3418 }
3419 }
3420
3421 *__flow = flow;
3422
3423 return 0;
3424
3425out:
3426 return err;
3427}
3428
a88780a9
RD
3429static int
3430mlx5e_add_nic_flow(struct mlx5e_priv *priv,
f9e30088 3431 struct flow_cls_offload *f,
226f2ca3 3432 unsigned long flow_flags,
d11afc26 3433 struct net_device *filter_dev,
a88780a9
RD
3434 struct mlx5e_tc_flow **__flow)
3435{
f9e30088 3436 struct flow_rule *rule = flow_cls_offload_flow_rule(f);
a88780a9
RD
3437 struct netlink_ext_ack *extack = f->common.extack;
3438 struct mlx5e_tc_flow_parse_attr *parse_attr;
3439 struct mlx5e_tc_flow *flow;
3440 int attr_size, err;
3441
bf07aa73
PB
3442 /* multi-chain not supported for NIC rules */
3443 if (!tc_cls_can_offload_and_chain0(priv->netdev, &f->common))
3444 return -EOPNOTSUPP;
3445
226f2ca3 3446 flow_flags |= BIT(MLX5E_TC_FLOW_FLAG_NIC);
a88780a9
RD
3447 attr_size = sizeof(struct mlx5_nic_flow_attr);
3448 err = mlx5e_alloc_flow(priv, attr_size, f, flow_flags,
3449 &parse_attr, &flow);
3450 if (err)
3451 goto out;
3452
d11afc26 3453 parse_attr->filter_dev = filter_dev;
54c177ca
OS
3454 err = parse_cls_flower(flow->priv, flow, &parse_attr->spec,
3455 f, filter_dev);
d11afc26
OS
3456 if (err)
3457 goto err_free;
3458
73867881 3459 err = parse_tc_nic_actions(priv, &rule->action, parse_attr, flow, extack);
a88780a9
RD
3460 if (err)
3461 goto err_free;
3462
3463 err = mlx5e_tc_add_nic_flow(priv, parse_attr, flow, extack);
3464 if (err)
3465 goto err_free;
3466
226f2ca3 3467 flow_flag_set(flow, OFFLOADED);
a88780a9
RD
3468 kvfree(parse_attr);
3469 *__flow = flow;
3470
3471 return 0;
e3a2b7ed 3472
e3a2b7ed 3473err_free:
5a7e5bcb 3474 mlx5e_flow_put(priv, flow);
17091853 3475 kvfree(parse_attr);
a88780a9
RD
3476out:
3477 return err;
3478}
3479
3480static int
3481mlx5e_tc_add_flow(struct mlx5e_priv *priv,
f9e30088 3482 struct flow_cls_offload *f,
226f2ca3 3483 unsigned long flags,
d11afc26 3484 struct net_device *filter_dev,
a88780a9
RD
3485 struct mlx5e_tc_flow **flow)
3486{
3487 struct mlx5_eswitch *esw = priv->mdev->priv.eswitch;
226f2ca3 3488 unsigned long flow_flags;
a88780a9
RD
3489 int err;
3490
3491 get_flags(flags, &flow_flags);
3492
bf07aa73
PB
3493 if (!tc_can_offload_extack(priv->netdev, f->common.extack))
3494 return -EOPNOTSUPP;
3495
f6455de0 3496 if (esw && esw->mode == MLX5_ESWITCH_OFFLOADS)
d11afc26
OS
3497 err = mlx5e_add_fdb_flow(priv, f, flow_flags,
3498 filter_dev, flow);
a88780a9 3499 else
d11afc26
OS
3500 err = mlx5e_add_nic_flow(priv, f, flow_flags,
3501 filter_dev, flow);
a88780a9
RD
3502
3503 return err;
3504}
3505
71d82d2a 3506int mlx5e_configure_flower(struct net_device *dev, struct mlx5e_priv *priv,
226f2ca3 3507 struct flow_cls_offload *f, unsigned long flags)
a88780a9
RD
3508{
3509 struct netlink_ext_ack *extack = f->common.extack;
d9ee0491 3510 struct rhashtable *tc_ht = get_tc_ht(priv, flags);
a88780a9
RD
3511 struct mlx5e_tc_flow *flow;
3512 int err = 0;
3513
c5d326b2
VB
3514 rcu_read_lock();
3515 flow = rhashtable_lookup(tc_ht, &f->cookie, tc_ht_params);
3516 rcu_read_unlock();
a88780a9
RD
3517 if (flow) {
3518 NL_SET_ERR_MSG_MOD(extack,
3519 "flow cookie already exists, ignoring");
3520 netdev_warn_once(priv->netdev,
3521 "flow cookie %lx already exists, ignoring\n",
3522 f->cookie);
0e1c1a2f 3523 err = -EEXIST;
a88780a9
RD
3524 goto out;
3525 }
3526
d11afc26 3527 err = mlx5e_tc_add_flow(priv, f, flags, dev, &flow);
a88780a9
RD
3528 if (err)
3529 goto out;
3530
c5d326b2 3531 err = rhashtable_lookup_insert_fast(tc_ht, &flow->node, tc_ht_params);
a88780a9
RD
3532 if (err)
3533 goto err_free;
3534
3535 return 0;
3536
3537err_free:
5a7e5bcb 3538 mlx5e_flow_put(priv, flow);
a88780a9 3539out:
e3a2b7ed
AV
3540 return err;
3541}
3542
8f8ae895
OG
3543static bool same_flow_direction(struct mlx5e_tc_flow *flow, int flags)
3544{
226f2ca3
VB
3545 bool dir_ingress = !!(flags & MLX5_TC_FLAG(INGRESS));
3546 bool dir_egress = !!(flags & MLX5_TC_FLAG(EGRESS));
8f8ae895 3547
226f2ca3
VB
3548 return flow_flag_test(flow, INGRESS) == dir_ingress &&
3549 flow_flag_test(flow, EGRESS) == dir_egress;
8f8ae895
OG
3550}
3551
71d82d2a 3552int mlx5e_delete_flower(struct net_device *dev, struct mlx5e_priv *priv,
226f2ca3 3553 struct flow_cls_offload *f, unsigned long flags)
e3a2b7ed 3554{
d9ee0491 3555 struct rhashtable *tc_ht = get_tc_ht(priv, flags);
e3a2b7ed 3556 struct mlx5e_tc_flow *flow;
c5d326b2 3557 int err;
e3a2b7ed 3558
c5d326b2 3559 rcu_read_lock();
05866c82 3560 flow = rhashtable_lookup_fast(tc_ht, &f->cookie, tc_ht_params);
c5d326b2
VB
3561 if (!flow || !same_flow_direction(flow, flags)) {
3562 err = -EINVAL;
3563 goto errout;
3564 }
e3a2b7ed 3565
c5d326b2
VB
3566 /* Only delete the flow if it doesn't have MLX5E_TC_FLOW_DELETED flag
3567 * set.
3568 */
3569 if (flow_flag_test_and_set(flow, DELETED)) {
3570 err = -EINVAL;
3571 goto errout;
3572 }
05866c82 3573 rhashtable_remove_fast(tc_ht, &flow->node, tc_ht_params);
c5d326b2 3574 rcu_read_unlock();
e3a2b7ed 3575
5a7e5bcb 3576 mlx5e_flow_put(priv, flow);
e3a2b7ed
AV
3577
3578 return 0;
c5d326b2
VB
3579
3580errout:
3581 rcu_read_unlock();
3582 return err;
e3a2b7ed
AV
3583}
3584
71d82d2a 3585int mlx5e_stats_flower(struct net_device *dev, struct mlx5e_priv *priv,
226f2ca3 3586 struct flow_cls_offload *f, unsigned long flags)
aad7e08d 3587{
04de7dda 3588 struct mlx5_devcom *devcom = priv->mdev->priv.devcom;
d9ee0491 3589 struct rhashtable *tc_ht = get_tc_ht(priv, flags);
04de7dda 3590 struct mlx5_eswitch *peer_esw;
aad7e08d 3591 struct mlx5e_tc_flow *flow;
aad7e08d 3592 struct mlx5_fc *counter;
316d5f72
RD
3593 u64 lastuse = 0;
3594 u64 packets = 0;
3595 u64 bytes = 0;
5a7e5bcb 3596 int err = 0;
aad7e08d 3597
c5d326b2
VB
3598 rcu_read_lock();
3599 flow = mlx5e_flow_get(rhashtable_lookup(tc_ht, &f->cookie,
3600 tc_ht_params));
3601 rcu_read_unlock();
5a7e5bcb
VB
3602 if (IS_ERR(flow))
3603 return PTR_ERR(flow);
3604
3605 if (!same_flow_direction(flow, flags)) {
3606 err = -EINVAL;
3607 goto errout;
3608 }
aad7e08d 3609
226f2ca3 3610 if (mlx5e_is_offloaded_flow(flow)) {
316d5f72
RD
3611 counter = mlx5e_tc_get_counter(flow);
3612 if (!counter)
5a7e5bcb 3613 goto errout;
aad7e08d 3614
316d5f72
RD
3615 mlx5_fc_query_cached(counter, &bytes, &packets, &lastuse);
3616 }
aad7e08d 3617
316d5f72
RD
3618 /* Under multipath it's possible for one rule to be currently
3619 * un-offloaded while the other rule is offloaded.
3620 */
04de7dda
RD
3621 peer_esw = mlx5_devcom_get_peer_data(devcom, MLX5_DEVCOM_ESW_OFFLOADS);
3622 if (!peer_esw)
3623 goto out;
3624
226f2ca3
VB
3625 if (flow_flag_test(flow, DUP) &&
3626 flow_flag_test(flow->peer_flow, OFFLOADED)) {
04de7dda
RD
3627 u64 bytes2;
3628 u64 packets2;
3629 u64 lastuse2;
3630
3631 counter = mlx5e_tc_get_counter(flow->peer_flow);
316d5f72
RD
3632 if (!counter)
3633 goto no_peer_counter;
04de7dda
RD
3634 mlx5_fc_query_cached(counter, &bytes2, &packets2, &lastuse2);
3635
3636 bytes += bytes2;
3637 packets += packets2;
3638 lastuse = max_t(u64, lastuse, lastuse2);
3639 }
3640
316d5f72 3641no_peer_counter:
04de7dda 3642 mlx5_devcom_release_peer_data(devcom, MLX5_DEVCOM_ESW_OFFLOADS);
04de7dda 3643out:
3b1903ef 3644 flow_stats_update(&f->stats, bytes, packets, lastuse);
5a7e5bcb
VB
3645errout:
3646 mlx5e_flow_put(priv, flow);
3647 return err;
aad7e08d
AV
3648}
3649
fcb64c0f
EC
3650static int apply_police_params(struct mlx5e_priv *priv, u32 rate,
3651 struct netlink_ext_ack *extack)
3652{
3653 struct mlx5e_rep_priv *rpriv = priv->ppriv;
3654 struct mlx5_eswitch *esw;
3655 u16 vport_num;
3656 u32 rate_mbps;
3657 int err;
3658
3659 esw = priv->mdev->priv.eswitch;
3660 /* rate is given in bytes/sec.
3661 * First convert to bits/sec and then round to the nearest mbit/secs.
3662 * mbit means million bits.
3663 * Moreover, if rate is non zero we choose to configure to a minimum of
3664 * 1 mbit/sec.
3665 */
3666 rate_mbps = rate ? max_t(u32, (rate * 8 + 500000) / 1000000, 1) : 0;
3667 vport_num = rpriv->rep->vport;
3668
3669 err = mlx5_esw_modify_vport_rate(esw, vport_num, rate_mbps);
3670 if (err)
3671 NL_SET_ERR_MSG_MOD(extack, "failed applying action to hardware");
3672
3673 return err;
3674}
3675
3676static int scan_tc_matchall_fdb_actions(struct mlx5e_priv *priv,
3677 struct flow_action *flow_action,
3678 struct netlink_ext_ack *extack)
3679{
3680 struct mlx5e_rep_priv *rpriv = priv->ppriv;
3681 const struct flow_action_entry *act;
3682 int err;
3683 int i;
3684
3685 if (!flow_action_has_entries(flow_action)) {
3686 NL_SET_ERR_MSG_MOD(extack, "matchall called with no action");
3687 return -EINVAL;
3688 }
3689
3690 if (!flow_offload_has_one_action(flow_action)) {
3691 NL_SET_ERR_MSG_MOD(extack, "matchall policing support only a single action");
3692 return -EOPNOTSUPP;
3693 }
3694
3695 flow_action_for_each(i, act, flow_action) {
3696 switch (act->id) {
3697 case FLOW_ACTION_POLICE:
3698 err = apply_police_params(priv, act->police.rate_bytes_ps, extack);
3699 if (err)
3700 return err;
3701
3702 rpriv->prev_vf_vport_stats = priv->stats.vf_vport;
3703 break;
3704 default:
3705 NL_SET_ERR_MSG_MOD(extack, "mlx5 supports only police action for matchall");
3706 return -EOPNOTSUPP;
3707 }
3708 }
3709
3710 return 0;
3711}
3712
3713int mlx5e_tc_configure_matchall(struct mlx5e_priv *priv,
3714 struct tc_cls_matchall_offload *ma)
3715{
3716 struct netlink_ext_ack *extack = ma->common.extack;
3717 int prio = TC_H_MAJ(ma->common.prio) >> 16;
3718
3719 if (prio != 1) {
3720 NL_SET_ERR_MSG_MOD(extack, "only priority 1 is supported");
3721 return -EINVAL;
3722 }
3723
3724 return scan_tc_matchall_fdb_actions(priv, &ma->rule->action, extack);
3725}
3726
3727int mlx5e_tc_delete_matchall(struct mlx5e_priv *priv,
3728 struct tc_cls_matchall_offload *ma)
3729{
3730 struct netlink_ext_ack *extack = ma->common.extack;
3731
3732 return apply_police_params(priv, 0, extack);
3733}
3734
3735void mlx5e_tc_stats_matchall(struct mlx5e_priv *priv,
3736 struct tc_cls_matchall_offload *ma)
3737{
3738 struct mlx5e_rep_priv *rpriv = priv->ppriv;
3739 struct rtnl_link_stats64 cur_stats;
3740 u64 dbytes;
3741 u64 dpkts;
3742
3743 cur_stats = priv->stats.vf_vport;
3744 dpkts = cur_stats.rx_packets - rpriv->prev_vf_vport_stats.rx_packets;
3745 dbytes = cur_stats.rx_bytes - rpriv->prev_vf_vport_stats.rx_bytes;
3746 rpriv->prev_vf_vport_stats = cur_stats;
3747 flow_stats_update(&ma->stats, dpkts, dbytes, jiffies);
3748}
3749
4d8fcf21
AH
3750static void mlx5e_tc_hairpin_update_dead_peer(struct mlx5e_priv *priv,
3751 struct mlx5e_priv *peer_priv)
3752{
3753 struct mlx5_core_dev *peer_mdev = peer_priv->mdev;
3754 struct mlx5e_hairpin_entry *hpe;
3755 u16 peer_vhca_id;
3756 int bkt;
3757
3758 if (!same_hw_devs(priv, peer_priv))
3759 return;
3760
3761 peer_vhca_id = MLX5_CAP_GEN(peer_mdev, vhca_id);
3762
3763 hash_for_each(priv->fs.tc.hairpin_tbl, bkt, hpe, hairpin_hlist) {
3764 if (hpe->peer_vhca_id == peer_vhca_id)
3765 hpe->hp->pair->peer_gone = true;
3766 }
3767}
3768
3769static int mlx5e_tc_netdev_event(struct notifier_block *this,
3770 unsigned long event, void *ptr)
3771{
3772 struct net_device *ndev = netdev_notifier_info_to_dev(ptr);
3773 struct mlx5e_flow_steering *fs;
3774 struct mlx5e_priv *peer_priv;
3775 struct mlx5e_tc_table *tc;
3776 struct mlx5e_priv *priv;
3777
3778 if (ndev->netdev_ops != &mlx5e_netdev_ops ||
3779 event != NETDEV_UNREGISTER ||
3780 ndev->reg_state == NETREG_REGISTERED)
3781 return NOTIFY_DONE;
3782
3783 tc = container_of(this, struct mlx5e_tc_table, netdevice_nb);
3784 fs = container_of(tc, struct mlx5e_flow_steering, tc);
3785 priv = container_of(fs, struct mlx5e_priv, fs);
3786 peer_priv = netdev_priv(ndev);
3787 if (priv == peer_priv ||
3788 !(priv->netdev->features & NETIF_F_HW_TC))
3789 return NOTIFY_DONE;
3790
3791 mlx5e_tc_hairpin_update_dead_peer(priv, peer_priv);
3792
3793 return NOTIFY_DONE;
3794}
3795
655dc3d2 3796int mlx5e_tc_nic_init(struct mlx5e_priv *priv)
e8f887ac 3797{
acff797c 3798 struct mlx5e_tc_table *tc = &priv->fs.tc;
4d8fcf21 3799 int err;
e8f887ac 3800
b6fac0b4 3801 mutex_init(&tc->t_lock);
11c9c548 3802 hash_init(tc->mod_hdr_tbl);
5c65c564 3803 hash_init(tc->hairpin_tbl);
11c9c548 3804
4d8fcf21
AH
3805 err = rhashtable_init(&tc->ht, &tc_ht_params);
3806 if (err)
3807 return err;
3808
3809 tc->netdevice_nb.notifier_call = mlx5e_tc_netdev_event;
3810 if (register_netdevice_notifier(&tc->netdevice_nb)) {
3811 tc->netdevice_nb.notifier_call = NULL;
3812 mlx5_core_warn(priv->mdev, "Failed to register netdev notifier\n");
3813 }
3814
3815 return err;
e8f887ac
AV
3816}
3817
3818static void _mlx5e_tc_del_flow(void *ptr, void *arg)
3819{
3820 struct mlx5e_tc_flow *flow = ptr;
655dc3d2 3821 struct mlx5e_priv *priv = flow->priv;
e8f887ac 3822
961e8979 3823 mlx5e_tc_del_flow(priv, flow);
e8f887ac
AV
3824 kfree(flow);
3825}
3826
655dc3d2 3827void mlx5e_tc_nic_cleanup(struct mlx5e_priv *priv)
e8f887ac 3828{
acff797c 3829 struct mlx5e_tc_table *tc = &priv->fs.tc;
e8f887ac 3830
4d8fcf21
AH
3831 if (tc->netdevice_nb.notifier_call)
3832 unregister_netdevice_notifier(&tc->netdevice_nb);
3833
d9ee0491 3834 rhashtable_destroy(&tc->ht);
e8f887ac 3835
acff797c
MG
3836 if (!IS_ERR_OR_NULL(tc->t)) {
3837 mlx5_destroy_flow_table(tc->t);
3838 tc->t = NULL;
e8f887ac 3839 }
b6fac0b4 3840 mutex_destroy(&tc->t_lock);
e8f887ac 3841}
655dc3d2
OG
3842
3843int mlx5e_tc_esw_init(struct rhashtable *tc_ht)
3844{
3845 return rhashtable_init(tc_ht, &tc_ht_params);
3846}
3847
3848void mlx5e_tc_esw_cleanup(struct rhashtable *tc_ht)
3849{
3850 rhashtable_free_and_destroy(tc_ht, _mlx5e_tc_del_flow, NULL);
3851}
01252a27 3852
226f2ca3 3853int mlx5e_tc_num_filters(struct mlx5e_priv *priv, unsigned long flags)
01252a27 3854{
d9ee0491 3855 struct rhashtable *tc_ht = get_tc_ht(priv, flags);
01252a27
OG
3856
3857 return atomic_read(&tc_ht->nelems);
3858}
04de7dda
RD
3859
3860void mlx5e_tc_clean_fdb_peer_flows(struct mlx5_eswitch *esw)
3861{
3862 struct mlx5e_tc_flow *flow, *tmp;
3863
3864 list_for_each_entry_safe(flow, tmp, &esw->offloads.peer_flows, peer)
3865 __mlx5e_tc_del_fdb_peer_flow(flow);
3866}
b4a23329
RD
3867
3868void mlx5e_tc_reoffload_flows_work(struct work_struct *work)
3869{
3870 struct mlx5_rep_uplink_priv *rpriv =
3871 container_of(work, struct mlx5_rep_uplink_priv,
3872 reoffload_flows_work);
3873 struct mlx5e_tc_flow *flow, *tmp;
3874
ad86755b 3875 mutex_lock(&rpriv->unready_flows_lock);
b4a23329
RD
3876 list_for_each_entry_safe(flow, tmp, &rpriv->unready_flows, unready) {
3877 if (!mlx5e_tc_add_fdb_flow(flow->priv, flow, NULL))
ad86755b 3878 unready_flow_del(flow);
b4a23329 3879 }
ad86755b 3880 mutex_unlock(&rpriv->unready_flows_lock);
b4a23329 3881}