summaryrefslogtreecommitdiff
path: root/net/tipc/node.c
diff options
context:
space:
mode:
authorJon Paul Maloy <jon.maloy@ericsson.com>2015-07-16 16:54:29 -0400
committerDavid S. Miller <davem@davemloft.net>2015-07-20 20:41:16 -0700
commit8a1577c96f122308ac9b5f195f9f9a7dd74ac541 (patch)
tree76c366004226f31bb11af37dfa00a6d0146fc4ad /net/tipc/node.c
parent333ef69ed2121f535e00ceb26e095d3745584c6e (diff)
tipc: move link supervision timer to node level
In our effort to move control of the links to the link aggregation layer, we move the perodic link supervision timer to struct tipc_node. The new timer is shared between all links belonging to the node, thus saving resources, while still kicking the FSM on both its pertaining links at each expiration. The current link timer and corresponding functions are removed. Reviewed-by: Ying Xue <ying.xue@windriver.com> Signed-off-by: Jon Maloy <jon.maloy@ericsson.com> Signed-off-by: David S. Miller <davem@davemloft.net>
Diffstat (limited to 'net/tipc/node.c')
-rw-r--r--net/tipc/node.c66
1 files changed, 62 insertions, 4 deletions
diff --git a/net/tipc/node.c b/net/tipc/node.c
index b7a4457f653c..77effb233725 100644
--- a/net/tipc/node.c
+++ b/net/tipc/node.c
@@ -44,6 +44,7 @@
static void node_lost_contact(struct tipc_node *n_ptr);
static void node_established_contact(struct tipc_node *n_ptr);
static void tipc_node_delete(struct tipc_node *node);
+static void tipc_node_timeout(unsigned long data);
struct tipc_sock_conn {
u32 port;
@@ -145,11 +146,27 @@ struct tipc_node *tipc_node_create(struct net *net, u32 addr)
n_ptr->active_links[0] = INVALID_BEARER_ID;
n_ptr->active_links[1] = INVALID_BEARER_ID;
tipc_node_get(n_ptr);
+ setup_timer(&n_ptr->timer, tipc_node_timeout, (unsigned long)n_ptr);
+ n_ptr->keepalive_intv = U32_MAX;
exit:
spin_unlock_bh(&tn->node_list_lock);
return n_ptr;
}
+static void tipc_node_calculate_timer(struct tipc_node *n, struct tipc_link *l)
+{
+ unsigned long tol = l->tolerance;
+ unsigned long intv = ((tol / 4) > 500) ? 500 : tol / 4;
+ unsigned long keepalive_intv = msecs_to_jiffies(intv);
+
+ /* Link with lowest tolerance determines timer interval */
+ if (keepalive_intv < n->keepalive_intv)
+ n->keepalive_intv = keepalive_intv;
+
+ /* Ensure link's abort limit corresponds to current interval */
+ l->abort_limit = l->tolerance / jiffies_to_msecs(n->keepalive_intv);
+}
+
static void tipc_node_delete(struct tipc_node *node)
{
list_del_rcu(&node->list);
@@ -163,8 +180,11 @@ void tipc_node_stop(struct net *net)
struct tipc_node *node, *t_node;
spin_lock_bh(&tn->node_list_lock);
- list_for_each_entry_safe(node, t_node, &tn->node_list, list)
+ list_for_each_entry_safe(node, t_node, &tn->node_list, list) {
+ if (del_timer(&node->timer))
+ tipc_node_put(node);
tipc_node_put(node);
+ }
spin_unlock_bh(&tn->node_list_lock);
}
@@ -222,6 +242,38 @@ void tipc_node_remove_conn(struct net *net, u32 dnode, u32 port)
tipc_node_put(node);
}
+/* tipc_node_timeout - handle expiration of node timer
+ */
+static void tipc_node_timeout(unsigned long data)
+{
+ struct tipc_node *n = (struct tipc_node *)data;
+ struct sk_buff_head xmitq;
+ struct tipc_link *l;
+ struct tipc_media_addr *maddr;
+ int bearer_id;
+ int rc = 0;
+
+ __skb_queue_head_init(&xmitq);
+
+ for (bearer_id = 0; bearer_id < MAX_BEARERS; bearer_id++) {
+ tipc_node_lock(n);
+ l = n->links[bearer_id].link;
+ if (l) {
+ /* Link tolerance may change asynchronously: */
+ tipc_node_calculate_timer(n, l);
+ rc = tipc_link_timeout(l, &xmitq);
+ if (rc & TIPC_LINK_DOWN_EVT)
+ tipc_link_reset(l);
+ }
+ tipc_node_unlock(n);
+ maddr = &n->links[bearer_id].maddr;
+ tipc_bearer_xmit(n->net, bearer_id, &xmitq, maddr);
+ }
+ if (!mod_timer(&n->timer, jiffies + n->keepalive_intv))
+ tipc_node_get(n);
+ tipc_node_put(n);
+}
+
/**
* tipc_node_link_up - handle addition of link
*
@@ -335,10 +387,16 @@ bool tipc_node_update_dest(struct tipc_node *n, struct tipc_bearer *b,
struct tipc_media_addr *curr = &n->links[b->identity].maddr;
struct sk_buff_head *inputq = &n->links[b->identity].inputq;
- if (!l)
+ if (!l) {
l = tipc_link_create(n, b, maddr, inputq, &n->bclink.namedq);
- if (!l)
- return false;
+ if (!l)
+ return false;
+ tipc_node_calculate_timer(n, l);
+ if (n->link_cnt == 1) {
+ if (!mod_timer(&n->timer, jiffies + n->keepalive_intv))
+ tipc_node_get(n);
+ }
+ }
memcpy(&l->media_addr, maddr, sizeof(*maddr));
memcpy(curr, maddr, sizeof(*maddr));
tipc_link_reset(l);