diff options
| -rw-r--r-- | ldpd/labelmapping.c | 4 | ||||
| -rw-r--r-- | tests/topotests/bfd-topo1/test_bfd_topo1.py | 2 | ||||
| -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 | 
21 files changed, 841 insertions, 518 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/tests/topotests/bfd-topo1/test_bfd_topo1.py b/tests/topotests/bfd-topo1/test_bfd_topo1.py index 91904c6aae..4fd4f97436 100644 --- a/tests/topotests/bfd-topo1/test_bfd_topo1.py +++ b/tests/topotests/bfd-topo1/test_bfd_topo1.py @@ -138,7 +138,7 @@ def test_bgp_convergence():          expected = json.loads(open(ref_file).read())          test_func = partial(topotest.router_json_cmp,                              router, 'show ip bgp summary json', expected) -        _, res = topotest.run_and_expect(test_func, None, count=20, wait=0.5) +        _, res = topotest.run_and_expect(test_func, None, count=125, wait=1.0)          assertmsg = '{}: bgp did not converge'.format(router.name)          assert res is None, assertmsg 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);  | 
