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

Collapse All | Expand All

(-)sys/conf/files (+1 lines)
Lines 3380-3385 netinet/tcp_reass.c optional inet | inet6 Link Here
3380
netinet/tcp_sack.c		optional inet | inet6
3380
netinet/tcp_sack.c		optional inet | inet6
3381
netinet/tcp_subr.c		optional inet | inet6
3381
netinet/tcp_subr.c		optional inet | inet6
3382
netinet/tcp_syncache.c		optional inet | inet6
3382
netinet/tcp_syncache.c		optional inet | inet6
3383
netinet/tcp_newcwv.c		optional inet | inet6
3383
netinet/tcp_timer.c		optional inet | inet6
3384
netinet/tcp_timer.c		optional inet | inet6
3384
netinet/tcp_timewait.c		optional inet | inet6
3385
netinet/tcp_timewait.c		optional inet | inet6
3385
netinet/tcp_usrreq.c		optional inet | inet6
3386
netinet/tcp_usrreq.c		optional inet | inet6
(-)sys/netinet/tcp_input.c (+30 lines)
Lines 105-110 __FBSDID("$FreeBSD$"); 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 SYSCTL_VNET_INT(_net_inet_tcp, OID_AUTO, abc_l_var 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_VNET_INT(_net_inet_tcp, OID_AUTO, newcwv, CTLFLAG_RW,
180
    &VNET_NAME(tcp_do_newcwv), 0,
181
    "Enable draft-ietf-tcpm-newcwv-06 (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 309-314 cc_ack_received(struct tcpcb *tp, struct tcphdr *t Link Here
309
		tp->ccv->curack = th->th_ack;
315
		tp->ccv->curack = th->th_ack;
310
		CC_ALGO(tp)->ack_received(tp->ccv, type);
316
		CC_ALGO(tp)->ack_received(tp->ccv, type);
311
	}
317
	}
318
319
	/*
320
	 * update draft-ietf-newcwv-06 pipeack
321
	 */
322
	if(V_tcp_do_newcwv && !IN_FASTRECOVERY(tp->t_flags))
323
		tcp_newcwv_update_pipeack(tp);
312
}
324
}
313
325
314
static void inline
326
static void inline
Lines 378-383 cc_conn_init(struct tcpcb *tp) Link Here
378
			tp->snd_cwnd = 4 * tp->t_maxseg;
390
			tp->snd_cwnd = 4 * tp->t_maxseg;
379
	}
391
	}
380
392
393
	/* 
394
	 * Initialise NewCWV state
395
	 */
396
	tp->init_cwnd = tp->snd_cwnd;
397
	tcp_newcwv_reset(tp);
398
381
	if (CC_ALGO(tp)->conn_init != NULL)
399
	if (CC_ALGO(tp)->conn_init != NULL)
382
		CC_ALGO(tp)->conn_init(tp->ccv);
400
		CC_ALGO(tp)->conn_init(tp->ccv);
383
}
401
}
Lines 426-431 cc_cong_signal(struct tcpcb *tp, struct tcphdr *th Link Here
426
		tp->t_badrxtwin = 0;
444
		tp->t_badrxtwin = 0;
427
		break;
445
		break;
428
	}
446
	}
447
	
448
	if (V_tcp_do_newcwv && 
449
			(type == CC_NDUPACK || type == CC_ECN) &&
450
				tp->pipeack <= (tp->snd_cwnd >> 1) )
451
		tcp_newcwv_enter_recovery(tp);
429
452
430
	if (CC_ALGO(tp)->cong_signal != NULL) {
453
	if (CC_ALGO(tp)->cong_signal != NULL) {
431
		if (th != NULL)
454
		if (th != NULL)
Lines 447-452 cc_post_recovery(struct tcpcb *tp, struct tcphdr * Link Here
447
	}
470
	}
448
	/* XXXLAS: EXIT_RECOVERY ? */
471
	/* XXXLAS: EXIT_RECOVERY ? */
449
	tp->t_bytes_acked = 0;
472
	tp->t_bytes_acked = 0;
473
474
	if(V_tcp_do_newcwv) {
475
		if(tp->loss_flight_size)
476
			tcp_newcwv_end_recovery(tp);
477
		tcp_newcwv_reset(tp);	
478
	}
479
	tp->loss_flight_size = 0;
450
}
480
}
451
481
452
#ifdef TCP_SIGNATURE
482
#ifdef TCP_SIGNATURE
(-)sys/netinet/tcp_newcwv.c (+174 lines)
Line 0 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-06) 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->psp = MAX(3 * tp->t_srtt,hz); 
60
61
	if (tp->snd_una >= tp->prev_snd_nxt) {
62
		/* get the pipeack sample */
63
		tmp_pipeack = tp->snd_una - tp->prev_snd_una;
64
65
		tp->prev_snd_una = tp->snd_una;
66
		tp->prev_snd_nxt = tp->snd_nxt;
67
68
		/* create a new element at the end of current pmp */
69
		if(ticks > tp->time_stamp[tp->head] + (tp->psp >> 2))  
70
			add_element(tp,tmp_pipeack);
71
		else 
72
			tp->psample[tp->head] = tmp_pipeack;
73
	}
74
75
	tp->pipeack = remove_expired_elements(tp);
76
77
	/* check if cwnd is validated */
78
	if (tp->pipeack == NCWV_UNDEF || 
79
		((tp->pipeack << 1) >= (tp->snd_cwnd * tp->t_maxseg))) {
80
		tp->cwnd_valid_ts = ticks;
81
	} 
82
}
83
84
void 
85
add_element(struct tcpcb *tp,u_int32_t value)
86
{
87
	tp->head = nextbin(tp->head);
88
	tp->psample[tp->head] = value;
89
	tp->time_stamp[tp->head] = ticks;
90
}
91
92
u_int32_t
93
remove_expired_elements(struct tcpcb *tp)
94
{
95
	uint8_t head = tp->head;
96
	u_int32_t tmp = tp->psample[head];
97
98
	while(tp->psample[head] != NCWV_UNDEF) {
99
		/* remove the element if expired */
100
		if (tp->time_stamp[head] < ticks - tp->psp) {
101
			tp->psample[head] = NCWV_UNDEF;
102
			return tmp;
103
		}
104
105
		/* search for the max pipeack */
106
		if(tp->psample[head] > tmp)
107
			tmp = tp->psample[head];
108
109
		head = prevbin(head);
110
		if(head == tp->head)
111
			return tmp;
112
	}	
113
114
	return tmp;
115
}
116
117
/* Initialise NewCWV state */
118
void
119
tcp_newcwv_reset(struct tcpcb *tp)
120
{
121
	tp->prev_snd_una = tp->snd_una;
122
	tp->prev_snd_nxt = tp->snd_nxt;
123
	tp->cwnd_valid_ts = ticks;
124
	tp->loss_flight_size = 0;
125
126
	tp->head = 0;
127
	tp->psample[0] = NCWV_UNDEF;
128
	tp->pipeack = NCWV_UNDEF;
129
}
130
131
/* NewCWV actions at loss detection */
132
void
133
tcp_newcwv_enter_recovery(struct tcpcb *tp)
134
{
135
	u_int32_t pipe;
136
137
	if(tp->pipeack == NCWV_UNDEF)
138
		return;
139
140
	tp->prior_retrans = tp->t_sndrexmitpack;
141
142
	/* Calculate the flight size */
143
	u_int32_t awnd = (tp->snd_nxt - tp->snd_fack) + tp->sackhint.sack_bytes_rexmit;
144
	tp->loss_flight_size = awnd;
145
146
	pipe = MAX(tp->pipeack,tp->loss_flight_size);
147
	tp->snd_cwnd = MAX(pipe >> 1,1);
148
}
149
150
/* NewCWV actions at the end of recovery */
151
void
152
tcp_newcwv_end_recovery(struct tcpcb *tp)
153
{
154
	u_int32_t retrans,pipe;
155
156
	retrans = (tp->t_sndrexmitpack - tp->prior_retrans) * tp->t_maxseg;
157
	pipe = MAX(tp->pipeack,tp->loss_flight_size) - retrans;
158
159
	/* Ensure that snd_ssthresh is non 0 */
160
	tp->snd_ssthresh = MAX(pipe >> 1,1); 
161
	tp->snd_cwnd = tp->snd_ssthresh;
162
}
163
164
void
165
tcp_newcwv_datalim_closedown(struct tcpcb *tp)
166
{
167
	while ((ticks - tp->cwnd_valid_ts) > NCWV_FIVEMINS && 
168
	  tp->snd_cwnd > tp->init_cwnd) {
169
170
		tp->cwnd_valid_ts += NCWV_FIVEMINS;
171
		tp->snd_ssthresh = MAX( (3 * tp->snd_cwnd ) >> 2,tp->snd_ssthresh);
172
		tp->snd_cwnd = MAX(tp->snd_cwnd >> 1, tp->init_cwnd);
173
	}
174
}
(-)sys/netinet/tcp_newcwv.h (+39 lines)
Line 0 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_ */
(-)sys/netinet/tcp_output.c (+5 lines)
Lines 74-79 __FBSDID("$FreeBSD$"); 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 691-696 send: Link Here
691
#endif
692
#endif
692
		hdrlen = sizeof (struct tcpiphdr);
693
		hdrlen = sizeof (struct tcpiphdr);
693
694
695
	/* Trigger the newcwv timer */
696
	if(V_tcp_do_newcwv)
697
		tcp_newcwv_datalim_closedown(tp);
698
694
	/*
699
	/*
695
	 * Compute options for segment.
700
	 * Compute options for segment.
696
	 * We only have to care about SYN and established connection
701
	 * We only have to care about SYN and established connection
(-)sys/netinet/tcp_subr.c (+1 lines)
Lines 800-805 tcp_newtcpcb(struct inpcb *inp) Link Here
800
		tp->t_flags = (TF_REQ_SCALE|TF_REQ_TSTMP);
800
		tp->t_flags = (TF_REQ_SCALE|TF_REQ_TSTMP);
801
	if (V_tcp_do_sack)
801
	if (V_tcp_do_sack)
802
		tp->t_flags |= TF_SACK_PERMIT;
802
		tp->t_flags |= TF_SACK_PERMIT;
803
803
	TAILQ_INIT(&tp->snd_holes);
804
	TAILQ_INIT(&tp->snd_holes);
804
	tp->t_inpcb = inp;	/* XXX */
805
	tp->t_inpcb = inp;	/* XXX */
805
	/*
806
	/*
(-)sys/netinet/tcp_var.h (+16 lines)
Lines 172-177 struct tcpcb { 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
	u_int32_t pipeack;
177
	u_int32_t psp;			/* pipeack sampling period */
178
179
	u_int32_t head;
180
	u_int32_t psample[4];	/* pipe ack samples */
181
	u_int32_t time_stamp[4];	/* time stamp samples */
182
	u_int32_t prev_snd_una;		/* previous snd_una in this sampe */
183
	u_int32_t prev_snd_nxt;		/* previous snd_nxt in this sampe */
184
185
	u_int32_t loss_flight_size;	/* flightsize at loss detection */
186
	u_int32_t prior_retrans;	/* Retransmission before going into FR */
187
	u_int32_t cwnd_valid_ts;	/*last time cwnd was found valid */
188
	u_int32_t init_cwnd;	/* The inital cwnd */
175
/* SACK related state */
189
/* SACK related state */
176
	int	snd_numholes;		/* number of holes seen by sender */
190
	int	snd_numholes;		/* number of holes seen by sender */
177
	TAILQ_HEAD(sackhole_head, sackhole) snd_holes;
191
	TAILQ_HEAD(sackhole_head, sackhole) snd_holes;
Lines 605-610 VNET_DECLARE(int, tcp_recvspace); Link Here
605
VNET_DECLARE(int, path_mtu_discovery);
619
VNET_DECLARE(int, path_mtu_discovery);
606
VNET_DECLARE(int, tcp_do_rfc3465);
620
VNET_DECLARE(int, tcp_do_rfc3465);
607
VNET_DECLARE(int, tcp_abc_l_var);
621
VNET_DECLARE(int, tcp_abc_l_var);
622
VNET_DECLARE(int, tcp_do_newcwv);
608
#define	V_tcb			VNET(tcb)
623
#define	V_tcb			VNET(tcb)
609
#define	V_tcbinfo		VNET(tcbinfo)
624
#define	V_tcbinfo		VNET(tcbinfo)
610
#define	V_tcp_mssdflt		VNET(tcp_mssdflt)
625
#define	V_tcp_mssdflt		VNET(tcp_mssdflt)
Lines 617-622 VNET_DECLARE(int, tcp_abc_l_var); Link Here
617
#define	V_path_mtu_discovery	VNET(path_mtu_discovery)
632
#define	V_path_mtu_discovery	VNET(path_mtu_discovery)
618
#define	V_tcp_do_rfc3465	VNET(tcp_do_rfc3465)
633
#define	V_tcp_do_rfc3465	VNET(tcp_do_rfc3465)
619
#define	V_tcp_abc_l_var		VNET(tcp_abc_l_var)
634
#define	V_tcp_abc_l_var		VNET(tcp_abc_l_var)
635
#define	V_tcp_do_newcwv		VNET(tcp_do_newcwv)
620
636
621
VNET_DECLARE(int, tcp_do_sack);			/* SACK enabled/disabled */
637
VNET_DECLARE(int, tcp_do_sack);			/* SACK enabled/disabled */
622
VNET_DECLARE(int, tcp_sc_rst_sock_fail);	/* RST on sock alloc failure */
638
VNET_DECLARE(int, tcp_sc_rst_sock_fail);	/* RST on sock alloc failure */

Return to bug 191520