FILE
bridge.c
File preview with syntax highlighting.
linux-6.19.14/drivers/net/ethernet/mellanox/mlx5/core/esw/bridge.c
1// SPDX-License-Identifier: GPL-2.0 OR Linux-OpenIB 2/* Copyright (c) 2021 Mellanox Technologies. */ 3 4#include <linux/build_bug.h> 5#include <linux/list.h> 6#include <linux/notifier.h> 7#include <net/netevent.h> 8#include <net/switchdev.h> 9#include "lib/devcom.h" 10#include "bridge.h" 11#include "eswitch.h" 12#include "bridge_priv.h" 13#define CREATE_TRACE_POINTS 14#include "diag/bridge_tracepoint.h" 15 16static const struct rhashtable_params fdb_ht_params = { 17 .key_offset = offsetof(struct mlx5_esw_bridge_fdb_entry, key), 18 .key_len = sizeof(struct mlx5_esw_bridge_fdb_key), 19 .head_offset = offsetof(struct mlx5_esw_bridge_fdb_entry, ht_node), 20 .automatic_shrinking = true, 21}; 22 23static void 24mlx5_esw_bridge_fdb_offload_notify(struct net_device *dev, const unsigned char *addr, u16 vid, 25 unsigned long val) 26{ 27 struct switchdev_notifier_fdb_info send_info = {}; 28 29 send_info.addr = addr; 30 send_info.vid = vid; 31 send_info.offloaded = true; 32 call_switchdev_notifiers(val, dev, &send_info.info, NULL); 33} 34 35static void 36mlx5_esw_bridge_fdb_del_notify(struct mlx5_esw_bridge_fdb_entry *entry) 37{ 38 if (!(entry->flags & (MLX5_ESW_BRIDGE_FLAG_ADDED_BY_USER | MLX5_ESW_BRIDGE_FLAG_PEER))) 39 mlx5_esw_bridge_fdb_offload_notify(entry->dev, entry->key.addr, 40 entry->key.vid, 41 SWITCHDEV_FDB_DEL_TO_BRIDGE); 42} 43 44static bool mlx5_esw_bridge_pkt_reformat_vlan_pop_supported(struct mlx5_eswitch *esw) 45{ 46 return BIT(MLX5_CAP_ESW_FLOWTABLE_FDB(esw->dev, reformat_remove)) && 47 MLX5_CAP_GEN_2(esw->dev, max_reformat_remove_size) >= sizeof(struct vlan_hdr) && 48 MLX5_CAP_GEN_2(esw->dev, max_reformat_remove_offset) >= 49 offsetof(struct vlan_ethhdr, h_vlan_proto); 50} 51 52static struct mlx5_pkt_reformat * 53mlx5_esw_bridge_pkt_reformat_vlan_pop_create(struct mlx5_eswitch *esw) 54{ 55 struct mlx5_pkt_reformat_params reformat_params = {}; 56 57 reformat_params.type = MLX5_REFORMAT_TYPE_REMOVE_HDR; 58 reformat_params.param_0 = MLX5_REFORMAT_CONTEXT_ANCHOR_MAC_START; 59 reformat_params.param_1 = offsetof(struct vlan_ethhdr, h_vlan_proto); 60 reformat_params.size = sizeof(struct vlan_hdr); 61 return mlx5_packet_reformat_alloc(esw->dev, &reformat_params, MLX5_FLOW_NAMESPACE_FDB); 62} 63 64struct mlx5_flow_table * 65mlx5_esw_bridge_table_create(int max_fte, u32 level, struct mlx5_eswitch *esw) 66{ 67 struct mlx5_flow_table_attr ft_attr = {}; 68 struct mlx5_core_dev *dev = esw->dev; 69 struct mlx5_flow_namespace *ns; 70 struct mlx5_flow_table *fdb; 71 72 ns = mlx5_get_flow_namespace(dev, MLX5_FLOW_NAMESPACE_FDB); 73 if (!ns) { 74 esw_warn(dev, "Failed to get FDB namespace\n"); 75 return ERR_PTR(-ENOENT); 76 } 77 78 ft_attr.flags = MLX5_FLOW_TABLE_TUNNEL_EN_REFORMAT; 79 ft_attr.max_fte = max_fte; 80 ft_attr.level = level; 81 ft_attr.prio = FDB_BR_OFFLOAD; 82 fdb = mlx5_create_flow_table(ns, &ft_attr); 83 if (IS_ERR(fdb)) 84 esw_warn(dev, "Failed to create bridge FDB Table (err=%pe)\n", 85 fdb); 86 87 return fdb; 88} 89 90static struct mlx5_flow_group * 91mlx5_esw_bridge_ingress_vlan_proto_fg_create(unsigned int from, unsigned int to, u16 vlan_proto, 92 struct mlx5_eswitch *esw, 93 struct mlx5_flow_table *ingress_ft) 94{ 95 int inlen = MLX5_ST_SZ_BYTES(create_flow_group_in); 96 struct mlx5_flow_group *fg; 97 u32 *in, *match; 98 99 in = kvzalloc(inlen, GFP_KERNEL); 100 if (!in) 101 return ERR_PTR(-ENOMEM); 102 103 MLX5_SET(create_flow_group_in, in, match_criteria_enable, 104 MLX5_MATCH_OUTER_HEADERS | MLX5_MATCH_MISC_PARAMETERS_2); 105 match = MLX5_ADDR_OF(create_flow_group_in, in, match_criteria); 106 107 MLX5_SET_TO_ONES(fte_match_param, match, outer_headers.smac_47_16); 108 MLX5_SET_TO_ONES(fte_match_param, match, outer_headers.smac_15_0); 109 if (vlan_proto == ETH_P_8021Q) 110 MLX5_SET_TO_ONES(fte_match_param, match, outer_headers.cvlan_tag); 111 else if (vlan_proto == ETH_P_8021AD) 112 MLX5_SET_TO_ONES(fte_match_param, match, outer_headers.svlan_tag); 113 MLX5_SET_TO_ONES(fte_match_param, match, outer_headers.first_vid); 114 115 MLX5_SET(fte_match_param, match, misc_parameters_2.metadata_reg_c_0, 116 mlx5_eswitch_get_vport_metadata_mask()); 117 118 MLX5_SET(create_flow_group_in, in, start_flow_index, from); 119 MLX5_SET(create_flow_group_in, in, end_flow_index, to); 120 121 fg = mlx5_create_flow_group(ingress_ft, in); 122 kvfree(in); 123 if (IS_ERR(fg)) 124 esw_warn(esw->dev, 125 "Failed to create VLAN(proto=%x) flow group for bridge ingress table (err=%pe)\n", 126 vlan_proto, fg); 127 128 return fg; 129} 130 131static struct mlx5_flow_group * 132mlx5_esw_bridge_ingress_vlan_fg_create(struct mlx5_eswitch *esw, 133 struct mlx5_flow_table *ingress_ft) 134{ 135 unsigned int from = MLX5_ESW_BRIDGE_INGRESS_TABLE_VLAN_GRP_IDX_FROM; 136 unsigned int to = MLX5_ESW_BRIDGE_INGRESS_TABLE_VLAN_GRP_IDX_TO; 137 138 return mlx5_esw_bridge_ingress_vlan_proto_fg_create(from, to, ETH_P_8021Q, esw, ingress_ft); 139} 140 141static struct mlx5_flow_group * 142mlx5_esw_bridge_ingress_qinq_fg_create(struct mlx5_eswitch *esw, 143 struct mlx5_flow_table *ingress_ft) 144{ 145 unsigned int from = MLX5_ESW_BRIDGE_INGRESS_TABLE_QINQ_GRP_IDX_FROM; 146 unsigned int to = MLX5_ESW_BRIDGE_INGRESS_TABLE_QINQ_GRP_IDX_TO; 147 148 return mlx5_esw_bridge_ingress_vlan_proto_fg_create(from, to, ETH_P_8021AD, esw, 149 ingress_ft); 150} 151 152static struct mlx5_flow_group * 153mlx5_esw_bridge_ingress_vlan_proto_filter_fg_create(unsigned int from, unsigned int to, 154 u16 vlan_proto, struct mlx5_eswitch *esw, 155 struct mlx5_flow_table *ingress_ft) 156{ 157 int inlen = MLX5_ST_SZ_BYTES(create_flow_group_in); 158 struct mlx5_flow_group *fg; 159 u32 *in, *match; 160 161 in = kvzalloc(inlen, GFP_KERNEL); 162 if (!in) 163 return ERR_PTR(-ENOMEM); 164 165 MLX5_SET(create_flow_group_in, in, match_criteria_enable, 166 MLX5_MATCH_OUTER_HEADERS | MLX5_MATCH_MISC_PARAMETERS_2); 167 match = MLX5_ADDR_OF(create_flow_group_in, in, match_criteria); 168 169 MLX5_SET_TO_ONES(fte_match_param, match, outer_headers.smac_47_16); 170 MLX5_SET_TO_ONES(fte_match_param, match, outer_headers.smac_15_0); 171 if (vlan_proto == ETH_P_8021Q) 172 MLX5_SET_TO_ONES(fte_match_param, match, outer_headers.cvlan_tag); 173 else if (vlan_proto == ETH_P_8021AD) 174 MLX5_SET_TO_ONES(fte_match_param, match, outer_headers.svlan_tag); 175 MLX5_SET(fte_match_param, match, misc_parameters_2.metadata_reg_c_0, 176 mlx5_eswitch_get_vport_metadata_mask()); 177 178 MLX5_SET(create_flow_group_in, in, start_flow_index, from); 179 MLX5_SET(create_flow_group_in, in, end_flow_index, to); 180 181 fg = mlx5_create_flow_group(ingress_ft, in); 182 if (IS_ERR(fg)) 183 esw_warn(esw->dev, 184 "Failed to create bridge ingress table VLAN filter flow group (err=%pe)\n", 185 fg); 186 kvfree(in); 187 return fg; 188} 189 190static struct mlx5_flow_group * 191mlx5_esw_bridge_ingress_vlan_filter_fg_create(struct mlx5_eswitch *esw, 192 struct mlx5_flow_table *ingress_ft) 193{ 194 unsigned int from = MLX5_ESW_BRIDGE_INGRESS_TABLE_VLAN_FILTER_GRP_IDX_FROM; 195 unsigned int to = MLX5_ESW_BRIDGE_INGRESS_TABLE_VLAN_FILTER_GRP_IDX_TO; 196 197 return mlx5_esw_bridge_ingress_vlan_proto_filter_fg_create(from, to, ETH_P_8021Q, esw, 198 ingress_ft); 199} 200 201static struct mlx5_flow_group * 202mlx5_esw_bridge_ingress_qinq_filter_fg_create(struct mlx5_eswitch *esw, 203 struct mlx5_flow_table *ingress_ft) 204{ 205 unsigned int from = MLX5_ESW_BRIDGE_INGRESS_TABLE_QINQ_FILTER_GRP_IDX_FROM; 206 unsigned int to = MLX5_ESW_BRIDGE_INGRESS_TABLE_QINQ_FILTER_GRP_IDX_TO; 207 208 return mlx5_esw_bridge_ingress_vlan_proto_filter_fg_create(from, to, ETH_P_8021AD, esw, 209 ingress_ft); 210} 211 212static struct mlx5_flow_group * 213mlx5_esw_bridge_ingress_mac_fg_create(struct mlx5_eswitch *esw, struct mlx5_flow_table *ingress_ft) 214{ 215 int inlen = MLX5_ST_SZ_BYTES(create_flow_group_in); 216 struct mlx5_flow_group *fg; 217 u32 *in, *match; 218 219 in = kvzalloc(inlen, GFP_KERNEL); 220 if (!in) 221 return ERR_PTR(-ENOMEM); 222 223 MLX5_SET(create_flow_group_in, in, match_criteria_enable, 224 MLX5_MATCH_OUTER_HEADERS | MLX5_MATCH_MISC_PARAMETERS_2); 225 match = MLX5_ADDR_OF(create_flow_group_in, in, match_criteria); 226 227 MLX5_SET_TO_ONES(fte_match_param, match, outer_headers.smac_47_16); 228 MLX5_SET_TO_ONES(fte_match_param, match, outer_headers.smac_15_0); 229 230 MLX5_SET(fte_match_param, match, misc_parameters_2.metadata_reg_c_0, 231 mlx5_eswitch_get_vport_metadata_mask()); 232 233 MLX5_SET(create_flow_group_in, in, start_flow_index, 234 MLX5_ESW_BRIDGE_INGRESS_TABLE_MAC_GRP_IDX_FROM); 235 MLX5_SET(create_flow_group_in, in, end_flow_index, 236 MLX5_ESW_BRIDGE_INGRESS_TABLE_MAC_GRP_IDX_TO); 237 238 fg = mlx5_create_flow_group(ingress_ft, in); 239 if (IS_ERR(fg)) 240 esw_warn(esw->dev, 241 "Failed to create MAC flow group for bridge ingress table (err=%pe)\n", 242 fg); 243 244 kvfree(in); 245 return fg; 246} 247 248static struct mlx5_flow_group * 249mlx5_esw_bridge_egress_vlan_proto_fg_create(unsigned int from, unsigned int to, u16 vlan_proto, 250 struct mlx5_eswitch *esw, 251 struct mlx5_flow_table *egress_ft) 252{ 253 int inlen = MLX5_ST_SZ_BYTES(create_flow_group_in); 254 struct mlx5_flow_group *fg; 255 u32 *in, *match; 256 257 in = kvzalloc(inlen, GFP_KERNEL); 258 if (!in) 259 return ERR_PTR(-ENOMEM); 260 261 MLX5_SET(create_flow_group_in, in, match_criteria_enable, MLX5_MATCH_OUTER_HEADERS); 262 match = MLX5_ADDR_OF(create_flow_group_in, in, match_criteria); 263 264 MLX5_SET_TO_ONES(fte_match_param, match, outer_headers.dmac_47_16); 265 MLX5_SET_TO_ONES(fte_match_param, match, outer_headers.dmac_15_0); 266 if (vlan_proto == ETH_P_8021Q) 267 MLX5_SET_TO_ONES(fte_match_param, match, outer_headers.cvlan_tag); 268 else if (vlan_proto == ETH_P_8021AD) 269 MLX5_SET_TO_ONES(fte_match_param, match, outer_headers.svlan_tag); 270 MLX5_SET_TO_ONES(fte_match_param, match, outer_headers.first_vid); 271 272 MLX5_SET(create_flow_group_in, in, start_flow_index, from); 273 MLX5_SET(create_flow_group_in, in, end_flow_index, to); 274 275 fg = mlx5_create_flow_group(egress_ft, in); 276 if (IS_ERR(fg)) 277 esw_warn(esw->dev, 278 "Failed to create VLAN flow group for bridge egress table (err=%pe)\n", 279 fg); 280 kvfree(in); 281 return fg; 282} 283 284static struct mlx5_flow_group * 285mlx5_esw_bridge_egress_vlan_fg_create(struct mlx5_eswitch *esw, struct mlx5_flow_table *egress_ft) 286{ 287 unsigned int from = MLX5_ESW_BRIDGE_EGRESS_TABLE_VLAN_GRP_IDX_FROM; 288 unsigned int to = MLX5_ESW_BRIDGE_EGRESS_TABLE_VLAN_GRP_IDX_TO; 289 290 return mlx5_esw_bridge_egress_vlan_proto_fg_create(from, to, ETH_P_8021Q, esw, egress_ft); 291} 292 293static struct mlx5_flow_group * 294mlx5_esw_bridge_egress_qinq_fg_create(struct mlx5_eswitch *esw, 295 struct mlx5_flow_table *egress_ft) 296{ 297 unsigned int from = MLX5_ESW_BRIDGE_EGRESS_TABLE_QINQ_GRP_IDX_FROM; 298 unsigned int to = MLX5_ESW_BRIDGE_EGRESS_TABLE_QINQ_GRP_IDX_TO; 299 300 return mlx5_esw_bridge_egress_vlan_proto_fg_create(from, to, ETH_P_8021AD, esw, egress_ft); 301} 302 303static struct mlx5_flow_group * 304mlx5_esw_bridge_egress_mac_fg_create(struct mlx5_eswitch *esw, struct mlx5_flow_table *egress_ft) 305{ 306 int inlen = MLX5_ST_SZ_BYTES(create_flow_group_in); 307 struct mlx5_flow_group *fg; 308 u32 *in, *match; 309 310 in = kvzalloc(inlen, GFP_KERNEL); 311 if (!in) 312 return ERR_PTR(-ENOMEM); 313 314 MLX5_SET(create_flow_group_in, in, match_criteria_enable, MLX5_MATCH_OUTER_HEADERS); 315 match = MLX5_ADDR_OF(create_flow_group_in, in, match_criteria); 316 317 MLX5_SET_TO_ONES(fte_match_param, match, outer_headers.dmac_47_16); 318 MLX5_SET_TO_ONES(fte_match_param, match, outer_headers.dmac_15_0); 319 320 MLX5_SET(create_flow_group_in, in, start_flow_index, 321 MLX5_ESW_BRIDGE_EGRESS_TABLE_MAC_GRP_IDX_FROM); 322 MLX5_SET(create_flow_group_in, in, end_flow_index, 323 MLX5_ESW_BRIDGE_EGRESS_TABLE_MAC_GRP_IDX_TO); 324 325 fg = mlx5_create_flow_group(egress_ft, in); 326 if (IS_ERR(fg)) 327 esw_warn(esw->dev, 328 "Failed to create bridge egress table MAC flow group (err=%pe)\n", 329 fg); 330 kvfree(in); 331 return fg; 332} 333 334static struct mlx5_flow_group * 335mlx5_esw_bridge_egress_miss_fg_create(struct mlx5_eswitch *esw, struct mlx5_flow_table *egress_ft) 336{ 337 int inlen = MLX5_ST_SZ_BYTES(create_flow_group_in); 338 struct mlx5_flow_group *fg; 339 u32 *in, *match; 340 341 in = kvzalloc(inlen, GFP_KERNEL); 342 if (!in) 343 return ERR_PTR(-ENOMEM); 344 345 MLX5_SET(create_flow_group_in, in, match_criteria_enable, MLX5_MATCH_MISC_PARAMETERS_2); 346 match = MLX5_ADDR_OF(create_flow_group_in, in, match_criteria); 347 348 MLX5_SET(fte_match_param, match, misc_parameters_2.metadata_reg_c_1, ESW_TUN_MASK); 349 350 MLX5_SET(create_flow_group_in, in, start_flow_index, 351 MLX5_ESW_BRIDGE_EGRESS_TABLE_MISS_GRP_IDX_FROM); 352 MLX5_SET(create_flow_group_in, in, end_flow_index, 353 MLX5_ESW_BRIDGE_EGRESS_TABLE_MISS_GRP_IDX_TO); 354 355 fg = mlx5_create_flow_group(egress_ft, in); 356 if (IS_ERR(fg)) 357 esw_warn(esw->dev, 358 "Failed to create bridge egress table miss flow group (err=%pe)\n", 359 fg); 360 kvfree(in); 361 return fg; 362} 363 364static int 365mlx5_esw_bridge_ingress_table_init(struct mlx5_esw_bridge_offloads *br_offloads) 366{ 367 struct mlx5_flow_group *mac_fg, *qinq_filter_fg, *qinq_fg, *vlan_filter_fg, *vlan_fg; 368 struct mlx5_flow_table *ingress_ft, *skip_ft; 369 struct mlx5_eswitch *esw = br_offloads->esw; 370 int err; 371 372 if (!mlx5_eswitch_vport_match_metadata_enabled(esw)) 373 return -EOPNOTSUPP; 374 375 ingress_ft = mlx5_esw_bridge_table_create(MLX5_ESW_BRIDGE_INGRESS_TABLE_SIZE, 376 MLX5_ESW_BRIDGE_LEVEL_INGRESS_TABLE, 377 esw); 378 if (IS_ERR(ingress_ft)) 379 return PTR_ERR(ingress_ft); 380 381 skip_ft = mlx5_esw_bridge_table_create(MLX5_ESW_BRIDGE_SKIP_TABLE_SIZE, 382 MLX5_ESW_BRIDGE_LEVEL_SKIP_TABLE, 383 esw); 384 if (IS_ERR(skip_ft)) { 385 err = PTR_ERR(skip_ft); 386 goto err_skip_tbl; 387 } 388 389 vlan_fg = mlx5_esw_bridge_ingress_vlan_fg_create(esw, ingress_ft); 390 if (IS_ERR(vlan_fg)) { 391 err = PTR_ERR(vlan_fg); 392 goto err_vlan_fg; 393 } 394 395 vlan_filter_fg = mlx5_esw_bridge_ingress_vlan_filter_fg_create(esw, ingress_ft); 396 if (IS_ERR(vlan_filter_fg)) { 397 err = PTR_ERR(vlan_filter_fg); 398 goto err_vlan_filter_fg; 399 } 400 401 qinq_fg = mlx5_esw_bridge_ingress_qinq_fg_create(esw, ingress_ft); 402 if (IS_ERR(qinq_fg)) { 403 err = PTR_ERR(qinq_fg); 404 goto err_qinq_fg; 405 } 406 407 qinq_filter_fg = mlx5_esw_bridge_ingress_qinq_filter_fg_create(esw, ingress_ft); 408 if (IS_ERR(qinq_filter_fg)) { 409 err = PTR_ERR(qinq_filter_fg); 410 goto err_qinq_filter_fg; 411 } 412 413 mac_fg = mlx5_esw_bridge_ingress_mac_fg_create(esw, ingress_ft); 414 if (IS_ERR(mac_fg)) { 415 err = PTR_ERR(mac_fg); 416 goto err_mac_fg; 417 } 418 419 br_offloads->ingress_ft = ingress_ft; 420 br_offloads->skip_ft = skip_ft; 421 br_offloads->ingress_vlan_fg = vlan_fg; 422 br_offloads->ingress_vlan_filter_fg = vlan_filter_fg; 423 br_offloads->ingress_qinq_fg = qinq_fg; 424 br_offloads->ingress_qinq_filter_fg = qinq_filter_fg; 425 br_offloads->ingress_mac_fg = mac_fg; 426 return 0; 427 428err_mac_fg: 429 mlx5_destroy_flow_group(qinq_filter_fg); 430err_qinq_filter_fg: 431 mlx5_destroy_flow_group(qinq_fg); 432err_qinq_fg: 433 mlx5_destroy_flow_group(vlan_filter_fg); 434err_vlan_filter_fg: 435 mlx5_destroy_flow_group(vlan_fg); 436err_vlan_fg: 437 mlx5_destroy_flow_table(skip_ft); 438err_skip_tbl: 439 mlx5_destroy_flow_table(ingress_ft); 440 return err; 441} 442 443static void 444mlx5_esw_bridge_ingress_table_cleanup(struct mlx5_esw_bridge_offloads *br_offloads) 445{ 446 mlx5_destroy_flow_group(br_offloads->ingress_mac_fg); 447 br_offloads->ingress_mac_fg = NULL; 448 mlx5_destroy_flow_group(br_offloads->ingress_qinq_filter_fg); 449 br_offloads->ingress_qinq_filter_fg = NULL; 450 mlx5_destroy_flow_group(br_offloads->ingress_qinq_fg); 451 br_offloads->ingress_qinq_fg = NULL; 452 mlx5_destroy_flow_group(br_offloads->ingress_vlan_filter_fg); 453 br_offloads->ingress_vlan_filter_fg = NULL; 454 mlx5_destroy_flow_group(br_offloads->ingress_vlan_fg); 455 br_offloads->ingress_vlan_fg = NULL; 456 mlx5_destroy_flow_table(br_offloads->skip_ft); 457 br_offloads->skip_ft = NULL; 458 mlx5_destroy_flow_table(br_offloads->ingress_ft); 459 br_offloads->ingress_ft = NULL; 460} 461 462static struct mlx5_flow_handle * 463mlx5_esw_bridge_egress_miss_flow_create(struct mlx5_flow_table *egress_ft, 464 struct mlx5_flow_table *skip_ft, 465 struct mlx5_pkt_reformat *pkt_reformat); 466 467static int 468mlx5_esw_bridge_egress_table_init(struct mlx5_esw_bridge_offloads *br_offloads, 469 struct mlx5_esw_bridge *bridge) 470{ 471 struct mlx5_flow_group *miss_fg = NULL, *mac_fg, *vlan_fg, *qinq_fg; 472 struct mlx5_pkt_reformat *miss_pkt_reformat = NULL; 473 struct mlx5_flow_handle *miss_handle = NULL; 474 struct mlx5_eswitch *esw = br_offloads->esw; 475 struct mlx5_flow_table *egress_ft; 476 int err; 477 478 egress_ft = mlx5_esw_bridge_table_create(MLX5_ESW_BRIDGE_EGRESS_TABLE_SIZE, 479 MLX5_ESW_BRIDGE_LEVEL_EGRESS_TABLE, 480 esw); 481 if (IS_ERR(egress_ft)) 482 return PTR_ERR(egress_ft); 483 484 vlan_fg = mlx5_esw_bridge_egress_vlan_fg_create(esw, egress_ft); 485 if (IS_ERR(vlan_fg)) { 486 err = PTR_ERR(vlan_fg); 487 goto err_vlan_fg; 488 } 489 490 qinq_fg = mlx5_esw_bridge_egress_qinq_fg_create(esw, egress_ft); 491 if (IS_ERR(qinq_fg)) { 492 err = PTR_ERR(qinq_fg); 493 goto err_qinq_fg; 494 } 495 496 mac_fg = mlx5_esw_bridge_egress_mac_fg_create(esw, egress_ft); 497 if (IS_ERR(mac_fg)) { 498 err = PTR_ERR(mac_fg); 499 goto err_mac_fg; 500 } 501 502 if (mlx5_esw_bridge_pkt_reformat_vlan_pop_supported(esw)) { 503 miss_fg = mlx5_esw_bridge_egress_miss_fg_create(esw, egress_ft); 504 if (IS_ERR(miss_fg)) { 505 esw_warn(esw->dev, "Failed to create miss flow group (err=%pe)\n", 506 miss_fg); 507 miss_fg = NULL; 508 goto skip_miss_flow; 509 } 510 511 miss_pkt_reformat = mlx5_esw_bridge_pkt_reformat_vlan_pop_create(esw); 512 if (IS_ERR(miss_pkt_reformat)) { 513 esw_warn(esw->dev, 514 "Failed to alloc packet reformat REMOVE_HEADER (err=%pe)\n", 515 miss_pkt_reformat); 516 miss_pkt_reformat = NULL; 517 mlx5_destroy_flow_group(miss_fg); 518 miss_fg = NULL; 519 goto skip_miss_flow; 520 } 521 522 miss_handle = mlx5_esw_bridge_egress_miss_flow_create(egress_ft, 523 br_offloads->skip_ft, 524 miss_pkt_reformat); 525 if (IS_ERR(miss_handle)) { 526 esw_warn(esw->dev, "Failed to create miss flow (err=%pe)\n", 527 miss_handle); 528 miss_handle = NULL; 529 mlx5_packet_reformat_dealloc(esw->dev, miss_pkt_reformat); 530 miss_pkt_reformat = NULL; 531 mlx5_destroy_flow_group(miss_fg); 532 miss_fg = NULL; 533 goto skip_miss_flow; 534 } 535 } 536skip_miss_flow: 537 538 bridge->egress_ft = egress_ft; 539 bridge->egress_vlan_fg = vlan_fg; 540 bridge->egress_qinq_fg = qinq_fg; 541 bridge->egress_mac_fg = mac_fg; 542 bridge->egress_miss_fg = miss_fg; 543 bridge->egress_miss_pkt_reformat = miss_pkt_reformat; 544 bridge->egress_miss_handle = miss_handle; 545 return 0; 546 547err_mac_fg: 548 mlx5_destroy_flow_group(qinq_fg); 549err_qinq_fg: 550 mlx5_destroy_flow_group(vlan_fg); 551err_vlan_fg: 552 mlx5_destroy_flow_table(egress_ft); 553 return err; 554} 555 556static void 557mlx5_esw_bridge_egress_table_cleanup(struct mlx5_esw_bridge *bridge) 558{ 559 if (bridge->egress_miss_handle) 560 mlx5_del_flow_rules(bridge->egress_miss_handle); 561 if (bridge->egress_miss_pkt_reformat) 562 mlx5_packet_reformat_dealloc(bridge->br_offloads->esw->dev, 563 bridge->egress_miss_pkt_reformat); 564 if (bridge->egress_miss_fg) 565 mlx5_destroy_flow_group(bridge->egress_miss_fg); 566 mlx5_destroy_flow_group(bridge->egress_mac_fg); 567 mlx5_destroy_flow_group(bridge->egress_qinq_fg); 568 mlx5_destroy_flow_group(bridge->egress_vlan_fg); 569 mlx5_destroy_flow_table(bridge->egress_ft); 570} 571 572static struct mlx5_flow_handle * 573mlx5_esw_bridge_ingress_flow_with_esw_create(u16 vport_num, const unsigned char *addr, 574 struct mlx5_esw_bridge_vlan *vlan, 575 struct mlx5_fc *counter, 576 struct mlx5_esw_bridge *bridge, 577 struct mlx5_eswitch *esw) 578{ 579 struct mlx5_esw_bridge_offloads *br_offloads = bridge->br_offloads; 580 struct mlx5_flow_act flow_act = { 581 .action = MLX5_FLOW_CONTEXT_ACTION_FWD_DEST | MLX5_FLOW_CONTEXT_ACTION_COUNT, 582 .flags = FLOW_ACT_NO_APPEND, 583 }; 584 struct mlx5_flow_destination dests[2] = {}; 585 struct mlx5_flow_spec *rule_spec; 586 struct mlx5_flow_handle *handle; 587 u8 *smac_v, *smac_c; 588 589 rule_spec = kvzalloc(sizeof(*rule_spec), GFP_KERNEL); 590 if (!rule_spec) 591 return ERR_PTR(-ENOMEM); 592 593 rule_spec->match_criteria_enable = MLX5_MATCH_OUTER_HEADERS | MLX5_MATCH_MISC_PARAMETERS_2; 594 595 smac_v = MLX5_ADDR_OF(fte_match_param, rule_spec->match_value, 596 outer_headers.smac_47_16); 597 ether_addr_copy(smac_v, addr); 598 smac_c = MLX5_ADDR_OF(fte_match_param, rule_spec->match_criteria, 599 outer_headers.smac_47_16); 600 eth_broadcast_addr(smac_c); 601 602 MLX5_SET(fte_match_param, rule_spec->match_criteria, 603 misc_parameters_2.metadata_reg_c_0, mlx5_eswitch_get_vport_metadata_mask()); 604 MLX5_SET(fte_match_param, rule_spec->match_value, misc_parameters_2.metadata_reg_c_0, 605 mlx5_eswitch_get_vport_metadata_for_match(esw, vport_num)); 606 607 if (vlan && vlan->pkt_reformat_push) { 608 flow_act.action |= MLX5_FLOW_CONTEXT_ACTION_PACKET_REFORMAT | 609 MLX5_FLOW_CONTEXT_ACTION_MOD_HDR; 610 flow_act.pkt_reformat = vlan->pkt_reformat_push; 611 flow_act.modify_hdr = vlan->pkt_mod_hdr_push_mark; 612 } else if (vlan) { 613 if (bridge->vlan_proto == ETH_P_8021Q) { 614 MLX5_SET_TO_ONES(fte_match_param, rule_spec->match_criteria, 615 outer_headers.cvlan_tag); 616 MLX5_SET_TO_ONES(fte_match_param, rule_spec->match_value, 617 outer_headers.cvlan_tag); 618 } else if (bridge->vlan_proto == ETH_P_8021AD) { 619 MLX5_SET_TO_ONES(fte_match_param, rule_spec->match_criteria, 620 outer_headers.svlan_tag); 621 MLX5_SET_TO_ONES(fte_match_param, rule_spec->match_value, 622 outer_headers.svlan_tag); 623 } 624 MLX5_SET_TO_ONES(fte_match_param, rule_spec->match_criteria, 625 outer_headers.first_vid); 626 MLX5_SET(fte_match_param, rule_spec->match_value, outer_headers.first_vid, 627 vlan->vid); 628 } 629 630 dests[0].type = MLX5_FLOW_DESTINATION_TYPE_FLOW_TABLE; 631 dests[0].ft = bridge->egress_ft; 632 dests[1].type = MLX5_FLOW_DESTINATION_TYPE_COUNTER; 633 dests[1].counter = counter; 634 635 handle = mlx5_add_flow_rules(br_offloads->ingress_ft, rule_spec, &flow_act, dests, 636 ARRAY_SIZE(dests)); 637 638 kvfree(rule_spec); 639 return handle; 640} 641 642static struct mlx5_flow_handle * 643mlx5_esw_bridge_ingress_flow_create(u16 vport_num, const unsigned char *addr, 644 struct mlx5_esw_bridge_vlan *vlan, 645 struct mlx5_fc *counter, 646 struct mlx5_esw_bridge *bridge) 647{ 648 return mlx5_esw_bridge_ingress_flow_with_esw_create(vport_num, addr, vlan, counter, 649 bridge, bridge->br_offloads->esw); 650} 651 652static struct mlx5_flow_handle * 653mlx5_esw_bridge_ingress_flow_peer_create(u16 vport_num, u16 esw_owner_vhca_id, 654 const unsigned char *addr, 655 struct mlx5_esw_bridge_vlan *vlan, 656 struct mlx5_fc *counter, 657 struct mlx5_esw_bridge *bridge) 658{ 659 struct mlx5_devcom_comp_dev *devcom = bridge->br_offloads->esw->devcom, *pos; 660 struct mlx5_eswitch *tmp, *peer_esw = NULL; 661 static struct mlx5_flow_handle *handle; 662 663 if (!mlx5_devcom_for_each_peer_begin(devcom)) 664 return ERR_PTR(-ENODEV); 665 666 mlx5_devcom_for_each_peer_entry(devcom, tmp, pos) { 667 if (mlx5_esw_is_owner(tmp, vport_num, esw_owner_vhca_id)) { 668 peer_esw = tmp; 669 break; 670 } 671 } 672 673 if (!peer_esw) { 674 handle = ERR_PTR(-ENODEV); 675 goto out; 676 } 677 678 handle = mlx5_esw_bridge_ingress_flow_with_esw_create(vport_num, addr, vlan, counter, 679 bridge, peer_esw); 680 681out: 682 mlx5_devcom_for_each_peer_end(devcom); 683 return handle; 684} 685 686static struct mlx5_flow_handle * 687mlx5_esw_bridge_ingress_filter_flow_create(u16 vport_num, const unsigned char *addr, 688 struct mlx5_esw_bridge *bridge) 689{ 690 struct mlx5_esw_bridge_offloads *br_offloads = bridge->br_offloads; 691 struct mlx5_flow_destination dest = { 692 .type = MLX5_FLOW_DESTINATION_TYPE_FLOW_TABLE, 693 .ft = br_offloads->skip_ft, 694 }; 695 struct mlx5_flow_act flow_act = { 696 .action = MLX5_FLOW_CONTEXT_ACTION_FWD_DEST, 697 .flags = FLOW_ACT_NO_APPEND, 698 }; 699 struct mlx5_flow_spec *rule_spec; 700 struct mlx5_flow_handle *handle; 701 u8 *smac_v, *smac_c; 702 703 rule_spec = kvzalloc(sizeof(*rule_spec), GFP_KERNEL); 704 if (!rule_spec) 705 return ERR_PTR(-ENOMEM); 706 707 rule_spec->match_criteria_enable = MLX5_MATCH_OUTER_HEADERS | MLX5_MATCH_MISC_PARAMETERS_2; 708 709 smac_v = MLX5_ADDR_OF(fte_match_param, rule_spec->match_value, 710 outer_headers.smac_47_16); 711 ether_addr_copy(smac_v, addr); 712 smac_c = MLX5_ADDR_OF(fte_match_param, rule_spec->match_criteria, 713 outer_headers.smac_47_16); 714 eth_broadcast_addr(smac_c); 715 716 MLX5_SET(fte_match_param, rule_spec->match_criteria, 717 misc_parameters_2.metadata_reg_c_0, mlx5_eswitch_get_vport_metadata_mask()); 718 MLX5_SET(fte_match_param, rule_spec->match_value, misc_parameters_2.metadata_reg_c_0, 719 mlx5_eswitch_get_vport_metadata_for_match(br_offloads->esw, vport_num)); 720 721 if (bridge->vlan_proto == ETH_P_8021Q) { 722 MLX5_SET_TO_ONES(fte_match_param, rule_spec->match_criteria, 723 outer_headers.cvlan_tag); 724 MLX5_SET_TO_ONES(fte_match_param, rule_spec->match_value, 725 outer_headers.cvlan_tag); 726 } else if (bridge->vlan_proto == ETH_P_8021AD) { 727 MLX5_SET_TO_ONES(fte_match_param, rule_spec->match_criteria, 728 outer_headers.svlan_tag); 729 MLX5_SET_TO_ONES(fte_match_param, rule_spec->match_value, 730 outer_headers.svlan_tag); 731 } 732 733 handle = mlx5_add_flow_rules(br_offloads->ingress_ft, rule_spec, &flow_act, &dest, 1); 734 735 kvfree(rule_spec); 736 return handle; 737} 738 739static struct mlx5_flow_handle * 740mlx5_esw_bridge_egress_flow_create(u16 vport_num, u16 esw_owner_vhca_id, const unsigned char *addr, 741 struct mlx5_esw_bridge_vlan *vlan, 742 struct mlx5_esw_bridge *bridge) 743{ 744 struct mlx5_flow_destination dest = { 745 .type = MLX5_FLOW_DESTINATION_TYPE_VPORT, 746 .vport.num = vport_num, 747 }; 748 struct mlx5_flow_act flow_act = { 749 .action = MLX5_FLOW_CONTEXT_ACTION_FWD_DEST, 750 .flags = FLOW_ACT_NO_APPEND, 751 }; 752 struct mlx5_flow_spec *rule_spec; 753 struct mlx5_flow_handle *handle; 754 u8 *dmac_v, *dmac_c; 755 756 rule_spec = kvzalloc(sizeof(*rule_spec), GFP_KERNEL); 757 if (!rule_spec) 758 return ERR_PTR(-ENOMEM); 759 760 if (MLX5_CAP_ESW_FLOWTABLE(bridge->br_offloads->esw->dev, flow_source) && 761 vport_num == MLX5_VPORT_UPLINK) 762 rule_spec->flow_context.flow_source = 763 MLX5_FLOW_CONTEXT_FLOW_SOURCE_LOCAL_VPORT; 764 rule_spec->match_criteria_enable = MLX5_MATCH_OUTER_HEADERS; 765 766 dmac_v = MLX5_ADDR_OF(fte_match_param, rule_spec->match_value, 767 outer_headers.dmac_47_16); 768 ether_addr_copy(dmac_v, addr); 769 dmac_c = MLX5_ADDR_OF(fte_match_param, rule_spec->match_criteria, 770 outer_headers.dmac_47_16); 771 eth_broadcast_addr(dmac_c); 772 773 if (vlan) { 774 if (vlan->pkt_reformat_pop) { 775 flow_act.action |= MLX5_FLOW_CONTEXT_ACTION_PACKET_REFORMAT; 776 flow_act.pkt_reformat = vlan->pkt_reformat_pop; 777 } 778 779 if (bridge->vlan_proto == ETH_P_8021Q) { 780 MLX5_SET_TO_ONES(fte_match_param, rule_spec->match_criteria, 781 outer_headers.cvlan_tag); 782 MLX5_SET_TO_ONES(fte_match_param, rule_spec->match_value, 783 outer_headers.cvlan_tag); 784 } else if (bridge->vlan_proto == ETH_P_8021AD) { 785 MLX5_SET_TO_ONES(fte_match_param, rule_spec->match_criteria, 786 outer_headers.svlan_tag); 787 MLX5_SET_TO_ONES(fte_match_param, rule_spec->match_value, 788 outer_headers.svlan_tag); 789 } 790 MLX5_SET_TO_ONES(fte_match_param, rule_spec->match_criteria, 791 outer_headers.first_vid); 792 MLX5_SET(fte_match_param, rule_spec->match_value, outer_headers.first_vid, 793 vlan->vid); 794 } 795 796 if (MLX5_CAP_ESW(bridge->br_offloads->esw->dev, merged_eswitch)) { 797 dest.vport.flags = MLX5_FLOW_DEST_VPORT_VHCA_ID; 798 dest.vport.vhca_id = esw_owner_vhca_id; 799 } 800 handle = mlx5_add_flow_rules(bridge->egress_ft, rule_spec, &flow_act, &dest, 1); 801 802 kvfree(rule_spec); 803 return handle; 804} 805 806static struct mlx5_flow_handle * 807mlx5_esw_bridge_egress_miss_flow_create(struct mlx5_flow_table *egress_ft, 808 struct mlx5_flow_table *skip_ft, 809 struct mlx5_pkt_reformat *pkt_reformat) 810{ 811 struct mlx5_flow_destination dest = { 812 .type = MLX5_FLOW_DESTINATION_TYPE_FLOW_TABLE, 813 .ft = skip_ft, 814 }; 815 struct mlx5_flow_act flow_act = { 816 .action = MLX5_FLOW_CONTEXT_ACTION_FWD_DEST | 817 MLX5_FLOW_CONTEXT_ACTION_PACKET_REFORMAT, 818 .flags = FLOW_ACT_NO_APPEND, 819 .pkt_reformat = pkt_reformat, 820 }; 821 struct mlx5_flow_spec *rule_spec; 822 struct mlx5_flow_handle *handle; 823 824 rule_spec = kvzalloc(sizeof(*rule_spec), GFP_KERNEL); 825 if (!rule_spec) 826 return ERR_PTR(-ENOMEM); 827 828 rule_spec->match_criteria_enable = MLX5_MATCH_MISC_PARAMETERS_2; 829 830 MLX5_SET(fte_match_param, rule_spec->match_criteria, 831 misc_parameters_2.metadata_reg_c_1, ESW_TUN_MASK); 832 MLX5_SET(fte_match_param, rule_spec->match_value, misc_parameters_2.metadata_reg_c_1, 833 ESW_TUN_BRIDGE_INGRESS_PUSH_VLAN_MARK); 834 835 handle = mlx5_add_flow_rules(egress_ft, rule_spec, &flow_act, &dest, 1); 836 837 kvfree(rule_spec); 838 return handle; 839} 840 841static struct mlx5_esw_bridge *mlx5_esw_bridge_create(struct net_device *br_netdev, 842 struct mlx5_esw_bridge_offloads *br_offloads) 843{ 844 struct mlx5_esw_bridge *bridge; 845 int err; 846 847 bridge = kvzalloc(sizeof(*bridge), GFP_KERNEL); 848 if (!bridge) 849 return ERR_PTR(-ENOMEM); 850 851 bridge->br_offloads = br_offloads; 852 err = mlx5_esw_bridge_egress_table_init(br_offloads, bridge); 853 if (err) 854 goto err_egress_tbl; 855 856 err = rhashtable_init(&bridge->fdb_ht, &fdb_ht_params); 857 if (err) 858 goto err_fdb_ht; 859 860 err = mlx5_esw_bridge_mdb_init(bridge); 861 if (err) 862 goto err_mdb_ht; 863 864 INIT_LIST_HEAD(&bridge->fdb_list); 865 bridge->ifindex = br_netdev->ifindex; 866 bridge->refcnt = 1; 867 bridge->ageing_time = clock_t_to_jiffies(BR_DEFAULT_AGEING_TIME); 868 bridge->vlan_proto = ETH_P_8021Q; 869 list_add(&bridge->list, &br_offloads->bridges); 870 mlx5_esw_bridge_debugfs_init(br_netdev, bridge); 871 872 return bridge; 873 874err_mdb_ht: 875 rhashtable_destroy(&bridge->fdb_ht); 876err_fdb_ht: 877 mlx5_esw_bridge_egress_table_cleanup(bridge); 878err_egress_tbl: 879 kvfree(bridge); 880 return ERR_PTR(err); 881} 882 883static void mlx5_esw_bridge_get(struct mlx5_esw_bridge *bridge) 884{ 885 bridge->refcnt++; 886} 887 888static void mlx5_esw_bridge_put(struct mlx5_esw_bridge_offloads *br_offloads, 889 struct mlx5_esw_bridge *bridge) 890{ 891 if (--bridge->refcnt) 892 return; 893 894 mlx5_esw_bridge_debugfs_cleanup(bridge); 895 mlx5_esw_bridge_egress_table_cleanup(bridge); 896 mlx5_esw_bridge_mcast_disable(bridge); 897 list_del(&bridge->list); 898 mlx5_esw_bridge_mdb_cleanup(bridge); 899 rhashtable_destroy(&bridge->fdb_ht); 900 kvfree(bridge); 901 902 if (list_empty(&br_offloads->bridges)) 903 mlx5_esw_bridge_ingress_table_cleanup(br_offloads); 904} 905 906static struct mlx5_esw_bridge * 907mlx5_esw_bridge_lookup(struct net_device *br_netdev, struct mlx5_esw_bridge_offloads *br_offloads) 908{ 909 struct mlx5_esw_bridge *bridge; 910 911 ASSERT_RTNL(); 912 913 list_for_each_entry(bridge, &br_offloads->bridges, list) { 914 if (bridge->ifindex == br_netdev->ifindex) { 915 mlx5_esw_bridge_get(bridge); 916 return bridge; 917 } 918 } 919 920 if (!br_offloads->ingress_ft) { 921 int err = mlx5_esw_bridge_ingress_table_init(br_offloads); 922 923 if (err) 924 return ERR_PTR(err); 925 } 926 927 bridge = mlx5_esw_bridge_create(br_netdev, br_offloads); 928 if (IS_ERR(bridge) && list_empty(&br_offloads->bridges)) 929 mlx5_esw_bridge_ingress_table_cleanup(br_offloads); 930 return bridge; 931} 932 933static unsigned long mlx5_esw_bridge_port_key_from_data(u16 vport_num, u16 esw_owner_vhca_id) 934{ 935 return vport_num | (unsigned long)esw_owner_vhca_id << sizeof(vport_num) * BITS_PER_BYTE; 936} 937 938unsigned long mlx5_esw_bridge_port_key(struct mlx5_esw_bridge_port *port) 939{ 940 return mlx5_esw_bridge_port_key_from_data(port->vport_num, port->esw_owner_vhca_id); 941} 942 943static int mlx5_esw_bridge_port_insert(struct mlx5_esw_bridge_port *port, 944 struct mlx5_esw_bridge_offloads *br_offloads) 945{ 946 return xa_insert(&br_offloads->ports, mlx5_esw_bridge_port_key(port), port, GFP_KERNEL); 947} 948 949static struct mlx5_esw_bridge_port * 950mlx5_esw_bridge_port_lookup(u16 vport_num, u16 esw_owner_vhca_id, 951 struct mlx5_esw_bridge_offloads *br_offloads) 952{ 953 return xa_load(&br_offloads->ports, mlx5_esw_bridge_port_key_from_data(vport_num, 954 esw_owner_vhca_id)); 955} 956 957static void mlx5_esw_bridge_port_erase(struct mlx5_esw_bridge_port *port, 958 struct mlx5_esw_bridge_offloads *br_offloads) 959{ 960 xa_erase(&br_offloads->ports, mlx5_esw_bridge_port_key(port)); 961} 962 963static struct mlx5_esw_bridge * 964mlx5_esw_bridge_from_port_lookup(u16 vport_num, u16 esw_owner_vhca_id, 965 struct mlx5_esw_bridge_offloads *br_offloads) 966{ 967 struct mlx5_esw_bridge_port *port; 968 969 port = mlx5_esw_bridge_port_lookup(vport_num, esw_owner_vhca_id, br_offloads); 970 if (!port) 971 return NULL; 972 973 return port->bridge; 974} 975 976static void mlx5_esw_bridge_fdb_entry_refresh(struct mlx5_esw_bridge_fdb_entry *entry) 977{ 978 trace_mlx5_esw_bridge_fdb_entry_refresh(entry); 979 980 mlx5_esw_bridge_fdb_offload_notify(entry->dev, entry->key.addr, 981 entry->key.vid, 982 SWITCHDEV_FDB_ADD_TO_BRIDGE); 983} 984 985static void 986mlx5_esw_bridge_fdb_entry_cleanup(struct mlx5_esw_bridge_fdb_entry *entry, 987 struct mlx5_esw_bridge *bridge) 988{ 989 trace_mlx5_esw_bridge_fdb_entry_cleanup(entry); 990 991 rhashtable_remove_fast(&bridge->fdb_ht, &entry->ht_node, fdb_ht_params); 992 mlx5_del_flow_rules(entry->egress_handle); 993 if (entry->filter_handle) 994 mlx5_del_flow_rules(entry->filter_handle); 995 mlx5_del_flow_rules(entry->ingress_handle); 996 mlx5_fc_destroy(bridge->br_offloads->esw->dev, entry->ingress_counter); 997 list_del(&entry->vlan_list); 998 list_del(&entry->list); 999 kvfree(entry); 1000} 1001 1002static void 1003mlx5_esw_bridge_fdb_entry_notify_and_cleanup(struct mlx5_esw_bridge_fdb_entry *entry, 1004 struct mlx5_esw_bridge *bridge) 1005{ 1006 mlx5_esw_bridge_fdb_del_notify(entry); 1007 mlx5_esw_bridge_fdb_entry_cleanup(entry, bridge); 1008} 1009 1010static void mlx5_esw_bridge_fdb_flush(struct mlx5_esw_bridge *bridge) 1011{ 1012 struct mlx5_esw_bridge_fdb_entry *entry, *tmp; 1013 1014 list_for_each_entry_safe(entry, tmp, &bridge->fdb_list, list) 1015 mlx5_esw_bridge_fdb_entry_notify_and_cleanup(entry, bridge); 1016} 1017 1018static struct mlx5_esw_bridge_vlan * 1019mlx5_esw_bridge_vlan_lookup(u16 vid, struct mlx5_esw_bridge_port *port) 1020{ 1021 return xa_load(&port->vlans, vid); 1022} 1023 1024static int 1025mlx5_esw_bridge_vlan_push_create(u16 vlan_proto, struct mlx5_esw_bridge_vlan *vlan, 1026 struct mlx5_eswitch *esw) 1027{ 1028 struct { 1029 __be16 h_vlan_proto; 1030 __be16 h_vlan_TCI; 1031 } vlan_hdr = { htons(vlan_proto), htons(vlan->vid) }; 1032 struct mlx5_pkt_reformat_params reformat_params = {}; 1033 struct mlx5_pkt_reformat *pkt_reformat; 1034 1035 if (!BIT(MLX5_CAP_ESW_FLOWTABLE_FDB(esw->dev, reformat_insert)) || 1036 MLX5_CAP_GEN_2(esw->dev, max_reformat_insert_size) < sizeof(vlan_hdr) || 1037 MLX5_CAP_GEN_2(esw->dev, max_reformat_insert_offset) < 1038 offsetof(struct vlan_ethhdr, h_vlan_proto)) { 1039 esw_warn(esw->dev, "Packet reformat INSERT_HEADER is not supported\n"); 1040 return -EOPNOTSUPP; 1041 } 1042 1043 reformat_params.type = MLX5_REFORMAT_TYPE_INSERT_HDR; 1044 reformat_params.param_0 = MLX5_REFORMAT_CONTEXT_ANCHOR_MAC_START; 1045 reformat_params.param_1 = offsetof(struct vlan_ethhdr, h_vlan_proto); 1046 reformat_params.size = sizeof(vlan_hdr); 1047 reformat_params.data = &vlan_hdr; 1048 pkt_reformat = mlx5_packet_reformat_alloc(esw->dev, 1049 &reformat_params, 1050 MLX5_FLOW_NAMESPACE_FDB); 1051 if (IS_ERR(pkt_reformat)) { 1052 esw_warn(esw->dev, "Failed to alloc packet reformat INSERT_HEADER (err=%pe)\n", 1053 pkt_reformat); 1054 return PTR_ERR(pkt_reformat); 1055 } 1056 1057 vlan->pkt_reformat_push = pkt_reformat; 1058 return 0; 1059} 1060 1061static void 1062mlx5_esw_bridge_vlan_push_cleanup(struct mlx5_esw_bridge_vlan *vlan, struct mlx5_eswitch *esw) 1063{ 1064 mlx5_packet_reformat_dealloc(esw->dev, vlan->pkt_reformat_push); 1065 vlan->pkt_reformat_push = NULL; 1066} 1067 1068static int 1069mlx5_esw_bridge_vlan_pop_create(struct mlx5_esw_bridge_vlan *vlan, struct mlx5_eswitch *esw) 1070{ 1071 struct mlx5_pkt_reformat *pkt_reformat; 1072 1073 if (!mlx5_esw_bridge_pkt_reformat_vlan_pop_supported(esw)) { 1074 esw_warn(esw->dev, "Packet reformat REMOVE_HEADER is not supported\n"); 1075 return -EOPNOTSUPP; 1076 } 1077 1078 pkt_reformat = mlx5_esw_bridge_pkt_reformat_vlan_pop_create(esw); 1079 if (IS_ERR(pkt_reformat)) { 1080 esw_warn(esw->dev, "Failed to alloc packet reformat REMOVE_HEADER (err=%pe)\n", 1081 pkt_reformat); 1082 return PTR_ERR(pkt_reformat); 1083 } 1084 1085 vlan->pkt_reformat_pop = pkt_reformat; 1086 return 0; 1087} 1088 1089static void 1090mlx5_esw_bridge_vlan_pop_cleanup(struct mlx5_esw_bridge_vlan *vlan, struct mlx5_eswitch *esw) 1091{ 1092 mlx5_packet_reformat_dealloc(esw->dev, vlan->pkt_reformat_pop); 1093 vlan->pkt_reformat_pop = NULL; 1094} 1095 1096static int 1097mlx5_esw_bridge_vlan_push_mark_create(struct mlx5_esw_bridge_vlan *vlan, struct mlx5_eswitch *esw) 1098{ 1099 u8 action[MLX5_UN_SZ_BYTES(set_add_copy_action_in_auto)] = {}; 1100 struct mlx5_modify_hdr *pkt_mod_hdr; 1101 1102 MLX5_SET(set_action_in, action, action_type, MLX5_ACTION_TYPE_SET); 1103 MLX5_SET(set_action_in, action, field, MLX5_ACTION_IN_FIELD_METADATA_REG_C_1); 1104 MLX5_SET(set_action_in, action, offset, 8); 1105 MLX5_SET(set_action_in, action, length, ESW_TUN_OPTS_BITS + ESW_TUN_ID_BITS); 1106 MLX5_SET(set_action_in, action, data, ESW_TUN_BRIDGE_INGRESS_PUSH_VLAN); 1107 1108 pkt_mod_hdr = mlx5_modify_header_alloc(esw->dev, MLX5_FLOW_NAMESPACE_FDB, 1, action); 1109 if (IS_ERR(pkt_mod_hdr)) 1110 return PTR_ERR(pkt_mod_hdr); 1111 1112 vlan->pkt_mod_hdr_push_mark = pkt_mod_hdr; 1113 return 0; 1114} 1115 1116static void 1117mlx5_esw_bridge_vlan_push_mark_cleanup(struct mlx5_esw_bridge_vlan *vlan, struct mlx5_eswitch *esw) 1118{ 1119 mlx5_modify_header_dealloc(esw->dev, vlan->pkt_mod_hdr_push_mark); 1120 vlan->pkt_mod_hdr_push_mark = NULL; 1121} 1122 1123static int 1124mlx5_esw_bridge_vlan_push_pop_fhs_create(u16 vlan_proto, struct mlx5_esw_bridge_port *port, 1125 struct mlx5_esw_bridge_vlan *vlan) 1126{ 1127 return mlx5_esw_bridge_vlan_mcast_init(vlan_proto, port, vlan); 1128} 1129 1130static void 1131mlx5_esw_bridge_vlan_push_pop_fhs_cleanup(struct mlx5_esw_bridge_vlan *vlan) 1132{ 1133 mlx5_esw_bridge_vlan_mcast_cleanup(vlan); 1134} 1135 1136static int 1137mlx5_esw_bridge_vlan_push_pop_create(u16 vlan_proto, u16 flags, struct mlx5_esw_bridge_port *port, 1138 struct mlx5_esw_bridge_vlan *vlan, struct mlx5_eswitch *esw) 1139{ 1140 int err; 1141 1142 if (flags & BRIDGE_VLAN_INFO_PVID) { 1143 err = mlx5_esw_bridge_vlan_push_create(vlan_proto, vlan, esw); 1144 if (err) 1145 return err; 1146 1147 err = mlx5_esw_bridge_vlan_push_mark_create(vlan, esw); 1148 if (err) 1149 goto err_vlan_push_mark; 1150 } 1151 1152 if (flags & BRIDGE_VLAN_INFO_UNTAGGED) { 1153 err = mlx5_esw_bridge_vlan_pop_create(vlan, esw); 1154 if (err) 1155 goto err_vlan_pop; 1156 1157 err = mlx5_esw_bridge_vlan_push_pop_fhs_create(vlan_proto, port, vlan); 1158 if (err) 1159 goto err_vlan_pop_fhs; 1160 } 1161 1162 return 0; 1163 1164err_vlan_pop_fhs: 1165 mlx5_esw_bridge_vlan_pop_cleanup(vlan, esw); 1166err_vlan_pop: 1167 if (vlan->pkt_mod_hdr_push_mark) 1168 mlx5_esw_bridge_vlan_push_mark_cleanup(vlan, esw); 1169err_vlan_push_mark: 1170 if (vlan->pkt_reformat_push) 1171 mlx5_esw_bridge_vlan_push_cleanup(vlan, esw); 1172 return err; 1173} 1174 1175static struct mlx5_esw_bridge_vlan * 1176mlx5_esw_bridge_vlan_create(u16 vlan_proto, u16 vid, u16 flags, struct mlx5_esw_bridge_port *port, 1177 struct mlx5_eswitch *esw) 1178{ 1179 struct mlx5_esw_bridge_vlan *vlan; 1180 int err; 1181 1182 vlan = kvzalloc(sizeof(*vlan), GFP_KERNEL); 1183 if (!vlan) 1184 return ERR_PTR(-ENOMEM); 1185 1186 vlan->vid = vid; 1187 vlan->flags = flags; 1188 INIT_LIST_HEAD(&vlan->fdb_list); 1189 1190 err = mlx5_esw_bridge_vlan_push_pop_create(vlan_proto, flags, port, vlan, esw); 1191 if (err) 1192 goto err_vlan_push_pop; 1193 1194 err = xa_insert(&port->vlans, vid, vlan, GFP_KERNEL); 1195 if (err) 1196 goto err_xa_insert; 1197 1198 trace_mlx5_esw_bridge_vlan_create(vlan); 1199 return vlan; 1200 1201err_xa_insert: 1202 if (vlan->mcast_handle) 1203 mlx5_esw_bridge_vlan_push_pop_fhs_cleanup(vlan); 1204 if (vlan->pkt_reformat_pop) 1205 mlx5_esw_bridge_vlan_pop_cleanup(vlan, esw); 1206 if (vlan->pkt_mod_hdr_push_mark) 1207 mlx5_esw_bridge_vlan_push_mark_cleanup(vlan, esw); 1208 if (vlan->pkt_reformat_push) 1209 mlx5_esw_bridge_vlan_push_cleanup(vlan, esw); 1210err_vlan_push_pop: 1211 kvfree(vlan); 1212 return ERR_PTR(err); 1213} 1214 1215static void mlx5_esw_bridge_vlan_erase(struct mlx5_esw_bridge_port *port, 1216 struct mlx5_esw_bridge_vlan *vlan) 1217{ 1218 xa_erase(&port->vlans, vlan->vid); 1219} 1220 1221static void mlx5_esw_bridge_vlan_flush(struct mlx5_esw_bridge_port *port, 1222 struct mlx5_esw_bridge_vlan *vlan, 1223 struct mlx5_esw_bridge *bridge) 1224{ 1225 struct mlx5_eswitch *esw = bridge->br_offloads->esw; 1226 struct mlx5_esw_bridge_fdb_entry *entry, *tmp; 1227 1228 list_for_each_entry_safe(entry, tmp, &vlan->fdb_list, vlan_list) 1229 mlx5_esw_bridge_fdb_entry_notify_and_cleanup(entry, bridge); 1230 mlx5_esw_bridge_port_mdb_vlan_flush(port, vlan); 1231 1232 if (vlan->mcast_handle) 1233 mlx5_esw_bridge_vlan_push_pop_fhs_cleanup(vlan); 1234 if (vlan->pkt_reformat_pop) 1235 mlx5_esw_bridge_vlan_pop_cleanup(vlan, esw); 1236 if (vlan->pkt_mod_hdr_push_mark) 1237 mlx5_esw_bridge_vlan_push_mark_cleanup(vlan, esw); 1238 if (vlan->pkt_reformat_push) 1239 mlx5_esw_bridge_vlan_push_cleanup(vlan, esw); 1240} 1241 1242static void mlx5_esw_bridge_vlan_cleanup(struct mlx5_esw_bridge_port *port, 1243 struct mlx5_esw_bridge_vlan *vlan, 1244 struct mlx5_esw_bridge *bridge) 1245{ 1246 trace_mlx5_esw_bridge_vlan_cleanup(vlan); 1247 mlx5_esw_bridge_vlan_flush(port, vlan, bridge); 1248 mlx5_esw_bridge_vlan_erase(port, vlan); 1249 kvfree(vlan); 1250} 1251 1252static void mlx5_esw_bridge_port_vlans_flush(struct mlx5_esw_bridge_port *port, 1253 struct mlx5_esw_bridge *bridge) 1254{ 1255 struct mlx5_esw_bridge_vlan *vlan; 1256 unsigned long index; 1257 1258 xa_for_each(&port->vlans, index, vlan) 1259 mlx5_esw_bridge_vlan_cleanup(port, vlan, bridge); 1260} 1261 1262static int mlx5_esw_bridge_port_vlans_recreate(struct mlx5_esw_bridge_port *port, 1263 struct mlx5_esw_bridge *bridge) 1264{ 1265 struct mlx5_esw_bridge_offloads *br_offloads = bridge->br_offloads; 1266 struct mlx5_esw_bridge_vlan *vlan; 1267 unsigned long i; 1268 int err; 1269 1270 xa_for_each(&port->vlans, i, vlan) { 1271 mlx5_esw_bridge_vlan_flush(port, vlan, bridge); 1272 err = mlx5_esw_bridge_vlan_push_pop_create(bridge->vlan_proto, vlan->flags, port, 1273 vlan, br_offloads->esw); 1274 if (err) { 1275 esw_warn(br_offloads->esw->dev, 1276 "Failed to create VLAN=%u(proto=%x) push/pop actions (vport=%u,err=%d)\n", 1277 vlan->vid, bridge->vlan_proto, port->vport_num, 1278 err); 1279 return err; 1280 } 1281 } 1282 1283 return 0; 1284} 1285 1286static int 1287mlx5_esw_bridge_vlans_recreate(struct mlx5_esw_bridge *bridge) 1288{ 1289 struct mlx5_esw_bridge_offloads *br_offloads = bridge->br_offloads; 1290 struct mlx5_esw_bridge_port *port; 1291 unsigned long i; 1292 int err; 1293 1294 xa_for_each(&br_offloads->ports, i, port) { 1295 if (port->bridge != bridge) 1296 continue; 1297 1298 err = mlx5_esw_bridge_port_vlans_recreate(port, bridge); 1299 if (err) 1300 return err; 1301 } 1302 1303 return 0; 1304} 1305 1306static struct mlx5_esw_bridge_vlan * 1307mlx5_esw_bridge_port_vlan_lookup(u16 vid, u16 vport_num, u16 esw_owner_vhca_id, 1308 struct mlx5_esw_bridge *bridge, struct mlx5_eswitch *esw) 1309{ 1310 struct mlx5_esw_bridge_port *port; 1311 struct mlx5_esw_bridge_vlan *vlan; 1312 1313 port = mlx5_esw_bridge_port_lookup(vport_num, esw_owner_vhca_id, bridge->br_offloads); 1314 if (!port) { 1315 /* FDB is added asynchronously on wq while port might have been deleted 1316 * concurrently. Report on 'info' logging level and skip the FDB offload. 1317 */ 1318 esw_info(esw->dev, "Failed to lookup bridge port (vport=%u)\n", vport_num); 1319 return ERR_PTR(-EINVAL); 1320 } 1321 1322 vlan = mlx5_esw_bridge_vlan_lookup(vid, port); 1323 if (!vlan) { 1324 /* FDB is added asynchronously on wq while vlan might have been deleted 1325 * concurrently. Report on 'info' logging level and skip the FDB offload. 1326 */ 1327 esw_info(esw->dev, "Failed to lookup bridge port vlan metadata (vport=%u)\n", 1328 vport_num); 1329 return ERR_PTR(-EINVAL); 1330 } 1331 1332 return vlan; 1333} 1334 1335static struct mlx5_esw_bridge_fdb_entry * 1336mlx5_esw_bridge_fdb_lookup(struct mlx5_esw_bridge *bridge, 1337 const unsigned char *addr, u16 vid) 1338{ 1339 struct mlx5_esw_bridge_fdb_key key = {}; 1340 1341 ether_addr_copy(key.addr, addr); 1342 key.vid = vid; 1343 return rhashtable_lookup_fast(&bridge->fdb_ht, &key, fdb_ht_params); 1344} 1345 1346static struct mlx5_esw_bridge_fdb_entry * 1347mlx5_esw_bridge_fdb_entry_init(struct net_device *dev, u16 vport_num, u16 esw_owner_vhca_id, 1348 const unsigned char *addr, u16 vid, bool added_by_user, bool peer, 1349 struct mlx5_eswitch *esw, struct mlx5_esw_bridge *bridge) 1350{ 1351 struct mlx5_esw_bridge_vlan *vlan = NULL; 1352 struct mlx5_esw_bridge_fdb_entry *entry; 1353 struct mlx5_flow_handle *handle; 1354 struct mlx5_fc *counter; 1355 int err; 1356 1357 if (bridge->flags & MLX5_ESW_BRIDGE_VLAN_FILTERING_FLAG && vid) { 1358 vlan = mlx5_esw_bridge_port_vlan_lookup(vid, vport_num, esw_owner_vhca_id, bridge, 1359 esw); 1360 if (IS_ERR(vlan)) 1361 return ERR_CAST(vlan); 1362 } 1363 1364 entry = mlx5_esw_bridge_fdb_lookup(bridge, addr, vid); 1365 if (entry) 1366 mlx5_esw_bridge_fdb_entry_notify_and_cleanup(entry, bridge); 1367 1368 entry = kvzalloc(sizeof(*entry), GFP_KERNEL); 1369 if (!entry) 1370 return ERR_PTR(-ENOMEM); 1371 1372 ether_addr_copy(entry->key.addr, addr); 1373 entry->key.vid = vid; 1374 entry->dev = dev; 1375 entry->vport_num = vport_num; 1376 entry->esw_owner_vhca_id = esw_owner_vhca_id; 1377 entry->lastuse = jiffies; 1378 if (added_by_user) 1379 entry->flags |= MLX5_ESW_BRIDGE_FLAG_ADDED_BY_USER; 1380 if (peer) 1381 entry->flags |= MLX5_ESW_BRIDGE_FLAG_PEER; 1382 1383 counter = mlx5_fc_create(esw->dev, true); 1384 if (IS_ERR(counter)) { 1385 err = PTR_ERR(counter); 1386 goto err_ingress_fc_create; 1387 } 1388 entry->ingress_counter = counter; 1389 1390 handle = peer ? 1391 mlx5_esw_bridge_ingress_flow_peer_create(vport_num, esw_owner_vhca_id, 1392 addr, vlan, counter, bridge) : 1393 mlx5_esw_bridge_ingress_flow_create(vport_num, addr, vlan, 1394 counter, bridge); 1395 if (IS_ERR(handle)) { 1396 err = PTR_ERR(handle); 1397 esw_warn(esw->dev, "Failed to create ingress flow(vport=%u,err=%d,peer=%d)\n", 1398 vport_num, err, peer); 1399 goto err_ingress_flow_create; 1400 } 1401 entry->ingress_handle = handle; 1402 1403 if (bridge->flags & MLX5_ESW_BRIDGE_VLAN_FILTERING_FLAG) { 1404 handle = mlx5_esw_bridge_ingress_filter_flow_create(vport_num, addr, bridge); 1405 if (IS_ERR(handle)) { 1406 err = PTR_ERR(handle); 1407 esw_warn(esw->dev, "Failed to create ingress filter(vport=%u,err=%d)\n", 1408 vport_num, err); 1409 goto err_ingress_filter_flow_create; 1410 } 1411 entry->filter_handle = handle; 1412 } 1413 1414 handle = mlx5_esw_bridge_egress_flow_create(vport_num, esw_owner_vhca_id, addr, vlan, 1415 bridge); 1416 if (IS_ERR(handle)) { 1417 err = PTR_ERR(handle); 1418 esw_warn(esw->dev, "Failed to create egress flow(vport=%u,err=%d)\n", 1419 vport_num, err); 1420 goto err_egress_flow_create; 1421 } 1422 entry->egress_handle = handle; 1423 1424 err = rhashtable_insert_fast(&bridge->fdb_ht, &entry->ht_node, fdb_ht_params); 1425 if (err) { 1426 esw_warn(esw->dev, "Failed to insert FDB flow(vport=%u,err=%d)\n", vport_num, err); 1427 goto err_ht_init; 1428 } 1429 1430 if (vlan) 1431 list_add(&entry->vlan_list, &vlan->fdb_list); 1432 else 1433 INIT_LIST_HEAD(&entry->vlan_list); 1434 list_add(&entry->list, &bridge->fdb_list); 1435 1436 trace_mlx5_esw_bridge_fdb_entry_init(entry); 1437 return entry; 1438 1439err_ht_init: 1440 mlx5_del_flow_rules(entry->egress_handle); 1441err_egress_flow_create: 1442 if (entry->filter_handle) 1443 mlx5_del_flow_rules(entry->filter_handle); 1444err_ingress_filter_flow_create: 1445 mlx5_del_flow_rules(entry->ingress_handle); 1446err_ingress_flow_create: 1447 mlx5_fc_destroy(esw->dev, entry->ingress_counter); 1448err_ingress_fc_create: 1449 kvfree(entry); 1450 return ERR_PTR(err); 1451} 1452 1453int mlx5_esw_bridge_ageing_time_set(u16 vport_num, u16 esw_owner_vhca_id, unsigned long ageing_time, 1454 struct mlx5_esw_bridge_offloads *br_offloads) 1455{ 1456 struct mlx5_esw_bridge *bridge; 1457 1458 bridge = mlx5_esw_bridge_from_port_lookup(vport_num, esw_owner_vhca_id, br_offloads); 1459 if (!bridge) 1460 return -EINVAL; 1461 1462 bridge->ageing_time = clock_t_to_jiffies(ageing_time); 1463 return 0; 1464} 1465 1466int mlx5_esw_bridge_vlan_filtering_set(u16 vport_num, u16 esw_owner_vhca_id, bool enable, 1467 struct mlx5_esw_bridge_offloads *br_offloads) 1468{ 1469 struct mlx5_esw_bridge *bridge; 1470 bool filtering; 1471 1472 bridge = mlx5_esw_bridge_from_port_lookup(vport_num, esw_owner_vhca_id, br_offloads); 1473 if (!bridge) 1474 return -EINVAL; 1475 1476 filtering = bridge->flags & MLX5_ESW_BRIDGE_VLAN_FILTERING_FLAG; 1477 if (filtering == enable) 1478 return 0; 1479 1480 mlx5_esw_bridge_fdb_flush(bridge); 1481 mlx5_esw_bridge_mdb_flush(bridge); 1482 if (enable) 1483 bridge->flags |= MLX5_ESW_BRIDGE_VLAN_FILTERING_FLAG; 1484 else 1485 bridge->flags &= ~MLX5_ESW_BRIDGE_VLAN_FILTERING_FLAG; 1486 1487 return 0; 1488} 1489 1490int mlx5_esw_bridge_vlan_proto_set(u16 vport_num, u16 esw_owner_vhca_id, u16 proto, 1491 struct mlx5_esw_bridge_offloads *br_offloads) 1492{ 1493 struct mlx5_esw_bridge *bridge; 1494 1495 bridge = mlx5_esw_bridge_from_port_lookup(vport_num, esw_owner_vhca_id, 1496 br_offloads); 1497 if (!bridge) 1498 return -EINVAL; 1499 1500 if (bridge->vlan_proto == proto) 1501 return 0; 1502 if (proto != ETH_P_8021Q && proto != ETH_P_8021AD) { 1503 esw_warn(br_offloads->esw->dev, "Can't set unsupported VLAN protocol %x", proto); 1504 return -EOPNOTSUPP; 1505 } 1506 1507 mlx5_esw_bridge_fdb_flush(bridge); 1508 mlx5_esw_bridge_mdb_flush(bridge); 1509 bridge->vlan_proto = proto; 1510 mlx5_esw_bridge_vlans_recreate(bridge); 1511 1512 return 0; 1513} 1514 1515int mlx5_esw_bridge_mcast_set(u16 vport_num, u16 esw_owner_vhca_id, bool enable, 1516 struct mlx5_esw_bridge_offloads *br_offloads) 1517{ 1518 struct mlx5_eswitch *esw = br_offloads->esw; 1519 struct mlx5_esw_bridge *bridge; 1520 int err = 0; 1521 bool mcast; 1522 1523 if (!(MLX5_CAP_ESW_FLOWTABLE((esw)->dev, fdb_multi_path_any_table) || 1524 MLX5_CAP_ESW_FLOWTABLE((esw)->dev, fdb_multi_path_any_table_limit_regc)) || 1525 !MLX5_CAP_ESW_FLOWTABLE((esw)->dev, fdb_uplink_hairpin) || 1526 !MLX5_CAP_ESW_FLOWTABLE_FDB((esw)->dev, ignore_flow_level)) 1527 return -EOPNOTSUPP; 1528 1529 bridge = mlx5_esw_bridge_from_port_lookup(vport_num, esw_owner_vhca_id, br_offloads); 1530 if (!bridge) 1531 return -EINVAL; 1532 1533 mcast = bridge->flags & MLX5_ESW_BRIDGE_MCAST_FLAG; 1534 if (mcast == enable) 1535 return 0; 1536 1537 if (enable) 1538 err = mlx5_esw_bridge_mcast_enable(bridge); 1539 else 1540 mlx5_esw_bridge_mcast_disable(bridge); 1541 1542 return err; 1543} 1544 1545static int mlx5_esw_bridge_vport_init(u16 vport_num, u16 esw_owner_vhca_id, u16 flags, 1546 struct mlx5_esw_bridge_offloads *br_offloads, 1547 struct mlx5_esw_bridge *bridge) 1548{ 1549 struct mlx5_eswitch *esw = br_offloads->esw; 1550 struct mlx5_esw_bridge_port *port; 1551 int err; 1552 1553 port = kvzalloc(sizeof(*port), GFP_KERNEL); 1554 if (!port) 1555 return -ENOMEM; 1556 1557 port->vport_num = vport_num; 1558 port->esw_owner_vhca_id = esw_owner_vhca_id; 1559 port->bridge = bridge; 1560 port->flags |= flags; 1561 xa_init(&port->vlans); 1562 1563 err = mlx5_esw_bridge_port_mcast_init(port); 1564 if (err) { 1565 esw_warn(esw->dev, 1566 "Failed to initialize port multicast (vport=%u,esw_owner_vhca_id=%u,err=%d)\n", 1567 port->vport_num, port->esw_owner_vhca_id, err); 1568 goto err_port_mcast; 1569 } 1570 1571 err = mlx5_esw_bridge_port_insert(port, br_offloads); 1572 if (err) { 1573 esw_warn(esw->dev, 1574 "Failed to insert port metadata (vport=%u,esw_owner_vhca_id=%u,err=%d)\n", 1575 port->vport_num, port->esw_owner_vhca_id, err); 1576 goto err_port_insert; 1577 } 1578 trace_mlx5_esw_bridge_vport_init(port); 1579 1580 return 0; 1581 1582err_port_insert: 1583 mlx5_esw_bridge_port_mcast_cleanup(port); 1584err_port_mcast: 1585 kvfree(port); 1586 return err; 1587} 1588 1589static int mlx5_esw_bridge_vport_cleanup(struct mlx5_esw_bridge_offloads *br_offloads, 1590 struct mlx5_esw_bridge_port *port) 1591{ 1592 u16 vport_num = port->vport_num, esw_owner_vhca_id = port->esw_owner_vhca_id; 1593 struct mlx5_esw_bridge *bridge = port->bridge; 1594 struct mlx5_esw_bridge_fdb_entry *entry, *tmp; 1595 1596 list_for_each_entry_safe(entry, tmp, &bridge->fdb_list, list) 1597 if (entry->vport_num == vport_num && entry->esw_owner_vhca_id == esw_owner_vhca_id) 1598 mlx5_esw_bridge_fdb_entry_cleanup(entry, bridge); 1599 1600 trace_mlx5_esw_bridge_vport_cleanup(port); 1601 mlx5_esw_bridge_port_vlans_flush(port, bridge); 1602 mlx5_esw_bridge_port_mcast_cleanup(port); 1603 mlx5_esw_bridge_port_erase(port, br_offloads); 1604 kvfree(port); 1605 mlx5_esw_bridge_put(br_offloads, bridge); 1606 return 0; 1607} 1608 1609static int mlx5_esw_bridge_vport_link_with_flags(struct net_device *br_netdev, u16 vport_num, 1610 u16 esw_owner_vhca_id, u16 flags, 1611 struct mlx5_esw_bridge_offloads *br_offloads, 1612 struct netlink_ext_ack *extack) 1613{ 1614 struct mlx5_esw_bridge *bridge; 1615 int err; 1616 1617 bridge = mlx5_esw_bridge_lookup(br_netdev, br_offloads); 1618 if (IS_ERR(bridge)) { 1619 NL_SET_ERR_MSG_MOD(extack, "Error checking for existing bridge with same ifindex"); 1620 return PTR_ERR(bridge); 1621 } 1622 1623 err = mlx5_esw_bridge_vport_init(vport_num, esw_owner_vhca_id, flags, br_offloads, bridge); 1624 if (err) { 1625 NL_SET_ERR_MSG_MOD(extack, "Error initializing port"); 1626 goto err_vport; 1627 } 1628 return 0; 1629 1630err_vport: 1631 mlx5_esw_bridge_put(br_offloads, bridge); 1632 return err; 1633} 1634 1635int mlx5_esw_bridge_vport_link(struct net_device *br_netdev, u16 vport_num, u16 esw_owner_vhca_id, 1636 struct mlx5_esw_bridge_offloads *br_offloads, 1637 struct netlink_ext_ack *extack) 1638{ 1639 return mlx5_esw_bridge_vport_link_with_flags(br_netdev, vport_num, esw_owner_vhca_id, 0, 1640 br_offloads, extack); 1641} 1642 1643int mlx5_esw_bridge_vport_unlink(struct net_device *br_netdev, u16 vport_num, 1644 u16 esw_owner_vhca_id, 1645 struct mlx5_esw_bridge_offloads *br_offloads, 1646 struct netlink_ext_ack *extack) 1647{ 1648 struct mlx5_esw_bridge_port *port; 1649 int err; 1650 1651 port = mlx5_esw_bridge_port_lookup(vport_num, esw_owner_vhca_id, br_offloads); 1652 if (!port) { 1653 NL_SET_ERR_MSG_MOD(extack, "Port is not attached to any bridge"); 1654 return -EINVAL; 1655 } 1656 if (port->bridge->ifindex != br_netdev->ifindex) { 1657 NL_SET_ERR_MSG_MOD(extack, "Port is attached to another bridge"); 1658 return -EINVAL; 1659 } 1660 1661 err = mlx5_esw_bridge_vport_cleanup(br_offloads, port); 1662 if (err) 1663 NL_SET_ERR_MSG_MOD(extack, "Port cleanup failed"); 1664 return err; 1665} 1666 1667int mlx5_esw_bridge_vport_peer_link(struct net_device *br_netdev, u16 vport_num, 1668 u16 esw_owner_vhca_id, 1669 struct mlx5_esw_bridge_offloads *br_offloads, 1670 struct netlink_ext_ack *extack) 1671{ 1672 if (!MLX5_CAP_ESW(br_offloads->esw->dev, merged_eswitch)) 1673 return 0; 1674 1675 return mlx5_esw_bridge_vport_link_with_flags(br_netdev, vport_num, esw_owner_vhca_id, 1676 MLX5_ESW_BRIDGE_PORT_FLAG_PEER, 1677 br_offloads, extack); 1678} 1679 1680int mlx5_esw_bridge_vport_peer_unlink(struct net_device *br_netdev, u16 vport_num, 1681 u16 esw_owner_vhca_id, 1682 struct mlx5_esw_bridge_offloads *br_offloads, 1683 struct netlink_ext_ack *extack) 1684{ 1685 return mlx5_esw_bridge_vport_unlink(br_netdev, vport_num, esw_owner_vhca_id, br_offloads, 1686 extack); 1687} 1688 1689int mlx5_esw_bridge_port_vlan_add(u16 vport_num, u16 esw_owner_vhca_id, u16 vid, u16 flags, 1690 struct mlx5_esw_bridge_offloads *br_offloads, 1691 struct netlink_ext_ack *extack) 1692{ 1693 struct mlx5_esw_bridge_port *port; 1694 struct mlx5_esw_bridge_vlan *vlan; 1695 1696 port = mlx5_esw_bridge_port_lookup(vport_num, esw_owner_vhca_id, br_offloads); 1697 if (!port) 1698 return -EINVAL; 1699 1700 vlan = mlx5_esw_bridge_vlan_lookup(vid, port); 1701 if (vlan) { 1702 if (vlan->flags == flags) 1703 return 0; 1704 mlx5_esw_bridge_vlan_cleanup(port, vlan, port->bridge); 1705 } 1706 1707 vlan = mlx5_esw_bridge_vlan_create(port->bridge->vlan_proto, vid, flags, port, 1708 br_offloads->esw); 1709 if (IS_ERR(vlan)) { 1710 NL_SET_ERR_MSG_MOD(extack, "Failed to create VLAN entry"); 1711 return PTR_ERR(vlan); 1712 } 1713 return 0; 1714} 1715 1716void mlx5_esw_bridge_port_vlan_del(u16 vport_num, u16 esw_owner_vhca_id, u16 vid, 1717 struct mlx5_esw_bridge_offloads *br_offloads) 1718{ 1719 struct mlx5_esw_bridge_port *port; 1720 struct mlx5_esw_bridge_vlan *vlan; 1721 1722 port = mlx5_esw_bridge_port_lookup(vport_num, esw_owner_vhca_id, br_offloads); 1723 if (!port) 1724 return; 1725 1726 vlan = mlx5_esw_bridge_vlan_lookup(vid, port); 1727 if (!vlan) 1728 return; 1729 mlx5_esw_bridge_vlan_cleanup(port, vlan, port->bridge); 1730} 1731 1732void mlx5_esw_bridge_fdb_update_used(struct net_device *dev, u16 vport_num, u16 esw_owner_vhca_id, 1733 struct mlx5_esw_bridge_offloads *br_offloads, 1734 struct switchdev_notifier_fdb_info *fdb_info) 1735{ 1736 struct mlx5_esw_bridge_fdb_entry *entry; 1737 struct mlx5_esw_bridge *bridge; 1738 1739 bridge = mlx5_esw_bridge_from_port_lookup(vport_num, esw_owner_vhca_id, br_offloads); 1740 if (!bridge) 1741 return; 1742 1743 entry = mlx5_esw_bridge_fdb_lookup(bridge, fdb_info->addr, fdb_info->vid); 1744 if (!entry) { 1745 esw_debug(br_offloads->esw->dev, 1746 "FDB update entry with specified key not found (MAC=%pM,vid=%u,vport=%u)\n", 1747 fdb_info->addr, fdb_info->vid, vport_num); 1748 return; 1749 } 1750 1751 entry->lastuse = jiffies; 1752} 1753 1754void mlx5_esw_bridge_fdb_mark_deleted(struct net_device *dev, u16 vport_num, u16 esw_owner_vhca_id, 1755 struct mlx5_esw_bridge_offloads *br_offloads, 1756 struct switchdev_notifier_fdb_info *fdb_info) 1757{ 1758 struct mlx5_esw_bridge_fdb_entry *entry; 1759 struct mlx5_esw_bridge *bridge; 1760 1761 bridge = mlx5_esw_bridge_from_port_lookup(vport_num, esw_owner_vhca_id, br_offloads); 1762 if (!bridge) 1763 return; 1764 1765 entry = mlx5_esw_bridge_fdb_lookup(bridge, fdb_info->addr, fdb_info->vid); 1766 if (!entry) { 1767 esw_debug(br_offloads->esw->dev, 1768 "FDB mark deleted entry with specified key not found (MAC=%pM,vid=%u,vport=%u)\n", 1769 fdb_info->addr, fdb_info->vid, vport_num); 1770 return; 1771 } 1772 1773 entry->flags |= MLX5_ESW_BRIDGE_FLAG_DELETED; 1774} 1775 1776void mlx5_esw_bridge_fdb_create(struct net_device *dev, u16 vport_num, u16 esw_owner_vhca_id, 1777 struct mlx5_esw_bridge_offloads *br_offloads, 1778 struct switchdev_notifier_fdb_info *fdb_info) 1779{ 1780 struct mlx5_esw_bridge_fdb_entry *entry; 1781 struct mlx5_esw_bridge_port *port; 1782 struct mlx5_esw_bridge *bridge; 1783 1784 port = mlx5_esw_bridge_port_lookup(vport_num, esw_owner_vhca_id, br_offloads); 1785 if (!port) 1786 return; 1787 1788 bridge = port->bridge; 1789 entry = mlx5_esw_bridge_fdb_entry_init(dev, vport_num, esw_owner_vhca_id, fdb_info->addr, 1790 fdb_info->vid, fdb_info->added_by_user, 1791 port->flags & MLX5_ESW_BRIDGE_PORT_FLAG_PEER, 1792 br_offloads->esw, bridge); 1793 if (IS_ERR(entry)) 1794 return; 1795 1796 if (entry->flags & MLX5_ESW_BRIDGE_FLAG_ADDED_BY_USER) 1797 mlx5_esw_bridge_fdb_offload_notify(dev, entry->key.addr, entry->key.vid, 1798 SWITCHDEV_FDB_OFFLOADED); 1799 else if (!(entry->flags & MLX5_ESW_BRIDGE_FLAG_PEER)) 1800 /* Take over dynamic entries to prevent kernel bridge from aging them out. */ 1801 mlx5_esw_bridge_fdb_offload_notify(dev, entry->key.addr, entry->key.vid, 1802 SWITCHDEV_FDB_ADD_TO_BRIDGE); 1803} 1804 1805void mlx5_esw_bridge_fdb_remove(struct net_device *dev, u16 vport_num, u16 esw_owner_vhca_id, 1806 struct mlx5_esw_bridge_offloads *br_offloads, 1807 struct switchdev_notifier_fdb_info *fdb_info) 1808{ 1809 struct mlx5_eswitch *esw = br_offloads->esw; 1810 struct mlx5_esw_bridge_fdb_entry *entry; 1811 struct mlx5_esw_bridge *bridge; 1812 1813 bridge = mlx5_esw_bridge_from_port_lookup(vport_num, esw_owner_vhca_id, br_offloads); 1814 if (!bridge) 1815 return; 1816 1817 entry = mlx5_esw_bridge_fdb_lookup(bridge, fdb_info->addr, fdb_info->vid); 1818 if (!entry) { 1819 esw_debug(esw->dev, 1820 "FDB remove entry with specified key not found (MAC=%pM,vid=%u,vport=%u)\n", 1821 fdb_info->addr, fdb_info->vid, vport_num); 1822 return; 1823 } 1824 1825 mlx5_esw_bridge_fdb_entry_notify_and_cleanup(entry, bridge); 1826} 1827 1828void mlx5_esw_bridge_update(struct mlx5_esw_bridge_offloads *br_offloads) 1829{ 1830 struct mlx5_esw_bridge_fdb_entry *entry, *tmp; 1831 struct mlx5_esw_bridge *bridge; 1832 1833 list_for_each_entry(bridge, &br_offloads->bridges, list) { 1834 list_for_each_entry_safe(entry, tmp, &bridge->fdb_list, list) { 1835 unsigned long lastuse = 1836 (unsigned long)mlx5_fc_query_lastuse(entry->ingress_counter); 1837 1838 if (entry->flags & (MLX5_ESW_BRIDGE_FLAG_ADDED_BY_USER | 1839 MLX5_ESW_BRIDGE_FLAG_DELETED)) 1840 continue; 1841 1842 if (time_after(lastuse, entry->lastuse)) 1843 mlx5_esw_bridge_fdb_entry_refresh(entry); 1844 else if (!(entry->flags & MLX5_ESW_BRIDGE_FLAG_PEER) && 1845 time_is_before_jiffies(entry->lastuse + bridge->ageing_time)) 1846 mlx5_esw_bridge_fdb_entry_notify_and_cleanup(entry, bridge); 1847 } 1848 } 1849} 1850 1851int mlx5_esw_bridge_port_mdb_add(struct net_device *dev, u16 vport_num, u16 esw_owner_vhca_id, 1852 const unsigned char *addr, u16 vid, 1853 struct mlx5_esw_bridge_offloads *br_offloads, 1854 struct netlink_ext_ack *extack) 1855{ 1856 struct mlx5_esw_bridge_vlan *vlan; 1857 struct mlx5_esw_bridge_port *port; 1858 struct mlx5_esw_bridge *bridge; 1859 int err; 1860 1861 port = mlx5_esw_bridge_port_lookup(vport_num, esw_owner_vhca_id, br_offloads); 1862 if (!port) { 1863 esw_warn(br_offloads->esw->dev, 1864 "Failed to lookup bridge port to add MDB (MAC=%pM,vport=%u)\n", 1865 addr, vport_num); 1866 NL_SET_ERR_MSG_FMT_MOD(extack, 1867 "Failed to lookup bridge port to add MDB (MAC=%pM,vport=%u)", 1868 addr, vport_num); 1869 return -EINVAL; 1870 } 1871 1872 bridge = port->bridge; 1873 if (bridge->flags & MLX5_ESW_BRIDGE_VLAN_FILTERING_FLAG && vid) { 1874 vlan = mlx5_esw_bridge_vlan_lookup(vid, port); 1875 if (!vlan) { 1876 esw_warn(br_offloads->esw->dev, 1877 "Failed to lookup bridge port vlan metadata to create MDB (MAC=%pM,vid=%u,vport=%u)\n", 1878 addr, vid, vport_num); 1879 NL_SET_ERR_MSG_FMT_MOD(extack, 1880 "Failed to lookup vlan metadata for MDB (MAC=%pM,vid=%u,vport=%u)", 1881 addr, vid, vport_num); 1882 return -EINVAL; 1883 } 1884 } 1885 1886 err = mlx5_esw_bridge_port_mdb_attach(dev, port, addr, vid); 1887 if (err) { 1888 NL_SET_ERR_MSG_FMT_MOD(extack, "Failed to add MDB (MAC=%pM,vid=%u,vport=%u)", 1889 addr, vid, vport_num); 1890 return err; 1891 } 1892 1893 return 0; 1894} 1895 1896void mlx5_esw_bridge_port_mdb_del(struct net_device *dev, u16 vport_num, u16 esw_owner_vhca_id, 1897 const unsigned char *addr, u16 vid, 1898 struct mlx5_esw_bridge_offloads *br_offloads) 1899{ 1900 struct mlx5_esw_bridge_port *port; 1901 1902 port = mlx5_esw_bridge_port_lookup(vport_num, esw_owner_vhca_id, br_offloads); 1903 if (!port) 1904 return; 1905 1906 mlx5_esw_bridge_port_mdb_detach(dev, port, addr, vid); 1907} 1908 1909static void mlx5_esw_bridge_flush(struct mlx5_esw_bridge_offloads *br_offloads) 1910{ 1911 struct mlx5_esw_bridge_port *port; 1912 unsigned long i; 1913 1914 xa_for_each(&br_offloads->ports, i, port) 1915 mlx5_esw_bridge_vport_cleanup(br_offloads, port); 1916 1917 WARN_ONCE(!list_empty(&br_offloads->bridges), 1918 "Cleaning up bridge offloads while still having bridges attached\n"); 1919} 1920 1921struct mlx5_esw_bridge_offloads *mlx5_esw_bridge_init(struct mlx5_eswitch *esw) 1922{ 1923 struct mlx5_esw_bridge_offloads *br_offloads; 1924 1925 ASSERT_RTNL(); 1926 1927 br_offloads = kvzalloc(sizeof(*br_offloads), GFP_KERNEL); 1928 if (!br_offloads) 1929 return ERR_PTR(-ENOMEM); 1930 1931 INIT_LIST_HEAD(&br_offloads->bridges); 1932 xa_init(&br_offloads->ports); 1933 br_offloads->esw = esw; 1934 esw->br_offloads = br_offloads; 1935 mlx5_esw_bridge_debugfs_offloads_init(br_offloads); 1936 1937 return br_offloads; 1938} 1939 1940void mlx5_esw_bridge_cleanup(struct mlx5_eswitch *esw) 1941{ 1942 struct mlx5_esw_bridge_offloads *br_offloads = esw->br_offloads; 1943 1944 ASSERT_RTNL(); 1945 1946 if (!br_offloads) 1947 return; 1948 1949 mlx5_esw_bridge_flush(br_offloads); 1950 WARN_ON(!xa_empty(&br_offloads->ports)); 1951 mlx5_esw_bridge_debugfs_offloads_cleanup(br_offloads); 1952 1953 esw->br_offloads = NULL; 1954 kvfree(br_offloads); 1955}
~/
Read-only file preview.