]> git.kernelconcepts.de Git - karo-tx-linux.git/blob - drivers/net/ethernet/mellanox/mlx5/core/en_flow_table.c
net/mlx5e: Cosmetics: use BIT() instead of "1 <<", and others
[karo-tx-linux.git] / drivers / net / ethernet / mellanox / mlx5 / core / en_flow_table.c
1 /*
2  * Copyright (c) 2015, 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
33 #include <linux/list.h>
34 #include <linux/ip.h>
35 #include <linux/ipv6.h>
36 #include <linux/tcp.h>
37 #include <linux/mlx5/flow_table.h>
38 #include "en.h"
39
40 enum {
41         MLX5E_FULLMATCH = 0,
42         MLX5E_ALLMULTI  = 1,
43         MLX5E_PROMISC   = 2,
44 };
45
46 enum {
47         MLX5E_UC        = 0,
48         MLX5E_MC_IPV4   = 1,
49         MLX5E_MC_IPV6   = 2,
50         MLX5E_MC_OTHER  = 3,
51 };
52
53 enum {
54         MLX5E_ACTION_NONE = 0,
55         MLX5E_ACTION_ADD  = 1,
56         MLX5E_ACTION_DEL  = 2,
57 };
58
59 struct mlx5e_eth_addr_hash_node {
60         struct hlist_node          hlist;
61         u8                         action;
62         struct mlx5e_eth_addr_info ai;
63 };
64
65 static inline int mlx5e_hash_eth_addr(u8 *addr)
66 {
67         return addr[5];
68 }
69
70 static void mlx5e_add_eth_addr_to_hash(struct hlist_head *hash, u8 *addr)
71 {
72         struct mlx5e_eth_addr_hash_node *hn;
73         int ix = mlx5e_hash_eth_addr(addr);
74         int found = 0;
75
76         hlist_for_each_entry(hn, &hash[ix], hlist)
77                 if (ether_addr_equal_64bits(hn->ai.addr, addr)) {
78                         found = 1;
79                         break;
80                 }
81
82         if (found) {
83                 hn->action = MLX5E_ACTION_NONE;
84                 return;
85         }
86
87         hn = kzalloc(sizeof(*hn), GFP_ATOMIC);
88         if (!hn)
89                 return;
90
91         ether_addr_copy(hn->ai.addr, addr);
92         hn->action = MLX5E_ACTION_ADD;
93
94         hlist_add_head(&hn->hlist, &hash[ix]);
95 }
96
97 static void mlx5e_del_eth_addr_from_hash(struct mlx5e_eth_addr_hash_node *hn)
98 {
99         hlist_del(&hn->hlist);
100         kfree(hn);
101 }
102
103 static void mlx5e_del_eth_addr_from_flow_table(struct mlx5e_priv *priv,
104                                                struct mlx5e_eth_addr_info *ai)
105 {
106         void *ft = priv->ft.main;
107
108         if (ai->tt_vec & BIT(MLX5E_TT_IPV6_TCP))
109                 mlx5_del_flow_table_entry(ft, ai->ft_ix[MLX5E_TT_IPV6_TCP]);
110
111         if (ai->tt_vec & BIT(MLX5E_TT_IPV4_TCP))
112                 mlx5_del_flow_table_entry(ft, ai->ft_ix[MLX5E_TT_IPV4_TCP]);
113
114         if (ai->tt_vec & BIT(MLX5E_TT_IPV6_UDP))
115                 mlx5_del_flow_table_entry(ft, ai->ft_ix[MLX5E_TT_IPV6_UDP]);
116
117         if (ai->tt_vec & BIT(MLX5E_TT_IPV4_UDP))
118                 mlx5_del_flow_table_entry(ft, ai->ft_ix[MLX5E_TT_IPV4_UDP]);
119
120         if (ai->tt_vec & BIT(MLX5E_TT_IPV6))
121                 mlx5_del_flow_table_entry(ft, ai->ft_ix[MLX5E_TT_IPV6]);
122
123         if (ai->tt_vec & BIT(MLX5E_TT_IPV4))
124                 mlx5_del_flow_table_entry(ft, ai->ft_ix[MLX5E_TT_IPV4]);
125
126         if (ai->tt_vec & BIT(MLX5E_TT_ANY))
127                 mlx5_del_flow_table_entry(ft, ai->ft_ix[MLX5E_TT_ANY]);
128 }
129
130 static int mlx5e_get_eth_addr_type(u8 *addr)
131 {
132         if (is_unicast_ether_addr(addr))
133                 return MLX5E_UC;
134
135         if ((addr[0] == 0x01) &&
136             (addr[1] == 0x00) &&
137             (addr[2] == 0x5e) &&
138            !(addr[3] &  0x80))
139                 return MLX5E_MC_IPV4;
140
141         if ((addr[0] == 0x33) &&
142             (addr[1] == 0x33))
143                 return MLX5E_MC_IPV6;
144
145         return MLX5E_MC_OTHER;
146 }
147
148 static u32 mlx5e_get_tt_vec(struct mlx5e_eth_addr_info *ai, int type)
149 {
150         int eth_addr_type;
151         u32 ret;
152
153         switch (type) {
154         case MLX5E_FULLMATCH:
155                 eth_addr_type = mlx5e_get_eth_addr_type(ai->addr);
156                 switch (eth_addr_type) {
157                 case MLX5E_UC:
158                         ret =
159                                 BIT(MLX5E_TT_IPV4_TCP)       |
160                                 BIT(MLX5E_TT_IPV6_TCP)       |
161                                 BIT(MLX5E_TT_IPV4_UDP)       |
162                                 BIT(MLX5E_TT_IPV6_UDP)       |
163                                 BIT(MLX5E_TT_IPV4)           |
164                                 BIT(MLX5E_TT_IPV6)           |
165                                 BIT(MLX5E_TT_ANY)            |
166                                 0;
167                         break;
168
169                 case MLX5E_MC_IPV4:
170                         ret =
171                                 BIT(MLX5E_TT_IPV4_UDP)       |
172                                 BIT(MLX5E_TT_IPV4)           |
173                                 0;
174                         break;
175
176                 case MLX5E_MC_IPV6:
177                         ret =
178                                 BIT(MLX5E_TT_IPV6_UDP)       |
179                                 BIT(MLX5E_TT_IPV6)           |
180                                 0;
181                         break;
182
183                 case MLX5E_MC_OTHER:
184                         ret =
185                                 BIT(MLX5E_TT_ANY)            |
186                                 0;
187                         break;
188                 }
189
190                 break;
191
192         case MLX5E_ALLMULTI:
193                 ret =
194                         BIT(MLX5E_TT_IPV4_UDP) |
195                         BIT(MLX5E_TT_IPV6_UDP) |
196                         BIT(MLX5E_TT_IPV4)     |
197                         BIT(MLX5E_TT_IPV6)     |
198                         BIT(MLX5E_TT_ANY)      |
199                         0;
200                 break;
201
202         default: /* MLX5E_PROMISC */
203                 ret =
204                         BIT(MLX5E_TT_IPV4_TCP)       |
205                         BIT(MLX5E_TT_IPV6_TCP)       |
206                         BIT(MLX5E_TT_IPV4_UDP)       |
207                         BIT(MLX5E_TT_IPV6_UDP)       |
208                         BIT(MLX5E_TT_IPV4)           |
209                         BIT(MLX5E_TT_IPV6)           |
210                         BIT(MLX5E_TT_ANY)            |
211                         0;
212                 break;
213         }
214
215         return ret;
216 }
217
218 static int __mlx5e_add_eth_addr_rule(struct mlx5e_priv *priv,
219                                      struct mlx5e_eth_addr_info *ai, int type,
220                                      void *flow_context, void *match_criteria)
221 {
222         u8 match_criteria_enable = 0;
223         void *match_value;
224         void *dest;
225         u8   *dmac;
226         u8   *match_criteria_dmac;
227         void *ft   = priv->ft.main;
228         u32  *tirn = priv->tirn;
229         u32  *ft_ix;
230         u32  tt_vec;
231         int  err;
232
233         match_value = MLX5_ADDR_OF(flow_context, flow_context, match_value);
234         dmac = MLX5_ADDR_OF(fte_match_param, match_value,
235                             outer_headers.dmac_47_16);
236         match_criteria_dmac = MLX5_ADDR_OF(fte_match_param, match_criteria,
237                                            outer_headers.dmac_47_16);
238         dest = MLX5_ADDR_OF(flow_context, flow_context, destination);
239
240         MLX5_SET(flow_context, flow_context, action,
241                  MLX5_FLOW_CONTEXT_ACTION_FWD_DEST);
242         MLX5_SET(flow_context, flow_context, destination_list_size, 1);
243         MLX5_SET(dest_format_struct, dest, destination_type,
244                  MLX5_FLOW_CONTEXT_DEST_TYPE_TIR);
245
246         switch (type) {
247         case MLX5E_FULLMATCH:
248                 match_criteria_enable = MLX5_MATCH_OUTER_HEADERS;
249                 memset(match_criteria_dmac, 0xff, ETH_ALEN);
250                 ether_addr_copy(dmac, ai->addr);
251                 break;
252
253         case MLX5E_ALLMULTI:
254                 match_criteria_enable = MLX5_MATCH_OUTER_HEADERS;
255                 match_criteria_dmac[0] = 0x01;
256                 dmac[0] = 0x01;
257                 break;
258
259         case MLX5E_PROMISC:
260                 break;
261         }
262
263         tt_vec = mlx5e_get_tt_vec(ai, type);
264
265         ft_ix = &ai->ft_ix[MLX5E_TT_ANY];
266         if (tt_vec & BIT(MLX5E_TT_ANY)) {
267                 MLX5_SET(dest_format_struct, dest, destination_id,
268                          tirn[MLX5E_TT_ANY]);
269                 err = mlx5_add_flow_table_entry(ft, match_criteria_enable,
270                                                 match_criteria, flow_context,
271                                                 ft_ix);
272                 if (err)
273                         goto err_del_ai;
274
275                 ai->tt_vec |= BIT(MLX5E_TT_ANY);
276         }
277
278         match_criteria_enable = MLX5_MATCH_OUTER_HEADERS;
279         MLX5_SET_TO_ONES(fte_match_param, match_criteria,
280                          outer_headers.ethertype);
281
282         ft_ix = &ai->ft_ix[MLX5E_TT_IPV4];
283         if (tt_vec & BIT(MLX5E_TT_IPV4)) {
284                 MLX5_SET(fte_match_param, match_value, outer_headers.ethertype,
285                          ETH_P_IP);
286                 MLX5_SET(dest_format_struct, dest, destination_id,
287                          tirn[MLX5E_TT_IPV4]);
288                 err = mlx5_add_flow_table_entry(ft, match_criteria_enable,
289                                                 match_criteria, flow_context,
290                                                 ft_ix);
291                 if (err)
292                         goto err_del_ai;
293
294                 ai->tt_vec |= BIT(MLX5E_TT_IPV4);
295         }
296
297         ft_ix = &ai->ft_ix[MLX5E_TT_IPV6];
298         if (tt_vec & BIT(MLX5E_TT_IPV6)) {
299                 MLX5_SET(fte_match_param, match_value, outer_headers.ethertype,
300                          ETH_P_IPV6);
301                 MLX5_SET(dest_format_struct, dest, destination_id,
302                          tirn[MLX5E_TT_IPV6]);
303                 err = mlx5_add_flow_table_entry(ft, match_criteria_enable,
304                                                 match_criteria, flow_context,
305                                                 ft_ix);
306                 if (err)
307                         goto err_del_ai;
308
309                 ai->tt_vec |= BIT(MLX5E_TT_IPV6);
310         }
311
312         MLX5_SET_TO_ONES(fte_match_param, match_criteria,
313                          outer_headers.ip_protocol);
314         MLX5_SET(fte_match_param, match_value, outer_headers.ip_protocol,
315                  IPPROTO_UDP);
316
317         ft_ix = &ai->ft_ix[MLX5E_TT_IPV4_UDP];
318         if (tt_vec & BIT(MLX5E_TT_IPV4_UDP)) {
319                 MLX5_SET(fte_match_param, match_value, outer_headers.ethertype,
320                          ETH_P_IP);
321                 MLX5_SET(dest_format_struct, dest, destination_id,
322                          tirn[MLX5E_TT_IPV4_UDP]);
323                 err = mlx5_add_flow_table_entry(ft, match_criteria_enable,
324                                                 match_criteria, flow_context,
325                                                 ft_ix);
326                 if (err)
327                         goto err_del_ai;
328
329                 ai->tt_vec |= BIT(MLX5E_TT_IPV4_UDP);
330         }
331
332         ft_ix = &ai->ft_ix[MLX5E_TT_IPV6_UDP];
333         if (tt_vec & BIT(MLX5E_TT_IPV6_UDP)) {
334                 MLX5_SET(fte_match_param, match_value, outer_headers.ethertype,
335                          ETH_P_IPV6);
336                 MLX5_SET(dest_format_struct, dest, destination_id,
337                          tirn[MLX5E_TT_IPV6_UDP]);
338                 err = mlx5_add_flow_table_entry(ft, match_criteria_enable,
339                                                 match_criteria, flow_context,
340                                                 ft_ix);
341                 if (err)
342                         goto err_del_ai;
343
344                 ai->tt_vec |= BIT(MLX5E_TT_IPV6_UDP);
345         }
346
347         MLX5_SET(fte_match_param, match_value, outer_headers.ip_protocol,
348                  IPPROTO_TCP);
349
350         ft_ix = &ai->ft_ix[MLX5E_TT_IPV4_TCP];
351         if (tt_vec & BIT(MLX5E_TT_IPV4_TCP)) {
352                 MLX5_SET(fte_match_param, match_value, outer_headers.ethertype,
353                          ETH_P_IP);
354                 MLX5_SET(dest_format_struct, dest, destination_id,
355                          tirn[MLX5E_TT_IPV4_TCP]);
356                 err = mlx5_add_flow_table_entry(ft, match_criteria_enable,
357                                                 match_criteria, flow_context,
358                                                 ft_ix);
359                 if (err)
360                         goto err_del_ai;
361
362                 ai->tt_vec |= BIT(MLX5E_TT_IPV4_TCP);
363         }
364
365         ft_ix = &ai->ft_ix[MLX5E_TT_IPV6_TCP];
366         if (tt_vec & BIT(MLX5E_TT_IPV6_TCP)) {
367                 MLX5_SET(fte_match_param, match_value, outer_headers.ethertype,
368                          ETH_P_IPV6);
369                 MLX5_SET(dest_format_struct, dest, destination_id,
370                          tirn[MLX5E_TT_IPV6_TCP]);
371                 err = mlx5_add_flow_table_entry(ft, match_criteria_enable,
372                                                 match_criteria, flow_context,
373                                                 ft_ix);
374                 if (err)
375                         goto err_del_ai;
376
377                 ai->tt_vec |= BIT(MLX5E_TT_IPV6_TCP);
378         }
379
380         return 0;
381
382 err_del_ai:
383         mlx5e_del_eth_addr_from_flow_table(priv, ai);
384
385         return err;
386 }
387
388 static int mlx5e_add_eth_addr_rule(struct mlx5e_priv *priv,
389                                    struct mlx5e_eth_addr_info *ai, int type)
390 {
391         u32 *flow_context;
392         u32 *match_criteria;
393         int err;
394
395         flow_context   = mlx5_vzalloc(MLX5_ST_SZ_BYTES(flow_context) +
396                                       MLX5_ST_SZ_BYTES(dest_format_struct));
397         match_criteria = mlx5_vzalloc(MLX5_ST_SZ_BYTES(fte_match_param));
398         if (!flow_context || !match_criteria) {
399                 netdev_err(priv->netdev, "%s: alloc failed\n", __func__);
400                 err = -ENOMEM;
401                 goto add_eth_addr_rule_out;
402         }
403
404         err = __mlx5e_add_eth_addr_rule(priv, ai, type, flow_context,
405                                         match_criteria);
406         if (err)
407                 netdev_err(priv->netdev, "%s: failed\n", __func__);
408
409 add_eth_addr_rule_out:
410         kvfree(match_criteria);
411         kvfree(flow_context);
412         return err;
413 }
414
415 enum mlx5e_vlan_rule_type {
416         MLX5E_VLAN_RULE_TYPE_UNTAGGED,
417         MLX5E_VLAN_RULE_TYPE_ANY_VID,
418         MLX5E_VLAN_RULE_TYPE_MATCH_VID,
419 };
420
421 static int mlx5e_add_vlan_rule(struct mlx5e_priv *priv,
422                                enum mlx5e_vlan_rule_type rule_type, u16 vid)
423 {
424         u8 match_criteria_enable = 0;
425         u32 *flow_context;
426         void *match_value;
427         void *dest;
428         u32 *match_criteria;
429         u32 *ft_ix;
430         int err;
431
432         flow_context   = mlx5_vzalloc(MLX5_ST_SZ_BYTES(flow_context) +
433                                       MLX5_ST_SZ_BYTES(dest_format_struct));
434         match_criteria = mlx5_vzalloc(MLX5_ST_SZ_BYTES(fte_match_param));
435         if (!flow_context || !match_criteria) {
436                 netdev_err(priv->netdev, "%s: alloc failed\n", __func__);
437                 err = -ENOMEM;
438                 goto add_vlan_rule_out;
439         }
440         match_value = MLX5_ADDR_OF(flow_context, flow_context, match_value);
441         dest = MLX5_ADDR_OF(flow_context, flow_context, destination);
442
443         MLX5_SET(flow_context, flow_context, action,
444                  MLX5_FLOW_CONTEXT_ACTION_FWD_DEST);
445         MLX5_SET(flow_context, flow_context, destination_list_size, 1);
446         MLX5_SET(dest_format_struct, dest, destination_type,
447                  MLX5_FLOW_CONTEXT_DEST_TYPE_FLOW_TABLE);
448         MLX5_SET(dest_format_struct, dest, destination_id,
449                  mlx5_get_flow_table_id(priv->ft.main));
450
451         match_criteria_enable = MLX5_MATCH_OUTER_HEADERS;
452         MLX5_SET_TO_ONES(fte_match_param, match_criteria,
453                          outer_headers.vlan_tag);
454
455         switch (rule_type) {
456         case MLX5E_VLAN_RULE_TYPE_UNTAGGED:
457                 ft_ix = &priv->vlan.untagged_rule_ft_ix;
458                 break;
459         case MLX5E_VLAN_RULE_TYPE_ANY_VID:
460                 ft_ix = &priv->vlan.any_vlan_rule_ft_ix;
461                 MLX5_SET(fte_match_param, match_value, outer_headers.vlan_tag,
462                          1);
463                 break;
464         default: /* MLX5E_VLAN_RULE_TYPE_MATCH_VID */
465                 ft_ix = &priv->vlan.active_vlans_ft_ix[vid];
466                 MLX5_SET(fte_match_param, match_value, outer_headers.vlan_tag,
467                          1);
468                 MLX5_SET_TO_ONES(fte_match_param, match_criteria,
469                                  outer_headers.first_vid);
470                 MLX5_SET(fte_match_param, match_value, outer_headers.first_vid,
471                          vid);
472                 break;
473         }
474
475         err = mlx5_add_flow_table_entry(priv->ft.vlan, match_criteria_enable,
476                                         match_criteria, flow_context, ft_ix);
477         if (err)
478                 netdev_err(priv->netdev, "%s: failed\n", __func__);
479
480 add_vlan_rule_out:
481         kvfree(match_criteria);
482         kvfree(flow_context);
483         return err;
484 }
485
486 static void mlx5e_del_vlan_rule(struct mlx5e_priv *priv,
487                                 enum mlx5e_vlan_rule_type rule_type, u16 vid)
488 {
489         switch (rule_type) {
490         case MLX5E_VLAN_RULE_TYPE_UNTAGGED:
491                 mlx5_del_flow_table_entry(priv->ft.vlan,
492                                           priv->vlan.untagged_rule_ft_ix);
493                 break;
494         case MLX5E_VLAN_RULE_TYPE_ANY_VID:
495                 mlx5_del_flow_table_entry(priv->ft.vlan,
496                                           priv->vlan.any_vlan_rule_ft_ix);
497                 break;
498         case MLX5E_VLAN_RULE_TYPE_MATCH_VID:
499                 mlx5_del_flow_table_entry(priv->ft.vlan,
500                                           priv->vlan.active_vlans_ft_ix[vid]);
501                 break;
502         }
503 }
504
505 void mlx5e_enable_vlan_filter(struct mlx5e_priv *priv)
506 {
507         WARN_ON(!mutex_is_locked(&priv->state_lock));
508
509         if (priv->vlan.filter_disabled) {
510                 priv->vlan.filter_disabled = false;
511                 if (test_bit(MLX5E_STATE_OPENED, &priv->state))
512                         mlx5e_del_vlan_rule(priv, MLX5E_VLAN_RULE_TYPE_ANY_VID,
513                                             0);
514         }
515 }
516
517 void mlx5e_disable_vlan_filter(struct mlx5e_priv *priv)
518 {
519         WARN_ON(!mutex_is_locked(&priv->state_lock));
520
521         if (!priv->vlan.filter_disabled) {
522                 priv->vlan.filter_disabled = true;
523                 if (test_bit(MLX5E_STATE_OPENED, &priv->state))
524                         mlx5e_add_vlan_rule(priv, MLX5E_VLAN_RULE_TYPE_ANY_VID,
525                                             0);
526         }
527 }
528
529 int mlx5e_vlan_rx_add_vid(struct net_device *dev, __always_unused __be16 proto,
530                           u16 vid)
531 {
532         struct mlx5e_priv *priv = netdev_priv(dev);
533         int err = 0;
534
535         mutex_lock(&priv->state_lock);
536
537         set_bit(vid, priv->vlan.active_vlans);
538         if (test_bit(MLX5E_STATE_OPENED, &priv->state))
539                 err = mlx5e_add_vlan_rule(priv, MLX5E_VLAN_RULE_TYPE_MATCH_VID,
540                                           vid);
541
542         mutex_unlock(&priv->state_lock);
543
544         return err;
545 }
546
547 int mlx5e_vlan_rx_kill_vid(struct net_device *dev, __always_unused __be16 proto,
548                            u16 vid)
549 {
550         struct mlx5e_priv *priv = netdev_priv(dev);
551
552         mutex_lock(&priv->state_lock);
553
554         clear_bit(vid, priv->vlan.active_vlans);
555         if (test_bit(MLX5E_STATE_OPENED, &priv->state))
556                 mlx5e_del_vlan_rule(priv, MLX5E_VLAN_RULE_TYPE_MATCH_VID, vid);
557
558         mutex_unlock(&priv->state_lock);
559
560         return 0;
561 }
562
563 int mlx5e_add_all_vlan_rules(struct mlx5e_priv *priv)
564 {
565         u16 vid;
566         int err;
567
568         for_each_set_bit(vid, priv->vlan.active_vlans, VLAN_N_VID) {
569                 err = mlx5e_add_vlan_rule(priv, MLX5E_VLAN_RULE_TYPE_MATCH_VID,
570                                           vid);
571                 if (err)
572                         return err;
573         }
574
575         err = mlx5e_add_vlan_rule(priv, MLX5E_VLAN_RULE_TYPE_UNTAGGED, 0);
576         if (err)
577                 return err;
578
579         if (priv->vlan.filter_disabled) {
580                 err = mlx5e_add_vlan_rule(priv, MLX5E_VLAN_RULE_TYPE_ANY_VID,
581                                           0);
582                 if (err)
583                         return err;
584         }
585
586         return 0;
587 }
588
589 void mlx5e_del_all_vlan_rules(struct mlx5e_priv *priv)
590 {
591         u16 vid;
592
593         if (priv->vlan.filter_disabled)
594                 mlx5e_del_vlan_rule(priv, MLX5E_VLAN_RULE_TYPE_ANY_VID, 0);
595
596         mlx5e_del_vlan_rule(priv, MLX5E_VLAN_RULE_TYPE_UNTAGGED, 0);
597
598         for_each_set_bit(vid, priv->vlan.active_vlans, VLAN_N_VID)
599                 mlx5e_del_vlan_rule(priv, MLX5E_VLAN_RULE_TYPE_MATCH_VID, vid);
600 }
601
602 #define mlx5e_for_each_hash_node(hn, tmp, hash, i) \
603         for (i = 0; i < MLX5E_ETH_ADDR_HASH_SIZE; i++) \
604                 hlist_for_each_entry_safe(hn, tmp, &hash[i], hlist)
605
606 static void mlx5e_execute_action(struct mlx5e_priv *priv,
607                                  struct mlx5e_eth_addr_hash_node *hn)
608 {
609         switch (hn->action) {
610         case MLX5E_ACTION_ADD:
611                 mlx5e_add_eth_addr_rule(priv, &hn->ai, MLX5E_FULLMATCH);
612                 hn->action = MLX5E_ACTION_NONE;
613                 break;
614
615         case MLX5E_ACTION_DEL:
616                 mlx5e_del_eth_addr_from_flow_table(priv, &hn->ai);
617                 mlx5e_del_eth_addr_from_hash(hn);
618                 break;
619         }
620 }
621
622 static void mlx5e_sync_netdev_addr(struct mlx5e_priv *priv)
623 {
624         struct net_device *netdev = priv->netdev;
625         struct netdev_hw_addr *ha;
626
627         netif_addr_lock_bh(netdev);
628
629         mlx5e_add_eth_addr_to_hash(priv->eth_addr.netdev_uc,
630                                    priv->netdev->dev_addr);
631
632         netdev_for_each_uc_addr(ha, netdev)
633                 mlx5e_add_eth_addr_to_hash(priv->eth_addr.netdev_uc, ha->addr);
634
635         netdev_for_each_mc_addr(ha, netdev)
636                 mlx5e_add_eth_addr_to_hash(priv->eth_addr.netdev_mc, ha->addr);
637
638         netif_addr_unlock_bh(netdev);
639 }
640
641 static void mlx5e_apply_netdev_addr(struct mlx5e_priv *priv)
642 {
643         struct mlx5e_eth_addr_hash_node *hn;
644         struct hlist_node *tmp;
645         int i;
646
647         mlx5e_for_each_hash_node(hn, tmp, priv->eth_addr.netdev_uc, i)
648                 mlx5e_execute_action(priv, hn);
649
650         mlx5e_for_each_hash_node(hn, tmp, priv->eth_addr.netdev_mc, i)
651                 mlx5e_execute_action(priv, hn);
652 }
653
654 static void mlx5e_handle_netdev_addr(struct mlx5e_priv *priv)
655 {
656         struct mlx5e_eth_addr_hash_node *hn;
657         struct hlist_node *tmp;
658         int i;
659
660         mlx5e_for_each_hash_node(hn, tmp, priv->eth_addr.netdev_uc, i)
661                 hn->action = MLX5E_ACTION_DEL;
662         mlx5e_for_each_hash_node(hn, tmp, priv->eth_addr.netdev_mc, i)
663                 hn->action = MLX5E_ACTION_DEL;
664
665         if (test_bit(MLX5E_STATE_OPENED, &priv->state))
666                 mlx5e_sync_netdev_addr(priv);
667
668         mlx5e_apply_netdev_addr(priv);
669 }
670
671 void mlx5e_set_rx_mode_core(struct mlx5e_priv *priv)
672 {
673         struct mlx5e_eth_addr_db *ea = &priv->eth_addr;
674         struct net_device *ndev = priv->netdev;
675
676         bool rx_mode_enable   = test_bit(MLX5E_STATE_OPENED, &priv->state);
677         bool promisc_enabled   = rx_mode_enable && (ndev->flags & IFF_PROMISC);
678         bool allmulti_enabled  = rx_mode_enable && (ndev->flags & IFF_ALLMULTI);
679         bool broadcast_enabled = rx_mode_enable;
680
681         bool enable_promisc    = !ea->promisc_enabled   &&  promisc_enabled;
682         bool disable_promisc   =  ea->promisc_enabled   && !promisc_enabled;
683         bool enable_allmulti   = !ea->allmulti_enabled  &&  allmulti_enabled;
684         bool disable_allmulti  =  ea->allmulti_enabled  && !allmulti_enabled;
685         bool enable_broadcast  = !ea->broadcast_enabled &&  broadcast_enabled;
686         bool disable_broadcast =  ea->broadcast_enabled && !broadcast_enabled;
687
688         if (enable_promisc)
689                 mlx5e_add_eth_addr_rule(priv, &ea->promisc, MLX5E_PROMISC);
690         if (enable_allmulti)
691                 mlx5e_add_eth_addr_rule(priv, &ea->allmulti, MLX5E_ALLMULTI);
692         if (enable_broadcast)
693                 mlx5e_add_eth_addr_rule(priv, &ea->broadcast, MLX5E_FULLMATCH);
694
695         mlx5e_handle_netdev_addr(priv);
696
697         if (disable_broadcast)
698                 mlx5e_del_eth_addr_from_flow_table(priv, &ea->broadcast);
699         if (disable_allmulti)
700                 mlx5e_del_eth_addr_from_flow_table(priv, &ea->allmulti);
701         if (disable_promisc)
702                 mlx5e_del_eth_addr_from_flow_table(priv, &ea->promisc);
703
704         ea->promisc_enabled   = promisc_enabled;
705         ea->allmulti_enabled  = allmulti_enabled;
706         ea->broadcast_enabled = broadcast_enabled;
707 }
708
709 void mlx5e_set_rx_mode_work(struct work_struct *work)
710 {
711         struct mlx5e_priv *priv = container_of(work, struct mlx5e_priv,
712                                                set_rx_mode_work);
713
714         mutex_lock(&priv->state_lock);
715         if (test_bit(MLX5E_STATE_OPENED, &priv->state))
716                 mlx5e_set_rx_mode_core(priv);
717         mutex_unlock(&priv->state_lock);
718 }
719
720 void mlx5e_init_eth_addr(struct mlx5e_priv *priv)
721 {
722         ether_addr_copy(priv->eth_addr.broadcast.addr, priv->netdev->broadcast);
723 }
724
725 static int mlx5e_create_main_flow_table(struct mlx5e_priv *priv)
726 {
727         struct mlx5_flow_table_group *g;
728         u8 *dmac;
729
730         g = kcalloc(9, sizeof(*g), GFP_KERNEL);
731         if (!g)
732                 return -ENOMEM;
733
734         g[0].log_sz = 2;
735         g[0].match_criteria_enable = MLX5_MATCH_OUTER_HEADERS;
736         MLX5_SET_TO_ONES(fte_match_param, g[0].match_criteria,
737                          outer_headers.ethertype);
738         MLX5_SET_TO_ONES(fte_match_param, g[0].match_criteria,
739                          outer_headers.ip_protocol);
740
741         g[1].log_sz = 1;
742         g[1].match_criteria_enable = MLX5_MATCH_OUTER_HEADERS;
743         MLX5_SET_TO_ONES(fte_match_param, g[1].match_criteria,
744                          outer_headers.ethertype);
745
746         g[2].log_sz = 0;
747
748         g[3].log_sz = 14;
749         g[3].match_criteria_enable = MLX5_MATCH_OUTER_HEADERS;
750         dmac = MLX5_ADDR_OF(fte_match_param, g[3].match_criteria,
751                             outer_headers.dmac_47_16);
752         memset(dmac, 0xff, ETH_ALEN);
753         MLX5_SET_TO_ONES(fte_match_param, g[3].match_criteria,
754                          outer_headers.ethertype);
755         MLX5_SET_TO_ONES(fte_match_param, g[3].match_criteria,
756                          outer_headers.ip_protocol);
757
758         g[4].log_sz = 13;
759         g[4].match_criteria_enable = MLX5_MATCH_OUTER_HEADERS;
760         dmac = MLX5_ADDR_OF(fte_match_param, g[4].match_criteria,
761                             outer_headers.dmac_47_16);
762         memset(dmac, 0xff, ETH_ALEN);
763         MLX5_SET_TO_ONES(fte_match_param, g[4].match_criteria,
764                          outer_headers.ethertype);
765
766         g[5].log_sz = 11;
767         g[5].match_criteria_enable = MLX5_MATCH_OUTER_HEADERS;
768         dmac = MLX5_ADDR_OF(fte_match_param, g[5].match_criteria,
769                             outer_headers.dmac_47_16);
770         memset(dmac, 0xff, ETH_ALEN);
771
772         g[6].log_sz = 2;
773         g[6].match_criteria_enable = MLX5_MATCH_OUTER_HEADERS;
774         dmac = MLX5_ADDR_OF(fte_match_param, g[6].match_criteria,
775                             outer_headers.dmac_47_16);
776         dmac[0] = 0x01;
777         MLX5_SET_TO_ONES(fte_match_param, g[6].match_criteria,
778                          outer_headers.ethertype);
779         MLX5_SET_TO_ONES(fte_match_param, g[6].match_criteria,
780                          outer_headers.ip_protocol);
781
782         g[7].log_sz = 1;
783         g[7].match_criteria_enable = MLX5_MATCH_OUTER_HEADERS;
784         dmac = MLX5_ADDR_OF(fte_match_param, g[7].match_criteria,
785                             outer_headers.dmac_47_16);
786         dmac[0] = 0x01;
787         MLX5_SET_TO_ONES(fte_match_param, g[7].match_criteria,
788                          outer_headers.ethertype);
789
790         g[8].log_sz = 0;
791         g[8].match_criteria_enable = MLX5_MATCH_OUTER_HEADERS;
792         dmac = MLX5_ADDR_OF(fte_match_param, g[8].match_criteria,
793                             outer_headers.dmac_47_16);
794         dmac[0] = 0x01;
795         priv->ft.main = mlx5_create_flow_table(priv->mdev, 1,
796                                                MLX5_FLOW_TABLE_TYPE_NIC_RCV,
797                                                9, g);
798         kfree(g);
799
800         return priv->ft.main ? 0 : -ENOMEM;
801 }
802
803 static void mlx5e_destroy_main_flow_table(struct mlx5e_priv *priv)
804 {
805         mlx5_destroy_flow_table(priv->ft.main);
806 }
807
808 static int mlx5e_create_vlan_flow_table(struct mlx5e_priv *priv)
809 {
810         struct mlx5_flow_table_group *g;
811
812         g = kcalloc(2, sizeof(*g), GFP_KERNEL);
813         if (!g)
814                 return -ENOMEM;
815
816         g[0].log_sz = 12;
817         g[0].match_criteria_enable = MLX5_MATCH_OUTER_HEADERS;
818         MLX5_SET_TO_ONES(fte_match_param, g[0].match_criteria,
819                          outer_headers.vlan_tag);
820         MLX5_SET_TO_ONES(fte_match_param, g[0].match_criteria,
821                          outer_headers.first_vid);
822
823         /* untagged + any vlan id */
824         g[1].log_sz = 1;
825         g[1].match_criteria_enable = MLX5_MATCH_OUTER_HEADERS;
826         MLX5_SET_TO_ONES(fte_match_param, g[1].match_criteria,
827                          outer_headers.vlan_tag);
828
829         priv->ft.vlan = mlx5_create_flow_table(priv->mdev, 0,
830                                                MLX5_FLOW_TABLE_TYPE_NIC_RCV,
831                                                2, g);
832
833         kfree(g);
834         return priv->ft.vlan ? 0 : -ENOMEM;
835 }
836
837 static void mlx5e_destroy_vlan_flow_table(struct mlx5e_priv *priv)
838 {
839         mlx5_destroy_flow_table(priv->ft.vlan);
840 }
841
842 int mlx5e_open_flow_table(struct mlx5e_priv *priv)
843 {
844         int err;
845
846         err = mlx5e_create_main_flow_table(priv);
847         if (err)
848                 return err;
849
850         err = mlx5e_create_vlan_flow_table(priv);
851         if (err)
852                 goto err_destroy_main_flow_table;
853
854         return 0;
855
856 err_destroy_main_flow_table:
857         mlx5e_destroy_main_flow_table(priv);
858
859         return err;
860 }
861
862 void mlx5e_close_flow_table(struct mlx5e_priv *priv)
863 {
864         mlx5e_destroy_vlan_flow_table(priv);
865         mlx5e_destroy_main_flow_table(priv);
866 }