cachepc-linux

Fork of AMDESE/linux with modifications for CachePC side-channel attack
git clone https://git.sinitax.com/sinitax/cachepc-linux
Log | Files | Refs | README | LICENSE | sfeed.txt

tcp_bic.c (6190B)


      1// SPDX-License-Identifier: GPL-2.0-only
      2/*
      3 * Binary Increase Congestion control for TCP
      4 * Home page:
      5 *      http://netsrv.csc.ncsu.edu/twiki/bin/view/Main/BIC
      6 * This is from the implementation of BICTCP in
      7 * Lison-Xu, Kahaled Harfoush, and Injong Rhee.
      8 *  "Binary Increase Congestion Control for Fast, Long Distance
      9 *  Networks" in InfoComm 2004
     10 * Available from:
     11 *  http://netsrv.csc.ncsu.edu/export/bitcp.pdf
     12 *
     13 * Unless BIC is enabled and congestion window is large
     14 * this behaves the same as the original Reno.
     15 */
     16
     17#include <linux/mm.h>
     18#include <linux/module.h>
     19#include <net/tcp.h>
     20
     21#define BICTCP_BETA_SCALE    1024	/* Scale factor beta calculation
     22					 * max_cwnd = snd_cwnd * beta
     23					 */
     24#define BICTCP_B		4	 /*
     25					  * In binary search,
     26					  * go to point (max+min)/N
     27					  */
     28
     29static int fast_convergence = 1;
     30static int max_increment = 16;
     31static int low_window = 14;
     32static int beta = 819;		/* = 819/1024 (BICTCP_BETA_SCALE) */
     33static int initial_ssthresh;
     34static int smooth_part = 20;
     35
     36module_param(fast_convergence, int, 0644);
     37MODULE_PARM_DESC(fast_convergence, "turn on/off fast convergence");
     38module_param(max_increment, int, 0644);
     39MODULE_PARM_DESC(max_increment, "Limit on increment allowed during binary search");
     40module_param(low_window, int, 0644);
     41MODULE_PARM_DESC(low_window, "lower bound on congestion window (for TCP friendliness)");
     42module_param(beta, int, 0644);
     43MODULE_PARM_DESC(beta, "beta for multiplicative increase");
     44module_param(initial_ssthresh, int, 0644);
     45MODULE_PARM_DESC(initial_ssthresh, "initial value of slow start threshold");
     46module_param(smooth_part, int, 0644);
     47MODULE_PARM_DESC(smooth_part, "log(B/(B*Smin))/log(B/(B-1))+B, # of RTT from Wmax-B to Wmax");
     48
     49/* BIC TCP Parameters */
     50struct bictcp {
     51	u32	cnt;		/* increase cwnd by 1 after ACKs */
     52	u32	last_max_cwnd;	/* last maximum snd_cwnd */
     53	u32	last_cwnd;	/* the last snd_cwnd */
     54	u32	last_time;	/* time when updated last_cwnd */
     55	u32	epoch_start;	/* beginning of an epoch */
     56#define ACK_RATIO_SHIFT	4
     57	u32	delayed_ack;	/* estimate the ratio of Packets/ACKs << 4 */
     58};
     59
     60static inline void bictcp_reset(struct bictcp *ca)
     61{
     62	ca->cnt = 0;
     63	ca->last_max_cwnd = 0;
     64	ca->last_cwnd = 0;
     65	ca->last_time = 0;
     66	ca->epoch_start = 0;
     67	ca->delayed_ack = 2 << ACK_RATIO_SHIFT;
     68}
     69
     70static void bictcp_init(struct sock *sk)
     71{
     72	struct bictcp *ca = inet_csk_ca(sk);
     73
     74	bictcp_reset(ca);
     75
     76	if (initial_ssthresh)
     77		tcp_sk(sk)->snd_ssthresh = initial_ssthresh;
     78}
     79
     80/*
     81 * Compute congestion window to use.
     82 */
     83static inline void bictcp_update(struct bictcp *ca, u32 cwnd)
     84{
     85	if (ca->last_cwnd == cwnd &&
     86	    (s32)(tcp_jiffies32 - ca->last_time) <= HZ / 32)
     87		return;
     88
     89	ca->last_cwnd = cwnd;
     90	ca->last_time = tcp_jiffies32;
     91
     92	if (ca->epoch_start == 0) /* record the beginning of an epoch */
     93		ca->epoch_start = tcp_jiffies32;
     94
     95	/* start off normal */
     96	if (cwnd <= low_window) {
     97		ca->cnt = cwnd;
     98		return;
     99	}
    100
    101	/* binary increase */
    102	if (cwnd < ca->last_max_cwnd) {
    103		__u32	dist = (ca->last_max_cwnd - cwnd)
    104			/ BICTCP_B;
    105
    106		if (dist > max_increment)
    107			/* linear increase */
    108			ca->cnt = cwnd / max_increment;
    109		else if (dist <= 1U)
    110			/* binary search increase */
    111			ca->cnt = (cwnd * smooth_part) / BICTCP_B;
    112		else
    113			/* binary search increase */
    114			ca->cnt = cwnd / dist;
    115	} else {
    116		/* slow start AMD linear increase */
    117		if (cwnd < ca->last_max_cwnd + BICTCP_B)
    118			/* slow start */
    119			ca->cnt = (cwnd * smooth_part) / BICTCP_B;
    120		else if (cwnd < ca->last_max_cwnd + max_increment*(BICTCP_B-1))
    121			/* slow start */
    122			ca->cnt = (cwnd * (BICTCP_B-1))
    123				/ (cwnd - ca->last_max_cwnd);
    124		else
    125			/* linear increase */
    126			ca->cnt = cwnd / max_increment;
    127	}
    128
    129	/* if in slow start or link utilization is very low */
    130	if (ca->last_max_cwnd == 0) {
    131		if (ca->cnt > 20) /* increase cwnd 5% per RTT */
    132			ca->cnt = 20;
    133	}
    134
    135	ca->cnt = (ca->cnt << ACK_RATIO_SHIFT) / ca->delayed_ack;
    136	if (ca->cnt == 0)			/* cannot be zero */
    137		ca->cnt = 1;
    138}
    139
    140static void bictcp_cong_avoid(struct sock *sk, u32 ack, u32 acked)
    141{
    142	struct tcp_sock *tp = tcp_sk(sk);
    143	struct bictcp *ca = inet_csk_ca(sk);
    144
    145	if (!tcp_is_cwnd_limited(sk))
    146		return;
    147
    148	if (tcp_in_slow_start(tp)) {
    149		acked = tcp_slow_start(tp, acked);
    150		if (!acked)
    151			return;
    152	}
    153	bictcp_update(ca, tcp_snd_cwnd(tp));
    154	tcp_cong_avoid_ai(tp, ca->cnt, acked);
    155}
    156
    157/*
    158 *	behave like Reno until low_window is reached,
    159 *	then increase congestion window slowly
    160 */
    161static u32 bictcp_recalc_ssthresh(struct sock *sk)
    162{
    163	const struct tcp_sock *tp = tcp_sk(sk);
    164	struct bictcp *ca = inet_csk_ca(sk);
    165
    166	ca->epoch_start = 0;	/* end of epoch */
    167
    168	/* Wmax and fast convergence */
    169	if (tcp_snd_cwnd(tp) < ca->last_max_cwnd && fast_convergence)
    170		ca->last_max_cwnd = (tcp_snd_cwnd(tp) * (BICTCP_BETA_SCALE + beta))
    171			/ (2 * BICTCP_BETA_SCALE);
    172	else
    173		ca->last_max_cwnd = tcp_snd_cwnd(tp);
    174
    175	if (tcp_snd_cwnd(tp) <= low_window)
    176		return max(tcp_snd_cwnd(tp) >> 1U, 2U);
    177	else
    178		return max((tcp_snd_cwnd(tp) * beta) / BICTCP_BETA_SCALE, 2U);
    179}
    180
    181static void bictcp_state(struct sock *sk, u8 new_state)
    182{
    183	if (new_state == TCP_CA_Loss)
    184		bictcp_reset(inet_csk_ca(sk));
    185}
    186
    187/* Track delayed acknowledgment ratio using sliding window
    188 * ratio = (15*ratio + sample) / 16
    189 */
    190static void bictcp_acked(struct sock *sk, const struct ack_sample *sample)
    191{
    192	const struct inet_connection_sock *icsk = inet_csk(sk);
    193
    194	if (icsk->icsk_ca_state == TCP_CA_Open) {
    195		struct bictcp *ca = inet_csk_ca(sk);
    196
    197		ca->delayed_ack += sample->pkts_acked -
    198			(ca->delayed_ack >> ACK_RATIO_SHIFT);
    199	}
    200}
    201
    202static struct tcp_congestion_ops bictcp __read_mostly = {
    203	.init		= bictcp_init,
    204	.ssthresh	= bictcp_recalc_ssthresh,
    205	.cong_avoid	= bictcp_cong_avoid,
    206	.set_state	= bictcp_state,
    207	.undo_cwnd	= tcp_reno_undo_cwnd,
    208	.pkts_acked     = bictcp_acked,
    209	.owner		= THIS_MODULE,
    210	.name		= "bic",
    211};
    212
    213static int __init bictcp_register(void)
    214{
    215	BUILD_BUG_ON(sizeof(struct bictcp) > ICSK_CA_PRIV_SIZE);
    216	return tcp_register_congestion_control(&bictcp);
    217}
    218
    219static void __exit bictcp_unregister(void)
    220{
    221	tcp_unregister_congestion_control(&bictcp);
    222}
    223
    224module_init(bictcp_register);
    225module_exit(bictcp_unregister);
    226
    227MODULE_AUTHOR("Stephen Hemminger");
    228MODULE_LICENSE("GPL");
    229MODULE_DESCRIPTION("BIC TCP");