lkml.org 
[lkml]   [2021]   [Nov]   [29]   [last100]   RSS Feed
Views: [wrap][no wrap]   [headers]  [forward] 
 
Messages in this thread
    Patch in this message
    /
    From
    Subject[PATCH 5.4 60/92] net: ipv6: add fib6_nh_release_dsts stub
    Date
    From: Nikolay Aleksandrov <nikolay@nvidia.com>

    [ Upstream commit 8837cbbf854246f5f4d565f21e6baa945d37aded ]

    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: 7bf4796dd099 ("nexthops: add support for replace")
    Signed-off-by: Nikolay Aleksandrov <nikolay@nvidia.com>
    Signed-off-by: David S. Miller <davem@davemloft.net>
    Signed-off-by: Sasha Levin <sashal@kernel.org>
    ---
    include/net/ip6_fib.h | 1 +
    include/net/ipv6_stubs.h | 1 +
    net/ipv6/af_inet6.c | 1 +
    net/ipv6/route.c | 19 +++++++++++++++++++
    4 files changed, 22 insertions(+)

    diff --git a/include/net/ip6_fib.h b/include/net/ip6_fib.h
    index bd0f1595bdc71..05ecaefeb6322 100644
    --- a/include/net/ip6_fib.h
    +++ b/include/net/ip6_fib.h
    @@ -451,6 +451,7 @@ int fib6_nh_init(struct net *net, struct fib6_nh *fib6_nh,
    struct fib6_config *cfg, gfp_t gfp_flags,
    struct netlink_ext_ack *extack);
    void fib6_nh_release(struct fib6_nh *fib6_nh);
    +void fib6_nh_release_dsts(struct fib6_nh *fib6_nh);

    int call_fib6_entry_notifiers(struct net *net,
    enum fib_event_type event_type,
    diff --git a/include/net/ipv6_stubs.h b/include/net/ipv6_stubs.h
    index 3e7d2c0e79ca1..af9e127779adf 100644
    --- a/include/net/ipv6_stubs.h
    +++ b/include/net/ipv6_stubs.h
    @@ -47,6 +47,7 @@ struct ipv6_stub {
    struct fib6_config *cfg, gfp_t gfp_flags,
    struct netlink_ext_ack *extack);
    void (*fib6_nh_release)(struct fib6_nh *fib6_nh);
    + void (*fib6_nh_release_dsts)(struct fib6_nh *fib6_nh);
    void (*fib6_update_sernum)(struct net *net, struct fib6_info *rt);
    int (*ip6_del_rt)(struct net *net, struct fib6_info *rt);
    void (*fib6_rt_update)(struct net *net, struct fib6_info *rt,
    diff --git a/net/ipv6/af_inet6.c b/net/ipv6/af_inet6.c
    index 14ac1d9112877..942da168f18fb 100644
    --- a/net/ipv6/af_inet6.c
    +++ b/net/ipv6/af_inet6.c
    @@ -955,6 +955,7 @@ static const struct ipv6_stub ipv6_stub_impl = {
    .ip6_mtu_from_fib6 = ip6_mtu_from_fib6,
    .fib6_nh_init = fib6_nh_init,
    .fib6_nh_release = fib6_nh_release,
    + .fib6_nh_release_dsts = fib6_nh_release_dsts,
    .fib6_update_sernum = fib6_update_sernum_stub,
    .fib6_rt_update = fib6_rt_update,
    .ip6_del_rt = ip6_del_rt,
    diff --git a/net/ipv6/route.c b/net/ipv6/route.c
    index daa876c6ae8db..f36db3dd97346 100644
    --- a/net/ipv6/route.c
    +++ b/net/ipv6/route.c
    @@ -3585,6 +3585,25 @@ void fib6_nh_release(struct fib6_nh *fib6_nh)
    fib_nh_common_release(&fib6_nh->nh_common);
    }

    +void fib6_nh_release_dsts(struct fib6_nh *fib6_nh)
    +{
    + int cpu;
    +
    + if (!fib6_nh->rt6i_pcpu)
    + return;
    +
    + for_each_possible_cpu(cpu) {
    + struct rt6_info *pcpu_rt, **ppcpu_rt;
    +
    + ppcpu_rt = per_cpu_ptr(fib6_nh->rt6i_pcpu, cpu);
    + pcpu_rt = xchg(ppcpu_rt, NULL);
    + if (pcpu_rt) {
    + dst_dev_put(&pcpu_rt->dst);
    + dst_release(&pcpu_rt->dst);
    + }
    + }
    +}
    +
    static struct fib6_info *ip6_route_info_create(struct fib6_config *cfg,
    gfp_t gfp_flags,
    struct netlink_ext_ack *extack)
    --
    2.33.0


    \
     
     \ /
      Last update: 2021-11-29 19:28    [W:3.629 / U:0.004 seconds]
    ©2003-2020 Jasper Spaans|hosted at Digital Ocean and TransIP|Read the blog|Advertise on this site