aboutsummaryrefslogtreecommitdiffstats
path: root/net/tipc
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
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')
-rw-r--r--net/tipc/link.c3
-rw-r--r--net/tipc/node.c12
2 files changed, 12 insertions, 3 deletions
diff --git a/net/tipc/link.c b/net/tipc/link.c
index 7058c86f5e48..75db07c78a69 100644
--- a/net/tipc/link.c
+++ b/net/tipc/link.c
@@ -1330,6 +1330,7 @@ static int tipc_link_proto_rcv(struct tipc_link *l, struct sk_buff *skb,
1330 u16 peers_snd_nxt = msg_next_sent(hdr); 1330 u16 peers_snd_nxt = msg_next_sent(hdr);
1331 u16 peers_tol = msg_link_tolerance(hdr); 1331 u16 peers_tol = msg_link_tolerance(hdr);
1332 u16 peers_prio = msg_linkprio(hdr); 1332 u16 peers_prio = msg_linkprio(hdr);
1333 u16 rcv_nxt = l->rcv_nxt;
1333 char *if_name; 1334 char *if_name;
1334 int rc = 0; 1335 int rc = 0;
1335 1336
@@ -1393,7 +1394,7 @@ static int tipc_link_proto_rcv(struct tipc_link *l, struct sk_buff *skb,
1393 break; 1394 break;
1394 1395
1395 /* Send NACK if peer has sent pkts we haven't received yet */ 1396 /* Send NACK if peer has sent pkts we haven't received yet */
1396 if (more(peers_snd_nxt, l->rcv_nxt)) 1397 if (more(peers_snd_nxt, rcv_nxt) && !tipc_link_is_synching(l))
1397 rcvgap = peers_snd_nxt - l->rcv_nxt; 1398 rcvgap = peers_snd_nxt - l->rcv_nxt;
1398 if (rcvgap || (msg_probe(hdr))) 1399 if (rcvgap || (msg_probe(hdr)))
1399 tipc_link_build_proto_msg(l, STATE_MSG, 0, rcvgap, 1400 tipc_link_build_proto_msg(l, STATE_MSG, 0, rcvgap,
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)