static struct fib6_node *fib6_add_1(struct fib6_node *root,
struct in6_addr *addr, int plen,
int offset, int allow_create,
- int replace_required, int sernum,
+ int replace_required,
struct netlink_ext_ack *extack)
{
struct fib6_node *fn, *in, *ln;
fn->leaf = NULL;
}
- fn->fn_sernum = sernum;
-
return fn;
}
*/
/* Try to walk down on tree. */
- fn->fn_sernum = sernum;
dir = addr_bit_set(addr, fn->fn_bit);
pn = fn;
fn = dir ? fn->right : fn->left;
ln->fn_bit = plen;
ln->parent = pn;
- ln->fn_sernum = sernum;
if (dir)
pn->right = ln;
in->leaf = fn->leaf;
atomic_inc(&in->leaf->rt6i_ref);
- in->fn_sernum = sernum;
-
/* update parent pointer */
if (dir)
pn->right = in;
ln->parent = in;
fn->parent = in;
- ln->fn_sernum = sernum;
-
if (addr_bit_set(addr, bit)) {
in->right = ln;
in->left = fn;
ln->parent = pn;
- ln->fn_sernum = sernum;
-
if (dir)
pn->right = ln;
else
jiffies + net->ipv6.sysctl.ip6_rt_gc_interval);
}
+static void fib6_update_sernum_upto_root(struct rt6_info *rt,
+ int sernum)
+{
+ struct fib6_node *fn = rcu_dereference_protected(rt->rt6i_node,
+ lockdep_is_held(&rt->rt6i_table->tb6_lock));
+
+ /* paired with smp_rmb() in rt6_get_cookie_safe() */
+ smp_wmb();
+ while (fn) {
+ fn->fn_sernum = sernum;
+ fn = fn->parent;
+ }
+}
+
/*
* Add routing information to the routing tree.
* <destination addr>/<source addr>
fn = fib6_add_1(root, &rt->rt6i_dst.addr, rt->rt6i_dst.plen,
offsetof(struct rt6_info, rt6i_dst), allow_create,
- replace_required, sernum, extack);
+ replace_required, extack);
if (IS_ERR(fn)) {
err = PTR_ERR(fn);
fn = NULL;
sfn->leaf = info->nl_net->ipv6.ip6_null_entry;
atomic_inc(&info->nl_net->ipv6.ip6_null_entry->rt6i_ref);
sfn->fn_flags = RTN_ROOT;
- sfn->fn_sernum = sernum;
/* Now add the first leaf node to new subtree */
sn = fib6_add_1(sfn, &rt->rt6i_src.addr,
rt->rt6i_src.plen,
offsetof(struct rt6_info, rt6i_src),
- allow_create, replace_required, sernum,
- extack);
+ allow_create, replace_required, extack);
if (IS_ERR(sn)) {
/* If it is failed, discard just allocated
sn = fib6_add_1(fn->subtree, &rt->rt6i_src.addr,
rt->rt6i_src.plen,
offsetof(struct rt6_info, rt6i_src),
- allow_create, replace_required, sernum,
- extack);
+ allow_create, replace_required, extack);
if (IS_ERR(sn)) {
err = PTR_ERR(sn);
#endif
err = fib6_add_rt2node(fn, rt, info, mxc);
- if (!err)
+ if (!err) {
+ fib6_update_sernum_upto_root(rt, sernum);
fib6_start_gc(info->nl_net, rt);
+ }
out:
if (err) {