aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorHerbert Xu <herbert@gondor.apana.org.au>2015-03-20 06:57:02 -0400
committerDavid S. Miller <davem@davemloft.net>2015-03-20 16:16:24 -0400
commitfa3773211eb61f2a08ffc399a98af53594ba1509 (patch)
tree091bc12c3e98e72cd7c6284eac1beeffe0dae9d4
parentc428ecd1a21f1457ca3beb4df71b8a079c410e41 (diff)
netfilter: Convert nft_hash to inlined rhashtable
This patch converts nft_hash to the inlined rhashtable interface. This patch also replaces the call to rhashtable_lookup_compare with a straight rhashtable_lookup_fast because it's simply doing a memcmp (in fact nft_hash_lookup already uses memcmp instead of nft_data_cmp). Furthermore, the compare function is only meant to compare, it is not supposed to have side-effects. The current side-effect code can simply be moved into the nft_hash_get. Signed-off-by: Herbert Xu <herbert@gondor.apana.org.au> Signed-off-by: David S. Miller <davem@davemloft.net>
-rw-r--r--net/netfilter/nft_hash.c70
1 files changed, 29 insertions, 41 deletions
diff --git a/net/netfilter/nft_hash.c b/net/netfilter/nft_hash.c
index c82df0a48fcd..4585c5724391 100644
--- a/net/netfilter/nft_hash.c
+++ b/net/netfilter/nft_hash.c
@@ -29,6 +29,8 @@ struct nft_hash_elem {
29 struct nft_data data[]; 29 struct nft_data data[];
30}; 30};
31 31
32static const struct rhashtable_params nft_hash_params;
33
32static bool nft_hash_lookup(const struct nft_set *set, 34static bool nft_hash_lookup(const struct nft_set *set,
33 const struct nft_data *key, 35 const struct nft_data *key,
34 struct nft_data *data) 36 struct nft_data *data)
@@ -36,7 +38,7 @@ static bool nft_hash_lookup(const struct nft_set *set,
36 struct rhashtable *priv = nft_set_priv(set); 38 struct rhashtable *priv = nft_set_priv(set);
37 const struct nft_hash_elem *he; 39 const struct nft_hash_elem *he;
38 40
39 he = rhashtable_lookup(priv, key); 41 he = rhashtable_lookup_fast(priv, key, nft_hash_params);
40 if (he && set->flags & NFT_SET_MAP) 42 if (he && set->flags & NFT_SET_MAP)
41 nft_data_copy(data, he->data); 43 nft_data_copy(data, he->data);
42 44
@@ -49,6 +51,7 @@ static int nft_hash_insert(const struct nft_set *set,
49 struct rhashtable *priv = nft_set_priv(set); 51 struct rhashtable *priv = nft_set_priv(set);
50 struct nft_hash_elem *he; 52 struct nft_hash_elem *he;
51 unsigned int size; 53 unsigned int size;
54 int err;
52 55
53 if (elem->flags != 0) 56 if (elem->flags != 0)
54 return -EINVAL; 57 return -EINVAL;
@@ -65,9 +68,11 @@ static int nft_hash_insert(const struct nft_set *set,
65 if (set->flags & NFT_SET_MAP) 68 if (set->flags & NFT_SET_MAP)
66 nft_data_copy(he->data, &elem->data); 69 nft_data_copy(he->data, &elem->data);
67 70
68 rhashtable_insert(priv, &he->node); 71 err = rhashtable_insert_fast(priv, &he->node, nft_hash_params);
72 if (err)
73 kfree(he);
69 74
70 return 0; 75 return err;
71} 76}
72 77
73static void nft_hash_elem_destroy(const struct nft_set *set, 78static void nft_hash_elem_destroy(const struct nft_set *set,
@@ -84,46 +89,26 @@ static void nft_hash_remove(const struct nft_set *set,
84{ 89{
85 struct rhashtable *priv = nft_set_priv(set); 90 struct rhashtable *priv = nft_set_priv(set);
86 91
87 rhashtable_remove(priv, elem->cookie); 92 rhashtable_remove_fast(priv, elem->cookie, nft_hash_params);
88 synchronize_rcu(); 93 synchronize_rcu();
89 kfree(elem->cookie); 94 kfree(elem->cookie);
90} 95}
91 96
92struct nft_compare_arg {
93 const struct nft_set *set;
94 struct nft_set_elem *elem;
95};
96
97static bool nft_hash_compare(void *ptr, void *arg)
98{
99 struct nft_hash_elem *he = ptr;
100 struct nft_compare_arg *x = arg;
101
102 if (!nft_data_cmp(&he->key, &x->elem->key, x->set->klen)) {
103 x->elem->cookie = he;
104 x->elem->flags = 0;
105 if (x->set->flags & NFT_SET_MAP)
106 nft_data_copy(&x->elem->data, he->data);
107
108 return true;
109 }
110
111 return false;
112}
113
114static int nft_hash_get(const struct nft_set *set, struct nft_set_elem *elem) 97static int nft_hash_get(const struct nft_set *set, struct nft_set_elem *elem)
115{ 98{
116 struct rhashtable *priv = nft_set_priv(set); 99 struct rhashtable *priv = nft_set_priv(set);
117 struct nft_compare_arg arg = { 100 struct nft_hash_elem *he;
118 .set = set, 101
119 .elem = elem, 102 he = rhashtable_lookup_fast(priv, &elem->key, nft_hash_params);
120 }; 103 if (!he)
104 return -ENOENT;
121 105
122 if (rhashtable_lookup_compare(priv, &elem->key, 106 elem->cookie = he;
123 &nft_hash_compare, &arg)) 107 elem->flags = 0;
124 return 0; 108 if (set->flags & NFT_SET_MAP)
109 nft_data_copy(&elem->data, he->data);
125 110
126 return -ENOENT; 111 return 0;
127} 112}
128 113
129static void nft_hash_walk(const struct nft_ctx *ctx, const struct nft_set *set, 114static void nft_hash_walk(const struct nft_ctx *ctx, const struct nft_set *set,
@@ -181,18 +166,21 @@ static unsigned int nft_hash_privsize(const struct nlattr * const nla[])
181 return sizeof(struct rhashtable); 166 return sizeof(struct rhashtable);
182} 167}
183 168
169static const struct rhashtable_params nft_hash_params = {
170 .head_offset = offsetof(struct nft_hash_elem, node),
171 .key_offset = offsetof(struct nft_hash_elem, key),
172 .hashfn = jhash,
173};
174
184static int nft_hash_init(const struct nft_set *set, 175static int nft_hash_init(const struct nft_set *set,
185 const struct nft_set_desc *desc, 176 const struct nft_set_desc *desc,
186 const struct nlattr * const tb[]) 177 const struct nlattr * const tb[])
187{ 178{
188 struct rhashtable *priv = nft_set_priv(set); 179 struct rhashtable *priv = nft_set_priv(set);
189 struct rhashtable_params params = { 180 struct rhashtable_params params = nft_hash_params;
190 .nelem_hint = desc->size ? : NFT_HASH_ELEMENT_HINT, 181
191 .head_offset = offsetof(struct nft_hash_elem, node), 182 params.nelem_hint = desc->size ?: NFT_HASH_ELEMENT_HINT;
192 .key_offset = offsetof(struct nft_hash_elem, key), 183 params.key_len = set->klen;
193 .key_len = set->klen,
194 .hashfn = jhash,
195 };
196 184
197 return rhashtable_init(priv, &params); 185 return rhashtable_init(priv, &params);
198} 186}