1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37#include "core.h"
38#include "config.h"
39#include "node.h"
40#include "name_distr.h"
41
42static void node_lost_contact(struct tipc_node *n_ptr);
43static void node_established_contact(struct tipc_node *n_ptr);
44
45static DEFINE_SPINLOCK(node_create_lock);
46
47static struct hlist_head node_htable[NODE_HTABLE_SIZE];
48LIST_HEAD(tipc_node_list);
49static u32 tipc_num_nodes;
50
51static atomic_t tipc_num_links = ATOMIC_INIT(0);
52u32 tipc_own_tag;
53
54
55
56
57
58struct tipc_node *tipc_node_find(u32 addr)
59{
60 struct tipc_node *node;
61 struct hlist_node *pos;
62
63 if (unlikely(!in_own_cluster(addr)))
64 return NULL;
65
66 hlist_for_each_entry(node, pos, &node_htable[tipc_hashfn(addr)], hash) {
67 if (node->addr == addr)
68 return node;
69 }
70 return NULL;
71}
72
73
74
75
76
77
78
79
80
81
82
83struct tipc_node *tipc_node_create(u32 addr)
84{
85 struct tipc_node *n_ptr, *temp_node;
86
87 spin_lock_bh(&node_create_lock);
88
89 n_ptr = tipc_node_find(addr);
90 if (n_ptr) {
91 spin_unlock_bh(&node_create_lock);
92 return n_ptr;
93 }
94
95 n_ptr = kzalloc(sizeof(*n_ptr), GFP_ATOMIC);
96 if (!n_ptr) {
97 spin_unlock_bh(&node_create_lock);
98 warn("Node creation failed, no memory\n");
99 return NULL;
100 }
101
102 n_ptr->addr = addr;
103 spin_lock_init(&n_ptr->lock);
104 INIT_HLIST_NODE(&n_ptr->hash);
105 INIT_LIST_HEAD(&n_ptr->list);
106 INIT_LIST_HEAD(&n_ptr->nsub);
107
108 hlist_add_head(&n_ptr->hash, &node_htable[tipc_hashfn(addr)]);
109
110 list_for_each_entry(temp_node, &tipc_node_list, list) {
111 if (n_ptr->addr < temp_node->addr)
112 break;
113 }
114 list_add_tail(&n_ptr->list, &temp_node->list);
115 n_ptr->block_setup = WAIT_PEER_DOWN;
116
117 tipc_num_nodes++;
118
119 spin_unlock_bh(&node_create_lock);
120 return n_ptr;
121}
122
123void tipc_node_delete(struct tipc_node *n_ptr)
124{
125 list_del(&n_ptr->list);
126 hlist_del(&n_ptr->hash);
127 kfree(n_ptr);
128
129 tipc_num_nodes--;
130}
131
132
133
134
135
136
137
138
139void tipc_node_link_up(struct tipc_node *n_ptr, struct tipc_link *l_ptr)
140{
141 struct tipc_link **active = &n_ptr->active_links[0];
142
143 n_ptr->working_links++;
144
145 info("Established link <%s> on network plane %c\n",
146 l_ptr->name, l_ptr->b_ptr->net_plane);
147
148 if (!active[0]) {
149 active[0] = active[1] = l_ptr;
150 node_established_contact(n_ptr);
151 return;
152 }
153 if (l_ptr->priority < active[0]->priority) {
154 info("New link <%s> becomes standby\n", l_ptr->name);
155 return;
156 }
157 tipc_link_send_duplicate(active[0], l_ptr);
158 if (l_ptr->priority == active[0]->priority) {
159 active[0] = l_ptr;
160 return;
161 }
162 info("Old link <%s> becomes standby\n", active[0]->name);
163 if (active[1] != active[0])
164 info("Old link <%s> becomes standby\n", active[1]->name);
165 active[0] = active[1] = l_ptr;
166}
167
168
169
170
171
172static void node_select_active_links(struct tipc_node *n_ptr)
173{
174 struct tipc_link **active = &n_ptr->active_links[0];
175 u32 i;
176 u32 highest_prio = 0;
177
178 active[0] = active[1] = NULL;
179
180 for (i = 0; i < MAX_BEARERS; i++) {
181 struct tipc_link *l_ptr = n_ptr->links[i];
182
183 if (!l_ptr || !tipc_link_is_up(l_ptr) ||
184 (l_ptr->priority < highest_prio))
185 continue;
186
187 if (l_ptr->priority > highest_prio) {
188 highest_prio = l_ptr->priority;
189 active[0] = active[1] = l_ptr;
190 } else {
191 active[1] = l_ptr;
192 }
193 }
194}
195
196
197
198
199
200void tipc_node_link_down(struct tipc_node *n_ptr, struct tipc_link *l_ptr)
201{
202 struct tipc_link **active;
203
204 n_ptr->working_links--;
205
206 if (!tipc_link_is_active(l_ptr)) {
207 info("Lost standby link <%s> on network plane %c\n",
208 l_ptr->name, l_ptr->b_ptr->net_plane);
209 return;
210 }
211 info("Lost link <%s> on network plane %c\n",
212 l_ptr->name, l_ptr->b_ptr->net_plane);
213
214 active = &n_ptr->active_links[0];
215 if (active[0] == l_ptr)
216 active[0] = active[1];
217 if (active[1] == l_ptr)
218 active[1] = active[0];
219 if (active[0] == l_ptr)
220 node_select_active_links(n_ptr);
221 if (tipc_node_is_up(n_ptr))
222 tipc_link_changeover(l_ptr);
223 else
224 node_lost_contact(n_ptr);
225}
226
227int tipc_node_active_links(struct tipc_node *n_ptr)
228{
229 return n_ptr->active_links[0] != NULL;
230}
231
232int tipc_node_redundant_links(struct tipc_node *n_ptr)
233{
234 return n_ptr->working_links > 1;
235}
236
237int tipc_node_is_up(struct tipc_node *n_ptr)
238{
239 return tipc_node_active_links(n_ptr);
240}
241
242void tipc_node_attach_link(struct tipc_node *n_ptr, struct tipc_link *l_ptr)
243{
244 n_ptr->links[l_ptr->b_ptr->identity] = l_ptr;
245 atomic_inc(&tipc_num_links);
246 n_ptr->link_cnt++;
247}
248
249void tipc_node_detach_link(struct tipc_node *n_ptr, struct tipc_link *l_ptr)
250{
251 n_ptr->links[l_ptr->b_ptr->identity] = NULL;
252 atomic_dec(&tipc_num_links);
253 n_ptr->link_cnt--;
254}
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302static void node_established_contact(struct tipc_node *n_ptr)
303{
304 tipc_k_signal((Handler)tipc_named_node_up, n_ptr->addr);
305
306
307 n_ptr->bclink.acked = tipc_bclink_get_last_sent();
308
309 if (n_ptr->bclink.supported) {
310 tipc_bclink_add_node(n_ptr->addr);
311 if (n_ptr->addr < tipc_own_addr)
312 tipc_own_tag++;
313 }
314}
315
316static void node_name_purge_complete(unsigned long node_addr)
317{
318 struct tipc_node *n_ptr;
319
320 read_lock_bh(&tipc_net_lock);
321 n_ptr = tipc_node_find(node_addr);
322 if (n_ptr) {
323 tipc_node_lock(n_ptr);
324 n_ptr->block_setup &= ~WAIT_NAMES_GONE;
325 tipc_node_unlock(n_ptr);
326 }
327 read_unlock_bh(&tipc_net_lock);
328}
329
330static void node_lost_contact(struct tipc_node *n_ptr)
331{
332 char addr_string[16];
333 u32 i;
334
335 info("Lost contact with %s\n",
336 tipc_addr_string_fill(addr_string, n_ptr->addr));
337
338
339
340 if (n_ptr->bclink.supported) {
341 n_ptr->bclink.gap_after = n_ptr->bclink.gap_to = 0;
342 while (n_ptr->bclink.deferred_head) {
343 struct sk_buff *buf = n_ptr->bclink.deferred_head;
344 n_ptr->bclink.deferred_head = buf->next;
345 buf_discard(buf);
346 }
347
348 if (n_ptr->bclink.defragm) {
349 buf_discard(n_ptr->bclink.defragm);
350 n_ptr->bclink.defragm = NULL;
351 }
352
353 tipc_bclink_remove_node(n_ptr->addr);
354 tipc_bclink_acknowledge(n_ptr, INVALID_LINK_SEQ);
355 if (n_ptr->addr < tipc_own_addr)
356 tipc_own_tag--;
357
358 n_ptr->bclink.supported = 0;
359 }
360
361
362 for (i = 0; i < MAX_BEARERS; i++) {
363 struct tipc_link *l_ptr = n_ptr->links[i];
364 if (!l_ptr)
365 continue;
366 l_ptr->reset_checkpoint = l_ptr->next_in_no;
367 l_ptr->exp_msg_count = 0;
368 tipc_link_reset_fragments(l_ptr);
369 }
370
371
372 tipc_nodesub_notify(n_ptr);
373
374
375
376 n_ptr->block_setup = WAIT_PEER_DOWN | WAIT_NAMES_GONE;
377 tipc_k_signal((Handler)node_name_purge_complete, n_ptr->addr);
378}
379
380struct sk_buff *tipc_node_get_nodes(const void *req_tlv_area, int req_tlv_space)
381{
382 u32 domain;
383 struct sk_buff *buf;
384 struct tipc_node *n_ptr;
385 struct tipc_node_info node_info;
386 u32 payload_size;
387
388 if (!TLV_CHECK(req_tlv_area, req_tlv_space, TIPC_TLV_NET_ADDR))
389 return tipc_cfg_reply_error_string(TIPC_CFG_TLV_ERROR);
390
391 domain = ntohl(*(__be32 *)TLV_DATA(req_tlv_area));
392 if (!tipc_addr_domain_valid(domain))
393 return tipc_cfg_reply_error_string(TIPC_CFG_INVALID_VALUE
394 " (network address)");
395
396 read_lock_bh(&tipc_net_lock);
397 if (!tipc_num_nodes) {
398 read_unlock_bh(&tipc_net_lock);
399 return tipc_cfg_reply_none();
400 }
401
402
403
404 payload_size = TLV_SPACE(sizeof(node_info)) * tipc_num_nodes;
405 if (payload_size > 32768u) {
406 read_unlock_bh(&tipc_net_lock);
407 return tipc_cfg_reply_error_string(TIPC_CFG_NOT_SUPPORTED
408 " (too many nodes)");
409 }
410 buf = tipc_cfg_reply_alloc(payload_size);
411 if (!buf) {
412 read_unlock_bh(&tipc_net_lock);
413 return NULL;
414 }
415
416
417
418 list_for_each_entry(n_ptr, &tipc_node_list, list) {
419 if (!tipc_in_scope(domain, n_ptr->addr))
420 continue;
421 node_info.addr = htonl(n_ptr->addr);
422 node_info.up = htonl(tipc_node_is_up(n_ptr));
423 tipc_cfg_append_tlv(buf, TIPC_TLV_NODE_INFO,
424 &node_info, sizeof(node_info));
425 }
426
427 read_unlock_bh(&tipc_net_lock);
428 return buf;
429}
430
431struct sk_buff *tipc_node_get_links(const void *req_tlv_area, int req_tlv_space)
432{
433 u32 domain;
434 struct sk_buff *buf;
435 struct tipc_node *n_ptr;
436 struct tipc_link_info link_info;
437 u32 payload_size;
438
439 if (!TLV_CHECK(req_tlv_area, req_tlv_space, TIPC_TLV_NET_ADDR))
440 return tipc_cfg_reply_error_string(TIPC_CFG_TLV_ERROR);
441
442 domain = ntohl(*(__be32 *)TLV_DATA(req_tlv_area));
443 if (!tipc_addr_domain_valid(domain))
444 return tipc_cfg_reply_error_string(TIPC_CFG_INVALID_VALUE
445 " (network address)");
446
447 if (tipc_mode != TIPC_NET_MODE)
448 return tipc_cfg_reply_none();
449
450 read_lock_bh(&tipc_net_lock);
451
452
453
454 payload_size = TLV_SPACE(sizeof(link_info)) *
455 (atomic_read(&tipc_num_links) + 1);
456 if (payload_size > 32768u) {
457 read_unlock_bh(&tipc_net_lock);
458 return tipc_cfg_reply_error_string(TIPC_CFG_NOT_SUPPORTED
459 " (too many links)");
460 }
461 buf = tipc_cfg_reply_alloc(payload_size);
462 if (!buf) {
463 read_unlock_bh(&tipc_net_lock);
464 return NULL;
465 }
466
467
468
469 link_info.dest = htonl(tipc_cluster_mask(tipc_own_addr));
470 link_info.up = htonl(1);
471 strlcpy(link_info.str, tipc_bclink_name, TIPC_MAX_LINK_NAME);
472 tipc_cfg_append_tlv(buf, TIPC_TLV_LINK_INFO, &link_info, sizeof(link_info));
473
474
475
476 list_for_each_entry(n_ptr, &tipc_node_list, list) {
477 u32 i;
478
479 if (!tipc_in_scope(domain, n_ptr->addr))
480 continue;
481 tipc_node_lock(n_ptr);
482 for (i = 0; i < MAX_BEARERS; i++) {
483 if (!n_ptr->links[i])
484 continue;
485 link_info.dest = htonl(n_ptr->addr);
486 link_info.up = htonl(tipc_link_is_up(n_ptr->links[i]));
487 strcpy(link_info.str, n_ptr->links[i]->name);
488 tipc_cfg_append_tlv(buf, TIPC_TLV_LINK_INFO,
489 &link_info, sizeof(link_info));
490 }
491 tipc_node_unlock(n_ptr);
492 }
493
494 read_unlock_bh(&tipc_net_lock);
495 return buf;
496}
497