Root/
1 | /* |
2 | * Device handling code |
3 | * Linux ethernet bridge |
4 | * |
5 | * Authors: |
6 | * Lennert Buytenhek <buytenh@gnu.org> |
7 | * |
8 | * This program is free software; you can redistribute it and/or |
9 | * modify it under the terms of the GNU General Public License |
10 | * as published by the Free Software Foundation; either version |
11 | * 2 of the License, or (at your option) any later version. |
12 | */ |
13 | |
14 | #include <linux/kernel.h> |
15 | #include <linux/netdevice.h> |
16 | #include <linux/netpoll.h> |
17 | #include <linux/etherdevice.h> |
18 | #include <linux/ethtool.h> |
19 | #include <linux/list.h> |
20 | #include <linux/netfilter_bridge.h> |
21 | |
22 | #include <asm/uaccess.h> |
23 | #include "br_private.h" |
24 | |
25 | /* net device transmit always called with BH disabled */ |
26 | netdev_tx_t br_dev_xmit(struct sk_buff *skb, struct net_device *dev) |
27 | { |
28 | struct net_bridge *br = netdev_priv(dev); |
29 | const unsigned char *dest = skb->data; |
30 | struct net_bridge_fdb_entry *dst; |
31 | struct net_bridge_mdb_entry *mdst; |
32 | struct br_cpu_netstats *brstats = this_cpu_ptr(br->stats); |
33 | |
34 | #ifdef CONFIG_BRIDGE_NETFILTER |
35 | if (skb->nf_bridge && (skb->nf_bridge->mask & BRNF_BRIDGED_DNAT)) { |
36 | br_nf_pre_routing_finish_bridge_slow(skb); |
37 | return NETDEV_TX_OK; |
38 | } |
39 | #endif |
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; |
47 | |
48 | skb_reset_mac_header(skb); |
49 | skb_pull(skb, ETH_HLEN); |
50 | |
51 | rcu_read_lock(); |
52 | if (is_multicast_ether_addr(dest)) { |
53 | if (unlikely(netpoll_tx_running(dev))) { |
54 | br_flood_deliver(br, skb); |
55 | goto out; |
56 | } |
57 | if (br_multicast_rcv(br, NULL, skb)) { |
58 | kfree_skb(skb); |
59 | goto out; |
60 | } |
61 | |
62 | mdst = br_mdb_get(br, skb); |
63 | if (mdst || BR_INPUT_SKB_CB_MROUTERS_ONLY(skb)) |
64 | br_multicast_deliver(mdst, skb); |
65 | else |
66 | br_flood_deliver(br, skb); |
67 | } else if ((dst = __br_fdb_get(br, dest)) != NULL) |
68 | br_deliver(dst->dst, skb); |
69 | else |
70 | br_flood_deliver(br, skb); |
71 | |
72 | out: |
73 | rcu_read_unlock(); |
74 | return NETDEV_TX_OK; |
75 | } |
76 | |
77 | static int br_dev_open(struct net_device *dev) |
78 | { |
79 | struct net_bridge *br = netdev_priv(dev); |
80 | |
81 | netif_carrier_off(dev); |
82 | |
83 | br_features_recompute(br); |
84 | netif_start_queue(dev); |
85 | br_stp_enable_bridge(br); |
86 | br_multicast_open(br); |
87 | |
88 | return 0; |
89 | } |
90 | |
91 | static void br_dev_set_multicast_list(struct net_device *dev) |
92 | { |
93 | } |
94 | |
95 | static int br_dev_stop(struct net_device *dev) |
96 | { |
97 | struct net_bridge *br = netdev_priv(dev); |
98 | |
99 | netif_carrier_off(dev); |
100 | |
101 | br_stp_disable_bridge(br); |
102 | br_multicast_stop(br); |
103 | |
104 | netif_stop_queue(dev); |
105 | |
106 | return 0; |
107 | } |
108 | |
109 | static struct rtnl_link_stats64 *br_get_stats64(struct net_device *dev, |
110 | struct rtnl_link_stats64 *stats) |
111 | { |
112 | struct net_bridge *br = netdev_priv(dev); |
113 | struct br_cpu_netstats tmp, sum = { 0 }; |
114 | unsigned int cpu; |
115 | |
116 | for_each_possible_cpu(cpu) { |
117 | unsigned int start; |
118 | const struct br_cpu_netstats *bstats |
119 | = per_cpu_ptr(br->stats, cpu); |
120 | do { |
121 | start = u64_stats_fetch_begin(&bstats->syncp); |
122 | memcpy(&tmp, bstats, sizeof(tmp)); |
123 | } while (u64_stats_fetch_retry(&bstats->syncp, start)); |
124 | sum.tx_bytes += tmp.tx_bytes; |
125 | sum.tx_packets += tmp.tx_packets; |
126 | sum.rx_bytes += tmp.rx_bytes; |
127 | sum.rx_packets += tmp.rx_packets; |
128 | } |
129 | |
130 | stats->tx_bytes = sum.tx_bytes; |
131 | stats->tx_packets = sum.tx_packets; |
132 | stats->rx_bytes = sum.rx_bytes; |
133 | stats->rx_packets = sum.rx_packets; |
134 | |
135 | return stats; |
136 | } |
137 | |
138 | static int br_change_mtu(struct net_device *dev, int new_mtu) |
139 | { |
140 | struct net_bridge *br = netdev_priv(dev); |
141 | if (new_mtu < 68 || new_mtu > br_min_mtu(br)) |
142 | return -EINVAL; |
143 | |
144 | dev->mtu = new_mtu; |
145 | |
146 | #ifdef CONFIG_BRIDGE_NETFILTER |
147 | /* remember the MTU in the rtable for PMTU */ |
148 | dst_metric_set(&br->fake_rtable.dst, RTAX_MTU, new_mtu); |
149 | #endif |
150 | |
151 | return 0; |
152 | } |
153 | |
154 | /* Allow setting mac address to any valid ethernet address. */ |
155 | static int br_set_mac_address(struct net_device *dev, void *p) |
156 | { |
157 | struct net_bridge *br = netdev_priv(dev); |
158 | struct sockaddr *addr = p; |
159 | |
160 | if (!is_valid_ether_addr(addr->sa_data)) |
161 | return -EINVAL; |
162 | |
163 | spin_lock_bh(&br->lock); |
164 | memcpy(dev->dev_addr, addr->sa_data, ETH_ALEN); |
165 | br_stp_change_bridge_id(br, addr->sa_data); |
166 | br->flags |= BR_SET_MAC_ADDR; |
167 | spin_unlock_bh(&br->lock); |
168 | |
169 | return 0; |
170 | } |
171 | |
172 | static void br_getinfo(struct net_device *dev, struct ethtool_drvinfo *info) |
173 | { |
174 | strcpy(info->driver, "bridge"); |
175 | strcpy(info->version, BR_VERSION); |
176 | strcpy(info->fw_version, "N/A"); |
177 | strcpy(info->bus_info, "N/A"); |
178 | } |
179 | |
180 | static int br_set_sg(struct net_device *dev, u32 data) |
181 | { |
182 | struct net_bridge *br = netdev_priv(dev); |
183 | |
184 | if (data) |
185 | br->feature_mask |= NETIF_F_SG; |
186 | else |
187 | br->feature_mask &= ~NETIF_F_SG; |
188 | |
189 | br_features_recompute(br); |
190 | return 0; |
191 | } |
192 | |
193 | static int br_set_tso(struct net_device *dev, u32 data) |
194 | { |
195 | struct net_bridge *br = netdev_priv(dev); |
196 | |
197 | if (data) |
198 | br->feature_mask |= NETIF_F_TSO; |
199 | else |
200 | br->feature_mask &= ~NETIF_F_TSO; |
201 | |
202 | br_features_recompute(br); |
203 | return 0; |
204 | } |
205 | |
206 | static int br_set_tx_csum(struct net_device *dev, u32 data) |
207 | { |
208 | struct net_bridge *br = netdev_priv(dev); |
209 | |
210 | if (data) |
211 | br->feature_mask |= NETIF_F_NO_CSUM; |
212 | else |
213 | br->feature_mask &= ~NETIF_F_ALL_CSUM; |
214 | |
215 | br_features_recompute(br); |
216 | return 0; |
217 | } |
218 | |
219 | static int br_set_flags(struct net_device *netdev, u32 data) |
220 | { |
221 | return ethtool_op_set_flags(netdev, data, ETH_FLAG_TXVLAN); |
222 | } |
223 | |
224 | #ifdef CONFIG_NET_POLL_CONTROLLER |
225 | static void br_poll_controller(struct net_device *br_dev) |
226 | { |
227 | } |
228 | |
229 | static void br_netpoll_cleanup(struct net_device *dev) |
230 | { |
231 | struct net_bridge *br = netdev_priv(dev); |
232 | struct net_bridge_port *p, *n; |
233 | |
234 | list_for_each_entry_safe(p, n, &br->port_list, list) { |
235 | br_netpoll_disable(p); |
236 | } |
237 | } |
238 | |
239 | static int br_netpoll_setup(struct net_device *dev, struct netpoll_info *ni) |
240 | { |
241 | struct net_bridge *br = netdev_priv(dev); |
242 | struct net_bridge_port *p, *n; |
243 | int err = 0; |
244 | |
245 | list_for_each_entry_safe(p, n, &br->port_list, list) { |
246 | if (!p->dev) |
247 | continue; |
248 | |
249 | err = br_netpoll_enable(p); |
250 | if (err) |
251 | goto fail; |
252 | } |
253 | |
254 | out: |
255 | return err; |
256 | |
257 | fail: |
258 | br_netpoll_cleanup(dev); |
259 | goto out; |
260 | } |
261 | |
262 | int br_netpoll_enable(struct net_bridge_port *p) |
263 | { |
264 | struct netpoll *np; |
265 | int err = 0; |
266 | |
267 | np = kzalloc(sizeof(*p->np), GFP_KERNEL); |
268 | err = -ENOMEM; |
269 | if (!np) |
270 | goto out; |
271 | |
272 | np->dev = p->dev; |
273 | |
274 | err = __netpoll_setup(np); |
275 | if (err) { |
276 | kfree(np); |
277 | goto out; |
278 | } |
279 | |
280 | p->np = np; |
281 | |
282 | out: |
283 | return err; |
284 | } |
285 | |
286 | void br_netpoll_disable(struct net_bridge_port *p) |
287 | { |
288 | struct netpoll *np = p->np; |
289 | |
290 | if (!np) |
291 | return; |
292 | |
293 | p->np = NULL; |
294 | |
295 | /* Wait for transmitting packets to finish before freeing. */ |
296 | synchronize_rcu_bh(); |
297 | |
298 | __netpoll_cleanup(np); |
299 | kfree(np); |
300 | } |
301 | |
302 | #endif |
303 | |
304 | static int br_add_slave(struct net_device *dev, struct net_device *slave_dev) |
305 | |
306 | { |
307 | struct net_bridge *br = netdev_priv(dev); |
308 | |
309 | return br_add_if(br, slave_dev); |
310 | } |
311 | |
312 | static int br_del_slave(struct net_device *dev, struct net_device *slave_dev) |
313 | { |
314 | struct net_bridge *br = netdev_priv(dev); |
315 | |
316 | return br_del_if(br, slave_dev); |
317 | } |
318 | |
319 | static const struct ethtool_ops br_ethtool_ops = { |
320 | .get_drvinfo = br_getinfo, |
321 | .get_link = ethtool_op_get_link, |
322 | .get_tx_csum = ethtool_op_get_tx_csum, |
323 | .set_tx_csum = br_set_tx_csum, |
324 | .get_sg = ethtool_op_get_sg, |
325 | .set_sg = br_set_sg, |
326 | .get_tso = ethtool_op_get_tso, |
327 | .set_tso = br_set_tso, |
328 | .get_ufo = ethtool_op_get_ufo, |
329 | .set_ufo = ethtool_op_set_ufo, |
330 | .get_flags = ethtool_op_get_flags, |
331 | .set_flags = br_set_flags, |
332 | }; |
333 | |
334 | static const struct net_device_ops br_netdev_ops = { |
335 | .ndo_open = br_dev_open, |
336 | .ndo_stop = br_dev_stop, |
337 | .ndo_start_xmit = br_dev_xmit, |
338 | .ndo_get_stats64 = br_get_stats64, |
339 | .ndo_set_mac_address = br_set_mac_address, |
340 | .ndo_set_multicast_list = br_dev_set_multicast_list, |
341 | .ndo_change_mtu = br_change_mtu, |
342 | .ndo_do_ioctl = br_dev_ioctl, |
343 | #ifdef CONFIG_NET_POLL_CONTROLLER |
344 | .ndo_netpoll_setup = br_netpoll_setup, |
345 | .ndo_netpoll_cleanup = br_netpoll_cleanup, |
346 | .ndo_poll_controller = br_poll_controller, |
347 | #endif |
348 | .ndo_add_slave = br_add_slave, |
349 | .ndo_del_slave = br_del_slave, |
350 | }; |
351 | |
352 | static void br_dev_free(struct net_device *dev) |
353 | { |
354 | struct net_bridge *br = netdev_priv(dev); |
355 | |
356 | free_percpu(br->stats); |
357 | free_netdev(dev); |
358 | } |
359 | |
360 | void br_dev_setup(struct net_device *dev) |
361 | { |
362 | random_ether_addr(dev->dev_addr); |
363 | ether_setup(dev); |
364 | |
365 | dev->netdev_ops = &br_netdev_ops; |
366 | dev->destructor = br_dev_free; |
367 | SET_ETHTOOL_OPS(dev, &br_ethtool_ops); |
368 | dev->tx_queue_len = 0; |
369 | dev->priv_flags = IFF_EBRIDGE; |
370 | |
371 | dev->features = NETIF_F_SG | NETIF_F_FRAGLIST | NETIF_F_HIGHDMA | |
372 | NETIF_F_GSO_MASK | NETIF_F_NO_CSUM | NETIF_F_LLTX | |
373 | NETIF_F_NETNS_LOCAL | NETIF_F_GSO | NETIF_F_HW_VLAN_TX; |
374 | } |
375 |
Branches:
ben-wpan
ben-wpan-stefan
javiroman/ks7010
jz-2.6.34
jz-2.6.34-rc5
jz-2.6.34-rc6
jz-2.6.34-rc7
jz-2.6.35
jz-2.6.36
jz-2.6.37
jz-2.6.38
jz-2.6.39
jz-3.0
jz-3.1
jz-3.11
jz-3.12
jz-3.13
jz-3.15
jz-3.16
jz-3.18-dt
jz-3.2
jz-3.3
jz-3.4
jz-3.5
jz-3.6
jz-3.6-rc2-pwm
jz-3.9
jz-3.9-clk
jz-3.9-rc8
jz47xx
jz47xx-2.6.38
master
Tags:
od-2011-09-04
od-2011-09-18
v2.6.34-rc5
v2.6.34-rc6
v2.6.34-rc7
v3.9