Do timestamping before cloneing. This fixes the bug where the timestamp was performed in tcp_transmit_skb on the cloned skb leading to the timestamp being lost.
Signed-off-by: Thomas Young <[EMAIL PROTECTED]> --- diff --git a/net/ipv4/tcp_output.c b/net/ipv4/tcp_output.c --- a/net/ipv4/tcp_output.c +++ b/net/ipv4/tcp_output.c @@ -265,7 +265,6 @@ static __inline__ u16 tcp_select_window( static int tcp_transmit_skb(struct sock *sk, struct sk_buff *skb) { if (skb != NULL) { - const struct inet_connection_sock *icsk = inet_csk(sk); struct inet_sock *inet = inet_sk(sk); struct tcp_sock *tp = tcp_sk(sk); struct tcp_skb_cb *tcb = TCP_SKB_CB(skb); @@ -280,10 +279,6 @@ static int tcp_transmit_skb(struct sock #define SYSCTL_FLAG_WSCALE 0x2 #define SYSCTL_FLAG_SACK 0x4 - /* If congestion control is doing timestamping */ - if (icsk->icsk_ca_ops->rtt_sample) - __net_timestamp(skb); - sysctl_flags = 0; if (tcb->flags & TCPCB_FLAG_SYN) { tcp_header_size = sizeof(struct tcphdr) + TCPOLEN_MSS; @@ -982,6 +977,7 @@ static int tcp_tso_should_defer(struct s static int tcp_write_xmit(struct sock *sk, unsigned int mss_now, int nonagle) { struct tcp_sock *tp = tcp_sk(sk); + struct inet_connection_sock *icsk = inet_csk(sk); struct sk_buff *skb; unsigned int tso_segs, sent_pkts; int cwnd_quota; @@ -1036,6 +1032,9 @@ static int tcp_write_xmit(struct sock *s TCP_SKB_CB(skb)->when = tcp_time_stamp; + if (icsk->icsk_ca_ops->rtt_sample) + __net_timestamp(skb); + if (unlikely(tcp_transmit_skb(sk, skb_clone(skb, GFP_ATOMIC)))) break; @@ -1076,6 +1075,7 @@ void __tcp_push_pending_frames(struct so void tcp_push_one(struct sock *sk, unsigned int mss_now) { struct tcp_sock *tp = tcp_sk(sk); + const struct inet_connection_sock *icsk = inet_csk(sk); struct sk_buff *skb = sk->sk_send_head; unsigned int tso_segs, cwnd_quota; @@ -1109,6 +1109,9 @@ void tcp_push_one(struct sock *sk, unsig /* Send it out now. */ TCP_SKB_CB(skb)->when = tcp_time_stamp; + if (icsk->icsk_ca_ops->rtt_sample) + __net_timestamp(skb); + if (likely(!tcp_transmit_skb(sk, skb_clone(skb, sk->sk_allocation)))) { update_send_head(sk, tp, skb); tcp_cwnd_validate(sk, tp); @@ -1364,6 +1367,7 @@ void tcp_simple_retransmit(struct sock * int tcp_retransmit_skb(struct sock *sk, struct sk_buff *skb) { struct tcp_sock *tp = tcp_sk(sk); + struct inet_connection_sock *icsk = inet_csk(sk); unsigned int cur_mss = tcp_current_mss(sk, 0); int err; @@ -1429,6 +1433,9 @@ int tcp_retransmit_skb(struct sock *sk, */ TCP_SKB_CB(skb)->when = tcp_time_stamp; + if (icsk->icsk_ca_ops->rtt_sample) + __net_timestamp(skb); + err = tcp_transmit_skb(sk, (skb_cloned(skb) ? pskb_copy(skb, GFP_ATOMIC): skb_clone(skb, GFP_ATOMIC))); @@ -1677,6 +1684,7 @@ void tcp_send_active_reset(struct sock * int tcp_send_synack(struct sock *sk) { struct sk_buff* skb; + struct inet_connection_sock *icsk = inet_csk(sk); skb = skb_peek(&sk->sk_write_queue); if (skb == NULL || !(TCP_SKB_CB(skb)->flags&TCPCB_FLAG_SYN)) { @@ -1700,6 +1708,8 @@ int tcp_send_synack(struct sock *sk) TCP_ECN_send_synack(tcp_sk(sk), skb); } TCP_SKB_CB(skb)->when = tcp_time_stamp; + if (icsk->icsk_ca_ops->rtt_sample) + __net_timestamp(skb); return tcp_transmit_skb(sk, skb_clone(skb, GFP_ATOMIC)); } @@ -1832,6 +1842,7 @@ static inline void tcp_connect_init(stru int tcp_connect(struct sock *sk) { struct tcp_sock *tp = tcp_sk(sk); + struct inet_connection_sock *icsk = inet_csk(sk); struct sk_buff *buff; tcp_connect_init(sk); @@ -1856,6 +1867,8 @@ int tcp_connect(struct sock *sk) /* Send it off. */ TCP_SKB_CB(buff)->when = tcp_time_stamp; + if (icsk->icsk_ca_ops->rtt_sample) + __net_timestamp(buff); tp->retrans_stamp = TCP_SKB_CB(buff)->when; skb_header_release(buff); __skb_queue_tail(&sk->sk_write_queue, buff); @@ -2004,6 +2017,7 @@ int tcp_write_wakeup(struct sock *sk) { if (sk->sk_state != TCP_CLOSE) { struct tcp_sock *tp = tcp_sk(sk); + struct inet_connection_sock *icsk = inet_csk(sk); struct sk_buff *skb; if ((skb = sk->sk_send_head) != NULL && @@ -2030,6 +2044,8 @@ int tcp_write_wakeup(struct sock *sk) TCP_SKB_CB(skb)->flags |= TCPCB_FLAG_PSH; TCP_SKB_CB(skb)->when = tcp_time_stamp; + if (icsk->icsk_ca_ops->rtt_sample) + __net_timestamp(skb); err = tcp_transmit_skb(sk, skb_clone(skb, GFP_ATOMIC)); if (!err) { update_send_head(sk, tp, skb); - To unsubscribe from this list: send the line "unsubscribe netdev" in the body of a message to [EMAIL PROTECTED] More majordomo info at http://vger.kernel.org/majordomo-info.html