|
@@ -113,6 +113,7 @@ int sysctl_tcp_early_retrans __read_mostly = 2;
|
|
|
#define FLAG_DSACKING_ACK 0x800 /* SACK blocks contained D-SACK info */
|
|
|
#define FLAG_NONHEAD_RETRANS_ACKED 0x1000 /* Non-head rexmitted data was ACKed */
|
|
|
#define FLAG_SACK_RENEGING 0x2000 /* snd_una advanced to a sacked seq */
|
|
|
+#define FLAG_UPDATE_TS_RECENT 0x4000 /* tcp_replace_ts_recent() */
|
|
|
|
|
|
#define FLAG_ACKED (FLAG_DATA_ACKED|FLAG_SYN_ACKED)
|
|
|
#define FLAG_NOT_DUP (FLAG_DATA|FLAG_WIN_UPDATE|FLAG_ACKED)
|
|
@@ -3564,6 +3565,27 @@ static void tcp_send_challenge_ack(struct sock *sk)
|
|
|
}
|
|
|
}
|
|
|
|
|
|
+static void tcp_store_ts_recent(struct tcp_sock *tp)
|
|
|
+{
|
|
|
+ tp->rx_opt.ts_recent = tp->rx_opt.rcv_tsval;
|
|
|
+ tp->rx_opt.ts_recent_stamp = get_seconds();
|
|
|
+}
|
|
|
+
|
|
|
+static void tcp_replace_ts_recent(struct tcp_sock *tp, u32 seq)
|
|
|
+{
|
|
|
+ if (tp->rx_opt.saw_tstamp && !after(seq, tp->rcv_wup)) {
|
|
|
+ /* PAWS bug workaround wrt. ACK frames, the PAWS discard
|
|
|
+ * extra check below makes sure this can only happen
|
|
|
+ * for pure ACK frames. -DaveM
|
|
|
+ *
|
|
|
+ * Not only, also it occurs for expired timestamps.
|
|
|
+ */
|
|
|
+
|
|
|
+ if (tcp_paws_check(&tp->rx_opt, 0))
|
|
|
+ tcp_store_ts_recent(tp);
|
|
|
+ }
|
|
|
+}
|
|
|
+
|
|
|
/* This routine deals with incoming acks, but not outgoing ones. */
|
|
|
static int tcp_ack(struct sock *sk, const struct sk_buff *skb, int flag)
|
|
|
{
|
|
@@ -3607,6 +3629,12 @@ static int tcp_ack(struct sock *sk, const struct sk_buff *skb, int flag)
|
|
|
prior_fackets = tp->fackets_out;
|
|
|
prior_in_flight = tcp_packets_in_flight(tp);
|
|
|
|
|
|
+ /* ts_recent update must be made after we are sure that the packet
|
|
|
+ * is in window.
|
|
|
+ */
|
|
|
+ if (flag & FLAG_UPDATE_TS_RECENT)
|
|
|
+ tcp_replace_ts_recent(tp, TCP_SKB_CB(skb)->seq);
|
|
|
+
|
|
|
if (!(flag & FLAG_SLOWPATH) && after(ack, prior_snd_una)) {
|
|
|
/* Window is constant, pure forward advance.
|
|
|
* No more checks are required.
|
|
@@ -3927,27 +3955,6 @@ const u8 *tcp_parse_md5sig_option(const struct tcphdr *th)
|
|
|
EXPORT_SYMBOL(tcp_parse_md5sig_option);
|
|
|
#endif
|
|
|
|
|
|
-static inline void tcp_store_ts_recent(struct tcp_sock *tp)
|
|
|
-{
|
|
|
- tp->rx_opt.ts_recent = tp->rx_opt.rcv_tsval;
|
|
|
- tp->rx_opt.ts_recent_stamp = get_seconds();
|
|
|
-}
|
|
|
-
|
|
|
-static inline void tcp_replace_ts_recent(struct tcp_sock *tp, u32 seq)
|
|
|
-{
|
|
|
- if (tp->rx_opt.saw_tstamp && !after(seq, tp->rcv_wup)) {
|
|
|
- /* PAWS bug workaround wrt. ACK frames, the PAWS discard
|
|
|
- * extra check below makes sure this can only happen
|
|
|
- * for pure ACK frames. -DaveM
|
|
|
- *
|
|
|
- * Not only, also it occurs for expired timestamps.
|
|
|
- */
|
|
|
-
|
|
|
- if (tcp_paws_check(&tp->rx_opt, 0))
|
|
|
- tcp_store_ts_recent(tp);
|
|
|
- }
|
|
|
-}
|
|
|
-
|
|
|
/* Sorry, PAWS as specified is broken wrt. pure-ACKs -DaveM
|
|
|
*
|
|
|
* It is not fatal. If this ACK does _not_ change critical state (seqs, window)
|
|
@@ -5543,14 +5550,9 @@ slow_path:
|
|
|
return 0;
|
|
|
|
|
|
step5:
|
|
|
- if (tcp_ack(sk, skb, FLAG_SLOWPATH) < 0)
|
|
|
+ if (tcp_ack(sk, skb, FLAG_SLOWPATH | FLAG_UPDATE_TS_RECENT) < 0)
|
|
|
goto discard;
|
|
|
|
|
|
- /* ts_recent update must be made after we are sure that the packet
|
|
|
- * is in window.
|
|
|
- */
|
|
|
- tcp_replace_ts_recent(tp, TCP_SKB_CB(skb)->seq);
|
|
|
-
|
|
|
tcp_rcv_rtt_measure_ts(sk, skb);
|
|
|
|
|
|
/* Process urgent data. */
|
|
@@ -5986,7 +5988,8 @@ int tcp_rcv_state_process(struct sock *sk, struct sk_buff *skb,
|
|
|
|
|
|
/* step 5: check the ACK field */
|
|
|
if (true) {
|
|
|
- int acceptable = tcp_ack(sk, skb, FLAG_SLOWPATH) > 0;
|
|
|
+ int acceptable = tcp_ack(sk, skb, FLAG_SLOWPATH |
|
|
|
+ FLAG_UPDATE_TS_RECENT) > 0;
|
|
|
|
|
|
switch (sk->sk_state) {
|
|
|
case TCP_SYN_RECV:
|
|
@@ -6137,11 +6140,6 @@ int tcp_rcv_state_process(struct sock *sk, struct sk_buff *skb,
|
|
|
}
|
|
|
}
|
|
|
|
|
|
- /* ts_recent update must be made after we are sure that the packet
|
|
|
- * is in window.
|
|
|
- */
|
|
|
- tcp_replace_ts_recent(tp, TCP_SKB_CB(skb)->seq);
|
|
|
-
|
|
|
/* step 6: check the URG bit */
|
|
|
tcp_urg(sk, skb, th);
|
|
|
|