summaryrefslogtreecommitdiff
path: root/zebra/zebra_dplane.c
diff options
context:
space:
mode:
Diffstat (limited to 'zebra/zebra_dplane.c')
-rw-r--r--zebra/zebra_dplane.c205
1 files changed, 165 insertions, 40 deletions
diff --git a/zebra/zebra_dplane.c b/zebra/zebra_dplane.c
index 9f9270db9a..6de2be3ab8 100644
--- a/zebra/zebra_dplane.c
+++ b/zebra/zebra_dplane.c
@@ -28,6 +28,7 @@
#include "lib/memory.h"
#include "lib/queue.h"
#include "lib/zebra.h"
+#include "zebra/netconf_netlink.h"
#include "zebra/zebra_router.h"
#include "zebra/zebra_dplane.h"
#include "zebra/zebra_vxlan_private.h"
@@ -290,6 +291,19 @@ struct dplane_gre_ctx {
unsigned int mtu;
struct zebra_l2info_gre info;
};
+
+
+/*
+ * Network interface configuration info - aligned with netlink's NETCONF
+ * info. The flags values are public, in the dplane.h file...
+ */
+struct dplane_netconf_info {
+ ns_id_t ns_id;
+ ifindex_t ifindex;
+ enum dplane_netconf_status_e mpls_val;
+ enum dplane_netconf_status_e mcast_val;
+};
+
/*
* The context block used to exchange info about route updates across
* the boundary between the zebra main context (and pthread) and the
@@ -347,6 +361,7 @@ struct zebra_dplane_ctx {
} ipset_entry;
struct dplane_neigh_table neightable;
struct dplane_gre_ctx gre;
+ struct dplane_netconf_info netconf;
} u;
/* Namespace info, used especially for netlink kernel communication */
@@ -416,6 +431,9 @@ PREDECL_DLIST(zns_info_list);
struct dplane_zns_info {
struct zebra_dplane_info info;
+ /* Request data from the OS */
+ struct thread *t_request;
+
/* Read event */
struct thread *t_read;
@@ -539,9 +557,7 @@ DECLARE_DLIST(zns_info_list, struct dplane_zns_info, link);
#define DPLANE_PROV_UNLOCK(p) pthread_mutex_unlock(&((p)->dp_mutex))
/* Prototypes */
-static int dplane_thread_loop(struct thread *event);
-static void dplane_info_from_zns(struct zebra_dplane_info *ns_info,
- struct zebra_ns *zns);
+static void dplane_thread_loop(struct thread *event);
static enum zebra_dplane_result lsp_update_internal(struct zebra_lsp *lsp,
enum dplane_op_e op);
static enum zebra_dplane_result pw_update_internal(struct zebra_pw *pw,
@@ -769,6 +785,7 @@ static void dplane_ctx_free_internal(struct zebra_dplane_ctx *ctx)
}
break;
case DPLANE_OP_GRE_SET:
+ case DPLANE_OP_INTF_NETCONFIG:
break;
}
}
@@ -1053,6 +1070,9 @@ const char *dplane_op2str(enum dplane_op_e op)
case DPLANE_OP_INTF_ADDR_DEL:
return "INTF_ADDR_DEL";
+
+ case DPLANE_OP_INTF_NETCONFIG:
+ return "INTF_NETCONFIG";
}
return ret;
@@ -2239,6 +2259,10 @@ uint32_t dplane_intf_extra_get_status(const struct dplane_intf_extra *ptr)
return ptr->status;
}
+/*
+ * End of interface extra info accessors
+ */
+
uint8_t dplane_ctx_neightable_get_family(const struct zebra_dplane_ctx *ctx)
{
DPLANE_CTX_VALID(ctx);
@@ -2270,9 +2294,66 @@ dplane_ctx_neightable_get_mcast_probes(const struct zebra_dplane_ctx *ctx)
return ctx->u.neightable.mcast_probes;
}
-/*
- * End of interface extra info accessors
- */
+ifindex_t dplane_ctx_get_netconf_ifindex(const struct zebra_dplane_ctx *ctx)
+{
+ DPLANE_CTX_VALID(ctx);
+
+ return ctx->u.netconf.ifindex;
+}
+
+ns_id_t dplane_ctx_get_netconf_ns_id(const struct zebra_dplane_ctx *ctx)
+{
+ DPLANE_CTX_VALID(ctx);
+
+ return ctx->u.netconf.ns_id;
+}
+
+void dplane_ctx_set_netconf_ifindex(struct zebra_dplane_ctx *ctx,
+ ifindex_t ifindex)
+{
+ DPLANE_CTX_VALID(ctx);
+
+ ctx->u.netconf.ifindex = ifindex;
+}
+
+void dplane_ctx_set_netconf_ns_id(struct zebra_dplane_ctx *ctx, ns_id_t ns_id)
+{
+ DPLANE_CTX_VALID(ctx);
+
+ ctx->u.netconf.ns_id = ns_id;
+}
+
+enum dplane_netconf_status_e
+dplane_ctx_get_netconf_mpls(const struct zebra_dplane_ctx *ctx)
+{
+ DPLANE_CTX_VALID(ctx);
+
+ return ctx->u.netconf.mpls_val;
+}
+
+enum dplane_netconf_status_e
+dplane_ctx_get_netconf_mcast(const struct zebra_dplane_ctx *ctx)
+{
+ DPLANE_CTX_VALID(ctx);
+
+ return ctx->u.netconf.mcast_val;
+}
+
+void dplane_ctx_set_netconf_mpls(struct zebra_dplane_ctx *ctx,
+ enum dplane_netconf_status_e val)
+{
+ DPLANE_CTX_VALID(ctx);
+
+ ctx->u.netconf.mpls_val = val;
+}
+
+void dplane_ctx_set_netconf_mcast(struct zebra_dplane_ctx *ctx,
+ enum dplane_netconf_status_e val)
+{
+ DPLANE_CTX_VALID(ctx);
+
+ ctx->u.netconf.mcast_val = val;
+}
/*
* Retrieve the limit on the number of pending, unprocessed updates.
@@ -2306,13 +2387,29 @@ uint32_t dplane_get_in_queue_len(void)
}
/*
+ * Internal helper that copies information from a zebra ns object; this is
+ * called in the zebra main pthread context as part of dplane ctx init.
+ */
+static void ctx_info_from_zns(struct zebra_dplane_info *ns_info,
+ struct zebra_ns *zns)
+{
+ ns_info->ns_id = zns->ns_id;
+
+#if defined(HAVE_NETLINK)
+ ns_info->is_cmd = true;
+ ns_info->sock = zns->netlink_dplane_out.sock;
+ ns_info->seq = zns->netlink_dplane_out.seq;
+#endif /* NETLINK */
+}
+
+/*
* Common dataplane context init with zebra namespace info.
*/
static int dplane_ctx_ns_init(struct zebra_dplane_ctx *ctx,
struct zebra_ns *zns,
bool is_update)
{
- dplane_info_from_zns(&(ctx->zd_ns_info), zns);
+ ctx_info_from_zns(&(ctx->zd_ns_info), zns); /* */
ctx->zd_is_update = is_update;
@@ -4844,27 +4941,12 @@ bool dplane_provider_is_threaded(const struct zebra_dplane_provider *prov)
return (prov->dp_flags & DPLANE_PROV_FLAG_THREADED);
}
-/*
- * Internal helper that copies information from a zebra ns object; this is
- * called in the zebra main pthread context as part of dplane ctx init.
- */
-static void dplane_info_from_zns(struct zebra_dplane_info *ns_info,
- struct zebra_ns *zns)
-{
- ns_info->ns_id = zns->ns_id;
-
-#if defined(HAVE_NETLINK)
- ns_info->is_cmd = true;
- ns_info->sock = zns->netlink_dplane_out.sock;
-#endif /* NETLINK */
-}
-
#ifdef HAVE_NETLINK
/*
* Callback when an OS (netlink) incoming event read is ready. This runs
* in the dplane pthread.
*/
-static int dplane_incoming_read(struct thread *event)
+static void dplane_incoming_read(struct thread *event)
{
struct dplane_zns_info *zi = THREAD_ARG(event);
@@ -4873,9 +4955,41 @@ static int dplane_incoming_read(struct thread *event)
/* Re-start read task */
thread_add_read(zdplane_info.dg_master, dplane_incoming_read, zi,
zi->info.sock, &zi->t_read);
+}
- return 0;
+/*
+ * Callback in the dataplane pthread that requests info from the OS and
+ * initiates netlink reads.
+ */
+static void dplane_incoming_request(struct thread *event)
+{
+ struct dplane_zns_info *zi = THREAD_ARG(event);
+
+ /* Start read task */
+ thread_add_read(zdplane_info.dg_master, dplane_incoming_read, zi,
+ zi->info.sock, &zi->t_read);
+
+ /* Send requests */
+ netlink_request_netconf(zi->info.sock);
+}
+
+/*
+ * Initiate requests for existing info from the OS. This is called by the
+ * main pthread, but we want all activity on the dplane netlink socket to
+ * take place on the dplane pthread, so we schedule an event to accomplish
+ * that.
+ */
+static void dplane_kernel_info_request(struct dplane_zns_info *zi)
+{
+ /* If we happen to encounter an enabled zns before the dplane
+ * pthread is running, we'll initiate this later on.
+ */
+ if (zdplane_info.dg_master)
+ thread_add_event(zdplane_info.dg_master,
+ dplane_incoming_request, zi, 0,
+ &zi->t_request);
}
+
#endif /* HAVE_NETLINK */
/*
@@ -4919,11 +5033,10 @@ void zebra_dplane_ns_enable(struct zebra_ns *zns, bool enabled)
zi->info.is_cmd = false;
zi->info.sock = zns->netlink_dplane_in.sock;
- /* Start read task for the dplane pthread. */
- if (zdplane_info.dg_master)
- thread_add_read(zdplane_info.dg_master,
- dplane_incoming_read, zi, zi->info.sock,
- &zi->t_read);
+ /* Initiate requests for existing info from the OS, and
+ * begin reading from the netlink socket.
+ */
+ dplane_kernel_info_request(zi);
#endif
} else if (zi) {
if (IS_ZEBRA_DEBUG_DPLANE)
@@ -4933,9 +5046,14 @@ void zebra_dplane_ns_enable(struct zebra_ns *zns, bool enabled)
/* Stop reading, free memory */
zns_info_list_del(&zdplane_info.dg_zns_list, zi);
- if (zdplane_info.dg_master)
+ /* Stop any outstanding tasks */
+ if (zdplane_info.dg_master) {
+ thread_cancel_async(zdplane_info.dg_master,
+ &zi->t_request, NULL);
+
thread_cancel_async(zdplane_info.dg_master, &zi->t_read,
NULL);
+ }
XFREE(MTYPE_DP_NS, zi);
}
@@ -5115,6 +5233,14 @@ static void kernel_dplane_log_detail(struct zebra_dplane_ctx *ctx)
dplane_ctx_get_ifname(ctx),
dplane_ctx_get_intf_addr(ctx));
break;
+
+ case DPLANE_OP_INTF_NETCONFIG:
+ zlog_debug("%s: ifindex %d, mpls %d, mcast %d",
+ dplane_op2str(dplane_ctx_get_op(ctx)),
+ dplane_ctx_get_netconf_ifindex(ctx),
+ dplane_ctx_get_netconf_mpls(ctx),
+ dplane_ctx_get_netconf_mcast(ctx));
+ break;
}
}
@@ -5260,6 +5386,7 @@ static void kernel_dplane_handle_result(struct zebra_dplane_ctx *ctx)
/* TODO -- error counters for incoming events? */
case DPLANE_OP_INTF_ADDR_ADD:
case DPLANE_OP_INTF_ADDR_DEL:
+ case DPLANE_OP_INTF_NETCONFIG:
break;
case DPLANE_OP_NONE:
@@ -5595,7 +5722,7 @@ done:
* final zebra shutdown.
* This runs in the dplane pthread context.
*/
-static int dplane_check_shutdown_status(struct thread *event)
+static void dplane_check_shutdown_status(struct thread *event)
{
struct dplane_zns_info *zi;
@@ -5606,8 +5733,10 @@ static int dplane_check_shutdown_status(struct thread *event)
frr_each_safe (zns_info_list, &zdplane_info.dg_zns_list, zi) {
zns_info_list_del(&zdplane_info.dg_zns_list, zi);
- if (zdplane_info.dg_master)
+ if (zdplane_info.dg_master) {
thread_cancel(&zi->t_read);
+ thread_cancel(&zi->t_request);
+ }
XFREE(MTYPE_DP_NS, zi);
}
@@ -5627,8 +5756,6 @@ static int dplane_check_shutdown_status(struct thread *event)
*/
thread_add_event(zrouter.master, zebra_finalize, NULL, 0, NULL);
}
-
- return 0;
}
/*
@@ -5662,7 +5789,7 @@ void zebra_dplane_finish(void)
* pthread can look for other pending work - such as i/o work on behalf of
* providers.
*/
-static int dplane_thread_loop(struct thread *event)
+static void dplane_thread_loop(struct thread *event)
{
struct dplane_ctx_q work_list;
struct dplane_ctx_q error_list;
@@ -5682,7 +5809,7 @@ static int dplane_thread_loop(struct thread *event)
/* Check for zebra shutdown */
if (!zdplane_info.dg_run)
- goto done;
+ return;
/* Dequeue some incoming work from zebra (if any) onto the temporary
* working list.
@@ -5848,9 +5975,6 @@ static int dplane_thread_loop(struct thread *event)
(zdplane_info.dg_results_cb)(&work_list);
TAILQ_INIT(&work_list);
-
-done:
- return 0;
}
/*
@@ -5942,11 +6066,12 @@ void zebra_dplane_start(void)
thread_add_event(zdplane_info.dg_master, dplane_thread_loop, NULL, 0,
&zdplane_info.dg_t_update);
- /* Enqueue reads if necessary */
+ /* Enqueue requests and reads if necessary */
frr_each (zns_info_list, &zdplane_info.dg_zns_list, zi) {
#if defined(HAVE_NETLINK)
thread_add_read(zdplane_info.dg_master, dplane_incoming_read,
zi, zi->info.sock, &zi->t_read);
+ dplane_kernel_info_request(zi);
#endif
}