path: root/net/ipv4
diff options
authorIdo Schimmel <idosch@mellanox.com>2020-01-14 13:23:09 +0200
committerDavid S. Miller <davem@davemloft.net>2020-01-14 18:53:35 -0800
commit6324d0fa03bf118e9682b6f3da437deaadb61924 (patch)
tree7d26791a03f990af174053d672cc66bc431697ed /net/ipv4
parentnet: socionext: get rid of huge dma sync in netsec_alloc_rx_data (diff)
ipv4: Replace route in list before notifying
Subsequent patches will add an offload / trap indication to routes which will signal if the route is present in hardware or not. After programming the route to the hardware, drivers will have to ask the IPv4 code to set the flags by passing the route's key. In the case of route replace, the new route is notified before it is actually inserted into the FIB alias list. This can prevent simple drivers (e.g., netdevsim) that program the route to the hardware in the same context it is notified in from being able to set the flag. Solve this by first inserting the new route to the list and rollback the operation in case the route was vetoed. Signed-off-by: Ido Schimmel <idosch@mellanox.com> Reviewed-by: Jiri Pirko <jiri@mellanox.com> Reviewed-by: David Ahern <dsahern@gmail.com> Signed-off-by: David S. Miller <davem@davemloft.net>
Diffstat (limited to 'net/ipv4')
1 files changed, 7 insertions, 4 deletions
diff --git a/net/ipv4/fib_trie.c b/net/ipv4/fib_trie.c
index b92a42433a7d..39f56d68ec19 100644
--- a/net/ipv4/fib_trie.c
+++ b/net/ipv4/fib_trie.c
@@ -1221,23 +1221,26 @@ int fib_table_insert(struct net *net, struct fib_table *tb,
new_fa->tb_id = tb->tb_id;
new_fa->fa_default = -1;
+ hlist_replace_rcu(&fa->fa_list, &new_fa->fa_list);
if (fib_find_alias(&l->leaf, fa->fa_slen, 0, 0,
- tb->tb_id, true) == fa) {
+ tb->tb_id, true) == new_fa) {
enum fib_event_type fib_event;
err = call_fib_entry_notifiers(net, fib_event,
key, plen,
new_fa, extack);
- if (err)
+ if (err) {
+ hlist_replace_rcu(&new_fa->fa_list,
+ &fa->fa_list);
goto out_free_new_fa;
+ }
rtmsg_fib(RTM_NEWROUTE, htonl(key), new_fa, plen,
tb->tb_id, &cfg->fc_nlinfo, nlflags);
- hlist_replace_rcu(&fa->fa_list, &new_fa->fa_list);