1 /* 2 * net/switchdev/switchdev.c - Switch device API 3 * Copyright (c) 2014 Jiri Pirko <jiri@resnulli.us> 4 * Copyright (c) 2014-2015 Scott Feldman <sfeldma@gmail.com> 5 * 6 * This program is free software; you can redistribute it and/or modify 7 * it under the terms of the GNU General Public License as published by 8 * the Free Software Foundation; either version 2 of the License, or 9 * (at your option) any later version. 10 */ 11 12 #include <linux/kernel.h> 13 #include <linux/types.h> 14 #include <linux/init.h> 15 #include <linux/mutex.h> 16 #include <linux/notifier.h> 17 #include <linux/netdevice.h> 18 #include <linux/if_bridge.h> 19 #include <net/ip_fib.h> 20 #include <net/switchdev.h> 21 22 /** 23 * switchdev_port_attr_get - Get port attribute 24 * 25 * @dev: port device 26 * @attr: attribute to get 27 */ 28 int switchdev_port_attr_get(struct net_device *dev, struct switchdev_attr *attr) 29 { 30 const struct switchdev_ops *ops = dev->switchdev_ops; 31 struct net_device *lower_dev; 32 struct list_head *iter; 33 struct switchdev_attr first = { 34 .id = SWITCHDEV_ATTR_UNDEFINED 35 }; 36 int err = -EOPNOTSUPP; 37 38 if (ops && ops->switchdev_port_attr_get) 39 return ops->switchdev_port_attr_get(dev, attr); 40 41 if (attr->flags & SWITCHDEV_F_NO_RECURSE) 42 return err; 43 44 /* Switch device port(s) may be stacked under 45 * bond/team/vlan dev, so recurse down to get attr on 46 * each port. Return -ENODATA if attr values don't 47 * compare across ports. 48 */ 49 50 netdev_for_each_lower_dev(dev, lower_dev, iter) { 51 err = switchdev_port_attr_get(lower_dev, attr); 52 if (err) 53 break; 54 if (first.id == SWITCHDEV_ATTR_UNDEFINED) 55 first = *attr; 56 else if (memcmp(&first, attr, sizeof(*attr))) 57 return -ENODATA; 58 } 59 60 return err; 61 } 62 EXPORT_SYMBOL_GPL(switchdev_port_attr_get); 63 64 static int __switchdev_port_attr_set(struct net_device *dev, 65 struct switchdev_attr *attr) 66 { 67 const struct switchdev_ops *ops = dev->switchdev_ops; 68 struct net_device *lower_dev; 69 struct list_head *iter; 70 int err = -EOPNOTSUPP; 71 72 if (ops && ops->switchdev_port_attr_set) 73 return ops->switchdev_port_attr_set(dev, attr); 74 75 if (attr->flags & SWITCHDEV_F_NO_RECURSE) 76 return err; 77 78 /* Switch device port(s) may be stacked under 79 * bond/team/vlan dev, so recurse down to set attr on 80 * each port. 81 */ 82 83 netdev_for_each_lower_dev(dev, lower_dev, iter) { 84 err = __switchdev_port_attr_set(lower_dev, attr); 85 if (err) 86 break; 87 } 88 89 return err; 90 } 91 92 struct switchdev_attr_set_work { 93 struct work_struct work; 94 struct net_device *dev; 95 struct switchdev_attr attr; 96 }; 97 98 static void switchdev_port_attr_set_work(struct work_struct *work) 99 { 100 struct switchdev_attr_set_work *asw = 101 container_of(work, struct switchdev_attr_set_work, work); 102 int err; 103 104 rtnl_lock(); 105 err = switchdev_port_attr_set(asw->dev, &asw->attr); 106 BUG_ON(err); 107 rtnl_unlock(); 108 109 dev_put(asw->dev); 110 kfree(work); 111 } 112 113 static int switchdev_port_attr_set_defer(struct net_device *dev, 114 struct switchdev_attr *attr) 115 { 116 struct switchdev_attr_set_work *asw; 117 118 asw = kmalloc(sizeof(*asw), GFP_ATOMIC); 119 if (!asw) 120 return -ENOMEM; 121 122 INIT_WORK(&asw->work, switchdev_port_attr_set_work); 123 124 dev_hold(dev); 125 asw->dev = dev; 126 memcpy(&asw->attr, attr, sizeof(asw->attr)); 127 128 schedule_work(&asw->work); 129 130 return 0; 131 } 132 133 /** 134 * switchdev_port_attr_set - Set port attribute 135 * 136 * @dev: port device 137 * @attr: attribute to set 138 * 139 * Use a 2-phase prepare-commit transaction model to ensure 140 * system is not left in a partially updated state due to 141 * failure from driver/device. 142 */ 143 int switchdev_port_attr_set(struct net_device *dev, struct switchdev_attr *attr) 144 { 145 int err; 146 147 if (!rtnl_is_locked()) { 148 /* Running prepare-commit transaction across stacked 149 * devices requires nothing moves, so if rtnl_lock is 150 * not held, schedule a worker thread to hold rtnl_lock 151 * while setting attr. 152 */ 153 154 return switchdev_port_attr_set_defer(dev, attr); 155 } 156 157 /* Phase I: prepare for attr set. Driver/device should fail 158 * here if there are going to be issues in the commit phase, 159 * such as lack of resources or support. The driver/device 160 * should reserve resources needed for the commit phase here, 161 * but should not commit the attr. 162 */ 163 164 attr->trans = SWITCHDEV_TRANS_PREPARE; 165 err = __switchdev_port_attr_set(dev, attr); 166 if (err) { 167 /* Prepare phase failed: abort the transaction. Any 168 * resources reserved in the prepare phase are 169 * released. 170 */ 171 172 attr->trans = SWITCHDEV_TRANS_ABORT; 173 __switchdev_port_attr_set(dev, attr); 174 175 return err; 176 } 177 178 /* Phase II: commit attr set. This cannot fail as a fault 179 * of driver/device. If it does, it's a bug in the driver/device 180 * because the driver said everythings was OK in phase I. 181 */ 182 183 attr->trans = SWITCHDEV_TRANS_COMMIT; 184 err = __switchdev_port_attr_set(dev, attr); 185 BUG_ON(err); 186 187 return err; 188 } 189 EXPORT_SYMBOL_GPL(switchdev_port_attr_set); 190 191 static int __switchdev_port_obj_add(struct net_device *dev, 192 struct switchdev_obj *obj) 193 { 194 const struct switchdev_ops *ops = dev->switchdev_ops; 195 struct net_device *lower_dev; 196 struct list_head *iter; 197 int err = -EOPNOTSUPP; 198 199 if (ops && ops->switchdev_port_obj_add) 200 return ops->switchdev_port_obj_add(dev, obj); 201 202 /* Switch device port(s) may be stacked under 203 * bond/team/vlan dev, so recurse down to add object on 204 * each port. 205 */ 206 207 netdev_for_each_lower_dev(dev, lower_dev, iter) { 208 err = __switchdev_port_obj_add(lower_dev, obj); 209 if (err) 210 break; 211 } 212 213 return err; 214 } 215 216 /** 217 * switchdev_port_obj_add - Add port object 218 * 219 * @dev: port device 220 * @obj: object to add 221 * 222 * Use a 2-phase prepare-commit transaction model to ensure 223 * system is not left in a partially updated state due to 224 * failure from driver/device. 225 * 226 * rtnl_lock must be held. 227 */ 228 int switchdev_port_obj_add(struct net_device *dev, struct switchdev_obj *obj) 229 { 230 int err; 231 232 ASSERT_RTNL(); 233 234 /* Phase I: prepare for obj add. Driver/device should fail 235 * here if there are going to be issues in the commit phase, 236 * such as lack of resources or support. The driver/device 237 * should reserve resources needed for the commit phase here, 238 * but should not commit the obj. 239 */ 240 241 obj->trans = SWITCHDEV_TRANS_PREPARE; 242 err = __switchdev_port_obj_add(dev, obj); 243 if (err) { 244 /* Prepare phase failed: abort the transaction. Any 245 * resources reserved in the prepare phase are 246 * released. 247 */ 248 249 obj->trans = SWITCHDEV_TRANS_ABORT; 250 __switchdev_port_obj_add(dev, obj); 251 252 return err; 253 } 254 255 /* Phase II: commit obj add. This cannot fail as a fault 256 * of driver/device. If it does, it's a bug in the driver/device 257 * because the driver said everythings was OK in phase I. 258 */ 259 260 obj->trans = SWITCHDEV_TRANS_COMMIT; 261 err = __switchdev_port_obj_add(dev, obj); 262 WARN(err, "%s: Commit of object (id=%d) failed.\n", dev->name, obj->id); 263 264 return err; 265 } 266 EXPORT_SYMBOL_GPL(switchdev_port_obj_add); 267 268 /** 269 * switchdev_port_obj_del - Delete port object 270 * 271 * @dev: port device 272 * @obj: object to delete 273 */ 274 int switchdev_port_obj_del(struct net_device *dev, struct switchdev_obj *obj) 275 { 276 const struct switchdev_ops *ops = dev->switchdev_ops; 277 struct net_device *lower_dev; 278 struct list_head *iter; 279 int err = -EOPNOTSUPP; 280 281 if (ops && ops->switchdev_port_obj_del) 282 return ops->switchdev_port_obj_del(dev, obj); 283 284 /* Switch device port(s) may be stacked under 285 * bond/team/vlan dev, so recurse down to delete object on 286 * each port. 287 */ 288 289 netdev_for_each_lower_dev(dev, lower_dev, iter) { 290 err = switchdev_port_obj_del(lower_dev, obj); 291 if (err) 292 break; 293 } 294 295 return err; 296 } 297 EXPORT_SYMBOL_GPL(switchdev_port_obj_del); 298 299 /** 300 * switchdev_port_obj_dump - Dump port objects 301 * 302 * @dev: port device 303 * @obj: object to dump 304 */ 305 int switchdev_port_obj_dump(struct net_device *dev, struct switchdev_obj *obj) 306 { 307 const struct switchdev_ops *ops = dev->switchdev_ops; 308 struct net_device *lower_dev; 309 struct list_head *iter; 310 int err = -EOPNOTSUPP; 311 312 if (ops && ops->switchdev_port_obj_dump) 313 return ops->switchdev_port_obj_dump(dev, obj); 314 315 /* Switch device port(s) may be stacked under 316 * bond/team/vlan dev, so recurse down to dump objects on 317 * first port at bottom of stack. 318 */ 319 320 netdev_for_each_lower_dev(dev, lower_dev, iter) { 321 err = switchdev_port_obj_dump(lower_dev, obj); 322 break; 323 } 324 325 return err; 326 } 327 EXPORT_SYMBOL_GPL(switchdev_port_obj_dump); 328 329 static DEFINE_MUTEX(switchdev_mutex); 330 static RAW_NOTIFIER_HEAD(switchdev_notif_chain); 331 332 /** 333 * register_switchdev_notifier - Register notifier 334 * @nb: notifier_block 335 * 336 * Register switch device notifier. This should be used by code 337 * which needs to monitor events happening in particular device. 338 * Return values are same as for atomic_notifier_chain_register(). 339 */ 340 int register_switchdev_notifier(struct notifier_block *nb) 341 { 342 int err; 343 344 mutex_lock(&switchdev_mutex); 345 err = raw_notifier_chain_register(&switchdev_notif_chain, nb); 346 mutex_unlock(&switchdev_mutex); 347 return err; 348 } 349 EXPORT_SYMBOL_GPL(register_switchdev_notifier); 350 351 /** 352 * unregister_switchdev_notifier - Unregister notifier 353 * @nb: notifier_block 354 * 355 * Unregister switch device notifier. 356 * Return values are same as for atomic_notifier_chain_unregister(). 357 */ 358 int unregister_switchdev_notifier(struct notifier_block *nb) 359 { 360 int err; 361 362 mutex_lock(&switchdev_mutex); 363 err = raw_notifier_chain_unregister(&switchdev_notif_chain, nb); 364 mutex_unlock(&switchdev_mutex); 365 return err; 366 } 367 EXPORT_SYMBOL_GPL(unregister_switchdev_notifier); 368 369 /** 370 * call_switchdev_notifiers - Call notifiers 371 * @val: value passed unmodified to notifier function 372 * @dev: port device 373 * @info: notifier information data 374 * 375 * Call all network notifier blocks. This should be called by driver 376 * when it needs to propagate hardware event. 377 * Return values are same as for atomic_notifier_call_chain(). 378 */ 379 int call_switchdev_notifiers(unsigned long val, struct net_device *dev, 380 struct switchdev_notifier_info *info) 381 { 382 int err; 383 384 info->dev = dev; 385 mutex_lock(&switchdev_mutex); 386 err = raw_notifier_call_chain(&switchdev_notif_chain, val, info); 387 mutex_unlock(&switchdev_mutex); 388 return err; 389 } 390 EXPORT_SYMBOL_GPL(call_switchdev_notifiers); 391 392 /** 393 * switchdev_port_bridge_getlink - Get bridge port attributes 394 * 395 * @dev: port device 396 * 397 * Called for SELF on rtnl_bridge_getlink to get bridge port 398 * attributes. 399 */ 400 int switchdev_port_bridge_getlink(struct sk_buff *skb, u32 pid, u32 seq, 401 struct net_device *dev, u32 filter_mask, 402 int nlflags) 403 { 404 struct switchdev_attr attr = { 405 .id = SWITCHDEV_ATTR_PORT_BRIDGE_FLAGS, 406 }; 407 u16 mode = BRIDGE_MODE_UNDEF; 408 u32 mask = BR_LEARNING | BR_LEARNING_SYNC; 409 int err; 410 411 err = switchdev_port_attr_get(dev, &attr); 412 if (err) 413 return err; 414 415 return ndo_dflt_bridge_getlink(skb, pid, seq, dev, mode, 416 attr.u.brport_flags, mask, nlflags); 417 } 418 EXPORT_SYMBOL_GPL(switchdev_port_bridge_getlink); 419 420 static int switchdev_port_br_setflag(struct net_device *dev, 421 struct nlattr *nlattr, 422 unsigned long brport_flag) 423 { 424 struct switchdev_attr attr = { 425 .id = SWITCHDEV_ATTR_PORT_BRIDGE_FLAGS, 426 }; 427 u8 flag = nla_get_u8(nlattr); 428 int err; 429 430 err = switchdev_port_attr_get(dev, &attr); 431 if (err) 432 return err; 433 434 if (flag) 435 attr.u.brport_flags |= brport_flag; 436 else 437 attr.u.brport_flags &= ~brport_flag; 438 439 return switchdev_port_attr_set(dev, &attr); 440 } 441 442 static const struct nla_policy 443 switchdev_port_bridge_policy[IFLA_BRPORT_MAX + 1] = { 444 [IFLA_BRPORT_STATE] = { .type = NLA_U8 }, 445 [IFLA_BRPORT_COST] = { .type = NLA_U32 }, 446 [IFLA_BRPORT_PRIORITY] = { .type = NLA_U16 }, 447 [IFLA_BRPORT_MODE] = { .type = NLA_U8 }, 448 [IFLA_BRPORT_GUARD] = { .type = NLA_U8 }, 449 [IFLA_BRPORT_PROTECT] = { .type = NLA_U8 }, 450 [IFLA_BRPORT_FAST_LEAVE] = { .type = NLA_U8 }, 451 [IFLA_BRPORT_LEARNING] = { .type = NLA_U8 }, 452 [IFLA_BRPORT_LEARNING_SYNC] = { .type = NLA_U8 }, 453 [IFLA_BRPORT_UNICAST_FLOOD] = { .type = NLA_U8 }, 454 }; 455 456 static int switchdev_port_br_setlink_protinfo(struct net_device *dev, 457 struct nlattr *protinfo) 458 { 459 struct nlattr *attr; 460 int rem; 461 int err; 462 463 err = nla_validate_nested(protinfo, IFLA_BRPORT_MAX, 464 switchdev_port_bridge_policy); 465 if (err) 466 return err; 467 468 nla_for_each_nested(attr, protinfo, rem) { 469 switch (nla_type(attr)) { 470 case IFLA_BRPORT_LEARNING: 471 err = switchdev_port_br_setflag(dev, attr, 472 BR_LEARNING); 473 break; 474 case IFLA_BRPORT_LEARNING_SYNC: 475 err = switchdev_port_br_setflag(dev, attr, 476 BR_LEARNING_SYNC); 477 break; 478 default: 479 err = -EOPNOTSUPP; 480 break; 481 } 482 if (err) 483 return err; 484 } 485 486 return 0; 487 } 488 489 static int switchdev_port_br_afspec(struct net_device *dev, 490 struct nlattr *afspec, 491 int (*f)(struct net_device *dev, 492 struct switchdev_obj *obj)) 493 { 494 struct nlattr *attr; 495 struct bridge_vlan_info *vinfo; 496 struct switchdev_obj obj = { 497 .id = SWITCHDEV_OBJ_PORT_VLAN, 498 }; 499 struct switchdev_obj_vlan *vlan = &obj.u.vlan; 500 int rem; 501 int err; 502 503 nla_for_each_nested(attr, afspec, rem) { 504 if (nla_type(attr) != IFLA_BRIDGE_VLAN_INFO) 505 continue; 506 if (nla_len(attr) != sizeof(struct bridge_vlan_info)) 507 return -EINVAL; 508 vinfo = nla_data(attr); 509 vlan->flags = vinfo->flags; 510 if (vinfo->flags & BRIDGE_VLAN_INFO_RANGE_BEGIN) { 511 if (vlan->vid_start) 512 return -EINVAL; 513 vlan->vid_start = vinfo->vid; 514 } else if (vinfo->flags & BRIDGE_VLAN_INFO_RANGE_END) { 515 if (!vlan->vid_start) 516 return -EINVAL; 517 vlan->vid_end = vinfo->vid; 518 if (vlan->vid_end <= vlan->vid_start) 519 return -EINVAL; 520 err = f(dev, &obj); 521 if (err) 522 return err; 523 memset(vlan, 0, sizeof(*vlan)); 524 } else { 525 if (vlan->vid_start) 526 return -EINVAL; 527 vlan->vid_start = vinfo->vid; 528 vlan->vid_end = vinfo->vid; 529 err = f(dev, &obj); 530 if (err) 531 return err; 532 memset(vlan, 0, sizeof(*vlan)); 533 } 534 } 535 536 return 0; 537 } 538 539 /** 540 * switchdev_port_bridge_setlink - Set bridge port attributes 541 * 542 * @dev: port device 543 * @nlh: netlink header 544 * @flags: netlink flags 545 * 546 * Called for SELF on rtnl_bridge_setlink to set bridge port 547 * attributes. 548 */ 549 int switchdev_port_bridge_setlink(struct net_device *dev, 550 struct nlmsghdr *nlh, u16 flags) 551 { 552 struct nlattr *protinfo; 553 struct nlattr *afspec; 554 int err = 0; 555 556 protinfo = nlmsg_find_attr(nlh, sizeof(struct ifinfomsg), 557 IFLA_PROTINFO); 558 if (protinfo) { 559 err = switchdev_port_br_setlink_protinfo(dev, protinfo); 560 if (err) 561 return err; 562 } 563 564 afspec = nlmsg_find_attr(nlh, sizeof(struct ifinfomsg), 565 IFLA_AF_SPEC); 566 if (afspec) 567 err = switchdev_port_br_afspec(dev, afspec, 568 switchdev_port_obj_add); 569 570 return err; 571 } 572 EXPORT_SYMBOL_GPL(switchdev_port_bridge_setlink); 573 574 /** 575 * switchdev_port_bridge_dellink - Set bridge port attributes 576 * 577 * @dev: port device 578 * @nlh: netlink header 579 * @flags: netlink flags 580 * 581 * Called for SELF on rtnl_bridge_dellink to set bridge port 582 * attributes. 583 */ 584 int switchdev_port_bridge_dellink(struct net_device *dev, 585 struct nlmsghdr *nlh, u16 flags) 586 { 587 struct nlattr *afspec; 588 589 afspec = nlmsg_find_attr(nlh, sizeof(struct ifinfomsg), 590 IFLA_AF_SPEC); 591 if (afspec) 592 return switchdev_port_br_afspec(dev, afspec, 593 switchdev_port_obj_del); 594 595 return 0; 596 } 597 EXPORT_SYMBOL_GPL(switchdev_port_bridge_dellink); 598 599 /** 600 * switchdev_port_fdb_add - Add FDB (MAC/VLAN) entry to port 601 * 602 * @ndmsg: netlink hdr 603 * @nlattr: netlink attributes 604 * @dev: port device 605 * @addr: MAC address to add 606 * @vid: VLAN to add 607 * 608 * Add FDB entry to switch device. 609 */ 610 int switchdev_port_fdb_add(struct ndmsg *ndm, struct nlattr *tb[], 611 struct net_device *dev, const unsigned char *addr, 612 u16 vid, u16 nlm_flags) 613 { 614 struct switchdev_obj obj = { 615 .id = SWITCHDEV_OBJ_PORT_FDB, 616 .u.fdb = { 617 .addr = addr, 618 .vid = vid, 619 }, 620 }; 621 622 return switchdev_port_obj_add(dev, &obj); 623 } 624 EXPORT_SYMBOL_GPL(switchdev_port_fdb_add); 625 626 /** 627 * switchdev_port_fdb_del - Delete FDB (MAC/VLAN) entry from port 628 * 629 * @ndmsg: netlink hdr 630 * @nlattr: netlink attributes 631 * @dev: port device 632 * @addr: MAC address to delete 633 * @vid: VLAN to delete 634 * 635 * Delete FDB entry from switch device. 636 */ 637 int switchdev_port_fdb_del(struct ndmsg *ndm, struct nlattr *tb[], 638 struct net_device *dev, const unsigned char *addr, 639 u16 vid) 640 { 641 struct switchdev_obj obj = { 642 .id = SWITCHDEV_OBJ_PORT_FDB, 643 .u.fdb = { 644 .addr = addr, 645 .vid = vid, 646 }, 647 }; 648 649 return switchdev_port_obj_del(dev, &obj); 650 } 651 EXPORT_SYMBOL_GPL(switchdev_port_fdb_del); 652 653 struct switchdev_fdb_dump { 654 struct switchdev_obj obj; 655 struct sk_buff *skb; 656 struct netlink_callback *cb; 657 struct net_device *filter_dev; 658 int idx; 659 }; 660 661 static int switchdev_port_fdb_dump_cb(struct net_device *dev, 662 struct switchdev_obj *obj) 663 { 664 struct switchdev_fdb_dump *dump = 665 container_of(obj, struct switchdev_fdb_dump, obj); 666 u32 portid = NETLINK_CB(dump->cb->skb).portid; 667 u32 seq = dump->cb->nlh->nlmsg_seq; 668 struct nlmsghdr *nlh; 669 struct ndmsg *ndm; 670 struct net_device *master = netdev_master_upper_dev_get(dev); 671 672 if (dump->idx < dump->cb->args[0]) 673 goto skip; 674 675 if (master && dump->filter_dev != master) 676 goto skip; 677 678 nlh = nlmsg_put(dump->skb, portid, seq, RTM_NEWNEIGH, 679 sizeof(*ndm), NLM_F_MULTI); 680 if (!nlh) 681 return -EMSGSIZE; 682 683 ndm = nlmsg_data(nlh); 684 ndm->ndm_family = AF_BRIDGE; 685 ndm->ndm_pad1 = 0; 686 ndm->ndm_pad2 = 0; 687 ndm->ndm_flags = NTF_SELF; 688 ndm->ndm_type = 0; 689 ndm->ndm_ifindex = dev->ifindex; 690 ndm->ndm_state = NUD_REACHABLE; 691 692 if (nla_put(dump->skb, NDA_LLADDR, ETH_ALEN, obj->u.fdb.addr)) 693 goto nla_put_failure; 694 695 if (obj->u.fdb.vid && nla_put_u16(dump->skb, NDA_VLAN, obj->u.fdb.vid)) 696 goto nla_put_failure; 697 698 nlmsg_end(dump->skb, nlh); 699 700 skip: 701 dump->idx++; 702 return 0; 703 704 nla_put_failure: 705 nlmsg_cancel(dump->skb, nlh); 706 return -EMSGSIZE; 707 } 708 709 /** 710 * switchdev_port_fdb_dump - Dump port FDB (MAC/VLAN) entries 711 * 712 * @skb: netlink skb 713 * @cb: netlink callback 714 * @dev: port device 715 * @filter_dev: filter device 716 * @idx: 717 * 718 * Delete FDB entry from switch device. 719 */ 720 int switchdev_port_fdb_dump(struct sk_buff *skb, struct netlink_callback *cb, 721 struct net_device *dev, 722 struct net_device *filter_dev, int idx) 723 { 724 struct switchdev_fdb_dump dump = { 725 .obj = { 726 .id = SWITCHDEV_OBJ_PORT_FDB, 727 .cb = switchdev_port_fdb_dump_cb, 728 }, 729 .skb = skb, 730 .cb = cb, 731 .filter_dev = filter_dev, 732 .idx = idx, 733 }; 734 int err; 735 736 err = switchdev_port_obj_dump(dev, &dump.obj); 737 if (err) 738 return err; 739 740 return dump.idx; 741 } 742 EXPORT_SYMBOL_GPL(switchdev_port_fdb_dump); 743 744 static struct net_device *switchdev_get_lowest_dev(struct net_device *dev) 745 { 746 const struct switchdev_ops *ops = dev->switchdev_ops; 747 struct net_device *lower_dev; 748 struct net_device *port_dev; 749 struct list_head *iter; 750 751 /* Recusively search down until we find a sw port dev. 752 * (A sw port dev supports switchdev_port_attr_get). 753 */ 754 755 if (ops && ops->switchdev_port_attr_get) 756 return dev; 757 758 netdev_for_each_lower_dev(dev, lower_dev, iter) { 759 port_dev = switchdev_get_lowest_dev(lower_dev); 760 if (port_dev) 761 return port_dev; 762 } 763 764 return NULL; 765 } 766 767 static struct net_device *switchdev_get_dev_by_nhs(struct fib_info *fi) 768 { 769 struct switchdev_attr attr = { 770 .id = SWITCHDEV_ATTR_PORT_PARENT_ID, 771 }; 772 struct switchdev_attr prev_attr; 773 struct net_device *dev = NULL; 774 int nhsel; 775 776 /* For this route, all nexthop devs must be on the same switch. */ 777 778 for (nhsel = 0; nhsel < fi->fib_nhs; nhsel++) { 779 const struct fib_nh *nh = &fi->fib_nh[nhsel]; 780 781 if (!nh->nh_dev) 782 return NULL; 783 784 dev = switchdev_get_lowest_dev(nh->nh_dev); 785 if (!dev) 786 return NULL; 787 788 if (switchdev_port_attr_get(dev, &attr)) 789 return NULL; 790 791 if (nhsel > 0) { 792 if (prev_attr.u.ppid.id_len != attr.u.ppid.id_len) 793 return NULL; 794 if (memcmp(prev_attr.u.ppid.id, attr.u.ppid.id, 795 attr.u.ppid.id_len)) 796 return NULL; 797 } 798 799 prev_attr = attr; 800 } 801 802 return dev; 803 } 804 805 /** 806 * switchdev_fib_ipv4_add - Add IPv4 route entry to switch 807 * 808 * @dst: route's IPv4 destination address 809 * @dst_len: destination address length (prefix length) 810 * @fi: route FIB info structure 811 * @tos: route TOS 812 * @type: route type 813 * @nlflags: netlink flags passed in (NLM_F_*) 814 * @tb_id: route table ID 815 * 816 * Add IPv4 route entry to switch device. 817 */ 818 int switchdev_fib_ipv4_add(u32 dst, int dst_len, struct fib_info *fi, 819 u8 tos, u8 type, u32 nlflags, u32 tb_id) 820 { 821 struct switchdev_obj fib_obj = { 822 .id = SWITCHDEV_OBJ_IPV4_FIB, 823 .u.ipv4_fib = { 824 .dst = dst, 825 .dst_len = dst_len, 826 .fi = fi, 827 .tos = tos, 828 .type = type, 829 .nlflags = nlflags, 830 .tb_id = tb_id, 831 }, 832 }; 833 struct net_device *dev; 834 int err = 0; 835 836 /* Don't offload route if using custom ip rules or if 837 * IPv4 FIB offloading has been disabled completely. 838 */ 839 840 #ifdef CONFIG_IP_MULTIPLE_TABLES 841 if (fi->fib_net->ipv4.fib_has_custom_rules) 842 return 0; 843 #endif 844 845 if (fi->fib_net->ipv4.fib_offload_disabled) 846 return 0; 847 848 dev = switchdev_get_dev_by_nhs(fi); 849 if (!dev) 850 return 0; 851 852 err = switchdev_port_obj_add(dev, &fib_obj); 853 if (!err) 854 fi->fib_flags |= RTNH_F_OFFLOAD; 855 856 return err; 857 } 858 EXPORT_SYMBOL_GPL(switchdev_fib_ipv4_add); 859 860 /** 861 * switchdev_fib_ipv4_del - Delete IPv4 route entry from switch 862 * 863 * @dst: route's IPv4 destination address 864 * @dst_len: destination address length (prefix length) 865 * @fi: route FIB info structure 866 * @tos: route TOS 867 * @type: route type 868 * @tb_id: route table ID 869 * 870 * Delete IPv4 route entry from switch device. 871 */ 872 int switchdev_fib_ipv4_del(u32 dst, int dst_len, struct fib_info *fi, 873 u8 tos, u8 type, u32 tb_id) 874 { 875 struct switchdev_obj fib_obj = { 876 .id = SWITCHDEV_OBJ_IPV4_FIB, 877 .u.ipv4_fib = { 878 .dst = dst, 879 .dst_len = dst_len, 880 .fi = fi, 881 .tos = tos, 882 .type = type, 883 .nlflags = 0, 884 .tb_id = tb_id, 885 }, 886 }; 887 struct net_device *dev; 888 int err = 0; 889 890 if (!(fi->fib_flags & RTNH_F_OFFLOAD)) 891 return 0; 892 893 dev = switchdev_get_dev_by_nhs(fi); 894 if (!dev) 895 return 0; 896 897 err = switchdev_port_obj_del(dev, &fib_obj); 898 if (!err) 899 fi->fib_flags &= ~RTNH_F_OFFLOAD; 900 901 return err; 902 } 903 EXPORT_SYMBOL_GPL(switchdev_fib_ipv4_del); 904 905 /** 906 * switchdev_fib_ipv4_abort - Abort an IPv4 FIB operation 907 * 908 * @fi: route FIB info structure 909 */ 910 void switchdev_fib_ipv4_abort(struct fib_info *fi) 911 { 912 /* There was a problem installing this route to the offload 913 * device. For now, until we come up with more refined 914 * policy handling, abruptly end IPv4 fib offloading for 915 * for entire net by flushing offload device(s) of all 916 * IPv4 routes, and mark IPv4 fib offloading broken from 917 * this point forward. 918 */ 919 920 fib_flush_external(fi->fib_net); 921 fi->fib_net->ipv4.fib_offload_disabled = true; 922 } 923 EXPORT_SYMBOL_GPL(switchdev_fib_ipv4_abort); 924