diff options
author | Patrick McHardy <kaber@trash.net> | 2015-03-25 09:07:48 -0400 |
---|---|---|
committer | Pablo Neira Ayuso <pablo@netfilter.org> | 2015-03-25 12:18:34 -0400 |
commit | bfd6e327e118d2fe443047829047862b49012457 (patch) | |
tree | 8b71562f6117d2b3a8c487390ebaa9504cf40e0a | |
parent | 45d84751fb310fe0063cf005ffd6593b4c2321a8 (diff) |
netfilter: nft_hash: convert to use rhashtable callbacks
A following patch will convert sets to use so called set extensions,
where the key is not located in a fixed position anymore. This will
require rhashtable hashing and comparison callbacks to be used.
As preparation, convert nft_hash to use these callbacks without any
functional changes.
Signed-off-by: Patrick McHardy <kaber@trash.net>
Signed-off-by: Pablo Neira Ayuso <pablo@netfilter.org>
-rw-r--r-- | net/netfilter/nft_hash.c | 54 |
1 files changed, 49 insertions, 5 deletions
diff --git a/net/netfilter/nft_hash.c b/net/netfilter/nft_hash.c index e35f0b2d8e65..dc96a7e94f80 100644 --- a/net/netfilter/nft_hash.c +++ b/net/netfilter/nft_hash.c | |||
@@ -33,16 +33,50 @@ struct nft_hash_elem { | |||
33 | struct nft_data data[]; | 33 | struct nft_data data[]; |
34 | }; | 34 | }; |
35 | 35 | ||
36 | struct nft_hash_cmp_arg { | ||
37 | const struct nft_set *set; | ||
38 | const struct nft_data *key; | ||
39 | }; | ||
40 | |||
36 | static const struct rhashtable_params nft_hash_params; | 41 | static const struct rhashtable_params nft_hash_params; |
37 | 42 | ||
43 | static inline u32 nft_hash_key(const void *data, u32 len, u32 seed) | ||
44 | { | ||
45 | const struct nft_hash_cmp_arg *arg = data; | ||
46 | |||
47 | return jhash(arg->key, len, seed); | ||
48 | } | ||
49 | |||
50 | static inline u32 nft_hash_obj(const void *data, u32 len, u32 seed) | ||
51 | { | ||
52 | const struct nft_hash_elem *he = data; | ||
53 | |||
54 | return jhash(&he->key, len, seed); | ||
55 | } | ||
56 | |||
57 | static inline int nft_hash_cmp(struct rhashtable_compare_arg *arg, | ||
58 | const void *ptr) | ||
59 | { | ||
60 | const struct nft_hash_cmp_arg *x = arg->key; | ||
61 | const struct nft_hash_elem *he = ptr; | ||
62 | |||
63 | if (nft_data_cmp(&he->key, x->key, x->set->klen)) | ||
64 | return 1; | ||
65 | return 0; | ||
66 | } | ||
67 | |||
38 | static bool nft_hash_lookup(const struct nft_set *set, | 68 | static bool nft_hash_lookup(const struct nft_set *set, |
39 | const struct nft_data *key, | 69 | const struct nft_data *key, |
40 | struct nft_data *data) | 70 | struct nft_data *data) |
41 | { | 71 | { |
42 | struct nft_hash *priv = nft_set_priv(set); | 72 | struct nft_hash *priv = nft_set_priv(set); |
43 | const struct nft_hash_elem *he; | 73 | const struct nft_hash_elem *he; |
74 | struct nft_hash_cmp_arg arg = { | ||
75 | .set = set, | ||
76 | .key = key, | ||
77 | }; | ||
44 | 78 | ||
45 | he = rhashtable_lookup_fast(&priv->ht, key, nft_hash_params); | 79 | he = rhashtable_lookup_fast(&priv->ht, &arg, nft_hash_params); |
46 | if (he && set->flags & NFT_SET_MAP) | 80 | if (he && set->flags & NFT_SET_MAP) |
47 | nft_data_copy(data, he->data); | 81 | nft_data_copy(data, he->data); |
48 | 82 | ||
@@ -54,6 +88,10 @@ static int nft_hash_insert(const struct nft_set *set, | |||
54 | { | 88 | { |
55 | struct nft_hash *priv = nft_set_priv(set); | 89 | struct nft_hash *priv = nft_set_priv(set); |
56 | struct nft_hash_elem *he; | 90 | struct nft_hash_elem *he; |
91 | struct nft_hash_cmp_arg arg = { | ||
92 | .set = set, | ||
93 | .key = &elem->key, | ||
94 | }; | ||
57 | unsigned int size; | 95 | unsigned int size; |
58 | int err; | 96 | int err; |
59 | 97 | ||
@@ -72,7 +110,8 @@ static int nft_hash_insert(const struct nft_set *set, | |||
72 | if (set->flags & NFT_SET_MAP) | 110 | if (set->flags & NFT_SET_MAP) |
73 | nft_data_copy(he->data, &elem->data); | 111 | nft_data_copy(he->data, &elem->data); |
74 | 112 | ||
75 | err = rhashtable_insert_fast(&priv->ht, &he->node, nft_hash_params); | 113 | err = rhashtable_lookup_insert_key(&priv->ht, &arg, &he->node, |
114 | nft_hash_params); | ||
76 | if (err) | 115 | if (err) |
77 | kfree(he); | 116 | kfree(he); |
78 | 117 | ||
@@ -102,8 +141,12 @@ static int nft_hash_get(const struct nft_set *set, struct nft_set_elem *elem) | |||
102 | { | 141 | { |
103 | struct nft_hash *priv = nft_set_priv(set); | 142 | struct nft_hash *priv = nft_set_priv(set); |
104 | struct nft_hash_elem *he; | 143 | struct nft_hash_elem *he; |
144 | struct nft_hash_cmp_arg arg = { | ||
145 | .set = set, | ||
146 | .key = &elem->key, | ||
147 | }; | ||
105 | 148 | ||
106 | he = rhashtable_lookup_fast(&priv->ht, &elem->key, nft_hash_params); | 149 | he = rhashtable_lookup_fast(&priv->ht, &arg, nft_hash_params); |
107 | if (!he) | 150 | if (!he) |
108 | return -ENOENT; | 151 | return -ENOENT; |
109 | 152 | ||
@@ -174,8 +217,9 @@ static unsigned int nft_hash_privsize(const struct nlattr * const nla[]) | |||
174 | 217 | ||
175 | static const struct rhashtable_params nft_hash_params = { | 218 | static const struct rhashtable_params nft_hash_params = { |
176 | .head_offset = offsetof(struct nft_hash_elem, node), | 219 | .head_offset = offsetof(struct nft_hash_elem, node), |
177 | .key_offset = offsetof(struct nft_hash_elem, key), | 220 | .hashfn = nft_hash_key, |
178 | .hashfn = jhash, | 221 | .obj_hashfn = nft_hash_obj, |
222 | .obj_cmpfn = nft_hash_cmp, | ||
179 | .automatic_shrinking = true, | 223 | .automatic_shrinking = true, |
180 | }; | 224 | }; |
181 | 225 | ||