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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 * 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 * 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 * 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 * 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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