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.c226
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;
}