Commit f69ad292cfd13aa7ee00847320c6bb9ba2154e87
Committed by
David S. Miller
1 parent
5bbb432c89
Exists in
smarct4x-processor-sdk-linux-03.00.00.04
and in
4 other branches
tcp: fill shinfo->gso_size at last moment
In commit cd7d8498c9a5 ("tcp: change tcp_skb_pcount() location") we stored gso_segs in a temporary cache hot location. This patch does the same for gso_size. This allows to save 2 cache line misses in tcp xmit path for the last packet that is considered but not sent because of various conditions (cwnd, tso defer, receiver window, TSQ...) Signed-off-by: Eric Dumazet <edumazet@google.com> Signed-off-by: David S. Miller <davem@davemloft.net>
Showing 3 changed files with 16 additions and 17 deletions Side-by-side Diff
include/net/tcp.h
... | ... | @@ -730,11 +730,14 @@ |
730 | 730 | /* Note : tcp_tw_isn is used in input path only |
731 | 731 | * (isn chosen by tcp_timewait_state_process()) |
732 | 732 | * |
733 | - * tcp_gso_segs is used in write queue only, | |
734 | - * cf tcp_skb_pcount() | |
733 | + * tcp_gso_segs/size are used in write queue only, | |
734 | + * cf tcp_skb_pcount()/tcp_skb_mss() | |
735 | 735 | */ |
736 | 736 | __u32 tcp_tw_isn; |
737 | - __u32 tcp_gso_segs; | |
737 | + struct { | |
738 | + u16 tcp_gso_segs; | |
739 | + u16 tcp_gso_size; | |
740 | + }; | |
738 | 741 | }; |
739 | 742 | __u8 tcp_flags; /* TCP header flags. (tcp[13]) */ |
740 | 743 | |
741 | 744 | |
... | ... | @@ -790,10 +793,10 @@ |
790 | 793 | TCP_SKB_CB(skb)->tcp_gso_segs += segs; |
791 | 794 | } |
792 | 795 | |
793 | -/* This is valid iff tcp_skb_pcount() > 1. */ | |
796 | +/* This is valid iff skb is in write queue and tcp_skb_pcount() > 1. */ | |
794 | 797 | static inline int tcp_skb_mss(const struct sk_buff *skb) |
795 | 798 | { |
796 | - return skb_shinfo(skb)->gso_size; | |
799 | + return TCP_SKB_CB(skb)->tcp_gso_size; | |
797 | 800 | } |
798 | 801 | |
799 | 802 | /* Events passed to congestion control interface */ |
net/ipv4/tcp_input.c
... | ... | @@ -1316,12 +1316,12 @@ |
1316 | 1316 | * code can come after this skb later on it's better to keep |
1317 | 1317 | * setting gso_size to something. |
1318 | 1318 | */ |
1319 | - if (!skb_shinfo(prev)->gso_size) | |
1320 | - skb_shinfo(prev)->gso_size = mss; | |
1319 | + if (!TCP_SKB_CB(prev)->tcp_gso_size) | |
1320 | + TCP_SKB_CB(prev)->tcp_gso_size = mss; | |
1321 | 1321 | |
1322 | 1322 | /* CHECKME: To clear or not to clear? Mimics normal skb currently */ |
1323 | 1323 | if (tcp_skb_pcount(skb) <= 1) |
1324 | - skb_shinfo(skb)->gso_size = 0; | |
1324 | + TCP_SKB_CB(skb)->tcp_gso_size = 0; | |
1325 | 1325 | |
1326 | 1326 | /* Difference in this won't matter, both ACKed by the same cumul. ACK */ |
1327 | 1327 | TCP_SKB_CB(prev)->sacked |= (TCP_SKB_CB(skb)->sacked & TCPCB_EVER_RETRANS); |
... | ... | @@ -2248,7 +2248,7 @@ |
2248 | 2248 | (oldcnt >= packets)) |
2249 | 2249 | break; |
2250 | 2250 | |
2251 | - mss = skb_shinfo(skb)->gso_size; | |
2251 | + mss = tcp_skb_mss(skb); | |
2252 | 2252 | err = tcp_fragment(sk, skb, (packets - oldcnt) * mss, |
2253 | 2253 | mss, GFP_ATOMIC); |
2254 | 2254 | if (err < 0) |
net/ipv4/tcp_output.c
... | ... | @@ -402,8 +402,6 @@ |
402 | 402 | */ |
403 | 403 | static void tcp_init_nondata_skb(struct sk_buff *skb, u32 seq, u8 flags) |
404 | 404 | { |
405 | - struct skb_shared_info *shinfo = skb_shinfo(skb); | |
406 | - | |
407 | 405 | skb->ip_summed = CHECKSUM_PARTIAL; |
408 | 406 | skb->csum = 0; |
409 | 407 | |
... | ... | @@ -411,7 +409,6 @@ |
411 | 409 | TCP_SKB_CB(skb)->sacked = 0; |
412 | 410 | |
413 | 411 | tcp_skb_pcount_set(skb, 1); |
414 | - shinfo->gso_size = 0; | |
415 | 412 | |
416 | 413 | TCP_SKB_CB(skb)->seq = seq; |
417 | 414 | if (flags & (TCPHDR_SYN | TCPHDR_FIN)) |
418 | 415 | |
... | ... | @@ -1028,8 +1025,9 @@ |
1028 | 1025 | tcp_skb_pcount(skb)); |
1029 | 1026 | |
1030 | 1027 | tp->segs_out += tcp_skb_pcount(skb); |
1031 | - /* OK, its time to fill skb_shinfo(skb)->gso_segs */ | |
1028 | + /* OK, its time to fill skb_shinfo(skb)->gso_{segs|size} */ | |
1032 | 1029 | skb_shinfo(skb)->gso_segs = tcp_skb_pcount(skb); |
1030 | + skb_shinfo(skb)->gso_size = tcp_skb_mss(skb); | |
1033 | 1031 | |
1034 | 1032 | /* Our usage of tstamp should remain private */ |
1035 | 1033 | skb->tstamp.tv64 = 0; |
... | ... | @@ -1068,8 +1066,6 @@ |
1068 | 1066 | /* Initialize TSO segments for a packet. */ |
1069 | 1067 | static void tcp_set_skb_tso_segs(struct sk_buff *skb, unsigned int mss_now) |
1070 | 1068 | { |
1071 | - struct skb_shared_info *shinfo = skb_shinfo(skb); | |
1072 | - | |
1073 | 1069 | /* Make sure we own this skb before messing gso_size/gso_segs */ |
1074 | 1070 | WARN_ON_ONCE(skb_cloned(skb)); |
1075 | 1071 | |
1076 | 1072 | |
... | ... | @@ -1078,10 +1074,10 @@ |
1078 | 1074 | * non-TSO case. |
1079 | 1075 | */ |
1080 | 1076 | tcp_skb_pcount_set(skb, 1); |
1081 | - shinfo->gso_size = 0; | |
1077 | + TCP_SKB_CB(skb)->tcp_gso_size = 0; | |
1082 | 1078 | } else { |
1083 | 1079 | tcp_skb_pcount_set(skb, DIV_ROUND_UP(skb->len, mss_now)); |
1084 | - shinfo->gso_size = mss_now; | |
1080 | + TCP_SKB_CB(skb)->tcp_gso_size = mss_now; | |
1085 | 1081 | } |
1086 | 1082 | } |
1087 | 1083 |