tcp_congctl.c revision 1.4
1/* $NetBSD: tcp_congctl.c,v 1.4 2006/10/10 11:12:39 rpaulo Exp $ */ 2 3/*- 4 * Copyright (c) 1997, 1998, 1999, 2001, 2005, 2006 The NetBSD Foundation, Inc. 5 * All rights reserved. 6 * 7 * This code is derived from software contributed to The NetBSD Foundation 8 * by Jason R. Thorpe and Kevin M. Lahey of the Numerical Aerospace Simulation 9 * Facility, NASA Ames Research Center. 10 * This code is derived from software contributed to The NetBSD Foundation 11 * by Charles M. Hannum. 12 * This code is derived from software contributed to The NetBSD Foundation 13 * by Rui Paulo. 14 * 15 * Redistribution and use in source and binary forms, with or without 16 * modification, are permitted provided that the following conditions 17 * are met: 18 * 1. Redistributions of source code must retain the above copyright 19 * notice, this list of conditions and the following disclaimer. 20 * 2. Redistributions in binary form must reproduce the above copyright 21 * notice, this list of conditions and the following disclaimer in the 22 * documentation and/or other materials provided with the distribution. 23 * 3. All advertising materials mentioning features or use of this software 24 * must display the following acknowledgement: 25 * This product includes software developed by the NetBSD 26 * Foundation, Inc. and its contributors. 27 * 4. Neither the name of The NetBSD Foundation nor the names of its 28 * contributors may be used to endorse or promote products derived 29 * from this software without specific prior written permission. 30 * 31 * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS 32 * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED 33 * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR 34 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS 35 * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 36 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 37 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 38 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 39 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 40 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 41 * POSSIBILITY OF SUCH DAMAGE. 42 */ 43 44/* 45 * Copyright (C) 1995, 1996, 1997, and 1998 WIDE Project. 46 * All rights reserved. 47 * 48 * Redistribution and use in source and binary forms, with or without 49 * modification, are permitted provided that the following conditions 50 * are met: 51 * 1. Redistributions of source code must retain the above copyright 52 * notice, this list of conditions and the following disclaimer. 53 * 2. Redistributions in binary form must reproduce the above copyright 54 * notice, this list of conditions and the following disclaimer in the 55 * documentation and/or other materials provided with the distribution. 56 * 3. Neither the name of the project nor the names of its contributors 57 * may be used to endorse or promote products derived from this software 58 * without specific prior written permission. 59 * 60 * THIS SOFTWARE IS PROVIDED BY THE PROJECT AND CONTRIBUTORS ``AS IS'' AND 61 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 62 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 63 * ARE DISCLAIMED. IN NO EVENT SHALL THE PROJECT OR CONTRIBUTORS BE LIABLE 64 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 65 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 66 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 67 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 68 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 69 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 70 * SUCH DAMAGE. 71 */ 72 73/* 74 * @(#)COPYRIGHT 1.1 (NRL) 17 January 1995 75 * 76 * NRL grants permission for redistribution and use in source and binary 77 * forms, with or without modification, of the software and documentation 78 * created at NRL provided that the following conditions are met: 79 * 80 * 1. Redistributions of source code must retain the above copyright 81 * notice, this list of conditions and the following disclaimer. 82 * 2. Redistributions in binary form must reproduce the above copyright 83 * notice, this list of conditions and the following disclaimer in the 84 * documentation and/or other materials provided with the distribution. 85 * 3. All advertising materials mentioning features or use of this software 86 * must display the following acknowledgements: 87 * This product includes software developed by the University of 88 * California, Berkeley and its contributors. 89 * This product includes software developed at the Information 90 * Technology Division, US Naval Research Laboratory. 91 * 4. Neither the name of the NRL nor the names of its contributors 92 * may be used to endorse or promote products derived from this software 93 * without specific prior written permission. 94 * 95 * THE SOFTWARE PROVIDED BY NRL IS PROVIDED BY NRL AND CONTRIBUTORS ``AS 96 * IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED 97 * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A 98 * PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL NRL OR 99 * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, 100 * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, 101 * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR 102 * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF 103 * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING 104 * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS 105 * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 106 * 107 * The views and conclusions contained in the software and documentation 108 * are those of the authors and should not be interpreted as representing 109 * official policies, either expressed or implied, of the US Naval 110 * Research Laboratory (NRL). 111 */ 112 113/* 114 * Copyright (c) 1982, 1986, 1988, 1990, 1993, 1994, 1995 115 * The Regents of the University of California. All rights reserved. 116 * 117 * Redistribution and use in source and binary forms, with or without 118 * modification, are permitted provided that the following conditions 119 * are met: 120 * 1. Redistributions of source code must retain the above copyright 121 * notice, this list of conditions and the following disclaimer. 122 * 2. Redistributions in binary form must reproduce the above copyright 123 * notice, this list of conditions and the following disclaimer in the 124 * documentation and/or other materials provided with the distribution. 125 * 3. Neither the name of the University nor the names of its contributors 126 * may be used to endorse or promote products derived from this software 127 * without specific prior written permission. 128 * 129 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND 130 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 131 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 132 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE 133 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 134 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 135 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 136 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 137 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 138 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 139 * SUCH DAMAGE. 140 * 141 * @(#)tcp_input.c 8.12 (Berkeley) 5/24/95 142 */ 143 144#include <sys/cdefs.h> 145__KERNEL_RCSID(0, "$NetBSD: tcp_congctl.c,v 1.4 2006/10/10 11:12:39 rpaulo Exp $"); 146 147#include "opt_inet.h" 148#include "opt_tcp_debug.h" 149#include "opt_tcp_congctl.h" 150 151#include <sys/param.h> 152#include <sys/systm.h> 153#include <sys/malloc.h> 154#include <sys/mbuf.h> 155#include <sys/protosw.h> 156#include <sys/socket.h> 157#include <sys/socketvar.h> 158#include <sys/errno.h> 159#include <sys/syslog.h> 160#include <sys/pool.h> 161#include <sys/domain.h> 162#include <sys/kernel.h> 163#include <sys/lock.h> 164 165#include <net/if.h> 166#include <net/route.h> 167 168#include <netinet/in.h> 169#include <netinet/in_systm.h> 170#include <netinet/ip.h> 171#include <netinet/in_pcb.h> 172#include <netinet/in_var.h> 173#include <netinet/ip_var.h> 174 175#ifdef INET6 176#ifndef INET 177#include <netinet/in.h> 178#endif 179#include <netinet/ip6.h> 180#include <netinet6/ip6_var.h> 181#include <netinet6/in6_pcb.h> 182#include <netinet6/ip6_var.h> 183#include <netinet6/in6_var.h> 184#include <netinet/icmp6.h> 185#include <netinet6/nd6.h> 186#endif 187 188#include <netinet/tcp.h> 189#include <netinet/tcp_fsm.h> 190#include <netinet/tcp_seq.h> 191#include <netinet/tcp_timer.h> 192#include <netinet/tcp_var.h> 193#include <netinet/tcpip.h> 194#include <netinet/tcp_congctl.h> 195#ifdef TCP_DEBUG 196#include <netinet/tcp_debug.h> 197#endif 198 199/* 200 * TODO: 201 * consider separating the actual implementations in another file. 202 */ 203 204static int tcp_reno_fast_retransmit(struct tcpcb *, struct tcphdr *); 205static void tcp_reno_slow_retransmit(struct tcpcb *); 206static void tcp_reno_fast_retransmit_newack(struct tcpcb *, struct tcphdr *); 207static void tcp_reno_newack(struct tcpcb *, struct tcphdr *); 208 209static int tcp_newreno_fast_retransmit(struct tcpcb *, struct tcphdr *); 210static void tcp_newreno_fast_retransmit_newack(struct tcpcb *, 211 struct tcphdr *); 212static void tcp_newreno_newack(struct tcpcb *, struct tcphdr *); 213 214 215static void tcp_congctl_fillnames(void); 216 217extern int tcprexmtthresh; 218 219MALLOC_DEFINE(M_TCPCONGCTL, "tcpcongctl", "TCP congestion control structures"); 220 221/* 222 * Used to list the available congestion control algorithms. 223 */ 224struct tcp_congctlent { 225 TAILQ_ENTRY(tcp_congctlent) congctl_ent; 226 char congctl_name[TCPCC_MAXLEN]; 227 struct tcp_congctl *congctl_ctl; 228}; 229TAILQ_HEAD(, tcp_congctlent) tcp_congctlhd; 230 231struct simplelock tcp_congctl_slock; 232 233void 234tcp_congctl_init(void) 235{ 236 int r; 237 238 TAILQ_INIT(&tcp_congctlhd); 239 simple_lock_init(&tcp_congctl_slock); 240 241 /* Base algorithms. */ 242 r = tcp_congctl_register("reno", &tcp_reno_ctl); 243 KASSERT(r == 0); 244 r = tcp_congctl_register("newreno", &tcp_newreno_ctl); 245 KASSERT(r == 0); 246 247 /* NewReno is the default. */ 248#ifndef TCP_CONGCTL_DEFAULT 249#define TCP_CONGCTL_DEFAULT "newreno" 250#endif 251 252 r = tcp_congctl_select(NULL, TCP_CONGCTL_DEFAULT); 253 KASSERT(r == 0); 254} 255 256/* 257 * Register a congestion algorithm and select it if we have none. 258 */ 259int 260tcp_congctl_register(const char *name, struct tcp_congctl *tcc) 261{ 262 struct tcp_congctlent *ntcc, *tccp; 263 264 TAILQ_FOREACH(tccp, &tcp_congctlhd, congctl_ent) 265 if (!strcmp(name, tccp->congctl_name)) { 266 /* name already registered */ 267 return EEXIST; 268 } 269 270 ntcc = malloc(sizeof(*ntcc), M_TCPCONGCTL, M_WAITOK); 271 272 strlcpy(ntcc->congctl_name, name, sizeof(ntcc->congctl_name) - 1); 273 ntcc->congctl_ctl = tcc; 274 275 TAILQ_INSERT_TAIL(&tcp_congctlhd, ntcc, congctl_ent); 276 tcp_congctl_fillnames(); 277 278 if (TAILQ_FIRST(&tcp_congctlhd) == ntcc) 279 tcp_congctl_select(NULL, name); 280 281 return 0; 282} 283 284int 285tcp_congctl_unregister(const char *name) 286{ 287 struct tcp_congctlent *tccp, *rtccp; 288 unsigned int size; 289 290 rtccp = NULL; 291 size = 0; 292 TAILQ_FOREACH(tccp, &tcp_congctlhd, congctl_ent) { 293 if (!strcmp(name, tccp->congctl_name)) 294 rtccp = tccp; 295 size++; 296 } 297 298 if (!rtccp) 299 return ENOENT; 300 301 if (size <= 1 || tcp_congctl_global == rtccp->congctl_ctl || 302 rtccp->congctl_ctl->refcnt) 303 return EBUSY; 304 305 TAILQ_REMOVE(&tcp_congctlhd, rtccp, congctl_ent); 306 free(rtccp, M_TCPCONGCTL); 307 tcp_congctl_fillnames(); 308 309 return 0; 310} 311 312/* 313 * Select a congestion algorithm by name. 314 */ 315int 316tcp_congctl_select(struct tcpcb *tp, const char *name) 317{ 318 struct tcp_congctlent *tccp; 319 320 KASSERT(name); 321 322 TAILQ_FOREACH(tccp, &tcp_congctlhd, congctl_ent) 323 if (!strcmp(name, tccp->congctl_name)) { 324 if (tp) { 325 simple_lock(&tcp_congctl_slock); 326 tp->t_congctl->refcnt--; 327 tp->t_congctl = tccp->congctl_ctl; 328 tp->t_congctl->refcnt++; 329 simple_unlock(&tcp_congctl_slock); 330 } else { 331 tcp_congctl_global = tccp->congctl_ctl; 332 strlcpy(tcp_congctl_global_name, 333 tccp->congctl_name, 334 sizeof(tcp_congctl_global_name) - 1); 335 } 336 return 0; 337 } 338 339 return EINVAL; 340} 341 342/* 343 * Returns the name of a congestion algorithm. 344 */ 345const char * 346tcp_congctl_bystruct(const struct tcp_congctl *tcc) 347{ 348 struct tcp_congctlent *tccp; 349 350 KASSERT(tcc); 351 352 TAILQ_FOREACH(tccp, &tcp_congctlhd, congctl_ent) 353 if (tccp->congctl_ctl == tcc) 354 return tccp->congctl_name; 355 356 return NULL; 357} 358 359static void 360tcp_congctl_fillnames(void) 361{ 362 struct tcp_congctlent *tccp; 363 const char *delim = " "; 364 365 tcp_congctl_avail[0] = '\0'; 366 TAILQ_FOREACH(tccp, &tcp_congctlhd, congctl_ent) { 367 strlcat(tcp_congctl_avail, tccp->congctl_name, 368 sizeof(tcp_congctl_avail) - 1); 369 if (TAILQ_NEXT(tccp, congctl_ent)) 370 strlcat(tcp_congctl_avail, delim, 371 sizeof(tcp_congctl_avail) - 1); 372 } 373 374} 375 376/* ------------------------------------------------------------------------ */ 377 378inline void 379tcp_reno_congestion_exp(struct tcpcb *tp) 380{ 381 u_int win; 382 383 /* 384 * Halve the congestion window and reduce the 385 * slow start threshold. 386 */ 387 win = min(tp->snd_wnd, tp->snd_cwnd) / 2 / tp->t_segsz; 388 if (win < 2) 389 win = 2; 390 391 tp->snd_ssthresh = win * tp->t_segsz; 392 tp->snd_recover = tp->snd_max; 393 tp->snd_cwnd = tp->snd_ssthresh; 394 395 if (TCP_ECN_ALLOWED(tp)) 396 tp->t_flags |= TF_ECN_SND_CWR; 397} 398 399 400/* 401 * TCP/Reno congestion control. 402 */ 403static int 404tcp_reno_fast_retransmit(struct tcpcb *tp, struct tcphdr *th) 405{ 406 tcp_seq onxt; 407 408 onxt = tp->snd_nxt; 409 tcp_reno_congestion_exp(tp); 410 tp->t_partialacks = 0; 411 TCP_TIMER_DISARM(tp, TCPT_REXMT); 412 tp->t_rtttime = 0; 413 if (TCP_SACK_ENABLED(tp)) { 414 tp->t_dupacks = tcprexmtthresh; 415 tp->sack_newdata = tp->snd_nxt; 416 tp->snd_cwnd = tp->t_segsz; 417 (void) tcp_output(tp); 418 return 0; 419 } 420 tp->snd_nxt = th->th_ack; 421 tp->snd_cwnd = tp->t_segsz; 422 (void) tcp_output(tp); 423 tp->snd_cwnd = tp->snd_ssthresh + tp->t_segsz * tp->t_dupacks; 424 if (SEQ_GT(onxt, tp->snd_nxt)) 425 tp->snd_nxt = onxt; 426 427 return 0; 428} 429 430static void 431tcp_reno_slow_retransmit(struct tcpcb *tp) 432{ 433 u_int win; 434 435 /* 436 * Close the congestion window down to one segment 437 * (we'll open it by one segment for each ack we get). 438 * Since we probably have a window's worth of unacked 439 * data accumulated, this "slow start" keeps us from 440 * dumping all that data as back-to-back packets (which 441 * might overwhelm an intermediate gateway). 442 * 443 * There are two phases to the opening: Initially we 444 * open by one mss on each ack. This makes the window 445 * size increase exponentially with time. If the 446 * window is larger than the path can handle, this 447 * exponential growth results in dropped packet(s) 448 * almost immediately. To get more time between 449 * drops but still "push" the network to take advantage 450 * of improving conditions, we switch from exponential 451 * to linear window opening at some threshhold size. 452 * For a threshhold, we use half the current window 453 * size, truncated to a multiple of the mss. 454 * 455 * (the minimum cwnd that will give us exponential 456 * growth is 2 mss. We don't allow the threshhold 457 * to go below this.) 458 */ 459 460 win = min(tp->snd_wnd, tp->snd_cwnd) / 2 / tp->t_segsz; 461 if (win < 2) 462 win = 2; 463 /* Loss Window MUST be one segment. */ 464 tp->snd_cwnd = tp->t_segsz; 465 tp->snd_ssthresh = win * tp->t_segsz; 466 tp->t_partialacks = -1; 467 tp->t_dupacks = 0; 468} 469 470static void 471tcp_reno_fast_retransmit_newack(struct tcpcb *tp, struct tcphdr *th) 472{ 473 if (tp->t_partialacks < 0) { 474 /* 475 * We were not in fast recovery. Reset the duplicate ack 476 * counter. 477 */ 478 tp->t_dupacks = 0; 479 } else { 480 /* 481 * Clamp the congestion window to the crossover point and 482 * exit fast recovery. 483 */ 484 if (tp->snd_cwnd > tp->snd_ssthresh) 485 tp->snd_cwnd = tp->snd_ssthresh; 486 tp->t_partialacks = -1; 487 tp->t_dupacks = 0; 488 } 489} 490 491static void 492tcp_reno_newack(struct tcpcb *tp, struct tcphdr *th) 493{ 494 /* 495 * When new data is acked, open the congestion window. 496 * If the window gives us less than ssthresh packets 497 * in flight, open exponentially (segsz per packet). 498 * Otherwise open linearly: segsz per window 499 * (segsz^2 / cwnd per packet). 500 */ 501 502 u_int cw = tp->snd_cwnd; 503 u_int incr = tp->t_segsz; 504 505 if (cw >= tp->snd_ssthresh) 506 incr = incr * incr / cw; 507 508 tp->snd_cwnd = min(cw + incr, TCP_MAXWIN << tp->snd_scale); 509} 510 511struct tcp_congctl tcp_reno_ctl = { 512 .fast_retransmit = tcp_reno_fast_retransmit, 513 .slow_retransmit = tcp_reno_slow_retransmit, 514 .fast_retransmit_newack = tcp_reno_fast_retransmit_newack, 515 .newack = tcp_reno_newack, 516}; 517 518/* 519 * TCP/NewReno Congestion control. 520 */ 521static int 522tcp_newreno_fast_retransmit(struct tcpcb *tp, struct tcphdr *th) 523{ 524 if (SEQ_LT(th->th_ack, tp->snd_high)) { 525 /* 526 * False fast retransmit after timeout. 527 * Do not enter fast recovery 528 */ 529 tp->t_dupacks = 0; 530 return 1; 531 } else { 532 /* 533 * Fast retransmit is same as reno. 534 */ 535 return tcp_reno_fast_retransmit(tp, th); 536 } 537 538 return 0; 539} 540 541/* 542 * Implement the NewReno response to a new ack, checking for partial acks in 543 * fast recovery. 544 */ 545static void 546tcp_newreno_fast_retransmit_newack(struct tcpcb *tp, struct tcphdr *th) 547{ 548 if (tp->t_partialacks < 0) { 549 /* 550 * We were not in fast recovery. Reset the duplicate ack 551 * counter. 552 */ 553 tp->t_dupacks = 0; 554 } else if (SEQ_LT(th->th_ack, tp->snd_recover)) { 555 /* 556 * This is a partial ack. Retransmit the first unacknowledged 557 * segment and deflate the congestion window by the amount of 558 * acknowledged data. Do not exit fast recovery. 559 */ 560 tcp_seq onxt = tp->snd_nxt; 561 u_long ocwnd = tp->snd_cwnd; 562 563 /* 564 * snd_una has not yet been updated and the socket's send 565 * buffer has not yet drained off the ACK'd data, so we 566 * have to leave snd_una as it was to get the correct data 567 * offset in tcp_output(). 568 */ 569 if (++tp->t_partialacks == 1) 570 TCP_TIMER_DISARM(tp, TCPT_REXMT); 571 tp->t_rtttime = 0; 572 tp->snd_nxt = th->th_ack; 573 /* 574 * Set snd_cwnd to one segment beyond ACK'd offset. snd_una 575 * is not yet updated when we're called. 576 */ 577 tp->snd_cwnd = tp->t_segsz + (th->th_ack - tp->snd_una); 578 (void) tcp_output(tp); 579 tp->snd_cwnd = ocwnd; 580 if (SEQ_GT(onxt, tp->snd_nxt)) 581 tp->snd_nxt = onxt; 582 /* 583 * Partial window deflation. Relies on fact that tp->snd_una 584 * not updated yet. 585 */ 586 tp->snd_cwnd -= (th->th_ack - tp->snd_una - tp->t_segsz); 587 } else { 588 /* 589 * Complete ack. Inflate the congestion window to ssthresh 590 * and exit fast recovery. 591 * 592 * Window inflation should have left us with approx. 593 * snd_ssthresh outstanding data. But in case we 594 * would be inclined to send a burst, better to do 595 * it via the slow start mechanism. 596 */ 597 if (SEQ_SUB(tp->snd_max, th->th_ack) < tp->snd_ssthresh) 598 tp->snd_cwnd = SEQ_SUB(tp->snd_max, th->th_ack) 599 + tp->t_segsz; 600 else 601 tp->snd_cwnd = tp->snd_ssthresh; 602 tp->t_partialacks = -1; 603 tp->t_dupacks = 0; 604 } 605} 606 607static void 608tcp_newreno_newack(struct tcpcb *tp, struct tcphdr *th) 609{ 610 /* 611 * If we are still in fast recovery (meaning we are using 612 * NewReno and we have only received partial acks), do not 613 * inflate the window yet. 614 */ 615 if (tp->t_partialacks < 0) 616 tcp_reno_newack(tp, th); 617} 618 619 620struct tcp_congctl tcp_newreno_ctl = { 621 .fast_retransmit = tcp_newreno_fast_retransmit, 622 .slow_retransmit = tcp_reno_slow_retransmit, 623 .fast_retransmit_newack = tcp_newreno_fast_retransmit_newack, 624 .newack = tcp_newreno_newack, 625}; 626 627 628