@@ -163,11 +163,6 @@ static int nft_bitwise_init(const struct nft_ctx *ctx,
163163 u32 len ;
164164 int err ;
165165
166- if (!tb [NFTA_BITWISE_SREG ] ||
167- !tb [NFTA_BITWISE_DREG ] ||
168- !tb [NFTA_BITWISE_LEN ])
169- return - EINVAL ;
170-
171166 err = nft_parse_u32_check (tb [NFTA_BITWISE_LEN ], U8_MAX , & len );
172167 if (err < 0 )
173168 return err ;
@@ -292,9 +287,143 @@ static const struct nft_expr_ops nft_bitwise_ops = {
292287 .offload = nft_bitwise_offload ,
293288};
294289
290+ static int
291+ nft_bitwise_extract_u32_data (const struct nlattr * const tb , u32 * out )
292+ {
293+ struct nft_data_desc desc ;
294+ struct nft_data data ;
295+ int err = 0 ;
296+
297+ err = nft_data_init (NULL , & data , sizeof (data ), & desc , tb );
298+ if (err < 0 )
299+ return err ;
300+
301+ if (desc .type != NFT_DATA_VALUE || desc .len != sizeof (u32 )) {
302+ err = - EINVAL ;
303+ goto err ;
304+ }
305+ * out = data .data [0 ];
306+ err :
307+ nft_data_release (& data , desc .type );
308+ return err ;
309+ }
310+
311+ static int nft_bitwise_fast_init (const struct nft_ctx * ctx ,
312+ const struct nft_expr * expr ,
313+ const struct nlattr * const tb [])
314+ {
315+ struct nft_bitwise_fast_expr * priv = nft_expr_priv (expr );
316+ int err ;
317+
318+ priv -> sreg = nft_parse_register (tb [NFTA_BITWISE_SREG ]);
319+ err = nft_validate_register_load (priv -> sreg , sizeof (u32 ));
320+ if (err < 0 )
321+ return err ;
322+
323+ priv -> dreg = nft_parse_register (tb [NFTA_BITWISE_DREG ]);
324+ err = nft_validate_register_store (ctx , priv -> dreg , NULL ,
325+ NFT_DATA_VALUE , sizeof (u32 ));
326+ if (err < 0 )
327+ return err ;
328+
329+ if (tb [NFTA_BITWISE_DATA ])
330+ return - EINVAL ;
331+
332+ if (!tb [NFTA_BITWISE_MASK ] ||
333+ !tb [NFTA_BITWISE_XOR ])
334+ return - EINVAL ;
335+
336+ err = nft_bitwise_extract_u32_data (tb [NFTA_BITWISE_MASK ], & priv -> mask );
337+ if (err < 0 )
338+ return err ;
339+
340+ err = nft_bitwise_extract_u32_data (tb [NFTA_BITWISE_XOR ], & priv -> xor );
341+ if (err < 0 )
342+ return err ;
343+
344+ return 0 ;
345+ }
346+
347+ static int
348+ nft_bitwise_fast_dump (struct sk_buff * skb , const struct nft_expr * expr )
349+ {
350+ const struct nft_bitwise_fast_expr * priv = nft_expr_priv (expr );
351+ struct nft_data data ;
352+
353+ if (nft_dump_register (skb , NFTA_BITWISE_SREG , priv -> sreg ))
354+ return -1 ;
355+ if (nft_dump_register (skb , NFTA_BITWISE_DREG , priv -> dreg ))
356+ return -1 ;
357+ if (nla_put_be32 (skb , NFTA_BITWISE_LEN , htonl (sizeof (u32 ))))
358+ return -1 ;
359+ if (nla_put_be32 (skb , NFTA_BITWISE_OP , htonl (NFT_BITWISE_BOOL )))
360+ return -1 ;
361+
362+ data .data [0 ] = priv -> mask ;
363+ if (nft_data_dump (skb , NFTA_BITWISE_MASK , & data ,
364+ NFT_DATA_VALUE , sizeof (u32 )) < 0 )
365+ return -1 ;
366+
367+ data .data [0 ] = priv -> xor ;
368+ if (nft_data_dump (skb , NFTA_BITWISE_XOR , & data ,
369+ NFT_DATA_VALUE , sizeof (u32 )) < 0 )
370+ return -1 ;
371+
372+ return 0 ;
373+ }
374+
375+ static int nft_bitwise_fast_offload (struct nft_offload_ctx * ctx ,
376+ struct nft_flow_rule * flow ,
377+ const struct nft_expr * expr )
378+ {
379+ const struct nft_bitwise_fast_expr * priv = nft_expr_priv (expr );
380+ struct nft_offload_reg * reg = & ctx -> regs [priv -> dreg ];
381+
382+ if (priv -> xor || priv -> sreg != priv -> dreg || reg -> len != sizeof (u32 ))
383+ return - EOPNOTSUPP ;
384+
385+ reg -> mask .data [0 ] = priv -> mask ;
386+ return 0 ;
387+ }
388+
389+ const struct nft_expr_ops nft_bitwise_fast_ops = {
390+ .type = & nft_bitwise_type ,
391+ .size = NFT_EXPR_SIZE (sizeof (struct nft_bitwise_fast_expr )),
392+ .eval = NULL , /* inlined */
393+ .init = nft_bitwise_fast_init ,
394+ .dump = nft_bitwise_fast_dump ,
395+ .offload = nft_bitwise_fast_offload ,
396+ };
397+
398+ static const struct nft_expr_ops *
399+ nft_bitwise_select_ops (const struct nft_ctx * ctx ,
400+ const struct nlattr * const tb [])
401+ {
402+ int err ;
403+ u32 len ;
404+
405+ if (!tb [NFTA_BITWISE_LEN ] ||
406+ !tb [NFTA_BITWISE_SREG ] ||
407+ !tb [NFTA_BITWISE_DREG ])
408+ return ERR_PTR (- EINVAL );
409+
410+ err = nft_parse_u32_check (tb [NFTA_BITWISE_LEN ], U8_MAX , & len );
411+ if (err < 0 )
412+ return ERR_PTR (err );
413+
414+ if (len != sizeof (u32 ))
415+ return & nft_bitwise_ops ;
416+
417+ if (tb [NFTA_BITWISE_OP ] &&
418+ ntohl (nla_get_be32 (tb [NFTA_BITWISE_OP ])) != NFT_BITWISE_BOOL )
419+ return & nft_bitwise_ops ;
420+
421+ return & nft_bitwise_fast_ops ;
422+ }
423+
295424struct nft_expr_type nft_bitwise_type __read_mostly = {
296425 .name = "bitwise" ,
297- .ops = & nft_bitwise_ops ,
426+ .select_ops = nft_bitwise_select_ops ,
298427 .policy = nft_bitwise_policy ,
299428 .maxattr = NFTA_BITWISE_MAX ,
300429 .owner = THIS_MODULE ,
0 commit comments