zebra: assorted parts of 0abf6796c

Author: Timo Teräs <timo.teras@iki.fi>
    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 <timo.teras@iki.fi>
This commit is contained in:
Christian Franke 2016-08-24 17:09:14 +02:00 committed by Donald Sharp
parent 020a845924
commit bab85d4fcb

View File

@ -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: