tipc: send out RESET immediately when link goes down
authorJon Paul Maloy <jon.maloy@ericsson.com>
Thu, 15 Oct 2015 18:52:45 +0000 (14:52 -0400)
committerDavid S. Miller <davem@davemloft.net>
Fri, 16 Oct 2015 06:55:22 +0000 (23:55 -0700)
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>
net/tipc/bearer.c
net/tipc/link.c
net/tipc/link.h
net/tipc/node.c
net/tipc/udp_media.c

index ce9f7bfc0b92444950f51893e87abbc426151eb6..82b278668ab708d98a77a221d73412b44a93e144 100644 (file)
@@ -362,6 +362,7 @@ static void bearer_disable(struct net *net, struct tipc_bearer *b_ptr)
        b_ptr->media->disable_media(b_ptr);
 
        tipc_node_delete_links(net, b_ptr->identity);
+       RCU_INIT_POINTER(b_ptr->media_ptr, NULL);
        if (b_ptr->link_req)
                tipc_disc_delete(b_ptr->link_req);
 
@@ -399,16 +400,13 @@ int tipc_enable_l2_media(struct net *net, struct tipc_bearer *b,
 
 /* tipc_disable_l2_media - detach TIPC bearer from an L2 interface
  *
- * Mark L2 bearer as inactive so that incoming buffers are thrown away,
- * then get worker thread to complete bearer cleanup.  (Can't do cleanup
- * here because cleanup code needs to sleep and caller holds spinlocks.)
+ * Mark L2 bearer as inactive so that incoming buffers are thrown away
  */
 void tipc_disable_l2_media(struct tipc_bearer *b)
 {
        struct net_device *dev;
 
        dev = (struct net_device *)rtnl_dereference(b->media_ptr);
-       RCU_INIT_POINTER(b->media_ptr, NULL);
        RCU_INIT_POINTER(dev->tipc_ptr, NULL);
        synchronize_net();
        dev_put(dev);
@@ -554,7 +552,7 @@ static int tipc_l2_device_event(struct notifier_block *nb, unsigned long evt,
        case NETDEV_CHANGE:
                if (netif_carrier_ok(dev))
                        break;
-       case NETDEV_DOWN:
+       case NETDEV_GOING_DOWN:
        case NETDEV_CHANGEMTU:
                tipc_reset_bearer(net, b_ptr);
                break;
index 8c794c1dd531db3d5535d66e19ec09c0d55db449..737b5980020d9059b5ba7f427b0432acfb0750f5 100644 (file)
@@ -1062,6 +1062,18 @@ void tipc_link_build_ack_msg(struct tipc_link *l, struct sk_buff_head *xmitq)
        tipc_link_build_proto_msg(l, STATE_MSG, 0, 0, 0, 0, xmitq);
 }
 
+/* tipc_link_build_reset_msg: prepare link RESET or ACTIVATE message
+ */
+void tipc_link_build_reset_msg(struct tipc_link *l, struct sk_buff_head *xmitq)
+{
+       int mtyp = RESET_MSG;
+
+       if (l->state == LINK_ESTABLISHING)
+               mtyp = ACTIVATE_MSG;
+
+       tipc_link_build_proto_msg(l, mtyp, 0, 0, 0, 0, xmitq);
+}
+
 /* tipc_link_build_nack_msg: prepare link nack message for transmission
  */
 static void tipc_link_build_nack_msg(struct tipc_link *l,
index d42dfc0e7bf56f325c3d1bea1954c5c504ede9d9..5872f090c8d8b9c18aafee46bb31adbccde8a946 100644 (file)
@@ -213,6 +213,7 @@ void tipc_link_tnl_prepare(struct tipc_link *l, struct tipc_link *tnl,
                           int mtyp, struct sk_buff_head *xmitq);
 void tipc_link_build_bcast_sync_msg(struct tipc_link *l,
                                    struct sk_buff_head *xmitq);
+void tipc_link_build_reset_msg(struct tipc_link *l, struct sk_buff_head *xmitq);
 int tipc_link_fsm_evt(struct tipc_link *l, int evt);
 void tipc_link_reset_fragments(struct tipc_link *l_ptr);
 bool tipc_link_is_up(struct tipc_link *l);
index 656b5791f1a576ef5e5ece17f2a9113998d82cfb..fba6e1af28e895169bba36af0bc820e39e179622 100644 (file)
@@ -41,7 +41,7 @@
 #include "socket.h"
 #include "bcast.h"
 #include "discover.h"
-
+#define pr_debug printk
 /* Node FSM states and events:
  */
 enum {
@@ -421,6 +421,8 @@ static void __tipc_node_link_down(struct tipc_node *n, int *bearer_id,
 
        if (!tipc_node_is_up(n)) {
                tipc_link_reset(l);
+               tipc_link_build_reset_msg(l, xmitq);
+               *maddr = &n->links[*bearer_id].maddr;
                node_lost_contact(n, &le->inputq);
                return;
        }
@@ -463,7 +465,6 @@ static void tipc_node_link_down(struct tipc_node *n, int bearer_id, bool delete)
                tipc_link_fsm_evt(l, LINK_RESET_EVT);
        }
        tipc_node_unlock(n);
-
        tipc_bearer_xmit(n->net, bearer_id, &xmitq, maddr);
        tipc_sk_rcv(n->net, &le->inputq);
 }
index c170d3138953a2361df5439aeffadd29afa52ad9..9bc0b1e515fa3278955a60a31d8298f5ac600336 100644 (file)
@@ -425,7 +425,6 @@ static void tipc_udp_disable(struct tipc_bearer *b)
        }
        if (ub->ubsock)
                sock_set_flag(ub->ubsock->sk, SOCK_DEAD);
-       RCU_INIT_POINTER(b->media_ptr, NULL);
        RCU_INIT_POINTER(ub->bearer, NULL);
 
        /* sock_release need to be done outside of rtnl lock */