The newreno congestion control module's ABE (RFC 8511) implementation (off by default) includes the "frlossreduce" control (also off by default), which when enabled, adjusts ssthresh from being 80% of cwnd to being 50% of cwnd on account of a loss actually having transpired within the recovery episode i.e. we try 80% backoff but fallback to traditional 50% if a loss happens after the ECN signal but before we exit the congestion recovery episode.
The 100 in the denominator of the "frlossreduce" ssthresh adjustment computation is a bug, as the calculation is supposed to be a ratio adjustment, not a fixed point math operation. Plugging in some concrete numbers (pre congestion cwnd = 1448000, mss = 1448) to demonstrate the problem:
On receipt of ECN, ssthresh = [(1448000 * 80) / (100 * 1448) ] * 1448 = 800 * 1448 = 1158400 (i.e. 80% of 1448000) and we enter CONGRECOVERY
On receipt of NDUPACK, the cwin calculation is skipped in favour of the calculation inside the NDUPACK block which does: ssthresh = [(1158400 * 50) / (100 * 80) ] = 7240 (oops)
The latter should be: ssthresh = [(1158400 * 50) / 80 ] = 724000 (i.e. 50% of 1448000)
While we're at it, also put a lower bound of 2 MSS on the computed value and add guard checks for setting beta and beta_ecn range.
Thanks to @rrs for spotting the bug during some ad hoc code review.