.. | .. |
---|
| 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); |
---|