Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit ae375044 authored by Patrick McHardy's avatar Patrick McHardy Committed by David S. Miller
Browse files

netfilter: nf_conntrack_tcp: decrease timeouts while data in unacknowledged



In order to time out dead connections quicker, keep track of outstanding data
and cap the timeout.

Suggested by Herbert Xu.

Signed-off-by: default avatarPatrick McHardy <kaber@trash.net>
Signed-off-by: default avatarDavid S. Miller <davem@davemloft.net>
parent a97a6f10
Loading
Loading
Loading
Loading
+3 −0
Original line number Diff line number Diff line
@@ -30,6 +30,9 @@ enum tcp_conntrack {
/* Be liberal in window checking */
#define IP_CT_TCP_FLAG_BE_LIBERAL		0x08

/* Has unacknowledged data */
#define IP_CT_TCP_FLAG_DATA_UNACKNOWLEDGED	0x10

struct nf_ct_tcp_flags {
	u_int8_t flags;
	u_int8_t mask;
+24 −5
Original line number Diff line number Diff line
@@ -68,6 +68,7 @@ static const char *const tcp_conntrack_names[] = {
   Linux uses 15 packets as limit, which corresponds
   to ~13-30min depending on RTO. */
static unsigned int nf_ct_tcp_timeout_max_retrans __read_mostly    =   5 MINS;
static unsigned int nf_ct_tcp_timeout_unacknowledged __read_mostly =   5 MINS;

static unsigned int tcp_timeouts[TCP_CONNTRACK_MAX] __read_mostly = {
	[TCP_CONNTRACK_SYN_SENT]	= 2 MINS,
@@ -625,8 +626,10 @@ static bool tcp_in_window(const struct nf_conn *ct,
		swin = win + (sack - ack);
		if (sender->td_maxwin < swin)
			sender->td_maxwin = swin;
		if (after(end, sender->td_end))
		if (after(end, sender->td_end)) {
			sender->td_end = end;
			sender->flags |= IP_CT_TCP_FLAG_DATA_UNACKNOWLEDGED;
		}
		/*
		 * Update receiver data.
		 */
@@ -637,6 +640,8 @@ static bool tcp_in_window(const struct nf_conn *ct,
			if (win == 0)
				receiver->td_maxend++;
		}
		if (ack == receiver->td_end)
			receiver->flags &= ~IP_CT_TCP_FLAG_DATA_UNACKNOWLEDGED;

		/*
		 * Check retransmissions.
@@ -951,9 +956,16 @@ static int tcp_packet(struct nf_conn *ct,
	if (old_state != new_state
	    && new_state == TCP_CONNTRACK_FIN_WAIT)
		ct->proto.tcp.seen[dir].flags |= IP_CT_TCP_FLAG_CLOSE_INIT;
	timeout = ct->proto.tcp.retrans >= nf_ct_tcp_max_retrans
		  && tcp_timeouts[new_state] > nf_ct_tcp_timeout_max_retrans
		  ? nf_ct_tcp_timeout_max_retrans : tcp_timeouts[new_state];

	if (ct->proto.tcp.retrans >= nf_ct_tcp_max_retrans &&
	    tcp_timeouts[new_state] > nf_ct_tcp_timeout_max_retrans)
		timeout = nf_ct_tcp_timeout_max_retrans;
	else if ((ct->proto.tcp.seen[0].flags | ct->proto.tcp.seen[1].flags) &
		 IP_CT_TCP_FLAG_DATA_UNACKNOWLEDGED &&
		 tcp_timeouts[new_state] > nf_ct_tcp_timeout_unacknowledged)
		timeout = nf_ct_tcp_timeout_unacknowledged;
	else
		timeout = tcp_timeouts[new_state];
	write_unlock_bh(&tcp_lock);

	nf_conntrack_event_cache(IPCT_PROTOINFO_VOLATILE, skb);
@@ -1235,6 +1247,13 @@ static struct ctl_table tcp_sysctl_table[] = {
		.mode		= 0644,
		.proc_handler	= &proc_dointvec_jiffies,
	},
	{
		.procname	= "nf_conntrack_tcp_timeout_unacknowledged",
		.data		= &nf_ct_tcp_timeout_unacknowledged,
		.maxlen		= sizeof(unsigned int),
		.mode		= 0644,
		.proc_handler	= &proc_dointvec_jiffies,
	},
	{
		.ctl_name	= NET_NF_CONNTRACK_TCP_LOOSE,
		.procname	= "nf_conntrack_tcp_loose",