summaryrefslogtreecommitdiff
path: root/include
diff options
context:
space:
mode:
Diffstat (limited to 'include')
-rw-r--r--include/linux/netdevice.h17
-rw-r--r--include/linux/skbuff.h6
-rw-r--r--include/net/ip6_route.h2
-rw-r--r--include/net/protocol.h6
-rw-r--r--include/net/sock.h13
-rw-r--r--include/net/tcp.h2
-rw-r--r--include/net/tcp_ecn.h4
7 files changed, 35 insertions, 15 deletions
diff --git a/include/linux/netdevice.h b/include/linux/netdevice.h
index aa2d3c12c4d8..85f99f60deea 100644
--- a/include/linux/netdevice.h
+++ b/include/linux/netdevice.h
@@ -313,10 +313,12 @@ struct net_device
/* Segmentation offload features */
#define NETIF_F_GSO_SHIFT 16
+#define NETIF_F_GSO_MASK 0xffff0000
#define NETIF_F_TSO (SKB_GSO_TCPV4 << NETIF_F_GSO_SHIFT)
-#define NETIF_F_UFO (SKB_GSO_UDPV4 << NETIF_F_GSO_SHIFT)
+#define NETIF_F_UFO (SKB_GSO_UDP << NETIF_F_GSO_SHIFT)
#define NETIF_F_GSO_ROBUST (SKB_GSO_DODGY << NETIF_F_GSO_SHIFT)
-#define NETIF_F_TSO_ECN (SKB_GSO_TCPV4_ECN << NETIF_F_GSO_SHIFT)
+#define NETIF_F_TSO_ECN (SKB_GSO_TCP_ECN << NETIF_F_GSO_SHIFT)
+#define NETIF_F_TSO6 (SKB_GSO_TCPV6 << NETIF_F_GSO_SHIFT)
#define NETIF_F_GEN_CSUM (NETIF_F_NO_CSUM | NETIF_F_HW_CSUM)
#define NETIF_F_ALL_CSUM (NETIF_F_IP_CSUM | NETIF_F_GEN_CSUM)
@@ -991,13 +993,18 @@ extern void dev_seq_stop(struct seq_file *seq, void *v);
extern void linkwatch_run_queue(void);
-static inline int skb_gso_ok(struct sk_buff *skb, int features)
+static inline int net_gso_ok(int features, int gso_type)
{
- int feature = skb_shinfo(skb)->gso_size ?
- skb_shinfo(skb)->gso_type << NETIF_F_GSO_SHIFT : 0;
+ int feature = gso_type << NETIF_F_GSO_SHIFT;
return (features & feature) == feature;
}
+static inline int skb_gso_ok(struct sk_buff *skb, int features)
+{
+ return net_gso_ok(features, skb_shinfo(skb)->gso_size ?
+ skb_shinfo(skb)->gso_type : 0);
+}
+
static inline int netif_needs_gso(struct net_device *dev, struct sk_buff *skb)
{
return !skb_gso_ok(skb, dev->features);
diff --git a/include/linux/skbuff.h b/include/linux/skbuff.h
index 59918be91d0a..57d7d4965f9a 100644
--- a/include/linux/skbuff.h
+++ b/include/linux/skbuff.h
@@ -171,13 +171,15 @@ enum {
enum {
SKB_GSO_TCPV4 = 1 << 0,
- SKB_GSO_UDPV4 = 1 << 1,
+ SKB_GSO_UDP = 1 << 1,
/* This indicates the skb is from an untrusted source. */
SKB_GSO_DODGY = 1 << 2,
/* This indicates the tcp segment has CWR set. */
- SKB_GSO_TCPV4_ECN = 1 << 3,
+ SKB_GSO_TCP_ECN = 1 << 3,
+
+ SKB_GSO_TCPV6 = 1 << 4,
};
/**
diff --git a/include/net/ip6_route.h b/include/net/ip6_route.h
index a398ae5e30f9..ab29dafb1a6a 100644
--- a/include/net/ip6_route.h
+++ b/include/net/ip6_route.h
@@ -146,7 +146,7 @@ static inline void ip6_dst_store(struct sock *sk, struct dst_entry *dst,
struct rt6_info *rt = (struct rt6_info *) dst;
write_lock(&sk->sk_dst_lock);
- __sk_dst_set(sk, dst);
+ sk_setup_caps(sk, dst);
np->daddr_cache = daddr;
np->dst_cookie = rt->rt6i_node ? rt->rt6i_node->fn_sernum : 0;
write_unlock(&sk->sk_dst_lock);
diff --git a/include/net/protocol.h b/include/net/protocol.h
index 40b6b9c9973f..a225d6371cb1 100644
--- a/include/net/protocol.h
+++ b/include/net/protocol.h
@@ -50,11 +50,17 @@ struct inet6_protocol
struct inet6_skb_parm *opt,
int type, int code, int offset,
__u32 info);
+
+ struct sk_buff *(*gso_segment)(struct sk_buff *skb,
+ int features);
+
unsigned int flags; /* INET6_PROTO_xxx */
};
#define INET6_PROTO_NOPOLICY 0x1
#define INET6_PROTO_FINAL 0x2
+/* This should be set for any extension header which is compatible with GSO. */
+#define INET6_PROTO_GSO_EXTHDR 0x4
#endif
/* This is used to register socket interfaces for IP protocols. */
diff --git a/include/net/sock.h b/include/net/sock.h
index 7136bae48c2f..7b3d6b856946 100644
--- a/include/net/sock.h
+++ b/include/net/sock.h
@@ -140,6 +140,7 @@ struct sock_common {
* @sk_flags: %SO_LINGER (l_onoff), %SO_BROADCAST, %SO_KEEPALIVE, %SO_OOBINLINE settings
* @sk_no_check: %SO_NO_CHECK setting, wether or not checkup packets
* @sk_route_caps: route capabilities (e.g. %NETIF_F_TSO)
+ * @sk_gso_type: GSO type (e.g. %SKB_GSO_TCPV4)
* @sk_lingertime: %SO_LINGER l_linger setting
* @sk_backlog: always used with the per-socket spinlock held
* @sk_callback_lock: used with the callbacks in the end of this struct
@@ -211,6 +212,7 @@ struct sock {
gfp_t sk_allocation;
int sk_sndbuf;
int sk_route_caps;
+ int sk_gso_type;
int sk_rcvlowat;
unsigned long sk_flags;
unsigned long sk_lingertime;
@@ -1025,15 +1027,20 @@ extern struct dst_entry *__sk_dst_check(struct sock *sk, u32 cookie);
extern struct dst_entry *sk_dst_check(struct sock *sk, u32 cookie);
+static inline int sk_can_gso(const struct sock *sk)
+{
+ return net_gso_ok(sk->sk_route_caps, sk->sk_gso_type);
+}
+
static inline void sk_setup_caps(struct sock *sk, struct dst_entry *dst)
{
__sk_dst_set(sk, dst);
sk->sk_route_caps = dst->dev->features;
if (sk->sk_route_caps & NETIF_F_GSO)
- sk->sk_route_caps |= NETIF_F_TSO;
- if (sk->sk_route_caps & NETIF_F_TSO) {
+ sk->sk_route_caps |= NETIF_F_GSO_MASK;
+ if (sk_can_gso(sk)) {
if (dst->header_len)
- sk->sk_route_caps &= ~NETIF_F_TSO;
+ sk->sk_route_caps &= ~NETIF_F_GSO_MASK;
else
sk->sk_route_caps |= NETIF_F_SG | NETIF_F_HW_CSUM;
}
diff --git a/include/net/tcp.h b/include/net/tcp.h
index 624921e76332..3cd803b0d7a5 100644
--- a/include/net/tcp.h
+++ b/include/net/tcp.h
@@ -751,7 +751,7 @@ static inline int tcp_is_cwnd_limited(const struct sock *sk, u32 in_flight)
if (in_flight >= tp->snd_cwnd)
return 1;
- if (!(sk->sk_route_caps & NETIF_F_TSO))
+ if (!sk_can_gso(sk))
return 0;
left = tp->snd_cwnd - in_flight;
diff --git a/include/net/tcp_ecn.h b/include/net/tcp_ecn.h
index 7bb366f70934..4629d77173f2 100644
--- a/include/net/tcp_ecn.h
+++ b/include/net/tcp_ecn.h
@@ -55,9 +55,7 @@ static inline void TCP_ECN_send(struct sock *sk, struct tcp_sock *tp,
if (tp->ecn_flags&TCP_ECN_QUEUE_CWR) {
tp->ecn_flags &= ~TCP_ECN_QUEUE_CWR;
skb->h.th->cwr = 1;
- if (skb_shinfo(skb)->gso_type & SKB_GSO_TCPV4)
- skb_shinfo(skb)->gso_type |=
- SKB_GSO_TCPV4_ECN;
+ skb_shinfo(skb)->gso_type |= SKB_GSO_TCP_ECN;
}
} else {
/* ACK or retransmitted segment: clear ECT|CE */