summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--ldpd/labelmapping.c4
-rw-r--r--zebra/rt.h20
-rw-r--r--zebra/rt_netlink.c52
-rw-r--r--zebra/rt_netlink.h4
-rw-r--r--zebra/rt_socket.c13
-rw-r--r--zebra/zapi_msg.c3
-rw-r--r--zebra/zebra_dplane.c562
-rw-r--r--zebra/zebra_dplane.h23
-rw-r--r--zebra/zebra_mpls.c167
-rw-r--r--zebra/zebra_mpls.h19
-rw-r--r--zebra/zebra_mpls_netlink.c89
-rw-r--r--zebra/zebra_mpls_null.c20
-rw-r--r--zebra/zebra_mpls_openbsd.c87
-rw-r--r--zebra/zebra_rib.c40
-rw-r--r--zebra/zebra_rnh.c123
-rw-r--r--zebra/zebra_rnh.h4
-rw-r--r--zebra/zebra_routemap.c16
-rw-r--r--zebra/zebra_routemap.h2
-rw-r--r--zebra/zebra_vrf.h4
-rw-r--r--zebra/zebra_vty.c105
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);