2 * Copyright (c) 2007-2012 Nicira, Inc.
4 * This program is free software; you can redistribute it and/or
5 * modify it under the terms of version 2 of the GNU General Public
6 * License as published by the Free Software Foundation.
8 * This program is distributed in the hope that it will be useful, but
9 * WITHOUT ANY WARRANTY; without even the implied warranty of
10 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
11 * General Public License for more details.
13 * You should have received a copy of the GNU General Public License
14 * along with this program; if not, write to the Free Software
15 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
19 #define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
22 #include <linux/skbuff.h>
24 #include <linux/if_tunnel.h>
25 #include <linux/if_vlan.h>
30 #include <net/protocol.h>
37 * The GRE header is composed of a series of sections: a base and then a variable
40 #define GRE_HEADER_SECTION 4
47 static int gre_hdr_len(const struct ovs_key_ipv4_tunnel
*tun_key
)
49 int len
= GRE_HEADER_SECTION
;
51 if (tun_key
->tun_flags
& OVS_TNL_F_KEY
)
52 len
+= GRE_HEADER_SECTION
;
53 if (tun_key
->tun_flags
& OVS_TNL_F_CSUM
)
54 len
+= GRE_HEADER_SECTION
;
58 static int gre64_hdr_len(const struct ovs_key_ipv4_tunnel
*tun_key
)
60 /* Set key for GRE64 tunnels, even when key if is zero. */
61 int len
= GRE_HEADER_SECTION
+ /* GRE Hdr */
62 GRE_HEADER_SECTION
+ /* GRE Key */
63 GRE_HEADER_SECTION
; /* GRE SEQ */
65 if (tun_key
->tun_flags
& OVS_TNL_F_CSUM
)
66 len
+= GRE_HEADER_SECTION
;
71 /* Returns the least-significant 32 bits of a __be64. */
72 static __be32
be64_get_low32(__be64 x
)
75 return (__force __be32
)x
;
77 return (__force __be32
)((__force u64
)x
>> 32);
81 static __be32
be64_get_high32(__be64 x
)
84 return (__force __be32
)((__force u64
)x
>> 32);
86 return (__force __be32
)x
;
90 static void __gre_build_header(struct sk_buff
*skb
,
94 const struct ovs_key_ipv4_tunnel
*tun_key
= OVS_CB(skb
)->tun_key
;
95 __be32
*options
= (__be32
*)(skb_network_header(skb
) + tunnel_hlen
96 - GRE_HEADER_SECTION
);
97 struct gre_base_hdr
*greh
= (struct gre_base_hdr
*) skb_transport_header(skb
);
98 greh
->protocol
= htons(ETH_P_TEB
);
101 /* Work backwards over the options so the checksum is last. */
102 if (tun_key
->tun_flags
& OVS_TNL_F_KEY
|| is_gre64
) {
103 greh
->flags
|= GRE_KEY
;
105 /* Set higher 32 bits to seq. */
106 *options
= be64_get_high32(tun_key
->tun_id
);
108 greh
->flags
|= GRE_SEQ
;
110 *options
= be64_get_low32(tun_key
->tun_id
);
114 if (tun_key
->tun_flags
& OVS_TNL_F_CSUM
) {
115 greh
->flags
|= GRE_CSUM
;
117 *(__sum16
*)options
= csum_fold(skb_checksum(skb
,
118 skb_transport_offset(skb
),
119 skb
->len
- skb_transport_offset(skb
),
124 static void gre_build_header(const struct vport
*vport
,
128 __gre_build_header(skb
, tunnel_hlen
, false);
131 static void gre64_build_header(const struct vport
*vport
,
135 __gre_build_header(skb
, tunnel_hlen
, true);
138 static __be64
key_to_tunnel_id(__be32 key
, __be32 seq
)
141 return (__force __be64
)((__force u64
)seq
<< 32 | (__force u32
)key
);
143 return (__force __be64
)((__force u64
)key
<< 32 | (__force u32
)seq
);
147 static int parse_header(struct iphdr
*iph
, __be16
*flags
, __be64
*tun_id
,
150 /* IP and ICMP protocol handlers check that the IHL is valid. */
151 struct gre_base_hdr
*greh
= (struct gre_base_hdr
*)((u8
*)iph
+ (iph
->ihl
<< 2));
152 __be32
*options
= (__be32
*)(greh
+ 1);
155 *flags
= greh
->flags
;
157 if (unlikely(greh
->flags
& (GRE_VERSION
| GRE_ROUTING
)))
160 if (unlikely(greh
->protocol
!= htons(ETH_P_TEB
)))
163 hdr_len
= GRE_HEADER_SECTION
;
165 if (greh
->flags
& GRE_CSUM
) {
166 hdr_len
+= GRE_HEADER_SECTION
;
170 if (greh
->flags
& GRE_KEY
) {
175 hdr_len
+= GRE_HEADER_SECTION
;
178 if (greh
->flags
& GRE_SEQ
) {
185 *tun_id
= key_to_tunnel_id(gre_key
, seq
);
188 /* Ignore GRE seq if there is no key present. */
192 if (greh
->flags
& GRE_SEQ
)
193 hdr_len
+= GRE_HEADER_SECTION
;
198 static bool check_checksum(struct sk_buff
*skb
)
200 struct iphdr
*iph
= ip_hdr(skb
);
201 struct gre_base_hdr
*greh
= (struct gre_base_hdr
*)(iph
+ 1);
204 if (greh
->flags
& GRE_CSUM
) {
205 switch (skb
->ip_summed
) {
206 case CHECKSUM_COMPLETE
:
207 csum
= csum_fold(skb
->csum
);
215 csum
= __skb_checksum_complete(skb
);
216 skb
->ip_summed
= CHECKSUM_COMPLETE
;
224 static u32
gre_flags_to_tunnel_flags(__be16 gre_flags
, bool is_gre64
)
226 u32 tunnel_flags
= 0;
228 if (gre_flags
& GRE_KEY
|| is_gre64
)
229 tunnel_flags
= OVS_TNL_F_KEY
;
231 if (gre_flags
& GRE_CSUM
)
232 tunnel_flags
|= OVS_TNL_F_CSUM
;
237 /* Called with rcu_read_lock and BH disabled. */
238 static int gre_rcv(struct sk_buff
*skb
)
240 struct ovs_net
*ovs_net
;
244 struct ovs_key_ipv4_tunnel tun_key
;
250 if (unlikely(!pskb_may_pull(skb
, sizeof(struct gre_base_hdr
) + ETH_HLEN
)))
252 if (unlikely(!check_checksum(skb
)))
255 hdr_len
= parse_header(ip_hdr(skb
), &gre_flags
, &key
, &is_gre64
);
256 if (unlikely(hdr_len
< 0))
259 ovs_net
= net_generic(dev_net(skb
->dev
), ovs_net_id
);
261 vport
= rcu_dereference(ovs_net
->vport_net
.gre64_vport
);
263 vport
= rcu_dereference(ovs_net
->vport_net
.gre_vport
);
264 if (unlikely(!vport
))
267 if (unlikely(!pskb_may_pull(skb
, hdr_len
+ ETH_HLEN
)))
271 tnl_flags
= gre_flags_to_tunnel_flags(gre_flags
, is_gre64
);
272 tnl_tun_key_init(&tun_key
, iph
, key
, tnl_flags
);
274 skb_pull_rcsum(skb
, hdr_len
);
276 ovs_tnl_rcv(vport
, skb
, &tun_key
);
284 static const struct net_protocol gre_protocol_handlers
= {
286 #if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,32)
291 static int gre_ports
;
292 static int gre_init(void)
300 err
= inet_add_protocol(&gre_protocol_handlers
, IPPROTO_GRE
);
302 pr_warn("cannot register gre protocol handler\n");
307 static void gre_exit(void)
313 inet_del_protocol(&gre_protocol_handlers
, IPPROTO_GRE
);
316 static const char *gre_get_name(const struct vport
*vport
)
318 return vport_priv(vport
);
321 static struct vport
*gre_create(const struct vport_parms
*parms
)
323 struct net
*net
= ovs_dp_get_net(parms
->dp
);
324 struct ovs_net
*ovs_net
;
332 ovs_net
= net_generic(net
, ovs_net_id
);
333 if (ovsl_dereference(ovs_net
->vport_net
.gre_vport
)) {
334 vport
= ERR_PTR(-EEXIST
);
338 vport
= ovs_vport_alloc(IFNAMSIZ
, &ovs_gre_vport_ops
, parms
);
342 strncpy(vport_priv(vport
), parms
->name
, IFNAMSIZ
);
343 rcu_assign_pointer(ovs_net
->vport_net
.gre_vport
, vport
);
351 static void gre_tnl_destroy(struct vport
*vport
)
353 struct net
*net
= ovs_dp_get_net(vport
->dp
);
354 struct ovs_net
*ovs_net
;
356 ovs_net
= net_generic(net
, ovs_net_id
);
358 rcu_assign_pointer(ovs_net
->vport_net
.gre_vport
, NULL
);
359 ovs_vport_deferred_free(vport
);
363 static int gre_tnl_send(struct vport
*vport
, struct sk_buff
*skb
)
367 if (unlikely(!OVS_CB(skb
)->tun_key
))
370 hlen
= gre_hdr_len(OVS_CB(skb
)->tun_key
);
371 return ovs_tnl_send(vport
, skb
, IPPROTO_GRE
, hlen
, gre_build_header
);
374 const struct vport_ops ovs_gre_vport_ops
= {
375 .type
= OVS_VPORT_TYPE_GRE
,
376 .create
= gre_create
,
377 .destroy
= gre_tnl_destroy
,
378 .get_name
= gre_get_name
,
379 .send
= gre_tnl_send
,
383 static struct vport
*gre64_create(const struct vport_parms
*parms
)
385 struct net
*net
= ovs_dp_get_net(parms
->dp
);
386 struct ovs_net
*ovs_net
;
394 ovs_net
= net_generic(net
, ovs_net_id
);
395 if (ovsl_dereference(ovs_net
->vport_net
.gre64_vport
)) {
396 vport
= ERR_PTR(-EEXIST
);
400 vport
= ovs_vport_alloc(IFNAMSIZ
, &ovs_gre64_vport_ops
, parms
);
404 strncpy(vport_priv(vport
), parms
->name
, IFNAMSIZ
);
405 rcu_assign_pointer(ovs_net
->vport_net
.gre64_vport
, vport
);
412 static void gre64_tnl_destroy(struct vport
*vport
)
414 struct net
*net
= ovs_dp_get_net(vport
->dp
);
415 struct ovs_net
*ovs_net
;
417 ovs_net
= net_generic(net
, ovs_net_id
);
419 rcu_assign_pointer(ovs_net
->vport_net
.gre64_vport
, NULL
);
420 ovs_vport_deferred_free(vport
);
424 static int gre64_tnl_send(struct vport
*vport
, struct sk_buff
*skb
)
428 if (unlikely(!OVS_CB(skb
)->tun_key
))
431 hlen
= gre64_hdr_len(OVS_CB(skb
)->tun_key
);
432 return ovs_tnl_send(vport
, skb
, IPPROTO_GRE
, hlen
, gre64_build_header
);
435 const struct vport_ops ovs_gre64_vport_ops
= {
436 .type
= OVS_VPORT_TYPE_GRE64
,
437 .create
= gre64_create
,
438 .destroy
= gre64_tnl_destroy
,
439 .get_name
= gre_get_name
,
440 .send
= gre64_tnl_send
,