aboutsummaryrefslogtreecommitdiffstats
path: root/net/tipc/node.c
diff options
context:
space:
mode:
Diffstat (limited to 'net/tipc/node.c')
-rw-r--r--net/tipc/node.c166
1 files changed, 7 insertions, 159 deletions
diff --git a/net/tipc/node.c b/net/tipc/node.c
index 8ffbdb33b2c..c47cc69eb57 100644
--- a/net/tipc/node.c
+++ b/net/tipc/node.c
@@ -95,11 +95,10 @@ struct tipc_node *tipc_node_create(u32 addr)
95 } 95 }
96 96
97 n_ptr->addr = addr; 97 n_ptr->addr = addr;
98 spin_lock_init(&n_ptr->lock); 98 spin_lock_init(&n_ptr->lock);
99 INIT_LIST_HEAD(&n_ptr->nsub); 99 INIT_LIST_HEAD(&n_ptr->nsub);
100 n_ptr->owner = c_ptr; 100 n_ptr->owner = c_ptr;
101 tipc_cltr_attach_node(c_ptr, n_ptr); 101 tipc_cltr_attach_node(c_ptr, n_ptr);
102 n_ptr->last_router = -1;
103 102
104 /* Insert node into ordered list */ 103 /* Insert node into ordered list */
105 for (curr_node = &tipc_nodes; *curr_node; 104 for (curr_node = &tipc_nodes; *curr_node;
@@ -229,14 +228,9 @@ int tipc_node_has_redundant_links(struct tipc_node *n_ptr)
229 return n_ptr->working_links > 1; 228 return n_ptr->working_links > 1;
230} 229}
231 230
232static int tipc_node_has_active_routes(struct tipc_node *n_ptr)
233{
234 return n_ptr && (n_ptr->last_router >= 0);
235}
236
237int tipc_node_is_up(struct tipc_node *n_ptr) 231int tipc_node_is_up(struct tipc_node *n_ptr)
238{ 232{
239 return tipc_node_has_active_links(n_ptr) || tipc_node_has_active_routes(n_ptr); 233 return tipc_node_has_active_links(n_ptr);
240} 234}
241 235
242struct tipc_node *tipc_node_attach_link(struct link *l_ptr) 236struct tipc_node *tipc_node_attach_link(struct link *l_ptr)
@@ -323,36 +317,17 @@ void tipc_node_detach_link(struct tipc_node *n_ptr, struct link *l_ptr)
323 317
324static void node_established_contact(struct tipc_node *n_ptr) 318static void node_established_contact(struct tipc_node *n_ptr)
325{ 319{
326 struct cluster *c_ptr;
327
328 dbg("node_established_contact:-> %x\n", n_ptr->addr); 320 dbg("node_established_contact:-> %x\n", n_ptr->addr);
329 if (!tipc_node_has_active_routes(n_ptr) && in_own_cluster(n_ptr->addr)) { 321 tipc_k_signal((Handler)tipc_named_node_up, n_ptr->addr);
330 tipc_k_signal((Handler)tipc_named_node_up, n_ptr->addr);
331 }
332 322
333 /* Syncronize broadcast acks */ 323 /* Syncronize broadcast acks */
334 n_ptr->bclink.acked = tipc_bclink_get_last_sent(); 324 n_ptr->bclink.acked = tipc_bclink_get_last_sent();
335 325
336 if (!in_own_cluster(n_ptr->addr)) {
337 /* Usage case 1 (see above) */
338 c_ptr = tipc_cltr_find(tipc_own_addr);
339 if (!c_ptr)
340 c_ptr = tipc_cltr_create(tipc_own_addr);
341 if (c_ptr)
342 tipc_cltr_bcast_new_route(c_ptr, n_ptr->addr, 1,
343 tipc_max_nodes);
344 return;
345 }
346
347 c_ptr = n_ptr->owner;
348 if (n_ptr->bclink.supported) { 326 if (n_ptr->bclink.supported) {
349 tipc_nmap_add(&tipc_cltr_bcast_nodes, n_ptr->addr); 327 tipc_nmap_add(&tipc_cltr_bcast_nodes, n_ptr->addr);
350 if (n_ptr->addr < tipc_own_addr) 328 if (n_ptr->addr < tipc_own_addr)
351 tipc_own_tag++; 329 tipc_own_tag++;
352 } 330 }
353
354 /* Case 3 (see above) */
355 tipc_net_send_external_routes(n_ptr->addr);
356} 331}
357 332
358static void node_cleanup_finished(unsigned long node_addr) 333static void node_cleanup_finished(unsigned long node_addr)
@@ -371,7 +346,6 @@ static void node_cleanup_finished(unsigned long node_addr)
371 346
372static void node_lost_contact(struct tipc_node *n_ptr) 347static void node_lost_contact(struct tipc_node *n_ptr)
373{ 348{
374 struct cluster *c_ptr;
375 struct tipc_node_subscr *ns, *tns; 349 struct tipc_node_subscr *ns, *tns;
376 char addr_string[16]; 350 char addr_string[16];
377 u32 i; 351 u32 i;
@@ -392,23 +366,11 @@ static void node_lost_contact(struct tipc_node *n_ptr)
392 } 366 }
393 367
394 /* Update routing tables */ 368 /* Update routing tables */
395 if (!in_own_cluster(n_ptr->addr)) { 369 if (n_ptr->bclink.supported) {
396 /* Case 4 (see above) */ 370 tipc_nmap_remove(&tipc_cltr_bcast_nodes, n_ptr->addr);
397 c_ptr = tipc_cltr_find(tipc_own_addr); 371 if (n_ptr->addr < tipc_own_addr)
398 tipc_cltr_bcast_lost_route(c_ptr, n_ptr->addr, 1, 372 tipc_own_tag--;
399 tipc_max_nodes);
400 } else {
401 /* Case 5 (see above) */
402 c_ptr = tipc_cltr_find(n_ptr->addr);
403 if (n_ptr->bclink.supported) {
404 tipc_nmap_remove(&tipc_cltr_bcast_nodes, n_ptr->addr);
405 if (n_ptr->addr < tipc_own_addr)
406 tipc_own_tag--;
407 }
408 tipc_net_remove_as_router(n_ptr->addr);
409 } 373 }
410 if (tipc_node_has_active_routes(n_ptr))
411 return;
412 374
413 info("Lost contact with %s\n", 375 info("Lost contact with %s\n",
414 tipc_addr_string_fill(addr_string, n_ptr->addr)); 376 tipc_addr_string_fill(addr_string, n_ptr->addr));
@@ -437,120 +399,6 @@ static void node_lost_contact(struct tipc_node *n_ptr)
437 tipc_k_signal((Handler)node_cleanup_finished, n_ptr->addr); 399 tipc_k_signal((Handler)node_cleanup_finished, n_ptr->addr);
438} 400}
439 401
440/**
441 * tipc_node_select_next_hop - find the next-hop node for a message
442 *
443 * Called by when cluster local lookup has failed.
444 */
445
446struct tipc_node *tipc_node_select_next_hop(u32 addr, u32 selector)
447{
448 struct tipc_node *n_ptr;
449 u32 router_addr;
450
451 if (!tipc_addr_domain_valid(addr))
452 return NULL;
453
454 /* Look for direct link to destination processsor */
455 n_ptr = tipc_node_find(addr);
456 if (n_ptr && tipc_node_has_active_links(n_ptr))
457 return n_ptr;
458
459 /* Cluster local system nodes *must* have direct links */
460 if (in_own_cluster(addr))
461 return NULL;
462
463 /* Look for cluster local router with direct link to node */
464 router_addr = tipc_node_select_router(n_ptr, selector);
465 if (router_addr)
466 return tipc_node_select(router_addr, selector);
467
468 /* Inter zone/cluster -- find any direct link to remote cluster */
469 addr = tipc_addr(tipc_zone(addr), tipc_cluster(addr), 0);
470 n_ptr = tipc_net_select_remote_node(addr, selector);
471 if (n_ptr && tipc_node_has_active_links(n_ptr))
472 return n_ptr;
473
474 /* Last resort -- look for any router to anywhere in remote zone */
475 router_addr = tipc_net_select_router(addr, selector);
476 if (router_addr)
477 return tipc_node_select(router_addr, selector);
478
479 return NULL;
480}
481
482/**
483 * tipc_node_select_router - select router to reach specified node
484 *
485 * Uses a deterministic and fair algorithm for selecting router node.
486 */
487
488u32 tipc_node_select_router(struct tipc_node *n_ptr, u32 ref)
489{
490 u32 ulim;
491 u32 mask;
492 u32 start;
493 u32 r;
494
495 if (!n_ptr)
496 return 0;
497
498 if (n_ptr->last_router < 0)
499 return 0;
500 ulim = ((n_ptr->last_router + 1) * 32) - 1;
501
502 /* Start entry must be random */
503 mask = tipc_max_nodes;
504 while (mask > ulim)
505 mask >>= 1;
506 start = ref & mask;
507 r = start;
508
509 /* Lookup upwards with wrap-around */
510 do {
511 if (((n_ptr->routers[r / 32]) >> (r % 32)) & 1)
512 break;
513 } while (++r <= ulim);
514 if (r > ulim) {
515 r = 1;
516 do {
517 if (((n_ptr->routers[r / 32]) >> (r % 32)) & 1)
518 break;
519 } while (++r < start);
520 assert(r != start);
521 }
522 assert(r && (r <= ulim));
523 return tipc_addr(own_zone(), own_cluster(), r);
524}
525
526void tipc_node_add_router(struct tipc_node *n_ptr, u32 router)
527{
528 u32 r_num = tipc_node(router);
529
530 n_ptr->routers[r_num / 32] =
531 ((1 << (r_num % 32)) | n_ptr->routers[r_num / 32]);
532 n_ptr->last_router = tipc_max_nodes / 32;
533 while ((--n_ptr->last_router >= 0) &&
534 !n_ptr->routers[n_ptr->last_router]);
535}
536
537void tipc_node_remove_router(struct tipc_node *n_ptr, u32 router)
538{
539 u32 r_num = tipc_node(router);
540
541 if (n_ptr->last_router < 0)
542 return; /* No routes */
543
544 n_ptr->routers[r_num / 32] =
545 ((~(1 << (r_num % 32))) & (n_ptr->routers[r_num / 32]));
546 n_ptr->last_router = tipc_max_nodes / 32;
547 while ((--n_ptr->last_router >= 0) &&
548 !n_ptr->routers[n_ptr->last_router]);
549
550 if (!tipc_node_is_up(n_ptr))
551 node_lost_contact(n_ptr);
552}
553
554struct sk_buff *tipc_node_get_nodes(const void *req_tlv_area, int req_tlv_space) 402struct sk_buff *tipc_node_get_nodes(const void *req_tlv_area, int req_tlv_space)
555{ 403{
556 u32 domain; 404 u32 domain;