aboutsummaryrefslogtreecommitdiffstats
path: root/net/ipv4/tcp_output.c
diff options
context:
space:
mode:
Diffstat (limited to 'net/ipv4/tcp_output.c')
-rw-r--r--net/ipv4/tcp_output.c19
1 files changed, 13 insertions, 6 deletions
diff --git a/net/ipv4/tcp_output.c b/net/ipv4/tcp_output.c
index f4aa4109334a..5474c9854f25 100644
--- a/net/ipv4/tcp_output.c
+++ b/net/ipv4/tcp_output.c
@@ -985,7 +985,8 @@ static void tcp_internal_pacing(struct sock *sk)
985 sock_hold(sk); 985 sock_hold(sk);
986} 986}
987 987
988static void tcp_update_skb_after_send(struct sock *sk, struct sk_buff *skb) 988static void tcp_update_skb_after_send(struct sock *sk, struct sk_buff *skb,
989 u64 prior_wstamp)
989{ 990{
990 struct tcp_sock *tp = tcp_sk(sk); 991 struct tcp_sock *tp = tcp_sk(sk);
991 992
@@ -998,7 +999,12 @@ static void tcp_update_skb_after_send(struct sock *sk, struct sk_buff *skb)
998 * this is a minor annoyance. 999 * this is a minor annoyance.
999 */ 1000 */
1000 if (rate != ~0UL && rate && tp->data_segs_out >= 10) { 1001 if (rate != ~0UL && rate && tp->data_segs_out >= 10) {
1001 tp->tcp_wstamp_ns += div64_ul((u64)skb->len * NSEC_PER_SEC, rate); 1002 u64 len_ns = div64_ul((u64)skb->len * NSEC_PER_SEC, rate);
1003 u64 credit = tp->tcp_wstamp_ns - prior_wstamp;
1004
1005 /* take into account OS jitter */
1006 len_ns -= min_t(u64, len_ns / 2, credit);
1007 tp->tcp_wstamp_ns += len_ns;
1002 1008
1003 tcp_internal_pacing(sk); 1009 tcp_internal_pacing(sk);
1004 } 1010 }
@@ -1029,6 +1035,7 @@ static int __tcp_transmit_skb(struct sock *sk, struct sk_buff *skb,
1029 struct sk_buff *oskb = NULL; 1035 struct sk_buff *oskb = NULL;
1030 struct tcp_md5sig_key *md5; 1036 struct tcp_md5sig_key *md5;
1031 struct tcphdr *th; 1037 struct tcphdr *th;
1038 u64 prior_wstamp;
1032 int err; 1039 int err;
1033 1040
1034 BUG_ON(!skb || !tcp_skb_pcount(skb)); 1041 BUG_ON(!skb || !tcp_skb_pcount(skb));
@@ -1050,7 +1057,7 @@ static int __tcp_transmit_skb(struct sock *sk, struct sk_buff *skb,
1050 return -ENOBUFS; 1057 return -ENOBUFS;
1051 } 1058 }
1052 1059
1053 /* TODO: might take care of jitter here */ 1060 prior_wstamp = tp->tcp_wstamp_ns;
1054 tp->tcp_wstamp_ns = max(tp->tcp_wstamp_ns, tp->tcp_clock_cache); 1061 tp->tcp_wstamp_ns = max(tp->tcp_wstamp_ns, tp->tcp_clock_cache);
1055 1062
1056 skb->skb_mstamp_ns = tp->tcp_wstamp_ns; 1063 skb->skb_mstamp_ns = tp->tcp_wstamp_ns;
@@ -1169,7 +1176,7 @@ static int __tcp_transmit_skb(struct sock *sk, struct sk_buff *skb,
1169 err = net_xmit_eval(err); 1176 err = net_xmit_eval(err);
1170 } 1177 }
1171 if (!err && oskb) { 1178 if (!err && oskb) {
1172 tcp_update_skb_after_send(sk, oskb); 1179 tcp_update_skb_after_send(sk, oskb, prior_wstamp);
1173 tcp_rate_skb_sent(sk, oskb); 1180 tcp_rate_skb_sent(sk, oskb);
1174 } 1181 }
1175 return err; 1182 return err;
@@ -2321,7 +2328,7 @@ static bool tcp_write_xmit(struct sock *sk, unsigned int mss_now, int nonagle,
2321 2328
2322 if (unlikely(tp->repair) && tp->repair_queue == TCP_SEND_QUEUE) { 2329 if (unlikely(tp->repair) && tp->repair_queue == TCP_SEND_QUEUE) {
2323 /* "skb_mstamp" is used as a start point for the retransmit timer */ 2330 /* "skb_mstamp" is used as a start point for the retransmit timer */
2324 tcp_update_skb_after_send(sk, skb); 2331 tcp_update_skb_after_send(sk, skb, tp->tcp_wstamp_ns);
2325 goto repair; /* Skip network transmission */ 2332 goto repair; /* Skip network transmission */
2326 } 2333 }
2327 2334
@@ -2896,7 +2903,7 @@ int __tcp_retransmit_skb(struct sock *sk, struct sk_buff *skb, int segs)
2896 } tcp_skb_tsorted_restore(skb); 2903 } tcp_skb_tsorted_restore(skb);
2897 2904
2898 if (!err) { 2905 if (!err) {
2899 tcp_update_skb_after_send(sk, skb); 2906 tcp_update_skb_after_send(sk, skb, tp->tcp_wstamp_ns);
2900 tcp_rate_skb_sent(sk, skb); 2907 tcp_rate_skb_sent(sk, skb);
2901 } 2908 }
2902 } else { 2909 } else {