@@ -714,6 +714,13 @@ AC_DEFUN([OVS_CHECK_LINUX_COMPAT], [
OVS_GREP_IFELSE([$KSRC/include/net/netfilter/nf_conntrack_seqadj.h], [nf_ct_seq_adjust])
OVS_GREP_IFELSE([$KSRC/include/net/netfilter/nf_conntrack_count.h], [nf_conncount_gc_list],
[OVS_DEFINE([HAVE_UPSTREAM_NF_CONNCOUNT])])
+ OVS_GREP_IFELSE([$KSRC/include/net/netfilter/nf_conntrack_timeout.h], [nf_ct_set_timeout])
+ OVS_GREP_IFELSE([$KSRC/include/net/netfilter/nf_conntrack_timeout.h], [struct nf_ct_timeout],
+ [OVS_DEFINE([HAVE_NF_CT_TIMEOUT])])
+ OVS_FIND_PARAM_IFELSE([$KSRC/include/net/netfilter/nf_conntrack_timeout.h],
+ [\(*nf_ct_timeout_find_get_hook\)], [net],
+ [OVS_DEFINE([HAVE_NF_CT_TIMEOUT_FIND_GET_HOOK_NET])])
+
OVS_GREP_IFELSE([$KSRC/include/linux/random.h], [prandom_u32])
OVS_GREP_IFELSE([$KSRC/include/linux/random.h], [prandom_u32_max])
@@ -21,6 +21,7 @@ openvswitch_sources += \
linux/compat/nf_conntrack_core.c \
linux/compat/nf_conntrack_proto.c \
linux/compat/nf_conntrack_reasm.c \
+ linux/compat/nf_conntrack_timeout.c \
linux/compat/reciprocal_div.c \
linux/compat/skbuff-openvswitch.c \
linux/compat/socket.c \
@@ -108,6 +109,7 @@ openvswitch_headers += \
linux/compat/include/net/netfilter/nf_conntrack_helper.h \
linux/compat/include/net/netfilter/nf_conntrack_labels.h \
linux/compat/include/net/netfilter/nf_conntrack_seqadj.h \
+ linux/compat/include/net/netfilter/nf_conntrack_timeout.h \
linux/compat/include/net/netfilter/nf_conntrack_zones.h \
linux/compat/include/net/netfilter/nf_nat.h \
linux/compat/include/net/netfilter/ipv6/nf_defrag_ipv6.h \
new file mode 100644
@@ -0,0 +1,34 @@
+#ifndef _NF_CONNTRACK_TIMEOUT_WRAPPER_H
+#define _NF_CONNTRACK_TIMEOUT_WRAPPER_H
+
+#include_next <net/netfilter/nf_conntrack_timeout.h>
+
+#ifndef HAVE_NF_CT_SET_TIMEOUT
+
+#ifndef HAVE_NF_CT_TIMEOUT
+#define nf_ct_timeout ctnl_timeout
+#endif
+
+#ifdef CONFIG_NF_CONNTRACK_TIMEOUT
+int rpl_nf_ct_set_timeout(struct net *net, struct nf_conn *ct, u8 l3num, u8 l4num,
+ const char *timeout_name);
+void rpl_nf_ct_destroy_timeout(struct nf_conn *ct);
+#else
+static inline int rpl_nf_ct_set_timeout(struct net *net, struct nf_conn *ct,
+ u8 l3num, u8 l4num,
+ const char *timeout_name)
+{
+ return -EOPNOTSUPP;
+}
+
+static inline void rpl_nf_ct_destroy_timeout(struct nf_conn *ct)
+{
+ return;
+}
+#endif /* CONFIG_NF_CONNTRACK_TIMEOUT */
+
+#define nf_ct_set_timeout rpl_nf_ct_set_timeout
+#define nf_ct_destroy_timeout rpl_nf_ct_destroy_timeout
+
+#endif /* HAVE_NF_CT_SET_TIMEOUT */
+#endif /* _NF_CONNTRACK_TIMEOUT_WRAPPER_H */
new file mode 100644
@@ -0,0 +1,102 @@
+#include <net/netfilter/nf_conntrack.h>
+#include <net/netfilter/nf_conntrack_core.h>
+#include <net/netfilter/nf_conntrack_extend.h>
+#include <net/netfilter/nf_conntrack_timeout.h>
+
+#ifdef CONFIG_NF_CONNTRACK_TIMEOUT
+#ifndef HAVE_NF_CT_SET_TIMEOUT
+static void rpl__nf_ct_timeout_put(struct nf_ct_timeout *timeout)
+{
+ typeof(nf_ct_timeout_put_hook) timeout_put;
+
+ timeout_put = rcu_dereference(nf_ct_timeout_put_hook);
+ if (timeout_put)
+ timeout_put(timeout);
+}
+
+int rpl_nf_ct_set_timeout(struct net *net, struct nf_conn *ct,
+ u8 l3num, u8 l4num, const char *timeout_name)
+{
+ typeof(nf_ct_timeout_find_get_hook) timeout_find_get;
+ struct nf_ct_timeout *timeout;
+ struct nf_conn_timeout *timeout_ext;
+ const char *errmsg = NULL;
+ int ret = 0;
+
+ rcu_read_lock();
+ timeout_find_get = rcu_dereference(nf_ct_timeout_find_get_hook);
+ if (!timeout_find_get) {
+ ret = -ENOENT;
+ errmsg = "Timeout policy base is empty";
+ goto out;
+ }
+
+#ifdef HAVE_NF_CT_TIMEOUT_FIND_GET_HOOK_NET
+ timeout = timeout_find_get(net, timeout_name);
+#else
+ timeout = timeout_find_get(timeout_name);
+#endif
+ if (!timeout) {
+ ret = -ENOENT;
+ pr_info_ratelimited("No such timeout policy \"%s\"\n",
+ timeout_name);
+ goto out;
+ }
+
+ if (timeout->l3num != l3num) {
+ ret = -EINVAL;
+ pr_info_ratelimited("Timeout policy `%s' can only be used by "
+ "L%d protocol number %d\n",
+ timeout_name, 3, timeout->l3num);
+ goto err_put_timeout;
+ }
+ /* Make sure the timeout policy matches any existing protocol tracker,
+ * otherwise default to generic.
+ */
+ if (timeout->l4proto->l4proto != l4num) {
+ ret = -EINVAL;
+ pr_info_ratelimited("Timeout policy `%s' can only be used by "
+ "L%d protocol number %d\n",
+ timeout_name, 4, timeout->l4proto->l4proto);
+ goto err_put_timeout;
+ }
+ timeout_ext = nf_ct_timeout_ext_add(ct, timeout, GFP_ATOMIC);
+ if (!timeout_ext) {
+ ret = -ENOMEM;
+ goto err_put_timeout;
+ }
+
+ rcu_read_unlock();
+ return ret;
+
+err_put_timeout:
+ rpl__nf_ct_timeout_put(timeout);
+out:
+ rcu_read_unlock();
+ if (errmsg)
+ pr_info_ratelimited("%s\n", errmsg);
+ return ret;
+}
+EXPORT_SYMBOL_GPL(rpl_nf_ct_set_timeout);
+
+void rpl_nf_ct_destroy_timeout(struct nf_conn *ct)
+{
+ struct nf_conn_timeout *timeout_ext;
+ typeof(nf_ct_timeout_put_hook) timeout_put;
+
+ rcu_read_lock();
+ timeout_put = rcu_dereference(nf_ct_timeout_put_hook);
+
+ if (timeout_put) {
+ timeout_ext = nf_ct_timeout_find(ct);
+ if (timeout_ext) {
+ timeout_put(timeout_ext->timeout);
+ RCU_INIT_POINTER(timeout_ext->timeout, NULL);
+ }
+ }
+ rcu_read_unlock();
+}
+EXPORT_SYMBOL_GPL(rpl_nf_ct_destroy_timeout);
+
+#endif /* HAVE_NF_CT_SET_TIMEOUT */
+#endif /* CONFIG_NF_CONNTRACK_TIMEOUT */
This patch brings in nf_ct_timeout_put() and nf_ct_set_timeout() when it is not available in the kernel. Three symbols are created in acinclude.m4. * HAVE_NF_CT_SET_TIMEOUT is used to determine if upstream net-next commit 717700d183d65 ("netfilter: Export nf_ct_{set,destroy}_timeout()") is availabe. If it is defined, the kernel should have all the nf_conntrack_timeout support that OVS needs. * HAVE_NF_CT_TIMEOUT is used to check if upstream net-next commit 6c1fd7dc489d9 ("netfilter: cttimeout: decouple timeout policy from nfnetlink_cttimeout object") is there. If it is not defined, we will use the old ctnl_timeout interface rather than the nf_ct_timeout interface that is introduced in this commit. * HAVE_NF_CT_TIMEOUT_FIND_GET_HOOK_NET is used to check if upstream commit 19576c9478682 ("netfilter: cttimeout: add netns support") is there, so that we pass different arguement based on whether the kernel has netns support. Signed-off-by: Yi-Hung Wei <yihung.wei@gmail.com> --- acinclude.m4 | 7 ++ datapath/linux/Modules.mk | 2 + .../include/net/netfilter/nf_conntrack_timeout.h | 34 +++++++ datapath/linux/compat/nf_conntrack_timeout.c | 102 +++++++++++++++++++++ 4 files changed, 145 insertions(+) create mode 100644 datapath/linux/compat/include/net/netfilter/nf_conntrack_timeout.h create mode 100644 datapath/linux/compat/nf_conntrack_timeout.c