]> git.karo-electronics.de Git - karo-tx-linux.git/blobdiff - net/ipv4/tcp_minisocks.c
tcp: Move timestamps from inetpeer to metrics cache.
[karo-tx-linux.git] / net / ipv4 / tcp_minisocks.c
index b85d9fe7d663081e8eba778285521d824f21a317..a51aa534dab127f0500158ab5c08891cf44f17cb 100644 (file)
@@ -49,56 +49,6 @@ struct inet_timewait_death_row tcp_death_row = {
 };
 EXPORT_SYMBOL_GPL(tcp_death_row);
 
-/* VJ's idea. Save last timestamp seen from this destination
- * and hold it at least for normal timewait interval to use for duplicate
- * segment detection in subsequent connections, before they enter synchronized
- * state.
- */
-
-static bool tcp_remember_stamp(struct sock *sk)
-{
-       const struct inet_connection_sock *icsk = inet_csk(sk);
-       struct tcp_sock *tp = tcp_sk(sk);
-       struct inet_peer *peer;
-       bool release_it;
-
-       peer = icsk->icsk_af_ops->get_peer(sk, &release_it);
-       if (peer) {
-               if ((s32)(peer->tcp_ts - tp->rx_opt.ts_recent) <= 0 ||
-                   ((u32)get_seconds() - peer->tcp_ts_stamp > TCP_PAWS_MSL &&
-                    peer->tcp_ts_stamp <= (u32)tp->rx_opt.ts_recent_stamp)) {
-                       peer->tcp_ts_stamp = (u32)tp->rx_opt.ts_recent_stamp;
-                       peer->tcp_ts = tp->rx_opt.ts_recent;
-               }
-               if (release_it)
-                       inet_putpeer(peer);
-               return true;
-       }
-
-       return false;
-}
-
-static bool tcp_tw_remember_stamp(struct inet_timewait_sock *tw)
-{
-       struct sock *sk = (struct sock *) tw;
-       struct inet_peer *peer;
-
-       peer = twsk_getpeer(sk);
-       if (peer) {
-               const struct tcp_timewait_sock *tcptw = tcp_twsk(sk);
-
-               if ((s32)(peer->tcp_ts - tcptw->tw_ts_recent) <= 0 ||
-                   ((u32)get_seconds() - peer->tcp_ts_stamp > TCP_PAWS_MSL &&
-                    peer->tcp_ts_stamp <= (u32)tcptw->tw_ts_recent_stamp)) {
-                       peer->tcp_ts_stamp = (u32)tcptw->tw_ts_recent_stamp;
-                       peer->tcp_ts       = tcptw->tw_ts_recent;
-               }
-               inet_putpeer(peer);
-               return true;
-       }
-       return false;
-}
-
 static bool tcp_in_window(u32 seq, u32 end_seq, u32 s_win, u32 e_win)
 {
        if (seq == s_win)
@@ -317,9 +267,12 @@ void tcp_time_wait(struct sock *sk, int state, int timeo)
        const struct inet_connection_sock *icsk = inet_csk(sk);
        const struct tcp_sock *tp = tcp_sk(sk);
        bool recycle_ok = false;
+       bool recycle_on = false;
 
-       if (tcp_death_row.sysctl_tw_recycle && tp->rx_opt.ts_recent_stamp)
+       if (tcp_death_row.sysctl_tw_recycle && tp->rx_opt.ts_recent_stamp) {
                recycle_ok = tcp_remember_stamp(sk);
+               recycle_on = true;
+       }
 
        if (tcp_death_row.tw_count < tcp_death_row.sysctl_max_tw_buckets)
                tw = inet_twsk_alloc(sk, state);
@@ -327,8 +280,10 @@ void tcp_time_wait(struct sock *sk, int state, int timeo)
        if (tw != NULL) {
                struct tcp_timewait_sock *tcptw = tcp_twsk((struct sock *)tw);
                const int rto = (icsk->icsk_rto << 2) - (icsk->icsk_rto >> 1);
+               struct inet_sock *inet = inet_sk(sk);
+               struct inet_peer *peer = NULL;
 
-               tw->tw_transparent      = inet_sk(sk)->transparent;
+               tw->tw_transparent      = inet->transparent;
                tw->tw_rcv_wscale       = tp->rx_opt.rcv_wscale;
                tcptw->tw_rcv_nxt       = tp->rcv_nxt;
                tcptw->tw_snd_nxt       = tp->snd_nxt;
@@ -350,6 +305,12 @@ void tcp_time_wait(struct sock *sk, int state, int timeo)
                }
 #endif
 
+               if (recycle_on)
+                       peer = icsk->icsk_af_ops->get_peer(sk);
+               tcptw->tw_peer = peer;
+               if (peer)
+                       atomic_inc(&peer->refcnt);
+
 #ifdef CONFIG_TCP_MD5SIG
                /*
                 * The timewait bucket does not have the key DB from the
@@ -401,8 +362,11 @@ void tcp_time_wait(struct sock *sk, int state, int timeo)
 
 void tcp_twsk_destructor(struct sock *sk)
 {
-#ifdef CONFIG_TCP_MD5SIG
        struct tcp_timewait_sock *twsk = tcp_twsk(sk);
+
+       if (twsk->tw_peer)
+               inet_putpeer(twsk->tw_peer);
+#ifdef CONFIG_TCP_MD5SIG
        if (twsk->tw_md5_key) {
                tcp_free_md5sig_pool();
                kfree_rcu(twsk->tw_md5_key, rcu);
@@ -435,6 +399,8 @@ struct sock *tcp_create_openreq_child(struct sock *sk, struct request_sock *req,
                struct tcp_sock *oldtp = tcp_sk(sk);
                struct tcp_cookie_values *oldcvp = oldtp->cookie_values;
 
+               newsk->sk_rx_dst = dst_clone(skb_dst(skb));
+
                /* TCP Cookie Transactions require space for the cookie pair,
                 * as it differs for each connection.  There is no need to
                 * copy any s_data_payload stored at the original socket.