Call nf_flow_table_iterate_cleanup() to remove flowtable entries that belong to the net_device that is being unregistered. Signed-off-by: Pablo Neira Ayuso <pablo@xxxxxxxxxxxxx> --- include/net/netfilter/nf_flow_table.h | 4 ++++ net/ipv4/netfilter/nf_flow_table_ipv4.c | 1 + net/ipv6/netfilter/nf_flow_table_ipv6.c | 1 + net/netfilter/nf_flow_table_core.c | 4 ++-- net/netfilter/nf_flow_table_inet.c | 1 + net/netfilter/nf_tables_api.c | 1 + 6 files changed, 10 insertions(+), 2 deletions(-) diff --git a/include/net/netfilter/nf_flow_table.h b/include/net/netfilter/nf_flow_table.h index f0897b3c97fb..43943567dc2e 100644 --- a/include/net/netfilter/nf_flow_table.h +++ b/include/net/netfilter/nf_flow_table.h @@ -27,6 +27,8 @@ struct nf_flowtable_type { const struct flow_offload *flow, enum flow_offload_tuple_dir dir, struct nf_flow_rule *flow_rule); + void (*cleanup)(struct nf_flowtable *ft, + struct net_device *dev); void (*free)(struct nf_flowtable *ft); nf_hookfn *hook; struct module *owner; @@ -122,6 +124,8 @@ int flow_offload_route_init(struct flow_offload *flow, int flow_offload_add(struct nf_flowtable *flow_table, struct flow_offload *flow); struct flow_offload_tuple_rhash *flow_offload_lookup(struct nf_flowtable *flow_table, struct flow_offload_tuple *tuple); +void nf_flow_table_iterate_cleanup(struct nf_flowtable *flowtable, + struct net_device *dev); void nf_flow_table_cleanup(struct net_device *dev); int nf_flow_table_init(struct nf_flowtable *flow_table); diff --git a/net/ipv4/netfilter/nf_flow_table_ipv4.c b/net/ipv4/netfilter/nf_flow_table_ipv4.c index e32e41b99f0f..6f20f8034eb3 100644 --- a/net/ipv4/netfilter/nf_flow_table_ipv4.c +++ b/net/ipv4/netfilter/nf_flow_table_ipv4.c @@ -11,6 +11,7 @@ static struct nf_flowtable_type flowtable_ipv4 = { .init = nf_flow_table_init, .setup = nf_flow_table_offload_setup, .action = nf_flow_rule_route_ipv4, + .cleanup = nf_flow_table_iterate_cleanup, .free = nf_flow_table_free, .hook = nf_flow_offload_ip_hook, .owner = THIS_MODULE, diff --git a/net/ipv6/netfilter/nf_flow_table_ipv6.c b/net/ipv6/netfilter/nf_flow_table_ipv6.c index a8566ee12e83..ed93b0a6d11a 100644 --- a/net/ipv6/netfilter/nf_flow_table_ipv6.c +++ b/net/ipv6/netfilter/nf_flow_table_ipv6.c @@ -12,6 +12,7 @@ static struct nf_flowtable_type flowtable_ipv6 = { .init = nf_flow_table_init, .setup = nf_flow_table_offload_setup, .action = nf_flow_rule_route_ipv6, + .cleanup = nf_flow_table_iterate_cleanup, .free = nf_flow_table_free, .hook = nf_flow_offload_ipv6_hook, .owner = THIS_MODULE, diff --git a/net/netfilter/nf_flow_table_core.c b/net/netfilter/nf_flow_table_core.c index 9889d52eda82..9a7421e2b039 100644 --- a/net/netfilter/nf_flow_table_core.c +++ b/net/netfilter/nf_flow_table_core.c @@ -532,8 +532,8 @@ static void nf_flow_table_do_cleanup(struct flow_offload *flow, void *data) flow_offload_dead(flow); } -static void nf_flow_table_iterate_cleanup(struct nf_flowtable *flowtable, - struct net_device *dev) +void nf_flow_table_iterate_cleanup(struct nf_flowtable *flowtable, + struct net_device *dev) { nf_flow_table_offload_flush(flowtable); nf_flow_table_iterate(flowtable, nf_flow_table_do_cleanup, dev); diff --git a/net/netfilter/nf_flow_table_inet.c b/net/netfilter/nf_flow_table_inet.c index 88bedf1ff1ae..487541cd2d09 100644 --- a/net/netfilter/nf_flow_table_inet.c +++ b/net/netfilter/nf_flow_table_inet.c @@ -49,6 +49,7 @@ static struct nf_flowtable_type flowtable_inet = { .init = nf_flow_table_init, .setup = nf_flow_table_offload_setup, .action = nf_flow_rule_route_inet, + .cleanup = nf_flow_table_iterate_cleanup, .free = nf_flow_table_free, .hook = nf_flow_offload_inet_hook, .owner = THIS_MODULE, diff --git a/net/netfilter/nf_tables_api.c b/net/netfilter/nf_tables_api.c index 062b73a83af0..f339bd9376b6 100644 --- a/net/netfilter/nf_tables_api.c +++ b/net/netfilter/nf_tables_api.c @@ -6490,6 +6490,7 @@ static void nft_flowtable_event(unsigned long event, struct net_device *dev, continue; nft_unregister_flowtable_hook(dev_net(dev), flowtable, hook); + flowtable->data.type->cleanup(&flowtable->data, dev); list_del_rcu(&hook->list); kfree_rcu(hook, rcu); break; -- 2.11.0