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