822 lines
14 KiB
HTML
822 lines
14 KiB
HTML
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0 Transitional//EN">
|
|
<HTML
|
|
><HEAD
|
|
><TITLE
|
|
>Using TCP keepalive under Linux</TITLE
|
|
><META
|
|
NAME="GENERATOR"
|
|
CONTENT="Modular DocBook HTML Stylesheet Version 1.7"><LINK
|
|
REL="HOME"
|
|
TITLE="TCP Keepalive HOWTO"
|
|
HREF="index.html"><LINK
|
|
REL="PREVIOUS"
|
|
TITLE="TCP keepalive overview"
|
|
HREF="overview.html"><LINK
|
|
REL="NEXT"
|
|
TITLE="Programming applications"
|
|
HREF="programming.html"></HEAD
|
|
><BODY
|
|
CLASS="sect1"
|
|
BGCOLOR="#FFFFFF"
|
|
TEXT="#000000"
|
|
LINK="#0000FF"
|
|
VLINK="#840084"
|
|
ALINK="#0000FF"
|
|
><DIV
|
|
CLASS="NAVHEADER"
|
|
><TABLE
|
|
SUMMARY="Header navigation table"
|
|
WIDTH="100%"
|
|
BORDER="0"
|
|
CELLPADDING="0"
|
|
CELLSPACING="0"
|
|
><TR
|
|
><TH
|
|
COLSPAN="3"
|
|
ALIGN="center"
|
|
>TCP Keepalive HOWTO</TH
|
|
></TR
|
|
><TR
|
|
><TD
|
|
WIDTH="10%"
|
|
ALIGN="left"
|
|
VALIGN="bottom"
|
|
><A
|
|
HREF="overview.html"
|
|
ACCESSKEY="P"
|
|
>Prev</A
|
|
></TD
|
|
><TD
|
|
WIDTH="80%"
|
|
ALIGN="center"
|
|
VALIGN="bottom"
|
|
></TD
|
|
><TD
|
|
WIDTH="10%"
|
|
ALIGN="right"
|
|
VALIGN="bottom"
|
|
><A
|
|
HREF="programming.html"
|
|
ACCESSKEY="N"
|
|
>Next</A
|
|
></TD
|
|
></TR
|
|
></TABLE
|
|
><HR
|
|
ALIGN="LEFT"
|
|
WIDTH="100%"></DIV
|
|
><DIV
|
|
CLASS="sect1"
|
|
><H1
|
|
CLASS="sect1"
|
|
><A
|
|
NAME="usingkeepalive"
|
|
></A
|
|
>3. Using TCP keepalive under Linux</H1
|
|
><P
|
|
> Linux has built-in support for keepalive. You need to enable TCP/IP
|
|
networking in order to use it. You also need <TT
|
|
CLASS="literal"
|
|
>procfs</TT
|
|
>
|
|
support and <TT
|
|
CLASS="literal"
|
|
>sysctl</TT
|
|
> support to be able to configure the
|
|
kernel parameters at runtime.
|
|
</P
|
|
><P
|
|
> The procedures involving keepalive use three user-driven variables:
|
|
|
|
<P
|
|
></P
|
|
><DIV
|
|
CLASS="variablelist"
|
|
><DL
|
|
><DT
|
|
><TT
|
|
CLASS="varname"
|
|
>tcp_keepalive_time</TT
|
|
></DT
|
|
><DD
|
|
><P
|
|
> the interval between the last data packet sent (simple ACKs are not
|
|
considered data) and the first keepalive probe; after the connection
|
|
is marked to need keepalive, this counter is not used any further
|
|
</P
|
|
></DD
|
|
><DT
|
|
><TT
|
|
CLASS="varname"
|
|
>tcp_keepalive_intvl</TT
|
|
></DT
|
|
><DD
|
|
><P
|
|
> the interval between subsequential keepalive probes, regardless of
|
|
what the connection has exchanged in the meantime
|
|
</P
|
|
></DD
|
|
><DT
|
|
><TT
|
|
CLASS="varname"
|
|
>tcp_keepalive_probes</TT
|
|
></DT
|
|
><DD
|
|
><P
|
|
> the number of unacknowledged probes to send before considering the
|
|
connection dead and notifying the application layer
|
|
</P
|
|
></DD
|
|
></DL
|
|
></DIV
|
|
>
|
|
</P
|
|
><P
|
|
> Remember that keepalive support, even if configured in the kernel, is not
|
|
the default behavior in Linux. Programs must request keepalive control for
|
|
their sockets using the <TT
|
|
CLASS="literal"
|
|
>setsockopt</TT
|
|
> interface. There are
|
|
relatively few programs implementing keepalive, but you can easily add
|
|
keepalive support for most of them following the instructions explained
|
|
later in this document.
|
|
</P
|
|
><DIV
|
|
CLASS="sect2"
|
|
><H2
|
|
CLASS="sect2"
|
|
><A
|
|
NAME="configuringkernel"
|
|
></A
|
|
>3.1. Configuring the kernel</H2
|
|
><P
|
|
> There are two ways to configure keepalive parameters inside the kernel via
|
|
userspace commands:
|
|
|
|
<P
|
|
></P
|
|
><UL
|
|
><LI
|
|
><P
|
|
><TT
|
|
CLASS="literal"
|
|
>procfs</TT
|
|
> interface</P
|
|
></LI
|
|
><LI
|
|
><P
|
|
><TT
|
|
CLASS="literal"
|
|
>sysctl</TT
|
|
> interface</P
|
|
></LI
|
|
></UL
|
|
>
|
|
</P
|
|
><P
|
|
> We mainly discuss how this is accomplished on the procfs interface because
|
|
it's the most used, recommended and the easiest to understand. The sysctl
|
|
interface, particularly regarding the <SPAN
|
|
CLASS="citerefentry"
|
|
><SPAN
|
|
CLASS="refentrytitle"
|
|
> <TT
|
|
CLASS="function"
|
|
>sysctl</TT
|
|
></SPAN
|
|
>(2)</SPAN
|
|
> syscall and not the <SPAN
|
|
CLASS="citerefentry"
|
|
><SPAN
|
|
CLASS="refentrytitle"
|
|
><B
|
|
CLASS="command"
|
|
> sysctl</B
|
|
></SPAN
|
|
>(8)</SPAN
|
|
>
|
|
tool, is only here for the purpose of background knowledge.
|
|
</P
|
|
><DIV
|
|
CLASS="sect3"
|
|
><H3
|
|
CLASS="sect3"
|
|
><A
|
|
NAME="procfsinterface"
|
|
></A
|
|
>3.1.1. The <TT
|
|
CLASS="literal"
|
|
>procfs</TT
|
|
> interface</H3
|
|
><P
|
|
> This interface requires both <TT
|
|
CLASS="literal"
|
|
>sysctl</TT
|
|
> and <TT
|
|
CLASS="literal"
|
|
> procfs</TT
|
|
> to be built into the kernel, and <TT
|
|
CLASS="literal"
|
|
>procfs
|
|
</TT
|
|
> mounted somewhere in the filesystem (usually on <TT
|
|
CLASS="filename"
|
|
> /proc</TT
|
|
>, as in the examples below). You can read the values for
|
|
the actual parameters by <SPAN
|
|
CLASS="QUOTE"
|
|
>"catting"</SPAN
|
|
> files in <TT
|
|
CLASS="filename"
|
|
> /proc/sys/net/ipv4/</TT
|
|
> directory:
|
|
|
|
<DIV
|
|
CLASS="informalexample"
|
|
><A
|
|
NAME="AEN133"
|
|
></A
|
|
><P
|
|
></P
|
|
><TABLE
|
|
BORDER="0"
|
|
BGCOLOR="#E0E0E0"
|
|
WIDTH="100%"
|
|
><TR
|
|
><TD
|
|
><FONT
|
|
COLOR="#000000"
|
|
><PRE
|
|
CLASS="programlisting"
|
|
> <TT
|
|
CLASS="prompt"
|
|
># </TT
|
|
><TT
|
|
CLASS="userinput"
|
|
><B
|
|
>cat /proc/sys/net/ipv4/tcp_keepalive_time</B
|
|
></TT
|
|
>
|
|
<TT
|
|
CLASS="computeroutput"
|
|
>7200</TT
|
|
>
|
|
|
|
<TT
|
|
CLASS="prompt"
|
|
># </TT
|
|
><TT
|
|
CLASS="userinput"
|
|
><B
|
|
>cat /proc/sys/net/ipv4/tcp_keepalive_intvl</B
|
|
></TT
|
|
>
|
|
<TT
|
|
CLASS="computeroutput"
|
|
>75</TT
|
|
>
|
|
|
|
<TT
|
|
CLASS="prompt"
|
|
># </TT
|
|
><TT
|
|
CLASS="userinput"
|
|
><B
|
|
>cat /proc/sys/net/ipv4/tcp_keepalive_probes</B
|
|
></TT
|
|
>
|
|
<TT
|
|
CLASS="computeroutput"
|
|
>9</TT
|
|
>
|
|
</PRE
|
|
></FONT
|
|
></TD
|
|
></TR
|
|
></TABLE
|
|
><P
|
|
></P
|
|
></DIV
|
|
>
|
|
</P
|
|
><P
|
|
> The first two parameters are expressed in seconds, and the last is the
|
|
pure number. This means that the keepalive routines wait for two hours
|
|
(7200 secs) before sending the first keepalive probe, and then resend it
|
|
every 75 seconds. If no ACK response is received for nine consecutive
|
|
times, the connection is marked as broken.
|
|
</P
|
|
><P
|
|
> Modifying this value is straightforward: you need to write new values
|
|
into the files. Suppose you decide to configure the host so that
|
|
keepalive starts after ten minutes of channel inactivity, and then send
|
|
probes in intervals of one minute. Because of the high instability of
|
|
our network trunk and the low value of the interval, suppose you also
|
|
want to increase the number of probes to 20.
|
|
</P
|
|
><P
|
|
> Here's how we would change the settings:
|
|
|
|
<DIV
|
|
CLASS="informalexample"
|
|
><A
|
|
NAME="AEN147"
|
|
></A
|
|
><P
|
|
></P
|
|
><TABLE
|
|
BORDER="0"
|
|
BGCOLOR="#E0E0E0"
|
|
WIDTH="100%"
|
|
><TR
|
|
><TD
|
|
><FONT
|
|
COLOR="#000000"
|
|
><PRE
|
|
CLASS="programlisting"
|
|
> <TT
|
|
CLASS="prompt"
|
|
># </TT
|
|
><TT
|
|
CLASS="userinput"
|
|
><B
|
|
>echo 600 > /proc/sys/net/ipv4/tcp_keepalive_time</B
|
|
></TT
|
|
>
|
|
|
|
<TT
|
|
CLASS="prompt"
|
|
># </TT
|
|
><TT
|
|
CLASS="userinput"
|
|
><B
|
|
>echo 60 > /proc/sys/net/ipv4/tcp_keepalive_intvl</B
|
|
></TT
|
|
>
|
|
|
|
<TT
|
|
CLASS="prompt"
|
|
># </TT
|
|
><TT
|
|
CLASS="userinput"
|
|
><B
|
|
>echo 20 > /proc/sys/net/ipv4/tcp_keepalive_probes</B
|
|
></TT
|
|
>
|
|
</PRE
|
|
></FONT
|
|
></TD
|
|
></TR
|
|
></TABLE
|
|
><P
|
|
></P
|
|
></DIV
|
|
>
|
|
</P
|
|
><P
|
|
> To be sure that all succeeds, recheck the files and confirm these new
|
|
values are showing in place of the old ones.
|
|
</P
|
|
><P
|
|
> Remember that <TT
|
|
CLASS="literal"
|
|
>procfs</TT
|
|
> handles special files, and you
|
|
cannot perform any sort of operation on them because they're just an interface within the kernel space, not real
|
|
files, so try your
|
|
scripts before using them, and try to use simple access methods as in
|
|
the examples shown earlier.
|
|
</P
|
|
><P
|
|
> You can access the interface through the <SPAN
|
|
CLASS="citerefentry"
|
|
><SPAN
|
|
CLASS="refentrytitle"
|
|
> <B
|
|
CLASS="command"
|
|
>sysctl</B
|
|
></SPAN
|
|
>(8)</SPAN
|
|
> tool, specifying what you want to read or write.
|
|
|
|
<DIV
|
|
CLASS="informalexample"
|
|
><A
|
|
NAME="AEN163"
|
|
></A
|
|
><P
|
|
></P
|
|
><TABLE
|
|
BORDER="0"
|
|
BGCOLOR="#E0E0E0"
|
|
WIDTH="100%"
|
|
><TR
|
|
><TD
|
|
><FONT
|
|
COLOR="#000000"
|
|
><PRE
|
|
CLASS="programlisting"
|
|
> <TT
|
|
CLASS="prompt"
|
|
># </TT
|
|
><TT
|
|
CLASS="userinput"
|
|
><B
|
|
>sysctl \</B
|
|
></TT
|
|
>
|
|
<TT
|
|
CLASS="prompt"
|
|
>> </TT
|
|
><TT
|
|
CLASS="userinput"
|
|
><B
|
|
>net.ipv4.tcp_keepalive_time \</B
|
|
></TT
|
|
>
|
|
<TT
|
|
CLASS="prompt"
|
|
>> </TT
|
|
><TT
|
|
CLASS="userinput"
|
|
><B
|
|
>net.ipv4.tcp_keepalive_intvl \</B
|
|
></TT
|
|
>
|
|
<TT
|
|
CLASS="prompt"
|
|
>> </TT
|
|
><TT
|
|
CLASS="userinput"
|
|
><B
|
|
>net.ipv4.tcp_keepalive_probes</B
|
|
></TT
|
|
>
|
|
<TT
|
|
CLASS="computeroutput"
|
|
>net.ipv4.tcp_keepalive_time = 7200
|
|
net.ipv4.tcp_keepalive_intvl = 75
|
|
net.ipv4.tcp_keepalive_probes = 9</TT
|
|
>
|
|
</PRE
|
|
></FONT
|
|
></TD
|
|
></TR
|
|
></TABLE
|
|
><P
|
|
></P
|
|
></DIV
|
|
>
|
|
</P
|
|
><P
|
|
> Note that <TT
|
|
CLASS="literal"
|
|
>sysctl</TT
|
|
> names are very close to <TT
|
|
CLASS="literal"
|
|
> procfs</TT
|
|
> paths. Write is performed using the <TT
|
|
CLASS="option"
|
|
>-w</TT
|
|
>
|
|
switch of <SPAN
|
|
CLASS="citerefentry"
|
|
><SPAN
|
|
CLASS="refentrytitle"
|
|
><B
|
|
CLASS="command"
|
|
>sysctl</B
|
|
>
|
|
</SPAN
|
|
>(8)</SPAN
|
|
>:
|
|
|
|
<DIV
|
|
CLASS="informalexample"
|
|
><A
|
|
NAME="AEN182"
|
|
></A
|
|
><P
|
|
></P
|
|
><TABLE
|
|
BORDER="0"
|
|
BGCOLOR="#E0E0E0"
|
|
WIDTH="100%"
|
|
><TR
|
|
><TD
|
|
><FONT
|
|
COLOR="#000000"
|
|
><PRE
|
|
CLASS="programlisting"
|
|
> <TT
|
|
CLASS="prompt"
|
|
># </TT
|
|
><TT
|
|
CLASS="userinput"
|
|
><B
|
|
>sysctl -w \</B
|
|
></TT
|
|
>
|
|
<TT
|
|
CLASS="prompt"
|
|
>> </TT
|
|
><TT
|
|
CLASS="userinput"
|
|
><B
|
|
>net.ipv4.tcp_keepalive_time=600 \</B
|
|
></TT
|
|
>
|
|
<TT
|
|
CLASS="prompt"
|
|
>> </TT
|
|
><TT
|
|
CLASS="userinput"
|
|
><B
|
|
>net.ipv4.tcp_keepalive_intvl=60 \</B
|
|
></TT
|
|
>
|
|
<TT
|
|
CLASS="prompt"
|
|
>> </TT
|
|
><TT
|
|
CLASS="userinput"
|
|
><B
|
|
>net.ipv4.tcp_keepalive_probes=20</B
|
|
></TT
|
|
>
|
|
<TT
|
|
CLASS="computeroutput"
|
|
>net.ipv4.tcp_keepalive_time = 600
|
|
net.ipv4.tcp_keepalive_intvl = 60
|
|
net.ipv4.tcp_keepalive_probes = 20</TT
|
|
>
|
|
</PRE
|
|
></FONT
|
|
></TD
|
|
></TR
|
|
></TABLE
|
|
><P
|
|
></P
|
|
></DIV
|
|
>
|
|
</P
|
|
><P
|
|
> Note that <SPAN
|
|
CLASS="citerefentry"
|
|
><SPAN
|
|
CLASS="refentrytitle"
|
|
><B
|
|
CLASS="command"
|
|
>sysctl</B
|
|
>
|
|
</SPAN
|
|
>(8)</SPAN
|
|
> doesn't use
|
|
<SPAN
|
|
CLASS="citerefentry"
|
|
><SPAN
|
|
CLASS="refentrytitle"
|
|
><TT
|
|
CLASS="function"
|
|
>sysctl</TT
|
|
></SPAN
|
|
>(2)</SPAN
|
|
> syscall, but reads and writes
|
|
directly in the <TT
|
|
CLASS="literal"
|
|
>procfs</TT
|
|
> subtree, so you will need
|
|
<TT
|
|
CLASS="literal"
|
|
>procfs</TT
|
|
> enabled in the kernel and mounted in the
|
|
filesystem, just as you would if you directly accessed the files within
|
|
the <TT
|
|
CLASS="literal"
|
|
>procfs</TT
|
|
> interface. <SPAN
|
|
CLASS="citerefentry"
|
|
><SPAN
|
|
CLASS="refentrytitle"
|
|
> <B
|
|
CLASS="command"
|
|
>Sysctl</B
|
|
></SPAN
|
|
>(8)</SPAN
|
|
> is just a different way to do the same thing.
|
|
</P
|
|
></DIV
|
|
><DIV
|
|
CLASS="sect3"
|
|
><H3
|
|
CLASS="sect3"
|
|
><A
|
|
NAME="sysctlinterface"
|
|
></A
|
|
>3.1.2. The <TT
|
|
CLASS="literal"
|
|
>sysctl</TT
|
|
> interface</H3
|
|
><P
|
|
> There is another way to access kernel variables: <SPAN
|
|
CLASS="citerefentry"
|
|
><SPAN
|
|
CLASS="refentrytitle"
|
|
><TT
|
|
CLASS="function"
|
|
>sysctl</TT
|
|
></SPAN
|
|
>(2
|
|
)</SPAN
|
|
> syscall. It can be useful when you don't
|
|
have <TT
|
|
CLASS="literal"
|
|
>procfs</TT
|
|
> available because the communication with
|
|
the kernel is performed directly via syscall and not through the
|
|
<TT
|
|
CLASS="literal"
|
|
>procfs</TT
|
|
> subtree. There is currently no program that
|
|
wraps this syscall (remember that <SPAN
|
|
CLASS="citerefentry"
|
|
><SPAN
|
|
CLASS="refentrytitle"
|
|
><B
|
|
CLASS="command"
|
|
> sysctl</B
|
|
></SPAN
|
|
>(8)</SPAN
|
|
>
|
|
doesn't use it).
|
|
</P
|
|
><P
|
|
> For more details about using <SPAN
|
|
CLASS="citerefentry"
|
|
><SPAN
|
|
CLASS="refentrytitle"
|
|
><TT
|
|
CLASS="function"
|
|
> sysctl</TT
|
|
></SPAN
|
|
>(2)</SPAN
|
|
>
|
|
refer to the manpage.
|
|
</P
|
|
></DIV
|
|
></DIV
|
|
><DIV
|
|
CLASS="sect2"
|
|
><H2
|
|
CLASS="sect2"
|
|
><A
|
|
NAME="makepersistchanges"
|
|
></A
|
|
>3.2. Making changes persistent to reboot</H2
|
|
><P
|
|
> There are several ways to reconfigure your system every time it boots up.
|
|
First, remember that every Linux distribution has its own set of init
|
|
scripts called by <SPAN
|
|
CLASS="citerefentry"
|
|
><SPAN
|
|
CLASS="refentrytitle"
|
|
><B
|
|
CLASS="command"
|
|
>init</B
|
|
>
|
|
</SPAN
|
|
>(8)</SPAN
|
|
>. The most common
|
|
configurations include the <TT
|
|
CLASS="filename"
|
|
>/etc/rc.d/</TT
|
|
> directory, or
|
|
the alternative, <TT
|
|
CLASS="filename"
|
|
>/etc/init.d/</TT
|
|
>. In any case, you can
|
|
set the parameters in any of the startup scripts, because keepalive
|
|
rereads the values every time its procedures need them. So if you change
|
|
the value of <TT
|
|
CLASS="varname"
|
|
>tcp_keepalive_intvl</TT
|
|
> when the connection is
|
|
still up, the kernel will use the new value going forward.
|
|
</P
|
|
><P
|
|
> There are three spots where the initialization commands should logically
|
|
be placed: the first is where your network is configured, the second is
|
|
the <TT
|
|
CLASS="filename"
|
|
>rc.local</TT
|
|
> script, usually included in all
|
|
distributions, which is known as the place where user configuration setups
|
|
are done. The third place may already exist in your system. Referring back
|
|
to the <SPAN
|
|
CLASS="citerefentry"
|
|
><SPAN
|
|
CLASS="refentrytitle"
|
|
><B
|
|
CLASS="command"
|
|
>sysctl</B
|
|
>
|
|
</SPAN
|
|
>(8)</SPAN
|
|
> tool, you can see
|
|
that the <TT
|
|
CLASS="option"
|
|
>-p</TT
|
|
> switch loads settings from the <TT
|
|
CLASS="filename"
|
|
> /etc/sysctl.conf</TT
|
|
> configuration file. In many cases your init
|
|
script already performs the <B
|
|
CLASS="command"
|
|
>sysctl</B
|
|
> <TT
|
|
CLASS="option"
|
|
>-p</TT
|
|
>
|
|
(you can <SPAN
|
|
CLASS="QUOTE"
|
|
>"grep"</SPAN
|
|
> it in the configuration directory for
|
|
confirmation), and so you just have to add the lines in <TT
|
|
CLASS="filename"
|
|
> /etc/sysctl.conf</TT
|
|
> to make them load at every boot. For more
|
|
information about the syntax of <SPAN
|
|
CLASS="citerefentry"
|
|
><SPAN
|
|
CLASS="refentrytitle"
|
|
><TT
|
|
CLASS="filename"
|
|
> sysctl.conf</TT
|
|
></SPAN
|
|
>(5)</SPAN
|
|
>, refer to the manpage.
|
|
</P
|
|
></DIV
|
|
></DIV
|
|
><DIV
|
|
CLASS="NAVFOOTER"
|
|
><HR
|
|
ALIGN="LEFT"
|
|
WIDTH="100%"><TABLE
|
|
SUMMARY="Footer navigation table"
|
|
WIDTH="100%"
|
|
BORDER="0"
|
|
CELLPADDING="0"
|
|
CELLSPACING="0"
|
|
><TR
|
|
><TD
|
|
WIDTH="33%"
|
|
ALIGN="left"
|
|
VALIGN="top"
|
|
><A
|
|
HREF="overview.html"
|
|
ACCESSKEY="P"
|
|
>Prev</A
|
|
></TD
|
|
><TD
|
|
WIDTH="34%"
|
|
ALIGN="center"
|
|
VALIGN="top"
|
|
><A
|
|
HREF="index.html"
|
|
ACCESSKEY="H"
|
|
>Home</A
|
|
></TD
|
|
><TD
|
|
WIDTH="33%"
|
|
ALIGN="right"
|
|
VALIGN="top"
|
|
><A
|
|
HREF="programming.html"
|
|
ACCESSKEY="N"
|
|
>Next</A
|
|
></TD
|
|
></TR
|
|
><TR
|
|
><TD
|
|
WIDTH="33%"
|
|
ALIGN="left"
|
|
VALIGN="top"
|
|
>TCP keepalive overview</TD
|
|
><TD
|
|
WIDTH="34%"
|
|
ALIGN="center"
|
|
VALIGN="top"
|
|
> </TD
|
|
><TD
|
|
WIDTH="33%"
|
|
ALIGN="right"
|
|
VALIGN="top"
|
|
>Programming applications</TD
|
|
></TR
|
|
></TABLE
|
|
></DIV
|
|
></BODY
|
|
></HTML
|
|
> |