summaryrefslogtreecommitdiff
path: root/zebra/zebra_rib.c
diff options
context:
space:
mode:
Diffstat (limited to 'zebra/zebra_rib.c')
-rw-r--r--zebra/zebra_rib.c26
1 files changed, 23 insertions, 3 deletions
diff --git a/zebra/zebra_rib.c b/zebra/zebra_rib.c
index 99b83d5cd9..ab07549ec2 100644
--- a/zebra/zebra_rib.c
+++ b/zebra/zebra_rib.c
@@ -1501,17 +1501,37 @@ static struct route_entry *rib_choose_best(struct route_entry *current,
/* filter route selection in following order:
* - connected beats other types
+ * - if both connected, loopback or vrf wins
* - lower distance beats higher
* - lower metric beats higher for equal distance
* - last, hence oldest, route wins tie break.
*/
- /* Connected routes. Pick the last connected
+ /* Connected routes. Check to see if either are a vrf
+ * or loopback interface. If not, pick the last connected
* route of the set of lowest metric connected routes.
*/
if (alternate->type == ZEBRA_ROUTE_CONNECT) {
- if (current->type != ZEBRA_ROUTE_CONNECT
- || alternate->metric <= current->metric)
+ if (current->type != ZEBRA_ROUTE_CONNECT)
+ return alternate;
+
+ /* both are connected. are either loop or vrf? */
+ struct nexthop *nexthop = NULL;
+
+ for (ALL_NEXTHOPS(alternate->ng, nexthop)) {
+ if (if_is_loopback_or_vrf(if_lookup_by_index(
+ nexthop->ifindex, alternate->vrf_id)))
+ return alternate;
+ }
+
+ for (ALL_NEXTHOPS(current->ng, nexthop)) {
+ if (if_is_loopback_or_vrf(if_lookup_by_index(
+ nexthop->ifindex, current->vrf_id)))
+ return current;
+ }
+
+ /* Neither are loop or vrf so pick best metric */
+ if (alternate->metric <= current->metric)
return alternate;
return current;