Commit ccb7c410ddc054b8c1ae780319bc98ae092d3854

Authored by David S. Miller
1 parent 4399ce402c

timewait_sock: Create and use getpeer op.

The only thing AF-specific about remembering the timestamp
for a time-wait TCP socket is getting the peer.

Abstract that behind a new timewait_sock_ops vector.

Support for real IPV6 sockets is not filled in yet, but
curiously this makes timewait recycling start to work
for v4-mapped ipv6 sockets.

Signed-off-by: David S. Miller <davem@davemloft.net>

Showing 5 changed files with 63 additions and 37 deletions Side-by-side Diff

... ... @@ -313,6 +313,7 @@
313 313 extern int tcp_v4_rcv(struct sk_buff *skb);
314 314  
315 315 extern struct inet_peer *tcp_v4_get_peer(struct sock *sk, bool *release_it);
  316 +extern void *tcp_v4_tw_get_peer(struct sock *sk);
316 317 extern int tcp_v4_tw_remember_stamp(struct inet_timewait_sock *tw);
317 318 extern int tcp_sendmsg(struct kiocb *iocb, struct sock *sk, struct msghdr *msg,
318 319 size_t size);
include/net/timewait_sock.h
... ... @@ -21,6 +21,7 @@
21 21 int (*twsk_unique)(struct sock *sk,
22 22 struct sock *sktw, void *twp);
23 23 void (*twsk_destructor)(struct sock *sk);
  24 + void *(*twsk_getpeer)(struct sock *sk);
24 25 };
25 26  
26 27 static inline int twsk_unique(struct sock *sk, struct sock *sktw, void *twp)
... ... @@ -37,6 +38,13 @@
37 38 BUG_ON(sk->sk_prot->twsk_prot == NULL);
38 39 if (sk->sk_prot->twsk_prot->twsk_destructor != NULL)
39 40 sk->sk_prot->twsk_prot->twsk_destructor(sk);
  41 +}
  42 +
  43 +static inline void *twsk_getpeer(struct sock *sk)
  44 +{
  45 + if (sk->sk_prot->twsk_prot->twsk_getpeer)
  46 + return sk->sk_prot->twsk_prot->twsk_getpeer(sk);
  47 + return NULL;
40 48 }
41 49  
42 50 #endif /* _TIMEWAIT_SOCK_H */
... ... @@ -1210,12 +1210,6 @@
1210 1210 };
1211 1211 #endif
1212 1212  
1213   -static struct timewait_sock_ops tcp_timewait_sock_ops = {
1214   - .twsk_obj_size = sizeof(struct tcp_timewait_sock),
1215   - .twsk_unique = tcp_twsk_unique,
1216   - .twsk_destructor= tcp_twsk_destructor,
1217   -};
1218   -
1219 1213 int tcp_v4_conn_request(struct sock *sk, struct sk_buff *skb)
1220 1214 {
1221 1215 struct tcp_extend_values tmp_ext;
1222 1216  
1223 1217  
1224 1218  
... ... @@ -1783,25 +1777,20 @@
1783 1777 }
1784 1778 EXPORT_SYMBOL(tcp_v4_get_peer);
1785 1779  
1786   -int tcp_v4_tw_remember_stamp(struct inet_timewait_sock *tw)
  1780 +void *tcp_v4_tw_get_peer(struct sock *sk)
1787 1781 {
1788   - struct inet_peer *peer = inet_getpeer_v4(tw->tw_daddr, 1);
  1782 + struct inet_timewait_sock *tw = inet_twsk(sk);
1789 1783  
1790   - if (peer) {
1791   - const struct tcp_timewait_sock *tcptw = tcp_twsk((struct sock *)tw);
1792   -
1793   - if ((s32)(peer->tcp_ts - tcptw->tw_ts_recent) <= 0 ||
1794   - ((u32)get_seconds() - peer->tcp_ts_stamp > TCP_PAWS_MSL &&
1795   - peer->tcp_ts_stamp <= (u32)tcptw->tw_ts_recent_stamp)) {
1796   - peer->tcp_ts_stamp = (u32)tcptw->tw_ts_recent_stamp;
1797   - peer->tcp_ts = tcptw->tw_ts_recent;
1798   - }
1799   - inet_putpeer(peer);
1800   - return 1;
1801   - }
1802   -
1803   - return 0;
  1784 + return inet_getpeer_v4(tw->tw_daddr, 1);
1804 1785 }
  1786 +EXPORT_SYMBOL(tcp_v4_tw_get_peer);
  1787 +
  1788 +static struct timewait_sock_ops tcp_timewait_sock_ops = {
  1789 + .twsk_obj_size = sizeof(struct tcp_timewait_sock),
  1790 + .twsk_unique = tcp_twsk_unique,
  1791 + .twsk_destructor= tcp_twsk_destructor,
  1792 + .twsk_getpeer = tcp_v4_tw_get_peer,
  1793 +};
1805 1794  
1806 1795 const struct inet_connection_sock_af_ops ipv4_specific = {
1807 1796 .queue_xmit = ip_queue_xmit,
net/ipv4/tcp_minisocks.c
... ... @@ -78,6 +78,27 @@
78 78 return 0;
79 79 }
80 80  
  81 +static int tcp_tw_remember_stamp(struct inet_timewait_sock *tw)
  82 +{
  83 + struct sock *sk = (struct sock *) tw;
  84 + struct inet_peer *peer;
  85 +
  86 + peer = twsk_getpeer(sk);
  87 + if (peer) {
  88 + const struct tcp_timewait_sock *tcptw = tcp_twsk(sk);
  89 +
  90 + if ((s32)(peer->tcp_ts - tcptw->tw_ts_recent) <= 0 ||
  91 + ((u32)get_seconds() - peer->tcp_ts_stamp > TCP_PAWS_MSL &&
  92 + peer->tcp_ts_stamp <= (u32)tcptw->tw_ts_recent_stamp)) {
  93 + peer->tcp_ts_stamp = (u32)tcptw->tw_ts_recent_stamp;
  94 + peer->tcp_ts = tcptw->tw_ts_recent;
  95 + }
  96 + inet_putpeer(peer);
  97 + return 1;
  98 + }
  99 + return 0;
  100 +}
  101 +
81 102 static __inline__ int tcp_in_window(u32 seq, u32 end_seq, u32 s_win, u32 e_win)
82 103 {
83 104 if (seq == s_win)
... ... @@ -178,14 +199,9 @@
178 199 tcptw->tw_ts_recent = tmp_opt.rcv_tsval;
179 200 }
180 201  
181   - /* I am shamed, but failed to make it more elegant.
182   - * Yes, it is direct reference to IP, which is impossible
183   - * to generalize to IPv6. Taking into account that IPv6
184   - * do not understand recycling in any case, it not
185   - * a big problem in practice. --ANK */
186   - if (tw->tw_family == AF_INET &&
187   - tcp_death_row.sysctl_tw_recycle && tcptw->tw_ts_recent_stamp &&
188   - tcp_v4_tw_remember_stamp(tw))
  202 + if (tcp_death_row.sysctl_tw_recycle &&
  203 + tcptw->tw_ts_recent_stamp &&
  204 + tcp_tw_remember_stamp(tw))
189 205 inet_twsk_schedule(tw, &tcp_death_row, tw->tw_timeout,
190 206 TCP_TIMEWAIT_LEN);
191 207 else
... ... @@ -906,12 +906,6 @@
906 906 };
907 907 #endif
908 908  
909   -static struct timewait_sock_ops tcp6_timewait_sock_ops = {
910   - .twsk_obj_size = sizeof(struct tcp6_timewait_sock),
911   - .twsk_unique = tcp_twsk_unique,
912   - .twsk_destructor= tcp_twsk_destructor,
913   -};
914   -
915 909 static void __tcp_v6_send_check(struct sk_buff *skb,
916 910 struct in6_addr *saddr, struct in6_addr *daddr)
917 911 {
918 912  
... ... @@ -1818,11 +1812,29 @@
1818 1812 goto discard_it;
1819 1813 }
1820 1814  
1821   -struct inet_peer *tcp_v6_get_peer(struct sock *sk, bool *release_it)
  1815 +static struct inet_peer *tcp_v6_get_peer(struct sock *sk, bool *release_it)
1822 1816 {
1823 1817 /* Alas, not yet... */
1824 1818 return NULL;
1825 1819 }
  1820 +
  1821 +static void *tcp_v6_tw_get_peer(struct sock *sk)
  1822 +{
  1823 + struct inet_timewait_sock *tw = inet_twsk(sk);
  1824 +
  1825 + if (tw->tw_family == AF_INET)
  1826 + return tcp_v4_tw_get_peer(sk);
  1827 +
  1828 + /* Alas, not yet... */
  1829 + return NULL;
  1830 +}
  1831 +
  1832 +static struct timewait_sock_ops tcp6_timewait_sock_ops = {
  1833 + .twsk_obj_size = sizeof(struct tcp6_timewait_sock),
  1834 + .twsk_unique = tcp_twsk_unique,
  1835 + .twsk_destructor= tcp_twsk_destructor,
  1836 + .twsk_getpeer = tcp_v6_tw_get_peer,
  1837 +};
1826 1838  
1827 1839 static const struct inet_connection_sock_af_ops ipv6_specific = {
1828 1840 .queue_xmit = inet6_csk_xmit,