nexthop: Expand nexthop_is_multipath in a few places

I got too fancy consolidating checks on multipath type. The result
is that path lookups can access 2 different nh_grp structs as exposed
by Nik's torture tests. Expand nexthop_is_multipath within nexthop.h to
avoid multiple, nh_grp dereferences and make decisions based on the
consistent struct.

Only 2 places left using nexthop_is_multipath are within IPv6, both
only check that the nexthop is a multipath for a branching decision
which are acceptable.

Fixes: 430a049190 ("nexthop: Add support for nexthop groups")
Signed-off-by: David Ahern <dsahern@gmail.com>
Acked-by: Nikolay Aleksandrov <nikolay@cumulusnetworks.com>
Signed-off-by: David S. Miller <davem@davemloft.net>
This commit is contained in:
David Ahern 2020-05-26 12:56:16 -06:00 коммит произвёл David S. Miller
Родитель 90f33bffa3
Коммит 0b5e2e3973
1 изменённых файлов: 25 добавлений и 16 удалений

Просмотреть файл

@ -137,10 +137,11 @@ static inline unsigned int nexthop_num_path(const struct nexthop *nh)
{
unsigned int rc = 1;
if (nexthop_is_multipath(nh)) {
if (nh->is_group) {
struct nh_group *nh_grp;
nh_grp = rcu_dereference_rtnl(nh->nh_grp);
if (nh_grp->mpath)
rc = nh_grp->num_nh;
}
@ -148,10 +149,8 @@ static inline unsigned int nexthop_num_path(const struct nexthop *nh)
}
static inline
struct nexthop *nexthop_mpath_select(const struct nexthop *nh, int nhsel)
struct nexthop *nexthop_mpath_select(const struct nh_group *nhg, int nhsel)
{
const struct nh_group *nhg = rcu_dereference_rtnl(nh->nh_grp);
/* for_nexthops macros in fib_semantics.c grabs a pointer to
* the nexthop before checking nhsel
*/
@ -186,12 +185,14 @@ static inline bool nexthop_is_blackhole(const struct nexthop *nh)
{
const struct nh_info *nhi;
if (nexthop_is_multipath(nh)) {
if (nexthop_num_path(nh) > 1)
return false;
nh = nexthop_mpath_select(nh, 0);
if (!nh)
if (nh->is_group) {
struct nh_group *nh_grp;
nh_grp = rcu_dereference_rtnl(nh->nh_grp);
if (nh_grp->num_nh > 1)
return false;
nh = nh_grp->nh_entries[0].nh;
}
nhi = rcu_dereference_rtnl(nh->nh_info);
@ -217,11 +218,16 @@ struct fib_nh_common *nexthop_fib_nhc(struct nexthop *nh, int nhsel)
BUILD_BUG_ON(offsetof(struct fib_nh, nh_common) != 0);
BUILD_BUG_ON(offsetof(struct fib6_nh, nh_common) != 0);
if (nexthop_is_multipath(nh)) {
nh = nexthop_mpath_select(nh, nhsel);
if (nh->is_group) {
struct nh_group *nh_grp;
nh_grp = rcu_dereference_rtnl(nh->nh_grp);
if (nh_grp->mpath) {
nh = nexthop_mpath_select(nh_grp, nhsel);
if (!nh)
return NULL;
}
}
nhi = rcu_dereference_rtnl(nh->nh_info);
return &nhi->fib_nhc;
@ -264,8 +270,11 @@ static inline struct fib6_nh *nexthop_fib6_nh(struct nexthop *nh)
{
struct nh_info *nhi;
if (nexthop_is_multipath(nh)) {
nh = nexthop_mpath_select(nh, 0);
if (nh->is_group) {
struct nh_group *nh_grp;
nh_grp = rcu_dereference_rtnl(nh->nh_grp);
nh = nexthop_mpath_select(nh_grp, 0);
if (!nh)
return NULL;
}