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
#define RTAX_REORDERING RTAX_REORDERING
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
{
......
......@@ -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
* it is safe "de facto".
......
......@@ -598,25 +598,17 @@ void tcp_update_metrics(struct sock *sk)
}
}
/* Increase initial CWND conservatively: if estimated
* RTT is low enough (<20msec) or if we have some preset ssthresh.
*
* Numbers are taken from RFC2414.
*/
__u32 tcp_init_cwnd(struct tcp_opt *tp)
/* Numbers are taken from RFC2414. */
__u32 tcp_init_cwnd(struct tcp_opt *tp, struct dst_entry *dst)
{
__u32 cwnd;
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;
__u32 cwnd = dst_metric(dst, RTAX_INITCWND);
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);
}
......@@ -675,7 +667,7 @@ static void tcp_init_metrics(struct sock *sk)
tcp_bound_rto(tp);
if (tp->rto < TCP_TIMEOUT_INIT && !tp->saw_tstamp)
goto reset;
tp->snd_cwnd = tcp_init_cwnd(tp);
tp->snd_cwnd = tcp_init_cwnd(tp, dst);
tp->snd_cwnd_stamp = tcp_time_stamp;
return;
......
......@@ -99,10 +99,10 @@ static __u16 tcp_advertise_mss(struct sock *sk)
/* RFC2861. Reset CWND after idle period longer RTO to "restart window".
* 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;
u32 restart_cwnd = tcp_init_cwnd(tp);
u32 restart_cwnd = tcp_init_cwnd(tp, dst);
u32 cwnd = tp->snd_cwnd;
tp->snd_ssthresh = tcp_current_ssthresh(tp);
......@@ -115,12 +115,12 @@ static void tcp_cwnd_restart(struct tcp_opt *tp)
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;
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;
......@@ -272,7 +272,7 @@ int tcp_transmit_skb(struct sock *sk, struct sk_buff *skb)
tcp_event_ack_sent(sk);
if (skb->len != tcp_header_size)
tcp_event_data_sent(tp, skb);
tcp_event_data_sent(tp, skb, sk);
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