|
@@ -68,8 +68,9 @@ int tcp_register_congestion_control(struct tcp_congestion_ops *ca)
|
|
|
{
|
|
|
int ret = 0;
|
|
|
|
|
|
- /* all algorithms must implement ssthresh and cong_avoid ops */
|
|
|
- if (!ca->ssthresh || !(ca->cong_avoid || ca->cong_control)) {
|
|
|
+ /* all algorithms must implement these */
|
|
|
+ if (!ca->ssthresh || !ca->undo_cwnd ||
|
|
|
+ !(ca->cong_avoid || ca->cong_control)) {
|
|
|
pr_err("%s does not implement required ops\n", ca->name);
|
|
|
return -EINVAL;
|
|
|
}
|
|
@@ -441,10 +442,19 @@ u32 tcp_reno_ssthresh(struct sock *sk)
|
|
|
}
|
|
|
EXPORT_SYMBOL_GPL(tcp_reno_ssthresh);
|
|
|
|
|
|
+u32 tcp_reno_undo_cwnd(struct sock *sk)
|
|
|
+{
|
|
|
+ const struct tcp_sock *tp = tcp_sk(sk);
|
|
|
+
|
|
|
+ return max(tp->snd_cwnd, tp->snd_ssthresh << 1);
|
|
|
+}
|
|
|
+EXPORT_SYMBOL_GPL(tcp_reno_undo_cwnd);
|
|
|
+
|
|
|
struct tcp_congestion_ops tcp_reno = {
|
|
|
.flags = TCP_CONG_NON_RESTRICTED,
|
|
|
.name = "reno",
|
|
|
.owner = THIS_MODULE,
|
|
|
.ssthresh = tcp_reno_ssthresh,
|
|
|
.cong_avoid = tcp_reno_cong_avoid,
|
|
|
+ .undo_cwnd = tcp_reno_undo_cwnd,
|
|
|
};
|