summaryrefslogtreecommitdiffstats
path: root/net/netfilter/nf_tables_core.c
diff options
context:
space:
mode:
authorPatrick McHardy2013-10-10 23:35:40 +0200
committerPablo Neira Ayuso2013-10-14 17:16:09 +0200
commitcb7dbfd0390c9e244339f3270fe8649568241812 (patch)
tree3e4587f757c08b59e936d4f45d0d2e7c25b3f93e /net/netfilter/nf_tables_core.c
parentnetfilter: nf_tables: expression ops overloading (diff)
downloadkernel-qcow2-linux-cb7dbfd0390c9e244339f3270fe8649568241812.tar.gz
kernel-qcow2-linux-cb7dbfd0390c9e244339f3270fe8649568241812.tar.xz
kernel-qcow2-linux-cb7dbfd0390c9e244339f3270fe8649568241812.zip
netfilter: nf_tables: add optimized data comparison for small values
Add an optimized version of nft_data_cmp() that only handles values of to 4 bytes length. This patch includes original Patrick McHardy's patch entitled (nf_tables: inline nft_cmp_fast_eval() into main evaluation loop). Signed-off-by: Patrick McHardy <kaber@trash.net> Signed-off-by: Pablo Neira Ayuso <pablo@netfilter.org>
Diffstat (limited to 'net/netfilter/nf_tables_core.c')
-rw-r--r--net/netfilter/nf_tables_core.c18
1 files changed, 17 insertions, 1 deletions
diff --git a/net/netfilter/nf_tables_core.c b/net/netfilter/nf_tables_core.c
index fd0ecd3255c1..24000182c8e7 100644
--- a/net/netfilter/nf_tables_core.c
+++ b/net/netfilter/nf_tables_core.c
@@ -20,6 +20,18 @@
#include <net/netfilter/nf_tables_core.h>
#include <net/netfilter/nf_tables.h>
+static void nft_cmp_fast_eval(const struct nft_expr *expr,
+ struct nft_data data[NFT_REG_MAX + 1])
+{
+ const struct nft_cmp_fast_expr *priv = nft_expr_priv(expr);
+ u32 mask;
+
+ mask = ~0U >> (sizeof(priv->data) * BITS_PER_BYTE - priv->len);
+ if ((data[priv->sreg].data[0] & mask) == priv->data)
+ return;
+ data[NFT_REG_VERDICT].verdict = NFT_BREAK;
+}
+
unsigned int nft_do_chain(const struct nf_hook_ops *ops,
struct sk_buff *skb,
const struct net_device *in,
@@ -48,7 +60,11 @@ next_rule:
data[NFT_REG_VERDICT].verdict = NFT_CONTINUE;
list_for_each_entry_continue_rcu(rule, &chain->rules, list) {
nft_rule_for_each_expr(expr, last, rule) {
- expr->ops->eval(expr, data, &pkt);
+ if (expr->ops == &nft_cmp_fast_ops)
+ nft_cmp_fast_eval(expr, data);
+ else
+ expr->ops->eval(expr, data, &pkt);
+
if (data[NFT_REG_VERDICT].verdict != NFT_CONTINUE)
break;
}