Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

netfilter: nf_flow_table: move init code to nf_flow_table_core.c

Reduces duplication of .gc and .params in flowtable type definitions and
makes the API clearer

Signed-off-by: Felix Fietkau <nbd@nbd.name>
Signed-off-by: Pablo Neira Ayuso <pablo@netfilter.org>

authored by

Felix Fietkau and committed by
Pablo Neira Ayuso
a268de77 1e80380b

+74 -65
+2 -4
include/net/netfilter/nf_flow_table.h
··· 14 14 struct nf_flowtable_type { 15 15 struct list_head list; 16 16 int family; 17 - void (*gc)(struct work_struct *work); 17 + int (*init)(struct nf_flowtable *ft); 18 18 void (*free)(struct nf_flowtable *ft); 19 - const struct rhashtable_params *params; 20 19 nf_hookfn *hook; 21 20 struct module *owner; 22 21 }; ··· 99 100 100 101 void nf_flow_table_cleanup(struct net *net, struct net_device *dev); 101 102 103 + int nf_flow_table_init(struct nf_flowtable *flow_table); 102 104 void nf_flow_table_free(struct nf_flowtable *flow_table); 103 - void nf_flow_offload_work_gc(struct work_struct *work); 104 - extern const struct rhashtable_params nf_flow_offload_rhash_params; 105 105 106 106 void flow_offload_dead(struct flow_offload *flow); 107 107
+1 -2
net/ipv4/netfilter/nf_flow_table_ipv4.c
··· 7 7 8 8 static struct nf_flowtable_type flowtable_ipv4 = { 9 9 .family = NFPROTO_IPV4, 10 - .params = &nf_flow_offload_rhash_params, 11 - .gc = nf_flow_offload_work_gc, 10 + .init = nf_flow_table_init, 12 11 .free = nf_flow_table_free, 13 12 .hook = nf_flow_offload_ip_hook, 14 13 .owner = THIS_MODULE,
+1 -2
net/ipv6/netfilter/nf_flow_table_ipv6.c
··· 8 8 9 9 static struct nf_flowtable_type flowtable_ipv6 = { 10 10 .family = NFPROTO_IPV6, 11 - .params = &nf_flow_offload_rhash_params, 12 - .gc = nf_flow_offload_work_gc, 11 + .init = nf_flow_table_init, 13 12 .free = nf_flow_table_free, 14 13 .hook = nf_flow_offload_ipv6_hook, 15 14 .owner = THIS_MODULE,
+60 -42
net/netfilter/nf_flow_table_core.c
··· 116 116 } 117 117 EXPORT_SYMBOL_GPL(flow_offload_dead); 118 118 119 + static u32 flow_offload_hash(const void *data, u32 len, u32 seed) 120 + { 121 + const struct flow_offload_tuple *tuple = data; 122 + 123 + return jhash(tuple, offsetof(struct flow_offload_tuple, dir), seed); 124 + } 125 + 126 + static u32 flow_offload_hash_obj(const void *data, u32 len, u32 seed) 127 + { 128 + const struct flow_offload_tuple_rhash *tuplehash = data; 129 + 130 + return jhash(&tuplehash->tuple, offsetof(struct flow_offload_tuple, dir), seed); 131 + } 132 + 133 + static int flow_offload_hash_cmp(struct rhashtable_compare_arg *arg, 134 + const void *ptr) 135 + { 136 + const struct flow_offload_tuple *tuple = arg->key; 137 + const struct flow_offload_tuple_rhash *x = ptr; 138 + 139 + if (memcmp(&x->tuple, tuple, offsetof(struct flow_offload_tuple, dir))) 140 + return 1; 141 + 142 + return 0; 143 + } 144 + 145 + static const struct rhashtable_params nf_flow_offload_rhash_params = { 146 + .head_offset = offsetof(struct flow_offload_tuple_rhash, node), 147 + .hashfn = flow_offload_hash, 148 + .obj_hashfn = flow_offload_hash_obj, 149 + .obj_cmpfn = flow_offload_hash_cmp, 150 + .automatic_shrinking = true, 151 + }; 152 + 119 153 int flow_offload_add(struct nf_flowtable *flow_table, struct flow_offload *flow) 120 154 { 121 155 flow->timeout = (u32)jiffies; 122 156 123 157 rhashtable_insert_fast(&flow_table->rhashtable, 124 158 &flow->tuplehash[FLOW_OFFLOAD_DIR_ORIGINAL].node, 125 - *flow_table->type->params); 159 + nf_flow_offload_rhash_params); 126 160 rhashtable_insert_fast(&flow_table->rhashtable, 127 161 &flow->tuplehash[FLOW_OFFLOAD_DIR_REPLY].node, 128 - *flow_table->type->params); 162 + nf_flow_offload_rhash_params); 129 163 return 0; 130 164 } 131 165 EXPORT_SYMBOL_GPL(flow_offload_add); ··· 169 135 { 170 136 rhashtable_remove_fast(&flow_table->rhashtable, 171 137 &flow->tuplehash[FLOW_OFFLOAD_DIR_ORIGINAL].node, 172 - *flow_table->type->params); 138 + nf_flow_offload_rhash_params); 173 139 rhashtable_remove_fast(&flow_table->rhashtable, 174 140 &flow->tuplehash[FLOW_OFFLOAD_DIR_REPLY].node, 175 - *flow_table->type->params); 141 + nf_flow_offload_rhash_params); 176 142 177 143 flow_offload_free(flow); 178 144 } ··· 182 148 struct flow_offload_tuple *tuple) 183 149 { 184 150 return rhashtable_lookup_fast(&flow_table->rhashtable, tuple, 185 - *flow_table->type->params); 151 + nf_flow_offload_rhash_params); 186 152 } 187 153 EXPORT_SYMBOL_GPL(flow_offload_lookup); 188 154 ··· 271 237 return 1; 272 238 } 273 239 274 - void nf_flow_offload_work_gc(struct work_struct *work) 240 + static void nf_flow_offload_work_gc(struct work_struct *work) 275 241 { 276 242 struct nf_flowtable *flow_table; 277 243 ··· 279 245 nf_flow_offload_gc_step(flow_table); 280 246 queue_delayed_work(system_power_efficient_wq, &flow_table->gc_work, HZ); 281 247 } 282 - EXPORT_SYMBOL_GPL(nf_flow_offload_work_gc); 283 - 284 - static u32 flow_offload_hash(const void *data, u32 len, u32 seed) 285 - { 286 - const struct flow_offload_tuple *tuple = data; 287 - 288 - return jhash(tuple, offsetof(struct flow_offload_tuple, dir), seed); 289 - } 290 - 291 - static u32 flow_offload_hash_obj(const void *data, u32 len, u32 seed) 292 - { 293 - const struct flow_offload_tuple_rhash *tuplehash = data; 294 - 295 - return jhash(&tuplehash->tuple, offsetof(struct flow_offload_tuple, dir), seed); 296 - } 297 - 298 - static int flow_offload_hash_cmp(struct rhashtable_compare_arg *arg, 299 - const void *ptr) 300 - { 301 - const struct flow_offload_tuple *tuple = arg->key; 302 - const struct flow_offload_tuple_rhash *x = ptr; 303 - 304 - if (memcmp(&x->tuple, tuple, offsetof(struct flow_offload_tuple, dir))) 305 - return 1; 306 - 307 - return 0; 308 - } 309 - 310 - const struct rhashtable_params nf_flow_offload_rhash_params = { 311 - .head_offset = offsetof(struct flow_offload_tuple_rhash, node), 312 - .hashfn = flow_offload_hash, 313 - .obj_hashfn = flow_offload_hash_obj, 314 - .obj_cmpfn = flow_offload_hash_cmp, 315 - .automatic_shrinking = true, 316 - }; 317 - EXPORT_SYMBOL_GPL(nf_flow_offload_rhash_params); 318 248 319 249 static int nf_flow_nat_port_tcp(struct sk_buff *skb, unsigned int thoff, 320 250 __be16 port, __be16 new_port) ··· 396 398 } 397 399 EXPORT_SYMBOL_GPL(nf_flow_dnat_port); 398 400 401 + int nf_flow_table_init(struct nf_flowtable *flowtable) 402 + { 403 + int err; 404 + 405 + INIT_DEFERRABLE_WORK(&flowtable->gc_work, nf_flow_offload_work_gc); 406 + 407 + err = rhashtable_init(&flowtable->rhashtable, 408 + &nf_flow_offload_rhash_params); 409 + if (err < 0) 410 + return err; 411 + 412 + queue_delayed_work(system_power_efficient_wq, 413 + &flowtable->gc_work, HZ); 414 + 415 + return 0; 416 + } 417 + EXPORT_SYMBOL_GPL(nf_flow_table_init); 418 + 399 419 static void nf_flow_table_do_cleanup(struct flow_offload *flow, void *data) 400 420 { 401 421 struct net_device *dev = data; ··· 439 423 440 424 void nf_flow_table_free(struct nf_flowtable *flow_table) 441 425 { 426 + cancel_delayed_work_sync(&flow_table->gc_work); 442 427 nf_flow_table_iterate(flow_table, nf_flow_table_do_cleanup, NULL); 443 428 WARN_ON(!nf_flow_offload_gc_step(flow_table)); 429 + rhashtable_destroy(&flow_table->rhashtable); 444 430 } 445 431 EXPORT_SYMBOL_GPL(nf_flow_table_free); 446 432
+1 -2
net/netfilter/nf_flow_table_inet.c
··· 22 22 23 23 static struct nf_flowtable_type flowtable_inet = { 24 24 .family = NFPROTO_INET, 25 - .params = &nf_flow_offload_rhash_params, 26 - .gc = nf_flow_offload_work_gc, 25 + .init = nf_flow_table_init, 27 26 .free = nf_flow_table_free, 28 27 .hook = nf_flow_offload_inet_hook, 29 28 .owner = THIS_MODULE,
+9 -13
net/netfilter/nf_tables_api.c
··· 5150 5150 } 5151 5151 5152 5152 flowtable->data.type = type; 5153 - err = rhashtable_init(&flowtable->data.rhashtable, type->params); 5153 + err = type->init(&flowtable->data); 5154 5154 if (err < 0) 5155 5155 goto err3; 5156 5156 5157 5157 err = nf_tables_flowtable_parse_hook(&ctx, nla[NFTA_FLOWTABLE_HOOK], 5158 5158 flowtable); 5159 5159 if (err < 0) 5160 - goto err3; 5160 + goto err4; 5161 5161 5162 5162 for (i = 0; i < flowtable->ops_len; i++) { 5163 5163 if (!flowtable->ops[i].dev) ··· 5171 5171 if (flowtable->ops[i].dev == ft->ops[k].dev && 5172 5172 flowtable->ops[i].pf == ft->ops[k].pf) { 5173 5173 err = -EBUSY; 5174 - goto err4; 5174 + goto err5; 5175 5175 } 5176 5176 } 5177 5177 } 5178 5178 5179 5179 err = nf_register_net_hook(net, &flowtable->ops[i]); 5180 5180 if (err < 0) 5181 - goto err4; 5181 + goto err5; 5182 5182 } 5183 5183 5184 5184 err = nft_trans_flowtable_add(&ctx, NFT_MSG_NEWFLOWTABLE, flowtable); 5185 5185 if (err < 0) 5186 - goto err5; 5187 - 5188 - INIT_DEFERRABLE_WORK(&flowtable->data.gc_work, type->gc); 5189 - queue_delayed_work(system_power_efficient_wq, 5190 - &flowtable->data.gc_work, HZ); 5186 + goto err6; 5191 5187 5192 5188 list_add_tail_rcu(&flowtable->list, &table->flowtables); 5193 5189 table->use++; 5194 5190 5195 5191 return 0; 5196 - err5: 5192 + err6: 5197 5193 i = flowtable->ops_len; 5198 - err4: 5194 + err5: 5199 5195 for (k = i - 1; k >= 0; k--) { 5200 5196 kfree(flowtable->dev_name[k]); 5201 5197 nf_unregister_net_hook(net, &flowtable->ops[k]); 5202 5198 } 5203 5199 5204 5200 kfree(flowtable->ops); 5201 + err4: 5202 + flowtable->data.type->free(&flowtable->data); 5205 5203 err3: 5206 5204 module_put(type->owner); 5207 5205 err2: ··· 5483 5485 5484 5486 static void nf_tables_flowtable_destroy(struct nft_flowtable *flowtable) 5485 5487 { 5486 - cancel_delayed_work_sync(&flowtable->data.gc_work); 5487 5488 kfree(flowtable->ops); 5488 5489 kfree(flowtable->name); 5489 5490 flowtable->data.type->free(&flowtable->data); 5490 - rhashtable_destroy(&flowtable->data.rhashtable); 5491 5491 module_put(flowtable->data.type->owner); 5492 5492 } 5493 5493