RFC - Netfilter - NF - Conntrack - Add Support For - Conntrack Zones - (LWN
RFC - Netfilter - NF - Conntrack - Add Support For - Conntrack Zones - (LWN
net]
Content ▶ Edition ▶
Something like this, with multiple tunl and veth devices, each pair
using a unique zone:
I'm not too fond of this partial feature duplication myself, but I
couldn't think of a better way to do this without the downsides of
using namespaces. Having partially shared network namespaces would
be great, but it doesn't seem to fit in the design very well.
https://lwn.net/Articles/370152/ 1/20
10/30/2017 RFC: netfilter: nf_conntrack: add support for "conntrack zones" [LWN.net]
I'm open for any better suggestion :)
- the overhead should be quite small, its mainly the extra argument
passing and an occasional extra comparison. Code size increase with
all netfilter options enabled on x86_64 is 152 bytes.
https://lwn.net/Articles/370152/ 2/20
10/30/2017 RFC: netfilter: nf_conntrack: add support for "conntrack zones" [LWN.net]
};
struct ip6_create_arg {
diff --git a/include/net/netfilter/nf_conntrack.h b/include/net/netfilter/nf_conntrack.h
index a0904ad..9488ac6 100644
--- a/include/net/netfilter/nf_conntrack.h
+++ b/include/net/netfilter/nf_conntrack.h
@@ -198,7 +198,8 @@ extern void *nf_ct_alloc_hashtable(unsigned int *sizep, int *vmalloced, int null
extern void nf_ct_free_hashtable(void *hash, int vmalloced, unsigned int size);
struct nf_conntrack_expect *
-__nf_ct_expect_find(struct net *net, const struct nf_conntrack_tuple *tuple);
+__nf_ct_expect_find(struct net *net, u16 zone,
+ const struct nf_conntrack_tuple *tuple);
struct nf_conntrack_expect *
-nf_ct_expect_find_get(struct net *net, const struct nf_conntrack_tuple *tuple);
+nf_ct_expect_find_get(struct net *net, u16 zone,
+ const struct nf_conntrack_tuple *tuple);
struct nf_conntrack_expect *
-nf_ct_find_expectation(struct net *net, const struct nf_conntrack_tuple *tuple);
+nf_ct_find_expectation(struct net *net, u16 zone,
+ const struct nf_conntrack_tuple *tuple);
https://lwn.net/Articles/370152/ 3/20
10/30/2017 RFC: netfilter: nf_conntrack: add support for "conntrack zones" [LWN.net]
--- a/include/net/netfilter/nf_conntrack_extend.h
+++ b/include/net/netfilter/nf_conntrack_extend.h
@@ -8,6 +8,7 @@ enum nf_ct_ext_id {
NF_CT_EXT_NAT,
NF_CT_EXT_ACCT,
NF_CT_EXT_ECACHE,
+ NF_CT_EXT_ZONE,
NF_CT_EXT_NUM,
};
- int (*error)(struct net *net, struct sk_buff *skb, unsigned int dataoff,
- enum ip_conntrack_info *ctinfo,
+ int (*error)(struct net *net, u16 zone, struct sk_buff *skb,
+ unsigned int dataoff, enum ip_conntrack_info *ctinfo,
u_int8_t pf, unsigned int hooknum);
/* Print out the per-protocol part of the tuple. Return like seq_* */
diff --git a/include/net/netfilter/nf_conntrack_zones.h b/include/net/netfilter/nf_conntrack_zones.h
new file mode 100644
index 0000000..77d430b
--- /dev/null
+++ b/include/net/netfilter/nf_conntrack_zones.h
@@ -0,0 +1,30 @@
+#ifndef _NF_CONNTRACK_ZONES_H
+#define _NF_CONNTRACK_ZONES_H
+
+#include <net/netfilter/nf_conntrack_extend.h>
+
+struct nf_conntrack_zone {
+ u16 id;
+};
+
+static inline u16 nf_ct_zone(const struct nf_conn *ct)
+{
+#ifdef CONFIG_NF_CONNTRACK_ZONES
+ struct nf_conntrack_zone *nf_ct_zone;
+ nf_ct_zone = nf_ct_ext_find(ct, NF_CT_EXT_ZONE);
+ if (nf_ct_zone)
+ return nf_ct_zone->id;
+#endif
+ return 0;
+}
+
+static inline u16 nf_ct_dev_zone(const struct net_device *dev)
+{
+#ifdef CONFIG_NF_CONNTRACK_ZONES
+ return dev->nf_ct_zone;
+#else
+ return 0;
+#endif
+}
+
+#endif /* _NF_CONNTRACK_ZONES_H */
diff --git a/net/core/net-sysfs.c b/net/core/net-sysfs.c
index fbc1c74..83d8bf2 100644
--- a/net/core/net-sysfs.c
+++ b/net/core/net-sysfs.c
@@ -289,6 +289,23 @@ static ssize_t show_ifalias(struct device *dev,
return ret;
https://lwn.net/Articles/370152/ 4/20
10/30/2017 RFC: netfilter: nf_conntrack: add support for "conntrack zones" [LWN.net]
}
+#ifdef CONFIG_NF_CONNTRACK_ZONES
+NETDEVICE_SHOW(nf_ct_zone, fmt_dec);
+
+static int change_nf_ct_zone(struct net_device *net, unsigned long zone)
+{
+ net->nf_ct_zone = zone;
+ return 0;
+}
+
+static ssize_t store_nf_ct_zone(struct device *dev,
+ struct device_attribute *attr,
+ const char *buf, size_t len)
+{
+ return netdev_store(dev, attr, buf, len, change_nf_ct_zone);
+}
+#endif
+
static struct device_attribute net_class_attributes[] = {
__ATTR(addr_len, S_IRUGO, show_addr_len, NULL),
__ATTR(dev_id, S_IRUGO, show_dev_id, NULL),
@@ -309,6 +326,9 @@ static struct device_attribute net_class_attributes[] = {
__ATTR(flags, S_IRUGO | S_IWUSR, show_flags, store_flags),
__ATTR(tx_queue_len, S_IRUGO | S_IWUSR, show_tx_queue_len,
store_tx_queue_len),
+#ifdef CONFIG_NF_CONNTRACK_ZONES
+ __ATTR(nf_ct_zone, S_IRUGO | S_IWUSR, show_nf_ct_zone, store_nf_ct_zone),
+#endif
{}
};
- h = nf_conntrack_find_get(sock_net(sk), &tuple);
+ h = nf_conntrack_find_get(sock_net(sk), 0, &tuple);
if (h) {
struct sockaddr_in sin;
struct nf_conn *ct = nf_ct_tuplehash_to_ctrack(h);
diff --git a/net/ipv4/netfilter/nf_conntrack_proto_icmp.c b/net/ipv4/netfilter/nf_conntrack_proto_icmp.c
index 7afd39b..82b4b30 100644
--- a/net/ipv4/netfilter/nf_conntrack_proto_icmp.c
+++ b/net/ipv4/netfilter/nf_conntrack_proto_icmp.c
https://lwn.net/Articles/370152/ 5/20
10/30/2017 RFC: netfilter: nf_conntrack: add support for "conntrack zones" [LWN.net]
@@ -114,7 +114,7 @@ static bool icmp_new(struct nf_conn *ct, const struct sk_buff *skb,
*ctinfo = IP_CT_RELATED;
- h = nf_conntrack_find_get(net, &innertuple);
+ h = nf_conntrack_find_get(net, zone, &innertuple);
if (!h) {
pr_debug("icmp_error_message: no match\n");
return -NF_ACCEPT;
@@ -163,7 +163,8 @@ icmp_error_message(struct net *net, struct sk_buff *skb,
#include <linux/netfilter_bridge.h>
#include <linux/netfilter_ipv4.h>
+#include <net/netfilter/nf_conntrack_zones.h>
#include <net/netfilter/ipv4/nf_defrag_ipv4.h>
https://lwn.net/Articles/370152/ 6/20
10/30/2017 RFC: netfilter: nf_conntrack: add support for "conntrack zones" [LWN.net]
if (ip_hdr(skb)->frag_off & htons(IP_MF | IP_OFFSET)) {
- enum ip_defrag_users user = nf_ct_defrag_user(hooknum, skb);
+ u16 zone = nf_ct_dev_zone(hooknum == NF_INET_PRE_ROUTING ? in : out);
+ enum ip_defrag_users user = nf_ct_defrag_user(hooknum, zone, skb);
+
if (nf_ct_ipv4_gather_frags(skb, user))
return NF_STOLEN;
}
diff --git a/net/ipv4/netfilter/nf_nat_core.c b/net/ipv4/netfilter/nf_nat_core.c
index fe1a644..64b9979 100644
--- a/net/ipv4/netfilter/nf_nat_core.c
+++ b/net/ipv4/netfilter/nf_nat_core.c
@@ -30,6 +30,7 @@
#include <net/netfilter/nf_conntrack_helper.h>
#include <net/netfilter/nf_conntrack_l3proto.h>
#include <net/netfilter/nf_conntrack_l4proto.h>
+#include <net/netfilter/nf_conntrack_zones.h>
static DEFINE_SPINLOCK(nf_nat_lock);
https://lwn.net/Articles/370152/ 7/20
10/30/2017 RFC: netfilter: nf_conntrack: add support for "conntrack zones" [LWN.net]
j = ((u64)j * (maxip - minip + 1)) >> 32;
*var_ipp = htonl(minip + j);
}
@@ -232,6 +233,7 @@ get_unique_tuple(struct nf_conntrack_tuple *tuple,
{
struct net *net = nf_ct_net(ct);
const struct nf_nat_protocol *proto;
+ u16 zone = nf_ct_zone(ct);
- srchash = hash_by_src(&ct->tuplehash[IP_CT_DIR_ORIGINAL].tuple);
+ srchash = hash_by_src(&ct->tuplehash[IP_CT_DIR_ORIGINAL].tuple,
+ nf_ct_zone(ct));
spin_lock_bh(&nf_nat_lock);
/* nf_conntrack_alter_reply might re-allocate exntension aera */
nat = nfct_nat(ct);
diff --git a/net/ipv4/netfilter/nf_nat_pptp.c b/net/ipv4/netfilter/nf_nat_pptp.c
index 9eb1710..4c06003 100644
--- a/net/ipv4/netfilter/nf_nat_pptp.c
+++ b/net/ipv4/netfilter/nf_nat_pptp.c
@@ -25,6 +25,7 @@
#include <net/netfilter/nf_nat_rule.h>
#include <net/netfilter/nf_conntrack_helper.h>
#include <net/netfilter/nf_conntrack_expect.h>
+#include <net/netfilter/nf_conntrack_zones.h>
#include <linux/netfilter/nf_conntrack_proto_gre.h>
#include <linux/netfilter/nf_conntrack_pptp.h>
https://lwn.net/Articles/370152/ 8/20
10/30/2017 RFC: netfilter: nf_conntrack: add support for "conntrack zones" [LWN.net]
https://lwn.net/Articles/370152/ 9/20
10/30/2017 RFC: netfilter: nf_conntrack: add support for "conntrack zones" [LWN.net]
}
- return __ipv6_conntrack_in(dev_net(out), hooknum, skb, okfn);
+ return __ipv6_conntrack_in(dev_net(out), nf_ct_dev_zone(out), hooknum, skb, okfn);
}
static int
-icmpv6_error_message(struct net *net,
+icmpv6_error_message(struct net *net, u16 zone,
struct sk_buff *skb,
unsigned int icmp6off,
enum ip_conntrack_info *ctinfo,
@@ -163,7 +163,7 @@ icmpv6_error_message(struct net *net,
*ctinfo = IP_CT_RELATED;
- h = nf_conntrack_find_get(net, &intuple);
+ h = nf_conntrack_find_get(net, zone, &intuple);
if (!h) {
pr_debug("icmpv6_error: no match\n");
return -NF_ACCEPT;
@@ -179,7 +179,8 @@ icmpv6_error_message(struct net *net,
}
static int
-icmpv6_error(struct net *net, struct sk_buff *skb, unsigned int dataoff,
+icmpv6_error(struct net *net, u16 zone,
+ struct sk_buff *skb, unsigned int dataoff,
enum ip_conntrack_info *ctinfo, u_int8_t pf, unsigned int hooknum)
{
const struct icmp6hdr *icmp6h;
@@ -215,7 +216,7 @@ icmpv6_error(struct net *net, struct sk_buff *skb, unsigned int dataoff,
if (icmp6h->icmp6_type >= 128)
return NF_ACCEPT;
+config NF_CONNTRACK_ZONES
+ bool 'Connection tracking zones'
+ help
+ This option enables support for connection tracking zones.
+ Normally, each connection needs to have a unique identity.
+ Connection tracking zones allow to have multiple connections
+ using the same identity, as long as they are contained in
+ different zones.
+
configNF_CONNTRACK_EVENTS
bool "Connection tracking events"
depends on NETFILTER_ADVANCED
diff --git a/net/netfilter/nf_conntrack_core.c b/net/netfilter/nf_conntrack_core.c
index 0e98c32..90909e3 100644
--- a/net/netfilter/nf_conntrack_core.c
+++ b/net/netfilter/nf_conntrack_core.c
@@ -41,6 +41,7 @@
#include <net/netfilter/nf_conntrack_extend.h>
#include <net/netfilter/nf_conntrack_acct.h>
#include <net/netfilter/nf_conntrack_ecache.h>
https://lwn.net/Articles/370152/ 10/20
10/30/2017 RFC: netfilter: nf_conntrack: add support for "conntrack zones" [LWN.net]
+#include <net/netfilter/nf_conntrack_zones.h>
#include <net/netfilter/nf_nat.h>
#include <net/netfilter/nf_nat_core.h>
/* Disable BHs the entire time since we normally need to disable them
* at least once for the stats anyway.
@@ -304,7 +307,8 @@ __nf_conntrack_find(struct net *net, const struct nf_conntrack_tuple *tuple)
local_bh_disable();
begin:
hlist_nulls_for_each_entry_rcu(h, n, &net->ct.hash[hash], hnnode) {
- if (nf_ct_tuple_equal(tuple, &h->tuple)) {
+ if (nf_ct_tuple_equal(tuple, &h->tuple) &&
+ nf_ct_zone(nf_ct_tuplehash_to_ctrack(h)) == zone) {
NF_CT_STAT_INC(net, found);
local_bh_enable();
return h;
@@ -326,21 +330,23 @@ EXPORT_SYMBOL_GPL(__nf_conntrack_find);
rcu_read_lock();
begin:
- h = __nf_conntrack_find(net, tuple);
+ h = __nf_conntrack_find(net, zone, tuple);
if (h) {
ct = nf_ct_tuplehash_to_ctrack(h);
https://lwn.net/Articles/370152/ 11/20
10/30/2017 RFC: netfilter: nf_conntrack: add support for "conntrack zones" [LWN.net]
if (unlikely(nf_ct_is_dying(ct) ||
!atomic_inc_not_zero(&ct->ct_general.use)))
h = NULL;
else {
- if (unlikely(!nf_ct_tuple_equal(tuple, &h->tuple))) {
+ if (unlikely(!nf_ct_tuple_equal(tuple, &h->tuple) ||
+ nf_ct_zone(ct) != zone)) {
nf_ct_put(ct);
goto begin;
}
@@ -367,9 +373,11 @@ static void __nf_conntrack_hash_insert(struct nf_conn *ct,
void nf_conntrack_hash_insert(struct nf_conn *ct)
{
unsigned int hash, repl_hash;
+ u16 zone;
- hash = hash_conntrack(&ct->tuplehash[IP_CT_DIR_ORIGINAL].tuple);
- repl_hash = hash_conntrack(&ct->tuplehash[IP_CT_DIR_REPLY].tuple);
+ zone = nf_ct_zone(ct);
+ hash = hash_conntrack(&ct->tuplehash[IP_CT_DIR_ORIGINAL].tuple, zone);
+ repl_hash = hash_conntrack(&ct->tuplehash[IP_CT_DIR_REPLY].tuple, zone);
ct = nf_ct_get(skb, &ctinfo);
@@ -397,8 +406,9 @@ __nf_conntrack_confirm(struct sk_buff *skb)
if (CTINFO2DIR(ctinfo) != IP_CT_DIR_ORIGINAL)
return NF_ACCEPT;
- hash = hash_conntrack(&ct->tuplehash[IP_CT_DIR_ORIGINAL].tuple);
- repl_hash = hash_conntrack(&ct->tuplehash[IP_CT_DIR_REPLY].tuple);
+ zone = nf_ct_zone(ct);
+ hash = hash_conntrack(&ct->tuplehash[IP_CT_DIR_ORIGINAL].tuple, zone);
+ repl_hash = hash_conntrack(&ct->tuplehash[IP_CT_DIR_REPLY].tuple, zone);
https://lwn.net/Articles/370152/ 12/20
10/30/2017 RFC: netfilter: nf_conntrack: add support for "conntrack zones" [LWN.net]
- nf_ct_tuple_equal(tuple, &h->tuple)) {
+ ct = nf_ct_tuplehash_to_ctrack(h);
+ if (ct != ignored_conntrack &&
+ nf_ct_tuple_equal(tuple, &h->tuple) &&
+ nf_ct_zone(ct) == zone) {
NF_CT_STAT_INC(net, found);
rcu_read_unlock_bh();
return 1;
@@ -539,7 +555,7 @@ static noinline int early_drop(struct net *net, unsigned int hash)
return dropped;
}
if (nf_conntrack_max &&
unlikely(atomic_read(&net->ct.count) > nf_conntrack_max)) {
- unsigned int hash = hash_conntrack(orig);
+ unsigned int hash = hash_conntrack(orig, zone);
if (!early_drop(net, hash)) {
atomic_dec(&net->ct.count);
if (net_ratelimit())
@@ -578,6 +594,7 @@ struct nf_conn *nf_conntrack_alloc(struct net *net,
atomic_dec(&net->ct.count);
return ERR_PTR(-ENOMEM);
}
+
/*
* Let ct->tuplehash[IP_CT_DIR_ORIGINAL].hnnode.next
* and ct->tuplehash[IP_CT_DIR_REPLY].hnnode.next unchanged.
@@ -594,6 +611,16 @@ struct nf_conn *nf_conntrack_alloc(struct net *net,
#ifdef CONFIG_NET_NS
ct->ct_net = net;
#endif
+#ifdef CONFIG_NF_CONNTRACK_ZONES
+ if (zone) {
+ struct nf_conntrack_zone *nf_ct_zone;
+
+ nf_ct_zone = nf_ct_ext_add(ct, NF_CT_EXT_ZONE, GFP_ATOMIC);
+ if (!nf_ct_zone)
+ goto out_free;
+ nf_ct_zone->id = zone;
+ }
+#endif
/*
* changes to lookup keys must be done before setting refcnt to 1
@@ -601,6 +628,12 @@ struct nf_conn *nf_conntrack_alloc(struct net *net,
smp_wmb();
atomic_set(&ct->ct_general.use, 1);
return ct;
+
+#ifdef CONFIG_NF_CONNTRACK_ZONES
+out_free:
+ kmem_cache_free(nf_conntrack_cachep, ct);
+ return ERR_PTR(-ENOMEM);
+#endif
}
EXPORT_SYMBOL_GPL(nf_conntrack_alloc);
https://lwn.net/Articles/370152/ 13/20
10/30/2017 RFC: netfilter: nf_conntrack: add support for "conntrack zones" [LWN.net]
}
spin_lock_bh(&nf_conntrack_lock);
- exp = nf_ct_find_expectation(net, tuple);
+ exp = nf_ct_find_expectation(net, zone, tuple);
if (exp) {
pr_debug("conntrack: expectation arrives ct=%p exp=%p\n",
ct, exp);
@@ -694,7 +727,7 @@ init_conntrack(struct net *net,
unsigned int
-nf_conntrack_in(struct net *net, u_int8_t pf, unsigned int hooknum,
+nf_conntrack_in(struct net *net, u16 zone, u_int8_t pf, unsigned int hooknum,
struct sk_buff *skb)
{
struct nf_conn *ct;
@@ -787,7 +821,8 @@ nf_conntrack_in(struct net *net, u_int8_t pf, unsigned int hooknum,
* inverse of the return code tells to the netfilter
* core what to do with the packet. */
if (l4proto->error != NULL) {
- ret = l4proto->error(net, skb, dataoff, &ctinfo, pf, hooknum);
+ ret = l4proto->error(net, zone, skb, dataoff, &ctinfo,
+ pf, hooknum);
if (ret <= 0) {
NF_CT_STAT_INC_ATOMIC(net, error);
NF_CT_STAT_INC_ATOMIC(net, invalid);
@@ -795,7 +830,7 @@ nf_conntrack_in(struct net *net, u_int8_t pf, unsigned int hooknum,
}
}
https://lwn.net/Articles/370152/ 14/20
10/30/2017 RFC: netfilter: nf_conntrack: add support for "conntrack zones" [LWN.net]
+
#if defined(CONFIG_NF_CT_NETLINK) || defined(CONFIG_NF_CT_NETLINK_MODULE)
#include <linux/netfilter/nfnetlink.h>
@@ -1115,6 +1156,7 @@ static void nf_conntrack_cleanup_init_net(void)
{
nf_conntrack_helper_fini();
nf_conntrack_proto_fini();
+ nf_ct_extend_unregister(&nf_ct_zone_extend);
kmem_cache_destroy(nf_conntrack_cachep);
}
+#ifdef CONFIG_NF_CONNTRACK_ZONES
+ ret = nf_ct_extend_register(&nf_ct_zone_extend);
+ if (ret < 0)
+ goto err_extend;
+#endif
return 0;
+#ifdef CONFIG_NF_CONNTRACK_ZONES
+err_extend:
+ nf_conntrack_helper_fini();
+#endif
err_helper:
nf_conntrack_proto_fini();
err_proto:
diff --git a/net/netfilter/nf_conntrack_expect.c b/net/netfilter/nf_conntrack_expect.c
index fdf5d2a..5fd0347 100644
--- a/net/netfilter/nf_conntrack_expect.c
+++ b/net/netfilter/nf_conntrack_expect.c
@@ -27,6 +27,7 @@
#include <net/netfilter/nf_conntrack_expect.h>
#include <net/netfilter/nf_conntrack_helper.h>
#include <net/netfilter/nf_conntrack_tuple.h>
+#include <net/netfilter/nf_conntrack_zones.h>
struct nf_conntrack_expect *
-__nf_ct_expect_find(struct net *net, const struct nf_conntrack_tuple *tuple)
+__nf_ct_expect_find(struct net *net, u16 zone,
+ const struct nf_conntrack_tuple *tuple)
{
struct nf_conntrack_expect *i;
struct hlist_node *n;
@@ -104,12 +106,13 @@ EXPORT_SYMBOL_GPL(__nf_ct_expect_find);
https://lwn.net/Articles/370152/ 15/20
10/30/2017 RFC: netfilter: nf_conntrack: add support for "conntrack zones" [LWN.net]
struct nf_conntrack_expect *
-nf_ct_expect_find_get(struct net *net, const struct nf_conntrack_tuple *tuple)
+nf_ct_expect_find_get(struct net *net, u16 zone,
+ const struct nf_conntrack_tuple *tuple)
{
struct nf_conntrack_expect *i;
rcu_read_lock();
- i = __nf_ct_expect_find(net, tuple);
+ i = __nf_ct_expect_find(net, zone, tuple);
if (i && !atomic_inc_not_zero(&i->use))
i = NULL;
rcu_read_unlock();
@@ -121,7 +124,8 @@ EXPORT_SYMBOL_GPL(nf_ct_expect_find_get);
/* If an expectation for this connection is found, it gets delete from
* global list then returned. */
struct nf_conntrack_expect *
-nf_ct_find_expectation(struct net *net, const struct nf_conntrack_tuple *tuple)
+nf_ct_find_expectation(struct net *net, u16 zone,
+ const struct nf_conntrack_tuple *tuple)
{
struct nf_conntrack_expect *i, *exp = NULL;
struct hlist_node *n;
@@ -133,7 +137,8 @@ nf_ct_find_expectation(struct net *net, const struct nf_conntrack_tuple *tuple)
h = nf_ct_expect_dst_hash(tuple);
hlist_for_each_entry(i, n, &net->ct.expect_hash[h], hnode) {
if (!(i->flags & NF_CT_EXPECT_INACTIVE) &&
- nf_ct_tuple_mask_cmp(tuple, &i->tuple, &i->mask)) {
+ nf_ct_tuple_mask_cmp(tuple, &i->tuple, &i->mask) &&
+ nf_ct_zone(i->master) == zone) {
exp = i;
break;
}
@@ -204,7 +209,8 @@ static inline int expect_matches(const struct nf_conntrack_expect *a,
{
return a->master == b->master && a->class == b->class &&
nf_ct_tuple_equal(&a->tuple, &b->tuple) &&
- nf_ct_tuple_mask_equal(&a->mask, &b->mask);
+ nf_ct_tuple_mask_equal(&a->mask, &b->mask) &&
+ nf_ct_zone(a->master) == nf_ct_zone(b->master);
}
/* Parameters */
@@ -1216,7 +1217,7 @@ static struct nf_conntrack_expect *find_expect(struct nf_conn *ct,
tuple.dst.u.tcp.port = port;
tuple.dst.protonum = IPPROTO_TCP;
- h = nf_conntrack_find_get(&init_net, &tuple);
+ h = nf_conntrack_find_get(&init_net, 0, &tuple);
if (!h)
https://lwn.net/Articles/370152/ 16/20
10/30/2017 RFC: netfilter: nf_conntrack: add support for "conntrack zones" [LWN.net]
return -ENOENT;
- h = nf_conntrack_find_get(&init_net, &tuple);
+ h = nf_conntrack_find_get(&init_net, 0, &tuple);
if (!h)
return -ENOENT;
spin_lock_bh(&nf_conntrack_lock);
if (cda[CTA_TUPLE_ORIG])
- h = __nf_conntrack_find(&init_net, &otuple);
+ h = __nf_conntrack_find(&init_net, 0, &otuple);
else if (cda[CTA_TUPLE_REPLY])
- h = __nf_conntrack_find(&init_net, &rtuple);
+ h = __nf_conntrack_find(&init_net, 0, &rtuple);
if (h == NULL) {
err = -ENOENT;
@@ -1660,7 +1660,7 @@ ctnetlink_get_expect(struct sock *ctnl, struct sk_buff *skb,
if (err < 0)
return err;
spin_lock_bh(&nf_conntrack_lock);
- exp = __nf_ct_expect_find(&init_net, &tuple);
+ exp = __nf_ct_expect_find(&init_net, 0, &tuple);
https://lwn.net/Articles/370152/ 17/20
10/30/2017 RFC: netfilter: nf_conntrack: add support for "conntrack zones" [LWN.net]
if (!exp) {
spin_unlock_bh(&nf_conntrack_lock);
diff --git a/net/netfilter/nf_conntrack_pptp.c b/net/netfilter/nf_conntrack_pptp.c
index 3807ac7..ffe2ae6 100644
--- a/net/netfilter/nf_conntrack_pptp.c
+++ b/net/netfilter/nf_conntrack_pptp.c
@@ -28,6 +28,7 @@
#include <net/netfilter/nf_conntrack.h>
#include <net/netfilter/nf_conntrack_core.h>
#include <net/netfilter/nf_conntrack_helper.h>
+#include <net/netfilter/nf_conntrack_zones.h>
#include <linux/netfilter/nf_conntrack_proto_gre.h>
#include <linux/netfilter/nf_conntrack_pptp.h>
- h = nf_conntrack_find_get(net, t);
+ h = nf_conntrack_find_get(net, zone, t);
if (h) {
sibling = nf_ct_tuplehash_to_ctrack(h);
pr_debug("setting timeout of conntrack %p to 0\n", sibling);
@@ -157,7 +158,7 @@ static int destroy_sibling_or_exp(struct net *net,
nf_ct_put(sibling);
return 1;
} else {
- exp = nf_ct_expect_find_get(net, t);
+ exp = nf_ct_expect_find_get(net, zone, t);
if (exp) {
pr_debug("unexpect_related of expect %p\n", exp);
nf_ct_unexpect_related(exp);
@@ -182,7 +183,7 @@ static void pptp_destroy_siblings(struct nf_conn *ct)
t.dst.protonum = IPPROTO_GRE;
t.src.u.gre.key = help->help.ct_pptp_info.pns_call_id;
t.dst.u.gre.key = help->help.ct_pptp_info.pac_call_id;
- if (!destroy_sibling_or_exp(net, &t))
+ if (!destroy_sibling_or_exp(net, nf_ct_zone(ct), &t))
pr_debug("failed to timeout original pns->pac ct/exp\n");
https://lwn.net/Articles/370152/ 18/20
10/30/2017 RFC: netfilter: nf_conntrack: add support for "conntrack zones" [LWN.net]
-static int udp_error(struct net *net, struct sk_buff *skb, unsigned int dataoff,
- enum ip_conntrack_info *ctinfo,
+static int udp_error(struct net *net, u16 zone, struct sk_buff *skb,
+ unsigned int dataoff, enum ip_conntrack_info *ctinfo,
u_int8_t pf,
unsigned int hooknum)
{
diff --git a/net/netfilter/nf_conntrack_proto_udplite.c b/net/netfilter/nf_conntrack_proto_udplite.c
index 458655b..cc94a67 100644
--- a/net/netfilter/nf_conntrack_proto_udplite.c
+++ b/net/netfilter/nf_conntrack_proto_udplite.c
@@ -89,7 +89,7 @@ static bool udplite_new(struct nf_conn *ct, const struct sk_buff *skb,
return true;
}
MODULE_LICENSE("GPL");
@@ -777,7 +778,7 @@ static int set_expected_rtp_rtcp(struct sk_buff *skb,
rcu_read_lock();
do {
- exp = __nf_ct_expect_find(net, &tuple);
+ exp = __nf_ct_expect_find(net, nf_ct_zone(ct), &tuple);
if (!exp || exp->master == ct ||
nfct_help(exp->master)->helper != nfct_help(ct)->helper ||
diff --git a/net/netfilter/nf_conntrack_standalone.c b/net/netfilter/nf_conntrack_standalone.c
index 028aba6..69da6ef 100644
--- a/net/netfilter/nf_conntrack_standalone.c
+++ b/net/netfilter/nf_conntrack_standalone.c
@@ -26,6 +26,7 @@
#include <net/netfilter/nf_conntrack_expect.h>
#include <net/netfilter/nf_conntrack_helper.h>
https://lwn.net/Articles/370152/ 19/20
10/30/2017 RFC: netfilter: nf_conntrack: add support for "conntrack zones" [LWN.net]
#include <net/netfilter/nf_conntrack_acct.h>
+#include <net/netfilter/nf_conntrack_zones.h>
MODULE_LICENSE("GPL");
+#ifdef CONFIG_NF_CONNTRACK_ZONES
+ if (seq_printf(s, "zone=%u ", nf_ct_zone(ct)));
+ goto release;
+#endif
+
if (seq_printf(s, "use=%u\n", atomic_read(&ct->ct_general.use)))
goto release;
if (found != NULL)
https://lwn.net/Articles/370152/ 20/20