diff options
Diffstat (limited to 'net/bridge')
-rw-r--r-- | net/bridge/br_device.c | 17 | ||||
-rw-r--r-- | net/bridge/br_fdb.c | 4 | ||||
-rw-r--r-- | net/bridge/br_if.c | 15 | ||||
-rw-r--r-- | net/bridge/br_input.c | 2 | ||||
-rw-r--r-- | net/bridge/br_multicast.c | 19 | ||||
-rw-r--r-- | net/bridge/br_private.h | 5 |
6 files changed, 43 insertions, 19 deletions
diff --git a/net/bridge/br_device.c b/net/bridge/br_device.c index 556443566e9c..1461b19efd38 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 | ||
300 | static 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 | |||
308 | static 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 | |||
300 | static const struct ethtool_ops br_ethtool_ops = { | 315 | static 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 | ||
331 | static void br_dev_free(struct net_device *dev) | 348 | static void br_dev_free(struct net_device *dev) |
diff --git a/net/bridge/br_fdb.c b/net/bridge/br_fdb.c index 2872393b2939..88485cc74dc3 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 d9d1e2bac1d6..dce8f0009a12 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) | |||
365 | void br_features_recompute(struct net_bridge *br) | 367 | void 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 | ||
381 | done: | 383 | done: |
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 | |||
465 | err4: | ||
466 | netdev_set_master(dev, NULL); | ||
458 | err3: | 467 | err3: |
459 | sysfs_remove_link(br->ifobj, p->dev->name); | 468 | sysfs_remove_link(br->ifobj, p->dev->name); |
460 | err2: | 469 | err2: |
diff --git a/net/bridge/br_input.c b/net/bridge/br_input.c index 6f6d8e1b776f..88e4aa9cb1f9 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 f701a21acb34..09d5c0987925 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 | ||
1183 | out: | 1182 | out: |
@@ -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 | ||
1254 | out: | 1253 | out: |
@@ -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 84aac7734bfc..f7afc364d777 100644 --- a/net/bridge/br_private.h +++ b/net/bridge/br_private.h | |||
@@ -84,13 +84,13 @@ struct net_bridge_port_group { | |||
84 | struct net_bridge_mdb_entry | 84 | struct 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; |