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.c90
1 files changed, 75 insertions, 15 deletions
diff --git a/net/tipc/node.c b/net/tipc/node.c
index 0453bd451ce8..68014f1b6976 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 */
100struct tipc_node { 102struct 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);
160static struct tipc_node *tipc_node_find_by_id(struct net *net, u8 *id); 163static struct tipc_node *tipc_node_find_by_id(struct net *net, u8 *id);
161static void tipc_node_put(struct tipc_node *node); 164static void tipc_node_put(struct tipc_node *node);
162static bool node_is_up(struct tipc_node *n); 165static bool node_is_up(struct tipc_node *n);
166static void tipc_node_delete_from_list(struct tipc_node *node);
163 167
164struct tipc_sock_conn { 168struct tipc_sock_conn {
165 u32 port; 169 u32 port;
@@ -359,13 +363,24 @@ static struct tipc_node *tipc_node_create(struct net *net, u32 addr,
359{ 363{
360 struct tipc_net *tn = net_generic(net, tipc_net_id); 364 struct tipc_net *tn = net_generic(net, tipc_net_id);
361 struct tipc_node *n, *temp_node; 365 struct tipc_node *n, *temp_node;
366 struct tipc_link *l;
367 int bearer_id;
362 int i; 368 int i;
363 369
364 spin_lock_bh(&tn->node_list_lock); 370 spin_lock_bh(&tn->node_list_lock);
365 n = tipc_node_find(net, addr); 371 n = tipc_node_find(net, addr);
366 if (n) { 372 if (n) {
373 if (n->capabilities == capabilities)
374 goto exit;
367 /* Same node may come back with new capabilities */ 375 /* Same node may come back with new capabilities */
376 write_lock_bh(&n->lock);
368 n->capabilities = capabilities; 377 n->capabilities = capabilities;
378 for (bearer_id = 0; bearer_id < MAX_BEARERS; bearer_id++) {
379 l = n->links[bearer_id].link;
380 if (l)
381 tipc_link_update_caps(l, capabilities);
382 }
383 write_unlock_bh(&n->lock);
369 goto exit; 384 goto exit;
370 } 385 }
371 n = kzalloc(sizeof(*n), GFP_ATOMIC); 386 n = kzalloc(sizeof(*n), GFP_ATOMIC);
@@ -390,6 +405,7 @@ static struct tipc_node *tipc_node_create(struct net *net, u32 addr,
390 for (i = 0; i < MAX_BEARERS; i++) 405 for (i = 0; i < MAX_BEARERS; i++)
391 spin_lock_init(&n->links[i].lock); 406 spin_lock_init(&n->links[i].lock);
392 n->state = SELF_DOWN_PEER_LEAVING; 407 n->state = SELF_DOWN_PEER_LEAVING;
408 n->delete_at = jiffies + msecs_to_jiffies(NODE_CLEANUP_AFTER);
393 n->signature = INVALID_NODE_SIG; 409 n->signature = INVALID_NODE_SIG;
394 n->active_links[0] = INVALID_BEARER_ID; 410 n->active_links[0] = INVALID_BEARER_ID;
395 n->active_links[1] = INVALID_BEARER_ID; 411 n->active_links[1] = INVALID_BEARER_ID;
@@ -433,11 +449,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); 449 tipc_link_set_abort_limit(l, tol / n->keepalive_intv);
434} 450}
435 451
436static void tipc_node_delete(struct tipc_node *node) 452static void tipc_node_delete_from_list(struct tipc_node *node)
437{ 453{
438 list_del_rcu(&node->list); 454 list_del_rcu(&node->list);
439 hlist_del_rcu(&node->hash); 455 hlist_del_rcu(&node->hash);
440 tipc_node_put(node); 456 tipc_node_put(node);
457}
458
459static void tipc_node_delete(struct tipc_node *node)
460{
461 tipc_node_delete_from_list(node);
441 462
442 del_timer_sync(&node->timer); 463 del_timer_sync(&node->timer);
443 tipc_node_put(node); 464 tipc_node_put(node);
@@ -544,6 +565,42 @@ void tipc_node_remove_conn(struct net *net, u32 dnode, u32 port)
544 tipc_node_put(node); 565 tipc_node_put(node);
545} 566}
546 567
568static void tipc_node_clear_links(struct tipc_node *node)
569{
570 int i;
571
572 for (i = 0; i < MAX_BEARERS; i++) {
573 struct tipc_link_entry *le = &node->links[i];
574
575 if (le->link) {
576 kfree(le->link);
577 le->link = NULL;
578 node->link_cnt--;
579 }
580 }
581}
582
583/* tipc_node_cleanup - delete nodes that does not
584 * have active links for NODE_CLEANUP_AFTER time
585 */
586static int tipc_node_cleanup(struct tipc_node *peer)
587{
588 struct tipc_net *tn = tipc_net(peer->net);
589 bool deleted = false;
590
591 spin_lock_bh(&tn->node_list_lock);
592 tipc_node_write_lock(peer);
593
594 if (!node_is_up(peer) && time_after(jiffies, peer->delete_at)) {
595 tipc_node_clear_links(peer);
596 tipc_node_delete_from_list(peer);
597 deleted = true;
598 }
599 tipc_node_write_unlock(peer);
600 spin_unlock_bh(&tn->node_list_lock);
601 return deleted;
602}
603
547/* tipc_node_timeout - handle expiration of node timer 604/* tipc_node_timeout - handle expiration of node timer
548 */ 605 */
549static void tipc_node_timeout(struct timer_list *t) 606static void tipc_node_timeout(struct timer_list *t)
@@ -551,21 +608,29 @@ static void tipc_node_timeout(struct timer_list *t)
551 struct tipc_node *n = from_timer(n, t, timer); 608 struct tipc_node *n = from_timer(n, t, timer);
552 struct tipc_link_entry *le; 609 struct tipc_link_entry *le;
553 struct sk_buff_head xmitq; 610 struct sk_buff_head xmitq;
611 int remains = n->link_cnt;
554 int bearer_id; 612 int bearer_id;
555 int rc = 0; 613 int rc = 0;
556 614
615 if (!node_is_up(n) && tipc_node_cleanup(n)) {
616 /*Removing the reference of Timer*/
617 tipc_node_put(n);
618 return;
619 }
620
557 __skb_queue_head_init(&xmitq); 621 __skb_queue_head_init(&xmitq);
558 622
559 for (bearer_id = 0; bearer_id < MAX_BEARERS; bearer_id++) { 623 for (bearer_id = 0; remains && (bearer_id < MAX_BEARERS); bearer_id++) {
560 tipc_node_read_lock(n); 624 tipc_node_read_lock(n);
561 le = &n->links[bearer_id]; 625 le = &n->links[bearer_id];
562 spin_lock_bh(&le->lock);
563 if (le->link) { 626 if (le->link) {
627 spin_lock_bh(&le->lock);
564 /* Link tolerance may change asynchronously: */ 628 /* Link tolerance may change asynchronously: */
565 tipc_node_calculate_timer(n, le->link); 629 tipc_node_calculate_timer(n, le->link);
566 rc = tipc_link_timeout(le->link, &xmitq); 630 rc = tipc_link_timeout(le->link, &xmitq);
631 spin_unlock_bh(&le->lock);
632 remains--;
567 } 633 }
568 spin_unlock_bh(&le->lock);
569 tipc_node_read_unlock(n); 634 tipc_node_read_unlock(n);
570 tipc_bearer_xmit(n->net, bearer_id, &xmitq, &le->maddr); 635 tipc_bearer_xmit(n->net, bearer_id, &xmitq, &le->maddr);
571 if (rc & TIPC_LINK_DOWN_EVT) 636 if (rc & TIPC_LINK_DOWN_EVT)
@@ -1174,6 +1239,7 @@ static void node_lost_contact(struct tipc_node *n,
1174 uint i; 1239 uint i;
1175 1240
1176 pr_debug("Lost contact with %x\n", n->addr); 1241 pr_debug("Lost contact with %x\n", n->addr);
1242 n->delete_at = jiffies + msecs_to_jiffies(NODE_CLEANUP_AFTER);
1177 1243
1178 /* Clean up broadcast state */ 1244 /* Clean up broadcast state */
1179 tipc_bcast_remove_peer(n->net, n->bc_entry.link); 1245 tipc_bcast_remove_peer(n->net, n->bc_entry.link);
@@ -1481,7 +1547,7 @@ static void tipc_node_bc_rcv(struct net *net, struct sk_buff *skb, int bearer_id
1481 * tipc_node_check_state - check and if necessary update node state 1547 * tipc_node_check_state - check and if necessary update node state
1482 * @skb: TIPC packet 1548 * @skb: TIPC packet
1483 * @bearer_id: identity of bearer delivering the packet 1549 * @bearer_id: identity of bearer delivering the packet
1484 * Returns true if state is ok, otherwise consumes buffer and returns false 1550 * Returns true if state and msg are ok, otherwise false
1485 */ 1551 */
1486static bool tipc_node_check_state(struct tipc_node *n, struct sk_buff *skb, 1552static bool tipc_node_check_state(struct tipc_node *n, struct sk_buff *skb,
1487 int bearer_id, struct sk_buff_head *xmitq) 1553 int bearer_id, struct sk_buff_head *xmitq)
@@ -1515,6 +1581,9 @@ static bool tipc_node_check_state(struct tipc_node *n, struct sk_buff *skb,
1515 } 1581 }
1516 } 1582 }
1517 1583
1584 if (!tipc_link_validate_msg(l, hdr))
1585 return false;
1586
1518 /* Check and update node accesibility if applicable */ 1587 /* Check and update node accesibility if applicable */
1519 if (state == SELF_UP_PEER_COMING) { 1588 if (state == SELF_UP_PEER_COMING) {
1520 if (!tipc_link_is_up(l)) 1589 if (!tipc_link_is_up(l))
@@ -1743,7 +1812,6 @@ int tipc_nl_peer_rm(struct sk_buff *skb, struct genl_info *info)
1743 struct tipc_node *peer; 1812 struct tipc_node *peer;
1744 u32 addr; 1813 u32 addr;
1745 int err; 1814 int err;
1746 int i;
1747 1815
1748 /* We identify the peer by its net */ 1816 /* We identify the peer by its net */
1749 if (!info->attrs[TIPC_NLA_NET]) 1817 if (!info->attrs[TIPC_NLA_NET])
@@ -1778,15 +1846,7 @@ int tipc_nl_peer_rm(struct sk_buff *skb, struct genl_info *info)
1778 goto err_out; 1846 goto err_out;
1779 } 1847 }
1780 1848
1781 for (i = 0; i < MAX_BEARERS; i++) { 1849 tipc_node_clear_links(peer);
1782 struct tipc_link_entry *le = &peer->links[i];
1783
1784 if (le->link) {
1785 kfree(le->link);
1786 le->link = NULL;
1787 peer->link_cnt--;
1788 }
1789 }
1790 tipc_node_write_unlock(peer); 1850 tipc_node_write_unlock(peer);
1791 tipc_node_delete(peer); 1851 tipc_node_delete(peer);
1792 1852