For Debian 8/Ubuntu 16 ONLY.
Linux-headers is required to get compilation done.
This module is supported in kernel version after 4.9 .
(Latest version – 2.2.1)
- export MOD=react_rc2
- apt-get install make gcc-4.9 -y
-
wget -O ./tcp_$MOD.c
https://gist.github.com/anonymous/27b7ea6e93acdd23b097ab1a399c1287/raw/00c318f613856ed400c556126b851d18369e936b/tcp_react_rc2.c - echo “obj-m:=tcp_$MOD.o” > Makefile
- make -C /lib/modules/$(uname -r)/build M=`pwd` modules CC=”/usr/bin/gcc-4.9 -Ofast” &&
- insmod tcp_$MOD.ko &&
- sysctl -w net.ipv4.tcp_congestion_control=$MOD
复制代码
(Other optimization – Recommended)
-
wget -qO-
https://gist.github.com/anonymous/63ada7904c29d685575716c2f5302f06/raw/93eb01e62f3a4f22390b2200ddb709987f9ed201/sysctl.conf|sysctl
-p – - ulimit -SHn 10240000
- echo “$(cat /etc/security/limits.conf | grep -v -E ‘(soft|hard).*nofile’)” > /etc/security/limits.conf
-
echo -e “* soft nofile 10240000\n*
hard nofile 10240000” >>
/etc/security/limits.conf - # setting fair queue
- export PATH_EXEC=/etc/init.d/tc-fq.sh
- cat>$PATH_EXEC<<‘EOF’
- sysctl net.core.default_qdisc=noqueue &&
- tc qdisc del dev eth0 root fq
- tc qdisc del dev eth0 root pfifo_fast
- tc qdisc del dev eth0 root red limit 42949672 avpkt 1000
- tc qdisc add dev eth0 root red limit 42949672 avpkt 1440 probability 0.01 bandwidth 1000Mbit min 187605 max 862816
- sysctl -w net.core.default_qdisc=red
- EOF
- chmod +x $PATH_EXEC
- $PATH_EXEC
- tc -s -d qdisc show
- echo “$(cat /etc/rc.local | grep -v -E ‘(‘$PATH_EXEC’)|(exit 0)’)” > /etc/rc.local
- echo -e “\n$PATH_EXEC\nexit 0” >> /etc/rc.local
/* React congestion control */ #include <linux/module.h> #include <net/tcp.h> #include <linux/win_minmax.h> #define BW_SCALE 24 #define REACT_SCALE 8 #define REACT_UNIT (1 << REACT_SCALE) #define REACT_INIT_CWND 25 #define DO_CONDITIONAL_OPT(a, b, c) ((c) ^ ((!(a) - 1) & ((b) ^ (c)))) #define REACT_MIN(a, b) DO_CONDITIONAL_OPT((a) < (b), a, b) #define REACT_MAX(a, b) DO_CONDITIONAL_OPT((a) > (b), a, b) #define REACT_MAX3(a, b, c) REACT_MAX(REACT_MAX(a, b), c) #define REACT_SGN32(x) -(-((x) >> 31) | (-(x) >> 31)) /* window length of min_rtt filter (in sec): */ static const u32 react_min_rtt_win_sec = 10; static const int react_high_gain = REACT_UNIT * 2885 / 1000 + 1; static const int react_drain_gain = REACT_UNIT * 3 / 4; static const int react_cwnd_gain = REACT_UNIT * 2; static const int react_probe_gain = REACT_UNIT * 3 / 2; static const u8 react_full_bw_cnt = 3; /* sampling windows size react_grad used for smoothing moving: */ static unsigned int window __read_mostly = 4; /* Window length of bw filter (in rounds): */ static unsigned int react_bw_rtts __read_mostly = 15; module_param(window, int, 0444); MODULE_PARM_DESC(window, "gradient window size (power of two <= 256)"); module_param(react_bw_rtts, uint, 0644); MODULE_PARM_DESC(react_bw_rtts, "window length of bw filter (in rounds)"); struct cdg_minmax { union { struct { s32 min; s32 max; }; u64 v64; }; }; enum react_state { CDG_UNKNOWN = 0, CDG_NONFULL = 1, CDG_FULL = 2 }; /* React congestion control block */ struct react { struct cdg_minmax rtt; struct cdg_minmax rtt_prev; struct cdg_minmax *gradients; struct cdg_minmax gsum; struct minmax bw; /* Max recent delivery rate in pkts/uS << 24 */ u32 cwnd_gain, pacing_gain, min_rtt_us, /* min RTT in min_rtt_win_sec window */ rtt_seq, min_rtt_stamp, /* timestamp of min_rtt_us */ next_rtt_delivered; /* scb->tx.delivered at end of round */ u16 rtt_cnt; /* count of packet-timed rounds elapsed */ u8 tail, state, full_bw_cnt; bool drain_queue, round_restart, packet_conservation; }; static inline u32 react_max_bw(struct react *ca) { return minmax_get(&ca->bw); } static inline u64 react_rate_bytes_per_sec(struct sock *sk, u64 rate, int gain) { rate *= tcp_mss_to_mtu(sk, tcp_sk(sk)->mss_cache); rate *= gain; rate >>= REACT_SCALE; rate *= USEC_PER_SEC; return rate >> BW_SCALE; } static inline void react_set_pacing_rate(struct sock *sk, u64 bw, int gain) { u64 rate = bw; rate = react_rate_bytes_per_sec(sk, rate, gain); rate = REACT_MIN(rate, sk->sk_max_pacing_rate); sk->sk_pacing_rate = REACT_MAX(rate, sk->sk_pacing_rate); } /* Find target cwnd. Right-size the cwnd based on min RTT and the * estimated bottleneck bandwidth: * * cwnd = bw * min_rtt * gain = BDP * gain * * The key factor, gain, controls the amount of queue. While a small gain * builds a smaller queue, it becomes more vulnerable to noise in RTT * measurements (e.g., delayed ACKs or other ACK compression effects). This * noise may cause BBR to under-estimate the rate. */ static u32 react_target_cwnd(struct sock *sk, struct react *ca, int gain) { u64 w; u32 bw, cwnd; if (unlikely(ca->min_rtt_us == ~0U)) /* no valid RTT samples yet? */ return REACT_INIT_CWND; /* be safe: cap at default initial cwnd */ bw = react_max_bw(ca); w = (u64)bw * ca->min_rtt_us; cwnd = ((w * gain) >> (BW_SCALE + REACT_SCALE)) + 18; /* Reduce delayed ACKs by rounding up cwnd to the next even number. */ cwnd = (cwnd + 1) & ~1U; return cwnd; } static inline void react_set_cwnd(struct sock *sk, const struct rate_sample *rs, int gain) { struct tcp_sock *tp = tcp_sk(sk); struct react *ca = inet_csk_ca(sk); u32 cwnd = tp->snd_cwnd, target_cwnd; target_cwnd = DO_CONDITIONAL_OPT(ca->packet_conservation, REACT_MAX(cwnd, tcp_packets_in_flight(tp) + rs->acked_sacked), react_target_cwnd(sk, ca, gain)); cwnd = REACT_MAX(target_cwnd, 4); tp->snd_cwnd = REACT_MIN(cwnd, tp->snd_cwnd_clamp); tp->rcv_ssthresh = TCP_INFINITE_SSTHRESH; tp->rcv_wnd = REACT_MAX(cwnd, tp->rcv_wnd); ca->packet_conservation = 0; } static void react_check_drain(struct sock *sk, const struct rate_sample *rs, struct react *ca) { bool non_cong = (ca->state != CDG_FULL); if (!ca->drain_queue && !ca->round_restart) { struct tcp_sock *tp = tcp_sk(sk); u32 inflight = REACT_MIN(tcp_packets_in_flight(tp), rs->prior_in_flight); ca->cwnd_gain = DO_CONDITIONAL_OPT(non_cong, react_high_gain, react_cwnd_gain); if (inflight < tp->snd_cwnd) ca->pacing_gain = DO_CONDITIONAL_OPT(non_cong, react_high_gain, react_probe_gain); else ca->pacing_gain = DO_CONDITIONAL_OPT(non_cong, react_probe_gain, REACT_UNIT); } else if (ca->drain_queue && !ca->round_restart) { ca->cwnd_gain = react_high_gain; ca->pacing_gain = DO_CONDITIONAL_OPT(non_cong, REACT_UNIT, react_drain_gain); ca->state = CDG_UNKNOWN; ca->packet_conservation = 1; } ca->round_restart = 0; } /* We use the delay gradient as a congestion signal. */ static void react_grad(struct react *ca) { s32 gmin = ca->rtt.min - ca->rtt_prev.min; s32 gmax = ca->rtt.max - ca->rtt_prev.max; if (ca->gradients) { ca->gsum.min += gmin - ca->gradients[ca->tail].min; ca->gsum.max += gmax - ca->gradients[ca->tail].max; ca->gradients[ca->tail].min = gmin; ca->gradients[ca->tail].max = gmax; ca->tail = (ca->tail + 1) & (window - 1); gmin = ca->gsum.min; gmax = ca->gsum.max; } gmin += 32; gmax += 32; if (gmin > 0 && gmax <= 0) ca->state = CDG_FULL; else if ((gmin > 0 && gmax > 0) || gmax < 0) { ca->state = CDG_NONFULL; ca->full_bw_cnt = 0; } } static void react_update_rtt_grad(struct sock *sk, const struct rate_sample *rs, struct react *ca) { if (likely(rs->rtt_us)) { ca->rtt.min = REACT_MIN(DO_CONDITIONAL_OPT(ca->rtt.min > 0, ca->rtt.min, 1), rs->rtt_us); ca->rtt.max = REACT_MAX(ca->rtt.max, rs->rtt_us); } if (after(tcp_sk(sk)->snd_una, ca->rtt_seq + 1) && ca->rtt.v64) { if (ca->rtt_prev.v64) react_grad(ca); ca->rtt_seq = tcp_sk(sk)->snd_nxt; ca->rtt_prev = ca->rtt; ca->rtt.v64 = 0; } } static void react_update_min_rtt(struct sock *sk, const struct rate_sample *rs, struct react *ca) { bool filter_expired; /* Track min RTT seen in the min_rtt_win_sec filter window: */ filter_expired = after(tcp_time_stamp, ca->min_rtt_stamp + react_min_rtt_win_sec * HZ); if (rs->rtt_us >= 0 && (rs->rtt_us <= ca->min_rtt_us || filter_expired)) { ca->min_rtt_us = rs->rtt_us; ca->min_rtt_stamp = tcp_time_stamp; } ca->drain_queue = (filter_expired || (ca->state == CDG_FULL && ca->full_bw_cnt >= react_full_bw_cnt)); } static void react_update_bw(struct sock *sk, const struct rate_sample *rs, struct react *ca) { u64 bw, bw_thresh; if (rs->delivered < 0 || rs->interval_us <= 0) return; /* Not a valid observation */ /* See if we've reached the next RTT */ if (!before(rs->prior_delivered, ca->next_rtt_delivered)) { ca->next_rtt_delivered = tcp_sk(sk)->delivered; ca->rtt_cnt++; } /* Divide delivered by the interval to find a (lower bound) bottleneck * bandwidth sample. Delivered is in packets and interval_us in uS and * ratio will be <<1 for most connections. So delivered is first scaled. */ bw = ((u64)rs->delivered << BW_SCALE); do_div(bw, rs->interval_us); bw_thresh = (((u64)react_max_bw(ca) >> 3) * 9); ++ca->full_bw_cnt; if (bw >= bw_thresh) { ca->full_bw_cnt = 0; ca->state = CDG_UNKNOWN; } ca->full_bw_cnt = REACT_MIN(ca->full_bw_cnt, react_full_bw_cnt); /* If this sample is application-limited, it is likely to have a very * low delivered count that represents application behavior rather than * the available network rate. Such a sample could drag down estimated * bw, causing needless slow-down. Thus, to continue to send at the * last measured network rate, we filter out app-limited samples unless * they describe the path bw at least as well as our bw model. * * So the goal during app-limited phase is to proceed with the best * network rate no matter how long. We automatically leave this * phase when app writes faster than the network can deliver :) */ if (!rs->is_app_limited || bw >= react_max_bw(ca)) { /* Incorporate new sample into our max bw filter. */ minmax_running_max(&ca->bw, react_bw_rtts, (u32)ca->rtt_cnt, bw); } } static inline void react_update_model(struct sock *sk, const struct rate_sample *rs, struct react *ca) { react_update_bw(sk, rs, ca); react_update_min_rtt(sk, rs, ca); react_update_rtt_grad(sk, rs, ca); react_check_drain(sk, rs, ca); } static void react_main(struct sock *sk, const struct rate_sample *rs) { struct react *ca = inet_csk_ca(sk); react_update_model(sk, rs, ca); react_set_cwnd(sk, rs, ca->cwnd_gain); react_set_pacing_rate(sk, react_max_bw(ca), ca->pacing_gain); } static void react_set_state(struct sock *sk, u8 new_state) { struct react *ca = inet_csk_ca(sk); switch (new_state) { case TCP_CA_Loss: if (ca->state != CDG_FULL) /* Reset zero-window probe timer to push pending frames. */ inet_csk_reset_xmit_timer(sk, ICSK_TIME_PROBE0, tcp_probe0_base(sk), TCP_RTO_MAX); ca->round_restart = 1; ca->pacing_gain = react_high_gain; ca->full_bw_cnt = 0; break; case TCP_CA_Recovery: if (ca->state != CDG_NONFULL) { ca->packet_conservation = 1; ca->next_rtt_delivered = tcp_sk(sk)->delivered; } break; default: break; } } static void react_init(struct sock *sk) { struct react *ca = inet_csk_ca(sk); struct tcp_sock *tp = tcp_sk(sk); /* We silently fall back to window = 1 if allocation fails. */ ca->gradients = kcalloc(window, sizeof(ca->gradients[0]), GFP_NOWAIT | __GFP_NOWARN); ca->rtt_seq = tp->snd_nxt; ca->min_rtt_stamp = tcp_time_stamp; ca->min_rtt_us = tcp_min_rtt(tp); ca->state = CDG_NONFULL; ca->full_bw_cnt = 0; ca->rtt_cnt = 0; ca->next_rtt_delivered = 0; ca->round_restart = 1; ca->packet_conservation = 0; ca->pacing_gain = react_high_gain; ca->cwnd_gain = react_high_gain; minmax_reset(&ca->bw, (u32)ca->rtt_cnt, 0); /* init max bw to 0 */ } static void react_cwnd_event(struct sock *sk, const enum tcp_ca_event ev) { struct react *ca = inet_csk_ca(sk); struct cdg_minmax *gradients; switch (ev) { case CA_EVENT_TX_START: ca->state = CDG_NONFULL; ca->pacing_gain = react_high_gain; ca->cwnd_gain = react_high_gain; ca->round_restart = 1; break; case CA_EVENT_CWND_RESTART: gradients = ca->gradients; if (gradients) memset(gradients, 0, window * sizeof(gradients[0])); memset(ca, 0, sizeof(*ca)); ca->state = CDG_UNKNOWN; ca->gradients = gradients; ca->rtt_seq = tcp_sk(sk)->snd_nxt; break; default: break; } } static u32 react_undo_cwnd(struct sock *sk) { return tcp_sk(sk)->snd_cwnd; } static void react_release(struct sock *sk) { struct react *ca = inet_csk_ca(sk); kfree(ca->gradients); } static u32 react_sndbuf_expand(struct sock *sk) { return 3; } static u32 react_ssthresh(struct sock *sk) { return TCP_INFINITE_SSTHRESH; } static struct tcp_congestion_ops react_cong_ops __read_mostly = { .flags = TCP_CONG_NON_RESTRICTED, .name = "react_rc2", .owner = THIS_MODULE, .init = react_init, .cong_control = react_main, .cwnd_event = react_cwnd_event, .release = react_release, .sndbuf_expand = react_sndbuf_expand, .undo_cwnd = react_undo_cwnd, .ssthresh = react_ssthresh, .set_state = react_set_state, }; static int __init react_register(void) { BUILD_BUG_ON(sizeof(struct react) > ICSK_CA_PRIV_SIZE); return tcp_register_congestion_control(&react_cong_ops); } static void __exit react_unregister(void) { tcp_unregister_congestion_control(&react_cong_ops); } module_init(react_register); module_exit(react_unregister); MODULE_AUTHOR("Neal Cardwell <ncardwell@google.com>"); MODULE_AUTHOR("Yuchung Cheng <ycheng@google.com>"); MODULE_AUTHOR("Kenneth Klette Jonassen"); MODULE_LICENSE("Dual BSD/GPL"); MODULE_DESCRIPTION("TCP React");
from
https://www.hostloc.com/forum.php?mod=viewthread&tid=374117