xref: /openbmc/linux/net/bridge/br_device.c (revision b181f7029bd71238ac2754ce7052dffd69432085)
12874c5fdSThomas Gleixner // SPDX-License-Identifier: GPL-2.0-or-later
21da177e4SLinus Torvalds /*
31da177e4SLinus Torvalds  *	Device handling code
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>
12c06ee961SWANG Cong #include <linux/netpoll.h>
134505a3efSStephen Hemminger #include <linux/etherdevice.h>
14edb5e46fSStephen Hemminger #include <linux/ethtool.h>
15c06ee961SWANG Cong #include <linux/list.h>
16ea2d9b41SBart De Schuymer #include <linux/netfilter_bridge.h>
174505a3efSStephen Hemminger 
187c0f6ba6SLinus Torvalds #include <linux/uaccess.h>
191da177e4SLinus Torvalds #include "br_private.h"
201da177e4SLinus Torvalds 
21161f65baSVlad Yasevich #define COMMON_FEATURES (NETIF_F_SG | NETIF_F_FRAGLIST | NETIF_F_HIGHDMA | \
22161f65baSVlad Yasevich 			 NETIF_F_GSO_MASK | NETIF_F_HW_CSUM)
23161f65baSVlad Yasevich 
241a4ba64dSPablo Neira Ayuso const struct nf_br_ops __rcu *nf_br_ops __read_mostly;
251a4ba64dSPablo Neira Ayuso EXPORT_SYMBOL_GPL(nf_br_ops);
261a4ba64dSPablo Neira Ayuso 
27eeaf61d8Sstephen hemminger /* net device transmit always called with BH disabled */
br_dev_xmit(struct sk_buff * skb,struct net_device * dev)286fef4c0cSStephen Hemminger netdev_tx_t br_dev_xmit(struct sk_buff *skb, struct net_device *dev)
291da177e4SLinus Torvalds {
30*1abb3711SNikolay Aleksandrov 	enum skb_drop_reason reason = pskb_may_pull_reason(skb, ETH_HLEN);
31f4b7002aSNikolay Aleksandrov 	struct net_bridge_mcast_port *pmctx_null = NULL;
321da177e4SLinus Torvalds 	struct net_bridge *br = netdev_priv(dev);
33adc47037SNikolay Aleksandrov 	struct net_bridge_mcast *brmctx = &br->multicast_ctx;
341da177e4SLinus Torvalds 	struct net_bridge_fdb_entry *dst;
35c4fcb78cSHerbert Xu 	struct net_bridge_mdb_entry *mdst;
361a4ba64dSPablo Neira Ayuso 	const struct nf_br_ops *nf_ops;
37a580c76dSNikolay Aleksandrov 	u8 state = BR_STATE_FORWARDING;
38f4b7002aSNikolay Aleksandrov 	struct net_bridge_vlan *vlan;
3931a4562dSNikolay Aleksandrov 	const unsigned char *dest;
4078851988SVlad Yasevich 	u16 vid = 0;
4114bb4789Sstephen hemminger 
42*1abb3711SNikolay Aleksandrov 	if (unlikely(reason != SKB_NOT_DROPPED_YET)) {
43*1abb3711SNikolay Aleksandrov 		kfree_skb_reason(skb, reason);
44*1abb3711SNikolay Aleksandrov 		return NETDEV_TX_OK;
45*1abb3711SNikolay Aleksandrov 	}
46*1abb3711SNikolay Aleksandrov 
47fd65e5a9SNikolay Aleksandrov 	memset(skb->cb, 0, sizeof(struct br_input_skb_cb));
487b4858dfSIdo Schimmel 	br_tc_skb_miss_set(skb, false);
49fd65e5a9SNikolay Aleksandrov 
50c03307eaSStephen Hemminger 	rcu_read_lock();
511a4ba64dSPablo Neira Ayuso 	nf_ops = rcu_dereference(nf_br_ops);
521a4ba64dSPablo Neira Ayuso 	if (nf_ops && nf_ops->br_dev_xmit_hook(skb)) {
53c03307eaSStephen Hemminger 		rcu_read_unlock();
54ea2d9b41SBart De Schuymer 		return NETDEV_TX_OK;
55ea2d9b41SBart De Schuymer 	}
56ea2d9b41SBart De Schuymer 
577609ecb2SHeiner Kallweit 	dev_sw_netstats_tx_add(dev, 1, skb->len);
581da177e4SLinus Torvalds 
59f1c2eddfSIdo Schimmel 	br_switchdev_frame_unmark(skb);
606088a539SHerbert Xu 	BR_INPUT_SKB_CB(skb)->brdev = dev;
613c171f49SPablo Neira Ayuso 	BR_INPUT_SKB_CB(skb)->frag_max_size = 0;
626088a539SHerbert Xu 
63459a98edSArnaldo Carvalho de Melo 	skb_reset_mac_header(skb);
641da177e4SLinus Torvalds 	skb_pull(skb, ETH_HLEN);
651da177e4SLinus Torvalds 
66f4b7002aSNikolay Aleksandrov 	if (!br_allowed_ingress(br, br_vlan_group_rcu(br), skb, &vid,
67f4b7002aSNikolay Aleksandrov 				&state, &vlan))
6812464bb8SToshiaki Makita 		goto out;
6912464bb8SToshiaki Makita 
70057658cbSRoopa Prabhu 	if (IS_ENABLED(CONFIG_INET) &&
71823d81b0SNikolay Aleksandrov 	    (eth_hdr(skb)->h_proto == htons(ETH_P_ARP) ||
72823d81b0SNikolay Aleksandrov 	     eth_hdr(skb)->h_proto == htons(ETH_P_RARP)) &&
73c69c2cd4SNikolay Aleksandrov 	    br_opt_get(br, BROPT_NEIGH_SUPPRESS_ENABLED)) {
74057658cbSRoopa Prabhu 		br_do_proxy_suppress_arp(skb, br, vid, NULL);
75ed842faeSRoopa Prabhu 	} else if (IS_ENABLED(CONFIG_IPV6) &&
76ed842faeSRoopa Prabhu 		   skb->protocol == htons(ETH_P_IPV6) &&
77c69c2cd4SNikolay Aleksandrov 		   br_opt_get(br, BROPT_NEIGH_SUPPRESS_ENABLED) &&
78ed842faeSRoopa Prabhu 		   pskb_may_pull(skb, sizeof(struct ipv6hdr) +
79ed842faeSRoopa Prabhu 				 sizeof(struct nd_msg)) &&
80ed842faeSRoopa Prabhu 		   ipv6_hdr(skb)->nexthdr == IPPROTO_ICMPV6) {
81ed842faeSRoopa Prabhu 			struct nd_msg *msg, _msg;
82ed842faeSRoopa Prabhu 
83ed842faeSRoopa Prabhu 			msg = br_is_nd_neigh_msg(skb, &_msg);
84ed842faeSRoopa Prabhu 			if (msg)
85ed842faeSRoopa Prabhu 				br_do_suppress_nd(skb, br, vid, NULL, msg);
86057658cbSRoopa Prabhu 	}
87057658cbSRoopa Prabhu 
8831a4562dSNikolay Aleksandrov 	dest = eth_hdr(skb)->h_dest;
8937b090e6SNikolay Aleksandrov 	if (is_broadcast_ether_addr(dest)) {
90e408336aSIdo Schimmel 		br_flood(br, skb, BR_PKT_BROADCAST, false, true, vid);
9137b090e6SNikolay Aleksandrov 	} else if (is_multicast_ether_addr(dest)) {
9291d2c34aSHerbert Xu 		if (unlikely(netpoll_tx_running(dev))) {
93e408336aSIdo Schimmel 			br_flood(br, skb, BR_PKT_MULTICAST, false, true, vid);
9491d2c34aSHerbert Xu 			goto out;
9591d2c34aSHerbert Xu 		}
96f4b7002aSNikolay Aleksandrov 		if (br_multicast_rcv(&brmctx, &pmctx_null, vlan, skb, vid)) {
976d1d1d39SHerbert Xu 			kfree_skb(skb);
98c4fcb78cSHerbert Xu 			goto out;
996d1d1d39SHerbert Xu 		}
100c4fcb78cSHerbert Xu 
101adc47037SNikolay Aleksandrov 		mdst = br_mdb_get(brmctx, skb, vid);
102b00589afSLinus Lüssing 		if ((mdst || BR_INPUT_SKB_CB_MROUTERS_ONLY(skb)) &&
103adc47037SNikolay Aleksandrov 		    br_multicast_querier_exists(brmctx, eth_hdr(skb), mdst))
104adc47037SNikolay Aleksandrov 			br_multicast_flood(mdst, skb, brmctx, false, true);
105c4fcb78cSHerbert Xu 		else
106e408336aSIdo Schimmel 			br_flood(br, skb, BR_PKT_MULTICAST, false, true, vid);
107bfd0aeacSNikolay Aleksandrov 	} else if ((dst = br_fdb_find_rcu(br, dest, vid)) != NULL) {
10837b090e6SNikolay Aleksandrov 		br_forward(dst->dst, skb, false, true);
10937b090e6SNikolay Aleksandrov 	} else {
110e408336aSIdo Schimmel 		br_flood(br, skb, BR_PKT_UNICAST, false, true, vid);
11137b090e6SNikolay Aleksandrov 	}
112c4fcb78cSHerbert Xu out:
113eeaf61d8Sstephen hemminger 	rcu_read_unlock();
1146ed10654SPatrick McHardy 	return NETDEV_TX_OK;
1151da177e4SLinus Torvalds }
1161da177e4SLinus Torvalds 
117845e0ebbSCong Wang static struct lock_class_key bridge_netdev_addr_lock_key;
118845e0ebbSCong Wang 
br_set_lockdep_class(struct net_device * dev)119845e0ebbSCong Wang static void br_set_lockdep_class(struct net_device *dev)
120845e0ebbSCong Wang {
121845e0ebbSCong Wang 	lockdep_set_class(&dev->addr_list_lock, &bridge_netdev_addr_lock_key);
122845e0ebbSCong Wang }
123845e0ebbSCong Wang 
br_dev_init(struct net_device * dev)124bb900b27Sstephen hemminger static int br_dev_init(struct net_device *dev)
125bb900b27Sstephen hemminger {
126bb900b27Sstephen hemminger 	struct net_bridge *br = netdev_priv(dev);
1275be5a2dfSVlad Yasevich 	int err;
128bb900b27Sstephen hemminger 
1297609ecb2SHeiner Kallweit 	dev->tstats = netdev_alloc_pcpu_stats(struct pcpu_sw_netstats);
1307609ecb2SHeiner Kallweit 	if (!dev->tstats)
131bb900b27Sstephen hemminger 		return -ENOMEM;
132bb900b27Sstephen hemminger 
133eb793583SNikolay Aleksandrov 	err = br_fdb_hash_init(br);
134eb793583SNikolay Aleksandrov 	if (err) {
1357609ecb2SHeiner Kallweit 		free_percpu(dev->tstats);
136eb793583SNikolay Aleksandrov 		return err;
137eb793583SNikolay Aleksandrov 	}
138eb793583SNikolay Aleksandrov 
13919e3a9c9SNikolay Aleksandrov 	err = br_mdb_hash_init(br);
14019e3a9c9SNikolay Aleksandrov 	if (err) {
1417609ecb2SHeiner Kallweit 		free_percpu(dev->tstats);
14219e3a9c9SNikolay Aleksandrov 		br_fdb_hash_fini(br);
14319e3a9c9SNikolay Aleksandrov 		return err;
14419e3a9c9SNikolay Aleksandrov 	}
14519e3a9c9SNikolay Aleksandrov 
1465be5a2dfSVlad Yasevich 	err = br_vlan_init(br);
1471080ab95SNikolay Aleksandrov 	if (err) {
1487609ecb2SHeiner Kallweit 		free_percpu(dev->tstats);
14919e3a9c9SNikolay Aleksandrov 		br_mdb_hash_fini(br);
150eb793583SNikolay Aleksandrov 		br_fdb_hash_fini(br);
1511080ab95SNikolay Aleksandrov 		return err;
1521080ab95SNikolay Aleksandrov 	}
1531080ab95SNikolay Aleksandrov 
1541080ab95SNikolay Aleksandrov 	err = br_multicast_init_stats(br);
1551080ab95SNikolay Aleksandrov 	if (err) {
1567609ecb2SHeiner Kallweit 		free_percpu(dev->tstats);
1571080ab95SNikolay Aleksandrov 		br_vlan_flush(br);
15819e3a9c9SNikolay Aleksandrov 		br_mdb_hash_fini(br);
159eb793583SNikolay Aleksandrov 		br_fdb_hash_fini(br);
1601080ab95SNikolay Aleksandrov 	}
1615be5a2dfSVlad Yasevich 
162845e0ebbSCong Wang 	br_set_lockdep_class(dev);
1635be5a2dfSVlad Yasevich 	return err;
164bb900b27Sstephen hemminger }
165bb900b27Sstephen hemminger 
br_dev_uninit(struct net_device * dev)166b6fe0440SIdo Schimmel static void br_dev_uninit(struct net_device *dev)
167b6fe0440SIdo Schimmel {
168b6fe0440SIdo Schimmel 	struct net_bridge *br = netdev_priv(dev);
169b6fe0440SIdo Schimmel 
170b1b9d366SXin Long 	br_multicast_dev_del(br);
171b6fe0440SIdo Schimmel 	br_multicast_uninit_stats(br);
172b6fe0440SIdo Schimmel 	br_vlan_flush(br);
17319e3a9c9SNikolay Aleksandrov 	br_mdb_hash_fini(br);
174eb793583SNikolay Aleksandrov 	br_fdb_hash_fini(br);
1757609ecb2SHeiner Kallweit 	free_percpu(dev->tstats);
176b6fe0440SIdo Schimmel }
177b6fe0440SIdo Schimmel 
br_dev_open(struct net_device * dev)1781da177e4SLinus Torvalds static int br_dev_open(struct net_device *dev)
1791da177e4SLinus Torvalds {
18081d35307SStephen Hemminger 	struct net_bridge *br = netdev_priv(dev);
1811da177e4SLinus Torvalds 
182c4d27ef9SMichał Mirosław 	netdev_update_features(dev);
18381d35307SStephen Hemminger 	netif_start_queue(dev);
18481d35307SStephen Hemminger 	br_stp_enable_bridge(br);
1853fe2d7c7SHerbert Xu 	br_multicast_open(br);
1861da177e4SLinus Torvalds 
187851d0a73SJoseph Huang 	if (br_opt_get(br, BROPT_MULTICAST_ENABLED))
188851d0a73SJoseph Huang 		br_multicast_join_snoopers(br);
189851d0a73SJoseph Huang 
1901da177e4SLinus Torvalds 	return 0;
1911da177e4SLinus Torvalds }
1921da177e4SLinus Torvalds 
br_dev_set_multicast_list(struct net_device * dev)1931da177e4SLinus Torvalds static void br_dev_set_multicast_list(struct net_device *dev)
1941da177e4SLinus Torvalds {
1951da177e4SLinus Torvalds }
1961da177e4SLinus Torvalds 
br_dev_change_rx_flags(struct net_device * dev,int change)1972796d0c6SVlad Yasevich static void br_dev_change_rx_flags(struct net_device *dev, int change)
1982796d0c6SVlad Yasevich {
1992796d0c6SVlad Yasevich 	if (change & IFF_PROMISC)
2002796d0c6SVlad Yasevich 		br_manage_promisc(netdev_priv(dev));
2012796d0c6SVlad Yasevich }
2022796d0c6SVlad Yasevich 
br_dev_stop(struct net_device * dev)2031da177e4SLinus Torvalds static int br_dev_stop(struct net_device *dev)
2041da177e4SLinus Torvalds {
2053fe2d7c7SHerbert Xu 	struct net_bridge *br = netdev_priv(dev);
2063fe2d7c7SHerbert Xu 
2073fe2d7c7SHerbert Xu 	br_stp_disable_bridge(br);
2083fe2d7c7SHerbert Xu 	br_multicast_stop(br);
2091da177e4SLinus Torvalds 
210851d0a73SJoseph Huang 	if (br_opt_get(br, BROPT_MULTICAST_ENABLED))
211851d0a73SJoseph Huang 		br_multicast_leave_snoopers(br);
212851d0a73SJoseph Huang 
2131da177e4SLinus Torvalds 	netif_stop_queue(dev);
2141da177e4SLinus Torvalds 
2151da177e4SLinus Torvalds 	return 0;
2161da177e4SLinus Torvalds }
2171da177e4SLinus Torvalds 
br_change_mtu(struct net_device * dev,int new_mtu)2181da177e4SLinus Torvalds static int br_change_mtu(struct net_device *dev, int new_mtu)
2191da177e4SLinus Torvalds {
2204adf0af6SSimon Wunderlich 	struct net_bridge *br = netdev_priv(dev);
221f40aa233SNikolay Aleksandrov 
2221da177e4SLinus Torvalds 	dev->mtu = new_mtu;
2234adf0af6SSimon Wunderlich 
224804b854dSNikolay Aleksandrov 	/* this flag will be cleared if the MTU was automatically adjusted */
2253341d917SNikolay Aleksandrov 	br_opt_toggle(br, BROPT_MTU_SET_BY_USER, true);
22634666d46SPablo Neira Ayuso #if IS_ENABLED(CONFIG_BRIDGE_NETFILTER)
2274adf0af6SSimon Wunderlich 	/* remember the MTU in the rtable for PMTU */
228defb3519SDavid S. Miller 	dst_metric_set(&br->fake_rtable.dst, RTAX_MTU, new_mtu);
2294adf0af6SSimon Wunderlich #endif
2304adf0af6SSimon Wunderlich 
2311da177e4SLinus Torvalds 	return 0;
2321da177e4SLinus Torvalds }
2331da177e4SLinus Torvalds 
234ffe1d49cSStephen Hemminger /* Allow setting mac address to any valid ethernet address. */
br_set_mac_address(struct net_device * dev,void * p)2354505a3efSStephen Hemminger static int br_set_mac_address(struct net_device *dev, void *p)
2364505a3efSStephen Hemminger {
2374505a3efSStephen Hemminger 	struct net_bridge *br = netdev_priv(dev);
2384505a3efSStephen Hemminger 	struct sockaddr *addr = p;
239ffe1d49cSStephen Hemminger 
240ffe1d49cSStephen Hemminger 	if (!is_valid_ether_addr(addr->sa_data))
2417ca1e11aSDanny Kukawka 		return -EADDRNOTAVAIL;
2424505a3efSStephen Hemminger 
243c4b4c421SNikolay Aleksandrov 	/* dev_set_mac_addr() can be called by a master device on bridge's
244c4b4c421SNikolay Aleksandrov 	 * NETDEV_UNREGISTER, but since it's being destroyed do nothing
245c4b4c421SNikolay Aleksandrov 	 */
246c4b4c421SNikolay Aleksandrov 	if (dev->reg_state != NETREG_REGISTERED)
247c4b4c421SNikolay Aleksandrov 		return -EBUSY;
248c4b4c421SNikolay Aleksandrov 
2494505a3efSStephen Hemminger 	spin_lock_bh(&br->lock);
2509a7b6ef9SJoe Perches 	if (!ether_addr_equal(dev->dev_addr, addr->sa_data)) {
251a3ebb7efSToshiaki Makita 		/* Mac address will be changed in br_stp_change_bridge_id(). */
2524505a3efSStephen Hemminger 		br_stp_change_bridge_id(br, addr->sa_data);
25343598813Sstephen hemminger 	}
2544505a3efSStephen Hemminger 	spin_unlock_bh(&br->lock);
2554505a3efSStephen Hemminger 
256ffe1d49cSStephen Hemminger 	return 0;
2574505a3efSStephen Hemminger }
2584505a3efSStephen Hemminger 
br_getinfo(struct net_device * dev,struct ethtool_drvinfo * info)259edb5e46fSStephen Hemminger static void br_getinfo(struct net_device *dev, struct ethtool_drvinfo *info)
260edb5e46fSStephen Hemminger {
261993e1634SWolfram Sang 	strscpy(info->driver, "bridge", sizeof(info->driver));
262993e1634SWolfram Sang 	strscpy(info->version, BR_VERSION, sizeof(info->version));
263993e1634SWolfram Sang 	strscpy(info->fw_version, "N/A", sizeof(info->fw_version));
264993e1634SWolfram Sang 	strscpy(info->bus_info, "N/A", sizeof(info->bus_info));
265edb5e46fSStephen Hemminger }
266edb5e46fSStephen Hemminger 
br_get_link_ksettings(struct net_device * dev,struct ethtool_link_ksettings * cmd)267542575feSMatthias Schiffer static int br_get_link_ksettings(struct net_device *dev,
268542575feSMatthias Schiffer 				 struct ethtool_link_ksettings *cmd)
269542575feSMatthias Schiffer {
270542575feSMatthias Schiffer 	struct net_bridge *br = netdev_priv(dev);
271542575feSMatthias Schiffer 	struct net_bridge_port *p;
272542575feSMatthias Schiffer 
273542575feSMatthias Schiffer 	cmd->base.duplex = DUPLEX_UNKNOWN;
274542575feSMatthias Schiffer 	cmd->base.port = PORT_OTHER;
275542575feSMatthias Schiffer 	cmd->base.speed = SPEED_UNKNOWN;
276542575feSMatthias Schiffer 
277542575feSMatthias Schiffer 	list_for_each_entry(p, &br->port_list, list) {
278542575feSMatthias Schiffer 		struct ethtool_link_ksettings ecmd;
279542575feSMatthias Schiffer 		struct net_device *pdev = p->dev;
280542575feSMatthias Schiffer 
281542575feSMatthias Schiffer 		if (!netif_running(pdev) || !netif_oper_up(pdev))
282542575feSMatthias Schiffer 			continue;
283542575feSMatthias Schiffer 
284542575feSMatthias Schiffer 		if (__ethtool_get_link_ksettings(pdev, &ecmd))
285542575feSMatthias Schiffer 			continue;
286542575feSMatthias Schiffer 
287542575feSMatthias Schiffer 		if (ecmd.base.speed == (__u32)SPEED_UNKNOWN)
288542575feSMatthias Schiffer 			continue;
289542575feSMatthias Schiffer 
290542575feSMatthias Schiffer 		if (cmd->base.speed == (__u32)SPEED_UNKNOWN ||
291542575feSMatthias Schiffer 		    cmd->base.speed < ecmd.base.speed)
292542575feSMatthias Schiffer 			cmd->base.speed = ecmd.base.speed;
293542575feSMatthias Schiffer 	}
294542575feSMatthias Schiffer 
295542575feSMatthias Schiffer 	return 0;
296542575feSMatthias Schiffer }
297542575feSMatthias Schiffer 
br_fix_features(struct net_device * dev,netdev_features_t features)298c8f44affSMichał Mirosław static netdev_features_t br_fix_features(struct net_device *dev,
299c8f44affSMichał Mirosław 	netdev_features_t features)
300edb5e46fSStephen Hemminger {
301edb5e46fSStephen Hemminger 	struct net_bridge *br = netdev_priv(dev);
302edb5e46fSStephen Hemminger 
303c4d27ef9SMichał Mirosław 	return br_features_recompute(br, features);
304361ff8a6SJesse Gross }
305361ff8a6SJesse Gross 
306c06ee961SWANG Cong #ifdef CONFIG_NET_POLL_CONTROLLER
br_poll_controller(struct net_device * br_dev)307c06ee961SWANG Cong static void br_poll_controller(struct net_device *br_dev)
308c06ee961SWANG Cong {
309c06ee961SWANG Cong }
310c06ee961SWANG Cong 
br_netpoll_cleanup(struct net_device * dev)31191d2c34aSHerbert Xu static void br_netpoll_cleanup(struct net_device *dev)
312c06ee961SWANG Cong {
313cfb478daSstephen hemminger 	struct net_bridge *br = netdev_priv(dev);
3144e3828c4SAmerigo Wang 	struct net_bridge_port *p;
315c06ee961SWANG Cong 
3164e3828c4SAmerigo Wang 	list_for_each_entry(p, &br->port_list, list)
31791d2c34aSHerbert Xu 		br_netpoll_disable(p);
318c06ee961SWANG Cong }
319c06ee961SWANG Cong 
__br_netpoll_enable(struct net_bridge_port * p)320a8779ec1SEric W. Biederman static int __br_netpoll_enable(struct net_bridge_port *p)
32191d2c34aSHerbert Xu {
32291d2c34aSHerbert Xu 	struct netpoll *np;
32393d8bf9fSstephen hemminger 	int err;
32493d8bf9fSstephen hemminger 
325a8779ec1SEric W. Biederman 	np = kzalloc(sizeof(*p->np), GFP_KERNEL);
32691d2c34aSHerbert Xu 	if (!np)
32793d8bf9fSstephen hemminger 		return -ENOMEM;
32891d2c34aSHerbert Xu 
329a8779ec1SEric W. Biederman 	err = __netpoll_setup(np, p->dev);
33091d2c34aSHerbert Xu 	if (err) {
33191d2c34aSHerbert Xu 		kfree(np);
33293d8bf9fSstephen hemminger 		return err;
33391d2c34aSHerbert Xu 	}
33491d2c34aSHerbert Xu 
33591d2c34aSHerbert Xu 	p->np = np;
33691d2c34aSHerbert Xu 	return err;
33791d2c34aSHerbert Xu }
33891d2c34aSHerbert Xu 
br_netpoll_enable(struct net_bridge_port * p)339a8779ec1SEric W. Biederman int br_netpoll_enable(struct net_bridge_port *p)
340dbe17307SCong Wang {
341dbe17307SCong Wang 	if (!p->br->dev->npinfo)
342dbe17307SCong Wang 		return 0;
343dbe17307SCong Wang 
344a8779ec1SEric W. Biederman 	return __br_netpoll_enable(p);
345dbe17307SCong Wang }
346dbe17307SCong Wang 
br_netpoll_setup(struct net_device * dev,struct netpoll_info * ni)347a8779ec1SEric W. Biederman static int br_netpoll_setup(struct net_device *dev, struct netpoll_info *ni)
348dbe17307SCong Wang {
349dbe17307SCong Wang 	struct net_bridge *br = netdev_priv(dev);
350dbe17307SCong Wang 	struct net_bridge_port *p;
351dbe17307SCong Wang 	int err = 0;
352dbe17307SCong Wang 
353dbe17307SCong Wang 	list_for_each_entry(p, &br->port_list, list) {
354dbe17307SCong Wang 		if (!p->dev)
355dbe17307SCong Wang 			continue;
356a8779ec1SEric W. Biederman 		err = __br_netpoll_enable(p);
357dbe17307SCong Wang 		if (err)
358dbe17307SCong Wang 			goto fail;
359dbe17307SCong Wang 	}
360dbe17307SCong Wang 
361dbe17307SCong Wang out:
362dbe17307SCong Wang 	return err;
363dbe17307SCong Wang 
364dbe17307SCong Wang fail:
365dbe17307SCong Wang 	br_netpoll_cleanup(dev);
366dbe17307SCong Wang 	goto out;
367dbe17307SCong Wang }
368dbe17307SCong Wang 
br_netpoll_disable(struct net_bridge_port * p)36991d2c34aSHerbert Xu void br_netpoll_disable(struct net_bridge_port *p)
37091d2c34aSHerbert Xu {
37191d2c34aSHerbert Xu 	struct netpoll *np = p->np;
37291d2c34aSHerbert Xu 
37391d2c34aSHerbert Xu 	if (!np)
37491d2c34aSHerbert Xu 		return;
37591d2c34aSHerbert Xu 
37691d2c34aSHerbert Xu 	p->np = NULL;
37791d2c34aSHerbert Xu 
378c9fbd71fSDebabrata Banerjee 	__netpoll_free(np);
379c06ee961SWANG Cong }
380c06ee961SWANG Cong 
381c06ee961SWANG Cong #endif
382c06ee961SWANG Cong 
br_add_slave(struct net_device * dev,struct net_device * slave_dev,struct netlink_ext_ack * extack)38333eaf2a6SDavid Ahern static int br_add_slave(struct net_device *dev, struct net_device *slave_dev,
38433eaf2a6SDavid Ahern 			struct netlink_ext_ack *extack)
385afc6151aSJiri Pirko 
386afc6151aSJiri Pirko {
387afc6151aSJiri Pirko 	struct net_bridge *br = netdev_priv(dev);
388afc6151aSJiri Pirko 
389ca752be0SDavid Ahern 	return br_add_if(br, slave_dev, extack);
390afc6151aSJiri Pirko }
391afc6151aSJiri Pirko 
br_del_slave(struct net_device * dev,struct net_device * slave_dev)392afc6151aSJiri Pirko static int br_del_slave(struct net_device *dev, struct net_device *slave_dev)
393afc6151aSJiri Pirko {
394afc6151aSJiri Pirko 	struct net_bridge *br = netdev_priv(dev);
395afc6151aSJiri Pirko 
396afc6151aSJiri Pirko 	return br_del_if(br, slave_dev);
397afc6151aSJiri Pirko }
398afc6151aSJiri Pirko 
br_fill_forward_path(struct net_device_path_ctx * ctx,struct net_device_path * path)399ec9d16baSPablo Neira Ayuso static int br_fill_forward_path(struct net_device_path_ctx *ctx,
400ec9d16baSPablo Neira Ayuso 				struct net_device_path *path)
401ec9d16baSPablo Neira Ayuso {
402ec9d16baSPablo Neira Ayuso 	struct net_bridge_fdb_entry *f;
403ec9d16baSPablo Neira Ayuso 	struct net_bridge_port *dst;
404ec9d16baSPablo Neira Ayuso 	struct net_bridge *br;
405ec9d16baSPablo Neira Ayuso 
406ec9d16baSPablo Neira Ayuso 	if (netif_is_bridge_port(ctx->dev))
407ec9d16baSPablo Neira Ayuso 		return -1;
408ec9d16baSPablo Neira Ayuso 
409ec9d16baSPablo Neira Ayuso 	br = netdev_priv(ctx->dev);
410bcf2766bSFelix Fietkau 
411bcf2766bSFelix Fietkau 	br_vlan_fill_forward_path_pvid(br, ctx, path);
412bcf2766bSFelix Fietkau 
413bcf2766bSFelix Fietkau 	f = br_fdb_find_rcu(br, ctx->daddr, path->bridge.vlan_id);
414ec9d16baSPablo Neira Ayuso 	if (!f || !f->dst)
415ec9d16baSPablo Neira Ayuso 		return -1;
416ec9d16baSPablo Neira Ayuso 
417ec9d16baSPablo Neira Ayuso 	dst = READ_ONCE(f->dst);
418ec9d16baSPablo Neira Ayuso 	if (!dst)
419ec9d16baSPablo Neira Ayuso 		return -1;
420ec9d16baSPablo Neira Ayuso 
421bcf2766bSFelix Fietkau 	if (br_vlan_fill_forward_path_mode(br, dst, path))
422bcf2766bSFelix Fietkau 		return -1;
423bcf2766bSFelix Fietkau 
424ec9d16baSPablo Neira Ayuso 	path->type = DEV_PATH_BRIDGE;
425ec9d16baSPablo Neira Ayuso 	path->dev = dst->br->dev;
426ec9d16baSPablo Neira Ayuso 	ctx->dev = dst->dev;
427ec9d16baSPablo Neira Ayuso 
428bcf2766bSFelix Fietkau 	switch (path->bridge.vlan_mode) {
429bcf2766bSFelix Fietkau 	case DEV_PATH_BR_VLAN_TAG:
430bcf2766bSFelix Fietkau 		if (ctx->num_vlans >= ARRAY_SIZE(ctx->vlan))
431bcf2766bSFelix Fietkau 			return -ENOSPC;
432bcf2766bSFelix Fietkau 		ctx->vlan[ctx->num_vlans].id = path->bridge.vlan_id;
433bcf2766bSFelix Fietkau 		ctx->vlan[ctx->num_vlans].proto = path->bridge.vlan_proto;
434bcf2766bSFelix Fietkau 		ctx->num_vlans++;
435bcf2766bSFelix Fietkau 		break;
43626267bf9SFelix Fietkau 	case DEV_PATH_BR_VLAN_UNTAG_HW:
437bcf2766bSFelix Fietkau 	case DEV_PATH_BR_VLAN_UNTAG:
438bcf2766bSFelix Fietkau 		ctx->num_vlans--;
439bcf2766bSFelix Fietkau 		break;
440bcf2766bSFelix Fietkau 	case DEV_PATH_BR_VLAN_KEEP:
441bcf2766bSFelix Fietkau 		break;
442bcf2766bSFelix Fietkau 	}
443bcf2766bSFelix Fietkau 
444ec9d16baSPablo Neira Ayuso 	return 0;
445ec9d16baSPablo Neira Ayuso }
446ec9d16baSPablo Neira Ayuso 
447a2dbb882SStephen Hemminger static const struct ethtool_ops br_ethtool_ops = {
448edb5e46fSStephen Hemminger 	.get_drvinfo		 = br_getinfo,
449edb5e46fSStephen Hemminger 	.get_link		 = ethtool_op_get_link,
450542575feSMatthias Schiffer 	.get_link_ksettings	 = br_get_link_ksettings,
451edb5e46fSStephen Hemminger };
452edb5e46fSStephen Hemminger 
453a2dbb882SStephen Hemminger static const struct net_device_ops br_netdev_ops = {
454a2dbb882SStephen Hemminger 	.ndo_open		 = br_dev_open,
455a2dbb882SStephen Hemminger 	.ndo_stop		 = br_dev_stop,
456bb900b27Sstephen hemminger 	.ndo_init		 = br_dev_init,
457b6fe0440SIdo Schimmel 	.ndo_uninit		 = br_dev_uninit,
45800829823SStephen Hemminger 	.ndo_start_xmit		 = br_dev_xmit,
4597609ecb2SHeiner Kallweit 	.ndo_get_stats64	 = dev_get_tstats64,
460a2dbb882SStephen Hemminger 	.ndo_set_mac_address	 = br_set_mac_address,
461afc4b13dSJiri Pirko 	.ndo_set_rx_mode	 = br_dev_set_multicast_list,
4622796d0c6SVlad Yasevich 	.ndo_change_rx_flags	 = br_dev_change_rx_flags,
463a2dbb882SStephen Hemminger 	.ndo_change_mtu		 = br_change_mtu,
464561d8352SArnd Bergmann 	.ndo_siocdevprivate	 = br_dev_siocdevprivate,
465c06ee961SWANG Cong #ifdef CONFIG_NET_POLL_CONTROLLER
46691d2c34aSHerbert Xu 	.ndo_netpoll_setup	 = br_netpoll_setup,
467c06ee961SWANG Cong 	.ndo_netpoll_cleanup	 = br_netpoll_cleanup,
468c06ee961SWANG Cong 	.ndo_poll_controller	 = br_poll_controller,
469c06ee961SWANG Cong #endif
470afc6151aSJiri Pirko 	.ndo_add_slave		 = br_add_slave,
471afc6151aSJiri Pirko 	.ndo_del_slave		 = br_del_slave,
472c4d27ef9SMichał Mirosław 	.ndo_fix_features        = br_fix_features,
47377162022SJohn Fastabend 	.ndo_fdb_add		 = br_fdb_add,
47477162022SJohn Fastabend 	.ndo_fdb_del		 = br_fdb_delete,
475edaef191SNikolay Aleksandrov 	.ndo_fdb_del_bulk	 = br_fdb_delete_bulk,
47677162022SJohn Fastabend 	.ndo_fdb_dump		 = br_fdb_dump,
47747674562SRoopa Prabhu 	.ndo_fdb_get		 = br_fdb_get,
478cc7f5022SIdo Schimmel 	.ndo_mdb_add		 = br_mdb_add,
479cc7f5022SIdo Schimmel 	.ndo_mdb_del		 = br_mdb_del,
480cc7f5022SIdo Schimmel 	.ndo_mdb_dump		 = br_mdb_dump,
481e5a55a89SJohn Fastabend 	.ndo_bridge_getlink	 = br_getlink,
482e5a55a89SJohn Fastabend 	.ndo_bridge_setlink	 = br_setlink,
483407af329SVlad Yasevich 	.ndo_bridge_dellink	 = br_dellink,
48466780530SToshiaki Makita 	.ndo_features_check	 = passthru_features_check,
485ec9d16baSPablo Neira Ayuso 	.ndo_fill_forward_path	 = br_fill_forward_path,
486a2dbb882SStephen Hemminger };
487a2dbb882SStephen Hemminger 
488bb900b27Sstephen hemminger static struct device_type br_type = {
489bb900b27Sstephen hemminger 	.name	= "bridge",
490bb900b27Sstephen hemminger };
491bb900b27Sstephen hemminger 
br_dev_setup(struct net_device * dev)4921da177e4SLinus Torvalds void br_dev_setup(struct net_device *dev)
4931da177e4SLinus Torvalds {
494bb900b27Sstephen hemminger 	struct net_bridge *br = netdev_priv(dev);
495bb900b27Sstephen hemminger 
4967ce5d222SDanny Kukawka 	eth_hw_addr_random(dev);
4971da177e4SLinus Torvalds 	ether_setup(dev);
4981da177e4SLinus Torvalds 
499a2dbb882SStephen Hemminger 	dev->netdev_ops = &br_netdev_ops;
500cf124db5SDavid S. Miller 	dev->needs_free_netdev = true;
5017ad24ea4SWilfried Klaebe 	dev->ethtool_ops = &br_ethtool_ops;
502bb900b27Sstephen hemminger 	SET_NETDEV_DEVTYPE(dev, &br_type);
503ccecb2a4SPhil Sutter 	dev->priv_flags = IFF_EBRIDGE | IFF_NO_QUEUE;
504edb5e46fSStephen Hemminger 
505161f65baSVlad Yasevich 	dev->features = COMMON_FEATURES | NETIF_F_LLTX | NETIF_F_NETNS_LOCAL |
5061c5abb6cSToshiaki Makita 			NETIF_F_HW_VLAN_CTAG_TX | NETIF_F_HW_VLAN_STAG_TX;
5071c5abb6cSToshiaki Makita 	dev->hw_features = COMMON_FEATURES | NETIF_F_HW_VLAN_CTAG_TX |
5081c5abb6cSToshiaki Makita 			   NETIF_F_HW_VLAN_STAG_TX;
509161f65baSVlad Yasevich 	dev->vlan_features = COMMON_FEATURES;
510bb900b27Sstephen hemminger 
511bb900b27Sstephen hemminger 	br->dev = dev;
512bb900b27Sstephen hemminger 	spin_lock_init(&br->lock);
513bb900b27Sstephen hemminger 	INIT_LIST_HEAD(&br->port_list);
514eb793583SNikolay Aleksandrov 	INIT_HLIST_HEAD(&br->fdb_list);
51590c628ddSHenrik Bjoernlund 	INIT_HLIST_HEAD(&br->frame_type_list);
51665369933SHoratiu Vultur #if IS_ENABLED(CONFIG_BRIDGE_MRP)
5170169b820SHoratiu Vultur 	INIT_HLIST_HEAD(&br->mrp_list);
51865369933SHoratiu Vultur #endif
519f323aa54SHenrik Bjoernlund #if IS_ENABLED(CONFIG_BRIDGE_CFM)
520f323aa54SHenrik Bjoernlund 	INIT_HLIST_HEAD(&br->mep_list);
521f323aa54SHenrik Bjoernlund #endif
522bb900b27Sstephen hemminger 	spin_lock_init(&br->hash_lock);
523bb900b27Sstephen hemminger 
524bb900b27Sstephen hemminger 	br->bridge_id.prio[0] = 0x80;
525bb900b27Sstephen hemminger 	br->bridge_id.prio[1] = 0x00;
526bb900b27Sstephen hemminger 
52705428729SEgil Hjelmeland 	ether_addr_copy(br->group_addr, eth_stp_addr);
528bb900b27Sstephen hemminger 
529bb900b27Sstephen hemminger 	br->stp_enabled = BR_NO_STP;
530515853ccSstephen hemminger 	br->group_fwd_mask = BR_GROUPFWD_DEFAULT;
531f2808d22SToshiaki Makita 	br->group_fwd_mask_required = BR_GROUPFWD_DEFAULT;
532515853ccSstephen hemminger 
533bb900b27Sstephen hemminger 	br->designated_root = br->bridge_id;
534bb900b27Sstephen hemminger 	br->bridge_max_age = br->max_age = 20 * HZ;
535bb900b27Sstephen hemminger 	br->bridge_hello_time = br->hello_time = 2 * HZ;
536bb900b27Sstephen hemminger 	br->bridge_forward_delay = br->forward_delay = 15 * HZ;
53734d8acd8SVivien Didelot 	br->bridge_ageing_time = br->ageing_time = BR_DEFAULT_AGEING_TIME;
53891572088SJarod Wilson 	dev->max_mtu = ETH_MAX_MTU;
539bb900b27Sstephen hemminger 
540bb900b27Sstephen hemminger 	br_netfilter_rtable_init(br);
541bb900b27Sstephen hemminger 	br_stp_timer_init(br);
542bb900b27Sstephen hemminger 	br_multicast_init(br);
543f7cdee8aSNikolay Aleksandrov 	INIT_DELAYED_WORK(&br->gc_work, br_fdb_cleanup);
5441da177e4SLinus Torvalds }
545