Skip to content

Commit 613f727

Browse files
committed
Merge branch 'ipv6-multipath-routing-fixes'
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/[email protected] Signed-off-by: Jakub Kicinski <[email protected]>
2 parents 51de360 + 8b8e0dd commit 613f727

File tree

1 file changed

+38
-4
lines changed

1 file changed

+38
-4
lines changed

net/ipv6/route.c

Lines changed: 38 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -412,12 +412,37 @@ static bool rt6_check_expired(const struct rt6_info *rt)
412412
return false;
413413
}
414414

415+
static struct fib6_info *
416+
rt6_multipath_first_sibling_rcu(const struct fib6_info *rt)
417+
{
418+
struct fib6_info *iter;
419+
struct fib6_node *fn;
420+
421+
fn = rcu_dereference(rt->fib6_node);
422+
if (!fn)
423+
goto out;
424+
iter = rcu_dereference(fn->leaf);
425+
if (!iter)
426+
goto out;
427+
428+
while (iter) {
429+
if (iter->fib6_metric == rt->fib6_metric &&
430+
rt6_qualify_for_ecmp(iter))
431+
return iter;
432+
iter = rcu_dereference(iter->fib6_next);
433+
}
434+
435+
out:
436+
return NULL;
437+
}
438+
415439
void fib6_select_path(const struct net *net, struct fib6_result *res,
416440
struct flowi6 *fl6, int oif, bool have_oif_match,
417441
const struct sk_buff *skb, int strict)
418442
{
419-
struct fib6_info *match = res->f6i;
443+
struct fib6_info *first, *match = res->f6i;
420444
struct fib6_info *sibling;
445+
int hash;
421446

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

443-
if (fl6->mp_hash <= atomic_read(&match->fib6_nh->fib_nh_upper_bound))
468+
first = rt6_multipath_first_sibling_rcu(match);
469+
if (!first)
444470
goto out;
445471

446-
list_for_each_entry_rcu(sibling, &match->fib6_siblings,
472+
hash = fl6->mp_hash;
473+
if (hash <= atomic_read(&first->fib6_nh->fib_nh_upper_bound) &&
474+
rt6_score_route(first->fib6_nh, first->fib6_flags, oif,
475+
strict) >= 0) {
476+
match = first;
477+
goto out;
478+
}
479+
480+
list_for_each_entry_rcu(sibling, &first->fib6_siblings,
447481
fib6_siblings) {
448482
const struct fib6_nh *nh = sibling->fib6_nh;
449483
int nh_upper_bound;
450484

451485
nh_upper_bound = atomic_read(&nh->fib_nh_upper_bound);
452-
if (fl6->mp_hash > nh_upper_bound)
486+
if (hash > nh_upper_bound)
453487
continue;
454488
if (rt6_score_route(nh, sibling->fib6_flags, oif, strict) < 0)
455489
break;

0 commit comments

Comments
 (0)