| .. | .. |
|---|
| 1 | +// SPDX-License-Identifier: GPL-2.0-or-later |
|---|
| 1 | 2 | /* |
|---|
| 2 | 3 | * Userspace interface |
|---|
| 3 | 4 | * Linux ethernet bridge |
|---|
| 4 | 5 | * |
|---|
| 5 | 6 | * Authors: |
|---|
| 6 | 7 | * Lennert Buytenhek <buytenh@gnu.org> |
|---|
| 7 | | - * |
|---|
| 8 | | - * This program is free software; you can redistribute it and/or |
|---|
| 9 | | - * modify it under the terms of the GNU General Public License |
|---|
| 10 | | - * as published by the Free Software Foundation; either version |
|---|
| 11 | | - * 2 of the License, or (at your option) any later version. |
|---|
| 12 | 8 | */ |
|---|
| 13 | 9 | |
|---|
| 14 | 10 | #include <linux/kernel.h> |
|---|
| .. | .. |
|---|
| 161 | 157 | * This lets us disable promiscuous mode and write |
|---|
| 162 | 158 | * this config to hw. |
|---|
| 163 | 159 | */ |
|---|
| 164 | | - if (br->auto_cnt == 0 || |
|---|
| 165 | | - (br->auto_cnt == 1 && br_auto_port(p))) |
|---|
| 160 | + if ((p->dev->priv_flags & IFF_UNICAST_FLT) && |
|---|
| 161 | + (br->auto_cnt == 0 || |
|---|
| 162 | + (br->auto_cnt == 1 && br_auto_port(p)))) |
|---|
| 166 | 163 | br_port_clear_promisc(p); |
|---|
| 167 | 164 | else |
|---|
| 168 | 165 | br_port_set_promisc(p); |
|---|
| .. | .. |
|---|
| 179 | 176 | ASSERT_RTNL(); |
|---|
| 180 | 177 | |
|---|
| 181 | 178 | if (backup_dev) { |
|---|
| 182 | | - if (!br_port_exists(backup_dev)) |
|---|
| 179 | + if (!netif_is_bridge_port(backup_dev)) |
|---|
| 183 | 180 | return -ENOENT; |
|---|
| 184 | 181 | |
|---|
| 185 | 182 | backup_p = br_port_get_rtnl(backup_dev); |
|---|
| .. | .. |
|---|
| 337 | 334 | br_stp_disable_port(p); |
|---|
| 338 | 335 | spin_unlock_bh(&br->lock); |
|---|
| 339 | 336 | |
|---|
| 337 | + br_mrp_port_del(br, p); |
|---|
| 338 | + |
|---|
| 340 | 339 | br_ifinfo_notify(RTM_DELLINK, NULL, p); |
|---|
| 341 | 340 | |
|---|
| 342 | 341 | list_del_rcu(&p->list); |
|---|
| .. | .. |
|---|
| 394 | 393 | struct net_bridge_port *p; |
|---|
| 395 | 394 | unsigned long *inuse; |
|---|
| 396 | 395 | |
|---|
| 397 | | - inuse = kcalloc(BITS_TO_LONGS(BR_MAX_PORTS), sizeof(unsigned long), |
|---|
| 398 | | - GFP_KERNEL); |
|---|
| 396 | + inuse = bitmap_zalloc(BR_MAX_PORTS, GFP_KERNEL); |
|---|
| 399 | 397 | if (!inuse) |
|---|
| 400 | 398 | return -ENOMEM; |
|---|
| 401 | 399 | |
|---|
| .. | .. |
|---|
| 404 | 402 | set_bit(p->port_no, inuse); |
|---|
| 405 | 403 | } |
|---|
| 406 | 404 | index = find_first_zero_bit(inuse, BR_MAX_PORTS); |
|---|
| 407 | | - kfree(inuse); |
|---|
| 405 | + bitmap_free(inuse); |
|---|
| 408 | 406 | |
|---|
| 409 | 407 | return (index >= BR_MAX_PORTS) ? -EXFULL : index; |
|---|
| 410 | 408 | } |
|---|
| .. | .. |
|---|
| 509 | 507 | ASSERT_RTNL(); |
|---|
| 510 | 508 | |
|---|
| 511 | 509 | /* if the bridge MTU was manually configured don't mess with it */ |
|---|
| 512 | | - if (br->mtu_set_by_user) |
|---|
| 510 | + if (br_opt_get(br, BROPT_MTU_SET_BY_USER)) |
|---|
| 513 | 511 | return; |
|---|
| 514 | 512 | |
|---|
| 515 | 513 | /* change to the minimum MTU and clear the flag which was set by |
|---|
| 516 | 514 | * the bridge ndo_change_mtu callback |
|---|
| 517 | 515 | */ |
|---|
| 518 | 516 | dev_set_mtu(br->dev, br_mtu_min(br)); |
|---|
| 519 | | - br->mtu_set_by_user = false; |
|---|
| 517 | + br_opt_toggle(br, BROPT_MTU_SET_BY_USER, false); |
|---|
| 520 | 518 | } |
|---|
| 521 | 519 | |
|---|
| 522 | 520 | static void br_set_gso_limits(struct net_bridge *br) |
|---|
| .. | .. |
|---|
| 566 | 564 | unsigned br_hr, dev_hr; |
|---|
| 567 | 565 | bool changed_addr, fdb_synced = false; |
|---|
| 568 | 566 | |
|---|
| 569 | | - /* Don't allow bridging non-ethernet like devices, or DSA-enabled |
|---|
| 570 | | - * master network devices since the bridge layer rx_handler prevents |
|---|
| 571 | | - * the DSA fake ethertype handler to be invoked, so we do not strip off |
|---|
| 572 | | - * the DSA switch tag protocol header and the bridge layer just return |
|---|
| 573 | | - * RX_HANDLER_CONSUMED, stopping RX processing for these frames. |
|---|
| 574 | | - */ |
|---|
| 567 | + /* Don't allow bridging non-ethernet like devices. */ |
|---|
| 575 | 568 | if ((dev->flags & IFF_LOOPBACK) || |
|---|
| 576 | 569 | dev->type != ARPHRD_ETHER || dev->addr_len != ETH_ALEN || |
|---|
| 577 | | - !is_valid_ether_addr(dev->dev_addr) || |
|---|
| 578 | | - netdev_uses_dsa(dev)) |
|---|
| 570 | + !is_valid_ether_addr(dev->dev_addr)) |
|---|
| 579 | 571 | return -EINVAL; |
|---|
| 572 | + |
|---|
| 573 | + /* Also don't allow bridging of net devices that are DSA masters, since |
|---|
| 574 | + * the bridge layer rx_handler prevents the DSA fake ethertype handler |
|---|
| 575 | + * to be invoked, so we don't get the chance to strip off and parse the |
|---|
| 576 | + * DSA switch tag protocol header (the bridge layer just returns |
|---|
| 577 | + * RX_HANDLER_CONSUMED, stopping RX processing for these frames). |
|---|
| 578 | + * The only case where that would not be an issue is when bridging can |
|---|
| 579 | + * already be offloaded, such as when the DSA master is itself a DSA |
|---|
| 580 | + * or plain switchdev port, and is bridged only with other ports from |
|---|
| 581 | + * the same hardware device. |
|---|
| 582 | + */ |
|---|
| 583 | + if (netdev_uses_dsa(dev)) { |
|---|
| 584 | + list_for_each_entry(p, &br->port_list, list) { |
|---|
| 585 | + if (!netdev_port_same_parent_id(dev, p->dev)) { |
|---|
| 586 | + NL_SET_ERR_MSG(extack, |
|---|
| 587 | + "Cannot do software bridging with a DSA master"); |
|---|
| 588 | + return -EINVAL; |
|---|
| 589 | + } |
|---|
| 590 | + } |
|---|
| 591 | + } |
|---|
| 580 | 592 | |
|---|
| 581 | 593 | /* No bridging of bridges */ |
|---|
| 582 | 594 | if (dev->netdev_ops->ndo_start_xmit == br_dev_xmit) { |
|---|
| .. | .. |
|---|
| 622 | 634 | if (err) |
|---|
| 623 | 635 | goto err3; |
|---|
| 624 | 636 | |
|---|
| 625 | | - err = netdev_rx_handler_register(dev, br_handle_frame, p); |
|---|
| 637 | + err = netdev_rx_handler_register(dev, br_get_rx_handler(dev), p); |
|---|
| 626 | 638 | if (err) |
|---|
| 627 | 639 | goto err4; |
|---|
| 628 | 640 | |
|---|
| .. | .. |
|---|
| 667 | 679 | if (br_fdb_insert(br, p, dev->dev_addr, 0)) |
|---|
| 668 | 680 | netdev_err(dev, "failed insert local address bridge forwarding table\n"); |
|---|
| 669 | 681 | |
|---|
| 670 | | - err = nbp_vlan_init(p); |
|---|
| 682 | + if (br->dev->addr_assign_type != NET_ADDR_SET) { |
|---|
| 683 | + /* Ask for permission to use this MAC address now, even if we |
|---|
| 684 | + * don't end up choosing it below. |
|---|
| 685 | + */ |
|---|
| 686 | + err = dev_pre_changeaddr_notify(br->dev, dev->dev_addr, extack); |
|---|
| 687 | + if (err) |
|---|
| 688 | + goto err7; |
|---|
| 689 | + } |
|---|
| 690 | + |
|---|
| 691 | + err = nbp_vlan_init(p, extack); |
|---|
| 671 | 692 | if (err) { |
|---|
| 672 | 693 | netdev_err(dev, "failed to initialize vlan filtering on this port\n"); |
|---|
| 673 | 694 | goto err7; |
|---|
| .. | .. |
|---|
| 758 | 779 | if (mask & BR_NEIGH_SUPPRESS) |
|---|
| 759 | 780 | br_recalculate_neigh_suppress_enabled(br); |
|---|
| 760 | 781 | } |
|---|
| 782 | + |
|---|
| 783 | +bool br_port_flag_is_set(const struct net_device *dev, unsigned long flag) |
|---|
| 784 | +{ |
|---|
| 785 | + struct net_bridge_port *p; |
|---|
| 786 | + |
|---|
| 787 | + p = br_port_get_rtnl_rcu(dev); |
|---|
| 788 | + if (!p) |
|---|
| 789 | + return false; |
|---|
| 790 | + |
|---|
| 791 | + return p->flags & flag; |
|---|
| 792 | +} |
|---|
| 793 | +EXPORT_SYMBOL_GPL(br_port_flag_is_set); |
|---|