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
        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.
 
    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.
    - 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
 
 
 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
     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
           : # 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
        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 <linux/icmpv6.h>
 #include <linux/rculist.h>
 #include <net/ip.h>
+#include <net/ip_tunnels.h>
 #include <net/ipv6.h>
 #include <net/ndisc.h>
 
 #include <net/ipv6.h>
 #include <net/ndisc.h>
 
index 58b1e73..07b270a 100644 (file)
@@ -16,6 +16,9 @@
  * 02110-1301, USA
  */
 
  * 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)
 
 #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 /* CONFIG_NET_IPGRE_DEMUX */
+
+#endif /* 3.12 */
index 32f906c..9ded17c 100644 (file)
@@ -16,6 +16,9 @@
  * 02110-1301, USA
  */
 
  * 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>
 #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;
 }
        }
        return ret;
 }
+#endif /* 3.12 */
index 44fd213..b83a4c3 100644 (file)
@@ -1,6 +1,9 @@
 #ifndef __LINUX_GSO_WRAPPER_H
 #define __LINUX_GSO_WRAPPER_H
 
 #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>
 
 #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);
 
 #define ip_local_out rpl_ip_local_out
 int ip_local_out(struct sk_buff *skb);
+
+#endif /* 3.12 */
 #endif
 #endif
index a6f29c4..6268655 100644 (file)
@@ -4,6 +4,7 @@
 #include <linux/skbuff.h>
 #include <net/ip_tunnels.h>
 
 #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>
 #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 */
 
 #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);
 #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;
 }
                addend += 4;
        return addend;
 }
+#endif
 
 #endif
 
 #endif
index a786aa9..e59f9f3 100644 (file)
@@ -1,6 +1,11 @@
 #ifndef __NET_IP_TUNNELS_WRAPPER_H
 #define __NET_IP_TUNNELS_WRAPPER_H 1
 
 #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>
 #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,
 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);
 
 int iptunnel_pull_header(struct sk_buff *skb, int hdr_len, __be16 inner_proto);
+
+#endif
 #endif /* __NET_IP_TUNNELS_H */
 #endif /* __NET_IP_TUNNELS_H */
index 3ac816b..414a497 100644 (file)
@@ -5,6 +5,11 @@
 #include <linux/netdevice.h>
 #include <linux/udp.h>
 
 #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);
 
 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,
 
 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);
 
 
 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);
 
 
 __be16 vxlan_src_port(__u16 port_min, __u16 port_max, struct sk_buff *skb);
 
+#endif /* 3.12 */
 #endif
 #endif
index 66d5e02..779075d 100644 (file)
@@ -16,6 +16,9 @@
  * 02110-1301, USA
  */
 
  * 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>
 #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,
 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;
 {
        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;
 }
        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.
  */
 
  * 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>
 #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;
 
        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)
 }
 
 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,
 
 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);
 }
 {
        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);
 }
 
        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,
        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:
 err_free_rt:
        ip_rt_put(rt);
 error:
index c2698ae..e33cffe 100644 (file)
@@ -381,6 +381,8 @@ error:
        return ERR_PTR(err);
 }
 
        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);
 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));
 }
 
        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;
 {
        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)
 {
 
 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 */
        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 &
        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,
        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;
 
 
        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);
 
        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;
        if (IS_ERR(vs)) {
                ovs_vport_free(vport);
                return (void *)vs;