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