diff options
42 files changed, 545 insertions, 680 deletions
diff --git a/babeld/babel_zebra.c b/babeld/babel_zebra.c index d10d418572..d0da93e507 100644 --- a/babeld/babel_zebra.c +++ b/babeld/babel_zebra.c @@ -234,16 +234,20 @@ babel_zebra_connected (struct zclient *zclient)    zclient_send_reg_requests (zclient, VRF_DEFAULT);  } +static zclient_handler *const babel_handlers[] = { +    [ZEBRA_INTERFACE_ADDRESS_ADD] = babel_interface_address_add, +    [ZEBRA_INTERFACE_ADDRESS_DELETE] = babel_interface_address_delete, +    [ZEBRA_REDISTRIBUTE_ROUTE_ADD] = babel_zebra_read_route, +    [ZEBRA_REDISTRIBUTE_ROUTE_DEL] = babel_zebra_read_route, +}; +  void babelz_zebra_init(void)  { -    zclient = zclient_new(master, &zclient_options_default); +    zclient = zclient_new(master, &zclient_options_default, babel_handlers, +			  array_size(babel_handlers));      zclient_init(zclient, ZEBRA_ROUTE_BABEL, 0, &babeld_privs);      zclient->zebra_connected = babel_zebra_connected; -    zclient->interface_address_add = babel_interface_address_add; -    zclient->interface_address_delete = babel_interface_address_delete; -    zclient->redistribute_route_add = babel_zebra_read_route; -    zclient->redistribute_route_del = babel_zebra_read_route;      install_element(BABEL_NODE, &babel_redistribute_type_cmd);      install_element(ENABLE_NODE, &debug_babel_cmd); diff --git a/bfdd/ptm_adapter.c b/bfdd/ptm_adapter.c index 838acf450f..434d79c8f5 100644 --- a/bfdd/ptm_adapter.c +++ b/bfdd/ptm_adapter.c @@ -844,29 +844,32 @@ static int bfd_ifp_create(struct interface *ifp)  	return 0;  } -void bfdd_zclient_init(struct zebra_privs_t *bfdd_priv) -{ -	if_zapi_callbacks(bfd_ifp_create, NULL, NULL, bfd_ifp_destroy); -	zclient = zclient_new(master, &zclient_options_default); -	assert(zclient != NULL); -	zclient_init(zclient, ZEBRA_ROUTE_BFD, 0, bfdd_priv); - +static zclient_handler *const bfd_handlers[] = {  	/*  	 * We'll receive all messages through replay, however it will  	 * contain a special field with the real command inside so we  	 * avoid having to create too many handlers.  	 */ -	zclient->bfd_dest_replay = bfdd_replay; - -	/* Send replay request on zebra connect. */ -	zclient->zebra_connected = bfdd_zebra_connected; +	[ZEBRA_BFD_DEST_REPLAY] = bfdd_replay,  	/* Learn about interface VRF. */ -	zclient->interface_vrf_update = bfdd_interface_vrf_update; +	[ZEBRA_INTERFACE_VRF_UPDATE] = bfdd_interface_vrf_update,  	/* Learn about new addresses being registered. */ -	zclient->interface_address_add = bfdd_interface_address_update; -	zclient->interface_address_delete = bfdd_interface_address_update; +	[ZEBRA_INTERFACE_ADDRESS_ADD] = bfdd_interface_address_update, +	[ZEBRA_INTERFACE_ADDRESS_DELETE] = bfdd_interface_address_update, +}; + +void bfdd_zclient_init(struct zebra_privs_t *bfdd_priv) +{ +	if_zapi_callbacks(bfd_ifp_create, NULL, NULL, bfd_ifp_destroy); +	zclient = zclient_new(master, &zclient_options_default, bfd_handlers, +			      array_size(bfd_handlers)); +	assert(zclient != NULL); +	zclient_init(zclient, ZEBRA_ROUTE_BFD, 0, bfdd_priv); + +	/* Send replay request on zebra connect. */ +	zclient->zebra_connected = bfdd_zebra_connected;  }  void bfdd_zclient_register(vrf_id_t vrf_id) diff --git a/bgpd/bgp_open.c b/bgpd/bgp_open.c index f1dfebdc1b..ca8b1e398b 100644 --- a/bgpd/bgp_open.c +++ b/bgpd/bgp_open.c @@ -42,6 +42,63 @@  #include "bgpd/bgp_vty.h"  #include "bgpd/bgp_memory.h" +static const struct message capcode_str[] = { +	{CAPABILITY_CODE_MP, "MultiProtocol Extensions"}, +	{CAPABILITY_CODE_REFRESH, "Route Refresh"}, +	{CAPABILITY_CODE_ORF, "Cooperative Route Filtering"}, +	{CAPABILITY_CODE_RESTART, "Graceful Restart"}, +	{CAPABILITY_CODE_AS4, "4-octet AS number"}, +	{CAPABILITY_CODE_ADDPATH, "AddPath"}, +	{CAPABILITY_CODE_DYNAMIC, "Dynamic"}, +	{CAPABILITY_CODE_ENHE, "Extended Next Hop Encoding"}, +	{CAPABILITY_CODE_DYNAMIC_OLD, "Dynamic (Old)"}, +	{CAPABILITY_CODE_REFRESH_OLD, "Route Refresh (Old)"}, +	{CAPABILITY_CODE_ORF_OLD, "ORF (Old)"}, +	{CAPABILITY_CODE_FQDN, "FQDN"}, +	{CAPABILITY_CODE_ENHANCED_RR, "Enhanced Route Refresh"}, +	{CAPABILITY_CODE_EXT_MESSAGE, "BGP Extended Message"}, +	{0}}; + +/* Minimum sizes for length field of each cap (so not inc. the header) */ +static const size_t cap_minsizes[] = { +		[CAPABILITY_CODE_MP] = CAPABILITY_CODE_MP_LEN, +		[CAPABILITY_CODE_REFRESH] = CAPABILITY_CODE_REFRESH_LEN, +		[CAPABILITY_CODE_ORF] = CAPABILITY_CODE_ORF_LEN, +		[CAPABILITY_CODE_RESTART] = CAPABILITY_CODE_RESTART_LEN, +		[CAPABILITY_CODE_AS4] = CAPABILITY_CODE_AS4_LEN, +		[CAPABILITY_CODE_ADDPATH] = CAPABILITY_CODE_ADDPATH_LEN, +		[CAPABILITY_CODE_DYNAMIC] = CAPABILITY_CODE_DYNAMIC_LEN, +		[CAPABILITY_CODE_DYNAMIC_OLD] = CAPABILITY_CODE_DYNAMIC_LEN, +		[CAPABILITY_CODE_ENHE] = CAPABILITY_CODE_ENHE_LEN, +		[CAPABILITY_CODE_REFRESH_OLD] = CAPABILITY_CODE_REFRESH_LEN, +		[CAPABILITY_CODE_ORF_OLD] = CAPABILITY_CODE_ORF_LEN, +		[CAPABILITY_CODE_FQDN] = CAPABILITY_CODE_MIN_FQDN_LEN, +		[CAPABILITY_CODE_ENHANCED_RR] = CAPABILITY_CODE_ENHANCED_LEN, +		[CAPABILITY_CODE_EXT_MESSAGE] = CAPABILITY_CODE_EXT_MESSAGE_LEN, +}; + +/* value the capability must be a multiple of. + * 0-data capabilities won't be checked against this. + * Other capabilities whose data doesn't fall on convenient boundaries for this + * table should be set to 1. + */ +static const size_t cap_modsizes[] = { +		[CAPABILITY_CODE_MP] = 4, +		[CAPABILITY_CODE_REFRESH] = 1, +		[CAPABILITY_CODE_ORF] = 1, +		[CAPABILITY_CODE_RESTART] = 1, +		[CAPABILITY_CODE_AS4] = 4, +		[CAPABILITY_CODE_ADDPATH] = 4, +		[CAPABILITY_CODE_DYNAMIC] = 1, +		[CAPABILITY_CODE_DYNAMIC_OLD] = 1, +		[CAPABILITY_CODE_ENHE] = 6, +		[CAPABILITY_CODE_REFRESH_OLD] = 1, +		[CAPABILITY_CODE_ORF_OLD] = 1, +		[CAPABILITY_CODE_FQDN] = 1, +		[CAPABILITY_CODE_ENHANCED_RR] = 1, +		[CAPABILITY_CODE_EXT_MESSAGE] = 1, +}; +  /* BGP-4 Multiprotocol Extentions lead us to the complex world. We can     negotiate remote peer supports extentions or not. But if     remote-peer doesn't supports negotiation process itself.  We would @@ -264,9 +321,9 @@ static int bgp_capability_mp(struct peer *peer, struct capability_header *hdr)  	bgp_capability_mp_data(s, &mpc);  	if (bgp_debug_neighbor_events(peer)) -		zlog_debug("%s OPEN has MP_EXT CAP for afi/safi: %s/%s", -			   peer->host, iana_afi2str(mpc.afi), -			   iana_safi2str(mpc.safi)); +		zlog_debug("%s OPEN has %s capability for afi/safi: %s/%s", +			   peer->host, lookup_msg(capcode_str, hdr->code, NULL), +			   iana_afi2str(mpc.afi), iana_safi2str(mpc.safi));  	/* Convert AFI, SAFI to internal values, check. */  	if (bgp_map_afi_safi_iana2int(mpc.afi, mpc.safi, &afi, &safi)) @@ -466,8 +523,6 @@ static int bgp_capability_restart(struct peer *peer,  	peer->v_gr_restart = restart_flag_time;  	if (bgp_debug_neighbor_events(peer)) { -		zlog_debug("%s OPEN has Graceful Restart capability", -			   peer->host);  		zlog_debug("%s Peer has%srestarted. Restart Time : %d",  			   peer->host,  			   CHECK_FLAG(peer->cap, PEER_CAP_RESTART_BIT_RCV) @@ -580,9 +635,10 @@ static int bgp_capability_addpath(struct peer *peer,  		if (bgp_debug_neighbor_events(peer))  			zlog_debug( -				"%s OPEN has AddPath CAP for afi/safi: %s/%s%s%s", -				peer->host, iana_afi2str(pkt_afi), -				iana_safi2str(pkt_safi), +				"%s OPEN has %s capability for afi/safi: %s/%s%s%s", +				peer->host, +				lookup_msg(capcode_str, hdr->code, NULL), +				iana_afi2str(pkt_afi), iana_safi2str(pkt_safi),  				(send_receive & BGP_ADDPATH_RX) ? ", receive"  								: "",  				(send_receive & BGP_ADDPATH_TX) ? ", transmit" @@ -763,63 +819,6 @@ static int bgp_capability_hostname(struct peer *peer,  	return 0;  } -static const struct message capcode_str[] = { -	{CAPABILITY_CODE_MP, "MultiProtocol Extensions"}, -	{CAPABILITY_CODE_REFRESH, "Route Refresh"}, -	{CAPABILITY_CODE_ORF, "Cooperative Route Filtering"}, -	{CAPABILITY_CODE_RESTART, "Graceful Restart"}, -	{CAPABILITY_CODE_AS4, "4-octet AS number"}, -	{CAPABILITY_CODE_ADDPATH, "AddPath"}, -	{CAPABILITY_CODE_DYNAMIC, "Dynamic"}, -	{CAPABILITY_CODE_ENHE, "Extended Next Hop Encoding"}, -	{CAPABILITY_CODE_DYNAMIC_OLD, "Dynamic (Old)"}, -	{CAPABILITY_CODE_REFRESH_OLD, "Route Refresh (Old)"}, -	{CAPABILITY_CODE_ORF_OLD, "ORF (Old)"}, -	{CAPABILITY_CODE_FQDN, "FQDN"}, -	{CAPABILITY_CODE_ENHANCED_RR, "Enhanced Route Refresh"}, -	{CAPABILITY_CODE_EXT_MESSAGE, "BGP Extended Message"}, -	{0}}; - -/* Minimum sizes for length field of each cap (so not inc. the header) */ -static const size_t cap_minsizes[] = { -		[CAPABILITY_CODE_MP] = CAPABILITY_CODE_MP_LEN, -		[CAPABILITY_CODE_REFRESH] = CAPABILITY_CODE_REFRESH_LEN, -		[CAPABILITY_CODE_ORF] = CAPABILITY_CODE_ORF_LEN, -		[CAPABILITY_CODE_RESTART] = CAPABILITY_CODE_RESTART_LEN, -		[CAPABILITY_CODE_AS4] = CAPABILITY_CODE_AS4_LEN, -		[CAPABILITY_CODE_ADDPATH] = CAPABILITY_CODE_ADDPATH_LEN, -		[CAPABILITY_CODE_DYNAMIC] = CAPABILITY_CODE_DYNAMIC_LEN, -		[CAPABILITY_CODE_DYNAMIC_OLD] = CAPABILITY_CODE_DYNAMIC_LEN, -		[CAPABILITY_CODE_ENHE] = CAPABILITY_CODE_ENHE_LEN, -		[CAPABILITY_CODE_REFRESH_OLD] = CAPABILITY_CODE_REFRESH_LEN, -		[CAPABILITY_CODE_ORF_OLD] = CAPABILITY_CODE_ORF_LEN, -		[CAPABILITY_CODE_FQDN] = CAPABILITY_CODE_MIN_FQDN_LEN, -		[CAPABILITY_CODE_ENHANCED_RR] = CAPABILITY_CODE_ENHANCED_LEN, -		[CAPABILITY_CODE_EXT_MESSAGE] = CAPABILITY_CODE_EXT_MESSAGE_LEN, -}; - -/* value the capability must be a multiple of. - * 0-data capabilities won't be checked against this. - * Other capabilities whose data doesn't fall on convenient boundaries for this - * table should be set to 1. - */ -static const size_t cap_modsizes[] = { -		[CAPABILITY_CODE_MP] = 4, -		[CAPABILITY_CODE_REFRESH] = 1, -		[CAPABILITY_CODE_ORF] = 1, -		[CAPABILITY_CODE_RESTART] = 1, -		[CAPABILITY_CODE_AS4] = 4, -		[CAPABILITY_CODE_ADDPATH] = 4, -		[CAPABILITY_CODE_DYNAMIC] = 1, -		[CAPABILITY_CODE_DYNAMIC_OLD] = 1, -		[CAPABILITY_CODE_ENHE] = 6, -		[CAPABILITY_CODE_REFRESH_OLD] = 1, -		[CAPABILITY_CODE_ORF_OLD] = 1, -		[CAPABILITY_CODE_FQDN] = 1, -		[CAPABILITY_CODE_ENHANCED_RR] = 1, -		[CAPABILITY_CODE_EXT_MESSAGE] = 1, -}; -  /**   * Parse given capability.   * XXX: This is reading into a stream, but not using stream API diff --git a/bgpd/bgp_route.c b/bgpd/bgp_route.c index 2a84f548f8..4b798cc264 100644 --- a/bgpd/bgp_route.c +++ b/bgpd/bgp_route.c @@ -8433,8 +8433,7 @@ enum bgp_display_type {  	normal_list,  }; -static const char * -bgp_path_selection_reason2str(enum bgp_path_selection_reason reason) +const char *bgp_path_selection_reason2str(enum bgp_path_selection_reason reason)  {  	switch (reason) {  	case bgp_path_selection_none: @@ -13451,16 +13450,6 @@ show_adj_route(struct vty *vty, struct peer *peer, struct bgp_table *table,  	bgp = peer->bgp; -	if (!bgp) { -		if (use_json) { -			json_object_string_add(json, "alert", "no BGP"); -			vty_out(vty, "%s\n", json_object_to_json_string(json)); -			json_object_free(json); -		} else -			vty_out(vty, "%% No bgp\n"); -		return; -	} -  	subgrp = peer_subgroup(peer, afi, safi);  	if (type == bgp_show_adj_route_advertised && subgrp @@ -13701,6 +13690,9 @@ static int peer_adj_routes(struct vty *vty, struct peer *peer, afi_t afi,  				"No such neighbor or address family");  			vty_out(vty, "%s\n", json_object_to_json_string(json));  			json_object_free(json); +			json_object_free(json_ar); +			json_object_free(json_scode); +			json_object_free(json_ocode);  		} else  			vty_out(vty, "%% No such neighbor or address family\n"); @@ -13717,6 +13709,9 @@ static int peer_adj_routes(struct vty *vty, struct peer *peer, afi_t afi,  				"Inbound soft reconfiguration not enabled");  			vty_out(vty, "%s\n", json_object_to_json_string(json));  			json_object_free(json); +			json_object_free(json_ar); +			json_object_free(json_scode); +			json_object_free(json_ocode);  		} else  			vty_out(vty,  				"%% Inbound soft reconfiguration not enabled\n"); @@ -13785,14 +13780,17 @@ static int peer_adj_routes(struct vty *vty, struct peer *peer, afi_t afi,  			json_object_to_json_string_ext(  				json, JSON_C_TO_STRING_PRETTY)); -		if (!output_count && !filtered_count) { +		/* +		 * These fields only give up ownership to `json` when `header1` +		 * is used (set to zero). See code in `show_adj_route` and +		 * `show_adj_route_header`. +		 */ +		if (header1 == 1) {  			json_object_free(json_scode);  			json_object_free(json_ocode);  		} -		if (json) -			json_object_free(json); - +		json_object_free(json);  	} else if (output_count > 0) {  		if (filtered_count > 0)  			vty_out(vty, diff --git a/bgpd/bgp_route.h b/bgpd/bgp_route.h index 37bf675b67..46802d0d14 100644 --- a/bgpd/bgp_route.h +++ b/bgpd/bgp_route.h @@ -90,6 +90,9 @@ enum bgp_show_adj_route_type {  /* Maximum number of sids we can process or send with a prefix. */  #define BGP_MAX_SIDS 6 +/* Maximum buffer length for storing BGP best path selection reason */ +#define BGP_MAX_SELECTION_REASON_STR_BUF 32 +  /* Error codes for handling NLRI */  #define BGP_NLRI_PARSE_OK 0  #define BGP_NLRI_PARSE_ERROR_PREFIX_OVERFLOW -1 @@ -803,4 +806,6 @@ extern void bgp_aggregate_toggle_suppressed(struct bgp_aggregate *aggregate,  					    const struct prefix *p, afi_t afi,  					    safi_t safi, bool suppress);  extern void subgroup_announce_reset_nhop(uint8_t family, struct attr *attr); +const char * +bgp_path_selection_reason2str(enum bgp_path_selection_reason reason);  #endif /* _QUAGGA_BGP_ROUTE_H */ diff --git a/bgpd/bgp_vty.c b/bgpd/bgp_vty.c index 158a5f30b7..772e20dc85 100644 --- a/bgpd/bgp_vty.c +++ b/bgpd/bgp_vty.c @@ -10241,6 +10241,7 @@ static int bgp_show_summary(struct vty *vty, struct bgp *bgp, int afi, int safi,  	count = 0;		/* Reset the value as its used again */  	filtered_count = 0; +	dn_count = 0;  	for (ALL_LIST_ELEMENTS(bgp->peer, node, nnode, peer)) {  		if (!CHECK_FLAG(peer->flags, PEER_FLAG_CONFIG_NODE))  			continue; diff --git a/bgpd/bgp_zebra.c b/bgpd/bgp_zebra.c index 6161f56fe6..6c9eb2972c 100644 --- a/bgpd/bgp_zebra.c +++ b/bgpd/bgp_zebra.c @@ -136,8 +136,7 @@ static void bgp_update_interface_nbrs(struct bgp *bgp, struct interface *ifp,  	}  } -static int bgp_read_fec_update(int command, struct zclient *zclient, -			       zebra_size_t length) +static int bgp_read_fec_update(ZAPI_CALLBACK_ARGS)  {  	bgp_parse_fec_update();  	return 0; @@ -1490,6 +1489,8 @@ void bgp_zebra_announce(struct bgp_dest *dest, const struct prefix *p,  	if (is_add && CHECK_FLAG(bm->flags, BM_FLAG_SEND_EXTRA_DATA_TO_ZEBRA)) {  		struct bgp_zebra_opaque bzo = {}; +		const char *reason = +			bgp_path_selection_reason2str(dest->reason);  		strlcpy(bzo.aspath, info->attr->aspath->str,  			sizeof(bzo.aspath)); @@ -1503,6 +1504,9 @@ void bgp_zebra_announce(struct bgp_dest *dest, const struct prefix *p,  			strlcpy(bzo.lcommunity, info->attr->lcommunity->str,  				sizeof(bzo.lcommunity)); +		strlcpy(bzo.selection_reason, reason, +			sizeof(bzo.selection_reason)); +  		SET_FLAG(api.message, ZAPI_MESSAGE_OPAQUE);  		api.opaque.length = MIN(sizeof(struct bgp_zebra_opaque),  					ZAPI_MESSAGE_OPAQUE_LENGTH); @@ -3005,7 +3009,7 @@ static int bgp_zebra_process_local_macip(ZAPI_CALLBACK_ARGS)  	}  } -static void bgp_zebra_process_local_ip_prefix(ZAPI_CALLBACK_ARGS) +static int bgp_zebra_process_local_ip_prefix(ZAPI_CALLBACK_ARGS)  {  	struct stream *s = NULL;  	struct bgp *bgp_vrf = NULL; @@ -3017,7 +3021,7 @@ static void bgp_zebra_process_local_ip_prefix(ZAPI_CALLBACK_ARGS)  	bgp_vrf = bgp_lookup_by_vrf_id(vrf_id);  	if (!bgp_vrf) -		return; +		return 0;  	if (BGP_DEBUG(zebra, ZEBRA))  		zlog_debug("Recv prefix %pFX %s on vrf %s", &p, @@ -3041,9 +3045,10 @@ static void bgp_zebra_process_local_ip_prefix(ZAPI_CALLBACK_ARGS)  			bgp_evpn_withdraw_type5_route(bgp_vrf, &p, AFI_IP6,  						      SAFI_UNICAST);  	} +	return 0;  } -static void bgp_zebra_process_label_chunk(ZAPI_CALLBACK_ARGS) +static int bgp_zebra_process_label_chunk(ZAPI_CALLBACK_ARGS)  {  	struct stream *s = NULL;  	uint8_t response_keep; @@ -3062,12 +3067,12 @@ static void bgp_zebra_process_label_chunk(ZAPI_CALLBACK_ARGS)  	if (zclient->redist_default != proto) {  		flog_err(EC_BGP_LM_ERROR, "Got LM msg with wrong proto %u",  			 proto); -		return; +		return 0;  	}  	if (zclient->instance != instance) {  		flog_err(EC_BGP_LM_ERROR, "Got LM msg with wrong instance %u",  			 proto); -		return; +		return 0;  	}  	if (first > last || @@ -3076,7 +3081,7 @@ static void bgp_zebra_process_label_chunk(ZAPI_CALLBACK_ARGS)  		flog_err(EC_BGP_LM_ERROR, "%s: Invalid Label chunk: %u - %u",  			 __func__, first, last); -		return; +		return 0;  	}  	if (BGP_DEBUG(zebra, ZEBRA)) {  		zlog_debug("Label Chunk assign: %u - %u (%u) ", @@ -3085,8 +3090,10 @@ static void bgp_zebra_process_label_chunk(ZAPI_CALLBACK_ARGS)  	bgp_lp_event_chunk(response_keep, first, last); +	return 0; +  stream_failure:		/* for STREAM_GETX */ -	return; +	return -1;  }  extern struct zebra_privs_t bgpd_privs; @@ -3109,7 +3116,7 @@ static int bgp_ifp_create(struct interface *ifp)  	return 0;  } -static void bgp_zebra_process_srv6_locator_chunk(ZAPI_CALLBACK_ARGS) +static int bgp_zebra_process_srv6_locator_chunk(ZAPI_CALLBACK_ARGS)  {  	struct stream *s = NULL;  	struct bgp *bgp = bgp_get_default(); @@ -3124,18 +3131,19 @@ static void bgp_zebra_process_srv6_locator_chunk(ZAPI_CALLBACK_ARGS)  	if (strcmp(bgp->srv6_locator_name, s6c.locator_name) != 0) {  		zlog_err("%s: Locator name unmatch %s:%s", __func__,  			 bgp->srv6_locator_name, s6c.locator_name); -		return; +		return 0;  	}  	for (ALL_LIST_ELEMENTS_RO(bgp->srv6_locator_chunks, node, c)) {  		if (!prefix_cmp(c, &s6c.prefix)) -			return; +			return 0;  	}  	chunk = prefix_ipv6_new();  	*chunk = s6c.prefix;  	listnode_add(bgp->srv6_locator_chunks, chunk);  	vpn_leak_postchange_all(); +	return 0;  }  static int bgp_zebra_process_srv6_locator_add(ZAPI_CALLBACK_ARGS) @@ -3220,6 +3228,41 @@ static int bgp_zebra_process_srv6_locator_delete(ZAPI_CALLBACK_ARGS)  	return 0;  } +static zclient_handler *const bgp_handlers[] = { +	[ZEBRA_ROUTER_ID_UPDATE] = bgp_router_id_update, +	[ZEBRA_INTERFACE_ADDRESS_ADD] = bgp_interface_address_add, +	[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, +	[ZEBRA_FEC_UPDATE] = bgp_read_fec_update, +	[ZEBRA_LOCAL_ES_ADD] = bgp_zebra_process_local_es_add, +	[ZEBRA_LOCAL_ES_DEL] = bgp_zebra_process_local_es_del, +	[ZEBRA_VNI_ADD] = bgp_zebra_process_local_vni, +	[ZEBRA_LOCAL_ES_EVI_ADD] = bgp_zebra_process_local_es_evi, +	[ZEBRA_LOCAL_ES_EVI_DEL] = bgp_zebra_process_local_es_evi, +	[ZEBRA_VNI_DEL] = bgp_zebra_process_local_vni, +	[ZEBRA_MACIP_ADD] = bgp_zebra_process_local_macip, +	[ZEBRA_MACIP_DEL] = bgp_zebra_process_local_macip, +	[ZEBRA_L3VNI_ADD] = bgp_zebra_process_local_l3vni, +	[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, +	[ZEBRA_IPTABLE_NOTIFY_OWNER] = iptable_notify_owner, +	[ZEBRA_ROUTE_NOTIFY_OWNER] = bgp_zebra_route_notify_owner, +	[ZEBRA_SRV6_LOCATOR_ADD] = bgp_zebra_process_srv6_locator_add, +	[ZEBRA_SRV6_LOCATOR_DELETE] = bgp_zebra_process_srv6_locator_delete, +	[ZEBRA_SRV6_MANAGER_GET_LOCATOR_CHUNK] = +		bgp_zebra_process_srv6_locator_chunk, +}; +  void bgp_zebra_init(struct thread_master *master, unsigned short instance)  {  	zclient_num_connects = 0; @@ -3228,43 +3271,11 @@ void bgp_zebra_init(struct thread_master *master, unsigned short instance)  			  bgp_ifp_down, bgp_ifp_destroy);  	/* Set default values. */ -	zclient = zclient_new(master, &zclient_options_default); +	zclient = zclient_new(master, &zclient_options_default, bgp_handlers, +			      array_size(bgp_handlers));  	zclient_init(zclient, ZEBRA_ROUTE_BGP, 0, &bgpd_privs);  	zclient->zebra_connected = bgp_zebra_connected; -	zclient->router_id_update = bgp_router_id_update; -	zclient->interface_address_add = bgp_interface_address_add; -	zclient->interface_address_delete = bgp_interface_address_delete; -	zclient->interface_nbr_address_add = bgp_interface_nbr_address_add; -	zclient->interface_nbr_address_delete = -		bgp_interface_nbr_address_delete; -	zclient->interface_vrf_update = bgp_interface_vrf_update; -	zclient->redistribute_route_add = zebra_read_route; -	zclient->redistribute_route_del = zebra_read_route; -	zclient->nexthop_update = bgp_read_nexthop_update; -	zclient->fec_update = bgp_read_fec_update; -	zclient->local_es_add = bgp_zebra_process_local_es_add; -	zclient->local_es_del = bgp_zebra_process_local_es_del; -	zclient->local_vni_add = bgp_zebra_process_local_vni; -	zclient->local_es_evi_add = bgp_zebra_process_local_es_evi; -	zclient->local_es_evi_del = bgp_zebra_process_local_es_evi; -	zclient->local_vni_del = bgp_zebra_process_local_vni; -	zclient->local_macip_add = bgp_zebra_process_local_macip; -	zclient->local_macip_del = bgp_zebra_process_local_macip; -	zclient->local_l3vni_add = bgp_zebra_process_local_l3vni; -	zclient->local_l3vni_del = bgp_zebra_process_local_l3vni; -	zclient->local_ip_prefix_add = bgp_zebra_process_local_ip_prefix; -	zclient->local_ip_prefix_del = bgp_zebra_process_local_ip_prefix; -	zclient->label_chunk = bgp_zebra_process_label_chunk; -	zclient->rule_notify_owner = rule_notify_owner; -	zclient->ipset_notify_owner = ipset_notify_owner; -	zclient->ipset_entry_notify_owner = ipset_entry_notify_owner; -	zclient->iptable_notify_owner = iptable_notify_owner; -	zclient->route_notify_owner = bgp_zebra_route_notify_owner;  	zclient->instance = instance; -	zclient->srv6_locator_add = bgp_zebra_process_srv6_locator_add; -	zclient->srv6_locator_delete = bgp_zebra_process_srv6_locator_delete; -	zclient->process_srv6_locator_chunk = -		bgp_zebra_process_srv6_locator_chunk;  }  void bgp_zebra_destroy(void) diff --git a/bgpd/bgpd.c b/bgpd/bgpd.c index b191029d2f..c5a5e49a48 100644 --- a/bgpd/bgpd.c +++ b/bgpd/bgpd.c @@ -4775,6 +4775,7 @@ int peer_ebgp_multihop_unset(struct peer *peer)  {  	struct peer_group *group;  	struct listnode *node, *nnode; +	int ttl;  	if (peer->sort == BGP_PEER_IBGP)  		return 0; @@ -4783,9 +4784,14 @@ int peer_ebgp_multihop_unset(struct peer *peer)  		return BGP_ERR_NO_EBGP_MULTIHOP_WITH_TTLHACK;  	if (peer_group_active(peer)) -		peer->ttl = peer->group->conf->ttl; +		ttl = peer->group->conf->ttl;  	else -		peer->ttl = BGP_DEFAULT_TTL; +		ttl = BGP_DEFAULT_TTL; + +	if (ttl == peer->ttl) +		return 0; + +	peer->ttl = ttl;  	if (!CHECK_FLAG(peer->sflags, PEER_STATUS_GROUP)) {  		if (BGP_IS_VALID_STATE_FOR_NOTIF(peer->status)) diff --git a/bgpd/rfapi/vnc_zebra.c b/bgpd/rfapi/vnc_zebra.c index ba849e4e0b..672a0e9780 100644 --- a/bgpd/rfapi/vnc_zebra.c +++ b/bgpd/rfapi/vnc_zebra.c @@ -895,6 +895,11 @@ int vnc_redistribute_unset(struct bgp *bgp, afi_t afi, int type)  extern struct zebra_privs_t bgpd_privs; +static zclient_handler *const vnc_handlers[] = { +	[ZEBRA_REDISTRIBUTE_ROUTE_ADD] = vnc_zebra_read_route, +	[ZEBRA_REDISTRIBUTE_ROUTE_DEL] = vnc_zebra_read_route, +}; +  /*   * Modeled after bgp_zebra.c'bgp_zebra_init()   * Charriere asks, "Is it possible to carry two?" @@ -902,11 +907,9 @@ extern struct zebra_privs_t bgpd_privs;  void vnc_zebra_init(struct thread_master *master)  {  	/* Set default values. */ -	zclient_vnc = zclient_new(master, &zclient_options_default); +	zclient_vnc = zclient_new(master, &zclient_options_default, +				  vnc_handlers, array_size(vnc_handlers));  	zclient_init(zclient_vnc, ZEBRA_ROUTE_VNC, 0, &bgpd_privs); - -	zclient_vnc->redistribute_route_add = vnc_zebra_read_route; -	zclient_vnc->redistribute_route_del = vnc_zebra_read_route;  }  void vnc_zebra_destroy(void) diff --git a/doc/user/bgp.rst b/doc/user/bgp.rst index 5fcddafaaa..1793ae3d27 100644 --- a/doc/user/bgp.rst +++ b/doc/user/bgp.rst @@ -1425,15 +1425,6 @@ Configuring Peers     Set description of the peer. -.. clicmd:: neighbor PEER version VERSION - -   Set up the neighbor's BGP version. `version` can be `4`, `4+` or `4-`. BGP -   version `4` is the default value used for BGP peering. BGP version `4+` -   means that the neighbor supports Multiprotocol Extensions for BGP-4. BGP -   version `4-` is similar but the neighbor speaks the old Internet-Draft -   revision 00's Multiprotocol Extensions for BGP-4. Some routing software is -   still using this version. -  .. clicmd:: neighbor PEER interface IFNAME     When you connect to a BGP peer over an IPv6 link-local address, you have to diff --git a/eigrpd/eigrp_zebra.c b/eigrpd/eigrp_zebra.c index 7c765248c6..89dd5be272 100644 --- a/eigrpd/eigrp_zebra.c +++ b/eigrpd/eigrp_zebra.c @@ -102,20 +102,24 @@ static void eigrp_zebra_connected(struct zclient *zclient)  	zclient_send_reg_requests(zclient, VRF_DEFAULT);  } +static zclient_handler *const eigrp_handlers[] = { +	[ZEBRA_ROUTER_ID_UPDATE] = eigrp_router_id_update_zebra, +	[ZEBRA_INTERFACE_ADDRESS_ADD] = eigrp_interface_address_add, +	[ZEBRA_INTERFACE_ADDRESS_DELETE] = eigrp_interface_address_delete, +	[ZEBRA_REDISTRIBUTE_ROUTE_ADD] = eigrp_zebra_read_route, +	[ZEBRA_REDISTRIBUTE_ROUTE_DEL] = eigrp_zebra_read_route, +	[ZEBRA_ROUTE_NOTIFY_OWNER] = eigrp_zebra_route_notify_owner, +}; +  void eigrp_zebra_init(void)  {  	struct zclient_options opt = {.receive_notify = false}; -	zclient = zclient_new(master, &opt); +	zclient = zclient_new(master, &opt, eigrp_handlers, +			      array_size(eigrp_handlers));  	zclient_init(zclient, ZEBRA_ROUTE_EIGRP, 0, &eigrpd_privs);  	zclient->zebra_connected = eigrp_zebra_connected; -	zclient->router_id_update = eigrp_router_id_update_zebra; -	zclient->interface_address_add = eigrp_interface_address_add; -	zclient->interface_address_delete = eigrp_interface_address_delete; -	zclient->redistribute_route_add = eigrp_zebra_read_route; -	zclient->redistribute_route_del = eigrp_zebra_read_route; -	zclient->route_notify_owner = eigrp_zebra_route_notify_owner;  } diff --git a/include/linux/nexthop.h b/include/linux/nexthop.h index ee2a15b9c7..d8ffa8c9ca 100644 --- a/include/linux/nexthop.h +++ b/include/linux/nexthop.h @@ -1,12 +1,9 @@  /* SPDX-License-Identifier: GPL-2.0 WITH Linux-syscall-note */ -#ifndef _LINUX_NEXTHOP_H -#define _LINUX_NEXTHOP_H +#ifndef _UAPI_LINUX_NEXTHOP_H +#define _UAPI_LINUX_NEXTHOP_H  #include <linux/types.h> -#define RTM_NHA(h)  ((struct rtattr *)(((char *)(h)) + \ -			NLMSG_ALIGN(sizeof(struct nhmsg)))) -  struct nhmsg {  	unsigned char	nh_family;  	unsigned char	nh_scope;     /* return only */ @@ -15,6 +12,7 @@ struct nhmsg {  	unsigned int	nh_flags;     /* RTNH_F flags */  }; +/* entry in a nexthop group */  struct nexthop_grp {  	__u32	id;	  /* nexthop id - must exist */  	__u8	weight;   /* weight of this nexthop */ @@ -23,7 +21,10 @@ struct nexthop_grp {  };  enum { -	NEXTHOP_GRP_TYPE_MPATH,  /* default type if not specified */ +	NEXTHOP_GRP_TYPE_MPATH,  /* hash-threshold nexthop group +				  * default type if not specified +				  */ +	NEXTHOP_GRP_TYPE_RES,    /* resilient nexthop group */  	__NEXTHOP_GRP_TYPE_MAX,  }; @@ -50,10 +51,54 @@ enum {  	 */  	NHA_GROUPS,	/* flag; only return nexthop groups in dump */  	NHA_MASTER,	/* u32;  only return nexthops with given master dev */ -	NHA_FDB,	/* nexthop belongs to a bridge fdb */ + +	NHA_FDB,	/* flag; nexthop belongs to a bridge fdb */ +	/* if NHA_FDB is added, OIF, BLACKHOLE, ENCAP cannot be set */ + +	/* nested; resilient nexthop group attributes */ +	NHA_RES_GROUP, +	/* nested; nexthop bucket attributes */ +	NHA_RES_BUCKET,  	__NHA_MAX,  };  #define NHA_MAX	(__NHA_MAX - 1) + +enum { +	NHA_RES_GROUP_UNSPEC, +	/* Pad attribute for 64-bit alignment. */ +	NHA_RES_GROUP_PAD = NHA_RES_GROUP_UNSPEC, + +	/* u16; number of nexthop buckets in a resilient nexthop group */ +	NHA_RES_GROUP_BUCKETS, +	/* clock_t as u32; nexthop bucket idle timer (per-group) */ +	NHA_RES_GROUP_IDLE_TIMER, +	/* clock_t as u32; nexthop unbalanced timer */ +	NHA_RES_GROUP_UNBALANCED_TIMER, +	/* clock_t as u64; nexthop unbalanced time */ +	NHA_RES_GROUP_UNBALANCED_TIME, + +	__NHA_RES_GROUP_MAX, +}; + +#define NHA_RES_GROUP_MAX	(__NHA_RES_GROUP_MAX - 1) + +enum { +	NHA_RES_BUCKET_UNSPEC, +	/* Pad attribute for 64-bit alignment. */ +	NHA_RES_BUCKET_PAD = NHA_RES_BUCKET_UNSPEC, + +	/* u16; nexthop bucket index */ +	NHA_RES_BUCKET_INDEX, +	/* clock_t as u64; nexthop bucket idle time */ +	NHA_RES_BUCKET_IDLE_TIME, +	/* u32; nexthop id assigned to the nexthop bucket */ +	NHA_RES_BUCKET_NH_ID, + +	__NHA_RES_BUCKET_MAX, +}; + +#define NHA_RES_BUCKET_MAX	(__NHA_RES_BUCKET_MAX - 1) +  #endif diff --git a/isisd/isis_zebra.c b/isisd/isis_zebra.c index 2c05cb8277..27e80e2501 100644 --- a/isisd/isis_zebra.c +++ b/isisd/isis_zebra.c @@ -800,23 +800,31 @@ static int isis_zebra_client_close_notify(ZAPI_CALLBACK_ARGS)  	return ret;  } +static zclient_handler *const isis_handlers[] = { +	[ZEBRA_ROUTER_ID_UPDATE] = isis_router_id_update_zebra, +	[ZEBRA_INTERFACE_ADDRESS_ADD] = isis_zebra_if_address_add, +	[ZEBRA_INTERFACE_ADDRESS_DELETE] = isis_zebra_if_address_del, +	[ZEBRA_INTERFACE_LINK_PARAMS] = isis_zebra_link_params, +	[ZEBRA_REDISTRIBUTE_ROUTE_ADD] = isis_zebra_read, +	[ZEBRA_REDISTRIBUTE_ROUTE_DEL] = isis_zebra_read, + +	[ZEBRA_OPAQUE_MESSAGE] = isis_opaque_msg_handler, + +	[ZEBRA_CLIENT_CLOSE_NOTIFY] = isis_zebra_client_close_notify, +}; +  void isis_zebra_init(struct thread_master *master, int instance)  {  	/* Initialize asynchronous zclient. */ -	zclient = zclient_new(master, &zclient_options_default); +	zclient = zclient_new(master, &zclient_options_default, isis_handlers, +			      array_size(isis_handlers));  	zclient_init(zclient, PROTO_TYPE, 0, &isisd_privs);  	zclient->zebra_connected = isis_zebra_connected; -	zclient->router_id_update = isis_router_id_update_zebra; -	zclient->interface_address_add = isis_zebra_if_address_add; -	zclient->interface_address_delete = isis_zebra_if_address_del; -	zclient->interface_link_params = isis_zebra_link_params; -	zclient->redistribute_route_add = isis_zebra_read; -	zclient->redistribute_route_del = isis_zebra_read;  	/* Initialize special zclient for synchronous message exchanges. */  	struct zclient_options options = zclient_options_default;  	options.synchronous = true; -	zclient_sync = zclient_new(master, &options); +	zclient_sync = zclient_new(master, &options, NULL, 0);  	zclient_sync->sock = -1;  	zclient_sync->redist_default = ZEBRA_ROUTE_ISIS;  	zclient_sync->instance = instance; @@ -826,10 +834,6 @@ void isis_zebra_init(struct thread_master *master, int instance)  	 */  	zclient_sync->session_id = 1;  	zclient_sync->privs = &isisd_privs; - -	zclient->opaque_msg_handler = isis_opaque_msg_handler; - -	zclient->zebra_client_close_notify = isis_zebra_client_close_notify;  }  void isis_zebra_stop(void) diff --git a/ldpd/lde.c b/ldpd/lde.c index babadc461f..0956310367 100644 --- a/ldpd/lde.c +++ b/ldpd/lde.c @@ -2192,7 +2192,7 @@ static void zclient_sync_init(void)  	options.synchronous = true;  	/* Initialize special zclient for synchronous message exchanges. */ -	zclient_sync = zclient_new(master, &options); +	zclient_sync = zclient_new(master, &options, NULL, 0);  	zclient_sync->sock = -1;  	zclient_sync->redist_default = ZEBRA_ROUTE_LDP;  	zclient_sync->session_id = 1; /* Distinguish from main session */ diff --git a/ldpd/ldp_zebra.c b/ldpd/ldp_zebra.c index 2d90412d17..059115915a 100644 --- a/ldpd/ldp_zebra.c +++ b/ldpd/ldp_zebra.c @@ -694,6 +694,16 @@ ldp_zebra_filter_update(struct access_list *access)  extern struct zebra_privs_t ldpd_privs; +static zclient_handler *const ldp_handlers[] = { +	[ZEBRA_ROUTER_ID_UPDATE] = ldp_router_id_update, +	[ZEBRA_INTERFACE_ADDRESS_ADD] = ldp_interface_address_add, +	[ZEBRA_INTERFACE_ADDRESS_DELETE] = ldp_interface_address_delete, +	[ZEBRA_REDISTRIBUTE_ROUTE_ADD] = ldp_zebra_read_route, +	[ZEBRA_REDISTRIBUTE_ROUTE_DEL] = ldp_zebra_read_route, +	[ZEBRA_PW_STATUS_UPDATE] = ldp_zebra_read_pw_status_update, +	[ZEBRA_OPAQUE_MESSAGE] = ldp_zebra_opaque_msg_handler, +}; +  void  ldp_zebra_init(struct thread_master *master)  { @@ -701,18 +711,12 @@ ldp_zebra_init(struct thread_master *master)  			  ldp_ifp_down, ldp_ifp_destroy);  	/* Set default values. */ -	zclient = zclient_new(master, &zclient_options_default); +	zclient = zclient_new(master, &zclient_options_default, ldp_handlers, +			      array_size(ldp_handlers));  	zclient_init(zclient, ZEBRA_ROUTE_LDP, 0, &ldpd_privs);  	/* set callbacks */  	zclient->zebra_connected = ldp_zebra_connected; -	zclient->router_id_update = ldp_router_id_update; -	zclient->interface_address_add = ldp_interface_address_add; -	zclient->interface_address_delete = ldp_interface_address_delete; -	zclient->redistribute_route_add = ldp_zebra_read_route; -	zclient->redistribute_route_del = ldp_zebra_read_route; -	zclient->pw_status_update = ldp_zebra_read_pw_status_update; -	zclient->opaque_msg_handler = ldp_zebra_opaque_msg_handler;  	/* Access list initialize. */  	access_list_add_hook(ldp_zebra_filter_update); @@ -821,10 +821,13 @@ void bfd_sess_show(struct vty *vty, struct json_object *json,   *   * Use this as `zclient` `bfd_dest_replay` callback.   */ -static int zclient_bfd_session_reply(ZAPI_CALLBACK_ARGS) +int zclient_bfd_session_reply(ZAPI_CALLBACK_ARGS)  {  	struct bfd_session_params *bsp; +	if (!zclient->bfd_integration) +		return 0; +  	/* Do nothing when shutting down. */  	if (bsglobal.shutting_down)  		return 0; @@ -855,7 +858,7 @@ static int zclient_bfd_session_reply(ZAPI_CALLBACK_ARGS)  	return 0;  } -static int zclient_bfd_session_update(ZAPI_CALLBACK_ARGS) +int zclient_bfd_session_update(ZAPI_CALLBACK_ARGS)  {  	struct bfd_session_params *bsp, *bspn;  	size_t sessions_updated = 0; @@ -868,6 +871,9 @@ static int zclient_bfd_session_update(ZAPI_CALLBACK_ARGS)  	struct prefix sp;  	char ifstr[128], cbitstr[32]; +	if (!zclient->bfd_integration) +		return 0; +  	/* Do nothing when shutting down. */  	if (bsglobal.shutting_down)  		return 0; @@ -969,9 +975,8 @@ void bfd_protocol_integration_init(struct zclient *zc, struct thread_master *tm)  	bsglobal.zc = zc;  	bsglobal.tm = tm; -	/* Install our callbacks. */ -	zc->interface_bfd_dest_update = zclient_bfd_session_update; -	zc->bfd_dest_replay = zclient_bfd_session_reply; +	/* Enable BFD callbacks. */ +	zc->bfd_integration = true;  	/* Send the client registration */  	bfd_client_sendmsg(zc, ZEBRA_BFD_CLIENT_REGISTER, VRF_DEFAULT); diff --git a/lib/route_opaque.h b/lib/route_opaque.h index 7c4e9a16e1..c5e7d6a327 100644 --- a/lib/route_opaque.h +++ b/lib/route_opaque.h @@ -36,6 +36,12 @@ struct bgp_zebra_opaque {  	/* Show at least 10 large-communities AA:BB:CC */  	char lcommunity[LCOMMUNITY_SIZE * 30]; + +	/* 32 bytes seems enough because of +	 * bgp_path_selection_confed_as_path which is +	 * `Confederation based AS Path`. +	 */ +	char selection_reason[BGP_MAX_SELECTION_REASON_STR_BUF];  };  static_assert(sizeof(struct bgp_zebra_opaque) <= ZAPI_MESSAGE_OPAQUE_LENGTH, diff --git a/lib/zclient.c b/lib/zclient.c index 90439d5e17..24546f3c45 100644 --- a/lib/zclient.c +++ b/lib/zclient.c @@ -66,7 +66,8 @@ static int zclient_debug;  /* Allocate zclient structure. */  struct zclient *zclient_new(struct thread_master *master, -			    struct zclient_options *opt) +			    struct zclient_options *opt, +			    zclient_handler *const *handlers, size_t n_handlers)  {  	struct zclient *zclient;  	size_t stream_size = @@ -79,6 +80,9 @@ struct zclient *zclient_new(struct thread_master *master,  	zclient->wb = buffer_new(0);  	zclient->master = master; +	zclient->handlers = handlers; +	zclient->n_handlers = n_handlers; +  	zclient->receive_notify = opt->receive_notify;  	zclient->synchronous = opt->synchronous; @@ -450,7 +454,7 @@ enum zclient_send_status zclient_send_localsid(struct zclient *zclient,  	p.prefix = *sid;  	api.vrf_id = VRF_DEFAULT; -	api.type = ZEBRA_ROUTE_BGP; +	api.type = zclient->redist_default;  	api.instance = 0;  	api.safi = SAFI_UNICAST;  	memcpy(&api.prefix, &p, sizeof(p)); @@ -2109,7 +2113,7 @@ stream_failure:   * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+   */ -static int zclient_vrf_add(struct zclient *zclient, vrf_id_t vrf_id) +static int zclient_vrf_add(ZAPI_CALLBACK_ARGS)  {  	struct vrf *vrf;  	char vrfname_tmp[VRF_NAMSIZ + 1] = {}; @@ -2141,7 +2145,7 @@ stream_failure:  	return -1;  } -static void zclient_vrf_delete(struct zclient *zclient, vrf_id_t vrf_id) +static int zclient_vrf_delete(ZAPI_CALLBACK_ARGS)  {  	struct vrf *vrf; @@ -2154,12 +2158,13 @@ static void zclient_vrf_delete(struct zclient *zclient, vrf_id_t vrf_id)  	 * no point in attempting to delete it.  	 */  	if (!vrf) -		return; +		return 0;  	vrf_delete(vrf); +	return 0;  } -static int zclient_interface_add(struct zclient *zclient, vrf_id_t vrf_id) +static int zclient_interface_add(ZAPI_CALLBACK_ARGS)  {  	struct interface *ifp;  	char ifname_tmp[INTERFACE_NAMSIZ + 1] = {}; @@ -2219,7 +2224,7 @@ stream_failure:  	return NULL;  } -static void zclient_interface_delete(struct zclient *zclient, vrf_id_t vrf_id) +static int zclient_interface_delete(ZAPI_CALLBACK_ARGS)  {  	struct interface *ifp;  	struct stream *s = zclient->ibuf; @@ -2227,13 +2232,13 @@ static void zclient_interface_delete(struct zclient *zclient, vrf_id_t vrf_id)  	ifp = zebra_interface_state_read(s, vrf_id);  	if (ifp == NULL) -		return; +		return 0;  	if_destroy_via_zapi(ifp); -	return; +	return 0;  } -static void zclient_interface_up(struct zclient *zclient, vrf_id_t vrf_id) +static int zclient_interface_up(ZAPI_CALLBACK_ARGS)  {  	struct interface *ifp;  	struct stream *s = zclient->ibuf; @@ -2241,12 +2246,13 @@ static void zclient_interface_up(struct zclient *zclient, vrf_id_t vrf_id)  	ifp = zebra_interface_state_read(s, vrf_id);  	if (!ifp) -		return; +		return 0;  	if_up_via_zapi(ifp); +	return 0;  } -static void zclient_interface_down(struct zclient *zclient, vrf_id_t vrf_id) +static int zclient_interface_down(ZAPI_CALLBACK_ARGS)  {  	struct interface *ifp;  	struct stream *s = zclient->ibuf; @@ -2254,12 +2260,13 @@ static void zclient_interface_down(struct zclient *zclient, vrf_id_t vrf_id)  	ifp = zebra_interface_state_read(s, vrf_id);  	if (!ifp) -		return; +		return 0;  	if_down_via_zapi(ifp); +	return 0;  } -static void zclient_handle_error(ZAPI_CALLBACK_ARGS) +static int zclient_handle_error(ZAPI_CALLBACK_ARGS)  {  	enum zebra_error_types error;  	struct stream *s = zclient->ibuf; @@ -2268,6 +2275,7 @@ static void zclient_handle_error(ZAPI_CALLBACK_ARGS)  	if (zclient->handle_error)  		(*zclient->handle_error)(error); +	return 0;  }  static int link_params_set_value(struct stream *s, struct if_link_params *iflp) @@ -3585,7 +3593,7 @@ stream_failure:  	return -1;  } -static void zclient_capability_decode(ZAPI_CALLBACK_ARGS) +static int zclient_capability_decode(ZAPI_CALLBACK_ARGS)  {  	struct zclient_capabilities cap;  	struct stream *s = zclient->ibuf; @@ -3612,7 +3620,7 @@ static void zclient_capability_decode(ZAPI_CALLBACK_ARGS)  		(*zclient->zebra_capabilities)(&cap);  stream_failure: -	return; +	return 0;  }  enum zclient_send_status zclient_send_mlag_register(struct zclient *client, @@ -3651,24 +3659,6 @@ enum zclient_send_status zclient_send_mlag_data(struct zclient *client,  	return zclient_send_message(client);  } -static void zclient_mlag_process_up(ZAPI_CALLBACK_ARGS) -{ -	if (zclient->mlag_process_up) -		(*zclient->mlag_process_up)(); -} - -static void zclient_mlag_process_down(ZAPI_CALLBACK_ARGS) -{ -	if (zclient->mlag_process_down) -		(*zclient->mlag_process_down)(); -} - -static void zclient_mlag_handle_msg(ZAPI_CALLBACK_ARGS) -{ -	if (zclient->mlag_handle_msg) -		(*zclient->mlag_handle_msg)(zclient->ibuf, length); -} -  /*   * Send an OPAQUE message, contents opaque to zebra. The message header   * is a message subtype. @@ -3858,6 +3848,24 @@ stream_failure:  	return -1;  } +static zclient_handler *const lib_handlers[] = { +	/* fundamentals */ +	[ZEBRA_CAPABILITIES] = zclient_capability_decode, +	[ZEBRA_ERROR] = zclient_handle_error, + +	/* VRF & interface code is shared in lib */ +	[ZEBRA_VRF_ADD] = zclient_vrf_add, +	[ZEBRA_VRF_DELETE] = zclient_vrf_delete, +	[ZEBRA_INTERFACE_ADD] = zclient_interface_add, +	[ZEBRA_INTERFACE_DELETE] = zclient_interface_delete, +	[ZEBRA_INTERFACE_UP] = zclient_interface_up, +	[ZEBRA_INTERFACE_DOWN] = zclient_interface_down, + +	/* BFD */ +	[ZEBRA_BFD_DEST_REPLAY] = zclient_bfd_session_reply, +	[ZEBRA_INTERFACE_BFD_DEST_UPDATE] = zclient_bfd_session_update, +}; +  /* Zebra client message read function. */  static int zclient_read(struct thread *thread)  { @@ -3957,283 +3965,10 @@ static int zclient_read(struct thread *thread)  		zlog_debug("zclient %p command %s VRF %u", zclient,  			   zserv_command_string(command), vrf_id); -	switch (command) { -	case ZEBRA_CAPABILITIES: -		zclient_capability_decode(command, zclient, length, vrf_id); -		break; -	case ZEBRA_ROUTER_ID_UPDATE: -		if (zclient->router_id_update) -			(*zclient->router_id_update)(command, zclient, length, -						     vrf_id); -		break; -	case ZEBRA_VRF_ADD: -		zclient_vrf_add(zclient, vrf_id); -		break; -	case ZEBRA_VRF_DELETE: -		zclient_vrf_delete(zclient, vrf_id); -		break; -	case ZEBRA_INTERFACE_ADD: -		zclient_interface_add(zclient, vrf_id); -		break; -	case ZEBRA_INTERFACE_DELETE: -		zclient_interface_delete(zclient, vrf_id); -		break; -	case ZEBRA_INTERFACE_ADDRESS_ADD: -		if (zclient->interface_address_add) -			(*zclient->interface_address_add)(command, zclient, -							  length, vrf_id); -		break; -	case ZEBRA_INTERFACE_ADDRESS_DELETE: -		if (zclient->interface_address_delete) -			(*zclient->interface_address_delete)(command, zclient, -							     length, vrf_id); -		break; -	case ZEBRA_INTERFACE_BFD_DEST_UPDATE: -		if (zclient->interface_bfd_dest_update) -			(*zclient->interface_bfd_dest_update)(command, zclient, -							      length, vrf_id); -		break; -	case ZEBRA_INTERFACE_NBR_ADDRESS_ADD: -		if (zclient->interface_nbr_address_add) -			(*zclient->interface_nbr_address_add)(command, zclient, -							      length, vrf_id); -		break; -	case ZEBRA_INTERFACE_NBR_ADDRESS_DELETE: -		if (zclient->interface_nbr_address_delete) -			(*zclient->interface_nbr_address_delete)( -				command, zclient, length, vrf_id); -		break; -	case ZEBRA_INTERFACE_UP: -		zclient_interface_up(zclient, vrf_id); -		break; -	case ZEBRA_INTERFACE_DOWN: -		zclient_interface_down(zclient, vrf_id); -		break; -	case ZEBRA_INTERFACE_VRF_UPDATE: -		if (zclient->interface_vrf_update) -			(*zclient->interface_vrf_update)(command, zclient, -							 length, vrf_id); -		break; -	case ZEBRA_NEXTHOP_UPDATE: -		if (zclient_debug) -			zlog_debug("zclient rcvd nexthop update"); -		if (zclient->nexthop_update) -			(*zclient->nexthop_update)(command, zclient, length, -						   vrf_id); -		break; -	case ZEBRA_BFD_DEST_REPLAY: -		if (zclient->bfd_dest_replay) -			(*zclient->bfd_dest_replay)(command, zclient, length, -						    vrf_id); -		break; -	case ZEBRA_REDISTRIBUTE_ROUTE_ADD: -		if (zclient->redistribute_route_add) -			(*zclient->redistribute_route_add)(command, zclient, -							   length, vrf_id); -		break; -	case ZEBRA_REDISTRIBUTE_ROUTE_DEL: -		if (zclient->redistribute_route_del) -			(*zclient->redistribute_route_del)(command, zclient, -							   length, vrf_id); -		break; -	case ZEBRA_INTERFACE_LINK_PARAMS: -		if (zclient->interface_link_params) -			(*zclient->interface_link_params)(command, zclient, -							  length, vrf_id); -		break; -	case ZEBRA_FEC_UPDATE: -		if (zclient_debug) -			zlog_debug("zclient rcvd fec update"); -		if (zclient->fec_update) -			(*zclient->fec_update)(command, zclient, length); -		break; -	case ZEBRA_LOCAL_ES_ADD: -		if (zclient->local_es_add) -			(*zclient->local_es_add)(command, zclient, length, -						 vrf_id); -		break; -	case ZEBRA_LOCAL_ES_DEL: -		if (zclient->local_es_del) -			(*zclient->local_es_del)(command, zclient, length, -						 vrf_id); -		break; -	case ZEBRA_LOCAL_ES_EVI_ADD: -		if (zclient->local_es_evi_add) -			(*zclient->local_es_evi_add)(command, zclient, length, -						 vrf_id); -		break; -	case ZEBRA_LOCAL_ES_EVI_DEL: -		if (zclient->local_es_evi_del) -			(*zclient->local_es_evi_del)(command, zclient, length, -						 vrf_id); -		break; -	case ZEBRA_VNI_ADD: -		if (zclient->local_vni_add) -			(*zclient->local_vni_add)(command, zclient, length, -						  vrf_id); -		break; -	case ZEBRA_VNI_DEL: -		if (zclient->local_vni_del) -			(*zclient->local_vni_del)(command, zclient, length, -						  vrf_id); -		break; -	case ZEBRA_L3VNI_ADD: -		if (zclient->local_l3vni_add) -			(*zclient->local_l3vni_add)(command, zclient, length, -						    vrf_id); -		break; -	case ZEBRA_L3VNI_DEL: -		if (zclient->local_l3vni_del) -			(*zclient->local_l3vni_del)(command, zclient, length, -						    vrf_id); -		break; -	case ZEBRA_MACIP_ADD: -		if (zclient->local_macip_add) -			(*zclient->local_macip_add)(command, zclient, length, -						    vrf_id); -		break; -	case ZEBRA_MACIP_DEL: -		if (zclient->local_macip_del) -			(*zclient->local_macip_del)(command, zclient, length, -						    vrf_id); -		break; -	case ZEBRA_IP_PREFIX_ROUTE_ADD: -		if (zclient->local_ip_prefix_add) -			(*zclient->local_ip_prefix_add)(command, zclient, -							length, vrf_id); -		break; -	case ZEBRA_IP_PREFIX_ROUTE_DEL: -		if (zclient->local_ip_prefix_del) -			(*zclient->local_ip_prefix_del)(command, zclient, -							length, vrf_id); -		break; -	case ZEBRA_PW_STATUS_UPDATE: -		if (zclient->pw_status_update) -			(*zclient->pw_status_update)(command, zclient, length, -						     vrf_id); -		break; -	case ZEBRA_ROUTE_NOTIFY_OWNER: -		if (zclient->route_notify_owner) -			(*zclient->route_notify_owner)(command, zclient, length, -						       vrf_id); -		break; -	case ZEBRA_RULE_NOTIFY_OWNER: -		if (zclient->rule_notify_owner) -			(*zclient->rule_notify_owner)(command, zclient, length, -						      vrf_id); -		break; -	case ZEBRA_NHG_NOTIFY_OWNER: -		if (zclient->nhg_notify_owner) -			(*zclient->nhg_notify_owner)(command, zclient, length, -						     vrf_id); -		break; -	case ZEBRA_GET_LABEL_CHUNK: -		if (zclient->label_chunk) -			(*zclient->label_chunk)(command, zclient, length, -						vrf_id); -		break; -	case ZEBRA_IPSET_NOTIFY_OWNER: -		if (zclient->ipset_notify_owner) -			(*zclient->ipset_notify_owner)(command, zclient, length, -						      vrf_id); -		break; -	case ZEBRA_IPSET_ENTRY_NOTIFY_OWNER: -		if (zclient->ipset_entry_notify_owner) -			(*zclient->ipset_entry_notify_owner)(command, -						     zclient, length, -						     vrf_id); -		break; -	case ZEBRA_IPTABLE_NOTIFY_OWNER: -		if (zclient->iptable_notify_owner) -			(*zclient->iptable_notify_owner)(command, -						 zclient, length, -						 vrf_id); -		break; -	case ZEBRA_VXLAN_SG_ADD: -		if (zclient->vxlan_sg_add) -			(*zclient->vxlan_sg_add)(command, zclient, length, -						    vrf_id); -		break; -	case ZEBRA_VXLAN_SG_DEL: -		if (zclient->vxlan_sg_del) -			(*zclient->vxlan_sg_del)(command, zclient, length, -						    vrf_id); -		break; -	case ZEBRA_MLAG_PROCESS_UP: -		zclient_mlag_process_up(command, zclient, length, vrf_id); -		break; -	case ZEBRA_MLAG_PROCESS_DOWN: -		zclient_mlag_process_down(command, zclient, length, vrf_id); -		break; -	case ZEBRA_MLAG_FORWARD_MSG: -		zclient_mlag_handle_msg(command, zclient, length, vrf_id); -		break; -	case ZEBRA_SRV6_LOCATOR_ADD: -		if (zclient->srv6_locator_add) -			(*zclient->srv6_locator_add)(command, zclient, length, -						     vrf_id); -		break; -	case ZEBRA_SRV6_LOCATOR_DELETE: -		if (zclient->srv6_locator_delete) -			(*zclient->srv6_locator_delete)(command, zclient, -							length, vrf_id); -		break; -	case ZEBRA_SRV6_MANAGER_GET_LOCATOR_CHUNK: -		if (zclient->process_srv6_locator_chunk) -			(*zclient->process_srv6_locator_chunk)(command, zclient, -							       length, vrf_id); -		break; -	case ZEBRA_ERROR: -		zclient_handle_error(command, zclient, length, vrf_id); -		break; -	case ZEBRA_OPAQUE_MESSAGE: -		if (zclient->opaque_msg_handler) -			(*zclient->opaque_msg_handler)(command, zclient, length, -						       vrf_id); -		break; -	case ZEBRA_OPAQUE_REGISTER: -		if (zclient->opaque_register_handler) -			(*zclient->opaque_register_handler)(command, zclient, -							    length, vrf_id); -		break; -	case ZEBRA_OPAQUE_UNREGISTER: -		if (zclient->opaque_unregister_handler) -			(*zclient->opaque_unregister_handler)(command, zclient, -							    length, vrf_id); -		break; -	case ZEBRA_SR_POLICY_NOTIFY_STATUS: -		if (zclient->sr_policy_notify_status) -			(*zclient->sr_policy_notify_status)(command, zclient, -							    length, vrf_id); -		break; -	case ZEBRA_CLIENT_CLOSE_NOTIFY: -		if (zclient->zebra_client_close_notify) -			(*zclient->zebra_client_close_notify)(command, zclient, -							      length, vrf_id); -		break; -	case ZEBRA_NHRP_NEIGH_ADDED: -		if (zclient->neighbor_added) -			(*zclient->neighbor_added)(command, zclient, length, -						   vrf_id); -		break; -	case ZEBRA_NHRP_NEIGH_REMOVED: -		if (zclient->neighbor_removed) -			(*zclient->neighbor_removed)(command, zclient, length, -						     vrf_id); -		break; -	case ZEBRA_NHRP_NEIGH_GET: -		if (zclient->neighbor_get) -			(*zclient->neighbor_get)(command, zclient, length, -						 vrf_id); -		break; -	case ZEBRA_GRE_UPDATE: -		if (zclient->gre_update) -			(*zclient->gre_update)(command, zclient, -					       length, vrf_id); -		break; -	default: -		break; -	} +	if (command < array_size(lib_handlers) && lib_handlers[command]) +		lib_handlers[command](command, zclient, length, vrf_id); +	if (command < zclient->n_handlers && zclient->handlers[command]) +		zclient->handlers[command](command, zclient, length, vrf_id);  	if (zclient->sock < 0)  		/* Connection was closed during packet processing. */ diff --git a/lib/zclient.h b/lib/zclient.h index 3cad9bd4fa..82eaefda42 100644 --- a/lib/zclient.h +++ b/lib/zclient.h @@ -21,6 +21,8 @@  #ifndef _ZEBRA_ZCLIENT_H  #define _ZEBRA_ZCLIENT_H +struct zclient; +  /* For struct zapi_route. */  #include "prefix.h"  #include "ipaddr.h" @@ -284,6 +286,14 @@ struct zapi_cap {  	vrf_id_t vrf_id;  }; +/* clang-format off */ +#define ZAPI_CALLBACK_ARGS                                                     \ +	int cmd, struct zclient *zclient, uint16_t length, vrf_id_t vrf_id + +/* function-type typedef (pointer not included) */ +typedef int (zclient_handler)(ZAPI_CALLBACK_ARGS); +/* clang-format on */ +  /* Structure for the zebra client. */  struct zclient {  	/* The thread master we schedule ourselves on */ @@ -298,6 +308,9 @@ struct zclient {  	/* Is this a synchronous client? */  	bool synchronous; +	/* BFD enabled with bfd_protocol_integration_init() */ +	bool bfd_integration; +  	/* Session id (optional) to support clients with multiple sessions */  	uint32_t session_id; @@ -332,13 +345,12 @@ struct zclient {  	/* Redistribute default. */  	vrf_bitmap_t default_information[AFI_MAX]; -#define ZAPI_CALLBACK_ARGS                                                     \ -	int cmd, struct zclient *zclient, uint16_t length, vrf_id_t vrf_id -  	/* Pointer to the callback functions. */  	void (*zebra_connected)(struct zclient *);  	void (*zebra_capabilities)(struct zclient_capabilities *cap); +	int (*handle_error)(enum zebra_error_types error); +  	/*  	 * When the zclient attempts to write the stream data to  	 * it's named pipe to/from zebra, we may have a situation @@ -350,61 +362,15 @@ struct zclient {  	 * more data.  	 */  	void (*zebra_buffer_write_ready)(void); -	int (*router_id_update)(ZAPI_CALLBACK_ARGS); -	int (*interface_address_add)(ZAPI_CALLBACK_ARGS); -	int (*interface_address_delete)(ZAPI_CALLBACK_ARGS); -	int (*interface_link_params)(ZAPI_CALLBACK_ARGS); -	int (*interface_bfd_dest_update)(ZAPI_CALLBACK_ARGS); -	int (*interface_nbr_address_add)(ZAPI_CALLBACK_ARGS); -	int (*interface_nbr_address_delete)(ZAPI_CALLBACK_ARGS); -	int (*interface_vrf_update)(ZAPI_CALLBACK_ARGS); -	int (*nexthop_update)(ZAPI_CALLBACK_ARGS); -	int (*bfd_dest_replay)(ZAPI_CALLBACK_ARGS); -	int (*redistribute_route_add)(ZAPI_CALLBACK_ARGS); -	int (*redistribute_route_del)(ZAPI_CALLBACK_ARGS); -	int (*fec_update)(int, struct zclient *, uint16_t); -	int (*local_es_add)(ZAPI_CALLBACK_ARGS); -	int (*local_es_del)(ZAPI_CALLBACK_ARGS); -	int (*local_es_evi_add)(ZAPI_CALLBACK_ARGS); -	int (*local_es_evi_del)(ZAPI_CALLBACK_ARGS); -	int (*local_vni_add)(ZAPI_CALLBACK_ARGS); -	int (*local_vni_del)(ZAPI_CALLBACK_ARGS); -	int (*local_l3vni_add)(ZAPI_CALLBACK_ARGS); -	int (*local_l3vni_del)(ZAPI_CALLBACK_ARGS); -	void (*local_ip_prefix_add)(ZAPI_CALLBACK_ARGS); -	void (*local_ip_prefix_del)(ZAPI_CALLBACK_ARGS); -	int (*local_macip_add)(ZAPI_CALLBACK_ARGS); -	int (*local_macip_del)(ZAPI_CALLBACK_ARGS); -	int (*pw_status_update)(ZAPI_CALLBACK_ARGS); -	int (*route_notify_owner)(ZAPI_CALLBACK_ARGS); -	int (*rule_notify_owner)(ZAPI_CALLBACK_ARGS); -	void (*label_chunk)(ZAPI_CALLBACK_ARGS); -	int (*ipset_notify_owner)(ZAPI_CALLBACK_ARGS); -	int (*ipset_entry_notify_owner)(ZAPI_CALLBACK_ARGS); -	int (*iptable_notify_owner)(ZAPI_CALLBACK_ARGS); -	int (*vxlan_sg_add)(ZAPI_CALLBACK_ARGS); -	int (*vxlan_sg_del)(ZAPI_CALLBACK_ARGS); -	int (*mlag_process_up)(void); -	int (*mlag_process_down)(void); -	int (*mlag_handle_msg)(struct stream *msg, int len); -	int (*nhg_notify_owner)(ZAPI_CALLBACK_ARGS); -	int (*srv6_locator_add)(ZAPI_CALLBACK_ARGS); -	int (*srv6_locator_delete)(ZAPI_CALLBACK_ARGS); -	int (*srv6_function_add)(ZAPI_CALLBACK_ARGS); -	int (*srv6_function_delete)(ZAPI_CALLBACK_ARGS); -	void (*process_srv6_locator_chunk)(ZAPI_CALLBACK_ARGS); -	int (*handle_error)(enum zebra_error_types error); -	int (*opaque_msg_handler)(ZAPI_CALLBACK_ARGS); -	int (*opaque_register_handler)(ZAPI_CALLBACK_ARGS); -	int (*opaque_unregister_handler)(ZAPI_CALLBACK_ARGS); -	int (*sr_policy_notify_status)(ZAPI_CALLBACK_ARGS); -	int (*zebra_client_close_notify)(ZAPI_CALLBACK_ARGS); -	void (*neighbor_added)(ZAPI_CALLBACK_ARGS); -	void (*neighbor_removed)(ZAPI_CALLBACK_ARGS); -	void (*neighbor_get)(ZAPI_CALLBACK_ARGS); -	void (*gre_update)(ZAPI_CALLBACK_ARGS); + +	zclient_handler *const *handlers; +	size_t n_handlers;  }; +/* lib handlers added in bfd.c */ +extern int zclient_bfd_session_reply(ZAPI_CALLBACK_ARGS); +extern int zclient_bfd_session_update(ZAPI_CALLBACK_ARGS); +  /* Zebra API message flag. */  #define ZAPI_MESSAGE_NEXTHOP  0x01  #define ZAPI_MESSAGE_DISTANCE 0x02 @@ -893,7 +859,9 @@ int zclient_neigh_ip_encode(struct stream *s, uint16_t cmd, union sockunion *in,  extern uint32_t zclient_get_nhg_start(uint32_t proto);  extern struct zclient *zclient_new(struct thread_master *m, -				   struct zclient_options *opt); +				   struct zclient_options *opt, +				   zclient_handler *const *handlers, +				   size_t n_handlers);  extern void zclient_init(struct zclient *, int, unsigned short,  			 struct zebra_privs_t *privs); diff --git a/nhrpd/netlink_arp.c b/nhrpd/netlink_arp.c index 0a618056d5..3658cb16bb 100644 --- a/nhrpd/netlink_arp.c +++ b/nhrpd/netlink_arp.c @@ -147,7 +147,7 @@ void netlink_set_nflog_group(int nlgroup)  	}  } -void nhrp_neighbor_operation(ZAPI_CALLBACK_ARGS) +int nhrp_neighbor_operation(ZAPI_CALLBACK_ARGS)  {  	union sockunion addr = {}, lladdr = {};  	struct interface *ifp; @@ -157,7 +157,7 @@ void nhrp_neighbor_operation(ZAPI_CALLBACK_ARGS)  	zclient_neigh_ip_decode(zclient->ibuf, &api);  	if (api.ip_in.ipa_type == AF_UNSPEC) -		return; +		return 0;  	sockunion_family(&addr) = api.ip_in.ipa_type;  	memcpy((uint8_t *)sockunion_get_addr(&addr), &api.ip_in.ip.addr,  	       family2addrsize(api.ip_in.ipa_type)); @@ -172,10 +172,10 @@ void nhrp_neighbor_operation(ZAPI_CALLBACK_ARGS)  	ndm_state = api.ndm_state;  	if (!ifp) -		return; +		return 0;  	c = nhrp_cache_get(ifp, &addr, 0);  	if (!c) -		return; +		return 0;  	debugf(NHRP_DEBUG_KERNEL,  	       "Netlink: %s %pSU dev %s lladdr %pSU nud 0x%x cache used %u type %u",  	       (cmd == ZEBRA_NHRP_NEIGH_GET) @@ -200,4 +200,5 @@ void nhrp_neighbor_operation(ZAPI_CALLBACK_ARGS)  			: ZEBRA_NEIGH_STATE_FAILED;  		nhrp_cache_set_used(c, state == ZEBRA_NEIGH_STATE_REACHABLE);  	} +	return 0;  } diff --git a/nhrpd/nhrp_route.c b/nhrpd/nhrp_route.c index 12a2fc2fa0..76e0978cb6 100644 --- a/nhrpd/nhrp_route.c +++ b/nhrpd/nhrp_route.c @@ -366,21 +366,25 @@ static void nhrp_zebra_connected(struct zclient *zclient)  	nhrp_zebra_register_neigh(VRF_DEFAULT, AFI_IP6, true);  } +static zclient_handler *const nhrp_handlers[] = { +	[ZEBRA_INTERFACE_ADDRESS_ADD] = nhrp_interface_address_add, +	[ZEBRA_INTERFACE_ADDRESS_DELETE] = nhrp_interface_address_delete, +	[ZEBRA_REDISTRIBUTE_ROUTE_ADD] = nhrp_route_read, +	[ZEBRA_REDISTRIBUTE_ROUTE_DEL] = nhrp_route_read, +	[ZEBRA_NHRP_NEIGH_ADDED] = nhrp_neighbor_operation, +	[ZEBRA_NHRP_NEIGH_REMOVED] = nhrp_neighbor_operation, +	[ZEBRA_NHRP_NEIGH_GET] = nhrp_neighbor_operation, +	[ZEBRA_GRE_UPDATE] = nhrp_gre_update, +}; +  void nhrp_zebra_init(void)  {  	zebra_rib[AFI_IP] = route_table_init();  	zebra_rib[AFI_IP6] = route_table_init(); -	zclient = zclient_new(master, &zclient_options_default); +	zclient = zclient_new(master, &zclient_options_default, nhrp_handlers, +			      array_size(nhrp_handlers));  	zclient->zebra_connected = nhrp_zebra_connected; -	zclient->interface_address_add = nhrp_interface_address_add; -	zclient->interface_address_delete = nhrp_interface_address_delete; -	zclient->redistribute_route_add = nhrp_route_read; -	zclient->redistribute_route_del = nhrp_route_read; -	zclient->neighbor_added = nhrp_neighbor_operation; -	zclient->neighbor_removed = nhrp_neighbor_operation; -	zclient->neighbor_get = nhrp_neighbor_operation; -	zclient->gre_update = nhrp_gre_update;  	zclient_init(zclient, ZEBRA_ROUTE_NHRP, 0, &nhrpd_privs);  } @@ -476,7 +480,7 @@ void nhrp_zebra_terminate(void)  	route_table_finish(zebra_rib[AFI_IP6]);  } -void nhrp_gre_update(ZAPI_CALLBACK_ARGS) +int nhrp_gre_update(ZAPI_CALLBACK_ARGS)  {  	struct stream *s;  	struct nhrp_gre_info gre_info, *val; @@ -485,7 +489,7 @@ void nhrp_gre_update(ZAPI_CALLBACK_ARGS)  	/* result */  	s = zclient->ibuf;  	if (vrf_id != VRF_DEFAULT) -		return; +		return 0;  	/* read GRE information */  	STREAM_GETL(s, gre_info.ifindex); @@ -516,7 +520,9 @@ void nhrp_gre_update(ZAPI_CALLBACK_ARGS)  	       ifp ? ifp->name : "<none>", gre_info.ifindex, vrf_id);  	if (ifp)  		nhrp_interface_update_nbma(ifp, val); -	return; +	return 0; +  stream_failure:  	zlog_err("%s(): error reading response ..", __func__); +	return -1;  } diff --git a/nhrpd/nhrpd.h b/nhrpd/nhrpd.h index 63f1cb97ef..753c6e9b22 100644 --- a/nhrpd/nhrpd.h +++ b/nhrpd/nhrpd.h @@ -376,8 +376,8 @@ int nhrp_interface_up(ZAPI_CALLBACK_ARGS);  int nhrp_interface_down(ZAPI_CALLBACK_ARGS);  int nhrp_interface_address_add(ZAPI_CALLBACK_ARGS);  int nhrp_interface_address_delete(ZAPI_CALLBACK_ARGS); -void nhrp_neighbor_operation(ZAPI_CALLBACK_ARGS); -void nhrp_gre_update(ZAPI_CALLBACK_ARGS); +int nhrp_neighbor_operation(ZAPI_CALLBACK_ARGS); +int nhrp_gre_update(ZAPI_CALLBACK_ARGS);  void nhrp_interface_notify_add(struct interface *ifp, struct notifier_block *n,  			       notifier_fn_t fn); diff --git a/ospf6d/ospf6_zebra.c b/ospf6d/ospf6_zebra.c index 81573da3a6..5e50a6cc55 100644 --- a/ospf6d/ospf6_zebra.c +++ b/ospf6d/ospf6_zebra.c @@ -709,19 +709,22 @@ static void ospf6_zebra_connected(struct zclient *zclient)  	zclient_send_reg_requests(zclient, VRF_DEFAULT);  } +static zclient_handler *const ospf6_handlers[] = { +	[ZEBRA_ROUTER_ID_UPDATE] = ospf6_router_id_update_zebra, +	[ZEBRA_INTERFACE_ADDRESS_ADD] = ospf6_zebra_if_address_update_add, +	[ZEBRA_INTERFACE_ADDRESS_DELETE] = ospf6_zebra_if_address_update_delete, +	[ZEBRA_REDISTRIBUTE_ROUTE_ADD] = ospf6_zebra_read_route, +	[ZEBRA_REDISTRIBUTE_ROUTE_DEL] = ospf6_zebra_read_route, +	[ZEBRA_NEXTHOP_UPDATE] = ospf6_zebra_import_check_update, +}; +  void ospf6_zebra_init(struct thread_master *master)  {  	/* Allocate zebra structure. */ -	zclient = zclient_new(master, &zclient_options_default); +	zclient = zclient_new(master, &zclient_options_default, ospf6_handlers, +			      array_size(ospf6_handlers));  	zclient_init(zclient, ZEBRA_ROUTE_OSPF6, 0, &ospf6d_privs);  	zclient->zebra_connected = ospf6_zebra_connected; -	zclient->router_id_update = ospf6_router_id_update_zebra; -	zclient->interface_address_add = ospf6_zebra_if_address_update_add; -	zclient->interface_address_delete = -		ospf6_zebra_if_address_update_delete; -	zclient->redistribute_route_add = ospf6_zebra_read_route; -	zclient->redistribute_route_del = ospf6_zebra_read_route; -	zclient->nexthop_update = ospf6_zebra_import_check_update;  	/* Install command element for zebra node. */  	install_element(VIEW_NODE, &show_ospf6_zebra_cmd); diff --git a/ospfd/ospf_zebra.c b/ospfd/ospf_zebra.c index 2ba976af5a..b0ed66da5f 100644 --- a/ospfd/ospf_zebra.c +++ b/ospfd/ospf_zebra.c @@ -2102,25 +2102,33 @@ static int ospf_zebra_client_close_notify(ZAPI_CALLBACK_ARGS)  	return ret;  } +static zclient_handler *const ospf_handlers[] = { +	[ZEBRA_ROUTER_ID_UPDATE] = ospf_router_id_update_zebra, +	[ZEBRA_INTERFACE_ADDRESS_ADD] = ospf_interface_address_add, +	[ZEBRA_INTERFACE_ADDRESS_DELETE] = ospf_interface_address_delete, +	[ZEBRA_INTERFACE_LINK_PARAMS] = ospf_interface_link_params, +	[ZEBRA_INTERFACE_VRF_UPDATE] = ospf_interface_vrf_update, + +	[ZEBRA_REDISTRIBUTE_ROUTE_ADD] = ospf_zebra_read_route, +	[ZEBRA_REDISTRIBUTE_ROUTE_DEL] = ospf_zebra_read_route, + +	[ZEBRA_OPAQUE_MESSAGE] = ospf_opaque_msg_handler, + +	[ZEBRA_CLIENT_CLOSE_NOTIFY] = ospf_zebra_client_close_notify, +}; +  void ospf_zebra_init(struct thread_master *master, unsigned short instance)  {  	/* Allocate zebra structure. */ -	zclient = zclient_new(master, &zclient_options_default); +	zclient = zclient_new(master, &zclient_options_default, ospf_handlers, +			      array_size(ospf_handlers));  	zclient_init(zclient, ZEBRA_ROUTE_OSPF, instance, &ospfd_privs);  	zclient->zebra_connected = ospf_zebra_connected; -	zclient->router_id_update = ospf_router_id_update_zebra; -	zclient->interface_address_add = ospf_interface_address_add; -	zclient->interface_address_delete = ospf_interface_address_delete; -	zclient->interface_link_params = ospf_interface_link_params; -	zclient->interface_vrf_update = ospf_interface_vrf_update; - -	zclient->redistribute_route_add = ospf_zebra_read_route; -	zclient->redistribute_route_del = ospf_zebra_read_route;  	/* Initialize special zclient for synchronous message exchanges. */  	struct zclient_options options = zclient_options_default;  	options.synchronous = true; -	zclient_sync = zclient_new(master, &options); +	zclient_sync = zclient_new(master, &options, NULL, 0);  	zclient_sync->sock = -1;  	zclient_sync->redist_default = ZEBRA_ROUTE_OSPF;  	zclient_sync->instance = instance; @@ -2135,10 +2143,6 @@ void ospf_zebra_init(struct thread_master *master, unsigned short instance)  	access_list_delete_hook(ospf_filter_update);  	prefix_list_add_hook(ospf_prefix_list_update);  	prefix_list_delete_hook(ospf_prefix_list_update); - -	zclient->opaque_msg_handler = ospf_opaque_msg_handler; - -	zclient->zebra_client_close_notify = ospf_zebra_client_close_notify;  }  void ospf_zebra_send_arp(const struct interface *ifp, const struct prefix *p) diff --git a/pathd/path_zebra.c b/pathd/path_zebra.c index 53d834f360..156267a394 100644 --- a/pathd/path_zebra.c +++ b/pathd/path_zebra.c @@ -320,6 +320,12 @@ static int path_zebra_opaque_msg_handler(ZAPI_CALLBACK_ARGS)  	return ret;  } +static zclient_handler *const path_handlers[] = { +	[ZEBRA_SR_POLICY_NOTIFY_STATUS] = path_zebra_sr_policy_notify_status, +	[ZEBRA_ROUTER_ID_UPDATE] = path_zebra_router_id_update, +	[ZEBRA_OPAQUE_MESSAGE] = path_zebra_opaque_msg_handler, +}; +  /**   * Initializes Zebra asynchronous connection.   * @@ -331,15 +337,13 @@ void path_zebra_init(struct thread_master *master)  	options.synchronous = true;  	/* Initialize asynchronous zclient. */ -	zclient = zclient_new(master, &zclient_options_default); +	zclient = zclient_new(master, &zclient_options_default, path_handlers, +			      array_size(path_handlers));  	zclient_init(zclient, ZEBRA_ROUTE_SRTE, 0, &pathd_privs);  	zclient->zebra_connected = path_zebra_connected; -	zclient->sr_policy_notify_status = path_zebra_sr_policy_notify_status; -	zclient->router_id_update = path_zebra_router_id_update; -	zclient->opaque_msg_handler = path_zebra_opaque_msg_handler;  	/* Initialize special zclient for synchronous message exchanges. */ -	zclient_sync = zclient_new(master, &options); +	zclient_sync = zclient_new(master, &options, NULL, 0);  	zclient_sync->sock = -1;  	zclient_sync->redist_default = ZEBRA_ROUTE_SRTE;  	zclient_sync->instance = 1; diff --git a/pbrd/pbr_zebra.c b/pbrd/pbr_zebra.c index 44c258cb3d..8a9bb0201e 100644 --- a/pbrd/pbr_zebra.c +++ b/pbrd/pbr_zebra.c @@ -429,20 +429,24 @@ static int pbr_zebra_nexthop_update(ZAPI_CALLBACK_ARGS)  extern struct zebra_privs_t pbr_privs; +static zclient_handler *const pbr_handlers[] = { +	[ZEBRA_INTERFACE_ADDRESS_ADD] = interface_address_add, +	[ZEBRA_INTERFACE_ADDRESS_DELETE] = interface_address_delete, +	[ZEBRA_INTERFACE_VRF_UPDATE] = interface_vrf_update, +	[ZEBRA_ROUTE_NOTIFY_OWNER] = route_notify_owner, +	[ZEBRA_RULE_NOTIFY_OWNER] = rule_notify_owner, +	[ZEBRA_NEXTHOP_UPDATE] = pbr_zebra_nexthop_update, +}; +  void pbr_zebra_init(void)  {  	struct zclient_options opt = { .receive_notify = true }; -	zclient = zclient_new(master, &opt); +	zclient = zclient_new(master, &opt, pbr_handlers, +			      array_size(pbr_handlers));  	zclient_init(zclient, ZEBRA_ROUTE_PBR, 0, &pbr_privs);  	zclient->zebra_connected = zebra_connected; -	zclient->interface_address_add = interface_address_add; -	zclient->interface_address_delete = interface_address_delete; -	zclient->interface_vrf_update = interface_vrf_update; -	zclient->route_notify_owner = route_notify_owner; -	zclient->rule_notify_owner = rule_notify_owner; -	zclient->nexthop_update = pbr_zebra_nexthop_update;  }  void pbr_send_rnh(struct nexthop *nhop, bool reg) diff --git a/pimd/pim_mlag.c b/pimd/pim_mlag.c index a06c0a6f4e..55d6e7e0fd 100644 --- a/pimd/pim_mlag.c +++ b/pimd/pim_mlag.c @@ -791,8 +791,10 @@ static void pim_mlag_process_mroute_del(struct mlag_mroute_del msg)  	pim_mlag_up_peer_del(&msg);  } -int pim_zebra_mlag_handle_msg(struct stream *s, int len) +int pim_zebra_mlag_handle_msg(int cmd, struct zclient *zclient, +			      uint16_t zapi_length, vrf_id_t vrf_id)  { +	struct stream *s = zclient->ibuf;  	struct mlag_msg mlag_msg;  	char buf[80];  	int rc = 0; @@ -880,7 +882,7 @@ int pim_zebra_mlag_handle_msg(struct stream *s, int len)  /****************End of PIM Mesasge processing handler********************/ -int pim_zebra_mlag_process_up(void) +int pim_zebra_mlag_process_up(ZAPI_CALLBACK_ARGS)  {  	if (PIM_DEBUG_MLAG)  		zlog_debug("%s: Received Process-Up from Mlag", __func__); @@ -908,7 +910,7 @@ static void pim_mlag_param_reset(void)  	router->peerlink_rif[0] = '\0';  } -int pim_zebra_mlag_process_down(void) +int pim_zebra_mlag_process_down(ZAPI_CALLBACK_ARGS)  {  	if (PIM_DEBUG_MLAG)  		zlog_debug("%s: Received Process-Down from Mlag", __func__); diff --git a/pimd/pim_mlag.h b/pimd/pim_mlag.h index b044c31c44..996e4d473f 100644 --- a/pimd/pim_mlag.h +++ b/pimd/pim_mlag.h @@ -24,6 +24,7 @@  #ifndef __PIM_MLAG_H__  #define __PIM_MLAG_H__ +#include "zclient.h"  #include "mlag.h"  #include "pim_iface.h" @@ -33,9 +34,9 @@ extern void pim_instance_mlag_init(struct pim_instance *pim);  extern void pim_instance_mlag_terminate(struct pim_instance *pim);  extern void pim_if_configure_mlag_dualactive(struct pim_interface *pim_ifp);  extern void pim_if_unconfigure_mlag_dualactive(struct pim_interface *pim_ifp); -extern int pim_zebra_mlag_process_up(void); -extern int pim_zebra_mlag_process_down(void); -extern int pim_zebra_mlag_handle_msg(struct stream *msg, int len); +extern int pim_zebra_mlag_process_up(ZAPI_CALLBACK_ARGS); +extern int pim_zebra_mlag_process_down(ZAPI_CALLBACK_ARGS); +extern int pim_zebra_mlag_handle_msg(ZAPI_CALLBACK_ARGS);  /* pm_zpthread.c */  extern int pim_mlag_signal_zpthread(void); diff --git a/pimd/pim_zebra.c b/pimd/pim_zebra.c index aa041df857..1da33af006 100644 --- a/pimd/pim_zebra.c +++ b/pimd/pim_zebra.c @@ -439,23 +439,29 @@ static void pim_zebra_capabilities(struct zclient_capabilities *cap)  	router->mlag_role = cap->role;  } +static zclient_handler *const pim_handlers[] = { +	[ZEBRA_ROUTER_ID_UPDATE] = pim_router_id_update_zebra, +	[ZEBRA_INTERFACE_ADDRESS_ADD] = pim_zebra_if_address_add, +	[ZEBRA_INTERFACE_ADDRESS_DELETE] = pim_zebra_if_address_del, +	[ZEBRA_INTERFACE_VRF_UPDATE] = pim_zebra_interface_vrf_update, +	[ZEBRA_NEXTHOP_UPDATE] = pim_parse_nexthop_update, + +	[ZEBRA_VXLAN_SG_ADD] = pim_zebra_vxlan_sg_proc, +	[ZEBRA_VXLAN_SG_DEL] = pim_zebra_vxlan_sg_proc, + +	[ZEBRA_MLAG_PROCESS_UP] = pim_zebra_mlag_process_up, +	[ZEBRA_MLAG_PROCESS_DOWN] = pim_zebra_mlag_process_down, +	[ZEBRA_MLAG_FORWARD_MSG] = pim_zebra_mlag_handle_msg, +}; +  void pim_zebra_init(void)  {  	/* Socket for receiving updates from Zebra daemon */ -	zclient = zclient_new(router->master, &zclient_options_default); +	zclient = zclient_new(router->master, &zclient_options_default, +			      pim_handlers, array_size(pim_handlers));  	zclient->zebra_capabilities = pim_zebra_capabilities;  	zclient->zebra_connected = pim_zebra_connected; -	zclient->router_id_update = pim_router_id_update_zebra; -	zclient->interface_address_add = pim_zebra_if_address_add; -	zclient->interface_address_delete = pim_zebra_if_address_del; -	zclient->interface_vrf_update = pim_zebra_interface_vrf_update; -	zclient->nexthop_update = pim_parse_nexthop_update; -	zclient->vxlan_sg_add = pim_zebra_vxlan_sg_proc; -	zclient->vxlan_sg_del = pim_zebra_vxlan_sg_proc; -	zclient->mlag_process_up = pim_zebra_mlag_process_up; -	zclient->mlag_process_down = pim_zebra_mlag_process_down; -	zclient->mlag_handle_msg = pim_zebra_mlag_handle_msg;  	zclient_init(zclient, ZEBRA_ROUTE_PIM, 0, &pimd_privs);  	if (PIM_DEBUG_PIM_TRACE) { diff --git a/pimd/pim_zlookup.c b/pimd/pim_zlookup.c index abf9577bd5..abf1119ac5 100644 --- a/pimd/pim_zlookup.c +++ b/pimd/pim_zlookup.c @@ -137,7 +137,7 @@ void zclient_lookup_new(void)  	struct zclient_options options = zclient_options_default;  	options.synchronous = true; -	zlookup = zclient_new(router->master, &options); +	zlookup = zclient_new(router->master, &options, NULL, 0);  	if (!zlookup) {  		flog_err(EC_LIB_ZAPI_SOCKET, "%s: zclient_new() failure",  			 __func__); diff --git a/ripd/rip_zebra.c b/ripd/rip_zebra.c index 074370dc26..1f15668635 100644 --- a/ripd/rip_zebra.c +++ b/ripd/rip_zebra.c @@ -230,17 +230,21 @@ static void rip_zebra_connected(struct zclient *zclient)  	zclient_send_reg_requests(zclient, VRF_DEFAULT);  } +zclient_handler *const rip_handlers[] = { +	[ZEBRA_INTERFACE_ADDRESS_ADD] = rip_interface_address_add, +	[ZEBRA_INTERFACE_ADDRESS_DELETE] = rip_interface_address_delete, +	[ZEBRA_INTERFACE_VRF_UPDATE] = rip_interface_vrf_update, +	[ZEBRA_REDISTRIBUTE_ROUTE_ADD] = rip_zebra_read_route, +	[ZEBRA_REDISTRIBUTE_ROUTE_DEL] = rip_zebra_read_route, +}; +  void rip_zclient_init(struct thread_master *master)  {  	/* Set default value to the zebra client structure. */ -	zclient = zclient_new(master, &zclient_options_default); +	zclient = zclient_new(master, &zclient_options_default, rip_handlers, +			      array_size(rip_handlers));  	zclient_init(zclient, ZEBRA_ROUTE_RIP, 0, &ripd_privs);  	zclient->zebra_connected = rip_zebra_connected; -	zclient->interface_address_add = rip_interface_address_add; -	zclient->interface_address_delete = rip_interface_address_delete; -	zclient->interface_vrf_update = rip_interface_vrf_update; -	zclient->redistribute_route_add = rip_zebra_read_route; -	zclient->redistribute_route_del = rip_zebra_read_route;  }  void rip_zclient_stop(void) diff --git a/ripngd/ripng_zebra.c b/ripngd/ripng_zebra.c index baf7f00961..4108aa506e 100644 --- a/ripngd/ripng_zebra.c +++ b/ripngd/ripng_zebra.c @@ -234,19 +234,23 @@ static void ripng_zebra_connected(struct zclient *zclient)  	zclient_send_reg_requests(zclient, VRF_DEFAULT);  } +static zclient_handler *const ripng_handlers[] = { +	[ZEBRA_INTERFACE_ADDRESS_ADD] = ripng_interface_address_add, +	[ZEBRA_INTERFACE_ADDRESS_DELETE] = ripng_interface_address_delete, +	[ZEBRA_INTERFACE_VRF_UPDATE] = ripng_interface_vrf_update, +	[ZEBRA_REDISTRIBUTE_ROUTE_ADD] = ripng_zebra_read_route, +	[ZEBRA_REDISTRIBUTE_ROUTE_DEL] = ripng_zebra_read_route, +}; +  /* Initialize zebra structure and it's commands. */  void zebra_init(struct thread_master *master)  {  	/* Allocate zebra structure. */ -	zclient = zclient_new(master, &zclient_options_default); +	zclient = zclient_new(master, &zclient_options_default, ripng_handlers, +			      array_size(ripng_handlers));  	zclient_init(zclient, ZEBRA_ROUTE_RIPNG, 0, &ripngd_privs);  	zclient->zebra_connected = ripng_zebra_connected; -	zclient->interface_address_add = ripng_interface_address_add; -	zclient->interface_address_delete = ripng_interface_address_delete; -	zclient->interface_vrf_update = ripng_interface_vrf_update; -	zclient->redistribute_route_add = ripng_zebra_read_route; -	zclient->redistribute_route_del = ripng_zebra_read_route;  }  void ripng_zebra_stop(void) diff --git a/sharpd/sharp_zebra.c b/sharpd/sharp_zebra.c index 67cff378ee..8c9f0c2784 100644 --- a/sharpd/sharp_zebra.c +++ b/sharpd/sharp_zebra.c @@ -720,6 +720,10 @@ void sharp_redistribute_vrf(struct vrf *vrf, int type)  				0, vrf->vrf_id);  } +static zclient_handler *const sharp_opaque_handlers[] = { +	[ZEBRA_OPAQUE_MESSAGE] = sharp_opaque_handler, +}; +  /* Add a zclient with a specified session id, for testing. */  int sharp_zclient_create(uint32_t session_id)  { @@ -732,15 +736,14 @@ int sharp_zclient_create(uint32_t session_id)  			return -1;  	} -	client = zclient_new(master, &zclient_options_default); +	client = zclient_new(master, &zclient_options_default, +			     sharp_opaque_handlers, +			     array_size(sharp_opaque_handlers));  	client->sock = -1;  	client->session_id = session_id;  	zclient_init(client, ZEBRA_ROUTE_SHARP, 0, &sharp_privs); -	/* Register handlers for messages we expect this session to see */ -	client->opaque_msg_handler = sharp_opaque_handler; -  	/* Enqueue on the list of test clients */  	add_zclient(client); @@ -928,7 +931,7 @@ int sharp_zebra_srv6_manager_release_locator_chunk(const char *locator_name)  	return srv6_manager_release_locator_chunk(zclient, locator_name);  } -static void sharp_zebra_process_srv6_locator_chunk(ZAPI_CALLBACK_ARGS) +static int sharp_zebra_process_srv6_locator_chunk(ZAPI_CALLBACK_ARGS)  {  	struct stream *s = NULL;  	struct srv6_locator_chunk s6c = {}; @@ -951,17 +954,31 @@ static void sharp_zebra_process_srv6_locator_chunk(ZAPI_CALLBACK_ARGS)  		for (ALL_LIST_ELEMENTS_RO(loc->chunks, chunk_node, c))  			if (!prefix_cmp(c, &s6c.prefix)) -				return; +				return 0;  		chunk = prefix_ipv6_new();  		*chunk = s6c.prefix;  		listnode_add(loc->chunks, chunk); -		return; +		return 0;  	}  	zlog_err("%s: can't get locator_chunk!!", __func__); +	return 0;  } +static zclient_handler *const sharp_handlers[] = { +	[ZEBRA_INTERFACE_ADDRESS_ADD] = interface_address_add, +	[ZEBRA_INTERFACE_ADDRESS_DELETE] = interface_address_delete, +	[ZEBRA_ROUTE_NOTIFY_OWNER] = route_notify_owner, +	[ZEBRA_NEXTHOP_UPDATE] = sharp_nexthop_update, +	[ZEBRA_NHG_NOTIFY_OWNER] = nhg_notify_owner, +	[ZEBRA_REDISTRIBUTE_ROUTE_ADD] = sharp_redistribute_route, +	[ZEBRA_REDISTRIBUTE_ROUTE_DEL] = sharp_redistribute_route, +	[ZEBRA_OPAQUE_MESSAGE] = sharp_opaque_handler, +	[ZEBRA_SRV6_MANAGER_GET_LOCATOR_CHUNK] = +		sharp_zebra_process_srv6_locator_chunk, +}; +  void sharp_zebra_init(void)  {  	struct zclient_options opt = {.receive_notify = true}; @@ -969,19 +986,10 @@ void sharp_zebra_init(void)  	if_zapi_callbacks(sharp_ifp_create, sharp_ifp_up,  			  sharp_ifp_down, sharp_ifp_destroy); -	zclient = zclient_new(master, &opt); +	zclient = zclient_new(master, &opt, sharp_handlers, +			      array_size(sharp_handlers));  	zclient_init(zclient, ZEBRA_ROUTE_SHARP, 0, &sharp_privs);  	zclient->zebra_connected = zebra_connected; -	zclient->interface_address_add = interface_address_add; -	zclient->interface_address_delete = interface_address_delete; -	zclient->route_notify_owner = route_notify_owner; -	zclient->nexthop_update = sharp_nexthop_update; -	zclient->nhg_notify_owner = nhg_notify_owner;  	zclient->zebra_buffer_write_ready = sharp_zclient_buffer_ready; -	zclient->redistribute_route_add = sharp_redistribute_route; -	zclient->redistribute_route_del = sharp_redistribute_route; -	zclient->opaque_msg_handler = sharp_opaque_handler; -	zclient->process_srv6_locator_chunk = -		sharp_zebra_process_srv6_locator_chunk;  } diff --git a/staticd/static_zebra.c b/staticd/static_zebra.c index a01ecad815..538fae28aa 100644 --- a/staticd/static_zebra.c +++ b/staticd/static_zebra.c @@ -508,6 +508,13 @@ extern void static_zebra_route_add(struct static_path *pn, bool install)  			   zclient, &api);  } +static zclient_handler *const static_handlers[] = { +	[ZEBRA_INTERFACE_ADDRESS_ADD] = interface_address_add, +	[ZEBRA_INTERFACE_ADDRESS_DELETE] = interface_address_delete, +	[ZEBRA_ROUTE_NOTIFY_OWNER] = route_notify_owner, +	[ZEBRA_NEXTHOP_UPDATE] = static_zebra_nexthop_update, +}; +  void static_zebra_init(void)  {  	struct zclient_options opt = { .receive_notify = true }; @@ -515,15 +522,12 @@ void static_zebra_init(void)  	if_zapi_callbacks(static_ifp_create, static_ifp_up,  			  static_ifp_down, static_ifp_destroy); -	zclient = zclient_new(master, &opt); +	zclient = zclient_new(master, &opt, static_handlers, +			      array_size(static_handlers));  	zclient_init(zclient, ZEBRA_ROUTE_STATIC, 0, &static_privs);  	zclient->zebra_capabilities = static_zebra_capabilities;  	zclient->zebra_connected = zebra_connected; -	zclient->interface_address_add = interface_address_add; -	zclient->interface_address_delete = interface_address_delete; -	zclient->route_notify_owner = route_notify_owner; -	zclient->nexthop_update = static_zebra_nexthop_update;  	static_nht_hash = hash_create(static_nht_hash_key,  				      static_nht_hash_cmp, diff --git a/tests/bgpd/test_mpath.c b/tests/bgpd/test_mpath.c index 77fd876594..d1ca356b94 100644 --- a/tests/bgpd/test_mpath.c +++ b/tests/bgpd/test_mpath.c @@ -392,7 +392,7 @@ static int global_test_init(void)  {  	qobj_init();  	master = thread_master_create(NULL); -	zclient = zclient_new(master, &zclient_options_default); +	zclient = zclient_new(master, &zclient_options_default, NULL, 0);  	bgp_master_init(master, BGP_SOCKET_SNDBUF_SIZE, list_new());  	vrf_init(NULL, NULL, NULL, NULL, NULL);  	bgp_option_set(BGP_OPT_NO_LISTEN); diff --git a/tests/topotests/bfd_isis_topo1/test_bfd_isis_topo1.py b/tests/topotests/bfd_isis_topo1/test_bfd_isis_topo1.py index 863c296927..27a4419329 100644 --- a/tests/topotests/bfd_isis_topo1/test_bfd_isis_topo1.py +++ b/tests/topotests/bfd_isis_topo1/test_bfd_isis_topo1.py @@ -193,7 +193,7 @@ def test_bfd_isis_interface_failure_rt2_step3():      # initial 2 seconds to let the CI not suffer.      # TODO: add check for array size      router_compare_json_output( -        "rt1", "show ip route isis json", "step3/show_ip_route_rt2_down.ref", 20, 10 +        "rt1", "show ip route isis json", "step3/show_ip_route_rt2_down.ref", 20, 1      )      router_compare_json_output(          "rt1", "show ipv6 route isis json", "step3/show_ipv6_route_rt2_down.ref", 20, 1 diff --git a/tests/topotests/bgp_l3vpn_to_bgp_direct/scripts/adjacencies.py b/tests/topotests/bgp_l3vpn_to_bgp_direct/scripts/adjacencies.py index 789f93b837..6cd92e293d 100644 --- a/tests/topotests/bgp_l3vpn_to_bgp_direct/scripts/adjacencies.py +++ b/tests/topotests/bgp_l3vpn_to_bgp_direct/scripts/adjacencies.py @@ -7,11 +7,18 @@ luCommand("ce1", 'vtysh -c "show bgp summary"', " 00:0", "wait", "Adjacencies up  luCommand("ce2", 'vtysh -c "show bgp summary"', " 00:0", "wait", "Adjacencies up", 180)  luCommand("ce3", 'vtysh -c "show bgp summary"', " 00:0", "wait", "Adjacencies up", 180)  luCommand( +    "r1", 'vtysh -c "show ip route ospf"', "2.2.2.2", "wait", "OSPF Route has Arrived", 60) +luCommand(      "r1", "ping 2.2.2.2 -c 1", " 0. packet loss", "wait", "PE->P2 (loopback) ping", 60  )  luCommand( +    "r3", 'vtysh -c "show ip route ospf"', "2.2.2.2", "wait", "OSPF Route has Arrived", 60) +luCommand(      "r3", "ping 2.2.2.2 -c 1", " 0. packet loss", "wait", "PE->P2 (loopback) ping", 60  ) + +luCommand( +    "r4", 'vtysh -c "show ip route ospf"', "2.2.2.2", "wait", "OSPF Route has Arrived", 60)  luCommand(      "r4", "ping 2.2.2.2 -c 1", " 0. packet loss", "wait", "PE->P2 (loopback) ping", 60  ) diff --git a/vrrpd/vrrp_zebra.c b/vrrpd/vrrp_zebra.c index 385d443571..d7d37f1f33 100644 --- a/vrrpd/vrrp_zebra.c +++ b/vrrpd/vrrp_zebra.c @@ -188,18 +188,22 @@ void vrrp_zclient_send_interface_protodown(struct interface *ifp, bool down)  	zclient_send_interface_protodown(zclient, ifp->vrf_id, ifp, down);  } +static zclient_handler *const vrrp_handlers[] = { +	[ZEBRA_ROUTER_ID_UPDATE] = vrrp_router_id_update_zebra, +	[ZEBRA_INTERFACE_ADDRESS_ADD] = vrrp_zebra_if_address_add, +	[ZEBRA_INTERFACE_ADDRESS_DELETE] = vrrp_zebra_if_address_del, +}; +  void vrrp_zebra_init(void)  {  	if_zapi_callbacks(vrrp_ifp_create, vrrp_ifp_up,  			  vrrp_ifp_down, vrrp_ifp_destroy);  	/* Socket for receiving updates from Zebra daemon */ -	zclient = zclient_new(master, &zclient_options_default); +	zclient = zclient_new(master, &zclient_options_default, vrrp_handlers, +			      array_size(vrrp_handlers));  	zclient->zebra_connected = vrrp_zebra_connected; -	zclient->router_id_update = vrrp_router_id_update_zebra; -	zclient->interface_address_add = vrrp_zebra_if_address_add; -	zclient->interface_address_delete = vrrp_zebra_if_address_del;  	zclient_init(zclient, ZEBRA_ROUTE_VRRP, 0, &vrrp_privs); diff --git a/zebra/debug_nl.c b/zebra/debug_nl.c index 842579f89e..2175aaff60 100644 --- a/zebra/debug_nl.c +++ b/zebra/debug_nl.c @@ -29,6 +29,7 @@  #include <stdint.h>  #include "zebra/rt_netlink.h" +#include "zebra/kernel_netlink.h"  const char *nlmsg_type2str(uint16_t type)  { diff --git a/zebra/kernel_netlink.h b/zebra/kernel_netlink.h index 37c76b9e59..cf8b8c785e 100644 --- a/zebra/kernel_netlink.h +++ b/zebra/kernel_netlink.h @@ -27,6 +27,10 @@ extern "C" {  #ifdef HAVE_NETLINK +#define RTM_NHA(h)                                                             \ +	((struct rtattr *)(((char *)(h)) + NLMSG_ALIGN(sizeof(struct nhmsg)))) + +  #define NL_RCV_PKT_BUF_SIZE     32768  #define NL_PKT_BUF_SIZE         8192 diff --git a/zebra/zapi_msg.c b/zebra/zapi_msg.c index 6cb4cf5ca1..61bd1417d1 100644 --- a/zebra/zapi_msg.c +++ b/zebra/zapi_msg.c @@ -3440,6 +3440,7 @@ static inline void zebra_gre_get(ZAPI_HANDLER_ARGS)  		stream_putl(s, IFINDEX_INTERNAL);  		stream_putl(s, VRF_UNKNOWN);  		stream_putl(s, 0); +		stream_putl(s, 0);  	}  	/* Write packet size. */  	stream_putw_at(s, 0, stream_get_endp(s)); diff --git a/zebra/zebra_vty.c b/zebra/zebra_vty.c index 5b79de9697..2cb2b5118b 100644 --- a/zebra/zebra_vty.c +++ b/zebra/zebra_vty.c @@ -449,6 +449,8 @@ static void zebra_show_ip_route_opaque(struct vty *vty, struct route_entry *re,  					       bzo.community);  			json_object_string_add(json, "largeCommunities",  					       bzo.lcommunity); +			json_object_string_add(json, "selectionReason", +					       bzo.selection_reason);  		} else {  			vty_out(vty, "    AS-Path          : %s\n", bzo.aspath); @@ -459,6 +461,9 @@ static void zebra_show_ip_route_opaque(struct vty *vty, struct route_entry *re,  			if (bzo.lcommunity[0] != '\0')  				vty_out(vty, "    Large-Communities: %s\n",  					bzo.lcommunity); + +			vty_out(vty, "    Selection reason : %s\n", +				bzo.selection_reason);  		}  	}  	default:  | 
