diff options
Diffstat (limited to 'zebra/zebra_rib.c')
| -rw-r--r-- | zebra/zebra_rib.c | 240 |
1 files changed, 152 insertions, 88 deletions
diff --git a/zebra/zebra_rib.c b/zebra/zebra_rib.c index 1279c7c9a9..e376d4b2af 100644 --- a/zebra/zebra_rib.c +++ b/zebra/zebra_rib.c @@ -116,6 +116,7 @@ static const struct { [ZEBRA_ROUTE_OPENFABRIC] = {ZEBRA_ROUTE_OPENFABRIC, 115, 5}, [ZEBRA_ROUTE_VRRP] = {ZEBRA_ROUTE_VRRP, 255, 7}, [ZEBRA_ROUTE_SRTE] = {ZEBRA_ROUTE_SRTE, 255, 7}, + [ZEBRA_ROUTE_ALL] = {ZEBRA_ROUTE_ALL, 255, 7}, /* Any new route type added to zebra, should be mirrored here */ /* no entry/default: 150 */ @@ -575,7 +576,7 @@ void rib_install_kernel(struct route_node *rn, struct route_entry *re, * know that they've lost */ if (old && (old != re) && (old->type != re->type)) - zsend_route_notify_owner(old, p, ZAPI_ROUTE_BETTER_ADMIN_WON, + zsend_route_notify_owner(rn, old, ZAPI_ROUTE_BETTER_ADMIN_WON, info->afi, info->safi); /* Update fib selection */ @@ -745,9 +746,9 @@ void zebra_rib_evaluate_rn_nexthops(struct route_node *rn, uint32_t seq, if (IS_ZEBRA_DEBUG_NHT_DETAILED) zlog_debug( - "%s(%u):%pRN has Nexthop(%pFX) depending on it, evaluating %u:%u", - zvrf_name(zvrf), zvrf_id(zvrf), rn, p, - seq, rnh->seqno); + "%s(%u):%pRN has Nexthop(%pRN) depending on it, evaluating %u:%u", + zvrf_name(zvrf), zvrf_id(zvrf), rn, + rnh->node, seq, rnh->seqno); /* * If we have evaluated this node on this pass @@ -1088,9 +1089,7 @@ static void rib_process(struct route_node *rn) rib_dest_t *dest; struct zebra_vrf *zvrf = NULL; struct vrf *vrf; - const struct prefix *p, *src_p; - srcdest_rnode_prefixes(rn, &p, &src_p); vrf_id_t vrf_id = VRF_UNKNOWN; assert(rn); @@ -1194,9 +1193,9 @@ static void rib_process(struct route_node *rn) info = srcdest_rnode_table_info(rn); srcdest_rnode_prefixes(rn, &p, NULL); - zsend_route_notify_owner(re, p, - ZAPI_ROUTE_FAIL_INSTALL, - info->afi, info->safi); + zsend_route_notify_owner( + rn, re, ZAPI_ROUTE_FAIL_INSTALL, + info->afi, info->safi); continue; } } else { @@ -1288,8 +1287,7 @@ static void rib_process(struct route_node *rn) */ if (!new_selected || CHECK_FLAG(old_selected->status, ROUTE_ENTRY_REMOVED)) - redistribute_delete(p, src_p, - old_selected, + redistribute_delete(rn, old_selected, new_selected); if (old_selected != new_selected) @@ -1758,8 +1756,7 @@ done: * when processing dplane results, e.g. Note well: the route-node is returned * with a ref held - route_unlock_node() must be called eventually. */ -static struct route_node * -rib_find_rn_from_ctx(const struct zebra_dplane_ctx *ctx) +struct route_node *rib_find_rn_from_ctx(const struct zebra_dplane_ctx *ctx) { struct route_table *table = NULL; struct route_node *rn = NULL; @@ -1806,7 +1803,6 @@ static void rib_process_result(struct zebra_dplane_ctx *ctx) bool is_update = false; enum dplane_op_e op; enum zebra_dplane_result status; - const struct prefix *dest_pfx, *src_pfx; uint32_t seq; rib_dest_t *dest; bool fib_changed = false; @@ -1815,22 +1811,19 @@ static void rib_process_result(struct zebra_dplane_ctx *ctx) zvrf = vrf_info_lookup(dplane_ctx_get_vrf(ctx)); vrf = vrf_lookup_by_id(dplane_ctx_get_vrf(ctx)); - dest_pfx = dplane_ctx_get_dest(ctx); /* Locate rn and re(s) from ctx */ rn = rib_find_rn_from_ctx(ctx); if (rn == NULL) { if (IS_ZEBRA_DEBUG_DPLANE) { zlog_debug( - "Failed to process dplane results: no route for %s(%u):%pFX", - VRF_LOGNAME(vrf), dplane_ctx_get_vrf(ctx), - dest_pfx); + "Failed to process dplane results: no route for %s(%u):%pRN", + VRF_LOGNAME(vrf), dplane_ctx_get_vrf(ctx), rn); } goto done; } dest = rib_dest_from_rnode(rn); - srcdest_rnode_prefixes(rn, &dest_pfx, &src_pfx); info = srcdest_rnode_table_info(rn); op = dplane_ctx_get_op(ctx); @@ -1838,10 +1831,10 @@ static void rib_process_result(struct zebra_dplane_ctx *ctx) if (IS_ZEBRA_DEBUG_DPLANE_DETAIL) zlog_debug( - "%s(%u:%u):%pFX Processing dplane result ctx %p, op %s result %s", + "%s(%u:%u):%pRN Processing dplane result ctx %p, op %s result %s", VRF_LOGNAME(vrf), dplane_ctx_get_vrf(ctx), - dplane_ctx_get_table(ctx), dest_pfx, ctx, - dplane_op2str(op), dplane_res2str(status)); + dplane_ctx_get_table(ctx), rn, ctx, dplane_op2str(op), + dplane_res2str(status)); /* * Update is a bit of a special case, where we may have both old and new @@ -1880,9 +1873,9 @@ static void rib_process_result(struct zebra_dplane_ctx *ctx) if (re->dplane_sequence != seq) { if (IS_ZEBRA_DEBUG_DPLANE_DETAIL) zlog_debug( - "%s(%u):%pFX Stale dplane result for re %p", + "%s(%u):%pRN Stale dplane result for re %p", VRF_LOGNAME(vrf), - dplane_ctx_get_vrf(ctx), dest_pfx, re); + dplane_ctx_get_vrf(ctx), rn, re); } else { if (!zrouter.asic_offloaded || (CHECK_FLAG(re->flags, ZEBRA_FLAG_OFFLOADED) || @@ -1895,10 +1888,10 @@ static void rib_process_result(struct zebra_dplane_ctx *ctx) if (old_re->dplane_sequence != dplane_ctx_get_old_seq(ctx)) { if (IS_ZEBRA_DEBUG_DPLANE_DETAIL) zlog_debug( - "%s(%u:%u):%pFX Stale dplane result for old_re %p", + "%s(%u:%u):%pRN Stale dplane result for old_re %p", VRF_LOGNAME(vrf), dplane_ctx_get_vrf(ctx), old_re->table, - dest_pfx, old_re); + rn, old_re); } else UNSET_FLAG(old_re->status, ROUTE_ENTRY_QUEUED); } @@ -1936,18 +1929,17 @@ static void rib_process_result(struct zebra_dplane_ctx *ctx) if (!fib_changed) { if (IS_ZEBRA_DEBUG_DPLANE_DETAIL) zlog_debug( - "%s(%u:%u):%pFX no fib change for re", + "%s(%u:%u):%pRN no fib change for re", VRF_LOGNAME(vrf), dplane_ctx_get_vrf(ctx), dplane_ctx_get_table( ctx), - dest_pfx); + rn); } /* Redistribute if this is the selected re */ if (dest && re == dest->selected_fib) - redistribute_update(dest_pfx, src_pfx, - re, old_re); + redistribute_update(rn, re, old_re); } /* @@ -1989,13 +1981,13 @@ static void rib_process_result(struct zebra_dplane_ctx *ctx) } if (old_re) SET_FLAG(old_re->status, ROUTE_ENTRY_FAILED); if (re) - zsend_route_notify_owner(re, dest_pfx, - ZAPI_ROUTE_FAIL_INSTALL, - info->afi, info->safi); + zsend_route_notify_owner( + rn, re, ZAPI_ROUTE_FAIL_INSTALL, + info->afi, info->safi); - zlog_warn("%s(%u:%u):%pFX: Route install failed", + zlog_warn("%s(%u:%u):%pRN: Route install failed", VRF_LOGNAME(vrf), dplane_ctx_get_vrf(ctx), - dplane_ctx_get_table(ctx), dest_pfx); + dplane_ctx_get_table(ctx), rn); } break; case DPLANE_OP_ROUTE_DELETE: @@ -2022,9 +2014,9 @@ static void rib_process_result(struct zebra_dplane_ctx *ctx) zsend_route_notify_owner_ctx(ctx, ZAPI_ROUTE_REMOVE_FAIL); - zlog_warn("%s(%u:%u):%pFX: Route Deletion failure", + zlog_warn("%s(%u:%u):%pRN: Route Deletion failure", VRF_LOGNAME(vrf), dplane_ctx_get_vrf(ctx), - dplane_ctx_get_table(ctx), dest_pfx); + dplane_ctx_get_table(ctx), rn); } /* @@ -2099,12 +2091,11 @@ static void rib_process_dplane_notify(struct zebra_dplane_ctx *ctx) struct route_entry *re = NULL; struct vrf *vrf; struct nexthop *nexthop; - const struct prefix *dest_pfx, *src_pfx; rib_dest_t *dest; bool fib_changed = false; bool debug_p = IS_ZEBRA_DEBUG_DPLANE | IS_ZEBRA_DEBUG_RIB; int start_count, end_count; - dest_pfx = dplane_ctx_get_dest(ctx); + vrf = vrf_lookup_by_id(dplane_ctx_get_vrf(ctx)); /* Locate rn and re(s) from ctx */ @@ -2112,20 +2103,19 @@ static void rib_process_dplane_notify(struct zebra_dplane_ctx *ctx) if (rn == NULL) { if (debug_p) { zlog_debug( - "Failed to process dplane notification: no routes for %s(%u:%u):%pFX", + "Failed to process dplane notification: no routes for %s(%u:%u):%pRN", VRF_LOGNAME(vrf), dplane_ctx_get_vrf(ctx), - dplane_ctx_get_table(ctx), dest_pfx); + dplane_ctx_get_table(ctx), rn); } goto done; } dest = rib_dest_from_rnode(rn); - srcdest_rnode_prefixes(rn, &dest_pfx, &src_pfx); if (debug_p) - zlog_debug("%s(%u:%u):%pFX Processing dplane notif ctx %p", + zlog_debug("%s(%u:%u):%pRN Processing dplane notif ctx %p", VRF_LOGNAME(vrf), dplane_ctx_get_vrf(ctx), - dplane_ctx_get_table(ctx), dest_pfx, ctx); + dplane_ctx_get_table(ctx), rn, ctx); /* * Take a pass through the routes, look for matches with the context @@ -2140,9 +2130,9 @@ static void rib_process_dplane_notify(struct zebra_dplane_ctx *ctx) if (re == NULL) { if (debug_p) zlog_debug( - "%s(%u:%u):%pFX Unable to process dplane notification: no entry for type %s", + "%s(%u:%u):%pRN Unable to process dplane notification: no entry for type %s", VRF_LOGNAME(vrf), dplane_ctx_get_vrf(ctx), - dplane_ctx_get_table(ctx), dest_pfx, + dplane_ctx_get_table(ctx), rn, zebra_route_string(dplane_ctx_get_type(ctx))); goto done; @@ -2175,20 +2165,20 @@ static void rib_process_dplane_notify(struct zebra_dplane_ctx *ctx) UNSET_FLAG(re->status, ROUTE_ENTRY_INSTALLED); if (debug_p) zlog_debug( - "%s(%u:%u):%pFX dplane notif, uninstalled type %s route", + "%s(%u:%u):%pRN dplane notif, uninstalled type %s route", VRF_LOGNAME(vrf), dplane_ctx_get_vrf(ctx), - dplane_ctx_get_table(ctx), dest_pfx, + dplane_ctx_get_table(ctx), rn, zebra_route_string( dplane_ctx_get_type(ctx))); } else { /* At least report on the event. */ if (debug_p) zlog_debug( - "%s(%u:%u):%pFX dplane notif, but type %s not selected_fib", + "%s(%u:%u):%pRN dplane notif, but type %s not selected_fib", VRF_LOGNAME(vrf), dplane_ctx_get_vrf(ctx), - dplane_ctx_get_table(ctx), dest_pfx, + dplane_ctx_get_table(ctx), rn, zebra_route_string( dplane_ctx_get_type(ctx))); } @@ -2212,9 +2202,9 @@ static void rib_process_dplane_notify(struct zebra_dplane_ctx *ctx) if (!fib_changed) { if (debug_p) zlog_debug( - "%s(%u:%u):%pFX dplane notification: rib_update returns FALSE", + "%s(%u:%u):%pRN dplane notification: rib_update returns FALSE", VRF_LOGNAME(vrf), dplane_ctx_get_vrf(ctx), - dplane_ctx_get_table(ctx), dest_pfx); + dplane_ctx_get_table(ctx), rn); } /* @@ -2229,9 +2219,9 @@ static void rib_process_dplane_notify(struct zebra_dplane_ctx *ctx) if (start_count > 0 && end_count > 0) { if (debug_p) zlog_debug( - "%s(%u:%u):%pFX applied nexthop changes from dplane notification", + "%s(%u:%u):%pRN applied nexthop changes from dplane notification", VRF_LOGNAME(vrf), dplane_ctx_get_vrf(ctx), - dplane_ctx_get_table(ctx), dest_pfx); + dplane_ctx_get_table(ctx), rn); /* Changed nexthops - update kernel/others */ dplane_route_notif_update(rn, re, @@ -2240,9 +2230,9 @@ static void rib_process_dplane_notify(struct zebra_dplane_ctx *ctx) } else if (start_count == 0 && end_count > 0) { if (debug_p) zlog_debug( - "%s(%u:%u):%pFX installed transition from dplane notification", + "%s(%u:%u):%pRN installed transition from dplane notification", VRF_LOGNAME(vrf), dplane_ctx_get_vrf(ctx), - dplane_ctx_get_table(ctx), dest_pfx); + dplane_ctx_get_table(ctx), rn); /* We expect this to be the selected route, so we want * to tell others about this transition. @@ -2253,14 +2243,14 @@ static void rib_process_dplane_notify(struct zebra_dplane_ctx *ctx) dplane_route_notif_update(rn, re, DPLANE_OP_ROUTE_UPDATE, ctx); /* Redistribute, lsp, and nht update */ - redistribute_update(dest_pfx, src_pfx, re, NULL); + redistribute_update(rn, re, NULL); } else if (start_count > 0 && end_count == 0) { if (debug_p) zlog_debug( - "%s(%u:%u):%pFX un-installed transition from dplane notification", + "%s(%u:%u):%pRN un-installed transition from dplane notification", VRF_LOGNAME(vrf), dplane_ctx_get_vrf(ctx), - dplane_ctx_get_table(ctx), dest_pfx); + dplane_ctx_get_table(ctx), rn); /* Transition from _something_ installed to _nothing_ * installed. @@ -2274,7 +2264,7 @@ static void rib_process_dplane_notify(struct zebra_dplane_ctx *ctx) dplane_route_notif_update(rn, re, DPLANE_OP_ROUTE_DELETE, ctx); /* Redistribute, lsp, and nht update */ - redistribute_delete(dest_pfx, src_pfx, re, NULL); + redistribute_delete(rn, re, NULL); } /* Make any changes visible for lsp and nexthop-tracking processing */ @@ -2955,6 +2945,59 @@ void meta_queue_free(struct meta_queue *mq) XFREE(MTYPE_WORK_QUEUE, mq); } +void rib_meta_queue_free_vrf(struct meta_queue *mq, struct zebra_vrf *zvrf) +{ + vrf_id_t vrf_id = zvrf->vrf->vrf_id; + unsigned int i; + + for (i = 0; i < MQ_SIZE; i++) { + struct listnode *lnode, *nnode; + void *data; + bool del; + + for (ALL_LIST_ELEMENTS(mq->subq[i], lnode, nnode, data)) { + del = false; + + if (i == META_QUEUE_EVPN) { + struct wq_evpn_wrapper *w = data; + + if (w->vrf_id == vrf_id) { + XFREE(MTYPE_WQ_WRAPPER, w); + del = true; + } + } else if (i == + route_info[ZEBRA_ROUTE_NHG].meta_q_map) { + struct wq_nhg_wrapper *w = data; + + if (w->type == WQ_NHG_WRAPPER_TYPE_CTX && + w->u.ctx->vrf_id == vrf_id) { + nhg_ctx_free(&w->u.ctx); + XFREE(MTYPE_WQ_WRAPPER, w); + del = true; + } else if (w->type == WQ_NHG_WRAPPER_TYPE_NHG && + w->u.nhe->vrf_id == vrf_id) { + zebra_nhg_free(w->u.nhe); + XFREE(MTYPE_WQ_WRAPPER, w); + del = true; + } + } else { + struct route_node *rnode = data; + rib_dest_t *dest = rib_dest_from_rnode(rnode); + + if (dest && rib_dest_vrf(dest) == zvrf) { + route_unlock_node(rnode); + del = true; + } + } + + if (del) { + list_delete_node(mq->subq[i], lnode); + mq->size--; + } + } + } +} + /* initialise zebra rib work queue */ static void rib_queue_init(void) { @@ -3081,6 +3124,17 @@ static void rib_addnode(struct route_node *rn, rib_link(rn, re, process); } +static void rib_re_nhg_free(struct route_entry *re) +{ + if (re->nhe && re->nhe_id) { + assert(re->nhe->id == re->nhe_id); + route_entry_update_nhe(re, NULL); + } else if (re->nhe && re->nhe->nhg.nexthop) + nexthops_free(re->nhe->nhg.nexthop); + + nexthops_free(re->fib_ng.nexthop); +} + /* * rib_unlink * @@ -3107,16 +3161,9 @@ void rib_unlink(struct route_node *rn, struct route_entry *re) if (dest->selected_fib == re) dest->selected_fib = NULL; - if (re->nhe && re->nhe_id) { - assert(re->nhe->id == re->nhe_id); + rib_re_nhg_free(re); - route_entry_update_nhe(re, NULL); - } else if (re->nhe && re->nhe->nhg.nexthop) - nexthops_free(re->nhe->nhg.nexthop); - - nexthops_free(re->fib_ng.nexthop); - - zapi_opaque_free(re->opaque); + zapi_re_opaque_free(re->opaque); XFREE(MTYPE_RE, re); } @@ -3304,7 +3351,7 @@ void _route_entry_dump(const char *func, union prefixconstptr pp, */ int rib_add_multipath_nhe(afi_t afi, safi_t safi, struct prefix *p, struct prefix_ipv6 *src_p, struct route_entry *re, - struct nhg_hash_entry *re_nhe) + struct nhg_hash_entry *re_nhe, bool startup) { struct nhg_hash_entry *nhe = NULL; struct route_table *table; @@ -3396,6 +3443,26 @@ int rib_add_multipath_nhe(afi_t afi, safi_t safi, struct prefix *p, same = first_same; + if (!startup && + (re->flags & ZEBRA_FLAG_SELFROUTE) && zrouter.asic_offloaded) { + if (!same) { + if (IS_ZEBRA_DEBUG_RIB) + zlog_debug("prefix: %pRN is a self route where we do not have an entry for it. Dropping this update, it's useless", rn); + /* + * We are not on startup, this is a self route + * and we have asic offload. Which means + * we are getting a callback for a entry + * that was already deleted to the kernel + * but an earlier response was just handed + * back. Drop it on the floor + */ + rib_re_nhg_free(re); + + XFREE(MTYPE_RE, re); + return ret; + } + } + /* If this route is kernel/connected route, notify the dataplane. */ if (RIB_SYSTEM_ROUTE(re)) { /* Notify dataplane */ @@ -3449,7 +3516,7 @@ int rib_add_multipath_nhe(afi_t afi, safi_t safi, struct prefix *p, */ int rib_add_multipath(afi_t afi, safi_t safi, struct prefix *p, struct prefix_ipv6 *src_p, struct route_entry *re, - struct nexthop_group *ng) + struct nexthop_group *ng, bool startup) { int ret; struct nhg_hash_entry nhe; @@ -3470,7 +3537,7 @@ int rib_add_multipath(afi_t afi, safi_t safi, struct prefix *p, else if (re->nhe_id > 0) nhe.id = re->nhe_id; - ret = rib_add_multipath_nhe(afi, safi, p, src_p, re, &nhe); + ret = rib_add_multipath_nhe(afi, safi, p, src_p, re, &nhe, startup); /* In this path, the callers expect memory to be freed. */ nexthop_group_delete(&ng); @@ -3522,8 +3589,8 @@ void rib_delete(afi_t afi, safi_t safi, vrf_id_t vrf_id, int type, else src_buf[0] = '\0'; - zlog_debug("%s[%d]:%pFX%s%s doesn't exist in rib", - vrf->name, table_id, p, + zlog_debug("%s[%d]:%pRN%s%s doesn't exist in rib", + vrf->name, table_id, rn, (src_buf[0] != '\0') ? " from " : "", src_buf); } @@ -3701,7 +3768,7 @@ int rib_add(afi_t afi, safi_t safi, vrf_id_t vrf_id, int type, unsigned short instance, uint32_t flags, struct prefix *p, struct prefix_ipv6 *src_p, const struct nexthop *nh, uint32_t nhe_id, uint32_t table_id, uint32_t metric, uint32_t mtu, - uint8_t distance, route_tag_t tag) + uint8_t distance, route_tag_t tag, bool startup) { struct route_entry *re = NULL; struct nexthop *nexthop = NULL; @@ -3733,7 +3800,7 @@ int rib_add(afi_t afi, safi_t safi, vrf_id_t vrf_id, int type, nexthop_group_add_sorted(ng, nexthop); } - return rib_add_multipath(afi, safi, p, src_p, re, ng); + return rib_add_multipath(afi, safi, p, src_p, re, ng, startup); } static const char *rib_update_event2str(enum rib_update_event event) @@ -3882,7 +3949,7 @@ static void rib_update_ctx_fini(struct rib_update_ctx **ctx) XFREE(MTYPE_RIB_UPDATE_CTX, *ctx); } -static int rib_update_handler(struct thread *thread) +static void rib_update_handler(struct thread *thread) { struct rib_update_ctx *ctx; @@ -3894,8 +3961,6 @@ static int rib_update_handler(struct thread *thread) rib_update_handle_vrf(ctx->vrf_id, ctx->event, ZEBRA_ROUTE_ALL); rib_update_ctx_fini(&ctx); - - return 0; } /* @@ -3989,7 +4054,7 @@ void rib_sweep_table(struct route_table *table) } /* Sweep all RIB tables. */ -int rib_sweep_route(struct thread *t) +void rib_sweep_route(struct thread *t) { struct vrf *vrf; struct zebra_vrf *zvrf; @@ -4004,8 +4069,6 @@ int rib_sweep_route(struct thread *t) zebra_router_sweep_route(); zebra_router_sweep_nhgs(); - - return 0; } /* Remove specific by protocol routes from 'table'. */ @@ -4115,7 +4178,7 @@ done: * Handle results from the dataplane system. Dequeue update context * structs, dispatch to appropriate internal handlers. */ -static int rib_process_dplane_results(struct thread *thread) +static void rib_process_dplane_results(struct thread *thread) { struct zebra_dplane_ctx *ctx; struct dplane_ctx_q ctxlist; @@ -4258,6 +4321,10 @@ static int rib_process_dplane_results(struct thread *thread) zebra_if_addr_update_ctx(ctx); break; + case DPLANE_OP_INTF_NETCONFIG: + zebra_if_netconf_update_ctx(ctx); + break; + /* Some op codes not handled here */ case DPLANE_OP_ADDR_INSTALL: case DPLANE_OP_ADDR_UNINSTALL: @@ -4283,8 +4350,6 @@ static int rib_process_dplane_results(struct thread *thread) } } while (1); - - return 0; } /* @@ -4322,9 +4387,8 @@ static void check_route_info(void) * ZEBRA_ROUTE_ALL is also ignored. */ for (int i = 0; i < len; i++) { - if (i == ZEBRA_ROUTE_SYSTEM || i == ZEBRA_ROUTE_ALL) - continue; - assert(route_info[i].key); + assert(route_info[i].key >= ZEBRA_ROUTE_SYSTEM && + route_info[i].key < ZEBRA_ROUTE_MAX); assert(route_info[i].meta_q_map < MQ_SIZE); } } |
