aboutsummaryrefslogtreecommitdiffstats
path: root/net/hsr/hsr_framereg.c
diff options
context:
space:
mode:
Diffstat (limited to 'net/hsr/hsr_framereg.c')
-rw-r--r--net/hsr/hsr_framereg.c477
1 files changed, 234 insertions, 243 deletions
diff --git a/net/hsr/hsr_framereg.c b/net/hsr/hsr_framereg.c
index 83e58449366a..bace124d14ef 100644
--- a/net/hsr/hsr_framereg.c
+++ b/net/hsr/hsr_framereg.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 * The HSR spec says never to forward the same frame twice on the same 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 12 * interface. A frame is identified by its source MAC address and its HSR
@@ -23,71 +23,68 @@
23#include "hsr_netlink.h" 23#include "hsr_netlink.h"
24 24
25 25
26struct node_entry { 26struct hsr_node {
27 struct list_head mac_list; 27 struct list_head mac_list;
28 unsigned char MacAddressA[ETH_ALEN]; 28 unsigned char MacAddressA[ETH_ALEN];
29 unsigned char MacAddressB[ETH_ALEN]; 29 unsigned char MacAddressB[ETH_ALEN];
30 enum hsr_dev_idx AddrB_if; /* The local slave through which AddrB 30 /* Local slave through which AddrB frames are received from this node */
31 * frames are received from this node 31 enum hsr_port_type AddrB_port;
32 */ 32 unsigned long time_in[HSR_PT_PORTS];
33 unsigned long time_in[HSR_MAX_SLAVE]; 33 bool time_in_stale[HSR_PT_PORTS];
34 bool time_in_stale[HSR_MAX_SLAVE]; 34 u16 seq_out[HSR_PT_PORTS];
35 u16 seq_out[HSR_MAX_DEV]; 35 struct rcu_head rcu_head;
36 struct rcu_head rcu_head;
37}; 36};
38 37
39/* TODO: use hash lists for mac addresses (linux/jhash.h)? */
40 38
39/* TODO: use hash lists for mac addresses (linux/jhash.h)? */
41 40
42 41
43/* Search for mac entry. Caller must hold rcu read lock. 42/* seq_nr_after(a, b) - return true if a is after (higher in sequence than) b,
43 * false otherwise.
44 */ 44 */
45static struct node_entry *find_node_by_AddrA(struct list_head *node_db, 45static bool seq_nr_after(u16 a, u16 b)
46 const unsigned char addr[ETH_ALEN])
47{ 46{
48 struct node_entry *node; 47 /* Remove inconsistency where
49 48 * seq_nr_after(a, b) == seq_nr_before(a, b)
50 list_for_each_entry_rcu(node, node_db, mac_list) { 49 */
51 if (ether_addr_equal(node->MacAddressA, addr)) 50 if ((int) b - a == 32768)
52 return node; 51 return false;
53 }
54 52
55 return NULL; 53 return (((s16) (b - a)) < 0);
56} 54}
55#define seq_nr_before(a, b) seq_nr_after((b), (a))
56#define seq_nr_after_or_eq(a, b) (!seq_nr_before((a), (b)))
57#define seq_nr_before_or_eq(a, b) (!seq_nr_after((a), (b)))
57 58
58 59
59/* Search for mac entry. Caller must hold rcu read lock. 60bool hsr_addr_is_self(struct hsr_priv *hsr, unsigned char *addr)
60 */
61static struct node_entry *find_node_by_AddrB(struct list_head *node_db,
62 const unsigned char addr[ETH_ALEN])
63{ 61{
64 struct node_entry *node; 62 struct hsr_node *node;
65 63
66 list_for_each_entry_rcu(node, node_db, mac_list) { 64 node = list_first_or_null_rcu(&hsr->self_node_db, struct hsr_node,
67 if (ether_addr_equal(node->MacAddressB, addr)) 65 mac_list);
68 return node; 66 if (!node) {
67 WARN_ONCE(1, "HSR: No self node\n");
68 return false;
69 } 69 }
70 70
71 return NULL; 71 if (ether_addr_equal(addr, node->MacAddressA))
72} 72 return true;
73 if (ether_addr_equal(addr, node->MacAddressB))
74 return true;
73 75
76 return false;
77}
74 78
75/* Search for mac entry. Caller must hold rcu read lock. 79/* Search for mac entry. Caller must hold rcu read lock.
76 */ 80 */
77struct node_entry *hsr_find_node(struct list_head *node_db, struct sk_buff *skb) 81static struct hsr_node *find_node_by_AddrA(struct list_head *node_db,
82 const unsigned char addr[ETH_ALEN])
78{ 83{
79 struct node_entry *node; 84 struct hsr_node *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 85
87 list_for_each_entry_rcu(node, node_db, mac_list) { 86 list_for_each_entry_rcu(node, node_db, mac_list) {
88 if (ether_addr_equal(node->MacAddressA, ethhdr->h_source)) 87 if (ether_addr_equal(node->MacAddressA, addr))
89 return node;
90 if (ether_addr_equal(node->MacAddressB, ethhdr->h_source))
91 return node; 88 return node;
92 } 89 }
93 90
@@ -102,7 +99,7 @@ int hsr_create_self_node(struct list_head *self_node_db,
102 unsigned char addr_a[ETH_ALEN], 99 unsigned char addr_a[ETH_ALEN],
103 unsigned char addr_b[ETH_ALEN]) 100 unsigned char addr_b[ETH_ALEN])
104{ 101{
105 struct node_entry *node, *oldnode; 102 struct hsr_node *node, *oldnode;
106 103
107 node = kmalloc(sizeof(*node), GFP_KERNEL); 104 node = kmalloc(sizeof(*node), GFP_KERNEL);
108 if (!node) 105 if (!node)
@@ -113,7 +110,7 @@ int hsr_create_self_node(struct list_head *self_node_db,
113 110
114 rcu_read_lock(); 111 rcu_read_lock();
115 oldnode = list_first_or_null_rcu(self_node_db, 112 oldnode = list_first_or_null_rcu(self_node_db,
116 struct node_entry, mac_list); 113 struct hsr_node, mac_list);
117 if (oldnode) { 114 if (oldnode) {
118 list_replace_rcu(&oldnode->mac_list, &node->mac_list); 115 list_replace_rcu(&oldnode->mac_list, &node->mac_list);
119 rcu_read_unlock(); 116 rcu_read_unlock();
@@ -128,135 +125,144 @@ int hsr_create_self_node(struct list_head *self_node_db,
128} 125}
129 126
130 127
131/* Add/merge node to the database of nodes. 'skb' must contain an HSR 128/* Allocate an hsr_node and add it to node_db. 'addr' is the node's AddressA;
132 * supervision frame. 129 * seq_out is used to initialize filtering of outgoing duplicate frames
133 * - If the supervision header's MacAddressA field is not yet in the database, 130 * originating from the newly added node.
134 * this frame is from an hitherto unknown node - add it to the database.
135 * - If the sender's MAC address is not the same as its MacAddressA address,
136 * the node is using PICS_SUBS (address substitution). Record the sender's
137 * address as the node's MacAddressB.
138 *
139 * This function needs to work even if the sender node has changed one of its
140 * slaves' MAC addresses. In this case, there are four different cases described
141 * by (Addr-changed, received-from) pairs as follows. Note that changing the
142 * SlaveA address is equal to changing the node's own address:
143 *
144 * - (AddrB, SlaveB): The new AddrB will be recorded by PICS_SUBS code since
145 * node == NULL.
146 * - (AddrB, SlaveA): Will work as usual (the AddrB change won't be detected
147 * from this frame).
148 *
149 * - (AddrA, SlaveB): The old node will be found. We need to detect this and
150 * remove the node.
151 * - (AddrA, SlaveA): A new node will be registered (non-PICS_SUBS at first).
152 * The old one will be pruned after HSR_NODE_FORGET_TIME.
153 *
154 * We also need to detect if the sender's SlaveA and SlaveB cables have been
155 * swapped.
156 */ 131 */
157struct node_entry *hsr_merge_node(struct hsr_priv *hsr_priv, 132struct hsr_node *hsr_add_node(struct list_head *node_db, unsigned char addr[],
158 struct node_entry *node, 133 u16 seq_out)
159 struct sk_buff *skb,
160 enum hsr_dev_idx dev_idx)
161{ 134{
162 struct hsr_sup_payload *hsr_sp; 135 struct hsr_node *node;
163 struct hsr_ethhdr_sp *hsr_ethsup;
164 int i;
165 unsigned long now; 136 unsigned long now;
166 137 int i;
167 hsr_ethsup = (struct hsr_ethhdr_sp *) skb_mac_header(skb);
168 hsr_sp = (struct hsr_sup_payload *) skb->data;
169
170 if (node && !ether_addr_equal(node->MacAddressA, hsr_sp->MacAddressA)) {
171 /* Node has changed its AddrA, frame was received from SlaveB */
172 list_del_rcu(&node->mac_list);
173 kfree_rcu(node, rcu_head);
174 node = NULL;
175 }
176
177 if (node && (dev_idx == node->AddrB_if) &&
178 !ether_addr_equal(node->MacAddressB, hsr_ethsup->ethhdr.h_source)) {
179 /* Cables have been swapped */
180 list_del_rcu(&node->mac_list);
181 kfree_rcu(node, rcu_head);
182 node = NULL;
183 }
184
185 if (node && (dev_idx != node->AddrB_if) &&
186 (node->AddrB_if != HSR_DEV_NONE) &&
187 !ether_addr_equal(node->MacAddressA, hsr_ethsup->ethhdr.h_source)) {
188 /* Cables have been swapped */
189 list_del_rcu(&node->mac_list);
190 kfree_rcu(node, rcu_head);
191 node = NULL;
192 }
193
194 if (node)
195 return node;
196
197 node = find_node_by_AddrA(&hsr_priv->node_db, hsr_sp->MacAddressA);
198 if (node) {
199 /* Node is known, but frame was received from an unknown
200 * address. Node is PICS_SUBS capable; merge its AddrB.
201 */
202 ether_addr_copy(node->MacAddressB, hsr_ethsup->ethhdr.h_source);
203 node->AddrB_if = dev_idx;
204 return node;
205 }
206 138
207 node = kzalloc(sizeof(*node), GFP_ATOMIC); 139 node = kzalloc(sizeof(*node), GFP_ATOMIC);
208 if (!node) 140 if (!node)
209 return NULL; 141 return NULL;
210 142
211 ether_addr_copy(node->MacAddressA, hsr_sp->MacAddressA); 143 ether_addr_copy(node->MacAddressA, addr);
212 ether_addr_copy(node->MacAddressB, hsr_ethsup->ethhdr.h_source);
213 if (!ether_addr_equal(hsr_sp->MacAddressA, hsr_ethsup->ethhdr.h_source))
214 node->AddrB_if = dev_idx;
215 else
216 node->AddrB_if = HSR_DEV_NONE;
217 144
218 /* We are only interested in time diffs here, so use current jiffies 145 /* We are only interested in time diffs here, so use current jiffies
219 * as initialization. (0 could trigger an spurious ring error warning). 146 * as initialization. (0 could trigger an spurious ring error warning).
220 */ 147 */
221 now = jiffies; 148 now = jiffies;
222 for (i = 0; i < HSR_MAX_SLAVE; i++) 149 for (i = 0; i < HSR_PT_PORTS; i++)
223 node->time_in[i] = now; 150 node->time_in[i] = now;
224 for (i = 0; i < HSR_MAX_DEV; i++) 151 for (i = 0; i < HSR_PT_PORTS; i++)
225 node->seq_out[i] = ntohs(hsr_ethsup->hsr_sup.sequence_nr) - 1; 152 node->seq_out[i] = seq_out;
226 153
227 list_add_tail_rcu(&node->mac_list, &hsr_priv->node_db); 154 list_add_tail_rcu(&node->mac_list, node_db);
228 155
229 return node; 156 return node;
230} 157}
231 158
159/* Get the hsr_node from which 'skb' was sent.
160 */
161struct hsr_node *hsr_get_node(struct list_head *node_db, struct sk_buff *skb,
162 bool is_sup)
163{
164 struct hsr_node *node;
165 struct ethhdr *ethhdr;
166 u16 seq_out;
167
168 if (!skb_mac_header_was_set(skb))
169 return NULL;
170
171 ethhdr = (struct ethhdr *) skb_mac_header(skb);
172
173 list_for_each_entry_rcu(node, node_db, mac_list) {
174 if (ether_addr_equal(node->MacAddressA, ethhdr->h_source))
175 return node;
176 if (ether_addr_equal(node->MacAddressB, ethhdr->h_source))
177 return node;
178 }
179
180 if (!is_sup)
181 return NULL; /* Only supervision frame may create node entry */
182
183 if (ethhdr->h_proto == htons(ETH_P_PRP)) {
184 /* Use the existing sequence_nr from the tag as starting point
185 * for filtering duplicate frames.
186 */
187 seq_out = hsr_get_skb_sequence_nr(skb) - 1;
188 } else {
189 WARN_ONCE(1, "%s: Non-HSR frame\n", __func__);
190 seq_out = 0;
191 }
192
193 return hsr_add_node(node_db, ethhdr->h_source, seq_out);
194}
195
196/* Use the Supervision frame's info about an eventual MacAddressB for merging
197 * nodes that has previously had their MacAddressB registered as a separate
198 * node.
199 */
200void hsr_handle_sup_frame(struct sk_buff *skb, struct hsr_node *node_curr,
201 struct hsr_port *port_rcv)
202{
203 struct hsr_node *node_real;
204 struct hsr_sup_payload *hsr_sp;
205 struct list_head *node_db;
206 int i;
207
208 skb_pull(skb, sizeof(struct hsr_ethhdr_sp));
209 hsr_sp = (struct hsr_sup_payload *) skb->data;
210
211 if (ether_addr_equal(eth_hdr(skb)->h_source, hsr_sp->MacAddressA))
212 /* Not sent from MacAddressB of a PICS_SUBS capable node */
213 goto done;
214
215 /* Merge node_curr (registered on MacAddressB) into node_real */
216 node_db = &port_rcv->hsr->node_db;
217 node_real = find_node_by_AddrA(node_db, hsr_sp->MacAddressA);
218 if (!node_real)
219 /* No frame received from AddrA of this node yet */
220 node_real = hsr_add_node(node_db, hsr_sp->MacAddressA,
221 HSR_SEQNR_START - 1);
222 if (!node_real)
223 goto done; /* No mem */
224 if (node_real == node_curr)
225 /* Node has already been merged */
226 goto done;
227
228 ether_addr_copy(node_real->MacAddressB, eth_hdr(skb)->h_source);
229 for (i = 0; i < HSR_PT_PORTS; i++) {
230 if (!node_curr->time_in_stale[i] &&
231 time_after(node_curr->time_in[i], node_real->time_in[i])) {
232 node_real->time_in[i] = node_curr->time_in[i];
233 node_real->time_in_stale[i] = node_curr->time_in_stale[i];
234 }
235 if (seq_nr_after(node_curr->seq_out[i], node_real->seq_out[i]))
236 node_real->seq_out[i] = node_curr->seq_out[i];
237 }
238 node_real->AddrB_port = port_rcv->type;
239
240 list_del_rcu(&node_curr->mac_list);
241 kfree_rcu(node_curr, rcu_head);
242
243done:
244 skb_push(skb, sizeof(struct hsr_ethhdr_sp));
245}
246
232 247
233/* 'skb' is a frame meant for this host, that is to be passed to upper layers. 248/* 'skb' is a frame meant for this host, that is to be passed to upper layers.
234 * 249 *
235 * If the frame was sent by a node's B interface, replace the sender 250 * If the frame was sent by a node's B interface, replace the source
236 * address with that node's "official" address (MacAddressA) so that upper 251 * address with that node's "official" address (MacAddressA) so that upper
237 * layers recognize where it came from. 252 * layers recognize where it came from.
238 */ 253 */
239void hsr_addr_subst_source(struct hsr_priv *hsr_priv, struct sk_buff *skb) 254void hsr_addr_subst_source(struct hsr_node *node, struct sk_buff *skb)
240{ 255{
241 struct ethhdr *ethhdr;
242 struct node_entry *node;
243
244 if (!skb_mac_header_was_set(skb)) { 256 if (!skb_mac_header_was_set(skb)) {
245 WARN_ONCE(1, "%s: Mac header not set\n", __func__); 257 WARN_ONCE(1, "%s: Mac header not set\n", __func__);
246 return; 258 return;
247 } 259 }
248 ethhdr = (struct ethhdr *) skb_mac_header(skb);
249 260
250 rcu_read_lock(); 261 memcpy(&eth_hdr(skb)->h_source, node->MacAddressA, ETH_ALEN);
251 node = find_node_by_AddrB(&hsr_priv->node_db, ethhdr->h_source);
252 if (node)
253 ether_addr_copy(ethhdr->h_source, node->MacAddressA);
254 rcu_read_unlock();
255} 262}
256 263
257
258/* 'skb' is a frame meant for another host. 264/* 'skb' is a frame meant for another host.
259 * 'hsr_dev_idx' is the HSR index of the outgoing device 265 * 'port' is the outgoing interface
260 * 266 *
261 * Substitute the target (dest) MAC address if necessary, so the it matches the 267 * Substitute the target (dest) MAC address if necessary, so the it matches the
262 * recipient interface MAC address, regardless of whether that is the 268 * recipient interface MAC address, regardless of whether that is the
@@ -264,47 +270,44 @@ void hsr_addr_subst_source(struct hsr_priv *hsr_priv, struct sk_buff *skb)
264 * This is needed to keep the packets flowing through switches that learn on 270 * This is needed to keep the packets flowing through switches that learn on
265 * which "side" the different interfaces are. 271 * which "side" the different interfaces are.
266 */ 272 */
267void hsr_addr_subst_dest(struct hsr_priv *hsr_priv, struct ethhdr *ethhdr, 273void hsr_addr_subst_dest(struct hsr_node *node_src, struct sk_buff *skb,
268 enum hsr_dev_idx dev_idx) 274 struct hsr_port *port)
269{ 275{
270 struct node_entry *node; 276 struct hsr_node *node_dst;
271 277
272 rcu_read_lock(); 278 if (!skb_mac_header_was_set(skb)) {
273 node = find_node_by_AddrA(&hsr_priv->node_db, ethhdr->h_dest); 279 WARN_ONCE(1, "%s: Mac header not set\n", __func__);
274 if (node && (node->AddrB_if == dev_idx)) 280 return;
275 ether_addr_copy(ethhdr->h_dest, node->MacAddressB); 281 }
276 rcu_read_unlock();
277}
278 282
283 if (!is_unicast_ether_addr(eth_hdr(skb)->h_dest))
284 return;
279 285
280/* seq_nr_after(a, b) - return true if a is after (higher in sequence than) b, 286 node_dst = find_node_by_AddrA(&port->hsr->node_db, eth_hdr(skb)->h_dest);
281 * false otherwise. 287 if (!node_dst) {
282 */ 288 WARN_ONCE(1, "%s: Unknown node\n", __func__);
283static bool seq_nr_after(u16 a, u16 b) 289 return;
284{ 290 }
285 /* Remove inconsistency where 291 if (port->type != node_dst->AddrB_port)
286 * seq_nr_after(a, b) == seq_nr_before(a, b) 292 return;
287 */
288 if ((int) b - a == 32768)
289 return false;
290 293
291 return (((s16) (b - a)) < 0); 294 ether_addr_copy(eth_hdr(skb)->h_dest, node_dst->MacAddressB);
292} 295}
293#define seq_nr_before(a, b) seq_nr_after((b), (a))
294#define seq_nr_after_or_eq(a, b) (!seq_nr_before((a), (b)))
295#define seq_nr_before_or_eq(a, b) (!seq_nr_after((a), (b)))
296 296
297 297
298void hsr_register_frame_in(struct node_entry *node, enum hsr_dev_idx dev_idx) 298void hsr_register_frame_in(struct hsr_node *node, struct hsr_port *port,
299 u16 sequence_nr)
299{ 300{
300 if ((dev_idx < 0) || (dev_idx >= HSR_MAX_SLAVE)) { 301 /* Don't register incoming frames without a valid sequence number. This
301 WARN_ONCE(1, "%s: Invalid dev_idx (%d)\n", __func__, dev_idx); 302 * ensures entries of restarted nodes gets pruned so that they can
303 * re-register and resume communications.
304 */
305 if (seq_nr_before(sequence_nr, node->seq_out[port->type]))
302 return; 306 return;
303 }
304 node->time_in[dev_idx] = jiffies;
305 node->time_in_stale[dev_idx] = false;
306}
307 307
308 node->time_in[port->type] = jiffies;
309 node->time_in_stale[port->type] = false;
310}
308 311
309/* 'skb' is a HSR Ethernet frame (with a HSR tag inserted), with a valid 312/* 'skb' is a HSR Ethernet frame (with a HSR tag inserted), with a valid
310 * ethhdr->h_source address and skb->mac_header set. 313 * ethhdr->h_source address and skb->mac_header set.
@@ -314,102 +317,87 @@ void hsr_register_frame_in(struct node_entry *node, enum hsr_dev_idx dev_idx)
314 * 0 otherwise, or 317 * 0 otherwise, or
315 * negative error code on error 318 * negative error code on error
316 */ 319 */
317int hsr_register_frame_out(struct node_entry *node, enum hsr_dev_idx dev_idx, 320int hsr_register_frame_out(struct hsr_port *port, struct hsr_node *node,
318 struct sk_buff *skb) 321 u16 sequence_nr)
319{ 322{
320 struct hsr_ethhdr *hsr_ethhdr; 323 if (seq_nr_before_or_eq(sequence_nr, node->seq_out[port->type]))
321 u16 sequence_nr;
322
323 if ((dev_idx < 0) || (dev_idx >= HSR_MAX_DEV)) {
324 WARN_ONCE(1, "%s: Invalid dev_idx (%d)\n", __func__, dev_idx);
325 return -EINVAL;
326 }
327 if (!skb_mac_header_was_set(skb)) {
328 WARN_ONCE(1, "%s: Mac header not set\n", __func__);
329 return -EINVAL;
330 }
331 hsr_ethhdr = (struct hsr_ethhdr *) skb_mac_header(skb);
332
333 sequence_nr = ntohs(hsr_ethhdr->hsr_tag.sequence_nr);
334 if (seq_nr_before_or_eq(sequence_nr, node->seq_out[dev_idx]))
335 return 1; 324 return 1;
336 325
337 node->seq_out[dev_idx] = sequence_nr; 326 node->seq_out[port->type] = sequence_nr;
338 return 0; 327 return 0;
339} 328}
340 329
341 330
342 331static struct hsr_port *get_late_port(struct hsr_priv *hsr,
343static bool is_late(struct node_entry *node, enum hsr_dev_idx dev_idx) 332 struct hsr_node *node)
344{ 333{
345 enum hsr_dev_idx other; 334 if (node->time_in_stale[HSR_PT_SLAVE_A])
346 335 return hsr_port_get_hsr(hsr, HSR_PT_SLAVE_A);
347 if (node->time_in_stale[dev_idx]) 336 if (node->time_in_stale[HSR_PT_SLAVE_B])
348 return true; 337 return hsr_port_get_hsr(hsr, HSR_PT_SLAVE_B);
349 338
350 if (dev_idx == HSR_DEV_SLAVE_A) 339 if (time_after(node->time_in[HSR_PT_SLAVE_B],
351 other = HSR_DEV_SLAVE_B; 340 node->time_in[HSR_PT_SLAVE_A] +
352 else 341 msecs_to_jiffies(MAX_SLAVE_DIFF)))
353 other = HSR_DEV_SLAVE_A; 342 return hsr_port_get_hsr(hsr, HSR_PT_SLAVE_A);
354 343 if (time_after(node->time_in[HSR_PT_SLAVE_A],
355 if (node->time_in_stale[other]) 344 node->time_in[HSR_PT_SLAVE_B] +
356 return false; 345 msecs_to_jiffies(MAX_SLAVE_DIFF)))
346 return hsr_port_get_hsr(hsr, HSR_PT_SLAVE_B);
357 347
358 if (time_after(node->time_in[other], node->time_in[dev_idx] + 348 return NULL;
359 msecs_to_jiffies(MAX_SLAVE_DIFF)))
360 return true;
361
362 return false;
363} 349}
364 350
365 351
366/* Remove stale sequence_nr records. Called by timer every 352/* Remove stale sequence_nr records. Called by timer every
367 * HSR_LIFE_CHECK_INTERVAL (two seconds or so). 353 * HSR_LIFE_CHECK_INTERVAL (two seconds or so).
368 */ 354 */
369void hsr_prune_nodes(struct hsr_priv *hsr_priv) 355void hsr_prune_nodes(unsigned long data)
370{ 356{
371 struct node_entry *node; 357 struct hsr_priv *hsr;
358 struct hsr_node *node;
359 struct hsr_port *port;
372 unsigned long timestamp; 360 unsigned long timestamp;
373 unsigned long time_a, time_b; 361 unsigned long time_a, time_b;
374 362
363 hsr = (struct hsr_priv *) data;
364
375 rcu_read_lock(); 365 rcu_read_lock();
376 list_for_each_entry_rcu(node, &hsr_priv->node_db, mac_list) { 366 list_for_each_entry_rcu(node, &hsr->node_db, mac_list) {
377 /* Shorthand */ 367 /* Shorthand */
378 time_a = node->time_in[HSR_DEV_SLAVE_A]; 368 time_a = node->time_in[HSR_PT_SLAVE_A];
379 time_b = node->time_in[HSR_DEV_SLAVE_B]; 369 time_b = node->time_in[HSR_PT_SLAVE_B];
380 370
381 /* Check for timestamps old enough to risk wrap-around */ 371 /* Check for timestamps old enough to risk wrap-around */
382 if (time_after(jiffies, time_a + MAX_JIFFY_OFFSET/2)) 372 if (time_after(jiffies, time_a + MAX_JIFFY_OFFSET/2))
383 node->time_in_stale[HSR_DEV_SLAVE_A] = true; 373 node->time_in_stale[HSR_PT_SLAVE_A] = true;
384 if (time_after(jiffies, time_b + MAX_JIFFY_OFFSET/2)) 374 if (time_after(jiffies, time_b + MAX_JIFFY_OFFSET/2))
385 node->time_in_stale[HSR_DEV_SLAVE_B] = true; 375 node->time_in_stale[HSR_PT_SLAVE_B] = true;
386 376
387 /* Get age of newest frame from node. 377 /* Get age of newest frame from node.
388 * At least one time_in is OK here; nodes get pruned long 378 * At least one time_in is OK here; nodes get pruned long
389 * before both time_ins can get stale 379 * before both time_ins can get stale
390 */ 380 */
391 timestamp = time_a; 381 timestamp = time_a;
392 if (node->time_in_stale[HSR_DEV_SLAVE_A] || 382 if (node->time_in_stale[HSR_PT_SLAVE_A] ||
393 (!node->time_in_stale[HSR_DEV_SLAVE_B] && 383 (!node->time_in_stale[HSR_PT_SLAVE_B] &&
394 time_after(time_b, time_a))) 384 time_after(time_b, time_a)))
395 timestamp = time_b; 385 timestamp = time_b;
396 386
397 /* Warn of ring error only as long as we get frames at all */ 387 /* Warn of ring error only as long as we get frames at all */
398 if (time_is_after_jiffies(timestamp + 388 if (time_is_after_jiffies(timestamp +
399 msecs_to_jiffies(1.5*MAX_SLAVE_DIFF))) { 389 msecs_to_jiffies(1.5*MAX_SLAVE_DIFF))) {
400 390 rcu_read_lock();
401 if (is_late(node, HSR_DEV_SLAVE_A)) 391 port = get_late_port(hsr, node);
402 hsr_nl_ringerror(hsr_priv, node->MacAddressA, 392 if (port != NULL)
403 HSR_DEV_SLAVE_A); 393 hsr_nl_ringerror(hsr, node->MacAddressA, port);
404 else if (is_late(node, HSR_DEV_SLAVE_B)) 394 rcu_read_unlock();
405 hsr_nl_ringerror(hsr_priv, node->MacAddressA,
406 HSR_DEV_SLAVE_B);
407 } 395 }
408 396
409 /* Prune old entries */ 397 /* Prune old entries */
410 if (time_is_before_jiffies(timestamp + 398 if (time_is_before_jiffies(timestamp +
411 msecs_to_jiffies(HSR_NODE_FORGET_TIME))) { 399 msecs_to_jiffies(HSR_NODE_FORGET_TIME))) {
412 hsr_nl_nodedown(hsr_priv, node->MacAddressA); 400 hsr_nl_nodedown(hsr, node->MacAddressA);
413 list_del_rcu(&node->mac_list); 401 list_del_rcu(&node->mac_list);
414 /* Note that we need to free this entry later: */ 402 /* Note that we need to free this entry later: */
415 kfree_rcu(node, rcu_head); 403 kfree_rcu(node, rcu_head);
@@ -419,21 +407,21 @@ void hsr_prune_nodes(struct hsr_priv *hsr_priv)
419} 407}
420 408
421 409
422void *hsr_get_next_node(struct hsr_priv *hsr_priv, void *_pos, 410void *hsr_get_next_node(struct hsr_priv *hsr, void *_pos,
423 unsigned char addr[ETH_ALEN]) 411 unsigned char addr[ETH_ALEN])
424{ 412{
425 struct node_entry *node; 413 struct hsr_node *node;
426 414
427 if (!_pos) { 415 if (!_pos) {
428 node = list_first_or_null_rcu(&hsr_priv->node_db, 416 node = list_first_or_null_rcu(&hsr->node_db,
429 struct node_entry, mac_list); 417 struct hsr_node, mac_list);
430 if (node) 418 if (node)
431 ether_addr_copy(addr, node->MacAddressA); 419 ether_addr_copy(addr, node->MacAddressA);
432 return node; 420 return node;
433 } 421 }
434 422
435 node = _pos; 423 node = _pos;
436 list_for_each_entry_continue_rcu(node, &hsr_priv->node_db, mac_list) { 424 list_for_each_entry_continue_rcu(node, &hsr->node_db, mac_list) {
437 ether_addr_copy(addr, node->MacAddressA); 425 ether_addr_copy(addr, node->MacAddressA);
438 return node; 426 return node;
439 } 427 }
@@ -442,7 +430,7 @@ void *hsr_get_next_node(struct hsr_priv *hsr_priv, void *_pos,
442} 430}
443 431
444 432
445int hsr_get_node_data(struct hsr_priv *hsr_priv, 433int hsr_get_node_data(struct hsr_priv *hsr,
446 const unsigned char *addr, 434 const unsigned char *addr,
447 unsigned char addr_b[ETH_ALEN], 435 unsigned char addr_b[ETH_ALEN],
448 unsigned int *addr_b_ifindex, 436 unsigned int *addr_b_ifindex,
@@ -451,12 +439,13 @@ int hsr_get_node_data(struct hsr_priv *hsr_priv,
451 int *if2_age, 439 int *if2_age,
452 u16 *if2_seq) 440 u16 *if2_seq)
453{ 441{
454 struct node_entry *node; 442 struct hsr_node *node;
443 struct hsr_port *port;
455 unsigned long tdiff; 444 unsigned long tdiff;
456 445
457 446
458 rcu_read_lock(); 447 rcu_read_lock();
459 node = find_node_by_AddrA(&hsr_priv->node_db, addr); 448 node = find_node_by_AddrA(&hsr->node_db, addr);
460 if (!node) { 449 if (!node) {
461 rcu_read_unlock(); 450 rcu_read_unlock();
462 return -ENOENT; /* No such entry */ 451 return -ENOENT; /* No such entry */
@@ -464,8 +453,8 @@ int hsr_get_node_data(struct hsr_priv *hsr_priv,
464 453
465 ether_addr_copy(addr_b, node->MacAddressB); 454 ether_addr_copy(addr_b, node->MacAddressB);
466 455
467 tdiff = jiffies - node->time_in[HSR_DEV_SLAVE_A]; 456 tdiff = jiffies - node->time_in[HSR_PT_SLAVE_A];
468 if (node->time_in_stale[HSR_DEV_SLAVE_A]) 457 if (node->time_in_stale[HSR_PT_SLAVE_A])
469 *if1_age = INT_MAX; 458 *if1_age = INT_MAX;
470#if HZ <= MSEC_PER_SEC 459#if HZ <= MSEC_PER_SEC
471 else if (tdiff > msecs_to_jiffies(INT_MAX)) 460 else if (tdiff > msecs_to_jiffies(INT_MAX))
@@ -474,8 +463,8 @@ int hsr_get_node_data(struct hsr_priv *hsr_priv,
474 else 463 else
475 *if1_age = jiffies_to_msecs(tdiff); 464 *if1_age = jiffies_to_msecs(tdiff);
476 465
477 tdiff = jiffies - node->time_in[HSR_DEV_SLAVE_B]; 466 tdiff = jiffies - node->time_in[HSR_PT_SLAVE_B];
478 if (node->time_in_stale[HSR_DEV_SLAVE_B]) 467 if (node->time_in_stale[HSR_PT_SLAVE_B])
479 *if2_age = INT_MAX; 468 *if2_age = INT_MAX;
480#if HZ <= MSEC_PER_SEC 469#if HZ <= MSEC_PER_SEC
481 else if (tdiff > msecs_to_jiffies(INT_MAX)) 470 else if (tdiff > msecs_to_jiffies(INT_MAX))
@@ -485,13 +474,15 @@ int hsr_get_node_data(struct hsr_priv *hsr_priv,
485 *if2_age = jiffies_to_msecs(tdiff); 474 *if2_age = jiffies_to_msecs(tdiff);
486 475
487 /* Present sequence numbers as if they were incoming on interface */ 476 /* Present sequence numbers as if they were incoming on interface */
488 *if1_seq = node->seq_out[HSR_DEV_SLAVE_B]; 477 *if1_seq = node->seq_out[HSR_PT_SLAVE_B];
489 *if2_seq = node->seq_out[HSR_DEV_SLAVE_A]; 478 *if2_seq = node->seq_out[HSR_PT_SLAVE_A];
490 479
491 if ((node->AddrB_if != HSR_DEV_NONE) && hsr_priv->slave[node->AddrB_if]) 480 if (node->AddrB_port != HSR_PT_NONE) {
492 *addr_b_ifindex = hsr_priv->slave[node->AddrB_if]->ifindex; 481 port = hsr_port_get_hsr(hsr, node->AddrB_port);
493 else 482 *addr_b_ifindex = port->dev->ifindex;
483 } else {
494 *addr_b_ifindex = -1; 484 *addr_b_ifindex = -1;
485 }
495 486
496 rcu_read_unlock(); 487 rcu_read_unlock();
497 488