-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathtcp_cubic.patch
More file actions
291 lines (275 loc) · 10.1 KB
/
Copy pathtcp_cubic.patch
File metadata and controls
291 lines (275 loc) · 10.1 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
--- original_tcp_cubic.c 2025-02-10 12:17:14.000000000 +1300
+++ modified_tcp_cubic.c 2025-02-24 12:21:59.000000000 +1300
@@ -46,6 +46,18 @@
#define HYSTART_DELAY_MAX (16000U) /* 16 ms */
#define HYSTART_DELAY_THRESH(x) clamp(x, HYSTART_DELAY_MIN, HYSTART_DELAY_MAX)
+/* {RFC9406_L253} */
+#define HSPP_MIN_RTT_THRESH (4000U) /* 4 ms */
+#define HSPP_MAX_RTT_THRESH (16000U) /* 16 ms */
+#define HSPP_CSS_MIN_RTT_DIV 3 /* RTT threshold is computed as RTT / (2^HSPP_CSS_MIN_RTT_DIV) */
+#define HSPP_N_RTT_SAMPLE 8 /* Number of RTTs in CSS to determine whether the exit from SS was premature */
+#define HSPP_CSS_GROWTH_DIV 4 /* For less aggressive growth, cwnd increase is divided by 4 in CSS */
+#define HSPP_CSS_ROUNDS 5 /* Maximum number of rounds for CSS phase */
+#define HSPP_DEACTIVE 0
+#define HSPP_IN_SS 1 /* SS phase is active */
+#define HSPP_IN_CSS 2 /* CSS phase is active */
+#define HSPP_RTT_THRESH(x) clamp(x, HSPP_MIN_RTT_THRESH, HSPP_MAX_RTT_THRESH)
+
static int fast_convergence __read_mostly = 1;
static int beta __read_mostly = 717; /* = 717/1024 (BICTCP_BETA_SCALE) */
static int initial_ssthresh __read_mostly;
@@ -82,6 +94,14 @@
module_param(hystart_ack_delta_us, int, 0644);
MODULE_PARM_DESC(hystart_ack_delta_us, "spacing between ack's indicating train (usecs)");
+static int hystartpp = 0;
+module_param(hystartpp, int, 0644);
+MODULE_PARM_DESC(hystartpp, "turn on/off hystart++ algorithm");
+// The following three lines are for monitoring purpose and will not be included in the final implementation.
+static int hystartpp_source_port = 80;
+module_param(hystartpp_source_port, int, 0644);
+MODULE_PARM_DESC(hystartpp_source_port, "Source port used for TCP data transfer");
+
/* BIC TCP Parameters */
struct bictcp {
u32 cnt; /* increase cwnd by 1 after ACKs */
@@ -102,6 +122,23 @@
u32 end_seq; /* end_seq of the round */
u32 last_ack; /* last time when the ACK spacing is close */
u32 curr_rtt; /* the minimum rtt of current round */
+
+/* While some variables from HyStart could be reused,
+ * we define separate variables for HyStart++ (HSPP) to enhance clarity.
+ */
+ u8 hspp_flag;
+ u8 hspp_rttsample_counter;
+ u32 hspp_last_round_minrtt;
+ u32 hspp_current_round_minrtt;
+ u8 hspp_round_counter;
+ u8 hspp_entered_css_at_round;
+ u32 hspp_css_baseline_minrtt;
+ u32 hspp_end_seq;
+
+ // The following three variables are used for monitoring and will not be included in the final implementation.
+ u32 hspp_recent_rtt;
+ u32 hspp_acked;
+ u32 snd_isn; // Initial sequence number (is used to calc delivered)
};
static inline void bictcp_reset(struct bictcp *ca)
@@ -115,6 +152,26 @@
return tcp_sk(sk)->tcp_mstamp;
}
+// This function is used for monitoring and will not be included in the final implementation.
+static void logprint(struct sock *sk, char *msg, int extra)
+{
+ if (ntohs(inet_sk(sk)->inet_sport) != hystartpp_source_port)
+ return;
+
+ struct tcp_sock *tp = tcp_sk(sk);
+ struct bictcp *ca = inet_csk_ca(sk);
+
+ printk(KERN_INFO "^ t %u c %u i %u f %u r %u a %u d %u l %u",
+ bictcp_clock_us(sk), tp->snd_cwnd, tcp_packets_in_flight(tp), ca->hspp_flag, (tp->srtt_us >> 3), ca->hspp_acked, (tp->snd_una - ca->snd_isn), tp->lost);
+
+ if (extra) {
+ printk(KERN_INFO "Extra info: %s t %u c %u i %u f %u ssthresh %u rttsample_counter %u last_round_minrtt %u "
+ "current_round_minrtt %u round_counter %u entered_css_at_round %u css_baseline_minrtt %u recent_rtt %u",
+ msg, bictcp_clock_us(sk), tp->snd_cwnd, tcp_packets_in_flight(tp), ca->hspp_flag, tp->snd_ssthresh, ca->hspp_rttsample_counter, ca->hspp_last_round_minrtt,
+ ca->hspp_current_round_minrtt, ca->hspp_round_counter, ca->hspp_entered_css_at_round, ca->hspp_css_baseline_minrtt, ca->hspp_recent_rtt);
+ }
+}
+
static inline void bictcp_hystart_reset(struct sock *sk)
{
struct tcp_sock *tp = tcp_sk(sk);
@@ -126,12 +183,35 @@
ca->sample_cnt = 0;
}
+static inline void hystartpp_reset(struct sock *sk)
+{
+ struct tcp_sock *tp = tcp_sk(sk);
+ struct bictcp *ca = inet_csk_ca(sk);
+
+ ca->hspp_last_round_minrtt = ca->hspp_current_round_minrtt; /* {RFC9406_L186} */
+ ca->hspp_current_round_minrtt = ~0U; /* {RFC9406_L187} */
+ ca->hspp_rttsample_counter = 0; /* {RFC9406_L188} */
+ ca->hspp_end_seq = tp->snd_nxt;
+}
+
__bpf_kfunc static void cubictcp_init(struct sock *sk)
{
struct bictcp *ca = inet_csk_ca(sk);
bictcp_reset(ca);
+
+ ca->snd_isn = tcp_sk(sk)->snd_una;
+ if (hystartpp) {
+ ca->hspp_round_counter = 0;
+ ca->hspp_flag = HSPP_IN_SS;
+ ca->hspp_last_round_minrtt = ~0U; /* {RFC9406_L167} */
+ ca->hspp_current_round_minrtt = ~0U; /* {RFC9406_L167} */
+ hystartpp_reset(sk);
+ logprint(sk, "INIT", 1);
+ return;
+ }
+
if (hystart)
bictcp_hystart_reset(sk);
@@ -321,6 +401,40 @@
ca->cnt = max(ca->cnt, 2U);
}
+static void hystartpp_adjust_cwnd(struct sock *sk, u32 acked) {
+ struct tcp_sock *tp = tcp_sk(sk);
+ struct bictcp *ca = inet_csk_ca(sk);
+ u32 rtt_thresh;
+
+ /* Check if it is time to enter CSS. {RFC9406_L202} */
+ if ((ca->hspp_flag == HSPP_IN_SS) &&
+ (ca->hspp_rttsample_counter >= HSPP_N_RTT_SAMPLE) &&
+ (ca->hspp_current_round_minrtt != ~0U) &&
+ (ca->hspp_last_round_minrtt != ~0U)) {
+ rtt_thresh = (ca->hspp_last_round_minrtt >> HSPP_CSS_MIN_RTT_DIV);
+ rtt_thresh = HSPP_RTT_THRESH(rtt_thresh);
+ if (ca->hspp_current_round_minrtt >= (ca->hspp_last_round_minrtt + rtt_thresh)) {
+ /* Enter CSS */
+ ca->hspp_css_baseline_minrtt = ca->hspp_current_round_minrtt;
+ ca->hspp_entered_css_at_round = ca->hspp_round_counter;
+ ca->hspp_flag = HSPP_IN_CSS;
+ logprint(sk, "Enter CSS", 1);
+ }
+ }
+
+ if (ca->hspp_flag == HSPP_IN_SS) {
+ tcp_slow_start(tp, acked);
+ } else if (ca->hspp_flag == HSPP_IN_CSS) {
+ tcp_cong_avoid_ai(tp, HSPP_CSS_GROWTH_DIV, acked); /* {RFC9406_L215} */
+ }
+
+ if (tcp_snd_cwnd(tp) >= tp->snd_ssthresh) {
+ /* Enter CA {RFC9406_L075} */
+ logprint(sk, "Enter CA1", 1);
+ ca->hspp_flag = HSPP_DEACTIVE;
+ }
+}
+
__bpf_kfunc static void cubictcp_cong_avoid(struct sock *sk, u32 ack, u32 acked)
{
struct tcp_sock *tp = tcp_sk(sk);
@@ -329,7 +443,15 @@
if (!tcp_is_cwnd_limited(sk))
return;
+ ca->hspp_acked = acked; // Used for monitoring
+ logprint(sk, "New ACK", 0); // Used for monitoring
+
if (tcp_in_slow_start(tp)) {
+ if (hystartpp && (ca->hspp_flag != HSPP_DEACTIVE)) { /* {RFC9406_L075} */
+ hystartpp_adjust_cwnd(sk, acked);
+ return;
+ }
+
acked = tcp_slow_start(tp, acked);
if (!acked)
return;
@@ -343,6 +465,9 @@
const struct tcp_sock *tp = tcp_sk(sk);
struct bictcp *ca = inet_csk_ca(sk);
+ logprint(sk, "recalc ssthresh", 1);
+ ca->hspp_flag = HSPP_DEACTIVE;
+
ca->epoch_start = 0; /* end of epoch */
/* Wmax and fast convergence */
@@ -357,6 +482,19 @@
__bpf_kfunc static void cubictcp_state(struct sock *sk, u8 new_state)
{
+ struct bictcp *ca = inet_csk_ca(sk);
+
+ if(ntohs(inet_sk(sk)->inet_sport) == hystartpp_source_port) // Used for monitoring
+ printk(KERN_INFO "~ State changed to %u t %u c %u i %u f %u ssthresh %u",
+ new_state, bictcp_clock_us(sk), tcp_sk(sk)->snd_cwnd, tcp_packets_in_flight(tcp_sk(sk)), ca->hspp_flag, tcp_sk(sk)->snd_ssthresh);
+
+ if (hystartpp && (ca->hspp_flag != HSPP_DEACTIVE) &&
+ ((new_state == TCP_CA_CWR) || (new_state == TCP_CA_Recovery) || (new_state == TCP_CA_Loss))) { /* {RFC9406_L245} */
+ logprint(sk, "State Changed", 1);
+ ca->hspp_flag = HSPP_DEACTIVE;
+ return;
+ }
+
if (new_state == TCP_CA_Loss) {
bictcp_reset(inet_csk_ca(sk));
bictcp_hystart_reset(sk);
@@ -383,6 +521,50 @@
div64_ul((u64)sk->sk_gso_max_size * 4 * USEC_PER_SEC, rate));
}
+static void hystartpp_new_round(struct sock *sk)
+{
+ struct tcp_sock *tp = tcp_sk(sk);
+ struct bictcp *ca = inet_csk_ca(sk);
+
+ logprint(sk, "New Round", 1);
+ hystartpp_reset(sk);
+ ca->hspp_round_counter++;
+
+ if ((ca->hspp_flag == HSPP_IN_CSS) &&
+ ((ca->hspp_round_counter - ca->hspp_entered_css_at_round) >= HSPP_CSS_ROUNDS)) {
+ tp->snd_ssthresh = tcp_snd_cwnd(tp); /* Enter CA {RFC9406_L155} {RFC9406_L240} */
+ ca->hspp_flag = HSPP_DEACTIVE;
+ logprint(sk, "Enter CA2", 1);
+ }
+}
+
+static void hystartpp_adjust_params(struct sock *sk, u32 rtt)
+{
+ struct tcp_sock *tp = tcp_sk(sk);
+ struct bictcp *ca = inet_csk_ca(sk);
+
+ ca->hspp_recent_rtt = rtt;
+
+ if (after(tp->snd_una, ca->hspp_end_seq)) /* Is it the start of a new round? */
+ hystartpp_new_round(sk);
+
+ if (rtt < ca->hspp_current_round_minrtt) {
+ ca->hspp_current_round_minrtt = rtt; /* {RFC9406_L199} {RFC9406_L224}*/
+ }
+
+ if (ca->hspp_rttsample_counter < HSPP_N_RTT_SAMPLE) {
+ ca->hspp_rttsample_counter++; /* {RFC9406_L200} {RFC9406_L225} */
+ } else {
+ if ((ca->hspp_flag == HSPP_IN_CSS) &&
+ (ca->hspp_current_round_minrtt < ca->hspp_css_baseline_minrtt)) {
+ /* We were in CSS and the RTT is now less, we entered CSS erroneously. Enter SS. {RFC9406_L152} {RFC9406_L227} */
+ logprint(sk, "Enter SS. We entered CSS erroneously", 1);
+ ca->hspp_css_baseline_minrtt = ~0U; /* In this implementation, the HSPP_IN_CSS flag indicates that we are in CSS, so this assignment is unnecessary. */
+ ca->hspp_flag = HSPP_IN_SS;
+ }
+ }
+}
+
static void hystart_update(struct sock *sk, u32 delay)
{
struct tcp_sock *tp = tcp_sk(sk);
@@ -415,6 +597,7 @@
if ((s32)(now - ca->round_start) > threshold) {
ca->found = 1;
+ logprint(sk, "HYSTART_ACK_TRAIN", 1);
pr_debug("hystart_ack_train (%u > %u) delay_min %u (+ ack_delay %u) cwnd %u\n",
now - ca->round_start, threshold,
ca->delay_min, hystart_ack_delay(sk), tcp_snd_cwnd(tp));
@@ -438,6 +621,7 @@
if (ca->curr_rtt > ca->delay_min +
HYSTART_DELAY_THRESH(ca->delay_min >> 3)) {
ca->found = 1;
+ logprint(sk, "HYSTART_DELAY", 1);
NET_INC_STATS(sock_net(sk),
LINUX_MIB_TCPHYSTARTDELAYDETECT);
NET_ADD_STATS(sock_net(sk),
@@ -471,6 +655,13 @@
if (ca->delay_min == 0 || ca->delay_min > delay)
ca->delay_min = delay;
+ if (hystartpp) {
+ if (tcp_in_slow_start(tp) && (ca->hspp_flag != HSPP_DEACTIVE)) { /* {RFC9406_L075} */
+ hystartpp_adjust_params(sk, delay);
+ }
+ return;
+ }
+
if (!ca->found && tcp_in_slow_start(tp) && hystart)
hystart_update(sk, delay);
}