From 0643a78b74cdada22061168bad5757a7ba523878 Mon Sep 17 00:00:00 2001 From: Pravin B Shelar Date: Mon, 18 Jul 2016 15:13:15 -0700 Subject: [PATCH] datapath: Add support for kernel 4.4 Most of changes are related to ip-fragment API and genetlink API changes. Signed-off-by: Pravin B Shelar Acked-by: Jesse Gross --- acinclude.m4 | 17 +++++++- datapath/actions.c | 7 ++-- datapath/datapath.c | 3 +- datapath/linux/compat/genetlink-openvswitch.c | 41 +++++++++---------- datapath/linux/compat/gso.c | 4 +- datapath/linux/compat/gso.h | 21 +++++++--- datapath/linux/compat/include/net/genetlink.h | 10 ++--- datapath/linux/compat/include/net/ip.h | 4 ++ .../linux/compat/include/net/ip6_tunnel.h | 20 +-------- .../linux/compat/include/net/ip_tunnels.h | 2 - .../net/netfilter/nf_conntrack_labels.h | 2 + datapath/linux/compat/ip_tunnels_core.c | 21 +++++++++- datapath/linux/compat/stt.c | 6 +++ datapath/linux/compat/udp_tunnel.c | 1 + datapath/linux/compat/vxlan.c | 4 +- 15 files changed, 98 insertions(+), 65 deletions(-) diff --git a/acinclude.m4 b/acinclude.m4 index 083ef77e6..6b608efa6 100644 --- a/acinclude.m4 +++ b/acinclude.m4 @@ -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 @@ -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], @@ -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])]) @@ -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]) diff --git a/datapath/actions.c b/datapath/actions.c index 3f2ba4cea..3f1fb9148 100644 --- a/datapath/actions.c +++ b/datapath/actions.c @@ -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.", @@ -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); diff --git a/datapath/datapath.c b/datapath/datapath.c index 6e0d9111c..db8a18a13 100644 --- a/datapath/datapath.c +++ b/datapath/datapath.c @@ -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); } /** diff --git a/datapath/linux/compat/genetlink-openvswitch.c b/datapath/linux/compat/genetlink-openvswitch.c index 9aea99777..5b0ecfa8d 100644 --- a/datapath/linux/compat/genetlink-openvswitch.c +++ b/datapath/linux/compat/genetlink-openvswitch.c @@ -2,27 +2,6 @@ #include #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; @@ -54,5 +33,23 @@ error: } 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 */ diff --git a/datapath/linux/compat/gso.c b/datapath/linux/compat/gso.c index 1f23173c9..92f54411c 100644 --- a/datapath/linux/compat/gso.c +++ b/datapath/linux/compat/gso.c @@ -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; @@ -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; diff --git a/datapath/linux/compat/gso.h b/datapath/linux/compat/gso.h index 280fc96b7..d0882062a 100644 --- a/datapath/linux/compat/gso.h +++ b/datapath/linux/compat/gso.h @@ -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 diff --git a/datapath/linux/compat/include/net/genetlink.h b/datapath/linux/compat/include/net/genetlink.h index c8ee81a76..4b42cf754 100644 --- a/datapath/linux/compat/include/net/genetlink.h +++ b/datapath/linux/compat/include/net/genetlink.h @@ -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) { @@ -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 diff --git a/datapath/linux/compat/include/net/ip.h b/datapath/linux/compat/include/net/ip.h index cbacb1083..b18899660 100644 --- a/datapath/linux/compat/include/net/ip.h +++ b/datapath/linux/compat/include/net/ip.h @@ -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 diff --git a/datapath/linux/compat/include/net/ip6_tunnel.h b/datapath/linux/compat/include/net/ip6_tunnel.h index a47aa3a7c..b0917d852 100644 --- a/datapath/linux/compat/include/net/ip6_tunnel.h +++ b/datapath/linux/compat/include/net/ip6_tunnel.h @@ -7,24 +7,8 @@ #include #include_next -#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 diff --git a/datapath/linux/compat/include/net/ip_tunnels.h b/datapath/linux/compat/include/net/ip_tunnels.h index 7c5c9b584..6775c9aaf 100644 --- a/datapath/linux/compat/include/net/ip_tunnels.h +++ b/datapath/linux/compat/include/net/ip_tunnels.h @@ -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) { diff --git a/datapath/linux/compat/include/net/netfilter/nf_conntrack_labels.h b/datapath/linux/compat/include/net/netfilter/nf_conntrack_labels.h index 31507c45f..c138de7ba 100644 --- a/datapath/linux/compat/include/net/netfilter/nf_conntrack_labels.h +++ b/datapath/linux/compat/include/net/netfilter/nf_conntrack_labels.h @@ -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 */ diff --git a/datapath/linux/compat/ip_tunnels_core.c b/datapath/linux/compat/ip_tunnels_core.c index 3964c4b20..8eab276dc 100644 --- a/datapath/linux/compat/ip_tunnels_core.c +++ b/datapath/linux/compat/ip_tunnels_core.c @@ -30,6 +30,7 @@ #include #include #include +#include #include #include @@ -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); @@ -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 diff --git a/datapath/linux/compat/stt.c b/datapath/linux/compat/stt.c index c89951776..d3ab8335d 100644 --- a/datapath/linux/compat/stt.c +++ b/datapath/linux/compat/stt.c @@ -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) @@ -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, diff --git a/datapath/linux/compat/udp_tunnel.c b/datapath/linux/compat/udp_tunnel.c index a80511b3e..9265c8a99 100644 --- a/datapath/linux/compat/udp_tunnel.c +++ b/datapath/linux/compat/udp_tunnel.c @@ -15,6 +15,7 @@ #include #include +#include "gso.h" int rpl_udp_sock_create4(struct net *net, struct udp_port_cfg *cfg, struct socket **sockp) diff --git a/datapath/linux/compat/vxlan.c b/datapath/linux/compat/vxlan.c index 8e0075d9e..6d7752796 100644 --- a/datapath/linux/compat/vxlan.c +++ b/datapath/linux/compat/vxlan.c @@ -42,7 +42,6 @@ #include #include #include -#include #include #if IS_ENABLED(CONFIG_IPV6) @@ -53,6 +52,7 @@ #include #endif +#include #include "gso.h" #include "vport-netdev.h" #include "compat.h" @@ -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; -- 2.20.1