@@ -15,6 +15,7 @@
#include <net/netfilter/nf_dup_netdev.h>
#include <net/neighbour.h>
#include <net/ip.h>
+#include <net/netfilter/nf_tables_offload.h>
struct nft_fwd_netdev {
enum nft_registers sreg_dev:8;
@@ -63,6 +64,33 @@ static int nft_fwd_netdev_dump(struct sk_buff *skb, const struct nft_expr *expr)
return -1;
}
+static int nft_fwd_netdev_offload(struct nft_offload_ctx *ctx,
+ struct nft_flow_rule *flow,
+ const struct nft_expr *expr)
+{
+ const struct nft_fwd_netdev *priv = nft_expr_priv(expr);
+ struct nft_offload_reg *reg = &ctx->regs[priv->sreg_dev];
+ const struct nft_data *data = ®->action.data;
+ struct flow_action_entry *entry;
+ struct net_device *dev;
+ int oif = -1;
+
+ if (reg->type != NFT_OFFLOAD_REG_ACTION)
+ return -EOPNOTSUPP;
+
+ entry = &flow->rule->action.entries[ctx->num_actions++];
+
+ memcpy(&oif, data->data, sizeof(oif));
+ dev = __dev_get_by_index(ctx->net, oif);
+ if (!dev)
+ return -EOPNOTSUPP;
+
+ entry->id = FLOW_ACTION_REDIRECT;
+ entry->dev = dev;
+
+ return 0;
+}
+
struct nft_fwd_neigh {
enum nft_registers sreg_dev:8;
enum nft_registers sreg_addr:8;
@@ -194,6 +222,8 @@ static int nft_fwd_neigh_dump(struct sk_buff *skb, const struct nft_expr *expr)
.eval = nft_fwd_netdev_eval,
.init = nft_fwd_netdev_init,
.dump = nft_fwd_netdev_dump,
+ .offload = nft_fwd_netdev_offload,
+ .offload_actions = nft_offload_action,
};
static const struct nft_expr_ops *