diff options
author | Arvid Brodin <arvid.brodin@alten.se> | 2014-07-04 17:37:27 -0400 |
---|---|---|
committer | David S. Miller <davem@davemloft.net> | 2014-07-08 14:35:31 -0400 |
commit | 51f3c605318b056ac5deb9079bbef2a976558827 (patch) | |
tree | 892ae91481ed018ce84f70a9b1c49ee0972d9406 /net/hsr/hsr_slave.c | |
parent | e9aae56ea43ef4a32527b9d86c1f6b5eebfbd223 (diff) |
net/hsr: Move slave init to hsr_slave.c.
Also try to prevent some possible slave dereference race conditions. This is
finalized in the next patch, which abandons the slave array in favour of
a list_head list and list RCU.
Signed-off-by: Arvid Brodin <arvid.brodin@alten.se>
Signed-off-by: David S. Miller <davem@davemloft.net>
Diffstat (limited to 'net/hsr/hsr_slave.c')
-rw-r--r-- | net/hsr/hsr_slave.c | 91 |
1 files changed, 91 insertions, 0 deletions
diff --git a/net/hsr/hsr_slave.c b/net/hsr/hsr_slave.c index 702814631ee1..d676090f7900 100644 --- a/net/hsr/hsr_slave.c +++ b/net/hsr/hsr_slave.c | |||
@@ -11,10 +11,45 @@ | |||
11 | 11 | ||
12 | #include "hsr_slave.h" | 12 | #include "hsr_slave.h" |
13 | #include <linux/etherdevice.h> | 13 | #include <linux/etherdevice.h> |
14 | #include <linux/if_arp.h> | ||
14 | #include "hsr_main.h" | 15 | #include "hsr_main.h" |
16 | #include "hsr_device.h" | ||
15 | #include "hsr_framereg.h" | 17 | #include "hsr_framereg.h" |
16 | 18 | ||
17 | 19 | ||
20 | static int check_slave_ok(struct net_device *dev) | ||
21 | { | ||
22 | /* Don't allow HSR on non-ethernet like devices */ | ||
23 | if ((dev->flags & IFF_LOOPBACK) || (dev->type != ARPHRD_ETHER) || | ||
24 | (dev->addr_len != ETH_ALEN)) { | ||
25 | netdev_info(dev, "Cannot use loopback or non-ethernet device as HSR slave.\n"); | ||
26 | return -EINVAL; | ||
27 | } | ||
28 | |||
29 | /* Don't allow enslaving hsr devices */ | ||
30 | if (is_hsr_master(dev)) { | ||
31 | netdev_info(dev, "Cannot create trees of HSR devices.\n"); | ||
32 | return -EINVAL; | ||
33 | } | ||
34 | |||
35 | if (is_hsr_slave(dev)) { | ||
36 | netdev_info(dev, "This device is already a HSR slave.\n"); | ||
37 | return -EINVAL; | ||
38 | } | ||
39 | |||
40 | if (dev->priv_flags & IFF_802_1Q_VLAN) { | ||
41 | netdev_info(dev, "HSR on top of VLAN is not yet supported in this driver.\n"); | ||
42 | return -EINVAL; | ||
43 | } | ||
44 | |||
45 | /* HSR over bonded devices has not been tested, but I'm not sure it | ||
46 | * won't work... | ||
47 | */ | ||
48 | |||
49 | return 0; | ||
50 | } | ||
51 | |||
52 | |||
18 | static struct sk_buff *hsr_pull_tag(struct sk_buff *skb) | 53 | static struct sk_buff *hsr_pull_tag(struct sk_buff *skb) |
19 | { | 54 | { |
20 | struct hsr_tag *hsr_tag; | 55 | struct hsr_tag *hsr_tag; |
@@ -241,3 +276,59 @@ forward: | |||
241 | 276 | ||
242 | return RX_HANDLER_CONSUMED; | 277 | return RX_HANDLER_CONSUMED; |
243 | } | 278 | } |
279 | |||
280 | int hsr_add_slave(struct hsr_priv *hsr, struct net_device *dev, int idx) | ||
281 | { | ||
282 | int res; | ||
283 | |||
284 | dev_hold(dev); | ||
285 | |||
286 | res = check_slave_ok(dev); | ||
287 | if (res) | ||
288 | goto fail; | ||
289 | |||
290 | res = dev_set_promiscuity(dev, 1); | ||
291 | if (res) | ||
292 | goto fail; | ||
293 | |||
294 | res = netdev_rx_handler_register(dev, hsr_handle_frame, hsr); | ||
295 | if (res) | ||
296 | goto fail_rx_handler; | ||
297 | |||
298 | |||
299 | hsr->slave[idx] = dev; | ||
300 | |||
301 | /* Set required header length */ | ||
302 | if (dev->hard_header_len + HSR_HLEN > hsr->dev->hard_header_len) | ||
303 | hsr->dev->hard_header_len = dev->hard_header_len + HSR_HLEN; | ||
304 | |||
305 | dev_set_mtu(hsr->dev, hsr_get_max_mtu(hsr)); | ||
306 | |||
307 | return 0; | ||
308 | |||
309 | fail_rx_handler: | ||
310 | dev_set_promiscuity(dev, -1); | ||
311 | |||
312 | fail: | ||
313 | dev_put(dev); | ||
314 | return res; | ||
315 | } | ||
316 | |||
317 | void hsr_del_slave(struct hsr_priv *hsr, int idx) | ||
318 | { | ||
319 | struct net_device *slave; | ||
320 | |||
321 | slave = hsr->slave[idx]; | ||
322 | hsr->slave[idx] = NULL; | ||
323 | |||
324 | netdev_update_features(hsr->dev); | ||
325 | dev_set_mtu(hsr->dev, hsr_get_max_mtu(hsr)); | ||
326 | |||
327 | if (slave) { | ||
328 | netdev_rx_handler_unregister(slave); | ||
329 | dev_set_promiscuity(slave, -1); | ||
330 | } | ||
331 | |||
332 | synchronize_rcu(); | ||
333 | dev_put(slave); | ||
334 | } | ||