|
@@ -58,6 +58,25 @@ static bool tcp_in_window(u32 seq, u32 end_seq, u32 s_win, u32 e_win)
|
|
|
return seq == e_win && seq == end_seq;
|
|
|
}
|
|
|
|
|
|
+static enum tcp_tw_status
|
|
|
+tcp_timewait_check_oow_rate_limit(struct inet_timewait_sock *tw,
|
|
|
+ const struct sk_buff *skb, int mib_idx)
|
|
|
+{
|
|
|
+ struct tcp_timewait_sock *tcptw = tcp_twsk((struct sock *)tw);
|
|
|
+
|
|
|
+ if (!tcp_oow_rate_limited(twsk_net(tw), skb, mib_idx,
|
|
|
+ &tcptw->tw_last_oow_ack_time)) {
|
|
|
+ /* Send ACK. Note, we do not put the bucket,
|
|
|
+ * it will be released by caller.
|
|
|
+ */
|
|
|
+ return TCP_TW_ACK;
|
|
|
+ }
|
|
|
+
|
|
|
+ /* We are rate-limiting, so just release the tw sock and drop skb. */
|
|
|
+ inet_twsk_put(tw);
|
|
|
+ return TCP_TW_SUCCESS;
|
|
|
+}
|
|
|
+
|
|
|
/*
|
|
|
* * Main purpose of TIME-WAIT state is to close connection gracefully,
|
|
|
* 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,
|
|
|
!tcp_in_window(TCP_SKB_CB(skb)->seq, TCP_SKB_CB(skb)->end_seq,
|
|
|
tcptw->tw_rcv_nxt,
|
|
|
tcptw->tw_rcv_nxt + tcptw->tw_rcv_wnd))
|
|
|
- return TCP_TW_ACK;
|
|
|
+ return tcp_timewait_check_oow_rate_limit(
|
|
|
+ tw, skb, LINUX_MIB_TCPACKSKIPPEDFINWAIT2);
|
|
|
|
|
|
if (th->rst)
|
|
|
goto kill;
|
|
@@ -250,10 +270,8 @@ kill:
|
|
|
inet_twsk_schedule(tw, &tcp_death_row, TCP_TIMEWAIT_LEN,
|
|
|
TCP_TIMEWAIT_LEN);
|
|
|
|
|
|
- /* Send ACK. Note, we do not put the bucket,
|
|
|
- * it will be released by caller.
|
|
|
- */
|
|
|
- return TCP_TW_ACK;
|
|
|
+ return tcp_timewait_check_oow_rate_limit(
|
|
|
+ tw, skb, LINUX_MIB_TCPACKSKIPPEDTIMEWAIT);
|
|
|
}
|
|
|
inet_twsk_put(tw);
|
|
|
return TCP_TW_SUCCESS;
|
|
@@ -289,6 +307,7 @@ void tcp_time_wait(struct sock *sk, int state, int timeo)
|
|
|
tcptw->tw_ts_recent = tp->rx_opt.ts_recent;
|
|
|
tcptw->tw_ts_recent_stamp = tp->rx_opt.ts_recent_stamp;
|
|
|
tcptw->tw_ts_offset = tp->tsoffset;
|
|
|
+ tcptw->tw_last_oow_ack_time = 0;
|
|
|
|
|
|
#if IS_ENABLED(CONFIG_IPV6)
|
|
|
if (tw->tw_family == PF_INET6) {
|