[ovs-dev] [PATCH 5/8] datapath: Add support for kernel 4.4

Pravin B Shelar pshelar at ovn.org
Mon Jul 18 02:24:06 UTC 2016


Most of changes are related to ip-fragment API and genetlink
API changes.

Signed-off-by: Pravin B Shelar <pshelar at ovn.org>
---
 acinclude.m4                                       | 17 ++++++++++--
 datapath/actions.c                                 |  5 +++-
 datapath/datapath.c                                |  3 +--
 datapath/linux/compat/genetlink-openvswitch.c      | 30 ++++++++++++++--------
 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 +++
 datapath/linux/compat/include/net/ip6_tunnel.h     | 20 ++-------------
 datapath/linux/compat/include/net/ip_tunnels.h     |  2 --
 .../include/net/netfilter/nf_conntrack_labels.h    |  2 ++
 datapath/linux/compat/ip_tunnels_core.c            | 20 ++++++++++++++-
 datapath/linux/compat/stt.c                        |  6 +++++
 datapath/linux/compat/udp_tunnel.c                 |  1 +
 datapath/linux/compat/vxlan.c                      |  2 +-
 15 files changed, 97 insertions(+), 50 deletions(-)

diff --git a/acinclude.m4 b/acinclude.m4
index 083ef77..6b608ef 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 3f2ba4c..e12ad0d 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.",
diff --git a/datapath/datapath.c b/datapath/datapath.c
index 6e0d911..db8a18a 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 9aea997..de63780 100644
--- a/datapath/linux/compat/genetlink-openvswitch.c
+++ b/datapath/linux/compat/genetlink-openvswitch.c
@@ -6,19 +6,16 @@
 #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)
+		     struct genl_info *info, u32 group, gfp_t flags)
 {
-#if LINUX_VERSION_CODE < KERNEL_VERSION(3,3,0)
-	struct sock *sk = net->genl_sock;
-	int report = 0;
+#ifdef HAVE_GENL_NOTIFY_TAKES_NET
+	struct net *net = genl_info_net(info);
+	u32 portid = info->snd_portid;
+	struct nlmsghdr *nlh = info->nlhdr;
 
-	if (nlh)
-		report = nlmsg_report(nlh);
-
-	nlmsg_notify(sk, skb, portid, group, report, flags);
-#else
 	genl_notify(skb, net, portid, group, nlh, flags);
+#else
+	genl_notify(family, skb, info, group, flags);
 #endif
 }
 EXPORT_SYMBOL_GPL(rpl_genl_notify);
@@ -54,5 +51,18 @@ error:
 
 }
 EXPORT_SYMBOL_GPL(rpl___genl_register_family);
+#else
+#ifdef HAVE_GENL_NOTIFY_TAKES_NET
+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;
 
+#undef genl_notify
+	genl_notify(family, skb, net, portid, group, nlh, flags);
+}
+EXPORT_SYMBOL_GPL(rpl_genl_notify);
+#endif
 #endif /* kernel version < 3.13.0 */
diff --git a/datapath/linux/compat/gso.c b/datapath/linux/compat/gso.c
index 1f23173..92f5441 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 280fc96..d088206 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 c8ee81a..4b42cf7 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 cbacb10..b188996 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 a47aa3a..b0917d8 100644
--- a/datapath/linux/compat/include/net/ip6_tunnel.h
+++ b/datapath/linux/compat/include/net/ip6_tunnel.h
@@ -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
diff --git a/datapath/linux/compat/include/net/ip_tunnels.h b/datapath/linux/compat/include/net/ip_tunnels.h
index 7c5c9b5..6775c9a 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 31507c4..c138de7 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 3964c4b..c3783bb 100644
--- a/datapath/linux/compat/ip_tunnels_core.c
+++ b/datapath/linux/compat/ip_tunnels_core.c
@@ -81,7 +81,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 +264,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 c899517..d3ab833 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 a80511b..9265c8a 100644
--- a/datapath/linux/compat/udp_tunnel.c
+++ b/datapath/linux/compat/udp_tunnel.c
@@ -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)
diff --git a/datapath/linux/compat/vxlan.c b/datapath/linux/compat/vxlan.c
index e835c6d..71b559f 100644
--- a/datapath/linux/compat/vxlan.c
+++ b/datapath/linux/compat/vxlan.c
@@ -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)
@@ -53,6 +52,7 @@
 #include <net/ip6_route.h>
 #endif
 
+#include <net/vxlan.h>
 #include "gso.h"
 #include "vport-netdev.h"
 #include "compat.h"
-- 
1.8.3.1




More information about the dev mailing list