aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--include/net/netfilter/nf_tables.h33
-rw-r--r--net/netfilter/nf_tables_api.c33
-rw-r--r--net/netfilter/nft_hash.c38
-rw-r--r--net/netfilter/nft_rbtree.c48
4 files changed, 112 insertions, 40 deletions
diff --git a/include/net/netfilter/nf_tables.h b/include/net/netfilter/nf_tables.h
index 4c46a325874e..b8cd60dcb4e1 100644
--- a/include/net/netfilter/nf_tables.h
+++ b/include/net/netfilter/nf_tables.h
@@ -138,15 +138,10 @@ struct nft_userdata {
138/** 138/**
139 * struct nft_set_elem - generic representation of set elements 139 * struct nft_set_elem - generic representation of set elements
140 * 140 *
141 * @cookie: implementation specific element cookie
142 * @key: element key 141 * @key: element key
143 * @priv: element private data and extensions 142 * @priv: element private data and extensions
144 *
145 * The cookie can be used to store a handle to the element for subsequent
146 * removal.
147 */ 143 */
148struct nft_set_elem { 144struct nft_set_elem {
149 void *cookie;
150 struct nft_data key; 145 struct nft_data key;
151 void *priv; 146 void *priv;
152}; 147};
@@ -207,6 +202,8 @@ struct nft_set_ext;
207 * 202 *
208 * @lookup: look up an element within the set 203 * @lookup: look up an element within the set
209 * @insert: insert new element into set 204 * @insert: insert new element into set
205 * @activate: activate new element in the next generation
206 * @deactivate: deactivate element in the next generation
210 * @remove: remove element from set 207 * @remove: remove element from set
211 * @walk: iterate over all set elemeennts 208 * @walk: iterate over all set elemeennts
212 * @privsize: function to return size of set private data 209 * @privsize: function to return size of set private data
@@ -221,10 +218,12 @@ struct nft_set_ops {
221 bool (*lookup)(const struct nft_set *set, 218 bool (*lookup)(const struct nft_set *set,
222 const struct nft_data *key, 219 const struct nft_data *key,
223 const struct nft_set_ext **ext); 220 const struct nft_set_ext **ext);
224 int (*get)(const struct nft_set *set,
225 struct nft_set_elem *elem);
226 int (*insert)(const struct nft_set *set, 221 int (*insert)(const struct nft_set *set,
227 const struct nft_set_elem *elem); 222 const struct nft_set_elem *elem);
223 void (*activate)(const struct nft_set *set,
224 const struct nft_set_elem *elem);
225 void * (*deactivate)(const struct nft_set *set,
226 const struct nft_set_elem *elem);
228 void (*remove)(const struct nft_set *set, 227 void (*remove)(const struct nft_set *set,
229 const struct nft_set_elem *elem); 228 const struct nft_set_elem *elem);
230 void (*walk)(const struct nft_ctx *ctx, 229 void (*walk)(const struct nft_ctx *ctx,
@@ -261,6 +260,7 @@ void nft_unregister_set(struct nft_set_ops *ops);
261 * @nelems: number of elements 260 * @nelems: number of elements
262 * @policy: set parameterization (see enum nft_set_policies) 261 * @policy: set parameterization (see enum nft_set_policies)
263 * @ops: set ops 262 * @ops: set ops
263 * @pnet: network namespace
264 * @flags: set flags 264 * @flags: set flags
265 * @klen: key length 265 * @klen: key length
266 * @dlen: data length 266 * @dlen: data length
@@ -277,6 +277,7 @@ struct nft_set {
277 u16 policy; 277 u16 policy;
278 /* runtime data below here */ 278 /* runtime data below here */
279 const struct nft_set_ops *ops ____cacheline_aligned; 279 const struct nft_set_ops *ops ____cacheline_aligned;
280 possible_net_t pnet;
280 u16 flags; 281 u16 flags;
281 u8 klen; 282 u8 klen;
282 u8 dlen; 283 u8 dlen;
@@ -355,10 +356,12 @@ struct nft_set_ext_tmpl {
355/** 356/**
356 * struct nft_set_ext - set extensions 357 * struct nft_set_ext - set extensions
357 * 358 *
359 * @genmask: generation mask
358 * @offset: offsets of individual extension types 360 * @offset: offsets of individual extension types
359 * @data: beginning of extension data 361 * @data: beginning of extension data
360 */ 362 */
361struct nft_set_ext { 363struct nft_set_ext {
364 u8 genmask;
362 u8 offset[NFT_SET_EXT_NUM]; 365 u8 offset[NFT_SET_EXT_NUM];
363 char data[0]; 366 char data[0];
364}; 367};
@@ -748,6 +751,22 @@ static inline u8 nft_genmask_cur(const struct net *net)
748 return 1 << ACCESS_ONCE(net->nft.gencursor); 751 return 1 << ACCESS_ONCE(net->nft.gencursor);
749} 752}
750 753
754/*
755 * Set element transaction helpers
756 */
757
758static inline bool nft_set_elem_active(const struct nft_set_ext *ext,
759 u8 genmask)
760{
761 return !(ext->genmask & genmask);
762}
763
764static inline void nft_set_elem_change_active(const struct nft_set *set,
765 struct nft_set_ext *ext)
766{
767 ext->genmask ^= nft_genmask_next(read_pnet(&set->pnet));
768}
769
751/** 770/**
752 * struct nft_trans - nf_tables object update in transaction 771 * struct nft_trans - nf_tables object update in transaction
753 * 772 *
diff --git a/net/netfilter/nf_tables_api.c b/net/netfilter/nf_tables_api.c
index 66fa5e935a55..5604c2df05d1 100644
--- a/net/netfilter/nf_tables_api.c
+++ b/net/netfilter/nf_tables_api.c
@@ -2690,6 +2690,7 @@ static int nf_tables_newset(struct sock *nlsk, struct sk_buff *skb,
2690 goto err2; 2690 goto err2;
2691 2691
2692 INIT_LIST_HEAD(&set->bindings); 2692 INIT_LIST_HEAD(&set->bindings);
2693 write_pnet(&set->pnet, net);
2693 set->ops = ops; 2694 set->ops = ops;
2694 set->ktype = ktype; 2695 set->ktype = ktype;
2695 set->klen = desc.klen; 2696 set->klen = desc.klen;
@@ -3221,10 +3222,6 @@ static int nft_add_set_elem(struct nft_ctx *ctx, struct nft_set *set,
3221 if (d1.type != NFT_DATA_VALUE || d1.len != set->klen) 3222 if (d1.type != NFT_DATA_VALUE || d1.len != set->klen)
3222 goto err2; 3223 goto err2;
3223 3224
3224 err = -EEXIST;
3225 if (set->ops->get(set, &elem) == 0)
3226 goto err2;
3227
3228 nft_set_ext_add(&tmpl, NFT_SET_EXT_KEY); 3225 nft_set_ext_add(&tmpl, NFT_SET_EXT_KEY);
3229 3226
3230 if (nla[NFTA_SET_ELEM_DATA] != NULL) { 3227 if (nla[NFTA_SET_ELEM_DATA] != NULL) {
@@ -3266,6 +3263,7 @@ static int nft_add_set_elem(struct nft_ctx *ctx, struct nft_set *set,
3266 if (trans == NULL) 3263 if (trans == NULL)
3267 goto err4; 3264 goto err4;
3268 3265
3266 ext->genmask = nft_genmask_cur(ctx->net);
3269 err = set->ops->insert(set, &elem); 3267 err = set->ops->insert(set, &elem);
3270 if (err < 0) 3268 if (err < 0)
3271 goto err5; 3269 goto err5;
@@ -3353,19 +3351,24 @@ static int nft_del_setelem(struct nft_ctx *ctx, struct nft_set *set,
3353 if (desc.type != NFT_DATA_VALUE || desc.len != set->klen) 3351 if (desc.type != NFT_DATA_VALUE || desc.len != set->klen)
3354 goto err2; 3352 goto err2;
3355 3353
3356 err = set->ops->get(set, &elem);
3357 if (err < 0)
3358 goto err2;
3359
3360 trans = nft_trans_elem_alloc(ctx, NFT_MSG_DELSETELEM, set); 3354 trans = nft_trans_elem_alloc(ctx, NFT_MSG_DELSETELEM, set);
3361 if (trans == NULL) { 3355 if (trans == NULL) {
3362 err = -ENOMEM; 3356 err = -ENOMEM;
3363 goto err2; 3357 goto err2;
3364 } 3358 }
3365 3359
3360 elem.priv = set->ops->deactivate(set, &elem);
3361 if (elem.priv == NULL) {
3362 err = -ENOENT;
3363 goto err3;
3364 }
3365
3366 nft_trans_elem(trans) = elem; 3366 nft_trans_elem(trans) = elem;
3367 list_add_tail(&trans->list, &ctx->net->nft.commit_list); 3367 list_add_tail(&trans->list, &ctx->net->nft.commit_list);
3368 return 0; 3368 return 0;
3369
3370err3:
3371 kfree(trans);
3369err2: 3372err2:
3370 nft_data_uninit(&elem.key, desc.type); 3373 nft_data_uninit(&elem.key, desc.type);
3371err1: 3374err1:
@@ -3692,9 +3695,11 @@ static int nf_tables_commit(struct sk_buff *skb)
3692 NFT_MSG_DELSET, GFP_KERNEL); 3695 NFT_MSG_DELSET, GFP_KERNEL);
3693 break; 3696 break;
3694 case NFT_MSG_NEWSETELEM: 3697 case NFT_MSG_NEWSETELEM:
3695 nf_tables_setelem_notify(&trans->ctx, 3698 te = (struct nft_trans_elem *)trans->data;
3696 nft_trans_elem_set(trans), 3699
3697 &nft_trans_elem(trans), 3700 te->set->ops->activate(te->set, &te->elem);
3701 nf_tables_setelem_notify(&trans->ctx, te->set,
3702 &te->elem,
3698 NFT_MSG_NEWSETELEM, 0); 3703 NFT_MSG_NEWSETELEM, 0);
3699 nft_trans_destroy(trans); 3704 nft_trans_destroy(trans);
3700 break; 3705 break;
@@ -3704,7 +3709,6 @@ static int nf_tables_commit(struct sk_buff *skb)
3704 nf_tables_setelem_notify(&trans->ctx, te->set, 3709 nf_tables_setelem_notify(&trans->ctx, te->set,
3705 &te->elem, 3710 &te->elem,
3706 NFT_MSG_DELSETELEM, 0); 3711 NFT_MSG_DELSETELEM, 0);
3707 te->set->ops->get(te->set, &te->elem);
3708 te->set->ops->remove(te->set, &te->elem); 3712 te->set->ops->remove(te->set, &te->elem);
3709 break; 3713 break;
3710 } 3714 }
@@ -3812,11 +3816,14 @@ static int nf_tables_abort(struct sk_buff *skb)
3812 nft_trans_elem_set(trans)->nelems--; 3816 nft_trans_elem_set(trans)->nelems--;
3813 te = (struct nft_trans_elem *)trans->data; 3817 te = (struct nft_trans_elem *)trans->data;
3814 3818
3815 te->set->ops->get(te->set, &te->elem);
3816 te->set->ops->remove(te->set, &te->elem); 3819 te->set->ops->remove(te->set, &te->elem);
3817 break; 3820 break;
3818 case NFT_MSG_DELSETELEM: 3821 case NFT_MSG_DELSETELEM:
3822 te = (struct nft_trans_elem *)trans->data;
3823
3819 nft_trans_elem_set(trans)->nelems++; 3824 nft_trans_elem_set(trans)->nelems++;
3825 te->set->ops->activate(te->set, &te->elem);
3826
3820 nft_trans_destroy(trans); 3827 nft_trans_destroy(trans);
3821 break; 3828 break;
3822 } 3829 }
diff --git a/net/netfilter/nft_hash.c b/net/netfilter/nft_hash.c
index 5bee82195ef5..c7e1a9d7d46f 100644
--- a/net/netfilter/nft_hash.c
+++ b/net/netfilter/nft_hash.c
@@ -35,6 +35,7 @@ struct nft_hash_elem {
35struct nft_hash_cmp_arg { 35struct nft_hash_cmp_arg {
36 const struct nft_set *set; 36 const struct nft_set *set;
37 const struct nft_data *key; 37 const struct nft_data *key;
38 u8 genmask;
38}; 39};
39 40
40static const struct rhashtable_params nft_hash_params; 41static const struct rhashtable_params nft_hash_params;
@@ -61,6 +62,8 @@ static inline int nft_hash_cmp(struct rhashtable_compare_arg *arg,
61 62
62 if (nft_data_cmp(nft_set_ext_key(&he->ext), x->key, x->set->klen)) 63 if (nft_data_cmp(nft_set_ext_key(&he->ext), x->key, x->set->klen))
63 return 1; 64 return 1;
65 if (!nft_set_elem_active(&he->ext, x->genmask))
66 return 1;
64 return 0; 67 return 0;
65} 68}
66 69
@@ -71,6 +74,7 @@ static bool nft_hash_lookup(const struct nft_set *set,
71 struct nft_hash *priv = nft_set_priv(set); 74 struct nft_hash *priv = nft_set_priv(set);
72 const struct nft_hash_elem *he; 75 const struct nft_hash_elem *he;
73 struct nft_hash_cmp_arg arg = { 76 struct nft_hash_cmp_arg arg = {
77 .genmask = nft_genmask_cur(read_pnet(&set->pnet)),
74 .set = set, 78 .set = set,
75 .key = key, 79 .key = key,
76 }; 80 };
@@ -88,6 +92,7 @@ static int nft_hash_insert(const struct nft_set *set,
88 struct nft_hash *priv = nft_set_priv(set); 92 struct nft_hash *priv = nft_set_priv(set);
89 struct nft_hash_elem *he = elem->priv; 93 struct nft_hash_elem *he = elem->priv;
90 struct nft_hash_cmp_arg arg = { 94 struct nft_hash_cmp_arg arg = {
95 .genmask = nft_genmask_next(read_pnet(&set->pnet)),
91 .set = set, 96 .set = set,
92 .key = &elem->key, 97 .key = &elem->key,
93 }; 98 };
@@ -96,30 +101,39 @@ static int nft_hash_insert(const struct nft_set *set,
96 nft_hash_params); 101 nft_hash_params);
97} 102}
98 103
99static void nft_hash_remove(const struct nft_set *set, 104static void nft_hash_activate(const struct nft_set *set,
100 const struct nft_set_elem *elem) 105 const struct nft_set_elem *elem)
101{ 106{
102 struct nft_hash *priv = nft_set_priv(set); 107 struct nft_hash_elem *he = elem->priv;
103 108
104 rhashtable_remove_fast(&priv->ht, elem->cookie, nft_hash_params); 109 nft_set_elem_change_active(set, &he->ext);
105} 110}
106 111
107static int nft_hash_get(const struct nft_set *set, struct nft_set_elem *elem) 112static void *nft_hash_deactivate(const struct nft_set *set,
113 const struct nft_set_elem *elem)
108{ 114{
109 struct nft_hash *priv = nft_set_priv(set); 115 struct nft_hash *priv = nft_set_priv(set);
110 struct nft_hash_elem *he; 116 struct nft_hash_elem *he;
111 struct nft_hash_cmp_arg arg = { 117 struct nft_hash_cmp_arg arg = {
118 .genmask = nft_genmask_next(read_pnet(&set->pnet)),
112 .set = set, 119 .set = set,
113 .key = &elem->key, 120 .key = &elem->key,
114 }; 121 };
115 122
116 he = rhashtable_lookup_fast(&priv->ht, &arg, nft_hash_params); 123 he = rhashtable_lookup_fast(&priv->ht, &arg, nft_hash_params);
117 if (!he) 124 if (he != NULL)
118 return -ENOENT; 125 nft_set_elem_change_active(set, &he->ext);
119 126
120 elem->priv = he; 127 return he;
128}
121 129
122 return 0; 130static void nft_hash_remove(const struct nft_set *set,
131 const struct nft_set_elem *elem)
132{
133 struct nft_hash *priv = nft_set_priv(set);
134 struct nft_hash_elem *he = elem->priv;
135
136 rhashtable_remove_fast(&priv->ht, &he->node, nft_hash_params);
123} 137}
124 138
125static void nft_hash_walk(const struct nft_ctx *ctx, const struct nft_set *set, 139static void nft_hash_walk(const struct nft_ctx *ctx, const struct nft_set *set,
@@ -129,6 +143,7 @@ static void nft_hash_walk(const struct nft_ctx *ctx, const struct nft_set *set,
129 struct nft_hash_elem *he; 143 struct nft_hash_elem *he;
130 struct rhashtable_iter hti; 144 struct rhashtable_iter hti;
131 struct nft_set_elem elem; 145 struct nft_set_elem elem;
146 u8 genmask = nft_genmask_cur(read_pnet(&set->pnet));
132 int err; 147 int err;
133 148
134 err = rhashtable_walk_init(&priv->ht, &hti); 149 err = rhashtable_walk_init(&priv->ht, &hti);
@@ -155,6 +170,8 @@ static void nft_hash_walk(const struct nft_ctx *ctx, const struct nft_set *set,
155 170
156 if (iter->count < iter->skip) 171 if (iter->count < iter->skip)
157 goto cont; 172 goto cont;
173 if (!nft_set_elem_active(&he->ext, genmask))
174 goto cont;
158 175
159 elem.priv = he; 176 elem.priv = he;
160 177
@@ -241,8 +258,9 @@ static struct nft_set_ops nft_hash_ops __read_mostly = {
241 .estimate = nft_hash_estimate, 258 .estimate = nft_hash_estimate,
242 .init = nft_hash_init, 259 .init = nft_hash_init,
243 .destroy = nft_hash_destroy, 260 .destroy = nft_hash_destroy,
244 .get = nft_hash_get,
245 .insert = nft_hash_insert, 261 .insert = nft_hash_insert,
262 .activate = nft_hash_activate,
263 .deactivate = nft_hash_deactivate,
246 .remove = nft_hash_remove, 264 .remove = nft_hash_remove,
247 .lookup = nft_hash_lookup, 265 .lookup = nft_hash_lookup,
248 .walk = nft_hash_walk, 266 .walk = nft_hash_walk,
diff --git a/net/netfilter/nft_rbtree.c b/net/netfilter/nft_rbtree.c
index cbba755ebebc..42d0ca45fb9e 100644
--- a/net/netfilter/nft_rbtree.c
+++ b/net/netfilter/nft_rbtree.c
@@ -29,6 +29,7 @@ struct nft_rbtree_elem {
29 struct nft_set_ext ext; 29 struct nft_set_ext ext;
30}; 30};
31 31
32
32static bool nft_rbtree_lookup(const struct nft_set *set, 33static bool nft_rbtree_lookup(const struct nft_set *set,
33 const struct nft_data *key, 34 const struct nft_data *key,
34 const struct nft_set_ext **ext) 35 const struct nft_set_ext **ext)
@@ -36,6 +37,7 @@ static bool nft_rbtree_lookup(const struct nft_set *set,
36 const struct nft_rbtree *priv = nft_set_priv(set); 37 const struct nft_rbtree *priv = nft_set_priv(set);
37 const struct nft_rbtree_elem *rbe, *interval = NULL; 38 const struct nft_rbtree_elem *rbe, *interval = NULL;
38 const struct rb_node *parent; 39 const struct rb_node *parent;
40 u8 genmask = nft_genmask_cur(read_pnet(&set->pnet));
39 int d; 41 int d;
40 42
41 spin_lock_bh(&nft_rbtree_lock); 43 spin_lock_bh(&nft_rbtree_lock);
@@ -51,6 +53,10 @@ static bool nft_rbtree_lookup(const struct nft_set *set,
51 parent = parent->rb_right; 53 parent = parent->rb_right;
52 else { 54 else {
53found: 55found:
56 if (!nft_set_elem_active(&rbe->ext, genmask)) {
57 parent = parent->rb_left;
58 continue;
59 }
54 if (nft_set_ext_exists(&rbe->ext, NFT_SET_EXT_FLAGS) && 60 if (nft_set_ext_exists(&rbe->ext, NFT_SET_EXT_FLAGS) &&
55 *nft_set_ext_flags(&rbe->ext) & 61 *nft_set_ext_flags(&rbe->ext) &
56 NFT_SET_ELEM_INTERVAL_END) 62 NFT_SET_ELEM_INTERVAL_END)
@@ -77,6 +83,7 @@ static int __nft_rbtree_insert(const struct nft_set *set,
77 struct nft_rbtree *priv = nft_set_priv(set); 83 struct nft_rbtree *priv = nft_set_priv(set);
78 struct nft_rbtree_elem *rbe; 84 struct nft_rbtree_elem *rbe;
79 struct rb_node *parent, **p; 85 struct rb_node *parent, **p;
86 u8 genmask = nft_genmask_next(read_pnet(&set->pnet));
80 int d; 87 int d;
81 88
82 parent = NULL; 89 parent = NULL;
@@ -91,8 +98,11 @@ static int __nft_rbtree_insert(const struct nft_set *set,
91 p = &parent->rb_left; 98 p = &parent->rb_left;
92 else if (d > 0) 99 else if (d > 0)
93 p = &parent->rb_right; 100 p = &parent->rb_right;
94 else 101 else {
95 return -EEXIST; 102 if (nft_set_elem_active(&rbe->ext, genmask))
103 return -EEXIST;
104 p = &parent->rb_left;
105 }
96 } 106 }
97 rb_link_node(&new->node, parent, p); 107 rb_link_node(&new->node, parent, p);
98 rb_insert_color(&new->node, &priv->root); 108 rb_insert_color(&new->node, &priv->root);
@@ -116,18 +126,28 @@ static void nft_rbtree_remove(const struct nft_set *set,
116 const struct nft_set_elem *elem) 126 const struct nft_set_elem *elem)
117{ 127{
118 struct nft_rbtree *priv = nft_set_priv(set); 128 struct nft_rbtree *priv = nft_set_priv(set);
119 struct nft_rbtree_elem *rbe = elem->cookie; 129 struct nft_rbtree_elem *rbe = elem->priv;
120 130
121 spin_lock_bh(&nft_rbtree_lock); 131 spin_lock_bh(&nft_rbtree_lock);
122 rb_erase(&rbe->node, &priv->root); 132 rb_erase(&rbe->node, &priv->root);
123 spin_unlock_bh(&nft_rbtree_lock); 133 spin_unlock_bh(&nft_rbtree_lock);
124} 134}
125 135
126static int nft_rbtree_get(const struct nft_set *set, struct nft_set_elem *elem) 136static void nft_rbtree_activate(const struct nft_set *set,
137 const struct nft_set_elem *elem)
138{
139 struct nft_rbtree_elem *rbe = elem->priv;
140
141 nft_set_elem_change_active(set, &rbe->ext);
142}
143
144static void *nft_rbtree_deactivate(const struct nft_set *set,
145 const struct nft_set_elem *elem)
127{ 146{
128 const struct nft_rbtree *priv = nft_set_priv(set); 147 const struct nft_rbtree *priv = nft_set_priv(set);
129 const struct rb_node *parent = priv->root.rb_node; 148 const struct rb_node *parent = priv->root.rb_node;
130 struct nft_rbtree_elem *rbe; 149 struct nft_rbtree_elem *rbe;
150 u8 genmask = nft_genmask_cur(read_pnet(&set->pnet));
131 int d; 151 int d;
132 152
133 while (parent != NULL) { 153 while (parent != NULL) {
@@ -140,12 +160,15 @@ static int nft_rbtree_get(const struct nft_set *set, struct nft_set_elem *elem)
140 else if (d > 0) 160 else if (d > 0)
141 parent = parent->rb_right; 161 parent = parent->rb_right;
142 else { 162 else {
143 elem->cookie = rbe; 163 if (!nft_set_elem_active(&rbe->ext, genmask)) {
144 elem->priv = rbe; 164 parent = parent->rb_left;
145 return 0; 165 continue;
166 }
167 nft_set_elem_change_active(set, &rbe->ext);
168 return rbe;
146 } 169 }
147 } 170 }
148 return -ENOENT; 171 return NULL;
149} 172}
150 173
151static void nft_rbtree_walk(const struct nft_ctx *ctx, 174static void nft_rbtree_walk(const struct nft_ctx *ctx,
@@ -156,13 +179,17 @@ static void nft_rbtree_walk(const struct nft_ctx *ctx,
156 struct nft_rbtree_elem *rbe; 179 struct nft_rbtree_elem *rbe;
157 struct nft_set_elem elem; 180 struct nft_set_elem elem;
158 struct rb_node *node; 181 struct rb_node *node;
182 u8 genmask = nft_genmask_cur(read_pnet(&set->pnet));
159 183
160 spin_lock_bh(&nft_rbtree_lock); 184 spin_lock_bh(&nft_rbtree_lock);
161 for (node = rb_first(&priv->root); node != NULL; node = rb_next(node)) { 185 for (node = rb_first(&priv->root); node != NULL; node = rb_next(node)) {
186 rbe = rb_entry(node, struct nft_rbtree_elem, node);
187
162 if (iter->count < iter->skip) 188 if (iter->count < iter->skip)
163 goto cont; 189 goto cont;
190 if (!nft_set_elem_active(&rbe->ext, genmask))
191 goto cont;
164 192
165 rbe = rb_entry(node, struct nft_rbtree_elem, node);
166 elem.priv = rbe; 193 elem.priv = rbe;
167 194
168 iter->err = iter->fn(ctx, set, iter, &elem); 195 iter->err = iter->fn(ctx, set, iter, &elem);
@@ -228,7 +255,8 @@ static struct nft_set_ops nft_rbtree_ops __read_mostly = {
228 .destroy = nft_rbtree_destroy, 255 .destroy = nft_rbtree_destroy,
229 .insert = nft_rbtree_insert, 256 .insert = nft_rbtree_insert,
230 .remove = nft_rbtree_remove, 257 .remove = nft_rbtree_remove,
231 .get = nft_rbtree_get, 258 .deactivate = nft_rbtree_deactivate,
259 .activate = nft_rbtree_activate,
232 .lookup = nft_rbtree_lookup, 260 .lookup = nft_rbtree_lookup,
233 .walk = nft_rbtree_walk, 261 .walk = nft_rbtree_walk,
234 .features = NFT_SET_INTERVAL | NFT_SET_MAP, 262 .features = NFT_SET_INTERVAL | NFT_SET_MAP,