aboutsummaryrefslogtreecommitdiffstats
path: root/net/tipc/node.c
diff options
context:
space:
mode:
authorWolfram Sang <wsa@the-dreams.de>2014-06-17 08:36:41 -0400
committerWolfram Sang <wsa@the-dreams.de>2014-06-17 08:37:31 -0400
commitf0b1f6442b5090fed3529cb39f3acf8c91693d3d (patch)
treebc5f62b017a82161c9a7f892f464813f6efd5bf3 /net/tipc/node.c
parent4632a93f015caf6d7db4352f37aab74a39e60d7a (diff)
parent7171511eaec5bf23fb06078f59784a3a0626b38f (diff)
Merge tag 'v3.16-rc1' into i2c/for-next
Merge a stable base (Linux 3.16-rc1) Signed-off-by: Wolfram Sang <wsa@the-dreams.de>
Diffstat (limited to 'net/tipc/node.c')
-rw-r--r--net/tipc/node.c110
1 files changed, 80 insertions, 30 deletions
diff --git a/net/tipc/node.c b/net/tipc/node.c
index 1d3a4999a70f..5b44c3041be4 100644
--- a/net/tipc/node.c
+++ b/net/tipc/node.c
@@ -108,7 +108,7 @@ struct tipc_node *tipc_node_create(u32 addr)
108 break; 108 break;
109 } 109 }
110 list_add_tail_rcu(&n_ptr->list, &temp_node->list); 110 list_add_tail_rcu(&n_ptr->list, &temp_node->list);
111 n_ptr->block_setup = WAIT_PEER_DOWN; 111 n_ptr->action_flags = TIPC_WAIT_PEER_LINKS_DOWN;
112 n_ptr->signature = INVALID_NODE_SIG; 112 n_ptr->signature = INVALID_NODE_SIG;
113 113
114 tipc_num_nodes++; 114 tipc_num_nodes++;
@@ -144,11 +144,13 @@ void tipc_node_stop(void)
144void tipc_node_link_up(struct tipc_node *n_ptr, struct tipc_link *l_ptr) 144void tipc_node_link_up(struct tipc_node *n_ptr, struct tipc_link *l_ptr)
145{ 145{
146 struct tipc_link **active = &n_ptr->active_links[0]; 146 struct tipc_link **active = &n_ptr->active_links[0];
147 u32 addr = n_ptr->addr;
147 148
148 n_ptr->working_links++; 149 n_ptr->working_links++;
149 150 tipc_nametbl_publish(TIPC_LINK_STATE, addr, addr, TIPC_NODE_SCOPE,
151 l_ptr->bearer_id, addr);
150 pr_info("Established link <%s> on network plane %c\n", 152 pr_info("Established link <%s> on network plane %c\n",
151 l_ptr->name, l_ptr->b_ptr->net_plane); 153 l_ptr->name, l_ptr->net_plane);
152 154
153 if (!active[0]) { 155 if (!active[0]) {
154 active[0] = active[1] = l_ptr; 156 active[0] = active[1] = l_ptr;
@@ -203,16 +205,18 @@ static void node_select_active_links(struct tipc_node *n_ptr)
203void tipc_node_link_down(struct tipc_node *n_ptr, struct tipc_link *l_ptr) 205void tipc_node_link_down(struct tipc_node *n_ptr, struct tipc_link *l_ptr)
204{ 206{
205 struct tipc_link **active; 207 struct tipc_link **active;
208 u32 addr = n_ptr->addr;
206 209
207 n_ptr->working_links--; 210 n_ptr->working_links--;
211 tipc_nametbl_withdraw(TIPC_LINK_STATE, addr, l_ptr->bearer_id, addr);
208 212
209 if (!tipc_link_is_active(l_ptr)) { 213 if (!tipc_link_is_active(l_ptr)) {
210 pr_info("Lost standby link <%s> on network plane %c\n", 214 pr_info("Lost standby link <%s> on network plane %c\n",
211 l_ptr->name, l_ptr->b_ptr->net_plane); 215 l_ptr->name, l_ptr->net_plane);
212 return; 216 return;
213 } 217 }
214 pr_info("Lost link <%s> on network plane %c\n", 218 pr_info("Lost link <%s> on network plane %c\n",
215 l_ptr->name, l_ptr->b_ptr->net_plane); 219 l_ptr->name, l_ptr->net_plane);
216 220
217 active = &n_ptr->active_links[0]; 221 active = &n_ptr->active_links[0];
218 if (active[0] == l_ptr) 222 if (active[0] == l_ptr)
@@ -239,7 +243,7 @@ int tipc_node_is_up(struct tipc_node *n_ptr)
239 243
240void tipc_node_attach_link(struct tipc_node *n_ptr, struct tipc_link *l_ptr) 244void tipc_node_attach_link(struct tipc_node *n_ptr, struct tipc_link *l_ptr)
241{ 245{
242 n_ptr->links[l_ptr->b_ptr->identity] = l_ptr; 246 n_ptr->links[l_ptr->bearer_id] = l_ptr;
243 spin_lock_bh(&node_list_lock); 247 spin_lock_bh(&node_list_lock);
244 tipc_num_links++; 248 tipc_num_links++;
245 spin_unlock_bh(&node_list_lock); 249 spin_unlock_bh(&node_list_lock);
@@ -263,26 +267,12 @@ void tipc_node_detach_link(struct tipc_node *n_ptr, struct tipc_link *l_ptr)
263 267
264static void node_established_contact(struct tipc_node *n_ptr) 268static void node_established_contact(struct tipc_node *n_ptr)
265{ 269{
266 tipc_k_signal((Handler)tipc_named_node_up, n_ptr->addr); 270 n_ptr->action_flags |= TIPC_NOTIFY_NODE_UP;
267 n_ptr->bclink.oos_state = 0; 271 n_ptr->bclink.oos_state = 0;
268 n_ptr->bclink.acked = tipc_bclink_get_last_sent(); 272 n_ptr->bclink.acked = tipc_bclink_get_last_sent();
269 tipc_bclink_add_node(n_ptr->addr); 273 tipc_bclink_add_node(n_ptr->addr);
270} 274}
271 275
272static void node_name_purge_complete(unsigned long node_addr)
273{
274 struct tipc_node *n_ptr;
275
276 read_lock_bh(&tipc_net_lock);
277 n_ptr = tipc_node_find(node_addr);
278 if (n_ptr) {
279 tipc_node_lock(n_ptr);
280 n_ptr->block_setup &= ~WAIT_NAMES_GONE;
281 tipc_node_unlock(n_ptr);
282 }
283 read_unlock_bh(&tipc_net_lock);
284}
285
286static void node_lost_contact(struct tipc_node *n_ptr) 276static void node_lost_contact(struct tipc_node *n_ptr)
287{ 277{
288 char addr_string[16]; 278 char addr_string[16];
@@ -296,10 +286,9 @@ static void node_lost_contact(struct tipc_node *n_ptr)
296 kfree_skb_list(n_ptr->bclink.deferred_head); 286 kfree_skb_list(n_ptr->bclink.deferred_head);
297 n_ptr->bclink.deferred_size = 0; 287 n_ptr->bclink.deferred_size = 0;
298 288
299 if (n_ptr->bclink.reasm_head) { 289 if (n_ptr->bclink.reasm_buf) {
300 kfree_skb(n_ptr->bclink.reasm_head); 290 kfree_skb(n_ptr->bclink.reasm_buf);
301 n_ptr->bclink.reasm_head = NULL; 291 n_ptr->bclink.reasm_buf = NULL;
302 n_ptr->bclink.reasm_tail = NULL;
303 } 292 }
304 293
305 tipc_bclink_remove_node(n_ptr->addr); 294 tipc_bclink_remove_node(n_ptr->addr);
@@ -318,12 +307,13 @@ static void node_lost_contact(struct tipc_node *n_ptr)
318 tipc_link_reset_fragments(l_ptr); 307 tipc_link_reset_fragments(l_ptr);
319 } 308 }
320 309
321 /* Notify subscribers */ 310 n_ptr->action_flags &= ~TIPC_WAIT_OWN_LINKS_DOWN;
322 tipc_nodesub_notify(n_ptr);
323 311
324 /* Prevent re-contact with node until cleanup is done */ 312 /* Notify subscribers and prevent re-contact with node until
325 n_ptr->block_setup = WAIT_PEER_DOWN | WAIT_NAMES_GONE; 313 * cleanup is done.
326 tipc_k_signal((Handler)node_name_purge_complete, n_ptr->addr); 314 */
315 n_ptr->action_flags |= TIPC_WAIT_PEER_LINKS_DOWN |
316 TIPC_NOTIFY_NODE_DOWN;
327} 317}
328 318
329struct sk_buff *tipc_node_get_nodes(const void *req_tlv_area, int req_tlv_space) 319struct sk_buff *tipc_node_get_nodes(const void *req_tlv_area, int req_tlv_space)
@@ -436,3 +426,63 @@ struct sk_buff *tipc_node_get_links(const void *req_tlv_area, int req_tlv_space)
436 rcu_read_unlock(); 426 rcu_read_unlock();
437 return buf; 427 return buf;
438} 428}
429
430/**
431 * tipc_node_get_linkname - get the name of a link
432 *
433 * @bearer_id: id of the bearer
434 * @node: peer node address
435 * @linkname: link name output buffer
436 *
437 * Returns 0 on success
438 */
439int tipc_node_get_linkname(u32 bearer_id, u32 addr, char *linkname, size_t len)
440{
441 struct tipc_link *link;
442 struct tipc_node *node = tipc_node_find(addr);
443
444 if ((bearer_id >= MAX_BEARERS) || !node)
445 return -EINVAL;
446 tipc_node_lock(node);
447 link = node->links[bearer_id];
448 if (link) {
449 strncpy(linkname, link->name, len);
450 tipc_node_unlock(node);
451 return 0;
452 }
453 tipc_node_unlock(node);
454 return -EINVAL;
455}
456
457void tipc_node_unlock(struct tipc_node *node)
458{
459 LIST_HEAD(nsub_list);
460 struct tipc_link *link;
461 int pkt_sz = 0;
462 u32 addr = 0;
463
464 if (likely(!node->action_flags)) {
465 spin_unlock_bh(&node->lock);
466 return;
467 }
468
469 if (node->action_flags & TIPC_NOTIFY_NODE_DOWN) {
470 list_replace_init(&node->nsub, &nsub_list);
471 node->action_flags &= ~TIPC_NOTIFY_NODE_DOWN;
472 }
473 if (node->action_flags & TIPC_NOTIFY_NODE_UP) {
474 link = node->active_links[0];
475 node->action_flags &= ~TIPC_NOTIFY_NODE_UP;
476 if (link) {
477 pkt_sz = ((link->max_pkt - INT_H_SIZE) / ITEM_SIZE) *
478 ITEM_SIZE;
479 addr = node->addr;
480 }
481 }
482 spin_unlock_bh(&node->lock);
483
484 if (!list_empty(&nsub_list))
485 tipc_nodesub_notify(&nsub_list);
486 if (pkt_sz)
487 tipc_named_node_up(pkt_sz, addr);
488}