aboutsummaryrefslogtreecommitdiffstats
path: root/net
diff options
context:
space:
mode:
authorHerbert Xu <herbert@gondor.apana.org.au>2006-06-22 05:40:14 -0400
committerDavid S. Miller <davem@sunset.davemloft.net>2006-06-23 05:07:29 -0400
commit7967168cefdbc63bf332d6b1548eca7cd65ebbcc (patch)
treec45759149ae0acdc89d746e556a0ae278d11776d /net
parentd4828d85d188dc70ed172802e798d3978bb6e29e (diff)
[NET]: Merge TSO/UFO fields in sk_buff
Having separate fields in sk_buff for TSO/UFO (tso_size/ufo_size) is not going to scale if we add any more segmentation methods (e.g., DCCP). So let's merge them. They were used to tell the protocol of a packet. This function has been subsumed by the new gso_type field. This is essentially a set of netdev feature bits (shifted by 16 bits) that are required to process a specific skb. As such it's easy to tell whether a given device can process a GSO skb: you just have to and the gso_type field and the netdev's features field. I've made gso_type a conjunction. The idea is that you have a base type (e.g., SKB_GSO_TCPV4) that can be modified further to support new features. For example, if we add a hardware TSO type that supports ECN, they would declare NETIF_F_TSO | NETIF_F_TSO_ECN. All TSO packets with CWR set would have a gso_type of SKB_GSO_TCPV4 | SKB_GSO_TCPV4_ECN while all other TSO packets would be SKB_GSO_TCPV4. This means that only the CWR packets need to be emulated in software. Signed-off-by: Herbert Xu <herbert@gondor.apana.org.au> Signed-off-by: David S. Miller <davem@davemloft.net>
Diffstat (limited to 'net')
-rw-r--r--net/bridge/br_forward.c4
-rw-r--r--net/bridge/br_netfilter.c2
-rw-r--r--net/core/skbuff.c16
-rw-r--r--net/ipv4/ip_output.c16
-rw-r--r--net/ipv4/tcp.c4
-rw-r--r--net/ipv4/tcp_input.c2
-rw-r--r--net/ipv4/tcp_output.c47
-rw-r--r--net/ipv6/ip6_output.c7
8 files changed, 56 insertions, 42 deletions
diff --git a/net/bridge/br_forward.c b/net/bridge/br_forward.c
index 0dca027ceb80..8be9f2123e54 100644
--- a/net/bridge/br_forward.c
+++ b/net/bridge/br_forward.c
@@ -34,8 +34,8 @@ static inline unsigned packet_length(const struct sk_buff *skb)
34 34
35int br_dev_queue_push_xmit(struct sk_buff *skb) 35int br_dev_queue_push_xmit(struct sk_buff *skb)
36{ 36{
37 /* drop mtu oversized packets except tso */ 37 /* drop mtu oversized packets except gso */
38 if (packet_length(skb) > skb->dev->mtu && !skb_shinfo(skb)->tso_size) 38 if (packet_length(skb) > skb->dev->mtu && !skb_shinfo(skb)->gso_size)
39 kfree_skb(skb); 39 kfree_skb(skb);
40 else { 40 else {
41#ifdef CONFIG_BRIDGE_NETFILTER 41#ifdef CONFIG_BRIDGE_NETFILTER
diff --git a/net/bridge/br_netfilter.c b/net/bridge/br_netfilter.c
index 3e41f9d6d51c..8298a5179aef 100644
--- a/net/bridge/br_netfilter.c
+++ b/net/bridge/br_netfilter.c
@@ -761,7 +761,7 @@ static int br_nf_dev_queue_xmit(struct sk_buff *skb)
761{ 761{
762 if (skb->protocol == htons(ETH_P_IP) && 762 if (skb->protocol == htons(ETH_P_IP) &&
763 skb->len > skb->dev->mtu && 763 skb->len > skb->dev->mtu &&
764 !(skb_shinfo(skb)->ufo_size || skb_shinfo(skb)->tso_size)) 764 !skb_shinfo(skb)->gso_size)
765 return ip_fragment(skb, br_dev_queue_push_xmit); 765 return ip_fragment(skb, br_dev_queue_push_xmit);
766 else 766 else
767 return br_dev_queue_push_xmit(skb); 767 return br_dev_queue_push_xmit(skb);
diff --git a/net/core/skbuff.c b/net/core/skbuff.c
index fe63d4efbd4d..368d98578c14 100644
--- a/net/core/skbuff.c
+++ b/net/core/skbuff.c
@@ -172,9 +172,9 @@ struct sk_buff *__alloc_skb(unsigned int size, gfp_t gfp_mask,
172 shinfo = skb_shinfo(skb); 172 shinfo = skb_shinfo(skb);
173 atomic_set(&shinfo->dataref, 1); 173 atomic_set(&shinfo->dataref, 1);
174 shinfo->nr_frags = 0; 174 shinfo->nr_frags = 0;
175 shinfo->tso_size = 0; 175 shinfo->gso_size = 0;
176 shinfo->tso_segs = 0; 176 shinfo->gso_segs = 0;
177 shinfo->ufo_size = 0; 177 shinfo->gso_type = 0;
178 shinfo->ip6_frag_id = 0; 178 shinfo->ip6_frag_id = 0;
179 shinfo->frag_list = NULL; 179 shinfo->frag_list = NULL;
180 180
@@ -238,8 +238,9 @@ struct sk_buff *alloc_skb_from_cache(kmem_cache_t *cp,
238 238
239 atomic_set(&(skb_shinfo(skb)->dataref), 1); 239 atomic_set(&(skb_shinfo(skb)->dataref), 1);
240 skb_shinfo(skb)->nr_frags = 0; 240 skb_shinfo(skb)->nr_frags = 0;
241 skb_shinfo(skb)->tso_size = 0; 241 skb_shinfo(skb)->gso_size = 0;
242 skb_shinfo(skb)->tso_segs = 0; 242 skb_shinfo(skb)->gso_segs = 0;
243 skb_shinfo(skb)->gso_type = 0;
243 skb_shinfo(skb)->frag_list = NULL; 244 skb_shinfo(skb)->frag_list = NULL;
244out: 245out:
245 return skb; 246 return skb;
@@ -528,8 +529,9 @@ static void copy_skb_header(struct sk_buff *new, const struct sk_buff *old)
528#endif 529#endif
529 skb_copy_secmark(new, old); 530 skb_copy_secmark(new, old);
530 atomic_set(&new->users, 1); 531 atomic_set(&new->users, 1);
531 skb_shinfo(new)->tso_size = skb_shinfo(old)->tso_size; 532 skb_shinfo(new)->gso_size = skb_shinfo(old)->gso_size;
532 skb_shinfo(new)->tso_segs = skb_shinfo(old)->tso_segs; 533 skb_shinfo(new)->gso_segs = skb_shinfo(old)->gso_segs;
534 skb_shinfo(new)->gso_type = skb_shinfo(old)->gso_type;
533} 535}
534 536
535/** 537/**
diff --git a/net/ipv4/ip_output.c b/net/ipv4/ip_output.c
index 8538aac3d148..7624fd1d8f9f 100644
--- a/net/ipv4/ip_output.c
+++ b/net/ipv4/ip_output.c
@@ -210,8 +210,7 @@ static inline int ip_finish_output(struct sk_buff *skb)
210 return dst_output(skb); 210 return dst_output(skb);
211 } 211 }
212#endif 212#endif
213 if (skb->len > dst_mtu(skb->dst) && 213 if (skb->len > dst_mtu(skb->dst) && !skb_shinfo(skb)->gso_size)
214 !(skb_shinfo(skb)->ufo_size || skb_shinfo(skb)->tso_size))
215 return ip_fragment(skb, ip_finish_output2); 214 return ip_fragment(skb, ip_finish_output2);
216 else 215 else
217 return ip_finish_output2(skb); 216 return ip_finish_output2(skb);
@@ -362,7 +361,7 @@ packet_routed:
362 } 361 }
363 362
364 ip_select_ident_more(iph, &rt->u.dst, sk, 363 ip_select_ident_more(iph, &rt->u.dst, sk,
365 (skb_shinfo(skb)->tso_segs ?: 1) - 1); 364 (skb_shinfo(skb)->gso_segs ?: 1) - 1);
366 365
367 /* Add an IP checksum. */ 366 /* Add an IP checksum. */
368 ip_send_check(iph); 367 ip_send_check(iph);
@@ -744,7 +743,8 @@ static inline int ip_ufo_append_data(struct sock *sk,
744 (length - transhdrlen)); 743 (length - transhdrlen));
745 if (!err) { 744 if (!err) {
746 /* specify the length of each IP datagram fragment*/ 745 /* specify the length of each IP datagram fragment*/
747 skb_shinfo(skb)->ufo_size = (mtu - fragheaderlen); 746 skb_shinfo(skb)->gso_size = mtu - fragheaderlen;
747 skb_shinfo(skb)->gso_type = SKB_GSO_UDPV4;
748 __skb_queue_tail(&sk->sk_write_queue, skb); 748 __skb_queue_tail(&sk->sk_write_queue, skb);
749 749
750 return 0; 750 return 0;
@@ -1087,14 +1087,16 @@ ssize_t ip_append_page(struct sock *sk, struct page *page,
1087 1087
1088 inet->cork.length += size; 1088 inet->cork.length += size;
1089 if ((sk->sk_protocol == IPPROTO_UDP) && 1089 if ((sk->sk_protocol == IPPROTO_UDP) &&
1090 (rt->u.dst.dev->features & NETIF_F_UFO)) 1090 (rt->u.dst.dev->features & NETIF_F_UFO)) {
1091 skb_shinfo(skb)->ufo_size = (mtu - fragheaderlen); 1091 skb_shinfo(skb)->gso_size = mtu - fragheaderlen;
1092 skb_shinfo(skb)->gso_type = SKB_GSO_UDPV4;
1093 }
1092 1094
1093 1095
1094 while (size > 0) { 1096 while (size > 0) {
1095 int i; 1097 int i;
1096 1098
1097 if (skb_shinfo(skb)->ufo_size) 1099 if (skb_shinfo(skb)->gso_size)
1098 len = size; 1100 len = size;
1099 else { 1101 else {
1100 1102
diff --git a/net/ipv4/tcp.c b/net/ipv4/tcp.c
index 74998f250071..062dd1a0d8a8 100644
--- a/net/ipv4/tcp.c
+++ b/net/ipv4/tcp.c
@@ -571,7 +571,7 @@ new_segment:
571 skb->ip_summed = CHECKSUM_HW; 571 skb->ip_summed = CHECKSUM_HW;
572 tp->write_seq += copy; 572 tp->write_seq += copy;
573 TCP_SKB_CB(skb)->end_seq += copy; 573 TCP_SKB_CB(skb)->end_seq += copy;
574 skb_shinfo(skb)->tso_segs = 0; 574 skb_shinfo(skb)->gso_segs = 0;
575 575
576 if (!copied) 576 if (!copied)
577 TCP_SKB_CB(skb)->flags &= ~TCPCB_FLAG_PSH; 577 TCP_SKB_CB(skb)->flags &= ~TCPCB_FLAG_PSH;
@@ -818,7 +818,7 @@ new_segment:
818 818
819 tp->write_seq += copy; 819 tp->write_seq += copy;
820 TCP_SKB_CB(skb)->end_seq += copy; 820 TCP_SKB_CB(skb)->end_seq += copy;
821 skb_shinfo(skb)->tso_segs = 0; 821 skb_shinfo(skb)->gso_segs = 0;
822 822
823 from += copy; 823 from += copy;
824 copied += copy; 824 copied += copy;
diff --git a/net/ipv4/tcp_input.c b/net/ipv4/tcp_input.c
index e08245bdda3a..94fe5b1f9dcb 100644
--- a/net/ipv4/tcp_input.c
+++ b/net/ipv4/tcp_input.c
@@ -1073,7 +1073,7 @@ tcp_sacktag_write_queue(struct sock *sk, struct sk_buff *ack_skb, u32 prior_snd_
1073 else 1073 else
1074 pkt_len = (end_seq - 1074 pkt_len = (end_seq -
1075 TCP_SKB_CB(skb)->seq); 1075 TCP_SKB_CB(skb)->seq);
1076 if (tcp_fragment(sk, skb, pkt_len, skb_shinfo(skb)->tso_size)) 1076 if (tcp_fragment(sk, skb, pkt_len, skb_shinfo(skb)->gso_size))
1077 break; 1077 break;
1078 pcount = tcp_skb_pcount(skb); 1078 pcount = tcp_skb_pcount(skb);
1079 } 1079 }
diff --git a/net/ipv4/tcp_output.c b/net/ipv4/tcp_output.c
index 07bb5a2b375e..bdd71db8bf90 100644
--- a/net/ipv4/tcp_output.c
+++ b/net/ipv4/tcp_output.c
@@ -515,15 +515,17 @@ static void tcp_set_skb_tso_segs(struct sock *sk, struct sk_buff *skb, unsigned
515 /* Avoid the costly divide in the normal 515 /* Avoid the costly divide in the normal
516 * non-TSO case. 516 * non-TSO case.
517 */ 517 */
518 skb_shinfo(skb)->tso_segs = 1; 518 skb_shinfo(skb)->gso_segs = 1;
519 skb_shinfo(skb)->tso_size = 0; 519 skb_shinfo(skb)->gso_size = 0;
520 skb_shinfo(skb)->gso_type = 0;
520 } else { 521 } else {
521 unsigned int factor; 522 unsigned int factor;
522 523
523 factor = skb->len + (mss_now - 1); 524 factor = skb->len + (mss_now - 1);
524 factor /= mss_now; 525 factor /= mss_now;
525 skb_shinfo(skb)->tso_segs = factor; 526 skb_shinfo(skb)->gso_segs = factor;
526 skb_shinfo(skb)->tso_size = mss_now; 527 skb_shinfo(skb)->gso_size = mss_now;
528 skb_shinfo(skb)->gso_type = SKB_GSO_TCPV4;
527 } 529 }
528} 530}
529 531
@@ -914,7 +916,7 @@ static int tcp_init_tso_segs(struct sock *sk, struct sk_buff *skb, unsigned int
914 916
915 if (!tso_segs || 917 if (!tso_segs ||
916 (tso_segs > 1 && 918 (tso_segs > 1 &&
917 skb_shinfo(skb)->tso_size != mss_now)) { 919 tcp_skb_mss(skb) != mss_now)) {
918 tcp_set_skb_tso_segs(sk, skb, mss_now); 920 tcp_set_skb_tso_segs(sk, skb, mss_now);
919 tso_segs = tcp_skb_pcount(skb); 921 tso_segs = tcp_skb_pcount(skb);
920 } 922 }
@@ -1724,8 +1726,9 @@ int tcp_retransmit_skb(struct sock *sk, struct sk_buff *skb)
1724 tp->snd_una == (TCP_SKB_CB(skb)->end_seq - 1)) { 1726 tp->snd_una == (TCP_SKB_CB(skb)->end_seq - 1)) {
1725 if (!pskb_trim(skb, 0)) { 1727 if (!pskb_trim(skb, 0)) {
1726 TCP_SKB_CB(skb)->seq = TCP_SKB_CB(skb)->end_seq - 1; 1728 TCP_SKB_CB(skb)->seq = TCP_SKB_CB(skb)->end_seq - 1;
1727 skb_shinfo(skb)->tso_segs = 1; 1729 skb_shinfo(skb)->gso_segs = 1;
1728 skb_shinfo(skb)->tso_size = 0; 1730 skb_shinfo(skb)->gso_size = 0;
1731 skb_shinfo(skb)->gso_type = 0;
1729 skb->ip_summed = CHECKSUM_NONE; 1732 skb->ip_summed = CHECKSUM_NONE;
1730 skb->csum = 0; 1733 skb->csum = 0;
1731 } 1734 }
@@ -1930,8 +1933,9 @@ void tcp_send_fin(struct sock *sk)
1930 skb->csum = 0; 1933 skb->csum = 0;
1931 TCP_SKB_CB(skb)->flags = (TCPCB_FLAG_ACK | TCPCB_FLAG_FIN); 1934 TCP_SKB_CB(skb)->flags = (TCPCB_FLAG_ACK | TCPCB_FLAG_FIN);
1932 TCP_SKB_CB(skb)->sacked = 0; 1935 TCP_SKB_CB(skb)->sacked = 0;
1933 skb_shinfo(skb)->tso_segs = 1; 1936 skb_shinfo(skb)->gso_segs = 1;
1934 skb_shinfo(skb)->tso_size = 0; 1937 skb_shinfo(skb)->gso_size = 0;
1938 skb_shinfo(skb)->gso_type = 0;
1935 1939
1936 /* FIN eats a sequence byte, write_seq advanced by tcp_queue_skb(). */ 1940 /* FIN eats a sequence byte, write_seq advanced by tcp_queue_skb(). */
1937 TCP_SKB_CB(skb)->seq = tp->write_seq; 1941 TCP_SKB_CB(skb)->seq = tp->write_seq;
@@ -1963,8 +1967,9 @@ void tcp_send_active_reset(struct sock *sk, gfp_t priority)
1963 skb->csum = 0; 1967 skb->csum = 0;
1964 TCP_SKB_CB(skb)->flags = (TCPCB_FLAG_ACK | TCPCB_FLAG_RST); 1968 TCP_SKB_CB(skb)->flags = (TCPCB_FLAG_ACK | TCPCB_FLAG_RST);
1965 TCP_SKB_CB(skb)->sacked = 0; 1969 TCP_SKB_CB(skb)->sacked = 0;
1966 skb_shinfo(skb)->tso_segs = 1; 1970 skb_shinfo(skb)->gso_segs = 1;
1967 skb_shinfo(skb)->tso_size = 0; 1971 skb_shinfo(skb)->gso_size = 0;
1972 skb_shinfo(skb)->gso_type = 0;
1968 1973
1969 /* Send it off. */ 1974 /* Send it off. */
1970 TCP_SKB_CB(skb)->seq = tcp_acceptable_seq(sk, tp); 1975 TCP_SKB_CB(skb)->seq = tcp_acceptable_seq(sk, tp);
@@ -2047,8 +2052,9 @@ struct sk_buff * tcp_make_synack(struct sock *sk, struct dst_entry *dst,
2047 TCP_SKB_CB(skb)->seq = tcp_rsk(req)->snt_isn; 2052 TCP_SKB_CB(skb)->seq = tcp_rsk(req)->snt_isn;
2048 TCP_SKB_CB(skb)->end_seq = TCP_SKB_CB(skb)->seq + 1; 2053 TCP_SKB_CB(skb)->end_seq = TCP_SKB_CB(skb)->seq + 1;
2049 TCP_SKB_CB(skb)->sacked = 0; 2054 TCP_SKB_CB(skb)->sacked = 0;
2050 skb_shinfo(skb)->tso_segs = 1; 2055 skb_shinfo(skb)->gso_segs = 1;
2051 skb_shinfo(skb)->tso_size = 0; 2056 skb_shinfo(skb)->gso_size = 0;
2057 skb_shinfo(skb)->gso_type = 0;
2052 th->seq = htonl(TCP_SKB_CB(skb)->seq); 2058 th->seq = htonl(TCP_SKB_CB(skb)->seq);
2053 th->ack_seq = htonl(tcp_rsk(req)->rcv_isn + 1); 2059 th->ack_seq = htonl(tcp_rsk(req)->rcv_isn + 1);
2054 if (req->rcv_wnd == 0) { /* ignored for retransmitted syns */ 2060 if (req->rcv_wnd == 0) { /* ignored for retransmitted syns */
@@ -2152,8 +2158,9 @@ int tcp_connect(struct sock *sk)
2152 TCP_SKB_CB(buff)->flags = TCPCB_FLAG_SYN; 2158 TCP_SKB_CB(buff)->flags = TCPCB_FLAG_SYN;
2153 TCP_ECN_send_syn(sk, tp, buff); 2159 TCP_ECN_send_syn(sk, tp, buff);
2154 TCP_SKB_CB(buff)->sacked = 0; 2160 TCP_SKB_CB(buff)->sacked = 0;
2155 skb_shinfo(buff)->tso_segs = 1; 2161 skb_shinfo(buff)->gso_segs = 1;
2156 skb_shinfo(buff)->tso_size = 0; 2162 skb_shinfo(buff)->gso_size = 0;
2163 skb_shinfo(buff)->gso_type = 0;
2157 buff->csum = 0; 2164 buff->csum = 0;
2158 TCP_SKB_CB(buff)->seq = tp->write_seq++; 2165 TCP_SKB_CB(buff)->seq = tp->write_seq++;
2159 TCP_SKB_CB(buff)->end_seq = tp->write_seq; 2166 TCP_SKB_CB(buff)->end_seq = tp->write_seq;
@@ -2257,8 +2264,9 @@ void tcp_send_ack(struct sock *sk)
2257 buff->csum = 0; 2264 buff->csum = 0;
2258 TCP_SKB_CB(buff)->flags = TCPCB_FLAG_ACK; 2265 TCP_SKB_CB(buff)->flags = TCPCB_FLAG_ACK;
2259 TCP_SKB_CB(buff)->sacked = 0; 2266 TCP_SKB_CB(buff)->sacked = 0;
2260 skb_shinfo(buff)->tso_segs = 1; 2267 skb_shinfo(buff)->gso_segs = 1;
2261 skb_shinfo(buff)->tso_size = 0; 2268 skb_shinfo(buff)->gso_size = 0;
2269 skb_shinfo(buff)->gso_type = 0;
2262 2270
2263 /* Send it off, this clears delayed acks for us. */ 2271 /* Send it off, this clears delayed acks for us. */
2264 TCP_SKB_CB(buff)->seq = TCP_SKB_CB(buff)->end_seq = tcp_acceptable_seq(sk, tp); 2272 TCP_SKB_CB(buff)->seq = TCP_SKB_CB(buff)->end_seq = tcp_acceptable_seq(sk, tp);
@@ -2293,8 +2301,9 @@ static int tcp_xmit_probe_skb(struct sock *sk, int urgent)
2293 skb->csum = 0; 2301 skb->csum = 0;
2294 TCP_SKB_CB(skb)->flags = TCPCB_FLAG_ACK; 2302 TCP_SKB_CB(skb)->flags = TCPCB_FLAG_ACK;
2295 TCP_SKB_CB(skb)->sacked = urgent; 2303 TCP_SKB_CB(skb)->sacked = urgent;
2296 skb_shinfo(skb)->tso_segs = 1; 2304 skb_shinfo(skb)->gso_segs = 1;
2297 skb_shinfo(skb)->tso_size = 0; 2305 skb_shinfo(skb)->gso_size = 0;
2306 skb_shinfo(skb)->gso_type = 0;
2298 2307
2299 /* Use a previous sequence. This should cause the other 2308 /* Use a previous sequence. This should cause the other
2300 * end to send an ack. Don't queue or clone SKB, just 2309 * end to send an ack. Don't queue or clone SKB, just
diff --git a/net/ipv6/ip6_output.c b/net/ipv6/ip6_output.c
index d29620f4910e..abb94de33768 100644
--- a/net/ipv6/ip6_output.c
+++ b/net/ipv6/ip6_output.c
@@ -148,7 +148,7 @@ static int ip6_output2(struct sk_buff *skb)
148 148
149int ip6_output(struct sk_buff *skb) 149int ip6_output(struct sk_buff *skb)
150{ 150{
151 if ((skb->len > dst_mtu(skb->dst) && !skb_shinfo(skb)->ufo_size) || 151 if ((skb->len > dst_mtu(skb->dst) && !skb_shinfo(skb)->gso_size) ||
152 dst_allfrag(skb->dst)) 152 dst_allfrag(skb->dst))
153 return ip6_fragment(skb, ip6_output2); 153 return ip6_fragment(skb, ip6_output2);
154 else 154 else
@@ -833,8 +833,9 @@ static inline int ip6_ufo_append_data(struct sock *sk,
833 struct frag_hdr fhdr; 833 struct frag_hdr fhdr;
834 834
835 /* specify the length of each IP datagram fragment*/ 835 /* specify the length of each IP datagram fragment*/
836 skb_shinfo(skb)->ufo_size = (mtu - fragheaderlen) - 836 skb_shinfo(skb)->gso_size = mtu - fragheaderlen -
837 sizeof(struct frag_hdr); 837 sizeof(struct frag_hdr);
838 skb_shinfo(skb)->gso_type = SKB_GSO_UDPV4;
838 ipv6_select_ident(skb, &fhdr); 839 ipv6_select_ident(skb, &fhdr);
839 skb_shinfo(skb)->ip6_frag_id = fhdr.identification; 840 skb_shinfo(skb)->ip6_frag_id = fhdr.identification;
840 __skb_queue_tail(&sk->sk_write_queue, skb); 841 __skb_queue_tail(&sk->sk_write_queue, skb);