Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

netfilter: nf_tables: Introduce nft_hook_find_ops{,_rcu}()

Also a pretty dull wrapper around the hook->ops.dev comparison for now.
Will search the embedded nf_hook_ops list in future. The ugly cast to
eliminate the const qualifier will vanish then, too.

Since this future list will be RCU-protected, also introduce an _rcu()
variant here.

Signed-off-by: Phil Sutter <phil@nwl.cc>
Signed-off-by: Pablo Neira Ayuso <pablo@netfilter.org>

authored by

Phil Sutter and committed by
Pablo Neira Ayuso
e225376d 75e20bcd

+31 -5
+5
include/net/netfilter/nf_tables.h
··· 1205 1205 u8 ifnamelen; 1206 1206 }; 1207 1207 1208 + struct nf_hook_ops *nft_hook_find_ops(const struct nft_hook *hook, 1209 + const struct net_device *dev); 1210 + struct nf_hook_ops *nft_hook_find_ops_rcu(const struct nft_hook *hook, 1211 + const struct net_device *dev); 1212 + 1208 1213 /** 1209 1214 * struct nft_base_chain - nf_tables base chain 1210 1215 *
+20 -1
net/netfilter/nf_tables_api.c
··· 9600 9600 return -EMSGSIZE; 9601 9601 } 9602 9602 9603 + struct nf_hook_ops *nft_hook_find_ops(const struct nft_hook *hook, 9604 + const struct net_device *dev) 9605 + { 9606 + if (hook->ops.dev == dev) 9607 + return (struct nf_hook_ops *)&hook->ops; 9608 + 9609 + return NULL; 9610 + } 9611 + EXPORT_SYMBOL_GPL(nft_hook_find_ops); 9612 + 9613 + struct nf_hook_ops *nft_hook_find_ops_rcu(const struct nft_hook *hook, 9614 + const struct net_device *dev) 9615 + { 9616 + return nft_hook_find_ops(hook, dev); 9617 + } 9618 + EXPORT_SYMBOL_GPL(nft_hook_find_ops_rcu); 9619 + 9603 9620 static void nft_flowtable_event(unsigned long event, struct net_device *dev, 9604 9621 struct nft_flowtable *flowtable) 9605 9622 { 9623 + struct nf_hook_ops *ops; 9606 9624 struct nft_hook *hook; 9607 9625 9608 9626 list_for_each_entry(hook, &flowtable->hook_list, list) { 9609 - if (hook->ops.dev != dev) 9627 + ops = nft_hook_find_ops(hook, dev); 9628 + if (!ops) 9610 9629 continue; 9611 9630 9612 9631 /* flow_offload_netdev_event() cleans up entries for us. */
+1 -1
net/netfilter/nf_tables_offload.c
··· 638 638 found = NULL; 639 639 basechain = nft_base_chain(chain); 640 640 list_for_each_entry(hook, &basechain->hook_list, list) { 641 - if (hook->ops.dev != dev) 641 + if (!nft_hook_find_ops(hook, dev)) 642 642 continue; 643 643 644 644 found = hook;
+4 -2
net/netfilter/nft_chain_filter.c
··· 321 321 static void nft_netdev_event(unsigned long event, struct net_device *dev, 322 322 struct nft_base_chain *basechain) 323 323 { 324 + struct nf_hook_ops *ops; 324 325 struct nft_hook *hook; 325 326 326 327 list_for_each_entry(hook, &basechain->hook_list, list) { 327 - if (hook->ops.dev != dev) 328 + ops = nft_hook_find_ops(hook, dev); 329 + if (!ops) 328 330 continue; 329 331 330 332 if (!(basechain->chain.table->flags & NFT_TABLE_F_DORMANT)) 331 - nf_unregister_net_hook(dev_net(dev), &hook->ops); 333 + nf_unregister_net_hook(dev_net(dev), ops); 332 334 333 335 list_del_rcu(&hook->list); 334 336 kfree_rcu(hook, rcu);
+1 -1
net/netfilter/nft_flow_offload.c
··· 175 175 bool found = false; 176 176 177 177 list_for_each_entry_rcu(hook, &ft->hook_list, list) { 178 - if (hook->ops.dev != dev) 178 + if (!nft_hook_find_ops_rcu(hook, dev)) 179 179 continue; 180 180 181 181 found = true;