2 * Copyright (c) 2015, Mellanox Technologies. All rights reserved.
4 * This software is available to you under a choice of one of two
5 * licenses. You may choose to be licensed under the terms of the GNU
6 * General Public License (GPL) Version 2, available from the file
7 * COPYING in the main directory of this source tree, or the
8 * OpenIB.org BSD license below:
10 * Redistribution and use in source and binary forms, with or
11 * without modification, are permitted provided that the following
14 * - Redistributions of source code must retain the above
15 * copyright notice, this list of conditions and the following
18 * - Redistributions in binary form must reproduce the above
19 * copyright notice, this list of conditions and the following
20 * disclaimer in the documentation and/or other materials
21 * provided with the distribution.
23 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
24 * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
25 * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
26 * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
27 * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
28 * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
29 * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
33 #include <linux/list.h>
35 #include <linux/ipv6.h>
36 #include <linux/tcp.h>
37 #include <linux/mlx5/fs.h>
38 #include <linux/mlx5/mpfs.h>
44 static int mlx5e_add_l2_flow_rule(struct mlx5e_flow_steering *fs,
45 struct mlx5e_l2_rule *ai, int type);
46 static void mlx5e_del_l2_flow_rule(struct mlx5e_flow_steering *fs,
47 struct mlx5e_l2_rule *ai);
62 MLX5E_ACTION_NONE = 0,
67 struct mlx5e_l2_hash_node {
68 struct hlist_node hlist;
70 struct mlx5e_l2_rule ai;
74 static inline int mlx5e_hash_l2(const u8 *addr)
79 static void mlx5e_add_l2_to_hash(struct hlist_head *hash, const u8 *addr)
81 struct mlx5e_l2_hash_node *hn;
82 int ix = mlx5e_hash_l2(addr);
85 hlist_for_each_entry(hn, &hash[ix], hlist)
86 if (ether_addr_equal_64bits(hn->ai.addr, addr)) {
92 hn->action = MLX5E_ACTION_NONE;
96 hn = kzalloc(sizeof(*hn), GFP_ATOMIC);
100 ether_addr_copy(hn->ai.addr, addr);
101 hn->action = MLX5E_ACTION_ADD;
103 hlist_add_head(&hn->hlist, &hash[ix]);
106 static void mlx5e_del_l2_from_hash(struct mlx5e_l2_hash_node *hn)
108 hlist_del(&hn->hlist);
112 struct mlx5e_vlan_table {
113 struct mlx5e_flow_table ft;
114 DECLARE_BITMAP(active_cvlans, VLAN_N_VID);
115 DECLARE_BITMAP(active_svlans, VLAN_N_VID);
116 struct mlx5_flow_handle *active_cvlans_rule[VLAN_N_VID];
117 struct mlx5_flow_handle *active_svlans_rule[VLAN_N_VID];
118 struct mlx5_flow_handle *untagged_rule;
119 struct mlx5_flow_handle *any_cvlan_rule;
120 struct mlx5_flow_handle *any_svlan_rule;
121 struct mlx5_flow_handle *trap_rule;
122 bool cvlan_filter_disabled;
125 unsigned long *mlx5e_vlan_get_active_svlans(struct mlx5e_vlan_table *vlan)
127 return vlan->active_svlans;
130 struct mlx5_flow_table *mlx5e_vlan_get_flowtable(struct mlx5e_vlan_table *vlan)
135 static int mlx5e_vport_context_update_vlans(struct mlx5e_flow_steering *fs)
145 for_each_set_bit(vlan, fs->vlan->active_cvlans, VLAN_N_VID)
148 max_list_size = 1 << MLX5_CAP_GEN(fs->mdev, log_max_vlan_list);
150 if (list_size > max_list_size) {
151 mlx5_core_warn(fs->mdev,
152 "netdev vlans list size (%d) > (%d) max vport list size, some vlans will be dropped\n",
153 list_size, max_list_size);
154 list_size = max_list_size;
157 vlans = kvcalloc(list_size, sizeof(*vlans), GFP_KERNEL);
162 for_each_set_bit(vlan, fs->vlan->active_cvlans, VLAN_N_VID) {
168 err = mlx5_modify_nic_vport_vlans(fs->mdev, vlans, list_size);
170 mlx5_core_err(fs->mdev, "Failed to modify vport vlans list err(%d)\n",
177 enum mlx5e_vlan_rule_type {
178 MLX5E_VLAN_RULE_TYPE_UNTAGGED,
179 MLX5E_VLAN_RULE_TYPE_ANY_CTAG_VID,
180 MLX5E_VLAN_RULE_TYPE_ANY_STAG_VID,
181 MLX5E_VLAN_RULE_TYPE_MATCH_CTAG_VID,
182 MLX5E_VLAN_RULE_TYPE_MATCH_STAG_VID,
185 static int __mlx5e_add_vlan_rule(struct mlx5e_flow_steering *fs,
186 enum mlx5e_vlan_rule_type rule_type,
187 u16 vid, struct mlx5_flow_spec *spec)
189 struct mlx5_flow_table *ft = fs->vlan->ft.t;
190 struct mlx5_flow_destination dest = {};
191 struct mlx5_flow_handle **rule_p;
192 MLX5_DECLARE_FLOW_ACT(flow_act);
195 dest.type = MLX5_FLOW_DESTINATION_TYPE_FLOW_TABLE;
196 dest.ft = fs->l2.ft.t;
198 spec->match_criteria_enable = MLX5_MATCH_OUTER_HEADERS;
201 case MLX5E_VLAN_RULE_TYPE_UNTAGGED:
202 /* cvlan_tag enabled in match criteria and
203 * disabled in match value means both S & C tags
204 * don't exist (untagged of both)
206 rule_p = &fs->vlan->untagged_rule;
207 MLX5_SET_TO_ONES(fte_match_param, spec->match_criteria,
208 outer_headers.cvlan_tag);
210 case MLX5E_VLAN_RULE_TYPE_ANY_CTAG_VID:
211 rule_p = &fs->vlan->any_cvlan_rule;
212 MLX5_SET_TO_ONES(fte_match_param, spec->match_criteria,
213 outer_headers.cvlan_tag);
214 MLX5_SET(fte_match_param, spec->match_value, outer_headers.cvlan_tag, 1);
216 case MLX5E_VLAN_RULE_TYPE_ANY_STAG_VID:
217 rule_p = &fs->vlan->any_svlan_rule;
218 MLX5_SET_TO_ONES(fte_match_param, spec->match_criteria,
219 outer_headers.svlan_tag);
220 MLX5_SET(fte_match_param, spec->match_value, outer_headers.svlan_tag, 1);
222 case MLX5E_VLAN_RULE_TYPE_MATCH_STAG_VID:
223 rule_p = &fs->vlan->active_svlans_rule[vid];
224 MLX5_SET_TO_ONES(fte_match_param, spec->match_criteria,
225 outer_headers.svlan_tag);
226 MLX5_SET(fte_match_param, spec->match_value, outer_headers.svlan_tag, 1);
227 MLX5_SET_TO_ONES(fte_match_param, spec->match_criteria,
228 outer_headers.first_vid);
229 MLX5_SET(fte_match_param, spec->match_value, outer_headers.first_vid,
232 default: /* MLX5E_VLAN_RULE_TYPE_MATCH_CTAG_VID */
233 rule_p = &fs->vlan->active_cvlans_rule[vid];
234 MLX5_SET_TO_ONES(fte_match_param, spec->match_criteria,
235 outer_headers.cvlan_tag);
236 MLX5_SET(fte_match_param, spec->match_value, outer_headers.cvlan_tag, 1);
237 MLX5_SET_TO_ONES(fte_match_param, spec->match_criteria,
238 outer_headers.first_vid);
239 MLX5_SET(fte_match_param, spec->match_value, outer_headers.first_vid,
244 if (WARN_ONCE(*rule_p, "VLAN rule already exists type %d", rule_type))
247 *rule_p = mlx5_add_flow_rules(ft, spec, &flow_act, &dest, 1);
249 if (IS_ERR(*rule_p)) {
250 err = PTR_ERR(*rule_p);
252 mlx5_core_err(fs->mdev, "%s: add rule failed\n", __func__);
258 static int mlx5e_add_vlan_rule(struct mlx5e_flow_steering *fs,
259 enum mlx5e_vlan_rule_type rule_type, u16 vid)
261 struct mlx5_flow_spec *spec;
264 spec = kvzalloc(sizeof(*spec), GFP_KERNEL);
268 if (rule_type == MLX5E_VLAN_RULE_TYPE_MATCH_CTAG_VID)
269 mlx5e_vport_context_update_vlans(fs);
271 err = __mlx5e_add_vlan_rule(fs, rule_type, vid, spec);
278 static void mlx5e_fs_del_vlan_rule(struct mlx5e_flow_steering *fs,
279 enum mlx5e_vlan_rule_type rule_type, u16 vid)
282 case MLX5E_VLAN_RULE_TYPE_UNTAGGED:
283 if (fs->vlan->untagged_rule) {
284 mlx5_del_flow_rules(fs->vlan->untagged_rule);
285 fs->vlan->untagged_rule = NULL;
288 case MLX5E_VLAN_RULE_TYPE_ANY_CTAG_VID:
289 if (fs->vlan->any_cvlan_rule) {
290 mlx5_del_flow_rules(fs->vlan->any_cvlan_rule);
291 fs->vlan->any_cvlan_rule = NULL;
294 case MLX5E_VLAN_RULE_TYPE_ANY_STAG_VID:
295 if (fs->vlan->any_svlan_rule) {
296 mlx5_del_flow_rules(fs->vlan->any_svlan_rule);
297 fs->vlan->any_svlan_rule = NULL;
300 case MLX5E_VLAN_RULE_TYPE_MATCH_STAG_VID:
301 if (fs->vlan->active_svlans_rule[vid]) {
302 mlx5_del_flow_rules(fs->vlan->active_svlans_rule[vid]);
303 fs->vlan->active_svlans_rule[vid] = NULL;
306 case MLX5E_VLAN_RULE_TYPE_MATCH_CTAG_VID:
307 if (fs->vlan->active_cvlans_rule[vid]) {
308 mlx5_del_flow_rules(fs->vlan->active_cvlans_rule[vid]);
309 fs->vlan->active_cvlans_rule[vid] = NULL;
311 mlx5e_vport_context_update_vlans(fs);
316 static void mlx5e_fs_del_any_vid_rules(struct mlx5e_flow_steering *fs)
318 mlx5e_fs_del_vlan_rule(fs, MLX5E_VLAN_RULE_TYPE_ANY_CTAG_VID, 0);
319 mlx5e_fs_del_vlan_rule(fs, MLX5E_VLAN_RULE_TYPE_ANY_STAG_VID, 0);
322 static int mlx5e_fs_add_any_vid_rules(struct mlx5e_flow_steering *fs)
326 err = mlx5e_add_vlan_rule(fs, MLX5E_VLAN_RULE_TYPE_ANY_CTAG_VID, 0);
330 return mlx5e_add_vlan_rule(fs, MLX5E_VLAN_RULE_TYPE_ANY_STAG_VID, 0);
333 static struct mlx5_flow_handle *
334 mlx5e_add_trap_rule(struct mlx5_flow_table *ft, int trap_id, int tir_num)
336 struct mlx5_flow_destination dest = {};
337 MLX5_DECLARE_FLOW_ACT(flow_act);
338 struct mlx5_flow_handle *rule;
339 struct mlx5_flow_spec *spec;
341 spec = kvzalloc(sizeof(*spec), GFP_KERNEL);
343 return ERR_PTR(-ENOMEM);
344 spec->flow_context.flags |= FLOW_CONTEXT_HAS_TAG;
345 spec->flow_context.flow_tag = trap_id;
346 dest.type = MLX5_FLOW_DESTINATION_TYPE_TIR;
347 dest.tir_num = tir_num;
349 rule = mlx5_add_flow_rules(ft, spec, &flow_act, &dest, 1);
354 int mlx5e_add_vlan_trap(struct mlx5e_priv *priv, int trap_id, int tir_num)
356 struct mlx5_flow_table *ft = priv->fs->vlan->ft.t;
357 struct mlx5_flow_handle *rule;
360 rule = mlx5e_add_trap_rule(ft, trap_id, tir_num);
363 priv->fs->vlan->trap_rule = NULL;
364 mlx5_core_err(priv->fs->mdev, "%s: add VLAN trap rule failed, err %d\n",
368 priv->fs->vlan->trap_rule = rule;
372 void mlx5e_remove_vlan_trap(struct mlx5e_priv *priv)
374 if (priv->fs->vlan->trap_rule) {
375 mlx5_del_flow_rules(priv->fs->vlan->trap_rule);
376 priv->fs->vlan->trap_rule = NULL;
380 int mlx5e_add_mac_trap(struct mlx5e_priv *priv, int trap_id, int tir_num)
382 struct mlx5_flow_table *ft = priv->fs->l2.ft.t;
383 struct mlx5_flow_handle *rule;
386 rule = mlx5e_add_trap_rule(ft, trap_id, tir_num);
389 priv->fs->l2.trap_rule = NULL;
390 mlx5_core_err(priv->fs->mdev, "%s: add MAC trap rule failed, err %d\n",
394 priv->fs->l2.trap_rule = rule;
398 void mlx5e_remove_mac_trap(struct mlx5e_priv *priv)
400 if (priv->fs->l2.trap_rule) {
401 mlx5_del_flow_rules(priv->fs->l2.trap_rule);
402 priv->fs->l2.trap_rule = NULL;
406 void mlx5e_enable_cvlan_filter(struct mlx5e_priv *priv)
408 if (!priv->fs->vlan->cvlan_filter_disabled)
411 priv->fs->vlan->cvlan_filter_disabled = false;
412 if (priv->netdev->flags & IFF_PROMISC)
414 mlx5e_fs_del_vlan_rule(priv->fs, MLX5E_VLAN_RULE_TYPE_ANY_CTAG_VID, 0);
417 void mlx5e_disable_cvlan_filter(struct mlx5e_priv *priv)
419 if (priv->fs->vlan->cvlan_filter_disabled)
422 priv->fs->vlan->cvlan_filter_disabled = true;
423 if (priv->netdev->flags & IFF_PROMISC)
425 mlx5e_add_vlan_rule(priv->fs, MLX5E_VLAN_RULE_TYPE_ANY_CTAG_VID, 0);
428 static int mlx5e_vlan_rx_add_cvid(struct mlx5e_flow_steering *fs, u16 vid)
432 set_bit(vid, fs->vlan->active_cvlans);
434 err = mlx5e_add_vlan_rule(fs, MLX5E_VLAN_RULE_TYPE_MATCH_CTAG_VID, vid);
436 clear_bit(vid, fs->vlan->active_cvlans);
441 static int mlx5e_vlan_rx_add_svid(struct mlx5e_flow_steering *fs,
442 struct net_device *netdev, u16 vid)
446 set_bit(vid, fs->vlan->active_svlans);
448 err = mlx5e_add_vlan_rule(fs, MLX5E_VLAN_RULE_TYPE_MATCH_STAG_VID, vid);
450 clear_bit(vid, fs->vlan->active_svlans);
454 /* Need to fix some features.. */
455 netdev_update_features(netdev);
459 int mlx5e_fs_vlan_rx_add_vid(struct mlx5e_flow_steering *fs,
460 struct net_device *netdev,
461 __be16 proto, u16 vid)
465 mlx5_core_err(fs->mdev, "Vlan doesn't exist\n");
469 if (be16_to_cpu(proto) == ETH_P_8021Q)
470 return mlx5e_vlan_rx_add_cvid(fs, vid);
471 else if (be16_to_cpu(proto) == ETH_P_8021AD)
472 return mlx5e_vlan_rx_add_svid(fs, netdev, vid);
477 int mlx5e_fs_vlan_rx_kill_vid(struct mlx5e_flow_steering *fs,
478 struct net_device *netdev,
479 __be16 proto, u16 vid)
482 mlx5_core_err(fs->mdev, "Vlan doesn't exist\n");
486 if (be16_to_cpu(proto) == ETH_P_8021Q) {
487 clear_bit(vid, fs->vlan->active_cvlans);
488 mlx5e_fs_del_vlan_rule(fs, MLX5E_VLAN_RULE_TYPE_MATCH_CTAG_VID, vid);
489 } else if (be16_to_cpu(proto) == ETH_P_8021AD) {
490 clear_bit(vid, fs->vlan->active_svlans);
491 mlx5e_fs_del_vlan_rule(fs, MLX5E_VLAN_RULE_TYPE_MATCH_STAG_VID, vid);
492 netdev_update_features(netdev);
498 static void mlx5e_fs_add_vlan_rules(struct mlx5e_flow_steering *fs)
502 mlx5e_add_vlan_rule(fs, MLX5E_VLAN_RULE_TYPE_UNTAGGED, 0);
504 for_each_set_bit(i, fs->vlan->active_cvlans, VLAN_N_VID) {
505 mlx5e_add_vlan_rule(fs, MLX5E_VLAN_RULE_TYPE_MATCH_CTAG_VID, i);
508 for_each_set_bit(i, fs->vlan->active_svlans, VLAN_N_VID)
509 mlx5e_add_vlan_rule(fs, MLX5E_VLAN_RULE_TYPE_MATCH_STAG_VID, i);
511 if (fs->vlan->cvlan_filter_disabled)
512 mlx5e_fs_add_any_vid_rules(fs);
515 static void mlx5e_del_vlan_rules(struct mlx5e_priv *priv)
519 mlx5e_fs_del_vlan_rule(priv->fs, MLX5E_VLAN_RULE_TYPE_UNTAGGED, 0);
521 for_each_set_bit(i, priv->fs->vlan->active_cvlans, VLAN_N_VID) {
522 mlx5e_fs_del_vlan_rule(priv->fs, MLX5E_VLAN_RULE_TYPE_MATCH_CTAG_VID, i);
525 for_each_set_bit(i, priv->fs->vlan->active_svlans, VLAN_N_VID)
526 mlx5e_fs_del_vlan_rule(priv->fs, MLX5E_VLAN_RULE_TYPE_MATCH_STAG_VID, i);
528 WARN_ON_ONCE(priv->fs->state_destroy);
530 mlx5e_remove_vlan_trap(priv);
532 /* must be called after DESTROY bit is set and
533 * set_rx_mode is called and flushed
535 if (priv->fs->vlan->cvlan_filter_disabled)
536 mlx5e_fs_del_any_vid_rules(priv->fs);
539 #define mlx5e_for_each_hash_node(hn, tmp, hash, i) \
540 for (i = 0; i < MLX5E_L2_ADDR_HASH_SIZE; i++) \
541 hlist_for_each_entry_safe(hn, tmp, &hash[i], hlist)
543 static void mlx5e_execute_l2_action(struct mlx5e_flow_steering *fs,
544 struct mlx5e_l2_hash_node *hn)
546 u8 action = hn->action;
547 u8 mac_addr[ETH_ALEN];
550 ether_addr_copy(mac_addr, hn->ai.addr);
553 case MLX5E_ACTION_ADD:
554 mlx5e_add_l2_flow_rule(fs, &hn->ai, MLX5E_FULLMATCH);
555 if (!is_multicast_ether_addr(mac_addr)) {
556 l2_err = mlx5_mpfs_add_mac(fs->mdev, mac_addr);
559 hn->action = MLX5E_ACTION_NONE;
562 case MLX5E_ACTION_DEL:
563 if (!is_multicast_ether_addr(mac_addr) && hn->mpfs)
564 l2_err = mlx5_mpfs_del_mac(fs->mdev, mac_addr);
565 mlx5e_del_l2_flow_rule(fs, &hn->ai);
566 mlx5e_del_l2_from_hash(hn);
571 mlx5_core_warn(fs->mdev, "MPFS, failed to %s mac %pM, err(%d)\n",
572 action == MLX5E_ACTION_ADD ? "add" : "del", mac_addr, l2_err);
575 static void mlx5e_sync_netdev_addr(struct mlx5e_flow_steering *fs,
576 struct net_device *netdev)
578 struct netdev_hw_addr *ha;
580 netif_addr_lock_bh(netdev);
582 mlx5e_add_l2_to_hash(fs->l2.netdev_uc, netdev->dev_addr);
583 netdev_for_each_uc_addr(ha, netdev)
584 mlx5e_add_l2_to_hash(fs->l2.netdev_uc, ha->addr);
586 netdev_for_each_mc_addr(ha, netdev)
587 mlx5e_add_l2_to_hash(fs->l2.netdev_mc, ha->addr);
589 netif_addr_unlock_bh(netdev);
592 static void mlx5e_fill_addr_array(struct mlx5e_flow_steering *fs, int list_type,
593 struct net_device *ndev,
594 u8 addr_array[][ETH_ALEN], int size)
596 bool is_uc = (list_type == MLX5_NVPRT_LIST_TYPE_UC);
597 struct mlx5e_l2_hash_node *hn;
598 struct hlist_head *addr_list;
599 struct hlist_node *tmp;
603 addr_list = is_uc ? fs->l2.netdev_uc : fs->l2.netdev_mc;
605 if (is_uc) /* Make sure our own address is pushed first */
606 ether_addr_copy(addr_array[i++], ndev->dev_addr);
607 else if (fs->l2.broadcast_enabled)
608 ether_addr_copy(addr_array[i++], ndev->broadcast);
610 mlx5e_for_each_hash_node(hn, tmp, addr_list, hi) {
611 if (ether_addr_equal(ndev->dev_addr, hn->ai.addr))
615 ether_addr_copy(addr_array[i++], hn->ai.addr);
619 static void mlx5e_vport_context_update_addr_list(struct mlx5e_flow_steering *fs,
620 struct net_device *netdev,
623 bool is_uc = (list_type == MLX5_NVPRT_LIST_TYPE_UC);
624 struct mlx5e_l2_hash_node *hn;
625 u8 (*addr_array)[ETH_ALEN] = NULL;
626 struct hlist_head *addr_list;
627 struct hlist_node *tmp;
633 size = is_uc ? 0 : (fs->l2.broadcast_enabled ? 1 : 0);
635 1 << MLX5_CAP_GEN(fs->mdev, log_max_current_uc_list) :
636 1 << MLX5_CAP_GEN(fs->mdev, log_max_current_mc_list);
638 addr_list = is_uc ? fs->l2.netdev_uc : fs->l2.netdev_mc;
639 mlx5e_for_each_hash_node(hn, tmp, addr_list, hi)
642 if (size > max_size) {
643 mlx5_core_warn(fs->mdev,
644 "mdev %s list size (%d) > (%d) max vport list size, some addresses will be dropped\n",
645 is_uc ? "UC" : "MC", size, max_size);
650 addr_array = kcalloc(size, ETH_ALEN, GFP_KERNEL);
655 mlx5e_fill_addr_array(fs, list_type, netdev, addr_array, size);
658 err = mlx5_modify_nic_vport_mac_list(fs->mdev, list_type, addr_array, size);
661 mlx5_core_err(fs->mdev,
662 "Failed to modify vport %s list err(%d)\n",
663 is_uc ? "UC" : "MC", err);
667 static void mlx5e_vport_context_update(struct mlx5e_flow_steering *fs,
668 struct net_device *netdev)
670 struct mlx5e_l2_table *ea = &fs->l2;
672 mlx5e_vport_context_update_addr_list(fs, netdev, MLX5_NVPRT_LIST_TYPE_UC);
673 mlx5e_vport_context_update_addr_list(fs, netdev, MLX5_NVPRT_LIST_TYPE_MC);
674 mlx5_modify_nic_vport_promisc(fs->mdev, 0,
675 ea->allmulti_enabled,
676 ea->promisc_enabled);
679 static void mlx5e_apply_netdev_addr(struct mlx5e_flow_steering *fs)
681 struct mlx5e_l2_hash_node *hn;
682 struct hlist_node *tmp;
685 mlx5e_for_each_hash_node(hn, tmp, fs->l2.netdev_uc, i)
686 mlx5e_execute_l2_action(fs, hn);
688 mlx5e_for_each_hash_node(hn, tmp, fs->l2.netdev_mc, i)
689 mlx5e_execute_l2_action(fs, hn);
692 static void mlx5e_handle_netdev_addr(struct mlx5e_flow_steering *fs,
693 struct net_device *netdev)
695 struct mlx5e_l2_hash_node *hn;
696 struct hlist_node *tmp;
699 mlx5e_for_each_hash_node(hn, tmp, fs->l2.netdev_uc, i)
700 hn->action = MLX5E_ACTION_DEL;
701 mlx5e_for_each_hash_node(hn, tmp, fs->l2.netdev_mc, i)
702 hn->action = MLX5E_ACTION_DEL;
704 if (fs->state_destroy)
705 mlx5e_sync_netdev_addr(fs, netdev);
707 mlx5e_apply_netdev_addr(fs);
710 #define MLX5E_PROMISC_GROUP0_SIZE BIT(0)
711 #define MLX5E_PROMISC_TABLE_SIZE MLX5E_PROMISC_GROUP0_SIZE
713 static int mlx5e_add_promisc_rule(struct mlx5e_flow_steering *fs)
715 struct mlx5_flow_table *ft = fs->promisc.ft.t;
716 struct mlx5_flow_destination dest = {};
717 struct mlx5_flow_handle **rule_p;
718 MLX5_DECLARE_FLOW_ACT(flow_act);
719 struct mlx5_flow_spec *spec;
722 spec = kvzalloc(sizeof(*spec), GFP_KERNEL);
725 dest.type = MLX5_FLOW_DESTINATION_TYPE_FLOW_TABLE;
726 dest.ft = mlx5_get_ttc_flow_table(fs->ttc);
728 rule_p = &fs->promisc.rule;
729 *rule_p = mlx5_add_flow_rules(ft, spec, &flow_act, &dest, 1);
730 if (IS_ERR(*rule_p)) {
731 err = PTR_ERR(*rule_p);
733 mlx5_core_err(fs->mdev, "%s: add promiscuous rule failed\n", __func__);
739 static int mlx5e_create_promisc_table(struct mlx5e_flow_steering *fs)
741 struct mlx5e_flow_table *ft = &fs->promisc.ft;
742 struct mlx5_flow_table_attr ft_attr = {};
745 ft_attr.max_fte = MLX5E_PROMISC_TABLE_SIZE;
746 ft_attr.autogroup.max_num_groups = 1;
747 ft_attr.level = MLX5E_PROMISC_FT_LEVEL;
748 ft_attr.prio = MLX5E_NIC_PRIO;
750 ft->t = mlx5_create_auto_grouped_flow_table(fs->ns, &ft_attr);
752 err = PTR_ERR(ft->t);
753 mlx5_core_err(fs->mdev, "fail to create promisc table err=%d\n", err);
757 err = mlx5e_add_promisc_rule(fs);
759 goto err_destroy_promisc_table;
763 err_destroy_promisc_table:
764 mlx5_destroy_flow_table(ft->t);
770 static void mlx5e_del_promisc_rule(struct mlx5e_flow_steering *fs)
772 if (WARN(!fs->promisc.rule, "Trying to remove non-existing promiscuous rule"))
774 mlx5_del_flow_rules(fs->promisc.rule);
775 fs->promisc.rule = NULL;
778 static void mlx5e_destroy_promisc_table(struct mlx5e_flow_steering *fs)
780 if (WARN(!fs->promisc.ft.t, "Trying to remove non-existing promiscuous table"))
782 mlx5e_del_promisc_rule(fs);
783 mlx5_destroy_flow_table(fs->promisc.ft.t);
784 fs->promisc.ft.t = NULL;
787 void mlx5e_fs_set_rx_mode_work(struct mlx5e_flow_steering *fs,
788 struct net_device *netdev)
790 struct mlx5e_l2_table *ea = &fs->l2;
792 bool rx_mode_enable = fs->state_destroy;
793 bool promisc_enabled = rx_mode_enable && (netdev->flags & IFF_PROMISC);
794 bool allmulti_enabled = rx_mode_enable && (netdev->flags & IFF_ALLMULTI);
795 bool broadcast_enabled = rx_mode_enable;
797 bool enable_promisc = !ea->promisc_enabled && promisc_enabled;
798 bool disable_promisc = ea->promisc_enabled && !promisc_enabled;
799 bool enable_allmulti = !ea->allmulti_enabled && allmulti_enabled;
800 bool disable_allmulti = ea->allmulti_enabled && !allmulti_enabled;
801 bool enable_broadcast = !ea->broadcast_enabled && broadcast_enabled;
802 bool disable_broadcast = ea->broadcast_enabled && !broadcast_enabled;
805 if (enable_promisc) {
806 err = mlx5e_create_promisc_table(fs);
808 enable_promisc = false;
809 if (!fs->vlan_strip_disable && !err)
810 mlx5_core_warn_once(fs->mdev,
811 "S-tagged traffic will be dropped while C-tag vlan stripping is enabled\n");
814 mlx5e_add_l2_flow_rule(fs, &ea->allmulti, MLX5E_ALLMULTI);
815 if (enable_broadcast)
816 mlx5e_add_l2_flow_rule(fs, &ea->broadcast, MLX5E_FULLMATCH);
818 mlx5e_handle_netdev_addr(fs, netdev);
820 if (disable_broadcast)
821 mlx5e_del_l2_flow_rule(fs, &ea->broadcast);
822 if (disable_allmulti)
823 mlx5e_del_l2_flow_rule(fs, &ea->allmulti);
825 mlx5e_destroy_promisc_table(fs);
827 ea->promisc_enabled = promisc_enabled;
828 ea->allmulti_enabled = allmulti_enabled;
829 ea->broadcast_enabled = broadcast_enabled;
831 mlx5e_vport_context_update(fs, netdev);
834 static void mlx5e_destroy_groups(struct mlx5e_flow_table *ft)
838 for (i = ft->num_groups - 1; i >= 0; i--) {
839 if (!IS_ERR_OR_NULL(ft->g[i]))
840 mlx5_destroy_flow_group(ft->g[i]);
846 void mlx5e_fs_init_l2_addr(struct mlx5e_flow_steering *fs, struct net_device *netdev)
848 ether_addr_copy(fs->l2.broadcast.addr, netdev->broadcast);
851 void mlx5e_destroy_flow_table(struct mlx5e_flow_table *ft)
853 mlx5e_destroy_groups(ft);
855 mlx5_destroy_flow_table(ft->t);
859 static void mlx5e_set_inner_ttc_params(struct mlx5e_priv *priv,
860 struct ttc_params *ttc_params)
862 struct mlx5_flow_table_attr *ft_attr = &ttc_params->ft_attr;
865 memset(ttc_params, 0, sizeof(*ttc_params));
866 ttc_params->ns = mlx5_get_flow_namespace(priv->fs->mdev,
867 MLX5_FLOW_NAMESPACE_KERNEL);
868 ft_attr->level = MLX5E_INNER_TTC_FT_LEVEL;
869 ft_attr->prio = MLX5E_NIC_PRIO;
871 for (tt = 0; tt < MLX5_NUM_TT; tt++) {
872 ttc_params->dests[tt].type = MLX5_FLOW_DESTINATION_TYPE_TIR;
873 ttc_params->dests[tt].tir_num =
875 mlx5e_rx_res_get_tirn_direct(priv->rx_res, 0) :
876 mlx5e_rx_res_get_tirn_rss_inner(priv->rx_res,
881 void mlx5e_set_ttc_params(struct mlx5e_priv *priv,
882 struct ttc_params *ttc_params, bool tunnel)
885 struct mlx5_flow_table_attr *ft_attr = &ttc_params->ft_attr;
888 memset(ttc_params, 0, sizeof(*ttc_params));
889 ttc_params->ns = mlx5_get_flow_namespace(priv->fs->mdev,
890 MLX5_FLOW_NAMESPACE_KERNEL);
891 ft_attr->level = MLX5E_TTC_FT_LEVEL;
892 ft_attr->prio = MLX5E_NIC_PRIO;
894 for (tt = 0; tt < MLX5_NUM_TT; tt++) {
895 ttc_params->dests[tt].type = MLX5_FLOW_DESTINATION_TYPE_TIR;
896 ttc_params->dests[tt].tir_num =
898 mlx5e_rx_res_get_tirn_direct(priv->rx_res, 0) :
899 mlx5e_rx_res_get_tirn_rss(priv->rx_res, tt);
902 ttc_params->inner_ttc = tunnel;
903 if (!tunnel || !mlx5_tunnel_inner_ft_supported(priv->fs->mdev))
906 for (tt = 0; tt < MLX5_NUM_TUNNEL_TT; tt++) {
907 ttc_params->tunnel_dests[tt].type =
908 MLX5_FLOW_DESTINATION_TYPE_FLOW_TABLE;
909 ttc_params->tunnel_dests[tt].ft =
910 mlx5_get_ttc_flow_table(priv->fs->inner_ttc);
914 static void mlx5e_del_l2_flow_rule(struct mlx5e_flow_steering *fs,
915 struct mlx5e_l2_rule *ai)
917 if (!IS_ERR_OR_NULL(ai->rule)) {
918 mlx5_del_flow_rules(ai->rule);
923 static int mlx5e_add_l2_flow_rule(struct mlx5e_flow_steering *fs,
924 struct mlx5e_l2_rule *ai, int type)
926 struct mlx5_flow_table *ft = fs->l2.ft.t;
927 struct mlx5_flow_destination dest = {};
928 MLX5_DECLARE_FLOW_ACT(flow_act);
929 struct mlx5_flow_spec *spec;
934 spec = kvzalloc(sizeof(*spec), GFP_KERNEL);
938 mc_dmac = MLX5_ADDR_OF(fte_match_param, spec->match_criteria,
939 outer_headers.dmac_47_16);
940 mv_dmac = MLX5_ADDR_OF(fte_match_param, spec->match_value,
941 outer_headers.dmac_47_16);
943 dest.type = MLX5_FLOW_DESTINATION_TYPE_FLOW_TABLE;
944 dest.ft = mlx5_get_ttc_flow_table(fs->ttc);
947 case MLX5E_FULLMATCH:
948 spec->match_criteria_enable = MLX5_MATCH_OUTER_HEADERS;
949 eth_broadcast_addr(mc_dmac);
950 ether_addr_copy(mv_dmac, ai->addr);
954 spec->match_criteria_enable = MLX5_MATCH_OUTER_HEADERS;
960 ai->rule = mlx5_add_flow_rules(ft, spec, &flow_act, &dest, 1);
961 if (IS_ERR(ai->rule)) {
962 mlx5_core_err(fs->mdev, "%s: add l2 rule(mac:%pM) failed\n",
964 err = PTR_ERR(ai->rule);
973 #define MLX5E_NUM_L2_GROUPS 3
974 #define MLX5E_L2_GROUP1_SIZE BIT(15)
975 #define MLX5E_L2_GROUP2_SIZE BIT(0)
976 #define MLX5E_L2_GROUP_TRAP_SIZE BIT(0) /* must be last */
977 #define MLX5E_L2_TABLE_SIZE (MLX5E_L2_GROUP1_SIZE +\
978 MLX5E_L2_GROUP2_SIZE +\
979 MLX5E_L2_GROUP_TRAP_SIZE)
980 static int mlx5e_create_l2_table_groups(struct mlx5e_l2_table *l2_table)
982 int inlen = MLX5_ST_SZ_BYTES(create_flow_group_in);
983 struct mlx5e_flow_table *ft = &l2_table->ft;
990 ft->g = kcalloc(MLX5E_NUM_L2_GROUPS, sizeof(*ft->g), GFP_KERNEL);
993 in = kvzalloc(inlen, GFP_KERNEL);
999 mc = MLX5_ADDR_OF(create_flow_group_in, in, match_criteria);
1000 mc_dmac = MLX5_ADDR_OF(fte_match_param, mc,
1001 outer_headers.dmac_47_16);
1002 /* Flow Group for full match */
1003 eth_broadcast_addr(mc_dmac);
1004 MLX5_SET_CFG(in, match_criteria_enable, MLX5_MATCH_OUTER_HEADERS);
1005 MLX5_SET_CFG(in, start_flow_index, ix);
1006 ix += MLX5E_L2_GROUP1_SIZE;
1007 MLX5_SET_CFG(in, end_flow_index, ix - 1);
1008 ft->g[ft->num_groups] = mlx5_create_flow_group(ft->t, in);
1009 if (IS_ERR(ft->g[ft->num_groups]))
1010 goto err_destroy_groups;
1013 /* Flow Group for allmulti */
1014 eth_zero_addr(mc_dmac);
1016 MLX5_SET_CFG(in, start_flow_index, ix);
1017 ix += MLX5E_L2_GROUP2_SIZE;
1018 MLX5_SET_CFG(in, end_flow_index, ix - 1);
1019 ft->g[ft->num_groups] = mlx5_create_flow_group(ft->t, in);
1020 if (IS_ERR(ft->g[ft->num_groups]))
1021 goto err_destroy_groups;
1024 /* Flow Group for l2 traps */
1025 memset(in, 0, inlen);
1026 MLX5_SET_CFG(in, start_flow_index, ix);
1027 ix += MLX5E_L2_GROUP_TRAP_SIZE;
1028 MLX5_SET_CFG(in, end_flow_index, ix - 1);
1029 ft->g[ft->num_groups] = mlx5_create_flow_group(ft->t, in);
1030 if (IS_ERR(ft->g[ft->num_groups]))
1031 goto err_destroy_groups;
1038 err = PTR_ERR(ft->g[ft->num_groups]);
1039 ft->g[ft->num_groups] = NULL;
1040 mlx5e_destroy_groups(ft);
1047 static void mlx5e_destroy_l2_table(struct mlx5e_priv *priv)
1049 mlx5e_destroy_flow_table(&priv->fs->l2.ft);
1052 static int mlx5e_create_l2_table(struct mlx5e_priv *priv)
1054 struct mlx5e_l2_table *l2_table = &priv->fs->l2;
1055 struct mlx5e_flow_table *ft = &l2_table->ft;
1056 struct mlx5_flow_table_attr ft_attr = {};
1061 ft_attr.max_fte = MLX5E_L2_TABLE_SIZE;
1062 ft_attr.level = MLX5E_L2_FT_LEVEL;
1063 ft_attr.prio = MLX5E_NIC_PRIO;
1065 ft->t = mlx5_create_flow_table(priv->fs->ns, &ft_attr);
1066 if (IS_ERR(ft->t)) {
1067 err = PTR_ERR(ft->t);
1072 err = mlx5e_create_l2_table_groups(l2_table);
1074 goto err_destroy_flow_table;
1078 err_destroy_flow_table:
1079 mlx5_destroy_flow_table(ft->t);
1085 #define MLX5E_NUM_VLAN_GROUPS 5
1086 #define MLX5E_VLAN_GROUP0_SIZE BIT(12)
1087 #define MLX5E_VLAN_GROUP1_SIZE BIT(12)
1088 #define MLX5E_VLAN_GROUP2_SIZE BIT(1)
1089 #define MLX5E_VLAN_GROUP3_SIZE BIT(0)
1090 #define MLX5E_VLAN_GROUP_TRAP_SIZE BIT(0) /* must be last */
1091 #define MLX5E_VLAN_TABLE_SIZE (MLX5E_VLAN_GROUP0_SIZE +\
1092 MLX5E_VLAN_GROUP1_SIZE +\
1093 MLX5E_VLAN_GROUP2_SIZE +\
1094 MLX5E_VLAN_GROUP3_SIZE +\
1095 MLX5E_VLAN_GROUP_TRAP_SIZE)
1097 static int __mlx5e_create_vlan_table_groups(struct mlx5e_flow_table *ft, u32 *in,
1102 u8 *mc = MLX5_ADDR_OF(create_flow_group_in, in, match_criteria);
1104 memset(in, 0, inlen);
1105 MLX5_SET_CFG(in, match_criteria_enable, MLX5_MATCH_OUTER_HEADERS);
1106 MLX5_SET_TO_ONES(fte_match_param, mc, outer_headers.cvlan_tag);
1107 MLX5_SET_TO_ONES(fte_match_param, mc, outer_headers.first_vid);
1108 MLX5_SET_CFG(in, start_flow_index, ix);
1109 ix += MLX5E_VLAN_GROUP0_SIZE;
1110 MLX5_SET_CFG(in, end_flow_index, ix - 1);
1111 ft->g[ft->num_groups] = mlx5_create_flow_group(ft->t, in);
1112 if (IS_ERR(ft->g[ft->num_groups]))
1113 goto err_destroy_groups;
1116 memset(in, 0, inlen);
1117 MLX5_SET_CFG(in, match_criteria_enable, MLX5_MATCH_OUTER_HEADERS);
1118 MLX5_SET_TO_ONES(fte_match_param, mc, outer_headers.svlan_tag);
1119 MLX5_SET_TO_ONES(fte_match_param, mc, outer_headers.first_vid);
1120 MLX5_SET_CFG(in, start_flow_index, ix);
1121 ix += MLX5E_VLAN_GROUP1_SIZE;
1122 MLX5_SET_CFG(in, end_flow_index, ix - 1);
1123 ft->g[ft->num_groups] = mlx5_create_flow_group(ft->t, in);
1124 if (IS_ERR(ft->g[ft->num_groups]))
1125 goto err_destroy_groups;
1128 memset(in, 0, inlen);
1129 MLX5_SET_CFG(in, match_criteria_enable, MLX5_MATCH_OUTER_HEADERS);
1130 MLX5_SET_TO_ONES(fte_match_param, mc, outer_headers.cvlan_tag);
1131 MLX5_SET_CFG(in, start_flow_index, ix);
1132 ix += MLX5E_VLAN_GROUP2_SIZE;
1133 MLX5_SET_CFG(in, end_flow_index, ix - 1);
1134 ft->g[ft->num_groups] = mlx5_create_flow_group(ft->t, in);
1135 if (IS_ERR(ft->g[ft->num_groups]))
1136 goto err_destroy_groups;
1139 memset(in, 0, inlen);
1140 MLX5_SET_CFG(in, match_criteria_enable, MLX5_MATCH_OUTER_HEADERS);
1141 MLX5_SET_TO_ONES(fte_match_param, mc, outer_headers.svlan_tag);
1142 MLX5_SET_CFG(in, start_flow_index, ix);
1143 ix += MLX5E_VLAN_GROUP3_SIZE;
1144 MLX5_SET_CFG(in, end_flow_index, ix - 1);
1145 ft->g[ft->num_groups] = mlx5_create_flow_group(ft->t, in);
1146 if (IS_ERR(ft->g[ft->num_groups]))
1147 goto err_destroy_groups;
1150 memset(in, 0, inlen);
1151 MLX5_SET_CFG(in, start_flow_index, ix);
1152 ix += MLX5E_VLAN_GROUP_TRAP_SIZE;
1153 MLX5_SET_CFG(in, end_flow_index, ix - 1);
1154 ft->g[ft->num_groups] = mlx5_create_flow_group(ft->t, in);
1155 if (IS_ERR(ft->g[ft->num_groups]))
1156 goto err_destroy_groups;
1162 err = PTR_ERR(ft->g[ft->num_groups]);
1163 ft->g[ft->num_groups] = NULL;
1164 mlx5e_destroy_groups(ft);
1169 static int mlx5e_create_vlan_table_groups(struct mlx5e_flow_table *ft)
1172 int inlen = MLX5_ST_SZ_BYTES(create_flow_group_in);
1175 in = kvzalloc(inlen, GFP_KERNEL);
1179 err = __mlx5e_create_vlan_table_groups(ft, in, inlen);
1185 static int mlx5e_fs_create_vlan_table(struct mlx5e_flow_steering *fs)
1187 struct mlx5_flow_table_attr ft_attr = {};
1188 struct mlx5e_flow_table *ft;
1194 ft_attr.max_fte = MLX5E_VLAN_TABLE_SIZE;
1195 ft_attr.level = MLX5E_VLAN_FT_LEVEL;
1196 ft_attr.prio = MLX5E_NIC_PRIO;
1198 ft->t = mlx5_create_flow_table(fs->ns, &ft_attr);
1200 return PTR_ERR(ft->t);
1202 ft->g = kcalloc(MLX5E_NUM_VLAN_GROUPS, sizeof(*ft->g), GFP_KERNEL);
1205 goto err_destroy_vlan_table;
1208 err = mlx5e_create_vlan_table_groups(ft);
1212 mlx5e_fs_add_vlan_rules(fs);
1218 err_destroy_vlan_table:
1219 mlx5_destroy_flow_table(ft->t);
1224 static void mlx5e_destroy_vlan_table(struct mlx5e_priv *priv)
1226 mlx5e_del_vlan_rules(priv);
1227 mlx5e_destroy_flow_table(&priv->fs->vlan->ft);
1230 static void mlx5e_destroy_inner_ttc_table(struct mlx5e_priv *priv)
1232 if (!mlx5_tunnel_inner_ft_supported(priv->fs->mdev))
1234 mlx5_destroy_ttc_table(priv->fs->inner_ttc);
1237 void mlx5e_destroy_ttc_table(struct mlx5e_priv *priv)
1239 mlx5_destroy_ttc_table(priv->fs->ttc);
1242 static int mlx5e_create_inner_ttc_table(struct mlx5e_priv *priv)
1244 struct ttc_params ttc_params = {};
1246 if (!mlx5_tunnel_inner_ft_supported(priv->fs->mdev))
1249 mlx5e_set_inner_ttc_params(priv, &ttc_params);
1250 priv->fs->inner_ttc = mlx5_create_inner_ttc_table(priv->fs->mdev,
1252 if (IS_ERR(priv->fs->inner_ttc))
1253 return PTR_ERR(priv->fs->inner_ttc);
1257 int mlx5e_create_ttc_table(struct mlx5e_priv *priv)
1259 struct ttc_params ttc_params = {};
1261 mlx5e_set_ttc_params(priv, &ttc_params, true);
1262 priv->fs->ttc = mlx5_create_ttc_table(priv->fs->mdev, &ttc_params);
1263 if (IS_ERR(priv->fs->ttc))
1264 return PTR_ERR(priv->fs->ttc);
1268 int mlx5e_create_flow_steering(struct mlx5e_priv *priv)
1272 priv->fs->ns = mlx5_get_flow_namespace(priv->fs->mdev,
1273 MLX5_FLOW_NAMESPACE_KERNEL);
1278 err = mlx5e_arfs_create_tables(priv);
1280 mlx5_core_err(priv->fs->mdev, "Failed to create arfs tables, err=%d\n",
1282 priv->netdev->hw_features &= ~NETIF_F_NTUPLE;
1285 err = mlx5e_create_inner_ttc_table(priv);
1287 mlx5_core_err(priv->fs->mdev,
1288 "Failed to create inner ttc table, err=%d\n", err);
1289 goto err_destroy_arfs_tables;
1292 err = mlx5e_create_ttc_table(priv);
1294 mlx5_core_err(priv->fs->mdev, "Failed to create ttc table, err=%d\n",
1296 goto err_destroy_inner_ttc_table;
1299 err = mlx5e_create_l2_table(priv);
1301 mlx5_core_err(priv->fs->mdev, "Failed to create l2 table, err=%d\n",
1303 goto err_destroy_ttc_table;
1306 err = mlx5e_fs_create_vlan_table(priv->fs);
1308 mlx5_core_err(priv->fs->mdev, "Failed to create vlan table, err=%d\n",
1310 goto err_destroy_l2_table;
1313 err = mlx5e_ptp_alloc_rx_fs(priv);
1315 goto err_destory_vlan_table;
1317 mlx5e_ethtool_init_steering(priv);
1321 err_destory_vlan_table:
1322 mlx5e_destroy_vlan_table(priv);
1323 err_destroy_l2_table:
1324 mlx5e_destroy_l2_table(priv);
1325 err_destroy_ttc_table:
1326 mlx5e_destroy_ttc_table(priv);
1327 err_destroy_inner_ttc_table:
1328 mlx5e_destroy_inner_ttc_table(priv);
1329 err_destroy_arfs_tables:
1330 mlx5e_arfs_destroy_tables(priv);
1335 void mlx5e_destroy_flow_steering(struct mlx5e_priv *priv)
1337 mlx5e_ptp_free_rx_fs(priv);
1338 mlx5e_destroy_vlan_table(priv);
1339 mlx5e_destroy_l2_table(priv);
1340 mlx5e_destroy_ttc_table(priv);
1341 mlx5e_destroy_inner_ttc_table(priv);
1342 mlx5e_arfs_destroy_tables(priv);
1343 mlx5e_ethtool_cleanup_steering(priv);
1346 static int mlx5e_fs_vlan_alloc(struct mlx5e_flow_steering *fs)
1348 fs->vlan = kvzalloc(sizeof(*fs->vlan), GFP_KERNEL);
1354 static void mlx5e_fs_vlan_free(struct mlx5e_flow_steering *fs)
1359 static int mlx5e_fs_tc_alloc(struct mlx5e_flow_steering *fs)
1361 fs->tc = mlx5e_tc_table_alloc();
1367 static void mlx5e_fs_tc_free(struct mlx5e_flow_steering *fs)
1369 mlx5e_tc_table_free(fs->tc);
1372 struct mlx5e_flow_steering *mlx5e_fs_init(const struct mlx5e_profile *profile,
1373 struct mlx5_core_dev *mdev,
1376 struct mlx5e_flow_steering *fs;
1379 fs = kvzalloc(sizeof(*fs), GFP_KERNEL);
1384 fs->state_destroy = state_destroy;
1385 if (mlx5e_profile_feature_cap(profile, FS_VLAN)) {
1386 err = mlx5e_fs_vlan_alloc(fs);
1391 if (mlx5e_profile_feature_cap(profile, FS_TC)) {
1392 err = mlx5e_fs_tc_alloc(fs);
1400 mlx5e_fs_vlan_free(fs);
1407 void mlx5e_fs_cleanup(struct mlx5e_flow_steering *fs)
1409 mlx5e_fs_tc_free(fs);
1410 mlx5e_fs_vlan_free(fs);