OpenWrt – Blame information for rev 1
?pathlinks?
Rev | Author | Line No. | Line |
---|---|---|---|
1 | office | 1 | From: Pablo Neira Ayuso <pablo@netfilter.org> |
2 | Date: Mon, 5 Feb 2018 21:44:50 +0100 |
||
3 | Subject: [PATCH] netfilter: nf_tables: fix flowtable free |
||
4 | |||
5 | Every flow_offload entry is added into the table twice. Because of this, |
||
6 | rhashtable_free_and_destroy can't be used, since it would call kfree for |
||
7 | each flow_offload object twice. |
||
8 | |||
9 | This patch adds a call to nf_flow_table_iterate_cleanup() to schedule |
||
10 | removal of entries, then there is an explicitly invocation of the |
||
11 | garbage collector to clean up resources. |
||
12 | |||
13 | Signed-off-by: Pablo Neira Ayuso <pablo@netfilter.org> |
||
14 | --- |
||
15 | |||
16 | --- a/include/net/netfilter/nf_flow_table.h |
||
17 | +++ b/include/net/netfilter/nf_flow_table.h |
||
18 | @@ -14,6 +14,7 @@ struct nf_flowtable_type { |
||
19 | struct list_head list; |
||
20 | int family; |
||
21 | void (*gc)(struct work_struct *work); |
||
22 | + void (*free)(struct nf_flowtable *ft); |
||
23 | const struct rhashtable_params *params; |
||
24 | nf_hookfn *hook; |
||
25 | struct module *owner; |
||
26 | @@ -98,6 +99,7 @@ int nf_flow_table_iterate(struct nf_flow |
||
27 | |||
28 | void nf_flow_table_cleanup(struct net *net, struct net_device *dev); |
||
29 | |||
30 | +void nf_flow_table_free(struct nf_flowtable *flow_table); |
||
31 | void nf_flow_offload_work_gc(struct work_struct *work); |
||
32 | extern const struct rhashtable_params nf_flow_offload_rhash_params; |
||
33 | |||
34 | --- a/net/ipv4/netfilter/nf_flow_table_ipv4.c |
||
35 | +++ b/net/ipv4/netfilter/nf_flow_table_ipv4.c |
||
36 | @@ -260,6 +260,7 @@ static struct nf_flowtable_type flowtabl |
||
37 | .family = NFPROTO_IPV4, |
||
38 | .params = &nf_flow_offload_rhash_params, |
||
39 | .gc = nf_flow_offload_work_gc, |
||
40 | + .free = nf_flow_table_free, |
||
41 | .hook = nf_flow_offload_ip_hook, |
||
42 | .owner = THIS_MODULE, |
||
43 | }; |
||
44 | --- a/net/ipv6/netfilter/nf_flow_table_ipv6.c |
||
45 | +++ b/net/ipv6/netfilter/nf_flow_table_ipv6.c |
||
46 | @@ -254,6 +254,7 @@ static struct nf_flowtable_type flowtabl |
||
47 | .family = NFPROTO_IPV6, |
||
48 | .params = &nf_flow_offload_rhash_params, |
||
49 | .gc = nf_flow_offload_work_gc, |
||
50 | + .free = nf_flow_table_free, |
||
51 | .hook = nf_flow_offload_ipv6_hook, |
||
52 | .owner = THIS_MODULE, |
||
53 | }; |
||
54 | --- a/net/netfilter/nf_flow_table.c |
||
55 | +++ b/net/netfilter/nf_flow_table.c |
||
56 | @@ -232,19 +232,16 @@ static inline bool nf_flow_is_dying(cons |
||
57 | return flow->flags & FLOW_OFFLOAD_DYING; |
||
58 | } |
||
59 | |||
60 | -void nf_flow_offload_work_gc(struct work_struct *work) |
||
61 | +static int nf_flow_offload_gc_step(struct nf_flowtable *flow_table) |
||
62 | { |
||
63 | struct flow_offload_tuple_rhash *tuplehash; |
||
64 | - struct nf_flowtable *flow_table; |
||
65 | struct rhashtable_iter hti; |
||
66 | struct flow_offload *flow; |
||
67 | int err; |
||
68 | |||
69 | - flow_table = container_of(work, struct nf_flowtable, gc_work.work); |
||
70 | - |
||
71 | err = rhashtable_walk_init(&flow_table->rhashtable, &hti, GFP_KERNEL); |
||
72 | if (err) |
||
73 | - goto schedule; |
||
74 | + return 0; |
||
75 | |||
76 | rhashtable_walk_start(&hti); |
||
77 | |||
78 | @@ -270,7 +267,16 @@ void nf_flow_offload_work_gc(struct work |
||
79 | out: |
||
80 | rhashtable_walk_stop(&hti); |
||
81 | rhashtable_walk_exit(&hti); |
||
82 | -schedule: |
||
83 | + |
||
84 | + return 1; |
||
85 | +} |
||
86 | + |
||
87 | +void nf_flow_offload_work_gc(struct work_struct *work) |
||
88 | +{ |
||
89 | + struct nf_flowtable *flow_table; |
||
90 | + |
||
91 | + flow_table = container_of(work, struct nf_flowtable, gc_work.work); |
||
92 | + nf_flow_offload_gc_step(flow_table); |
||
93 | queue_delayed_work(system_power_efficient_wq, &flow_table->gc_work, HZ); |
||
94 | } |
||
95 | EXPORT_SYMBOL_GPL(nf_flow_offload_work_gc); |
||
96 | @@ -449,5 +455,12 @@ void nf_flow_table_cleanup(struct net *n |
||
97 | } |
||
98 | EXPORT_SYMBOL_GPL(nf_flow_table_cleanup); |
||
99 | |||
100 | +void nf_flow_table_free(struct nf_flowtable *flow_table) |
||
101 | +{ |
||
102 | + nf_flow_table_iterate(flow_table, nf_flow_table_do_cleanup, NULL); |
||
103 | + WARN_ON(!nf_flow_offload_gc_step(flow_table)); |
||
104 | +} |
||
105 | +EXPORT_SYMBOL_GPL(nf_flow_table_free); |
||
106 | + |
||
107 | MODULE_LICENSE("GPL"); |
||
108 | MODULE_AUTHOR("Pablo Neira Ayuso <pablo@netfilter.org>"); |
||
109 | --- a/net/netfilter/nf_flow_table_inet.c |
||
110 | +++ b/net/netfilter/nf_flow_table_inet.c |
||
111 | @@ -24,6 +24,7 @@ static struct nf_flowtable_type flowtabl |
||
112 | .family = NFPROTO_INET, |
||
113 | .params = &nf_flow_offload_rhash_params, |
||
114 | .gc = nf_flow_offload_work_gc, |
||
115 | + .free = nf_flow_table_free, |
||
116 | .hook = nf_flow_offload_inet_hook, |
||
117 | .owner = THIS_MODULE, |
||
118 | }; |
||
119 | --- a/net/netfilter/nf_tables_api.c |
||
120 | +++ b/net/netfilter/nf_tables_api.c |
||
121 | @@ -5265,17 +5265,12 @@ err: |
||
122 | nfnetlink_set_err(ctx->net, ctx->portid, NFNLGRP_NFTABLES, -ENOBUFS); |
||
123 | } |
||
124 | |||
125 | -static void nft_flowtable_destroy(void *ptr, void *arg) |
||
126 | -{ |
||
127 | - kfree(ptr); |
||
128 | -} |
||
129 | - |
||
130 | static void nf_tables_flowtable_destroy(struct nft_flowtable *flowtable) |
||
131 | { |
||
132 | cancel_delayed_work_sync(&flowtable->data.gc_work); |
||
133 | kfree(flowtable->name); |
||
134 | - rhashtable_free_and_destroy(&flowtable->data.rhashtable, |
||
135 | - nft_flowtable_destroy, NULL); |
||
136 | + flowtable->data.type->free(&flowtable->data); |
||
137 | + rhashtable_destroy(&flowtable->data.rhashtable); |
||
138 | module_put(flowtable->data.type->owner); |
||
139 | } |
||
140 |