diff options
Diffstat (limited to 'net/ipv4/tcp_input.c')
| -rw-r--r-- | net/ipv4/tcp_input.c | 64 | 
1 files changed, 31 insertions, 33 deletions
diff --git a/net/ipv4/tcp_input.c b/net/ipv4/tcp_input.c index 3bd55bad230a..13b9c08fc158 100644 --- a/net/ipv4/tcp_input.c +++ b/net/ipv4/tcp_input.c @@ -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);  |