aboutsummaryrefslogtreecommitdiffstats
path: root/net/tipc/node.c
diff options
context:
space:
mode:
authorJon Paul Maloy <jon.maloy@ericsson.com>2015-08-20 02:12:56 -0400
committerDavid S. Miller <davem@davemloft.net>2015-08-23 19:14:45 -0400
commit2be80c2d87de789550982e74a11e9f9ff5940845 (patch)
tree770c62b51c829656d65a00834fb82e9b845ec547 /net/tipc/node.c
parent5ae2f8e6857968d6dddbd3879ed0a32b860e02d1 (diff)
tipc: fix stale link problem during synchronization
Recent changes to the link synchronization means that we can now just drop packets arriving on the synchronizing link before the synch point is reached. This has lead to significant simplifications to the implementation, but also turns out to have a flip side that we need to consider. Under unlucky circumstances, the two endpoints may end up repeatedly dropping each other's packets, while immediately asking for retransmission of the same packets, just to drop them once more. This pattern will eventually be broken when the synch point is reached on the other link, but before that, the endpoints may have arrived at the retransmission limit (stale counter) that indicates that the link should be broken. We see this happen at rare occasions. The fix for this is to not ask for retransmissions when a link is in state LINK_SYNCHING. The fact that the link has reached this state means that it has already received the first SYNCH packet, and that it knows the synch point. Hence, it doesn't need any more packets until the other link has reached the synch point, whereafter it can go ahead and ask for the missing packets. However, because of the reduced traffic on the synching link that follows this change, it may now take longer to discover that the synch point has been reached. We compensate for this by letting all packets, on any of the links, trig a check for synchronization termination. This is possible because the packets themselves don't contain any information that is needed for discovering this condition. Reviewed-by: Ying Xue <ying.xue@windriver.com> Signed-off-by: Jon Maloy <jon.maloy@ericsson.com> Signed-off-by: David S. Miller <davem@davemloft.net>
Diffstat (limited to 'net/tipc/node.c')
-rw-r--r--net/tipc/node.c12
1 files changed, 10 insertions, 2 deletions
diff --git a/net/tipc/node.c b/net/tipc/node.c
index 937cc6192bcf..703875fd6cde 100644
--- a/net/tipc/node.c
+++ b/net/tipc/node.c
@@ -1079,7 +1079,7 @@ static bool tipc_node_check_state(struct tipc_node *n, struct sk_buff *skb,
1079 u16 exp_pkts = msg_msgcnt(hdr); 1079 u16 exp_pkts = msg_msgcnt(hdr);
1080 u16 rcv_nxt, syncpt, dlv_nxt; 1080 u16 rcv_nxt, syncpt, dlv_nxt;
1081 int state = n->state; 1081 int state = n->state;
1082 struct tipc_link *l, *pl = NULL; 1082 struct tipc_link *l, *tnl, *pl = NULL;
1083 struct tipc_media_addr *maddr; 1083 struct tipc_media_addr *maddr;
1084 int i, pb_id; 1084 int i, pb_id;
1085 1085
@@ -1164,12 +1164,20 @@ static bool tipc_node_check_state(struct tipc_node *n, struct sk_buff *skb,
1164 1164
1165 /* Open tunnel link when parallel link reaches synch point */ 1165 /* Open tunnel link when parallel link reaches synch point */
1166 if ((n->state == NODE_SYNCHING) && tipc_link_is_synching(l)) { 1166 if ((n->state == NODE_SYNCHING) && tipc_link_is_synching(l)) {
1167 if (tipc_link_is_synching(l)) {
1168 tnl = l;
1169 } else {
1170 tnl = pl;
1171 pl = l;
1172 }
1167 dlv_nxt = pl->rcv_nxt - mod(skb_queue_len(pl->inputq)); 1173 dlv_nxt = pl->rcv_nxt - mod(skb_queue_len(pl->inputq));
1168 if (more(dlv_nxt, n->sync_point)) { 1174 if (more(dlv_nxt, n->sync_point)) {
1169 tipc_link_fsm_evt(l, LINK_SYNCH_END_EVT); 1175 tipc_link_fsm_evt(tnl, LINK_SYNCH_END_EVT);
1170 tipc_node_fsm_evt(n, NODE_SYNCH_END_EVT); 1176 tipc_node_fsm_evt(n, NODE_SYNCH_END_EVT);
1171 return true; 1177 return true;
1172 } 1178 }
1179 if (l == pl)
1180 return true;
1173 if ((usr == TUNNEL_PROTOCOL) && (mtyp == SYNCH_MSG)) 1181 if ((usr == TUNNEL_PROTOCOL) && (mtyp == SYNCH_MSG))
1174 return true; 1182 return true;
1175 if (usr == LINK_PROTOCOL) 1183 if (usr == LINK_PROTOCOL)