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:
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
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.
- 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.
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
- 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
#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>
+#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)
}
#endif /* CONFIG_NET_IPGRE_DEMUX */
}
#endif /* CONFIG_NET_IPGRE_DEMUX */
+#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>
#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>
#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);
#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>
#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);
addend += 4;
return addend;
}
addend += 4;
return addend;
}
#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>
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 /* __NET_IP_TUNNELS_H */
#endif /* __NET_IP_TUNNELS_H */
#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);
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 ipv6);
void vxlan_sock_release(struct vxlan_sock *vs);
void vxlan_sock_release(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);
+#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>
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;
skb->pkt_type = PACKET_HOST;
return 0;
}
skb->pkt_type = PACKET_HOST;
return 0;
}
* 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>
- 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)
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 ipv6)
{
return vxlan_socket_create(net, port, rcv, data);
}
{
return vxlan_socket_create(net, port, rcv, data);
}
queue_work(system_wq, &vs->del_work);
}
queue_work(system_wq, &vs->del_work);
}
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:
+#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);
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;
+#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)
{
lisp_build_header(vport, skb);
/* Offloading */
lisp_build_header(vport, skb);
/* Offloading */
+ 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 &
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;
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;