diff options
Diffstat (limited to 'zebra/zebra_dplane.c')
| -rw-r--r-- | zebra/zebra_dplane.c | 325 |
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); } |
