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.c325
1 files changed, 318 insertions, 7 deletions
diff --git a/zebra/zebra_dplane.c b/zebra/zebra_dplane.c
index 6fc62147c8..1707d3a68b 100644
--- a/zebra/zebra_dplane.c
+++ b/zebra/zebra_dplane.c
@@ -172,6 +172,11 @@ struct zebra_dplane_ctx {
uint32_t zd_seq;
uint32_t zd_old_seq;
+ /* Some updates may be generated by notifications: allow the
+ * plugin to notice and ignore results from its own notifications.
+ */
+ uint32_t zd_notif_provider;
+
/* TODO -- internal/sub-operation status? */
enum zebra_dplane_result zd_remote_status;
enum zebra_dplane_result zd_kernel_status;
@@ -222,6 +227,8 @@ struct zebra_dplane_provider {
/* Flags */
int dp_flags;
+ int (*dp_start)(struct zebra_dplane_provider *prov);
+
int (*dp_fp)(struct zebra_dplane_provider *prov);
int (*dp_fini)(struct zebra_dplane_provider *prov, bool early_p);
@@ -351,7 +358,7 @@ struct thread_master *dplane_get_thread_master(void)
/*
* Allocate a dataplane update context
*/
-static struct zebra_dplane_ctx *dplane_ctx_alloc(void)
+struct zebra_dplane_ctx *dplane_ctx_alloc(void)
{
struct zebra_dplane_ctx *p;
@@ -392,6 +399,7 @@ static void dplane_ctx_free(struct zebra_dplane_ctx **pctx)
case DPLANE_OP_ROUTE_DELETE:
case DPLANE_OP_SYS_ROUTE_ADD:
case DPLANE_OP_SYS_ROUTE_DELETE:
+ case DPLANE_OP_ROUTE_NOTIFY:
/* Free allocated nexthops */
if ((*pctx)->u.rinfo.zd_ng.nexthop) {
@@ -413,6 +421,7 @@ static void dplane_ctx_free(struct zebra_dplane_ctx **pctx)
case DPLANE_OP_LSP_INSTALL:
case DPLANE_OP_LSP_UPDATE:
case DPLANE_OP_LSP_DELETE:
+ case DPLANE_OP_LSP_NOTIFY:
{
zebra_nhlfe_t *nhlfe, *next;
@@ -543,6 +552,12 @@ bool dplane_ctx_is_skip_kernel(const struct zebra_dplane_ctx *ctx)
return CHECK_FLAG(ctx->zd_flags, DPLANE_CTX_FLAG_NO_KERNEL);
}
+void dplane_ctx_set_op(struct zebra_dplane_ctx *ctx, enum dplane_op_e op)
+{
+ DPLANE_CTX_VALID(ctx);
+ ctx->zd_op = op;
+}
+
enum dplane_op_e dplane_ctx_get_op(const struct zebra_dplane_ctx *ctx)
{
DPLANE_CTX_VALID(ctx);
@@ -569,6 +584,9 @@ const char *dplane_op2str(enum dplane_op_e op)
case DPLANE_OP_ROUTE_DELETE:
ret = "ROUTE_DELETE";
break;
+ case DPLANE_OP_ROUTE_NOTIFY:
+ ret = "ROUTE_NOTIFY";
+ break;
case DPLANE_OP_LSP_INSTALL:
ret = "LSP_INSTALL";
@@ -579,6 +597,9 @@ const char *dplane_op2str(enum dplane_op_e op)
case DPLANE_OP_LSP_DELETE:
ret = "LSP_DELETE";
break;
+ case DPLANE_OP_LSP_NOTIFY:
+ ret = "LSP_NOTIFY";
+ break;
case DPLANE_OP_PW_INSTALL:
ret = "PW_INSTALL";
@@ -625,6 +646,14 @@ const char *dplane_res2str(enum zebra_dplane_result res)
return ret;
}
+void dplane_ctx_set_dest(struct zebra_dplane_ctx *ctx,
+ const struct prefix *dest)
+{
+ DPLANE_CTX_VALID(ctx);
+
+ prefix_copy(&(ctx->u.rinfo.zd_dest), dest);
+}
+
const struct prefix *dplane_ctx_get_dest(const struct zebra_dplane_ctx *ctx)
{
DPLANE_CTX_VALID(ctx);
@@ -632,6 +661,16 @@ const struct prefix *dplane_ctx_get_dest(const struct zebra_dplane_ctx *ctx)
return &(ctx->u.rinfo.zd_dest);
}
+void dplane_ctx_set_src(struct zebra_dplane_ctx *ctx, const struct prefix *src)
+{
+ DPLANE_CTX_VALID(ctx);
+
+ if (src)
+ prefix_copy(&(ctx->u.rinfo.zd_src), src);
+ else
+ memset(&(ctx->u.rinfo.zd_src), 0, sizeof(struct prefix));
+}
+
/* Source prefix is a little special - return NULL for "no src prefix" */
const struct prefix *dplane_ctx_get_src(const struct zebra_dplane_ctx *ctx)
{
@@ -666,6 +705,13 @@ uint32_t dplane_ctx_get_old_seq(const struct zebra_dplane_ctx *ctx)
return ctx->zd_old_seq;
}
+void dplane_ctx_set_vrf(struct zebra_dplane_ctx *ctx, vrf_id_t vrf)
+{
+ DPLANE_CTX_VALID(ctx);
+
+ ctx->zd_vrf_id = vrf;
+}
+
vrf_id_t dplane_ctx_get_vrf(const struct zebra_dplane_ctx *ctx)
{
DPLANE_CTX_VALID(ctx);
@@ -673,6 +719,35 @@ vrf_id_t dplane_ctx_get_vrf(const struct zebra_dplane_ctx *ctx)
return ctx->zd_vrf_id;
}
+bool dplane_ctx_is_from_notif(const struct zebra_dplane_ctx *ctx)
+{
+ DPLANE_CTX_VALID(ctx);
+
+ return (ctx->zd_notif_provider != 0);
+}
+
+uint32_t dplane_ctx_get_notif_provider(const struct zebra_dplane_ctx *ctx)
+{
+ DPLANE_CTX_VALID(ctx);
+
+ return ctx->zd_notif_provider;
+}
+
+void dplane_ctx_set_notif_provider(struct zebra_dplane_ctx *ctx,
+ uint32_t id)
+{
+ DPLANE_CTX_VALID(ctx);
+
+ ctx->zd_notif_provider = id;
+}
+
+void dplane_ctx_set_type(struct zebra_dplane_ctx *ctx, int type)
+{
+ DPLANE_CTX_VALID(ctx);
+
+ ctx->u.rinfo.zd_type = type;
+}
+
int dplane_ctx_get_type(const struct zebra_dplane_ctx *ctx)
{
DPLANE_CTX_VALID(ctx);
@@ -687,6 +762,13 @@ int dplane_ctx_get_old_type(const struct zebra_dplane_ctx *ctx)
return ctx->u.rinfo.zd_old_type;
}
+void dplane_ctx_set_afi(struct zebra_dplane_ctx *ctx, afi_t afi)
+{
+ DPLANE_CTX_VALID(ctx);
+
+ ctx->u.rinfo.zd_afi = afi;
+}
+
afi_t dplane_ctx_get_afi(const struct zebra_dplane_ctx *ctx)
{
DPLANE_CTX_VALID(ctx);
@@ -694,6 +776,13 @@ afi_t dplane_ctx_get_afi(const struct zebra_dplane_ctx *ctx)
return ctx->u.rinfo.zd_afi;
}
+void dplane_ctx_set_safi(struct zebra_dplane_ctx *ctx, safi_t safi)
+{
+ DPLANE_CTX_VALID(ctx);
+
+ ctx->u.rinfo.zd_safi = safi;
+}
+
safi_t dplane_ctx_get_safi(const struct zebra_dplane_ctx *ctx)
{
DPLANE_CTX_VALID(ctx);
@@ -701,6 +790,13 @@ safi_t dplane_ctx_get_safi(const struct zebra_dplane_ctx *ctx)
return ctx->u.rinfo.zd_safi;
}
+void dplane_ctx_set_table(struct zebra_dplane_ctx *ctx, uint32_t table)
+{
+ DPLANE_CTX_VALID(ctx);
+
+ ctx->zd_table_id = table;
+}
+
uint32_t dplane_ctx_get_table(const struct zebra_dplane_ctx *ctx)
{
DPLANE_CTX_VALID(ctx);
@@ -715,6 +811,13 @@ route_tag_t dplane_ctx_get_tag(const struct zebra_dplane_ctx *ctx)
return ctx->u.rinfo.zd_tag;
}
+void dplane_ctx_set_tag(struct zebra_dplane_ctx *ctx, route_tag_t tag)
+{
+ DPLANE_CTX_VALID(ctx);
+
+ ctx->u.rinfo.zd_tag = tag;
+}
+
route_tag_t dplane_ctx_get_old_tag(const struct zebra_dplane_ctx *ctx)
{
DPLANE_CTX_VALID(ctx);
@@ -729,6 +832,13 @@ uint16_t dplane_ctx_get_instance(const struct zebra_dplane_ctx *ctx)
return ctx->u.rinfo.zd_instance;
}
+void dplane_ctx_set_instance(struct zebra_dplane_ctx *ctx, uint16_t instance)
+{
+ DPLANE_CTX_VALID(ctx);
+
+ ctx->u.rinfo.zd_instance = instance;
+}
+
uint16_t dplane_ctx_get_old_instance(const struct zebra_dplane_ctx *ctx)
{
DPLANE_CTX_VALID(ctx);
@@ -771,6 +881,13 @@ uint8_t dplane_ctx_get_distance(const struct zebra_dplane_ctx *ctx)
return ctx->u.rinfo.zd_distance;
}
+void dplane_ctx_set_distance(struct zebra_dplane_ctx *ctx, uint8_t distance)
+{
+ DPLANE_CTX_VALID(ctx);
+
+ ctx->u.rinfo.zd_distance = distance;
+}
+
uint8_t dplane_ctx_get_old_distance(const struct zebra_dplane_ctx *ctx)
{
DPLANE_CTX_VALID(ctx);
@@ -778,6 +895,17 @@ uint8_t dplane_ctx_get_old_distance(const struct zebra_dplane_ctx *ctx)
return ctx->u.rinfo.zd_old_distance;
}
+void dplane_ctx_set_nexthops(struct zebra_dplane_ctx *ctx, struct nexthop *nh)
+{
+ DPLANE_CTX_VALID(ctx);
+
+ if (ctx->u.rinfo.zd_ng.nexthop) {
+ nexthops_free(ctx->u.rinfo.zd_ng.nexthop);
+ ctx->u.rinfo.zd_ng.nexthop = NULL;
+ }
+ copy_nexthops(&(ctx->u.rinfo.zd_ng.nexthop), nh, NULL);
+}
+
const struct nexthop_group *dplane_ctx_get_ng(
const struct zebra_dplane_ctx *ctx)
{
@@ -811,6 +939,13 @@ mpls_label_t dplane_ctx_get_in_label(const struct zebra_dplane_ctx *ctx)
return ctx->u.lsp.ile.in_label;
}
+void dplane_ctx_set_in_label(struct zebra_dplane_ctx *ctx, mpls_label_t label)
+{
+ DPLANE_CTX_VALID(ctx);
+
+ ctx->u.lsp.ile.in_label = label;
+}
+
uint8_t dplane_ctx_get_addr_family(const struct zebra_dplane_ctx *ctx)
{
DPLANE_CTX_VALID(ctx);
@@ -818,6 +953,14 @@ uint8_t dplane_ctx_get_addr_family(const struct zebra_dplane_ctx *ctx)
return ctx->u.lsp.addr_family;
}
+void dplane_ctx_set_addr_family(struct zebra_dplane_ctx *ctx,
+ uint8_t family)
+{
+ DPLANE_CTX_VALID(ctx);
+
+ ctx->u.lsp.addr_family = family;
+}
+
uint32_t dplane_ctx_get_lsp_flags(const struct zebra_dplane_ctx *ctx)
{
DPLANE_CTX_VALID(ctx);
@@ -825,6 +968,14 @@ uint32_t dplane_ctx_get_lsp_flags(const struct zebra_dplane_ctx *ctx)
return ctx->u.lsp.flags;
}
+void dplane_ctx_set_lsp_flags(struct zebra_dplane_ctx *ctx,
+ uint32_t flags)
+{
+ DPLANE_CTX_VALID(ctx);
+
+ ctx->u.lsp.flags = flags;
+}
+
const zebra_nhlfe_t *dplane_ctx_get_nhlfe(const struct zebra_dplane_ctx *ctx)
{
DPLANE_CTX_VALID(ctx);
@@ -832,6 +983,24 @@ const zebra_nhlfe_t *dplane_ctx_get_nhlfe(const struct zebra_dplane_ctx *ctx)
return ctx->u.lsp.nhlfe_list;
}
+zebra_nhlfe_t *dplane_ctx_add_nhlfe(struct zebra_dplane_ctx *ctx,
+ enum lsp_types_t lsp_type,
+ enum nexthop_types_t nh_type,
+ union g_addr *gate,
+ ifindex_t ifindex,
+ mpls_label_t out_label)
+{
+ zebra_nhlfe_t *nhlfe;
+
+ DPLANE_CTX_VALID(ctx);
+
+ nhlfe = zebra_mpls_lsp_add_nhlfe(&(ctx->u.lsp),
+ lsp_type, nh_type, gate,
+ ifindex, out_label);
+
+ return nhlfe;
+}
+
const zebra_nhlfe_t *
dplane_ctx_get_best_nhlfe(const struct zebra_dplane_ctx *ctx)
{
@@ -840,6 +1009,16 @@ dplane_ctx_get_best_nhlfe(const struct zebra_dplane_ctx *ctx)
return ctx->u.lsp.best_nhlfe;
}
+const zebra_nhlfe_t *
+dplane_ctx_set_best_nhlfe(struct zebra_dplane_ctx *ctx,
+ zebra_nhlfe_t *nhlfe)
+{
+ DPLANE_CTX_VALID(ctx);
+
+ ctx->u.lsp.best_nhlfe = nhlfe;
+ return ctx->u.lsp.best_nhlfe;
+}
+
uint32_t dplane_ctx_get_lsp_num_ecmp(const struct zebra_dplane_ctx *ctx)
{
DPLANE_CTX_VALID(ctx);
@@ -1497,6 +1676,59 @@ done:
}
/*
+ * Update from an async notification, to bring other fibs up-to-date.
+ */
+enum zebra_dplane_result
+dplane_route_notif_update(struct route_node *rn,
+ struct route_entry *re,
+ enum dplane_op_e op,
+ struct zebra_dplane_ctx *ctx)
+{
+ enum zebra_dplane_result ret = ZEBRA_DPLANE_REQUEST_FAILURE;
+ struct zebra_dplane_ctx *new_ctx = NULL;
+ struct nexthop *nexthop;
+
+ if (rn == NULL || re == NULL)
+ goto done;
+
+ new_ctx = dplane_ctx_alloc();
+ if (new_ctx == NULL)
+ goto done;
+
+ /* Init context with info from zebra data structs */
+ dplane_ctx_route_init(new_ctx, op, rn, re);
+
+ /* For add/update, need to adjust the nexthops so that we match
+ * the notification state, which may not be the route-entry/RIB
+ * state.
+ */
+ if (op == DPLANE_OP_ROUTE_UPDATE ||
+ op == DPLANE_OP_ROUTE_INSTALL) {
+
+ nexthops_free(new_ctx->u.rinfo.zd_ng.nexthop);
+ new_ctx->u.rinfo.zd_ng.nexthop = NULL;
+
+ copy_nexthops(&(new_ctx->u.rinfo.zd_ng.nexthop),
+ (rib_active_nhg(re))->nexthop, NULL);
+
+ for (ALL_NEXTHOPS(new_ctx->u.rinfo.zd_ng, nexthop))
+ UNSET_FLAG(nexthop->flags, NEXTHOP_FLAG_FIB);
+
+ }
+
+ /* Capture info about the source of the notification, in 'ctx' */
+ dplane_ctx_set_notif_provider(new_ctx,
+ dplane_ctx_get_notif_provider(ctx));
+
+ dplane_route_enqueue(new_ctx);
+
+ ret = ZEBRA_DPLANE_REQUEST_QUEUED;
+
+done:
+ return ret;
+}
+
+/*
* Enqueue LSP add for the dataplane.
*/
enum zebra_dplane_result dplane_lsp_add(zebra_lsp_t *lsp)
@@ -1529,6 +1761,50 @@ enum zebra_dplane_result dplane_lsp_delete(zebra_lsp_t *lsp)
return ret;
}
+/* Update or un-install resulting from an async notification */
+enum zebra_dplane_result
+dplane_lsp_notif_update(zebra_lsp_t *lsp,
+ enum dplane_op_e op,
+ struct zebra_dplane_ctx *notif_ctx)
+{
+ enum zebra_dplane_result result = ZEBRA_DPLANE_REQUEST_FAILURE;
+ int ret = EINVAL;
+ struct zebra_dplane_ctx *ctx = NULL;
+
+ /* Obtain context block */
+ ctx = dplane_ctx_alloc();
+ if (ctx == NULL) {
+ ret = ENOMEM;
+ goto done;
+ }
+
+ ret = dplane_ctx_lsp_init(ctx, op, lsp);
+ if (ret != AOK)
+ goto done;
+
+ /* Capture info about the source of the notification */
+ dplane_ctx_set_notif_provider(
+ ctx,
+ dplane_ctx_get_notif_provider(notif_ctx));
+
+ ret = dplane_route_enqueue(ctx);
+
+done:
+ /* Update counter */
+ atomic_fetch_add_explicit(&zdplane_info.dg_lsps_in, 1,
+ memory_order_relaxed);
+
+ if (ret == AOK)
+ result = ZEBRA_DPLANE_REQUEST_QUEUED;
+ else {
+ atomic_fetch_add_explicit(&zdplane_info.dg_lsp_errors, 1,
+ memory_order_relaxed);
+ if (ctx)
+ dplane_ctx_free(&ctx);
+ }
+ return result;
+}
+
/*
* Enqueue pseudowire install for the dataplane.
*/
@@ -1823,6 +2099,7 @@ int dplane_show_provs_helper(struct vty *vty, bool detailed)
int dplane_provider_register(const char *name,
enum dplane_provider_prio prio,
int flags,
+ int (*start_fp)(struct zebra_dplane_provider *),
int (*fp)(struct zebra_dplane_provider *),
int (*fini_fp)(struct zebra_dplane_provider *,
bool early),
@@ -1853,6 +2130,7 @@ int dplane_provider_register(const char *name,
p->dp_priority = prio;
p->dp_fp = fp;
+ p->dp_start = start_fp;
p->dp_fini = fini_fp;
p->dp_data = data;
@@ -2046,6 +2324,20 @@ int dplane_provider_work_ready(void)
}
/*
+ * Enqueue a context directly to zebra main.
+ */
+void dplane_provider_enqueue_to_zebra(struct zebra_dplane_ctx *ctx)
+{
+ struct dplane_ctx_q temp_list;
+
+ /* Zebra's api takes a list, so we need to use a temporary list */
+ TAILQ_INIT(&temp_list);
+
+ TAILQ_INSERT_TAIL(&temp_list, ctx, zd_q_entries);
+ (zdplane_info.dg_results_cb)(&temp_list);
+}
+
+/*
* Kernel dataplane provider
*/
@@ -2207,9 +2499,11 @@ static int kernel_dplane_process_func(struct zebra_dplane_provider *prov)
res = kernel_dplane_address_update(ctx);
break;
- /* Ignore system 'notifications' - the kernel already knows */
+ /* Ignore 'notifications' - no-op */
case DPLANE_OP_SYS_ROUTE_ADD:
case DPLANE_OP_SYS_ROUTE_DELETE:
+ case DPLANE_OP_ROUTE_NOTIFY:
+ case DPLANE_OP_LSP_NOTIFY:
res = ZEBRA_DPLANE_REQUEST_SUCCESS;
break;
@@ -2320,7 +2614,7 @@ static void dplane_provider_init(void)
ret = dplane_provider_register("Kernel",
DPLANE_PRIO_KERNEL,
- DPLANE_PROV_FLAGS_DEFAULT,
+ DPLANE_PROV_FLAGS_DEFAULT, NULL,
kernel_dplane_process_func,
NULL,
NULL, NULL);
@@ -2333,7 +2627,7 @@ static void dplane_provider_init(void)
/* Optional test provider ... */
ret = dplane_provider_register("Test",
DPLANE_PRIO_PRE_KERNEL,
- DPLANE_PROV_FLAGS_DEFAULT,
+ DPLANE_PROV_FLAGS_DEFAULT, NULL,
test_dplane_process_func,
test_dplane_shutdown_func,
NULL /* data */, NULL);
@@ -2652,7 +2946,6 @@ static int dplane_thread_loop(struct thread *event)
TAILQ_INIT(&error_list);
-
/* Call through to zebra main */
(zdplane_info.dg_results_cb)(&work_list);
@@ -2717,13 +3010,14 @@ static void zebra_dplane_init_internal(void)
*/
void zebra_dplane_start(void)
{
- /* Start dataplane pthread */
-
+ struct zebra_dplane_provider *prov;
struct frr_pthread_attr pattr = {
.start = frr_pthread_attr_default.start,
.stop = frr_pthread_attr_default.stop
};
+ /* Start dataplane pthread */
+
zdplane_info.dg_pthread = frr_pthread_new(&pattr, "Zebra dplane thread",
"Zebra dplane");
@@ -2735,6 +3029,23 @@ void zebra_dplane_start(void)
thread_add_event(zdplane_info.dg_master, dplane_thread_loop, NULL, 0,
&zdplane_info.dg_t_update);
+ /* Call start callbacks for registered providers */
+
+ DPLANE_LOCK();
+ prov = TAILQ_FIRST(&zdplane_info.dg_providers_q);
+ DPLANE_UNLOCK();
+
+ while (prov) {
+
+ if (prov->dp_start)
+ (prov->dp_start)(prov);
+
+ /* Locate next provider */
+ DPLANE_LOCK();
+ prov = TAILQ_NEXT(prov, dp_prov_link);
+ DPLANE_UNLOCK();
+ }
+
frr_pthread_run(zdplane_info.dg_pthread, NULL);
}