kernel: bump 4.14 to 4.14.93
[openwrt/staging/chunkeey.git] / target / linux / generic / hack-4.14 / 650-netfilter-add-xt_OFFLOAD-target.patch
index cb05cf8e1d27197d5eccd945c8f3a53d5c29090f..2044bfaeb8a6509eba456bf01d4357fe129686cc 100644 (file)
@@ -8,7 +8,7 @@ Signed-off-by: Felix Fietkau <nbd@nbd.name>
 
 --- a/net/ipv4/netfilter/Kconfig
 +++ b/net/ipv4/netfilter/Kconfig
-@@ -75,8 +75,6 @@ config NF_TABLES_ARP
+@@ -76,8 +76,6 @@ config NF_TABLES_ARP
        help
          This option enables the ARP support for nf_tables.
  
@@ -17,7 +17,7 @@ Signed-off-by: Felix Fietkau <nbd@nbd.name>
  config NF_FLOW_TABLE_IPV4
        tristate "Netfilter flow table IPv4 module"
        depends on NF_FLOW_TABLE
-@@ -85,6 +83,8 @@ config NF_FLOW_TABLE_IPV4
+@@ -86,6 +84,8 @@ config NF_FLOW_TABLE_IPV4
  
          To compile it as a module, choose M here.
  
@@ -28,7 +28,7 @@ Signed-off-by: Felix Fietkau <nbd@nbd.name>
        depends on !NF_CONNTRACK || NF_CONNTRACK
 --- a/net/ipv6/netfilter/Kconfig
 +++ b/net/ipv6/netfilter/Kconfig
-@@ -69,7 +69,6 @@ config NFT_FIB_IPV6
+@@ -97,7 +97,6 @@ config NFT_FIB_IPV6
          multicast or blackhole.
  
  endif # NF_TABLES_IPV6
@@ -36,7 +36,7 @@ Signed-off-by: Felix Fietkau <nbd@nbd.name>
  
  config NF_FLOW_TABLE_IPV6
        tristate "Netfilter flow table IPv6 module"
-@@ -79,6 +78,8 @@ config NF_FLOW_TABLE_IPV6
+@@ -107,6 +106,8 @@ config NF_FLOW_TABLE_IPV6
  
          To compile it as a module, choose M here.
  
@@ -47,7 +47,7 @@ Signed-off-by: Felix Fietkau <nbd@nbd.name>
        depends on !NF_CONNTRACK || NF_CONNTRACK
 --- a/net/netfilter/Kconfig
 +++ b/net/netfilter/Kconfig
-@@ -665,8 +665,6 @@ config NFT_FIB_NETDEV
+@@ -671,8 +671,6 @@ config NFT_FIB_NETDEV
  
  endif # NF_TABLES_NETDEV
  
@@ -56,7 +56,7 @@ Signed-off-by: Felix Fietkau <nbd@nbd.name>
  config NF_FLOW_TABLE_INET
        tristate "Netfilter flow table mixed IPv4/IPv6 module"
        depends on NF_FLOW_TABLE
-@@ -675,11 +673,12 @@ config NF_FLOW_TABLE_INET
+@@ -681,11 +679,12 @@ config NF_FLOW_TABLE_INET
  
          To compile it as a module, choose M here.
  
@@ -70,7 +70,7 @@ Signed-off-by: Felix Fietkau <nbd@nbd.name>
        help
          This option adds the flow table core infrastructure.
  
-@@ -968,6 +967,15 @@ config NETFILTER_XT_TARGET_NOTRACK
+@@ -974,6 +973,15 @@ config NETFILTER_XT_TARGET_NOTRACK
        depends on NETFILTER_ADVANCED
        select NETFILTER_XT_TARGET_CT
  
@@ -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
-@@ -0,0 +1,335 @@
+@@ -0,0 +1,368 @@
 +/*
 + * 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/netfilter/xt_FLOWOFFLOAD.h>
 +#include <net/ip.h>
 +#include <net/netfilter/nf_conntrack.h>
 +#include <net/netfilter/nf_flow_table.h>
@@ -121,6 +122,7 @@ Signed-off-by: Felix Fietkau <nbd@nbd.name>
 +struct xt_flowoffload_hook {
 +      struct hlist_node list;
 +      struct nf_hook_ops ops;
++      struct net *net;
 +      bool registered;
 +      bool used;
 +};
@@ -201,8 +203,9 @@ Signed-off-by: Felix Fietkau <nbd@nbd.name>
 +                      continue;
 +
 +              hook->registered = true;
++              hook->net = dev_net(hook->ops.dev);
 +              spin_unlock_bh(&hooks_lock);
-+              nf_register_net_hook(dev_net(hook->ops.dev), &hook->ops);
++              nf_register_net_hook(hook->net, &hook->ops);
 +              spin_lock_bh(&hooks_lock);
 +              goto restart;
 +      }
@@ -216,12 +219,12 @@ Signed-off-by: Felix Fietkau <nbd@nbd.name>
 +
 +restart:
 +      hlist_for_each_entry(hook, &hooks, list) {
-+              if (hook->used)
++              if (hook->used || !hook->registered)
 +                      continue;
 +
 +              hlist_del(&hook->list);
 +              spin_unlock_bh(&hooks_lock);
-+              nf_unregister_net_hook(dev_net(hook->ops.dev), &hook->ops);
++              nf_unregister_net_hook(hook->net, &hook->ops);
 +              kfree(hook);
 +              spin_lock_bh(&hooks_lock);
 +              goto restart;
@@ -288,29 +291,44 @@ Signed-off-by: Felix Fietkau <nbd@nbd.name>
 +      return false;
 +}
 +
-+static int
-+xt_flowoffload_route(struct sk_buff *skb, const struct nf_conn *ct,
-+                 const struct xt_action_param *par,
-+                 struct nf_flow_route *route, enum ip_conntrack_dir dir)
++static struct dst_entry *
++xt_flowoffload_dst(const struct nf_conn *ct, enum ip_conntrack_dir dir,
++                 const struct xt_action_param *par)
 +{
-+      struct dst_entry *this_dst = skb_dst(skb);
-+      struct dst_entry *other_dst = NULL;
++      struct dst_entry *dst = NULL;
 +      struct flowi fl;
 +
 +      memset(&fl, 0, sizeof(fl));
 +      switch (xt_family(par)) {
 +      case NFPROTO_IPV4:
-+              fl.u.ip4.daddr = ct->tuplehash[!dir].tuple.dst.u3.ip;
++              fl.u.ip4.daddr = ct->tuplehash[dir].tuple.src.u3.ip;
 +              break;
 +      case NFPROTO_IPV6:
-+              fl.u.ip6.daddr = ct->tuplehash[!dir].tuple.dst.u3.in6;
++              fl.u.ip6.saddr = ct->tuplehash[dir].tuple.dst.u3.in6;
++              fl.u.ip6.daddr = ct->tuplehash[dir].tuple.src.u3.in6;
 +              break;
 +      }
 +
-+      nf_route(xt_net(par), &other_dst, &fl, false, xt_family(par));
-+      if (!other_dst)
++      nf_route(xt_net(par), &dst, &fl, false, xt_family(par));
++
++      return dst;
++}
++
++static int
++xt_flowoffload_route(struct sk_buff *skb, const struct nf_conn *ct,
++                 const struct xt_action_param *par,
++                 struct nf_flow_route *route, enum ip_conntrack_dir dir)
++{
++      struct dst_entry *this_dst, *other_dst;
++
++      this_dst = xt_flowoffload_dst(ct, dir, par);
++      other_dst = xt_flowoffload_dst(ct, !dir, par);
++      if (!this_dst || !other_dst)
 +              return -ENOENT;
 +
++      if (dst_xfrm(this_dst) || dst_xfrm(other_dst))
++              return -EINVAL;
++
 +      route->tuple[dir].dst           = this_dst;
 +      route->tuple[dir].ifindex       = xt_in(par)->ifindex;
 +      route->tuple[!dir].dst          = other_dst;
@@ -322,6 +340,7 @@ Signed-off-by: Felix Fietkau <nbd@nbd.name>
 +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;
@@ -337,6 +356,9 @@ Signed-off-by: Felix Fietkau <nbd@nbd.name>
 +
 +      switch (ct->tuplehash[IP_CT_DIR_ORIGINAL].tuple.dst.protonum) {
 +      case IPPROTO_TCP:
++              if (ct->proto.tcp.state != TCP_CONNTRACK_ESTABLISHED)
++                      return XT_CONTINUE;
++              break;
 +      case IPPROTO_UDP:
 +              break;
 +      default:
@@ -371,6 +393,9 @@ Signed-off-by: Felix Fietkau <nbd@nbd.name>
 +      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:
@@ -385,6 +410,11 @@ Signed-off-by: Felix Fietkau <nbd@nbd.name>
 +
 +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;
 +}
 +
@@ -392,6 +422,8 @@ Signed-off-by: Felix Fietkau <nbd@nbd.name>
 +      .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,
@@ -399,6 +431,7 @@ Signed-off-by: Felix Fietkau <nbd@nbd.name>
 +
 +static int xt_flowoffload_table_init(struct nf_flowtable *table)
 +{
++      table->flags = NF_FLOWTABLE_F_HW;
 +      nf_flow_table_init(table);
 +      return 0;
 +}
@@ -444,3 +477,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>
+--- /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 */