diff options
| author | Rafael Zalamena <rzalamena@opensourcerouting.org> | 2019-12-04 15:07:11 -0300 |
|---|---|---|
| committer | Rafael Zalamena <rzalamena@opensourcerouting.org> | 2020-04-14 11:44:39 -0300 |
| commit | 018e77bcb55e299a7da7bf5435c32040ec362e46 (patch) | |
| tree | 4846a18d0df62666bd7824fbf5999b8dfe759bc6 | |
| parent | d35f447d67a59c8916378662a55eb368990d4706 (diff) | |
zebra: data plane FPM RIB walk code
Implement the code that walks the RIB to send routes that are already
inside the RIB.
Signed-off-by: Rafael Zalamena <rzalamena@opensourcerouting.org>
| -rw-r--r-- | zebra/dplane_fpm_nl.c | 113 | ||||
| -rw-r--r-- | zebra/zebra_dplane.c | 6 | ||||
| -rw-r--r-- | zebra/zebra_dplane.h | 3 |
3 files changed, 118 insertions, 4 deletions
diff --git a/zebra/dplane_fpm_nl.c b/zebra/dplane_fpm_nl.c index d859834fc8..2cd2cb58e2 100644 --- a/zebra/dplane_fpm_nl.c +++ b/zebra/dplane_fpm_nl.c @@ -35,6 +35,7 @@ #include "lib/ns.h" #include "lib/frr_pthread.h" #include "zebra/zebra_dplane.h" +#include "zebra/zebra_router.h" #include "zebra/kernel_netlink.h" #include "zebra/rt_netlink.h" #include "zebra/debug.h" @@ -48,6 +49,7 @@ struct fpm_nl_ctx { /* data plane connection. */ int socket; bool connecting; + bool rib_complete; struct sockaddr_storage addr; /* data plane buffers. */ @@ -60,9 +62,20 @@ struct fpm_nl_ctx { struct thread *t_connect; struct thread *t_read; struct thread *t_write; + + /* zebra events. */ + struct thread *t_ribreset; + struct thread *t_ribwalk; }; /* + * Prototypes. + */ +static int fpm_nl_enqueue(struct fpm_nl_ctx *fnc, struct zebra_dplane_ctx *ctx); +static int fpm_rib_send(struct thread *t); +static int fpm_rib_reset(struct thread *t); + +/* * FPM functions. */ static int fpm_connect(struct thread *t); @@ -78,6 +91,12 @@ static void fpm_reconnect(struct fpm_nl_ctx *fnc) stream_reset(fnc->obuf); THREAD_OFF(fnc->t_read); THREAD_OFF(fnc->t_write); + + if (fnc->t_ribreset) + thread_cancel_async(zrouter.master, &fnc->t_ribreset, NULL); + if (fnc->t_ribwalk) + thread_cancel_async(zrouter.master, &fnc->t_ribwalk, NULL); + thread_add_timer(fnc->fthread->master, fpm_connect, fnc, 3, &fnc->t_connect); } @@ -140,6 +159,10 @@ static int fpm_write(struct thread *t) } fnc->connecting = false; + + /* Ask zebra main thread to start walking the RIB table. */ + thread_add_timer(zrouter.master, fpm_rib_send, fnc, 0, + &fnc->t_ribwalk); } frr_mutex_lock_autounlock(&fnc->obuf_mutex); @@ -231,6 +254,10 @@ static int fpm_connect(struct thread *t) thread_add_write(fnc->fthread->master, fpm_write, fnc, sock, &fnc->t_write); + /* Mark all routes as unsent. */ + thread_add_timer(zrouter.master, fpm_rib_reset, fnc, 0, + &fnc->t_ribreset); + return 0; } @@ -353,6 +380,92 @@ static int fpm_nl_enqueue(struct fpm_nl_ctx *fnc, struct zebra_dplane_ctx *ctx) return 0; } +/** + * Send all RIB installed routes to the connected data plane. + */ +static int fpm_rib_send(struct thread *t) +{ + struct fpm_nl_ctx *fnc = THREAD_ARG(t); + rib_dest_t *dest; + struct route_node *rn; + struct route_table *rt; + struct zebra_dplane_ctx *ctx; + rib_tables_iter_t rt_iter; + + /* Allocate temporary context for all transactions. */ + ctx = dplane_ctx_alloc(); + + rt_iter.state = RIB_TABLES_ITER_S_INIT; + while ((rt = rib_tables_iter_next(&rt_iter))) { + for (rn = route_top(rt); rn; rn = srcdest_route_next(rn)) { + dest = rib_dest_from_rnode(rn); + /* Skip bad route entries. */ + if (dest == NULL || dest->selected_fib == NULL) { + continue; + } + + /* Check for already sent routes. */ + if (CHECK_FLAG(dest->flags, RIB_DEST_UPDATE_FPM)) { + continue; + } + + /* Enqueue route install. */ + dplane_ctx_reset(ctx); + dplane_ctx_route_init(ctx, DPLANE_OP_ROUTE_INSTALL, rn, + dest->selected_fib); + if (fpm_nl_enqueue(fnc, ctx) == -1) { + /* Free the temporary allocated context. */ + dplane_ctx_fini(&ctx); + + zlog_debug("%s: buffer full, come back later", + __func__); + thread_add_timer(zrouter.master, fpm_rib_send, + fnc, 1, &fnc->t_ribwalk); + return 0; + } + + /* Mark as sent. */ + SET_FLAG(dest->flags, RIB_DEST_UPDATE_FPM); + } + } + + /* Free the temporary allocated context. */ + dplane_ctx_fini(&ctx); + + /* All RIB routes sent! */ + fnc->rib_complete = true; + + return 0; +} + +/** + * Resets the RIB FPM flags so we send all routes again. + */ +static int fpm_rib_reset(struct thread *t) +{ + struct fpm_nl_ctx *fnc = THREAD_ARG(t); + rib_dest_t *dest; + struct route_node *rn; + struct route_table *rt; + rib_tables_iter_t rt_iter; + + fnc->rib_complete = false; + + rt_iter.state = RIB_TABLES_ITER_S_INIT; + while ((rt = rib_tables_iter_next(&rt_iter))) { + for (rn = route_top(rt); rn; rn = srcdest_route_next(rn)) { + dest = rib_dest_from_rnode(rn); + /* Skip bad route entries. */ + if (dest == NULL) + continue; + + UNSET_FLAG(dest->flags, RIB_DEST_UPDATE_FPM); + } + } + + return 0; +} + /* * Data plane functions. */ diff --git a/zebra/zebra_dplane.c b/zebra/zebra_dplane.c index dde572df93..e3eeecefc4 100644 --- a/zebra/zebra_dplane.c +++ b/zebra/zebra_dplane.c @@ -1525,10 +1525,8 @@ static int dplane_ctx_ns_init(struct zebra_dplane_ctx *ctx, /* * Initialize a context block for a route update from zebra data structs. */ -static int dplane_ctx_route_init(struct zebra_dplane_ctx *ctx, - enum dplane_op_e op, - struct route_node *rn, - struct route_entry *re) +int dplane_ctx_route_init(struct zebra_dplane_ctx *ctx, enum dplane_op_e op, + struct route_node *rn, struct route_entry *re) { int ret = EINVAL; const struct route_table *table = NULL; diff --git a/zebra/zebra_dplane.h b/zebra/zebra_dplane.h index 9fe8b3b513..8302758d3f 100644 --- a/zebra/zebra_dplane.h +++ b/zebra/zebra_dplane.h @@ -489,6 +489,9 @@ enum zebra_dplane_result dplane_vtep_delete(const struct interface *ifp, const struct in_addr *ip, vni_t vni); +/* Encode route information into data plane context. */ +int dplane_ctx_route_init(struct zebra_dplane_ctx *ctx, enum dplane_op_e op, + struct route_node *rn, struct route_entry *re); /* Retrieve the limit on the number of pending, unprocessed updates. */ uint32_t dplane_get_in_queue_limit(void); |
