]> CyberLeo.Net >> Repos - FreeBSD/FreeBSD.git/blob - sys/netinet/sctp_cc_functions.c
This commit was generated by cvs2svn to compensate for changes in r179193,
[FreeBSD/FreeBSD.git] / sys / netinet / sctp_cc_functions.c
1 /*-
2  * Copyright (c) 2001-2007, by Cisco Systems, Inc. All rights reserved.
3  *
4  * Redistribution and use in source and binary forms, with or without
5  * modification, are permitted provided that the following conditions are met:
6  *
7  * a) Redistributions of source code must retain the above copyright notice,
8  *   this list of conditions and the following disclaimer.
9  *
10  * b) Redistributions in binary form must reproduce the above copyright
11  *    notice, this list of conditions and the following disclaimer in
12  *   the documentation and/or other materials provided with the distribution.
13  *
14  * c) Neither the name of Cisco Systems, Inc. nor the names of its
15  *    contributors may be used to endorse or promote products derived
16  *    from this software without specific prior written permission.
17  *
18  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
19  * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
20  * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
21  * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
22  * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
23  * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
24  * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
25  * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
26  * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
27  * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
28  * THE POSSIBILITY OF SUCH DAMAGE.
29  */
30
31 #include <netinet/sctp_os.h>
32 #include <netinet/sctp_var.h>
33 #include <netinet/sctp_sysctl.h>
34 #include <netinet/sctp_pcb.h>
35 #include <netinet/sctp_header.h>
36 #include <netinet/sctputil.h>
37 #include <netinet/sctp_output.h>
38 #include <netinet/sctp_input.h>
39 #include <netinet/sctp_indata.h>
40 #include <netinet/sctp_uio.h>
41 #include <netinet/sctp_timer.h>
42 #include <netinet/sctp_auth.h>
43 #include <netinet/sctp_asconf.h>
44 #include <netinet/sctp_cc_functions.h>
45 #include <sys/cdefs.h>
46 __FBSDID("$FreeBSD$");
47 void
48 sctp_set_initial_cc_param(struct sctp_tcb *stcb, struct sctp_nets *net)
49 {
50         /*
51          * We take the max of the burst limit times a MTU or the
52          * INITIAL_CWND. We then limit this to 4 MTU's of sending. cwnd must
53          * be at least 2 MTU.
54          */
55         net->cwnd = min((net->mtu * 4), max((2 * net->mtu), SCTP_INITIAL_CWND));
56         net->ssthresh = stcb->asoc.peers_rwnd;
57
58         if (sctp_logging_level & (SCTP_CWND_MONITOR_ENABLE | SCTP_CWND_LOGGING_ENABLE)) {
59                 sctp_log_cwnd(stcb, net, 0, SCTP_CWND_INITIALIZATION);
60         }
61 }
62
63 void
64 sctp_cwnd_update_after_fr(struct sctp_tcb *stcb,
65     struct sctp_association *asoc)
66 {
67         struct sctp_nets *net;
68
69         /*-
70          * CMT fast recovery code. Need to debug. ((sctp_cmt_on_off == 1) &&
71          * (net->fast_retran_loss_recovery == 0)))
72          */
73         TAILQ_FOREACH(net, &asoc->nets, sctp_next) {
74                 if ((asoc->fast_retran_loss_recovery == 0) || (sctp_cmt_on_off == 1)) {
75                         /* out of a RFC2582 Fast recovery window? */
76                         if (net->net_ack > 0) {
77                                 /*
78                                  * per section 7.2.3, are there any
79                                  * destinations that had a fast retransmit
80                                  * to them. If so what we need to do is
81                                  * adjust ssthresh and cwnd.
82                                  */
83                                 struct sctp_tmit_chunk *lchk;
84                                 int old_cwnd = net->cwnd;
85
86                                 net->ssthresh = net->cwnd / 2;
87                                 if (net->ssthresh < (net->mtu * 2)) {
88                                         net->ssthresh = 2 * net->mtu;
89                                 }
90                                 net->cwnd = net->ssthresh;
91                                 if (sctp_logging_level & SCTP_CWND_MONITOR_ENABLE) {
92                                         sctp_log_cwnd(stcb, net, (net->cwnd - old_cwnd),
93                                             SCTP_CWND_LOG_FROM_FR);
94                                 }
95                                 lchk = TAILQ_FIRST(&asoc->send_queue);
96
97                                 net->partial_bytes_acked = 0;
98                                 /* Turn on fast recovery window */
99                                 asoc->fast_retran_loss_recovery = 1;
100                                 if (lchk == NULL) {
101                                         /* Mark end of the window */
102                                         asoc->fast_recovery_tsn = asoc->sending_seq - 1;
103                                 } else {
104                                         asoc->fast_recovery_tsn = lchk->rec.data.TSN_seq - 1;
105                                 }
106
107                                 /*
108                                  * CMT fast recovery -- per destination
109                                  * recovery variable.
110                                  */
111                                 net->fast_retran_loss_recovery = 1;
112
113                                 if (lchk == NULL) {
114                                         /* Mark end of the window */
115                                         net->fast_recovery_tsn = asoc->sending_seq - 1;
116                                 } else {
117                                         net->fast_recovery_tsn = lchk->rec.data.TSN_seq - 1;
118                                 }
119
120                                 /*
121                                  * Disable Nonce Sum Checking and store the
122                                  * resync tsn
123                                  */
124                                 asoc->nonce_sum_check = 0;
125                                 asoc->nonce_resync_tsn = asoc->fast_recovery_tsn + 1;
126
127                                 sctp_timer_stop(SCTP_TIMER_TYPE_SEND,
128                                     stcb->sctp_ep, stcb, net, SCTP_FROM_SCTP_INDATA + SCTP_LOC_32);
129                                 sctp_timer_start(SCTP_TIMER_TYPE_SEND,
130                                     stcb->sctp_ep, stcb, net);
131                         }
132                 } else if (net->net_ack > 0) {
133                         /*
134                          * Mark a peg that we WOULD have done a cwnd
135                          * reduction but RFC2582 prevented this action.
136                          */
137                         SCTP_STAT_INCR(sctps_fastretransinrtt);
138                 }
139         }
140 }
141
142 void
143 sctp_cwnd_update_after_sack(struct sctp_tcb *stcb,
144     struct sctp_association *asoc,
145     int accum_moved, int reneged_all, int will_exit)
146 {
147         struct sctp_nets *net;
148
149         /******************************/
150         /* update cwnd and Early FR   */
151         /******************************/
152         TAILQ_FOREACH(net, &asoc->nets, sctp_next) {
153
154 #ifdef JANA_CMT_FAST_RECOVERY
155                 /*
156                  * CMT fast recovery code. Need to debug.
157                  */
158                 if (net->fast_retran_loss_recovery && net->new_pseudo_cumack) {
159                         if (compare_with_wrap(asoc->last_acked_seq,
160                             net->fast_recovery_tsn, MAX_TSN) ||
161                             (asoc->last_acked_seq == net->fast_recovery_tsn) ||
162                             compare_with_wrap(net->pseudo_cumack, net->fast_recovery_tsn, MAX_TSN) ||
163                             (net->pseudo_cumack == net->fast_recovery_tsn)) {
164                                 net->will_exit_fast_recovery = 1;
165                         }
166                 }
167 #endif
168                 if (sctp_early_fr) {
169                         /*
170                          * So, first of all do we need to have a Early FR
171                          * timer running?
172                          */
173                         if (((TAILQ_FIRST(&asoc->sent_queue)) &&
174                             (net->ref_count > 1) &&
175                             (net->flight_size < net->cwnd)) ||
176                             (reneged_all)) {
177                                 /*
178                                  * yes, so in this case stop it if its
179                                  * running, and then restart it. Reneging
180                                  * all is a special case where we want to
181                                  * run the Early FR timer and then force the
182                                  * last few unacked to be sent, causing us
183                                  * to illicit a sack with gaps to force out
184                                  * the others.
185                                  */
186                                 if (SCTP_OS_TIMER_PENDING(&net->fr_timer.timer)) {
187                                         SCTP_STAT_INCR(sctps_earlyfrstpidsck2);
188                                         sctp_timer_stop(SCTP_TIMER_TYPE_EARLYFR, stcb->sctp_ep, stcb, net,
189                                             SCTP_FROM_SCTP_INDATA + SCTP_LOC_20);
190                                 }
191                                 SCTP_STAT_INCR(sctps_earlyfrstrid);
192                                 sctp_timer_start(SCTP_TIMER_TYPE_EARLYFR, stcb->sctp_ep, stcb, net);
193                         } else {
194                                 /* No, stop it if its running */
195                                 if (SCTP_OS_TIMER_PENDING(&net->fr_timer.timer)) {
196                                         SCTP_STAT_INCR(sctps_earlyfrstpidsck3);
197                                         sctp_timer_stop(SCTP_TIMER_TYPE_EARLYFR, stcb->sctp_ep, stcb, net,
198                                             SCTP_FROM_SCTP_INDATA + SCTP_LOC_21);
199                                 }
200                         }
201                 }
202                 /* if nothing was acked on this destination skip it */
203                 if (net->net_ack == 0) {
204                         if (sctp_logging_level & SCTP_CWND_LOGGING_ENABLE) {
205                                 sctp_log_cwnd(stcb, net, 0, SCTP_CWND_LOG_FROM_SACK);
206                         }
207                         continue;
208                 }
209                 if (net->net_ack2 > 0) {
210                         /*
211                          * Karn's rule applies to clearing error count, this
212                          * is optional.
213                          */
214                         net->error_count = 0;
215                         if ((net->dest_state & SCTP_ADDR_NOT_REACHABLE) ==
216                             SCTP_ADDR_NOT_REACHABLE) {
217                                 /* addr came good */
218                                 net->dest_state &= ~SCTP_ADDR_NOT_REACHABLE;
219                                 net->dest_state |= SCTP_ADDR_REACHABLE;
220                                 sctp_ulp_notify(SCTP_NOTIFY_INTERFACE_UP, stcb,
221                                     SCTP_RECEIVED_SACK, (void *)net, SCTP_SO_NOT_LOCKED);
222                                 /* now was it the primary? if so restore */
223                                 if (net->dest_state & SCTP_ADDR_WAS_PRIMARY) {
224                                         (void)sctp_set_primary_addr(stcb, (struct sockaddr *)NULL, net);
225                                 }
226                         }
227                         /*
228                          * JRS 5/14/07 - If CMT PF is on and the destination
229                          * is in PF state, set the destination to active
230                          * state and set the cwnd to one or two MTU's based
231                          * on whether PF1 or PF2 is being used.
232                          * 
233                          * Should we stop any running T3 timer here?
234                          */
235                         if (sctp_cmt_on_off && sctp_cmt_pf && ((net->dest_state & SCTP_ADDR_PF) ==
236                             SCTP_ADDR_PF)) {
237                                 net->dest_state &= ~SCTP_ADDR_PF;
238                                 net->cwnd = net->mtu * sctp_cmt_pf;
239                                 SCTPDBG(SCTP_DEBUG_INDATA1, "Destination %p moved from PF to reachable with cwnd %d.\n",
240                                     net, net->cwnd);
241                                 /*
242                                  * Since the cwnd value is explicitly set,
243                                  * skip the code that updates the cwnd
244                                  * value.
245                                  */
246                                 goto skip_cwnd_update;
247                         }
248                 }
249 #ifdef JANA_CMT_FAST_RECOVERY
250                 /*
251                  * CMT fast recovery code
252                  */
253                 /*
254                  * if (sctp_cmt_on_off == 1 &&
255                  * net->fast_retran_loss_recovery &&
256                  * net->will_exit_fast_recovery == 0) { @@@ Do something }
257                  * else if (sctp_cmt_on_off == 0 &&
258                  * asoc->fast_retran_loss_recovery && will_exit == 0) {
259                  */
260 #endif
261
262                 if (asoc->fast_retran_loss_recovery && will_exit == 0 && sctp_cmt_on_off == 0) {
263                         /*
264                          * If we are in loss recovery we skip any cwnd
265                          * update
266                          */
267                         goto skip_cwnd_update;
268                 }
269                 /*
270                  * CMT: CUC algorithm. Update cwnd if pseudo-cumack has
271                  * moved.
272                  */
273                 if (accum_moved || (sctp_cmt_on_off && net->new_pseudo_cumack)) {
274                         /* If the cumulative ack moved we can proceed */
275                         if (net->cwnd <= net->ssthresh) {
276                                 /* We are in slow start */
277                                 if (net->flight_size + net->net_ack >= net->cwnd) {
278                                         if (net->net_ack > (net->mtu * sctp_L2_abc_variable)) {
279                                                 net->cwnd += (net->mtu * sctp_L2_abc_variable);
280                                                 if (sctp_logging_level & SCTP_CWND_MONITOR_ENABLE) {
281                                                         sctp_log_cwnd(stcb, net, net->mtu,
282                                                             SCTP_CWND_LOG_FROM_SS);
283                                                 }
284                                         } else {
285                                                 net->cwnd += net->net_ack;
286                                                 if (sctp_logging_level & SCTP_CWND_MONITOR_ENABLE) {
287                                                         sctp_log_cwnd(stcb, net, net->net_ack,
288                                                             SCTP_CWND_LOG_FROM_SS);
289                                                 }
290                                         }
291                                 } else {
292                                         if (sctp_logging_level & SCTP_CWND_LOGGING_ENABLE) {
293                                                 sctp_log_cwnd(stcb, net, net->net_ack,
294                                                     SCTP_CWND_LOG_NOADV_SS);
295                                         }
296                                 }
297                         } else {
298                                 /* We are in congestion avoidance */
299                                 /*
300                                  * Add to pba
301                                  */
302                                 net->partial_bytes_acked += net->net_ack;
303
304                                 if ((net->flight_size + net->net_ack >= net->cwnd) &&
305                                     (net->partial_bytes_acked >= net->cwnd)) {
306                                         net->partial_bytes_acked -= net->cwnd;
307                                         net->cwnd += net->mtu;
308                                         if (sctp_logging_level & SCTP_CWND_MONITOR_ENABLE) {
309                                                 sctp_log_cwnd(stcb, net, net->mtu,
310                                                     SCTP_CWND_LOG_FROM_CA);
311                                         }
312                                 } else {
313                                         if (sctp_logging_level & SCTP_CWND_LOGGING_ENABLE) {
314                                                 sctp_log_cwnd(stcb, net, net->net_ack,
315                                                     SCTP_CWND_LOG_NOADV_CA);
316                                         }
317                                 }
318                         }
319                 } else {
320                         if (sctp_logging_level & SCTP_CWND_LOGGING_ENABLE) {
321                                 sctp_log_cwnd(stcb, net, net->mtu,
322                                     SCTP_CWND_LOG_NO_CUMACK);
323                         }
324                 }
325 skip_cwnd_update:
326                 /*
327                  * NOW, according to Karn's rule do we need to restore the
328                  * RTO timer back? Check our net_ack2. If not set then we
329                  * have a ambiguity.. i.e. all data ack'd was sent to more
330                  * than one place.
331                  */
332                 if (net->net_ack2) {
333                         /* restore any doubled timers */
334                         net->RTO = ((net->lastsa >> 2) + net->lastsv) >> 1;
335                         if (net->RTO < stcb->asoc.minrto) {
336                                 net->RTO = stcb->asoc.minrto;
337                         }
338                         if (net->RTO > stcb->asoc.maxrto) {
339                                 net->RTO = stcb->asoc.maxrto;
340                         }
341                 }
342         }
343 }
344
345 void
346 sctp_cwnd_update_after_timeout(struct sctp_tcb *stcb, struct sctp_nets *net)
347 {
348         int old_cwnd = net->cwnd;
349
350         net->ssthresh = max(net->cwnd / 2, 2 * net->mtu);
351         net->cwnd = net->mtu;
352         net->partial_bytes_acked = 0;
353
354         if (sctp_logging_level & SCTP_CWND_MONITOR_ENABLE) {
355                 sctp_log_cwnd(stcb, net, net->cwnd - old_cwnd, SCTP_CWND_LOG_FROM_RTX);
356         }
357 }
358
359 void
360 sctp_cwnd_update_after_ecn_echo(struct sctp_tcb *stcb, struct sctp_nets *net)
361 {
362         int old_cwnd = net->cwnd;
363
364         SCTP_STAT_INCR(sctps_ecnereducedcwnd);
365         net->ssthresh = net->cwnd / 2;
366         if (net->ssthresh < net->mtu) {
367                 net->ssthresh = net->mtu;
368                 /* here back off the timer as well, to slow us down */
369                 net->RTO <<= 1;
370         }
371         net->cwnd = net->ssthresh;
372         if (sctp_logging_level & SCTP_CWND_MONITOR_ENABLE) {
373                 sctp_log_cwnd(stcb, net, (net->cwnd - old_cwnd), SCTP_CWND_LOG_FROM_SAT);
374         }
375 }
376
377 void
378 sctp_cwnd_update_after_packet_dropped(struct sctp_tcb *stcb,
379     struct sctp_nets *net, struct sctp_pktdrop_chunk *cp,
380     uint32_t * bottle_bw, uint32_t * on_queue)
381 {
382         uint32_t bw_avail;
383         int rtt, incr;
384         int old_cwnd = net->cwnd;
385
386         /* need real RTT for this calc */
387         rtt = ((net->lastsa >> 2) + net->lastsv) >> 1;
388         /* get bottle neck bw */
389         *bottle_bw = ntohl(cp->bottle_bw);
390         /* and whats on queue */
391         *on_queue = ntohl(cp->current_onq);
392         /*
393          * adjust the on-queue if our flight is more it could be that the
394          * router has not yet gotten data "in-flight" to it
395          */
396         if (*on_queue < net->flight_size)
397                 *on_queue = net->flight_size;
398         /* calculate the available space */
399         bw_avail = (*bottle_bw * rtt) / 1000;
400         if (bw_avail > *bottle_bw) {
401                 /*
402                  * Cap the growth to no more than the bottle neck. This can
403                  * happen as RTT slides up due to queues. It also means if
404                  * you have more than a 1 second RTT with a empty queue you
405                  * will be limited to the bottle_bw per second no matter if
406                  * other points have 1/2 the RTT and you could get more
407                  * out...
408                  */
409                 bw_avail = *bottle_bw;
410         }
411         if (*on_queue > bw_avail) {
412                 /*
413                  * No room for anything else don't allow anything else to be
414                  * "added to the fire".
415                  */
416                 int seg_inflight, seg_onqueue, my_portion;
417
418                 net->partial_bytes_acked = 0;
419
420                 /* how much are we over queue size? */
421                 incr = *on_queue - bw_avail;
422                 if (stcb->asoc.seen_a_sack_this_pkt) {
423                         /*
424                          * undo any cwnd adjustment that the sack might have
425                          * made
426                          */
427                         net->cwnd = net->prev_cwnd;
428                 }
429                 /* Now how much of that is mine? */
430                 seg_inflight = net->flight_size / net->mtu;
431                 seg_onqueue = *on_queue / net->mtu;
432                 my_portion = (incr * seg_inflight) / seg_onqueue;
433
434                 /* Have I made an adjustment already */
435                 if (net->cwnd > net->flight_size) {
436                         /*
437                          * for this flight I made an adjustment we need to
438                          * decrease the portion by a share our previous
439                          * adjustment.
440                          */
441                         int diff_adj;
442
443                         diff_adj = net->cwnd - net->flight_size;
444                         if (diff_adj > my_portion)
445                                 my_portion = 0;
446                         else
447                                 my_portion -= diff_adj;
448                 }
449                 /*
450                  * back down to the previous cwnd (assume we have had a sack
451                  * before this packet). minus what ever portion of the
452                  * overage is my fault.
453                  */
454                 net->cwnd -= my_portion;
455
456                 /* we will NOT back down more than 1 MTU */
457                 if (net->cwnd <= net->mtu) {
458                         net->cwnd = net->mtu;
459                 }
460                 /* force into CA */
461                 net->ssthresh = net->cwnd - 1;
462         } else {
463                 /*
464                  * Take 1/4 of the space left or max burst up .. whichever
465                  * is less.
466                  */
467                 incr = min((bw_avail - *on_queue) >> 2,
468                     stcb->asoc.max_burst * net->mtu);
469                 net->cwnd += incr;
470         }
471         if (net->cwnd > bw_avail) {
472                 /* We can't exceed the pipe size */
473                 net->cwnd = bw_avail;
474         }
475         if (net->cwnd < net->mtu) {
476                 /* We always have 1 MTU */
477                 net->cwnd = net->mtu;
478         }
479         if (net->cwnd - old_cwnd != 0) {
480                 /* log only changes */
481                 if (sctp_logging_level & SCTP_CWND_MONITOR_ENABLE) {
482                         sctp_log_cwnd(stcb, net, (net->cwnd - old_cwnd),
483                             SCTP_CWND_LOG_FROM_SAT);
484                 }
485         }
486 }
487
488 void
489 sctp_cwnd_update_after_output(struct sctp_tcb *stcb,
490     struct sctp_nets *net, int burst_limit)
491 {
492         int old_cwnd = net->cwnd;
493
494         if (net->ssthresh < net->cwnd)
495                 net->ssthresh = net->cwnd;
496         net->cwnd = (net->flight_size + (burst_limit * net->mtu));
497
498         if (sctp_logging_level & SCTP_CWND_MONITOR_ENABLE) {
499                 sctp_log_cwnd(stcb, net, (net->cwnd - old_cwnd), SCTP_CWND_LOG_FROM_BRST);
500         }
501 }
502
503 void
504 sctp_cwnd_update_after_fr_timer(struct sctp_inpcb *inp,
505     struct sctp_tcb *stcb, struct sctp_nets *net)
506 {
507         int old_cwnd = net->cwnd;
508
509         sctp_chunk_output(inp, stcb, SCTP_OUTPUT_FROM_EARLY_FR_TMR, SCTP_SO_NOT_LOCKED);
510         /*
511          * make a small adjustment to cwnd and force to CA.
512          */
513         if (net->cwnd > net->mtu)
514                 /* drop down one MTU after sending */
515                 net->cwnd -= net->mtu;
516         if (net->cwnd < net->ssthresh)
517                 /* still in SS move to CA */
518                 net->ssthresh = net->cwnd - 1;
519         if (sctp_logging_level & SCTP_CWND_MONITOR_ENABLE) {
520                 sctp_log_cwnd(stcb, net, (old_cwnd - net->cwnd), SCTP_CWND_LOG_FROM_FR);
521         }
522 }
523
524 struct sctp_hs_raise_drop {
525         int32_t cwnd;
526         int32_t increase;
527         int32_t drop_percent;
528 };
529
530 #define SCTP_HS_TABLE_SIZE 73
531
532 struct sctp_hs_raise_drop sctp_cwnd_adjust[SCTP_HS_TABLE_SIZE] = {
533         {38, 1, 50},            /* 0   */
534         {118, 2, 44},           /* 1   */
535         {221, 3, 41},           /* 2   */
536         {347, 4, 38},           /* 3   */
537         {495, 5, 37},           /* 4   */
538         {663, 6, 35},           /* 5   */
539         {851, 7, 34},           /* 6   */
540         {1058, 8, 33},          /* 7   */
541         {1284, 9, 32},          /* 8   */
542         {1529, 10, 31},         /* 9   */
543         {1793, 11, 30},         /* 10  */
544         {2076, 12, 29},         /* 11  */
545         {2378, 13, 28},         /* 12  */
546         {2699, 14, 28},         /* 13  */
547         {3039, 15, 27},         /* 14  */
548         {3399, 16, 27},         /* 15  */
549         {3778, 17, 26},         /* 16  */
550         {4177, 18, 26},         /* 17  */
551         {4596, 19, 25},         /* 18  */
552         {5036, 20, 25},         /* 19  */
553         {5497, 21, 24},         /* 20  */
554         {5979, 22, 24},         /* 21  */
555         {6483, 23, 23},         /* 22  */
556         {7009, 24, 23},         /* 23  */
557         {7558, 25, 22},         /* 24  */
558         {8130, 26, 22},         /* 25  */
559         {8726, 27, 22},         /* 26  */
560         {9346, 28, 21},         /* 27  */
561         {9991, 29, 21},         /* 28  */
562         {10661, 30, 21},        /* 29  */
563         {11358, 31, 20},        /* 30  */
564         {12082, 32, 20},        /* 31  */
565         {12834, 33, 20},        /* 32  */
566         {13614, 34, 19},        /* 33  */
567         {14424, 35, 19},        /* 34  */
568         {15265, 36, 19},        /* 35  */
569         {16137, 37, 19},        /* 36  */
570         {17042, 38, 18},        /* 37  */
571         {17981, 39, 18},        /* 38  */
572         {18955, 40, 18},        /* 39  */
573         {19965, 41, 17},        /* 40  */
574         {21013, 42, 17},        /* 41  */
575         {22101, 43, 17},        /* 42  */
576         {23230, 44, 17},        /* 43  */
577         {24402, 45, 16},        /* 44  */
578         {25618, 46, 16},        /* 45  */
579         {26881, 47, 16},        /* 46  */
580         {28193, 48, 16},        /* 47  */
581         {29557, 49, 15},        /* 48  */
582         {30975, 50, 15},        /* 49  */
583         {32450, 51, 15},        /* 50  */
584         {33986, 52, 15},        /* 51  */
585         {35586, 53, 14},        /* 52  */
586         {37253, 54, 14},        /* 53  */
587         {38992, 55, 14},        /* 54  */
588         {40808, 56, 14},        /* 55  */
589         {42707, 57, 13},        /* 56  */
590         {44694, 58, 13},        /* 57  */
591         {46776, 59, 13},        /* 58  */
592         {48961, 60, 13},        /* 59  */
593         {51258, 61, 13},        /* 60  */
594         {53677, 62, 12},        /* 61  */
595         {56230, 63, 12},        /* 62  */
596         {58932, 64, 12},        /* 63  */
597         {61799, 65, 12},        /* 64  */
598         {64851, 66, 11},        /* 65  */
599         {68113, 67, 11},        /* 66  */
600         {71617, 68, 11},        /* 67  */
601         {75401, 69, 10},        /* 68  */
602         {79517, 70, 10},        /* 69  */
603         {84035, 71, 10},        /* 70  */
604         {89053, 72, 10},        /* 71  */
605         {94717, 73, 9}          /* 72  */
606 };
607
608 static void
609 sctp_hs_cwnd_increase(struct sctp_tcb *stcb, struct sctp_nets *net)
610 {
611         int cur_val, i, indx, incr;
612
613         cur_val = net->cwnd >> 10;
614         indx = SCTP_HS_TABLE_SIZE - 1;
615 #ifdef SCTP_DEBUG
616         printf("HS CC CAlled.\n");
617 #endif
618         if (cur_val < sctp_cwnd_adjust[0].cwnd) {
619                 /* normal mode */
620                 if (net->net_ack > net->mtu) {
621                         net->cwnd += net->mtu;
622                         if (sctp_logging_level & SCTP_CWND_MONITOR_ENABLE) {
623                                 sctp_log_cwnd(stcb, net, net->mtu, SCTP_CWND_LOG_FROM_SS);
624                         }
625                 } else {
626                         net->cwnd += net->net_ack;
627                         if (sctp_logging_level & SCTP_CWND_MONITOR_ENABLE) {
628                                 sctp_log_cwnd(stcb, net, net->net_ack, SCTP_CWND_LOG_FROM_SS);
629                         }
630                 }
631         } else {
632                 for (i = net->last_hs_used; i < SCTP_HS_TABLE_SIZE; i++) {
633                         if (cur_val < sctp_cwnd_adjust[i].cwnd) {
634                                 indx = i;
635                                 break;
636                         }
637                 }
638                 net->last_hs_used = indx;
639                 incr = ((sctp_cwnd_adjust[indx].increase) << 10);
640                 net->cwnd += incr;
641                 if (sctp_logging_level & SCTP_CWND_MONITOR_ENABLE) {
642                         sctp_log_cwnd(stcb, net, incr, SCTP_CWND_LOG_FROM_SS);
643                 }
644         }
645 }
646
647 static void
648 sctp_hs_cwnd_decrease(struct sctp_tcb *stcb, struct sctp_nets *net)
649 {
650         int cur_val, i, indx;
651         int old_cwnd = net->cwnd;
652
653         cur_val = net->cwnd >> 10;
654         indx = net->last_hs_used;
655         if (cur_val < sctp_cwnd_adjust[0].cwnd) {
656                 /* normal mode */
657                 net->ssthresh = net->cwnd / 2;
658                 if (net->ssthresh < (net->mtu * 2)) {
659                         net->ssthresh = 2 * net->mtu;
660                 }
661                 net->cwnd = net->ssthresh;
662         } else {
663                 /* drop by the proper amount */
664                 net->ssthresh = net->cwnd - (int)((net->cwnd / 100) *
665                     sctp_cwnd_adjust[net->last_hs_used].drop_percent);
666                 net->cwnd = net->ssthresh;
667                 /* now where are we */
668                 indx = net->last_hs_used;
669                 cur_val = net->cwnd >> 10;
670                 /* reset where we are in the table */
671                 if (cur_val < sctp_cwnd_adjust[0].cwnd) {
672                         /* feel out of hs */
673                         net->last_hs_used = 0;
674                 } else {
675                         for (i = indx; i >= 1; i--) {
676                                 if (cur_val > sctp_cwnd_adjust[i - 1].cwnd) {
677                                         break;
678                                 }
679                         }
680                         net->last_hs_used = indx;
681                 }
682         }
683         if (sctp_logging_level & SCTP_CWND_MONITOR_ENABLE) {
684                 sctp_log_cwnd(stcb, net, (net->cwnd - old_cwnd), SCTP_CWND_LOG_FROM_FR);
685         }
686 }
687
688 void
689 sctp_hs_cwnd_update_after_fr(struct sctp_tcb *stcb,
690     struct sctp_association *asoc)
691 {
692         struct sctp_nets *net;
693
694         /*
695          * CMT fast recovery code. Need to debug. ((sctp_cmt_on_off == 1) &&
696          * (net->fast_retran_loss_recovery == 0)))
697          */
698         TAILQ_FOREACH(net, &asoc->nets, sctp_next) {
699                 if ((asoc->fast_retran_loss_recovery == 0) || (sctp_cmt_on_off == 1)) {
700                         /* out of a RFC2582 Fast recovery window? */
701                         if (net->net_ack > 0) {
702                                 /*
703                                  * per section 7.2.3, are there any
704                                  * destinations that had a fast retransmit
705                                  * to them. If so what we need to do is
706                                  * adjust ssthresh and cwnd.
707                                  */
708                                 struct sctp_tmit_chunk *lchk;
709
710                                 sctp_hs_cwnd_decrease(stcb, net);
711
712                                 lchk = TAILQ_FIRST(&asoc->send_queue);
713
714                                 net->partial_bytes_acked = 0;
715                                 /* Turn on fast recovery window */
716                                 asoc->fast_retran_loss_recovery = 1;
717                                 if (lchk == NULL) {
718                                         /* Mark end of the window */
719                                         asoc->fast_recovery_tsn = asoc->sending_seq - 1;
720                                 } else {
721                                         asoc->fast_recovery_tsn = lchk->rec.data.TSN_seq - 1;
722                                 }
723
724                                 /*
725                                  * CMT fast recovery -- per destination
726                                  * recovery variable.
727                                  */
728                                 net->fast_retran_loss_recovery = 1;
729
730                                 if (lchk == NULL) {
731                                         /* Mark end of the window */
732                                         net->fast_recovery_tsn = asoc->sending_seq - 1;
733                                 } else {
734                                         net->fast_recovery_tsn = lchk->rec.data.TSN_seq - 1;
735                                 }
736
737                                 /*
738                                  * Disable Nonce Sum Checking and store the
739                                  * resync tsn
740                                  */
741                                 asoc->nonce_sum_check = 0;
742                                 asoc->nonce_resync_tsn = asoc->fast_recovery_tsn + 1;
743
744                                 sctp_timer_stop(SCTP_TIMER_TYPE_SEND,
745                                     stcb->sctp_ep, stcb, net, SCTP_FROM_SCTP_INDATA + SCTP_LOC_32);
746                                 sctp_timer_start(SCTP_TIMER_TYPE_SEND,
747                                     stcb->sctp_ep, stcb, net);
748                         }
749                 } else if (net->net_ack > 0) {
750                         /*
751                          * Mark a peg that we WOULD have done a cwnd
752                          * reduction but RFC2582 prevented this action.
753                          */
754                         SCTP_STAT_INCR(sctps_fastretransinrtt);
755                 }
756         }
757 }
758
759 void
760 sctp_hs_cwnd_update_after_sack(struct sctp_tcb *stcb,
761     struct sctp_association *asoc,
762     int accum_moved, int reneged_all, int will_exit)
763 {
764         struct sctp_nets *net;
765
766         /******************************/
767         /* update cwnd and Early FR   */
768         /******************************/
769         TAILQ_FOREACH(net, &asoc->nets, sctp_next) {
770
771 #ifdef JANA_CMT_FAST_RECOVERY
772                 /*
773                  * CMT fast recovery code. Need to debug.
774                  */
775                 if (net->fast_retran_loss_recovery && net->new_pseudo_cumack) {
776                         if (compare_with_wrap(asoc->last_acked_seq,
777                             net->fast_recovery_tsn, MAX_TSN) ||
778                             (asoc->last_acked_seq == net->fast_recovery_tsn) ||
779                             compare_with_wrap(net->pseudo_cumack, net->fast_recovery_tsn, MAX_TSN) ||
780                             (net->pseudo_cumack == net->fast_recovery_tsn)) {
781                                 net->will_exit_fast_recovery = 1;
782                         }
783                 }
784 #endif
785                 if (sctp_early_fr) {
786                         /*
787                          * So, first of all do we need to have a Early FR
788                          * timer running?
789                          */
790                         if (((TAILQ_FIRST(&asoc->sent_queue)) &&
791                             (net->ref_count > 1) &&
792                             (net->flight_size < net->cwnd)) ||
793                             (reneged_all)) {
794                                 /*
795                                  * yes, so in this case stop it if its
796                                  * running, and then restart it. Reneging
797                                  * all is a special case where we want to
798                                  * run the Early FR timer and then force the
799                                  * last few unacked to be sent, causing us
800                                  * to illicit a sack with gaps to force out
801                                  * the others.
802                                  */
803                                 if (SCTP_OS_TIMER_PENDING(&net->fr_timer.timer)) {
804                                         SCTP_STAT_INCR(sctps_earlyfrstpidsck2);
805                                         sctp_timer_stop(SCTP_TIMER_TYPE_EARLYFR, stcb->sctp_ep, stcb, net,
806                                             SCTP_FROM_SCTP_INDATA + SCTP_LOC_20);
807                                 }
808                                 SCTP_STAT_INCR(sctps_earlyfrstrid);
809                                 sctp_timer_start(SCTP_TIMER_TYPE_EARLYFR, stcb->sctp_ep, stcb, net);
810                         } else {
811                                 /* No, stop it if its running */
812                                 if (SCTP_OS_TIMER_PENDING(&net->fr_timer.timer)) {
813                                         SCTP_STAT_INCR(sctps_earlyfrstpidsck3);
814                                         sctp_timer_stop(SCTP_TIMER_TYPE_EARLYFR, stcb->sctp_ep, stcb, net,
815                                             SCTP_FROM_SCTP_INDATA + SCTP_LOC_21);
816                                 }
817                         }
818                 }
819                 /* if nothing was acked on this destination skip it */
820                 if (net->net_ack == 0) {
821                         if (sctp_logging_level & SCTP_CWND_LOGGING_ENABLE) {
822                                 sctp_log_cwnd(stcb, net, 0, SCTP_CWND_LOG_FROM_SACK);
823                         }
824                         continue;
825                 }
826                 if (net->net_ack2 > 0) {
827                         /*
828                          * Karn's rule applies to clearing error count, this
829                          * is optional.
830                          */
831                         net->error_count = 0;
832                         if ((net->dest_state & SCTP_ADDR_NOT_REACHABLE) ==
833                             SCTP_ADDR_NOT_REACHABLE) {
834                                 /* addr came good */
835                                 net->dest_state &= ~SCTP_ADDR_NOT_REACHABLE;
836                                 net->dest_state |= SCTP_ADDR_REACHABLE;
837                                 sctp_ulp_notify(SCTP_NOTIFY_INTERFACE_UP, stcb,
838                                     SCTP_RECEIVED_SACK, (void *)net, SCTP_SO_NOT_LOCKED);
839                                 /* now was it the primary? if so restore */
840                                 if (net->dest_state & SCTP_ADDR_WAS_PRIMARY) {
841                                         (void)sctp_set_primary_addr(stcb, (struct sockaddr *)NULL, net);
842                                 }
843                         }
844                         /*
845                          * JRS 5/14/07 - If CMT PF is on and the destination
846                          * is in PF state, set the destination to active
847                          * state and set the cwnd to one or two MTU's based
848                          * on whether PF1 or PF2 is being used.
849                          * 
850                          * Should we stop any running T3 timer here?
851                          */
852                         if (sctp_cmt_on_off && sctp_cmt_pf && ((net->dest_state & SCTP_ADDR_PF) ==
853                             SCTP_ADDR_PF)) {
854                                 net->dest_state &= ~SCTP_ADDR_PF;
855                                 net->cwnd = net->mtu * sctp_cmt_pf;
856                                 SCTPDBG(SCTP_DEBUG_INDATA1, "Destination %p moved from PF to reachable with cwnd %d.\n",
857                                     net, net->cwnd);
858                                 /*
859                                  * Since the cwnd value is explicitly set,
860                                  * skip the code that updates the cwnd
861                                  * value.
862                                  */
863                                 goto skip_cwnd_update;
864                         }
865                 }
866 #ifdef JANA_CMT_FAST_RECOVERY
867                 /*
868                  * CMT fast recovery code
869                  */
870                 /*
871                  * if (sctp_cmt_on_off == 1 &&
872                  * net->fast_retran_loss_recovery &&
873                  * net->will_exit_fast_recovery == 0) { @@@ Do something }
874                  * else if (sctp_cmt_on_off == 0 &&
875                  * asoc->fast_retran_loss_recovery && will_exit == 0) {
876                  */
877 #endif
878
879                 if (asoc->fast_retran_loss_recovery && will_exit == 0 && sctp_cmt_on_off == 0) {
880                         /*
881                          * If we are in loss recovery we skip any cwnd
882                          * update
883                          */
884                         goto skip_cwnd_update;
885                 }
886                 /*
887                  * CMT: CUC algorithm. Update cwnd if pseudo-cumack has
888                  * moved.
889                  */
890                 if (accum_moved || (sctp_cmt_on_off && net->new_pseudo_cumack)) {
891                         /* If the cumulative ack moved we can proceed */
892                         if (net->cwnd <= net->ssthresh) {
893                                 /* We are in slow start */
894                                 if (net->flight_size + net->net_ack >= net->cwnd) {
895
896                                         sctp_hs_cwnd_increase(stcb, net);
897
898                                 } else {
899                                         if (sctp_logging_level & SCTP_CWND_LOGGING_ENABLE) {
900                                                 sctp_log_cwnd(stcb, net, net->net_ack,
901                                                     SCTP_CWND_LOG_NOADV_SS);
902                                         }
903                                 }
904                         } else {
905                                 /* We are in congestion avoidance */
906                                 net->partial_bytes_acked += net->net_ack;
907                                 if ((net->flight_size + net->net_ack >= net->cwnd) &&
908                                     (net->partial_bytes_acked >= net->cwnd)) {
909                                         net->partial_bytes_acked -= net->cwnd;
910                                         net->cwnd += net->mtu;
911                                         if (sctp_logging_level & SCTP_CWND_MONITOR_ENABLE) {
912                                                 sctp_log_cwnd(stcb, net, net->mtu,
913                                                     SCTP_CWND_LOG_FROM_CA);
914                                         }
915                                 } else {
916                                         if (sctp_logging_level & SCTP_CWND_LOGGING_ENABLE) {
917                                                 sctp_log_cwnd(stcb, net, net->net_ack,
918                                                     SCTP_CWND_LOG_NOADV_CA);
919                                         }
920                                 }
921                         }
922                 } else {
923                         if (sctp_logging_level & SCTP_CWND_LOGGING_ENABLE) {
924                                 sctp_log_cwnd(stcb, net, net->mtu,
925                                     SCTP_CWND_LOG_NO_CUMACK);
926                         }
927                 }
928 skip_cwnd_update:
929                 /*
930                  * NOW, according to Karn's rule do we need to restore the
931                  * RTO timer back? Check our net_ack2. If not set then we
932                  * have a ambiguity.. i.e. all data ack'd was sent to more
933                  * than one place.
934                  */
935                 if (net->net_ack2) {
936                         /* restore any doubled timers */
937                         net->RTO = ((net->lastsa >> 2) + net->lastsv) >> 1;
938                         if (net->RTO < stcb->asoc.minrto) {
939                                 net->RTO = stcb->asoc.minrto;
940                         }
941                         if (net->RTO > stcb->asoc.maxrto) {
942                                 net->RTO = stcb->asoc.maxrto;
943                         }
944                 }
945         }
946 }
947
948
949 /*
950  * H-TCP congestion control. The algorithm is detailed in:
951  * R.N.Shorten, D.J.Leith:
952  *   "H-TCP: TCP for high-speed and long-distance networks"
953  *   Proc. PFLDnet, Argonne, 2004.
954  * http://www.hamilton.ie/net/htcp3.pdf
955  */
956
957
958 static int use_rtt_scaling = 1;
959 static int use_bandwidth_switch = 1;
960
961 static inline int
962 between(uint32_t seq1, uint32_t seq2, uint32_t seq3)
963 {
964         return seq3 - seq2 >= seq1 - seq2;
965 }
966
967 static inline uint32_t
968 htcp_cong_time(struct htcp *ca)
969 {
970         return sctp_get_tick_count() - ca->last_cong;
971 }
972
973 static inline uint32_t
974 htcp_ccount(struct htcp *ca)
975 {
976         return htcp_cong_time(ca) / ca->minRTT;
977 }
978
979 static inline void
980 htcp_reset(struct htcp *ca)
981 {
982         ca->undo_last_cong = ca->last_cong;
983         ca->undo_maxRTT = ca->maxRTT;
984         ca->undo_old_maxB = ca->old_maxB;
985         ca->last_cong = sctp_get_tick_count();
986 }
987
988 #ifdef SCTP_NOT_USED
989
990 static uint32_t
991 htcp_cwnd_undo(struct sctp_tcb *stcb, struct sctp_nets *net)
992 {
993         net->htcp_ca.last_cong = net->htcp_ca.undo_last_cong;
994         net->htcp_ca.maxRTT = net->htcp_ca.undo_maxRTT;
995         net->htcp_ca.old_maxB = net->htcp_ca.undo_old_maxB;
996         return max(net->cwnd, ((net->ssthresh / net->mtu << 7) / net->htcp_ca.beta) * net->mtu);
997 }
998
999 #endif
1000
1001 static inline void
1002 measure_rtt(struct sctp_tcb *stcb, struct sctp_nets *net)
1003 {
1004         uint32_t srtt = net->lastsa >> 3;
1005
1006         /* keep track of minimum RTT seen so far, minRTT is zero at first */
1007         if (net->htcp_ca.minRTT > srtt || !net->htcp_ca.minRTT)
1008                 net->htcp_ca.minRTT = srtt;
1009
1010         /* max RTT */
1011         if (net->fast_retran_ip == 0 && net->ssthresh < 0xFFFF && htcp_ccount(&net->htcp_ca) > 3) {
1012                 if (net->htcp_ca.maxRTT < net->htcp_ca.minRTT)
1013                         net->htcp_ca.maxRTT = net->htcp_ca.minRTT;
1014                 if (net->htcp_ca.maxRTT < srtt && srtt <= net->htcp_ca.maxRTT + MSEC_TO_TICKS(20))
1015                         net->htcp_ca.maxRTT = srtt;
1016         }
1017 }
1018
1019 static void
1020 measure_achieved_throughput(struct sctp_tcb *stcb, struct sctp_nets *net)
1021 {
1022         uint32_t now = sctp_get_tick_count();
1023
1024         if (net->fast_retran_ip == 0)
1025                 net->htcp_ca.bytes_acked = net->net_ack;
1026
1027         if (!use_bandwidth_switch)
1028                 return;
1029
1030         /* achieved throughput calculations */
1031         /* JRS - not 100% sure of this statement */
1032         if (net->fast_retran_ip == 1) {
1033                 net->htcp_ca.bytecount = 0;
1034                 net->htcp_ca.lasttime = now;
1035                 return;
1036         }
1037         net->htcp_ca.bytecount += net->net_ack;
1038
1039         if (net->htcp_ca.bytecount >= net->cwnd - ((net->htcp_ca.alpha >> 7 ? : 1) * net->mtu)
1040             && now - net->htcp_ca.lasttime >= net->htcp_ca.minRTT
1041             && net->htcp_ca.minRTT > 0) {
1042                 uint32_t cur_Bi = net->htcp_ca.bytecount / net->mtu * hz / (now - net->htcp_ca.lasttime);
1043
1044                 if (htcp_ccount(&net->htcp_ca) <= 3) {
1045                         /* just after backoff */
1046                         net->htcp_ca.minB = net->htcp_ca.maxB = net->htcp_ca.Bi = cur_Bi;
1047                 } else {
1048                         net->htcp_ca.Bi = (3 * net->htcp_ca.Bi + cur_Bi) / 4;
1049                         if (net->htcp_ca.Bi > net->htcp_ca.maxB)
1050                                 net->htcp_ca.maxB = net->htcp_ca.Bi;
1051                         if (net->htcp_ca.minB > net->htcp_ca.maxB)
1052                                 net->htcp_ca.minB = net->htcp_ca.maxB;
1053                 }
1054                 net->htcp_ca.bytecount = 0;
1055                 net->htcp_ca.lasttime = now;
1056         }
1057 }
1058
1059 static inline void
1060 htcp_beta_update(struct htcp *ca, uint32_t minRTT, uint32_t maxRTT)
1061 {
1062         if (use_bandwidth_switch) {
1063                 uint32_t maxB = ca->maxB;
1064                 uint32_t old_maxB = ca->old_maxB;
1065
1066                 ca->old_maxB = ca->maxB;
1067
1068                 if (!between(5 * maxB, 4 * old_maxB, 6 * old_maxB)) {
1069                         ca->beta = BETA_MIN;
1070                         ca->modeswitch = 0;
1071                         return;
1072                 }
1073         }
1074         if (ca->modeswitch && minRTT > (uint32_t) MSEC_TO_TICKS(10) && maxRTT) {
1075                 ca->beta = (minRTT << 7) / maxRTT;
1076                 if (ca->beta < BETA_MIN)
1077                         ca->beta = BETA_MIN;
1078                 else if (ca->beta > BETA_MAX)
1079                         ca->beta = BETA_MAX;
1080         } else {
1081                 ca->beta = BETA_MIN;
1082                 ca->modeswitch = 1;
1083         }
1084 }
1085
1086 static inline void
1087 htcp_alpha_update(struct htcp *ca)
1088 {
1089         uint32_t minRTT = ca->minRTT;
1090         uint32_t factor = 1;
1091         uint32_t diff = htcp_cong_time(ca);
1092
1093         if (diff > (uint32_t) hz) {
1094                 diff -= hz;
1095                 factor = 1 + (10 * diff + ((diff / 2) * (diff / 2) / hz)) / hz;
1096         }
1097         if (use_rtt_scaling && minRTT) {
1098                 uint32_t scale = (hz << 3) / (10 * minRTT);
1099
1100                 scale = min(max(scale, 1U << 2), 10U << 3);     /* clamping ratio to
1101                                                                  * interval [0.5,10]<<3 */
1102                 factor = (factor << 3) / scale;
1103                 if (!factor)
1104                         factor = 1;
1105         }
1106         ca->alpha = 2 * factor * ((1 << 7) - ca->beta);
1107         if (!ca->alpha)
1108                 ca->alpha = ALPHA_BASE;
1109 }
1110
1111 /* After we have the rtt data to calculate beta, we'd still prefer to wait one
1112  * rtt before we adjust our beta to ensure we are working from a consistent
1113  * data.
1114  *
1115  * This function should be called when we hit a congestion event since only at
1116  * that point do we really have a real sense of maxRTT (the queues en route
1117  * were getting just too full now).
1118  */
1119 static void
1120 htcp_param_update(struct sctp_tcb *stcb, struct sctp_nets *net)
1121 {
1122         uint32_t minRTT = net->htcp_ca.minRTT;
1123         uint32_t maxRTT = net->htcp_ca.maxRTT;
1124
1125         htcp_beta_update(&net->htcp_ca, minRTT, maxRTT);
1126         htcp_alpha_update(&net->htcp_ca);
1127
1128         /*
1129          * add slowly fading memory for maxRTT to accommodate routing
1130          * changes etc
1131          */
1132         if (minRTT > 0 && maxRTT > minRTT)
1133                 net->htcp_ca.maxRTT = minRTT + ((maxRTT - minRTT) * 95) / 100;
1134 }
1135
1136 static uint32_t
1137 htcp_recalc_ssthresh(struct sctp_tcb *stcb, struct sctp_nets *net)
1138 {
1139         htcp_param_update(stcb, net);
1140         return max(((net->cwnd / net->mtu * net->htcp_ca.beta) >> 7) * net->mtu, 2U * net->mtu);
1141 }
1142
1143 static void
1144 htcp_cong_avoid(struct sctp_tcb *stcb, struct sctp_nets *net)
1145 {
1146         /*-
1147          * How to handle these functions?
1148          *      if (!tcp_is_cwnd_limited(sk, in_flight)) RRS - good question.
1149          *              return;
1150          */
1151         if (net->cwnd <= net->ssthresh) {
1152                 /* We are in slow start */
1153                 if (net->flight_size + net->net_ack >= net->cwnd) {
1154                         if (net->net_ack > (net->mtu * sctp_L2_abc_variable)) {
1155                                 net->cwnd += (net->mtu * sctp_L2_abc_variable);
1156                                 if (sctp_logging_level & SCTP_CWND_MONITOR_ENABLE) {
1157                                         sctp_log_cwnd(stcb, net, net->mtu,
1158                                             SCTP_CWND_LOG_FROM_SS);
1159                                 }
1160                         } else {
1161                                 net->cwnd += net->net_ack;
1162                                 if (sctp_logging_level & SCTP_CWND_MONITOR_ENABLE) {
1163                                         sctp_log_cwnd(stcb, net, net->net_ack,
1164                                             SCTP_CWND_LOG_FROM_SS);
1165                                 }
1166                         }
1167                 } else {
1168                         if (sctp_logging_level & SCTP_CWND_LOGGING_ENABLE) {
1169                                 sctp_log_cwnd(stcb, net, net->net_ack,
1170                                     SCTP_CWND_LOG_NOADV_SS);
1171                         }
1172                 }
1173         } else {
1174                 measure_rtt(stcb, net);
1175
1176                 /*
1177                  * In dangerous area, increase slowly. In theory this is
1178                  * net->cwnd += alpha / net->cwnd
1179                  */
1180                 /* What is snd_cwnd_cnt?? */
1181                 if (((net->partial_bytes_acked / net->mtu * net->htcp_ca.alpha) >> 7) * net->mtu >= net->cwnd) {
1182                         /*-
1183                          * Does SCTP have a cwnd clamp?
1184                          * if (net->snd_cwnd < net->snd_cwnd_clamp) - Nope (RRS).
1185                          */
1186                         net->cwnd += net->mtu;
1187                         net->partial_bytes_acked = 0;
1188                         htcp_alpha_update(&net->htcp_ca);
1189                         if (sctp_logging_level & SCTP_CWND_MONITOR_ENABLE) {
1190                                 sctp_log_cwnd(stcb, net, net->mtu,
1191                                     SCTP_CWND_LOG_FROM_CA);
1192                         }
1193                 } else {
1194                         net->partial_bytes_acked += net->net_ack;
1195                         if (sctp_logging_level & SCTP_CWND_LOGGING_ENABLE) {
1196                                 sctp_log_cwnd(stcb, net, net->net_ack,
1197                                     SCTP_CWND_LOG_NOADV_CA);
1198                         }
1199                 }
1200
1201                 net->htcp_ca.bytes_acked = net->mtu;
1202         }
1203 }
1204
1205 #ifdef SCTP_NOT_USED
1206 /* Lower bound on congestion window. */
1207 static uint32_t
1208 htcp_min_cwnd(struct sctp_tcb *stcb, struct sctp_nets *net)
1209 {
1210         return net->ssthresh;
1211 }
1212
1213 #endif
1214
1215 static void
1216 htcp_init(struct sctp_tcb *stcb, struct sctp_nets *net)
1217 {
1218         memset(&net->htcp_ca, 0, sizeof(struct htcp));
1219         net->htcp_ca.alpha = ALPHA_BASE;
1220         net->htcp_ca.beta = BETA_MIN;
1221         net->htcp_ca.bytes_acked = net->mtu;
1222         net->htcp_ca.last_cong = sctp_get_tick_count();
1223 }
1224
1225 void
1226 sctp_htcp_set_initial_cc_param(struct sctp_tcb *stcb, struct sctp_nets *net)
1227 {
1228         /*
1229          * We take the max of the burst limit times a MTU or the
1230          * INITIAL_CWND. We then limit this to 4 MTU's of sending.
1231          */
1232         net->cwnd = min((net->mtu * 4), max((2 * net->mtu), SCTP_INITIAL_CWND));
1233         net->ssthresh = stcb->asoc.peers_rwnd;
1234         htcp_init(stcb, net);
1235
1236         if (sctp_logging_level & (SCTP_CWND_MONITOR_ENABLE | SCTP_CWND_LOGGING_ENABLE)) {
1237                 sctp_log_cwnd(stcb, net, 0, SCTP_CWND_INITIALIZATION);
1238         }
1239 }
1240
1241 void
1242 sctp_htcp_cwnd_update_after_sack(struct sctp_tcb *stcb,
1243     struct sctp_association *asoc,
1244     int accum_moved, int reneged_all, int will_exit)
1245 {
1246         struct sctp_nets *net;
1247
1248         /******************************/
1249         /* update cwnd and Early FR   */
1250         /******************************/
1251         TAILQ_FOREACH(net, &asoc->nets, sctp_next) {
1252
1253 #ifdef JANA_CMT_FAST_RECOVERY
1254                 /*
1255                  * CMT fast recovery code. Need to debug.
1256                  */
1257                 if (net->fast_retran_loss_recovery && net->new_pseudo_cumack) {
1258                         if (compare_with_wrap(asoc->last_acked_seq,
1259                             net->fast_recovery_tsn, MAX_TSN) ||
1260                             (asoc->last_acked_seq == net->fast_recovery_tsn) ||
1261                             compare_with_wrap(net->pseudo_cumack, net->fast_recovery_tsn, MAX_TSN) ||
1262                             (net->pseudo_cumack == net->fast_recovery_tsn)) {
1263                                 net->will_exit_fast_recovery = 1;
1264                         }
1265                 }
1266 #endif
1267                 if (sctp_early_fr) {
1268                         /*
1269                          * So, first of all do we need to have a Early FR
1270                          * timer running?
1271                          */
1272                         if (((TAILQ_FIRST(&asoc->sent_queue)) &&
1273                             (net->ref_count > 1) &&
1274                             (net->flight_size < net->cwnd)) ||
1275                             (reneged_all)) {
1276                                 /*
1277                                  * yes, so in this case stop it if its
1278                                  * running, and then restart it. Reneging
1279                                  * all is a special case where we want to
1280                                  * run the Early FR timer and then force the
1281                                  * last few unacked to be sent, causing us
1282                                  * to illicit a sack with gaps to force out
1283                                  * the others.
1284                                  */
1285                                 if (SCTP_OS_TIMER_PENDING(&net->fr_timer.timer)) {
1286                                         SCTP_STAT_INCR(sctps_earlyfrstpidsck2);
1287                                         sctp_timer_stop(SCTP_TIMER_TYPE_EARLYFR, stcb->sctp_ep, stcb, net,
1288                                             SCTP_FROM_SCTP_INDATA + SCTP_LOC_20);
1289                                 }
1290                                 SCTP_STAT_INCR(sctps_earlyfrstrid);
1291                                 sctp_timer_start(SCTP_TIMER_TYPE_EARLYFR, stcb->sctp_ep, stcb, net);
1292                         } else {
1293                                 /* No, stop it if its running */
1294                                 if (SCTP_OS_TIMER_PENDING(&net->fr_timer.timer)) {
1295                                         SCTP_STAT_INCR(sctps_earlyfrstpidsck3);
1296                                         sctp_timer_stop(SCTP_TIMER_TYPE_EARLYFR, stcb->sctp_ep, stcb, net,
1297                                             SCTP_FROM_SCTP_INDATA + SCTP_LOC_21);
1298                                 }
1299                         }
1300                 }
1301                 /* if nothing was acked on this destination skip it */
1302                 if (net->net_ack == 0) {
1303                         if (sctp_logging_level & SCTP_CWND_LOGGING_ENABLE) {
1304                                 sctp_log_cwnd(stcb, net, 0, SCTP_CWND_LOG_FROM_SACK);
1305                         }
1306                         continue;
1307                 }
1308                 if (net->net_ack2 > 0) {
1309                         /*
1310                          * Karn's rule applies to clearing error count, this
1311                          * is optional.
1312                          */
1313                         net->error_count = 0;
1314                         if ((net->dest_state & SCTP_ADDR_NOT_REACHABLE) ==
1315                             SCTP_ADDR_NOT_REACHABLE) {
1316                                 /* addr came good */
1317                                 net->dest_state &= ~SCTP_ADDR_NOT_REACHABLE;
1318                                 net->dest_state |= SCTP_ADDR_REACHABLE;
1319                                 sctp_ulp_notify(SCTP_NOTIFY_INTERFACE_UP, stcb,
1320                                     SCTP_RECEIVED_SACK, (void *)net, SCTP_SO_NOT_LOCKED);
1321                                 /* now was it the primary? if so restore */
1322                                 if (net->dest_state & SCTP_ADDR_WAS_PRIMARY) {
1323                                         (void)sctp_set_primary_addr(stcb, (struct sockaddr *)NULL, net);
1324                                 }
1325                         }
1326                         /*
1327                          * JRS 5/14/07 - If CMT PF is on and the destination
1328                          * is in PF state, set the destination to active
1329                          * state and set the cwnd to one or two MTU's based
1330                          * on whether PF1 or PF2 is being used.
1331                          * 
1332                          * Should we stop any running T3 timer here?
1333                          */
1334                         if (sctp_cmt_on_off && sctp_cmt_pf && ((net->dest_state & SCTP_ADDR_PF) ==
1335                             SCTP_ADDR_PF)) {
1336                                 net->dest_state &= ~SCTP_ADDR_PF;
1337                                 net->cwnd = net->mtu * sctp_cmt_pf;
1338                                 SCTPDBG(SCTP_DEBUG_INDATA1, "Destination %p moved from PF to reachable with cwnd %d.\n",
1339                                     net, net->cwnd);
1340                                 /*
1341                                  * Since the cwnd value is explicitly set,
1342                                  * skip the code that updates the cwnd
1343                                  * value.
1344                                  */
1345                                 goto skip_cwnd_update;
1346                         }
1347                 }
1348 #ifdef JANA_CMT_FAST_RECOVERY
1349                 /*
1350                  * CMT fast recovery code
1351                  */
1352                 /*
1353                  * if (sctp_cmt_on_off == 1 &&
1354                  * net->fast_retran_loss_recovery &&
1355                  * net->will_exit_fast_recovery == 0) { @@@ Do something }
1356                  * else if (sctp_cmt_on_off == 0 &&
1357                  * asoc->fast_retran_loss_recovery && will_exit == 0) {
1358                  */
1359 #endif
1360
1361                 if (asoc->fast_retran_loss_recovery && will_exit == 0 && sctp_cmt_on_off == 0) {
1362                         /*
1363                          * If we are in loss recovery we skip any cwnd
1364                          * update
1365                          */
1366                         goto skip_cwnd_update;
1367                 }
1368                 /*
1369                  * CMT: CUC algorithm. Update cwnd if pseudo-cumack has
1370                  * moved.
1371                  */
1372                 if (accum_moved || (sctp_cmt_on_off && net->new_pseudo_cumack)) {
1373                         htcp_cong_avoid(stcb, net);
1374                         measure_achieved_throughput(stcb, net);
1375                 } else {
1376                         if (sctp_logging_level & SCTP_CWND_LOGGING_ENABLE) {
1377                                 sctp_log_cwnd(stcb, net, net->mtu,
1378                                     SCTP_CWND_LOG_NO_CUMACK);
1379                         }
1380                 }
1381 skip_cwnd_update:
1382                 /*
1383                  * NOW, according to Karn's rule do we need to restore the
1384                  * RTO timer back? Check our net_ack2. If not set then we
1385                  * have a ambiguity.. i.e. all data ack'd was sent to more
1386                  * than one place.
1387                  */
1388                 if (net->net_ack2) {
1389                         /* restore any doubled timers */
1390                         net->RTO = ((net->lastsa >> 2) + net->lastsv) >> 1;
1391                         if (net->RTO < stcb->asoc.minrto) {
1392                                 net->RTO = stcb->asoc.minrto;
1393                         }
1394                         if (net->RTO > stcb->asoc.maxrto) {
1395                                 net->RTO = stcb->asoc.maxrto;
1396                         }
1397                 }
1398         }
1399 }
1400
1401 void
1402 sctp_htcp_cwnd_update_after_fr(struct sctp_tcb *stcb,
1403     struct sctp_association *asoc)
1404 {
1405         struct sctp_nets *net;
1406
1407         /*
1408          * CMT fast recovery code. Need to debug. ((sctp_cmt_on_off == 1) &&
1409          * (net->fast_retran_loss_recovery == 0)))
1410          */
1411         TAILQ_FOREACH(net, &asoc->nets, sctp_next) {
1412                 if ((asoc->fast_retran_loss_recovery == 0) || (sctp_cmt_on_off == 1)) {
1413                         /* out of a RFC2582 Fast recovery window? */
1414                         if (net->net_ack > 0) {
1415                                 /*
1416                                  * per section 7.2.3, are there any
1417                                  * destinations that had a fast retransmit
1418                                  * to them. If so what we need to do is
1419                                  * adjust ssthresh and cwnd.
1420                                  */
1421                                 struct sctp_tmit_chunk *lchk;
1422                                 int old_cwnd = net->cwnd;
1423
1424                                 /* JRS - reset as if state were changed */
1425                                 htcp_reset(&net->htcp_ca);
1426                                 net->ssthresh = htcp_recalc_ssthresh(stcb, net);
1427                                 net->cwnd = net->ssthresh;
1428                                 if (sctp_logging_level & SCTP_CWND_MONITOR_ENABLE) {
1429                                         sctp_log_cwnd(stcb, net, (net->cwnd - old_cwnd),
1430                                             SCTP_CWND_LOG_FROM_FR);
1431                                 }
1432                                 lchk = TAILQ_FIRST(&asoc->send_queue);
1433
1434                                 net->partial_bytes_acked = 0;
1435                                 /* Turn on fast recovery window */
1436                                 asoc->fast_retran_loss_recovery = 1;
1437                                 if (lchk == NULL) {
1438                                         /* Mark end of the window */
1439                                         asoc->fast_recovery_tsn = asoc->sending_seq - 1;
1440                                 } else {
1441                                         asoc->fast_recovery_tsn = lchk->rec.data.TSN_seq - 1;
1442                                 }
1443
1444                                 /*
1445                                  * CMT fast recovery -- per destination
1446                                  * recovery variable.
1447                                  */
1448                                 net->fast_retran_loss_recovery = 1;
1449
1450                                 if (lchk == NULL) {
1451                                         /* Mark end of the window */
1452                                         net->fast_recovery_tsn = asoc->sending_seq - 1;
1453                                 } else {
1454                                         net->fast_recovery_tsn = lchk->rec.data.TSN_seq - 1;
1455                                 }
1456
1457                                 /*
1458                                  * Disable Nonce Sum Checking and store the
1459                                  * resync tsn
1460                                  */
1461                                 asoc->nonce_sum_check = 0;
1462                                 asoc->nonce_resync_tsn = asoc->fast_recovery_tsn + 1;
1463
1464                                 sctp_timer_stop(SCTP_TIMER_TYPE_SEND,
1465                                     stcb->sctp_ep, stcb, net, SCTP_FROM_SCTP_INDATA + SCTP_LOC_32);
1466                                 sctp_timer_start(SCTP_TIMER_TYPE_SEND,
1467                                     stcb->sctp_ep, stcb, net);
1468                         }
1469                 } else if (net->net_ack > 0) {
1470                         /*
1471                          * Mark a peg that we WOULD have done a cwnd
1472                          * reduction but RFC2582 prevented this action.
1473                          */
1474                         SCTP_STAT_INCR(sctps_fastretransinrtt);
1475                 }
1476         }
1477 }
1478
1479 void
1480 sctp_htcp_cwnd_update_after_timeout(struct sctp_tcb *stcb,
1481     struct sctp_nets *net)
1482 {
1483         int old_cwnd = net->cwnd;
1484
1485         /* JRS - reset as if the state were being changed to timeout */
1486         htcp_reset(&net->htcp_ca);
1487         net->ssthresh = htcp_recalc_ssthresh(stcb, net);
1488         net->cwnd = net->mtu;
1489         net->partial_bytes_acked = 0;
1490         if (sctp_logging_level & SCTP_CWND_MONITOR_ENABLE) {
1491                 sctp_log_cwnd(stcb, net, net->cwnd - old_cwnd, SCTP_CWND_LOG_FROM_RTX);
1492         }
1493 }
1494
1495 void
1496 sctp_htcp_cwnd_update_after_fr_timer(struct sctp_inpcb *inp,
1497     struct sctp_tcb *stcb, struct sctp_nets *net)
1498 {
1499         int old_cwnd;
1500
1501         old_cwnd = net->cwnd;
1502
1503         sctp_chunk_output(inp, stcb, SCTP_OUTPUT_FROM_EARLY_FR_TMR, SCTP_SO_NOT_LOCKED);
1504         net->htcp_ca.last_cong = sctp_get_tick_count();
1505         /*
1506          * make a small adjustment to cwnd and force to CA.
1507          */
1508         if (net->cwnd > net->mtu)
1509                 /* drop down one MTU after sending */
1510                 net->cwnd -= net->mtu;
1511         if (net->cwnd < net->ssthresh)
1512                 /* still in SS move to CA */
1513                 net->ssthresh = net->cwnd - 1;
1514         if (sctp_logging_level & SCTP_CWND_MONITOR_ENABLE) {
1515                 sctp_log_cwnd(stcb, net, (old_cwnd - net->cwnd), SCTP_CWND_LOG_FROM_FR);
1516         }
1517 }
1518
1519 void
1520 sctp_htcp_cwnd_update_after_ecn_echo(struct sctp_tcb *stcb,
1521     struct sctp_nets *net)
1522 {
1523         int old_cwnd;
1524
1525         old_cwnd = net->cwnd;
1526
1527         /* JRS - reset hctp as if state changed */
1528         htcp_reset(&net->htcp_ca);
1529         SCTP_STAT_INCR(sctps_ecnereducedcwnd);
1530         net->ssthresh = htcp_recalc_ssthresh(stcb, net);
1531         if (net->ssthresh < net->mtu) {
1532                 net->ssthresh = net->mtu;
1533                 /* here back off the timer as well, to slow us down */
1534                 net->RTO <<= 1;
1535         }
1536         net->cwnd = net->ssthresh;
1537         if (sctp_logging_level & SCTP_CWND_MONITOR_ENABLE) {
1538                 sctp_log_cwnd(stcb, net, (net->cwnd - old_cwnd), SCTP_CWND_LOG_FROM_SAT);
1539         }
1540 }