]> git.proxmox.com Git - mirror_ubuntu-focal-kernel.git/blame - drivers/net/ethernet/mellanox/mlx5/core/en_tc.c
Merge remote-tracking branches 'asoc/topic/ac97', 'asoc/topic/ac97-mfd', 'asoc/topic...
[mirror_ubuntu-focal-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>
03a9d11e
OG
41#include <net/switchdev.h>
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>
a54e20b4 47#include <net/vxlan.h>
f6dfb4c3 48#include <net/arp.h>
e8f887ac 49#include "en.h"
1d447a39 50#include "en_rep.h"
232c0013 51#include "en_tc.h"
03a9d11e 52#include "eswitch.h"
bbd00f7e 53#include "vxlan.h"
e8f887ac 54
3bc4b7bf
OG
55struct mlx5_nic_flow_attr {
56 u32 action;
57 u32 flow_tag;
2f4fe4ca 58 u32 mod_hdr_id;
3bc4b7bf
OG
59};
60
65ba8fb7
OG
61enum {
62 MLX5E_TC_FLOW_ESWITCH = BIT(0),
3bc4b7bf 63 MLX5E_TC_FLOW_NIC = BIT(1),
0b67a38f 64 MLX5E_TC_FLOW_OFFLOADED = BIT(2),
65ba8fb7
OG
65};
66
e8f887ac
AV
67struct mlx5e_tc_flow {
68 struct rhash_head node;
69 u64 cookie;
65ba8fb7 70 u8 flags;
74491de9 71 struct mlx5_flow_handle *rule;
11c9c548
OG
72 struct list_head encap; /* flows sharing the same encap ID */
73 struct list_head mod_hdr; /* flows sharing the same mod hdr ID */
3bc4b7bf
OG
74 union {
75 struct mlx5_esw_flow_attr esw_attr[0];
76 struct mlx5_nic_flow_attr nic_attr[0];
77 };
e8f887ac
AV
78};
79
17091853 80struct mlx5e_tc_flow_parse_attr {
3c37745e 81 struct ip_tunnel_info tun_info;
17091853 82 struct mlx5_flow_spec spec;
d79b6df6
OG
83 int num_mod_hdr_actions;
84 void *mod_hdr_actions;
3c37745e 85 int mirred_ifindex;
17091853
OG
86};
87
a54e20b4
HHZ
88enum {
89 MLX5_HEADER_TYPE_VXLAN = 0x0,
90 MLX5_HEADER_TYPE_NVGRE = 0x1,
91};
92
acff797c
MG
93#define MLX5E_TC_TABLE_NUM_ENTRIES 1024
94#define MLX5E_TC_TABLE_NUM_GROUPS 4
e8f887ac 95
11c9c548
OG
96struct mod_hdr_key {
97 int num_actions;
98 void *actions;
99};
100
101struct mlx5e_mod_hdr_entry {
102 /* a node of a hash table which keeps all the mod_hdr entries */
103 struct hlist_node mod_hdr_hlist;
104
105 /* flows sharing the same mod_hdr entry */
106 struct list_head flows;
107
108 struct mod_hdr_key key;
109
110 u32 mod_hdr_id;
111};
112
113#define MLX5_MH_ACT_SZ MLX5_UN_SZ_BYTES(set_action_in_add_action_in_auto)
114
115static inline u32 hash_mod_hdr_info(struct mod_hdr_key *key)
116{
117 return jhash(key->actions,
118 key->num_actions * MLX5_MH_ACT_SZ, 0);
119}
120
121static inline int cmp_mod_hdr_info(struct mod_hdr_key *a,
122 struct mod_hdr_key *b)
123{
124 if (a->num_actions != b->num_actions)
125 return 1;
126
127 return memcmp(a->actions, b->actions, a->num_actions * MLX5_MH_ACT_SZ);
128}
129
130static int mlx5e_attach_mod_hdr(struct mlx5e_priv *priv,
131 struct mlx5e_tc_flow *flow,
132 struct mlx5e_tc_flow_parse_attr *parse_attr)
133{
134 struct mlx5_eswitch *esw = priv->mdev->priv.eswitch;
135 int num_actions, actions_size, namespace, err;
136 struct mlx5e_mod_hdr_entry *mh;
137 struct mod_hdr_key key;
138 bool found = false;
139 u32 hash_key;
140
141 num_actions = parse_attr->num_mod_hdr_actions;
142 actions_size = MLX5_MH_ACT_SZ * num_actions;
143
144 key.actions = parse_attr->mod_hdr_actions;
145 key.num_actions = num_actions;
146
147 hash_key = hash_mod_hdr_info(&key);
148
149 if (flow->flags & MLX5E_TC_FLOW_ESWITCH) {
150 namespace = MLX5_FLOW_NAMESPACE_FDB;
151 hash_for_each_possible(esw->offloads.mod_hdr_tbl, mh,
152 mod_hdr_hlist, hash_key) {
153 if (!cmp_mod_hdr_info(&mh->key, &key)) {
154 found = true;
155 break;
156 }
157 }
158 } else {
159 namespace = MLX5_FLOW_NAMESPACE_KERNEL;
160 hash_for_each_possible(priv->fs.tc.mod_hdr_tbl, mh,
161 mod_hdr_hlist, hash_key) {
162 if (!cmp_mod_hdr_info(&mh->key, &key)) {
163 found = true;
164 break;
165 }
166 }
167 }
168
169 if (found)
170 goto attach_flow;
171
172 mh = kzalloc(sizeof(*mh) + actions_size, GFP_KERNEL);
173 if (!mh)
174 return -ENOMEM;
175
176 mh->key.actions = (void *)mh + sizeof(*mh);
177 memcpy(mh->key.actions, key.actions, actions_size);
178 mh->key.num_actions = num_actions;
179 INIT_LIST_HEAD(&mh->flows);
180
181 err = mlx5_modify_header_alloc(priv->mdev, namespace,
182 mh->key.num_actions,
183 mh->key.actions,
184 &mh->mod_hdr_id);
185 if (err)
186 goto out_err;
187
188 if (flow->flags & MLX5E_TC_FLOW_ESWITCH)
189 hash_add(esw->offloads.mod_hdr_tbl, &mh->mod_hdr_hlist, hash_key);
190 else
191 hash_add(priv->fs.tc.mod_hdr_tbl, &mh->mod_hdr_hlist, hash_key);
192
193attach_flow:
194 list_add(&flow->mod_hdr, &mh->flows);
195 if (flow->flags & MLX5E_TC_FLOW_ESWITCH)
196 flow->esw_attr->mod_hdr_id = mh->mod_hdr_id;
197 else
198 flow->nic_attr->mod_hdr_id = mh->mod_hdr_id;
199
200 return 0;
201
202out_err:
203 kfree(mh);
204 return err;
205}
206
207static void mlx5e_detach_mod_hdr(struct mlx5e_priv *priv,
208 struct mlx5e_tc_flow *flow)
209{
210 struct list_head *next = flow->mod_hdr.next;
211
212 list_del(&flow->mod_hdr);
213
214 if (list_empty(next)) {
215 struct mlx5e_mod_hdr_entry *mh;
216
217 mh = list_entry(next, struct mlx5e_mod_hdr_entry, flows);
218
219 mlx5_modify_header_dealloc(priv->mdev, mh->mod_hdr_id);
220 hash_del(&mh->mod_hdr_hlist);
221 kfree(mh);
222 }
223}
224
74491de9
MB
225static struct mlx5_flow_handle *
226mlx5e_tc_add_nic_flow(struct mlx5e_priv *priv,
17091853 227 struct mlx5e_tc_flow_parse_attr *parse_attr,
aa0cbbae 228 struct mlx5e_tc_flow *flow)
e8f887ac 229{
aa0cbbae 230 struct mlx5_nic_flow_attr *attr = flow->nic_attr;
aad7e08d 231 struct mlx5_core_dev *dev = priv->mdev;
aa0cbbae 232 struct mlx5_flow_destination dest = {};
66958ed9 233 struct mlx5_flow_act flow_act = {
3bc4b7bf
OG
234 .action = attr->action,
235 .flow_tag = attr->flow_tag,
66958ed9
HHZ
236 .encap_id = 0,
237 };
aad7e08d 238 struct mlx5_fc *counter = NULL;
74491de9 239 struct mlx5_flow_handle *rule;
e8f887ac 240 bool table_created = false;
2f4fe4ca 241 int err;
e8f887ac 242
3bc4b7bf 243 if (attr->action & MLX5_FLOW_CONTEXT_ACTION_FWD_DEST) {
aad7e08d
AV
244 dest.type = MLX5_FLOW_DESTINATION_TYPE_FLOW_TABLE;
245 dest.ft = priv->fs.vlan.ft.t;
3bc4b7bf 246 } else if (attr->action & MLX5_FLOW_CONTEXT_ACTION_COUNT) {
aad7e08d
AV
247 counter = mlx5_fc_create(dev, true);
248 if (IS_ERR(counter))
249 return ERR_CAST(counter);
250
251 dest.type = MLX5_FLOW_DESTINATION_TYPE_COUNTER;
252 dest.counter = counter;
253 }
254
2f4fe4ca 255 if (attr->action & MLX5_FLOW_CONTEXT_ACTION_MOD_HDR) {
3099eb5a 256 err = mlx5e_attach_mod_hdr(priv, flow, parse_attr);
d7e75a32 257 flow_act.modify_id = attr->mod_hdr_id;
2f4fe4ca
OG
258 kfree(parse_attr->mod_hdr_actions);
259 if (err) {
260 rule = ERR_PTR(err);
261 goto err_create_mod_hdr_id;
262 }
263 }
264
acff797c
MG
265 if (IS_ERR_OR_NULL(priv->fs.tc.t)) {
266 priv->fs.tc.t =
267 mlx5_create_auto_grouped_flow_table(priv->fs.ns,
268 MLX5E_TC_PRIO,
269 MLX5E_TC_TABLE_NUM_ENTRIES,
270 MLX5E_TC_TABLE_NUM_GROUPS,
c9f1b073 271 0, 0);
acff797c 272 if (IS_ERR(priv->fs.tc.t)) {
e8f887ac
AV
273 netdev_err(priv->netdev,
274 "Failed to create tc offload table\n");
aad7e08d
AV
275 rule = ERR_CAST(priv->fs.tc.t);
276 goto err_create_ft;
e8f887ac
AV
277 }
278
279 table_created = true;
280 }
281
17091853
OG
282 parse_attr->spec.match_criteria_enable = MLX5_MATCH_OUTER_HEADERS;
283 rule = mlx5_add_flow_rules(priv->fs.tc.t, &parse_attr->spec,
284 &flow_act, &dest, 1);
aad7e08d
AV
285
286 if (IS_ERR(rule))
287 goto err_add_rule;
288
289 return rule;
e8f887ac 290
aad7e08d
AV
291err_add_rule:
292 if (table_created) {
acff797c
MG
293 mlx5_destroy_flow_table(priv->fs.tc.t);
294 priv->fs.tc.t = NULL;
e8f887ac 295 }
aad7e08d 296err_create_ft:
2f4fe4ca 297 if (attr->action & MLX5_FLOW_CONTEXT_ACTION_MOD_HDR)
3099eb5a 298 mlx5e_detach_mod_hdr(priv, flow);
2f4fe4ca 299err_create_mod_hdr_id:
aad7e08d 300 mlx5_fc_destroy(dev, counter);
e8f887ac
AV
301
302 return rule;
303}
304
d85cdccb
OG
305static void mlx5e_tc_del_nic_flow(struct mlx5e_priv *priv,
306 struct mlx5e_tc_flow *flow)
307{
513f8f7f 308 struct mlx5_nic_flow_attr *attr = flow->nic_attr;
d85cdccb
OG
309 struct mlx5_fc *counter = NULL;
310
aa0cbbae
OG
311 counter = mlx5_flow_rule_counter(flow->rule);
312 mlx5_del_flow_rules(flow->rule);
313 mlx5_fc_destroy(priv->mdev, counter);
d85cdccb
OG
314
315 if (!mlx5e_tc_num_filters(priv) && (priv->fs.tc.t)) {
316 mlx5_destroy_flow_table(priv->fs.tc.t);
317 priv->fs.tc.t = NULL;
318 }
2f4fe4ca 319
513f8f7f 320 if (attr->action & MLX5_FLOW_CONTEXT_ACTION_MOD_HDR)
3099eb5a 321 mlx5e_detach_mod_hdr(priv, flow);
d85cdccb
OG
322}
323
aa0cbbae
OG
324static void mlx5e_detach_encap(struct mlx5e_priv *priv,
325 struct mlx5e_tc_flow *flow);
326
3c37745e
OG
327static int mlx5e_attach_encap(struct mlx5e_priv *priv,
328 struct ip_tunnel_info *tun_info,
329 struct net_device *mirred_dev,
330 struct net_device **encap_dev,
331 struct mlx5e_tc_flow *flow);
332
74491de9
MB
333static struct mlx5_flow_handle *
334mlx5e_tc_add_fdb_flow(struct mlx5e_priv *priv,
17091853 335 struct mlx5e_tc_flow_parse_attr *parse_attr,
aa0cbbae 336 struct mlx5e_tc_flow *flow)
adb4c123
OG
337{
338 struct mlx5_eswitch *esw = priv->mdev->priv.eswitch;
aa0cbbae 339 struct mlx5_esw_flow_attr *attr = flow->esw_attr;
3c37745e
OG
340 struct net_device *out_dev, *encap_dev = NULL;
341 struct mlx5_flow_handle *rule = NULL;
342 struct mlx5e_rep_priv *rpriv;
343 struct mlx5e_priv *out_priv;
8b32580d
OG
344 int err;
345
3c37745e
OG
346 if (attr->action & MLX5_FLOW_CONTEXT_ACTION_ENCAP) {
347 out_dev = __dev_get_by_index(dev_net(priv->netdev),
348 attr->parse_attr->mirred_ifindex);
349 err = mlx5e_attach_encap(priv, &parse_attr->tun_info,
350 out_dev, &encap_dev, flow);
351 if (err) {
352 rule = ERR_PTR(err);
353 if (err != -EAGAIN)
354 goto err_attach_encap;
355 }
356 out_priv = netdev_priv(encap_dev);
357 rpriv = out_priv->ppriv;
358 attr->out_rep = rpriv->rep;
359 }
360
8b32580d 361 err = mlx5_eswitch_add_vlan_action(esw, attr);
aa0cbbae
OG
362 if (err) {
363 rule = ERR_PTR(err);
364 goto err_add_vlan;
365 }
adb4c123 366
d7e75a32 367 if (attr->action & MLX5_FLOW_CONTEXT_ACTION_MOD_HDR) {
1a9527bb 368 err = mlx5e_attach_mod_hdr(priv, flow, parse_attr);
d7e75a32
OG
369 kfree(parse_attr->mod_hdr_actions);
370 if (err) {
371 rule = ERR_PTR(err);
372 goto err_mod_hdr;
373 }
374 }
375
3c37745e
OG
376 /* we get here if (1) there's no error (rule being null) or when
377 * (2) there's an encap action and we're on -EAGAIN (no valid neigh)
378 */
379 if (rule != ERR_PTR(-EAGAIN)) {
380 rule = mlx5_eswitch_add_offloaded_rule(esw, &parse_attr->spec, attr);
381 if (IS_ERR(rule))
382 goto err_add_rule;
383 }
aa0cbbae
OG
384 return rule;
385
386err_add_rule:
513f8f7f 387 if (attr->action & MLX5_FLOW_CONTEXT_ACTION_MOD_HDR)
1a9527bb 388 mlx5e_detach_mod_hdr(priv, flow);
d7e75a32 389err_mod_hdr:
aa0cbbae
OG
390 mlx5_eswitch_del_vlan_action(esw, attr);
391err_add_vlan:
392 if (attr->action & MLX5_FLOW_CONTEXT_ACTION_ENCAP)
393 mlx5e_detach_encap(priv, flow);
3c37745e 394err_attach_encap:
aa0cbbae
OG
395 return rule;
396}
d85cdccb
OG
397
398static void mlx5e_tc_del_fdb_flow(struct mlx5e_priv *priv,
399 struct mlx5e_tc_flow *flow)
400{
401 struct mlx5_eswitch *esw = priv->mdev->priv.eswitch;
d7e75a32 402 struct mlx5_esw_flow_attr *attr = flow->esw_attr;
d85cdccb 403
232c0013
HHZ
404 if (flow->flags & MLX5E_TC_FLOW_OFFLOADED) {
405 flow->flags &= ~MLX5E_TC_FLOW_OFFLOADED;
513f8f7f 406 mlx5_eswitch_del_offloaded_rule(esw, flow->rule, attr);
232c0013 407 }
d85cdccb 408
513f8f7f 409 mlx5_eswitch_del_vlan_action(esw, attr);
d85cdccb 410
513f8f7f 411 if (attr->action & MLX5_FLOW_CONTEXT_ACTION_ENCAP) {
d85cdccb 412 mlx5e_detach_encap(priv, flow);
513f8f7f 413 kvfree(attr->parse_attr);
232c0013 414 }
d7e75a32 415
513f8f7f 416 if (attr->action & MLX5_FLOW_CONTEXT_ACTION_MOD_HDR)
1a9527bb 417 mlx5e_detach_mod_hdr(priv, flow);
d85cdccb
OG
418}
419
232c0013
HHZ
420void mlx5e_tc_encap_flows_add(struct mlx5e_priv *priv,
421 struct mlx5e_encap_entry *e)
422{
3c37745e
OG
423 struct mlx5_eswitch *esw = priv->mdev->priv.eswitch;
424 struct mlx5_esw_flow_attr *esw_attr;
232c0013
HHZ
425 struct mlx5e_tc_flow *flow;
426 int err;
427
428 err = mlx5_encap_alloc(priv->mdev, e->tunnel_type,
429 e->encap_size, e->encap_header,
430 &e->encap_id);
431 if (err) {
432 mlx5_core_warn(priv->mdev, "Failed to offload cached encapsulation header, %d\n",
433 err);
434 return;
435 }
436 e->flags |= MLX5_ENCAP_ENTRY_VALID;
f6dfb4c3 437 mlx5e_rep_queue_neigh_stats_work(priv);
232c0013
HHZ
438
439 list_for_each_entry(flow, &e->flows, encap) {
3c37745e
OG
440 esw_attr = flow->esw_attr;
441 esw_attr->encap_id = e->encap_id;
442 flow->rule = mlx5_eswitch_add_offloaded_rule(esw, &esw_attr->parse_attr->spec, esw_attr);
232c0013
HHZ
443 if (IS_ERR(flow->rule)) {
444 err = PTR_ERR(flow->rule);
445 mlx5_core_warn(priv->mdev, "Failed to update cached encapsulation flow, %d\n",
446 err);
447 continue;
448 }
449 flow->flags |= MLX5E_TC_FLOW_OFFLOADED;
450 }
451}
452
453void mlx5e_tc_encap_flows_del(struct mlx5e_priv *priv,
454 struct mlx5e_encap_entry *e)
455{
3c37745e 456 struct mlx5_eswitch *esw = priv->mdev->priv.eswitch;
232c0013 457 struct mlx5e_tc_flow *flow;
232c0013
HHZ
458
459 list_for_each_entry(flow, &e->flows, encap) {
460 if (flow->flags & MLX5E_TC_FLOW_OFFLOADED) {
461 flow->flags &= ~MLX5E_TC_FLOW_OFFLOADED;
3c37745e 462 mlx5_eswitch_del_offloaded_rule(esw, flow->rule, flow->esw_attr);
232c0013
HHZ
463 }
464 }
465
466 if (e->flags & MLX5_ENCAP_ENTRY_VALID) {
467 e->flags &= ~MLX5_ENCAP_ENTRY_VALID;
468 mlx5_encap_dealloc(priv->mdev, e->encap_id);
469 }
470}
471
f6dfb4c3
HHZ
472void mlx5e_tc_update_neigh_used_value(struct mlx5e_neigh_hash_entry *nhe)
473{
474 struct mlx5e_neigh *m_neigh = &nhe->m_neigh;
475 u64 bytes, packets, lastuse = 0;
476 struct mlx5e_tc_flow *flow;
477 struct mlx5e_encap_entry *e;
478 struct mlx5_fc *counter;
479 struct neigh_table *tbl;
480 bool neigh_used = false;
481 struct neighbour *n;
482
483 if (m_neigh->family == AF_INET)
484 tbl = &arp_tbl;
485#if IS_ENABLED(CONFIG_IPV6)
486 else if (m_neigh->family == AF_INET6)
487 tbl = ipv6_stub->nd_tbl;
488#endif
489 else
490 return;
491
492 list_for_each_entry(e, &nhe->encap_list, encap_list) {
493 if (!(e->flags & MLX5_ENCAP_ENTRY_VALID))
494 continue;
495 list_for_each_entry(flow, &e->flows, encap) {
496 if (flow->flags & MLX5E_TC_FLOW_OFFLOADED) {
497 counter = mlx5_flow_rule_counter(flow->rule);
498 mlx5_fc_query_cached(counter, &bytes, &packets, &lastuse);
499 if (time_after((unsigned long)lastuse, nhe->reported_lastuse)) {
500 neigh_used = true;
501 break;
502 }
503 }
504 }
505 }
506
507 if (neigh_used) {
508 nhe->reported_lastuse = jiffies;
509
510 /* find the relevant neigh according to the cached device and
511 * dst ip pair
512 */
513 n = neigh_lookup(tbl, &m_neigh->dst_ip, m_neigh->dev);
514 if (!n) {
515 WARN(1, "The neighbour already freed\n");
516 return;
517 }
518
519 neigh_event_send(n, NULL);
520 neigh_release(n);
521 }
522}
523
d85cdccb
OG
524static void mlx5e_detach_encap(struct mlx5e_priv *priv,
525 struct mlx5e_tc_flow *flow)
526{
5067b602
RD
527 struct list_head *next = flow->encap.next;
528
529 list_del(&flow->encap);
530 if (list_empty(next)) {
c1ae1152 531 struct mlx5e_encap_entry *e;
5067b602 532
c1ae1152 533 e = list_entry(next, struct mlx5e_encap_entry, flows);
232c0013
HHZ
534 mlx5e_rep_encap_entry_detach(netdev_priv(e->out_dev), e);
535
536 if (e->flags & MLX5_ENCAP_ENTRY_VALID)
5067b602 537 mlx5_encap_dealloc(priv->mdev, e->encap_id);
232c0013 538
cdc5a7f3 539 hash_del_rcu(&e->encap_hlist);
232c0013 540 kfree(e->encap_header);
5067b602
RD
541 kfree(e);
542 }
543}
544
e8f887ac 545static void mlx5e_tc_del_flow(struct mlx5e_priv *priv,
961e8979 546 struct mlx5e_tc_flow *flow)
e8f887ac 547{
d85cdccb
OG
548 if (flow->flags & MLX5E_TC_FLOW_ESWITCH)
549 mlx5e_tc_del_fdb_flow(priv, flow);
550 else
551 mlx5e_tc_del_nic_flow(priv, flow);
e8f887ac
AV
552}
553
bbd00f7e
HHZ
554static void parse_vxlan_attr(struct mlx5_flow_spec *spec,
555 struct tc_cls_flower_offload *f)
556{
557 void *headers_c = MLX5_ADDR_OF(fte_match_param, spec->match_criteria,
558 outer_headers);
559 void *headers_v = MLX5_ADDR_OF(fte_match_param, spec->match_value,
560 outer_headers);
561 void *misc_c = MLX5_ADDR_OF(fte_match_param, spec->match_criteria,
562 misc_parameters);
563 void *misc_v = MLX5_ADDR_OF(fte_match_param, spec->match_value,
564 misc_parameters);
565
566 MLX5_SET_TO_ONES(fte_match_set_lyr_2_4, headers_c, ip_protocol);
567 MLX5_SET(fte_match_set_lyr_2_4, headers_v, ip_protocol, IPPROTO_UDP);
568
569 if (dissector_uses_key(f->dissector, FLOW_DISSECTOR_KEY_ENC_KEYID)) {
570 struct flow_dissector_key_keyid *key =
571 skb_flow_dissector_target(f->dissector,
572 FLOW_DISSECTOR_KEY_ENC_KEYID,
573 f->key);
574 struct flow_dissector_key_keyid *mask =
575 skb_flow_dissector_target(f->dissector,
576 FLOW_DISSECTOR_KEY_ENC_KEYID,
577 f->mask);
578 MLX5_SET(fte_match_set_misc, misc_c, vxlan_vni,
579 be32_to_cpu(mask->keyid));
580 MLX5_SET(fte_match_set_misc, misc_v, vxlan_vni,
581 be32_to_cpu(key->keyid));
582 }
583}
584
585static int parse_tunnel_attr(struct mlx5e_priv *priv,
586 struct mlx5_flow_spec *spec,
587 struct tc_cls_flower_offload *f)
588{
589 void *headers_c = MLX5_ADDR_OF(fte_match_param, spec->match_criteria,
590 outer_headers);
591 void *headers_v = MLX5_ADDR_OF(fte_match_param, spec->match_value,
592 outer_headers);
593
2e72eb43
OG
594 struct flow_dissector_key_control *enc_control =
595 skb_flow_dissector_target(f->dissector,
596 FLOW_DISSECTOR_KEY_ENC_CONTROL,
597 f->key);
598
bbd00f7e
HHZ
599 if (dissector_uses_key(f->dissector, FLOW_DISSECTOR_KEY_ENC_PORTS)) {
600 struct flow_dissector_key_ports *key =
601 skb_flow_dissector_target(f->dissector,
602 FLOW_DISSECTOR_KEY_ENC_PORTS,
603 f->key);
604 struct flow_dissector_key_ports *mask =
605 skb_flow_dissector_target(f->dissector,
606 FLOW_DISSECTOR_KEY_ENC_PORTS,
607 f->mask);
1ad9a00a
PB
608 struct mlx5_eswitch *esw = priv->mdev->priv.eswitch;
609 struct net_device *up_dev = mlx5_eswitch_get_uplink_netdev(esw);
610 struct mlx5e_priv *up_priv = netdev_priv(up_dev);
bbd00f7e
HHZ
611
612 /* Full udp dst port must be given */
613 if (memchr_inv(&mask->dst, 0xff, sizeof(mask->dst)))
2fcd82e9 614 goto vxlan_match_offload_err;
bbd00f7e 615
1ad9a00a 616 if (mlx5e_vxlan_lookup_port(up_priv, be16_to_cpu(key->dst)) &&
bbd00f7e
HHZ
617 MLX5_CAP_ESW(priv->mdev, vxlan_encap_decap))
618 parse_vxlan_attr(spec, f);
2fcd82e9
OG
619 else {
620 netdev_warn(priv->netdev,
621 "%d isn't an offloaded vxlan udp dport\n", be16_to_cpu(key->dst));
bbd00f7e 622 return -EOPNOTSUPP;
2fcd82e9 623 }
bbd00f7e
HHZ
624
625 MLX5_SET(fte_match_set_lyr_2_4, headers_c,
626 udp_dport, ntohs(mask->dst));
627 MLX5_SET(fte_match_set_lyr_2_4, headers_v,
628 udp_dport, ntohs(key->dst));
629
cd377663
OG
630 MLX5_SET(fte_match_set_lyr_2_4, headers_c,
631 udp_sport, ntohs(mask->src));
632 MLX5_SET(fte_match_set_lyr_2_4, headers_v,
633 udp_sport, ntohs(key->src));
bbd00f7e 634 } else { /* udp dst port must be given */
2fcd82e9
OG
635vxlan_match_offload_err:
636 netdev_warn(priv->netdev,
637 "IP tunnel decap offload supported only for vxlan, must set UDP dport\n");
638 return -EOPNOTSUPP;
bbd00f7e
HHZ
639 }
640
2e72eb43 641 if (enc_control->addr_type == FLOW_DISSECTOR_KEY_IPV4_ADDRS) {
bbd00f7e
HHZ
642 struct flow_dissector_key_ipv4_addrs *key =
643 skb_flow_dissector_target(f->dissector,
644 FLOW_DISSECTOR_KEY_ENC_IPV4_ADDRS,
645 f->key);
646 struct flow_dissector_key_ipv4_addrs *mask =
647 skb_flow_dissector_target(f->dissector,
648 FLOW_DISSECTOR_KEY_ENC_IPV4_ADDRS,
649 f->mask);
650 MLX5_SET(fte_match_set_lyr_2_4, headers_c,
651 src_ipv4_src_ipv6.ipv4_layout.ipv4,
652 ntohl(mask->src));
653 MLX5_SET(fte_match_set_lyr_2_4, headers_v,
654 src_ipv4_src_ipv6.ipv4_layout.ipv4,
655 ntohl(key->src));
656
657 MLX5_SET(fte_match_set_lyr_2_4, headers_c,
658 dst_ipv4_dst_ipv6.ipv4_layout.ipv4,
659 ntohl(mask->dst));
660 MLX5_SET(fte_match_set_lyr_2_4, headers_v,
661 dst_ipv4_dst_ipv6.ipv4_layout.ipv4,
662 ntohl(key->dst));
bbd00f7e 663
2e72eb43
OG
664 MLX5_SET_TO_ONES(fte_match_set_lyr_2_4, headers_c, ethertype);
665 MLX5_SET(fte_match_set_lyr_2_4, headers_v, ethertype, ETH_P_IP);
19f44401
OG
666 } else if (enc_control->addr_type == FLOW_DISSECTOR_KEY_IPV6_ADDRS) {
667 struct flow_dissector_key_ipv6_addrs *key =
668 skb_flow_dissector_target(f->dissector,
669 FLOW_DISSECTOR_KEY_ENC_IPV6_ADDRS,
670 f->key);
671 struct flow_dissector_key_ipv6_addrs *mask =
672 skb_flow_dissector_target(f->dissector,
673 FLOW_DISSECTOR_KEY_ENC_IPV6_ADDRS,
674 f->mask);
675
676 memcpy(MLX5_ADDR_OF(fte_match_set_lyr_2_4, headers_c,
677 src_ipv4_src_ipv6.ipv6_layout.ipv6),
678 &mask->src, MLX5_FLD_SZ_BYTES(ipv6_layout, ipv6));
679 memcpy(MLX5_ADDR_OF(fte_match_set_lyr_2_4, headers_v,
680 src_ipv4_src_ipv6.ipv6_layout.ipv6),
681 &key->src, MLX5_FLD_SZ_BYTES(ipv6_layout, ipv6));
682
683 memcpy(MLX5_ADDR_OF(fte_match_set_lyr_2_4, headers_c,
684 dst_ipv4_dst_ipv6.ipv6_layout.ipv6),
685 &mask->dst, MLX5_FLD_SZ_BYTES(ipv6_layout, ipv6));
686 memcpy(MLX5_ADDR_OF(fte_match_set_lyr_2_4, headers_v,
687 dst_ipv4_dst_ipv6.ipv6_layout.ipv6),
688 &key->dst, MLX5_FLD_SZ_BYTES(ipv6_layout, ipv6));
689
690 MLX5_SET_TO_ONES(fte_match_set_lyr_2_4, headers_c, ethertype);
691 MLX5_SET(fte_match_set_lyr_2_4, headers_v, ethertype, ETH_P_IPV6);
2e72eb43 692 }
bbd00f7e
HHZ
693
694 /* Enforce DMAC when offloading incoming tunneled flows.
695 * Flow counters require a match on the DMAC.
696 */
697 MLX5_SET_TO_ONES(fte_match_set_lyr_2_4, headers_c, dmac_47_16);
698 MLX5_SET_TO_ONES(fte_match_set_lyr_2_4, headers_c, dmac_15_0);
699 ether_addr_copy(MLX5_ADDR_OF(fte_match_set_lyr_2_4, headers_v,
700 dmac_47_16), priv->netdev->dev_addr);
701
702 /* let software handle IP fragments */
703 MLX5_SET(fte_match_set_lyr_2_4, headers_c, frag, 1);
704 MLX5_SET(fte_match_set_lyr_2_4, headers_v, frag, 0);
705
706 return 0;
707}
708
de0af0bf
RD
709static int __parse_cls_flower(struct mlx5e_priv *priv,
710 struct mlx5_flow_spec *spec,
711 struct tc_cls_flower_offload *f,
712 u8 *min_inline)
e3a2b7ed 713{
c5bb1730
MG
714 void *headers_c = MLX5_ADDR_OF(fte_match_param, spec->match_criteria,
715 outer_headers);
716 void *headers_v = MLX5_ADDR_OF(fte_match_param, spec->match_value,
717 outer_headers);
e3a2b7ed
AV
718 u16 addr_type = 0;
719 u8 ip_proto = 0;
720
de0af0bf
RD
721 *min_inline = MLX5_INLINE_MODE_L2;
722
e3a2b7ed
AV
723 if (f->dissector->used_keys &
724 ~(BIT(FLOW_DISSECTOR_KEY_CONTROL) |
725 BIT(FLOW_DISSECTOR_KEY_BASIC) |
726 BIT(FLOW_DISSECTOR_KEY_ETH_ADDRS) |
095b6cfd 727 BIT(FLOW_DISSECTOR_KEY_VLAN) |
e3a2b7ed
AV
728 BIT(FLOW_DISSECTOR_KEY_IPV4_ADDRS) |
729 BIT(FLOW_DISSECTOR_KEY_IPV6_ADDRS) |
bbd00f7e
HHZ
730 BIT(FLOW_DISSECTOR_KEY_PORTS) |
731 BIT(FLOW_DISSECTOR_KEY_ENC_KEYID) |
732 BIT(FLOW_DISSECTOR_KEY_ENC_IPV4_ADDRS) |
733 BIT(FLOW_DISSECTOR_KEY_ENC_IPV6_ADDRS) |
734 BIT(FLOW_DISSECTOR_KEY_ENC_PORTS) |
e77834ec 735 BIT(FLOW_DISSECTOR_KEY_ENC_CONTROL) |
fd7da28b
OG
736 BIT(FLOW_DISSECTOR_KEY_TCP) |
737 BIT(FLOW_DISSECTOR_KEY_IP))) {
e3a2b7ed
AV
738 netdev_warn(priv->netdev, "Unsupported key used: 0x%x\n",
739 f->dissector->used_keys);
740 return -EOPNOTSUPP;
741 }
742
bbd00f7e
HHZ
743 if ((dissector_uses_key(f->dissector,
744 FLOW_DISSECTOR_KEY_ENC_IPV4_ADDRS) ||
745 dissector_uses_key(f->dissector, FLOW_DISSECTOR_KEY_ENC_KEYID) ||
746 dissector_uses_key(f->dissector, FLOW_DISSECTOR_KEY_ENC_PORTS)) &&
747 dissector_uses_key(f->dissector, FLOW_DISSECTOR_KEY_ENC_CONTROL)) {
748 struct flow_dissector_key_control *key =
749 skb_flow_dissector_target(f->dissector,
750 FLOW_DISSECTOR_KEY_ENC_CONTROL,
751 f->key);
752 switch (key->addr_type) {
753 case FLOW_DISSECTOR_KEY_IPV4_ADDRS:
19f44401 754 case FLOW_DISSECTOR_KEY_IPV6_ADDRS:
bbd00f7e
HHZ
755 if (parse_tunnel_attr(priv, spec, f))
756 return -EOPNOTSUPP;
757 break;
758 default:
759 return -EOPNOTSUPP;
760 }
761
762 /* In decap flow, header pointers should point to the inner
763 * headers, outer header were already set by parse_tunnel_attr
764 */
765 headers_c = MLX5_ADDR_OF(fte_match_param, spec->match_criteria,
766 inner_headers);
767 headers_v = MLX5_ADDR_OF(fte_match_param, spec->match_value,
768 inner_headers);
769 }
770
e3a2b7ed
AV
771 if (dissector_uses_key(f->dissector, FLOW_DISSECTOR_KEY_CONTROL)) {
772 struct flow_dissector_key_control *key =
773 skb_flow_dissector_target(f->dissector,
1dbd0d37 774 FLOW_DISSECTOR_KEY_CONTROL,
e3a2b7ed 775 f->key);
3f7d0eb4
OG
776
777 struct flow_dissector_key_control *mask =
778 skb_flow_dissector_target(f->dissector,
779 FLOW_DISSECTOR_KEY_CONTROL,
780 f->mask);
e3a2b7ed 781 addr_type = key->addr_type;
3f7d0eb4
OG
782
783 if (mask->flags & FLOW_DIS_IS_FRAGMENT) {
784 MLX5_SET(fte_match_set_lyr_2_4, headers_c, frag, 1);
785 MLX5_SET(fte_match_set_lyr_2_4, headers_v, frag,
786 key->flags & FLOW_DIS_IS_FRAGMENT);
0827444d
OG
787
788 /* the HW doesn't need L3 inline to match on frag=no */
789 if (key->flags & FLOW_DIS_IS_FRAGMENT)
790 *min_inline = MLX5_INLINE_MODE_IP;
3f7d0eb4 791 }
e3a2b7ed
AV
792 }
793
794 if (dissector_uses_key(f->dissector, FLOW_DISSECTOR_KEY_BASIC)) {
795 struct flow_dissector_key_basic *key =
796 skb_flow_dissector_target(f->dissector,
797 FLOW_DISSECTOR_KEY_BASIC,
798 f->key);
799 struct flow_dissector_key_basic *mask =
800 skb_flow_dissector_target(f->dissector,
801 FLOW_DISSECTOR_KEY_BASIC,
802 f->mask);
803 ip_proto = key->ip_proto;
804
805 MLX5_SET(fte_match_set_lyr_2_4, headers_c, ethertype,
806 ntohs(mask->n_proto));
807 MLX5_SET(fte_match_set_lyr_2_4, headers_v, ethertype,
808 ntohs(key->n_proto));
809
810 MLX5_SET(fte_match_set_lyr_2_4, headers_c, ip_protocol,
811 mask->ip_proto);
812 MLX5_SET(fte_match_set_lyr_2_4, headers_v, ip_protocol,
813 key->ip_proto);
de0af0bf
RD
814
815 if (mask->ip_proto)
816 *min_inline = MLX5_INLINE_MODE_IP;
e3a2b7ed
AV
817 }
818
819 if (dissector_uses_key(f->dissector, FLOW_DISSECTOR_KEY_ETH_ADDRS)) {
820 struct flow_dissector_key_eth_addrs *key =
821 skb_flow_dissector_target(f->dissector,
822 FLOW_DISSECTOR_KEY_ETH_ADDRS,
823 f->key);
824 struct flow_dissector_key_eth_addrs *mask =
825 skb_flow_dissector_target(f->dissector,
826 FLOW_DISSECTOR_KEY_ETH_ADDRS,
827 f->mask);
828
829 ether_addr_copy(MLX5_ADDR_OF(fte_match_set_lyr_2_4, headers_c,
830 dmac_47_16),
831 mask->dst);
832 ether_addr_copy(MLX5_ADDR_OF(fte_match_set_lyr_2_4, headers_v,
833 dmac_47_16),
834 key->dst);
835
836 ether_addr_copy(MLX5_ADDR_OF(fte_match_set_lyr_2_4, headers_c,
837 smac_47_16),
838 mask->src);
839 ether_addr_copy(MLX5_ADDR_OF(fte_match_set_lyr_2_4, headers_v,
840 smac_47_16),
841 key->src);
842 }
843
095b6cfd
OG
844 if (dissector_uses_key(f->dissector, FLOW_DISSECTOR_KEY_VLAN)) {
845 struct flow_dissector_key_vlan *key =
846 skb_flow_dissector_target(f->dissector,
847 FLOW_DISSECTOR_KEY_VLAN,
848 f->key);
849 struct flow_dissector_key_vlan *mask =
850 skb_flow_dissector_target(f->dissector,
851 FLOW_DISSECTOR_KEY_VLAN,
852 f->mask);
358d79a4 853 if (mask->vlan_id || mask->vlan_priority) {
10543365
MHY
854 MLX5_SET(fte_match_set_lyr_2_4, headers_c, cvlan_tag, 1);
855 MLX5_SET(fte_match_set_lyr_2_4, headers_v, cvlan_tag, 1);
095b6cfd
OG
856
857 MLX5_SET(fte_match_set_lyr_2_4, headers_c, first_vid, mask->vlan_id);
858 MLX5_SET(fte_match_set_lyr_2_4, headers_v, first_vid, key->vlan_id);
358d79a4
OG
859
860 MLX5_SET(fte_match_set_lyr_2_4, headers_c, first_prio, mask->vlan_priority);
861 MLX5_SET(fte_match_set_lyr_2_4, headers_v, first_prio, key->vlan_priority);
095b6cfd
OG
862 }
863 }
864
e3a2b7ed
AV
865 if (addr_type == FLOW_DISSECTOR_KEY_IPV4_ADDRS) {
866 struct flow_dissector_key_ipv4_addrs *key =
867 skb_flow_dissector_target(f->dissector,
868 FLOW_DISSECTOR_KEY_IPV4_ADDRS,
869 f->key);
870 struct flow_dissector_key_ipv4_addrs *mask =
871 skb_flow_dissector_target(f->dissector,
872 FLOW_DISSECTOR_KEY_IPV4_ADDRS,
873 f->mask);
874
875 memcpy(MLX5_ADDR_OF(fte_match_set_lyr_2_4, headers_c,
876 src_ipv4_src_ipv6.ipv4_layout.ipv4),
877 &mask->src, sizeof(mask->src));
878 memcpy(MLX5_ADDR_OF(fte_match_set_lyr_2_4, headers_v,
879 src_ipv4_src_ipv6.ipv4_layout.ipv4),
880 &key->src, sizeof(key->src));
881 memcpy(MLX5_ADDR_OF(fte_match_set_lyr_2_4, headers_c,
882 dst_ipv4_dst_ipv6.ipv4_layout.ipv4),
883 &mask->dst, sizeof(mask->dst));
884 memcpy(MLX5_ADDR_OF(fte_match_set_lyr_2_4, headers_v,
885 dst_ipv4_dst_ipv6.ipv4_layout.ipv4),
886 &key->dst, sizeof(key->dst));
de0af0bf
RD
887
888 if (mask->src || mask->dst)
889 *min_inline = MLX5_INLINE_MODE_IP;
e3a2b7ed
AV
890 }
891
892 if (addr_type == FLOW_DISSECTOR_KEY_IPV6_ADDRS) {
893 struct flow_dissector_key_ipv6_addrs *key =
894 skb_flow_dissector_target(f->dissector,
895 FLOW_DISSECTOR_KEY_IPV6_ADDRS,
896 f->key);
897 struct flow_dissector_key_ipv6_addrs *mask =
898 skb_flow_dissector_target(f->dissector,
899 FLOW_DISSECTOR_KEY_IPV6_ADDRS,
900 f->mask);
901
902 memcpy(MLX5_ADDR_OF(fte_match_set_lyr_2_4, headers_c,
903 src_ipv4_src_ipv6.ipv6_layout.ipv6),
904 &mask->src, sizeof(mask->src));
905 memcpy(MLX5_ADDR_OF(fte_match_set_lyr_2_4, headers_v,
906 src_ipv4_src_ipv6.ipv6_layout.ipv6),
907 &key->src, sizeof(key->src));
908
909 memcpy(MLX5_ADDR_OF(fte_match_set_lyr_2_4, headers_c,
910 dst_ipv4_dst_ipv6.ipv6_layout.ipv6),
911 &mask->dst, sizeof(mask->dst));
912 memcpy(MLX5_ADDR_OF(fte_match_set_lyr_2_4, headers_v,
913 dst_ipv4_dst_ipv6.ipv6_layout.ipv6),
914 &key->dst, sizeof(key->dst));
de0af0bf
RD
915
916 if (ipv6_addr_type(&mask->src) != IPV6_ADDR_ANY ||
917 ipv6_addr_type(&mask->dst) != IPV6_ADDR_ANY)
918 *min_inline = MLX5_INLINE_MODE_IP;
e3a2b7ed
AV
919 }
920
1f97a526
OG
921 if (dissector_uses_key(f->dissector, FLOW_DISSECTOR_KEY_IP)) {
922 struct flow_dissector_key_ip *key =
923 skb_flow_dissector_target(f->dissector,
924 FLOW_DISSECTOR_KEY_IP,
925 f->key);
926 struct flow_dissector_key_ip *mask =
927 skb_flow_dissector_target(f->dissector,
928 FLOW_DISSECTOR_KEY_IP,
929 f->mask);
930
931 MLX5_SET(fte_match_set_lyr_2_4, headers_c, ip_ecn, mask->tos & 0x3);
932 MLX5_SET(fte_match_set_lyr_2_4, headers_v, ip_ecn, key->tos & 0x3);
933
934 MLX5_SET(fte_match_set_lyr_2_4, headers_c, ip_dscp, mask->tos >> 2);
935 MLX5_SET(fte_match_set_lyr_2_4, headers_v, ip_dscp, key->tos >> 2);
936
a8ade55f
OG
937 MLX5_SET(fte_match_set_lyr_2_4, headers_c, ttl_hoplimit, mask->ttl);
938 MLX5_SET(fte_match_set_lyr_2_4, headers_v, ttl_hoplimit, key->ttl);
1f97a526 939
a8ade55f
OG
940 if (mask->ttl &&
941 !MLX5_CAP_ESW_FLOWTABLE_FDB(priv->mdev,
942 ft_field_support.outer_ipv4_ttl))
1f97a526 943 return -EOPNOTSUPP;
a8ade55f
OG
944
945 if (mask->tos || mask->ttl)
946 *min_inline = MLX5_INLINE_MODE_IP;
1f97a526
OG
947 }
948
e3a2b7ed
AV
949 if (dissector_uses_key(f->dissector, FLOW_DISSECTOR_KEY_PORTS)) {
950 struct flow_dissector_key_ports *key =
951 skb_flow_dissector_target(f->dissector,
952 FLOW_DISSECTOR_KEY_PORTS,
953 f->key);
954 struct flow_dissector_key_ports *mask =
955 skb_flow_dissector_target(f->dissector,
956 FLOW_DISSECTOR_KEY_PORTS,
957 f->mask);
958 switch (ip_proto) {
959 case IPPROTO_TCP:
960 MLX5_SET(fte_match_set_lyr_2_4, headers_c,
961 tcp_sport, ntohs(mask->src));
962 MLX5_SET(fte_match_set_lyr_2_4, headers_v,
963 tcp_sport, ntohs(key->src));
964
965 MLX5_SET(fte_match_set_lyr_2_4, headers_c,
966 tcp_dport, ntohs(mask->dst));
967 MLX5_SET(fte_match_set_lyr_2_4, headers_v,
968 tcp_dport, ntohs(key->dst));
969 break;
970
971 case IPPROTO_UDP:
972 MLX5_SET(fte_match_set_lyr_2_4, headers_c,
973 udp_sport, ntohs(mask->src));
974 MLX5_SET(fte_match_set_lyr_2_4, headers_v,
975 udp_sport, ntohs(key->src));
976
977 MLX5_SET(fte_match_set_lyr_2_4, headers_c,
978 udp_dport, ntohs(mask->dst));
979 MLX5_SET(fte_match_set_lyr_2_4, headers_v,
980 udp_dport, ntohs(key->dst));
981 break;
982 default:
983 netdev_err(priv->netdev,
984 "Only UDP and TCP transport are supported\n");
985 return -EINVAL;
986 }
de0af0bf
RD
987
988 if (mask->src || mask->dst)
989 *min_inline = MLX5_INLINE_MODE_TCP_UDP;
e3a2b7ed
AV
990 }
991
e77834ec
OG
992 if (dissector_uses_key(f->dissector, FLOW_DISSECTOR_KEY_TCP)) {
993 struct flow_dissector_key_tcp *key =
994 skb_flow_dissector_target(f->dissector,
995 FLOW_DISSECTOR_KEY_TCP,
996 f->key);
997 struct flow_dissector_key_tcp *mask =
998 skb_flow_dissector_target(f->dissector,
999 FLOW_DISSECTOR_KEY_TCP,
1000 f->mask);
1001
1002 MLX5_SET(fte_match_set_lyr_2_4, headers_c, tcp_flags,
1003 ntohs(mask->flags));
1004 MLX5_SET(fte_match_set_lyr_2_4, headers_v, tcp_flags,
1005 ntohs(key->flags));
1006
1007 if (mask->flags)
1008 *min_inline = MLX5_INLINE_MODE_TCP_UDP;
1009 }
1010
e3a2b7ed
AV
1011 return 0;
1012}
1013
de0af0bf 1014static int parse_cls_flower(struct mlx5e_priv *priv,
65ba8fb7 1015 struct mlx5e_tc_flow *flow,
de0af0bf
RD
1016 struct mlx5_flow_spec *spec,
1017 struct tc_cls_flower_offload *f)
1018{
1019 struct mlx5_core_dev *dev = priv->mdev;
1020 struct mlx5_eswitch *esw = dev->priv.eswitch;
1d447a39
SM
1021 struct mlx5e_rep_priv *rpriv = priv->ppriv;
1022 struct mlx5_eswitch_rep *rep;
de0af0bf
RD
1023 u8 min_inline;
1024 int err;
1025
1026 err = __parse_cls_flower(priv, spec, f, &min_inline);
1027
1d447a39
SM
1028 if (!err && (flow->flags & MLX5E_TC_FLOW_ESWITCH)) {
1029 rep = rpriv->rep;
1030 if (rep->vport != FDB_UPLINK_VPORT &&
1031 (esw->offloads.inline_mode != MLX5_INLINE_MODE_NONE &&
1032 esw->offloads.inline_mode < min_inline)) {
de0af0bf
RD
1033 netdev_warn(priv->netdev,
1034 "Flow is not offloaded due to min inline setting, required %d actual %d\n",
1035 min_inline, esw->offloads.inline_mode);
1036 return -EOPNOTSUPP;
1037 }
1038 }
1039
1040 return err;
1041}
1042
d79b6df6
OG
1043struct pedit_headers {
1044 struct ethhdr eth;
1045 struct iphdr ip4;
1046 struct ipv6hdr ip6;
1047 struct tcphdr tcp;
1048 struct udphdr udp;
1049};
1050
1051static int pedit_header_offsets[] = {
1052 [TCA_PEDIT_KEY_EX_HDR_TYPE_ETH] = offsetof(struct pedit_headers, eth),
1053 [TCA_PEDIT_KEY_EX_HDR_TYPE_IP4] = offsetof(struct pedit_headers, ip4),
1054 [TCA_PEDIT_KEY_EX_HDR_TYPE_IP6] = offsetof(struct pedit_headers, ip6),
1055 [TCA_PEDIT_KEY_EX_HDR_TYPE_TCP] = offsetof(struct pedit_headers, tcp),
1056 [TCA_PEDIT_KEY_EX_HDR_TYPE_UDP] = offsetof(struct pedit_headers, udp),
1057};
1058
1059#define pedit_header(_ph, _htype) ((void *)(_ph) + pedit_header_offsets[_htype])
1060
1061static int set_pedit_val(u8 hdr_type, u32 mask, u32 val, u32 offset,
1062 struct pedit_headers *masks,
1063 struct pedit_headers *vals)
1064{
1065 u32 *curr_pmask, *curr_pval;
1066
1067 if (hdr_type >= __PEDIT_HDR_TYPE_MAX)
1068 goto out_err;
1069
1070 curr_pmask = (u32 *)(pedit_header(masks, hdr_type) + offset);
1071 curr_pval = (u32 *)(pedit_header(vals, hdr_type) + offset);
1072
1073 if (*curr_pmask & mask) /* disallow acting twice on the same location */
1074 goto out_err;
1075
1076 *curr_pmask |= mask;
1077 *curr_pval |= (val & mask);
1078
1079 return 0;
1080
1081out_err:
1082 return -EOPNOTSUPP;
1083}
1084
1085struct mlx5_fields {
1086 u8 field;
1087 u8 size;
1088 u32 offset;
1089};
1090
a8e4f0c4
OG
1091#define OFFLOAD(fw_field, size, field, off) \
1092 {MLX5_ACTION_IN_FIELD_OUT_ ## fw_field, size, offsetof(struct pedit_headers, field) + (off)}
1093
d79b6df6 1094static struct mlx5_fields fields[] = {
a8e4f0c4
OG
1095 OFFLOAD(DMAC_47_16, 4, eth.h_dest[0], 0),
1096 OFFLOAD(DMAC_47_16, 4, eth.h_dest[0], 0),
1097 OFFLOAD(DMAC_15_0, 2, eth.h_dest[4], 0),
1098 OFFLOAD(SMAC_47_16, 4, eth.h_source[0], 0),
1099 OFFLOAD(SMAC_15_0, 2, eth.h_source[4], 0),
1100 OFFLOAD(ETHERTYPE, 2, eth.h_proto, 0),
1101
1102 OFFLOAD(IP_TTL, 1, ip4.ttl, 0),
1103 OFFLOAD(SIPV4, 4, ip4.saddr, 0),
1104 OFFLOAD(DIPV4, 4, ip4.daddr, 0),
1105
1106 OFFLOAD(SIPV6_127_96, 4, ip6.saddr.s6_addr32[0], 0),
1107 OFFLOAD(SIPV6_95_64, 4, ip6.saddr.s6_addr32[1], 0),
1108 OFFLOAD(SIPV6_63_32, 4, ip6.saddr.s6_addr32[2], 0),
1109 OFFLOAD(SIPV6_31_0, 4, ip6.saddr.s6_addr32[3], 0),
1110 OFFLOAD(DIPV6_127_96, 4, ip6.daddr.s6_addr32[0], 0),
1111 OFFLOAD(DIPV6_95_64, 4, ip6.daddr.s6_addr32[1], 0),
1112 OFFLOAD(DIPV6_63_32, 4, ip6.daddr.s6_addr32[2], 0),
1113 OFFLOAD(DIPV6_31_0, 4, ip6.daddr.s6_addr32[3], 0),
0c0316f5 1114 OFFLOAD(IPV6_HOPLIMIT, 1, ip6.hop_limit, 0),
a8e4f0c4
OG
1115
1116 OFFLOAD(TCP_SPORT, 2, tcp.source, 0),
1117 OFFLOAD(TCP_DPORT, 2, tcp.dest, 0),
1118 OFFLOAD(TCP_FLAGS, 1, tcp.ack_seq, 5),
1119
1120 OFFLOAD(UDP_SPORT, 2, udp.source, 0),
1121 OFFLOAD(UDP_DPORT, 2, udp.dest, 0),
d79b6df6
OG
1122};
1123
1124/* On input attr->num_mod_hdr_actions tells how many HW actions can be parsed at
1125 * max from the SW pedit action. On success, it says how many HW actions were
1126 * actually parsed.
1127 */
1128static int offload_pedit_fields(struct pedit_headers *masks,
1129 struct pedit_headers *vals,
1130 struct mlx5e_tc_flow_parse_attr *parse_attr)
1131{
1132 struct pedit_headers *set_masks, *add_masks, *set_vals, *add_vals;
2b64beba 1133 int i, action_size, nactions, max_actions, first, last, next_z;
d79b6df6 1134 void *s_masks_p, *a_masks_p, *vals_p;
d79b6df6
OG
1135 struct mlx5_fields *f;
1136 u8 cmd, field_bsize;
e3ca4e05 1137 u32 s_mask, a_mask;
d79b6df6 1138 unsigned long mask;
2b64beba
OG
1139 __be32 mask_be32;
1140 __be16 mask_be16;
d79b6df6
OG
1141 void *action;
1142
1143 set_masks = &masks[TCA_PEDIT_KEY_EX_CMD_SET];
1144 add_masks = &masks[TCA_PEDIT_KEY_EX_CMD_ADD];
1145 set_vals = &vals[TCA_PEDIT_KEY_EX_CMD_SET];
1146 add_vals = &vals[TCA_PEDIT_KEY_EX_CMD_ADD];
1147
1148 action_size = MLX5_UN_SZ_BYTES(set_action_in_add_action_in_auto);
1149 action = parse_attr->mod_hdr_actions;
1150 max_actions = parse_attr->num_mod_hdr_actions;
1151 nactions = 0;
1152
1153 for (i = 0; i < ARRAY_SIZE(fields); i++) {
1154 f = &fields[i];
1155 /* avoid seeing bits set from previous iterations */
e3ca4e05
OG
1156 s_mask = 0;
1157 a_mask = 0;
d79b6df6
OG
1158
1159 s_masks_p = (void *)set_masks + f->offset;
1160 a_masks_p = (void *)add_masks + f->offset;
1161
1162 memcpy(&s_mask, s_masks_p, f->size);
1163 memcpy(&a_mask, a_masks_p, f->size);
1164
1165 if (!s_mask && !a_mask) /* nothing to offload here */
1166 continue;
1167
1168 if (s_mask && a_mask) {
1169 printk(KERN_WARNING "mlx5: can't set and add to the same HW field (%x)\n", f->field);
1170 return -EOPNOTSUPP;
1171 }
1172
1173 if (nactions == max_actions) {
1174 printk(KERN_WARNING "mlx5: parsed %d pedit actions, can't do more\n", nactions);
1175 return -EOPNOTSUPP;
1176 }
1177
1178 if (s_mask) {
1179 cmd = MLX5_ACTION_TYPE_SET;
1180 mask = s_mask;
1181 vals_p = (void *)set_vals + f->offset;
1182 /* clear to denote we consumed this field */
1183 memset(s_masks_p, 0, f->size);
1184 } else {
1185 cmd = MLX5_ACTION_TYPE_ADD;
1186 mask = a_mask;
1187 vals_p = (void *)add_vals + f->offset;
1188 /* clear to denote we consumed this field */
1189 memset(a_masks_p, 0, f->size);
1190 }
1191
d79b6df6 1192 field_bsize = f->size * BITS_PER_BYTE;
e3ca4e05 1193
2b64beba
OG
1194 if (field_bsize == 32) {
1195 mask_be32 = *(__be32 *)&mask;
1196 mask = (__force unsigned long)cpu_to_le32(be32_to_cpu(mask_be32));
1197 } else if (field_bsize == 16) {
1198 mask_be16 = *(__be16 *)&mask;
1199 mask = (__force unsigned long)cpu_to_le16(be16_to_cpu(mask_be16));
1200 }
1201
d79b6df6 1202 first = find_first_bit(&mask, field_bsize);
2b64beba 1203 next_z = find_next_zero_bit(&mask, field_bsize, first);
d79b6df6 1204 last = find_last_bit(&mask, field_bsize);
2b64beba
OG
1205 if (first < next_z && next_z < last) {
1206 printk(KERN_WARNING "mlx5: rewrite of few sub-fields (mask %lx) isn't offloaded\n",
d79b6df6
OG
1207 mask);
1208 return -EOPNOTSUPP;
1209 }
1210
1211 MLX5_SET(set_action_in, action, action_type, cmd);
1212 MLX5_SET(set_action_in, action, field, f->field);
1213
1214 if (cmd == MLX5_ACTION_TYPE_SET) {
2b64beba 1215 MLX5_SET(set_action_in, action, offset, first);
d79b6df6 1216 /* length is num of bits to be written, zero means length of 32 */
2b64beba 1217 MLX5_SET(set_action_in, action, length, (last - first + 1));
d79b6df6
OG
1218 }
1219
1220 if (field_bsize == 32)
2b64beba 1221 MLX5_SET(set_action_in, action, data, ntohl(*(__be32 *)vals_p) >> first);
d79b6df6 1222 else if (field_bsize == 16)
2b64beba 1223 MLX5_SET(set_action_in, action, data, ntohs(*(__be16 *)vals_p) >> first);
d79b6df6 1224 else if (field_bsize == 8)
2b64beba 1225 MLX5_SET(set_action_in, action, data, *(u8 *)vals_p >> first);
d79b6df6
OG
1226
1227 action += action_size;
1228 nactions++;
1229 }
1230
1231 parse_attr->num_mod_hdr_actions = nactions;
1232 return 0;
1233}
1234
1235static int alloc_mod_hdr_actions(struct mlx5e_priv *priv,
1236 const struct tc_action *a, int namespace,
1237 struct mlx5e_tc_flow_parse_attr *parse_attr)
1238{
1239 int nkeys, action_size, max_actions;
1240
1241 nkeys = tcf_pedit_nkeys(a);
1242 action_size = MLX5_UN_SZ_BYTES(set_action_in_add_action_in_auto);
1243
1244 if (namespace == MLX5_FLOW_NAMESPACE_FDB) /* FDB offloading */
1245 max_actions = MLX5_CAP_ESW_FLOWTABLE_FDB(priv->mdev, max_modify_header_actions);
1246 else /* namespace is MLX5_FLOW_NAMESPACE_KERNEL - NIC offloading */
1247 max_actions = MLX5_CAP_FLOWTABLE_NIC_RX(priv->mdev, max_modify_header_actions);
1248
1249 /* can get up to crazingly 16 HW actions in 32 bits pedit SW key */
1250 max_actions = min(max_actions, nkeys * 16);
1251
1252 parse_attr->mod_hdr_actions = kcalloc(max_actions, action_size, GFP_KERNEL);
1253 if (!parse_attr->mod_hdr_actions)
1254 return -ENOMEM;
1255
1256 parse_attr->num_mod_hdr_actions = max_actions;
1257 return 0;
1258}
1259
1260static const struct pedit_headers zero_masks = {};
1261
1262static int parse_tc_pedit_action(struct mlx5e_priv *priv,
1263 const struct tc_action *a, int namespace,
1264 struct mlx5e_tc_flow_parse_attr *parse_attr)
1265{
1266 struct pedit_headers masks[__PEDIT_CMD_MAX], vals[__PEDIT_CMD_MAX], *cmd_masks;
1267 int nkeys, i, err = -EOPNOTSUPP;
1268 u32 mask, val, offset;
1269 u8 cmd, htype;
1270
1271 nkeys = tcf_pedit_nkeys(a);
1272
1273 memset(masks, 0, sizeof(struct pedit_headers) * __PEDIT_CMD_MAX);
1274 memset(vals, 0, sizeof(struct pedit_headers) * __PEDIT_CMD_MAX);
1275
1276 for (i = 0; i < nkeys; i++) {
1277 htype = tcf_pedit_htype(a, i);
1278 cmd = tcf_pedit_cmd(a, i);
1279 err = -EOPNOTSUPP; /* can't be all optimistic */
1280
1281 if (htype == TCA_PEDIT_KEY_EX_HDR_TYPE_NETWORK) {
1282 printk(KERN_WARNING "mlx5: legacy pedit isn't offloaded\n");
1283 goto out_err;
1284 }
1285
1286 if (cmd != TCA_PEDIT_KEY_EX_CMD_SET && cmd != TCA_PEDIT_KEY_EX_CMD_ADD) {
1287 printk(KERN_WARNING "mlx5: pedit cmd %d isn't offloaded\n", cmd);
1288 goto out_err;
1289 }
1290
1291 mask = tcf_pedit_mask(a, i);
1292 val = tcf_pedit_val(a, i);
1293 offset = tcf_pedit_offset(a, i);
1294
1295 err = set_pedit_val(htype, ~mask, val, offset, &masks[cmd], &vals[cmd]);
1296 if (err)
1297 goto out_err;
1298 }
1299
1300 err = alloc_mod_hdr_actions(priv, a, namespace, parse_attr);
1301 if (err)
1302 goto out_err;
1303
1304 err = offload_pedit_fields(masks, vals, parse_attr);
1305 if (err < 0)
1306 goto out_dealloc_parsed_actions;
1307
1308 for (cmd = 0; cmd < __PEDIT_CMD_MAX; cmd++) {
1309 cmd_masks = &masks[cmd];
1310 if (memcmp(cmd_masks, &zero_masks, sizeof(zero_masks))) {
1311 printk(KERN_WARNING "mlx5: attempt to offload an unsupported field (cmd %d)\n",
1312 cmd);
1313 print_hex_dump(KERN_WARNING, "mask: ", DUMP_PREFIX_ADDRESS,
1314 16, 1, cmd_masks, sizeof(zero_masks), true);
1315 err = -EOPNOTSUPP;
1316 goto out_dealloc_parsed_actions;
1317 }
1318 }
1319
1320 return 0;
1321
1322out_dealloc_parsed_actions:
1323 kfree(parse_attr->mod_hdr_actions);
1324out_err:
1325 return err;
1326}
1327
26c02749
OG
1328static bool csum_offload_supported(struct mlx5e_priv *priv, u32 action, u32 update_flags)
1329{
1330 u32 prot_flags = TCA_CSUM_UPDATE_FLAG_IPV4HDR | TCA_CSUM_UPDATE_FLAG_TCP |
1331 TCA_CSUM_UPDATE_FLAG_UDP;
1332
1333 /* The HW recalcs checksums only if re-writing headers */
1334 if (!(action & MLX5_FLOW_CONTEXT_ACTION_MOD_HDR)) {
1335 netdev_warn(priv->netdev,
1336 "TC csum action is only offloaded with pedit\n");
1337 return false;
1338 }
1339
1340 if (update_flags & ~prot_flags) {
1341 netdev_warn(priv->netdev,
1342 "can't offload TC csum action for some header/s - flags %#x\n",
1343 update_flags);
1344 return false;
1345 }
1346
1347 return true;
1348}
1349
bdd66ac0
OG
1350static bool modify_header_match_supported(struct mlx5_flow_spec *spec,
1351 struct tcf_exts *exts)
1352{
1353 const struct tc_action *a;
1354 bool modify_ip_header;
1355 LIST_HEAD(actions);
1356 u8 htype, ip_proto;
1357 void *headers_v;
1358 u16 ethertype;
1359 int nkeys, i;
1360
1361 headers_v = MLX5_ADDR_OF(fte_match_param, spec->match_value, outer_headers);
1362 ethertype = MLX5_GET(fte_match_set_lyr_2_4, headers_v, ethertype);
1363
1364 /* for non-IP we only re-write MACs, so we're okay */
1365 if (ethertype != ETH_P_IP && ethertype != ETH_P_IPV6)
1366 goto out_ok;
1367
1368 modify_ip_header = false;
1369 tcf_exts_to_list(exts, &actions);
1370 list_for_each_entry(a, &actions, list) {
1371 if (!is_tcf_pedit(a))
1372 continue;
1373
1374 nkeys = tcf_pedit_nkeys(a);
1375 for (i = 0; i < nkeys; i++) {
1376 htype = tcf_pedit_htype(a, i);
1377 if (htype == TCA_PEDIT_KEY_EX_HDR_TYPE_IP4 ||
1378 htype == TCA_PEDIT_KEY_EX_HDR_TYPE_IP6) {
1379 modify_ip_header = true;
1380 break;
1381 }
1382 }
1383 }
1384
1385 ip_proto = MLX5_GET(fte_match_set_lyr_2_4, headers_v, ip_protocol);
1386 if (modify_ip_header && ip_proto != IPPROTO_TCP && ip_proto != IPPROTO_UDP) {
1387 pr_info("can't offload re-write of ip proto %d\n", ip_proto);
1388 return false;
1389 }
1390
1391out_ok:
1392 return true;
1393}
1394
1395static bool actions_match_supported(struct mlx5e_priv *priv,
1396 struct tcf_exts *exts,
1397 struct mlx5e_tc_flow_parse_attr *parse_attr,
1398 struct mlx5e_tc_flow *flow)
1399{
1400 u32 actions;
1401
1402 if (flow->flags & MLX5E_TC_FLOW_ESWITCH)
1403 actions = flow->esw_attr->action;
1404 else
1405 actions = flow->nic_attr->action;
1406
1407 if (actions & MLX5_FLOW_CONTEXT_ACTION_MOD_HDR)
1408 return modify_header_match_supported(&parse_attr->spec, exts);
1409
1410 return true;
1411}
1412
5c40348c 1413static int parse_tc_nic_actions(struct mlx5e_priv *priv, struct tcf_exts *exts,
aa0cbbae
OG
1414 struct mlx5e_tc_flow_parse_attr *parse_attr,
1415 struct mlx5e_tc_flow *flow)
e3a2b7ed 1416{
aa0cbbae 1417 struct mlx5_nic_flow_attr *attr = flow->nic_attr;
e3a2b7ed 1418 const struct tc_action *a;
22dc13c8 1419 LIST_HEAD(actions);
2f4fe4ca 1420 int err;
e3a2b7ed 1421
3bcc0cec 1422 if (!tcf_exts_has_actions(exts))
e3a2b7ed
AV
1423 return -EINVAL;
1424
3bc4b7bf
OG
1425 attr->flow_tag = MLX5_FS_DEFAULT_FLOW_TAG;
1426 attr->action = 0;
e3a2b7ed 1427
22dc13c8
WC
1428 tcf_exts_to_list(exts, &actions);
1429 list_for_each_entry(a, &actions, list) {
e3a2b7ed 1430 if (is_tcf_gact_shot(a)) {
3bc4b7bf 1431 attr->action |= MLX5_FLOW_CONTEXT_ACTION_DROP;
aad7e08d
AV
1432 if (MLX5_CAP_FLOWTABLE(priv->mdev,
1433 flow_table_properties_nic_receive.flow_counter))
3bc4b7bf 1434 attr->action |= MLX5_FLOW_CONTEXT_ACTION_COUNT;
e3a2b7ed
AV
1435 continue;
1436 }
1437
2f4fe4ca
OG
1438 if (is_tcf_pedit(a)) {
1439 err = parse_tc_pedit_action(priv, a, MLX5_FLOW_NAMESPACE_KERNEL,
1440 parse_attr);
1441 if (err)
1442 return err;
1443
1444 attr->action |= MLX5_FLOW_CONTEXT_ACTION_MOD_HDR |
1445 MLX5_FLOW_CONTEXT_ACTION_FWD_DEST;
1446 continue;
1447 }
1448
26c02749
OG
1449 if (is_tcf_csum(a)) {
1450 if (csum_offload_supported(priv, attr->action,
1451 tcf_csum_update_flags(a)))
1452 continue;
1453
1454 return -EOPNOTSUPP;
1455 }
1456
e3a2b7ed
AV
1457 if (is_tcf_skbedit_mark(a)) {
1458 u32 mark = tcf_skbedit_mark(a);
1459
1460 if (mark & ~MLX5E_TC_FLOW_ID_MASK) {
1461 netdev_warn(priv->netdev, "Bad flow mark - only 16 bit is supported: 0x%x\n",
1462 mark);
1463 return -EINVAL;
1464 }
1465
3bc4b7bf
OG
1466 attr->flow_tag = mark;
1467 attr->action |= MLX5_FLOW_CONTEXT_ACTION_FWD_DEST;
e3a2b7ed
AV
1468 continue;
1469 }
1470
1471 return -EINVAL;
1472 }
1473
bdd66ac0
OG
1474 if (!actions_match_supported(priv, exts, parse_attr, flow))
1475 return -EOPNOTSUPP;
1476
e3a2b7ed
AV
1477 return 0;
1478}
1479
76f7444d
OG
1480static inline int cmp_encap_info(struct ip_tunnel_key *a,
1481 struct ip_tunnel_key *b)
a54e20b4
HHZ
1482{
1483 return memcmp(a, b, sizeof(*a));
1484}
1485
76f7444d 1486static inline int hash_encap_info(struct ip_tunnel_key *key)
a54e20b4 1487{
76f7444d 1488 return jhash(key, sizeof(*key), 0);
a54e20b4
HHZ
1489}
1490
1491static int mlx5e_route_lookup_ipv4(struct mlx5e_priv *priv,
1492 struct net_device *mirred_dev,
1493 struct net_device **out_dev,
1494 struct flowi4 *fl4,
1495 struct neighbour **out_n,
a54e20b4
HHZ
1496 int *out_ttl)
1497{
3e621b19 1498 struct mlx5_eswitch *esw = priv->mdev->priv.eswitch;
a54e20b4
HHZ
1499 struct rtable *rt;
1500 struct neighbour *n = NULL;
a54e20b4
HHZ
1501
1502#if IS_ENABLED(CONFIG_INET)
abeffce9
AB
1503 int ret;
1504
a54e20b4 1505 rt = ip_route_output_key(dev_net(mirred_dev), fl4);
abeffce9
AB
1506 ret = PTR_ERR_OR_ZERO(rt);
1507 if (ret)
1508 return ret;
a54e20b4
HHZ
1509#else
1510 return -EOPNOTSUPP;
1511#endif
3e621b19
HHZ
1512 /* if the egress device isn't on the same HW e-switch, we use the uplink */
1513 if (!switchdev_port_same_parent_id(priv->netdev, rt->dst.dev))
1514 *out_dev = mlx5_eswitch_get_uplink_netdev(esw);
1515 else
1516 *out_dev = rt->dst.dev;
a54e20b4 1517
75c33da8 1518 *out_ttl = ip4_dst_hoplimit(&rt->dst);
a54e20b4
HHZ
1519 n = dst_neigh_lookup(&rt->dst, &fl4->daddr);
1520 ip_rt_put(rt);
1521 if (!n)
1522 return -ENOMEM;
1523
1524 *out_n = n;
a54e20b4
HHZ
1525 return 0;
1526}
1527
ce99f6b9
OG
1528static int mlx5e_route_lookup_ipv6(struct mlx5e_priv *priv,
1529 struct net_device *mirred_dev,
1530 struct net_device **out_dev,
1531 struct flowi6 *fl6,
1532 struct neighbour **out_n,
1533 int *out_ttl)
1534{
1535 struct neighbour *n = NULL;
1536 struct dst_entry *dst;
1537
1538#if IS_ENABLED(CONFIG_INET) && IS_ENABLED(CONFIG_IPV6)
1539 struct mlx5_eswitch *esw = priv->mdev->priv.eswitch;
1540 int ret;
1541
08820528
PB
1542 ret = ipv6_stub->ipv6_dst_lookup(dev_net(mirred_dev), NULL, &dst,
1543 fl6);
1544 if (ret < 0)
ce99f6b9 1545 return ret;
ce99f6b9
OG
1546
1547 *out_ttl = ip6_dst_hoplimit(dst);
1548
1549 /* if the egress device isn't on the same HW e-switch, we use the uplink */
1550 if (!switchdev_port_same_parent_id(priv->netdev, dst->dev))
1551 *out_dev = mlx5_eswitch_get_uplink_netdev(esw);
1552 else
1553 *out_dev = dst->dev;
1554#else
1555 return -EOPNOTSUPP;
1556#endif
1557
1558 n = dst_neigh_lookup(dst, &fl6->daddr);
1559 dst_release(dst);
1560 if (!n)
1561 return -ENOMEM;
1562
1563 *out_n = n;
1564 return 0;
1565}
1566
32f3671f
OG
1567static void gen_vxlan_header_ipv4(struct net_device *out_dev,
1568 char buf[], int encap_size,
1569 unsigned char h_dest[ETH_ALEN],
1570 int ttl,
1571 __be32 daddr,
1572 __be32 saddr,
1573 __be16 udp_dst_port,
1574 __be32 vx_vni)
a54e20b4 1575{
a54e20b4
HHZ
1576 struct ethhdr *eth = (struct ethhdr *)buf;
1577 struct iphdr *ip = (struct iphdr *)((char *)eth + sizeof(struct ethhdr));
1578 struct udphdr *udp = (struct udphdr *)((char *)ip + sizeof(struct iphdr));
1579 struct vxlanhdr *vxh = (struct vxlanhdr *)((char *)udp + sizeof(struct udphdr));
1580
1581 memset(buf, 0, encap_size);
1582
1583 ether_addr_copy(eth->h_dest, h_dest);
1584 ether_addr_copy(eth->h_source, out_dev->dev_addr);
1585 eth->h_proto = htons(ETH_P_IP);
1586
1587 ip->daddr = daddr;
1588 ip->saddr = saddr;
1589
1590 ip->ttl = ttl;
1591 ip->protocol = IPPROTO_UDP;
1592 ip->version = 0x4;
1593 ip->ihl = 0x5;
1594
1595 udp->dest = udp_dst_port;
1596 vxh->vx_flags = VXLAN_HF_VNI;
1597 vxh->vx_vni = vxlan_vni_field(vx_vni);
a54e20b4
HHZ
1598}
1599
225aabaf
OG
1600static void gen_vxlan_header_ipv6(struct net_device *out_dev,
1601 char buf[], int encap_size,
1602 unsigned char h_dest[ETH_ALEN],
1603 int ttl,
1604 struct in6_addr *daddr,
1605 struct in6_addr *saddr,
1606 __be16 udp_dst_port,
1607 __be32 vx_vni)
ce99f6b9 1608{
ce99f6b9
OG
1609 struct ethhdr *eth = (struct ethhdr *)buf;
1610 struct ipv6hdr *ip6h = (struct ipv6hdr *)((char *)eth + sizeof(struct ethhdr));
1611 struct udphdr *udp = (struct udphdr *)((char *)ip6h + sizeof(struct ipv6hdr));
1612 struct vxlanhdr *vxh = (struct vxlanhdr *)((char *)udp + sizeof(struct udphdr));
1613
1614 memset(buf, 0, encap_size);
1615
1616 ether_addr_copy(eth->h_dest, h_dest);
1617 ether_addr_copy(eth->h_source, out_dev->dev_addr);
1618 eth->h_proto = htons(ETH_P_IPV6);
1619
1620 ip6_flow_hdr(ip6h, 0, 0);
1621 /* the HW fills up ipv6 payload len */
1622 ip6h->nexthdr = IPPROTO_UDP;
1623 ip6h->hop_limit = ttl;
1624 ip6h->daddr = *daddr;
1625 ip6h->saddr = *saddr;
1626
1627 udp->dest = udp_dst_port;
1628 vxh->vx_flags = VXLAN_HF_VNI;
1629 vxh->vx_vni = vxlan_vni_field(vx_vni);
ce99f6b9
OG
1630}
1631
a54e20b4
HHZ
1632static int mlx5e_create_encap_header_ipv4(struct mlx5e_priv *priv,
1633 struct net_device *mirred_dev,
1a8552bd 1634 struct mlx5e_encap_entry *e)
a54e20b4
HHZ
1635{
1636 int max_encap_size = MLX5_CAP_ESW(priv->mdev, max_encap_header_size);
32f3671f 1637 int ipv4_encap_size = ETH_HLEN + sizeof(struct iphdr) + VXLAN_HLEN;
76f7444d 1638 struct ip_tunnel_key *tun_key = &e->tun_info.key;
1a8552bd 1639 struct net_device *out_dev;
a42485eb 1640 struct neighbour *n = NULL;
a54e20b4 1641 struct flowi4 fl4 = {};
a54e20b4 1642 char *encap_header;
32f3671f 1643 int ttl, err;
033354d5 1644 u8 nud_state;
32f3671f
OG
1645
1646 if (max_encap_size < ipv4_encap_size) {
1647 mlx5_core_warn(priv->mdev, "encap size %d too big, max supported is %d\n",
1648 ipv4_encap_size, max_encap_size);
1649 return -EOPNOTSUPP;
1650 }
a54e20b4 1651
32f3671f 1652 encap_header = kzalloc(ipv4_encap_size, GFP_KERNEL);
a54e20b4
HHZ
1653 if (!encap_header)
1654 return -ENOMEM;
1655
1656 switch (e->tunnel_type) {
1657 case MLX5_HEADER_TYPE_VXLAN:
1658 fl4.flowi4_proto = IPPROTO_UDP;
76f7444d 1659 fl4.fl4_dport = tun_key->tp_dst;
a54e20b4
HHZ
1660 break;
1661 default:
1662 err = -EOPNOTSUPP;
ace74321 1663 goto free_encap;
a54e20b4 1664 }
9a941117 1665 fl4.flowi4_tos = tun_key->tos;
76f7444d 1666 fl4.daddr = tun_key->u.ipv4.dst;
9a941117 1667 fl4.saddr = tun_key->u.ipv4.src;
a54e20b4 1668
1a8552bd 1669 err = mlx5e_route_lookup_ipv4(priv, mirred_dev, &out_dev,
9a941117 1670 &fl4, &n, &ttl);
a54e20b4 1671 if (err)
ace74321 1672 goto free_encap;
a54e20b4 1673
232c0013
HHZ
1674 /* used by mlx5e_detach_encap to lookup a neigh hash table
1675 * entry in the neigh hash table when a user deletes a rule
1676 */
1677 e->m_neigh.dev = n->dev;
f6dfb4c3 1678 e->m_neigh.family = n->ops->family;
232c0013
HHZ
1679 memcpy(&e->m_neigh.dst_ip, n->primary_key, n->tbl->key_len);
1680 e->out_dev = out_dev;
1681
1682 /* It's importent to add the neigh to the hash table before checking
1683 * the neigh validity state. So if we'll get a notification, in case the
1684 * neigh changes it's validity state, we would find the relevant neigh
1685 * in the hash.
1686 */
1687 err = mlx5e_rep_encap_entry_attach(netdev_priv(out_dev), e);
1688 if (err)
ace74321 1689 goto free_encap;
232c0013 1690
033354d5
HHZ
1691 read_lock_bh(&n->lock);
1692 nud_state = n->nud_state;
1693 ether_addr_copy(e->h_dest, n->ha);
1694 read_unlock_bh(&n->lock);
1695
a54e20b4
HHZ
1696 switch (e->tunnel_type) {
1697 case MLX5_HEADER_TYPE_VXLAN:
1a8552bd 1698 gen_vxlan_header_ipv4(out_dev, encap_header,
32f3671f
OG
1699 ipv4_encap_size, e->h_dest, ttl,
1700 fl4.daddr,
1701 fl4.saddr, tun_key->tp_dst,
1702 tunnel_id_to_key32(tun_key->tun_id));
a54e20b4
HHZ
1703 break;
1704 default:
1705 err = -EOPNOTSUPP;
232c0013
HHZ
1706 goto destroy_neigh_entry;
1707 }
1708 e->encap_size = ipv4_encap_size;
1709 e->encap_header = encap_header;
1710
1711 if (!(nud_state & NUD_VALID)) {
1712 neigh_event_send(n, NULL);
27902f08
WY
1713 err = -EAGAIN;
1714 goto out;
a54e20b4
HHZ
1715 }
1716
1717 err = mlx5_encap_alloc(priv->mdev, e->tunnel_type,
32f3671f 1718 ipv4_encap_size, encap_header, &e->encap_id);
232c0013
HHZ
1719 if (err)
1720 goto destroy_neigh_entry;
1721
1722 e->flags |= MLX5_ENCAP_ENTRY_VALID;
f6dfb4c3 1723 mlx5e_rep_queue_neigh_stats_work(netdev_priv(out_dev));
232c0013
HHZ
1724 neigh_release(n);
1725 return err;
1726
1727destroy_neigh_entry:
1728 mlx5e_rep_encap_entry_detach(netdev_priv(e->out_dev), e);
ace74321 1729free_encap:
a54e20b4 1730 kfree(encap_header);
ace74321 1731out:
232c0013
HHZ
1732 if (n)
1733 neigh_release(n);
a54e20b4
HHZ
1734 return err;
1735}
1736
ce99f6b9
OG
1737static int mlx5e_create_encap_header_ipv6(struct mlx5e_priv *priv,
1738 struct net_device *mirred_dev,
1a8552bd 1739 struct mlx5e_encap_entry *e)
ce99f6b9
OG
1740{
1741 int max_encap_size = MLX5_CAP_ESW(priv->mdev, max_encap_header_size);
225aabaf 1742 int ipv6_encap_size = ETH_HLEN + sizeof(struct ipv6hdr) + VXLAN_HLEN;
ce99f6b9 1743 struct ip_tunnel_key *tun_key = &e->tun_info.key;
1a8552bd 1744 struct net_device *out_dev;
ce99f6b9
OG
1745 struct neighbour *n = NULL;
1746 struct flowi6 fl6 = {};
1747 char *encap_header;
225aabaf 1748 int err, ttl = 0;
033354d5 1749 u8 nud_state;
ce99f6b9 1750
225aabaf
OG
1751 if (max_encap_size < ipv6_encap_size) {
1752 mlx5_core_warn(priv->mdev, "encap size %d too big, max supported is %d\n",
1753 ipv6_encap_size, max_encap_size);
1754 return -EOPNOTSUPP;
1755 }
ce99f6b9 1756
225aabaf 1757 encap_header = kzalloc(ipv6_encap_size, GFP_KERNEL);
ce99f6b9
OG
1758 if (!encap_header)
1759 return -ENOMEM;
1760
1761 switch (e->tunnel_type) {
1762 case MLX5_HEADER_TYPE_VXLAN:
1763 fl6.flowi6_proto = IPPROTO_UDP;
1764 fl6.fl6_dport = tun_key->tp_dst;
1765 break;
1766 default:
1767 err = -EOPNOTSUPP;
ace74321 1768 goto free_encap;
ce99f6b9
OG
1769 }
1770
1771 fl6.flowlabel = ip6_make_flowinfo(RT_TOS(tun_key->tos), tun_key->label);
1772 fl6.daddr = tun_key->u.ipv6.dst;
1773 fl6.saddr = tun_key->u.ipv6.src;
1774
1a8552bd 1775 err = mlx5e_route_lookup_ipv6(priv, mirred_dev, &out_dev,
ce99f6b9
OG
1776 &fl6, &n, &ttl);
1777 if (err)
ace74321 1778 goto free_encap;
ce99f6b9 1779
232c0013
HHZ
1780 /* used by mlx5e_detach_encap to lookup a neigh hash table
1781 * entry in the neigh hash table when a user deletes a rule
1782 */
1783 e->m_neigh.dev = n->dev;
f6dfb4c3 1784 e->m_neigh.family = n->ops->family;
232c0013
HHZ
1785 memcpy(&e->m_neigh.dst_ip, n->primary_key, n->tbl->key_len);
1786 e->out_dev = out_dev;
1787
1788 /* It's importent to add the neigh to the hash table before checking
1789 * the neigh validity state. So if we'll get a notification, in case the
1790 * neigh changes it's validity state, we would find the relevant neigh
1791 * in the hash.
1792 */
1793 err = mlx5e_rep_encap_entry_attach(netdev_priv(out_dev), e);
1794 if (err)
ace74321 1795 goto free_encap;
232c0013 1796
033354d5
HHZ
1797 read_lock_bh(&n->lock);
1798 nud_state = n->nud_state;
1799 ether_addr_copy(e->h_dest, n->ha);
1800 read_unlock_bh(&n->lock);
1801
ce99f6b9
OG
1802 switch (e->tunnel_type) {
1803 case MLX5_HEADER_TYPE_VXLAN:
1a8552bd 1804 gen_vxlan_header_ipv6(out_dev, encap_header,
225aabaf
OG
1805 ipv6_encap_size, e->h_dest, ttl,
1806 &fl6.daddr,
1807 &fl6.saddr, tun_key->tp_dst,
1808 tunnel_id_to_key32(tun_key->tun_id));
ce99f6b9
OG
1809 break;
1810 default:
1811 err = -EOPNOTSUPP;
232c0013
HHZ
1812 goto destroy_neigh_entry;
1813 }
1814
1815 e->encap_size = ipv6_encap_size;
1816 e->encap_header = encap_header;
1817
1818 if (!(nud_state & NUD_VALID)) {
1819 neigh_event_send(n, NULL);
27902f08
WY
1820 err = -EAGAIN;
1821 goto out;
ce99f6b9
OG
1822 }
1823
1824 err = mlx5_encap_alloc(priv->mdev, e->tunnel_type,
225aabaf 1825 ipv6_encap_size, encap_header, &e->encap_id);
232c0013
HHZ
1826 if (err)
1827 goto destroy_neigh_entry;
1828
1829 e->flags |= MLX5_ENCAP_ENTRY_VALID;
f6dfb4c3 1830 mlx5e_rep_queue_neigh_stats_work(netdev_priv(out_dev));
232c0013
HHZ
1831 neigh_release(n);
1832 return err;
1833
1834destroy_neigh_entry:
1835 mlx5e_rep_encap_entry_detach(netdev_priv(e->out_dev), e);
ace74321 1836free_encap:
ce99f6b9 1837 kfree(encap_header);
ace74321 1838out:
232c0013
HHZ
1839 if (n)
1840 neigh_release(n);
ce99f6b9
OG
1841 return err;
1842}
1843
a54e20b4
HHZ
1844static int mlx5e_attach_encap(struct mlx5e_priv *priv,
1845 struct ip_tunnel_info *tun_info,
1846 struct net_device *mirred_dev,
45247bf2
OG
1847 struct net_device **encap_dev,
1848 struct mlx5e_tc_flow *flow)
a54e20b4
HHZ
1849{
1850 struct mlx5_eswitch *esw = priv->mdev->priv.eswitch;
1ad9a00a 1851 struct net_device *up_dev = mlx5_eswitch_get_uplink_netdev(esw);
a54e20b4 1852 unsigned short family = ip_tunnel_info_af(tun_info);
45247bf2
OG
1853 struct mlx5e_priv *up_priv = netdev_priv(up_dev);
1854 struct mlx5_esw_flow_attr *attr = flow->esw_attr;
a54e20b4 1855 struct ip_tunnel_key *key = &tun_info->key;
c1ae1152 1856 struct mlx5e_encap_entry *e;
45247bf2 1857 int tunnel_type, err = 0;
a54e20b4
HHZ
1858 uintptr_t hash_key;
1859 bool found = false;
a54e20b4 1860
2fcd82e9 1861 /* udp dst port must be set */
a54e20b4 1862 if (!memchr_inv(&key->tp_dst, 0, sizeof(key->tp_dst)))
2fcd82e9 1863 goto vxlan_encap_offload_err;
a54e20b4 1864
cd377663 1865 /* setting udp src port isn't supported */
2fcd82e9
OG
1866 if (memchr_inv(&key->tp_src, 0, sizeof(key->tp_src))) {
1867vxlan_encap_offload_err:
1868 netdev_warn(priv->netdev,
1869 "must set udp dst port and not set udp src port\n");
cd377663 1870 return -EOPNOTSUPP;
2fcd82e9 1871 }
cd377663 1872
1ad9a00a 1873 if (mlx5e_vxlan_lookup_port(up_priv, be16_to_cpu(key->tp_dst)) &&
a54e20b4 1874 MLX5_CAP_ESW(priv->mdev, vxlan_encap_decap)) {
a54e20b4
HHZ
1875 tunnel_type = MLX5_HEADER_TYPE_VXLAN;
1876 } else {
2fcd82e9
OG
1877 netdev_warn(priv->netdev,
1878 "%d isn't an offloaded vxlan udp dport\n", be16_to_cpu(key->tp_dst));
a54e20b4
HHZ
1879 return -EOPNOTSUPP;
1880 }
1881
76f7444d 1882 hash_key = hash_encap_info(key);
a54e20b4
HHZ
1883
1884 hash_for_each_possible_rcu(esw->offloads.encap_tbl, e,
1885 encap_hlist, hash_key) {
76f7444d 1886 if (!cmp_encap_info(&e->tun_info.key, key)) {
a54e20b4
HHZ
1887 found = true;
1888 break;
1889 }
1890 }
1891
b2812089 1892 /* must verify if encap is valid or not */
45247bf2
OG
1893 if (found)
1894 goto attach_flow;
a54e20b4
HHZ
1895
1896 e = kzalloc(sizeof(*e), GFP_KERNEL);
1897 if (!e)
1898 return -ENOMEM;
1899
76f7444d 1900 e->tun_info = *tun_info;
a54e20b4
HHZ
1901 e->tunnel_type = tunnel_type;
1902 INIT_LIST_HEAD(&e->flows);
1903
ce99f6b9 1904 if (family == AF_INET)
1a8552bd 1905 err = mlx5e_create_encap_header_ipv4(priv, mirred_dev, e);
ce99f6b9 1906 else if (family == AF_INET6)
1a8552bd 1907 err = mlx5e_create_encap_header_ipv6(priv, mirred_dev, e);
ce99f6b9 1908
232c0013 1909 if (err && err != -EAGAIN)
a54e20b4
HHZ
1910 goto out_err;
1911
a54e20b4
HHZ
1912 hash_add_rcu(esw->offloads.encap_tbl, &e->encap_hlist, hash_key);
1913
45247bf2
OG
1914attach_flow:
1915 list_add(&flow->encap, &e->flows);
1916 *encap_dev = e->out_dev;
232c0013
HHZ
1917 if (e->flags & MLX5_ENCAP_ENTRY_VALID)
1918 attr->encap_id = e->encap_id;
b2812089
VB
1919 else
1920 err = -EAGAIN;
45247bf2 1921
232c0013 1922 return err;
a54e20b4
HHZ
1923
1924out_err:
1925 kfree(e);
1926 return err;
1927}
1928
03a9d11e 1929static int parse_tc_fdb_actions(struct mlx5e_priv *priv, struct tcf_exts *exts,
d7e75a32 1930 struct mlx5e_tc_flow_parse_attr *parse_attr,
a54e20b4 1931 struct mlx5e_tc_flow *flow)
03a9d11e 1932{
ecf5bb79 1933 struct mlx5_esw_flow_attr *attr = flow->esw_attr;
1d447a39 1934 struct mlx5e_rep_priv *rpriv = priv->ppriv;
a54e20b4 1935 struct ip_tunnel_info *info = NULL;
03a9d11e 1936 const struct tc_action *a;
22dc13c8 1937 LIST_HEAD(actions);
a54e20b4 1938 bool encap = false;
232c0013 1939 int err = 0;
03a9d11e 1940
3bcc0cec 1941 if (!tcf_exts_has_actions(exts))
03a9d11e
OG
1942 return -EINVAL;
1943
776b12b6 1944 memset(attr, 0, sizeof(*attr));
1d447a39 1945 attr->in_rep = rpriv->rep;
03a9d11e 1946
22dc13c8
WC
1947 tcf_exts_to_list(exts, &actions);
1948 list_for_each_entry(a, &actions, list) {
03a9d11e 1949 if (is_tcf_gact_shot(a)) {
8b32580d
OG
1950 attr->action |= MLX5_FLOW_CONTEXT_ACTION_DROP |
1951 MLX5_FLOW_CONTEXT_ACTION_COUNT;
03a9d11e
OG
1952 continue;
1953 }
1954
d7e75a32
OG
1955 if (is_tcf_pedit(a)) {
1956 err = parse_tc_pedit_action(priv, a, MLX5_FLOW_NAMESPACE_FDB,
1957 parse_attr);
1958 if (err)
1959 return err;
1960
1961 attr->action |= MLX5_FLOW_CONTEXT_ACTION_MOD_HDR;
1962 continue;
1963 }
1964
26c02749
OG
1965 if (is_tcf_csum(a)) {
1966 if (csum_offload_supported(priv, attr->action,
1967 tcf_csum_update_flags(a)))
1968 continue;
1969
1970 return -EOPNOTSUPP;
1971 }
1972
5724b8b5 1973 if (is_tcf_mirred_egress_redirect(a)) {
03a9d11e 1974 int ifindex = tcf_mirred_ifindex(a);
3c37745e 1975 struct net_device *out_dev;
03a9d11e 1976 struct mlx5e_priv *out_priv;
03a9d11e
OG
1977
1978 out_dev = __dev_get_by_index(dev_net(priv->netdev), ifindex);
1979
a54e20b4
HHZ
1980 if (switchdev_port_same_parent_id(priv->netdev,
1981 out_dev)) {
1982 attr->action |= MLX5_FLOW_CONTEXT_ACTION_FWD_DEST |
1983 MLX5_FLOW_CONTEXT_ACTION_COUNT;
1984 out_priv = netdev_priv(out_dev);
1d447a39
SM
1985 rpriv = out_priv->ppriv;
1986 attr->out_rep = rpriv->rep;
a54e20b4 1987 } else if (encap) {
3c37745e
OG
1988 parse_attr->mirred_ifindex = ifindex;
1989 parse_attr->tun_info = *info;
1990 attr->parse_attr = parse_attr;
a54e20b4
HHZ
1991 attr->action |= MLX5_FLOW_CONTEXT_ACTION_ENCAP |
1992 MLX5_FLOW_CONTEXT_ACTION_FWD_DEST |
1993 MLX5_FLOW_CONTEXT_ACTION_COUNT;
3c37745e 1994 /* attr->out_rep is resolved when we handle encap */
a54e20b4 1995 } else {
03a9d11e
OG
1996 pr_err("devices %s %s not on same switch HW, can't offload forwarding\n",
1997 priv->netdev->name, out_dev->name);
1998 return -EINVAL;
1999 }
a54e20b4
HHZ
2000 continue;
2001 }
03a9d11e 2002
a54e20b4
HHZ
2003 if (is_tcf_tunnel_set(a)) {
2004 info = tcf_tunnel_info(a);
2005 if (info)
2006 encap = true;
2007 else
2008 return -EOPNOTSUPP;
03a9d11e
OG
2009 continue;
2010 }
2011
8b32580d 2012 if (is_tcf_vlan(a)) {
09c91ddf 2013 if (tcf_vlan_action(a) == TCA_VLAN_ACT_POP) {
8b32580d 2014 attr->action |= MLX5_FLOW_CONTEXT_ACTION_VLAN_POP;
09c91ddf 2015 } else if (tcf_vlan_action(a) == TCA_VLAN_ACT_PUSH) {
8b32580d
OG
2016 if (tcf_vlan_push_proto(a) != htons(ETH_P_8021Q))
2017 return -EOPNOTSUPP;
2018
2019 attr->action |= MLX5_FLOW_CONTEXT_ACTION_VLAN_PUSH;
2020 attr->vlan = tcf_vlan_push_vid(a);
09c91ddf
OG
2021 } else { /* action is TCA_VLAN_ACT_MODIFY */
2022 return -EOPNOTSUPP;
8b32580d
OG
2023 }
2024 continue;
2025 }
2026
bbd00f7e
HHZ
2027 if (is_tcf_tunnel_release(a)) {
2028 attr->action |= MLX5_FLOW_CONTEXT_ACTION_DECAP;
2029 continue;
2030 }
2031
03a9d11e
OG
2032 return -EINVAL;
2033 }
bdd66ac0
OG
2034
2035 if (!actions_match_supported(priv, exts, parse_attr, flow))
2036 return -EOPNOTSUPP;
2037
232c0013 2038 return err;
03a9d11e
OG
2039}
2040
5fd9fc4e 2041int mlx5e_configure_flower(struct mlx5e_priv *priv,
e3a2b7ed
AV
2042 struct tc_cls_flower_offload *f)
2043{
3bc4b7bf 2044 struct mlx5_eswitch *esw = priv->mdev->priv.eswitch;
17091853 2045 struct mlx5e_tc_flow_parse_attr *parse_attr;
acff797c 2046 struct mlx5e_tc_table *tc = &priv->fs.tc;
3bc4b7bf
OG
2047 struct mlx5e_tc_flow *flow;
2048 int attr_size, err = 0;
65ba8fb7 2049 u8 flow_flags = 0;
e3a2b7ed 2050
65ba8fb7
OG
2051 if (esw && esw->mode == SRIOV_OFFLOADS) {
2052 flow_flags = MLX5E_TC_FLOW_ESWITCH;
2053 attr_size = sizeof(struct mlx5_esw_flow_attr);
3bc4b7bf
OG
2054 } else {
2055 flow_flags = MLX5E_TC_FLOW_NIC;
2056 attr_size = sizeof(struct mlx5_nic_flow_attr);
65ba8fb7 2057 }
e3a2b7ed 2058
65ba8fb7 2059 flow = kzalloc(sizeof(*flow) + attr_size, GFP_KERNEL);
1b9a07ee 2060 parse_attr = kvzalloc(sizeof(*parse_attr), GFP_KERNEL);
17091853 2061 if (!parse_attr || !flow) {
e3a2b7ed
AV
2062 err = -ENOMEM;
2063 goto err_free;
2064 }
2065
2066 flow->cookie = f->cookie;
65ba8fb7 2067 flow->flags = flow_flags;
e3a2b7ed 2068
17091853 2069 err = parse_cls_flower(priv, flow, &parse_attr->spec, f);
e3a2b7ed
AV
2070 if (err < 0)
2071 goto err_free;
2072
65ba8fb7 2073 if (flow->flags & MLX5E_TC_FLOW_ESWITCH) {
d7e75a32 2074 err = parse_tc_fdb_actions(priv, f->exts, parse_attr, flow);
adb4c123 2075 if (err < 0)
3c37745e 2076 goto err_free;
aa0cbbae 2077 flow->rule = mlx5e_tc_add_fdb_flow(priv, parse_attr, flow);
adb4c123 2078 } else {
aa0cbbae 2079 err = parse_tc_nic_actions(priv, f->exts, parse_attr, flow);
adb4c123
OG
2080 if (err < 0)
2081 goto err_free;
aa0cbbae 2082 flow->rule = mlx5e_tc_add_nic_flow(priv, parse_attr, flow);
adb4c123 2083 }
e3a2b7ed 2084
e3a2b7ed
AV
2085 if (IS_ERR(flow->rule)) {
2086 err = PTR_ERR(flow->rule);
3c37745e
OG
2087 if (err != -EAGAIN)
2088 goto err_free;
e3a2b7ed
AV
2089 }
2090
3c37745e
OG
2091 if (err != -EAGAIN)
2092 flow->flags |= MLX5E_TC_FLOW_OFFLOADED;
2093
5c40348c
OG
2094 err = rhashtable_insert_fast(&tc->ht, &flow->node,
2095 tc->ht_params);
2096 if (err)
2097 goto err_del_rule;
2098
232c0013
HHZ
2099 if (flow->flags & MLX5E_TC_FLOW_ESWITCH &&
2100 !(flow->esw_attr->action & MLX5_FLOW_CONTEXT_ACTION_ENCAP))
2101 kvfree(parse_attr);
2102 return err;
e3a2b7ed 2103
5c40348c 2104err_del_rule:
5e86397a 2105 mlx5e_tc_del_flow(priv, flow);
e3a2b7ed
AV
2106
2107err_free:
17091853 2108 kvfree(parse_attr);
232c0013 2109 kfree(flow);
e3a2b7ed
AV
2110 return err;
2111}
2112
2113int mlx5e_delete_flower(struct mlx5e_priv *priv,
2114 struct tc_cls_flower_offload *f)
2115{
2116 struct mlx5e_tc_flow *flow;
acff797c 2117 struct mlx5e_tc_table *tc = &priv->fs.tc;
e3a2b7ed
AV
2118
2119 flow = rhashtable_lookup_fast(&tc->ht, &f->cookie,
2120 tc->ht_params);
2121 if (!flow)
2122 return -EINVAL;
2123
2124 rhashtable_remove_fast(&tc->ht, &flow->node, tc->ht_params);
2125
961e8979 2126 mlx5e_tc_del_flow(priv, flow);
e3a2b7ed
AV
2127
2128 kfree(flow);
2129
2130 return 0;
2131}
2132
aad7e08d
AV
2133int mlx5e_stats_flower(struct mlx5e_priv *priv,
2134 struct tc_cls_flower_offload *f)
2135{
2136 struct mlx5e_tc_table *tc = &priv->fs.tc;
2137 struct mlx5e_tc_flow *flow;
aad7e08d
AV
2138 struct mlx5_fc *counter;
2139 u64 bytes;
2140 u64 packets;
2141 u64 lastuse;
2142
2143 flow = rhashtable_lookup_fast(&tc->ht, &f->cookie,
2144 tc->ht_params);
2145 if (!flow)
2146 return -EINVAL;
2147
0b67a38f
HHZ
2148 if (!(flow->flags & MLX5E_TC_FLOW_OFFLOADED))
2149 return 0;
2150
aad7e08d
AV
2151 counter = mlx5_flow_rule_counter(flow->rule);
2152 if (!counter)
2153 return 0;
2154
2155 mlx5_fc_query_cached(counter, &bytes, &packets, &lastuse);
2156
d897a638 2157 tcf_exts_stats_update(f->exts, bytes, packets, lastuse);
fed06ee8 2158
aad7e08d
AV
2159 return 0;
2160}
2161
e8f887ac
AV
2162static const struct rhashtable_params mlx5e_tc_flow_ht_params = {
2163 .head_offset = offsetof(struct mlx5e_tc_flow, node),
2164 .key_offset = offsetof(struct mlx5e_tc_flow, cookie),
2165 .key_len = sizeof(((struct mlx5e_tc_flow *)0)->cookie),
2166 .automatic_shrinking = true,
2167};
2168
2169int mlx5e_tc_init(struct mlx5e_priv *priv)
2170{
acff797c 2171 struct mlx5e_tc_table *tc = &priv->fs.tc;
e8f887ac 2172
11c9c548
OG
2173 hash_init(tc->mod_hdr_tbl);
2174
e8f887ac
AV
2175 tc->ht_params = mlx5e_tc_flow_ht_params;
2176 return rhashtable_init(&tc->ht, &tc->ht_params);
2177}
2178
2179static void _mlx5e_tc_del_flow(void *ptr, void *arg)
2180{
2181 struct mlx5e_tc_flow *flow = ptr;
2182 struct mlx5e_priv *priv = arg;
2183
961e8979 2184 mlx5e_tc_del_flow(priv, flow);
e8f887ac
AV
2185 kfree(flow);
2186}
2187
2188void mlx5e_tc_cleanup(struct mlx5e_priv *priv)
2189{
acff797c 2190 struct mlx5e_tc_table *tc = &priv->fs.tc;
e8f887ac
AV
2191
2192 rhashtable_free_and_destroy(&tc->ht, _mlx5e_tc_del_flow, priv);
2193
acff797c
MG
2194 if (!IS_ERR_OR_NULL(tc->t)) {
2195 mlx5_destroy_flow_table(tc->t);
2196 tc->t = NULL;
e8f887ac
AV
2197 }
2198}