Skip to content

Commit ccb7c41

Browse files
committed
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 <[email protected]>
1 parent 4399ce4 commit ccb7c41

File tree

5 files changed

+63
-37
lines changed

5 files changed

+63
-37
lines changed

include/net/tcp.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -313,6 +313,7 @@ extern void tcp_shutdown (struct sock *sk, int how);
313313
extern int tcp_v4_rcv(struct sk_buff *skb);
314314

315315
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);
316317
extern int tcp_v4_tw_remember_stamp(struct inet_timewait_sock *tw);
317318
extern int tcp_sendmsg(struct kiocb *iocb, struct sock *sk, struct msghdr *msg,
318319
size_t size);

include/net/timewait_sock.h

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,7 @@ struct timewait_sock_ops {
2121
int (*twsk_unique)(struct sock *sk,
2222
struct sock *sktw, void *twp);
2323
void (*twsk_destructor)(struct sock *sk);
24+
void *(*twsk_getpeer)(struct sock *sk);
2425
};
2526

2627
static inline int twsk_unique(struct sock *sk, struct sock *sktw, void *twp)
@@ -39,4 +40,11 @@ static inline void twsk_destructor(struct sock *sk)
3940
sk->sk_prot->twsk_prot->twsk_destructor(sk);
4041
}
4142

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;
48+
}
49+
4250
#endif /* _TIMEWAIT_SOCK_H */

net/ipv4/tcp_ipv4.c

Lines changed: 11 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -1210,12 +1210,6 @@ static const struct tcp_request_sock_ops tcp_request_sock_ipv4_ops = {
12101210
};
12111211
#endif
12121212

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-
12191213
int tcp_v4_conn_request(struct sock *sk, struct sk_buff *skb)
12201214
{
12211215
struct tcp_extend_values tmp_ext;
@@ -1783,25 +1777,20 @@ struct inet_peer *tcp_v4_get_peer(struct sock *sk, bool *release_it)
17831777
}
17841778
EXPORT_SYMBOL(tcp_v4_get_peer);
17851779

1786-
int tcp_v4_tw_remember_stamp(struct inet_timewait_sock *tw)
1780+
void *tcp_v4_tw_get_peer(struct sock *sk)
17871781
{
1788-
struct inet_peer *peer = inet_getpeer_v4(tw->tw_daddr, 1);
1789-
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-
}
1782+
struct inet_timewait_sock *tw = inet_twsk(sk);
18021783

1803-
return 0;
1784+
return inet_getpeer_v4(tw->tw_daddr, 1);
18041785
}
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+
};
18051794

18061795
const struct inet_connection_sock_af_ops ipv4_specific = {
18071796
.queue_xmit = ip_queue_xmit,

net/ipv4/tcp_minisocks.c

Lines changed: 24 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -78,6 +78,27 @@ static int tcp_remember_stamp(struct sock *sk)
7878
return 0;
7979
}
8080

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+
81102
static __inline__ int tcp_in_window(u32 seq, u32 end_seq, u32 s_win, u32 e_win)
82103
{
83104
if (seq == s_win)
@@ -178,14 +199,9 @@ tcp_timewait_state_process(struct inet_timewait_sock *tw, struct sk_buff *skb,
178199
tcptw->tw_ts_recent = tmp_opt.rcv_tsval;
179200
}
180201

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))
189205
inet_twsk_schedule(tw, &tcp_death_row, tw->tw_timeout,
190206
TCP_TIMEWAIT_LEN);
191207
else

net/ipv6/tcp_ipv6.c

Lines changed: 19 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -906,12 +906,6 @@ static const struct tcp_request_sock_ops tcp_request_sock_ipv6_ops = {
906906
};
907907
#endif
908908

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-
915909
static void __tcp_v6_send_check(struct sk_buff *skb,
916910
struct in6_addr *saddr, struct in6_addr *daddr)
917911
{
@@ -1818,12 +1812,30 @@ static int tcp_v6_rcv(struct sk_buff *skb)
18181812
goto discard_it;
18191813
}
18201814

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)
1816+
{
1817+
/* Alas, not yet... */
1818+
return NULL;
1819+
}
1820+
1821+
static void *tcp_v6_tw_get_peer(struct sock *sk)
18221822
{
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+
18231828
/* Alas, not yet... */
18241829
return NULL;
18251830
}
18261831

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+
};
1838+
18271839
static const struct inet_connection_sock_af_ops ipv6_specific = {
18281840
.queue_xmit = inet6_csk_xmit,
18291841
.send_check = tcp_v6_send_check,

0 commit comments

Comments
 (0)