Skip to content

Commit b90eb75

Browse files
jpirkodavem330
authored andcommitted
fib: introduce FIB notification infrastructure
This allows to pass information about added/deleted FIB entries/rules to whoever is interested. This is done in a very similar way as devinet notifies address additions/removals. Signed-off-by: Jiri Pirko <[email protected]> Signed-off-by: David S. Miller <[email protected]>
1 parent eb523f4 commit b90eb75

File tree

4 files changed

+108
-14
lines changed

4 files changed

+108
-14
lines changed

include/net/ip_fib.h

Lines changed: 31 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,7 @@
2222
#include <net/fib_rules.h>
2323
#include <net/inetpeer.h>
2424
#include <linux/percpu.h>
25+
#include <linux/notifier.h>
2526

2627
struct fib_config {
2728
u8 fc_dst_len;
@@ -185,6 +186,33 @@ __be32 fib_info_update_nh_saddr(struct net *net, struct fib_nh *nh);
185186
#define FIB_RES_PREFSRC(net, res) ((res).fi->fib_prefsrc ? : \
186187
FIB_RES_SADDR(net, res))
187188

189+
struct fib_notifier_info {
190+
struct net *net;
191+
};
192+
193+
struct fib_entry_notifier_info {
194+
struct fib_notifier_info info; /* must be first */
195+
u32 dst;
196+
int dst_len;
197+
struct fib_info *fi;
198+
u8 tos;
199+
u8 type;
200+
u32 tb_id;
201+
u32 nlflags;
202+
};
203+
204+
enum fib_event_type {
205+
FIB_EVENT_ENTRY_ADD,
206+
FIB_EVENT_ENTRY_DEL,
207+
FIB_EVENT_RULE_ADD,
208+
FIB_EVENT_RULE_DEL,
209+
};
210+
211+
int register_fib_notifier(struct notifier_block *nb);
212+
int unregister_fib_notifier(struct notifier_block *nb);
213+
int call_fib_notifiers(struct net *net, enum fib_event_type event_type,
214+
struct fib_notifier_info *info);
215+
188216
struct fib_table {
189217
struct hlist_node tb_hlist;
190218
u32 tb_id;
@@ -196,11 +224,11 @@ struct fib_table {
196224

197225
int fib_table_lookup(struct fib_table *tb, const struct flowi4 *flp,
198226
struct fib_result *res, int fib_flags);
199-
int fib_table_insert(struct fib_table *, struct fib_config *);
200-
int fib_table_delete(struct fib_table *, struct fib_config *);
227+
int fib_table_insert(struct net *, struct fib_table *, struct fib_config *);
228+
int fib_table_delete(struct net *, struct fib_table *, struct fib_config *);
201229
int fib_table_dump(struct fib_table *table, struct sk_buff *skb,
202230
struct netlink_callback *cb);
203-
int fib_table_flush(struct fib_table *table);
231+
int fib_table_flush(struct net *net, struct fib_table *table);
204232
struct fib_table *fib_trie_unmerge(struct fib_table *main_tb);
205233
void fib_table_flush_external(struct fib_table *table);
206234
void fib_free_table(struct fib_table *tb);

net/ipv4/fib_frontend.c

Lines changed: 8 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -182,7 +182,7 @@ static void fib_flush(struct net *net)
182182
struct fib_table *tb;
183183

184184
hlist_for_each_entry_safe(tb, tmp, head, tb_hlist)
185-
flushed += fib_table_flush(tb);
185+
flushed += fib_table_flush(net, tb);
186186
}
187187

188188
if (flushed)
@@ -590,13 +590,13 @@ int ip_rt_ioctl(struct net *net, unsigned int cmd, void __user *arg)
590590
if (cmd == SIOCDELRT) {
591591
tb = fib_get_table(net, cfg.fc_table);
592592
if (tb)
593-
err = fib_table_delete(tb, &cfg);
593+
err = fib_table_delete(net, tb, &cfg);
594594
else
595595
err = -ESRCH;
596596
} else {
597597
tb = fib_new_table(net, cfg.fc_table);
598598
if (tb)
599-
err = fib_table_insert(tb, &cfg);
599+
err = fib_table_insert(net, tb, &cfg);
600600
else
601601
err = -ENOBUFS;
602602
}
@@ -719,7 +719,7 @@ static int inet_rtm_delroute(struct sk_buff *skb, struct nlmsghdr *nlh)
719719
goto errout;
720720
}
721721

722-
err = fib_table_delete(tb, &cfg);
722+
err = fib_table_delete(net, tb, &cfg);
723723
errout:
724724
return err;
725725
}
@@ -741,7 +741,7 @@ static int inet_rtm_newroute(struct sk_buff *skb, struct nlmsghdr *nlh)
741741
goto errout;
742742
}
743743

744-
err = fib_table_insert(tb, &cfg);
744+
err = fib_table_insert(net, tb, &cfg);
745745
errout:
746746
return err;
747747
}
@@ -828,9 +828,9 @@ static void fib_magic(int cmd, int type, __be32 dst, int dst_len, struct in_ifad
828828
cfg.fc_scope = RT_SCOPE_HOST;
829829

830830
if (cmd == RTM_NEWROUTE)
831-
fib_table_insert(tb, &cfg);
831+
fib_table_insert(net, tb, &cfg);
832832
else
833-
fib_table_delete(tb, &cfg);
833+
fib_table_delete(net, tb, &cfg);
834834
}
835835

836836
void fib_add_ifaddr(struct in_ifaddr *ifa)
@@ -1254,7 +1254,7 @@ static void ip_fib_net_exit(struct net *net)
12541254

12551255
hlist_for_each_entry_safe(tb, tmp, head, tb_hlist) {
12561256
hlist_del(&tb->tb_hlist);
1257-
fib_table_flush(tb);
1257+
fib_table_flush(net, tb);
12581258
fib_free_table(tb);
12591259
}
12601260
}

net/ipv4/fib_rules.c

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -164,6 +164,14 @@ static struct fib_table *fib_empty_table(struct net *net)
164164
return NULL;
165165
}
166166

167+
static int call_fib_rule_notifiers(struct net *net,
168+
enum fib_event_type event_type)
169+
{
170+
struct fib_notifier_info info;
171+
172+
return call_fib_notifiers(net, event_type, &info);
173+
}
174+
167175
static const struct nla_policy fib4_rule_policy[FRA_MAX+1] = {
168176
FRA_GENERIC_POLICY,
169177
[FRA_FLOW] = { .type = NLA_U32 },
@@ -221,6 +229,7 @@ static int fib4_rule_configure(struct fib_rule *rule, struct sk_buff *skb,
221229

222230
net->ipv4.fib_has_custom_rules = true;
223231
fib_flush_external(rule->fr_net);
232+
call_fib_rule_notifiers(net, FIB_EVENT_RULE_ADD);
224233

225234
err = 0;
226235
errout:
@@ -243,6 +252,7 @@ static int fib4_rule_delete(struct fib_rule *rule)
243252
#endif
244253
net->ipv4.fib_has_custom_rules = true;
245254
fib_flush_external(rule->fr_net);
255+
call_fib_rule_notifiers(net, FIB_EVENT_RULE_DEL);
246256
errout:
247257
return err;
248258
}

net/ipv4/fib_trie.c

Lines changed: 59 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -73,6 +73,7 @@
7373
#include <linux/slab.h>
7474
#include <linux/export.h>
7575
#include <linux/vmalloc.h>
76+
#include <linux/notifier.h>
7677
#include <net/net_namespace.h>
7778
#include <net/ip.h>
7879
#include <net/protocol.h>
@@ -84,6 +85,44 @@
8485
#include <trace/events/fib.h>
8586
#include "fib_lookup.h"
8687

88+
static BLOCKING_NOTIFIER_HEAD(fib_chain);
89+
90+
int register_fib_notifier(struct notifier_block *nb)
91+
{
92+
return blocking_notifier_chain_register(&fib_chain, nb);
93+
}
94+
EXPORT_SYMBOL(register_fib_notifier);
95+
96+
int unregister_fib_notifier(struct notifier_block *nb)
97+
{
98+
return blocking_notifier_chain_unregister(&fib_chain, nb);
99+
}
100+
EXPORT_SYMBOL(unregister_fib_notifier);
101+
102+
int call_fib_notifiers(struct net *net, enum fib_event_type event_type,
103+
struct fib_notifier_info *info)
104+
{
105+
info->net = net;
106+
return blocking_notifier_call_chain(&fib_chain, event_type, info);
107+
}
108+
109+
static int call_fib_entry_notifiers(struct net *net,
110+
enum fib_event_type event_type, u32 dst,
111+
int dst_len, struct fib_info *fi,
112+
u8 tos, u8 type, u32 tb_id, u32 nlflags)
113+
{
114+
struct fib_entry_notifier_info info = {
115+
.dst = dst,
116+
.dst_len = dst_len,
117+
.fi = fi,
118+
.tos = tos,
119+
.type = type,
120+
.tb_id = tb_id,
121+
.nlflags = nlflags,
122+
};
123+
return call_fib_notifiers(net, event_type, &info.info);
124+
}
125+
87126
#define MAX_STAT_DEPTH 32
88127

89128
#define KEYLENGTH (8*sizeof(t_key))
@@ -1076,7 +1115,8 @@ static int fib_insert_alias(struct trie *t, struct key_vector *tp,
10761115
}
10771116

10781117
/* Caller must hold RTNL. */
1079-
int fib_table_insert(struct fib_table *tb, struct fib_config *cfg)
1118+
int fib_table_insert(struct net *net, struct fib_table *tb,
1119+
struct fib_config *cfg)
10801120
{
10811121
struct trie *t = (struct trie *)tb->tb_data;
10821122
struct fib_alias *fa, *new_fa;
@@ -1193,6 +1233,11 @@ int fib_table_insert(struct fib_table *tb, struct fib_config *cfg)
11931233
fib_release_info(fi_drop);
11941234
if (state & FA_S_ACCESSED)
11951235
rt_cache_flush(cfg->fc_nlinfo.nl_net);
1236+
1237+
call_fib_entry_notifiers(net, FIB_EVENT_ENTRY_ADD,
1238+
key, plen, fi,
1239+
new_fa->fa_tos, cfg->fc_type,
1240+
tb->tb_id, cfg->fc_nlflags);
11961241
rtmsg_fib(RTM_NEWROUTE, htonl(key), new_fa, plen,
11971242
tb->tb_id, &cfg->fc_nlinfo, nlflags);
11981243

@@ -1245,6 +1290,8 @@ int fib_table_insert(struct fib_table *tb, struct fib_config *cfg)
12451290
tb->tb_num_default++;
12461291

12471292
rt_cache_flush(cfg->fc_nlinfo.nl_net);
1293+
call_fib_entry_notifiers(net, FIB_EVENT_ENTRY_ADD, key, plen, fi, tos,
1294+
cfg->fc_type, tb->tb_id, cfg->fc_nlflags);
12481295
rtmsg_fib(RTM_NEWROUTE, htonl(key), new_fa, plen, new_fa->tb_id,
12491296
&cfg->fc_nlinfo, nlflags);
12501297
succeeded:
@@ -1490,7 +1537,8 @@ static void fib_remove_alias(struct trie *t, struct key_vector *tp,
14901537
}
14911538

14921539
/* Caller must hold RTNL. */
1493-
int fib_table_delete(struct fib_table *tb, struct fib_config *cfg)
1540+
int fib_table_delete(struct net *net, struct fib_table *tb,
1541+
struct fib_config *cfg)
14941542
{
14951543
struct trie *t = (struct trie *) tb->tb_data;
14961544
struct fib_alias *fa, *fa_to_delete;
@@ -1546,6 +1594,9 @@ int fib_table_delete(struct fib_table *tb, struct fib_config *cfg)
15461594
switchdev_fib_ipv4_del(key, plen, fa_to_delete->fa_info, tos,
15471595
cfg->fc_type, tb->tb_id);
15481596

1597+
call_fib_entry_notifiers(net, FIB_EVENT_ENTRY_DEL, key, plen,
1598+
fa_to_delete->fa_info, tos, cfg->fc_type,
1599+
tb->tb_id, 0);
15491600
rtmsg_fib(RTM_DELROUTE, htonl(key), fa_to_delete, plen, tb->tb_id,
15501601
&cfg->fc_nlinfo, 0);
15511602

@@ -1809,7 +1860,7 @@ void fib_table_flush_external(struct fib_table *tb)
18091860
}
18101861

18111862
/* Caller must hold RTNL. */
1812-
int fib_table_flush(struct fib_table *tb)
1863+
int fib_table_flush(struct net *net, struct fib_table *tb)
18131864
{
18141865
struct trie *t = (struct trie *)tb->tb_data;
18151866
struct key_vector *pn = t->kv;
@@ -1861,6 +1912,11 @@ int fib_table_flush(struct fib_table *tb)
18611912
switchdev_fib_ipv4_del(n->key, KEYLENGTH - fa->fa_slen,
18621913
fi, fa->fa_tos, fa->fa_type,
18631914
tb->tb_id);
1915+
call_fib_entry_notifiers(net, FIB_EVENT_ENTRY_DEL,
1916+
n->key,
1917+
KEYLENGTH - fa->fa_slen,
1918+
fi, fa->fa_tos, fa->fa_type,
1919+
tb->tb_id, 0);
18641920
hlist_del_rcu(&fa->fa_list);
18651921
fib_release_info(fa->fa_info);
18661922
alias_free_mem_rcu(fa);

0 commit comments

Comments
 (0)