Index: sys/netinet/tcp_congctl.c
===================================================================
RCS file: /cvsroot/src/sys/netinet/tcp_congctl.c,v
retrieving revision 1.29
diff -p -u -r1.29 tcp_congctl.c
--- sys/netinet/tcp_congctl.c	14 May 2024 19:00:44 -0000	1.29
+++ sys/netinet/tcp_congctl.c	11 Jul 2025 20:19:35 -0000
@@ -603,7 +603,7 @@ tcp_reno_newack(struct tcpcb *tp, const 
 
 		int acked = th->th_ack - tp->snd_una;
 
-		if (cw >= tp->snd_ssthresh) {
+		if (cw > tp->snd_ssthresh) {
 			tp->t_bytes_acked += acked;
 			if (tp->t_bytes_acked >= cw) {
 				/* Time to increase the window. */
@@ -624,6 +624,7 @@ tcp_reno_newack(struct tcpcb *tp, const 
 			abc_lim = (tcp_abc_aggressive == 0 ||
 			    tp->snd_nxt != tp->snd_max) ? incr : incr * 2;
 			incr = uimin(acked, abc_lim);
+			tp->t_bytes_acked = 0;
 		}
 	} else {
 
@@ -632,14 +633,17 @@ tcp_reno_newack(struct tcpcb *tp, const 
 		 * in flight, open exponentially (segsz per packet).
 		 * Otherwise open linearly: segsz per window
 		 * (segsz^2 / cwnd per packet).
-		 */
-
-		if (cw >= tp->snd_ssthresh) {
-			incr = incr * incr / cw;
+		 * If cwnd > maxseg^2, fix the cwnd increment at 1 byte
+		 * to avoid capping cwnd.
+                 */
+ 
+		if (cw > tp->snd_ssthresh) {
+			incr = uimax(incr * incr / cw, 1);
 		}
 	}
 
-	tp->snd_cwnd = uimin(cw + incr, TCP_MAXWIN << tp->snd_scale);
+	if (incr > 0)
+		tp->snd_cwnd = uimin(cw + incr, TCP_MAXWIN << tp->snd_scale);
 }
 
 const struct tcp_congctl tcp_reno_ctl = {
@@ -726,6 +730,8 @@ tcp_newreno_fast_retransmit_newack(struc
 			tp->snd_cwnd = sack_bytes_rxmt +
 			    (tp->snd_nxt - tp->sack_newdata) +
 			    sack_num_segs * tp->t_segsz;
+			// if (tp->snd_cwnd > tp->snd_ssthresh)
+			// 	tp->snd_cwnd = tp->snd_ssthresh;
 			tp->t_flags |= TF_ACKNOW;
 			(void) tcp_output(tp);
 		} else {
@@ -735,6 +741,7 @@ tcp_newreno_fast_retransmit_newack(struc
 			 * snd_una is not yet updated when we're called
 			 */
 			tp->snd_cwnd = tp->t_segsz + (th->th_ack - tp->snd_una);
+			tp->t_flags |= TF_ACKNOW;
 			(void) tcp_output(tp);
 			tp->snd_cwnd = ocwnd;
 			if (SEQ_GT(onxt, tp->snd_nxt))
@@ -755,17 +762,23 @@ tcp_newreno_fast_retransmit_newack(struc
 		 * snd_ssthresh outstanding data.  But in case we
 		 * would be inclined to send a burst, better to do
 		 * it via the slow start mechanism.
+		 *
+		 * RFC 6582 3.2
+		 * cwnd = min(sshtresh, max(flightsize, smss) + smss)
 		 */
-		if (SEQ_SUB(tp->snd_max, th->th_ack) < tp->snd_ssthresh)
-			tp->snd_cwnd = SEQ_SUB(tp->snd_max, th->th_ack)
-			    + tp->t_segsz;
-		else
-			tp->snd_cwnd = tp->snd_ssthresh;
+
+		long flight;
+		flight = uimax(SEQ_SUB(tp->snd_max, th->th_ack), tp->t_segsz);
+		tp->snd_cwnd = uimin(flight + tp->t_segsz, tp->snd_ssthresh);
+
 		tp->t_partialacks = -1;
 		tp->t_dupacks = 0;
 		tp->t_bytes_acked = 0;
 		if (TCP_SACK_ENABLED(tp) && SEQ_GT(th->th_ack, tp->snd_fack))
 			tp->snd_fack = th->th_ack;
+
+		if (SEQ_LEQ(th->th_ack, tp->snd_max))
+			tp->t_flags |= TF_ACKNOW;
 	}
 }
 
@@ -868,12 +881,15 @@ tcp_cubic_getW(struct tcpcb *tp, uint32_
 	long tK3;
 
 	/* Section 3.1 Eq. 2 */
-	K = tcp_cubic_cbrt(tp->snd_cubic_wmax / CUBIC_BETAB *
+	K = tcp_cubic_cbrt(tp->snd_cubic_wmax / (CUBIC_BETAB - CUBIC_BETAA) / CUBIC_BETAB *
 	    CUBIC_CB / CUBIC_CA);
 	/*  (t-K)^3 - not clear why is the measure unit mattering */
 	tK3 = (long)(ms_elapsed + rtt) - (long)K;
-	tK3 = tK3 * tK3 * tK3;
 
+	if (tK3 <= 0)
+		return tp->snd_cubic_wmax;
+
+	tK3 = tK3 * tK3 * tK3;
 	return CUBIC_CA * tK3 / CUBIC_CB + tp->snd_cubic_wmax;
 }
 
@@ -896,7 +912,7 @@ tcp_cubic_congestion_exp(struct tcpcb *t
 		tp->snd_cubic_wmax = tp->snd_cwnd;
 	}
 
-	tp->snd_cubic_wmax = uimax(tp->t_segsz, tp->snd_cubic_wmax);
+	tp->snd_cubic_wmax = ulmax(tp->t_segsz, tp->snd_cubic_wmax);
 
 	/* Shrink CWND */
 	tcp_common_congestion_exp(tp, CUBIC_BETAA, CUBIC_BETAB);
@@ -939,7 +955,7 @@ tcp_cubic_newack(struct tcpcb *tp, const
 
 		/* Compute W_tcp(t) */
 		w_tcp = tp->snd_cubic_wmax * CUBIC_BETAA / CUBIC_BETAB +
-		    ms_elapsed / rtt / 3;
+		    ms_elapsed / rtt / ((CUBIC_BETAB + CUBIC_BETAA)/(3*(CUBIC_BETAB - CUBIC_BETAA)));
 
 		if (tp->snd_cwnd > w_tcp) {
 			/* Not in TCP friendly mode */
@@ -951,8 +967,8 @@ tcp_cubic_newack(struct tcpcb *tp, const
 		}
 
 		/* Make sure we are within limits */
-		tp->snd_cwnd = uimax(tp->snd_cwnd, tp->t_segsz);
-		tp->snd_cwnd = uimin(tp->snd_cwnd, TCP_MAXWIN << tp->snd_scale);
+		tp->snd_cwnd = ulmax(tp->snd_cwnd, tp->t_segsz);
+		tp->snd_cwnd = ulmin(tp->snd_cwnd, TCP_MAXWIN << tp->snd_scale);
 	} else {
 		/* Use New Reno */
 		tcp_newreno_newack(tp, th);
Index: sys/netinet/tcp_input.c
===================================================================
RCS file: /cvsroot/src/sys/netinet/tcp_input.c,v
retrieving revision 1.441
diff -p -u -r1.441 tcp_input.c
--- sys/netinet/tcp_input.c	8 Oct 2024 06:17:14 -0000	1.441
+++ sys/netinet/tcp_input.c	11 Jul 2025 20:19:35 -0000
@@ -1486,7 +1486,7 @@ findpcb:
 
 	/* Unscale the window into a 32-bit value. */
 	if ((tiflags & TH_SYN) == 0)
-		tiwin = th->th_win << tp->snd_scale;
+		tiwin = (u_long)th->th_win << tp->snd_scale;
 	else
 		tiwin = th->th_win;
 
@@ -1911,7 +1911,7 @@ after_listen:
 		} else if (th->th_ack == tp->snd_una &&
 		    TAILQ_FIRST(&tp->segq) == NULL &&
 		    tlen <= sbspace(&so->so_rcv)) {
-			int newsize = 0;
+			u_long newsize = 0;
 
 			/*
 			 * this is a pure, in-sequence data packet
@@ -1978,8 +1978,8 @@ after_listen:
 					    (so->so_rcv.sb_hiwat / 8 * 7) &&
 					    so->so_rcv.sb_hiwat <
 					    tcp_autorcvbuf_max) {
-						newsize =
-						    uimin(so->so_rcv.sb_hiwat +
+						newsize = tcp_growbuf(
+						    so->so_rcv.sb_hiwat,
 						    tcp_autorcvbuf_inc,
 						    tcp_autorcvbuf_max);
 					}
Index: sys/netinet/tcp_output.c
===================================================================
RCS file: /cvsroot/src/sys/netinet/tcp_output.c,v
retrieving revision 1.222
diff -p -u -r1.222 tcp_output.c
--- sys/netinet/tcp_output.c	8 Sep 2024 09:36:52 -0000	1.222
+++ sys/netinet/tcp_output.c	11 Jul 2025 20:19:35 -0000
@@ -521,7 +521,9 @@ tcp_output(struct tcpcb *tp)
 	unsigned int sack_numblks;
 	int idle, sendalot, txsegsize, rxsegsize;
 	int txsegsize_nosack;
+#if 0
 	int maxburst = TCP_MAXBURST;
+#endif
 	int af;		/* address family on the wire */
 	int iphdrlen;
 	int has_tso4, has_tso6;
@@ -596,22 +598,27 @@ tcp_output(struct tcpcb *tp)
 	 *	larger value for the restart window should never increase
 	 *	the size of cwnd).
 	 */
-	if (tcp_cwm) {
+	if (idle && (tcp_now - tp->t_rcvtime) >= tp->t_rxtcur) {
 		/*
-		 * Hughes/Touch/Heidemann Congestion Window Monitoring.
-		 * Count the number of packets currently pending
-		 * acknowledgement, and limit our congestion window
-		 * to a pre-determined allowed burst size plus that count.
-		 * This prevents bursting once all pending packets have
-		 * been acknowledged (i.e. transmission is idle).
-		 *
-		 * XXX Link this to Initial Window?
+		 * RFC2861 Section 2, limit ssthresh to 3/4 of
+		 * the old cwnd to not exit slow-start prematurely.
 		 */
-		tp->snd_cwnd = uimin(tp->snd_cwnd,
-		    (tcp_cwm_burstsize * txsegsize) +
-		    (tp->snd_nxt - tp->snd_una));
-	} else {
-		if (idle && (tcp_now - tp->t_rcvtime) >= tp->t_rxtcur) {
+		tp->snd_ssthresh = ulmax(tp->snd_ssthresh,
+		    tp->snd_cwnd * 3 / 4);
+
+		if (tcp_cwm) {
+			/*
+			 * Hughes/Touch/Heidemann Congestion Window Monitoring.
+			 * Count the number of packets currently pending
+			 * acknowledgement, and limit our congestion window
+			 * to a pre-determined allowed burst size plus that count.
+			 * This prevents bursting once all pending packets have
+			 * been acknowledged (i.e. transmission is idle).
+			 */
+				tp->snd_cwnd = uimin(tp->snd_cwnd,
+				    (tcp_cwm_burstsize * txsegsize) +
+				    (tp->snd_nxt - tp->snd_una));
+		} else {
 			/*
 			 * We have been idle for "a while" and no acks are
 			 * expected to clock out any data we send --
@@ -770,7 +777,11 @@ again:
 	}
 
 	if (sack_rxmit == 0) {
+#if 0
 		if (TCP_SACK_ENABLED(tp) && tp->t_partialacks >= 0) {
+#else
+		if (sack_bytes_rxmt > 0) {
+#endif
 			long cwin;
 
 			/*
@@ -796,7 +807,7 @@ again:
 			 */
 			if (len > 0) {
 				cwin = tp->snd_cwnd -
-				    (tp->snd_nxt - tp->sack_newdata) -
+				    imax(0, (tp->snd_nxt - tp->sack_newdata)) -
 				    sack_bytes_rxmt;
 				if (cwin < 0)
 					cwin = 0;
@@ -879,9 +890,11 @@ again:
 		    so->so_snd.sb_cc >= (so->so_snd.sb_hiwat / 8 * 7) &&
 		    so->so_snd.sb_cc < tcp_autosndbuf_max &&
 		    win >= (so->so_snd.sb_cc - (tp->snd_nxt - tp->snd_una))) {
-			if (!sbreserve(&so->so_snd,
-			    uimin(so->so_snd.sb_hiwat + tcp_autosndbuf_inc,
-			     tcp_autosndbuf_max), so))
+			u_long newsize = tcp_growbuf(
+			    so->so_snd.sb_hiwat,
+			    tcp_autosndbuf_inc,
+			    tcp_autosndbuf_max);
+			if (!sbreserve(&so->so_snd, newsize, so))
 				so->so_snd.sb_flags &= ~SB_AUTOSIZE;
 		}
 	}
@@ -1648,12 +1661,17 @@ out:
 	tp->last_ack_sent = tp->rcv_nxt;
 	tp->t_flags &= ~TF_ACKNOW;
 	TCP_CLEAR_DELACK(tp);
+#if 0
 #ifdef DIAGNOSTIC
 	if (maxburst < 0)
 		printf("tcp_output: maxburst exceeded by %d\n", -maxburst);
 #endif
 	if (sendalot && (tp->t_congctl == &tcp_reno_ctl || --maxburst))
 		goto again;
+#else
+	if (sendalot)
+		goto again;
+#endif
 	return 0;
 }
 
Index: sys/netinet/tcp_subr.c
===================================================================
RCS file: /cvsroot/src/sys/netinet/tcp_subr.c,v
retrieving revision 1.298
diff -p -u -r1.298 tcp_subr.c
--- sys/netinet/tcp_subr.c	26 Feb 2025 04:49:45 -0000	1.298
+++ sys/netinet/tcp_subr.c	11 Jul 2025 20:19:35 -0000
@@ -862,6 +862,7 @@ tcp_respond(struct tcpcb *tp, struct mbu
 		break;
 #endif
 	default:
+		m_freem(m);
 		error = EAFNOSUPPORT;
 		break;
 	}
Index: sys/netinet/tcp_var.h
===================================================================
RCS file: /cvsroot/src/sys/netinet/tcp_var.h,v
retrieving revision 1.199
diff -p -u -r1.199 tcp_var.h
--- sys/netinet/tcp_var.h	3 Dec 2024 20:02:30 -0000	1.199
+++ sys/netinet/tcp_var.h	11 Jul 2025 20:19:36 -0000
@@ -785,6 +785,21 @@ extern int tcp_do_autosndbuf;
 extern int tcp_autosndbuf_inc;
 extern int tcp_autosndbuf_max;
 
+static __inline u_long
+tcp_growbuf(u_long current, int increment, int limit)
+{
+	if (increment < 0) {
+		uint64_t adj;
+
+		adj = (uint64_t)current * -increment / 65536;
+		current += adj;
+	} else {
+		current += increment;
+	}
+
+	return uimin(current, limit); 
+}
+
 struct secasvar;
 
 void	 tcp_canceltimers(struct tcpcb *);
