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

Signed-off-by: Pravin B Shelar <pshe...@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

_______________________________________________
dev mailing list
dev@openvswitch.org
http://openvswitch.org/mailman/listinfo/dev

Reply via email to