diff options
Diffstat (limited to 'zebra/zebra_rib.c')
| -rw-r--r-- | zebra/zebra_rib.c | 226 |
1 files changed, 129 insertions, 97 deletions
diff --git a/zebra/zebra_rib.c b/zebra/zebra_rib.c index fc3f57eeb8..32cfa4d04c 100644 --- a/zebra/zebra_rib.c +++ b/zebra/zebra_rib.c @@ -18,7 +18,7 @@ #include "sockunion.h" #include "srcdest_table.h" #include "table.h" -#include "thread.h" +#include "frrevent.h" #include "vrf.h" #include "workqueue.h" #include "nexthop_group_private.h" @@ -56,7 +56,7 @@ DEFINE_MTYPE_STATIC(ZEBRA, WQ_WRAPPER, "WQ wrapper"); * Event, list, and mutex for delivery of dataplane results */ static pthread_mutex_t dplane_mutex; -static struct thread *t_dplane; +static struct event *t_dplane; static struct dplane_ctx_list_head rib_dplane_q; DEFINE_HOOK(rib_update, (struct route_node * rn, const char *reason), @@ -64,7 +64,12 @@ DEFINE_HOOK(rib_update, (struct route_node * rn, const char *reason), DEFINE_HOOK(rib_shutdown, (struct route_node * rn), (rn)); -/* Meta Q's specific names */ +/* + * Meta Q's specific names + * + * If you add something here ensure that you + * change MQ_SIZE as well over in rib.h + */ enum meta_queue_indexes { META_QUEUE_NHG, META_QUEUE_EVPN, @@ -76,6 +81,7 @@ enum meta_queue_indexes { META_QUEUE_NOTBGP, META_QUEUE_BGP, META_QUEUE_OTHER, + META_QUEUE_GR_RUN, }; /* Each route type's string and default distance value. */ @@ -250,6 +256,8 @@ static const char *subqueue2str(enum meta_queue_indexes index) return "BGP Routes"; case META_QUEUE_OTHER: return "Other Routes"; + case META_QUEUE_GR_RUN: + return "Graceful Restart"; } return "Unknown"; @@ -509,31 +517,28 @@ struct route_entry *rib_match(afi_t afi, safi_t safi, vrf_id_t vrf_id, return NULL; } -struct route_entry *rib_match_ipv4_multicast(vrf_id_t vrf_id, - struct in_addr addr, - struct route_node **rn_out) +struct route_entry *rib_match_multicast(afi_t afi, vrf_id_t vrf_id, + union g_addr *gaddr, + struct route_node **rn_out) { struct route_entry *re = NULL, *mre = NULL, *ure = NULL; struct route_node *m_rn = NULL, *u_rn = NULL; - union g_addr gaddr = {.ipv4 = addr}; switch (zrouter.ipv4_multicast_mode) { case MCAST_MRIB_ONLY: - return rib_match(AFI_IP, SAFI_MULTICAST, vrf_id, &gaddr, - rn_out); + return rib_match(afi, SAFI_MULTICAST, vrf_id, gaddr, rn_out); case MCAST_URIB_ONLY: - return rib_match(AFI_IP, SAFI_UNICAST, vrf_id, &gaddr, rn_out); + return rib_match(afi, SAFI_UNICAST, vrf_id, gaddr, rn_out); case MCAST_NO_CONFIG: case MCAST_MIX_MRIB_FIRST: - re = mre = rib_match(AFI_IP, SAFI_MULTICAST, vrf_id, &gaddr, - &m_rn); + re = mre = rib_match(afi, SAFI_MULTICAST, vrf_id, gaddr, &m_rn); if (!mre) - re = ure = rib_match(AFI_IP, SAFI_UNICAST, vrf_id, - &gaddr, &u_rn); + re = ure = rib_match(afi, SAFI_UNICAST, vrf_id, gaddr, + &u_rn); break; case MCAST_MIX_DISTANCE: - mre = rib_match(AFI_IP, SAFI_MULTICAST, vrf_id, &gaddr, &m_rn); - ure = rib_match(AFI_IP, SAFI_UNICAST, vrf_id, &gaddr, &u_rn); + mre = rib_match(afi, SAFI_MULTICAST, vrf_id, gaddr, &m_rn); + ure = rib_match(afi, SAFI_UNICAST, vrf_id, gaddr, &u_rn); if (mre && ure) re = ure->distance < mre->distance ? ure : mre; else if (mre) @@ -542,8 +547,8 @@ struct route_entry *rib_match_ipv4_multicast(vrf_id_t vrf_id, re = ure; break; case MCAST_MIX_PFXLEN: - mre = rib_match(AFI_IP, SAFI_MULTICAST, vrf_id, &gaddr, &m_rn); - ure = rib_match(AFI_IP, SAFI_UNICAST, vrf_id, &gaddr, &u_rn); + mre = rib_match(afi, SAFI_MULTICAST, vrf_id, gaddr, &m_rn); + ure = rib_match(afi, SAFI_UNICAST, vrf_id, gaddr, &u_rn); if (mre && ure) re = u_rn->p.prefixlen > m_rn->p.prefixlen ? ure : mre; else if (mre) @@ -558,10 +563,12 @@ struct route_entry *rib_match_ipv4_multicast(vrf_id_t vrf_id, if (IS_ZEBRA_DEBUG_RIB) { char buf[BUFSIZ]; - inet_ntop(AF_INET, &addr, buf, BUFSIZ); + inet_ntop(afi == AFI_IP ? AF_INET : AF_INET6, gaddr, buf, + BUFSIZ); - zlog_debug("%s: %s: vrf: %s(%u) found %s, using %s", __func__, - buf, vrf_id_to_name(vrf_id), vrf_id, + zlog_debug("%s: %s: %pRN vrf: %s(%u) found %s, using %s", + __func__, buf, (re == mre) ? m_rn : u_rn, + vrf_id_to_name(vrf_id), vrf_id, mre ? (ure ? "MRIB+URIB" : "MRIB") : ure ? "URIB" : "nothing", re == ure ? "URIB" : re == mre ? "MRIB" : "none"); @@ -569,62 +576,6 @@ struct route_entry *rib_match_ipv4_multicast(vrf_id_t vrf_id, return re; } -struct route_entry *rib_match_ipv6_multicast(vrf_id_t vrf_id, - struct in6_addr addr, - struct route_node **rn_out) -{ - struct route_entry *re = NULL, *mre = NULL, *ure = NULL; - struct route_node *m_rn = NULL, *u_rn = NULL; - union g_addr gaddr = {.ipv6 = addr}; - - switch (zrouter.ipv4_multicast_mode) { - case MCAST_MRIB_ONLY: - return rib_match(AFI_IP6, SAFI_MULTICAST, vrf_id, &gaddr, - rn_out); - case MCAST_URIB_ONLY: - return rib_match(AFI_IP6, SAFI_UNICAST, vrf_id, &gaddr, rn_out); - case MCAST_NO_CONFIG: - case MCAST_MIX_MRIB_FIRST: - re = mre = rib_match(AFI_IP6, SAFI_MULTICAST, vrf_id, &gaddr, - &m_rn); - if (!mre) - re = ure = rib_match(AFI_IP6, SAFI_UNICAST, vrf_id, - &gaddr, &u_rn); - break; - case MCAST_MIX_DISTANCE: - mre = rib_match(AFI_IP6, SAFI_MULTICAST, vrf_id, &gaddr, &m_rn); - ure = rib_match(AFI_IP6, SAFI_UNICAST, vrf_id, &gaddr, &u_rn); - if (mre && ure) - re = ure->distance < mre->distance ? ure : mre; - else if (mre) - re = mre; - else if (ure) - re = ure; - break; - case MCAST_MIX_PFXLEN: - mre = rib_match(AFI_IP6, SAFI_MULTICAST, vrf_id, &gaddr, &m_rn); - ure = rib_match(AFI_IP6, SAFI_UNICAST, vrf_id, &gaddr, &u_rn); - if (mre && ure) - re = u_rn->p.prefixlen > m_rn->p.prefixlen ? ure : mre; - else if (mre) - re = mre; - else if (ure) - re = ure; - break; - } - - if (rn_out) - *rn_out = (re == mre) ? m_rn : u_rn; - - if (IS_ZEBRA_DEBUG_RIB) - zlog_debug("%s: %pI6: vrf: %s(%u) found %s, using %s", __func__, - &addr, vrf_id_to_name(vrf_id), vrf_id, - mre ? (ure ? "MRIB+URIB" : "MRIB") - : ure ? "URIB" : "nothing", - re == ure ? "URIB" : re == mre ? "MRIB" : "none"); - return re; -} - struct route_entry *rib_lookup_ipv4(struct prefix_ipv4 *p, vrf_id_t vrf_id) { struct route_table *table; @@ -689,7 +640,7 @@ void rib_install_kernel(struct route_node *rn, struct route_entry *re, { struct nexthop *nexthop; struct rib_table_info *info = srcdest_rnode_table_info(rn); - struct zebra_vrf *zvrf = vrf_info_lookup(re->vrf_id); + struct zebra_vrf *zvrf = zebra_vrf_lookup_by_id(re->vrf_id); const struct prefix *p, *src_p; enum zebra_dplane_result ret; @@ -772,7 +723,7 @@ void rib_uninstall_kernel(struct route_node *rn, struct route_entry *re) { struct nexthop *nexthop; struct rib_table_info *info = srcdest_rnode_table_info(rn); - struct zebra_vrf *zvrf = vrf_info_lookup(re->vrf_id); + struct zebra_vrf *zvrf = zebra_vrf_lookup_by_id(re->vrf_id); if (info->safi != SAFI_UNICAST) { UNSET_FLAG(re->status, ROUTE_ENTRY_INSTALLED); @@ -1467,7 +1418,7 @@ static void rib_process(struct route_node *rn) static void zebra_rib_evaluate_mpls(struct route_node *rn) { rib_dest_t *dest = rib_dest_from_rnode(rn); - struct zebra_vrf *zvrf = vrf_info_lookup(VRF_DEFAULT); + struct zebra_vrf *zvrf = zebra_vrf_lookup_by_id(VRF_DEFAULT); if (!dest) return; @@ -1955,7 +1906,7 @@ static void rib_process_result(struct zebra_dplane_ctx *ctx) struct rib_table_info *info; bool rt_delete = false; - zvrf = vrf_info_lookup(dplane_ctx_get_vrf(ctx)); + zvrf = zebra_vrf_lookup_by_id(dplane_ctx_get_vrf(ctx)); vrf = vrf_lookup_by_id(dplane_ctx_get_vrf(ctx)); /* Locate rn and re(s) from ctx */ @@ -2623,7 +2574,7 @@ static void process_subq_early_label(struct listnode *lnode) if (!w) return; - zvrf = vrf_info_lookup(w->vrf_id); + zvrf = zebra_vrf_lookup_by_id(w->vrf_id); if (!zvrf) { XFREE(MTYPE_WQ_WRAPPER, w); return; @@ -3146,6 +3097,23 @@ static void process_subq_early_route(struct listnode *lnode) process_subq_early_route_add(ere); } +struct meta_q_gr_run { + afi_t afi; + vrf_id_t vrf_id; + uint8_t proto; + uint8_t instance; +}; + +static void process_subq_gr_run(struct listnode *lnode) +{ + struct meta_q_gr_run *gr_run = listgetdata(lnode); + + zebra_gr_process_client(gr_run->afi, gr_run->vrf_id, gr_run->proto, + gr_run->instance); + + XFREE(MTYPE_WQ_WRAPPER, gr_run); +} + /* * Examine the specified subqueue; process one entry and return 1 if * there is a node, return 0 otherwise. @@ -3179,6 +3147,9 @@ static unsigned int process_subq(struct list *subq, case META_QUEUE_OTHER: process_subq_route(lnode, qindex); break; + case META_QUEUE_GR_RUN: + process_subq_gr_run(lnode); + break; } list_delete_node(subq, lnode); @@ -3784,6 +3755,20 @@ static void early_route_meta_queue_free(struct meta_queue *mq, struct list *l, } } +static void rib_meta_queue_gr_run_free(struct meta_queue *mq, struct list *l, + struct zebra_vrf *zvrf) +{ + struct meta_q_gr_run *gr_run; + struct listnode *node, *nnode; + + for (ALL_LIST_ELEMENTS(l, node, nnode, gr_run)) { + if (zvrf && zvrf->vrf->vrf_id != gr_run->vrf_id) + continue; + + XFREE(MTYPE_WQ_WRAPPER, gr_run); + } +} + void meta_queue_free(struct meta_queue *mq, struct zebra_vrf *zvrf) { enum meta_queue_indexes i; @@ -3811,6 +3796,9 @@ void meta_queue_free(struct meta_queue *mq, struct zebra_vrf *zvrf) case META_QUEUE_OTHER: rib_meta_queue_free(mq, mq->subq[i], zvrf); break; + case META_QUEUE_GR_RUN: + rib_meta_queue_gr_run_free(mq, mq->subq[i], zvrf); + break; } if (!zvrf) list_delete(&mq->subq[i]); @@ -3924,7 +3912,9 @@ static void rib_link(struct route_node *rn, struct route_entry *re, int process) rmap_name = zebra_get_import_table_route_map(afi, re->table); zebra_add_import_table_entry(zvrf, rn, re, rmap_name); - } else if (process) + } + + if (process) rib_queue_add(rn); } @@ -3999,11 +3989,9 @@ void rib_delnode(struct route_node *rn, struct route_entry *re) zlog_debug("%s(%u):%pRN: Freeing route rn %p, re %p (%s)", vrf_id_to_name(re->vrf_id), re->vrf_id, rn, rn, re, zebra_route_string(re->type)); - - rib_unlink(rn, re); - } else { - rib_queue_add(rn); } + + rib_queue_add(rn); } /* @@ -4151,6 +4139,17 @@ void _route_entry_dump(const char *func, union prefixconstptr pp, zlog_debug("%s: dump complete", straddr); } +static int rib_meta_queue_gr_run_add(struct meta_queue *mq, void *data) +{ + listnode_add(mq->subq[META_QUEUE_GR_RUN], data); + mq->size++; + + if (IS_ZEBRA_DEBUG_RIB_DETAILED) + zlog_debug("Graceful Run adding"); + + return 0; +} + static int rib_meta_queue_early_route_add(struct meta_queue *mq, void *data) { struct zebra_early_route *ere = data; @@ -4167,6 +4166,20 @@ static int rib_meta_queue_early_route_add(struct meta_queue *mq, void *data) return 0; } +int rib_add_gr_run(afi_t afi, vrf_id_t vrf_id, uint8_t proto, uint8_t instance) +{ + struct meta_q_gr_run *gr_run; + + gr_run = XCALLOC(MTYPE_WQ_WRAPPER, sizeof(*gr_run)); + + gr_run->afi = afi; + gr_run->proto = proto; + gr_run->vrf_id = vrf_id; + gr_run->instance = instance; + + return mq_add_handler(gr_run, rib_meta_queue_gr_run_add); +} + struct route_entry *zebra_rib_route_entry_new(vrf_id_t vrf_id, int type, uint8_t instance, uint32_t flags, uint32_t nhe_id, @@ -4450,11 +4463,11 @@ static void rib_update_ctx_fini(struct rib_update_ctx **ctx) XFREE(MTYPE_RIB_UPDATE_CTX, *ctx); } -static void rib_update_handler(struct thread *thread) +static void rib_update_handler(struct event *thread) { struct rib_update_ctx *ctx; - ctx = THREAD_ARG(thread); + ctx = EVENT_ARG(thread); rib_update_handle_vrf_all(ctx->event, ZEBRA_ROUTE_ALL); @@ -4465,20 +4478,39 @@ static void rib_update_handler(struct thread *thread) * Thread list to ensure we don't schedule a ton of events * if interfaces are flapping for instance. */ -static struct thread *t_rib_update_threads[RIB_UPDATE_MAX]; +static struct event *t_rib_update_threads[RIB_UPDATE_MAX]; + +void rib_update_finish(void) +{ + int i; + + for (i = RIB_UPDATE_KERNEL; i < RIB_UPDATE_MAX; i++) { + if (event_is_scheduled(t_rib_update_threads[i])) { + struct rib_update_ctx *ctx; + + ctx = EVENT_ARG(t_rib_update_threads[i]); + + rib_update_ctx_fini(&ctx); + EVENT_OFF(t_rib_update_threads[i]); + } + } +} /* Schedule a RIB update event for all vrfs */ void rib_update(enum rib_update_event event) { struct rib_update_ctx *ctx; - if (thread_is_scheduled(t_rib_update_threads[event])) + if (event_is_scheduled(t_rib_update_threads[event])) + return; + + if (zebra_router_in_shutdown()) return; ctx = rib_update_ctx_init(0, event); - thread_add_event(zrouter.master, rib_update_handler, ctx, 0, - &t_rib_update_threads[event]); + event_add_event(zrouter.master, rib_update_handler, ctx, 0, + &t_rib_update_threads[event]); if (IS_ZEBRA_DEBUG_EVENT) zlog_debug("%s: Scheduled VRF (ALL), event %s", __func__, @@ -4551,7 +4583,7 @@ void rib_sweep_table(struct route_table *table) } /* Sweep all RIB tables. */ -void rib_sweep_route(struct thread *t) +void rib_sweep_route(struct event *t) { struct vrf *vrf; struct zebra_vrf *zvrf; @@ -4663,7 +4695,7 @@ static void handle_pw_result(struct zebra_dplane_ctx *ctx) * Handle results from the dataplane system. Dequeue update context * structs, dispatch to appropriate internal handlers. */ -static void rib_process_dplane_results(struct thread *thread) +static void rib_process_dplane_results(struct event *thread) { struct zebra_dplane_ctx *ctx; struct dplane_ctx_list_head ctxlist; @@ -4850,8 +4882,8 @@ static int rib_dplane_results(struct dplane_ctx_list_head *ctxlist) } /* Ensure event is signalled to zebra main pthread */ - thread_add_event(zrouter.master, rib_process_dplane_results, NULL, 0, - &t_dplane); + event_add_event(zrouter.master, rib_process_dplane_results, NULL, 0, + &t_dplane); return 0; } |
