zebra: Use ROUTE_ENTRY_INSTALLED as decision for route is installed

zebra is using NEXTHOP_FLAG_FIB as the basis of whether or not
a route_entry is installed.  This is problematic in that we plan
to separate out nexthop handling from route installation.  So modify
the code to keep track of whether or not a route_entry is installed/failed.

This basically means that every place we set/unset NEXTHOP_FLAG_FIB, we
actually also set/unset ROUTE_ENTRY_INSTALLED on the route_entry.
Additionally where we check for route installed via NEXTHOP_FLAG_FIB
switch over to checking if the route think's it is installed.

Signed-off-by: Donald Sharp <sharpd@cumulusnetworks.com>
This commit is contained in:
Donald Sharp 2019-01-14 16:37:53 -05:00
parent 4a2f796f2e
commit 677c1dd5cb
4 changed files with 110 additions and 61 deletions

View File

@ -276,7 +276,7 @@ static int netlink_route_info_fill(netlink_route_info_t *ri, int cmd,
if ((cmd == RTM_NEWROUTE if ((cmd == RTM_NEWROUTE
&& CHECK_FLAG(nexthop->flags, NEXTHOP_FLAG_ACTIVE)) && CHECK_FLAG(nexthop->flags, NEXTHOP_FLAG_ACTIVE))
|| (cmd == RTM_DELROUTE || (cmd == RTM_DELROUTE
&& CHECK_FLAG(nexthop->flags, NEXTHOP_FLAG_FIB))) { && CHECK_FLAG(re->status, ROUTE_ENTRY_INSTALLED))) {
netlink_route_info_add_nh(ri, nexthop); netlink_route_info_add_nh(ri, nexthop);
} }
} }

View File

@ -566,8 +566,8 @@ static int nexthop_active(afi_t afi, struct route_entry *re,
} else if (CHECK_FLAG(re->flags, ZEBRA_FLAG_ALLOW_RECURSION)) { } else if (CHECK_FLAG(re->flags, ZEBRA_FLAG_ALLOW_RECURSION)) {
resolved = 0; resolved = 0;
for (ALL_NEXTHOPS(match->ng, newhop)) { for (ALL_NEXTHOPS(match->ng, newhop)) {
if (!CHECK_FLAG(newhop->flags, if (!CHECK_FLAG(match->status,
NEXTHOP_FLAG_FIB)) ROUTE_ENTRY_INSTALLED))
continue; continue;
if (CHECK_FLAG(newhop->flags, if (CHECK_FLAG(newhop->flags,
NEXTHOP_FLAG_RECURSIVE)) NEXTHOP_FLAG_RECURSIVE))
@ -592,8 +592,8 @@ static int nexthop_active(afi_t afi, struct route_entry *re,
} else if (re->type == ZEBRA_ROUTE_STATIC) { } else if (re->type == ZEBRA_ROUTE_STATIC) {
resolved = 0; resolved = 0;
for (ALL_NEXTHOPS(match->ng, newhop)) { for (ALL_NEXTHOPS(match->ng, newhop)) {
if (!CHECK_FLAG(newhop->flags, if (!CHECK_FLAG(match->status,
NEXTHOP_FLAG_FIB)) ROUTE_ENTRY_INSTALLED))
continue; continue;
if (set) { if (set) {
@ -637,7 +637,6 @@ struct route_entry *rib_match(afi_t afi, safi_t safi, vrf_id_t vrf_id,
struct route_table *table; struct route_table *table;
struct route_node *rn; struct route_node *rn;
struct route_entry *match = NULL; struct route_entry *match = NULL;
struct nexthop *newhop;
/* Lookup table. */ /* Lookup table. */
table = zebra_vrf_table(afi, safi, vrf_id); table = zebra_vrf_table(afi, safi, vrf_id);
@ -677,14 +676,8 @@ struct route_entry *rib_match(afi_t afi, safi_t safi, vrf_id_t vrf_id,
route_lock_node(rn); route_lock_node(rn);
} else { } else {
if (match->type != ZEBRA_ROUTE_CONNECT) { if (match->type != ZEBRA_ROUTE_CONNECT) {
int found = 0; if (!CHECK_FLAG(match->status,
for (ALL_NEXTHOPS(match->ng, newhop)) ROUTE_ENTRY_INSTALLED))
if (CHECK_FLAG(newhop->flags,
NEXTHOP_FLAG_FIB)) {
found = 1;
break;
}
if (!found)
return NULL; return NULL;
} }
@ -774,7 +767,6 @@ struct route_entry *rib_lookup_ipv4(struct prefix_ipv4 *p, vrf_id_t vrf_id)
struct route_table *table; struct route_table *table;
struct route_node *rn; struct route_node *rn;
struct route_entry *match = NULL; struct route_entry *match = NULL;
struct nexthop *nexthop;
rib_dest_t *dest; rib_dest_t *dest;
/* Lookup table. */ /* Lookup table. */
@ -802,9 +794,8 @@ struct route_entry *rib_lookup_ipv4(struct prefix_ipv4 *p, vrf_id_t vrf_id)
if (match->type == ZEBRA_ROUTE_CONNECT) if (match->type == ZEBRA_ROUTE_CONNECT)
return match; return match;
for (ALL_NEXTHOPS(match->ng, nexthop)) if (CHECK_FLAG(match->status, ROUTE_ENTRY_INSTALLED))
if (CHECK_FLAG(nexthop->flags, NEXTHOP_FLAG_FIB)) return match;
return match;
return NULL; return NULL;
} }
@ -1119,6 +1110,7 @@ void rib_uninstall_kernel(struct route_node *rn, struct route_entry *re)
struct zebra_vrf *zvrf = vrf_info_lookup(re->vrf_id); struct zebra_vrf *zvrf = vrf_info_lookup(re->vrf_id);
if (info->safi != SAFI_UNICAST) { if (info->safi != SAFI_UNICAST) {
UNSET_FLAG(re->status, ROUTE_ENTRY_INSTALLED);
for (ALL_NEXTHOPS(re->ng, nexthop)) for (ALL_NEXTHOPS(re->ng, nexthop))
UNSET_FLAG(nexthop->flags, NEXTHOP_FLAG_FIB); UNSET_FLAG(nexthop->flags, NEXTHOP_FLAG_FIB);
return; return;
@ -1171,6 +1163,8 @@ static void rib_uninstall(struct route_node *rn, struct route_entry *re)
if (!RIB_SYSTEM_ROUTE(re)) if (!RIB_SYSTEM_ROUTE(re))
rib_uninstall_kernel(rn, re); rib_uninstall_kernel(rn, re);
else
UNSET_FLAG(re->status, ROUTE_ENTRY_INSTALLED);
dest->selected_fib = NULL; dest->selected_fib = NULL;
@ -1301,6 +1295,7 @@ static void rib_process_del_fib(struct zebra_vrf *zvrf, struct route_node *rn,
if (!RIB_SYSTEM_ROUTE(old)) if (!RIB_SYSTEM_ROUTE(old))
rib_uninstall_kernel(rn, old); rib_uninstall_kernel(rn, old);
else { else {
UNSET_FLAG(old->status, ROUTE_ENTRY_INSTALLED);
/* /*
* We are setting this to NULL here * We are setting this to NULL here
* because that is what we traditionally * because that is what we traditionally
@ -1381,6 +1376,7 @@ static void rib_process_update_fib(struct zebra_vrf *zvrf,
rib_install_kernel(rn, new, old); rib_install_kernel(rn, new, old);
} else { } else {
UNSET_FLAG(new->status, ROUTE_ENTRY_INSTALLED);
/* /*
* We do not need to install the * We do not need to install the
* selected route because it * selected route because it
@ -1400,7 +1396,13 @@ static void rib_process_update_fib(struct zebra_vrf *zvrf,
if (RIB_SYSTEM_ROUTE(new)) { if (RIB_SYSTEM_ROUTE(new)) {
if (!RIB_SYSTEM_ROUTE(old)) if (!RIB_SYSTEM_ROUTE(old))
rib_uninstall_kernel(rn, old); rib_uninstall_kernel(rn, old);
else
UNSET_FLAG(
old->status,
ROUTE_ENTRY_INSTALLED);
} else { } else {
UNSET_FLAG(old->status,
ROUTE_ENTRY_INSTALLED);
for (nexthop = old->ng.nexthop; nexthop; for (nexthop = old->ng.nexthop; nexthop;
nexthop = nexthop->next) nexthop = nexthop->next)
UNSET_FLAG(nexthop->flags, UNSET_FLAG(nexthop->flags,
@ -1437,8 +1439,10 @@ static void rib_process_update_fib(struct zebra_vrf *zvrf,
if (!RIB_SYSTEM_ROUTE(old)) if (!RIB_SYSTEM_ROUTE(old))
rib_uninstall_kernel(rn, old); rib_uninstall_kernel(rn, old);
else else {
UNSET_FLAG(old->status, ROUTE_ENTRY_INSTALLED);
dest->selected_fib = NULL; dest->selected_fib = NULL;
}
} }
} else { } else {
/* /*
@ -1450,18 +1454,9 @@ static void rib_process_update_fib(struct zebra_vrf *zvrf,
* is ready * is ready
* to add routes. * to add routes.
*/ */
if (!RIB_SYSTEM_ROUTE(new)) { if (!RIB_SYSTEM_ROUTE(new)
bool in_fib = false; && !CHECK_FLAG(new->status, ROUTE_ENTRY_INSTALLED))
rib_install_kernel(rn, new, NULL);
for (ALL_NEXTHOPS(new->ng, nexthop))
if (CHECK_FLAG(nexthop->flags,
NEXTHOP_FLAG_FIB)) {
in_fib = true;
break;
}
if (!in_fib)
rib_install_kernel(rn, new, NULL);
}
} }
/* Update prior route. */ /* Update prior route. */
@ -1823,6 +1818,8 @@ static void rib_process_result(struct zebra_dplane_ctx *ctx)
enum dplane_op_e op; enum dplane_op_e op;
enum zebra_dplane_result status; enum zebra_dplane_result status;
const struct prefix *dest_pfx, *src_pfx; const struct prefix *dest_pfx, *src_pfx;
bool re_stale = false;
bool old_re_stale = false;
/* Locate rn and re(s) from ctx */ /* Locate rn and re(s) from ctx */
@ -1907,7 +1904,7 @@ static void rib_process_result(struct zebra_dplane_ctx *ctx)
zlog_debug("%u:%s Stale dplane result for re %p", zlog_debug("%u:%s Stale dplane result for re %p",
dplane_ctx_get_vrf(ctx), dest_str, re); dplane_ctx_get_vrf(ctx), dest_str, re);
} }
re = NULL; re_stale = true;
} }
if (old_re && if (old_re &&
@ -1916,7 +1913,7 @@ static void rib_process_result(struct zebra_dplane_ctx *ctx)
zlog_debug("%u:%s Stale dplane result for old_re %p", zlog_debug("%u:%s Stale dplane result for old_re %p",
dplane_ctx_get_vrf(ctx), dest_str, old_re); dplane_ctx_get_vrf(ctx), dest_str, old_re);
} }
old_re = NULL; old_re_stale = true;
} }
/* /*
@ -1934,12 +1931,24 @@ static void rib_process_result(struct zebra_dplane_ctx *ctx)
case DPLANE_OP_ROUTE_INSTALL: case DPLANE_OP_ROUTE_INSTALL:
case DPLANE_OP_ROUTE_UPDATE: case DPLANE_OP_ROUTE_UPDATE:
if (status == ZEBRA_DPLANE_REQUEST_SUCCESS) { if (status == ZEBRA_DPLANE_REQUEST_SUCCESS) {
if (re) {
UNSET_FLAG(re->status, ROUTE_ENTRY_FAILED);
SET_FLAG(re->status, ROUTE_ENTRY_INSTALLED);
}
if (old_re) {
UNSET_FLAG(old_re->status, ROUTE_ENTRY_FAILED);
UNSET_FLAG(old_re->status,
ROUTE_ENTRY_INSTALLED);
}
/* Update zebra nexthop FIB flag for each /* Update zebra nexthop FIB flag for each
* nexthop that was installed. * nexthop that was installed.
*/ */
for (ALL_NEXTHOPS_PTR(dplane_ctx_get_ng(ctx), for (ALL_NEXTHOPS_PTR(dplane_ctx_get_ng(ctx),
ctx_nexthop)) { ctx_nexthop)) {
if (!re)
continue;
for (ALL_NEXTHOPS(re->ng, nexthop)) { for (ALL_NEXTHOPS(re->ng, nexthop)) {
if (nexthop_same(ctx_nexthop, nexthop)) if (nexthop_same(ctx_nexthop, nexthop))
break; break;
@ -1976,15 +1985,21 @@ static void rib_process_result(struct zebra_dplane_ctx *ctx)
* 'old' context info was stale, 'old_re' will be * 'old' context info was stale, 'old_re' will be
* NULL here and that delete will not be sent. * NULL here and that delete will not be sent.
*/ */
redistribute_update(dest_pfx, src_pfx, re, old_re); if (re)
redistribute_update(dest_pfx, src_pfx,
re, old_re);
/* Notify route owner */ /* Notify route owner */
zsend_route_notify_owner(re, dest_pfx, zsend_route_notify_owner_ctx(ctx, ZAPI_ROUTE_INSTALLED);
ZAPI_ROUTE_INSTALLED);
} else { } else {
zsend_route_notify_owner(re, dest_pfx, if (re)
ZAPI_ROUTE_FAIL_INSTALL); SET_FLAG(re->status, ROUTE_ENTRY_FAILED);
if (old_re)
SET_FLAG(old_re->status, ROUTE_ENTRY_FAILED);
if (re)
zsend_route_notify_owner(re, dest_pfx,
ZAPI_ROUTE_FAIL_INSTALL);
zlog_warn("%u:%s: Route install failed", zlog_warn("%u:%s: Route install failed",
dplane_ctx_get_vrf(ctx), dplane_ctx_get_vrf(ctx),
@ -1993,17 +2008,25 @@ static void rib_process_result(struct zebra_dplane_ctx *ctx)
} }
break; break;
case DPLANE_OP_ROUTE_DELETE: case DPLANE_OP_ROUTE_DELETE:
if (re)
SET_FLAG(re->status, ROUTE_ENTRY_FAILED);
/* /*
* In the delete case, the zebra core datastructs were * In the delete case, the zebra core datastructs were
* updated (or removed) at the time the delete was issued, * updated (or removed) at the time the delete was issued,
* so we're just notifying the route owner. * so we're just notifying the route owner.
*/ */
if (status == ZEBRA_DPLANE_REQUEST_SUCCESS) { if (status == ZEBRA_DPLANE_REQUEST_SUCCESS) {
if (re) {
UNSET_FLAG(re->status, ROUTE_ENTRY_INSTALLED);
UNSET_FLAG(re->status, ROUTE_ENTRY_FAILED);
}
zsend_route_notify_owner_ctx(ctx, ZAPI_ROUTE_REMOVED); zsend_route_notify_owner_ctx(ctx, ZAPI_ROUTE_REMOVED);
if (zvrf) if (zvrf)
zvrf->removals++; zvrf->removals++;
} else { } else {
if (re)
SET_FLAG(re->status, ROUTE_ENTRY_FAILED);
zsend_route_notify_owner_ctx(ctx, zsend_route_notify_owner_ctx(ctx,
ZAPI_ROUTE_REMOVE_FAIL); ZAPI_ROUTE_REMOVE_FAIL);
@ -2527,7 +2550,7 @@ void _route_entry_dump(const char *func, union prefixconstptr pp,
(CHECK_FLAG(nexthop->flags, NEXTHOP_FLAG_ACTIVE) (CHECK_FLAG(nexthop->flags, NEXTHOP_FLAG_ACTIVE)
? "ACTIVE " ? "ACTIVE "
: ""), : ""),
(CHECK_FLAG(nexthop->flags, NEXTHOP_FLAG_FIB) (CHECK_FLAG(re->status, ROUTE_ENTRY_INSTALLED)
? "FIB " ? "FIB "
: ""), : ""),
(CHECK_FLAG(nexthop->flags, NEXTHOP_FLAG_RECURSIVE) (CHECK_FLAG(nexthop->flags, NEXTHOP_FLAG_RECURSIVE)
@ -2708,9 +2731,11 @@ int rib_add_multipath(afi_t afi, safi_t safi, struct prefix *p,
} }
/* If this route is kernel route, set FIB flag to the route. */ /* If this route is kernel route, set FIB flag to the route. */
if (RIB_SYSTEM_ROUTE(re)) if (RIB_SYSTEM_ROUTE(re)) {
SET_FLAG(re->status, ROUTE_ENTRY_INSTALLED);
for (nexthop = re->ng.nexthop; nexthop; nexthop = nexthop->next) for (nexthop = re->ng.nexthop; nexthop; nexthop = nexthop->next)
SET_FLAG(nexthop->flags, NEXTHOP_FLAG_FIB); SET_FLAG(nexthop->flags, NEXTHOP_FLAG_FIB);
}
/* Link new re to node.*/ /* Link new re to node.*/
if (IS_ZEBRA_DEBUG_RIB) { if (IS_ZEBRA_DEBUG_RIB) {
@ -2847,6 +2872,7 @@ void rib_delete(afi_t afi, safi_t safi, vrf_id_t vrf_id, int type,
rn, fib, fib->type); rn, fib, fib->type);
} }
if (allow_delete) { if (allow_delete) {
UNSET_FLAG(fib->status, ROUTE_ENTRY_INSTALLED);
/* Unset flags. */ /* Unset flags. */
for (rtnh = fib->ng.nexthop; rtnh; for (rtnh = fib->ng.nexthop; rtnh;
rtnh = rtnh->next) rtnh = rtnh->next)
@ -3093,6 +3119,7 @@ void rib_sweep_table(struct route_table *table)
* to a different spot (ie startup ) * to a different spot (ie startup )
* this decision needs to be revisited * this decision needs to be revisited
*/ */
SET_FLAG(re->status, ROUTE_ENTRY_INSTALLED);
for (ALL_NEXTHOPS(re->ng, nexthop)) for (ALL_NEXTHOPS(re->ng, nexthop))
SET_FLAG(nexthop->flags, NEXTHOP_FLAG_FIB); SET_FLAG(nexthop->flags, NEXTHOP_FLAG_FIB);

View File

@ -370,14 +370,10 @@ static void zebra_rnh_eval_import_check_entry(vrf_id_t vrfid, afi_t afi,
struct zserv *client; struct zserv *client;
char bufn[INET6_ADDRSTRLEN]; char bufn[INET6_ADDRSTRLEN];
struct listnode *node; struct listnode *node;
struct nexthop *nexthop;
if (re && (rnh->state == NULL)) { if (re && (rnh->state == NULL)) {
for (ALL_NEXTHOPS(re->ng, nexthop)) if (CHECK_FLAG(re->status, ROUTE_ENTRY_INSTALLED))
if (CHECK_FLAG(nexthop->flags, NEXTHOP_FLAG_FIB)) { state_changed = 1;
state_changed = 1;
break;
}
} else if (!re && (rnh->state != NULL)) } else if (!re && (rnh->state != NULL))
state_changed = 1; state_changed = 1;
@ -511,9 +507,10 @@ static void zebra_rnh_process_pbr_tables(afi_t afi, struct route_node *nrn,
* check in a couple of places, so this is a single home for the logic we * check in a couple of places, so this is a single home for the logic we
* use. * use.
*/ */
static bool rnh_nexthop_valid(const struct nexthop *nh) static bool rnh_nexthop_valid(const struct route_entry *re,
const struct nexthop *nh)
{ {
return (CHECK_FLAG(nh->flags, NEXTHOP_FLAG_FIB) return (CHECK_FLAG(re->status, ROUTE_ENTRY_INSTALLED)
&& CHECK_FLAG(nh->flags, NEXTHOP_FLAG_ACTIVE)); && CHECK_FLAG(nh->flags, NEXTHOP_FLAG_ACTIVE));
} }
@ -566,7 +563,7 @@ zebra_rnh_resolve_nexthop_entry(struct zebra_vrf *zvrf, afi_t afi,
* have an installed nexthop to be useful. * have an installed nexthop to be useful.
*/ */
for (ALL_NEXTHOPS(re->ng, nexthop)) { for (ALL_NEXTHOPS(re->ng, nexthop)) {
if (rnh_nexthop_valid(nexthop)) if (rnh_nexthop_valid(re, nexthop))
break; break;
} }
@ -820,6 +817,7 @@ static void copy_state(struct rnh *rnh, struct route_entry *re,
state->distance = re->distance; state->distance = re->distance;
state->metric = re->metric; state->metric = re->metric;
state->vrf_id = re->vrf_id; state->vrf_id = re->vrf_id;
state->status = re->status;
route_entry_copy_nexthops(state, re->ng.nexthop); route_entry_copy_nexthops(state, re->ng.nexthop);
rnh->state = state; rnh->state = state;
@ -895,7 +893,7 @@ static int send_client(struct rnh *rnh, struct zserv *client, rnh_type_t type,
nump = stream_get_endp(s); nump = stream_get_endp(s);
stream_putc(s, 0); stream_putc(s, 0);
for (ALL_NEXTHOPS(re->ng, nh)) for (ALL_NEXTHOPS(re->ng, nh))
if (rnh_nexthop_valid(nh)) { if (rnh_nexthop_valid(re, nh)) {
stream_putl(s, nh->vrf_id); stream_putl(s, nh->vrf_id);
stream_putc(s, nh->type); stream_putc(s, nh->type);
switch (nh->type) { switch (nh->type) {

View File

@ -163,13 +163,23 @@ DEFUN (show_ip_rpf_addr,
static char re_status_output_char(struct route_entry *re, struct nexthop *nhop) static char re_status_output_char(struct route_entry *re, struct nexthop *nhop)
{ {
if (CHECK_FLAG(nhop->flags, NEXTHOP_FLAG_FIB)) { if (CHECK_FLAG(re->status, ROUTE_ENTRY_INSTALLED)) {
if (CHECK_FLAG(nhop->flags, NEXTHOP_FLAG_DUPLICATE)) if (!CHECK_FLAG(nhop->flags, NEXTHOP_FLAG_DUPLICATE))
return ' ';
else
return '*'; return '*';
else
return ' ';
} }
if (CHECK_FLAG(re->status, ROUTE_ENTRY_FAILED)) {
if (CHECK_FLAG(re->status, ROUTE_ENTRY_QUEUED))
return 'q';
return 'f';
}
if (CHECK_FLAG(re->status, ROUTE_ENTRY_QUEUED))
return 'q';
return ' '; return ' ';
} }
@ -400,6 +410,21 @@ static void vty_show_ip_route(struct vty *vty, struct route_node *rn,
re->distance); re->distance);
json_object_int_add(json_route, "metric", re->metric); json_object_int_add(json_route, "metric", re->metric);
if (CHECK_FLAG(re->status, ROUTE_ENTRY_INSTALLED))
json_object_boolean_true_add(json_route, "installed");
if (CHECK_FLAG(re->status, ROUTE_ENTRY_FAILED))
json_object_boolean_true_add(json_route, "failed");
if (CHECK_FLAG(re->status, ROUTE_ENTRY_QUEUED))
json_object_boolean_true_add(json_route, "queued");
if (re->type != ZEBRA_ROUTE_CONNECT) {
json_object_int_add(json_route, "distance",
re->distance);
json_object_int_add(json_route, "metric", re->metric);
}
if (re->tag) if (re->tag)
json_object_int_add(json_route, "tag", re->tag); json_object_int_add(json_route, "tag", re->tag);
@ -1409,21 +1434,20 @@ static void vty_show_ip_route_summary_prefix(struct vty *vty,
* In case of ECMP, count only once. * In case of ECMP, count only once.
*/ */
cnt = 0; cnt = 0;
if (CHECK_FLAG(re->status, ROUTE_ENTRY_INSTALLED)) {
fib_cnt[ZEBRA_ROUTE_TOTAL]++;
fib_cnt[re->type]++;
}
for (nexthop = re->ng.nexthop; (!cnt && nexthop); for (nexthop = re->ng.nexthop; (!cnt && nexthop);
nexthop = nexthop->next) { nexthop = nexthop->next) {
cnt++; cnt++;
rib_cnt[ZEBRA_ROUTE_TOTAL]++; rib_cnt[ZEBRA_ROUTE_TOTAL]++;
rib_cnt[re->type]++; rib_cnt[re->type]++;
if (CHECK_FLAG(nexthop->flags,
NEXTHOP_FLAG_FIB)) {
fib_cnt[ZEBRA_ROUTE_TOTAL]++;
fib_cnt[re->type]++;
}
if (re->type == ZEBRA_ROUTE_BGP if (re->type == ZEBRA_ROUTE_BGP
&& CHECK_FLAG(re->flags, ZEBRA_FLAG_IBGP)) { && CHECK_FLAG(re->flags, ZEBRA_FLAG_IBGP)) {
rib_cnt[ZEBRA_ROUTE_IBGP]++; rib_cnt[ZEBRA_ROUTE_IBGP]++;
if (CHECK_FLAG(nexthop->flags, if (CHECK_FLAG(re->status,
NEXTHOP_FLAG_FIB)) ROUTE_ENTRY_INSTALLED))
fib_cnt[ZEBRA_ROUTE_IBGP]++; fib_cnt[ZEBRA_ROUTE_IBGP]++;
} }
} }