aboutsummaryrefslogtreecommitdiffstats
path: root/include
diff options
context:
space:
mode:
Diffstat (limited to 'include')
-rw-r--r--include/linux/netdev_features.h4
-rw-r--r--include/linux/netdevice.h1
-rw-r--r--include/linux/skbuff.h4
-rw-r--r--include/net/fou.h38
-rw-r--r--include/net/gue.h103
-rw-r--r--include/uapi/linux/if_tunnel.h1
6 files changed, 144 insertions, 7 deletions
diff --git a/include/linux/netdev_features.h b/include/linux/netdev_features.h
index dcfdecbfa0b7..8c94b07e654a 100644
--- a/include/linux/netdev_features.h
+++ b/include/linux/netdev_features.h
@@ -48,8 +48,9 @@ enum {
48 NETIF_F_GSO_UDP_TUNNEL_BIT, /* ... UDP TUNNEL with TSO */ 48 NETIF_F_GSO_UDP_TUNNEL_BIT, /* ... UDP TUNNEL with TSO */
49 NETIF_F_GSO_UDP_TUNNEL_CSUM_BIT,/* ... UDP TUNNEL with TSO & CSUM */ 49 NETIF_F_GSO_UDP_TUNNEL_CSUM_BIT,/* ... UDP TUNNEL with TSO & CSUM */
50 NETIF_F_GSO_MPLS_BIT, /* ... MPLS segmentation */ 50 NETIF_F_GSO_MPLS_BIT, /* ... MPLS segmentation */
51 NETIF_F_GSO_TUNNEL_REMCSUM_BIT, /* ... TUNNEL with TSO & REMCSUM */
51 /**/NETIF_F_GSO_LAST = /* last bit, see GSO_MASK */ 52 /**/NETIF_F_GSO_LAST = /* last bit, see GSO_MASK */
52 NETIF_F_GSO_MPLS_BIT, 53 NETIF_F_GSO_TUNNEL_REMCSUM_BIT,
53 54
54 NETIF_F_FCOE_CRC_BIT, /* FCoE CRC32 */ 55 NETIF_F_FCOE_CRC_BIT, /* FCoE CRC32 */
55 NETIF_F_SCTP_CSUM_BIT, /* SCTP checksum offload */ 56 NETIF_F_SCTP_CSUM_BIT, /* SCTP checksum offload */
@@ -119,6 +120,7 @@ enum {
119#define NETIF_F_GSO_UDP_TUNNEL __NETIF_F(GSO_UDP_TUNNEL) 120#define NETIF_F_GSO_UDP_TUNNEL __NETIF_F(GSO_UDP_TUNNEL)
120#define NETIF_F_GSO_UDP_TUNNEL_CSUM __NETIF_F(GSO_UDP_TUNNEL_CSUM) 121#define NETIF_F_GSO_UDP_TUNNEL_CSUM __NETIF_F(GSO_UDP_TUNNEL_CSUM)
121#define NETIF_F_GSO_MPLS __NETIF_F(GSO_MPLS) 122#define NETIF_F_GSO_MPLS __NETIF_F(GSO_MPLS)
123#define NETIF_F_GSO_TUNNEL_REMCSUM __NETIF_F(GSO_TUNNEL_REMCSUM)
122#define NETIF_F_HW_VLAN_STAG_FILTER __NETIF_F(HW_VLAN_STAG_FILTER) 124#define NETIF_F_HW_VLAN_STAG_FILTER __NETIF_F(HW_VLAN_STAG_FILTER)
123#define NETIF_F_HW_VLAN_STAG_RX __NETIF_F(HW_VLAN_STAG_RX) 125#define NETIF_F_HW_VLAN_STAG_RX __NETIF_F(HW_VLAN_STAG_RX)
124#define NETIF_F_HW_VLAN_STAG_TX __NETIF_F(HW_VLAN_STAG_TX) 126#define NETIF_F_HW_VLAN_STAG_TX __NETIF_F(HW_VLAN_STAG_TX)
diff --git a/include/linux/netdevice.h b/include/linux/netdevice.h
index 5ed05bd764dc..4767f546d7c0 100644
--- a/include/linux/netdevice.h
+++ b/include/linux/netdevice.h
@@ -3584,6 +3584,7 @@ static inline bool net_gso_ok(netdev_features_t features, int gso_type)
3584 BUILD_BUG_ON(SKB_GSO_UDP_TUNNEL != (NETIF_F_GSO_UDP_TUNNEL >> NETIF_F_GSO_SHIFT)); 3584 BUILD_BUG_ON(SKB_GSO_UDP_TUNNEL != (NETIF_F_GSO_UDP_TUNNEL >> NETIF_F_GSO_SHIFT));
3585 BUILD_BUG_ON(SKB_GSO_UDP_TUNNEL_CSUM != (NETIF_F_GSO_UDP_TUNNEL_CSUM >> NETIF_F_GSO_SHIFT)); 3585 BUILD_BUG_ON(SKB_GSO_UDP_TUNNEL_CSUM != (NETIF_F_GSO_UDP_TUNNEL_CSUM >> NETIF_F_GSO_SHIFT));
3586 BUILD_BUG_ON(SKB_GSO_MPLS != (NETIF_F_GSO_MPLS >> NETIF_F_GSO_SHIFT)); 3586 BUILD_BUG_ON(SKB_GSO_MPLS != (NETIF_F_GSO_MPLS >> NETIF_F_GSO_SHIFT));
3587 BUILD_BUG_ON(SKB_GSO_TUNNEL_REMCSUM != (NETIF_F_GSO_TUNNEL_REMCSUM >> NETIF_F_GSO_SHIFT));
3587 3588
3588 return (features & feature) == feature; 3589 return (features & feature) == feature;
3589} 3590}
diff --git a/include/linux/skbuff.h b/include/linux/skbuff.h
index 5ad9675b6fe1..74ed34413969 100644
--- a/include/linux/skbuff.h
+++ b/include/linux/skbuff.h
@@ -373,6 +373,7 @@ enum {
373 373
374 SKB_GSO_MPLS = 1 << 12, 374 SKB_GSO_MPLS = 1 << 12,
375 375
376 SKB_GSO_TUNNEL_REMCSUM = 1 << 13,
376}; 377};
377 378
378#if BITS_PER_LONG > 32 379#if BITS_PER_LONG > 32
@@ -603,7 +604,8 @@ struct sk_buff {
603#endif 604#endif
604 __u8 ipvs_property:1; 605 __u8 ipvs_property:1;
605 __u8 inner_protocol_type:1; 606 __u8 inner_protocol_type:1;
606 /* 4 or 6 bit hole */ 607 __u8 remcsum_offload:1;
608 /* 3 or 5 bit hole */
607 609
608#ifdef CONFIG_NET_SCHED 610#ifdef CONFIG_NET_SCHED
609 __u16 tc_index; /* traffic control index */ 611 __u16 tc_index; /* traffic control index */
diff --git a/include/net/fou.h b/include/net/fou.h
new file mode 100644
index 000000000000..25b26ffcf1df
--- /dev/null
+++ b/include/net/fou.h
@@ -0,0 +1,38 @@
1#ifndef __NET_FOU_H
2#define __NET_FOU_H
3
4#include <linux/skbuff.h>
5
6#include <net/flow.h>
7#include <net/gue.h>
8#include <net/ip_tunnels.h>
9#include <net/udp.h>
10
11int fou_build_header(struct sk_buff *skb, struct ip_tunnel_encap *e,
12 u8 *protocol, struct flowi4 *fl4);
13int gue_build_header(struct sk_buff *skb, struct ip_tunnel_encap *e,
14 u8 *protocol, struct flowi4 *fl4);
15
16static size_t fou_encap_hlen(struct ip_tunnel_encap *e)
17{
18 return sizeof(struct udphdr);
19}
20
21static size_t gue_encap_hlen(struct ip_tunnel_encap *e)
22{
23 size_t len;
24 bool need_priv = false;
25
26 len = sizeof(struct udphdr) + sizeof(struct guehdr);
27
28 if (e->flags & TUNNEL_ENCAP_FLAG_REMCSUM) {
29 len += GUE_PLEN_REMCSUM;
30 need_priv = true;
31 }
32
33 len += need_priv ? GUE_LEN_PRIV : 0;
34
35 return len;
36}
37
38#endif
diff --git a/include/net/gue.h b/include/net/gue.h
index b6c332788084..3f28ec7f1c7f 100644
--- a/include/net/gue.h
+++ b/include/net/gue.h
@@ -1,23 +1,116 @@
1#ifndef __NET_GUE_H 1#ifndef __NET_GUE_H
2#define __NET_GUE_H 2#define __NET_GUE_H
3 3
4/* Definitions for the GUE header, standard and private flags, lengths
5 * of optional fields are below.
6 *
7 * Diagram of GUE header:
8 *
9 * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
10 * |Ver|C| Hlen | Proto/ctype | Standard flags |P|
11 * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
12 * | |
13 * ~ Fields (optional) ~
14 * | |
15 * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
16 * | Private flags (optional, P bit is set) |
17 * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
18 * | |
19 * ~ Private fields (optional) ~
20 * | |
21 * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
22 *
23 * C bit indicates contol message when set, data message when unset.
24 * For a control message, proto/ctype is interpreted as a type of
25 * control message. For data messages, proto/ctype is the IP protocol
26 * of the next header.
27 *
28 * P bit indicates private flags field is present. The private flags
29 * may refer to options placed after this field.
30 */
31
4struct guehdr { 32struct guehdr {
5 union { 33 union {
6 struct { 34 struct {
7#if defined(__LITTLE_ENDIAN_BITFIELD) 35#if defined(__LITTLE_ENDIAN_BITFIELD)
8 __u8 hlen:4, 36 __u8 hlen:5,
9 version:4; 37 control:1,
38 version:2;
10#elif defined (__BIG_ENDIAN_BITFIELD) 39#elif defined (__BIG_ENDIAN_BITFIELD)
11 __u8 version:4, 40 __u8 version:2,
12 hlen:4; 41 control:1,
42 hlen:5;
13#else 43#else
14#error "Please fix <asm/byteorder.h>" 44#error "Please fix <asm/byteorder.h>"
15#endif 45#endif
16 __u8 next_hdr; 46 __u8 proto_ctype;
17 __u16 flags; 47 __u16 flags;
18 }; 48 };
19 __u32 word; 49 __u32 word;
20 }; 50 };
21}; 51};
22 52
53/* Standard flags in GUE header */
54
55#define GUE_FLAG_PRIV htons(1<<0) /* Private flags are in options */
56#define GUE_LEN_PRIV 4
57
58#define GUE_FLAGS_ALL (GUE_FLAG_PRIV)
59
60/* Private flags in the private option extension */
61
62#define GUE_PFLAG_REMCSUM htonl(1 << 31)
63#define GUE_PLEN_REMCSUM 4
64
65#define GUE_PFLAGS_ALL (GUE_PFLAG_REMCSUM)
66
67/* Functions to compute options length corresponding to flags.
68 * If we ever have a lot of flags this can be potentially be
69 * converted to a more optimized algorithm (table lookup
70 * for instance).
71 */
72static inline size_t guehdr_flags_len(__be16 flags)
73{
74 return ((flags & GUE_FLAG_PRIV) ? GUE_LEN_PRIV : 0);
75}
76
77static inline size_t guehdr_priv_flags_len(__be32 flags)
78{
79 return 0;
80}
81
82/* Validate standard and private flags. Returns non-zero (meaning invalid)
83 * if there is an unknown standard or private flags, or the options length for
84 * the flags exceeds the options length specific in hlen of the GUE header.
85 */
86static inline int validate_gue_flags(struct guehdr *guehdr,
87 size_t optlen)
88{
89 size_t len;
90 __be32 flags = guehdr->flags;
91
92 if (flags & ~GUE_FLAGS_ALL)
93 return 1;
94
95 len = guehdr_flags_len(flags);
96 if (len > optlen)
97 return 1;
98
99 if (flags & GUE_FLAG_PRIV) {
100 /* Private flags are last four bytes accounted in
101 * guehdr_flags_len
102 */
103 flags = *(__be32 *)((void *)&guehdr[1] + len - GUE_LEN_PRIV);
104
105 if (flags & ~GUE_PFLAGS_ALL)
106 return 1;
107
108 len += guehdr_priv_flags_len(flags);
109 if (len > optlen)
110 return 1;
111 }
112
113 return 0;
114}
115
23#endif 116#endif
diff --git a/include/uapi/linux/if_tunnel.h b/include/uapi/linux/if_tunnel.h
index 280d9e092283..bd3cc11a431f 100644
--- a/include/uapi/linux/if_tunnel.h
+++ b/include/uapi/linux/if_tunnel.h
@@ -69,6 +69,7 @@ enum tunnel_encap_types {
69 69
70#define TUNNEL_ENCAP_FLAG_CSUM (1<<0) 70#define TUNNEL_ENCAP_FLAG_CSUM (1<<0)
71#define TUNNEL_ENCAP_FLAG_CSUM6 (1<<1) 71#define TUNNEL_ENCAP_FLAG_CSUM6 (1<<1)
72#define TUNNEL_ENCAP_FLAG_REMCSUM (1<<2)
72 73
73/* SIT-mode i_flags */ 74/* SIT-mode i_flags */
74#define SIT_ISATAP 0x0001 75#define SIT_ISATAP 0x0001