Skip to content

Commit 4cbf8ac

Browse files
Tuong Liendavem330
authored andcommitted
tipc: enable creating a "preliminary" node
When user sets RX key for a peer not existing on the own node, a new node entry is needed to which the RX key will be attached. However, since the peer node address (& capabilities) is unknown at that moment, only the node-ID is provided, this commit allows the creation of a node with only the data that we call as “preliminary”. A preliminary node is not the object of the “tipc_node_find()” but the “tipc_node_find_by_id()”. Once the first message i.e. LINK_CONFIG comes from that peer, and is successfully decrypted by the own node, the actual peer node data will be properly updated and the node will function as usual. In addition, the node timer always starts when a node object is created so if a preliminary node is not used, it will be cleaned up. The later encryption functions will also use the node timer and be able to create a preliminary node automatically when needed. Acked-by: Ying Xue <[email protected]> Acked-by: Jon Maloy <[email protected]> Signed-off-by: Tuong Lien <[email protected]> Signed-off-by: David S. Miller <[email protected]>
1 parent 2a7ee69 commit 4cbf8ac

File tree

2 files changed

+73
-27
lines changed

2 files changed

+73
-27
lines changed

net/tipc/node.c

Lines changed: 72 additions & 27 deletions
Original file line numberDiff line numberDiff line change
@@ -89,6 +89,7 @@ struct tipc_bclink_entry {
8989
* @links: array containing references to all links to node
9090
* @action_flags: bit mask of different types of node actions
9191
* @state: connectivity state vs peer node
92+
* @preliminary: a preliminary node or not
9293
* @sync_point: sequence number where synch/failover is finished
9394
* @list: links to adjacent nodes in sorted list of cluster's nodes
9495
* @working_links: number of working links to node (both active and standby)
@@ -112,6 +113,7 @@ struct tipc_node {
112113
int action_flags;
113114
struct list_head list;
114115
int state;
116+
bool preliminary;
115117
bool failover_sent;
116118
u16 sync_point;
117119
int link_cnt;
@@ -120,6 +122,7 @@ struct tipc_node {
120122
u32 signature;
121123
u32 link_id;
122124
u8 peer_id[16];
125+
char peer_id_string[NODE_ID_STR_LEN];
123126
struct list_head publ_list;
124127
struct list_head conn_sks;
125128
unsigned long keepalive_intv;
@@ -245,6 +248,16 @@ u16 tipc_node_get_capabilities(struct net *net, u32 addr)
245248
return caps;
246249
}
247250

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+
248261
static void tipc_node_kref_release(struct kref *kref)
249262
{
250263
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)
274287

275288
rcu_read_lock();
276289
hlist_for_each_entry_rcu(node, &tn->node_htable[thash], hash) {
277-
if (node->addr != addr)
290+
if (node->addr != addr || node->preliminary)
278291
continue;
279292
if (!kref_get_unless_zero(&node->kref))
280293
node = NULL;
@@ -400,17 +413,39 @@ static void tipc_node_assign_peer_net(struct tipc_node *n, u32 hash_mixes)
400413

401414
static struct tipc_node *tipc_node_create(struct net *net, u32 addr,
402415
u8 *peer_id, u16 capabilities,
403-
u32 signature, u32 hash_mixes)
416+
u32 hash_mixes, bool preliminary)
404417
{
405418
struct tipc_net *tn = net_generic(net, tipc_net_id);
406419
struct tipc_node *n, *temp_node;
407420
struct tipc_link *l;
421+
unsigned long intv;
408422
int bearer_id;
409423
int i;
410424

411425
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);
413428
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:
414449
if (n->peer_hash_mix ^ hash_mixes)
415450
tipc_node_assign_peer_net(n, hash_mixes);
416451
if (n->capabilities == capabilities)
@@ -438,7 +473,9 @@ static struct tipc_node *tipc_node_create(struct net *net, u32 addr,
438473
pr_warn("Node creation failed, no memory\n");
439474
goto exit;
440475
}
476+
tipc_nodeid2string(n->peer_id_string, peer_id);
441477
n->addr = addr;
478+
n->preliminary = preliminary;
442479
memcpy(&n->peer_id, peer_id, 16);
443480
n->net = net;
444481
n->peer_net = NULL;
@@ -463,22 +500,14 @@ static struct tipc_node *tipc_node_create(struct net *net, u32 addr,
463500
n->signature = INVALID_NODE_SIG;
464501
n->active_links[0] = INVALID_BEARER_ID;
465502
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;
479504
tipc_node_get(n);
480505
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);
482511
hlist_add_head_rcu(&n->hash, &tn->node_htable[tipc_hashfn(addr)]);
483512
list_for_each_entry_rcu(temp_node, &tn->node_list, list) {
484513
if (n->addr < temp_node->addr)
@@ -1001,6 +1030,8 @@ u32 tipc_node_try_addr(struct net *net, u8 *id, u32 addr)
10011030
{
10021031
struct tipc_net *tn = tipc_net(net);
10031032
struct tipc_node *n;
1033+
bool preliminary;
1034+
u32 sugg_addr;
10041035

10051036
/* Suggest new address if some other peer is using this one */
10061037
n = tipc_node_find(net, addr);
@@ -1016,9 +1047,11 @@ u32 tipc_node_try_addr(struct net *net, u8 *id, u32 addr)
10161047
/* Suggest previously used address if peer is known */
10171048
n = tipc_node_find_by_id(net, id);
10181049
if (n) {
1019-
addr = n->addr;
1050+
sugg_addr = n->addr;
1051+
preliminary = n->preliminary;
10201052
tipc_node_put(n);
1021-
return addr;
1053+
if (!preliminary)
1054+
return sugg_addr;
10221055
}
10231056

10241057
/* Even this node may be in conflict */
@@ -1035,7 +1068,7 @@ void tipc_node_check_dest(struct net *net, u32 addr,
10351068
bool *respond, bool *dupl_addr)
10361069
{
10371070
struct tipc_node *n;
1038-
struct tipc_link *l;
1071+
struct tipc_link *l, *snd_l;
10391072
struct tipc_link_entry *le;
10401073
bool addr_match = false;
10411074
bool sign_match = false;
@@ -1049,12 +1082,27 @@ void tipc_node_check_dest(struct net *net, u32 addr,
10491082
*dupl_addr = false;
10501083
*respond = false;
10511084

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);
10541087
if (!n)
10551088
return;
10561089

10571090
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+
}
10581106

10591107
le = &n->links[b->identity];
10601108

@@ -2134,6 +2182,8 @@ int tipc_nl_node_dump(struct sk_buff *skb, struct netlink_callback *cb)
21342182
}
21352183

21362184
list_for_each_entry_rcu(node, &tn->node_list, list) {
2185+
if (node->preliminary)
2186+
continue;
21372187
if (last_addr) {
21382188
if (node->addr == last_addr)
21392189
last_addr = 0;
@@ -2649,11 +2699,6 @@ int tipc_nl_node_dump_monitor_peer(struct sk_buff *skb,
26492699
return skb->len;
26502700
}
26512701

2652-
u32 tipc_node_get_addr(struct tipc_node *node)
2653-
{
2654-
return (node) ? node->addr : 0;
2655-
}
2656-
26572702
/**
26582703
* tipc_node_dump - dump TIPC node data
26592704
* @n: tipc node to be dumped

net/tipc/node.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -75,6 +75,7 @@ enum {
7575
void tipc_node_stop(struct net *net);
7676
bool tipc_node_get_id(struct net *net, u32 addr, u8 *id);
7777
u32 tipc_node_get_addr(struct tipc_node *node);
78+
char *tipc_node_get_id_str(struct tipc_node *node);
7879
u32 tipc_node_try_addr(struct net *net, u8 *id, u32 addr);
7980
void tipc_node_check_dest(struct net *net, u32 onode, u8 *peer_id128,
8081
struct tipc_bearer *bearer,

0 commit comments

Comments
 (0)