1b55b3538SParav Pandit // SPDX-License-Identifier: GPL-2.0 OR Linux-OpenIB 2b55b3538SParav Pandit /* Copyright (c) 2021 Mellanox Technologies Ltd */ 3b55b3538SParav Pandit 4b55b3538SParav Pandit #include <linux/etherdevice.h> 5b55b3538SParav Pandit #include <linux/mlx5/driver.h> 6b55b3538SParav Pandit #include <linux/mlx5/mlx5_ifc.h> 7b55b3538SParav Pandit #include <linux/mlx5/vport.h> 8b55b3538SParav Pandit #include <linux/mlx5/fs.h> 9b55b3538SParav Pandit #include "esw/acl/lgcy.h" 10b55b3538SParav Pandit #include "esw/legacy.h" 11b55b3538SParav Pandit #include "mlx5_core.h" 12b55b3538SParav Pandit #include "eswitch.h" 13b55b3538SParav Pandit #include "fs_core.h" 14*0c9d8765SPaul Blakey #include "fs_ft_pool.h" 152d116e3eSDmytro Linkin #include "esw/qos.h" 16b55b3538SParav Pandit 17b55b3538SParav Pandit enum { 18b55b3538SParav Pandit LEGACY_VEPA_PRIO = 0, 19b55b3538SParav Pandit LEGACY_FDB_PRIO, 20b55b3538SParav Pandit }; 21b55b3538SParav Pandit 22b55b3538SParav Pandit static int esw_create_legacy_vepa_table(struct mlx5_eswitch *esw) 23b55b3538SParav Pandit { 24b55b3538SParav Pandit struct mlx5_flow_table_attr ft_attr = {}; 25b55b3538SParav Pandit struct mlx5_core_dev *dev = esw->dev; 26b55b3538SParav Pandit struct mlx5_flow_namespace *root_ns; 27b55b3538SParav Pandit struct mlx5_flow_table *fdb; 28b55b3538SParav Pandit int err; 29b55b3538SParav Pandit 30b55b3538SParav Pandit root_ns = mlx5_get_fdb_sub_ns(dev, 0); 31b55b3538SParav Pandit if (!root_ns) { 32b55b3538SParav Pandit esw_warn(dev, "Failed to get FDB flow namespace\n"); 33b55b3538SParav Pandit return -EOPNOTSUPP; 34b55b3538SParav Pandit } 35b55b3538SParav Pandit 36b55b3538SParav Pandit /* num FTE 2, num FG 2 */ 37b55b3538SParav Pandit ft_attr.prio = LEGACY_VEPA_PRIO; 38b55b3538SParav Pandit ft_attr.max_fte = 2; 39b55b3538SParav Pandit ft_attr.autogroup.max_num_groups = 2; 40b55b3538SParav Pandit fdb = mlx5_create_auto_grouped_flow_table(root_ns, &ft_attr); 41b55b3538SParav Pandit if (IS_ERR(fdb)) { 42b55b3538SParav Pandit err = PTR_ERR(fdb); 43b55b3538SParav Pandit esw_warn(dev, "Failed to create VEPA FDB err %d\n", err); 44b55b3538SParav Pandit return err; 45b55b3538SParav Pandit } 46b55b3538SParav Pandit esw->fdb_table.legacy.vepa_fdb = fdb; 47b55b3538SParav Pandit 48b55b3538SParav Pandit return 0; 49b55b3538SParav Pandit } 50b55b3538SParav Pandit 51b55b3538SParav Pandit static void esw_destroy_legacy_fdb_table(struct mlx5_eswitch *esw) 52b55b3538SParav Pandit { 53b55b3538SParav Pandit esw_debug(esw->dev, "Destroy FDB Table\n"); 54b55b3538SParav Pandit if (!esw->fdb_table.legacy.fdb) 55b55b3538SParav Pandit return; 56b55b3538SParav Pandit 57b55b3538SParav Pandit if (esw->fdb_table.legacy.promisc_grp) 58b55b3538SParav Pandit mlx5_destroy_flow_group(esw->fdb_table.legacy.promisc_grp); 59b55b3538SParav Pandit if (esw->fdb_table.legacy.allmulti_grp) 60b55b3538SParav Pandit mlx5_destroy_flow_group(esw->fdb_table.legacy.allmulti_grp); 61b55b3538SParav Pandit if (esw->fdb_table.legacy.addr_grp) 62b55b3538SParav Pandit mlx5_destroy_flow_group(esw->fdb_table.legacy.addr_grp); 63b55b3538SParav Pandit mlx5_destroy_flow_table(esw->fdb_table.legacy.fdb); 64b55b3538SParav Pandit 65b55b3538SParav Pandit esw->fdb_table.legacy.fdb = NULL; 66b55b3538SParav Pandit esw->fdb_table.legacy.addr_grp = NULL; 67b55b3538SParav Pandit esw->fdb_table.legacy.allmulti_grp = NULL; 68b55b3538SParav Pandit esw->fdb_table.legacy.promisc_grp = NULL; 69b55b3538SParav Pandit atomic64_set(&esw->user_count, 0); 70b55b3538SParav Pandit } 71b55b3538SParav Pandit 72b55b3538SParav Pandit static int esw_create_legacy_fdb_table(struct mlx5_eswitch *esw) 73b55b3538SParav Pandit { 74b55b3538SParav Pandit int inlen = MLX5_ST_SZ_BYTES(create_flow_group_in); 75b55b3538SParav Pandit struct mlx5_flow_table_attr ft_attr = {}; 76b55b3538SParav Pandit struct mlx5_core_dev *dev = esw->dev; 77b55b3538SParav Pandit struct mlx5_flow_namespace *root_ns; 78b55b3538SParav Pandit struct mlx5_flow_table *fdb; 79b55b3538SParav Pandit struct mlx5_flow_group *g; 80b55b3538SParav Pandit void *match_criteria; 81b55b3538SParav Pandit int table_size; 82b55b3538SParav Pandit u32 *flow_group_in; 83b55b3538SParav Pandit u8 *dmac; 84b55b3538SParav Pandit int err = 0; 85b55b3538SParav Pandit 86b55b3538SParav Pandit esw_debug(dev, "Create FDB log_max_size(%d)\n", 87b55b3538SParav Pandit MLX5_CAP_ESW_FLOWTABLE_FDB(dev, log_max_ft_size)); 88b55b3538SParav Pandit 89b55b3538SParav Pandit root_ns = mlx5_get_fdb_sub_ns(dev, 0); 90b55b3538SParav Pandit if (!root_ns) { 91b55b3538SParav Pandit esw_warn(dev, "Failed to get FDB flow namespace\n"); 92b55b3538SParav Pandit return -EOPNOTSUPP; 93b55b3538SParav Pandit } 94b55b3538SParav Pandit 95b55b3538SParav Pandit flow_group_in = kvzalloc(inlen, GFP_KERNEL); 96b55b3538SParav Pandit if (!flow_group_in) 97b55b3538SParav Pandit return -ENOMEM; 98b55b3538SParav Pandit 99*0c9d8765SPaul Blakey ft_attr.max_fte = POOL_NEXT_SIZE; 100b55b3538SParav Pandit ft_attr.prio = LEGACY_FDB_PRIO; 101b55b3538SParav Pandit fdb = mlx5_create_flow_table(root_ns, &ft_attr); 102b55b3538SParav Pandit if (IS_ERR(fdb)) { 103b55b3538SParav Pandit err = PTR_ERR(fdb); 104b55b3538SParav Pandit esw_warn(dev, "Failed to create FDB Table err %d\n", err); 105b55b3538SParav Pandit goto out; 106b55b3538SParav Pandit } 107b55b3538SParav Pandit esw->fdb_table.legacy.fdb = fdb; 108*0c9d8765SPaul Blakey table_size = fdb->max_fte; 109b55b3538SParav Pandit 110b55b3538SParav Pandit /* Addresses group : Full match unicast/multicast addresses */ 111b55b3538SParav Pandit MLX5_SET(create_flow_group_in, flow_group_in, match_criteria_enable, 112b55b3538SParav Pandit MLX5_MATCH_OUTER_HEADERS); 113b55b3538SParav Pandit match_criteria = MLX5_ADDR_OF(create_flow_group_in, flow_group_in, match_criteria); 114b55b3538SParav Pandit dmac = MLX5_ADDR_OF(fte_match_param, match_criteria, outer_headers.dmac_47_16); 115b55b3538SParav Pandit MLX5_SET(create_flow_group_in, flow_group_in, start_flow_index, 0); 116b55b3538SParav Pandit /* Preserve 2 entries for allmulti and promisc rules*/ 117b55b3538SParav Pandit MLX5_SET(create_flow_group_in, flow_group_in, end_flow_index, table_size - 3); 118b55b3538SParav Pandit eth_broadcast_addr(dmac); 119b55b3538SParav Pandit g = mlx5_create_flow_group(fdb, flow_group_in); 120b55b3538SParav Pandit if (IS_ERR(g)) { 121b55b3538SParav Pandit err = PTR_ERR(g); 122b55b3538SParav Pandit esw_warn(dev, "Failed to create flow group err(%d)\n", err); 123b55b3538SParav Pandit goto out; 124b55b3538SParav Pandit } 125b55b3538SParav Pandit esw->fdb_table.legacy.addr_grp = g; 126b55b3538SParav Pandit 127b55b3538SParav Pandit /* Allmulti group : One rule that forwards any mcast traffic */ 128b55b3538SParav Pandit MLX5_SET(create_flow_group_in, flow_group_in, match_criteria_enable, 129b55b3538SParav Pandit MLX5_MATCH_OUTER_HEADERS); 130b55b3538SParav Pandit MLX5_SET(create_flow_group_in, flow_group_in, start_flow_index, table_size - 2); 131b55b3538SParav Pandit MLX5_SET(create_flow_group_in, flow_group_in, end_flow_index, table_size - 2); 132b55b3538SParav Pandit eth_zero_addr(dmac); 133b55b3538SParav Pandit dmac[0] = 0x01; 134b55b3538SParav Pandit g = mlx5_create_flow_group(fdb, flow_group_in); 135b55b3538SParav Pandit if (IS_ERR(g)) { 136b55b3538SParav Pandit err = PTR_ERR(g); 137b55b3538SParav Pandit esw_warn(dev, "Failed to create allmulti flow group err(%d)\n", err); 138b55b3538SParav Pandit goto out; 139b55b3538SParav Pandit } 140b55b3538SParav Pandit esw->fdb_table.legacy.allmulti_grp = g; 141b55b3538SParav Pandit 142b55b3538SParav Pandit /* Promiscuous group : 143b55b3538SParav Pandit * One rule that forward all unmatched traffic from previous groups 144b55b3538SParav Pandit */ 145b55b3538SParav Pandit eth_zero_addr(dmac); 146b55b3538SParav Pandit MLX5_SET(create_flow_group_in, flow_group_in, match_criteria_enable, 147b55b3538SParav Pandit MLX5_MATCH_MISC_PARAMETERS); 148b55b3538SParav Pandit MLX5_SET_TO_ONES(fte_match_param, match_criteria, misc_parameters.source_port); 149b55b3538SParav Pandit MLX5_SET(create_flow_group_in, flow_group_in, start_flow_index, table_size - 1); 150b55b3538SParav Pandit MLX5_SET(create_flow_group_in, flow_group_in, end_flow_index, table_size - 1); 151b55b3538SParav Pandit g = mlx5_create_flow_group(fdb, flow_group_in); 152b55b3538SParav Pandit if (IS_ERR(g)) { 153b55b3538SParav Pandit err = PTR_ERR(g); 154b55b3538SParav Pandit esw_warn(dev, "Failed to create promisc flow group err(%d)\n", err); 155b55b3538SParav Pandit goto out; 156b55b3538SParav Pandit } 157b55b3538SParav Pandit esw->fdb_table.legacy.promisc_grp = g; 158b55b3538SParav Pandit 159b55b3538SParav Pandit out: 160b55b3538SParav Pandit if (err) 161b55b3538SParav Pandit esw_destroy_legacy_fdb_table(esw); 162b55b3538SParav Pandit 163b55b3538SParav Pandit kvfree(flow_group_in); 164b55b3538SParav Pandit return err; 165b55b3538SParav Pandit } 166b55b3538SParav Pandit 167b55b3538SParav Pandit static void esw_destroy_legacy_vepa_table(struct mlx5_eswitch *esw) 168b55b3538SParav Pandit { 169b55b3538SParav Pandit esw_debug(esw->dev, "Destroy VEPA Table\n"); 170b55b3538SParav Pandit if (!esw->fdb_table.legacy.vepa_fdb) 171b55b3538SParav Pandit return; 172b55b3538SParav Pandit 173b55b3538SParav Pandit mlx5_destroy_flow_table(esw->fdb_table.legacy.vepa_fdb); 174b55b3538SParav Pandit esw->fdb_table.legacy.vepa_fdb = NULL; 175b55b3538SParav Pandit } 176b55b3538SParav Pandit 177b55b3538SParav Pandit static int esw_create_legacy_table(struct mlx5_eswitch *esw) 178b55b3538SParav Pandit { 179b55b3538SParav Pandit int err; 180b55b3538SParav Pandit 181b55b3538SParav Pandit memset(&esw->fdb_table.legacy, 0, sizeof(struct legacy_fdb)); 182b55b3538SParav Pandit atomic64_set(&esw->user_count, 0); 183b55b3538SParav Pandit 184b55b3538SParav Pandit err = esw_create_legacy_vepa_table(esw); 185b55b3538SParav Pandit if (err) 186b55b3538SParav Pandit return err; 187b55b3538SParav Pandit 188b55b3538SParav Pandit err = esw_create_legacy_fdb_table(esw); 189b55b3538SParav Pandit if (err) 190b55b3538SParav Pandit esw_destroy_legacy_vepa_table(esw); 191b55b3538SParav Pandit 192b55b3538SParav Pandit return err; 193b55b3538SParav Pandit } 194b55b3538SParav Pandit 195b55b3538SParav Pandit static void esw_cleanup_vepa_rules(struct mlx5_eswitch *esw) 196b55b3538SParav Pandit { 197b55b3538SParav Pandit if (esw->fdb_table.legacy.vepa_uplink_rule) 198b55b3538SParav Pandit mlx5_del_flow_rules(esw->fdb_table.legacy.vepa_uplink_rule); 199b55b3538SParav Pandit 200b55b3538SParav Pandit if (esw->fdb_table.legacy.vepa_star_rule) 201b55b3538SParav Pandit mlx5_del_flow_rules(esw->fdb_table.legacy.vepa_star_rule); 202b55b3538SParav Pandit 203b55b3538SParav Pandit esw->fdb_table.legacy.vepa_uplink_rule = NULL; 204b55b3538SParav Pandit esw->fdb_table.legacy.vepa_star_rule = NULL; 205b55b3538SParav Pandit } 206b55b3538SParav Pandit 207b55b3538SParav Pandit static void esw_destroy_legacy_table(struct mlx5_eswitch *esw) 208b55b3538SParav Pandit { 209b55b3538SParav Pandit esw_cleanup_vepa_rules(esw); 210b55b3538SParav Pandit esw_destroy_legacy_fdb_table(esw); 211b55b3538SParav Pandit esw_destroy_legacy_vepa_table(esw); 212b55b3538SParav Pandit } 213b55b3538SParav Pandit 214b55b3538SParav Pandit #define MLX5_LEGACY_SRIOV_VPORT_EVENTS (MLX5_VPORT_UC_ADDR_CHANGE | \ 215b55b3538SParav Pandit MLX5_VPORT_MC_ADDR_CHANGE | \ 216b55b3538SParav Pandit MLX5_VPORT_PROMISC_CHANGE) 217b55b3538SParav Pandit 218b55b3538SParav Pandit int esw_legacy_enable(struct mlx5_eswitch *esw) 219b55b3538SParav Pandit { 220b55b3538SParav Pandit struct mlx5_vport *vport; 22147dd7e60SParav Pandit unsigned long i; 22247dd7e60SParav Pandit int ret; 223b55b3538SParav Pandit 224b55b3538SParav Pandit ret = esw_create_legacy_table(esw); 225b55b3538SParav Pandit if (ret) 226b55b3538SParav Pandit return ret; 227b55b3538SParav Pandit 228b55b3538SParav Pandit mlx5_esw_for_each_vf_vport(esw, i, vport, esw->esw_funcs.num_vfs) 229b55b3538SParav Pandit vport->info.link_state = MLX5_VPORT_ADMIN_STATE_AUTO; 230b55b3538SParav Pandit 231b55b3538SParav Pandit ret = mlx5_eswitch_enable_pf_vf_vports(esw, MLX5_LEGACY_SRIOV_VPORT_EVENTS); 232b55b3538SParav Pandit if (ret) 233b55b3538SParav Pandit esw_destroy_legacy_table(esw); 234b55b3538SParav Pandit return ret; 235b55b3538SParav Pandit } 236b55b3538SParav Pandit 237b55b3538SParav Pandit void esw_legacy_disable(struct mlx5_eswitch *esw) 238b55b3538SParav Pandit { 239b55b3538SParav Pandit struct esw_mc_addr *mc_promisc; 240b55b3538SParav Pandit 241b55b3538SParav Pandit mlx5_eswitch_disable_pf_vf_vports(esw); 242b55b3538SParav Pandit 243b55b3538SParav Pandit mc_promisc = &esw->mc_promisc; 244b55b3538SParav Pandit if (mc_promisc->uplink_rule) 245b55b3538SParav Pandit mlx5_del_flow_rules(mc_promisc->uplink_rule); 246b55b3538SParav Pandit 247b55b3538SParav Pandit esw_destroy_legacy_table(esw); 248b55b3538SParav Pandit } 249b55b3538SParav Pandit 250b55b3538SParav Pandit static int _mlx5_eswitch_set_vepa_locked(struct mlx5_eswitch *esw, 251b55b3538SParav Pandit u8 setting) 252b55b3538SParav Pandit { 253b55b3538SParav Pandit struct mlx5_flow_destination dest = {}; 254b55b3538SParav Pandit struct mlx5_flow_act flow_act = {}; 255b55b3538SParav Pandit struct mlx5_flow_handle *flow_rule; 256b55b3538SParav Pandit struct mlx5_flow_spec *spec; 257b55b3538SParav Pandit int err = 0; 258b55b3538SParav Pandit void *misc; 259b55b3538SParav Pandit 260b55b3538SParav Pandit if (!setting) { 261b55b3538SParav Pandit esw_cleanup_vepa_rules(esw); 262b55b3538SParav Pandit return 0; 263b55b3538SParav Pandit } 264b55b3538SParav Pandit 265b55b3538SParav Pandit if (esw->fdb_table.legacy.vepa_uplink_rule) 266b55b3538SParav Pandit return 0; 267b55b3538SParav Pandit 268b55b3538SParav Pandit spec = kvzalloc(sizeof(*spec), GFP_KERNEL); 269b55b3538SParav Pandit if (!spec) 270b55b3538SParav Pandit return -ENOMEM; 271b55b3538SParav Pandit 272b55b3538SParav Pandit /* Uplink rule forward uplink traffic to FDB */ 273b55b3538SParav Pandit misc = MLX5_ADDR_OF(fte_match_param, spec->match_value, misc_parameters); 274b55b3538SParav Pandit MLX5_SET(fte_match_set_misc, misc, source_port, MLX5_VPORT_UPLINK); 275b55b3538SParav Pandit 276b55b3538SParav Pandit misc = MLX5_ADDR_OF(fte_match_param, spec->match_criteria, misc_parameters); 277b55b3538SParav Pandit MLX5_SET_TO_ONES(fte_match_set_misc, misc, source_port); 278b55b3538SParav Pandit 279b55b3538SParav Pandit spec->match_criteria_enable = MLX5_MATCH_MISC_PARAMETERS; 280b55b3538SParav Pandit dest.type = MLX5_FLOW_DESTINATION_TYPE_FLOW_TABLE; 281b55b3538SParav Pandit dest.ft = esw->fdb_table.legacy.fdb; 282b55b3538SParav Pandit flow_act.action = MLX5_FLOW_CONTEXT_ACTION_FWD_DEST; 283b55b3538SParav Pandit flow_rule = mlx5_add_flow_rules(esw->fdb_table.legacy.vepa_fdb, spec, 284b55b3538SParav Pandit &flow_act, &dest, 1); 285b55b3538SParav Pandit if (IS_ERR(flow_rule)) { 286b55b3538SParav Pandit err = PTR_ERR(flow_rule); 287b55b3538SParav Pandit goto out; 288b55b3538SParav Pandit } else { 289b55b3538SParav Pandit esw->fdb_table.legacy.vepa_uplink_rule = flow_rule; 290b55b3538SParav Pandit } 291b55b3538SParav Pandit 292b55b3538SParav Pandit /* Star rule to forward all traffic to uplink vport */ 293b55b3538SParav Pandit memset(&dest, 0, sizeof(dest)); 294b55b3538SParav Pandit dest.type = MLX5_FLOW_DESTINATION_TYPE_VPORT; 295b55b3538SParav Pandit dest.vport.num = MLX5_VPORT_UPLINK; 296b55b3538SParav Pandit flow_act.action = MLX5_FLOW_CONTEXT_ACTION_FWD_DEST; 297b55b3538SParav Pandit flow_rule = mlx5_add_flow_rules(esw->fdb_table.legacy.vepa_fdb, NULL, 298b55b3538SParav Pandit &flow_act, &dest, 1); 299b55b3538SParav Pandit if (IS_ERR(flow_rule)) { 300b55b3538SParav Pandit err = PTR_ERR(flow_rule); 301b55b3538SParav Pandit goto out; 302b55b3538SParav Pandit } else { 303b55b3538SParav Pandit esw->fdb_table.legacy.vepa_star_rule = flow_rule; 304b55b3538SParav Pandit } 305b55b3538SParav Pandit 306b55b3538SParav Pandit out: 307b55b3538SParav Pandit kvfree(spec); 308b55b3538SParav Pandit if (err) 309b55b3538SParav Pandit esw_cleanup_vepa_rules(esw); 310b55b3538SParav Pandit return err; 311b55b3538SParav Pandit } 312b55b3538SParav Pandit 313b55b3538SParav Pandit int mlx5_eswitch_set_vepa(struct mlx5_eswitch *esw, u8 setting) 314b55b3538SParav Pandit { 315b55b3538SParav Pandit int err = 0; 316b55b3538SParav Pandit 317b55b3538SParav Pandit if (!esw) 318b55b3538SParav Pandit return -EOPNOTSUPP; 319b55b3538SParav Pandit 320b55b3538SParav Pandit if (!mlx5_esw_allowed(esw)) 321b55b3538SParav Pandit return -EPERM; 322b55b3538SParav Pandit 323b55b3538SParav Pandit mutex_lock(&esw->state_lock); 324b55b3538SParav Pandit if (esw->mode != MLX5_ESWITCH_LEGACY) { 325b55b3538SParav Pandit err = -EOPNOTSUPP; 326b55b3538SParav Pandit goto out; 327b55b3538SParav Pandit } 328b55b3538SParav Pandit 329b55b3538SParav Pandit err = _mlx5_eswitch_set_vepa_locked(esw, setting); 330b55b3538SParav Pandit 331b55b3538SParav Pandit out: 332b55b3538SParav Pandit mutex_unlock(&esw->state_lock); 333b55b3538SParav Pandit return err; 334b55b3538SParav Pandit } 335b55b3538SParav Pandit 336b55b3538SParav Pandit int mlx5_eswitch_get_vepa(struct mlx5_eswitch *esw, u8 *setting) 337b55b3538SParav Pandit { 338b55b3538SParav Pandit if (!esw) 339b55b3538SParav Pandit return -EOPNOTSUPP; 340b55b3538SParav Pandit 341b55b3538SParav Pandit if (!mlx5_esw_allowed(esw)) 342b55b3538SParav Pandit return -EPERM; 343b55b3538SParav Pandit 344b55b3538SParav Pandit if (esw->mode != MLX5_ESWITCH_LEGACY) 345b55b3538SParav Pandit return -EOPNOTSUPP; 346b55b3538SParav Pandit 347b55b3538SParav Pandit *setting = esw->fdb_table.legacy.vepa_uplink_rule ? 1 : 0; 348b55b3538SParav Pandit return 0; 349b55b3538SParav Pandit } 350b55b3538SParav Pandit 351b55b3538SParav Pandit int esw_legacy_vport_acl_setup(struct mlx5_eswitch *esw, struct mlx5_vport *vport) 352b55b3538SParav Pandit { 353b55b3538SParav Pandit int ret; 354b55b3538SParav Pandit 355b55b3538SParav Pandit /* Only non manager vports need ACL in legacy mode */ 356b55b3538SParav Pandit if (mlx5_esw_is_manager_vport(esw, vport->vport)) 357b55b3538SParav Pandit return 0; 358b55b3538SParav Pandit 359b55b3538SParav Pandit ret = esw_acl_ingress_lgcy_setup(esw, vport); 360b55b3538SParav Pandit if (ret) 361b55b3538SParav Pandit goto ingress_err; 362b55b3538SParav Pandit 363b55b3538SParav Pandit ret = esw_acl_egress_lgcy_setup(esw, vport); 364b55b3538SParav Pandit if (ret) 365b55b3538SParav Pandit goto egress_err; 366b55b3538SParav Pandit 367b55b3538SParav Pandit return 0; 368b55b3538SParav Pandit 369b55b3538SParav Pandit egress_err: 370b55b3538SParav Pandit esw_acl_ingress_lgcy_cleanup(esw, vport); 371b55b3538SParav Pandit ingress_err: 372b55b3538SParav Pandit return ret; 373b55b3538SParav Pandit } 374b55b3538SParav Pandit 375b55b3538SParav Pandit void esw_legacy_vport_acl_cleanup(struct mlx5_eswitch *esw, struct mlx5_vport *vport) 376b55b3538SParav Pandit { 377b55b3538SParav Pandit if (mlx5_esw_is_manager_vport(esw, vport->vport)) 378b55b3538SParav Pandit return; 379b55b3538SParav Pandit 380b55b3538SParav Pandit esw_acl_egress_lgcy_cleanup(esw, vport); 381b55b3538SParav Pandit esw_acl_ingress_lgcy_cleanup(esw, vport); 382b55b3538SParav Pandit } 383b55b3538SParav Pandit 384b55b3538SParav Pandit int mlx5_esw_query_vport_drop_stats(struct mlx5_core_dev *dev, 385b55b3538SParav Pandit struct mlx5_vport *vport, 386b55b3538SParav Pandit struct mlx5_vport_drop_stats *stats) 387b55b3538SParav Pandit { 388b55b3538SParav Pandit u64 rx_discard_vport_down, tx_discard_vport_down; 389b55b3538SParav Pandit struct mlx5_eswitch *esw = dev->priv.eswitch; 390b55b3538SParav Pandit u64 bytes = 0; 391b55b3538SParav Pandit int err = 0; 392b55b3538SParav Pandit 393b55b3538SParav Pandit if (esw->mode != MLX5_ESWITCH_LEGACY) 394b55b3538SParav Pandit return 0; 395b55b3538SParav Pandit 396b55b3538SParav Pandit mutex_lock(&esw->state_lock); 397b55b3538SParav Pandit if (!vport->enabled) 398b55b3538SParav Pandit goto unlock; 399b55b3538SParav Pandit 400b55b3538SParav Pandit if (!IS_ERR_OR_NULL(vport->egress.legacy.drop_counter)) 401b55b3538SParav Pandit mlx5_fc_query(dev, vport->egress.legacy.drop_counter, 402b55b3538SParav Pandit &stats->rx_dropped, &bytes); 403b55b3538SParav Pandit 404b55b3538SParav Pandit if (vport->ingress.legacy.drop_counter) 405b55b3538SParav Pandit mlx5_fc_query(dev, vport->ingress.legacy.drop_counter, 406b55b3538SParav Pandit &stats->tx_dropped, &bytes); 407b55b3538SParav Pandit 408b55b3538SParav Pandit if (!MLX5_CAP_GEN(dev, receive_discard_vport_down) && 409b55b3538SParav Pandit !MLX5_CAP_GEN(dev, transmit_discard_vport_down)) 410b55b3538SParav Pandit goto unlock; 411b55b3538SParav Pandit 412b55b3538SParav Pandit err = mlx5_query_vport_down_stats(dev, vport->vport, 1, 413b55b3538SParav Pandit &rx_discard_vport_down, 414b55b3538SParav Pandit &tx_discard_vport_down); 415b55b3538SParav Pandit if (err) 416b55b3538SParav Pandit goto unlock; 417b55b3538SParav Pandit 418b55b3538SParav Pandit if (MLX5_CAP_GEN(dev, receive_discard_vport_down)) 419b55b3538SParav Pandit stats->rx_dropped += rx_discard_vport_down; 420b55b3538SParav Pandit if (MLX5_CAP_GEN(dev, transmit_discard_vport_down)) 421b55b3538SParav Pandit stats->tx_dropped += tx_discard_vport_down; 422b55b3538SParav Pandit 423b55b3538SParav Pandit unlock: 424b55b3538SParav Pandit mutex_unlock(&esw->state_lock); 425b55b3538SParav Pandit return err; 426b55b3538SParav Pandit } 427b55b3538SParav Pandit 428b55b3538SParav Pandit int mlx5_eswitch_set_vport_vlan(struct mlx5_eswitch *esw, 429b55b3538SParav Pandit u16 vport, u16 vlan, u8 qos) 430b55b3538SParav Pandit { 431b55b3538SParav Pandit u8 set_flags = 0; 432b55b3538SParav Pandit int err = 0; 433b55b3538SParav Pandit 434b55b3538SParav Pandit if (!mlx5_esw_allowed(esw)) 4357846665dSMaor Dickman return vlan ? -EPERM : 0; 436b55b3538SParav Pandit 437b55b3538SParav Pandit if (vlan || qos) 438b55b3538SParav Pandit set_flags = SET_VLAN_STRIP | SET_VLAN_INSERT; 439b55b3538SParav Pandit 440b55b3538SParav Pandit mutex_lock(&esw->state_lock); 441b55b3538SParav Pandit if (esw->mode != MLX5_ESWITCH_LEGACY) { 442b55b3538SParav Pandit if (!vlan) 443b55b3538SParav Pandit goto unlock; /* compatibility with libvirt */ 444b55b3538SParav Pandit 445b55b3538SParav Pandit err = -EOPNOTSUPP; 446b55b3538SParav Pandit goto unlock; 447b55b3538SParav Pandit } 448b55b3538SParav Pandit 449b55b3538SParav Pandit err = __mlx5_eswitch_set_vport_vlan(esw, vport, vlan, qos, set_flags); 450b55b3538SParav Pandit 451b55b3538SParav Pandit unlock: 452b55b3538SParav Pandit mutex_unlock(&esw->state_lock); 453b55b3538SParav Pandit return err; 454b55b3538SParav Pandit } 455b55b3538SParav Pandit 456b55b3538SParav Pandit int mlx5_eswitch_set_vport_spoofchk(struct mlx5_eswitch *esw, 457b55b3538SParav Pandit u16 vport, bool spoofchk) 458b55b3538SParav Pandit { 459b55b3538SParav Pandit struct mlx5_vport *evport = mlx5_eswitch_get_vport(esw, vport); 460b55b3538SParav Pandit bool pschk; 461b55b3538SParav Pandit int err = 0; 462b55b3538SParav Pandit 463b55b3538SParav Pandit if (!mlx5_esw_allowed(esw)) 464b55b3538SParav Pandit return -EPERM; 465b55b3538SParav Pandit if (IS_ERR(evport)) 466b55b3538SParav Pandit return PTR_ERR(evport); 467b55b3538SParav Pandit 468b55b3538SParav Pandit mutex_lock(&esw->state_lock); 469b55b3538SParav Pandit if (esw->mode != MLX5_ESWITCH_LEGACY) { 470b55b3538SParav Pandit err = -EOPNOTSUPP; 471b55b3538SParav Pandit goto unlock; 472b55b3538SParav Pandit } 473b55b3538SParav Pandit pschk = evport->info.spoofchk; 474b55b3538SParav Pandit evport->info.spoofchk = spoofchk; 475b55b3538SParav Pandit if (pschk && !is_valid_ether_addr(evport->info.mac)) 476b55b3538SParav Pandit mlx5_core_warn(esw->dev, 477b55b3538SParav Pandit "Spoofchk in set while MAC is invalid, vport(%d)\n", 478b55b3538SParav Pandit evport->vport); 479b55b3538SParav Pandit if (evport->enabled && esw->mode == MLX5_ESWITCH_LEGACY) 480b55b3538SParav Pandit err = esw_acl_ingress_lgcy_setup(esw, evport); 481b55b3538SParav Pandit if (err) 482b55b3538SParav Pandit evport->info.spoofchk = pschk; 483b55b3538SParav Pandit 484b55b3538SParav Pandit unlock: 485b55b3538SParav Pandit mutex_unlock(&esw->state_lock); 486b55b3538SParav Pandit return err; 487b55b3538SParav Pandit } 488b55b3538SParav Pandit 489b55b3538SParav Pandit int mlx5_eswitch_set_vport_trust(struct mlx5_eswitch *esw, 490b55b3538SParav Pandit u16 vport, bool setting) 491b55b3538SParav Pandit { 492b55b3538SParav Pandit struct mlx5_vport *evport = mlx5_eswitch_get_vport(esw, vport); 493b55b3538SParav Pandit int err = 0; 494b55b3538SParav Pandit 495b55b3538SParav Pandit if (!mlx5_esw_allowed(esw)) 496b55b3538SParav Pandit return -EPERM; 497b55b3538SParav Pandit if (IS_ERR(evport)) 498b55b3538SParav Pandit return PTR_ERR(evport); 499b55b3538SParav Pandit 500b55b3538SParav Pandit mutex_lock(&esw->state_lock); 501b55b3538SParav Pandit if (esw->mode != MLX5_ESWITCH_LEGACY) { 502b55b3538SParav Pandit err = -EOPNOTSUPP; 503b55b3538SParav Pandit goto unlock; 504b55b3538SParav Pandit } 505b55b3538SParav Pandit evport->info.trusted = setting; 506b55b3538SParav Pandit if (evport->enabled) 507b55b3538SParav Pandit esw_vport_change_handle_locked(evport); 508b55b3538SParav Pandit 509b55b3538SParav Pandit unlock: 510b55b3538SParav Pandit mutex_unlock(&esw->state_lock); 511b55b3538SParav Pandit return err; 512b55b3538SParav Pandit } 5132d116e3eSDmytro Linkin 5142d116e3eSDmytro Linkin int mlx5_eswitch_set_vport_rate(struct mlx5_eswitch *esw, u16 vport, 5152d116e3eSDmytro Linkin u32 max_rate, u32 min_rate) 5162d116e3eSDmytro Linkin { 5172d116e3eSDmytro Linkin struct mlx5_vport *evport = mlx5_eswitch_get_vport(esw, vport); 5182d116e3eSDmytro Linkin int err; 5192d116e3eSDmytro Linkin 5202d116e3eSDmytro Linkin if (!mlx5_esw_allowed(esw)) 5212d116e3eSDmytro Linkin return -EPERM; 5222d116e3eSDmytro Linkin if (IS_ERR(evport)) 5232d116e3eSDmytro Linkin return PTR_ERR(evport); 5242d116e3eSDmytro Linkin 5252d116e3eSDmytro Linkin mutex_lock(&esw->state_lock); 526d7df09f5SDmytro Linkin err = mlx5_esw_qos_set_vport_rate(esw, evport, max_rate, min_rate); 5272d116e3eSDmytro Linkin mutex_unlock(&esw->state_lock); 5282d116e3eSDmytro Linkin return err; 5292d116e3eSDmytro Linkin } 530