diff options
| author | Chirag Shah <chirag@nvidia.com> | 2020-08-12 13:30:24 -0700 | 
|---|---|---|
| committer | Chirag Shah <chirag@nvidia.com> | 2020-10-03 11:25:37 -0700 | 
| commit | ff8a8a7ac10b3211d5586c29dfcc5a3b32841029 (patch) | |
| tree | 3a6354d31147a423a90c05a6abb3a48fcfde83a5 | |
| parent | e4a464160dee2b53f2851879b2c736139061e74c (diff) | |
bgpd: convert global config to transactional cli
Convert global congigurations clis to transactional
clis using northbound plugin callbacks.
Signed-off-by: Chirag Shah <chirag@nvidia.com>
| -rw-r--r-- | bgpd/bgp_mplsvpn.c | 6 | ||||
| -rw-r--r-- | bgpd/bgp_mplsvpn.h | 2 | ||||
| -rw-r--r-- | bgpd/bgp_nb.c | 41 | ||||
| -rw-r--r-- | bgpd/bgp_nb.h | 68 | ||||
| -rw-r--r-- | bgpd/bgp_nb_config.c | 1033 | ||||
| -rw-r--r-- | bgpd/bgp_vty.c | 1756 | ||||
| -rw-r--r-- | bgpd/bgp_vty.h | 7 | ||||
| -rw-r--r-- | bgpd/bgpd.c | 10 | ||||
| -rw-r--r-- | bgpd/bgpd.h | 7 | ||||
| -rw-r--r-- | yang/frr-bgp-common.yang | 2 | 
10 files changed, 1887 insertions, 1045 deletions
diff --git a/bgpd/bgp_mplsvpn.c b/bgpd/bgp_mplsvpn.c index 5ef3cf736d..b33251635c 100644 --- a/bgpd/bgp_mplsvpn.c +++ b/bgpd/bgp_mplsvpn.c @@ -2581,7 +2581,7 @@ void vpn_leak_postchange_all(void)   * also VRF Y should unimport its routes from VRF X table.   * This will ensure VPN table is cleaned up appropriately.   */ -int bgp_vpn_leak_unimport(struct bgp *from_bgp, struct vty *vty) +void bgp_vpn_leak_unimport(struct bgp *from_bgp)  {  	struct bgp *to_bgp;  	const char *tmp_name; @@ -2593,7 +2593,7 @@ int bgp_vpn_leak_unimport(struct bgp *from_bgp, struct vty *vty)  	int debug;  	if (from_bgp->inst_type != BGP_INSTANCE_TYPE_VRF) -		return 0; +		return;  	debug = (BGP_DEBUG(vpn, VPN_LEAK_TO_VRF) |  		     BGP_DEBUG(vpn, VPN_LEAK_FROM_VRF)); @@ -2662,7 +2662,7 @@ int bgp_vpn_leak_unimport(struct bgp *from_bgp, struct vty *vty)  			}  		}  	} -	return 0; +	return;  }  /* When a router bgp is configured, there could be a bgp vrf diff --git a/bgpd/bgp_mplsvpn.h b/bgpd/bgp_mplsvpn.h index ccd0d96169..df2544d608 100644 --- a/bgpd/bgp_mplsvpn.h +++ b/bgpd/bgp_mplsvpn.h @@ -266,7 +266,7 @@ extern vrf_id_t get_first_vrf_for_redirect_with_rt(struct ecommunity *eckey);  extern void vpn_leak_postchange_all(void);  extern void vpn_handle_router_id_update(struct bgp *bgp, bool withdraw,  					bool is_config); -extern int bgp_vpn_leak_unimport(struct bgp *from_bgp, struct vty *vty); +extern void bgp_vpn_leak_unimport(struct bgp *from_bgp);  extern void bgp_vpn_leak_export(struct bgp *from_bgp);  #endif /* _QUAGGA_BGP_MPLSVPN_H */ diff --git a/bgpd/bgp_nb.c b/bgpd/bgp_nb.c index 1983b7ae6c..b4a4269b00 100644 --- a/bgpd/bgp_nb.c +++ b/bgpd/bgp_nb.c @@ -29,6 +29,7 @@ const struct frr_yang_module_info frr_bgp_info = {  		{  			.xpath = "/frr-routing:routing/control-plane-protocols/control-plane-protocol/frr-bgp:bgp/global",  			.cbs = { +				.cli_show = cli_show_router_bgp,  				.create = routing_control_plane_protocols_control_plane_protocol_bgp_global_create,  				.destroy = routing_control_plane_protocols_control_plane_protocol_bgp_global_destroy,  			} @@ -42,6 +43,7 @@ const struct frr_yang_module_info frr_bgp_info = {  		{  			.xpath = "/frr-routing:routing/control-plane-protocols/control-plane-protocol/frr-bgp:bgp/global/router-id",  			.cbs = { +				.cli_show = cli_show_router_bgp_router_id,  				.modify = routing_control_plane_protocols_control_plane_protocol_bgp_global_router_id_modify,  				.destroy = routing_control_plane_protocols_control_plane_protocol_bgp_global_router_id_destroy,  			} @@ -49,6 +51,7 @@ const struct frr_yang_module_info frr_bgp_info = {  		{  			.xpath = "/frr-routing:routing/control-plane-protocols/control-plane-protocol/frr-bgp:bgp/global/confederation/identifier",  			.cbs = { +				.cli_show = cli_show_router_bgp_confederation_identifier,  				.modify = routing_control_plane_protocols_control_plane_protocol_bgp_global_confederation_identifier_modify,  				.destroy = routing_control_plane_protocols_control_plane_protocol_bgp_global_confederation_identifier_destroy,  			} @@ -56,11 +59,19 @@ const struct frr_yang_module_info frr_bgp_info = {  		{  			.xpath = "/frr-routing:routing/control-plane-protocols/control-plane-protocol/frr-bgp:bgp/global/confederation/member-as",  			.cbs = { +				.cli_show = cli_show_router_bgp_confederation_member_as,  				.create = routing_control_plane_protocols_control_plane_protocol_bgp_global_confederation_member_as_create,  				.destroy = routing_control_plane_protocols_control_plane_protocol_bgp_global_confederation_member_as_destroy,  			}  		},  		{ +			.xpath = "/frr-routing:routing/control-plane-protocols/control-plane-protocol/frr-bgp:bgp/global/med-config", +			.cbs = { +				.cli_show = cli_show_router_bgp_med_config, +				.apply_finish = routing_control_plane_protocols_control_plane_protocol_bgp_global_med_config_apply_finish, +			} +		}, +		{  			.xpath = "/frr-routing:routing/control-plane-protocols/control-plane-protocol/frr-bgp:bgp/global/med-config/enable-med-admin",  			.cbs = {  				.modify = routing_control_plane_protocols_control_plane_protocol_bgp_global_med_config_enable_med_admin_modify, @@ -86,6 +97,12 @@ const struct frr_yang_module_info frr_bgp_info = {  			}  		},  		{ +			.xpath = "/frr-routing:routing/control-plane-protocols/control-plane-protocol/frr-bgp:bgp/global/route-reflector", +			.cbs = { +				.cli_show = cli_show_router_bgp_route_reflector, +			} +		}, +		{  			.xpath = "/frr-routing:routing/control-plane-protocols/control-plane-protocol/frr-bgp:bgp/global/route-reflector/route-reflector-cluster-id",  			.cbs = {  				.modify = routing_control_plane_protocols_control_plane_protocol_bgp_global_route_reflector_route_reflector_cluster_id_modify, @@ -105,6 +122,13 @@ const struct frr_yang_module_info frr_bgp_info = {  			}  		},  		{ +			.xpath = "/frr-routing:routing/control-plane-protocols/control-plane-protocol/frr-bgp:bgp/global/route-selection-options", +			.cbs = { +				.apply_finish = routing_control_plane_protocols_control_plane_protocol_bgp_global_route_selection_options_apply_finish, +				.cli_show = cli_show_router_bgp_route_selection, +			} +		}, +		{  			.xpath = "/frr-routing:routing/control-plane-protocols/control-plane-protocol/frr-bgp:bgp/global/route-selection-options/always-compare-med",  			.cbs = {  				.modify = routing_control_plane_protocols_control_plane_protocol_bgp_global_route_selection_options_always_compare_med_modify, @@ -160,6 +184,12 @@ const struct frr_yang_module_info frr_bgp_info = {  			}  		},  		{ +			.xpath = "/frr-routing:routing/control-plane-protocols/control-plane-protocol/frr-bgp:bgp/global/global-neighbor-config", +			.cbs = { +				.cli_show = cli_show_router_global_neighbor_config, +			} +		}, +		{  			.xpath = "/frr-routing:routing/control-plane-protocols/control-plane-protocol/frr-bgp:bgp/global/global-neighbor-config/dynamic-neighbors-limit",  			.cbs = {  				.modify = routing_control_plane_protocols_control_plane_protocol_bgp_global_global_neighbor_config_dynamic_neighbors_limit_modify, @@ -231,12 +261,14 @@ const struct frr_yang_module_info frr_bgp_info = {  		{  			.xpath = "/frr-routing:routing/control-plane-protocols/control-plane-protocol/frr-bgp:bgp/global/global-update-group-config/subgroup-pkt-queue-size",  			.cbs = { +				.cli_show = cli_show_router_global_update_group_config_subgroup_pkt_queue_size,  				.modify = routing_control_plane_protocols_control_plane_protocol_bgp_global_global_update_group_config_subgroup_pkt_queue_size_modify,  			}  		},  		{  			.xpath = "/frr-routing:routing/control-plane-protocols/control-plane-protocol/frr-bgp:bgp/global/global-update-group-config/coalesce-time",  			.cbs = { +				.cli_show = cli_show_router_global_update_group_config_coalesce_time,  				.modify = routing_control_plane_protocols_control_plane_protocol_bgp_global_global_update_group_config_coalesce_time_modify,  			}  		}, @@ -287,54 +319,63 @@ const struct frr_yang_module_info frr_bgp_info = {  		{  			.xpath = "/frr-routing:routing/control-plane-protocols/control-plane-protocol/frr-bgp:bgp/global/ebgp-multihop-connected-route-check",  			.cbs = { +				.cli_show = cli_show_router_global_ebgp_multihop_connected_route_check,  				.modify = routing_control_plane_protocols_control_plane_protocol_bgp_global_ebgp_multihop_connected_route_check_modify,  			}  		},  		{  			.xpath = "/frr-routing:routing/control-plane-protocols/control-plane-protocol/frr-bgp:bgp/global/fast-external-failover",  			.cbs = { +				.cli_show = cli_show_router_bgp_fast_external_failover,  				.modify = routing_control_plane_protocols_control_plane_protocol_bgp_global_fast_external_failover_modify,  			}  		},  		{  			.xpath = "/frr-routing:routing/control-plane-protocols/control-plane-protocol/frr-bgp:bgp/global/local-pref",  			.cbs = { +				.cli_show = cli_show_router_bgp_local_pref,  				.modify = routing_control_plane_protocols_control_plane_protocol_bgp_global_local_pref_modify,  			}  		},  		{  			.xpath = "/frr-routing:routing/control-plane-protocols/control-plane-protocol/frr-bgp:bgp/global/default-shutdown",  			.cbs = { +				.cli_show = cli_show_router_bgp_default_shutdown,  				.modify = routing_control_plane_protocols_control_plane_protocol_bgp_global_default_shutdown_modify,  			}  		},  		{  			.xpath = "/frr-routing:routing/control-plane-protocols/control-plane-protocol/frr-bgp:bgp/global/ebgp-requires-policy",  			.cbs = { +				.cli_show = cli_show_router_bgp_ebgp_requires_policy,  				.modify = routing_control_plane_protocols_control_plane_protocol_bgp_global_ebgp_requires_policy_modify,  			}  		},  		{  			.xpath = "/frr-routing:routing/control-plane-protocols/control-plane-protocol/frr-bgp:bgp/global/show-hostname",  			.cbs = { +				.cli_show = cli_show_router_bgp_show_hostname,  				.modify = routing_control_plane_protocols_control_plane_protocol_bgp_global_show_hostname_modify,  			}  		},  		{  			.xpath = "/frr-routing:routing/control-plane-protocols/control-plane-protocol/frr-bgp:bgp/global/show-nexthop-hostname",  			.cbs = { +				.cli_show = cli_show_router_bgp_show_nexthop_hostname,  				.modify = routing_control_plane_protocols_control_plane_protocol_bgp_global_show_nexthop_hostname_modify,  			}  		},  		{  			.xpath = "/frr-routing:routing/control-plane-protocols/control-plane-protocol/frr-bgp:bgp/global/import-check",  			.cbs = { +				.cli_show = cli_show_router_bgp_import_check,  				.modify = routing_control_plane_protocols_control_plane_protocol_bgp_global_import_check_modify,  			}  		},  		{  			.xpath = "/frr-routing:routing/control-plane-protocols/control-plane-protocol/frr-bgp:bgp/global/graceful-shutdown/enable",  			.cbs = { +				.cli_show = cli_show_router_bgp_graceful_shutdown,  				.modify = routing_control_plane_protocols_control_plane_protocol_bgp_global_graceful_shutdown_enable_modify,  			}  		}, diff --git a/bgpd/bgp_nb.h b/bgpd/bgp_nb.h index ecfdf987dc..2bed6bcfe6 100644 --- a/bgpd/bgp_nb.h +++ b/bgpd/bgp_nb.h @@ -3406,4 +3406,72 @@ int routing_control_plane_protocols_control_plane_protocol_bgp_peer_groups_peer_  	struct nb_cb_modify_args *args);  int routing_control_plane_protocols_control_plane_protocol_bgp_peer_groups_peer_group_afi_safis_afi_safi_ipv6_flowspec_soft_reconfiguration_modify(  	struct nb_cb_modify_args *args); + +/* Optional 'cli_show' callbacks. */ +void cli_show_router_bgp(struct vty *vty, struct lyd_node *dnode, +			 bool show_defaults); +void cli_show_router_bgp_router_id(struct vty *vty, struct lyd_node *dnode, +				   bool show_defaults); +void cli_show_router_bgp_route_selection(struct vty *vty, +					 struct lyd_node *dnode, +					 bool show_defaults); +void cli_show_router_bgp_ebgp_requires_policy(struct vty *vty, +					      struct lyd_node *dnode, +					      bool show_defaults); +void cli_show_router_bgp_default_shutdown(struct vty *vty, +					  struct lyd_node *dnode, +					  bool show_defaults); +void cli_show_router_bgp_import_check(struct vty *vty, struct lyd_node *dnode, +				      bool show_defaults); +void cli_show_router_bgp_show_hostname(struct vty *vty, struct lyd_node *dnode, +				       bool show_defaults); +void cli_show_router_bgp_show_nexthop_hostname(struct vty *vty, +					       struct lyd_node *dnode, +					       bool show_defaults); +void cli_show_router_bgp_fast_external_failover(struct vty *vty, +						struct lyd_node *dnode, +						bool show_defaults); +void cli_show_router_global_neighbor_config(struct vty *vty, +					    struct lyd_node *dnode, +					    bool show_defaults); +void cli_show_router_global_update_group_config_subgroup_pkt_queue_size( +	struct vty *vty, struct lyd_node *dnode, bool show_defaults); +void cli_show_router_global_update_group_config_coalesce_time( +	struct vty *vty, struct lyd_node *dnode, bool show_defaults); +void cli_show_router_global_ebgp_multihop_connected_route_check( +	struct vty *vty, struct lyd_node *dnode, bool show_defaults); +void cli_show_router_bgp_local_pref(struct vty *vty, struct lyd_node *dnode, +				    bool show_defaults); +void cli_show_router_bgp_route_reflector(struct vty *vty, +					 struct lyd_node *dnode, +					 bool show_defaults); +void cli_show_router_bgp_confederation_identifier(struct vty *vty, +						  struct lyd_node *dnode, +						  bool show_defaults); +void cli_show_router_bgp_confederation_member_as(struct vty *vty, +						 struct lyd_node *dnode, +						 bool show_defaults); +void cli_show_router_bgp_graceful_shutdown(struct vty *vty, +					   struct lyd_node *dnode, +					   bool show_defaults); +void cli_show_router_bgp_med_config(struct vty *vty, struct lyd_node *dnode, +				    bool show_defaults); + +void routing_control_plane_protocols_control_plane_protocol_bgp_global_route_selection_options_apply_finish( +	struct nb_cb_apply_finish_args *args); +void routing_control_plane_protocols_control_plane_protocol_bgp_global_med_config_apply_finish( +	struct nb_cb_apply_finish_args *args); + +/* xpath macros */ +/* route-list */ +#define FRR_BGP_GLOBAL_XPATH                                                   \ +	"/frr-routing:routing/control-plane-protocols/"                        \ +	"control-plane-protocol[type='%s'][name='%s'][vrf='%s']/"              \ +	"frr-bgp:bgp/global" + +#define FRR_BGP_GLOBAL_AS_XPATH                                                \ +	"/frr-routing:routing/control-plane-protocols/"                        \ +	"control-plane-protocol[type='%s'][name='%s'][vrf='%s']/"              \ +	"frr-bgp:bgp/local-as[" +  #endif diff --git a/bgpd/bgp_nb_config.c b/bgpd/bgp_nb_config.c index a0b65056c4..e3bb7ec295 100644 --- a/bgpd/bgp_nb_config.c +++ b/bgpd/bgp_nb_config.c @@ -25,6 +25,24 @@  #include "bgpd/bgp_nb.h"  #include "bgpd/bgpd.h"  #include "bgpd/bgp_vty.h" +#include "bgpd/bgp_mplsvpn.h" +#include "bgpd/bgp_fsm.h" +#include "bgpd/bgp_addpath.h" +#include "bgpd/bgp_updgrp.h" +#include "bgpd/bgp_io.h" + +FRR_CFG_DEFAULT_ULONG(BGP_CONNECT_RETRY, +        { .val_ulong = 10, .match_profile = "datacenter", }, +        { .val_ulong = 120 }, +) +FRR_CFG_DEFAULT_ULONG(BGP_HOLDTIME, +        { .val_ulong = 9, .match_profile = "datacenter", }, +        { .val_ulong = 180 }, +) +FRR_CFG_DEFAULT_ULONG(BGP_KEEPALIVE, +        { .val_ulong = 3, .match_profile = "datacenter", }, +        { .val_ulong = 60 }, +)  /*   * XPath: @@ -33,12 +51,70 @@  int routing_control_plane_protocols_control_plane_protocol_bgp_global_create(  	struct nb_cb_create_args *args)  { + +	const struct lyd_node *vrf_dnode; +	struct bgp *bgp; +	struct vrf *vrf; +	const char *name = NULL; +	as_t as; +	enum bgp_instance_type inst_type; +	bool is_view_inst = false; +	int ret; +	int is_new_bgp = 0; + +	inst_type = BGP_INSTANCE_TYPE_DEFAULT; +  	switch (args->event) {  	case NB_EV_VALIDATE:  	case NB_EV_PREPARE:  	case NB_EV_ABORT: +		return NB_OK;  	case NB_EV_APPLY: -		/* TODO: implement me. */ +		vrf_dnode = yang_dnode_get_parent(args->dnode, +						  "control-plane-protocol"); +		vrf = nb_running_get_entry(vrf_dnode, NULL, true); + +		if (strmatch(vrf->name, VRF_DEFAULT_NAME)) { +			name = NULL; +		} else { +			name = vrf->name; +			inst_type = BGP_INSTANCE_TYPE_VRF; +		} + +		as = yang_dnode_get_uint32(args->dnode, "./local-as"); + +		is_view_inst = yang_dnode_get_bool(args->dnode, +						   "./instance-type-view"); +		if (is_view_inst) +			inst_type = BGP_INSTANCE_TYPE_VIEW; + +		if (inst_type == BGP_INSTANCE_TYPE_DEFAULT) +			is_new_bgp = (bgp_lookup(as, name) == NULL); + +		ret = bgp_get_vty(&bgp, &as, name, inst_type); +		if (ret == BGP_ERR_INSTANCE_MISMATCH) { +			snprintf( +				args->errmsg, args->errmsg_len, +				"BGP instance name and AS number mismatch\nBGP instance is already running; AS is %u", +				as); + +			return NB_ERR_INCONSISTENCY; +		} +		/* +		 * If we just instantiated the default instance, complete +		 * any pending VRF-VPN leaking that was configured via +		 * earlier "router bgp X vrf FOO" blocks. +		 */ +		if (is_new_bgp && inst_type == BGP_INSTANCE_TYPE_DEFAULT) +			vpn_leak_postchange_all(); + +		if (inst_type == BGP_INSTANCE_TYPE_VRF) +			bgp_vpn_leak_export(bgp); + +		UNSET_FLAG(bgp->vrf_flags, BGP_VRF_AUTO); + +		nb_running_set_entry(args->dnode, bgp); +  		break;  	} @@ -48,12 +124,44 @@ int routing_control_plane_protocols_control_plane_protocol_bgp_global_create(  int routing_control_plane_protocols_control_plane_protocol_bgp_global_destroy(  	struct nb_cb_destroy_args *args)  { +	struct bgp *bgp; +  	switch (args->event) {  	case NB_EV_VALIDATE: +		bgp = nb_running_get_entry(args->dnode, NULL, false); + +		if (bgp->l3vni) { +			snprintf(args->errmsg, args->errmsg_len, +				 "Please unconfigure l3vni %u", bgp->l3vni); +			return NB_ERR_VALIDATION; +		} + +		/* Cannot delete default instance if vrf instances exist */ +		if (bgp->inst_type == BGP_INSTANCE_TYPE_DEFAULT) { +			struct listnode *node; +			struct bgp *tmp_bgp; + +			for (ALL_LIST_ELEMENTS_RO(bm->bgp, node, tmp_bgp)) { +				if (tmp_bgp->inst_type +				    == BGP_INSTANCE_TYPE_VRF) { +					snprintf( +						args->errmsg, args->errmsg_len, +						"Cannot delete default BGP instance. Dependent VRF instances exist\n"); +					return NB_ERR_VALIDATION; +				} +			} +		} + +		break;  	case NB_EV_PREPARE:  	case NB_EV_ABORT: +		return NB_OK;  	case NB_EV_APPLY: -		/* TODO: implement me. */ +		bgp = nb_running_unset_entry(args->dnode); + +		bgp_vpn_leak_unimport(bgp); +		bgp_delete(bgp); +  		break;  	} @@ -67,12 +175,38 @@ int routing_control_plane_protocols_control_plane_protocol_bgp_global_destroy(  int routing_control_plane_protocols_control_plane_protocol_bgp_global_local_as_modify(  	struct nb_cb_modify_args *args)  { +	struct bgp *bgp; +	as_t as; +  	switch (args->event) {  	case NB_EV_VALIDATE: +		as = yang_dnode_get_uint32(args->dnode, NULL); + +		bgp = nb_running_get_entry_non_rec(args->dnode, NULL, false); +		if (bgp && bgp->as != as) { +			snprintf(args->errmsg, args->errmsg_len, +				 "BGP instance is already running; AS is %u", +				 bgp->as); +			return NB_ERR_VALIDATION; +		} + +		break;  	case NB_EV_PREPARE:  	case NB_EV_ABORT: +		return NB_OK;  	case NB_EV_APPLY: -		/* TODO: implement me. */ +		/* NOTE: handled in bgp_global_create callback, the as change +		 * will be rejected in validate phase. +		 */ +		as = yang_dnode_get_uint32(args->dnode, NULL); +		bgp = nb_running_get_entry(args->dnode, NULL, true); +		if (bgp->as != as) { +			snprintf(args->errmsg, args->errmsg_len, +				 "BGP instance is already running; AS is %u", +				 bgp->as); +			return NB_ERR_INCONSISTENCY; +		} +  		break;  	} @@ -86,14 +220,15 @@ int routing_control_plane_protocols_control_plane_protocol_bgp_global_local_as_m  int routing_control_plane_protocols_control_plane_protocol_bgp_global_router_id_modify(  	struct nb_cb_modify_args *args)  { -	switch (args->event) { -	case NB_EV_VALIDATE: -	case NB_EV_PREPARE: -	case NB_EV_ABORT: -	case NB_EV_APPLY: -		/* TODO: implement me. */ -		break; -	} +	if (args->event != NB_EV_APPLY) +		return NB_OK; + +	struct bgp *bgp; +	struct in_addr router_id; + +	bgp = nb_running_get_entry(args->dnode, NULL, true); +	yang_dnode_get_ipv4(&router_id, args->dnode, NULL); +	bgp_router_id_static_set(bgp, router_id);  	return NB_OK;  } @@ -101,14 +236,16 @@ int routing_control_plane_protocols_control_plane_protocol_bgp_global_router_id_  int routing_control_plane_protocols_control_plane_protocol_bgp_global_router_id_destroy(  	struct nb_cb_destroy_args *args)  { -	switch (args->event) { -	case NB_EV_VALIDATE: -	case NB_EV_PREPARE: -	case NB_EV_ABORT: -	case NB_EV_APPLY: -		/* TODO: implement me. */ -		break; -	} +	if (args->event != NB_EV_APPLY) +		return NB_OK; + +	struct bgp *bgp; +	struct in_addr router_id; + +	bgp = nb_running_get_entry(args->dnode, NULL, true); + +	router_id.s_addr = 0; +	bgp_router_id_static_set(bgp, router_id);  	return NB_OK;  } @@ -120,29 +257,48 @@ int routing_control_plane_protocols_control_plane_protocol_bgp_global_router_id_  int routing_control_plane_protocols_control_plane_protocol_bgp_global_confederation_identifier_modify(  	struct nb_cb_modify_args *args)  { +	struct bgp *bgp; +	as_t as; +  	switch (args->event) {  	case NB_EV_VALIDATE: +		as = yang_dnode_get_uint32(args->dnode, NULL); +		if (!as) { +			snprintf(args->errmsg, args->errmsg_len, "Invalid AS."); +			return NB_ERR_VALIDATION; +		} + +		break;  	case NB_EV_PREPARE:  	case NB_EV_ABORT: +		return NB_OK;  	case NB_EV_APPLY: -		/* TODO: implement me. */ +		bgp = nb_running_get_entry(args->dnode, NULL, true); + +		as = yang_dnode_get_uint32(args->dnode, NULL); + +		bgp_confederation_id_set(bgp, as); +  		break;  	} +	as = yang_dnode_get_uint32(args->dnode, NULL); + +  	return NB_OK;  }  int routing_control_plane_protocols_control_plane_protocol_bgp_global_confederation_identifier_destroy(  	struct nb_cb_destroy_args *args)  { -	switch (args->event) { -	case NB_EV_VALIDATE: -	case NB_EV_PREPARE: -	case NB_EV_ABORT: -	case NB_EV_APPLY: -		/* TODO: implement me. */ -		break; -	} +	if (args->event != NB_EV_APPLY) +		return NB_OK; + +	struct bgp *bgp; + +	bgp = nb_running_get_entry(args->dnode, NULL, true); + +	bgp_confederation_id_unset(bgp);  	return NB_OK;  } @@ -154,12 +310,39 @@ int routing_control_plane_protocols_control_plane_protocol_bgp_global_confederat  int routing_control_plane_protocols_control_plane_protocol_bgp_global_confederation_member_as_create(  	struct nb_cb_create_args *args)  { +	as_t my_as, as; +	struct bgp *bgp; +	int ret; +  	switch (args->event) {  	case NB_EV_VALIDATE: +		my_as = yang_dnode_get_uint32(args->dnode, +					      "../../../global/local-as"); +		as = yang_dnode_get_uint32(args->dnode, NULL); +		if (my_as == as) { +			snprintf( +				args->errmsg, args->errmsg_len, +				"Local member-AS %u not allowed in confed peer list", +				my_as); +			return NB_ERR_VALIDATION; +		} + +		break;  	case NB_EV_PREPARE:  	case NB_EV_ABORT: +		return NB_OK;  	case NB_EV_APPLY: -		/* TODO: implement me. */ +		bgp = nb_running_get_entry(args->dnode, NULL, true); +		as = yang_dnode_get_uint32(args->dnode, NULL); + +		ret = bgp_confederation_peers_add(bgp, as); +		if (ret == BGP_ERR_INVALID_AS) { +			snprintf( +				args->errmsg, args->errmsg_len, +				"Local member-AS not alloed in confed peer list"); +			return NB_ERR_INCONSISTENCY; +		} +  		break;  	} @@ -169,33 +352,49 @@ int routing_control_plane_protocols_control_plane_protocol_bgp_global_confederat  int routing_control_plane_protocols_control_plane_protocol_bgp_global_confederation_member_as_destroy(  	struct nb_cb_destroy_args *args)  { -	switch (args->event) { -	case NB_EV_VALIDATE: -	case NB_EV_PREPARE: -	case NB_EV_ABORT: -	case NB_EV_APPLY: -		/* TODO: implement me. */ -		break; -	} +	if (args->event != NB_EV_APPLY) +		return NB_OK; + +	as_t as; +	struct bgp *bgp; + +	bgp = nb_running_get_entry(args->dnode, NULL, true); +	as = yang_dnode_get_uint32(args->dnode, NULL); + +	bgp_confederation_peers_remove(bgp, as);  	return NB_OK;  }  /*   * XPath: + * /frr-routing:routing/control-plane-protocols/control-plane-protocol/frr-bgp:bgp/global/med-config + */ +void routing_control_plane_protocols_control_plane_protocol_bgp_global_med_config_apply_finish( +	struct nb_cb_apply_finish_args *args) +{ +	struct bgp *bgp; + +	bgp = nb_running_get_entry(args->dnode, NULL, true); + +	bgp_maxmed_update(bgp); +} + +/* + * XPath:   * /frr-routing:routing/control-plane-protocols/control-plane-protocol/frr-bgp:bgp/global/med-config/enable-med-admin   */  int routing_control_plane_protocols_control_plane_protocol_bgp_global_med_config_enable_med_admin_modify(  	struct nb_cb_modify_args *args)  { -	switch (args->event) { -	case NB_EV_VALIDATE: -	case NB_EV_PREPARE: -	case NB_EV_ABORT: -	case NB_EV_APPLY: -		/* TODO: implement me. */ -		break; -	} +	if (args->event != NB_EV_APPLY) +		return NB_OK; + +	struct bgp *bgp; + +	bgp = nb_running_get_entry(args->dnode, NULL, true); + +	bgp->v_maxmed_admin = yang_dnode_get_bool(args->dnode, NULL);  	return NB_OK;  } @@ -207,12 +406,35 @@ int routing_control_plane_protocols_control_plane_protocol_bgp_global_med_config  int routing_control_plane_protocols_control_plane_protocol_bgp_global_med_config_max_med_admin_modify(  	struct nb_cb_modify_args *args)  { +	struct bgp *bgp; +	uint32_t med_admin_val; +  	switch (args->event) {  	case NB_EV_VALIDATE: +		med_admin_val = yang_dnode_get_uint32(args->dnode, NULL); + +		/* enable_med_admin is required to be enabled for max-med-admin +		 * non default value. +		 */ +		if (med_admin_val != BGP_MAXMED_VALUE_DEFAULT +		    && !yang_dnode_get_bool(args->dnode, +					    "../enable-med-admin")) { +			snprintf(args->errmsg, args->errmsg_len, +				 "enable med admin is not set"); +			return NB_ERR_VALIDATION; +		} + +		break;  	case NB_EV_PREPARE:  	case NB_EV_ABORT: +		return NB_OK;  	case NB_EV_APPLY: -		/* TODO: implement me. */ +		bgp = nb_running_get_entry(args->dnode, NULL, true); + +		med_admin_val = yang_dnode_get_uint32(args->dnode, NULL); + +		bgp->maxmed_admin_value = med_admin_val; +  		break;  	} @@ -226,12 +448,19 @@ int routing_control_plane_protocols_control_plane_protocol_bgp_global_med_config  int routing_control_plane_protocols_control_plane_protocol_bgp_global_med_config_max_med_onstart_up_time_modify(  	struct nb_cb_modify_args *args)  { +	struct bgp *bgp; +  	switch (args->event) {  	case NB_EV_VALIDATE:  	case NB_EV_PREPARE:  	case NB_EV_ABORT: +		return NB_OK;  	case NB_EV_APPLY: -		/* TODO: implement me. */ +		bgp = nb_running_get_entry(args->dnode, NULL, true); + +		bgp->v_maxmed_onstartup = +			yang_dnode_get_uint32(args->dnode, NULL); +  		break;  	} @@ -241,12 +470,28 @@ int routing_control_plane_protocols_control_plane_protocol_bgp_global_med_config  int routing_control_plane_protocols_control_plane_protocol_bgp_global_med_config_max_med_onstart_up_time_destroy(  	struct nb_cb_destroy_args *args)  { +	struct bgp *bgp; +  	switch (args->event) {  	case NB_EV_VALIDATE:  	case NB_EV_PREPARE:  	case NB_EV_ABORT: +		return NB_OK;  	case NB_EV_APPLY: -		/* TODO: implement me. */ +		bgp = nb_running_get_entry(args->dnode, NULL, true); + +		/* Cancel max-med onstartup if its on */ +		if (bgp->t_maxmed_onstartup) { +			THREAD_TIMER_OFF(bgp->t_maxmed_onstartup); +			bgp->maxmed_onstartup_over = 1; +		} + +		bgp->v_maxmed_onstartup = BGP_MAXMED_ONSTARTUP_UNCONFIGURED; +		/* Resetting onstartup value as part of dependent node is +		 * detroyed. +		 */ +		bgp->maxmed_onstartup_value = BGP_MAXMED_VALUE_DEFAULT; +  		break;  	} @@ -260,12 +505,31 @@ int routing_control_plane_protocols_control_plane_protocol_bgp_global_med_config  int routing_control_plane_protocols_control_plane_protocol_bgp_global_med_config_max_med_onstart_up_value_modify(  	struct nb_cb_modify_args *args)  { +	struct bgp *bgp; +	uint32_t onstartup_val; +  	switch (args->event) {  	case NB_EV_VALIDATE: +		onstartup_val = yang_dnode_get_uint32(args->dnode, NULL); + +		if (!yang_dnode_exists(args->dnode, +				       "../max-med-onstart-up-time") +		    && onstartup_val != BGP_MAXMED_VALUE_DEFAULT) { +			snprintf(args->errmsg, args->errmsg_len, +				 "max-med-onstart-up-time is not set."); +			return NB_ERR_VALIDATION; +		} + +		break;  	case NB_EV_PREPARE:  	case NB_EV_ABORT: +		return NB_OK;  	case NB_EV_APPLY: -		/* TODO: implement me. */ +		bgp = nb_running_get_entry(args->dnode, NULL, true); + +		bgp->maxmed_onstartup_value = +			yang_dnode_get_uint32(args->dnode, NULL); +  		break;  	} @@ -279,14 +543,25 @@ int routing_control_plane_protocols_control_plane_protocol_bgp_global_med_config  int routing_control_plane_protocols_control_plane_protocol_bgp_global_route_reflector_route_reflector_cluster_id_modify(  	struct nb_cb_modify_args *args)  { -	switch (args->event) { -	case NB_EV_VALIDATE: -	case NB_EV_PREPARE: -	case NB_EV_ABORT: -	case NB_EV_APPLY: -		/* TODO: implement me. */ -		break; -	} +	if (args->event != NB_EV_APPLY) +		return NB_OK; + +	struct bgp *bgp; +	struct in_addr cluster_id; +	const struct lyd_node_leaf_list *dleaf; + +	bgp = nb_running_get_entry(args->dnode, NULL, true); + +	dleaf = (const struct lyd_node_leaf_list *)args->dnode; +	if (dleaf->value_type == LY_TYPE_STRING) +		yang_dnode_get_ipv4(&cluster_id, args->dnode, NULL); +	else +		(void)inet_aton(dleaf->value_str, &cluster_id); + +	bgp_cluster_id_set(bgp, &cluster_id); + +	if (bgp_clear_star_soft_out(bgp->name, args->errmsg, args->errmsg_len)) +		return NB_ERR_INCONSISTENCY;  	return NB_OK;  } @@ -294,14 +569,17 @@ int routing_control_plane_protocols_control_plane_protocol_bgp_global_route_refl  int routing_control_plane_protocols_control_plane_protocol_bgp_global_route_reflector_route_reflector_cluster_id_destroy(  	struct nb_cb_destroy_args *args)  { -	switch (args->event) { -	case NB_EV_VALIDATE: -	case NB_EV_PREPARE: -	case NB_EV_ABORT: -	case NB_EV_APPLY: -		/* TODO: implement me. */ -		break; -	} +	if (args->event != NB_EV_APPLY) +		return NB_OK; + +	struct bgp *bgp; + +	bgp = nb_running_get_entry(args->dnode, NULL, true); + +	bgp_cluster_id_unset(bgp); + +	if (bgp_clear_star_soft_out(bgp->name, args->errmsg, args->errmsg_len)) +		return NB_ERR_INCONSISTENCY;  	return NB_OK;  } @@ -313,14 +591,20 @@ int routing_control_plane_protocols_control_plane_protocol_bgp_global_route_refl  int routing_control_plane_protocols_control_plane_protocol_bgp_global_route_reflector_no_client_reflect_modify(  	struct nb_cb_modify_args *args)  { -	switch (args->event) { -	case NB_EV_VALIDATE: -	case NB_EV_PREPARE: -	case NB_EV_ABORT: -	case NB_EV_APPLY: -		/* TODO: implement me. */ -		break; -	} +	if (args->event != NB_EV_APPLY) +		return NB_OK; + +	struct bgp *bgp; + +	bgp = nb_running_get_entry(args->dnode, NULL, true); + +	if (yang_dnode_get_bool(args->dnode, NULL)) +		SET_FLAG(bgp->flags, BGP_FLAG_NO_CLIENT_TO_CLIENT); +	else +		UNSET_FLAG(bgp->flags, BGP_FLAG_NO_CLIENT_TO_CLIENT); + +	if (bgp_clear_star_soft_out(bgp->name, args->errmsg, args->errmsg_len)) +		return NB_ERR_INCONSISTENCY;  	return NB_OK;  } @@ -332,33 +616,59 @@ int routing_control_plane_protocols_control_plane_protocol_bgp_global_route_refl  int routing_control_plane_protocols_control_plane_protocol_bgp_global_route_reflector_allow_outbound_policy_modify(  	struct nb_cb_modify_args *args)  { -	switch (args->event) { -	case NB_EV_VALIDATE: -	case NB_EV_PREPARE: -	case NB_EV_ABORT: -	case NB_EV_APPLY: -		/* TODO: implement me. */ -		break; -	} +	if (args->event != NB_EV_APPLY) +		return NB_OK; + +	struct bgp *bgp; + +	bgp = nb_running_get_entry(args->dnode, NULL, true); + +	if (yang_dnode_get_bool(args->dnode, NULL)) +		SET_FLAG(bgp->flags, BGP_FLAG_RR_ALLOW_OUTBOUND_POLICY); +	else +		UNSET_FLAG(bgp->flags, BGP_FLAG_RR_ALLOW_OUTBOUND_POLICY); + +	update_group_announce_rrclients(bgp); + +	if (bgp_clear_star_soft_out(bgp->name, args->errmsg, args->errmsg_len)) +		return NB_ERR_INCONSISTENCY;  	return NB_OK;  }  /*   * XPath: + * /frr-routing:routing/control-plane-protocols/control-plane-protocol/frr-bgp:bgp/global/route-selection-options + */ +void routing_control_plane_protocols_control_plane_protocol_bgp_global_route_selection_options_apply_finish( +	struct nb_cb_apply_finish_args *args) +{ +	struct bgp *bgp; + +	bgp = nb_running_get_entry(args->dnode, NULL, true); + +	bgp_recalculate_all_bestpaths(bgp); +} + +/* + * XPath:   * /frr-routing:routing/control-plane-protocols/control-plane-protocol/frr-bgp:bgp/global/route-selection-options/always-compare-med   */  int routing_control_plane_protocols_control_plane_protocol_bgp_global_route_selection_options_always_compare_med_modify(  	struct nb_cb_modify_args *args)  { -	switch (args->event) { -	case NB_EV_VALIDATE: -	case NB_EV_PREPARE: -	case NB_EV_ABORT: -	case NB_EV_APPLY: -		/* TODO: implement me. */ -		break; -	} +	if (args->event != NB_EV_APPLY) +		return NB_OK; + +	struct bgp *bgp; + +	bgp = nb_running_get_entry(args->dnode, NULL, true); + +	if (yang_dnode_get_bool(args->dnode, NULL)) +		SET_FLAG(bgp->flags, BGP_FLAG_ALWAYS_COMPARE_MED); +	else +		UNSET_FLAG(bgp->flags, BGP_FLAG_ALWAYS_COMPARE_MED); +  	return NB_OK;  } @@ -370,12 +680,58 @@ int routing_control_plane_protocols_control_plane_protocol_bgp_global_route_sele  int routing_control_plane_protocols_control_plane_protocol_bgp_global_route_selection_options_deterministic_med_modify(  	struct nb_cb_modify_args *args)  { +	struct bgp *bgp; +	int bestpath_per_as_used; +	afi_t afi; +	safi_t safi; +	struct peer *peer; +	struct listnode *node; +  	switch (args->event) {  	case NB_EV_VALIDATE: +		bgp = nb_running_get_entry(args->dnode, NULL, false); + +		if (!bgp) +			return NB_OK; + +		/* for deconfiguring deterministic-med case */ +		if (!yang_dnode_get_bool(args->dnode, NULL) +		    && CHECK_FLAG(bgp->flags, BGP_FLAG_DETERMINISTIC_MED)) { +			bestpath_per_as_used = 0; + +			for (ALL_LIST_ELEMENTS_RO(bgp->peer, node, peer)) { +				FOREACH_AFI_SAFI (afi, safi) +					if (bgp_addpath_dmed_required( +						    peer->addpath_type[afi] +								      [safi])) { +						bestpath_per_as_used = 1; +						break; +					} + +				if (bestpath_per_as_used) +					break; +			} + +			if (bestpath_per_as_used) { +				snprintf( +					args->errmsg, args->errmsg_len, +					"bgp deterministic-med cannot be disabled while addpath-tx-bestpath-per-AS is in use"); +				return NB_ERR_VALIDATION; +			} +		} + +		break;  	case NB_EV_PREPARE:  	case NB_EV_ABORT: +		return NB_OK;  	case NB_EV_APPLY: -		/* TODO: implement me. */ +		bgp = nb_running_get_entry(args->dnode, NULL, true); + +		if (yang_dnode_get_bool(args->dnode, NULL)) +			SET_FLAG(bgp->flags, BGP_FLAG_DETERMINISTIC_MED); +		else +			UNSET_FLAG(bgp->flags, BGP_FLAG_DETERMINISTIC_MED); +  		break;  	} @@ -389,14 +745,17 @@ int routing_control_plane_protocols_control_plane_protocol_bgp_global_route_sele  int routing_control_plane_protocols_control_plane_protocol_bgp_global_route_selection_options_confed_med_modify(  	struct nb_cb_modify_args *args)  { -	switch (args->event) { -	case NB_EV_VALIDATE: -	case NB_EV_PREPARE: -	case NB_EV_ABORT: -	case NB_EV_APPLY: -		/* TODO: implement me. */ -		break; -	} +	if (args->event != NB_EV_APPLY) +		return NB_OK; + +	struct bgp *bgp; + +	bgp = nb_running_get_entry(args->dnode, NULL, true); + +	if (yang_dnode_get_bool(args->dnode, NULL)) +		SET_FLAG(bgp->flags, BGP_FLAG_MED_CONFED); +	else +		UNSET_FLAG(bgp->flags, BGP_FLAG_MED_CONFED);  	return NB_OK;  } @@ -408,14 +767,17 @@ int routing_control_plane_protocols_control_plane_protocol_bgp_global_route_sele  int routing_control_plane_protocols_control_plane_protocol_bgp_global_route_selection_options_missing_as_worst_med_modify(  	struct nb_cb_modify_args *args)  { -	switch (args->event) { -	case NB_EV_VALIDATE: -	case NB_EV_PREPARE: -	case NB_EV_ABORT: -	case NB_EV_APPLY: -		/* TODO: implement me. */ -		break; -	} +	if (args->event != NB_EV_APPLY) +		return NB_OK; + +	struct bgp *bgp; + +	bgp = nb_running_get_entry(args->dnode, NULL, true); + +	if (yang_dnode_get_bool(args->dnode, NULL)) +		SET_FLAG(bgp->flags, BGP_FLAG_MED_MISSING_AS_WORST); +	else +		UNSET_FLAG(bgp->flags, BGP_FLAG_MED_MISSING_AS_WORST);  	return NB_OK;  } @@ -446,14 +808,17 @@ int routing_control_plane_protocols_control_plane_protocol_bgp_global_route_sele  int routing_control_plane_protocols_control_plane_protocol_bgp_global_route_selection_options_ignore_as_path_length_modify(  	struct nb_cb_modify_args *args)  { -	switch (args->event) { -	case NB_EV_VALIDATE: -	case NB_EV_PREPARE: -	case NB_EV_ABORT: -	case NB_EV_APPLY: -		/* TODO: implement me. */ -		break; -	} +	if (args->event != NB_EV_APPLY) +		return NB_OK; + +	struct bgp *bgp; + +	bgp = nb_running_get_entry(args->dnode, NULL, true); + +	if (yang_dnode_get_bool(args->dnode, NULL)) +		SET_FLAG(bgp->flags, BGP_FLAG_ASPATH_IGNORE); +	else +		UNSET_FLAG(bgp->flags, BGP_FLAG_ASPATH_IGNORE);  	return NB_OK;  } @@ -465,14 +830,17 @@ int routing_control_plane_protocols_control_plane_protocol_bgp_global_route_sele  int routing_control_plane_protocols_control_plane_protocol_bgp_global_route_selection_options_external_compare_router_id_modify(  	struct nb_cb_modify_args *args)  { -	switch (args->event) { -	case NB_EV_VALIDATE: -	case NB_EV_PREPARE: -	case NB_EV_ABORT: -	case NB_EV_APPLY: -		/* TODO: implement me. */ -		break; -	} +	if (args->event != NB_EV_APPLY) +		return NB_OK; + +	struct bgp *bgp; + +	bgp = nb_running_get_entry(args->dnode, NULL, true); + +	if (yang_dnode_get_bool(args->dnode, NULL)) +		SET_FLAG(bgp->flags, BGP_FLAG_COMPARE_ROUTER_ID); +	else +		UNSET_FLAG(bgp->flags, BGP_FLAG_COMPARE_ROUTER_ID);  	return NB_OK;  } @@ -484,12 +852,29 @@ int routing_control_plane_protocols_control_plane_protocol_bgp_global_route_sele  int routing_control_plane_protocols_control_plane_protocol_bgp_global_route_selection_options_allow_multiple_as_modify(  	struct nb_cb_modify_args *args)  { +	struct bgp *bgp; +  	switch (args->event) {  	case NB_EV_VALIDATE:  	case NB_EV_PREPARE:  	case NB_EV_ABORT: +		return NB_OK;  	case NB_EV_APPLY: -		/* TODO: implement me. */ +		bgp = nb_running_get_entry(args->dnode, NULL, true); + +		if (yang_dnode_get_bool(args->dnode, NULL)) { +			SET_FLAG(bgp->flags, BGP_FLAG_ASPATH_MULTIPATH_RELAX); +			if (yang_dnode_get_bool(args->dnode, +						"../multi-path-as-set")) { +				SET_FLAG(bgp->flags, +					 BGP_FLAG_MULTIPATH_RELAX_AS_SET); +			} +		} else { +			UNSET_FLAG(bgp->flags, BGP_FLAG_ASPATH_MULTIPATH_RELAX); +			/* unset as-set */ +			UNSET_FLAG(bgp->flags, BGP_FLAG_MULTIPATH_RELAX_AS_SET); +		} +  		break;  	} @@ -503,12 +888,24 @@ int routing_control_plane_protocols_control_plane_protocol_bgp_global_route_sele  int routing_control_plane_protocols_control_plane_protocol_bgp_global_route_selection_options_multi_path_as_set_modify(  	struct nb_cb_modify_args *args)  { +	struct bgp *bgp; +  	switch (args->event) {  	case NB_EV_VALIDATE:  	case NB_EV_PREPARE:  	case NB_EV_ABORT: +		return NB_OK;  	case NB_EV_APPLY: -		/* TODO: implement me. */ +		bgp = nb_running_get_entry(args->dnode, NULL, true); + +		if (!CHECK_FLAG(bgp->flags, BGP_FLAG_MULTIPATH_RELAX_AS_SET)) { +			SET_FLAG(bgp->flags, BGP_FLAG_MULTIPATH_RELAX_AS_SET); + +		} else +			zlog_debug( +				"%s multi-path-as-set as part of allow-multiple-as modify cb.", +				__func__); +  		break;  	} @@ -518,12 +915,24 @@ int routing_control_plane_protocols_control_plane_protocol_bgp_global_route_sele  int routing_control_plane_protocols_control_plane_protocol_bgp_global_route_selection_options_multi_path_as_set_destroy(  	struct nb_cb_destroy_args *args)  { +	struct bgp *bgp; +  	switch (args->event) {  	case NB_EV_VALIDATE:  	case NB_EV_PREPARE:  	case NB_EV_ABORT: +		return NB_OK;  	case NB_EV_APPLY: -		/* TODO: implement me. */ +		bgp = nb_running_get_entry(args->dnode, NULL, true); +		/* Only unset if it set, it is possible allow_multiple_as_modify +		 * unset this. +		 */ +		if (CHECK_FLAG(bgp->flags, BGP_FLAG_MULTIPATH_RELAX_AS_SET)) { +			UNSET_FLAG(bgp->flags, BGP_FLAG_MULTIPATH_RELAX_AS_SET); + +			bgp_recalculate_all_bestpaths(bgp); +		} +  		break;  	} @@ -537,14 +946,17 @@ int routing_control_plane_protocols_control_plane_protocol_bgp_global_route_sele  int routing_control_plane_protocols_control_plane_protocol_bgp_global_global_neighbor_config_dynamic_neighbors_limit_modify(  	struct nb_cb_modify_args *args)  { -	switch (args->event) { -	case NB_EV_VALIDATE: -	case NB_EV_PREPARE: -	case NB_EV_ABORT: -	case NB_EV_APPLY: -		/* TODO: implement me. */ -		break; -	} +	if (args->event != NB_EV_APPLY) +		return NB_OK; + +	struct bgp *bgp; +	uint32_t listen_limit; + +	bgp = nb_running_get_entry(args->dnode, NULL, true); + +	listen_limit = yang_dnode_get_uint32(args->dnode, NULL); + +	bgp_listen_limit_set(bgp, listen_limit);  	return NB_OK;  } @@ -552,14 +964,14 @@ int routing_control_plane_protocols_control_plane_protocol_bgp_global_global_nei  int routing_control_plane_protocols_control_plane_protocol_bgp_global_global_neighbor_config_dynamic_neighbors_limit_destroy(  	struct nb_cb_destroy_args *args)  { -	switch (args->event) { -	case NB_EV_VALIDATE: -	case NB_EV_PREPARE: -	case NB_EV_ABORT: -	case NB_EV_APPLY: -		/* TODO: implement me. */ -		break; -	} +	if (args->event != NB_EV_APPLY) +		return NB_OK; + +	struct bgp *bgp; + +	bgp = nb_running_get_entry(args->dnode, NULL, true); + +	bgp_listen_limit_unset(bgp);  	return NB_OK;  } @@ -571,14 +983,17 @@ int routing_control_plane_protocols_control_plane_protocol_bgp_global_global_nei  int routing_control_plane_protocols_control_plane_protocol_bgp_global_global_neighbor_config_log_neighbor_changes_modify(  	struct nb_cb_modify_args *args)  { -	switch (args->event) { -	case NB_EV_VALIDATE: -	case NB_EV_PREPARE: -	case NB_EV_ABORT: -	case NB_EV_APPLY: -		/* TODO: implement me. */ -		break; -	} +	if (args->event != NB_EV_APPLY) +		return NB_OK; + +	struct bgp *bgp; + +	bgp = nb_running_get_entry(args->dnode, NULL, true); + +	if (yang_dnode_get_bool(args->dnode, NULL)) +		SET_FLAG(bgp->flags, BGP_FLAG_LOG_NEIGHBOR_CHANGES); +	else +		UNSET_FLAG(bgp->flags, BGP_FLAG_LOG_NEIGHBOR_CHANGES);  	return NB_OK;  } @@ -590,14 +1005,21 @@ int routing_control_plane_protocols_control_plane_protocol_bgp_global_global_nei  int routing_control_plane_protocols_control_plane_protocol_bgp_global_global_neighbor_config_packet_quanta_config_wpkt_quanta_modify(  	struct nb_cb_modify_args *args)  { -	switch (args->event) { -	case NB_EV_VALIDATE: -	case NB_EV_PREPARE: -	case NB_EV_ABORT: -	case NB_EV_APPLY: -		/* TODO: implement me. */ -		break; -	} +	if (args->event != NB_EV_APPLY) +		return NB_OK; + +	struct bgp *bgp; +	uint32_t quanta; + +	bgp = nb_running_get_entry(args->dnode, NULL, true); + +	quanta = yang_dnode_get_uint32(args->dnode, NULL); + +	if (atomic_load_explicit(&bgp->wpkt_quanta, memory_order_relaxed) +	    == BGP_WRITE_PACKET_MAX) +		bgp_wpkt_quanta_config_vty(bgp, quanta, true); +	else +		bgp_wpkt_quanta_config_vty(bgp, quanta, false);  	return NB_OK;  } @@ -609,14 +1031,21 @@ int routing_control_plane_protocols_control_plane_protocol_bgp_global_global_nei  int routing_control_plane_protocols_control_plane_protocol_bgp_global_global_neighbor_config_packet_quanta_config_rpkt_quanta_modify(  	struct nb_cb_modify_args *args)  { -	switch (args->event) { -	case NB_EV_VALIDATE: -	case NB_EV_PREPARE: -	case NB_EV_ABORT: -	case NB_EV_APPLY: -		/* TODO: implement me. */ -		break; -	} +	if (args->event != NB_EV_APPLY) +		return NB_OK; + +	struct bgp *bgp; +	uint32_t quanta; + +	bgp = nb_running_get_entry(args->dnode, NULL, true); + +	quanta = yang_dnode_get_uint32(args->dnode, NULL); + +	if (atomic_load_explicit(&bgp->rpkt_quanta, memory_order_relaxed) +	    == BGP_READ_PACKET_MAX) +		bgp_rpkt_quanta_config_vty(bgp, quanta, true); +	else +		bgp_rpkt_quanta_config_vty(bgp, quanta, false);  	return NB_OK;  } @@ -791,14 +1220,17 @@ int routing_control_plane_protocols_control_plane_protocol_bgp_global_graceful_r  int routing_control_plane_protocols_control_plane_protocol_bgp_global_global_update_group_config_subgroup_pkt_queue_size_modify(  	struct nb_cb_modify_args *args)  { -	switch (args->event) { -	case NB_EV_VALIDATE: -	case NB_EV_PREPARE: -	case NB_EV_ABORT: -	case NB_EV_APPLY: -		/* TODO: implement me. */ -		break; -	} +	if (args->event != NB_EV_APPLY) +		return NB_OK; + +	struct bgp *bgp; +	uint32_t max_size; + +	bgp = nb_running_get_entry(args->dnode, NULL, true); + +	max_size = yang_dnode_get_uint32(args->dnode, NULL); + +	bgp_default_subgroup_pkt_queue_max_set(bgp, max_size);  	return NB_OK;  } @@ -810,13 +1242,22 @@ int routing_control_plane_protocols_control_plane_protocol_bgp_global_global_upd  int routing_control_plane_protocols_control_plane_protocol_bgp_global_global_update_group_config_coalesce_time_modify(  	struct nb_cb_modify_args *args)  { -	switch (args->event) { -	case NB_EV_VALIDATE: -	case NB_EV_PREPARE: -	case NB_EV_ABORT: -	case NB_EV_APPLY: -		/* TODO: implement me. */ -		break; +	if (args->event != NB_EV_APPLY) +		return NB_OK; + +	struct bgp *bgp; +	uint32_t coalesce_time; + +	bgp = nb_running_get_entry(args->dnode, NULL, true); + +	coalesce_time = yang_dnode_get_uint32(args->dnode, NULL); + +	if (coalesce_time != BGP_DEFAULT_SUBGROUP_COALESCE_TIME) { +		bgp->heuristic_coalesce = false; +		bgp->coalesce_time = coalesce_time; +	} else { +		bgp->heuristic_coalesce = true; +		bgp->coalesce_time = BGP_DEFAULT_SUBGROUP_COALESCE_TIME;  	}  	return NB_OK; @@ -935,12 +1376,35 @@ int routing_control_plane_protocols_control_plane_protocol_bgp_global_global_con  int routing_control_plane_protocols_control_plane_protocol_bgp_global_global_config_timers_hold_time_modify(  	struct nb_cb_modify_args *args)  { +	struct bgp *bgp; +	unsigned long keepalive = 0; +	unsigned long holdtime = 0; +  	switch (args->event) {  	case NB_EV_VALIDATE: +		keepalive = yang_dnode_get_uint16(args->dnode, "../keepalive"); +		holdtime = yang_dnode_get_uint16(args->dnode, NULL); +		/* Holdtime value check. */ +		if (holdtime < 3 && holdtime != 0) { +			snprintf( +				args->errmsg, args->errmsg_len, +				"hold time value must be either 0 or greater than 3"); +			return NB_ERR_VALIDATION; +		} + +		break;  	case NB_EV_PREPARE:  	case NB_EV_ABORT: +		return NB_OK;  	case NB_EV_APPLY: -		/* TODO: implement me. */ +		bgp = nb_running_get_entry(args->dnode, NULL, true); + +		keepalive = yang_dnode_get_uint16(args->dnode, "../keepalive"); +		holdtime = yang_dnode_get_uint16(args->dnode, NULL); + +		bgp_timers_set(bgp, keepalive, holdtime, +			       DFLT_BGP_CONNECT_RETRY); +  		break;  	} @@ -954,12 +1418,35 @@ int routing_control_plane_protocols_control_plane_protocol_bgp_global_global_con  int routing_control_plane_protocols_control_plane_protocol_bgp_global_global_config_timers_keepalive_modify(  	struct nb_cb_modify_args *args)  { +	struct bgp *bgp; +	unsigned long keepalive = 0; +	unsigned long holdtime = 0; +  	switch (args->event) {  	case NB_EV_VALIDATE: +		keepalive = yang_dnode_get_uint16(args->dnode, NULL); +		holdtime = yang_dnode_get_uint16(args->dnode, "../hold-time"); +		/* Holdtime value check. */ +		if (holdtime < 3 && holdtime != 0) { +			snprintf( +				args->errmsg, args->errmsg_len, +				"hold time value must be either 0 or greater than 3"); +			return NB_ERR_VALIDATION; +		} + +		break;  	case NB_EV_PREPARE:  	case NB_EV_ABORT: +		return NB_OK;  	case NB_EV_APPLY: -		/* TODO: implement me. */ +		bgp = nb_running_get_entry(args->dnode, NULL, true); + +		keepalive = yang_dnode_get_uint16(args->dnode, NULL); +		holdtime = yang_dnode_get_uint16(args->dnode, "../hold-time"); + +		bgp_timers_set(bgp, keepalive, holdtime, +			       DFLT_BGP_CONNECT_RETRY); +  		break;  	} @@ -992,14 +1479,20 @@ int routing_control_plane_protocols_control_plane_protocol_bgp_global_instance_t  int routing_control_plane_protocols_control_plane_protocol_bgp_global_ebgp_multihop_connected_route_check_modify(  	struct nb_cb_modify_args *args)  { -	switch (args->event) { -	case NB_EV_VALIDATE: -	case NB_EV_PREPARE: -	case NB_EV_ABORT: -	case NB_EV_APPLY: -		/* TODO: implement me. */ -		break; -	} +	if (args->event != NB_EV_APPLY) +		return NB_OK; + +	struct bgp *bgp; + +	bgp = nb_running_get_entry(args->dnode, NULL, true); + +	if (yang_dnode_get_bool(args->dnode, NULL)) +		SET_FLAG(bgp->flags, BGP_FLAG_DISABLE_NH_CONNECTED_CHK); +	else +		UNSET_FLAG(bgp->flags, BGP_FLAG_DISABLE_NH_CONNECTED_CHK); + +	if (bgp_clear_star_soft_in(bgp->name, args->errmsg, args->errmsg_len)) +		return NB_ERR_INCONSISTENCY;  	return NB_OK;  } @@ -1011,14 +1504,15 @@ int routing_control_plane_protocols_control_plane_protocol_bgp_global_ebgp_multi  int routing_control_plane_protocols_control_plane_protocol_bgp_global_fast_external_failover_modify(  	struct nb_cb_modify_args *args)  { -	switch (args->event) { -	case NB_EV_VALIDATE: -	case NB_EV_PREPARE: -	case NB_EV_ABORT: -	case NB_EV_APPLY: -		/* TODO: implement me. */ -		break; -	} +	if (args->event != NB_EV_APPLY) +		return NB_OK; +	struct bgp *bgp; + +	bgp = nb_running_get_entry(args->dnode, NULL, true); +	if (!yang_dnode_get_bool(args->dnode, NULL)) { +		SET_FLAG(bgp->flags, BGP_FLAG_NO_FAST_EXT_FAILOVER); +	} else +		UNSET_FLAG(bgp->flags, BGP_FLAG_NO_FAST_EXT_FAILOVER);  	return NB_OK;  } @@ -1030,14 +1524,18 @@ int routing_control_plane_protocols_control_plane_protocol_bgp_global_fast_exter  int routing_control_plane_protocols_control_plane_protocol_bgp_global_local_pref_modify(  	struct nb_cb_modify_args *args)  { -	switch (args->event) { -	case NB_EV_VALIDATE: -	case NB_EV_PREPARE: -	case NB_EV_ABORT: -	case NB_EV_APPLY: -		/* TODO: implement me. */ -		break; -	} +	if (args->event != NB_EV_APPLY) +		return NB_OK; +	struct bgp *bgp; +	uint32_t local_pref; + +	bgp = nb_running_get_entry(args->dnode, NULL, true); +	local_pref = yang_dnode_get_uint32(args->dnode, NULL); + +	bgp_default_local_preference_set(bgp, local_pref); + +	if (bgp_clear_star_soft_in(bgp->name, args->errmsg, args->errmsg_len)) +		return NB_ERR_INCONSISTENCY;  	return NB_OK;  } @@ -1049,14 +1547,13 @@ int routing_control_plane_protocols_control_plane_protocol_bgp_global_local_pref  int routing_control_plane_protocols_control_plane_protocol_bgp_global_default_shutdown_modify(  	struct nb_cb_modify_args *args)  { -	switch (args->event) { -	case NB_EV_VALIDATE: -	case NB_EV_PREPARE: -	case NB_EV_ABORT: -	case NB_EV_APPLY: -		/* TODO: implement me. */ -		break; -	} +	if (args->event != NB_EV_APPLY) +		return NB_OK; + +	struct bgp *bgp; + +	bgp = nb_running_get_entry(args->dnode, NULL, true); +	bgp->autoshutdown = yang_dnode_get_bool(args->dnode, NULL);  	return NB_OK;  } @@ -1068,14 +1565,17 @@ int routing_control_plane_protocols_control_plane_protocol_bgp_global_default_sh  int routing_control_plane_protocols_control_plane_protocol_bgp_global_ebgp_requires_policy_modify(  	struct nb_cb_modify_args *args)  { -	switch (args->event) { -	case NB_EV_VALIDATE: -	case NB_EV_PREPARE: -	case NB_EV_ABORT: -	case NB_EV_APPLY: -		/* TODO: implement me. */ -		break; -	} +	if (args->event != NB_EV_APPLY) +		return NB_OK; + +	struct bgp *bgp; + +	bgp = nb_running_get_entry(args->dnode, NULL, true); + +	if (yang_dnode_get_bool(args->dnode, NULL)) +		SET_FLAG(bgp->flags, BGP_FLAG_EBGP_REQUIRES_POLICY); +	else +		UNSET_FLAG(bgp->flags, BGP_FLAG_EBGP_REQUIRES_POLICY);  	return NB_OK;  } @@ -1087,14 +1587,17 @@ int routing_control_plane_protocols_control_plane_protocol_bgp_global_ebgp_requi  int routing_control_plane_protocols_control_plane_protocol_bgp_global_show_hostname_modify(  	struct nb_cb_modify_args *args)  { -	switch (args->event) { -	case NB_EV_VALIDATE: -	case NB_EV_PREPARE: -	case NB_EV_ABORT: -	case NB_EV_APPLY: -		/* TODO: implement me. */ -		break; -	} +	if (args->event != NB_EV_APPLY) +		return NB_OK; + +	struct bgp *bgp; + +	bgp = nb_running_get_entry(args->dnode, NULL, true); + +	if (yang_dnode_get_bool(args->dnode, NULL)) +		SET_FLAG(bgp->flags, BGP_FLAG_SHOW_HOSTNAME); +	else +		UNSET_FLAG(bgp->flags, BGP_FLAG_SHOW_HOSTNAME);  	return NB_OK;  } @@ -1106,14 +1609,17 @@ int routing_control_plane_protocols_control_plane_protocol_bgp_global_show_hostn  int routing_control_plane_protocols_control_plane_protocol_bgp_global_show_nexthop_hostname_modify(  	struct nb_cb_modify_args *args)  { -	switch (args->event) { -	case NB_EV_VALIDATE: -	case NB_EV_PREPARE: -	case NB_EV_ABORT: -	case NB_EV_APPLY: -		/* TODO: implement me. */ -		break; -	} +	if (args->event != NB_EV_APPLY) +		return NB_OK; + +	struct bgp *bgp; + +	bgp = nb_running_get_entry(args->dnode, NULL, true); + +	if (yang_dnode_get_bool(args->dnode, NULL)) +		SET_FLAG(bgp->flags, BGP_FLAG_SHOW_NEXTHOP_HOSTNAME); +	else +		UNSET_FLAG(bgp->flags, BGP_FLAG_SHOW_NEXTHOP_HOSTNAME);  	return NB_OK;  } @@ -1125,14 +1631,19 @@ int routing_control_plane_protocols_control_plane_protocol_bgp_global_show_nexth  int routing_control_plane_protocols_control_plane_protocol_bgp_global_import_check_modify(  	struct nb_cb_modify_args *args)  { -	switch (args->event) { -	case NB_EV_VALIDATE: -	case NB_EV_PREPARE: -	case NB_EV_ABORT: -	case NB_EV_APPLY: -		/* TODO: implement me. */ -		break; -	} +	if (args->event != NB_EV_APPLY) +		return NB_OK; + +	struct bgp *bgp; + +	bgp = nb_running_get_entry(args->dnode, NULL, true); + +	if (yang_dnode_get_bool(args->dnode, NULL)) +		SET_FLAG(bgp->flags, BGP_FLAG_IMPORT_CHECK); +	else +		UNSET_FLAG(bgp->flags, BGP_FLAG_IMPORT_CHECK); + +	bgp_static_redo_import_check(bgp);  	return NB_OK;  } @@ -1144,12 +1655,40 @@ int routing_control_plane_protocols_control_plane_protocol_bgp_global_import_che  int routing_control_plane_protocols_control_plane_protocol_bgp_global_graceful_shutdown_enable_modify(  	struct nb_cb_modify_args *args)  { +	struct bgp *bgp; +  	switch (args->event) {  	case NB_EV_VALIDATE: +		if (CHECK_FLAG(bm->flags, BM_FLAG_GRACEFUL_SHUTDOWN)) { +			snprintf( +				args->errmsg, args->errmsg_len, +				"%%Failed: per-vrf graceful-shutdown config not permitted with global graceful-shutdown"); +			return NB_ERR_VALIDATION; +		} + +		break;  	case NB_EV_PREPARE:  	case NB_EV_ABORT: +		return NB_OK;  	case NB_EV_APPLY: -		/* TODO: implement me. */ +		bgp = nb_running_get_entry(args->dnode, NULL, true); + +		if (yang_dnode_get_bool(args->dnode, NULL)) +			SET_FLAG(bgp->flags, BGP_FLAG_GRACEFUL_SHUTDOWN); +		else +			UNSET_FLAG(bgp->flags, BGP_FLAG_GRACEFUL_SHUTDOWN); + +		bgp_static_redo_import_check(bgp); +		bgp_redistribute_redo(bgp); + +		if (bgp_clear_star_soft_out(bgp->name, args->errmsg, +					    args->errmsg_len)) +			return NB_ERR_INCONSISTENCY; + +		if (bgp_clear_star_soft_in(bgp->name, args->errmsg, +					   args->errmsg_len)) +			return NB_ERR_INCONSISTENCY; +  		break;  	} diff --git a/bgpd/bgp_vty.c b/bgpd/bgp_vty.c index 795a4adfc7..8264519a8b 100644 --- a/bgpd/bgp_vty.c +++ b/bgpd/bgp_vty.c @@ -73,6 +73,11 @@  #include "bgpd/rfapi/bgp_rfapi_cfg.h"  #endif +#include "northbound.h" +#include "northbound_cli.h" +#include "bgpd/bgp_nb.h" + +  FRR_CFG_DEFAULT_BOOL(BGP_IMPORT_CHECK,  	{  		.val_bool = false, @@ -751,18 +756,19 @@ enum clear_sort {  	clear_as  }; -static void bgp_clear_vty_error(struct vty *vty, struct peer *peer, afi_t afi, -				safi_t safi, int error) +static void bgp_clear_vty_error(struct peer *peer, afi_t afi, safi_t safi, +				int error, char *errmsg, size_t errmsg_len)  {  	switch (error) {  	case BGP_ERR_AF_UNCONFIGURED: -		vty_out(vty, -			"%%BGP: Enable %s address family for the neighbor %s\n", -			get_afi_safi_str(afi, safi, false), peer->host); +		snprintf(errmsg, errmsg_len, +			 "%%BGP: Enable %s address family for the neighbor %s", +			 get_afi_safi_str(afi, safi, false), peer->host);  		break;  	case BGP_ERR_SOFT_RECONFIG_UNCONFIGURED: -		vty_out(vty, -			"%%BGP: Inbound soft reconfig for %s not possible as it\n      has neither refresh capability, nor inbound soft reconfig\n", +		snprintf( +			errmsg, errmsg_len, +			"%%BGP: Inbound soft reconfig for %s not possible as it\n      has neither refresh capability, nor inbound soft reconfig",  			peer->host);  		break;  	default: @@ -820,9 +826,9 @@ static int bgp_peer_clear(struct peer *peer, afi_t afi, safi_t safi,  }  /* `clear ip bgp' functions. */ -static int bgp_clear(struct vty *vty, struct bgp *bgp, afi_t afi, safi_t safi, +static int bgp_clear(struct bgp *bgp, afi_t afi, safi_t safi,  		     enum clear_sort sort, enum bgp_clear_type stype, -		     const char *arg) +		     const char *arg, char *errmsg, size_t errmsg_len)  {  	int ret = 0;  	bool found = false; @@ -848,7 +854,8 @@ static int bgp_clear(struct vty *vty, struct bgp *bgp, afi_t afi, safi_t safi,  							  stype);  			if (ret < 0) -				bgp_clear_vty_error(vty, peer, afi, safi, ret); +				bgp_clear_vty_error(peer, afi, safi, ret, +						    errmsg, errmsg_len);  		}  		if (gr_router_detected @@ -877,8 +884,9 @@ static int bgp_clear(struct vty *vty, struct bgp *bgp, afi_t afi, safi_t safi,  			if (!peer) {  				peer = peer_lookup_by_hostname(bgp, arg);  				if (!peer) { -					vty_out(vty, -						"Malformed address or name: %s\n", +					snprintf( +						errmsg, errmsg_len, +						"Malformed address or name: %s",  						arg);  					return CMD_WARNING;  				} @@ -886,9 +894,9 @@ static int bgp_clear(struct vty *vty, struct bgp *bgp, afi_t afi, safi_t safi,  		} else {  			peer = peer_lookup(bgp, &su);  			if (!peer) { -				vty_out(vty, -					"%%BGP: Unknown neighbor - \"%s\"\n", -					arg); +				snprintf(errmsg, errmsg_len, +					 "%%BGP: Unknown neighbor - \"%s\"", +					 arg);  				return CMD_WARNING;  			}  		} @@ -903,7 +911,8 @@ static int bgp_clear(struct vty *vty, struct bgp *bgp, afi_t afi, safi_t safi,  			ret = BGP_ERR_AF_UNCONFIGURED;  		if (ret < 0) -			bgp_clear_vty_error(vty, peer, afi, safi, ret); +			bgp_clear_vty_error(peer, afi, safi, ret, errmsg, +					    errmsg_len);  		return CMD_SUCCESS;  	} @@ -914,7 +923,8 @@ static int bgp_clear(struct vty *vty, struct bgp *bgp, afi_t afi, safi_t safi,  		group = peer_group_lookup(bgp, arg);  		if (!group) { -			vty_out(vty, "%%BGP: No such peer-group %s\n", arg); +			snprintf(errmsg, errmsg_len, +				 "%%BGP: No such peer-group %s", arg);  			return CMD_WARNING;  		} @@ -922,14 +932,16 @@ static int bgp_clear(struct vty *vty, struct bgp *bgp, afi_t afi, safi_t safi,  			ret = bgp_peer_clear(peer, afi, safi, &nnode, stype);  			if (ret < 0) -				bgp_clear_vty_error(vty, peer, afi, safi, ret); +				bgp_clear_vty_error(peer, afi, safi, ret, +						    errmsg, errmsg_len);  			else  				found = true;  		}  		if (!found) -			vty_out(vty, -				"%%BGP: No %s peer belonging to peer-group %s is configured\n", +			snprintf( +				errmsg, errmsg_len, +				"%%BGP: No %s peer belonging to peer-group %s is configured",  				get_afi_safi_str(afi, safi, false), arg);  		return CMD_SUCCESS; @@ -949,7 +961,8 @@ static int bgp_clear(struct vty *vty, struct bgp *bgp, afi_t afi, safi_t safi,  			ret = bgp_peer_clear(peer, afi, safi, &nnode, stype);  			if (ret < 0) -				bgp_clear_vty_error(vty, peer, afi, safi, ret); +				bgp_clear_vty_error(peer, afi, safi, ret, +						    errmsg, errmsg_len);  			else  				found = true;  		} @@ -963,9 +976,9 @@ static int bgp_clear(struct vty *vty, struct bgp *bgp, afi_t afi, safi_t safi,  		}  		if (!found) -			vty_out(vty, -				"%%BGP: No external %s peer is configured\n", -				get_afi_safi_str(afi, safi, false)); +			snprintf(errmsg, errmsg_len, +				 "%%BGP: No external %s peer is configured", +				 get_afi_safi_str(afi, safi, false));  		return CMD_SUCCESS;  	} @@ -986,7 +999,8 @@ static int bgp_clear(struct vty *vty, struct bgp *bgp, afi_t afi, safi_t safi,  			ret = bgp_peer_clear(peer, afi, safi, &nnode, stype);  			if (ret < 0) -				bgp_clear_vty_error(vty, peer, afi, safi, ret); +				bgp_clear_vty_error(peer, afi, safi, ret, +						    errmsg, errmsg_len);  			else  				found = true;  		} @@ -1000,9 +1014,9 @@ static int bgp_clear(struct vty *vty, struct bgp *bgp, afi_t afi, safi_t safi,  		}  		if (!found) -			vty_out(vty, -				"%%BGP: No %s peer is configured with AS %s\n", -				get_afi_safi_str(afi, safi, false), arg); +			snprintf(errmsg, errmsg_len, +				 "%%BGP: No %s peer is configured with AS %s", +				 get_afi_safi_str(afi, safi, false), arg);  		return CMD_SUCCESS;  	} @@ -1010,9 +1024,9 @@ static int bgp_clear(struct vty *vty, struct bgp *bgp, afi_t afi, safi_t safi,  	return CMD_SUCCESS;  } -static int bgp_clear_vty(struct vty *vty, const char *name, afi_t afi, -			 safi_t safi, enum clear_sort sort, -			 enum bgp_clear_type stype, const char *arg) +static int bgp_clear_vty(const char *name, afi_t afi, safi_t safi, +			 enum clear_sort sort, enum bgp_clear_type stype, +			 const char *arg, char *errmsg, size_t errmsg_len)  {  	struct bgp *bgp; @@ -1020,40 +1034,56 @@ static int bgp_clear_vty(struct vty *vty, const char *name, afi_t afi,  	if (name) {  		bgp = bgp_lookup_by_name(name);  		if (bgp == NULL) { -			vty_out(vty, "Can't find BGP instance %s\n", name); +			snprintf(errmsg, errmsg_len, +				 "Can't find BGP instance %s", name);  			return CMD_WARNING;  		}  	} else {  		bgp = bgp_get_default();  		if (bgp == NULL) { -			vty_out(vty, "No BGP process is configured\n"); +			snprintf(errmsg, errmsg_len, +				 "No BGP process is configured");  			return CMD_WARNING;  		}  	} -	return bgp_clear(vty, bgp, afi, safi, sort, stype, arg); +	return bgp_clear(bgp, afi, safi, sort, stype, arg, errmsg, errmsg_len);  }  /* clear soft inbound */ -static void bgp_clear_star_soft_in(struct vty *vty, const char *name) +int bgp_clear_star_soft_in(const char *name, char *errmsg, size_t errmsg_len)  {  	afi_t afi;  	safi_t safi; +	int ret; -	FOREACH_AFI_SAFI (afi, safi) -		bgp_clear_vty(vty, name, afi, safi, clear_all, -			      BGP_CLEAR_SOFT_IN, NULL); +	FOREACH_AFI_SAFI (afi, safi) { +		ret = bgp_clear_vty(name, afi, safi, clear_all, +				    BGP_CLEAR_SOFT_IN, NULL, errmsg, +				    errmsg_len); +		if (ret != CMD_SUCCESS) +			return -1; +	} + +	return 0;  }  /* clear soft outbound */ -static void bgp_clear_star_soft_out(struct vty *vty, const char *name) +int bgp_clear_star_soft_out(const char *name, char *errmsg, size_t errmsg_len)  {  	afi_t afi;  	safi_t safi; +	int ret; -	FOREACH_AFI_SAFI (afi, safi) -		bgp_clear_vty(vty, name, afi, safi, clear_all, -			      BGP_CLEAR_SOFT_OUT, NULL); +	FOREACH_AFI_SAFI (afi, safi) { +		ret = bgp_clear_vty(name, afi, safi, clear_all, +				    BGP_CLEAR_SOFT_OUT, NULL, errmsg, +				    errmsg_len); +		if (ret != CMD_SUCCESS) +			return -1; +	} + +	return 0;  } @@ -1162,23 +1192,21 @@ DEFUN (no_auto_summary,  }  /* "router bgp" commands. */ -DEFUN_NOSH (router_bgp, -       router_bgp_cmd, -       "router bgp [(1-4294967295)$instasn [<view|vrf> VIEWVRFNAME]]", -       ROUTER_STR -       BGP_STR -       AS_STR -       BGP_INSTANCE_HELP_STR) +DEFUN_YANG_NOSH(router_bgp, +		router_bgp_cmd, +		"router bgp [(1-4294967295)$instasn [<view|vrf> VIEWVRFNAME]]", +		ROUTER_STR BGP_STR AS_STR BGP_INSTANCE_HELP_STR)  {  	int idx_asn = 2;  	int idx_view_vrf = 3;  	int idx_vrf = 4; -	int is_new_bgp = 0; -	int ret; +	int ret = CMD_SUCCESS;  	as_t as;  	struct bgp *bgp;  	const char *name = NULL; +	char as_str[12] = {'\0'};  	enum bgp_instance_type inst_type; +	char base_xpath[XPATH_MAXLEN];  	// "router bgp" without an ASN  	if (argc == 2) { @@ -1194,12 +1222,38 @@ DEFUN_NOSH (router_bgp,  			vty_out(vty, "%% Please specify ASN and VRF\n");  			return CMD_WARNING_CONFIG_FAILED;  		} +		/* unset the auto created flag as the user config is now present +		 */ +		UNSET_FLAG(bgp->vrf_flags, BGP_VRF_AUTO); + +		snprintf(base_xpath, sizeof(base_xpath), FRR_BGP_GLOBAL_XPATH, +			 "frr-bgp:bgp", "bgp", name ? name : VRF_DEFAULT_NAME); + +		nb_cli_enqueue_change(vty, ".", NB_OP_CREATE, NULL); +		snprintf(as_str, 12, "%d", bgp->as); +		nb_cli_enqueue_change(vty, "./local-as", NB_OP_MODIFY, as_str); +		if (bgp->inst_type == BGP_INSTANCE_TYPE_VIEW) { +			nb_cli_enqueue_change(vty, "./instance-type-view", +					      NB_OP_MODIFY, "true"); +		} + +		ret = nb_cli_apply_changes(vty, base_xpath); +		if (ret == CMD_SUCCESS) { +			VTY_PUSH_XPATH(BGP_NODE, base_xpath); + +			/* +			 * For backward compatibility with old commands we still +			 * need to use the qobj infrastructure. +			 */ +			VTY_PUSH_CONTEXT(BGP_NODE, bgp); +		} +		return ret;  	}  	// "router bgp X"  	else { -		as = strtoul(argv[idx_asn]->arg, NULL, 10); +		as = strtoul(argv[idx_asn]->arg, NULL, 10);  		inst_type = BGP_INSTANCE_TYPE_DEFAULT;  		if (argc > 3) {  			name = argv[idx_vrf]->arg; @@ -1209,63 +1263,51 @@ DEFUN_NOSH (router_bgp,  					name = NULL;  				else  					inst_type = BGP_INSTANCE_TYPE_VRF; -			} else if (!strcmp(argv[idx_view_vrf]->text, "view")) +			} else if (!strcmp(argv[idx_view_vrf]->text, "view")) {  				inst_type = BGP_INSTANCE_TYPE_VIEW; +			}  		} - -		if (inst_type == BGP_INSTANCE_TYPE_DEFAULT) -			is_new_bgp = (bgp_lookup(as, name) == NULL); - -		ret = bgp_get_vty(&bgp, &as, name, inst_type); -		switch (ret) { -		case BGP_ERR_AS_MISMATCH: -			vty_out(vty, "BGP is already running; AS is %u\n", as); -			return CMD_WARNING_CONFIG_FAILED; -		case BGP_ERR_INSTANCE_MISMATCH: -			vty_out(vty, -				"BGP instance name and AS number mismatch\n"); -			vty_out(vty, -				"BGP instance is already running; AS is %u\n", -				as); -			return CMD_WARNING_CONFIG_FAILED; +		snprintf(base_xpath, sizeof(base_xpath), FRR_BGP_GLOBAL_XPATH, +			 "frr-bgp:bgp", "bgp", name ? name : VRF_DEFAULT_NAME); + +		nb_cli_enqueue_change(vty, ".", NB_OP_CREATE, NULL); +		nb_cli_enqueue_change(vty, "./local-as", NB_OP_MODIFY, +				      argv[idx_asn]->arg); +		if (inst_type == BGP_INSTANCE_TYPE_VIEW) { +			nb_cli_enqueue_change(vty, "./instance-type-view", +					      NB_OP_MODIFY, "true");  		} -		/* -		 * If we just instantiated the default instance, complete -		 * any pending VRF-VPN leaking that was configured via -		 * earlier "router bgp X vrf FOO" blocks. -		 */ -		if (is_new_bgp && inst_type == BGP_INSTANCE_TYPE_DEFAULT) -			vpn_leak_postchange_all(); +		nb_cli_pending_commit_check(vty); +		ret = nb_cli_apply_changes(vty, base_xpath); +		if (ret == CMD_SUCCESS) { +			VTY_PUSH_XPATH(BGP_NODE, base_xpath); -		if (inst_type == BGP_INSTANCE_TYPE_VRF) -			bgp_vpn_leak_export(bgp); -		/* Pending: handle when user tries to change a view to vrf n vv. -		 */ +			/* +			 * For backward compatibility with old commands we still +			 * need to use the qobj infrastructure. +			 */ +			bgp = bgp_lookup(as, name); +			if (bgp) +				VTY_PUSH_CONTEXT(BGP_NODE, bgp); +		}  	} -	/* unset the auto created flag as the user config is now present */ -	UNSET_FLAG(bgp->vrf_flags, BGP_VRF_AUTO); -	VTY_PUSH_CONTEXT(BGP_NODE, bgp); - -	return CMD_SUCCESS; +	return ret;  }  /* "no router bgp" commands. */ -DEFUN (no_router_bgp, -       no_router_bgp_cmd, -       "no router bgp [(1-4294967295)$instasn [<view|vrf> VIEWVRFNAME]]", -       NO_STR -       ROUTER_STR -       BGP_STR -       AS_STR -       BGP_INSTANCE_HELP_STR) +DEFUN_YANG(no_router_bgp, +	   no_router_bgp_cmd, +	   "no router bgp [(1-4294967295)$instasn [<view|vrf> VIEWVRFNAME]]", +	   NO_STR ROUTER_STR BGP_STR AS_STR BGP_INSTANCE_HELP_STR)  {  	int idx_asn = 3;  	int idx_vrf = 5; -	as_t as; +	as_t as = 0;  	struct bgp *bgp;  	const char *name = NULL; +	char base_xpath[XPATH_MAXLEN];  	// "no router bgp" without an ASN  	if (argc == 3) { @@ -1321,94 +1363,93 @@ DEFUN (no_router_bgp,  			}  		}  	} +	snprintf(base_xpath, sizeof(base_xpath), FRR_BGP_GLOBAL_XPATH, +		 "frr-bgp:bgp", "bgp", +		 bgp->name ? bgp->name : VRF_DEFAULT_NAME); -	if (bgp_vpn_leak_unimport(bgp, vty)) -		return CMD_WARNING_CONFIG_FAILED; - -	bgp_delete(bgp); +	nb_cli_enqueue_change(vty, ".", NB_OP_DESTROY, NULL); -	return CMD_SUCCESS; +	return nb_cli_apply_changes(vty, base_xpath);  } +void cli_show_router_bgp(struct vty *vty, struct lyd_node *dnode, +			 bool show_defaults) +{ +	const struct lyd_node *vrf_dnode; +	const char *vrf_name; +	as_t as; -/* BGP router-id.  */ +	vrf_dnode = yang_dnode_get_parent(dnode, "control-plane-protocol"); +	vrf_name = yang_dnode_get_string(vrf_dnode, "./vrf"); +	as = yang_dnode_get_uint32(dnode, "./local-as"); -DEFPY (bgp_router_id, -       bgp_router_id_cmd, -       "bgp router-id A.B.C.D", -       BGP_STR -       "Override configured router identifier\n" -       "Manually configured router identifier\n") -{ -	VTY_DECLVAR_CONTEXT(bgp, bgp); -	bgp_router_id_static_set(bgp, router_id); -	return CMD_SUCCESS; +	vty_out(vty, "!\n"); +	vty_out(vty, "router bgp %u", as); +	if (!strmatch(vrf_name, VRF_DEFAULT_NAME)) +		vty_out(vty, " vrf %s", vrf_name); +	vty_out(vty, "\n");  } -DEFPY (no_bgp_router_id, -       no_bgp_router_id_cmd, -       "no bgp router-id [A.B.C.D]", -       NO_STR -       BGP_STR -       "Override configured router identifier\n" -       "Manually configured router identifier\n") +/* BGP router-id.  */ + +DEFPY_YANG(bgp_router_id, bgp_router_id_cmd, "bgp router-id A.B.C.D", +	   BGP_STR +	   "Override configured router identifier\n" +	   "Manually configured router identifier\n")  { -	VTY_DECLVAR_CONTEXT(bgp, bgp); +	nb_cli_enqueue_change(vty, "./router-id", NB_OP_MODIFY, router_id_str); -	if (router_id_str) { -		if (!IPV4_ADDR_SAME(&bgp->router_id_static, &router_id)) { -			vty_out(vty, "%% BGP router-id doesn't match\n"); -			return CMD_WARNING_CONFIG_FAILED; -		} -	} +	return nb_cli_apply_changes(vty, NULL); +} -	router_id.s_addr = 0; -	bgp_router_id_static_set(bgp, router_id); +DEFPY_YANG(no_bgp_router_id, no_bgp_router_id_cmd, "no bgp router-id [A.B.C.D]", +	   NO_STR BGP_STR +	   "Override configured router identifier\n" +	   "Manually configured router identifier\n") +{ +	nb_cli_enqueue_change(vty, "./router-id", NB_OP_DESTROY, +			      router_id_str ? router_id_str : NULL); -	return CMD_SUCCESS; +	return nb_cli_apply_changes(vty, NULL);  } +void cli_show_router_bgp_router_id(struct vty *vty, struct lyd_node *dnode, +				   bool show_defaults) +{ +	vty_out(vty, " bgp router-id %s\n", yang_dnode_get_string(dnode, NULL)); +}  /* BGP Cluster ID.  */ -DEFUN (bgp_cluster_id, -       bgp_cluster_id_cmd, -       "bgp cluster-id <A.B.C.D|(1-4294967295)>", -       BGP_STR -       "Configure Route-Reflector Cluster-id\n" -       "Route-Reflector Cluster-id in IP address format\n" -       "Route-Reflector Cluster-id as 32 bit quantity\n") +DEFUN_YANG(bgp_cluster_id, +	   bgp_cluster_id_cmd, +	   "bgp cluster-id <A.B.C.D|(1-4294967295)>", +	   BGP_STR +	   "Configure Route-Reflector Cluster-id\n" +	   "Route-Reflector Cluster-id in IP address format\n" +	   "Route-Reflector Cluster-id as 32 bit quantity\n")  { -	VTY_DECLVAR_CONTEXT(bgp, bgp);  	int idx_ipv4 = 2; -	int ret; -	struct in_addr cluster; -	ret = inet_aton(argv[idx_ipv4]->arg, &cluster); -	if (!ret) { -		vty_out(vty, "%% Malformed bgp cluster identifier\n"); -		return CMD_WARNING_CONFIG_FAILED; -	} +	nb_cli_enqueue_change(vty, +			      "./route-reflector/route-reflector-cluster-id", +			      NB_OP_MODIFY, argv[idx_ipv4]->arg); -	bgp_cluster_id_set(bgp, &cluster); -	bgp_clear_star_soft_out(vty, bgp->name); - -	return CMD_SUCCESS; +	return nb_cli_apply_changes(vty, NULL);  } -DEFUN (no_bgp_cluster_id, -       no_bgp_cluster_id_cmd, -       "no bgp cluster-id [<A.B.C.D|(1-4294967295)>]", -       NO_STR -       BGP_STR -       "Configure Route-Reflector Cluster-id\n" -       "Route-Reflector Cluster-id in IP address format\n" -       "Route-Reflector Cluster-id as 32 bit quantity\n") +DEFUN_YANG(no_bgp_cluster_id, +	   no_bgp_cluster_id_cmd, +	   "no bgp cluster-id [<A.B.C.D|(1-4294967295)>]", +	   NO_STR BGP_STR +	   "Configure Route-Reflector Cluster-id\n" +	   "Route-Reflector Cluster-id in IP address format\n" +	   "Route-Reflector Cluster-id as 32 bit quantity\n")  { -	VTY_DECLVAR_CONTEXT(bgp, bgp); -	bgp_cluster_id_unset(bgp); -	bgp_clear_star_soft_out(vty, bgp->name); +	nb_cli_enqueue_change(vty, +			      "./route-reflector/route-reflector-cluster-id", +			      NB_OP_DESTROY, NULL); -	return CMD_SUCCESS; +	return nb_cli_apply_changes(vty, NULL);  }  DEFPY (bgp_norib, @@ -1446,87 +1487,86 @@ DEFPY (no_bgp_norib,  	return CMD_SUCCESS;  } -DEFUN (bgp_confederation_identifier, -       bgp_confederation_identifier_cmd, -       "bgp confederation identifier (1-4294967295)", -       "BGP specific commands\n" -       "AS confederation parameters\n" -       "AS number\n" -       "Set routing domain confederation AS\n") +DEFUN_YANG(bgp_confederation_identifier, +	   bgp_confederation_identifier_cmd, +	   "bgp confederation identifier (1-4294967295)", +	   "BGP specific commands\n" +	   "AS confederation parameters\n" +	   "AS number\n" +	   "Set routing domain confederation AS\n")  { -	VTY_DECLVAR_CONTEXT(bgp, bgp);  	int idx_number = 3; -	as_t as; - -	as = strtoul(argv[idx_number]->arg, NULL, 10); -	bgp_confederation_id_set(bgp, as); +	nb_cli_enqueue_change(vty, "./confederation/identifier", NB_OP_MODIFY, +			      argv[idx_number]->arg); -	return CMD_SUCCESS; +	return nb_cli_apply_changes(vty, NULL);  } -DEFUN (no_bgp_confederation_identifier, -       no_bgp_confederation_identifier_cmd, -       "no bgp confederation identifier [(1-4294967295)]", -       NO_STR -       "BGP specific commands\n" -       "AS confederation parameters\n" -       "AS number\n" -       "Set routing domain confederation AS\n") +DEFUN_YANG(no_bgp_confederation_identifier, +	   no_bgp_confederation_identifier_cmd, +	   "no bgp confederation identifier [(1-4294967295)]", +	   NO_STR +	   "BGP specific commands\n" +	   "AS confederation parameters\n" +	   "AS number\n" +	   "Set routing domain confederation AS\n")  { -	VTY_DECLVAR_CONTEXT(bgp, bgp); -	bgp_confederation_id_unset(bgp); +	nb_cli_enqueue_change(vty, "./confederation/identifier", NB_OP_DESTROY, +			      NULL); -	return CMD_SUCCESS; +	return nb_cli_apply_changes(vty, NULL);  } -DEFUN (bgp_confederation_peers, -       bgp_confederation_peers_cmd, -       "bgp confederation peers (1-4294967295)...", -       "BGP specific commands\n" -       "AS confederation parameters\n" -       "Peer ASs in BGP confederation\n" -       AS_STR) +void cli_show_router_bgp_confederation_identifier(struct vty *vty, +						  struct lyd_node *dnode, +						  bool show_defaults) +{ +	vty_out(vty, " bgp confederation identifier %u\n", +		yang_dnode_get_uint32(dnode, NULL)); +} + +DEFUN_YANG(bgp_confederation_peers, +	   bgp_confederation_peers_cmd, +	   "bgp confederation peers (1-4294967295)...", +	   "BGP specific commands\n" +	   "AS confederation parameters\n" +	   "Peer ASs in BGP confederation\n" AS_STR)  { -	VTY_DECLVAR_CONTEXT(bgp, bgp);  	int idx_asn = 3; -	as_t as;  	int i; -	for (i = idx_asn; i < argc; i++) { -		as = strtoul(argv[i]->arg, NULL, 10); - -		if (bgp->as == as) { -			vty_out(vty, -				"%% Local member-AS not allowed in confed peer list\n"); -			continue; -		} +	for (i = idx_asn; i < argc; i++) +		nb_cli_enqueue_change(vty, "./confederation/member-as", +				      NB_OP_CREATE, argv[i]->arg); -		bgp_confederation_peers_add(bgp, as); -	} -	return CMD_SUCCESS; +	return nb_cli_apply_changes(vty, NULL);  } -DEFUN (no_bgp_confederation_peers, -       no_bgp_confederation_peers_cmd, -       "no bgp confederation peers (1-4294967295)...", -       NO_STR -       "BGP specific commands\n" -       "AS confederation parameters\n" -       "Peer ASs in BGP confederation\n" -       AS_STR) +DEFUN_YANG(no_bgp_confederation_peers, +	   no_bgp_confederation_peers_cmd, +	   "no bgp confederation peers (1-4294967295)...", +	   NO_STR +	   "BGP specific commands\n" +	   "AS confederation parameters\n" +	   "Peer ASs in BGP confederation\n" AS_STR)  { -	VTY_DECLVAR_CONTEXT(bgp, bgp);  	int idx_asn = 4; -	as_t as;  	int i; -	for (i = idx_asn; i < argc; i++) { -		as = strtoul(argv[i]->arg, NULL, 10); +	for (i = idx_asn; i < argc; i++) +		nb_cli_enqueue_change(vty, "./confederation/member-as", +				      NB_OP_DESTROY, argv[i]->arg); -		bgp_confederation_peers_remove(bgp, as); -	} -	return CMD_SUCCESS; +	return nb_cli_apply_changes(vty, NULL); +} + +void cli_show_router_bgp_confederation_member_as(struct vty *vty, +						 struct lyd_node *dnode, +						 bool show_defaults) +{ +	vty_out(vty, " bgp confederation peers %u \n", +		yang_dnode_get_uint32(dnode, NULL));  }  /** @@ -1574,107 +1614,127 @@ static int bgp_maxpaths_config_vty(struct vty *vty, int peer_type,  	return CMD_SUCCESS;  } -DEFUN (bgp_maxmed_admin, -       bgp_maxmed_admin_cmd, -       "bgp max-med administrative ", -       BGP_STR -       "Advertise routes with max-med\n" -       "Administratively applied, for an indefinite period\n") +void cli_show_router_bgp_med_config(struct vty *vty, struct lyd_node *dnode, +				    bool show_defaults)  { -	VTY_DECLVAR_CONTEXT(bgp, bgp); +	if (yang_dnode_get_bool(dnode, "./enable-med-admin")) { +		uint32_t med_admin_val; -	bgp->v_maxmed_admin = 1; -	bgp->maxmed_admin_value = BGP_MAXMED_VALUE_DEFAULT; +		vty_out(vty, " bgp max-med administrative"); +		if ((med_admin_val = +			     yang_dnode_get_uint32(dnode, "./max-med-admin")) +		    != BGP_MAXMED_VALUE_DEFAULT) +			vty_out(vty, " %u", med_admin_val); +		vty_out(vty, "\n"); +	} -	bgp_maxmed_update(bgp); +	if (yang_dnode_exists(dnode, "./max-med-onstart-up-time")) { +		uint32_t onstartup_val; -	return CMD_SUCCESS; +		vty_out(vty, " bgp max-med on-startup %u", +			yang_dnode_get_uint32(dnode, +					      "./max-med-onstart-up-time")); +		onstartup_val = yang_dnode_get_uint32( +			dnode, "./max-med-onstart-up-value"); +		if (onstartup_val != BGP_MAXMED_VALUE_DEFAULT) +			vty_out(vty, " %u", onstartup_val); + +		vty_out(vty, "\n"); +	}  } -DEFUN (bgp_maxmed_admin_medv, -       bgp_maxmed_admin_medv_cmd, -       "bgp max-med administrative (0-4294967295)", -       BGP_STR -       "Advertise routes with max-med\n" -       "Administratively applied, for an indefinite period\n" -       "Max MED value to be used\n") +DEFUN_YANG(bgp_maxmed_admin, +	   bgp_maxmed_admin_cmd, +	   "bgp max-med administrative ", +	   BGP_STR +	   "Advertise routes with max-med\n" +	   "Administratively applied, for an indefinite period\n") +{ +	nb_cli_enqueue_change(vty, "./med-config/enable-med-admin", +			      NB_OP_MODIFY, "true"); + +	return nb_cli_apply_changes(vty, NULL); +} + +DEFUN_YANG(bgp_maxmed_admin_medv, +	   bgp_maxmed_admin_medv_cmd, +	   "bgp max-med administrative (0-4294967295)", +	   BGP_STR +	   "Advertise routes with max-med\n" +	   "Administratively applied, for an indefinite period\n" +	   "Max MED value to be used\n")  { -	VTY_DECLVAR_CONTEXT(bgp, bgp);  	int idx_number = 3; -	bgp->v_maxmed_admin = 1; -	bgp->maxmed_admin_value = strtoul(argv[idx_number]->arg, NULL, 10); +	nb_cli_enqueue_change(vty, "./med-config/enable-med-admin", +			      NB_OP_MODIFY, "true"); -	bgp_maxmed_update(bgp); +	nb_cli_enqueue_change(vty, "./med-config/max-med-admin", NB_OP_MODIFY, +			      argv[idx_number]->arg); -	return CMD_SUCCESS; +	return nb_cli_apply_changes(vty, NULL);  } -DEFUN (no_bgp_maxmed_admin, -       no_bgp_maxmed_admin_cmd, -       "no bgp max-med administrative [(0-4294967295)]", -       NO_STR -       BGP_STR -       "Advertise routes with max-med\n" -       "Administratively applied, for an indefinite period\n" -       "Max MED value to be used\n") +DEFUN_YANG(no_bgp_maxmed_admin, +	   no_bgp_maxmed_admin_cmd, +	   "no bgp max-med administrative [(0-4294967295)]", +	   NO_STR BGP_STR +	   "Advertise routes with max-med\n" +	   "Administratively applied, for an indefinite period\n" +	   "Max MED value to be used\n")  { -	VTY_DECLVAR_CONTEXT(bgp, bgp); -	bgp->v_maxmed_admin = BGP_MAXMED_ADMIN_UNCONFIGURED; -	bgp->maxmed_admin_value = BGP_MAXMED_VALUE_DEFAULT; -	bgp_maxmed_update(bgp); +	nb_cli_enqueue_change(vty, "./med-config/enable-med-admin", +			      NB_OP_MODIFY, "false"); -	return CMD_SUCCESS; +	nb_cli_enqueue_change(vty, "./med-config/max-med-admin", NB_OP_MODIFY, +			      NULL); + +	return nb_cli_apply_changes(vty, NULL);  } -DEFUN (bgp_maxmed_onstartup, -       bgp_maxmed_onstartup_cmd, -       "bgp max-med on-startup (5-86400) [(0-4294967295)]", -       BGP_STR -       "Advertise routes with max-med\n" -       "Effective on a startup\n" -       "Time (seconds) period for max-med\n" -       "Max MED value to be used\n") +DEFUN_YANG(bgp_maxmed_onstartup, +	   bgp_maxmed_onstartup_cmd, +	   "bgp max-med on-startup (5-86400) [(0-4294967295)]", +	   BGP_STR +	   "Advertise routes with max-med\n" +	   "Effective on a startup\n" +	   "Time (seconds) period for max-med\n" +	   "Max MED value to be used\n")  { -	VTY_DECLVAR_CONTEXT(bgp, bgp);  	int idx = 0;  	argv_find(argv, argc, "(5-86400)", &idx); -	bgp->v_maxmed_onstartup = strtoul(argv[idx]->arg, NULL, 10); +	nb_cli_enqueue_change(vty, "./med-config/max-med-onstart-up-time", +			      NB_OP_MODIFY, argv[idx]->arg); +  	if (argv_find(argv, argc, "(0-4294967295)", &idx)) -		bgp->maxmed_onstartup_value = strtoul(argv[idx]->arg, NULL, 10); +		nb_cli_enqueue_change(vty, +				      "./med-config/max-med-onstart-up-value", +				      NB_OP_MODIFY, argv[idx]->arg);  	else -		bgp->maxmed_onstartup_value = BGP_MAXMED_VALUE_DEFAULT; - -	bgp_maxmed_update(bgp); +		nb_cli_enqueue_change(vty, +				      "./med-config/max-med-onstart-up-value", +				      NB_OP_MODIFY, NULL); -	return CMD_SUCCESS; +	return nb_cli_apply_changes(vty, NULL);  } -DEFUN (no_bgp_maxmed_onstartup, -       no_bgp_maxmed_onstartup_cmd, -       "no bgp max-med on-startup [(5-86400) [(0-4294967295)]]", -       NO_STR -       BGP_STR -       "Advertise routes with max-med\n" -       "Effective on a startup\n" -       "Time (seconds) period for max-med\n" -       "Max MED value to be used\n") +DEFUN_YANG(no_bgp_maxmed_onstartup, +	   no_bgp_maxmed_onstartup_cmd, +	   "no bgp max-med on-startup [(5-86400) [(0-4294967295)]]", +	   NO_STR BGP_STR +	   "Advertise routes with max-med\n" +	   "Effective on a startup\n" +	   "Time (seconds) period for max-med\n" +	   "Max MED value to be used\n")  { -	VTY_DECLVAR_CONTEXT(bgp, bgp); - -	/* Cancel max-med onstartup if its on */ -	if (bgp->t_maxmed_onstartup) { -		THREAD_TIMER_OFF(bgp->t_maxmed_onstartup); -		bgp->maxmed_onstartup_over = 1; -	} - -	bgp->v_maxmed_onstartup = BGP_MAXMED_ONSTARTUP_UNCONFIGURED; -	bgp->maxmed_onstartup_value = BGP_MAXMED_VALUE_DEFAULT; +	nb_cli_enqueue_change(vty, "./med-config/max-med-onstart-up-time", +			      NB_OP_DESTROY, NULL); -	bgp_maxmed_update(bgp); +	nb_cli_enqueue_change(vty, "./med-config/max-med-onstart-up-value", +			      NB_OP_MODIFY, NULL); -	return CMD_SUCCESS; +	return nb_cli_apply_changes(vty, NULL);  }  static int bgp_global_update_delay_config_vty(struct vty *vty, @@ -1858,22 +1918,16 @@ DEFPY (no_bgp_update_delay,  } -static int bgp_wpkt_quanta_config_vty(struct vty *vty, uint32_t quanta, -				      bool set) +int bgp_wpkt_quanta_config_vty(struct bgp *bgp, uint32_t quanta, bool set)  { -	VTY_DECLVAR_CONTEXT(bgp, bgp); -  	quanta = set ? quanta : BGP_WRITE_PACKET_MAX;  	atomic_store_explicit(&bgp->wpkt_quanta, quanta, memory_order_relaxed);  	return CMD_SUCCESS;  } -static int bgp_rpkt_quanta_config_vty(struct vty *vty, uint32_t quanta, -				      bool set) +int bgp_rpkt_quanta_config_vty(struct bgp *bgp, uint32_t quanta, bool set)  { -	VTY_DECLVAR_CONTEXT(bgp, bgp); -  	quanta = set ? quanta : BGP_READ_PACKET_MAX;  	atomic_store_explicit(&bgp->rpkt_quanta, quanta, memory_order_relaxed); @@ -1904,24 +1958,46 @@ void bgp_config_write_rpkt_quanta(struct vty *vty, struct bgp *bgp)   * Furthermore, the maximums used here should correspond to   * BGP_WRITE_PACKET_MAX and BGP_READ_PACKET_MAX.   */ -DEFPY (bgp_wpkt_quanta, -       bgp_wpkt_quanta_cmd, -       "[no] write-quanta (1-64)$quanta", -       NO_STR -       "How many packets to write to peer socket per run\n" -       "Number of packets\n") -{ -	return bgp_wpkt_quanta_config_vty(vty, quanta, !no); -} +DEFPY_YANG(bgp_wpkt_quanta, +	   bgp_wpkt_quanta_cmd, +	   "[no] write-quanta (1-64)$quanta", +	   NO_STR +	   "How many packets to write to peer socket per run\n" +	   "Number of packets\n") +{ +	if (!no) +		nb_cli_enqueue_change( +			vty, +			"./global-neighbor-config/packet-quanta-config/wpkt-quanta", +			NB_OP_MODIFY, quanta_str); +	else +		nb_cli_enqueue_change( +			vty, +			"./global-neighbor-config/packet-quanta-config/wpkt-quanta", +			NB_OP_MODIFY, NULL); + +	return nb_cli_apply_changes(vty, NULL); +} + +DEFPY_YANG(bgp_rpkt_quanta, +	   bgp_rpkt_quanta_cmd, +	   "[no] read-quanta (1-10)$quanta", +	   NO_STR +	   "How many packets to read from peer socket per I/O cycle\n" +	   "Number of packets\n") +{ +	if (!no) +		nb_cli_enqueue_change( +			vty, +			"./global-neighbor-config/packet-quanta-config/rpkt-quanta", +			NB_OP_MODIFY, quanta_str); +	else +		nb_cli_enqueue_change( +			vty, +			"./global-neighbor-config/packet-quanta-config/rpkt-quanta", +			NB_OP_MODIFY, NULL); -DEFPY (bgp_rpkt_quanta, -       bgp_rpkt_quanta_cmd, -       "[no] read-quanta (1-10)$quanta", -       NO_STR -       "How many packets to read from peer socket per I/O cycle\n" -       "Number of packets\n") -{ -	return bgp_rpkt_quanta_config_vty(vty, quanta, !no); +	return nb_cli_apply_changes(vty, NULL);  }  void bgp_config_write_coalesce_time(struct vty *vty, struct bgp *bgp) @@ -1930,34 +2006,39 @@ void bgp_config_write_coalesce_time(struct vty *vty, struct bgp *bgp)  		vty_out(vty, " coalesce-time %u\n", bgp->coalesce_time);  } - -DEFUN (bgp_coalesce_time, -       bgp_coalesce_time_cmd, -       "coalesce-time (0-4294967295)", -       "Subgroup coalesce timer\n" -       "Subgroup coalesce timer value (in ms)\n") +void cli_show_router_global_update_group_config_coalesce_time( +	struct vty *vty, struct lyd_node *dnode, bool show_defaults)  { -	VTY_DECLVAR_CONTEXT(bgp, bgp); +	vty_out(vty, " coalesce-time %u\n", yang_dnode_get_uint32(dnode, NULL)); +} + +DEFUN_YANG(bgp_coalesce_time, +	   bgp_coalesce_time_cmd, +	   "coalesce-time (0-4294967295)", +	   "Subgroup coalesce timer\n" +	   "Subgroup coalesce timer value (in ms)\n") +{  	int idx = 0; +  	argv_find(argv, argc, "(0-4294967295)", &idx); -	bgp->heuristic_coalesce = false; -	bgp->coalesce_time = strtoul(argv[idx]->arg, NULL, 10); -	return CMD_SUCCESS; +	nb_cli_enqueue_change(vty, "./global-update-group-config/coalesce-time", +			      NB_OP_MODIFY, argv[idx]->arg); + +	return nb_cli_apply_changes(vty, NULL);  } -DEFUN (no_bgp_coalesce_time, -       no_bgp_coalesce_time_cmd, -       "no coalesce-time (0-4294967295)", -       NO_STR -       "Subgroup coalesce timer\n" -       "Subgroup coalesce timer value (in ms)\n") +DEFUN_YANG(no_bgp_coalesce_time, +	   no_bgp_coalesce_time_cmd, +	   "no coalesce-time (0-4294967295)", +	   NO_STR +	   "Subgroup coalesce timer\n" +	   "Subgroup coalesce timer value (in ms)\n")  { -	VTY_DECLVAR_CONTEXT(bgp, bgp); +	nb_cli_enqueue_change(vty, "./global-update-group-config/coalesce-time", +			      NB_OP_MODIFY, NULL); -	bgp->heuristic_coalesce = true; -	bgp->coalesce_time = BGP_DEFAULT_SUBGROUP_COALESCE_TIME; -	return CMD_SUCCESS; +	return nb_cli_apply_changes(vty, NULL);  }  /* Maximum-paths configuration */ @@ -2073,129 +2154,181 @@ static void bgp_config_write_maxpaths(struct vty *vty, struct bgp *bgp,  /* BGP timers.  */ -DEFUN (bgp_timers, -       bgp_timers_cmd, -       "timers bgp (0-65535) (0-65535)", -       "Adjust routing timers\n" -       "BGP timers\n" -       "Keepalive interval\n" -       "Holdtime\n") +DEFUN_YANG(bgp_timers, +	   bgp_timers_cmd, +	   "timers bgp (0-65535) (0-65535)", +	   "Adjust routing timers\n" +	   "BGP timers\n" +	   "Keepalive interval\n" +	   "Holdtime\n")  { -	VTY_DECLVAR_CONTEXT(bgp, bgp);  	int idx_number = 2;  	int idx_number_2 = 3; -	unsigned long keepalive = 0; -	unsigned long holdtime = 0; -	keepalive = strtoul(argv[idx_number]->arg, NULL, 10); -	holdtime = strtoul(argv[idx_number_2]->arg, NULL, 10); +	nb_cli_enqueue_change(vty, "./global-config-timers/keepalive", +			      NB_OP_MODIFY, argv[idx_number]->arg); +	nb_cli_enqueue_change(vty, "./global-config-timers/hold-time", +			      NB_OP_MODIFY, argv[idx_number_2]->arg); -	/* Holdtime value check. */ -	if (holdtime < 3 && holdtime != 0) { -		vty_out(vty, -			"%% hold time value must be either 0 or greater than 3\n"); -		return CMD_WARNING_CONFIG_FAILED; -	} +	return nb_cli_apply_changes(vty, NULL); +} -	bgp_timers_set(bgp, keepalive, holdtime, DFLT_BGP_CONNECT_RETRY); +DEFUN_YANG(no_bgp_timers, +	   no_bgp_timers_cmd, +	   "no timers bgp [(0-65535) (0-65535)]", +	   NO_STR +	   "Adjust routing timers\n" +	   "BGP timers\n" +	   "Keepalive interval\n" +	   "Holdtime\n") +{ +	nb_cli_enqueue_change(vty, "./global-config-timers/keepalive", +			      NB_OP_DESTROY, NULL); +	nb_cli_enqueue_change(vty, "./global-config-timers/hold-time", +			      NB_OP_DESTROY, NULL); -	return CMD_SUCCESS; +	return nb_cli_apply_changes(vty, NULL);  } -DEFUN (no_bgp_timers, -       no_bgp_timers_cmd, -       "no timers bgp [(0-65535) (0-65535)]", -       NO_STR -       "Adjust routing timers\n" -       "BGP timers\n" -       "Keepalive interval\n" -       "Holdtime\n") +void cli_show_router_bgp_route_reflector(struct vty *vty, +					 struct lyd_node *dnode, +					 bool show_defaults)  { -	VTY_DECLVAR_CONTEXT(bgp, bgp); -	bgp_timers_set(bgp, DFLT_BGP_KEEPALIVE, DFLT_BGP_HOLDTIME, -		       DFLT_BGP_CONNECT_RETRY); +	if (yang_dnode_get_bool(dnode, "./no-client-reflect")) +		vty_out(vty, " no bgp client-to-client reflection\n"); -	return CMD_SUCCESS; +	if (yang_dnode_get_bool(dnode, "./allow-outbound-policy")) +		vty_out(vty, " bgp route-reflector allow-outbound-policy\n"); + +	if (yang_dnode_exists(dnode, "./route-reflector-cluster-id")) +		vty_out(vty, " bgp cluster-id %s\n", +			yang_dnode_get_string(dnode, +					      "./route-reflector-cluster-id"));  } +DEFUN_YANG(bgp_client_to_client_reflection, +	   bgp_client_to_client_reflection_cmd, +	   "bgp client-to-client reflection", +	   "BGP specific commands\n" +	   "Configure client to client route reflection\n" +	   "reflection of routes allowed\n") +{ +	nb_cli_enqueue_change(vty, "./route-reflector/no-client-reflect", +			      NB_OP_MODIFY, "false"); -DEFUN (bgp_client_to_client_reflection, -       bgp_client_to_client_reflection_cmd, -       "bgp client-to-client reflection", -       "BGP specific commands\n" -       "Configure client to client route reflection\n" -       "reflection of routes allowed\n") +	return nb_cli_apply_changes(vty, NULL); +} + +DEFUN_YANG(no_bgp_client_to_client_reflection, +	   no_bgp_client_to_client_reflection_cmd, +	   "no bgp client-to-client reflection", +	   NO_STR +	   "BGP specific commands\n" +	   "Configure client to client route reflection\n" +	   "reflection of routes allowed\n")  { -	VTY_DECLVAR_CONTEXT(bgp, bgp); -	UNSET_FLAG(bgp->flags, BGP_FLAG_NO_CLIENT_TO_CLIENT); -	bgp_clear_star_soft_out(vty, bgp->name); +	nb_cli_enqueue_change(vty, "./route-reflector/no-client-reflect", +			      NB_OP_MODIFY, "true"); -	return CMD_SUCCESS; +	return nb_cli_apply_changes(vty, NULL);  } -DEFUN (no_bgp_client_to_client_reflection, -       no_bgp_client_to_client_reflection_cmd, -       "no bgp client-to-client reflection", -       NO_STR -       "BGP specific commands\n" -       "Configure client to client route reflection\n" -       "reflection of routes allowed\n") +void cli_show_router_bgp_route_selection(struct vty *vty, +					 struct lyd_node *dnode, +					 bool show_defaults)  { -	VTY_DECLVAR_CONTEXT(bgp, bgp); -	SET_FLAG(bgp->flags, BGP_FLAG_NO_CLIENT_TO_CLIENT); -	bgp_clear_star_soft_out(vty, bgp->name); -	return CMD_SUCCESS; +	if (yang_dnode_get_bool(dnode, "./always-compare-med")) +		vty_out(vty, " bgp always-compare-med\n"); + +	if (yang_dnode_get_bool(dnode, "./ignore-as-path-length")) +		vty_out(vty, " bgp bestpath as-path ignore\n"); + +	if (yang_dnode_get_bool(dnode, "./aspath-confed")) +		vty_out(vty, " bgp bestpath as-path confed\n"); + +	if (yang_dnode_get_bool(dnode, "./external-compare-router-id")) +		vty_out(vty, " bgp bestpath compare-routerid\n"); + +	if (yang_dnode_get_bool(dnode, "./allow-multiple-as")) { +		if (yang_dnode_get_bool(dnode, "./multi-path-as-set")) +			vty_out(vty, +				" bgp bestpath as-path multipath-relax as-set\n"); +		else +			vty_out(vty, " bgp bestpath as-path multipath-relax\n"); +	} + +	if (yang_dnode_get_bool(dnode, "./deterministic-med")) +		vty_out(vty, " bgp deterministic-med\n"); + +	if (yang_dnode_get_bool(dnode, "./confed-med") +	    || yang_dnode_get_bool(dnode, "./missing-as-worst-med")) { +		vty_out(vty, " bgp bestpath med"); +		if (yang_dnode_get_bool(dnode, "./confed-med")) +			vty_out(vty, " confed"); +		if (yang_dnode_get_bool(dnode, "./missing-as-worst-med")) +			vty_out(vty, " missing-as-worst"); +		vty_out(vty, "\n"); +	}  }  /* "bgp always-compare-med" configuration. */ -DEFUN (bgp_always_compare_med, -       bgp_always_compare_med_cmd, -       "bgp always-compare-med", -       "BGP specific commands\n" -       "Allow comparing MED from different neighbors\n") +DEFUN_YANG(bgp_always_compare_med, +	   bgp_always_compare_med_cmd, +	   "bgp always-compare-med", +	   "BGP specific commands\n" +	   "Allow comparing MED from different neighbors\n")  { -	VTY_DECLVAR_CONTEXT(bgp, bgp); -	SET_FLAG(bgp->flags, BGP_FLAG_ALWAYS_COMPARE_MED); -	bgp_recalculate_all_bestpaths(bgp); +	nb_cli_enqueue_change(vty, +			      "./route-selection-options/always-compare-med", +			      NB_OP_MODIFY, "true"); -	return CMD_SUCCESS; +	return nb_cli_apply_changes(vty, NULL);  } -DEFUN (no_bgp_always_compare_med, -       no_bgp_always_compare_med_cmd, -       "no bgp always-compare-med", -       NO_STR -       "BGP specific commands\n" -       "Allow comparing MED from different neighbors\n") +DEFUN_YANG(no_bgp_always_compare_med, +	   no_bgp_always_compare_med_cmd, +	   "no bgp always-compare-med", +	   NO_STR +	   "BGP specific commands\n" +	   "Allow comparing MED from different neighbors\n")  { -	VTY_DECLVAR_CONTEXT(bgp, bgp); -	UNSET_FLAG(bgp->flags, BGP_FLAG_ALWAYS_COMPARE_MED); -	bgp_recalculate_all_bestpaths(bgp); +	nb_cli_enqueue_change(vty, +			      "./route-selection-options/always-compare-med", +			      NB_OP_MODIFY, "false"); -	return CMD_SUCCESS; +	return nb_cli_apply_changes(vty, NULL);  } +DEFUN_YANG(bgp_ebgp_requires_policy, +	   bgp_ebgp_requires_policy_cmd, +	   "bgp ebgp-requires-policy", +	   "BGP specific commands\n" +	   "Require in and out policy for eBGP peers (RFC8212)\n") +{ +	nb_cli_enqueue_change(vty, "./ebgp-requires-policy", NB_OP_MODIFY, +			      "true"); +	return nb_cli_apply_changes(vty, NULL); +} -DEFUN(bgp_ebgp_requires_policy, bgp_ebgp_requires_policy_cmd, -      "bgp ebgp-requires-policy", -      "BGP specific commands\n" -      "Require in and out policy for eBGP peers (RFC8212)\n") +DEFUN_YANG(no_bgp_ebgp_requires_policy, +	   no_bgp_ebgp_requires_policy_cmd, +	   "no bgp ebgp-requires-policy", +	   NO_STR +	   "BGP specific commands\n" +	   "Require in and out policy for eBGP peers (RFC8212)\n")  { -	VTY_DECLVAR_CONTEXT(bgp, bgp); -	SET_FLAG(bgp->flags, BGP_FLAG_EBGP_REQUIRES_POLICY); -	return CMD_SUCCESS; +	nb_cli_enqueue_change(vty, "./ebgp-requires-policy", NB_OP_MODIFY, +			      "false"); +	return nb_cli_apply_changes(vty, NULL);  } -DEFUN(no_bgp_ebgp_requires_policy, no_bgp_ebgp_requires_policy_cmd, -      "no bgp ebgp-requires-policy", -      NO_STR -      "BGP specific commands\n" -      "Require in and out policy for eBGP peers (RFC8212)\n") +void cli_show_router_bgp_ebgp_requires_policy(struct vty *vty, +					      struct lyd_node *dnode, +					      bool show_defaults)  { -	VTY_DECLVAR_CONTEXT(bgp, bgp); -	UNSET_FLAG(bgp->flags, BGP_FLAG_EBGP_REQUIRES_POLICY); -	return CMD_SUCCESS; +	if (yang_dnode_get_bool(dnode, NULL) != SAVE_BGP_EBGP_REQUIRES_POLICY) +		vty_out(vty, " bgp ebgp-requires-policy\n");  }  DEFUN(bgp_reject_as_sets, bgp_reject_as_sets_cmd, @@ -2250,62 +2383,31 @@ DEFUN(no_bgp_reject_as_sets, no_bgp_reject_as_sets_cmd,  }  /* "bgp deterministic-med" configuration. */ -DEFUN (bgp_deterministic_med, +DEFUN_YANG (bgp_deterministic_med,         bgp_deterministic_med_cmd,         "bgp deterministic-med",         "BGP specific commands\n"         "Pick the best-MED path among paths advertised from the neighboring AS\n")  { -	VTY_DECLVAR_CONTEXT(bgp, bgp); +	nb_cli_enqueue_change(vty, +			      "./route-selection-options/deterministic-med", +			      NB_OP_MODIFY, "true"); -	if (!CHECK_FLAG(bgp->flags, BGP_FLAG_DETERMINISTIC_MED)) { -		SET_FLAG(bgp->flags, BGP_FLAG_DETERMINISTIC_MED); -		bgp_recalculate_all_bestpaths(bgp); -	} - -	return CMD_SUCCESS; +	return nb_cli_apply_changes(vty, NULL);  } -DEFUN (no_bgp_deterministic_med, +DEFUN_YANG (no_bgp_deterministic_med,         no_bgp_deterministic_med_cmd,         "no bgp deterministic-med",         NO_STR         "BGP specific commands\n"         "Pick the best-MED path among paths advertised from the neighboring AS\n")  { -	VTY_DECLVAR_CONTEXT(bgp, bgp); -	int bestpath_per_as_used; -	afi_t afi; -	safi_t safi; -	struct peer *peer; -	struct listnode *node, *nnode; - -	if (CHECK_FLAG(bgp->flags, BGP_FLAG_DETERMINISTIC_MED)) { -		bestpath_per_as_used = 0; - -		for (ALL_LIST_ELEMENTS(bgp->peer, node, nnode, peer)) { -			FOREACH_AFI_SAFI (afi, safi) -				if (bgp_addpath_dmed_required( -					peer->addpath_type[afi][safi])) { -					bestpath_per_as_used = 1; -					break; -				} - -			if (bestpath_per_as_used) -				break; -		} - -		if (bestpath_per_as_used) { -			vty_out(vty, -				"bgp deterministic-med cannot be disabled while addpath-tx-bestpath-per-AS is in use\n"); -			return CMD_WARNING_CONFIG_FAILED; -		} else { -			UNSET_FLAG(bgp->flags, BGP_FLAG_DETERMINISTIC_MED); -			bgp_recalculate_all_bestpaths(bgp); -		} -	} +	nb_cli_enqueue_change(vty, +			      "./route-selection-options/deterministic-med", +			      NB_OP_MODIFY, "false"); -	return CMD_SUCCESS; +	return nb_cli_apply_changes(vty, NULL);  }  /* "bgp graceful-restart mode" configuration. */ @@ -2840,13 +2942,18 @@ DEFUN (no_bgp_graceful_restart_rib_stale_time,  	return CMD_SUCCESS;  } -static inline void bgp_initiate_graceful_shut_unshut(struct vty *vty, -						     struct bgp *bgp) +static inline int bgp_initiate_graceful_shut_unshut(struct bgp *bgp, +						    char *errmsg, +						    size_t errmsg_len)  {  	bgp_static_redo_import_check(bgp);  	bgp_redistribute_redo(bgp); -	bgp_clear_star_soft_out(vty, bgp->name); -	bgp_clear_star_soft_in(vty, bgp->name); +	if (bgp_clear_star_soft_out(bgp->name, errmsg, errmsg_len) < 0) +		return -1; +	if (bgp_clear_star_soft_in(bgp->name, errmsg, errmsg_len) < 0) +		return -1; + +	return 0;  }  static int bgp_global_graceful_shutdown_config_vty(struct vty *vty) @@ -2854,6 +2961,7 @@ static int bgp_global_graceful_shutdown_config_vty(struct vty *vty)  	struct listnode *node, *nnode;  	struct bgp *bgp;  	bool vrf_cfg = false; +	char errmsg[BUFSIZ] = {'\0'};  	if (CHECK_FLAG(bm->flags, BM_FLAG_GRACEFUL_SHUTDOWN))  		return CMD_SUCCESS; @@ -2879,8 +2987,13 @@ static int bgp_global_graceful_shutdown_config_vty(struct vty *vty)  	SET_FLAG(bm->flags, BM_FLAG_GRACEFUL_SHUTDOWN);  	/* Initiate processing for all BGP instances. */ -	for (ALL_LIST_ELEMENTS(bm->bgp, node, nnode, bgp)) -		bgp_initiate_graceful_shut_unshut(vty, bgp); +	for (ALL_LIST_ELEMENTS(bm->bgp, node, nnode, bgp)) { +		if (bgp_initiate_graceful_shut_unshut(bgp, errmsg, +						      sizeof(errmsg)) +		    < 0) +			if (strlen(errmsg)) +				vty_out(vty, "%s\n", errmsg); +	}  	return CMD_SUCCESS;  } @@ -2889,6 +3002,7 @@ static int bgp_global_graceful_shutdown_deconfig_vty(struct vty *vty)  {  	struct listnode *node, *nnode;  	struct bgp *bgp; +	char errmsg[BUFSIZ] = {'\0'};  	if (!CHECK_FLAG(bm->flags, BM_FLAG_GRACEFUL_SHUTDOWN))  		return CMD_SUCCESS; @@ -2897,8 +3011,13 @@ static int bgp_global_graceful_shutdown_deconfig_vty(struct vty *vty)  	UNSET_FLAG(bm->flags, BM_FLAG_GRACEFUL_SHUTDOWN);  	/* Initiate processing for all BGP instances. */ -	for (ALL_LIST_ELEMENTS(bm->bgp, node, nnode, bgp)) -		bgp_initiate_graceful_shut_unshut(vty, bgp); +	for (ALL_LIST_ELEMENTS(bm->bgp, node, nnode, bgp)) { +		if (bgp_initiate_graceful_shut_unshut(bgp, errmsg, +						      sizeof(errmsg)) +		    < 0) +			if (strlen(errmsg)) +				vty_out(vty, "%s\n", errmsg); +	}  	return CMD_SUCCESS;  } @@ -2913,24 +3032,13 @@ DEFUN (bgp_graceful_shutdown,  	if (vty->node == CONFIG_NODE)  		return bgp_global_graceful_shutdown_config_vty(vty); -	VTY_DECLVAR_CONTEXT(bgp, bgp); - -	/* if configured globally, per-instance config is not allowed */ -	if (CHECK_FLAG(bm->flags, BM_FLAG_GRACEFUL_SHUTDOWN)) { -		vty_out(vty, -			"%%Failed: per-vrf graceful-shutdown config not permitted with global graceful-shutdown\n"); -		return CMD_WARNING_CONFIG_FAILED; -	} - -	if (!CHECK_FLAG(bgp->flags, BGP_FLAG_GRACEFUL_SHUTDOWN)) { -		SET_FLAG(bgp->flags, BGP_FLAG_GRACEFUL_SHUTDOWN); -		bgp_initiate_graceful_shut_unshut(vty, bgp); -	} +	nb_cli_enqueue_change(vty, "./graceful-shutdown/enable", NB_OP_MODIFY, +			      "true"); -	return CMD_SUCCESS; +	return nb_cli_apply_changes(vty, NULL);  } -DEFUN (no_bgp_graceful_shutdown, +DEFUN_YANG (no_bgp_graceful_shutdown,         no_bgp_graceful_shutdown_cmd,         "no bgp graceful-shutdown",         NO_STR @@ -2940,111 +3048,118 @@ DEFUN (no_bgp_graceful_shutdown,  	if (vty->node == CONFIG_NODE)  		return bgp_global_graceful_shutdown_deconfig_vty(vty); -	VTY_DECLVAR_CONTEXT(bgp, bgp); - -	/* If configured globally, cannot remove from one bgp instance */ -	if (CHECK_FLAG(bm->flags, BM_FLAG_GRACEFUL_SHUTDOWN)) { -		vty_out(vty, -			"%%Failed: bgp graceful-shutdown configured globally. Delete per-vrf not permitted\n"); -		return CMD_WARNING_CONFIG_FAILED; -	} +	nb_cli_enqueue_change(vty, "./graceful-shutdown/enable", NB_OP_MODIFY, +			      "false"); -	if (CHECK_FLAG(bgp->flags, BGP_FLAG_GRACEFUL_SHUTDOWN)) { -		UNSET_FLAG(bgp->flags, BGP_FLAG_GRACEFUL_SHUTDOWN); -		bgp_initiate_graceful_shut_unshut(vty, bgp); -	} +	return nb_cli_apply_changes(vty, NULL); +} -	return CMD_SUCCESS; +void cli_show_router_bgp_graceful_shutdown(struct vty *vty, +					   struct lyd_node *dnode, +					   bool show_defaults) +{ +	if (yang_dnode_get_bool(dnode, NULL)) +		vty_out(vty, " bgp graceful-shutdown\n");  }  /* "bgp fast-external-failover" configuration. */ -DEFUN (bgp_fast_external_failover, +DEFUN_YANG (bgp_fast_external_failover,         bgp_fast_external_failover_cmd,         "bgp fast-external-failover",         BGP_STR         "Immediately reset session if a link to a directly connected external peer goes down\n")  { -	VTY_DECLVAR_CONTEXT(bgp, bgp); -	UNSET_FLAG(bgp->flags, BGP_FLAG_NO_FAST_EXT_FAILOVER); -	return CMD_SUCCESS; +	nb_cli_enqueue_change(vty, "./fast-external-failover", NB_OP_MODIFY, +			      "false"); + +	return nb_cli_apply_changes(vty, NULL);  } -DEFUN (no_bgp_fast_external_failover, +DEFUN_YANG (no_bgp_fast_external_failover,         no_bgp_fast_external_failover_cmd,         "no bgp fast-external-failover",         NO_STR         BGP_STR         "Immediately reset session if a link to a directly connected external peer goes down\n")  { -	VTY_DECLVAR_CONTEXT(bgp, bgp); -	SET_FLAG(bgp->flags, BGP_FLAG_NO_FAST_EXT_FAILOVER); -	return CMD_SUCCESS; +	nb_cli_enqueue_change(vty, "./fast-external-failover", NB_OP_MODIFY, +			      "true"); + +	return nb_cli_apply_changes(vty, NULL); +} + +void cli_show_router_bgp_fast_external_failover(struct vty *vty, +						struct lyd_node *dnode, +						bool show_defaults) +{ +	if (!yang_dnode_get_bool(dnode, NULL)) +		vty_out(vty, " no bgp fast-external-failover\n");  }  /* "bgp bestpath compare-routerid" configuration.  */ -DEFUN (bgp_bestpath_compare_router_id, -       bgp_bestpath_compare_router_id_cmd, -       "bgp bestpath compare-routerid", -       "BGP specific commands\n" -       "Change the default bestpath selection\n" -       "Compare router-id for identical EBGP paths\n") +DEFUN_YANG(bgp_bestpath_compare_router_id, +	   bgp_bestpath_compare_router_id_cmd, +	   "bgp bestpath compare-routerid", +	   "BGP specific commands\n" +	   "Change the default bestpath selection\n" +	   "Compare router-id for identical EBGP paths\n")  { -	VTY_DECLVAR_CONTEXT(bgp, bgp); -	SET_FLAG(bgp->flags, BGP_FLAG_COMPARE_ROUTER_ID); -	bgp_recalculate_all_bestpaths(bgp); +	nb_cli_enqueue_change( +		vty, "./route-selection-options/external-compare-router-id", +		NB_OP_MODIFY, "true"); -	return CMD_SUCCESS; +	return nb_cli_apply_changes(vty, NULL);  } -DEFUN (no_bgp_bestpath_compare_router_id, -       no_bgp_bestpath_compare_router_id_cmd, -       "no bgp bestpath compare-routerid", -       NO_STR -       "BGP specific commands\n" -       "Change the default bestpath selection\n" -       "Compare router-id for identical EBGP paths\n") +DEFUN_YANG(no_bgp_bestpath_compare_router_id, +	   no_bgp_bestpath_compare_router_id_cmd, +	   "no bgp bestpath compare-routerid", +	   NO_STR +	   "BGP specific commands\n" +	   "Change the default bestpath selection\n" +	   "Compare router-id for identical EBGP paths\n")  { -	VTY_DECLVAR_CONTEXT(bgp, bgp); -	UNSET_FLAG(bgp->flags, BGP_FLAG_COMPARE_ROUTER_ID); -	bgp_recalculate_all_bestpaths(bgp); +	nb_cli_enqueue_change( +		vty, "./route-selection-options/external-compare-router-id", +		NB_OP_MODIFY, "false"); -	return CMD_SUCCESS; +	return nb_cli_apply_changes(vty, NULL);  }  /* "bgp bestpath as-path ignore" configuration.  */ -DEFUN (bgp_bestpath_aspath_ignore, -       bgp_bestpath_aspath_ignore_cmd, -       "bgp bestpath as-path ignore", -       "BGP specific commands\n" -       "Change the default bestpath selection\n" -       "AS-path attribute\n" -       "Ignore as-path length in selecting a route\n") +DEFUN_YANG(bgp_bestpath_aspath_ignore, +	   bgp_bestpath_aspath_ignore_cmd, +	   "bgp bestpath as-path ignore", +	   "BGP specific commands\n" +	   "Change the default bestpath selection\n" +	   "AS-path attribute\n" +	   "Ignore as-path length in selecting a route\n")  { -	VTY_DECLVAR_CONTEXT(bgp, bgp); -	SET_FLAG(bgp->flags, BGP_FLAG_ASPATH_IGNORE); -	bgp_recalculate_all_bestpaths(bgp); +	nb_cli_enqueue_change(vty, +			      "./route-selection-options/ignore-as-path-length", +			      NB_OP_MODIFY, "true"); -	return CMD_SUCCESS; +	return nb_cli_apply_changes(vty, NULL);  } -DEFUN (no_bgp_bestpath_aspath_ignore, -       no_bgp_bestpath_aspath_ignore_cmd, -       "no bgp bestpath as-path ignore", -       NO_STR -       "BGP specific commands\n" -       "Change the default bestpath selection\n" -       "AS-path attribute\n" -       "Ignore as-path length in selecting a route\n") +DEFUN_YANG(no_bgp_bestpath_aspath_ignore, +	   no_bgp_bestpath_aspath_ignore_cmd, +	   "no bgp bestpath as-path ignore", +	   NO_STR +	   "BGP specific commands\n" +	   "Change the default bestpath selection\n" +	   "AS-path attribute\n" +	   "Ignore as-path length in selecting a route\n")  { -	VTY_DECLVAR_CONTEXT(bgp, bgp); -	UNSET_FLAG(bgp->flags, BGP_FLAG_ASPATH_IGNORE); -	bgp_recalculate_all_bestpaths(bgp); +	nb_cli_enqueue_change(vty, +			      "./route-selection-options/ignore-as-path-length", +			      NB_OP_MODIFY, "false"); -	return CMD_SUCCESS; +	return nb_cli_apply_changes(vty, NULL);  }  /* "bgp bestpath as-path confed" configuration.  */ -DEFUN (bgp_bestpath_aspath_confed, +DEFUN_YANG (bgp_bestpath_aspath_confed,         bgp_bestpath_aspath_confed_cmd,         "bgp bestpath as-path confed",         "BGP specific commands\n" @@ -3052,14 +3167,13 @@ DEFUN (bgp_bestpath_aspath_confed,         "AS-path attribute\n"         "Compare path lengths including confederation sets & sequences in selecting a route\n")  { -	VTY_DECLVAR_CONTEXT(bgp, bgp); -	SET_FLAG(bgp->flags, BGP_FLAG_ASPATH_CONFED); -	bgp_recalculate_all_bestpaths(bgp); +	nb_cli_enqueue_change(vty, "./route-selection-options/aspath-confed", +			      NB_OP_MODIFY, "true"); -	return CMD_SUCCESS; +	return nb_cli_apply_changes(vty, NULL);  } -DEFUN (no_bgp_bestpath_aspath_confed, +DEFUN_YANG (no_bgp_bestpath_aspath_confed,         no_bgp_bestpath_aspath_confed_cmd,         "no bgp bestpath as-path confed",         NO_STR @@ -3068,15 +3182,14 @@ DEFUN (no_bgp_bestpath_aspath_confed,         "AS-path attribute\n"         "Compare path lengths including confederation sets & sequences in selecting a route\n")  { -	VTY_DECLVAR_CONTEXT(bgp, bgp); -	UNSET_FLAG(bgp->flags, BGP_FLAG_ASPATH_CONFED); -	bgp_recalculate_all_bestpaths(bgp); +	nb_cli_enqueue_change(vty, "./route-selection-options/aspath-confed", +			      NB_OP_MODIFY, "false"); -	return CMD_SUCCESS; +	return nb_cli_apply_changes(vty, NULL);  }  /* "bgp bestpath as-path multipath-relax" configuration.  */ -DEFUN (bgp_bestpath_aspath_multipath_relax, +DEFUN_YANG (bgp_bestpath_aspath_multipath_relax,         bgp_bestpath_aspath_multipath_relax_cmd,         "bgp bestpath as-path multipath-relax [<as-set|no-as-set>]",         "BGP specific commands\n" @@ -3086,23 +3199,24 @@ DEFUN (bgp_bestpath_aspath_multipath_relax,         "Generate an AS_SET\n"         "Do not generate an AS_SET\n")  { -	VTY_DECLVAR_CONTEXT(bgp, bgp);  	int idx = 0; -	SET_FLAG(bgp->flags, BGP_FLAG_ASPATH_MULTIPATH_RELAX); -	/* no-as-set is now the default behavior so we can silently -	 * ignore it */ +	nb_cli_enqueue_change(vty, +			      "./route-selection-options/allow-multiple-as", +			      NB_OP_MODIFY, "true");  	if (argv_find(argv, argc, "as-set", &idx)) -		SET_FLAG(bgp->flags, BGP_FLAG_MULTIPATH_RELAX_AS_SET); +		nb_cli_enqueue_change( +			vty, "./route-selection-options/multi-path-as-set", +			NB_OP_MODIFY, "true");  	else -		UNSET_FLAG(bgp->flags, BGP_FLAG_MULTIPATH_RELAX_AS_SET); - -	bgp_recalculate_all_bestpaths(bgp); +		nb_cli_enqueue_change( +			vty, "./route-selection-options/multi-path-as-set", +			NB_OP_MODIFY, "false"); -	return CMD_SUCCESS; +	return nb_cli_apply_changes(vty, NULL);  } -DEFUN (no_bgp_bestpath_aspath_multipath_relax, +DEFUN_YANG (no_bgp_bestpath_aspath_multipath_relax,         no_bgp_bestpath_aspath_multipath_relax_cmd,         "no bgp bestpath as-path multipath-relax [<as-set|no-as-set>]",         NO_STR @@ -3113,40 +3227,46 @@ DEFUN (no_bgp_bestpath_aspath_multipath_relax,         "Generate an AS_SET\n"         "Do not generate an AS_SET\n")  { -	VTY_DECLVAR_CONTEXT(bgp, bgp); -	UNSET_FLAG(bgp->flags, BGP_FLAG_ASPATH_MULTIPATH_RELAX); -	UNSET_FLAG(bgp->flags, BGP_FLAG_MULTIPATH_RELAX_AS_SET); -	bgp_recalculate_all_bestpaths(bgp); +	nb_cli_enqueue_change(vty, +			      "./route-selection-options/allow-multiple-as", +			      NB_OP_MODIFY, "false"); +	nb_cli_enqueue_change(vty, +			      "./route-selection-options/multi-path-as-set", +			      NB_OP_MODIFY, "false"); -	return CMD_SUCCESS; +	return nb_cli_apply_changes(vty, NULL);  }  /* "bgp log-neighbor-changes" configuration.  */ -DEFUN (bgp_log_neighbor_changes, -       bgp_log_neighbor_changes_cmd, -       "bgp log-neighbor-changes", -       "BGP specific commands\n" -       "Log neighbor up/down and reset reason\n") +DEFUN_YANG(bgp_log_neighbor_changes, +	   bgp_log_neighbor_changes_cmd, +	   "bgp log-neighbor-changes", +	   "BGP specific commands\n" +	   "Log neighbor up/down and reset reason\n")  { -	VTY_DECLVAR_CONTEXT(bgp, bgp); -	SET_FLAG(bgp->flags, BGP_FLAG_LOG_NEIGHBOR_CHANGES); -	return CMD_SUCCESS; +	nb_cli_enqueue_change(vty, +			      "./global-neighbor-config/log-neighbor-changes", +			      NB_OP_MODIFY, "true"); + +	return nb_cli_apply_changes(vty, NULL);  } -DEFUN (no_bgp_log_neighbor_changes, -       no_bgp_log_neighbor_changes_cmd, -       "no bgp log-neighbor-changes", -       NO_STR -       "BGP specific commands\n" -       "Log neighbor up/down and reset reason\n") +DEFUN_YANG(no_bgp_log_neighbor_changes, +	   no_bgp_log_neighbor_changes_cmd, +	   "no bgp log-neighbor-changes", +	   NO_STR +	   "BGP specific commands\n" +	   "Log neighbor up/down and reset reason\n")  { -	VTY_DECLVAR_CONTEXT(bgp, bgp); -	UNSET_FLAG(bgp->flags, BGP_FLAG_LOG_NEIGHBOR_CHANGES); -	return CMD_SUCCESS; +	nb_cli_enqueue_change(vty, +			      "./global-neighbor-config/log-neighbor-changes", +			      NB_OP_MODIFY, "false"); + +	return nb_cli_apply_changes(vty, NULL);  }  /* "bgp bestpath med" configuration. */ -DEFUN (bgp_bestpath_med, +DEFUN_YANG (bgp_bestpath_med,         bgp_bestpath_med_cmd,         "bgp bestpath med <confed [missing-as-worst]|missing-as-worst [confed]>",         "BGP specific commands\n" @@ -3157,21 +3277,29 @@ DEFUN (bgp_bestpath_med,         "Treat missing MED as the least preferred one\n"         "Compare MED among confederation paths\n")  { -	VTY_DECLVAR_CONTEXT(bgp, bgp); -  	int idx = 0; +	bool confed = false; +	bool worst_med = false; + +  	if (argv_find(argv, argc, "confed", &idx)) -		SET_FLAG(bgp->flags, BGP_FLAG_MED_CONFED); +		confed = true; + +	nb_cli_enqueue_change(vty, "./route-selection-options/confed-med", +			      NB_OP_MODIFY, confed ? "true" : "false"); +  	idx = 0;  	if (argv_find(argv, argc, "missing-as-worst", &idx)) -		SET_FLAG(bgp->flags, BGP_FLAG_MED_MISSING_AS_WORST); +		worst_med = true; -	bgp_recalculate_all_bestpaths(bgp); +	nb_cli_enqueue_change(vty, +			      "./route-selection-options/missing-as-worst-med", +			      NB_OP_MODIFY, worst_med ? "true" : "false"); -	return CMD_SUCCESS; +	return nb_cli_apply_changes(vty, NULL);  } -DEFUN (no_bgp_bestpath_med, +DEFUN_YANG (no_bgp_bestpath_med,         no_bgp_bestpath_med_cmd,         "no bgp bestpath med <confed [missing-as-worst]|missing-as-worst [confed]>",         NO_STR @@ -3183,18 +3311,20 @@ DEFUN (no_bgp_bestpath_med,         "Treat missing MED as the least preferred one\n"         "Compare MED among confederation paths\n")  { -	VTY_DECLVAR_CONTEXT(bgp, bgp); -  	int idx = 0; +  	if (argv_find(argv, argc, "confed", &idx)) -		UNSET_FLAG(bgp->flags, BGP_FLAG_MED_CONFED); +		nb_cli_enqueue_change(vty, +				      "./route-selection-options/confed-med", +				      NB_OP_MODIFY, "false"); +  	idx = 0;  	if (argv_find(argv, argc, "missing-as-worst", &idx)) -		UNSET_FLAG(bgp->flags, BGP_FLAG_MED_MISSING_AS_WORST); +		nb_cli_enqueue_change( +			vty, "./route-selection-options/missing-as-worst-med", +			NB_OP_MODIFY, "false"); -	bgp_recalculate_all_bestpaths(bgp); - -	return CMD_SUCCESS; +	return nb_cli_apply_changes(vty, NULL);  }  /* "bgp bestpath bandwidth" configuration. */ @@ -3288,29 +3418,36 @@ DEFUN (bgp_default_ipv4_unicast,  }  /* Display hostname in certain command outputs */ -DEFUN (bgp_default_show_hostname, +DEFUN_YANG (bgp_default_show_hostname,         bgp_default_show_hostname_cmd,         "bgp default show-hostname",         "BGP specific commands\n"         "Configure BGP defaults\n"         "Show hostname in certain command outputs\n")  { -	VTY_DECLVAR_CONTEXT(bgp, bgp); -	SET_FLAG(bgp->flags, BGP_FLAG_SHOW_HOSTNAME); -	return CMD_SUCCESS; +	nb_cli_enqueue_change(vty, "./show-hostname", NB_OP_MODIFY, "true"); + +	return nb_cli_apply_changes(vty, NULL);  } -DEFUN (no_bgp_default_show_hostname, -       no_bgp_default_show_hostname_cmd, -       "no bgp default show-hostname", -       NO_STR -       "BGP specific commands\n" -       "Configure BGP defaults\n" -       "Show hostname in certain command outputs\n") +DEFUN_YANG(no_bgp_default_show_hostname, +	   no_bgp_default_show_hostname_cmd, +	   "no bgp default show-hostname", +	   NO_STR +	   "BGP specific commands\n" +	   "Configure BGP defaults\n" +	   "Show hostname in certain command outputs\n")  { -	VTY_DECLVAR_CONTEXT(bgp, bgp); -	UNSET_FLAG(bgp->flags, BGP_FLAG_SHOW_HOSTNAME); -	return CMD_SUCCESS; +	nb_cli_enqueue_change(vty, "./show-hostname", NB_OP_MODIFY, "false"); + +	return nb_cli_apply_changes(vty, NULL); +} + +void cli_show_router_bgp_show_hostname(struct vty *vty, struct lyd_node *dnode, +				       bool show_defaults) +{ +	if (yang_dnode_get_bool(dnode, NULL) != SAVE_BGP_SHOW_HOSTNAME) +		vty_out(vty, " bgp default show-hostname\n");  }  /* Display hostname in certain command outputs */ @@ -3321,9 +3458,10 @@ DEFUN (bgp_default_show_nexthop_hostname,         "Configure BGP defaults\n"         "Show hostname for nexthop in certain command outputs\n")  { -	VTY_DECLVAR_CONTEXT(bgp, bgp); -	SET_FLAG(bgp->flags, BGP_FLAG_SHOW_NEXTHOP_HOSTNAME); -	return CMD_SUCCESS; +	nb_cli_enqueue_change(vty, "./show-nexthop-hostname", NB_OP_MODIFY, +			      "true"); + +	return nb_cli_apply_changes(vty, NULL);  }  DEFUN (no_bgp_default_show_nexthop_hostname, @@ -3334,26 +3472,31 @@ DEFUN (no_bgp_default_show_nexthop_hostname,         "Configure BGP defaults\n"         "Show hostname for nexthop in certain command outputs\n")  { -	VTY_DECLVAR_CONTEXT(bgp, bgp); -	UNSET_FLAG(bgp->flags, BGP_FLAG_SHOW_NEXTHOP_HOSTNAME); -	return CMD_SUCCESS; +	nb_cli_enqueue_change(vty, "./show-nexthop-hostname", NB_OP_MODIFY, +			      "false"); + +	return nb_cli_apply_changes(vty, NULL); +} + +void cli_show_router_bgp_show_nexthop_hostname(struct vty *vty, +					       struct lyd_node *dnode, +					       bool show_defaults) +{ +	if (yang_dnode_get_bool(dnode, NULL) != SAVE_BGP_SHOW_HOSTNAME) +		vty_out(vty, " bgp default show-nexthop-hostname\n");  }  /* "bgp network import-check" configuration.  */ -DEFUN (bgp_network_import_check, -       bgp_network_import_check_cmd, -       "bgp network import-check", -       "BGP specific commands\n" -       "BGP network command\n" -       "Check BGP network route exists in IGP\n") +DEFUN_YANG(bgp_network_import_check, +	   bgp_network_import_check_cmd, +	   "bgp network import-check", +	   "BGP specific commands\n" +	   "BGP network command\n" +	   "Check BGP network route exists in IGP\n")  { -	VTY_DECLVAR_CONTEXT(bgp, bgp); -	if (!CHECK_FLAG(bgp->flags, BGP_FLAG_IMPORT_CHECK)) { -		SET_FLAG(bgp->flags, BGP_FLAG_IMPORT_CHECK); -		bgp_static_redo_import_check(bgp); -	} +	nb_cli_enqueue_change(vty, "./import-check", NB_OP_MODIFY, "true"); -	return CMD_SUCCESS; +	return nb_cli_apply_changes(vty, NULL);  }  ALIAS_HIDDEN(bgp_network_import_check, bgp_network_import_check_exact_cmd, @@ -3363,162 +3506,190 @@ ALIAS_HIDDEN(bgp_network_import_check, bgp_network_import_check_exact_cmd,  	     "Check BGP network route exists in IGP\n"  	     "Match route precisely\n") -DEFUN (no_bgp_network_import_check, -       no_bgp_network_import_check_cmd, -       "no bgp network import-check", -       NO_STR -       "BGP specific commands\n" -       "BGP network command\n" -       "Check BGP network route exists in IGP\n") +DEFUN_YANG(no_bgp_network_import_check, +	   no_bgp_network_import_check_cmd, +	   "no bgp network import-check", +	   NO_STR +	   "BGP specific commands\n" +	   "BGP network command\n" +	   "Check BGP network route exists in IGP\n")  { -	VTY_DECLVAR_CONTEXT(bgp, bgp); -	if (CHECK_FLAG(bgp->flags, BGP_FLAG_IMPORT_CHECK)) { -		UNSET_FLAG(bgp->flags, BGP_FLAG_IMPORT_CHECK); -		bgp_static_redo_import_check(bgp); -	} +	nb_cli_enqueue_change(vty, "./import-check", NB_OP_MODIFY, "false"); -	return CMD_SUCCESS; +	return nb_cli_apply_changes(vty, NULL);  } -DEFUN (bgp_default_local_preference, -       bgp_default_local_preference_cmd, -       "bgp default local-preference (0-4294967295)", -       "BGP specific commands\n" -       "Configure BGP defaults\n" -       "local preference (higher=more preferred)\n" -       "Configure default local preference value\n") +void cli_show_router_bgp_import_check(struct vty *vty, struct lyd_node *dnode, +				      bool show_defaults)  { -	VTY_DECLVAR_CONTEXT(bgp, bgp); -	int idx_number = 3; -	uint32_t local_pref; +	if (yang_dnode_get_bool(dnode, NULL) != SAVE_BGP_IMPORT_CHECK) +		vty_out(vty, " bgp network import-check\n"); +} -	local_pref = strtoul(argv[idx_number]->arg, NULL, 10); +DEFUN_YANG(bgp_default_local_preference, +	   bgp_default_local_preference_cmd, +	   "bgp default local-preference (0-4294967295)", +	   "BGP specific commands\n" +	   "Configure BGP defaults\n" +	   "local preference (higher=more preferred)\n" +	   "Configure default local preference value\n") +{ +	int idx_number = 3; -	bgp_default_local_preference_set(bgp, local_pref); -	bgp_clear_star_soft_in(vty, bgp->name); +	nb_cli_enqueue_change(vty, "./local-pref", NB_OP_MODIFY, +			      argv[idx_number]->arg); -	return CMD_SUCCESS; +	return nb_cli_apply_changes(vty, NULL);  } -DEFUN (no_bgp_default_local_preference, -       no_bgp_default_local_preference_cmd, -       "no bgp default local-preference [(0-4294967295)]", -       NO_STR -       "BGP specific commands\n" -       "Configure BGP defaults\n" -       "local preference (higher=more preferred)\n" -       "Configure default local preference value\n") +DEFUN_YANG(no_bgp_default_local_preference, +	   no_bgp_default_local_preference_cmd, +	   "no bgp default local-preference [(0-4294967295)]", +	   NO_STR +	   "BGP specific commands\n" +	   "Configure BGP defaults\n" +	   "local preference (higher=more preferred)\n" +	   "Configure default local preference value\n")  { -	VTY_DECLVAR_CONTEXT(bgp, bgp); -	bgp_default_local_preference_unset(bgp); -	bgp_clear_star_soft_in(vty, bgp->name); +	nb_cli_enqueue_change(vty, "./local-pref", NB_OP_MODIFY, NULL); -	return CMD_SUCCESS; +	return nb_cli_apply_changes(vty, NULL);  } +void cli_show_router_bgp_local_pref(struct vty *vty, struct lyd_node *dnode, +				    bool show_defaults) +{ +	vty_out(vty, " bgp default local-preference %u\n", +		yang_dnode_get_uint32(dnode, NULL)); +} -DEFUN (bgp_default_subgroup_pkt_queue_max, -       bgp_default_subgroup_pkt_queue_max_cmd, -       "bgp default subgroup-pkt-queue-max (20-100)", -       "BGP specific commands\n" -       "Configure BGP defaults\n" -       "subgroup-pkt-queue-max\n" -       "Configure subgroup packet queue max\n") + +DEFUN_YANG(bgp_default_subgroup_pkt_queue_max, +	   bgp_default_subgroup_pkt_queue_max_cmd, +	   "bgp default subgroup-pkt-queue-max (20-100)", +	   "BGP specific commands\n" +	   "Configure BGP defaults\n" +	   "subgroup-pkt-queue-max\n" +	   "Configure subgroup packet queue max\n")  { -	VTY_DECLVAR_CONTEXT(bgp, bgp);  	int idx_number = 3; -	uint32_t max_size; -	max_size = strtoul(argv[idx_number]->arg, NULL, 10); +	nb_cli_enqueue_change( +		vty, "./global-update-group-config/subgroup-pkt-queue-size", +		NB_OP_MODIFY, argv[idx_number]->arg); -	bgp_default_subgroup_pkt_queue_max_set(bgp, max_size); - -	return CMD_SUCCESS; +	return nb_cli_apply_changes(vty, NULL);  } -DEFUN (no_bgp_default_subgroup_pkt_queue_max, -       no_bgp_default_subgroup_pkt_queue_max_cmd, -       "no bgp default subgroup-pkt-queue-max [(20-100)]", -       NO_STR -       "BGP specific commands\n" -       "Configure BGP defaults\n" -       "subgroup-pkt-queue-max\n" -       "Configure subgroup packet queue max\n") +DEFUN_YANG(no_bgp_default_subgroup_pkt_queue_max, +	   no_bgp_default_subgroup_pkt_queue_max_cmd, +	   "no bgp default subgroup-pkt-queue-max [(20-100)]", +	   NO_STR +	   "BGP specific commands\n" +	   "Configure BGP defaults\n" +	   "subgroup-pkt-queue-max\n" +	   "Configure subgroup packet queue max\n")  { -	VTY_DECLVAR_CONTEXT(bgp, bgp); -	bgp_default_subgroup_pkt_queue_max_unset(bgp); -	return CMD_SUCCESS; +	nb_cli_enqueue_change( +		vty, "./global-update-group-config/subgroup-pkt-queue-size", +		NB_OP_MODIFY, NULL); + +	return nb_cli_apply_changes(vty, NULL);  } +void cli_show_router_global_update_group_config_subgroup_pkt_queue_size( +	struct vty *vty, struct lyd_node *dnode, bool show_defaults) +{ +	vty_out(vty, " bgp default subgroup-pkt-queue-max %u\n", +		yang_dnode_get_uint32(dnode, NULL)); +} -DEFUN (bgp_rr_allow_outbound_policy, -       bgp_rr_allow_outbound_policy_cmd, -       "bgp route-reflector allow-outbound-policy", -       "BGP specific commands\n" -       "Allow modifications made by out route-map\n" -       "on ibgp neighbors\n") +DEFUN_YANG(bgp_rr_allow_outbound_policy, +	   bgp_rr_allow_outbound_policy_cmd, +	   "bgp route-reflector allow-outbound-policy", +	   "BGP specific commands\n" +	   "Allow modifications made by out route-map\n" +	   "on ibgp neighbors\n")  { -	VTY_DECLVAR_CONTEXT(bgp, bgp); +	nb_cli_enqueue_change(vty, "./route-reflector/allow-outbound-policy", +			      NB_OP_MODIFY, "true"); -	if (!CHECK_FLAG(bgp->flags, BGP_FLAG_RR_ALLOW_OUTBOUND_POLICY)) { -		SET_FLAG(bgp->flags, BGP_FLAG_RR_ALLOW_OUTBOUND_POLICY); -		update_group_announce_rrclients(bgp); -		bgp_clear_star_soft_out(vty, bgp->name); -	} +	return nb_cli_apply_changes(vty, NULL); +} -	return CMD_SUCCESS; +DEFUN_YANG(no_bgp_rr_allow_outbound_policy, +	   no_bgp_rr_allow_outbound_policy_cmd, +	   "no bgp route-reflector allow-outbound-policy", +	   NO_STR +	   "BGP specific commands\n" +	   "Allow modifications made by out route-map\n" +	   "on ibgp neighbors\n") +{ +	nb_cli_enqueue_change(vty, "./route-reflector/allow-outbound-policy", +			      NB_OP_MODIFY, "false"); + +	return nb_cli_apply_changes(vty, NULL);  } -DEFUN (no_bgp_rr_allow_outbound_policy, -       no_bgp_rr_allow_outbound_policy_cmd, -       "no bgp route-reflector allow-outbound-policy", -       NO_STR -       "BGP specific commands\n" -       "Allow modifications made by out route-map\n" -       "on ibgp neighbors\n") + +void cli_show_router_global_neighbor_config(struct vty *vty, +					    struct lyd_node *dnode, +					    bool show_defaults)  { -	VTY_DECLVAR_CONTEXT(bgp, bgp); +	uint32_t write_quanta, read_quanta; + +	if (yang_dnode_get_bool(dnode, "./log-neighbor-changes")) +		vty_out(vty, " bgp log-neighbor-changes\n"); -	if (CHECK_FLAG(bgp->flags, BGP_FLAG_RR_ALLOW_OUTBOUND_POLICY)) { -		UNSET_FLAG(bgp->flags, BGP_FLAG_RR_ALLOW_OUTBOUND_POLICY); -		update_group_announce_rrclients(bgp); -		bgp_clear_star_soft_out(vty, bgp->name); +	if (yang_dnode_exists(dnode, "./dynamic-neighbors-limit")) { +		uint32_t listen_limit = yang_dnode_get_uint32( +			dnode, "./dynamic-neighbors-limit"); +		vty_out(vty, " bgp listen limit %u\n", listen_limit);  	} -	return CMD_SUCCESS; +	write_quanta = yang_dnode_get_uint32( +		dnode, "./packet-quanta-config/wpkt-quanta"); +	if (write_quanta != BGP_WRITE_PACKET_MAX) +		vty_out(vty, " write-quanta %d\n", write_quanta); + +	read_quanta = yang_dnode_get_uint32( +		dnode, "./packet-quanta-config/rpkt-quanta"); + +	if (read_quanta != BGP_READ_PACKET_MAX) +		vty_out(vty, " read-quanta %d\n", read_quanta);  } -DEFUN (bgp_listen_limit, -       bgp_listen_limit_cmd, -       "bgp listen limit (1-5000)", -       "BGP specific commands\n" -       "BGP Dynamic Neighbors listen commands\n" -       "Maximum number of BGP Dynamic Neighbors that can be created\n" -       "Configure Dynamic Neighbors listen limit value\n") +DEFUN_YANG(bgp_listen_limit, +	   bgp_listen_limit_cmd, +	   "bgp listen limit (1-5000)", +	   "BGP specific commands\n" +	   "BGP Dynamic Neighbors listen commands\n" +	   "Maximum number of BGP Dynamic Neighbors that can be created\n" +	   "Configure Dynamic Neighbors listen limit value\n")  { -	VTY_DECLVAR_CONTEXT(bgp, bgp);  	int idx_number = 3; -	int listen_limit; -	listen_limit = strtoul(argv[idx_number]->arg, NULL, 10); +	nb_cli_enqueue_change( +		vty, "./global-neighbor-config/dynamic-neighbors-limit", +		NB_OP_MODIFY, argv[idx_number]->arg); -	bgp_listen_limit_set(bgp, listen_limit); - -	return CMD_SUCCESS; +	return nb_cli_apply_changes(vty, NULL);  } -DEFUN (no_bgp_listen_limit, -       no_bgp_listen_limit_cmd, -       "no bgp listen limit [(1-5000)]", -       NO_STR -       "BGP specific commands\n" -       "BGP Dynamic Neighbors listen commands\n" -       "Maximum number of BGP Dynamic Neighbors that can be created\n" -       "Configure Dynamic Neighbors listen limit value\n") +DEFUN_YANG(no_bgp_listen_limit, +	   no_bgp_listen_limit_cmd, +	   "no bgp listen limit [(1-5000)]", +	   NO_STR +	   "BGP specific commands\n" +	   "BGP Dynamic Neighbors listen commands\n" +	   "Maximum number of BGP Dynamic Neighbors that can be created\n" +	   "Configure Dynamic Neighbors listen limit value\n")  { -	VTY_DECLVAR_CONTEXT(bgp, bgp); -	bgp_listen_limit_unset(bgp); -	return CMD_SUCCESS; +	nb_cli_enqueue_change( +		vty, "./global-neighbor-config/dynamic-neighbors-limit", +		NB_OP_DESTROY, NULL); + +	return nb_cli_apply_changes(vty, NULL);  } @@ -3700,33 +3871,37 @@ void bgp_config_write_listen(struct vty *vty, struct bgp *bgp)  } -DEFUN (bgp_disable_connected_route_check, -       bgp_disable_connected_route_check_cmd, -       "bgp disable-ebgp-connected-route-check", -       "BGP specific commands\n" -       "Disable checking if nexthop is connected on ebgp sessions\n") +DEFUN_YANG(bgp_disable_connected_route_check, +	   bgp_disable_connected_route_check_cmd, +	   "bgp disable-ebgp-connected-route-check", +	   "BGP specific commands\n" +	   "Disable checking if nexthop is connected on ebgp sessions\n")  { -	VTY_DECLVAR_CONTEXT(bgp, bgp); -	SET_FLAG(bgp->flags, BGP_FLAG_DISABLE_NH_CONNECTED_CHK); -	bgp_clear_star_soft_in(vty, bgp->name); +	nb_cli_enqueue_change(vty, "./ebgp-multihop-connected-route-check", +			      NB_OP_MODIFY, "true"); -	return CMD_SUCCESS; +	return nb_cli_apply_changes(vty, NULL);  } -DEFUN (no_bgp_disable_connected_route_check, -       no_bgp_disable_connected_route_check_cmd, -       "no bgp disable-ebgp-connected-route-check", -       NO_STR -       "BGP specific commands\n" -       "Disable checking if nexthop is connected on ebgp sessions\n") +DEFUN_YANG(no_bgp_disable_connected_route_check, +	   no_bgp_disable_connected_route_check_cmd, +	   "no bgp disable-ebgp-connected-route-check", +	   NO_STR +	   "BGP specific commands\n" +	   "Disable checking if nexthop is connected on ebgp sessions\n")  { -	VTY_DECLVAR_CONTEXT(bgp, bgp); -	UNSET_FLAG(bgp->flags, BGP_FLAG_DISABLE_NH_CONNECTED_CHK); -	bgp_clear_star_soft_in(vty, bgp->name); +	nb_cli_enqueue_change(vty, "./ebgp-multihop-connected-route-check", +			      NB_OP_MODIFY, "false"); -	return CMD_SUCCESS; +	return nb_cli_apply_changes(vty, NULL);  } +void cli_show_router_global_ebgp_multihop_connected_route_check( +	struct vty *vty, struct lyd_node *dnode, bool show_defaults) +{ +	if (yang_dnode_get_bool(dnode, NULL)) +		vty_out(vty, " bgp disable-ebgp-connected-route-check\n"); +}  static int peer_remote_as_vty(struct vty *vty, const char *peer_str,  			      const char *as_str, afi_t afi, safi_t safi) @@ -3792,17 +3967,25 @@ static int peer_remote_as_vty(struct vty *vty, const char *peer_str,  	return bgp_vty_return(vty, ret);  } -DEFUN (bgp_default_shutdown, -       bgp_default_shutdown_cmd, -       "[no] bgp default shutdown", -       NO_STR -       BGP_STR -       "Configure BGP defaults\n" -       "Apply administrative shutdown to newly configured peers\n") +DEFUN_YANG(bgp_default_shutdown, +	   bgp_default_shutdown_cmd, +	   "[no] bgp default shutdown", +	   NO_STR BGP_STR +	   "Configure BGP defaults\n" +	   "Apply administrative shutdown to newly configured peers\n")  { -	VTY_DECLVAR_CONTEXT(bgp, bgp); -	bgp->autoshutdown = !strmatch(argv[0]->text, "no"); -	return CMD_SUCCESS; +	nb_cli_enqueue_change(vty, "./default-shutdown", NB_OP_MODIFY, +			      strmatch(argv[0]->text, "no") ? "false" : "true"); + +	return nb_cli_apply_changes(vty, NULL); +} + +void cli_show_router_bgp_default_shutdown(struct vty *vty, +					  struct lyd_node *dnode, +					  bool show_defaults) +{ +	if (yang_dnode_get_bool(dnode, NULL)) +		vty_out(vty, " bgp default shutdown\n");  }  DEFPY(bgp_shutdown_msg, bgp_shutdown_msg_cmd, "bgp shutdown message MSG...", @@ -8603,6 +8786,8 @@ DEFUN (clear_ip_bgp_all,  	char *clr_arg = NULL;  	int idx = 0; +	char errmsg[BUFSIZ] = {'\0'}; +	int ret;  	/* clear [ip] bgp */  	if (argv_find(argv, argc, "ip", &idx)) @@ -8667,7 +8852,12 @@ DEFUN (clear_ip_bgp_all,  	} else  		clr_type = BGP_CLEAR_SOFT_NONE; -	return bgp_clear_vty(vty, vrf, afi, safi, clr_sort, clr_type, clr_arg); +	ret = bgp_clear_vty(vrf, afi, safi, clr_sort, clr_type, clr_arg, errmsg, +			    sizeof(errmsg)); +	if (ret != NB_OK) +		vty_out(vty, "Error description: %s\n", errmsg); + +	return ret;  }  DEFUN (clear_ip_bgp_prefix, diff --git a/bgpd/bgp_vty.h b/bgpd/bgp_vty.h index 95eefbc36f..a9e86ec09a 100644 --- a/bgpd/bgp_vty.h +++ b/bgpd/bgp_vty.h @@ -180,5 +180,12 @@ int bgp_vty_find_and_parse_bgp(struct vty *vty, struct cmd_token **argv,  extern int bgp_show_summary_vty(struct vty *vty, const char *name, afi_t afi,  				safi_t safi, bool show_failed,  				bool show_established, bool use_json); +extern int bgp_clear_star_soft_in(const char *name, char *errmsg, +				  size_t errmsg_len); +extern int bgp_clear_star_soft_out(const char *name, char *errmsg, +				   size_t errmsg_len); +int bgp_wpkt_quanta_config_vty(struct bgp *bgp, uint32_t quanta, bool set); +int bgp_rpkt_quanta_config_vty(struct bgp *bgp, uint32_t quanta, bool set); +  #endif /* _QUAGGA_BGP_VTY_H */ diff --git a/bgpd/bgpd.c b/bgpd/bgpd.c index 4260970541..30566b2c16 100644 --- a/bgpd/bgpd.c +++ b/bgpd/bgpd.c @@ -397,10 +397,6 @@ int bgp_cluster_id_set(struct bgp *bgp, struct in_addr *cluster_id)  	struct peer *peer;  	struct listnode *node, *nnode; -	if (bgp_config_check(bgp, BGP_CONFIG_CLUSTER_ID) -	    && IPV4_ADDR_SAME(&bgp->cluster_id, cluster_id)) -		return 0; -  	IPV4_ADDR_COPY(&bgp->cluster_id, cluster_id);  	bgp_config_set(bgp, BGP_CONFIG_CLUSTER_ID); @@ -473,14 +469,14 @@ void bgp_timers_unset(struct bgp *bgp)  }  /* BGP confederation configuration.  */ -int bgp_confederation_id_set(struct bgp *bgp, as_t as) +void bgp_confederation_id_set(struct bgp *bgp, as_t as)  {  	struct peer *peer;  	struct listnode *node, *nnode;  	int already_confed;  	if (as == 0) -		return BGP_ERR_INVALID_AS; +		return;  	/* Remember - were we doing confederation before? */  	already_confed = bgp_config_check(bgp, BGP_CONFIG_CONFEDERATION); @@ -528,7 +524,7 @@ int bgp_confederation_id_set(struct bgp *bgp, as_t as)  			}  		}  	} -	return 0; +	return;  }  int bgp_confederation_id_unset(struct bgp *bgp) diff --git a/bgpd/bgpd.h b/bgpd/bgpd.h index 9f72a3e19e..3e3c6fc9e3 100644 --- a/bgpd/bgpd.h +++ b/bgpd/bgpd.h @@ -391,8 +391,9 @@ struct bgp {  		*t_maxmed_onstartup; /* non-null when max-med onstartup is on */  	uint8_t maxmed_onstartup_over; /* Flag to make it effective only once */ -	uint8_t v_maxmed_admin; /* 1/0 if max-med administrative is on/off */ -#define BGP_MAXMED_ADMIN_UNCONFIGURED  0 /* Off by default */ +	bool v_maxmed_admin; /* true/false if max-med administrative is on/off +			      */ +#define BGP_MAXMED_ADMIN_UNCONFIGURED false /* Off by default */  	uint32_t maxmed_admin_value; /* Max-med value when administrative in on  				      */  #define BGP_MAXMED_VALUE_DEFAULT  4294967294 /* Maximum by default */ @@ -1827,7 +1828,7 @@ extern void bgp_router_id_static_set(struct bgp *, struct in_addr);  extern int bgp_cluster_id_set(struct bgp *, struct in_addr *);  extern int bgp_cluster_id_unset(struct bgp *); -extern int bgp_confederation_id_set(struct bgp *, as_t); +extern void bgp_confederation_id_set(struct bgp *, as_t);  extern int bgp_confederation_id_unset(struct bgp *);  extern bool bgp_confederation_peers_check(struct bgp *, as_t); diff --git a/yang/frr-bgp-common.yang b/yang/frr-bgp-common.yang index 96ec9dc969..f02d28800e 100644 --- a/yang/frr-bgp-common.yang +++ b/yang/frr-bgp-common.yang @@ -195,7 +195,7 @@ submodule frr-bgp-common {        leaf external-compare-router-id {          type boolean; -        default "true"; +        default "false";          description            "When comparing similar routes received from external BGP             peers, use the router-id as a criterion to select the  | 
