Skip to content

Commit

Permalink
datapath: Add support for kernel 4.4
Browse files Browse the repository at this point in the history
Most of changes are related to ip-fragment API and genetlink
API changes.

Signed-off-by: Pravin B Shelar <[email protected]>
Acked-by: Jesse Gross <[email protected]>
  • Loading branch information
pshelar committed Jul 19, 2016
1 parent 6a9722f commit 0643a78
Show file tree
Hide file tree
Showing 15 changed files with 98 additions and 65 deletions.
17 changes: 15 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 4; then
if test "$version" = 4 && test "$patchlevel" -le 3; then
if test "$version" = 4 && test "$patchlevel" -le 4; then
: # Linux 4.x
else
AC_ERROR([Linux kernel in $KBUILD is version $kversion, but version newer than 4.3.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.4.x is not supported (please refer to the FAQ for advice)])
fi
elif test "$version" = 3 && test "$patchlevel" -ge 10; then
: # Linux 3.x
Expand Down Expand Up @@ -415,6 +415,10 @@ AC_DEFUN([OVS_CHECK_LINUX_COMPAT], [
OVS_FIND_PARAM_IFELSE([$KSRC/include/net/ip.h],
[ip_do_fragment], [net],
[OVS_DEFINE([HAVE_IP_DO_FRAGMENT_TAKES_NET])])
OVS_FIND_PARAM_IFELSE([$KSRC/include/net/ip.h],
[ip_local_out], [net],
[OVS_DEFINE([HAVE_IP_LOCAL_OUT_TAKES_NET])])
OVS_GREP_IFELSE([$KSRC/include/net/ip.h], [ip_skb_dst_mtu])
OVS_GREP_IFELSE([$KSRC/include/net/ip.h], [IPSKB_FRAG_PMTU],
Expand Down Expand Up @@ -476,6 +480,11 @@ AC_DEFUN([OVS_CHECK_LINUX_COMPAT], [
OVS_GREP_IFELSE([$KSRC/include/linux/netfilter.h], [nf_register_net_hook])
OVS_GREP_IFELSE([$KSRC/include/linux/netfilter.h], [nf_hookfn.*nf_hook_ops],
[OVS_DEFINE([HAVE_NF_HOOKFN_ARG_OPS])])
OVS_FIND_PARAM_IFELSE([$KSRC/include/linux/netfilter.h], [nf_hookfn], [priv],
[OVS_DEFINE([HAVE_NF_HOOKFN_ARG_PRIV])])
OVS_FIND_FIELD_IFELSE([$KSRC/include/linux/netfilter.h], [nf_hook_ops],
[owner], [OVS_DEFINE([HAVE_NF_HOOKS_OPS_OWNER])])
OVS_FIND_FIELD_IFELSE([$KSRC/include/linux/netfilter_ipv6.h], [nf_ipv6_ops],
[fragment.*sock], [OVS_DEFINE([HAVE_NF_IPV6_OPS_FRAGMENT])])
Expand Down Expand Up @@ -581,6 +590,10 @@ AC_DEFUN([OVS_CHECK_LINUX_COMPAT], [
OVS_GREP_IFELSE([$KSRC/include/net/genetlink.h], [genlmsg_parse])
OVS_GREP_IFELSE([$KSRC/include/net/genetlink.h], [genl_notify.*family],
[OVS_DEFINE([HAVE_GENL_NOTIFY_TAKES_FAMILY])])
OVS_FIND_PARAM_IFELSE([$KSRC/include/net/genetlink.h],
[genl_notify], [net],
[OVS_DEFINE([HAVE_GENL_NOTIFY_TAKES_NET])])
OVS_FIND_FIELD_IFELSE([$KSRC/include/net/genetlink.h],
[genl_multicast_group], [id])
Expand Down
7 changes: 4 additions & 3 deletions datapath/actions.c
Original file line number Diff line number Diff line change
Expand Up @@ -729,8 +729,11 @@ static void ovs_fragment(struct net *net, struct vport *vport,
orig_dst = (unsigned long) skb_dst(skb);
skb_dst_set_noref(skb, &ovs_rt.dst);
IP6CB(skb)->frag_max_size = mru;

#ifdef HAVE_IP_LOCAL_OUT_TAKES_NET
v6ops->fragment(net, skb->sk, skb, ovs_vport_output);
#else
v6ops->fragment(skb->sk, skb, ovs_vport_output);
#endif
refdst_drop(orig_dst);
} else {
WARN_ONCE(1, "Failed fragment ->%s: eth=%04x, MRU=%d, MTU=%d.",
Expand Down Expand Up @@ -814,8 +817,6 @@ static int output_userspace(struct datapath *dp, struct sk_buff *skb,

vport = ovs_vport_rcu(dp, nla_get_u32(a));
if (vport) {
int err;

err = dev_fill_metadata_dst(vport->dev, skb);
if (!err)
upcall.egress_tun_info = skb_tunnel_info(skb);
Expand Down
3 changes: 1 addition & 2 deletions datapath/datapath.c
Original file line number Diff line number Diff line change
Expand Up @@ -95,8 +95,7 @@ static bool ovs_must_notify(struct genl_family *family, struct genl_info *info,
static void ovs_notify(struct genl_family *family, struct genl_multicast_group *grp,
struct sk_buff *skb, struct genl_info *info)
{
genl_notify(family, skb, genl_info_net(info),
info->snd_portid, GROUP_ID(grp), info->nlhdr, GFP_KERNEL);
genl_notify(family, skb, info, GROUP_ID(grp), GFP_KERNEL);
}

/**
Expand Down
41 changes: 19 additions & 22 deletions datapath/linux/compat/genetlink-openvswitch.c
Original file line number Diff line number Diff line change
Expand Up @@ -2,27 +2,6 @@
#include <linux/version.h>

#ifndef HAVE_GENL_NOTIFY_TAKES_FAMILY

#undef genl_notify

void rpl_genl_notify(struct rpl_genl_family *family, struct sk_buff *skb,
struct net *net, u32 portid, u32 group,
struct nlmsghdr *nlh, gfp_t flags)
{
#if LINUX_VERSION_CODE < KERNEL_VERSION(3,3,0)
struct sock *sk = net->genl_sock;
int report = 0;

if (nlh)
report = nlmsg_report(nlh);

nlmsg_notify(sk, skb, portid, group, report, flags);
#else
genl_notify(skb, net, portid, group, nlh, flags);
#endif
}
EXPORT_SYMBOL_GPL(rpl_genl_notify);

int rpl___genl_register_family(struct rpl_genl_family *f)
{
int err;
Expand Down Expand Up @@ -54,5 +33,23 @@ int rpl___genl_register_family(struct rpl_genl_family *f)

}
EXPORT_SYMBOL_GPL(rpl___genl_register_family);
#endif /* HAVE_GENL_NOTIFY_TAKES_FAMILY */

#ifdef HAVE_GENL_NOTIFY_TAKES_NET

#undef genl_notify

void rpl_genl_notify(struct genl_family *family, struct sk_buff *skb,
struct genl_info *info, u32 group, gfp_t flags)
{
struct net *net = genl_info_net(info);
u32 portid = info->snd_portid;
struct nlmsghdr *nlh = info->nlhdr;

#endif /* kernel version < 3.13.0 */
#ifdef HAVE_GENL_NOTIFY_TAKES_FAMILY
genl_notify(family, skb, net, portid, group, nlh, flags);
#else
genl_notify(skb, net, portid, group, nlh, flags);
#endif
}
#endif /* HAVE_GENL_NOTIFY_TAKES_NET */
4 changes: 2 additions & 2 deletions datapath/linux/compat/gso.c
Original file line number Diff line number Diff line change
Expand Up @@ -263,7 +263,7 @@ static int output_ip(struct sk_buff *skb)
return ret;
}

int rpl_ip_local_out(struct sk_buff *skb)
int rpl_ip_local_out(struct net *net, struct sock *sk, struct sk_buff *skb)
{
int ret = NETDEV_TX_OK;
int id = -1;
Expand Down Expand Up @@ -318,7 +318,7 @@ static int output_ipv6(struct sk_buff *skb)
return ret;
}

int rpl_ip6_local_out(struct sk_buff *skb)
int rpl_ip6_local_out(struct net *net, struct sock *sk, struct sk_buff *skb)
{
int ret = NETDEV_TX_OK;

Expand Down
21 changes: 15 additions & 6 deletions datapath/linux/compat/gso.h
Original file line number Diff line number Diff line change
Expand Up @@ -86,29 +86,38 @@ static inline void ovs_skb_set_inner_protocol(struct sk_buff *skb,
#endif /* HAVE_INNER_PROTOCOL */

#if LINUX_VERSION_CODE < KERNEL_VERSION(3,18,0)
#define ip_local_out rpl_ip_local_out
int rpl_ip_local_out(struct sk_buff *skb);

static inline int skb_inner_mac_offset(const struct sk_buff *skb)
{
return skb_inner_mac_header(skb) - skb->data;
}

#define ip_local_out rpl_ip_local_out
int rpl_ip_local_out(struct net *net, struct sock *sk, struct sk_buff *skb);

#define ip6_local_out rpl_ip6_local_out
int rpl_ip6_local_out(struct sk_buff *skb);
int rpl_ip6_local_out(struct net *net, struct sock *sk, struct sk_buff *skb);
#else

static inline int rpl_ip_local_out(struct sk_buff *skb)
static inline int rpl_ip_local_out(struct net *net, struct sock *sk, struct sk_buff *skb)
{
memset(IPCB(skb), 0, sizeof(*IPCB(skb)));
#ifdef HAVE_IP_LOCAL_OUT_TAKES_NET
/* net and sk parameters are added at same time. */
return ip_local_out(net, sk, skb);
#else
return ip_local_out(skb);
#endif
}
#define ip_local_out rpl_ip_local_out

static inline int rpl_ip6_local_out(struct sk_buff *skb)
static inline int rpl_ip6_local_out(struct net *net, struct sock *sk, struct sk_buff *skb)
{
memset(IP6CB(skb), 0, sizeof (*IP6CB(skb)));
#ifdef HAVE_IP_LOCAL_OUT_TAKES_NET
return ip6_local_out(net, sk, skb);
#else
return ip6_local_out(skb);
#endif
}
#define ip6_local_out rpl_ip6_local_out

Expand Down
10 changes: 5 additions & 5 deletions datapath/linux/compat/include/net/genetlink.h
Original file line number Diff line number Diff line change
Expand Up @@ -44,11 +44,6 @@ struct rpl_genl_family {
};

#define genl_family rpl_genl_family
#define genl_notify rpl_genl_notify
void rpl_genl_notify(struct genl_family *family,
struct sk_buff *skb, struct net *net, u32 portid, u32 group,
struct nlmsghdr *nlh, gfp_t flags);

static inline void *rpl_genlmsg_put(struct sk_buff *skb, u32 portid, u32 seq,
struct genl_family *family, int flags, u8 cmd)
{
Expand Down Expand Up @@ -93,7 +88,12 @@ static inline int rpl_genl_register_family(struct genl_family *family)
family->module = THIS_MODULE;
return rpl___genl_register_family(family);
}
#endif

#ifdef HAVE_GENL_NOTIFY_TAKES_NET
#define genl_notify rpl_genl_notify
void rpl_genl_notify(struct genl_family *family, struct sk_buff *skb,
struct genl_info *info , u32 group, gfp_t flags);
#endif

#ifndef HAVE_GENL_HAS_LISTENERS
Expand Down
4 changes: 4 additions & 0 deletions datapath/linux/compat/include/net/ip.h
Original file line number Diff line number Diff line change
Expand Up @@ -60,7 +60,11 @@ static inline unsigned int rpl_ip_skb_dst_mtu(const struct sk_buff *skb)
#endif /* HAVE_IP_SKB_DST_MTU */

#ifdef HAVE_IP_FRAGMENT_TAKES_SOCK
#ifdef HAVE_IP_LOCAL_OUT_TAKES_NET
#define OVS_VPORT_OUTPUT_PARAMS struct net *net, struct sock *sock, struct sk_buff *skb
#else
#define OVS_VPORT_OUTPUT_PARAMS struct sock *sock, struct sk_buff *skb
#endif
#else
#define OVS_VPORT_OUTPUT_PARAMS struct sk_buff *skb
#endif
Expand Down
20 changes: 2 additions & 18 deletions datapath/linux/compat/include/net/ip6_tunnel.h
Original file line number Diff line number Diff line change
Expand Up @@ -7,24 +7,8 @@
#include <linux/ip6_tunnel.h>
#include_next <net/ip6_tunnel.h>

#include "gso.h"

#define ip6tunnel_xmit rpl_ip6tunnel_xmit
static inline void ip6tunnel_xmit(struct sock *sk, struct sk_buff *skb,
struct net_device *dev)
{
int pkt_len, err;

pkt_len = skb->len - skb_inner_network_offset(skb);
#ifdef HAVE_IP6_LOCAL_OUT_SK
err = ip6_local_out_sk(sk, skb);
#else
err = ip6_local_out(skb);
#endif
if (net_xmit_eval(err))
pkt_len = -1;

iptunnel_xmit_stats(dev, pkt_len);
}
void rpl_ip6tunnel_xmit(struct sock *sk, struct sk_buff *skb,
struct net_device *dev);

#endif
2 changes: 0 additions & 2 deletions datapath/linux/compat/include/net/ip_tunnels.h
Original file line number Diff line number Diff line change
Expand Up @@ -326,10 +326,8 @@ int rpl_ip_tunnel_get_iflink(const struct net_device *dev);
#define ip_tunnel_get_link_net rpl_ip_tunnel_get_link_net
struct net *rpl_ip_tunnel_get_link_net(const struct net_device *dev);

#ifndef HAVE___IP_TUNNEL_CHANGE_MTU
#define __ip_tunnel_change_mtu rpl___ip_tunnel_change_mtu
int rpl___ip_tunnel_change_mtu(struct net_device *dev, int new_mtu, bool strict);
#endif

static inline int iptunnel_pull_offloads(struct sk_buff *skb)
{
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -47,11 +47,13 @@ static inline void rpl_nf_connlabels_put(struct net *net)
#define nf_connlabels_put rpl_nf_connlabels_put

#else /* CONFIG_NF_CONNTRACK_LABELS */
#define nf_connlabels_get rpl_nf_connlabels_get
static inline int nf_connlabels_get(struct net *net, unsigned int bits)
{
return -ERANGE;
}

#define nf_connlabels_put rpl_nf_connlabels_put
static inline void nf_connlabels_put(struct net *net) { }
#endif /* CONFIG_NF_CONNTRACK_LABELS */
#endif /* HAVE_NF_CONNLABELS_GET_TAKES_BIT */
Expand Down
21 changes: 20 additions & 1 deletion datapath/linux/compat/ip_tunnels_core.c
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,7 @@
#include <linux/workqueue.h>
#include <linux/rculist.h>
#include <net/ip_tunnels.h>
#include <net/ip6_tunnel.h>
#include <net/route.h>
#include <net/xfrm.h>

Expand Down Expand Up @@ -81,7 +82,7 @@ void rpl_iptunnel_xmit(struct sock *sk, struct rtable *rt, struct sk_buff *skb,
__ip_select_ident(iph, skb_shinfo(skb)->gso_segs ?: 1);
#endif

err = ip_local_out(skb);
err = ip_local_out(dev_net(rt->dst.dev), sk, skb);
if (unlikely(net_xmit_eval(err)))
pkt_len = 0;
iptunnel_xmit_stats(dev, pkt_len);
Expand Down Expand Up @@ -264,4 +265,22 @@ struct rtnl_link_stats64 *rpl_ip_tunnel_get_stats64(struct net_device *dev,
return tot;
}
#endif

void rpl_ip6tunnel_xmit(struct sock *sk, struct sk_buff *skb,
struct net_device *dev)
{
int pkt_len, err;

pkt_len = skb->len - skb_inner_network_offset(skb);
#ifdef HAVE_IP6_LOCAL_OUT_SK
err = ip6_local_out_sk(sk, skb);
#else
err = ip6_local_out(dev_net(skb_dst(skb)->dev), sk, skb);
#endif
if (net_xmit_eval(err))
pkt_len = -1;

iptunnel_xmit_stats(dev, pkt_len);
}
EXPORT_SYMBOL_GPL(rpl_ip6tunnel_xmit);
#endif
6 changes: 6 additions & 0 deletions datapath/linux/compat/stt.c
Original file line number Diff line number Diff line change
Expand Up @@ -1554,8 +1554,12 @@ static void clean_percpu(struct work_struct *work)
#ifdef HAVE_NF_HOOKFN_ARG_OPS
#define FIRST_PARAM const struct nf_hook_ops *ops
#else
#ifdef HAVE_NF_HOOKFN_ARG_PRIV
#define FIRST_PARAM void *priv
#else
#define FIRST_PARAM unsigned int hooknum
#endif
#endif

#ifdef HAVE_NF_HOOK_STATE
#if RHEL_RELEASE_CODE > RHEL_RELEASE_VERSION(7,0)
Expand Down Expand Up @@ -1600,7 +1604,9 @@ static unsigned int nf_ip_hook(FIRST_PARAM, struct sk_buff *skb, LAST_PARAM)

static struct nf_hook_ops nf_hook_ops __read_mostly = {
.hook = nf_ip_hook,
#ifdef HAVE_NF_HOOKS_OPS_OWNER
.owner = THIS_MODULE,
#endif
.pf = NFPROTO_IPV4,
.hooknum = NF_INET_LOCAL_IN,
.priority = INT_MAX,
Expand Down
1 change: 1 addition & 0 deletions datapath/linux/compat/udp_tunnel.c
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@
#include <net/ip6_checksum.h>
#include <net/ip6_tunnel.h>

#include "gso.h"

int rpl_udp_sock_create4(struct net *net, struct udp_port_cfg *cfg,
struct socket **sockp)
Expand Down
4 changes: 2 additions & 2 deletions datapath/linux/compat/vxlan.c
Original file line number Diff line number Diff line change
Expand Up @@ -42,7 +42,6 @@
#include <net/inet_ecn.h>
#include <net/net_namespace.h>
#include <net/netns/generic.h>
#include <net/vxlan.h>
#include <net/protocol.h>

#if IS_ENABLED(CONFIG_IPV6)
Expand All @@ -53,6 +52,7 @@
#include <net/ip6_route.h>
#endif

#include <net/vxlan.h>
#include "gso.h"
#include "vport-netdev.h"
#include "compat.h"
Expand Down Expand Up @@ -221,7 +221,7 @@ static struct vxlan_dev *vxlan_find_vni(struct net *net, __be32 vni,
static int vxlan_fdb_create(struct vxlan_dev *vxlan,
const u8 *mac, union vxlan_addr *ip,
__u16 state, __u16 flags,
__be16 port, __u32 vni, __u32 ifindex,
__be16 port, __be32 vni, __u32 ifindex,
__u8 ndm_flags)
{
return -EINVAL;
Expand Down

0 comments on commit 0643a78

Please sign in to comment.