@@ -24,28 +24,58 @@ struct nft_ng_inc {
24
24
u32 modulus ;
25
25
atomic_t counter ;
26
26
u32 offset ;
27
+ struct nft_set * map ;
27
28
};
28
29
29
- static void nft_ng_inc_eval (const struct nft_expr * expr ,
30
- struct nft_regs * regs ,
31
- const struct nft_pktinfo * pkt )
30
+ static u32 nft_ng_inc_gen (struct nft_ng_inc * priv )
32
31
{
33
- struct nft_ng_inc * priv = nft_expr_priv (expr );
34
32
u32 nval , oval ;
35
33
36
34
do {
37
35
oval = atomic_read (& priv -> counter );
38
36
nval = (oval + 1 < priv -> modulus ) ? oval + 1 : 0 ;
39
37
} while (atomic_cmpxchg (& priv -> counter , oval , nval ) != oval );
40
38
41
- regs -> data [priv -> dreg ] = nval + priv -> offset ;
39
+ return nval + priv -> offset ;
40
+ }
41
+
42
+ static void nft_ng_inc_eval (const struct nft_expr * expr ,
43
+ struct nft_regs * regs ,
44
+ const struct nft_pktinfo * pkt )
45
+ {
46
+ struct nft_ng_inc * priv = nft_expr_priv (expr );
47
+
48
+ regs -> data [priv -> dreg ] = nft_ng_inc_gen (priv );
49
+ }
50
+
51
+ static void nft_ng_inc_map_eval (const struct nft_expr * expr ,
52
+ struct nft_regs * regs ,
53
+ const struct nft_pktinfo * pkt )
54
+ {
55
+ struct nft_ng_inc * priv = nft_expr_priv (expr );
56
+ const struct nft_set * map = priv -> map ;
57
+ const struct nft_set_ext * ext ;
58
+ u32 result ;
59
+ bool found ;
60
+
61
+ result = nft_ng_inc_gen (priv );
62
+ found = map -> ops -> lookup (nft_net (pkt ), map , & result , & ext );
63
+
64
+ if (!found )
65
+ return ;
66
+
67
+ nft_data_copy (& regs -> data [priv -> dreg ],
68
+ nft_set_ext_data (ext ), map -> dlen );
42
69
}
43
70
44
71
static const struct nla_policy nft_ng_policy [NFTA_NG_MAX + 1 ] = {
45
72
[NFTA_NG_DREG ] = { .type = NLA_U32 },
46
73
[NFTA_NG_MODULUS ] = { .type = NLA_U32 },
47
74
[NFTA_NG_TYPE ] = { .type = NLA_U32 },
48
75
[NFTA_NG_OFFSET ] = { .type = NLA_U32 },
76
+ [NFTA_NG_SET_NAME ] = { .type = NLA_STRING ,
77
+ .len = NFT_SET_MAXNAMELEN - 1 },
78
+ [NFTA_NG_SET_ID ] = { .type = NLA_U32 },
49
79
};
50
80
51
81
static int nft_ng_inc_init (const struct nft_ctx * ctx ,
@@ -71,6 +101,25 @@ static int nft_ng_inc_init(const struct nft_ctx *ctx,
71
101
NFT_DATA_VALUE , sizeof (u32 ));
72
102
}
73
103
104
+ static int nft_ng_inc_map_init (const struct nft_ctx * ctx ,
105
+ const struct nft_expr * expr ,
106
+ const struct nlattr * const tb [])
107
+ {
108
+ struct nft_ng_inc * priv = nft_expr_priv (expr );
109
+ u8 genmask = nft_genmask_next (ctx -> net );
110
+
111
+ nft_ng_inc_init (ctx , expr , tb );
112
+
113
+ priv -> map = nft_set_lookup_global (ctx -> net , ctx -> table ,
114
+ tb [NFTA_NG_SET_NAME ],
115
+ tb [NFTA_NG_SET_ID ], genmask );
116
+
117
+ if (IS_ERR (priv -> map ))
118
+ return PTR_ERR (priv -> map );
119
+
120
+ return 0 ;
121
+ }
122
+
74
123
static int nft_ng_dump (struct sk_buff * skb , enum nft_registers dreg ,
75
124
u32 modulus , enum nft_ng_types type , u32 offset )
76
125
{
@@ -97,6 +146,22 @@ static int nft_ng_inc_dump(struct sk_buff *skb, const struct nft_expr *expr)
97
146
priv -> offset );
98
147
}
99
148
149
+ static int nft_ng_inc_map_dump (struct sk_buff * skb ,
150
+ const struct nft_expr * expr )
151
+ {
152
+ const struct nft_ng_inc * priv = nft_expr_priv (expr );
153
+
154
+ if (nft_ng_dump (skb , priv -> dreg , priv -> modulus ,
155
+ NFT_NG_INCREMENTAL , priv -> offset ) ||
156
+ nla_put_string (skb , NFTA_NG_SET_NAME , priv -> map -> name ))
157
+ goto nla_put_failure ;
158
+
159
+ return 0 ;
160
+
161
+ nla_put_failure :
162
+ return -1 ;
163
+ }
164
+
100
165
struct nft_ng_random {
101
166
enum nft_registers dreg :8 ;
102
167
u32 modulus ;
@@ -156,6 +221,14 @@ static const struct nft_expr_ops nft_ng_inc_ops = {
156
221
.dump = nft_ng_inc_dump ,
157
222
};
158
223
224
+ static const struct nft_expr_ops nft_ng_inc_map_ops = {
225
+ .type = & nft_ng_type ,
226
+ .size = NFT_EXPR_SIZE (sizeof (struct nft_ng_inc )),
227
+ .eval = nft_ng_inc_map_eval ,
228
+ .init = nft_ng_inc_map_init ,
229
+ .dump = nft_ng_inc_map_dump ,
230
+ };
231
+
159
232
static const struct nft_expr_ops nft_ng_random_ops = {
160
233
.type = & nft_ng_type ,
161
234
.size = NFT_EXPR_SIZE (sizeof (struct nft_ng_random )),
@@ -178,6 +251,8 @@ nft_ng_select_ops(const struct nft_ctx *ctx, const struct nlattr * const tb[])
178
251
179
252
switch (type ) {
180
253
case NFT_NG_INCREMENTAL :
254
+ if (tb [NFTA_NG_SET_NAME ])
255
+ return & nft_ng_inc_map_ops ;
181
256
return & nft_ng_inc_ops ;
182
257
case NFT_NG_RANDOM :
183
258
return & nft_ng_random_ops ;
0 commit comments