diff options
| author | Jakub Urbańczyk <xthaid@gmail.com> | 2020-07-15 15:11:21 +0200 | 
|---|---|---|
| committer | Jakub Urbańczyk <xthaid@gmail.com> | 2020-08-10 21:32:59 +0200 | 
| commit | fef24b03399d26808bd57af8e318b0e818c7ffef (patch) | |
| tree | 66b2cc5e6b679362653ae59d9bb3361090061070 | |
| parent | 271ac28499e6be25a1c42b9ea138e782548893f6 (diff) | |
zebra: prepare dplane for batching
Extend kernel interface to allow the data plane to send many kernel
updates at once.
Signed-off-by: Jakub Urbańczyk <xthaid@gmail.com>
| -rw-r--r-- | zebra/kernel_netlink.c | 10 | ||||
| -rw-r--r-- | zebra/kernel_socket.c | 10 | ||||
| -rw-r--r-- | zebra/rt.h | 6 | ||||
| -rw-r--r-- | zebra/rt_netlink.c | 13 | ||||
| -rw-r--r-- | zebra/rt_socket.c | 14 | ||||
| -rw-r--r-- | zebra/zebra_dplane.c | 284 | 
6 files changed, 159 insertions, 178 deletions
diff --git a/zebra/kernel_netlink.c b/zebra/kernel_netlink.c index a4d22c12a4..b35ed9df43 100644 --- a/zebra/kernel_netlink.c +++ b/zebra/kernel_netlink.c @@ -1080,6 +1080,16 @@ int netlink_request(struct nlsock *nl, void *req)  	return 0;  } +void kernel_update_multi(struct dplane_ctx_q *ctx_list) +{ +	/* no-op */ +} + +bool kernel_supports_batch(void) +{ +	return false; +} +  /* Exported interface function.  This function simply calls     netlink_socket (). */  void kernel_init(struct zebra_ns *zns) diff --git a/zebra/kernel_socket.c b/zebra/kernel_socket.c index 873d221149..896926bcbe 100644 --- a/zebra/kernel_socket.c +++ b/zebra/kernel_socket.c @@ -1464,4 +1464,14 @@ void kernel_terminate(struct zebra_ns *zns, bool complete)  	return;  } +void kernel_update_multi(struct dplane_ctx_q *ctx_list) +{ +	/* no-op */ +} + +bool kernel_supports_batch(void) +{ +	return false; +} +  #endif /* !HAVE_NETLINK */ diff --git a/zebra/rt.h b/zebra/rt.h index 143e16b3ea..c0ff2e22b3 100644 --- a/zebra/rt.h +++ b/zebra/rt.h @@ -97,6 +97,12 @@ extern int kernel_upd_mac_nhg(uint32_t nhg_id, uint32_t nh_cnt,  		struct nh_grp *nh_ids);  extern int kernel_del_mac_nhg(uint32_t nhg_id); +/* + * Message batching interface. + */ +extern void kernel_update_multi(struct dplane_ctx_q *ctx_list); +extern bool kernel_supports_batch(void); +  #ifdef __cplusplus  }  #endif diff --git a/zebra/rt_netlink.c b/zebra/rt_netlink.c index ea15de6bdb..70c34252f4 100644 --- a/zebra/rt_netlink.c +++ b/zebra/rt_netlink.c @@ -2352,19 +2352,6 @@ enum zebra_dplane_result kernel_route_update(struct zebra_dplane_ctx *ctx)  	} else  		ret = 0; -	if ((cmd == RTM_NEWROUTE) && (ret == 0)) { -		/* Update installed nexthops to signal which have been -		 * installed. -		 */ -		for (ALL_NEXTHOPS_PTR(dplane_ctx_get_ng(ctx), nexthop)) { -			if (CHECK_FLAG(nexthop->flags, NEXTHOP_FLAG_RECURSIVE)) -				continue; - -			if (CHECK_FLAG(nexthop->flags, NEXTHOP_FLAG_ACTIVE)) { -				SET_FLAG(nexthop->flags, NEXTHOP_FLAG_FIB); -			} -		} -	}  	return (ret == 0 ?  		ZEBRA_DPLANE_REQUEST_SUCCESS : ZEBRA_DPLANE_REQUEST_FAILURE); diff --git a/zebra/rt_socket.c b/zebra/rt_socket.c index 0271dc7f41..a2e15cbd2b 100644 --- a/zebra/rt_socket.c +++ b/zebra/rt_socket.c @@ -358,20 +358,6 @@ enum zebra_dplane_result kernel_route_update(struct zebra_dplane_ctx *ctx)  		}  	} /* Elevated privs */ -	if (RSYSTEM_ROUTE(type) -	    && dplane_ctx_get_op(ctx) != DPLANE_OP_ROUTE_DELETE) { -		struct nexthop *nexthop; - -		for (ALL_NEXTHOPS_PTR(dplane_ctx_get_ng(ctx), nexthop)) { -			if (CHECK_FLAG(nexthop->flags, NEXTHOP_FLAG_RECURSIVE)) -				continue; - -			if (CHECK_FLAG(nexthop->flags, NEXTHOP_FLAG_ACTIVE)) { -				SET_FLAG(nexthop->flags, NEXTHOP_FLAG_FIB); -			} -		} -	} -  	return res;  } diff --git a/zebra/zebra_dplane.c b/zebra/zebra_dplane.c index 5dcf76db15..7d060943f1 100644 --- a/zebra/zebra_dplane.c +++ b/zebra/zebra_dplane.c @@ -3717,149 +3717,99 @@ void dplane_provider_enqueue_to_zebra(struct zebra_dplane_ctx *ctx)   * Kernel dataplane provider   */ -/* - * Handler for kernel LSP updates - */ -static enum zebra_dplane_result -kernel_dplane_lsp_update(struct zebra_dplane_ctx *ctx) -{ -	return kernel_lsp_update(ctx); -} - -/* - * Handler for kernel pseudowire updates - */ -static enum zebra_dplane_result -kernel_dplane_pw_update(struct zebra_dplane_ctx *ctx) +static void kernel_dplane_log_detail(struct zebra_dplane_ctx *ctx)  { -	if (IS_ZEBRA_DEBUG_DPLANE_DETAIL) -		zlog_debug("Dplane pw %s: op %s af %d loc: %u rem: %u", -			   dplane_ctx_get_ifname(ctx), -			   dplane_op2str(ctx->zd_op), -			   dplane_ctx_get_pw_af(ctx), -			   dplane_ctx_get_pw_local_label(ctx), -			   dplane_ctx_get_pw_remote_label(ctx)); - -	return kernel_pw_update(ctx); -} +	char buf[PREFIX_STRLEN]; -/* - * Handler for kernel route updates - */ -static enum zebra_dplane_result -kernel_dplane_route_update(struct zebra_dplane_ctx *ctx) -{ -	if (IS_ZEBRA_DEBUG_DPLANE_DETAIL) { -		char dest_str[PREFIX_STRLEN]; +	switch (dplane_ctx_get_op(ctx)) { -		prefix2str(dplane_ctx_get_dest(ctx), -			   dest_str, sizeof(dest_str)); +	case DPLANE_OP_ROUTE_INSTALL: +	case DPLANE_OP_ROUTE_UPDATE: +	case DPLANE_OP_ROUTE_DELETE: +		prefix2str(dplane_ctx_get_dest(ctx), buf, sizeof(buf));  		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))); -	} - -	return kernel_route_update(ctx); -} - -/* - * Handler for kernel-facing interface address updates - */ -static enum zebra_dplane_result -kernel_dplane_address_update(struct zebra_dplane_ctx *ctx) -{ -	if (IS_ZEBRA_DEBUG_DPLANE_DETAIL) { -		char dest_str[PREFIX_STRLEN]; - -		prefix2str(dplane_ctx_get_intf_addr(ctx), dest_str, -			   sizeof(dest_str)); - -		zlog_debug("Dplane intf %s, idx %u, addr %s", -			   dplane_op2str(dplane_ctx_get_op(ctx)), -			   dplane_ctx_get_ifindex(ctx), dest_str); -	} - -	return kernel_address_update_ctx(ctx); -} +			   dplane_ctx_get_vrf(ctx), buf, ctx, +			   dplane_op2str(dplane_ctx_get_op(ctx))); +		break; -/** - * kernel_dplane_nexthop_update() - Handler for kernel nexthop updates - * - * @ctx:	Dataplane context - * - * Return:	Dataplane result flag - */ -static enum zebra_dplane_result -kernel_dplane_nexthop_update(struct zebra_dplane_ctx *ctx) -{ -	if (IS_ZEBRA_DEBUG_DPLANE_DETAIL) { +	case DPLANE_OP_NH_INSTALL: +	case DPLANE_OP_NH_UPDATE: +	case DPLANE_OP_NH_DELETE:  		zlog_debug("ID (%u) Dplane nexthop update ctx %p op %s",  			   dplane_ctx_get_nhe_id(ctx), ctx,  			   dplane_op2str(dplane_ctx_get_op(ctx))); -	} +		break; -	return kernel_nexthop_update(ctx); -} +	case DPLANE_OP_LSP_INSTALL: +	case DPLANE_OP_LSP_UPDATE: +	case DPLANE_OP_LSP_DELETE: +		break; -/* - * Handler for kernel-facing EVPN MAC address updates - */ -static enum zebra_dplane_result -kernel_dplane_mac_update(struct zebra_dplane_ctx *ctx) -{ -	if (IS_ZEBRA_DEBUG_DPLANE_DETAIL) { -		char buf[ETHER_ADDR_STRLEN]; +	case DPLANE_OP_PW_INSTALL: +	case DPLANE_OP_PW_UNINSTALL: +		zlog_debug("Dplane pw %s: op %s af %d loc: %u rem: %u", +			   dplane_ctx_get_ifname(ctx), +			   dplane_op2str(ctx->zd_op), dplane_ctx_get_pw_af(ctx), +			   dplane_ctx_get_pw_local_label(ctx), +			   dplane_ctx_get_pw_remote_label(ctx)); +		break; + +	case DPLANE_OP_ADDR_INSTALL: +	case DPLANE_OP_ADDR_UNINSTALL: +		prefix2str(dplane_ctx_get_intf_addr(ctx), buf, sizeof(buf)); + +		zlog_debug("Dplane intf %s, idx %u, addr %s", +			   dplane_op2str(dplane_ctx_get_op(ctx)), +			   dplane_ctx_get_ifindex(ctx), buf); +		break; +	case DPLANE_OP_MAC_INSTALL: +	case DPLANE_OP_MAC_DELETE:  		prefix_mac2str(dplane_ctx_mac_get_addr(ctx), buf,  			       sizeof(buf));  		zlog_debug("Dplane %s, mac %s, ifindex %u",  			   dplane_op2str(dplane_ctx_get_op(ctx)),  			   buf, dplane_ctx_get_ifindex(ctx)); -	} - -	return kernel_mac_update_ctx(ctx); -} - -/* - * Handler for kernel-facing EVPN neighbor updates - */ -static enum zebra_dplane_result -kernel_dplane_neigh_update(struct zebra_dplane_ctx *ctx) -{ -	if (IS_ZEBRA_DEBUG_DPLANE_DETAIL) { -		char buf[PREFIX_STRLEN]; +		break; +	case DPLANE_OP_NEIGH_INSTALL: +	case DPLANE_OP_NEIGH_UPDATE: +	case DPLANE_OP_NEIGH_DELETE: +	case DPLANE_OP_VTEP_ADD: +	case DPLANE_OP_VTEP_DELETE:  		ipaddr2str(dplane_ctx_neigh_get_ipaddr(ctx), buf,  			   sizeof(buf));  		zlog_debug("Dplane %s, ip %s, ifindex %u",  			   dplane_op2str(dplane_ctx_get_op(ctx)),  			   buf, dplane_ctx_get_ifindex(ctx)); -	} - -	return kernel_neigh_update_ctx(ctx); -} +		break; -/* - *  Handler for kernel PBR rule updates - */ -static enum zebra_dplane_result -kernel_dplane_rule_update(struct zebra_dplane_ctx *ctx) -{ -	if (IS_ZEBRA_DEBUG_DPLANE_DETAIL) +	case DPLANE_OP_RULE_ADD: +	case DPLANE_OP_RULE_DELETE: +	case DPLANE_OP_RULE_UPDATE:  		zlog_debug("Dplane rule update op %s, if %s(%u), ctx %p",  			   dplane_op2str(dplane_ctx_get_op(ctx)),  			   dplane_ctx_get_ifname(ctx),  			   dplane_ctx_get_ifindex(ctx), ctx); +		break; -	return kernel_pbr_rule_update(ctx); +	case DPLANE_OP_SYS_ROUTE_ADD: +	case DPLANE_OP_SYS_ROUTE_DELETE: +	case DPLANE_OP_ROUTE_NOTIFY: +	case DPLANE_OP_LSP_NOTIFY: + +	case DPLANE_OP_NONE: +		break; +	}  } -static void kernel_dplane_handle_result(struct zebra_dplane_ctx *ctx, -					enum zebra_dplane_result res) +static void kernel_dplane_handle_result(struct zebra_dplane_ctx *ctx)  { +	enum zebra_dplane_result res = dplane_ctx_get_status(ctx); +  	switch (dplane_ctx_get_op(ctx)) {  	case DPLANE_OP_ROUTE_INSTALL: @@ -3868,6 +3818,27 @@ static void kernel_dplane_handle_result(struct zebra_dplane_ctx *ctx,  		if (res != ZEBRA_DPLANE_REQUEST_SUCCESS)  			atomic_fetch_add_explicit(&zdplane_info.dg_route_errors,  						  1, memory_order_relaxed); + +		if ((dplane_ctx_get_op(ctx) != DPLANE_OP_ROUTE_DELETE) +		    && (res == ZEBRA_DPLANE_REQUEST_SUCCESS)) { +			struct nexthop *nexthop; + +			/* Update installed nexthops to signal which have been +			 * installed. +			 */ +			for (ALL_NEXTHOPS_PTR(dplane_ctx_get_ng(ctx), +					      nexthop)) { +				if (CHECK_FLAG(nexthop->flags, +					       NEXTHOP_FLAG_RECURSIVE)) +					continue; + +				if (CHECK_FLAG(nexthop->flags, +					       NEXTHOP_FLAG_ACTIVE)) { +					SET_FLAG(nexthop->flags, +						 NEXTHOP_FLAG_FIB); +				} +			} +		}  		break;  	case DPLANE_OP_NH_INSTALL: @@ -3932,38 +3903,24 @@ static void kernel_dplane_handle_result(struct zebra_dplane_ctx *ctx,  	case DPLANE_OP_SYS_ROUTE_DELETE:  	case DPLANE_OP_ROUTE_NOTIFY:  	case DPLANE_OP_LSP_NOTIFY: +		break; +  	case DPLANE_OP_NONE: +		if (res != ZEBRA_DPLANE_REQUEST_SUCCESS) +			atomic_fetch_add_explicit(&zdplane_info.dg_other_errors, +						  1, memory_order_relaxed);  		break;  	} - -	dplane_ctx_set_status(ctx, res);  } -/* - * Kernel provider callback - */ -static int kernel_dplane_process_func(struct zebra_dplane_provider *prov) +static void kernel_dplane_dispatch_updates(struct dplane_ctx_q *ctx_list)  {  	enum zebra_dplane_result res; -	struct zebra_dplane_ctx *ctx, *tctx; -	struct dplane_ctx_q work_list; -	int counter, limit; - -	TAILQ_INIT(&work_list); - -	limit = dplane_provider_get_work_limit(prov); - -	if (IS_ZEBRA_DEBUG_DPLANE_DETAIL) -		zlog_debug("dplane provider '%s': processing", -			   dplane_provider_get_name(prov)); - -	for (counter = 0; counter < limit; counter++) { - -		ctx = dplane_provider_dequeue_in_ctx(prov); -		if (ctx == NULL) -			break; +	struct zebra_dplane_ctx *ctx; -		/* A previous provider plugin may have asked to skip the +	TAILQ_FOREACH (ctx, ctx_list, zd_q_entries) { +		/* +		 * A previous provider plugin may have asked to skip the  		 * kernel update.  		 */  		if (dplane_ctx_is_skip_kernel(ctx)) { @@ -3977,34 +3934,34 @@ static int kernel_dplane_process_func(struct zebra_dplane_provider *prov)  		case DPLANE_OP_ROUTE_INSTALL:  		case DPLANE_OP_ROUTE_UPDATE:  		case DPLANE_OP_ROUTE_DELETE: -			res = kernel_dplane_route_update(ctx); +			res = kernel_route_update(ctx);  			break;  		case DPLANE_OP_NH_INSTALL:  		case DPLANE_OP_NH_UPDATE:  		case DPLANE_OP_NH_DELETE: -			res = kernel_dplane_nexthop_update(ctx); +			res = kernel_nexthop_update(ctx);  			break;  		case DPLANE_OP_LSP_INSTALL:  		case DPLANE_OP_LSP_UPDATE:  		case DPLANE_OP_LSP_DELETE: -			res = kernel_dplane_lsp_update(ctx); +			res = kernel_lsp_update(ctx);  			break;  		case DPLANE_OP_PW_INSTALL:  		case DPLANE_OP_PW_UNINSTALL: -			res = kernel_dplane_pw_update(ctx); +			res = kernel_pw_update(ctx);  			break;  		case DPLANE_OP_ADDR_INSTALL:  		case DPLANE_OP_ADDR_UNINSTALL: -			res = kernel_dplane_address_update(ctx); +			res = kernel_address_update_ctx(ctx);  			break;  		case DPLANE_OP_MAC_INSTALL:  		case DPLANE_OP_MAC_DELETE: -			res = kernel_dplane_mac_update(ctx); +			res = kernel_mac_update_ctx(ctx);  			break;  		case DPLANE_OP_NEIGH_INSTALL: @@ -4012,13 +3969,13 @@ static int kernel_dplane_process_func(struct zebra_dplane_provider *prov)  		case DPLANE_OP_NEIGH_DELETE:  		case DPLANE_OP_VTEP_ADD:  		case DPLANE_OP_VTEP_DELETE: -			res = kernel_dplane_neigh_update(ctx); +			res = kernel_neigh_update_ctx(ctx);  			break;  		case DPLANE_OP_RULE_ADD:  		case DPLANE_OP_RULE_DELETE:  		case DPLANE_OP_RULE_UPDATE: -			res = kernel_dplane_rule_update(ctx); +			res = kernel_pbr_rule_update(ctx);  			break;  		/* Ignore 'notifications' - no-op */ @@ -4030,25 +3987,51 @@ static int kernel_dplane_process_func(struct zebra_dplane_provider *prov)  			break;  		default: -			atomic_fetch_add_explicit( -				&zdplane_info.dg_other_errors, 1, -				memory_order_relaxed); -  			res = ZEBRA_DPLANE_REQUEST_FAILURE;  			break;  		}  	skip_one: -		/* If the request isn't pending, we can handle the result right -		 * away. -		 */ -		if (res != ZEBRA_DPLANE_REQUEST_PENDING) -			kernel_dplane_handle_result(ctx, res); +		dplane_ctx_set_status(ctx, res); +	} +} + +/* + * Kernel provider callback + */ +static int kernel_dplane_process_func(struct zebra_dplane_provider *prov) +{ +	struct zebra_dplane_ctx *ctx, *tctx; +	struct dplane_ctx_q work_list; +	int counter, limit; + +	TAILQ_INIT(&work_list); + +	limit = dplane_provider_get_work_limit(prov); + +	if (IS_ZEBRA_DEBUG_DPLANE_DETAIL) +		zlog_debug("dplane provider '%s': processing", +			   dplane_provider_get_name(prov)); + +	for (counter = 0; counter < limit; counter++) { +		ctx = dplane_provider_dequeue_in_ctx(prov); +		if (ctx == NULL) +			break; + +		if (IS_ZEBRA_DEBUG_DPLANE_DETAIL) +			kernel_dplane_log_detail(ctx);  		TAILQ_INSERT_TAIL(&work_list, ctx, zd_q_entries);  	} +	if (kernel_supports_batch()) +		kernel_update_multi(&work_list); +	else +		kernel_dplane_dispatch_updates(&work_list); +  	TAILQ_FOREACH_SAFE (ctx, &work_list, zd_q_entries, tctx) { +		kernel_dplane_handle_result(ctx); +  		TAILQ_REMOVE(&work_list, ctx, zd_q_entries);  		dplane_provider_enqueue_out_ctx(prov, ctx);  	} @@ -4093,7 +4076,6 @@ static int test_dplane_process_func(struct zebra_dplane_provider *prov)  	limit = dplane_provider_get_work_limit(prov);  	for (counter = 0; counter < limit; counter++) { -  		ctx = dplane_provider_dequeue_in_ctx(prov);  		if (ctx == NULL)  			break;  | 
