@@ -89,6 +89,7 @@ struct tipc_bclink_entry {
89
89
* @links: array containing references to all links to node
90
90
* @action_flags: bit mask of different types of node actions
91
91
* @state: connectivity state vs peer node
92
+ * @preliminary: a preliminary node or not
92
93
* @sync_point: sequence number where synch/failover is finished
93
94
* @list: links to adjacent nodes in sorted list of cluster's nodes
94
95
* @working_links: number of working links to node (both active and standby)
@@ -112,6 +113,7 @@ struct tipc_node {
112
113
int action_flags ;
113
114
struct list_head list ;
114
115
int state ;
116
+ bool preliminary ;
115
117
bool failover_sent ;
116
118
u16 sync_point ;
117
119
int link_cnt ;
@@ -120,6 +122,7 @@ struct tipc_node {
120
122
u32 signature ;
121
123
u32 link_id ;
122
124
u8 peer_id [16 ];
125
+ char peer_id_string [NODE_ID_STR_LEN ];
123
126
struct list_head publ_list ;
124
127
struct list_head conn_sks ;
125
128
unsigned long keepalive_intv ;
@@ -245,6 +248,16 @@ u16 tipc_node_get_capabilities(struct net *net, u32 addr)
245
248
return caps ;
246
249
}
247
250
251
+ u32 tipc_node_get_addr (struct tipc_node * node )
252
+ {
253
+ return (node ) ? node -> addr : 0 ;
254
+ }
255
+
256
+ char * tipc_node_get_id_str (struct tipc_node * node )
257
+ {
258
+ return node -> peer_id_string ;
259
+ }
260
+
248
261
static void tipc_node_kref_release (struct kref * kref )
249
262
{
250
263
struct tipc_node * n = container_of (kref , struct tipc_node , kref );
@@ -274,7 +287,7 @@ static struct tipc_node *tipc_node_find(struct net *net, u32 addr)
274
287
275
288
rcu_read_lock ();
276
289
hlist_for_each_entry_rcu (node , & tn -> node_htable [thash ], hash ) {
277
- if (node -> addr != addr )
290
+ if (node -> addr != addr || node -> preliminary )
278
291
continue ;
279
292
if (!kref_get_unless_zero (& node -> kref ))
280
293
node = NULL ;
@@ -400,17 +413,39 @@ static void tipc_node_assign_peer_net(struct tipc_node *n, u32 hash_mixes)
400
413
401
414
static struct tipc_node * tipc_node_create (struct net * net , u32 addr ,
402
415
u8 * peer_id , u16 capabilities ,
403
- u32 signature , u32 hash_mixes )
416
+ u32 hash_mixes , bool preliminary )
404
417
{
405
418
struct tipc_net * tn = net_generic (net , tipc_net_id );
406
419
struct tipc_node * n , * temp_node ;
407
420
struct tipc_link * l ;
421
+ unsigned long intv ;
408
422
int bearer_id ;
409
423
int i ;
410
424
411
425
spin_lock_bh (& tn -> node_list_lock );
412
- n = tipc_node_find (net , addr );
426
+ n = tipc_node_find (net , addr ) ?:
427
+ tipc_node_find_by_id (net , peer_id );
413
428
if (n ) {
429
+ if (!n -> preliminary )
430
+ goto update ;
431
+ if (preliminary )
432
+ goto exit ;
433
+ /* A preliminary node becomes "real" now, refresh its data */
434
+ tipc_node_write_lock (n );
435
+ n -> preliminary = false;
436
+ n -> addr = addr ;
437
+ hlist_del_rcu (& n -> hash );
438
+ hlist_add_head_rcu (& n -> hash ,
439
+ & tn -> node_htable [tipc_hashfn (addr )]);
440
+ list_del_rcu (& n -> list );
441
+ list_for_each_entry_rcu (temp_node , & tn -> node_list , list ) {
442
+ if (n -> addr < temp_node -> addr )
443
+ break ;
444
+ }
445
+ list_add_tail_rcu (& n -> list , & temp_node -> list );
446
+ tipc_node_write_unlock_fast (n );
447
+
448
+ update :
414
449
if (n -> peer_hash_mix ^ hash_mixes )
415
450
tipc_node_assign_peer_net (n , hash_mixes );
416
451
if (n -> capabilities == capabilities )
@@ -438,7 +473,9 @@ static struct tipc_node *tipc_node_create(struct net *net, u32 addr,
438
473
pr_warn ("Node creation failed, no memory\n" );
439
474
goto exit ;
440
475
}
476
+ tipc_nodeid2string (n -> peer_id_string , peer_id );
441
477
n -> addr = addr ;
478
+ n -> preliminary = preliminary ;
442
479
memcpy (& n -> peer_id , peer_id , 16 );
443
480
n -> net = net ;
444
481
n -> peer_net = NULL ;
@@ -463,22 +500,14 @@ static struct tipc_node *tipc_node_create(struct net *net, u32 addr,
463
500
n -> signature = INVALID_NODE_SIG ;
464
501
n -> active_links [0 ] = INVALID_BEARER_ID ;
465
502
n -> active_links [1 ] = INVALID_BEARER_ID ;
466
- if (!tipc_link_bc_create (net , tipc_own_addr (net ),
467
- addr , U16_MAX ,
468
- tipc_link_window (tipc_bc_sndlink (net )),
469
- n -> capabilities ,
470
- & n -> bc_entry .inputq1 ,
471
- & n -> bc_entry .namedq ,
472
- tipc_bc_sndlink (net ),
473
- & n -> bc_entry .link )) {
474
- pr_warn ("Broadcast rcv link creation failed, no memory\n" );
475
- kfree (n );
476
- n = NULL ;
477
- goto exit ;
478
- }
503
+ n -> bc_entry .link = NULL ;
479
504
tipc_node_get (n );
480
505
timer_setup (& n -> timer , tipc_node_timeout , 0 );
481
- n -> keepalive_intv = U32_MAX ;
506
+ /* Start a slow timer anyway, crypto needs it */
507
+ n -> keepalive_intv = 10000 ;
508
+ intv = jiffies + msecs_to_jiffies (n -> keepalive_intv );
509
+ if (!mod_timer (& n -> timer , intv ))
510
+ tipc_node_get (n );
482
511
hlist_add_head_rcu (& n -> hash , & tn -> node_htable [tipc_hashfn (addr )]);
483
512
list_for_each_entry_rcu (temp_node , & tn -> node_list , list ) {
484
513
if (n -> addr < temp_node -> addr )
@@ -1001,6 +1030,8 @@ u32 tipc_node_try_addr(struct net *net, u8 *id, u32 addr)
1001
1030
{
1002
1031
struct tipc_net * tn = tipc_net (net );
1003
1032
struct tipc_node * n ;
1033
+ bool preliminary ;
1034
+ u32 sugg_addr ;
1004
1035
1005
1036
/* Suggest new address if some other peer is using this one */
1006
1037
n = tipc_node_find (net , addr );
@@ -1016,9 +1047,11 @@ u32 tipc_node_try_addr(struct net *net, u8 *id, u32 addr)
1016
1047
/* Suggest previously used address if peer is known */
1017
1048
n = tipc_node_find_by_id (net , id );
1018
1049
if (n ) {
1019
- addr = n -> addr ;
1050
+ sugg_addr = n -> addr ;
1051
+ preliminary = n -> preliminary ;
1020
1052
tipc_node_put (n );
1021
- return addr ;
1053
+ if (!preliminary )
1054
+ return sugg_addr ;
1022
1055
}
1023
1056
1024
1057
/* Even this node may be in conflict */
@@ -1035,7 +1068,7 @@ void tipc_node_check_dest(struct net *net, u32 addr,
1035
1068
bool * respond , bool * dupl_addr )
1036
1069
{
1037
1070
struct tipc_node * n ;
1038
- struct tipc_link * l ;
1071
+ struct tipc_link * l , * snd_l ;
1039
1072
struct tipc_link_entry * le ;
1040
1073
bool addr_match = false;
1041
1074
bool sign_match = false;
@@ -1049,12 +1082,27 @@ void tipc_node_check_dest(struct net *net, u32 addr,
1049
1082
* dupl_addr = false;
1050
1083
* respond = false;
1051
1084
1052
- n = tipc_node_create (net , addr , peer_id , capabilities , signature ,
1053
- hash_mixes );
1085
+ n = tipc_node_create (net , addr , peer_id , capabilities , hash_mixes ,
1086
+ false );
1054
1087
if (!n )
1055
1088
return ;
1056
1089
1057
1090
tipc_node_write_lock (n );
1091
+ if (unlikely (!n -> bc_entry .link )) {
1092
+ snd_l = tipc_bc_sndlink (net );
1093
+ if (!tipc_link_bc_create (net , tipc_own_addr (net ),
1094
+ addr , U16_MAX ,
1095
+ tipc_link_window (snd_l ),
1096
+ n -> capabilities ,
1097
+ & n -> bc_entry .inputq1 ,
1098
+ & n -> bc_entry .namedq , snd_l ,
1099
+ & n -> bc_entry .link )) {
1100
+ pr_warn ("Broadcast rcv link creation failed, no mem\n" );
1101
+ tipc_node_write_unlock_fast (n );
1102
+ tipc_node_put (n );
1103
+ return ;
1104
+ }
1105
+ }
1058
1106
1059
1107
le = & n -> links [b -> identity ];
1060
1108
@@ -2134,6 +2182,8 @@ int tipc_nl_node_dump(struct sk_buff *skb, struct netlink_callback *cb)
2134
2182
}
2135
2183
2136
2184
list_for_each_entry_rcu (node , & tn -> node_list , list ) {
2185
+ if (node -> preliminary )
2186
+ continue ;
2137
2187
if (last_addr ) {
2138
2188
if (node -> addr == last_addr )
2139
2189
last_addr = 0 ;
@@ -2649,11 +2699,6 @@ int tipc_nl_node_dump_monitor_peer(struct sk_buff *skb,
2649
2699
return skb -> len ;
2650
2700
}
2651
2701
2652
- u32 tipc_node_get_addr (struct tipc_node * node )
2653
- {
2654
- return (node ) ? node -> addr : 0 ;
2655
- }
2656
-
2657
2702
/**
2658
2703
* tipc_node_dump - dump TIPC node data
2659
2704
* @n: tipc node to be dumped
0 commit comments