diff options
Diffstat (limited to 'net/hsr/hsr_netlink.c')
-rw-r--r-- | net/hsr/hsr_netlink.c | 102 |
1 files changed, 65 insertions, 37 deletions
diff --git a/net/hsr/hsr_netlink.c b/net/hsr/hsr_netlink.c index 01a5261ac7a5..a2c7e4c0ac1e 100644 --- a/net/hsr/hsr_netlink.c +++ b/net/hsr/hsr_netlink.c | |||
@@ -1,4 +1,4 @@ | |||
1 | /* Copyright 2011-2013 Autronica Fire and Security AS | 1 | /* Copyright 2011-2014 Autronica Fire and Security AS |
2 | * | 2 | * |
3 | * This program is free software; you can redistribute it and/or modify it | 3 | * This program is free software; you can redistribute it and/or modify it |
4 | * under the terms of the GNU General Public License as published by the Free | 4 | * under the terms of the GNU General Public License as published by the Free |
@@ -6,7 +6,7 @@ | |||
6 | * any later version. | 6 | * any later version. |
7 | * | 7 | * |
8 | * Author(s): | 8 | * Author(s): |
9 | * 2011-2013 Arvid Brodin, arvid.brodin@xdin.com | 9 | * 2011-2014 Arvid Brodin, arvid.brodin@alten.se |
10 | * | 10 | * |
11 | * Routines for handling Netlink messages for HSR. | 11 | * Routines for handling Netlink messages for HSR. |
12 | */ | 12 | */ |
@@ -37,13 +37,17 @@ static int hsr_newlink(struct net *src_net, struct net_device *dev, | |||
37 | struct net_device *link[2]; | 37 | struct net_device *link[2]; |
38 | unsigned char multicast_spec; | 38 | unsigned char multicast_spec; |
39 | 39 | ||
40 | if (!data) { | ||
41 | netdev_info(dev, "HSR: No slave devices specified\n"); | ||
42 | return -EINVAL; | ||
43 | } | ||
40 | if (!data[IFLA_HSR_SLAVE1]) { | 44 | if (!data[IFLA_HSR_SLAVE1]) { |
41 | netdev_info(dev, "IFLA_HSR_SLAVE1 missing!\n"); | 45 | netdev_info(dev, "HSR: Slave1 device not specified\n"); |
42 | return -EINVAL; | 46 | return -EINVAL; |
43 | } | 47 | } |
44 | link[0] = __dev_get_by_index(src_net, nla_get_u32(data[IFLA_HSR_SLAVE1])); | 48 | link[0] = __dev_get_by_index(src_net, nla_get_u32(data[IFLA_HSR_SLAVE1])); |
45 | if (!data[IFLA_HSR_SLAVE2]) { | 49 | if (!data[IFLA_HSR_SLAVE2]) { |
46 | netdev_info(dev, "IFLA_HSR_SLAVE2 missing!\n"); | 50 | netdev_info(dev, "HSR: Slave2 device not specified\n"); |
47 | return -EINVAL; | 51 | return -EINVAL; |
48 | } | 52 | } |
49 | link[1] = __dev_get_by_index(src_net, nla_get_u32(data[IFLA_HSR_SLAVE2])); | 53 | link[1] = __dev_get_by_index(src_net, nla_get_u32(data[IFLA_HSR_SLAVE2])); |
@@ -63,21 +67,33 @@ static int hsr_newlink(struct net *src_net, struct net_device *dev, | |||
63 | 67 | ||
64 | static int hsr_fill_info(struct sk_buff *skb, const struct net_device *dev) | 68 | static int hsr_fill_info(struct sk_buff *skb, const struct net_device *dev) |
65 | { | 69 | { |
66 | struct hsr_priv *hsr_priv; | 70 | struct hsr_priv *hsr; |
71 | struct hsr_port *port; | ||
72 | int res; | ||
67 | 73 | ||
68 | hsr_priv = netdev_priv(dev); | 74 | hsr = netdev_priv(dev); |
69 | 75 | ||
70 | if (hsr_priv->slave[0]) | 76 | res = 0; |
71 | if (nla_put_u32(skb, IFLA_HSR_SLAVE1, hsr_priv->slave[0]->ifindex)) | ||
72 | goto nla_put_failure; | ||
73 | 77 | ||
74 | if (hsr_priv->slave[1]) | 78 | rcu_read_lock(); |
75 | if (nla_put_u32(skb, IFLA_HSR_SLAVE2, hsr_priv->slave[1]->ifindex)) | 79 | port = hsr_port_get_hsr(hsr, HSR_PT_SLAVE_A); |
76 | goto nla_put_failure; | 80 | if (port) |
81 | res = nla_put_u32(skb, IFLA_HSR_SLAVE1, port->dev->ifindex); | ||
82 | rcu_read_unlock(); | ||
83 | if (res) | ||
84 | goto nla_put_failure; | ||
85 | |||
86 | rcu_read_lock(); | ||
87 | port = hsr_port_get_hsr(hsr, HSR_PT_SLAVE_B); | ||
88 | if (port) | ||
89 | res = nla_put_u32(skb, IFLA_HSR_SLAVE2, port->dev->ifindex); | ||
90 | rcu_read_unlock(); | ||
91 | if (res) | ||
92 | goto nla_put_failure; | ||
77 | 93 | ||
78 | if (nla_put(skb, IFLA_HSR_SUPERVISION_ADDR, ETH_ALEN, | 94 | if (nla_put(skb, IFLA_HSR_SUPERVISION_ADDR, ETH_ALEN, |
79 | hsr_priv->sup_multicast_addr) || | 95 | hsr->sup_multicast_addr) || |
80 | nla_put_u16(skb, IFLA_HSR_SEQ_NR, hsr_priv->sequence_nr)) | 96 | nla_put_u16(skb, IFLA_HSR_SEQ_NR, hsr->sequence_nr)) |
81 | goto nla_put_failure; | 97 | goto nla_put_failure; |
82 | 98 | ||
83 | return 0; | 99 | return 0; |
@@ -128,13 +144,13 @@ static const struct genl_multicast_group hsr_mcgrps[] = { | |||
128 | * over one of the slave interfaces. This would indicate an open network ring | 144 | * over one of the slave interfaces. This would indicate an open network ring |
129 | * (i.e. a link has failed somewhere). | 145 | * (i.e. a link has failed somewhere). |
130 | */ | 146 | */ |
131 | void hsr_nl_ringerror(struct hsr_priv *hsr_priv, unsigned char addr[ETH_ALEN], | 147 | void hsr_nl_ringerror(struct hsr_priv *hsr, unsigned char addr[ETH_ALEN], |
132 | enum hsr_dev_idx dev_idx) | 148 | struct hsr_port *port) |
133 | { | 149 | { |
134 | struct sk_buff *skb; | 150 | struct sk_buff *skb; |
135 | void *msg_head; | 151 | void *msg_head; |
152 | struct hsr_port *master; | ||
136 | int res; | 153 | int res; |
137 | int ifindex; | ||
138 | 154 | ||
139 | skb = genlmsg_new(NLMSG_GOODSIZE, GFP_ATOMIC); | 155 | skb = genlmsg_new(NLMSG_GOODSIZE, GFP_ATOMIC); |
140 | if (!skb) | 156 | if (!skb) |
@@ -148,11 +164,7 @@ void hsr_nl_ringerror(struct hsr_priv *hsr_priv, unsigned char addr[ETH_ALEN], | |||
148 | if (res < 0) | 164 | if (res < 0) |
149 | goto nla_put_failure; | 165 | goto nla_put_failure; |
150 | 166 | ||
151 | if (hsr_priv->slave[dev_idx]) | 167 | res = nla_put_u32(skb, HSR_A_IFINDEX, port->dev->ifindex); |
152 | ifindex = hsr_priv->slave[dev_idx]->ifindex; | ||
153 | else | ||
154 | ifindex = -1; | ||
155 | res = nla_put_u32(skb, HSR_A_IFINDEX, ifindex); | ||
156 | if (res < 0) | 168 | if (res < 0) |
157 | goto nla_put_failure; | 169 | goto nla_put_failure; |
158 | 170 | ||
@@ -165,16 +177,20 @@ nla_put_failure: | |||
165 | kfree_skb(skb); | 177 | kfree_skb(skb); |
166 | 178 | ||
167 | fail: | 179 | fail: |
168 | netdev_warn(hsr_priv->dev, "Could not send HSR ring error message\n"); | 180 | rcu_read_lock(); |
181 | master = hsr_port_get_hsr(hsr, HSR_PT_MASTER); | ||
182 | netdev_warn(master->dev, "Could not send HSR ring error message\n"); | ||
183 | rcu_read_unlock(); | ||
169 | } | 184 | } |
170 | 185 | ||
171 | /* This is called when we haven't heard from the node with MAC address addr for | 186 | /* This is called when we haven't heard from the node with MAC address addr for |
172 | * some time (just before the node is removed from the node table/list). | 187 | * some time (just before the node is removed from the node table/list). |
173 | */ | 188 | */ |
174 | void hsr_nl_nodedown(struct hsr_priv *hsr_priv, unsigned char addr[ETH_ALEN]) | 189 | void hsr_nl_nodedown(struct hsr_priv *hsr, unsigned char addr[ETH_ALEN]) |
175 | { | 190 | { |
176 | struct sk_buff *skb; | 191 | struct sk_buff *skb; |
177 | void *msg_head; | 192 | void *msg_head; |
193 | struct hsr_port *master; | ||
178 | int res; | 194 | int res; |
179 | 195 | ||
180 | skb = genlmsg_new(NLMSG_GOODSIZE, GFP_ATOMIC); | 196 | skb = genlmsg_new(NLMSG_GOODSIZE, GFP_ATOMIC); |
@@ -199,7 +215,10 @@ nla_put_failure: | |||
199 | kfree_skb(skb); | 215 | kfree_skb(skb); |
200 | 216 | ||
201 | fail: | 217 | fail: |
202 | netdev_warn(hsr_priv->dev, "Could not send HSR node down\n"); | 218 | rcu_read_lock(); |
219 | master = hsr_port_get_hsr(hsr, HSR_PT_MASTER); | ||
220 | netdev_warn(master->dev, "Could not send HSR node down\n"); | ||
221 | rcu_read_unlock(); | ||
203 | } | 222 | } |
204 | 223 | ||
205 | 224 | ||
@@ -220,7 +239,8 @@ static int hsr_get_node_status(struct sk_buff *skb_in, struct genl_info *info) | |||
220 | /* For sending */ | 239 | /* For sending */ |
221 | struct sk_buff *skb_out; | 240 | struct sk_buff *skb_out; |
222 | void *msg_head; | 241 | void *msg_head; |
223 | struct hsr_priv *hsr_priv; | 242 | struct hsr_priv *hsr; |
243 | struct hsr_port *port; | ||
224 | unsigned char hsr_node_addr_b[ETH_ALEN]; | 244 | unsigned char hsr_node_addr_b[ETH_ALEN]; |
225 | int hsr_node_if1_age; | 245 | int hsr_node_if1_age; |
226 | u16 hsr_node_if1_seq; | 246 | u16 hsr_node_if1_seq; |
@@ -267,8 +287,8 @@ static int hsr_get_node_status(struct sk_buff *skb_in, struct genl_info *info) | |||
267 | if (res < 0) | 287 | if (res < 0) |
268 | goto nla_put_failure; | 288 | goto nla_put_failure; |
269 | 289 | ||
270 | hsr_priv = netdev_priv(hsr_dev); | 290 | hsr = netdev_priv(hsr_dev); |
271 | res = hsr_get_node_data(hsr_priv, | 291 | res = hsr_get_node_data(hsr, |
272 | (unsigned char *) nla_data(info->attrs[HSR_A_NODE_ADDR]), | 292 | (unsigned char *) nla_data(info->attrs[HSR_A_NODE_ADDR]), |
273 | hsr_node_addr_b, | 293 | hsr_node_addr_b, |
274 | &addr_b_ifindex, | 294 | &addr_b_ifindex, |
@@ -301,9 +321,12 @@ static int hsr_get_node_status(struct sk_buff *skb_in, struct genl_info *info) | |||
301 | res = nla_put_u16(skb_out, HSR_A_IF1_SEQ, hsr_node_if1_seq); | 321 | res = nla_put_u16(skb_out, HSR_A_IF1_SEQ, hsr_node_if1_seq); |
302 | if (res < 0) | 322 | if (res < 0) |
303 | goto nla_put_failure; | 323 | goto nla_put_failure; |
304 | if (hsr_priv->slave[0]) | 324 | rcu_read_lock(); |
325 | port = hsr_port_get_hsr(hsr, HSR_PT_SLAVE_A); | ||
326 | if (port) | ||
305 | res = nla_put_u32(skb_out, HSR_A_IF1_IFINDEX, | 327 | res = nla_put_u32(skb_out, HSR_A_IF1_IFINDEX, |
306 | hsr_priv->slave[0]->ifindex); | 328 | port->dev->ifindex); |
329 | rcu_read_unlock(); | ||
307 | if (res < 0) | 330 | if (res < 0) |
308 | goto nla_put_failure; | 331 | goto nla_put_failure; |
309 | 332 | ||
@@ -313,9 +336,14 @@ static int hsr_get_node_status(struct sk_buff *skb_in, struct genl_info *info) | |||
313 | res = nla_put_u16(skb_out, HSR_A_IF2_SEQ, hsr_node_if2_seq); | 336 | res = nla_put_u16(skb_out, HSR_A_IF2_SEQ, hsr_node_if2_seq); |
314 | if (res < 0) | 337 | if (res < 0) |
315 | goto nla_put_failure; | 338 | goto nla_put_failure; |
316 | if (hsr_priv->slave[1]) | 339 | rcu_read_lock(); |
340 | port = hsr_port_get_hsr(hsr, HSR_PT_SLAVE_B); | ||
341 | if (port) | ||
317 | res = nla_put_u32(skb_out, HSR_A_IF2_IFINDEX, | 342 | res = nla_put_u32(skb_out, HSR_A_IF2_IFINDEX, |
318 | hsr_priv->slave[1]->ifindex); | 343 | port->dev->ifindex); |
344 | rcu_read_unlock(); | ||
345 | if (res < 0) | ||
346 | goto nla_put_failure; | ||
319 | 347 | ||
320 | genlmsg_end(skb_out, msg_head); | 348 | genlmsg_end(skb_out, msg_head); |
321 | genlmsg_unicast(genl_info_net(info), skb_out, info->snd_portid); | 349 | genlmsg_unicast(genl_info_net(info), skb_out, info->snd_portid); |
@@ -334,7 +362,7 @@ fail: | |||
334 | return res; | 362 | return res; |
335 | } | 363 | } |
336 | 364 | ||
337 | /* Get a list of MacAddressA of all nodes known to this node (other than self). | 365 | /* Get a list of MacAddressA of all nodes known to this node (including self). |
338 | */ | 366 | */ |
339 | static int hsr_get_node_list(struct sk_buff *skb_in, struct genl_info *info) | 367 | static int hsr_get_node_list(struct sk_buff *skb_in, struct genl_info *info) |
340 | { | 368 | { |
@@ -345,7 +373,7 @@ static int hsr_get_node_list(struct sk_buff *skb_in, struct genl_info *info) | |||
345 | /* For sending */ | 373 | /* For sending */ |
346 | struct sk_buff *skb_out; | 374 | struct sk_buff *skb_out; |
347 | void *msg_head; | 375 | void *msg_head; |
348 | struct hsr_priv *hsr_priv; | 376 | struct hsr_priv *hsr; |
349 | void *pos; | 377 | void *pos; |
350 | unsigned char addr[ETH_ALEN]; | 378 | unsigned char addr[ETH_ALEN]; |
351 | int res; | 379 | int res; |
@@ -385,17 +413,17 @@ static int hsr_get_node_list(struct sk_buff *skb_in, struct genl_info *info) | |||
385 | if (res < 0) | 413 | if (res < 0) |
386 | goto nla_put_failure; | 414 | goto nla_put_failure; |
387 | 415 | ||
388 | hsr_priv = netdev_priv(hsr_dev); | 416 | hsr = netdev_priv(hsr_dev); |
389 | 417 | ||
390 | rcu_read_lock(); | 418 | rcu_read_lock(); |
391 | pos = hsr_get_next_node(hsr_priv, NULL, addr); | 419 | pos = hsr_get_next_node(hsr, NULL, addr); |
392 | while (pos) { | 420 | while (pos) { |
393 | res = nla_put(skb_out, HSR_A_NODE_ADDR, ETH_ALEN, addr); | 421 | res = nla_put(skb_out, HSR_A_NODE_ADDR, ETH_ALEN, addr); |
394 | if (res < 0) { | 422 | if (res < 0) { |
395 | rcu_read_unlock(); | 423 | rcu_read_unlock(); |
396 | goto nla_put_failure; | 424 | goto nla_put_failure; |
397 | } | 425 | } |
398 | pos = hsr_get_next_node(hsr_priv, pos, addr); | 426 | pos = hsr_get_next_node(hsr, pos, addr); |
399 | } | 427 | } |
400 | rcu_read_unlock(); | 428 | rcu_read_unlock(); |
401 | 429 | ||