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 ifindex = upper->ifindex; 140 int err = 0; 141 142 if (!netif_is_bridge_master(upper)) 143 return 0; 144 145 rep = mlx5_esw_bridge_rep_vport_num_vhca_id_get(dev, esw, &vport_num, &esw_owner_vhca_id); 146 if (!rep) 147 return 0; 148 149 extack = netdev_notifier_info_to_extack(&info->info); 150 151 if (mlx5_esw_bridge_is_local(dev, rep, esw)) 152 err = info->linking ? 153 mlx5_esw_bridge_vport_link(ifindex, vport_num, esw_owner_vhca_id, 154 br_offloads, extack) : 155 mlx5_esw_bridge_vport_unlink(ifindex, vport_num, esw_owner_vhca_id, 156 br_offloads, extack); 157 else if (mlx5_esw_bridge_dev_same_hw(rep, esw)) 158 err = info->linking ? 159 mlx5_esw_bridge_vport_peer_link(ifindex, vport_num, esw_owner_vhca_id, 160 br_offloads, extack) : 161 mlx5_esw_bridge_vport_peer_unlink(ifindex, vport_num, esw_owner_vhca_id, 162 br_offloads, extack); 163 164 return err; 165 } 166 167 static int 168 mlx5_esw_bridge_changeupper_validate_netdev(void *ptr) 169 { 170 struct net_device *dev = netdev_notifier_info_to_dev(ptr); 171 struct netdev_notifier_changeupper_info *info = ptr; 172 struct net_device *upper = info->upper_dev; 173 struct net_device *lower; 174 struct list_head *iter; 175 176 if (!netif_is_bridge_master(upper) || !netif_is_lag_master(dev)) 177 return 0; 178 179 netdev_for_each_lower_dev(dev, lower, iter) { 180 struct mlx5_core_dev *mdev; 181 struct mlx5e_priv *priv; 182 183 if (!mlx5e_eswitch_rep(lower)) 184 continue; 185 186 priv = netdev_priv(lower); 187 mdev = priv->mdev; 188 if (!mlx5_lag_is_active(mdev)) 189 return -EAGAIN; 190 if (!mlx5_lag_is_shared_fdb(mdev)) 191 return -EOPNOTSUPP; 192 } 193 194 return 0; 195 } 196 197 static int mlx5_esw_bridge_switchdev_port_event(struct notifier_block *nb, 198 unsigned long event, void *ptr) 199 { 200 int err = 0; 201 202 switch (event) { 203 case NETDEV_PRECHANGEUPPER: 204 err = mlx5_esw_bridge_changeupper_validate_netdev(ptr); 205 break; 206 207 case NETDEV_CHANGEUPPER: 208 err = mlx5_esw_bridge_port_changeupper(nb, ptr); 209 break; 210 } 211 212 return notifier_from_errno(err); 213 } 214 215 static int 216 mlx5_esw_bridge_port_obj_add(struct net_device *dev, 217 struct switchdev_notifier_port_obj_info *port_obj_info, 218 struct mlx5_esw_bridge_offloads *br_offloads) 219 { 220 struct netlink_ext_ack *extack = switchdev_notifier_info_to_extack(&port_obj_info->info); 221 const struct switchdev_obj *obj = port_obj_info->obj; 222 const struct switchdev_obj_port_vlan *vlan; 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 default: 239 return -EOPNOTSUPP; 240 } 241 return err; 242 } 243 244 static int 245 mlx5_esw_bridge_port_obj_del(struct net_device *dev, 246 struct switchdev_notifier_port_obj_info *port_obj_info, 247 struct mlx5_esw_bridge_offloads *br_offloads) 248 { 249 const struct switchdev_obj *obj = port_obj_info->obj; 250 const struct switchdev_obj_port_vlan *vlan; 251 u16 vport_num, esw_owner_vhca_id; 252 253 if (!mlx5_esw_bridge_rep_vport_num_vhca_id_get(dev, br_offloads->esw, &vport_num, 254 &esw_owner_vhca_id)) 255 return 0; 256 257 port_obj_info->handled = true; 258 259 switch (obj->id) { 260 case SWITCHDEV_OBJ_ID_PORT_VLAN: 261 vlan = SWITCHDEV_OBJ_PORT_VLAN(obj); 262 mlx5_esw_bridge_port_vlan_del(vport_num, esw_owner_vhca_id, vlan->vid, br_offloads); 263 break; 264 default: 265 return -EOPNOTSUPP; 266 } 267 return 0; 268 } 269 270 static int 271 mlx5_esw_bridge_port_obj_attr_set(struct net_device *dev, 272 struct switchdev_notifier_port_attr_info *port_attr_info, 273 struct mlx5_esw_bridge_offloads *br_offloads) 274 { 275 struct netlink_ext_ack *extack = switchdev_notifier_info_to_extack(&port_attr_info->info); 276 const struct switchdev_attr *attr = port_attr_info->attr; 277 u16 vport_num, esw_owner_vhca_id; 278 int err = 0; 279 280 if (!mlx5_esw_bridge_lower_rep_vport_num_vhca_id_get(dev, br_offloads->esw, &vport_num, 281 &esw_owner_vhca_id)) 282 return 0; 283 284 port_attr_info->handled = true; 285 286 switch (attr->id) { 287 case SWITCHDEV_ATTR_ID_PORT_PRE_BRIDGE_FLAGS: 288 if (attr->u.brport_flags.mask & ~(BR_LEARNING | BR_FLOOD | BR_MCAST_FLOOD)) { 289 NL_SET_ERR_MSG_MOD(extack, "Flag is not supported"); 290 err = -EINVAL; 291 } 292 break; 293 case SWITCHDEV_ATTR_ID_PORT_BRIDGE_FLAGS: 294 break; 295 case SWITCHDEV_ATTR_ID_BRIDGE_AGEING_TIME: 296 err = mlx5_esw_bridge_ageing_time_set(vport_num, esw_owner_vhca_id, 297 attr->u.ageing_time, br_offloads); 298 break; 299 case SWITCHDEV_ATTR_ID_BRIDGE_VLAN_FILTERING: 300 err = mlx5_esw_bridge_vlan_filtering_set(vport_num, esw_owner_vhca_id, 301 attr->u.vlan_filtering, br_offloads); 302 break; 303 case SWITCHDEV_ATTR_ID_BRIDGE_VLAN_PROTOCOL: 304 err = mlx5_esw_bridge_vlan_proto_set(vport_num, 305 esw_owner_vhca_id, 306 attr->u.vlan_protocol, 307 br_offloads); 308 break; 309 default: 310 err = -EOPNOTSUPP; 311 } 312 313 return err; 314 } 315 316 static int mlx5_esw_bridge_event_blocking(struct notifier_block *nb, 317 unsigned long event, void *ptr) 318 { 319 struct mlx5_esw_bridge_offloads *br_offloads = container_of(nb, 320 struct mlx5_esw_bridge_offloads, 321 nb_blk); 322 struct net_device *dev = switchdev_notifier_info_to_dev(ptr); 323 int err; 324 325 switch (event) { 326 case SWITCHDEV_PORT_OBJ_ADD: 327 err = mlx5_esw_bridge_port_obj_add(dev, ptr, br_offloads); 328 break; 329 case SWITCHDEV_PORT_OBJ_DEL: 330 err = mlx5_esw_bridge_port_obj_del(dev, ptr, br_offloads); 331 break; 332 case SWITCHDEV_PORT_ATTR_SET: 333 err = mlx5_esw_bridge_port_obj_attr_set(dev, ptr, br_offloads); 334 break; 335 default: 336 err = 0; 337 } 338 339 return notifier_from_errno(err); 340 } 341 342 static void 343 mlx5_esw_bridge_cleanup_switchdev_fdb_work(struct mlx5_bridge_switchdev_fdb_work *fdb_work) 344 { 345 dev_put(fdb_work->dev); 346 kfree(fdb_work->fdb_info.addr); 347 kfree(fdb_work); 348 } 349 350 static void mlx5_esw_bridge_switchdev_fdb_event_work(struct work_struct *work) 351 { 352 struct mlx5_bridge_switchdev_fdb_work *fdb_work = 353 container_of(work, struct mlx5_bridge_switchdev_fdb_work, work); 354 struct switchdev_notifier_fdb_info *fdb_info = 355 &fdb_work->fdb_info; 356 struct mlx5_esw_bridge_offloads *br_offloads = 357 fdb_work->br_offloads; 358 struct net_device *dev = fdb_work->dev; 359 u16 vport_num, esw_owner_vhca_id; 360 361 rtnl_lock(); 362 363 if (!mlx5_esw_bridge_rep_vport_num_vhca_id_get(dev, br_offloads->esw, &vport_num, 364 &esw_owner_vhca_id)) 365 goto out; 366 367 if (fdb_work->add) 368 mlx5_esw_bridge_fdb_create(dev, vport_num, esw_owner_vhca_id, br_offloads, 369 fdb_info); 370 else 371 mlx5_esw_bridge_fdb_remove(dev, vport_num, esw_owner_vhca_id, br_offloads, 372 fdb_info); 373 374 out: 375 rtnl_unlock(); 376 mlx5_esw_bridge_cleanup_switchdev_fdb_work(fdb_work); 377 } 378 379 static struct mlx5_bridge_switchdev_fdb_work * 380 mlx5_esw_bridge_init_switchdev_fdb_work(struct net_device *dev, bool add, 381 struct switchdev_notifier_fdb_info *fdb_info, 382 struct mlx5_esw_bridge_offloads *br_offloads) 383 { 384 struct mlx5_bridge_switchdev_fdb_work *work; 385 u8 *addr; 386 387 work = kzalloc(sizeof(*work), GFP_ATOMIC); 388 if (!work) 389 return ERR_PTR(-ENOMEM); 390 391 INIT_WORK(&work->work, mlx5_esw_bridge_switchdev_fdb_event_work); 392 memcpy(&work->fdb_info, fdb_info, sizeof(work->fdb_info)); 393 394 addr = kzalloc(ETH_ALEN, GFP_ATOMIC); 395 if (!addr) { 396 kfree(work); 397 return ERR_PTR(-ENOMEM); 398 } 399 ether_addr_copy(addr, fdb_info->addr); 400 work->fdb_info.addr = addr; 401 402 dev_hold(dev); 403 work->dev = dev; 404 work->br_offloads = br_offloads; 405 work->add = add; 406 return work; 407 } 408 409 static int mlx5_esw_bridge_switchdev_event(struct notifier_block *nb, 410 unsigned long event, void *ptr) 411 { 412 struct mlx5_esw_bridge_offloads *br_offloads = container_of(nb, 413 struct mlx5_esw_bridge_offloads, 414 nb); 415 struct net_device *dev = switchdev_notifier_info_to_dev(ptr); 416 struct switchdev_notifier_fdb_info *fdb_info; 417 struct mlx5_bridge_switchdev_fdb_work *work; 418 struct mlx5_eswitch *esw = br_offloads->esw; 419 struct switchdev_notifier_info *info = ptr; 420 u16 vport_num, esw_owner_vhca_id; 421 struct net_device *upper, *rep; 422 423 if (event == SWITCHDEV_PORT_ATTR_SET) { 424 int err = mlx5_esw_bridge_port_obj_attr_set(dev, ptr, br_offloads); 425 426 return notifier_from_errno(err); 427 } 428 429 upper = netdev_master_upper_dev_get_rcu(dev); 430 if (!upper) 431 return NOTIFY_DONE; 432 if (!netif_is_bridge_master(upper)) 433 return NOTIFY_DONE; 434 435 rep = mlx5_esw_bridge_rep_vport_num_vhca_id_get(dev, esw, &vport_num, &esw_owner_vhca_id); 436 if (!rep) 437 return NOTIFY_DONE; 438 439 switch (event) { 440 case SWITCHDEV_FDB_ADD_TO_BRIDGE: 441 /* only handle the event on native eswtich of representor */ 442 if (!mlx5_esw_bridge_is_local(dev, rep, esw)) 443 break; 444 445 fdb_info = container_of(info, 446 struct switchdev_notifier_fdb_info, 447 info); 448 mlx5_esw_bridge_fdb_update_used(dev, vport_num, esw_owner_vhca_id, br_offloads, 449 fdb_info); 450 break; 451 case SWITCHDEV_FDB_DEL_TO_BRIDGE: 452 /* only handle the event on peers */ 453 if (mlx5_esw_bridge_is_local(dev, rep, esw)) 454 break; 455 fallthrough; 456 case SWITCHDEV_FDB_ADD_TO_DEVICE: 457 case SWITCHDEV_FDB_DEL_TO_DEVICE: 458 fdb_info = container_of(info, 459 struct switchdev_notifier_fdb_info, 460 info); 461 462 work = mlx5_esw_bridge_init_switchdev_fdb_work(dev, 463 event == SWITCHDEV_FDB_ADD_TO_DEVICE, 464 fdb_info, 465 br_offloads); 466 if (IS_ERR(work)) { 467 WARN_ONCE(1, "Failed to init switchdev work, err=%ld", 468 PTR_ERR(work)); 469 return notifier_from_errno(PTR_ERR(work)); 470 } 471 472 queue_work(br_offloads->wq, &work->work); 473 break; 474 default: 475 break; 476 } 477 return NOTIFY_DONE; 478 } 479 480 static void mlx5_esw_bridge_update_work(struct work_struct *work) 481 { 482 struct mlx5_esw_bridge_offloads *br_offloads = container_of(work, 483 struct mlx5_esw_bridge_offloads, 484 update_work.work); 485 486 rtnl_lock(); 487 mlx5_esw_bridge_update(br_offloads); 488 rtnl_unlock(); 489 490 queue_delayed_work(br_offloads->wq, &br_offloads->update_work, 491 msecs_to_jiffies(MLX5_ESW_BRIDGE_UPDATE_INTERVAL)); 492 } 493 494 void mlx5e_rep_bridge_init(struct mlx5e_priv *priv) 495 { 496 struct mlx5_esw_bridge_offloads *br_offloads; 497 struct mlx5_core_dev *mdev = priv->mdev; 498 struct mlx5_eswitch *esw = 499 mdev->priv.eswitch; 500 int err; 501 502 rtnl_lock(); 503 br_offloads = mlx5_esw_bridge_init(esw); 504 rtnl_unlock(); 505 if (IS_ERR(br_offloads)) { 506 esw_warn(mdev, "Failed to init esw bridge (err=%ld)\n", PTR_ERR(br_offloads)); 507 return; 508 } 509 510 br_offloads->wq = alloc_ordered_workqueue("mlx5_bridge_wq", 0); 511 if (!br_offloads->wq) { 512 esw_warn(mdev, "Failed to allocate bridge offloads workqueue\n"); 513 goto err_alloc_wq; 514 } 515 516 br_offloads->nb.notifier_call = mlx5_esw_bridge_switchdev_event; 517 err = register_switchdev_notifier(&br_offloads->nb); 518 if (err) { 519 esw_warn(mdev, "Failed to register switchdev notifier (err=%d)\n", err); 520 goto err_register_swdev; 521 } 522 523 br_offloads->nb_blk.notifier_call = mlx5_esw_bridge_event_blocking; 524 err = register_switchdev_blocking_notifier(&br_offloads->nb_blk); 525 if (err) { 526 esw_warn(mdev, "Failed to register blocking switchdev notifier (err=%d)\n", err); 527 goto err_register_swdev_blk; 528 } 529 530 br_offloads->netdev_nb.notifier_call = mlx5_esw_bridge_switchdev_port_event; 531 err = register_netdevice_notifier_net(&init_net, &br_offloads->netdev_nb); 532 if (err) { 533 esw_warn(mdev, "Failed to register bridge offloads netdevice notifier (err=%d)\n", 534 err); 535 goto err_register_netdev; 536 } 537 INIT_DELAYED_WORK(&br_offloads->update_work, mlx5_esw_bridge_update_work); 538 queue_delayed_work(br_offloads->wq, &br_offloads->update_work, 539 msecs_to_jiffies(MLX5_ESW_BRIDGE_UPDATE_INTERVAL)); 540 return; 541 542 err_register_netdev: 543 unregister_switchdev_blocking_notifier(&br_offloads->nb_blk); 544 err_register_swdev_blk: 545 unregister_switchdev_notifier(&br_offloads->nb); 546 err_register_swdev: 547 destroy_workqueue(br_offloads->wq); 548 err_alloc_wq: 549 rtnl_lock(); 550 mlx5_esw_bridge_cleanup(esw); 551 rtnl_unlock(); 552 } 553 554 void mlx5e_rep_bridge_cleanup(struct mlx5e_priv *priv) 555 { 556 struct mlx5_esw_bridge_offloads *br_offloads; 557 struct mlx5_core_dev *mdev = priv->mdev; 558 struct mlx5_eswitch *esw = 559 mdev->priv.eswitch; 560 561 br_offloads = esw->br_offloads; 562 if (!br_offloads) 563 return; 564 565 cancel_delayed_work_sync(&br_offloads->update_work); 566 unregister_netdevice_notifier_net(&init_net, &br_offloads->netdev_nb); 567 unregister_switchdev_blocking_notifier(&br_offloads->nb_blk); 568 unregister_switchdev_notifier(&br_offloads->nb); 569 destroy_workqueue(br_offloads->wq); 570 rtnl_lock(); 571 mlx5_esw_bridge_cleanup(esw); 572 rtnl_unlock(); 573 } 574