Blame view

net/hsr/hsr_framereg.c 13.4 KB
70ebe4a47   Arvid Brodin   net/hsr: Better v...
1
  /* Copyright 2011-2014 Autronica Fire and Security AS
f421436a5   Arvid Brodin   net/hsr: Add supp...
2
3
4
5
6
7
8
   *
   * This program is free software; you can redistribute it and/or modify it
   * under the terms of the GNU General Public License as published by the Free
   * Software Foundation; either version 2 of the License, or (at your option)
   * any later version.
   *
   * Author(s):
70ebe4a47   Arvid Brodin   net/hsr: Better v...
9
   *	2011-2014 Arvid Brodin, arvid.brodin@alten.se
f421436a5   Arvid Brodin   net/hsr: Add supp...
10
11
12
13
14
15
16
17
18
19
20
21
22
23
   *
   * The HSR spec says never to forward the same frame twice on the same
   * interface. A frame is identified by its source MAC address and its HSR
   * sequence number. This code keeps track of senders and their sequence numbers
   * to allow filtering of duplicate frames, and to detect HSR ring errors.
   */
  
  #include <linux/if_ether.h>
  #include <linux/etherdevice.h>
  #include <linux/slab.h>
  #include <linux/rculist.h>
  #include "hsr_main.h"
  #include "hsr_framereg.h"
  #include "hsr_netlink.h"
70ebe4a47   Arvid Brodin   net/hsr: Better v...
24
25
26
27
  struct hsr_node {
  	struct list_head	mac_list;
  	unsigned char		MacAddressA[ETH_ALEN];
  	unsigned char		MacAddressB[ETH_ALEN];
c5a759117   Arvid Brodin   net/hsr: Use list...
28
29
30
31
32
  	/* Local slave through which AddrB frames are received from this node */
  	enum hsr_port_type	AddrB_port;
  	unsigned long		time_in[HSR_PT_PORTS];
  	bool			time_in_stale[HSR_PT_PORTS];
  	u16			seq_out[HSR_PT_PORTS];
70ebe4a47   Arvid Brodin   net/hsr: Better v...
33
  	struct rcu_head		rcu_head;
f421436a5   Arvid Brodin   net/hsr: Add supp...
34
  };
f421436a5   Arvid Brodin   net/hsr: Add supp...
35

f266a683a   Arvid Brodin   net/hsr: Better f...
36
  /*	TODO: use hash lists for mac addresses (linux/jhash.h)?    */
f421436a5   Arvid Brodin   net/hsr: Add supp...
37

f266a683a   Arvid Brodin   net/hsr: Better f...
38
39
  /* seq_nr_after(a, b) - return true if a is after (higher in sequence than) b,
   * false otherwise.
f421436a5   Arvid Brodin   net/hsr: Add supp...
40
   */
f266a683a   Arvid Brodin   net/hsr: Better f...
41
  static bool seq_nr_after(u16 a, u16 b)
f421436a5   Arvid Brodin   net/hsr: Add supp...
42
  {
f266a683a   Arvid Brodin   net/hsr: Better f...
43
44
45
46
47
  	/* Remove inconsistency where
  	 * seq_nr_after(a, b) == seq_nr_before(a, b)
  	 */
  	if ((int) b - a == 32768)
  		return false;
f421436a5   Arvid Brodin   net/hsr: Add supp...
48

f266a683a   Arvid Brodin   net/hsr: Better f...
49
  	return (((s16) (b - a)) < 0);
f421436a5   Arvid Brodin   net/hsr: Add supp...
50
  }
f266a683a   Arvid Brodin   net/hsr: Better f...
51
52
53
  #define seq_nr_before(a, b)		seq_nr_after((b), (a))
  #define seq_nr_after_or_eq(a, b)	(!seq_nr_before((a), (b)))
  #define seq_nr_before_or_eq(a, b)	(!seq_nr_after((a), (b)))
f421436a5   Arvid Brodin   net/hsr: Add supp...
54

f266a683a   Arvid Brodin   net/hsr: Better f...
55
  bool hsr_addr_is_self(struct hsr_priv *hsr, unsigned char *addr)
f421436a5   Arvid Brodin   net/hsr: Add supp...
56
  {
70ebe4a47   Arvid Brodin   net/hsr: Better v...
57
  	struct hsr_node *node;
f421436a5   Arvid Brodin   net/hsr: Add supp...
58

f266a683a   Arvid Brodin   net/hsr: Better f...
59
60
61
62
63
64
  	node = list_first_or_null_rcu(&hsr->self_node_db, struct hsr_node,
  				      mac_list);
  	if (!node) {
  		WARN_ONCE(1, "HSR: No self node
  ");
  		return false;
f421436a5   Arvid Brodin   net/hsr: Add supp...
65
  	}
f266a683a   Arvid Brodin   net/hsr: Better f...
66
67
68
69
  	if (ether_addr_equal(addr, node->MacAddressA))
  		return true;
  	if (ether_addr_equal(addr, node->MacAddressB))
  		return true;
f421436a5   Arvid Brodin   net/hsr: Add supp...
70

f266a683a   Arvid Brodin   net/hsr: Better f...
71
72
  	return false;
  }
f421436a5   Arvid Brodin   net/hsr: Add supp...
73
74
75
  
  /* Search for mac entry. Caller must hold rcu read lock.
   */
f266a683a   Arvid Brodin   net/hsr: Better f...
76
77
  static struct hsr_node *find_node_by_AddrA(struct list_head *node_db,
  					   const unsigned char addr[ETH_ALEN])
f421436a5   Arvid Brodin   net/hsr: Add supp...
78
  {
70ebe4a47   Arvid Brodin   net/hsr: Better v...
79
  	struct hsr_node *node;
f421436a5   Arvid Brodin   net/hsr: Add supp...
80
81
  
  	list_for_each_entry_rcu(node, node_db, mac_list) {
f266a683a   Arvid Brodin   net/hsr: Better f...
82
  		if (ether_addr_equal(node->MacAddressA, addr))
f421436a5   Arvid Brodin   net/hsr: Add supp...
83
84
85
86
87
88
89
90
91
92
93
94
95
96
  			return node;
  	}
  
  	return NULL;
  }
  
  
  /* Helper for device init; the self_node_db is used in hsr_rcv() to recognize
   * frames from self that's been looped over the HSR ring.
   */
  int hsr_create_self_node(struct list_head *self_node_db,
  			 unsigned char addr_a[ETH_ALEN],
  			 unsigned char addr_b[ETH_ALEN])
  {
70ebe4a47   Arvid Brodin   net/hsr: Better v...
97
  	struct hsr_node *node, *oldnode;
f421436a5   Arvid Brodin   net/hsr: Add supp...
98
99
100
101
  
  	node = kmalloc(sizeof(*node), GFP_KERNEL);
  	if (!node)
  		return -ENOMEM;
e83abe37b   Joe Perches   hsr: Use ether_ad...
102
103
  	ether_addr_copy(node->MacAddressA, addr_a);
  	ether_addr_copy(node->MacAddressB, addr_b);
f421436a5   Arvid Brodin   net/hsr: Add supp...
104
105
106
  
  	rcu_read_lock();
  	oldnode = list_first_or_null_rcu(self_node_db,
70ebe4a47   Arvid Brodin   net/hsr: Better v...
107
  						struct hsr_node, mac_list);
f421436a5   Arvid Brodin   net/hsr: Add supp...
108
109
110
111
112
113
114
115
116
117
118
119
  	if (oldnode) {
  		list_replace_rcu(&oldnode->mac_list, &node->mac_list);
  		rcu_read_unlock();
  		synchronize_rcu();
  		kfree(oldnode);
  	} else {
  		rcu_read_unlock();
  		list_add_tail_rcu(&node->mac_list, self_node_db);
  	}
  
  	return 0;
  }
f421436a5   Arvid Brodin   net/hsr: Add supp...
120

f266a683a   Arvid Brodin   net/hsr: Better f...
121
122
123
  /* Allocate an hsr_node and add it to node_db. 'addr' is the node's AddressA;
   * seq_out is used to initialize filtering of outgoing duplicate frames
   * originating from the newly added node.
f421436a5   Arvid Brodin   net/hsr: Add supp...
124
   */
f266a683a   Arvid Brodin   net/hsr: Better f...
125
126
  struct hsr_node *hsr_add_node(struct list_head *node_db, unsigned char addr[],
  			      u16 seq_out)
f421436a5   Arvid Brodin   net/hsr: Add supp...
127
  {
f266a683a   Arvid Brodin   net/hsr: Better f...
128
  	struct hsr_node *node;
f421436a5   Arvid Brodin   net/hsr: Add supp...
129
  	unsigned long now;
f266a683a   Arvid Brodin   net/hsr: Better f...
130
  	int i;
f421436a5   Arvid Brodin   net/hsr: Add supp...
131
132
133
134
  
  	node = kzalloc(sizeof(*node), GFP_ATOMIC);
  	if (!node)
  		return NULL;
f266a683a   Arvid Brodin   net/hsr: Better f...
135
  	ether_addr_copy(node->MacAddressA, addr);
f421436a5   Arvid Brodin   net/hsr: Add supp...
136
137
138
139
140
  
  	/* We are only interested in time diffs here, so use current jiffies
  	 * as initialization. (0 could trigger an spurious ring error warning).
  	 */
  	now = jiffies;
c5a759117   Arvid Brodin   net/hsr: Use list...
141
  	for (i = 0; i < HSR_PT_PORTS; i++)
f421436a5   Arvid Brodin   net/hsr: Add supp...
142
  		node->time_in[i] = now;
c5a759117   Arvid Brodin   net/hsr: Use list...
143
  	for (i = 0; i < HSR_PT_PORTS; i++)
f266a683a   Arvid Brodin   net/hsr: Better f...
144
  		node->seq_out[i] = seq_out;
f421436a5   Arvid Brodin   net/hsr: Add supp...
145

f266a683a   Arvid Brodin   net/hsr: Better f...
146
  	list_add_tail_rcu(&node->mac_list, node_db);
f421436a5   Arvid Brodin   net/hsr: Add supp...
147
148
149
  
  	return node;
  }
f266a683a   Arvid Brodin   net/hsr: Better f...
150
151
  /* Get the hsr_node from which 'skb' was sent.
   */
675c8da04   Karicheri, Muralidharan   hsr: fix incorrec...
152
  struct hsr_node *hsr_get_node(struct hsr_port *port, struct sk_buff *skb,
f266a683a   Arvid Brodin   net/hsr: Better f...
153
154
  			      bool is_sup)
  {
675c8da04   Karicheri, Muralidharan   hsr: fix incorrec...
155
  	struct list_head *node_db = &port->hsr->node_db;
f266a683a   Arvid Brodin   net/hsr: Better f...
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
  	struct hsr_node *node;
  	struct ethhdr *ethhdr;
  	u16 seq_out;
  
  	if (!skb_mac_header_was_set(skb))
  		return NULL;
  
  	ethhdr = (struct ethhdr *) skb_mac_header(skb);
  
  	list_for_each_entry_rcu(node, node_db, mac_list) {
  		if (ether_addr_equal(node->MacAddressA, ethhdr->h_source))
  			return node;
  		if (ether_addr_equal(node->MacAddressB, ethhdr->h_source))
  			return node;
  	}
ee1c27977   Peter Heise   net/hsr: Added su...
171
  	/* Everyone may create a node entry, connected node to a HSR device. */
f266a683a   Arvid Brodin   net/hsr: Better f...
172

ee1c27977   Peter Heise   net/hsr: Added su...
173
174
  	if (ethhdr->h_proto == htons(ETH_P_PRP)
  			|| ethhdr->h_proto == htons(ETH_P_HSR)) {
f266a683a   Arvid Brodin   net/hsr: Better f...
175
176
177
178
179
  		/* Use the existing sequence_nr from the tag as starting point
  		 * for filtering duplicate frames.
  		 */
  		seq_out = hsr_get_skb_sequence_nr(skb) - 1;
  	} else {
675c8da04   Karicheri, Muralidharan   hsr: fix incorrec...
180
181
182
183
184
185
  		/* this is called also for frames from master port and
  		 * so warn only for non master ports
  		 */
  		if (port->type != HSR_PT_MASTER)
  			WARN_ONCE(1, "%s: Non-HSR frame
  ", __func__);
ee1c27977   Peter Heise   net/hsr: Added su...
186
  		seq_out = HSR_SEQNR_START;
f266a683a   Arvid Brodin   net/hsr: Better f...
187
188
189
190
191
192
193
194
195
196
197
198
  	}
  
  	return hsr_add_node(node_db, ethhdr->h_source, seq_out);
  }
  
  /* Use the Supervision frame's info about an eventual MacAddressB for merging
   * nodes that has previously had their MacAddressB registered as a separate
   * node.
   */
  void hsr_handle_sup_frame(struct sk_buff *skb, struct hsr_node *node_curr,
  			  struct hsr_port *port_rcv)
  {
ee1c27977   Peter Heise   net/hsr: Added su...
199
  	struct ethhdr *ethhdr;
f266a683a   Arvid Brodin   net/hsr: Better f...
200
201
202
203
  	struct hsr_node *node_real;
  	struct hsr_sup_payload *hsr_sp;
  	struct list_head *node_db;
  	int i;
ee1c27977   Peter Heise   net/hsr: Added su...
204
  	ethhdr = (struct ethhdr *) skb_mac_header(skb);
f266a683a   Arvid Brodin   net/hsr: Better f...
205

ee1c27977   Peter Heise   net/hsr: Added su...
206
207
208
209
210
211
212
213
214
215
216
  	/* Leave the ethernet header. */
  	skb_pull(skb, sizeof(struct ethhdr));
  
  	/* And leave the HSR tag. */
  	if (ethhdr->h_proto == htons(ETH_P_HSR))
  		skb_pull(skb, sizeof(struct hsr_tag));
  
  	/* And leave the HSR sup tag. */
  	skb_pull(skb, sizeof(struct hsr_sup_tag));
  
  	hsr_sp = (struct hsr_sup_payload *) skb->data;
f266a683a   Arvid Brodin   net/hsr: Better f...
217
218
219
220
221
222
223
224
225
226
227
228
229
  
  	/* Merge node_curr (registered on MacAddressB) into node_real */
  	node_db = &port_rcv->hsr->node_db;
  	node_real = find_node_by_AddrA(node_db, hsr_sp->MacAddressA);
  	if (!node_real)
  		/* No frame received from AddrA of this node yet */
  		node_real = hsr_add_node(node_db, hsr_sp->MacAddressA,
  					 HSR_SEQNR_START - 1);
  	if (!node_real)
  		goto done; /* No mem */
  	if (node_real == node_curr)
  		/* Node has already been merged */
  		goto done;
ee1c27977   Peter Heise   net/hsr: Added su...
230
  	ether_addr_copy(node_real->MacAddressB, ethhdr->h_source);
f266a683a   Arvid Brodin   net/hsr: Better f...
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
  	for (i = 0; i < HSR_PT_PORTS; i++) {
  		if (!node_curr->time_in_stale[i] &&
  		    time_after(node_curr->time_in[i], node_real->time_in[i])) {
  			node_real->time_in[i] = node_curr->time_in[i];
  			node_real->time_in_stale[i] = node_curr->time_in_stale[i];
  		}
  		if (seq_nr_after(node_curr->seq_out[i], node_real->seq_out[i]))
  			node_real->seq_out[i] = node_curr->seq_out[i];
  	}
  	node_real->AddrB_port = port_rcv->type;
  
  	list_del_rcu(&node_curr->mac_list);
  	kfree_rcu(node_curr, rcu_head);
  
  done:
ee1c27977   Peter Heise   net/hsr: Added su...
246
  	skb_push(skb, sizeof(struct hsrv1_ethhdr_sp));
f266a683a   Arvid Brodin   net/hsr: Better f...
247
  }
f421436a5   Arvid Brodin   net/hsr: Add supp...
248
249
250
  
  /* 'skb' is a frame meant for this host, that is to be passed to upper layers.
   *
f266a683a   Arvid Brodin   net/hsr: Better f...
251
   * If the frame was sent by a node's B interface, replace the source
f421436a5   Arvid Brodin   net/hsr: Add supp...
252
253
254
   * address with that node's "official" address (MacAddressA) so that upper
   * layers recognize where it came from.
   */
f266a683a   Arvid Brodin   net/hsr: Better f...
255
  void hsr_addr_subst_source(struct hsr_node *node, struct sk_buff *skb)
f421436a5   Arvid Brodin   net/hsr: Add supp...
256
  {
f421436a5   Arvid Brodin   net/hsr: Add supp...
257
258
259
260
261
  	if (!skb_mac_header_was_set(skb)) {
  		WARN_ONCE(1, "%s: Mac header not set
  ", __func__);
  		return;
  	}
f421436a5   Arvid Brodin   net/hsr: Add supp...
262

f266a683a   Arvid Brodin   net/hsr: Better f...
263
  	memcpy(&eth_hdr(skb)->h_source, node->MacAddressA, ETH_ALEN);
f421436a5   Arvid Brodin   net/hsr: Add supp...
264
  }
f421436a5   Arvid Brodin   net/hsr: Add supp...
265
  /* 'skb' is a frame meant for another host.
f266a683a   Arvid Brodin   net/hsr: Better f...
266
   * 'port' is the outgoing interface
f421436a5   Arvid Brodin   net/hsr: Add supp...
267
268
269
270
271
272
273
   *
   * Substitute the target (dest) MAC address if necessary, so the it matches the
   * recipient interface MAC address, regardless of whether that is the
   * recipient's A or B interface.
   * This is needed to keep the packets flowing through switches that learn on
   * which "side" the different interfaces are.
   */
f266a683a   Arvid Brodin   net/hsr: Better f...
274
  void hsr_addr_subst_dest(struct hsr_node *node_src, struct sk_buff *skb,
c5a759117   Arvid Brodin   net/hsr: Use list...
275
  			 struct hsr_port *port)
f421436a5   Arvid Brodin   net/hsr: Add supp...
276
  {
f266a683a   Arvid Brodin   net/hsr: Better f...
277
  	struct hsr_node *node_dst;
f421436a5   Arvid Brodin   net/hsr: Add supp...
278

f266a683a   Arvid Brodin   net/hsr: Better f...
279
280
281
282
283
  	if (!skb_mac_header_was_set(skb)) {
  		WARN_ONCE(1, "%s: Mac header not set
  ", __func__);
  		return;
  	}
f421436a5   Arvid Brodin   net/hsr: Add supp...
284

f266a683a   Arvid Brodin   net/hsr: Better f...
285
286
  	if (!is_unicast_ether_addr(eth_hdr(skb)->h_dest))
  		return;
f421436a5   Arvid Brodin   net/hsr: Add supp...
287

f266a683a   Arvid Brodin   net/hsr: Better f...
288
289
290
291
292
293
294
295
  	node_dst = find_node_by_AddrA(&port->hsr->node_db, eth_hdr(skb)->h_dest);
  	if (!node_dst) {
  		WARN_ONCE(1, "%s: Unknown node
  ", __func__);
  		return;
  	}
  	if (port->type != node_dst->AddrB_port)
  		return;
f421436a5   Arvid Brodin   net/hsr: Add supp...
296

f266a683a   Arvid Brodin   net/hsr: Better f...
297
  	ether_addr_copy(eth_hdr(skb)->h_dest, node_dst->MacAddressB);
f421436a5   Arvid Brodin   net/hsr: Add supp...
298
  }
f421436a5   Arvid Brodin   net/hsr: Add supp...
299

f266a683a   Arvid Brodin   net/hsr: Better f...
300
301
  void hsr_register_frame_in(struct hsr_node *node, struct hsr_port *port,
  			   u16 sequence_nr)
f421436a5   Arvid Brodin   net/hsr: Add supp...
302
  {
f266a683a   Arvid Brodin   net/hsr: Better f...
303
304
305
306
307
308
  	/* Don't register incoming frames without a valid sequence number. This
  	 * ensures entries of restarted nodes gets pruned so that they can
  	 * re-register and resume communications.
  	 */
  	if (seq_nr_before(sequence_nr, node->seq_out[port->type]))
  		return;
c5a759117   Arvid Brodin   net/hsr: Use list...
309
310
  	node->time_in[port->type] = jiffies;
  	node->time_in_stale[port->type] = false;
f421436a5   Arvid Brodin   net/hsr: Add supp...
311
  }
f421436a5   Arvid Brodin   net/hsr: Add supp...
312
313
314
315
316
317
318
319
  /* 'skb' is a HSR Ethernet frame (with a HSR tag inserted), with a valid
   * ethhdr->h_source address and skb->mac_header set.
   *
   * Return:
   *	 1 if frame can be shown to have been sent recently on this interface,
   *	 0 otherwise, or
   *	 negative error code on error
   */
f266a683a   Arvid Brodin   net/hsr: Better f...
320
321
  int hsr_register_frame_out(struct hsr_port *port, struct hsr_node *node,
  			   u16 sequence_nr)
f421436a5   Arvid Brodin   net/hsr: Add supp...
322
  {
c5a759117   Arvid Brodin   net/hsr: Use list...
323
  	if (seq_nr_before_or_eq(sequence_nr, node->seq_out[port->type]))
f421436a5   Arvid Brodin   net/hsr: Add supp...
324
  		return 1;
c5a759117   Arvid Brodin   net/hsr: Use list...
325
  	node->seq_out[port->type] = sequence_nr;
f421436a5   Arvid Brodin   net/hsr: Add supp...
326
327
  	return 0;
  }
c5a759117   Arvid Brodin   net/hsr: Use list...
328
329
  static struct hsr_port *get_late_port(struct hsr_priv *hsr,
  				      struct hsr_node *node)
f421436a5   Arvid Brodin   net/hsr: Add supp...
330
  {
c5a759117   Arvid Brodin   net/hsr: Use list...
331
332
333
334
335
336
337
338
339
340
341
342
343
  	if (node->time_in_stale[HSR_PT_SLAVE_A])
  		return hsr_port_get_hsr(hsr, HSR_PT_SLAVE_A);
  	if (node->time_in_stale[HSR_PT_SLAVE_B])
  		return hsr_port_get_hsr(hsr, HSR_PT_SLAVE_B);
  
  	if (time_after(node->time_in[HSR_PT_SLAVE_B],
  		       node->time_in[HSR_PT_SLAVE_A] +
  					msecs_to_jiffies(MAX_SLAVE_DIFF)))
  		return hsr_port_get_hsr(hsr, HSR_PT_SLAVE_A);
  	if (time_after(node->time_in[HSR_PT_SLAVE_A],
  		       node->time_in[HSR_PT_SLAVE_B] +
  					msecs_to_jiffies(MAX_SLAVE_DIFF)))
  		return hsr_port_get_hsr(hsr, HSR_PT_SLAVE_B);
f421436a5   Arvid Brodin   net/hsr: Add supp...
344

c5a759117   Arvid Brodin   net/hsr: Use list...
345
  	return NULL;
f421436a5   Arvid Brodin   net/hsr: Add supp...
346
347
348
349
350
351
  }
  
  
  /* Remove stale sequence_nr records. Called by timer every
   * HSR_LIFE_CHECK_INTERVAL (two seconds or so).
   */
abff71627   Arvid Brodin   net/hsr: Move to ...
352
  void hsr_prune_nodes(unsigned long data)
f421436a5   Arvid Brodin   net/hsr: Add supp...
353
  {
abff71627   Arvid Brodin   net/hsr: Move to ...
354
  	struct hsr_priv *hsr;
70ebe4a47   Arvid Brodin   net/hsr: Better v...
355
  	struct hsr_node *node;
c5a759117   Arvid Brodin   net/hsr: Use list...
356
  	struct hsr_port *port;
f421436a5   Arvid Brodin   net/hsr: Add supp...
357
358
  	unsigned long timestamp;
  	unsigned long time_a, time_b;
abff71627   Arvid Brodin   net/hsr: Move to ...
359
  	hsr = (struct hsr_priv *) data;
f421436a5   Arvid Brodin   net/hsr: Add supp...
360
  	rcu_read_lock();
70ebe4a47   Arvid Brodin   net/hsr: Better v...
361
  	list_for_each_entry_rcu(node, &hsr->node_db, mac_list) {
f421436a5   Arvid Brodin   net/hsr: Add supp...
362
  		/* Shorthand */
c5a759117   Arvid Brodin   net/hsr: Use list...
363
364
  		time_a = node->time_in[HSR_PT_SLAVE_A];
  		time_b = node->time_in[HSR_PT_SLAVE_B];
f421436a5   Arvid Brodin   net/hsr: Add supp...
365
366
367
  
  		/* Check for timestamps old enough to risk wrap-around */
  		if (time_after(jiffies, time_a + MAX_JIFFY_OFFSET/2))
c5a759117   Arvid Brodin   net/hsr: Use list...
368
  			node->time_in_stale[HSR_PT_SLAVE_A] = true;
f421436a5   Arvid Brodin   net/hsr: Add supp...
369
  		if (time_after(jiffies, time_b + MAX_JIFFY_OFFSET/2))
c5a759117   Arvid Brodin   net/hsr: Use list...
370
  			node->time_in_stale[HSR_PT_SLAVE_B] = true;
f421436a5   Arvid Brodin   net/hsr: Add supp...
371
372
373
374
375
376
  
  		/* Get age of newest frame from node.
  		 * At least one time_in is OK here; nodes get pruned long
  		 * before both time_ins can get stale
  		 */
  		timestamp = time_a;
c5a759117   Arvid Brodin   net/hsr: Use list...
377
378
  		if (node->time_in_stale[HSR_PT_SLAVE_A] ||
  		    (!node->time_in_stale[HSR_PT_SLAVE_B] &&
f421436a5   Arvid Brodin   net/hsr: Add supp...
379
380
381
382
383
384
  		    time_after(time_b, time_a)))
  			timestamp = time_b;
  
  		/* Warn of ring error only as long as we get frames at all */
  		if (time_is_after_jiffies(timestamp +
  					msecs_to_jiffies(1.5*MAX_SLAVE_DIFF))) {
c5a759117   Arvid Brodin   net/hsr: Use list...
385
386
387
388
389
  			rcu_read_lock();
  			port = get_late_port(hsr, node);
  			if (port != NULL)
  				hsr_nl_ringerror(hsr, node->MacAddressA, port);
  			rcu_read_unlock();
f421436a5   Arvid Brodin   net/hsr: Add supp...
390
391
392
393
394
  		}
  
  		/* Prune old entries */
  		if (time_is_before_jiffies(timestamp +
  					msecs_to_jiffies(HSR_NODE_FORGET_TIME))) {
70ebe4a47   Arvid Brodin   net/hsr: Better v...
395
  			hsr_nl_nodedown(hsr, node->MacAddressA);
f421436a5   Arvid Brodin   net/hsr: Add supp...
396
397
  			list_del_rcu(&node->mac_list);
  			/* Note that we need to free this entry later: */
1aee6cc2a   Wei Yongjun   net/hsr: using kf...
398
  			kfree_rcu(node, rcu_head);
f421436a5   Arvid Brodin   net/hsr: Add supp...
399
400
401
402
  		}
  	}
  	rcu_read_unlock();
  }
70ebe4a47   Arvid Brodin   net/hsr: Better v...
403
  void *hsr_get_next_node(struct hsr_priv *hsr, void *_pos,
f421436a5   Arvid Brodin   net/hsr: Add supp...
404
405
  			unsigned char addr[ETH_ALEN])
  {
70ebe4a47   Arvid Brodin   net/hsr: Better v...
406
  	struct hsr_node *node;
f421436a5   Arvid Brodin   net/hsr: Add supp...
407
408
  
  	if (!_pos) {
70ebe4a47   Arvid Brodin   net/hsr: Better v...
409
410
  		node = list_first_or_null_rcu(&hsr->node_db,
  					      struct hsr_node, mac_list);
f421436a5   Arvid Brodin   net/hsr: Add supp...
411
  		if (node)
e83abe37b   Joe Perches   hsr: Use ether_ad...
412
  			ether_addr_copy(addr, node->MacAddressA);
f421436a5   Arvid Brodin   net/hsr: Add supp...
413
414
415
416
  		return node;
  	}
  
  	node = _pos;
70ebe4a47   Arvid Brodin   net/hsr: Better v...
417
  	list_for_each_entry_continue_rcu(node, &hsr->node_db, mac_list) {
e83abe37b   Joe Perches   hsr: Use ether_ad...
418
  		ether_addr_copy(addr, node->MacAddressA);
f421436a5   Arvid Brodin   net/hsr: Add supp...
419
420
421
422
423
  		return node;
  	}
  
  	return NULL;
  }
70ebe4a47   Arvid Brodin   net/hsr: Better v...
424
  int hsr_get_node_data(struct hsr_priv *hsr,
f421436a5   Arvid Brodin   net/hsr: Add supp...
425
426
427
428
429
430
431
432
  		      const unsigned char *addr,
  		      unsigned char addr_b[ETH_ALEN],
  		      unsigned int *addr_b_ifindex,
  		      int *if1_age,
  		      u16 *if1_seq,
  		      int *if2_age,
  		      u16 *if2_seq)
  {
70ebe4a47   Arvid Brodin   net/hsr: Better v...
433
  	struct hsr_node *node;
c5a759117   Arvid Brodin   net/hsr: Use list...
434
  	struct hsr_port *port;
f421436a5   Arvid Brodin   net/hsr: Add supp...
435
436
437
438
  	unsigned long tdiff;
  
  
  	rcu_read_lock();
70ebe4a47   Arvid Brodin   net/hsr: Better v...
439
  	node = find_node_by_AddrA(&hsr->node_db, addr);
f421436a5   Arvid Brodin   net/hsr: Add supp...
440
441
442
443
  	if (!node) {
  		rcu_read_unlock();
  		return -ENOENT;	/* No such entry */
  	}
e83abe37b   Joe Perches   hsr: Use ether_ad...
444
  	ether_addr_copy(addr_b, node->MacAddressB);
f421436a5   Arvid Brodin   net/hsr: Add supp...
445

c5a759117   Arvid Brodin   net/hsr: Use list...
446
447
  	tdiff = jiffies - node->time_in[HSR_PT_SLAVE_A];
  	if (node->time_in_stale[HSR_PT_SLAVE_A])
f421436a5   Arvid Brodin   net/hsr: Add supp...
448
449
450
451
452
453
454
  		*if1_age = INT_MAX;
  #if HZ <= MSEC_PER_SEC
  	else if (tdiff > msecs_to_jiffies(INT_MAX))
  		*if1_age = INT_MAX;
  #endif
  	else
  		*if1_age = jiffies_to_msecs(tdiff);
c5a759117   Arvid Brodin   net/hsr: Use list...
455
456
  	tdiff = jiffies - node->time_in[HSR_PT_SLAVE_B];
  	if (node->time_in_stale[HSR_PT_SLAVE_B])
f421436a5   Arvid Brodin   net/hsr: Add supp...
457
458
459
460
461
462
463
464
465
  		*if2_age = INT_MAX;
  #if HZ <= MSEC_PER_SEC
  	else if (tdiff > msecs_to_jiffies(INT_MAX))
  		*if2_age = INT_MAX;
  #endif
  	else
  		*if2_age = jiffies_to_msecs(tdiff);
  
  	/* Present sequence numbers as if they were incoming on interface */
c5a759117   Arvid Brodin   net/hsr: Use list...
466
467
  	*if1_seq = node->seq_out[HSR_PT_SLAVE_B];
  	*if2_seq = node->seq_out[HSR_PT_SLAVE_A];
f421436a5   Arvid Brodin   net/hsr: Add supp...
468

c5a759117   Arvid Brodin   net/hsr: Use list...
469
470
471
472
  	if (node->AddrB_port != HSR_PT_NONE) {
  		port = hsr_port_get_hsr(hsr, node->AddrB_port);
  		*addr_b_ifindex = port->dev->ifindex;
  	} else {
f421436a5   Arvid Brodin   net/hsr: Add supp...
473
  		*addr_b_ifindex = -1;
c5a759117   Arvid Brodin   net/hsr: Use list...
474
  	}
f421436a5   Arvid Brodin   net/hsr: Add supp...
475
476
477
478
479
  
  	rcu_read_unlock();
  
  	return 0;
  }