diff options
author | John Heffner <jheffner@psc.edu> | 2006-03-20 20:53:41 -0500 |
---|---|---|
committer | David S. Miller <davem@davemloft.net> | 2006-03-20 20:53:41 -0500 |
commit | 5d424d5a674f782d0659a3b66d951f412901faee (patch) | |
tree | 579871172044e02e626a90388d19ec55cf2d1fc4 /net/ipv4/tcp_input.c | |
parent | 1d60290f27e7dc4bce2c43922d0bfa9abd246fc9 (diff) |
[TCP]: MTU probing
Implementation of packetization layer path mtu discovery for TCP, based on
the internet-draft currently found at
<http://www.ietf.org/internet-drafts/draft-ietf-pmtud-method-05.txt>.
Signed-off-by: John Heffner <jheffner@psc.edu>
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 | 49 |
1 files changed, 49 insertions, 0 deletions
diff --git a/net/ipv4/tcp_input.c b/net/ipv4/tcp_input.c index e9a54ae7d690..0ac388e3d01d 100644 --- a/net/ipv4/tcp_input.c +++ b/net/ipv4/tcp_input.c | |||
@@ -1891,6 +1891,34 @@ static void tcp_try_to_open(struct sock *sk, struct tcp_sock *tp, int flag) | |||
1891 | } | 1891 | } |
1892 | } | 1892 | } |
1893 | 1893 | ||
1894 | static void tcp_mtup_probe_failed(struct sock *sk) | ||
1895 | { | ||
1896 | struct inet_connection_sock *icsk = inet_csk(sk); | ||
1897 | |||
1898 | icsk->icsk_mtup.search_high = icsk->icsk_mtup.probe_size - 1; | ||
1899 | icsk->icsk_mtup.probe_size = 0; | ||
1900 | } | ||
1901 | |||
1902 | static void tcp_mtup_probe_success(struct sock *sk, struct sk_buff *skb) | ||
1903 | { | ||
1904 | struct tcp_sock *tp = tcp_sk(sk); | ||
1905 | struct inet_connection_sock *icsk = inet_csk(sk); | ||
1906 | |||
1907 | /* FIXME: breaks with very large cwnd */ | ||
1908 | tp->prior_ssthresh = tcp_current_ssthresh(sk); | ||
1909 | tp->snd_cwnd = tp->snd_cwnd * | ||
1910 | tcp_mss_to_mtu(sk, tp->mss_cache) / | ||
1911 | icsk->icsk_mtup.probe_size; | ||
1912 | tp->snd_cwnd_cnt = 0; | ||
1913 | tp->snd_cwnd_stamp = tcp_time_stamp; | ||
1914 | tp->rcv_ssthresh = tcp_current_ssthresh(sk); | ||
1915 | |||
1916 | icsk->icsk_mtup.search_low = icsk->icsk_mtup.probe_size; | ||
1917 | icsk->icsk_mtup.probe_size = 0; | ||
1918 | tcp_sync_mss(sk, icsk->icsk_pmtu_cookie); | ||
1919 | } | ||
1920 | |||
1921 | |||
1894 | /* Process an event, which can update packets-in-flight not trivially. | 1922 | /* Process an event, which can update packets-in-flight not trivially. |
1895 | * Main goal of this function is to calculate new estimate for left_out, | 1923 | * Main goal of this function is to calculate new estimate for left_out, |
1896 | * taking into account both packets sitting in receiver's buffer and | 1924 | * taking into account both packets sitting in receiver's buffer and |
@@ -2023,6 +2051,17 @@ tcp_fastretrans_alert(struct sock *sk, u32 prior_snd_una, | |||
2023 | return; | 2051 | return; |
2024 | } | 2052 | } |
2025 | 2053 | ||
2054 | /* MTU probe failure: don't reduce cwnd */ | ||
2055 | if (icsk->icsk_ca_state < TCP_CA_CWR && | ||
2056 | icsk->icsk_mtup.probe_size && | ||
2057 | tp->snd_una == icsk->icsk_mtup.probe_seq_start) { | ||
2058 | tcp_mtup_probe_failed(sk); | ||
2059 | /* Restores the reduction we did in tcp_mtup_probe() */ | ||
2060 | tp->snd_cwnd++; | ||
2061 | tcp_simple_retransmit(sk); | ||
2062 | return; | ||
2063 | } | ||
2064 | |||
2026 | /* Otherwise enter Recovery state */ | 2065 | /* Otherwise enter Recovery state */ |
2027 | 2066 | ||
2028 | if (IsReno(tp)) | 2067 | if (IsReno(tp)) |
@@ -2243,6 +2282,13 @@ static int tcp_clean_rtx_queue(struct sock *sk, __s32 *seq_rtt_p) | |||
2243 | tp->retrans_stamp = 0; | 2282 | tp->retrans_stamp = 0; |
2244 | } | 2283 | } |
2245 | 2284 | ||
2285 | /* MTU probing checks */ | ||
2286 | if (icsk->icsk_mtup.probe_size) { | ||
2287 | if (!after(icsk->icsk_mtup.probe_seq_end, TCP_SKB_CB(skb)->end_seq)) { | ||
2288 | tcp_mtup_probe_success(sk, skb); | ||
2289 | } | ||
2290 | } | ||
2291 | |||
2246 | if (sacked) { | 2292 | if (sacked) { |
2247 | if (sacked & TCPCB_RETRANS) { | 2293 | if (sacked & TCPCB_RETRANS) { |
2248 | if(sacked & TCPCB_SACKED_RETRANS) | 2294 | if(sacked & TCPCB_SACKED_RETRANS) |
@@ -4101,6 +4147,7 @@ static int tcp_rcv_synsent_state_process(struct sock *sk, struct sk_buff *skb, | |||
4101 | if (tp->rx_opt.sack_ok && sysctl_tcp_fack) | 4147 | if (tp->rx_opt.sack_ok && sysctl_tcp_fack) |
4102 | tp->rx_opt.sack_ok |= 2; | 4148 | tp->rx_opt.sack_ok |= 2; |
4103 | 4149 | ||
4150 | tcp_mtup_init(sk); | ||
4104 | tcp_sync_mss(sk, icsk->icsk_pmtu_cookie); | 4151 | tcp_sync_mss(sk, icsk->icsk_pmtu_cookie); |
4105 | tcp_initialize_rcv_mss(sk); | 4152 | tcp_initialize_rcv_mss(sk); |
4106 | 4153 | ||
@@ -4211,6 +4258,7 @@ discard: | |||
4211 | if (tp->ecn_flags&TCP_ECN_OK) | 4258 | if (tp->ecn_flags&TCP_ECN_OK) |
4212 | sock_set_flag(sk, SOCK_NO_LARGESEND); | 4259 | sock_set_flag(sk, SOCK_NO_LARGESEND); |
4213 | 4260 | ||
4261 | tcp_mtup_init(sk); | ||
4214 | tcp_sync_mss(sk, icsk->icsk_pmtu_cookie); | 4262 | tcp_sync_mss(sk, icsk->icsk_pmtu_cookie); |
4215 | tcp_initialize_rcv_mss(sk); | 4263 | tcp_initialize_rcv_mss(sk); |
4216 | 4264 | ||
@@ -4399,6 +4447,7 @@ int tcp_rcv_state_process(struct sock *sk, struct sk_buff *skb, | |||
4399 | */ | 4447 | */ |
4400 | tp->lsndtime = tcp_time_stamp; | 4448 | tp->lsndtime = tcp_time_stamp; |
4401 | 4449 | ||
4450 | tcp_mtup_init(sk); | ||
4402 | tcp_initialize_rcv_mss(sk); | 4451 | tcp_initialize_rcv_mss(sk); |
4403 | tcp_init_buffer_space(sk); | 4452 | tcp_init_buffer_space(sk); |
4404 | tcp_fast_path_on(tp); | 4453 | tcp_fast_path_on(tp); |