Skip to content

Commit

Permalink
datapath: Add support for 4.1 kernel.
Browse files Browse the repository at this point in the history
Signed-off-by: Joe Stringer <joestringer@nicira.com>
Signed-off-by: Pravin B Shelar <pshelar@nicira.com>
Acked-by: Jesse Gross <jesse@nicira.com>
  • Loading branch information
joestringer authored and Pravin B Shelar committed Sep 18, 2015
1 parent 1b494f3 commit c0cddce
Show file tree
Hide file tree
Showing 15 changed files with 83 additions and 38 deletions.
3 changes: 2 additions & 1 deletion .travis.yml
Expand Up @@ -12,7 +12,8 @@ env:
- TESTSUITE=1 KERNEL=3.18.1
- TESTSUITE=1 OPTS="--enable-shared"
- BUILD_ENV="-m32" OPTS="--disable-ssl"
- KERNEL=4.0.2
- KERNEL=4.1.6
- KERNEL=4.0.9
- KERNEL=3.17.7 DPDK=1
- KERNEL=3.17.7 DPDK=1 OPTS="--enable-shared"
- KERNEL=3.17.7
Expand Down
1 change: 1 addition & 0 deletions FAQ.md
Expand Up @@ -156,6 +156,7 @@ A: The following table lists the Linux kernel versions against which the
| 2.1.x | 2.6.32 to 3.11
| 2.3.x | 2.6.32 to 3.14
| 2.4.x | 2.6.32 to 4.0
| 2.5.x | 2.6.32 to 4.1

Open vSwitch userspace should also work with the Linux kernel module
built into Linux 3.3 and later.
Expand Down
4 changes: 2 additions & 2 deletions acinclude.m4
Expand Up @@ -134,10 +134,10 @@ AC_DEFUN([OVS_CHECK_LINUX], [
AC_MSG_RESULT([$kversion])
if test "$version" -ge 4; then
if test "$version" = 4 && test "$patchlevel" -le 0; then
if test "$version" = 4 && test "$patchlevel" -le 1; then
: # Linux 4.x
else
AC_ERROR([Linux kernel in $KBUILD is version $kversion, but version newer than 4.0.x is not supported (please refer to the FAQ for advice)])
AC_ERROR([Linux kernel in $KBUILD is version $kversion, but version newer than 4.1.x is not supported (please refer to the FAQ for advice)])
fi
elif test "$version" = 3; then
: # Linux 3.x
Expand Down
4 changes: 1 addition & 3 deletions datapath/datapath.c
Expand Up @@ -205,7 +205,6 @@ static void destroy_dp_rcu(struct rcu_head *rcu)

ovs_flow_tbl_destroy(&dp->table);
free_percpu(dp->stats_percpu);
release_net(ovs_dp_get_net(dp));
kfree(dp->ports);
kfree(dp);
}
Expand Down Expand Up @@ -1527,7 +1526,7 @@ static int ovs_dp_cmd_new(struct sk_buff *skb, struct genl_info *info)
if (dp == NULL)
goto err_free_reply;

ovs_dp_set_net(dp, hold_net(sock_net(skb->sk)));
ovs_dp_set_net(dp, sock_net(skb->sk));

/* Allocate table. */
err = ovs_flow_tbl_init(&dp->table);
Expand Down Expand Up @@ -1601,7 +1600,6 @@ static int ovs_dp_cmd_new(struct sk_buff *skb, struct genl_info *info)
err_destroy_table:
ovs_flow_tbl_destroy(&dp->table);
err_free_dp:
release_net(ovs_dp_get_net(dp));
kfree(dp);
err_free_reply:
kfree_skb(reply);
Expand Down
9 changes: 4 additions & 5 deletions datapath/datapath.h
Expand Up @@ -25,6 +25,7 @@
#include <linux/netdevice.h>
#include <linux/skbuff.h>
#include <linux/u64_stats_sync.h>
#include <net/net_namespace.h>

#include "compat.h"
#include "flow.h"
Expand Down Expand Up @@ -86,10 +87,8 @@ struct datapath {
/* Stats. */
struct dp_stats_percpu __percpu *stats_percpu;

#ifdef CONFIG_NET_NS
/* Network namespace ref. */
struct net *net;
#endif
possible_net_t net;

u32 user_features;
};
Expand Down Expand Up @@ -156,12 +155,12 @@ int lockdep_ovsl_is_held(void);

static inline struct net *ovs_dp_get_net(const struct datapath *dp)
{
return read_pnet(&dp->net);
return rpl_read_pnet(&dp->net);
}

static inline void ovs_dp_set_net(struct datapath *dp, struct net *net)
{
write_pnet(&dp->net, net);
rpl_write_pnet(&dp->net, net);
}

struct vport *ovs_lookup_vport(const struct datapath *dp, u16 port_no);
Expand Down
4 changes: 3 additions & 1 deletion datapath/flow.c
Expand Up @@ -101,7 +101,9 @@ void ovs_flow_stats_update(struct sw_flow *flow, __be16 tcp_flags,

new_stats =
kmem_cache_alloc_node(flow_stats_cache,
GFP_THISNODE |
GFP_NOWAIT |
__GFP_THISNODE |
__GFP_NOWARN |
__GFP_NOMEMALLOC,
node);
if (likely(new_stats)) {
Expand Down
2 changes: 1 addition & 1 deletion datapath/linux/compat/geneve.c
Expand Up @@ -117,7 +117,7 @@ int rpl_geneve_xmit_skb(struct geneve_sock *gs, struct rtable *rt,

ovs_skb_set_inner_protocol(skb, htons(ETH_P_TEB));

return udp_tunnel_xmit_skb(rt, skb, src, dst,
return udp_tunnel_xmit_skb(rt, gs->sock->sk, skb, src, dst,
tos, ttl, df, src_port, dst_port, xnet,
!csum);
}
Expand Down
27 changes: 27 additions & 0 deletions datapath/linux/compat/include/net/net_namespace.h
Expand Up @@ -51,4 +51,31 @@ static void rpl_unregister_pernet_gen_##TYPE(struct rpl_pernet_operations *rpl_p
#define DEFINE_COMPAT_PNET_REG_FUNC(TYPE)
#endif /* 2.6.33 */

#if LINUX_VERSION_CODE < KERNEL_VERSION(4,1,0)
typedef struct {
#ifdef CONFIG_NET_NS
struct net *net;
#endif
} possible_net_t;

static inline void rpl_write_pnet(possible_net_t *pnet, struct net *net)
{
#ifdef CONFIG_NET_NS
pnet->net = net;
#endif
}

static inline struct net *rpl_read_pnet(const possible_net_t *pnet)
{
#ifdef CONFIG_NET_NS
return pnet->net;
#else
return &init_net;
#endif
}
#else /* Linux >= 4.1 */
#define rpl_read_pnet read_pnet
#define rpl_write_pnet write_pnet
#endif /* Linux >= 4.1 */

#endif /* net/net_namespace.h wrapper */
15 changes: 14 additions & 1 deletion datapath/linux/compat/include/net/udp_tunnel.h
Expand Up @@ -19,6 +19,18 @@ rpl_udp_tunnel_handle_offloads(struct sk_buff *skb, bool udp_csum,
}
#define udp_tunnel_handle_offloads rpl_udp_tunnel_handle_offloads

#if LINUX_VERSION_CODE < KERNEL_VERSION(4,1,0)
static inline int rpl_udp_tunnel_xmit_skb(struct rtable *rt,
struct sock *sk, struct sk_buff *skb,
__be32 src, __be32 dst, __u8 tos, __u8 ttl,
__be16 df, __be16 src_port, __be16 dst_port,
bool xnet, bool nocheck)
{
return udp_tunnel_xmit_skb(rt, skb, src, dst, tos, ttl, df, src_port,
dst_port, xnet, nocheck);
}
#define udp_tunnel_xmit_skb rpl_udp_tunnel_xmit_skb
#endif
#else

#include <net/ip_tunnels.h>
Expand Down Expand Up @@ -71,7 +83,8 @@ void rpl_setup_udp_tunnel_sock(struct net *net, struct socket *sock,

/* Transmit the skb using UDP encapsulation. */
#define udp_tunnel_xmit_skb rpl_udp_tunnel_xmit_skb
int rpl_udp_tunnel_xmit_skb(struct rtable *rt, struct sk_buff *skb,
int rpl_udp_tunnel_xmit_skb(struct rtable *rt,
struct sock *sk, struct sk_buff *skb,
__be32 src, __be32 dst, __u8 tos, __u8 ttl,
__be16 df, __be16 src_port, __be16 dst_port,
bool xnet, bool nocheck);
Expand Down
14 changes: 8 additions & 6 deletions datapath/linux/compat/include/net/vxlan.h
Expand Up @@ -88,18 +88,21 @@ struct vxlanhdr_gbp {
#endif

#ifdef USE_UPSTREAM_VXLAN
static inline int rpl_vxlan_xmit_skb(struct vxlan_sock *vs,
struct rtable *rt, struct sk_buff *skb,
__be32 src, __be32 dst, __u8 tos, __u8 ttl, __be16 df,
__be16 src_port, __be16 dst_port,
static inline int rpl_vxlan_xmit_skb(struct rtable *rt, struct sock *sk,
struct sk_buff *skb, __be32 src, __be32 dst, __u8 tos,
__u8 ttl, __be16 df, __be16 src_port, __be16 dst_port,
struct vxlan_metadata *md, bool xnet, u32 vxflags)
{
if (skb_is_gso(skb) && skb_is_encapsulated(skb)) {
kfree_skb(skb);
return -ENOSYS;
}

#if LINUX_VERSION_CODE < KERNEL_VERSION(4,1,0)
return vxlan_xmit_skb(rt, skb, src, dst, tos, ttl, df,
#else
return vxlan_xmit_skb(rt, sk, skb, src, dst, tos, ttl, df,
#endif
src_port, dst_port, md, xnet, vxflags);
}

Expand Down Expand Up @@ -138,8 +141,7 @@ struct vxlan_sock *rpl_vxlan_sock_add(struct net *net, __be16 port,
void rpl_vxlan_sock_release(struct vxlan_sock *vs);

#define vxlan_xmit_skb rpl_vxlan_xmit_skb
int rpl_vxlan_xmit_skb(struct vxlan_sock *vs,
struct rtable *rt, struct sk_buff *skb,
int rpl_vxlan_xmit_skb(struct rtable *rt, struct sock *sk, struct sk_buff *skb,
__be32 src, __be32 dst, __u8 tos, __u8 ttl, __be16 df,
__be16 src_port, __be16 dst_port,
struct vxlan_metadata *md, bool xnet, u32 vxflags);
Expand Down
16 changes: 9 additions & 7 deletions datapath/linux/compat/stt.c
Expand Up @@ -1320,16 +1320,18 @@ static void clean_percpu(struct work_struct *work)
}

#ifdef HAVE_NF_HOOKFN_ARG_OPS
#define FIRST_PARAM const struct nf_hook_ops *ops,
#define FIRST_PARAM const struct nf_hook_ops *ops
#else
#define FIRST_PARAM unsigned int hooknum,
#define FIRST_PARAM unsigned int hooknum
#endif

static unsigned int nf_ip_hook(FIRST_PARAM
struct sk_buff *skb,
const struct net_device *in,
const struct net_device *out,
int (*okfn)(struct sk_buff *))
#if LINUX_VERSION_CODE >= KERNEL_VERSION(4,1,0)
#define LAST_PARAM const struct nf_hook_state *state
#else
#define LAST_PARAM const struct net_device *in, const struct net_device *out, int (*okfn)(struct sk_buff *)
#endif

static unsigned int nf_ip_hook(FIRST_PARAM, struct sk_buff *skb, LAST_PARAM)
{
struct stt_sock *stt_sock;
int ip_hdr_len;
Expand Down
10 changes: 5 additions & 5 deletions datapath/linux/compat/udp_tunnel.c
Expand Up @@ -142,10 +142,10 @@ void ovs_udp_csum_gso(struct sk_buff *skb)
}
EXPORT_SYMBOL_GPL(ovs_udp_csum_gso);

int rpl_udp_tunnel_xmit_skb(struct rtable *rt, struct sk_buff *skb,
__be32 src, __be32 dst, __u8 tos, __u8 ttl,
__be16 df, __be16 src_port, __be16 dst_port,
bool xnet, bool nocheck)
int rpl_udp_tunnel_xmit_skb(struct rtable *rt, struct sock *sk,
struct sk_buff *skb, __be32 src, __be32 dst,
__u8 tos, __u8 ttl, __be16 df, __be16 src_port,
__be16 dst_port, bool xnet, bool nocheck)
{
struct udphdr *uh;

Expand All @@ -159,7 +159,7 @@ int rpl_udp_tunnel_xmit_skb(struct rtable *rt, struct sk_buff *skb,

udp_set_csum(nocheck, skb, src, dst, skb->len);

return iptunnel_xmit(skb->sk, rt, skb, src, dst, IPPROTO_UDP,
return iptunnel_xmit(sk, rt, skb, src, dst, IPPROTO_UDP,
tos, ttl, df, xnet);
}
EXPORT_SYMBOL_GPL(rpl_udp_tunnel_xmit_skb);
Expand Down
7 changes: 3 additions & 4 deletions datapath/linux/compat/vxlan.c
Expand Up @@ -180,8 +180,7 @@ static void vxlan_build_gbp_hdr(struct vxlanhdr *vxh, u32 vxflags,
gbp->policy_id = htons(md->gbp & VXLAN_GBP_ID_MASK);
}

int rpl_vxlan_xmit_skb(struct vxlan_sock *vs,
struct rtable *rt, struct sk_buff *skb,
int rpl_vxlan_xmit_skb(struct rtable *rt, struct sock *sk, struct sk_buff *skb,
__be32 src, __be32 dst, __u8 tos, __u8 ttl, __be16 df,
__be16 src_port, __be16 dst_port,
struct vxlan_metadata *md, bool xnet, u32 vxflags)
Expand Down Expand Up @@ -217,11 +216,11 @@ int rpl_vxlan_xmit_skb(struct vxlan_sock *vs,
if (vxflags & VXLAN_F_GBP)
vxlan_build_gbp_hdr(vxh, vxflags, md);

vxlan_set_owner(vs->sock->sk, skb);
vxlan_set_owner(sk, skb);

ovs_skb_set_inner_protocol(skb, htons(ETH_P_TEB));

return udp_tunnel_xmit_skb(rt, skb, src, dst, tos,
return udp_tunnel_xmit_skb(rt, sk, skb, src, dst, tos,
ttl, df, src_port, dst_port, xnet,
!udp_sum);
}
Expand Down
3 changes: 2 additions & 1 deletion datapath/vport-lisp.c
Expand Up @@ -455,7 +455,8 @@ static int lisp_send(struct vport *vport, struct sk_buff *skb)
ovs_skb_set_inner_protocol(skb, skb->protocol);

df = tun_key->tun_flags & TUNNEL_DONT_FRAGMENT ? htons(IP_DF) : 0;
sent_len = udp_tunnel_xmit_skb(rt, skb, saddr, tun_key->ipv4_dst,
sent_len = udp_tunnel_xmit_skb(rt, lisp_port->lisp_rcv_socket->sk, skb,
saddr, tun_key->ipv4_dst,
tun_key->ipv4_tos, tun_key->ipv4_ttl,
df, src_port, dst_port, false, true);

Expand Down
2 changes: 1 addition & 1 deletion datapath/vport-vxlan.c
Expand Up @@ -260,7 +260,7 @@ static int vxlan_tnl_send(struct vport *vport, struct sk_buff *skb)
vxflags = vxlan_port->exts |
(tun_key->tun_flags & TUNNEL_CSUM ? VXLAN_F_UDP_CSUM : 0);

err = vxlan_xmit_skb(vxlan_port->vs, rt, skb,
err = vxlan_xmit_skb(rt, vxlan_port->vs->sock->sk, skb,
saddr, tun_key->ipv4_dst,
tun_key->ipv4_tos,
tun_key->ipv4_ttl, df,
Expand Down

0 comments on commit c0cddce

Please sign in to comment.