diff options
Diffstat (limited to 'net/tipc/node.c')
-rw-r--r-- | net/tipc/node.c | 66 |
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 @@ | |||
44 | static void node_lost_contact(struct tipc_node *n_ptr); | 44 | static void node_lost_contact(struct tipc_node *n_ptr); |
45 | static void node_established_contact(struct tipc_node *n_ptr); | 45 | static void node_established_contact(struct tipc_node *n_ptr); |
46 | static void tipc_node_delete(struct tipc_node *node); | 46 | static void tipc_node_delete(struct tipc_node *node); |
47 | static void tipc_node_timeout(unsigned long data); | ||
47 | 48 | ||
48 | struct tipc_sock_conn { | 49 | struct 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; | ||
148 | exit: | 151 | exit: |
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 | ||
156 | static 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 | |||
153 | static void tipc_node_delete(struct tipc_node *node) | 170 | static 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 | */ | ||
247 | static 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); |