@@ -127,6 +127,7 @@ enum nft_expr_track_type {
NFT_EXPR_UNSET = 0,
NFT_EXPR_PAYLOAD,
NFT_EXPR_META,
+ NFT_EXPR_BITWISE,
NFT_EXPR_CMP
};
@@ -152,6 +153,11 @@ struct nft_expr_track {
bool inv;
struct nft_data data;
} cmp;
+ struct {
+ u8 sreg;
+ u8 dreg;
+ struct nft_data mask;
+ } bitwise;
};
};
@@ -183,8 +189,8 @@ struct nft_combo_expr {
struct nft_exprs_track {
int num_exprs;
- struct nft_expr_track expr[2];
- const struct nft_expr *saved_expr[2];
+ struct nft_expr_track expr[3];
+ const struct nft_expr *saved_expr[3];
struct nft_combo_expr _expr;
};
@@ -155,7 +155,7 @@ void nft_objref_eval(const struct nft_expr *expr, struct nft_regs *regs,
void nft_objref_map_eval(const struct nft_expr *expr, struct nft_regs *regs,
const struct nft_pktinfo *pkt);
-void nft_payload_combo_init(struct nft_expr *expr, struct nft_exprs_track *track);
+void nft_payload_combo_init(struct nft_expr *expr, struct nft_exprs_track *track, bool mask);
void nft_meta_combo_init(struct nft_expr *expr, struct nft_exprs_track *track);
#endif /* _NET_NF_TABLES_CORE_H */
@@ -8934,7 +8934,7 @@ static int nft_expr_track(struct nft_exprs_track *expr_track,
switch (expr_track->expr[0].type) {
case NFT_EXPR_PAYLOAD:
if (expr_track->expr[1].type == NFT_EXPR_CMP) {
- nft_payload_combo_init((struct nft_expr *)&expr_track->_expr, expr_track);
+ nft_payload_combo_init((struct nft_expr *)&expr_track->_expr, expr_track, false);
expr_track->saved_expr[0] = (struct nft_expr *)&expr_track->_expr;
expr_track->num_exprs = 1;
return 1;
@@ -8948,6 +8948,24 @@ static int nft_expr_track(struct nft_exprs_track *expr_track,
return 1;
}
break;
+ case NFT_EXPR_BITWISE:
+ expr_track->num_exprs++;
+ return 0;
+ default:
+ return 1;
+ }
+ break;
+ case 2:
+ switch (expr_track->expr[0].type) {
+ case NFT_EXPR_PAYLOAD:
+ if (expr_track->expr[2].type == NFT_EXPR_CMP) {
+ nft_payload_combo_init((struct nft_expr *)&expr_track->_expr, expr_track, true);
+ expr_track->saved_expr[0] = (struct nft_expr *)&expr_track->_expr;
+ expr_track->num_exprs = 1;
+ pr_info("collapsing\n");
+ return 1;
+ }
+ break;
default:
return 1;
}
@@ -262,6 +262,25 @@ static int nft_bitwise_dump(struct sk_buff *skb,
static struct nft_data zero;
+static int nft_bitwise_track(struct nft_expr_track *track,
+ const struct nft_expr *expr)
+{
+ const struct nft_bitwise *priv = nft_expr_priv(expr);
+
+ if (priv->op != NFT_BITWISE_BOOL)
+ return 1;
+
+ if (memcmp(&priv->xor, &zero, sizeof(priv->xor)))
+ return 1;
+
+ track->type = NFT_EXPR_BITWISE;
+ track->bitwise.sreg = priv->sreg;
+ track->bitwise.dreg = priv->dreg;
+ memcpy(&track->bitwise.mask, &priv->mask, sizeof(priv->mask));
+
+ return 0;
+}
+
static int nft_bitwise_offload(struct nft_offload_ctx *ctx,
struct nft_flow_rule *flow,
const struct nft_expr *expr)
@@ -287,6 +306,7 @@ static const struct nft_expr_ops nft_bitwise_ops = {
.eval = nft_bitwise_eval,
.init = nft_bitwise_init,
.dump = nft_bitwise_dump,
+ .track = nft_bitwise_track,
.offload = nft_bitwise_offload,
};
@@ -1023,16 +1023,21 @@ void nft_cmp16_mask(struct nft_data *data, unsigned int len)
data->data[i] = 0;
}
-void nft_payload_combo_init(struct nft_expr *expr, struct nft_exprs_track *track)
+void nft_payload_combo_init(struct nft_expr *expr,
+ struct nft_exprs_track *track, bool bitmask)
{
struct nft_payload_combo *priv = nft_expr_priv(expr);
+ int index = bitmask ? 2 : 1;
expr->ops = &nft_payload_combo_ops;
priv->offset = track->expr[0].payload.offset;
priv->len = track->expr[0].payload.len;
- memcpy(&priv->data, &track->expr[1].cmp.data, sizeof(priv->data));
- priv->inv = track->expr[1].cmp.inv;
- nft_cmp16_mask(&priv->mask, track->expr[1].cmp.len);
+ memcpy(&priv->data, &track->expr[index].cmp.data, sizeof(priv->data));
+ priv->inv = track->expr[index].cmp.inv;
+ nft_cmp16_mask(&priv->mask, track->expr[index].cmp.len);
+
+ if (bitmask)
+ priv->mask.data[0] &= track->expr[1].bitwise.mask.data[0];
}
const struct nft_expr_ops nft_payload_combo_ops = {
This allows to coalesce payload + bitwise + cmp expression into one combo expression. This does not require updates on the datapath, the existing mask field is adjusted based on the bitwise mask. Signed-off-by: Pablo Neira Ayuso <pablo@netfilter.org> --- include/net/netfilter/nf_tables.h | 10 ++++++++-- include/net/netfilter/nf_tables_core.h | 2 +- net/netfilter/nf_tables_api.c | 20 +++++++++++++++++++- net/netfilter/nft_bitwise.c | 20 ++++++++++++++++++++ net/netfilter/nft_payload.c | 13 +++++++++---- 5 files changed, 57 insertions(+), 8 deletions(-)