12874c5fdSThomas Gleixner // SPDX-License-Identifier: GPL-2.0-or-later
21da177e4SLinus Torvalds /*
31da177e4SLinus Torvalds * Userspace interface
41da177e4SLinus Torvalds * Linux ethernet bridge
51da177e4SLinus Torvalds *
61da177e4SLinus Torvalds * Authors:
71da177e4SLinus Torvalds * Lennert Buytenhek <buytenh@gnu.org>
81da177e4SLinus Torvalds */
91da177e4SLinus Torvalds
101da177e4SLinus Torvalds #include <linux/kernel.h>
111da177e4SLinus Torvalds #include <linux/netdevice.h>
1277f98598Sstephen hemminger #include <linux/etherdevice.h>
13c06ee961SWANG Cong #include <linux/netpoll.h>
141da177e4SLinus Torvalds #include <linux/ethtool.h>
151da177e4SLinus Torvalds #include <linux/if_arp.h>
161da177e4SLinus Torvalds #include <linux/module.h>
171da177e4SLinus Torvalds #include <linux/init.h>
181da177e4SLinus Torvalds #include <linux/rtnetlink.h>
1946f25dffSKris Katterjohn #include <linux/if_ether.h>
205a0e3ad6STejun Heo #include <linux/slab.h>
21c6e970a0SAndrew Lunn #include <net/dsa.h>
221da177e4SLinus Torvalds #include <net/sock.h>
23407af329SVlad Yasevich #include <linux/if_vlan.h>
2456607386SJiri Pirko #include <net/switchdev.h>
25705e0deaSTyler Hicks #include <net/net_namespace.h>
261da177e4SLinus Torvalds
271da177e4SLinus Torvalds #include "br_private.h"
281da177e4SLinus Torvalds
291da177e4SLinus Torvalds /*
301da177e4SLinus Torvalds * Determine initial path cost based on speed.
311da177e4SLinus Torvalds * using recommendations from 802.1d standard
321da177e4SLinus Torvalds *
3361a44b9cSMatthew Wilcox * Since driver might sleep need to not be holding any locks.
341da177e4SLinus Torvalds */
port_cost(struct net_device * dev)354433f420SStephen Hemminger static int port_cost(struct net_device *dev)
361da177e4SLinus Torvalds {
37702b26a2SDavid Decotigny struct ethtool_link_ksettings ecmd;
38b4a488d1SStephen Hemminger
39702b26a2SDavid Decotigny if (!__ethtool_get_link_ksettings(dev, &ecmd)) {
40702b26a2SDavid Decotigny switch (ecmd.base.speed) {
411da177e4SLinus Torvalds case SPEED_10000:
421da177e4SLinus Torvalds return 2;
43bd139381SSteven Hsieh case SPEED_5000:
44bd139381SSteven Hsieh return 3;
45bd139381SSteven Hsieh case SPEED_2500:
46b4a488d1SStephen Hemminger return 4;
47bd139381SSteven Hsieh case SPEED_1000:
48bd139381SSteven Hsieh return 5;
49b4a488d1SStephen Hemminger case SPEED_100:
50b4a488d1SStephen Hemminger return 19;
511da177e4SLinus Torvalds case SPEED_10:
521da177e4SLinus Torvalds return 100;
53bd139381SSteven Hsieh case SPEED_UNKNOWN:
54bd139381SSteven Hsieh return 100;
55bd139381SSteven Hsieh default:
56bd139381SSteven Hsieh if (ecmd.base.speed > SPEED_10000)
57bd139381SSteven Hsieh return 1;
581da177e4SLinus Torvalds }
591da177e4SLinus Torvalds }
601da177e4SLinus Torvalds
611da177e4SLinus Torvalds /* Old silly heuristics based on name */
621da177e4SLinus Torvalds if (!strncmp(dev->name, "lec", 3))
631da177e4SLinus Torvalds return 7;
641da177e4SLinus Torvalds
651da177e4SLinus Torvalds if (!strncmp(dev->name, "plip", 4))
661da177e4SLinus Torvalds return 2500;
671da177e4SLinus Torvalds
681da177e4SLinus Torvalds return 100; /* assume old 10Mbps */
691da177e4SLinus Torvalds }
701da177e4SLinus Torvalds
714433f420SStephen Hemminger
721a81a2e0Stanxiaojun /* Check for port carrier transitions. */
br_port_carrier_check(struct net_bridge_port * p,bool * notified)73faa1cd82SNikolay Aleksandrov void br_port_carrier_check(struct net_bridge_port *p, bool *notified)
744433f420SStephen Hemminger {
75269def7cSStephen Hemminger struct net_device *dev = p->dev;
76269def7cSStephen Hemminger struct net_bridge *br = p->br;
77b3f1be4bSStephen Hemminger
788f3359bdSstephen hemminger if (!(p->flags & BR_ADMIN_COST) &&
798f3359bdSstephen hemminger netif_running(dev) && netif_oper_up(dev))
806e86b890SStephen Hemminger p->path_cost = port_cost(dev);
814433f420SStephen Hemminger
82faa1cd82SNikolay Aleksandrov *notified = false;
83aa7c6e5fSstephen hemminger if (!netif_running(br->dev))
84aa7c6e5fSstephen hemminger return;
85aa7c6e5fSstephen hemminger
866e86b890SStephen Hemminger spin_lock_bh(&br->lock);
87576eb625Sstephen hemminger if (netif_running(dev) && netif_oper_up(dev)) {
88faa1cd82SNikolay Aleksandrov if (p->state == BR_STATE_DISABLED) {
894433f420SStephen Hemminger br_stp_enable_port(p);
90faa1cd82SNikolay Aleksandrov *notified = true;
91faa1cd82SNikolay Aleksandrov }
924433f420SStephen Hemminger } else {
93faa1cd82SNikolay Aleksandrov if (p->state != BR_STATE_DISABLED) {
944433f420SStephen Hemminger br_stp_disable_port(p);
95faa1cd82SNikolay Aleksandrov *notified = true;
96faa1cd82SNikolay Aleksandrov }
976e86b890SStephen Hemminger }
986e86b890SStephen Hemminger spin_unlock_bh(&br->lock);
994433f420SStephen Hemminger }
1004433f420SStephen Hemminger
br_port_set_promisc(struct net_bridge_port * p)1012796d0c6SVlad Yasevich static void br_port_set_promisc(struct net_bridge_port *p)
1022796d0c6SVlad Yasevich {
1032796d0c6SVlad Yasevich int err = 0;
1042796d0c6SVlad Yasevich
1052796d0c6SVlad Yasevich if (br_promisc_port(p))
1062796d0c6SVlad Yasevich return;
1072796d0c6SVlad Yasevich
1082796d0c6SVlad Yasevich err = dev_set_promiscuity(p->dev, 1);
1092796d0c6SVlad Yasevich if (err)
1102796d0c6SVlad Yasevich return;
1112796d0c6SVlad Yasevich
1122796d0c6SVlad Yasevich br_fdb_unsync_static(p->br, p);
1132796d0c6SVlad Yasevich p->flags |= BR_PROMISC;
1142796d0c6SVlad Yasevich }
1152796d0c6SVlad Yasevich
br_port_clear_promisc(struct net_bridge_port * p)1162796d0c6SVlad Yasevich static void br_port_clear_promisc(struct net_bridge_port *p)
1172796d0c6SVlad Yasevich {
1182796d0c6SVlad Yasevich int err;
1192796d0c6SVlad Yasevich
1202796d0c6SVlad Yasevich /* Check if the port is already non-promisc or if it doesn't
1212796d0c6SVlad Yasevich * support UNICAST filtering. Without unicast filtering support
1222796d0c6SVlad Yasevich * we'll end up re-enabling promisc mode anyway, so just check for
1232796d0c6SVlad Yasevich * it here.
1242796d0c6SVlad Yasevich */
1252796d0c6SVlad Yasevich if (!br_promisc_port(p) || !(p->dev->priv_flags & IFF_UNICAST_FLT))
1262796d0c6SVlad Yasevich return;
1272796d0c6SVlad Yasevich
1282796d0c6SVlad Yasevich /* Since we'll be clearing the promisc mode, program the port
1292796d0c6SVlad Yasevich * first so that we don't have interruption in traffic.
1302796d0c6SVlad Yasevich */
1312796d0c6SVlad Yasevich err = br_fdb_sync_static(p->br, p);
1322796d0c6SVlad Yasevich if (err)
1332796d0c6SVlad Yasevich return;
1342796d0c6SVlad Yasevich
1352796d0c6SVlad Yasevich dev_set_promiscuity(p->dev, -1);
1362796d0c6SVlad Yasevich p->flags &= ~BR_PROMISC;
1372796d0c6SVlad Yasevich }
1382796d0c6SVlad Yasevich
1392796d0c6SVlad Yasevich /* When a port is added or removed or when certain port flags
1402796d0c6SVlad Yasevich * change, this function is called to automatically manage
1412796d0c6SVlad Yasevich * promiscuity setting of all the bridge ports. We are always called
1422796d0c6SVlad Yasevich * under RTNL so can skip using rcu primitives.
1432796d0c6SVlad Yasevich */
br_manage_promisc(struct net_bridge * br)1442796d0c6SVlad Yasevich void br_manage_promisc(struct net_bridge *br)
1452796d0c6SVlad Yasevich {
1462796d0c6SVlad Yasevich struct net_bridge_port *p;
1472796d0c6SVlad Yasevich bool set_all = false;
1482796d0c6SVlad Yasevich
1492796d0c6SVlad Yasevich /* If vlan filtering is disabled or bridge interface is placed
1502796d0c6SVlad Yasevich * into promiscuous mode, place all ports in promiscuous mode.
1512796d0c6SVlad Yasevich */
1521f51445aSIdo Schimmel if ((br->dev->flags & IFF_PROMISC) || !br_vlan_enabled(br->dev))
1532796d0c6SVlad Yasevich set_all = true;
1542796d0c6SVlad Yasevich
1552796d0c6SVlad Yasevich list_for_each_entry(p, &br->port_list, list) {
1562796d0c6SVlad Yasevich if (set_all) {
1572796d0c6SVlad Yasevich br_port_set_promisc(p);
1582796d0c6SVlad Yasevich } else {
1592796d0c6SVlad Yasevich /* If the number of auto-ports is <= 1, then all other
1602796d0c6SVlad Yasevich * ports will have their output configuration
1612796d0c6SVlad Yasevich * statically specified through fdbs. Since ingress
1622796d0c6SVlad Yasevich * on the auto-port becomes forwarding/egress to other
1632796d0c6SVlad Yasevich * ports and egress configuration is statically known,
1642796d0c6SVlad Yasevich * we can say that ingress configuration of the
1652796d0c6SVlad Yasevich * auto-port is also statically known.
1662796d0c6SVlad Yasevich * This lets us disable promiscuous mode and write
1672796d0c6SVlad Yasevich * this config to hw.
1682796d0c6SVlad Yasevich */
169e0a47d1fSToshiaki Makita if ((p->dev->priv_flags & IFF_UNICAST_FLT) &&
170e0a47d1fSToshiaki Makita (br->auto_cnt == 0 ||
1712796d0c6SVlad Yasevich (br->auto_cnt == 1 && br_auto_port(p))))
1722796d0c6SVlad Yasevich br_port_clear_promisc(p);
1732796d0c6SVlad Yasevich else
1742796d0c6SVlad Yasevich br_port_set_promisc(p);
1752796d0c6SVlad Yasevich }
1762796d0c6SVlad Yasevich }
1772796d0c6SVlad Yasevich }
1782756f68cSNikolay Aleksandrov
nbp_backup_change(struct net_bridge_port * p,struct net_device * backup_dev)1792756f68cSNikolay Aleksandrov int nbp_backup_change(struct net_bridge_port *p,
1802756f68cSNikolay Aleksandrov struct net_device *backup_dev)
1812756f68cSNikolay Aleksandrov {
1822756f68cSNikolay Aleksandrov struct net_bridge_port *old_backup = rtnl_dereference(p->backup_port);
1832756f68cSNikolay Aleksandrov struct net_bridge_port *backup_p = NULL;
1842756f68cSNikolay Aleksandrov
1852756f68cSNikolay Aleksandrov ASSERT_RTNL();
1862756f68cSNikolay Aleksandrov
18735f861e3SJulian Wiedmann if (backup_dev) {
1882756f68cSNikolay Aleksandrov if (!netif_is_bridge_port(backup_dev))
1892756f68cSNikolay Aleksandrov return -ENOENT;
1902756f68cSNikolay Aleksandrov
1912756f68cSNikolay Aleksandrov backup_p = br_port_get_rtnl(backup_dev);
1922756f68cSNikolay Aleksandrov if (backup_p->br != p->br)
1932756f68cSNikolay Aleksandrov return -EINVAL;
1942756f68cSNikolay Aleksandrov }
1952756f68cSNikolay Aleksandrov
1962756f68cSNikolay Aleksandrov if (p == backup_p)
1972756f68cSNikolay Aleksandrov return -EINVAL;
1982756f68cSNikolay Aleksandrov
1992756f68cSNikolay Aleksandrov if (old_backup == backup_p)
2002756f68cSNikolay Aleksandrov return 0;
2012756f68cSNikolay Aleksandrov
2022756f68cSNikolay Aleksandrov /* if the backup link is already set, clear it */
2032756f68cSNikolay Aleksandrov if (old_backup)
2042756f68cSNikolay Aleksandrov old_backup->backup_redirected_cnt--;
2052756f68cSNikolay Aleksandrov
2062756f68cSNikolay Aleksandrov if (backup_p)
2072756f68cSNikolay Aleksandrov backup_p->backup_redirected_cnt++;
2082756f68cSNikolay Aleksandrov rcu_assign_pointer(p->backup_port, backup_p);
2092756f68cSNikolay Aleksandrov
2102756f68cSNikolay Aleksandrov return 0;
2112756f68cSNikolay Aleksandrov }
2122756f68cSNikolay Aleksandrov
nbp_backup_clear(struct net_bridge_port * p)2132756f68cSNikolay Aleksandrov static void nbp_backup_clear(struct net_bridge_port *p)
2142756f68cSNikolay Aleksandrov {
2152756f68cSNikolay Aleksandrov nbp_backup_change(p, NULL);
2162756f68cSNikolay Aleksandrov if (p->backup_redirected_cnt) {
2172756f68cSNikolay Aleksandrov struct net_bridge_port *cur_p;
2182756f68cSNikolay Aleksandrov
2192756f68cSNikolay Aleksandrov list_for_each_entry(cur_p, &p->br->port_list, list) {
2202756f68cSNikolay Aleksandrov struct net_bridge_port *backup_p;
2212756f68cSNikolay Aleksandrov
2222756f68cSNikolay Aleksandrov backup_p = rtnl_dereference(cur_p->backup_port);
2232756f68cSNikolay Aleksandrov if (backup_p == p)
2242756f68cSNikolay Aleksandrov nbp_backup_change(cur_p, NULL);
2252756f68cSNikolay Aleksandrov }
2262756f68cSNikolay Aleksandrov }
2272756f68cSNikolay Aleksandrov
2282756f68cSNikolay Aleksandrov WARN_ON(rcu_access_pointer(p->backup_port) || p->backup_redirected_cnt);
2292756f68cSNikolay Aleksandrov }
230e028e4b8SVlad Yasevich
nbp_update_port_count(struct net_bridge * br)231e028e4b8SVlad Yasevich static void nbp_update_port_count(struct net_bridge *br)
232e028e4b8SVlad Yasevich {
233e028e4b8SVlad Yasevich struct net_bridge_port *p;
234e028e4b8SVlad Yasevich u32 cnt = 0;
235e028e4b8SVlad Yasevich
236e028e4b8SVlad Yasevich list_for_each_entry(p, &br->port_list, list) {
237e028e4b8SVlad Yasevich if (br_auto_port(p))
238e028e4b8SVlad Yasevich cnt++;
2392796d0c6SVlad Yasevich }
240e028e4b8SVlad Yasevich if (br->auto_cnt != cnt) {
2412796d0c6SVlad Yasevich br->auto_cnt = cnt;
2422796d0c6SVlad Yasevich br_manage_promisc(br);
2432796d0c6SVlad Yasevich }
2442796d0c6SVlad Yasevich }
2452796d0c6SVlad Yasevich
nbp_delete_promisc(struct net_bridge_port * p)2462796d0c6SVlad Yasevich static void nbp_delete_promisc(struct net_bridge_port *p)
247025559eeSstephen hemminger {
2482796d0c6SVlad Yasevich /* If port is currently promiscuous, unset promiscuity.
2492796d0c6SVlad Yasevich * Otherwise, it is a static port so remove all addresses
2502796d0c6SVlad Yasevich * from it.
2512796d0c6SVlad Yasevich */
2522796d0c6SVlad Yasevich dev_set_allmulti(p->dev, -1);
2532796d0c6SVlad Yasevich if (br_promisc_port(p))
2542796d0c6SVlad Yasevich dev_set_promiscuity(p->dev, -1);
2552796d0c6SVlad Yasevich else
256e028e4b8SVlad Yasevich br_fdb_unsync_static(p->br, p);
257e028e4b8SVlad Yasevich }
258bab1deeaSStephen Hemminger
release_nbp(struct kobject * kobj)259bab1deeaSStephen Hemminger static void release_nbp(struct kobject *kobj)
260bab1deeaSStephen Hemminger {
261bab1deeaSStephen Hemminger struct net_bridge_port *p
262bab1deeaSStephen Hemminger = container_of(kobj, struct net_bridge_port, kobj);
263bab1deeaSStephen Hemminger kfree(p);
264bab1deeaSStephen Hemminger }
26502a476d9SGreg Kroah-Hartman
brport_get_ownership(const struct kobject * kobj,kuid_t * uid,kgid_t * gid)266705e0deaSTyler Hicks static void brport_get_ownership(const struct kobject *kobj, kuid_t *uid, kgid_t *gid)
267705e0deaSTyler Hicks {
268705e0deaSTyler Hicks struct net_bridge_port *p = kobj_to_brport(kobj);
269705e0deaSTyler Hicks
270705e0deaSTyler Hicks net_ns_get_ownership(dev_net(p->dev), uid, gid);
271705e0deaSTyler Hicks }
272e8c6cbd7SThomas Weißschuh
273bab1deeaSStephen Hemminger static const struct kobj_type brport_ktype = {
274bab1deeaSStephen Hemminger #ifdef CONFIG_SYSFS
275bab1deeaSStephen Hemminger .sysfs_ops = &brport_sysfs_ops,
276bab1deeaSStephen Hemminger #endif
277705e0deaSTyler Hicks .release = release_nbp,
278bab1deeaSStephen Hemminger .get_ownership = brport_get_ownership,
279bab1deeaSStephen Hemminger };
2801da177e4SLinus Torvalds
destroy_nbp(struct net_bridge_port * p)2811da177e4SLinus Torvalds static void destroy_nbp(struct net_bridge_port *p)
2821da177e4SLinus Torvalds {
2831da177e4SLinus Torvalds struct net_device *dev = p->dev;
2841da177e4SLinus Torvalds
2851da177e4SLinus Torvalds p->br = NULL;
286d62607c3SJakub Kicinski p->dev = NULL;
2871da177e4SLinus Torvalds netdev_put(dev, &p->dev_tracker);
288bab1deeaSStephen Hemminger
2891da177e4SLinus Torvalds kobject_put(&p->kobj);
2901da177e4SLinus Torvalds }
2911da177e4SLinus Torvalds
destroy_nbp_rcu(struct rcu_head * head)2921da177e4SLinus Torvalds static void destroy_nbp_rcu(struct rcu_head *head)
2931da177e4SLinus Torvalds {
2941da177e4SLinus Torvalds struct net_bridge_port *p =
2951da177e4SLinus Torvalds container_of(head, struct net_bridge_port, rcu);
2961da177e4SLinus Torvalds destroy_nbp(p);
2971da177e4SLinus Torvalds }
29845493d47SPaolo Abeni
get_max_headroom(struct net_bridge * br)29945493d47SPaolo Abeni static unsigned get_max_headroom(struct net_bridge *br)
30045493d47SPaolo Abeni {
30145493d47SPaolo Abeni unsigned max_headroom = 0;
30245493d47SPaolo Abeni struct net_bridge_port *p;
30345493d47SPaolo Abeni
30445493d47SPaolo Abeni list_for_each_entry(p, &br->port_list, list) {
30545493d47SPaolo Abeni unsigned dev_headroom = netdev_get_fwd_headroom(p->dev);
30645493d47SPaolo Abeni
30745493d47SPaolo Abeni if (dev_headroom > max_headroom)
30845493d47SPaolo Abeni max_headroom = dev_headroom;
30945493d47SPaolo Abeni }
31045493d47SPaolo Abeni
31145493d47SPaolo Abeni return max_headroom;
31245493d47SPaolo Abeni }
31345493d47SPaolo Abeni
update_headroom(struct net_bridge * br,int new_hr)31445493d47SPaolo Abeni static void update_headroom(struct net_bridge *br, int new_hr)
31545493d47SPaolo Abeni {
31645493d47SPaolo Abeni struct net_bridge_port *p;
31745493d47SPaolo Abeni
31845493d47SPaolo Abeni list_for_each_entry(p, &br->port_list, list)
31945493d47SPaolo Abeni netdev_set_rx_headroom(p->dev, new_hr);
32045493d47SPaolo Abeni
32145493d47SPaolo Abeni br->dev->needed_headroom = new_hr;
32245493d47SPaolo Abeni }
3233f4cfc2dSStephen Hemminger
3243f4cfc2dSStephen Hemminger /* Delete port(interface) from bridge is done in two steps.
3253f4cfc2dSStephen Hemminger * via RCU. First step, marks device as down. That deletes
3263f4cfc2dSStephen Hemminger * all the timers and stops new packets from flowing through.
3273f4cfc2dSStephen Hemminger *
3283f4cfc2dSStephen Hemminger * Final cleanup doesn't occur until after all CPU's finished
3293f4cfc2dSStephen Hemminger * processing packets.
3303f4cfc2dSStephen Hemminger *
3313f4cfc2dSStephen Hemminger * Protected from multiple admin operations by RTNL mutex
3321da177e4SLinus Torvalds */
del_nbp(struct net_bridge_port * p)3331da177e4SLinus Torvalds static void del_nbp(struct net_bridge_port *p)
3341da177e4SLinus Torvalds {
3351da177e4SLinus Torvalds struct net_bridge *br = p->br;
3361da177e4SLinus Torvalds struct net_device *dev = p->dev;
337b3bcb72eSRandy Dunlap
338bab1deeaSStephen Hemminger sysfs_remove_link(br->ifobj, p->dev->name);
3392796d0c6SVlad Yasevich
3401da177e4SLinus Torvalds nbp_delete_promisc(p);
3411da177e4SLinus Torvalds
3421da177e4SLinus Torvalds spin_lock_bh(&br->lock);
3431da177e4SLinus Torvalds br_stp_disable_port(p);
3441da177e4SLinus Torvalds spin_unlock_bh(&br->lock);
34565369933SHoratiu Vultur
34686a14b79SHenrik Bjoernlund br_mrp_port_del(br, p);
34765369933SHoratiu Vultur br_cfm_port_del(br, p);
34892899063SNikolay Aleksandrov
349b86c4503SStephen Hemminger br_ifinfo_notify(RTM_DELLINK, NULL, p);
3501da177e4SLinus Torvalds
35145493d47SPaolo Abeni list_del_rcu(&p->list);
35245493d47SPaolo Abeni if (netdev_get_fwd_headroom(dev) == br->dev->needed_headroom)
35345493d47SPaolo Abeni update_headroom(br, get_max_headroom(br));
3541da177e4SLinus Torvalds netdev_reset_rx_headroom(dev);
355f409d0edSNikolay Aleksandrov
3561ea2d020SNikolay Aleksandrov nbp_vlan_flush(p);
35756607386SJiri Pirko br_fdb_delete_by_port(br, p, 0, 1);
3582756f68cSNikolay Aleksandrov switchdev_deferred_process();
35956607386SJiri Pirko nbp_backup_clear(p);
360e028e4b8SVlad Yasevich
361e028e4b8SVlad Yasevich nbp_update_port_count(br);
3620f49579aSJiri Pirko
3630f49579aSJiri Pirko netdev_upper_dev_unlink(dev, br->dev);
364f350a0a8SJiri Pirko
365f350a0a8SJiri Pirko dev->priv_flags &= ~IFF_BRIDGE_PORT;
366ab95bfe0SJiri Pirko
367b3f1be4bSStephen Hemminger netdev_rx_handler_unregister(dev);
3683fe2d7c7SHerbert Xu
3693fe2d7c7SHerbert Xu br_multicast_del_port(p);
370125a12ccSStephen Hemminger
371bab1deeaSStephen Hemminger kobject_uevent(&p->kobj, KOBJ_REMOVE);
372bab1deeaSStephen Hemminger kobject_del(&p->kobj);
37391d2c34aSHerbert Xu
37491d2c34aSHerbert Xu br_netpoll_disable(p);
3751da177e4SLinus Torvalds
3761da177e4SLinus Torvalds call_rcu(&p->rcu, destroy_nbp_rcu);
3771da177e4SLinus Torvalds }
3781ce5cce8Sstephen hemminger
3791ce5cce8Sstephen hemminger /* Delete bridge device */
br_dev_delete(struct net_device * dev,struct list_head * head)3801da177e4SLinus Torvalds void br_dev_delete(struct net_device *dev, struct list_head *head)
3811ce5cce8Sstephen hemminger {
3821da177e4SLinus Torvalds struct net_bridge *br = netdev_priv(dev);
3831da177e4SLinus Torvalds struct net_bridge_port *p, *n;
3841da177e4SLinus Torvalds
3851da177e4SLinus Torvalds list_for_each_entry_safe(p, n, &br->port_list, list) {
3861da177e4SLinus Torvalds del_nbp(p);
3871da177e4SLinus Torvalds }
388821f1b21SRoopa Prabhu
389821f1b21SRoopa Prabhu br_recalculate_neigh_suppress_enabled(br);
3901ea2d020SNikolay Aleksandrov
391f8730420SDing Tianhong br_fdb_delete_by_port(br, NULL, 0, 1);
392f7cdee8aSNikolay Aleksandrov
3931da177e4SLinus Torvalds cancel_delayed_work_sync(&br->gc_work);
3941da177e4SLinus Torvalds
3958c56ba05SEric Dumazet br_sysfs_delbr(br->dev);
3961da177e4SLinus Torvalds unregister_netdevice_queue(br->dev, head);
3971da177e4SLinus Torvalds }
3981da177e4SLinus Torvalds
3991da177e4SLinus Torvalds /* find an available port number */
find_portno(struct net_bridge * br)4001da177e4SLinus Torvalds static int find_portno(struct net_bridge *br)
4011da177e4SLinus Torvalds {
4021da177e4SLinus Torvalds int index;
4031da177e4SLinus Torvalds struct net_bridge_port *p;
4041da177e4SLinus Torvalds unsigned long *inuse;
405459479daSAndy Shevchenko
4061da177e4SLinus Torvalds inuse = bitmap_zalloc(BR_MAX_PORTS, GFP_KERNEL);
4071da177e4SLinus Torvalds if (!inuse)
4081da177e4SLinus Torvalds return -ENOMEM;
409cc0be1adSChristophe JAILLET
410cc0be1adSChristophe JAILLET __set_bit(0, inuse); /* zero is reserved */
411cc0be1adSChristophe JAILLET list_for_each_entry(p, &br->port_list, list)
412cc0be1adSChristophe JAILLET __set_bit(p->port_no, inuse);
4131da177e4SLinus Torvalds
414459479daSAndy Shevchenko index = find_first_zero_bit(inuse, BR_MAX_PORTS);
4151da177e4SLinus Torvalds bitmap_free(inuse);
4161da177e4SLinus Torvalds
4171da177e4SLinus Torvalds return (index >= BR_MAX_PORTS) ? -EXFULL : index;
4181da177e4SLinus Torvalds }
4194433f420SStephen Hemminger
4201da177e4SLinus Torvalds /* called with RTNL but without bridge lock */
new_nbp(struct net_bridge * br,struct net_device * dev)4214433f420SStephen Hemminger static struct net_bridge_port *new_nbp(struct net_bridge *br,
4221da177e4SLinus Torvalds struct net_device *dev)
4231da177e4SLinus Torvalds {
4241080ab95SNikolay Aleksandrov struct net_bridge_port *p;
4251da177e4SLinus Torvalds int index, err;
4261da177e4SLinus Torvalds
4271da177e4SLinus Torvalds index = find_portno(br);
4281da177e4SLinus Torvalds if (index < 0)
4291da177e4SLinus Torvalds return ERR_PTR(index);
430cee48541SStephen Hemminger
4311da177e4SLinus Torvalds p = kzalloc(sizeof(*p), GFP_KERNEL);
4321da177e4SLinus Torvalds if (p == NULL)
4331da177e4SLinus Torvalds return ERR_PTR(-ENOMEM);
4341da177e4SLinus Torvalds
435d62607c3SJakub Kicinski p->br = br;
4361da177e4SLinus Torvalds netdev_hold(dev, &p->dev_tracker, GFP_KERNEL);
4374433f420SStephen Hemminger p->dev = dev;
4381da177e4SLinus Torvalds p->path_cost = port_cost(dev);
4391da177e4SLinus Torvalds p->priority = 0x8000 >> BR_PORT_BITS;
44099f906e9SMike Manning p->port_no = index;
4411da177e4SLinus Torvalds p->flags = BR_LEARNING | BR_FLOOD | BR_MCAST_FLOOD | BR_BCAST_FLOOD;
442775dd692SFlorian Fainelli br_init_port(p);
443d32439c0SStephen Hemminger br_set_state(p, BR_STATE_DISABLED);
4441080ab95SNikolay Aleksandrov br_stp_port_timer_init(p);
4451080ab95SNikolay Aleksandrov err = br_multicast_add_port(p);
446d62607c3SJakub Kicinski if (err) {
4471080ab95SNikolay Aleksandrov netdev_put(dev, &p->dev_tracker);
4481080ab95SNikolay Aleksandrov kfree(p);
4491080ab95SNikolay Aleksandrov p = ERR_PTR(err);
4501da177e4SLinus Torvalds }
4511da177e4SLinus Torvalds
4521da177e4SLinus Torvalds return p;
4531da177e4SLinus Torvalds }
4544aa678baSAlexey Dobriyan
br_add_bridge(struct net * net,const char * name)4551da177e4SLinus Torvalds int br_add_bridge(struct net *net, const char *name)
4561da177e4SLinus Torvalds {
45711f3a6bdSEric Dumazet struct net_device *dev;
4581da177e4SLinus Torvalds int res;
459c835a677STom Gundersen
460bb900b27Sstephen hemminger dev = alloc_netdev(sizeof(struct net_bridge), name, NET_NAME_UNKNOWN,
461bb900b27Sstephen hemminger br_dev_setup);
4621da177e4SLinus Torvalds
4631da177e4SLinus Torvalds if (!dev)
4641da177e4SLinus Torvalds return -ENOMEM;
465bb900b27Sstephen hemminger
466149ddd83Sstephen hemminger dev_net_set(dev, net);
4671da177e4SLinus Torvalds dev->rtnl_link_ops = &br_link_ops;
468893b1958SNikolay Aleksandrov
46911f3a6bdSEric Dumazet res = register_netdevice(dev);
47011f3a6bdSEric Dumazet if (res)
47111f3a6bdSEric Dumazet free_netdev(dev);
4721da177e4SLinus Torvalds return res;
4731da177e4SLinus Torvalds }
4744aa678baSAlexey Dobriyan
br_del_bridge(struct net * net,const char * name)4751da177e4SLinus Torvalds int br_del_bridge(struct net *net, const char *name)
4761da177e4SLinus Torvalds {
4771da177e4SLinus Torvalds struct net_device *dev;
4781da177e4SLinus Torvalds int ret = 0;
4794aa678baSAlexey Dobriyan
4801da177e4SLinus Torvalds dev = __dev_get_by_name(net, name);
4811da177e4SLinus Torvalds if (dev == NULL)
4821da177e4SLinus Torvalds ret = -ENXIO; /* Could not find device */
483254ec036SKyungrok Chung
4841da177e4SLinus Torvalds else if (!netif_is_bridge_master(dev)) {
4851da177e4SLinus Torvalds /* Attempt to delete non bridge device! */
4861da177e4SLinus Torvalds ret = -EPERM;
4871da177e4SLinus Torvalds }
4881da177e4SLinus Torvalds
4891da177e4SLinus Torvalds else if (dev->flags & IFF_UP) {
4901da177e4SLinus Torvalds /* Not shutdown yet. */
4911da177e4SLinus Torvalds ret = -EBUSY;
4921da177e4SLinus Torvalds }
4931da177e4SLinus Torvalds
4941ce5cce8Sstephen hemminger else
4951da177e4SLinus Torvalds br_dev_delete(dev, NULL);
4961da177e4SLinus Torvalds
4971da177e4SLinus Torvalds return ret;
4981da177e4SLinus Torvalds }
499804b854dSNikolay Aleksandrov
500804b854dSNikolay Aleksandrov /* MTU of the bridge pseudo-device: ETH_DATA_LEN or the minimum of the ports */
br_mtu_min(const struct net_bridge * br)5011da177e4SLinus Torvalds static int br_mtu_min(const struct net_bridge *br)
5021da177e4SLinus Torvalds {
503f40aa233SNikolay Aleksandrov const struct net_bridge_port *p;
5041da177e4SLinus Torvalds int ret_mtu = 0;
505804b854dSNikolay Aleksandrov
506f40aa233SNikolay Aleksandrov list_for_each_entry(p, &br->port_list, list)
507f40aa233SNikolay Aleksandrov if (!ret_mtu || ret_mtu > p->dev->mtu)
5081da177e4SLinus Torvalds ret_mtu = p->dev->mtu;
509f40aa233SNikolay Aleksandrov
510419d14afSChas Williams return ret_mtu ? ret_mtu : ETH_DATA_LEN;
511419d14afSChas Williams }
512804b854dSNikolay Aleksandrov
br_mtu_auto_adjust(struct net_bridge * br)513804b854dSNikolay Aleksandrov void br_mtu_auto_adjust(struct net_bridge *br)
514804b854dSNikolay Aleksandrov {
515804b854dSNikolay Aleksandrov ASSERT_RTNL();
516804b854dSNikolay Aleksandrov
5173341d917SNikolay Aleksandrov /* if the bridge MTU was manually configured don't mess with it */
518804b854dSNikolay Aleksandrov if (br_opt_get(br, BROPT_MTU_SET_BY_USER))
519804b854dSNikolay Aleksandrov return;
520804b854dSNikolay Aleksandrov
521804b854dSNikolay Aleksandrov /* change to the minimum MTU and clear the flag which was set by
522804b854dSNikolay Aleksandrov * the bridge ndo_change_mtu callback
523804b854dSNikolay Aleksandrov */
5243341d917SNikolay Aleksandrov dev_set_mtu(br->dev, br_mtu_min(br));
525804b854dSNikolay Aleksandrov br_opt_toggle(br, BROPT_MTU_SET_BY_USER, false);
526804b854dSNikolay Aleksandrov }
527ae74f100SEric Dumazet
br_set_gso_limits(struct net_bridge * br)528ae74f100SEric Dumazet static void br_set_gso_limits(struct net_bridge *br)
529ee8b7a11SJakub Kicinski {
530ae74f100SEric Dumazet unsigned int tso_max_size = TSO_MAX_SIZE;
531ee8b7a11SJakub Kicinski const struct net_bridge_port *p;
532ae74f100SEric Dumazet u16 tso_max_segs = TSO_MAX_SEGS;
533ae74f100SEric Dumazet
534ee8b7a11SJakub Kicinski list_for_each_entry(p, &br->port_list, list) {
535ee8b7a11SJakub Kicinski tso_max_size = min(tso_max_size, p->dev->tso_max_size);
536ae74f100SEric Dumazet tso_max_segs = min(tso_max_segs, p->dev->tso_max_segs);
537ee8b7a11SJakub Kicinski }
538ee8b7a11SJakub Kicinski netif_set_tso_max_size(br->dev, tso_max_size);
539ae74f100SEric Dumazet netif_set_tso_max_segs(br->dev, tso_max_segs);
540ae74f100SEric Dumazet }
54181d35307SStephen Hemminger
54281d35307SStephen Hemminger /*
54381d35307SStephen Hemminger * Recomputes features using slave's features
544c8f44affSMichał Mirosław */
br_features_recompute(struct net_bridge * br,netdev_features_t features)545c8f44affSMichał Mirosław netdev_features_t br_features_recompute(struct net_bridge *br,
54681d35307SStephen Hemminger netdev_features_t features)
54781d35307SStephen Hemminger {
548c8f44affSMichał Mirosław struct net_bridge_port *p;
54981d35307SStephen Hemminger netdev_features_t mask;
550b63365a2SHerbert Xu
551c4d27ef9SMichał Mirosław if (list_empty(&br->port_list))
552b63365a2SHerbert Xu return features;
553c4d27ef9SMichał Mirosław
554b63365a2SHerbert Xu mask = features;
55581d35307SStephen Hemminger features &= ~NETIF_F_ONE_FOR_ALL;
55681d35307SStephen Hemminger
557b63365a2SHerbert Xu list_for_each_entry(p, &br->port_list, list) {
558b63365a2SHerbert Xu features = netdev_increment_features(features,
55981d35307SStephen Hemminger p->dev->features, mask);
560f902e881SToshiaki Makita }
56181d35307SStephen Hemminger features = netdev_add_tso_features(features, mask);
562c4d27ef9SMichał Mirosław
56381d35307SStephen Hemminger return features;
56481d35307SStephen Hemminger }
5651da177e4SLinus Torvalds
566ca752be0SDavid Ahern /* called with RTNL */
br_add_if(struct net_bridge * br,struct net_device * dev,struct netlink_ext_ack * extack)567ca752be0SDavid Ahern int br_add_if(struct net_bridge *br, struct net_device *dev,
5681da177e4SLinus Torvalds struct netlink_ext_ack *extack)
5691da177e4SLinus Torvalds {
5701da177e4SLinus Torvalds struct net_bridge_port *p;
57145493d47SPaolo Abeni int err = 0;
572a019abd8SWolfgang Bumiller unsigned br_hr, dev_hr;
5731da177e4SLinus Torvalds bool changed_addr, fdb_synced = false;
5749eb8eff0SVladimir Oltean
5751056bd51SStephen Hemminger /* Don't allow bridging non-ethernet like devices. */
57677f98598Sstephen hemminger if ((dev->flags & IFF_LOOPBACK) ||
5779eb8eff0SVladimir Oltean dev->type != ARPHRD_ETHER || dev->addr_len != ETH_ALEN ||
5781da177e4SLinus Torvalds !is_valid_ether_addr(dev->dev_addr))
5791da177e4SLinus Torvalds return -EINVAL;
5801056bd51SStephen Hemminger
581ca752be0SDavid Ahern /* No bridging of bridges */
582ca752be0SDavid Ahern if (dev->netdev_ops->ndo_start_xmit == br_dev_xmit) {
583ca752be0SDavid Ahern NL_SET_ERR_MSG(extack,
5841da177e4SLinus Torvalds "Can not enslave a bridge to a bridge");
585ca752be0SDavid Ahern return -ELOOP;
5861da177e4SLinus Torvalds }
587e8238fc2SHangbin Liu
588e8238fc2SHangbin Liu /* Device has master upper dev */
5891da177e4SLinus Torvalds if (netdev_master_upper_dev_get(dev))
5901da177e4SLinus Torvalds return -EBUSY;
591ad4bb6f8SJohannes Berg
592ca752be0SDavid Ahern /* No bridging devices that dislike that (e.g. wireless) */
593ca752be0SDavid Ahern if (dev->priv_flags & IFF_DONT_BRIDGE) {
594ca752be0SDavid Ahern NL_SET_ERR_MSG(extack,
595ad4bb6f8SJohannes Berg "Device does not allow enslaving to a bridge");
596ca752be0SDavid Ahern return -EOPNOTSUPP;
597ad4bb6f8SJohannes Berg }
598bab1deeaSStephen Hemminger
599bab1deeaSStephen Hemminger p = new_nbp(br, dev);
6001da177e4SLinus Torvalds if (IS_ERR(p))
6011da177e4SLinus Torvalds return PTR_ERR(p);
602bb8ed630SAmerigo Wang
603bb8ed630SAmerigo Wang call_netdevice_notifiers(NETDEV_JOIN, dev);
6042796d0c6SVlad Yasevich
605bdfad5aeSTobin C. Harding err = dev_set_allmulti(dev, 1);
606519133deSYang Yingliang if (err) {
607d62607c3SJakub Kicinski br_multicast_del_port(p);
608bdfad5aeSTobin C. Harding netdev_put(dev, &p->dev_tracker);
609bdfad5aeSTobin C. Harding kfree(p); /* kobject not yet init'd, manually free */
610bdfad5aeSTobin C. Harding goto err1;
611bc3f9076SWang Chen }
612e32cc736SGreg Kroah-Hartman
613e32cc736SGreg Kroah-Hartman err = kobject_init_and_add(&p->kobj, &brport_ktype, &(dev->dev.kobj),
614bab1deeaSStephen Hemminger SYSFS_BRIDGE_PORT_ATTR);
615bdfad5aeSTobin C. Harding if (err)
616bab1deeaSStephen Hemminger goto err2;
617bab1deeaSStephen Hemminger
618bab1deeaSStephen Hemminger err = br_sysfs_addif(p);
619bab1deeaSStephen Hemminger if (err)
620bab1deeaSStephen Hemminger goto err2;
621a8779ec1SEric W. Biederman
62293d8bf9fSstephen hemminger err = br_netpoll_enable(p);
62391d2c34aSHerbert Xu if (err)
62491d2c34aSHerbert Xu goto err3;
6259eb8eff0SVladimir Oltean
626ab95bfe0SJiri Pirko err = netdev_rx_handler_register(dev, br_get_rx_handler(dev), p);
6279b1536c4SGao feng if (err)
628f350a0a8SJiri Pirko goto err4;
6290f49579aSJiri Pirko
6300f49579aSJiri Pirko dev->priv_flags |= IFF_BRIDGE_PORT;
631ca752be0SDavid Ahern
632afc6151aSJiri Pirko err = netdev_master_upper_dev_link(dev, br->dev, NULL, NULL, extack);
6339b1536c4SGao feng if (err)
634afc6151aSJiri Pirko goto err5;
6350187bdfbSBen Hutchings
6361da177e4SLinus Torvalds dev_disable_lro(dev);
6371da177e4SLinus Torvalds
6381da177e4SLinus Torvalds list_add_rcu(&p->list, &br->port_list);
639e028e4b8SVlad Yasevich
640a019abd8SWolfgang Bumiller nbp_update_port_count(br);
641a019abd8SWolfgang Bumiller if (!br_promisc_port(p) && (p->dev->priv_flags & IFF_UNICAST_FLT)) {
642a019abd8SWolfgang Bumiller /* When updating the port count we also update all ports'
643a019abd8SWolfgang Bumiller * promiscuous mode.
644a019abd8SWolfgang Bumiller * A port leaving promiscuous mode normally gets the bridge's
645a019abd8SWolfgang Bumiller * fdb synced to the unicast filter (if supported), however,
646a019abd8SWolfgang Bumiller * `br_port_clear_promisc` does not distinguish between
647a019abd8SWolfgang Bumiller * non-promiscuous ports and *new* ports, so we need to
648a019abd8SWolfgang Bumiller * sync explicitly here.
649a019abd8SWolfgang Bumiller */
650a019abd8SWolfgang Bumiller fdb_synced = br_fdb_sync_static(br, p) == 0;
651a019abd8SWolfgang Bumiller if (!fdb_synced)
652a019abd8SWolfgang Bumiller netdev_err(dev, "failed to sync bridge static fdb addresses to this port\n");
653e028e4b8SVlad Yasevich }
654c4d27ef9SMichał Mirosław
655c4d27ef9SMichał Mirosław netdev_update_features(br->dev);
65645493d47SPaolo Abeni
65745493d47SPaolo Abeni br_hr = br->dev->needed_headroom;
65845493d47SPaolo Abeni dev_hr = netdev_get_fwd_headroom(dev);
65945493d47SPaolo Abeni if (br_hr < dev_hr)
66045493d47SPaolo Abeni update_headroom(br, dev_hr);
66145493d47SPaolo Abeni else
662fd094808SFlorian Fainelli netdev_set_rx_headroom(dev, br_hr);
663f6814fdcSVladimir Oltean
664a4b816d8SToshiaki Makita if (br_fdb_add_local(br, p, dev->dev_addr, 0))
665a4b816d8SToshiaki Makita netdev_err(dev, "failed insert local address bridge forwarding table\n");
666ca935da7SPetr Machata
667ca935da7SPetr Machata if (br->dev->addr_assign_type != NET_ADDR_SET) {
668ca935da7SPetr Machata /* Ask for permission to use this MAC address now, even if we
669ca935da7SPetr Machata * don't end up choosing it below.
670ca935da7SPetr Machata */
671ca935da7SPetr Machata err = dev_pre_changeaddr_notify(br->dev, dev->dev_addr, extack);
6722f5dc00fSVladimir Oltean if (err)
673ca935da7SPetr Machata goto err6;
674ca935da7SPetr Machata }
675169327d5SPetr Machata
67608474cc1SElad Raz err = nbp_vlan_init(p, extack);
6775be5a2dfSVlad Yasevich if (err) {
6782f5dc00fSVladimir Oltean netdev_err(dev, "failed to initialize vlan filtering on this port\n");
67908474cc1SElad Raz goto err6;
6805be5a2dfSVlad Yasevich }
6811da177e4SLinus Torvalds
682edf947f1Sstephen hemminger spin_lock_bh(&br->lock);
683de79059eSAji Srinivas changed_addr = br_stp_recalculate_bridge_id(br);
684576eb625Sstephen hemminger
685de79059eSAji Srinivas if (netif_running(dev) && netif_oper_up(dev) &&
686de79059eSAji Srinivas (br->dev->flags & IFF_UP))
6871da177e4SLinus Torvalds br_stp_enable_port(p);
6881da177e4SLinus Torvalds spin_unlock_bh(&br->lock);
68992899063SNikolay Aleksandrov
690b86c4503SStephen Hemminger br_ifinfo_notify(RTM_NEWLINK, NULL, p);
691edf947f1Sstephen hemminger
69256139fc5Sstephen hemminger if (changed_addr)
693edf947f1Sstephen hemminger call_netdevice_notifiers(NETDEV_CHANGEADDR, br->dev);
694804b854dSNikolay Aleksandrov
695ae74f100SEric Dumazet br_mtu_auto_adjust(br);
696269def7cSStephen Hemminger br_set_gso_limits(br);
697bab1deeaSStephen Hemminger
6981da177e4SLinus Torvalds kobject_uevent(&p->kobj, KOBJ_ADD);
699bab1deeaSStephen Hemminger
700afc6151aSJiri Pirko return 0;
7012f5dc00fSVladimir Oltean
702a019abd8SWolfgang Bumiller err6:
703a019abd8SWolfgang Bumiller if (fdb_synced)
70408474cc1SElad Raz br_fdb_unsync_static(br, p);
70508474cc1SElad Raz list_del_rcu(&p->list);
70608474cc1SElad Raz br_fdb_delete_by_port(br, p, 0, 1);
70708474cc1SElad Raz nbp_update_port_count(br);
7089b1536c4SGao feng netdev_upper_dev_unlink(dev, br->dev);
7090f49579aSJiri Pirko err5:
7100f49579aSJiri Pirko dev->priv_flags &= ~IFF_BRIDGE_PORT;
7119b1536c4SGao feng netdev_rx_handler_unregister(dev);
7129b1536c4SGao feng err4:
71391d2c34aSHerbert Xu br_netpoll_disable(p);
71491d2c34aSHerbert Xu err3:
715bab1deeaSStephen Hemminger sysfs_remove_link(br->ifobj, p->dev->name);
716519133deSYang Yingliang err2:
717d62607c3SJakub Kicinski br_multicast_del_port(p);
718c587aea9SXiaotian Feng netdev_put(dev, &p->dev_tracker);
719019ee792Swangweidong kobject_put(&p->kobj);
720bdfad5aeSTobin C. Harding dev_set_allmulti(dev, -1);
7211da177e4SLinus Torvalds err1:
7221da177e4SLinus Torvalds return err;
7231da177e4SLinus Torvalds }
7241da177e4SLinus Torvalds
7251da177e4SLinus Torvalds /* called with RTNL */
br_del_if(struct net_bridge * br,struct net_device * dev)7261da177e4SLinus Torvalds int br_del_if(struct net_bridge *br, struct net_device *dev)
727f350a0a8SJiri Pirko {
7289be6dd65SAndrei Warkentin struct net_bridge_port *p;
7291da177e4SLinus Torvalds bool changed_addr;
730ec1e5610SEric Dumazet
731b5ed54e9Sstephen hemminger p = br_port_get_rtnl(dev);
7321da177e4SLinus Torvalds if (!p || p->br != br)
7331da177e4SLinus Torvalds return -EINVAL;
734d30362c0SAmerigo Wang
735d30362c0SAmerigo Wang /* Since more than one interface can be attached to a bridge,
736d30362c0SAmerigo Wang * there still maybe an alternate path for netconsole to use;
737d30362c0SAmerigo Wang * therefore there is no reason for a NETDEV_RELEASE event.
7381da177e4SLinus Torvalds */
7391da177e4SLinus Torvalds del_nbp(p);
740804b854dSNikolay Aleksandrov
741ae74f100SEric Dumazet br_mtu_auto_adjust(br);
7424c906c27SVenkat Venkatsubra br_set_gso_limits(br);
7431da177e4SLinus Torvalds
7449be6dd65SAndrei Warkentin spin_lock_bh(&br->lock);
7451da177e4SLinus Torvalds changed_addr = br_stp_recalculate_bridge_id(br);
7461da177e4SLinus Torvalds spin_unlock_bh(&br->lock);
7479be6dd65SAndrei Warkentin
7489be6dd65SAndrei Warkentin if (changed_addr)
7499be6dd65SAndrei Warkentin call_netdevice_notifiers(NETDEV_CHANGEADDR, br->dev);
750c4d27ef9SMichał Mirosław
751c4d27ef9SMichał Mirosław netdev_update_features(br->dev);
7521da177e4SLinus Torvalds
7531da177e4SLinus Torvalds return 0;
754e028e4b8SVlad Yasevich }
755e028e4b8SVlad Yasevich
br_port_flags_change(struct net_bridge_port * p,unsigned long mask)756e028e4b8SVlad Yasevich void br_port_flags_change(struct net_bridge_port *p, unsigned long mask)
757e028e4b8SVlad Yasevich {
758e028e4b8SVlad Yasevich struct net_bridge *br = p->br;
759e028e4b8SVlad Yasevich
760e028e4b8SVlad Yasevich if (mask & BR_AUTO_MASK)
761821f1b21SRoopa Prabhu nbp_update_port_count(br);
762*6be42ed0SIdo Schimmel
763821f1b21SRoopa Prabhu if (mask & (BR_NEIGH_SUPPRESS | BR_NEIGH_VLAN_SUPPRESS))
764e028e4b8SVlad Yasevich br_recalculate_neigh_suppress_enabled(br);
765085ddc87SIdo Schimmel }
766085ddc87SIdo Schimmel
br_port_flag_is_set(const struct net_device * dev,unsigned long flag)767085ddc87SIdo Schimmel bool br_port_flag_is_set(const struct net_device *dev, unsigned long flag)
768085ddc87SIdo Schimmel {
769085ddc87SIdo Schimmel struct net_bridge_port *p;
770085ddc87SIdo Schimmel
771085ddc87SIdo Schimmel p = br_port_get_rtnl_rcu(dev);
772085ddc87SIdo Schimmel if (!p)
773085ddc87SIdo Schimmel return false;
774085ddc87SIdo Schimmel
775085ddc87SIdo Schimmel return p->flags & flag;
776085ddc87SIdo Schimmel }
777 EXPORT_SYMBOL_GPL(br_port_flag_is_set);
778