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