Commit 06d392cb authored by wenxu's avatar wenxu Committed by Pablo Neira Ayuso
Browse files

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: default avatarwenxu <wenxu@ucloud.cn>
Signed-off-by: default avatarPablo Neira Ayuso <pablo@netfilter.org>
parent e211aab7
Loading
Loading
Loading
Loading
+1 −1
Original line number Diff line number Diff line
@@ -77,7 +77,7 @@ int nft_flow_rule_offload_commit(struct net *net);

int nft_chain_offload_priority(struct nft_base_chain *basechain);

void nft_offload_init(void);
int nft_offload_init(void);
void nft_offload_exit(void);

#endif
+8 −3
Original line number Diff line number Diff line
@@ -7694,15 +7694,20 @@ static int __init nf_tables_module_init(void)
	if (err < 0)
		goto err4;

	err = nft_offload_init();
	if (err < 0)
		goto err5;

	/* must be last */
	err = nfnetlink_subsys_register(&nf_tables_subsys);
	if (err < 0)
		goto err5;
		goto err6;

	nft_chain_route_init();
	nft_offload_init();

	return err;
err6:
	nft_offload_exit();
err5:
	rhltable_destroy(&nft_objname_ht);
err4:
@@ -7718,8 +7723,8 @@ err1:

static void __exit nf_tables_module_exit(void)
{
	nft_offload_exit();
	nfnetlink_subsys_unregister(&nf_tables_subsys);
	nft_offload_exit();
	unregister_netdevice_notifier(&nf_tables_flowtable_notifier);
	nft_chain_filter_fini();
	nft_chain_route_fini();
+42 −1
Original line number Diff line number Diff line
@@ -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);
}