struct prefix p;
struct route_table *table;
struct route_node *rn;
- struct route_entry *match;
+ struct route_entry *match = NULL;
int resolved;
struct nexthop *newhop;
struct interface *ifp;
+ rib_dest_t *dest;
if ((nexthop->type == NEXTHOP_TYPE_IPV4)
|| nexthop->type == NEXTHOP_TYPE_IPV6)
&& !nh_resolve_via_default(p.family))
return 0;
- RNODE_FOREACH_RE (rn, match) {
- if (CHECK_FLAG(match->status, ROUTE_ENTRY_REMOVED))
- continue;
-
- /* if the next hop is imported from another table, skip
- * it */
- if (match->type == ZEBRA_ROUTE_TABLE)
- continue;
- if (CHECK_FLAG(match->status, ROUTE_ENTRY_SELECTED_FIB))
- break;
- }
+ dest = rib_dest_from_rnode(rn);
+ if (dest && dest->selected_fib &&
+ !CHECK_FLAG(dest->selected_fib->status,
+ ROUTE_ENTRY_REMOVED) &&
+ dest->selected_fib->type != ZEBRA_ROUTE_TABLE)
+ match = dest->selected_fib;
/* If there is no selected route or matched route is EGP, go up
tree. */
struct prefix p;
struct route_table *table;
struct route_node *rn;
- struct route_entry *match;
+ struct route_entry *match = NULL;
struct nexthop *newhop;
/* Lookup table. */
rn = route_node_match(table, (struct prefix *)&p);
while (rn) {
+ rib_dest_t *dest;
+
route_unlock_node(rn);
- /* Pick up selected route. */
- RNODE_FOREACH_RE (rn, match) {
- if (CHECK_FLAG(match->status, ROUTE_ENTRY_REMOVED))
- continue;
- if (CHECK_FLAG(match->status, ROUTE_ENTRY_SELECTED_FIB))
- break;
- }
+ dest = rib_dest_from_rnode(rn);
+ if (dest && dest->selected_fib &&
+ !CHECK_FLAG(dest->selected_fib->status, ROUTE_ENTRY_REMOVED))
+ match = dest->selected_fib;
/* If there is no selected route or matched route is EGP, go up
tree. */
{
struct route_table *table;
struct route_node *rn;
- struct route_entry *match;
+ struct route_entry *match = NULL;
struct nexthop *nexthop;
+ rib_dest_t *dest;
/* Lookup table. */
table = zebra_vrf_table(AFI_IP, SAFI_UNICAST, vrf_id);
/* Unlock node. */
route_unlock_node(rn);
+ dest = rib_dest_from_rnode(rn);
- RNODE_FOREACH_RE (rn, match) {
- if (CHECK_FLAG(match->status, ROUTE_ENTRY_REMOVED))
- continue;
- if (CHECK_FLAG(match->status, ROUTE_ENTRY_SELECTED_FIB))
- break;
- }
+ if (dest && dest->selected_fib &&
+ !CHECK_FLAG(dest->selected_fib->status, ROUTE_ENTRY_REMOVED))
+ match = dest->selected_fib;
if (!match)
return NULL;
{
struct route_table *table;
struct route_node *rn;
- struct route_entry *match;
+ struct route_entry *match = NULL;
struct nexthop *nexthop;
int nexthops_active;
+ rib_dest_t *dest;
/* Lookup table. */
table = zebra_vrf_table(AFI_IP, SAFI_UNICAST, vrf_id);
/* Unlock node. */
route_unlock_node(rn);
+ dest = rib_dest_from_rnode(rn);
/* Find out if a "selected" RR for the discovered RIB entry exists ever.
*/
- RNODE_FOREACH_RE (rn, match) {
- if (CHECK_FLAG(match->status, ROUTE_ENTRY_REMOVED))
- continue;
- if (CHECK_FLAG(match->status, ROUTE_ENTRY_SELECTED_FIB))
- break;
- }
+ if (dest && dest->selected_fib &&
+ !CHECK_FLAG(dest->selected_fib->status, ROUTE_ENTRY_REMOVED))
+ match = dest->selected_fib;
/* None such found :( */
if (!match)
static void rib_uninstall(struct route_node *rn, struct route_entry *re)
{
rib_table_info_t *info = srcdest_rnode_table_info(rn);
+ rib_dest_t *dest = rib_dest_from_rnode(rn);
- if (CHECK_FLAG(re->status, ROUTE_ENTRY_SELECTED_FIB)) {
+ if (dest && dest->selected_fib == re) {
if (info->safi == SAFI_UNICAST)
hook_call(rib_update, rn, "rib_uninstall");
if (zebra_rib_labeled_unicast(re))
zebra_mpls_lsp_uninstall(info->zvrf, rn, re);
- UNSET_FLAG(re->status, ROUTE_ENTRY_SELECTED_FIB);
+ dest->selected_fib = NULL;
}
if (CHECK_FLAG(re->flags, ZEBRA_FLAG_SELECTED)) {
static void rib_process_add_fib(struct zebra_vrf *zvrf, struct route_node *rn,
struct route_entry *new)
{
+ rib_dest_t *dest = rib_dest_from_rnode(rn);
+
hook_call(rib_update, rn, "new route selected");
/* Update real nexthop. This may actually determine if nexthop is active
return;
}
- SET_FLAG(new->status, ROUTE_ENTRY_SELECTED_FIB);
+ dest->selected_fib = new;
if (IS_ZEBRA_DEBUG_RIB) {
char buf[SRCDEST2STR_BUFFER];
srcdest_rnode2str(rn, buf, sizeof(buf));
static void rib_process_del_fib(struct zebra_vrf *zvrf, struct route_node *rn,
struct route_entry *old)
{
+ rib_dest_t *dest = rib_dest_from_rnode(rn);
hook_call(rib_update, rn, "removing existing route");
/* Uninstall from kernel. */
if (!RIB_SYSTEM_ROUTE(old))
rib_uninstall_kernel(rn, old);
- UNSET_FLAG(old->status, ROUTE_ENTRY_SELECTED_FIB);
+ dest->selected_fib = NULL;
/* Update nexthop for route, reset changed flag. */
nexthop_active_update(rn, old, 1);
struct nexthop *nexthop = NULL;
int nh_active = 0;
int installed = 1;
+ rib_dest_t *dest = rib_dest_from_rnode(rn);
/*
* We have to install or update if a new route has been selected or
/* Update for redistribution. */
if (installed)
- SET_FLAG(new->status, ROUTE_ENTRY_SELECTED_FIB);
+ dest->selected_fib = new;
}
/*
if (!RIB_SYSTEM_ROUTE(old))
rib_uninstall_kernel(rn, old);
- UNSET_FLAG(new->status, ROUTE_ENTRY_SELECTED_FIB);
+ dest->selected_fib = NULL;
}
} else {
/*
/* Update prior route. */
if (new != old) {
- UNSET_FLAG(old->status, ROUTE_ENTRY_SELECTED_FIB);
-
/* Set real nexthop. */
nexthop_active_update(rn, old, 1);
UNSET_FLAG(old->status, ROUTE_ENTRY_CHANGED);
if (IS_ZEBRA_DEBUG_RIB_DETAILED)
zlog_debug("%u:%s: Processing rn %p", vrf_id, buf, rn);
+ old_fib = dest->selected_fib;
+
RNODE_FOREACH_RE_SAFE (rn, re, next) {
if (IS_ZEBRA_DEBUG_RIB_DETAILED)
zlog_debug(
assert(old_selected == NULL);
old_selected = re;
}
- /* Currently in fib */
- if (CHECK_FLAG(re->status, ROUTE_ENTRY_SELECTED_FIB)) {
- assert(old_fib == NULL);
- old_fib = re;
- }
/* Skip deleted entries from selection */
if (CHECK_FLAG(re->status, ROUTE_ENTRY_REMOVED))
{
struct route_table *table;
struct route_node *rn;
- struct route_entry *re;
unsigned changed = 0;
+ rib_dest_t *dest;
if (NULL == (table = zebra_vrf_table(AFI_IP, SAFI_UNICAST, vrf_id))) {
zlog_err("%s: zebra_vrf_table() returned NULL", __func__);
/* Unlock node. */
route_unlock_node(rn);
+ dest = rib_dest_from_rnode(rn);
/* Check all RE entries. In case any changes have to be done, requeue
* the RN into RIBQ head. If the routing message about the new connected
* route (generated by the IP address we are going to assign very soon)
* revalidation
* of the rest of the RE.
*/
- RNODE_FOREACH_RE (rn, re) {
- if (CHECK_FLAG(re->status, ROUTE_ENTRY_SELECTED_FIB)
- && !RIB_SYSTEM_ROUTE(re)) {
- changed = 1;
- if (IS_ZEBRA_DEBUG_RIB) {
- char buf[PREFIX_STRLEN];
- zlog_debug(
- "%u:%s: freeing way for connected prefix",
- re->vrf_id,
- prefix2str(&rn->p, buf, sizeof(buf)));
- route_entry_dump(&rn->p, NULL, re);
- }
- rib_uninstall(rn, re);
+ if (dest->selected_fib && !RIB_SYSTEM_ROUTE(dest->selected_fib)) {
+ changed = 1;
+ if (IS_ZEBRA_DEBUG_RIB) {
+ char buf[PREFIX_STRLEN];
+
+ zlog_debug("%u:%s: freeing way for connected prefix",
+ dest->selected_fib->vrf_id,
+ prefix2str(&rn->p, buf, sizeof(buf)));
+ route_entry_dump(&rn->p, NULL, dest->selected_fib);
}
+ rib_uninstall(rn, dest->selected_fib);
}
if (changed)
rib_queue_add(rn);
struct route_entry *same = NULL;
struct nexthop *rtnh;
char buf2[INET6_ADDRSTRLEN];
+ rib_dest_t *dest;
assert(!src_p || afi == AFI_IP6);
return;
}
+ dest = rib_dest_from_rnode(rn);
+ fib = dest->selected_fib;
+
/* Lookup same type route. */
RNODE_FOREACH_RE (rn, re) {
if (CHECK_FLAG(re->status, ROUTE_ENTRY_REMOVED))
continue;
- if (CHECK_FLAG(re->status, ROUTE_ENTRY_SELECTED_FIB))
- fib = re;
-
if (re->type != type)
continue;
if (re->instance != instance)
UNSET_FLAG(rtnh->flags,
NEXTHOP_FLAG_FIB);
- UNSET_FLAG(fib->status,
- ROUTE_ENTRY_SELECTED_FIB);
+ dest->selected_fib = NULL;
} else {
/* This means someone else, other than Zebra,
* has deleted
{
struct route_node *rn;
rib_table_info_t *info;
- struct route_entry *re;
+ rib_dest_t *dest;
if (!table)
return;
info = table->info;
- for (rn = route_top(table); rn; rn = srcdest_route_next(rn))
- RNODE_FOREACH_RE (rn, re) {
- if (!CHECK_FLAG(re->status, ROUTE_ENTRY_SELECTED_FIB))
- continue;
+ for (rn = route_top(table); rn; rn = srcdest_route_next(rn)) {
+ dest = rib_dest_from_rnode(rn);
+ if (dest && dest->selected_fib) {
if (info->safi == SAFI_UNICAST)
hook_call(rib_update, rn, NULL);
- if (!RIB_SYSTEM_ROUTE(re))
- rib_uninstall_kernel(rn, re);
+ if (!RIB_SYSTEM_ROUTE(dest->selected_fib))
+ rib_uninstall_kernel(rn, dest->selected_fib);
}
+ }
}
/* Routing information base initialize. */