summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorhiren <hiren@FreeBSD.org>2016-01-11 23:31:13 +0000
committerhiren <hiren@FreeBSD.org>2016-01-11 23:31:13 +0000
commit4c421d2677178a7681006ade0918941097492ddc (patch)
tree0143216f7f7b26fba7c77c8534798fbd433b9776
parentd7f218dabddb221278509b64fbfe6223b81b1058 (diff)
downloadFreeBSD-src-4c421d2677178a7681006ade0918941097492ddc.zip
FreeBSD-src-4c421d2677178a7681006ade0918941097492ddc.tar.gz
MFC: r290122
Calculate the correct amount of bytes that are in-flight for a connection as suggested by RFC 6675. MFC: r292046 r290122 added 4 bytes and removed 8 in struct sackhint. Add a pad entry of 4 bytes to restore the size.
-rw-r--r--sys/netinet/tcp_input.c27
-rw-r--r--sys/netinet/tcp_sack.c6
-rw-r--r--sys/netinet/tcp_var.h11
3 files changed, 40 insertions, 4 deletions
diff --git a/sys/netinet/tcp_input.c b/sys/netinet/tcp_input.c
index b824ba2..b6fddc7 100644
--- a/sys/netinet/tcp_input.c
+++ b/sys/netinet/tcp_input.c
@@ -148,6 +148,11 @@ SYSCTL_VNET_INT(_net_inet_tcp, OID_AUTO, drop_synfin, CTLFLAG_RW,
&VNET_NAME(drop_synfin), 0,
"Drop TCP packets with SYN+FIN set");
+VNET_DEFINE(int, tcp_do_rfc6675_pipe) = 0;
+SYSCTL_INT(_net_inet_tcp, OID_AUTO, do_pipe, CTLFLAG_VNET | CTLFLAG_RW,
+ &VNET_NAME(tcp_do_rfc6675_pipe), 0,
+ "Use calculated pipe/in-flight bytes per RFC 6675");
+
VNET_DEFINE(int, tcp_do_rfc3042) = 1;
#define V_tcp_do_rfc3042 VNET(tcp_do_rfc3042)
SYSCTL_VNET_INT(_net_inet_tcp, OID_AUTO, rfc3042, CTLFLAG_RW,
@@ -2455,6 +2460,12 @@ tcp_do_segment(struct mbuf *m, struct tcphdr *th, struct socket *so,
((to.to_flags & TOF_SACK) ||
!TAILQ_EMPTY(&tp->snd_holes)))
tcp_sack_doack(tp, &to, th->th_ack);
+ else
+ /*
+ * Reset the value so that previous (valid) value
+ * from the last ack with SACK doesn't get used.
+ */
+ tp->sackhint.sacked_bytes = 0;
/* Run HHOOK_TCP_ESTABLISHED_IN helper hooks. */
hhook_run_tcp_est_in(tp, th, &to);
@@ -2505,8 +2516,12 @@ tcp_do_segment(struct mbuf *m, struct tcphdr *th, struct socket *so,
* we have less than 1/2 the original window's
* worth of data in flight.
*/
- awnd = (tp->snd_nxt - tp->snd_fack) +
- tp->sackhint.sack_bytes_rexmit;
+ if (V_tcp_do_rfc6675_pipe)
+ awnd = tcp_compute_pipe(tp);
+ else
+ awnd = (tp->snd_nxt - tp->snd_fack) +
+ tp->sackhint.sack_bytes_rexmit;
+
if (awnd < tp->snd_ssthresh) {
tp->snd_cwnd += tp->t_maxseg;
if (tp->snd_cwnd > tp->snd_ssthresh)
@@ -3798,3 +3813,11 @@ tcp_newreno_partial_ack(struct tcpcb *tp, struct tcphdr *th)
tp->snd_cwnd = 0;
tp->snd_cwnd += tp->t_maxseg;
}
+
+int
+tcp_compute_pipe(struct tcpcb *tp)
+{
+ return (tp->snd_max - tp->snd_una +
+ tp->sackhint.sack_bytes_rexmit -
+ tp->sackhint.sacked_bytes);
+}
diff --git a/sys/netinet/tcp_sack.c b/sys/netinet/tcp_sack.c
index 440bd64..28ee45c 100644
--- a/sys/netinet/tcp_sack.c
+++ b/sys/netinet/tcp_sack.c
@@ -368,6 +368,7 @@ tcp_sack_doack(struct tcpcb *tp, struct tcpopt *to, tcp_seq th_ack)
* received new blocks from the other side.
*/
if (to->to_flags & TOF_SACK) {
+ tp->sackhint.sacked_bytes = 0; /* reset */
for (i = 0; i < to->to_nsacks; i++) {
bcopy((to->to_sacks + i * TCPOLEN_SACK),
&sack, sizeof(sack));
@@ -378,8 +379,11 @@ tcp_sack_doack(struct tcpcb *tp, struct tcpopt *to, tcp_seq th_ack)
SEQ_GT(sack.start, th_ack) &&
SEQ_LT(sack.start, tp->snd_max) &&
SEQ_GT(sack.end, tp->snd_una) &&
- SEQ_LEQ(sack.end, tp->snd_max))
+ SEQ_LEQ(sack.end, tp->snd_max)) {
sack_blocks[num_sack_blks++] = sack;
+ tp->sackhint.sacked_bytes +=
+ (sack.end-sack.start);
+ }
}
}
/*
diff --git a/sys/netinet/tcp_var.h b/sys/netinet/tcp_var.h
index cff81c5..2d008c8 100644
--- a/sys/netinet/tcp_var.h
+++ b/sys/netinet/tcp_var.h
@@ -73,7 +73,12 @@ struct sackhint {
tcp_seq last_sack_ack; /* Most recent/largest sacked ack */
int ispare; /* explicit pad for 64bit alignment */
- uint64_t _pad[2]; /* 1 sacked_bytes, 1 TBD */
+ int sacked_bytes; /*
+ * Total sacked bytes reported by the
+ * receiver via sack option
+ */
+ uint32_t _pad1[1]; /* TBD */
+ uint64_t _pad[1]; /* TBD */
};
struct tcptemp {
@@ -668,6 +673,9 @@ VNET_DECLARE(int, tcp_ecn_maxretries);
VNET_DECLARE(struct hhook_head *, tcp_hhh[HHOOK_TCP_LAST + 1]);
#define V_tcp_hhh VNET(tcp_hhh)
+VNET_DECLARE(int, tcp_do_rfc6675_pipe);
+#define V_tcp_do_rfc6675_pipe VNET(tcp_do_rfc6675_pipe)
+
int tcp_addoptions(struct tcpopt *, u_char *);
int tcp_ccalgounload(struct cc_algo *unload_algo);
struct tcpcb *
@@ -757,6 +765,7 @@ void tcp_sack_partialack(struct tcpcb *, struct tcphdr *);
void tcp_free_sackholes(struct tcpcb *tp);
int tcp_newreno(struct tcpcb *, struct tcphdr *);
u_long tcp_seq_subtract(u_long, u_long );
+int tcp_compute_pipe(struct tcpcb *);
void cc_cong_signal(struct tcpcb *tp, struct tcphdr *th, uint32_t type);
OpenPOWER on IntegriCloud