Skip to content

Commit 6a939f3

Browse files
GhantaKrishnamurthy MohanKrishnadavem330
GhantaKrishnamurthy MohanKrishna
authored andcommitted
tipc: Auto removal of peer down node instance
A peer node is considered down if there are no active links (or) lost contact to the node. In current implementation, a peer node instance is deleted either if a) TIPC module is removed (or) b) Application can use a netlink/iproute2 interface to delete a specific down node. Thus, a down node instance lives in the system forever, unless the application explicitly removes it. We fix this by deleting the nodes which are down for a specified amount of time (5 minutes). Existing node supervision timer is used to achieve this. Acked-by: Ying Xue <[email protected]> Acked-by: Jon Maloy <[email protected]> Signed-off-by: GhantaKrishnamurthy MohanKrishna <[email protected]> Signed-off-by: David S. Miller <[email protected]>
1 parent e397286 commit 6a939f3

File tree

1 file changed

+55
-11
lines changed

1 file changed

+55
-11
lines changed

net/tipc/node.c

Lines changed: 55 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -45,6 +45,7 @@
4545
#include "netlink.h"
4646

4747
#define INVALID_NODE_SIG 0x10000
48+
#define NODE_CLEANUP_AFTER 300000
4849

4950
/* Flags used to take different actions according to flag type
5051
* TIPC_NOTIFY_NODE_DOWN: notify node is down
@@ -96,6 +97,7 @@ struct tipc_bclink_entry {
9697
* @link_id: local and remote bearer ids of changing link, if any
9798
* @publ_list: list of publications
9899
* @rcu: rcu struct for tipc_node
100+
* @delete_at: indicates the time for deleting a down node
99101
*/
100102
struct tipc_node {
101103
u32 addr;
@@ -121,6 +123,7 @@ struct tipc_node {
121123
unsigned long keepalive_intv;
122124
struct timer_list timer;
123125
struct rcu_head rcu;
126+
unsigned long delete_at;
124127
};
125128

126129
/* Node FSM states and events:
@@ -160,6 +163,7 @@ static struct tipc_node *tipc_node_find(struct net *net, u32 addr);
160163
static struct tipc_node *tipc_node_find_by_id(struct net *net, u8 *id);
161164
static void tipc_node_put(struct tipc_node *node);
162165
static bool node_is_up(struct tipc_node *n);
166+
static void tipc_node_delete_from_list(struct tipc_node *node);
163167

164168
struct tipc_sock_conn {
165169
u32 port;
@@ -390,6 +394,7 @@ static struct tipc_node *tipc_node_create(struct net *net, u32 addr,
390394
for (i = 0; i < MAX_BEARERS; i++)
391395
spin_lock_init(&n->links[i].lock);
392396
n->state = SELF_DOWN_PEER_LEAVING;
397+
n->delete_at = jiffies + msecs_to_jiffies(NODE_CLEANUP_AFTER);
393398
n->signature = INVALID_NODE_SIG;
394399
n->active_links[0] = INVALID_BEARER_ID;
395400
n->active_links[1] = INVALID_BEARER_ID;
@@ -433,11 +438,16 @@ static void tipc_node_calculate_timer(struct tipc_node *n, struct tipc_link *l)
433438
tipc_link_set_abort_limit(l, tol / n->keepalive_intv);
434439
}
435440

436-
static void tipc_node_delete(struct tipc_node *node)
441+
static void tipc_node_delete_from_list(struct tipc_node *node)
437442
{
438443
list_del_rcu(&node->list);
439444
hlist_del_rcu(&node->hash);
440445
tipc_node_put(node);
446+
}
447+
448+
static void tipc_node_delete(struct tipc_node *node)
449+
{
450+
tipc_node_delete_from_list(node);
441451

442452
del_timer_sync(&node->timer);
443453
tipc_node_put(node);
@@ -544,6 +554,42 @@ void tipc_node_remove_conn(struct net *net, u32 dnode, u32 port)
544554
tipc_node_put(node);
545555
}
546556

557+
static void tipc_node_clear_links(struct tipc_node *node)
558+
{
559+
int i;
560+
561+
for (i = 0; i < MAX_BEARERS; i++) {
562+
struct tipc_link_entry *le = &node->links[i];
563+
564+
if (le->link) {
565+
kfree(le->link);
566+
le->link = NULL;
567+
node->link_cnt--;
568+
}
569+
}
570+
}
571+
572+
/* tipc_node_cleanup - delete nodes that does not
573+
* have active links for NODE_CLEANUP_AFTER time
574+
*/
575+
static int tipc_node_cleanup(struct tipc_node *peer)
576+
{
577+
struct tipc_net *tn = tipc_net(peer->net);
578+
bool deleted = false;
579+
580+
spin_lock_bh(&tn->node_list_lock);
581+
tipc_node_write_lock(peer);
582+
583+
if (!node_is_up(peer) && time_after(jiffies, peer->delete_at)) {
584+
tipc_node_clear_links(peer);
585+
tipc_node_delete_from_list(peer);
586+
deleted = true;
587+
}
588+
tipc_node_write_unlock(peer);
589+
spin_unlock_bh(&tn->node_list_lock);
590+
return deleted;
591+
}
592+
547593
/* tipc_node_timeout - handle expiration of node timer
548594
*/
549595
static void tipc_node_timeout(struct timer_list *t)
@@ -555,6 +601,12 @@ static void tipc_node_timeout(struct timer_list *t)
555601
int bearer_id;
556602
int rc = 0;
557603

604+
if (!node_is_up(n) && tipc_node_cleanup(n)) {
605+
/*Removing the reference of Timer*/
606+
tipc_node_put(n);
607+
return;
608+
}
609+
558610
__skb_queue_head_init(&xmitq);
559611

560612
for (bearer_id = 0; remains && (bearer_id < MAX_BEARERS); bearer_id++) {
@@ -1173,6 +1225,7 @@ static void node_lost_contact(struct tipc_node *n,
11731225
uint i;
11741226

11751227
pr_debug("Lost contact with %x\n", n->addr);
1228+
n->delete_at = jiffies + msecs_to_jiffies(NODE_CLEANUP_AFTER);
11761229

11771230
/* Clean up broadcast state */
11781231
tipc_bcast_remove_peer(n->net, n->bc_entry.link);
@@ -1742,7 +1795,6 @@ int tipc_nl_peer_rm(struct sk_buff *skb, struct genl_info *info)
17421795
struct tipc_node *peer;
17431796
u32 addr;
17441797
int err;
1745-
int i;
17461798

17471799
/* We identify the peer by its net */
17481800
if (!info->attrs[TIPC_NLA_NET])
@@ -1777,15 +1829,7 @@ int tipc_nl_peer_rm(struct sk_buff *skb, struct genl_info *info)
17771829
goto err_out;
17781830
}
17791831

1780-
for (i = 0; i < MAX_BEARERS; i++) {
1781-
struct tipc_link_entry *le = &peer->links[i];
1782-
1783-
if (le->link) {
1784-
kfree(le->link);
1785-
le->link = NULL;
1786-
peer->link_cnt--;
1787-
}
1788-
}
1832+
tipc_node_clear_links(peer);
17891833
tipc_node_write_unlock(peer);
17901834
tipc_node_delete(peer);
17911835

0 commit comments

Comments
 (0)