[ovs-dev] [PATCH 1/2] datapath: compat: introduce ovs_iptunnel_handle_offloads()

Pravin B Shelar pshelar at nicira.com
Sat Dec 20 00:24:57 UTC 2014


handle offload code is replicated for different tunneling protocols
define compat function to simplify the code.

Signed-off-by: Pravin B Shelar <pshelar at nicira.com>
---
 datapath/linux/compat/gre.c                    |   32 +++-----------
 datapath/linux/compat/include/net/ip_tunnels.h |    3 +
 datapath/linux/compat/ip_tunnels_core.c        |   52 ++++++++++++++++++++++++
 datapath/linux/compat/vxlan.c                  |   19 ++------
 datapath/vport-geneve.c                        |   25 +++++-------
 datapath/vport-lisp.c                          |   26 +++++-------
 6 files changed, 87 insertions(+), 70 deletions(-)

diff --git a/datapath/linux/compat/gre.c b/datapath/linux/compat/gre.c
index 1cd885b..30ee34c 100644
--- a/datapath/linux/compat/gre.c
+++ b/datapath/linux/compat/gre.c
@@ -287,33 +287,15 @@ static void gre_csum_fix(struct sk_buff *skb)
 
 struct sk_buff *gre_handle_offloads(struct sk_buff *skb, bool gre_csum)
 {
-	int err;
-
-	skb_reset_inner_headers(skb);
+	void (*fix_segment)(struct sk_buff *);
 
-	if (skb_is_gso(skb)) {
-		if (skb_is_encapsulated(skb)) {
-			err = -ENOSYS;
-			goto error;
-		}
+	if (gre_csum)
+		fix_segment = gre_csum_fix;
+	else
+		fix_segment = NULL;
 
-		if (gre_csum)
-			OVS_GSO_CB(skb)->fix_segment = gre_csum_fix;
-		else
-			OVS_GSO_CB(skb)->fix_segment = NULL;
-	} else {
-		if (skb->ip_summed == CHECKSUM_PARTIAL && gre_csum) {
-			err = skb_checksum_help(skb);
-			if (err)
-				goto error;
-
-		} else if (skb->ip_summed != CHECKSUM_PARTIAL)
-			skb->ip_summed = CHECKSUM_NONE;
-	}
-	return skb;
-error:
-	kfree_skb(skb);
-	return ERR_PTR(err);
+	skb_reset_inner_headers(skb);
+	return ovs_iptunnel_handle_offloads(skb, gre_csum, fix_segment);
 }
 
 static bool is_gre_gso(struct sk_buff *skb)
diff --git a/datapath/linux/compat/include/net/ip_tunnels.h b/datapath/linux/compat/include/net/ip_tunnels.h
index 8fb9527..cd5a9e4 100644
--- a/datapath/linux/compat/include/net/ip_tunnels.h
+++ b/datapath/linux/compat/include/net/ip_tunnels.h
@@ -76,5 +76,8 @@ int iptunnel_pull_header(struct sk_buff *skb, int hdr_len, __be16 inner_proto);
 #define TUNNEL_OPTIONS_PRESENT	__cpu_to_be16(0x0800)
 
 bool skb_is_encapsulated(struct sk_buff *skb);
+struct sk_buff *ovs_iptunnel_handle_offloads(struct sk_buff *skb,
+                                             bool csum_help,
+					     void (*fix_segment)(struct sk_buff *));
 
 #endif /* __NET_IP_TUNNELS_H */
diff --git a/datapath/linux/compat/ip_tunnels_core.c b/datapath/linux/compat/ip_tunnels_core.c
index e71ba4e..7606ad6 100644
--- a/datapath/linux/compat/ip_tunnels_core.c
+++ b/datapath/linux/compat/ip_tunnels_core.c
@@ -126,3 +126,55 @@ bool skb_is_encapsulated(struct sk_buff *skb)
 	/* XXX: set inner protocol for all tunnel in OVS. */
 	return ovs_skb_get_inner_protocol(skb) || skb_encapsulation(skb);
 }
+
+struct sk_buff *ovs_iptunnel_handle_offloads(struct sk_buff *skb,
+                                             bool csum_help,
+					     void (*fix_segment)(struct sk_buff *))
+{
+	int err;
+
+	if (skb_is_encapsulated(skb)) {
+		err = -ENOSYS;
+		goto error;
+	}
+
+	/* XXX: synchronize inner header for compat and non compat code so that
+	 * we can do it here.
+	 */
+
+	/* skb_reset_inner_headers(skb); */
+
+	/* OVS compat code does not maintain encapsulation bit.
+	 * skb->encapsulation = 1; */
+
+	if (skb_is_gso(skb)) {
+		err = skb_unclone(skb, GFP_ATOMIC);
+		if (unlikely(err))
+			goto error;
+
+		OVS_GSO_CB(skb)->fix_segment = fix_segment;
+		return skb;
+	}
+
+	/* If packet is not gso and we are resolving any partial checksum,
+	 * clear encapsulation flag. This allows setting CHECKSUM_PARTIAL
+	 * on the outer header without confusing devices that implement
+	 * NETIF_F_IP_CSUM with encapsulation.
+	 */
+	/*
+	if (csum_help)
+		skb->encapsulation = 0;
+	*/
+
+	if (skb->ip_summed == CHECKSUM_PARTIAL && csum_help) {
+		err = skb_checksum_help(skb);
+		if (unlikely(err))
+			goto error;
+	} else if (skb->ip_summed != CHECKSUM_PARTIAL)
+		skb->ip_summed = CHECKSUM_NONE;
+
+	return skb;
+error:
+	kfree_skb(skb);
+	return ERR_PTR(err);
+}
diff --git a/datapath/linux/compat/vxlan.c b/datapath/linux/compat/vxlan.c
index ff040ac..76ae552 100644
--- a/datapath/linux/compat/vxlan.c
+++ b/datapath/linux/compat/vxlan.c
@@ -166,18 +166,9 @@ static void vxlan_gso(struct sk_buff *skb)
 	skb->ip_summed = CHECKSUM_NONE;
 }
 
-static int handle_offloads(struct sk_buff *skb)
+static struct sk_buff *handle_offloads(struct sk_buff *skb)
 {
-	if (skb_is_gso(skb)) {
-		if (skb_is_encapsulated(skb))
-			return -ENOSYS;
-
-		OVS_GSO_CB(skb)->fix_segment = vxlan_gso;
-	} else {
-		if (skb->ip_summed != CHECKSUM_PARTIAL)
-			skb->ip_summed = CHECKSUM_NONE;
-	}
-	return 0;
+	return ovs_iptunnel_handle_offloads(skb, false, vxlan_gso);
 }
 
 int vxlan_xmit_skb(struct vxlan_sock *vs,
@@ -226,9 +217,9 @@ int vxlan_xmit_skb(struct vxlan_sock *vs,
 
 	vxlan_set_owner(vs->sock->sk, skb);
 
-	err = handle_offloads(skb);
-	if (err)
-		return err;
+	skb = handle_offloads(skb);
+	if (IS_ERR(skb))
+		return PTR_ERR(skb);
 
 	return iptunnel_xmit(vs->sock->sk, rt, skb, src, dst, IPPROTO_UDP,
 			     tos, ttl, df, false);
diff --git a/datapath/vport-geneve.c b/datapath/vport-geneve.c
index 200cc14..6fcf1cc 100644
--- a/datapath/vport-geneve.c
+++ b/datapath/vport-geneve.c
@@ -324,36 +324,29 @@ static void geneve_fix_segment(struct sk_buff *skb)
 	udph->len = htons(skb->len - skb_transport_offset(skb));
 }
 
-static int handle_offloads(struct sk_buff *skb)
+static struct sk_buff *handle_offloads(struct sk_buff *skb)
 {
-	if (skb_is_gso(skb)) {
-		if (skb_is_encapsulated(skb))
-			return -ENOSYS;
-		OVS_GSO_CB(skb)->fix_segment = geneve_fix_segment;
-	} else if (skb->ip_summed != CHECKSUM_PARTIAL) {
-		skb->ip_summed = CHECKSUM_NONE;
-	}
-	return 0;
+	return ovs_iptunnel_handle_offloads(skb, false, geneve_fix_segment);
 }
 #else
-static int handle_offloads(struct sk_buff *skb)
+static struct sk_buff *handle_offloads(struct sk_buff *skb)
 {
 	if (skb_is_gso(skb)) {
 		int err;
 
 		if (skb_is_encapsulated(skb))
-			return -ENOSYS;
+			return ERR_PTR(-ENOSYS);
 
 		err = skb_unclone(skb, GFP_ATOMIC);
 		if (unlikely(err))
-			return err;
+			return ERR_PTR(err);
 
 		skb_shinfo(skb)->gso_type |= SKB_GSO_UDP_TUNNEL;
 	} else if (skb->ip_summed != CHECKSUM_PARTIAL)
 		skb->ip_summed = CHECKSUM_NONE;
 
 	skb->encapsulation = 1;
-	return 0;
+	return skb;
 }
 #endif
 
@@ -420,9 +413,11 @@ static int geneve_send(struct vport *vport, struct sk_buff *skb)
 	geneve_build_header(vport, skb);
 
 	/* Offloading */
-	err = handle_offloads(skb);
-	if (err)
+	skb = handle_offloads(skb);
+	if (IS_ERR(skb)) {
+		err = PTR_ERR(skb);
 		goto err_free_rt;
+	}
 
 	df = tun_key->tun_flags & TUNNEL_DONT_FRAGMENT ? htons(IP_DF) : 0;
 
diff --git a/datapath/vport-lisp.c b/datapath/vport-lisp.c
index a067e05..ce30f69 100644
--- a/datapath/vport-lisp.c
+++ b/datapath/vport-lisp.c
@@ -406,37 +406,29 @@ static void lisp_fix_segment(struct sk_buff *skb)
 	udph->len = htons(skb->len - skb_transport_offset(skb));
 }
 
-static int handle_offloads(struct sk_buff *skb)
+static struct sk_buff *handle_offloads(struct sk_buff *skb)
 {
-	if (skb_is_gso(skb)) {
-		if (skb_is_encapsulated(skb))
-			return -ENOSYS;
-
-		OVS_GSO_CB(skb)->fix_segment = lisp_fix_segment;
-	} else if (skb->ip_summed != CHECKSUM_PARTIAL) {
-		skb->ip_summed = CHECKSUM_NONE;
-	}
-	return 0;
+	return ovs_iptunnel_handle_offloads(skb, false, lisp_fix_segment);
 }
 #else
-static int handle_offloads(struct sk_buff *skb)
+static struct sk_buff *handle_offloads(struct sk_buff *skb)
 {
 	if (skb_is_gso(skb)) {
 		int err;
 
 		if (skb_is_encapsulated(skb))
-			return -ENOSYS;
+			return ERR_PTR(-ENOSYS);
 
 		err = skb_unclone(skb, GFP_ATOMIC);
 		if (unlikely(err))
-			return err;
+			return ERR_PTR(err);
 
 		skb_shinfo(skb)->gso_type |= SKB_GSO_UDP_TUNNEL;
 	} else if (skb->ip_summed != CHECKSUM_PARTIAL)
 		skb->ip_summed = CHECKSUM_NONE;
 
 	skb->encapsulation = 1;
-	return 0;
+	return skb;
 }
 #endif
 
@@ -500,9 +492,11 @@ static int lisp_send(struct vport *vport, struct sk_buff *skb)
 	lisp_build_header(vport, skb);
 
 	/* Offloading */
-	err = handle_offloads(skb);
-	if (err)
+	skb = handle_offloads(skb);
+	if (IS_ERR(skb)) {
+		err = PTR_ERR(skb);
 		goto err_free_rt;
+	}
 
 	skb->ignore_df = 1;
 
-- 
1.7.1




More information about the dev mailing list