+// SPDX-License-Identifier: GPL-2.0-or-later
/*
* Zebra dataplane plugin for Forwarding Plane Manager (FPM) using netlink.
*
* Copyright (C) 2019 Network Device Education Foundation, Inc. ("NetDEF")
* Rafael Zalamena
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful, but
- * WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License along
- * with this program; see the file COPYING; if not, write to the Free Software
- * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
*/
#ifdef HAVE_CONFIG_H
/* data plane events. */
struct zebra_dplane_provider *prov;
struct frr_pthread *fthread;
- struct thread *t_connect;
- struct thread *t_read;
- struct thread *t_write;
- struct thread *t_event;
- struct thread *t_nhg;
- struct thread *t_dequeue;
+ struct event *t_connect;
+ struct event *t_read;
+ struct event *t_write;
+ struct event *t_event;
+ struct event *t_nhg;
+ struct event *t_dequeue;
/* zebra events. */
- struct thread *t_lspreset;
- struct thread *t_lspwalk;
- struct thread *t_nhgreset;
- struct thread *t_nhgwalk;
- struct thread *t_ribreset;
- struct thread *t_ribwalk;
- struct thread *t_rmacreset;
- struct thread *t_rmacwalk;
+ struct event *t_lspreset;
+ struct event *t_lspwalk;
+ struct event *t_nhgreset;
+ struct event *t_nhgwalk;
+ struct event *t_ribreset;
+ struct event *t_ribwalk;
+ struct event *t_rmacreset;
+ struct event *t_rmacwalk;
/* Statistic counters. */
struct {
};
#define FPM_RECONNECT(fnc) \
- thread_add_event((fnc)->fthread->master, fpm_process_event, (fnc), \
- FNE_INTERNAL_RECONNECT, &(fnc)->t_event)
+ event_add_event((fnc)->fthread->master, fpm_process_event, (fnc), \
+ FNE_INTERNAL_RECONNECT, &(fnc)->t_event)
#define WALK_FINISH(fnc, ev) \
- thread_add_event((fnc)->fthread->master, fpm_process_event, (fnc), \
- (ev), NULL)
+ event_add_event((fnc)->fthread->master, fpm_process_event, (fnc), \
+ (ev), NULL)
/*
* Prototypes.
*/
-static void fpm_process_event(struct thread *t);
+static void fpm_process_event(struct event *t);
static int fpm_nl_enqueue(struct fpm_nl_ctx *fnc, struct zebra_dplane_ctx *ctx);
-static void fpm_lsp_send(struct thread *t);
-static void fpm_lsp_reset(struct thread *t);
-static void fpm_nhg_send(struct thread *t);
-static void fpm_nhg_reset(struct thread *t);
-static void fpm_rib_send(struct thread *t);
-static void fpm_rib_reset(struct thread *t);
-static void fpm_rmac_send(struct thread *t);
-static void fpm_rmac_reset(struct thread *t);
+static void fpm_lsp_send(struct event *t);
+static void fpm_lsp_reset(struct event *t);
+static void fpm_nhg_send(struct event *t);
+static void fpm_nhg_reset(struct event *t);
+static void fpm_rib_send(struct event *t);
+static void fpm_rib_reset(struct event *t);
+static void fpm_rmac_send(struct event *t);
+static void fpm_rmac_reset(struct event *t);
/*
* CLI.
memcpy(&sin6->sin6_addr, naddr, sizeof(sin6->sin6_addr));
ask_reconnect:
- thread_add_event(gfnc->fthread->master, fpm_process_event, gfnc,
- FNE_RECONNECT, &gfnc->t_event);
+ event_add_event(gfnc->fthread->master, fpm_process_event, gfnc,
+ FNE_RECONNECT, &gfnc->t_event);
return CMD_SUCCESS;
}
"FPM remote listening server port\n"
"Remote FPM server port\n")
{
- thread_add_event(gfnc->fthread->master, fpm_process_event, gfnc,
- FNE_DISABLE, &gfnc->t_event);
+ event_add_event(gfnc->fthread->master, fpm_process_event, gfnc,
+ FNE_DISABLE, &gfnc->t_event);
return CMD_SUCCESS;
}
if (gfnc->use_nhg)
return CMD_SUCCESS;
- thread_add_event(gfnc->fthread->master, fpm_process_event, gfnc,
- FNE_TOGGLE_NHG, &gfnc->t_nhg);
+ event_add_event(gfnc->fthread->master, fpm_process_event, gfnc,
+ FNE_TOGGLE_NHG, &gfnc->t_nhg);
return CMD_SUCCESS;
}
if (!gfnc->use_nhg)
return CMD_SUCCESS;
- thread_add_event(gfnc->fthread->master, fpm_process_event, gfnc,
- FNE_TOGGLE_NHG, &gfnc->t_nhg);
+ event_add_event(gfnc->fthread->master, fpm_process_event, gfnc,
+ FNE_TOGGLE_NHG, &gfnc->t_nhg);
return CMD_SUCCESS;
}
FPM_STR
"FPM statistic counters\n")
{
- thread_add_event(gfnc->fthread->master, fpm_process_event, gfnc,
- FNE_RESET_COUNTERS, &gfnc->t_event);
+ event_add_event(gfnc->fthread->master, fpm_process_event, gfnc,
+ FNE_RESET_COUNTERS, &gfnc->t_event);
return CMD_SUCCESS;
}
/*
* FPM functions.
*/
-static void fpm_connect(struct thread *t);
+static void fpm_connect(struct event *t);
static void fpm_reconnect(struct fpm_nl_ctx *fnc)
{
/* Cancel all zebra threads first. */
- thread_cancel_async(zrouter.master, &fnc->t_lspreset, NULL);
- thread_cancel_async(zrouter.master, &fnc->t_lspwalk, NULL);
- thread_cancel_async(zrouter.master, &fnc->t_nhgreset, NULL);
- thread_cancel_async(zrouter.master, &fnc->t_nhgwalk, NULL);
- thread_cancel_async(zrouter.master, &fnc->t_ribreset, NULL);
- thread_cancel_async(zrouter.master, &fnc->t_ribwalk, NULL);
- thread_cancel_async(zrouter.master, &fnc->t_rmacreset, NULL);
- thread_cancel_async(zrouter.master, &fnc->t_rmacwalk, NULL);
+ event_cancel_async(zrouter.master, &fnc->t_lspreset, NULL);
+ event_cancel_async(zrouter.master, &fnc->t_lspwalk, NULL);
+ event_cancel_async(zrouter.master, &fnc->t_nhgreset, NULL);
+ event_cancel_async(zrouter.master, &fnc->t_nhgwalk, NULL);
+ event_cancel_async(zrouter.master, &fnc->t_ribreset, NULL);
+ event_cancel_async(zrouter.master, &fnc->t_ribwalk, NULL);
+ event_cancel_async(zrouter.master, &fnc->t_rmacreset, NULL);
+ event_cancel_async(zrouter.master, &fnc->t_rmacwalk, NULL);
/*
* Grab the lock to empty the streams (data plane might try to
stream_reset(fnc->ibuf);
stream_reset(fnc->obuf);
- THREAD_OFF(fnc->t_read);
- THREAD_OFF(fnc->t_write);
+ EVENT_OFF(fnc->t_read);
+ EVENT_OFF(fnc->t_write);
/* FPM is disabled, don't attempt to connect. */
if (fnc->disabled)
return;
- thread_add_timer(fnc->fthread->master, fpm_connect, fnc, 3,
- &fnc->t_connect);
+ event_add_timer(fnc->fthread->master, fpm_connect, fnc, 3,
+ &fnc->t_connect);
}
-static void fpm_read(struct thread *t)
+static void fpm_read(struct event *t)
{
- struct fpm_nl_ctx *fnc = THREAD_ARG(t);
+ struct fpm_nl_ctx *fnc = EVENT_ARG(t);
fpm_msg_hdr_t fpm;
ssize_t rv;
char buf[65535];
}
/* Schedule the next read */
- thread_add_read(fnc->fthread->master, fpm_read, fnc, fnc->socket,
- &fnc->t_read);
+ event_add_read(fnc->fthread->master, fpm_read, fnc, fnc->socket,
+ &fnc->t_read);
/* We've got an interruption. */
if (rv == -2)
stream_reset(fnc->ibuf);
}
-static void fpm_write(struct thread *t)
+static void fpm_write(struct event *t)
{
- struct fpm_nl_ctx *fnc = THREAD_ARG(t);
+ struct fpm_nl_ctx *fnc = EVENT_ARG(t);
socklen_t statuslen;
ssize_t bwritten;
int rv, status;
* Starting with LSPs walk all FPM objects, marking them
* as unsent and then replaying them.
*/
- thread_add_timer(zrouter.master, fpm_lsp_reset, fnc, 0,
- &fnc->t_lspreset);
+ event_add_timer(zrouter.master, fpm_lsp_reset, fnc, 0,
+ &fnc->t_lspreset);
/* Permit receiving messages now. */
- thread_add_read(fnc->fthread->master, fpm_read, fnc,
- fnc->socket, &fnc->t_read);
+ event_add_read(fnc->fthread->master, fpm_read, fnc, fnc->socket,
+ &fnc->t_read);
}
frr_mutex_lock_autounlock(&fnc->obuf_mutex);
/* Stream is not empty yet, we must schedule more writes. */
if (STREAM_READABLE(fnc->obuf)) {
stream_pulldown(fnc->obuf);
- thread_add_write(fnc->fthread->master, fpm_write, fnc,
- fnc->socket, &fnc->t_write);
+ event_add_write(fnc->fthread->master, fpm_write, fnc,
+ fnc->socket, &fnc->t_write);
return;
}
}
-static void fpm_connect(struct thread *t)
+static void fpm_connect(struct event *t)
{
- struct fpm_nl_ctx *fnc = THREAD_ARG(t);
+ struct fpm_nl_ctx *fnc = EVENT_ARG(t);
struct sockaddr_in *sin = (struct sockaddr_in *)&fnc->addr;
struct sockaddr_in6 *sin6 = (struct sockaddr_in6 *)&fnc->addr;
socklen_t slen;
if (sock == -1) {
zlog_err("%s: fpm socket failed: %s", __func__,
strerror(errno));
- thread_add_timer(fnc->fthread->master, fpm_connect, fnc, 3,
- &fnc->t_connect);
+ event_add_timer(fnc->fthread->master, fpm_connect, fnc, 3,
+ &fnc->t_connect);
return;
}
close(sock);
zlog_warn("%s: fpm connection failed: %s", __func__,
strerror(errno));
- thread_add_timer(fnc->fthread->master, fpm_connect, fnc, 3,
- &fnc->t_connect);
+ event_add_timer(fnc->fthread->master, fpm_connect, fnc, 3,
+ &fnc->t_connect);
return;
}
fnc->connecting = (errno == EINPROGRESS);
fnc->socket = sock;
if (!fnc->connecting)
- thread_add_read(fnc->fthread->master, fpm_read, fnc, sock,
- &fnc->t_read);
- thread_add_write(fnc->fthread->master, fpm_write, fnc, sock,
- &fnc->t_write);
+ event_add_read(fnc->fthread->master, fpm_read, fnc, sock,
+ &fnc->t_read);
+ event_add_write(fnc->fthread->master, fpm_write, fnc, sock,
+ &fnc->t_write);
/*
* Starting with LSPs walk all FPM objects, marking them
* If we are not connected, then delay the objects reset/send.
*/
if (!fnc->connecting)
- thread_add_timer(zrouter.master, fpm_lsp_reset, fnc, 0,
- &fnc->t_lspreset);
+ event_add_timer(zrouter.master, fpm_lsp_reset, fnc, 0,
+ &fnc->t_lspreset);
}
/**
memory_order_relaxed);
/* Tell the thread to start writing. */
- thread_add_write(fnc->fthread->master, fpm_write, fnc, fnc->socket,
- &fnc->t_write);
+ event_add_write(fnc->fthread->master, fpm_write, fnc, fnc->socket,
+ &fnc->t_write);
return 0;
}
return HASHWALK_CONTINUE;
}
-static void fpm_lsp_send(struct thread *t)
+static void fpm_lsp_send(struct event *t)
{
- struct fpm_nl_ctx *fnc = THREAD_ARG(t);
- struct zebra_vrf *zvrf = vrf_info_lookup(VRF_DEFAULT);
+ struct fpm_nl_ctx *fnc = EVENT_ARG(t);
+ struct zebra_vrf *zvrf = zebra_vrf_lookup_by_id(VRF_DEFAULT);
struct fpm_lsp_arg fla;
fla.fnc = fnc;
WALK_FINISH(fnc, FNE_LSP_FINISHED);
/* Now move onto routes */
- thread_add_timer(zrouter.master, fpm_nhg_reset, fnc, 0,
- &fnc->t_nhgreset);
+ event_add_timer(zrouter.master, fpm_nhg_reset, fnc, 0,
+ &fnc->t_nhgreset);
} else {
/* Didn't finish - reschedule LSP walk */
- thread_add_timer(zrouter.master, fpm_lsp_send, fnc, 0,
- &fnc->t_lspwalk);
+ event_add_timer(zrouter.master, fpm_lsp_send, fnc, 0,
+ &fnc->t_lspwalk);
}
}
return HASHWALK_CONTINUE;
}
-static void fpm_nhg_send(struct thread *t)
+static void fpm_nhg_send(struct event *t)
{
- struct fpm_nl_ctx *fnc = THREAD_ARG(t);
+ struct fpm_nl_ctx *fnc = EVENT_ARG(t);
struct fpm_nhg_arg fna;
fna.fnc = fnc;
/* We are done sending next hops, lets install the routes now. */
if (fna.complete) {
WALK_FINISH(fnc, FNE_NHG_FINISHED);
- thread_add_timer(zrouter.master, fpm_rib_reset, fnc, 0,
- &fnc->t_ribreset);
+ event_add_timer(zrouter.master, fpm_rib_reset, fnc, 0,
+ &fnc->t_ribreset);
} else /* Otherwise reschedule next hop group again. */
- thread_add_timer(zrouter.master, fpm_nhg_send, fnc, 0,
- &fnc->t_nhgwalk);
+ event_add_timer(zrouter.master, fpm_nhg_send, fnc, 0,
+ &fnc->t_nhgwalk);
}
/**
* Send all RIB installed routes to the connected data plane.
*/
-static void fpm_rib_send(struct thread *t)
+static void fpm_rib_send(struct event *t)
{
- struct fpm_nl_ctx *fnc = THREAD_ARG(t);
+ struct fpm_nl_ctx *fnc = EVENT_ARG(t);
rib_dest_t *dest;
struct route_node *rn;
struct route_table *rt;
/* Free the temporary allocated context. */
dplane_ctx_fini(&ctx);
- thread_add_timer(zrouter.master, fpm_rib_send,
- fnc, 1, &fnc->t_ribwalk);
+ event_add_timer(zrouter.master, fpm_rib_send,
+ fnc, 1, &fnc->t_ribwalk);
return;
}
WALK_FINISH(fnc, FNE_RIB_FINISHED);
/* Schedule next event: RMAC reset. */
- thread_add_event(zrouter.master, fpm_rmac_reset, fnc, 0,
- &fnc->t_rmacreset);
+ event_add_event(zrouter.master, fpm_rmac_reset, fnc, 0,
+ &fnc->t_rmacreset);
}
/*
zrmac->fwd_info.r_vtep_ip, sticky, 0 /*nhg*/,
0 /*update_flags*/);
if (fpm_nl_enqueue(fra->fnc, fra->ctx) == -1) {
- thread_add_timer(zrouter.master, fpm_rmac_send,
- fra->fnc, 1, &fra->fnc->t_rmacwalk);
+ event_add_timer(zrouter.master, fpm_rmac_send, fra->fnc, 1,
+ &fra->fnc->t_rmacwalk);
fra->complete = false;
}
}
hash_iterate(zl3vni->rmac_table, fpm_enqueue_rmac_table, zl3vni);
}
-static void fpm_rmac_send(struct thread *t)
+static void fpm_rmac_send(struct event *t)
{
struct fpm_rmac_arg fra;
- fra.fnc = THREAD_ARG(t);
+ fra.fnc = EVENT_ARG(t);
fra.ctx = dplane_ctx_alloc();
fra.complete = true;
hash_iterate(zrouter.l3vni_table, fpm_enqueue_l3vni_table, &fra);
UNSET_FLAG(nhe->flags, NEXTHOP_GROUP_FPM);
}
-static void fpm_nhg_reset(struct thread *t)
+static void fpm_nhg_reset(struct event *t)
{
- struct fpm_nl_ctx *fnc = THREAD_ARG(t);
+ struct fpm_nl_ctx *fnc = EVENT_ARG(t);
hash_iterate(zrouter.nhgs_id, fpm_nhg_reset_cb, NULL);
/* Schedule next step: send next hop groups. */
- thread_add_event(zrouter.master, fpm_nhg_send, fnc, 0, &fnc->t_nhgwalk);
+ event_add_event(zrouter.master, fpm_nhg_send, fnc, 0, &fnc->t_nhgwalk);
}
/*
UNSET_FLAG(lsp->flags, LSP_FLAG_FPM);
}
-static void fpm_lsp_reset(struct thread *t)
+static void fpm_lsp_reset(struct event *t)
{
- struct fpm_nl_ctx *fnc = THREAD_ARG(t);
- struct zebra_vrf *zvrf = vrf_info_lookup(VRF_DEFAULT);
+ struct fpm_nl_ctx *fnc = EVENT_ARG(t);
+ struct zebra_vrf *zvrf = zebra_vrf_lookup_by_id(VRF_DEFAULT);
hash_iterate(zvrf->lsp_table, fpm_lsp_reset_cb, NULL);
/* Schedule next step: send LSPs */
- thread_add_event(zrouter.master, fpm_lsp_send, fnc, 0, &fnc->t_lspwalk);
+ event_add_event(zrouter.master, fpm_lsp_send, fnc, 0, &fnc->t_lspwalk);
}
/**
* Resets the RIB FPM flags so we send all routes again.
*/
-static void fpm_rib_reset(struct thread *t)
+static void fpm_rib_reset(struct event *t)
{
- struct fpm_nl_ctx *fnc = THREAD_ARG(t);
+ struct fpm_nl_ctx *fnc = EVENT_ARG(t);
rib_dest_t *dest;
struct route_node *rn;
struct route_table *rt;
}
/* Schedule next step: send RIB routes. */
- thread_add_event(zrouter.master, fpm_rib_send, fnc, 0, &fnc->t_ribwalk);
+ event_add_event(zrouter.master, fpm_rib_send, fnc, 0, &fnc->t_ribwalk);
}
/*
hash_iterate(zl3vni->rmac_table, fpm_unset_rmac_table, zl3vni);
}
-static void fpm_rmac_reset(struct thread *t)
+static void fpm_rmac_reset(struct event *t)
{
- struct fpm_nl_ctx *fnc = THREAD_ARG(t);
+ struct fpm_nl_ctx *fnc = EVENT_ARG(t);
hash_iterate(zrouter.l3vni_table, fpm_unset_l3vni_table, NULL);
/* Schedule next event: send RMAC entries. */
- thread_add_event(zrouter.master, fpm_rmac_send, fnc, 0,
- &fnc->t_rmacwalk);
+ event_add_event(zrouter.master, fpm_rmac_send, fnc, 0,
+ &fnc->t_rmacwalk);
}
-static void fpm_process_queue(struct thread *t)
+static void fpm_process_queue(struct event *t)
{
- struct fpm_nl_ctx *fnc = THREAD_ARG(t);
+ struct fpm_nl_ctx *fnc = EVENT_ARG(t);
struct zebra_dplane_ctx *ctx;
bool no_bufs = false;
uint64_t processed_contexts = 0;
/* Re-schedule if we ran out of buffer space */
if (no_bufs)
- thread_add_timer(fnc->fthread->master, fpm_process_queue,
- fnc, 0, &fnc->t_dequeue);
+ event_add_timer(fnc->fthread->master, fpm_process_queue, fnc, 0,
+ &fnc->t_dequeue);
/*
* Let the dataplane thread know if there are items in the
/**
* Handles external (e.g. CLI, data plane or others) events.
*/
-static void fpm_process_event(struct thread *t)
+static void fpm_process_event(struct event *t)
{
- struct fpm_nl_ctx *fnc = THREAD_ARG(t);
- enum fpm_nl_events event = THREAD_VAL(t);
+ struct fpm_nl_ctx *fnc = EVENT_ARG(t);
+ enum fpm_nl_events event = EVENT_VAL(t);
switch (event) {
case FNE_DISABLE:
static int fpm_nl_finish_early(struct fpm_nl_ctx *fnc)
{
/* Disable all events and close socket. */
- THREAD_OFF(fnc->t_lspreset);
- THREAD_OFF(fnc->t_lspwalk);
- THREAD_OFF(fnc->t_nhgreset);
- THREAD_OFF(fnc->t_nhgwalk);
- THREAD_OFF(fnc->t_ribreset);
- THREAD_OFF(fnc->t_ribwalk);
- THREAD_OFF(fnc->t_rmacreset);
- THREAD_OFF(fnc->t_rmacwalk);
- THREAD_OFF(fnc->t_event);
- THREAD_OFF(fnc->t_nhg);
- thread_cancel_async(fnc->fthread->master, &fnc->t_read, NULL);
- thread_cancel_async(fnc->fthread->master, &fnc->t_write, NULL);
- thread_cancel_async(fnc->fthread->master, &fnc->t_connect, NULL);
+ EVENT_OFF(fnc->t_lspreset);
+ EVENT_OFF(fnc->t_lspwalk);
+ EVENT_OFF(fnc->t_nhgreset);
+ EVENT_OFF(fnc->t_nhgwalk);
+ EVENT_OFF(fnc->t_ribreset);
+ EVENT_OFF(fnc->t_ribwalk);
+ EVENT_OFF(fnc->t_rmacreset);
+ EVENT_OFF(fnc->t_rmacwalk);
+ EVENT_OFF(fnc->t_event);
+ EVENT_OFF(fnc->t_nhg);
+ event_cancel_async(fnc->fthread->master, &fnc->t_read, NULL);
+ event_cancel_async(fnc->fthread->master, &fnc->t_write, NULL);
+ event_cancel_async(fnc->fthread->master, &fnc->t_connect, NULL);
if (fnc->socket != -1) {
close(fnc->socket);
if (atomic_load_explicit(&fnc->counters.ctxqueue_len,
memory_order_relaxed)
> 0)
- thread_add_timer(fnc->fthread->master, fpm_process_queue,
- fnc, 0, &fnc->t_dequeue);
+ event_add_timer(fnc->fthread->master, fpm_process_queue, fnc, 0,
+ &fnc->t_dequeue);
/* Ensure dataplane thread is rescheduled if we hit the work limit */
if (counter >= limit)
return 0;
}
-static int fpm_nl_new(struct thread_master *tm)
+static int fpm_nl_new(struct event_loop *tm)
{
struct zebra_dplane_provider *prov = NULL;
int rv;