Message ID | 1564097054-72663-10-git-send-email-yihung.wei@gmail.com |
---|---|
State | Changes Requested |
Headers | show |
Series | Support zone-based conntrack timeout policy | expand |
On Thu, Jul 25, 2019 at 04:24:11PM -0700, Yi-Hung Wei wrote: > 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> > --- Looks good to me. Acked-by: William Tu <u9012063@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 > > diff --git a/acinclude.m4 b/acinclude.m4 > index 9e1569b07c73..396b5f412094 100644 > --- a/acinclude.m4 > +++ b/acinclude.m4 > @@ -707,6 +707,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]) > diff --git a/datapath/linux/Modules.mk b/datapath/linux/Modules.mk > index cbb29f1c69d0..f93097b8e0e5 100644 > --- a/datapath/linux/Modules.mk > +++ b/datapath/linux/Modules.mk > @@ -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 \ > diff --git a/datapath/linux/compat/include/net/netfilter/nf_conntrack_timeout.h b/datapath/linux/compat/include/net/netfilter/nf_conntrack_timeout.h > new file mode 100644 > index 000000000000..134e72b8363e > --- /dev/null > +++ b/datapath/linux/compat/include/net/netfilter/nf_conntrack_timeout.h > @@ -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 */ > diff --git a/datapath/linux/compat/nf_conntrack_timeout.c b/datapath/linux/compat/nf_conntrack_timeout.c > new file mode 100644 > index 000000000000..c02baff5771b > --- /dev/null > +++ b/datapath/linux/compat/nf_conntrack_timeout.c > @@ -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 */ > -- > 2.7.4 > > _______________________________________________ > dev mailing list > dev@openvswitch.org > https://mail.openvswitch.org/mailman/listinfo/ovs-dev
diff --git a/acinclude.m4 b/acinclude.m4 index 9e1569b07c73..396b5f412094 100644 --- a/acinclude.m4 +++ b/acinclude.m4 @@ -707,6 +707,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]) diff --git a/datapath/linux/Modules.mk b/datapath/linux/Modules.mk index cbb29f1c69d0..f93097b8e0e5 100644 --- a/datapath/linux/Modules.mk +++ b/datapath/linux/Modules.mk @@ -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 \ diff --git a/datapath/linux/compat/include/net/netfilter/nf_conntrack_timeout.h b/datapath/linux/compat/include/net/netfilter/nf_conntrack_timeout.h new file mode 100644 index 000000000000..134e72b8363e --- /dev/null +++ b/datapath/linux/compat/include/net/netfilter/nf_conntrack_timeout.h @@ -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 */ diff --git a/datapath/linux/compat/nf_conntrack_timeout.c b/datapath/linux/compat/nf_conntrack_timeout.c new file mode 100644 index 000000000000..c02baff5771b --- /dev/null +++ b/datapath/linux/compat/nf_conntrack_timeout.c @@ -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