tcp: Stalling connections: Fix timeout calculation routine
[safe/jmp/linux-2.6] / include / net / tcp.h
index 738b65f..e54bd85 100644 (file)
@@ -30,6 +30,7 @@
 #include <linux/dmaengine.h>
 #include <linux/crypto.h>
 #include <linux/cryptohash.h>
+#include <linux/kref.h>
 
 #include <net/inet_connection_sock.h>
 #include <net/inet_timewait_sock.h>
@@ -164,6 +165,7 @@ extern void tcp_time_wait(struct sock *sk, int state, int timeo);
 #define TCPOPT_SACK             5       /* SACK Block */
 #define TCPOPT_TIMESTAMP       8       /* Better RTT estimations/PAWS */
 #define TCPOPT_MD5SIG          19      /* MD5 Signature (RFC2385) */
+#define TCPOPT_COOKIE          253     /* Cookie extension (experimental) */
 
 /*
  *     TCP option lengths
@@ -174,6 +176,10 @@ extern void tcp_time_wait(struct sock *sk, int state, int timeo);
 #define TCPOLEN_SACK_PERM      2
 #define TCPOLEN_TIMESTAMP      10
 #define TCPOLEN_MD5SIG         18
+#define TCPOLEN_COOKIE_BASE    2       /* Cookie-less header extension */
+#define TCPOLEN_COOKIE_PAIR    3       /* Cookie pair header extension */
+#define TCPOLEN_COOKIE_MIN     (TCPOLEN_COOKIE_BASE+TCP_COOKIE_MIN)
+#define TCPOLEN_COOKIE_MAX     (TCPOLEN_COOKIE_BASE+TCP_COOKIE_MAX)
 
 /* But this is what stacks really send out. */
 #define TCPOLEN_TSTAMP_ALIGNED         12
@@ -401,6 +407,7 @@ extern int                  tcp_recvmsg(struct kiocb *iocb, struct sock *sk,
 
 extern void                    tcp_parse_options(struct sk_buff *skb,
                                                  struct tcp_options_received *opt_rx,
+                                                 u8 **hvpp,
                                                  int estab,
                                                  struct dst_entry *dst);
 
@@ -1222,6 +1229,7 @@ static inline void tcp_write_queue_purge(struct sock *sk)
        while ((skb = __skb_dequeue(&sk->sk_write_queue)) != NULL)
                sk_wmem_free_skb(sk, skb);
        sk_mem_reclaim(sk);
+       tcp_clear_all_retrans_hints(tcp_sk(sk));
 }
 
 static inline struct sk_buff *tcp_write_queue_head(struct sock *sk)
@@ -1257,14 +1265,20 @@ static inline struct sk_buff *tcp_write_queue_prev(struct sock *sk, struct sk_bu
  * TCP connection after "boundary" unsucessful, exponentially backed-off
  * retransmissions with an initial RTO of TCP_RTO_MIN.
  */
-static inline bool retransmits_timed_out(const struct sock *sk,
+static inline bool retransmits_timed_out(struct sock *sk,
                                         unsigned int boundary)
 {
        unsigned int timeout, linear_backoff_thresh;
+       unsigned int start_ts;
 
        if (!inet_csk(sk)->icsk_retransmits)
                return false;
 
+       if (unlikely(!tcp_sk(sk)->retrans_stamp))
+               start_ts = TCP_SKB_CB(tcp_write_queue_head(sk))->when;
+       else
+               start_ts = tcp_sk(sk)->retrans_stamp;
+
        linear_backoff_thresh = ilog2(TCP_RTO_MAX/TCP_RTO_MIN);
 
        if (boundary <= linear_backoff_thresh)
@@ -1273,7 +1287,7 @@ static inline bool retransmits_timed_out(const struct sock *sk,
                timeout = ((2 << linear_backoff_thresh) - 1) * TCP_RTO_MIN +
                          (boundary - linear_backoff_thresh) * TCP_RTO_MAX;
 
-       return (tcp_time_stamp - tcp_sk(sk)->retrans_stamp) >= timeout;
+       return (tcp_time_stamp - start_ts) >= timeout;
 }
 
 static inline struct sk_buff *tcp_send_head(struct sock *sk)
@@ -1482,6 +1496,83 @@ struct tcp_request_sock_ops {
 
 extern int tcp_cookie_generator(u32 *bakery);
 
+/**
+ *     struct tcp_cookie_values - each socket needs extra space for the
+ *     cookies, together with (optional) space for any SYN data.
+ *
+ *     A tcp_sock contains a pointer to the current value, and this is
+ *     cloned to the tcp_timewait_sock.
+ *
+ * @cookie_pair:       variable data from the option exchange.
+ *
+ * @cookie_desired:    user specified tcpct_cookie_desired.  Zero
+ *                     indicates default (sysctl_tcp_cookie_size).
+ *                     After cookie sent, remembers size of cookie.
+ *                     Range 0, TCP_COOKIE_MIN to TCP_COOKIE_MAX.
+ *
+ * @s_data_desired:    user specified tcpct_s_data_desired.  When the
+ *                     constant payload is specified (@s_data_constant),
+ *                     holds its length instead.
+ *                     Range 0 to TCP_MSS_DESIRED.
+ *
+ * @s_data_payload:    constant data that is to be included in the
+ *                     payload of SYN or SYNACK segments when the
+ *                     cookie option is present.
+ */
+struct tcp_cookie_values {
+       struct kref     kref;
+       u8              cookie_pair[TCP_COOKIE_PAIR_SIZE];
+       u8              cookie_pair_size;
+       u8              cookie_desired;
+       u16             s_data_desired:11,
+                       s_data_constant:1,
+                       s_data_in:1,
+                       s_data_out:1,
+                       s_data_unused:2;
+       u8              s_data_payload[0];
+};
+
+static inline void tcp_cookie_values_release(struct kref *kref)
+{
+       kfree(container_of(kref, struct tcp_cookie_values, kref));
+}
+
+/* The length of constant payload data.  Note that s_data_desired is
+ * overloaded, depending on s_data_constant: either the length of constant
+ * data (returned here) or the limit on variable data.
+ */
+static inline int tcp_s_data_size(const struct tcp_sock *tp)
+{
+       return (tp->cookie_values != NULL && tp->cookie_values->s_data_constant)
+               ? tp->cookie_values->s_data_desired
+               : 0;
+}
+
+/**
+ *     struct tcp_extend_values - tcp_ipv?.c to tcp_output.c workspace.
+ *
+ *     As tcp_request_sock has already been extended in other places, the
+ *     only remaining method is to pass stack values along as function
+ *     parameters.  These parameters are not needed after sending SYNACK.
+ *
+ * @cookie_bakery:     cryptographic secret and message workspace.
+ *
+ * @cookie_plus:       bytes in authenticator/cookie option, copied from
+ *                     struct tcp_options_received (above).
+ */
+struct tcp_extend_values {
+       struct request_values           rv;
+       u32                             cookie_bakery[COOKIE_WORKSPACE_WORDS];
+       u8                              cookie_plus:6,
+                                       cookie_out_never:1,
+                                       cookie_in_always:1;
+};
+
+static inline struct tcp_extend_values *tcp_xv(struct request_values *rvp)
+{
+       return (struct tcp_extend_values *)rvp;
+}
+
 extern void tcp_v4_init(void);
 extern void tcp_init(void);