aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--include/net/inet_connection_sock.h2
-rw-r--r--include/net/tcp.h2
-rw-r--r--net/ipv4/tcp_ipv4.c35
-rw-r--r--net/ipv4/tcp_minisocks.c31
-rw-r--r--net/ipv6/tcp_ipv6.c8
5 files changed, 44 insertions, 34 deletions
diff --git a/include/net/inet_connection_sock.h b/include/net/inet_connection_sock.h
index e4f494b42e06..6c93a56cc958 100644
--- a/include/net/inet_connection_sock.h
+++ b/include/net/inet_connection_sock.h
@@ -43,7 +43,7 @@ struct inet_connection_sock_af_ops {
43 struct sock *(*syn_recv_sock)(struct sock *sk, struct sk_buff *skb, 43 struct sock *(*syn_recv_sock)(struct sock *sk, struct sk_buff *skb,
44 struct request_sock *req, 44 struct request_sock *req,
45 struct dst_entry *dst); 45 struct dst_entry *dst);
46 int (*remember_stamp)(struct sock *sk); 46 struct inet_peer *(*get_peer)(struct sock *sk, bool *release_it);
47 u16 net_header_len; 47 u16 net_header_len;
48 u16 sockaddr_len; 48 u16 sockaddr_len;
49 int (*setsockopt)(struct sock *sk, int level, int optname, 49 int (*setsockopt)(struct sock *sk, int level, int optname,
diff --git a/include/net/tcp.h b/include/net/tcp.h
index e36c874c7fb1..3e239641d4ee 100644
--- a/include/net/tcp.h
+++ b/include/net/tcp.h
@@ -312,7 +312,7 @@ extern void tcp_shutdown (struct sock *sk, int how);
312 312
313extern int tcp_v4_rcv(struct sk_buff *skb); 313extern int tcp_v4_rcv(struct sk_buff *skb);
314 314
315extern int tcp_v4_remember_stamp(struct sock *sk); 315extern struct inet_peer *tcp_v4_get_peer(struct sock *sk, bool *release_it);
316extern int tcp_v4_tw_remember_stamp(struct inet_timewait_sock *tw); 316extern int tcp_v4_tw_remember_stamp(struct inet_timewait_sock *tw);
317extern int tcp_sendmsg(struct kiocb *iocb, struct sock *sk, struct msghdr *msg, 317extern int tcp_sendmsg(struct kiocb *iocb, struct sock *sk, struct msghdr *msg,
318 size_t size); 318 size_t size);
diff --git a/net/ipv4/tcp_ipv4.c b/net/ipv4/tcp_ipv4.c
index 00285fcf6788..0ddf819cfb5d 100644
--- a/net/ipv4/tcp_ipv4.c
+++ b/net/ipv4/tcp_ipv4.c
@@ -1763,44 +1763,25 @@ do_time_wait:
1763 goto discard_it; 1763 goto discard_it;
1764} 1764}
1765 1765
1766/* VJ's idea. Save last timestamp seen from this destination 1766struct inet_peer *tcp_v4_get_peer(struct sock *sk, bool *release_it)
1767 * and hold it at least for normal timewait interval to use for duplicate
1768 * segment detection in subsequent connections, before they enter synchronized
1769 * state.
1770 */
1771
1772int tcp_v4_remember_stamp(struct sock *sk)
1773{ 1767{
1768 struct rtable *rt = (struct rtable *) __sk_dst_get(sk);
1774 struct inet_sock *inet = inet_sk(sk); 1769 struct inet_sock *inet = inet_sk(sk);
1775 struct tcp_sock *tp = tcp_sk(sk); 1770 struct inet_peer *peer;
1776 struct rtable *rt = (struct rtable *)__sk_dst_get(sk);
1777 struct inet_peer *peer = NULL;
1778 int release_it = 0;
1779 1771
1780 if (!rt || rt->rt_dst != inet->inet_daddr) { 1772 if (!rt || rt->rt_dst != inet->inet_daddr) {
1781 peer = inet_getpeer_v4(inet->inet_daddr, 1); 1773 peer = inet_getpeer_v4(inet->inet_daddr, 1);
1782 release_it = 1; 1774 *release_it = true;
1783 } else { 1775 } else {
1784 if (!rt->peer) 1776 if (!rt->peer)
1785 rt_bind_peer(rt, 1); 1777 rt_bind_peer(rt, 1);
1786 peer = rt->peer; 1778 peer = rt->peer;
1779 *release_it = false;
1787 } 1780 }
1788 1781
1789 if (peer) { 1782 return peer;
1790 if ((s32)(peer->tcp_ts - tp->rx_opt.ts_recent) <= 0 ||
1791 ((u32)get_seconds() - peer->tcp_ts_stamp > TCP_PAWS_MSL &&
1792 peer->tcp_ts_stamp <= (u32)tp->rx_opt.ts_recent_stamp)) {
1793 peer->tcp_ts_stamp = (u32)tp->rx_opt.ts_recent_stamp;
1794 peer->tcp_ts = tp->rx_opt.ts_recent;
1795 }
1796 if (release_it)
1797 inet_putpeer(peer);
1798 return 1;
1799 }
1800
1801 return 0;
1802} 1783}
1803EXPORT_SYMBOL(tcp_v4_remember_stamp); 1784EXPORT_SYMBOL(tcp_v4_get_peer);
1804 1785
1805int tcp_v4_tw_remember_stamp(struct inet_timewait_sock *tw) 1786int tcp_v4_tw_remember_stamp(struct inet_timewait_sock *tw)
1806{ 1787{
@@ -1828,7 +1809,7 @@ const struct inet_connection_sock_af_ops ipv4_specific = {
1828 .rebuild_header = inet_sk_rebuild_header, 1809 .rebuild_header = inet_sk_rebuild_header,
1829 .conn_request = tcp_v4_conn_request, 1810 .conn_request = tcp_v4_conn_request,
1830 .syn_recv_sock = tcp_v4_syn_recv_sock, 1811 .syn_recv_sock = tcp_v4_syn_recv_sock,
1831 .remember_stamp = tcp_v4_remember_stamp, 1812 .get_peer = tcp_v4_get_peer,
1832 .net_header_len = sizeof(struct iphdr), 1813 .net_header_len = sizeof(struct iphdr),
1833 .setsockopt = ip_setsockopt, 1814 .setsockopt = ip_setsockopt,
1834 .getsockopt = ip_getsockopt, 1815 .getsockopt = ip_getsockopt,
diff --git a/net/ipv4/tcp_minisocks.c b/net/ipv4/tcp_minisocks.c
index 43cf901d7659..059082c873cf 100644
--- a/net/ipv4/tcp_minisocks.c
+++ b/net/ipv4/tcp_minisocks.c
@@ -49,6 +49,35 @@ struct inet_timewait_death_row tcp_death_row = {
49}; 49};
50EXPORT_SYMBOL_GPL(tcp_death_row); 50EXPORT_SYMBOL_GPL(tcp_death_row);
51 51
52/* VJ's idea. Save last timestamp seen from this destination
53 * and hold it at least for normal timewait interval to use for duplicate
54 * segment detection in subsequent connections, before they enter synchronized
55 * state.
56 */
57
58static int tcp_remember_stamp(struct sock *sk)
59{
60 const struct inet_connection_sock *icsk = inet_csk(sk);
61 struct tcp_sock *tp = tcp_sk(sk);
62 struct inet_peer *peer;
63 bool release_it;
64
65 peer = icsk->icsk_af_ops->get_peer(sk, &release_it);
66 if (peer) {
67 if ((s32)(peer->tcp_ts - tp->rx_opt.ts_recent) <= 0 ||
68 ((u32)get_seconds() - peer->tcp_ts_stamp > TCP_PAWS_MSL &&
69 peer->tcp_ts_stamp <= (u32)tp->rx_opt.ts_recent_stamp)) {
70 peer->tcp_ts_stamp = (u32)tp->rx_opt.ts_recent_stamp;
71 peer->tcp_ts = tp->rx_opt.ts_recent;
72 }
73 if (release_it)
74 inet_putpeer(peer);
75 return 1;
76 }
77
78 return 0;
79}
80
52static __inline__ int tcp_in_window(u32 seq, u32 end_seq, u32 s_win, u32 e_win) 81static __inline__ int tcp_in_window(u32 seq, u32 end_seq, u32 s_win, u32 e_win)
53{ 82{
54 if (seq == s_win) 83 if (seq == s_win)
@@ -274,7 +303,7 @@ void tcp_time_wait(struct sock *sk, int state, int timeo)
274 int recycle_ok = 0; 303 int recycle_ok = 0;
275 304
276 if (tcp_death_row.sysctl_tw_recycle && tp->rx_opt.ts_recent_stamp) 305 if (tcp_death_row.sysctl_tw_recycle && tp->rx_opt.ts_recent_stamp)
277 recycle_ok = icsk->icsk_af_ops->remember_stamp(sk); 306 recycle_ok = tcp_remember_stamp(sk);
278 307
279 if (tcp_death_row.tw_count < tcp_death_row.sysctl_max_tw_buckets) 308 if (tcp_death_row.tw_count < tcp_death_row.sysctl_max_tw_buckets)
280 tw = inet_twsk_alloc(sk, state); 309 tw = inet_twsk_alloc(sk, state);
diff --git a/net/ipv6/tcp_ipv6.c b/net/ipv6/tcp_ipv6.c
index 7e41e2cbb85e..e394d0029d8d 100644
--- a/net/ipv6/tcp_ipv6.c
+++ b/net/ipv6/tcp_ipv6.c
@@ -1818,10 +1818,10 @@ do_time_wait:
1818 goto discard_it; 1818 goto discard_it;
1819} 1819}
1820 1820
1821static int tcp_v6_remember_stamp(struct sock *sk) 1821struct inet_peer *tcp_v6_get_peer(struct sock *sk, bool *release_it)
1822{ 1822{
1823 /* Alas, not yet... */ 1823 /* Alas, not yet... */
1824 return 0; 1824 return NULL;
1825} 1825}
1826 1826
1827static const struct inet_connection_sock_af_ops ipv6_specific = { 1827static const struct inet_connection_sock_af_ops ipv6_specific = {
@@ -1830,7 +1830,7 @@ static const struct inet_connection_sock_af_ops ipv6_specific = {
1830 .rebuild_header = inet6_sk_rebuild_header, 1830 .rebuild_header = inet6_sk_rebuild_header,
1831 .conn_request = tcp_v6_conn_request, 1831 .conn_request = tcp_v6_conn_request,
1832 .syn_recv_sock = tcp_v6_syn_recv_sock, 1832 .syn_recv_sock = tcp_v6_syn_recv_sock,
1833 .remember_stamp = tcp_v6_remember_stamp, 1833 .get_peer = tcp_v6_get_peer,
1834 .net_header_len = sizeof(struct ipv6hdr), 1834 .net_header_len = sizeof(struct ipv6hdr),
1835 .setsockopt = ipv6_setsockopt, 1835 .setsockopt = ipv6_setsockopt,
1836 .getsockopt = ipv6_getsockopt, 1836 .getsockopt = ipv6_getsockopt,
@@ -1862,7 +1862,7 @@ static const struct inet_connection_sock_af_ops ipv6_mapped = {
1862 .rebuild_header = inet_sk_rebuild_header, 1862 .rebuild_header = inet_sk_rebuild_header,
1863 .conn_request = tcp_v6_conn_request, 1863 .conn_request = tcp_v6_conn_request,
1864 .syn_recv_sock = tcp_v6_syn_recv_sock, 1864 .syn_recv_sock = tcp_v6_syn_recv_sock,
1865 .remember_stamp = tcp_v4_remember_stamp, 1865 .get_peer = tcp_v4_get_peer,
1866 .net_header_len = sizeof(struct iphdr), 1866 .net_header_len = sizeof(struct iphdr),
1867 .setsockopt = ipv6_setsockopt, 1867 .setsockopt = ipv6_setsockopt,
1868 .getsockopt = ipv6_getsockopt, 1868 .getsockopt = ipv6_getsockopt,