sctp: import internal copy of usrsctp library
[platform/upstream/gstreamer.git] / ext / sctp / usrsctp / usrsctplib / netinet / sctp_cc_functions.c
1 /*-
2  * SPDX-License-Identifier: BSD-3-Clause
3  *
4  * Copyright (c) 2001-2007, by Cisco Systems, Inc. All rights reserved.
5  * Copyright (c) 2008-2012, by Randall Stewart. All rights reserved.
6  * Copyright (c) 2008-2012, by Michael Tuexen. All rights reserved.
7  *
8  * Redistribution and use in source and binary forms, with or without
9  * modification, are permitted provided that the following conditions are met:
10  *
11  * a) Redistributions of source code must retain the above copyright notice,
12  *    this list of conditions and the following disclaimer.
13  *
14  * b) Redistributions in binary form must reproduce the above copyright
15  *    notice, this list of conditions and the following disclaimer in
16  *    the documentation and/or other materials provided with the distribution.
17  *
18  * c) Neither the name of Cisco Systems, Inc. nor the names of its
19  *    contributors may be used to endorse or promote products derived
20  *    from this software without specific prior written permission.
21  *
22  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
23  * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
24  * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
25  * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
26  * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
27  * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
28  * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
29  * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
30  * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
31  * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
32  * THE POSSIBILITY OF SUCH DAMAGE.
33  */
34
35 #if defined(__FreeBSD__) && !defined(__Userspace__)
36 #include <sys/cdefs.h>
37 __FBSDID("$FreeBSD: head/sys/netinet/sctp_cc_functions.c 359405 2020-03-28 20:25:45Z tuexen $");
38 #endif
39
40 #include <netinet/sctp_os.h>
41 #include <netinet/sctp_var.h>
42 #include <netinet/sctp_sysctl.h>
43 #include <netinet/sctp_pcb.h>
44 #include <netinet/sctp_header.h>
45 #include <netinet/sctputil.h>
46 #include <netinet/sctp_output.h>
47 #include <netinet/sctp_input.h>
48 #include <netinet/sctp_indata.h>
49 #include <netinet/sctp_uio.h>
50 #include <netinet/sctp_timer.h>
51 #include <netinet/sctp_auth.h>
52 #include <netinet/sctp_asconf.h>
53 #if defined(__FreeBSD__) && !defined(__Userspace__)
54 #include <netinet/sctp_kdtrace.h>
55 #endif
56
57 #define SHIFT_MPTCP_MULTI_N 40
58 #define SHIFT_MPTCP_MULTI_Z 16
59 #define SHIFT_MPTCP_MULTI 8
60
61 static void
62 sctp_enforce_cwnd_limit(struct sctp_association *assoc, struct sctp_nets *net)
63 {
64         if ((assoc->max_cwnd > 0) &&
65             (net->cwnd > assoc->max_cwnd) &&
66             (net->cwnd > (net->mtu - sizeof(struct sctphdr)))) {
67                 net->cwnd = assoc->max_cwnd ;
68                 if (net->cwnd < (net->mtu - sizeof(struct sctphdr))) {
69                         net->cwnd = net->mtu - sizeof(struct sctphdr);
70                 }
71         }
72 }
73
74 static void
75 sctp_set_initial_cc_param(struct sctp_tcb *stcb, struct sctp_nets *net)
76 {
77         struct sctp_association *assoc;
78         uint32_t cwnd_in_mtu;
79
80         assoc = &stcb->asoc;
81         cwnd_in_mtu = SCTP_BASE_SYSCTL(sctp_initial_cwnd);
82         if (cwnd_in_mtu == 0) {
83                 /* Using 0 means that the value of RFC 4960 is used. */
84                 net->cwnd = min((net->mtu * 4), max((2 * net->mtu), SCTP_INITIAL_CWND));
85         } else {
86                 /*
87                  * We take the minimum of the burst limit and the
88                  * initial congestion window.
89                  */
90                 if ((assoc->max_burst > 0) && (cwnd_in_mtu > assoc->max_burst))
91                         cwnd_in_mtu = assoc->max_burst;
92                 net->cwnd = (net->mtu - sizeof(struct sctphdr)) * cwnd_in_mtu;
93         }
94         if ((stcb->asoc.sctp_cmt_on_off == SCTP_CMT_RPV1) ||
95             (stcb->asoc.sctp_cmt_on_off == SCTP_CMT_RPV2)) {
96                 /* In case of resource pooling initialize appropriately */
97                 net->cwnd /= assoc->numnets;
98                 if (net->cwnd < (net->mtu - sizeof(struct sctphdr))) {
99                         net->cwnd = net->mtu - sizeof(struct sctphdr);
100                 }
101         }
102         sctp_enforce_cwnd_limit(assoc, net);
103         net->ssthresh = assoc->peers_rwnd;
104 #if defined(__FreeBSD__) && !defined(__Userspace__)
105         SDT_PROBE5(sctp, cwnd, net, init,
106                   stcb->asoc.my_vtag, ((stcb->sctp_ep->sctp_lport << 16) | (stcb->rport)), net,
107                   0, net->cwnd);
108 #endif
109         if (SCTP_BASE_SYSCTL(sctp_logging_level) &
110             (SCTP_CWND_MONITOR_ENABLE|SCTP_CWND_LOGGING_ENABLE)) {
111                 sctp_log_cwnd(stcb, net, 0, SCTP_CWND_INITIALIZATION);
112         }
113 }
114
115 static void
116 sctp_cwnd_update_after_fr(struct sctp_tcb *stcb,
117                           struct sctp_association *asoc)
118 {
119         struct sctp_nets *net;
120         uint32_t t_ssthresh, t_cwnd;
121         uint64_t t_ucwnd_sbw;
122
123         /* MT FIXME: Don't compute this over and over again */
124         t_ssthresh = 0;
125         t_cwnd = 0;
126         t_ucwnd_sbw = 0;
127         if ((asoc->sctp_cmt_on_off == SCTP_CMT_RPV1) ||
128             (asoc->sctp_cmt_on_off == SCTP_CMT_RPV2)) {
129                 TAILQ_FOREACH(net, &asoc->nets, sctp_next) {
130                         t_ssthresh += net->ssthresh;
131                         t_cwnd += net->cwnd;
132                         if (net->lastsa > 0) {
133                                 t_ucwnd_sbw += (uint64_t)net->cwnd / (uint64_t)net->lastsa;
134                         }
135                 }
136                 if (t_ucwnd_sbw == 0) {
137                         t_ucwnd_sbw = 1;
138                 }
139         }
140
141         /*-
142          * CMT fast recovery code. Need to debug. ((sctp_cmt_on_off > 0) &&
143          * (net->fast_retran_loss_recovery == 0)))
144          */
145         TAILQ_FOREACH(net, &asoc->nets, sctp_next) {
146                 if ((asoc->fast_retran_loss_recovery == 0) ||
147                     (asoc->sctp_cmt_on_off > 0)) {
148                         /* out of a RFC2582 Fast recovery window? */
149                         if (net->net_ack > 0) {
150                                 /*
151                                  * per section 7.2.3, are there any
152                                  * destinations that had a fast retransmit
153                                  * to them. If so what we need to do is
154                                  * adjust ssthresh and cwnd.
155                                  */
156                                 struct sctp_tmit_chunk *lchk;
157                                 int old_cwnd = net->cwnd;
158
159                                 if ((asoc->sctp_cmt_on_off == SCTP_CMT_RPV1) ||
160                                     (asoc->sctp_cmt_on_off == SCTP_CMT_RPV2)) {
161                                         if (asoc->sctp_cmt_on_off == SCTP_CMT_RPV1) {
162                                                 net->ssthresh = (uint32_t)(((uint64_t)4 *
163                                                                             (uint64_t)net->mtu *
164                                                                             (uint64_t)net->ssthresh) /
165                                                                            (uint64_t)t_ssthresh);
166
167                                         }
168                                         if (asoc->sctp_cmt_on_off == SCTP_CMT_RPV2) {
169                                                 uint32_t srtt;
170
171                                                 srtt = net->lastsa;
172                                                 /* lastsa>>3;  we don't need to devide ...*/
173                                                 if (srtt == 0) {
174                                                         srtt = 1;
175                                                 }
176                                                 /* Short Version => Equal to Contel Version MBe */
177                                                 net->ssthresh = (uint32_t) (((uint64_t)4 *
178                                                                              (uint64_t)net->mtu *
179                                                                              (uint64_t)net->cwnd) /
180                                                                             ((uint64_t)srtt *
181                                                                              t_ucwnd_sbw));
182                                                                              /* INCREASE FACTOR */;
183                                         }
184                                         if ((net->cwnd > t_cwnd / 2) &&
185                                             (net->ssthresh < net->cwnd - t_cwnd / 2)) {
186                                                 net->ssthresh = net->cwnd - t_cwnd / 2;
187                                         }
188                                         if (net->ssthresh < net->mtu) {
189                                                 net->ssthresh = net->mtu;
190                                         }
191                                 } else {
192                                         net->ssthresh = net->cwnd / 2;
193                                         if (net->ssthresh < (net->mtu * 2)) {
194                                                 net->ssthresh = 2 * net->mtu;
195                                         }
196                                 }
197                                 net->cwnd = net->ssthresh;
198                                 sctp_enforce_cwnd_limit(asoc, net);
199 #if defined(__FreeBSD__) && !defined(__Userspace__)
200                                 SDT_PROBE5(sctp, cwnd, net, fr,
201                                           stcb->asoc.my_vtag, ((stcb->sctp_ep->sctp_lport << 16) | (stcb->rport)), net,
202                                           old_cwnd, net->cwnd);
203 #endif
204                                 if (SCTP_BASE_SYSCTL(sctp_logging_level) & SCTP_CWND_MONITOR_ENABLE) {
205                                         sctp_log_cwnd(stcb, net, (net->cwnd - old_cwnd),
206                                                 SCTP_CWND_LOG_FROM_FR);
207                                 }
208                                 lchk = TAILQ_FIRST(&asoc->send_queue);
209
210                                 net->partial_bytes_acked = 0;
211                                 /* Turn on fast recovery window */
212                                 asoc->fast_retran_loss_recovery = 1;
213                                 if (lchk == NULL) {
214                                         /* Mark end of the window */
215                                         asoc->fast_recovery_tsn = asoc->sending_seq - 1;
216                                 } else {
217                                         asoc->fast_recovery_tsn = lchk->rec.data.tsn - 1;
218                                 }
219
220                                 /*
221                                  * CMT fast recovery -- per destination
222                                  * recovery variable.
223                                  */
224                                 net->fast_retran_loss_recovery = 1;
225
226                                 if (lchk == NULL) {
227                                         /* Mark end of the window */
228                                         net->fast_recovery_tsn = asoc->sending_seq - 1;
229                                 } else {
230                                         net->fast_recovery_tsn = lchk->rec.data.tsn - 1;
231                                 }
232
233                                 sctp_timer_stop(SCTP_TIMER_TYPE_SEND,
234                                                 stcb->sctp_ep, stcb, net,
235                                                 SCTP_FROM_SCTP_CC_FUNCTIONS + SCTP_LOC_1);
236                                 sctp_timer_start(SCTP_TIMER_TYPE_SEND,
237                                                  stcb->sctp_ep, stcb, net);
238                         }
239                 } else if (net->net_ack > 0) {
240                         /*
241                          * Mark a peg that we WOULD have done a cwnd
242                          * reduction but RFC2582 prevented this action.
243                          */
244                         SCTP_STAT_INCR(sctps_fastretransinrtt);
245                 }
246         }
247 }
248
249 /* Defines for instantaneous bw decisions */
250 #define SCTP_INST_LOOSING 1 /* Losing to other flows */
251 #define SCTP_INST_NEUTRAL 2 /* Neutral, no indication */
252 #define SCTP_INST_GAINING 3 /* Gaining, step down possible */
253
254
255 #if defined(__FreeBSD__) && !defined(__Userspace__)
256 static int
257 cc_bw_same(struct sctp_tcb *stcb, struct sctp_nets *net, uint64_t nbw,
258            uint64_t rtt_offset, uint64_t vtag, uint8_t inst_ind)
259 #else
260 static int
261 cc_bw_same(struct sctp_tcb *stcb SCTP_UNUSED, struct sctp_nets *net, uint64_t nbw,
262            uint64_t rtt_offset, uint8_t inst_ind)
263 #endif
264 {
265 #if defined(__FreeBSD__) && !defined(__Userspace__)
266         uint64_t oth, probepoint;
267 #endif
268
269 #if defined(__FreeBSD__) && !defined(__Userspace__)
270         probepoint = (((uint64_t)net->cwnd) << 32);
271 #endif
272         if (net->rtt > net->cc_mod.rtcc.lbw_rtt + rtt_offset) {
273                 /*
274                  * rtt increased
275                  * we don't update bw.. so we don't
276                  * update the rtt either.
277                  */
278 #if defined(__FreeBSD__) && !defined(__Userspace__)
279                 /* Probe point 5 */
280                 probepoint |=  ((5 << 16) | 1);
281                 SDT_PROBE5(sctp, cwnd, net, rttvar,
282                           vtag,
283                           ((net->cc_mod.rtcc.lbw << 32) | nbw),
284                           ((net->cc_mod.rtcc.lbw_rtt << 32) | net->rtt),
285                           net->flight_size,
286                           probepoint);
287 #endif
288                 if ((net->cc_mod.rtcc.steady_step) && (inst_ind != SCTP_INST_LOOSING)) {
289                         if (net->cc_mod.rtcc.last_step_state == 5)
290                                 net->cc_mod.rtcc.step_cnt++;
291                         else
292                                 net->cc_mod.rtcc.step_cnt = 1;
293                         net->cc_mod.rtcc.last_step_state = 5;
294                         if ((net->cc_mod.rtcc.step_cnt == net->cc_mod.rtcc.steady_step) ||
295                             ((net->cc_mod.rtcc.step_cnt > net->cc_mod.rtcc.steady_step) &&
296                              ((net->cc_mod.rtcc.step_cnt % net->cc_mod.rtcc.steady_step) == 0))) {
297                                 /* Try a step down */
298 #if defined(__FreeBSD__) && !defined(__Userspace__)
299                                 oth = net->cc_mod.rtcc.vol_reduce;
300                                 oth <<= 16;
301                                 oth |= net->cc_mod.rtcc.step_cnt;
302                                 oth <<= 16;
303                                 oth |= net->cc_mod.rtcc.last_step_state;
304                                 SDT_PROBE5(sctp, cwnd, net, rttstep,
305                                           vtag,
306                                           ((net->cc_mod.rtcc.lbw << 32) | nbw),
307                                           ((net->cc_mod.rtcc.lbw_rtt << 32) | net->rtt),
308                                           oth,
309                                           probepoint);
310 #endif
311                                 if (net->cwnd > (4 * net->mtu)) {
312                                         net->cwnd -= net->mtu;
313                                         net->cc_mod.rtcc.vol_reduce++;
314                                 } else {
315                                         net->cc_mod.rtcc.step_cnt = 0;
316                                 }
317                         }
318                 }
319                 return (1);
320         }
321         if (net->rtt < net->cc_mod.rtcc.lbw_rtt-rtt_offset) {
322                 /*
323                  * rtt decreased, there could be more room.
324                  * we update both the bw and the rtt here to
325                  * lock this in as a good step down.
326                  */
327 #if defined(__FreeBSD__) && !defined(__Userspace__)
328                 /* Probe point 6 */
329                 probepoint |=  ((6 << 16) | 0);
330                 SDT_PROBE5(sctp, cwnd, net, rttvar,
331                           vtag,
332                           ((net->cc_mod.rtcc.lbw << 32) | nbw),
333                           ((net->cc_mod.rtcc.lbw_rtt << 32) | net->rtt),
334                           net->flight_size,
335                           probepoint);
336 #endif
337                 if (net->cc_mod.rtcc.steady_step) {
338 #if defined(__FreeBSD__) && !defined(__Userspace__)
339                         oth = net->cc_mod.rtcc.vol_reduce;
340                         oth <<= 16;
341                         oth |= net->cc_mod.rtcc.step_cnt;
342                         oth <<= 16;
343                         oth |= net->cc_mod.rtcc.last_step_state;
344                         SDT_PROBE5(sctp, cwnd, net, rttstep,
345                                   vtag,
346                                   ((net->cc_mod.rtcc.lbw << 32) | nbw),
347                                   ((net->cc_mod.rtcc.lbw_rtt << 32) | net->rtt),
348                                   oth,
349                                   probepoint);
350 #endif
351                         if ((net->cc_mod.rtcc.last_step_state == 5) &&
352                             (net->cc_mod.rtcc.step_cnt > net->cc_mod.rtcc.steady_step)) {
353                                 /* Step down worked */
354                                 net->cc_mod.rtcc.step_cnt = 0;
355                                 return (1);
356                         } else {
357                                 net->cc_mod.rtcc.last_step_state = 6;
358                                 net->cc_mod.rtcc.step_cnt = 0;
359                         }
360                 }
361                 net->cc_mod.rtcc.lbw = nbw;
362                 net->cc_mod.rtcc.lbw_rtt = net->rtt;
363                 net->cc_mod.rtcc.cwnd_at_bw_set = net->cwnd;
364                 if (inst_ind == SCTP_INST_GAINING)
365                         return (1);
366                 else if (inst_ind == SCTP_INST_NEUTRAL)
367                         return (1);
368                 else
369                         return (0);
370         }
371         /* Ok bw and rtt remained the same .. no update to any
372          */
373 #if defined(__FreeBSD__) && !defined(__Userspace__)
374         /* Probe point 7 */
375         probepoint |=  ((7 << 16) | net->cc_mod.rtcc.ret_from_eq);
376         SDT_PROBE5(sctp, cwnd, net, rttvar,
377                   vtag,
378                   ((net->cc_mod.rtcc.lbw << 32) | nbw),
379                   ((net->cc_mod.rtcc.lbw_rtt << 32) | net->rtt),
380                   net->flight_size,
381                   probepoint);
382 #endif
383         if ((net->cc_mod.rtcc.steady_step) && (inst_ind != SCTP_INST_LOOSING)) {
384                 if (net->cc_mod.rtcc.last_step_state == 5)
385                         net->cc_mod.rtcc.step_cnt++;
386                 else
387                         net->cc_mod.rtcc.step_cnt = 1;
388                 net->cc_mod.rtcc.last_step_state = 5;
389                 if ((net->cc_mod.rtcc.step_cnt == net->cc_mod.rtcc.steady_step) ||
390                     ((net->cc_mod.rtcc.step_cnt > net->cc_mod.rtcc.steady_step) &&
391                      ((net->cc_mod.rtcc.step_cnt % net->cc_mod.rtcc.steady_step) == 0))) {
392                         /* Try a step down */
393                         if (net->cwnd > (4 * net->mtu)) {
394                                 net->cwnd -= net->mtu;
395                                 net->cc_mod.rtcc.vol_reduce++;
396                                 return (1);
397                         } else {
398                                 net->cc_mod.rtcc.step_cnt = 0;
399                         }
400                 }
401         }
402         if (inst_ind == SCTP_INST_GAINING)
403                 return (1);
404         else if (inst_ind == SCTP_INST_NEUTRAL)
405                 return (1);
406         else
407                 return ((int)net->cc_mod.rtcc.ret_from_eq);
408 }
409
410 #if defined(__FreeBSD__) && !defined(__Userspace__)
411 static int
412 cc_bw_decrease(struct sctp_tcb *stcb, struct sctp_nets *net, uint64_t nbw, uint64_t rtt_offset,
413                uint64_t vtag, uint8_t inst_ind)
414 #else
415 static int
416 cc_bw_decrease(struct sctp_tcb *stcb SCTP_UNUSED, struct sctp_nets *net, uint64_t nbw, uint64_t rtt_offset,
417                uint8_t inst_ind)
418 #endif
419 {
420 #if defined(__FreeBSD__) && !defined(__Userspace__)
421         uint64_t oth, probepoint;
422 #endif
423
424         /* Bandwidth decreased.*/
425 #if defined(__FreeBSD__) && !defined(__Userspace__)
426         probepoint = (((uint64_t)net->cwnd) << 32);
427 #endif
428         if (net->rtt  > net->cc_mod.rtcc.lbw_rtt+rtt_offset) {
429                 /* rtt increased */
430                 /* Did we add more */
431                 if ((net->cwnd > net->cc_mod.rtcc.cwnd_at_bw_set) &&
432                     (inst_ind != SCTP_INST_LOOSING)) {
433                         /* We caused it maybe.. back off? */
434 #if defined(__FreeBSD__) && !defined(__Userspace__)
435                         /* PROBE POINT 1 */
436                         probepoint |=  ((1 << 16) | 1);
437                         SDT_PROBE5(sctp, cwnd, net, rttvar,
438                                   vtag,
439                                   ((net->cc_mod.rtcc.lbw << 32) | nbw),
440                                   ((net->cc_mod.rtcc.lbw_rtt << 32) | net->rtt),
441                                   net->flight_size,
442                                   probepoint);
443 #endif
444                         if (net->cc_mod.rtcc.ret_from_eq) {
445                                 /* Switch over to CA if we are less aggressive */
446                                 net->ssthresh = net->cwnd-1;
447                                 net->partial_bytes_acked = 0;
448                         }
449                         return (1);
450                 }
451 #if defined(__FreeBSD__) && !defined(__Userspace__)
452                 /* Probe point 2 */
453                 probepoint |=  ((2 << 16) | 0);
454                 SDT_PROBE5(sctp, cwnd, net, rttvar,
455                           vtag,
456                           ((net->cc_mod.rtcc.lbw << 32) | nbw),
457                           ((net->cc_mod.rtcc.lbw_rtt << 32) | net->rtt),
458                           net->flight_size,
459                           probepoint);
460 #endif
461                 /* Someone else - fight for more? */
462                 if (net->cc_mod.rtcc.steady_step) {
463 #if defined(__FreeBSD__) && !defined(__Userspace__)
464                         oth = net->cc_mod.rtcc.vol_reduce;
465                         oth <<= 16;
466                         oth |= net->cc_mod.rtcc.step_cnt;
467                         oth <<= 16;
468                         oth |= net->cc_mod.rtcc.last_step_state;
469                         SDT_PROBE5(sctp, cwnd, net, rttstep,
470                                   vtag,
471                                   ((net->cc_mod.rtcc.lbw << 32) | nbw),
472                                   ((net->cc_mod.rtcc.lbw_rtt << 32) | net->rtt),
473                                   oth,
474                                   probepoint);
475 #endif
476                         /* Did we voluntarily give up some? if so take
477                          * one back please
478                          */
479                         if ((net->cc_mod.rtcc.vol_reduce) &&
480                             (inst_ind != SCTP_INST_GAINING)) {
481                                 net->cwnd += net->mtu;
482                                 sctp_enforce_cwnd_limit(&stcb->asoc, net);
483                                 net->cc_mod.rtcc.vol_reduce--;
484                         }
485                         net->cc_mod.rtcc.last_step_state = 2;
486                         net->cc_mod.rtcc.step_cnt = 0;
487                 }
488                 goto out_decision;
489         } else  if (net->rtt  < net->cc_mod.rtcc.lbw_rtt-rtt_offset) {
490                 /* bw & rtt decreased */
491 #if defined(__FreeBSD__) && !defined(__Userspace__)
492                 /* Probe point 3 */
493                 probepoint |=  ((3 << 16) | 0);
494                 SDT_PROBE5(sctp, cwnd, net, rttvar,
495                           vtag,
496                           ((net->cc_mod.rtcc.lbw << 32) | nbw),
497                           ((net->cc_mod.rtcc.lbw_rtt << 32) | net->rtt),
498                           net->flight_size,
499                           probepoint);
500 #endif
501                 if (net->cc_mod.rtcc.steady_step) {
502 #if defined(__FreeBSD__) && !defined(__Userspace__)
503                         oth = net->cc_mod.rtcc.vol_reduce;
504                         oth <<= 16;
505                         oth |= net->cc_mod.rtcc.step_cnt;
506                         oth <<= 16;
507                         oth |= net->cc_mod.rtcc.last_step_state;
508                         SDT_PROBE5(sctp, cwnd, net, rttstep,
509                                   vtag,
510                                   ((net->cc_mod.rtcc.lbw << 32) | nbw),
511                                   ((net->cc_mod.rtcc.lbw_rtt << 32) | net->rtt),
512                                   oth,
513                                   probepoint);
514 #endif
515                         if ((net->cc_mod.rtcc.vol_reduce) &&
516                             (inst_ind != SCTP_INST_GAINING)) {
517                                 net->cwnd += net->mtu;
518                                 sctp_enforce_cwnd_limit(&stcb->asoc, net);
519                                 net->cc_mod.rtcc.vol_reduce--;
520                         }
521                         net->cc_mod.rtcc.last_step_state = 3;
522                         net->cc_mod.rtcc.step_cnt = 0;
523                 }
524                 goto out_decision;
525         }
526         /* The bw decreased but rtt stayed the same */
527 #if defined(__FreeBSD__) && !defined(__Userspace__)
528         /* Probe point 4 */
529         probepoint |=  ((4 << 16) | 0);
530         SDT_PROBE5(sctp, cwnd, net, rttvar,
531                   vtag,
532                   ((net->cc_mod.rtcc.lbw << 32) | nbw),
533                   ((net->cc_mod.rtcc.lbw_rtt << 32) | net->rtt),
534                   net->flight_size,
535                   probepoint);
536 #endif
537         if (net->cc_mod.rtcc.steady_step) {
538 #if defined(__FreeBSD__) && !defined(__Userspace__)
539                 oth = net->cc_mod.rtcc.vol_reduce;
540                 oth <<= 16;
541                 oth |= net->cc_mod.rtcc.step_cnt;
542                 oth <<= 16;
543                 oth |= net->cc_mod.rtcc.last_step_state;
544                 SDT_PROBE5(sctp, cwnd, net, rttstep,
545                           vtag,
546                           ((net->cc_mod.rtcc.lbw << 32) | nbw),
547                           ((net->cc_mod.rtcc.lbw_rtt << 32) | net->rtt),
548                           oth,
549                           probepoint);
550 #endif
551                 if ((net->cc_mod.rtcc.vol_reduce) &&
552                     (inst_ind != SCTP_INST_GAINING)) {
553                         net->cwnd += net->mtu;
554                         sctp_enforce_cwnd_limit(&stcb->asoc, net);
555                         net->cc_mod.rtcc.vol_reduce--;
556                 }
557                 net->cc_mod.rtcc.last_step_state = 4;
558                 net->cc_mod.rtcc.step_cnt = 0;
559         }
560 out_decision:
561         net->cc_mod.rtcc.lbw = nbw;
562         net->cc_mod.rtcc.lbw_rtt = net->rtt;
563         net->cc_mod.rtcc.cwnd_at_bw_set = net->cwnd;
564         if (inst_ind == SCTP_INST_GAINING) {
565                 return (1);
566         } else {
567                 return (0);
568         }
569 }
570
571 #if defined(__FreeBSD__) && !defined(__Userspace__)
572 static int
573 cc_bw_increase(struct sctp_tcb *stcb, struct sctp_nets *net, uint64_t nbw, uint64_t vtag)
574 #else
575 static int
576 cc_bw_increase(struct sctp_tcb *stcb SCTP_UNUSED, struct sctp_nets *net, uint64_t nbw)
577 #endif
578 {
579 #if defined(__FreeBSD__) && !defined(__Userspace__)
580         uint64_t oth, probepoint;
581
582 #endif
583         /* BW increased, so update and
584          * return 0, since all actions in
585          * our table say to do the normal CC
586          * update. Note that we pay no attention to
587          * the inst_ind since our overall sum is increasing.
588          */
589 #if defined(__FreeBSD__) && !defined(__Userspace__)
590         /* PROBE POINT 0 */
591         probepoint = (((uint64_t)net->cwnd) << 32);
592         SDT_PROBE5(sctp, cwnd, net, rttvar,
593                   vtag,
594                   ((net->cc_mod.rtcc.lbw << 32) | nbw),
595                   ((net->cc_mod.rtcc.lbw_rtt << 32) | net->rtt),
596                   net->flight_size,
597                   probepoint);
598 #endif
599         if (net->cc_mod.rtcc.steady_step) {
600 #if defined(__FreeBSD__) && !defined(__Userspace__)
601                 oth = net->cc_mod.rtcc.vol_reduce;
602                 oth <<= 16;
603                 oth |= net->cc_mod.rtcc.step_cnt;
604                 oth <<= 16;
605                 oth |= net->cc_mod.rtcc.last_step_state;
606                 SDT_PROBE5(sctp, cwnd, net, rttstep,
607                           vtag,
608                           ((net->cc_mod.rtcc.lbw << 32) | nbw),
609                           ((net->cc_mod.rtcc.lbw_rtt << 32) | net->rtt),
610                           oth,
611                           probepoint);
612 #endif
613                 net->cc_mod.rtcc.last_step_state = 0;
614                 net->cc_mod.rtcc.step_cnt = 0;
615                 net->cc_mod.rtcc.vol_reduce = 0;
616         }
617         net->cc_mod.rtcc.lbw = nbw;
618         net->cc_mod.rtcc.lbw_rtt = net->rtt;
619         net->cc_mod.rtcc.cwnd_at_bw_set = net->cwnd;
620         return (0);
621 }
622
623 /* RTCC Algorithm to limit growth of cwnd, return
624  * true if you want to NOT allow cwnd growth
625  */
626 static int
627 cc_bw_limit(struct sctp_tcb *stcb, struct sctp_nets *net, uint64_t nbw)
628 {
629         uint64_t bw_offset, rtt_offset;
630 #if defined(__FreeBSD__) && !defined(__Userspace__)
631         uint64_t probepoint, rtt, vtag;
632 #endif
633         uint64_t bytes_for_this_rtt, inst_bw;
634         uint64_t div, inst_off;
635         int bw_shift;
636         uint8_t inst_ind;
637         int ret;
638         /*-
639          * Here we need to see if we want
640          * to limit cwnd growth due to increase
641          * in overall rtt but no increase in bw.
642          * We use the following table to figure
643          * out what we should do. When we return
644          * 0, cc update goes on as planned. If we
645          * return 1, then no cc update happens and cwnd
646          * stays where it is at.
647          * ----------------------------------
648          *   BW    |    RTT   | Action
649          * *********************************
650          *   INC   |    INC   | return 0
651          * ----------------------------------
652          *   INC   |    SAME  | return 0
653          * ----------------------------------
654          *   INC   |    DECR  | return 0
655          * ----------------------------------
656          *   SAME  |    INC   | return 1
657          * ----------------------------------
658          *   SAME  |    SAME  | return 1
659          * ----------------------------------
660          *   SAME  |    DECR  | return 0
661          * ----------------------------------
662          *   DECR  |    INC   | return 0 or 1 based on if we caused.
663          * ----------------------------------
664          *   DECR  |    SAME  | return 0
665          * ----------------------------------
666          *   DECR  |    DECR  | return 0
667          * ----------------------------------
668          *
669          * We are a bit fuzz on what an increase or
670          * decrease is. For BW it is the same if
671          * it did not change within 1/64th. For
672          * RTT it stayed the same if it did not
673          * change within 1/32nd
674          */
675         bw_shift = SCTP_BASE_SYSCTL(sctp_rttvar_bw);
676 #if defined(__FreeBSD__) && !defined(__Userspace__)
677         rtt = stcb->asoc.my_vtag;
678         vtag = (rtt << 32) | (((uint32_t)(stcb->sctp_ep->sctp_lport)) << 16) | (stcb->rport);
679         probepoint = (((uint64_t)net->cwnd) << 32);
680         rtt = net->rtt;
681 #endif
682         if (net->cc_mod.rtcc.rtt_set_this_sack) {
683                 net->cc_mod.rtcc.rtt_set_this_sack = 0;
684                 bytes_for_this_rtt = net->cc_mod.rtcc.bw_bytes - net->cc_mod.rtcc.bw_bytes_at_last_rttc;
685                 net->cc_mod.rtcc.bw_bytes_at_last_rttc = net->cc_mod.rtcc.bw_bytes;
686                 if (net->rtt) {
687                         div = net->rtt / 1000;
688                         if (div) {
689                                 inst_bw = bytes_for_this_rtt / div;
690                                 inst_off = inst_bw >> bw_shift;
691                                 if (inst_bw > nbw)
692                                         inst_ind = SCTP_INST_GAINING;
693                                 else if ((inst_bw+inst_off) < nbw)
694                                         inst_ind = SCTP_INST_LOOSING;
695                                 else
696                                         inst_ind = SCTP_INST_NEUTRAL;
697 #if defined(__FreeBSD__) && !defined(__Userspace__)
698                                 probepoint |=  ((0xb << 16) | inst_ind);
699 #endif
700                         } else {
701                                 inst_ind = net->cc_mod.rtcc.last_inst_ind;
702 #if defined(__FreeBSD__) && !defined(__Userspace__)
703                                 inst_bw = bytes_for_this_rtt / (uint64_t)(net->rtt);
704                                 /* Can't determine do not change */
705                                 probepoint |=  ((0xc << 16) | inst_ind);
706 #endif
707                         }
708                 } else {
709                         inst_ind = net->cc_mod.rtcc.last_inst_ind;
710 #if defined(__FreeBSD__) && !defined(__Userspace__)
711                         inst_bw = bytes_for_this_rtt;
712                         /* Can't determine do not change */
713                         probepoint |=  ((0xd << 16) | inst_ind);
714 #endif
715                 }
716 #if defined(__FreeBSD__) && !defined(__Userspace__)
717                 SDT_PROBE5(sctp, cwnd, net, rttvar,
718                           vtag,
719                           ((nbw << 32) | inst_bw),
720                           ((net->cc_mod.rtcc.lbw_rtt << 32) | rtt),
721                           net->flight_size,
722                           probepoint);
723 #endif
724         } else {
725                 /* No rtt measurement, use last one */
726                 inst_ind = net->cc_mod.rtcc.last_inst_ind;
727         }
728         bw_offset = net->cc_mod.rtcc.lbw >> bw_shift;
729         if (nbw > net->cc_mod.rtcc.lbw + bw_offset) {
730 #if defined(__FreeBSD__) && !defined(__Userspace__)
731                 ret = cc_bw_increase(stcb, net, nbw, vtag);
732 #else
733                 ret = cc_bw_increase(stcb, net, nbw);
734 #endif
735                 goto out;
736         }
737         rtt_offset = net->cc_mod.rtcc.lbw_rtt >> SCTP_BASE_SYSCTL(sctp_rttvar_rtt);
738         if (nbw < net->cc_mod.rtcc.lbw - bw_offset) {
739 #if defined(__FreeBSD__) && !defined(__Userspace__)
740                 ret = cc_bw_decrease(stcb, net, nbw, rtt_offset, vtag, inst_ind);
741 #else
742                 ret = cc_bw_decrease(stcb, net, nbw, rtt_offset, inst_ind);
743 #endif
744                 goto out;
745         }
746         /* If we reach here then
747          * we are in a situation where
748          * the bw stayed the same.
749          */
750 #if defined(__FreeBSD__) && !defined(__Userspace__)
751         ret = cc_bw_same(stcb, net, nbw, rtt_offset, vtag, inst_ind);
752 #else
753         ret = cc_bw_same(stcb, net, nbw, rtt_offset, inst_ind);
754 #endif
755 out:
756         net->cc_mod.rtcc.last_inst_ind = inst_ind;
757         return (ret);
758 }
759
760 static void
761 sctp_cwnd_update_after_sack_common(struct sctp_tcb *stcb,
762                                    struct sctp_association *asoc,
763                                    int accum_moved, int reneged_all SCTP_UNUSED, int will_exit, int use_rtcc)
764 {
765         struct sctp_nets *net;
766 #if defined(__FreeBSD__) && !defined(__Userspace__)
767         int old_cwnd;
768 #endif
769         uint32_t t_ssthresh, t_cwnd, incr;
770         uint64_t t_ucwnd_sbw;
771         uint64_t t_path_mptcp;
772         uint64_t mptcp_like_alpha;
773         uint32_t srtt;
774         uint64_t max_path;
775
776         /* MT FIXME: Don't compute this over and over again */
777         t_ssthresh = 0;
778         t_cwnd = 0;
779         t_ucwnd_sbw = 0;
780         t_path_mptcp = 0;
781         mptcp_like_alpha = 1;
782         if ((stcb->asoc.sctp_cmt_on_off == SCTP_CMT_RPV1) ||
783             (stcb->asoc.sctp_cmt_on_off == SCTP_CMT_RPV2) ||
784             (stcb->asoc.sctp_cmt_on_off == SCTP_CMT_MPTCP)) {
785                 max_path = 0;
786                 TAILQ_FOREACH(net, &stcb->asoc.nets, sctp_next) {
787                         t_ssthresh += net->ssthresh;
788                         t_cwnd += net->cwnd;
789                         /* lastsa>>3;  we don't need to devide ...*/
790                         srtt = net->lastsa;
791                         if (srtt > 0) {
792                                 uint64_t tmp;
793
794                                 t_ucwnd_sbw += (uint64_t)net->cwnd / (uint64_t)srtt;
795                                 t_path_mptcp += (((uint64_t)net->cwnd) << SHIFT_MPTCP_MULTI_Z) /
796                                                 (((uint64_t)net->mtu) * (uint64_t)srtt);
797                                 tmp = (((uint64_t)net->cwnd) << SHIFT_MPTCP_MULTI_N) /
798                                       ((uint64_t)net->mtu * (uint64_t)(srtt * srtt));
799                                 if (tmp > max_path) {
800                                         max_path = tmp;
801                                 }
802                         }
803                 }
804                 if (t_path_mptcp > 0) {
805                         mptcp_like_alpha = max_path / (t_path_mptcp * t_path_mptcp);
806                 } else {
807                         mptcp_like_alpha = 1;
808                 }
809         }
810         if (t_ssthresh == 0) {
811                 t_ssthresh = 1;
812         }
813         if (t_ucwnd_sbw == 0) {
814                 t_ucwnd_sbw = 1;
815         }
816         /******************************/
817         /* update cwnd and Early FR   */
818         /******************************/
819         TAILQ_FOREACH(net, &asoc->nets, sctp_next) {
820
821 #ifdef JANA_CMT_FAST_RECOVERY
822                 /*
823                  * CMT fast recovery code. Need to debug.
824                  */
825                 if (net->fast_retran_loss_recovery && net->new_pseudo_cumack) {
826                         if (SCTP_TSN_GE(asoc->last_acked_seq, net->fast_recovery_tsn) ||
827                             SCTP_TSN_GE(net->pseudo_cumack,net->fast_recovery_tsn)) {
828                                 net->will_exit_fast_recovery = 1;
829                         }
830                 }
831 #endif
832                 /* if nothing was acked on this destination skip it */
833                 if (net->net_ack == 0) {
834                         if (SCTP_BASE_SYSCTL(sctp_logging_level) & SCTP_CWND_LOGGING_ENABLE) {
835                                 sctp_log_cwnd(stcb, net, 0, SCTP_CWND_LOG_FROM_SACK);
836                         }
837                         continue;
838                 }
839 #ifdef JANA_CMT_FAST_RECOVERY
840                 /* CMT fast recovery code
841                  */
842                 /*
843                   if (sctp_cmt_on_off > 0 && net->fast_retran_loss_recovery && net->will_exit_fast_recovery == 0) {
844                   @@@ Do something
845                   }
846                   else if (sctp_cmt_on_off == 0 && asoc->fast_retran_loss_recovery && will_exit == 0) {
847                 */
848 #endif
849
850                 if (asoc->fast_retran_loss_recovery &&
851                     (will_exit == 0) &&
852                     (asoc->sctp_cmt_on_off == 0)) {
853                         /*
854                          * If we are in loss recovery we skip any cwnd
855                          * update
856                          */
857                         return;
858                 }
859                 /*
860                  * Did any measurements go on for this network?
861                  */
862                 if (use_rtcc && (net->cc_mod.rtcc.tls_needs_set > 0)) {
863                         uint64_t nbw;
864                         /*
865                          * At this point our bw_bytes has been updated
866                          * by incoming sack information.
867                          *
868                          * But our bw may not yet be set.
869                          *
870                          */
871                         if ((net->cc_mod.rtcc.new_tot_time/1000) > 0) {
872                                 nbw = net->cc_mod.rtcc.bw_bytes/(net->cc_mod.rtcc.new_tot_time/1000);
873                         } else {
874                                 nbw = net->cc_mod.rtcc.bw_bytes;
875                         }
876                         if (net->cc_mod.rtcc.lbw) {
877                                 if (cc_bw_limit(stcb, net, nbw)) {
878                                         /* Hold here, no update */
879                                         continue;
880                                 }
881                         } else {
882 #if defined(__FreeBSD__) && !defined(__Userspace__)
883                                 uint64_t vtag, probepoint;
884
885                                 probepoint = (((uint64_t)net->cwnd) << 32);
886                                 probepoint |=  ((0xa << 16) | 0);
887                                 vtag = (net->rtt << 32) |
888                                         (((uint32_t)(stcb->sctp_ep->sctp_lport)) << 16) |
889                                         (stcb->rport);
890
891                                 SDT_PROBE5(sctp, cwnd, net, rttvar,
892                                           vtag,
893                                           nbw,
894                                           ((net->cc_mod.rtcc.lbw_rtt << 32) | net->rtt),
895                                           net->flight_size,
896                                           probepoint);
897 #endif
898                                 net->cc_mod.rtcc.lbw = nbw;
899                                 net->cc_mod.rtcc.lbw_rtt = net->rtt;
900                                 if (net->cc_mod.rtcc.rtt_set_this_sack) {
901                                         net->cc_mod.rtcc.rtt_set_this_sack = 0;
902                                         net->cc_mod.rtcc.bw_bytes_at_last_rttc = net->cc_mod.rtcc.bw_bytes;
903                                 }
904                         }
905                 }
906                 /*
907                  * CMT: CUC algorithm. Update cwnd if pseudo-cumack has
908                  * moved.
909                  */
910                 if (accum_moved ||
911                     ((asoc->sctp_cmt_on_off > 0) && net->new_pseudo_cumack)) {
912                         /* If the cumulative ack moved we can proceed */
913                         if (net->cwnd <= net->ssthresh) {
914                                 /* We are in slow start */
915                                 if (net->flight_size + net->net_ack >= net->cwnd) {
916                                         uint32_t limit;
917
918 #if defined(__FreeBSD__) && !defined(__Userspace__)
919                                         old_cwnd = net->cwnd;
920 #endif
921                                         switch (asoc->sctp_cmt_on_off) {
922                                         case SCTP_CMT_RPV1:
923                                                 limit = (uint32_t)(((uint64_t)net->mtu *
924                                                                     (uint64_t)SCTP_BASE_SYSCTL(sctp_L2_abc_variable) *
925                                                                     (uint64_t)net->ssthresh) /
926                                                                    (uint64_t)t_ssthresh);
927                                                 incr = (uint32_t)(((uint64_t)net->net_ack *
928                                                                    (uint64_t)net->ssthresh) /
929                                                                   (uint64_t)t_ssthresh);
930                                                 if (incr > limit) {
931                                                         incr = limit;
932                                                 }
933                                                 if (incr == 0) {
934                                                         incr = 1;
935                                                 }
936                                                 break;
937                                         case SCTP_CMT_RPV2:
938                                                 /* lastsa>>3;  we don't need to divide ...*/
939                                                 srtt = net->lastsa;
940                                                 if (srtt == 0) {
941                                                         srtt = 1;
942                                                 }
943                                                 limit = (uint32_t)(((uint64_t)net->mtu *
944                                                                     (uint64_t)SCTP_BASE_SYSCTL(sctp_L2_abc_variable) *
945                                                                     (uint64_t)net->cwnd) /
946                                                                    ((uint64_t)srtt * t_ucwnd_sbw));
947                                                                    /* INCREASE FACTOR */
948                                                 incr = (uint32_t)(((uint64_t)net->net_ack *
949                                                                    (uint64_t)net->cwnd) /
950                                                                   ((uint64_t)srtt * t_ucwnd_sbw));
951                                                                   /* INCREASE FACTOR */
952                                                 if (incr > limit) {
953                                                         incr = limit;
954                                                 }
955                                                 if (incr == 0) {
956                                                         incr = 1;
957                                                 }
958                                                 break;
959                                         case SCTP_CMT_MPTCP:
960                                                 limit = (uint32_t)(((uint64_t)net->mtu *
961                                                                     mptcp_like_alpha *
962                                                                     (uint64_t)SCTP_BASE_SYSCTL(sctp_L2_abc_variable)) >>
963                                                                    SHIFT_MPTCP_MULTI);
964                                                 incr  = (uint32_t)(((uint64_t)net->net_ack *
965                                                                     mptcp_like_alpha) >>
966                                                                    SHIFT_MPTCP_MULTI);
967                                                 if (incr > limit) {
968                                                         incr = limit;
969                                                 }
970                                                 if (incr > net->net_ack) {
971                                                         incr = net->net_ack;
972                                                 }
973                                                 if (incr > net->mtu) {
974                                                         incr = net->mtu;
975                                                 }
976                                                 break;
977                                         default:
978                                                 incr = net->net_ack;
979                                                 if (incr > net->mtu * SCTP_BASE_SYSCTL(sctp_L2_abc_variable)) {
980                                                         incr = net->mtu * SCTP_BASE_SYSCTL(sctp_L2_abc_variable);
981                                                 }
982                                                 break;
983                                         }
984                                         net->cwnd += incr;
985                                         sctp_enforce_cwnd_limit(asoc, net);
986                                         if (SCTP_BASE_SYSCTL(sctp_logging_level) & SCTP_CWND_MONITOR_ENABLE) {
987                                                 sctp_log_cwnd(stcb, net, incr,
988                                                               SCTP_CWND_LOG_FROM_SS);
989                                         }
990 #if defined(__FreeBSD__) && !defined(__Userspace__)
991                                         SDT_PROBE5(sctp, cwnd, net, ack,
992                                                   stcb->asoc.my_vtag,
993                                                   ((stcb->sctp_ep->sctp_lport << 16) | (stcb->rport)),
994                                                   net,
995                                                   old_cwnd, net->cwnd);
996 #endif
997                                 } else {
998                                         if (SCTP_BASE_SYSCTL(sctp_logging_level) & SCTP_CWND_LOGGING_ENABLE) {
999                                                 sctp_log_cwnd(stcb, net, net->net_ack,
1000                                                               SCTP_CWND_LOG_NOADV_SS);
1001                                         }
1002                                 }
1003                         } else {
1004                                 /* We are in congestion avoidance */
1005                                 /*
1006                                  * Add to pba
1007                                  */
1008                                 net->partial_bytes_acked += net->net_ack;
1009
1010                                 if ((net->flight_size + net->net_ack >= net->cwnd) &&
1011                                     (net->partial_bytes_acked >= net->cwnd)) {
1012                                         net->partial_bytes_acked -= net->cwnd;
1013 #if defined(__FreeBSD__) && !defined(__Userspace__)
1014                                         old_cwnd = net->cwnd;
1015 #endif
1016                                         switch (asoc->sctp_cmt_on_off) {
1017                                         case SCTP_CMT_RPV1:
1018                                                 incr = (uint32_t)(((uint64_t)net->mtu *
1019                                                                    (uint64_t)net->ssthresh) /
1020                                                                   (uint64_t)t_ssthresh);
1021                                                 if (incr == 0) {
1022                                                         incr = 1;
1023                                                 }
1024                                                 break;
1025                                         case SCTP_CMT_RPV2:
1026                                                 /* lastsa>>3;  we don't need to divide ... */
1027                                                 srtt = net->lastsa;
1028                                                 if (srtt == 0) {
1029                                                         srtt = 1;
1030                                                 }
1031                                                 incr = (uint32_t)((uint64_t)net->mtu *
1032                                                                   (uint64_t)net->cwnd /
1033                                                                   ((uint64_t)srtt *
1034                                                                    t_ucwnd_sbw));
1035                                                                   /* INCREASE FACTOR */
1036                                                 if (incr == 0) {
1037                                                         incr = 1;
1038                                                 }
1039                                                 break;
1040                                         case SCTP_CMT_MPTCP:
1041                                                 incr = (uint32_t)((mptcp_like_alpha *
1042                                                                    (uint64_t) net->cwnd) >>
1043                                                                   SHIFT_MPTCP_MULTI);
1044                                                 if (incr > net->mtu) {
1045                                                         incr = net->mtu;
1046                                                 }
1047                                                 break;
1048                                         default:
1049                                                 incr = net->mtu;
1050                                                 break;
1051                                         }
1052                                         net->cwnd += incr;
1053                                         sctp_enforce_cwnd_limit(asoc, net);
1054 #if defined(__FreeBSD__) && !defined(__Userspace__)
1055                                         SDT_PROBE5(sctp, cwnd, net, ack,
1056                                                   stcb->asoc.my_vtag,
1057                                                   ((stcb->sctp_ep->sctp_lport << 16) | (stcb->rport)),
1058                                                   net,
1059                                                   old_cwnd, net->cwnd);
1060 #endif
1061                                         if (SCTP_BASE_SYSCTL(sctp_logging_level) & SCTP_CWND_MONITOR_ENABLE) {
1062                                                 sctp_log_cwnd(stcb, net, net->mtu,
1063                                                               SCTP_CWND_LOG_FROM_CA);
1064                                         }
1065                                 } else {
1066                                         if (SCTP_BASE_SYSCTL(sctp_logging_level) & SCTP_CWND_LOGGING_ENABLE) {
1067                                                 sctp_log_cwnd(stcb, net, net->net_ack,
1068                                                               SCTP_CWND_LOG_NOADV_CA);
1069                                         }
1070                                 }
1071                         }
1072                 } else {
1073                         if (SCTP_BASE_SYSCTL(sctp_logging_level) & SCTP_CWND_LOGGING_ENABLE) {
1074                                 sctp_log_cwnd(stcb, net, net->mtu,
1075                                               SCTP_CWND_LOG_NO_CUMACK);
1076                         }
1077                 }
1078         }
1079 }
1080
1081 #if defined(__FreeBSD__) && !defined(__Userspace__)
1082 static void
1083 sctp_cwnd_update_exit_pf_common(struct sctp_tcb *stcb, struct sctp_nets *net)
1084 #else
1085 static void
1086 sctp_cwnd_update_exit_pf_common(struct sctp_tcb *stcb SCTP_UNUSED, struct sctp_nets *net)
1087 #endif
1088 {
1089 #if defined(__FreeBSD__) && !defined(__Userspace__)
1090         int old_cwnd;
1091
1092         old_cwnd = net->cwnd;
1093 #endif
1094         net->cwnd = net->mtu;
1095 #if defined(__FreeBSD__) && !defined(__Userspace__)
1096         SDT_PROBE5(sctp, cwnd, net, ack,
1097                   stcb->asoc.my_vtag, ((stcb->sctp_ep->sctp_lport << 16) | (stcb->rport)), net,
1098                   old_cwnd, net->cwnd);
1099 #endif
1100         SCTPDBG(SCTP_DEBUG_INDATA1, "Destination %p moved from PF to reachable with cwnd %d.\n",
1101                 (void *)net, net->cwnd);
1102 }
1103
1104
1105 static void
1106 sctp_cwnd_update_after_timeout(struct sctp_tcb *stcb, struct sctp_nets *net)
1107 {
1108         int old_cwnd = net->cwnd;
1109         uint32_t t_ssthresh, t_cwnd;
1110         uint64_t t_ucwnd_sbw;
1111
1112         /* MT FIXME: Don't compute this over and over again */
1113         t_ssthresh = 0;
1114         t_cwnd = 0;
1115         if ((stcb->asoc.sctp_cmt_on_off == SCTP_CMT_RPV1) ||
1116             (stcb->asoc.sctp_cmt_on_off == SCTP_CMT_RPV2)) {
1117                 struct sctp_nets *lnet;
1118                 uint32_t srtt;
1119
1120                 t_ucwnd_sbw = 0;
1121                 TAILQ_FOREACH(lnet, &stcb->asoc.nets, sctp_next) {
1122                         t_ssthresh += lnet->ssthresh;
1123                         t_cwnd += lnet->cwnd;
1124                         srtt = lnet->lastsa;
1125                         /* lastsa>>3;  we don't need to divide ... */
1126                         if (srtt > 0) {
1127                                 t_ucwnd_sbw += (uint64_t)lnet->cwnd / (uint64_t)srtt;
1128                         }
1129                 }
1130                 if (t_ssthresh < 1) {
1131                         t_ssthresh = 1;
1132                 }
1133                 if (t_ucwnd_sbw < 1) {
1134                         t_ucwnd_sbw = 1;
1135                 }
1136                 if (stcb->asoc.sctp_cmt_on_off == SCTP_CMT_RPV1) {
1137                         net->ssthresh = (uint32_t)(((uint64_t)4 *
1138                                                     (uint64_t)net->mtu *
1139                                                     (uint64_t)net->ssthresh) /
1140                                                    (uint64_t)t_ssthresh);
1141                 } else {
1142                         uint64_t cc_delta;
1143
1144                         srtt = net->lastsa;
1145                         /* lastsa>>3;  we don't need to divide ... */
1146                         if (srtt == 0) {
1147                                 srtt = 1;
1148                         }
1149                         cc_delta = t_ucwnd_sbw * (uint64_t)srtt / 2;
1150                         if (cc_delta < t_cwnd) {
1151                                 net->ssthresh = (uint32_t)((uint64_t)t_cwnd - cc_delta);
1152                         } else {
1153                                 net->ssthresh  = net->mtu;
1154                         }
1155                 }
1156                 if ((net->cwnd > t_cwnd / 2) &&
1157                     (net->ssthresh < net->cwnd - t_cwnd / 2)) {
1158                         net->ssthresh = net->cwnd - t_cwnd / 2;
1159                 }
1160                 if (net->ssthresh < net->mtu) {
1161                         net->ssthresh = net->mtu;
1162                 }
1163         } else {
1164                 net->ssthresh = max(net->cwnd / 2, 4 * net->mtu);
1165         }
1166         net->cwnd = net->mtu;
1167         net->partial_bytes_acked = 0;
1168 #if defined(__FreeBSD__) && !defined(__Userspace__)
1169         SDT_PROBE5(sctp, cwnd, net, to,
1170                   stcb->asoc.my_vtag,
1171                   ((stcb->sctp_ep->sctp_lport << 16) | (stcb->rport)),
1172                   net,
1173                   old_cwnd, net->cwnd);
1174 #endif
1175         if (SCTP_BASE_SYSCTL(sctp_logging_level) & SCTP_CWND_MONITOR_ENABLE) {
1176                 sctp_log_cwnd(stcb, net, net->cwnd - old_cwnd, SCTP_CWND_LOG_FROM_RTX);
1177         }
1178 }
1179
1180 static void
1181 sctp_cwnd_update_after_ecn_echo_common(struct sctp_tcb *stcb, struct sctp_nets *net,
1182                                             int in_window, int num_pkt_lost, int use_rtcc)
1183 {
1184         int old_cwnd = net->cwnd;
1185         if ((use_rtcc) && (net->lan_type == SCTP_LAN_LOCAL) && (net->cc_mod.rtcc.use_dccc_ecn)) {
1186                 /* Data center Congestion Control */
1187                 if (in_window == 0) {
1188                         /* Go to CA with the cwnd at the point we sent
1189                          * the TSN that was marked with a CE.
1190                          */
1191                         if (net->ecn_prev_cwnd < net->cwnd) {
1192                                 /* Restore to prev cwnd */
1193                                 net->cwnd = net->ecn_prev_cwnd - (net->mtu * num_pkt_lost);
1194                         } else {
1195                                 /* Just cut in 1/2 */
1196                                 net->cwnd /= 2;
1197                         }
1198                         /* Drop to CA */
1199                         net->ssthresh = net->cwnd - (num_pkt_lost * net->mtu);
1200                         if (SCTP_BASE_SYSCTL(sctp_logging_level) & SCTP_CWND_MONITOR_ENABLE) {
1201                                 sctp_log_cwnd(stcb, net, (net->cwnd - old_cwnd), SCTP_CWND_LOG_FROM_SAT);
1202                         }
1203                 } else {
1204                         /* Further tuning down required over the drastic original cut */
1205                         net->ssthresh -= (net->mtu * num_pkt_lost);
1206                         net->cwnd -= (net->mtu * num_pkt_lost);
1207                         if (SCTP_BASE_SYSCTL(sctp_logging_level) & SCTP_CWND_MONITOR_ENABLE) {
1208                                 sctp_log_cwnd(stcb, net, (net->cwnd - old_cwnd), SCTP_CWND_LOG_FROM_SAT);
1209                         }
1210
1211                 }
1212                 SCTP_STAT_INCR(sctps_ecnereducedcwnd);
1213         }  else {
1214                 if (in_window == 0) {
1215                         SCTP_STAT_INCR(sctps_ecnereducedcwnd);
1216                         net->ssthresh = net->cwnd / 2;
1217                         if (net->ssthresh < net->mtu) {
1218                                 net->ssthresh = net->mtu;
1219                                 /* here back off the timer as well, to slow us down */
1220                                 net->RTO <<= 1;
1221                         }
1222                         net->cwnd = net->ssthresh;
1223 #if defined(__FreeBSD__) && !defined(__Userspace__)
1224                         SDT_PROBE5(sctp, cwnd, net, ecn,
1225                                   stcb->asoc.my_vtag,
1226                                   ((stcb->sctp_ep->sctp_lport << 16) | (stcb->rport)),
1227                                   net,
1228                                   old_cwnd, net->cwnd);
1229 #endif
1230                         if (SCTP_BASE_SYSCTL(sctp_logging_level) & SCTP_CWND_MONITOR_ENABLE) {
1231                                 sctp_log_cwnd(stcb, net, (net->cwnd - old_cwnd), SCTP_CWND_LOG_FROM_SAT);
1232                         }
1233                 }
1234         }
1235
1236 }
1237
1238 static void
1239 sctp_cwnd_update_after_packet_dropped(struct sctp_tcb *stcb,
1240         struct sctp_nets *net, struct sctp_pktdrop_chunk *cp,
1241         uint32_t *bottle_bw, uint32_t *on_queue)
1242 {
1243         uint32_t bw_avail;
1244         unsigned int incr;
1245         int old_cwnd = net->cwnd;
1246
1247         /* get bottle neck bw */
1248         *bottle_bw = ntohl(cp->bottle_bw);
1249         /* and whats on queue */
1250         *on_queue = ntohl(cp->current_onq);
1251         /*
1252          * adjust the on-queue if our flight is more it could be
1253          * that the router has not yet gotten data "in-flight" to it
1254          */
1255         if (*on_queue < net->flight_size) {
1256                 *on_queue = net->flight_size;
1257         }
1258         /* rtt is measured in micro seconds, bottle_bw in bytes per second */
1259         bw_avail = (uint32_t)(((uint64_t)(*bottle_bw) * net->rtt) / (uint64_t)1000000);
1260         if (bw_avail > *bottle_bw) {
1261                 /*
1262                  * Cap the growth to no more than the bottle neck.
1263                  * This can happen as RTT slides up due to queues.
1264                  * It also means if you have more than a 1 second
1265                  * RTT with a empty queue you will be limited to the
1266                  * bottle_bw per second no matter if other points
1267                  * have 1/2 the RTT and you could get more out...
1268                  */
1269                 bw_avail = *bottle_bw;
1270         }
1271         if (*on_queue > bw_avail) {
1272                 /*
1273                  * No room for anything else don't allow anything
1274                  * else to be "added to the fire".
1275                  */
1276                 int seg_inflight, seg_onqueue, my_portion;
1277
1278                 net->partial_bytes_acked = 0;
1279                 /* how much are we over queue size? */
1280                 incr = *on_queue - bw_avail;
1281                 if (stcb->asoc.seen_a_sack_this_pkt) {
1282                         /*
1283                          * undo any cwnd adjustment that the sack
1284                          * might have made
1285                          */
1286                         net->cwnd = net->prev_cwnd;
1287                 }
1288                 /* Now how much of that is mine? */
1289                 seg_inflight = net->flight_size / net->mtu;
1290                 seg_onqueue = *on_queue / net->mtu;
1291                 my_portion = (incr * seg_inflight) / seg_onqueue;
1292
1293                 /* Have I made an adjustment already */
1294                 if (net->cwnd > net->flight_size) {
1295                         /*
1296                          * for this flight I made an adjustment we
1297                          * need to decrease the portion by a share
1298                          * our previous adjustment.
1299                          */
1300                         int diff_adj;
1301
1302                         diff_adj = net->cwnd - net->flight_size;
1303                         if (diff_adj > my_portion)
1304                                 my_portion = 0;
1305                         else
1306                                 my_portion -= diff_adj;
1307                 }
1308                 /*
1309                  * back down to the previous cwnd (assume we have
1310                  * had a sack before this packet). minus what ever
1311                  * portion of the overage is my fault.
1312                  */
1313                 net->cwnd -= my_portion;
1314
1315                 /* we will NOT back down more than 1 MTU */
1316                 if (net->cwnd <= net->mtu) {
1317                         net->cwnd = net->mtu;
1318                 }
1319                 /* force into CA */
1320                 net->ssthresh = net->cwnd - 1;
1321         } else {
1322                 /*
1323                  * Take 1/4 of the space left or max burst up ..
1324                  * whichever is less.
1325                  */
1326                 incr = (bw_avail - *on_queue) >> 2;
1327                 if ((stcb->asoc.max_burst > 0) &&
1328                     (stcb->asoc.max_burst * net->mtu < incr)) {
1329                         incr = stcb->asoc.max_burst * net->mtu;
1330                 }
1331                 net->cwnd += incr;
1332         }
1333         if (net->cwnd > bw_avail) {
1334                 /* We can't exceed the pipe size */
1335                 net->cwnd = bw_avail;
1336         }
1337         if (net->cwnd < net->mtu) {
1338                 /* We always have 1 MTU */
1339                 net->cwnd = net->mtu;
1340         }
1341         sctp_enforce_cwnd_limit(&stcb->asoc, net);
1342         if (net->cwnd - old_cwnd != 0) {
1343                 /* log only changes */
1344 #if defined(__FreeBSD__) && !defined(__Userspace__)
1345                 SDT_PROBE5(sctp, cwnd, net, pd,
1346                           stcb->asoc.my_vtag,
1347                           ((stcb->sctp_ep->sctp_lport << 16) | (stcb->rport)),
1348                           net,
1349                           old_cwnd, net->cwnd);
1350 #endif
1351                 if (SCTP_BASE_SYSCTL(sctp_logging_level) & SCTP_CWND_MONITOR_ENABLE) {
1352                         sctp_log_cwnd(stcb, net, (net->cwnd - old_cwnd),
1353                                 SCTP_CWND_LOG_FROM_SAT);
1354                 }
1355         }
1356 }
1357
1358 static void
1359 sctp_cwnd_update_after_output(struct sctp_tcb *stcb,
1360                               struct sctp_nets *net, int burst_limit)
1361 {
1362         int old_cwnd = net->cwnd;
1363
1364         if (net->ssthresh < net->cwnd)
1365                 net->ssthresh = net->cwnd;
1366         if (burst_limit) {
1367                 net->cwnd = (net->flight_size + (burst_limit * net->mtu));
1368                 sctp_enforce_cwnd_limit(&stcb->asoc, net);
1369 #if defined(__FreeBSD__) && !defined(__Userspace__)
1370                 SDT_PROBE5(sctp, cwnd, net, bl,
1371                           stcb->asoc.my_vtag,
1372                           ((stcb->sctp_ep->sctp_lport << 16) | (stcb->rport)),
1373                           net,
1374                           old_cwnd, net->cwnd);
1375 #endif
1376                 if (SCTP_BASE_SYSCTL(sctp_logging_level) & SCTP_CWND_MONITOR_ENABLE) {
1377                         sctp_log_cwnd(stcb, net, (net->cwnd - old_cwnd), SCTP_CWND_LOG_FROM_BRST);
1378                 }
1379         }
1380 }
1381
1382 static void
1383 sctp_cwnd_update_after_sack(struct sctp_tcb *stcb,
1384                             struct sctp_association *asoc,
1385                             int accum_moved, int reneged_all, int will_exit)
1386 {
1387         /* Passing a zero argument in last disables the rtcc algorithm */
1388         sctp_cwnd_update_after_sack_common(stcb, asoc, accum_moved, reneged_all, will_exit, 0);
1389 }
1390
1391 static void
1392 sctp_cwnd_update_after_ecn_echo(struct sctp_tcb *stcb, struct sctp_nets *net,
1393         int in_window, int num_pkt_lost)
1394 {
1395         /* Passing a zero argument in last disables the rtcc algorithm */
1396         sctp_cwnd_update_after_ecn_echo_common(stcb, net, in_window, num_pkt_lost, 0);
1397 }
1398
1399 /* Here starts the RTCCVAR type CC invented by RRS which
1400  * is a slight mod to RFC2581. We reuse a common routine or
1401  * two since these algorithms are so close and need to
1402  * remain the same.
1403  */
1404 static void
1405 sctp_cwnd_update_rtcc_after_ecn_echo(struct sctp_tcb *stcb, struct sctp_nets *net,
1406                                      int in_window, int num_pkt_lost)
1407 {
1408         sctp_cwnd_update_after_ecn_echo_common(stcb, net, in_window, num_pkt_lost, 1);
1409 }
1410
1411
1412 static
1413 void sctp_cwnd_update_rtcc_tsn_acknowledged(struct sctp_nets *net,
1414                                             struct sctp_tmit_chunk *tp1)
1415 {
1416         net->cc_mod.rtcc.bw_bytes += tp1->send_size;
1417 }
1418
1419 static void
1420 sctp_cwnd_prepare_rtcc_net_for_sack(struct sctp_tcb *stcb SCTP_UNUSED,
1421                                     struct sctp_nets *net)
1422 {
1423         if (net->cc_mod.rtcc.tls_needs_set > 0) {
1424                 /* We had a bw measurment going on */
1425                 struct timeval ltls;
1426                 SCTP_GETPTIME_TIMEVAL(&ltls);
1427                 timevalsub(&ltls, &net->cc_mod.rtcc.tls);
1428                 net->cc_mod.rtcc.new_tot_time = (ltls.tv_sec * 1000000) + ltls.tv_usec;
1429         }
1430 }
1431
1432 static void
1433 sctp_cwnd_new_rtcc_transmission_begins(struct sctp_tcb *stcb,
1434                                        struct sctp_nets *net)
1435 {
1436 #if defined(__FreeBSD__) && !defined(__Userspace__)
1437         uint64_t vtag, probepoint;
1438
1439 #endif
1440         if (net->cc_mod.rtcc.lbw) {
1441 #if defined(__FreeBSD__) && !defined(__Userspace__)
1442                 /* Clear the old bw.. we went to 0 in-flight */
1443                 vtag = (net->rtt << 32) | (((uint32_t)(stcb->sctp_ep->sctp_lport)) << 16) |
1444                         (stcb->rport);
1445                 probepoint = (((uint64_t)net->cwnd) << 32);
1446                 /* Probe point 8 */
1447                 probepoint |=  ((8 << 16) | 0);
1448                 SDT_PROBE5(sctp, cwnd, net, rttvar,
1449                           vtag,
1450                           ((net->cc_mod.rtcc.lbw << 32) | 0),
1451                           ((net->cc_mod.rtcc.lbw_rtt << 32) | net->rtt),
1452                           net->flight_size,
1453                           probepoint);
1454 #endif
1455                 net->cc_mod.rtcc.lbw_rtt = 0;
1456                 net->cc_mod.rtcc.cwnd_at_bw_set = 0;
1457                 net->cc_mod.rtcc.lbw = 0;
1458                 net->cc_mod.rtcc.bw_bytes_at_last_rttc = 0;
1459                 net->cc_mod.rtcc.vol_reduce = 0;
1460                 net->cc_mod.rtcc.bw_tot_time = 0;
1461                 net->cc_mod.rtcc.bw_bytes = 0;
1462                 net->cc_mod.rtcc.tls_needs_set = 0;
1463                 if (net->cc_mod.rtcc.steady_step) {
1464                         net->cc_mod.rtcc.vol_reduce = 0;
1465                         net->cc_mod.rtcc.step_cnt = 0;
1466                         net->cc_mod.rtcc.last_step_state = 0;
1467                 }
1468                 if (net->cc_mod.rtcc.ret_from_eq) {
1469                         /* less aggressive one - reset cwnd too */
1470                         uint32_t cwnd_in_mtu, cwnd;
1471
1472                         cwnd_in_mtu = SCTP_BASE_SYSCTL(sctp_initial_cwnd);
1473                         if (cwnd_in_mtu == 0) {
1474                                 /* Using 0 means that the value of RFC 4960 is used. */
1475                                 cwnd = min((net->mtu * 4), max((2 * net->mtu), SCTP_INITIAL_CWND));
1476                         } else {
1477                                 /*
1478                                  * We take the minimum of the burst limit and the
1479                                  * initial congestion window.
1480                                  */
1481                                 if ((stcb->asoc.max_burst > 0) && (cwnd_in_mtu > stcb->asoc.max_burst))
1482                                         cwnd_in_mtu = stcb->asoc.max_burst;
1483                                 cwnd = (net->mtu - sizeof(struct sctphdr)) * cwnd_in_mtu;
1484                         }
1485                         if (net->cwnd > cwnd) {
1486                                 /* Only set if we are not a timeout (i.e. down to 1 mtu) */
1487                                 net->cwnd = cwnd;
1488                         }
1489                 }
1490         }
1491 }
1492
1493 static void
1494 sctp_set_rtcc_initial_cc_param(struct sctp_tcb *stcb,
1495                                struct sctp_nets *net)
1496 {
1497 #if defined(__FreeBSD__) && !defined(__Userspace__)
1498         uint64_t vtag, probepoint;
1499
1500 #endif
1501         sctp_set_initial_cc_param(stcb, net);
1502         stcb->asoc.use_precise_time = 1;
1503 #if defined(__FreeBSD__) && !defined(__Userspace__)
1504         probepoint = (((uint64_t)net->cwnd) << 32);
1505         probepoint |=  ((9 << 16) | 0);
1506         vtag = (net->rtt << 32) |
1507                 (((uint32_t)(stcb->sctp_ep->sctp_lport)) << 16) |
1508                 (stcb->rport);
1509         SDT_PROBE5(sctp, cwnd, net, rttvar,
1510                   vtag,
1511                   0,
1512                   0,
1513                   0,
1514                   probepoint);
1515 #endif
1516         net->cc_mod.rtcc.lbw_rtt = 0;
1517         net->cc_mod.rtcc.cwnd_at_bw_set = 0;
1518         net->cc_mod.rtcc.vol_reduce = 0;
1519         net->cc_mod.rtcc.lbw = 0;
1520         net->cc_mod.rtcc.vol_reduce = 0;
1521         net->cc_mod.rtcc.bw_bytes_at_last_rttc = 0;
1522         net->cc_mod.rtcc.bw_tot_time = 0;
1523         net->cc_mod.rtcc.bw_bytes = 0;
1524         net->cc_mod.rtcc.tls_needs_set = 0;
1525         net->cc_mod.rtcc.ret_from_eq = SCTP_BASE_SYSCTL(sctp_rttvar_eqret);
1526         net->cc_mod.rtcc.steady_step = SCTP_BASE_SYSCTL(sctp_steady_step);
1527         net->cc_mod.rtcc.use_dccc_ecn = SCTP_BASE_SYSCTL(sctp_use_dccc_ecn);
1528         net->cc_mod.rtcc.step_cnt = 0;
1529         net->cc_mod.rtcc.last_step_state = 0;
1530
1531
1532 }
1533
1534 static int
1535 sctp_cwnd_rtcc_socket_option(struct sctp_tcb *stcb, int setorget,
1536                              struct sctp_cc_option *cc_opt)
1537 {
1538         struct sctp_nets *net;
1539         if (setorget == 1) {
1540                 /* a set */
1541                 if (cc_opt->option == SCTP_CC_OPT_RTCC_SETMODE) {
1542                         if ((cc_opt->aid_value.assoc_value != 0) &&
1543                             (cc_opt->aid_value.assoc_value != 1)) {
1544                                 return (EINVAL);
1545                         }
1546                         TAILQ_FOREACH(net, &stcb->asoc.nets, sctp_next) {
1547                                 net->cc_mod.rtcc.ret_from_eq = cc_opt->aid_value.assoc_value;
1548                         }
1549                 } else if (cc_opt->option == SCTP_CC_OPT_USE_DCCC_ECN) {
1550                         if ((cc_opt->aid_value.assoc_value != 0) &&
1551                             (cc_opt->aid_value.assoc_value != 1)) {
1552                                 return (EINVAL);
1553                         }
1554                         TAILQ_FOREACH(net, &stcb->asoc.nets, sctp_next) {
1555                                 net->cc_mod.rtcc.use_dccc_ecn = cc_opt->aid_value.assoc_value;
1556                         }
1557                 } else if (cc_opt->option == SCTP_CC_OPT_STEADY_STEP) {
1558                         TAILQ_FOREACH(net, &stcb->asoc.nets, sctp_next) {
1559                                 net->cc_mod.rtcc.steady_step = cc_opt->aid_value.assoc_value;
1560                         }
1561                 } else {
1562                         return (EINVAL);
1563                 }
1564         } else {
1565                 /* a get */
1566                 if (cc_opt->option == SCTP_CC_OPT_RTCC_SETMODE) {
1567                         net = TAILQ_FIRST(&stcb->asoc.nets);
1568                         if (net == NULL) {
1569                                 return (EFAULT);
1570                         }
1571                         cc_opt->aid_value.assoc_value = net->cc_mod.rtcc.ret_from_eq;
1572                 } else if (cc_opt->option == SCTP_CC_OPT_USE_DCCC_ECN) {
1573                         net = TAILQ_FIRST(&stcb->asoc.nets);
1574                         if (net == NULL) {
1575                                 return (EFAULT);
1576                         }
1577                         cc_opt->aid_value.assoc_value = net->cc_mod.rtcc.use_dccc_ecn;
1578                 } else if (cc_opt->option == SCTP_CC_OPT_STEADY_STEP) {
1579                         net = TAILQ_FIRST(&stcb->asoc.nets);
1580                         if (net == NULL) {
1581                                 return (EFAULT);
1582                         }
1583                         cc_opt->aid_value.assoc_value = net->cc_mod.rtcc.steady_step;
1584                 } else {
1585                         return (EINVAL);
1586                 }
1587         }
1588         return (0);
1589 }
1590
1591 static void
1592 sctp_cwnd_update_rtcc_packet_transmitted(struct sctp_tcb *stcb SCTP_UNUSED,
1593                                          struct sctp_nets *net)
1594 {
1595         if (net->cc_mod.rtcc.tls_needs_set == 0) {
1596                 SCTP_GETPTIME_TIMEVAL(&net->cc_mod.rtcc.tls);
1597                 net->cc_mod.rtcc.tls_needs_set = 2;
1598         }
1599 }
1600
1601 static void
1602 sctp_cwnd_update_rtcc_after_sack(struct sctp_tcb *stcb,
1603                                  struct sctp_association *asoc,
1604                                  int accum_moved, int reneged_all, int will_exit)
1605 {
1606         /* Passing a one argument at the last enables the rtcc algorithm */
1607         sctp_cwnd_update_after_sack_common(stcb, asoc, accum_moved, reneged_all, will_exit, 1);
1608 }
1609
1610 static void
1611 sctp_rtt_rtcc_calculated(struct sctp_tcb *stcb SCTP_UNUSED,
1612                          struct sctp_nets *net,
1613                          struct timeval *now SCTP_UNUSED)
1614 {
1615         net->cc_mod.rtcc.rtt_set_this_sack = 1;
1616 }
1617
1618 /* Here starts Sally Floyds HS-TCP */
1619
1620 struct sctp_hs_raise_drop {
1621         int32_t cwnd;
1622         int8_t increase;
1623         int8_t drop_percent;
1624 };
1625
1626 #define SCTP_HS_TABLE_SIZE 73
1627
1628 static const struct sctp_hs_raise_drop sctp_cwnd_adjust[SCTP_HS_TABLE_SIZE] = {
1629         {38, 1, 50},            /* 0   */
1630         {118, 2, 44},           /* 1   */
1631         {221, 3, 41},           /* 2   */
1632         {347, 4, 38},           /* 3   */
1633         {495, 5, 37},           /* 4   */
1634         {663, 6, 35},           /* 5   */
1635         {851, 7, 34},           /* 6   */
1636         {1058, 8, 33},          /* 7   */
1637         {1284, 9, 32},          /* 8   */
1638         {1529, 10, 31},         /* 9   */
1639         {1793, 11, 30},         /* 10  */
1640         {2076, 12, 29},         /* 11  */
1641         {2378, 13, 28},         /* 12  */
1642         {2699, 14, 28},         /* 13  */
1643         {3039, 15, 27},         /* 14  */
1644         {3399, 16, 27},         /* 15  */
1645         {3778, 17, 26},         /* 16  */
1646         {4177, 18, 26},         /* 17  */
1647         {4596, 19, 25},         /* 18  */
1648         {5036, 20, 25},         /* 19  */
1649         {5497, 21, 24},         /* 20  */
1650         {5979, 22, 24},         /* 21  */
1651         {6483, 23, 23},         /* 22  */
1652         {7009, 24, 23},         /* 23  */
1653         {7558, 25, 22},         /* 24  */
1654         {8130, 26, 22},         /* 25  */
1655         {8726, 27, 22},         /* 26  */
1656         {9346, 28, 21},         /* 27  */
1657         {9991, 29, 21},         /* 28  */
1658         {10661, 30, 21},        /* 29  */
1659         {11358, 31, 20},        /* 30  */
1660         {12082, 32, 20},        /* 31  */
1661         {12834, 33, 20},        /* 32  */
1662         {13614, 34, 19},        /* 33  */
1663         {14424, 35, 19},        /* 34  */
1664         {15265, 36, 19},        /* 35  */
1665         {16137, 37, 19},        /* 36  */
1666         {17042, 38, 18},        /* 37  */
1667         {17981, 39, 18},        /* 38  */
1668         {18955, 40, 18},        /* 39  */
1669         {19965, 41, 17},        /* 40  */
1670         {21013, 42, 17},        /* 41  */
1671         {22101, 43, 17},        /* 42  */
1672         {23230, 44, 17},        /* 43  */
1673         {24402, 45, 16},        /* 44  */
1674         {25618, 46, 16},        /* 45  */
1675         {26881, 47, 16},        /* 46  */
1676         {28193, 48, 16},        /* 47  */
1677         {29557, 49, 15},        /* 48  */
1678         {30975, 50, 15},        /* 49  */
1679         {32450, 51, 15},        /* 50  */
1680         {33986, 52, 15},        /* 51  */
1681         {35586, 53, 14},        /* 52  */
1682         {37253, 54, 14},        /* 53  */
1683         {38992, 55, 14},        /* 54  */
1684         {40808, 56, 14},        /* 55  */
1685         {42707, 57, 13},        /* 56  */
1686         {44694, 58, 13},        /* 57  */
1687         {46776, 59, 13},        /* 58  */
1688         {48961, 60, 13},        /* 59  */
1689         {51258, 61, 13},        /* 60  */
1690         {53677, 62, 12},        /* 61  */
1691         {56230, 63, 12},        /* 62  */
1692         {58932, 64, 12},        /* 63  */
1693         {61799, 65, 12},        /* 64  */
1694         {64851, 66, 11},        /* 65  */
1695         {68113, 67, 11},        /* 66  */
1696         {71617, 68, 11},        /* 67  */
1697         {75401, 69, 10},        /* 68  */
1698         {79517, 70, 10},        /* 69  */
1699         {84035, 71, 10},        /* 70  */
1700         {89053, 72, 10},        /* 71  */
1701         {94717, 73, 9}          /* 72  */
1702 };
1703
1704 static void
1705 sctp_hs_cwnd_increase(struct sctp_tcb *stcb, struct sctp_nets *net)
1706 {
1707         int cur_val, i, indx, incr;
1708         int old_cwnd = net->cwnd;
1709
1710         cur_val = net->cwnd >> 10;
1711         indx = SCTP_HS_TABLE_SIZE - 1;
1712
1713         if (cur_val < sctp_cwnd_adjust[0].cwnd) {
1714                 /* normal mode */
1715                 if (net->net_ack > net->mtu) {
1716                         net->cwnd += net->mtu;
1717                 } else {
1718                         net->cwnd += net->net_ack;
1719                 }
1720         } else {
1721                 for (i = net->last_hs_used; i < SCTP_HS_TABLE_SIZE; i++) {
1722                         if (cur_val < sctp_cwnd_adjust[i].cwnd) {
1723                                 indx = i;
1724                                 break;
1725                         }
1726                 }
1727                 net->last_hs_used = indx;
1728                 incr = (((int32_t)sctp_cwnd_adjust[indx].increase) << 10);
1729                 net->cwnd += incr;
1730         }
1731         sctp_enforce_cwnd_limit(&stcb->asoc, net);
1732         if (SCTP_BASE_SYSCTL(sctp_logging_level) & SCTP_CWND_MONITOR_ENABLE) {
1733                 sctp_log_cwnd(stcb, net, (net->cwnd - old_cwnd), SCTP_CWND_LOG_FROM_SS);
1734         }
1735 }
1736
1737 static void
1738 sctp_hs_cwnd_decrease(struct sctp_tcb *stcb, struct sctp_nets *net)
1739 {
1740         int cur_val, i, indx;
1741         int old_cwnd = net->cwnd;
1742
1743         cur_val = net->cwnd >> 10;
1744         if (cur_val < sctp_cwnd_adjust[0].cwnd) {
1745                 /* normal mode */
1746                 net->ssthresh = net->cwnd / 2;
1747                 if (net->ssthresh < (net->mtu * 2)) {
1748                         net->ssthresh = 2 * net->mtu;
1749                 }
1750                 net->cwnd = net->ssthresh;
1751         } else {
1752                 /* drop by the proper amount */
1753                 net->ssthresh = net->cwnd - (int)((net->cwnd / 100) *
1754                     (int32_t)sctp_cwnd_adjust[net->last_hs_used].drop_percent);
1755                 net->cwnd = net->ssthresh;
1756                 /* now where are we */
1757                 indx = net->last_hs_used;
1758                 cur_val = net->cwnd >> 10;
1759                 /* reset where we are in the table */
1760                 if (cur_val < sctp_cwnd_adjust[0].cwnd) {
1761                         /* feel out of hs */
1762                         net->last_hs_used = 0;
1763                 } else {
1764                         for (i = indx; i >= 1; i--) {
1765                                 if (cur_val > sctp_cwnd_adjust[i - 1].cwnd) {
1766                                         break;
1767                                 }
1768                         }
1769                         net->last_hs_used = indx;
1770                 }
1771         }
1772         sctp_enforce_cwnd_limit(&stcb->asoc, net);
1773         if (SCTP_BASE_SYSCTL(sctp_logging_level) & SCTP_CWND_MONITOR_ENABLE) {
1774                 sctp_log_cwnd(stcb, net, (net->cwnd - old_cwnd), SCTP_CWND_LOG_FROM_FR);
1775         }
1776 }
1777
1778 static void
1779 sctp_hs_cwnd_update_after_fr(struct sctp_tcb *stcb,
1780                              struct sctp_association *asoc)
1781 {
1782         struct sctp_nets *net;
1783                 /*
1784          * CMT fast recovery code. Need to debug. ((sctp_cmt_on_off > 0) &&
1785          * (net->fast_retran_loss_recovery == 0)))
1786          */
1787         TAILQ_FOREACH(net, &asoc->nets, sctp_next) {
1788                 if ((asoc->fast_retran_loss_recovery == 0) ||
1789                     (asoc->sctp_cmt_on_off > 0)) {
1790                         /* out of a RFC2582 Fast recovery window? */
1791                         if (net->net_ack > 0) {
1792                                 /*
1793                                  * per section 7.2.3, are there any
1794                                  * destinations that had a fast retransmit
1795                                  * to them. If so what we need to do is
1796                                  * adjust ssthresh and cwnd.
1797                                  */
1798                                 struct sctp_tmit_chunk *lchk;
1799
1800                                 sctp_hs_cwnd_decrease(stcb, net);
1801
1802                                 lchk = TAILQ_FIRST(&asoc->send_queue);
1803
1804                                 net->partial_bytes_acked = 0;
1805                                 /* Turn on fast recovery window */
1806                                 asoc->fast_retran_loss_recovery = 1;
1807                                 if (lchk == NULL) {
1808                                         /* Mark end of the window */
1809                                         asoc->fast_recovery_tsn = asoc->sending_seq - 1;
1810                                 } else {
1811                                         asoc->fast_recovery_tsn = lchk->rec.data.tsn - 1;
1812                                 }
1813
1814                                 /*
1815                                  * CMT fast recovery -- per destination
1816                                  * recovery variable.
1817                                  */
1818                                 net->fast_retran_loss_recovery = 1;
1819
1820                                 if (lchk == NULL) {
1821                                         /* Mark end of the window */
1822                                         net->fast_recovery_tsn = asoc->sending_seq - 1;
1823                                 } else {
1824                                         net->fast_recovery_tsn = lchk->rec.data.tsn - 1;
1825                                 }
1826
1827                                 sctp_timer_stop(SCTP_TIMER_TYPE_SEND,
1828                                                 stcb->sctp_ep, stcb, net,
1829                                                 SCTP_FROM_SCTP_CC_FUNCTIONS + SCTP_LOC_2);
1830                                 sctp_timer_start(SCTP_TIMER_TYPE_SEND,
1831                                                  stcb->sctp_ep, stcb, net);
1832                         }
1833                 } else if (net->net_ack > 0) {
1834                         /*
1835                          * Mark a peg that we WOULD have done a cwnd
1836                          * reduction but RFC2582 prevented this action.
1837                          */
1838                         SCTP_STAT_INCR(sctps_fastretransinrtt);
1839                 }
1840         }
1841 }
1842
1843 static void
1844 sctp_hs_cwnd_update_after_sack(struct sctp_tcb *stcb,
1845                  struct sctp_association *asoc,
1846                  int accum_moved, int reneged_all SCTP_UNUSED, int will_exit)
1847 {
1848         struct sctp_nets *net;
1849         /******************************/
1850         /* update cwnd and Early FR   */
1851         /******************************/
1852         TAILQ_FOREACH(net, &asoc->nets, sctp_next) {
1853
1854 #ifdef JANA_CMT_FAST_RECOVERY
1855                 /*
1856                  * CMT fast recovery code. Need to debug.
1857                  */
1858                 if (net->fast_retran_loss_recovery && net->new_pseudo_cumack) {
1859                         if (SCTP_TSN_GE(asoc->last_acked_seq, net->fast_recovery_tsn) ||
1860                             SCTP_TSN_GE(net->pseudo_cumack,net->fast_recovery_tsn)) {
1861                                 net->will_exit_fast_recovery = 1;
1862                         }
1863                 }
1864 #endif
1865                 /* if nothing was acked on this destination skip it */
1866                 if (net->net_ack == 0) {
1867                         if (SCTP_BASE_SYSCTL(sctp_logging_level) & SCTP_CWND_LOGGING_ENABLE) {
1868                                 sctp_log_cwnd(stcb, net, 0, SCTP_CWND_LOG_FROM_SACK);
1869                         }
1870                         continue;
1871                 }
1872 #ifdef JANA_CMT_FAST_RECOVERY
1873                 /* CMT fast recovery code
1874                  */
1875                 /*
1876                 if (sctp_cmt_on_off > 0 && net->fast_retran_loss_recovery && net->will_exit_fast_recovery == 0) {
1877                     @@@ Do something
1878                  }
1879                  else if (sctp_cmt_on_off == 0 && asoc->fast_retran_loss_recovery && will_exit == 0) {
1880                 */
1881 #endif
1882
1883                  if (asoc->fast_retran_loss_recovery &&
1884                      (will_exit == 0) &&
1885                      (asoc->sctp_cmt_on_off == 0)) {
1886                         /*
1887                          * If we are in loss recovery we skip any cwnd
1888                          * update
1889                          */
1890                         return;
1891                 }
1892                 /*
1893                  * CMT: CUC algorithm. Update cwnd if pseudo-cumack has
1894                  * moved.
1895                  */
1896                 if (accum_moved ||
1897                     ((asoc->sctp_cmt_on_off > 0) && net->new_pseudo_cumack)) {
1898                         /* If the cumulative ack moved we can proceed */
1899                         if (net->cwnd <= net->ssthresh) {
1900                                 /* We are in slow start */
1901                                 if (net->flight_size + net->net_ack >= net->cwnd) {
1902                                         sctp_hs_cwnd_increase(stcb, net);
1903                                 } else {
1904                                         if (SCTP_BASE_SYSCTL(sctp_logging_level) & SCTP_CWND_LOGGING_ENABLE) {
1905                                                 sctp_log_cwnd(stcb, net, net->net_ack,
1906                                                         SCTP_CWND_LOG_NOADV_SS);
1907                                         }
1908                                 }
1909                         } else {
1910                                 /* We are in congestion avoidance */
1911                                 net->partial_bytes_acked += net->net_ack;
1912                                 if ((net->flight_size + net->net_ack >= net->cwnd) &&
1913                                     (net->partial_bytes_acked >= net->cwnd)) {
1914                                         net->partial_bytes_acked -= net->cwnd;
1915                                         net->cwnd += net->mtu;
1916                                         sctp_enforce_cwnd_limit(asoc, net);
1917                                         if (SCTP_BASE_SYSCTL(sctp_logging_level) & SCTP_CWND_MONITOR_ENABLE) {
1918                                                 sctp_log_cwnd(stcb, net, net->mtu,
1919                                                         SCTP_CWND_LOG_FROM_CA);
1920                                         }
1921                                 } else {
1922                                         if (SCTP_BASE_SYSCTL(sctp_logging_level) & SCTP_CWND_LOGGING_ENABLE) {
1923                                                 sctp_log_cwnd(stcb, net, net->net_ack,
1924                                                         SCTP_CWND_LOG_NOADV_CA);
1925                                         }
1926                                 }
1927                         }
1928                 } else {
1929                         if (SCTP_BASE_SYSCTL(sctp_logging_level) & SCTP_CWND_LOGGING_ENABLE) {
1930                                 sctp_log_cwnd(stcb, net, net->mtu,
1931                                         SCTP_CWND_LOG_NO_CUMACK);
1932                         }
1933                 }
1934         }
1935 }
1936
1937
1938 /*
1939  * H-TCP congestion control. The algorithm is detailed in:
1940  * R.N.Shorten, D.J.Leith:
1941  *   "H-TCP: TCP for high-speed and long-distance networks"
1942  *   Proc. PFLDnet, Argonne, 2004.
1943  * http://www.hamilton.ie/net/htcp3.pdf
1944  */
1945
1946
1947 static int use_rtt_scaling = 1;
1948 static int use_bandwidth_switch = 1;
1949
1950 static inline int
1951 between(uint32_t seq1, uint32_t seq2, uint32_t seq3)
1952 {
1953         return (seq3 - seq2 >= seq1 - seq2);
1954 }
1955
1956 static inline uint32_t
1957 htcp_cong_time(struct htcp *ca)
1958 {
1959         return (sctp_get_tick_count() - ca->last_cong);
1960 }
1961
1962 static inline uint32_t
1963 htcp_ccount(struct htcp *ca)
1964 {
1965         return (ca->minRTT == 0 ? htcp_cong_time(ca) : htcp_cong_time(ca)/ca->minRTT);
1966 }
1967
1968 static inline void
1969 htcp_reset(struct htcp *ca)
1970 {
1971         ca->undo_last_cong = ca->last_cong;
1972         ca->undo_maxRTT = ca->maxRTT;
1973         ca->undo_old_maxB = ca->old_maxB;
1974         ca->last_cong = sctp_get_tick_count();
1975 }
1976
1977 #ifdef SCTP_NOT_USED
1978
1979 static uint32_t
1980 htcp_cwnd_undo(struct sctp_tcb *stcb, struct sctp_nets *net)
1981 {
1982         net->cc_mod.htcp_ca.last_cong = net->cc_mod.htcp_ca.undo_last_cong;
1983         net->cc_mod.htcp_ca.maxRTT = net->cc_mod.htcp_ca.undo_maxRTT;
1984         net->cc_mod.htcp_ca.old_maxB = net->cc_mod.htcp_ca.undo_old_maxB;
1985         return (max(net->cwnd, ((net->ssthresh/net->mtu<<7)/net->cc_mod.htcp_ca.beta)*net->mtu));
1986 }
1987
1988 #endif
1989
1990 static inline void
1991 measure_rtt(struct sctp_nets *net)
1992 {
1993         uint32_t srtt = net->lastsa>>SCTP_RTT_SHIFT;
1994
1995         /* keep track of minimum RTT seen so far, minRTT is zero at first */
1996         if (net->cc_mod.htcp_ca.minRTT > srtt || !net->cc_mod.htcp_ca.minRTT)
1997                 net->cc_mod.htcp_ca.minRTT = srtt;
1998
1999         /* max RTT */
2000         if (net->fast_retran_ip == 0 && net->ssthresh < 0xFFFF && htcp_ccount(&net->cc_mod.htcp_ca) > 3) {
2001                 if (net->cc_mod.htcp_ca.maxRTT < net->cc_mod.htcp_ca.minRTT)
2002                         net->cc_mod.htcp_ca.maxRTT = net->cc_mod.htcp_ca.minRTT;
2003                 if (net->cc_mod.htcp_ca.maxRTT < srtt && srtt <= net->cc_mod.htcp_ca.maxRTT+sctp_msecs_to_ticks(20))
2004                         net->cc_mod.htcp_ca.maxRTT = srtt;
2005         }
2006 }
2007
2008 static void
2009 measure_achieved_throughput(struct sctp_nets *net)
2010 {
2011         uint32_t now = sctp_get_tick_count();
2012
2013         if (net->fast_retran_ip == 0)
2014                 net->cc_mod.htcp_ca.bytes_acked = net->net_ack;
2015
2016         if (!use_bandwidth_switch)
2017                 return;
2018
2019         /* achieved throughput calculations */
2020         /* JRS - not 100% sure of this statement */
2021         if (net->fast_retran_ip == 1) {
2022                 net->cc_mod.htcp_ca.bytecount = 0;
2023                 net->cc_mod.htcp_ca.lasttime = now;
2024                 return;
2025         }
2026
2027         net->cc_mod.htcp_ca.bytecount += net->net_ack;
2028         if ((net->cc_mod.htcp_ca.bytecount >= net->cwnd - (((net->cc_mod.htcp_ca.alpha >> 7) ? (net->cc_mod.htcp_ca.alpha >> 7) : 1) * net->mtu)) &&
2029             (now - net->cc_mod.htcp_ca.lasttime >= net->cc_mod.htcp_ca.minRTT) &&
2030             (net->cc_mod.htcp_ca.minRTT > 0)) {
2031                 uint32_t cur_Bi = net->cc_mod.htcp_ca.bytecount/net->mtu*hz/(now - net->cc_mod.htcp_ca.lasttime);
2032
2033                 if (htcp_ccount(&net->cc_mod.htcp_ca) <= 3) {
2034                         /* just after backoff */
2035                         net->cc_mod.htcp_ca.minB = net->cc_mod.htcp_ca.maxB = net->cc_mod.htcp_ca.Bi = cur_Bi;
2036                 } else {
2037                         net->cc_mod.htcp_ca.Bi = (3*net->cc_mod.htcp_ca.Bi + cur_Bi)/4;
2038                         if (net->cc_mod.htcp_ca.Bi > net->cc_mod.htcp_ca.maxB)
2039                                 net->cc_mod.htcp_ca.maxB = net->cc_mod.htcp_ca.Bi;
2040                         if (net->cc_mod.htcp_ca.minB > net->cc_mod.htcp_ca.maxB)
2041                                 net->cc_mod.htcp_ca.minB = net->cc_mod.htcp_ca.maxB;
2042                 }
2043                 net->cc_mod.htcp_ca.bytecount = 0;
2044                 net->cc_mod.htcp_ca.lasttime = now;
2045         }
2046 }
2047
2048 static inline void
2049 htcp_beta_update(struct htcp *ca, uint32_t minRTT, uint32_t maxRTT)
2050 {
2051         if (use_bandwidth_switch) {
2052                 uint32_t maxB = ca->maxB;
2053                 uint32_t old_maxB = ca->old_maxB;
2054                 ca->old_maxB = ca->maxB;
2055
2056                 if (!between(5*maxB, 4*old_maxB, 6*old_maxB)) {
2057                         ca->beta = BETA_MIN;
2058                         ca->modeswitch = 0;
2059                         return;
2060                 }
2061         }
2062
2063         if (ca->modeswitch && minRTT > sctp_msecs_to_ticks(10) && maxRTT) {
2064                 ca->beta = (minRTT<<7)/maxRTT;
2065                 if (ca->beta < BETA_MIN)
2066                         ca->beta = BETA_MIN;
2067                 else if (ca->beta > BETA_MAX)
2068                         ca->beta = BETA_MAX;
2069         } else {
2070                 ca->beta = BETA_MIN;
2071                 ca->modeswitch = 1;
2072         }
2073 }
2074
2075 static inline void
2076 htcp_alpha_update(struct htcp *ca)
2077 {
2078         uint32_t minRTT = ca->minRTT;
2079         uint32_t factor = 1;
2080         uint32_t diff = htcp_cong_time(ca);
2081
2082         if (diff > (uint32_t)hz) {
2083                 diff -= hz;
2084                 factor = 1+ ( 10*diff + ((diff/2)*(diff/2)/hz))/hz;
2085         }
2086
2087         if (use_rtt_scaling && minRTT) {
2088                 uint32_t scale = (hz<<3)/(10*minRTT);
2089                 scale = min(max(scale, 1U<<2), 10U<<3); /* clamping ratio to interval [0.5,10]<<3 */
2090                 factor = (factor<<3)/scale;
2091                 if (!factor)
2092                         factor = 1;
2093         }
2094
2095         ca->alpha = 2*factor*((1<<7)-ca->beta);
2096         if (!ca->alpha)
2097                 ca->alpha = ALPHA_BASE;
2098 }
2099
2100 /* After we have the rtt data to calculate beta, we'd still prefer to wait one
2101  * rtt before we adjust our beta to ensure we are working from a consistent
2102  * data.
2103  *
2104  * This function should be called when we hit a congestion event since only at
2105  * that point do we really have a real sense of maxRTT (the queues en route
2106  * were getting just too full now).
2107  */
2108 static void
2109 htcp_param_update(struct sctp_nets *net)
2110 {
2111         uint32_t minRTT = net->cc_mod.htcp_ca.minRTT;
2112         uint32_t maxRTT = net->cc_mod.htcp_ca.maxRTT;
2113
2114         htcp_beta_update(&net->cc_mod.htcp_ca, minRTT, maxRTT);
2115         htcp_alpha_update(&net->cc_mod.htcp_ca);
2116
2117         /* add slowly fading memory for maxRTT to accommodate routing changes etc */
2118         if (minRTT > 0 && maxRTT > minRTT)
2119                 net->cc_mod.htcp_ca.maxRTT = minRTT + ((maxRTT-minRTT)*95)/100;
2120 }
2121
2122 static uint32_t
2123 htcp_recalc_ssthresh(struct sctp_nets *net)
2124 {
2125         htcp_param_update(net);
2126         return (max(((net->cwnd/net->mtu * net->cc_mod.htcp_ca.beta) >> 7)*net->mtu, 2U*net->mtu));
2127 }
2128
2129 static void
2130 htcp_cong_avoid(struct sctp_tcb *stcb, struct sctp_nets *net)
2131 {
2132         /*-
2133          * How to handle these functions?
2134          *      if (!tcp_is_cwnd_limited(sk, in_flight)) RRS - good question.
2135          *              return;
2136          */
2137         if (net->cwnd <= net->ssthresh) {
2138                 /* We are in slow start */
2139                 if (net->flight_size + net->net_ack >= net->cwnd) {
2140                         if (net->net_ack > (net->mtu * SCTP_BASE_SYSCTL(sctp_L2_abc_variable))) {
2141                                 net->cwnd += (net->mtu * SCTP_BASE_SYSCTL(sctp_L2_abc_variable));
2142                                 if (SCTP_BASE_SYSCTL(sctp_logging_level) & SCTP_CWND_MONITOR_ENABLE) {
2143                                         sctp_log_cwnd(stcb, net, net->mtu,
2144                                                 SCTP_CWND_LOG_FROM_SS);
2145                                 }
2146
2147                         } else {
2148                                 net->cwnd += net->net_ack;
2149                                 if (SCTP_BASE_SYSCTL(sctp_logging_level) & SCTP_CWND_MONITOR_ENABLE) {
2150                                         sctp_log_cwnd(stcb, net, net->net_ack,
2151                                                 SCTP_CWND_LOG_FROM_SS);
2152                                 }
2153
2154                         }
2155                         sctp_enforce_cwnd_limit(&stcb->asoc, net);
2156                 } else {
2157                         if (SCTP_BASE_SYSCTL(sctp_logging_level) & SCTP_CWND_LOGGING_ENABLE) {
2158                                 sctp_log_cwnd(stcb, net, net->net_ack,
2159                                         SCTP_CWND_LOG_NOADV_SS);
2160                         }
2161                 }
2162         } else {
2163                 measure_rtt(net);
2164
2165                 /* In dangerous area, increase slowly.
2166                  * In theory this is net->cwnd += alpha / net->cwnd
2167                  */
2168                 /* What is snd_cwnd_cnt?? */
2169                 if (((net->partial_bytes_acked/net->mtu * net->cc_mod.htcp_ca.alpha) >> 7)*net->mtu >= net->cwnd) {
2170                         /*-
2171                          * Does SCTP have a cwnd clamp?
2172                          * if (net->snd_cwnd < net->snd_cwnd_clamp) - Nope (RRS).
2173                          */
2174                         net->cwnd += net->mtu;
2175                         net->partial_bytes_acked = 0;
2176                         sctp_enforce_cwnd_limit(&stcb->asoc, net);
2177                         htcp_alpha_update(&net->cc_mod.htcp_ca);
2178                         if (SCTP_BASE_SYSCTL(sctp_logging_level) & SCTP_CWND_MONITOR_ENABLE) {
2179                                 sctp_log_cwnd(stcb, net, net->mtu,
2180                                         SCTP_CWND_LOG_FROM_CA);
2181                         }
2182                 } else {
2183                         net->partial_bytes_acked += net->net_ack;
2184                         if (SCTP_BASE_SYSCTL(sctp_logging_level) & SCTP_CWND_LOGGING_ENABLE) {
2185                                 sctp_log_cwnd(stcb, net, net->net_ack,
2186                                         SCTP_CWND_LOG_NOADV_CA);
2187                         }
2188                 }
2189
2190                 net->cc_mod.htcp_ca.bytes_acked = net->mtu;
2191         }
2192 }
2193
2194 #ifdef SCTP_NOT_USED
2195 /* Lower bound on congestion window. */
2196 static uint32_t
2197 htcp_min_cwnd(struct sctp_tcb *stcb, struct sctp_nets *net)
2198 {
2199         return (net->ssthresh);
2200 }
2201 #endif
2202
2203 static void
2204 htcp_init(struct sctp_nets *net)
2205 {
2206         memset(&net->cc_mod.htcp_ca, 0, sizeof(struct htcp));
2207         net->cc_mod.htcp_ca.alpha = ALPHA_BASE;
2208         net->cc_mod.htcp_ca.beta = BETA_MIN;
2209         net->cc_mod.htcp_ca.bytes_acked = net->mtu;
2210         net->cc_mod.htcp_ca.last_cong = sctp_get_tick_count();
2211 }
2212
2213 static void
2214 sctp_htcp_set_initial_cc_param(struct sctp_tcb *stcb, struct sctp_nets *net)
2215 {
2216         /*
2217          * We take the max of the burst limit times a MTU or the
2218          * INITIAL_CWND. We then limit this to 4 MTU's of sending.
2219          */
2220         net->cwnd = min((net->mtu * 4), max((2 * net->mtu), SCTP_INITIAL_CWND));
2221         net->ssthresh = stcb->asoc.peers_rwnd;
2222         sctp_enforce_cwnd_limit(&stcb->asoc, net);
2223         htcp_init(net);
2224
2225         if (SCTP_BASE_SYSCTL(sctp_logging_level) & (SCTP_CWND_MONITOR_ENABLE|SCTP_CWND_LOGGING_ENABLE)) {
2226                 sctp_log_cwnd(stcb, net, 0, SCTP_CWND_INITIALIZATION);
2227         }
2228 }
2229
2230 static void
2231 sctp_htcp_cwnd_update_after_sack(struct sctp_tcb *stcb,
2232                  struct sctp_association *asoc,
2233                  int accum_moved, int reneged_all SCTP_UNUSED, int will_exit)
2234 {
2235         struct sctp_nets *net;
2236
2237         /******************************/
2238         /* update cwnd and Early FR   */
2239         /******************************/
2240         TAILQ_FOREACH(net, &asoc->nets, sctp_next) {
2241
2242 #ifdef JANA_CMT_FAST_RECOVERY
2243                 /*
2244                  * CMT fast recovery code. Need to debug.
2245                  */
2246                 if (net->fast_retran_loss_recovery && net->new_pseudo_cumack) {
2247                         if (SCTP_TSN_GE(asoc->last_acked_seq, net->fast_recovery_tsn) ||
2248                             SCTP_TSN_GE(net->pseudo_cumack,net->fast_recovery_tsn)) {
2249                                 net->will_exit_fast_recovery = 1;
2250                         }
2251                 }
2252 #endif
2253                 /* if nothing was acked on this destination skip it */
2254                 if (net->net_ack == 0) {
2255                         if (SCTP_BASE_SYSCTL(sctp_logging_level) & SCTP_CWND_LOGGING_ENABLE) {
2256                                 sctp_log_cwnd(stcb, net, 0, SCTP_CWND_LOG_FROM_SACK);
2257                         }
2258                         continue;
2259                 }
2260 #ifdef JANA_CMT_FAST_RECOVERY
2261                 /* CMT fast recovery code
2262                  */
2263                 /*
2264                 if (sctp_cmt_on_off > 0 && net->fast_retran_loss_recovery && net->will_exit_fast_recovery == 0) {
2265                     @@@ Do something
2266                  }
2267                  else if (sctp_cmt_on_off == 0 && asoc->fast_retran_loss_recovery && will_exit == 0) {
2268                 */
2269 #endif
2270
2271                 if (asoc->fast_retran_loss_recovery &&
2272                     will_exit == 0 &&
2273                     (asoc->sctp_cmt_on_off == 0)) {
2274                         /*
2275                          * If we are in loss recovery we skip any cwnd
2276                          * update
2277                          */
2278                         return;
2279                 }
2280                 /*
2281                  * CMT: CUC algorithm. Update cwnd if pseudo-cumack has
2282                  * moved.
2283                  */
2284                 if (accum_moved ||
2285                     ((asoc->sctp_cmt_on_off > 0) && net->new_pseudo_cumack)) {
2286                         htcp_cong_avoid(stcb, net);
2287                         measure_achieved_throughput(net);
2288                 } else {
2289                         if (SCTP_BASE_SYSCTL(sctp_logging_level) & SCTP_CWND_LOGGING_ENABLE) {
2290                                 sctp_log_cwnd(stcb, net, net->mtu,
2291                                         SCTP_CWND_LOG_NO_CUMACK);
2292                         }
2293                 }
2294         }
2295 }
2296
2297 static void
2298 sctp_htcp_cwnd_update_after_fr(struct sctp_tcb *stcb,
2299                 struct sctp_association *asoc)
2300 {
2301         struct sctp_nets *net;
2302         /*
2303          * CMT fast recovery code. Need to debug. ((sctp_cmt_on_off > 0) &&
2304          * (net->fast_retran_loss_recovery == 0)))
2305          */
2306         TAILQ_FOREACH(net, &asoc->nets, sctp_next) {
2307                 if ((asoc->fast_retran_loss_recovery == 0) ||
2308                     (asoc->sctp_cmt_on_off > 0)) {
2309                         /* out of a RFC2582 Fast recovery window? */
2310                         if (net->net_ack > 0) {
2311                                 /*
2312                                  * per section 7.2.3, are there any
2313                                  * destinations that had a fast retransmit
2314                                  * to them. If so what we need to do is
2315                                  * adjust ssthresh and cwnd.
2316                                  */
2317                                 struct sctp_tmit_chunk *lchk;
2318                                 int old_cwnd = net->cwnd;
2319
2320                                 /* JRS - reset as if state were changed */
2321                                 htcp_reset(&net->cc_mod.htcp_ca);
2322                                 net->ssthresh = htcp_recalc_ssthresh(net);
2323                                 net->cwnd = net->ssthresh;
2324                                 sctp_enforce_cwnd_limit(asoc, net);
2325                                 if (SCTP_BASE_SYSCTL(sctp_logging_level) & SCTP_CWND_MONITOR_ENABLE) {
2326                                         sctp_log_cwnd(stcb, net, (net->cwnd - old_cwnd),
2327                                                 SCTP_CWND_LOG_FROM_FR);
2328                                 }
2329                                 lchk = TAILQ_FIRST(&asoc->send_queue);
2330
2331                                 net->partial_bytes_acked = 0;
2332                                 /* Turn on fast recovery window */
2333                                 asoc->fast_retran_loss_recovery = 1;
2334                                 if (lchk == NULL) {
2335                                         /* Mark end of the window */
2336                                         asoc->fast_recovery_tsn = asoc->sending_seq - 1;
2337                                 } else {
2338                                         asoc->fast_recovery_tsn = lchk->rec.data.tsn - 1;
2339                                 }
2340
2341                                 /*
2342                                  * CMT fast recovery -- per destination
2343                                  * recovery variable.
2344                                  */
2345                                 net->fast_retran_loss_recovery = 1;
2346
2347                                 if (lchk == NULL) {
2348                                         /* Mark end of the window */
2349                                         net->fast_recovery_tsn = asoc->sending_seq - 1;
2350                                 } else {
2351                                         net->fast_recovery_tsn = lchk->rec.data.tsn - 1;
2352                                 }
2353
2354                                 sctp_timer_stop(SCTP_TIMER_TYPE_SEND,
2355                                                 stcb->sctp_ep, stcb, net,
2356                                                 SCTP_FROM_SCTP_CC_FUNCTIONS + SCTP_LOC_3);
2357                                 sctp_timer_start(SCTP_TIMER_TYPE_SEND,
2358                                                  stcb->sctp_ep, stcb, net);
2359                         }
2360                 } else if (net->net_ack > 0) {
2361                         /*
2362                          * Mark a peg that we WOULD have done a cwnd
2363                          * reduction but RFC2582 prevented this action.
2364                          */
2365                         SCTP_STAT_INCR(sctps_fastretransinrtt);
2366                 }
2367         }
2368 }
2369
2370 static void
2371 sctp_htcp_cwnd_update_after_timeout(struct sctp_tcb *stcb,
2372         struct sctp_nets *net)
2373 {
2374                 int old_cwnd = net->cwnd;
2375
2376                 /* JRS - reset as if the state were being changed to timeout */
2377                 htcp_reset(&net->cc_mod.htcp_ca);
2378                 net->ssthresh = htcp_recalc_ssthresh(net);
2379                 net->cwnd = net->mtu;
2380                 net->partial_bytes_acked = 0;
2381                 if (SCTP_BASE_SYSCTL(sctp_logging_level) & SCTP_CWND_MONITOR_ENABLE) {
2382                         sctp_log_cwnd(stcb, net, net->cwnd - old_cwnd, SCTP_CWND_LOG_FROM_RTX);
2383                 }
2384 }
2385
2386 static void
2387 sctp_htcp_cwnd_update_after_ecn_echo(struct sctp_tcb *stcb,
2388                 struct sctp_nets *net, int in_window, int num_pkt_lost SCTP_UNUSED)
2389 {
2390         int old_cwnd;
2391         old_cwnd = net->cwnd;
2392
2393         /* JRS - reset hctp as if state changed */
2394         if (in_window == 0) {
2395                 htcp_reset(&net->cc_mod.htcp_ca);
2396                 SCTP_STAT_INCR(sctps_ecnereducedcwnd);
2397                 net->ssthresh = htcp_recalc_ssthresh(net);
2398                 if (net->ssthresh < net->mtu) {
2399                         net->ssthresh = net->mtu;
2400                         /* here back off the timer as well, to slow us down */
2401                         net->RTO <<= 1;
2402                 }
2403                 net->cwnd = net->ssthresh;
2404                 sctp_enforce_cwnd_limit(&stcb->asoc, net);
2405                 if (SCTP_BASE_SYSCTL(sctp_logging_level) & SCTP_CWND_MONITOR_ENABLE) {
2406                         sctp_log_cwnd(stcb, net, (net->cwnd - old_cwnd), SCTP_CWND_LOG_FROM_SAT);
2407                 }
2408         }
2409 }
2410
2411 const struct sctp_cc_functions sctp_cc_functions[] = {
2412 {
2413 #if defined(_WIN32) && !defined(__MINGW32__)
2414         sctp_set_initial_cc_param,
2415         sctp_cwnd_update_after_sack,
2416         sctp_cwnd_update_exit_pf_common,
2417         sctp_cwnd_update_after_fr,
2418         sctp_cwnd_update_after_timeout,
2419         sctp_cwnd_update_after_ecn_echo,
2420         sctp_cwnd_update_after_packet_dropped,
2421         sctp_cwnd_update_after_output,
2422 #else
2423         .sctp_set_initial_cc_param = sctp_set_initial_cc_param,
2424         .sctp_cwnd_update_after_sack = sctp_cwnd_update_after_sack,
2425         .sctp_cwnd_update_exit_pf = sctp_cwnd_update_exit_pf_common,
2426         .sctp_cwnd_update_after_fr = sctp_cwnd_update_after_fr,
2427         .sctp_cwnd_update_after_timeout = sctp_cwnd_update_after_timeout,
2428         .sctp_cwnd_update_after_ecn_echo = sctp_cwnd_update_after_ecn_echo,
2429         .sctp_cwnd_update_after_packet_dropped = sctp_cwnd_update_after_packet_dropped,
2430         .sctp_cwnd_update_after_output = sctp_cwnd_update_after_output,
2431 #endif
2432 },
2433 {
2434 #if defined(_WIN32) && !defined(__MINGW32__)
2435         sctp_set_initial_cc_param,
2436         sctp_hs_cwnd_update_after_sack,
2437         sctp_cwnd_update_exit_pf_common,
2438         sctp_hs_cwnd_update_after_fr,
2439         sctp_cwnd_update_after_timeout,
2440         sctp_cwnd_update_after_ecn_echo,
2441         sctp_cwnd_update_after_packet_dropped,
2442         sctp_cwnd_update_after_output,
2443 #else
2444         .sctp_set_initial_cc_param = sctp_set_initial_cc_param,
2445         .sctp_cwnd_update_after_sack = sctp_hs_cwnd_update_after_sack,
2446         .sctp_cwnd_update_exit_pf = sctp_cwnd_update_exit_pf_common,
2447         .sctp_cwnd_update_after_fr = sctp_hs_cwnd_update_after_fr,
2448         .sctp_cwnd_update_after_timeout = sctp_cwnd_update_after_timeout,
2449         .sctp_cwnd_update_after_ecn_echo = sctp_cwnd_update_after_ecn_echo,
2450         .sctp_cwnd_update_after_packet_dropped = sctp_cwnd_update_after_packet_dropped,
2451         .sctp_cwnd_update_after_output = sctp_cwnd_update_after_output,
2452 #endif
2453 },
2454 {
2455 #if defined(_WIN32) && !defined(__MINGW32__)
2456         sctp_htcp_set_initial_cc_param,
2457         sctp_htcp_cwnd_update_after_sack,
2458         sctp_cwnd_update_exit_pf_common,
2459         sctp_htcp_cwnd_update_after_fr,
2460         sctp_htcp_cwnd_update_after_timeout,
2461         sctp_htcp_cwnd_update_after_ecn_echo,
2462         sctp_cwnd_update_after_packet_dropped,
2463         sctp_cwnd_update_after_output,
2464 #else
2465         .sctp_set_initial_cc_param = sctp_htcp_set_initial_cc_param,
2466         .sctp_cwnd_update_after_sack = sctp_htcp_cwnd_update_after_sack,
2467         .sctp_cwnd_update_exit_pf = sctp_cwnd_update_exit_pf_common,
2468         .sctp_cwnd_update_after_fr = sctp_htcp_cwnd_update_after_fr,
2469         .sctp_cwnd_update_after_timeout = sctp_htcp_cwnd_update_after_timeout,
2470         .sctp_cwnd_update_after_ecn_echo = sctp_htcp_cwnd_update_after_ecn_echo,
2471         .sctp_cwnd_update_after_packet_dropped = sctp_cwnd_update_after_packet_dropped,
2472         .sctp_cwnd_update_after_output = sctp_cwnd_update_after_output,
2473 #endif
2474 },
2475 {
2476 #if defined(_WIN32) && !defined(__MINGW32__)
2477         sctp_set_rtcc_initial_cc_param,
2478         sctp_cwnd_update_rtcc_after_sack,
2479         sctp_cwnd_update_exit_pf_common,
2480         sctp_cwnd_update_after_fr,
2481         sctp_cwnd_update_after_timeout,
2482         sctp_cwnd_update_rtcc_after_ecn_echo,
2483         sctp_cwnd_update_after_packet_dropped,
2484         sctp_cwnd_update_after_output,
2485         sctp_cwnd_update_rtcc_packet_transmitted,
2486         sctp_cwnd_update_rtcc_tsn_acknowledged,
2487         sctp_cwnd_new_rtcc_transmission_begins,
2488         sctp_cwnd_prepare_rtcc_net_for_sack,
2489         sctp_cwnd_rtcc_socket_option,
2490         sctp_rtt_rtcc_calculated
2491 #else
2492         .sctp_set_initial_cc_param = sctp_set_rtcc_initial_cc_param,
2493         .sctp_cwnd_update_after_sack = sctp_cwnd_update_rtcc_after_sack,
2494         .sctp_cwnd_update_exit_pf = sctp_cwnd_update_exit_pf_common,
2495         .sctp_cwnd_update_after_fr = sctp_cwnd_update_after_fr,
2496         .sctp_cwnd_update_after_timeout = sctp_cwnd_update_after_timeout,
2497         .sctp_cwnd_update_after_ecn_echo = sctp_cwnd_update_rtcc_after_ecn_echo,
2498         .sctp_cwnd_update_after_packet_dropped = sctp_cwnd_update_after_packet_dropped,
2499         .sctp_cwnd_update_after_output = sctp_cwnd_update_after_output,
2500         .sctp_cwnd_update_packet_transmitted = sctp_cwnd_update_rtcc_packet_transmitted,
2501         .sctp_cwnd_update_tsn_acknowledged = sctp_cwnd_update_rtcc_tsn_acknowledged,
2502         .sctp_cwnd_new_transmission_begins = sctp_cwnd_new_rtcc_transmission_begins,
2503         .sctp_cwnd_prepare_net_for_sack = sctp_cwnd_prepare_rtcc_net_for_sack,
2504         .sctp_cwnd_socket_option = sctp_cwnd_rtcc_socket_option,
2505         .sctp_rtt_calculated = sctp_rtt_rtcc_calculated
2506 #endif
2507 }
2508 };