diff options
author | wenxu <wenxu@ucloud.cn> | 2019-09-11 12:53:24 +0800 |
---|---|---|
committer | Pablo Neira Ayuso <pablo@netfilter.org> | 2019-09-13 10:58:10 +0200 |
commit | 06d392cbe3db52c2ce01a2f486afd03eda75743b (patch) | |
tree | b5289026f04f942719f95863601c6c321892d3f8 /net/netfilter/nf_tables_offload.c | |
parent | e211aab73d4c804fe426960c8c9a7a26ec45f190 (diff) |
netfilter: nf_tables_offload: remove rules when the device unregisters
If the net_device unregisters, clean up the offload rules before the
chain is destroy.
Signed-off-by: wenxu <wenxu@ucloud.cn>
Signed-off-by: Pablo Neira Ayuso <pablo@netfilter.org>
Diffstat (limited to 'net/netfilter/nf_tables_offload.c')
-rw-r--r-- | net/netfilter/nf_tables_offload.c | 43 |
1 files changed, 42 insertions, 1 deletions
diff --git a/net/netfilter/nf_tables_offload.c b/net/netfilter/nf_tables_offload.c index 739a79cdb741..21bb772cb4b7 100644 --- a/net/netfilter/nf_tables_offload.c +++ b/net/netfilter/nf_tables_offload.c @@ -426,17 +426,58 @@ static void nft_indr_block_cb(struct net_device *dev, mutex_unlock(&net->nft.commit_mutex); } +static void nft_offload_chain_clean(struct nft_chain *chain) +{ + struct nft_rule *rule; + + list_for_each_entry(rule, &chain->rules, list) { + nft_flow_offload_rule(chain, rule, + NULL, FLOW_CLS_DESTROY); + } + + nft_flow_offload_chain(chain, NULL, FLOW_BLOCK_UNBIND); +} + +static int nft_offload_netdev_event(struct notifier_block *this, + unsigned long event, void *ptr) +{ + struct net_device *dev = netdev_notifier_info_to_dev(ptr); + struct net *net = dev_net(dev); + struct nft_chain *chain; + + mutex_lock(&net->nft.commit_mutex); + chain = __nft_offload_get_chain(dev); + if (chain) + nft_offload_chain_clean(chain); + mutex_unlock(&net->nft.commit_mutex); + + return NOTIFY_DONE; +} + static struct flow_indr_block_ing_entry block_ing_entry = { .cb = nft_indr_block_cb, .list = LIST_HEAD_INIT(block_ing_entry.list), }; -void nft_offload_init(void) +static struct notifier_block nft_offload_netdev_notifier = { + .notifier_call = nft_offload_netdev_event, +}; + +int nft_offload_init(void) { + int err; + + err = register_netdevice_notifier(&nft_offload_netdev_notifier); + if (err < 0) + return err; + flow_indr_add_block_ing_cb(&block_ing_entry); + + return 0; } void nft_offload_exit(void) { flow_indr_del_block_ing_cb(&block_ing_entry); + unregister_netdevice_notifier(&nft_offload_netdev_notifier); } |