From: wenxu <wenxu@xxxxxxxxx> Currently the nft_offload_reg is only can be used for match condition. Can not be used for action. Add nft_offload_reg_type to make nft_offload_reg can be used for action also. Signed-off-by: wenxu <wenxu@xxxxxxxxx> --- include/net/netfilter/nf_tables_offload.h | 20 +++++++++++++++++- net/netfilter/nft_cmp.c | 10 ++++----- net/netfilter/nft_meta.c | 6 ++++-- net/netfilter/nft_payload.c | 34 ++++++++++++++++++++----------- 4 files changed, 50 insertions(+), 20 deletions(-) diff --git a/include/net/netfilter/nf_tables_offload.h b/include/net/netfilter/nf_tables_offload.h index 275d014..82e3936 100644 --- a/include/net/netfilter/nf_tables_offload.h +++ b/include/net/netfilter/nf_tables_offload.h @@ -4,7 +4,13 @@ #include <net/flow_offload.h> #include <net/netfilter/nf_tables.h> -struct nft_offload_reg { +enum nft_offload_reg_type { + NFT_OFFLOAD_REG_UNSPEC = 0, + NFT_OFFLOAD_REG_MATCH, + NFT_OFFLOAD_REG_ACTION, +}; + +struct nft_offload_match { u32 key; u32 len; u32 base_offset; @@ -12,6 +18,18 @@ struct nft_offload_reg { struct nft_data mask; }; +struct nft_offload_action { + struct nft_data data; +}; + +struct nft_offload_reg { + enum nft_offload_reg_type type; + union { + struct nft_offload_match match; + struct nft_offload_action action; + }; +}; + enum nft_offload_dep_type { NFT_OFFLOAD_DEP_UNSPEC = 0, NFT_OFFLOAD_DEP_NETWORK, diff --git a/net/netfilter/nft_cmp.c b/net/netfilter/nft_cmp.c index bd173b1..ee38cba 100644 --- a/net/netfilter/nft_cmp.c +++ b/net/netfilter/nft_cmp.c @@ -116,14 +116,14 @@ static int __nft_cmp_offload(struct nft_offload_ctx *ctx, u8 *mask = (u8 *)&flow->match.mask; u8 *key = (u8 *)&flow->match.key; - if (priv->op != NFT_CMP_EQ) + if (priv->op != NFT_CMP_EQ || reg->type != NFT_OFFLOAD_REG_MATCH) return -EOPNOTSUPP; - memcpy(key + reg->offset, &priv->data, priv->len); - memcpy(mask + reg->offset, ®->mask, priv->len); + memcpy(key + reg->match.offset, &priv->data, priv->len); + memcpy(mask + reg->match.offset, ®->match.mask, priv->len); - flow->match.dissector.used_keys |= BIT(reg->key); - flow->match.dissector.offset[reg->key] = reg->base_offset; + flow->match.dissector.used_keys |= BIT(reg->match.key); + flow->match.dissector.offset[reg->match.key] = reg->match.base_offset; nft_offload_update_dependency(ctx, &priv->data, priv->len); diff --git a/net/netfilter/nft_meta.c b/net/netfilter/nft_meta.c index f1b1d94..6bb5ba6 100644 --- a/net/netfilter/nft_meta.c +++ b/net/netfilter/nft_meta.c @@ -498,15 +498,17 @@ static int nft_meta_get_offload(struct nft_offload_ctx *ctx, const struct nft_meta *priv = nft_expr_priv(expr); struct nft_offload_reg *reg = &ctx->regs[priv->dreg]; + reg->type = NFT_OFFLOAD_REG_MATCH; + switch (priv->key) { case NFT_META_PROTOCOL: NFT_OFFLOAD_MATCH(FLOW_DISSECTOR_KEY_BASIC, basic, n_proto, - sizeof(__u16), reg); + sizeof(__u16), ®->match); nft_offload_set_dependency(ctx, NFT_OFFLOAD_DEP_NETWORK); break; case NFT_META_L4PROTO: NFT_OFFLOAD_MATCH(FLOW_DISSECTOR_KEY_BASIC, basic, ip_proto, - sizeof(__u8), reg); + sizeof(__u8), ®->match); nft_offload_set_dependency(ctx, NFT_OFFLOAD_DEP_TRANSPORT); break; default: diff --git a/net/netfilter/nft_payload.c b/net/netfilter/nft_payload.c index 22a80eb..36efa1c 100644 --- a/net/netfilter/nft_payload.c +++ b/net/netfilter/nft_payload.c @@ -159,14 +159,16 @@ static int nft_payload_offload_ll(struct nft_offload_ctx *ctx, { struct nft_offload_reg *reg = &ctx->regs[priv->dreg]; + reg->type = NFT_OFFLOAD_REG_MATCH; + switch (priv->offset) { case offsetof(struct ethhdr, h_source): NFT_OFFLOAD_MATCH(FLOW_DISSECTOR_KEY_ETH_ADDRS, eth_addrs, - src, ETH_ALEN, reg); + src, ETH_ALEN, ®->match); break; case offsetof(struct ethhdr, h_dest): NFT_OFFLOAD_MATCH(FLOW_DISSECTOR_KEY_ETH_ADDRS, eth_addrs, - dst, ETH_ALEN, reg); + dst, ETH_ALEN, ®->match); break; } @@ -179,18 +181,20 @@ static int nft_payload_offload_ip(struct nft_offload_ctx *ctx, { struct nft_offload_reg *reg = &ctx->regs[priv->dreg]; + reg->type = NFT_OFFLOAD_REG_MATCH; + switch (priv->offset) { case offsetof(struct iphdr, saddr): NFT_OFFLOAD_MATCH(FLOW_DISSECTOR_KEY_IPV4_ADDRS, ipv4, src, - sizeof(struct in_addr), reg); + sizeof(struct in_addr), ®->match); break; case offsetof(struct iphdr, daddr): NFT_OFFLOAD_MATCH(FLOW_DISSECTOR_KEY_IPV4_ADDRS, ipv4, dst, - sizeof(struct in_addr), reg); + sizeof(struct in_addr), ®->match); break; case offsetof(struct iphdr, protocol): NFT_OFFLOAD_MATCH(FLOW_DISSECTOR_KEY_BASIC, basic, ip_proto, - sizeof(__u8), reg); + sizeof(__u8), ®->match); nft_offload_set_dependency(ctx, NFT_OFFLOAD_DEP_TRANSPORT); break; default: @@ -206,18 +210,20 @@ static int nft_payload_offload_ip6(struct nft_offload_ctx *ctx, { struct nft_offload_reg *reg = &ctx->regs[priv->dreg]; + reg->type = NFT_OFFLOAD_REG_MATCH; + switch (priv->offset) { case offsetof(struct ipv6hdr, saddr): NFT_OFFLOAD_MATCH(FLOW_DISSECTOR_KEY_IPV6_ADDRS, ipv6, src, - sizeof(struct in6_addr), reg); + sizeof(struct in6_addr), ®->match); break; case offsetof(struct ipv6hdr, daddr): NFT_OFFLOAD_MATCH(FLOW_DISSECTOR_KEY_IPV6_ADDRS, ipv6, dst, - sizeof(struct in6_addr), reg); + sizeof(struct in6_addr), ®->match); break; case offsetof(struct ipv6hdr, nexthdr): NFT_OFFLOAD_MATCH(FLOW_DISSECTOR_KEY_BASIC, basic, ip_proto, - sizeof(__u8), reg); + sizeof(__u8), ®->match); nft_offload_set_dependency(ctx, NFT_OFFLOAD_DEP_TRANSPORT); break; default: @@ -253,14 +259,16 @@ static int nft_payload_offload_tcp(struct nft_offload_ctx *ctx, { struct nft_offload_reg *reg = &ctx->regs[priv->dreg]; + reg->type = NFT_OFFLOAD_REG_MATCH; + switch (priv->offset) { case offsetof(struct tcphdr, source): NFT_OFFLOAD_MATCH(FLOW_DISSECTOR_KEY_PORTS, tp, src, - sizeof(__be16), reg); + sizeof(__be16), ®->match); break; case offsetof(struct tcphdr, dest): NFT_OFFLOAD_MATCH(FLOW_DISSECTOR_KEY_PORTS, tp, dst, - sizeof(__be16), reg); + sizeof(__be16), ®->match); break; default: return -EOPNOTSUPP; @@ -275,14 +283,16 @@ static int nft_payload_offload_udp(struct nft_offload_ctx *ctx, { struct nft_offload_reg *reg = &ctx->regs[priv->dreg]; + reg->type = NFT_OFFLOAD_REG_MATCH; + switch (priv->offset) { case offsetof(struct udphdr, source): NFT_OFFLOAD_MATCH(FLOW_DISSECTOR_KEY_PORTS, tp, src, - sizeof(__be16), reg); + sizeof(__be16), ®->match); break; case offsetof(struct udphdr, dest): NFT_OFFLOAD_MATCH(FLOW_DISSECTOR_KEY_PORTS, tp, dst, - sizeof(__be16), reg); + sizeof(__be16), ®->match); break; default: return -EOPNOTSUPP; -- 1.8.3.1