datapath: Add support for Linux 3.12
authorPravin Shelar <pshelar@nicira.com>
Fri, 7 Feb 2014 18:46:53 +0000 (10:46 -0800)
committerPravin B Shelar <pshelar@nicira.com>
Fri, 7 Mar 2014 12:00:24 +0000 (04:00 -0800)
Bump kernel support for datapath module to include 3.12.
Make use of native ip-tunnel API for Kernel >= 3.12.

Based on patch from James Page.

Signed-off-by: James Page <james.page@ubuntu.com>
Signed-off-by: Pravin B Shelar <pshelar@nicira.com>
Reviewed-by: Kyle Mestery <mestery@noironetworks.com>
15 files changed:
FAQ
NEWS
acinclude.m4
datapath/flow_netlink.c
datapath/linux/compat/gre.c
datapath/linux/compat/gso.c
datapath/linux/compat/gso.h
datapath/linux/compat/include/net/gre.h
datapath/linux/compat/include/net/ip_tunnels.h
datapath/linux/compat/include/net/vxlan.h
datapath/linux/compat/ip_tunnels_core.c
datapath/linux/compat/vxlan.c
datapath/vport-gre.c
datapath/vport-lisp.c
datapath/vport-vxlan.c

diff --git a/FAQ b/FAQ
index c6ccbd1..f46170c 100644 (file)
--- a/FAQ
+++ b/FAQ
@@ -148,7 +148,7 @@ A: The following table lists the Linux kernel versions against which the
        1.10.x     2.6.18 to 3.8
        1.11.x     2.6.18 to 3.8
        2.0.x      2.6.32 to 3.10
-       2.1.x      2.6.32 to 3.11
+       2.1.x      2.6.32 to 3.12
 
    Open vSwitch userspace should also work with the Linux kernel module
    built into Linux 3.3 and later.
diff --git a/NEWS b/NEWS
index f0d5a10..8ec6c90 100644 (file)
--- a/NEWS
+++ b/NEWS
@@ -8,6 +8,8 @@ Post-v2.1.0
    - Upon the receipt of a SIGHUP signal, ovs-vswitchd no longer reopens its
      log file (it will terminate instead). Please use 'ovs-appctl vlog/reopen'
      instead.
+   - Support for Linux kernels up to 3.12. On Kernel 3.12 OVS uses tunnel
+     API for GRE and VXLAN.
 
 
 v2.1.0 - xx xxx xxxx
index 830fd3f..8f41e33 100644 (file)
@@ -134,10 +134,10 @@ AC_DEFUN([OVS_CHECK_LINUX], [
     AC_MSG_RESULT([$kversion])
 
     if test "$version" -ge 3; then
-       if test "$version" = 3 && test "$patchlevel" -le 11; then
+       if test "$version" = 3 && test "$patchlevel" -le 12; then
           : # Linux 3.x
        else
-         AC_ERROR([Linux kernel in $KBUILD is version $kversion, but version newer than 3.11.x is not supported])
+         AC_ERROR([Linux kernel in $KBUILD is version $kversion, but version newer than 3.12.x is not supported])
        fi
     else
        if test "$version" -le 1 || test "$patchlevel" -le 5 || test "$sublevel" -le 31; then
index 40751cb..4c68a68 100644 (file)
@@ -43,6 +43,7 @@
 #include <linux/icmpv6.h>
 #include <linux/rculist.h>
 #include <net/ip.h>
+#include <net/ip_tunnels.h>
 #include <net/ipv6.h>
 #include <net/ndisc.h>
 
index 58b1e73..07b270a 100644 (file)
@@ -16,6 +16,9 @@
  * 02110-1301, USA
  */
 
+#include <linux/version.h>
+#if LINUX_VERSION_CODE < KERNEL_VERSION(3,12,0)
+
 #include <linux/kconfig.h>
 #if IS_ENABLED(CONFIG_NET_IPGRE_DEMUX)
 
@@ -340,3 +343,5 @@ void gre_build_header(struct sk_buff *skb, const struct tnl_ptk_info *tpi,
 }
 
 #endif /* CONFIG_NET_IPGRE_DEMUX */
+
+#endif /* 3.12 */
index 32f906c..9ded17c 100644 (file)
@@ -16,6 +16,9 @@
  * 02110-1301, USA
  */
 
+#include <linux/version.h>
+#if LINUX_VERSION_CODE < KERNEL_VERSION(3,12,0)
+
 #include <linux/module.h>
 #include <linux/if.h>
 #include <linux/if_tunnel.h>
@@ -229,3 +232,4 @@ int rpl_ip_local_out(struct sk_buff *skb)
        }
        return ret;
 }
+#endif /* 3.12 */
index 44fd213..b83a4c3 100644 (file)
@@ -1,6 +1,9 @@
 #ifndef __LINUX_GSO_WRAPPER_H
 #define __LINUX_GSO_WRAPPER_H
 
+#include <linux/version.h>
+#if LINUX_VERSION_CODE < KERNEL_VERSION(3,12,0)
+
 #include <linux/skbuff.h>
 #include <net/protocol.h>
 
@@ -69,4 +72,6 @@ static inline void skb_reset_inner_headers(struct sk_buff *skb)
 
 #define ip_local_out rpl_ip_local_out
 int ip_local_out(struct sk_buff *skb);
+
+#endif /* 3.12 */
 #endif
index a6f29c4..6268655 100644 (file)
@@ -4,6 +4,7 @@
 #include <linux/skbuff.h>
 #include <net/ip_tunnels.h>
 
+#include <linux/version.h>
 #if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,37) || \
    defined(HAVE_GRE_CISCO_REGISTER)
 #include_next <net/gre.h>
@@ -78,6 +79,8 @@ static inline __be16 tnl_flags_to_gre_flags(__be16 tflags)
 #endif /* LINUX_VERSION_CODE < KERNEL_VERSION(3,10,0) */
 #endif /* HAVE_GRE_CISCO_REGISTER */
 
+#if LINUX_VERSION_CODE < KERNEL_VERSION(3,12,0)
+
 #define gre_build_header rpl_gre_build_header
 void gre_build_header(struct sk_buff *skb, const struct tnl_ptk_info *tpi,
                      int hdr_len);
@@ -98,5 +101,6 @@ static inline int ip_gre_calc_hlen(__be16 o_flags)
                addend += 4;
        return addend;
 }
+#endif
 
 #endif
index a786aa9..e59f9f3 100644 (file)
@@ -1,6 +1,11 @@
 #ifndef __NET_IP_TUNNELS_WRAPPER_H
 #define __NET_IP_TUNNELS_WRAPPER_H 1
 
+#include <linux/version.h>
+#if LINUX_VERSION_CODE >= KERNEL_VERSION(3,12,0)
+#include_next <net/ip_tunnels.h>
+#else
+
 #include <linux/if_tunnel.h>
 #include <linux/netdevice.h>
 #include <linux/skbuff.h>
@@ -34,7 +39,9 @@ struct tnl_ptk_info {
 int iptunnel_xmit(struct rtable *rt,
                  struct sk_buff *skb,
                  __be32 src, __be32 dst, __u8 proto,
-                 __u8 tos, __u8 ttl, __be16 df);
+                 __u8 tos, __u8 ttl, __be16 df, bool xnet);
 
 int iptunnel_pull_header(struct sk_buff *skb, int hdr_len, __be16 inner_proto);
+
+#endif
 #endif /* __NET_IP_TUNNELS_H */
index 3ac816b..414a497 100644 (file)
@@ -5,6 +5,11 @@
 #include <linux/netdevice.h>
 #include <linux/udp.h>
 
+#include <linux/version.h>
+#if LINUX_VERSION_CODE >= KERNEL_VERSION(3,12,0)
+#include_next <net/vxlan.h>
+#else
+
 struct vxlan_sock;
 typedef void (vxlan_rcv_t)(struct vxlan_sock *vs, struct sk_buff *skb, __be32 key);
 
@@ -20,7 +25,7 @@ struct vxlan_sock {
 
 struct vxlan_sock *vxlan_sock_add(struct net *net, __be16 port,
                                  vxlan_rcv_t *rcv, void *data,
-                                 bool no_share);
+                                 bool no_share, bool ipv6);
 
 void vxlan_sock_release(struct vxlan_sock *vs);
 
@@ -31,4 +36,5 @@ int vxlan_xmit_skb(struct vxlan_sock *vs,
 
 __be16 vxlan_src_port(__u16 port_min, __u16 port_max, struct sk_buff *skb);
 
+#endif /* 3.12 */
 #endif
index 66d5e02..779075d 100644 (file)
@@ -16,6 +16,9 @@
  * 02110-1301, USA
  */
 
+#include <linux/version.h>
+#if LINUX_VERSION_CODE < KERNEL_VERSION(3,12,0)
+
 #define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
 
 #include <linux/in.h>
@@ -37,7 +40,7 @@
 int iptunnel_xmit(struct rtable *rt,
                  struct sk_buff *skb,
                  __be32 src, __be32 dst, __u8 proto,
-                 __u8 tos, __u8 ttl, __be16 df)
+                 __u8 tos, __u8 ttl, __be16 df, bool xnet)
 {
        int pkt_len = skb->len;
        struct iphdr *iph;
@@ -108,3 +111,5 @@ int iptunnel_pull_header(struct sk_buff *skb, int hdr_len, __be16 inner_proto)
        skb->pkt_type = PACKET_HOST;
        return 0;
 }
+
+#endif /* 3.12 */
index 64877e0..848a395 100644 (file)
@@ -18,6 +18,9 @@
  * This code is derived from kernel vxlan module.
  */
 
+#include <linux/version.h>
+#if LINUX_VERSION_CODE < KERNEL_VERSION(3,12,0)
+
 #define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
 
 #include <linux/kernel.h>
@@ -223,7 +226,7 @@ int vxlan_xmit_skb(struct vxlan_sock *vs,
        if (err)
                return err;
 
-       return iptunnel_xmit(rt, skb, src, dst, IPPROTO_UDP, tos, ttl, df);
+       return iptunnel_xmit(rt, skb, src, dst, IPPROTO_UDP, tos, ttl, df, false);
 }
 
 static void rcu_free_vs(struct rcu_head *rcu)
@@ -298,7 +301,7 @@ static struct vxlan_sock *vxlan_socket_create(struct net *net, __be16 port,
 
 struct vxlan_sock *vxlan_sock_add(struct net *net, __be16 port,
                                  vxlan_rcv_t *rcv, void *data,
-                                 bool no_share)
+                                 bool no_share, bool ipv6)
 {
        return vxlan_socket_create(net, port, rcv, data);
 }
@@ -310,3 +313,5 @@ void vxlan_sock_release(struct vxlan_sock *vs)
 
        queue_work(system_wq, &vs->del_work);
 }
+
+#endif /* 3.12 */
index 8737b63..8613756 100644 (file)
@@ -178,7 +178,7 @@ static int __send(struct vport *vport, struct sk_buff *skb,
        return iptunnel_xmit(rt, skb, saddr,
                             OVS_CB(skb)->tun_key->ipv4_dst, IPPROTO_GRE,
                             OVS_CB(skb)->tun_key->ipv4_tos,
-                            OVS_CB(skb)->tun_key->ipv4_ttl, df);
+                            OVS_CB(skb)->tun_key->ipv4_ttl, df, false);
 err_free_rt:
        ip_rt_put(rt);
 error:
index c2698ae..e33cffe 100644 (file)
@@ -381,6 +381,8 @@ error:
        return ERR_PTR(err);
 }
 
+#if LINUX_VERSION_CODE < KERNEL_VERSION(3,12,0)
+
 static void lisp_fix_segment(struct sk_buff *skb)
 {
        struct udphdr *udph = udp_hdr(skb);
@@ -388,13 +390,30 @@ static void lisp_fix_segment(struct sk_buff *skb)
        udph->len = htons(skb->len - skb_transport_offset(skb));
 }
 
-static void handle_offloads(struct sk_buff *skb)
+static int handle_offloads(struct sk_buff *skb)
 {
        if (skb_is_gso(skb))
                OVS_GSO_CB(skb)->fix_segment = lisp_fix_segment;
        else if (skb->ip_summed != CHECKSUM_PARTIAL)
                skb->ip_summed = CHECKSUM_NONE;
+       return 0;
 }
+#else
+static int handle_offloads(struct sk_buff *skb)
+{
+       if (skb_is_gso(skb)) {
+               int err = skb_unclone(skb, GFP_ATOMIC);
+               if (unlikely(err))
+                       return 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;
+}
+#endif
 
 static int lisp_send(struct vport *vport, struct sk_buff *skb)
 {
@@ -455,7 +474,10 @@ static int lisp_send(struct vport *vport, struct sk_buff *skb)
        lisp_build_header(vport, skb);
 
        /* Offloading */
-       handle_offloads(skb);
+       err = handle_offloads(skb);
+       if (err)
+               goto err_free_rt;
+
        skb->local_df = 1;
 
        df = OVS_CB(skb)->tun_key->tun_flags &
@@ -463,7 +485,7 @@ static int lisp_send(struct vport *vport, struct sk_buff *skb)
        sent_len = iptunnel_xmit(rt, skb,
                             saddr, OVS_CB(skb)->tun_key->ipv4_dst,
                             IPPROTO_UDP, OVS_CB(skb)->tun_key->ipv4_tos,
-                            OVS_CB(skb)->tun_key->ipv4_ttl, df);
+                            OVS_CB(skb)->tun_key->ipv4_ttl, df, false);
 
        return sent_len > 0 ? sent_len + network_offset : sent_len;
 
index ab2b6f7..d264785 100644 (file)
@@ -124,7 +124,7 @@ static struct vport *vxlan_tnl_create(const struct vport_parms *parms)
        vxlan_port = vxlan_vport(vport);
        strncpy(vxlan_port->name, parms->name, IFNAMSIZ);
 
-       vs = vxlan_sock_add(net, htons(dst_port), vxlan_rcv, vport, true);
+       vs = vxlan_sock_add(net, htons(dst_port), vxlan_rcv, vport, true, false);
        if (IS_ERR(vs)) {
                ovs_vport_free(vport);
                return (void *)vs;