Skip to content

Commit

Permalink
Merge branch 'ipv6-multipath-routing-fixes'
Browse files Browse the repository at this point in the history
Ido Schimmel says:

====================
ipv6: Multipath routing fixes

This patchset contains two fixes for IPv6 multipath routing. See the
commit messages for more details.
====================

Link: https://patch.msgid.link/20250402114224.293392-1-idosch@nvidia.com
Signed-off-by: Jakub Kicinski <kuba@kernel.org>
  • Loading branch information
Jakub Kicinski committed Apr 4, 2025
2 parents 51de360 + 8b8e0dd commit 613f727
Showing 1 changed file with 38 additions and 4 deletions.
42 changes: 38 additions & 4 deletions net/ipv6/route.c
Original file line number Diff line number Diff line change
Expand Up @@ -412,12 +412,37 @@ static bool rt6_check_expired(const struct rt6_info *rt)
return false;
}

static struct fib6_info *
rt6_multipath_first_sibling_rcu(const struct fib6_info *rt)
{
struct fib6_info *iter;
struct fib6_node *fn;

fn = rcu_dereference(rt->fib6_node);
if (!fn)
goto out;
iter = rcu_dereference(fn->leaf);
if (!iter)
goto out;

while (iter) {
if (iter->fib6_metric == rt->fib6_metric &&
rt6_qualify_for_ecmp(iter))
return iter;
iter = rcu_dereference(iter->fib6_next);
}

out:
return NULL;
}

void fib6_select_path(const struct net *net, struct fib6_result *res,
struct flowi6 *fl6, int oif, bool have_oif_match,
const struct sk_buff *skb, int strict)
{
struct fib6_info *match = res->f6i;
struct fib6_info *first, *match = res->f6i;
struct fib6_info *sibling;
int hash;

if (!match->nh && (!match->fib6_nsiblings || have_oif_match))
goto out;
Expand All @@ -440,16 +465,25 @@ void fib6_select_path(const struct net *net, struct fib6_result *res,
return;
}

if (fl6->mp_hash <= atomic_read(&match->fib6_nh->fib_nh_upper_bound))
first = rt6_multipath_first_sibling_rcu(match);
if (!first)
goto out;

list_for_each_entry_rcu(sibling, &match->fib6_siblings,
hash = fl6->mp_hash;
if (hash <= atomic_read(&first->fib6_nh->fib_nh_upper_bound) &&
rt6_score_route(first->fib6_nh, first->fib6_flags, oif,
strict) >= 0) {
match = first;
goto out;
}

list_for_each_entry_rcu(sibling, &first->fib6_siblings,
fib6_siblings) {
const struct fib6_nh *nh = sibling->fib6_nh;
int nh_upper_bound;

nh_upper_bound = atomic_read(&nh->fib_nh_upper_bound);
if (fl6->mp_hash > nh_upper_bound)
if (hash > nh_upper_bound)
continue;
if (rt6_score_route(nh, sibling->fib6_flags, oif, strict) < 0)
break;
Expand Down

0 comments on commit 613f727

Please sign in to comment.