[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_GREP_IFELSE([$KSRC/include/linux/netfilter.h], [NFPROTO_INET])
+
OVS_FIND_FIELD_IFELSE([$KSRC/include/linux/netfilter_ipv6.h], [nf_ipv6_ops],
[fragment.*sock], [OVS_DEFINE([HAVE_NF_IPV6_OPS_FRAGMENT])])
[nf_ct_is_untracked])
OVS_GREP_IFELSE([$KSRC/include/net/netfilter/nf_conntrack_zones.h],
[nf_ct_zone_init])
+ OVS_FIND_FIELD_IFELSE([$KSRC/include/net/netfilter/nf_conntrack_l3proto.h],
+ [net_ns_get])
OVS_GREP_IFELSE([$KSRC/include/net/netfilter/nf_conntrack_labels.h],
[nf_connlabels_get])
OVS_FIND_PARAM_IFELSE([$KSRC/include/net/netfilter/nf_conntrack_labels.h],
linux/compat/lisp.c \
linux/compat/netdevice.c \
linux/compat/nf_conntrack_core.c \
+ linux/compat/nf_conntrack_proto.c \
linux/compat/nf_conntrack_reasm.c \
linux/compat/reciprocal_div.c \
linux/compat/skbuff-openvswitch.c \
linux/compat/include/net/netfilter/nf_nat.h \
linux/compat/include/net/netfilter/ipv6/nf_defrag_ipv6.h \
linux/compat/include/net/sctp/checksum.h \
- linux/compat/include/net/erspan.h
+ linux/compat/include/net/erspan.h \
+ linux/compat/include/uapi/linux/netfilter.h
EXTRA_DIST += linux/compat/build-aux/export-check-whitelist
--- /dev/null
+#include <linux/types.h>
+
+#include <net/netfilter/nf_conntrack.h>
+#include <net/netfilter/nf_conntrack_l3proto.h>
+
+/*
+ * Upstream net-next commmit 7e35ec0e8044
+ * ("netfilter: conntrack: move nf_ct_netns_{get,put}() to core")
+ * is introduced in v4.15, and it supports NFPROTO_INET in
+ * nf_ct_netns_{get,put}() that OVS conntrack uses this feature.
+ *
+ * However, we only need this feature if the underlying nf_conntrack_l3proto
+ * supports net_ns_get/put. Thus, we just mock the functions if
+ * HAVE_NET_NS_SET is false.
+ */
+#if LINUX_VERSION_CODE < KERNEL_VERSION(4,15,0)
+#ifdef HAVE_NET_NS_SET
+static int nf_ct_netns_do_get(struct net *net, u8 nfproto)
+{
+ const struct nf_conntrack_l3proto *l3proto;
+ int ret;
+
+ might_sleep();
+
+ ret = nf_ct_l3proto_try_module_get(nfproto);
+ if (ret < 0)
+ return ret;
+
+ /* we already have a reference, can't fail */
+ rcu_read_lock();
+ l3proto = __nf_ct_l3proto_find(nfproto);
+ rcu_read_unlock();
+
+ if (!l3proto->net_ns_get)
+ return 0;
+
+ ret = l3proto->net_ns_get(net);
+ if (ret < 0)
+ nf_ct_l3proto_module_put(nfproto);
+
+ return ret;
+}
+
+int rpl_nf_ct_netns_get(struct net *net, u8 nfproto)
+{
+ int err;
+
+ if (nfproto == NFPROTO_INET) {
+ err = nf_ct_netns_do_get(net, NFPROTO_IPV4);
+ if (err < 0)
+ goto err1;
+ err = nf_ct_netns_do_get(net, NFPROTO_IPV6);
+ if (err < 0)
+ goto err2;
+ } else {
+ err = nf_ct_netns_do_get(net, nfproto);
+ if (err < 0)
+ goto err1;
+ }
+ return 0;
+
+err2:
+ nf_ct_netns_put(net, NFPROTO_IPV4);
+err1:
+ return err;
+}
+EXPORT_SYMBOL_GPL(rpl_nf_ct_netns_get);
+
+static void nf_ct_netns_do_put(struct net *net, u8 nfproto)
+{
+ const struct nf_conntrack_l3proto *l3proto;
+
+ might_sleep();
+
+ /* same as nf_conntrack_netns_get(), reference assumed */
+ rcu_read_lock();
+ l3proto = __nf_ct_l3proto_find(nfproto);
+ rcu_read_unlock();
+
+ if (WARN_ON(!l3proto))
+ return;
+
+ if (l3proto->net_ns_put)
+ l3proto->net_ns_put(net);
+
+ nf_ct_l3proto_module_put(nfproto);
+}
+
+void rpl_nf_ct_netns_put(struct net *net, uint8_t nfproto)
+{
+ if (nfproto == NFPROTO_INET) {
+ nf_ct_netns_do_put(net, NFPROTO_IPV4);
+ nf_ct_netns_do_put(net, NFPROTO_IPV6);
+ } else
+ nf_ct_netns_do_put(net, nfproto);
+}
+EXPORT_SYMBOL_GPL(rpl_nf_ct_netns_put);
+
+#else /* !HAVE_NET_NS_SET */
+void rpl_nf_ct_netns_put(struct net *net, uint8_t nfproto)
+{
+}
+EXPORT_SYMBOL_GPL(rpl_nf_ct_netns_put);
+
+int rpl_nf_ct_netns_get(struct net *net, u8 nfproto)
+{
+ return 0;
+}
+EXPORT_SYMBOL_GPL(rpl_nf_ct_netns_get);
+
+#endif /* HAVE_NET_NS_SET */
+#endif /* LINUX_VERSION_CODE < KERNEL_VERSION(4,15,0) */