aboutsummaryrefslogtreecommitdiffstats
path: root/target/linux/generic/backport-4.14/357-netfilter-nf_flow_table-move-init-code-to-nf_flow_ta.patch
diff options
context:
space:
mode:
authorFelix Fietkau <nbd@nbd.name>2018-02-05 13:35:24 +0100
committerFelix Fietkau <nbd@nbd.name>2018-02-21 20:12:42 +0100
commit103335644265d96c656a7de3d5994fbd11246300 (patch)
tree2b19dea75e812b8240d6a458f0ed6dd22a8148b2 /target/linux/generic/backport-4.14/357-netfilter-nf_flow_table-move-init-code-to-nf_flow_ta.patch
parentb7265c59ab7dd0ec5dccb96e7b0dc1432404feb7 (diff)
downloadupstream-103335644265d96c656a7de3d5994fbd11246300.tar.gz
upstream-103335644265d96c656a7de3d5994fbd11246300.tar.bz2
upstream-103335644265d96c656a7de3d5994fbd11246300.zip
kernel: backport netfilter NAT offload support to 4.14
This only works with nftables for now, iptables support will be added later. Includes a number of related upstream nftables improvements to simplify backporting follow-up changes Signed-off-by: John Crispin <john@phrozen.org> Signed-off-by: Felix Fietkau <nbd@nbd.name>
Diffstat (limited to 'target/linux/generic/backport-4.14/357-netfilter-nf_flow_table-move-init-code-to-nf_flow_ta.patch')
-rw-r--r--target/linux/generic/backport-4.14/357-netfilter-nf_flow_table-move-init-code-to-nf_flow_ta.patch298
1 files changed, 298 insertions, 0 deletions
diff --git a/target/linux/generic/backport-4.14/357-netfilter-nf_flow_table-move-init-code-to-nf_flow_ta.patch b/target/linux/generic/backport-4.14/357-netfilter-nf_flow_table-move-init-code-to-nf_flow_ta.patch
new file mode 100644
index 0000000000..75cbda6baf
--- /dev/null
+++ b/target/linux/generic/backport-4.14/357-netfilter-nf_flow_table-move-init-code-to-nf_flow_ta.patch
@@ -0,0 +1,298 @@
+From: Felix Fietkau <nbd@nbd.name>
+Date: Sun, 18 Feb 2018 18:16:31 +0100
+Subject: [PATCH] netfilter: nf_flow_table: move init code to
+ nf_flow_table_core.c
+
+Reduces duplication of .gc and .params in flowtable type definitions and
+makes the API clearer
+
+Signed-off-by: Felix Fietkau <nbd@nbd.name>
+---
+
+--- a/include/net/netfilter/nf_flow_table.h
++++ b/include/net/netfilter/nf_flow_table.h
+@@ -14,9 +14,8 @@ struct nf_flowtable;
+ struct nf_flowtable_type {
+ struct list_head list;
+ int family;
+- void (*gc)(struct work_struct *work);
++ int (*init)(struct nf_flowtable *ft);
+ void (*free)(struct nf_flowtable *ft);
+- const struct rhashtable_params *params;
+ nf_hookfn *hook;
+ struct module *owner;
+ };
+@@ -100,9 +99,8 @@ int nf_flow_table_iterate(struct nf_flow
+
+ void nf_flow_table_cleanup(struct net *net, struct net_device *dev);
+
++int nf_flow_table_init(struct nf_flowtable *flow_table);
+ void nf_flow_table_free(struct nf_flowtable *flow_table);
+-void nf_flow_offload_work_gc(struct work_struct *work);
+-extern const struct rhashtable_params nf_flow_offload_rhash_params;
+
+ void flow_offload_dead(struct flow_offload *flow);
+
+--- a/net/ipv4/netfilter/nf_flow_table_ipv4.c
++++ b/net/ipv4/netfilter/nf_flow_table_ipv4.c
+@@ -7,8 +7,7 @@
+
+ static struct nf_flowtable_type flowtable_ipv4 = {
+ .family = NFPROTO_IPV4,
+- .params = &nf_flow_offload_rhash_params,
+- .gc = nf_flow_offload_work_gc,
++ .init = nf_flow_table_init,
+ .free = nf_flow_table_free,
+ .hook = nf_flow_offload_ip_hook,
+ .owner = THIS_MODULE,
+--- a/net/ipv6/netfilter/nf_flow_table_ipv6.c
++++ b/net/ipv6/netfilter/nf_flow_table_ipv6.c
+@@ -8,8 +8,7 @@
+
+ static struct nf_flowtable_type flowtable_ipv6 = {
+ .family = NFPROTO_IPV6,
+- .params = &nf_flow_offload_rhash_params,
+- .gc = nf_flow_offload_work_gc,
++ .init = nf_flow_table_init,
+ .free = nf_flow_table_free,
+ .hook = nf_flow_offload_ipv6_hook,
+ .owner = THIS_MODULE,
+--- a/net/netfilter/nf_flow_table_core.c
++++ b/net/netfilter/nf_flow_table_core.c
+@@ -116,16 +116,50 @@ void flow_offload_dead(struct flow_offlo
+ }
+ EXPORT_SYMBOL_GPL(flow_offload_dead);
+
++static u32 flow_offload_hash(const void *data, u32 len, u32 seed)
++{
++ const struct flow_offload_tuple *tuple = data;
++
++ return jhash(tuple, offsetof(struct flow_offload_tuple, dir), seed);
++}
++
++static u32 flow_offload_hash_obj(const void *data, u32 len, u32 seed)
++{
++ const struct flow_offload_tuple_rhash *tuplehash = data;
++
++ return jhash(&tuplehash->tuple, offsetof(struct flow_offload_tuple, dir), seed);
++}
++
++static int flow_offload_hash_cmp(struct rhashtable_compare_arg *arg,
++ const void *ptr)
++{
++ const struct flow_offload_tuple *tuple = arg->key;
++ const struct flow_offload_tuple_rhash *x = ptr;
++
++ if (memcmp(&x->tuple, tuple, offsetof(struct flow_offload_tuple, dir)))
++ return 1;
++
++ return 0;
++}
++
++static const struct rhashtable_params nf_flow_offload_rhash_params = {
++ .head_offset = offsetof(struct flow_offload_tuple_rhash, node),
++ .hashfn = flow_offload_hash,
++ .obj_hashfn = flow_offload_hash_obj,
++ .obj_cmpfn = flow_offload_hash_cmp,
++ .automatic_shrinking = true,
++};
++
+ int flow_offload_add(struct nf_flowtable *flow_table, struct flow_offload *flow)
+ {
+ flow->timeout = (u32)jiffies;
+
+ rhashtable_insert_fast(&flow_table->rhashtable,
+ &flow->tuplehash[FLOW_OFFLOAD_DIR_ORIGINAL].node,
+- *flow_table->type->params);
++ nf_flow_offload_rhash_params);
+ rhashtable_insert_fast(&flow_table->rhashtable,
+ &flow->tuplehash[FLOW_OFFLOAD_DIR_REPLY].node,
+- *flow_table->type->params);
++ nf_flow_offload_rhash_params);
+ return 0;
+ }
+ EXPORT_SYMBOL_GPL(flow_offload_add);
+@@ -135,10 +169,10 @@ static void flow_offload_del(struct nf_f
+ {
+ rhashtable_remove_fast(&flow_table->rhashtable,
+ &flow->tuplehash[FLOW_OFFLOAD_DIR_ORIGINAL].node,
+- *flow_table->type->params);
++ nf_flow_offload_rhash_params);
+ rhashtable_remove_fast(&flow_table->rhashtable,
+ &flow->tuplehash[FLOW_OFFLOAD_DIR_REPLY].node,
+- *flow_table->type->params);
++ nf_flow_offload_rhash_params);
+
+ flow_offload_free(flow);
+ }
+@@ -148,7 +182,7 @@ flow_offload_lookup(struct nf_flowtable
+ struct flow_offload_tuple *tuple)
+ {
+ return rhashtable_lookup_fast(&flow_table->rhashtable, tuple,
+- *flow_table->type->params);
++ nf_flow_offload_rhash_params);
+ }
+ EXPORT_SYMBOL_GPL(flow_offload_lookup);
+
+@@ -237,7 +271,7 @@ out:
+ return 1;
+ }
+
+-void nf_flow_offload_work_gc(struct work_struct *work)
++static void nf_flow_offload_work_gc(struct work_struct *work)
+ {
+ struct nf_flowtable *flow_table;
+
+@@ -245,42 +279,6 @@ void nf_flow_offload_work_gc(struct work
+ nf_flow_offload_gc_step(flow_table);
+ queue_delayed_work(system_power_efficient_wq, &flow_table->gc_work, HZ);
+ }
+-EXPORT_SYMBOL_GPL(nf_flow_offload_work_gc);
+-
+-static u32 flow_offload_hash(const void *data, u32 len, u32 seed)
+-{
+- const struct flow_offload_tuple *tuple = data;
+-
+- return jhash(tuple, offsetof(struct flow_offload_tuple, dir), seed);
+-}
+-
+-static u32 flow_offload_hash_obj(const void *data, u32 len, u32 seed)
+-{
+- const struct flow_offload_tuple_rhash *tuplehash = data;
+-
+- return jhash(&tuplehash->tuple, offsetof(struct flow_offload_tuple, dir), seed);
+-}
+-
+-static int flow_offload_hash_cmp(struct rhashtable_compare_arg *arg,
+- const void *ptr)
+-{
+- const struct flow_offload_tuple *tuple = arg->key;
+- const struct flow_offload_tuple_rhash *x = ptr;
+-
+- if (memcmp(&x->tuple, tuple, offsetof(struct flow_offload_tuple, dir)))
+- return 1;
+-
+- return 0;
+-}
+-
+-const struct rhashtable_params nf_flow_offload_rhash_params = {
+- .head_offset = offsetof(struct flow_offload_tuple_rhash, node),
+- .hashfn = flow_offload_hash,
+- .obj_hashfn = flow_offload_hash_obj,
+- .obj_cmpfn = flow_offload_hash_cmp,
+- .automatic_shrinking = true,
+-};
+-EXPORT_SYMBOL_GPL(nf_flow_offload_rhash_params);
+
+ static int nf_flow_nat_port_tcp(struct sk_buff *skb, unsigned int thoff,
+ __be16 port, __be16 new_port)
+@@ -398,6 +396,24 @@ int nf_flow_dnat_port(const struct flow_
+ }
+ EXPORT_SYMBOL_GPL(nf_flow_dnat_port);
+
++int nf_flow_table_init(struct nf_flowtable *flowtable)
++{
++ int err;
++
++ INIT_DEFERRABLE_WORK(&flowtable->gc_work, nf_flow_offload_work_gc);
++
++ err = rhashtable_init(&flowtable->rhashtable,
++ &nf_flow_offload_rhash_params);
++ if (err < 0)
++ return err;
++
++ queue_delayed_work(system_power_efficient_wq,
++ &flowtable->gc_work, HZ);
++
++ return 0;
++}
++EXPORT_SYMBOL_GPL(nf_flow_table_init);
++
+ static void nf_flow_table_do_cleanup(struct flow_offload *flow, void *data)
+ {
+ struct net_device *dev = data;
+@@ -423,8 +439,10 @@ EXPORT_SYMBOL_GPL(nf_flow_table_cleanup)
+
+ void nf_flow_table_free(struct nf_flowtable *flow_table)
+ {
++ cancel_delayed_work_sync(&flow_table->gc_work);
+ nf_flow_table_iterate(flow_table, nf_flow_table_do_cleanup, NULL);
+ WARN_ON(!nf_flow_offload_gc_step(flow_table));
++ rhashtable_destroy(&flow_table->rhashtable);
+ }
+ EXPORT_SYMBOL_GPL(nf_flow_table_free);
+
+--- a/net/netfilter/nf_flow_table_inet.c
++++ b/net/netfilter/nf_flow_table_inet.c
+@@ -22,8 +22,7 @@ nf_flow_offload_inet_hook(void *priv, st
+
+ static struct nf_flowtable_type flowtable_inet = {
+ .family = NFPROTO_INET,
+- .params = &nf_flow_offload_rhash_params,
+- .gc = nf_flow_offload_work_gc,
++ .init = nf_flow_table_init,
+ .free = nf_flow_table_free,
+ .hook = nf_flow_offload_inet_hook,
+ .owner = THIS_MODULE,
+--- a/net/netfilter/nf_tables_api.c
++++ b/net/netfilter/nf_tables_api.c
+@@ -5013,40 +5013,38 @@ static int nf_tables_newflowtable(struct
+ }
+
+ flowtable->data.type = type;
+- err = rhashtable_init(&flowtable->data.rhashtable, type->params);
++ err = type->init(&flowtable->data);
+ if (err < 0)
+ goto err3;
+
+ err = nf_tables_flowtable_parse_hook(&ctx, nla[NFTA_FLOWTABLE_HOOK],
+ flowtable);
+ if (err < 0)
+- goto err3;
++ goto err4;
+
+ for (i = 0; i < flowtable->ops_len; i++) {
+ err = nf_register_net_hook(net, &flowtable->ops[i]);
+ if (err < 0)
+- goto err4;
++ goto err5;
+ }
+
+ err = nft_trans_flowtable_add(&ctx, NFT_MSG_NEWFLOWTABLE, flowtable);
+ if (err < 0)
+- goto err5;
+-
+- INIT_DEFERRABLE_WORK(&flowtable->data.gc_work, type->gc);
+- queue_delayed_work(system_power_efficient_wq,
+- &flowtable->data.gc_work, HZ);
++ goto err6;
+
+ list_add_tail_rcu(&flowtable->list, &table->flowtables);
+ table->use++;
+
+ return 0;
+-err5:
++err6:
+ i = flowtable->ops_len;
+-err4:
++err5:
+ for (k = i - 1; k >= 0; k--)
+ nf_unregister_net_hook(net, &flowtable->ops[i]);
+
+ kfree(flowtable->ops);
++err4:
++ flowtable->data.type->free(&flowtable->data);
+ err3:
+ module_put(type->owner);
+ err2:
+@@ -5325,10 +5323,8 @@ err:
+
+ static void nf_tables_flowtable_destroy(struct nft_flowtable *flowtable)
+ {
+- cancel_delayed_work_sync(&flowtable->data.gc_work);
+ kfree(flowtable->name);
+ flowtable->data.type->free(&flowtable->data);
+- rhashtable_destroy(&flowtable->data.rhashtable);
+ module_put(flowtable->data.type->owner);
+ }
+