diff options
| -rw-r--r-- | net/netfilter/nft_hash.c | 70 |
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 | ||
| 32 | static const struct rhashtable_params nft_hash_params; | ||
| 33 | |||
| 32 | static bool nft_hash_lookup(const struct nft_set *set, | 34 | static 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 | ||
| 73 | static void nft_hash_elem_destroy(const struct nft_set *set, | 78 | static 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 | ||
| 92 | struct nft_compare_arg { | ||
| 93 | const struct nft_set *set; | ||
| 94 | struct nft_set_elem *elem; | ||
| 95 | }; | ||
| 96 | |||
| 97 | static 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 | |||
| 114 | static int nft_hash_get(const struct nft_set *set, struct nft_set_elem *elem) | 97 | static 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 | ||
| 129 | static void nft_hash_walk(const struct nft_ctx *ctx, const struct nft_set *set, | 114 | static 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 | ||
| 169 | static 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 | |||
| 184 | static int nft_hash_init(const struct nft_set *set, | 175 | static 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, ¶ms); | 185 | return rhashtable_init(priv, ¶ms); |
| 198 | } | 186 | } |
