aboutsummaryrefslogtreecommitdiffstats
path: root/include/net
diff options
context:
space:
mode:
authorMichael Chan <mchan@broadcom.com>2006-06-29 15:30:00 -0400
committerDavid S. Miller <davem@sunset.davemloft.net>2006-06-29 19:58:08 -0400
commitb0da8537037f337103348f239ad901477e907aa8 (patch)
tree498a5dceb0d536fa54dcf4acc26ae1d1b43dfaf1 /include/net
parent877ce7c1b3afd69a9b1caeb1b9964c992641f52a (diff)
[NET]: Add ECN support for TSO
In the current TSO implementation, NETIF_F_TSO and ECN cannot be turned on together in a TCP connection. The problem is that most hardware that supports TSO does not handle CWR correctly if it is set in the TSO packet. Correct handling requires CWR to be set in the first packet only if it is set in the TSO header. This patch adds the ability to turn on NETIF_F_TSO and ECN using GSO if necessary to handle TSO packets with CWR set. Hardware that handles CWR correctly can turn on NETIF_F_TSO_ECN in the dev-> features flag. All TSO packets with CWR set will have the SKB_GSO_TCPV4_ECN set. If the output device does not have the NETIF_F_TSO_ECN feature set, GSO will split the packet up correctly with CWR only set in the first segment. With help from Herbert Xu <herbert@gondor.apana.org.au>. Since ECN can always be enabled with TSO, the SOCK_NO_LARGESEND sock flag is completely removed. Signed-off-by: Michael Chan <mchan@broadcom.com> Signed-off-by: David S. Miller <davem@davemloft.net>
Diffstat (limited to 'include/net')
-rw-r--r--include/net/sock.h3
-rw-r--r--include/net/tcp_ecn.h6
2 files changed, 5 insertions, 4 deletions
diff --git a/include/net/sock.h b/include/net/sock.h
index 2d8d6adf1616..7136bae48c2f 100644
--- a/include/net/sock.h
+++ b/include/net/sock.h
@@ -383,7 +383,6 @@ enum sock_flags {
383 SOCK_USE_WRITE_QUEUE, /* whether to call sk->sk_write_space in sock_wfree */ 383 SOCK_USE_WRITE_QUEUE, /* whether to call sk->sk_write_space in sock_wfree */
384 SOCK_DBG, /* %SO_DEBUG setting */ 384 SOCK_DBG, /* %SO_DEBUG setting */
385 SOCK_RCVTSTAMP, /* %SO_TIMESTAMP setting */ 385 SOCK_RCVTSTAMP, /* %SO_TIMESTAMP setting */
386 SOCK_NO_LARGESEND, /* whether to sent large segments or not */
387 SOCK_LOCALROUTE, /* route locally only, %SO_DONTROUTE setting */ 386 SOCK_LOCALROUTE, /* route locally only, %SO_DONTROUTE setting */
388 SOCK_QUEUE_SHRUNK, /* write queue has been shrunk recently */ 387 SOCK_QUEUE_SHRUNK, /* write queue has been shrunk recently */
389}; 388};
@@ -1033,7 +1032,7 @@ static inline void sk_setup_caps(struct sock *sk, struct dst_entry *dst)
1033 if (sk->sk_route_caps & NETIF_F_GSO) 1032 if (sk->sk_route_caps & NETIF_F_GSO)
1034 sk->sk_route_caps |= NETIF_F_TSO; 1033 sk->sk_route_caps |= NETIF_F_TSO;
1035 if (sk->sk_route_caps & NETIF_F_TSO) { 1034 if (sk->sk_route_caps & NETIF_F_TSO) {
1036 if (sock_flag(sk, SOCK_NO_LARGESEND) || dst->header_len) 1035 if (dst->header_len)
1037 sk->sk_route_caps &= ~NETIF_F_TSO; 1036 sk->sk_route_caps &= ~NETIF_F_TSO;
1038 else 1037 else
1039 sk->sk_route_caps |= NETIF_F_SG | NETIF_F_HW_CSUM; 1038 sk->sk_route_caps |= NETIF_F_SG | NETIF_F_HW_CSUM;
diff --git a/include/net/tcp_ecn.h b/include/net/tcp_ecn.h
index c6b84397448d..7bb366f70934 100644
--- a/include/net/tcp_ecn.h
+++ b/include/net/tcp_ecn.h
@@ -31,10 +31,9 @@ static inline void TCP_ECN_send_syn(struct sock *sk, struct tcp_sock *tp,
31 struct sk_buff *skb) 31 struct sk_buff *skb)
32{ 32{
33 tp->ecn_flags = 0; 33 tp->ecn_flags = 0;
34 if (sysctl_tcp_ecn && !(sk->sk_route_caps & NETIF_F_TSO)) { 34 if (sysctl_tcp_ecn) {
35 TCP_SKB_CB(skb)->flags |= TCPCB_FLAG_ECE|TCPCB_FLAG_CWR; 35 TCP_SKB_CB(skb)->flags |= TCPCB_FLAG_ECE|TCPCB_FLAG_CWR;
36 tp->ecn_flags = TCP_ECN_OK; 36 tp->ecn_flags = TCP_ECN_OK;
37 sock_set_flag(sk, SOCK_NO_LARGESEND);
38 } 37 }
39} 38}
40 39
@@ -56,6 +55,9 @@ static inline void TCP_ECN_send(struct sock *sk, struct tcp_sock *tp,
56 if (tp->ecn_flags&TCP_ECN_QUEUE_CWR) { 55 if (tp->ecn_flags&TCP_ECN_QUEUE_CWR) {
57 tp->ecn_flags &= ~TCP_ECN_QUEUE_CWR; 56 tp->ecn_flags &= ~TCP_ECN_QUEUE_CWR;
58 skb->h.th->cwr = 1; 57 skb->h.th->cwr = 1;
58 if (skb_shinfo(skb)->gso_type & SKB_GSO_TCPV4)
59 skb_shinfo(skb)->gso_type |=
60 SKB_GSO_TCPV4_ECN;
59 } 61 }
60 } else { 62 } else {
61 /* ACK or retransmitted segment: clear ECT|CE */ 63 /* ACK or retransmitted segment: clear ECT|CE */