git: e5049a173352 - main - TCP rack does not work properly with cubic.

From: Randall Stewart <rrs_at_FreeBSD.org>
Date: Mon, 26 Sep 2022 19:13:51 UTC
The branch main has been updated by rrs:

URL: https://cgit.FreeBSD.org/src/commit/?id=e5049a17335248fa1c9219ddaa60bd25563f7f81

commit e5049a17335248fa1c9219ddaa60bd25563f7f81
Author:     Randall Stewart <rrs@FreeBSD.org>
AuthorDate: 2022-09-26 19:12:03 +0000
Commit:     Randall Stewart <rrs@FreeBSD.org>
CommitDate: 2022-09-26 19:12:03 +0000

    TCP rack does not work properly with cubic.
    
    Right now if you use rack with cubic (the new default cc) you will have
    improper results. This is because rack uses different variables than
    the base stack (or bbr) and thus tcp_compute_pipe() always returns
    so that cubic will choose a 30% backoff not the 50% backoff it should
    when it is newreno compatibility mode. The fix is to allow a stack (rack)
    to override its own compute_pipe.
    
    Reviewed by: tuexen, rscheff
    Sponsored by: Netflix Inc
    Differential Revision: https://reviews.freebsd.org/D36711
---
 sys/netinet/tcp_input.c       | 10 +++++++---
 sys/netinet/tcp_stacks/rack.c | 17 ++++++++++++++++-
 sys/netinet/tcp_var.h         |  1 +
 3 files changed, 24 insertions(+), 4 deletions(-)

diff --git a/sys/netinet/tcp_input.c b/sys/netinet/tcp_input.c
index ac2944a94e36..03941e2bb9a7 100644
--- a/sys/netinet/tcp_input.c
+++ b/sys/netinet/tcp_input.c
@@ -4060,9 +4060,13 @@ tcp_newreno_partial_ack(struct tcpcb *tp, struct tcphdr *th)
 int
 tcp_compute_pipe(struct tcpcb *tp)
 {
-	return (tp->snd_max - tp->snd_una +
-		tp->sackhint.sack_bytes_rexmit -
-		tp->sackhint.sacked_bytes);
+	if (tp->t_fb->tfb_compute_pipe == NULL) {
+		return (tp->snd_max - tp->snd_una +
+			tp->sackhint.sack_bytes_rexmit -
+			tp->sackhint.sacked_bytes);
+	} else {
+		return((*tp->t_fb->tfb_compute_pipe)(tp));
+	}
 }
 
 uint32_t
diff --git a/sys/netinet/tcp_stacks/rack.c b/sys/netinet/tcp_stacks/rack.c
index 6e323350100a..de88e47e5e41 100644
--- a/sys/netinet/tcp_stacks/rack.c
+++ b/sys/netinet/tcp_stacks/rack.c
@@ -9397,6 +9397,20 @@ skip_dsack_round:
 	return (was_tlp);
 }
 
+static uint32_t
+do_rack_compute_pipe(struct tcpcb *tp, struct tcp_rack *rack, uint32_t snd_una)
+{
+	return (((tp->snd_max - snd_una) - rack->r_ctl.rc_sacked) + rack->r_ctl.rc_holes_rxt);
+}
+
+static int32_t
+rack_compute_pipe(struct tcpcb *tp)
+{
+	return ((int32_t)do_rack_compute_pipe(tp,
+					      (struct tcp_rack *)tp->t_fb_ptr,
+					      tp->snd_una));
+}
+
 static void
 rack_update_prr(struct tcpcb *tp, struct tcp_rack *rack, uint32_t changed, tcp_seq th_ack)
 {
@@ -9421,7 +9435,7 @@ rack_update_prr(struct tcpcb *tp, struct tcp_rack *rack, uint32_t changed, tcp_s
 	} else {
 		snd_una = th_ack;
 	}
-	pipe = ((tp->snd_max - snd_una) - rack->r_ctl.rc_sacked) + rack->r_ctl.rc_holes_rxt;
+	pipe = do_rack_compute_pipe(tp, rack, snd_una);
 	if (pipe > tp->snd_ssthresh) {
 		long sndcnt;
 
@@ -20317,6 +20331,7 @@ static struct tcp_function_block __tcp_rack = {
 	.tfb_tcp_mtu_chg = rack_mtu_change,
 	.tfb_pru_options = rack_pru_options,
 	.tfb_hwtls_change = rack_hw_tls_change,
+	.tfb_compute_pipe = rack_compute_pipe,
 	.tfb_flags = TCP_FUNC_OUTPUT_CANDROP,
 };
 
diff --git a/sys/netinet/tcp_var.h b/sys/netinet/tcp_var.h
index 1b7e25099ced..b3284d338b83 100644
--- a/sys/netinet/tcp_var.h
+++ b/sys/netinet/tcp_var.h
@@ -375,6 +375,7 @@ struct tcp_function_block {
 	void	(*tfb_tcp_mtu_chg)(struct tcpcb *);
 	int	(*tfb_pru_options)(struct tcpcb *, int);
 	void	(*tfb_hwtls_change)(struct tcpcb *, int);
+	int     (*tfb_compute_pipe)(struct tcpcb *tp);
 	volatile uint32_t tfb_refcnt;
 	uint32_t  tfb_flags;
 	uint8_t	tfb_id;