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.c146
1 files changed, 83 insertions, 63 deletions
diff --git a/zebra/zebra_rib.c b/zebra/zebra_rib.c
index 99ddd438ea..1eda55dca0 100644
--- a/zebra/zebra_rib.c
+++ b/zebra/zebra_rib.c
@@ -571,8 +571,8 @@ static int nexthop_active(afi_t afi, struct route_entry *re,
} else if (CHECK_FLAG(re->flags, ZEBRA_FLAG_ALLOW_RECURSION)) {
resolved = 0;
for (ALL_NEXTHOPS(match->ng, newhop)) {
- if (!CHECK_FLAG(newhop->flags,
- NEXTHOP_FLAG_FIB))
+ if (!CHECK_FLAG(match->status,
+ ROUTE_ENTRY_INSTALLED))
continue;
if (CHECK_FLAG(newhop->flags,
NEXTHOP_FLAG_RECURSIVE))
@@ -597,8 +597,8 @@ static int nexthop_active(afi_t afi, struct route_entry *re,
} else if (re->type == ZEBRA_ROUTE_STATIC) {
resolved = 0;
for (ALL_NEXTHOPS(match->ng, newhop)) {
- if (!CHECK_FLAG(newhop->flags,
- NEXTHOP_FLAG_FIB))
+ if (!CHECK_FLAG(match->status,
+ ROUTE_ENTRY_INSTALLED))
continue;
if (set) {
@@ -642,7 +642,6 @@ struct route_entry *rib_match(afi_t afi, safi_t safi, vrf_id_t vrf_id,
struct route_table *table;
struct route_node *rn;
struct route_entry *match = NULL;
- struct nexthop *newhop;
/* Lookup table. */
table = zebra_vrf_table(afi, safi, vrf_id);
@@ -682,14 +681,8 @@ struct route_entry *rib_match(afi_t afi, safi_t safi, vrf_id_t vrf_id,
route_lock_node(rn);
} else {
if (match->type != ZEBRA_ROUTE_CONNECT) {
- int found = 0;
- for (ALL_NEXTHOPS(match->ng, newhop))
- if (CHECK_FLAG(newhop->flags,
- NEXTHOP_FLAG_FIB)) {
- found = 1;
- break;
- }
- if (!found)
+ if (!CHECK_FLAG(match->status,
+ ROUTE_ENTRY_INSTALLED))
return NULL;
}
@@ -779,7 +772,6 @@ struct route_entry *rib_lookup_ipv4(struct prefix_ipv4 *p, vrf_id_t vrf_id)
struct route_table *table;
struct route_node *rn;
struct route_entry *match = NULL;
- struct nexthop *nexthop;
rib_dest_t *dest;
/* Lookup table. */
@@ -807,9 +799,8 @@ struct route_entry *rib_lookup_ipv4(struct prefix_ipv4 *p, vrf_id_t vrf_id)
if (match->type == ZEBRA_ROUTE_CONNECT)
return match;
- for (ALL_NEXTHOPS(match->ng, nexthop))
- if (CHECK_FLAG(nexthop->flags, NEXTHOP_FLAG_FIB))
- return match;
+ if (CHECK_FLAG(match->status, ROUTE_ENTRY_INSTALLED))
+ return match;
return NULL;
}
@@ -1094,6 +1085,9 @@ void rib_install_kernel(struct route_node *rn, struct route_entry *re,
switch (ret) {
case ZEBRA_DPLANE_REQUEST_QUEUED:
+ SET_FLAG(re->status, ROUTE_ENTRY_QUEUED);
+ if (old)
+ SET_FLAG(old->status, ROUTE_ENTRY_QUEUED);
if (zvrf)
zvrf->installs_queued++;
break;
@@ -1124,6 +1118,7 @@ void rib_uninstall_kernel(struct route_node *rn, struct route_entry *re)
struct zebra_vrf *zvrf = vrf_info_lookup(re->vrf_id);
if (info->safi != SAFI_UNICAST) {
+ UNSET_FLAG(re->status, ROUTE_ENTRY_INSTALLED);
for (ALL_NEXTHOPS(re->ng, nexthop))
UNSET_FLAG(nexthop->flags, NEXTHOP_FLAG_FIB);
return;
@@ -1176,6 +1171,8 @@ static void rib_uninstall(struct route_node *rn, struct route_entry *re)
if (!RIB_SYSTEM_ROUTE(re))
rib_uninstall_kernel(rn, re);
+ else
+ UNSET_FLAG(re->status, ROUTE_ENTRY_INSTALLED);
dest->selected_fib = NULL;
@@ -1306,6 +1303,7 @@ static void rib_process_del_fib(struct zebra_vrf *zvrf, struct route_node *rn,
if (!RIB_SYSTEM_ROUTE(old))
rib_uninstall_kernel(rn, old);
else {
+ UNSET_FLAG(old->status, ROUTE_ENTRY_INSTALLED);
/*
* We are setting this to NULL here
* because that is what we traditionally
@@ -1386,6 +1384,7 @@ static void rib_process_update_fib(struct zebra_vrf *zvrf,
rib_install_kernel(rn, new, old);
} else {
+ UNSET_FLAG(new->status, ROUTE_ENTRY_INSTALLED);
/*
* We do not need to install the
* selected route because it
@@ -1405,7 +1404,13 @@ static void rib_process_update_fib(struct zebra_vrf *zvrf,
if (RIB_SYSTEM_ROUTE(new)) {
if (!RIB_SYSTEM_ROUTE(old))
rib_uninstall_kernel(rn, old);
+ else
+ UNSET_FLAG(
+ old->status,
+ ROUTE_ENTRY_INSTALLED);
} else {
+ UNSET_FLAG(old->status,
+ ROUTE_ENTRY_INSTALLED);
for (nexthop = old->ng.nexthop; nexthop;
nexthop = nexthop->next)
UNSET_FLAG(nexthop->flags,
@@ -1442,8 +1447,10 @@ static void rib_process_update_fib(struct zebra_vrf *zvrf,
if (!RIB_SYSTEM_ROUTE(old))
rib_uninstall_kernel(rn, old);
- else
+ else {
+ UNSET_FLAG(old->status, ROUTE_ENTRY_INSTALLED);
dest->selected_fib = NULL;
+ }
}
} else {
/*
@@ -1455,18 +1462,9 @@ static void rib_process_update_fib(struct zebra_vrf *zvrf,
* is ready
* to add routes.
*/
- if (!RIB_SYSTEM_ROUTE(new)) {
- bool in_fib = false;
-
- 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);
- }
+ if (!RIB_SYSTEM_ROUTE(new)
+ && !CHECK_FLAG(new->status, ROUTE_ENTRY_INSTALLED))
+ rib_install_kernel(rn, new, NULL);
}
/* Update prior route. */
@@ -1907,44 +1905,48 @@ static void rib_process_result(struct zebra_dplane_ctx *ctx)
/*
* Check sequence number(s) to detect stale results before continuing
*/
- if (re && (re->dplane_sequence != dplane_ctx_get_seq(ctx))) {
- if (IS_ZEBRA_DEBUG_DPLANE_DETAIL) {
- zlog_debug("%u:%s Stale dplane result for re %p",
- dplane_ctx_get_vrf(ctx), dest_str, re);
- }
- re = NULL;
- }
-
- if (old_re &&
- (old_re->dplane_sequence != dplane_ctx_get_old_seq(ctx))) {
- if (IS_ZEBRA_DEBUG_DPLANE_DETAIL) {
- zlog_debug("%u:%s Stale dplane result for old_re %p",
- dplane_ctx_get_vrf(ctx), dest_str, old_re);
- }
- old_re = NULL;
- }
-
- /*
- * Here's sort of a tough one: the route update result is stale.
- * Is it better to use the context block info to generate
- * redist and owner notification, or is it better to wait
- * for the up-to-date result to arrive?
- */
- if (re == NULL) {
- /* TODO -- for now, only expose up-to-date results */
- goto done;
+ if (re) {
+ if (re->dplane_sequence != dplane_ctx_get_seq(ctx)) {
+ if (IS_ZEBRA_DEBUG_DPLANE_DETAIL)
+ zlog_debug("%u:%s Stale dplane result for re %p",
+ dplane_ctx_get_vrf(ctx),
+ dest_str, re);
+ } else
+ UNSET_FLAG(re->status, ROUTE_ENTRY_QUEUED);
+ }
+
+ if (old_re) {
+ if (old_re->dplane_sequence != dplane_ctx_get_old_seq(ctx)) {
+ if (IS_ZEBRA_DEBUG_DPLANE_DETAIL)
+ zlog_debug("%u:%s Stale dplane result for old_re %p",
+ dplane_ctx_get_vrf(ctx),
+ dest_str, old_re);
+ } else
+ UNSET_FLAG(re->status, ROUTE_ENTRY_QUEUED);
}
switch (op) {
case DPLANE_OP_ROUTE_INSTALL:
case DPLANE_OP_ROUTE_UPDATE:
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
* nexthop that was installed.
*/
for (ALL_NEXTHOPS_PTR(dplane_ctx_get_ng(ctx),
ctx_nexthop)) {
+ if (!re)
+ continue;
+
for (ALL_NEXTHOPS(re->ng, nexthop)) {
if (nexthop_same(ctx_nexthop, nexthop))
break;
@@ -1981,15 +1983,21 @@ static void rib_process_result(struct zebra_dplane_ctx *ctx)
* 'old' context info was stale, 'old_re' will be
* 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 */
- zsend_route_notify_owner(re, dest_pfx,
- ZAPI_ROUTE_INSTALLED);
+ zsend_route_notify_owner_ctx(ctx, ZAPI_ROUTE_INSTALLED);
} else {
- zsend_route_notify_owner(re, dest_pfx,
- ZAPI_ROUTE_FAIL_INSTALL);
+ if (re)
+ 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",
dplane_ctx_get_vrf(ctx),
@@ -1998,17 +2006,25 @@ static void rib_process_result(struct zebra_dplane_ctx *ctx)
}
break;
case DPLANE_OP_ROUTE_DELETE:
+ if (re)
+ SET_FLAG(re->status, ROUTE_ENTRY_FAILED);
/*
* In the delete case, the zebra core datastructs were
* updated (or removed) at the time the delete was issued,
* so we're just notifying the route owner.
*/
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);
if (zvrf)
zvrf->removals++;
} else {
+ if (re)
+ SET_FLAG(re->status, ROUTE_ENTRY_FAILED);
zsend_route_notify_owner_ctx(ctx,
ZAPI_ROUTE_REMOVE_FAIL);
@@ -2532,7 +2548,7 @@ void _route_entry_dump(const char *func, union prefixconstptr pp,
(CHECK_FLAG(nexthop->flags, NEXTHOP_FLAG_ACTIVE)
? "ACTIVE "
: ""),
- (CHECK_FLAG(nexthop->flags, NEXTHOP_FLAG_FIB)
+ (CHECK_FLAG(re->status, ROUTE_ENTRY_INSTALLED)
? "FIB "
: ""),
(CHECK_FLAG(nexthop->flags, NEXTHOP_FLAG_RECURSIVE)
@@ -2713,9 +2729,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 (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)
SET_FLAG(nexthop->flags, NEXTHOP_FLAG_FIB);
+ }
/* Link new re to node.*/
if (IS_ZEBRA_DEBUG_RIB) {
@@ -2852,6 +2870,7 @@ void rib_delete(afi_t afi, safi_t safi, vrf_id_t vrf_id, int type,
rn, fib, fib->type);
}
if (allow_delete) {
+ UNSET_FLAG(fib->status, ROUTE_ENTRY_INSTALLED);
/* Unset flags. */
for (rtnh = fib->ng.nexthop; rtnh;
rtnh = rtnh->next)
@@ -3098,6 +3117,7 @@ void rib_sweep_table(struct route_table *table)
* to a different spot (ie startup )
* this decision needs to be revisited
*/
+ SET_FLAG(re->status, ROUTE_ENTRY_INSTALLED);
for (ALL_NEXTHOPS(re->ng, nexthop))
SET_FLAG(nexthop->flags, NEXTHOP_FLAG_FIB);