diff options
Diffstat (limited to 'bgpd/bgp_zebra.c')
| -rw-r--r-- | bgpd/bgp_zebra.c | 522 | 
1 files changed, 277 insertions, 245 deletions
diff --git a/bgpd/bgp_zebra.c b/bgpd/bgp_zebra.c index 1965cd2704..a04d54fa92 100644 --- a/bgpd/bgp_zebra.c +++ b/bgpd/bgp_zebra.c @@ -1,6 +1,7 @@  // SPDX-License-Identifier: GPL-2.0-or-later  /* zebra client   * Copyright (C) 1997, 98, 99 Kunihiro Ishiguro + * Copyright (c) 2023 LabN Consulting, L.L.C.   */  #include <zebra.h> @@ -55,6 +56,8 @@  /* All information about zebra. */  struct zclient *zclient = NULL; +struct zclient *zclient_sync; +static bool bgp_zebra_label_manager_connect(void);  /* hook to indicate vrf status change for SNMP */  DEFINE_HOOK(bgp_vrf_status_changed, (struct bgp *bgp, struct interface *ifp), @@ -137,11 +140,11 @@ static void bgp_start_interface_nbrs(struct bgp *bgp, struct interface *ifp)  	struct peer *peer;  	for (ALL_LIST_ELEMENTS(bgp->peer, node, nnode, peer)) { -		if (peer->conf_if && (strcmp(peer->conf_if, ifp->name) == 0) -		    && !peer_established(peer)) { +		if (peer->conf_if && (strcmp(peer->conf_if, ifp->name) == 0) && +		    !peer_established(peer->connection)) {  			if (peer_active(peer)) -				BGP_EVENT_ADD(peer, BGP_Stop); -			BGP_EVENT_ADD(peer, BGP_Start); +				BGP_EVENT_ADD(peer->connection, BGP_Stop); +			BGP_EVENT_ADD(peer->connection, BGP_Start);  		}  	}  } @@ -180,7 +183,7 @@ static void bgp_nbr_connected_delete(struct bgp *bgp, struct nbr_connected *ifc,  		if (peer->conf_if  		    && (strcmp(peer->conf_if, ifc->ifp->name) == 0)) {  			peer->last_reset = PEER_DOWN_NBR_ADDR_DEL; -			BGP_EVENT_ADD(peer, BGP_Stop); +			BGP_EVENT_ADD(peer->connection, BGP_Stop);  		}  	}  	/* Free neighbor also, if we're asked to. */ @@ -276,7 +279,7 @@ static int bgp_ifp_down(struct interface *ifp)  				continue;  			if (ifp == peer->nexthop.ifp) { -				BGP_EVENT_ADD(peer, BGP_Stop); +				BGP_EVENT_ADD(peer->connection, BGP_Stop);  				peer->last_reset = PEER_DOWN_IF_DOWN;  			}  		} @@ -474,65 +477,6 @@ static int bgp_interface_nbr_address_delete(ZAPI_CALLBACK_ARGS)  	return 0;  } -/* VRF update for an interface. */ -static int bgp_interface_vrf_update(ZAPI_CALLBACK_ARGS) -{ -	struct interface *ifp; -	vrf_id_t new_vrf_id; -	struct connected *c; -	struct nbr_connected *nc; -	struct listnode *node, *nnode; -	struct bgp *bgp; -	struct peer *peer; - -	ifp = zebra_interface_vrf_update_read(zclient->ibuf, vrf_id, -					      &new_vrf_id); -	if (!ifp) -		return 0; - -	if (BGP_DEBUG(zebra, ZEBRA)) -		zlog_debug("Rx Intf VRF change VRF %u IF %s NewVRF %u", vrf_id, -			   ifp->name, new_vrf_id); - -	bgp = bgp_lookup_by_vrf_id(vrf_id); - -	if (bgp) { -		for (ALL_LIST_ELEMENTS(ifp->connected, node, nnode, c)) -			bgp_connected_delete(bgp, c); - -		for (ALL_LIST_ELEMENTS(ifp->nbr_connected, node, nnode, nc)) -			bgp_nbr_connected_delete(bgp, nc, 1); - -		/* Fast external-failover */ -		if (!CHECK_FLAG(bgp->flags, BGP_FLAG_NO_FAST_EXT_FAILOVER)) { -			for (ALL_LIST_ELEMENTS(bgp->peer, node, nnode, peer)) { -				if ((peer->ttl != BGP_DEFAULT_TTL) -				    && (peer->gtsm_hops -					!= BGP_GTSM_HOPS_CONNECTED)) -					continue; - -				if (ifp == peer->nexthop.ifp) -					BGP_EVENT_ADD(peer, BGP_Stop); -			} -		} -	} - -	if_update_to_new_vrf(ifp, new_vrf_id); - -	bgp = bgp_lookup_by_vrf_id(new_vrf_id); -	if (!bgp) -		return 0; - -	for (ALL_LIST_ELEMENTS(ifp->connected, node, nnode, c)) -		bgp_connected_add(bgp, c); - -	for (ALL_LIST_ELEMENTS(ifp->nbr_connected, node, nnode, nc)) -		bgp_nbr_connected_add(bgp, nc); - -	hook_call(bgp_vrf_status_changed, bgp, ifp); -	return 0; -} -  /* Zebra route add and delete treatment. */  static int zebra_read_route(ZAPI_CALLBACK_ARGS)  { @@ -1073,14 +1017,17 @@ static void bgp_zebra_tm_connect(struct event *t)  		ret = tm_table_manager_connect(zclient);  	}  	if (ret < 0) { -		zlog_info("Error connecting to table manager!"); +		zlog_err("Error connecting to table manager!");  		bgp_tm_status_connected = false;  	} else { -		if (!bgp_tm_status_connected) -			zlog_debug("Connecting to table manager. Success"); +		if (!bgp_tm_status_connected) { +			if (BGP_DEBUG(zebra, ZEBRA)) +				zlog_debug( +					"Connecting to table manager. Success"); +		}  		bgp_tm_status_connected = true;  		if (!bgp_tm_chunk_obtained) { -			if (bgp_zebra_get_table_range(bgp_tm_chunk_size, +			if (bgp_zebra_get_table_range(zclient, bgp_tm_chunk_size,  						      &bgp_tm_min,  						      &bgp_tm_max) >= 0) {  				bgp_tm_chunk_obtained = true; @@ -1120,18 +1067,18 @@ void bgp_zebra_init_tm_connect(struct bgp *bgp)  	bgp_tm_min = bgp_tm_max = 0;  	bgp_tm_chunk_size = BGP_FLOWSPEC_TABLE_CHUNK;  	bgp_tm_bgp = bgp; -	event_add_timer(bm->master, bgp_zebra_tm_connect, zclient, delay, +	event_add_timer(bm->master, bgp_zebra_tm_connect, zclient_sync, delay,  			&bgp_tm_thread_connect);  } -int bgp_zebra_get_table_range(uint32_t chunk_size, +int bgp_zebra_get_table_range(struct zclient *zc, uint32_t chunk_size,  			      uint32_t *start, uint32_t *end)  {  	int ret;  	if (!bgp_tm_status_connected)  		return -1; -	ret = tm_get_table_chunk(zclient, chunk_size, start, end); +	ret = tm_get_table_chunk(zc, chunk_size, start, end);  	if (ret < 0) {  		flog_err(EC_BGP_TABLE_CHUNK,  			 "BGP: Error getting table chunk %u", chunk_size); @@ -1302,7 +1249,6 @@ void bgp_zebra_announce(struct bgp_dest *dest, const struct prefix *p,  	struct bgp_path_info local_info;  	struct bgp_path_info *mpinfo_cp = &local_info;  	route_tag_t tag; -	struct bgp_sid_info *sid_info;  	mpls_label_t *labels;  	uint32_t num_labels = 0;  	mpls_label_t nh_label; @@ -1316,6 +1262,10 @@ void bgp_zebra_announce(struct bgp_dest *dest, const struct prefix *p,  	uint32_t bos = 0;  	uint32_t exp = 0; +	if (afi == AFI_LINKSTATE) +		/* nothing to install */ +		return; +  	/*  	 * BGP is installing this route and bgp has been configured  	 * to suppress announcements until the route has been installed @@ -1342,7 +1292,8 @@ void bgp_zebra_announce(struct bgp_dest *dest, const struct prefix *p,  	/*  	 * vrf leaking support (will have only one nexthop)  	 */ -	if (info->extra && info->extra->bgp_orig) +	if (info->extra && info->extra->vrfleak && +	    info->extra->vrfleak->bgp_orig)  		nh_othervrf = 1;  	/* Make Zebra API structure. */ @@ -1358,8 +1309,10 @@ void bgp_zebra_announce(struct bgp_dest *dest, const struct prefix *p,  	    && info->sub_type == BGP_ROUTE_IMPORTED) {  		/* Obtain peer from parent */ -		if (info->extra && info->extra->parent) -			peer = ((struct bgp_path_info *)(info->extra->parent)) +		if (info->extra && info->extra->vrfleak && +		    info->extra->vrfleak->parent) +			peer = ((struct bgp_path_info *)(info->extra->vrfleak +								 ->parent))  				       ->peer;  	} @@ -1440,7 +1393,7 @@ void bgp_zebra_announce(struct bgp_dest *dest, const struct prefix *p,  		if (CHECK_FLAG(info->attr->flag,  			       ATTR_FLAG_BIT(BGP_ATTR_SRTE_COLOR))) -			api_nh->srte_color = info->attr->srte_color; +			api_nh->srte_color = bgp_attr_get_color(info->attr);  		if (bgp_debug_zebra(&api.prefix)) {  			if (mpinfo->extra) { @@ -1547,15 +1500,21 @@ void bgp_zebra_announce(struct bgp_dest *dest, const struct prefix *p,  		api_nh->weight = nh_weight; -		if (mpinfo->extra && !is_evpn && -		    bgp_is_valid_label(&labels[0]) && -		    !sid_zero(&mpinfo->extra->sid[0].sid)) { -			sid_info = &mpinfo->extra->sid[0]; - -			memcpy(&api_nh->seg6_segs, &sid_info->sid, -			       sizeof(api_nh->seg6_segs)); - -			if (sid_info->transposition_len != 0) { +		if (((mpinfo->attr->srv6_l3vpn && +		      !sid_zero_ipv6(&mpinfo->attr->srv6_l3vpn->sid)) || +		     (mpinfo->attr->srv6_vpn && +		      !sid_zero_ipv6(&mpinfo->attr->srv6_vpn->sid))) && +		    !is_evpn && bgp_is_valid_label(&labels[0])) { +			struct in6_addr *sid_tmp = +				mpinfo->attr->srv6_l3vpn +					? (&mpinfo->attr->srv6_l3vpn->sid) +					: (&mpinfo->attr->srv6_vpn->sid); + +			memcpy(&api_nh->seg6_segs[0], sid_tmp, +			       sizeof(api_nh->seg6_segs[0])); + +			if (mpinfo->attr->srv6_l3vpn && +			    mpinfo->attr->srv6_l3vpn->transposition_len != 0) {  				mpls_lse_decode(labels[0], &nh_label, &ttl,  						&exp, &bos); @@ -1566,11 +1525,14 @@ void bgp_zebra_announce(struct bgp_dest *dest, const struct prefix *p,  					continue;  				} -				transpose_sid(&api_nh->seg6_segs, nh_label, -					      sid_info->transposition_offset, -					      sid_info->transposition_len); +				transpose_sid(&api_nh->seg6_segs[0], nh_label, +					      mpinfo->attr->srv6_l3vpn +						      ->transposition_offset, +					      mpinfo->attr->srv6_l3vpn +						      ->transposition_len);  			} +			api_nh->seg_num = 1;  			SET_FLAG(api_nh->flags, ZAPI_NEXTHOP_FLAG_SEG6);  		} @@ -1687,7 +1649,7 @@ void bgp_zebra_announce(struct bgp_dest *dest, const struct prefix *p,  			if (CHECK_FLAG(api_nh->flags, ZAPI_NEXTHOP_FLAG_SEG6) &&  			    !CHECK_FLAG(api_nh->flags,  					ZAPI_NEXTHOP_FLAG_EVPN)) { -				inet_ntop(AF_INET6, &api_nh->seg6_segs, +				inet_ntop(AF_INET6, &api_nh->seg6_segs[0],  					  sid_buf, sizeof(sid_buf));  				snprintf(segs_buf, sizeof(segs_buf), "segs %s",  					 sid_buf); @@ -1909,7 +1871,7 @@ int bgp_redistribute_set(struct bgp *bgp, afi_t afi, int type,  		redist_add_instance(&zclient->mi_redist[afi][type], instance);  	} else { -		if (vrf_bitmap_check(zclient->redist[afi][type], bgp->vrf_id)) +		if (vrf_bitmap_check(&zclient->redist[afi][type], bgp->vrf_id))  			return CMD_WARNING;  #ifdef ENABLE_BGP_VNC @@ -1919,7 +1881,7 @@ int bgp_redistribute_set(struct bgp *bgp, afi_t afi, int type,  		}  #endif -		vrf_bitmap_set(zclient->redist[afi][type], bgp->vrf_id); +		vrf_bitmap_set(&zclient->redist[afi][type], bgp->vrf_id);  	}  	/* @@ -2040,9 +2002,9 @@ int bgp_redistribute_unreg(struct bgp *bgp, afi_t afi, int type,  			return CMD_WARNING;  		redist_del_instance(&zclient->mi_redist[afi][type], instance);  	} else { -		if (!vrf_bitmap_check(zclient->redist[afi][type], bgp->vrf_id)) +		if (!vrf_bitmap_check(&zclient->redist[afi][type], bgp->vrf_id))  			return CMD_WARNING; -		vrf_bitmap_unset(zclient->redist[afi][type], bgp->vrf_id); +		vrf_bitmap_unset(&zclient->redist[afi][type], bgp->vrf_id);  	}  	if (bgp_install_info_to_zebra(bgp)) { @@ -2062,8 +2024,8 @@ int bgp_redistribute_unreg(struct bgp *bgp, afi_t afi, int type,  }  /* Unset redistribution.  */ -int bgp_redistribute_unset(struct bgp *bgp, afi_t afi, int type, -			   unsigned short instance) +static void _bgp_redistribute_unset(struct bgp *bgp, afi_t afi, int type, +				    unsigned short instance)  {  	struct bgp_redist *red; @@ -2080,7 +2042,7 @@ int bgp_redistribute_unset(struct bgp *bgp, afi_t afi, int type,  	red = bgp_redist_lookup(bgp, afi, type, instance);  	if (!red) -		return CMD_SUCCESS; +		return;  	bgp_redistribute_unreg(bgp, afi, type, instance); @@ -2094,8 +2056,23 @@ int bgp_redistribute_unset(struct bgp *bgp, afi_t afi, int type,  	red->redist_metric = 0;  	bgp_redist_del(bgp, afi, type, instance); +} -	return CMD_SUCCESS; +void bgp_redistribute_unset(struct bgp *bgp, afi_t afi, int type, +			    unsigned short instance) +{ +	struct listnode *node, *nnode; +	struct bgp_redist *red; + +	if (type != ZEBRA_ROUTE_TABLE || instance != 0) +		return _bgp_redistribute_unset(bgp, afi, type, instance); + +	/* walk over instance */ +	if (!bgp->redist[afi][type]) +		return; + +	for (ALL_LIST_ELEMENTS(bgp->redist[afi][type], node, nnode, red)) +		_bgp_redistribute_unset(bgp, afi, type, red->instance);  }  void bgp_redistribute_redo(struct bgp *bgp) @@ -2430,8 +2407,14 @@ static int rule_notify_owner(ZAPI_CALLBACK_ARGS)  			/* link bgp_info to bgp_pbr */  			path = (struct bgp_path_info *)bgp_pbr->path;  			extra = bgp_path_info_extra_get(path); -			listnode_add_force(&extra->bgp_fs_iprule, -					   bgp_pbr); +			if (!extra->flowspec) { +				extra->flowspec = +					XCALLOC(MTYPE_BGP_ROUTE_EXTRA_FS, +						sizeof(struct bgp_path_info_extra_fs)); +				extra->flowspec->bgp_fs_iprule = NULL; +				extra->flowspec->bgp_fs_pbr = NULL; +			} +			listnode_add_force(&extra->flowspec->bgp_fs_iprule, bgp_pbr);  		}  		if (BGP_DEBUG(zebra, ZEBRA))  			zlog_debug("%s: Received RULE_INSTALLED", __func__); @@ -2533,7 +2516,14 @@ static int ipset_entry_notify_owner(ZAPI_CALLBACK_ARGS)  		/* link bgp_path_info to bpme */  		path = (struct bgp_path_info *)bgp_pbime->path;  		extra = bgp_path_info_extra_get(path); -		listnode_add_force(&extra->bgp_fs_pbr, bgp_pbime); +		if (!extra->flowspec) { +			extra->flowspec = +				XCALLOC(MTYPE_BGP_ROUTE_EXTRA_FS, +					sizeof(struct bgp_path_info_extra_fs)); +			extra->flowspec->bgp_fs_iprule = NULL; +			extra->flowspec->bgp_fs_pbr = NULL; +		} +		listnode_add_force(&extra->flowspec->bgp_fs_pbr, bgp_pbime);  		}  		break;  	case ZAPI_IPSET_ENTRY_FAIL_REMOVE: @@ -2629,7 +2619,7 @@ static int bgp_zebra_route_notify_owner(int command, struct zclient *zclient,  		UNSET_FLAG(dest->flags, BGP_NODE_FIB_INSTALL_PENDING);  		SET_FLAG(dest->flags, BGP_NODE_FIB_INSTALLED);  		if (BGP_DEBUG(zebra, ZEBRA)) -			zlog_debug("route %pRN : INSTALLED", dest); +			zlog_debug("route %pRN : INSTALLED", (void *)dest);  		/* Find the best route */  		for (pi = dest->info; pi; pi = pi->next) {  			/* Process aggregate route */ @@ -2642,7 +2632,7 @@ static int bgp_zebra_route_notify_owner(int command, struct zclient *zclient,  			group_announce_route(bgp, afi, safi, dest, new_select);  		else {  			flog_err(EC_BGP_INVALID_ROUTE, -				 "selected route %pRN not found", dest); +				 "selected route %pRN not found", (void *)dest);  			bgp_dest_unlock_node(dest);  			return -1; @@ -2655,13 +2645,13 @@ static int bgp_zebra_route_notify_owner(int command, struct zclient *zclient,  		 */  		UNSET_FLAG(dest->flags, BGP_NODE_FIB_INSTALLED);  		if (BGP_DEBUG(zebra, ZEBRA)) -			zlog_debug("route %pRN: Removed from Fib", dest); +			zlog_debug("route %pRN: Removed from Fib", (void *)dest);  		break;  	case ZAPI_ROUTE_FAIL_INSTALL:  		new_select = NULL;  		if (BGP_DEBUG(zebra, ZEBRA))  			zlog_debug("route: %pRN Failed to Install into Fib", -				   dest); +				   (void *)dest);  		UNSET_FLAG(dest->flags, BGP_NODE_FIB_INSTALL_PENDING);  		UNSET_FLAG(dest->flags, BGP_NODE_FIB_INSTALLED);  		for (pi = bgp_dest_get_bgp_path_info(dest); pi; pi = pi->next) { @@ -2675,7 +2665,7 @@ static int bgp_zebra_route_notify_owner(int command, struct zclient *zclient,  	case ZAPI_ROUTE_BETTER_ADMIN_WON:  		if (BGP_DEBUG(zebra, ZEBRA))  			zlog_debug("route: %pRN removed due to better admin won", -				   dest); +				   (void *)dest);  		new_select = NULL;  		UNSET_FLAG(dest->flags, BGP_NODE_FIB_INSTALL_PENDING);  		UNSET_FLAG(dest->flags, BGP_NODE_FIB_INSTALLED); @@ -2690,7 +2680,7 @@ static int bgp_zebra_route_notify_owner(int command, struct zclient *zclient,  		break;  	case ZAPI_ROUTE_REMOVE_FAIL:  		zlog_warn("%s: Route %pRN failure to remove", -			  __func__, dest); +			  __func__, (void *)dest);  		break;  	} @@ -2706,17 +2696,20 @@ static void bgp_encode_pbr_rule_action(struct stream *s,  				       struct bgp_pbr_action *pbra,  				       struct bgp_pbr_rule *pbr)  { -	struct prefix pfx;  	uint8_t fam = AF_INET; -	char ifname[INTERFACE_NAMSIZ]; +	struct pbr_rule r;  	if (pbra->nh.type == NEXTHOP_TYPE_IPV6)  		fam = AF_INET6; -	stream_putl(s, 0); /* seqno unused */ + +	/* +	 * Convert to canonical form +	 */ +	memset(&r, 0, sizeof(r)); +	/* r.seq unused */  	if (pbr) -		stream_putl(s, pbr->priority); -	else -		stream_putl(s, 0); +		r.priority = pbr->priority; +  	/* ruleno unused - priority change  	 * ruleno permits distinguishing various FS PBR entries  	 * - FS PBR entries based on ipset/iptables @@ -2724,49 +2717,38 @@ static void bgp_encode_pbr_rule_action(struct stream *s,  	 * the latter may contain default routing information injected by FS  	 */  	if (pbr) -		stream_putl(s, pbr->unique); +		r.unique = pbr->unique;  	else -		stream_putl(s, pbra->unique); -	stream_putc(s, 0); /* ip protocol being used */ -	if (pbr && pbr->flags & MATCH_IP_SRC_SET) -		memcpy(&pfx, &(pbr->src), sizeof(struct prefix)); -	else { -		memset(&pfx, 0, sizeof(pfx)); -		pfx.family = fam; -	} -	stream_putc(s, pfx.family); -	stream_putc(s, pfx.prefixlen); -	stream_put(s, &pfx.u.prefix, prefix_blen(&pfx)); +		r.unique = pbra->unique; -	stream_putw(s, 0);  /* src port */ +	r.family = fam; -	if (pbr && pbr->flags & MATCH_IP_DST_SET) -		memcpy(&pfx, &(pbr->dst), sizeof(struct prefix)); -	else { -		memset(&pfx, 0, sizeof(pfx)); -		pfx.family = fam; -	} -	stream_putc(s, pfx.family); -	stream_putc(s, pfx.prefixlen); -	stream_put(s, &pfx.u.prefix, prefix_blen(&pfx)); - -	stream_putw(s, 0);  /* dst port */ -	stream_putc(s, 0);  /* dsfield */ -	/* if pbr present, fwmark is not used */ -	if (pbr) -		stream_putl(s, 0); -	else -		stream_putl(s, pbra->fwmark);  /* fwmark */ +	/* filter */ -	stream_putl(s, 0); /* queue id */ -	stream_putw(s, 0); /* vlan_id */ -	stream_putw(s, 0); /* vlan_flags */ -	stream_putw(s, 0); /* pcp */ +	if (pbr && pbr->flags & MATCH_IP_SRC_SET) { +		SET_FLAG(r.filter.filter_bm, PBR_FILTER_SRC_IP); +		r.filter.src_ip = pbr->src; +	} else { +		/* ??? */ +		r.filter.src_ip.family = fam; +	} +	if (pbr && pbr->flags & MATCH_IP_DST_SET) { +		SET_FLAG(r.filter.filter_bm, PBR_FILTER_DST_IP); +		r.filter.dst_ip = pbr->dst; +	} else { +		/* ??? */ +		r.filter.dst_ip.family = fam; +	} +	/* src_port, dst_port, pcp, dsfield not used */ +	if (!pbr) { +		SET_FLAG(r.filter.filter_bm, PBR_FILTER_FWMARK); +		r.filter.fwmark = pbra->fwmark; +	} -	stream_putl(s, pbra->table_id); +	SET_FLAG(r.action.flags, PBR_ACTION_TABLE); /* always valid */ +	r.action.table = pbra->table_id; -	memset(ifname, 0, sizeof(ifname)); -	stream_put(s, ifname, INTERFACE_NAMSIZ); /* ifname unused */ +	zapi_pbr_rule_encode(s, &r);  }  static void bgp_encode_pbr_ipset_match(struct stream *s, @@ -2854,9 +2836,6 @@ static void bgp_zebra_connected(struct zclient *zclient)  	bgp_zebra_instance_register(bgp); -	/* tell label pool that zebra is connected */ -	bgp_lp_event_zebra_up(); -  	/* TODO - What if we have peers and networks configured, do we have to  	 * kick-start them?  	 */ @@ -2984,9 +2963,9 @@ static int bgp_zebra_process_local_l3vni(ZAPI_CALLBACK_ARGS)  		if (BGP_DEBUG(zebra, ZEBRA))  			zlog_debug( -				"Rx L3-VNI ADD VRF %s VNI %u RMAC svi-mac %pEA vrr-mac %pEA filter %s svi-if %u", -				vrf_id_to_name(vrf_id), l3vni, &svi_rmac, -				&vrr_rmac, +				"Rx L3-VNI ADD VRF %s VNI %u Originator-IP %pI4 RMAC svi-mac %pEA vrr-mac %pEA filter %s svi-if %u", +				vrf_id_to_name(vrf_id), l3vni, &originator_ip, +				&svi_rmac, &vrr_rmac,  				filter ? "prefix-routes-only" : "none",  				svi_ifindex); @@ -3161,54 +3140,6 @@ static int bgp_zebra_process_local_ip_prefix(ZAPI_CALLBACK_ARGS)  	return 0;  } -static int bgp_zebra_process_label_chunk(ZAPI_CALLBACK_ARGS) -{ -	struct stream *s = NULL; -	uint8_t response_keep; -	uint32_t first; -	uint32_t last; -	uint8_t proto; -	unsigned short instance; - -	s = zclient->ibuf; -	STREAM_GETC(s, proto); -	STREAM_GETW(s, instance); -	STREAM_GETC(s, response_keep); -	STREAM_GETL(s, first); -	STREAM_GETL(s, last); - -	if (zclient->redist_default != proto) { -		flog_err(EC_BGP_LM_ERROR, "Got LM msg with wrong proto %u", -			 proto); -		return 0; -	} -	if (zclient->instance != instance) { -		flog_err(EC_BGP_LM_ERROR, "Got LM msg with wrong instance %u", -			 proto); -		return 0; -	} - -	if (first > last || -		first < MPLS_LABEL_UNRESERVED_MIN || -		last > MPLS_LABEL_UNRESERVED_MAX) { - -		flog_err(EC_BGP_LM_ERROR, "%s: Invalid Label chunk: %u - %u", -			 __func__, first, last); -		return 0; -	} -	if (BGP_DEBUG(zebra, ZEBRA)) { -		zlog_debug("Label Chunk assign: %u - %u (%u) ", -			first, last, response_keep); -	} - -	bgp_lp_event_chunk(response_keep, first, last); - -	return 0; - -stream_failure:		/* for STREAM_GETX */ -	return -1; -} -  extern struct zebra_privs_t bgpd_privs;  static int bgp_ifp_create(struct interface *ifp) @@ -3410,7 +3341,6 @@ static zclient_handler *const bgp_handlers[] = {  	[ZEBRA_INTERFACE_ADDRESS_DELETE] = bgp_interface_address_delete,  	[ZEBRA_INTERFACE_NBR_ADDRESS_ADD] = bgp_interface_nbr_address_add,  	[ZEBRA_INTERFACE_NBR_ADDRESS_DELETE] = bgp_interface_nbr_address_delete, -	[ZEBRA_INTERFACE_VRF_UPDATE] = bgp_interface_vrf_update,  	[ZEBRA_REDISTRIBUTE_ROUTE_ADD] = zebra_read_route,  	[ZEBRA_REDISTRIBUTE_ROUTE_DEL] = zebra_read_route,  	[ZEBRA_NEXTHOP_UPDATE] = bgp_read_nexthop_update, @@ -3427,7 +3357,6 @@ static zclient_handler *const bgp_handlers[] = {  	[ZEBRA_L3VNI_DEL] = bgp_zebra_process_local_l3vni,  	[ZEBRA_IP_PREFIX_ROUTE_ADD] = bgp_zebra_process_local_ip_prefix,  	[ZEBRA_IP_PREFIX_ROUTE_DEL] = bgp_zebra_process_local_ip_prefix, -	[ZEBRA_GET_LABEL_CHUNK] = bgp_zebra_process_label_chunk,  	[ZEBRA_RULE_NOTIFY_OWNER] = rule_notify_owner,  	[ZEBRA_IPSET_NOTIFY_OWNER] = ipset_notify_owner,  	[ZEBRA_IPSET_ENTRY_NOTIFY_OWNER] = ipset_entry_notify_owner, @@ -3464,8 +3393,62 @@ void bgp_if_init(void)  	hook_register_prio(if_del, 0, bgp_if_delete_hook);  } +static void bgp_start_label_manager(struct event *start) +{ +	bgp_zebra_label_manager_connect(); +} + +static bool bgp_zebra_label_manager_ready(void) +{ +	return (zclient_sync->sock > 0); +} + +static bool bgp_zebra_label_manager_connect(void) +{ +	/* Connect to label manager. */ +	if (zclient_socket_connect(zclient_sync) < 0) { +		zlog_warn("%s: failed connecting synchronous zclient!", +			  __func__); +		return false; +	} +	/* make socket non-blocking */ +	set_nonblocking(zclient_sync->sock); + +	/* Send hello to notify zebra this is a synchronous client */ +	if (zclient_send_hello(zclient_sync) == ZCLIENT_SEND_FAILURE) { +		zlog_warn("%s: failed sending hello for synchronous zclient!", +			  __func__); +		close(zclient_sync->sock); +		zclient_sync->sock = -1; +		return false; +	} + +	/* Connect to label manager */ +	if (lm_label_manager_connect(zclient_sync, 0) != 0) { +		zlog_warn("%s: failed connecting to label manager!", __func__); +		if (zclient_sync->sock > 0) { +			close(zclient_sync->sock); +			zclient_sync->sock = -1; +		} +		return false; +	} + +	/* tell label pool that zebra is connected */ +	bgp_lp_event_zebra_up(); + +	return true; +} + +static void bgp_zebra_capabilities(struct zclient_capabilities *cap) +{ +	bm->v6_with_v4_nexthops = cap->v6_with_v4_nexthop; +} +  void bgp_zebra_init(struct event_loop *master, unsigned short instance)  { +	struct zclient_options options = zclient_options_default; + +	options.synchronous = true;  	zclient_num_connects = 0;  	if_zapi_callbacks(bgp_ifp_create, bgp_ifp_up, @@ -3476,7 +3459,20 @@ void bgp_zebra_init(struct event_loop *master, unsigned short instance)  			      array_size(bgp_handlers));  	zclient_init(zclient, ZEBRA_ROUTE_BGP, 0, &bgpd_privs);  	zclient->zebra_connected = bgp_zebra_connected; +	zclient->zebra_capabilities = bgp_zebra_capabilities;  	zclient->instance = instance; + +	/* Initialize special zclient for synchronous message exchanges. */ +	zclient_sync = zclient_new(master, &options, NULL, 0); +	zclient_sync->sock = -1; +	zclient_sync->redist_default = ZEBRA_ROUTE_BGP; +	zclient_sync->instance = instance; +	zclient_sync->session_id = 1; +	zclient_sync->privs = &bgpd_privs; + +	if (!bgp_zebra_label_manager_ready()) +		event_add_timer(master, bgp_start_label_manager, NULL, 1, +				&bm->t_bgp_start_label_manager);  }  void bgp_zebra_destroy(void) @@ -3486,6 +3482,12 @@ void bgp_zebra_destroy(void)  	zclient_stop(zclient);  	zclient_free(zclient);  	zclient = NULL; + +	if (zclient_sync == NULL) +		return; +	zclient_stop(zclient_sync); +	zclient_free(zclient_sync); +	zclient_sync = NULL;  }  int bgp_zebra_num_connects(void) @@ -3517,11 +3519,9 @@ void bgp_send_pbr_rule_action(struct bgp_pbr_action *pbra,  	zclient_create_header(s,  			      install ? ZEBRA_RULE_ADD : ZEBRA_RULE_DELETE,  			      VRF_DEFAULT); -	stream_putl(s, 1); /* send one pbr action */  	bgp_encode_pbr_rule_action(s, pbra, pbr); -	stream_putw_at(s, 0, stream_get_endp(s));  	if ((zclient_send_message(zclient) != ZCLIENT_SEND_FAILURE)  	    && install) {  		if (!pbr) @@ -3704,38 +3704,26 @@ void bgp_zebra_announce_default(struct bgp *bgp, struct nexthop *nh,  	api.distance = ZEBRA_EBGP_DISTANCE_DEFAULT;  	SET_FLAG(api.message, ZAPI_MESSAGE_DISTANCE); +	api_nh->vrf_id = nh->vrf_id; + +	if (BGP_DEBUG(zebra, ZEBRA)) { +		struct vrf *vrf; + +		vrf = vrf_lookup_by_id(nh->vrf_id); +		zlog_debug("%s: %s default route to %pNHvv(%s) table %d", +			   bgp->name_pretty, announce ? "adding" : "withdrawing", +			   nh, VRF_LOGNAME(vrf), table_id); +	} +  	/* redirect IP */  	if (afi == AFI_IP && nh->gate.ipv4.s_addr != INADDR_ANY) { -		api_nh->vrf_id = nh->vrf_id;  		api_nh->gate.ipv4 = nh->gate.ipv4;  		api_nh->type = NEXTHOP_TYPE_IPV4; - -		if (BGP_DEBUG(zebra, ZEBRA)) -			zlog_debug( -				"BGP: %s default route to %pI4 table %d (redirect IP)", -				announce ? "adding" : "withdrawing", -				&nh->gate.ipv4, table_id); - -		zclient_route_send(announce ? ZEBRA_ROUTE_ADD -				   : ZEBRA_ROUTE_DELETE, -				   zclient, &api); -	} else if (afi == AFI_IP6 && -		   memcmp(&nh->gate.ipv6, -			  &in6addr_any, sizeof(struct in6_addr))) { -		api_nh->vrf_id = nh->vrf_id; +	} else if (afi == AFI_IP6 && memcmp(&nh->gate.ipv6, &in6addr_any, +					    sizeof(struct in6_addr))) {  		memcpy(&api_nh->gate.ipv6, &nh->gate.ipv6,  		       sizeof(struct in6_addr));  		api_nh->type = NEXTHOP_TYPE_IPV6; - -		if (BGP_DEBUG(zebra, ZEBRA)) -			zlog_debug( -				"BGP: %s default route to %pI6 table %d (redirect IP)", -				announce ? "adding" : "withdrawing", -				&nh->gate.ipv6, table_id); - -		zclient_route_send(announce ? ZEBRA_ROUTE_ADD -				   : ZEBRA_ROUTE_DELETE, -				   zclient, &api);  	} else if (nh->vrf_id != bgp->vrf_id) {  		struct vrf *vrf;  		struct interface *ifp; @@ -3749,18 +3737,12 @@ void bgp_zebra_announce_default(struct bgp *bgp, struct nexthop *nh,  		ifp = if_lookup_by_name_vrf(vrf->name, vrf);  		if (!ifp)  			return; -		api_nh->vrf_id = nh->vrf_id;  		api_nh->type = NEXTHOP_TYPE_IFINDEX;  		api_nh->ifindex = ifp->ifindex; -		if (BGP_DEBUG(zebra, ZEBRA)) -			zlog_info("BGP: %s default route to %s table %d (redirect VRF)", -				  announce ? "adding" : "withdrawing", -				  vrf->name, table_id); -		zclient_route_send(announce ? ZEBRA_ROUTE_ADD -				   : ZEBRA_ROUTE_DELETE, -				   zclient, &api); -		return;  	} + +	zclient_route_send(announce ? ZEBRA_ROUTE_ADD : ZEBRA_ROUTE_DELETE, +			   zclient, &api);  }  /* Send capabilities to RIB */ @@ -3914,10 +3896,13 @@ int bgp_zebra_srv6_manager_release_locator_chunk(const char *name)  void bgp_zebra_send_nexthop_label(int cmd, mpls_label_t label,  				  ifindex_t ifindex, vrf_id_t vrf_id, -				  enum lsp_types_t ltype, struct prefix *p) +				  enum lsp_types_t ltype, struct prefix *p, +				  uint32_t num_labels, +				  mpls_label_t out_labels[])  {  	struct zapi_labels zl = {};  	struct zapi_nexthop *znh; +	int i = 0;  	zl.type = ltype;  	zl.local_label = label; @@ -3935,8 +3920,55 @@ void bgp_zebra_send_nexthop_label(int cmd, mpls_label_t label,  						   : NEXTHOP_TYPE_IPV6_IFINDEX;  	znh->ifindex = ifindex;  	znh->vrf_id = vrf_id; -	znh->label_num = 0; - +	if (num_labels == 0) +		znh->label_num = 0; +	else { +		if (num_labels > MPLS_MAX_LABELS) +			znh->label_num = MPLS_MAX_LABELS; +		else +			znh->label_num = num_labels; +		for (i = 0; i < znh->label_num; i++) +			znh->labels[i] = out_labels[i]; +	}  	/* vrf_id is DEFAULT_VRF */  	zebra_send_mpls_labels(zclient, cmd, &zl);  } + +bool bgp_zebra_request_label_range(uint32_t base, uint32_t chunk_size) +{ +	int ret; +	uint32_t start, end; + +	if (!zclient_sync || !bgp_zebra_label_manager_ready()) +		return false; + +	ret = lm_get_label_chunk(zclient_sync, 0, base, chunk_size, &start, +				 &end); +	if (ret < 0) { +		zlog_warn("%s: error getting label range!", __func__); +		return false; +	} + +	if (start > end || start < MPLS_LABEL_UNRESERVED_MIN || +	    end > MPLS_LABEL_UNRESERVED_MAX) { +		flog_err(EC_BGP_LM_ERROR, "%s: Invalid Label chunk: %u - %u", +			 __func__, start, end); +		return false; +	} + +	bgp_lp_event_chunk(start, end); + +	return true; +} + +void bgp_zebra_release_label_range(uint32_t start, uint32_t end) +{ +	int ret; + +	if (!zclient_sync || !bgp_zebra_label_manager_ready()) +		return; + +	ret = lm_release_label_chunk(zclient_sync, start, end); +	if (ret < 0) +		zlog_warn("%s: error releasing label range!", __func__); +}  | 
