Skip to content

Commit

Permalink
netfilter: nf_conntrack_tcp: decrease timeouts while data in unacknow…
Browse files Browse the repository at this point in the history
…ledged

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

Suggested by Herbert Xu.

Signed-off-by: Patrick McHardy <kaber@trash.net>
Signed-off-by: David S. Miller <davem@davemloft.net>
  • Loading branch information
Patrick McHardy authored and David S. Miller committed Jul 31, 2008
1 parent a97a6f1 commit ae37504
Show file tree
Hide file tree
Showing 2 changed files with 27 additions and 5 deletions.
3 changes: 3 additions & 0 deletions include/linux/netfilter/nf_conntrack_tcp.h
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand Down
29 changes: 24 additions & 5 deletions net/netfilter/nf_conntrack_proto_tcp.c
Original file line number Diff line number Diff line change
Expand Up @@ -67,7 +67,8 @@ static const char *const tcp_conntrack_names[] = {
/* RFC1122 says the R2 limit should be at least 100 seconds.
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_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,
Expand Down Expand Up @@ -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.
*/
Expand All @@ -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.
Expand Down Expand Up @@ -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);
Expand Down Expand Up @@ -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",
Expand Down

0 comments on commit ae37504

Please sign in to comment.