@@ -83,14 +83,16 @@ static int nft_limit_init(struct nft_limit *limit,
8383 return 0 ;
8484}
8585
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 )
8788{
8889 u64 secs = div_u64 (limit -> nsecs , NSEC_PER_SEC );
8990 u64 rate = limit -> rate - limit -> burst ;
9091
9192 if (nla_put_be64 (skb , NFTA_LIMIT_RATE , cpu_to_be64 (rate )) ||
9293 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 )))
9496 goto nla_put_failure ;
9597 return 0 ;
9698
@@ -117,6 +119,7 @@ static const struct nla_policy nft_limit_policy[NFTA_LIMIT_MAX + 1] = {
117119 [NFTA_LIMIT_RATE ] = { .type = NLA_U64 },
118120 [NFTA_LIMIT_UNIT ] = { .type = NLA_U64 },
119121 [NFTA_LIMIT_BURST ] = { .type = NLA_U32 },
122+ [NFTA_LIMIT_TYPE ] = { .type = NLA_U32 },
120123};
121124
122125static 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)
138141{
139142 const struct nft_limit_pkts * priv = nft_expr_priv (expr );
140143
141- return nft_limit_dump (skb , & priv -> limit );
144+ return nft_limit_dump (skb , & priv -> limit , NFT_LIMIT_PKTS );
142145}
143146
144147static struct nft_expr_type nft_limit_type ;
@@ -150,9 +153,61 @@ static const struct nft_expr_ops nft_limit_pkts_ops = {
150153 .dump = nft_limit_pkts_dump ,
151154};
152155
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+
153208static struct nft_expr_type nft_limit_type __read_mostly = {
154209 .name = "limit" ,
155- .ops = & nft_limit_pkts_ops ,
210+ .select_ops = nft_limit_select_ops ,
156211 .policy = nft_limit_policy ,
157212 .maxattr = NFTA_LIMIT_MAX ,
158213 .flags = NFT_EXPR_STATEFUL ,
0 commit comments