Orange Pi5 kernel

Deprecated Linux kernel 5.10.110 for OrangePi 5/5B/5+ boards

3 Commits   0 Branches   0 Tags
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   1) // SPDX-License-Identifier: GPL-2.0-only
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   2) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   3)  * TCP Low Priority (TCP-LP)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   4)  *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   5)  * TCP Low Priority is a distributed algorithm whose goal is to utilize only
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   6)  *   the excess network bandwidth as compared to the ``fair share`` of
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   7)  *   bandwidth as targeted by TCP.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   8)  *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   9)  * As of 2.6.13, Linux supports pluggable congestion control algorithms.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  10)  * Due to the limitation of the API, we take the following changes from
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  11)  * the original TCP-LP implementation:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  12)  *   o We use newReno in most core CA handling. Only add some checking
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  13)  *     within cong_avoid.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  14)  *   o Error correcting in remote HZ, therefore remote HZ will be keeped
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  15)  *     on checking and updating.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  16)  *   o Handling calculation of One-Way-Delay (OWD) within rtt_sample, since
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  17)  *     OWD have a similar meaning as RTT. Also correct the buggy formular.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  18)  *   o Handle reaction for Early Congestion Indication (ECI) within
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  19)  *     pkts_acked, as mentioned within pseudo code.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  20)  *   o OWD is handled in relative format, where local time stamp will in
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  21)  *     tcp_time_stamp format.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  22)  *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  23)  * Original Author:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  24)  *   Aleksandar Kuzmanovic <akuzma@northwestern.edu>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  25)  * Available from:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  26)  *   http://www.ece.rice.edu/~akuzma/Doc/akuzma/TCP-LP.pdf
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  27)  * Original implementation for 2.4.19:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  28)  *   http://www-ece.rice.edu/networks/TCP-LP/
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  29)  *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  30)  * 2.6.x module Authors:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  31)  *   Wong Hoi Sing, Edison <hswong3i@gmail.com>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  32)  *   Hung Hing Lun, Mike <hlhung3i@gmail.com>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  33)  * SourceForge project page:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  34)  *   http://tcp-lp-mod.sourceforge.net/
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  35)  */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  36) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  37) #include <linux/module.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  38) #include <net/tcp.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  39) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  40) /* resolution of owd */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  41) #define LP_RESOL       TCP_TS_HZ
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  42) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  43) /**
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  44)  * enum tcp_lp_state
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  45)  * @LP_VALID_RHZ: is remote HZ valid?
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  46)  * @LP_VALID_OWD: is OWD valid?
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  47)  * @LP_WITHIN_THR: are we within threshold?
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  48)  * @LP_WITHIN_INF: are we within inference?
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  49)  *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  50)  * TCP-LP's state flags.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  51)  * We create this set of state flag mainly for debugging.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  52)  */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  53) enum tcp_lp_state {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  54) 	LP_VALID_RHZ = (1 << 0),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  55) 	LP_VALID_OWD = (1 << 1),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  56) 	LP_WITHIN_THR = (1 << 3),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  57) 	LP_WITHIN_INF = (1 << 4),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  58) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  59) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  60) /**
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  61)  * struct lp
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  62)  * @flag: TCP-LP state flag
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  63)  * @sowd: smoothed OWD << 3
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  64)  * @owd_min: min OWD
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  65)  * @owd_max: max OWD
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  66)  * @owd_max_rsv: resrved max owd
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  67)  * @remote_hz: estimated remote HZ
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  68)  * @remote_ref_time: remote reference time
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  69)  * @local_ref_time: local reference time
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  70)  * @last_drop: time for last active drop
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  71)  * @inference: current inference
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  72)  *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  73)  * TCP-LP's private struct.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  74)  * We get the idea from original TCP-LP implementation where only left those we
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  75)  * found are really useful.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  76)  */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  77) struct lp {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  78) 	u32 flag;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  79) 	u32 sowd;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  80) 	u32 owd_min;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  81) 	u32 owd_max;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  82) 	u32 owd_max_rsv;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  83) 	u32 remote_hz;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  84) 	u32 remote_ref_time;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  85) 	u32 local_ref_time;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  86) 	u32 last_drop;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  87) 	u32 inference;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  88) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  89) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  90) /**
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  91)  * tcp_lp_init
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  92)  *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  93)  * Init all required variables.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  94)  * Clone the handling from Vegas module implementation.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  95)  */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  96) static void tcp_lp_init(struct sock *sk)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  97) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  98) 	struct lp *lp = inet_csk_ca(sk);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  99) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 100) 	lp->flag = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 101) 	lp->sowd = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 102) 	lp->owd_min = 0xffffffff;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 103) 	lp->owd_max = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 104) 	lp->owd_max_rsv = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 105) 	lp->remote_hz = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 106) 	lp->remote_ref_time = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 107) 	lp->local_ref_time = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 108) 	lp->last_drop = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 109) 	lp->inference = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 110) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 111) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 112) /**
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 113)  * tcp_lp_cong_avoid
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 114)  *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 115)  * Implementation of cong_avoid.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 116)  * Will only call newReno CA when away from inference.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 117)  * From TCP-LP's paper, this will be handled in additive increasement.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 118)  */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 119) static void tcp_lp_cong_avoid(struct sock *sk, u32 ack, u32 acked)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 120) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 121) 	struct lp *lp = inet_csk_ca(sk);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 122) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 123) 	if (!(lp->flag & LP_WITHIN_INF))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 124) 		tcp_reno_cong_avoid(sk, ack, acked);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 125) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 126) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 127) /**
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 128)  * tcp_lp_remote_hz_estimator
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 129)  *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 130)  * Estimate remote HZ.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 131)  * We keep on updating the estimated value, where original TCP-LP
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 132)  * implementation only guest it for once and use forever.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 133)  */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 134) static u32 tcp_lp_remote_hz_estimator(struct sock *sk)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 135) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 136) 	struct tcp_sock *tp = tcp_sk(sk);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 137) 	struct lp *lp = inet_csk_ca(sk);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 138) 	s64 rhz = lp->remote_hz << 6;	/* remote HZ << 6 */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 139) 	s64 m = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 140) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 141) 	/* not yet record reference time
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 142) 	 * go away!! record it before come back!! */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 143) 	if (lp->remote_ref_time == 0 || lp->local_ref_time == 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 144) 		goto out;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 145) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 146) 	/* we can't calc remote HZ with no different!! */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 147) 	if (tp->rx_opt.rcv_tsval == lp->remote_ref_time ||
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 148) 	    tp->rx_opt.rcv_tsecr == lp->local_ref_time)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 149) 		goto out;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 150) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 151) 	m = TCP_TS_HZ *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 152) 	    (tp->rx_opt.rcv_tsval - lp->remote_ref_time) /
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 153) 	    (tp->rx_opt.rcv_tsecr - lp->local_ref_time);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 154) 	if (m < 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 155) 		m = -m;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 156) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 157) 	if (rhz > 0) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 158) 		m -= rhz >> 6;	/* m is now error in remote HZ est */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 159) 		rhz += m;	/* 63/64 old + 1/64 new */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 160) 	} else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 161) 		rhz = m << 6;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 162) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 163)  out:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 164) 	/* record time for successful remote HZ calc */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 165) 	if ((rhz >> 6) > 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 166) 		lp->flag |= LP_VALID_RHZ;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 167) 	else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 168) 		lp->flag &= ~LP_VALID_RHZ;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 169) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 170) 	/* record reference time stamp */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 171) 	lp->remote_ref_time = tp->rx_opt.rcv_tsval;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 172) 	lp->local_ref_time = tp->rx_opt.rcv_tsecr;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 173) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 174) 	return rhz >> 6;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 175) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 176) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 177) /**
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 178)  * tcp_lp_owd_calculator
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 179)  *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 180)  * Calculate one way delay (in relative format).
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 181)  * Original implement OWD as minus of remote time difference to local time
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 182)  * difference directly. As this time difference just simply equal to RTT, when
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 183)  * the network status is stable, remote RTT will equal to local RTT, and result
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 184)  * OWD into zero.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 185)  * It seems to be a bug and so we fixed it.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 186)  */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 187) static u32 tcp_lp_owd_calculator(struct sock *sk)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 188) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 189) 	struct tcp_sock *tp = tcp_sk(sk);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 190) 	struct lp *lp = inet_csk_ca(sk);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 191) 	s64 owd = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 192) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 193) 	lp->remote_hz = tcp_lp_remote_hz_estimator(sk);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 194) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 195) 	if (lp->flag & LP_VALID_RHZ) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 196) 		owd =
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 197) 		    tp->rx_opt.rcv_tsval * (LP_RESOL / lp->remote_hz) -
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 198) 		    tp->rx_opt.rcv_tsecr * (LP_RESOL / TCP_TS_HZ);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 199) 		if (owd < 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 200) 			owd = -owd;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 201) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 202) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 203) 	if (owd > 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 204) 		lp->flag |= LP_VALID_OWD;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 205) 	else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 206) 		lp->flag &= ~LP_VALID_OWD;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 207) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 208) 	return owd;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 209) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 210) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 211) /**
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 212)  * tcp_lp_rtt_sample
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 213)  *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 214)  * Implementation or rtt_sample.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 215)  * Will take the following action,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 216)  *   1. calc OWD,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 217)  *   2. record the min/max OWD,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 218)  *   3. calc smoothed OWD (SOWD).
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 219)  * Most ideas come from the original TCP-LP implementation.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 220)  */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 221) static void tcp_lp_rtt_sample(struct sock *sk, u32 rtt)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 222) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 223) 	struct lp *lp = inet_csk_ca(sk);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 224) 	s64 mowd = tcp_lp_owd_calculator(sk);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 225) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 226) 	/* sorry that we don't have valid data */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 227) 	if (!(lp->flag & LP_VALID_RHZ) || !(lp->flag & LP_VALID_OWD))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 228) 		return;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 229) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 230) 	/* record the next min owd */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 231) 	if (mowd < lp->owd_min)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 232) 		lp->owd_min = mowd;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 233) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 234) 	/* always forget the max of the max
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 235) 	 * we just set owd_max as one below it */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 236) 	if (mowd > lp->owd_max) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 237) 		if (mowd > lp->owd_max_rsv) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 238) 			if (lp->owd_max_rsv == 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 239) 				lp->owd_max = mowd;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 240) 			else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 241) 				lp->owd_max = lp->owd_max_rsv;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 242) 			lp->owd_max_rsv = mowd;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 243) 		} else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 244) 			lp->owd_max = mowd;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 245) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 246) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 247) 	/* calc for smoothed owd */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 248) 	if (lp->sowd != 0) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 249) 		mowd -= lp->sowd >> 3;	/* m is now error in owd est */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 250) 		lp->sowd += mowd;	/* owd = 7/8 owd + 1/8 new */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 251) 	} else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 252) 		lp->sowd = mowd << 3;	/* take the measured time be owd */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 253) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 254) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 255) /**
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 256)  * tcp_lp_pkts_acked
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 257)  *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 258)  * Implementation of pkts_acked.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 259)  * Deal with active drop under Early Congestion Indication.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 260)  * Only drop to half and 1 will be handle, because we hope to use back
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 261)  * newReno in increase case.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 262)  * We work it out by following the idea from TCP-LP's paper directly
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 263)  */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 264) static void tcp_lp_pkts_acked(struct sock *sk, const struct ack_sample *sample)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 265) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 266) 	struct tcp_sock *tp = tcp_sk(sk);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 267) 	struct lp *lp = inet_csk_ca(sk);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 268) 	u32 now = tcp_time_stamp(tp);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 269) 	u32 delta;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 270) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 271) 	if (sample->rtt_us > 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 272) 		tcp_lp_rtt_sample(sk, sample->rtt_us);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 273) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 274) 	/* calc inference */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 275) 	delta = now - tp->rx_opt.rcv_tsecr;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 276) 	if ((s32)delta > 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 277) 		lp->inference = 3 * delta;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 278) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 279) 	/* test if within inference */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 280) 	if (lp->last_drop && (now - lp->last_drop < lp->inference))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 281) 		lp->flag |= LP_WITHIN_INF;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 282) 	else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 283) 		lp->flag &= ~LP_WITHIN_INF;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 284) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 285) 	/* test if within threshold */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 286) 	if (lp->sowd >> 3 <
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 287) 	    lp->owd_min + 15 * (lp->owd_max - lp->owd_min) / 100)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 288) 		lp->flag |= LP_WITHIN_THR;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 289) 	else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 290) 		lp->flag &= ~LP_WITHIN_THR;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 291) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 292) 	pr_debug("TCP-LP: %05o|%5u|%5u|%15u|%15u|%15u\n", lp->flag,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 293) 		 tp->snd_cwnd, lp->remote_hz, lp->owd_min, lp->owd_max,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 294) 		 lp->sowd >> 3);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 295) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 296) 	if (lp->flag & LP_WITHIN_THR)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 297) 		return;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 298) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 299) 	/* FIXME: try to reset owd_min and owd_max here
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 300) 	 * so decrease the chance the min/max is no longer suitable
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 301) 	 * and will usually within threshold when whithin inference */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 302) 	lp->owd_min = lp->sowd >> 3;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 303) 	lp->owd_max = lp->sowd >> 2;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 304) 	lp->owd_max_rsv = lp->sowd >> 2;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 305) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 306) 	/* happened within inference
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 307) 	 * drop snd_cwnd into 1 */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 308) 	if (lp->flag & LP_WITHIN_INF)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 309) 		tp->snd_cwnd = 1U;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 310) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 311) 	/* happened after inference
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 312) 	 * cut snd_cwnd into half */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 313) 	else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 314) 		tp->snd_cwnd = max(tp->snd_cwnd >> 1U, 1U);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 315) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 316) 	/* record this drop time */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 317) 	lp->last_drop = now;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 318) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 319) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 320) static struct tcp_congestion_ops tcp_lp __read_mostly = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 321) 	.init = tcp_lp_init,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 322) 	.ssthresh = tcp_reno_ssthresh,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 323) 	.undo_cwnd = tcp_reno_undo_cwnd,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 324) 	.cong_avoid = tcp_lp_cong_avoid,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 325) 	.pkts_acked = tcp_lp_pkts_acked,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 326) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 327) 	.owner = THIS_MODULE,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 328) 	.name = "lp"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 329) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 330) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 331) static int __init tcp_lp_register(void)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 332) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 333) 	BUILD_BUG_ON(sizeof(struct lp) > ICSK_CA_PRIV_SIZE);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 334) 	return tcp_register_congestion_control(&tcp_lp);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 335) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 336) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 337) static void __exit tcp_lp_unregister(void)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 338) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 339) 	tcp_unregister_congestion_control(&tcp_lp);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 340) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 341) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 342) module_init(tcp_lp_register);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 343) module_exit(tcp_lp_unregister);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 344) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 345) MODULE_AUTHOR("Wong Hoi Sing Edison, Hung Hing Lun Mike");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 346) MODULE_LICENSE("GPL");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 347) MODULE_DESCRIPTION("TCP Low Priority");