aboutsummaryrefslogtreecommitdiffstats
path: root/net/bridge/br_device.c
diff options
context:
space:
mode:
authorGlenn Elliott <gelliott@cs.unc.edu>2012-03-04 19:47:13 -0500
committerGlenn Elliott <gelliott@cs.unc.edu>2012-03-04 19:47:13 -0500
commitc71c03bda1e86c9d5198c5d83f712e695c4f2a1e (patch)
treeecb166cb3e2b7e2adb3b5e292245fefd23381ac8 /net/bridge/br_device.c
parentea53c912f8a86a8567697115b6a0d8152beee5c8 (diff)
parent6a00f206debf8a5c8899055726ad127dbeeed098 (diff)
Merge branch 'mpi-master' into wip-k-fmlpwip-k-fmlp
Conflicts: litmus/sched_cedf.c
Diffstat (limited to 'net/bridge/br_device.c')
-rw-r--r--net/bridge/br_device.c120
1 files changed, 73 insertions, 47 deletions
diff --git a/net/bridge/br_device.c b/net/bridge/br_device.c
index cf09fe591fc2..32b8f9f7f79e 100644
--- a/net/bridge/br_device.c
+++ b/net/bridge/br_device.c
@@ -49,7 +49,9 @@ netdev_tx_t br_dev_xmit(struct sk_buff *skb, struct net_device *dev)
49 skb_pull(skb, ETH_HLEN); 49 skb_pull(skb, ETH_HLEN);
50 50
51 rcu_read_lock(); 51 rcu_read_lock();
52 if (is_multicast_ether_addr(dest)) { 52 if (is_broadcast_ether_addr(dest))
53 br_flood_deliver(br, skb);
54 else if (is_multicast_ether_addr(dest)) {
53 if (unlikely(netpoll_tx_running(dev))) { 55 if (unlikely(netpoll_tx_running(dev))) {
54 br_flood_deliver(br, skb); 56 br_flood_deliver(br, skb);
55 goto out; 57 goto out;
@@ -74,11 +76,23 @@ out:
74 return NETDEV_TX_OK; 76 return NETDEV_TX_OK;
75} 77}
76 78
79static int br_dev_init(struct net_device *dev)
80{
81 struct net_bridge *br = netdev_priv(dev);
82
83 br->stats = alloc_percpu(struct br_cpu_netstats);
84 if (!br->stats)
85 return -ENOMEM;
86
87 return 0;
88}
89
77static int br_dev_open(struct net_device *dev) 90static int br_dev_open(struct net_device *dev)
78{ 91{
79 struct net_bridge *br = netdev_priv(dev); 92 struct net_bridge *br = netdev_priv(dev);
80 93
81 br_features_recompute(br); 94 netif_carrier_off(dev);
95 netdev_update_features(dev);
82 netif_start_queue(dev); 96 netif_start_queue(dev);
83 br_stp_enable_bridge(br); 97 br_stp_enable_bridge(br);
84 br_multicast_open(br); 98 br_multicast_open(br);
@@ -94,6 +108,8 @@ static int br_dev_stop(struct net_device *dev)
94{ 108{
95 struct net_bridge *br = netdev_priv(dev); 109 struct net_bridge *br = netdev_priv(dev);
96 110
111 netif_carrier_off(dev);
112
97 br_stp_disable_bridge(br); 113 br_stp_disable_bridge(br);
98 br_multicast_stop(br); 114 br_multicast_stop(br);
99 115
@@ -141,7 +157,7 @@ static int br_change_mtu(struct net_device *dev, int new_mtu)
141 157
142#ifdef CONFIG_BRIDGE_NETFILTER 158#ifdef CONFIG_BRIDGE_NETFILTER
143 /* remember the MTU in the rtable for PMTU */ 159 /* remember the MTU in the rtable for PMTU */
144 br->fake_rtable.dst.metrics[RTAX_MTU - 1] = new_mtu; 160 dst_metric_set(&br->fake_rtable.dst, RTAX_MTU, new_mtu);
145#endif 161#endif
146 162
147 return 0; 163 return 0;
@@ -173,43 +189,11 @@ static void br_getinfo(struct net_device *dev, struct ethtool_drvinfo *info)
173 strcpy(info->bus_info, "N/A"); 189 strcpy(info->bus_info, "N/A");
174} 190}
175 191
176static int br_set_sg(struct net_device *dev, u32 data) 192static u32 br_fix_features(struct net_device *dev, u32 features)
177{
178 struct net_bridge *br = netdev_priv(dev);
179
180 if (data)
181 br->feature_mask |= NETIF_F_SG;
182 else
183 br->feature_mask &= ~NETIF_F_SG;
184
185 br_features_recompute(br);
186 return 0;
187}
188
189static int br_set_tso(struct net_device *dev, u32 data)
190{ 193{
191 struct net_bridge *br = netdev_priv(dev); 194 struct net_bridge *br = netdev_priv(dev);
192 195
193 if (data) 196 return br_features_recompute(br, features);
194 br->feature_mask |= NETIF_F_TSO;
195 else
196 br->feature_mask &= ~NETIF_F_TSO;
197
198 br_features_recompute(br);
199 return 0;
200}
201
202static int br_set_tx_csum(struct net_device *dev, u32 data)
203{
204 struct net_bridge *br = netdev_priv(dev);
205
206 if (data)
207 br->feature_mask |= NETIF_F_NO_CSUM;
208 else
209 br->feature_mask &= ~NETIF_F_ALL_CSUM;
210
211 br_features_recompute(br);
212 return 0;
213} 197}
214 198
215#ifdef CONFIG_NET_POLL_CONTROLLER 199#ifdef CONFIG_NET_POLL_CONTROLLER
@@ -261,6 +245,7 @@ int br_netpoll_enable(struct net_bridge_port *p)
261 goto out; 245 goto out;
262 246
263 np->dev = p->dev; 247 np->dev = p->dev;
248 strlcpy(np->dev_name, p->dev->name, IFNAMSIZ);
264 249
265 err = __netpoll_setup(np); 250 err = __netpoll_setup(np);
266 if (err) { 251 if (err) {
@@ -292,23 +277,30 @@ void br_netpoll_disable(struct net_bridge_port *p)
292 277
293#endif 278#endif
294 279
280static int br_add_slave(struct net_device *dev, struct net_device *slave_dev)
281
282{
283 struct net_bridge *br = netdev_priv(dev);
284
285 return br_add_if(br, slave_dev);
286}
287
288static int br_del_slave(struct net_device *dev, struct net_device *slave_dev)
289{
290 struct net_bridge *br = netdev_priv(dev);
291
292 return br_del_if(br, slave_dev);
293}
294
295static const struct ethtool_ops br_ethtool_ops = { 295static const struct ethtool_ops br_ethtool_ops = {
296 .get_drvinfo = br_getinfo, 296 .get_drvinfo = br_getinfo,
297 .get_link = ethtool_op_get_link, 297 .get_link = ethtool_op_get_link,
298 .get_tx_csum = ethtool_op_get_tx_csum,
299 .set_tx_csum = br_set_tx_csum,
300 .get_sg = ethtool_op_get_sg,
301 .set_sg = br_set_sg,
302 .get_tso = ethtool_op_get_tso,
303 .set_tso = br_set_tso,
304 .get_ufo = ethtool_op_get_ufo,
305 .set_ufo = ethtool_op_set_ufo,
306 .get_flags = ethtool_op_get_flags,
307}; 298};
308 299
309static const struct net_device_ops br_netdev_ops = { 300static const struct net_device_ops br_netdev_ops = {
310 .ndo_open = br_dev_open, 301 .ndo_open = br_dev_open,
311 .ndo_stop = br_dev_stop, 302 .ndo_stop = br_dev_stop,
303 .ndo_init = br_dev_init,
312 .ndo_start_xmit = br_dev_xmit, 304 .ndo_start_xmit = br_dev_xmit,
313 .ndo_get_stats64 = br_get_stats64, 305 .ndo_get_stats64 = br_get_stats64,
314 .ndo_set_mac_address = br_set_mac_address, 306 .ndo_set_mac_address = br_set_mac_address,
@@ -320,6 +312,9 @@ static const struct net_device_ops br_netdev_ops = {
320 .ndo_netpoll_cleanup = br_netpoll_cleanup, 312 .ndo_netpoll_cleanup = br_netpoll_cleanup,
321 .ndo_poll_controller = br_poll_controller, 313 .ndo_poll_controller = br_poll_controller,
322#endif 314#endif
315 .ndo_add_slave = br_add_slave,
316 .ndo_del_slave = br_del_slave,
317 .ndo_fix_features = br_fix_features,
323}; 318};
324 319
325static void br_dev_free(struct net_device *dev) 320static void br_dev_free(struct net_device *dev)
@@ -330,18 +325,49 @@ static void br_dev_free(struct net_device *dev)
330 free_netdev(dev); 325 free_netdev(dev);
331} 326}
332 327
328static struct device_type br_type = {
329 .name = "bridge",
330};
331
333void br_dev_setup(struct net_device *dev) 332void br_dev_setup(struct net_device *dev)
334{ 333{
334 struct net_bridge *br = netdev_priv(dev);
335
335 random_ether_addr(dev->dev_addr); 336 random_ether_addr(dev->dev_addr);
336 ether_setup(dev); 337 ether_setup(dev);
337 338
338 dev->netdev_ops = &br_netdev_ops; 339 dev->netdev_ops = &br_netdev_ops;
339 dev->destructor = br_dev_free; 340 dev->destructor = br_dev_free;
340 SET_ETHTOOL_OPS(dev, &br_ethtool_ops); 341 SET_ETHTOOL_OPS(dev, &br_ethtool_ops);
342 SET_NETDEV_DEVTYPE(dev, &br_type);
341 dev->tx_queue_len = 0; 343 dev->tx_queue_len = 0;
342 dev->priv_flags = IFF_EBRIDGE; 344 dev->priv_flags = IFF_EBRIDGE;
343 345
344 dev->features = NETIF_F_SG | NETIF_F_FRAGLIST | NETIF_F_HIGHDMA | 346 dev->features = NETIF_F_SG | NETIF_F_FRAGLIST | NETIF_F_HIGHDMA |
345 NETIF_F_GSO_MASK | NETIF_F_NO_CSUM | NETIF_F_LLTX | 347 NETIF_F_GSO_MASK | NETIF_F_NO_CSUM | NETIF_F_LLTX |
346 NETIF_F_NETNS_LOCAL | NETIF_F_GSO; 348 NETIF_F_NETNS_LOCAL | NETIF_F_HW_VLAN_TX;
349 dev->hw_features = NETIF_F_SG | NETIF_F_FRAGLIST | NETIF_F_HIGHDMA |
350 NETIF_F_GSO_MASK | NETIF_F_NO_CSUM |
351 NETIF_F_HW_VLAN_TX;
352
353 br->dev = dev;
354 spin_lock_init(&br->lock);
355 INIT_LIST_HEAD(&br->port_list);
356 spin_lock_init(&br->hash_lock);
357
358 br->bridge_id.prio[0] = 0x80;
359 br->bridge_id.prio[1] = 0x00;
360
361 memcpy(br->group_addr, br_group_address, ETH_ALEN);
362
363 br->stp_enabled = BR_NO_STP;
364 br->designated_root = br->bridge_id;
365 br->bridge_max_age = br->max_age = 20 * HZ;
366 br->bridge_hello_time = br->hello_time = 2 * HZ;
367 br->bridge_forward_delay = br->forward_delay = 15 * HZ;
368 br->ageing_time = 300 * HZ;
369
370 br_netfilter_rtable_init(br);
371 br_stp_timer_init(br);
372 br_multicast_init(br);
347} 373}