diff options
author | Patrick McHardy <kaber@trash.net> | 2013-10-10 09:06:41 (GMT) |
---|---|---|
committer | Pablo Neira Ayuso <pablo@netfilter.org> | 2013-10-14 15:16:10 (GMT) |
commit | c29b72e02573b8fe5e6cae5d192a6a4772e7bbd6 (patch) | |
tree | cd4d3e4f18568111c0cf754a2ffe28efefd8ca41 /net/netfilter/nf_tables_core.c | |
parent | cb7dbfd0390c9e244339f3270fe8649568241812 (diff) | |
download | linux-c29b72e02573b8fe5e6cae5d192a6a4772e7bbd6.tar.xz |
netfilter: nft_payload: add optimized payload implementation for small loads
Add an optimized payload expression implementation for small (up to 4 bytes)
aligned data loads from the linear packet area.
This patch also includes original Patrick McHardy's entitled (nf_tables:
inline nft_payload_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.c | 31 |
1 files changed, 30 insertions, 1 deletions
diff --git a/net/netfilter/nf_tables_core.c b/net/netfilter/nf_tables_core.c index 2400018..9aede59 100644 --- a/net/netfilter/nf_tables_core.c +++ b/net/netfilter/nf_tables_core.c @@ -32,6 +32,34 @@ static void nft_cmp_fast_eval(const struct nft_expr *expr, data[NFT_REG_VERDICT].verdict = NFT_BREAK; } +static bool nft_payload_fast_eval(const struct nft_expr *expr, + struct nft_data data[NFT_REG_MAX + 1], + const struct nft_pktinfo *pkt) +{ + const struct nft_payload *priv = nft_expr_priv(expr); + const struct sk_buff *skb = pkt->skb; + struct nft_data *dest = &data[priv->dreg]; + unsigned char *ptr; + + if (priv->base == NFT_PAYLOAD_NETWORK_HEADER) + ptr = skb_network_header(skb); + else + ptr = skb_transport_header(skb); + + ptr += priv->offset; + + if (unlikely(ptr + priv->len >= skb_tail_pointer(skb))) + return false; + + if (priv->len == 2) + *(u16 *)dest->data = *(u16 *)ptr; + else if (priv->len == 4) + *(u32 *)dest->data = *(u32 *)ptr; + else + *(u8 *)dest->data = *(u8 *)ptr; + return true; +} + unsigned int nft_do_chain(const struct nf_hook_ops *ops, struct sk_buff *skb, const struct net_device *in, @@ -62,7 +90,8 @@ next_rule: nft_rule_for_each_expr(expr, last, rule) { if (expr->ops == &nft_cmp_fast_ops) nft_cmp_fast_eval(expr, data); - else + else if (expr->ops != &nft_payload_fast_ops || + !nft_payload_fast_eval(expr, data, &pkt)) expr->ops->eval(expr, data, &pkt); if (data[NFT_REG_VERDICT].verdict != NFT_CONTINUE) |