diff options
Diffstat (limited to 'zebra/zebra_rib.c')
| -rw-r--r-- | zebra/zebra_rib.c | 146 |
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); |
