diff options
author | Eric Dumazet <edumazet@google.com> | 2014-09-24 07:11:22 -0400 |
---|---|---|
committer | David S. Miller <davem@davemloft.net> | 2014-09-28 16:36:48 -0400 |
commit | cd7d8498c9a5d510c64db38d9f4f4fbc41790f09 (patch) | |
tree | 4057e715ca8227a081db71f1ec1359011c5c1a00 /include/net/tcp.h | |
parent | dc83d4d8f6c897022c974a00769b7a6efee6aed8 (diff) |
tcp: change tcp_skb_pcount() location
Our goal is to access no more than one cache line access per skb in
a write or receive queue when doing the various walks.
After recent TCP_SKB_CB() reorganizations, it is almost done.
Last part is tcp_skb_pcount() which currently uses
skb_shinfo(skb)->gso_segs, which is a terrible choice, because it needs
3 cache lines in current kernel (skb->head, skb->end, and
shinfo->gso_segs are all in 3 different cache lines, far from skb->cb)
This very simple patch reuses space currently taken by tcp_tw_isn
only in input path, as tcp_skb_pcount is only needed for skb stored in
write queue.
This considerably speeds up tcp_ack(), granted we avoid shinfo->tx_flags
to get SKBTX_ACK_TSTAMP, which seems possible.
This also speeds up all sack processing in general.
This speeds up tcp_sendmsg() because it no longer has to access/dirty
shinfo.
Signed-off-by: Eric Dumazet <edumazet@google.com>
Signed-off-by: David S. Miller <davem@davemloft.net>
Diffstat (limited to 'include/net/tcp.h')
-rw-r--r-- | include/net/tcp.h | 23 |
1 files changed, 21 insertions, 2 deletions
diff --git a/include/net/tcp.h b/include/net/tcp.h index 4dc6641ee990..02a9a2c366bf 100644 --- a/include/net/tcp.h +++ b/include/net/tcp.h | |||
@@ -698,7 +698,16 @@ static inline u32 tcp_skb_timestamp(const struct sk_buff *skb) | |||
698 | struct tcp_skb_cb { | 698 | struct tcp_skb_cb { |
699 | __u32 seq; /* Starting sequence number */ | 699 | __u32 seq; /* Starting sequence number */ |
700 | __u32 end_seq; /* SEQ + FIN + SYN + datalen */ | 700 | __u32 end_seq; /* SEQ + FIN + SYN + datalen */ |
701 | __u32 tcp_tw_isn; /* isn chosen by tcp_timewait_state_process() */ | 701 | union { |
702 | /* Note : tcp_tw_isn is used in input path only | ||
703 | * (isn chosen by tcp_timewait_state_process()) | ||
704 | * | ||
705 | * tcp_gso_segs is used in write queue only, | ||
706 | * cf tcp_skb_pcount() | ||
707 | */ | ||
708 | __u32 tcp_tw_isn; | ||
709 | __u32 tcp_gso_segs; | ||
710 | }; | ||
702 | __u8 tcp_flags; /* TCP header flags. (tcp[13]) */ | 711 | __u8 tcp_flags; /* TCP header flags. (tcp[13]) */ |
703 | 712 | ||
704 | __u8 sacked; /* State flags for SACK/FACK. */ | 713 | __u8 sacked; /* State flags for SACK/FACK. */ |
@@ -746,7 +755,17 @@ TCP_ECN_create_request(struct request_sock *req, const struct sk_buff *skb, | |||
746 | */ | 755 | */ |
747 | static inline int tcp_skb_pcount(const struct sk_buff *skb) | 756 | static inline int tcp_skb_pcount(const struct sk_buff *skb) |
748 | { | 757 | { |
749 | return skb_shinfo(skb)->gso_segs; | 758 | return TCP_SKB_CB(skb)->tcp_gso_segs; |
759 | } | ||
760 | |||
761 | static inline void tcp_skb_pcount_set(struct sk_buff *skb, int segs) | ||
762 | { | ||
763 | TCP_SKB_CB(skb)->tcp_gso_segs = segs; | ||
764 | } | ||
765 | |||
766 | static inline void tcp_skb_pcount_add(struct sk_buff *skb, int segs) | ||
767 | { | ||
768 | TCP_SKB_CB(skb)->tcp_gso_segs += segs; | ||
750 | } | 769 | } |
751 | 770 | ||
752 | /* This is valid iff tcp_skb_pcount() > 1. */ | 771 | /* This is valid iff tcp_skb_pcount() > 1. */ |