aboutsummaryrefslogtreecommitdiffstats
path: root/net/bridge
diff options
context:
space:
mode:
Diffstat (limited to 'net/bridge')
-rw-r--r--net/bridge/br_netlink.c4
-rw-r--r--net/bridge/br_private.h8
-rw-r--r--net/bridge/br_stp.c23
-rw-r--r--net/bridge/br_stp_if.c12
4 files changed, 31 insertions, 16 deletions
diff --git a/net/bridge/br_netlink.c b/net/bridge/br_netlink.c
index b9259efa636e..e74ddc1c29a8 100644
--- a/net/bridge/br_netlink.c
+++ b/net/bridge/br_netlink.c
@@ -207,7 +207,7 @@ int br_getlink(struct sk_buff *skb, u32 pid, u32 seq,
207 struct net_device *dev, u32 filter_mask) 207 struct net_device *dev, u32 filter_mask)
208{ 208{
209 int err = 0; 209 int err = 0;
210 struct net_bridge_port *port = br_port_get_rcu(dev); 210 struct net_bridge_port *port = br_port_get_rtnl(dev);
211 211
212 /* not a bridge port and */ 212 /* not a bridge port and */
213 if (!port && !(filter_mask & RTEXT_FILTER_BRVLAN)) 213 if (!port && !(filter_mask & RTEXT_FILTER_BRVLAN))
@@ -451,7 +451,7 @@ static size_t br_get_link_af_size(const struct net_device *dev)
451 struct net_port_vlans *pv; 451 struct net_port_vlans *pv;
452 452
453 if (br_port_exists(dev)) 453 if (br_port_exists(dev))
454 pv = nbp_get_vlan_info(br_port_get_rcu(dev)); 454 pv = nbp_get_vlan_info(br_port_get_rtnl(dev));
455 else if (dev->priv_flags & IFF_EBRIDGE) 455 else if (dev->priv_flags & IFF_EBRIDGE)
456 pv = br_get_vlan_info((struct net_bridge *)netdev_priv(dev)); 456 pv = br_get_vlan_info((struct net_bridge *)netdev_priv(dev));
457 else 457 else
diff --git a/net/bridge/br_private.h b/net/bridge/br_private.h
index 598cb0b333c6..efb57d911569 100644
--- a/net/bridge/br_private.h
+++ b/net/bridge/br_private.h
@@ -202,13 +202,10 @@ struct net_bridge_port
202 202
203static inline struct net_bridge_port *br_port_get_rcu(const struct net_device *dev) 203static inline struct net_bridge_port *br_port_get_rcu(const struct net_device *dev)
204{ 204{
205 struct net_bridge_port *port = 205 return rcu_dereference(dev->rx_handler_data);
206 rcu_dereference_rtnl(dev->rx_handler_data);
207
208 return br_port_exists(dev) ? port : NULL;
209} 206}
210 207
211static inline struct net_bridge_port *br_port_get_rtnl(struct net_device *dev) 208static inline struct net_bridge_port *br_port_get_rtnl(const struct net_device *dev)
212{ 209{
213 return br_port_exists(dev) ? 210 return br_port_exists(dev) ?
214 rtnl_dereference(dev->rx_handler_data) : NULL; 211 rtnl_dereference(dev->rx_handler_data) : NULL;
@@ -746,6 +743,7 @@ extern struct net_bridge_port *br_get_port(struct net_bridge *br,
746extern void br_init_port(struct net_bridge_port *p); 743extern void br_init_port(struct net_bridge_port *p);
747extern void br_become_designated_port(struct net_bridge_port *p); 744extern void br_become_designated_port(struct net_bridge_port *p);
748 745
746extern void __br_set_forward_delay(struct net_bridge *br, unsigned long t);
749extern int br_set_forward_delay(struct net_bridge *br, unsigned long x); 747extern int br_set_forward_delay(struct net_bridge *br, unsigned long x);
750extern int br_set_hello_time(struct net_bridge *br, unsigned long x); 748extern int br_set_hello_time(struct net_bridge *br, unsigned long x);
751extern int br_set_max_age(struct net_bridge *br, unsigned long x); 749extern int br_set_max_age(struct net_bridge *br, unsigned long x);
diff --git a/net/bridge/br_stp.c b/net/bridge/br_stp.c
index 1c0a50f13229..3c86f0538cbb 100644
--- a/net/bridge/br_stp.c
+++ b/net/bridge/br_stp.c
@@ -209,7 +209,7 @@ static void br_record_config_information(struct net_bridge_port *p,
209 p->designated_age = jiffies - bpdu->message_age; 209 p->designated_age = jiffies - bpdu->message_age;
210 210
211 mod_timer(&p->message_age_timer, jiffies 211 mod_timer(&p->message_age_timer, jiffies
212 + (p->br->max_age - bpdu->message_age)); 212 + (bpdu->max_age - bpdu->message_age));
213} 213}
214 214
215/* called under bridge lock */ 215/* called under bridge lock */
@@ -544,18 +544,27 @@ int br_set_max_age(struct net_bridge *br, unsigned long val)
544 544
545} 545}
546 546
547void __br_set_forward_delay(struct net_bridge *br, unsigned long t)
548{
549 br->bridge_forward_delay = t;
550 if (br_is_root_bridge(br))
551 br->forward_delay = br->bridge_forward_delay;
552}
553
547int br_set_forward_delay(struct net_bridge *br, unsigned long val) 554int br_set_forward_delay(struct net_bridge *br, unsigned long val)
548{ 555{
549 unsigned long t = clock_t_to_jiffies(val); 556 unsigned long t = clock_t_to_jiffies(val);
557 int err = -ERANGE;
550 558
559 spin_lock_bh(&br->lock);
551 if (br->stp_enabled != BR_NO_STP && 560 if (br->stp_enabled != BR_NO_STP &&
552 (t < BR_MIN_FORWARD_DELAY || t > BR_MAX_FORWARD_DELAY)) 561 (t < BR_MIN_FORWARD_DELAY || t > BR_MAX_FORWARD_DELAY))
553 return -ERANGE; 562 goto unlock;
554 563
555 spin_lock_bh(&br->lock); 564 __br_set_forward_delay(br, t);
556 br->bridge_forward_delay = t; 565 err = 0;
557 if (br_is_root_bridge(br)) 566
558 br->forward_delay = br->bridge_forward_delay; 567unlock:
559 spin_unlock_bh(&br->lock); 568 spin_unlock_bh(&br->lock);
560 return 0; 569 return err;
561} 570}
diff --git a/net/bridge/br_stp_if.c b/net/bridge/br_stp_if.c
index d45e760141bb..108084a04671 100644
--- a/net/bridge/br_stp_if.c
+++ b/net/bridge/br_stp_if.c
@@ -129,6 +129,14 @@ static void br_stp_start(struct net_bridge *br)
129 char *envp[] = { NULL }; 129 char *envp[] = { NULL };
130 130
131 r = call_usermodehelper(BR_STP_PROG, argv, envp, UMH_WAIT_PROC); 131 r = call_usermodehelper(BR_STP_PROG, argv, envp, UMH_WAIT_PROC);
132
133 spin_lock_bh(&br->lock);
134
135 if (br->bridge_forward_delay < BR_MIN_FORWARD_DELAY)
136 __br_set_forward_delay(br, BR_MIN_FORWARD_DELAY);
137 else if (br->bridge_forward_delay < BR_MAX_FORWARD_DELAY)
138 __br_set_forward_delay(br, BR_MAX_FORWARD_DELAY);
139
132 if (r == 0) { 140 if (r == 0) {
133 br->stp_enabled = BR_USER_STP; 141 br->stp_enabled = BR_USER_STP;
134 br_debug(br, "userspace STP started\n"); 142 br_debug(br, "userspace STP started\n");
@@ -137,10 +145,10 @@ static void br_stp_start(struct net_bridge *br)
137 br_debug(br, "using kernel STP\n"); 145 br_debug(br, "using kernel STP\n");
138 146
139 /* To start timers on any ports left in blocking */ 147 /* To start timers on any ports left in blocking */
140 spin_lock_bh(&br->lock);
141 br_port_state_selection(br); 148 br_port_state_selection(br);
142 spin_unlock_bh(&br->lock);
143 } 149 }
150
151 spin_unlock_bh(&br->lock);
144} 152}
145 153
146static void br_stp_stop(struct net_bridge *br) 154static void br_stp_stop(struct net_bridge *br)