aboutsummaryrefslogtreecommitdiffstats
path: root/net
diff options
context:
space:
mode:
authorEric Dumazet <edumazet@google.com>2016-05-13 12:16:40 -0400
committerDavid S. Miller <davem@davemloft.net>2016-05-16 13:46:23 -0400
commitea1627c20c3462168a087ccecc69084b55b9c0b2 (patch)
treee0b21e3af57979d1f5b1faf718582aaa4a6566b0 /net
parent5022524308c64f2954ac206a8781b64a98cddf00 (diff)
tcp: minor optimizations around tcp_hdr() usage
tcp_hdr() is slightly more expensive than using skb->data in contexts where we know they point to the same byte. In receive path, tcp_v4_rcv() and tcp_v6_rcv() are in this situation, as tcp header has not been pulled yet. In output path, the same can be said when we just pushed the tcp header in the skb, in tcp_transmit_skb() and tcp_make_synack() Also factorize the two checks for tcb->tcp_flags & TCPHDR_SYN in tcp_transmit_skb() and pass tcp header pointer to tcp_ecn_send(), so that compiler can further optimize and avoid a reload. Signed-off-by: Eric Dumazet <edumazet@google.com> Signed-off-by: David S. Miller <davem@davemloft.net>
Diffstat (limited to 'net')
-rw-r--r--net/ipv4/tcp_ipv4.c6
-rw-r--r--net/ipv4/tcp_output.c30
-rw-r--r--net/ipv6/tcp_ipv6.c6
3 files changed, 20 insertions, 22 deletions
diff --git a/net/ipv4/tcp_ipv4.c b/net/ipv4/tcp_ipv4.c
index 8219d0d8dc83..3708de2a6683 100644
--- a/net/ipv4/tcp_ipv4.c
+++ b/net/ipv4/tcp_ipv4.c
@@ -1556,9 +1556,9 @@ int tcp_v4_rcv(struct sk_buff *skb)
1556 if (!pskb_may_pull(skb, sizeof(struct tcphdr))) 1556 if (!pskb_may_pull(skb, sizeof(struct tcphdr)))
1557 goto discard_it; 1557 goto discard_it;
1558 1558
1559 th = tcp_hdr(skb); 1559 th = (const struct tcphdr *)skb->data;
1560 1560
1561 if (th->doff < sizeof(struct tcphdr) / 4) 1561 if (unlikely(th->doff < sizeof(struct tcphdr) / 4))
1562 goto bad_packet; 1562 goto bad_packet;
1563 if (!pskb_may_pull(skb, th->doff * 4)) 1563 if (!pskb_may_pull(skb, th->doff * 4))
1564 goto discard_it; 1564 goto discard_it;
@@ -1571,7 +1571,7 @@ int tcp_v4_rcv(struct sk_buff *skb)
1571 if (skb_checksum_init(skb, IPPROTO_TCP, inet_compute_pseudo)) 1571 if (skb_checksum_init(skb, IPPROTO_TCP, inet_compute_pseudo))
1572 goto csum_error; 1572 goto csum_error;
1573 1573
1574 th = tcp_hdr(skb); 1574 th = (const struct tcphdr *)skb->data;
1575 iph = ip_hdr(skb); 1575 iph = ip_hdr(skb);
1576 /* This is tricky : We move IPCB at its correct location into TCP_SKB_CB() 1576 /* This is tricky : We move IPCB at its correct location into TCP_SKB_CB()
1577 * barrier() makes sure compiler wont play fool^Waliasing games. 1577 * barrier() makes sure compiler wont play fool^Waliasing games.
diff --git a/net/ipv4/tcp_output.c b/net/ipv4/tcp_output.c
index b69d84e7a97d..8bd9911fdd16 100644
--- a/net/ipv4/tcp_output.c
+++ b/net/ipv4/tcp_output.c
@@ -364,7 +364,7 @@ tcp_ecn_make_synack(const struct request_sock *req, struct tcphdr *th)
364 * be sent. 364 * be sent.
365 */ 365 */
366static void tcp_ecn_send(struct sock *sk, struct sk_buff *skb, 366static void tcp_ecn_send(struct sock *sk, struct sk_buff *skb,
367 int tcp_header_len) 367 struct tcphdr *th, int tcp_header_len)
368{ 368{
369 struct tcp_sock *tp = tcp_sk(sk); 369 struct tcp_sock *tp = tcp_sk(sk);
370 370
@@ -375,7 +375,7 @@ static void tcp_ecn_send(struct sock *sk, struct sk_buff *skb,
375 INET_ECN_xmit(sk); 375 INET_ECN_xmit(sk);
376 if (tp->ecn_flags & TCP_ECN_QUEUE_CWR) { 376 if (tp->ecn_flags & TCP_ECN_QUEUE_CWR) {
377 tp->ecn_flags &= ~TCP_ECN_QUEUE_CWR; 377 tp->ecn_flags &= ~TCP_ECN_QUEUE_CWR;
378 tcp_hdr(skb)->cwr = 1; 378 th->cwr = 1;
379 skb_shinfo(skb)->gso_type |= SKB_GSO_TCP_ECN; 379 skb_shinfo(skb)->gso_type |= SKB_GSO_TCP_ECN;
380 } 380 }
381 } else if (!tcp_ca_needs_ecn(sk)) { 381 } else if (!tcp_ca_needs_ecn(sk)) {
@@ -383,7 +383,7 @@ static void tcp_ecn_send(struct sock *sk, struct sk_buff *skb,
383 INET_ECN_dontxmit(sk); 383 INET_ECN_dontxmit(sk);
384 } 384 }
385 if (tp->ecn_flags & TCP_ECN_DEMAND_CWR) 385 if (tp->ecn_flags & TCP_ECN_DEMAND_CWR)
386 tcp_hdr(skb)->ece = 1; 386 th->ece = 1;
387 } 387 }
388} 388}
389 389
@@ -954,7 +954,7 @@ static int tcp_transmit_skb(struct sock *sk, struct sk_buff *skb, int clone_it,
954 atomic_add(skb->truesize, &sk->sk_wmem_alloc); 954 atomic_add(skb->truesize, &sk->sk_wmem_alloc);
955 955
956 /* Build TCP header and checksum it. */ 956 /* Build TCP header and checksum it. */
957 th = tcp_hdr(skb); 957 th = (struct tcphdr *)skb->data;
958 th->source = inet->inet_sport; 958 th->source = inet->inet_sport;
959 th->dest = inet->inet_dport; 959 th->dest = inet->inet_dport;
960 th->seq = htonl(tcb->seq); 960 th->seq = htonl(tcb->seq);
@@ -962,14 +962,6 @@ static int tcp_transmit_skb(struct sock *sk, struct sk_buff *skb, int clone_it,
962 *(((__be16 *)th) + 6) = htons(((tcp_header_size >> 2) << 12) | 962 *(((__be16 *)th) + 6) = htons(((tcp_header_size >> 2) << 12) |
963 tcb->tcp_flags); 963 tcb->tcp_flags);
964 964
965 if (unlikely(tcb->tcp_flags & TCPHDR_SYN)) {
966 /* RFC1323: The window in SYN & SYN/ACK segments
967 * is never scaled.
968 */
969 th->window = htons(min(tp->rcv_wnd, 65535U));
970 } else {
971 th->window = htons(tcp_select_window(sk));
972 }
973 th->check = 0; 965 th->check = 0;
974 th->urg_ptr = 0; 966 th->urg_ptr = 0;
975 967
@@ -986,9 +978,15 @@ static int tcp_transmit_skb(struct sock *sk, struct sk_buff *skb, int clone_it,
986 978
987 tcp_options_write((__be32 *)(th + 1), tp, &opts); 979 tcp_options_write((__be32 *)(th + 1), tp, &opts);
988 skb_shinfo(skb)->gso_type = sk->sk_gso_type; 980 skb_shinfo(skb)->gso_type = sk->sk_gso_type;
989 if (likely((tcb->tcp_flags & TCPHDR_SYN) == 0)) 981 if (likely(!(tcb->tcp_flags & TCPHDR_SYN))) {
990 tcp_ecn_send(sk, skb, tcp_header_size); 982 th->window = htons(tcp_select_window(sk));
991 983 tcp_ecn_send(sk, skb, th, tcp_header_size);
984 } else {
985 /* RFC1323: The window in SYN & SYN/ACK segments
986 * is never scaled.
987 */
988 th->window = htons(min(tp->rcv_wnd, 65535U));
989 }
992#ifdef CONFIG_TCP_MD5SIG 990#ifdef CONFIG_TCP_MD5SIG
993 /* Calculate the MD5 hash, as we have all we need now */ 991 /* Calculate the MD5 hash, as we have all we need now */
994 if (md5) { 992 if (md5) {
@@ -3040,7 +3038,7 @@ struct sk_buff *tcp_make_synack(const struct sock *sk, struct dst_entry *dst,
3040 skb_push(skb, tcp_header_size); 3038 skb_push(skb, tcp_header_size);
3041 skb_reset_transport_header(skb); 3039 skb_reset_transport_header(skb);
3042 3040
3043 th = tcp_hdr(skb); 3041 th = (struct tcphdr *)skb->data;
3044 memset(th, 0, sizeof(struct tcphdr)); 3042 memset(th, 0, sizeof(struct tcphdr));
3045 th->syn = 1; 3043 th->syn = 1;
3046 th->ack = 1; 3044 th->ack = 1;
diff --git a/net/ipv6/tcp_ipv6.c b/net/ipv6/tcp_ipv6.c
index c4efaa97280c..79e33e02f11a 100644
--- a/net/ipv6/tcp_ipv6.c
+++ b/net/ipv6/tcp_ipv6.c
@@ -1369,9 +1369,9 @@ static int tcp_v6_rcv(struct sk_buff *skb)
1369 if (!pskb_may_pull(skb, sizeof(struct tcphdr))) 1369 if (!pskb_may_pull(skb, sizeof(struct tcphdr)))
1370 goto discard_it; 1370 goto discard_it;
1371 1371
1372 th = tcp_hdr(skb); 1372 th = (const struct tcphdr *)skb->data;
1373 1373
1374 if (th->doff < sizeof(struct tcphdr)/4) 1374 if (unlikely(th->doff < sizeof(struct tcphdr)/4))
1375 goto bad_packet; 1375 goto bad_packet;
1376 if (!pskb_may_pull(skb, th->doff*4)) 1376 if (!pskb_may_pull(skb, th->doff*4))
1377 goto discard_it; 1377 goto discard_it;
@@ -1379,7 +1379,7 @@ static int tcp_v6_rcv(struct sk_buff *skb)
1379 if (skb_checksum_init(skb, IPPROTO_TCP, ip6_compute_pseudo)) 1379 if (skb_checksum_init(skb, IPPROTO_TCP, ip6_compute_pseudo))
1380 goto csum_error; 1380 goto csum_error;
1381 1381
1382 th = tcp_hdr(skb); 1382 th = (const struct tcphdr *)skb->data;
1383 hdr = ipv6_hdr(skb); 1383 hdr = ipv6_hdr(skb);
1384 1384
1385lookup: 1385lookup: