aboutsummaryrefslogtreecommitdiffstats
path: root/net/bridge
diff options
context:
space:
mode:
Diffstat (limited to 'net/bridge')
-rw-r--r--net/bridge/br_device.c17
-rw-r--r--net/bridge/br_fdb.c4
-rw-r--r--net/bridge/br_if.c15
-rw-r--r--net/bridge/br_input.c2
-rw-r--r--net/bridge/br_multicast.c19
-rw-r--r--net/bridge/br_private.h5
6 files changed, 43 insertions, 19 deletions
diff --git a/net/bridge/br_device.c b/net/bridge/br_device.c
index 556443566e9..1461b19efd3 100644
--- a/net/bridge/br_device.c
+++ b/net/bridge/br_device.c
@@ -297,6 +297,21 @@ void br_netpoll_disable(struct net_bridge_port *p)
297 297
298#endif 298#endif
299 299
300static int br_add_slave(struct net_device *dev, struct net_device *slave_dev)
301
302{
303 struct net_bridge *br = netdev_priv(dev);
304
305 return br_add_if(br, slave_dev);
306}
307
308static int br_del_slave(struct net_device *dev, struct net_device *slave_dev)
309{
310 struct net_bridge *br = netdev_priv(dev);
311
312 return br_del_if(br, slave_dev);
313}
314
300static const struct ethtool_ops br_ethtool_ops = { 315static const struct ethtool_ops br_ethtool_ops = {
301 .get_drvinfo = br_getinfo, 316 .get_drvinfo = br_getinfo,
302 .get_link = ethtool_op_get_link, 317 .get_link = ethtool_op_get_link,
@@ -326,6 +341,8 @@ static const struct net_device_ops br_netdev_ops = {
326 .ndo_netpoll_cleanup = br_netpoll_cleanup, 341 .ndo_netpoll_cleanup = br_netpoll_cleanup,
327 .ndo_poll_controller = br_poll_controller, 342 .ndo_poll_controller = br_poll_controller,
328#endif 343#endif
344 .ndo_add_slave = br_add_slave,
345 .ndo_del_slave = br_del_slave,
329}; 346};
330 347
331static void br_dev_free(struct net_device *dev) 348static void br_dev_free(struct net_device *dev)
diff --git a/net/bridge/br_fdb.c b/net/bridge/br_fdb.c
index 2872393b293..88485cc74dc 100644
--- a/net/bridge/br_fdb.c
+++ b/net/bridge/br_fdb.c
@@ -328,12 +328,12 @@ static struct net_bridge_fdb_entry *fdb_create(struct hlist_head *head,
328 fdb = kmem_cache_alloc(br_fdb_cache, GFP_ATOMIC); 328 fdb = kmem_cache_alloc(br_fdb_cache, GFP_ATOMIC);
329 if (fdb) { 329 if (fdb) {
330 memcpy(fdb->addr.addr, addr, ETH_ALEN); 330 memcpy(fdb->addr.addr, addr, ETH_ALEN);
331 hlist_add_head_rcu(&fdb->hlist, head);
332
333 fdb->dst = source; 331 fdb->dst = source;
334 fdb->is_local = is_local; 332 fdb->is_local = is_local;
335 fdb->is_static = is_local; 333 fdb->is_static = is_local;
336 fdb->ageing_timer = jiffies; 334 fdb->ageing_timer = jiffies;
335
336 hlist_add_head_rcu(&fdb->hlist, head);
337 } 337 }
338 return fdb; 338 return fdb;
339} 339}
diff --git a/net/bridge/br_if.c b/net/bridge/br_if.c
index d9d1e2bac1d..dce8f0009a1 100644
--- a/net/bridge/br_if.c
+++ b/net/bridge/br_if.c
@@ -148,6 +148,8 @@ static void del_nbp(struct net_bridge_port *p)
148 148
149 netdev_rx_handler_unregister(dev); 149 netdev_rx_handler_unregister(dev);
150 150
151 netdev_set_master(dev, NULL);
152
151 br_multicast_del_port(p); 153 br_multicast_del_port(p);
152 154
153 kobject_uevent(&p->kobj, KOBJ_REMOVE); 155 kobject_uevent(&p->kobj, KOBJ_REMOVE);
@@ -365,7 +367,7 @@ int br_min_mtu(const struct net_bridge *br)
365void br_features_recompute(struct net_bridge *br) 367void br_features_recompute(struct net_bridge *br)
366{ 368{
367 struct net_bridge_port *p; 369 struct net_bridge_port *p;
368 unsigned long features, mask; 370 u32 features, mask;
369 371
370 features = mask = br->feature_mask; 372 features = mask = br->feature_mask;
371 if (list_empty(&br->port_list)) 373 if (list_empty(&br->port_list))
@@ -379,7 +381,7 @@ void br_features_recompute(struct net_bridge *br)
379 } 381 }
380 382
381done: 383done:
382 br->dev->features = netdev_fix_features(features, NULL); 384 br->dev->features = netdev_fix_features(br->dev, features);
383} 385}
384 386
385/* called with RTNL */ 387/* called with RTNL */
@@ -429,10 +431,14 @@ int br_add_if(struct net_bridge *br, struct net_device *dev)
429 if (br_netpoll_info(br) && ((err = br_netpoll_enable(p)))) 431 if (br_netpoll_info(br) && ((err = br_netpoll_enable(p))))
430 goto err3; 432 goto err3;
431 433
432 err = netdev_rx_handler_register(dev, br_handle_frame, p); 434 err = netdev_set_master(dev, br->dev);
433 if (err) 435 if (err)
434 goto err3; 436 goto err3;
435 437
438 err = netdev_rx_handler_register(dev, br_handle_frame, p);
439 if (err)
440 goto err4;
441
436 dev->priv_flags |= IFF_BRIDGE_PORT; 442 dev->priv_flags |= IFF_BRIDGE_PORT;
437 443
438 dev_disable_lro(dev); 444 dev_disable_lro(dev);
@@ -455,6 +461,9 @@ int br_add_if(struct net_bridge *br, struct net_device *dev)
455 kobject_uevent(&p->kobj, KOBJ_ADD); 461 kobject_uevent(&p->kobj, KOBJ_ADD);
456 462
457 return 0; 463 return 0;
464
465err4:
466 netdev_set_master(dev, NULL);
458err3: 467err3:
459 sysfs_remove_link(br->ifobj, p->dev->name); 468 sysfs_remove_link(br->ifobj, p->dev->name);
460err2: 469err2:
diff --git a/net/bridge/br_input.c b/net/bridge/br_input.c
index 6f6d8e1b776..88e4aa9cb1f 100644
--- a/net/bridge/br_input.c
+++ b/net/bridge/br_input.c
@@ -80,7 +80,7 @@ int br_handle_frame_finish(struct sk_buff *skb)
80 if (is_multicast_ether_addr(dest)) { 80 if (is_multicast_ether_addr(dest)) {
81 mdst = br_mdb_get(br, skb); 81 mdst = br_mdb_get(br, skb);
82 if (mdst || BR_INPUT_SKB_CB_MROUTERS_ONLY(skb)) { 82 if (mdst || BR_INPUT_SKB_CB_MROUTERS_ONLY(skb)) {
83 if ((mdst && !hlist_unhashed(&mdst->mglist)) || 83 if ((mdst && mdst->mglist) ||
84 br_multicast_is_router(br)) 84 br_multicast_is_router(br))
85 skb2 = skb; 85 skb2 = skb;
86 br_multicast_forward(mdst, skb, skb2); 86 br_multicast_forward(mdst, skb, skb2);
diff --git a/net/bridge/br_multicast.c b/net/bridge/br_multicast.c
index f701a21acb3..09d5c098792 100644
--- a/net/bridge/br_multicast.c
+++ b/net/bridge/br_multicast.c
@@ -232,8 +232,7 @@ static void br_multicast_group_expired(unsigned long data)
232 if (!netif_running(br->dev) || timer_pending(&mp->timer)) 232 if (!netif_running(br->dev) || timer_pending(&mp->timer))
233 goto out; 233 goto out;
234 234
235 if (!hlist_unhashed(&mp->mglist)) 235 mp->mglist = false;
236 hlist_del_init(&mp->mglist);
237 236
238 if (mp->ports) 237 if (mp->ports)
239 goto out; 238 goto out;
@@ -276,7 +275,7 @@ static void br_multicast_del_pg(struct net_bridge *br,
276 del_timer(&p->query_timer); 275 del_timer(&p->query_timer);
277 call_rcu_bh(&p->rcu, br_multicast_free_pg); 276 call_rcu_bh(&p->rcu, br_multicast_free_pg);
278 277
279 if (!mp->ports && hlist_unhashed(&mp->mglist) && 278 if (!mp->ports && !mp->mglist &&
280 netif_running(br->dev)) 279 netif_running(br->dev))
281 mod_timer(&mp->timer, jiffies); 280 mod_timer(&mp->timer, jiffies);
282 281
@@ -528,7 +527,7 @@ static void br_multicast_group_query_expired(unsigned long data)
528 struct net_bridge *br = mp->br; 527 struct net_bridge *br = mp->br;
529 528
530 spin_lock(&br->multicast_lock); 529 spin_lock(&br->multicast_lock);
531 if (!netif_running(br->dev) || hlist_unhashed(&mp->mglist) || 530 if (!netif_running(br->dev) || !mp->mglist ||
532 mp->queries_sent >= br->multicast_last_member_count) 531 mp->queries_sent >= br->multicast_last_member_count)
533 goto out; 532 goto out;
534 533
@@ -719,7 +718,7 @@ static int br_multicast_add_group(struct net_bridge *br,
719 goto err; 718 goto err;
720 719
721 if (!port) { 720 if (!port) {
722 hlist_add_head(&mp->mglist, &br->mglist); 721 mp->mglist = true;
723 mod_timer(&mp->timer, now + br->multicast_membership_interval); 722 mod_timer(&mp->timer, now + br->multicast_membership_interval);
724 goto out; 723 goto out;
725 } 724 }
@@ -1165,7 +1164,7 @@ static int br_ip4_multicast_query(struct net_bridge *br,
1165 1164
1166 max_delay *= br->multicast_last_member_count; 1165 max_delay *= br->multicast_last_member_count;
1167 1166
1168 if (!hlist_unhashed(&mp->mglist) && 1167 if (mp->mglist &&
1169 (timer_pending(&mp->timer) ? 1168 (timer_pending(&mp->timer) ?
1170 time_after(mp->timer.expires, now + max_delay) : 1169 time_after(mp->timer.expires, now + max_delay) :
1171 try_to_del_timer_sync(&mp->timer) >= 0)) 1170 try_to_del_timer_sync(&mp->timer) >= 0))
@@ -1177,7 +1176,7 @@ static int br_ip4_multicast_query(struct net_bridge *br,
1177 if (timer_pending(&p->timer) ? 1176 if (timer_pending(&p->timer) ?
1178 time_after(p->timer.expires, now + max_delay) : 1177 time_after(p->timer.expires, now + max_delay) :
1179 try_to_del_timer_sync(&p->timer) >= 0) 1178 try_to_del_timer_sync(&p->timer) >= 0)
1180 mod_timer(&mp->timer, now + max_delay); 1179 mod_timer(&p->timer, now + max_delay);
1181 } 1180 }
1182 1181
1183out: 1182out:
@@ -1236,7 +1235,7 @@ static int br_ip6_multicast_query(struct net_bridge *br,
1236 goto out; 1235 goto out;
1237 1236
1238 max_delay *= br->multicast_last_member_count; 1237 max_delay *= br->multicast_last_member_count;
1239 if (!hlist_unhashed(&mp->mglist) && 1238 if (mp->mglist &&
1240 (timer_pending(&mp->timer) ? 1239 (timer_pending(&mp->timer) ?
1241 time_after(mp->timer.expires, now + max_delay) : 1240 time_after(mp->timer.expires, now + max_delay) :
1242 try_to_del_timer_sync(&mp->timer) >= 0)) 1241 try_to_del_timer_sync(&mp->timer) >= 0))
@@ -1248,7 +1247,7 @@ static int br_ip6_multicast_query(struct net_bridge *br,
1248 if (timer_pending(&p->timer) ? 1247 if (timer_pending(&p->timer) ?
1249 time_after(p->timer.expires, now + max_delay) : 1248 time_after(p->timer.expires, now + max_delay) :
1250 try_to_del_timer_sync(&p->timer) >= 0) 1249 try_to_del_timer_sync(&p->timer) >= 0)
1251 mod_timer(&mp->timer, now + max_delay); 1250 mod_timer(&p->timer, now + max_delay);
1252 } 1251 }
1253 1252
1254out: 1253out:
@@ -1283,7 +1282,7 @@ static void br_multicast_leave_group(struct net_bridge *br,
1283 br->multicast_last_member_interval; 1282 br->multicast_last_member_interval;
1284 1283
1285 if (!port) { 1284 if (!port) {
1286 if (!hlist_unhashed(&mp->mglist) && 1285 if (mp->mglist &&
1287 (timer_pending(&mp->timer) ? 1286 (timer_pending(&mp->timer) ?
1288 time_after(mp->timer.expires, time) : 1287 time_after(mp->timer.expires, time) :
1289 try_to_del_timer_sync(&mp->timer) >= 0)) { 1288 try_to_del_timer_sync(&mp->timer) >= 0)) {
diff --git a/net/bridge/br_private.h b/net/bridge/br_private.h
index 84aac7734bf..f7afc364d77 100644
--- a/net/bridge/br_private.h
+++ b/net/bridge/br_private.h
@@ -84,13 +84,13 @@ struct net_bridge_port_group {
84struct net_bridge_mdb_entry 84struct net_bridge_mdb_entry
85{ 85{
86 struct hlist_node hlist[2]; 86 struct hlist_node hlist[2];
87 struct hlist_node mglist;
88 struct net_bridge *br; 87 struct net_bridge *br;
89 struct net_bridge_port_group __rcu *ports; 88 struct net_bridge_port_group __rcu *ports;
90 struct rcu_head rcu; 89 struct rcu_head rcu;
91 struct timer_list timer; 90 struct timer_list timer;
92 struct timer_list query_timer; 91 struct timer_list query_timer;
93 struct br_ip addr; 92 struct br_ip addr;
93 bool mglist;
94 u32 queries_sent; 94 u32 queries_sent;
95}; 95};
96 96
@@ -182,7 +182,7 @@ struct net_bridge
182 struct br_cpu_netstats __percpu *stats; 182 struct br_cpu_netstats __percpu *stats;
183 spinlock_t hash_lock; 183 spinlock_t hash_lock;
184 struct hlist_head hash[BR_HASH_SIZE]; 184 struct hlist_head hash[BR_HASH_SIZE];
185 unsigned long feature_mask; 185 u32 feature_mask;
186#ifdef CONFIG_BRIDGE_NETFILTER 186#ifdef CONFIG_BRIDGE_NETFILTER
187 struct rtable fake_rtable; 187 struct rtable fake_rtable;
188 bool nf_call_iptables; 188 bool nf_call_iptables;
@@ -238,7 +238,6 @@ struct net_bridge
238 spinlock_t multicast_lock; 238 spinlock_t multicast_lock;
239 struct net_bridge_mdb_htable __rcu *mdb; 239 struct net_bridge_mdb_htable __rcu *mdb;
240 struct hlist_head router_list; 240 struct hlist_head router_list;
241 struct hlist_head mglist;
242 241
243 struct timer_list multicast_router_timer; 242 struct timer_list multicast_router_timer;
244 struct timer_list multicast_querier_timer; 243 struct timer_list multicast_querier_timer;