Skip to content

Commit

Permalink
netfilter: nft_hash: Add hash offset value
Browse files Browse the repository at this point in the history
Add support to pass through an offset to the hash value. With this
feature, the sysadmin is able to generate a hash with a given
offset value.

Example:

	meta mark set jhash ip saddr mod 2 seed 0xabcd offset 100

This option generates marks according to the source address from 100 to
101.

Signed-off-by: Laura Garcia Liebana <nevola@gmail.com>
  • Loading branch information
Laura Garcia Liebana authored and Pablo Neira Ayuso committed Sep 12, 2016
1 parent 3c15b8e commit 70ca767
Show file tree
Hide file tree
Showing 2 changed files with 15 additions and 4 deletions.
2 changes: 2 additions & 0 deletions include/uapi/linux/netfilter/nf_tables.h
Original file line number Diff line number Diff line change
Expand Up @@ -731,6 +731,7 @@ enum nft_meta_keys {
* @NFTA_HASH_LEN: source data length (NLA_U32)
* @NFTA_HASH_MODULUS: modulus value (NLA_U32)
* @NFTA_HASH_SEED: seed value (NLA_U32)
* @NFTA_HASH_OFFSET: add this offset value to hash result (NLA_U32)
*/
enum nft_hash_attributes {
NFTA_HASH_UNSPEC,
Expand All @@ -739,6 +740,7 @@ enum nft_hash_attributes {
NFTA_HASH_LEN,
NFTA_HASH_MODULUS,
NFTA_HASH_SEED,
NFTA_HASH_OFFSET,
__NFTA_HASH_MAX,
};
#define NFTA_HASH_MAX (__NFTA_HASH_MAX - 1)
Expand Down
17 changes: 13 additions & 4 deletions net/netfilter/nft_hash.c
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,7 @@ struct nft_hash {
u8 len;
u32 modulus;
u32 seed;
u32 offset;
};

static void nft_hash_eval(const struct nft_expr *expr,
Expand All @@ -31,10 +32,10 @@ static void nft_hash_eval(const struct nft_expr *expr,
{
struct nft_hash *priv = nft_expr_priv(expr);
const void *data = &regs->data[priv->sreg];
u32 h;

regs->data[priv->dreg] =
reciprocal_scale(jhash(data, priv->len, priv->seed),
priv->modulus);
h = reciprocal_scale(jhash(data, priv->len, priv->seed), priv->modulus);
regs->data[priv->dreg] = h + priv->offset;
}

static const struct nla_policy nft_hash_policy[NFTA_HASH_MAX + 1] = {
Expand All @@ -59,6 +60,9 @@ static int nft_hash_init(const struct nft_ctx *ctx,
!tb[NFTA_HASH_MODULUS])
return -EINVAL;

if (tb[NFTA_HASH_OFFSET])
priv->offset = ntohl(nla_get_be32(tb[NFTA_HASH_OFFSET]));

priv->sreg = nft_parse_register(tb[NFTA_HASH_SREG]);
priv->dreg = nft_parse_register(tb[NFTA_HASH_DREG]);

Expand All @@ -72,6 +76,9 @@ static int nft_hash_init(const struct nft_ctx *ctx,
if (priv->modulus <= 1)
return -ERANGE;

if (priv->offset + priv->modulus - 1 < U32_MAX)
return -EOVERFLOW;

priv->seed = ntohl(nla_get_be32(tb[NFTA_HASH_SEED]));

return nft_validate_register_load(priv->sreg, len) &&
Expand All @@ -94,7 +101,9 @@ static int nft_hash_dump(struct sk_buff *skb,
goto nla_put_failure;
if (nla_put_be32(skb, NFTA_HASH_SEED, htonl(priv->seed)))
goto nla_put_failure;

if (priv->offset != 0)
if (nla_put_be32(skb, NFTA_HASH_OFFSET, htonl(priv->offset)))
goto nla_put_failure;
return 0;

nla_put_failure:
Expand Down

0 comments on commit 70ca767

Please sign in to comment.