[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