@@ -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,
@@ -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);
@@ -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:
@@ -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;