public inbox for netdev@vger.kernel.org
 help / color / mirror / Atom feed
* [PATCH net-next] ipv4: fib: Replay events when registering FIB notifier
@ 2016-10-31  8:29 idosch
  2016-10-31 11:32 ` kbuild test robot
  2016-10-31 16:54 ` kbuild test robot
  0 siblings, 2 replies; 4+ messages in thread
From: idosch @ 2016-10-31  8:29 UTC (permalink / raw)
  To: netdev
  Cc: davem, jiri, mlxsw, roopa, nikolay, dsa, andy, alexander.h.duyck,
	vivien.didelot, f.fainelli, andrew, kuznet, jmorris, yoshfuji,
	kaber, Ido Schimmel

From: Ido Schimmel <idosch@mellanox.com>

When registering a FIB notifier block we should notify the caller of
already existing FIB entries and rules, as it would otherwise have an
incomplete view of the FIB tables. This is especially important for
switchdev drivers that support FIB offloads. Failing to notify them of
existing entries may lead to packet loss.

Upon registration, walk the leafs of all the routing tables and for each
leaf send notification of existing FIB aliases. Similarly, when
unregistering the notifier synthesize a deletion event, thereby
relieving potential callers from the need to perform cleanup.

The above is consistent with the netdevice notification chain, where
"registration and up events are replayed to the new notifier" upon
registration.

Signed-off-by: Ido Schimmel <idosch@mellanox.com>
Reviewed-by: Jiri Pirko <jiri@mellanox.com>
---
 net/ipv4/fib_trie.c | 147 +++++++++++++++++++++++++++++++++++++++++++++++++++-
 1 file changed, 145 insertions(+), 2 deletions(-)

diff --git a/net/ipv4/fib_trie.c b/net/ipv4/fib_trie.c
index 31cef36..608f9d4 100644
--- a/net/ipv4/fib_trie.c
+++ b/net/ipv4/fib_trie.c
@@ -86,15 +86,102 @@
 
 static BLOCKING_NOTIFIER_HEAD(fib_chain);
 
+static void fib_notify(struct net *net, struct notifier_block *nb,
+		       enum fib_event_type event_type);
+
+static int call_fib_notifier(struct notifier_block *nb, struct net *net,
+			     enum fib_event_type event_type,
+			     struct fib_notifier_info *info)
+{
+	info->net = net;
+	return nb->notifier_call(nb, event_type, info);
+}
+
+static int call_fib_entry_notifier(struct notifier_block *nb, struct net *net,
+				   enum fib_event_type event_type, u32 dst,
+				   int dst_len, struct fib_info *fi,
+				   u8 tos, u8 type, u32 tb_id, u32 nlflags)
+{
+	struct fib_entry_notifier_info info = {
+		.dst = dst,
+		.dst_len = dst_len,
+		.fi = fi,
+		.tos = tos,
+		.type = type,
+		.tb_id = tb_id,
+		.nlflags = nlflags,
+	};
+	return call_fib_notifier(nb, net, event_type, &info.info);
+}
+
+/**
+ *	register_fib_notifier - register a fib notifier block
+ *	@nb: notifier
+ *
+ *	Register a notifier to be called when FIB entries or rules are
+ *	added or removed. A negative errno code is returned on failure.
+ *
+ *	When registered, all FIB addition events are replayed to the new
+ *	notifier to allow the caller to have a complete view of the FIB
+ *	tables.
+ */
+
 int register_fib_notifier(struct notifier_block *nb)
 {
-	return blocking_notifier_chain_register(&fib_chain, nb);
+	struct net *net;
+	int err;
+
+	rtnl_lock();
+	err = blocking_notifier_chain_register(&fib_chain, nb);
+	if (err)
+		goto unlock;
+	for_each_net(net) {
+		struct fib_notifier_info info;
+
+		if (net->ipv4.fib_has_custom_rules)
+			call_fib_notifier(nb, net, FIB_EVENT_RULE_ADD, &info);
+		fib_notify(net, nb, FIB_EVENT_ENTRY_ADD);
+	}
+
+unlock:
+	rtnl_unlock();
+	return err;
 }
 EXPORT_SYMBOL(register_fib_notifier);
 
+/**
+ *	unregister_fib_notifier - unregister a fib notifier block
+ *	@nb: notifier
+ *
+ *	unregister a notifier previously registered by
+ *	register_fib_notifier(). A negative errno code is returned on
+ *	failure.
+ *
+ *	After unregistering, FIB deletion events are synthesized to the
+ *	removed notifier for all present FIB entries. This removes the
+ *	need for special case cleanup code.
+ */
+
 int unregister_fib_notifier(struct notifier_block *nb)
 {
-	return blocking_notifier_chain_unregister(&fib_chain, nb);
+	struct net *net;
+	int err;
+
+	rtnl_lock();
+	err = blocking_notifier_chain_unregister(&fib_chain, nb);
+	if (err)
+		goto unlock;
+	for_each_net(net) {
+		struct fib_notifier_info info;
+
+		fib_notify(net, nb, FIB_EVENT_ENTRY_DEL);
+		if (net->ipv4.fib_has_custom_rules)
+			call_fib_notifier(nb, net, FIB_EVENT_RULE_DEL, &info);
+	}
+
+unlock:
+	rtnl_unlock();
+	return err;
 }
 EXPORT_SYMBOL(unregister_fib_notifier);
 
@@ -1834,6 +1921,62 @@ int fib_table_flush(struct net *net, struct fib_table *tb)
 	return found;
 }
 
+static void fib_leaf_notify(struct net *net, struct key_vector *l,
+			    struct fib_table *tb, struct notifier_block *nb,
+			    enum fib_event_type event_type)
+{
+	struct fib_alias *fa;
+
+	hlist_for_each_entry(fa, &l->leaf, fa_list) {
+		struct fib_info *fi = fa->fa_info;
+
+		if (!fi)
+			continue;
+
+		/* local and main table can share the same trie,
+		 * so don't notify twice for the same entry.
+		 */
+		if (tb->tb_id != fa->tb_id)
+			continue;
+
+		call_fib_entry_notifier(nb, net, event_type, l->key,
+					KEYLENGTH - fa->fa_slen, fi, fa->fa_tos,
+					fa->fa_type, fa->tb_id, 0);
+	}
+}
+
+static void fib_table_notify(struct net *net, struct fib_table *tb,
+			     struct notifier_block *nb,
+			     enum fib_event_type event_type)
+{
+	struct trie *t = (struct trie *)tb->tb_data;
+	struct key_vector *l, *tp = t->kv;
+	t_key key = 0;
+
+	while ((l = leaf_walk_rcu(&tp, key)) != NULL) {
+		fib_leaf_notify(net, l, tb, nb, event_type);
+
+		key = l->key + 1;
+		/* stop in case of wrap around */
+		if (key < l->key)
+			break;
+	}
+}
+
+static void fib_notify(struct net *net, struct notifier_block *nb,
+		       enum fib_event_type event_type)
+{
+	unsigned int h;
+
+	for (h = 0; h < FIB_TABLE_HASHSZ; h++) {
+		struct hlist_head *head = &net->ipv4.fib_table_hash[h];
+		struct fib_table *tb;
+
+		hlist_for_each_entry(tb, head, tb_hlist)
+			fib_table_notify(net, tb, nb, event_type);
+	}
+}
+
 static void __trie_free_rcu(struct rcu_head *head)
 {
 	struct fib_table *tb = container_of(head, struct fib_table, rcu);
-- 
2.7.4

^ permalink raw reply related	[flat|nested] 4+ messages in thread

* Re: [PATCH net-next] ipv4: fib: Replay events when registering FIB notifier
  2016-10-31 16:54 ` kbuild test robot
@ 2016-10-31  9:03   ` Ido Schimmel
  0 siblings, 0 replies; 4+ messages in thread
From: Ido Schimmel @ 2016-10-31  9:03 UTC (permalink / raw)
  To: kbuild test robot
  Cc: kbuild-all, netdev, davem, jiri, mlxsw, roopa, nikolay, dsa, andy,
	alexander.h.duyck, vivien.didelot, f.fainelli, andrew, kuznet,
	jmorris, yoshfuji, kaber, Ido Schimmel

On Tue, Nov 01, 2016 at 12:54:01AM +0800, kbuild test robot wrote:
> Hi Ido,
> 
> [auto build test ERROR on net-next/master]
> 
> url:    https://github.com/0day-ci/linux/commits/idosch-idosch-org/ipv4-fib-Replay-events-when-registering-FIB-notifier/20161031-163334
> config: x86_64-randconfig-x014-201644 (attached as .config)
> compiler: gcc-6 (Debian 6.2.0-3) 6.2.0 20160901
> reproduce:
>         # save the attached .config to linux build tree
>         make ARCH=x86_64 
> 
> All errors (new ones prefixed by >>):
> 
>    net/ipv4/fib_trie.c: In function 'register_fib_notifier':
> >> net/ipv4/fib_trie.c:141:16: error: 'struct netns_ipv4' has no member named 'fib_has_custom_rules'
>       if (net->ipv4.fib_has_custom_rules)
>                    ^
>    net/ipv4/fib_trie.c: In function 'unregister_fib_notifier':
>    net/ipv4/fib_trie.c:178:16: error: 'struct netns_ipv4' has no member named 'fib_has_custom_rules'
>       if (net->ipv4.fib_has_custom_rules)
>                    ^

Right, I missed that. Will send a v2.

Thanks!

> 
> vim +141 net/ipv4/fib_trie.c
> 
>    135		err = blocking_notifier_chain_register(&fib_chain, nb);
>    136		if (err)
>    137			goto unlock;
>    138		for_each_net(net) {
>    139			struct fib_notifier_info info;
>    140	
>  > 141			if (net->ipv4.fib_has_custom_rules)
>    142				call_fib_notifier(nb, net, FIB_EVENT_RULE_ADD, &info);
>    143			fib_notify(net, nb, FIB_EVENT_ENTRY_ADD);
>    144		}
> 
> ---
> 0-DAY kernel test infrastructure                Open Source Technology Center
> https://lists.01.org/pipermail/kbuild-all                   Intel Corporation

^ permalink raw reply	[flat|nested] 4+ messages in thread

* Re: [PATCH net-next] ipv4: fib: Replay events when registering FIB notifier
  2016-10-31  8:29 [PATCH net-next] ipv4: fib: Replay events when registering FIB notifier idosch
@ 2016-10-31 11:32 ` kbuild test robot
  2016-10-31 16:54 ` kbuild test robot
  1 sibling, 0 replies; 4+ messages in thread
From: kbuild test robot @ 2016-10-31 11:32 UTC (permalink / raw)
  To: idosch
  Cc: kbuild-all, netdev, davem, jiri, mlxsw, roopa, nikolay, dsa, andy,
	alexander.h.duyck, vivien.didelot, f.fainelli, andrew, kuznet,
	jmorris, yoshfuji, kaber, Ido Schimmel

[-- Attachment #1: Type: text/plain, Size: 6723 bytes --]

Hi Ido,

[auto build test WARNING on net-next/master]

url:    https://github.com/0day-ci/linux/commits/idosch-idosch-org/ipv4-fib-Replay-events-when-registering-FIB-notifier/20161031-163334
config: x86_64-randconfig-s4-10311807 (attached as .config)
compiler: gcc-6 (Debian 6.2.0-3) 6.2.0 20160901
reproduce:
        # save the attached .config to linux build tree
        make ARCH=x86_64 

All warnings (new ones prefixed by >>):

   In file included from arch/x86/include/asm/uaccess.h:7:0,
                    from net/ipv4/fib_trie.c:53:
   net/ipv4/fib_trie.c: In function 'register_fib_notifier':
   net/ipv4/fib_trie.c:141:16: error: 'struct netns_ipv4' has no member named 'fib_has_custom_rules'
      if (net->ipv4.fib_has_custom_rules)
                   ^
   include/linux/compiler.h:149:30: note: in definition of macro '__trace_if'
     if (__builtin_constant_p(!!(cond)) ? !!(cond) :   \
                                 ^~~~
>> net/ipv4/fib_trie.c:141:3: note: in expansion of macro 'if'
      if (net->ipv4.fib_has_custom_rules)
      ^~
   net/ipv4/fib_trie.c:141:16: error: 'struct netns_ipv4' has no member named 'fib_has_custom_rules'
      if (net->ipv4.fib_has_custom_rules)
                   ^
   include/linux/compiler.h:149:42: note: in definition of macro '__trace_if'
     if (__builtin_constant_p(!!(cond)) ? !!(cond) :   \
                                             ^~~~
>> net/ipv4/fib_trie.c:141:3: note: in expansion of macro 'if'
      if (net->ipv4.fib_has_custom_rules)
      ^~
   net/ipv4/fib_trie.c:141:16: error: 'struct netns_ipv4' has no member named 'fib_has_custom_rules'
      if (net->ipv4.fib_has_custom_rules)
                   ^
   include/linux/compiler.h:160:16: note: in definition of macro '__trace_if'
      ______r = !!(cond);     \
                   ^~~~
>> net/ipv4/fib_trie.c:141:3: note: in expansion of macro 'if'
      if (net->ipv4.fib_has_custom_rules)
      ^~
   net/ipv4/fib_trie.c: In function 'unregister_fib_notifier':
   net/ipv4/fib_trie.c:178:16: error: 'struct netns_ipv4' has no member named 'fib_has_custom_rules'
      if (net->ipv4.fib_has_custom_rules)
                   ^
   include/linux/compiler.h:149:30: note: in definition of macro '__trace_if'
     if (__builtin_constant_p(!!(cond)) ? !!(cond) :   \
                                 ^~~~
   net/ipv4/fib_trie.c:178:3: note: in expansion of macro 'if'
      if (net->ipv4.fib_has_custom_rules)
      ^~
   net/ipv4/fib_trie.c:178:16: error: 'struct netns_ipv4' has no member named 'fib_has_custom_rules'
      if (net->ipv4.fib_has_custom_rules)
                   ^
   include/linux/compiler.h:149:42: note: in definition of macro '__trace_if'
     if (__builtin_constant_p(!!(cond)) ? !!(cond) :   \
                                             ^~~~
   net/ipv4/fib_trie.c:178:3: note: in expansion of macro 'if'
      if (net->ipv4.fib_has_custom_rules)
      ^~
   net/ipv4/fib_trie.c:178:16: error: 'struct netns_ipv4' has no member named 'fib_has_custom_rules'
      if (net->ipv4.fib_has_custom_rules)
                   ^
   include/linux/compiler.h:160:16: note: in definition of macro '__trace_if'
      ______r = !!(cond);     \
                   ^~~~
   net/ipv4/fib_trie.c:178:3: note: in expansion of macro 'if'
      if (net->ipv4.fib_has_custom_rules)
      ^~

vim +/if +141 net/ipv4/fib_trie.c

    47	 *		Paul E. McKenney <paulmck@us.ibm.com>
    48	 *		Patrick McHardy <kaber@trash.net>
    49	 */
    50	
    51	#define VERSION "0.409"
    52	
  > 53	#include <asm/uaccess.h>
    54	#include <linux/bitops.h>
    55	#include <linux/types.h>
    56	#include <linux/kernel.h>
    57	#include <linux/mm.h>
    58	#include <linux/string.h>
    59	#include <linux/socket.h>
    60	#include <linux/sockios.h>
    61	#include <linux/errno.h>
    62	#include <linux/in.h>
    63	#include <linux/inet.h>
    64	#include <linux/inetdevice.h>
    65	#include <linux/netdevice.h>
    66	#include <linux/if_arp.h>
    67	#include <linux/proc_fs.h>
    68	#include <linux/rcupdate.h>
    69	#include <linux/skbuff.h>
    70	#include <linux/netlink.h>
    71	#include <linux/init.h>
    72	#include <linux/list.h>
    73	#include <linux/slab.h>
    74	#include <linux/export.h>
    75	#include <linux/vmalloc.h>
    76	#include <linux/notifier.h>
    77	#include <net/net_namespace.h>
    78	#include <net/ip.h>
    79	#include <net/protocol.h>
    80	#include <net/route.h>
    81	#include <net/tcp.h>
    82	#include <net/sock.h>
    83	#include <net/ip_fib.h>
    84	#include <trace/events/fib.h>
    85	#include "fib_lookup.h"
    86	
    87	static BLOCKING_NOTIFIER_HEAD(fib_chain);
    88	
    89	static void fib_notify(struct net *net, struct notifier_block *nb,
    90			       enum fib_event_type event_type);
    91	
    92	static int call_fib_notifier(struct notifier_block *nb, struct net *net,
    93				     enum fib_event_type event_type,
    94				     struct fib_notifier_info *info)
    95	{
    96		info->net = net;
    97		return nb->notifier_call(nb, event_type, info);
    98	}
    99	
   100	static int call_fib_entry_notifier(struct notifier_block *nb, struct net *net,
   101					   enum fib_event_type event_type, u32 dst,
   102					   int dst_len, struct fib_info *fi,
   103					   u8 tos, u8 type, u32 tb_id, u32 nlflags)
   104	{
   105		struct fib_entry_notifier_info info = {
   106			.dst = dst,
   107			.dst_len = dst_len,
   108			.fi = fi,
   109			.tos = tos,
   110			.type = type,
   111			.tb_id = tb_id,
   112			.nlflags = nlflags,
   113		};
   114		return call_fib_notifier(nb, net, event_type, &info.info);
   115	}
   116	
   117	/**
   118	 *	register_fib_notifier - register a fib notifier block
   119	 *	@nb: notifier
   120	 *
   121	 *	Register a notifier to be called when FIB entries or rules are
   122	 *	added or removed. A negative errno code is returned on failure.
   123	 *
   124	 *	When registered, all FIB addition events are replayed to the new
   125	 *	notifier to allow the caller to have a complete view of the FIB
   126	 *	tables.
   127	 */
   128	
   129	int register_fib_notifier(struct notifier_block *nb)
   130	{
   131		struct net *net;
   132		int err;
   133	
   134		rtnl_lock();
   135		err = blocking_notifier_chain_register(&fib_chain, nb);
   136		if (err)
   137			goto unlock;
   138		for_each_net(net) {
   139			struct fib_notifier_info info;
   140	
 > 141			if (net->ipv4.fib_has_custom_rules)
   142				call_fib_notifier(nb, net, FIB_EVENT_RULE_ADD, &info);
   143			fib_notify(net, nb, FIB_EVENT_ENTRY_ADD);
   144		}

---
0-DAY kernel test infrastructure                Open Source Technology Center
https://lists.01.org/pipermail/kbuild-all                   Intel Corporation

[-- Attachment #2: .config.gz --]
[-- Type: application/gzip, Size: 27187 bytes --]

^ permalink raw reply	[flat|nested] 4+ messages in thread

* Re: [PATCH net-next] ipv4: fib: Replay events when registering FIB notifier
  2016-10-31  8:29 [PATCH net-next] ipv4: fib: Replay events when registering FIB notifier idosch
  2016-10-31 11:32 ` kbuild test robot
@ 2016-10-31 16:54 ` kbuild test robot
  2016-10-31  9:03   ` Ido Schimmel
  1 sibling, 1 reply; 4+ messages in thread
From: kbuild test robot @ 2016-10-31 16:54 UTC (permalink / raw)
  To: idosch
  Cc: kbuild-all, netdev, davem, jiri, mlxsw, roopa, nikolay, dsa, andy,
	alexander.h.duyck, vivien.didelot, f.fainelli, andrew, kuznet,
	jmorris, yoshfuji, kaber, Ido Schimmel

[-- Attachment #1: Type: text/plain, Size: 1424 bytes --]

Hi Ido,

[auto build test ERROR on net-next/master]

url:    https://github.com/0day-ci/linux/commits/idosch-idosch-org/ipv4-fib-Replay-events-when-registering-FIB-notifier/20161031-163334
config: x86_64-randconfig-x014-201644 (attached as .config)
compiler: gcc-6 (Debian 6.2.0-3) 6.2.0 20160901
reproduce:
        # save the attached .config to linux build tree
        make ARCH=x86_64 

All errors (new ones prefixed by >>):

   net/ipv4/fib_trie.c: In function 'register_fib_notifier':
>> net/ipv4/fib_trie.c:141:16: error: 'struct netns_ipv4' has no member named 'fib_has_custom_rules'
      if (net->ipv4.fib_has_custom_rules)
                   ^
   net/ipv4/fib_trie.c: In function 'unregister_fib_notifier':
   net/ipv4/fib_trie.c:178:16: error: 'struct netns_ipv4' has no member named 'fib_has_custom_rules'
      if (net->ipv4.fib_has_custom_rules)
                   ^

vim +141 net/ipv4/fib_trie.c

   135		err = blocking_notifier_chain_register(&fib_chain, nb);
   136		if (err)
   137			goto unlock;
   138		for_each_net(net) {
   139			struct fib_notifier_info info;
   140	
 > 141			if (net->ipv4.fib_has_custom_rules)
   142				call_fib_notifier(nb, net, FIB_EVENT_RULE_ADD, &info);
   143			fib_notify(net, nb, FIB_EVENT_ENTRY_ADD);
   144		}

---
0-DAY kernel test infrastructure                Open Source Technology Center
https://lists.01.org/pipermail/kbuild-all                   Intel Corporation

[-- Attachment #2: .config.gz --]
[-- Type: application/gzip, Size: 33925 bytes --]

^ permalink raw reply	[flat|nested] 4+ messages in thread

end of thread, other threads:[~2016-10-31 11:34 UTC | newest]

Thread overview: 4+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2016-10-31  8:29 [PATCH net-next] ipv4: fib: Replay events when registering FIB notifier idosch
2016-10-31 11:32 ` kbuild test robot
2016-10-31 16:54 ` kbuild test robot
2016-10-31  9:03   ` Ido Schimmel

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox