diff options
author | GhantaKrishnamurthy MohanKrishna <mohan.krishna.ghanta.krishnamurthy@ericsson.com> | 2018-06-29 07:23:41 -0400 |
---|---|---|
committer | David S. Miller <davem@davemloft.net> | 2018-06-30 08:05:23 -0400 |
commit | 6a939f365bdb03a74b4617bdb4402fc08da088b9 (patch) | |
tree | aa22caa509706d637c8d2f84304f86f9aa4c1c56 /net/tipc/node.c | |
parent | e397286b8e89bf38f4f56c0dcf6626e79dc2a323 (diff) |
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 <ying.xue@windriver.com>
Acked-by: Jon Maloy <jon.maloy@ericsson.com>
Signed-off-by: GhantaKrishnamurthy MohanKrishna <mohan.krishna.ghanta.krishnamurthy@ericsson.com>
Signed-off-by: David S. Miller <davem@davemloft.net>
Diffstat (limited to 'net/tipc/node.c')
-rw-r--r-- | net/tipc/node.c | 66 |
1 files changed, 55 insertions, 11 deletions
diff --git a/net/tipc/node.c b/net/tipc/node.c index 8972ca1c654c..cfdbaf479fd1 100644 --- a/net/tipc/node.c +++ b/net/tipc/node.c | |||
@@ -45,6 +45,7 @@ | |||
45 | #include "netlink.h" | 45 | #include "netlink.h" |
46 | 46 | ||
47 | #define INVALID_NODE_SIG 0x10000 | 47 | #define INVALID_NODE_SIG 0x10000 |
48 | #define NODE_CLEANUP_AFTER 300000 | ||
48 | 49 | ||
49 | /* Flags used to take different actions according to flag type | 50 | /* Flags used to take different actions according to flag type |
50 | * TIPC_NOTIFY_NODE_DOWN: notify node is down | 51 | * TIPC_NOTIFY_NODE_DOWN: notify node is down |
@@ -96,6 +97,7 @@ struct tipc_bclink_entry { | |||
96 | * @link_id: local and remote bearer ids of changing link, if any | 97 | * @link_id: local and remote bearer ids of changing link, if any |
97 | * @publ_list: list of publications | 98 | * @publ_list: list of publications |
98 | * @rcu: rcu struct for tipc_node | 99 | * @rcu: rcu struct for tipc_node |
100 | * @delete_at: indicates the time for deleting a down node | ||
99 | */ | 101 | */ |
100 | struct tipc_node { | 102 | struct tipc_node { |
101 | u32 addr; | 103 | u32 addr; |
@@ -121,6 +123,7 @@ struct tipc_node { | |||
121 | unsigned long keepalive_intv; | 123 | unsigned long keepalive_intv; |
122 | struct timer_list timer; | 124 | struct timer_list timer; |
123 | struct rcu_head rcu; | 125 | struct rcu_head rcu; |
126 | unsigned long delete_at; | ||
124 | }; | 127 | }; |
125 | 128 | ||
126 | /* Node FSM states and events: | 129 | /* Node FSM states and events: |
@@ -160,6 +163,7 @@ static struct tipc_node *tipc_node_find(struct net *net, u32 addr); | |||
160 | static struct tipc_node *tipc_node_find_by_id(struct net *net, u8 *id); | 163 | static struct tipc_node *tipc_node_find_by_id(struct net *net, u8 *id); |
161 | static void tipc_node_put(struct tipc_node *node); | 164 | static void tipc_node_put(struct tipc_node *node); |
162 | static bool node_is_up(struct tipc_node *n); | 165 | static bool node_is_up(struct tipc_node *n); |
166 | static void tipc_node_delete_from_list(struct tipc_node *node); | ||
163 | 167 | ||
164 | struct tipc_sock_conn { | 168 | struct tipc_sock_conn { |
165 | u32 port; | 169 | u32 port; |
@@ -390,6 +394,7 @@ static struct tipc_node *tipc_node_create(struct net *net, u32 addr, | |||
390 | for (i = 0; i < MAX_BEARERS; i++) | 394 | for (i = 0; i < MAX_BEARERS; i++) |
391 | spin_lock_init(&n->links[i].lock); | 395 | spin_lock_init(&n->links[i].lock); |
392 | n->state = SELF_DOWN_PEER_LEAVING; | 396 | n->state = SELF_DOWN_PEER_LEAVING; |
397 | n->delete_at = jiffies + msecs_to_jiffies(NODE_CLEANUP_AFTER); | ||
393 | n->signature = INVALID_NODE_SIG; | 398 | n->signature = INVALID_NODE_SIG; |
394 | n->active_links[0] = INVALID_BEARER_ID; | 399 | n->active_links[0] = INVALID_BEARER_ID; |
395 | n->active_links[1] = INVALID_BEARER_ID; | 400 | 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) | |||
433 | tipc_link_set_abort_limit(l, tol / n->keepalive_intv); | 438 | tipc_link_set_abort_limit(l, tol / n->keepalive_intv); |
434 | } | 439 | } |
435 | 440 | ||
436 | static void tipc_node_delete(struct tipc_node *node) | 441 | static void tipc_node_delete_from_list(struct tipc_node *node) |
437 | { | 442 | { |
438 | list_del_rcu(&node->list); | 443 | list_del_rcu(&node->list); |
439 | hlist_del_rcu(&node->hash); | 444 | hlist_del_rcu(&node->hash); |
440 | tipc_node_put(node); | 445 | tipc_node_put(node); |
446 | } | ||
447 | |||
448 | static void tipc_node_delete(struct tipc_node *node) | ||
449 | { | ||
450 | tipc_node_delete_from_list(node); | ||
441 | 451 | ||
442 | del_timer_sync(&node->timer); | 452 | del_timer_sync(&node->timer); |
443 | tipc_node_put(node); | 453 | tipc_node_put(node); |
@@ -544,6 +554,42 @@ void tipc_node_remove_conn(struct net *net, u32 dnode, u32 port) | |||
544 | tipc_node_put(node); | 554 | tipc_node_put(node); |
545 | } | 555 | } |
546 | 556 | ||
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 | |||
547 | /* tipc_node_timeout - handle expiration of node timer | 593 | /* tipc_node_timeout - handle expiration of node timer |
548 | */ | 594 | */ |
549 | static void tipc_node_timeout(struct timer_list *t) | 595 | static void tipc_node_timeout(struct timer_list *t) |
@@ -555,6 +601,12 @@ static void tipc_node_timeout(struct timer_list *t) | |||
555 | int bearer_id; | 601 | int bearer_id; |
556 | int rc = 0; | 602 | int rc = 0; |
557 | 603 | ||
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 | |||
558 | __skb_queue_head_init(&xmitq); | 610 | __skb_queue_head_init(&xmitq); |
559 | 611 | ||
560 | for (bearer_id = 0; remains && (bearer_id < MAX_BEARERS); bearer_id++) { | 612 | for (bearer_id = 0; remains && (bearer_id < MAX_BEARERS); bearer_id++) { |
@@ -1173,6 +1225,7 @@ static void node_lost_contact(struct tipc_node *n, | |||
1173 | uint i; | 1225 | uint i; |
1174 | 1226 | ||
1175 | pr_debug("Lost contact with %x\n", n->addr); | 1227 | pr_debug("Lost contact with %x\n", n->addr); |
1228 | n->delete_at = jiffies + msecs_to_jiffies(NODE_CLEANUP_AFTER); | ||
1176 | 1229 | ||
1177 | /* Clean up broadcast state */ | 1230 | /* Clean up broadcast state */ |
1178 | tipc_bcast_remove_peer(n->net, n->bc_entry.link); | 1231 | 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) | |||
1742 | struct tipc_node *peer; | 1795 | struct tipc_node *peer; |
1743 | u32 addr; | 1796 | u32 addr; |
1744 | int err; | 1797 | int err; |
1745 | int i; | ||
1746 | 1798 | ||
1747 | /* We identify the peer by its net */ | 1799 | /* We identify the peer by its net */ |
1748 | if (!info->attrs[TIPC_NLA_NET]) | 1800 | if (!info->attrs[TIPC_NLA_NET]) |
@@ -1777,15 +1829,7 @@ int tipc_nl_peer_rm(struct sk_buff *skb, struct genl_info *info) | |||
1777 | goto err_out; | 1829 | goto err_out; |
1778 | } | 1830 | } |
1779 | 1831 | ||
1780 | for (i = 0; i < MAX_BEARERS; i++) { | 1832 | tipc_node_clear_links(peer); |
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 | } | ||
1789 | tipc_node_write_unlock(peer); | 1833 | tipc_node_write_unlock(peer); |
1790 | tipc_node_delete(peer); | 1834 | tipc_node_delete(peer); |
1791 | 1835 | ||