diff options
Diffstat (limited to 'net/bridge')
-rw-r--r-- | net/bridge/br_device.c | 14 | ||||
-rw-r--r-- | net/bridge/br_fdb.c | 2 | ||||
-rw-r--r-- | net/bridge/br_if.c | 23 | ||||
-rw-r--r-- | net/bridge/br_multicast.c | 23 | ||||
-rw-r--r-- | net/bridge/br_netfilter.c | 18 | ||||
-rw-r--r-- | net/bridge/br_netlink.c | 18 | ||||
-rw-r--r-- | net/bridge/br_notify.c | 7 | ||||
-rw-r--r-- | net/bridge/br_private.h | 2 | ||||
-rw-r--r-- | net/bridge/br_private_stp.h | 3 | ||||
-rw-r--r-- | net/bridge/br_stp.c | 31 | ||||
-rw-r--r-- | net/bridge/br_stp_bpdu.c | 15 | ||||
-rw-r--r-- | net/bridge/br_stp_if.c | 3 | ||||
-rw-r--r-- | net/bridge/br_stp_timer.c | 1 | ||||
-rw-r--r-- | net/bridge/netfilter/Kconfig | 2 | ||||
-rw-r--r-- | net/bridge/netfilter/ebt_ulog.c | 1 | ||||
-rw-r--r-- | net/bridge/netfilter/ebtables.c | 3 |
16 files changed, 110 insertions, 56 deletions
diff --git a/net/bridge/br_device.c b/net/bridge/br_device.c index 32b8f9f7f79..dac6a214746 100644 --- a/net/bridge/br_device.c +++ b/net/bridge/br_device.c | |||
@@ -38,16 +38,17 @@ netdev_tx_t br_dev_xmit(struct sk_buff *skb, struct net_device *dev) | |||
38 | } | 38 | } |
39 | #endif | 39 | #endif |
40 | 40 | ||
41 | u64_stats_update_begin(&brstats->syncp); | ||
42 | brstats->tx_packets++; | ||
43 | brstats->tx_bytes += skb->len; | ||
44 | u64_stats_update_end(&brstats->syncp); | ||
45 | |||
46 | BR_INPUT_SKB_CB(skb)->brdev = dev; | 41 | BR_INPUT_SKB_CB(skb)->brdev = dev; |
47 | 42 | ||
48 | skb_reset_mac_header(skb); | 43 | skb_reset_mac_header(skb); |
49 | skb_pull(skb, ETH_HLEN); | 44 | skb_pull(skb, ETH_HLEN); |
50 | 45 | ||
46 | u64_stats_update_begin(&brstats->syncp); | ||
47 | brstats->tx_packets++; | ||
48 | /* Exclude ETH_HLEN from byte stats for consistency with Rx chain */ | ||
49 | brstats->tx_bytes += skb->len; | ||
50 | u64_stats_update_end(&brstats->syncp); | ||
51 | |||
51 | rcu_read_lock(); | 52 | rcu_read_lock(); |
52 | if (is_broadcast_ether_addr(dest)) | 53 | if (is_broadcast_ether_addr(dest)) |
53 | br_flood_deliver(br, skb); | 54 | br_flood_deliver(br, skb); |
@@ -91,7 +92,6 @@ static int br_dev_open(struct net_device *dev) | |||
91 | { | 92 | { |
92 | struct net_bridge *br = netdev_priv(dev); | 93 | struct net_bridge *br = netdev_priv(dev); |
93 | 94 | ||
94 | netif_carrier_off(dev); | ||
95 | netdev_update_features(dev); | 95 | netdev_update_features(dev); |
96 | netif_start_queue(dev); | 96 | netif_start_queue(dev); |
97 | br_stp_enable_bridge(br); | 97 | br_stp_enable_bridge(br); |
@@ -108,8 +108,6 @@ static int br_dev_stop(struct net_device *dev) | |||
108 | { | 108 | { |
109 | struct net_bridge *br = netdev_priv(dev); | 109 | struct net_bridge *br = netdev_priv(dev); |
110 | 110 | ||
111 | netif_carrier_off(dev); | ||
112 | |||
113 | br_stp_disable_bridge(br); | 111 | br_stp_disable_bridge(br); |
114 | br_multicast_stop(br); | 112 | br_multicast_stop(br); |
115 | 113 | ||
diff --git a/net/bridge/br_fdb.c b/net/bridge/br_fdb.c index e0dfbc151dd..68def3b7fb4 100644 --- a/net/bridge/br_fdb.c +++ b/net/bridge/br_fdb.c | |||
@@ -21,7 +21,7 @@ | |||
21 | #include <linux/jhash.h> | 21 | #include <linux/jhash.h> |
22 | #include <linux/random.h> | 22 | #include <linux/random.h> |
23 | #include <linux/slab.h> | 23 | #include <linux/slab.h> |
24 | #include <asm/atomic.h> | 24 | #include <linux/atomic.h> |
25 | #include <asm/unaligned.h> | 25 | #include <asm/unaligned.h> |
26 | #include "br_private.h" | 26 | #include "br_private.h" |
27 | 27 | ||
diff --git a/net/bridge/br_if.c b/net/bridge/br_if.c index 1bacca4cb67..1d420f64ff2 100644 --- a/net/bridge/br_if.c +++ b/net/bridge/br_if.c | |||
@@ -161,9 +161,10 @@ static void del_nbp(struct net_bridge_port *p) | |||
161 | call_rcu(&p->rcu, destroy_nbp_rcu); | 161 | call_rcu(&p->rcu, destroy_nbp_rcu); |
162 | } | 162 | } |
163 | 163 | ||
164 | /* called with RTNL */ | 164 | /* Delete bridge device */ |
165 | static void del_br(struct net_bridge *br, struct list_head *head) | 165 | void br_dev_delete(struct net_device *dev, struct list_head *head) |
166 | { | 166 | { |
167 | struct net_bridge *br = netdev_priv(dev); | ||
167 | struct net_bridge_port *p, *n; | 168 | struct net_bridge_port *p, *n; |
168 | 169 | ||
169 | list_for_each_entry_safe(p, n, &br->port_list, list) { | 170 | list_for_each_entry_safe(p, n, &br->port_list, list) { |
@@ -231,6 +232,7 @@ static struct net_bridge_port *new_nbp(struct net_bridge *br, | |||
231 | int br_add_bridge(struct net *net, const char *name) | 232 | int br_add_bridge(struct net *net, const char *name) |
232 | { | 233 | { |
233 | struct net_device *dev; | 234 | struct net_device *dev; |
235 | int res; | ||
234 | 236 | ||
235 | dev = alloc_netdev(sizeof(struct net_bridge), name, | 237 | dev = alloc_netdev(sizeof(struct net_bridge), name, |
236 | br_dev_setup); | 238 | br_dev_setup); |
@@ -240,7 +242,10 @@ int br_add_bridge(struct net *net, const char *name) | |||
240 | 242 | ||
241 | dev_net_set(dev, net); | 243 | dev_net_set(dev, net); |
242 | 244 | ||
243 | return register_netdev(dev); | 245 | res = register_netdev(dev); |
246 | if (res) | ||
247 | free_netdev(dev); | ||
248 | return res; | ||
244 | } | 249 | } |
245 | 250 | ||
246 | int br_del_bridge(struct net *net, const char *name) | 251 | int br_del_bridge(struct net *net, const char *name) |
@@ -264,7 +269,7 @@ int br_del_bridge(struct net *net, const char *name) | |||
264 | } | 269 | } |
265 | 270 | ||
266 | else | 271 | else |
267 | del_br(netdev_priv(dev), NULL); | 272 | br_dev_delete(dev, NULL); |
268 | 273 | ||
269 | rtnl_unlock(); | 274 | rtnl_unlock(); |
270 | return ret; | 275 | return ret; |
@@ -388,7 +393,7 @@ int br_add_if(struct net_bridge *br, struct net_device *dev) | |||
388 | br_ifinfo_notify(RTM_NEWLINK, p); | 393 | br_ifinfo_notify(RTM_NEWLINK, p); |
389 | 394 | ||
390 | if (changed_addr) | 395 | if (changed_addr) |
391 | call_netdevice_notifiers(NETDEV_CHANGEADDR, dev); | 396 | call_netdevice_notifiers(NETDEV_CHANGEADDR, br->dev); |
392 | 397 | ||
393 | dev_set_mtu(br->dev, br_min_mtu(br)); | 398 | dev_set_mtu(br->dev, br_min_mtu(br)); |
394 | 399 | ||
@@ -417,6 +422,7 @@ put_back: | |||
417 | int br_del_if(struct net_bridge *br, struct net_device *dev) | 422 | int br_del_if(struct net_bridge *br, struct net_device *dev) |
418 | { | 423 | { |
419 | struct net_bridge_port *p; | 424 | struct net_bridge_port *p; |
425 | bool changed_addr; | ||
420 | 426 | ||
421 | p = br_port_get_rtnl(dev); | 427 | p = br_port_get_rtnl(dev); |
422 | if (!p || p->br != br) | 428 | if (!p || p->br != br) |
@@ -425,9 +431,12 @@ int br_del_if(struct net_bridge *br, struct net_device *dev) | |||
425 | del_nbp(p); | 431 | del_nbp(p); |
426 | 432 | ||
427 | spin_lock_bh(&br->lock); | 433 | spin_lock_bh(&br->lock); |
428 | br_stp_recalculate_bridge_id(br); | 434 | changed_addr = br_stp_recalculate_bridge_id(br); |
429 | spin_unlock_bh(&br->lock); | 435 | spin_unlock_bh(&br->lock); |
430 | 436 | ||
437 | if (changed_addr) | ||
438 | call_netdevice_notifiers(NETDEV_CHANGEADDR, br->dev); | ||
439 | |||
431 | netdev_update_features(br->dev); | 440 | netdev_update_features(br->dev); |
432 | 441 | ||
433 | return 0; | 442 | return 0; |
@@ -441,7 +450,7 @@ void __net_exit br_net_exit(struct net *net) | |||
441 | rtnl_lock(); | 450 | rtnl_lock(); |
442 | for_each_netdev(net, dev) | 451 | for_each_netdev(net, dev) |
443 | if (dev->priv_flags & IFF_EBRIDGE) | 452 | if (dev->priv_flags & IFF_EBRIDGE) |
444 | del_br(netdev_priv(dev), &list); | 453 | br_dev_delete(dev, &list); |
445 | 454 | ||
446 | unregister_netdevice_many(&list); | 455 | unregister_netdevice_many(&list); |
447 | rtnl_unlock(); | 456 | rtnl_unlock(); |
diff --git a/net/bridge/br_multicast.c b/net/bridge/br_multicast.c index 2d85ca7111d..e79ff75b0e7 100644 --- a/net/bridge/br_multicast.c +++ b/net/bridge/br_multicast.c | |||
@@ -1456,7 +1456,7 @@ static int br_multicast_ipv6_rcv(struct net_bridge *br, | |||
1456 | { | 1456 | { |
1457 | struct sk_buff *skb2; | 1457 | struct sk_buff *skb2; |
1458 | const struct ipv6hdr *ip6h; | 1458 | const struct ipv6hdr *ip6h; |
1459 | struct icmp6hdr *icmp6h; | 1459 | u8 icmp6_type; |
1460 | u8 nexthdr; | 1460 | u8 nexthdr; |
1461 | unsigned len; | 1461 | unsigned len; |
1462 | int offset; | 1462 | int offset; |
@@ -1501,10 +1501,12 @@ static int br_multicast_ipv6_rcv(struct net_bridge *br, | |||
1501 | 1501 | ||
1502 | __skb_pull(skb2, offset); | 1502 | __skb_pull(skb2, offset); |
1503 | skb_reset_transport_header(skb2); | 1503 | skb_reset_transport_header(skb2); |
1504 | skb_postpull_rcsum(skb2, skb_network_header(skb2), | ||
1505 | skb_network_header_len(skb2)); | ||
1504 | 1506 | ||
1505 | icmp6h = icmp6_hdr(skb2); | 1507 | icmp6_type = icmp6_hdr(skb2)->icmp6_type; |
1506 | 1508 | ||
1507 | switch (icmp6h->icmp6_type) { | 1509 | switch (icmp6_type) { |
1508 | case ICMPV6_MGM_QUERY: | 1510 | case ICMPV6_MGM_QUERY: |
1509 | case ICMPV6_MGM_REPORT: | 1511 | case ICMPV6_MGM_REPORT: |
1510 | case ICMPV6_MGM_REDUCTION: | 1512 | case ICMPV6_MGM_REDUCTION: |
@@ -1520,16 +1522,23 @@ static int br_multicast_ipv6_rcv(struct net_bridge *br, | |||
1520 | err = pskb_trim_rcsum(skb2, len); | 1522 | err = pskb_trim_rcsum(skb2, len); |
1521 | if (err) | 1523 | if (err) |
1522 | goto out; | 1524 | goto out; |
1525 | err = -EINVAL; | ||
1523 | } | 1526 | } |
1524 | 1527 | ||
1528 | ip6h = ipv6_hdr(skb2); | ||
1529 | |||
1525 | switch (skb2->ip_summed) { | 1530 | switch (skb2->ip_summed) { |
1526 | case CHECKSUM_COMPLETE: | 1531 | case CHECKSUM_COMPLETE: |
1527 | if (!csum_fold(skb2->csum)) | 1532 | if (!csum_ipv6_magic(&ip6h->saddr, &ip6h->daddr, skb2->len, |
1533 | IPPROTO_ICMPV6, skb2->csum)) | ||
1528 | break; | 1534 | break; |
1529 | /*FALLTHROUGH*/ | 1535 | /*FALLTHROUGH*/ |
1530 | case CHECKSUM_NONE: | 1536 | case CHECKSUM_NONE: |
1531 | skb2->csum = 0; | 1537 | skb2->csum = ~csum_unfold(csum_ipv6_magic(&ip6h->saddr, |
1532 | if (skb_checksum_complete(skb2)) | 1538 | &ip6h->daddr, |
1539 | skb2->len, | ||
1540 | IPPROTO_ICMPV6, 0)); | ||
1541 | if (__skb_checksum_complete(skb2)) | ||
1533 | goto out; | 1542 | goto out; |
1534 | } | 1543 | } |
1535 | 1544 | ||
@@ -1537,7 +1546,7 @@ static int br_multicast_ipv6_rcv(struct net_bridge *br, | |||
1537 | 1546 | ||
1538 | BR_INPUT_SKB_CB(skb)->igmp = 1; | 1547 | BR_INPUT_SKB_CB(skb)->igmp = 1; |
1539 | 1548 | ||
1540 | switch (icmp6h->icmp6_type) { | 1549 | switch (icmp6_type) { |
1541 | case ICMPV6_MGM_REPORT: | 1550 | case ICMPV6_MGM_REPORT: |
1542 | { | 1551 | { |
1543 | struct mld_msg *mld; | 1552 | struct mld_msg *mld; |
diff --git a/net/bridge/br_netfilter.c b/net/bridge/br_netfilter.c index 56149ec36d7..5693e5f9e03 100644 --- a/net/bridge/br_netfilter.c +++ b/net/bridge/br_netfilter.c | |||
@@ -109,11 +109,17 @@ static u32 *fake_cow_metrics(struct dst_entry *dst, unsigned long old) | |||
109 | return NULL; | 109 | return NULL; |
110 | } | 110 | } |
111 | 111 | ||
112 | static struct neighbour *fake_neigh_lookup(const struct dst_entry *dst, const void *daddr) | ||
113 | { | ||
114 | return NULL; | ||
115 | } | ||
116 | |||
112 | static struct dst_ops fake_dst_ops = { | 117 | static struct dst_ops fake_dst_ops = { |
113 | .family = AF_INET, | 118 | .family = AF_INET, |
114 | .protocol = cpu_to_be16(ETH_P_IP), | 119 | .protocol = cpu_to_be16(ETH_P_IP), |
115 | .update_pmtu = fake_update_pmtu, | 120 | .update_pmtu = fake_update_pmtu, |
116 | .cow_metrics = fake_cow_metrics, | 121 | .cow_metrics = fake_cow_metrics, |
122 | .neigh_lookup = fake_neigh_lookup, | ||
117 | }; | 123 | }; |
118 | 124 | ||
119 | /* | 125 | /* |
@@ -135,7 +141,7 @@ void br_netfilter_rtable_init(struct net_bridge *br) | |||
135 | rt->dst.dev = br->dev; | 141 | rt->dst.dev = br->dev; |
136 | rt->dst.path = &rt->dst; | 142 | rt->dst.path = &rt->dst; |
137 | dst_init_metrics(&rt->dst, br_dst_default_metrics, true); | 143 | dst_init_metrics(&rt->dst, br_dst_default_metrics, true); |
138 | rt->dst.flags = DST_NOXFRM; | 144 | rt->dst.flags = DST_NOXFRM | DST_NOPEER; |
139 | rt->dst.ops = &fake_dst_ops; | 145 | rt->dst.ops = &fake_dst_ops; |
140 | } | 146 | } |
141 | 147 | ||
@@ -343,24 +349,26 @@ static int br_nf_pre_routing_finish_ipv6(struct sk_buff *skb) | |||
343 | static int br_nf_pre_routing_finish_bridge(struct sk_buff *skb) | 349 | static int br_nf_pre_routing_finish_bridge(struct sk_buff *skb) |
344 | { | 350 | { |
345 | struct nf_bridge_info *nf_bridge = skb->nf_bridge; | 351 | struct nf_bridge_info *nf_bridge = skb->nf_bridge; |
352 | struct neighbour *neigh; | ||
346 | struct dst_entry *dst; | 353 | struct dst_entry *dst; |
347 | 354 | ||
348 | skb->dev = bridge_parent(skb->dev); | 355 | skb->dev = bridge_parent(skb->dev); |
349 | if (!skb->dev) | 356 | if (!skb->dev) |
350 | goto free_skb; | 357 | goto free_skb; |
351 | dst = skb_dst(skb); | 358 | dst = skb_dst(skb); |
352 | if (dst->hh) { | 359 | neigh = dst_get_neighbour(dst); |
353 | neigh_hh_bridge(dst->hh, skb); | 360 | if (neigh->hh.hh_len) { |
361 | neigh_hh_bridge(&neigh->hh, skb); | ||
354 | skb->dev = nf_bridge->physindev; | 362 | skb->dev = nf_bridge->physindev; |
355 | return br_handle_frame_finish(skb); | 363 | return br_handle_frame_finish(skb); |
356 | } else if (dst->neighbour) { | 364 | } else { |
357 | /* the neighbour function below overwrites the complete | 365 | /* the neighbour function below overwrites the complete |
358 | * MAC header, so we save the Ethernet source address and | 366 | * MAC header, so we save the Ethernet source address and |
359 | * protocol number. */ | 367 | * protocol number. */ |
360 | skb_copy_from_linear_data_offset(skb, -(ETH_HLEN-ETH_ALEN), skb->nf_bridge->data, ETH_HLEN-ETH_ALEN); | 368 | skb_copy_from_linear_data_offset(skb, -(ETH_HLEN-ETH_ALEN), skb->nf_bridge->data, ETH_HLEN-ETH_ALEN); |
361 | /* tell br_dev_xmit to continue with forwarding */ | 369 | /* tell br_dev_xmit to continue with forwarding */ |
362 | nf_bridge->mask |= BRNF_BRIDGED_DNAT; | 370 | nf_bridge->mask |= BRNF_BRIDGED_DNAT; |
363 | return dst->neighbour->output(skb); | 371 | return neigh->output(neigh, skb); |
364 | } | 372 | } |
365 | free_skb: | 373 | free_skb: |
366 | kfree_skb(skb); | 374 | kfree_skb(skb); |
diff --git a/net/bridge/br_netlink.c b/net/bridge/br_netlink.c index ffb0dc4cc0e..e5f9ece3c9a 100644 --- a/net/bridge/br_netlink.c +++ b/net/bridge/br_netlink.c | |||
@@ -188,6 +188,8 @@ static int br_rtm_setlink(struct sk_buff *skb, struct nlmsghdr *nlh, void *arg) | |||
188 | 188 | ||
189 | p->state = new_state; | 189 | p->state = new_state; |
190 | br_log_state(p); | 190 | br_log_state(p); |
191 | br_ifinfo_notify(RTM_NEWLINK, p); | ||
192 | |||
191 | return 0; | 193 | return 0; |
192 | } | 194 | } |
193 | 195 | ||
@@ -208,6 +210,7 @@ static struct rtnl_link_ops br_link_ops __read_mostly = { | |||
208 | .priv_size = sizeof(struct net_bridge), | 210 | .priv_size = sizeof(struct net_bridge), |
209 | .setup = br_dev_setup, | 211 | .setup = br_dev_setup, |
210 | .validate = br_validate, | 212 | .validate = br_validate, |
213 | .dellink = br_dev_delete, | ||
211 | }; | 214 | }; |
212 | 215 | ||
213 | int __init br_netlink_init(void) | 216 | int __init br_netlink_init(void) |
@@ -218,19 +221,24 @@ int __init br_netlink_init(void) | |||
218 | if (err < 0) | 221 | if (err < 0) |
219 | goto err1; | 222 | goto err1; |
220 | 223 | ||
221 | err = __rtnl_register(PF_BRIDGE, RTM_GETLINK, NULL, br_dump_ifinfo); | 224 | err = __rtnl_register(PF_BRIDGE, RTM_GETLINK, NULL, |
225 | br_dump_ifinfo, NULL); | ||
222 | if (err) | 226 | if (err) |
223 | goto err2; | 227 | goto err2; |
224 | err = __rtnl_register(PF_BRIDGE, RTM_SETLINK, br_rtm_setlink, NULL); | 228 | err = __rtnl_register(PF_BRIDGE, RTM_SETLINK, |
229 | br_rtm_setlink, NULL, NULL); | ||
225 | if (err) | 230 | if (err) |
226 | goto err3; | 231 | goto err3; |
227 | err = __rtnl_register(PF_BRIDGE, RTM_NEWNEIGH, br_fdb_add, NULL); | 232 | err = __rtnl_register(PF_BRIDGE, RTM_NEWNEIGH, |
233 | br_fdb_add, NULL, NULL); | ||
228 | if (err) | 234 | if (err) |
229 | goto err3; | 235 | goto err3; |
230 | err = __rtnl_register(PF_BRIDGE, RTM_DELNEIGH, br_fdb_delete, NULL); | 236 | err = __rtnl_register(PF_BRIDGE, RTM_DELNEIGH, |
237 | br_fdb_delete, NULL, NULL); | ||
231 | if (err) | 238 | if (err) |
232 | goto err3; | 239 | goto err3; |
233 | err = __rtnl_register(PF_BRIDGE, RTM_GETNEIGH, NULL, br_fdb_dump); | 240 | err = __rtnl_register(PF_BRIDGE, RTM_GETNEIGH, |
241 | NULL, br_fdb_dump, NULL); | ||
234 | if (err) | 242 | if (err) |
235 | goto err3; | 243 | goto err3; |
236 | 244 | ||
diff --git a/net/bridge/br_notify.c b/net/bridge/br_notify.c index 6545ee9591d..a76b6213555 100644 --- a/net/bridge/br_notify.c +++ b/net/bridge/br_notify.c | |||
@@ -34,6 +34,7 @@ static int br_device_event(struct notifier_block *unused, unsigned long event, v | |||
34 | struct net_device *dev = ptr; | 34 | struct net_device *dev = ptr; |
35 | struct net_bridge_port *p; | 35 | struct net_bridge_port *p; |
36 | struct net_bridge *br; | 36 | struct net_bridge *br; |
37 | bool changed_addr; | ||
37 | int err; | 38 | int err; |
38 | 39 | ||
39 | /* register of bridge completed, add sysfs entries */ | 40 | /* register of bridge completed, add sysfs entries */ |
@@ -57,8 +58,12 @@ static int br_device_event(struct notifier_block *unused, unsigned long event, v | |||
57 | case NETDEV_CHANGEADDR: | 58 | case NETDEV_CHANGEADDR: |
58 | spin_lock_bh(&br->lock); | 59 | spin_lock_bh(&br->lock); |
59 | br_fdb_changeaddr(p, dev->dev_addr); | 60 | br_fdb_changeaddr(p, dev->dev_addr); |
60 | br_stp_recalculate_bridge_id(br); | 61 | changed_addr = br_stp_recalculate_bridge_id(br); |
61 | spin_unlock_bh(&br->lock); | 62 | spin_unlock_bh(&br->lock); |
63 | |||
64 | if (changed_addr) | ||
65 | call_netdevice_notifiers(NETDEV_CHANGEADDR, br->dev); | ||
66 | |||
62 | break; | 67 | break; |
63 | 68 | ||
64 | case NETDEV_CHANGE: | 69 | case NETDEV_CHANGE: |
diff --git a/net/bridge/br_private.h b/net/bridge/br_private.h index 54578f274d8..857a021deea 100644 --- a/net/bridge/br_private.h +++ b/net/bridge/br_private.h | |||
@@ -124,6 +124,7 @@ struct net_bridge_port | |||
124 | bridge_id designated_bridge; | 124 | bridge_id designated_bridge; |
125 | u32 path_cost; | 125 | u32 path_cost; |
126 | u32 designated_cost; | 126 | u32 designated_cost; |
127 | unsigned long designated_age; | ||
127 | 128 | ||
128 | struct timer_list forward_delay_timer; | 129 | struct timer_list forward_delay_timer; |
129 | struct timer_list hold_timer; | 130 | struct timer_list hold_timer; |
@@ -293,6 +294,7 @@ static inline int br_is_root_bridge(const struct net_bridge *br) | |||
293 | 294 | ||
294 | /* br_device.c */ | 295 | /* br_device.c */ |
295 | extern void br_dev_setup(struct net_device *dev); | 296 | extern void br_dev_setup(struct net_device *dev); |
297 | extern void br_dev_delete(struct net_device *dev, struct list_head *list); | ||
296 | extern netdev_tx_t br_dev_xmit(struct sk_buff *skb, | 298 | extern netdev_tx_t br_dev_xmit(struct sk_buff *skb, |
297 | struct net_device *dev); | 299 | struct net_device *dev); |
298 | #ifdef CONFIG_NET_POLL_CONTROLLER | 300 | #ifdef CONFIG_NET_POLL_CONTROLLER |
diff --git a/net/bridge/br_private_stp.h b/net/bridge/br_private_stp.h index 642ef47a867..05ed9bc7e42 100644 --- a/net/bridge/br_private_stp.h +++ b/net/bridge/br_private_stp.h | |||
@@ -56,7 +56,8 @@ extern void br_become_root_bridge(struct net_bridge *br); | |||
56 | extern void br_config_bpdu_generation(struct net_bridge *); | 56 | extern void br_config_bpdu_generation(struct net_bridge *); |
57 | extern void br_configuration_update(struct net_bridge *); | 57 | extern void br_configuration_update(struct net_bridge *); |
58 | extern void br_port_state_selection(struct net_bridge *); | 58 | extern void br_port_state_selection(struct net_bridge *); |
59 | extern void br_received_config_bpdu(struct net_bridge_port *p, struct br_config_bpdu *bpdu); | 59 | extern void br_received_config_bpdu(struct net_bridge_port *p, |
60 | const struct br_config_bpdu *bpdu); | ||
60 | extern void br_received_tcn_bpdu(struct net_bridge_port *p); | 61 | extern void br_received_tcn_bpdu(struct net_bridge_port *p); |
61 | extern void br_transmit_config(struct net_bridge_port *p); | 62 | extern void br_transmit_config(struct net_bridge_port *p); |
62 | extern void br_transmit_tcn(struct net_bridge *br); | 63 | extern void br_transmit_tcn(struct net_bridge *br); |
diff --git a/net/bridge/br_stp.c b/net/bridge/br_stp.c index bb4383e84de..ad0a3f7cf6c 100644 --- a/net/bridge/br_stp.c +++ b/net/bridge/br_stp.c | |||
@@ -109,7 +109,6 @@ static void br_root_selection(struct net_bridge *br) | |||
109 | list_for_each_entry(p, &br->port_list, list) { | 109 | list_for_each_entry(p, &br->port_list, list) { |
110 | if (br_should_become_root_port(p, root_port)) | 110 | if (br_should_become_root_port(p, root_port)) |
111 | root_port = p->port_no; | 111 | root_port = p->port_no; |
112 | |||
113 | } | 112 | } |
114 | 113 | ||
115 | br->root_port = root_port; | 114 | br->root_port = root_port; |
@@ -145,7 +144,6 @@ void br_transmit_config(struct net_bridge_port *p) | |||
145 | struct br_config_bpdu bpdu; | 144 | struct br_config_bpdu bpdu; |
146 | struct net_bridge *br; | 145 | struct net_bridge *br; |
147 | 146 | ||
148 | |||
149 | if (timer_pending(&p->hold_timer)) { | 147 | if (timer_pending(&p->hold_timer)) { |
150 | p->config_pending = 1; | 148 | p->config_pending = 1; |
151 | return; | 149 | return; |
@@ -164,8 +162,7 @@ void br_transmit_config(struct net_bridge_port *p) | |||
164 | else { | 162 | else { |
165 | struct net_bridge_port *root | 163 | struct net_bridge_port *root |
166 | = br_get_port(br, br->root_port); | 164 | = br_get_port(br, br->root_port); |
167 | bpdu.message_age = br->max_age | 165 | bpdu.message_age = (jiffies - root->designated_age) |
168 | - (root->message_age_timer.expires - jiffies) | ||
169 | + MESSAGE_AGE_INCR; | 166 | + MESSAGE_AGE_INCR; |
170 | } | 167 | } |
171 | bpdu.max_age = br->max_age; | 168 | bpdu.max_age = br->max_age; |
@@ -182,20 +179,21 @@ void br_transmit_config(struct net_bridge_port *p) | |||
182 | } | 179 | } |
183 | 180 | ||
184 | /* called under bridge lock */ | 181 | /* called under bridge lock */ |
185 | static inline void br_record_config_information(struct net_bridge_port *p, | 182 | static void br_record_config_information(struct net_bridge_port *p, |
186 | const struct br_config_bpdu *bpdu) | 183 | const struct br_config_bpdu *bpdu) |
187 | { | 184 | { |
188 | p->designated_root = bpdu->root; | 185 | p->designated_root = bpdu->root; |
189 | p->designated_cost = bpdu->root_path_cost; | 186 | p->designated_cost = bpdu->root_path_cost; |
190 | p->designated_bridge = bpdu->bridge_id; | 187 | p->designated_bridge = bpdu->bridge_id; |
191 | p->designated_port = bpdu->port_id; | 188 | p->designated_port = bpdu->port_id; |
189 | p->designated_age = jiffies + bpdu->message_age; | ||
192 | 190 | ||
193 | mod_timer(&p->message_age_timer, jiffies | 191 | mod_timer(&p->message_age_timer, jiffies |
194 | + (p->br->max_age - bpdu->message_age)); | 192 | + (p->br->max_age - bpdu->message_age)); |
195 | } | 193 | } |
196 | 194 | ||
197 | /* called under bridge lock */ | 195 | /* called under bridge lock */ |
198 | static inline void br_record_config_timeout_values(struct net_bridge *br, | 196 | static void br_record_config_timeout_values(struct net_bridge *br, |
199 | const struct br_config_bpdu *bpdu) | 197 | const struct br_config_bpdu *bpdu) |
200 | { | 198 | { |
201 | br->max_age = bpdu->max_age; | 199 | br->max_age = bpdu->max_age; |
@@ -254,7 +252,8 @@ static void br_designated_port_selection(struct net_bridge *br) | |||
254 | } | 252 | } |
255 | 253 | ||
256 | /* called under bridge lock */ | 254 | /* called under bridge lock */ |
257 | static int br_supersedes_port_info(struct net_bridge_port *p, struct br_config_bpdu *bpdu) | 255 | static int br_supersedes_port_info(const struct net_bridge_port *p, |
256 | const struct br_config_bpdu *bpdu) | ||
258 | { | 257 | { |
259 | int t; | 258 | int t; |
260 | 259 | ||
@@ -285,7 +284,7 @@ static int br_supersedes_port_info(struct net_bridge_port *p, struct br_config_b | |||
285 | } | 284 | } |
286 | 285 | ||
287 | /* called under bridge lock */ | 286 | /* called under bridge lock */ |
288 | static inline void br_topology_change_acknowledged(struct net_bridge *br) | 287 | static void br_topology_change_acknowledged(struct net_bridge *br) |
289 | { | 288 | { |
290 | br->topology_change_detected = 0; | 289 | br->topology_change_detected = 0; |
291 | del_timer(&br->tcn_timer); | 290 | del_timer(&br->tcn_timer); |
@@ -327,7 +326,7 @@ void br_config_bpdu_generation(struct net_bridge *br) | |||
327 | } | 326 | } |
328 | 327 | ||
329 | /* called under bridge lock */ | 328 | /* called under bridge lock */ |
330 | static inline void br_reply(struct net_bridge_port *p) | 329 | static void br_reply(struct net_bridge_port *p) |
331 | { | 330 | { |
332 | br_transmit_config(p); | 331 | br_transmit_config(p); |
333 | } | 332 | } |
@@ -363,6 +362,8 @@ static void br_make_blocking(struct net_bridge_port *p) | |||
363 | 362 | ||
364 | p->state = BR_STATE_BLOCKING; | 363 | p->state = BR_STATE_BLOCKING; |
365 | br_log_state(p); | 364 | br_log_state(p); |
365 | br_ifinfo_notify(RTM_NEWLINK, p); | ||
366 | |||
366 | del_timer(&p->forward_delay_timer); | 367 | del_timer(&p->forward_delay_timer); |
367 | } | 368 | } |
368 | } | 369 | } |
@@ -379,15 +380,14 @@ static void br_make_forwarding(struct net_bridge_port *p) | |||
379 | p->state = BR_STATE_FORWARDING; | 380 | p->state = BR_STATE_FORWARDING; |
380 | br_topology_change_detection(br); | 381 | br_topology_change_detection(br); |
381 | del_timer(&p->forward_delay_timer); | 382 | del_timer(&p->forward_delay_timer); |
382 | } | 383 | } else if (br->stp_enabled == BR_KERNEL_STP) |
383 | else if (br->stp_enabled == BR_KERNEL_STP) | ||
384 | p->state = BR_STATE_LISTENING; | 384 | p->state = BR_STATE_LISTENING; |
385 | else | 385 | else |
386 | p->state = BR_STATE_LEARNING; | 386 | p->state = BR_STATE_LEARNING; |
387 | 387 | ||
388 | br_multicast_enable_port(p); | 388 | br_multicast_enable_port(p); |
389 | |||
390 | br_log_state(p); | 389 | br_log_state(p); |
390 | br_ifinfo_notify(RTM_NEWLINK, p); | ||
391 | 391 | ||
392 | if (br->forward_delay != 0) | 392 | if (br->forward_delay != 0) |
393 | mod_timer(&p->forward_delay_timer, jiffies + br->forward_delay); | 393 | mod_timer(&p->forward_delay_timer, jiffies + br->forward_delay); |
@@ -431,14 +431,15 @@ void br_port_state_selection(struct net_bridge *br) | |||
431 | } | 431 | } |
432 | 432 | ||
433 | /* called under bridge lock */ | 433 | /* called under bridge lock */ |
434 | static inline void br_topology_change_acknowledge(struct net_bridge_port *p) | 434 | static void br_topology_change_acknowledge(struct net_bridge_port *p) |
435 | { | 435 | { |
436 | p->topology_change_ack = 1; | 436 | p->topology_change_ack = 1; |
437 | br_transmit_config(p); | 437 | br_transmit_config(p); |
438 | } | 438 | } |
439 | 439 | ||
440 | /* called under bridge lock */ | 440 | /* called under bridge lock */ |
441 | void br_received_config_bpdu(struct net_bridge_port *p, struct br_config_bpdu *bpdu) | 441 | void br_received_config_bpdu(struct net_bridge_port *p, |
442 | const struct br_config_bpdu *bpdu) | ||
442 | { | 443 | { |
443 | struct net_bridge *br; | 444 | struct net_bridge *br; |
444 | int was_root; | 445 | int was_root; |
diff --git a/net/bridge/br_stp_bpdu.c b/net/bridge/br_stp_bpdu.c index 289646ec9b7..e16aade51ae 100644 --- a/net/bridge/br_stp_bpdu.c +++ b/net/bridge/br_stp_bpdu.c | |||
@@ -210,10 +210,19 @@ void br_stp_rcv(const struct stp_proto *proto, struct sk_buff *skb, | |||
210 | bpdu.hello_time = br_get_ticks(buf+28); | 210 | bpdu.hello_time = br_get_ticks(buf+28); |
211 | bpdu.forward_delay = br_get_ticks(buf+30); | 211 | bpdu.forward_delay = br_get_ticks(buf+30); |
212 | 212 | ||
213 | br_received_config_bpdu(p, &bpdu); | 213 | if (bpdu.message_age > bpdu.max_age) { |
214 | } | 214 | if (net_ratelimit()) |
215 | br_notice(p->br, | ||
216 | "port %u config from %pM" | ||
217 | " (message_age %ul > max_age %ul)\n", | ||
218 | p->port_no, | ||
219 | eth_hdr(skb)->h_source, | ||
220 | bpdu.message_age, bpdu.max_age); | ||
221 | goto out; | ||
222 | } | ||
215 | 223 | ||
216 | else if (buf[0] == BPDU_TYPE_TCN) { | 224 | br_received_config_bpdu(p, &bpdu); |
225 | } else if (buf[0] == BPDU_TYPE_TCN) { | ||
217 | br_received_tcn_bpdu(p); | 226 | br_received_tcn_bpdu(p); |
218 | } | 227 | } |
219 | out: | 228 | out: |
diff --git a/net/bridge/br_stp_if.c b/net/bridge/br_stp_if.c index 6f615b8192f..10eda3cd1d7 100644 --- a/net/bridge/br_stp_if.c +++ b/net/bridge/br_stp_if.c | |||
@@ -88,6 +88,7 @@ void br_stp_enable_port(struct net_bridge_port *p) | |||
88 | br_init_port(p); | 88 | br_init_port(p); |
89 | br_port_state_selection(p->br); | 89 | br_port_state_selection(p->br); |
90 | br_log_state(p); | 90 | br_log_state(p); |
91 | br_ifinfo_notify(RTM_NEWLINK, p); | ||
91 | } | 92 | } |
92 | 93 | ||
93 | /* called under bridge lock */ | 94 | /* called under bridge lock */ |
@@ -104,6 +105,8 @@ void br_stp_disable_port(struct net_bridge_port *p) | |||
104 | p->topology_change_ack = 0; | 105 | p->topology_change_ack = 0; |
105 | p->config_pending = 0; | 106 | p->config_pending = 0; |
106 | 107 | ||
108 | br_ifinfo_notify(RTM_NEWLINK, p); | ||
109 | |||
107 | del_timer(&p->message_age_timer); | 110 | del_timer(&p->message_age_timer); |
108 | del_timer(&p->forward_delay_timer); | 111 | del_timer(&p->forward_delay_timer); |
109 | del_timer(&p->hold_timer); | 112 | del_timer(&p->hold_timer); |
diff --git a/net/bridge/br_stp_timer.c b/net/bridge/br_stp_timer.c index 3e965140051..58de2a0f997 100644 --- a/net/bridge/br_stp_timer.c +++ b/net/bridge/br_stp_timer.c | |||
@@ -97,6 +97,7 @@ static void br_forward_delay_timer_expired(unsigned long arg) | |||
97 | netif_carrier_on(br->dev); | 97 | netif_carrier_on(br->dev); |
98 | } | 98 | } |
99 | br_log_state(p); | 99 | br_log_state(p); |
100 | br_ifinfo_notify(RTM_NEWLINK, p); | ||
100 | spin_unlock(&br->lock); | 101 | spin_unlock(&br->lock); |
101 | } | 102 | } |
102 | 103 | ||
diff --git a/net/bridge/netfilter/Kconfig b/net/bridge/netfilter/Kconfig index ba6f73eb06c..a9aff9c7d02 100644 --- a/net/bridge/netfilter/Kconfig +++ b/net/bridge/netfilter/Kconfig | |||
@@ -4,7 +4,7 @@ | |||
4 | 4 | ||
5 | menuconfig BRIDGE_NF_EBTABLES | 5 | menuconfig BRIDGE_NF_EBTABLES |
6 | tristate "Ethernet Bridge tables (ebtables) support" | 6 | tristate "Ethernet Bridge tables (ebtables) support" |
7 | depends on BRIDGE && BRIDGE_NETFILTER | 7 | depends on BRIDGE && NETFILTER |
8 | select NETFILTER_XTABLES | 8 | select NETFILTER_XTABLES |
9 | help | 9 | help |
10 | ebtables is a general, extensible frame/packet identification | 10 | ebtables is a general, extensible frame/packet identification |
diff --git a/net/bridge/netfilter/ebt_ulog.c b/net/bridge/netfilter/ebt_ulog.c index 26377e96fa1..bf2a333ca7c 100644 --- a/net/bridge/netfilter/ebt_ulog.c +++ b/net/bridge/netfilter/ebt_ulog.c | |||
@@ -216,7 +216,6 @@ unlock: | |||
216 | nlmsg_failure: | 216 | nlmsg_failure: |
217 | pr_debug("error during NLMSG_PUT. This should " | 217 | pr_debug("error during NLMSG_PUT. This should " |
218 | "not happen, please report to author.\n"); | 218 | "not happen, please report to author.\n"); |
219 | goto unlock; | ||
220 | alloc_failure: | 219 | alloc_failure: |
221 | goto unlock; | 220 | goto unlock; |
222 | } | 221 | } |
diff --git a/net/bridge/netfilter/ebtables.c b/net/bridge/netfilter/ebtables.c index 2b5ca1a0054..5864cc49136 100644 --- a/net/bridge/netfilter/ebtables.c +++ b/net/bridge/netfilter/ebtables.c | |||
@@ -1198,7 +1198,8 @@ ebt_register_table(struct net *net, const struct ebt_table *input_table) | |||
1198 | 1198 | ||
1199 | if (table->check && table->check(newinfo, table->valid_hooks)) { | 1199 | if (table->check && table->check(newinfo, table->valid_hooks)) { |
1200 | BUGPRINT("The table doesn't like its own initial data, lol\n"); | 1200 | BUGPRINT("The table doesn't like its own initial data, lol\n"); |
1201 | return ERR_PTR(-EINVAL); | 1201 | ret = -EINVAL; |
1202 | goto free_chainstack; | ||
1202 | } | 1203 | } |
1203 | 1204 | ||
1204 | table->private = newinfo; | 1205 | table->private = newinfo; |