@@ -75,32 +75,11 @@ static int nft_cmp_init(const struct nft_ctx *ctx, const struct nft_expr *expr,
7575 struct nft_data_desc desc ;
7676 int err ;
7777
78- if (tb [NFTA_CMP_SREG ] == NULL ||
79- tb [NFTA_CMP_OP ] == NULL ||
80- tb [NFTA_CMP_DATA ] == NULL )
81- return - EINVAL ;
82-
8378 priv -> sreg = ntohl (nla_get_be32 (tb [NFTA_CMP_SREG ]));
84- err = nft_validate_input_register (priv -> sreg );
85- if (err < 0 )
86- return err ;
87-
8879 priv -> op = ntohl (nla_get_be32 (tb [NFTA_CMP_OP ]));
89- switch (priv -> op ) {
90- case NFT_CMP_EQ :
91- case NFT_CMP_NEQ :
92- case NFT_CMP_LT :
93- case NFT_CMP_LTE :
94- case NFT_CMP_GT :
95- case NFT_CMP_GTE :
96- break ;
97- default :
98- return - EINVAL ;
99- }
10080
10181 err = nft_data_init (NULL , & priv -> data , & desc , tb [NFTA_CMP_DATA ]);
102- if (err < 0 )
103- return err ;
82+ BUG_ON (err < 0 );
10483
10584 priv -> len = desc .len ;
10685 return 0 ;
@@ -133,9 +112,100 @@ static const struct nft_expr_ops nft_cmp_ops = {
133112 .dump = nft_cmp_dump ,
134113};
135114
115+ static int nft_cmp_fast_init (const struct nft_ctx * ctx ,
116+ const struct nft_expr * expr ,
117+ const struct nlattr * const tb [])
118+ {
119+ struct nft_cmp_fast_expr * priv = nft_expr_priv (expr );
120+ struct nft_data_desc desc ;
121+ struct nft_data data ;
122+ u32 mask ;
123+ int err ;
124+
125+ priv -> sreg = ntohl (nla_get_be32 (tb [NFTA_CMP_SREG ]));
126+
127+ err = nft_data_init (NULL , & data , & desc , tb [NFTA_CMP_DATA ]);
128+ BUG_ON (err < 0 );
129+ desc .len *= BITS_PER_BYTE ;
130+
131+ mask = ~0U >> (sizeof (priv -> data ) * BITS_PER_BYTE - desc .len );
132+ priv -> data = data .data [0 ] & mask ;
133+ priv -> len = desc .len ;
134+ return 0 ;
135+ }
136+
137+ static int nft_cmp_fast_dump (struct sk_buff * skb , const struct nft_expr * expr )
138+ {
139+ const struct nft_cmp_fast_expr * priv = nft_expr_priv (expr );
140+ struct nft_data data ;
141+
142+ if (nla_put_be32 (skb , NFTA_CMP_SREG , htonl (priv -> sreg )))
143+ goto nla_put_failure ;
144+ if (nla_put_be32 (skb , NFTA_CMP_OP , htonl (NFT_CMP_EQ )))
145+ goto nla_put_failure ;
146+
147+ data .data [0 ] = priv -> data ;
148+ if (nft_data_dump (skb , NFTA_CMP_DATA , & data ,
149+ NFT_DATA_VALUE , priv -> len / BITS_PER_BYTE ) < 0 )
150+ goto nla_put_failure ;
151+ return 0 ;
152+
153+ nla_put_failure :
154+ return -1 ;
155+ }
156+
157+ const struct nft_expr_ops nft_cmp_fast_ops = {
158+ .type = & nft_cmp_type ,
159+ .size = NFT_EXPR_SIZE (sizeof (struct nft_cmp_fast_expr )),
160+ .eval = NULL , /* inlined */
161+ .init = nft_cmp_fast_init ,
162+ .dump = nft_cmp_fast_dump ,
163+ };
164+
165+ static const struct nft_expr_ops * nft_cmp_select_ops (const struct nlattr * const tb [])
166+ {
167+ struct nft_data_desc desc ;
168+ struct nft_data data ;
169+ enum nft_registers sreg ;
170+ enum nft_cmp_ops op ;
171+ int err ;
172+
173+ if (tb [NFTA_CMP_SREG ] == NULL ||
174+ tb [NFTA_CMP_OP ] == NULL ||
175+ tb [NFTA_CMP_DATA ] == NULL )
176+ return ERR_PTR (- EINVAL );
177+
178+ sreg = ntohl (nla_get_be32 (tb [NFTA_CMP_SREG ]));
179+ err = nft_validate_input_register (sreg );
180+ if (err < 0 )
181+ return ERR_PTR (err );
182+
183+ op = ntohl (nla_get_be32 (tb [NFTA_CMP_OP ]));
184+ switch (op ) {
185+ case NFT_CMP_EQ :
186+ case NFT_CMP_NEQ :
187+ case NFT_CMP_LT :
188+ case NFT_CMP_LTE :
189+ case NFT_CMP_GT :
190+ case NFT_CMP_GTE :
191+ break ;
192+ default :
193+ return ERR_PTR (- EINVAL );
194+ }
195+
196+ err = nft_data_init (NULL , & data , & desc , tb [NFTA_CMP_DATA ]);
197+ if (err < 0 )
198+ return ERR_PTR (err );
199+
200+ if (desc .len <= sizeof (u32 ) && op == NFT_CMP_EQ )
201+ return & nft_cmp_fast_ops ;
202+ else
203+ return & nft_cmp_ops ;
204+ }
205+
136206static struct nft_expr_type nft_cmp_type __read_mostly = {
137207 .name = "cmp" ,
138- .ops = & nft_cmp_ops ,
208+ .select_ops = nft_cmp_select_ops ,
139209 .policy = nft_cmp_policy ,
140210 .maxattr = NFTA_CMP_MAX ,
141211 .owner = THIS_MODULE ,
0 commit comments