View | Details | Raw Unified | Return to bug 191520 | Differences between
and this patch

Collapse All | Expand All

(-)b/head/sys/conf/files (+1 lines)
Lines 3515-3520 Link Here
3515
netinet/tcp_sack.c		optional inet | inet6
3515
netinet/tcp_sack.c		optional inet | inet6
3516
netinet/tcp_subr.c		optional inet | inet6
3516
netinet/tcp_subr.c		optional inet | inet6
3517
netinet/tcp_syncache.c		optional inet | inet6
3517
netinet/tcp_syncache.c		optional inet | inet6
3518
netinet/tcp_newcwv.c		optional inet | inet6
3518
netinet/tcp_timer.c		optional inet | inet6
3519
netinet/tcp_timer.c		optional inet | inet6
3519
netinet/tcp_timewait.c		optional inet | inet6
3520
netinet/tcp_timewait.c		optional inet | inet6
3520
netinet/tcp_usrreq.c		optional inet | inet6
3521
netinet/tcp_usrreq.c		optional inet | inet6
(-)b/head/sys/netinet/tcp_input.c (-2 / +35 lines)
Lines 105-110 Link Here
105
#include <netinet6/tcp6_var.h>
105
#include <netinet6/tcp6_var.h>
106
#include <netinet/tcpip.h>
106
#include <netinet/tcpip.h>
107
#include <netinet/tcp_syncache.h>
107
#include <netinet/tcp_syncache.h>
108
#include <netinet/tcp_newcwv.h>
108
#ifdef TCPDEBUG
109
#ifdef TCPDEBUG
109
#include <netinet/tcp_debug.h>
110
#include <netinet/tcp_debug.h>
110
#endif /* TCPDEBUG */
111
#endif /* TCPDEBUG */
Lines 174-179 Link Here
174
    &VNET_NAME(tcp_abc_l_var), 2,
175
    &VNET_NAME(tcp_abc_l_var), 2,
175
    "Cap the max cwnd increment during slow-start to this number of segments");
176
    "Cap the max cwnd increment during slow-start to this number of segments");
176
177
178
VNET_DEFINE(int, tcp_do_newcwv) = 0;
179
SYSCTL_INT(_net_inet_tcp, OID_AUTO, newcwv, CTLFLAG_RW,
180
    &VNET_NAME(tcp_do_newcwv), 0,
181
    "Enable draft-ietf-tcpm-newcwv-10 (New Congestion Window Validation)");
182
177
static SYSCTL_NODE(_net_inet_tcp, OID_AUTO, ecn, CTLFLAG_RW, 0, "TCP ECN");
183
static SYSCTL_NODE(_net_inet_tcp, OID_AUTO, ecn, CTLFLAG_RW, 0, "TCP ECN");
178
184
179
VNET_DEFINE(int, tcp_do_ecn) = 0;
185
VNET_DEFINE(int, tcp_do_ecn) = 0;
Lines 291-299 Link Here
291
	INP_WLOCK_ASSERT(tp->t_inpcb);
297
	INP_WLOCK_ASSERT(tp->t_inpcb);
292
298
293
	tp->ccv->bytes_this_ack = BYTES_THIS_ACK(tp, th);
299
	tp->ccv->bytes_this_ack = BYTES_THIS_ACK(tp, th);
294
	if (tp->snd_cwnd <= tp->snd_wnd)
300
	/* draft-ietf-tcpm-newcwv relaxes conditions for growing cwnd */
301
	if (tp->snd_cwnd <= tp->snd_wnd || 
302
		(V_tcp_do_newcwv && tp->newcwv.pipeack >= (tp->snd_cwnd >> 1)) ) {
295
		tp->ccv->flags |= CCF_CWND_LIMITED;
303
		tp->ccv->flags |= CCF_CWND_LIMITED;
296
	else
304
		tp->newcwv.cwnd_valid_ts = ticks;
305
	} else
297
		tp->ccv->flags &= ~CCF_CWND_LIMITED;
306
		tp->ccv->flags &= ~CCF_CWND_LIMITED;
298
307
299
	if (type == CC_ACK) {
308
	if (type == CC_ACK) {
Lines 315-320 Link Here
315
		tp->ccv->curack = th->th_ack;
324
		tp->ccv->curack = th->th_ack;
316
		CC_ALGO(tp)->ack_received(tp->ccv, type);
325
		CC_ALGO(tp)->ack_received(tp->ccv, type);
317
	}
326
	}
327
328
	/*
329
	 * update draft-ietf-newcwv-10 pipeack
330
	 */
331
	if(V_tcp_do_newcwv && !IN_FASTRECOVERY(tp->t_flags))
332
		tcp_newcwv_update_pipeack(tp);
318
}
333
}
319
334
320
static void inline
335
static void inline
Lines 384-389 Link Here
384
			tp->snd_cwnd = 4 * tp->t_maxseg;
399
			tp->snd_cwnd = 4 * tp->t_maxseg;
385
	}
400
	}
386
401
402
	/* 
403
	 * Initialise NewCWV state
404
	 */
405
	tp->newcwv.init_cwnd = tp->snd_cwnd;
406
	tcp_newcwv_reset(tp);
407
387
	if (CC_ALGO(tp)->conn_init != NULL)
408
	if (CC_ALGO(tp)->conn_init != NULL)
388
		CC_ALGO(tp)->conn_init(tp->ccv);
409
		CC_ALGO(tp)->conn_init(tp->ccv);
389
}
410
}
Lines 432-437 Link Here
432
		tp->t_badrxtwin = 0;
453
		tp->t_badrxtwin = 0;
433
		break;
454
		break;
434
	}
455
	}
456
	
457
	if (V_tcp_do_newcwv && 
458
			(type == CC_NDUPACK || type == CC_ECN) &&
459
				tp->newcwv.pipeack <= (tp->snd_cwnd >> 1) )
460
		tcp_newcwv_enter_recovery(tp);
435
461
436
	if (CC_ALGO(tp)->cong_signal != NULL) {
462
	if (CC_ALGO(tp)->cong_signal != NULL) {
437
		if (th != NULL)
463
		if (th != NULL)
Lines 453-458 Link Here
453
	}
479
	}
454
	/* XXXLAS: EXIT_RECOVERY ? */
480
	/* XXXLAS: EXIT_RECOVERY ? */
455
	tp->t_bytes_acked = 0;
481
	tp->t_bytes_acked = 0;
482
483
	if(V_tcp_do_newcwv) {
484
		if(tp->newcwv.loss_flight_size)
485
			tcp_newcwv_end_recovery(tp);
486
		tcp_newcwv_reset(tp);	
487
	}
488
	tp->newcwv.loss_flight_size = 0;
456
}
489
}
457
490
458
#ifdef TCP_SIGNATURE
491
#ifdef TCP_SIGNATURE
(-)b/head/sys/netinet/tcp_newcwv.c (+175 lines)
Added Link Here
1
/*
2
 * Copyright (c) 2014 Tom Jones <jones@sdf.org>
3
 * All rights reserved.
4
 *
5
 * Redistribution and use in source and binary forms, with or without
6
 * modification, are permitted provided that the following conditions
7
 * are met:
8
 * 1. Redistributions of source code must retain the above copyright
9
 *    notice, this list of conditions and the following disclaimer.
10
 * 2. Redistributions in binary form must reproduce the above copyright
11
 *    notice, this list of conditions and the following disclaimer in the
12
 *    documentation and/or other materials provided with the distribution.
13
 *
14
 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
15
 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
16
 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
17
 * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
18
 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
19
 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
20
 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
21
 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
22
 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
23
 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
24
 * SUCH DAMAGE.
25
 *
26
 */
27
28
#include <sys/cdefs.h>
29
30
#include <sys/param.h>
31
#include <sys/kernel.h>
32
#include <sys/libkern.h>
33
#include <sys/socket.h>
34
#include <sys/socketvar.h>
35
36
#include <netinet/tcp.h>
37
#include <netinet/tcp_var.h>
38
#include <netinet/tcp_newcwv.h>
39
40
/*
41
 * An implementation of NewCWV (draft-ietf-tcpm-newcwv-10) for FreeBSD.
42
 * Based on the Linux implementation by Raffaello Secchi and the an initial
43
 * implementation of draft-ietf-tcpm-newcwv-00 by Aris Angelogiannopoulos.
44
 */
45
46
#define nextbin(x) (((x)+1) & 0x03)
47
#define prevbin(x) (((x)-1) & 0x03)
48
49
#define NCWV_UNDEF 0xFFFFFFFF
50
#define NCWV_FIVEMINS (300*hz)
51
52
void add_element(struct tcpcb *,u_int32_t);
53
u_int32_t remove_expired_elements(struct tcpcb *);
54
55
void
56
tcp_newcwv_update_pipeack(struct tcpcb *tp)
57
{
58
	u_int32_t tmp_pipeack;
59
	tp->newcwv.psp = MAX(3 * tp->t_srtt,hz); 
60
61
	if (tp->snd_una >= tp->newcwv.prev_snd_nxt) {
62
		/* get the pipeack sample */
63
		tmp_pipeack = tp->snd_una - tp->newcwv.prev_snd_una;
64
65
		tp->newcwv.prev_snd_una = tp->snd_una;
66
		tp->newcwv.prev_snd_nxt = tp->snd_nxt;
67
68
		/* create a new element at the end of current pmp */
69
		if(ticks > tp->newcwv.time_stamp[tp->newcwv.head] + 
70
			(tp->newcwv.psp >> 2)) 
71
			add_element(tp,tmp_pipeack);
72
		else 
73
			tp->newcwv.psample[tp->newcwv.head] = tmp_pipeack;
74
	}
75
76
	tp->newcwv.pipeack = remove_expired_elements(tp);
77
78
	/* check if cwnd is validated */
79
	if (tp->newcwv.pipeack == NCWV_UNDEF || 
80
		((tp->newcwv.pipeack << 1) >= (tp->snd_cwnd * tp->t_maxseg))) {
81
		tp->newcwv.cwnd_valid_ts = ticks;
82
	} 
83
}
84
85
void 
86
add_element(struct tcpcb *tp,u_int32_t value)
87
{
88
	tp->newcwv.head = nextbin(tp->newcwv.head);
89
	tp->newcwv.psample[tp->newcwv.head] = value;
90
	tp->newcwv.time_stamp[tp->newcwv.head] = ticks;
91
}
92
93
u_int32_t
94
remove_expired_elements(struct tcpcb *tp)
95
{
96
	uint8_t head = tp->newcwv.head;
97
	u_int32_t tmp = tp->newcwv.psample[head];
98
99
	while(tp->newcwv.psample[head] != NCWV_UNDEF) {
100
		/* remove the element if expired */
101
		if (tp->newcwv.time_stamp[head] < ticks - tp->newcwv.psp) {
102
			tp->newcwv.psample[head] = NCWV_UNDEF;
103
			return tmp;
104
		}
105
106
		/* search for the max pipeack */
107
		if(tp->newcwv.psample[head] > tmp)
108
			tmp = tp->newcwv.psample[head];
109
110
		head = prevbin(head);
111
		if(head == tp->newcwv.head)
112
			return tmp;
113
	}	
114
115
	return tmp;
116
}
117
118
/* Initialise NewCWV state */
119
void
120
tcp_newcwv_reset(struct tcpcb *tp)
121
{
122
	tp->newcwv.prev_snd_una = tp->snd_una;
123
	tp->newcwv.prev_snd_nxt = tp->snd_nxt;
124
	tp->newcwv.cwnd_valid_ts = ticks;
125
	tp->newcwv.loss_flight_size = 0;
126
127
	tp->newcwv.head = 0;
128
	tp->newcwv.psample[0] = NCWV_UNDEF;
129
	tp->newcwv.pipeack = NCWV_UNDEF;
130
}
131
132
/* NewCWV actions at loss detection */
133
void
134
tcp_newcwv_enter_recovery(struct tcpcb *tp)
135
{
136
	u_int32_t pipe;
137
138
	if(tp->newcwv.pipeack == NCWV_UNDEF)
139
		return;
140
141
	tp->newcwv.prior_retrans = tp->t_sndrexmitpack;
142
143
	/* Calculate the flight size */
144
	u_int32_t awnd = (tp->snd_nxt - tp->snd_fack) + tp->sackhint.sack_bytes_rexmit;
145
	tp->newcwv.loss_flight_size = awnd;
146
147
	pipe = MAX(tp->newcwv.pipeack,tp->newcwv.loss_flight_size);
148
	tp->snd_cwnd = MAX(pipe >> 1,1);
149
}
150
151
/* NewCWV actions at the end of recovery */
152
void
153
tcp_newcwv_end_recovery(struct tcpcb *tp)
154
{
155
	u_int32_t retrans,pipe;
156
157
	retrans = (tp->t_sndrexmitpack - tp->newcwv.prior_retrans) * tp->t_maxseg;
158
	pipe = MAX(tp->newcwv.pipeack,tp->newcwv.loss_flight_size) - retrans;
159
160
	/* Ensure that snd_ssthresh is non 0 */
161
	tp->snd_ssthresh = MAX(pipe >> 1,1); 
162
	tp->snd_cwnd = tp->snd_ssthresh;
163
}
164
165
void
166
tcp_newcwv_datalim_closedown(struct tcpcb *tp)
167
{
168
	while ((ticks - tp->newcwv.cwnd_valid_ts) > NCWV_FIVEMINS && 
169
	  tp->snd_cwnd > tp->newcwv.init_cwnd) {
170
171
		tp->newcwv.cwnd_valid_ts += NCWV_FIVEMINS;
172
		tp->snd_ssthresh = MAX( (3 * tp->snd_cwnd ) >> 2,tp->snd_ssthresh);
173
		tp->snd_cwnd = MAX(tp->snd_cwnd >> 1, tp->newcwv.init_cwnd);
174
	}
175
}
(-)b/head/sys/netinet/tcp_newcwv.h (+39 lines)
Added Link Here
1
/*
2
 * Copyright (c) 2014 Tom Jones <jones@sdf.org>
3
 * All rights reserved.
4
 *
5
 * Redistribution and use in source and binary forms, with or without
6
 * modification, are permitted provided that the following conditions
7
 * are met:
8
 * 1. Redistributions of source code must retain the above copyright
9
 *    notice, this list of conditions and the following disclaimer.
10
 * 2. Redistributions in binary form must reproduce the above copyright
11
 *    notice, this list of conditions and the following disclaimer in the
12
 *    documentation and/or other materials provided with the distribution.
13
 *
14
 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
15
 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
16
 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
17
 * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
18
 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
19
 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
20
 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
21
 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
22
 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
23
 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
24
 * SUCH DAMAGE.
25
 *
26
 */
27
28
#ifndef _NETINET_TCP_NEWCWV_H_
29
#define _NETINET_TCP_NEWCWV_H_
30
31
#include <netinet/tcp_var.h>
32
33
void tcp_newcwv_update_pipeack(struct tcpcb *);
34
void tcp_newcwv_reset(struct tcpcb *);
35
void tcp_newcwv_enter_recovery(struct tcpcb *);
36
void tcp_newcwv_end_recovery(struct tcpcb *);
37
void tcp_newcwv_datalim_closedown(struct tcpcb *);
38
39
#endif /* _NETINET_TCP_NEWCWV_H_ */
(-)b/head/sys/netinet/tcp_output.c (+5 lines)
Lines 74-79 Link Here
74
#include <netinet/tcp_timer.h>
74
#include <netinet/tcp_timer.h>
75
#include <netinet/tcp_var.h>
75
#include <netinet/tcp_var.h>
76
#include <netinet/tcpip.h>
76
#include <netinet/tcpip.h>
77
#include <netinet/tcp_newcwv.h>
77
#ifdef TCPDEBUG
78
#ifdef TCPDEBUG
78
#include <netinet/tcp_debug.h>
79
#include <netinet/tcp_debug.h>
79
#endif
80
#endif
Lines 702-707 Link Here
702
#endif
703
#endif
703
		hdrlen = sizeof (struct tcpiphdr);
704
		hdrlen = sizeof (struct tcpiphdr);
704
705
706
	/* Trigger the newcwv timer */
707
	if(V_tcp_do_newcwv)
708
		tcp_newcwv_datalim_closedown(tp);
709
705
	/*
710
	/*
706
	 * Compute options for segment.
711
	 * Compute options for segment.
707
	 * We only have to care about SYN and established connection
712
	 * We only have to care about SYN and established connection
(-)b/head/sys/netinet/tcp_var.h (+18 lines)
Lines 172-177 Link Here
172
	int	t_sndzerowin;		/* zero-window updates sent */
172
	int	t_sndzerowin;		/* zero-window updates sent */
173
	u_int	t_badrxtwin;		/* window for retransmit recovery */
173
	u_int	t_badrxtwin;		/* window for retransmit recovery */
174
	u_char	snd_limited;		/* segments limited transmitted */
174
	u_char	snd_limited;		/* segments limited transmitted */
175
/* NewCWV releated state */
176
	struct {
177
		u_int32_t pipeack;
178
		u_int32_t psp;			/* pipeack sampling period */
179
180
		u_int32_t head;
181
		u_int32_t psample[4];	/* pipe ack samples */
182
		u_int32_t time_stamp[4];	/* time stamp samples */
183
		u_int32_t prev_snd_una;		/* previous snd_una in this sampe */
184
		u_int32_t prev_snd_nxt;		/* previous snd_nxt in this sampe */
185
186
		u_int32_t loss_flight_size;	/* flightsize at loss detection */
187
		u_int32_t prior_retrans;	/* Retransmission before going into FR */
188
		u_int32_t cwnd_valid_ts;	/*last time cwnd was found valid */
189
		u_int32_t init_cwnd;	/* The inital cwnd */
190
	} newcwv;
175
/* SACK related state */
191
/* SACK related state */
176
	int	snd_numholes;		/* number of holes seen by sender */
192
	int	snd_numholes;		/* number of holes seen by sender */
177
	TAILQ_HEAD(sackhole_head, sackhole) snd_holes;
193
	TAILQ_HEAD(sackhole_head, sackhole) snd_holes;
Lines 619-624 Link Here
619
VNET_DECLARE(int, path_mtu_discovery);
635
VNET_DECLARE(int, path_mtu_discovery);
620
VNET_DECLARE(int, tcp_do_rfc3465);
636
VNET_DECLARE(int, tcp_do_rfc3465);
621
VNET_DECLARE(int, tcp_abc_l_var);
637
VNET_DECLARE(int, tcp_abc_l_var);
638
VNET_DECLARE(int, tcp_do_newcwv);
622
#define	V_tcb			VNET(tcb)
639
#define	V_tcb			VNET(tcb)
623
#define	V_tcbinfo		VNET(tcbinfo)
640
#define	V_tcbinfo		VNET(tcbinfo)
624
#define	V_tcp_mssdflt		VNET(tcp_mssdflt)
641
#define	V_tcp_mssdflt		VNET(tcp_mssdflt)
Lines 631-636 Link Here
631
#define	V_path_mtu_discovery	VNET(path_mtu_discovery)
648
#define	V_path_mtu_discovery	VNET(path_mtu_discovery)
632
#define	V_tcp_do_rfc3465	VNET(tcp_do_rfc3465)
649
#define	V_tcp_do_rfc3465	VNET(tcp_do_rfc3465)
633
#define	V_tcp_abc_l_var		VNET(tcp_abc_l_var)
650
#define	V_tcp_abc_l_var		VNET(tcp_abc_l_var)
651
#define	V_tcp_do_newcwv		VNET(tcp_do_newcwv)
634
652
635
VNET_DECLARE(int, tcp_do_sack);			/* SACK enabled/disabled */
653
VNET_DECLARE(int, tcp_do_sack);			/* SACK enabled/disabled */
636
VNET_DECLARE(int, tcp_sc_rst_sock_fail);	/* RST on sock alloc failure */
654
VNET_DECLARE(int, tcp_sc_rst_sock_fail);	/* RST on sock alloc failure */

Return to bug 191520