On 26/05/2020 18:01, David Ahern wrote: > From: David Ahern <dsah...@gmail.com> > > Similar to the last path, need to fix fib_info_nh_uses_dev for > external nexthops to avoid referencing multiple nh_grp structs. > Move the device check in fib_info_nh_uses_dev to a helper and > create a nexthop version that is called if the fib_info uses an > external nexthop. > > Fixes: 430a049190de ("nexthop: Add support for nexthop groups") > Signed-off-by: David Ahern <dsah...@gmail.com> > --- > include/net/ip_fib.h | 10 ++++++++++ > include/net/nexthop.h | 25 +++++++++++++++++++++++++ > net/ipv4/fib_frontend.c | 19 ++++++++++--------- > 3 files changed, 45 insertions(+), 9 deletions(-) >
Acked-by: Nikolay Aleksandrov <niko...@cumulusnetworks.com> > diff --git a/include/net/ip_fib.h b/include/net/ip_fib.h > index 1f1dd22980e4..6683558db7c9 100644 > --- a/include/net/ip_fib.h > +++ b/include/net/ip_fib.h > @@ -448,6 +448,16 @@ static inline int fib_num_tclassid_users(struct net *net) > #endif > int fib_unmerge(struct net *net); > > +static inline bool nhc_l3mdev_matches_dev(const struct fib_nh_common *nhc, > +const struct net_device *dev) > +{ > + if (nhc->nhc_dev == dev || > + l3mdev_master_ifindex_rcu(nhc->nhc_dev) == dev->ifindex) > + return true; > + > + return false; > +} > + > /* Exported by fib_semantics.c */ > int ip_fib_check_default(__be32 gw, struct net_device *dev); > int fib_sync_down_dev(struct net_device *dev, unsigned long event, bool > force); > diff --git a/include/net/nexthop.h b/include/net/nexthop.h > index 9414ae46fc1c..35680a8c2a1c 100644 > --- a/include/net/nexthop.h > +++ b/include/net/nexthop.h > @@ -266,6 +266,31 @@ struct fib_nh_common *nexthop_get_nhc_lookup(const > struct nexthop *nh, > return NULL; > } > > +static inline bool nexthop_uses_dev(const struct nexthop *nh, > + const struct net_device *dev) > +{ > + struct nh_info *nhi; > + > + if (nh->is_group) { > + struct nh_group *nhg = rcu_dereference(nh->nh_grp); > + int i; > + > + for (i = 0; i < nhg->num_nh; i++) { > + struct nexthop *nhe = nhg->nh_entries[i].nh; > + > + nhi = rcu_dereference(nhe->nh_info); > + if (nhc_l3mdev_matches_dev(&nhi->fib_nhc, dev)) > + return true; > + } > + } else { > + nhi = rcu_dereference(nh->nh_info); > + if (nhc_l3mdev_matches_dev(&nhi->fib_nhc, dev)) > + return true; > + } > + > + return false; > +} > + > static inline unsigned int fib_info_num_path(const struct fib_info *fi) > { > if (unlikely(fi->nh)) > diff --git a/net/ipv4/fib_frontend.c b/net/ipv4/fib_frontend.c > index 213be9c050ad..aebb50735c68 100644 > --- a/net/ipv4/fib_frontend.c > +++ b/net/ipv4/fib_frontend.c > @@ -309,17 +309,18 @@ bool fib_info_nh_uses_dev(struct fib_info *fi, const > struct net_device *dev) > { > bool dev_match = false; > #ifdef CONFIG_IP_ROUTE_MULTIPATH > - int ret; > + if (unlikely(fi->nh)) { > + dev_match = nexthop_uses_dev(fi->nh, dev); > + } else { > + int ret; > > - for (ret = 0; ret < fib_info_num_path(fi); ret++) { > - const struct fib_nh_common *nhc = fib_info_nhc(fi, ret); > + for (ret = 0; ret < fib_info_num_path(fi); ret++) { > + const struct fib_nh_common *nhc = fib_info_nhc(fi, ret); > > - if (nhc->nhc_dev == dev) { > - dev_match = true; > - break; > - } else if (l3mdev_master_ifindex_rcu(nhc->nhc_dev) == > dev->ifindex) { > - dev_match = true; > - break; > + if (nhc_l3mdev_matches_dev(nhc, dev)) { > + dev_match = true; > + break; > + } > } > } > #else >