Commit 307f2fb95e9b96b3577916e73d92e104f8f26494

Authored by Hannes Frederic Sowa
Committed by David S. Miller
1 parent 9b4fe5fb0b

ipv6: only static routes qualify for equal cost multipathing

Static routes in this case are non-expiring routes which did not get
configured by autoconf or by icmpv6 redirects.

To make sure we actually get an ecmp route while searching for the first
one in this fib6_node's leafs, also make sure it matches the ecmp route
assumptions.

v2:
a) Removed RTF_EXPIRE check in dst.from chain. The check of RTF_ADDRCONF
   already ensures that this route, even if added again without
   RTF_EXPIRES (in case of a RA announcement with infinite timeout),
   does not cause the rt6i_nsiblings logic to go wrong if a later RA
   updates the expiration time later.

v3:
a) Allow RTF_EXPIRES routes to enter the ecmp route set. We have to do so,
   because an pmtu event could update the RTF_EXPIRES flag and we would
   not count this route, if another route joins this set. We now filter
   only for RTF_GATEWAY|RTF_ADDRCONF|RTF_DYNAMIC, which are flags that
   don't get changed after rt6_info construction.

Cc: Nicolas Dichtel <nicolas.dichtel@6wind.com>
Signed-off-by: Hannes Frederic Sowa <hannes@stressinduktion.org>
Signed-off-by: David S. Miller <davem@davemloft.net>

Showing 1 changed file with 11 additions and 4 deletions Side-by-side Diff

... ... @@ -632,6 +632,12 @@
632 632 return ln;
633 633 }
634 634  
  635 +static inline bool rt6_qualify_for_ecmp(struct rt6_info *rt)
  636 +{
  637 + return (rt->rt6i_flags & (RTF_GATEWAY|RTF_ADDRCONF|RTF_DYNAMIC)) ==
  638 + RTF_GATEWAY;
  639 +}
  640 +
635 641 /*
636 642 * Insert routing information in a node.
637 643 */
... ... @@ -646,6 +652,7 @@
646 652 int add = (!info->nlh ||
647 653 (info->nlh->nlmsg_flags & NLM_F_CREATE));
648 654 int found = 0;
  655 + bool rt_can_ecmp = rt6_qualify_for_ecmp(rt);
649 656  
650 657 ins = &fn->leaf;
651 658  
... ... @@ -691,9 +698,8 @@
691 698 * To avoid long list, we only had siblings if the
692 699 * route have a gateway.
693 700 */
694   - if (rt->rt6i_flags & RTF_GATEWAY &&
695   - !(rt->rt6i_flags & RTF_EXPIRES) &&
696   - !(iter->rt6i_flags & RTF_EXPIRES))
  701 + if (rt_can_ecmp &&
  702 + rt6_qualify_for_ecmp(iter))
697 703 rt->rt6i_nsiblings++;
698 704 }
699 705  
... ... @@ -715,7 +721,8 @@
715 721 /* Find the first route that have the same metric */
716 722 sibling = fn->leaf;
717 723 while (sibling) {
718   - if (sibling->rt6i_metric == rt->rt6i_metric) {
  724 + if (sibling->rt6i_metric == rt->rt6i_metric &&
  725 + rt6_qualify_for_ecmp(sibling)) {
719 726 list_add_tail(&rt->rt6i_siblings,
720 727 &sibling->rt6i_siblings);
721 728 break;