[ovs-dev] [PATCH] gre: Check whether IPv6 is compiled into the kernel.
Jesse Gross
jesse at nicira.com
Wed May 19 01:21:14 UTC 2010
Add guards to check whether IPv6 is supported by the kernel instead
of causing the module to fail to load. If IPv6 is not supported
GRE packets can still be encapsulated but they will not receive any
special treatment such as path MTU discovery.
---
datapath/vport-gre.c | 60 +++++++++++++++++++++++++++++++++++++++----------
1 files changed, 47 insertions(+), 13 deletions(-)
diff --git a/datapath/vport-gre.c b/datapath/vport-gre.c
index dbfc100..e731aa7 100644
--- a/datapath/vport-gre.c
+++ b/datapath/vport-gre.c
@@ -22,7 +22,9 @@
#include <net/icmp.h>
#include <net/inet_ecn.h>
#include <net/ip.h>
+#if defined(CONFIG_IPV6) || defined(CONFIG_IPV6_MODULE)
#include <net/ipv6.h>
+#endif
#include <net/protocol.h>
#include <net/route.h>
#include <net/xfrm.h>
@@ -377,6 +379,7 @@ ipv4_build_icmp(struct sk_buff *skb, struct sk_buff *nskb,
icmph->checksum = csum_fold(nskb->csum);
}
+#if defined(CONFIG_IPV6) || defined(CONFIG_IPV6_MODULE)
static bool
ipv6_should_icmp(struct sk_buff *skb)
{
@@ -452,13 +455,14 @@ ipv6_build_icmp(struct sk_buff *skb, struct sk_buff *nskb, unsigned int mtu,
+ payload_length,
ipv6h->nexthdr, nskb->csum);
}
+#endif /* IPv6 */
static bool
send_frag_needed(struct vport *vport, const struct mutable_config *mutable,
struct sk_buff *skb, unsigned int mtu, __be32 flow_key)
{
unsigned int eth_hdr_len = ETH_HLEN;
- unsigned int total_length, header_length, payload_length;
+ unsigned int total_length, header_length = 0, payload_length = 0;
struct ethhdr *eh, *old_eh = eth_hdr(skb);
struct sk_buff *nskb;
@@ -469,7 +473,9 @@ send_frag_needed(struct vport *vport, const struct mutable_config *mutable,
if (!ipv4_should_icmp(skb))
return true;
- } else {
+ }
+#if defined(CONFIG_IPV6) || defined(CONFIG_IPV6_MODULE)
+ else if (skb->protocol == htons(ETH_P_IPV6)) {
if (mtu < IPV6_MIN_MTU)
return false;
@@ -481,6 +487,9 @@ send_frag_needed(struct vport *vport, const struct mutable_config *mutable,
if (!ipv6_should_icmp(skb))
return true;
}
+#endif
+ else
+ return false;
/* Allocate */
if (old_eh->h_proto == htons(ETH_P_8021Q))
@@ -491,12 +500,16 @@ send_frag_needed(struct vport *vport, const struct mutable_config *mutable,
header_length = sizeof(struct iphdr) + sizeof(struct icmphdr);
total_length = min_t(unsigned int, header_length +
payload_length, 576);
- } else {
+ }
+#if defined(CONFIG_IPV6) || defined(CONFIG_IPV6_MODULE)
+ else {
header_length = sizeof(struct ipv6hdr) +
sizeof(struct icmp6hdr);
total_length = min_t(unsigned int, header_length +
payload_length, IPV6_MIN_MTU);
}
+#endif
+
total_length = min(total_length, mutable->mtu);
payload_length = total_length - header_length;
@@ -523,8 +536,10 @@ send_frag_needed(struct vport *vport, const struct mutable_config *mutable,
/* Protocol */
if (skb->protocol == htons(ETH_P_IP))
ipv4_build_icmp(skb, nskb, mtu, payload_length);
+#if defined(CONFIG_IPV6) || defined(CONFIG_IPV6_MODULE)
else
ipv6_build_icmp(skb, nskb, mtu, payload_length);
+#endif
/* Assume that flow based keys are symmetric with respect to input
* and output and use the key that we were going to put on the
@@ -672,8 +687,10 @@ ecn_encapsulate(u8 tos, struct sk_buff *skb)
if (skb->protocol == htons(ETH_P_IP))
inner = ((struct iphdr *)skb_network_header(skb))->tos;
+#if defined(CONFIG_IPV6) || defined(CONFIG_IPV6_MODULE)
else if (skb->protocol == htons(ETH_P_IPV6))
inner = ipv6_get_dsfield((struct ipv6hdr *)skb_network_header(skb));
+#endif
else
inner = 0;
@@ -701,7 +718,9 @@ ecn_decapsulate(u8 tos, struct sk_buff *skb)
return;
IP_ECN_set_ce((struct iphdr *)(nw_header + skb->data));
- } else if (protocol == htons(ETH_P_IPV6)) {
+ }
+#if defined(CONFIG_IPV6) || defined(CONFIG_IPV6_MODULE)
+ else if (protocol == htons(ETH_P_IPV6)) {
if (unlikely(!pskb_may_pull(skb, nw_header
+ sizeof(struct ipv6hdr))))
return;
@@ -709,6 +728,7 @@ ecn_decapsulate(u8 tos, struct sk_buff *skb)
IP6_ECN_set_ce((struct ipv6hdr *)(nw_header
+ skb->data));
}
+#endif
}
}
@@ -809,8 +829,10 @@ gre_err(struct sk_buff *skb, u32 info)
if (skb->protocol == htons(ETH_P_IP))
tot_hdr_len += sizeof(struct iphdr);
+#if defined(CONFIG_IPV6) || defined(CONFIG_IPV6_MODULE)
else if (skb->protocol == htons(ETH_P_IPV6))
tot_hdr_len += sizeof(struct ipv6hdr);
+#endif
else
goto out;
@@ -825,7 +847,9 @@ gre_err(struct sk_buff *skb, u32 info)
goto out;
}
- } else if (skb->protocol == htons(ETH_P_IPV6)) {
+ }
+#if defined(CONFIG_IPV6) || defined(CONFIG_IPV6_MODULE)
+ else if (skb->protocol == htons(ETH_P_IPV6)) {
if (mtu < IPV6_MIN_MTU) {
unsigned int packet_length = sizeof(struct ipv6hdr) +
ntohs(ipv6_hdr(skb)->payload_len);
@@ -837,6 +861,7 @@ gre_err(struct sk_buff *skb, u32 info)
goto out;
}
}
+#endif
__pskb_pull(skb, tunnel_hdr_len);
send_frag_needed(vport, mutable, skb, mtu, key);
@@ -942,7 +967,9 @@ build_packet(struct vport *vport, const struct mutable_config *mutable,
goto error_free;
}
- } else if (skb->protocol == htons(ETH_P_IPV6)) {
+ }
+#if defined(CONFIG_IPV6) || defined(CONFIG_IPV6_MODULE)
+ else if (skb->protocol == htons(ETH_P_IPV6)) {
unsigned int packet_length = skb->len - ETH_HLEN
- (eth_hdr(skb)->h_proto == htons(ETH_P_8021Q) ? VLAN_HLEN : 0);
@@ -955,6 +982,7 @@ build_packet(struct vport *vport, const struct mutable_config *mutable,
goto error_free;
}
}
+#endif
skb_reset_transport_header(skb);
new_iph = (struct iphdr *)skb_push(skb, mutable->tunnel_hlen);
@@ -996,7 +1024,6 @@ gre_send(struct vport *vport, struct sk_buff *skb)
const struct mutable_config *mutable = rcu_dereference(gre_vport->mutable);
struct iphdr *old_iph;
- struct ipv6hdr *old_ipv6h;
int orig_len;
struct iphdr iph;
struct rtable *rt;
@@ -1016,21 +1043,24 @@ gre_send(struct vport *vport, struct sk_buff *skb)
if (unlikely(!pskb_may_pull(skb, skb_network_header(skb)
+ sizeof(struct iphdr) - skb->data)))
skb->protocol = 0;
- } else if (skb->protocol == htons(ETH_P_IPV6)) {
+ }
+#if defined(CONFIG_IPV6) || defined(CONFIG_IPV6_MODULE)
+ else if (skb->protocol == htons(ETH_P_IPV6)) {
if (unlikely(!pskb_may_pull(skb, skb_network_header(skb)
+ sizeof(struct ipv6hdr) - skb->data)))
skb->protocol = 0;
}
-
+#endif
old_iph = ip_hdr(skb);
- old_ipv6h = ipv6_hdr(skb);
iph.tos = mutable->port_config.tos;
if (mutable->port_config.flags & GRE_F_TOS_INHERIT) {
if (skb->protocol == htons(ETH_P_IP))
iph.tos = old_iph->tos;
+#if defined(CONFIG_IPV6) || defined(CONFIG_IPV6_MODULE)
else if (skb->protocol == htons(ETH_P_IPV6))
iph.tos = ipv6_get_dsfield(ipv6_hdr(skb));
+#endif
}
iph.tos = ecn_encapsulate(iph.tos, skb);
@@ -1049,8 +1079,10 @@ gre_send(struct vport *vport, struct sk_buff *skb)
if (mutable->port_config.flags & GRE_F_TTL_INHERIT) {
if (skb->protocol == htons(ETH_P_IP))
iph.ttl = old_iph->ttl;
+#if defined(CONFIG_IPV6) || defined(CONFIG_IPV6_MODULE)
else if (skb->protocol == htons(ETH_P_IPV6))
- iph.ttl = old_ipv6h->hop_limit;
+ iph.ttl = ipv6_hdr(skb)->hop_limit;
+#endif
}
if (!iph.ttl)
iph.ttl = dst_metric(&rt->u.dst, RTAX_HOPLIMIT);
@@ -1067,9 +1099,11 @@ gre_send(struct vport *vport, struct sk_buff *skb)
if (skb->protocol == htons(ETH_P_IP)) {
iph.frag_off |= old_iph->frag_off & htons(IP_DF);
mtu = max(mtu, IP_MIN_MTU);
-
- } else if (skb->protocol == htons(ETH_P_IPV6))
+ }
+#if defined(CONFIG_IPV6) || defined(CONFIG_IPV6_MODULE)
+ else if (skb->protocol == htons(ETH_P_IPV6))
mtu = max(mtu, IPV6_MIN_MTU);
+#endif
iph.version = 4;
iph.ihl = sizeof(struct iphdr) >> 2;
--
1.7.0.4
More information about the dev
mailing list