@@ -83,14 +83,16 @@ static int nft_limit_init(struct nft_limit *limit,
83
83
return 0 ;
84
84
}
85
85
86
- static int nft_limit_dump (struct sk_buff * skb , const struct nft_limit * limit )
86
+ static int nft_limit_dump (struct sk_buff * skb , const struct nft_limit * limit ,
87
+ enum nft_limit_type type )
87
88
{
88
89
u64 secs = div_u64 (limit -> nsecs , NSEC_PER_SEC );
89
90
u64 rate = limit -> rate - limit -> burst ;
90
91
91
92
if (nla_put_be64 (skb , NFTA_LIMIT_RATE , cpu_to_be64 (rate )) ||
92
93
nla_put_be64 (skb , NFTA_LIMIT_UNIT , cpu_to_be64 (secs )) ||
93
- nla_put_be32 (skb , NFTA_LIMIT_BURST , htonl (limit -> burst )))
94
+ nla_put_be32 (skb , NFTA_LIMIT_BURST , htonl (limit -> burst )) ||
95
+ nla_put_be32 (skb , NFTA_LIMIT_TYPE , htonl (type )))
94
96
goto nla_put_failure ;
95
97
return 0 ;
96
98
@@ -117,6 +119,7 @@ static const struct nla_policy nft_limit_policy[NFTA_LIMIT_MAX + 1] = {
117
119
[NFTA_LIMIT_RATE ] = { .type = NLA_U64 },
118
120
[NFTA_LIMIT_UNIT ] = { .type = NLA_U64 },
119
121
[NFTA_LIMIT_BURST ] = { .type = NLA_U32 },
122
+ [NFTA_LIMIT_TYPE ] = { .type = NLA_U32 },
120
123
};
121
124
122
125
static int nft_limit_pkts_init (const struct nft_ctx * ctx ,
@@ -138,7 +141,7 @@ static int nft_limit_pkts_dump(struct sk_buff *skb, const struct nft_expr *expr)
138
141
{
139
142
const struct nft_limit_pkts * priv = nft_expr_priv (expr );
140
143
141
- return nft_limit_dump (skb , & priv -> limit );
144
+ return nft_limit_dump (skb , & priv -> limit , NFT_LIMIT_PKTS );
142
145
}
143
146
144
147
static struct nft_expr_type nft_limit_type ;
@@ -150,9 +153,61 @@ static const struct nft_expr_ops nft_limit_pkts_ops = {
150
153
.dump = nft_limit_pkts_dump ,
151
154
};
152
155
156
+ static void nft_limit_pkt_bytes_eval (const struct nft_expr * expr ,
157
+ struct nft_regs * regs ,
158
+ const struct nft_pktinfo * pkt )
159
+ {
160
+ struct nft_limit * priv = nft_expr_priv (expr );
161
+ u64 cost = div_u64 (priv -> nsecs * pkt -> skb -> len , priv -> rate );
162
+
163
+ if (nft_limit_eval (priv , cost ))
164
+ regs -> verdict .code = NFT_BREAK ;
165
+ }
166
+
167
+ static int nft_limit_pkt_bytes_init (const struct nft_ctx * ctx ,
168
+ const struct nft_expr * expr ,
169
+ const struct nlattr * const tb [])
170
+ {
171
+ struct nft_limit * priv = nft_expr_priv (expr );
172
+
173
+ return nft_limit_init (priv , tb );
174
+ }
175
+
176
+ static int nft_limit_pkt_bytes_dump (struct sk_buff * skb ,
177
+ const struct nft_expr * expr )
178
+ {
179
+ const struct nft_limit * priv = nft_expr_priv (expr );
180
+
181
+ return nft_limit_dump (skb , priv , NFT_LIMIT_PKT_BYTES );
182
+ }
183
+
184
+ static const struct nft_expr_ops nft_limit_pkt_bytes_ops = {
185
+ .type = & nft_limit_type ,
186
+ .size = NFT_EXPR_SIZE (sizeof (struct nft_limit )),
187
+ .eval = nft_limit_pkt_bytes_eval ,
188
+ .init = nft_limit_pkt_bytes_init ,
189
+ .dump = nft_limit_pkt_bytes_dump ,
190
+ };
191
+
192
+ static const struct nft_expr_ops *
193
+ nft_limit_select_ops (const struct nft_ctx * ctx ,
194
+ const struct nlattr * const tb [])
195
+ {
196
+ if (tb [NFTA_LIMIT_TYPE ] == NULL )
197
+ return & nft_limit_pkts_ops ;
198
+
199
+ switch (ntohl (nla_get_be32 (tb [NFTA_LIMIT_TYPE ]))) {
200
+ case NFT_LIMIT_PKTS :
201
+ return & nft_limit_pkts_ops ;
202
+ case NFT_LIMIT_PKT_BYTES :
203
+ return & nft_limit_pkt_bytes_ops ;
204
+ }
205
+ return ERR_PTR (- EOPNOTSUPP );
206
+ }
207
+
153
208
static struct nft_expr_type nft_limit_type __read_mostly = {
154
209
.name = "limit" ,
155
- .ops = & nft_limit_pkts_ops ,
210
+ .select_ops = nft_limit_select_ops ,
156
211
.policy = nft_limit_policy ,
157
212
.maxattr = NFTA_LIMIT_MAX ,
158
213
.flags = NFT_EXPR_STATEFUL ,
0 commit comments