aboutsummaryrefslogtreecommitdiffstats
path: root/net
diff options
context:
space:
mode:
authorArvid Brodin <Arvid.Brodin@xdin.com>2013-10-30 16:10:47 -0400
committerDavid S. Miller <davem@davemloft.net>2013-11-03 23:20:14 -0500
commitf421436a591d34fa5279b54a96ac07d70250cc8d (patch)
treef5435cfb8877fd029dce3bdb617fae090711316f /net
parent74d332c13b2148ae934ea94dac1745ae92efe8e5 (diff)
net/hsr: Add support for the High-availability Seamless Redundancy protocol (HSRv0)
High-availability Seamless Redundancy ("HSR") provides instant failover redundancy for Ethernet networks. It requires a special network topology where all nodes are connected in a ring (each node having two physical network interfaces). It is suited for applications that demand high availability and very short reaction time. HSR acts on the Ethernet layer, using a registered Ethernet protocol type to send special HSR frames in both directions over the ring. The driver creates virtual network interfaces that can be used just like any ordinary Linux network interface, for IP/TCP/UDP traffic etc. All nodes in the network ring must be HSR capable. This code is a "best effort" to comply with the HSR standard as described in IEC 62439-3:2010 (HSRv0). Signed-off-by: Arvid Brodin <arvid.brodin@xdin.com> Signed-off-by: David S. Miller <davem@davemloft.net>
Diffstat (limited to 'net')
-rw-r--r--net/Kconfig1
-rw-r--r--net/Makefile1
-rw-r--r--net/hsr/Kconfig27
-rw-r--r--net/hsr/Makefile7
-rw-r--r--net/hsr/hsr_device.c596
-rw-r--r--net/hsr/hsr_device.h29
-rw-r--r--net/hsr/hsr_framereg.c503
-rw-r--r--net/hsr/hsr_framereg.h53
-rw-r--r--net/hsr/hsr_main.c469
-rw-r--r--net/hsr/hsr_main.h166
-rw-r--r--net/hsr/hsr_netlink.c457
-rw-r--r--net/hsr/hsr_netlink.h30
12 files changed, 2339 insertions, 0 deletions
diff --git a/net/Kconfig b/net/Kconfig
index b50dacc072f0..0715db64a5c3 100644
--- a/net/Kconfig
+++ b/net/Kconfig
@@ -220,6 +220,7 @@ source "net/openvswitch/Kconfig"
220source "net/vmw_vsock/Kconfig" 220source "net/vmw_vsock/Kconfig"
221source "net/netlink/Kconfig" 221source "net/netlink/Kconfig"
222source "net/mpls/Kconfig" 222source "net/mpls/Kconfig"
223source "net/hsr/Kconfig"
223 224
224config RPS 225config RPS
225 boolean 226 boolean
diff --git a/net/Makefile b/net/Makefile
index 9492e8cb64e9..8fa2f91517f1 100644
--- a/net/Makefile
+++ b/net/Makefile
@@ -71,3 +71,4 @@ obj-$(CONFIG_NFC) += nfc/
71obj-$(CONFIG_OPENVSWITCH) += openvswitch/ 71obj-$(CONFIG_OPENVSWITCH) += openvswitch/
72obj-$(CONFIG_VSOCKETS) += vmw_vsock/ 72obj-$(CONFIG_VSOCKETS) += vmw_vsock/
73obj-$(CONFIG_NET_MPLS_GSO) += mpls/ 73obj-$(CONFIG_NET_MPLS_GSO) += mpls/
74obj-$(CONFIG_HSR) += hsr/
diff --git a/net/hsr/Kconfig b/net/hsr/Kconfig
new file mode 100644
index 000000000000..0d3d709052ca
--- /dev/null
+++ b/net/hsr/Kconfig
@@ -0,0 +1,27 @@
1#
2# IEC 62439-3 High-availability Seamless Redundancy
3#
4
5config HSR
6 tristate "High-availability Seamless Redundancy (HSR)"
7 ---help---
8 If you say Y here, then your Linux box will be able to act as a
9 DANH ("Doubly attached node implementing HSR"). For this to work,
10 your Linux box needs (at least) two physical Ethernet interfaces,
11 and it must be connected as a node in a ring network together with
12 other HSR capable nodes.
13
14 All Ethernet frames sent over the hsr device will be sent in both
15 directions on the ring (over both slave ports), giving a redundant,
16 instant fail-over network. Each HSR node in the ring acts like a
17 bridge for HSR frames, but filters frames that have been forwarded
18 earlier.
19
20 This code is a "best effort" to comply with the HSR standard as
21 described in IEC 62439-3:2010 (HSRv0), but no compliancy tests have
22 been made.
23
24 You need to perform any and all necessary tests yourself before
25 relying on this code in a safety critical system!
26
27 If unsure, say N.
diff --git a/net/hsr/Makefile b/net/hsr/Makefile
new file mode 100644
index 000000000000..b68359f181cc
--- /dev/null
+++ b/net/hsr/Makefile
@@ -0,0 +1,7 @@
1#
2# Makefile for HSR
3#
4
5obj-$(CONFIG_HSR) += hsr.o
6
7hsr-y := hsr_main.o hsr_framereg.o hsr_device.o hsr_netlink.o
diff --git a/net/hsr/hsr_device.c b/net/hsr/hsr_device.c
new file mode 100644
index 000000000000..cac505f166d5
--- /dev/null
+++ b/net/hsr/hsr_device.c
@@ -0,0 +1,596 @@
1/* Copyright 2011-2013 Autronica Fire and Security AS
2 *
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
5 * Software Foundation; either version 2 of the License, or (at your option)
6 * any later version.
7 *
8 * Author(s):
9 * 2011-2013 Arvid Brodin, arvid.brodin@xdin.com
10 *
11 * This file contains device methods for creating, using and destroying
12 * virtual HSR devices.
13 */
14
15#include <linux/netdevice.h>
16#include <linux/skbuff.h>
17#include <linux/etherdevice.h>
18#include <linux/if_arp.h>
19#include <linux/rtnetlink.h>
20#include <linux/pkt_sched.h>
21#include "hsr_device.h"
22#include "hsr_framereg.h"
23#include "hsr_main.h"
24
25
26static bool is_admin_up(struct net_device *dev)
27{
28 return dev && (dev->flags & IFF_UP);
29}
30
31static bool is_slave_up(struct net_device *dev)
32{
33 return dev && is_admin_up(dev) && netif_oper_up(dev);
34}
35
36static void __hsr_set_operstate(struct net_device *dev, int transition)
37{
38 write_lock_bh(&dev_base_lock);
39 if (dev->operstate != transition) {
40 dev->operstate = transition;
41 write_unlock_bh(&dev_base_lock);
42 netdev_state_change(dev);
43 } else {
44 write_unlock_bh(&dev_base_lock);
45 }
46}
47
48void hsr_set_operstate(struct net_device *hsr_dev, struct net_device *slave1,
49 struct net_device *slave2)
50{
51 if (!is_admin_up(hsr_dev)) {
52 __hsr_set_operstate(hsr_dev, IF_OPER_DOWN);
53 return;
54 }
55
56 if (is_slave_up(slave1) || is_slave_up(slave2))
57 __hsr_set_operstate(hsr_dev, IF_OPER_UP);
58 else
59 __hsr_set_operstate(hsr_dev, IF_OPER_LOWERLAYERDOWN);
60}
61
62void hsr_set_carrier(struct net_device *hsr_dev, struct net_device *slave1,
63 struct net_device *slave2)
64{
65 if (is_slave_up(slave1) || is_slave_up(slave2))
66 netif_carrier_on(hsr_dev);
67 else
68 netif_carrier_off(hsr_dev);
69}
70
71
72void hsr_check_announce(struct net_device *hsr_dev, int old_operstate)
73{
74 struct hsr_priv *hsr_priv;
75
76 hsr_priv = netdev_priv(hsr_dev);
77
78 if ((hsr_dev->operstate == IF_OPER_UP) && (old_operstate != IF_OPER_UP)) {
79 /* Went up */
80 hsr_priv->announce_count = 0;
81 hsr_priv->announce_timer.expires = jiffies +
82 msecs_to_jiffies(HSR_ANNOUNCE_INTERVAL);
83 add_timer(&hsr_priv->announce_timer);
84 }
85
86 if ((hsr_dev->operstate != IF_OPER_UP) && (old_operstate == IF_OPER_UP))
87 /* Went down */
88 del_timer(&hsr_priv->announce_timer);
89}
90
91
92int hsr_get_max_mtu(struct hsr_priv *hsr_priv)
93{
94 int mtu_max;
95
96 if (hsr_priv->slave[0] && hsr_priv->slave[1])
97 mtu_max = min(hsr_priv->slave[0]->mtu, hsr_priv->slave[1]->mtu);
98 else if (hsr_priv->slave[0])
99 mtu_max = hsr_priv->slave[0]->mtu;
100 else if (hsr_priv->slave[1])
101 mtu_max = hsr_priv->slave[1]->mtu;
102 else
103 mtu_max = HSR_TAGLEN;
104
105 return mtu_max - HSR_TAGLEN;
106}
107
108static int hsr_dev_change_mtu(struct net_device *dev, int new_mtu)
109{
110 struct hsr_priv *hsr_priv;
111
112 hsr_priv = netdev_priv(dev);
113
114 if (new_mtu > hsr_get_max_mtu(hsr_priv)) {
115 netdev_info(hsr_priv->dev, "A HSR master's MTU cannot be greater than the smallest MTU of its slaves minus the HSR Tag length (%d octets).\n",
116 HSR_TAGLEN);
117 return -EINVAL;
118 }
119
120 dev->mtu = new_mtu;
121
122 return 0;
123}
124
125static int hsr_dev_open(struct net_device *dev)
126{
127 struct hsr_priv *hsr_priv;
128 int i;
129 char *slave_name;
130
131 hsr_priv = netdev_priv(dev);
132
133 for (i = 0; i < HSR_MAX_SLAVE; i++) {
134 if (hsr_priv->slave[i])
135 slave_name = hsr_priv->slave[i]->name;
136 else
137 slave_name = "null";
138
139 if (!is_slave_up(hsr_priv->slave[i]))
140 netdev_warn(dev, "Slave %c (%s) is not up; please bring it up to get a working HSR network\n",
141 'A' + i, slave_name);
142 }
143
144 return 0;
145}
146
147static int hsr_dev_close(struct net_device *dev)
148{
149 /* Nothing to do here. We could try to restore the state of the slaves
150 * to what they were before being changed by the hsr master dev's state,
151 * but they might have been changed manually in the mean time too, so
152 * taking them up or down here might be confusing and is probably not a
153 * good idea.
154 */
155 return 0;
156}
157
158
159static void hsr_fill_tag(struct hsr_ethhdr *hsr_ethhdr, struct hsr_priv *hsr_priv)
160{
161 unsigned long irqflags;
162
163 /* IEC 62439-1:2010, p 48, says the 4-bit "path" field can take values
164 * between 0001-1001 ("ring identifier", for regular HSR frames),
165 * or 1111 ("HSR management", supervision frames). Unfortunately, the
166 * spec writers forgot to explain what a "ring identifier" is, or
167 * how it is used. So we just set this to 0001 for regular frames,
168 * and 1111 for supervision frames.
169 */
170 set_hsr_tag_path(&hsr_ethhdr->hsr_tag, 0x1);
171
172 /* IEC 62439-1:2010, p 12: "The link service data unit in an Ethernet
173 * frame is the content of the frame located between the Length/Type
174 * field and the Frame Check Sequence."
175 *
176 * IEC 62439-3, p 48, specifies the "original LPDU" to include the
177 * original "LT" field (what "LT" means is not explained anywhere as
178 * far as I can see - perhaps "Length/Type"?). So LSDU_size might
179 * equal original length + 2.
180 * Also, the fact that this field is not used anywhere (might be used
181 * by a RedBox connecting HSR and PRP nets?) means I cannot test its
182 * correctness. Instead of guessing, I set this to 0 here, to make any
183 * problems immediately apparent. Anyone using this driver with PRP/HSR
184 * RedBoxes might need to fix this...
185 */
186 set_hsr_tag_LSDU_size(&hsr_ethhdr->hsr_tag, 0);
187
188 spin_lock_irqsave(&hsr_priv->seqnr_lock, irqflags);
189 hsr_ethhdr->hsr_tag.sequence_nr = htons(hsr_priv->sequence_nr);
190 hsr_priv->sequence_nr++;
191 spin_unlock_irqrestore(&hsr_priv->seqnr_lock, irqflags);
192
193 hsr_ethhdr->hsr_tag.encap_proto = hsr_ethhdr->ethhdr.h_proto;
194
195 hsr_ethhdr->ethhdr.h_proto = htons(ETH_P_PRP);
196}
197
198static int slave_xmit(struct sk_buff *skb, struct hsr_priv *hsr_priv,
199 enum hsr_dev_idx dev_idx)
200{
201 struct hsr_ethhdr *hsr_ethhdr;
202
203 hsr_ethhdr = (struct hsr_ethhdr *) skb->data;
204
205 skb->dev = hsr_priv->slave[dev_idx];
206
207 hsr_addr_subst_dest(hsr_priv, &hsr_ethhdr->ethhdr, dev_idx);
208
209 /* Address substitution (IEC62439-3 pp 26, 50): replace mac
210 * address of outgoing frame with that of the outgoing slave's.
211 */
212 memcpy(hsr_ethhdr->ethhdr.h_source, skb->dev->dev_addr, ETH_ALEN);
213
214 return dev_queue_xmit(skb);
215}
216
217
218static int hsr_dev_xmit(struct sk_buff *skb, struct net_device *dev)
219{
220 struct hsr_priv *hsr_priv;
221 struct hsr_ethhdr *hsr_ethhdr;
222 struct sk_buff *skb2;
223 int res1, res2;
224
225 hsr_priv = netdev_priv(dev);
226 hsr_ethhdr = (struct hsr_ethhdr *) skb->data;
227
228 if ((skb->protocol != htons(ETH_P_PRP)) ||
229 (hsr_ethhdr->ethhdr.h_proto != htons(ETH_P_PRP))) {
230 hsr_fill_tag(hsr_ethhdr, hsr_priv);
231 skb->protocol = htons(ETH_P_PRP);
232 }
233
234 skb2 = pskb_copy(skb, GFP_ATOMIC);
235
236 res1 = NET_XMIT_DROP;
237 if (likely(hsr_priv->slave[HSR_DEV_SLAVE_A]))
238 res1 = slave_xmit(skb, hsr_priv, HSR_DEV_SLAVE_A);
239
240 res2 = NET_XMIT_DROP;
241 if (likely(skb2 && hsr_priv->slave[HSR_DEV_SLAVE_B]))
242 res2 = slave_xmit(skb2, hsr_priv, HSR_DEV_SLAVE_B);
243
244 if (likely(res1 == NET_XMIT_SUCCESS || res1 == NET_XMIT_CN ||
245 res2 == NET_XMIT_SUCCESS || res2 == NET_XMIT_CN)) {
246 hsr_priv->dev->stats.tx_packets++;
247 hsr_priv->dev->stats.tx_bytes += skb->len;
248 } else {
249 hsr_priv->dev->stats.tx_dropped++;
250 }
251
252 return NETDEV_TX_OK;
253}
254
255
256static int hsr_header_create(struct sk_buff *skb, struct net_device *dev,
257 unsigned short type, const void *daddr,
258 const void *saddr, unsigned int len)
259{
260 int res;
261
262 /* Make room for the HSR tag now. We will fill it in later (in
263 * hsr_dev_xmit)
264 */
265 if (skb_headroom(skb) < HSR_TAGLEN + ETH_HLEN)
266 return -ENOBUFS;
267 skb_push(skb, HSR_TAGLEN);
268
269 /* To allow VLAN/HSR combos we should probably use
270 * res = dev_hard_header(skb, dev, type, daddr, saddr, len + HSR_TAGLEN);
271 * here instead. It would require other changes too, though - e.g.
272 * separate headers for each slave etc...
273 */
274 res = eth_header(skb, dev, type, daddr, saddr, len + HSR_TAGLEN);
275 if (res <= 0)
276 return res;
277 skb_reset_mac_header(skb);
278
279 return res + HSR_TAGLEN;
280}
281
282
283static const struct header_ops hsr_header_ops = {
284 .create = hsr_header_create,
285 .parse = eth_header_parse,
286};
287
288
289/* HSR:2010 supervision frames should be padded so that the whole frame,
290 * including headers and FCS, is 64 bytes (without VLAN).
291 */
292static int hsr_pad(int size)
293{
294 const int min_size = ETH_ZLEN - HSR_TAGLEN - ETH_HLEN;
295
296 if (size >= min_size)
297 return size;
298 return min_size;
299}
300
301static void send_hsr_supervision_frame(struct net_device *hsr_dev, u8 type)
302{
303 struct hsr_priv *hsr_priv;
304 struct sk_buff *skb;
305 int hlen, tlen;
306 struct hsr_sup_tag *hsr_stag;
307 struct hsr_sup_payload *hsr_sp;
308 unsigned long irqflags;
309
310 hlen = LL_RESERVED_SPACE(hsr_dev);
311 tlen = hsr_dev->needed_tailroom;
312 skb = alloc_skb(hsr_pad(sizeof(struct hsr_sup_payload)) + hlen + tlen,
313 GFP_ATOMIC);
314
315 if (skb == NULL)
316 return;
317
318 hsr_priv = netdev_priv(hsr_dev);
319
320 skb_reserve(skb, hlen);
321
322 skb->dev = hsr_dev;
323 skb->protocol = htons(ETH_P_PRP);
324 skb->priority = TC_PRIO_CONTROL;
325
326 if (dev_hard_header(skb, skb->dev, ETH_P_PRP,
327 hsr_priv->sup_multicast_addr,
328 skb->dev->dev_addr, skb->len) < 0)
329 goto out;
330
331 skb_pull(skb, sizeof(struct ethhdr));
332 hsr_stag = (typeof(hsr_stag)) skb->data;
333
334 set_hsr_stag_path(hsr_stag, 0xf);
335 set_hsr_stag_HSR_Ver(hsr_stag, 0);
336
337 spin_lock_irqsave(&hsr_priv->seqnr_lock, irqflags);
338 hsr_stag->sequence_nr = htons(hsr_priv->sequence_nr);
339 hsr_priv->sequence_nr++;
340 spin_unlock_irqrestore(&hsr_priv->seqnr_lock, irqflags);
341
342 hsr_stag->HSR_TLV_Type = type;
343 hsr_stag->HSR_TLV_Length = 12;
344
345 skb_push(skb, sizeof(struct ethhdr));
346
347 /* Payload: MacAddressA */
348 hsr_sp = (typeof(hsr_sp)) skb_put(skb, sizeof(*hsr_sp));
349 memcpy(hsr_sp->MacAddressA, hsr_dev->dev_addr, ETH_ALEN);
350
351 dev_queue_xmit(skb);
352 return;
353
354out:
355 kfree_skb(skb);
356}
357
358
359/* Announce (supervision frame) timer function
360 */
361static void hsr_announce(unsigned long data)
362{
363 struct hsr_priv *hsr_priv;
364
365 hsr_priv = (struct hsr_priv *) data;
366
367 if (hsr_priv->announce_count < 3) {
368 send_hsr_supervision_frame(hsr_priv->dev, HSR_TLV_ANNOUNCE);
369 hsr_priv->announce_count++;
370 } else {
371 send_hsr_supervision_frame(hsr_priv->dev, HSR_TLV_LIFE_CHECK);
372 }
373
374 if (hsr_priv->announce_count < 3)
375 hsr_priv->announce_timer.expires = jiffies +
376 msecs_to_jiffies(HSR_ANNOUNCE_INTERVAL);
377 else
378 hsr_priv->announce_timer.expires = jiffies +
379 msecs_to_jiffies(HSR_LIFE_CHECK_INTERVAL);
380
381 if (is_admin_up(hsr_priv->dev))
382 add_timer(&hsr_priv->announce_timer);
383}
384
385
386static void restore_slaves(struct net_device *hsr_dev)
387{
388 struct hsr_priv *hsr_priv;
389 int i;
390 int res;
391
392 hsr_priv = netdev_priv(hsr_dev);
393
394 rtnl_lock();
395
396 /* Restore promiscuity */
397 for (i = 0; i < HSR_MAX_SLAVE; i++) {
398 if (!hsr_priv->slave[i])
399 continue;
400 res = dev_set_promiscuity(hsr_priv->slave[i], -1);
401 if (res)
402 netdev_info(hsr_dev,
403 "Cannot restore slave promiscuity (%s, %d)\n",
404 hsr_priv->slave[i]->name, res);
405 }
406
407 rtnl_unlock();
408}
409
410static void reclaim_hsr_dev(struct rcu_head *rh)
411{
412 struct hsr_priv *hsr_priv;
413
414 hsr_priv = container_of(rh, struct hsr_priv, rcu_head);
415 free_netdev(hsr_priv->dev);
416}
417
418
419/* According to comments in the declaration of struct net_device, this function
420 * is "Called from unregister, can be used to call free_netdev". Ok then...
421 */
422static void hsr_dev_destroy(struct net_device *hsr_dev)
423{
424 struct hsr_priv *hsr_priv;
425
426 hsr_priv = netdev_priv(hsr_dev);
427
428 del_timer(&hsr_priv->announce_timer);
429 unregister_hsr_master(hsr_priv); /* calls list_del_rcu on hsr_priv */
430 restore_slaves(hsr_dev);
431 call_rcu(&hsr_priv->rcu_head, reclaim_hsr_dev); /* reclaim hsr_priv */
432}
433
434static const struct net_device_ops hsr_device_ops = {
435 .ndo_change_mtu = hsr_dev_change_mtu,
436 .ndo_open = hsr_dev_open,
437 .ndo_stop = hsr_dev_close,
438 .ndo_start_xmit = hsr_dev_xmit,
439};
440
441
442void hsr_dev_setup(struct net_device *dev)
443{
444 random_ether_addr(dev->dev_addr);
445
446 ether_setup(dev);
447 dev->header_ops = &hsr_header_ops;
448 dev->netdev_ops = &hsr_device_ops;
449 dev->tx_queue_len = 0;
450
451 dev->destructor = hsr_dev_destroy;
452}
453
454
455/* Return true if dev is a HSR master; return false otherwise.
456 */
457bool is_hsr_master(struct net_device *dev)
458{
459 return (dev->netdev_ops->ndo_start_xmit == hsr_dev_xmit);
460}
461
462static int check_slave_ok(struct net_device *dev)
463{
464 /* Don't allow HSR on non-ethernet like devices */
465 if ((dev->flags & IFF_LOOPBACK) || (dev->type != ARPHRD_ETHER) ||
466 (dev->addr_len != ETH_ALEN)) {
467 netdev_info(dev, "Cannot use loopback or non-ethernet device as HSR slave.\n");
468 return -EINVAL;
469 }
470
471 /* Don't allow enslaving hsr devices */
472 if (is_hsr_master(dev)) {
473 netdev_info(dev, "Cannot create trees of HSR devices.\n");
474 return -EINVAL;
475 }
476
477 if (is_hsr_slave(dev)) {
478 netdev_info(dev, "This device is already a HSR slave.\n");
479 return -EINVAL;
480 }
481
482 if (dev->priv_flags & IFF_802_1Q_VLAN) {
483 netdev_info(dev, "HSR on top of VLAN is not yet supported in this driver.\n");
484 return -EINVAL;
485 }
486
487 /* HSR over bonded devices has not been tested, but I'm not sure it
488 * won't work...
489 */
490
491 return 0;
492}
493
494
495/* Default multicast address for HSR Supervision frames */
496static const unsigned char def_multicast_addr[ETH_ALEN] = {
497 0x01, 0x15, 0x4e, 0x00, 0x01, 0x00
498};
499
500int hsr_dev_finalize(struct net_device *hsr_dev, struct net_device *slave[2],
501 unsigned char multicast_spec)
502{
503 struct hsr_priv *hsr_priv;
504 int i;
505 int res;
506
507 hsr_priv = netdev_priv(hsr_dev);
508 hsr_priv->dev = hsr_dev;
509 INIT_LIST_HEAD(&hsr_priv->node_db);
510 INIT_LIST_HEAD(&hsr_priv->self_node_db);
511 for (i = 0; i < HSR_MAX_SLAVE; i++)
512 hsr_priv->slave[i] = slave[i];
513
514 spin_lock_init(&hsr_priv->seqnr_lock);
515 /* Overflow soon to find bugs easier: */
516 hsr_priv->sequence_nr = USHRT_MAX - 1024;
517
518 init_timer(&hsr_priv->announce_timer);
519 hsr_priv->announce_timer.function = hsr_announce;
520 hsr_priv->announce_timer.data = (unsigned long) hsr_priv;
521
522 memcpy(hsr_priv->sup_multicast_addr, def_multicast_addr, ETH_ALEN);
523 hsr_priv->sup_multicast_addr[ETH_ALEN - 1] = multicast_spec;
524
525/* FIXME: should I modify the value of these?
526 *
527 * - hsr_dev->flags - i.e.
528 * IFF_MASTER/SLAVE?
529 * - hsr_dev->priv_flags - i.e.
530 * IFF_EBRIDGE?
531 * IFF_TX_SKB_SHARING?
532 * IFF_HSR_MASTER/SLAVE?
533 */
534
535 for (i = 0; i < HSR_MAX_SLAVE; i++) {
536 res = check_slave_ok(slave[i]);
537 if (res)
538 return res;
539 }
540
541 hsr_dev->features = slave[0]->features & slave[1]->features;
542 /* Prevent recursive tx locking */
543 hsr_dev->features |= NETIF_F_LLTX;
544 /* VLAN on top of HSR needs testing and probably some work on
545 * hsr_header_create() etc.
546 */
547 hsr_dev->features |= NETIF_F_VLAN_CHALLENGED;
548
549 /* Set hsr_dev's MAC address to that of mac_slave1 */
550 memcpy(hsr_dev->dev_addr, hsr_priv->slave[0]->dev_addr, ETH_ALEN);
551
552 /* Set required header length */
553 for (i = 0; i < HSR_MAX_SLAVE; i++) {
554 if (slave[i]->hard_header_len + HSR_TAGLEN >
555 hsr_dev->hard_header_len)
556 hsr_dev->hard_header_len =
557 slave[i]->hard_header_len + HSR_TAGLEN;
558 }
559
560 /* MTU */
561 for (i = 0; i < HSR_MAX_SLAVE; i++)
562 if (slave[i]->mtu - HSR_TAGLEN < hsr_dev->mtu)
563 hsr_dev->mtu = slave[i]->mtu - HSR_TAGLEN;
564
565 /* Make sure the 1st call to netif_carrier_on() gets through */
566 netif_carrier_off(hsr_dev);
567
568 /* Promiscuity */
569 for (i = 0; i < HSR_MAX_SLAVE; i++) {
570 res = dev_set_promiscuity(slave[i], 1);
571 if (res) {
572 netdev_info(hsr_dev, "Cannot set slave promiscuity (%s, %d)\n",
573 slave[i]->name, res);
574 goto fail;
575 }
576 }
577
578 /* Make sure we recognize frames from ourselves in hsr_rcv() */
579 res = hsr_create_self_node(&hsr_priv->self_node_db,
580 hsr_dev->dev_addr,
581 hsr_priv->slave[1]->dev_addr);
582 if (res < 0)
583 goto fail;
584
585 res = register_netdevice(hsr_dev);
586 if (res)
587 goto fail;
588
589 register_hsr_master(hsr_priv);
590
591 return 0;
592
593fail:
594 restore_slaves(hsr_dev);
595 return res;
596}
diff --git a/net/hsr/hsr_device.h b/net/hsr/hsr_device.h
new file mode 100644
index 000000000000..2c7148e73914
--- /dev/null
+++ b/net/hsr/hsr_device.h
@@ -0,0 +1,29 @@
1/* Copyright 2011-2013 Autronica Fire and Security AS
2 *
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
5 * Software Foundation; either version 2 of the License, or (at your option)
6 * any later version.
7 *
8 * Author(s):
9 * 2011-2013 Arvid Brodin, arvid.brodin@xdin.com
10 */
11
12#ifndef __HSR_DEVICE_H
13#define __HSR_DEVICE_H
14
15#include <linux/netdevice.h>
16#include "hsr_main.h"
17
18void hsr_dev_setup(struct net_device *dev);
19int hsr_dev_finalize(struct net_device *hsr_dev, struct net_device *slave[2],
20 unsigned char multicast_spec);
21void hsr_set_operstate(struct net_device *hsr_dev, struct net_device *slave1,
22 struct net_device *slave2);
23void hsr_set_carrier(struct net_device *hsr_dev, struct net_device *slave1,
24 struct net_device *slave2);
25void hsr_check_announce(struct net_device *hsr_dev, int old_operstate);
26bool is_hsr_master(struct net_device *dev);
27int hsr_get_max_mtu(struct hsr_priv *hsr_priv);
28
29#endif /* __HSR_DEVICE_H */
diff --git a/net/hsr/hsr_framereg.c b/net/hsr/hsr_framereg.c
new file mode 100644
index 000000000000..003f5bb3acd2
--- /dev/null
+++ b/net/hsr/hsr_framereg.c
@@ -0,0 +1,503 @@
1/* Copyright 2011-2013 Autronica Fire and Security AS
2 *
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
5 * Software Foundation; either version 2 of the License, or (at your option)
6 * any later version.
7 *
8 * Author(s):
9 * 2011-2013 Arvid Brodin, arvid.brodin@xdin.com
10 *
11 * The HSR spec says never to forward the same frame twice on the same
12 * interface. A frame is identified by its source MAC address and its HSR
13 * sequence number. This code keeps track of senders and their sequence numbers
14 * to allow filtering of duplicate frames, and to detect HSR ring errors.
15 */
16
17#include <linux/if_ether.h>
18#include <linux/etherdevice.h>
19#include <linux/slab.h>
20#include <linux/rculist.h>
21#include "hsr_main.h"
22#include "hsr_framereg.h"
23#include "hsr_netlink.h"
24
25
26struct node_entry {
27 struct list_head mac_list;
28 unsigned char MacAddressA[ETH_ALEN];
29 unsigned char MacAddressB[ETH_ALEN];
30 enum hsr_dev_idx AddrB_if; /* The local slave through which AddrB
31 * frames are received from this node
32 */
33 unsigned long time_in[HSR_MAX_SLAVE];
34 bool time_in_stale[HSR_MAX_SLAVE];
35 u16 seq_out[HSR_MAX_DEV];
36 struct rcu_head rcu_head;
37};
38
39/* TODO: use hash lists for mac addresses (linux/jhash.h)? */
40
41
42
43/* Search for mac entry. Caller must hold rcu read lock.
44 */
45static struct node_entry *find_node_by_AddrA(struct list_head *node_db,
46 const unsigned char addr[ETH_ALEN])
47{
48 struct node_entry *node;
49
50 list_for_each_entry_rcu(node, node_db, mac_list) {
51 if (ether_addr_equal(node->MacAddressA, addr))
52 return node;
53 }
54
55 return NULL;
56}
57
58
59/* Search for mac entry. Caller must hold rcu read lock.
60 */
61static struct node_entry *find_node_by_AddrB(struct list_head *node_db,
62 const unsigned char addr[ETH_ALEN])
63{
64 struct node_entry *node;
65
66 list_for_each_entry_rcu(node, node_db, mac_list) {
67 if (ether_addr_equal(node->MacAddressB, addr))
68 return node;
69 }
70
71 return NULL;
72}
73
74
75/* Search for mac entry. Caller must hold rcu read lock.
76 */
77struct node_entry *hsr_find_node(struct list_head *node_db, struct sk_buff *skb)
78{
79 struct node_entry *node;
80 struct ethhdr *ethhdr;
81
82 if (!skb_mac_header_was_set(skb))
83 return NULL;
84
85 ethhdr = (struct ethhdr *) skb_mac_header(skb);
86
87 list_for_each_entry_rcu(node, node_db, mac_list) {
88 if (ether_addr_equal(node->MacAddressA, ethhdr->h_source))
89 return node;
90 if (ether_addr_equal(node->MacAddressB, ethhdr->h_source))
91 return node;
92 }
93
94 return NULL;
95}
96
97
98/* Helper for device init; the self_node_db is used in hsr_rcv() to recognize
99 * frames from self that's been looped over the HSR ring.
100 */
101int hsr_create_self_node(struct list_head *self_node_db,
102 unsigned char addr_a[ETH_ALEN],
103 unsigned char addr_b[ETH_ALEN])
104{
105 struct node_entry *node, *oldnode;
106
107 node = kmalloc(sizeof(*node), GFP_KERNEL);
108 if (!node)
109 return -ENOMEM;
110
111 memcpy(node->MacAddressA, addr_a, ETH_ALEN);
112 memcpy(node->MacAddressB, addr_b, ETH_ALEN);
113
114 rcu_read_lock();
115 oldnode = list_first_or_null_rcu(self_node_db,
116 struct node_entry, mac_list);
117 if (oldnode) {
118 list_replace_rcu(&oldnode->mac_list, &node->mac_list);
119 rcu_read_unlock();
120 synchronize_rcu();
121 kfree(oldnode);
122 } else {
123 rcu_read_unlock();
124 list_add_tail_rcu(&node->mac_list, self_node_db);
125 }
126
127 return 0;
128}
129
130static void node_entry_reclaim(struct rcu_head *rh)
131{
132 kfree(container_of(rh, struct node_entry, rcu_head));
133}
134
135
136/* Add/merge node to the database of nodes. 'skb' must contain an HSR
137 * supervision frame.
138 * - If the supervision header's MacAddressA field is not yet in the database,
139 * this frame is from an hitherto unknown node - add it to the database.
140 * - If the sender's MAC address is not the same as its MacAddressA address,
141 * the node is using PICS_SUBS (address substitution). Record the sender's
142 * address as the node's MacAddressB.
143 *
144 * This function needs to work even if the sender node has changed one of its
145 * slaves' MAC addresses. In this case, there are four different cases described
146 * by (Addr-changed, received-from) pairs as follows. Note that changing the
147 * SlaveA address is equal to changing the node's own address:
148 *
149 * - (AddrB, SlaveB): The new AddrB will be recorded by PICS_SUBS code since
150 * node == NULL.
151 * - (AddrB, SlaveA): Will work as usual (the AddrB change won't be detected
152 * from this frame).
153 *
154 * - (AddrA, SlaveB): The old node will be found. We need to detect this and
155 * remove the node.
156 * - (AddrA, SlaveA): A new node will be registered (non-PICS_SUBS at first).
157 * The old one will be pruned after HSR_NODE_FORGET_TIME.
158 *
159 * We also need to detect if the sender's SlaveA and SlaveB cables have been
160 * swapped.
161 */
162struct node_entry *hsr_merge_node(struct hsr_priv *hsr_priv,
163 struct node_entry *node,
164 struct sk_buff *skb,
165 enum hsr_dev_idx dev_idx)
166{
167 struct hsr_sup_payload *hsr_sp;
168 struct hsr_ethhdr_sp *hsr_ethsup;
169 int i;
170 unsigned long now;
171
172 hsr_ethsup = (struct hsr_ethhdr_sp *) skb_mac_header(skb);
173 hsr_sp = (struct hsr_sup_payload *) skb->data;
174
175 if (node && !ether_addr_equal(node->MacAddressA, hsr_sp->MacAddressA)) {
176 /* Node has changed its AddrA, frame was received from SlaveB */
177 list_del_rcu(&node->mac_list);
178 call_rcu(&node->rcu_head, node_entry_reclaim);
179 node = NULL;
180 }
181
182 if (node && (dev_idx == node->AddrB_if) &&
183 !ether_addr_equal(node->MacAddressB, hsr_ethsup->ethhdr.h_source)) {
184 /* Cables have been swapped */
185 list_del_rcu(&node->mac_list);
186 call_rcu(&node->rcu_head, node_entry_reclaim);
187 node = NULL;
188 }
189
190 if (node && (dev_idx != node->AddrB_if) &&
191 (node->AddrB_if != HSR_DEV_NONE) &&
192 !ether_addr_equal(node->MacAddressA, hsr_ethsup->ethhdr.h_source)) {
193 /* Cables have been swapped */
194 list_del_rcu(&node->mac_list);
195 call_rcu(&node->rcu_head, node_entry_reclaim);
196 node = NULL;
197 }
198
199 if (node)
200 return node;
201
202 node = find_node_by_AddrA(&hsr_priv->node_db, hsr_sp->MacAddressA);
203 if (node) {
204 /* Node is known, but frame was received from an unknown
205 * address. Node is PICS_SUBS capable; merge its AddrB.
206 */
207 memcpy(node->MacAddressB, hsr_ethsup->ethhdr.h_source, ETH_ALEN);
208 node->AddrB_if = dev_idx;
209 return node;
210 }
211
212 node = kzalloc(sizeof(*node), GFP_ATOMIC);
213 if (!node)
214 return NULL;
215
216 memcpy(node->MacAddressA, hsr_sp->MacAddressA, ETH_ALEN);
217 memcpy(node->MacAddressB, hsr_ethsup->ethhdr.h_source, ETH_ALEN);
218 if (!ether_addr_equal(hsr_sp->MacAddressA, hsr_ethsup->ethhdr.h_source))
219 node->AddrB_if = dev_idx;
220 else
221 node->AddrB_if = HSR_DEV_NONE;
222
223 /* We are only interested in time diffs here, so use current jiffies
224 * as initialization. (0 could trigger an spurious ring error warning).
225 */
226 now = jiffies;
227 for (i = 0; i < HSR_MAX_SLAVE; i++)
228 node->time_in[i] = now;
229 for (i = 0; i < HSR_MAX_DEV; i++)
230 node->seq_out[i] = ntohs(hsr_ethsup->hsr_sup.sequence_nr) - 1;
231
232 list_add_tail_rcu(&node->mac_list, &hsr_priv->node_db);
233
234 return node;
235}
236
237
238/* 'skb' is a frame meant for this host, that is to be passed to upper layers.
239 *
240 * If the frame was sent by a node's B interface, replace the sender
241 * address with that node's "official" address (MacAddressA) so that upper
242 * layers recognize where it came from.
243 */
244void hsr_addr_subst_source(struct hsr_priv *hsr_priv, struct sk_buff *skb)
245{
246 struct ethhdr *ethhdr;
247 struct node_entry *node;
248
249 if (!skb_mac_header_was_set(skb)) {
250 WARN_ONCE(1, "%s: Mac header not set\n", __func__);
251 return;
252 }
253 ethhdr = (struct ethhdr *) skb_mac_header(skb);
254
255 rcu_read_lock();
256 node = find_node_by_AddrB(&hsr_priv->node_db, ethhdr->h_source);
257 if (node)
258 memcpy(ethhdr->h_source, node->MacAddressA, ETH_ALEN);
259 rcu_read_unlock();
260}
261
262
263/* 'skb' is a frame meant for another host.
264 * 'hsr_dev_idx' is the HSR index of the outgoing device
265 *
266 * Substitute the target (dest) MAC address if necessary, so the it matches the
267 * recipient interface MAC address, regardless of whether that is the
268 * recipient's A or B interface.
269 * This is needed to keep the packets flowing through switches that learn on
270 * which "side" the different interfaces are.
271 */
272void hsr_addr_subst_dest(struct hsr_priv *hsr_priv, struct ethhdr *ethhdr,
273 enum hsr_dev_idx dev_idx)
274{
275 struct node_entry *node;
276
277 rcu_read_lock();
278 node = find_node_by_AddrA(&hsr_priv->node_db, ethhdr->h_dest);
279 if (node && (node->AddrB_if == dev_idx))
280 memcpy(ethhdr->h_dest, node->MacAddressB, ETH_ALEN);
281 rcu_read_unlock();
282}
283
284
285/* seq_nr_after(a, b) - return true if a is after (higher in sequence than) b,
286 * false otherwise.
287 */
288static bool seq_nr_after(u16 a, u16 b)
289{
290 /* Remove inconsistency where
291 * seq_nr_after(a, b) == seq_nr_before(a, b) */
292 if ((int) b - a == 32768)
293 return false;
294
295 return (((s16) (b - a)) < 0);
296}
297#define seq_nr_before(a, b) seq_nr_after((b), (a))
298#define seq_nr_after_or_eq(a, b) (!seq_nr_before((a), (b)))
299#define seq_nr_before_or_eq(a, b) (!seq_nr_after((a), (b)))
300
301
302void hsr_register_frame_in(struct node_entry *node, enum hsr_dev_idx dev_idx)
303{
304 if ((dev_idx < 0) || (dev_idx >= HSR_MAX_DEV)) {
305 WARN_ONCE(1, "%s: Invalid dev_idx (%d)\n", __func__, dev_idx);
306 return;
307 }
308 node->time_in[dev_idx] = jiffies;
309 node->time_in_stale[dev_idx] = false;
310}
311
312
313/* 'skb' is a HSR Ethernet frame (with a HSR tag inserted), with a valid
314 * ethhdr->h_source address and skb->mac_header set.
315 *
316 * Return:
317 * 1 if frame can be shown to have been sent recently on this interface,
318 * 0 otherwise, or
319 * negative error code on error
320 */
321int hsr_register_frame_out(struct node_entry *node, enum hsr_dev_idx dev_idx,
322 struct sk_buff *skb)
323{
324 struct hsr_ethhdr *hsr_ethhdr;
325 u16 sequence_nr;
326
327 if ((dev_idx < 0) || (dev_idx >= HSR_MAX_DEV)) {
328 WARN_ONCE(1, "%s: Invalid dev_idx (%d)\n", __func__, dev_idx);
329 return -EINVAL;
330 }
331 if (!skb_mac_header_was_set(skb)) {
332 WARN_ONCE(1, "%s: Mac header not set\n", __func__);
333 return -EINVAL;
334 }
335 hsr_ethhdr = (struct hsr_ethhdr *) skb_mac_header(skb);
336
337 sequence_nr = ntohs(hsr_ethhdr->hsr_tag.sequence_nr);
338 if (seq_nr_before_or_eq(sequence_nr, node->seq_out[dev_idx]))
339 return 1;
340
341 node->seq_out[dev_idx] = sequence_nr;
342 return 0;
343}
344
345
346
347static bool is_late(struct node_entry *node, enum hsr_dev_idx dev_idx)
348{
349 enum hsr_dev_idx other;
350
351 if (node->time_in_stale[dev_idx])
352 return true;
353
354 if (dev_idx == HSR_DEV_SLAVE_A)
355 other = HSR_DEV_SLAVE_B;
356 else
357 other = HSR_DEV_SLAVE_A;
358
359 if (node->time_in_stale[other])
360 return false;
361
362 if (time_after(node->time_in[other], node->time_in[dev_idx] +
363 msecs_to_jiffies(MAX_SLAVE_DIFF)))
364 return true;
365
366 return false;
367}
368
369
370/* Remove stale sequence_nr records. Called by timer every
371 * HSR_LIFE_CHECK_INTERVAL (two seconds or so).
372 */
373void hsr_prune_nodes(struct hsr_priv *hsr_priv)
374{
375 struct node_entry *node;
376 unsigned long timestamp;
377 unsigned long time_a, time_b;
378
379 rcu_read_lock();
380 list_for_each_entry_rcu(node, &hsr_priv->node_db, mac_list) {
381 /* Shorthand */
382 time_a = node->time_in[HSR_DEV_SLAVE_A];
383 time_b = node->time_in[HSR_DEV_SLAVE_B];
384
385 /* Check for timestamps old enough to risk wrap-around */
386 if (time_after(jiffies, time_a + MAX_JIFFY_OFFSET/2))
387 node->time_in_stale[HSR_DEV_SLAVE_A] = true;
388 if (time_after(jiffies, time_b + MAX_JIFFY_OFFSET/2))
389 node->time_in_stale[HSR_DEV_SLAVE_B] = true;
390
391 /* Get age of newest frame from node.
392 * At least one time_in is OK here; nodes get pruned long
393 * before both time_ins can get stale
394 */
395 timestamp = time_a;
396 if (node->time_in_stale[HSR_DEV_SLAVE_A] ||
397 (!node->time_in_stale[HSR_DEV_SLAVE_B] &&
398 time_after(time_b, time_a)))
399 timestamp = time_b;
400
401 /* Warn of ring error only as long as we get frames at all */
402 if (time_is_after_jiffies(timestamp +
403 msecs_to_jiffies(1.5*MAX_SLAVE_DIFF))) {
404
405 if (is_late(node, HSR_DEV_SLAVE_A))
406 hsr_nl_ringerror(hsr_priv, node->MacAddressA,
407 HSR_DEV_SLAVE_A);
408 else if (is_late(node, HSR_DEV_SLAVE_B))
409 hsr_nl_ringerror(hsr_priv, node->MacAddressA,
410 HSR_DEV_SLAVE_B);
411 }
412
413 /* Prune old entries */
414 if (time_is_before_jiffies(timestamp +
415 msecs_to_jiffies(HSR_NODE_FORGET_TIME))) {
416 hsr_nl_nodedown(hsr_priv, node->MacAddressA);
417 list_del_rcu(&node->mac_list);
418 /* Note that we need to free this entry later: */
419 call_rcu(&node->rcu_head, node_entry_reclaim);
420 }
421 }
422 rcu_read_unlock();
423}
424
425
426void *hsr_get_next_node(struct hsr_priv *hsr_priv, void *_pos,
427 unsigned char addr[ETH_ALEN])
428{
429 struct node_entry *node;
430
431 if (!_pos) {
432 node = list_first_or_null_rcu(&hsr_priv->node_db,
433 struct node_entry, mac_list);
434 if (node)
435 memcpy(addr, node->MacAddressA, ETH_ALEN);
436 return node;
437 }
438
439 node = _pos;
440 list_for_each_entry_continue_rcu(node, &hsr_priv->node_db, mac_list) {
441 memcpy(addr, node->MacAddressA, ETH_ALEN);
442 return node;
443 }
444
445 return NULL;
446}
447
448
449int hsr_get_node_data(struct hsr_priv *hsr_priv,
450 const unsigned char *addr,
451 unsigned char addr_b[ETH_ALEN],
452 unsigned int *addr_b_ifindex,
453 int *if1_age,
454 u16 *if1_seq,
455 int *if2_age,
456 u16 *if2_seq)
457{
458 struct node_entry *node;
459 unsigned long tdiff;
460
461
462 rcu_read_lock();
463 node = find_node_by_AddrA(&hsr_priv->node_db, addr);
464 if (!node) {
465 rcu_read_unlock();
466 return -ENOENT; /* No such entry */
467 }
468
469 memcpy(addr_b, node->MacAddressB, ETH_ALEN);
470
471 tdiff = jiffies - node->time_in[HSR_DEV_SLAVE_A];
472 if (node->time_in_stale[HSR_DEV_SLAVE_A])
473 *if1_age = INT_MAX;
474#if HZ <= MSEC_PER_SEC
475 else if (tdiff > msecs_to_jiffies(INT_MAX))
476 *if1_age = INT_MAX;
477#endif
478 else
479 *if1_age = jiffies_to_msecs(tdiff);
480
481 tdiff = jiffies - node->time_in[HSR_DEV_SLAVE_B];
482 if (node->time_in_stale[HSR_DEV_SLAVE_B])
483 *if2_age = INT_MAX;
484#if HZ <= MSEC_PER_SEC
485 else if (tdiff > msecs_to_jiffies(INT_MAX))
486 *if2_age = INT_MAX;
487#endif
488 else
489 *if2_age = jiffies_to_msecs(tdiff);
490
491 /* Present sequence numbers as if they were incoming on interface */
492 *if1_seq = node->seq_out[HSR_DEV_SLAVE_B];
493 *if2_seq = node->seq_out[HSR_DEV_SLAVE_A];
494
495 if ((node->AddrB_if != HSR_DEV_NONE) && hsr_priv->slave[node->AddrB_if])
496 *addr_b_ifindex = hsr_priv->slave[node->AddrB_if]->ifindex;
497 else
498 *addr_b_ifindex = -1;
499
500 rcu_read_unlock();
501
502 return 0;
503}
diff --git a/net/hsr/hsr_framereg.h b/net/hsr/hsr_framereg.h
new file mode 100644
index 000000000000..e6c4022030ad
--- /dev/null
+++ b/net/hsr/hsr_framereg.h
@@ -0,0 +1,53 @@
1/* Copyright 2011-2013 Autronica Fire and Security AS
2 *
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
5 * Software Foundation; either version 2 of the License, or (at your option)
6 * any later version.
7 *
8 * Author(s):
9 * 2011-2013 Arvid Brodin, arvid.brodin@xdin.com
10 */
11
12#ifndef _HSR_FRAMEREG_H
13#define _HSR_FRAMEREG_H
14
15#include "hsr_main.h"
16
17struct node_entry;
18
19struct node_entry *hsr_find_node(struct list_head *node_db, struct sk_buff *skb);
20
21struct node_entry *hsr_merge_node(struct hsr_priv *hsr_priv,
22 struct node_entry *node,
23 struct sk_buff *skb,
24 enum hsr_dev_idx dev_idx);
25
26void hsr_addr_subst_source(struct hsr_priv *hsr_priv, struct sk_buff *skb);
27void hsr_addr_subst_dest(struct hsr_priv *hsr_priv, struct ethhdr *ethhdr,
28 enum hsr_dev_idx dev_idx);
29
30void hsr_register_frame_in(struct node_entry *node, enum hsr_dev_idx dev_idx);
31
32int hsr_register_frame_out(struct node_entry *node, enum hsr_dev_idx dev_idx,
33 struct sk_buff *skb);
34
35void hsr_prune_nodes(struct hsr_priv *hsr_priv);
36
37int hsr_create_self_node(struct list_head *self_node_db,
38 unsigned char addr_a[ETH_ALEN],
39 unsigned char addr_b[ETH_ALEN]);
40
41void *hsr_get_next_node(struct hsr_priv *hsr_priv, void *_pos,
42 unsigned char addr[ETH_ALEN]);
43
44int hsr_get_node_data(struct hsr_priv *hsr_priv,
45 const unsigned char *addr,
46 unsigned char addr_b[ETH_ALEN],
47 unsigned int *addr_b_ifindex,
48 int *if1_age,
49 u16 *if1_seq,
50 int *if2_age,
51 u16 *if2_seq);
52
53#endif /* _HSR_FRAMEREG_H */
diff --git a/net/hsr/hsr_main.c b/net/hsr/hsr_main.c
new file mode 100644
index 000000000000..af68dd83a4e3
--- /dev/null
+++ b/net/hsr/hsr_main.c
@@ -0,0 +1,469 @@
1/* Copyright 2011-2013 Autronica Fire and Security AS
2 *
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
5 * Software Foundation; either version 2 of the License, or (at your option)
6 * any later version.
7 *
8 * Author(s):
9 * 2011-2013 Arvid Brodin, arvid.brodin@xdin.com
10 *
11 * In addition to routines for registering and unregistering HSR support, this
12 * file also contains the receive routine that handles all incoming frames with
13 * Ethertype (protocol) ETH_P_PRP (HSRv0), and network device event handling.
14 */
15
16#include <linux/netdevice.h>
17#include <linux/rculist.h>
18#include <linux/timer.h>
19#include <linux/etherdevice.h>
20#include "hsr_main.h"
21#include "hsr_device.h"
22#include "hsr_netlink.h"
23#include "hsr_framereg.h"
24
25
26/* List of all registered virtual HSR devices */
27static LIST_HEAD(hsr_list);
28
29void register_hsr_master(struct hsr_priv *hsr_priv)
30{
31 list_add_tail_rcu(&hsr_priv->hsr_list, &hsr_list);
32}
33
34void unregister_hsr_master(struct hsr_priv *hsr_priv)
35{
36 struct hsr_priv *hsr_priv_it;
37
38 list_for_each_entry(hsr_priv_it, &hsr_list, hsr_list)
39 if (hsr_priv_it == hsr_priv) {
40 list_del_rcu(&hsr_priv_it->hsr_list);
41 return;
42 }
43}
44
45bool is_hsr_slave(struct net_device *dev)
46{
47 struct hsr_priv *hsr_priv_it;
48
49 list_for_each_entry_rcu(hsr_priv_it, &hsr_list, hsr_list) {
50 if (dev == hsr_priv_it->slave[0])
51 return true;
52 if (dev == hsr_priv_it->slave[1])
53 return true;
54 }
55
56 return false;
57}
58
59
60/* If dev is a HSR slave device, return the virtual master device. Return NULL
61 * otherwise.
62 */
63static struct hsr_priv *get_hsr_master(struct net_device *dev)
64{
65 struct hsr_priv *hsr_priv;
66
67 rcu_read_lock();
68 list_for_each_entry_rcu(hsr_priv, &hsr_list, hsr_list)
69 if ((dev == hsr_priv->slave[0]) ||
70 (dev == hsr_priv->slave[1])) {
71 rcu_read_unlock();
72 return hsr_priv;
73 }
74
75 rcu_read_unlock();
76 return NULL;
77}
78
79
80/* If dev is a HSR slave device, return the other slave device. Return NULL
81 * otherwise.
82 */
83static struct net_device *get_other_slave(struct hsr_priv *hsr_priv,
84 struct net_device *dev)
85{
86 if (dev == hsr_priv->slave[0])
87 return hsr_priv->slave[1];
88 if (dev == hsr_priv->slave[1])
89 return hsr_priv->slave[0];
90
91 return NULL;
92}
93
94
95static int hsr_netdev_notify(struct notifier_block *nb, unsigned long event,
96 void *ptr)
97{
98 struct net_device *slave, *other_slave;
99 struct hsr_priv *hsr_priv;
100 int old_operstate;
101 int mtu_max;
102 int res;
103 struct net_device *dev;
104
105 dev = netdev_notifier_info_to_dev(ptr);
106
107 hsr_priv = get_hsr_master(dev);
108 if (hsr_priv) {
109 /* dev is a slave device */
110 slave = dev;
111 other_slave = get_other_slave(hsr_priv, slave);
112 } else {
113 if (!is_hsr_master(dev))
114 return NOTIFY_DONE;
115 hsr_priv = netdev_priv(dev);
116 slave = hsr_priv->slave[0];
117 other_slave = hsr_priv->slave[1];
118 }
119
120 switch (event) {
121 case NETDEV_UP: /* Administrative state DOWN */
122 case NETDEV_DOWN: /* Administrative state UP */
123 case NETDEV_CHANGE: /* Link (carrier) state changes */
124 old_operstate = hsr_priv->dev->operstate;
125 hsr_set_carrier(hsr_priv->dev, slave, other_slave);
126 /* netif_stacked_transfer_operstate() cannot be used here since
127 * it doesn't set IF_OPER_LOWERLAYERDOWN (?)
128 */
129 hsr_set_operstate(hsr_priv->dev, slave, other_slave);
130 hsr_check_announce(hsr_priv->dev, old_operstate);
131 break;
132 case NETDEV_CHANGEADDR:
133
134 /* This should not happen since there's no ndo_set_mac_address()
135 * for HSR devices - i.e. not supported.
136 */
137 if (dev == hsr_priv->dev)
138 break;
139
140 if (dev == hsr_priv->slave[0])
141 memcpy(hsr_priv->dev->dev_addr,
142 hsr_priv->slave[0]->dev_addr, ETH_ALEN);
143
144 /* Make sure we recognize frames from ourselves in hsr_rcv() */
145 res = hsr_create_self_node(&hsr_priv->self_node_db,
146 hsr_priv->dev->dev_addr,
147 hsr_priv->slave[1] ?
148 hsr_priv->slave[1]->dev_addr :
149 hsr_priv->dev->dev_addr);
150 if (res)
151 netdev_warn(hsr_priv->dev,
152 "Could not update HSR node address.\n");
153
154 if (dev == hsr_priv->slave[0])
155 call_netdevice_notifiers(NETDEV_CHANGEADDR, hsr_priv->dev);
156 break;
157 case NETDEV_CHANGEMTU:
158 if (dev == hsr_priv->dev)
159 break; /* Handled in ndo_change_mtu() */
160 mtu_max = hsr_get_max_mtu(hsr_priv);
161 if (hsr_priv->dev->mtu > mtu_max)
162 dev_set_mtu(hsr_priv->dev, mtu_max);
163 break;
164 case NETDEV_UNREGISTER:
165 if (dev == hsr_priv->slave[0])
166 hsr_priv->slave[0] = NULL;
167 if (dev == hsr_priv->slave[1])
168 hsr_priv->slave[1] = NULL;
169
170 /* There should really be a way to set a new slave device... */
171
172 break;
173 case NETDEV_PRE_TYPE_CHANGE:
174 /* HSR works only on Ethernet devices. Refuse slave to change
175 * its type.
176 */
177 return NOTIFY_BAD;
178 }
179
180 return NOTIFY_DONE;
181}
182
183
184static struct timer_list prune_timer;
185
186static void prune_nodes_all(unsigned long data)
187{
188 struct hsr_priv *hsr_priv;
189
190 rcu_read_lock();
191 list_for_each_entry_rcu(hsr_priv, &hsr_list, hsr_list)
192 hsr_prune_nodes(hsr_priv);
193 rcu_read_unlock();
194
195 prune_timer.expires = jiffies + msecs_to_jiffies(PRUNE_PERIOD);
196 add_timer(&prune_timer);
197}
198
199
200static struct sk_buff *hsr_pull_tag(struct sk_buff *skb)
201{
202 struct hsr_tag *hsr_tag;
203 struct sk_buff *skb2;
204
205 skb2 = skb_share_check(skb, GFP_ATOMIC);
206 if (unlikely(!skb2))
207 goto err_free;
208 skb = skb2;
209
210 if (unlikely(!pskb_may_pull(skb, HSR_TAGLEN)))
211 goto err_free;
212
213 hsr_tag = (struct hsr_tag *) skb->data;
214 skb->protocol = hsr_tag->encap_proto;
215 skb_pull(skb, HSR_TAGLEN);
216
217 return skb;
218
219err_free:
220 kfree_skb(skb);
221 return NULL;
222}
223
224
225/* The uses I can see for these HSR supervision frames are:
226 * 1) Use the frames that are sent after node initialization ("HSR_TLV.Type =
227 * 22") to reset any sequence_nr counters belonging to that node. Useful if
228 * the other node's counter has been reset for some reason.
229 * --
230 * Or not - resetting the counter and bridging the frame would create a
231 * loop, unfortunately.
232 *
233 * 2) Use the LifeCheck frames to detect ring breaks. I.e. if no LifeCheck
234 * frame is received from a particular node, we know something is wrong.
235 * We just register these (as with normal frames) and throw them away.
236 *
237 * 3) Allow different MAC addresses for the two slave interfaces, using the
238 * MacAddressA field.
239 */
240static bool is_supervision_frame(struct hsr_priv *hsr_priv, struct sk_buff *skb)
241{
242 struct hsr_sup_tag *hsr_stag;
243
244 if (!ether_addr_equal(eth_hdr(skb)->h_dest,
245 hsr_priv->sup_multicast_addr))
246 return false;
247
248 hsr_stag = (struct hsr_sup_tag *) skb->data;
249 if (get_hsr_stag_path(hsr_stag) != 0x0f)
250 return false;
251 if ((hsr_stag->HSR_TLV_Type != HSR_TLV_ANNOUNCE) &&
252 (hsr_stag->HSR_TLV_Type != HSR_TLV_LIFE_CHECK))
253 return false;
254 if (hsr_stag->HSR_TLV_Length != 12)
255 return false;
256
257 return true;
258}
259
260
261/* Implementation somewhat according to IEC-62439-3, p. 43
262 */
263static int hsr_rcv(struct sk_buff *skb, struct net_device *dev,
264 struct packet_type *pt, struct net_device *orig_dev)
265{
266 struct hsr_priv *hsr_priv;
267 struct net_device *other_slave;
268 struct node_entry *node;
269 bool deliver_to_self;
270 struct sk_buff *skb_deliver;
271 enum hsr_dev_idx dev_in_idx, dev_other_idx;
272 bool dup_out;
273 int ret;
274
275 hsr_priv = get_hsr_master(dev);
276
277 if (!hsr_priv) {
278 /* Non-HSR-slave device 'dev' is connected to a HSR network */
279 kfree_skb(skb);
280 dev->stats.rx_errors++;
281 return NET_RX_SUCCESS;
282 }
283
284 if (dev == hsr_priv->slave[0]) {
285 dev_in_idx = HSR_DEV_SLAVE_A;
286 dev_other_idx = HSR_DEV_SLAVE_B;
287 } else {
288 dev_in_idx = HSR_DEV_SLAVE_B;
289 dev_other_idx = HSR_DEV_SLAVE_A;
290 }
291
292 node = hsr_find_node(&hsr_priv->self_node_db, skb);
293 if (node) {
294 /* Always kill frames sent by ourselves */
295 kfree_skb(skb);
296 return NET_RX_SUCCESS;
297 }
298
299 /* Is this frame a candidate for local reception? */
300 deliver_to_self = false;
301 if ((skb->pkt_type == PACKET_HOST) ||
302 (skb->pkt_type == PACKET_MULTICAST) ||
303 (skb->pkt_type == PACKET_BROADCAST))
304 deliver_to_self = true;
305 else if (ether_addr_equal(eth_hdr(skb)->h_dest,
306 hsr_priv->dev->dev_addr)) {
307 skb->pkt_type = PACKET_HOST;
308 deliver_to_self = true;
309 }
310
311
312 rcu_read_lock(); /* node_db */
313 node = hsr_find_node(&hsr_priv->node_db, skb);
314
315 if (is_supervision_frame(hsr_priv, skb)) {
316 skb_pull(skb, sizeof(struct hsr_sup_tag));
317 node = hsr_merge_node(hsr_priv, node, skb, dev_in_idx);
318 if (!node) {
319 rcu_read_unlock(); /* node_db */
320 kfree_skb(skb);
321 hsr_priv->dev->stats.rx_dropped++;
322 return NET_RX_DROP;
323 }
324 skb_push(skb, sizeof(struct hsr_sup_tag));
325 deliver_to_self = false;
326 }
327
328 if (!node) {
329 /* Source node unknown; this might be a HSR frame from
330 * another net (different multicast address). Ignore it.
331 */
332 rcu_read_unlock(); /* node_db */
333 kfree_skb(skb);
334 return NET_RX_SUCCESS;
335 }
336
337 /* Register ALL incoming frames as outgoing through the other interface.
338 * This allows us to register frames as incoming only if they are valid
339 * for the receiving interface, without using a specific counter for
340 * incoming frames.
341 */
342 dup_out = hsr_register_frame_out(node, dev_other_idx, skb);
343 if (!dup_out)
344 hsr_register_frame_in(node, dev_in_idx);
345
346 /* Forward this frame? */
347 if (!dup_out && (skb->pkt_type != PACKET_HOST))
348 other_slave = get_other_slave(hsr_priv, dev);
349 else
350 other_slave = NULL;
351
352 if (hsr_register_frame_out(node, HSR_DEV_MASTER, skb))
353 deliver_to_self = false;
354
355 rcu_read_unlock(); /* node_db */
356
357 if (!deliver_to_self && !other_slave) {
358 kfree_skb(skb);
359 /* Circulated frame; silently remove it. */
360 return NET_RX_SUCCESS;
361 }
362
363 skb_deliver = skb;
364 if (deliver_to_self && other_slave) {
365 /* skb_clone() is not enough since we will strip the hsr tag
366 * and do address substitution below
367 */
368 skb_deliver = pskb_copy(skb, GFP_ATOMIC);
369 if (!skb_deliver) {
370 deliver_to_self = false;
371 hsr_priv->dev->stats.rx_dropped++;
372 }
373 }
374
375 if (deliver_to_self) {
376 bool multicast_frame;
377
378 skb_deliver = hsr_pull_tag(skb_deliver);
379 if (!skb_deliver) {
380 hsr_priv->dev->stats.rx_dropped++;
381 goto forward;
382 }
383#if !defined(CONFIG_HAVE_EFFICIENT_UNALIGNED_ACCESS)
384 /* Move everything in the header that is after the HSR tag,
385 * to work around alignment problems caused by the 6-byte HSR
386 * tag. In practice, this removes/overwrites the HSR tag in
387 * the header and restores a "standard" packet.
388 */
389 memmove(skb_deliver->data - HSR_TAGLEN, skb_deliver->data,
390 skb_headlen(skb_deliver));
391
392 /* Adjust skb members so they correspond with the move above.
393 * This cannot possibly underflow skb->data since hsr_pull_tag()
394 * above succeeded.
395 * At this point in the protocol stack, the transport and
396 * network headers have not been set yet, and we haven't touched
397 * the mac header nor the head. So we only need to adjust data
398 * and tail:
399 */
400 skb_deliver->data -= HSR_TAGLEN;
401 skb_deliver->tail -= HSR_TAGLEN;
402#endif
403 skb_deliver->dev = hsr_priv->dev;
404 hsr_addr_subst_source(hsr_priv, skb_deliver);
405 multicast_frame = (skb_deliver->pkt_type == PACKET_MULTICAST);
406 ret = netif_rx(skb_deliver);
407 if (ret == NET_RX_DROP) {
408 hsr_priv->dev->stats.rx_dropped++;
409 } else {
410 hsr_priv->dev->stats.rx_packets++;
411 hsr_priv->dev->stats.rx_bytes += skb->len;
412 if (multicast_frame)
413 hsr_priv->dev->stats.multicast++;
414 }
415 }
416
417forward:
418 if (other_slave) {
419 skb_push(skb, ETH_HLEN);
420 skb->dev = other_slave;
421 dev_queue_xmit(skb);
422 }
423
424 return NET_RX_SUCCESS;
425}
426
427
428static struct packet_type hsr_pt __read_mostly = {
429 .type = htons(ETH_P_PRP),
430 .func = hsr_rcv,
431};
432
433static struct notifier_block hsr_nb = {
434 .notifier_call = hsr_netdev_notify, /* Slave event notifications */
435};
436
437
438static int __init hsr_init(void)
439{
440 int res;
441
442 BUILD_BUG_ON(sizeof(struct hsr_tag) != HSR_TAGLEN);
443
444 dev_add_pack(&hsr_pt);
445
446 init_timer(&prune_timer);
447 prune_timer.function = prune_nodes_all;
448 prune_timer.data = 0;
449 prune_timer.expires = jiffies + msecs_to_jiffies(PRUNE_PERIOD);
450 add_timer(&prune_timer);
451
452 register_netdevice_notifier(&hsr_nb);
453
454 res = hsr_netlink_init();
455
456 return res;
457}
458
459static void __exit hsr_exit(void)
460{
461 unregister_netdevice_notifier(&hsr_nb);
462 del_timer(&prune_timer);
463 hsr_netlink_exit();
464 dev_remove_pack(&hsr_pt);
465}
466
467module_init(hsr_init);
468module_exit(hsr_exit);
469MODULE_LICENSE("GPL");
diff --git a/net/hsr/hsr_main.h b/net/hsr/hsr_main.h
new file mode 100644
index 000000000000..56fe060c0ab1
--- /dev/null
+++ b/net/hsr/hsr_main.h
@@ -0,0 +1,166 @@
1/* Copyright 2011-2013 Autronica Fire and Security AS
2 *
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
5 * Software Foundation; either version 2 of the License, or (at your option)
6 * any later version.
7 *
8 * Author(s):
9 * 2011-2013 Arvid Brodin, arvid.brodin@xdin.com
10 */
11
12#ifndef _HSR_PRIVATE_H
13#define _HSR_PRIVATE_H
14
15#include <linux/netdevice.h>
16#include <linux/list.h>
17
18
19/* Time constants as specified in the HSR specification (IEC-62439-3 2010)
20 * Table 8.
21 * All values in milliseconds.
22 */
23#define HSR_LIFE_CHECK_INTERVAL 2000 /* ms */
24#define HSR_NODE_FORGET_TIME 60000 /* ms */
25#define HSR_ANNOUNCE_INTERVAL 100 /* ms */
26
27
28/* By how much may slave1 and slave2 timestamps of latest received frame from
29 * each node differ before we notify of communication problem?
30 */
31#define MAX_SLAVE_DIFF 3000 /* ms */
32
33
34/* How often shall we check for broken ring and remove node entries older than
35 * HSR_NODE_FORGET_TIME?
36 */
37#define PRUNE_PERIOD 3000 /* ms */
38
39
40#define HSR_TLV_ANNOUNCE 22
41#define HSR_TLV_LIFE_CHECK 23
42
43
44/* HSR Tag.
45 * As defined in IEC-62439-3:2010, the HSR tag is really { ethertype = 0x88FB,
46 * path, LSDU_size, sequence Nr }. But we let eth_header() create { h_dest,
47 * h_source, h_proto = 0x88FB }, and add { path, LSDU_size, sequence Nr,
48 * encapsulated protocol } instead.
49 */
50#define HSR_TAGLEN 6
51
52/* Field names below as defined in the IEC:2010 standard for HSR. */
53struct hsr_tag {
54 __be16 path_and_LSDU_size;
55 __be16 sequence_nr;
56 __be16 encap_proto;
57} __packed;
58
59
60/* The helper functions below assumes that 'path' occupies the 4 most
61 * significant bits of the 16-bit field shared by 'path' and 'LSDU_size' (or
62 * equivalently, the 4 most significant bits of HSR tag byte 14).
63 *
64 * This is unclear in the IEC specification; its definition of MAC addresses
65 * indicates the spec is written with the least significant bit first (to the
66 * left). This, however, would mean that the LSDU field would be split in two
67 * with the path field in-between, which seems strange. I'm guessing the MAC
68 * address definition is in error.
69 */
70static inline u16 get_hsr_tag_path(struct hsr_tag *ht)
71{
72 return ntohs(ht->path_and_LSDU_size) >> 12;
73}
74
75static inline u16 get_hsr_tag_LSDU_size(struct hsr_tag *ht)
76{
77 return ntohs(ht->path_and_LSDU_size) & 0x0FFF;
78}
79
80static inline void set_hsr_tag_path(struct hsr_tag *ht, u16 path)
81{
82 ht->path_and_LSDU_size = htons(
83 (ntohs(ht->path_and_LSDU_size) & 0x0FFF) | (path << 12));
84}
85
86static inline void set_hsr_tag_LSDU_size(struct hsr_tag *ht, u16 LSDU_size)
87{
88 ht->path_and_LSDU_size = htons(
89 (ntohs(ht->path_and_LSDU_size) & 0xF000) |
90 (LSDU_size & 0x0FFF));
91}
92
93struct hsr_ethhdr {
94 struct ethhdr ethhdr;
95 struct hsr_tag hsr_tag;
96} __packed;
97
98
99/* HSR Supervision Frame data types.
100 * Field names as defined in the IEC:2010 standard for HSR.
101 */
102struct hsr_sup_tag {
103 __be16 path_and_HSR_Ver;
104 __be16 sequence_nr;
105 __u8 HSR_TLV_Type;
106 __u8 HSR_TLV_Length;
107} __packed;
108
109struct hsr_sup_payload {
110 unsigned char MacAddressA[ETH_ALEN];
111} __packed;
112
113static inline u16 get_hsr_stag_path(struct hsr_sup_tag *hst)
114{
115 return get_hsr_tag_path((struct hsr_tag *) hst);
116}
117
118static inline u16 get_hsr_stag_HSR_ver(struct hsr_sup_tag *hst)
119{
120 return get_hsr_tag_LSDU_size((struct hsr_tag *) hst);
121}
122
123static inline void set_hsr_stag_path(struct hsr_sup_tag *hst, u16 path)
124{
125 set_hsr_tag_path((struct hsr_tag *) hst, path);
126}
127
128static inline void set_hsr_stag_HSR_Ver(struct hsr_sup_tag *hst, u16 HSR_Ver)
129{
130 set_hsr_tag_LSDU_size((struct hsr_tag *) hst, HSR_Ver);
131}
132
133struct hsr_ethhdr_sp {
134 struct ethhdr ethhdr;
135 struct hsr_sup_tag hsr_sup;
136} __packed;
137
138
139enum hsr_dev_idx {
140 HSR_DEV_NONE = -1,
141 HSR_DEV_SLAVE_A = 0,
142 HSR_DEV_SLAVE_B,
143 HSR_DEV_MASTER,
144};
145#define HSR_MAX_SLAVE (HSR_DEV_SLAVE_B + 1)
146#define HSR_MAX_DEV (HSR_DEV_MASTER + 1)
147
148struct hsr_priv {
149 struct list_head hsr_list; /* List of hsr devices */
150 struct rcu_head rcu_head;
151 struct net_device *dev;
152 struct net_device *slave[HSR_MAX_SLAVE];
153 struct list_head node_db; /* Other HSR nodes */
154 struct list_head self_node_db; /* MACs of slaves */
155 struct timer_list announce_timer; /* Supervision frame dispatch */
156 int announce_count;
157 u16 sequence_nr;
158 spinlock_t seqnr_lock; /* locking for sequence_nr */
159 unsigned char sup_multicast_addr[ETH_ALEN];
160};
161
162void register_hsr_master(struct hsr_priv *hsr_priv);
163void unregister_hsr_master(struct hsr_priv *hsr_priv);
164bool is_hsr_slave(struct net_device *dev);
165
166#endif /* _HSR_PRIVATE_H */
diff --git a/net/hsr/hsr_netlink.c b/net/hsr/hsr_netlink.c
new file mode 100644
index 000000000000..4e66bf61f585
--- /dev/null
+++ b/net/hsr/hsr_netlink.c
@@ -0,0 +1,457 @@
1/* Copyright 2011-2013 Autronica Fire and Security AS
2 *
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
5 * Software Foundation; either version 2 of the License, or (at your option)
6 * any later version.
7 *
8 * Author(s):
9 * 2011-2013 Arvid Brodin, arvid.brodin@xdin.com
10 *
11 * Routines for handling Netlink messages for HSR.
12 */
13
14#include "hsr_netlink.h"
15#include <linux/kernel.h>
16#include <net/rtnetlink.h>
17#include <net/genetlink.h>
18#include "hsr_main.h"
19#include "hsr_device.h"
20#include "hsr_framereg.h"
21
22static const struct nla_policy hsr_policy[IFLA_HSR_MAX + 1] = {
23 [IFLA_HSR_SLAVE1] = { .type = NLA_U32 },
24 [IFLA_HSR_SLAVE2] = { .type = NLA_U32 },
25 [IFLA_HSR_MULTICAST_SPEC] = { .type = NLA_U8 },
26};
27
28
29/* Here, it seems a netdevice has already been allocated for us, and the
30 * hsr_dev_setup routine has been executed. Nice!
31 */
32static int hsr_newlink(struct net *src_net, struct net_device *dev,
33 struct nlattr *tb[], struct nlattr *data[])
34{
35 struct net_device *link[2];
36 unsigned char multicast_spec;
37
38 if (!data[IFLA_HSR_SLAVE1]) {
39 netdev_info(dev, "IFLA_HSR_SLAVE1 missing!\n");
40 return -EINVAL;
41 }
42 link[0] = __dev_get_by_index(src_net, nla_get_u32(data[IFLA_HSR_SLAVE1]));
43 if (!data[IFLA_HSR_SLAVE2]) {
44 netdev_info(dev, "IFLA_HSR_SLAVE2 missing!\n");
45 return -EINVAL;
46 }
47 link[1] = __dev_get_by_index(src_net, nla_get_u32(data[IFLA_HSR_SLAVE2]));
48
49 if (!link[0] || !link[1])
50 return -ENODEV;
51 if (link[0] == link[1])
52 return -EINVAL;
53
54 if (!data[IFLA_HSR_MULTICAST_SPEC])
55 multicast_spec = 0;
56 else
57 multicast_spec = nla_get_u8(data[IFLA_HSR_MULTICAST_SPEC]);
58
59 return hsr_dev_finalize(dev, link, multicast_spec);
60}
61
62static struct rtnl_link_ops hsr_link_ops __read_mostly = {
63 .kind = "hsr",
64 .maxtype = IFLA_HSR_MAX,
65 .policy = hsr_policy,
66 .priv_size = sizeof(struct hsr_priv),
67 .setup = hsr_dev_setup,
68 .newlink = hsr_newlink,
69};
70
71
72
73/* attribute policy */
74/* NLA_BINARY missing in libnl; use NLA_UNSPEC in userspace instead. */
75static const struct nla_policy hsr_genl_policy[HSR_A_MAX + 1] = {
76 [HSR_A_NODE_ADDR] = { .type = NLA_BINARY, .len = ETH_ALEN },
77 [HSR_A_NODE_ADDR_B] = { .type = NLA_BINARY, .len = ETH_ALEN },
78 [HSR_A_IFINDEX] = { .type = NLA_U32 },
79 [HSR_A_IF1_AGE] = { .type = NLA_U32 },
80 [HSR_A_IF2_AGE] = { .type = NLA_U32 },
81 [HSR_A_IF1_SEQ] = { .type = NLA_U16 },
82 [HSR_A_IF2_SEQ] = { .type = NLA_U16 },
83};
84
85static struct genl_family hsr_genl_family = {
86 .id = GENL_ID_GENERATE,
87 .hdrsize = 0,
88 .name = "HSR",
89 .version = 1,
90 .maxattr = HSR_A_MAX,
91};
92
93static struct genl_multicast_group hsr_network_genl_mcgrp = {
94 .name = "hsr-network",
95};
96
97
98
99/* This is called if for some node with MAC address addr, we only get frames
100 * over one of the slave interfaces. This would indicate an open network ring
101 * (i.e. a link has failed somewhere).
102 */
103void hsr_nl_ringerror(struct hsr_priv *hsr_priv, unsigned char addr[ETH_ALEN],
104 enum hsr_dev_idx dev_idx)
105{
106 struct sk_buff *skb;
107 void *msg_head;
108 int res;
109 int ifindex;
110
111 skb = genlmsg_new(NLMSG_GOODSIZE, GFP_ATOMIC);
112 if (!skb)
113 goto fail;
114
115 msg_head = genlmsg_put(skb, 0, 0, &hsr_genl_family, 0, HSR_C_RING_ERROR);
116 if (!msg_head)
117 goto nla_put_failure;
118
119 res = nla_put(skb, HSR_A_NODE_ADDR, ETH_ALEN, addr);
120 if (res < 0)
121 goto nla_put_failure;
122
123 if (hsr_priv->slave[dev_idx])
124 ifindex = hsr_priv->slave[dev_idx]->ifindex;
125 else
126 ifindex = -1;
127 res = nla_put_u32(skb, HSR_A_IFINDEX, ifindex);
128 if (res < 0)
129 goto nla_put_failure;
130
131 genlmsg_end(skb, msg_head);
132 genlmsg_multicast(skb, 0, hsr_network_genl_mcgrp.id, GFP_ATOMIC);
133
134 return;
135
136nla_put_failure:
137 kfree_skb(skb);
138
139fail:
140 netdev_warn(hsr_priv->dev, "Could not send HSR ring error message\n");
141}
142
143/* This is called when we haven't heard from the node with MAC address addr for
144 * some time (just before the node is removed from the node table/list).
145 */
146void hsr_nl_nodedown(struct hsr_priv *hsr_priv, unsigned char addr[ETH_ALEN])
147{
148 struct sk_buff *skb;
149 void *msg_head;
150 int res;
151
152 skb = genlmsg_new(NLMSG_GOODSIZE, GFP_ATOMIC);
153 if (!skb)
154 goto fail;
155
156 msg_head = genlmsg_put(skb, 0, 0, &hsr_genl_family, 0, HSR_C_NODE_DOWN);
157 if (!msg_head)
158 goto nla_put_failure;
159
160
161 res = nla_put(skb, HSR_A_NODE_ADDR, ETH_ALEN, addr);
162 if (res < 0)
163 goto nla_put_failure;
164
165 genlmsg_end(skb, msg_head);
166 genlmsg_multicast(skb, 0, hsr_network_genl_mcgrp.id, GFP_ATOMIC);
167
168 return;
169
170nla_put_failure:
171 kfree_skb(skb);
172
173fail:
174 netdev_warn(hsr_priv->dev, "Could not send HSR node down\n");
175}
176
177
178/* HSR_C_GET_NODE_STATUS lets userspace query the internal HSR node table
179 * about the status of a specific node in the network, defined by its MAC
180 * address.
181 *
182 * Input: hsr ifindex, node mac address
183 * Output: hsr ifindex, node mac address (copied from request),
184 * age of latest frame from node over slave 1, slave 2 [ms]
185 */
186static int hsr_get_node_status(struct sk_buff *skb_in, struct genl_info *info)
187{
188 /* For receiving */
189 struct nlattr *na;
190 struct net_device *hsr_dev;
191
192 /* For sending */
193 struct sk_buff *skb_out;
194 void *msg_head;
195 struct hsr_priv *hsr_priv;
196 unsigned char hsr_node_addr_b[ETH_ALEN];
197 int hsr_node_if1_age;
198 u16 hsr_node_if1_seq;
199 int hsr_node_if2_age;
200 u16 hsr_node_if2_seq;
201 int addr_b_ifindex;
202 int res;
203
204 if (!info)
205 goto invalid;
206
207 na = info->attrs[HSR_A_IFINDEX];
208 if (!na)
209 goto invalid;
210 na = info->attrs[HSR_A_NODE_ADDR];
211 if (!na)
212 goto invalid;
213
214 hsr_dev = __dev_get_by_index(genl_info_net(info),
215 nla_get_u32(info->attrs[HSR_A_IFINDEX]));
216 if (!hsr_dev)
217 goto invalid;
218 if (!is_hsr_master(hsr_dev))
219 goto invalid;
220
221
222 /* Send reply */
223
224 skb_out = genlmsg_new(NLMSG_GOODSIZE, GFP_KERNEL);
225 if (!skb_out) {
226 res = -ENOMEM;
227 goto fail;
228 }
229
230 msg_head = genlmsg_put(skb_out, NETLINK_CB(skb_in).portid,
231 info->snd_seq, &hsr_genl_family, 0,
232 HSR_C_SET_NODE_STATUS);
233 if (!msg_head) {
234 res = -ENOMEM;
235 goto nla_put_failure;
236 }
237
238 res = nla_put_u32(skb_out, HSR_A_IFINDEX, hsr_dev->ifindex);
239 if (res < 0)
240 goto nla_put_failure;
241
242 hsr_priv = netdev_priv(hsr_dev);
243 res = hsr_get_node_data(hsr_priv,
244 (unsigned char *) nla_data(info->attrs[HSR_A_NODE_ADDR]),
245 hsr_node_addr_b,
246 &addr_b_ifindex,
247 &hsr_node_if1_age,
248 &hsr_node_if1_seq,
249 &hsr_node_if2_age,
250 &hsr_node_if2_seq);
251 if (res < 0)
252 goto fail;
253
254 res = nla_put(skb_out, HSR_A_NODE_ADDR, ETH_ALEN,
255 nla_data(info->attrs[HSR_A_NODE_ADDR]));
256 if (res < 0)
257 goto nla_put_failure;
258
259 if (addr_b_ifindex > -1) {
260 res = nla_put(skb_out, HSR_A_NODE_ADDR_B, ETH_ALEN,
261 hsr_node_addr_b);
262 if (res < 0)
263 goto nla_put_failure;
264
265 res = nla_put_u32(skb_out, HSR_A_ADDR_B_IFINDEX, addr_b_ifindex);
266 if (res < 0)
267 goto nla_put_failure;
268 }
269
270 res = nla_put_u32(skb_out, HSR_A_IF1_AGE, hsr_node_if1_age);
271 if (res < 0)
272 goto nla_put_failure;
273 res = nla_put_u16(skb_out, HSR_A_IF1_SEQ, hsr_node_if1_seq);
274 if (res < 0)
275 goto nla_put_failure;
276 if (hsr_priv->slave[0])
277 res = nla_put_u32(skb_out, HSR_A_IF1_IFINDEX,
278 hsr_priv->slave[0]->ifindex);
279 if (res < 0)
280 goto nla_put_failure;
281
282 res = nla_put_u32(skb_out, HSR_A_IF2_AGE, hsr_node_if2_age);
283 if (res < 0)
284 goto nla_put_failure;
285 res = nla_put_u16(skb_out, HSR_A_IF2_SEQ, hsr_node_if2_seq);
286 if (res < 0)
287 goto nla_put_failure;
288 if (hsr_priv->slave[1])
289 res = nla_put_u32(skb_out, HSR_A_IF2_IFINDEX,
290 hsr_priv->slave[1]->ifindex);
291
292 genlmsg_end(skb_out, msg_head);
293 genlmsg_unicast(genl_info_net(info), skb_out, info->snd_portid);
294
295 return 0;
296
297invalid:
298 netlink_ack(skb_in, nlmsg_hdr(skb_in), -EINVAL);
299 return 0;
300
301nla_put_failure:
302 kfree_skb(skb_out);
303 /* Fall through */
304
305fail:
306 return res;
307}
308
309static struct genl_ops hsr_ops_get_node_status = {
310 .cmd = HSR_C_GET_NODE_STATUS,
311 .flags = 0,
312 .policy = hsr_genl_policy,
313 .doit = hsr_get_node_status,
314 .dumpit = NULL,
315};
316
317
318/* Get a list of MacAddressA of all nodes known to this node (other than self).
319 */
320static int hsr_get_node_list(struct sk_buff *skb_in, struct genl_info *info)
321{
322 /* For receiving */
323 struct nlattr *na;
324 struct net_device *hsr_dev;
325
326 /* For sending */
327 struct sk_buff *skb_out;
328 void *msg_head;
329 struct hsr_priv *hsr_priv;
330 void *pos;
331 unsigned char addr[ETH_ALEN];
332 int res;
333
334 if (!info)
335 goto invalid;
336
337 na = info->attrs[HSR_A_IFINDEX];
338 if (!na)
339 goto invalid;
340
341 hsr_dev = __dev_get_by_index(genl_info_net(info),
342 nla_get_u32(info->attrs[HSR_A_IFINDEX]));
343 if (!hsr_dev)
344 goto invalid;
345 if (!is_hsr_master(hsr_dev))
346 goto invalid;
347
348
349 /* Send reply */
350
351 skb_out = genlmsg_new(NLMSG_GOODSIZE, GFP_KERNEL);
352 if (!skb_out) {
353 res = -ENOMEM;
354 goto fail;
355 }
356
357 msg_head = genlmsg_put(skb_out, NETLINK_CB(skb_in).portid,
358 info->snd_seq, &hsr_genl_family, 0,
359 HSR_C_SET_NODE_LIST);
360 if (!msg_head) {
361 res = -ENOMEM;
362 goto nla_put_failure;
363 }
364
365 res = nla_put_u32(skb_out, HSR_A_IFINDEX, hsr_dev->ifindex);
366 if (res < 0)
367 goto nla_put_failure;
368
369 hsr_priv = netdev_priv(hsr_dev);
370
371 rcu_read_lock();
372 pos = hsr_get_next_node(hsr_priv, NULL, addr);
373 while (pos) {
374 res = nla_put(skb_out, HSR_A_NODE_ADDR, ETH_ALEN, addr);
375 if (res < 0) {
376 rcu_read_unlock();
377 goto nla_put_failure;
378 }
379 pos = hsr_get_next_node(hsr_priv, pos, addr);
380 }
381 rcu_read_unlock();
382
383 genlmsg_end(skb_out, msg_head);
384 genlmsg_unicast(genl_info_net(info), skb_out, info->snd_portid);
385
386 return 0;
387
388invalid:
389 netlink_ack(skb_in, nlmsg_hdr(skb_in), -EINVAL);
390 return 0;
391
392nla_put_failure:
393 kfree_skb(skb_out);
394 /* Fall through */
395
396fail:
397 return res;
398}
399
400
401static struct genl_ops hsr_ops_get_node_list = {
402 .cmd = HSR_C_GET_NODE_LIST,
403 .flags = 0,
404 .policy = hsr_genl_policy,
405 .doit = hsr_get_node_list,
406 .dumpit = NULL,
407};
408
409int __init hsr_netlink_init(void)
410{
411 int rc;
412
413 rc = rtnl_link_register(&hsr_link_ops);
414 if (rc)
415 goto fail_rtnl_link_register;
416
417 rc = genl_register_family(&hsr_genl_family);
418 if (rc)
419 goto fail_genl_register_family;
420
421 rc = genl_register_ops(&hsr_genl_family, &hsr_ops_get_node_status);
422 if (rc)
423 goto fail_genl_register_ops;
424
425 rc = genl_register_ops(&hsr_genl_family, &hsr_ops_get_node_list);
426 if (rc)
427 goto fail_genl_register_ops_node_list;
428
429 rc = genl_register_mc_group(&hsr_genl_family, &hsr_network_genl_mcgrp);
430 if (rc)
431 goto fail_genl_register_mc_group;
432
433 return 0;
434
435fail_genl_register_mc_group:
436 genl_unregister_ops(&hsr_genl_family, &hsr_ops_get_node_list);
437fail_genl_register_ops_node_list:
438 genl_unregister_ops(&hsr_genl_family, &hsr_ops_get_node_status);
439fail_genl_register_ops:
440 genl_unregister_family(&hsr_genl_family);
441fail_genl_register_family:
442 rtnl_link_unregister(&hsr_link_ops);
443fail_rtnl_link_register:
444
445 return rc;
446}
447
448void __exit hsr_netlink_exit(void)
449{
450 genl_unregister_mc_group(&hsr_genl_family, &hsr_network_genl_mcgrp);
451 genl_unregister_ops(&hsr_genl_family, &hsr_ops_get_node_status);
452 genl_unregister_family(&hsr_genl_family);
453
454 rtnl_link_unregister(&hsr_link_ops);
455}
456
457MODULE_ALIAS_RTNL_LINK("hsr");
diff --git a/net/hsr/hsr_netlink.h b/net/hsr/hsr_netlink.h
new file mode 100644
index 000000000000..d4579dcc3c7d
--- /dev/null
+++ b/net/hsr/hsr_netlink.h
@@ -0,0 +1,30 @@
1/* Copyright 2011-2013 Autronica Fire and Security AS
2 *
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
5 * Software Foundation; either version 2 of the License, or (at your option)
6 * any later version.
7 *
8 * Author(s):
9 * 2011-2013 Arvid Brodin, arvid.brodin@xdin.com
10 */
11
12#ifndef __HSR_NETLINK_H
13#define __HSR_NETLINK_H
14
15#include <linux/if_ether.h>
16#include <linux/module.h>
17#include <uapi/linux/hsr_netlink.h>
18
19struct hsr_priv;
20
21int __init hsr_netlink_init(void);
22void __exit hsr_netlink_exit(void);
23
24void hsr_nl_ringerror(struct hsr_priv *hsr_priv, unsigned char addr[ETH_ALEN],
25 int dev_idx);
26void hsr_nl_nodedown(struct hsr_priv *hsr_priv, unsigned char addr[ETH_ALEN]);
27void hsr_nl_framedrop(int dropcount, int dev_idx);
28void hsr_nl_linkdown(int dev_idx);
29
30#endif /* __HSR_NETLINK_H */