1dc7e38acSHans Petter Selasky /*-
2e059c120SHans Petter Selasky * Copyright (c) 2015-2021 Mellanox Technologies. All rights reserved.
3dc7e38acSHans Petter Selasky *
4dc7e38acSHans Petter Selasky * Redistribution and use in source and binary forms, with or without
5dc7e38acSHans Petter Selasky * modification, are permitted provided that the following conditions
6dc7e38acSHans Petter Selasky * are met:
7dc7e38acSHans Petter Selasky * 1. Redistributions of source code must retain the above copyright
8dc7e38acSHans Petter Selasky * notice, this list of conditions and the following disclaimer.
9dc7e38acSHans Petter Selasky * 2. Redistributions in binary form must reproduce the above copyright
10dc7e38acSHans Petter Selasky * notice, this list of conditions and the following disclaimer in the
11dc7e38acSHans Petter Selasky * documentation and/or other materials provided with the distribution.
12dc7e38acSHans Petter Selasky *
13dc7e38acSHans Petter Selasky * THIS SOFTWARE IS PROVIDED BY AUTHOR AND CONTRIBUTORS `AS IS' AND
14dc7e38acSHans Petter Selasky * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
15dc7e38acSHans Petter Selasky * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
16dc7e38acSHans Petter Selasky * ARE DISCLAIMED. IN NO EVENT SHALL AUTHOR OR CONTRIBUTORS BE LIABLE
17dc7e38acSHans Petter Selasky * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
18dc7e38acSHans Petter Selasky * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
19dc7e38acSHans Petter Selasky * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
20dc7e38acSHans Petter Selasky * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
21dc7e38acSHans Petter Selasky * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
22dc7e38acSHans Petter Selasky * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
23dc7e38acSHans Petter Selasky * SUCH DAMAGE.
24dc7e38acSHans Petter Selasky */
25dc7e38acSHans Petter Selasky
26b984b956SKonstantin Belousov #include "opt_rss.h"
27b984b956SKonstantin Belousov #include "opt_ratelimit.h"
28b984b956SKonstantin Belousov
2989918a23SKonstantin Belousov #include <dev/mlx5/mlx5_en/en.h>
302787f8c3SKonstantin Belousov #include <dev/mlx5/mlx5_accel/ipsec.h>
31dc7e38acSHans Petter Selasky
32dc7e38acSHans Petter Selasky #include <linux/list.h>
335a93b4cdSHans Petter Selasky #include <dev/mlx5/fs.h>
3466b38bfeSHans Petter Selasky #include <dev/mlx5/mpfs.h>
352c0ade80SHans Petter Selasky #include <dev/mlx5/mlx5_core/fs_tcp.h>
36aa9f073cSHans Petter Selasky
37b1277d42SKonstantin Belousov /*
38b1277d42SKonstantin Belousov * The flow tables with rules define the packet processing on receive.
392c0ade80SHans Petter Selasky * Currently the following structure is set up to handle different
402c0ade80SHans Petter Selasky * offloads like TLS RX offload, VLAN decapsulation, packet
412c0ade80SHans Petter Selasky * classification, RSS hashing, VxLAN checksum offloading:
42b1277d42SKonstantin Belousov *
432c0ade80SHans Petter Selasky * +=========+ +=========+ +=================+
442c0ade80SHans Petter Selasky * |TCP/IPv4 | |TCP/IPv4 | |TCP/IPv4 Match |
452c0ade80SHans Petter Selasky * |Flowtable|------>| |----->|Outer Proto Match|=====> TLS TIR n
462c0ade80SHans Petter Selasky * | | |Catch-all|\ | |
472c0ade80SHans Petter Selasky * +=========+ +=========+| +=================+
482c0ade80SHans Petter Selasky * |
492c0ade80SHans Petter Selasky * +------------------------+
502c0ade80SHans Petter Selasky * V
512c0ade80SHans Petter Selasky * +=========+ +=========+ +=================+
522c0ade80SHans Petter Selasky * |TCP/IPv6 | |TCP/IPv6 | |TCP/IPv6 Match |
532c0ade80SHans Petter Selasky * |Flowtable|------>| |----->|Outer Proto Match|=====> TLS TIR n
542c0ade80SHans Petter Selasky * | | |Catch-all|\ | |
552c0ade80SHans Petter Selasky * +=========+ +=========+| +=================+
562c0ade80SHans Petter Selasky * |
572c0ade80SHans Petter Selasky * +------------------------+
582c0ade80SHans Petter Selasky * V
59b1277d42SKonstantin Belousov * +=========+ +=========+ +=================+
60b1277d42SKonstantin Belousov * |VLAN ft: | |VxLAN | |VxLAN Main |
61b1277d42SKonstantin Belousov * |CTAG/STAG|------>| VNI|----->|Inner Proto Match|=====> Inner TIR n
62b1277d42SKonstantin Belousov * |VID/noVID|/ |Catch-all|\ | |
63b1277d42SKonstantin Belousov * +=========+ +=========+| +=================+
64b1277d42SKonstantin Belousov * |
65b1277d42SKonstantin Belousov * |
66b1277d42SKonstantin Belousov * |
67b1277d42SKonstantin Belousov * v
68b1277d42SKonstantin Belousov * +=================+
69b1277d42SKonstantin Belousov * |Main |
70b1277d42SKonstantin Belousov * |Outer Proto Match|=====> TIR n
71b1277d42SKonstantin Belousov * | |
72b1277d42SKonstantin Belousov * +=================+
73b1277d42SKonstantin Belousov *
74b1277d42SKonstantin Belousov * The path through flow rules directs each packet into an appropriate TIR,
75b1277d42SKonstantin Belousov * according to the:
76b1277d42SKonstantin Belousov * - VLAN encapsulation
77b1277d42SKonstantin Belousov * - Outer protocol
78b1277d42SKonstantin Belousov * - Presence of inner protocol
79b1277d42SKonstantin Belousov */
80b1277d42SKonstantin Belousov
815a93b4cdSHans Petter Selasky #define MLX5_SET_CFG(p, f, v) MLX5_SET(create_flow_group_in, p, f, v)
82dc7e38acSHans Petter Selasky
83dc7e38acSHans Petter Selasky enum {
84dc7e38acSHans Petter Selasky MLX5E_FULLMATCH = 0,
85dc7e38acSHans Petter Selasky MLX5E_ALLMULTI = 1,
86dc7e38acSHans Petter Selasky MLX5E_PROMISC = 2,
87dc7e38acSHans Petter Selasky };
88dc7e38acSHans Petter Selasky
89dc7e38acSHans Petter Selasky enum {
90dc7e38acSHans Petter Selasky MLX5E_UC = 0,
91dc7e38acSHans Petter Selasky MLX5E_MC_IPV4 = 1,
92dc7e38acSHans Petter Selasky MLX5E_MC_IPV6 = 2,
93dc7e38acSHans Petter Selasky MLX5E_MC_OTHER = 3,
94dc7e38acSHans Petter Selasky };
95dc7e38acSHans Petter Selasky
96dc7e38acSHans Petter Selasky enum {
97dc7e38acSHans Petter Selasky MLX5E_ACTION_NONE = 0,
98dc7e38acSHans Petter Selasky MLX5E_ACTION_ADD = 1,
99dc7e38acSHans Petter Selasky MLX5E_ACTION_DEL = 2,
100dc7e38acSHans Petter Selasky };
101dc7e38acSHans Petter Selasky
102dc7e38acSHans Petter Selasky struct mlx5e_eth_addr_hash_node {
103dc7e38acSHans Petter Selasky LIST_ENTRY(mlx5e_eth_addr_hash_node) hlist;
104dc7e38acSHans Petter Selasky u8 action;
10566b38bfeSHans Petter Selasky u32 mpfs_index;
106dc7e38acSHans Petter Selasky struct mlx5e_eth_addr_info ai;
107dc7e38acSHans Petter Selasky };
108dc7e38acSHans Petter Selasky
109e059c120SHans Petter Selasky static void mlx5e_del_all_vlan_rules(struct mlx5e_priv *);
110e059c120SHans Petter Selasky
111dc7e38acSHans Petter Selasky static inline int
mlx5e_hash_eth_addr(const u8 * addr)112dc7e38acSHans Petter Selasky mlx5e_hash_eth_addr(const u8 * addr)
113dc7e38acSHans Petter Selasky {
114dc7e38acSHans Petter Selasky return (addr[5]);
115dc7e38acSHans Petter Selasky }
116dc7e38acSHans Petter Selasky
11766b38bfeSHans Petter Selasky static bool
mlx5e_add_eth_addr_to_hash(struct mlx5e_eth_addr_hash_head * hash,struct mlx5e_eth_addr_hash_node * hn_new)118dc7e38acSHans Petter Selasky mlx5e_add_eth_addr_to_hash(struct mlx5e_eth_addr_hash_head *hash,
11966b38bfeSHans Petter Selasky struct mlx5e_eth_addr_hash_node *hn_new)
120dc7e38acSHans Petter Selasky {
121dc7e38acSHans Petter Selasky struct mlx5e_eth_addr_hash_node *hn;
12266b38bfeSHans Petter Selasky u32 ix = mlx5e_hash_eth_addr(hn_new->ai.addr);
123dc7e38acSHans Petter Selasky
124dc7e38acSHans Petter Selasky LIST_FOREACH(hn, &hash[ix], hlist) {
12566b38bfeSHans Petter Selasky if (bcmp(hn->ai.addr, hn_new->ai.addr, ETHER_ADDR_LEN) == 0) {
126dc7e38acSHans Petter Selasky if (hn->action == MLX5E_ACTION_DEL)
127dc7e38acSHans Petter Selasky hn->action = MLX5E_ACTION_NONE;
12866b38bfeSHans Petter Selasky free(hn_new, M_MLX5EN);
12966b38bfeSHans Petter Selasky return (false);
130dc7e38acSHans Petter Selasky }
131dc7e38acSHans Petter Selasky }
13266b38bfeSHans Petter Selasky LIST_INSERT_HEAD(&hash[ix], hn_new, hlist);
13366b38bfeSHans Petter Selasky return (true);
134dc7e38acSHans Petter Selasky }
135dc7e38acSHans Petter Selasky
136dc7e38acSHans Petter Selasky static void
mlx5e_del_eth_addr_from_hash(struct mlx5e_eth_addr_hash_node * hn)137dc7e38acSHans Petter Selasky mlx5e_del_eth_addr_from_hash(struct mlx5e_eth_addr_hash_node *hn)
138dc7e38acSHans Petter Selasky {
139dc7e38acSHans Petter Selasky LIST_REMOVE(hn, hlist);
140dc7e38acSHans Petter Selasky free(hn, M_MLX5EN);
141dc7e38acSHans Petter Selasky }
142dc7e38acSHans Petter Selasky
143dc7e38acSHans Petter Selasky static void
mlx5e_del_eth_addr_from_flow_table(struct mlx5e_priv * priv,struct mlx5e_eth_addr_info * ai)144dc7e38acSHans Petter Selasky mlx5e_del_eth_addr_from_flow_table(struct mlx5e_priv *priv,
145dc7e38acSHans Petter Selasky struct mlx5e_eth_addr_info *ai)
146dc7e38acSHans Petter Selasky {
147e23731dbSKonstantin Belousov mlx5_del_flow_rules(&ai->ft_rule[MLX5E_TT_IPV6_IPSEC_ESP]);
148e23731dbSKonstantin Belousov mlx5_del_flow_rules(&ai->ft_rule[MLX5E_TT_IPV4_IPSEC_ESP]);
149e23731dbSKonstantin Belousov mlx5_del_flow_rules(&ai->ft_rule[MLX5E_TT_IPV6_IPSEC_AH]);
150e23731dbSKonstantin Belousov mlx5_del_flow_rules(&ai->ft_rule[MLX5E_TT_IPV4_IPSEC_AH]);
151e23731dbSKonstantin Belousov mlx5_del_flow_rules(&ai->ft_rule[MLX5E_TT_IPV6_TCP]);
152e23731dbSKonstantin Belousov mlx5_del_flow_rules(&ai->ft_rule[MLX5E_TT_IPV4_TCP]);
153e23731dbSKonstantin Belousov mlx5_del_flow_rules(&ai->ft_rule[MLX5E_TT_IPV6_UDP]);
154e23731dbSKonstantin Belousov mlx5_del_flow_rules(&ai->ft_rule[MLX5E_TT_IPV4_UDP]);
155e23731dbSKonstantin Belousov mlx5_del_flow_rules(&ai->ft_rule[MLX5E_TT_IPV6]);
156e23731dbSKonstantin Belousov mlx5_del_flow_rules(&ai->ft_rule[MLX5E_TT_IPV4]);
157e23731dbSKonstantin Belousov mlx5_del_flow_rules(&ai->ft_rule[MLX5E_TT_ANY]);
158dc7e38acSHans Petter Selasky }
159dc7e38acSHans Petter Selasky
160dc7e38acSHans Petter Selasky static int
mlx5e_get_eth_addr_type(const u8 * addr)161dc7e38acSHans Petter Selasky mlx5e_get_eth_addr_type(const u8 * addr)
162dc7e38acSHans Petter Selasky {
163dc7e38acSHans Petter Selasky if (ETHER_IS_MULTICAST(addr) == 0)
164dc7e38acSHans Petter Selasky return (MLX5E_UC);
165dc7e38acSHans Petter Selasky
166dc7e38acSHans Petter Selasky if ((addr[0] == 0x01) &&
167dc7e38acSHans Petter Selasky (addr[1] == 0x00) &&
168dc7e38acSHans Petter Selasky (addr[2] == 0x5e) &&
169dc7e38acSHans Petter Selasky !(addr[3] & 0x80))
170dc7e38acSHans Petter Selasky return (MLX5E_MC_IPV4);
171dc7e38acSHans Petter Selasky
172dc7e38acSHans Petter Selasky if ((addr[0] == 0x33) &&
173dc7e38acSHans Petter Selasky (addr[1] == 0x33))
174dc7e38acSHans Petter Selasky return (MLX5E_MC_IPV6);
175dc7e38acSHans Petter Selasky
176dc7e38acSHans Petter Selasky return (MLX5E_MC_OTHER);
177dc7e38acSHans Petter Selasky }
178dc7e38acSHans Petter Selasky
179dc7e38acSHans Petter Selasky static u32
mlx5e_get_tt_vec(struct mlx5e_eth_addr_info * ai,int type)180dc7e38acSHans Petter Selasky mlx5e_get_tt_vec(struct mlx5e_eth_addr_info *ai, int type)
181dc7e38acSHans Petter Selasky {
182dc7e38acSHans Petter Selasky int eth_addr_type;
183dc7e38acSHans Petter Selasky u32 ret;
184dc7e38acSHans Petter Selasky
185dc7e38acSHans Petter Selasky switch (type) {
186dc7e38acSHans Petter Selasky case MLX5E_FULLMATCH:
187dc7e38acSHans Petter Selasky eth_addr_type = mlx5e_get_eth_addr_type(ai->addr);
188dc7e38acSHans Petter Selasky switch (eth_addr_type) {
189dc7e38acSHans Petter Selasky case MLX5E_UC:
190dc7e38acSHans Petter Selasky ret =
191dc7e38acSHans Petter Selasky (1 << MLX5E_TT_IPV4_TCP) |
192dc7e38acSHans Petter Selasky (1 << MLX5E_TT_IPV6_TCP) |
193dc7e38acSHans Petter Selasky (1 << MLX5E_TT_IPV4_UDP) |
194dc7e38acSHans Petter Selasky (1 << MLX5E_TT_IPV6_UDP) |
195dc7e38acSHans Petter Selasky (1 << MLX5E_TT_IPV4) |
196dc7e38acSHans Petter Selasky (1 << MLX5E_TT_IPV6) |
197dc7e38acSHans Petter Selasky (1 << MLX5E_TT_ANY) |
198dc7e38acSHans Petter Selasky 0;
199dc7e38acSHans Petter Selasky break;
200dc7e38acSHans Petter Selasky
201dc7e38acSHans Petter Selasky case MLX5E_MC_IPV4:
202dc7e38acSHans Petter Selasky ret =
203dc7e38acSHans Petter Selasky (1 << MLX5E_TT_IPV4_UDP) |
204dc7e38acSHans Petter Selasky (1 << MLX5E_TT_IPV4) |
205dc7e38acSHans Petter Selasky 0;
206dc7e38acSHans Petter Selasky break;
207dc7e38acSHans Petter Selasky
208dc7e38acSHans Petter Selasky case MLX5E_MC_IPV6:
209dc7e38acSHans Petter Selasky ret =
210dc7e38acSHans Petter Selasky (1 << MLX5E_TT_IPV6_UDP) |
211dc7e38acSHans Petter Selasky (1 << MLX5E_TT_IPV6) |
212dc7e38acSHans Petter Selasky 0;
213dc7e38acSHans Petter Selasky break;
214dc7e38acSHans Petter Selasky
215dc7e38acSHans Petter Selasky default:
216dc7e38acSHans Petter Selasky ret =
217dc7e38acSHans Petter Selasky (1 << MLX5E_TT_ANY) |
218dc7e38acSHans Petter Selasky 0;
219dc7e38acSHans Petter Selasky break;
220dc7e38acSHans Petter Selasky }
221dc7e38acSHans Petter Selasky break;
222dc7e38acSHans Petter Selasky
223dc7e38acSHans Petter Selasky case MLX5E_ALLMULTI:
224dc7e38acSHans Petter Selasky ret =
225dc7e38acSHans Petter Selasky (1 << MLX5E_TT_IPV4_UDP) |
226dc7e38acSHans Petter Selasky (1 << MLX5E_TT_IPV6_UDP) |
227dc7e38acSHans Petter Selasky (1 << MLX5E_TT_IPV4) |
228dc7e38acSHans Petter Selasky (1 << MLX5E_TT_IPV6) |
229dc7e38acSHans Petter Selasky (1 << MLX5E_TT_ANY) |
230dc7e38acSHans Petter Selasky 0;
231dc7e38acSHans Petter Selasky break;
232dc7e38acSHans Petter Selasky
233dc7e38acSHans Petter Selasky default: /* MLX5E_PROMISC */
234dc7e38acSHans Petter Selasky ret =
235dc7e38acSHans Petter Selasky (1 << MLX5E_TT_IPV4_TCP) |
236dc7e38acSHans Petter Selasky (1 << MLX5E_TT_IPV6_TCP) |
237dc7e38acSHans Petter Selasky (1 << MLX5E_TT_IPV4_UDP) |
238dc7e38acSHans Petter Selasky (1 << MLX5E_TT_IPV6_UDP) |
239dc7e38acSHans Petter Selasky (1 << MLX5E_TT_IPV4) |
240dc7e38acSHans Petter Selasky (1 << MLX5E_TT_IPV6) |
241dc7e38acSHans Petter Selasky (1 << MLX5E_TT_ANY) |
242dc7e38acSHans Petter Selasky 0;
243dc7e38acSHans Petter Selasky break;
244dc7e38acSHans Petter Selasky }
245dc7e38acSHans Petter Selasky
246dc7e38acSHans Petter Selasky return (ret);
247dc7e38acSHans Petter Selasky }
248dc7e38acSHans Petter Selasky
249dc7e38acSHans Petter Selasky static int
mlx5e_add_eth_addr_rule_sub(struct mlx5e_priv * priv,struct mlx5e_eth_addr_info * ai,int type,struct mlx5_flow_spec * spec)250dc7e38acSHans Petter Selasky mlx5e_add_eth_addr_rule_sub(struct mlx5e_priv *priv,
251dc7e38acSHans Petter Selasky struct mlx5e_eth_addr_info *ai, int type,
252e23731dbSKonstantin Belousov struct mlx5_flow_spec *spec)
253dc7e38acSHans Petter Selasky {
25447d93c5cSHans Petter Selasky struct mlx5_flow_destination dest = {};
2555a93b4cdSHans Petter Selasky u8 mc_enable = 0;
256e23731dbSKonstantin Belousov struct mlx5_flow_handle **rule_p;
2575a93b4cdSHans Petter Selasky struct mlx5_flow_table *ft = priv->fts.main.t;
258e23731dbSKonstantin Belousov u8 *mc_dmac = MLX5_ADDR_OF(fte_match_param, spec->match_criteria,
2595a93b4cdSHans Petter Selasky outer_headers.dmac_47_16);
260e23731dbSKonstantin Belousov u8 *mv_dmac = MLX5_ADDR_OF(fte_match_param, spec->match_value,
2615a93b4cdSHans Petter Selasky outer_headers.dmac_47_16);
262dc7e38acSHans Petter Selasky u32 *tirn = priv->tirn;
263dc7e38acSHans Petter Selasky u32 tt_vec;
2645a93b4cdSHans Petter Selasky int err = 0;
265cb054a49SMark Bloch struct mlx5_flow_act flow_act = {
266b762b199SSlava Shwartsman .action = MLX5_FLOW_CONTEXT_ACTION_FWD_DEST,
267cb054a49SMark Bloch };
268e23731dbSKonstantin Belousov u8 *mc;
269e23731dbSKonstantin Belousov u8 *mv;
270dc7e38acSHans Petter Selasky
271e23731dbSKonstantin Belousov mv = (u8 *)spec->match_value;
272e23731dbSKonstantin Belousov mc = (u8 *)spec->match_criteria;
273e23731dbSKonstantin Belousov
274e23731dbSKonstantin Belousov spec->flow_context.flow_tag = MLX5_FS_ETH_FLOW_TAG;
275e23731dbSKonstantin Belousov spec->flow_context.flags = FLOW_CONTEXT_HAS_TAG;
2765a93b4cdSHans Petter Selasky dest.type = MLX5_FLOW_DESTINATION_TYPE_TIR;
277dc7e38acSHans Petter Selasky
278dc7e38acSHans Petter Selasky switch (type) {
279dc7e38acSHans Petter Selasky case MLX5E_FULLMATCH:
2805a93b4cdSHans Petter Selasky mc_enable = MLX5_MATCH_OUTER_HEADERS;
2815a93b4cdSHans Petter Selasky memset(mc_dmac, 0xff, ETH_ALEN);
2825a93b4cdSHans Petter Selasky ether_addr_copy(mv_dmac, ai->addr);
283dc7e38acSHans Petter Selasky break;
284dc7e38acSHans Petter Selasky
285dc7e38acSHans Petter Selasky case MLX5E_ALLMULTI:
2865a93b4cdSHans Petter Selasky mc_enable = MLX5_MATCH_OUTER_HEADERS;
2875a93b4cdSHans Petter Selasky mc_dmac[0] = 0x01;
2885a93b4cdSHans Petter Selasky mv_dmac[0] = 0x01;
289dc7e38acSHans Petter Selasky break;
290dc7e38acSHans Petter Selasky
291dc7e38acSHans Petter Selasky case MLX5E_PROMISC:
292dc7e38acSHans Petter Selasky break;
293dc7e38acSHans Petter Selasky default:
294dc7e38acSHans Petter Selasky break;
295dc7e38acSHans Petter Selasky }
296dc7e38acSHans Petter Selasky
297dc7e38acSHans Petter Selasky tt_vec = mlx5e_get_tt_vec(ai, type);
298dc7e38acSHans Petter Selasky
299e23731dbSKonstantin Belousov spec->match_criteria_enable = mc_enable;
3005a93b4cdSHans Petter Selasky if (tt_vec & BIT(MLX5E_TT_ANY)) {
3015a93b4cdSHans Petter Selasky rule_p = &ai->ft_rule[MLX5E_TT_ANY];
3025a93b4cdSHans Petter Selasky dest.tir_num = tirn[MLX5E_TT_ANY];
303e23731dbSKonstantin Belousov *rule_p = mlx5_add_flow_rules(ft, spec, &flow_act, &dest, 1);
3045a93b4cdSHans Petter Selasky if (IS_ERR_OR_NULL(*rule_p))
3055a93b4cdSHans Petter Selasky goto err_del_ai;
306dc7e38acSHans Petter Selasky }
307dc7e38acSHans Petter Selasky
3085a93b4cdSHans Petter Selasky mc_enable = MLX5_MATCH_OUTER_HEADERS;
3095a93b4cdSHans Petter Selasky MLX5_SET_TO_ONES(fte_match_param, mc, outer_headers.ethertype);
310dc7e38acSHans Petter Selasky
311e23731dbSKonstantin Belousov spec->match_criteria_enable = mc_enable;
3125a93b4cdSHans Petter Selasky if (tt_vec & BIT(MLX5E_TT_IPV4)) {
3135a93b4cdSHans Petter Selasky rule_p = &ai->ft_rule[MLX5E_TT_IPV4];
3145a93b4cdSHans Petter Selasky dest.tir_num = tirn[MLX5E_TT_IPV4];
3155a93b4cdSHans Petter Selasky MLX5_SET(fte_match_param, mv, outer_headers.ethertype,
316dc7e38acSHans Petter Selasky ETHERTYPE_IP);
317e23731dbSKonstantin Belousov *rule_p = mlx5_add_flow_rules(ft, spec, &flow_act, &dest, 1);
3185a93b4cdSHans Petter Selasky if (IS_ERR_OR_NULL(*rule_p))
3195a93b4cdSHans Petter Selasky goto err_del_ai;
320dc7e38acSHans Petter Selasky }
321dc7e38acSHans Petter Selasky
3225a93b4cdSHans Petter Selasky if (tt_vec & BIT(MLX5E_TT_IPV6)) {
3235a93b4cdSHans Petter Selasky rule_p = &ai->ft_rule[MLX5E_TT_IPV6];
3245a93b4cdSHans Petter Selasky dest.tir_num = tirn[MLX5E_TT_IPV6];
3255a93b4cdSHans Petter Selasky MLX5_SET(fte_match_param, mv, outer_headers.ethertype,
326dc7e38acSHans Petter Selasky ETHERTYPE_IPV6);
327e23731dbSKonstantin Belousov *rule_p = mlx5_add_flow_rules(ft, spec, &flow_act, &dest, 1);
3285a93b4cdSHans Petter Selasky if (IS_ERR_OR_NULL(*rule_p))
3295a93b4cdSHans Petter Selasky goto err_del_ai;
3305a93b4cdSHans Petter Selasky }
3315a93b4cdSHans Petter Selasky
3325a93b4cdSHans Petter Selasky MLX5_SET_TO_ONES(fte_match_param, mc, outer_headers.ip_protocol);
3335a93b4cdSHans Petter Selasky MLX5_SET(fte_match_param, mv, outer_headers.ip_protocol, IPPROTO_UDP);
3345a93b4cdSHans Petter Selasky
3355a93b4cdSHans Petter Selasky if (tt_vec & BIT(MLX5E_TT_IPV4_UDP)) {
3365a93b4cdSHans Petter Selasky rule_p = &ai->ft_rule[MLX5E_TT_IPV4_UDP];
3375a93b4cdSHans Petter Selasky dest.tir_num = tirn[MLX5E_TT_IPV4_UDP];
3385a93b4cdSHans Petter Selasky MLX5_SET(fte_match_param, mv, outer_headers.ethertype,
3395a93b4cdSHans Petter Selasky ETHERTYPE_IP);
340e23731dbSKonstantin Belousov *rule_p = mlx5_add_flow_rules(ft, spec, &flow_act, &dest, 1);
3415a93b4cdSHans Petter Selasky if (IS_ERR_OR_NULL(*rule_p))
3425a93b4cdSHans Petter Selasky goto err_del_ai;
3435a93b4cdSHans Petter Selasky }
3445a93b4cdSHans Petter Selasky
3455a93b4cdSHans Petter Selasky if (tt_vec & BIT(MLX5E_TT_IPV6_UDP)) {
3465a93b4cdSHans Petter Selasky rule_p = &ai->ft_rule[MLX5E_TT_IPV6_UDP];
3475a93b4cdSHans Petter Selasky dest.tir_num = tirn[MLX5E_TT_IPV6_UDP];
3485a93b4cdSHans Petter Selasky MLX5_SET(fte_match_param, mv, outer_headers.ethertype,
3495a93b4cdSHans Petter Selasky ETHERTYPE_IPV6);
350e23731dbSKonstantin Belousov *rule_p = mlx5_add_flow_rules(ft, spec, &flow_act, &dest, 1);
3515a93b4cdSHans Petter Selasky if (IS_ERR_OR_NULL(*rule_p))
3525a93b4cdSHans Petter Selasky goto err_del_ai;
3535a93b4cdSHans Petter Selasky }
3545a93b4cdSHans Petter Selasky
3555a93b4cdSHans Petter Selasky MLX5_SET(fte_match_param, mv, outer_headers.ip_protocol, IPPROTO_TCP);
3565a93b4cdSHans Petter Selasky
3575a93b4cdSHans Petter Selasky if (tt_vec & BIT(MLX5E_TT_IPV4_TCP)) {
3585a93b4cdSHans Petter Selasky rule_p = &ai->ft_rule[MLX5E_TT_IPV4_TCP];
3595a93b4cdSHans Petter Selasky dest.tir_num = tirn[MLX5E_TT_IPV4_TCP];
3605a93b4cdSHans Petter Selasky MLX5_SET(fte_match_param, mv, outer_headers.ethertype,
3615a93b4cdSHans Petter Selasky ETHERTYPE_IP);
362e23731dbSKonstantin Belousov *rule_p = mlx5_add_flow_rules(ft, spec, &flow_act, &dest, 1);
3635a93b4cdSHans Petter Selasky if (IS_ERR_OR_NULL(*rule_p))
3645a93b4cdSHans Petter Selasky goto err_del_ai;
3655a93b4cdSHans Petter Selasky }
3665a93b4cdSHans Petter Selasky
3675a93b4cdSHans Petter Selasky if (tt_vec & BIT(MLX5E_TT_IPV6_TCP)) {
3685a93b4cdSHans Petter Selasky rule_p = &ai->ft_rule[MLX5E_TT_IPV6_TCP];
3695a93b4cdSHans Petter Selasky dest.tir_num = tirn[MLX5E_TT_IPV6_TCP];
3705a93b4cdSHans Petter Selasky MLX5_SET(fte_match_param, mv, outer_headers.ethertype,
3715a93b4cdSHans Petter Selasky ETHERTYPE_IPV6);
372e23731dbSKonstantin Belousov *rule_p = mlx5_add_flow_rules(ft, spec, &flow_act, &dest, 1);
3735a93b4cdSHans Petter Selasky if (IS_ERR_OR_NULL(*rule_p))
3745a93b4cdSHans Petter Selasky goto err_del_ai;
3755a93b4cdSHans Petter Selasky }
3765a93b4cdSHans Petter Selasky
3775a93b4cdSHans Petter Selasky MLX5_SET(fte_match_param, mv, outer_headers.ip_protocol, IPPROTO_AH);
3785a93b4cdSHans Petter Selasky
3795a93b4cdSHans Petter Selasky if (tt_vec & BIT(MLX5E_TT_IPV4_IPSEC_AH)) {
3805a93b4cdSHans Petter Selasky rule_p = &ai->ft_rule[MLX5E_TT_IPV4_IPSEC_AH];
3815a93b4cdSHans Petter Selasky dest.tir_num = tirn[MLX5E_TT_IPV4_IPSEC_AH];
3825a93b4cdSHans Petter Selasky MLX5_SET(fte_match_param, mv, outer_headers.ethertype,
3835a93b4cdSHans Petter Selasky ETHERTYPE_IP);
384e23731dbSKonstantin Belousov *rule_p = mlx5_add_flow_rules(ft, spec, &flow_act, &dest, 1);
3855a93b4cdSHans Petter Selasky if (IS_ERR_OR_NULL(*rule_p))
3865a93b4cdSHans Petter Selasky goto err_del_ai;
3875a93b4cdSHans Petter Selasky }
3885a93b4cdSHans Petter Selasky
3895a93b4cdSHans Petter Selasky if (tt_vec & BIT(MLX5E_TT_IPV6_IPSEC_AH)) {
3905a93b4cdSHans Petter Selasky rule_p = &ai->ft_rule[MLX5E_TT_IPV6_IPSEC_AH];
3915a93b4cdSHans Petter Selasky dest.tir_num = tirn[MLX5E_TT_IPV6_IPSEC_AH];
3925a93b4cdSHans Petter Selasky MLX5_SET(fte_match_param, mv, outer_headers.ethertype,
3935a93b4cdSHans Petter Selasky ETHERTYPE_IPV6);
394e23731dbSKonstantin Belousov *rule_p = mlx5_add_flow_rules(ft, spec, &flow_act, &dest, 1);
3955a93b4cdSHans Petter Selasky if (IS_ERR_OR_NULL(*rule_p))
3965a93b4cdSHans Petter Selasky goto err_del_ai;
3975a93b4cdSHans Petter Selasky }
3985a93b4cdSHans Petter Selasky
3995a93b4cdSHans Petter Selasky MLX5_SET(fte_match_param, mv, outer_headers.ip_protocol, IPPROTO_ESP);
4005a93b4cdSHans Petter Selasky
4015a93b4cdSHans Petter Selasky if (tt_vec & BIT(MLX5E_TT_IPV4_IPSEC_ESP)) {
4025a93b4cdSHans Petter Selasky rule_p = &ai->ft_rule[MLX5E_TT_IPV4_IPSEC_ESP];
4035a93b4cdSHans Petter Selasky dest.tir_num = tirn[MLX5E_TT_IPV4_IPSEC_ESP];
4045a93b4cdSHans Petter Selasky MLX5_SET(fte_match_param, mv, outer_headers.ethertype,
4055a93b4cdSHans Petter Selasky ETHERTYPE_IP);
406e23731dbSKonstantin Belousov *rule_p = mlx5_add_flow_rules(ft, spec, &flow_act, &dest, 1);
4075a93b4cdSHans Petter Selasky if (IS_ERR_OR_NULL(*rule_p))
4085a93b4cdSHans Petter Selasky goto err_del_ai;
4095a93b4cdSHans Petter Selasky }
4105a93b4cdSHans Petter Selasky
4115a93b4cdSHans Petter Selasky if (tt_vec & BIT(MLX5E_TT_IPV6_IPSEC_ESP)) {
4125a93b4cdSHans Petter Selasky rule_p = &ai->ft_rule[MLX5E_TT_IPV6_IPSEC_ESP];
4135a93b4cdSHans Petter Selasky dest.tir_num = tirn[MLX5E_TT_IPV6_IPSEC_ESP];
4145a93b4cdSHans Petter Selasky MLX5_SET(fte_match_param, mv, outer_headers.ethertype,
4155a93b4cdSHans Petter Selasky ETHERTYPE_IPV6);
416e23731dbSKonstantin Belousov *rule_p = mlx5_add_flow_rules(ft, spec, &flow_act, &dest, 1);
4175a93b4cdSHans Petter Selasky if (IS_ERR_OR_NULL(*rule_p))
4185a93b4cdSHans Petter Selasky goto err_del_ai;
4195a93b4cdSHans Petter Selasky }
4205a93b4cdSHans Petter Selasky
4215a93b4cdSHans Petter Selasky return 0;
4225a93b4cdSHans Petter Selasky
4235a93b4cdSHans Petter Selasky err_del_ai:
4245a93b4cdSHans Petter Selasky err = PTR_ERR(*rule_p);
4255a93b4cdSHans Petter Selasky *rule_p = NULL;
426dc7e38acSHans Petter Selasky mlx5e_del_eth_addr_from_flow_table(priv, ai);
4275a93b4cdSHans Petter Selasky
4285a93b4cdSHans Petter Selasky return err;
429dc7e38acSHans Petter Selasky }
430dc7e38acSHans Petter Selasky
431dc7e38acSHans Petter Selasky static int
mlx5e_add_eth_addr_rule(struct mlx5e_priv * priv,struct mlx5e_eth_addr_info * ai,int type)432dc7e38acSHans Petter Selasky mlx5e_add_eth_addr_rule(struct mlx5e_priv *priv,
433dc7e38acSHans Petter Selasky struct mlx5e_eth_addr_info *ai, int type)
434dc7e38acSHans Petter Selasky {
435e23731dbSKonstantin Belousov struct mlx5_flow_spec *spec;
4365a93b4cdSHans Petter Selasky int err = 0;
437dc7e38acSHans Petter Selasky
438e23731dbSKonstantin Belousov spec = mlx5_vzalloc(sizeof(*spec));
439e23731dbSKonstantin Belousov if (!spec) {
4406b4040d8SHans Petter Selasky mlx5_en_err(priv->ifp, "alloc failed\n");
441dc7e38acSHans Petter Selasky err = -ENOMEM;
442dc7e38acSHans Petter Selasky goto add_eth_addr_rule_out;
443dc7e38acSHans Petter Selasky }
444e23731dbSKonstantin Belousov err = mlx5e_add_eth_addr_rule_sub(priv, ai, type, spec);
445dc7e38acSHans Petter Selasky
446dc7e38acSHans Petter Selasky add_eth_addr_rule_out:
447e23731dbSKonstantin Belousov kvfree(spec);
4485a93b4cdSHans Petter Selasky
449dc7e38acSHans Petter Selasky return (err);
450dc7e38acSHans Petter Selasky }
451dc7e38acSHans Petter Selasky
452861a612dSKonstantin Belousov static void
mlx5e_del_main_vxlan_rules(struct mlx5e_priv * priv)453861a612dSKonstantin Belousov mlx5e_del_main_vxlan_rules(struct mlx5e_priv *priv)
454861a612dSKonstantin Belousov {
455e23731dbSKonstantin Belousov mlx5_del_flow_rules(&priv->fts.main_vxlan_rule[MLX5E_TT_IPV6_IPSEC_ESP]);
456e23731dbSKonstantin Belousov mlx5_del_flow_rules(&priv->fts.main_vxlan_rule[MLX5E_TT_IPV4_IPSEC_ESP]);
457e23731dbSKonstantin Belousov mlx5_del_flow_rules(&priv->fts.main_vxlan_rule[MLX5E_TT_IPV6_IPSEC_AH]);
458e23731dbSKonstantin Belousov mlx5_del_flow_rules(&priv->fts.main_vxlan_rule[MLX5E_TT_IPV4_IPSEC_AH]);
459e23731dbSKonstantin Belousov mlx5_del_flow_rules(&priv->fts.main_vxlan_rule[MLX5E_TT_IPV6_TCP]);
460e23731dbSKonstantin Belousov mlx5_del_flow_rules(&priv->fts.main_vxlan_rule[MLX5E_TT_IPV4_TCP]);
461e23731dbSKonstantin Belousov mlx5_del_flow_rules(&priv->fts.main_vxlan_rule[MLX5E_TT_IPV6_UDP]);
462e23731dbSKonstantin Belousov mlx5_del_flow_rules(&priv->fts.main_vxlan_rule[MLX5E_TT_IPV4_UDP]);
463e23731dbSKonstantin Belousov mlx5_del_flow_rules(&priv->fts.main_vxlan_rule[MLX5E_TT_IPV6]);
464e23731dbSKonstantin Belousov mlx5_del_flow_rules(&priv->fts.main_vxlan_rule[MLX5E_TT_IPV4]);
465e23731dbSKonstantin Belousov mlx5_del_flow_rules(&priv->fts.main_vxlan_rule[MLX5E_TT_ANY]);
466861a612dSKonstantin Belousov }
467861a612dSKonstantin Belousov
468861a612dSKonstantin Belousov static int
mlx5e_add_main_vxlan_rules_sub(struct mlx5e_priv * priv,struct mlx5_flow_spec * spec)469e23731dbSKonstantin Belousov mlx5e_add_main_vxlan_rules_sub(struct mlx5e_priv *priv,
470e23731dbSKonstantin Belousov struct mlx5_flow_spec *spec)
471861a612dSKonstantin Belousov {
472861a612dSKonstantin Belousov struct mlx5_flow_destination dest = {};
473e23731dbSKonstantin Belousov struct mlx5_flow_handle **rule_p;
474861a612dSKonstantin Belousov struct mlx5_flow_table *ft = priv->fts.main_vxlan.t;
475861a612dSKonstantin Belousov u32 *tirn = priv->tirn_inner_vxlan;
476cb054a49SMark Bloch struct mlx5_flow_act flow_act = {
477b762b199SSlava Shwartsman .action = MLX5_FLOW_CONTEXT_ACTION_FWD_DEST,
478cb054a49SMark Bloch };
479861a612dSKonstantin Belousov int err = 0;
480e23731dbSKonstantin Belousov u8 *mc;
481e23731dbSKonstantin Belousov u8 *mv;
482e23731dbSKonstantin Belousov
483e23731dbSKonstantin Belousov spec->flow_context.flags = FLOW_CONTEXT_HAS_TAG;
484e23731dbSKonstantin Belousov spec->flow_context.flow_tag = MLX5_FS_ETH_FLOW_TAG;
485e23731dbSKonstantin Belousov
486e23731dbSKonstantin Belousov mc = (u8 *)spec->match_criteria;
487e23731dbSKonstantin Belousov mv = (u8 *)spec->match_value;
488861a612dSKonstantin Belousov
489861a612dSKonstantin Belousov dest.type = MLX5_FLOW_DESTINATION_TYPE_TIR;
490861a612dSKonstantin Belousov
491e23731dbSKonstantin Belousov spec->match_criteria_enable = MLX5_MATCH_INNER_HEADERS;
492861a612dSKonstantin Belousov MLX5_SET_TO_ONES(fte_match_param, mc, inner_headers.ethertype);
493861a612dSKonstantin Belousov
494861a612dSKonstantin Belousov rule_p = &priv->fts.main_vxlan_rule[MLX5E_TT_IPV4];
495861a612dSKonstantin Belousov dest.tir_num = tirn[MLX5E_TT_IPV4];
496861a612dSKonstantin Belousov MLX5_SET(fte_match_param, mv, inner_headers.ethertype, ETHERTYPE_IP);
497e23731dbSKonstantin Belousov *rule_p = mlx5_add_flow_rules(ft, spec, &flow_act, &dest, 1);
498861a612dSKonstantin Belousov if (IS_ERR_OR_NULL(*rule_p))
499861a612dSKonstantin Belousov goto err_del_ai;
500861a612dSKonstantin Belousov
501861a612dSKonstantin Belousov rule_p = &priv->fts.main_vxlan_rule[MLX5E_TT_IPV6];
502861a612dSKonstantin Belousov dest.tir_num = tirn[MLX5E_TT_IPV6];
503861a612dSKonstantin Belousov MLX5_SET(fte_match_param, mv, inner_headers.ethertype, ETHERTYPE_IPV6);
504e23731dbSKonstantin Belousov *rule_p = mlx5_add_flow_rules(ft, spec, &flow_act, &dest, 1);
505861a612dSKonstantin Belousov if (IS_ERR_OR_NULL(*rule_p))
506861a612dSKonstantin Belousov goto err_del_ai;
507861a612dSKonstantin Belousov
508861a612dSKonstantin Belousov MLX5_SET_TO_ONES(fte_match_param, mc, inner_headers.ip_protocol);
509861a612dSKonstantin Belousov MLX5_SET(fte_match_param, mv, inner_headers.ip_protocol, IPPROTO_UDP);
510861a612dSKonstantin Belousov
511861a612dSKonstantin Belousov rule_p = &priv->fts.main_vxlan_rule[MLX5E_TT_IPV4_UDP];
512861a612dSKonstantin Belousov dest.tir_num = tirn[MLX5E_TT_IPV4_UDP];
513861a612dSKonstantin Belousov MLX5_SET(fte_match_param, mv, inner_headers.ethertype, ETHERTYPE_IP);
514e23731dbSKonstantin Belousov *rule_p = mlx5_add_flow_rules(ft, spec, &flow_act, &dest, 1);
515861a612dSKonstantin Belousov if (IS_ERR_OR_NULL(*rule_p))
516861a612dSKonstantin Belousov goto err_del_ai;
517861a612dSKonstantin Belousov
518861a612dSKonstantin Belousov rule_p = &priv->fts.main_vxlan_rule[MLX5E_TT_IPV6_UDP];
519861a612dSKonstantin Belousov dest.tir_num = tirn[MLX5E_TT_IPV6_UDP];
520861a612dSKonstantin Belousov MLX5_SET(fte_match_param, mv, inner_headers.ethertype, ETHERTYPE_IPV6);
521e23731dbSKonstantin Belousov *rule_p = mlx5_add_flow_rules(ft, spec, &flow_act, &dest, 1);
522861a612dSKonstantin Belousov if (IS_ERR_OR_NULL(*rule_p))
523861a612dSKonstantin Belousov goto err_del_ai;
524861a612dSKonstantin Belousov
525861a612dSKonstantin Belousov MLX5_SET(fte_match_param, mv, inner_headers.ip_protocol, IPPROTO_TCP);
526861a612dSKonstantin Belousov
527861a612dSKonstantin Belousov rule_p = &priv->fts.main_vxlan_rule[MLX5E_TT_IPV4_TCP];
528861a612dSKonstantin Belousov dest.tir_num = tirn[MLX5E_TT_IPV4_TCP];
529861a612dSKonstantin Belousov MLX5_SET(fte_match_param, mv, inner_headers.ethertype, ETHERTYPE_IP);
530e23731dbSKonstantin Belousov *rule_p = mlx5_add_flow_rules(ft, spec, &flow_act, &dest, 1);
531861a612dSKonstantin Belousov if (IS_ERR_OR_NULL(*rule_p))
532861a612dSKonstantin Belousov goto err_del_ai;
533861a612dSKonstantin Belousov
534861a612dSKonstantin Belousov rule_p = &priv->fts.main_vxlan_rule[MLX5E_TT_IPV6_TCP];
535861a612dSKonstantin Belousov dest.tir_num = tirn[MLX5E_TT_IPV6_TCP];
536861a612dSKonstantin Belousov MLX5_SET(fte_match_param, mv, inner_headers.ethertype, ETHERTYPE_IPV6);
537e23731dbSKonstantin Belousov *rule_p = mlx5_add_flow_rules(ft, spec, &flow_act, &dest, 1);
538861a612dSKonstantin Belousov if (IS_ERR_OR_NULL(*rule_p))
539861a612dSKonstantin Belousov goto err_del_ai;
540861a612dSKonstantin Belousov
541861a612dSKonstantin Belousov MLX5_SET(fte_match_param, mv, inner_headers.ip_protocol, IPPROTO_AH);
542861a612dSKonstantin Belousov
543861a612dSKonstantin Belousov rule_p = &priv->fts.main_vxlan_rule[MLX5E_TT_IPV4_IPSEC_AH];
544861a612dSKonstantin Belousov dest.tir_num = tirn[MLX5E_TT_IPV4_IPSEC_AH];
545861a612dSKonstantin Belousov MLX5_SET(fte_match_param, mv, inner_headers.ethertype, ETHERTYPE_IP);
546e23731dbSKonstantin Belousov *rule_p = mlx5_add_flow_rules(ft, spec, &flow_act, &dest, 1);
547861a612dSKonstantin Belousov if (IS_ERR_OR_NULL(*rule_p))
548861a612dSKonstantin Belousov goto err_del_ai;
549861a612dSKonstantin Belousov
550861a612dSKonstantin Belousov rule_p = &priv->fts.main_vxlan_rule[MLX5E_TT_IPV6_IPSEC_AH];
551861a612dSKonstantin Belousov dest.tir_num = tirn[MLX5E_TT_IPV6_IPSEC_AH];
552861a612dSKonstantin Belousov MLX5_SET(fte_match_param, mv, inner_headers.ethertype, ETHERTYPE_IPV6);
553e23731dbSKonstantin Belousov *rule_p = mlx5_add_flow_rules(ft, spec, &flow_act, &dest, 1);
554861a612dSKonstantin Belousov if (IS_ERR_OR_NULL(*rule_p))
555861a612dSKonstantin Belousov goto err_del_ai;
556861a612dSKonstantin Belousov
557861a612dSKonstantin Belousov MLX5_SET(fte_match_param, mv, inner_headers.ip_protocol, IPPROTO_ESP);
558861a612dSKonstantin Belousov
559861a612dSKonstantin Belousov rule_p = &priv->fts.main_vxlan_rule[MLX5E_TT_IPV4_IPSEC_ESP];
560861a612dSKonstantin Belousov dest.tir_num = tirn[MLX5E_TT_IPV4_IPSEC_ESP];
561861a612dSKonstantin Belousov MLX5_SET(fte_match_param, mv, inner_headers.ethertype, ETHERTYPE_IP);
562e23731dbSKonstantin Belousov *rule_p = mlx5_add_flow_rules(ft, spec, &flow_act, &dest, 1);
563861a612dSKonstantin Belousov if (IS_ERR_OR_NULL(*rule_p))
564861a612dSKonstantin Belousov goto err_del_ai;
565861a612dSKonstantin Belousov
566861a612dSKonstantin Belousov rule_p = &priv->fts.main_vxlan_rule[MLX5E_TT_IPV6_IPSEC_ESP];
567861a612dSKonstantin Belousov dest.tir_num = tirn[MLX5E_TT_IPV6_IPSEC_ESP];
568861a612dSKonstantin Belousov MLX5_SET(fte_match_param, mv, inner_headers.ethertype,
569861a612dSKonstantin Belousov ETHERTYPE_IPV6);
570e23731dbSKonstantin Belousov *rule_p = mlx5_add_flow_rules(ft, spec, &flow_act, &dest, 1);
571861a612dSKonstantin Belousov if (IS_ERR_OR_NULL(*rule_p))
572861a612dSKonstantin Belousov goto err_del_ai;
573861a612dSKonstantin Belousov
574e23731dbSKonstantin Belousov spec->match_criteria_enable = 0;
575861a612dSKonstantin Belousov memset(mv, 0, MLX5_ST_SZ_BYTES(fte_match_param));
576861a612dSKonstantin Belousov memset(mc, 0, MLX5_ST_SZ_BYTES(fte_match_param));
577861a612dSKonstantin Belousov rule_p = &priv->fts.main_vxlan_rule[MLX5E_TT_ANY];
578861a612dSKonstantin Belousov dest.tir_num = tirn[MLX5E_TT_ANY];
579e23731dbSKonstantin Belousov *rule_p = mlx5_add_flow_rules(ft, NULL, &flow_act, &dest, 1);
580861a612dSKonstantin Belousov if (IS_ERR_OR_NULL(*rule_p))
581861a612dSKonstantin Belousov goto err_del_ai;
582861a612dSKonstantin Belousov
583861a612dSKonstantin Belousov return (0);
584861a612dSKonstantin Belousov
585861a612dSKonstantin Belousov err_del_ai:
586861a612dSKonstantin Belousov err = PTR_ERR(*rule_p);
587861a612dSKonstantin Belousov *rule_p = NULL;
588861a612dSKonstantin Belousov mlx5e_del_main_vxlan_rules(priv);
589861a612dSKonstantin Belousov
590861a612dSKonstantin Belousov return (err);
591861a612dSKonstantin Belousov }
592861a612dSKonstantin Belousov
593861a612dSKonstantin Belousov static int
mlx5e_add_main_vxlan_rules(struct mlx5e_priv * priv)594861a612dSKonstantin Belousov mlx5e_add_main_vxlan_rules(struct mlx5e_priv *priv)
595861a612dSKonstantin Belousov {
596e23731dbSKonstantin Belousov struct mlx5_flow_spec *spec;
597861a612dSKonstantin Belousov int err = 0;
598861a612dSKonstantin Belousov
599e23731dbSKonstantin Belousov spec = mlx5_vzalloc(sizeof(*spec));
600e23731dbSKonstantin Belousov if (!spec) {
601861a612dSKonstantin Belousov mlx5_en_err(priv->ifp, "alloc failed\n");
602861a612dSKonstantin Belousov err = -ENOMEM;
603861a612dSKonstantin Belousov goto add_main_vxlan_rules_out;
604861a612dSKonstantin Belousov }
605e23731dbSKonstantin Belousov err = mlx5e_add_main_vxlan_rules_sub(priv, spec);
606861a612dSKonstantin Belousov
607861a612dSKonstantin Belousov add_main_vxlan_rules_out:
608e23731dbSKonstantin Belousov kvfree(spec);
609861a612dSKonstantin Belousov
610861a612dSKonstantin Belousov return (err);
611861a612dSKonstantin Belousov }
612861a612dSKonstantin Belousov
mlx5e_vport_context_update_vlans(struct mlx5e_priv * priv)61376a5241fSHans Petter Selasky static int mlx5e_vport_context_update_vlans(struct mlx5e_priv *priv)
61476a5241fSHans Petter Selasky {
6155dc00f00SJustin Hibbits if_t ifp = priv->ifp;
61676a5241fSHans Petter Selasky int max_list_size;
61776a5241fSHans Petter Selasky int list_size;
61876a5241fSHans Petter Selasky u16 *vlans;
61976a5241fSHans Petter Selasky int vlan;
62076a5241fSHans Petter Selasky int err;
62176a5241fSHans Petter Selasky int i;
62276a5241fSHans Petter Selasky
62376a5241fSHans Petter Selasky list_size = 0;
62476a5241fSHans Petter Selasky for_each_set_bit(vlan, priv->vlan.active_vlans, VLAN_N_VID)
62576a5241fSHans Petter Selasky list_size++;
62676a5241fSHans Petter Selasky
62776a5241fSHans Petter Selasky max_list_size = 1 << MLX5_CAP_GEN(priv->mdev, log_max_vlan_list);
62876a5241fSHans Petter Selasky
62976a5241fSHans Petter Selasky if (list_size > max_list_size) {
6306b4040d8SHans Petter Selasky mlx5_en_err(ifp,
63176a5241fSHans Petter Selasky "ifnet vlans list size (%d) > (%d) max vport list size, some vlans will be dropped\n",
63276a5241fSHans Petter Selasky list_size, max_list_size);
63376a5241fSHans Petter Selasky list_size = max_list_size;
63476a5241fSHans Petter Selasky }
63576a5241fSHans Petter Selasky
63676a5241fSHans Petter Selasky vlans = kcalloc(list_size, sizeof(*vlans), GFP_KERNEL);
63776a5241fSHans Petter Selasky if (!vlans)
63876a5241fSHans Petter Selasky return -ENOMEM;
63976a5241fSHans Petter Selasky
64076a5241fSHans Petter Selasky i = 0;
64176a5241fSHans Petter Selasky for_each_set_bit(vlan, priv->vlan.active_vlans, VLAN_N_VID) {
64276a5241fSHans Petter Selasky if (i >= list_size)
64376a5241fSHans Petter Selasky break;
64476a5241fSHans Petter Selasky vlans[i++] = vlan;
64576a5241fSHans Petter Selasky }
64676a5241fSHans Petter Selasky
64776a5241fSHans Petter Selasky err = mlx5_modify_nic_vport_vlans(priv->mdev, vlans, list_size);
64876a5241fSHans Petter Selasky if (err)
6496b4040d8SHans Petter Selasky mlx5_en_err(ifp, "Failed to modify vport vlans list err(%d)\n",
65076a5241fSHans Petter Selasky err);
65176a5241fSHans Petter Selasky
65276a5241fSHans Petter Selasky kfree(vlans);
65376a5241fSHans Petter Selasky return err;
65476a5241fSHans Petter Selasky }
65576a5241fSHans Petter Selasky
656dc7e38acSHans Petter Selasky enum mlx5e_vlan_rule_type {
657dc7e38acSHans Petter Selasky MLX5E_VLAN_RULE_TYPE_UNTAGGED,
6585a93b4cdSHans Petter Selasky MLX5E_VLAN_RULE_TYPE_ANY_CTAG_VID,
6595a93b4cdSHans Petter Selasky MLX5E_VLAN_RULE_TYPE_ANY_STAG_VID,
660dc7e38acSHans Petter Selasky MLX5E_VLAN_RULE_TYPE_MATCH_VID,
661dc7e38acSHans Petter Selasky };
662dc7e38acSHans Petter Selasky
663dc7e38acSHans Petter Selasky static int
mlx5e_add_vlan_rule_sub(struct mlx5e_priv * priv,enum mlx5e_vlan_rule_type rule_type,u16 vid,struct mlx5_flow_spec * spec)6645a93b4cdSHans Petter Selasky mlx5e_add_vlan_rule_sub(struct mlx5e_priv *priv,
6655a93b4cdSHans Petter Selasky enum mlx5e_vlan_rule_type rule_type, u16 vid,
666e23731dbSKonstantin Belousov struct mlx5_flow_spec *spec)
6675a93b4cdSHans Petter Selasky {
6685a93b4cdSHans Petter Selasky struct mlx5_flow_table *ft = priv->fts.vlan.t;
66947d93c5cSHans Petter Selasky struct mlx5_flow_destination dest = {};
670e23731dbSKonstantin Belousov struct mlx5_flow_handle **rule_p;
6715a93b4cdSHans Petter Selasky int err = 0;
672cb054a49SMark Bloch struct mlx5_flow_act flow_act = {
673b762b199SSlava Shwartsman .action = MLX5_FLOW_CONTEXT_ACTION_FWD_DEST,
674cb054a49SMark Bloch };
675e23731dbSKonstantin Belousov u8 *mv;
676e23731dbSKonstantin Belousov u8 *mc;
6775a93b4cdSHans Petter Selasky
678e23731dbSKonstantin Belousov mv = (u8 *)spec->match_value;
679e23731dbSKonstantin Belousov mc = (u8 *)spec->match_criteria;
680e23731dbSKonstantin Belousov
681e23731dbSKonstantin Belousov spec->flow_context.flow_tag = MLX5_FS_ETH_FLOW_TAG;
682e23731dbSKonstantin Belousov spec->flow_context.flags = FLOW_CONTEXT_HAS_TAG;
6835a93b4cdSHans Petter Selasky dest.type = MLX5_FLOW_DESTINATION_TYPE_FLOW_TABLE;
684e059c120SHans Petter Selasky dest.ft = priv->fts.vxlan.t;
6855a93b4cdSHans Petter Selasky
686e23731dbSKonstantin Belousov spec->match_criteria_enable = MLX5_MATCH_OUTER_HEADERS;
6875a93b4cdSHans Petter Selasky
6885a93b4cdSHans Petter Selasky switch (rule_type) {
6895a93b4cdSHans Petter Selasky case MLX5E_VLAN_RULE_TYPE_UNTAGGED:
6905a93b4cdSHans Petter Selasky rule_p = &priv->vlan.untagged_ft_rule;
6915a93b4cdSHans Petter Selasky MLX5_SET_TO_ONES(fte_match_param, mc, outer_headers.cvlan_tag);
6925a93b4cdSHans Petter Selasky break;
6935a93b4cdSHans Petter Selasky case MLX5E_VLAN_RULE_TYPE_ANY_CTAG_VID:
6945a93b4cdSHans Petter Selasky rule_p = &priv->vlan.any_cvlan_ft_rule;
6955a93b4cdSHans Petter Selasky MLX5_SET_TO_ONES(fte_match_param, mc, outer_headers.cvlan_tag);
6965a93b4cdSHans Petter Selasky MLX5_SET(fte_match_param, mv, outer_headers.cvlan_tag, 1);
6975a93b4cdSHans Petter Selasky break;
6985a93b4cdSHans Petter Selasky case MLX5E_VLAN_RULE_TYPE_ANY_STAG_VID:
6995a93b4cdSHans Petter Selasky rule_p = &priv->vlan.any_svlan_ft_rule;
7005a93b4cdSHans Petter Selasky MLX5_SET_TO_ONES(fte_match_param, mc, outer_headers.svlan_tag);
7015a93b4cdSHans Petter Selasky MLX5_SET(fte_match_param, mv, outer_headers.svlan_tag, 1);
7025a93b4cdSHans Petter Selasky break;
7035a93b4cdSHans Petter Selasky default: /* MLX5E_VLAN_RULE_TYPE_MATCH_VID */
7045a93b4cdSHans Petter Selasky rule_p = &priv->vlan.active_vlans_ft_rule[vid];
7055a93b4cdSHans Petter Selasky MLX5_SET_TO_ONES(fte_match_param, mc, outer_headers.cvlan_tag);
7065a93b4cdSHans Petter Selasky MLX5_SET(fte_match_param, mv, outer_headers.cvlan_tag, 1);
7075a93b4cdSHans Petter Selasky MLX5_SET_TO_ONES(fte_match_param, mc, outer_headers.first_vid);
7085a93b4cdSHans Petter Selasky MLX5_SET(fte_match_param, mv, outer_headers.first_vid, vid);
7095a93b4cdSHans Petter Selasky mlx5e_vport_context_update_vlans(priv);
7105a93b4cdSHans Petter Selasky break;
7115a93b4cdSHans Petter Selasky }
7125a93b4cdSHans Petter Selasky
713e23731dbSKonstantin Belousov *rule_p = mlx5_add_flow_rules(ft, spec, &flow_act, &dest, 1);
7145a93b4cdSHans Petter Selasky if (IS_ERR(*rule_p)) {
7155a93b4cdSHans Petter Selasky err = PTR_ERR(*rule_p);
7165a93b4cdSHans Petter Selasky *rule_p = NULL;
7176b4040d8SHans Petter Selasky mlx5_en_err(priv->ifp, "add rule failed\n");
7185a93b4cdSHans Petter Selasky }
7195a93b4cdSHans Petter Selasky
7205a93b4cdSHans Petter Selasky return (err);
7215a93b4cdSHans Petter Selasky }
7225a93b4cdSHans Petter Selasky
7235a93b4cdSHans Petter Selasky static int
mlx5e_add_vlan_rule(struct mlx5e_priv * priv,enum mlx5e_vlan_rule_type rule_type,u16 vid)724dc7e38acSHans Petter Selasky mlx5e_add_vlan_rule(struct mlx5e_priv *priv,
725dc7e38acSHans Petter Selasky enum mlx5e_vlan_rule_type rule_type, u16 vid)
726dc7e38acSHans Petter Selasky {
727e23731dbSKonstantin Belousov struct mlx5_flow_spec *spec;
7285a93b4cdSHans Petter Selasky int err = 0;
729dc7e38acSHans Petter Selasky
730e23731dbSKonstantin Belousov spec = mlx5_vzalloc(sizeof(*spec));
731e23731dbSKonstantin Belousov if (!spec) {
7326b4040d8SHans Petter Selasky mlx5_en_err(priv->ifp, "alloc failed\n");
733dc7e38acSHans Petter Selasky err = -ENOMEM;
734dc7e38acSHans Petter Selasky goto add_vlan_rule_out;
735dc7e38acSHans Petter Selasky }
736dc7e38acSHans Petter Selasky
737e23731dbSKonstantin Belousov err = mlx5e_add_vlan_rule_sub(priv, rule_type, vid, spec);
738dc7e38acSHans Petter Selasky
739dc7e38acSHans Petter Selasky add_vlan_rule_out:
740e23731dbSKonstantin Belousov kvfree(spec);
7415a93b4cdSHans Petter Selasky
742dc7e38acSHans Petter Selasky return (err);
743dc7e38acSHans Petter Selasky }
744dc7e38acSHans Petter Selasky
745dc7e38acSHans Petter Selasky static void
mlx5e_del_vlan_rule(struct mlx5e_priv * priv,enum mlx5e_vlan_rule_type rule_type,u16 vid)746dc7e38acSHans Petter Selasky mlx5e_del_vlan_rule(struct mlx5e_priv *priv,
747dc7e38acSHans Petter Selasky enum mlx5e_vlan_rule_type rule_type, u16 vid)
748dc7e38acSHans Petter Selasky {
749dc7e38acSHans Petter Selasky switch (rule_type) {
750dc7e38acSHans Petter Selasky case MLX5E_VLAN_RULE_TYPE_UNTAGGED:
751e23731dbSKonstantin Belousov mlx5_del_flow_rules(&priv->vlan.untagged_ft_rule);
752dc7e38acSHans Petter Selasky break;
7535a93b4cdSHans Petter Selasky case MLX5E_VLAN_RULE_TYPE_ANY_CTAG_VID:
754e23731dbSKonstantin Belousov mlx5_del_flow_rules(&priv->vlan.any_cvlan_ft_rule);
7555a93b4cdSHans Petter Selasky break;
7565a93b4cdSHans Petter Selasky case MLX5E_VLAN_RULE_TYPE_ANY_STAG_VID:
757e23731dbSKonstantin Belousov mlx5_del_flow_rules(&priv->vlan.any_svlan_ft_rule);
758dc7e38acSHans Petter Selasky break;
759dc7e38acSHans Petter Selasky case MLX5E_VLAN_RULE_TYPE_MATCH_VID:
760e23731dbSKonstantin Belousov mlx5_del_flow_rules(&priv->vlan.active_vlans_ft_rule[vid]);
76176a5241fSHans Petter Selasky mlx5e_vport_context_update_vlans(priv);
762dc7e38acSHans Petter Selasky break;
7635a93b4cdSHans Petter Selasky default:
7645a93b4cdSHans Petter Selasky break;
765dc7e38acSHans Petter Selasky }
766dc7e38acSHans Petter Selasky }
767dc7e38acSHans Petter Selasky
7685a93b4cdSHans Petter Selasky static void
mlx5e_del_any_vid_rules(struct mlx5e_priv * priv)7695a93b4cdSHans Petter Selasky mlx5e_del_any_vid_rules(struct mlx5e_priv *priv)
7705a93b4cdSHans Petter Selasky {
7715a93b4cdSHans Petter Selasky mlx5e_del_vlan_rule(priv, MLX5E_VLAN_RULE_TYPE_ANY_CTAG_VID, 0);
7725a93b4cdSHans Petter Selasky mlx5e_del_vlan_rule(priv, MLX5E_VLAN_RULE_TYPE_ANY_STAG_VID, 0);
7735a93b4cdSHans Petter Selasky }
7745a93b4cdSHans Petter Selasky
7755a93b4cdSHans Petter Selasky static int
mlx5e_add_any_vid_rules(struct mlx5e_priv * priv)7765a93b4cdSHans Petter Selasky mlx5e_add_any_vid_rules(struct mlx5e_priv *priv)
7775a93b4cdSHans Petter Selasky {
7785a93b4cdSHans Petter Selasky int err;
7795a93b4cdSHans Petter Selasky
7805a93b4cdSHans Petter Selasky err = mlx5e_add_vlan_rule(priv, MLX5E_VLAN_RULE_TYPE_ANY_CTAG_VID, 0);
7815a93b4cdSHans Petter Selasky if (err)
7825a93b4cdSHans Petter Selasky return (err);
7835a93b4cdSHans Petter Selasky
784f5233a73SHans Petter Selasky err = mlx5e_add_vlan_rule(priv, MLX5E_VLAN_RULE_TYPE_ANY_STAG_VID, 0);
785f5233a73SHans Petter Selasky if (err)
786f5233a73SHans Petter Selasky mlx5e_del_vlan_rule(priv, MLX5E_VLAN_RULE_TYPE_ANY_CTAG_VID, 0);
787f5233a73SHans Petter Selasky
788f5233a73SHans Petter Selasky return (err);
7895a93b4cdSHans Petter Selasky }
7905a93b4cdSHans Petter Selasky
791dc7e38acSHans Petter Selasky void
mlx5e_enable_vlan_filter(struct mlx5e_priv * priv)792dc7e38acSHans Petter Selasky mlx5e_enable_vlan_filter(struct mlx5e_priv *priv)
793dc7e38acSHans Petter Selasky {
794dc7e38acSHans Petter Selasky if (priv->vlan.filter_disabled) {
795dc7e38acSHans Petter Selasky priv->vlan.filter_disabled = false;
7965dc00f00SJustin Hibbits if (if_getflags(priv->ifp) & IFF_PROMISC)
7975a93b4cdSHans Petter Selasky return;
798e059c120SHans Petter Selasky if (test_bit(MLX5E_STATE_FLOW_RULES_READY, &priv->state))
7995a93b4cdSHans Petter Selasky mlx5e_del_any_vid_rules(priv);
800dc7e38acSHans Petter Selasky }
801dc7e38acSHans Petter Selasky }
802dc7e38acSHans Petter Selasky
803dc7e38acSHans Petter Selasky void
mlx5e_disable_vlan_filter(struct mlx5e_priv * priv)804dc7e38acSHans Petter Selasky mlx5e_disable_vlan_filter(struct mlx5e_priv *priv)
805dc7e38acSHans Petter Selasky {
806dc7e38acSHans Petter Selasky if (!priv->vlan.filter_disabled) {
807dc7e38acSHans Petter Selasky priv->vlan.filter_disabled = true;
8085dc00f00SJustin Hibbits if (if_getflags(priv->ifp) & IFF_PROMISC)
8095a93b4cdSHans Petter Selasky return;
810e059c120SHans Petter Selasky if (test_bit(MLX5E_STATE_FLOW_RULES_READY, &priv->state))
8115a93b4cdSHans Petter Selasky mlx5e_add_any_vid_rules(priv);
812dc7e38acSHans Petter Selasky }
813dc7e38acSHans Petter Selasky }
814dc7e38acSHans Petter Selasky
815dc7e38acSHans Petter Selasky void
mlx5e_vlan_rx_add_vid(void * arg,if_t ifp,u16 vid)8165dc00f00SJustin Hibbits mlx5e_vlan_rx_add_vid(void *arg, if_t ifp, u16 vid)
817dc7e38acSHans Petter Selasky {
818dc7e38acSHans Petter Selasky struct mlx5e_priv *priv = arg;
819dc7e38acSHans Petter Selasky
820dc7e38acSHans Petter Selasky if (ifp != priv->ifp)
821dc7e38acSHans Petter Selasky return;
822dc7e38acSHans Petter Selasky
823dc7e38acSHans Petter Selasky PRIV_LOCK(priv);
8245a93b4cdSHans Petter Selasky if (!test_and_set_bit(vid, priv->vlan.active_vlans) &&
825e059c120SHans Petter Selasky test_bit(MLX5E_STATE_FLOW_RULES_READY, &priv->state))
826dc7e38acSHans Petter Selasky mlx5e_add_vlan_rule(priv, MLX5E_VLAN_RULE_TYPE_MATCH_VID, vid);
827dc7e38acSHans Petter Selasky PRIV_UNLOCK(priv);
828dc7e38acSHans Petter Selasky }
829dc7e38acSHans Petter Selasky
830dc7e38acSHans Petter Selasky void
mlx5e_vlan_rx_kill_vid(void * arg,if_t ifp,u16 vid)8315dc00f00SJustin Hibbits mlx5e_vlan_rx_kill_vid(void *arg, if_t ifp, u16 vid)
832dc7e38acSHans Petter Selasky {
833dc7e38acSHans Petter Selasky struct mlx5e_priv *priv = arg;
834dc7e38acSHans Petter Selasky
835dc7e38acSHans Petter Selasky if (ifp != priv->ifp)
836dc7e38acSHans Petter Selasky return;
837dc7e38acSHans Petter Selasky
838dc7e38acSHans Petter Selasky PRIV_LOCK(priv);
839dc7e38acSHans Petter Selasky clear_bit(vid, priv->vlan.active_vlans);
840e059c120SHans Petter Selasky if (test_bit(MLX5E_STATE_FLOW_RULES_READY, &priv->state))
841dc7e38acSHans Petter Selasky mlx5e_del_vlan_rule(priv, MLX5E_VLAN_RULE_TYPE_MATCH_VID, vid);
842dc7e38acSHans Petter Selasky PRIV_UNLOCK(priv);
843dc7e38acSHans Petter Selasky }
844dc7e38acSHans Petter Selasky
845e059c120SHans Petter Selasky static int
mlx5e_add_all_vlan_rules(struct mlx5e_priv * priv)846dc7e38acSHans Petter Selasky mlx5e_add_all_vlan_rules(struct mlx5e_priv *priv)
847dc7e38acSHans Petter Selasky {
848dc7e38acSHans Petter Selasky int err;
8495a93b4cdSHans Petter Selasky int i;
850dc7e38acSHans Petter Selasky
851952e75c7SKonstantin Belousov set_bit(0, priv->vlan.active_vlans);
8525a93b4cdSHans Petter Selasky for_each_set_bit(i, priv->vlan.active_vlans, VLAN_N_VID) {
853dc7e38acSHans Petter Selasky err = mlx5e_add_vlan_rule(priv, MLX5E_VLAN_RULE_TYPE_MATCH_VID,
8545a93b4cdSHans Petter Selasky i);
855dc7e38acSHans Petter Selasky if (err)
856f5233a73SHans Petter Selasky goto error;
857dc7e38acSHans Petter Selasky }
858dc7e38acSHans Petter Selasky
859dc7e38acSHans Petter Selasky err = mlx5e_add_vlan_rule(priv, MLX5E_VLAN_RULE_TYPE_UNTAGGED, 0);
860dc7e38acSHans Petter Selasky if (err)
861f5233a73SHans Petter Selasky goto error;
862dc7e38acSHans Petter Selasky
863dc7e38acSHans Petter Selasky if (priv->vlan.filter_disabled) {
8645a93b4cdSHans Petter Selasky err = mlx5e_add_any_vid_rules(priv);
865dc7e38acSHans Petter Selasky if (err)
866f5233a73SHans Petter Selasky goto error;
867dc7e38acSHans Petter Selasky }
868dc7e38acSHans Petter Selasky return (0);
869f5233a73SHans Petter Selasky error:
870f5233a73SHans Petter Selasky mlx5e_del_all_vlan_rules(priv);
871f5233a73SHans Petter Selasky return (err);
872dc7e38acSHans Petter Selasky }
873dc7e38acSHans Petter Selasky
874e059c120SHans Petter Selasky static void
mlx5e_del_all_vlan_rules(struct mlx5e_priv * priv)875dc7e38acSHans Petter Selasky mlx5e_del_all_vlan_rules(struct mlx5e_priv *priv)
876dc7e38acSHans Petter Selasky {
8775a93b4cdSHans Petter Selasky int i;
878dc7e38acSHans Petter Selasky
879dc7e38acSHans Petter Selasky if (priv->vlan.filter_disabled)
8805a93b4cdSHans Petter Selasky mlx5e_del_any_vid_rules(priv);
881dc7e38acSHans Petter Selasky
882dc7e38acSHans Petter Selasky mlx5e_del_vlan_rule(priv, MLX5E_VLAN_RULE_TYPE_UNTAGGED, 0);
883dc7e38acSHans Petter Selasky
8845a93b4cdSHans Petter Selasky for_each_set_bit(i, priv->vlan.active_vlans, VLAN_N_VID)
8855a93b4cdSHans Petter Selasky mlx5e_del_vlan_rule(priv, MLX5E_VLAN_RULE_TYPE_MATCH_VID, i);
886952e75c7SKonstantin Belousov clear_bit(0, priv->vlan.active_vlans);
887dc7e38acSHans Petter Selasky }
888dc7e38acSHans Petter Selasky
889dc7e38acSHans Petter Selasky #define mlx5e_for_each_hash_node(hn, tmp, hash, i) \
890dc7e38acSHans Petter Selasky for (i = 0; i < MLX5E_ETH_ADDR_HASH_SIZE; i++) \
891dc7e38acSHans Petter Selasky LIST_FOREACH_SAFE(hn, &(hash)[i], hlist, tmp)
892dc7e38acSHans Petter Selasky
893dc7e38acSHans Petter Selasky static void
mlx5e_execute_action(struct mlx5e_priv * priv,struct mlx5e_eth_addr_hash_node * hn)894dc7e38acSHans Petter Selasky mlx5e_execute_action(struct mlx5e_priv *priv,
895dc7e38acSHans Petter Selasky struct mlx5e_eth_addr_hash_node *hn)
896dc7e38acSHans Petter Selasky {
897dc7e38acSHans Petter Selasky switch (hn->action) {
898dc7e38acSHans Petter Selasky case MLX5E_ACTION_ADD:
899dc7e38acSHans Petter Selasky mlx5e_add_eth_addr_rule(priv, &hn->ai, MLX5E_FULLMATCH);
900dc7e38acSHans Petter Selasky hn->action = MLX5E_ACTION_NONE;
901dc7e38acSHans Petter Selasky break;
902dc7e38acSHans Petter Selasky
903dc7e38acSHans Petter Selasky case MLX5E_ACTION_DEL:
904dc7e38acSHans Petter Selasky mlx5e_del_eth_addr_from_flow_table(priv, &hn->ai);
90566b38bfeSHans Petter Selasky if (hn->mpfs_index != -1U)
90666b38bfeSHans Petter Selasky mlx5_mpfs_del_mac(priv->mdev, hn->mpfs_index);
907dc7e38acSHans Petter Selasky mlx5e_del_eth_addr_from_hash(hn);
908dc7e38acSHans Petter Selasky break;
909dc7e38acSHans Petter Selasky
910dc7e38acSHans Petter Selasky default:
911dc7e38acSHans Petter Selasky break;
912dc7e38acSHans Petter Selasky }
913dc7e38acSHans Petter Selasky }
914dc7e38acSHans Petter Selasky
91566b38bfeSHans Petter Selasky static struct mlx5e_eth_addr_hash_node *
mlx5e_move_hn(struct mlx5e_eth_addr_hash_head * fh,struct mlx5e_eth_addr_hash_head * uh)91666b38bfeSHans Petter Selasky mlx5e_move_hn(struct mlx5e_eth_addr_hash_head *fh, struct mlx5e_eth_addr_hash_head *uh)
91766b38bfeSHans Petter Selasky {
91866b38bfeSHans Petter Selasky struct mlx5e_eth_addr_hash_node *hn;
91966b38bfeSHans Petter Selasky
92066b38bfeSHans Petter Selasky hn = LIST_FIRST(fh);
92166b38bfeSHans Petter Selasky if (hn != NULL) {
92266b38bfeSHans Petter Selasky LIST_REMOVE(hn, hlist);
92366b38bfeSHans Petter Selasky LIST_INSERT_HEAD(uh, hn, hlist);
92466b38bfeSHans Petter Selasky }
92566b38bfeSHans Petter Selasky return (hn);
92666b38bfeSHans Petter Selasky }
92766b38bfeSHans Petter Selasky
92866b38bfeSHans Petter Selasky static struct mlx5e_eth_addr_hash_node *
mlx5e_remove_hn(struct mlx5e_eth_addr_hash_head * fh)92966b38bfeSHans Petter Selasky mlx5e_remove_hn(struct mlx5e_eth_addr_hash_head *fh)
93066b38bfeSHans Petter Selasky {
93166b38bfeSHans Petter Selasky struct mlx5e_eth_addr_hash_node *hn;
93266b38bfeSHans Petter Selasky
93366b38bfeSHans Petter Selasky hn = LIST_FIRST(fh);
93466b38bfeSHans Petter Selasky if (hn != NULL)
93566b38bfeSHans Petter Selasky LIST_REMOVE(hn, hlist);
93666b38bfeSHans Petter Selasky return (hn);
93766b38bfeSHans Petter Selasky }
93866b38bfeSHans Petter Selasky
93920b26072SGleb Smirnoff struct mlx5e_copy_addr_ctx {
94020b26072SGleb Smirnoff struct mlx5e_eth_addr_hash_head *free;
94120b26072SGleb Smirnoff struct mlx5e_eth_addr_hash_head *fill;
94220b26072SGleb Smirnoff bool success;
94320b26072SGleb Smirnoff };
94420b26072SGleb Smirnoff
94520b26072SGleb Smirnoff static u_int
mlx5e_copy_addr(void * arg,struct sockaddr_dl * sdl,u_int cnt)94620b26072SGleb Smirnoff mlx5e_copy_addr(void *arg, struct sockaddr_dl *sdl, u_int cnt)
94720b26072SGleb Smirnoff {
94820b26072SGleb Smirnoff struct mlx5e_copy_addr_ctx *ctx = arg;
94920b26072SGleb Smirnoff struct mlx5e_eth_addr_hash_node *hn;
95020b26072SGleb Smirnoff
95120b26072SGleb Smirnoff hn = mlx5e_move_hn(ctx->free, ctx->fill);
95220b26072SGleb Smirnoff if (hn == NULL) {
95320b26072SGleb Smirnoff ctx->success = false;
95420b26072SGleb Smirnoff return (0);
95520b26072SGleb Smirnoff }
95620b26072SGleb Smirnoff ether_addr_copy(hn->ai.addr, LLADDR(sdl));
95720b26072SGleb Smirnoff
95820b26072SGleb Smirnoff return (1);
95920b26072SGleb Smirnoff }
96020b26072SGleb Smirnoff
961dc7e38acSHans Petter Selasky static void
mlx5e_sync_ifp_addr(struct mlx5e_priv * priv)962dc7e38acSHans Petter Selasky mlx5e_sync_ifp_addr(struct mlx5e_priv *priv)
963dc7e38acSHans Petter Selasky {
96420b26072SGleb Smirnoff struct mlx5e_copy_addr_ctx ctx;
96566b38bfeSHans Petter Selasky struct mlx5e_eth_addr_hash_head head_free;
96666b38bfeSHans Petter Selasky struct mlx5e_eth_addr_hash_head head_uc;
96766b38bfeSHans Petter Selasky struct mlx5e_eth_addr_hash_head head_mc;
96866b38bfeSHans Petter Selasky struct mlx5e_eth_addr_hash_node *hn;
9695dc00f00SJustin Hibbits if_t ifp = priv->ifp;
97066b38bfeSHans Petter Selasky size_t x;
97166b38bfeSHans Petter Selasky size_t num;
972dc7e38acSHans Petter Selasky
9732db3dd50SHans Petter Selasky PRIV_ASSERT_LOCKED(priv);
9742db3dd50SHans Petter Selasky
97520b26072SGleb Smirnoff retry:
97666b38bfeSHans Petter Selasky LIST_INIT(&head_free);
97766b38bfeSHans Petter Selasky LIST_INIT(&head_uc);
97866b38bfeSHans Petter Selasky LIST_INIT(&head_mc);
97920b26072SGleb Smirnoff num = 1 + if_lladdr_count(ifp) + if_llmaddr_count(ifp);
98066b38bfeSHans Petter Selasky
98166b38bfeSHans Petter Selasky /* allocate place holders */
98266b38bfeSHans Petter Selasky for (x = 0; x != num; x++) {
98366b38bfeSHans Petter Selasky hn = malloc(sizeof(*hn), M_MLX5EN, M_WAITOK | M_ZERO);
98466b38bfeSHans Petter Selasky hn->action = MLX5E_ACTION_ADD;
98566b38bfeSHans Petter Selasky hn->mpfs_index = -1U;
98666b38bfeSHans Petter Selasky LIST_INSERT_HEAD(&head_free, hn, hlist);
98766b38bfeSHans Petter Selasky }
98866b38bfeSHans Petter Selasky
98966b38bfeSHans Petter Selasky hn = mlx5e_move_hn(&head_free, &head_uc);
99020b26072SGleb Smirnoff MPASS(hn != NULL);
99166b38bfeSHans Petter Selasky
9925dc00f00SJustin Hibbits ether_addr_copy(hn->ai.addr, if_getlladdr(ifp));
99366b38bfeSHans Petter Selasky
99420b26072SGleb Smirnoff ctx.free = &head_free;
99520b26072SGleb Smirnoff ctx.fill = &head_uc;
99620b26072SGleb Smirnoff ctx.success = true;
99720b26072SGleb Smirnoff if_foreach_lladdr(ifp, mlx5e_copy_addr, &ctx);
99820b26072SGleb Smirnoff if (ctx.success == false)
99966b38bfeSHans Petter Selasky goto cleanup;
100066b38bfeSHans Petter Selasky
100120b26072SGleb Smirnoff ctx.fill = &head_mc;
100220b26072SGleb Smirnoff if_foreach_llmaddr(ifp, mlx5e_copy_addr, &ctx);
100320b26072SGleb Smirnoff if (ctx.success == false)
100466b38bfeSHans Petter Selasky goto cleanup;
100566b38bfeSHans Petter Selasky
100666b38bfeSHans Petter Selasky /* insert L2 unicast addresses into hash list */
100766b38bfeSHans Petter Selasky
100866b38bfeSHans Petter Selasky while ((hn = mlx5e_remove_hn(&head_uc)) != NULL) {
100966b38bfeSHans Petter Selasky if (mlx5e_add_eth_addr_to_hash(priv->eth_addr.if_uc, hn) == 0)
101066b38bfeSHans Petter Selasky continue;
101166b38bfeSHans Petter Selasky if (hn->mpfs_index == -1U)
1012f6ca0b21SKonstantin Belousov mlx5_mpfs_add_mac(priv->mdev, &hn->mpfs_index,
1013f6ca0b21SKonstantin Belousov hn->ai.addr, 0, 0);
101466b38bfeSHans Petter Selasky }
101566b38bfeSHans Petter Selasky
101666b38bfeSHans Petter Selasky /* insert L2 multicast addresses into hash list */
101766b38bfeSHans Petter Selasky
101866b38bfeSHans Petter Selasky while ((hn = mlx5e_remove_hn(&head_mc)) != NULL) {
101966b38bfeSHans Petter Selasky if (mlx5e_add_eth_addr_to_hash(priv->eth_addr.if_mc, hn) == 0)
102066b38bfeSHans Petter Selasky continue;
102166b38bfeSHans Petter Selasky }
102266b38bfeSHans Petter Selasky
102366b38bfeSHans Petter Selasky cleanup:
102466b38bfeSHans Petter Selasky while ((hn = mlx5e_remove_hn(&head_uc)) != NULL)
102566b38bfeSHans Petter Selasky free(hn, M_MLX5EN);
102666b38bfeSHans Petter Selasky while ((hn = mlx5e_remove_hn(&head_mc)) != NULL)
102766b38bfeSHans Petter Selasky free(hn, M_MLX5EN);
102866b38bfeSHans Petter Selasky while ((hn = mlx5e_remove_hn(&head_free)) != NULL)
102966b38bfeSHans Petter Selasky free(hn, M_MLX5EN);
103066b38bfeSHans Petter Selasky
103120b26072SGleb Smirnoff if (ctx.success == false)
103266b38bfeSHans Petter Selasky goto retry;
1033dc7e38acSHans Petter Selasky }
1034dc7e38acSHans Petter Selasky
mlx5e_fill_addr_array(struct mlx5e_priv * priv,int list_type,u8 addr_array[][ETH_ALEN],int size)103576a5241fSHans Petter Selasky static void mlx5e_fill_addr_array(struct mlx5e_priv *priv, int list_type,
103676a5241fSHans Petter Selasky u8 addr_array[][ETH_ALEN], int size)
103776a5241fSHans Petter Selasky {
103876a5241fSHans Petter Selasky bool is_uc = (list_type == MLX5_NIC_VPORT_LIST_TYPE_UC);
10395dc00f00SJustin Hibbits if_t ifp = priv->ifp;
104076a5241fSHans Petter Selasky struct mlx5e_eth_addr_hash_node *hn;
104176a5241fSHans Petter Selasky struct mlx5e_eth_addr_hash_head *addr_list;
104276a5241fSHans Petter Selasky struct mlx5e_eth_addr_hash_node *tmp;
104376a5241fSHans Petter Selasky int i = 0;
104476a5241fSHans Petter Selasky int hi;
104576a5241fSHans Petter Selasky
104676a5241fSHans Petter Selasky addr_list = is_uc ? priv->eth_addr.if_uc : priv->eth_addr.if_mc;
104776a5241fSHans Petter Selasky
104876a5241fSHans Petter Selasky if (is_uc) /* Make sure our own address is pushed first */
10495dc00f00SJustin Hibbits ether_addr_copy(addr_array[i++], if_getlladdr(ifp));
105076a5241fSHans Petter Selasky else if (priv->eth_addr.broadcast_enabled)
10515dc00f00SJustin Hibbits ether_addr_copy(addr_array[i++], if_getbroadcastaddr(ifp));
105276a5241fSHans Petter Selasky
105376a5241fSHans Petter Selasky mlx5e_for_each_hash_node(hn, tmp, addr_list, hi) {
10545dc00f00SJustin Hibbits if (ether_addr_equal(if_getlladdr(ifp), hn->ai.addr))
105576a5241fSHans Petter Selasky continue;
105676a5241fSHans Petter Selasky if (i >= size)
105776a5241fSHans Petter Selasky break;
105876a5241fSHans Petter Selasky ether_addr_copy(addr_array[i++], hn->ai.addr);
105976a5241fSHans Petter Selasky }
106076a5241fSHans Petter Selasky }
106176a5241fSHans Petter Selasky
mlx5e_vport_context_update_addr_list(struct mlx5e_priv * priv,int list_type)106276a5241fSHans Petter Selasky static void mlx5e_vport_context_update_addr_list(struct mlx5e_priv *priv,
106376a5241fSHans Petter Selasky int list_type)
106476a5241fSHans Petter Selasky {
106576a5241fSHans Petter Selasky bool is_uc = (list_type == MLX5_NIC_VPORT_LIST_TYPE_UC);
106676a5241fSHans Petter Selasky struct mlx5e_eth_addr_hash_node *hn;
106776a5241fSHans Petter Selasky u8 (*addr_array)[ETH_ALEN] = NULL;
106876a5241fSHans Petter Selasky struct mlx5e_eth_addr_hash_head *addr_list;
106976a5241fSHans Petter Selasky struct mlx5e_eth_addr_hash_node *tmp;
107076a5241fSHans Petter Selasky int max_size;
107176a5241fSHans Petter Selasky int size;
107276a5241fSHans Petter Selasky int err;
107376a5241fSHans Petter Selasky int hi;
107476a5241fSHans Petter Selasky
107576a5241fSHans Petter Selasky size = is_uc ? 0 : (priv->eth_addr.broadcast_enabled ? 1 : 0);
107676a5241fSHans Petter Selasky max_size = is_uc ?
107776a5241fSHans Petter Selasky 1 << MLX5_CAP_GEN(priv->mdev, log_max_current_uc_list) :
107876a5241fSHans Petter Selasky 1 << MLX5_CAP_GEN(priv->mdev, log_max_current_mc_list);
107976a5241fSHans Petter Selasky
108076a5241fSHans Petter Selasky addr_list = is_uc ? priv->eth_addr.if_uc : priv->eth_addr.if_mc;
108176a5241fSHans Petter Selasky mlx5e_for_each_hash_node(hn, tmp, addr_list, hi)
108276a5241fSHans Petter Selasky size++;
108376a5241fSHans Petter Selasky
108476a5241fSHans Petter Selasky if (size > max_size) {
10856b4040d8SHans Petter Selasky mlx5_en_err(priv->ifp,
108676a5241fSHans Petter Selasky "ifp %s list size (%d) > (%d) max vport list size, some addresses will be dropped\n",
108776a5241fSHans Petter Selasky is_uc ? "UC" : "MC", size, max_size);
108876a5241fSHans Petter Selasky size = max_size;
108976a5241fSHans Petter Selasky }
109076a5241fSHans Petter Selasky
109176a5241fSHans Petter Selasky if (size) {
109276a5241fSHans Petter Selasky addr_array = kcalloc(size, ETH_ALEN, GFP_KERNEL);
109376a5241fSHans Petter Selasky if (!addr_array) {
109476a5241fSHans Petter Selasky err = -ENOMEM;
109576a5241fSHans Petter Selasky goto out;
109676a5241fSHans Petter Selasky }
109776a5241fSHans Petter Selasky mlx5e_fill_addr_array(priv, list_type, addr_array, size);
109876a5241fSHans Petter Selasky }
109976a5241fSHans Petter Selasky
110076a5241fSHans Petter Selasky err = mlx5_modify_nic_vport_mac_list(priv->mdev, list_type, addr_array, size);
110176a5241fSHans Petter Selasky out:
110276a5241fSHans Petter Selasky if (err)
11036b4040d8SHans Petter Selasky mlx5_en_err(priv->ifp,
110476a5241fSHans Petter Selasky "Failed to modify vport %s list err(%d)\n",
110576a5241fSHans Petter Selasky is_uc ? "UC" : "MC", err);
110676a5241fSHans Petter Selasky kfree(addr_array);
110776a5241fSHans Petter Selasky }
110876a5241fSHans Petter Selasky
mlx5e_vport_context_update(struct mlx5e_priv * priv)110976a5241fSHans Petter Selasky static void mlx5e_vport_context_update(struct mlx5e_priv *priv)
111076a5241fSHans Petter Selasky {
111176a5241fSHans Petter Selasky struct mlx5e_eth_addr_db *ea = &priv->eth_addr;
111276a5241fSHans Petter Selasky
111376a5241fSHans Petter Selasky mlx5e_vport_context_update_addr_list(priv, MLX5_NIC_VPORT_LIST_TYPE_UC);
111476a5241fSHans Petter Selasky mlx5e_vport_context_update_addr_list(priv, MLX5_NIC_VPORT_LIST_TYPE_MC);
111576a5241fSHans Petter Selasky mlx5_modify_nic_vport_promisc(priv->mdev, 0,
111676a5241fSHans Petter Selasky ea->allmulti_enabled,
111776a5241fSHans Petter Selasky ea->promisc_enabled);
111876a5241fSHans Petter Selasky }
111976a5241fSHans Petter Selasky
1120dc7e38acSHans Petter Selasky static void
mlx5e_apply_ifp_addr(struct mlx5e_priv * priv)1121dc7e38acSHans Petter Selasky mlx5e_apply_ifp_addr(struct mlx5e_priv *priv)
1122dc7e38acSHans Petter Selasky {
1123dc7e38acSHans Petter Selasky struct mlx5e_eth_addr_hash_node *hn;
1124dc7e38acSHans Petter Selasky struct mlx5e_eth_addr_hash_node *tmp;
1125dc7e38acSHans Petter Selasky int i;
1126dc7e38acSHans Petter Selasky
1127dc7e38acSHans Petter Selasky mlx5e_for_each_hash_node(hn, tmp, priv->eth_addr.if_uc, i)
1128dc7e38acSHans Petter Selasky mlx5e_execute_action(priv, hn);
1129dc7e38acSHans Petter Selasky
1130dc7e38acSHans Petter Selasky mlx5e_for_each_hash_node(hn, tmp, priv->eth_addr.if_mc, i)
1131dc7e38acSHans Petter Selasky mlx5e_execute_action(priv, hn);
1132dc7e38acSHans Petter Selasky }
1133dc7e38acSHans Petter Selasky
1134dc7e38acSHans Petter Selasky static void
mlx5e_handle_ifp_addr(struct mlx5e_priv * priv,bool rx_mode_enable)113504f407a3SHans Petter Selasky mlx5e_handle_ifp_addr(struct mlx5e_priv *priv, bool rx_mode_enable)
1136dc7e38acSHans Petter Selasky {
1137dc7e38acSHans Petter Selasky struct mlx5e_eth_addr_hash_node *hn;
1138dc7e38acSHans Petter Selasky struct mlx5e_eth_addr_hash_node *tmp;
1139dc7e38acSHans Petter Selasky int i;
1140dc7e38acSHans Petter Selasky
1141dc7e38acSHans Petter Selasky mlx5e_for_each_hash_node(hn, tmp, priv->eth_addr.if_uc, i)
1142dc7e38acSHans Petter Selasky hn->action = MLX5E_ACTION_DEL;
1143dc7e38acSHans Petter Selasky mlx5e_for_each_hash_node(hn, tmp, priv->eth_addr.if_mc, i)
1144dc7e38acSHans Petter Selasky hn->action = MLX5E_ACTION_DEL;
1145dc7e38acSHans Petter Selasky
114604f407a3SHans Petter Selasky if (rx_mode_enable)
1147dc7e38acSHans Petter Selasky mlx5e_sync_ifp_addr(priv);
1148dc7e38acSHans Petter Selasky
1149dc7e38acSHans Petter Selasky mlx5e_apply_ifp_addr(priv);
1150dc7e38acSHans Petter Selasky }
1151dc7e38acSHans Petter Selasky
1152e059c120SHans Petter Selasky static void
mlx5e_set_rx_mode_core(struct mlx5e_priv * priv,bool rx_mode_enable)1153e059c120SHans Petter Selasky mlx5e_set_rx_mode_core(struct mlx5e_priv *priv, bool rx_mode_enable)
1154dc7e38acSHans Petter Selasky {
1155dc7e38acSHans Petter Selasky struct mlx5e_eth_addr_db *ea = &priv->eth_addr;
11565dc00f00SJustin Hibbits if_t ndev = priv->ifp;
11575dc00f00SJustin Hibbits int ndev_flags = if_getflags(ndev);
1158dc7e38acSHans Petter Selasky
11595dc00f00SJustin Hibbits bool promisc_enabled = rx_mode_enable && (ndev_flags & IFF_PROMISC);
11605dc00f00SJustin Hibbits bool allmulti_enabled = rx_mode_enable && (ndev_flags & IFF_ALLMULTI);
1161dc7e38acSHans Petter Selasky bool broadcast_enabled = rx_mode_enable;
1162dc7e38acSHans Petter Selasky
1163dc7e38acSHans Petter Selasky bool enable_promisc = !ea->promisc_enabled && promisc_enabled;
1164dc7e38acSHans Petter Selasky bool disable_promisc = ea->promisc_enabled && !promisc_enabled;
1165dc7e38acSHans Petter Selasky bool enable_allmulti = !ea->allmulti_enabled && allmulti_enabled;
1166dc7e38acSHans Petter Selasky bool disable_allmulti = ea->allmulti_enabled && !allmulti_enabled;
1167dc7e38acSHans Petter Selasky bool enable_broadcast = !ea->broadcast_enabled && broadcast_enabled;
1168dc7e38acSHans Petter Selasky bool disable_broadcast = ea->broadcast_enabled && !broadcast_enabled;
1169dc7e38acSHans Petter Selasky
1170dc7e38acSHans Petter Selasky /* update broadcast address */
1171dc7e38acSHans Petter Selasky ether_addr_copy(priv->eth_addr.broadcast.addr,
11725dc00f00SJustin Hibbits if_getbroadcastaddr(priv->ifp));
1173dc7e38acSHans Petter Selasky
11745a93b4cdSHans Petter Selasky if (enable_promisc) {
1175dc7e38acSHans Petter Selasky mlx5e_add_eth_addr_rule(priv, &ea->promisc, MLX5E_PROMISC);
11765a93b4cdSHans Petter Selasky if (!priv->vlan.filter_disabled)
11775a93b4cdSHans Petter Selasky mlx5e_add_any_vid_rules(priv);
11785a93b4cdSHans Petter Selasky }
1179dc7e38acSHans Petter Selasky if (enable_allmulti)
1180dc7e38acSHans Petter Selasky mlx5e_add_eth_addr_rule(priv, &ea->allmulti, MLX5E_ALLMULTI);
1181dc7e38acSHans Petter Selasky if (enable_broadcast)
1182dc7e38acSHans Petter Selasky mlx5e_add_eth_addr_rule(priv, &ea->broadcast, MLX5E_FULLMATCH);
1183dc7e38acSHans Petter Selasky
118404f407a3SHans Petter Selasky mlx5e_handle_ifp_addr(priv, rx_mode_enable);
1185dc7e38acSHans Petter Selasky
1186dc7e38acSHans Petter Selasky if (disable_broadcast)
1187dc7e38acSHans Petter Selasky mlx5e_del_eth_addr_from_flow_table(priv, &ea->broadcast);
1188dc7e38acSHans Petter Selasky if (disable_allmulti)
1189dc7e38acSHans Petter Selasky mlx5e_del_eth_addr_from_flow_table(priv, &ea->allmulti);
11905a93b4cdSHans Petter Selasky if (disable_promisc) {
11915a93b4cdSHans Petter Selasky if (!priv->vlan.filter_disabled)
11925a93b4cdSHans Petter Selasky mlx5e_del_any_vid_rules(priv);
1193dc7e38acSHans Petter Selasky mlx5e_del_eth_addr_from_flow_table(priv, &ea->promisc);
11945a93b4cdSHans Petter Selasky }
1195dc7e38acSHans Petter Selasky
1196dc7e38acSHans Petter Selasky ea->promisc_enabled = promisc_enabled;
1197dc7e38acSHans Petter Selasky ea->allmulti_enabled = allmulti_enabled;
1198dc7e38acSHans Petter Selasky ea->broadcast_enabled = broadcast_enabled;
119976a5241fSHans Petter Selasky
120076a5241fSHans Petter Selasky mlx5e_vport_context_update(priv);
1201dc7e38acSHans Petter Selasky }
1202dc7e38acSHans Petter Selasky
1203dc7e38acSHans Petter Selasky void
mlx5e_set_rx_mode_work(struct work_struct * work)1204dc7e38acSHans Petter Selasky mlx5e_set_rx_mode_work(struct work_struct *work)
1205dc7e38acSHans Petter Selasky {
1206dc7e38acSHans Petter Selasky struct mlx5e_priv *priv =
1207dc7e38acSHans Petter Selasky container_of(work, struct mlx5e_priv, set_rx_mode_work);
1208dc7e38acSHans Petter Selasky
1209dc7e38acSHans Petter Selasky PRIV_LOCK(priv);
1210e059c120SHans Petter Selasky if (test_bit(MLX5E_STATE_FLOW_RULES_READY, &priv->state))
1211e059c120SHans Petter Selasky mlx5e_set_rx_mode_core(priv, true);
1212dc7e38acSHans Petter Selasky PRIV_UNLOCK(priv);
1213dc7e38acSHans Petter Selasky }
1214dc7e38acSHans Petter Selasky
12155a93b4cdSHans Petter Selasky static void
mlx5e_destroy_groups(struct mlx5e_flow_table * ft)12165a93b4cdSHans Petter Selasky mlx5e_destroy_groups(struct mlx5e_flow_table *ft)
1217dc7e38acSHans Petter Selasky {
12185a93b4cdSHans Petter Selasky int i;
1219dc7e38acSHans Petter Selasky
12205a93b4cdSHans Petter Selasky for (i = ft->num_groups - 1; i >= 0; i--) {
12215a93b4cdSHans Petter Selasky if (!IS_ERR_OR_NULL(ft->g[i]))
12225a93b4cdSHans Petter Selasky mlx5_destroy_flow_group(ft->g[i]);
12235a93b4cdSHans Petter Selasky ft->g[i] = NULL;
12245a93b4cdSHans Petter Selasky }
12255a93b4cdSHans Petter Selasky ft->num_groups = 0;
1226dc7e38acSHans Petter Selasky }
1227dc7e38acSHans Petter Selasky
1228dc7e38acSHans Petter Selasky static void
mlx5e_destroy_flow_table(struct mlx5e_flow_table * ft)12295a93b4cdSHans Petter Selasky mlx5e_destroy_flow_table(struct mlx5e_flow_table *ft)
1230dc7e38acSHans Petter Selasky {
12315a93b4cdSHans Petter Selasky mlx5e_destroy_groups(ft);
12325a93b4cdSHans Petter Selasky kfree(ft->g);
12335a93b4cdSHans Petter Selasky mlx5_destroy_flow_table(ft->t);
12345a93b4cdSHans Petter Selasky ft->t = NULL;
12355a93b4cdSHans Petter Selasky }
12365a93b4cdSHans Petter Selasky
12375a93b4cdSHans Petter Selasky #define MLX5E_NUM_MAIN_GROUPS 10
12385a93b4cdSHans Petter Selasky #define MLX5E_MAIN_GROUP0_SIZE BIT(4)
12395a93b4cdSHans Petter Selasky #define MLX5E_MAIN_GROUP1_SIZE BIT(3)
12405a93b4cdSHans Petter Selasky #define MLX5E_MAIN_GROUP2_SIZE BIT(1)
12415a93b4cdSHans Petter Selasky #define MLX5E_MAIN_GROUP3_SIZE BIT(0)
12425a93b4cdSHans Petter Selasky #define MLX5E_MAIN_GROUP4_SIZE BIT(14)
12435a93b4cdSHans Petter Selasky #define MLX5E_MAIN_GROUP5_SIZE BIT(13)
12445a93b4cdSHans Petter Selasky #define MLX5E_MAIN_GROUP6_SIZE BIT(11)
12455a93b4cdSHans Petter Selasky #define MLX5E_MAIN_GROUP7_SIZE BIT(2)
12465a93b4cdSHans Petter Selasky #define MLX5E_MAIN_GROUP8_SIZE BIT(1)
12475a93b4cdSHans Petter Selasky #define MLX5E_MAIN_GROUP9_SIZE BIT(0)
12485a93b4cdSHans Petter Selasky #define MLX5E_MAIN_TABLE_SIZE (MLX5E_MAIN_GROUP0_SIZE +\
12495a93b4cdSHans Petter Selasky MLX5E_MAIN_GROUP1_SIZE +\
12505a93b4cdSHans Petter Selasky MLX5E_MAIN_GROUP2_SIZE +\
12515a93b4cdSHans Petter Selasky MLX5E_MAIN_GROUP3_SIZE +\
12525a93b4cdSHans Petter Selasky MLX5E_MAIN_GROUP4_SIZE +\
12535a93b4cdSHans Petter Selasky MLX5E_MAIN_GROUP5_SIZE +\
12545a93b4cdSHans Petter Selasky MLX5E_MAIN_GROUP6_SIZE +\
12555a93b4cdSHans Petter Selasky MLX5E_MAIN_GROUP7_SIZE +\
12565a93b4cdSHans Petter Selasky MLX5E_MAIN_GROUP8_SIZE +\
12575a93b4cdSHans Petter Selasky MLX5E_MAIN_GROUP9_SIZE +\
12585a93b4cdSHans Petter Selasky 0)
12595a93b4cdSHans Petter Selasky
12605a93b4cdSHans Petter Selasky static int
mlx5e_create_main_groups_sub(struct mlx5e_flow_table * ft,u32 * in,int inlen)12615a93b4cdSHans Petter Selasky mlx5e_create_main_groups_sub(struct mlx5e_flow_table *ft, u32 *in,
12625a93b4cdSHans Petter Selasky int inlen)
12635a93b4cdSHans Petter Selasky {
12645a93b4cdSHans Petter Selasky u8 *mc = MLX5_ADDR_OF(create_flow_group_in, in, match_criteria);
12655a93b4cdSHans Petter Selasky u8 *dmac = MLX5_ADDR_OF(create_flow_group_in, in,
12665a93b4cdSHans Petter Selasky match_criteria.outer_headers.dmac_47_16);
12675a93b4cdSHans Petter Selasky int err;
12685a93b4cdSHans Petter Selasky int ix = 0;
12695a93b4cdSHans Petter Selasky
12705a93b4cdSHans Petter Selasky /* Tunnel rules need to be first in this list of groups */
12715a93b4cdSHans Petter Selasky
12725a93b4cdSHans Petter Selasky /* Start tunnel rules */
12735a93b4cdSHans Petter Selasky memset(in, 0, inlen);
12745a93b4cdSHans Petter Selasky MLX5_SET_CFG(in, match_criteria_enable, MLX5_MATCH_OUTER_HEADERS);
12755a93b4cdSHans Petter Selasky MLX5_SET_TO_ONES(fte_match_param, mc, outer_headers.ethertype);
12765a93b4cdSHans Petter Selasky MLX5_SET_TO_ONES(fte_match_param, mc, outer_headers.ip_protocol);
12775a93b4cdSHans Petter Selasky MLX5_SET_TO_ONES(fte_match_param, mc, outer_headers.udp_dport);
12785a93b4cdSHans Petter Selasky MLX5_SET_CFG(in, start_flow_index, ix);
12795a93b4cdSHans Petter Selasky ix += MLX5E_MAIN_GROUP0_SIZE;
12805a93b4cdSHans Petter Selasky MLX5_SET_CFG(in, end_flow_index, ix - 1);
12815a93b4cdSHans Petter Selasky ft->g[ft->num_groups] = mlx5_create_flow_group(ft->t, in);
12825a93b4cdSHans Petter Selasky if (IS_ERR(ft->g[ft->num_groups]))
12835a93b4cdSHans Petter Selasky goto err_destory_groups;
12845a93b4cdSHans Petter Selasky ft->num_groups++;
12855a93b4cdSHans Petter Selasky /* End Tunnel Rules */
12865a93b4cdSHans Petter Selasky
12875a93b4cdSHans Petter Selasky memset(in, 0, inlen);
12885a93b4cdSHans Petter Selasky MLX5_SET_CFG(in, match_criteria_enable, MLX5_MATCH_OUTER_HEADERS);
12895a93b4cdSHans Petter Selasky MLX5_SET_TO_ONES(fte_match_param, mc, outer_headers.ethertype);
12905a93b4cdSHans Petter Selasky MLX5_SET_TO_ONES(fte_match_param, mc, outer_headers.ip_protocol);
12915a93b4cdSHans Petter Selasky MLX5_SET_CFG(in, start_flow_index, ix);
12925a93b4cdSHans Petter Selasky ix += MLX5E_MAIN_GROUP1_SIZE;
12935a93b4cdSHans Petter Selasky MLX5_SET_CFG(in, end_flow_index, ix - 1);
12945a93b4cdSHans Petter Selasky ft->g[ft->num_groups] = mlx5_create_flow_group(ft->t, in);
12955a93b4cdSHans Petter Selasky if (IS_ERR(ft->g[ft->num_groups]))
12965a93b4cdSHans Petter Selasky goto err_destory_groups;
12975a93b4cdSHans Petter Selasky ft->num_groups++;
12985a93b4cdSHans Petter Selasky
12995a93b4cdSHans Petter Selasky memset(in, 0, inlen);
13005a93b4cdSHans Petter Selasky MLX5_SET_CFG(in, match_criteria_enable, MLX5_MATCH_OUTER_HEADERS);
13015a93b4cdSHans Petter Selasky MLX5_SET_TO_ONES(fte_match_param, mc, outer_headers.ethertype);
13025a93b4cdSHans Petter Selasky MLX5_SET_CFG(in, start_flow_index, ix);
13035a93b4cdSHans Petter Selasky ix += MLX5E_MAIN_GROUP2_SIZE;
13045a93b4cdSHans Petter Selasky MLX5_SET_CFG(in, end_flow_index, ix - 1);
13055a93b4cdSHans Petter Selasky ft->g[ft->num_groups] = mlx5_create_flow_group(ft->t, in);
13065a93b4cdSHans Petter Selasky if (IS_ERR(ft->g[ft->num_groups]))
13075a93b4cdSHans Petter Selasky goto err_destory_groups;
13085a93b4cdSHans Petter Selasky ft->num_groups++;
13095a93b4cdSHans Petter Selasky
13105a93b4cdSHans Petter Selasky memset(in, 0, inlen);
13115a93b4cdSHans Petter Selasky MLX5_SET_CFG(in, start_flow_index, ix);
13125a93b4cdSHans Petter Selasky ix += MLX5E_MAIN_GROUP3_SIZE;
13135a93b4cdSHans Petter Selasky MLX5_SET_CFG(in, end_flow_index, ix - 1);
13145a93b4cdSHans Petter Selasky ft->g[ft->num_groups] = mlx5_create_flow_group(ft->t, in);
13155a93b4cdSHans Petter Selasky if (IS_ERR(ft->g[ft->num_groups]))
13165a93b4cdSHans Petter Selasky goto err_destory_groups;
13175a93b4cdSHans Petter Selasky ft->num_groups++;
13185a93b4cdSHans Petter Selasky
13195a93b4cdSHans Petter Selasky memset(in, 0, inlen);
13205a93b4cdSHans Petter Selasky MLX5_SET_CFG(in, match_criteria_enable, MLX5_MATCH_OUTER_HEADERS);
13215a93b4cdSHans Petter Selasky MLX5_SET_TO_ONES(fte_match_param, mc, outer_headers.ethertype);
13225a93b4cdSHans Petter Selasky MLX5_SET_TO_ONES(fte_match_param, mc, outer_headers.ip_protocol);
13235a93b4cdSHans Petter Selasky memset(dmac, 0xff, ETH_ALEN);
13245a93b4cdSHans Petter Selasky MLX5_SET_CFG(in, start_flow_index, ix);
13255a93b4cdSHans Petter Selasky ix += MLX5E_MAIN_GROUP4_SIZE;
13265a93b4cdSHans Petter Selasky MLX5_SET_CFG(in, end_flow_index, ix - 1);
13275a93b4cdSHans Petter Selasky ft->g[ft->num_groups] = mlx5_create_flow_group(ft->t, in);
13285a93b4cdSHans Petter Selasky if (IS_ERR(ft->g[ft->num_groups]))
13295a93b4cdSHans Petter Selasky goto err_destory_groups;
13305a93b4cdSHans Petter Selasky ft->num_groups++;
13315a93b4cdSHans Petter Selasky
13325a93b4cdSHans Petter Selasky memset(in, 0, inlen);
13335a93b4cdSHans Petter Selasky MLX5_SET_CFG(in, match_criteria_enable, MLX5_MATCH_OUTER_HEADERS);
13345a93b4cdSHans Petter Selasky MLX5_SET_TO_ONES(fte_match_param, mc, outer_headers.ethertype);
13355a93b4cdSHans Petter Selasky memset(dmac, 0xff, ETH_ALEN);
13365a93b4cdSHans Petter Selasky MLX5_SET_CFG(in, start_flow_index, ix);
13375a93b4cdSHans Petter Selasky ix += MLX5E_MAIN_GROUP5_SIZE;
13385a93b4cdSHans Petter Selasky MLX5_SET_CFG(in, end_flow_index, ix - 1);
13395a93b4cdSHans Petter Selasky ft->g[ft->num_groups] = mlx5_create_flow_group(ft->t, in);
13405a93b4cdSHans Petter Selasky if (IS_ERR(ft->g[ft->num_groups]))
13415a93b4cdSHans Petter Selasky goto err_destory_groups;
13425a93b4cdSHans Petter Selasky ft->num_groups++;
13435a93b4cdSHans Petter Selasky
13445a93b4cdSHans Petter Selasky memset(in, 0, inlen);
13455a93b4cdSHans Petter Selasky MLX5_SET_CFG(in, match_criteria_enable, MLX5_MATCH_OUTER_HEADERS);
13465a93b4cdSHans Petter Selasky memset(dmac, 0xff, ETH_ALEN);
13475a93b4cdSHans Petter Selasky MLX5_SET_CFG(in, start_flow_index, ix);
13485a93b4cdSHans Petter Selasky ix += MLX5E_MAIN_GROUP6_SIZE;
13495a93b4cdSHans Petter Selasky MLX5_SET_CFG(in, end_flow_index, ix - 1);
13505a93b4cdSHans Petter Selasky ft->g[ft->num_groups] = mlx5_create_flow_group(ft->t, in);
13515a93b4cdSHans Petter Selasky if (IS_ERR(ft->g[ft->num_groups]))
13525a93b4cdSHans Petter Selasky goto err_destory_groups;
13535a93b4cdSHans Petter Selasky ft->num_groups++;
13545a93b4cdSHans Petter Selasky
13555a93b4cdSHans Petter Selasky memset(in, 0, inlen);
13565a93b4cdSHans Petter Selasky MLX5_SET_CFG(in, match_criteria_enable, MLX5_MATCH_OUTER_HEADERS);
13575a93b4cdSHans Petter Selasky MLX5_SET_TO_ONES(fte_match_param, mc, outer_headers.ethertype);
13585a93b4cdSHans Petter Selasky MLX5_SET_TO_ONES(fte_match_param, mc, outer_headers.ip_protocol);
13595a93b4cdSHans Petter Selasky dmac[0] = 0x01;
13605a93b4cdSHans Petter Selasky MLX5_SET_CFG(in, start_flow_index, ix);
13615a93b4cdSHans Petter Selasky ix += MLX5E_MAIN_GROUP7_SIZE;
13625a93b4cdSHans Petter Selasky MLX5_SET_CFG(in, end_flow_index, ix - 1);
13635a93b4cdSHans Petter Selasky ft->g[ft->num_groups] = mlx5_create_flow_group(ft->t, in);
13645a93b4cdSHans Petter Selasky if (IS_ERR(ft->g[ft->num_groups]))
13655a93b4cdSHans Petter Selasky goto err_destory_groups;
13665a93b4cdSHans Petter Selasky ft->num_groups++;
13675a93b4cdSHans Petter Selasky
13685a93b4cdSHans Petter Selasky memset(in, 0, inlen);
13695a93b4cdSHans Petter Selasky MLX5_SET_CFG(in, match_criteria_enable, MLX5_MATCH_OUTER_HEADERS);
13705a93b4cdSHans Petter Selasky MLX5_SET_TO_ONES(fte_match_param, mc, outer_headers.ethertype);
13715a93b4cdSHans Petter Selasky dmac[0] = 0x01;
13725a93b4cdSHans Petter Selasky MLX5_SET_CFG(in, start_flow_index, ix);
13735a93b4cdSHans Petter Selasky ix += MLX5E_MAIN_GROUP8_SIZE;
13745a93b4cdSHans Petter Selasky MLX5_SET_CFG(in, end_flow_index, ix - 1);
13755a93b4cdSHans Petter Selasky ft->g[ft->num_groups] = mlx5_create_flow_group(ft->t, in);
13765a93b4cdSHans Petter Selasky if (IS_ERR(ft->g[ft->num_groups]))
13775a93b4cdSHans Petter Selasky goto err_destory_groups;
13785a93b4cdSHans Petter Selasky ft->num_groups++;
13795a93b4cdSHans Petter Selasky
13805a93b4cdSHans Petter Selasky memset(in, 0, inlen);
13815a93b4cdSHans Petter Selasky MLX5_SET_CFG(in, match_criteria_enable, MLX5_MATCH_OUTER_HEADERS);
13825a93b4cdSHans Petter Selasky dmac[0] = 0x01;
13835a93b4cdSHans Petter Selasky MLX5_SET_CFG(in, start_flow_index, ix);
13845a93b4cdSHans Petter Selasky ix += MLX5E_MAIN_GROUP9_SIZE;
13855a93b4cdSHans Petter Selasky MLX5_SET_CFG(in, end_flow_index, ix - 1);
13865a93b4cdSHans Petter Selasky ft->g[ft->num_groups] = mlx5_create_flow_group(ft->t, in);
13875a93b4cdSHans Petter Selasky if (IS_ERR(ft->g[ft->num_groups]))
13885a93b4cdSHans Petter Selasky goto err_destory_groups;
13895a93b4cdSHans Petter Selasky ft->num_groups++;
13905a93b4cdSHans Petter Selasky
13915a93b4cdSHans Petter Selasky return (0);
13925a93b4cdSHans Petter Selasky
13935a93b4cdSHans Petter Selasky err_destory_groups:
13945a93b4cdSHans Petter Selasky err = PTR_ERR(ft->g[ft->num_groups]);
13955a93b4cdSHans Petter Selasky ft->g[ft->num_groups] = NULL;
13965a93b4cdSHans Petter Selasky mlx5e_destroy_groups(ft);
13975a93b4cdSHans Petter Selasky
13985a93b4cdSHans Petter Selasky return (err);
13995a93b4cdSHans Petter Selasky }
14005a93b4cdSHans Petter Selasky
14015a93b4cdSHans Petter Selasky static int
mlx5e_create_main_groups(struct mlx5e_flow_table * ft)14025a93b4cdSHans Petter Selasky mlx5e_create_main_groups(struct mlx5e_flow_table *ft)
14035a93b4cdSHans Petter Selasky {
14045a93b4cdSHans Petter Selasky u32 *in;
14055a93b4cdSHans Petter Selasky int inlen = MLX5_ST_SZ_BYTES(create_flow_group_in);
14065a93b4cdSHans Petter Selasky int err;
14075a93b4cdSHans Petter Selasky
14085a93b4cdSHans Petter Selasky in = mlx5_vzalloc(inlen);
14095a93b4cdSHans Petter Selasky if (!in)
14105a93b4cdSHans Petter Selasky return (-ENOMEM);
14115a93b4cdSHans Petter Selasky
14125a93b4cdSHans Petter Selasky err = mlx5e_create_main_groups_sub(ft, in, inlen);
14135a93b4cdSHans Petter Selasky
14145a93b4cdSHans Petter Selasky kvfree(in);
14155a93b4cdSHans Petter Selasky return (err);
14165a93b4cdSHans Petter Selasky }
14175a93b4cdSHans Petter Selasky
1418861a612dSKonstantin Belousov #define MLX5E_MAIN_VXLAN_GROUP0_SIZE BIT(3)
1419861a612dSKonstantin Belousov #define MLX5E_MAIN_VXLAN_GROUP1_SIZE BIT(3)
1420861a612dSKonstantin Belousov #define MLX5E_MAIN_VXLAN_GROUP2_SIZE BIT(0)
1421861a612dSKonstantin Belousov static int
mlx5e_create_main_vxlan_groups_sub(struct mlx5e_flow_table * ft,u32 * in,int inlen)1422861a612dSKonstantin Belousov mlx5e_create_main_vxlan_groups_sub(struct mlx5e_flow_table *ft, u32 *in,
1423861a612dSKonstantin Belousov int inlen)
14245a93b4cdSHans Petter Selasky {
1425861a612dSKonstantin Belousov u8 *mc = MLX5_ADDR_OF(create_flow_group_in, in, match_criteria);
1426861a612dSKonstantin Belousov int err;
1427861a612dSKonstantin Belousov int ix = 0;
1428861a612dSKonstantin Belousov
1429861a612dSKonstantin Belousov memset(in, 0, inlen);
1430861a612dSKonstantin Belousov MLX5_SET_CFG(in, match_criteria_enable, MLX5_MATCH_INNER_HEADERS);
1431861a612dSKonstantin Belousov MLX5_SET_TO_ONES(fte_match_param, mc, inner_headers.ethertype);
1432861a612dSKonstantin Belousov MLX5_SET_TO_ONES(fte_match_param, mc, inner_headers.ip_protocol);
1433861a612dSKonstantin Belousov MLX5_SET_CFG(in, start_flow_index, ix);
1434861a612dSKonstantin Belousov ix += MLX5E_MAIN_VXLAN_GROUP0_SIZE;
1435861a612dSKonstantin Belousov MLX5_SET_CFG(in, end_flow_index, ix - 1);
1436861a612dSKonstantin Belousov ft->g[ft->num_groups] = mlx5_create_flow_group(ft->t, in);
1437861a612dSKonstantin Belousov if (IS_ERR(ft->g[ft->num_groups]))
1438861a612dSKonstantin Belousov goto err_destory_groups;
1439861a612dSKonstantin Belousov ft->num_groups++;
1440861a612dSKonstantin Belousov
1441861a612dSKonstantin Belousov memset(in, 0, inlen);
1442861a612dSKonstantin Belousov MLX5_SET_CFG(in, match_criteria_enable, MLX5_MATCH_INNER_HEADERS);
1443861a612dSKonstantin Belousov MLX5_SET_TO_ONES(fte_match_param, mc, inner_headers.ethertype);
1444861a612dSKonstantin Belousov MLX5_SET_CFG(in, start_flow_index, ix);
1445861a612dSKonstantin Belousov ix += MLX5E_MAIN_VXLAN_GROUP1_SIZE;
1446861a612dSKonstantin Belousov MLX5_SET_CFG(in, end_flow_index, ix - 1);
1447861a612dSKonstantin Belousov ft->g[ft->num_groups] = mlx5_create_flow_group(ft->t, in);
1448861a612dSKonstantin Belousov if (IS_ERR(ft->g[ft->num_groups]))
1449861a612dSKonstantin Belousov goto err_destory_groups;
1450861a612dSKonstantin Belousov ft->num_groups++;
1451861a612dSKonstantin Belousov
1452861a612dSKonstantin Belousov memset(in, 0, inlen);
1453861a612dSKonstantin Belousov MLX5_SET_CFG(in, start_flow_index, ix);
1454861a612dSKonstantin Belousov ix += MLX5E_MAIN_VXLAN_GROUP2_SIZE;
1455861a612dSKonstantin Belousov MLX5_SET_CFG(in, end_flow_index, ix - 1);
1456861a612dSKonstantin Belousov ft->g[ft->num_groups] = mlx5_create_flow_group(ft->t, in);
1457861a612dSKonstantin Belousov if (IS_ERR(ft->g[ft->num_groups]))
1458861a612dSKonstantin Belousov goto err_destory_groups;
1459861a612dSKonstantin Belousov ft->num_groups++;
1460861a612dSKonstantin Belousov
1461861a612dSKonstantin Belousov return (0);
1462861a612dSKonstantin Belousov
1463861a612dSKonstantin Belousov err_destory_groups:
1464861a612dSKonstantin Belousov err = PTR_ERR(ft->g[ft->num_groups]);
1465861a612dSKonstantin Belousov ft->g[ft->num_groups] = NULL;
1466861a612dSKonstantin Belousov mlx5e_destroy_groups(ft);
1467861a612dSKonstantin Belousov
1468861a612dSKonstantin Belousov return (err);
1469861a612dSKonstantin Belousov }
1470861a612dSKonstantin Belousov
1471861a612dSKonstantin Belousov static int
mlx5e_create_main_vxlan_groups(struct mlx5e_flow_table * ft)1472861a612dSKonstantin Belousov mlx5e_create_main_vxlan_groups(struct mlx5e_flow_table *ft)
1473861a612dSKonstantin Belousov {
1474861a612dSKonstantin Belousov u32 *in;
1475861a612dSKonstantin Belousov int inlen = MLX5_ST_SZ_BYTES(create_flow_group_in);
1476861a612dSKonstantin Belousov int err;
1477861a612dSKonstantin Belousov
1478861a612dSKonstantin Belousov in = mlx5_vzalloc(inlen);
1479861a612dSKonstantin Belousov if (!in)
1480861a612dSKonstantin Belousov return (-ENOMEM);
1481861a612dSKonstantin Belousov
1482861a612dSKonstantin Belousov err = mlx5e_create_main_vxlan_groups_sub(ft, in, inlen);
1483861a612dSKonstantin Belousov
1484861a612dSKonstantin Belousov kvfree(in);
1485861a612dSKonstantin Belousov return (err);
1486861a612dSKonstantin Belousov }
1487861a612dSKonstantin Belousov
1488861a612dSKonstantin Belousov
1489861a612dSKonstantin Belousov static int
mlx5e_create_main_flow_table(struct mlx5e_priv * priv,bool inner_vxlan)1490861a612dSKonstantin Belousov mlx5e_create_main_flow_table(struct mlx5e_priv *priv, bool inner_vxlan)
1491861a612dSKonstantin Belousov {
1492861a612dSKonstantin Belousov struct mlx5e_flow_table *ft = inner_vxlan ? &priv->fts.main_vxlan :
1493861a612dSKonstantin Belousov &priv->fts.main;
1494e23731dbSKonstantin Belousov struct mlx5_flow_table_attr ft_attr = {};
14955a93b4cdSHans Petter Selasky int err;
14965a93b4cdSHans Petter Selasky
14975a93b4cdSHans Petter Selasky ft->num_groups = 0;
1498e23731dbSKonstantin Belousov ft_attr.max_fte = MLX5E_MAIN_TABLE_SIZE;
1499e23731dbSKonstantin Belousov if (priv->ipsec)
1500e23731dbSKonstantin Belousov ft_attr.level = inner_vxlan ? 10 : 12;
1501e23731dbSKonstantin Belousov else
1502e23731dbSKonstantin Belousov ft_attr.level = inner_vxlan ? 2 : 4;
1503e23731dbSKonstantin Belousov ft->t = mlx5_create_flow_table(priv->fts.ns, &ft_attr);
15045a93b4cdSHans Petter Selasky
15055a93b4cdSHans Petter Selasky if (IS_ERR(ft->t)) {
15065a93b4cdSHans Petter Selasky err = PTR_ERR(ft->t);
15075a93b4cdSHans Petter Selasky ft->t = NULL;
15085a93b4cdSHans Petter Selasky return (err);
15095a93b4cdSHans Petter Selasky }
15105a93b4cdSHans Petter Selasky ft->g = kcalloc(MLX5E_NUM_MAIN_GROUPS, sizeof(*ft->g), GFP_KERNEL);
15115a93b4cdSHans Petter Selasky if (!ft->g) {
15125a93b4cdSHans Petter Selasky err = -ENOMEM;
15135a93b4cdSHans Petter Selasky goto err_destroy_main_flow_table;
15145a93b4cdSHans Petter Selasky }
15155a93b4cdSHans Petter Selasky
1516861a612dSKonstantin Belousov err = inner_vxlan ? mlx5e_create_main_vxlan_groups(ft) :
1517861a612dSKonstantin Belousov mlx5e_create_main_groups(ft);
15185a93b4cdSHans Petter Selasky if (err)
15195a93b4cdSHans Petter Selasky goto err_free_g;
15205a93b4cdSHans Petter Selasky return (0);
15215a93b4cdSHans Petter Selasky
15225a93b4cdSHans Petter Selasky err_free_g:
15235a93b4cdSHans Petter Selasky kfree(ft->g);
15245a93b4cdSHans Petter Selasky
15255a93b4cdSHans Petter Selasky err_destroy_main_flow_table:
15265a93b4cdSHans Petter Selasky mlx5_destroy_flow_table(ft->t);
15275a93b4cdSHans Petter Selasky ft->t = NULL;
15285a93b4cdSHans Petter Selasky
15295a93b4cdSHans Petter Selasky return (err);
15305a93b4cdSHans Petter Selasky }
15315a93b4cdSHans Petter Selasky
mlx5e_destroy_main_flow_table(struct mlx5e_priv * priv)15325a93b4cdSHans Petter Selasky static void mlx5e_destroy_main_flow_table(struct mlx5e_priv *priv)
15335a93b4cdSHans Petter Selasky {
15345a93b4cdSHans Petter Selasky mlx5e_destroy_flow_table(&priv->fts.main);
15355a93b4cdSHans Petter Selasky }
15365a93b4cdSHans Petter Selasky
mlx5e_destroy_main_vxlan_flow_table(struct mlx5e_priv * priv)1537861a612dSKonstantin Belousov static void mlx5e_destroy_main_vxlan_flow_table(struct mlx5e_priv *priv)
1538861a612dSKonstantin Belousov {
1539861a612dSKonstantin Belousov mlx5e_destroy_flow_table(&priv->fts.main_vxlan);
1540861a612dSKonstantin Belousov }
1541861a612dSKonstantin Belousov
15425a93b4cdSHans Petter Selasky #define MLX5E_NUM_VLAN_GROUPS 3
15435a93b4cdSHans Petter Selasky #define MLX5E_VLAN_GROUP0_SIZE BIT(12)
15445a93b4cdSHans Petter Selasky #define MLX5E_VLAN_GROUP1_SIZE BIT(1)
15455a93b4cdSHans Petter Selasky #define MLX5E_VLAN_GROUP2_SIZE BIT(0)
15465a93b4cdSHans Petter Selasky #define MLX5E_VLAN_TABLE_SIZE (MLX5E_VLAN_GROUP0_SIZE +\
15475a93b4cdSHans Petter Selasky MLX5E_VLAN_GROUP1_SIZE +\
15485a93b4cdSHans Petter Selasky MLX5E_VLAN_GROUP2_SIZE +\
15495a93b4cdSHans Petter Selasky 0)
15505a93b4cdSHans Petter Selasky
15515a93b4cdSHans Petter Selasky static int
mlx5e_create_vlan_groups_sub(struct mlx5e_flow_table * ft,u32 * in,int inlen)15525a93b4cdSHans Petter Selasky mlx5e_create_vlan_groups_sub(struct mlx5e_flow_table *ft, u32 *in,
15535a93b4cdSHans Petter Selasky int inlen)
15545a93b4cdSHans Petter Selasky {
15555a93b4cdSHans Petter Selasky int err;
15565a93b4cdSHans Petter Selasky int ix = 0;
15575a93b4cdSHans Petter Selasky u8 *mc = MLX5_ADDR_OF(create_flow_group_in, in, match_criteria);
15585a93b4cdSHans Petter Selasky
15595a93b4cdSHans Petter Selasky memset(in, 0, inlen);
15605a93b4cdSHans Petter Selasky MLX5_SET_CFG(in, match_criteria_enable, MLX5_MATCH_OUTER_HEADERS);
15615a93b4cdSHans Petter Selasky MLX5_SET_TO_ONES(fte_match_param, mc, outer_headers.cvlan_tag);
15625a93b4cdSHans Petter Selasky MLX5_SET_TO_ONES(fte_match_param, mc, outer_headers.first_vid);
15635a93b4cdSHans Petter Selasky MLX5_SET_CFG(in, start_flow_index, ix);
15645a93b4cdSHans Petter Selasky ix += MLX5E_VLAN_GROUP0_SIZE;
15655a93b4cdSHans Petter Selasky MLX5_SET_CFG(in, end_flow_index, ix - 1);
15665a93b4cdSHans Petter Selasky ft->g[ft->num_groups] = mlx5_create_flow_group(ft->t, in);
15675a93b4cdSHans Petter Selasky if (IS_ERR(ft->g[ft->num_groups]))
15685a93b4cdSHans Petter Selasky goto err_destory_groups;
15695a93b4cdSHans Petter Selasky ft->num_groups++;
15705a93b4cdSHans Petter Selasky
15715a93b4cdSHans Petter Selasky memset(in, 0, inlen);
15725a93b4cdSHans Petter Selasky MLX5_SET_CFG(in, match_criteria_enable, MLX5_MATCH_OUTER_HEADERS);
15735a93b4cdSHans Petter Selasky MLX5_SET_TO_ONES(fte_match_param, mc, outer_headers.cvlan_tag);
15745a93b4cdSHans Petter Selasky MLX5_SET_CFG(in, start_flow_index, ix);
15755a93b4cdSHans Petter Selasky ix += MLX5E_VLAN_GROUP1_SIZE;
15765a93b4cdSHans Petter Selasky MLX5_SET_CFG(in, end_flow_index, ix - 1);
15775a93b4cdSHans Petter Selasky ft->g[ft->num_groups] = mlx5_create_flow_group(ft->t, in);
15785a93b4cdSHans Petter Selasky if (IS_ERR(ft->g[ft->num_groups]))
15795a93b4cdSHans Petter Selasky goto err_destory_groups;
15805a93b4cdSHans Petter Selasky ft->num_groups++;
15815a93b4cdSHans Petter Selasky
15825a93b4cdSHans Petter Selasky memset(in, 0, inlen);
15835a93b4cdSHans Petter Selasky MLX5_SET_CFG(in, match_criteria_enable, MLX5_MATCH_OUTER_HEADERS);
15845a93b4cdSHans Petter Selasky MLX5_SET_TO_ONES(fte_match_param, mc, outer_headers.svlan_tag);
15855a93b4cdSHans Petter Selasky MLX5_SET_CFG(in, start_flow_index, ix);
15865a93b4cdSHans Petter Selasky ix += MLX5E_VLAN_GROUP2_SIZE;
15875a93b4cdSHans Petter Selasky MLX5_SET_CFG(in, end_flow_index, ix - 1);
15885a93b4cdSHans Petter Selasky ft->g[ft->num_groups] = mlx5_create_flow_group(ft->t, in);
15895a93b4cdSHans Petter Selasky if (IS_ERR(ft->g[ft->num_groups]))
15905a93b4cdSHans Petter Selasky goto err_destory_groups;
15915a93b4cdSHans Petter Selasky ft->num_groups++;
15925a93b4cdSHans Petter Selasky
15935a93b4cdSHans Petter Selasky return (0);
15945a93b4cdSHans Petter Selasky
15955a93b4cdSHans Petter Selasky err_destory_groups:
15965a93b4cdSHans Petter Selasky err = PTR_ERR(ft->g[ft->num_groups]);
15975a93b4cdSHans Petter Selasky ft->g[ft->num_groups] = NULL;
15985a93b4cdSHans Petter Selasky mlx5e_destroy_groups(ft);
15995a93b4cdSHans Petter Selasky
16005a93b4cdSHans Petter Selasky return (err);
16015a93b4cdSHans Petter Selasky }
16025a93b4cdSHans Petter Selasky
16035a93b4cdSHans Petter Selasky static int
mlx5e_create_vlan_groups(struct mlx5e_flow_table * ft)16045a93b4cdSHans Petter Selasky mlx5e_create_vlan_groups(struct mlx5e_flow_table *ft)
16055a93b4cdSHans Petter Selasky {
16065a93b4cdSHans Petter Selasky u32 *in;
16075a93b4cdSHans Petter Selasky int inlen = MLX5_ST_SZ_BYTES(create_flow_group_in);
16085a93b4cdSHans Petter Selasky int err;
16095a93b4cdSHans Petter Selasky
16105a93b4cdSHans Petter Selasky in = mlx5_vzalloc(inlen);
16115a93b4cdSHans Petter Selasky if (!in)
16125a93b4cdSHans Petter Selasky return (-ENOMEM);
16135a93b4cdSHans Petter Selasky
16145a93b4cdSHans Petter Selasky err = mlx5e_create_vlan_groups_sub(ft, in, inlen);
16155a93b4cdSHans Petter Selasky
16165a93b4cdSHans Petter Selasky kvfree(in);
16175a93b4cdSHans Petter Selasky return (err);
1618dc7e38acSHans Petter Selasky }
1619dc7e38acSHans Petter Selasky
1620dc7e38acSHans Petter Selasky static int
mlx5e_create_vlan_flow_table(struct mlx5e_priv * priv)1621dc7e38acSHans Petter Selasky mlx5e_create_vlan_flow_table(struct mlx5e_priv *priv)
1622dc7e38acSHans Petter Selasky {
16235a93b4cdSHans Petter Selasky struct mlx5e_flow_table *ft = &priv->fts.vlan;
1624e23731dbSKonstantin Belousov struct mlx5_flow_table_attr ft_attr = {};
16255a93b4cdSHans Petter Selasky int err;
1626dc7e38acSHans Petter Selasky
16275a93b4cdSHans Petter Selasky ft->num_groups = 0;
1628e23731dbSKonstantin Belousov ft_attr.max_fte = MLX5E_VLAN_TABLE_SIZE;
1629*080f68d0SAriel Ehrenberg ft_attr.level = (priv->ipsec) ? 9 : 0;
1630e23731dbSKonstantin Belousov ft->t = mlx5_create_flow_table(priv->fts.ns, &ft_attr);
1631dc7e38acSHans Petter Selasky
16325a93b4cdSHans Petter Selasky if (IS_ERR(ft->t)) {
16335a93b4cdSHans Petter Selasky err = PTR_ERR(ft->t);
16345a93b4cdSHans Petter Selasky ft->t = NULL;
16355a93b4cdSHans Petter Selasky return (err);
16365a93b4cdSHans Petter Selasky }
16375a93b4cdSHans Petter Selasky ft->g = kcalloc(MLX5E_NUM_VLAN_GROUPS, sizeof(*ft->g), GFP_KERNEL);
16385a93b4cdSHans Petter Selasky if (!ft->g) {
16395a93b4cdSHans Petter Selasky err = -ENOMEM;
16405a93b4cdSHans Petter Selasky goto err_destroy_vlan_flow_table;
16415a93b4cdSHans Petter Selasky }
1642dc7e38acSHans Petter Selasky
16435a93b4cdSHans Petter Selasky err = mlx5e_create_vlan_groups(ft);
16445a93b4cdSHans Petter Selasky if (err)
16455a93b4cdSHans Petter Selasky goto err_free_g;
1646dc7e38acSHans Petter Selasky
16475a93b4cdSHans Petter Selasky return (0);
1648dc7e38acSHans Petter Selasky
16495a93b4cdSHans Petter Selasky err_free_g:
16505a93b4cdSHans Petter Selasky kfree(ft->g);
16515a93b4cdSHans Petter Selasky
16525a93b4cdSHans Petter Selasky err_destroy_vlan_flow_table:
16535a93b4cdSHans Petter Selasky mlx5_destroy_flow_table(ft->t);
16545a93b4cdSHans Petter Selasky ft->t = NULL;
16555a93b4cdSHans Petter Selasky
16565a93b4cdSHans Petter Selasky return (err);
1657dc7e38acSHans Petter Selasky }
1658dc7e38acSHans Petter Selasky
1659dc7e38acSHans Petter Selasky static void
mlx5e_destroy_vlan_flow_table(struct mlx5e_priv * priv)1660dc7e38acSHans Petter Selasky mlx5e_destroy_vlan_flow_table(struct mlx5e_priv *priv)
1661dc7e38acSHans Petter Selasky {
16625a93b4cdSHans Petter Selasky mlx5e_destroy_flow_table(&priv->fts.vlan);
16635a93b4cdSHans Petter Selasky }
16645a93b4cdSHans Petter Selasky
1665861a612dSKonstantin Belousov static int
mlx5e_add_vxlan_rule_sub(struct mlx5e_priv * priv,struct mlx5_flow_spec * spec,struct mlx5e_vxlan_db_el * el)1666e23731dbSKonstantin Belousov mlx5e_add_vxlan_rule_sub(struct mlx5e_priv *priv, struct mlx5_flow_spec *spec,
1667e012189dSKonstantin Belousov struct mlx5e_vxlan_db_el *el)
1668861a612dSKonstantin Belousov {
1669861a612dSKonstantin Belousov struct mlx5_flow_table *ft = priv->fts.vxlan.t;
1670861a612dSKonstantin Belousov struct mlx5_flow_destination dest = {};
1671e23731dbSKonstantin Belousov struct mlx5_flow_handle **rule_p;
1672861a612dSKonstantin Belousov int err = 0;
1673cb054a49SMark Bloch struct mlx5_flow_act flow_act = {
1674b762b199SSlava Shwartsman .action = MLX5_FLOW_CONTEXT_ACTION_FWD_DEST,
1675cb054a49SMark Bloch };
1676e23731dbSKonstantin Belousov u8 *mc;
1677e23731dbSKonstantin Belousov u8 *mv;
1678e23731dbSKonstantin Belousov
1679e23731dbSKonstantin Belousov mv = (u8 *)spec->match_value;
1680e23731dbSKonstantin Belousov mc = (u8 *)spec->match_criteria;
1681e23731dbSKonstantin Belousov
1682e23731dbSKonstantin Belousov spec->flow_context.flow_tag = MLX5_FS_ETH_FLOW_TAG;
1683e23731dbSKonstantin Belousov spec->flow_context.flags = FLOW_CONTEXT_HAS_TAG;
1684861a612dSKonstantin Belousov
1685861a612dSKonstantin Belousov dest.type = MLX5_FLOW_DESTINATION_TYPE_FLOW_TABLE;
1686861a612dSKonstantin Belousov dest.ft = priv->fts.main_vxlan.t;
1687861a612dSKonstantin Belousov
1688e23731dbSKonstantin Belousov spec->match_criteria_enable = MLX5_MATCH_OUTER_HEADERS;
1689861a612dSKonstantin Belousov rule_p = &el->vxlan_ft_rule;
1690861a612dSKonstantin Belousov MLX5_SET_TO_ONES(fte_match_param, mc, outer_headers.ethertype);
1691e012189dSKonstantin Belousov MLX5_SET(fte_match_param, mv, outer_headers.ethertype, el->proto);
1692861a612dSKonstantin Belousov MLX5_SET_TO_ONES(fte_match_param, mc, outer_headers.ip_protocol);
1693861a612dSKonstantin Belousov MLX5_SET(fte_match_param, mv, outer_headers.ip_protocol, IPPROTO_UDP);
1694861a612dSKonstantin Belousov MLX5_SET_TO_ONES(fte_match_param, mc, outer_headers.udp_dport);
1695e012189dSKonstantin Belousov MLX5_SET(fte_match_param, mv, outer_headers.udp_dport, el->port);
1696861a612dSKonstantin Belousov
1697e23731dbSKonstantin Belousov *rule_p = mlx5_add_flow_rules(ft, spec, &flow_act, &dest, 1);
1698861a612dSKonstantin Belousov
1699861a612dSKonstantin Belousov if (IS_ERR(*rule_p)) {
1700861a612dSKonstantin Belousov err = PTR_ERR(*rule_p);
1701861a612dSKonstantin Belousov *rule_p = NULL;
1702861a612dSKonstantin Belousov mlx5_en_err(priv->ifp, "add rule failed\n");
1703861a612dSKonstantin Belousov }
1704861a612dSKonstantin Belousov
1705861a612dSKonstantin Belousov return (err);
1706861a612dSKonstantin Belousov }
1707861a612dSKonstantin Belousov
1708861a612dSKonstantin Belousov static struct mlx5e_vxlan_db_el *
mlx5e_vxlan_find_db_el(struct mlx5e_priv * priv,u_int proto,u_int port)1709861a612dSKonstantin Belousov mlx5e_vxlan_find_db_el(struct mlx5e_priv *priv, u_int proto, u_int port)
1710861a612dSKonstantin Belousov {
1711861a612dSKonstantin Belousov struct mlx5e_vxlan_db_el *el;
1712861a612dSKonstantin Belousov
1713861a612dSKonstantin Belousov TAILQ_FOREACH(el, &priv->vxlan.head, link) {
1714861a612dSKonstantin Belousov if (el->proto == proto && el->port == port)
1715861a612dSKonstantin Belousov return (el);
1716861a612dSKonstantin Belousov }
1717861a612dSKonstantin Belousov return (NULL);
1718861a612dSKonstantin Belousov }
1719861a612dSKonstantin Belousov
1720861a612dSKonstantin Belousov static struct mlx5e_vxlan_db_el *
mlx5e_vxlan_alloc_db_el(struct mlx5e_priv * priv,u_int proto,u_int port)1721861a612dSKonstantin Belousov mlx5e_vxlan_alloc_db_el(struct mlx5e_priv *priv, u_int proto, u_int port)
1722861a612dSKonstantin Belousov {
1723861a612dSKonstantin Belousov struct mlx5e_vxlan_db_el *el;
1724861a612dSKonstantin Belousov
1725861a612dSKonstantin Belousov el = mlx5_vzalloc(sizeof(*el));
1726861a612dSKonstantin Belousov el->refcount = 1;
1727861a612dSKonstantin Belousov el->proto = proto;
1728861a612dSKonstantin Belousov el->port = port;
1729861a612dSKonstantin Belousov el->vxlan_ft_rule = NULL;
1730861a612dSKonstantin Belousov return (el);
1731861a612dSKonstantin Belousov }
1732861a612dSKonstantin Belousov
1733861a612dSKonstantin Belousov static int
mlx5e_vxlan_family_to_proto(sa_family_t family,u_int * proto)1734861a612dSKonstantin Belousov mlx5e_vxlan_family_to_proto(sa_family_t family, u_int *proto)
1735861a612dSKonstantin Belousov {
1736861a612dSKonstantin Belousov switch (family) {
1737861a612dSKonstantin Belousov case AF_INET:
1738861a612dSKonstantin Belousov *proto = ETHERTYPE_IP;
1739861a612dSKonstantin Belousov return (0);
1740861a612dSKonstantin Belousov case AF_INET6:
1741861a612dSKonstantin Belousov *proto = ETHERTYPE_IPV6;
1742861a612dSKonstantin Belousov return (0);
1743861a612dSKonstantin Belousov default:
1744861a612dSKonstantin Belousov return (-EINVAL);
1745861a612dSKonstantin Belousov }
1746861a612dSKonstantin Belousov }
1747861a612dSKonstantin Belousov
1748861a612dSKonstantin Belousov static int
mlx5e_add_vxlan_rule_from_db(struct mlx5e_priv * priv,struct mlx5e_vxlan_db_el * el)1749559eaa44SKonstantin Belousov mlx5e_add_vxlan_rule_from_db(struct mlx5e_priv *priv,
1750559eaa44SKonstantin Belousov struct mlx5e_vxlan_db_el *el)
1751559eaa44SKonstantin Belousov {
1752e23731dbSKonstantin Belousov struct mlx5_flow_spec *spec;
1753559eaa44SKonstantin Belousov int err;
1754559eaa44SKonstantin Belousov
1755e23731dbSKonstantin Belousov spec = mlx5_vzalloc(sizeof(*spec));
1756e23731dbSKonstantin Belousov if (!spec) {
1757559eaa44SKonstantin Belousov mlx5_en_err(priv->ifp, "alloc failed\n");
1758559eaa44SKonstantin Belousov err = -ENOMEM;
1759559eaa44SKonstantin Belousov goto add_vxlan_rule_out;
1760559eaa44SKonstantin Belousov }
1761559eaa44SKonstantin Belousov
1762e23731dbSKonstantin Belousov err = mlx5e_add_vxlan_rule_sub(priv, spec, el);
1763559eaa44SKonstantin Belousov
1764559eaa44SKonstantin Belousov add_vxlan_rule_out:
1765e23731dbSKonstantin Belousov kvfree(spec);
1766559eaa44SKonstantin Belousov
1767559eaa44SKonstantin Belousov return (err);
1768559eaa44SKonstantin Belousov }
1769559eaa44SKonstantin Belousov
1770559eaa44SKonstantin Belousov static int
mlx5e_add_vxlan_rule(struct mlx5e_priv * priv,sa_family_t family,u_int port)1771861a612dSKonstantin Belousov mlx5e_add_vxlan_rule(struct mlx5e_priv *priv, sa_family_t family, u_int port)
1772861a612dSKonstantin Belousov {
1773861a612dSKonstantin Belousov struct mlx5e_vxlan_db_el *el;
1774861a612dSKonstantin Belousov u_int proto;
1775861a612dSKonstantin Belousov int err;
1776861a612dSKonstantin Belousov
1777861a612dSKonstantin Belousov err = mlx5e_vxlan_family_to_proto(family, &proto);
1778861a612dSKonstantin Belousov if (err != 0)
1779861a612dSKonstantin Belousov return (err);
1780861a612dSKonstantin Belousov
1781861a612dSKonstantin Belousov el = mlx5e_vxlan_find_db_el(priv, proto, port);
1782861a612dSKonstantin Belousov if (el != NULL) {
1783861a612dSKonstantin Belousov el->refcount++;
17840e4cb0d5SKonstantin Belousov if (el->installed)
1785861a612dSKonstantin Belousov return (0);
1786861a612dSKonstantin Belousov }
1787861a612dSKonstantin Belousov el = mlx5e_vxlan_alloc_db_el(priv, proto, port);
1788861a612dSKonstantin Belousov
17895dc00f00SJustin Hibbits if ((if_getcapenable(priv->ifp) & IFCAP_VXLAN_HWCSUM) != 0) {
1790559eaa44SKonstantin Belousov err = mlx5e_add_vxlan_rule_from_db(priv, el);
179148acda2bSKonstantin Belousov if (err == 0)
17920e4cb0d5SKonstantin Belousov el->installed = true;
1793861a612dSKonstantin Belousov }
179448acda2bSKonstantin Belousov if (err == 0)
179548acda2bSKonstantin Belousov TAILQ_INSERT_TAIL(&priv->vxlan.head, el, link);
179648acda2bSKonstantin Belousov else
179748acda2bSKonstantin Belousov kvfree(el);
1798861a612dSKonstantin Belousov
1799861a612dSKonstantin Belousov return (err);
1800861a612dSKonstantin Belousov }
1801861a612dSKonstantin Belousov
1802861a612dSKonstantin Belousov static int
mlx5e_add_vxlan_catchall_rule_sub(struct mlx5e_priv * priv,struct mlx5_flow_spec * spec)1803e23731dbSKonstantin Belousov mlx5e_add_vxlan_catchall_rule_sub(struct mlx5e_priv *priv,
1804e23731dbSKonstantin Belousov struct mlx5_flow_spec *spec)
1805861a612dSKonstantin Belousov {
1806861a612dSKonstantin Belousov struct mlx5_flow_table *ft = priv->fts.vxlan.t;
1807861a612dSKonstantin Belousov struct mlx5_flow_destination dest = {};
1808e23731dbSKonstantin Belousov struct mlx5_flow_handle **rule_p;
1809861a612dSKonstantin Belousov int err = 0;
1810cb054a49SMark Bloch struct mlx5_flow_act flow_act = {
1811b762b199SSlava Shwartsman .action = MLX5_FLOW_CONTEXT_ACTION_FWD_DEST,
1812cb054a49SMark Bloch };
1813861a612dSKonstantin Belousov
1814e23731dbSKonstantin Belousov spec->flow_context.flow_tag = MLX5_FS_ETH_FLOW_TAG;
1815e23731dbSKonstantin Belousov spec->flow_context.flags = FLOW_CONTEXT_HAS_TAG;
1816e23731dbSKonstantin Belousov
1817861a612dSKonstantin Belousov dest.type = MLX5_FLOW_DESTINATION_TYPE_FLOW_TABLE;
1818861a612dSKonstantin Belousov dest.ft = priv->fts.main.t;
1819861a612dSKonstantin Belousov
1820861a612dSKonstantin Belousov rule_p = &priv->fts.vxlan_catchall_ft_rule;
1821e23731dbSKonstantin Belousov *rule_p = mlx5_add_flow_rules(ft, spec, &flow_act, &dest, 1);
1822861a612dSKonstantin Belousov
1823861a612dSKonstantin Belousov if (IS_ERR(*rule_p)) {
1824861a612dSKonstantin Belousov err = PTR_ERR(*rule_p);
1825861a612dSKonstantin Belousov *rule_p = NULL;
1826861a612dSKonstantin Belousov mlx5_en_err(priv->ifp, "add rule failed\n");
1827861a612dSKonstantin Belousov }
1828861a612dSKonstantin Belousov
1829861a612dSKonstantin Belousov return (err);
1830861a612dSKonstantin Belousov }
1831861a612dSKonstantin Belousov
1832861a612dSKonstantin Belousov
1833861a612dSKonstantin Belousov static int
mlx5e_add_vxlan_catchall_rule(struct mlx5e_priv * priv)1834861a612dSKonstantin Belousov mlx5e_add_vxlan_catchall_rule(struct mlx5e_priv *priv)
1835861a612dSKonstantin Belousov {
1836e23731dbSKonstantin Belousov struct mlx5_flow_spec *spec;
1837861a612dSKonstantin Belousov int err;
1838861a612dSKonstantin Belousov
1839e23731dbSKonstantin Belousov spec = mlx5_vzalloc(sizeof(*spec));
1840e23731dbSKonstantin Belousov if (!spec) {
1841861a612dSKonstantin Belousov mlx5_en_err(priv->ifp, "alloc failed\n");
1842861a612dSKonstantin Belousov err = -ENOMEM;
1843861a612dSKonstantin Belousov goto add_vxlan_rule_out;
1844861a612dSKonstantin Belousov }
1845861a612dSKonstantin Belousov
1846e23731dbSKonstantin Belousov err = mlx5e_add_vxlan_catchall_rule_sub(priv, spec);
1847861a612dSKonstantin Belousov
1848861a612dSKonstantin Belousov add_vxlan_rule_out:
1849e23731dbSKonstantin Belousov kvfree(spec);
1850861a612dSKonstantin Belousov
1851861a612dSKonstantin Belousov return (err);
1852861a612dSKonstantin Belousov }
1853861a612dSKonstantin Belousov
18540e4cb0d5SKonstantin Belousov int
mlx5e_add_all_vxlan_rules(struct mlx5e_priv * priv)18550e4cb0d5SKonstantin Belousov mlx5e_add_all_vxlan_rules(struct mlx5e_priv *priv)
18560e4cb0d5SKonstantin Belousov {
18570e4cb0d5SKonstantin Belousov struct mlx5e_vxlan_db_el *el;
18580e4cb0d5SKonstantin Belousov int err;
18590e4cb0d5SKonstantin Belousov
18600e4cb0d5SKonstantin Belousov err = 0;
18610e4cb0d5SKonstantin Belousov TAILQ_FOREACH(el, &priv->vxlan.head, link) {
18620e4cb0d5SKonstantin Belousov if (el->installed)
18630e4cb0d5SKonstantin Belousov continue;
18640e4cb0d5SKonstantin Belousov err = mlx5e_add_vxlan_rule_from_db(priv, el);
18650e4cb0d5SKonstantin Belousov if (err != 0)
18660e4cb0d5SKonstantin Belousov break;
18676176a5e3SHans Petter Selasky el->installed = true;
18680e4cb0d5SKonstantin Belousov }
18690e4cb0d5SKonstantin Belousov
18700e4cb0d5SKonstantin Belousov return (err);
18710e4cb0d5SKonstantin Belousov }
18720e4cb0d5SKonstantin Belousov
1873861a612dSKonstantin Belousov static int
mlx5e_del_vxlan_rule(struct mlx5e_priv * priv,sa_family_t family,u_int port)1874861a612dSKonstantin Belousov mlx5e_del_vxlan_rule(struct mlx5e_priv *priv, sa_family_t family, u_int port)
1875861a612dSKonstantin Belousov {
1876861a612dSKonstantin Belousov struct mlx5e_vxlan_db_el *el;
1877861a612dSKonstantin Belousov u_int proto;
1878861a612dSKonstantin Belousov int err;
1879861a612dSKonstantin Belousov
1880861a612dSKonstantin Belousov err = mlx5e_vxlan_family_to_proto(family, &proto);
1881861a612dSKonstantin Belousov if (err != 0)
1882861a612dSKonstantin Belousov return (err);
1883861a612dSKonstantin Belousov
1884861a612dSKonstantin Belousov el = mlx5e_vxlan_find_db_el(priv, proto, port);
1885861a612dSKonstantin Belousov if (el == NULL)
1886861a612dSKonstantin Belousov return (0);
1887861a612dSKonstantin Belousov if (el->refcount > 1) {
1888861a612dSKonstantin Belousov el->refcount--;
1889861a612dSKonstantin Belousov return (0);
1890861a612dSKonstantin Belousov }
1891861a612dSKonstantin Belousov
18929680b1baSHans Petter Selasky if (el->installed)
1893e23731dbSKonstantin Belousov mlx5_del_flow_rules(&el->vxlan_ft_rule);
1894861a612dSKonstantin Belousov TAILQ_REMOVE(&priv->vxlan.head, el, link);
1895861a612dSKonstantin Belousov kvfree(el);
1896861a612dSKonstantin Belousov return (0);
1897861a612dSKonstantin Belousov }
1898861a612dSKonstantin Belousov
18990e4cb0d5SKonstantin Belousov void
mlx5e_del_all_vxlan_rules(struct mlx5e_priv * priv)19000e4cb0d5SKonstantin Belousov mlx5e_del_all_vxlan_rules(struct mlx5e_priv *priv)
19010e4cb0d5SKonstantin Belousov {
19020e4cb0d5SKonstantin Belousov struct mlx5e_vxlan_db_el *el;
19030e4cb0d5SKonstantin Belousov
19040e4cb0d5SKonstantin Belousov TAILQ_FOREACH(el, &priv->vxlan.head, link) {
19050e4cb0d5SKonstantin Belousov if (!el->installed)
19060e4cb0d5SKonstantin Belousov continue;
1907e23731dbSKonstantin Belousov mlx5_del_flow_rules(&el->vxlan_ft_rule);
19080e4cb0d5SKonstantin Belousov el->installed = false;
19090e4cb0d5SKonstantin Belousov }
19100e4cb0d5SKonstantin Belousov }
19110e4cb0d5SKonstantin Belousov
1912861a612dSKonstantin Belousov static void
mlx5e_del_vxlan_catchall_rule(struct mlx5e_priv * priv)1913861a612dSKonstantin Belousov mlx5e_del_vxlan_catchall_rule(struct mlx5e_priv *priv)
1914861a612dSKonstantin Belousov {
1915e23731dbSKonstantin Belousov mlx5_del_flow_rules(&priv->fts.vxlan_catchall_ft_rule);
1916861a612dSKonstantin Belousov }
1917861a612dSKonstantin Belousov
1918861a612dSKonstantin Belousov void
mlx5e_vxlan_start(void * arg,if_t ifp __unused,sa_family_t family,u_int port)19195dc00f00SJustin Hibbits mlx5e_vxlan_start(void *arg, if_t ifp __unused, sa_family_t family,
1920861a612dSKonstantin Belousov u_int port)
1921861a612dSKonstantin Belousov {
1922861a612dSKonstantin Belousov struct mlx5e_priv *priv = arg;
1923861a612dSKonstantin Belousov int err;
1924861a612dSKonstantin Belousov
1925861a612dSKonstantin Belousov PRIV_LOCK(priv);
1926861a612dSKonstantin Belousov err = mlx5_vxlan_udp_port_add(priv->mdev, port);
1927e059c120SHans Petter Selasky if (err == 0 && test_bit(MLX5E_STATE_FLOW_RULES_READY, &priv->state))
1928861a612dSKonstantin Belousov mlx5e_add_vxlan_rule(priv, family, port);
1929861a612dSKonstantin Belousov PRIV_UNLOCK(priv);
1930861a612dSKonstantin Belousov }
1931861a612dSKonstantin Belousov
1932861a612dSKonstantin Belousov void
mlx5e_vxlan_stop(void * arg,if_t ifp __unused,sa_family_t family,u_int port)19335dc00f00SJustin Hibbits mlx5e_vxlan_stop(void *arg, if_t ifp __unused, sa_family_t family,
1934861a612dSKonstantin Belousov u_int port)
1935861a612dSKonstantin Belousov {
1936861a612dSKonstantin Belousov struct mlx5e_priv *priv = arg;
1937861a612dSKonstantin Belousov
1938861a612dSKonstantin Belousov PRIV_LOCK(priv);
1939e059c120SHans Petter Selasky if (test_bit(MLX5E_STATE_FLOW_RULES_READY, &priv->state))
1940861a612dSKonstantin Belousov mlx5e_del_vxlan_rule(priv, family, port);
1941861a612dSKonstantin Belousov (void)mlx5_vxlan_udp_port_delete(priv->mdev, port);
1942861a612dSKonstantin Belousov PRIV_UNLOCK(priv);
1943861a612dSKonstantin Belousov }
1944861a612dSKonstantin Belousov
1945861a612dSKonstantin Belousov #define MLX5E_VXLAN_GROUP0_SIZE BIT(3) /* XXXKIB */
1946861a612dSKonstantin Belousov #define MLX5E_VXLAN_GROUP1_SIZE BIT(0)
1947861a612dSKonstantin Belousov #define MLX5E_NUM_VXLAN_GROUPS BIT(1)
1948861a612dSKonstantin Belousov #define MLX5E_VXLAN_TABLE_SIZE \
1949861a612dSKonstantin Belousov (MLX5E_VXLAN_GROUP0_SIZE + MLX5E_VXLAN_GROUP1_SIZE)
1950861a612dSKonstantin Belousov
1951861a612dSKonstantin Belousov static int
mlx5e_create_vxlan_groups_sub(struct mlx5e_flow_table * ft,u32 * in,int inlen)1952861a612dSKonstantin Belousov mlx5e_create_vxlan_groups_sub(struct mlx5e_flow_table *ft, u32 *in,
1953861a612dSKonstantin Belousov int inlen)
1954861a612dSKonstantin Belousov {
1955861a612dSKonstantin Belousov int err;
1956861a612dSKonstantin Belousov int ix = 0;
1957861a612dSKonstantin Belousov u8 *mc = MLX5_ADDR_OF(create_flow_group_in, in, match_criteria);
1958861a612dSKonstantin Belousov
1959861a612dSKonstantin Belousov memset(in, 0, inlen);
1960861a612dSKonstantin Belousov MLX5_SET_CFG(in, match_criteria_enable, MLX5_MATCH_OUTER_HEADERS);
1961861a612dSKonstantin Belousov MLX5_SET_TO_ONES(fte_match_param, mc, outer_headers.ethertype);
1962861a612dSKonstantin Belousov MLX5_SET_TO_ONES(fte_match_param, mc, outer_headers.ip_protocol);
1963861a612dSKonstantin Belousov MLX5_SET_TO_ONES(fte_match_param, mc, outer_headers.udp_dport);
1964861a612dSKonstantin Belousov MLX5_SET_CFG(in, start_flow_index, ix);
1965861a612dSKonstantin Belousov ix += MLX5E_VXLAN_GROUP0_SIZE;
1966861a612dSKonstantin Belousov MLX5_SET_CFG(in, end_flow_index, ix - 1);
1967861a612dSKonstantin Belousov ft->g[ft->num_groups] = mlx5_create_flow_group(ft->t, in);
1968861a612dSKonstantin Belousov if (IS_ERR(ft->g[ft->num_groups]))
1969861a612dSKonstantin Belousov goto err_destory_groups;
1970861a612dSKonstantin Belousov ft->num_groups++;
1971861a612dSKonstantin Belousov
1972861a612dSKonstantin Belousov memset(in, 0, inlen);
1973861a612dSKonstantin Belousov MLX5_SET_CFG(in, start_flow_index, ix);
1974861a612dSKonstantin Belousov ix += MLX5E_VXLAN_GROUP1_SIZE;
1975861a612dSKonstantin Belousov MLX5_SET_CFG(in, end_flow_index, ix - 1);
1976861a612dSKonstantin Belousov ft->g[ft->num_groups] = mlx5_create_flow_group(ft->t, in);
1977861a612dSKonstantin Belousov if (IS_ERR(ft->g[ft->num_groups]))
1978861a612dSKonstantin Belousov goto err_destory_groups;
1979861a612dSKonstantin Belousov ft->num_groups++;
1980861a612dSKonstantin Belousov
1981861a612dSKonstantin Belousov return (0);
1982861a612dSKonstantin Belousov
1983861a612dSKonstantin Belousov err_destory_groups:
1984861a612dSKonstantin Belousov err = PTR_ERR(ft->g[ft->num_groups]);
1985861a612dSKonstantin Belousov ft->g[ft->num_groups] = NULL;
1986861a612dSKonstantin Belousov mlx5e_destroy_groups(ft);
1987861a612dSKonstantin Belousov
1988861a612dSKonstantin Belousov return (err);
1989861a612dSKonstantin Belousov }
1990861a612dSKonstantin Belousov
1991861a612dSKonstantin Belousov static int
mlx5e_create_vxlan_groups(struct mlx5e_flow_table * ft)1992861a612dSKonstantin Belousov mlx5e_create_vxlan_groups(struct mlx5e_flow_table *ft)
1993861a612dSKonstantin Belousov {
1994861a612dSKonstantin Belousov u32 *in;
1995861a612dSKonstantin Belousov int inlen = MLX5_ST_SZ_BYTES(create_flow_group_in);
1996861a612dSKonstantin Belousov int err;
1997861a612dSKonstantin Belousov
1998861a612dSKonstantin Belousov in = mlx5_vzalloc(inlen);
1999861a612dSKonstantin Belousov if (!in)
2000861a612dSKonstantin Belousov return (-ENOMEM);
2001861a612dSKonstantin Belousov
2002861a612dSKonstantin Belousov err = mlx5e_create_vxlan_groups_sub(ft, in, inlen);
2003861a612dSKonstantin Belousov
2004861a612dSKonstantin Belousov kvfree(in);
2005861a612dSKonstantin Belousov return (err);
2006861a612dSKonstantin Belousov }
2007861a612dSKonstantin Belousov
2008861a612dSKonstantin Belousov static int
mlx5e_create_vxlan_flow_table(struct mlx5e_priv * priv)2009861a612dSKonstantin Belousov mlx5e_create_vxlan_flow_table(struct mlx5e_priv *priv)
2010861a612dSKonstantin Belousov {
2011861a612dSKonstantin Belousov struct mlx5e_flow_table *ft = &priv->fts.vxlan;
2012e23731dbSKonstantin Belousov struct mlx5_flow_table_attr ft_attr = {};
2013861a612dSKonstantin Belousov int err;
2014861a612dSKonstantin Belousov
2015861a612dSKonstantin Belousov ft->num_groups = 0;
2016e23731dbSKonstantin Belousov ft_attr.max_fte = MLX5E_VXLAN_TABLE_SIZE;
2017*080f68d0SAriel Ehrenberg ft_attr.level = (priv->ipsec) ? 10 : 1;
2018e23731dbSKonstantin Belousov ft->t = mlx5_create_flow_table(priv->fts.ns, &ft_attr);
2019861a612dSKonstantin Belousov
2020861a612dSKonstantin Belousov if (IS_ERR(ft->t)) {
2021861a612dSKonstantin Belousov err = PTR_ERR(ft->t);
2022861a612dSKonstantin Belousov ft->t = NULL;
2023861a612dSKonstantin Belousov return (err);
2024861a612dSKonstantin Belousov }
2025861a612dSKonstantin Belousov ft->g = kcalloc(MLX5E_NUM_VXLAN_GROUPS, sizeof(*ft->g), GFP_KERNEL);
2026861a612dSKonstantin Belousov if (!ft->g) {
2027861a612dSKonstantin Belousov err = -ENOMEM;
2028861a612dSKonstantin Belousov goto err_destroy_vxlan_flow_table;
2029861a612dSKonstantin Belousov }
2030861a612dSKonstantin Belousov
2031861a612dSKonstantin Belousov err = mlx5e_create_vxlan_groups(ft);
2032861a612dSKonstantin Belousov if (err)
2033861a612dSKonstantin Belousov goto err_free_g;
2034861a612dSKonstantin Belousov
2035861a612dSKonstantin Belousov TAILQ_INIT(&priv->vxlan.head);
2036861a612dSKonstantin Belousov return (0);
2037861a612dSKonstantin Belousov
2038861a612dSKonstantin Belousov err_free_g:
2039861a612dSKonstantin Belousov kfree(ft->g);
2040861a612dSKonstantin Belousov
2041861a612dSKonstantin Belousov err_destroy_vxlan_flow_table:
2042861a612dSKonstantin Belousov mlx5_destroy_flow_table(ft->t);
2043861a612dSKonstantin Belousov ft->t = NULL;
2044861a612dSKonstantin Belousov
2045861a612dSKonstantin Belousov return (err);
2046861a612dSKonstantin Belousov }
2047861a612dSKonstantin Belousov
20485a93b4cdSHans Petter Selasky #define MLX5E_NUM_INNER_RSS_GROUPS 3
20495a93b4cdSHans Petter Selasky #define MLX5E_INNER_RSS_GROUP0_SIZE BIT(3)
20505a93b4cdSHans Petter Selasky #define MLX5E_INNER_RSS_GROUP1_SIZE BIT(1)
20515a93b4cdSHans Petter Selasky #define MLX5E_INNER_RSS_GROUP2_SIZE BIT(0)
20525a93b4cdSHans Petter Selasky #define MLX5E_INNER_RSS_TABLE_SIZE (MLX5E_INNER_RSS_GROUP0_SIZE +\
20535a93b4cdSHans Petter Selasky MLX5E_INNER_RSS_GROUP1_SIZE +\
20545a93b4cdSHans Petter Selasky MLX5E_INNER_RSS_GROUP2_SIZE +\
20555a93b4cdSHans Petter Selasky 0)
20565a93b4cdSHans Petter Selasky
20575a93b4cdSHans Petter Selasky static int
mlx5e_create_inner_rss_groups_sub(struct mlx5e_flow_table * ft,u32 * in,int inlen)20585a93b4cdSHans Petter Selasky mlx5e_create_inner_rss_groups_sub(struct mlx5e_flow_table *ft, u32 *in,
20595a93b4cdSHans Petter Selasky int inlen)
20605a93b4cdSHans Petter Selasky {
20615a93b4cdSHans Petter Selasky u8 *mc = MLX5_ADDR_OF(create_flow_group_in, in, match_criteria);
20625a93b4cdSHans Petter Selasky int err;
20635a93b4cdSHans Petter Selasky int ix = 0;
20645a93b4cdSHans Petter Selasky
20655a93b4cdSHans Petter Selasky memset(in, 0, inlen);
20665a93b4cdSHans Petter Selasky MLX5_SET_CFG(in, match_criteria_enable, MLX5_MATCH_INNER_HEADERS);
20675a93b4cdSHans Petter Selasky MLX5_SET_TO_ONES(fte_match_param, mc, inner_headers.ethertype);
20685a93b4cdSHans Petter Selasky MLX5_SET_TO_ONES(fte_match_param, mc, inner_headers.ip_protocol);
20695a93b4cdSHans Petter Selasky MLX5_SET_CFG(in, start_flow_index, ix);
20705a93b4cdSHans Petter Selasky ix += MLX5E_INNER_RSS_GROUP0_SIZE;
20715a93b4cdSHans Petter Selasky MLX5_SET_CFG(in, end_flow_index, ix - 1);
20725a93b4cdSHans Petter Selasky ft->g[ft->num_groups] = mlx5_create_flow_group(ft->t, in);
20735a93b4cdSHans Petter Selasky if (IS_ERR(ft->g[ft->num_groups]))
20745a93b4cdSHans Petter Selasky goto err_destory_groups;
20755a93b4cdSHans Petter Selasky ft->num_groups++;
20765a93b4cdSHans Petter Selasky
20775a93b4cdSHans Petter Selasky memset(in, 0, inlen);
20785a93b4cdSHans Petter Selasky MLX5_SET_CFG(in, match_criteria_enable, MLX5_MATCH_INNER_HEADERS);
20795a93b4cdSHans Petter Selasky MLX5_SET_TO_ONES(fte_match_param, mc, inner_headers.ethertype);
20805a93b4cdSHans Petter Selasky MLX5_SET_CFG(in, start_flow_index, ix);
20815a93b4cdSHans Petter Selasky ix += MLX5E_INNER_RSS_GROUP1_SIZE;
20825a93b4cdSHans Petter Selasky MLX5_SET_CFG(in, end_flow_index, ix - 1);
20835a93b4cdSHans Petter Selasky ft->g[ft->num_groups] = mlx5_create_flow_group(ft->t, in);
20845a93b4cdSHans Petter Selasky if (IS_ERR(ft->g[ft->num_groups]))
20855a93b4cdSHans Petter Selasky goto err_destory_groups;
20865a93b4cdSHans Petter Selasky ft->num_groups++;
20875a93b4cdSHans Petter Selasky
20885a93b4cdSHans Petter Selasky memset(in, 0, inlen);
20895a93b4cdSHans Petter Selasky MLX5_SET_CFG(in, start_flow_index, ix);
20905a93b4cdSHans Petter Selasky ix += MLX5E_INNER_RSS_GROUP2_SIZE;
20915a93b4cdSHans Petter Selasky MLX5_SET_CFG(in, end_flow_index, ix - 1);
20925a93b4cdSHans Petter Selasky ft->g[ft->num_groups] = mlx5_create_flow_group(ft->t, in);
20935a93b4cdSHans Petter Selasky if (IS_ERR(ft->g[ft->num_groups]))
20945a93b4cdSHans Petter Selasky goto err_destory_groups;
20955a93b4cdSHans Petter Selasky ft->num_groups++;
20965a93b4cdSHans Petter Selasky
20975a93b4cdSHans Petter Selasky return (0);
20985a93b4cdSHans Petter Selasky
20995a93b4cdSHans Petter Selasky err_destory_groups:
21005a93b4cdSHans Petter Selasky err = PTR_ERR(ft->g[ft->num_groups]);
21015a93b4cdSHans Petter Selasky ft->g[ft->num_groups] = NULL;
21025a93b4cdSHans Petter Selasky mlx5e_destroy_groups(ft);
21035a93b4cdSHans Petter Selasky
21045a93b4cdSHans Petter Selasky return (err);
21055a93b4cdSHans Petter Selasky }
21065a93b4cdSHans Petter Selasky
21075a93b4cdSHans Petter Selasky static int
mlx5e_create_inner_rss_groups(struct mlx5e_flow_table * ft)21085a93b4cdSHans Petter Selasky mlx5e_create_inner_rss_groups(struct mlx5e_flow_table *ft)
21095a93b4cdSHans Petter Selasky {
21105a93b4cdSHans Petter Selasky u32 *in;
21115a93b4cdSHans Petter Selasky int inlen = MLX5_ST_SZ_BYTES(create_flow_group_in);
21125a93b4cdSHans Petter Selasky int err;
21135a93b4cdSHans Petter Selasky
21145a93b4cdSHans Petter Selasky in = mlx5_vzalloc(inlen);
21155a93b4cdSHans Petter Selasky if (!in)
21165a93b4cdSHans Petter Selasky return (-ENOMEM);
21175a93b4cdSHans Petter Selasky
21185a93b4cdSHans Petter Selasky err = mlx5e_create_inner_rss_groups_sub(ft, in, inlen);
21195a93b4cdSHans Petter Selasky
21205a93b4cdSHans Petter Selasky kvfree(in);
21215a93b4cdSHans Petter Selasky return (err);
21225a93b4cdSHans Petter Selasky }
21235a93b4cdSHans Petter Selasky
21245a93b4cdSHans Petter Selasky static int
mlx5e_create_inner_rss_flow_table(struct mlx5e_priv * priv)21255a93b4cdSHans Petter Selasky mlx5e_create_inner_rss_flow_table(struct mlx5e_priv *priv)
21265a93b4cdSHans Petter Selasky {
21275a93b4cdSHans Petter Selasky struct mlx5e_flow_table *ft = &priv->fts.inner_rss;
2128e23731dbSKonstantin Belousov struct mlx5_flow_table_attr ft_attr = {};
21295a93b4cdSHans Petter Selasky int err;
21305a93b4cdSHans Petter Selasky
21315a93b4cdSHans Petter Selasky ft->num_groups = 0;
2132e23731dbSKonstantin Belousov ft_attr.max_fte = MLX5E_INNER_RSS_TABLE_SIZE;
2133e23731dbSKonstantin Belousov ft_attr.level = (priv->ipsec) ? 11 : 3;
2134e23731dbSKonstantin Belousov ft->t = mlx5_create_flow_table(priv->fts.ns, &ft_attr);
21355a93b4cdSHans Petter Selasky
21365a93b4cdSHans Petter Selasky if (IS_ERR(ft->t)) {
21375a93b4cdSHans Petter Selasky err = PTR_ERR(ft->t);
21385a93b4cdSHans Petter Selasky ft->t = NULL;
21395a93b4cdSHans Petter Selasky return (err);
21405a93b4cdSHans Petter Selasky }
21415a93b4cdSHans Petter Selasky ft->g = kcalloc(MLX5E_NUM_INNER_RSS_GROUPS, sizeof(*ft->g),
21425a93b4cdSHans Petter Selasky GFP_KERNEL);
21435a93b4cdSHans Petter Selasky if (!ft->g) {
21445a93b4cdSHans Petter Selasky err = -ENOMEM;
21455a93b4cdSHans Petter Selasky goto err_destroy_inner_rss_flow_table;
21465a93b4cdSHans Petter Selasky }
21475a93b4cdSHans Petter Selasky
21485a93b4cdSHans Petter Selasky err = mlx5e_create_inner_rss_groups(ft);
21495a93b4cdSHans Petter Selasky if (err)
21505a93b4cdSHans Petter Selasky goto err_free_g;
21515a93b4cdSHans Petter Selasky
21525a93b4cdSHans Petter Selasky return (0);
21535a93b4cdSHans Petter Selasky
21545a93b4cdSHans Petter Selasky err_free_g:
21555a93b4cdSHans Petter Selasky kfree(ft->g);
21565a93b4cdSHans Petter Selasky
21575a93b4cdSHans Petter Selasky err_destroy_inner_rss_flow_table:
21585a93b4cdSHans Petter Selasky mlx5_destroy_flow_table(ft->t);
21595a93b4cdSHans Petter Selasky ft->t = NULL;
21605a93b4cdSHans Petter Selasky
21615a93b4cdSHans Petter Selasky return (err);
21625a93b4cdSHans Petter Selasky }
21635a93b4cdSHans Petter Selasky
mlx5e_destroy_inner_rss_flow_table(struct mlx5e_priv * priv)21645a93b4cdSHans Petter Selasky static void mlx5e_destroy_inner_rss_flow_table(struct mlx5e_priv *priv)
21655a93b4cdSHans Petter Selasky {
21665a93b4cdSHans Petter Selasky mlx5e_destroy_flow_table(&priv->fts.inner_rss);
2167dc7e38acSHans Petter Selasky }
2168dc7e38acSHans Petter Selasky
2169861a612dSKonstantin Belousov static void
mlx5e_destroy_vxlan_flow_table(struct mlx5e_priv * priv)2170861a612dSKonstantin Belousov mlx5e_destroy_vxlan_flow_table(struct mlx5e_priv *priv)
2171861a612dSKonstantin Belousov {
2172861a612dSKonstantin Belousov mlx5e_destroy_flow_table(&priv->fts.vxlan);
2173861a612dSKonstantin Belousov }
2174861a612dSKonstantin Belousov
2175dc7e38acSHans Petter Selasky int
mlx5e_open_flow_tables(struct mlx5e_priv * priv)2176e059c120SHans Petter Selasky mlx5e_open_flow_tables(struct mlx5e_priv *priv)
2177dc7e38acSHans Petter Selasky {
2178dc7e38acSHans Petter Selasky int err;
2179dc7e38acSHans Petter Selasky
2180e059c120SHans Petter Selasky /* setup namespace pointer */
2181e059c120SHans Petter Selasky priv->fts.ns = mlx5_get_flow_namespace(
2182e059c120SHans Petter Selasky priv->mdev, MLX5_FLOW_NAMESPACE_KERNEL);
21835a93b4cdSHans Petter Selasky
2184e23731dbSKonstantin Belousov err = mlx5e_accel_ipsec_fs_rx_tables_create(priv);
2185e23731dbSKonstantin Belousov if (err)
2186e23731dbSKonstantin Belousov return err;
2187e23731dbSKonstantin Belousov
21885a93b4cdSHans Petter Selasky err = mlx5e_create_vlan_flow_table(priv);
2189dc7e38acSHans Petter Selasky if (err)
2190e23731dbSKonstantin Belousov goto err_destroy_ipsec_flow_table;
2191dc7e38acSHans Petter Selasky
2192861a612dSKonstantin Belousov err = mlx5e_create_vxlan_flow_table(priv);
21935a93b4cdSHans Petter Selasky if (err)
21945a93b4cdSHans Petter Selasky goto err_destroy_vlan_flow_table;
21955a93b4cdSHans Petter Selasky
2196001106f8SHans Petter Selasky err = mlx5e_create_main_flow_table(priv, true);
2197861a612dSKonstantin Belousov if (err)
2198861a612dSKonstantin Belousov goto err_destroy_vxlan_flow_table;
2199861a612dSKonstantin Belousov
2200861a612dSKonstantin Belousov err = mlx5e_create_inner_rss_flow_table(priv);
2201861a612dSKonstantin Belousov if (err)
2202001106f8SHans Petter Selasky goto err_destroy_main_flow_table_true;
2203001106f8SHans Petter Selasky
2204001106f8SHans Petter Selasky err = mlx5e_create_main_flow_table(priv, false);
2205001106f8SHans Petter Selasky if (err)
2206001106f8SHans Petter Selasky goto err_destroy_inner_rss_flow_table;
2207861a612dSKonstantin Belousov
2208861a612dSKonstantin Belousov err = mlx5e_add_vxlan_catchall_rule(priv);
2209e059c120SHans Petter Selasky if (err)
2210001106f8SHans Petter Selasky goto err_destroy_main_flow_table_false;
2211861a612dSKonstantin Belousov
2212e23731dbSKonstantin Belousov err = mlx5e_accel_ipsec_fs_rx_catchall_rules(priv);
2213e23731dbSKonstantin Belousov if (err)
2214e23731dbSKonstantin Belousov goto err_destroy_vxlan_catchall_rule;
2215e23731dbSKonstantin Belousov
22162c0ade80SHans Petter Selasky err = mlx5e_accel_fs_tcp_create(priv);
22172c0ade80SHans Petter Selasky if (err)
2218e23731dbSKonstantin Belousov goto err_destroy_ipsec_catchall_rules;
22192c0ade80SHans Petter Selasky
2220dc7e38acSHans Petter Selasky return (0);
2221dc7e38acSHans Petter Selasky
2222e23731dbSKonstantin Belousov err_destroy_ipsec_catchall_rules:
2223e23731dbSKonstantin Belousov mlx5e_accel_ipsec_fs_rx_catchall_rules_destroy(priv);
2224e23731dbSKonstantin Belousov err_destroy_vxlan_catchall_rule:
22252c0ade80SHans Petter Selasky mlx5e_del_vxlan_catchall_rule(priv);
2226001106f8SHans Petter Selasky err_destroy_main_flow_table_false:
2227001106f8SHans Petter Selasky mlx5e_destroy_main_flow_table(priv);
2228861a612dSKonstantin Belousov err_destroy_inner_rss_flow_table:
2229861a612dSKonstantin Belousov mlx5e_destroy_inner_rss_flow_table(priv);
2230001106f8SHans Petter Selasky err_destroy_main_flow_table_true:
2231861a612dSKonstantin Belousov mlx5e_destroy_main_vxlan_flow_table(priv);
2232861a612dSKonstantin Belousov err_destroy_vxlan_flow_table:
2233861a612dSKonstantin Belousov mlx5e_destroy_vxlan_flow_table(priv);
22345a93b4cdSHans Petter Selasky err_destroy_vlan_flow_table:
22355a93b4cdSHans Petter Selasky mlx5e_destroy_vlan_flow_table(priv);
2236e23731dbSKonstantin Belousov err_destroy_ipsec_flow_table:
2237e23731dbSKonstantin Belousov mlx5e_accel_ipsec_fs_rx_tables_destroy(priv);
2238dc7e38acSHans Petter Selasky
2239dc7e38acSHans Petter Selasky return (err);
2240dc7e38acSHans Petter Selasky }
2241dc7e38acSHans Petter Selasky
2242dc7e38acSHans Petter Selasky void
mlx5e_close_flow_tables(struct mlx5e_priv * priv)2243e059c120SHans Petter Selasky mlx5e_close_flow_tables(struct mlx5e_priv *priv)
2244dc7e38acSHans Petter Selasky {
22452c0ade80SHans Petter Selasky mlx5e_accel_fs_tcp_destroy(priv);
2246e23731dbSKonstantin Belousov mlx5e_accel_ipsec_fs_rx_catchall_rules_destroy(priv);
2247861a612dSKonstantin Belousov mlx5e_del_vxlan_catchall_rule(priv);
2248001106f8SHans Petter Selasky mlx5e_destroy_main_flow_table(priv);
2249e059c120SHans Petter Selasky mlx5e_destroy_inner_rss_flow_table(priv);
2250861a612dSKonstantin Belousov mlx5e_destroy_main_vxlan_flow_table(priv);
2251e059c120SHans Petter Selasky mlx5e_destroy_vxlan_flow_table(priv);
22525a93b4cdSHans Petter Selasky mlx5e_destroy_vlan_flow_table(priv);
2253e23731dbSKonstantin Belousov mlx5e_accel_ipsec_fs_rx_tables_destroy(priv);
2254dc7e38acSHans Petter Selasky }
2255e059c120SHans Petter Selasky
2256e059c120SHans Petter Selasky int
mlx5e_open_flow_rules(struct mlx5e_priv * priv)2257e059c120SHans Petter Selasky mlx5e_open_flow_rules(struct mlx5e_priv *priv)
2258e059c120SHans Petter Selasky {
2259e059c120SHans Petter Selasky int err;
2260e059c120SHans Petter Selasky
2261e059c120SHans Petter Selasky err = mlx5e_add_all_vlan_rules(priv);
2262e059c120SHans Petter Selasky if (err)
2263e059c120SHans Petter Selasky return (err);
2264e059c120SHans Petter Selasky
2265e059c120SHans Petter Selasky err = mlx5e_add_main_vxlan_rules(priv);
2266e059c120SHans Petter Selasky if (err)
2267e059c120SHans Petter Selasky goto err_del_all_vlan_rules;
2268e059c120SHans Petter Selasky
2269e059c120SHans Petter Selasky err = mlx5e_add_all_vxlan_rules(priv);
2270e059c120SHans Petter Selasky if (err)
2271e059c120SHans Petter Selasky goto err_del_main_vxlan_rules;
2272e059c120SHans Petter Selasky
2273e059c120SHans Petter Selasky mlx5e_set_rx_mode_core(priv, true);
2274e059c120SHans Petter Selasky
2275e059c120SHans Petter Selasky set_bit(MLX5E_STATE_FLOW_RULES_READY, &priv->state);
2276e059c120SHans Petter Selasky
2277e059c120SHans Petter Selasky return (0);
2278e059c120SHans Petter Selasky
2279e059c120SHans Petter Selasky err_del_main_vxlan_rules:
2280e059c120SHans Petter Selasky mlx5e_del_main_vxlan_rules(priv);
2281e059c120SHans Petter Selasky
2282e059c120SHans Petter Selasky err_del_all_vlan_rules:
2283e059c120SHans Petter Selasky mlx5e_del_all_vlan_rules(priv);
2284e059c120SHans Petter Selasky
2285e059c120SHans Petter Selasky return (err);
2286e059c120SHans Petter Selasky }
2287e059c120SHans Petter Selasky
2288e059c120SHans Petter Selasky void
mlx5e_close_flow_rules(struct mlx5e_priv * priv)2289e059c120SHans Petter Selasky mlx5e_close_flow_rules(struct mlx5e_priv *priv)
2290e059c120SHans Petter Selasky {
2291e059c120SHans Petter Selasky clear_bit(MLX5E_STATE_FLOW_RULES_READY, &priv->state);
2292e059c120SHans Petter Selasky
2293e059c120SHans Petter Selasky mlx5e_set_rx_mode_core(priv, false);
2294e059c120SHans Petter Selasky mlx5e_del_all_vxlan_rules(priv);
2295e059c120SHans Petter Selasky mlx5e_del_main_vxlan_rules(priv);
2296e059c120SHans Petter Selasky mlx5e_del_all_vlan_rules(priv);
2297e059c120SHans Petter Selasky }
2298