diff options
-rw-r--r-- | include/net/netfilter/nf_tables.h | 28 | ||||
-rw-r--r-- | net/netfilter/nf_tables_api.c | 17 | ||||
-rw-r--r-- | net/netfilter/nf_tables_core.c | 6 |
3 files changed, 35 insertions, 16 deletions
diff --git a/include/net/netfilter/nf_tables.h b/include/net/netfilter/nf_tables.h index f190d26bda7d..4c46a325874e 100644 --- a/include/net/netfilter/nf_tables.h +++ b/include/net/netfilter/nf_tables.h | |||
@@ -720,6 +720,34 @@ void nft_unregister_expr(struct nft_expr_type *); | |||
720 | #define MODULE_ALIAS_NFT_SET() \ | 720 | #define MODULE_ALIAS_NFT_SET() \ |
721 | MODULE_ALIAS("nft-set") | 721 | MODULE_ALIAS("nft-set") |
722 | 722 | ||
723 | /* | ||
724 | * The gencursor defines two generations, the currently active and the | ||
725 | * next one. Objects contain a bitmask of 2 bits specifying the generations | ||
726 | * they're active in. A set bit means they're inactive in the generation | ||
727 | * represented by that bit. | ||
728 | * | ||
729 | * New objects start out as inactive in the current and active in the | ||
730 | * next generation. When committing the ruleset the bitmask is cleared, | ||
731 | * meaning they're active in all generations. When removing an object, | ||
732 | * it is set inactive in the next generation. After committing the ruleset, | ||
733 | * the objects are removed. | ||
734 | */ | ||
735 | static inline unsigned int nft_gencursor_next(const struct net *net) | ||
736 | { | ||
737 | return net->nft.gencursor + 1 == 1 ? 1 : 0; | ||
738 | } | ||
739 | |||
740 | static inline u8 nft_genmask_next(const struct net *net) | ||
741 | { | ||
742 | return 1 << nft_gencursor_next(net); | ||
743 | } | ||
744 | |||
745 | static inline u8 nft_genmask_cur(const struct net *net) | ||
746 | { | ||
747 | /* Use ACCESS_ONCE() to prevent refetching the value for atomicity */ | ||
748 | return 1 << ACCESS_ONCE(net->nft.gencursor); | ||
749 | } | ||
750 | |||
723 | /** | 751 | /** |
724 | * struct nft_trans - nf_tables object update in transaction | 752 | * struct nft_trans - nf_tables object update in transaction |
725 | * | 753 | * |
diff --git a/net/netfilter/nf_tables_api.c b/net/netfilter/nf_tables_api.c index b35512f1934c..66fa5e935a55 100644 --- a/net/netfilter/nf_tables_api.c +++ b/net/netfilter/nf_tables_api.c | |||
@@ -198,36 +198,31 @@ static int nft_delchain(struct nft_ctx *ctx) | |||
198 | static inline bool | 198 | static inline bool |
199 | nft_rule_is_active(struct net *net, const struct nft_rule *rule) | 199 | nft_rule_is_active(struct net *net, const struct nft_rule *rule) |
200 | { | 200 | { |
201 | return (rule->genmask & (1 << net->nft.gencursor)) == 0; | 201 | return (rule->genmask & nft_genmask_cur(net)) == 0; |
202 | } | ||
203 | |||
204 | static inline int gencursor_next(struct net *net) | ||
205 | { | ||
206 | return net->nft.gencursor+1 == 1 ? 1 : 0; | ||
207 | } | 202 | } |
208 | 203 | ||
209 | static inline int | 204 | static inline int |
210 | nft_rule_is_active_next(struct net *net, const struct nft_rule *rule) | 205 | nft_rule_is_active_next(struct net *net, const struct nft_rule *rule) |
211 | { | 206 | { |
212 | return (rule->genmask & (1 << gencursor_next(net))) == 0; | 207 | return (rule->genmask & nft_genmask_next(net)) == 0; |
213 | } | 208 | } |
214 | 209 | ||
215 | static inline void | 210 | static inline void |
216 | nft_rule_activate_next(struct net *net, struct nft_rule *rule) | 211 | nft_rule_activate_next(struct net *net, struct nft_rule *rule) |
217 | { | 212 | { |
218 | /* Now inactive, will be active in the future */ | 213 | /* Now inactive, will be active in the future */ |
219 | rule->genmask = (1 << net->nft.gencursor); | 214 | rule->genmask = nft_genmask_cur(net); |
220 | } | 215 | } |
221 | 216 | ||
222 | static inline void | 217 | static inline void |
223 | nft_rule_deactivate_next(struct net *net, struct nft_rule *rule) | 218 | nft_rule_deactivate_next(struct net *net, struct nft_rule *rule) |
224 | { | 219 | { |
225 | rule->genmask = (1 << gencursor_next(net)); | 220 | rule->genmask = nft_genmask_next(net); |
226 | } | 221 | } |
227 | 222 | ||
228 | static inline void nft_rule_clear(struct net *net, struct nft_rule *rule) | 223 | static inline void nft_rule_clear(struct net *net, struct nft_rule *rule) |
229 | { | 224 | { |
230 | rule->genmask &= ~(1 << gencursor_next(net)); | 225 | rule->genmask &= ~nft_genmask_next(net); |
231 | } | 226 | } |
232 | 227 | ||
233 | static int | 228 | static int |
@@ -3626,7 +3621,7 @@ static int nf_tables_commit(struct sk_buff *skb) | |||
3626 | while (++net->nft.base_seq == 0); | 3621 | while (++net->nft.base_seq == 0); |
3627 | 3622 | ||
3628 | /* A new generation has just started */ | 3623 | /* A new generation has just started */ |
3629 | net->nft.gencursor = gencursor_next(net); | 3624 | net->nft.gencursor = nft_gencursor_next(net); |
3630 | 3625 | ||
3631 | /* Make sure all packets have left the previous generation before | 3626 | /* Make sure all packets have left the previous generation before |
3632 | * purging old rules. | 3627 | * purging old rules. |
diff --git a/net/netfilter/nf_tables_core.c b/net/netfilter/nf_tables_core.c index 4429008fe99d..ef4dfcbaf149 100644 --- a/net/netfilter/nf_tables_core.c +++ b/net/netfilter/nf_tables_core.c | |||
@@ -121,11 +121,7 @@ nft_do_chain(struct nft_pktinfo *pkt, const struct nf_hook_ops *ops) | |||
121 | struct nft_jumpstack jumpstack[NFT_JUMP_STACK_SIZE]; | 121 | struct nft_jumpstack jumpstack[NFT_JUMP_STACK_SIZE]; |
122 | struct nft_stats *stats; | 122 | struct nft_stats *stats; |
123 | int rulenum; | 123 | int rulenum; |
124 | /* | 124 | unsigned int gencursor = nft_genmask_cur(net); |
125 | * Cache cursor to avoid problems in case that the cursor is updated | ||
126 | * while traversing the ruleset. | ||
127 | */ | ||
128 | unsigned int gencursor = ACCESS_ONCE(net->nft.gencursor); | ||
129 | 125 | ||
130 | do_chain: | 126 | do_chain: |
131 | rulenum = 0; | 127 | rulenum = 0; |