Commit 4d4d3d1e authored by Stephen Hemminger's avatar Stephen Hemminger Committed by David S. Miller

[TCP]: Congestion control initialization.

Change to defer congestion control initialization.

If setsockopt() was used to change TCP_CONGESTION before
connection is established, then protocols that use sequence numbers
to keep track of one RTT interval (vegas, illinois, ...) get confused.

Change the init hook to be called after handshake.
Signed-off-by: default avatarStephen Hemminger <shemminger@linux-foundation.org>
Signed-off-by: default avatarDavid S. Miller <davem@davemloft.net>
parent c445a31c
...@@ -77,9 +77,8 @@ void tcp_init_congestion_control(struct sock *sk) ...@@ -77,9 +77,8 @@ void tcp_init_congestion_control(struct sock *sk)
struct inet_connection_sock *icsk = inet_csk(sk); struct inet_connection_sock *icsk = inet_csk(sk);
struct tcp_congestion_ops *ca; struct tcp_congestion_ops *ca;
if (icsk->icsk_ca_ops != &tcp_init_congestion_ops) /* if no choice made yet assign the current value set as default */
return; if (icsk->icsk_ca_ops == &tcp_init_congestion_ops) {
rcu_read_lock(); rcu_read_lock();
list_for_each_entry_rcu(ca, &tcp_cong_list, list) { list_for_each_entry_rcu(ca, &tcp_cong_list, list) {
if (try_module_get(ca->owner)) { if (try_module_get(ca->owner)) {
...@@ -87,8 +86,10 @@ void tcp_init_congestion_control(struct sock *sk) ...@@ -87,8 +86,10 @@ void tcp_init_congestion_control(struct sock *sk)
break; break;
} }
/* fallback to next available */
} }
rcu_read_unlock(); rcu_read_unlock();
}
if (icsk->icsk_ca_ops->init) if (icsk->icsk_ca_ops->init)
icsk->icsk_ca_ops->init(sk); icsk->icsk_ca_ops->init(sk);
...@@ -236,6 +237,7 @@ int tcp_set_congestion_control(struct sock *sk, const char *name) ...@@ -236,6 +237,7 @@ int tcp_set_congestion_control(struct sock *sk, const char *name)
rcu_read_lock(); rcu_read_lock();
ca = tcp_ca_find(name); ca = tcp_ca_find(name);
/* no change asking for existing value */ /* no change asking for existing value */
if (ca == icsk->icsk_ca_ops) if (ca == icsk->icsk_ca_ops)
goto out; goto out;
...@@ -261,7 +263,8 @@ int tcp_set_congestion_control(struct sock *sk, const char *name) ...@@ -261,7 +263,8 @@ int tcp_set_congestion_control(struct sock *sk, const char *name)
else { else {
tcp_cleanup_congestion_control(sk); tcp_cleanup_congestion_control(sk);
icsk->icsk_ca_ops = ca; icsk->icsk_ca_ops = ca;
if (icsk->icsk_ca_ops->init)
if (sk->sk_state != TCP_CLOSE && icsk->icsk_ca_ops->init)
icsk->icsk_ca_ops->init(sk); icsk->icsk_ca_ops->init(sk);
} }
out: out:
......
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