diff options
Diffstat (limited to 'net/ipv4/tcp_minisocks.c')
-rw-r--r-- | net/ipv4/tcp_minisocks.c | 29 |
1 files changed, 24 insertions, 5 deletions
diff --git a/net/ipv4/tcp_minisocks.c b/net/ipv4/tcp_minisocks.c index 98a840561ec8..dd11ac7798c6 100644 --- a/net/ipv4/tcp_minisocks.c +++ b/net/ipv4/tcp_minisocks.c | |||
@@ -58,6 +58,25 @@ static bool tcp_in_window(u32 seq, u32 end_seq, u32 s_win, u32 e_win) | |||
58 | return seq == e_win && seq == end_seq; | 58 | return seq == e_win && seq == end_seq; |
59 | } | 59 | } |
60 | 60 | ||
61 | static enum tcp_tw_status | ||
62 | tcp_timewait_check_oow_rate_limit(struct inet_timewait_sock *tw, | ||
63 | const struct sk_buff *skb, int mib_idx) | ||
64 | { | ||
65 | struct tcp_timewait_sock *tcptw = tcp_twsk((struct sock *)tw); | ||
66 | |||
67 | if (!tcp_oow_rate_limited(twsk_net(tw), skb, mib_idx, | ||
68 | &tcptw->tw_last_oow_ack_time)) { | ||
69 | /* Send ACK. Note, we do not put the bucket, | ||
70 | * it will be released by caller. | ||
71 | */ | ||
72 | return TCP_TW_ACK; | ||
73 | } | ||
74 | |||
75 | /* We are rate-limiting, so just release the tw sock and drop skb. */ | ||
76 | inet_twsk_put(tw); | ||
77 | return TCP_TW_SUCCESS; | ||
78 | } | ||
79 | |||
61 | /* | 80 | /* |
62 | * * Main purpose of TIME-WAIT state is to close connection gracefully, | 81 | * * Main purpose of TIME-WAIT state is to close connection gracefully, |
63 | * when one of ends sits in LAST-ACK or CLOSING retransmitting FIN | 82 | * when one of ends sits in LAST-ACK or CLOSING retransmitting FIN |
@@ -116,7 +135,8 @@ tcp_timewait_state_process(struct inet_timewait_sock *tw, struct sk_buff *skb, | |||
116 | !tcp_in_window(TCP_SKB_CB(skb)->seq, TCP_SKB_CB(skb)->end_seq, | 135 | !tcp_in_window(TCP_SKB_CB(skb)->seq, TCP_SKB_CB(skb)->end_seq, |
117 | tcptw->tw_rcv_nxt, | 136 | tcptw->tw_rcv_nxt, |
118 | tcptw->tw_rcv_nxt + tcptw->tw_rcv_wnd)) | 137 | tcptw->tw_rcv_nxt + tcptw->tw_rcv_wnd)) |
119 | return TCP_TW_ACK; | 138 | return tcp_timewait_check_oow_rate_limit( |
139 | tw, skb, LINUX_MIB_TCPACKSKIPPEDFINWAIT2); | ||
120 | 140 | ||
121 | if (th->rst) | 141 | if (th->rst) |
122 | goto kill; | 142 | goto kill; |
@@ -250,10 +270,8 @@ kill: | |||
250 | inet_twsk_schedule(tw, &tcp_death_row, TCP_TIMEWAIT_LEN, | 270 | inet_twsk_schedule(tw, &tcp_death_row, TCP_TIMEWAIT_LEN, |
251 | TCP_TIMEWAIT_LEN); | 271 | TCP_TIMEWAIT_LEN); |
252 | 272 | ||
253 | /* Send ACK. Note, we do not put the bucket, | 273 | return tcp_timewait_check_oow_rate_limit( |
254 | * it will be released by caller. | 274 | tw, skb, LINUX_MIB_TCPACKSKIPPEDTIMEWAIT); |
255 | */ | ||
256 | return TCP_TW_ACK; | ||
257 | } | 275 | } |
258 | inet_twsk_put(tw); | 276 | inet_twsk_put(tw); |
259 | return TCP_TW_SUCCESS; | 277 | return TCP_TW_SUCCESS; |
@@ -289,6 +307,7 @@ void tcp_time_wait(struct sock *sk, int state, int timeo) | |||
289 | tcptw->tw_ts_recent = tp->rx_opt.ts_recent; | 307 | tcptw->tw_ts_recent = tp->rx_opt.ts_recent; |
290 | tcptw->tw_ts_recent_stamp = tp->rx_opt.ts_recent_stamp; | 308 | tcptw->tw_ts_recent_stamp = tp->rx_opt.ts_recent_stamp; |
291 | tcptw->tw_ts_offset = tp->tsoffset; | 309 | tcptw->tw_ts_offset = tp->tsoffset; |
310 | tcptw->tw_last_oow_ack_time = 0; | ||
292 | 311 | ||
293 | #if IS_ENABLED(CONFIG_IPV6) | 312 | #if IS_ENABLED(CONFIG_IPV6) |
294 | if (tw->tw_family == PF_INET6) { | 313 | if (tw->tw_family == PF_INET6) { |