aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorJon Paul Maloy <jon.maloy@ericsson.com>2015-10-15 14:52:45 -0400
committerDavid S. Miller <davem@davemloft.net>2015-10-16 02:55:22 -0400
commit282b3a056225b35024246f63feb91d769d714dad (patch)
tree0e29576cbef2318c0ddaf404c5f46c7b997ef7fe
parent73f646cec35477b5099d7e952297cb9e1855be45 (diff)
tipc: send out RESET immediately when link goes down
When a link is taken down because of a node local event, such as disabling of a bearer or an interface, we currently leave it to the peer node to discover the broken communication. The default time for such failure discovery is 1.5-2 seconds. If we instead allow the terminating link endpoint to send out a RESET message at the moment it is reset, we can achieve the impression that both endpoints are going down instantly. Since this is a very common scenario, we find it worthwhile to make this small modification. Apart from letting the link produce the said message, we also have to ensure that the interface is able to transmit it before TIPC is detached. We do this by performing the disabling of a bearer in three steps: 1) Disable reception of TIPC packets from the interface in question. 2) Take down the links, while allowing them so send out a RESET message. 3) Disable transmission of TIPC packets on the interface. Apart from this, we now have to react on the NETDEV_GOING_DOWN event, instead of as currently the NEDEV_DOWN event, to ensure that such transmission is possible during the teardown phase. Signed-off-by: Jon Maloy <jon.maloy@ericsson.com> Acked-by: Ying Xue <ying.xue@windriver.com> Signed-off-by: David S. Miller <davem@davemloft.net>
-rw-r--r--net/tipc/bearer.c8
-rw-r--r--net/tipc/link.c12
-rw-r--r--net/tipc/link.h1
-rw-r--r--net/tipc/node.c5
-rw-r--r--net/tipc/udp_media.c1
5 files changed, 19 insertions, 8 deletions
diff --git a/net/tipc/bearer.c b/net/tipc/bearer.c
index ce9f7bfc0b92..82b278668ab7 100644
--- a/net/tipc/bearer.c
+++ b/net/tipc/bearer.c
@@ -362,6 +362,7 @@ static void bearer_disable(struct net *net, struct tipc_bearer *b_ptr)
362 b_ptr->media->disable_media(b_ptr); 362 b_ptr->media->disable_media(b_ptr);
363 363
364 tipc_node_delete_links(net, b_ptr->identity); 364 tipc_node_delete_links(net, b_ptr->identity);
365 RCU_INIT_POINTER(b_ptr->media_ptr, NULL);
365 if (b_ptr->link_req) 366 if (b_ptr->link_req)
366 tipc_disc_delete(b_ptr->link_req); 367 tipc_disc_delete(b_ptr->link_req);
367 368
@@ -399,16 +400,13 @@ int tipc_enable_l2_media(struct net *net, struct tipc_bearer *b,
399 400
400/* tipc_disable_l2_media - detach TIPC bearer from an L2 interface 401/* tipc_disable_l2_media - detach TIPC bearer from an L2 interface
401 * 402 *
402 * Mark L2 bearer as inactive so that incoming buffers are thrown away, 403 * Mark L2 bearer as inactive so that incoming buffers are thrown away
403 * then get worker thread to complete bearer cleanup. (Can't do cleanup
404 * here because cleanup code needs to sleep and caller holds spinlocks.)
405 */ 404 */
406void tipc_disable_l2_media(struct tipc_bearer *b) 405void tipc_disable_l2_media(struct tipc_bearer *b)
407{ 406{
408 struct net_device *dev; 407 struct net_device *dev;
409 408
410 dev = (struct net_device *)rtnl_dereference(b->media_ptr); 409 dev = (struct net_device *)rtnl_dereference(b->media_ptr);
411 RCU_INIT_POINTER(b->media_ptr, NULL);
412 RCU_INIT_POINTER(dev->tipc_ptr, NULL); 410 RCU_INIT_POINTER(dev->tipc_ptr, NULL);
413 synchronize_net(); 411 synchronize_net();
414 dev_put(dev); 412 dev_put(dev);
@@ -554,7 +552,7 @@ static int tipc_l2_device_event(struct notifier_block *nb, unsigned long evt,
554 case NETDEV_CHANGE: 552 case NETDEV_CHANGE:
555 if (netif_carrier_ok(dev)) 553 if (netif_carrier_ok(dev))
556 break; 554 break;
557 case NETDEV_DOWN: 555 case NETDEV_GOING_DOWN:
558 case NETDEV_CHANGEMTU: 556 case NETDEV_CHANGEMTU:
559 tipc_reset_bearer(net, b_ptr); 557 tipc_reset_bearer(net, b_ptr);
560 break; 558 break;
diff --git a/net/tipc/link.c b/net/tipc/link.c
index 8c794c1dd531..737b5980020d 100644
--- a/net/tipc/link.c
+++ b/net/tipc/link.c
@@ -1062,6 +1062,18 @@ void tipc_link_build_ack_msg(struct tipc_link *l, struct sk_buff_head *xmitq)
1062 tipc_link_build_proto_msg(l, STATE_MSG, 0, 0, 0, 0, xmitq); 1062 tipc_link_build_proto_msg(l, STATE_MSG, 0, 0, 0, 0, xmitq);
1063} 1063}
1064 1064
1065/* tipc_link_build_reset_msg: prepare link RESET or ACTIVATE message
1066 */
1067void tipc_link_build_reset_msg(struct tipc_link *l, struct sk_buff_head *xmitq)
1068{
1069 int mtyp = RESET_MSG;
1070
1071 if (l->state == LINK_ESTABLISHING)
1072 mtyp = ACTIVATE_MSG;
1073
1074 tipc_link_build_proto_msg(l, mtyp, 0, 0, 0, 0, xmitq);
1075}
1076
1065/* tipc_link_build_nack_msg: prepare link nack message for transmission 1077/* tipc_link_build_nack_msg: prepare link nack message for transmission
1066 */ 1078 */
1067static void tipc_link_build_nack_msg(struct tipc_link *l, 1079static void tipc_link_build_nack_msg(struct tipc_link *l,
diff --git a/net/tipc/link.h b/net/tipc/link.h
index d42dfc0e7bf5..5872f090c8d8 100644
--- a/net/tipc/link.h
+++ b/net/tipc/link.h
@@ -213,6 +213,7 @@ void tipc_link_tnl_prepare(struct tipc_link *l, struct tipc_link *tnl,
213 int mtyp, struct sk_buff_head *xmitq); 213 int mtyp, struct sk_buff_head *xmitq);
214void tipc_link_build_bcast_sync_msg(struct tipc_link *l, 214void tipc_link_build_bcast_sync_msg(struct tipc_link *l,
215 struct sk_buff_head *xmitq); 215 struct sk_buff_head *xmitq);
216void tipc_link_build_reset_msg(struct tipc_link *l, struct sk_buff_head *xmitq);
216int tipc_link_fsm_evt(struct tipc_link *l, int evt); 217int tipc_link_fsm_evt(struct tipc_link *l, int evt);
217void tipc_link_reset_fragments(struct tipc_link *l_ptr); 218void tipc_link_reset_fragments(struct tipc_link *l_ptr);
218bool tipc_link_is_up(struct tipc_link *l); 219bool tipc_link_is_up(struct tipc_link *l);
diff --git a/net/tipc/node.c b/net/tipc/node.c
index 656b5791f1a5..fba6e1af28e8 100644
--- a/net/tipc/node.c
+++ b/net/tipc/node.c
@@ -41,7 +41,7 @@
41#include "socket.h" 41#include "socket.h"
42#include "bcast.h" 42#include "bcast.h"
43#include "discover.h" 43#include "discover.h"
44 44#define pr_debug printk
45/* Node FSM states and events: 45/* Node FSM states and events:
46 */ 46 */
47enum { 47enum {
@@ -421,6 +421,8 @@ static void __tipc_node_link_down(struct tipc_node *n, int *bearer_id,
421 421
422 if (!tipc_node_is_up(n)) { 422 if (!tipc_node_is_up(n)) {
423 tipc_link_reset(l); 423 tipc_link_reset(l);
424 tipc_link_build_reset_msg(l, xmitq);
425 *maddr = &n->links[*bearer_id].maddr;
424 node_lost_contact(n, &le->inputq); 426 node_lost_contact(n, &le->inputq);
425 return; 427 return;
426 } 428 }
@@ -463,7 +465,6 @@ static void tipc_node_link_down(struct tipc_node *n, int bearer_id, bool delete)
463 tipc_link_fsm_evt(l, LINK_RESET_EVT); 465 tipc_link_fsm_evt(l, LINK_RESET_EVT);
464 } 466 }
465 tipc_node_unlock(n); 467 tipc_node_unlock(n);
466
467 tipc_bearer_xmit(n->net, bearer_id, &xmitq, maddr); 468 tipc_bearer_xmit(n->net, bearer_id, &xmitq, maddr);
468 tipc_sk_rcv(n->net, &le->inputq); 469 tipc_sk_rcv(n->net, &le->inputq);
469} 470}
diff --git a/net/tipc/udp_media.c b/net/tipc/udp_media.c
index c170d3138953..9bc0b1e515fa 100644
--- a/net/tipc/udp_media.c
+++ b/net/tipc/udp_media.c
@@ -425,7 +425,6 @@ static void tipc_udp_disable(struct tipc_bearer *b)
425 } 425 }
426 if (ub->ubsock) 426 if (ub->ubsock)
427 sock_set_flag(ub->ubsock->sk, SOCK_DEAD); 427 sock_set_flag(ub->ubsock->sk, SOCK_DEAD);
428 RCU_INIT_POINTER(b->media_ptr, NULL);
429 RCU_INIT_POINTER(ub->bearer, NULL); 428 RCU_INIT_POINTER(ub->bearer, NULL);
430 429
431 /* sock_release need to be done outside of rtnl lock */ 430 /* sock_release need to be done outside of rtnl lock */