* [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