aboutsummaryrefslogtreecommitdiffstats
path: root/net/bridge/br_if.c
diff options
context:
space:
mode:
Diffstat (limited to 'net/bridge/br_if.c')
-rw-r--r--net/bridge/br_if.c121
1 files changed, 79 insertions, 42 deletions
diff --git a/net/bridge/br_if.c b/net/bridge/br_if.c
index da687c8dc6ff..f36b35edd60c 100644
--- a/net/bridge/br_if.c
+++ b/net/bridge/br_if.c
@@ -79,37 +79,57 @@ static int port_cost(struct net_device *dev)
79 */ 79 */
80static void port_carrier_check(void *arg) 80static void port_carrier_check(void *arg)
81{ 81{
82 struct net_bridge_port *p = arg; 82 struct net_device *dev = arg;
83 struct net_bridge_port *p;
84 struct net_bridge *br;
83 85
84 rtnl_lock(); 86 rtnl_lock();
85 if (netif_carrier_ok(p->dev)) { 87 p = dev->br_port;
86 u32 cost = port_cost(p->dev); 88 if (!p)
89 goto done;
90 br = p->br;
87 91
88 spin_lock_bh(&p->br->lock); 92 if (netif_carrier_ok(dev))
89 if (p->state == BR_STATE_DISABLED) { 93 p->path_cost = port_cost(dev);
90 p->path_cost = cost; 94
91 br_stp_enable_port(p); 95 if (br->dev->flags & IFF_UP) {
96 spin_lock_bh(&br->lock);
97 if (netif_carrier_ok(dev)) {
98 if (p->state == BR_STATE_DISABLED)
99 br_stp_enable_port(p);
100 } else {
101 if (p->state != BR_STATE_DISABLED)
102 br_stp_disable_port(p);
92 } 103 }
93 spin_unlock_bh(&p->br->lock); 104 spin_unlock_bh(&br->lock);
94 } else {
95 spin_lock_bh(&p->br->lock);
96 if (p->state != BR_STATE_DISABLED)
97 br_stp_disable_port(p);
98 spin_unlock_bh(&p->br->lock);
99 } 105 }
106done:
100 rtnl_unlock(); 107 rtnl_unlock();
101} 108}
102 109
110static void release_nbp(struct kobject *kobj)
111{
112 struct net_bridge_port *p
113 = container_of(kobj, struct net_bridge_port, kobj);
114 kfree(p);
115}
116
117static struct kobj_type brport_ktype = {
118#ifdef CONFIG_SYSFS
119 .sysfs_ops = &brport_sysfs_ops,
120#endif
121 .release = release_nbp,
122};
123
103static void destroy_nbp(struct net_bridge_port *p) 124static void destroy_nbp(struct net_bridge_port *p)
104{ 125{
105 struct net_device *dev = p->dev; 126 struct net_device *dev = p->dev;
106 127
107 dev->br_port = NULL;
108 p->br = NULL; 128 p->br = NULL;
109 p->dev = NULL; 129 p->dev = NULL;
110 dev_put(dev); 130 dev_put(dev);
111 131
112 br_sysfs_freeif(p); 132 kobject_put(&p->kobj);
113} 133}
114 134
115static void destroy_nbp_rcu(struct rcu_head *head) 135static void destroy_nbp_rcu(struct rcu_head *head)
@@ -133,24 +153,25 @@ static void del_nbp(struct net_bridge_port *p)
133 struct net_bridge *br = p->br; 153 struct net_bridge *br = p->br;
134 struct net_device *dev = p->dev; 154 struct net_device *dev = p->dev;
135 155
136 /* Race between RTNL notify and RCU callback */ 156 sysfs_remove_link(&br->ifobj, dev->name);
137 if (p->deleted)
138 return;
139 157
140 dev_set_promiscuity(dev, -1); 158 dev_set_promiscuity(dev, -1);
141 159
142 cancel_delayed_work(&p->carrier_check); 160 cancel_delayed_work(&p->carrier_check);
143 flush_scheduled_work();
144 161
145 spin_lock_bh(&br->lock); 162 spin_lock_bh(&br->lock);
146 br_stp_disable_port(p); 163 br_stp_disable_port(p);
147 p->deleted = 1;
148 spin_unlock_bh(&br->lock); 164 spin_unlock_bh(&br->lock);
149 165
150 br_fdb_delete_by_port(br, p); 166 br_fdb_delete_by_port(br, p);
151 167
152 list_del_rcu(&p->list); 168 list_del_rcu(&p->list);
153 169
170 rcu_assign_pointer(dev->br_port, NULL);
171
172 kobject_uevent(&p->kobj, KOBJ_REMOVE);
173 kobject_del(&p->kobj);
174
154 call_rcu(&p->rcu, destroy_nbp_rcu); 175 call_rcu(&p->rcu, destroy_nbp_rcu);
155} 176}
156 177
@@ -160,7 +181,6 @@ static void del_br(struct net_bridge *br)
160 struct net_bridge_port *p, *n; 181 struct net_bridge_port *p, *n;
161 182
162 list_for_each_entry_safe(p, n, &br->port_list, list) { 183 list_for_each_entry_safe(p, n, &br->port_list, list) {
163 br_sysfs_removeif(p);
164 del_nbp(p); 184 del_nbp(p);
165 } 185 }
166 186
@@ -254,12 +274,17 @@ static struct net_bridge_port *new_nbp(struct net_bridge *br,
254 p->dev = dev; 274 p->dev = dev;
255 p->path_cost = port_cost(dev); 275 p->path_cost = port_cost(dev);
256 p->priority = 0x8000 >> BR_PORT_BITS; 276 p->priority = 0x8000 >> BR_PORT_BITS;
257 dev->br_port = p;
258 p->port_no = index; 277 p->port_no = index;
259 br_init_port(p); 278 br_init_port(p);
260 p->state = BR_STATE_DISABLED; 279 p->state = BR_STATE_DISABLED;
261 INIT_WORK(&p->carrier_check, port_carrier_check, p); 280 INIT_WORK(&p->carrier_check, port_carrier_check, dev);
281 br_stp_port_timer_init(p);
282
262 kobject_init(&p->kobj); 283 kobject_init(&p->kobj);
284 kobject_set_name(&p->kobj, SYSFS_BRIDGE_PORT_ATTR);
285 p->kobj.ktype = &brport_ktype;
286 p->kobj.parent = &(dev->class_dev.kobj);
287 p->kobj.kset = NULL;
263 288
264 return p; 289 return p;
265} 290}
@@ -388,30 +413,43 @@ int br_add_if(struct net_bridge *br, struct net_device *dev)
388 if (dev->br_port != NULL) 413 if (dev->br_port != NULL)
389 return -EBUSY; 414 return -EBUSY;
390 415
391 if (IS_ERR(p = new_nbp(br, dev))) 416 p = new_nbp(br, dev);
417 if (IS_ERR(p))
392 return PTR_ERR(p); 418 return PTR_ERR(p);
393 419
394 if ((err = br_fdb_insert(br, p, dev->dev_addr))) 420 err = kobject_add(&p->kobj);
395 destroy_nbp(p); 421 if (err)
396 422 goto err0;
397 else if ((err = br_sysfs_addif(p)))
398 del_nbp(p);
399 else {
400 dev_set_promiscuity(dev, 1);
401 423
402 list_add_rcu(&p->list, &br->port_list); 424 err = br_fdb_insert(br, p, dev->dev_addr);
425 if (err)
426 goto err1;
403 427
404 spin_lock_bh(&br->lock); 428 err = br_sysfs_addif(p);
405 br_stp_recalculate_bridge_id(br); 429 if (err)
406 br_features_recompute(br); 430 goto err2;
407 if ((br->dev->flags & IFF_UP)
408 && (dev->flags & IFF_UP) && netif_carrier_ok(dev))
409 br_stp_enable_port(p);
410 spin_unlock_bh(&br->lock);
411 431
412 dev_set_mtu(br->dev, br_min_mtu(br)); 432 rcu_assign_pointer(dev->br_port, p);
413 } 433 dev_set_promiscuity(dev, 1);
414 434
435 list_add_rcu(&p->list, &br->port_list);
436
437 spin_lock_bh(&br->lock);
438 br_stp_recalculate_bridge_id(br);
439 br_features_recompute(br);
440 schedule_delayed_work(&p->carrier_check, BR_PORT_DEBOUNCE);
441 spin_unlock_bh(&br->lock);
442
443 dev_set_mtu(br->dev, br_min_mtu(br));
444 kobject_uevent(&p->kobj, KOBJ_ADD);
445
446 return 0;
447err2:
448 br_fdb_delete_by_port(br, p);
449err1:
450 kobject_del(&p->kobj);
451err0:
452 kobject_put(&p->kobj);
415 return err; 453 return err;
416} 454}
417 455
@@ -423,7 +461,6 @@ int br_del_if(struct net_bridge *br, struct net_device *dev)
423 if (!p || p->br != br) 461 if (!p || p->br != br)
424 return -EINVAL; 462 return -EINVAL;
425 463
426 br_sysfs_removeif(p);
427 del_nbp(p); 464 del_nbp(p);
428 465
429 spin_lock_bh(&br->lock); 466 spin_lock_bh(&br->lock);