├── Makefile ├── README.md └── tcp_elastic.c /Makefile: -------------------------------------------------------------------------------- 1 | obj-m += tcp_elastic.o 2 | 3 | all: 4 | make -C /lib/modules/`uname -r`/build M=`pwd` modules 5 | install: 6 | make -C /lib/modules/`uname -r`/build M=`pwd` modules_install 7 | clean: 8 | rm -f \ 9 | *.ko \ 10 | .*.o.cmd \ 11 | *.o \ 12 | *.mod.c \ 13 | Module.symvers \ 14 | .*.mod.cmd \ 15 | modules.order \ 16 | .*.ko.cmd \ 17 | *.mod \ 18 | .modules.order.cmd \ 19 | .Module.symvers.cmd 20 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # Elastic-TCP: Flexible Congestion Control Algorithm to Adapt for High-BDP Networks 2 | 3 | The paper: https://ieeexplore.ieee.org/stamp/stamp.jsp?tp=&arnumber=8642512 4 | 5 | ## Test environment 6 | * NetEm on receiver side 7 | - `qdisc netem 8004: dev ifb0 root refcnt 2 limit 865 delay 100.0ms rate 100Mbit` 8 | * 100Mbps 9 | * 100ms RTT 10 | 11 | Test result: 12 | 13 | ![image](https://user-images.githubusercontent.com/980728/125387081-eedb0a80-e3cf-11eb-92a1-6f6dfdcce280.png) 14 | 15 | compared to RENO 16 | 17 | ![image](https://user-images.githubusercontent.com/980728/130021405-a16e6be4-296d-43d3-b3d9-74635aa5305c.png) 18 | 19 | compared to CUBIC 20 | 21 | ![image](https://user-images.githubusercontent.com/980728/130021501-8f97a30b-49a0-43d0-9695-5599ebfa03a4.png) 22 | 23 | -------------------------------------------------------------------------------- /tcp_elastic.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | 4 | #define ELASTIC_SCALE 6 5 | #define ELASTIC_UNIT (1 << ELASTIC_SCALE) 6 | 7 | struct elastic { 8 | u32 rtt_max; 9 | u32 rtt_curr; 10 | }; 11 | 12 | static void elastic_init(struct sock *sk) 13 | { 14 | struct elastic *ca = inet_csk_ca(sk); 15 | ca->rtt_max = 0; 16 | ca->rtt_curr = 1; 17 | } 18 | 19 | static void elastic_cong_avoid(struct sock *sk, u32 ack, u32 acked) 20 | { 21 | struct tcp_sock *tp = tcp_sk(sk); 22 | struct elastic *ca = inet_csk_ca(sk); 23 | 24 | if (!tcp_is_cwnd_limited(sk)) 25 | return; 26 | 27 | if (tcp_in_slow_start(tp)) 28 | tcp_slow_start(tp, acked); 29 | else { 30 | u64 wwf64 = int_sqrt(tp->snd_cwnd*int_pow(ELASTIC_UNIT,2)*ca->rtt_max/ca->rtt_curr); 31 | u32 wwf = wwf64 >> ELASTIC_SCALE; 32 | tcp_cong_avoid_ai(tp, tp->snd_cwnd, wwf); 33 | } 34 | } 35 | 36 | static void elastic_update_rtt(struct sock *sk, const struct ack_sample *sample) 37 | { 38 | struct elastic *ca = inet_csk_ca(sk); 39 | ca->rtt_curr = sample->rtt_us + 1; 40 | if (ca->rtt_curr > ca->rtt_max) { 41 | ca->rtt_max = ca->rtt_curr; 42 | } 43 | } 44 | 45 | static void elastic_event(struct sock *sk, enum tcp_ca_event event) 46 | { 47 | struct elastic *ca = inet_csk_ca(sk); 48 | if (event == CA_EVENT_LOSS) { 49 | ca->rtt_max = 0; 50 | } 51 | } 52 | 53 | static struct tcp_congestion_ops tcp_elastic __read_mostly = { 54 | .name = "elastic", 55 | .owner = THIS_MODULE, 56 | .init = elastic_init, 57 | .ssthresh = tcp_reno_ssthresh, 58 | .undo_cwnd = tcp_reno_undo_cwnd, 59 | .cong_avoid = elastic_cong_avoid, 60 | .pkts_acked = elastic_update_rtt, 61 | .cwnd_event = elastic_event 62 | }; 63 | 64 | static int __init elastic_register(void) 65 | { 66 | BUILD_BUG_ON(sizeof(struct elastic) > ICSK_CA_PRIV_SIZE); 67 | return tcp_register_congestion_control(&tcp_elastic); 68 | } 69 | 70 | static void __exit elastic_unregister(void) 71 | { 72 | tcp_unregister_congestion_control(&tcp_elastic); 73 | } 74 | 75 | module_init(elastic_register); 76 | module_exit(elastic_unregister); 77 | 78 | MODULE_AUTHOR("xtao"); 79 | MODULE_LICENSE("GPL"); 80 | MODULE_DESCRIPTION("Elastic TCP"); 81 | --------------------------------------------------------------------------------