diff options
author | Ilpo Järvinen <ilpo.jarvinen@helsinki.fi> | 2008-01-03 23:39:01 -0500 |
---|---|---|
committer | David S. Miller <davem@davemloft.net> | 2008-01-28 18:00:34 -0500 |
commit | e870a8efcddaaa3da7e180b6ae21239fb96aa2bb (patch) | |
tree | d7e5930e78eb1c81ac10c59e0f74b89188e8abf7 | |
parent | 19773b4923ed0e21e3289361dba5e69e1ce6e00b (diff) |
[TCP]: Perform setting of common control fields in one place
In case of segments which are purely for control without any
data (SYN/ACK/FIN/RST), many fields are set to common values
in multiple places.
i386 results:
$ gcc --version
gcc (GCC) 4.1.2 20070626 (Red Hat 4.1.2-13)
$ codiff tcp_output.o.old tcp_output.o.new
net/ipv4/tcp_output.c:
tcp_xmit_probe_skb | -48
tcp_send_ack | -56
tcp_retransmit_skb | -79
tcp_connect | -43
tcp_send_active_reset | -35
tcp_make_synack | -42
tcp_send_fin | -48
7 functions changed, 351 bytes removed
net/ipv4/tcp_output.c:
tcp_init_nondata_skb | +90
1 function changed, 90 bytes added
tcp_output.o.mid:
8 functions changed, 90 bytes added, 351 bytes removed, diff: -261
Signed-off-by: Ilpo Järvinen <ilpo.jarvinen@helsinki.fi>
Signed-off-by: David S. Miller <davem@davemloft.net>
-rw-r--r-- | net/ipv4/tcp_output.c | 91 |
1 files changed, 36 insertions, 55 deletions
diff --git a/net/ipv4/tcp_output.c b/net/ipv4/tcp_output.c index 6c7cd0a9098a..89f0188885c7 100644 --- a/net/ipv4/tcp_output.c +++ b/net/ipv4/tcp_output.c | |||
@@ -327,6 +327,26 @@ static inline void TCP_ECN_send(struct sock *sk, struct sk_buff *skb, | |||
327 | } | 327 | } |
328 | } | 328 | } |
329 | 329 | ||
330 | /* Constructs common control bits of non-data skb. If SYN/FIN is present, | ||
331 | * auto increment end seqno. | ||
332 | */ | ||
333 | static void tcp_init_nondata_skb(struct sk_buff *skb, u32 seq, u8 flags) | ||
334 | { | ||
335 | skb->csum = 0; | ||
336 | |||
337 | TCP_SKB_CB(skb)->flags = flags; | ||
338 | TCP_SKB_CB(skb)->sacked = 0; | ||
339 | |||
340 | skb_shinfo(skb)->gso_segs = 1; | ||
341 | skb_shinfo(skb)->gso_size = 0; | ||
342 | skb_shinfo(skb)->gso_type = 0; | ||
343 | |||
344 | TCP_SKB_CB(skb)->seq = seq; | ||
345 | if (flags & (TCPCB_FLAG_SYN | TCPCB_FLAG_FIN)) | ||
346 | seq++; | ||
347 | TCP_SKB_CB(skb)->end_seq = seq; | ||
348 | } | ||
349 | |||
330 | static void tcp_build_and_update_options(__be32 *ptr, struct tcp_sock *tp, | 350 | static void tcp_build_and_update_options(__be32 *ptr, struct tcp_sock *tp, |
331 | __u32 tstamp, __u8 **md5_hash) | 351 | __u32 tstamp, __u8 **md5_hash) |
332 | { | 352 | { |
@@ -1864,12 +1884,10 @@ int tcp_retransmit_skb(struct sock *sk, struct sk_buff *skb) | |||
1864 | (TCP_SKB_CB(skb)->flags & TCPCB_FLAG_FIN) && | 1884 | (TCP_SKB_CB(skb)->flags & TCPCB_FLAG_FIN) && |
1865 | tp->snd_una == (TCP_SKB_CB(skb)->end_seq - 1)) { | 1885 | tp->snd_una == (TCP_SKB_CB(skb)->end_seq - 1)) { |
1866 | if (!pskb_trim(skb, 0)) { | 1886 | if (!pskb_trim(skb, 0)) { |
1867 | TCP_SKB_CB(skb)->seq = TCP_SKB_CB(skb)->end_seq - 1; | 1887 | /* Reuse, even though it does some unnecessary work */ |
1868 | skb_shinfo(skb)->gso_segs = 1; | 1888 | tcp_init_nondata_skb(skb, TCP_SKB_CB(skb)->end_seq - 1, |
1869 | skb_shinfo(skb)->gso_size = 0; | 1889 | TCP_SKB_CB(skb)->flags); |
1870 | skb_shinfo(skb)->gso_type = 0; | ||
1871 | skb->ip_summed = CHECKSUM_NONE; | 1890 | skb->ip_summed = CHECKSUM_NONE; |
1872 | skb->csum = 0; | ||
1873 | } | 1891 | } |
1874 | } | 1892 | } |
1875 | 1893 | ||
@@ -2068,16 +2086,9 @@ void tcp_send_fin(struct sock *sk) | |||
2068 | 2086 | ||
2069 | /* Reserve space for headers and prepare control bits. */ | 2087 | /* Reserve space for headers and prepare control bits. */ |
2070 | skb_reserve(skb, MAX_TCP_HEADER); | 2088 | skb_reserve(skb, MAX_TCP_HEADER); |
2071 | skb->csum = 0; | ||
2072 | TCP_SKB_CB(skb)->flags = (TCPCB_FLAG_ACK | TCPCB_FLAG_FIN); | ||
2073 | TCP_SKB_CB(skb)->sacked = 0; | ||
2074 | skb_shinfo(skb)->gso_segs = 1; | ||
2075 | skb_shinfo(skb)->gso_size = 0; | ||
2076 | skb_shinfo(skb)->gso_type = 0; | ||
2077 | |||
2078 | /* FIN eats a sequence byte, write_seq advanced by tcp_queue_skb(). */ | 2089 | /* FIN eats a sequence byte, write_seq advanced by tcp_queue_skb(). */ |
2079 | TCP_SKB_CB(skb)->seq = tp->write_seq; | 2090 | tcp_init_nondata_skb(skb, tp->write_seq, |
2080 | TCP_SKB_CB(skb)->end_seq = TCP_SKB_CB(skb)->seq + 1; | 2091 | TCPCB_FLAG_ACK | TCPCB_FLAG_FIN); |
2081 | tcp_queue_skb(sk, skb); | 2092 | tcp_queue_skb(sk, skb); |
2082 | } | 2093 | } |
2083 | __tcp_push_pending_frames(sk, mss_now, TCP_NAGLE_OFF); | 2094 | __tcp_push_pending_frames(sk, mss_now, TCP_NAGLE_OFF); |
@@ -2101,16 +2112,9 @@ void tcp_send_active_reset(struct sock *sk, gfp_t priority) | |||
2101 | 2112 | ||
2102 | /* Reserve space for headers and prepare control bits. */ | 2113 | /* Reserve space for headers and prepare control bits. */ |
2103 | skb_reserve(skb, MAX_TCP_HEADER); | 2114 | skb_reserve(skb, MAX_TCP_HEADER); |
2104 | skb->csum = 0; | 2115 | tcp_init_nondata_skb(skb, tcp_acceptable_seq(sk), |
2105 | TCP_SKB_CB(skb)->flags = (TCPCB_FLAG_ACK | TCPCB_FLAG_RST); | 2116 | TCPCB_FLAG_ACK | TCPCB_FLAG_RST); |
2106 | TCP_SKB_CB(skb)->sacked = 0; | ||
2107 | skb_shinfo(skb)->gso_segs = 1; | ||
2108 | skb_shinfo(skb)->gso_size = 0; | ||
2109 | skb_shinfo(skb)->gso_type = 0; | ||
2110 | |||
2111 | /* Send it off. */ | 2117 | /* Send it off. */ |
2112 | TCP_SKB_CB(skb)->seq = tcp_acceptable_seq(sk); | ||
2113 | TCP_SKB_CB(skb)->end_seq = TCP_SKB_CB(skb)->seq; | ||
2114 | TCP_SKB_CB(skb)->when = tcp_time_stamp; | 2118 | TCP_SKB_CB(skb)->when = tcp_time_stamp; |
2115 | if (tcp_transmit_skb(sk, skb, 0, priority)) | 2119 | if (tcp_transmit_skb(sk, skb, 0, priority)) |
2116 | NET_INC_STATS(LINUX_MIB_TCPABORTFAILED); | 2120 | NET_INC_STATS(LINUX_MIB_TCPABORTFAILED); |
@@ -2198,12 +2202,11 @@ struct sk_buff *tcp_make_synack(struct sock *sk, struct dst_entry *dst, | |||
2198 | TCP_ECN_make_synack(req, th); | 2202 | TCP_ECN_make_synack(req, th); |
2199 | th->source = inet_sk(sk)->sport; | 2203 | th->source = inet_sk(sk)->sport; |
2200 | th->dest = ireq->rmt_port; | 2204 | th->dest = ireq->rmt_port; |
2201 | TCP_SKB_CB(skb)->seq = tcp_rsk(req)->snt_isn; | 2205 | /* Setting of flags are superfluous here for callers (and ECE is |
2202 | TCP_SKB_CB(skb)->end_seq = TCP_SKB_CB(skb)->seq + 1; | 2206 | * not even correctly set) |
2203 | TCP_SKB_CB(skb)->sacked = 0; | 2207 | */ |
2204 | skb_shinfo(skb)->gso_segs = 1; | 2208 | tcp_init_nondata_skb(skb, tcp_rsk(req)->snt_isn, |
2205 | skb_shinfo(skb)->gso_size = 0; | 2209 | TCPCB_FLAG_SYN | TCPCB_FLAG_ACK); |
2206 | skb_shinfo(skb)->gso_type = 0; | ||
2207 | th->seq = htonl(TCP_SKB_CB(skb)->seq); | 2210 | th->seq = htonl(TCP_SKB_CB(skb)->seq); |
2208 | th->ack_seq = htonl(tcp_rsk(req)->rcv_isn + 1); | 2211 | th->ack_seq = htonl(tcp_rsk(req)->rcv_isn + 1); |
2209 | if (req->rcv_wnd == 0) { /* ignored for retransmitted syns */ | 2212 | if (req->rcv_wnd == 0) { /* ignored for retransmitted syns */ |
@@ -2235,7 +2238,6 @@ struct sk_buff *tcp_make_synack(struct sock *sk, struct dst_entry *dst, | |||
2235 | NULL) | 2238 | NULL) |
2236 | ); | 2239 | ); |
2237 | 2240 | ||
2238 | skb->csum = 0; | ||
2239 | th->doff = (tcp_header_size >> 2); | 2241 | th->doff = (tcp_header_size >> 2); |
2240 | TCP_INC_STATS(TCP_MIB_OUTSEGS); | 2242 | TCP_INC_STATS(TCP_MIB_OUTSEGS); |
2241 | 2243 | ||
@@ -2327,16 +2329,9 @@ int tcp_connect(struct sock *sk) | |||
2327 | /* Reserve space for headers. */ | 2329 | /* Reserve space for headers. */ |
2328 | skb_reserve(buff, MAX_TCP_HEADER); | 2330 | skb_reserve(buff, MAX_TCP_HEADER); |
2329 | 2331 | ||
2330 | TCP_SKB_CB(buff)->flags = TCPCB_FLAG_SYN; | ||
2331 | TCP_ECN_send_syn(sk, buff); | ||
2332 | TCP_SKB_CB(buff)->sacked = 0; | ||
2333 | skb_shinfo(buff)->gso_segs = 1; | ||
2334 | skb_shinfo(buff)->gso_size = 0; | ||
2335 | skb_shinfo(buff)->gso_type = 0; | ||
2336 | buff->csum = 0; | ||
2337 | tp->snd_nxt = tp->write_seq; | 2332 | tp->snd_nxt = tp->write_seq; |
2338 | TCP_SKB_CB(buff)->seq = tp->write_seq++; | 2333 | tcp_init_nondata_skb(buff, tp->write_seq++, TCPCB_FLAG_SYN); |
2339 | TCP_SKB_CB(buff)->end_seq = tp->write_seq; | 2334 | TCP_ECN_send_syn(sk, buff); |
2340 | 2335 | ||
2341 | /* Send it off. */ | 2336 | /* Send it off. */ |
2342 | TCP_SKB_CB(buff)->when = tcp_time_stamp; | 2337 | TCP_SKB_CB(buff)->when = tcp_time_stamp; |
@@ -2441,15 +2436,9 @@ void tcp_send_ack(struct sock *sk) | |||
2441 | 2436 | ||
2442 | /* Reserve space for headers and prepare control bits. */ | 2437 | /* Reserve space for headers and prepare control bits. */ |
2443 | skb_reserve(buff, MAX_TCP_HEADER); | 2438 | skb_reserve(buff, MAX_TCP_HEADER); |
2444 | buff->csum = 0; | 2439 | tcp_init_nondata_skb(buff, tcp_acceptable_seq(sk), TCPCB_FLAG_ACK); |
2445 | TCP_SKB_CB(buff)->flags = TCPCB_FLAG_ACK; | ||
2446 | TCP_SKB_CB(buff)->sacked = 0; | ||
2447 | skb_shinfo(buff)->gso_segs = 1; | ||
2448 | skb_shinfo(buff)->gso_size = 0; | ||
2449 | skb_shinfo(buff)->gso_type = 0; | ||
2450 | 2440 | ||
2451 | /* Send it off, this clears delayed acks for us. */ | 2441 | /* Send it off, this clears delayed acks for us. */ |
2452 | TCP_SKB_CB(buff)->seq = TCP_SKB_CB(buff)->end_seq = tcp_acceptable_seq(sk); | ||
2453 | TCP_SKB_CB(buff)->when = tcp_time_stamp; | 2442 | TCP_SKB_CB(buff)->when = tcp_time_stamp; |
2454 | tcp_transmit_skb(sk, buff, 0, GFP_ATOMIC); | 2443 | tcp_transmit_skb(sk, buff, 0, GFP_ATOMIC); |
2455 | } | 2444 | } |
@@ -2477,19 +2466,11 @@ static int tcp_xmit_probe_skb(struct sock *sk, int urgent) | |||
2477 | 2466 | ||
2478 | /* Reserve space for headers and set control bits. */ | 2467 | /* Reserve space for headers and set control bits. */ |
2479 | skb_reserve(skb, MAX_TCP_HEADER); | 2468 | skb_reserve(skb, MAX_TCP_HEADER); |
2480 | skb->csum = 0; | ||
2481 | TCP_SKB_CB(skb)->flags = TCPCB_FLAG_ACK; | ||
2482 | TCP_SKB_CB(skb)->sacked = 0; | ||
2483 | skb_shinfo(skb)->gso_segs = 1; | ||
2484 | skb_shinfo(skb)->gso_size = 0; | ||
2485 | skb_shinfo(skb)->gso_type = 0; | ||
2486 | |||
2487 | /* Use a previous sequence. This should cause the other | 2469 | /* Use a previous sequence. This should cause the other |
2488 | * end to send an ack. Don't queue or clone SKB, just | 2470 | * end to send an ack. Don't queue or clone SKB, just |
2489 | * send it. | 2471 | * send it. |
2490 | */ | 2472 | */ |
2491 | TCP_SKB_CB(skb)->seq = tp->snd_una - !urgent; | 2473 | tcp_init_nondata_skb(skb, tp->snd_una - !urgent, TCPCB_FLAG_ACK); |
2492 | TCP_SKB_CB(skb)->end_seq = TCP_SKB_CB(skb)->seq; | ||
2493 | TCP_SKB_CB(skb)->when = tcp_time_stamp; | 2474 | TCP_SKB_CB(skb)->when = tcp_time_stamp; |
2494 | return tcp_transmit_skb(sk, skb, 0, GFP_ATOMIC); | 2475 | return tcp_transmit_skb(sk, skb, 0, GFP_ATOMIC); |
2495 | } | 2476 | } |