|
@@ -632,6 +632,12 @@ insert_above:
|
|
|
return ln;
|
|
|
}
|
|
|
|
|
|
+static inline bool rt6_qualify_for_ecmp(struct rt6_info *rt)
|
|
|
+{
|
|
|
+ return (rt->rt6i_flags & (RTF_GATEWAY|RTF_ADDRCONF|RTF_DYNAMIC)) ==
|
|
|
+ RTF_GATEWAY;
|
|
|
+}
|
|
|
+
|
|
|
/*
|
|
|
* Insert routing information in a node.
|
|
|
*/
|
|
@@ -646,6 +652,7 @@ static int fib6_add_rt2node(struct fib6_node *fn, struct rt6_info *rt,
|
|
|
int add = (!info->nlh ||
|
|
|
(info->nlh->nlmsg_flags & NLM_F_CREATE));
|
|
|
int found = 0;
|
|
|
+ bool rt_can_ecmp = rt6_qualify_for_ecmp(rt);
|
|
|
|
|
|
ins = &fn->leaf;
|
|
|
|
|
@@ -691,9 +698,8 @@ static int fib6_add_rt2node(struct fib6_node *fn, struct rt6_info *rt,
|
|
|
* To avoid long list, we only had siblings if the
|
|
|
* route have a gateway.
|
|
|
*/
|
|
|
- if (rt->rt6i_flags & RTF_GATEWAY &&
|
|
|
- !(rt->rt6i_flags & RTF_EXPIRES) &&
|
|
|
- !(iter->rt6i_flags & RTF_EXPIRES))
|
|
|
+ if (rt_can_ecmp &&
|
|
|
+ rt6_qualify_for_ecmp(iter))
|
|
|
rt->rt6i_nsiblings++;
|
|
|
}
|
|
|
|
|
@@ -715,7 +721,8 @@ static int fib6_add_rt2node(struct fib6_node *fn, struct rt6_info *rt,
|
|
|
/* Find the first route that have the same metric */
|
|
|
sibling = fn->leaf;
|
|
|
while (sibling) {
|
|
|
- if (sibling->rt6i_metric == rt->rt6i_metric) {
|
|
|
+ if (sibling->rt6i_metric == rt->rt6i_metric &&
|
|
|
+ rt6_qualify_for_ecmp(sibling)) {
|
|
|
list_add_tail(&rt->rt6i_siblings,
|
|
|
&sibling->rt6i_siblings);
|
|
|
break;
|