On 9/5/2019 3:40 AM, Pablo Neira Ayuso wrote: > Thanks for working on this. > > On Wed, Sep 04, 2019 at 03:07:31PM +0800, wenxu@xxxxxxxxx wrote: >> diff --git a/net/netfilter/nf_tables_offload.c b/net/netfilter/nf_tables_offload.c >> index 9657001..9fa3bdb 100644 >> --- a/net/netfilter/nf_tables_offload.c >> +++ b/net/netfilter/nf_tables_offload.c >> @@ -396,17 +396,78 @@ 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, 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 nft_base_chain *basechain; >> + struct net *net = dev_net(dev); >> + struct nft_table *table; >> + struct nft_chain *chain; >> + >> + if (event != NETDEV_UNREGISTER) >> + return NOTIFY_DONE; >> + >> + mutex_lock(&net->nft.commit_mutex); >> + list_for_each_entry(table, &net->nft.tables, list) { >> + if (table->family != NFPROTO_NETDEV) >> + continue; >> + >> + list_for_each_entry(chain, &table->chains, list) { >> + if (!nft_is_base_chain(chain) || >> + !(chain->flags & NFT_CHAIN_HW_OFFLOAD)) >> + continue; >> + >> + basechain = nft_base_chain(chain); >> + if (strncmp(basechain->dev_name, dev->name, IFNAMSIZ)) >> + continue; >> + >> + nft_offload_chain_clean(chain); >> + mutex_unlock(&net->nft.commit_mutex); >> + return NOTIFY_DONE; >> + } >> + } >> + mutex_unlock(&net->nft.commit_mutex); > This code around the mutex look very similar to nft_block_indr_cb(), > could you consolidate this? Probably something like > nft_offload_netdev_iterate() and add a callback. nft_offload_netdev_iterate is a good idear, But maybe it can't provide a common callback. The nft_offload_netdev_iterate(without mutex) can return the chain amke each function(with mutex) use it > >> + 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, > No need for priority because of registration order, right? yes, nft_offload_init will early than nft_chain_filter mod init >