Commit 5da50850 authored by David S. Miller's avatar David S. Miller

[TCP]: Sanitize initcwnd calculation, add new metrics.

1) Remove srtt etc. tests in tcp_init_cwnd, was buggy
   anyways.
2) Add RTAX_INITCWMD route metric, use this in tcp_init_cwnd()
   if non-zero.
3) Add RTAX_FEATURES (to enable/disable ECN/SACK/TIMESTAMPS
   on a per-route basis), currently unused.
parent 012af0b9
...@@ -284,9 +284,17 @@ enum ...@@ -284,9 +284,17 @@ enum
#define RTAX_REORDERING RTAX_REORDERING #define RTAX_REORDERING RTAX_REORDERING
RTAX_HOPLIMIT, RTAX_HOPLIMIT,
#define RTAX_HOPLIMIT RTAX_HOPLIMIT #define RTAX_HOPLIMIT RTAX_HOPLIMIT
RTAX_INITCWND,
#define RTAX_INITCWND RTAX_INITCWND
RTAX_FEATURES,
#define RTAX_FEATURES RTAX_FEATURES
}; };
#define RTAX_MAX RTAX_HOPLIMIT #define RTAX_MAX RTAX_FEATURES
#define RTAX_FEATURE_ECN 0x00000001
#define RTAX_FEATURE_SACK 0x00000002
#define RTAX_FEATURE_TIMESTAMP 0x00000004
struct rta_session struct rta_session
{ {
......
...@@ -1244,7 +1244,7 @@ static inline void tcp_enter_cwr(struct tcp_opt *tp) ...@@ -1244,7 +1244,7 @@ static inline void tcp_enter_cwr(struct tcp_opt *tp)
} }
} }
extern __u32 tcp_init_cwnd(struct tcp_opt *tp); extern __u32 tcp_init_cwnd(struct tcp_opt *tp, struct dst_entry *dst);
/* Slow start with delack produces 3 packets of burst, so that /* Slow start with delack produces 3 packets of burst, so that
* it is safe "de facto". * it is safe "de facto".
......
...@@ -598,25 +598,17 @@ void tcp_update_metrics(struct sock *sk) ...@@ -598,25 +598,17 @@ void tcp_update_metrics(struct sock *sk)
} }
} }
/* Increase initial CWND conservatively: if estimated /* Numbers are taken from RFC2414. */
* RTT is low enough (<20msec) or if we have some preset ssthresh. __u32 tcp_init_cwnd(struct tcp_opt *tp, struct dst_entry *dst)
*
* Numbers are taken from RFC2414.
*/
__u32 tcp_init_cwnd(struct tcp_opt *tp)
{ {
__u32 cwnd; __u32 cwnd = dst_metric(dst, RTAX_INITCWND);
if (tp->mss_cache > 1460)
return 2;
cwnd = (tp->mss_cache > 1095) ? 3 : 4;
if (!tp->srtt || (tp->snd_ssthresh >= 0xFFFF && tp->srtt > ((HZ/50)<<3)))
cwnd = 2;
else if (cwnd > tp->snd_ssthresh)
cwnd = tp->snd_ssthresh;
if (!cwnd) {
if (tp->mss_cache > 1460)
cwnd = 2;
else
cwnd = (tp->mss_cache > 1095) ? 3 : 4;
}
return min_t(__u32, cwnd, tp->snd_cwnd_clamp); return min_t(__u32, cwnd, tp->snd_cwnd_clamp);
} }
...@@ -675,7 +667,7 @@ static void tcp_init_metrics(struct sock *sk) ...@@ -675,7 +667,7 @@ static void tcp_init_metrics(struct sock *sk)
tcp_bound_rto(tp); tcp_bound_rto(tp);
if (tp->rto < TCP_TIMEOUT_INIT && !tp->saw_tstamp) if (tp->rto < TCP_TIMEOUT_INIT && !tp->saw_tstamp)
goto reset; goto reset;
tp->snd_cwnd = tcp_init_cwnd(tp); tp->snd_cwnd = tcp_init_cwnd(tp, dst);
tp->snd_cwnd_stamp = tcp_time_stamp; tp->snd_cwnd_stamp = tcp_time_stamp;
return; return;
......
...@@ -99,10 +99,10 @@ static __u16 tcp_advertise_mss(struct sock *sk) ...@@ -99,10 +99,10 @@ static __u16 tcp_advertise_mss(struct sock *sk)
/* RFC2861. Reset CWND after idle period longer RTO to "restart window". /* RFC2861. Reset CWND after idle period longer RTO to "restart window".
* This is the first part of cwnd validation mechanism. */ * This is the first part of cwnd validation mechanism. */
static void tcp_cwnd_restart(struct tcp_opt *tp) static void tcp_cwnd_restart(struct tcp_opt *tp, struct dst_entry *dst)
{ {
s32 delta = tcp_time_stamp - tp->lsndtime; s32 delta = tcp_time_stamp - tp->lsndtime;
u32 restart_cwnd = tcp_init_cwnd(tp); u32 restart_cwnd = tcp_init_cwnd(tp, dst);
u32 cwnd = tp->snd_cwnd; u32 cwnd = tp->snd_cwnd;
tp->snd_ssthresh = tcp_current_ssthresh(tp); tp->snd_ssthresh = tcp_current_ssthresh(tp);
...@@ -115,12 +115,12 @@ static void tcp_cwnd_restart(struct tcp_opt *tp) ...@@ -115,12 +115,12 @@ static void tcp_cwnd_restart(struct tcp_opt *tp)
tp->snd_cwnd_used = 0; tp->snd_cwnd_used = 0;
} }
static __inline__ void tcp_event_data_sent(struct tcp_opt *tp, struct sk_buff *skb) static __inline__ void tcp_event_data_sent(struct tcp_opt *tp, struct sk_buff *skb, struct sock *sk)
{ {
u32 now = tcp_time_stamp; u32 now = tcp_time_stamp;
if (!tp->packets_out && (s32)(now - tp->lsndtime) > tp->rto) if (!tp->packets_out && (s32)(now - tp->lsndtime) > tp->rto)
tcp_cwnd_restart(tp); tcp_cwnd_restart(tp, __sk_dst_get(sk));
tp->lsndtime = now; tp->lsndtime = now;
...@@ -272,7 +272,7 @@ int tcp_transmit_skb(struct sock *sk, struct sk_buff *skb) ...@@ -272,7 +272,7 @@ int tcp_transmit_skb(struct sock *sk, struct sk_buff *skb)
tcp_event_ack_sent(sk); tcp_event_ack_sent(sk);
if (skb->len != tcp_header_size) if (skb->len != tcp_header_size)
tcp_event_data_sent(tp, skb); tcp_event_data_sent(tp, skb, sk);
TCP_INC_STATS(TcpOutSegs); TCP_INC_STATS(TcpOutSegs);
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment