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