diff options
Diffstat (limited to 'zebra/zebra_dplane.c')
| -rw-r--r-- | zebra/zebra_dplane.c | 312 |
1 files changed, 272 insertions, 40 deletions
diff --git a/zebra/zebra_dplane.c b/zebra/zebra_dplane.c index a547a97c24..ab06ea6438 100644 --- a/zebra/zebra_dplane.c +++ b/zebra/zebra_dplane.c @@ -37,11 +37,12 @@ #include "zebra/zebra_pbr.h" #include "printfrr.h" -/* Memory type for context blocks */ +/* Memory types */ DEFINE_MTYPE_STATIC(ZEBRA, DP_CTX, "Zebra DPlane Ctx"); DEFINE_MTYPE_STATIC(ZEBRA, DP_INTF, "Zebra DPlane Intf"); DEFINE_MTYPE_STATIC(ZEBRA, DP_PROV, "Zebra DPlane Provider"); DEFINE_MTYPE_STATIC(ZEBRA, DP_NETFILTER, "Zebra Netfilter Internal Object"); +DEFINE_MTYPE_STATIC(ZEBRA, DP_NS, "DPlane NSes"); #ifndef AOK # define AOK 0 @@ -324,7 +325,7 @@ struct zebra_dplane_ctx { /* Support info for different kinds of updates */ union { struct dplane_route_info rinfo; - zebra_lsp_t lsp; + struct zebra_lsp lsp; struct dplane_pw_info pw; struct dplane_br_port_info br_port; struct dplane_intf_info intf; @@ -402,6 +403,19 @@ struct zebra_dplane_provider { TAILQ_ENTRY(zebra_dplane_provider) dp_prov_link; }; +/* Declare types for list of zns info objects */ +PREDECL_DLIST(zns_info_list); + +struct dplane_zns_info { + struct zebra_dplane_info info; + + /* Read event */ + struct thread *t_read; + + /* List linkage */ + struct zns_info_list_item link; +}; + /* * Globals */ @@ -424,6 +438,9 @@ static struct zebra_dplane_globals { /* Ordered list of providers */ TAILQ_HEAD(zdg_prov_q, zebra_dplane_provider) dg_providers_q; + /* List of info about each zns */ + struct zns_info_list_head dg_zns_list; + /* Counter used to assign internal ids to providers */ uint32_t dg_provider_id; @@ -498,6 +515,9 @@ static struct zebra_dplane_globals { } zdplane_info; +/* Instantiate zns list type */ +DECLARE_DLIST(zns_info_list, struct dplane_zns_info, link); + /* * Lock and unlock for interactions with the zebra 'core' pthread */ @@ -515,7 +535,7 @@ static struct zebra_dplane_globals { 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 enum zebra_dplane_result lsp_update_internal(zebra_lsp_t *lsp, +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, enum dplane_op_e op); @@ -641,7 +661,7 @@ static void dplane_ctx_free_internal(struct zebra_dplane_ctx *ctx) case DPLANE_OP_LSP_DELETE: case DPLANE_OP_LSP_NOTIFY: { - zebra_nhlfe_t *nhlfe; + struct zebra_nhlfe *nhlfe; /* Unlink and free allocated NHLFEs */ frr_each_safe(nhlfe_list, &ctx->u.lsp.nhlfe_list, nhlfe) { @@ -690,6 +710,8 @@ static void dplane_ctx_free_internal(struct zebra_dplane_ctx *ctx) case DPLANE_OP_ADDR_INSTALL: case DPLANE_OP_ADDR_UNINSTALL: + case DPLANE_OP_INTF_ADDR_ADD: + case DPLANE_OP_INTF_ADDR_DEL: /* Maybe free label string, if allocated */ if (ctx->u.intf.label != NULL && ctx->u.intf.label != ctx->u.intf.label_buf) { @@ -1011,6 +1033,12 @@ const char *dplane_op2str(enum dplane_op_e op) case DPLANE_OP_GRE_SET: ret = "GRE_SET"; break; + + case DPLANE_OP_INTF_ADDR_ADD: + return "INTF_ADDR_ADD"; + + case DPLANE_OP_INTF_ADDR_DEL: + return "INTF_ADDR_DEL"; } return ret; @@ -1108,6 +1136,21 @@ vrf_id_t dplane_ctx_get_vrf(const struct zebra_dplane_ctx *ctx) return ctx->zd_vrf_id; } +/* In some paths we have only a namespace id */ +void dplane_ctx_set_ns_id(struct zebra_dplane_ctx *ctx, ns_id_t nsid) +{ + DPLANE_CTX_VALID(ctx); + + ctx->zd_ns_info.ns_id = nsid; +} + +ns_id_t dplane_ctx_get_ns_id(const struct zebra_dplane_ctx *ctx) +{ + DPLANE_CTX_VALID(ctx); + + return ctx->zd_ns_info.ns_id; +} + bool dplane_ctx_is_from_notif(const struct zebra_dplane_ctx *ctx) { DPLANE_CTX_VALID(ctx); @@ -1154,6 +1197,13 @@ ifindex_t dplane_ctx_get_ifindex(const struct zebra_dplane_ctx *ctx) return ctx->zd_ifindex; } +void dplane_ctx_set_ifindex(struct zebra_dplane_ctx *ctx, ifindex_t ifindex) +{ + DPLANE_CTX_VALID(ctx); + + ctx->zd_ifindex = ifindex; +} + void dplane_ctx_set_type(struct zebra_dplane_ctx *ctx, int type) { DPLANE_CTX_VALID(ctx); @@ -1512,15 +1562,14 @@ const struct nhlfe_list_head *dplane_ctx_get_backup_nhlfe_list( return &(ctx->u.lsp.backup_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, - const union g_addr *gate, - ifindex_t ifindex, - uint8_t num_labels, - mpls_label_t *out_labels) +struct zebra_nhlfe *dplane_ctx_add_nhlfe(struct zebra_dplane_ctx *ctx, + enum lsp_types_t lsp_type, + enum nexthop_types_t nh_type, + const union g_addr *gate, + ifindex_t ifindex, uint8_t num_labels, + mpls_label_t *out_labels) { - zebra_nhlfe_t *nhlfe; + struct zebra_nhlfe *nhlfe; DPLANE_CTX_VALID(ctx); @@ -1531,15 +1580,12 @@ zebra_nhlfe_t *dplane_ctx_add_nhlfe(struct zebra_dplane_ctx *ctx, return nhlfe; } -zebra_nhlfe_t *dplane_ctx_add_backup_nhlfe(struct zebra_dplane_ctx *ctx, - enum lsp_types_t lsp_type, - enum nexthop_types_t nh_type, - const union g_addr *gate, - ifindex_t ifindex, - uint8_t num_labels, - mpls_label_t *out_labels) +struct zebra_nhlfe *dplane_ctx_add_backup_nhlfe( + struct zebra_dplane_ctx *ctx, enum lsp_types_t lsp_type, + enum nexthop_types_t nh_type, const union g_addr *gate, + ifindex_t ifindex, uint8_t num_labels, mpls_label_t *out_labels) { - zebra_nhlfe_t *nhlfe; + struct zebra_nhlfe *nhlfe; DPLANE_CTX_VALID(ctx); @@ -1551,7 +1597,7 @@ zebra_nhlfe_t *dplane_ctx_add_backup_nhlfe(struct zebra_dplane_ctx *ctx, return nhlfe; } -const zebra_nhlfe_t * +const struct zebra_nhlfe * dplane_ctx_get_best_nhlfe(const struct zebra_dplane_ctx *ctx) { DPLANE_CTX_VALID(ctx); @@ -1559,9 +1605,9 @@ dplane_ctx_get_best_nhlfe(const struct zebra_dplane_ctx *ctx) return ctx->u.lsp.best_nhlfe; } -const zebra_nhlfe_t * +const struct zebra_nhlfe * dplane_ctx_set_best_nhlfe(struct zebra_dplane_ctx *ctx, - zebra_nhlfe_t *nhlfe) + struct zebra_nhlfe *nhlfe) { DPLANE_CTX_VALID(ctx); @@ -1673,6 +1719,13 @@ uint32_t dplane_ctx_get_intf_metric(const struct zebra_dplane_ctx *ctx) return ctx->u.intf.metric; } +void dplane_ctx_set_intf_metric(struct zebra_dplane_ctx *ctx, uint32_t metric) +{ + DPLANE_CTX_VALID(ctx); + + ctx->u.intf.metric = metric; +} + /* Is interface addr p2p? */ bool dplane_ctx_intf_is_connected(const struct zebra_dplane_ctx *ctx) { @@ -1695,6 +1748,27 @@ bool dplane_ctx_intf_is_broadcast(const struct zebra_dplane_ctx *ctx) return (ctx->u.intf.flags & DPLANE_INTF_BROADCAST); } +void dplane_ctx_intf_set_connected(struct zebra_dplane_ctx *ctx) +{ + DPLANE_CTX_VALID(ctx); + + ctx->u.intf.flags |= DPLANE_INTF_CONNECTED; +} + +void dplane_ctx_intf_set_secondary(struct zebra_dplane_ctx *ctx) +{ + DPLANE_CTX_VALID(ctx); + + ctx->u.intf.flags |= DPLANE_INTF_SECONDARY; +} + +void dplane_ctx_intf_set_broadcast(struct zebra_dplane_ctx *ctx) +{ + DPLANE_CTX_VALID(ctx); + + ctx->u.intf.flags |= DPLANE_INTF_BROADCAST; +} + const struct prefix *dplane_ctx_get_intf_addr( const struct zebra_dplane_ctx *ctx) { @@ -1703,6 +1777,14 @@ const struct prefix *dplane_ctx_get_intf_addr( return &(ctx->u.intf.prefix); } +void dplane_ctx_set_intf_addr(struct zebra_dplane_ctx *ctx, + const struct prefix *p) +{ + DPLANE_CTX_VALID(ctx); + + prefix_copy(&(ctx->u.intf.prefix), p); +} + bool dplane_ctx_intf_has_dest(const struct zebra_dplane_ctx *ctx) { DPLANE_CTX_VALID(ctx); @@ -1715,10 +1797,15 @@ const struct prefix *dplane_ctx_get_intf_dest( { DPLANE_CTX_VALID(ctx); - if (ctx->u.intf.flags & DPLANE_INTF_HAS_DEST) - return &(ctx->u.intf.dest_prefix); - else - return NULL; + return &(ctx->u.intf.dest_prefix); +} + +void dplane_ctx_set_intf_dest(struct zebra_dplane_ctx *ctx, + const struct prefix *p) +{ + DPLANE_CTX_VALID(ctx); + + prefix_copy(&(ctx->u.intf.dest_prefix), p); } bool dplane_ctx_intf_has_label(const struct zebra_dplane_ctx *ctx) @@ -1735,6 +1822,35 @@ const char *dplane_ctx_get_intf_label(const struct zebra_dplane_ctx *ctx) return ctx->u.intf.label; } +void dplane_ctx_set_intf_label(struct zebra_dplane_ctx *ctx, const char *label) +{ + size_t len; + + DPLANE_CTX_VALID(ctx); + + if (ctx->u.intf.label && ctx->u.intf.label != ctx->u.intf.label_buf) + free(ctx->u.intf.label); + + ctx->u.intf.label = NULL; + + if (label) { + ctx->u.intf.flags |= DPLANE_INTF_HAS_LABEL; + + /* Use embedded buffer if it's adequate; else allocate. */ + len = strlen(label); + + if (len < sizeof(ctx->u.intf.label_buf)) { + strlcpy(ctx->u.intf.label_buf, label, + sizeof(ctx->u.intf.label_buf)); + ctx->u.intf.label = ctx->u.intf.label_buf; + } else { + ctx->u.intf.label = strdup(label); + } + } else { + ctx->u.intf.flags &= ~DPLANE_INTF_HAS_LABEL; + } +} + /* Accessors for MAC information */ vlanid_t dplane_ctx_mac_get_vlan(const struct zebra_dplane_ctx *ctx) { @@ -2181,9 +2297,9 @@ static int dplane_ctx_ns_init(struct zebra_dplane_ctx *ctx, * two messages in some 'update' cases. */ if (is_update) - zns->netlink_dplane.seq += 2; + zns->netlink_dplane_out.seq += 2; else - zns->netlink_dplane.seq++; + zns->netlink_dplane_out.seq++; #endif /* HAVE_NETLINK */ return AOK; @@ -2202,7 +2318,7 @@ int dplane_ctx_route_init(struct zebra_dplane_ctx *ctx, enum dplane_op_e op, struct zebra_ns *zns; struct zebra_vrf *zvrf; struct nexthop *nexthop; - zebra_l3vni_t *zl3vni; + struct zebra_l3vni *zl3vni; const struct interface *ifp; struct dplane_intf_extra *if_extra; @@ -2404,10 +2520,10 @@ done: * Capture information for an LSP update in a dplane context. */ int dplane_ctx_lsp_init(struct zebra_dplane_ctx *ctx, enum dplane_op_e op, - zebra_lsp_t *lsp) + struct zebra_lsp *lsp) { int ret = AOK; - zebra_nhlfe_t *nhlfe, *new_nhlfe; + struct zebra_nhlfe *nhlfe, *new_nhlfe; ctx->zd_op = op; ctx->zd_status = ZEBRA_DPLANE_REQUEST_SUCCESS; @@ -3227,7 +3343,7 @@ enum zebra_dplane_result dplane_nexthop_delete(struct nhg_hash_entry *nhe) /* * Enqueue LSP add for the dataplane. */ -enum zebra_dplane_result dplane_lsp_add(zebra_lsp_t *lsp) +enum zebra_dplane_result dplane_lsp_add(struct zebra_lsp *lsp) { enum zebra_dplane_result ret = lsp_update_internal(lsp, DPLANE_OP_LSP_INSTALL); @@ -3238,7 +3354,7 @@ enum zebra_dplane_result dplane_lsp_add(zebra_lsp_t *lsp) /* * Enqueue LSP update for the dataplane. */ -enum zebra_dplane_result dplane_lsp_update(zebra_lsp_t *lsp) +enum zebra_dplane_result dplane_lsp_update(struct zebra_lsp *lsp) { enum zebra_dplane_result ret = lsp_update_internal(lsp, DPLANE_OP_LSP_UPDATE); @@ -3249,7 +3365,7 @@ enum zebra_dplane_result dplane_lsp_update(zebra_lsp_t *lsp) /* * Enqueue LSP delete for the dataplane. */ -enum zebra_dplane_result dplane_lsp_delete(zebra_lsp_t *lsp) +enum zebra_dplane_result dplane_lsp_delete(struct zebra_lsp *lsp) { enum zebra_dplane_result ret = lsp_update_internal(lsp, DPLANE_OP_LSP_DELETE); @@ -3259,15 +3375,14 @@ enum zebra_dplane_result dplane_lsp_delete(zebra_lsp_t *lsp) /* 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, +dplane_lsp_notif_update(struct zebra_lsp *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; struct nhlfe_list_head *head; - zebra_nhlfe_t *nhlfe, *new_nhlfe; + struct zebra_nhlfe *nhlfe, *new_nhlfe; /* Obtain context block */ ctx = dplane_ctx_alloc(); @@ -3339,7 +3454,7 @@ enum zebra_dplane_result dplane_pw_uninstall(struct zebra_pw *pw) /* * Common internal LSP update utility */ -static enum zebra_dplane_result lsp_update_internal(zebra_lsp_t *lsp, +static enum zebra_dplane_result lsp_update_internal(struct zebra_lsp *lsp, enum dplane_op_e op) { enum zebra_dplane_result result = ZEBRA_DPLANE_REQUEST_FAILURE; @@ -4714,10 +4829,92 @@ static void dplane_info_from_zns(struct zebra_dplane_info *ns_info, #if defined(HAVE_NETLINK) ns_info->is_cmd = true; - ns_info->nls = zns->netlink_dplane; + ns_info->nls = zns->netlink_dplane_out; #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) +{ + struct dplane_zns_info *zi = THREAD_ARG(event); + + kernel_dplane_read(&zi->info); + + /* Re-start read task */ + thread_add_read(zdplane_info.dg_master, dplane_incoming_read, zi, + zi->info.nls.sock, &zi->t_read); + + return 0; +} +#endif /* HAVE_NETLINK */ + +/* + * Notify dplane when namespaces are enabled and disabled. The dplane + * needs to start and stop reading incoming events from the zns. In the + * common case where vrfs are _not_ namespaces, there will only be one + * of these. + * + * This is called in the main pthread. + */ +void zebra_dplane_ns_enable(struct zebra_ns *zns, bool enabled) +{ + struct dplane_zns_info *zi; + + if (IS_ZEBRA_DEBUG_DPLANE) + zlog_debug("%s: %s for nsid %u", __func__, + (enabled ? "ENABLED" : "DISABLED"), zns->ns_id); + + /* Search for an existing zns info entry */ + frr_each (zns_info_list, &zdplane_info.dg_zns_list, zi) { + if (zi->info.ns_id == zns->ns_id) + break; + } + + if (enabled) { + /* Create a new entry if necessary; start reading. */ + if (zi == NULL) { + zi = XCALLOC(MTYPE_DP_NS, sizeof(*zi)); + + zi->info.ns_id = zns->ns_id; + + zns_info_list_add_tail(&zdplane_info.dg_zns_list, zi); + + if (IS_ZEBRA_DEBUG_DPLANE) + zlog_debug("%s: nsid %u, new zi %p", __func__, + zns->ns_id, zi); + } + + /* Make sure we're up-to-date with the zns object */ +#if defined(HAVE_NETLINK) + zi->info.is_cmd = false; + zi->info.nls = zns->netlink_dplane_in; + + /* 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.nls.sock, &zi->t_read); +#endif + } else if (zi) { + if (IS_ZEBRA_DEBUG_DPLANE) + zlog_debug("%s: nsid %u, deleting zi %p", __func__, + zns->ns_id, zi); + + /* Stop reading, free memory */ + zns_info_list_del(&zdplane_info.dg_zns_list, zi); + + if (zdplane_info.dg_master) + thread_cancel_async(zdplane_info.dg_master, &zi->t_read, + NULL); + + XFREE(MTYPE_DP_NS, zi); + } +} + /* * Provider api to signal that work/events are available * for the dataplane pthread. @@ -4883,6 +5080,14 @@ static void kernel_dplane_log_detail(struct zebra_dplane_ctx *ctx) dplane_ctx_get_ifname(ctx), ctx->u.gre.link_ifindex); break; + + case DPLANE_OP_INTF_ADDR_ADD: + case DPLANE_OP_INTF_ADDR_DEL: + zlog_debug("Dplane incoming op %s, intf %s, addr %pFX", + dplane_op2str(dplane_ctx_get_op(ctx)), + dplane_ctx_get_ifname(ctx), + dplane_ctx_get_intf_addr(ctx)); + break; } } @@ -5025,6 +5230,11 @@ static void kernel_dplane_handle_result(struct zebra_dplane_ctx *ctx) case DPLANE_OP_BR_PORT_UPDATE: break; + /* TODO -- error counters for incoming events? */ + case DPLANE_OP_INTF_ADDR_ADD: + case DPLANE_OP_INTF_ADDR_DEL: + break; + case DPLANE_OP_NONE: if (res != ZEBRA_DPLANE_REQUEST_SUCCESS) atomic_fetch_add_explicit(&zdplane_info.dg_other_errors, @@ -5360,9 +5570,21 @@ done: */ static int dplane_check_shutdown_status(struct thread *event) { + struct dplane_zns_info *zi; + if (IS_ZEBRA_DEBUG_DPLANE) zlog_debug("Zebra dataplane shutdown status check called"); + /* Remove any zns info entries as we stop the dplane pthread. */ + 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) + thread_cancel(&zi->t_read); + + XFREE(MTYPE_DP_NS, zi); + } + if (dplane_work_pending()) { /* Reschedule dplane check on a short timer */ thread_add_timer_msec(zdplane_info.dg_master, @@ -5657,6 +5879,7 @@ static void zebra_dplane_init_internal(void) TAILQ_INIT(&zdplane_info.dg_update_ctx_q); TAILQ_INIT(&zdplane_info.dg_providers_q); + zns_info_list_init(&zdplane_info.dg_zns_list); zdplane_info.dg_updates_per_cycle = DPLANE_DEFAULT_NEW_WORK; @@ -5672,6 +5895,7 @@ static void zebra_dplane_init_internal(void) */ void zebra_dplane_start(void) { + struct dplane_zns_info *zi; struct zebra_dplane_provider *prov; struct frr_pthread_attr pattr = { .start = frr_pthread_attr_default.start, @@ -5691,6 +5915,14 @@ 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 */ + 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.nls.sock, &zi->t_read); +#endif + } + /* Call start callbacks for registered providers */ DPLANE_LOCK(); |
