diff options
author | Tuong Lien <tuong.t.lien@dektech.com.au> | 2019-06-17 01:15:42 -0400 |
---|---|---|
committer | David S. Miller <davem@davemloft.net> | 2019-06-17 16:27:32 -0400 |
commit | 6a6b5c8bff89c76b09a921ef05b042fdee940f2a (patch) | |
tree | ae40dc030f1726f75b5386ae6f4709859b9364f7 /net/tipc | |
parent | 9ed68ca0d90b53ba00745cb61ef105599532226f (diff) |
tipc: include retrans failure detection for unicast
In patch series, commit 9195948fbf34 ("tipc: improve TIPC throughput by
Gap ACK blocks"), as for simplicity, the repeated retransmit failures'
detection in the function - "tipc_link_retrans()" was kept there for
broadcast retransmissions only.
This commit now reapplies this feature for link unicast retransmissions
that has been done via the function - "tipc_link_advance_transmq()".
Also, the "tipc_link_retrans()" is renamed to "tipc_link_bc_retrans()"
as it is used only for broadcast.
Acked-by: Jon Maloy <jon.maloy@ericsson.se>
Signed-off-by: Tuong Lien <tuong.t.lien@dektech.com.au>
Signed-off-by: David S. Miller <davem@davemloft.net>
Diffstat (limited to 'net/tipc')
-rw-r--r-- | net/tipc/link.c | 106 |
1 files changed, 70 insertions, 36 deletions
diff --git a/net/tipc/link.c b/net/tipc/link.c index f5cd986e1e50..d5ed509e0660 100644 --- a/net/tipc/link.c +++ b/net/tipc/link.c | |||
@@ -249,9 +249,9 @@ static void tipc_link_build_bc_init_msg(struct tipc_link *l, | |||
249 | struct sk_buff_head *xmitq); | 249 | struct sk_buff_head *xmitq); |
250 | static bool tipc_link_release_pkts(struct tipc_link *l, u16 to); | 250 | static bool tipc_link_release_pkts(struct tipc_link *l, u16 to); |
251 | static u16 tipc_build_gap_ack_blks(struct tipc_link *l, void *data); | 251 | static u16 tipc_build_gap_ack_blks(struct tipc_link *l, void *data); |
252 | static void tipc_link_advance_transmq(struct tipc_link *l, u16 acked, u16 gap, | 252 | static int tipc_link_advance_transmq(struct tipc_link *l, u16 acked, u16 gap, |
253 | struct tipc_gap_ack_blks *ga, | 253 | struct tipc_gap_ack_blks *ga, |
254 | struct sk_buff_head *xmitq); | 254 | struct sk_buff_head *xmitq); |
255 | 255 | ||
256 | /* | 256 | /* |
257 | * Simple non-static link routines (i.e. referenced outside this file) | 257 | * Simple non-static link routines (i.e. referenced outside this file) |
@@ -1044,32 +1044,69 @@ static void tipc_link_advance_backlog(struct tipc_link *l, | |||
1044 | l->snd_nxt = seqno; | 1044 | l->snd_nxt = seqno; |
1045 | } | 1045 | } |
1046 | 1046 | ||
1047 | static void link_retransmit_failure(struct tipc_link *l, struct sk_buff *skb) | 1047 | /** |
1048 | * link_retransmit_failure() - Detect repeated retransmit failures | ||
1049 | * @l: tipc link sender | ||
1050 | * @r: tipc link receiver (= l in case of unicast) | ||
1051 | * @from: seqno of the 1st packet in retransmit request | ||
1052 | * @rc: returned code | ||
1053 | * | ||
1054 | * Return: true if the repeated retransmit failures happens, otherwise | ||
1055 | * false | ||
1056 | */ | ||
1057 | static bool link_retransmit_failure(struct tipc_link *l, struct tipc_link *r, | ||
1058 | u16 from, int *rc) | ||
1048 | { | 1059 | { |
1049 | struct tipc_msg *hdr = buf_msg(skb); | 1060 | struct sk_buff *skb = skb_peek(&l->transmq); |
1061 | struct tipc_msg *hdr; | ||
1062 | |||
1063 | if (!skb) | ||
1064 | return false; | ||
1065 | hdr = buf_msg(skb); | ||
1066 | |||
1067 | /* Detect repeated retransmit failures on same packet */ | ||
1068 | if (r->prev_from != from) { | ||
1069 | r->prev_from = from; | ||
1070 | r->stale_limit = jiffies + msecs_to_jiffies(r->tolerance); | ||
1071 | r->stale_cnt = 0; | ||
1072 | } else if (++r->stale_cnt > 99 && time_after(jiffies, r->stale_limit)) { | ||
1073 | pr_warn("Retransmission failure on link <%s>\n", l->name); | ||
1074 | link_print(l, "State of link "); | ||
1075 | pr_info("Failed msg: usr %u, typ %u, len %u, err %u\n", | ||
1076 | msg_user(hdr), msg_type(hdr), msg_size(hdr), | ||
1077 | msg_errcode(hdr)); | ||
1078 | pr_info("sqno %u, prev: %x, src: %x\n", | ||
1079 | msg_seqno(hdr), msg_prevnode(hdr), msg_orignode(hdr)); | ||
1080 | |||
1081 | trace_tipc_list_dump(&l->transmq, true, "retrans failure!"); | ||
1082 | trace_tipc_link_dump(l, TIPC_DUMP_NONE, "retrans failure!"); | ||
1083 | trace_tipc_link_dump(r, TIPC_DUMP_NONE, "retrans failure!"); | ||
1084 | |||
1085 | if (link_is_bc_sndlink(l)) | ||
1086 | *rc = TIPC_LINK_DOWN_EVT; | ||
1087 | |||
1088 | *rc = tipc_link_fsm_evt(l, LINK_FAILURE_EVT); | ||
1089 | return true; | ||
1090 | } | ||
1050 | 1091 | ||
1051 | pr_warn("Retransmission failure on link <%s>\n", l->name); | 1092 | return false; |
1052 | link_print(l, "State of link "); | ||
1053 | pr_info("Failed msg: usr %u, typ %u, len %u, err %u\n", | ||
1054 | msg_user(hdr), msg_type(hdr), msg_size(hdr), msg_errcode(hdr)); | ||
1055 | pr_info("sqno %u, prev: %x, src: %x\n", | ||
1056 | msg_seqno(hdr), msg_prevnode(hdr), msg_orignode(hdr)); | ||
1057 | } | 1093 | } |
1058 | 1094 | ||
1059 | /* tipc_link_retrans() - retransmit one or more packets | 1095 | /* tipc_link_bc_retrans() - retransmit zero or more packets |
1060 | * @l: the link to transmit on | 1096 | * @l: the link to transmit on |
1061 | * @r: the receiving link ordering the retransmit. Same as l if unicast | 1097 | * @r: the receiving link ordering the retransmit. Same as l if unicast |
1062 | * @from: retransmit from (inclusive) this sequence number | 1098 | * @from: retransmit from (inclusive) this sequence number |
1063 | * @to: retransmit to (inclusive) this sequence number | 1099 | * @to: retransmit to (inclusive) this sequence number |
1064 | * xmitq: queue for accumulating the retransmitted packets | 1100 | * xmitq: queue for accumulating the retransmitted packets |
1065 | */ | 1101 | */ |
1066 | static int tipc_link_retrans(struct tipc_link *l, struct tipc_link *r, | 1102 | static int tipc_link_bc_retrans(struct tipc_link *l, struct tipc_link *r, |
1067 | u16 from, u16 to, struct sk_buff_head *xmitq) | 1103 | u16 from, u16 to, struct sk_buff_head *xmitq) |
1068 | { | 1104 | { |
1069 | struct sk_buff *_skb, *skb = skb_peek(&l->transmq); | 1105 | struct sk_buff *_skb, *skb = skb_peek(&l->transmq); |
1070 | u16 bc_ack = l->bc_rcvlink->rcv_nxt - 1; | 1106 | u16 bc_ack = l->bc_rcvlink->rcv_nxt - 1; |
1071 | u16 ack = l->rcv_nxt - 1; | 1107 | u16 ack = l->rcv_nxt - 1; |
1072 | struct tipc_msg *hdr; | 1108 | struct tipc_msg *hdr; |
1109 | int rc = 0; | ||
1073 | 1110 | ||
1074 | if (!skb) | 1111 | if (!skb) |
1075 | return 0; | 1112 | return 0; |
@@ -1077,20 +1114,9 @@ static int tipc_link_retrans(struct tipc_link *l, struct tipc_link *r, | |||
1077 | return 0; | 1114 | return 0; |
1078 | 1115 | ||
1079 | trace_tipc_link_retrans(r, from, to, &l->transmq); | 1116 | trace_tipc_link_retrans(r, from, to, &l->transmq); |
1080 | /* Detect repeated retransmit failures on same packet */ | 1117 | |
1081 | if (r->prev_from != from) { | 1118 | if (link_retransmit_failure(l, r, from, &rc)) |
1082 | r->prev_from = from; | 1119 | return rc; |
1083 | r->stale_limit = jiffies + msecs_to_jiffies(r->tolerance); | ||
1084 | r->stale_cnt = 0; | ||
1085 | } else if (++r->stale_cnt > 99 && time_after(jiffies, r->stale_limit)) { | ||
1086 | link_retransmit_failure(l, skb); | ||
1087 | trace_tipc_list_dump(&l->transmq, true, "retrans failure!"); | ||
1088 | trace_tipc_link_dump(l, TIPC_DUMP_NONE, "retrans failure!"); | ||
1089 | trace_tipc_link_dump(r, TIPC_DUMP_NONE, "retrans failure!"); | ||
1090 | if (link_is_bc_sndlink(l)) | ||
1091 | return TIPC_LINK_DOWN_EVT; | ||
1092 | return tipc_link_fsm_evt(l, LINK_FAILURE_EVT); | ||
1093 | } | ||
1094 | 1120 | ||
1095 | skb_queue_walk(&l->transmq, skb) { | 1121 | skb_queue_walk(&l->transmq, skb) { |
1096 | hdr = buf_msg(skb); | 1122 | hdr = buf_msg(skb); |
@@ -1324,17 +1350,23 @@ exit: | |||
1324 | * @gap: # of gap packets | 1350 | * @gap: # of gap packets |
1325 | * @ga: buffer pointer to Gap ACK blocks from peer | 1351 | * @ga: buffer pointer to Gap ACK blocks from peer |
1326 | * @xmitq: queue for accumulating the retransmitted packets if any | 1352 | * @xmitq: queue for accumulating the retransmitted packets if any |
1353 | * | ||
1354 | * In case of a repeated retransmit failures, the call will return shortly | ||
1355 | * with a returned code (e.g. TIPC_LINK_DOWN_EVT) | ||
1327 | */ | 1356 | */ |
1328 | static void tipc_link_advance_transmq(struct tipc_link *l, u16 acked, u16 gap, | 1357 | static int tipc_link_advance_transmq(struct tipc_link *l, u16 acked, u16 gap, |
1329 | struct tipc_gap_ack_blks *ga, | 1358 | struct tipc_gap_ack_blks *ga, |
1330 | struct sk_buff_head *xmitq) | 1359 | struct sk_buff_head *xmitq) |
1331 | { | 1360 | { |
1332 | struct sk_buff *skb, *_skb, *tmp; | 1361 | struct sk_buff *skb, *_skb, *tmp; |
1333 | struct tipc_msg *hdr; | 1362 | struct tipc_msg *hdr; |
1334 | u16 bc_ack = l->bc_rcvlink->rcv_nxt - 1; | 1363 | u16 bc_ack = l->bc_rcvlink->rcv_nxt - 1; |
1335 | u16 ack = l->rcv_nxt - 1; | 1364 | u16 ack = l->rcv_nxt - 1; |
1336 | u16 seqno; | 1365 | u16 seqno, n = 0; |
1337 | u16 n = 0; | 1366 | int rc = 0; |
1367 | |||
1368 | if (gap && link_retransmit_failure(l, l, acked + 1, &rc)) | ||
1369 | return rc; | ||
1338 | 1370 | ||
1339 | skb_queue_walk_safe(&l->transmq, skb, tmp) { | 1371 | skb_queue_walk_safe(&l->transmq, skb, tmp) { |
1340 | seqno = buf_seqno(skb); | 1372 | seqno = buf_seqno(skb); |
@@ -1369,6 +1401,8 @@ next_gap_ack: | |||
1369 | goto next_gap_ack; | 1401 | goto next_gap_ack; |
1370 | } | 1402 | } |
1371 | } | 1403 | } |
1404 | |||
1405 | return 0; | ||
1372 | } | 1406 | } |
1373 | 1407 | ||
1374 | /* tipc_link_build_state_msg: prepare link state message for transmission | 1408 | /* tipc_link_build_state_msg: prepare link state message for transmission |
@@ -1919,7 +1953,7 @@ static int tipc_link_proto_rcv(struct tipc_link *l, struct sk_buff *skb, | |||
1919 | tipc_link_build_proto_msg(l, STATE_MSG, 0, reply, | 1953 | tipc_link_build_proto_msg(l, STATE_MSG, 0, reply, |
1920 | rcvgap, 0, 0, xmitq); | 1954 | rcvgap, 0, 0, xmitq); |
1921 | 1955 | ||
1922 | tipc_link_advance_transmq(l, ack, gap, ga, xmitq); | 1956 | rc |= tipc_link_advance_transmq(l, ack, gap, ga, xmitq); |
1923 | 1957 | ||
1924 | /* If NACK, retransmit will now start at right position */ | 1958 | /* If NACK, retransmit will now start at right position */ |
1925 | if (gap) | 1959 | if (gap) |
@@ -2036,7 +2070,7 @@ int tipc_link_bc_sync_rcv(struct tipc_link *l, struct tipc_msg *hdr, | |||
2036 | if (more(peers_snd_nxt, l->rcv_nxt + l->window)) | 2070 | if (more(peers_snd_nxt, l->rcv_nxt + l->window)) |
2037 | return rc; | 2071 | return rc; |
2038 | 2072 | ||
2039 | rc = tipc_link_retrans(snd_l, l, from, to, xmitq); | 2073 | rc = tipc_link_bc_retrans(snd_l, l, from, to, xmitq); |
2040 | 2074 | ||
2041 | l->snd_nxt = peers_snd_nxt; | 2075 | l->snd_nxt = peers_snd_nxt; |
2042 | if (link_bc_rcv_gap(l)) | 2076 | if (link_bc_rcv_gap(l)) |
@@ -2132,7 +2166,7 @@ int tipc_link_bc_nack_rcv(struct tipc_link *l, struct sk_buff *skb, | |||
2132 | 2166 | ||
2133 | if (dnode == tipc_own_addr(l->net)) { | 2167 | if (dnode == tipc_own_addr(l->net)) { |
2134 | tipc_link_bc_ack_rcv(l, acked, xmitq); | 2168 | tipc_link_bc_ack_rcv(l, acked, xmitq); |
2135 | rc = tipc_link_retrans(l->bc_sndlink, l, from, to, xmitq); | 2169 | rc = tipc_link_bc_retrans(l->bc_sndlink, l, from, to, xmitq); |
2136 | l->stats.recv_nacks++; | 2170 | l->stats.recv_nacks++; |
2137 | return rc; | 2171 | return rc; |
2138 | } | 2172 | } |