netfilter-devel.vger.kernel.org archive mirror
 help / color / mirror / Atom feed
From: Pablo Neira Ayuso <pablo@netfilter.org>
To: netfilter-devel@vger.kernel.org
Cc: davem@davemloft.net, netdev@vger.kernel.org
Subject: [PATCH 10/36] netfilter: nft_rbtree: allow adjacent intervals with dynamic updates
Date: Mon,  9 May 2016 20:46:28 +0200	[thread overview]
Message-ID: <1462819614-5402-11-git-send-email-pablo@netfilter.org> (raw)
In-Reply-To: <1462819614-5402-1-git-send-email-pablo@netfilter.org>

This patch fixes dynamic element updates for adjacent intervals in the
rb-tree representation.

Since elements are sorted in the rb-tree, in case of adjacent nodes with
the same key, the assumption is that an interval end node must be placed
before an interval opening.

In tree lookup operations, the idea is to search for the closer element
that is smaller than the one we're searching for. Given that we'll have
two possible matchings, we have to take the opening interval in case of
adjacent nodes.

Range merges are not trivial with the current representation,
specifically we have to check if node extensions are equal and make sure
we keep the existing internal states around.

Signed-off-by: Pablo Neira Ayuso <pablo@netfilter.org>
---
 net/netfilter/nft_rbtree.c | 40 +++++++++++++++++++++++++++++++++++-----
 1 file changed, 35 insertions(+), 5 deletions(-)

diff --git a/net/netfilter/nft_rbtree.c b/net/netfilter/nft_rbtree.c
index 29f2ab8..f762094 100644
--- a/net/netfilter/nft_rbtree.c
+++ b/net/netfilter/nft_rbtree.c
@@ -35,6 +35,12 @@ static bool nft_rbtree_interval_end(const struct nft_rbtree_elem *rbe)
 	       (*nft_set_ext_flags(&rbe->ext) & NFT_SET_ELEM_INTERVAL_END);
 }
 
+static bool nft_rbtree_equal(const struct nft_set *set, const void *this,
+			     const struct nft_rbtree_elem *interval)
+{
+	return memcmp(this, nft_set_ext_key(&interval->ext), set->klen) == 0;
+}
+
 static bool nft_rbtree_lookup(const struct nft_set *set, const u32 *key,
 			      const struct nft_set_ext **ext)
 {
@@ -42,6 +48,7 @@ static bool nft_rbtree_lookup(const struct nft_set *set, const u32 *key,
 	const struct nft_rbtree_elem *rbe, *interval = NULL;
 	const struct rb_node *parent;
 	u8 genmask = nft_genmask_cur(read_pnet(&set->pnet));
+	const void *this;
 	int d;
 
 	spin_lock_bh(&nft_rbtree_lock);
@@ -49,9 +56,16 @@ static bool nft_rbtree_lookup(const struct nft_set *set, const u32 *key,
 	while (parent != NULL) {
 		rbe = rb_entry(parent, struct nft_rbtree_elem, node);
 
-		d = memcmp(nft_set_ext_key(&rbe->ext), key, set->klen);
+		this = nft_set_ext_key(&rbe->ext);
+		d = memcmp(this, key, set->klen);
 		if (d < 0) {
 			parent = parent->rb_left;
+			/* In case of adjacent ranges, we always see the high
+			 * part of the range in first place, before the low one.
+			 * So don't update interval if the keys are equal.
+			 */
+			if (interval && nft_rbtree_equal(set, this, interval))
+				continue;
 			interval = rbe;
 		} else if (d > 0)
 			parent = parent->rb_right;
@@ -101,9 +115,16 @@ static int __nft_rbtree_insert(const struct nft_set *set,
 		else if (d > 0)
 			p = &parent->rb_right;
 		else {
-			if (nft_set_elem_active(&rbe->ext, genmask))
-				return -EEXIST;
-			p = &parent->rb_left;
+			if (nft_set_elem_active(&rbe->ext, genmask)) {
+				if (nft_rbtree_interval_end(rbe) &&
+				    !nft_rbtree_interval_end(new))
+					p = &parent->rb_left;
+				else if (!nft_rbtree_interval_end(rbe) &&
+					 nft_rbtree_interval_end(new))
+					p = &parent->rb_right;
+				else
+					return -EEXIST;
+			}
 		}
 	}
 	rb_link_node(&new->node, parent, p);
@@ -148,7 +169,7 @@ static void *nft_rbtree_deactivate(const struct nft_set *set,
 {
 	const struct nft_rbtree *priv = nft_set_priv(set);
 	const struct rb_node *parent = priv->root.rb_node;
-	struct nft_rbtree_elem *rbe;
+	struct nft_rbtree_elem *rbe, *this = elem->priv;
 	u8 genmask = nft_genmask_cur(read_pnet(&set->pnet));
 	int d;
 
@@ -166,6 +187,15 @@ static void *nft_rbtree_deactivate(const struct nft_set *set,
 				parent = parent->rb_left;
 				continue;
 			}
+			if (nft_rbtree_interval_end(rbe) &&
+			    !nft_rbtree_interval_end(this)) {
+				parent = parent->rb_left;
+				continue;
+			} else if (!nft_rbtree_interval_end(rbe) &&
+				   nft_rbtree_interval_end(this)) {
+				parent = parent->rb_right;
+				continue;
+			}
 			nft_set_elem_change_active(set, &rbe->ext);
 			return rbe;
 		}
-- 
2.1.4

  parent reply	other threads:[~2016-05-09 18:46 UTC|newest]

Thread overview: 38+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2016-05-09 18:46 [PATCH 00/36] Netfilter updates for net-next Pablo Neira Ayuso
2016-05-09 18:46 ` [PATCH 01/36] ipvs: handle connections started by real-servers Pablo Neira Ayuso
2016-05-09 18:46 ` [PATCH 02/36] ipvs: optimize release of connections in OPS mode Pablo Neira Ayuso
2016-05-09 18:46 ` [PATCH 03/36] ipvs: don't alter conntrack " Pablo Neira Ayuso
2016-05-09 18:46 ` [PATCH 04/36] netfilter: conntrack: move generation seqcnt out of netns_ct Pablo Neira Ayuso
2016-05-09 18:46 ` [PATCH 05/36] netfilter: conntrack: use get_random_once for nat and expectations Pablo Neira Ayuso
2016-05-09 18:46 ` [PATCH 06/36] netfilter: conntrack: use get_random_once for conntrack hash seed Pablo Neira Ayuso
2016-05-09 18:46 ` [PATCH 07/36] netfilter: nf_tables: introduce nft_setelem_parse_flags() helper Pablo Neira Ayuso
2016-05-09 18:46 ` [PATCH 08/36] netfilter: nf_tables: parse element flags from nft_del_setelem() Pablo Neira Ayuso
2016-05-09 18:46 ` [PATCH 09/36] netfilter: nft_rbtree: introduce nft_rbtree_interval_end() helper Pablo Neira Ayuso
2016-05-09 18:46 ` Pablo Neira Ayuso [this message]
2016-05-09 18:46 ` [PATCH 11/36] netfilter: nf_ct_helper: disable automatic helper assignment Pablo Neira Ayuso
2016-05-09 18:46 ` [PATCH 12/36] netfilter: ip6t_SYNPROXY: unnecessary to check whether ip6_route_output returns NULL Pablo Neira Ayuso
2016-05-09 18:46 ` [PATCH 13/36] netfilter: fix IS_ERR_VALUE usage Pablo Neira Ayuso
2016-05-09 18:46 ` [PATCH 14/36] netfilter: nftables: add connlabel set support Pablo Neira Ayuso
2016-05-09 18:46 ` [PATCH 15/36] netfilter: conntrack: keep BH enabled during lookup Pablo Neira Ayuso
2016-05-09 18:46 ` [PATCH 16/36] netfilter: conntrack: fix lookup race during hash resize Pablo Neira Ayuso
2016-05-09 18:46 ` [PATCH 17/36] netfilter: conntrack: don't attempt to iterate over empty table Pablo Neira Ayuso
2016-05-09 18:46 ` [PATCH 18/36] netfilter: conntrack: use nf_ct_key_equal() in more places Pablo Neira Ayuso
2016-05-09 18:46 ` [PATCH 19/36] netfilter: conntrack: small refactoring of conntrack seq_printf Pablo Neira Ayuso
2016-05-09 18:46 ` [PATCH 20/36] netfilter: conntrack: check netns when comparing conntrack objects Pablo Neira Ayuso
2016-05-09 18:46 ` [PATCH 21/36] netfilter: conntrack: make netns address part of hash Pablo Neira Ayuso
2016-05-09 18:46 ` [PATCH 22/36] netfilter: conntrack: use a single hashtable for all namespaces Pablo Neira Ayuso
2016-05-09 18:46 ` [PATCH 23/36] netfilter: conntrack: consider ct netns in early_drop logic Pablo Neira Ayuso
2016-05-09 18:46 ` [PATCH 24/36] netfilter: conntrack: __nf_ct_l4proto_find() always returns valid pointer Pablo Neira Ayuso
2016-05-09 18:46 ` [PATCH 25/36] netfilter: conntrack: introduce nf_ct_acct_update() Pablo Neira Ayuso
2016-05-09 18:46 ` [PATCH 26/36] netfilter: conntrack: introduce clash resolution on insertion race Pablo Neira Ayuso
2016-05-09 18:46 ` [PATCH 27/36] openvswitch: __nf_ct_l{3,4}proto_find() always return a valid pointer Pablo Neira Ayuso
2016-05-09 18:46 ` [PATCH 28/36] netfilter: x_tables: get rid of old and inconsistent debugging Pablo Neira Ayuso
2016-05-09 18:46 ` [PATCH 29/36] netfilter: nf_tables: allow set names up to 32 bytes Pablo Neira Ayuso
2016-05-09 18:46 ` [PATCH 30/36] ipvs: make drop_entry protection effective for SIP-pe Pablo Neira Ayuso
2016-05-09 18:46 ` [PATCH 31/36] netfilter: conntrack: check netns when walking expect hash Pablo Neira Ayuso
2016-05-09 18:46 ` [PATCH 32/36] netfilter: conntrack: make netns address part of " Pablo Neira Ayuso
2016-05-09 18:46 ` [PATCH 33/36] netfilter: conntrack: use a single expectation table for all namespaces Pablo Neira Ayuso
2016-05-09 18:46 ` [PATCH 34/36] netfilter: conntrack: make netns address part of nat bysrc hash Pablo Neira Ayuso
2016-05-09 18:46 ` [PATCH 35/36] netfilter: conntrack: use a single nat bysource table for all namespaces Pablo Neira Ayuso
2016-05-09 18:46 ` [PATCH 36/36] netfilter: conntrack: use single slab cache Pablo Neira Ayuso
2016-05-09 19:15 ` [PATCH 00/36] Netfilter updates for net-next David Miller

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=1462819614-5402-11-git-send-email-pablo@netfilter.org \
    --to=pablo@netfilter.org \
    --cc=davem@davemloft.net \
    --cc=netdev@vger.kernel.org \
    --cc=netfilter-devel@vger.kernel.org \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).