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.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 @@
44static void node_lost_contact(struct tipc_node *n_ptr); 44static void node_lost_contact(struct tipc_node *n_ptr);
45static void node_established_contact(struct tipc_node *n_ptr); 45static void node_established_contact(struct tipc_node *n_ptr);
46static void tipc_node_delete(struct tipc_node *node); 46static void tipc_node_delete(struct tipc_node *node);
47static void tipc_node_timeout(unsigned long data);
47 48
48struct tipc_sock_conn { 49struct tipc_sock_conn {
49 u32 port; 50 u32 port;
@@ -145,11 +146,27 @@ struct tipc_node *tipc_node_create(struct net *net, u32 addr)
145 n_ptr->active_links[0] = INVALID_BEARER_ID; 146 n_ptr->active_links[0] = INVALID_BEARER_ID;
146 n_ptr->active_links[1] = INVALID_BEARER_ID; 147 n_ptr->active_links[1] = INVALID_BEARER_ID;
147 tipc_node_get(n_ptr); 148 tipc_node_get(n_ptr);
149 setup_timer(&n_ptr->timer, tipc_node_timeout, (unsigned long)n_ptr);
150 n_ptr->keepalive_intv = U32_MAX;
148exit: 151exit:
149 spin_unlock_bh(&tn->node_list_lock); 152 spin_unlock_bh(&tn->node_list_lock);
150 return n_ptr; 153 return n_ptr;
151} 154}
152 155
156static void tipc_node_calculate_timer(struct tipc_node *n, struct tipc_link *l)
157{
158 unsigned long tol = l->tolerance;
159 unsigned long intv = ((tol / 4) > 500) ? 500 : tol / 4;
160 unsigned long keepalive_intv = msecs_to_jiffies(intv);
161
162 /* Link with lowest tolerance determines timer interval */
163 if (keepalive_intv < n->keepalive_intv)
164 n->keepalive_intv = keepalive_intv;
165
166 /* Ensure link's abort limit corresponds to current interval */
167 l->abort_limit = l->tolerance / jiffies_to_msecs(n->keepalive_intv);
168}
169
153static void tipc_node_delete(struct tipc_node *node) 170static void tipc_node_delete(struct tipc_node *node)
154{ 171{
155 list_del_rcu(&node->list); 172 list_del_rcu(&node->list);
@@ -163,8 +180,11 @@ void tipc_node_stop(struct net *net)
163 struct tipc_node *node, *t_node; 180 struct tipc_node *node, *t_node;
164 181
165 spin_lock_bh(&tn->node_list_lock); 182 spin_lock_bh(&tn->node_list_lock);
166 list_for_each_entry_safe(node, t_node, &tn->node_list, list) 183 list_for_each_entry_safe(node, t_node, &tn->node_list, list) {
184 if (del_timer(&node->timer))
185 tipc_node_put(node);
167 tipc_node_put(node); 186 tipc_node_put(node);
187 }
168 spin_unlock_bh(&tn->node_list_lock); 188 spin_unlock_bh(&tn->node_list_lock);
169} 189}
170 190
@@ -222,6 +242,38 @@ void tipc_node_remove_conn(struct net *net, u32 dnode, u32 port)
222 tipc_node_put(node); 242 tipc_node_put(node);
223} 243}
224 244
245/* tipc_node_timeout - handle expiration of node timer
246 */
247static void tipc_node_timeout(unsigned long data)
248{
249 struct tipc_node *n = (struct tipc_node *)data;
250 struct sk_buff_head xmitq;
251 struct tipc_link *l;
252 struct tipc_media_addr *maddr;
253 int bearer_id;
254 int rc = 0;
255
256 __skb_queue_head_init(&xmitq);
257
258 for (bearer_id = 0; bearer_id < MAX_BEARERS; bearer_id++) {
259 tipc_node_lock(n);
260 l = n->links[bearer_id].link;
261 if (l) {
262 /* Link tolerance may change asynchronously: */
263 tipc_node_calculate_timer(n, l);
264 rc = tipc_link_timeout(l, &xmitq);
265 if (rc & TIPC_LINK_DOWN_EVT)
266 tipc_link_reset(l);
267 }
268 tipc_node_unlock(n);
269 maddr = &n->links[bearer_id].maddr;
270 tipc_bearer_xmit(n->net, bearer_id, &xmitq, maddr);
271 }
272 if (!mod_timer(&n->timer, jiffies + n->keepalive_intv))
273 tipc_node_get(n);
274 tipc_node_put(n);
275}
276
225/** 277/**
226 * tipc_node_link_up - handle addition of link 278 * tipc_node_link_up - handle addition of link
227 * 279 *
@@ -335,10 +387,16 @@ bool tipc_node_update_dest(struct tipc_node *n, struct tipc_bearer *b,
335 struct tipc_media_addr *curr = &n->links[b->identity].maddr; 387 struct tipc_media_addr *curr = &n->links[b->identity].maddr;
336 struct sk_buff_head *inputq = &n->links[b->identity].inputq; 388 struct sk_buff_head *inputq = &n->links[b->identity].inputq;
337 389
338 if (!l) 390 if (!l) {
339 l = tipc_link_create(n, b, maddr, inputq, &n->bclink.namedq); 391 l = tipc_link_create(n, b, maddr, inputq, &n->bclink.namedq);
340 if (!l) 392 if (!l)
341 return false; 393 return false;
394 tipc_node_calculate_timer(n, l);
395 if (n->link_cnt == 1) {
396 if (!mod_timer(&n->timer, jiffies + n->keepalive_intv))
397 tipc_node_get(n);
398 }
399 }
342 memcpy(&l->media_addr, maddr, sizeof(*maddr)); 400 memcpy(&l->media_addr, maddr, sizeof(*maddr));
343 memcpy(curr, maddr, sizeof(*maddr)); 401 memcpy(curr, maddr, sizeof(*maddr));
344 tipc_link_reset(l); 402 tipc_link_reset(l);