From 5c65d4733b999b10a18e7e3862381eda6b9c1113 Mon Sep 17 00:00:00 2001 From: fbernon Date: Sun, 11 Mar 2007 15:53:43 +0000 Subject: [PATCH] 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 --- CHANGELOG | 6 ++++++ src/api/sockets.c | 48 +++++++++++++++++++++++++++++++++++++++--- src/core/tcp.c | 24 ++++++++++++++++----- src/core/tcp_in.c | 4 ++-- src/core/tcp_out.c | 2 +- src/include/lwip/opt.h | 6 ++++++ src/include/lwip/tcp.h | 28 +++++++++++++++--------- 7 files changed, 97 insertions(+), 21 deletions(-) diff --git a/CHANGELOG b/CHANGELOG index fcf35cc1..51edc167 100644 --- a/CHANGELOG +++ b/CHANGELOG @@ -22,6 +22,12 @@ HISTORY * [Enter new changes just after this line - do not remove this line] ++ 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 * tcp.h: Keepalive values can be configured at compile time, but don't change diff --git a/src/api/sockets.c b/src/api/sockets.c index aaa8c762..9df7870d 100644 --- a/src/api/sockets.c +++ b/src/api/sockets.c @@ -1055,6 +1055,11 @@ int lwip_getsockopt (int s, int level, int optname, void *optval, socklen_t *opt switch( optname ) { case TCP_NODELAY: case TCP_KEEPALIVE: +#if LWIP_TCP_KEEPALIVE + case TCP_KEEPIDLE: + case TCP_KEEPINTVL: + case TCP_KEEPCNT: +#endif /* LWIP_TCP_KEEPALIVE */ break; 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") ); break; 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)); 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 */ break; } @@ -1252,6 +1273,11 @@ int lwip_setsockopt (int s, int level, int optname, const void *optval, socklen_ switch( optname ) { case TCP_NODELAY: case TCP_KEEPALIVE: +#if LWIP_TCP_KEEPALIVE + case TCP_KEEPIDLE: + case TCP_KEEPINTVL: + case TCP_KEEPCNT: +#endif /* LWIP_TCP_KEEPALIVE */ break; 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") ); break; case TCP_KEEPALIVE: - sock->conn->pcb.tcp->keepalive = (u32_t)(*(int*)optval); - LWIP_DEBUGF(SOCKETS_DEBUG, ("lwip_setsockopt(%d, IPPROTO_TCP, TCP_KEEPALIVE) -> %lu\n", s, sock->conn->pcb.tcp->keepalive)); + 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->keep_idle)); 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 */ break; } /* switch */ diff --git a/src/core/tcp.c b/src/core/tcp.c index 89dfd241..567d03cc 100644 --- a/src/core/tcp.c +++ b/src/core/tcp.c @@ -537,16 +537,24 @@ tcp_slowtmr(void) /* Check if KEEPALIVE should be sent */ 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", ip4_addr1(&pcb->remote_ip), ip4_addr2(&pcb->remote_ip), ip4_addr3(&pcb->remote_ip), ip4_addr4(&pcb->remote_ip))); 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); - pcb->keep_cnt++; + pcb->keep_cnt_sent++; } } @@ -853,8 +861,14 @@ tcp_alloc(u8_t prio) #endif /* LWIP_CALLBACK_API */ /* Init KEEPALIVE timer */ - pcb->keepalive = TCP_KEEPDEFAULT; - pcb->keep_cnt = 0; + pcb->keep_idle = TCP_KEEPIDLE_DEFAULT; + +#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; } diff --git a/src/core/tcp_in.c b/src/core/tcp_in.c index f6a3b870..a35e3895 100644 --- a/src/core/tcp_in.c +++ b/src/core/tcp_in.c @@ -476,7 +476,7 @@ tcp_process(struct tcp_pcb *pcb) /* Update the PCB (in)activity timer. */ pcb->tmr = tcp_ticks; - pcb->keep_cnt = 0; + pcb->keep_cnt_sent = 0; /* Do different things depending on the TCP state. */ switch (pcb->state) { @@ -825,7 +825,7 @@ tcp_receive(struct tcp_pcb *pcb) pcb->sv += m; 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->rttest = 0; diff --git a/src/core/tcp_out.c b/src/core/tcp_out.c index 409110a9..ff5ea242 100644 --- a/src/core/tcp_out.c +++ b/src/core/tcp_out.c @@ -683,7 +683,7 @@ tcp_keepalive(struct tcp_pcb *pcb) ip4_addr1(&pcb->remote_ip), ip4_addr2(&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); diff --git a/src/include/lwip/opt.h b/src/include/lwip/opt.h index 0e1839ba..269434c1 100644 --- a/src/include/lwip/opt.h +++ b/src/include/lwip/opt.h @@ -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 #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) */ #ifndef LWIP_SO_RCVTIMEO #define LWIP_SO_RCVTIMEO 0 diff --git a/src/include/lwip/tcp.h b/src/include/lwip/tcp.h index c1ecb49e..4c9227ec 100644 --- a/src/include/lwip/tcp.h +++ b/src/include/lwip/tcp.h @@ -155,22 +155,26 @@ void tcp_rexmit_rto (struct tcp_pcb *pcb); * User-settable options (used with setsockopt). */ #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 */ -#ifndef TCP_KEEPDEFAULT -#define TCP_KEEPDEFAULT 7200000 /* KEEPALIVE timer in miliseconds */ +#ifndef TCP_KEEPIDLE_DEFAULT +#define TCP_KEEPIDLE_DEFAULT 7200000 /* Default KEEPALIVE timer in milliseconds */ #endif -#ifndef TCP_KEEPINTVL -#define TCP_KEEPINTVL 75000 /* Time between KEEPALIVE probes in miliseconds */ +#ifndef TCP_KEEPINTVL_DEFAULT +#define TCP_KEEPINTVL_DEFAULT 75000 /* Default Time between KEEPALIVE probes in milliseconds */ #endif -#ifndef TCP_KEEPCNT -#define TCP_KEEPCNT 9 /* Counter for KEEPALIVE probes */ +#ifndef TCP_KEEPCNT_DEFAULT +#define TCP_KEEPCNT_DEFAULT 9 /* Default Counter for KEEPALIVE probes */ #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 # include "arch/bpstruct.h" @@ -311,10 +315,14 @@ struct tcp_pcb { #endif /* LWIP_CALLBACK_API */ /* 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 */ - u8_t keep_cnt; + u8_t keep_cnt_sent; }; struct tcp_pcb_listen {