kernel: add support for enabling hardware flow offload via iptables
authorFelix Fietkau <nbd@nbd.name>
Fri, 23 Mar 2018 11:53:44 +0000 (12:53 +0100)
committerFelix Fietkau <nbd@nbd.name>
Thu, 5 Apr 2018 16:12:30 +0000 (18:12 +0200)
Signed-off-by: Felix Fietkau <nbd@nbd.name>
package/network/utils/iptables/patches/800-flowoffload_target.patch
target/linux/generic/hack-4.14/650-netfilter-add-xt_OFFLOAD-target.patch

index c6fe65c..2f79ee8 100644 (file)
@@ -1,14 +1,71 @@
 --- /dev/null
 +++ b/extensions/libxt_FLOWOFFLOAD.c
 --- /dev/null
 +++ b/extensions/libxt_FLOWOFFLOAD.c
-@@ -0,0 +1,15 @@
+@@ -0,0 +1,72 @@
++#include <stdio.h>
 +#include <xtables.h>
 +#include <xtables.h>
++#include <linux/netfilter/xt_FLOWOFFLOAD.h>
++
++enum {
++    O_HW,
++};
++
++static void offload_help(void)
++{
++      printf(
++"FLOWOFFLOAD target options:\n"
++" --hw                                Enable hardware offload\n"
++      );
++}
++
++static const struct xt_option_entry offload_opts[] = {
++      {.name = "hw", .id = O_HW, .type = XTTYPE_NONE},
++      XTOPT_TABLEEND,
++};
++
++static void offload_parse(struct xt_option_call *cb)
++{
++      struct xt_flowoffload_target_info *info = cb->data;
++
++      xtables_option_parse(cb);
++      switch (cb->entry->id) {
++      case O_HW:
++              info->flags |= XT_FLOWOFFLOAD_HW;
++              break;
++      }
++}
++
++static void offload_print(const void *ip, const struct xt_entry_target *target, int numeric)
++{
++      const struct xt_flowoffload_target_info *info =
++              (const struct xt_flowoffload_target_info *)target->data;
++
++      printf(" FLOWOFFLOAD");
++      if (info->flags & XT_FLOWOFFLOAD_HW)
++              printf(" hw");
++}
++
++static void offload_save(const void *ip, const struct xt_entry_target *target)
++{
++      const struct xt_flowoffload_target_info *info =
++              (const struct xt_flowoffload_target_info *)target->data;
++
++      if (info->flags & XT_FLOWOFFLOAD_HW)
++              printf(" --hw");
++}
 +
 +static struct xtables_target offload_tg_reg[] = {
 +      {
 +
 +static struct xtables_target offload_tg_reg[] = {
 +      {
-+              .family        = NFPROTO_UNSPEC,
-+              .name          = "FLOWOFFLOAD",
-+              .revision      = 0,
-+              .version       = XTABLES_VERSION,
++              .family         = NFPROTO_UNSPEC,
++              .name           = "FLOWOFFLOAD",
++              .revision       = 0,
++              .version        = XTABLES_VERSION,
++              .size           = XT_ALIGN(sizeof(struct xt_flowoffload_target_info)),
++              .userspacesize  = sizeof(struct xt_flowoffload_target_info),
++              .help           = offload_help,
++              .print          = offload_print,
++              .save           = offload_save,
++              .x6_parse       = offload_parse,
++              .x6_options     = offload_opts,
 +      },
 +};
 +
 +      },
 +};
 +
 +{
 +      xtables_register_targets(offload_tg_reg, ARRAY_SIZE(offload_tg_reg));
 +}
 +{
 +      xtables_register_targets(offload_tg_reg, ARRAY_SIZE(offload_tg_reg));
 +}
+--- /dev/null
++++ b/include/linux/netfilter/xt_FLOWOFFLOAD.h
+@@ -0,0 +1,17 @@
++/* SPDX-License-Identifier: GPL-2.0 WITH Linux-syscall-note */
++#ifndef _XT_FLOWOFFLOAD_H
++#define _XT_FLOWOFFLOAD_H
++
++#include <linux/types.h>
++
++enum {
++      XT_FLOWOFFLOAD_HW       = 1 << 0,
++
++      XT_FLOWOFFLOAD_MASK     = XT_FLOWOFFLOAD_HW
++};
++
++struct xt_flowoffload_target_info {
++      __u32 flags;
++};
++
++#endif /* _XT_FLOWOFFLOAD_H */
index 7296cfa..a322e60 100644 (file)
@@ -98,7 +98,7 @@ Signed-off-by: Felix Fietkau <nbd@nbd.name>
  obj-$(CONFIG_NETFILTER_XT_TARGET_LED) += xt_LED.o
 --- /dev/null
 +++ b/net/netfilter/xt_FLOWOFFLOAD.c
  obj-$(CONFIG_NETFILTER_XT_TARGET_LED) += xt_LED.o
 --- /dev/null
 +++ b/net/netfilter/xt_FLOWOFFLOAD.c
-@@ -0,0 +1,351 @@
+@@ -0,0 +1,364 @@
 +/*
 + * Copyright (C) 2018 Felix Fietkau <nbd@nbd.name>
 + *
 +/*
 + * Copyright (C) 2018 Felix Fietkau <nbd@nbd.name>
 + *
@@ -109,6 +109,7 @@ Signed-off-by: Felix Fietkau <nbd@nbd.name>
 +#include <linux/module.h>
 +#include <linux/init.h>
 +#include <linux/netfilter.h>
 +#include <linux/module.h>
 +#include <linux/init.h>
 +#include <linux/netfilter.h>
++#include <linux/netfilter/xt_FLOWOFFLOAD.h>
 +#include <net/ip.h>
 +#include <net/netfilter/nf_conntrack.h>
 +#include <net/netfilter/nf_flow_table.h>
 +#include <net/ip.h>
 +#include <net/netfilter/nf_conntrack.h>
 +#include <net/netfilter/nf_flow_table.h>
@@ -335,6 +336,7 @@ Signed-off-by: Felix Fietkau <nbd@nbd.name>
 +static unsigned int
 +flowoffload_tg(struct sk_buff *skb, const struct xt_action_param *par)
 +{
 +static unsigned int
 +flowoffload_tg(struct sk_buff *skb, const struct xt_action_param *par)
 +{
++      const struct xt_flowoffload_target_info *info = par->targinfo;
 +      enum ip_conntrack_info ctinfo;
 +      enum ip_conntrack_dir dir;
 +      struct nf_flow_route route;
 +      enum ip_conntrack_info ctinfo;
 +      enum ip_conntrack_dir dir;
 +      struct nf_flow_route route;
@@ -387,6 +389,9 @@ Signed-off-by: Felix Fietkau <nbd@nbd.name>
 +      xt_flowoffload_check_device(xt_in(par));
 +      xt_flowoffload_check_device(xt_out(par));
 +
 +      xt_flowoffload_check_device(xt_in(par));
 +      xt_flowoffload_check_device(xt_out(par));
 +
++      if (info->flags & XT_FLOWOFFLOAD_HW)
++              nf_flow_offload_hw_add(xt_net(par), flow, ct);
++
 +      return XT_CONTINUE;
 +
 +err_flow_add:
 +      return XT_CONTINUE;
 +
 +err_flow_add:
@@ -401,6 +406,11 @@ Signed-off-by: Felix Fietkau <nbd@nbd.name>
 +
 +static int flowoffload_chk(const struct xt_tgchk_param *par)
 +{
 +
 +static int flowoffload_chk(const struct xt_tgchk_param *par)
 +{
++      struct xt_flowoffload_target_info *info = par->targinfo;
++
++      if (info->flags & ~XT_FLOWOFFLOAD_MASK)
++              return -EINVAL;
++
 +      return 0;
 +}
 +
 +      return 0;
 +}
 +
@@ -408,6 +418,8 @@ Signed-off-by: Felix Fietkau <nbd@nbd.name>
 +      .family         = NFPROTO_UNSPEC,
 +      .name           = "FLOWOFFLOAD",
 +      .revision       = 0,
 +      .family         = NFPROTO_UNSPEC,
 +      .name           = "FLOWOFFLOAD",
 +      .revision       = 0,
++      .targetsize     = sizeof(struct xt_flowoffload_target_info),
++      .usersize       = sizeof(struct xt_flowoffload_target_info),
 +      .checkentry     = flowoffload_chk,
 +      .target         = flowoffload_tg,
 +      .me             = THIS_MODULE,
 +      .checkentry     = flowoffload_chk,
 +      .target         = flowoffload_tg,
 +      .me             = THIS_MODULE,
@@ -415,6 +427,7 @@ Signed-off-by: Felix Fietkau <nbd@nbd.name>
 +
 +static int xt_flowoffload_table_init(struct nf_flowtable *table)
 +{
 +
 +static int xt_flowoffload_table_init(struct nf_flowtable *table)
 +{
++      table->flags = NF_FLOWTABLE_F_HW;
 +      nf_flow_table_init(table);
 +      return 0;
 +}
 +      nf_flow_table_init(table);
 +      return 0;
 +}
@@ -460,3 +473,23 @@ Signed-off-by: Felix Fietkau <nbd@nbd.name>
  #include <net/netfilter/nf_flow_table.h>
  #include <net/netfilter/nf_conntrack.h>
  #include <net/netfilter/nf_conntrack_core.h>
  #include <net/netfilter/nf_flow_table.h>
  #include <net/netfilter/nf_conntrack.h>
  #include <net/netfilter/nf_conntrack_core.h>
+--- /dev/null
++++ b/include/uapi/linux/netfilter/xt_FLOWOFFLOAD.h
+@@ -0,0 +1,17 @@
++/* SPDX-License-Identifier: GPL-2.0 WITH Linux-syscall-note */
++#ifndef _XT_FLOWOFFLOAD_H
++#define _XT_FLOWOFFLOAD_H
++
++#include <linux/types.h>
++
++enum {
++      XT_FLOWOFFLOAD_HW       = 1 << 0,
++
++      XT_FLOWOFFLOAD_MASK     = XT_FLOWOFFLOAD_HW
++};
++
++struct xt_flowoffload_target_info {
++      __u32 flags;
++};
++
++#endif /* _XT_FLOWOFFLOAD_H */