Hi

Because of the huge changes in 2.3.15 networking
code I am posting new keepalive patch for this kernel.
It behaves the same as the previous one (but is much
simpler) and as before introduces 4 more tcp options.

Furthermore it corrects bug in setting keepalive
timer presented currently in 2.3.15 function
tcp_create_openreq_child.

Unfortunately I did not understand the need for
randomizing the interval between keepalive probes so
I have removed that. I think that sending keepalive
messages are already randomized by the fact that
it is precisely 2 hours after last received TCP segment
and they arrive at random times.

regards
Pavel

Only in linux-2.3.15.orig/drivers/net: sk_mca.h.orig
diff -ru linux-2.3.15.orig/include/linux/socket.h linux-2.3.15/include/linux/socket.h
--- linux-2.3.15.orig/include/linux/socket.h    Thu Aug 26 08:29:39 1999
+++ linux-2.3.15/include/linux/socket.h Thu Aug 26 08:58:00 1999
@@ -252,6 +252,10 @@
 #define TCP_NODELAY    1
 #define TCP_MAXSEG     2
 #define TCP_CORK       3       /* Linux specific (for use with sendfile) */
+#define TCP_KEEPIDLE   4
+#define TCP_KEEPINTVL  5
+#define TCP_KEEPCNT    6
+#define TCP_SYNCNT     7
 
 #ifdef __KERNEL__
 extern int memcpy_fromiovec(unsigned char *kdata, struct iovec *iov, int len);
diff -ru linux-2.3.15.orig/include/linux/sysctl.h linux-2.3.15/include/linux/sysctl.h
--- linux-2.3.15.orig/include/linux/sysctl.h    Thu Aug 26 08:29:40 1999
+++ linux-2.3.15/include/linux/sysctl.h Thu Aug 26 08:59:45 1999
@@ -206,26 +206,27 @@
        NET_IPV4_TCP_MAX_KA_PROBES=44,
        NET_IPV4_TCP_KEEPALIVE_TIME=45,
        NET_IPV4_TCP_KEEPALIVE_PROBES=46,
-       NET_IPV4_TCP_RETRIES1=47,
-       NET_IPV4_TCP_RETRIES2=48,
-       NET_IPV4_TCP_FIN_TIMEOUT=49,
-       NET_IPV4_IP_MASQ_DEBUG=50,
-       NET_TCP_SYNCOOKIES=51,
-       NET_TCP_STDURG=52,
-       NET_TCP_RFC1337=53,
-       NET_TCP_SYN_TAILDROP=54,
-       NET_TCP_MAX_SYN_BACKLOG=55,
-       NET_IPV4_LOCAL_PORT_RANGE=56,
-       NET_IPV4_ICMP_ECHO_IGNORE_ALL=57,
-       NET_IPV4_ICMP_ECHO_IGNORE_BROADCASTS=58,
-       NET_IPV4_ICMP_SOURCEQUENCH_RATE=59,
-       NET_IPV4_ICMP_DESTUNREACH_RATE=60,
-       NET_IPV4_ICMP_TIMEEXCEED_RATE=61,
-       NET_IPV4_ICMP_PARAMPROB_RATE=62,
-       NET_IPV4_ICMP_ECHOREPLY_RATE=63,
-       NET_IPV4_ICMP_IGNORE_BOGUS_ERROR_RESPONSES=64,
-       NET_IPV4_IGMP_MAX_MEMBERSHIPS=65,
-       NET_TCP_TW_RECYCLE=66
+       NET_IPV4_TCP_KEEPALIVE_INTVL=47,
+       NET_IPV4_TCP_RETRIES1=48,
+       NET_IPV4_TCP_RETRIES2=49,
+       NET_IPV4_TCP_FIN_TIMEOUT=50,
+       NET_IPV4_IP_MASQ_DEBUG=51,
+       NET_TCP_SYNCOOKIES=52,
+       NET_TCP_STDURG=53,
+       NET_TCP_RFC1337=54,
+       NET_TCP_SYN_TAILDROP=55,
+       NET_TCP_MAX_SYN_BACKLOG=56,
+       NET_IPV4_LOCAL_PORT_RANGE=57,
+       NET_IPV4_ICMP_ECHO_IGNORE_ALL=58,
+       NET_IPV4_ICMP_ECHO_IGNORE_BROADCASTS=59,
+       NET_IPV4_ICMP_SOURCEQUENCH_RATE=60,
+       NET_IPV4_ICMP_DESTUNREACH_RATE=61,
+       NET_IPV4_ICMP_TIMEEXCEED_RATE=62,
+       NET_IPV4_ICMP_PARAMPROB_RATE=63,
+       NET_IPV4_ICMP_ECHOREPLY_RATE=64,
+       NET_IPV4_ICMP_IGNORE_BOGUS_ERROR_RESPONSES=65,
+       NET_IPV4_IGMP_MAX_MEMBERSHIPS=66,
+       NET_TCP_TW_RECYCLE=67
 };
 
 enum {
diff -ru linux-2.3.15.orig/include/net/sock.h linux-2.3.15/include/net/sock.h
--- linux-2.3.15.orig/include/net/sock.h        Thu Aug 26 08:29:40 1999
+++ linux-2.3.15/include/net/sock.h     Fri Aug 27 16:56:06 1999
@@ -317,6 +317,11 @@
 
        int syn_backlog;        /* Backlog of received SYNs */
        int write_pending;
+       
+       unsigned int            keepalive_time;   /* time before keep alive takes 
+place */
+       unsigned int            keepalive_intvl;  /* time interval between keep alive 
+probes */
+       unsigned char           keepalive_probes; /* num of allowed keep alive probes 
+*/
+       unsigned char           syn_retries;      /* num of allowed syn retries */
 };
 
        
diff -ru linux-2.3.15.orig/include/net/tcp.h linux-2.3.15/include/net/tcp.h
--- linux-2.3.15.orig/include/net/tcp.h Thu Aug 26 08:29:40 1999
+++ linux-2.3.15/include/net/tcp.h      Sat Aug 28 16:23:41 1999
@@ -286,7 +286,12 @@
                                 * there is no window                   */
 #define TCP_KEEPALIVE_TIME (120*60*HZ)         /* two hours */
 #define TCP_KEEPALIVE_PROBES   9               /* Max of 9 keepalive probes    */
-#define TCP_KEEPALIVE_PERIOD ((75*HZ)>>2)      /* period of keepalive check    */
+#define TCP_KEEPALIVE_INTVL    (75*HZ)
+
+#define MAX_TCP_KEEPIDLE       32767
+#define MAX_TCP_KEEPINTVL      32767
+#define MAX_TCP_KEEPCNT                127
+#define MAX_TCP_SYNCNT         127
 
 #define TCP_SYNACK_PERIOD      (HZ/2) /* How often to run the synack slow timer */
 #define TCP_QUICK_TRIES                8  /* How often we try to retransmit, until
@@ -332,6 +337,12 @@
 #define TIME_PROBE0    4
 #define TIME_KEEPOPEN  5
 
+/* sysctl variables for tcp */
+extern int sysctl_tcp_keepalive_time;
+extern int sysctl_tcp_keepalive_probes;
+extern int sysctl_tcp_keepalive_intvl;
+extern int sysctl_tcp_syn_retries;
+
 struct open_request;
 
 struct or_calltable {
@@ -611,7 +622,7 @@
 extern void tcp_send_partial(struct sock *);
 extern void tcp_write_wakeup(struct sock *);
 extern void tcp_send_fin(struct sock *sk);
-extern void tcp_send_active_reset(struct sock *sk);
+extern void tcp_send_active_reset(struct sock *sk, int priority);
 extern int  tcp_send_synack(struct sock *);
 extern void tcp_transmit_skb(struct sock *, struct sk_buff *);
 extern void tcp_send_skb(struct sock *, struct sk_buff *, int force_queue);
@@ -1229,6 +1240,22 @@
 {
        if (atomic_dec_and_test(&tcp_lhash_users))
                wake_up(&tcp_lhash_wait);
+}
+
+static inline int keepalive_intvl_when(struct tcp_opt *tp)
+{
+       if (tp->keepalive_intvl)
+               return tp->keepalive_intvl;
+       else
+               return sysctl_tcp_keepalive_intvl;
+}
+
+static inline int keepalive_time_when(struct tcp_opt *tp)
+{
+       if (tp->keepalive_time)
+               return tp->keepalive_time;
+       else
+               return sysctl_tcp_keepalive_time;
 }
 
 #endif /* _TCP_H */
diff -ru linux-2.3.15.orig/net/ipv4/sysctl_net_ipv4.c 
linux-2.3.15/net/ipv4/sysctl_net_ipv4.c
--- linux-2.3.15.orig/net/ipv4/sysctl_net_ipv4.c        Thu Aug 26 08:29:41 1999
+++ linux-2.3.15/net/ipv4/sysctl_net_ipv4.c     Thu Aug 26 09:09:34 1999
@@ -150,6 +150,9 @@
        {NET_IPV4_TCP_KEEPALIVE_PROBES, "tcp_keepalive_probes",
         &sysctl_tcp_keepalive_probes, sizeof(int), 0644, NULL, 
         &proc_dointvec},
+       {NET_IPV4_TCP_KEEPALIVE_INTVL, "tcp_keepalive_intvl",
+        &sysctl_tcp_keepalive_intvl, sizeof(int), 0644, NULL,
+        &proc_dointvec_jiffies, &sysctl_jiffies},
        {NET_IPV4_TCP_RETRIES1, "tcp_retries1",
         &sysctl_tcp_retries1, sizeof(int), 0644, NULL, &proc_dointvec_minmax, 
         &sysctl_intvec, NULL, NULL, &tcp_retr1_max},
diff -ru linux-2.3.15.orig/net/ipv4/tcp.c linux-2.3.15/net/ipv4/tcp.c
--- linux-2.3.15.orig/net/ipv4/tcp.c    Thu Aug 26 08:29:41 1999
+++ linux-2.3.15/net/ipv4/tcp.c Fri Aug 27 14:53:15 1999
@@ -1580,7 +1580,7 @@
        if(data_was_unread != 0) {
                /* Unread data was tossed, zap the connection. */
                tcp_set_state(sk, TCP_CLOSE);
-               tcp_send_active_reset(sk);
+               tcp_send_active_reset(sk, GFP_KERNEL);
        } else if (tcp_close_state(sk,1)) {
                /* We FIN if the application ate all the data before
                 * zapping the connection.
@@ -1658,7 +1658,7 @@
        if (old_state == TCP_LISTEN) {
                tcp_close_pending(sk);
        } else if (tcp_connected(old_state)) {
-               tcp_send_active_reset(sk);
+               tcp_send_active_reset(sk, GFP_KERNEL);
                sk->err = ECONNRESET;
        } else if (old_state == TCP_SYN_SENT)
                sk->err = ECONNRESET;
@@ -1870,6 +1870,40 @@
                        tcp_push_pending_frames(sk, tp);
                }
                break;
+               
+       case TCP_KEEPIDLE:
+               if (val < 1 || val > MAX_TCP_KEEPIDLE)
+                       err = -EINVAL;
+               else {
+                       tp->keepalive_time = val * HZ;
+                       if (sk->keepopen) {
+                               __u32 elapsed = tcp_time_stamp - tp->rcv_tstamp;
+                               if (tp->keepalive_time > elapsed)
+                                       elapsed = tp->keepalive_time - elapsed;
+                               else
+                                       elapsed = 0;
+                               tcp_reset_keepalive_timer(sk, elapsed);
+                       }
+               }
+               break;
+       case TCP_KEEPINTVL:
+               if (val < 1 || val > MAX_TCP_KEEPINTVL)
+                       err = -EINVAL;
+               else
+                       tp->keepalive_intvl = val * HZ;
+               break;
+       case TCP_KEEPCNT:
+               if (val < 1 || val > MAX_TCP_KEEPCNT)
+                       err = -EINVAL;
+               else
+                       tp->keepalive_probes = val;
+               break;
+       case TCP_SYNCNT:
+               if (val < 1 || val > MAX_TCP_SYNCNT)
+                       err = -EINVAL;
+               else
+                       tp->syn_retries = val;
+               break;
 
        default:
                err = -ENOPROTOOPT;
@@ -1903,6 +1937,30 @@
                break;
        case TCP_CORK:
                val = (sk->nonagle == 2);
+               break;
+       case TCP_KEEPIDLE:
+               if (tp->keepalive_time)
+                       val = tp->keepalive_time / HZ;
+               else
+                       val = sysctl_tcp_keepalive_time / HZ;
+               break;
+       case TCP_KEEPINTVL:
+               if (tp->keepalive_intvl)
+                       val = tp->keepalive_intvl / HZ;
+               else
+                       val = sysctl_tcp_keepalive_intvl / HZ;
+               break;
+       case TCP_KEEPCNT:
+               if (tp->keepalive_probes)
+                       val = tp->keepalive_probes;
+               else
+                       val = sysctl_tcp_keepalive_probes;
+               break;
+       case TCP_SYNCNT:
+               if (tp->syn_retries)
+                       val = tp->syn_retries;
+               else
+                       val = sysctl_tcp_syn_retries;
                break;
        default:
                return -ENOPROTOOPT;
diff -ru linux-2.3.15.orig/net/ipv4/tcp_input.c linux-2.3.15/net/ipv4/tcp_input.c
--- linux-2.3.15.orig/net/ipv4/tcp_input.c      Thu Aug 26 08:29:41 1999
+++ linux-2.3.15/net/ipv4/tcp_input.c   Sat Aug 28 16:22:28 1999
@@ -1779,7 +1779,7 @@
 
         if (skb->len == 0 && !th->fin)
                return(0);
-
+       
        /* 
         *      If our receive queue has grown past its limits shrink it.
         *      Make sure to do this before moving snd_nxt, otherwise
@@ -2423,7 +2423,7 @@
                newsk->timer.function = &tcp_keepalive_timer;
                newsk->timer.data = (unsigned long) newsk;
                if (newsk->keepopen)
-                       tcp_reset_keepalive_timer(sk, sysctl_tcp_keepalive_time);
+                       tcp_reset_keepalive_timer(newsk, keepalive_time_when(newtp));
                newsk->socket = NULL;
                newsk->sleep = NULL;
 
diff -ru linux-2.3.15.orig/net/ipv4/tcp_output.c linux-2.3.15/net/ipv4/tcp_output.c
--- linux-2.3.15.orig/net/ipv4/tcp_output.c     Thu Aug 26 08:29:42 1999
+++ linux-2.3.15/net/ipv4/tcp_output.c  Thu Aug 26 09:20:33 1999
@@ -825,13 +825,13 @@
  * was unread data in the receive queue.  This behavior is recommended
  * by draft-ietf-tcpimpl-prob-03.txt section 3.10.  -DaveM
  */
-void tcp_send_active_reset(struct sock *sk)
+void tcp_send_active_reset(struct sock *sk, int priority)
 {
        struct tcp_opt *tp = &(sk->tp_pinfo.af_tcp);
        struct sk_buff *skb;
 
        /* NOTE: No TCP options attached and we never retransmit this. */
-       skb = alloc_skb(MAX_HEADER + sk->prot->max_header, GFP_KERNEL);
+       skb = alloc_skb(MAX_HEADER + sk->prot->max_header, priority);
        if (!skb)
                return;
 
diff -ru linux-2.3.15.orig/net/ipv4/tcp_timer.c linux-2.3.15/net/ipv4/tcp_timer.c
--- linux-2.3.15.orig/net/ipv4/tcp_timer.c      Thu Aug 26 08:29:42 1999
+++ linux-2.3.15/net/ipv4/tcp_timer.c   Fri Aug 27 16:34:18 1999
@@ -25,6 +25,7 @@
 int sysctl_tcp_syn_retries = TCP_SYN_RETRIES; 
 int sysctl_tcp_keepalive_time = TCP_KEEPALIVE_TIME;
 int sysctl_tcp_keepalive_probes = TCP_KEEPALIVE_PROBES;
+int sysctl_tcp_keepalive_intvl = TCP_KEEPALIVE_INTVL;
 int sysctl_tcp_retries1 = TCP_RETR1;
 int sysctl_tcp_retries2 = TCP_RETR2;
 
@@ -183,7 +184,9 @@
        }
        
        /* Have we tried to SYN too many times (repent repent 8)) */
-       if(tp->retransmits > sysctl_tcp_syn_retries && sk->state==TCP_SYN_SENT) {
+       if (sk->state == TCP_SYN_SENT && 
+           ((!tp->syn_retries && tp->retransmits > sysctl_tcp_syn_retries) ||
+             (tp->syn_retries && tp->retransmits > tp->syn_retries))) {
                tcp_write_err(sk, 1);
                /* Don't FIN, we got nothing back */
        } else if (tp->retransmits > sysctl_tcp_retries2) {
@@ -587,7 +590,7 @@
 void tcp_set_keepalive(struct sock *sk, int val)
 {
        if (val && !sk->keepopen)
-               tcp_reset_keepalive_timer(sk, sysctl_tcp_keepalive_time);
+               tcp_reset_keepalive_timer(sk, 
+keepalive_time_when(&sk->tp_pinfo.af_tcp));
        else if (!val)
                tcp_delete_keepalive_timer(sk);
 }
@@ -613,25 +616,29 @@
        if (!sk->keepopen)
                goto out;
 
-       elapsed = sysctl_tcp_keepalive_time;
+       elapsed = keepalive_time_when(tp);
        if (!((1<<sk->state) & (TCPF_ESTABLISHED|TCPF_CLOSE_WAIT|TCPF_FIN_WAIT2)))
                goto resched;
 
        elapsed = tcp_time_stamp - tp->rcv_tstamp;
 
-       if (elapsed >= sysctl_tcp_keepalive_time) {
-               if (tp->probes_out > sysctl_tcp_keepalive_probes) {
+       if (elapsed >= keepalive_time_when(tp)) {
+               if ((!tp->keepalive_probes && tp->probes_out >= 
+sysctl_tcp_keepalive_probes) ||
+                    (tp->keepalive_probes && tp->probes_out >= tp->keepalive_probes)) 
+{
+                       tcp_send_active_reset(sk, GFP_ATOMIC);
                        tcp_write_err(sk, 1);
                        goto out;
                }
                tp->probes_out++;
                tp->pending = TIME_KEEPOPEN;
                tcp_write_wakeup(sk);
-               /* Randomize to avoid synchronization */
-               elapsed = (TCP_KEEPALIVE_PERIOD>>1) + 
(net_random()%TCP_KEEPALIVE_PERIOD);
+               elapsed = keepalive_intvl_when(tp);
        } else {
-               /* It is tp->rcv_tstamp + sysctl_tcp_keepalive_time */
-               elapsed = sysctl_tcp_keepalive_time - elapsed;
+               /* It is tp->rcv_tstamp + keepalive_time_when(tp) */
+               if (keepalive_time_when(tp) > elapsed)
+                       elapsed = keepalive_time_when(tp) - elapsed;
+               else
+                       elapsed = 0;
        }
 
 resched:

Reply via email to