1 // SPDX-License-Identifier: GPL-2.0 OR Linux-OpenIB 2 /* Copyright (c) 2021 Mellanox Technologies. */ 3 4 #include <linux/netdevice.h> 5 #include <linux/if_bridge.h> 6 #include <net/netevent.h> 7 #include <net/switchdev.h> 8 #include "bridge.h" 9 #include "esw/bridge.h" 10 #include "en_rep.h" 11 12 #define MLX5_ESW_BRIDGE_UPDATE_INTERVAL 1000 13 14 struct mlx5_bridge_switchdev_fdb_work { 15 struct work_struct work; 16 struct switchdev_notifier_fdb_info fdb_info; 17 struct net_device *dev; 18 struct mlx5_esw_bridge_offloads *br_offloads; 19 bool add; 20 }; 21 22 static bool mlx5_esw_bridge_dev_same_esw(struct net_device *dev, struct mlx5_eswitch *esw) 23 { 24 struct mlx5e_priv *priv = netdev_priv(dev); 25 26 return esw == priv->mdev->priv.eswitch; 27 } 28 29 static bool mlx5_esw_bridge_dev_same_hw(struct net_device *dev, struct mlx5_eswitch *esw) 30 { 31 struct mlx5e_priv *priv = netdev_priv(dev); 32 struct mlx5_core_dev *mdev, *esw_mdev; 33 u64 system_guid, esw_system_guid; 34 35 mdev = priv->mdev; 36 esw_mdev = esw->dev; 37 38 system_guid = mlx5_query_nic_system_image_guid(mdev); 39 esw_system_guid = mlx5_query_nic_system_image_guid(esw_mdev); 40 41 return system_guid == esw_system_guid; 42 } 43 44 static struct net_device * 45 mlx5_esw_bridge_lag_rep_get(struct net_device *dev, struct mlx5_eswitch *esw) 46 { 47 struct net_device *lower; 48 struct list_head *iter; 49 50 netdev_for_each_lower_dev(dev, lower, iter) { 51 struct mlx5_core_dev *mdev; 52 struct mlx5e_priv *priv; 53 54 if (!mlx5e_eswitch_rep(lower)) 55 continue; 56 57 priv = netdev_priv(lower); 58 mdev = priv->mdev; 59 if (mlx5_lag_is_shared_fdb(mdev) && mlx5_esw_bridge_dev_same_esw(lower, esw)) 60 return lower; 61 } 62 63 return NULL; 64 } 65 66 static struct net_device * 67 mlx5_esw_bridge_rep_vport_num_vhca_id_get(struct net_device *dev, struct mlx5_eswitch *esw, 68 u16 *vport_num, u16 *esw_owner_vhca_id) 69 { 70 struct mlx5e_rep_priv *rpriv; 71 struct mlx5e_priv *priv; 72 73 if (netif_is_lag_master(dev)) 74 dev = mlx5_esw_bridge_lag_rep_get(dev, esw); 75 76 if (!dev || !mlx5e_eswitch_rep(dev) || !mlx5_esw_bridge_dev_same_hw(dev, esw)) 77 return NULL; 78 79 priv = netdev_priv(dev); 80 rpriv = priv->ppriv; 81 *vport_num = rpriv->rep->vport; 82 *esw_owner_vhca_id = MLX5_CAP_GEN(priv->mdev, vhca_id); 83 return dev; 84 } 85 86 static struct net_device * 87 mlx5_esw_bridge_lower_rep_vport_num_vhca_id_get(struct net_device *dev, struct mlx5_eswitch *esw, 88 u16 *vport_num, u16 *esw_owner_vhca_id) 89 { 90 struct net_device *lower_dev; 91 struct list_head *iter; 92 93 if (netif_is_lag_master(dev) || mlx5e_eswitch_rep(dev)) 94 return mlx5_esw_bridge_rep_vport_num_vhca_id_get(dev, esw, vport_num, 95 esw_owner_vhca_id); 96 97 netdev_for_each_lower_dev(dev, lower_dev, iter) { 98 struct net_device *rep; 99 100 if (netif_is_bridge_master(lower_dev)) 101 continue; 102 103 rep = mlx5_esw_bridge_lower_rep_vport_num_vhca_id_get(lower_dev, esw, vport_num, 104 esw_owner_vhca_id); 105 if (rep) 106 return rep; 107 } 108 109 return NULL; 110 } 111 112 static bool mlx5_esw_bridge_is_local(struct net_device *dev, struct net_device *rep, 113 struct mlx5_eswitch *esw) 114 { 115 struct mlx5_core_dev *mdev; 116 struct mlx5e_priv *priv; 117 118 if (!mlx5_esw_bridge_dev_same_esw(rep, esw)) 119 return false; 120 121 priv = netdev_priv(rep); 122 mdev = priv->mdev; 123 if (netif_is_lag_master(dev)) 124 return mlx5_lag_is_shared_fdb(mdev) && mlx5_lag_is_master(mdev); 125 return true; 126 } 127 128 static int mlx5_esw_bridge_port_changeupper(struct notifier_block *nb, void *ptr) 129 { 130 struct mlx5_esw_bridge_offloads *br_offloads = container_of(nb, 131 struct mlx5_esw_bridge_offloads, 132 netdev_nb); 133 struct net_device *dev = netdev_notifier_info_to_dev(ptr); 134 struct netdev_notifier_changeupper_info *info = ptr; 135 struct net_device *upper = info->upper_dev, *rep; 136 struct mlx5_eswitch *esw = br_offloads->esw; 137 u16 vport_num, esw_owner_vhca_id; 138 struct netlink_ext_ack *extack; 139 int err = 0; 140 141 if (!netif_is_bridge_master(upper)) 142 return 0; 143 144 rep = mlx5_esw_bridge_rep_vport_num_vhca_id_get(dev, esw, &vport_num, &esw_owner_vhca_id); 145 if (!rep) 146 return 0; 147 148 extack = netdev_notifier_info_to_extack(&info->info); 149 150 if (mlx5_esw_bridge_is_local(dev, rep, esw)) 151 err = info->linking ? 152 mlx5_esw_bridge_vport_link(upper, vport_num, esw_owner_vhca_id, 153 br_offloads, extack) : 154 mlx5_esw_bridge_vport_unlink(upper, vport_num, esw_owner_vhca_id, 155 br_offloads, extack); 156 else if (mlx5_esw_bridge_dev_same_hw(rep, esw)) 157 err = info->linking ? 158 mlx5_esw_bridge_vport_peer_link(upper, vport_num, esw_owner_vhca_id, 159 br_offloads, extack) : 160 mlx5_esw_bridge_vport_peer_unlink(upper, vport_num, esw_owner_vhca_id, 161 br_offloads, extack); 162 163 return err; 164 } 165 166 static int 167 mlx5_esw_bridge_changeupper_validate_netdev(void *ptr) 168 { 169 struct net_device *dev = netdev_notifier_info_to_dev(ptr); 170 struct netdev_notifier_changeupper_info *info = ptr; 171 struct net_device *upper = info->upper_dev; 172 struct net_device *lower; 173 struct list_head *iter; 174 175 if (!netif_is_bridge_master(upper) || !netif_is_lag_master(dev)) 176 return 0; 177 178 netdev_for_each_lower_dev(dev, lower, iter) { 179 struct mlx5_core_dev *mdev; 180 struct mlx5e_priv *priv; 181 182 if (!mlx5e_eswitch_rep(lower)) 183 continue; 184 185 priv = netdev_priv(lower); 186 mdev = priv->mdev; 187 if (!mlx5_lag_is_active(mdev)) 188 return -EAGAIN; 189 if (!mlx5_lag_is_shared_fdb(mdev)) 190 return -EOPNOTSUPP; 191 } 192 193 return 0; 194 } 195 196 static int mlx5_esw_bridge_switchdev_port_event(struct notifier_block *nb, 197 unsigned long event, void *ptr) 198 { 199 int err = 0; 200 201 switch (event) { 202 case NETDEV_PRECHANGEUPPER: 203 err = mlx5_esw_bridge_changeupper_validate_netdev(ptr); 204 break; 205 206 case NETDEV_CHANGEUPPER: 207 err = mlx5_esw_bridge_port_changeupper(nb, ptr); 208 break; 209 } 210 211 return notifier_from_errno(err); 212 } 213 214 static int 215 mlx5_esw_bridge_port_obj_add(struct net_device *dev, 216 struct switchdev_notifier_port_obj_info *port_obj_info, 217 struct mlx5_esw_bridge_offloads *br_offloads) 218 { 219 struct netlink_ext_ack *extack = switchdev_notifier_info_to_extack(&port_obj_info->info); 220 const struct switchdev_obj *obj = port_obj_info->obj; 221 const struct switchdev_obj_port_vlan *vlan; 222 const struct switchdev_obj_port_mdb *mdb; 223 u16 vport_num, esw_owner_vhca_id; 224 int err; 225 226 if (!mlx5_esw_bridge_rep_vport_num_vhca_id_get(dev, br_offloads->esw, &vport_num, 227 &esw_owner_vhca_id)) 228 return 0; 229 230 port_obj_info->handled = true; 231 232 switch (obj->id) { 233 case SWITCHDEV_OBJ_ID_PORT_VLAN: 234 vlan = SWITCHDEV_OBJ_PORT_VLAN(obj); 235 err = mlx5_esw_bridge_port_vlan_add(vport_num, esw_owner_vhca_id, vlan->vid, 236 vlan->flags, br_offloads, extack); 237 break; 238 case SWITCHDEV_OBJ_ID_PORT_MDB: 239 mdb = SWITCHDEV_OBJ_PORT_MDB(obj); 240 err = mlx5_esw_bridge_port_mdb_add(dev, vport_num, esw_owner_vhca_id, mdb->addr, 241 mdb->vid, br_offloads, extack); 242 break; 243 default: 244 return -EOPNOTSUPP; 245 } 246 return err; 247 } 248 249 static int 250 mlx5_esw_bridge_port_obj_del(struct net_device *dev, 251 struct switchdev_notifier_port_obj_info *port_obj_info, 252 struct mlx5_esw_bridge_offloads *br_offloads) 253 { 254 const struct switchdev_obj *obj = port_obj_info->obj; 255 const struct switchdev_obj_port_vlan *vlan; 256 const struct switchdev_obj_port_mdb *mdb; 257 u16 vport_num, esw_owner_vhca_id; 258 259 if (!mlx5_esw_bridge_rep_vport_num_vhca_id_get(dev, br_offloads->esw, &vport_num, 260 &esw_owner_vhca_id)) 261 return 0; 262 263 port_obj_info->handled = true; 264 265 switch (obj->id) { 266 case SWITCHDEV_OBJ_ID_PORT_VLAN: 267 vlan = SWITCHDEV_OBJ_PORT_VLAN(obj); 268 mlx5_esw_bridge_port_vlan_del(vport_num, esw_owner_vhca_id, vlan->vid, br_offloads); 269 break; 270 case SWITCHDEV_OBJ_ID_PORT_MDB: 271 mdb = SWITCHDEV_OBJ_PORT_MDB(obj); 272 mlx5_esw_bridge_port_mdb_del(dev, vport_num, esw_owner_vhca_id, mdb->addr, mdb->vid, 273 br_offloads); 274 break; 275 default: 276 return -EOPNOTSUPP; 277 } 278 return 0; 279 } 280 281 static int 282 mlx5_esw_bridge_port_obj_attr_set(struct net_device *dev, 283 struct switchdev_notifier_port_attr_info *port_attr_info, 284 struct mlx5_esw_bridge_offloads *br_offloads) 285 { 286 struct netlink_ext_ack *extack = switchdev_notifier_info_to_extack(&port_attr_info->info); 287 const struct switchdev_attr *attr = port_attr_info->attr; 288 u16 vport_num, esw_owner_vhca_id; 289 int err = 0; 290 291 if (!mlx5_esw_bridge_lower_rep_vport_num_vhca_id_get(dev, br_offloads->esw, &vport_num, 292 &esw_owner_vhca_id)) 293 return 0; 294 295 port_attr_info->handled = true; 296 297 switch (attr->id) { 298 case SWITCHDEV_ATTR_ID_PORT_PRE_BRIDGE_FLAGS: 299 if (attr->u.brport_flags.mask & ~(BR_LEARNING | BR_FLOOD | BR_MCAST_FLOOD)) { 300 NL_SET_ERR_MSG_MOD(extack, "Flag is not supported"); 301 err = -EINVAL; 302 } 303 break; 304 case SWITCHDEV_ATTR_ID_PORT_BRIDGE_FLAGS: 305 break; 306 case SWITCHDEV_ATTR_ID_BRIDGE_AGEING_TIME: 307 err = mlx5_esw_bridge_ageing_time_set(vport_num, esw_owner_vhca_id, 308 attr->u.ageing_time, br_offloads); 309 break; 310 case SWITCHDEV_ATTR_ID_BRIDGE_VLAN_FILTERING: 311 err = mlx5_esw_bridge_vlan_filtering_set(vport_num, esw_owner_vhca_id, 312 attr->u.vlan_filtering, br_offloads); 313 break; 314 case SWITCHDEV_ATTR_ID_BRIDGE_VLAN_PROTOCOL: 315 err = mlx5_esw_bridge_vlan_proto_set(vport_num, 316 esw_owner_vhca_id, 317 attr->u.vlan_protocol, 318 br_offloads); 319 break; 320 case SWITCHDEV_ATTR_ID_BRIDGE_MC_DISABLED: 321 err = mlx5_esw_bridge_mcast_set(vport_num, esw_owner_vhca_id, 322 !attr->u.mc_disabled, br_offloads); 323 break; 324 default: 325 err = -EOPNOTSUPP; 326 } 327 328 return err; 329 } 330 331 static int mlx5_esw_bridge_event_blocking(struct notifier_block *nb, 332 unsigned long event, void *ptr) 333 { 334 struct mlx5_esw_bridge_offloads *br_offloads = container_of(nb, 335 struct mlx5_esw_bridge_offloads, 336 nb_blk); 337 struct net_device *dev = switchdev_notifier_info_to_dev(ptr); 338 int err; 339 340 switch (event) { 341 case SWITCHDEV_PORT_OBJ_ADD: 342 err = mlx5_esw_bridge_port_obj_add(dev, ptr, br_offloads); 343 break; 344 case SWITCHDEV_PORT_OBJ_DEL: 345 err = mlx5_esw_bridge_port_obj_del(dev, ptr, br_offloads); 346 break; 347 case SWITCHDEV_PORT_ATTR_SET: 348 err = mlx5_esw_bridge_port_obj_attr_set(dev, ptr, br_offloads); 349 break; 350 default: 351 err = 0; 352 } 353 354 return notifier_from_errno(err); 355 } 356 357 static void 358 mlx5_esw_bridge_cleanup_switchdev_fdb_work(struct mlx5_bridge_switchdev_fdb_work *fdb_work) 359 { 360 dev_put(fdb_work->dev); 361 kfree(fdb_work->fdb_info.addr); 362 kfree(fdb_work); 363 } 364 365 static void mlx5_esw_bridge_switchdev_fdb_event_work(struct work_struct *work) 366 { 367 struct mlx5_bridge_switchdev_fdb_work *fdb_work = 368 container_of(work, struct mlx5_bridge_switchdev_fdb_work, work); 369 struct switchdev_notifier_fdb_info *fdb_info = 370 &fdb_work->fdb_info; 371 struct mlx5_esw_bridge_offloads *br_offloads = 372 fdb_work->br_offloads; 373 struct net_device *dev = fdb_work->dev; 374 u16 vport_num, esw_owner_vhca_id; 375 376 rtnl_lock(); 377 378 if (!mlx5_esw_bridge_rep_vport_num_vhca_id_get(dev, br_offloads->esw, &vport_num, 379 &esw_owner_vhca_id)) 380 goto out; 381 382 if (fdb_work->add) 383 mlx5_esw_bridge_fdb_create(dev, vport_num, esw_owner_vhca_id, br_offloads, 384 fdb_info); 385 else 386 mlx5_esw_bridge_fdb_remove(dev, vport_num, esw_owner_vhca_id, br_offloads, 387 fdb_info); 388 389 out: 390 rtnl_unlock(); 391 mlx5_esw_bridge_cleanup_switchdev_fdb_work(fdb_work); 392 } 393 394 static struct mlx5_bridge_switchdev_fdb_work * 395 mlx5_esw_bridge_init_switchdev_fdb_work(struct net_device *dev, bool add, 396 struct switchdev_notifier_fdb_info *fdb_info, 397 struct mlx5_esw_bridge_offloads *br_offloads) 398 { 399 struct mlx5_bridge_switchdev_fdb_work *work; 400 u8 *addr; 401 402 work = kzalloc(sizeof(*work), GFP_ATOMIC); 403 if (!work) 404 return ERR_PTR(-ENOMEM); 405 406 INIT_WORK(&work->work, mlx5_esw_bridge_switchdev_fdb_event_work); 407 memcpy(&work->fdb_info, fdb_info, sizeof(work->fdb_info)); 408 409 addr = kzalloc(ETH_ALEN, GFP_ATOMIC); 410 if (!addr) { 411 kfree(work); 412 return ERR_PTR(-ENOMEM); 413 } 414 ether_addr_copy(addr, fdb_info->addr); 415 work->fdb_info.addr = addr; 416 417 dev_hold(dev); 418 work->dev = dev; 419 work->br_offloads = br_offloads; 420 work->add = add; 421 return work; 422 } 423 424 static int mlx5_esw_bridge_switchdev_event(struct notifier_block *nb, 425 unsigned long event, void *ptr) 426 { 427 struct mlx5_esw_bridge_offloads *br_offloads = container_of(nb, 428 struct mlx5_esw_bridge_offloads, 429 nb); 430 struct net_device *dev = switchdev_notifier_info_to_dev(ptr); 431 struct switchdev_notifier_fdb_info *fdb_info; 432 struct mlx5_bridge_switchdev_fdb_work *work; 433 struct mlx5_eswitch *esw = br_offloads->esw; 434 struct switchdev_notifier_info *info = ptr; 435 u16 vport_num, esw_owner_vhca_id; 436 struct net_device *upper, *rep; 437 438 if (event == SWITCHDEV_PORT_ATTR_SET) { 439 int err = mlx5_esw_bridge_port_obj_attr_set(dev, ptr, br_offloads); 440 441 return notifier_from_errno(err); 442 } 443 444 upper = netdev_master_upper_dev_get_rcu(dev); 445 if (!upper) 446 return NOTIFY_DONE; 447 if (!netif_is_bridge_master(upper)) 448 return NOTIFY_DONE; 449 450 rep = mlx5_esw_bridge_rep_vport_num_vhca_id_get(dev, esw, &vport_num, &esw_owner_vhca_id); 451 if (!rep) 452 return NOTIFY_DONE; 453 454 switch (event) { 455 case SWITCHDEV_FDB_ADD_TO_BRIDGE: 456 fdb_info = container_of(info, 457 struct switchdev_notifier_fdb_info, 458 info); 459 mlx5_esw_bridge_fdb_update_used(dev, vport_num, esw_owner_vhca_id, br_offloads, 460 fdb_info); 461 break; 462 case SWITCHDEV_FDB_DEL_TO_BRIDGE: 463 /* only handle the event on peers */ 464 if (mlx5_esw_bridge_is_local(dev, rep, esw)) 465 break; 466 fallthrough; 467 case SWITCHDEV_FDB_ADD_TO_DEVICE: 468 case SWITCHDEV_FDB_DEL_TO_DEVICE: 469 fdb_info = container_of(info, 470 struct switchdev_notifier_fdb_info, 471 info); 472 473 work = mlx5_esw_bridge_init_switchdev_fdb_work(dev, 474 event == SWITCHDEV_FDB_ADD_TO_DEVICE, 475 fdb_info, 476 br_offloads); 477 if (IS_ERR(work)) { 478 WARN_ONCE(1, "Failed to init switchdev work, err=%ld", 479 PTR_ERR(work)); 480 return notifier_from_errno(PTR_ERR(work)); 481 } 482 483 queue_work(br_offloads->wq, &work->work); 484 break; 485 default: 486 break; 487 } 488 return NOTIFY_DONE; 489 } 490 491 static void mlx5_esw_bridge_update_work(struct work_struct *work) 492 { 493 struct mlx5_esw_bridge_offloads *br_offloads = container_of(work, 494 struct mlx5_esw_bridge_offloads, 495 update_work.work); 496 497 rtnl_lock(); 498 mlx5_esw_bridge_update(br_offloads); 499 rtnl_unlock(); 500 501 queue_delayed_work(br_offloads->wq, &br_offloads->update_work, 502 msecs_to_jiffies(MLX5_ESW_BRIDGE_UPDATE_INTERVAL)); 503 } 504 505 void mlx5e_rep_bridge_init(struct mlx5e_priv *priv) 506 { 507 struct mlx5_esw_bridge_offloads *br_offloads; 508 struct mlx5_core_dev *mdev = priv->mdev; 509 struct mlx5_eswitch *esw = 510 mdev->priv.eswitch; 511 int err; 512 513 rtnl_lock(); 514 br_offloads = mlx5_esw_bridge_init(esw); 515 rtnl_unlock(); 516 if (IS_ERR(br_offloads)) { 517 esw_warn(mdev, "Failed to init esw bridge (err=%ld)\n", PTR_ERR(br_offloads)); 518 return; 519 } 520 521 br_offloads->wq = alloc_ordered_workqueue("mlx5_bridge_wq", 0); 522 if (!br_offloads->wq) { 523 esw_warn(mdev, "Failed to allocate bridge offloads workqueue\n"); 524 goto err_alloc_wq; 525 } 526 527 br_offloads->nb.notifier_call = mlx5_esw_bridge_switchdev_event; 528 err = register_switchdev_notifier(&br_offloads->nb); 529 if (err) { 530 esw_warn(mdev, "Failed to register switchdev notifier (err=%d)\n", err); 531 goto err_register_swdev; 532 } 533 534 br_offloads->nb_blk.notifier_call = mlx5_esw_bridge_event_blocking; 535 err = register_switchdev_blocking_notifier(&br_offloads->nb_blk); 536 if (err) { 537 esw_warn(mdev, "Failed to register blocking switchdev notifier (err=%d)\n", err); 538 goto err_register_swdev_blk; 539 } 540 541 br_offloads->netdev_nb.notifier_call = mlx5_esw_bridge_switchdev_port_event; 542 err = register_netdevice_notifier_net(&init_net, &br_offloads->netdev_nb); 543 if (err) { 544 esw_warn(mdev, "Failed to register bridge offloads netdevice notifier (err=%d)\n", 545 err); 546 goto err_register_netdev; 547 } 548 INIT_DELAYED_WORK(&br_offloads->update_work, mlx5_esw_bridge_update_work); 549 queue_delayed_work(br_offloads->wq, &br_offloads->update_work, 550 msecs_to_jiffies(MLX5_ESW_BRIDGE_UPDATE_INTERVAL)); 551 return; 552 553 err_register_netdev: 554 unregister_switchdev_blocking_notifier(&br_offloads->nb_blk); 555 err_register_swdev_blk: 556 unregister_switchdev_notifier(&br_offloads->nb); 557 err_register_swdev: 558 destroy_workqueue(br_offloads->wq); 559 err_alloc_wq: 560 rtnl_lock(); 561 mlx5_esw_bridge_cleanup(esw); 562 rtnl_unlock(); 563 } 564 565 void mlx5e_rep_bridge_cleanup(struct mlx5e_priv *priv) 566 { 567 struct mlx5_esw_bridge_offloads *br_offloads; 568 struct mlx5_core_dev *mdev = priv->mdev; 569 struct mlx5_eswitch *esw = 570 mdev->priv.eswitch; 571 572 br_offloads = esw->br_offloads; 573 if (!br_offloads) 574 return; 575 576 cancel_delayed_work_sync(&br_offloads->update_work); 577 unregister_netdevice_notifier_net(&init_net, &br_offloads->netdev_nb); 578 unregister_switchdev_blocking_notifier(&br_offloads->nb_blk); 579 unregister_switchdev_notifier(&br_offloads->nb); 580 destroy_workqueue(br_offloads->wq); 581 rtnl_lock(); 582 mlx5_esw_bridge_cleanup(esw); 583 rtnl_unlock(); 584 } 585