diff options
Diffstat (limited to 'net/bridge/br_if.c')
-rw-r--r-- | net/bridge/br_if.c | 104 |
1 files changed, 16 insertions, 88 deletions
diff --git a/net/bridge/br_if.c b/net/bridge/br_if.c index 718b60366dfe..5dbdfdfc3a34 100644 --- a/net/bridge/br_if.c +++ b/net/bridge/br_if.c | |||
@@ -36,8 +36,8 @@ static int port_cost(struct net_device *dev) | |||
36 | if (dev->ethtool_ops && dev->ethtool_ops->get_settings) { | 36 | if (dev->ethtool_ops && dev->ethtool_ops->get_settings) { |
37 | struct ethtool_cmd ecmd = { .cmd = ETHTOOL_GSET, }; | 37 | struct ethtool_cmd ecmd = { .cmd = ETHTOOL_GSET, }; |
38 | 38 | ||
39 | if (!dev->ethtool_ops->get_settings(dev, &ecmd)) { | 39 | if (!dev_ethtool_get_settings(dev, &ecmd)) { |
40 | switch(ecmd.speed) { | 40 | switch (ethtool_cmd_speed(&ecmd)) { |
41 | case SPEED_10000: | 41 | case SPEED_10000: |
42 | return 2; | 42 | return 2; |
43 | case SPEED_1000: | 43 | case SPEED_1000: |
@@ -175,56 +175,6 @@ static void del_br(struct net_bridge *br, struct list_head *head) | |||
175 | unregister_netdevice_queue(br->dev, head); | 175 | unregister_netdevice_queue(br->dev, head); |
176 | } | 176 | } |
177 | 177 | ||
178 | static struct net_device *new_bridge_dev(struct net *net, const char *name) | ||
179 | { | ||
180 | struct net_bridge *br; | ||
181 | struct net_device *dev; | ||
182 | |||
183 | dev = alloc_netdev(sizeof(struct net_bridge), name, | ||
184 | br_dev_setup); | ||
185 | |||
186 | if (!dev) | ||
187 | return NULL; | ||
188 | dev_net_set(dev, net); | ||
189 | |||
190 | br = netdev_priv(dev); | ||
191 | br->dev = dev; | ||
192 | |||
193 | br->stats = alloc_percpu(struct br_cpu_netstats); | ||
194 | if (!br->stats) { | ||
195 | free_netdev(dev); | ||
196 | return NULL; | ||
197 | } | ||
198 | |||
199 | spin_lock_init(&br->lock); | ||
200 | INIT_LIST_HEAD(&br->port_list); | ||
201 | spin_lock_init(&br->hash_lock); | ||
202 | |||
203 | br->bridge_id.prio[0] = 0x80; | ||
204 | br->bridge_id.prio[1] = 0x00; | ||
205 | |||
206 | memcpy(br->group_addr, br_group_address, ETH_ALEN); | ||
207 | |||
208 | br->feature_mask = dev->features; | ||
209 | br->stp_enabled = BR_NO_STP; | ||
210 | br->designated_root = br->bridge_id; | ||
211 | br->root_path_cost = 0; | ||
212 | br->root_port = 0; | ||
213 | br->bridge_max_age = br->max_age = 20 * HZ; | ||
214 | br->bridge_hello_time = br->hello_time = 2 * HZ; | ||
215 | br->bridge_forward_delay = br->forward_delay = 15 * HZ; | ||
216 | br->topology_change = 0; | ||
217 | br->topology_change_detected = 0; | ||
218 | br->ageing_time = 300 * HZ; | ||
219 | |||
220 | br_netfilter_rtable_init(br); | ||
221 | |||
222 | br_stp_timer_init(br); | ||
223 | br_multicast_init(br); | ||
224 | |||
225 | return dev; | ||
226 | } | ||
227 | |||
228 | /* find an available port number */ | 178 | /* find an available port number */ |
229 | static int find_portno(struct net_bridge *br) | 179 | static int find_portno(struct net_bridge *br) |
230 | { | 180 | { |
@@ -277,42 +227,19 @@ static struct net_bridge_port *new_nbp(struct net_bridge *br, | |||
277 | return p; | 227 | return p; |
278 | } | 228 | } |
279 | 229 | ||
280 | static struct device_type br_type = { | ||
281 | .name = "bridge", | ||
282 | }; | ||
283 | |||
284 | int br_add_bridge(struct net *net, const char *name) | 230 | int br_add_bridge(struct net *net, const char *name) |
285 | { | 231 | { |
286 | struct net_device *dev; | 232 | struct net_device *dev; |
287 | int ret; | ||
288 | 233 | ||
289 | dev = new_bridge_dev(net, name); | 234 | dev = alloc_netdev(sizeof(struct net_bridge), name, |
235 | br_dev_setup); | ||
236 | |||
290 | if (!dev) | 237 | if (!dev) |
291 | return -ENOMEM; | 238 | return -ENOMEM; |
292 | 239 | ||
293 | rtnl_lock(); | 240 | dev_net_set(dev, net); |
294 | if (strchr(dev->name, '%')) { | ||
295 | ret = dev_alloc_name(dev, dev->name); | ||
296 | if (ret < 0) | ||
297 | goto out_free; | ||
298 | } | ||
299 | |||
300 | SET_NETDEV_DEVTYPE(dev, &br_type); | ||
301 | |||
302 | ret = register_netdevice(dev); | ||
303 | if (ret) | ||
304 | goto out_free; | ||
305 | |||
306 | ret = br_sysfs_addbr(dev); | ||
307 | if (ret) | ||
308 | unregister_netdevice(dev); | ||
309 | out: | ||
310 | rtnl_unlock(); | ||
311 | return ret; | ||
312 | 241 | ||
313 | out_free: | 242 | return register_netdev(dev); |
314 | free_netdev(dev); | ||
315 | goto out; | ||
316 | } | 243 | } |
317 | 244 | ||
318 | int br_del_bridge(struct net *net, const char *name) | 245 | int br_del_bridge(struct net *net, const char *name) |
@@ -364,15 +291,15 @@ int br_min_mtu(const struct net_bridge *br) | |||
364 | /* | 291 | /* |
365 | * Recomputes features using slave's features | 292 | * Recomputes features using slave's features |
366 | */ | 293 | */ |
367 | void br_features_recompute(struct net_bridge *br) | 294 | u32 br_features_recompute(struct net_bridge *br, u32 features) |
368 | { | 295 | { |
369 | struct net_bridge_port *p; | 296 | struct net_bridge_port *p; |
370 | u32 features, mask; | 297 | u32 mask; |
371 | 298 | ||
372 | features = mask = br->feature_mask; | ||
373 | if (list_empty(&br->port_list)) | 299 | if (list_empty(&br->port_list)) |
374 | goto done; | 300 | return features; |
375 | 301 | ||
302 | mask = features; | ||
376 | features &= ~NETIF_F_ONE_FOR_ALL; | 303 | features &= ~NETIF_F_ONE_FOR_ALL; |
377 | 304 | ||
378 | list_for_each_entry(p, &br->port_list, list) { | 305 | list_for_each_entry(p, &br->port_list, list) { |
@@ -380,8 +307,7 @@ void br_features_recompute(struct net_bridge *br) | |||
380 | p->dev->features, mask); | 307 | p->dev->features, mask); |
381 | } | 308 | } |
382 | 309 | ||
383 | done: | 310 | return features; |
384 | br->dev->features = netdev_fix_features(br->dev, features); | ||
385 | } | 311 | } |
386 | 312 | ||
387 | /* called with RTNL */ | 313 | /* called with RTNL */ |
@@ -446,9 +372,10 @@ int br_add_if(struct net_bridge *br, struct net_device *dev) | |||
446 | 372 | ||
447 | list_add_rcu(&p->list, &br->port_list); | 373 | list_add_rcu(&p->list, &br->port_list); |
448 | 374 | ||
375 | netdev_update_features(br->dev); | ||
376 | |||
449 | spin_lock_bh(&br->lock); | 377 | spin_lock_bh(&br->lock); |
450 | changed_addr = br_stp_recalculate_bridge_id(br); | 378 | changed_addr = br_stp_recalculate_bridge_id(br); |
451 | br_features_recompute(br); | ||
452 | 379 | ||
453 | if ((dev->flags & IFF_UP) && netif_carrier_ok(dev) && | 380 | if ((dev->flags & IFF_UP) && netif_carrier_ok(dev) && |
454 | (br->dev->flags & IFF_UP)) | 381 | (br->dev->flags & IFF_UP)) |
@@ -496,9 +423,10 @@ int br_del_if(struct net_bridge *br, struct net_device *dev) | |||
496 | 423 | ||
497 | spin_lock_bh(&br->lock); | 424 | spin_lock_bh(&br->lock); |
498 | br_stp_recalculate_bridge_id(br); | 425 | br_stp_recalculate_bridge_id(br); |
499 | br_features_recompute(br); | ||
500 | spin_unlock_bh(&br->lock); | 426 | spin_unlock_bh(&br->lock); |
501 | 427 | ||
428 | netdev_update_features(br->dev); | ||
429 | |||
502 | return 0; | 430 | return 0; |
503 | } | 431 | } |
504 | 432 | ||