From bab85d4fcbc55577019bd746b9cc9073778721ce Mon Sep 17 00:00:00 2001 From: Christian Franke Date: Wed, 24 Aug 2016 17:09:14 +0200 Subject: [PATCH] zebra: assorted parts of 0abf6796c MIME-Version: 1.0 Content-Type: text/plain; charset=utf8 Content-Transfer-Encoding: 8bit Author: Timo Teräs Date: Fri Jan 15 17:36:29 2016 +0200 zebra: atomic FIB updates This commit updates the kernel API so that route changes are atomically updated using change/replaces messages instead of first sending a withdraw followed with update. Same for zclient updates, changes are sent as single ADD instead of DELETE + ADD. Signed-off-by: Timo Teräs --- zebra/zebra_rib.c | 105 ++++++++++++++++++++++------------------------ 1 file changed, 49 insertions(+), 56 deletions(-) diff --git a/zebra/zebra_rib.c b/zebra/zebra_rib.c index 23ec8dab9a..3812101431 100644 --- a/zebra/zebra_rib.c +++ b/zebra/zebra_rib.c @@ -1574,6 +1574,48 @@ rib_process_update_route (struct zebra_vrf *zvrf, struct route_node *rn, UNSET_FLAG(select->status, RIB_ENTRY_CHANGED); } +/* Check if 'alternate' RIB entry is better than 'current'. */ +static struct rib * +rib_choose_best (struct rib *current, struct rib *alternate) +{ + if (current == NULL) + return alternate; + + /* filter route selection in following order: + * - connected beats other types + * - lower distance beats higher + * - lower metric beats higher for equal distance + * - last, hence oldest, route wins tie break. + */ + + /* Connected routes. 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) + return alternate; + + return current; + } + + if (current->type == ZEBRA_ROUTE_CONNECT) + return current; + + /* higher distance loses */ + if (alternate->distance < current->distance) + return alternate; + if (current->distance < alternate->distance) + return current; + + /* metric tie-breaks equal distance */ + if (alternate->metric <= current->metric) + return alternate; + + return current; +} + /* Core function for processing routing information base. */ static void rib_process (struct route_node *rn) @@ -1583,6 +1625,7 @@ rib_process (struct route_node *rn) struct rib *fib = NULL; struct rib *select = NULL; struct rib *del = NULL; + struct rib *best = NULL; char buf[INET6_ADDRSTRLEN]; rib_dest_t *dest; struct zebra_vrf *zvrf = NULL; @@ -1683,62 +1726,12 @@ rib_process (struct route_node *rn) continue; } - /* Newly selected rib, the common case. */ - if (!select) - { - select = rib; - continue; - } - - /* filter route selection in following order: - * - connected beats other types - * - lower distance beats higher - * - lower metric beats higher for equal distance - * - last, hence oldest, route wins tie break. - */ - - /* Connected routes. Pick the last connected - * route of the set of lowest metric connected routes. - */ - if (rib->type == ZEBRA_ROUTE_CONNECT) - { - if (select->type != ZEBRA_ROUTE_CONNECT - || rib->metric <= select->metric) - { - UNSET_FLAG (select->status, RIB_ENTRY_CHANGED); - select = rib; - } - else - UNSET_FLAG (rib->status, RIB_ENTRY_CHANGED); - continue; - } - else if (select->type == ZEBRA_ROUTE_CONNECT) - { - UNSET_FLAG (rib->status, RIB_ENTRY_CHANGED); - continue; - } - - /* higher distance loses */ - if (rib->distance > select->distance) - { - UNSET_FLAG (rib->status, RIB_ENTRY_CHANGED); - continue; - } - - /* lower wins */ - if (rib->distance < select->distance) - { - UNSET_FLAG (select->status, RIB_ENTRY_CHANGED); - select = rib; - continue; - } - - /* metric tie-breaks equal distance */ - if (rib->metric <= select->metric) - { - UNSET_FLAG (select->status, RIB_ENTRY_CHANGED); - select = rib; - } + best = rib_choose_best(select, rib); + if (select && best != select) + UNSET_FLAG (select->status, RIB_ENTRY_CHANGED); + if (best != rib) + UNSET_FLAG (rib->status, RIB_ENTRY_CHANGED); + select = best; } /* RNODE_FOREACH_RIB_SAFE */ /* After the cycle is finished, the following pointers will be set: -- 2.39.5