2 * Copyright (c) 2010 Nicira Networks.
3 * Distributed under the terms of the GNU GPL version 2.
5 * Significant portions of this file may be copied from parts of the Linux
6 * kernel, by Linus Torvalds and others.
10 #include <linux/skbuff.h>
12 #include <linux/if_tunnel.h>
13 #include <linux/if_vlan.h>
18 #include <net/protocol.h>
22 #include "vport-generic.h"
25 * The GRE header is composed of a series of sections: a base and then a variable
28 #define GRE_HEADER_SECTION 4
35 static int gre_hdr_len(const struct tnl_port_config
*port_config
)
39 len
= GRE_HEADER_SECTION
;
41 if (port_config
->flags
& TNL_F_CSUM
)
42 len
+= GRE_HEADER_SECTION
;
44 if (port_config
->out_key
||
45 port_config
->flags
& TNL_F_OUT_KEY_ACTION
)
46 len
+= GRE_HEADER_SECTION
;
51 static void gre_build_header(struct sk_buff
*skb
,
52 const struct vport
*vport
,
53 const struct tnl_mutable_config
*mutable)
55 struct gre_base_hdr
*greh
= (struct gre_base_hdr
*)skb_transport_header(skb
);
56 __be32
*options
= (__be32
*)(skb_network_header(skb
) + mutable->tunnel_hlen
57 - GRE_HEADER_SECTION
);
59 greh
->protocol
= htons(ETH_P_TEB
);
62 /* Work backwards over the options so the checksum is last. */
63 if (mutable->port_config
.out_key
||
64 mutable->port_config
.flags
& TNL_F_OUT_KEY_ACTION
) {
65 greh
->flags
|= GRE_KEY
;
67 if (mutable->port_config
.flags
& TNL_F_OUT_KEY_ACTION
)
68 *options
= OVS_CB(skb
)->tun_id
;
70 *options
= mutable->port_config
.out_key
;
75 if (mutable->port_config
.flags
& TNL_F_CSUM
) {
76 greh
->flags
|= GRE_CSUM
;
79 *(__sum16
*)options
= csum_fold(skb_checksum(skb
,
81 skb
->len
- sizeof(struct iphdr
),
86 static int parse_header(struct iphdr
*iph
, __be16
*flags
, __be32
*key
)
88 /* IP and ICMP protocol handlers check that the IHL is valid. */
89 struct gre_base_hdr
*greh
= (struct gre_base_hdr
*)((u8
*)iph
+ (iph
->ihl
<< 2));
90 __be32
*options
= (__be32
*)(greh
+ 1);
95 if (unlikely(greh
->flags
& (GRE_VERSION
| GRE_ROUTING
)))
98 if (unlikely(greh
->protocol
!= htons(ETH_P_TEB
)))
101 hdr_len
= GRE_HEADER_SECTION
;
103 if (greh
->flags
& GRE_CSUM
) {
104 hdr_len
+= GRE_HEADER_SECTION
;
108 if (greh
->flags
& GRE_KEY
) {
109 hdr_len
+= GRE_HEADER_SECTION
;
116 if (unlikely(greh
->flags
& GRE_SEQ
))
117 hdr_len
+= GRE_HEADER_SECTION
;
122 /* Called with rcu_read_lock and BH disabled. */
123 static void gre_err(struct sk_buff
*skb
, u32 info
)
126 const struct tnl_mutable_config
*mutable;
127 const int type
= icmp_hdr(skb
)->type
;
128 const int code
= icmp_hdr(skb
)->code
;
129 int mtu
= ntohs(icmp_hdr(skb
)->un
.frag
.mtu
);
134 int tunnel_hdr_len
, tot_hdr_len
;
135 unsigned int orig_mac_header
;
136 unsigned int orig_nw_header
;
138 if (type
!= ICMP_DEST_UNREACH
|| code
!= ICMP_FRAG_NEEDED
)
142 * The mimimum size packet that we would actually be able to process:
143 * encapsulating IP header, minimum GRE header, Ethernet header,
146 if (!pskb_may_pull(skb
, sizeof(struct iphdr
) + GRE_HEADER_SECTION
+
147 ETH_HLEN
+ sizeof(struct iphdr
)))
150 iph
= (struct iphdr
*)skb
->data
;
152 tunnel_hdr_len
= parse_header(iph
, &flags
, &key
);
153 if (tunnel_hdr_len
< 0)
156 vport
= tnl_find_port(iph
->saddr
, iph
->daddr
, key
,
157 TNL_T_PROTO_GRE
| TNL_T_KEY_EITHER
, &mutable);
162 * Packets received by this function were previously sent by us, so
163 * any comparisons should be to the output values, not the input.
164 * However, it's not really worth it to have a hash table based on
165 * output keys (especially since ICMP error handling of tunneled packets
166 * isn't that reliable anyways). Therefore, we do a lookup based on the
167 * out key as if it were the in key and then check to see if the input
168 * and output keys are the same.
170 if (mutable->port_config
.in_key
!= mutable->port_config
.out_key
)
173 if (!!(mutable->port_config
.flags
& TNL_F_IN_KEY_MATCH
) !=
174 !!(mutable->port_config
.flags
& TNL_F_OUT_KEY_ACTION
))
177 if ((mutable->port_config
.flags
& TNL_F_CSUM
) && !(flags
& GRE_CSUM
))
180 tunnel_hdr_len
+= iph
->ihl
<< 2;
182 orig_mac_header
= skb_mac_header(skb
) - skb
->data
;
183 orig_nw_header
= skb_network_header(skb
) - skb
->data
;
184 skb_set_mac_header(skb
, tunnel_hdr_len
);
186 tot_hdr_len
= tunnel_hdr_len
+ ETH_HLEN
;
188 skb
->protocol
= eth_hdr(skb
)->h_proto
;
189 if (skb
->protocol
== htons(ETH_P_8021Q
)) {
190 tot_hdr_len
+= VLAN_HLEN
;
191 skb
->protocol
= vlan_eth_hdr(skb
)->h_vlan_encapsulated_proto
;
194 skb_set_network_header(skb
, tot_hdr_len
);
197 if (skb
->protocol
== htons(ETH_P_IP
))
198 tot_hdr_len
+= sizeof(struct iphdr
);
199 #if defined(CONFIG_IPV6) || defined(CONFIG_IPV6_MODULE)
200 else if (skb
->protocol
== htons(ETH_P_IPV6
))
201 tot_hdr_len
+= sizeof(struct ipv6hdr
);
206 if (!pskb_may_pull(skb
, tot_hdr_len
))
209 if (skb
->protocol
== htons(ETH_P_IP
)) {
210 if (mtu
< IP_MIN_MTU
) {
211 if (ntohs(ip_hdr(skb
)->tot_len
) >= IP_MIN_MTU
)
218 #if defined(CONFIG_IPV6) || defined(CONFIG_IPV6_MODULE)
219 else if (skb
->protocol
== htons(ETH_P_IPV6
)) {
220 if (mtu
< IPV6_MIN_MTU
) {
221 unsigned int packet_length
= sizeof(struct ipv6hdr
) +
222 ntohs(ipv6_hdr(skb
)->payload_len
);
224 if (packet_length
>= IPV6_MIN_MTU
225 || ntohs(ipv6_hdr(skb
)->payload_len
) == 0)
233 __skb_pull(skb
, tunnel_hdr_len
);
234 tnl_frag_needed(vport
, mutable, skb
, mtu
, key
);
235 __skb_push(skb
, tunnel_hdr_len
);
238 skb_set_mac_header(skb
, orig_mac_header
);
239 skb_set_network_header(skb
, orig_nw_header
);
240 skb
->protocol
= htons(ETH_P_IP
);
243 static bool check_checksum(struct sk_buff
*skb
)
245 struct iphdr
*iph
= ip_hdr(skb
);
246 struct gre_base_hdr
*greh
= (struct gre_base_hdr
*)(iph
+ 1);
249 if (greh
->flags
& GRE_CSUM
) {
250 switch (skb
->ip_summed
) {
251 case CHECKSUM_COMPLETE
:
252 csum
= csum_fold(skb
->csum
);
260 csum
= __skb_checksum_complete(skb
);
261 skb
->ip_summed
= CHECKSUM_COMPLETE
;
269 /* Called with rcu_read_lock and BH disabled. */
270 static int gre_rcv(struct sk_buff
*skb
)
273 const struct tnl_mutable_config
*mutable;
279 if (unlikely(!pskb_may_pull(skb
, sizeof(struct gre_base_hdr
) + ETH_HLEN
)))
282 if (unlikely(!check_checksum(skb
)))
285 hdr_len
= parse_header(ip_hdr(skb
), &flags
, &key
);
286 if (unlikely(hdr_len
< 0))
289 if (unlikely(!pskb_may_pull(skb
, hdr_len
+ ETH_HLEN
)))
293 vport
= tnl_find_port(iph
->daddr
, iph
->saddr
, key
,
294 TNL_T_PROTO_GRE
| TNL_T_KEY_EITHER
, &mutable);
295 if (unlikely(!vport
)) {
296 icmp_send(skb
, ICMP_DEST_UNREACH
, ICMP_PORT_UNREACH
, 0);
300 if (mutable->port_config
.flags
& TNL_F_IN_KEY_MATCH
)
301 OVS_CB(skb
)->tun_id
= key
;
303 OVS_CB(skb
)->tun_id
= 0;
305 __skb_pull(skb
, hdr_len
);
306 skb_postpull_rcsum(skb
, skb_transport_header(skb
), hdr_len
+ ETH_HLEN
);
316 struct tnl_ops gre_tnl_ops
= {
317 .tunnel_type
= TNL_T_PROTO_GRE
,
318 .ipproto
= IPPROTO_GRE
,
319 .hdr_len
= gre_hdr_len
,
320 .build_header
= gre_build_header
,
323 static struct vport
*gre_create(const char *name
, const void __user
*config
)
325 return tnl_create(name
, config
, &gre_vport_ops
, &gre_tnl_ops
);
328 static struct net_protocol gre_protocol_handlers
= {
330 .err_handler
= gre_err
,
333 static int gre_init(void)
337 err
= inet_add_protocol(&gre_protocol_handlers
, IPPROTO_GRE
);
339 printk(KERN_WARNING
"openvswitch: cannot register gre protocol handler\n");
349 static void gre_exit(void)
352 inet_del_protocol(&gre_protocol_handlers
, IPPROTO_GRE
);
355 struct vport_ops gre_vport_ops
= {
357 .flags
= VPORT_F_GEN_STATS
| VPORT_F_TUN_ID
,
360 .create
= gre_create
,
361 .modify
= tnl_modify
,
362 .destroy
= tnl_destroy
,
363 .set_mtu
= tnl_set_mtu
,
364 .set_addr
= tnl_set_addr
,
365 .get_name
= tnl_get_name
,
366 .get_addr
= tnl_get_addr
,
367 .get_dev_flags
= vport_gen_get_dev_flags
,
368 .is_running
= vport_gen_is_running
,
369 .get_operstate
= vport_gen_get_operstate
,
370 .get_mtu
= tnl_get_mtu
,