diff options
| -rw-r--r-- | ldpd/labelmapping.c | 4 | ||||
| -rw-r--r-- | zebra/rt.h | 20 | ||||
| -rw-r--r-- | zebra/rt_netlink.c | 52 | ||||
| -rw-r--r-- | zebra/rt_netlink.h | 4 | ||||
| -rw-r--r-- | zebra/rt_socket.c | 13 | ||||
| -rw-r--r-- | zebra/zapi_msg.c | 3 | ||||
| -rw-r--r-- | zebra/zebra_dplane.c | 562 | ||||
| -rw-r--r-- | zebra/zebra_dplane.h | 23 | ||||
| -rw-r--r-- | zebra/zebra_mpls.c | 167 | ||||
| -rw-r--r-- | zebra/zebra_mpls.h | 19 | ||||
| -rw-r--r-- | zebra/zebra_mpls_netlink.c | 89 | ||||
| -rw-r--r-- | zebra/zebra_mpls_null.c | 20 | ||||
| -rw-r--r-- | zebra/zebra_mpls_openbsd.c | 87 | ||||
| -rw-r--r-- | zebra/zebra_rib.c | 40 | ||||
| -rw-r--r-- | zebra/zebra_rnh.c | 123 | ||||
| -rw-r--r-- | zebra/zebra_rnh.h | 4 | ||||
| -rw-r--r-- | zebra/zebra_routemap.c | 16 | ||||
| -rw-r--r-- | zebra/zebra_routemap.h | 2 | ||||
| -rw-r--r-- | zebra/zebra_vrf.h | 4 | ||||
| -rw-r--r-- | zebra/zebra_vty.c | 105 |
20 files changed, 840 insertions, 517 deletions
diff --git a/ldpd/labelmapping.c b/ldpd/labelmapping.c index 944f93331f..5e1b422a41 100644 --- a/ldpd/labelmapping.c +++ b/ldpd/labelmapping.c @@ -37,7 +37,7 @@ enqueue_pdu(struct nbr *nbr, uint16_t type, struct ibuf *buf, uint16_t size) struct ldp_hdr *ldp_hdr; ldp_hdr = ibuf_seek(buf, 0, sizeof(struct ldp_hdr)); - ldp_hdr->length = htons(size); + ldp_hdr->length = htons(size - LDP_HDR_DEAD_LEN); evbuf_enqueue(&nbr->tcp->wbuf, buf); } @@ -65,7 +65,7 @@ send_labelmessage(struct nbr *nbr, uint16_t type, struct mapping_head *mh) /* real size will be set up later */ err |= gen_ldp_hdr(buf, 0); - size = LDP_HDR_PDU_LEN; + size = LDP_HDR_SIZE; first = 0; } diff --git a/zebra/rt.h b/zebra/rt.h index 0317dc85ba..f2b531400f 100644 --- a/zebra/rt.h +++ b/zebra/rt.h @@ -32,12 +32,15 @@ #include "zebra/zebra_dplane.h" /* - * Update or delete a prefix from the kernel, + * Update or delete a route or LSP from the kernel, * using info from a dataplane context. */ extern enum zebra_dplane_result kernel_route_update( struct zebra_dplane_ctx *ctx); +extern enum zebra_dplane_result kernel_lsp_update( + struct zebra_dplane_ctx *ctx); + extern int kernel_address_add_ipv4(struct interface *, struct connected *); extern int kernel_address_delete_ipv4(struct interface *, struct connected *); extern int kernel_address_add_ipv6(struct interface *, struct connected *); @@ -47,21 +50,6 @@ extern int kernel_neigh_update(int cmd, int ifindex, uint32_t addr, char *lla, extern int kernel_interface_set_master(struct interface *master, struct interface *slave); -extern enum zebra_dplane_result kernel_add_lsp(zebra_lsp_t *lsp); -extern enum zebra_dplane_result kernel_upd_lsp(zebra_lsp_t *lsp); -extern enum zebra_dplane_result kernel_del_lsp(zebra_lsp_t *lsp); - -/* - * Add the ability to pass back up the lsp install/delete - * success/failure. - * - * This functions goal is similiar to kernel_route_rib_pass_fail - * in that we are separating out the mechanics for - * the install/failure to set/unset flags and to notify - * as needed. - */ -extern void kernel_lsp_pass_fail(zebra_lsp_t *lsp, enum zebra_dplane_status res); - extern int mpls_kernel_init(void); extern uint32_t kernel_get_speed(struct interface *ifp); diff --git a/zebra/rt_netlink.c b/zebra/rt_netlink.c index ae4bc52727..45bc3b3ba0 100644 --- a/zebra/rt_netlink.c +++ b/zebra/rt_netlink.c @@ -2616,16 +2616,16 @@ int kernel_del_neigh(struct interface *ifp, struct ipaddr *ip) } /* - * MPLS label forwarding table change via netlink interface. + * MPLS label forwarding table change via netlink interface, using dataplane + * context information. */ -int netlink_mpls_multipath(int cmd, zebra_lsp_t *lsp) +int netlink_mpls_multipath(int cmd, struct zebra_dplane_ctx *ctx) { mpls_lse_t lse; zebra_nhlfe_t *nhlfe; struct nexthop *nexthop = NULL; unsigned int nexthop_num; const char *routedesc; - struct zebra_ns *zns = zebra_ns_lookup(NS_DEFAULT); int route_type; struct { @@ -2634,14 +2634,14 @@ int netlink_mpls_multipath(int cmd, zebra_lsp_t *lsp) char buf[NL_PKT_BUF_SIZE]; } req; - memset(&req, 0, sizeof req - NL_PKT_BUF_SIZE); + memset(&req, 0, sizeof(req) - NL_PKT_BUF_SIZE); /* * Count # nexthops so we can decide whether to use singlepath * or multipath case. */ nexthop_num = 0; - for (nhlfe = lsp->nhlfe_list; nhlfe; nhlfe = nhlfe->next) { + for (nhlfe = dplane_ctx_get_nhlfe(ctx); nhlfe; nhlfe = nhlfe->next) { nexthop = nhlfe->nexthop; if (!nexthop) continue; @@ -2650,8 +2650,7 @@ int netlink_mpls_multipath(int cmd, zebra_lsp_t *lsp) if (CHECK_FLAG(nhlfe->flags, NHLFE_FLAG_SELECTED) && CHECK_FLAG(nexthop->flags, NEXTHOP_FLAG_ACTIVE)) nexthop_num++; - } else /* DEL */ - { + } else { /* DEL */ /* Count all installed NHLFEs */ if (CHECK_FLAG(nhlfe->flags, NHLFE_FLAG_INSTALLED) && CHECK_FLAG(nexthop->flags, NEXTHOP_FLAG_FIB)) @@ -2659,13 +2658,14 @@ int netlink_mpls_multipath(int cmd, zebra_lsp_t *lsp) } } - if ((nexthop_num == 0) || (!lsp->best_nhlfe && (cmd != RTM_DELROUTE))) + if ((nexthop_num == 0) || + (!dplane_ctx_get_best_nhlfe(ctx) && (cmd != RTM_DELROUTE))) return 0; req.n.nlmsg_len = NLMSG_LENGTH(sizeof(struct rtmsg)); req.n.nlmsg_flags = NLM_F_CREATE | NLM_F_REQUEST; req.n.nlmsg_type = cmd; - req.n.nlmsg_pid = zns->netlink_cmd.snl.nl_pid; + req.n.nlmsg_pid = dplane_ctx_get_ns(ctx)->nls.snl.nl_pid; req.r.rtm_family = AF_MPLS; req.r.rtm_table = RT_TABLE_MAIN; @@ -2678,23 +2678,26 @@ int netlink_mpls_multipath(int cmd, zebra_lsp_t *lsp) req.n.nlmsg_flags |= NLM_F_REPLACE; /* set the protocol value if installing */ - route_type = re_type_from_lsp_type(lsp->best_nhlfe->type); + route_type = re_type_from_lsp_type( + dplane_ctx_get_best_nhlfe(ctx)->type); req.r.rtm_protocol = zebra2proto(route_type); } /* Fill destination */ - lse = mpls_lse_encode(lsp->ile.in_label, 0, 0, 1); - addattr_l(&req.n, sizeof req, RTA_DST, &lse, sizeof(mpls_lse_t)); + lse = mpls_lse_encode(dplane_ctx_get_in_label(ctx), 0, 0, 1); + addattr_l(&req.n, sizeof(req), RTA_DST, &lse, sizeof(mpls_lse_t)); /* Fill nexthops (paths) based on single-path or multipath. The paths * chosen depend on the operation. */ if (nexthop_num == 1) { routedesc = "single-path"; - _netlink_mpls_debug(cmd, lsp->ile.in_label, routedesc); + _netlink_mpls_debug(cmd, dplane_ctx_get_in_label(ctx), + routedesc); nexthop_num = 0; - for (nhlfe = lsp->nhlfe_list; nhlfe; nhlfe = nhlfe->next) { + for (nhlfe = dplane_ctx_get_nhlfe(ctx); + nhlfe; nhlfe = nhlfe->next) { nexthop = nhlfe->nexthop; if (!nexthop) continue; @@ -2709,15 +2712,16 @@ int netlink_mpls_multipath(int cmd, zebra_lsp_t *lsp) && CHECK_FLAG(nexthop->flags, NEXTHOP_FLAG_FIB)))) { /* Add the gateway */ - _netlink_mpls_build_singlepath(routedesc, nhlfe, - &req.n, &req.r, - sizeof req, cmd); + _netlink_mpls_build_singlepath( + routedesc, nhlfe, + &req.n, &req.r, + sizeof(req), cmd); + nexthop_num++; break; } } - } else /* Multipath case */ - { + } else { /* Multipath case */ char buf[NL_PKT_BUF_SIZE]; struct rtattr *rta = (void *)buf; struct rtnexthop *rtnh; @@ -2728,10 +2732,12 @@ int netlink_mpls_multipath(int cmd, zebra_lsp_t *lsp) rtnh = RTA_DATA(rta); routedesc = "multipath"; - _netlink_mpls_debug(cmd, lsp->ile.in_label, routedesc); + _netlink_mpls_debug(cmd, dplane_ctx_get_in_label(ctx), + routedesc); nexthop_num = 0; - for (nhlfe = lsp->nhlfe_list; nhlfe; nhlfe = nhlfe->next) { + for (nhlfe = dplane_ctx_get_nhlfe(ctx); + nhlfe; nhlfe = nhlfe->next) { nexthop = nhlfe->nexthop; if (!nexthop) continue; @@ -2762,7 +2768,7 @@ int netlink_mpls_multipath(int cmd, zebra_lsp_t *lsp) } /* Talk to netlink socket. */ - return netlink_talk(netlink_talk_filter, &req.n, &zns->netlink_cmd, zns, - 0); + return netlink_talk_info(netlink_talk_filter, &req.n, + dplane_ctx_get_ns(ctx), 0); } #endif /* HAVE_NETLINK */ diff --git a/zebra/rt_netlink.h b/zebra/rt_netlink.h index cefd1996a9..914a0b5d71 100644 --- a/zebra/rt_netlink.h +++ b/zebra/rt_netlink.h @@ -24,6 +24,7 @@ #ifdef HAVE_NETLINK #include "zebra/zebra_mpls.h" +#include "zebra/zebra_dplane.h" #define NL_DEFAULT_ROUTE_METRIC 20 @@ -58,7 +59,8 @@ void rt_netlink_init(void); -extern int netlink_mpls_multipath(int cmd, zebra_lsp_t *lsp); +/* MPLS label forwarding table change, using dataplane context information. */ +extern int netlink_mpls_multipath(int cmd, struct zebra_dplane_ctx *ctx); extern int netlink_route_change(struct nlmsghdr *h, ns_id_t ns_id, int startup); extern int netlink_route_read(struct zebra_ns *zns); diff --git a/zebra/rt_socket.c b/zebra/rt_socket.c index 7dc5ef8b66..abcff22b6b 100644 --- a/zebra/rt_socket.c +++ b/zebra/rt_socket.c @@ -84,8 +84,7 @@ static int kernel_rtm(int cmd, const struct prefix *p, char prefix_buf[PREFIX_STRLEN]; enum blackhole_type bh_type = BLACKHOLE_UNSPEC; - if (IS_ZEBRA_DEBUG_RIB || IS_ZEBRA_DEBUG_KERNEL) - prefix2str(p, prefix_buf, sizeof(prefix_buf)); + prefix2str(p, prefix_buf, sizeof(prefix_buf)); /* * We only have the ability to ADD or DELETE at this point @@ -214,10 +213,12 @@ static int kernel_rtm(int cmd, const struct prefix *p, } #ifdef __OpenBSD__ - if (nexthop->nh_label - && !kernel_rtm_add_labels(nexthop->nh_label, &smpls)) - continue; - smplsp = (union sockunion *)&smpls; + if (nexthop->nh_label) { + if (kernel_rtm_add_labels(nexthop->nh_label, + &smpls) != 0) + continue; + smplsp = (union sockunion *)&smpls; + } #endif error = rtm_write(cmd, &sin_dest, &sin_mask, gate ? &sin_gate : NULL, smplsp, diff --git a/zebra/zapi_msg.c b/zebra/zapi_msg.c index a119c5ab4b..b6d0948d35 100644 --- a/zebra/zapi_msg.c +++ b/zebra/zapi_msg.c @@ -1109,7 +1109,8 @@ static void zread_rnh_register(ZAPI_HANDLER_ARGS) zebra_add_rnh_client(rnh, client, type, zvrf_id(zvrf)); /* Anything not AF_INET/INET6 has been filtered out above */ if (!exist) - zebra_evaluate_rnh(zvrf, p.family, 1, type, &p); + zebra_evaluate_rnh(zvrf, family2afi(p.family), 1, type, + &p); } stream_failure: diff --git a/zebra/zebra_dplane.c b/zebra/zebra_dplane.c index feede21cd9..fc316dbcb6 100644 --- a/zebra/zebra_dplane.c +++ b/zebra/zebra_dplane.c @@ -62,49 +62,25 @@ const uint32_t DPLANE_DEFAULT_NEW_WORK = 100; #endif /* DPLANE_DEBUG */ /* - * The context block used to exchange info about route updates across - * the boundary between the zebra main context (and pthread) and the - * dataplane layer (and pthread). + * Route information captured for route updates. */ -struct zebra_dplane_ctx { - - /* Operation code */ - enum dplane_op_e zd_op; - - /* Status on return */ - enum zebra_dplane_result zd_status; - - /* Dplane provider id */ - uint32_t zd_provider; - - /* Flags - used by providers, e.g. */ - int zd_flags; - - /* TODO -- internal/sub-operation status? */ - enum zebra_dplane_result zd_remote_status; - enum zebra_dplane_result zd_kernel_status; +struct dplane_route_info { /* Dest and (optional) source prefixes */ struct prefix zd_dest; struct prefix zd_src; - bool zd_is_update; - - uint32_t zd_seq; - uint32_t zd_old_seq; - vrf_id_t zd_vrf_id; - uint32_t zd_table_id; + afi_t zd_afi; + safi_t zd_safi; int zd_type; int zd_old_type; - afi_t zd_afi; - safi_t zd_safi; - route_tag_t zd_tag; route_tag_t zd_old_tag; uint32_t zd_metric; uint32_t zd_old_metric; + uint16_t zd_instance; uint16_t zd_old_instance; @@ -114,9 +90,6 @@ struct zebra_dplane_ctx { uint32_t zd_mtu; uint32_t zd_nexthop_mtu; - /* Namespace info */ - struct zebra_dplane_info zd_ns_info; - /* Nexthops */ struct nexthop_group zd_ng; @@ -125,6 +98,48 @@ struct zebra_dplane_ctx { /* TODO -- use fixed array of nexthops, to avoid mallocs? */ +}; + +/* + * The context block used to exchange info about route updates across + * the boundary between the zebra main context (and pthread) and the + * dataplane layer (and pthread). + */ +struct zebra_dplane_ctx { + + /* Operation code */ + enum dplane_op_e zd_op; + + /* Status on return */ + enum zebra_dplane_result zd_status; + + /* Dplane provider id */ + uint32_t zd_provider; + + /* Flags - used by providers, e.g. */ + int zd_flags; + + bool zd_is_update; + + uint32_t zd_seq; + uint32_t zd_old_seq; + + /* TODO -- internal/sub-operation status? */ + enum zebra_dplane_result zd_remote_status; + enum zebra_dplane_result zd_kernel_status; + + vrf_id_t zd_vrf_id; + uint32_t zd_table_id; + + /* Support info for either route or LSP update */ + union { + struct dplane_route_info rinfo; + zebra_lsp_t lsp; + } u; + + /* Namespace info, used especially for netlink kernel communication */ + struct zebra_dplane_info zd_ns_info; + /* Embedded list linkage */ TAILQ_ENTRY(zebra_dplane_ctx) zd_q_entries; }; @@ -218,6 +233,13 @@ static struct zebra_dplane_globals { _Atomic uint32_t dg_routes_queued; _Atomic uint32_t dg_routes_queued_max; _Atomic uint32_t dg_route_errors; + _Atomic uint32_t dg_other_errors; + + _Atomic uint32_t dg_lsps_in; + _Atomic uint32_t dg_lsps_queued; + _Atomic uint32_t dg_lsps_queued_max; + _Atomic uint32_t dg_lsp_errors; + _Atomic uint32_t dg_update_yields; /* Dataplane pthread */ @@ -251,6 +273,8 @@ 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, + enum dplane_op_e op); /* * Public APIs @@ -282,27 +306,68 @@ static struct zebra_dplane_ctx *dplane_ctx_alloc(void) */ static void dplane_ctx_free(struct zebra_dplane_ctx **pctx) { - if (pctx) { - DPLANE_CTX_VALID(*pctx); + if (pctx == NULL) + return; - /* TODO -- just freeing memory, but would like to maintain - * a pool - */ + DPLANE_CTX_VALID(*pctx); - /* Free embedded nexthops */ - if ((*pctx)->zd_ng.nexthop) { + /* TODO -- just freeing memory, but would like to maintain + * a pool + */ + + /* Some internal allocations may need to be freed, depending on + * the type of info captured in the ctx. + */ + switch ((*pctx)->zd_op) { + case DPLANE_OP_ROUTE_INSTALL: + case DPLANE_OP_ROUTE_UPDATE: + case DPLANE_OP_ROUTE_DELETE: + + /* Free allocated nexthops */ + if ((*pctx)->u.rinfo.zd_ng.nexthop) { /* This deals with recursive nexthops too */ - nexthops_free((*pctx)->zd_ng.nexthop); + nexthops_free((*pctx)->u.rinfo.zd_ng.nexthop); + + (*pctx)->u.rinfo.zd_ng.nexthop = NULL; } - if ((*pctx)->zd_old_ng.nexthop) { + if ((*pctx)->u.rinfo.zd_old_ng.nexthop) { /* This deals with recursive nexthops too */ - nexthops_free((*pctx)->zd_old_ng.nexthop); + nexthops_free((*pctx)->u.rinfo.zd_old_ng.nexthop); + + (*pctx)->u.rinfo.zd_old_ng.nexthop = NULL; } - XFREE(MTYPE_DP_CTX, *pctx); - *pctx = NULL; + break; + + case DPLANE_OP_LSP_INSTALL: + case DPLANE_OP_LSP_UPDATE: + case DPLANE_OP_LSP_DELETE: + { + zebra_nhlfe_t *nhlfe, *next; + + /* Free allocated NHLFEs */ + for (nhlfe = (*pctx)->u.lsp.nhlfe_list; nhlfe; nhlfe = next) { + next = nhlfe->next; + + zebra_mpls_nhlfe_del(nhlfe); + } + + /* Clear pointers in lsp struct, in case we're cacheing + * free context structs. + */ + (*pctx)->u.lsp.nhlfe_list = NULL; + (*pctx)->u.lsp.best_nhlfe = NULL; + + break; + } + + case DPLANE_OP_NONE: + break; } + + XFREE(MTYPE_DP_CTX, *pctx); + *pctx = NULL; } /* @@ -414,6 +479,16 @@ const char *dplane_op2str(enum dplane_op_e op) ret = "ROUTE_DELETE"; break; + case DPLANE_OP_LSP_INSTALL: + ret = "LSP_INSTALL"; + break; + case DPLANE_OP_LSP_UPDATE: + ret = "LSP_UPDATE"; + break; + case DPLANE_OP_LSP_DELETE: + ret = "LSP_DELETE"; + break; + }; return ret; @@ -442,7 +517,7 @@ const struct prefix *dplane_ctx_get_dest(const struct zebra_dplane_ctx *ctx) { DPLANE_CTX_VALID(ctx); - return &(ctx->zd_dest); + return &(ctx->u.rinfo.zd_dest); } /* Source prefix is a little special - return NULL for "no src prefix" */ @@ -450,11 +525,11 @@ const struct prefix *dplane_ctx_get_src(const struct zebra_dplane_ctx *ctx) { DPLANE_CTX_VALID(ctx); - if (ctx->zd_src.prefixlen == 0 && - IN6_IS_ADDR_UNSPECIFIED(&(ctx->zd_src.u.prefix6))) { + if (ctx->u.rinfo.zd_src.prefixlen == 0 && + IN6_IS_ADDR_UNSPECIFIED(&(ctx->u.rinfo.zd_src.u.prefix6))) { return NULL; } else { - return &(ctx->zd_src); + return &(ctx->u.rinfo.zd_src); } } @@ -490,28 +565,28 @@ int dplane_ctx_get_type(const struct zebra_dplane_ctx *ctx) { DPLANE_CTX_VALID(ctx); - return ctx->zd_type; + return ctx->u.rinfo.zd_type; } int dplane_ctx_get_old_type(const struct zebra_dplane_ctx *ctx) { DPLANE_CTX_VALID(ctx); - return ctx->zd_old_type; + return ctx->u.rinfo.zd_old_type; } afi_t dplane_ctx_get_afi(const struct zebra_dplane_ctx *ctx) { DPLANE_CTX_VALID(ctx); - return ctx->zd_afi; + return ctx->u.rinfo.zd_afi; } safi_t dplane_ctx_get_safi(const struct zebra_dplane_ctx *ctx) { DPLANE_CTX_VALID(ctx); - return ctx->zd_safi; + return ctx->u.rinfo.zd_safi; } uint32_t dplane_ctx_get_table(const struct zebra_dplane_ctx *ctx) @@ -525,70 +600,70 @@ route_tag_t dplane_ctx_get_tag(const struct zebra_dplane_ctx *ctx) { DPLANE_CTX_VALID(ctx); - return ctx->zd_tag; + return ctx->u.rinfo.zd_tag; } route_tag_t dplane_ctx_get_old_tag(const struct zebra_dplane_ctx *ctx) { DPLANE_CTX_VALID(ctx); - return ctx->zd_old_tag; + return ctx->u.rinfo.zd_old_tag; } uint16_t dplane_ctx_get_instance(const struct zebra_dplane_ctx *ctx) { DPLANE_CTX_VALID(ctx); - return ctx->zd_instance; + return ctx->u.rinfo.zd_instance; } uint16_t dplane_ctx_get_old_instance(const struct zebra_dplane_ctx *ctx) { DPLANE_CTX_VALID(ctx); - return ctx->zd_old_instance; + return ctx->u.rinfo.zd_old_instance; } uint32_t dplane_ctx_get_metric(const struct zebra_dplane_ctx *ctx) { DPLANE_CTX_VALID(ctx); - return ctx->zd_metric; + return ctx->u.rinfo.zd_metric; } uint32_t dplane_ctx_get_old_metric(const struct zebra_dplane_ctx *ctx) { DPLANE_CTX_VALID(ctx); - return ctx->zd_old_metric; + return ctx->u.rinfo.zd_old_metric; } uint32_t dplane_ctx_get_mtu(const struct zebra_dplane_ctx *ctx) { DPLANE_CTX_VALID(ctx); - return ctx->zd_mtu; + return ctx->u.rinfo.zd_mtu; } uint32_t dplane_ctx_get_nh_mtu(const struct zebra_dplane_ctx *ctx) { DPLANE_CTX_VALID(ctx); - return ctx->zd_nexthop_mtu; + return ctx->u.rinfo.zd_nexthop_mtu; } uint8_t dplane_ctx_get_distance(const struct zebra_dplane_ctx *ctx) { DPLANE_CTX_VALID(ctx); - return ctx->zd_distance; + return ctx->u.rinfo.zd_distance; } uint8_t dplane_ctx_get_old_distance(const struct zebra_dplane_ctx *ctx) { DPLANE_CTX_VALID(ctx); - return ctx->zd_old_distance; + return ctx->u.rinfo.zd_old_distance; } const struct nexthop_group *dplane_ctx_get_ng( @@ -596,7 +671,7 @@ const struct nexthop_group *dplane_ctx_get_ng( { DPLANE_CTX_VALID(ctx); - return &(ctx->zd_ng); + return &(ctx->u.rinfo.zd_ng); } const struct nexthop_group *dplane_ctx_get_old_ng( @@ -604,7 +679,7 @@ const struct nexthop_group *dplane_ctx_get_old_ng( { DPLANE_CTX_VALID(ctx); - return &(ctx->zd_old_ng); + return &(ctx->u.rinfo.zd_old_ng); } const struct zebra_dplane_info *dplane_ctx_get_ns( @@ -615,6 +690,50 @@ const struct zebra_dplane_info *dplane_ctx_get_ns( return &(ctx->zd_ns_info); } +/* Accessors for LSP information */ + +mpls_label_t dplane_ctx_get_in_label(const struct zebra_dplane_ctx *ctx) +{ + DPLANE_CTX_VALID(ctx); + + return ctx->u.lsp.ile.in_label; +} + +uint8_t dplane_ctx_get_addr_family(const struct zebra_dplane_ctx *ctx) +{ + DPLANE_CTX_VALID(ctx); + + return ctx->u.lsp.addr_family; +} + +uint32_t dplane_ctx_get_lsp_flags(const struct zebra_dplane_ctx *ctx) +{ + DPLANE_CTX_VALID(ctx); + + return ctx->u.lsp.flags; +} + +zebra_nhlfe_t *dplane_ctx_get_nhlfe(struct zebra_dplane_ctx *ctx) +{ + DPLANE_CTX_VALID(ctx); + + return ctx->u.lsp.nhlfe_list; +} + +zebra_nhlfe_t *dplane_ctx_get_best_nhlfe(struct zebra_dplane_ctx *ctx) +{ + DPLANE_CTX_VALID(ctx); + + return ctx->u.lsp.best_nhlfe; +} + +uint32_t dplane_ctx_get_lsp_num_ecmp(const struct zebra_dplane_ctx *ctx) +{ + DPLANE_CTX_VALID(ctx); + + return ctx->u.lsp.num_ecmp; +} + /* * End of dplane context accessors */ @@ -652,6 +771,28 @@ uint32_t dplane_get_in_queue_len(void) } /* + * 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); + +#if defined(HAVE_NETLINK) + /* Increment message counter after copying to context struct - may need + * two messages in some 'update' cases. + */ + if (is_update) + zns->netlink_dplane.seq += 2; + else + zns->netlink_dplane.seq++; +#endif /* HAVE_NETLINK */ + + return AOK; +} + +/* * Initialize a context block for a route update from zebra data structs. */ static int dplane_ctx_route_init(struct zebra_dplane_ctx *ctx, @@ -673,61 +814,50 @@ static int dplane_ctx_route_init(struct zebra_dplane_ctx *ctx, ctx->zd_op = op; ctx->zd_status = ZEBRA_DPLANE_REQUEST_SUCCESS; - ctx->zd_type = re->type; - ctx->zd_old_type = re->type; + ctx->u.rinfo.zd_type = re->type; + ctx->u.rinfo.zd_old_type = re->type; /* Prefixes: dest, and optional source */ srcdest_rnode_prefixes(rn, &p, &src_p); - prefix_copy(&(ctx->zd_dest), p); + prefix_copy(&(ctx->u.rinfo.zd_dest), p); if (src_p) - prefix_copy(&(ctx->zd_src), src_p); + prefix_copy(&(ctx->u.rinfo.zd_src), src_p); else - memset(&(ctx->zd_src), 0, sizeof(ctx->zd_src)); + memset(&(ctx->u.rinfo.zd_src), 0, sizeof(ctx->u.rinfo.zd_src)); ctx->zd_table_id = re->table; - ctx->zd_metric = re->metric; - ctx->zd_old_metric = re->metric; + ctx->u.rinfo.zd_metric = re->metric; + ctx->u.rinfo.zd_old_metric = re->metric; ctx->zd_vrf_id = re->vrf_id; - ctx->zd_mtu = re->mtu; - ctx->zd_nexthop_mtu = re->nexthop_mtu; - ctx->zd_instance = re->instance; - ctx->zd_tag = re->tag; - ctx->zd_old_tag = re->tag; - ctx->zd_distance = re->distance; + ctx->u.rinfo.zd_mtu = re->mtu; + ctx->u.rinfo.zd_nexthop_mtu = re->nexthop_mtu; + ctx->u.rinfo.zd_instance = re->instance; + ctx->u.rinfo.zd_tag = re->tag; + ctx->u.rinfo.zd_old_tag = re->tag; + ctx->u.rinfo.zd_distance = re->distance; table = srcdest_rnode_table(rn); info = table->info; - ctx->zd_afi = info->afi; - ctx->zd_safi = info->safi; + ctx->u.rinfo.zd_afi = info->afi; + ctx->u.rinfo.zd_safi = info->safi; /* Extract ns info - can't use pointers to 'core' structs */ zvrf = vrf_info_lookup(re->vrf_id); zns = zvrf->zns; - /* Internal copy helper */ - dplane_info_from_zns(&(ctx->zd_ns_info), zns); - -#if defined(HAVE_NETLINK) - /* Increment message counter after copying to context struct - may need - * two messages in some 'update' cases. - */ - if (op == DPLANE_OP_ROUTE_UPDATE) - zns->netlink_dplane.seq += 2; - else - zns->netlink_dplane.seq++; -#endif /* NETLINK*/ + dplane_ctx_ns_init(ctx, zns, (op == DPLANE_OP_ROUTE_UPDATE)); /* Copy nexthops; recursive info is included too */ - copy_nexthops(&(ctx->zd_ng.nexthop), re->ng.nexthop, NULL); + copy_nexthops(&(ctx->u.rinfo.zd_ng.nexthop), re->ng.nexthop, NULL); /* TODO -- maybe use array of nexthops to avoid allocs? */ /* Ensure that the dplane's nexthops flags are clear. */ - for (ALL_NEXTHOPS(ctx->zd_ng, nexthop)) + for (ALL_NEXTHOPS(ctx->u.rinfo.zd_ng, nexthop)) UNSET_FLAG(nexthop->flags, NEXTHOP_FLAG_FIB); /* Trying out the sequence number idea, so we can try to detect @@ -743,15 +873,79 @@ done: } /* + * Capture information for an LSP update in a dplane context. + */ +static int dplane_ctx_lsp_init(struct zebra_dplane_ctx *ctx, + enum dplane_op_e op, + zebra_lsp_t *lsp) +{ + int ret = AOK; + zebra_nhlfe_t *nhlfe, *new_nhlfe; + + if (IS_ZEBRA_DEBUG_DPLANE_DETAIL) + zlog_debug("init dplane ctx %s: in-label %u ecmp# %d", + dplane_op2str(op), lsp->ile.in_label, + lsp->num_ecmp); + + ctx->zd_op = op; + ctx->zd_status = ZEBRA_DPLANE_REQUEST_SUCCESS; + + /* Capture namespace info */ + dplane_ctx_ns_init(ctx, zebra_ns_lookup(NS_DEFAULT), + (op == DPLANE_OP_LSP_UPDATE)); + + memset(&ctx->u.lsp, 0, sizeof(ctx->u.lsp)); + + ctx->u.lsp.ile = lsp->ile; + ctx->u.lsp.addr_family = lsp->addr_family; + ctx->u.lsp.num_ecmp = lsp->num_ecmp; + ctx->u.lsp.flags = lsp->flags; + + /* Copy source LSP's nhlfes, and capture 'best' nhlfe */ + for (nhlfe = lsp->nhlfe_list; nhlfe; nhlfe = nhlfe->next) { + /* Not sure if this is meaningful... */ + if (nhlfe->nexthop == NULL) + continue; + + new_nhlfe = + zebra_mpls_lsp_add_nhlfe( + &(ctx->u.lsp), + nhlfe->type, + nhlfe->nexthop->type, + &(nhlfe->nexthop->gate), + nhlfe->nexthop->ifindex, + nhlfe->nexthop->nh_label->label[0]); + + if (new_nhlfe == NULL || new_nhlfe->nexthop == NULL) { + ret = ENOMEM; + break; + } + + /* Need to copy flags too */ + new_nhlfe->flags = nhlfe->flags; + new_nhlfe->nexthop->flags = nhlfe->nexthop->flags; + + if (nhlfe == lsp->best_nhlfe) + ctx->u.lsp.best_nhlfe = new_nhlfe; + } + + /* On error the ctx will be cleaned-up, so we don't need to + * deal with any allocated nhlfe or nexthop structs here. + */ + + return ret; +} + +/* * Enqueue a new route update, - * and ensure an event is active for the dataplane thread. + * and ensure an event is active for the dataplane pthread. */ static int dplane_route_enqueue(struct zebra_dplane_ctx *ctx) { int ret = EINVAL; uint32_t high, curr; - /* Enqueue for processing by the dataplane thread */ + /* Enqueue for processing by the dataplane pthread */ DPLANE_LOCK(); { TAILQ_INSERT_TAIL(&zdplane_info.dg_route_ctx_q, ctx, @@ -821,17 +1015,17 @@ dplane_route_update_internal(struct route_node *rn, old_re->dplane_sequence++; ctx->zd_old_seq = old_re->dplane_sequence; - ctx->zd_old_tag = old_re->tag; - ctx->zd_old_type = old_re->type; - ctx->zd_old_instance = old_re->instance; - ctx->zd_old_distance = old_re->distance; - ctx->zd_old_metric = old_re->metric; + ctx->u.rinfo.zd_old_tag = old_re->tag; + ctx->u.rinfo.zd_old_type = old_re->type; + ctx->u.rinfo.zd_old_instance = old_re->instance; + ctx->u.rinfo.zd_old_distance = old_re->distance; + ctx->u.rinfo.zd_old_metric = old_re->metric; #ifndef HAVE_NETLINK /* For bsd, capture previous re's nexthops too, sigh. * We'll need these to do per-nexthop deletes. */ - copy_nexthops(&(ctx->zd_old_ng.nexthop), + copy_nexthops(&(ctx->u.rinfo.zd_old_ng.nexthop), old_re->ng.nexthop, NULL); #endif /* !HAVE_NETLINK */ } @@ -847,10 +1041,11 @@ done: if (ret == AOK) result = ZEBRA_DPLANE_REQUEST_QUEUED; - else if (ctx) { + else { atomic_fetch_add_explicit(&zdplane_info.dg_route_errors, 1, memory_order_relaxed); - dplane_ctx_free(&ctx); + if (ctx) + dplane_ctx_free(&ctx); } return result; @@ -911,11 +1106,85 @@ done: } /* + * Enqueue LSP add for the dataplane. + */ +enum zebra_dplane_result dplane_lsp_add(zebra_lsp_t *lsp) +{ + enum zebra_dplane_result ret = + lsp_update_internal(lsp, DPLANE_OP_LSP_INSTALL); + + return ret; +} + +/* + * Enqueue LSP update for the dataplane. + */ +enum zebra_dplane_result dplane_lsp_update(zebra_lsp_t *lsp) +{ + enum zebra_dplane_result ret = + lsp_update_internal(lsp, DPLANE_OP_LSP_UPDATE); + + return ret; +} + +/* + * Enqueue LSP delete for the dataplane. + */ +enum zebra_dplane_result dplane_lsp_delete(zebra_lsp_t *lsp) +{ + enum zebra_dplane_result ret = + lsp_update_internal(lsp, DPLANE_OP_LSP_DELETE); + + return ret; +} + +/* + * Common internal LSP update utility + */ +static enum zebra_dplane_result lsp_update_internal(zebra_lsp_t *lsp, + enum dplane_op_e op) +{ + 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; + + 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; +} + +/* * Handler for 'show dplane' */ int dplane_show_helper(struct vty *vty, bool detailed) { - uint64_t queued, queue_max, limit, errs, incoming, yields; + uint64_t queued, queue_max, limit, errs, incoming, yields, + other_errs; /* Using atomics because counters are being changed in different * pthread contexts. @@ -932,14 +1201,17 @@ int dplane_show_helper(struct vty *vty, bool detailed) memory_order_relaxed); yields = atomic_load_explicit(&zdplane_info.dg_update_yields, memory_order_relaxed); + other_errs = atomic_load_explicit(&zdplane_info.dg_other_errors, + memory_order_relaxed); vty_out(vty, "Zebra dataplane:\nRoute updates: %"PRIu64"\n", incoming); vty_out(vty, "Route update errors: %"PRIu64"\n", errs); + vty_out(vty, "Other errors : %"PRIu64"\n", other_errs); vty_out(vty, "Route update queue limit: %"PRIu64"\n", limit); vty_out(vty, "Route update queue depth: %"PRIu64"\n", queued); vty_out(vty, "Route update queue max: %"PRIu64"\n", queue_max); - vty_out(vty, "Route update yields: %"PRIu64"\n", yields); + vty_out(vty, "Dplane update yields: %"PRIu64"\n", yields); return CMD_SUCCESS; } @@ -1219,6 +1491,55 @@ int dplane_provider_work_ready(void) */ /* + * Handler for kernel LSP updates + */ +static enum zebra_dplane_result +kernel_dplane_lsp_update(struct zebra_dplane_ctx *ctx) +{ + enum zebra_dplane_result res; + + /* Call into the synchronous kernel-facing code here */ + res = kernel_lsp_update(ctx); + + if (res != ZEBRA_DPLANE_REQUEST_SUCCESS) + atomic_fetch_add_explicit( + &zdplane_info.dg_lsp_errors, 1, + memory_order_relaxed); + + return res; +} + +/* + * Handler for kernel route updates + */ +static enum zebra_dplane_result +kernel_dplane_route_update(struct zebra_dplane_ctx *ctx) +{ + enum zebra_dplane_result res; + + if (IS_ZEBRA_DEBUG_DPLANE_DETAIL) { + char dest_str[PREFIX_STRLEN]; + + prefix2str(dplane_ctx_get_dest(ctx), + dest_str, sizeof(dest_str)); + + zlog_debug("%u:%s Dplane route update ctx %p op %s", + dplane_ctx_get_vrf(ctx), dest_str, + ctx, dplane_op2str(dplane_ctx_get_op(ctx))); + } + + /* Call into the synchronous kernel-facing code here */ + res = kernel_route_update(ctx); + + if (res != ZEBRA_DPLANE_REQUEST_SUCCESS) + atomic_fetch_add_explicit( + &zdplane_info.dg_route_errors, 1, + memory_order_relaxed); + + return res; +} + +/* * Kernel provider callback */ static int kernel_dplane_process_func(struct zebra_dplane_provider *prov) @@ -1239,25 +1560,30 @@ static int kernel_dplane_process_func(struct zebra_dplane_provider *prov) if (ctx == NULL) break; - if (IS_ZEBRA_DEBUG_DPLANE_DETAIL) { - char dest_str[PREFIX_STRLEN]; - - prefix2str(dplane_ctx_get_dest(ctx), - dest_str, sizeof(dest_str)); + /* Dispatch to appropriate kernel-facing apis */ + switch (dplane_ctx_get_op(ctx)) { - zlog_debug("%u:%s Dplane route update ctx %p op %s", - dplane_ctx_get_vrf(ctx), dest_str, - ctx, dplane_op2str(dplane_ctx_get_op(ctx))); - } + case DPLANE_OP_ROUTE_INSTALL: + case DPLANE_OP_ROUTE_UPDATE: + case DPLANE_OP_ROUTE_DELETE: + res = kernel_dplane_route_update(ctx); + break; - /* Call into the synchronous kernel-facing code here */ - res = kernel_route_update(ctx); + case DPLANE_OP_LSP_INSTALL: + case DPLANE_OP_LSP_UPDATE: + case DPLANE_OP_LSP_DELETE: + res = kernel_dplane_lsp_update(ctx); + break; - if (res != ZEBRA_DPLANE_REQUEST_SUCCESS) + default: atomic_fetch_add_explicit( - &zdplane_info.dg_route_errors, 1, + &zdplane_info.dg_other_errors, 1, memory_order_relaxed); + res = ZEBRA_DPLANE_REQUEST_FAILURE; + break; + } + dplane_ctx_set_status(ctx, res); dplane_provider_enqueue_out_ctx(prov, ctx); diff --git a/zebra/zebra_dplane.h b/zebra/zebra_dplane.h index 1c053b85bf..562a8499a2 100644 --- a/zebra/zebra_dplane.h +++ b/zebra/zebra_dplane.h @@ -28,6 +28,7 @@ #include "zebra/zebra_ns.h" #include "zebra/rib.h" #include "zebra/zserv.h" +#include "zebra/zebra_mpls.h" /* Key netlink info from zebra ns */ struct zebra_dplane_info { @@ -101,6 +102,10 @@ enum dplane_op_e { DPLANE_OP_ROUTE_UPDATE, DPLANE_OP_ROUTE_DELETE, + /* LSP update */ + DPLANE_OP_LSP_INSTALL, + DPLANE_OP_LSP_UPDATE, + DPLANE_OP_LSP_DELETE }; /* @@ -167,6 +172,8 @@ bool dplane_ctx_is_update(const struct zebra_dplane_ctx *ctx); uint32_t dplane_ctx_get_seq(const struct zebra_dplane_ctx *ctx); uint32_t dplane_ctx_get_old_seq(const struct zebra_dplane_ctx *ctx); vrf_id_t dplane_ctx_get_vrf(const struct zebra_dplane_ctx *ctx); + +/* Accessors for route update information */ int dplane_ctx_get_type(const struct zebra_dplane_ctx *ctx); int dplane_ctx_get_old_type(const struct zebra_dplane_ctx *ctx); afi_t dplane_ctx_get_afi(const struct zebra_dplane_ctx *ctx); @@ -188,6 +195,15 @@ const struct nexthop_group *dplane_ctx_get_ng( const struct nexthop_group *dplane_ctx_get_old_ng( const struct zebra_dplane_ctx *ctx); +/* Accessors for LSP information */ +mpls_label_t dplane_ctx_get_in_label(const struct zebra_dplane_ctx *ctx); +uint8_t dplane_ctx_get_addr_family(const struct zebra_dplane_ctx *ctx); +uint32_t dplane_ctx_get_lsp_flags(const struct zebra_dplane_ctx *ctx); +zebra_nhlfe_t *dplane_ctx_get_nhlfe(struct zebra_dplane_ctx *ctx); +zebra_nhlfe_t *dplane_ctx_get_best_nhlfe(struct zebra_dplane_ctx *ctx); +uint32_t dplane_ctx_get_lsp_num_ecmp(const struct zebra_dplane_ctx *ctx); + +/* Namespace info - esp. for netlink communication */ const struct zebra_dplane_info *dplane_ctx_get_ns( const struct zebra_dplane_ctx *ctx); @@ -209,6 +225,13 @@ enum zebra_dplane_result dplane_route_update(struct route_node *rn, enum zebra_dplane_result dplane_route_delete(struct route_node *rn, struct route_entry *re); +/* + * Enqueue LSP change operations for the dataplane. + */ +enum zebra_dplane_result dplane_lsp_add(zebra_lsp_t *lsp); +enum zebra_dplane_result dplane_lsp_update(zebra_lsp_t *lsp); +enum zebra_dplane_result dplane_lsp_delete(zebra_lsp_t *lsp); + /* Retrieve the limit on the number of pending, unprocessed updates. */ uint32_t dplane_get_in_queue_limit(void); diff --git a/zebra/zebra_mpls.c b/zebra/zebra_mpls.c index c0764cd4b8..4ea7f32446 100644 --- a/zebra/zebra_mpls.c +++ b/zebra/zebra_mpls.c @@ -862,7 +862,7 @@ static void lsp_uninstall_from_kernel(struct hash_backet *backet, void *ctxt) lsp = (zebra_lsp_t *)backet->data; if (CHECK_FLAG(lsp->flags, LSP_FLAG_INSTALLED)) - (void)kernel_del_lsp(lsp); + (void)dplane_lsp_delete(lsp); } /* @@ -887,6 +887,7 @@ static wq_item_status lsp_process(struct work_queue *wq, void *data) zebra_nhlfe_t *oldbest, *newbest; char buf[BUFSIZ], buf2[BUFSIZ]; struct zebra_vrf *zvrf = vrf_info_lookup(VRF_DEFAULT); + enum zebra_dplane_result res; lsp = (zebra_lsp_t *)data; if (!lsp) // unexpected @@ -916,13 +917,20 @@ static wq_item_status lsp_process(struct work_queue *wq, void *data) if (newbest) { UNSET_FLAG(lsp->flags, LSP_FLAG_CHANGED); - switch (kernel_add_lsp(lsp)) { + + switch (dplane_lsp_add(lsp)) { case ZEBRA_DPLANE_REQUEST_QUEUED: - flog_err( - EC_ZEBRA_DP_INVALID_RC, - "No current DataPlane interfaces can return this, please fix"); + /* Set 'installed' flag so we will know + * that an install is in-flight. + */ + SET_FLAG(lsp->flags, LSP_FLAG_INSTALLED); + + zvrf->lsp_installs_queued++; break; case ZEBRA_DPLANE_REQUEST_FAILURE: + flog_warn(EC_ZEBRA_LSP_INSTALL_FAILURE, + "LSP Install Failure: %u", + lsp->ile.in_label); break; case ZEBRA_DPLANE_REQUEST_SUCCESS: zvrf->lsp_installs++; @@ -932,14 +940,22 @@ static wq_item_status lsp_process(struct work_queue *wq, void *data) } else { /* Installed, may need an update and/or delete. */ if (!newbest) { + res = dplane_lsp_delete(lsp); - switch (kernel_del_lsp(lsp)) { + /* We do some of the lsp cleanup immediately for + * deletes. + */ + UNSET_FLAG(lsp->flags, LSP_FLAG_INSTALLED); + clear_nhlfe_installed(lsp); + + switch (res) { case ZEBRA_DPLANE_REQUEST_QUEUED: - flog_err( - EC_ZEBRA_DP_INVALID_RC, - "No current DataPlane interfaces can return this, please fix"); + zvrf->lsp_removals_queued++; break; case ZEBRA_DPLANE_REQUEST_FAILURE: + flog_warn(EC_ZEBRA_LSP_DELETE_FAILURE, + "LSP Deletion Failure: %u", + lsp->ile.in_label); break; case ZEBRA_DPLANE_REQUEST_SUCCESS: zvrf->lsp_removals++; @@ -950,7 +966,10 @@ static wq_item_status lsp_process(struct work_queue *wq, void *data) struct nexthop *nexthop; UNSET_FLAG(lsp->flags, LSP_FLAG_CHANGED); - UNSET_FLAG(lsp->flags, LSP_FLAG_INSTALLED); + + /* We leave the INSTALLED flag set here + * so we know an update in in-flight. + */ /* * Any NHLFE that was installed but is not @@ -973,13 +992,14 @@ static wq_item_status lsp_process(struct work_queue *wq, void *data) } } - switch (kernel_upd_lsp(lsp)) { + switch (dplane_lsp_update(lsp)) { case ZEBRA_DPLANE_REQUEST_QUEUED: - flog_err( - EC_ZEBRA_DP_INVALID_RC, - "No current DataPlane interfaces can return this, please fix"); + zvrf->lsp_installs_queued++; break; case ZEBRA_DPLANE_REQUEST_FAILURE: + flog_warn(EC_ZEBRA_LSP_INSTALL_FAILURE, + "LSP Update Failure: %u", + lsp->ile.in_label); break; case ZEBRA_DPLANE_REQUEST_SUCCESS: zvrf->lsp_installs++; @@ -1716,43 +1736,85 @@ static int mpls_processq_init(struct zebra_t *zebra) /* Public functions */ -void kernel_lsp_pass_fail(zebra_lsp_t *lsp, enum zebra_dplane_status res) +/* + * Process LSP update results from zebra dataplane. + */ +void zebra_mpls_lsp_dplane_result(struct zebra_dplane_ctx *ctx) { - struct nexthop *nexthop; + struct zebra_vrf *zvrf; + zebra_ile_t tmp_ile; + struct hash *lsp_table; + zebra_lsp_t *lsp; zebra_nhlfe_t *nhlfe; + struct nexthop *nexthop; + enum dplane_op_e op; + enum zebra_dplane_status status; + + op = dplane_ctx_get_op(ctx); + status = dplane_ctx_get_status(ctx); + + if (IS_ZEBRA_DEBUG_DPLANE_DETAIL) + zlog_debug("LSP dplane ctx %p, op %s, in-label %u, result %s", + ctx, dplane_op2str(op), + dplane_ctx_get_in_label(ctx), + dplane_res2str(status)); + + switch (op) { + case DPLANE_OP_LSP_INSTALL: + case DPLANE_OP_LSP_UPDATE: + /* Look for zebra LSP object */ + zvrf = vrf_info_lookup(VRF_DEFAULT); + if (zvrf == NULL) + break; - if (!lsp) - return; + lsp_table = zvrf->lsp_table; - switch (res) { - case ZEBRA_DPLANE_INSTALL_FAILURE: - UNSET_FLAG(lsp->flags, LSP_FLAG_INSTALLED); - clear_nhlfe_installed(lsp); - flog_warn(EC_ZEBRA_LSP_INSTALL_FAILURE, - "LSP Install Failure: %u", lsp->ile.in_label); - break; - case ZEBRA_DPLANE_INSTALL_SUCCESS: - SET_FLAG(lsp->flags, LSP_FLAG_INSTALLED); - for (nhlfe = lsp->nhlfe_list; nhlfe; nhlfe = nhlfe->next) { - nexthop = nhlfe->nexthop; - if (!nexthop) - continue; + tmp_ile.in_label = dplane_ctx_get_in_label(ctx); + lsp = hash_lookup(lsp_table, &tmp_ile); + if (lsp == NULL) { + if (IS_ZEBRA_DEBUG_DPLANE) + zlog_debug("LSP ctx %p: in-label %u not found", + ctx, dplane_ctx_get_in_label(ctx)); + break; + } - SET_FLAG(nhlfe->flags, NHLFE_FLAG_INSTALLED); - SET_FLAG(nexthop->flags, NEXTHOP_FLAG_FIB); + /* TODO -- Confirm that this result is still 'current' */ + + if (dplane_ctx_get_status(ctx) == + ZEBRA_DPLANE_REQUEST_SUCCESS) { + /* Update zebra object */ + SET_FLAG(lsp->flags, LSP_FLAG_INSTALLED); + for (nhlfe = lsp->nhlfe_list; nhlfe; + nhlfe = nhlfe->next) { + nexthop = nhlfe->nexthop; + if (!nexthop) + continue; + + SET_FLAG(nhlfe->flags, NHLFE_FLAG_INSTALLED); + SET_FLAG(nexthop->flags, NEXTHOP_FLAG_FIB); + } + } else { + UNSET_FLAG(lsp->flags, LSP_FLAG_INSTALLED); + clear_nhlfe_installed(lsp); + flog_warn(EC_ZEBRA_LSP_INSTALL_FAILURE, + "LSP Install Failure: in-label %u", + lsp->ile.in_label); } + break; - case ZEBRA_DPLANE_DELETE_SUCCESS: - UNSET_FLAG(lsp->flags, LSP_FLAG_INSTALLED); - clear_nhlfe_installed(lsp); - break; - case ZEBRA_DPLANE_DELETE_FAILURE: + + case DPLANE_OP_LSP_DELETE: flog_warn(EC_ZEBRA_LSP_DELETE_FAILURE, - "LSP Deletion Failure: %u", lsp->ile.in_label); + "LSP Deletion Failure: in-label %u", + dplane_ctx_get_in_label(ctx)); break; - case ZEBRA_DPLANE_STATUS_NONE: + + default: break; - } + + } /* Switch */ + + dplane_ctx_fini(&ctx); } /* @@ -1808,6 +1870,29 @@ int zebra_mpls_lsp_uninstall(struct zebra_vrf *zvrf, struct route_node *rn, } /* + * Add an NHLFE to an LSP, return the newly-added object + */ +zebra_nhlfe_t *zebra_mpls_lsp_add_nhlfe(zebra_lsp_t *lsp, + enum lsp_types_t lsp_type, + enum nexthop_types_t gtype, + union g_addr *gate, + ifindex_t ifindex, + mpls_label_t out_label) +{ + /* Just a public pass-through to the internal implementation */ + return nhlfe_add(lsp, lsp_type, gtype, gate, ifindex, out_label); +} + +/* + * Free an allocated NHLFE + */ +void zebra_mpls_nhlfe_del(zebra_nhlfe_t *nhlfe) +{ + /* Just a pass-through to the internal implementation */ + nhlfe_del(nhlfe); +} + +/* * Registration from a client for the label binding for a FEC. If a binding * already exists, it is informed to the client. * NOTE: If there is a manually configured label binding, that is used. diff --git a/zebra/zebra_mpls.h b/zebra/zebra_mpls.h index c250fc4058..fb32adde31 100644 --- a/zebra/zebra_mpls.h +++ b/zebra/zebra_mpls.h @@ -191,6 +191,17 @@ int zebra_mpls_lsp_install(struct zebra_vrf *zvrf, struct route_node *rn, int zebra_mpls_lsp_uninstall(struct zebra_vrf *zvrf, struct route_node *rn, struct route_entry *re); +/* Add an NHLFE to an LSP, return the newly-added object */ +zebra_nhlfe_t *zebra_mpls_lsp_add_nhlfe(zebra_lsp_t *lsp, + enum lsp_types_t lsp_type, + enum nexthop_types_t gtype, + union g_addr *gate, + ifindex_t ifindex, + mpls_label_t out_label); + +/* Free an allocated NHLFE */ +void zebra_mpls_nhlfe_del(zebra_nhlfe_t *nhlfe); + int zebra_mpls_fec_register(struct zebra_vrf *zvrf, struct prefix *p, uint32_t label, uint32_t label_index, struct zserv *client); @@ -331,6 +342,14 @@ int zebra_mpls_static_lsp_del(struct zebra_vrf *zvrf, mpls_label_t in_label, ifindex_t ifindex); /* + * Process LSP update results from zebra dataplane. + */ +/* Forward ref of dplane update context type */ +struct zebra_dplane_ctx; + +void zebra_mpls_lsp_dplane_result(struct zebra_dplane_ctx *ctx); + +/* * Schedule all MPLS label forwarding entries for processing. * Called upon changes that may affect one or more of them such as * interface or nexthop state changes. diff --git a/zebra/zebra_mpls_netlink.c b/zebra/zebra_mpls_netlink.c index c4ab316d0b..d8b5ef4ce1 100644 --- a/zebra/zebra_mpls_netlink.c +++ b/zebra/zebra_mpls_netlink.c @@ -22,84 +22,43 @@ #ifdef HAVE_NETLINK +#include "zebra/debug.h" #include "zebra/rt.h" #include "zebra/rt_netlink.h" #include "zebra/zebra_mpls.h" /* - * Install Label Forwarding entry into the kernel. + * LSP forwarding update using dataplane context information. */ -enum zebra_dplane_result kernel_add_lsp(zebra_lsp_t *lsp) +enum zebra_dplane_result kernel_lsp_update(struct zebra_dplane_ctx *ctx) { - int ret; + int cmd, ret = -1; - if (!lsp || !lsp->best_nhlfe) { // unexpected - kernel_lsp_pass_fail(lsp, ZEBRA_DPLANE_INSTALL_FAILURE); - return ZEBRA_DPLANE_REQUEST_FAILURE; - } + /* Call to netlink layer based on type of update */ + if (dplane_ctx_get_op(ctx) == DPLANE_OP_LSP_DELETE) { + cmd = RTM_DELROUTE; + } else if (dplane_ctx_get_op(ctx) == DPLANE_OP_LSP_INSTALL || + dplane_ctx_get_op(ctx) == DPLANE_OP_LSP_UPDATE) { - ret = netlink_mpls_multipath(RTM_NEWROUTE, lsp); + /* Validate */ + if (dplane_ctx_get_best_nhlfe(ctx) == NULL) { + if (IS_ZEBRA_DEBUG_KERNEL || IS_ZEBRA_DEBUG_MPLS) + zlog_debug("LSP in-label %u: update fails, no best NHLFE", + dplane_ctx_get_in_label(ctx)); + goto done; + } - kernel_lsp_pass_fail(lsp, - (!ret) ? ZEBRA_DPLANE_INSTALL_SUCCESS - : ZEBRA_DPLANE_INSTALL_FAILURE); + cmd = RTM_NEWROUTE; + } else + /* Invalid op? */ + goto done; - return ZEBRA_DPLANE_REQUEST_SUCCESS; -} - -/* - * Update Label Forwarding entry in the kernel. This means that the Label - * forwarding entry is already installed and needs an update - either a new - * path is to be added, an installed path has changed (e.g., outgoing label) - * or an installed path (but not all paths) has to be removed. - * TODO: Performs a DEL followed by ADD now, need to change to REPLACE. Note - * that REPLACE was originally implemented for IPv4 nexthops but removed as - * it was not functioning when moving from swap to PHP as that was signaled - * through the metric field (before kernel-MPLS). This shouldn't be an issue - * any longer, so REPLACE can be reintroduced. - */ -enum zebra_dplane_result kernel_upd_lsp(zebra_lsp_t *lsp) -{ - int ret; - - if (!lsp || !lsp->best_nhlfe) { // unexpected - kernel_lsp_pass_fail(lsp, ZEBRA_DPLANE_INSTALL_FAILURE); - return ZEBRA_DPLANE_REQUEST_FAILURE; - } - - ret = netlink_mpls_multipath(RTM_NEWROUTE, lsp); - - kernel_lsp_pass_fail(lsp, - (!ret) ? ZEBRA_DPLANE_INSTALL_SUCCESS - : ZEBRA_DPLANE_INSTALL_FAILURE); - - return ZEBRA_DPLANE_REQUEST_SUCCESS; -} - -/* - * Delete Label Forwarding entry from the kernel. - */ -enum zebra_dplane_result kernel_del_lsp(zebra_lsp_t *lsp) -{ - int ret; - - if (!lsp) { // unexpected - kernel_lsp_pass_fail(lsp, ZEBRA_DPLANE_DELETE_FAILURE); - return ZEBRA_DPLANE_REQUEST_FAILURE; - } - - if (!CHECK_FLAG(lsp->flags, LSP_FLAG_INSTALLED)) { - kernel_lsp_pass_fail(lsp, ZEBRA_DPLANE_DELETE_FAILURE); - return ZEBRA_DPLANE_REQUEST_FAILURE; - } - - ret = netlink_mpls_multipath(RTM_DELROUTE, lsp); + ret = netlink_mpls_multipath(cmd, ctx); - kernel_lsp_pass_fail(lsp, - (!ret) ? ZEBRA_DPLANE_DELETE_SUCCESS - : ZEBRA_DPLANE_DELETE_FAILURE); +done: - return ZEBRA_DPLANE_REQUEST_SUCCESS; + return (ret == 0 ? + ZEBRA_DPLANE_REQUEST_SUCCESS : ZEBRA_DPLANE_REQUEST_FAILURE); } int mpls_kernel_init(void) diff --git a/zebra/zebra_mpls_null.c b/zebra/zebra_mpls_null.c index 02ec506d84..409432c4fb 100644 --- a/zebra/zebra_mpls_null.c +++ b/zebra/zebra_mpls_null.c @@ -24,24 +24,14 @@ #if !defined(HAVE_NETLINK) && !defined(OPEN_BSD) -enum zebra_dplane_result kernel_add_lsp(zebra_lsp_t *lsp) -{ - return ZEBRA_DPLANE_REQUEST_SUCCESS; -} - -enum zebra_dplane_result kernel_upd_lsp(zebra_lsp_t *lsp) -{ - return ZEBRA_DPLANE_REQUEST_SUCCESS; -} - -enum zebra_dplane_result kernel_del_lsp(zebra_lsp_t *lsp) -{ - return ZEBRA_DPLANE_REQUEST_SUCCESS; -} - int mpls_kernel_init(void) { return -1; }; +enum zebra_dplane_result kernel_lsp_update(struct zebra_dplane_ctx *ctx) +{ + return ZEBRA_DPLANE_REQUEST_FAILURE; +} + #endif /* !defined(HAVE_NETLINK) && !defined(OPEN_BSD) */ diff --git a/zebra/zebra_mpls_openbsd.c b/zebra/zebra_mpls_openbsd.c index 60f944b844..da76c6ebf9 100644 --- a/zebra/zebra_mpls_openbsd.c +++ b/zebra/zebra_mpls_openbsd.c @@ -236,13 +236,28 @@ static int kernel_send_rtmsg_v6(int action, mpls_label_t in_label, return ret; } -static int kernel_lsp_cmd(int action, zebra_lsp_t *lsp) +static int kernel_lsp_cmd(struct zebra_dplane_ctx *ctx) { zebra_nhlfe_t *nhlfe; struct nexthop *nexthop = NULL; unsigned int nexthop_num = 0; + int action; - for (nhlfe = lsp->nhlfe_list; nhlfe; nhlfe = nhlfe->next) { + switch (dplane_ctx_get_op(ctx)) { + case DPLANE_OP_LSP_DELETE: + action = RTM_DELETE; + break; + case DPLANE_OP_LSP_INSTALL: + action = RTM_ADD; + break; + case DPLANE_OP_LSP_UPDATE: + action = RTM_CHANGE; + break; + default: + return -1; + } + + for (nhlfe = dplane_ctx_get_nhlfe(ctx); nhlfe; nhlfe = nhlfe->next) { nexthop = nhlfe->nexthop; if (!nexthop) continue; @@ -269,12 +284,16 @@ static int kernel_lsp_cmd(int action, zebra_lsp_t *lsp) switch (NHLFE_FAMILY(nhlfe)) { case AF_INET: - kernel_send_rtmsg_v4(action, lsp->ile.in_label, - nhlfe); + kernel_send_rtmsg_v4( + action, + dplane_ctx_get_in_label(ctx), + nhlfe); break; case AF_INET6: - kernel_send_rtmsg_v6(action, lsp->ile.in_label, - nhlfe); + kernel_send_rtmsg_v6( + action, + dplane_ctx_get_in_label(ctx), + nhlfe); break; default: break; @@ -285,62 +304,14 @@ static int kernel_lsp_cmd(int action, zebra_lsp_t *lsp) return (0); } -enum zebra_dplane_result kernel_add_lsp(zebra_lsp_t *lsp) +enum zebra_dplane_result kernel_lsp_update(struct zebra_dplane_ctx *ctx) { int ret; - if (!lsp || !lsp->best_nhlfe) { // unexpected - kernel_lsp_pass_fail(lsp, ZEBRA_DPLANE_INSTALL_FAILURE); - return ZEBRA_DPLANE_REQUEST_FAILURE; - } - - ret = kernel_lsp_cmd(RTM_ADD, lsp); - - kernel_lsp_pass_fail(lsp, - (!ret) ? ZEBRA_DPLANE_INSTALL_SUCCESS - : ZEBRA_DPLANE_INSTALL_FAILURE); - - return ZEBRA_DPLANE_REQUEST_SUCCESS; -} - -enum zebra_dplane_result kernel_upd_lsp(zebra_lsp_t *lsp) -{ - int ret; - - if (!lsp || !lsp->best_nhlfe) { // unexpected - kernel_lsp_pass_fail(lsp, ZEBRA_DPLANE_INSTALL_FAILURE); - return ZEBRA_DPLANE_REQUEST_FAILURE; - } - - ret = kernel_lsp_cmd(RTM_CHANGE, lsp); - - kernel_lsp_pass_fail(lsp, - (!ret) ? ZEBRA_DPLANE_INSTALL_SUCCESS - : ZEBRA_DPLANE_INSTALL_FAILURE); - return ZEBRA_DPLANE_REQUEST_SUCCESS; -} - -enum zebra_dplane_result kernel_del_lsp(zebra_lsp_t *lsp) -{ - int ret; - - if (!lsp) { // unexpected - kernel_lsp_pass_fail(lsp, ZEBRA_DPLANE_DELETE_FAILURE); - return ZEBRA_DPLANE_REQUEST_FAILURE; - } - - if (!CHECK_FLAG(lsp->flags, LSP_FLAG_INSTALLED)) { - kernel_lsp_pass_fail(lsp, ZEBRA_DPLANE_DELETE_FAILURE); - return ZEBRA_DPLANE_REQUEST_FAILURE; - } - - ret = kernel_lsp_cmd(RTM_DELETE, lsp); - - kernel_lsp_pass_fail(lsp, - (!ret) ? ZEBRA_DPLANE_DELETE_SUCCESS - : ZEBRA_DPLANE_DELETE_FAILURE); + ret = kernel_lsp_cmd(ctx); - return ZEBRA_DPLANE_REQUEST_SUCCESS; + return (ret == 0 ? + ZEBRA_DPLANE_REQUEST_SUCCESS : ZEBRA_DPLANE_REQUEST_FAILURE); } static int kmpw_install(struct zebra_pw *pw) diff --git a/zebra/zebra_rib.c b/zebra/zebra_rib.c index 7e4ac1ddd2..0dc8a05e9c 100644 --- a/zebra/zebra_rib.c +++ b/zebra/zebra_rib.c @@ -1811,7 +1811,7 @@ done: /* * Route-update results processing after async dataplane update. */ -static void rib_process_after(struct zebra_dplane_ctx *ctx) +static void rib_process_result(struct zebra_dplane_ctx *ctx) { struct route_table *table = NULL; struct zebra_vrf *zvrf = NULL; @@ -1931,8 +1931,6 @@ static void rib_process_after(struct zebra_dplane_ctx *ctx) } switch (op) { - case DPLANE_OP_NONE: - break; case DPLANE_OP_ROUTE_INSTALL: case DPLANE_OP_ROUTE_UPDATE: if (status == ZEBRA_DPLANE_REQUEST_SUCCESS) { @@ -2015,6 +2013,8 @@ static void rib_process_after(struct zebra_dplane_ctx *ctx) dest_str, sizeof(dest_str))); } break; + default: + break; } done: @@ -2090,11 +2090,11 @@ static void do_nht_processing(void) zvrf_name(zvrf)); zvrf->flags &= ~ZEBRA_VRF_RIB_SCHEDULED; - zebra_evaluate_rnh(zvrf, AF_INET, 0, RNH_NEXTHOP_TYPE, NULL); - zebra_evaluate_rnh(zvrf, AF_INET, 0, RNH_IMPORT_CHECK_TYPE, + zebra_evaluate_rnh(zvrf, AFI_IP, 0, RNH_NEXTHOP_TYPE, NULL); + zebra_evaluate_rnh(zvrf, AFI_IP, 0, RNH_IMPORT_CHECK_TYPE, NULL); - zebra_evaluate_rnh(zvrf, AF_INET6, 0, RNH_NEXTHOP_TYPE, NULL); - zebra_evaluate_rnh(zvrf, AF_INET6, 0, RNH_IMPORT_CHECK_TYPE, + zebra_evaluate_rnh(zvrf, AFI_IP6, 0, RNH_NEXTHOP_TYPE, NULL); + zebra_evaluate_rnh(zvrf, AFI_IP6, 0, RNH_IMPORT_CHECK_TYPE, NULL); } @@ -3191,7 +3191,8 @@ void rib_close_table(struct route_table *table) } /* - * + * Handle results from the dataplane system. Dequeue update context + * structs, dispatch to appropriate internal handlers. */ static int rib_process_dplane_results(struct thread *thread) { @@ -3200,13 +3201,15 @@ static int rib_process_dplane_results(struct thread *thread) /* Dequeue a list of completed updates with one lock/unlock cycle */ + /* TODO -- dequeue a list with one lock/unlock cycle? */ + do { TAILQ_INIT(&ctxlist); /* Take lock controlling queue of results */ pthread_mutex_lock(&dplane_mutex); { - /* Dequeue context block */ + /* Dequeue list of context structs */ dplane_ctx_list_append(&ctxlist, &rib_dplane_q); } pthread_mutex_unlock(&dplane_mutex); @@ -3219,7 +3222,24 @@ static int rib_process_dplane_results(struct thread *thread) break; while (ctx) { - rib_process_after(ctx); + switch (dplane_ctx_get_op(ctx)) { + case DPLANE_OP_ROUTE_INSTALL: + case DPLANE_OP_ROUTE_UPDATE: + case DPLANE_OP_ROUTE_DELETE: + rib_process_result(ctx); + break; + + case DPLANE_OP_LSP_INSTALL: + case DPLANE_OP_LSP_UPDATE: + case DPLANE_OP_LSP_DELETE: + zebra_mpls_lsp_dplane_result(ctx); + break; + + default: + /* Don't expect this: just return the struct? */ + dplane_ctx_fini(&ctx); + break; + } /* Dispatch by op code */ ctx = dplane_ctx_dequeue(&ctxlist); } diff --git a/zebra/zebra_rnh.c b/zebra/zebra_rnh.c index c3781888b1..317a7cdeca 100644 --- a/zebra/zebra_rnh.c +++ b/zebra/zebra_rnh.c @@ -54,16 +54,6 @@ static void free_state(vrf_id_t vrf_id, struct route_entry *re, struct route_node *rn); static void copy_state(struct rnh *rnh, struct route_entry *re, struct route_node *rn); -#define lookup_rnh_table(v, f) \ - ({ \ - struct zebra_vrf *zvrf; \ - struct route_table *t = NULL; \ - zvrf = zebra_vrf_lookup_by_id(v); \ - if (zvrf) \ - t = zvrf->rnh_table[family2afi(f)]; \ - t; \ - }) - static int compare_state(struct route_entry *r1, struct route_entry *r2); static int send_client(struct rnh *rnh, struct zserv *client, rnh_type_t type, vrf_id_t vrf_id); @@ -78,7 +68,7 @@ void zebra_rnh_init(void) hook_register(zserv_client_close, zebra_client_cleanup_rnh); } -static inline struct route_table *get_rnh_table(vrf_id_t vrfid, int family, +static inline struct route_table *get_rnh_table(vrf_id_t vrfid, afi_t afi, rnh_type_t type) { struct zebra_vrf *zvrf; @@ -88,10 +78,10 @@ static inline struct route_table *get_rnh_table(vrf_id_t vrfid, int family, if (zvrf) switch (type) { case RNH_NEXTHOP_TYPE: - t = zvrf->rnh_table[family2afi(family)]; + t = zvrf->rnh_table[afi]; break; case RNH_IMPORT_CHECK_TYPE: - t = zvrf->import_check_table[family2afi(family)]; + t = zvrf->import_check_table[afi]; break; } @@ -116,7 +106,7 @@ struct rnh *zebra_add_rnh(struct prefix *p, vrf_id_t vrfid, rnh_type_t type, prefix2str(p, buf, sizeof(buf)); zlog_debug("%u: Add RNH %s type %d", vrfid, buf, type); } - table = get_rnh_table(vrfid, PREFIX_FAMILY(p), type); + table = get_rnh_table(vrfid, family2afi(PREFIX_FAMILY(p)), type); if (!table) { prefix2str(p, buf, sizeof(buf)); flog_warn(EC_ZEBRA_RNH_NO_TABLE, @@ -153,7 +143,7 @@ struct rnh *zebra_lookup_rnh(struct prefix *p, vrf_id_t vrfid, rnh_type_t type) struct route_table *table; struct route_node *rn; - table = get_rnh_table(vrfid, PREFIX_FAMILY(p), type); + table = get_rnh_table(vrfid, family2afi(PREFIX_FAMILY(p)), type); if (!table) return NULL; @@ -278,7 +268,8 @@ void zebra_register_rnh_pseudowire(vrf_id_t vrf_id, struct zebra_pw *pw) if (rnh && !listnode_lookup(rnh->zebra_pseudowire_list, pw)) { listnode_add(rnh->zebra_pseudowire_list, pw); pw->rnh = rnh; - zebra_evaluate_rnh(zvrf, pw->af, 1, RNH_NEXTHOP_TYPE, &nh); + zebra_evaluate_rnh(zvrf, family2afi(pw->af), 1, + RNH_NEXTHOP_TYPE, &nh); } } @@ -299,22 +290,19 @@ void zebra_deregister_rnh_pseudowire(vrf_id_t vrf_id, struct zebra_pw *pw) /* Apply the NHT route-map for a client to the route (and nexthops) * resolving a NH. */ -static int zebra_rnh_apply_nht_rmap(int family, struct zebra_vrf *zvrf, +static int zebra_rnh_apply_nht_rmap(afi_t afi, struct zebra_vrf *zvrf, struct route_node *prn, struct route_entry *re, int proto) { int at_least_one = 0; - int rmap_family; /* Route map has diff AF family enum */ struct nexthop *nexthop; int ret; - rmap_family = (family == AF_INET) ? AFI_IP : AFI_IP6; - if (prn && re) { for (nexthop = re->ng.nexthop; nexthop; nexthop = nexthop->next) { ret = zebra_nht_route_map_check( - rmap_family, proto, &prn->p, zvrf, re, nexthop); + afi, proto, &prn->p, zvrf, re, nexthop); if (ret != RMAP_DENYMATCH) { SET_FLAG(nexthop->flags, NEXTHOP_FLAG_ACTIVE); at_least_one++; /* at least one valid NH */ @@ -331,7 +319,7 @@ static int zebra_rnh_apply_nht_rmap(int family, struct zebra_vrf *zvrf, * for BGP route for import. */ static struct route_entry * -zebra_rnh_resolve_import_entry(struct zebra_vrf *zvrf, int family, +zebra_rnh_resolve_import_entry(struct zebra_vrf *zvrf, afi_t afi, struct route_node *nrn, struct rnh *rnh, struct route_node **prn) { @@ -341,7 +329,7 @@ zebra_rnh_resolve_import_entry(struct zebra_vrf *zvrf, int family, *prn = NULL; - route_table = zvrf->table[family2afi(family)][SAFI_UNICAST]; + route_table = zvrf->table[afi][SAFI_UNICAST]; if (!route_table) // unexpected return NULL; @@ -373,7 +361,7 @@ zebra_rnh_resolve_import_entry(struct zebra_vrf *zvrf, int family, * See if a tracked route entry for import (by BGP) has undergone any * change, and if so, notify the client. */ -static void zebra_rnh_eval_import_check_entry(vrf_id_t vrfid, int family, +static void zebra_rnh_eval_import_check_entry(vrf_id_t vrfid, afi_t afi, int force, struct route_node *nrn, struct rnh *rnh, struct route_entry *re) @@ -413,9 +401,11 @@ static void zebra_rnh_eval_import_check_entry(vrf_id_t vrfid, int family, /* * Notify clients registered for this nexthop about a change. */ -static void zebra_rnh_notify_protocol_clients( - struct zebra_vrf *zvrf, int family, struct route_node *nrn, - struct rnh *rnh, struct route_node *prn, struct route_entry *re) +static void zebra_rnh_notify_protocol_clients(struct zebra_vrf *zvrf, afi_t afi, + struct route_node *nrn, + struct rnh *rnh, + struct route_node *prn, + struct route_entry *re) { struct listnode *node; struct zserv *client; @@ -441,7 +431,7 @@ static void zebra_rnh_notify_protocol_clients( * nexthop to see if it is filtered or not. */ num_resolving_nh = zebra_rnh_apply_nht_rmap( - family, zvrf, prn, re, client->proto); + afi, zvrf, prn, re, client->proto); if (num_resolving_nh) rnh->filtered[client->proto] = 0; else @@ -468,8 +458,7 @@ static void zebra_rnh_notify_protocol_clients( } } -static void zebra_rnh_process_pbr_tables(int family, - struct route_node *nrn, +static void zebra_rnh_process_pbr_tables(afi_t afi, struct route_node *nrn, struct rnh *rnh, struct route_node *prn, struct route_entry *re) @@ -479,10 +468,6 @@ static void zebra_rnh_process_pbr_tables(int family, struct route_node *o_rn; struct listnode *node; struct zserv *client; - afi_t afi = AFI_IP; - - if (family == AF_INET6) - afi = AFI_IP6; /* * We are only concerned about nexthops that change for @@ -537,7 +522,7 @@ static bool rnh_nexthop_valid(const struct nexthop *nh) * nexthop. */ static struct route_entry * -zebra_rnh_resolve_nexthop_entry(struct zebra_vrf *zvrf, int family, +zebra_rnh_resolve_nexthop_entry(struct zebra_vrf *zvrf, afi_t afi, struct route_node *nrn, struct rnh *rnh, struct route_node **prn) { @@ -548,7 +533,7 @@ zebra_rnh_resolve_nexthop_entry(struct zebra_vrf *zvrf, int family, *prn = NULL; - route_table = zvrf->table[family2afi(family)][SAFI_UNICAST]; + route_table = zvrf->table[afi][SAFI_UNICAST]; if (!route_table) return NULL; @@ -635,7 +620,7 @@ static void zebra_rnh_process_pseudowires(vrf_id_t vrfid, struct rnh *rnh) * take appropriate action; this involves notifying any clients and/or * scheduling dependent static routes for processing. */ -static void zebra_rnh_eval_nexthop_entry(struct zebra_vrf *zvrf, int family, +static void zebra_rnh_eval_nexthop_entry(struct zebra_vrf *zvrf, afi_t afi, int force, struct route_node *nrn, struct rnh *rnh, struct route_node *prn, @@ -665,10 +650,10 @@ static void zebra_rnh_eval_nexthop_entry(struct zebra_vrf *zvrf, int family, * rnh->state. */ /* Notify registered protocol clients. */ - zebra_rnh_notify_protocol_clients(zvrf, family, nrn, rnh, prn, + zebra_rnh_notify_protocol_clients(zvrf, afi, nrn, rnh, prn, rnh->state); - zebra_rnh_process_pbr_tables(family, nrn, rnh, prn, rnh->state); + zebra_rnh_process_pbr_tables(afi, nrn, rnh, prn, rnh->state); /* Process pseudowires attached to this nexthop */ zebra_rnh_process_pseudowires(zvrf->vrf->vrf_id, rnh); @@ -676,7 +661,7 @@ static void zebra_rnh_eval_nexthop_entry(struct zebra_vrf *zvrf, int family, } /* Evaluate one tracked entry */ -static void zebra_rnh_evaluate_entry(struct zebra_vrf *zvrf, int family, +static void zebra_rnh_evaluate_entry(struct zebra_vrf *zvrf, afi_t afi, int force, rnh_type_t type, struct route_node *nrn) { @@ -695,11 +680,9 @@ static void zebra_rnh_evaluate_entry(struct zebra_vrf *zvrf, int family, /* Identify route entry (RE) resolving this tracked entry. */ if (type == RNH_IMPORT_CHECK_TYPE) - re = zebra_rnh_resolve_import_entry(zvrf, family, nrn, rnh, - &prn); + re = zebra_rnh_resolve_import_entry(zvrf, afi, nrn, rnh, &prn); else - re = zebra_rnh_resolve_nexthop_entry(zvrf, family, nrn, rnh, - &prn); + re = zebra_rnh_resolve_nexthop_entry(zvrf, afi, nrn, rnh, &prn); /* If the entry cannot be resolved and that is also the existing state, * there is nothing further to do. @@ -709,10 +692,10 @@ static void zebra_rnh_evaluate_entry(struct zebra_vrf *zvrf, int family, /* Process based on type of entry. */ if (type == RNH_IMPORT_CHECK_TYPE) - zebra_rnh_eval_import_check_entry(zvrf->vrf->vrf_id, family, - force, nrn, rnh, re); + zebra_rnh_eval_import_check_entry(zvrf->vrf->vrf_id, afi, force, + nrn, rnh, re); else - zebra_rnh_eval_nexthop_entry(zvrf, family, force, nrn, rnh, prn, + zebra_rnh_eval_nexthop_entry(zvrf, afi, force, nrn, rnh, prn, re); } @@ -725,7 +708,7 @@ static void zebra_rnh_evaluate_entry(struct zebra_vrf *zvrf, int family, * we can have a situation where one re entry * covers multiple nexthops we are interested in. */ -static void zebra_rnh_clear_nhc_flag(struct zebra_vrf *zvrf, int family, +static void zebra_rnh_clear_nhc_flag(struct zebra_vrf *zvrf, afi_t afi, rnh_type_t type, struct route_node *nrn) { struct rnh *rnh; @@ -736,10 +719,10 @@ static void zebra_rnh_clear_nhc_flag(struct zebra_vrf *zvrf, int family, /* Identify route entry (RIB) resolving this tracked entry. */ if (type == RNH_IMPORT_CHECK_TYPE) - re = zebra_rnh_resolve_import_entry(zvrf, family, nrn, rnh, + re = zebra_rnh_resolve_import_entry(zvrf, afi, nrn, rnh, &prn); else - re = zebra_rnh_resolve_nexthop_entry(zvrf, family, nrn, rnh, + re = zebra_rnh_resolve_nexthop_entry(zvrf, afi, nrn, rnh, &prn); if (re) { @@ -751,13 +734,13 @@ static void zebra_rnh_clear_nhc_flag(struct zebra_vrf *zvrf, int family, /* Evaluate all tracked entries (nexthops or routes for import into BGP) * of a particular VRF and address-family or a specific prefix. */ -void zebra_evaluate_rnh(struct zebra_vrf *zvrf, int family, int force, +void zebra_evaluate_rnh(struct zebra_vrf *zvrf, afi_t afi, int force, rnh_type_t type, struct prefix *p) { struct route_table *rnh_table; struct route_node *nrn; - rnh_table = get_rnh_table(zvrf->vrf->vrf_id, family, type); + rnh_table = get_rnh_table(zvrf->vrf->vrf_id, afi, type); if (!rnh_table) // unexpected return; @@ -765,8 +748,7 @@ void zebra_evaluate_rnh(struct zebra_vrf *zvrf, int family, int force, /* Evaluating a specific entry, make sure it exists. */ nrn = route_node_lookup(rnh_table, p); if (nrn && nrn->info) - zebra_rnh_evaluate_entry(zvrf, family, force, type, - nrn); + zebra_rnh_evaluate_entry(zvrf, afi, force, type, nrn); if (nrn) route_unlock_node(nrn); @@ -775,27 +757,26 @@ void zebra_evaluate_rnh(struct zebra_vrf *zvrf, int family, int force, nrn = route_top(rnh_table); while (nrn) { if (nrn->info) - zebra_rnh_evaluate_entry(zvrf, family, force, - type, nrn); + zebra_rnh_evaluate_entry(zvrf, afi, force, type, + nrn); nrn = route_next(nrn); /* this will also unlock nrn */ } nrn = route_top(rnh_table); while (nrn) { if (nrn->info) - zebra_rnh_clear_nhc_flag(zvrf, family, type, - nrn); + zebra_rnh_clear_nhc_flag(zvrf, afi, type, nrn); nrn = route_next(nrn); /* this will also unlock nrn */ } } } -void zebra_print_rnh_table(vrf_id_t vrfid, int af, struct vty *vty, +void zebra_print_rnh_table(vrf_id_t vrfid, afi_t afi, struct vty *vty, rnh_type_t type) { struct route_table *table; struct route_node *rn; - table = get_rnh_table(vrfid, af, type); + table = get_rnh_table(vrfid, afi, type); if (!table) { zlog_debug("print_rnhs: rnh table not found\n"); return; @@ -1032,7 +1013,7 @@ static void print_rnh(struct route_node *rn, struct vty *vty) vty_out(vty, "\n"); } -static int zebra_cleanup_rnh_client(vrf_id_t vrf_id, int family, +static int zebra_cleanup_rnh_client(vrf_id_t vrf_id, afi_t afi, struct zserv *client, rnh_type_t type) { struct route_table *ntable; @@ -1040,11 +1021,11 @@ static int zebra_cleanup_rnh_client(vrf_id_t vrf_id, int family, struct rnh *rnh; if (IS_ZEBRA_DEBUG_NHT) - zlog_debug("%u: Client %s RNH cleanup for family %d type %d", - vrf_id, zebra_route_string(client->proto), family, - type); + zlog_debug("%u: Client %s RNH cleanup for family %s type %d", + vrf_id, zebra_route_string(client->proto), + afi2str(afi), type); - ntable = get_rnh_table(vrf_id, family, type); + ntable = get_rnh_table(vrf_id, afi, type); if (!ntable) { zlog_debug("cleanup_rnh_client: rnh table not found\n"); return -1; @@ -1069,14 +1050,14 @@ static int zebra_client_cleanup_rnh(struct zserv *client) RB_FOREACH (vrf, vrf_id_head, &vrfs_by_id) { zvrf = vrf->info; if (zvrf) { - zebra_cleanup_rnh_client(zvrf_id(zvrf), AF_INET, client, + zebra_cleanup_rnh_client(zvrf_id(zvrf), AFI_IP, client, RNH_NEXTHOP_TYPE); - zebra_cleanup_rnh_client(zvrf_id(zvrf), AF_INET6, - client, RNH_NEXTHOP_TYPE); - zebra_cleanup_rnh_client(zvrf_id(zvrf), AF_INET, client, + zebra_cleanup_rnh_client(zvrf_id(zvrf), AFI_IP6, client, + RNH_NEXTHOP_TYPE); + zebra_cleanup_rnh_client(zvrf_id(zvrf), AFI_IP, client, + RNH_IMPORT_CHECK_TYPE); + zebra_cleanup_rnh_client(zvrf_id(zvrf), AFI_IP6, client, RNH_IMPORT_CHECK_TYPE); - zebra_cleanup_rnh_client(zvrf_id(zvrf), AF_INET6, - client, RNH_IMPORT_CHECK_TYPE); if (client->proto == ZEBRA_ROUTE_LDP) { hash_iterate(zvrf->lsp_table, mpls_ldp_lsp_uninstall_all, diff --git a/zebra/zebra_rnh.h b/zebra/zebra_rnh.h index ed1fe9b756..00ee60dc1a 100644 --- a/zebra/zebra_rnh.h +++ b/zebra/zebra_rnh.h @@ -78,9 +78,9 @@ extern void zebra_register_rnh_pseudowire(vrf_id_t, struct zebra_pw *); extern void zebra_deregister_rnh_pseudowire(vrf_id_t, struct zebra_pw *); extern void zebra_remove_rnh_client(struct rnh *rnh, struct zserv *client, rnh_type_t type); -extern void zebra_evaluate_rnh(struct zebra_vrf *zvrf, int family, int force, +extern void zebra_evaluate_rnh(struct zebra_vrf *zvrf, afi_t afi, int force, rnh_type_t type, struct prefix *p); -extern void zebra_print_rnh_table(vrf_id_t vrfid, int family, struct vty *vty, +extern void zebra_print_rnh_table(vrf_id_t vrfid, afi_t afi, struct vty *vty, rnh_type_t); extern char *rnh_str(struct rnh *rnh, char *buf, int size); #endif /*_ZEBRA_RNH_H */ diff --git a/zebra/zebra_routemap.c b/zebra/zebra_routemap.c index c9918a7887..5461a7883d 100644 --- a/zebra/zebra_routemap.c +++ b/zebra/zebra_routemap.c @@ -389,7 +389,7 @@ static int ip_nht_rm_add(struct zebra_vrf *zvrf, const char *rmap, int rtype, route_map_lookup_by_name(NHT_RM_NAME(zvrf, afi, rtype)); if (NHT_RM_MAP(zvrf, afi, rtype)) - zebra_evaluate_rnh(zvrf, AF_INET, 1, RNH_NEXTHOP_TYPE, NULL); + zebra_evaluate_rnh(zvrf, AFI_IP, 1, RNH_NEXTHOP_TYPE, NULL); return CMD_SUCCESS; } @@ -409,7 +409,7 @@ static int ip_nht_rm_del(struct zebra_vrf *zvrf, const char *rmap, int rtype, zvrf->vrf->vrf_id, rtype); NHT_RM_MAP(zvrf, afi, rtype) = NULL; - zebra_evaluate_rnh(zvrf, AF_INET, 1, RNH_NEXTHOP_TYPE, + zebra_evaluate_rnh(zvrf, AFI_IP, 1, RNH_NEXTHOP_TYPE, NULL); } XFREE(MTYPE_ROUTE_MAP_NAME, NHT_RM_NAME(zvrf, afi, rtype)); @@ -1556,7 +1556,7 @@ static void zebra_nht_rm_update(const char *rmap) afi_ip = 1; zebra_evaluate_rnh( - zvrf, AF_INET, 1, + zvrf, AFI_IP, 1, RNH_NEXTHOP_TYPE, NULL); } } @@ -1582,7 +1582,7 @@ static void zebra_nht_rm_update(const char *rmap) afi_ipv6 = 1; zebra_evaluate_rnh( - zvrf, AF_INET, 1, + zvrf, AFI_IP, 1, RNH_NEXTHOP_TYPE, NULL); } } @@ -1713,7 +1713,7 @@ zebra_import_table_route_map_check(int family, int re_type, uint8_t instance, return (ret); } -route_map_result_t zebra_nht_route_map_check(int family, int client_proto, +route_map_result_t zebra_nht_route_map_check(afi_t afi, int client_proto, const struct prefix *p, struct zebra_vrf *zvrf, struct route_entry *re, @@ -1731,9 +1731,9 @@ route_map_result_t zebra_nht_route_map_check(int family, int client_proto, nh_obj.tag = re->tag; if (client_proto >= 0 && client_proto < ZEBRA_ROUTE_MAX) - rmap = NHT_RM_MAP(zvrf, family, client_proto); - if (!rmap && NHT_RM_MAP(zvrf, family, ZEBRA_ROUTE_MAX)) - rmap = NHT_RM_MAP(zvrf, family, ZEBRA_ROUTE_MAX); + rmap = NHT_RM_MAP(zvrf, afi, client_proto); + if (!rmap && NHT_RM_MAP(zvrf, afi, ZEBRA_ROUTE_MAX)) + rmap = NHT_RM_MAP(zvrf, afi, ZEBRA_ROUTE_MAX); if (rmap) ret = route_map_apply(rmap, p, RMAP_ZEBRA, &nh_obj); diff --git a/zebra/zebra_routemap.h b/zebra/zebra_routemap.h index a8579e7c6e..abd2ad78f7 100644 --- a/zebra/zebra_routemap.h +++ b/zebra/zebra_routemap.h @@ -44,7 +44,7 @@ zebra_route_map_check(int family, int rib_type, uint8_t instance, const struct prefix *p, struct nexthop *nexthop, struct zebra_vrf *zvrf, route_tag_t tag); extern route_map_result_t -zebra_nht_route_map_check(int family, int client_proto, const struct prefix *p, +zebra_nht_route_map_check(afi_t afi, int client_proto, const struct prefix *p, struct zebra_vrf *zvrf, struct route_entry *, struct nexthop *nexthop); diff --git a/zebra/zebra_vrf.h b/zebra/zebra_vrf.h index c28025403b..2473299d17 100644 --- a/zebra/zebra_vrf.h +++ b/zebra/zebra_vrf.h @@ -137,12 +137,14 @@ struct zebra_vrf { */ enum vxlan_flood_control vxlan_flood_ctrl; - /* Route Installs */ + /* Install stats */ uint64_t installs; uint64_t removals; uint64_t installs_queued; uint64_t removals_queued; uint64_t neigh_updates; + uint64_t lsp_installs_queued; + uint64_t lsp_removals_queued; uint64_t lsp_installs; uint64_t lsp_removals; }; diff --git a/zebra/zebra_vty.c b/zebra/zebra_vty.c index b18f0e943c..87b279b1e9 100644 --- a/zebra/zebra_vty.c +++ b/zebra/zebra_vty.c @@ -930,21 +930,35 @@ DEFPY (show_route_table_vrf, return CMD_SUCCESS; } -DEFUN (show_ip_nht, +DEFPY (show_ip_nht, show_ip_nht_cmd, - "show ip nht [vrf NAME]", + "show <ip$ipv4|ipv6$ipv6> nht [vrf NAME$vrf_name|vrf all$vrf_all]", SHOW_STR IP_STR + IP6_STR "IP nexthop tracking table\n" - VRF_CMD_HELP_STR) + VRF_CMD_HELP_STR + VRF_ALL_CMD_HELP_STR) { - int idx_vrf = 4; + afi_t afi = ipv4 ? AFI_IP : AFI_IP6; vrf_id_t vrf_id = VRF_DEFAULT; - if (argc == 5) - VRF_GET_ID(vrf_id, argv[idx_vrf]->arg, false); + if (vrf_all) { + struct vrf *vrf; + struct zebra_vrf *zvrf; + + RB_FOREACH (vrf, vrf_name_head, &vrfs_by_name) + if ((zvrf = vrf->info) != NULL) { + vty_out(vty, "\nVRF %s:\n", zvrf_name(zvrf)); + zebra_print_rnh_table(zvrf_id(zvrf), afi, vty, + RNH_NEXTHOP_TYPE); + } + return CMD_SUCCESS; + } + if (vrf_name) + VRF_GET_ID(vrf_id, vrf_name, false); - zebra_print_rnh_table(vrf_id, AF_INET, vty, RNH_NEXTHOP_TYPE); + zebra_print_rnh_table(vrf_id, afi, vty, RNH_NEXTHOP_TYPE); return CMD_SUCCESS; } @@ -969,9 +983,8 @@ DEFPY (show_ip_import_check, if ((zvrf = vrf->info) != NULL) { vty_out(vty, "\nVRF %s:\n", zvrf_name(zvrf)); - zebra_print_rnh_table(zvrf_id(zvrf), - afi, vty, - RNH_NEXTHOP_TYPE); + zebra_print_rnh_table(zvrf_id(zvrf), afi, vty, + RNH_IMPORT_CHECK_TYPE); } return CMD_SUCCESS; } @@ -982,67 +995,6 @@ DEFPY (show_ip_import_check, return CMD_SUCCESS; } -DEFUN (show_ip_nht_vrf_all, - show_ip_nht_vrf_all_cmd, - "show ip nht vrf all", - SHOW_STR - IP_STR - "IP nexthop tracking table\n" - VRF_ALL_CMD_HELP_STR) -{ - struct vrf *vrf; - struct zebra_vrf *zvrf; - - RB_FOREACH (vrf, vrf_name_head, &vrfs_by_name) - if ((zvrf = vrf->info) != NULL) { - vty_out(vty, "\nVRF %s:\n", zvrf_name(zvrf)); - zebra_print_rnh_table(zvrf_id(zvrf), AF_INET, vty, - RNH_NEXTHOP_TYPE); - } - - return CMD_SUCCESS; -} - -DEFUN (show_ipv6_nht, - show_ipv6_nht_cmd, - "show ipv6 nht [vrf NAME]", - SHOW_STR - IPV6_STR - "IPv6 nexthop tracking table\n" - VRF_CMD_HELP_STR) -{ - int idx_vrf = 4; - vrf_id_t vrf_id = VRF_DEFAULT; - - if (argc == 5) - VRF_GET_ID(vrf_id, argv[idx_vrf]->arg, false); - - zebra_print_rnh_table(vrf_id, AF_INET6, vty, RNH_NEXTHOP_TYPE); - return CMD_SUCCESS; -} - - -DEFUN (show_ipv6_nht_vrf_all, - show_ipv6_nht_vrf_all_cmd, - "show ipv6 nht vrf all", - SHOW_STR - IP_STR - "IPv6 nexthop tracking table\n" - VRF_ALL_CMD_HELP_STR) -{ - struct vrf *vrf; - struct zebra_vrf *zvrf; - - RB_FOREACH (vrf, vrf_name_head, &vrfs_by_name) - if ((zvrf = vrf->info) != NULL) { - vty_out(vty, "\nVRF %s:\n", zvrf_name(zvrf)); - zebra_print_rnh_table(zvrf_id(zvrf), AF_INET6, vty, - RNH_NEXTHOP_TYPE); - } - - return CMD_SUCCESS; -} - DEFUN (ip_nht_default_route, ip_nht_default_route_cmd, "ip nht resolve-via-default", @@ -1060,7 +1012,7 @@ DEFUN (ip_nht_default_route, zebra_rnh_ip_default_route = 1; - zebra_evaluate_rnh(zvrf, AF_INET, 1, RNH_NEXTHOP_TYPE, NULL); + zebra_evaluate_rnh(zvrf, AFI_IP, 1, RNH_NEXTHOP_TYPE, NULL); return CMD_SUCCESS; } @@ -1081,7 +1033,7 @@ DEFUN (no_ip_nht_default_route, return CMD_SUCCESS; zebra_rnh_ip_default_route = 0; - zebra_evaluate_rnh(zvrf, AF_INET, 1, RNH_NEXTHOP_TYPE, NULL); + zebra_evaluate_rnh(zvrf, AFI_IP, 1, RNH_NEXTHOP_TYPE, NULL); return CMD_SUCCESS; } @@ -1101,7 +1053,7 @@ DEFUN (ipv6_nht_default_route, return CMD_SUCCESS; zebra_rnh_ipv6_default_route = 1; - zebra_evaluate_rnh(zvrf, AF_INET6, 1, RNH_NEXTHOP_TYPE, NULL); + zebra_evaluate_rnh(zvrf, AFI_IP6, 1, RNH_NEXTHOP_TYPE, NULL); return CMD_SUCCESS; } @@ -1123,7 +1075,7 @@ DEFUN (no_ipv6_nht_default_route, return CMD_SUCCESS; zebra_rnh_ipv6_default_route = 0; - zebra_evaluate_rnh(zvrf, AF_INET6, 1, RNH_NEXTHOP_TYPE, NULL); + zebra_evaluate_rnh(zvrf, AFI_IP6, 1, RNH_NEXTHOP_TYPE, NULL); return CMD_SUCCESS; } @@ -2955,9 +2907,6 @@ void zebra_vty_init(void) install_element(VIEW_NODE, &show_route_summary_cmd); install_element(VIEW_NODE, &show_ip_nht_cmd); install_element(VIEW_NODE, &show_ip_import_check_cmd); - install_element(VIEW_NODE, &show_ip_nht_vrf_all_cmd); - install_element(VIEW_NODE, &show_ipv6_nht_cmd); - install_element(VIEW_NODE, &show_ipv6_nht_vrf_all_cmd); install_element(VIEW_NODE, &show_ip_rpf_cmd); install_element(VIEW_NODE, &show_ip_rpf_addr_cmd); |
