Skip to content

Commit 8837cbb

Browse files
Nikolay Aleksandrovdavem330
authored andcommitted
net: ipv6: add fib6_nh_release_dsts stub
We need a way to release a fib6_nh's per-cpu dsts when replacing nexthops otherwise we can end up with stale per-cpu dsts which hold net device references, so add a new IPv6 stub called fib6_nh_release_dsts. It must be used after an RCU grace period, so no new dsts can be created through a group's nexthop entry. Similar to fib6_nh_release it shouldn't be used if fib6_nh_init has failed so it doesn't need a dummy stub when IPv6 is not enabled. Fixes: 7bf4796 ("nexthops: add support for replace") Signed-off-by: Nikolay Aleksandrov <[email protected]> Signed-off-by: David S. Miller <[email protected]>
1 parent 4177d5b commit 8837cbb

File tree

4 files changed

+22
-0
lines changed

4 files changed

+22
-0
lines changed

include/net/ip6_fib.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -485,6 +485,7 @@ int fib6_nh_init(struct net *net, struct fib6_nh *fib6_nh,
485485
struct fib6_config *cfg, gfp_t gfp_flags,
486486
struct netlink_ext_ack *extack);
487487
void fib6_nh_release(struct fib6_nh *fib6_nh);
488+
void fib6_nh_release_dsts(struct fib6_nh *fib6_nh);
488489

489490
int call_fib6_entry_notifiers(struct net *net,
490491
enum fib_event_type event_type,

include/net/ipv6_stubs.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -47,6 +47,7 @@ struct ipv6_stub {
4747
struct fib6_config *cfg, gfp_t gfp_flags,
4848
struct netlink_ext_ack *extack);
4949
void (*fib6_nh_release)(struct fib6_nh *fib6_nh);
50+
void (*fib6_nh_release_dsts)(struct fib6_nh *fib6_nh);
5051
void (*fib6_update_sernum)(struct net *net, struct fib6_info *rt);
5152
int (*ip6_del_rt)(struct net *net, struct fib6_info *rt, bool skip_notify);
5253
void (*fib6_rt_update)(struct net *net, struct fib6_info *rt,

net/ipv6/af_inet6.c

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1026,6 +1026,7 @@ static const struct ipv6_stub ipv6_stub_impl = {
10261026
.ip6_mtu_from_fib6 = ip6_mtu_from_fib6,
10271027
.fib6_nh_init = fib6_nh_init,
10281028
.fib6_nh_release = fib6_nh_release,
1029+
.fib6_nh_release_dsts = fib6_nh_release_dsts,
10291030
.fib6_update_sernum = fib6_update_sernum_stub,
10301031
.fib6_rt_update = fib6_rt_update,
10311032
.ip6_del_rt = ip6_del_rt,

net/ipv6/route.c

Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3680,6 +3680,25 @@ void fib6_nh_release(struct fib6_nh *fib6_nh)
36803680
fib_nh_common_release(&fib6_nh->nh_common);
36813681
}
36823682

3683+
void fib6_nh_release_dsts(struct fib6_nh *fib6_nh)
3684+
{
3685+
int cpu;
3686+
3687+
if (!fib6_nh->rt6i_pcpu)
3688+
return;
3689+
3690+
for_each_possible_cpu(cpu) {
3691+
struct rt6_info *pcpu_rt, **ppcpu_rt;
3692+
3693+
ppcpu_rt = per_cpu_ptr(fib6_nh->rt6i_pcpu, cpu);
3694+
pcpu_rt = xchg(ppcpu_rt, NULL);
3695+
if (pcpu_rt) {
3696+
dst_dev_put(&pcpu_rt->dst);
3697+
dst_release(&pcpu_rt->dst);
3698+
}
3699+
}
3700+
}
3701+
36833702
static struct fib6_info *ip6_route_info_create(struct fib6_config *cfg,
36843703
gfp_t gfp_flags,
36853704
struct netlink_ext_ack *extack)

0 commit comments

Comments
 (0)