Message ID | 20200526150114.41687-2-dsahern@kernel.org |
---|---|
State | Accepted |
Delegated to: | David Miller |
Headers | show |
Series | nexthops: Fix 2 fundamental flaws with nexthop groups | expand |
On 26/05/2020 18:01, David Ahern wrote: > From: David Ahern <dsahern@gmail.com> > > Move nh_grp dereference and check for removing nexthop group due to > all members gone into remove_nh_grp_entry. > > Fixes: 430a049190de ("nexthop: Add support for nexthop groups") > Signed-off-by: David Ahern <dsahern@gmail.com> > --- > net/ipv4/nexthop.c | 27 +++++++++++++-------------- > 1 file changed, 13 insertions(+), 14 deletions(-) > Acked-by: Nikolay Aleksandrov <nikolay@cumulusnetworks.com> > diff --git a/net/ipv4/nexthop.c b/net/ipv4/nexthop.c > index 2a31c4af845e..0f68d9801808 100644 > --- a/net/ipv4/nexthop.c > +++ b/net/ipv4/nexthop.c > @@ -693,17 +693,21 @@ static void nh_group_rebalance(struct nh_group *nhg) > } > } > > -static void remove_nh_grp_entry(struct nh_grp_entry *nhge, > - struct nh_group *nhg, > +static void remove_nh_grp_entry(struct net *net, struct nh_grp_entry *nhge, > struct nl_info *nlinfo) > { > + struct nexthop *nhp = nhge->nh_parent; > struct nexthop *nh = nhge->nh; > struct nh_grp_entry *nhges; > + struct nh_group *nhg; > bool found = false; > int i; > > WARN_ON(!nh); > > + list_del(&nhge->nh_list); > + > + nhg = rtnl_dereference(nhp->nh_grp); > nhges = nhg->nh_entries; > for (i = 0; i < nhg->num_nh; ++i) { > if (found) { > @@ -727,7 +731,11 @@ static void remove_nh_grp_entry(struct nh_grp_entry *nhge, > nexthop_put(nh); > > if (nlinfo) > - nexthop_notify(RTM_NEWNEXTHOP, nhge->nh_parent, nlinfo); > + nexthop_notify(RTM_NEWNEXTHOP, nhp, nlinfo); > + > + /* if this group has no more entries then remove it */ > + if (!nhg->num_nh) > + remove_nexthop(net, nhp, nlinfo); > } > > static void remove_nexthop_from_groups(struct net *net, struct nexthop *nh, > @@ -735,17 +743,8 @@ static void remove_nexthop_from_groups(struct net *net, struct nexthop *nh, > { > struct nh_grp_entry *nhge, *tmp; > > - list_for_each_entry_safe(nhge, tmp, &nh->grp_list, nh_list) { > - struct nh_group *nhg; > - > - list_del(&nhge->nh_list); > - nhg = rtnl_dereference(nhge->nh_parent->nh_grp); > - remove_nh_grp_entry(nhge, nhg, nlinfo); > - > - /* if this group has no more entries then remove it */ > - if (!nhg->num_nh) > - remove_nexthop(net, nhge->nh_parent, nlinfo); > - } > + list_for_each_entry_safe(nhge, tmp, &nh->grp_list, nh_list) > + remove_nh_grp_entry(net, nhge, nlinfo); > } > > static void remove_nexthop_group(struct nexthop *nh, struct nl_info *nlinfo) >
diff --git a/net/ipv4/nexthop.c b/net/ipv4/nexthop.c index 2a31c4af845e..0f68d9801808 100644 --- a/net/ipv4/nexthop.c +++ b/net/ipv4/nexthop.c @@ -693,17 +693,21 @@ static void nh_group_rebalance(struct nh_group *nhg) } } -static void remove_nh_grp_entry(struct nh_grp_entry *nhge, - struct nh_group *nhg, +static void remove_nh_grp_entry(struct net *net, struct nh_grp_entry *nhge, struct nl_info *nlinfo) { + struct nexthop *nhp = nhge->nh_parent; struct nexthop *nh = nhge->nh; struct nh_grp_entry *nhges; + struct nh_group *nhg; bool found = false; int i; WARN_ON(!nh); + list_del(&nhge->nh_list); + + nhg = rtnl_dereference(nhp->nh_grp); nhges = nhg->nh_entries; for (i = 0; i < nhg->num_nh; ++i) { if (found) { @@ -727,7 +731,11 @@ static void remove_nh_grp_entry(struct nh_grp_entry *nhge, nexthop_put(nh); if (nlinfo) - nexthop_notify(RTM_NEWNEXTHOP, nhge->nh_parent, nlinfo); + nexthop_notify(RTM_NEWNEXTHOP, nhp, nlinfo); + + /* if this group has no more entries then remove it */ + if (!nhg->num_nh) + remove_nexthop(net, nhp, nlinfo); } static void remove_nexthop_from_groups(struct net *net, struct nexthop *nh, @@ -735,17 +743,8 @@ static void remove_nexthop_from_groups(struct net *net, struct nexthop *nh, { struct nh_grp_entry *nhge, *tmp; - list_for_each_entry_safe(nhge, tmp, &nh->grp_list, nh_list) { - struct nh_group *nhg; - - list_del(&nhge->nh_list); - nhg = rtnl_dereference(nhge->nh_parent->nh_grp); - remove_nh_grp_entry(nhge, nhg, nlinfo); - - /* if this group has no more entries then remove it */ - if (!nhg->num_nh) - remove_nexthop(net, nhge->nh_parent, nlinfo); - } + list_for_each_entry_safe(nhge, tmp, &nh->grp_list, nh_list) + remove_nh_grp_entry(net, nhge, nlinfo); } static void remove_nexthop_group(struct nexthop *nh, struct nl_info *nlinfo)