Commit 438e38fadca2f6e57eeecc08326c8a95758594d4

Authored by Eric Dumazet
Committed by David S. Miller
1 parent 0e5959346c

gre_offload: statically build GRE offloading support

GRO/GSO layers can be enabled on a node, even if said
node is only forwarding packets.

This patch permits GSO (and upcoming GRO) support for GRE
encapsulated packets, even if the host has no GRE tunnel setup.

Signed-off-by: Eric Dumazet <edumazet@google.com>
Cc: H.K. Jerry Chu <hkchu@google.com>
Signed-off-by: David S. Miller <davem@davemloft.net>

Showing 4 changed files with 7 additions and 16 deletions Inline Diff

1 #ifndef __LINUX_GRE_H 1 #ifndef __LINUX_GRE_H
2 #define __LINUX_GRE_H 2 #define __LINUX_GRE_H
3 3
4 #include <linux/skbuff.h> 4 #include <linux/skbuff.h>
5 #include <net/ip_tunnels.h> 5 #include <net/ip_tunnels.h>
6 6
7 #define GREPROTO_CISCO 0 7 #define GREPROTO_CISCO 0
8 #define GREPROTO_PPTP 1 8 #define GREPROTO_PPTP 1
9 #define GREPROTO_MAX 2 9 #define GREPROTO_MAX 2
10 #define GRE_IP_PROTO_MAX 2 10 #define GRE_IP_PROTO_MAX 2
11 11
12 struct gre_protocol { 12 struct gre_protocol {
13 int (*handler)(struct sk_buff *skb); 13 int (*handler)(struct sk_buff *skb);
14 void (*err_handler)(struct sk_buff *skb, u32 info); 14 void (*err_handler)(struct sk_buff *skb, u32 info);
15 }; 15 };
16 16
17 struct gre_base_hdr { 17 struct gre_base_hdr {
18 __be16 flags; 18 __be16 flags;
19 __be16 protocol; 19 __be16 protocol;
20 }; 20 };
21 #define GRE_HEADER_SECTION 4 21 #define GRE_HEADER_SECTION 4
22 22
23 int gre_add_protocol(const struct gre_protocol *proto, u8 version); 23 int gre_add_protocol(const struct gre_protocol *proto, u8 version);
24 int gre_del_protocol(const struct gre_protocol *proto, u8 version); 24 int gre_del_protocol(const struct gre_protocol *proto, u8 version);
25 25
26 struct gre_cisco_protocol { 26 struct gre_cisco_protocol {
27 int (*handler)(struct sk_buff *skb, const struct tnl_ptk_info *tpi); 27 int (*handler)(struct sk_buff *skb, const struct tnl_ptk_info *tpi);
28 int (*err_handler)(struct sk_buff *skb, u32 info, 28 int (*err_handler)(struct sk_buff *skb, u32 info,
29 const struct tnl_ptk_info *tpi); 29 const struct tnl_ptk_info *tpi);
30 u8 priority; 30 u8 priority;
31 }; 31 };
32 32
33 int gre_cisco_register(struct gre_cisco_protocol *proto); 33 int gre_cisco_register(struct gre_cisco_protocol *proto);
34 int gre_cisco_unregister(struct gre_cisco_protocol *proto); 34 int gre_cisco_unregister(struct gre_cisco_protocol *proto);
35 35
36 int gre_offload_init(void);
37 void gre_offload_exit(void);
38
39 void gre_build_header(struct sk_buff *skb, const struct tnl_ptk_info *tpi, 36 void gre_build_header(struct sk_buff *skb, const struct tnl_ptk_info *tpi,
40 int hdr_len); 37 int hdr_len);
41 38
42 static inline struct sk_buff *gre_handle_offloads(struct sk_buff *skb, 39 static inline struct sk_buff *gre_handle_offloads(struct sk_buff *skb,
43 bool gre_csum) 40 bool gre_csum)
44 { 41 {
45 return iptunnel_handle_offloads(skb, gre_csum, SKB_GSO_GRE); 42 return iptunnel_handle_offloads(skb, gre_csum, SKB_GSO_GRE);
46 } 43 }
47 44
48 45
49 static inline int ip_gre_calc_hlen(__be16 o_flags) 46 static inline int ip_gre_calc_hlen(__be16 o_flags)
50 { 47 {
51 int addend = 4; 48 int addend = 4;
52 49
53 if (o_flags&TUNNEL_CSUM) 50 if (o_flags&TUNNEL_CSUM)
54 addend += 4; 51 addend += 4;
55 if (o_flags&TUNNEL_KEY) 52 if (o_flags&TUNNEL_KEY)
56 addend += 4; 53 addend += 4;
57 if (o_flags&TUNNEL_SEQ) 54 if (o_flags&TUNNEL_SEQ)
58 addend += 4; 55 addend += 4;
59 return addend; 56 return addend;
60 } 57 }
61 58
62 static inline __be16 gre_flags_to_tnl_flags(__be16 flags) 59 static inline __be16 gre_flags_to_tnl_flags(__be16 flags)
63 { 60 {
64 __be16 tflags = 0; 61 __be16 tflags = 0;
65 62
66 if (flags & GRE_CSUM) 63 if (flags & GRE_CSUM)
67 tflags |= TUNNEL_CSUM; 64 tflags |= TUNNEL_CSUM;
68 if (flags & GRE_ROUTING) 65 if (flags & GRE_ROUTING)
69 tflags |= TUNNEL_ROUTING; 66 tflags |= TUNNEL_ROUTING;
70 if (flags & GRE_KEY) 67 if (flags & GRE_KEY)
71 tflags |= TUNNEL_KEY; 68 tflags |= TUNNEL_KEY;
72 if (flags & GRE_SEQ) 69 if (flags & GRE_SEQ)
73 tflags |= TUNNEL_SEQ; 70 tflags |= TUNNEL_SEQ;
74 if (flags & GRE_STRICT) 71 if (flags & GRE_STRICT)
75 tflags |= TUNNEL_STRICT; 72 tflags |= TUNNEL_STRICT;
76 if (flags & GRE_REC) 73 if (flags & GRE_REC)
77 tflags |= TUNNEL_REC; 74 tflags |= TUNNEL_REC;
78 if (flags & GRE_VERSION) 75 if (flags & GRE_VERSION)
79 tflags |= TUNNEL_VERSION; 76 tflags |= TUNNEL_VERSION;
80 77
81 return tflags; 78 return tflags;
82 } 79 }
83 80
84 static inline __be16 tnl_flags_to_gre_flags(__be16 tflags) 81 static inline __be16 tnl_flags_to_gre_flags(__be16 tflags)
85 { 82 {
86 __be16 flags = 0; 83 __be16 flags = 0;
87 84
88 if (tflags & TUNNEL_CSUM) 85 if (tflags & TUNNEL_CSUM)
89 flags |= GRE_CSUM; 86 flags |= GRE_CSUM;
90 if (tflags & TUNNEL_ROUTING) 87 if (tflags & TUNNEL_ROUTING)
91 flags |= GRE_ROUTING; 88 flags |= GRE_ROUTING;
92 if (tflags & TUNNEL_KEY) 89 if (tflags & TUNNEL_KEY)
93 flags |= GRE_KEY; 90 flags |= GRE_KEY;
94 if (tflags & TUNNEL_SEQ) 91 if (tflags & TUNNEL_SEQ)
95 flags |= GRE_SEQ; 92 flags |= GRE_SEQ;
96 if (tflags & TUNNEL_STRICT) 93 if (tflags & TUNNEL_STRICT)
97 flags |= GRE_STRICT; 94 flags |= GRE_STRICT;
98 if (tflags & TUNNEL_REC) 95 if (tflags & TUNNEL_REC)
99 flags |= GRE_REC; 96 flags |= GRE_REC;
100 if (tflags & TUNNEL_VERSION) 97 if (tflags & TUNNEL_VERSION)
101 flags |= GRE_VERSION; 98 flags |= GRE_VERSION;
102 99
103 return flags; 100 return flags;
104 } 101 }
105 102
106 #endif 103 #endif
107 104
1 # 1 #
2 # Makefile for the Linux TCP/IP (INET) layer. 2 # Makefile for the Linux TCP/IP (INET) layer.
3 # 3 #
4 4
5 obj-y := route.o inetpeer.o protocol.o \ 5 obj-y := route.o inetpeer.o protocol.o \
6 ip_input.o ip_fragment.o ip_forward.o ip_options.o \ 6 ip_input.o ip_fragment.o ip_forward.o ip_options.o \
7 ip_output.o ip_sockglue.o inet_hashtables.o \ 7 ip_output.o ip_sockglue.o inet_hashtables.o \
8 inet_timewait_sock.o inet_connection_sock.o \ 8 inet_timewait_sock.o inet_connection_sock.o \
9 tcp.o tcp_input.o tcp_output.o tcp_timer.o tcp_ipv4.o \ 9 tcp.o tcp_input.o tcp_output.o tcp_timer.o tcp_ipv4.o \
10 tcp_minisocks.o tcp_cong.o tcp_metrics.o tcp_fastopen.o \ 10 tcp_minisocks.o tcp_cong.o tcp_metrics.o tcp_fastopen.o \
11 tcp_offload.o datagram.o raw.o udp.o udplite.o \ 11 tcp_offload.o datagram.o raw.o udp.o udplite.o \
12 udp_offload.o arp.o icmp.o devinet.o af_inet.o igmp.o \ 12 udp_offload.o arp.o icmp.o devinet.o af_inet.o igmp.o \
13 fib_frontend.o fib_semantics.o fib_trie.o \ 13 fib_frontend.o fib_semantics.o fib_trie.o \
14 inet_fragment.o ping.o ip_tunnel_core.o 14 inet_fragment.o ping.o ip_tunnel_core.o gre_offload.o
15 15
16 obj-$(CONFIG_NET_IP_TUNNEL) += ip_tunnel.o 16 obj-$(CONFIG_NET_IP_TUNNEL) += ip_tunnel.o
17 obj-$(CONFIG_SYSCTL) += sysctl_net_ipv4.o 17 obj-$(CONFIG_SYSCTL) += sysctl_net_ipv4.o
18 obj-$(CONFIG_PROC_FS) += proc.o 18 obj-$(CONFIG_PROC_FS) += proc.o
19 obj-$(CONFIG_IP_MULTIPLE_TABLES) += fib_rules.o 19 obj-$(CONFIG_IP_MULTIPLE_TABLES) += fib_rules.o
20 obj-$(CONFIG_IP_MROUTE) += ipmr.o 20 obj-$(CONFIG_IP_MROUTE) += ipmr.o
21 obj-$(CONFIG_NET_IPIP) += ipip.o 21 obj-$(CONFIG_NET_IPIP) += ipip.o
22 gre-y := gre_demux.o gre_offload.o 22 gre-y := gre_demux.o
23 obj-$(CONFIG_NET_IPGRE_DEMUX) += gre.o 23 obj-$(CONFIG_NET_IPGRE_DEMUX) += gre.o
24 obj-$(CONFIG_NET_IPGRE) += ip_gre.o 24 obj-$(CONFIG_NET_IPGRE) += ip_gre.o
25 obj-$(CONFIG_NET_IPVTI) += ip_vti.o 25 obj-$(CONFIG_NET_IPVTI) += ip_vti.o
26 obj-$(CONFIG_SYN_COOKIES) += syncookies.o 26 obj-$(CONFIG_SYN_COOKIES) += syncookies.o
27 obj-$(CONFIG_INET_AH) += ah4.o 27 obj-$(CONFIG_INET_AH) += ah4.o
28 obj-$(CONFIG_INET_ESP) += esp4.o 28 obj-$(CONFIG_INET_ESP) += esp4.o
29 obj-$(CONFIG_INET_IPCOMP) += ipcomp.o 29 obj-$(CONFIG_INET_IPCOMP) += ipcomp.o
30 obj-$(CONFIG_INET_XFRM_TUNNEL) += xfrm4_tunnel.o 30 obj-$(CONFIG_INET_XFRM_TUNNEL) += xfrm4_tunnel.o
31 obj-$(CONFIG_INET_XFRM_MODE_BEET) += xfrm4_mode_beet.o 31 obj-$(CONFIG_INET_XFRM_MODE_BEET) += xfrm4_mode_beet.o
32 obj-$(CONFIG_INET_LRO) += inet_lro.o 32 obj-$(CONFIG_INET_LRO) += inet_lro.o
33 obj-$(CONFIG_INET_TUNNEL) += tunnel4.o 33 obj-$(CONFIG_INET_TUNNEL) += tunnel4.o
34 obj-$(CONFIG_INET_XFRM_MODE_TRANSPORT) += xfrm4_mode_transport.o 34 obj-$(CONFIG_INET_XFRM_MODE_TRANSPORT) += xfrm4_mode_transport.o
35 obj-$(CONFIG_INET_XFRM_MODE_TUNNEL) += xfrm4_mode_tunnel.o 35 obj-$(CONFIG_INET_XFRM_MODE_TUNNEL) += xfrm4_mode_tunnel.o
36 obj-$(CONFIG_IP_PNP) += ipconfig.o 36 obj-$(CONFIG_IP_PNP) += ipconfig.o
37 obj-$(CONFIG_NETFILTER) += netfilter.o netfilter/ 37 obj-$(CONFIG_NETFILTER) += netfilter.o netfilter/
38 obj-$(CONFIG_INET_DIAG) += inet_diag.o 38 obj-$(CONFIG_INET_DIAG) += inet_diag.o
39 obj-$(CONFIG_INET_TCP_DIAG) += tcp_diag.o 39 obj-$(CONFIG_INET_TCP_DIAG) += tcp_diag.o
40 obj-$(CONFIG_INET_UDP_DIAG) += udp_diag.o 40 obj-$(CONFIG_INET_UDP_DIAG) += udp_diag.o
41 obj-$(CONFIG_NET_TCPPROBE) += tcp_probe.o 41 obj-$(CONFIG_NET_TCPPROBE) += tcp_probe.o
42 obj-$(CONFIG_TCP_CONG_BIC) += tcp_bic.o 42 obj-$(CONFIG_TCP_CONG_BIC) += tcp_bic.o
43 obj-$(CONFIG_TCP_CONG_CUBIC) += tcp_cubic.o 43 obj-$(CONFIG_TCP_CONG_CUBIC) += tcp_cubic.o
44 obj-$(CONFIG_TCP_CONG_WESTWOOD) += tcp_westwood.o 44 obj-$(CONFIG_TCP_CONG_WESTWOOD) += tcp_westwood.o
45 obj-$(CONFIG_TCP_CONG_HSTCP) += tcp_highspeed.o 45 obj-$(CONFIG_TCP_CONG_HSTCP) += tcp_highspeed.o
46 obj-$(CONFIG_TCP_CONG_HYBLA) += tcp_hybla.o 46 obj-$(CONFIG_TCP_CONG_HYBLA) += tcp_hybla.o
47 obj-$(CONFIG_TCP_CONG_HTCP) += tcp_htcp.o 47 obj-$(CONFIG_TCP_CONG_HTCP) += tcp_htcp.o
48 obj-$(CONFIG_TCP_CONG_VEGAS) += tcp_vegas.o 48 obj-$(CONFIG_TCP_CONG_VEGAS) += tcp_vegas.o
49 obj-$(CONFIG_TCP_CONG_VENO) += tcp_veno.o 49 obj-$(CONFIG_TCP_CONG_VENO) += tcp_veno.o
50 obj-$(CONFIG_TCP_CONG_SCALABLE) += tcp_scalable.o 50 obj-$(CONFIG_TCP_CONG_SCALABLE) += tcp_scalable.o
51 obj-$(CONFIG_TCP_CONG_LP) += tcp_lp.o 51 obj-$(CONFIG_TCP_CONG_LP) += tcp_lp.o
52 obj-$(CONFIG_TCP_CONG_YEAH) += tcp_yeah.o 52 obj-$(CONFIG_TCP_CONG_YEAH) += tcp_yeah.o
53 obj-$(CONFIG_TCP_CONG_ILLINOIS) += tcp_illinois.o 53 obj-$(CONFIG_TCP_CONG_ILLINOIS) += tcp_illinois.o
54 obj-$(CONFIG_MEMCG_KMEM) += tcp_memcontrol.o 54 obj-$(CONFIG_MEMCG_KMEM) += tcp_memcontrol.o
55 obj-$(CONFIG_NETLABEL) += cipso_ipv4.o 55 obj-$(CONFIG_NETLABEL) += cipso_ipv4.o
56 56
57 obj-$(CONFIG_XFRM) += xfrm4_policy.o xfrm4_state.o xfrm4_input.o \ 57 obj-$(CONFIG_XFRM) += xfrm4_policy.o xfrm4_state.o xfrm4_input.o \
58 xfrm4_output.o 58 xfrm4_output.o
59 59
net/ipv4/gre_demux.c
1 /* 1 /*
2 * GRE over IPv4 demultiplexer driver 2 * GRE over IPv4 demultiplexer driver
3 * 3 *
4 * Authors: Dmitry Kozlov (xeb@mail.ru) 4 * Authors: Dmitry Kozlov (xeb@mail.ru)
5 * 5 *
6 * This program is free software; you can redistribute it and/or 6 * This program is free software; you can redistribute it and/or
7 * modify it under the terms of the GNU General Public License 7 * modify it under the terms of the GNU General Public License
8 * as published by the Free Software Foundation; either version 8 * as published by the Free Software Foundation; either version
9 * 2 of the License, or (at your option) any later version. 9 * 2 of the License, or (at your option) any later version.
10 * 10 *
11 */ 11 */
12 12
13 #define pr_fmt(fmt) KBUILD_MODNAME ": " fmt 13 #define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
14 14
15 #include <linux/module.h> 15 #include <linux/module.h>
16 #include <linux/if.h> 16 #include <linux/if.h>
17 #include <linux/icmp.h> 17 #include <linux/icmp.h>
18 #include <linux/kernel.h> 18 #include <linux/kernel.h>
19 #include <linux/kmod.h> 19 #include <linux/kmod.h>
20 #include <linux/skbuff.h> 20 #include <linux/skbuff.h>
21 #include <linux/in.h> 21 #include <linux/in.h>
22 #include <linux/ip.h> 22 #include <linux/ip.h>
23 #include <linux/netdevice.h> 23 #include <linux/netdevice.h>
24 #include <linux/if_tunnel.h> 24 #include <linux/if_tunnel.h>
25 #include <linux/spinlock.h> 25 #include <linux/spinlock.h>
26 #include <net/protocol.h> 26 #include <net/protocol.h>
27 #include <net/gre.h> 27 #include <net/gre.h>
28 28
29 #include <net/icmp.h> 29 #include <net/icmp.h>
30 #include <net/route.h> 30 #include <net/route.h>
31 #include <net/xfrm.h> 31 #include <net/xfrm.h>
32 32
33 static const struct gre_protocol __rcu *gre_proto[GREPROTO_MAX] __read_mostly; 33 static const struct gre_protocol __rcu *gre_proto[GREPROTO_MAX] __read_mostly;
34 static struct gre_cisco_protocol __rcu *gre_cisco_proto_list[GRE_IP_PROTO_MAX]; 34 static struct gre_cisco_protocol __rcu *gre_cisco_proto_list[GRE_IP_PROTO_MAX];
35 35
36 int gre_add_protocol(const struct gre_protocol *proto, u8 version) 36 int gre_add_protocol(const struct gre_protocol *proto, u8 version)
37 { 37 {
38 if (version >= GREPROTO_MAX) 38 if (version >= GREPROTO_MAX)
39 return -EINVAL; 39 return -EINVAL;
40 40
41 return (cmpxchg((const struct gre_protocol **)&gre_proto[version], NULL, proto) == NULL) ? 41 return (cmpxchg((const struct gre_protocol **)&gre_proto[version], NULL, proto) == NULL) ?
42 0 : -EBUSY; 42 0 : -EBUSY;
43 } 43 }
44 EXPORT_SYMBOL_GPL(gre_add_protocol); 44 EXPORT_SYMBOL_GPL(gre_add_protocol);
45 45
46 int gre_del_protocol(const struct gre_protocol *proto, u8 version) 46 int gre_del_protocol(const struct gre_protocol *proto, u8 version)
47 { 47 {
48 int ret; 48 int ret;
49 49
50 if (version >= GREPROTO_MAX) 50 if (version >= GREPROTO_MAX)
51 return -EINVAL; 51 return -EINVAL;
52 52
53 ret = (cmpxchg((const struct gre_protocol **)&gre_proto[version], proto, NULL) == proto) ? 53 ret = (cmpxchg((const struct gre_protocol **)&gre_proto[version], proto, NULL) == proto) ?
54 0 : -EBUSY; 54 0 : -EBUSY;
55 55
56 if (ret) 56 if (ret)
57 return ret; 57 return ret;
58 58
59 synchronize_rcu(); 59 synchronize_rcu();
60 return 0; 60 return 0;
61 } 61 }
62 EXPORT_SYMBOL_GPL(gre_del_protocol); 62 EXPORT_SYMBOL_GPL(gre_del_protocol);
63 63
64 void gre_build_header(struct sk_buff *skb, const struct tnl_ptk_info *tpi, 64 void gre_build_header(struct sk_buff *skb, const struct tnl_ptk_info *tpi,
65 int hdr_len) 65 int hdr_len)
66 { 66 {
67 struct gre_base_hdr *greh; 67 struct gre_base_hdr *greh;
68 68
69 skb_push(skb, hdr_len); 69 skb_push(skb, hdr_len);
70 70
71 greh = (struct gre_base_hdr *)skb->data; 71 greh = (struct gre_base_hdr *)skb->data;
72 greh->flags = tnl_flags_to_gre_flags(tpi->flags); 72 greh->flags = tnl_flags_to_gre_flags(tpi->flags);
73 greh->protocol = tpi->proto; 73 greh->protocol = tpi->proto;
74 74
75 if (tpi->flags&(TUNNEL_KEY|TUNNEL_CSUM|TUNNEL_SEQ)) { 75 if (tpi->flags&(TUNNEL_KEY|TUNNEL_CSUM|TUNNEL_SEQ)) {
76 __be32 *ptr = (__be32 *)(((u8 *)greh) + hdr_len - 4); 76 __be32 *ptr = (__be32 *)(((u8 *)greh) + hdr_len - 4);
77 77
78 if (tpi->flags&TUNNEL_SEQ) { 78 if (tpi->flags&TUNNEL_SEQ) {
79 *ptr = tpi->seq; 79 *ptr = tpi->seq;
80 ptr--; 80 ptr--;
81 } 81 }
82 if (tpi->flags&TUNNEL_KEY) { 82 if (tpi->flags&TUNNEL_KEY) {
83 *ptr = tpi->key; 83 *ptr = tpi->key;
84 ptr--; 84 ptr--;
85 } 85 }
86 if (tpi->flags&TUNNEL_CSUM && 86 if (tpi->flags&TUNNEL_CSUM &&
87 !(skb_shinfo(skb)->gso_type & SKB_GSO_GRE)) { 87 !(skb_shinfo(skb)->gso_type & SKB_GSO_GRE)) {
88 *ptr = 0; 88 *ptr = 0;
89 *(__sum16 *)ptr = csum_fold(skb_checksum(skb, 0, 89 *(__sum16 *)ptr = csum_fold(skb_checksum(skb, 0,
90 skb->len, 0)); 90 skb->len, 0));
91 } 91 }
92 } 92 }
93 } 93 }
94 EXPORT_SYMBOL_GPL(gre_build_header); 94 EXPORT_SYMBOL_GPL(gre_build_header);
95 95
96 static __sum16 check_checksum(struct sk_buff *skb) 96 static __sum16 check_checksum(struct sk_buff *skb)
97 { 97 {
98 __sum16 csum = 0; 98 __sum16 csum = 0;
99 99
100 switch (skb->ip_summed) { 100 switch (skb->ip_summed) {
101 case CHECKSUM_COMPLETE: 101 case CHECKSUM_COMPLETE:
102 csum = csum_fold(skb->csum); 102 csum = csum_fold(skb->csum);
103 103
104 if (!csum) 104 if (!csum)
105 break; 105 break;
106 /* Fall through. */ 106 /* Fall through. */
107 107
108 case CHECKSUM_NONE: 108 case CHECKSUM_NONE:
109 skb->csum = 0; 109 skb->csum = 0;
110 csum = __skb_checksum_complete(skb); 110 csum = __skb_checksum_complete(skb);
111 skb->ip_summed = CHECKSUM_COMPLETE; 111 skb->ip_summed = CHECKSUM_COMPLETE;
112 break; 112 break;
113 } 113 }
114 114
115 return csum; 115 return csum;
116 } 116 }
117 117
118 static int parse_gre_header(struct sk_buff *skb, struct tnl_ptk_info *tpi, 118 static int parse_gre_header(struct sk_buff *skb, struct tnl_ptk_info *tpi,
119 bool *csum_err) 119 bool *csum_err)
120 { 120 {
121 unsigned int ip_hlen = ip_hdrlen(skb); 121 unsigned int ip_hlen = ip_hdrlen(skb);
122 const struct gre_base_hdr *greh; 122 const struct gre_base_hdr *greh;
123 __be32 *options; 123 __be32 *options;
124 int hdr_len; 124 int hdr_len;
125 125
126 if (unlikely(!pskb_may_pull(skb, sizeof(struct gre_base_hdr)))) 126 if (unlikely(!pskb_may_pull(skb, sizeof(struct gre_base_hdr))))
127 return -EINVAL; 127 return -EINVAL;
128 128
129 greh = (struct gre_base_hdr *)(skb_network_header(skb) + ip_hlen); 129 greh = (struct gre_base_hdr *)(skb_network_header(skb) + ip_hlen);
130 if (unlikely(greh->flags & (GRE_VERSION | GRE_ROUTING))) 130 if (unlikely(greh->flags & (GRE_VERSION | GRE_ROUTING)))
131 return -EINVAL; 131 return -EINVAL;
132 132
133 tpi->flags = gre_flags_to_tnl_flags(greh->flags); 133 tpi->flags = gre_flags_to_tnl_flags(greh->flags);
134 hdr_len = ip_gre_calc_hlen(tpi->flags); 134 hdr_len = ip_gre_calc_hlen(tpi->flags);
135 135
136 if (!pskb_may_pull(skb, hdr_len)) 136 if (!pskb_may_pull(skb, hdr_len))
137 return -EINVAL; 137 return -EINVAL;
138 138
139 greh = (struct gre_base_hdr *)(skb_network_header(skb) + ip_hlen); 139 greh = (struct gre_base_hdr *)(skb_network_header(skb) + ip_hlen);
140 tpi->proto = greh->protocol; 140 tpi->proto = greh->protocol;
141 141
142 options = (__be32 *)(greh + 1); 142 options = (__be32 *)(greh + 1);
143 if (greh->flags & GRE_CSUM) { 143 if (greh->flags & GRE_CSUM) {
144 if (check_checksum(skb)) { 144 if (check_checksum(skb)) {
145 *csum_err = true; 145 *csum_err = true;
146 return -EINVAL; 146 return -EINVAL;
147 } 147 }
148 options++; 148 options++;
149 } 149 }
150 150
151 if (greh->flags & GRE_KEY) { 151 if (greh->flags & GRE_KEY) {
152 tpi->key = *options; 152 tpi->key = *options;
153 options++; 153 options++;
154 } else 154 } else
155 tpi->key = 0; 155 tpi->key = 0;
156 156
157 if (unlikely(greh->flags & GRE_SEQ)) { 157 if (unlikely(greh->flags & GRE_SEQ)) {
158 tpi->seq = *options; 158 tpi->seq = *options;
159 options++; 159 options++;
160 } else 160 } else
161 tpi->seq = 0; 161 tpi->seq = 0;
162 162
163 /* WCCP version 1 and 2 protocol decoding. 163 /* WCCP version 1 and 2 protocol decoding.
164 * - Change protocol to IP 164 * - Change protocol to IP
165 * - When dealing with WCCPv2, Skip extra 4 bytes in GRE header 165 * - When dealing with WCCPv2, Skip extra 4 bytes in GRE header
166 */ 166 */
167 if (greh->flags == 0 && tpi->proto == htons(ETH_P_WCCP)) { 167 if (greh->flags == 0 && tpi->proto == htons(ETH_P_WCCP)) {
168 tpi->proto = htons(ETH_P_IP); 168 tpi->proto = htons(ETH_P_IP);
169 if ((*(u8 *)options & 0xF0) != 0x40) { 169 if ((*(u8 *)options & 0xF0) != 0x40) {
170 hdr_len += 4; 170 hdr_len += 4;
171 if (!pskb_may_pull(skb, hdr_len)) 171 if (!pskb_may_pull(skb, hdr_len))
172 return -EINVAL; 172 return -EINVAL;
173 } 173 }
174 } 174 }
175 175
176 return iptunnel_pull_header(skb, hdr_len, tpi->proto); 176 return iptunnel_pull_header(skb, hdr_len, tpi->proto);
177 } 177 }
178 178
179 static int gre_cisco_rcv(struct sk_buff *skb) 179 static int gre_cisco_rcv(struct sk_buff *skb)
180 { 180 {
181 struct tnl_ptk_info tpi; 181 struct tnl_ptk_info tpi;
182 int i; 182 int i;
183 bool csum_err = false; 183 bool csum_err = false;
184 184
185 if (parse_gre_header(skb, &tpi, &csum_err) < 0) 185 if (parse_gre_header(skb, &tpi, &csum_err) < 0)
186 goto drop; 186 goto drop;
187 187
188 rcu_read_lock(); 188 rcu_read_lock();
189 for (i = 0; i < GRE_IP_PROTO_MAX; i++) { 189 for (i = 0; i < GRE_IP_PROTO_MAX; i++) {
190 struct gre_cisco_protocol *proto; 190 struct gre_cisco_protocol *proto;
191 int ret; 191 int ret;
192 192
193 proto = rcu_dereference(gre_cisco_proto_list[i]); 193 proto = rcu_dereference(gre_cisco_proto_list[i]);
194 if (!proto) 194 if (!proto)
195 continue; 195 continue;
196 ret = proto->handler(skb, &tpi); 196 ret = proto->handler(skb, &tpi);
197 if (ret == PACKET_RCVD) { 197 if (ret == PACKET_RCVD) {
198 rcu_read_unlock(); 198 rcu_read_unlock();
199 return 0; 199 return 0;
200 } 200 }
201 } 201 }
202 rcu_read_unlock(); 202 rcu_read_unlock();
203 203
204 icmp_send(skb, ICMP_DEST_UNREACH, ICMP_PORT_UNREACH, 0); 204 icmp_send(skb, ICMP_DEST_UNREACH, ICMP_PORT_UNREACH, 0);
205 drop: 205 drop:
206 kfree_skb(skb); 206 kfree_skb(skb);
207 return 0; 207 return 0;
208 } 208 }
209 209
210 static void gre_cisco_err(struct sk_buff *skb, u32 info) 210 static void gre_cisco_err(struct sk_buff *skb, u32 info)
211 { 211 {
212 /* All the routers (except for Linux) return only 212 /* All the routers (except for Linux) return only
213 * 8 bytes of packet payload. It means, that precise relaying of 213 * 8 bytes of packet payload. It means, that precise relaying of
214 * ICMP in the real Internet is absolutely infeasible. 214 * ICMP in the real Internet is absolutely infeasible.
215 * 215 *
216 * Moreover, Cisco "wise men" put GRE key to the third word 216 * Moreover, Cisco "wise men" put GRE key to the third word
217 * in GRE header. It makes impossible maintaining even soft 217 * in GRE header. It makes impossible maintaining even soft
218 * state for keyed 218 * state for keyed
219 * GRE tunnels with enabled checksum. Tell them "thank you". 219 * GRE tunnels with enabled checksum. Tell them "thank you".
220 * 220 *
221 * Well, I wonder, rfc1812 was written by Cisco employee, 221 * Well, I wonder, rfc1812 was written by Cisco employee,
222 * what the hell these idiots break standards established 222 * what the hell these idiots break standards established
223 * by themselves??? 223 * by themselves???
224 */ 224 */
225 225
226 const int type = icmp_hdr(skb)->type; 226 const int type = icmp_hdr(skb)->type;
227 const int code = icmp_hdr(skb)->code; 227 const int code = icmp_hdr(skb)->code;
228 struct tnl_ptk_info tpi; 228 struct tnl_ptk_info tpi;
229 bool csum_err = false; 229 bool csum_err = false;
230 int i; 230 int i;
231 231
232 if (parse_gre_header(skb, &tpi, &csum_err)) { 232 if (parse_gre_header(skb, &tpi, &csum_err)) {
233 if (!csum_err) /* ignore csum errors. */ 233 if (!csum_err) /* ignore csum errors. */
234 return; 234 return;
235 } 235 }
236 236
237 if (type == ICMP_DEST_UNREACH && code == ICMP_FRAG_NEEDED) { 237 if (type == ICMP_DEST_UNREACH && code == ICMP_FRAG_NEEDED) {
238 ipv4_update_pmtu(skb, dev_net(skb->dev), info, 238 ipv4_update_pmtu(skb, dev_net(skb->dev), info,
239 skb->dev->ifindex, 0, IPPROTO_GRE, 0); 239 skb->dev->ifindex, 0, IPPROTO_GRE, 0);
240 return; 240 return;
241 } 241 }
242 if (type == ICMP_REDIRECT) { 242 if (type == ICMP_REDIRECT) {
243 ipv4_redirect(skb, dev_net(skb->dev), skb->dev->ifindex, 0, 243 ipv4_redirect(skb, dev_net(skb->dev), skb->dev->ifindex, 0,
244 IPPROTO_GRE, 0); 244 IPPROTO_GRE, 0);
245 return; 245 return;
246 } 246 }
247 247
248 rcu_read_lock(); 248 rcu_read_lock();
249 for (i = 0; i < GRE_IP_PROTO_MAX; i++) { 249 for (i = 0; i < GRE_IP_PROTO_MAX; i++) {
250 struct gre_cisco_protocol *proto; 250 struct gre_cisco_protocol *proto;
251 251
252 proto = rcu_dereference(gre_cisco_proto_list[i]); 252 proto = rcu_dereference(gre_cisco_proto_list[i]);
253 if (!proto) 253 if (!proto)
254 continue; 254 continue;
255 255
256 if (proto->err_handler(skb, info, &tpi) == PACKET_RCVD) 256 if (proto->err_handler(skb, info, &tpi) == PACKET_RCVD)
257 goto out; 257 goto out;
258 258
259 } 259 }
260 out: 260 out:
261 rcu_read_unlock(); 261 rcu_read_unlock();
262 } 262 }
263 263
264 static int gre_rcv(struct sk_buff *skb) 264 static int gre_rcv(struct sk_buff *skb)
265 { 265 {
266 const struct gre_protocol *proto; 266 const struct gre_protocol *proto;
267 u8 ver; 267 u8 ver;
268 int ret; 268 int ret;
269 269
270 if (!pskb_may_pull(skb, 12)) 270 if (!pskb_may_pull(skb, 12))
271 goto drop; 271 goto drop;
272 272
273 ver = skb->data[1]&0x7f; 273 ver = skb->data[1]&0x7f;
274 if (ver >= GREPROTO_MAX) 274 if (ver >= GREPROTO_MAX)
275 goto drop; 275 goto drop;
276 276
277 rcu_read_lock(); 277 rcu_read_lock();
278 proto = rcu_dereference(gre_proto[ver]); 278 proto = rcu_dereference(gre_proto[ver]);
279 if (!proto || !proto->handler) 279 if (!proto || !proto->handler)
280 goto drop_unlock; 280 goto drop_unlock;
281 ret = proto->handler(skb); 281 ret = proto->handler(skb);
282 rcu_read_unlock(); 282 rcu_read_unlock();
283 return ret; 283 return ret;
284 284
285 drop_unlock: 285 drop_unlock:
286 rcu_read_unlock(); 286 rcu_read_unlock();
287 drop: 287 drop:
288 kfree_skb(skb); 288 kfree_skb(skb);
289 return NET_RX_DROP; 289 return NET_RX_DROP;
290 } 290 }
291 291
292 static void gre_err(struct sk_buff *skb, u32 info) 292 static void gre_err(struct sk_buff *skb, u32 info)
293 { 293 {
294 const struct gre_protocol *proto; 294 const struct gre_protocol *proto;
295 const struct iphdr *iph = (const struct iphdr *)skb->data; 295 const struct iphdr *iph = (const struct iphdr *)skb->data;
296 u8 ver = skb->data[(iph->ihl<<2) + 1]&0x7f; 296 u8 ver = skb->data[(iph->ihl<<2) + 1]&0x7f;
297 297
298 if (ver >= GREPROTO_MAX) 298 if (ver >= GREPROTO_MAX)
299 return; 299 return;
300 300
301 rcu_read_lock(); 301 rcu_read_lock();
302 proto = rcu_dereference(gre_proto[ver]); 302 proto = rcu_dereference(gre_proto[ver]);
303 if (proto && proto->err_handler) 303 if (proto && proto->err_handler)
304 proto->err_handler(skb, info); 304 proto->err_handler(skb, info);
305 rcu_read_unlock(); 305 rcu_read_unlock();
306 } 306 }
307 307
308 static const struct net_protocol net_gre_protocol = { 308 static const struct net_protocol net_gre_protocol = {
309 .handler = gre_rcv, 309 .handler = gre_rcv,
310 .err_handler = gre_err, 310 .err_handler = gre_err,
311 .netns_ok = 1, 311 .netns_ok = 1,
312 }; 312 };
313 313
314 static const struct gre_protocol ipgre_protocol = { 314 static const struct gre_protocol ipgre_protocol = {
315 .handler = gre_cisco_rcv, 315 .handler = gre_cisco_rcv,
316 .err_handler = gre_cisco_err, 316 .err_handler = gre_cisco_err,
317 }; 317 };
318 318
319 int gre_cisco_register(struct gre_cisco_protocol *newp) 319 int gre_cisco_register(struct gre_cisco_protocol *newp)
320 { 320 {
321 struct gre_cisco_protocol **proto = (struct gre_cisco_protocol **) 321 struct gre_cisco_protocol **proto = (struct gre_cisco_protocol **)
322 &gre_cisco_proto_list[newp->priority]; 322 &gre_cisco_proto_list[newp->priority];
323 323
324 return (cmpxchg(proto, NULL, newp) == NULL) ? 0 : -EBUSY; 324 return (cmpxchg(proto, NULL, newp) == NULL) ? 0 : -EBUSY;
325 } 325 }
326 EXPORT_SYMBOL_GPL(gre_cisco_register); 326 EXPORT_SYMBOL_GPL(gre_cisco_register);
327 327
328 int gre_cisco_unregister(struct gre_cisco_protocol *del_proto) 328 int gre_cisco_unregister(struct gre_cisco_protocol *del_proto)
329 { 329 {
330 struct gre_cisco_protocol **proto = (struct gre_cisco_protocol **) 330 struct gre_cisco_protocol **proto = (struct gre_cisco_protocol **)
331 &gre_cisco_proto_list[del_proto->priority]; 331 &gre_cisco_proto_list[del_proto->priority];
332 int ret; 332 int ret;
333 333
334 ret = (cmpxchg(proto, del_proto, NULL) == del_proto) ? 0 : -EINVAL; 334 ret = (cmpxchg(proto, del_proto, NULL) == del_proto) ? 0 : -EINVAL;
335 335
336 if (ret) 336 if (ret)
337 return ret; 337 return ret;
338 338
339 synchronize_net(); 339 synchronize_net();
340 return 0; 340 return 0;
341 } 341 }
342 EXPORT_SYMBOL_GPL(gre_cisco_unregister); 342 EXPORT_SYMBOL_GPL(gre_cisco_unregister);
343 343
344 static int __init gre_init(void) 344 static int __init gre_init(void)
345 { 345 {
346 pr_info("GRE over IPv4 demultiplexor driver\n"); 346 pr_info("GRE over IPv4 demultiplexor driver\n");
347 347
348 if (inet_add_protocol(&net_gre_protocol, IPPROTO_GRE) < 0) { 348 if (inet_add_protocol(&net_gre_protocol, IPPROTO_GRE) < 0) {
349 pr_err("can't add protocol\n"); 349 pr_err("can't add protocol\n");
350 goto err; 350 goto err;
351 } 351 }
352 352
353 if (gre_add_protocol(&ipgre_protocol, GREPROTO_CISCO) < 0) { 353 if (gre_add_protocol(&ipgre_protocol, GREPROTO_CISCO) < 0) {
354 pr_info("%s: can't add ipgre handler\n", __func__); 354 pr_info("%s: can't add ipgre handler\n", __func__);
355 goto err_gre; 355 goto err_gre;
356 } 356 }
357 357
358 if (gre_offload_init()) {
359 pr_err("can't add protocol offload\n");
360 goto err_gso;
361 }
362
363 return 0; 358 return 0;
364 err_gso:
365 gre_del_protocol(&ipgre_protocol, GREPROTO_CISCO);
366 err_gre: 359 err_gre:
367 inet_del_protocol(&net_gre_protocol, IPPROTO_GRE); 360 inet_del_protocol(&net_gre_protocol, IPPROTO_GRE);
368 err: 361 err:
369 return -EAGAIN; 362 return -EAGAIN;
370 } 363 }
371 364
372 static void __exit gre_exit(void) 365 static void __exit gre_exit(void)
373 { 366 {
374 gre_offload_exit();
375
376 gre_del_protocol(&ipgre_protocol, GREPROTO_CISCO); 367 gre_del_protocol(&ipgre_protocol, GREPROTO_CISCO);
377 inet_del_protocol(&net_gre_protocol, IPPROTO_GRE); 368 inet_del_protocol(&net_gre_protocol, IPPROTO_GRE);
378 } 369 }
379 370
380 module_init(gre_init); 371 module_init(gre_init);
381 module_exit(gre_exit); 372 module_exit(gre_exit);
382 373
383 MODULE_DESCRIPTION("GRE over IPv4 demultiplexer driver"); 374 MODULE_DESCRIPTION("GRE over IPv4 demultiplexer driver");
384 MODULE_AUTHOR("D. Kozlov (xeb@mail.ru)"); 375 MODULE_AUTHOR("D. Kozlov (xeb@mail.ru)");
385 MODULE_LICENSE("GPL"); 376 MODULE_LICENSE("GPL");
386 377
net/ipv4/gre_offload.c
1 /* 1 /*
2 * IPV4 GSO/GRO offload support 2 * IPV4 GSO/GRO offload support
3 * Linux INET implementation 3 * Linux INET implementation
4 * 4 *
5 * This program is free software; you can redistribute it and/or 5 * This program is free software; you can redistribute it and/or
6 * modify it under the terms of the GNU General Public License 6 * modify it under the terms of the GNU General Public License
7 * as published by the Free Software Foundation; either version 7 * as published by the Free Software Foundation; either version
8 * 2 of the License, or (at your option) any later version. 8 * 2 of the License, or (at your option) any later version.
9 * 9 *
10 * GRE GSO support 10 * GRE GSO support
11 */ 11 */
12 12
13 #include <linux/skbuff.h> 13 #include <linux/skbuff.h>
14 #include <net/protocol.h> 14 #include <net/protocol.h>
15 #include <net/gre.h> 15 #include <net/gre.h>
16 16
17 static int gre_gso_send_check(struct sk_buff *skb) 17 static int gre_gso_send_check(struct sk_buff *skb)
18 { 18 {
19 if (!skb->encapsulation) 19 if (!skb->encapsulation)
20 return -EINVAL; 20 return -EINVAL;
21 return 0; 21 return 0;
22 } 22 }
23 23
24 static struct sk_buff *gre_gso_segment(struct sk_buff *skb, 24 static struct sk_buff *gre_gso_segment(struct sk_buff *skb,
25 netdev_features_t features) 25 netdev_features_t features)
26 { 26 {
27 struct sk_buff *segs = ERR_PTR(-EINVAL); 27 struct sk_buff *segs = ERR_PTR(-EINVAL);
28 netdev_features_t enc_features; 28 netdev_features_t enc_features;
29 int ghl = GRE_HEADER_SECTION; 29 int ghl = GRE_HEADER_SECTION;
30 struct gre_base_hdr *greh; 30 struct gre_base_hdr *greh;
31 u16 mac_offset = skb->mac_header; 31 u16 mac_offset = skb->mac_header;
32 int mac_len = skb->mac_len; 32 int mac_len = skb->mac_len;
33 __be16 protocol = skb->protocol; 33 __be16 protocol = skb->protocol;
34 int tnl_hlen; 34 int tnl_hlen;
35 bool csum; 35 bool csum;
36 36
37 if (unlikely(skb_shinfo(skb)->gso_type & 37 if (unlikely(skb_shinfo(skb)->gso_type &
38 ~(SKB_GSO_TCPV4 | 38 ~(SKB_GSO_TCPV4 |
39 SKB_GSO_TCPV6 | 39 SKB_GSO_TCPV6 |
40 SKB_GSO_UDP | 40 SKB_GSO_UDP |
41 SKB_GSO_DODGY | 41 SKB_GSO_DODGY |
42 SKB_GSO_TCP_ECN | 42 SKB_GSO_TCP_ECN |
43 SKB_GSO_GRE | 43 SKB_GSO_GRE |
44 SKB_GSO_IPIP))) 44 SKB_GSO_IPIP)))
45 goto out; 45 goto out;
46 46
47 if (unlikely(!pskb_may_pull(skb, sizeof(*greh)))) 47 if (unlikely(!pskb_may_pull(skb, sizeof(*greh))))
48 goto out; 48 goto out;
49 49
50 greh = (struct gre_base_hdr *)skb_transport_header(skb); 50 greh = (struct gre_base_hdr *)skb_transport_header(skb);
51 51
52 if (greh->flags & GRE_KEY) 52 if (greh->flags & GRE_KEY)
53 ghl += GRE_HEADER_SECTION; 53 ghl += GRE_HEADER_SECTION;
54 if (greh->flags & GRE_SEQ) 54 if (greh->flags & GRE_SEQ)
55 ghl += GRE_HEADER_SECTION; 55 ghl += GRE_HEADER_SECTION;
56 if (greh->flags & GRE_CSUM) { 56 if (greh->flags & GRE_CSUM) {
57 ghl += GRE_HEADER_SECTION; 57 ghl += GRE_HEADER_SECTION;
58 csum = true; 58 csum = true;
59 } else 59 } else
60 csum = false; 60 csum = false;
61 61
62 if (unlikely(!pskb_may_pull(skb, ghl))) 62 if (unlikely(!pskb_may_pull(skb, ghl)))
63 goto out; 63 goto out;
64 64
65 /* setup inner skb. */ 65 /* setup inner skb. */
66 skb->protocol = greh->protocol; 66 skb->protocol = greh->protocol;
67 skb->encapsulation = 0; 67 skb->encapsulation = 0;
68 68
69 __skb_pull(skb, ghl); 69 __skb_pull(skb, ghl);
70 skb_reset_mac_header(skb); 70 skb_reset_mac_header(skb);
71 skb_set_network_header(skb, skb_inner_network_offset(skb)); 71 skb_set_network_header(skb, skb_inner_network_offset(skb));
72 skb->mac_len = skb_inner_network_offset(skb); 72 skb->mac_len = skb_inner_network_offset(skb);
73 73
74 /* segment inner packet. */ 74 /* segment inner packet. */
75 enc_features = skb->dev->hw_enc_features & netif_skb_features(skb); 75 enc_features = skb->dev->hw_enc_features & netif_skb_features(skb);
76 segs = skb_mac_gso_segment(skb, enc_features); 76 segs = skb_mac_gso_segment(skb, enc_features);
77 if (!segs || IS_ERR(segs)) { 77 if (!segs || IS_ERR(segs)) {
78 skb_gso_error_unwind(skb, protocol, ghl, mac_offset, mac_len); 78 skb_gso_error_unwind(skb, protocol, ghl, mac_offset, mac_len);
79 goto out; 79 goto out;
80 } 80 }
81 81
82 skb = segs; 82 skb = segs;
83 tnl_hlen = skb_tnl_header_len(skb); 83 tnl_hlen = skb_tnl_header_len(skb);
84 do { 84 do {
85 __skb_push(skb, ghl); 85 __skb_push(skb, ghl);
86 if (csum) { 86 if (csum) {
87 __be32 *pcsum; 87 __be32 *pcsum;
88 88
89 if (skb_has_shared_frag(skb)) { 89 if (skb_has_shared_frag(skb)) {
90 int err; 90 int err;
91 91
92 err = __skb_linearize(skb); 92 err = __skb_linearize(skb);
93 if (err) { 93 if (err) {
94 kfree_skb_list(segs); 94 kfree_skb_list(segs);
95 segs = ERR_PTR(err); 95 segs = ERR_PTR(err);
96 goto out; 96 goto out;
97 } 97 }
98 } 98 }
99 99
100 greh = (struct gre_base_hdr *)(skb->data); 100 greh = (struct gre_base_hdr *)(skb->data);
101 pcsum = (__be32 *)(greh + 1); 101 pcsum = (__be32 *)(greh + 1);
102 *pcsum = 0; 102 *pcsum = 0;
103 *(__sum16 *)pcsum = csum_fold(skb_checksum(skb, 0, skb->len, 0)); 103 *(__sum16 *)pcsum = csum_fold(skb_checksum(skb, 0, skb->len, 0));
104 } 104 }
105 __skb_push(skb, tnl_hlen - ghl); 105 __skb_push(skb, tnl_hlen - ghl);
106 106
107 skb_reset_inner_headers(skb); 107 skb_reset_inner_headers(skb);
108 skb->encapsulation = 1; 108 skb->encapsulation = 1;
109 109
110 skb_reset_mac_header(skb); 110 skb_reset_mac_header(skb);
111 skb_set_network_header(skb, mac_len); 111 skb_set_network_header(skb, mac_len);
112 skb->mac_len = mac_len; 112 skb->mac_len = mac_len;
113 skb->protocol = protocol; 113 skb->protocol = protocol;
114 } while ((skb = skb->next)); 114 } while ((skb = skb->next));
115 out: 115 out:
116 return segs; 116 return segs;
117 } 117 }
118 118
119 static const struct net_offload gre_offload = { 119 static const struct net_offload gre_offload = {
120 .callbacks = { 120 .callbacks = {
121 .gso_send_check = gre_gso_send_check, 121 .gso_send_check = gre_gso_send_check,
122 .gso_segment = gre_gso_segment, 122 .gso_segment = gre_gso_segment,
123 }, 123 },
124 }; 124 };
125 125
126 int __init gre_offload_init(void) 126 static int __init gre_offload_init(void)
127 { 127 {
128 return inet_add_offload(&gre_offload, IPPROTO_GRE); 128 return inet_add_offload(&gre_offload, IPPROTO_GRE);
129 } 129 }
130 130
131 void __exit gre_offload_exit(void) 131 static void __exit gre_offload_exit(void)
132 { 132 {
133 inet_del_offload(&gre_offload, IPPROTO_GRE); 133 inet_del_offload(&gre_offload, IPPROTO_GRE);
134 } 134 }
135
136 module_init(gre_offload_init);
137 module_exit(gre_offload_exit);
135 138