[PATCH 1/3] netfilter: nf_tables: fix suboptimal set selection

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

 



The rb-tree is currently used for simple sets and maps with no
intervals which is suboptimal. Fix it by adding the weight field
to each existing set implementation, this value allows to select
the best candidate in case that several set types can be used.

Signed-off-by: Pablo Neira Ayuso <pablo@xxxxxxxxxxxxx>
---
 include/net/netfilter/nf_tables.h |   13 +++++++++++++
 net/netfilter/nf_tables_api.c     |   10 +++++-----
 net/netfilter/nft_hash.c          |    1 +
 net/netfilter/nft_rbtree.c        |    1 +
 4 files changed, 20 insertions(+), 5 deletions(-)

diff --git a/include/net/netfilter/nf_tables.h b/include/net/netfilter/nf_tables.h
index 5a91abf..82920e8 100644
--- a/include/net/netfilter/nf_tables.h
+++ b/include/net/netfilter/nf_tables.h
@@ -143,6 +143,17 @@ struct nft_set_iter {
 };
 
 /**
+ *	enum nft_set_prio - nf_tables set priority
+ *
+ *	This is used to set preference in case that all set types provide the
+ *	same features.
+ */
+enum nft_set_prio {
+	NFT_SET_PRIO_HASH	= 0,
+	NFT_SET_PRIO_RBTREE,
+};
+
+/**
  *	struct nft_set_ops - nf_tables set operations
  *
  *	@lookup: look up an element within the set
@@ -155,6 +166,7 @@ struct nft_set_iter {
  *	@list: nf_tables_set_ops list node
  *	@owner: module reference
  *	@features: features supported by the implementation
+ *	@priority: priority of this set type
  */
 struct nft_set_ops {
 	bool				(*lookup)(const struct nft_set *set,
@@ -178,6 +190,7 @@ struct nft_set_ops {
 	struct list_head		list;
 	struct module			*owner;
 	u32				features;
+	u32				priority;
 };
 
 int nft_register_set(struct nft_set_ops *ops);
diff --git a/net/netfilter/nf_tables_api.c b/net/netfilter/nf_tables_api.c
index 0d4b42d..60efb61 100644
--- a/net/netfilter/nf_tables_api.c
+++ b/net/netfilter/nf_tables_api.c
@@ -1857,7 +1857,7 @@ EXPORT_SYMBOL_GPL(nft_unregister_set);
 
 static const struct nft_set_ops *nft_select_set_ops(const struct nlattr * const nla[])
 {
-	const struct nft_set_ops *ops;
+	const struct nft_set_ops *ops, *cand = NULL;
 	u32 features;
 
 #ifdef CONFIG_MODULES
@@ -1875,14 +1875,14 @@ static const struct nft_set_ops *nft_select_set_ops(const struct nlattr * const
 		features &= NFT_SET_INTERVAL | NFT_SET_MAP;
 	}
 
-	// FIXME: implement selection properly
 	list_for_each_entry(ops, &nf_tables_set_ops, list) {
 		if ((ops->features & features) != features)
 			continue;
-		if (!try_module_get(ops->owner))
-			continue;
-		return ops;
+		if (!cand || cand->priority > ops->priority)
+			cand = ops;
 	}
+	if (cand && try_module_get(cand->owner))
+		return 0;
 
 	return ERR_PTR(-EOPNOTSUPP);
 }
diff --git a/net/netfilter/nft_hash.c b/net/netfilter/nft_hash.c
index 3d3f8fc..f640c1c 100644
--- a/net/netfilter/nft_hash.c
+++ b/net/netfilter/nft_hash.c
@@ -210,6 +210,7 @@ static struct nft_set_ops nft_hash_ops __read_mostly = {
 	.lookup		= nft_hash_lookup,
 	.walk		= nft_hash_walk,
 	.features	= NFT_SET_MAP,
+	.priority	= NFT_SET_PRIO_HASH,
 	.owner		= THIS_MODULE,
 };
 
diff --git a/net/netfilter/nft_rbtree.c b/net/netfilter/nft_rbtree.c
index ca0c1b2..acddc64 100644
--- a/net/netfilter/nft_rbtree.c
+++ b/net/netfilter/nft_rbtree.c
@@ -226,6 +226,7 @@ static struct nft_set_ops nft_rbtree_ops __read_mostly = {
 	.lookup		= nft_rbtree_lookup,
 	.walk		= nft_rbtree_walk,
 	.features	= NFT_SET_INTERVAL | NFT_SET_MAP,
+	.priority	= NFT_SET_PRIO_RBTREE,
 	.owner		= THIS_MODULE,
 };
 
-- 
1.7.10.4

--
To unsubscribe from this list: send the line "unsubscribe netfilter-devel" in
the body of a message to majordomo@xxxxxxxxxxxxxxx
More majordomo info at  http://vger.kernel.org/majordomo-info.html




[Index of Archives]     [Netfitler Users]     [LARTC]     [Bugtraq]     [Yosemite Forum]

  Powered by Linux