Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux
1
fork

Configure Feed

Select the types of activity you want to include in your feed.

Merge branch 'mlx5-updates-2021-01-26'

Saeed Mahameed says:

====================
mlx5 devlink traps support

Add support for devlink traps [1] reporting in mlx5,
mlx5 will also report/trap packets filtered due to dest mac steering miss

The first patch in the series defines the new DMAC trap type in devlink
for this purpose.

Other patches in the series are mlx5 only and they gradually traps support.
Supported traps:

DMAC: Drops due to destination MAC not configured in the MAC table
VLAN: Drops due to vlan not configured in the vlan table

Design note:
devlink instance is managed by the low level mlx5 core layer, mlx5 core will
serve as an abstraction layer for trap reporting, since we might have multiple
mlx5 interfaces who might want to report traps on the same device.
====================

Link: https://lore.kernel.org/r/20210126232419.175836-1-saeedm@nvidia.com
Signed-off-by: Jakub Kicinski <kuba@kernel.org>

+1079 -52
+1 -1
drivers/net/ethernet/mellanox/mlx5/core/Makefile
··· 27 27 en_selftest.o en/port.o en/monitor_stats.o en/health.o \ 28 28 en/reporter_tx.o en/reporter_rx.o en/params.o en/xsk/pool.o \ 29 29 en/xsk/setup.o en/xsk/rx.o en/xsk/tx.o en/devlink.o en/ptp.o \ 30 - en/qos.o 30 + en/qos.o en/trap.o 31 31 32 32 # 33 33 # Netdev extra
+188
drivers/net/ethernet/mellanox/mlx5/core/devlink.c
··· 168 168 return 0; 169 169 } 170 170 171 + static struct mlx5_devlink_trap *mlx5_find_trap_by_id(struct mlx5_core_dev *dev, int trap_id) 172 + { 173 + struct mlx5_devlink_trap *dl_trap; 174 + 175 + list_for_each_entry(dl_trap, &dev->priv.traps, list) 176 + if (dl_trap->trap.id == trap_id) 177 + return dl_trap; 178 + 179 + return NULL; 180 + } 181 + 182 + static int mlx5_devlink_trap_init(struct devlink *devlink, const struct devlink_trap *trap, 183 + void *trap_ctx) 184 + { 185 + struct mlx5_core_dev *dev = devlink_priv(devlink); 186 + struct mlx5_devlink_trap *dl_trap; 187 + 188 + dl_trap = kzalloc(sizeof(*dl_trap), GFP_KERNEL); 189 + if (!dl_trap) 190 + return -ENOMEM; 191 + 192 + dl_trap->trap.id = trap->id; 193 + dl_trap->trap.action = DEVLINK_TRAP_ACTION_DROP; 194 + dl_trap->item = trap_ctx; 195 + 196 + if (mlx5_find_trap_by_id(dev, trap->id)) { 197 + kfree(dl_trap); 198 + mlx5_core_err(dev, "Devlink trap: Trap 0x%x already found", trap->id); 199 + return -EEXIST; 200 + } 201 + 202 + list_add_tail(&dl_trap->list, &dev->priv.traps); 203 + return 0; 204 + } 205 + 206 + static void mlx5_devlink_trap_fini(struct devlink *devlink, const struct devlink_trap *trap, 207 + void *trap_ctx) 208 + { 209 + struct mlx5_core_dev *dev = devlink_priv(devlink); 210 + struct mlx5_devlink_trap *dl_trap; 211 + 212 + dl_trap = mlx5_find_trap_by_id(dev, trap->id); 213 + if (!dl_trap) { 214 + mlx5_core_err(dev, "Devlink trap: Missing trap id 0x%x", trap->id); 215 + return; 216 + } 217 + list_del(&dl_trap->list); 218 + kfree(dl_trap); 219 + } 220 + 221 + static int mlx5_devlink_trap_action_set(struct devlink *devlink, 222 + const struct devlink_trap *trap, 223 + enum devlink_trap_action action, 224 + struct netlink_ext_ack *extack) 225 + { 226 + struct mlx5_core_dev *dev = devlink_priv(devlink); 227 + enum devlink_trap_action action_orig; 228 + struct mlx5_devlink_trap *dl_trap; 229 + int err = 0; 230 + 231 + dl_trap = mlx5_find_trap_by_id(dev, trap->id); 232 + if (!dl_trap) { 233 + mlx5_core_err(dev, "Devlink trap: Set action on invalid trap id 0x%x", trap->id); 234 + err = -EINVAL; 235 + goto out; 236 + } 237 + 238 + if (action != DEVLINK_TRAP_ACTION_DROP && action != DEVLINK_TRAP_ACTION_TRAP) { 239 + err = -EOPNOTSUPP; 240 + goto out; 241 + } 242 + 243 + if (action == dl_trap->trap.action) 244 + goto out; 245 + 246 + action_orig = dl_trap->trap.action; 247 + dl_trap->trap.action = action; 248 + err = mlx5_blocking_notifier_call_chain(dev, MLX5_DRIVER_EVENT_TYPE_TRAP, 249 + &dl_trap->trap); 250 + if (err) 251 + dl_trap->trap.action = action_orig; 252 + out: 253 + return err; 254 + } 255 + 171 256 static const struct devlink_ops mlx5_devlink_ops = { 172 257 #ifdef CONFIG_MLX5_ESWITCH 173 258 .eswitch_mode_set = mlx5_devlink_eswitch_mode_set, ··· 271 186 .reload_limits = BIT(DEVLINK_RELOAD_LIMIT_NO_RESET), 272 187 .reload_down = mlx5_devlink_reload_down, 273 188 .reload_up = mlx5_devlink_reload_up, 189 + .trap_init = mlx5_devlink_trap_init, 190 + .trap_fini = mlx5_devlink_trap_fini, 191 + .trap_action_set = mlx5_devlink_trap_action_set, 274 192 }; 193 + 194 + void mlx5_devlink_trap_report(struct mlx5_core_dev *dev, int trap_id, struct sk_buff *skb, 195 + struct devlink_port *dl_port) 196 + { 197 + struct devlink *devlink = priv_to_devlink(dev); 198 + struct mlx5_devlink_trap *dl_trap; 199 + 200 + dl_trap = mlx5_find_trap_by_id(dev, trap_id); 201 + if (!dl_trap) { 202 + mlx5_core_err(dev, "Devlink trap: Report on invalid trap id 0x%x", trap_id); 203 + return; 204 + } 205 + 206 + if (dl_trap->trap.action != DEVLINK_TRAP_ACTION_TRAP) { 207 + mlx5_core_dbg(dev, "Devlink trap: Trap id %d has action %d", trap_id, 208 + dl_trap->trap.action); 209 + return; 210 + } 211 + devlink_trap_report(devlink, skb, dl_trap->item, dl_port, NULL); 212 + } 213 + 214 + int mlx5_devlink_trap_get_num_active(struct mlx5_core_dev *dev) 215 + { 216 + struct mlx5_devlink_trap *dl_trap; 217 + int count = 0; 218 + 219 + list_for_each_entry(dl_trap, &dev->priv.traps, list) 220 + if (dl_trap->trap.action == DEVLINK_TRAP_ACTION_TRAP) 221 + count++; 222 + 223 + return count; 224 + } 225 + 226 + int mlx5_devlink_traps_get_action(struct mlx5_core_dev *dev, int trap_id, 227 + enum devlink_trap_action *action) 228 + { 229 + struct mlx5_devlink_trap *dl_trap; 230 + 231 + dl_trap = mlx5_find_trap_by_id(dev, trap_id); 232 + if (!dl_trap) { 233 + mlx5_core_err(dev, "Devlink trap: Get action on invalid trap id 0x%x", 234 + trap_id); 235 + return -EINVAL; 236 + } 237 + 238 + *action = dl_trap->trap.action; 239 + return 0; 240 + } 275 241 276 242 struct devlink *mlx5_devlink_alloc(void) 277 243 { ··· 494 358 #endif 495 359 } 496 360 361 + #define MLX5_TRAP_DROP(_id, _group_id) \ 362 + DEVLINK_TRAP_GENERIC(DROP, DROP, _id, \ 363 + DEVLINK_TRAP_GROUP_GENERIC_ID_##_group_id, \ 364 + DEVLINK_TRAP_METADATA_TYPE_F_IN_PORT) 365 + 366 + static const struct devlink_trap mlx5_traps_arr[] = { 367 + MLX5_TRAP_DROP(INGRESS_VLAN_FILTER, L2_DROPS), 368 + MLX5_TRAP_DROP(DMAC_FILTER, L2_DROPS), 369 + }; 370 + 371 + static const struct devlink_trap_group mlx5_trap_groups_arr[] = { 372 + DEVLINK_TRAP_GROUP_GENERIC(L2_DROPS, 0), 373 + }; 374 + 375 + static int mlx5_devlink_traps_register(struct devlink *devlink) 376 + { 377 + struct mlx5_core_dev *core_dev = devlink_priv(devlink); 378 + int err; 379 + 380 + err = devlink_trap_groups_register(devlink, mlx5_trap_groups_arr, 381 + ARRAY_SIZE(mlx5_trap_groups_arr)); 382 + if (err) 383 + return err; 384 + 385 + err = devlink_traps_register(devlink, mlx5_traps_arr, ARRAY_SIZE(mlx5_traps_arr), 386 + &core_dev->priv); 387 + if (err) 388 + goto err_trap_group; 389 + return 0; 390 + 391 + err_trap_group: 392 + devlink_trap_groups_unregister(devlink, mlx5_trap_groups_arr, 393 + ARRAY_SIZE(mlx5_trap_groups_arr)); 394 + return err; 395 + } 396 + 397 + static void mlx5_devlink_traps_unregister(struct devlink *devlink) 398 + { 399 + devlink_traps_unregister(devlink, mlx5_traps_arr, ARRAY_SIZE(mlx5_traps_arr)); 400 + devlink_trap_groups_unregister(devlink, mlx5_trap_groups_arr, 401 + ARRAY_SIZE(mlx5_trap_groups_arr)); 402 + } 403 + 497 404 int mlx5_devlink_register(struct devlink *devlink, struct device *dev) 498 405 { 499 406 int err; ··· 551 372 goto params_reg_err; 552 373 mlx5_devlink_set_params_init_values(devlink); 553 374 devlink_params_publish(devlink); 375 + 376 + err = mlx5_devlink_traps_register(devlink); 377 + if (err) 378 + goto traps_reg_err; 379 + 554 380 return 0; 555 381 382 + traps_reg_err: 383 + devlink_params_unregister(devlink, mlx5_devlink_params, 384 + ARRAY_SIZE(mlx5_devlink_params)); 556 385 params_reg_err: 557 386 devlink_unregister(devlink); 558 387 return err; ··· 568 381 569 382 void mlx5_devlink_unregister(struct devlink *devlink) 570 383 { 384 + mlx5_devlink_traps_unregister(devlink); 571 385 devlink_params_unregister(devlink, mlx5_devlink_params, 572 386 ARRAY_SIZE(mlx5_devlink_params)); 573 387 devlink_unregister(devlink);
+18
drivers/net/ethernet/mellanox/mlx5/core/devlink.h
··· 12 12 MLX5_DEVLINK_PARAM_ID_ESW_LARGE_GROUP_NUM, 13 13 }; 14 14 15 + struct mlx5_trap_ctx { 16 + int id; 17 + int action; 18 + }; 19 + 20 + struct mlx5_devlink_trap { 21 + struct mlx5_trap_ctx trap; 22 + void *item; 23 + struct list_head list; 24 + }; 25 + 26 + struct mlx5_core_dev; 27 + void mlx5_devlink_trap_report(struct mlx5_core_dev *dev, int trap_id, struct sk_buff *skb, 28 + struct devlink_port *dl_port); 29 + int mlx5_devlink_trap_get_num_active(struct mlx5_core_dev *dev); 30 + int mlx5_devlink_traps_get_action(struct mlx5_core_dev *dev, int trap_id, 31 + enum devlink_trap_action *action); 32 + 15 33 struct devlink *mlx5_devlink_alloc(void); 16 34 void mlx5_devlink_free(struct devlink *devlink); 17 35 int mlx5_devlink_register(struct devlink *devlink, struct device *dev);
+10
drivers/net/ethernet/mellanox/mlx5/core/en.h
··· 564 564 typedef void (*mlx5e_fp_dealloc_wqe)(struct mlx5e_rq*, u16); 565 565 566 566 int mlx5e_rq_set_handlers(struct mlx5e_rq *rq, struct mlx5e_params *params, bool xsk); 567 + void mlx5e_rq_set_trap_handlers(struct mlx5e_rq *rq, struct mlx5e_params *params); 567 568 568 569 enum mlx5e_rq_flag { 569 570 MLX5E_RQ_FLAG_XDP_XMIT, ··· 806 805 u16 defcls; 807 806 }; 808 807 808 + struct mlx5e_trap; 809 + 809 810 struct mlx5e_priv { 810 811 /* priv data path fields - start */ 811 812 /* +1 for port ptp ts */ ··· 847 844 848 845 struct mlx5_core_dev *mdev; 849 846 struct net_device *netdev; 847 + struct mlx5e_trap *en_trap; 850 848 struct mlx5e_stats stats; 851 849 struct mlx5e_channel_stats channel_stats[MLX5E_MAX_NUM_CHANNELS]; 850 + struct mlx5e_channel_stats trap_stats; 852 851 struct mlx5e_port_ptp_stats port_ptp_stats; 853 852 u16 max_nch; 854 853 u8 max_opened_tc; ··· 859 854 u16 q_counter; 860 855 u16 drop_rq_q_counter; 861 856 struct notifier_block events_nb; 857 + struct notifier_block blocking_events_nb; 862 858 int num_tc_x_num_ch; 863 859 864 860 struct udp_tunnel_nic_info nic_info; ··· 967 961 int mlx5e_wait_for_min_rx_wqes(struct mlx5e_rq *rq, int wait_time); 968 962 void mlx5e_deactivate_rq(struct mlx5e_rq *rq); 969 963 void mlx5e_close_rq(struct mlx5e_rq *rq); 964 + int mlx5e_create_rq(struct mlx5e_rq *rq, struct mlx5e_rq_param *param); 965 + void mlx5e_destroy_rq(struct mlx5e_rq *rq); 970 966 971 967 struct mlx5e_sq_param; 972 968 int mlx5e_open_icosq(struct mlx5e_channel *c, struct mlx5e_params *params, ··· 1080 1072 int mlx5e_open_drop_rq(struct mlx5e_priv *priv, 1081 1073 struct mlx5e_rq *drop_rq); 1082 1074 void mlx5e_close_drop_rq(struct mlx5e_rq *drop_rq); 1075 + int mlx5e_init_di_list(struct mlx5e_rq *rq, int wq_sz, int node); 1076 + void mlx5e_free_di_list(struct mlx5e_rq *rq); 1083 1077 1084 1078 int mlx5e_create_indirect_rqt(struct mlx5e_priv *priv); 1085 1079
+14 -2
drivers/net/ethernet/mellanox/mlx5/core/en/fs.h
··· 44 44 45 45 #define MLX5E_L2_ADDR_HASH_SIZE BIT(BITS_PER_BYTE) 46 46 47 + struct mlx5e_promisc_table { 48 + struct mlx5e_flow_table ft; 49 + struct mlx5_flow_handle *rule; 50 + }; 51 + 47 52 struct mlx5e_vlan_table { 48 53 struct mlx5e_flow_table ft; 49 54 DECLARE_BITMAP(active_cvlans, VLAN_N_VID); ··· 58 53 struct mlx5_flow_handle *untagged_rule; 59 54 struct mlx5_flow_handle *any_cvlan_rule; 60 55 struct mlx5_flow_handle *any_svlan_rule; 56 + struct mlx5_flow_handle *trap_rule; 61 57 bool cvlan_filter_disabled; 62 58 }; 63 59 ··· 68 62 struct hlist_head netdev_mc[MLX5E_L2_ADDR_HASH_SIZE]; 69 63 struct mlx5e_l2_rule broadcast; 70 64 struct mlx5e_l2_rule allmulti; 71 - struct mlx5e_l2_rule promisc; 65 + struct mlx5_flow_handle *trap_rule; 72 66 bool broadcast_enabled; 73 67 bool allmulti_enabled; 74 68 bool promisc_enabled; ··· 132 126 133 127 /* NIC prio FTS */ 134 128 enum { 135 - MLX5E_VLAN_FT_LEVEL = 0, 129 + MLX5E_PROMISC_FT_LEVEL, 130 + MLX5E_VLAN_FT_LEVEL, 136 131 MLX5E_L2_FT_LEVEL, 137 132 MLX5E_TTC_FT_LEVEL, 138 133 MLX5E_INNER_TTC_FT_LEVEL, ··· 248 241 struct mlx5e_ethtool_steering ethtool; 249 242 #endif 250 243 struct mlx5e_tc_table tc; 244 + struct mlx5e_promisc_table promisc; 251 245 struct mlx5e_vlan_table vlan; 252 246 struct mlx5e_l2_table l2; 253 247 struct mlx5e_ttc_table ttc; ··· 296 288 void mlx5e_destroy_flow_steering(struct mlx5e_priv *priv); 297 289 298 290 u8 mlx5e_get_proto_by_tunnel_type(enum mlx5e_tunnel_types tt); 291 + int mlx5e_add_vlan_trap(struct mlx5e_priv *priv, int trap_id, int tir_num); 292 + void mlx5e_remove_vlan_trap(struct mlx5e_priv *priv); 293 + int mlx5e_add_mac_trap(struct mlx5e_priv *priv, int trap_id, int tir_num); 294 + void mlx5e_remove_mac_trap(struct mlx5e_priv *priv); 299 295 300 296 #endif /* __MLX5E_FLOW_STEER_H__ */ 301 297
+457
drivers/net/ethernet/mellanox/mlx5/core/en/trap.c
··· 1 + // SPDX-License-Identifier: GPL-2.0 OR Linux-OpenIB 2 + /* Copyright (c) 2020 Mellanox Technologies */ 3 + 4 + #include <net/page_pool.h> 5 + #include "en/txrx.h" 6 + #include "en/params.h" 7 + #include "en/trap.h" 8 + 9 + static int mlx5e_trap_napi_poll(struct napi_struct *napi, int budget) 10 + { 11 + struct mlx5e_trap *trap_ctx = container_of(napi, struct mlx5e_trap, napi); 12 + struct mlx5e_ch_stats *ch_stats = trap_ctx->stats; 13 + struct mlx5e_rq *rq = &trap_ctx->rq; 14 + bool busy = false; 15 + int work_done = 0; 16 + 17 + ch_stats->poll++; 18 + 19 + work_done = mlx5e_poll_rx_cq(&rq->cq, budget); 20 + busy |= work_done == budget; 21 + busy |= rq->post_wqes(rq); 22 + 23 + if (busy) 24 + return budget; 25 + 26 + if (unlikely(!napi_complete_done(napi, work_done))) 27 + return work_done; 28 + 29 + mlx5e_cq_arm(&rq->cq); 30 + return work_done; 31 + } 32 + 33 + static int mlx5e_alloc_trap_rq(struct mlx5e_priv *priv, struct mlx5e_rq_param *rqp, 34 + struct mlx5e_rq_stats *stats, struct mlx5e_params *params, 35 + struct mlx5e_ch_stats *ch_stats, 36 + struct mlx5e_rq *rq) 37 + { 38 + void *rqc_wq = MLX5_ADDR_OF(rqc, rqp->rqc, wq); 39 + struct mlx5_core_dev *mdev = priv->mdev; 40 + struct page_pool_params pp_params = {}; 41 + int node = dev_to_node(mdev->device); 42 + u32 pool_size; 43 + int wq_sz; 44 + int err; 45 + int i; 46 + 47 + rqp->wq.db_numa_node = node; 48 + 49 + rq->wq_type = params->rq_wq_type; 50 + rq->pdev = mdev->device; 51 + rq->netdev = priv->netdev; 52 + rq->mdev = mdev; 53 + rq->priv = priv; 54 + rq->stats = stats; 55 + rq->clock = &mdev->clock; 56 + rq->tstamp = &priv->tstamp; 57 + rq->hw_mtu = MLX5E_SW2HW_MTU(params, params->sw_mtu); 58 + 59 + xdp_rxq_info_unused(&rq->xdp_rxq); 60 + 61 + rq->buff.map_dir = DMA_FROM_DEVICE; 62 + rq->buff.headroom = mlx5e_get_rq_headroom(mdev, params, NULL); 63 + pool_size = 1 << params->log_rq_mtu_frames; 64 + 65 + err = mlx5_wq_cyc_create(mdev, &rqp->wq, rqc_wq, &rq->wqe.wq, &rq->wq_ctrl); 66 + if (err) 67 + return err; 68 + 69 + rq->wqe.wq.db = &rq->wqe.wq.db[MLX5_RCV_DBR]; 70 + 71 + wq_sz = mlx5_wq_cyc_get_size(&rq->wqe.wq); 72 + 73 + rq->wqe.info = rqp->frags_info; 74 + rq->buff.frame0_sz = rq->wqe.info.arr[0].frag_stride; 75 + rq->wqe.frags = kvzalloc_node(array_size(sizeof(*rq->wqe.frags), 76 + (wq_sz << rq->wqe.info.log_num_frags)), 77 + GFP_KERNEL, node); 78 + if (!rq->wqe.frags) { 79 + err = -ENOMEM; 80 + goto err_wq_cyc_destroy; 81 + } 82 + 83 + err = mlx5e_init_di_list(rq, wq_sz, node); 84 + if (err) 85 + goto err_free_frags; 86 + 87 + rq->mkey_be = cpu_to_be32(priv->mdev->mlx5e_res.mkey.key); 88 + 89 + mlx5e_rq_set_trap_handlers(rq, params); 90 + 91 + /* Create a page_pool and register it with rxq */ 92 + pp_params.order = 0; 93 + pp_params.flags = 0; /* No-internal DMA mapping in page_pool */ 94 + pp_params.pool_size = pool_size; 95 + pp_params.nid = node; 96 + pp_params.dev = mdev->device; 97 + pp_params.dma_dir = rq->buff.map_dir; 98 + 99 + /* page_pool can be used even when there is no rq->xdp_prog, 100 + * given page_pool does not handle DMA mapping there is no 101 + * required state to clear. And page_pool gracefully handle 102 + * elevated refcnt. 103 + */ 104 + rq->page_pool = page_pool_create(&pp_params); 105 + if (IS_ERR(rq->page_pool)) { 106 + err = PTR_ERR(rq->page_pool); 107 + rq->page_pool = NULL; 108 + goto err_free_di_list; 109 + } 110 + for (i = 0; i < wq_sz; i++) { 111 + struct mlx5e_rx_wqe_cyc *wqe = 112 + mlx5_wq_cyc_get_wqe(&rq->wqe.wq, i); 113 + int f; 114 + 115 + for (f = 0; f < rq->wqe.info.num_frags; f++) { 116 + u32 frag_size = rq->wqe.info.arr[f].frag_size | 117 + MLX5_HW_START_PADDING; 118 + 119 + wqe->data[f].byte_count = cpu_to_be32(frag_size); 120 + wqe->data[f].lkey = rq->mkey_be; 121 + } 122 + /* check if num_frags is not a pow of two */ 123 + if (rq->wqe.info.num_frags < (1 << rq->wqe.info.log_num_frags)) { 124 + wqe->data[f].byte_count = 0; 125 + wqe->data[f].lkey = cpu_to_be32(MLX5_INVALID_LKEY); 126 + wqe->data[f].addr = 0; 127 + } 128 + } 129 + return 0; 130 + 131 + err_free_di_list: 132 + mlx5e_free_di_list(rq); 133 + err_free_frags: 134 + kvfree(rq->wqe.frags); 135 + err_wq_cyc_destroy: 136 + mlx5_wq_destroy(&rq->wq_ctrl); 137 + 138 + return err; 139 + } 140 + 141 + static void mlx5e_free_trap_rq(struct mlx5e_rq *rq) 142 + { 143 + page_pool_destroy(rq->page_pool); 144 + mlx5e_free_di_list(rq); 145 + kvfree(rq->wqe.frags); 146 + mlx5_wq_destroy(&rq->wq_ctrl); 147 + } 148 + 149 + static int mlx5e_open_trap_rq(struct mlx5e_priv *priv, struct napi_struct *napi, 150 + struct mlx5e_rq_stats *stats, struct mlx5e_params *params, 151 + struct mlx5e_rq_param *rq_param, 152 + struct mlx5e_ch_stats *ch_stats, 153 + struct mlx5e_rq *rq) 154 + { 155 + struct mlx5_core_dev *mdev = priv->mdev; 156 + struct mlx5e_create_cq_param ccp = {}; 157 + struct dim_cq_moder trap_moder = {}; 158 + struct mlx5e_cq *cq = &rq->cq; 159 + int err; 160 + 161 + ccp.node = dev_to_node(mdev->device); 162 + ccp.ch_stats = ch_stats; 163 + ccp.napi = napi; 164 + ccp.ix = 0; 165 + err = mlx5e_open_cq(priv, trap_moder, &rq_param->cqp, &ccp, cq); 166 + if (err) 167 + return err; 168 + 169 + err = mlx5e_alloc_trap_rq(priv, rq_param, stats, params, ch_stats, rq); 170 + if (err) 171 + goto err_destroy_cq; 172 + 173 + err = mlx5e_create_rq(rq, rq_param); 174 + if (err) 175 + goto err_free_rq; 176 + 177 + err = mlx5e_modify_rq_state(rq, MLX5_RQC_STATE_RST, MLX5_RQC_STATE_RDY); 178 + if (err) 179 + goto err_destroy_rq; 180 + 181 + return 0; 182 + 183 + err_destroy_rq: 184 + mlx5e_destroy_rq(rq); 185 + mlx5e_free_rx_descs(rq); 186 + err_free_rq: 187 + mlx5e_free_trap_rq(rq); 188 + err_destroy_cq: 189 + mlx5e_close_cq(cq); 190 + 191 + return err; 192 + } 193 + 194 + static void mlx5e_close_trap_rq(struct mlx5e_rq *rq) 195 + { 196 + mlx5e_destroy_rq(rq); 197 + mlx5e_free_rx_descs(rq); 198 + mlx5e_free_trap_rq(rq); 199 + mlx5e_close_cq(&rq->cq); 200 + } 201 + 202 + static int mlx5e_create_trap_direct_rq_tir(struct mlx5_core_dev *mdev, struct mlx5e_tir *tir, 203 + u32 rqn) 204 + { 205 + void *tirc; 206 + int inlen; 207 + u32 *in; 208 + int err; 209 + 210 + inlen = MLX5_ST_SZ_BYTES(create_tir_in); 211 + in = kvzalloc(inlen, GFP_KERNEL); 212 + if (!in) 213 + return -ENOMEM; 214 + 215 + tirc = MLX5_ADDR_OF(create_tir_in, in, ctx); 216 + MLX5_SET(tirc, tirc, transport_domain, mdev->mlx5e_res.td.tdn); 217 + MLX5_SET(tirc, tirc, rx_hash_fn, MLX5_RX_HASH_FN_NONE); 218 + MLX5_SET(tirc, tirc, disp_type, MLX5_TIRC_DISP_TYPE_DIRECT); 219 + MLX5_SET(tirc, tirc, inline_rqn, rqn); 220 + err = mlx5e_create_tir(mdev, tir, in); 221 + kvfree(in); 222 + 223 + return err; 224 + } 225 + 226 + static void mlx5e_destroy_trap_direct_rq_tir(struct mlx5_core_dev *mdev, struct mlx5e_tir *tir) 227 + { 228 + mlx5e_destroy_tir(mdev, tir); 229 + } 230 + 231 + static void mlx5e_activate_trap_rq(struct mlx5e_rq *rq) 232 + { 233 + set_bit(MLX5E_RQ_STATE_ENABLED, &rq->state); 234 + } 235 + 236 + static void mlx5e_deactivate_trap_rq(struct mlx5e_rq *rq) 237 + { 238 + clear_bit(MLX5E_RQ_STATE_ENABLED, &rq->state); 239 + } 240 + 241 + static void mlx5e_build_trap_params(struct mlx5e_priv *priv, struct mlx5e_trap *t) 242 + { 243 + struct mlx5e_params *params = &t->params; 244 + 245 + params->rq_wq_type = MLX5_WQ_TYPE_CYCLIC; 246 + mlx5e_init_rq_type_params(priv->mdev, params); 247 + params->sw_mtu = priv->netdev->max_mtu; 248 + mlx5e_build_rq_param(priv, params, NULL, &t->rq_param); 249 + } 250 + 251 + static struct mlx5e_trap *mlx5e_open_trap(struct mlx5e_priv *priv) 252 + { 253 + int cpu = cpumask_first(mlx5_comp_irq_get_affinity_mask(priv->mdev, 0)); 254 + struct net_device *netdev = priv->netdev; 255 + struct mlx5e_trap *t; 256 + int err; 257 + 258 + t = kvzalloc_node(sizeof(*t), GFP_KERNEL, cpu_to_node(cpu)); 259 + if (!t) 260 + return ERR_PTR(-ENOMEM); 261 + 262 + mlx5e_build_trap_params(priv, t); 263 + 264 + t->priv = priv; 265 + t->mdev = priv->mdev; 266 + t->tstamp = &priv->tstamp; 267 + t->pdev = mlx5_core_dma_dev(priv->mdev); 268 + t->netdev = priv->netdev; 269 + t->mkey_be = cpu_to_be32(priv->mdev->mlx5e_res.mkey.key); 270 + t->stats = &priv->trap_stats.ch; 271 + 272 + netif_napi_add(netdev, &t->napi, mlx5e_trap_napi_poll, 64); 273 + 274 + err = mlx5e_open_trap_rq(priv, &t->napi, 275 + &priv->trap_stats.rq, 276 + &t->params, &t->rq_param, 277 + &priv->trap_stats.ch, 278 + &t->rq); 279 + if (unlikely(err)) 280 + goto err_napi_del; 281 + 282 + err = mlx5e_create_trap_direct_rq_tir(t->mdev, &t->tir, t->rq.rqn); 283 + if (err) 284 + goto err_close_trap_rq; 285 + 286 + return t; 287 + 288 + err_close_trap_rq: 289 + mlx5e_close_trap_rq(&t->rq); 290 + err_napi_del: 291 + netif_napi_del(&t->napi); 292 + kvfree(t); 293 + return ERR_PTR(err); 294 + } 295 + 296 + void mlx5e_close_trap(struct mlx5e_trap *trap) 297 + { 298 + mlx5e_destroy_trap_direct_rq_tir(trap->mdev, &trap->tir); 299 + mlx5e_close_trap_rq(&trap->rq); 300 + netif_napi_del(&trap->napi); 301 + kvfree(trap); 302 + } 303 + 304 + static void mlx5e_activate_trap(struct mlx5e_trap *trap) 305 + { 306 + napi_enable(&trap->napi); 307 + mlx5e_activate_trap_rq(&trap->rq); 308 + napi_schedule(&trap->napi); 309 + } 310 + 311 + void mlx5e_deactivate_trap(struct mlx5e_priv *priv) 312 + { 313 + struct mlx5e_trap *trap = priv->en_trap; 314 + 315 + mlx5e_deactivate_trap_rq(&trap->rq); 316 + napi_disable(&trap->napi); 317 + } 318 + 319 + static struct mlx5e_trap *mlx5e_add_trap_queue(struct mlx5e_priv *priv) 320 + { 321 + struct mlx5e_trap *trap; 322 + 323 + trap = mlx5e_open_trap(priv); 324 + if (IS_ERR(trap)) 325 + goto out; 326 + 327 + mlx5e_activate_trap(trap); 328 + out: 329 + return trap; 330 + } 331 + 332 + static void mlx5e_del_trap_queue(struct mlx5e_priv *priv) 333 + { 334 + mlx5e_deactivate_trap(priv); 335 + mlx5e_close_trap(priv->en_trap); 336 + priv->en_trap = NULL; 337 + } 338 + 339 + static int mlx5e_trap_get_tirn(struct mlx5e_trap *en_trap) 340 + { 341 + return en_trap->tir.tirn; 342 + } 343 + 344 + static int mlx5e_handle_action_trap(struct mlx5e_priv *priv, int trap_id) 345 + { 346 + bool open_queue = !priv->en_trap; 347 + struct mlx5e_trap *trap; 348 + int err; 349 + 350 + if (open_queue) { 351 + trap = mlx5e_add_trap_queue(priv); 352 + if (IS_ERR(trap)) 353 + return PTR_ERR(trap); 354 + priv->en_trap = trap; 355 + } 356 + 357 + switch (trap_id) { 358 + case DEVLINK_TRAP_GENERIC_ID_INGRESS_VLAN_FILTER: 359 + err = mlx5e_add_vlan_trap(priv, trap_id, mlx5e_trap_get_tirn(priv->en_trap)); 360 + if (err) 361 + goto err_out; 362 + break; 363 + case DEVLINK_TRAP_GENERIC_ID_DMAC_FILTER: 364 + err = mlx5e_add_mac_trap(priv, trap_id, mlx5e_trap_get_tirn(priv->en_trap)); 365 + if (err) 366 + goto err_out; 367 + break; 368 + default: 369 + netdev_warn(priv->netdev, "%s: Unknown trap id %d\n", __func__, trap_id); 370 + err = -EINVAL; 371 + goto err_out; 372 + } 373 + return 0; 374 + 375 + err_out: 376 + if (open_queue) 377 + mlx5e_del_trap_queue(priv); 378 + return err; 379 + } 380 + 381 + static int mlx5e_handle_action_drop(struct mlx5e_priv *priv, int trap_id) 382 + { 383 + switch (trap_id) { 384 + case DEVLINK_TRAP_GENERIC_ID_INGRESS_VLAN_FILTER: 385 + mlx5e_remove_vlan_trap(priv); 386 + break; 387 + case DEVLINK_TRAP_GENERIC_ID_DMAC_FILTER: 388 + mlx5e_remove_mac_trap(priv); 389 + break; 390 + default: 391 + netdev_warn(priv->netdev, "%s: Unknown trap id %d\n", __func__, trap_id); 392 + return -EINVAL; 393 + } 394 + if (priv->en_trap && !mlx5_devlink_trap_get_num_active(priv->mdev)) 395 + mlx5e_del_trap_queue(priv); 396 + 397 + return 0; 398 + } 399 + 400 + int mlx5e_handle_trap_event(struct mlx5e_priv *priv, struct mlx5_trap_ctx *trap_ctx) 401 + { 402 + int err = 0; 403 + 404 + /* Traps are unarmed when interface is down, no need to update 405 + * them. The configuration is saved in the core driver, 406 + * queried and applied upon interface up operation in 407 + * mlx5e_open_locked(). 408 + */ 409 + if (!test_bit(MLX5E_STATE_OPENED, &priv->state)) 410 + return 0; 411 + 412 + switch (trap_ctx->action) { 413 + case DEVLINK_TRAP_ACTION_TRAP: 414 + err = mlx5e_handle_action_trap(priv, trap_ctx->id); 415 + break; 416 + case DEVLINK_TRAP_ACTION_DROP: 417 + err = mlx5e_handle_action_drop(priv, trap_ctx->id); 418 + break; 419 + default: 420 + netdev_warn(priv->netdev, "%s: Unsupported action %d\n", __func__, 421 + trap_ctx->action); 422 + err = -EINVAL; 423 + } 424 + return err; 425 + } 426 + 427 + static int mlx5e_apply_trap(struct mlx5e_priv *priv, int trap_id, bool enable) 428 + { 429 + enum devlink_trap_action action; 430 + int err; 431 + 432 + err = mlx5_devlink_traps_get_action(priv->mdev, trap_id, &action); 433 + if (err) 434 + return err; 435 + if (action == DEVLINK_TRAP_ACTION_TRAP) 436 + err = enable ? mlx5e_handle_action_trap(priv, trap_id) : 437 + mlx5e_handle_action_drop(priv, trap_id); 438 + return err; 439 + } 440 + 441 + static const int mlx5e_traps_arr[] = { 442 + DEVLINK_TRAP_GENERIC_ID_INGRESS_VLAN_FILTER, 443 + DEVLINK_TRAP_GENERIC_ID_DMAC_FILTER, 444 + }; 445 + 446 + int mlx5e_apply_traps(struct mlx5e_priv *priv, bool enable) 447 + { 448 + int err; 449 + int i; 450 + 451 + for (i = 0; i < ARRAY_SIZE(mlx5e_traps_arr); i++) { 452 + err = mlx5e_apply_trap(priv, mlx5e_traps_arr[i], enable); 453 + if (err) 454 + return err; 455 + } 456 + return 0; 457 + }
+37
drivers/net/ethernet/mellanox/mlx5/core/en/trap.h
··· 1 + /* SPDX-License-Identifier: GPL-2.0 OR Linux-OpenIB */ 2 + /* Copyright (c) 2020, Mellanox Technologies */ 3 + 4 + #ifndef __MLX5E_TRAP_H__ 5 + #define __MLX5E_TRAP_H__ 6 + 7 + #include "../en.h" 8 + #include "../devlink.h" 9 + 10 + struct mlx5e_trap { 11 + /* data path */ 12 + struct mlx5e_rq rq; 13 + struct mlx5e_tir tir; 14 + struct napi_struct napi; 15 + struct device *pdev; 16 + struct net_device *netdev; 17 + __be32 mkey_be; 18 + 19 + /* data path - accessed per napi poll */ 20 + struct mlx5e_ch_stats *stats; 21 + 22 + /* control */ 23 + struct mlx5e_priv *priv; 24 + struct mlx5_core_dev *mdev; 25 + struct hwtstamp_config *tstamp; 26 + DECLARE_BITMAP(state, MLX5E_CHANNEL_NUM_STATES); 27 + 28 + struct mlx5e_params params; 29 + struct mlx5e_rq_param rq_param; 30 + }; 31 + 32 + void mlx5e_close_trap(struct mlx5e_trap *trap); 33 + void mlx5e_deactivate_trap(struct mlx5e_priv *priv); 34 + int mlx5e_handle_trap_event(struct mlx5e_priv *priv, struct mlx5_trap_ctx *trap_ctx); 35 + int mlx5e_apply_traps(struct mlx5e_priv *priv, bool enable); 36 + 37 + #endif
+188 -30
drivers/net/ethernet/mellanox/mlx5/core/en_fs.c
··· 46 46 enum { 47 47 MLX5E_FULLMATCH = 0, 48 48 MLX5E_ALLMULTI = 1, 49 - MLX5E_PROMISC = 2, 50 49 }; 51 50 52 51 enum { ··· 305 306 return mlx5e_add_vlan_rule(priv, MLX5E_VLAN_RULE_TYPE_ANY_STAG_VID, 0); 306 307 } 307 308 309 + static struct mlx5_flow_handle * 310 + mlx5e_add_trap_rule(struct mlx5_flow_table *ft, int trap_id, int tir_num) 311 + { 312 + struct mlx5_flow_destination dest = {}; 313 + MLX5_DECLARE_FLOW_ACT(flow_act); 314 + struct mlx5_flow_handle *rule; 315 + struct mlx5_flow_spec *spec; 316 + 317 + spec = kvzalloc(sizeof(*spec), GFP_KERNEL); 318 + if (!spec) 319 + return ERR_PTR(-ENOMEM); 320 + spec->flow_context.flags |= FLOW_CONTEXT_HAS_TAG; 321 + spec->flow_context.flow_tag = trap_id; 322 + dest.type = MLX5_FLOW_DESTINATION_TYPE_TIR; 323 + dest.tir_num = tir_num; 324 + 325 + rule = mlx5_add_flow_rules(ft, spec, &flow_act, &dest, 1); 326 + kvfree(spec); 327 + return rule; 328 + } 329 + 330 + int mlx5e_add_vlan_trap(struct mlx5e_priv *priv, int trap_id, int tir_num) 331 + { 332 + struct mlx5_flow_table *ft = priv->fs.vlan.ft.t; 333 + struct mlx5_flow_handle *rule; 334 + int err; 335 + 336 + rule = mlx5e_add_trap_rule(ft, trap_id, tir_num); 337 + if (IS_ERR(rule)) { 338 + err = PTR_ERR(rule); 339 + priv->fs.vlan.trap_rule = NULL; 340 + netdev_err(priv->netdev, "%s: add VLAN trap rule failed, err %d\n", 341 + __func__, err); 342 + return err; 343 + } 344 + priv->fs.vlan.trap_rule = rule; 345 + return 0; 346 + } 347 + 348 + void mlx5e_remove_vlan_trap(struct mlx5e_priv *priv) 349 + { 350 + if (priv->fs.vlan.trap_rule) { 351 + mlx5_del_flow_rules(priv->fs.vlan.trap_rule); 352 + priv->fs.vlan.trap_rule = NULL; 353 + } 354 + } 355 + 356 + int mlx5e_add_mac_trap(struct mlx5e_priv *priv, int trap_id, int tir_num) 357 + { 358 + struct mlx5_flow_table *ft = priv->fs.l2.ft.t; 359 + struct mlx5_flow_handle *rule; 360 + int err; 361 + 362 + rule = mlx5e_add_trap_rule(ft, trap_id, tir_num); 363 + if (IS_ERR(rule)) { 364 + err = PTR_ERR(rule); 365 + priv->fs.l2.trap_rule = NULL; 366 + netdev_err(priv->netdev, "%s: add MAC trap rule failed, err %d\n", 367 + __func__, err); 368 + return err; 369 + } 370 + priv->fs.l2.trap_rule = rule; 371 + return 0; 372 + } 373 + 374 + void mlx5e_remove_mac_trap(struct mlx5e_priv *priv) 375 + { 376 + if (priv->fs.l2.trap_rule) { 377 + mlx5_del_flow_rules(priv->fs.l2.trap_rule); 378 + priv->fs.l2.trap_rule = NULL; 379 + } 380 + } 381 + 308 382 void mlx5e_enable_cvlan_filter(struct mlx5e_priv *priv) 309 383 { 310 384 if (!priv->fs.vlan.cvlan_filter_disabled) ··· 490 418 mlx5e_del_vlan_rule(priv, MLX5E_VLAN_RULE_TYPE_MATCH_STAG_VID, i); 491 419 492 420 WARN_ON_ONCE(!(test_bit(MLX5E_STATE_DESTROYING, &priv->state))); 421 + 422 + mlx5e_remove_vlan_trap(priv); 493 423 494 424 /* must be called after DESTROY bit is set and 495 425 * set_rx_mode is called and flushed ··· 670 596 mlx5e_apply_netdev_addr(priv); 671 597 } 672 598 599 + #define MLX5E_PROMISC_GROUP0_SIZE BIT(0) 600 + #define MLX5E_PROMISC_TABLE_SIZE MLX5E_PROMISC_GROUP0_SIZE 601 + 602 + static int mlx5e_add_promisc_rule(struct mlx5e_priv *priv) 603 + { 604 + struct mlx5_flow_table *ft = priv->fs.promisc.ft.t; 605 + struct mlx5_flow_destination dest = {}; 606 + struct mlx5_flow_handle **rule_p; 607 + MLX5_DECLARE_FLOW_ACT(flow_act); 608 + struct mlx5_flow_spec *spec; 609 + int err = 0; 610 + 611 + spec = kvzalloc(sizeof(*spec), GFP_KERNEL); 612 + if (!spec) 613 + return -ENOMEM; 614 + dest.type = MLX5_FLOW_DESTINATION_TYPE_FLOW_TABLE; 615 + dest.ft = priv->fs.ttc.ft.t; 616 + 617 + rule_p = &priv->fs.promisc.rule; 618 + *rule_p = mlx5_add_flow_rules(ft, spec, &flow_act, &dest, 1); 619 + if (IS_ERR(*rule_p)) { 620 + err = PTR_ERR(*rule_p); 621 + *rule_p = NULL; 622 + netdev_err(priv->netdev, "%s: add promiscuous rule failed\n", __func__); 623 + } 624 + kvfree(spec); 625 + return err; 626 + } 627 + 628 + static int mlx5e_create_promisc_table(struct mlx5e_priv *priv) 629 + { 630 + struct mlx5e_flow_table *ft = &priv->fs.promisc.ft; 631 + struct mlx5_flow_table_attr ft_attr = {}; 632 + int err; 633 + 634 + ft_attr.max_fte = MLX5E_PROMISC_TABLE_SIZE; 635 + ft_attr.autogroup.max_num_groups = 1; 636 + ft_attr.level = MLX5E_PROMISC_FT_LEVEL; 637 + ft_attr.prio = MLX5E_NIC_PRIO; 638 + 639 + ft->t = mlx5_create_auto_grouped_flow_table(priv->fs.ns, &ft_attr); 640 + if (IS_ERR(ft->t)) { 641 + err = PTR_ERR(ft->t); 642 + netdev_err(priv->netdev, "fail to create promisc table err=%d\n", err); 643 + return err; 644 + } 645 + 646 + err = mlx5e_add_promisc_rule(priv); 647 + if (err) 648 + goto err_destroy_promisc_table; 649 + 650 + return 0; 651 + 652 + err_destroy_promisc_table: 653 + mlx5_destroy_flow_table(ft->t); 654 + ft->t = NULL; 655 + 656 + return err; 657 + } 658 + 659 + static void mlx5e_del_promisc_rule(struct mlx5e_priv *priv) 660 + { 661 + if (WARN(!priv->fs.promisc.rule, "Trying to remove non-existing promiscuous rule")) 662 + return; 663 + mlx5_del_flow_rules(priv->fs.promisc.rule); 664 + priv->fs.promisc.rule = NULL; 665 + } 666 + 667 + static void mlx5e_destroy_promisc_table(struct mlx5e_priv *priv) 668 + { 669 + if (WARN(!priv->fs.promisc.ft.t, "Trying to remove non-existing promiscuous table")) 670 + return; 671 + mlx5e_del_promisc_rule(priv); 672 + mlx5_destroy_flow_table(priv->fs.promisc.ft.t); 673 + priv->fs.promisc.ft.t = NULL; 674 + } 675 + 673 676 void mlx5e_set_rx_mode_work(struct work_struct *work) 674 677 { 675 678 struct mlx5e_priv *priv = container_of(work, struct mlx5e_priv, ··· 766 615 bool disable_allmulti = ea->allmulti_enabled && !allmulti_enabled; 767 616 bool enable_broadcast = !ea->broadcast_enabled && broadcast_enabled; 768 617 bool disable_broadcast = ea->broadcast_enabled && !broadcast_enabled; 618 + int err; 769 619 770 620 if (enable_promisc) { 771 - if (!priv->channels.params.vlan_strip_disable) 621 + err = mlx5e_create_promisc_table(priv); 622 + if (err) 623 + enable_promisc = false; 624 + if (!priv->channels.params.vlan_strip_disable && !err) 772 625 netdev_warn_once(ndev, 773 626 "S-tagged traffic will be dropped while C-tag vlan stripping is enabled\n"); 774 - mlx5e_add_l2_flow_rule(priv, &ea->promisc, MLX5E_PROMISC); 775 - if (!priv->fs.vlan.cvlan_filter_disabled) 776 - mlx5e_add_any_vid_rules(priv); 777 627 } 778 628 if (enable_allmulti) 779 629 mlx5e_add_l2_flow_rule(priv, &ea->allmulti, MLX5E_ALLMULTI); ··· 787 635 mlx5e_del_l2_flow_rule(priv, &ea->broadcast); 788 636 if (disable_allmulti) 789 637 mlx5e_del_l2_flow_rule(priv, &ea->allmulti); 790 - if (disable_promisc) { 791 - if (!priv->fs.vlan.cvlan_filter_disabled) 792 - mlx5e_del_any_vid_rules(priv); 793 - mlx5e_del_l2_flow_rule(priv, &ea->promisc); 794 - } 638 + if (disable_promisc) 639 + mlx5e_destroy_promisc_table(priv); 795 640 796 641 ea->promisc_enabled = promisc_enabled; 797 642 ea->allmulti_enabled = allmulti_enabled; ··· 1455 1306 mc_dmac[0] = 0x01; 1456 1307 mv_dmac[0] = 0x01; 1457 1308 break; 1458 - 1459 - case MLX5E_PROMISC: 1460 - break; 1461 1309 } 1462 1310 1463 1311 ai->rule = mlx5_add_flow_rules(ft, spec, &flow_act, &dest, 1); ··· 1471 1325 } 1472 1326 1473 1327 #define MLX5E_NUM_L2_GROUPS 3 1474 - #define MLX5E_L2_GROUP1_SIZE BIT(0) 1475 - #define MLX5E_L2_GROUP2_SIZE BIT(15) 1476 - #define MLX5E_L2_GROUP3_SIZE BIT(0) 1328 + #define MLX5E_L2_GROUP1_SIZE BIT(15) 1329 + #define MLX5E_L2_GROUP2_SIZE BIT(0) 1330 + #define MLX5E_L2_GROUP_TRAP_SIZE BIT(0) /* must be last */ 1477 1331 #define MLX5E_L2_TABLE_SIZE (MLX5E_L2_GROUP1_SIZE +\ 1478 1332 MLX5E_L2_GROUP2_SIZE +\ 1479 - MLX5E_L2_GROUP3_SIZE) 1333 + MLX5E_L2_GROUP_TRAP_SIZE) 1480 1334 static int mlx5e_create_l2_table_groups(struct mlx5e_l2_table *l2_table) 1481 1335 { 1482 1336 int inlen = MLX5_ST_SZ_BYTES(create_flow_group_in); ··· 1499 1353 mc = MLX5_ADDR_OF(create_flow_group_in, in, match_criteria); 1500 1354 mc_dmac = MLX5_ADDR_OF(fte_match_param, mc, 1501 1355 outer_headers.dmac_47_16); 1502 - /* Flow Group for promiscuous */ 1503 - MLX5_SET_CFG(in, start_flow_index, ix); 1504 - ix += MLX5E_L2_GROUP1_SIZE; 1505 - MLX5_SET_CFG(in, end_flow_index, ix - 1); 1506 - ft->g[ft->num_groups] = mlx5_create_flow_group(ft->t, in); 1507 - if (IS_ERR(ft->g[ft->num_groups])) 1508 - goto err_destroy_groups; 1509 - ft->num_groups++; 1510 - 1511 1356 /* Flow Group for full match */ 1512 1357 eth_broadcast_addr(mc_dmac); 1513 1358 MLX5_SET_CFG(in, match_criteria_enable, MLX5_MATCH_OUTER_HEADERS); 1514 1359 MLX5_SET_CFG(in, start_flow_index, ix); 1515 - ix += MLX5E_L2_GROUP2_SIZE; 1360 + ix += MLX5E_L2_GROUP1_SIZE; 1516 1361 MLX5_SET_CFG(in, end_flow_index, ix - 1); 1517 1362 ft->g[ft->num_groups] = mlx5_create_flow_group(ft->t, in); 1518 1363 if (IS_ERR(ft->g[ft->num_groups])) ··· 1514 1377 eth_zero_addr(mc_dmac); 1515 1378 mc_dmac[0] = 0x01; 1516 1379 MLX5_SET_CFG(in, start_flow_index, ix); 1517 - ix += MLX5E_L2_GROUP3_SIZE; 1380 + ix += MLX5E_L2_GROUP2_SIZE; 1381 + MLX5_SET_CFG(in, end_flow_index, ix - 1); 1382 + ft->g[ft->num_groups] = mlx5_create_flow_group(ft->t, in); 1383 + if (IS_ERR(ft->g[ft->num_groups])) 1384 + goto err_destroy_groups; 1385 + ft->num_groups++; 1386 + 1387 + /* Flow Group for l2 traps */ 1388 + memset(in, 0, inlen); 1389 + MLX5_SET_CFG(in, start_flow_index, ix); 1390 + ix += MLX5E_L2_GROUP_TRAP_SIZE; 1518 1391 MLX5_SET_CFG(in, end_flow_index, ix - 1); 1519 1392 ft->g[ft->num_groups] = mlx5_create_flow_group(ft->t, in); 1520 1393 if (IS_ERR(ft->g[ft->num_groups])) ··· 1582 1435 return err; 1583 1436 } 1584 1437 1585 - #define MLX5E_NUM_VLAN_GROUPS 4 1438 + #define MLX5E_NUM_VLAN_GROUPS 5 1586 1439 #define MLX5E_VLAN_GROUP0_SIZE BIT(12) 1587 1440 #define MLX5E_VLAN_GROUP1_SIZE BIT(12) 1588 1441 #define MLX5E_VLAN_GROUP2_SIZE BIT(1) 1589 1442 #define MLX5E_VLAN_GROUP3_SIZE BIT(0) 1443 + #define MLX5E_VLAN_GROUP_TRAP_SIZE BIT(0) /* must be last */ 1590 1444 #define MLX5E_VLAN_TABLE_SIZE (MLX5E_VLAN_GROUP0_SIZE +\ 1591 1445 MLX5E_VLAN_GROUP1_SIZE +\ 1592 1446 MLX5E_VLAN_GROUP2_SIZE +\ 1593 - MLX5E_VLAN_GROUP3_SIZE) 1447 + MLX5E_VLAN_GROUP3_SIZE +\ 1448 + MLX5E_VLAN_GROUP_TRAP_SIZE) 1594 1449 1595 1450 static int __mlx5e_create_vlan_table_groups(struct mlx5e_flow_table *ft, u32 *in, 1596 1451 int inlen) ··· 1641 1492 MLX5_SET_TO_ONES(fte_match_param, mc, outer_headers.svlan_tag); 1642 1493 MLX5_SET_CFG(in, start_flow_index, ix); 1643 1494 ix += MLX5E_VLAN_GROUP3_SIZE; 1495 + MLX5_SET_CFG(in, end_flow_index, ix - 1); 1496 + ft->g[ft->num_groups] = mlx5_create_flow_group(ft->t, in); 1497 + if (IS_ERR(ft->g[ft->num_groups])) 1498 + goto err_destroy_groups; 1499 + ft->num_groups++; 1500 + 1501 + memset(in, 0, inlen); 1502 + MLX5_SET_CFG(in, start_flow_index, ix); 1503 + ix += MLX5E_VLAN_GROUP_TRAP_SIZE; 1644 1504 MLX5_SET_CFG(in, end_flow_index, ix - 1); 1645 1505 ft->g[ft->num_groups] = mlx5_create_flow_group(ft->t, in); 1646 1506 if (IS_ERR(ft->g[ft->num_groups]))
+43 -9
drivers/net/ethernet/mellanox/mlx5/core/en_main.c
··· 66 66 #include "lib/mlx5.h" 67 67 #include "en/ptp.h" 68 68 #include "qos.h" 69 + #include "en/trap.h" 69 70 70 71 bool mlx5e_check_fragmented_striding_rq_cap(struct mlx5_core_dev *mdev) 71 72 { ··· 213 212 mlx5_notifier_unregister(priv->mdev, &priv->events_nb); 214 213 } 215 214 215 + static int blocking_event(struct notifier_block *nb, unsigned long event, void *data) 216 + { 217 + struct mlx5e_priv *priv = container_of(nb, struct mlx5e_priv, blocking_events_nb); 218 + int err; 219 + 220 + switch (event) { 221 + case MLX5_DRIVER_EVENT_TYPE_TRAP: 222 + err = mlx5e_handle_trap_event(priv, data); 223 + break; 224 + default: 225 + netdev_warn(priv->netdev, "Sync event: Unknouwn event %ld\n", event); 226 + err = -EINVAL; 227 + } 228 + return err; 229 + } 230 + 231 + static void mlx5e_enable_blocking_events(struct mlx5e_priv *priv) 232 + { 233 + priv->blocking_events_nb.notifier_call = blocking_event; 234 + mlx5_blocking_notifier_register(priv->mdev, &priv->blocking_events_nb); 235 + } 236 + 237 + static void mlx5e_disable_blocking_events(struct mlx5e_priv *priv) 238 + { 239 + mlx5_blocking_notifier_unregister(priv->mdev, &priv->blocking_events_nb); 240 + } 241 + 216 242 static inline void mlx5e_build_umr_wqe(struct mlx5e_rq *rq, 217 243 struct mlx5e_icosq *sq, 218 244 struct mlx5e_umr_wqe *wqe) ··· 371 343 prev->last_in_page = true; 372 344 } 373 345 374 - static int mlx5e_init_di_list(struct mlx5e_rq *rq, 375 - int wq_sz, int cpu) 346 + int mlx5e_init_di_list(struct mlx5e_rq *rq, int wq_sz, int node) 376 347 { 377 348 int len = wq_sz << rq->wqe.info.log_num_frags; 378 349 379 - rq->wqe.di = kvzalloc_node(array_size(len, sizeof(*rq->wqe.di)), 380 - GFP_KERNEL, cpu_to_node(cpu)); 350 + rq->wqe.di = kvzalloc_node(array_size(len, sizeof(*rq->wqe.di)), GFP_KERNEL, node); 381 351 if (!rq->wqe.di) 382 352 return -ENOMEM; 383 353 ··· 384 358 return 0; 385 359 } 386 360 387 - static void mlx5e_free_di_list(struct mlx5e_rq *rq) 361 + void mlx5e_free_di_list(struct mlx5e_rq *rq) 388 362 { 389 363 kvfree(rq->wqe.di); 390 364 } ··· 526 500 goto err_rq_wq_destroy; 527 501 } 528 502 529 - err = mlx5e_init_di_list(rq, wq_sz, c->cpu); 503 + err = mlx5e_init_di_list(rq, wq_sz, cpu_to_node(c->cpu)); 530 504 if (err) 531 505 goto err_rq_frags; 532 506 ··· 677 651 mlx5_wq_destroy(&rq->wq_ctrl); 678 652 } 679 653 680 - static int mlx5e_create_rq(struct mlx5e_rq *rq, 681 - struct mlx5e_rq_param *param) 654 + int mlx5e_create_rq(struct mlx5e_rq *rq, struct mlx5e_rq_param *param) 682 655 { 683 656 struct mlx5_core_dev *mdev = rq->mdev; 684 657 ··· 800 775 return err; 801 776 } 802 777 803 - static void mlx5e_destroy_rq(struct mlx5e_rq *rq) 778 + void mlx5e_destroy_rq(struct mlx5e_rq *rq) 804 779 { 805 780 mlx5_core_destroy_rq(rq->mdev, rq->rqn); 806 781 } ··· 3247 3222 3248 3223 priv->profile->update_rx(priv); 3249 3224 mlx5e_activate_priv_channels(priv); 3225 + mlx5e_apply_traps(priv, true); 3250 3226 if (priv->profile->update_carrier) 3251 3227 priv->profile->update_carrier(priv); 3252 3228 ··· 3283 3257 if (!test_bit(MLX5E_STATE_OPENED, &priv->state)) 3284 3258 return 0; 3285 3259 3260 + mlx5e_apply_traps(priv, false); 3286 3261 clear_bit(MLX5E_STATE_OPENED, &priv->state); 3287 3262 3288 3263 netif_carrier_off(priv->netdev); ··· 5371 5344 mlx5_lag_add(mdev, netdev); 5372 5345 5373 5346 mlx5e_enable_async_events(priv); 5347 + mlx5e_enable_blocking_events(priv); 5374 5348 if (mlx5e_monitor_counter_supported(priv)) 5375 5349 mlx5e_monitor_counter_init(priv); 5376 5350 ··· 5409 5381 if (mlx5e_monitor_counter_supported(priv)) 5410 5382 mlx5e_monitor_counter_cleanup(priv); 5411 5383 5384 + mlx5e_disable_blocking_events(priv); 5385 + if (priv->en_trap) { 5386 + mlx5e_deactivate_trap(priv); 5387 + mlx5e_close_trap(priv->en_trap); 5388 + priv->en_trap = NULL; 5389 + } 5412 5390 mlx5e_disable_async_events(priv); 5413 5391 mlx5_lag_remove(mdev); 5414 5392 mlx5_vxlan_reset_to_default(mdev->vxlan);
+46
drivers/net/ethernet/mellanox/mlx5/core/en_rx.c
··· 52 52 #include "en/xsk/rx.h" 53 53 #include "en/health.h" 54 54 #include "en/params.h" 55 + #include "devlink.h" 55 56 56 57 static struct sk_buff * 57 58 mlx5e_skb_from_cqe_mpwrq_linear(struct mlx5e_rq *rq, struct mlx5e_mpw_info *wi, ··· 1815 1814 } 1816 1815 1817 1816 return 0; 1817 + } 1818 + 1819 + static void mlx5e_trap_handle_rx_cqe(struct mlx5e_rq *rq, struct mlx5_cqe64 *cqe) 1820 + { 1821 + struct mlx5e_priv *priv = netdev_priv(rq->netdev); 1822 + struct mlx5_wq_cyc *wq = &rq->wqe.wq; 1823 + struct mlx5e_wqe_frag_info *wi; 1824 + struct sk_buff *skb; 1825 + u32 cqe_bcnt; 1826 + u16 trap_id; 1827 + u16 ci; 1828 + 1829 + trap_id = get_cqe_flow_tag(cqe); 1830 + ci = mlx5_wq_cyc_ctr2ix(wq, be16_to_cpu(cqe->wqe_counter)); 1831 + wi = get_frag(rq, ci); 1832 + cqe_bcnt = be32_to_cpu(cqe->byte_cnt); 1833 + 1834 + if (unlikely(MLX5E_RX_ERR_CQE(cqe))) { 1835 + rq->stats->wqe_err++; 1836 + goto free_wqe; 1837 + } 1838 + 1839 + skb = mlx5e_skb_from_cqe_nonlinear(rq, cqe, wi, cqe_bcnt); 1840 + if (!skb) 1841 + goto free_wqe; 1842 + 1843 + mlx5e_complete_rx_cqe(rq, cqe, cqe_bcnt, skb); 1844 + skb_push(skb, ETH_HLEN); 1845 + 1846 + mlx5_devlink_trap_report(rq->mdev, trap_id, skb, &priv->dl_port); 1847 + dev_kfree_skb_any(skb); 1848 + 1849 + free_wqe: 1850 + mlx5e_free_rx_wqe(rq, wi, false); 1851 + mlx5_wq_cyc_pop(wq); 1852 + } 1853 + 1854 + void mlx5e_rq_set_trap_handlers(struct mlx5e_rq *rq, struct mlx5e_params *params) 1855 + { 1856 + rq->wqe.skb_from_cqe = mlx5e_rx_is_linear_skb(params, NULL) ? 1857 + mlx5e_skb_from_cqe_linear : 1858 + mlx5e_skb_from_cqe_nonlinear; 1859 + rq->post_wqes = mlx5e_post_rx_wqes; 1860 + rq->dealloc_wqe = mlx5e_dealloc_rx_wqe; 1861 + rq->handle_rx_cqe = mlx5e_trap_handle_rx_cqe; 1818 1862 }
+39 -8
drivers/net/ethernet/mellanox/mlx5/core/events.c
··· 23 23 static int port_module(struct notifier_block *, unsigned long, void *); 24 24 static int pcie_core(struct notifier_block *, unsigned long, void *); 25 25 26 - /* handler which forwards the event to events->nh, driver notifiers */ 26 + /* handler which forwards the event to events->fw_nh, driver notifiers */ 27 27 static int forward_event(struct notifier_block *, unsigned long, void *); 28 28 29 29 static struct mlx5_nb events_nbs_ref[] = { ··· 55 55 struct mlx5_core_dev *dev; 56 56 struct workqueue_struct *wq; 57 57 struct mlx5_event_nb notifiers[ARRAY_SIZE(events_nbs_ref)]; 58 - /* driver notifier chain */ 59 - struct atomic_notifier_head nh; 58 + /* driver notifier chain for fw events */ 59 + struct atomic_notifier_head fw_nh; 60 60 /* port module events stats */ 61 61 struct mlx5_pme_stats pme_stats; 62 62 /*pcie_core*/ 63 63 struct work_struct pcie_core_work; 64 + /* driver notifier chain for sw events */ 65 + struct blocking_notifier_head sw_nh; 64 66 }; 65 67 66 68 static const char *eqe_type_str(u8 type) ··· 333 331 334 332 mlx5_core_dbg(events->dev, "Async eqe type %s, subtype (%d) forward to interfaces\n", 335 333 eqe_type_str(eqe->type), eqe->sub_type); 336 - atomic_notifier_call_chain(&events->nh, event, data); 334 + atomic_notifier_call_chain(&events->fw_nh, event, data); 337 335 return NOTIFY_OK; 338 336 } 339 337 ··· 344 342 if (!events) 345 343 return -ENOMEM; 346 344 347 - ATOMIC_INIT_NOTIFIER_HEAD(&events->nh); 345 + ATOMIC_INIT_NOTIFIER_HEAD(&events->fw_nh); 348 346 events->dev = dev; 349 347 dev->priv.events = events; 350 348 events->wq = create_singlethread_workqueue("mlx5_events"); ··· 353 351 return -ENOMEM; 354 352 } 355 353 INIT_WORK(&events->pcie_core_work, mlx5_pcie_event); 354 + BLOCKING_INIT_NOTIFIER_HEAD(&events->sw_nh); 356 355 357 356 return 0; 358 357 } ··· 386 383 flush_workqueue(events->wq); 387 384 } 388 385 386 + /* This API is used only for processing and forwarding firmware 387 + * events to mlx5 consumer. 388 + */ 389 389 int mlx5_notifier_register(struct mlx5_core_dev *dev, struct notifier_block *nb) 390 390 { 391 391 struct mlx5_events *events = dev->priv.events; 392 392 393 - return atomic_notifier_chain_register(&events->nh, nb); 393 + return atomic_notifier_chain_register(&events->fw_nh, nb); 394 394 } 395 395 EXPORT_SYMBOL(mlx5_notifier_register); 396 396 ··· 401 395 { 402 396 struct mlx5_events *events = dev->priv.events; 403 397 404 - return atomic_notifier_chain_unregister(&events->nh, nb); 398 + return atomic_notifier_chain_unregister(&events->fw_nh, nb); 405 399 } 406 400 EXPORT_SYMBOL(mlx5_notifier_unregister); 407 401 408 402 int mlx5_notifier_call_chain(struct mlx5_events *events, unsigned int event, void *data) 409 403 { 410 - return atomic_notifier_call_chain(&events->nh, event, data); 404 + return atomic_notifier_call_chain(&events->fw_nh, event, data); 405 + } 406 + 407 + /* This API is used only for processing and forwarding driver-specific 408 + * events to mlx5 consumers. 409 + */ 410 + int mlx5_blocking_notifier_register(struct mlx5_core_dev *dev, struct notifier_block *nb) 411 + { 412 + struct mlx5_events *events = dev->priv.events; 413 + 414 + return blocking_notifier_chain_register(&events->sw_nh, nb); 415 + } 416 + 417 + int mlx5_blocking_notifier_unregister(struct mlx5_core_dev *dev, struct notifier_block *nb) 418 + { 419 + struct mlx5_events *events = dev->priv.events; 420 + 421 + return blocking_notifier_chain_unregister(&events->sw_nh, nb); 422 + } 423 + 424 + int mlx5_blocking_notifier_call_chain(struct mlx5_core_dev *dev, unsigned int event, 425 + void *data) 426 + { 427 + struct mlx5_events *events = dev->priv.events; 428 + 429 + return blocking_notifier_call_chain(&events->sw_nh, event, data); 411 430 }
+2 -2
drivers/net/ethernet/mellanox/mlx5/core/fs_core.c
··· 105 105 #define ETHTOOL_PRIO_NUM_LEVELS 1 106 106 #define ETHTOOL_NUM_PRIOS 11 107 107 #define ETHTOOL_MIN_LEVEL (KERNEL_MIN_LEVEL + ETHTOOL_NUM_PRIOS) 108 - /* Vlan, mac, ttc, inner ttc, {aRFS/accel and esp/esp_err} */ 109 - #define KERNEL_NIC_PRIO_NUM_LEVELS 6 108 + /* Promiscuous, Vlan, mac, ttc, inner ttc, {aRFS/accel and esp/esp_err} */ 109 + #define KERNEL_NIC_PRIO_NUM_LEVELS 7 110 110 #define KERNEL_NIC_NUM_PRIOS 1 111 111 /* One more level for tc */ 112 112 #define KERNEL_MIN_LEVEL (KERNEL_NIC_PRIO_NUM_LEVELS + 1)
+2
drivers/net/ethernet/mellanox/mlx5/core/main.c
··· 1305 1305 1306 1306 priv->dbg_root = debugfs_create_dir(dev_name(dev->device), 1307 1307 mlx5_debugfs_root); 1308 + INIT_LIST_HEAD(&priv->traps); 1309 + 1308 1310 err = mlx5_health_init(dev); 1309 1311 if (err) 1310 1312 goto err_health_init;
+9
include/linux/mlx5/device.h
··· 359 359 MLX5_EVENT_TYPE_MAX = 0x100, 360 360 }; 361 361 362 + enum mlx5_driver_event { 363 + MLX5_DRIVER_EVENT_TYPE_TRAP = 0, 364 + }; 365 + 362 366 enum { 363 367 MLX5_TRACER_SUBTYPE_OWNERSHIP_CHANGE = 0x0, 364 368 MLX5_TRACER_SUBTYPE_TRACES_AVAILABLE = 0x1, ··· 901 897 lo = be32_to_cpu(cqe->timestamp_l); 902 898 903 899 return (u64)lo | ((u64)hi << 32); 900 + } 901 + 902 + static inline u16 get_cqe_flow_tag(struct mlx5_cqe64 *cqe) 903 + { 904 + return be32_to_cpu(cqe->sop_drop_qpn) & 0xFFF; 904 905 } 905 906 906 907 #define MLX5_MPWQE_LOG_NUM_STRIDES_BASE (9)
+16
include/linux/mlx5/driver.h
··· 564 564 int host_pf_pages; 565 565 566 566 struct mlx5_core_health health; 567 + struct list_head traps; 567 568 568 569 /* start: qp staff */ 569 570 struct dentry *qp_debugfs; ··· 1073 1072 MAX_MR_CACHE_ENTRIES 1074 1073 }; 1075 1074 1075 + /* Async-atomic event notifier used by mlx5 core to forward FW 1076 + * evetns recived from event queue to mlx5 consumers. 1077 + * Optimise event queue dipatching. 1078 + */ 1076 1079 int mlx5_notifier_register(struct mlx5_core_dev *dev, struct notifier_block *nb); 1077 1080 int mlx5_notifier_unregister(struct mlx5_core_dev *dev, struct notifier_block *nb); 1081 + 1082 + /* Async-atomic event notifier used for forwarding 1083 + * evetns from the event queue into the to mlx5 events dispatcher, 1084 + * eswitch, clock and others. 1085 + */ 1078 1086 int mlx5_eq_notifier_register(struct mlx5_core_dev *dev, struct mlx5_nb *nb); 1079 1087 int mlx5_eq_notifier_unregister(struct mlx5_core_dev *dev, struct mlx5_nb *nb); 1088 + 1089 + /* Blocking event notifier used to forward SW events, used for slow path */ 1090 + int mlx5_blocking_notifier_register(struct mlx5_core_dev *dev, struct notifier_block *nb); 1091 + int mlx5_blocking_notifier_unregister(struct mlx5_core_dev *dev, struct notifier_block *nb); 1092 + int mlx5_blocking_notifier_call_chain(struct mlx5_core_dev *dev, unsigned int event, 1093 + void *data); 1080 1094 1081 1095 int mlx5_core_query_vendor_id(struct mlx5_core_dev *mdev, u32 *vendor_id); 1082 1096
+3
include/net/devlink.h
··· 838 838 DEVLINK_TRAP_GENERIC_ID_GTP_PARSING, 839 839 DEVLINK_TRAP_GENERIC_ID_ESP_PARSING, 840 840 DEVLINK_TRAP_GENERIC_ID_BLACKHOLE_NEXTHOP, 841 + DEVLINK_TRAP_GENERIC_ID_DMAC_FILTER, 841 842 842 843 /* Add new generic trap IDs above */ 843 844 __DEVLINK_TRAP_GENERIC_ID_MAX, ··· 1064 1063 "esp_parsing" 1065 1064 #define DEVLINK_TRAP_GENERIC_NAME_BLACKHOLE_NEXTHOP \ 1066 1065 "blackhole_nexthop" 1066 + #define DEVLINK_TRAP_GENERIC_NAME_DMAC_FILTER \ 1067 + "dest_mac_filter" 1067 1068 1068 1069 #define DEVLINK_TRAP_GROUP_GENERIC_NAME_L2_DROPS \ 1069 1070 "l2_drops"
+1
net/core/devlink.c
··· 9512 9512 DEVLINK_TRAP(GTP_PARSING, DROP), 9513 9513 DEVLINK_TRAP(ESP_PARSING, DROP), 9514 9514 DEVLINK_TRAP(BLACKHOLE_NEXTHOP, DROP), 9515 + DEVLINK_TRAP(DMAC_FILTER, DROP), 9515 9516 }; 9516 9517 9517 9518 #define DEVLINK_TRAP_GROUP(_id) \