diff options
author | Ilpo Järvinen <ilpo.jarvinen@helsinki.fi> | 2008-09-21 00:20:20 -0400 |
---|---|---|
committer | David S. Miller <davem@davemloft.net> | 2008-09-21 00:20:20 -0400 |
commit | 006f582c73f4eda35e06fd323193c3df43fb3459 (patch) | |
tree | d82762cfb6fb5e6889a52d316fa263a80c4f9fb3 /net/ipv4/tcp_input.c | |
parent | 41ea36e35a0daa75377b3e70680e5c3a3f83fe27 (diff) |
tcp: convert retransmit_cnt_hint to seqno
Main benefit in this is that we can then freely point
the retransmit_skb_hint to anywhere we want to because
there's no longer need to know what would be the count
changes involve, and since this is really used only as a
terminator, unnecessary work is one time walk at most,
and if some retransmissions are necessary after that
point later on, the walk is not full waste of time
anyway.
Since retransmit_high must be kept valid, all lost
markers must ensure that.
Now I also have learned how those "holes" in the
rexmittable skbs can appear, mtu probe does them. So
I removed the misleading comment as well.
Signed-off-by: Ilpo Järvinen <ilpo.jarvinen@helsinki.fi>
Signed-off-by: David S. Miller <davem@davemloft.net>
Diffstat (limited to 'net/ipv4/tcp_input.c')
-rw-r--r-- | net/ipv4/tcp_input.c | 34 |
1 files changed, 20 insertions, 14 deletions
diff --git a/net/ipv4/tcp_input.c b/net/ipv4/tcp_input.c index 12512336dbd8..d271cc825005 100644 --- a/net/ipv4/tcp_input.c +++ b/net/ipv4/tcp_input.c | |||
@@ -979,17 +979,17 @@ static void tcp_update_reordering(struct sock *sk, const int metric, | |||
979 | } | 979 | } |
980 | } | 980 | } |
981 | 981 | ||
982 | /* RFC: This is from the original, I doubt that this is necessary at all: | 982 | /* This must be called before lost_out is incremented */ |
983 | * clear xmit_retrans hint if seq of this skb is beyond hint. How could we | ||
984 | * retransmitted past LOST markings in the first place? I'm not fully sure | ||
985 | * about undo and end of connection cases, which can cause R without L? | ||
986 | */ | ||
987 | static void tcp_verify_retransmit_hint(struct tcp_sock *tp, struct sk_buff *skb) | 983 | static void tcp_verify_retransmit_hint(struct tcp_sock *tp, struct sk_buff *skb) |
988 | { | 984 | { |
989 | if ((tp->retransmit_skb_hint != NULL) && | 985 | if ((tp->retransmit_skb_hint == NULL) || |
990 | before(TCP_SKB_CB(skb)->seq, | 986 | before(TCP_SKB_CB(skb)->seq, |
991 | TCP_SKB_CB(tp->retransmit_skb_hint)->seq)) | 987 | TCP_SKB_CB(tp->retransmit_skb_hint)->seq)) |
992 | tp->retransmit_skb_hint = NULL; | 988 | tp->retransmit_skb_hint = skb; |
989 | |||
990 | if (!tp->lost_out || | ||
991 | after(TCP_SKB_CB(skb)->end_seq, tp->retransmit_high)) | ||
992 | tp->retransmit_high = TCP_SKB_CB(skb)->end_seq; | ||
993 | } | 993 | } |
994 | 994 | ||
995 | static void tcp_skb_mark_lost(struct tcp_sock *tp, struct sk_buff *skb) | 995 | static void tcp_skb_mark_lost(struct tcp_sock *tp, struct sk_buff *skb) |
@@ -1002,6 +1002,16 @@ static void tcp_skb_mark_lost(struct tcp_sock *tp, struct sk_buff *skb) | |||
1002 | } | 1002 | } |
1003 | } | 1003 | } |
1004 | 1004 | ||
1005 | void tcp_skb_mark_lost_uncond_verify(struct tcp_sock *tp, struct sk_buff *skb) | ||
1006 | { | ||
1007 | tcp_verify_retransmit_hint(tp, skb); | ||
1008 | |||
1009 | if (!(TCP_SKB_CB(skb)->sacked & (TCPCB_LOST|TCPCB_SACKED_ACKED))) { | ||
1010 | tp->lost_out += tcp_skb_pcount(skb); | ||
1011 | TCP_SKB_CB(skb)->sacked |= TCPCB_LOST; | ||
1012 | } | ||
1013 | } | ||
1014 | |||
1005 | /* This procedure tags the retransmission queue when SACKs arrive. | 1015 | /* This procedure tags the retransmission queue when SACKs arrive. |
1006 | * | 1016 | * |
1007 | * We have three tag bits: SACKED(S), RETRANS(R) and LOST(L). | 1017 | * We have three tag bits: SACKED(S), RETRANS(R) and LOST(L). |
@@ -1178,13 +1188,7 @@ static void tcp_mark_lost_retrans(struct sock *sk) | |||
1178 | TCP_SKB_CB(skb)->sacked &= ~TCPCB_SACKED_RETRANS; | 1188 | TCP_SKB_CB(skb)->sacked &= ~TCPCB_SACKED_RETRANS; |
1179 | tp->retrans_out -= tcp_skb_pcount(skb); | 1189 | tp->retrans_out -= tcp_skb_pcount(skb); |
1180 | 1190 | ||
1181 | /* clear lost hint */ | 1191 | tcp_skb_mark_lost_uncond_verify(tp, skb); |
1182 | tp->retransmit_skb_hint = NULL; | ||
1183 | |||
1184 | if (!(TCP_SKB_CB(skb)->sacked & (TCPCB_LOST|TCPCB_SACKED_ACKED))) { | ||
1185 | tp->lost_out += tcp_skb_pcount(skb); | ||
1186 | TCP_SKB_CB(skb)->sacked |= TCPCB_LOST; | ||
1187 | } | ||
1188 | NET_INC_STATS_BH(sock_net(sk), LINUX_MIB_TCPLOSTRETRANSMIT); | 1192 | NET_INC_STATS_BH(sock_net(sk), LINUX_MIB_TCPLOSTRETRANSMIT); |
1189 | } else { | 1193 | } else { |
1190 | if (before(ack_seq, new_low_seq)) | 1194 | if (before(ack_seq, new_low_seq)) |
@@ -1890,6 +1894,7 @@ static void tcp_enter_frto_loss(struct sock *sk, int allowed_segments, int flag) | |||
1890 | if (!(TCP_SKB_CB(skb)->sacked & TCPCB_SACKED_ACKED)) { | 1894 | if (!(TCP_SKB_CB(skb)->sacked & TCPCB_SACKED_ACKED)) { |
1891 | TCP_SKB_CB(skb)->sacked |= TCPCB_LOST; | 1895 | TCP_SKB_CB(skb)->sacked |= TCPCB_LOST; |
1892 | tp->lost_out += tcp_skb_pcount(skb); | 1896 | tp->lost_out += tcp_skb_pcount(skb); |
1897 | tp->retransmit_high = TCP_SKB_CB(skb)->end_seq; | ||
1893 | } | 1898 | } |
1894 | } | 1899 | } |
1895 | tcp_verify_left_out(tp); | 1900 | tcp_verify_left_out(tp); |
@@ -1974,6 +1979,7 @@ void tcp_enter_loss(struct sock *sk, int how) | |||
1974 | TCP_SKB_CB(skb)->sacked &= ~TCPCB_SACKED_ACKED; | 1979 | TCP_SKB_CB(skb)->sacked &= ~TCPCB_SACKED_ACKED; |
1975 | TCP_SKB_CB(skb)->sacked |= TCPCB_LOST; | 1980 | TCP_SKB_CB(skb)->sacked |= TCPCB_LOST; |
1976 | tp->lost_out += tcp_skb_pcount(skb); | 1981 | tp->lost_out += tcp_skb_pcount(skb); |
1982 | tp->retransmit_high = TCP_SKB_CB(skb)->end_seq; | ||
1977 | } | 1983 | } |
1978 | } | 1984 | } |
1979 | tcp_verify_left_out(tp); | 1985 | tcp_verify_left_out(tp); |