mirror of
https://github.com/openvswitch/ovs
synced 2025-09-01 06:45:17 +00:00
compat: Backport nf_ct_netns_{get, put}()
This patch backports nf_ct_netns_get/put() in order to support a feature in the follow up patch. nf_ct_netns_{get,put} were first introduced in upstream net-next commit ecb2421b5ddf ("netfilter: add and use nf_ct_netns_get/put") in kernel v4.10, and then updated in commmit 7e35ec0e8044 ("netfilter: conntrack: move nf_ct_netns_{get,put}() to core") in kernel v4.15. We need to invoke nf_ct_netns_get/put() when the underlying nf_conntrack_l3proto supports net_ns_{get,put}(). Therefore, there are 3 cases that we need to consider. 1) Before nf_ct_{get,put}() is introduced. We just mock nf_ct_nets_{get,put}() and do nothing. 2) After 1) and before v4.15 Backports based on commit 7e35ec0e8044 . 3) Staring from v4.15 Use the upstream version. Signed-off-by: Yi-Hung Wei <yihung.wei@gmail.com> Signed-off-by: Justin Pettit <jpettit@ovn.org>
This commit is contained in:
committed by
Justin Pettit
parent
7f63d8302e
commit
179fccce34
@@ -589,6 +589,8 @@ AC_DEFUN([OVS_CHECK_LINUX_COMPAT], [
|
||||
[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])])
|
||||
@@ -611,6 +613,8 @@ AC_DEFUN([OVS_CHECK_LINUX_COMPAT], [
|
||||
[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],
|
||||
|
@@ -18,6 +18,7 @@ openvswitch_sources += \
|
||||
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 \
|
||||
@@ -107,5 +108,6 @@ openvswitch_headers += \
|
||||
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
|
||||
|
@@ -22,4 +22,12 @@ nf_ct_set(struct sk_buff *skb, struct nf_conn *ct, enum ip_conntrack_info info)
|
||||
skb->nfctinfo = info;
|
||||
}
|
||||
#endif
|
||||
|
||||
#if LINUX_VERSION_CODE < KERNEL_VERSION(4,15,0)
|
||||
int rpl_nf_ct_netns_get(struct net *net, u8 nfproto);
|
||||
void rpl_nf_ct_netns_put(struct net *net, u8 nfproto);
|
||||
#define nf_ct_netns_get rpl_nf_ct_netns_get
|
||||
#define nf_ct_netns_put rpl_nf_ct_netns_put
|
||||
#endif
|
||||
|
||||
#endif /* _NF_CONNTRACK_WRAPPER_H */
|
||||
|
14
datapath/linux/compat/include/uapi/linux/netfilter.h
Normal file
14
datapath/linux/compat/include/uapi/linux/netfilter.h
Normal file
@@ -0,0 +1,14 @@
|
||||
#ifndef _NETFILTER_WRAPPER_H
|
||||
#define _NETFILTER_WRAPPER_H
|
||||
|
||||
#include_next <uapi/linux/netfilter.h>
|
||||
|
||||
/*
|
||||
* NFPROTO_INET was introduced in net-next commit 1d49144c0aaa
|
||||
* ("netfilter: nf_tables: add "inet" table for IPv4/IPv6") in v3.14.
|
||||
* Define this symbol to support back to v3.10 kernel. */
|
||||
#ifndef HAVE_NFPROTO_INET
|
||||
#define NFPROTO_INET 1
|
||||
#endif
|
||||
|
||||
#endif /* _NETFILTER_WRAPPER_H */
|
112
datapath/linux/compat/nf_conntrack_proto.c
Normal file
112
datapath/linux/compat/nf_conntrack_proto.c
Normal file
@@ -0,0 +1,112 @@
|
||||
#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) */
|
Reference in New Issue
Block a user