xref: /openbmc/linux/net/bridge/br_if.c (revision 1ac731c529cd4d6adbce134754b51ff7d822b145)
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