summaryrefslogtreecommitdiffstats
path: root/sys/netinet/tcp_usrreq.c
diff options
context:
space:
mode:
authorglebius <glebius@FreeBSD.org>2012-02-05 16:53:02 +0000
committerglebius <glebius@FreeBSD.org>2012-02-05 16:53:02 +0000
commit4326beb059fb2e0786289b19b1bf9a8b7a2b824b (patch)
treedcb36bc519c1f170cc8c8a32ba0dd1c8c7acfc78 /sys/netinet/tcp_usrreq.c
parent96baefc0cb3bd4bac8a5c692c335abaf29650d71 (diff)
downloadFreeBSD-src-4326beb059fb2e0786289b19b1bf9a8b7a2b824b.zip
FreeBSD-src-4326beb059fb2e0786289b19b1bf9a8b7a2b824b.tar.gz
Add new socket options: TCP_KEEPINIT, TCP_KEEPIDLE, TCP_KEEPINTVL and
TCP_KEEPCNT, that allow to control initial timeout, idle time, idle re-send interval and idle send count on a per-socket basis. Reviewed by: andre, bz, lstewart
Diffstat (limited to 'sys/netinet/tcp_usrreq.c')
-rw-r--r--sys/netinet/tcp_usrreq.c61
1 files changed, 58 insertions, 3 deletions
diff --git a/sys/netinet/tcp_usrreq.c b/sys/netinet/tcp_usrreq.c
index 5e2af8f..a9045f3 100644
--- a/sys/netinet/tcp_usrreq.c
+++ b/sys/netinet/tcp_usrreq.c
@@ -45,6 +45,7 @@ __FBSDID("$FreeBSD$");
#include <sys/param.h>
#include <sys/systm.h>
+#include <sys/limits.h>
#include <sys/malloc.h>
#include <sys/kernel.h>
#include <sys/sysctl.h>
@@ -1118,7 +1119,7 @@ tcp_connect(struct tcpcb *tp, struct sockaddr *nam, struct thread *td)
soisconnecting(so);
TCPSTAT_INC(tcps_connattempt);
tp->t_state = TCPS_SYN_SENT;
- tcp_timer_activate(tp, TT_KEEP, tcp_keepinit);
+ tcp_timer_activate(tp, TT_KEEP, TP_KEEPINIT(tp));
tp->iss = tcp_new_isn(tp);
tcp_sendseqinit(tp);
@@ -1191,7 +1192,7 @@ tcp6_connect(struct tcpcb *tp, struct sockaddr *nam, struct thread *td)
soisconnecting(so);
TCPSTAT_INC(tcps_connattempt);
tp->t_state = TCPS_SYN_SENT;
- tcp_timer_activate(tp, TT_KEEP, tcp_keepinit);
+ tcp_timer_activate(tp, TT_KEEP, TP_KEEPINIT(tp));
tp->iss = tcp_new_isn(tp);
tcp_sendseqinit(tp);
@@ -1272,6 +1273,7 @@ int
tcp_ctloutput(struct socket *so, struct sockopt *sopt)
{
int error, opt, optval;
+ u_int ui;
struct inpcb *inp;
struct tcpcb *tp;
struct tcp_info ti;
@@ -1439,6 +1441,59 @@ tcp_ctloutput(struct socket *so, struct sockopt *sopt)
INP_WUNLOCK(inp);
break;
+ case TCP_KEEPIDLE:
+ case TCP_KEEPINTVL:
+ case TCP_KEEPCNT:
+ case TCP_KEEPINIT:
+ INP_WUNLOCK(inp);
+ error = sooptcopyin(sopt, &ui, sizeof(ui), sizeof(ui));
+ if (error)
+ return (error);
+
+ if (ui > (UINT_MAX / hz)) {
+ error = EINVAL;
+ break;
+ }
+ ui *= hz;
+
+ INP_WLOCK_RECHECK(inp);
+ switch (sopt->sopt_name) {
+ case TCP_KEEPIDLE:
+ tp->t_keepidle = ui;
+ /*
+ * XXX: better check current remaining
+ * timeout and "merge" it with new value.
+ */
+ if ((tp->t_state > TCPS_LISTEN) &&
+ (tp->t_state <= TCPS_CLOSING))
+ tcp_timer_activate(tp, TT_KEEP,
+ TP_KEEPIDLE(tp));
+ break;
+ case TCP_KEEPINTVL:
+ tp->t_keepintvl = ui;
+ if ((tp->t_state == TCPS_FIN_WAIT_2) &&
+ (TP_MAXIDLE(tp) > 0))
+ tcp_timer_activate(tp, TT_2MSL,
+ TP_MAXIDLE(tp));
+ break;
+ case TCP_KEEPCNT:
+ tp->t_keepcnt = ui;
+ if ((tp->t_state == TCPS_FIN_WAIT_2) &&
+ (TP_MAXIDLE(tp) > 0))
+ tcp_timer_activate(tp, TT_2MSL,
+ TP_MAXIDLE(tp));
+ break;
+ case TCP_KEEPINIT:
+ tp->t_keepinit = ui;
+ if (tp->t_state == TCPS_SYN_RECEIVED ||
+ tp->t_state == TCPS_SYN_SENT)
+ tcp_timer_activate(tp, TT_KEEP,
+ TP_KEEPINIT(tp));
+ break;
+ }
+ INP_WUNLOCK(inp);
+ break;
+
default:
INP_WUNLOCK(inp);
error = ENOPROTOOPT;
@@ -1636,7 +1691,7 @@ tcp_usrclosed(struct tcpcb *tp)
int timeout;
timeout = (tcp_fast_finwait2_recycle) ?
- tcp_finwait2_timeout : tcp_maxidle;
+ tcp_finwait2_timeout : TP_MAXIDLE(tp);
tcp_timer_activate(tp, TT_2MSL, timeout);
}
}
OpenPOWER on IntegriCloud