Keepalive values can be configured at run time with LWIP_TCP_KEEPALIVE, but don't change this unless you know what you're doing (default are RFC1122 compliant). Note that TCP_KEEPIDLE and TCP_KEEPINTVL have to be set in seconds.

Old TCP_KEEPALIVE can always be used, and its only difference with TCP_KEEPIDLE is this last use seconds and not milliseconds with setsockopt.

Some documentation (not perfect, but...):

http://publib.boulder.ibm.com/infocenter/pseries/v5r3/index.jsp?topic=/com.ibm.aix.commtechref/doc/commtrf2/setsockopt.htm
This commit is contained in:
fbernon 2007-03-11 15:53:43 +00:00
parent 41a84ef1d3
commit 5c65d4733b
7 changed files with 97 additions and 21 deletions

View File

@ -23,6 +23,12 @@ HISTORY
++ New features: ++ New features:
2007-03-11 Frédéric Bernon
* tcp.h, tcp.c, sockets.c, tcp_out.c, tcp_in.c, opt.h: Keepalive values can
be configured at run time with LWIP_TCP_KEEPALIVE, but don't change this
unless you know what you're doing (default are RFC1122 compliant). Note
that TCP_KEEPIDLE and TCP_KEEPINTVL have to be set in seconds.
2007-03-08 Frédéric Bernon 2007-03-08 Frédéric Bernon
* tcp.h: Keepalive values can be configured at compile time, but don't change * tcp.h: Keepalive values can be configured at compile time, but don't change
this unless you know what you're doing (default are RFC1122 compliant). this unless you know what you're doing (default are RFC1122 compliant).

View File

@ -1055,6 +1055,11 @@ int lwip_getsockopt (int s, int level, int optname, void *optval, socklen_t *opt
switch( optname ) { switch( optname ) {
case TCP_NODELAY: case TCP_NODELAY:
case TCP_KEEPALIVE: case TCP_KEEPALIVE:
#if LWIP_TCP_KEEPALIVE
case TCP_KEEPIDLE:
case TCP_KEEPINTVL:
case TCP_KEEPCNT:
#endif /* LWIP_TCP_KEEPALIVE */
break; break;
default: default:
@ -1157,9 +1162,25 @@ int lwip_getsockopt (int s, int level, int optname, void *optval, socklen_t *opt
LWIP_DEBUGF(SOCKETS_DEBUG, ("lwip_getsockopt(%d, IPPROTO_TCP, TCP_NODELAY) = %s\n", s, (*(int*)optval)?"on":"off") ); LWIP_DEBUGF(SOCKETS_DEBUG, ("lwip_getsockopt(%d, IPPROTO_TCP, TCP_NODELAY) = %s\n", s, (*(int*)optval)?"on":"off") );
break; break;
case TCP_KEEPALIVE: case TCP_KEEPALIVE:
*(int*)optval = (int)sock->conn->pcb.tcp->keepalive; *(int*)optval = (int)sock->conn->pcb.tcp->keep_idle;
LWIP_DEBUGF(SOCKETS_DEBUG, ("lwip_getsockopt(%d, IPPROTO_IP, TCP_KEEPALIVE) = %d\n", s, *(int *)optval)); LWIP_DEBUGF(SOCKETS_DEBUG, ("lwip_getsockopt(%d, IPPROTO_IP, TCP_KEEPALIVE) = %d\n", s, *(int *)optval));
break; break;
#if LWIP_TCP_KEEPALIVE
case TCP_KEEPIDLE:
*(int*)optval = (int)(sock->conn->pcb.tcp->keep_idle/1000);
LWIP_DEBUGF(SOCKETS_DEBUG, ("lwip_getsockopt(%d, IPPROTO_IP, TCP_KEEPIDLE) = %d\n", s, *(int *)optval));
break;
case TCP_KEEPINTVL:
*(int*)optval = (int)(sock->conn->pcb.tcp->keep_intvl/1000);
LWIP_DEBUGF(SOCKETS_DEBUG, ("lwip_getsockopt(%d, IPPROTO_IP, TCP_KEEPINTVL) = %d\n", s, *(int *)optval));
break;
case TCP_KEEPCNT:
*(int*)optval = (int)sock->conn->pcb.tcp->keep_cnt;
LWIP_DEBUGF(SOCKETS_DEBUG, ("lwip_getsockopt(%d, IPPROTO_IP, TCP_KEEPCNT) = %d\n", s, *(int *)optval));
break;
#endif /* LWIP_TCP_KEEPALIVE */
} /* switch */ } /* switch */
break; break;
} }
@ -1252,6 +1273,11 @@ int lwip_setsockopt (int s, int level, int optname, const void *optval, socklen_
switch( optname ) { switch( optname ) {
case TCP_NODELAY: case TCP_NODELAY:
case TCP_KEEPALIVE: case TCP_KEEPALIVE:
#if LWIP_TCP_KEEPALIVE
case TCP_KEEPIDLE:
case TCP_KEEPINTVL:
case TCP_KEEPCNT:
#endif /* LWIP_TCP_KEEPALIVE */
break; break;
default: default:
@ -1334,9 +1360,25 @@ int lwip_setsockopt (int s, int level, int optname, const void *optval, socklen_
LWIP_DEBUGF(SOCKETS_DEBUG, ("lwip_setsockopt(%d, IPPROTO_TCP, TCP_NODELAY) -> %s\n", s, (*(int *)optval)?"on":"off") ); LWIP_DEBUGF(SOCKETS_DEBUG, ("lwip_setsockopt(%d, IPPROTO_TCP, TCP_NODELAY) -> %s\n", s, (*(int *)optval)?"on":"off") );
break; break;
case TCP_KEEPALIVE: case TCP_KEEPALIVE:
sock->conn->pcb.tcp->keepalive = (u32_t)(*(int*)optval); sock->conn->pcb.tcp->keep_idle = (u32_t)(*(int*)optval);
LWIP_DEBUGF(SOCKETS_DEBUG, ("lwip_setsockopt(%d, IPPROTO_TCP, TCP_KEEPALIVE) -> %lu\n", s, sock->conn->pcb.tcp->keepalive)); LWIP_DEBUGF(SOCKETS_DEBUG, ("lwip_setsockopt(%d, IPPROTO_TCP, TCP_KEEPALIVE) -> %lu\n", s, sock->conn->pcb.tcp->keep_idle));
break; break;
#if LWIP_TCP_KEEPALIVE
case TCP_KEEPIDLE:
sock->conn->pcb.tcp->keep_idle = 1000*(u32_t)(*(int*)optval);
LWIP_DEBUGF(SOCKETS_DEBUG, ("lwip_setsockopt(%d, IPPROTO_TCP, TCP_KEEPIDLE) -> %lu\n", s, sock->conn->pcb.tcp->keep_idle));
break;
case TCP_KEEPINTVL:
sock->conn->pcb.tcp->keep_intvl = 1000*(u32_t)(*(int*)optval);
LWIP_DEBUGF(SOCKETS_DEBUG, ("lwip_setsockopt(%d, IPPROTO_TCP, TCP_KEEPINTVL) -> %lu\n", s, sock->conn->pcb.tcp->keep_intvl));
break;
case TCP_KEEPCNT:
sock->conn->pcb.tcp->keep_cnt = (u32_t)(*(int*)optval);
LWIP_DEBUGF(SOCKETS_DEBUG, ("lwip_setsockopt(%d, IPPROTO_TCP, TCP_KEEPCNT) -> %lu\n", s, sock->conn->pcb.tcp->keep_cnt));
break;
#endif /* LWIP_TCP_KEEPALIVE */
} /* switch */ } /* switch */
break; break;
} /* switch */ } /* switch */

View File

@ -537,16 +537,24 @@ tcp_slowtmr(void)
/* Check if KEEPALIVE should be sent */ /* Check if KEEPALIVE should be sent */
if((pcb->so_options & SOF_KEEPALIVE) && ((pcb->state == ESTABLISHED) || (pcb->state == CLOSE_WAIT))) { if((pcb->so_options & SOF_KEEPALIVE) && ((pcb->state == ESTABLISHED) || (pcb->state == CLOSE_WAIT))) {
if((u32_t)(tcp_ticks - pcb->tmr) > (pcb->keepalive + TCP_MAXIDLE) / TCP_SLOW_INTERVAL) { #if LWIP_TCP_KEEPALIVE
if((u32_t)(tcp_ticks - pcb->tmr) > (pcb->keep_idle + (pcb->keep_cnt*pcb->keep_intvl)) / TCP_SLOW_INTERVAL) {
#else
if((u32_t)(tcp_ticks - pcb->tmr) > (pcb->keep_idle + TCP_MAXIDLE ) / TCP_SLOW_INTERVAL) {
#endif /* LWIP_TCP_KEEPALIVE */
LWIP_DEBUGF(TCP_DEBUG, ("tcp_slowtmr: KEEPALIVE timeout. Aborting connection to %"U16_F".%"U16_F".%"U16_F".%"U16_F".\n", LWIP_DEBUGF(TCP_DEBUG, ("tcp_slowtmr: KEEPALIVE timeout. Aborting connection to %"U16_F".%"U16_F".%"U16_F".%"U16_F".\n",
ip4_addr1(&pcb->remote_ip), ip4_addr2(&pcb->remote_ip), ip4_addr1(&pcb->remote_ip), ip4_addr2(&pcb->remote_ip),
ip4_addr3(&pcb->remote_ip), ip4_addr4(&pcb->remote_ip))); ip4_addr3(&pcb->remote_ip), ip4_addr4(&pcb->remote_ip)));
tcp_abort(pcb); tcp_abort(pcb);
} }
else if((u32_t)(tcp_ticks - pcb->tmr) > (pcb->keepalive + pcb->keep_cnt * TCP_KEEPINTVL) / TCP_SLOW_INTERVAL) { #if LWIP_TCP_KEEPALIVE
else if((u32_t)(tcp_ticks - pcb->tmr) > (pcb->keep_idle + pcb->keep_cnt_sent * pcb->keep_intvl) / TCP_SLOW_INTERVAL) {
#else
else if((u32_t)(tcp_ticks - pcb->tmr) > (pcb->keep_idle + pcb->keep_cnt_sent * TCP_KEEPINTVL_DEFAULT) / TCP_SLOW_INTERVAL) {
#endif /* LWIP_TCP_KEEPALIVE */
tcp_keepalive(pcb); tcp_keepalive(pcb);
pcb->keep_cnt++; pcb->keep_cnt_sent++;
} }
} }
@ -853,8 +861,14 @@ tcp_alloc(u8_t prio)
#endif /* LWIP_CALLBACK_API */ #endif /* LWIP_CALLBACK_API */
/* Init KEEPALIVE timer */ /* Init KEEPALIVE timer */
pcb->keepalive = TCP_KEEPDEFAULT; pcb->keep_idle = TCP_KEEPIDLE_DEFAULT;
pcb->keep_cnt = 0;
#if LWIP_TCP_KEEPALIVE
pcb->keep_intvl = TCP_KEEPINTVL_DEFAULT;
pcb->keep_cnt = TCP_KEEPCNT_DEFAULT;
#endif /* LWIP_TCP_KEEPALIVE */
pcb->keep_cnt_sent = 0;
} }
return pcb; return pcb;
} }

View File

@ -476,7 +476,7 @@ tcp_process(struct tcp_pcb *pcb)
/* Update the PCB (in)activity timer. */ /* Update the PCB (in)activity timer. */
pcb->tmr = tcp_ticks; pcb->tmr = tcp_ticks;
pcb->keep_cnt = 0; pcb->keep_cnt_sent = 0;
/* Do different things depending on the TCP state. */ /* Do different things depending on the TCP state. */
switch (pcb->state) { switch (pcb->state) {
@ -825,7 +825,7 @@ tcp_receive(struct tcp_pcb *pcb)
pcb->sv += m; pcb->sv += m;
pcb->rto = (pcb->sa >> 3) + pcb->sv; pcb->rto = (pcb->sa >> 3) + pcb->sv;
LWIP_DEBUGF(TCP_RTO_DEBUG, ("tcp_receive: RTO %"U16_F" (%"U16_F" miliseconds)\n", LWIP_DEBUGF(TCP_RTO_DEBUG, ("tcp_receive: RTO %"U16_F" (%"U16_F" milliseconds)\n",
pcb->rto, pcb->rto * TCP_SLOW_INTERVAL)); pcb->rto, pcb->rto * TCP_SLOW_INTERVAL));
pcb->rttest = 0; pcb->rttest = 0;

View File

@ -683,7 +683,7 @@ tcp_keepalive(struct tcp_pcb *pcb)
ip4_addr1(&pcb->remote_ip), ip4_addr2(&pcb->remote_ip), ip4_addr1(&pcb->remote_ip), ip4_addr2(&pcb->remote_ip),
ip4_addr3(&pcb->remote_ip), ip4_addr4(&pcb->remote_ip))); ip4_addr3(&pcb->remote_ip), ip4_addr4(&pcb->remote_ip)));
LWIP_DEBUGF(TCP_DEBUG, ("tcp_keepalive: tcp_ticks %"U32_F" pcb->tmr %"U32_F" pcb->keep_cnt %"U16_F"\n", tcp_ticks, pcb->tmr, pcb->keep_cnt)); LWIP_DEBUGF(TCP_DEBUG, ("tcp_keepalive: tcp_ticks %"U32_F" pcb->tmr %"U32_F" pcb->keep_cnt_sent %"U16_F"\n", tcp_ticks, pcb->tmr, pcb->keep_cnt_sent));
p = pbuf_alloc(PBUF_IP, TCP_HLEN, PBUF_RAM); p = pbuf_alloc(PBUF_IP, TCP_HLEN, PBUF_RAM);

View File

@ -420,6 +420,12 @@ a lot of data that needs to be copied, this should be set high. */
#define LWIP_POSIX_SOCKETS_IO_NAMES 1 #define LWIP_POSIX_SOCKETS_IO_NAMES 1
#endif #endif
/* Enable TCP_KEEPIDLE, TCP_KEEPINTVL and TCP_KEEPCNT options processing.
Note that TCP_KEEPIDLE and TCP_KEEPINTVL have to be set in seconds. */
#ifndef LWIP_TCP_KEEPALIVE
#define LWIP_TCP_KEEPALIVE 0
#endif
/* Enable SO_RCVTIMEO processing (only for UDP sockets) */ /* Enable SO_RCVTIMEO processing (only for UDP sockets) */
#ifndef LWIP_SO_RCVTIMEO #ifndef LWIP_SO_RCVTIMEO
#define LWIP_SO_RCVTIMEO 0 #define LWIP_SO_RCVTIMEO 0

View File

@ -155,22 +155,26 @@ void tcp_rexmit_rto (struct tcp_pcb *pcb);
* User-settable options (used with setsockopt). * User-settable options (used with setsockopt).
*/ */
#define TCP_NODELAY 0x01 /* don't delay send to coalesce packets */ #define TCP_NODELAY 0x01 /* don't delay send to coalesce packets */
#define TCP_KEEPALIVE 0x02 /* send KEEPALIVE probes when idle for pcb->keepalive miliseconds */ #define TCP_KEEPALIVE 0x02 /* send KEEPALIVE probes when idle for pcb->keep_idle milliseconds */
#define TCP_KEEPIDLE 0x03 /* set pcb->keep_idle - Same as TCP_KEEPALIVE, but use seconds for get/setsockopt*/
#define TCP_KEEPINTVL 0x04 /* set pcb->keep_intvl - Use seconds for get/setsockopt */
#define TCP_KEEPCNT 0x05 /* set pcb->keep_cnt - Use number of probes sent for get/setsockopt */
/* Keepalive values, compliant with RFC 1122. Don't change this unless you know what you're doing */ /* Keepalive values, compliant with RFC 1122. Don't change this unless you know what you're doing */
#ifndef TCP_KEEPDEFAULT #ifndef TCP_KEEPIDLE_DEFAULT
#define TCP_KEEPDEFAULT 7200000 /* KEEPALIVE timer in miliseconds */ #define TCP_KEEPIDLE_DEFAULT 7200000 /* Default KEEPALIVE timer in milliseconds */
#endif #endif
#ifndef TCP_KEEPINTVL #ifndef TCP_KEEPINTVL_DEFAULT
#define TCP_KEEPINTVL 75000 /* Time between KEEPALIVE probes in miliseconds */ #define TCP_KEEPINTVL_DEFAULT 75000 /* Default Time between KEEPALIVE probes in milliseconds */
#endif #endif
#ifndef TCP_KEEPCNT #ifndef TCP_KEEPCNT_DEFAULT
#define TCP_KEEPCNT 9 /* Counter for KEEPALIVE probes */ #define TCP_KEEPCNT_DEFAULT 9 /* Default Counter for KEEPALIVE probes */
#endif #endif
#define TCP_MAXIDLE TCP_KEEPCNT * TCP_KEEPINTVL /* Maximum KEEPALIVE probe time */ #define TCP_MAXIDLE TCP_KEEPCNT_DEFAULT * TCP_KEEPINTVL_DEFAULT /* Maximum KEEPALIVE probe time */
#ifdef PACK_STRUCT_USE_INCLUDES #ifdef PACK_STRUCT_USE_INCLUDES
# include "arch/bpstruct.h" # include "arch/bpstruct.h"
@ -311,10 +315,14 @@ struct tcp_pcb {
#endif /* LWIP_CALLBACK_API */ #endif /* LWIP_CALLBACK_API */
/* idle time before KEEPALIVE is sent */ /* idle time before KEEPALIVE is sent */
u32_t keepalive; u32_t keep_idle;
#if LWIP_TCP_KEEPALIVE
u32_t keep_intvl;
u32_t keep_cnt;
#endif /* LWIP_TCP_KEEPALIVE */
/* KEEPALIVE counter */ /* KEEPALIVE counter */
u8_t keep_cnt; u8_t keep_cnt_sent;
}; };
struct tcp_pcb_listen { struct tcp_pcb_listen {