net/mlx5e: Refactor tc del flow to accept mlx5e_tc_flow instance
[linux-2.6-block.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
AV
33#include <net/flow_dissector.h>
34#include <net/pkt_cls.h>
35#include <net/tc_act/tc_gact.h>
12185a9f 36#include <net/tc_act/tc_skbedit.h>
e8f887ac
AV
37#include <linux/mlx5/fs.h>
38#include <linux/mlx5/device.h>
39#include <linux/rhashtable.h>
03a9d11e
OG
40#include <net/switchdev.h>
41#include <net/tc_act/tc_mirred.h>
776b12b6 42#include <net/tc_act/tc_vlan.h>
bbd00f7e 43#include <net/tc_act/tc_tunnel_key.h>
a54e20b4 44#include <net/vxlan.h>
e8f887ac
AV
45#include "en.h"
46#include "en_tc.h"
03a9d11e 47#include "eswitch.h"
bbd00f7e 48#include "vxlan.h"
e8f887ac
AV
49
50struct mlx5e_tc_flow {
51 struct rhash_head node;
52 u64 cookie;
74491de9 53 struct mlx5_flow_handle *rule;
a54e20b4 54 struct list_head encap; /* flows sharing the same encap */
776b12b6 55 struct mlx5_esw_flow_attr *attr;
e8f887ac
AV
56};
57
a54e20b4
HHZ
58enum {
59 MLX5_HEADER_TYPE_VXLAN = 0x0,
60 MLX5_HEADER_TYPE_NVGRE = 0x1,
61};
62
acff797c
MG
63#define MLX5E_TC_TABLE_NUM_ENTRIES 1024
64#define MLX5E_TC_TABLE_NUM_GROUPS 4
e8f887ac 65
74491de9
MB
66static struct mlx5_flow_handle *
67mlx5e_tc_add_nic_flow(struct mlx5e_priv *priv,
68 struct mlx5_flow_spec *spec,
69 u32 action, u32 flow_tag)
e8f887ac 70{
aad7e08d
AV
71 struct mlx5_core_dev *dev = priv->mdev;
72 struct mlx5_flow_destination dest = { 0 };
66958ed9
HHZ
73 struct mlx5_flow_act flow_act = {
74 .action = action,
75 .flow_tag = flow_tag,
76 .encap_id = 0,
77 };
aad7e08d 78 struct mlx5_fc *counter = NULL;
74491de9 79 struct mlx5_flow_handle *rule;
e8f887ac
AV
80 bool table_created = false;
81
aad7e08d
AV
82 if (action & MLX5_FLOW_CONTEXT_ACTION_FWD_DEST) {
83 dest.type = MLX5_FLOW_DESTINATION_TYPE_FLOW_TABLE;
84 dest.ft = priv->fs.vlan.ft.t;
55130287 85 } else if (action & MLX5_FLOW_CONTEXT_ACTION_COUNT) {
aad7e08d
AV
86 counter = mlx5_fc_create(dev, true);
87 if (IS_ERR(counter))
88 return ERR_CAST(counter);
89
90 dest.type = MLX5_FLOW_DESTINATION_TYPE_COUNTER;
91 dest.counter = counter;
92 }
93
acff797c
MG
94 if (IS_ERR_OR_NULL(priv->fs.tc.t)) {
95 priv->fs.tc.t =
96 mlx5_create_auto_grouped_flow_table(priv->fs.ns,
97 MLX5E_TC_PRIO,
98 MLX5E_TC_TABLE_NUM_ENTRIES,
99 MLX5E_TC_TABLE_NUM_GROUPS,
c9f1b073 100 0, 0);
acff797c 101 if (IS_ERR(priv->fs.tc.t)) {
e8f887ac
AV
102 netdev_err(priv->netdev,
103 "Failed to create tc offload table\n");
aad7e08d
AV
104 rule = ERR_CAST(priv->fs.tc.t);
105 goto err_create_ft;
e8f887ac
AV
106 }
107
108 table_created = true;
109 }
110
c5bb1730 111 spec->match_criteria_enable = MLX5_MATCH_OUTER_HEADERS;
66958ed9 112 rule = mlx5_add_flow_rules(priv->fs.tc.t, spec, &flow_act, &dest, 1);
aad7e08d
AV
113
114 if (IS_ERR(rule))
115 goto err_add_rule;
116
117 return rule;
e8f887ac 118
aad7e08d
AV
119err_add_rule:
120 if (table_created) {
acff797c
MG
121 mlx5_destroy_flow_table(priv->fs.tc.t);
122 priv->fs.tc.t = NULL;
e8f887ac 123 }
aad7e08d
AV
124err_create_ft:
125 mlx5_fc_destroy(dev, counter);
e8f887ac
AV
126
127 return rule;
128}
129
74491de9
MB
130static struct mlx5_flow_handle *
131mlx5e_tc_add_fdb_flow(struct mlx5e_priv *priv,
132 struct mlx5_flow_spec *spec,
133 struct mlx5_esw_flow_attr *attr)
adb4c123
OG
134{
135 struct mlx5_eswitch *esw = priv->mdev->priv.eswitch;
8b32580d
OG
136 int err;
137
138 err = mlx5_eswitch_add_vlan_action(esw, attr);
139 if (err)
140 return ERR_PTR(err);
adb4c123 141
776b12b6 142 return mlx5_eswitch_add_offloaded_rule(esw, spec, attr);
adb4c123
OG
143}
144
e8f887ac 145static void mlx5e_tc_del_flow(struct mlx5e_priv *priv,
961e8979 146 struct mlx5e_tc_flow *flow)
e8f887ac 147{
8b32580d 148 struct mlx5_eswitch *esw = priv->mdev->priv.eswitch;
aad7e08d
AV
149 struct mlx5_fc *counter = NULL;
150
961e8979 151 counter = mlx5_flow_rule_counter(flow->rule);
aad7e08d 152
961e8979 153 mlx5_del_flow_rules(flow->rule);
86a33ae1 154
8b32580d 155 if (esw && esw->mode == SRIOV_OFFLOADS)
961e8979 156 mlx5_eswitch_del_vlan_action(esw, flow->attr);
8b32580d 157
aad7e08d
AV
158 mlx5_fc_destroy(priv->mdev, counter);
159
5c40348c 160 if (!mlx5e_tc_num_filters(priv) && (priv->fs.tc.t)) {
acff797c
MG
161 mlx5_destroy_flow_table(priv->fs.tc.t);
162 priv->fs.tc.t = NULL;
e8f887ac
AV
163 }
164}
165
bbd00f7e
HHZ
166static void parse_vxlan_attr(struct mlx5_flow_spec *spec,
167 struct tc_cls_flower_offload *f)
168{
169 void *headers_c = MLX5_ADDR_OF(fte_match_param, spec->match_criteria,
170 outer_headers);
171 void *headers_v = MLX5_ADDR_OF(fte_match_param, spec->match_value,
172 outer_headers);
173 void *misc_c = MLX5_ADDR_OF(fte_match_param, spec->match_criteria,
174 misc_parameters);
175 void *misc_v = MLX5_ADDR_OF(fte_match_param, spec->match_value,
176 misc_parameters);
177
178 MLX5_SET_TO_ONES(fte_match_set_lyr_2_4, headers_c, ip_protocol);
179 MLX5_SET(fte_match_set_lyr_2_4, headers_v, ip_protocol, IPPROTO_UDP);
180
181 if (dissector_uses_key(f->dissector, FLOW_DISSECTOR_KEY_ENC_KEYID)) {
182 struct flow_dissector_key_keyid *key =
183 skb_flow_dissector_target(f->dissector,
184 FLOW_DISSECTOR_KEY_ENC_KEYID,
185 f->key);
186 struct flow_dissector_key_keyid *mask =
187 skb_flow_dissector_target(f->dissector,
188 FLOW_DISSECTOR_KEY_ENC_KEYID,
189 f->mask);
190 MLX5_SET(fte_match_set_misc, misc_c, vxlan_vni,
191 be32_to_cpu(mask->keyid));
192 MLX5_SET(fte_match_set_misc, misc_v, vxlan_vni,
193 be32_to_cpu(key->keyid));
194 }
195}
196
197static int parse_tunnel_attr(struct mlx5e_priv *priv,
198 struct mlx5_flow_spec *spec,
199 struct tc_cls_flower_offload *f)
200{
201 void *headers_c = MLX5_ADDR_OF(fte_match_param, spec->match_criteria,
202 outer_headers);
203 void *headers_v = MLX5_ADDR_OF(fte_match_param, spec->match_value,
204 outer_headers);
205
206 if (dissector_uses_key(f->dissector, FLOW_DISSECTOR_KEY_ENC_PORTS)) {
207 struct flow_dissector_key_ports *key =
208 skb_flow_dissector_target(f->dissector,
209 FLOW_DISSECTOR_KEY_ENC_PORTS,
210 f->key);
211 struct flow_dissector_key_ports *mask =
212 skb_flow_dissector_target(f->dissector,
213 FLOW_DISSECTOR_KEY_ENC_PORTS,
214 f->mask);
215
216 /* Full udp dst port must be given */
217 if (memchr_inv(&mask->dst, 0xff, sizeof(mask->dst)))
218 return -EOPNOTSUPP;
219
220 /* udp src port isn't supported */
221 if (memchr_inv(&mask->src, 0, sizeof(mask->src)))
222 return -EOPNOTSUPP;
223
224 if (mlx5e_vxlan_lookup_port(priv, be16_to_cpu(key->dst)) &&
225 MLX5_CAP_ESW(priv->mdev, vxlan_encap_decap))
226 parse_vxlan_attr(spec, f);
227 else
228 return -EOPNOTSUPP;
229
230 MLX5_SET(fte_match_set_lyr_2_4, headers_c,
231 udp_dport, ntohs(mask->dst));
232 MLX5_SET(fte_match_set_lyr_2_4, headers_v,
233 udp_dport, ntohs(key->dst));
234
235 } else { /* udp dst port must be given */
236 return -EOPNOTSUPP;
237 }
238
239 if (dissector_uses_key(f->dissector, FLOW_DISSECTOR_KEY_ENC_IPV4_ADDRS)) {
240 struct flow_dissector_key_ipv4_addrs *key =
241 skb_flow_dissector_target(f->dissector,
242 FLOW_DISSECTOR_KEY_ENC_IPV4_ADDRS,
243 f->key);
244 struct flow_dissector_key_ipv4_addrs *mask =
245 skb_flow_dissector_target(f->dissector,
246 FLOW_DISSECTOR_KEY_ENC_IPV4_ADDRS,
247 f->mask);
248 MLX5_SET(fte_match_set_lyr_2_4, headers_c,
249 src_ipv4_src_ipv6.ipv4_layout.ipv4,
250 ntohl(mask->src));
251 MLX5_SET(fte_match_set_lyr_2_4, headers_v,
252 src_ipv4_src_ipv6.ipv4_layout.ipv4,
253 ntohl(key->src));
254
255 MLX5_SET(fte_match_set_lyr_2_4, headers_c,
256 dst_ipv4_dst_ipv6.ipv4_layout.ipv4,
257 ntohl(mask->dst));
258 MLX5_SET(fte_match_set_lyr_2_4, headers_v,
259 dst_ipv4_dst_ipv6.ipv4_layout.ipv4,
260 ntohl(key->dst));
261 }
262
263 MLX5_SET_TO_ONES(fte_match_set_lyr_2_4, headers_c, ethertype);
264 MLX5_SET(fte_match_set_lyr_2_4, headers_v, ethertype, ETH_P_IP);
265
266 /* Enforce DMAC when offloading incoming tunneled flows.
267 * Flow counters require a match on the DMAC.
268 */
269 MLX5_SET_TO_ONES(fte_match_set_lyr_2_4, headers_c, dmac_47_16);
270 MLX5_SET_TO_ONES(fte_match_set_lyr_2_4, headers_c, dmac_15_0);
271 ether_addr_copy(MLX5_ADDR_OF(fte_match_set_lyr_2_4, headers_v,
272 dmac_47_16), priv->netdev->dev_addr);
273
274 /* let software handle IP fragments */
275 MLX5_SET(fte_match_set_lyr_2_4, headers_c, frag, 1);
276 MLX5_SET(fte_match_set_lyr_2_4, headers_v, frag, 0);
277
278 return 0;
279}
280
de0af0bf
RD
281static int __parse_cls_flower(struct mlx5e_priv *priv,
282 struct mlx5_flow_spec *spec,
283 struct tc_cls_flower_offload *f,
284 u8 *min_inline)
e3a2b7ed 285{
c5bb1730
MG
286 void *headers_c = MLX5_ADDR_OF(fte_match_param, spec->match_criteria,
287 outer_headers);
288 void *headers_v = MLX5_ADDR_OF(fte_match_param, spec->match_value,
289 outer_headers);
e3a2b7ed
AV
290 u16 addr_type = 0;
291 u8 ip_proto = 0;
292
de0af0bf
RD
293 *min_inline = MLX5_INLINE_MODE_L2;
294
e3a2b7ed
AV
295 if (f->dissector->used_keys &
296 ~(BIT(FLOW_DISSECTOR_KEY_CONTROL) |
297 BIT(FLOW_DISSECTOR_KEY_BASIC) |
298 BIT(FLOW_DISSECTOR_KEY_ETH_ADDRS) |
095b6cfd 299 BIT(FLOW_DISSECTOR_KEY_VLAN) |
e3a2b7ed
AV
300 BIT(FLOW_DISSECTOR_KEY_IPV4_ADDRS) |
301 BIT(FLOW_DISSECTOR_KEY_IPV6_ADDRS) |
bbd00f7e
HHZ
302 BIT(FLOW_DISSECTOR_KEY_PORTS) |
303 BIT(FLOW_DISSECTOR_KEY_ENC_KEYID) |
304 BIT(FLOW_DISSECTOR_KEY_ENC_IPV4_ADDRS) |
305 BIT(FLOW_DISSECTOR_KEY_ENC_IPV6_ADDRS) |
306 BIT(FLOW_DISSECTOR_KEY_ENC_PORTS) |
307 BIT(FLOW_DISSECTOR_KEY_ENC_CONTROL))) {
e3a2b7ed
AV
308 netdev_warn(priv->netdev, "Unsupported key used: 0x%x\n",
309 f->dissector->used_keys);
310 return -EOPNOTSUPP;
311 }
312
bbd00f7e
HHZ
313 if ((dissector_uses_key(f->dissector,
314 FLOW_DISSECTOR_KEY_ENC_IPV4_ADDRS) ||
315 dissector_uses_key(f->dissector, FLOW_DISSECTOR_KEY_ENC_KEYID) ||
316 dissector_uses_key(f->dissector, FLOW_DISSECTOR_KEY_ENC_PORTS)) &&
317 dissector_uses_key(f->dissector, FLOW_DISSECTOR_KEY_ENC_CONTROL)) {
318 struct flow_dissector_key_control *key =
319 skb_flow_dissector_target(f->dissector,
320 FLOW_DISSECTOR_KEY_ENC_CONTROL,
321 f->key);
322 switch (key->addr_type) {
323 case FLOW_DISSECTOR_KEY_IPV4_ADDRS:
324 if (parse_tunnel_attr(priv, spec, f))
325 return -EOPNOTSUPP;
326 break;
327 default:
328 return -EOPNOTSUPP;
329 }
330
331 /* In decap flow, header pointers should point to the inner
332 * headers, outer header were already set by parse_tunnel_attr
333 */
334 headers_c = MLX5_ADDR_OF(fte_match_param, spec->match_criteria,
335 inner_headers);
336 headers_v = MLX5_ADDR_OF(fte_match_param, spec->match_value,
337 inner_headers);
338 }
339
e3a2b7ed
AV
340 if (dissector_uses_key(f->dissector, FLOW_DISSECTOR_KEY_CONTROL)) {
341 struct flow_dissector_key_control *key =
342 skb_flow_dissector_target(f->dissector,
1dbd0d37 343 FLOW_DISSECTOR_KEY_CONTROL,
e3a2b7ed
AV
344 f->key);
345 addr_type = key->addr_type;
346 }
347
348 if (dissector_uses_key(f->dissector, FLOW_DISSECTOR_KEY_BASIC)) {
349 struct flow_dissector_key_basic *key =
350 skb_flow_dissector_target(f->dissector,
351 FLOW_DISSECTOR_KEY_BASIC,
352 f->key);
353 struct flow_dissector_key_basic *mask =
354 skb_flow_dissector_target(f->dissector,
355 FLOW_DISSECTOR_KEY_BASIC,
356 f->mask);
357 ip_proto = key->ip_proto;
358
359 MLX5_SET(fte_match_set_lyr_2_4, headers_c, ethertype,
360 ntohs(mask->n_proto));
361 MLX5_SET(fte_match_set_lyr_2_4, headers_v, ethertype,
362 ntohs(key->n_proto));
363
364 MLX5_SET(fte_match_set_lyr_2_4, headers_c, ip_protocol,
365 mask->ip_proto);
366 MLX5_SET(fte_match_set_lyr_2_4, headers_v, ip_protocol,
367 key->ip_proto);
de0af0bf
RD
368
369 if (mask->ip_proto)
370 *min_inline = MLX5_INLINE_MODE_IP;
e3a2b7ed
AV
371 }
372
373 if (dissector_uses_key(f->dissector, FLOW_DISSECTOR_KEY_ETH_ADDRS)) {
374 struct flow_dissector_key_eth_addrs *key =
375 skb_flow_dissector_target(f->dissector,
376 FLOW_DISSECTOR_KEY_ETH_ADDRS,
377 f->key);
378 struct flow_dissector_key_eth_addrs *mask =
379 skb_flow_dissector_target(f->dissector,
380 FLOW_DISSECTOR_KEY_ETH_ADDRS,
381 f->mask);
382
383 ether_addr_copy(MLX5_ADDR_OF(fte_match_set_lyr_2_4, headers_c,
384 dmac_47_16),
385 mask->dst);
386 ether_addr_copy(MLX5_ADDR_OF(fte_match_set_lyr_2_4, headers_v,
387 dmac_47_16),
388 key->dst);
389
390 ether_addr_copy(MLX5_ADDR_OF(fte_match_set_lyr_2_4, headers_c,
391 smac_47_16),
392 mask->src);
393 ether_addr_copy(MLX5_ADDR_OF(fte_match_set_lyr_2_4, headers_v,
394 smac_47_16),
395 key->src);
396 }
397
095b6cfd
OG
398 if (dissector_uses_key(f->dissector, FLOW_DISSECTOR_KEY_VLAN)) {
399 struct flow_dissector_key_vlan *key =
400 skb_flow_dissector_target(f->dissector,
401 FLOW_DISSECTOR_KEY_VLAN,
402 f->key);
403 struct flow_dissector_key_vlan *mask =
404 skb_flow_dissector_target(f->dissector,
405 FLOW_DISSECTOR_KEY_VLAN,
406 f->mask);
358d79a4 407 if (mask->vlan_id || mask->vlan_priority) {
095b6cfd
OG
408 MLX5_SET(fte_match_set_lyr_2_4, headers_c, vlan_tag, 1);
409 MLX5_SET(fte_match_set_lyr_2_4, headers_v, vlan_tag, 1);
410
411 MLX5_SET(fte_match_set_lyr_2_4, headers_c, first_vid, mask->vlan_id);
412 MLX5_SET(fte_match_set_lyr_2_4, headers_v, first_vid, key->vlan_id);
358d79a4
OG
413
414 MLX5_SET(fte_match_set_lyr_2_4, headers_c, first_prio, mask->vlan_priority);
415 MLX5_SET(fte_match_set_lyr_2_4, headers_v, first_prio, key->vlan_priority);
095b6cfd
OG
416 }
417 }
418
e3a2b7ed
AV
419 if (addr_type == FLOW_DISSECTOR_KEY_IPV4_ADDRS) {
420 struct flow_dissector_key_ipv4_addrs *key =
421 skb_flow_dissector_target(f->dissector,
422 FLOW_DISSECTOR_KEY_IPV4_ADDRS,
423 f->key);
424 struct flow_dissector_key_ipv4_addrs *mask =
425 skb_flow_dissector_target(f->dissector,
426 FLOW_DISSECTOR_KEY_IPV4_ADDRS,
427 f->mask);
428
429 memcpy(MLX5_ADDR_OF(fte_match_set_lyr_2_4, headers_c,
430 src_ipv4_src_ipv6.ipv4_layout.ipv4),
431 &mask->src, sizeof(mask->src));
432 memcpy(MLX5_ADDR_OF(fte_match_set_lyr_2_4, headers_v,
433 src_ipv4_src_ipv6.ipv4_layout.ipv4),
434 &key->src, sizeof(key->src));
435 memcpy(MLX5_ADDR_OF(fte_match_set_lyr_2_4, headers_c,
436 dst_ipv4_dst_ipv6.ipv4_layout.ipv4),
437 &mask->dst, sizeof(mask->dst));
438 memcpy(MLX5_ADDR_OF(fte_match_set_lyr_2_4, headers_v,
439 dst_ipv4_dst_ipv6.ipv4_layout.ipv4),
440 &key->dst, sizeof(key->dst));
de0af0bf
RD
441
442 if (mask->src || mask->dst)
443 *min_inline = MLX5_INLINE_MODE_IP;
e3a2b7ed
AV
444 }
445
446 if (addr_type == FLOW_DISSECTOR_KEY_IPV6_ADDRS) {
447 struct flow_dissector_key_ipv6_addrs *key =
448 skb_flow_dissector_target(f->dissector,
449 FLOW_DISSECTOR_KEY_IPV6_ADDRS,
450 f->key);
451 struct flow_dissector_key_ipv6_addrs *mask =
452 skb_flow_dissector_target(f->dissector,
453 FLOW_DISSECTOR_KEY_IPV6_ADDRS,
454 f->mask);
455
456 memcpy(MLX5_ADDR_OF(fte_match_set_lyr_2_4, headers_c,
457 src_ipv4_src_ipv6.ipv6_layout.ipv6),
458 &mask->src, sizeof(mask->src));
459 memcpy(MLX5_ADDR_OF(fte_match_set_lyr_2_4, headers_v,
460 src_ipv4_src_ipv6.ipv6_layout.ipv6),
461 &key->src, sizeof(key->src));
462
463 memcpy(MLX5_ADDR_OF(fte_match_set_lyr_2_4, headers_c,
464 dst_ipv4_dst_ipv6.ipv6_layout.ipv6),
465 &mask->dst, sizeof(mask->dst));
466 memcpy(MLX5_ADDR_OF(fte_match_set_lyr_2_4, headers_v,
467 dst_ipv4_dst_ipv6.ipv6_layout.ipv6),
468 &key->dst, sizeof(key->dst));
de0af0bf
RD
469
470 if (ipv6_addr_type(&mask->src) != IPV6_ADDR_ANY ||
471 ipv6_addr_type(&mask->dst) != IPV6_ADDR_ANY)
472 *min_inline = MLX5_INLINE_MODE_IP;
e3a2b7ed
AV
473 }
474
475 if (dissector_uses_key(f->dissector, FLOW_DISSECTOR_KEY_PORTS)) {
476 struct flow_dissector_key_ports *key =
477 skb_flow_dissector_target(f->dissector,
478 FLOW_DISSECTOR_KEY_PORTS,
479 f->key);
480 struct flow_dissector_key_ports *mask =
481 skb_flow_dissector_target(f->dissector,
482 FLOW_DISSECTOR_KEY_PORTS,
483 f->mask);
484 switch (ip_proto) {
485 case IPPROTO_TCP:
486 MLX5_SET(fte_match_set_lyr_2_4, headers_c,
487 tcp_sport, ntohs(mask->src));
488 MLX5_SET(fte_match_set_lyr_2_4, headers_v,
489 tcp_sport, ntohs(key->src));
490
491 MLX5_SET(fte_match_set_lyr_2_4, headers_c,
492 tcp_dport, ntohs(mask->dst));
493 MLX5_SET(fte_match_set_lyr_2_4, headers_v,
494 tcp_dport, ntohs(key->dst));
495 break;
496
497 case IPPROTO_UDP:
498 MLX5_SET(fte_match_set_lyr_2_4, headers_c,
499 udp_sport, ntohs(mask->src));
500 MLX5_SET(fte_match_set_lyr_2_4, headers_v,
501 udp_sport, ntohs(key->src));
502
503 MLX5_SET(fte_match_set_lyr_2_4, headers_c,
504 udp_dport, ntohs(mask->dst));
505 MLX5_SET(fte_match_set_lyr_2_4, headers_v,
506 udp_dport, ntohs(key->dst));
507 break;
508 default:
509 netdev_err(priv->netdev,
510 "Only UDP and TCP transport are supported\n");
511 return -EINVAL;
512 }
de0af0bf
RD
513
514 if (mask->src || mask->dst)
515 *min_inline = MLX5_INLINE_MODE_TCP_UDP;
e3a2b7ed
AV
516 }
517
518 return 0;
519}
520
de0af0bf
RD
521static int parse_cls_flower(struct mlx5e_priv *priv,
522 struct mlx5_flow_spec *spec,
523 struct tc_cls_flower_offload *f)
524{
525 struct mlx5_core_dev *dev = priv->mdev;
526 struct mlx5_eswitch *esw = dev->priv.eswitch;
527 struct mlx5_eswitch_rep *rep = priv->ppriv;
528 u8 min_inline;
529 int err;
530
531 err = __parse_cls_flower(priv, spec, f, &min_inline);
532
533 if (!err && esw->mode == SRIOV_OFFLOADS &&
534 rep->vport != FDB_UPLINK_VPORT) {
535 if (min_inline > esw->offloads.inline_mode) {
536 netdev_warn(priv->netdev,
537 "Flow is not offloaded due to min inline setting, required %d actual %d\n",
538 min_inline, esw->offloads.inline_mode);
539 return -EOPNOTSUPP;
540 }
541 }
542
543 return err;
544}
545
5c40348c
OG
546static int parse_tc_nic_actions(struct mlx5e_priv *priv, struct tcf_exts *exts,
547 u32 *action, u32 *flow_tag)
e3a2b7ed
AV
548{
549 const struct tc_action *a;
22dc13c8 550 LIST_HEAD(actions);
e3a2b7ed
AV
551
552 if (tc_no_actions(exts))
553 return -EINVAL;
554
555 *flow_tag = MLX5_FS_DEFAULT_FLOW_TAG;
556 *action = 0;
557
22dc13c8
WC
558 tcf_exts_to_list(exts, &actions);
559 list_for_each_entry(a, &actions, list) {
e3a2b7ed
AV
560 /* Only support a single action per rule */
561 if (*action)
562 return -EINVAL;
563
564 if (is_tcf_gact_shot(a)) {
565 *action |= MLX5_FLOW_CONTEXT_ACTION_DROP;
aad7e08d
AV
566 if (MLX5_CAP_FLOWTABLE(priv->mdev,
567 flow_table_properties_nic_receive.flow_counter))
568 *action |= MLX5_FLOW_CONTEXT_ACTION_COUNT;
e3a2b7ed
AV
569 continue;
570 }
571
572 if (is_tcf_skbedit_mark(a)) {
573 u32 mark = tcf_skbedit_mark(a);
574
575 if (mark & ~MLX5E_TC_FLOW_ID_MASK) {
576 netdev_warn(priv->netdev, "Bad flow mark - only 16 bit is supported: 0x%x\n",
577 mark);
578 return -EINVAL;
579 }
580
581 *flow_tag = mark;
582 *action |= MLX5_FLOW_CONTEXT_ACTION_FWD_DEST;
583 continue;
584 }
585
586 return -EINVAL;
587 }
588
589 return 0;
590}
591
a54e20b4
HHZ
592static inline int cmp_encap_info(struct mlx5_encap_info *a,
593 struct mlx5_encap_info *b)
594{
595 return memcmp(a, b, sizeof(*a));
596}
597
598static inline int hash_encap_info(struct mlx5_encap_info *info)
599{
600 return jhash(info, sizeof(*info), 0);
601}
602
603static int mlx5e_route_lookup_ipv4(struct mlx5e_priv *priv,
604 struct net_device *mirred_dev,
605 struct net_device **out_dev,
606 struct flowi4 *fl4,
607 struct neighbour **out_n,
608 __be32 *saddr,
609 int *out_ttl)
610{
611 struct rtable *rt;
612 struct neighbour *n = NULL;
613 int ttl;
614
615#if IS_ENABLED(CONFIG_INET)
616 rt = ip_route_output_key(dev_net(mirred_dev), fl4);
617 if (IS_ERR(rt)) {
618 pr_warn("%s: no route to %pI4\n", __func__, &fl4->daddr);
619 return -EOPNOTSUPP;
620 }
621#else
622 return -EOPNOTSUPP;
623#endif
624
625 if (!switchdev_port_same_parent_id(priv->netdev, rt->dst.dev)) {
626 pr_warn("%s: Can't offload the flow, netdevices aren't on the same HW e-switch\n",
627 __func__);
628 ip_rt_put(rt);
629 return -EOPNOTSUPP;
630 }
631
632 ttl = ip4_dst_hoplimit(&rt->dst);
633 n = dst_neigh_lookup(&rt->dst, &fl4->daddr);
634 ip_rt_put(rt);
635 if (!n)
636 return -ENOMEM;
637
638 *out_n = n;
639 *saddr = fl4->saddr;
640 *out_ttl = ttl;
641 *out_dev = rt->dst.dev;
642
643 return 0;
644}
645
646static int gen_vxlan_header_ipv4(struct net_device *out_dev,
647 char buf[],
648 unsigned char h_dest[ETH_ALEN],
649 int ttl,
650 __be32 daddr,
651 __be32 saddr,
652 __be16 udp_dst_port,
653 __be32 vx_vni)
654{
655 int encap_size = VXLAN_HLEN + sizeof(struct iphdr) + ETH_HLEN;
656 struct ethhdr *eth = (struct ethhdr *)buf;
657 struct iphdr *ip = (struct iphdr *)((char *)eth + sizeof(struct ethhdr));
658 struct udphdr *udp = (struct udphdr *)((char *)ip + sizeof(struct iphdr));
659 struct vxlanhdr *vxh = (struct vxlanhdr *)((char *)udp + sizeof(struct udphdr));
660
661 memset(buf, 0, encap_size);
662
663 ether_addr_copy(eth->h_dest, h_dest);
664 ether_addr_copy(eth->h_source, out_dev->dev_addr);
665 eth->h_proto = htons(ETH_P_IP);
666
667 ip->daddr = daddr;
668 ip->saddr = saddr;
669
670 ip->ttl = ttl;
671 ip->protocol = IPPROTO_UDP;
672 ip->version = 0x4;
673 ip->ihl = 0x5;
674
675 udp->dest = udp_dst_port;
676 vxh->vx_flags = VXLAN_HF_VNI;
677 vxh->vx_vni = vxlan_vni_field(vx_vni);
678
679 return encap_size;
680}
681
682static int mlx5e_create_encap_header_ipv4(struct mlx5e_priv *priv,
683 struct net_device *mirred_dev,
684 struct mlx5_encap_entry *e,
685 struct net_device **out_dev)
686{
687 int max_encap_size = MLX5_CAP_ESW(priv->mdev, max_encap_header_size);
688 struct flowi4 fl4 = {};
689 struct neighbour *n;
690 char *encap_header;
691 int encap_size;
692 __be32 saddr;
693 int ttl;
694 int err;
695
696 encap_header = kzalloc(max_encap_size, GFP_KERNEL);
697 if (!encap_header)
698 return -ENOMEM;
699
700 switch (e->tunnel_type) {
701 case MLX5_HEADER_TYPE_VXLAN:
702 fl4.flowi4_proto = IPPROTO_UDP;
703 fl4.fl4_dport = e->tun_info.tp_dst;
704 break;
705 default:
706 err = -EOPNOTSUPP;
707 goto out;
708 }
709 fl4.daddr = e->tun_info.daddr;
710
711 err = mlx5e_route_lookup_ipv4(priv, mirred_dev, out_dev,
712 &fl4, &n, &saddr, &ttl);
713 if (err)
714 goto out;
715
716 e->n = n;
717 e->out_dev = *out_dev;
718
719 if (!(n->nud_state & NUD_VALID)) {
720 err = -ENOTSUPP;
721 goto out;
722 }
723
724 neigh_ha_snapshot(e->h_dest, n, *out_dev);
725
726 switch (e->tunnel_type) {
727 case MLX5_HEADER_TYPE_VXLAN:
728 encap_size = gen_vxlan_header_ipv4(*out_dev, encap_header,
729 e->h_dest, ttl,
730 e->tun_info.daddr,
731 saddr, e->tun_info.tp_dst,
732 e->tun_info.tun_id);
733 break;
734 default:
735 err = -EOPNOTSUPP;
736 goto out;
737 }
738
739 err = mlx5_encap_alloc(priv->mdev, e->tunnel_type,
740 encap_size, encap_header, &e->encap_id);
741out:
742 kfree(encap_header);
743 return err;
744}
745
746static int mlx5e_attach_encap(struct mlx5e_priv *priv,
747 struct ip_tunnel_info *tun_info,
748 struct net_device *mirred_dev,
749 struct mlx5_esw_flow_attr *attr)
750{
751 struct mlx5_eswitch *esw = priv->mdev->priv.eswitch;
752 unsigned short family = ip_tunnel_info_af(tun_info);
753 struct ip_tunnel_key *key = &tun_info->key;
754 struct mlx5_encap_info info;
755 struct mlx5_encap_entry *e;
756 struct net_device *out_dev;
757 uintptr_t hash_key;
758 bool found = false;
759 int tunnel_type;
760 int err;
761
762 /* udp dst port must be given */
763 if (!memchr_inv(&key->tp_dst, 0, sizeof(key->tp_dst)))
764 return -EOPNOTSUPP;
765
766 if (mlx5e_vxlan_lookup_port(priv, be16_to_cpu(key->tp_dst)) &&
767 MLX5_CAP_ESW(priv->mdev, vxlan_encap_decap)) {
768 info.tp_dst = key->tp_dst;
769 info.tun_id = tunnel_id_to_key32(key->tun_id);
770 tunnel_type = MLX5_HEADER_TYPE_VXLAN;
771 } else {
772 return -EOPNOTSUPP;
773 }
774
775 switch (family) {
776 case AF_INET:
777 info.daddr = key->u.ipv4.dst;
778 break;
779 default:
780 return -EOPNOTSUPP;
781 }
782
783 hash_key = hash_encap_info(&info);
784
785 hash_for_each_possible_rcu(esw->offloads.encap_tbl, e,
786 encap_hlist, hash_key) {
787 if (!cmp_encap_info(&e->tun_info, &info)) {
788 found = true;
789 break;
790 }
791 }
792
793 if (found) {
794 attr->encap = e;
795 return 0;
796 }
797
798 e = kzalloc(sizeof(*e), GFP_KERNEL);
799 if (!e)
800 return -ENOMEM;
801
802 e->tun_info = info;
803 e->tunnel_type = tunnel_type;
804 INIT_LIST_HEAD(&e->flows);
805
806 err = mlx5e_create_encap_header_ipv4(priv, mirred_dev, e, &out_dev);
807 if (err)
808 goto out_err;
809
810 attr->encap = e;
811 hash_add_rcu(esw->offloads.encap_tbl, &e->encap_hlist, hash_key);
812
813 return err;
814
815out_err:
816 kfree(e);
817 return err;
818}
819
03a9d11e 820static int parse_tc_fdb_actions(struct mlx5e_priv *priv, struct tcf_exts *exts,
a54e20b4 821 struct mlx5e_tc_flow *flow)
03a9d11e 822{
a54e20b4
HHZ
823 struct mlx5_esw_flow_attr *attr = flow->attr;
824 struct ip_tunnel_info *info = NULL;
03a9d11e 825 const struct tc_action *a;
22dc13c8 826 LIST_HEAD(actions);
a54e20b4
HHZ
827 bool encap = false;
828 int err;
03a9d11e
OG
829
830 if (tc_no_actions(exts))
831 return -EINVAL;
832
776b12b6
OG
833 memset(attr, 0, sizeof(*attr));
834 attr->in_rep = priv->ppriv;
03a9d11e 835
22dc13c8
WC
836 tcf_exts_to_list(exts, &actions);
837 list_for_each_entry(a, &actions, list) {
03a9d11e 838 if (is_tcf_gact_shot(a)) {
8b32580d
OG
839 attr->action |= MLX5_FLOW_CONTEXT_ACTION_DROP |
840 MLX5_FLOW_CONTEXT_ACTION_COUNT;
03a9d11e
OG
841 continue;
842 }
843
5724b8b5 844 if (is_tcf_mirred_egress_redirect(a)) {
03a9d11e
OG
845 int ifindex = tcf_mirred_ifindex(a);
846 struct net_device *out_dev;
847 struct mlx5e_priv *out_priv;
03a9d11e
OG
848
849 out_dev = __dev_get_by_index(dev_net(priv->netdev), ifindex);
850
a54e20b4
HHZ
851 if (switchdev_port_same_parent_id(priv->netdev,
852 out_dev)) {
853 attr->action |= MLX5_FLOW_CONTEXT_ACTION_FWD_DEST |
854 MLX5_FLOW_CONTEXT_ACTION_COUNT;
855 out_priv = netdev_priv(out_dev);
856 attr->out_rep = out_priv->ppriv;
857 } else if (encap) {
858 err = mlx5e_attach_encap(priv, info,
859 out_dev, attr);
860 if (err)
861 return err;
862 list_add(&flow->encap, &attr->encap->flows);
863 attr->action |= MLX5_FLOW_CONTEXT_ACTION_ENCAP |
864 MLX5_FLOW_CONTEXT_ACTION_FWD_DEST |
865 MLX5_FLOW_CONTEXT_ACTION_COUNT;
866 out_priv = netdev_priv(attr->encap->out_dev);
867 attr->out_rep = out_priv->ppriv;
868 } else {
03a9d11e
OG
869 pr_err("devices %s %s not on same switch HW, can't offload forwarding\n",
870 priv->netdev->name, out_dev->name);
871 return -EINVAL;
872 }
a54e20b4
HHZ
873 continue;
874 }
03a9d11e 875
a54e20b4
HHZ
876 if (is_tcf_tunnel_set(a)) {
877 info = tcf_tunnel_info(a);
878 if (info)
879 encap = true;
880 else
881 return -EOPNOTSUPP;
03a9d11e
OG
882 continue;
883 }
884
8b32580d
OG
885 if (is_tcf_vlan(a)) {
886 if (tcf_vlan_action(a) == VLAN_F_POP) {
887 attr->action |= MLX5_FLOW_CONTEXT_ACTION_VLAN_POP;
888 } else if (tcf_vlan_action(a) == VLAN_F_PUSH) {
889 if (tcf_vlan_push_proto(a) != htons(ETH_P_8021Q))
890 return -EOPNOTSUPP;
891
892 attr->action |= MLX5_FLOW_CONTEXT_ACTION_VLAN_PUSH;
893 attr->vlan = tcf_vlan_push_vid(a);
894 }
895 continue;
896 }
897
bbd00f7e
HHZ
898 if (is_tcf_tunnel_release(a)) {
899 attr->action |= MLX5_FLOW_CONTEXT_ACTION_DECAP;
900 continue;
901 }
902
03a9d11e
OG
903 return -EINVAL;
904 }
905 return 0;
906}
907
e3a2b7ed
AV
908int mlx5e_configure_flower(struct mlx5e_priv *priv, __be16 protocol,
909 struct tc_cls_flower_offload *f)
910{
acff797c 911 struct mlx5e_tc_table *tc = &priv->fs.tc;
e3a2b7ed 912 int err = 0;
776b12b6
OG
913 bool fdb_flow = false;
914 u32 flow_tag, action;
e3a2b7ed 915 struct mlx5e_tc_flow *flow;
c5bb1730 916 struct mlx5_flow_spec *spec;
adb4c123 917 struct mlx5_eswitch *esw = priv->mdev->priv.eswitch;
e3a2b7ed 918
776b12b6
OG
919 if (esw && esw->mode == SRIOV_OFFLOADS)
920 fdb_flow = true;
921
53636068
RD
922 if (fdb_flow)
923 flow = kzalloc(sizeof(*flow) +
924 sizeof(struct mlx5_esw_flow_attr),
925 GFP_KERNEL);
926 else
927 flow = kzalloc(sizeof(*flow), GFP_KERNEL);
e3a2b7ed 928
c5bb1730
MG
929 spec = mlx5_vzalloc(sizeof(*spec));
930 if (!spec || !flow) {
e3a2b7ed
AV
931 err = -ENOMEM;
932 goto err_free;
933 }
934
935 flow->cookie = f->cookie;
936
c5bb1730 937 err = parse_cls_flower(priv, spec, f);
e3a2b7ed
AV
938 if (err < 0)
939 goto err_free;
940
776b12b6
OG
941 if (fdb_flow) {
942 flow->attr = (struct mlx5_esw_flow_attr *)(flow + 1);
a54e20b4 943 err = parse_tc_fdb_actions(priv, f->exts, flow);
adb4c123
OG
944 if (err < 0)
945 goto err_free;
776b12b6 946 flow->rule = mlx5e_tc_add_fdb_flow(priv, spec, flow->attr);
adb4c123
OG
947 } else {
948 err = parse_tc_nic_actions(priv, f->exts, &action, &flow_tag);
949 if (err < 0)
950 goto err_free;
951 flow->rule = mlx5e_tc_add_nic_flow(priv, spec, action, flow_tag);
952 }
e3a2b7ed 953
e3a2b7ed
AV
954 if (IS_ERR(flow->rule)) {
955 err = PTR_ERR(flow->rule);
5c40348c 956 goto err_free;
e3a2b7ed
AV
957 }
958
5c40348c
OG
959 err = rhashtable_insert_fast(&tc->ht, &flow->node,
960 tc->ht_params);
961 if (err)
962 goto err_del_rule;
963
e3a2b7ed
AV
964 goto out;
965
5c40348c 966err_del_rule:
74491de9 967 mlx5_del_flow_rules(flow->rule);
e3a2b7ed
AV
968
969err_free:
53636068 970 kfree(flow);
e3a2b7ed 971out:
c5bb1730 972 kvfree(spec);
e3a2b7ed
AV
973 return err;
974}
975
a54e20b4
HHZ
976static void mlx5e_detach_encap(struct mlx5e_priv *priv,
977 struct mlx5e_tc_flow *flow) {
978 struct list_head *next = flow->encap.next;
979
980 list_del(&flow->encap);
981 if (list_empty(next)) {
982 struct mlx5_encap_entry *e;
983
984 e = list_entry(next, struct mlx5_encap_entry, flows);
985 if (e->n) {
986 mlx5_encap_dealloc(priv->mdev, e->encap_id);
987 neigh_release(e->n);
988 }
989 hlist_del_rcu(&e->encap_hlist);
990 kfree(e);
991 }
992}
993
e3a2b7ed
AV
994int mlx5e_delete_flower(struct mlx5e_priv *priv,
995 struct tc_cls_flower_offload *f)
996{
997 struct mlx5e_tc_flow *flow;
acff797c 998 struct mlx5e_tc_table *tc = &priv->fs.tc;
e3a2b7ed
AV
999
1000 flow = rhashtable_lookup_fast(&tc->ht, &f->cookie,
1001 tc->ht_params);
1002 if (!flow)
1003 return -EINVAL;
1004
1005 rhashtable_remove_fast(&tc->ht, &flow->node, tc->ht_params);
1006
961e8979 1007 mlx5e_tc_del_flow(priv, flow);
e3a2b7ed 1008
a54e20b4
HHZ
1009 if (flow->attr->action & MLX5_FLOW_CONTEXT_ACTION_ENCAP)
1010 mlx5e_detach_encap(priv, flow);
1011
e3a2b7ed
AV
1012 kfree(flow);
1013
1014 return 0;
1015}
1016
aad7e08d
AV
1017int mlx5e_stats_flower(struct mlx5e_priv *priv,
1018 struct tc_cls_flower_offload *f)
1019{
1020 struct mlx5e_tc_table *tc = &priv->fs.tc;
1021 struct mlx5e_tc_flow *flow;
1022 struct tc_action *a;
1023 struct mlx5_fc *counter;
22dc13c8 1024 LIST_HEAD(actions);
aad7e08d
AV
1025 u64 bytes;
1026 u64 packets;
1027 u64 lastuse;
1028
1029 flow = rhashtable_lookup_fast(&tc->ht, &f->cookie,
1030 tc->ht_params);
1031 if (!flow)
1032 return -EINVAL;
1033
1034 counter = mlx5_flow_rule_counter(flow->rule);
1035 if (!counter)
1036 return 0;
1037
1038 mlx5_fc_query_cached(counter, &bytes, &packets, &lastuse);
1039
22dc13c8
WC
1040 tcf_exts_to_list(f->exts, &actions);
1041 list_for_each_entry(a, &actions, list)
aad7e08d
AV
1042 tcf_action_stats_update(a, bytes, packets, lastuse);
1043
1044 return 0;
1045}
1046
e8f887ac
AV
1047static const struct rhashtable_params mlx5e_tc_flow_ht_params = {
1048 .head_offset = offsetof(struct mlx5e_tc_flow, node),
1049 .key_offset = offsetof(struct mlx5e_tc_flow, cookie),
1050 .key_len = sizeof(((struct mlx5e_tc_flow *)0)->cookie),
1051 .automatic_shrinking = true,
1052};
1053
1054int mlx5e_tc_init(struct mlx5e_priv *priv)
1055{
acff797c 1056 struct mlx5e_tc_table *tc = &priv->fs.tc;
e8f887ac
AV
1057
1058 tc->ht_params = mlx5e_tc_flow_ht_params;
1059 return rhashtable_init(&tc->ht, &tc->ht_params);
1060}
1061
1062static void _mlx5e_tc_del_flow(void *ptr, void *arg)
1063{
1064 struct mlx5e_tc_flow *flow = ptr;
1065 struct mlx5e_priv *priv = arg;
1066
961e8979 1067 mlx5e_tc_del_flow(priv, flow);
e8f887ac
AV
1068 kfree(flow);
1069}
1070
1071void mlx5e_tc_cleanup(struct mlx5e_priv *priv)
1072{
acff797c 1073 struct mlx5e_tc_table *tc = &priv->fs.tc;
e8f887ac
AV
1074
1075 rhashtable_free_and_destroy(&tc->ht, _mlx5e_tc_del_flow, priv);
1076
acff797c
MG
1077 if (!IS_ERR_OR_NULL(tc->t)) {
1078 mlx5_destroy_flow_table(tc->t);
1079 tc->t = NULL;
e8f887ac
AV
1080 }
1081}