Skip to content

Commit

Permalink
datapath: Add support for Linux 3.12
Browse files Browse the repository at this point in the history
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 <[email protected]>
Signed-off-by: Pravin B Shelar <[email protected]>
Reviewed-by: Kyle Mestery <[email protected]>
  • Loading branch information
Pravin Shelar committed Mar 7, 2014
1 parent 72310b0 commit 29c71cf
Show file tree
Hide file tree
Showing 15 changed files with 79 additions and 13 deletions.
2 changes: 1 addition & 1 deletion FAQ
Original file line number Diff line number Diff line change
Expand Up @@ -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.
Expand Down
2 changes: 2 additions & 0 deletions NEWS
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down
4 changes: 2 additions & 2 deletions acinclude.m4
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down
1 change: 1 addition & 0 deletions datapath/flow_netlink.c
Original file line number Diff line number Diff line change
Expand Up @@ -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>

Expand Down
5 changes: 5 additions & 0 deletions datapath/linux/compat/gre.c
Original file line number Diff line number Diff line change
Expand Up @@ -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)

Expand Down Expand Up @@ -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 */
4 changes: 4 additions & 0 deletions datapath/linux/compat/gso.c
Original file line number Diff line number Diff line change
Expand Up @@ -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>
Expand Down Expand Up @@ -229,3 +232,4 @@ int rpl_ip_local_out(struct sk_buff *skb)
}
return ret;
}
#endif /* 3.12 */
5 changes: 5 additions & 0 deletions datapath/linux/compat/gso.h
Original file line number Diff line number Diff line change
@@ -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>

Expand Down Expand Up @@ -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
4 changes: 4 additions & 0 deletions datapath/linux/compat/include/net/gre.h
Original file line number Diff line number Diff line change
Expand Up @@ -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>
Expand Down Expand Up @@ -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);
Expand All @@ -98,5 +101,6 @@ static inline int ip_gre_calc_hlen(__be16 o_flags)
addend += 4;
return addend;
}
#endif

#endif
9 changes: 8 additions & 1 deletion datapath/linux/compat/include/net/ip_tunnels.h
Original file line number Diff line number Diff line change
@@ -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>
Expand Down Expand Up @@ -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 */
8 changes: 7 additions & 1 deletion datapath/linux/compat/include/net/vxlan.h
Original file line number Diff line number Diff line change
Expand Up @@ -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);

Expand All @@ -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);

Expand All @@ -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
7 changes: 6 additions & 1 deletion datapath/linux/compat/ip_tunnels_core.c
Original file line number Diff line number Diff line change
Expand Up @@ -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>
Expand All @@ -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;
Expand Down Expand Up @@ -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 */
9 changes: 7 additions & 2 deletions datapath/linux/compat/vxlan.c
Original file line number Diff line number Diff line change
Expand Up @@ -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>
Expand Down Expand Up @@ -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)
Expand Down Expand Up @@ -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);
}
Expand All @@ -310,3 +313,5 @@ void vxlan_sock_release(struct vxlan_sock *vs)

queue_work(system_wq, &vs->del_work);
}

#endif /* 3.12 */
2 changes: 1 addition & 1 deletion datapath/vport-gre.c
Original file line number Diff line number Diff line change
Expand Up @@ -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:
Expand Down
28 changes: 25 additions & 3 deletions datapath/vport-lisp.c
Original file line number Diff line number Diff line change
Expand Up @@ -381,20 +381,39 @@ static struct vport *lisp_tnl_create(const struct vport_parms *parms)
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);

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)
{
Expand Down Expand Up @@ -455,15 +474,18 @@ 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 &
TUNNEL_DONT_FRAGMENT ? htons(IP_DF) : 0;
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;

Expand Down
2 changes: 1 addition & 1 deletion datapath/vport-vxlan.c
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand Down

0 comments on commit 29c71cf

Please sign in to comment.