From 2e42ea81ad623c7a7978966587acb8dab4287565 Mon Sep 17 00:00:00 2001 From: Nischal Sheth Date: Mon, 9 Nov 2015 18:01:01 -0800 Subject: [PATCH] Add admin_down configuration for bgp router and neighbor Highlights: - Add admin-down to BgpRouterParams and BgpSessionAttributes in schema - BgpPeer is admin down if it's configured to be admin down - BgpPeer is admin down if local or remote bgp-router is admin down - Add admin down state to BgpServer - Reuse existing admin down functionality in BgpPeer and StateMachine - Include admin down in introspect, tracing, logging and UVEs - Don't publish to discovery is the bgp-router is admin down - Bring down all xmpp connections if bgp-router is admin down - Don't accept xmpp connections if bgp-router is admin down - Add tests to exercise the new code Change-Id: I2eae401902f1af6132ddddd28605482eef29de21 Closes-Bug: 1514670 --- src/bgp/bgp_config.cc | 5 + src/bgp/bgp_config.h | 11 +- src/bgp/bgp_config_ifmap.cc | 15 + src/bgp/bgp_config_ifmap.h | 1 + src/bgp/bgp_log.sandesh | 16 + src/bgp/bgp_peer.cc | 16 +- src/bgp/bgp_peer.sandesh | 5 +- src/bgp/bgp_sandesh.cc | 1 + src/bgp/bgp_server.cc | 70 ++- src/bgp/bgp_server.h | 9 + src/bgp/bgp_session_manager.cc | 8 + src/bgp/bgp_xmpp_channel.cc | 15 + src/bgp/bgp_xmpp_channel.h | 2 + src/bgp/test/bgp_server_test.cc | 437 +++++++++++++++++- src/bgp/test/bgp_xmpp_basic_test.cc | 101 ++++ src/control-node/main.cc | 14 + src/control-node/sandesh/control_node.sandesh | 1 + src/schema/bgp_schema.xsd | 2 + 18 files changed, 720 insertions(+), 9 deletions(-) diff --git a/src/bgp/bgp_config.cc b/src/bgp/bgp_config.cc index dbb78809aa3..a009fc8c352 100644 --- a/src/bgp/bgp_config.cc +++ b/src/bgp/bgp_config.cc @@ -138,6 +138,7 @@ std::vector AuthenticationData::KeysToStringDetail() const { BgpNeighborConfig::BgpNeighborConfig() : type_(UNSPECIFIED), + admin_down_(false), peer_as_(0), identifier_(0), port_(BgpConfigManager::kDefaultPort), @@ -151,6 +152,7 @@ void BgpNeighborConfig::CopyValues(const BgpNeighborConfig &rhs) { instance_name_ = rhs.instance_name_; group_name_ = rhs.group_name_; type_ = rhs.type_; + admin_down_ = rhs.admin_down_; peer_as_ = rhs.peer_as_; identifier_ = rhs.identifier_; address_ = rhs.address_; @@ -167,6 +169,7 @@ int BgpNeighborConfig::CompareTo(const BgpNeighborConfig &rhs) const { KEY_COMPARE(uuid_, rhs.uuid_); KEY_COMPARE(instance_name_, rhs.instance_name_); KEY_COMPARE(type_, rhs.type_); + KEY_COMPARE(admin_down_, rhs.admin_down_); KEY_COMPARE(peer_as_, rhs.peer_as_); KEY_COMPARE(identifier_, rhs.identifier_); KEY_COMPARE(address_, rhs.address_); @@ -202,6 +205,7 @@ std::vector BgpNeighborConfig::AuthKeysToString() const { BgpProtocolConfig::BgpProtocolConfig(const std::string &instance_name) : instance_name_(instance_name), + admin_down_(false), autonomous_system_(0), local_autonomous_system_(0), identifier_(0), @@ -212,6 +216,7 @@ BgpProtocolConfig::BgpProtocolConfig(const std::string &instance_name) int BgpProtocolConfig::CompareTo(const BgpProtocolConfig &rhs) const { KEY_COMPARE(instance_name_, rhs.instance_name_); + KEY_COMPARE(admin_down_, rhs.admin_down_); KEY_COMPARE(autonomous_system_, rhs.autonomous_system_); KEY_COMPARE(identifier_, rhs.identifier_); KEY_COMPARE(port_, rhs.port_); diff --git a/src/bgp/bgp_config.h b/src/bgp/bgp_config.h index 2fb11ac69f5..71d3c2a6511 100644 --- a/src/bgp/bgp_config.h +++ b/src/bgp/bgp_config.h @@ -159,7 +159,10 @@ class BgpNeighborConfig { Type peer_type() const { return type_; } void set_peer_type(Type type) { type_ = type; } - + + bool admin_down() const { return admin_down_; } + void set_admin_down(bool admin_down) { admin_down_ = admin_down; } + uint32_t peer_as() const { return peer_as_; } void set_peer_as(uint32_t peer_as) { peer_as_ = peer_as; } @@ -220,6 +223,7 @@ class BgpNeighborConfig { std::string instance_name_; std::string group_name_; Type type_; + bool admin_down_; uint32_t peer_as_; uint32_t identifier_; IpAddress address_; @@ -339,8 +343,12 @@ class BgpProtocolConfig { int CompareTo(const BgpProtocolConfig &rhs) const; + bool admin_down() const { return admin_down_; } + void set_admin_down(bool admin_down) { admin_down_ = admin_down; } + uint32_t identifier() const { return identifier_; } void set_identifier(uint32_t identifier) { identifier_ = identifier; } + uint32_t autonomous_system() const { return autonomous_system_; } void set_autonomous_system(uint32_t autonomous_system) { autonomous_system_ = autonomous_system; @@ -364,6 +372,7 @@ class BgpProtocolConfig { private: std::string instance_name_; + bool admin_down_; uint32_t autonomous_system_; uint32_t local_autonomous_system_; uint32_t identifier_; diff --git a/src/bgp/bgp_config_ifmap.cc b/src/bgp/bgp_config_ifmap.cc index 990f060dece..1db85a7263f 100644 --- a/src/bgp/bgp_config_ifmap.cc +++ b/src/bgp/bgp_config_ifmap.cc @@ -168,6 +168,9 @@ static void NeighborSetSessionAttributes( attributes = local; } if (attributes != NULL) { + if (attributes->admin_down) { + neighbor->set_admin_down(true); + } if (attributes->hold_time) { neighbor->set_hold_time(attributes->hold_time); } @@ -199,6 +202,9 @@ static BgpNeighborConfig *MakeBgpNeighborConfig( // Store a copy of the remote bgp-router's autogen::BgpRouterParams and // derive the autogen::BgpSessionAttributes for the session. const autogen::BgpRouterParams ¶ms = remote_router->parameters(); + if (params.admin_down) { + neighbor->set_admin_down(true); + } if (params.local_autonomous_system) { neighbor->set_peer_as(params.local_autonomous_system); } else { @@ -232,6 +238,9 @@ static BgpNeighborConfig *MakeBgpNeighborConfig( const BgpIfmapProtocolConfig *protocol = instance->protocol_config(); if (protocol && protocol->bgp_router()) { const autogen::BgpRouterParams ¶ms = protocol->router_params(); + if (params.admin_down) { + neighbor->set_admin_down(true); + } Ip4Address localid = Ip4Address::from_string(params.identifier, err); if (err == 0) { neighbor->set_local_identifier(IpAddressToBgpIdentifier(localid)); @@ -464,6 +473,7 @@ void BgpIfmapProtocolConfig::Update(BgpIfmapConfigManager *manager, const autogen::BgpRouter *router) { bgp_router_.reset(router); const autogen::BgpRouterParams ¶ms = router->parameters(); + data_.set_admin_down(params.admin_down); data_.set_autonomous_system(params.autonomous_system); data_.set_local_autonomous_system(params.local_autonomous_system); boost::system::error_code err; @@ -793,6 +803,7 @@ void BgpIfmapInstanceConfig::AddNeighbor(BgpConfigManager *manager, BGP_CONFIG_LOG_NEIGHBOR( Create, manager->server(), neighbor, SandeshLevel::SYS_DEBUG, BGP_LOG_FLAG_ALL, + neighbor->admin_down(), BgpIdentifierToString(neighbor->local_identifier()), neighbor->local_as(), neighbor->peer_address().to_string(), neighbor->peer_as(), @@ -814,6 +825,7 @@ void BgpIfmapInstanceConfig::ChangeNeighbor(BgpConfigManager *manager, BGP_CONFIG_LOG_NEIGHBOR( Update, manager->server(), neighbor, SandeshLevel::SYS_DEBUG, BGP_LOG_FLAG_ALL, + neighbor->admin_down(), BgpIdentifierToString(neighbor->local_identifier()), neighbor->local_as(), neighbor->peer_address().to_string(), neighbor->peer_as(), @@ -1147,6 +1159,7 @@ void BgpIfmapConfigManager::DefaultConfig() { BGP_CONFIG_LOG_PROTOCOL( Create, server(), protocol, SandeshLevel::SYS_DEBUG, BGP_LOG_FLAG_ALL, + protocol->router_params().admin_down, protocol->router_params().autonomous_system, protocol->router_params().identifier, protocol->router_params().address, @@ -1340,6 +1353,7 @@ void BgpIfmapConfigManager::ProcessBgpProtocol(const BgpConfigDelta &delta) { if (event == BgpConfigManager::CFG_ADD) { BGP_CONFIG_LOG_PROTOCOL(Create, server(), protocol, SandeshLevel::SYS_DEBUG, BGP_LOG_FLAG_ALL, + protocol->router_params().admin_down, protocol->router_params().autonomous_system, protocol->router_params().identifier, protocol->router_params().address, @@ -1348,6 +1362,7 @@ void BgpIfmapConfigManager::ProcessBgpProtocol(const BgpConfigDelta &delta) { } else { BGP_CONFIG_LOG_PROTOCOL(Update, server(), protocol, SandeshLevel::SYS_DEBUG, BGP_LOG_FLAG_ALL, + protocol->router_params().admin_down, protocol->router_params().autonomous_system, protocol->router_params().identifier, protocol->router_params().address, diff --git a/src/bgp/bgp_config_ifmap.h b/src/bgp/bgp_config_ifmap.h index 36f77f6441f..90bf954d28a 100644 --- a/src/bgp/bgp_config_ifmap.h +++ b/src/bgp/bgp_config_ifmap.h @@ -134,6 +134,7 @@ class BgpIfmapProtocolConfig { const BgpIfmapInstanceConfig *instance() { return instance_; } const BgpProtocolConfig *protocol_config() const { return &data_; } + private: BgpIfmapInstanceConfig *instance_; IFMapNodeProxy node_proxy_; diff --git a/src/bgp/bgp_log.sandesh b/src/bgp/bgp_log.sandesh index 4d5190c0f72..8c9656625ab 100644 --- a/src/bgp/bgp_log.sandesh +++ b/src/bgp/bgp_log.sandesh @@ -121,6 +121,8 @@ systemlog sandesh BgpConfigInstanceUpdateLog { trace sandesh BgpConfigNeighborCreateTrace { 1: "Neighbor"; 2: string name; + 16: "AdminDown"; + 17: bool admin_down; 9: "Local Identifier"; 10: string local_identifier; 11: "Local AS"; @@ -139,6 +141,8 @@ trace sandesh BgpConfigNeighborCreateTrace { systemlog sandesh BgpConfigNeighborCreateLog { 1: "Neighbor"; 2: string name; + 16: "AdminDown"; + 17: bool admin_down; 9: "Local Identifier"; 10: string local_identifier; 11: "Local AS"; @@ -167,6 +171,8 @@ systemlog sandesh BgpConfigNeighborDeleteLog { trace sandesh BgpConfigNeighborUpdateTrace { 1: "Neighbor"; 2: string name; + 16: "AdminDown"; + 17: bool admin_down; 9: "Local Identifier"; 10: string local_identifier; 11: "Local AS"; @@ -185,6 +191,8 @@ trace sandesh BgpConfigNeighborUpdateTrace { systemlog sandesh BgpConfigNeighborUpdateLog { 1: "Neighbor"; 2: string name; + 16: "AdminDown"; + 17: bool admin_down; 9: "Local Identifier"; 10: string local_identifier; 11: "Local AS"; @@ -233,6 +241,8 @@ systemlog sandesh BgpConfigPeeringUpdateLog { trace sandesh BgpConfigProtocolCreateTrace { 1: "Routing Instance"; 2: string name; + 13: "AdminDown"; + 14: bool admin_down; 3: "Local AS"; 4: i32 as_number; 5: "Router ID"; @@ -248,6 +258,8 @@ trace sandesh BgpConfigProtocolCreateTrace { systemlog sandesh BgpConfigProtocolCreateLog { 1: "Routing Instance"; 2: string name; + 13: "AdminDown"; + 14: bool admin_down; 3: "Local AS"; 4: i32 as_number; 5: "Router ID"; @@ -273,6 +285,8 @@ systemlog sandesh BgpConfigProtocolDeleteLog { trace sandesh BgpConfigProtocolUpdateTrace { 1: "Routing Instance"; 2: string name; + 13: "AdminDown"; + 14: bool admin_down; 3: "Local AS"; 4: i32 as_number; 5: "Router ID"; @@ -288,6 +302,8 @@ trace sandesh BgpConfigProtocolUpdateTrace { systemlog sandesh BgpConfigProtocolUpdateLog { 1: "Routing Instance"; 2: string name; + 13: "AdminDown"; + 14: bool admin_down; 3: "Local AS"; 4: i32 as_number; 5: "Router ID"; diff --git a/src/bgp/bgp_peer.cc b/src/bgp/bgp_peer.cc index afcd56dc721..d935021bd7c 100644 --- a/src/bgp/bgp_peer.cc +++ b/src/bgp/bgp_peer.cc @@ -352,7 +352,7 @@ BgpPeer::BgpPeer(BgpServer *server, RoutingInstance *instance, TaskScheduler::GetInstance()->GetTaskId("bgp::StateMachine"), GetIndex())), send_ready_(true), - admin_down_(false), + admin_down_(config->admin_down()), state_machine_(BgpObjectFactory::Create(this)), membership_req_pending_(0), defer_close_(false), @@ -390,8 +390,9 @@ BgpPeer::BgpPeer(BgpServer *server, RoutingInstance *instance, BgpPeerInfoData peer_info; peer_info.set_name(ToUVEKey()); - peer_info.set_peer_type(PeerType() == BgpProto::IBGP ? - "internal" : "external"); + peer_info.set_admin_down(admin_down_); + peer_info.set_peer_type( + PeerType() == BgpProto::IBGP ? "internal" : "external"); peer_info.set_local_asn(local_as_); peer_info.set_peer_asn(peer_as_); peer_info.set_local_id(local_bgp_id_); @@ -413,7 +414,8 @@ BgpPeer::~BgpPeer() { } void BgpPeer::Initialize() { - state_machine_->Initialize(); + if (!admin_down_) + state_machine_->Initialize(); } void BgpPeer::BindLocalEndpoint(BgpSession *session) { @@ -553,6 +555,11 @@ void BgpPeer::ConfigUpdate(const BgpNeighborConfig *config) { BgpPeerInfoData peer_info; peer_info.set_name(ToUVEKey()); + if (admin_down_ != config->admin_down()) { + SetAdminState(config->admin_down()); + peer_info.set_admin_down(admin_down_); + } + // Check if there is any change in the peer address. // If the peer address is changing, remove the key for the older address. // Update with the new peer address and then process the key chain info @@ -1579,6 +1586,7 @@ void BgpPeer::FillNeighborInfo(const BgpSandeshContext *bsc, nbr.set_peer(peer_basename_); nbr.set_deleted(IsDeleted()); nbr.set_deleted_at(UTCUsecToString(deleter_->delete_time_stamp_usecs())); + nbr.set_admin_down(admin_down_); nbr.set_peer_address(peer_key_.endpoint.address().to_string()); nbr.set_peer_id(bgp_identifier_string()); nbr.set_peer_asn(peer_as()); diff --git a/src/bgp/bgp_peer.sandesh b/src/bgp/bgp_peer.sandesh index 6ca9a59ef01..6949d2b1ff4 100644 --- a/src/bgp/bgp_peer.sandesh +++ b/src/bgp/bgp_peer.sandesh @@ -43,6 +43,7 @@ struct BgpNeighborResp { 1: string peer (link="BgpNeighborReq"); // Peer name 36: bool deleted; // Deletion in progress 43: string deleted_at; + 47: bool admin_down; 2: string peer_address (link="BgpNeighborReq"); 25: string peer_id; 3: u32 peer_asn; @@ -434,6 +435,7 @@ struct ShowBgpPeeringConfig { struct ShowBgpNeighborConfig { 1: string instance_name; 2: string name; + 13: bool admin_down; 8: string local_identifier; 9: i32 local_as; 3: string vendor; @@ -456,7 +458,8 @@ request sandesh ShowBgpNeighborConfigReq { struct BgpPeerInfoData { 1: string name (key="ObjectBgpPeer"); // RoutingInstance:RemoteEnd:LocalEnd - 2: optional bool deleted + 2: optional bool deleted + 23: optional bool admin_down 3: optional string peer_type; // internal/external 20: optional string peer_address; 4: optional u32 local_asn; diff --git a/src/bgp/bgp_sandesh.cc b/src/bgp/bgp_sandesh.cc index 5d31bbbbc0f..d47328c111a 100644 --- a/src/bgp/bgp_sandesh.cc +++ b/src/bgp/bgp_sandesh.cc @@ -455,6 +455,7 @@ class ShowBgpNeighborConfigHandler { ShowBgpNeighborConfig nbr; nbr.set_instance_name(neighbor->instance_name()); nbr.set_name(neighbor->name()); + nbr.set_admin_down(neighbor->admin_down()); Ip4Address localid(ntohl(neighbor->local_identifier())); nbr.set_local_identifier(localid.to_string()); nbr.set_local_as(neighbor->local_as()); diff --git a/src/bgp/bgp_server.cc b/src/bgp/bgp_server.cc index 4fb60f4d28a..a6a074615d7 100644 --- a/src/bgp/bgp_server.cc +++ b/src/bgp/bgp_server.cc @@ -22,6 +22,8 @@ using boost::system::error_code; using process::ConnectionState; +using std::boolalpha; +using std::noboolalpha; using std::string; // The ConfigUpdater serves as glue between the BgpConfigManager and the @@ -66,13 +68,32 @@ class BgpServer::ConfigUpdater { uint32_t config_autonomous_system = 0; uint32_t config_local_autonomous_system = 0; uint16_t config_hold_time = 0; + bool config_admin_down = false; if (config) { + config_admin_down = config->admin_down(); config_identifier = config->identifier(); config_autonomous_system = config->autonomous_system(); config_local_autonomous_system = config->local_autonomous_system(); config_hold_time = config->hold_time(); } + if (server_->admin_down_ != config_admin_down) { + SandeshLevel::type log_level; + if (server_->admin_down_) { + log_level = SandeshLevel::SYS_DEBUG; + } else { + log_level = SandeshLevel::SYS_NOTICE; + } + BGP_LOG_STR(BgpConfig, log_level, BGP_LOG_FLAG_SYSLOG, + "Updated Admin Down from " << + boolalpha << server_->admin_down_ << noboolalpha << + " to " << + boolalpha << config_admin_down << noboolalpha); + server_->admin_down_ = config_admin_down; + if (server_->admin_down_) + server_->NotifyAdminDown(); + } + Ip4Address identifier(ntohl(config_identifier)); if (server_->bgp_identifier_ != identifier) { SandeshLevel::type log_level; @@ -240,7 +261,8 @@ bool BgpServer::IsReadyForDeletion() { } BgpServer::BgpServer(EventManager *evm) - : autonomous_system_(0), + : admin_down_(false), + autonomous_system_(0), local_autonomous_system_(0), bgp_identifier_(0), hold_time_(0), @@ -419,6 +441,52 @@ void BgpServer::VisitBgpPeers(BgpServer::VisitorFn fn) const { } } +int BgpServer::RegisterAdminDownCallback(AdminDownCb callback) { + tbb::spin_rw_mutex::scoped_lock write_lock(rw_mutex_, true); + size_t i = admin_down_bmap_.find_first(); + if (i == admin_down_bmap_.npos) { + i = admin_down_listeners_.size(); + admin_down_listeners_.push_back(callback); + } else { + admin_down_bmap_.reset(i); + if (admin_down_bmap_.none()) { + admin_down_bmap_.clear(); + } + admin_down_listeners_[i] = callback; + } + return i; +} + +void BgpServer::UnregisterAdminDownCallback(int listener) { + tbb::spin_rw_mutex::scoped_lock write_lock(rw_mutex_, true); + admin_down_listeners_[listener] = NULL; + if ((size_t) listener == admin_down_listeners_.size() - 1) { + while (!admin_down_listeners_.empty() && + admin_down_listeners_.back() == NULL) { + admin_down_listeners_.pop_back(); + } + if (admin_down_bmap_.size() > admin_down_listeners_.size()) { + admin_down_bmap_.resize(admin_down_listeners_.size()); + } + } else { + if ((size_t) listener >= admin_down_bmap_.size()) { + admin_down_bmap_.resize(listener + 1); + } + admin_down_bmap_.set(listener); + } +} + +void BgpServer::NotifyAdminDown() { + tbb::spin_rw_mutex::scoped_lock read_lock(rw_mutex_, false); + for (AdminDownListenersList::iterator iter = admin_down_listeners_.begin(); + iter != admin_down_listeners_.end(); ++iter) { + if (*iter != NULL) { + AdminDownCb cb = *iter; + (cb)(); + } + } +} + int BgpServer::RegisterASNUpdateCallback(ASNUpdateCb callback) { tbb::spin_rw_mutex::scoped_lock write_lock(rw_mutex_, true); size_t i = asn_bmap_.find_first(); diff --git a/src/bgp/bgp_server.h b/src/bgp/bgp_server.h index 0f6a40f957e..193c05ca435 100644 --- a/src/bgp/bgp_server.h +++ b/src/bgp/bgp_server.h @@ -46,6 +46,7 @@ class SchedulingGroupManager; class BgpServer { public: + typedef boost::function AdminDownCb; typedef boost::function ASNUpdateCb; typedef boost::function IdentifierUpdateCb; typedef boost::function VisitorFn; @@ -134,6 +135,7 @@ class BgpServer { DB *database() { return &db_; } const std::string &localname() const; + bool admin_down() const { return admin_down_; } as_t autonomous_system() const { return autonomous_system_; } as_t local_autonomous_system() const { return local_autonomous_system_; } uint32_t bgp_identifier() const { return bgp_identifier_.to_ulong(); } @@ -177,6 +179,9 @@ class BgpServer { void increment_message_build_error() const { ++message_build_error_; } uint64_t message_build_error() const { return message_build_error_; } + int RegisterAdminDownCallback(AdminDownCb callback); + void UnregisterAdminDownCallback(int listener); + void NotifyAdminDown(); int RegisterASNUpdateCallback(ASNUpdateCb callback); void UnregisterASNUpdateCallback(int listener); void NotifyASNUpdate(as_t old_asn, as_t old_local_asn); @@ -196,6 +201,7 @@ class BgpServer { friend class BgpServerTest; friend class BgpServerUnitTest; typedef std::map BgpPeerList; + typedef std::vector AdminDownListenersList; typedef std::vector ASNUpdateListenersList; typedef std::vector IdentifierUpdateListenersList; @@ -203,6 +209,9 @@ class BgpServer { // base config variables tbb::spin_rw_mutex rw_mutex_; + bool admin_down_; + AdminDownListenersList admin_down_listeners_; + boost::dynamic_bitset<> admin_down_bmap_; // free list. as_t autonomous_system_; as_t local_autonomous_system_; ASNUpdateListenersList asn_listeners_; diff --git a/src/bgp/bgp_session_manager.cc b/src/bgp/bgp_session_manager.cc index bcc2770b92e..f2d8dfb25f3 100644 --- a/src/bgp/bgp_session_manager.cc +++ b/src/bgp/bgp_session_manager.cc @@ -170,6 +170,14 @@ bool BgpSessionManager::ProcessSession(BgpSession *session) { return true; } + // Ignore if this server is being held administratively down. + if (server_->admin_down()) { + session->SendNotification(BgpProto::Notification::Cease, + BgpProto::Notification::AdminShutdown); + DeleteSession(session); + return true; + } + // Ignore if this peer is not configured or is being deleted. if (peer == NULL || peer->deleter()->IsDeleted()) { session->SendNotification(BgpProto::Notification::Cease, diff --git a/src/bgp/bgp_xmpp_channel.cc b/src/bgp/bgp_xmpp_channel.cc index 9db5a52041f..7dd2eaf740d 100644 --- a/src/bgp/bgp_xmpp_channel.cc +++ b/src/bgp/bgp_xmpp_channel.cc @@ -2262,6 +2262,9 @@ BgpXmppChannelManager::BgpXmppChannelManager(XmppServer *xmpp_server, boost::bind(&BgpXmppChannelManager::XmppHandleChannelEvent, this, _1, _2)); } + admin_down_listener_id_ = + server->RegisterAdminDownCallback(boost::bind( + &BgpXmppChannelManager::AdminDownCallback, this)); asn_listener_id_ = server->RegisterASNUpdateCallback(boost::bind( &BgpXmppChannelManager::ASNUpdateCallback, this, _1, _2)); @@ -2283,6 +2286,7 @@ BgpXmppChannelManager::~BgpXmppChannelManager() { } queue_.Shutdown(); + bgp_server_->UnregisterAdminDownCallback(admin_down_listener_id_); bgp_server_->UnregisterASNUpdateCallback(asn_listener_id_); bgp_server_->routing_instance_mgr()->UnregisterInstanceOpCallback(id_); } @@ -2299,6 +2303,10 @@ size_t BgpXmppChannelManager::GetQueueSize() const { return queue_.Length(); } +void BgpXmppChannelManager::AdminDownCallback() { + xmpp_server_->ClearAllConnections(); +} + void BgpXmppChannelManager::ASNUpdateCallback(as_t old_asn, as_t old_local_asn) { BOOST_FOREACH(XmppChannelMap::value_type &i, channel_map_) { @@ -2378,6 +2386,13 @@ void BgpXmppChannelManager::XmppHandleChannelEvent(XmppChannel *channel, "No BGP configuration for self - closing channel"); channel->Close(); } + if (bgp_server_->admin_down()) { + BGP_LOG_PEER(Message, bgp_xmpp_channel->Peer(), + SandeshLevel::SYS_INFO, BGP_LOG_FLAG_SYSLOG, + BGP_PEER_DIR_IN, + "BGP is administratively down - closing channel"); + channel->Close(); + } } else { bgp_xmpp_channel = (*it).second; bgp_xmpp_channel->peer_->SetDeleted(false); diff --git a/src/bgp/bgp_xmpp_channel.h b/src/bgp/bgp_xmpp_channel.h index e3d793b3b6a..272b326532a 100644 --- a/src/bgp/bgp_xmpp_channel.h +++ b/src/bgp/bgp_xmpp_channel.h @@ -282,6 +282,7 @@ class BgpXmppChannelManager { void SetQueueDisable(bool disabled); size_t GetQueueSize() const; void RoutingInstanceCallback(std::string vrf_name, int op); + void AdminDownCallback(); void ASNUpdateCallback(as_t old_asn, as_t old_local_asn); void IdentifierUpdateCallback(Ip4Address old_identifier); @@ -312,6 +313,7 @@ class BgpXmppChannelManager { XmppChannelMap channel_map_; XmppChannelNameMap channel_name_map_; int id_; + int admin_down_listener_id_; int asn_listener_id_; int identifier_listener_id_; uint32_t closing_count_; diff --git a/src/bgp/test/bgp_server_test.cc b/src/bgp/test/bgp_server_test.cc index 12f0a5afa0b..868832ae4b1 100644 --- a/src/bgp/test/bgp_server_test.cc +++ b/src/bgp/test/bgp_server_test.cc @@ -149,6 +149,12 @@ class BgpServerUnitTest : public ::testing::Test { session_manager->SetSessionQueueDisable(flag); } + void SetupPeers(int peer_count, unsigned short port_a, + unsigned short port_b, bool verify_keepalives, + bool admin_down1, bool admin_down2, + bool nbr_admin_down1, bool nbr_admin_down2, + uint16_t as_num1, uint16_t as_num2, + uint16_t local_as_num1, uint16_t local_as_num2); void SetupPeers(int peer_count, unsigned short port_a, unsigned short port_b, bool verify_keepalives, uint16_t as_num1 = BgpConfigManager::kDefaultAutonomousSystem, @@ -212,6 +218,8 @@ class BgpServerUnitTest : public ::testing::Test { uint16_t local_as_num2 = BgpConfigManager::kDefaultAutonomousSystem); string GetConfigStr(int peer_count, unsigned short port_a, unsigned short port_b, + bool admin_down1, bool admin_down2, + bool nbr_admin_down1, bool nbr_admin_down2, uint16_t as_num1, uint16_t as_num2, uint16_t local_as_num1, uint16_t local_as_num2, string peer_address1, string peer_address2, @@ -263,6 +271,8 @@ void BgpServerUnitTest::ValidateShowBgpServerResponse(Sandesh *sandesh) { string BgpServerUnitTest::GetConfigStr(int peer_count, unsigned short port_a, unsigned short port_b, + bool admin_down1, bool admin_down2, + bool nbr_admin_down1, bool nbr_admin_down2, as_t as_num1, as_t as_num2, as_t local_as_num1, as_t local_as_num2, string peer_address1, string peer_address2, @@ -278,6 +288,9 @@ string BgpServerUnitTest::GetConfigStr(int peer_count, config << (!delete_config ? "" : ""); config << "" + "" << + std::boolalpha << admin_down1 << std::noboolalpha << + "" "" << as_num1 << "" "" << local_as_num1 << "" @@ -311,6 +324,9 @@ string BgpServerUnitTest::GetConfigStr(int peer_count, for (int i = 0; i < peer_count; i++) { config << ""; + config << ""; + config << std::boolalpha << nbr_admin_down1 << std::noboolalpha; + config << ""; if (nbr_hold_time1) config << "" << nbr_hold_time1 << ""; config << ""; @@ -324,6 +340,9 @@ string BgpServerUnitTest::GetConfigStr(int peer_count, config << ""; config << "" + "" << + std::boolalpha << admin_down2 << std::noboolalpha << + "" "" << as_num2 << "" "" << local_as_num2 << "" @@ -357,6 +376,9 @@ string BgpServerUnitTest::GetConfigStr(int peer_count, for (int i = 0; i < peer_count; i++) { config << ""; + config << ""; + config << std::boolalpha << nbr_admin_down2 << std::noboolalpha; + config << ""; if (nbr_hold_time2) config << "" << nbr_hold_time2 << ""; config << ""; @@ -381,6 +403,7 @@ void BgpServerUnitTest::SetupPeers(BgpServerTest *server, int peer_count, vector families1, vector families2, bool delete_config) { string config = GetConfigStr(peer_count, port_a, port_b, + false, false, false, false, as_num1, as_num2, as_num1, as_num2, peer_address1, peer_address2, @@ -400,7 +423,9 @@ void BgpServerUnitTest::SetupPeers(BgpServerTest *server, int peer_count, string bgp_identifier1, string bgp_identifier2, vector families1, vector families2, bool delete_config) { - string config = GetConfigStr(peer_count, port_a, port_b, as_num1, as_num2, + string config = GetConfigStr(peer_count, port_a, port_b, + false, false, false, false, + as_num1, as_num2, as_num1, as_num2, peer_address1, peer_address2, bgp_identifier1, bgp_identifier2, families1, families2, @@ -411,6 +436,32 @@ void BgpServerUnitTest::SetupPeers(BgpServerTest *server, int peer_count, task_util::WaitForIdle(); } +void BgpServerUnitTest::SetupPeers(int peer_count, + unsigned short port_a, unsigned short port_b, bool verify_keepalives, + bool admin_down1, bool admin_down2, + bool nbr_admin_down1, bool nbr_admin_down2, + as_t as_num1, as_t as_num2, + as_t local_as_num1, as_t local_as_num2) { + string config = GetConfigStr(peer_count, port_a, port_b, + admin_down1, admin_down2, + nbr_admin_down1, nbr_admin_down2, + as_num1, as_num2, + local_as_num1, local_as_num2, + "127.0.0.1", + "127.0.0.1", + "192.168.0.10", + "192.168.0.11", + vector(), + vector(), + StateMachine::kHoldTime, + StateMachine::kHoldTime, + 0, 0, false); + a_->Configure(config); + task_util::WaitForIdle(); + b_->Configure(config); + task_util::WaitForIdle(); +} + void BgpServerUnitTest::SetupPeers(int peer_count, unsigned short port_a, unsigned short port_b, bool verify_keepalives, vector auth_keys, @@ -419,7 +470,9 @@ void BgpServerUnitTest::SetupPeers(int peer_count, string bgp_identifier1, string bgp_identifier2, vector families1, vector families2, uint16_t hold_time1, uint16_t hold_time2) { - string config = GetConfigStr(peer_count, port_a, port_b, as_num1, as_num2, + string config = GetConfigStr(peer_count, port_a, port_b, + false, false, false, false, + as_num1, as_num2, as_num1, as_num2, peer_address1, peer_address2, bgp_identifier1, bgp_identifier2, families1, families2, @@ -441,6 +494,7 @@ void BgpServerUnitTest::SetupPeers(int peer_count, uint16_t hold_time1, uint16_t hold_time2, uint16_t nbr_hold_time1, uint16_t nbr_hold_time2) { string config = GetConfigStr(peer_count, port_a, port_b, + false, false, false, false, as_num1, as_num2, as_num1, as_num2, peer_address1, peer_address2, @@ -459,6 +513,7 @@ void BgpServerUnitTest::SetupPeers(int peer_count, unsigned short port_a, unsigned short port_b, bool verify_keepalives, as_t as_num1, as_t as_num2, as_t local_as_num1, as_t local_as_num2) { string config = GetConfigStr(peer_count, port_a, port_b, + false, false, false, false, as_num1, as_num2, local_as_num1, local_as_num2, "127.0.0.1", "127.0.0.1", @@ -1458,6 +1513,383 @@ TEST_F(BgpServerUnitTest, AdminDown) { VerifyPeers(peer_count); } +TEST_F(BgpServerUnitTest, ConfigAdminDown1) { + int peer_count = 3; + BgpPeerTest::verbose_name(true); + + // + // Set bgp-router on A and B to be admin down. + // + SetupPeers(peer_count, a_->session_manager()->GetPort(), + b_->session_manager()->GetPort(), false, + true, true, false, false, + BgpConfigManager::kDefaultAutonomousSystem, + BgpConfigManager::kDefaultAutonomousSystem, + BgpConfigManager::kDefaultAutonomousSystem, + BgpConfigManager::kDefaultAutonomousSystem); + + // + // Make sure that the peers are admin down. + // + for (int j = 0; j < peer_count; j++) { + string uuid = BgpConfigParser::session_uuid("A", "B", j + 1); + BgpPeer *peer_a = a_->FindPeerByUuid(BgpConfigManager::kMasterInstance, + uuid); + BgpPeer *peer_b = b_->FindPeerByUuid(BgpConfigManager::kMasterInstance, + uuid); + TASK_UTIL_EXPECT_TRUE(peer_a->IsAdminDown()); + TASK_UTIL_EXPECT_TRUE(peer_b->IsAdminDown()); + } + + // + // Set bgp-router on A and B to not be admin down. + // Verify that sessions come up. + // + SetupPeers(peer_count, a_->session_manager()->GetPort(), + b_->session_manager()->GetPort(), false, + false, false, false, false, + BgpConfigManager::kDefaultAutonomousSystem, + BgpConfigManager::kDefaultAutonomousSystem, + BgpConfigManager::kDefaultAutonomousSystem, + BgpConfigManager::kDefaultAutonomousSystem); + VerifyPeers(peer_count); +} + +TEST_F(BgpServerUnitTest, ConfigAdminDown2) { + int peer_count = 3; + BgpPeerTest::verbose_name(true); + + // + // Set bgp-router on A and B to not be admin down. + // Verify that sessions come up. + // + SetupPeers(peer_count, a_->session_manager()->GetPort(), + b_->session_manager()->GetPort(), false, + false, false, false, false, + BgpConfigManager::kDefaultAutonomousSystem, + BgpConfigManager::kDefaultAutonomousSystem, + BgpConfigManager::kDefaultAutonomousSystem, + BgpConfigManager::kDefaultAutonomousSystem); + VerifyPeers(peer_count); + + vector flap_count_a; + vector flap_count_b; + + // + // Note down the current flap count + // + for (int j = 0; j < peer_count; j++) { + string uuid = BgpConfigParser::session_uuid("A", "B", j + 1); + BgpPeer *peer_a = a_->FindPeerByUuid(BgpConfigManager::kMasterInstance, + uuid); + BgpPeer *peer_b = b_->FindPeerByUuid(BgpConfigManager::kMasterInstance, + uuid); + flap_count_a.push_back(peer_a->flap_count()); + flap_count_b.push_back(peer_b->flap_count()); + } + + // + // Set bgp-router on A and B to be admin down. + // + SetupPeers(peer_count, a_->session_manager()->GetPort(), + b_->session_manager()->GetPort(), false, + true, true, false, false, + BgpConfigManager::kDefaultAutonomousSystem, + BgpConfigManager::kDefaultAutonomousSystem, + BgpConfigManager::kDefaultAutonomousSystem, + BgpConfigManager::kDefaultAutonomousSystem); + + // + // Make sure that the peers flapped and are admin down now. + // + for (int j = 0; j < peer_count; j++) { + string uuid = BgpConfigParser::session_uuid("A", "B", j + 1); + BgpPeer *peer_a = a_->FindPeerByUuid(BgpConfigManager::kMasterInstance, + uuid); + BgpPeer *peer_b = b_->FindPeerByUuid(BgpConfigManager::kMasterInstance, + uuid); + TASK_UTIL_EXPECT_TRUE(peer_a->flap_count() > flap_count_a[j]); + TASK_UTIL_EXPECT_TRUE(peer_b->flap_count() > flap_count_b[j]); + TASK_UTIL_EXPECT_TRUE(peer_a->IsAdminDown()); + TASK_UTIL_EXPECT_TRUE(peer_b->IsAdminDown()); + } + + // + // Set bgp-router on A and B to not be admin down. + // Verify that sessions come up. + // + SetupPeers(peer_count, a_->session_manager()->GetPort(), + b_->session_manager()->GetPort(), false, + false, false, false, false, + BgpConfigManager::kDefaultAutonomousSystem, + BgpConfigManager::kDefaultAutonomousSystem, + BgpConfigManager::kDefaultAutonomousSystem, + BgpConfigManager::kDefaultAutonomousSystem); + VerifyPeers(peer_count); +} + +TEST_F(BgpServerUnitTest, ConfigAdminDown3) { + int peer_count = 3; + BgpPeerTest::verbose_name(true); + + // + // Set bgp-router on A and B to not be admin down. + // Verify that sessions come up. + // + SetupPeers(peer_count, a_->session_manager()->GetPort(), + b_->session_manager()->GetPort(), false, + false, false, false, false, + BgpConfigManager::kDefaultAutonomousSystem, + BgpConfigManager::kDefaultAutonomousSystem, + BgpConfigManager::kDefaultAutonomousSystem, + BgpConfigManager::kDefaultAutonomousSystem); + VerifyPeers(peer_count); + + vector flap_count_a; + vector flap_count_b; + + // + // Note down the current flap count + // + for (int j = 0; j < peer_count; j++) { + string uuid = BgpConfigParser::session_uuid("A", "B", j + 1); + BgpPeer *peer_a = a_->FindPeerByUuid(BgpConfigManager::kMasterInstance, + uuid); + BgpPeer *peer_b = b_->FindPeerByUuid(BgpConfigManager::kMasterInstance, + uuid); + flap_count_a.push_back(peer_a->flap_count()); + flap_count_b.push_back(peer_b->flap_count()); + } + + // + // Set bgp-router on A to be admin down. + // + SetupPeers(peer_count, a_->session_manager()->GetPort(), + b_->session_manager()->GetPort(), false, + true, false, false, false, + BgpConfigManager::kDefaultAutonomousSystem, + BgpConfigManager::kDefaultAutonomousSystem, + BgpConfigManager::kDefaultAutonomousSystem, + BgpConfigManager::kDefaultAutonomousSystem); + + // + // Make sure that the peers flapped and are admin down now. + // + for (int j = 0; j < peer_count; j++) { + string uuid = BgpConfigParser::session_uuid("A", "B", j + 1); + BgpPeer *peer_a = a_->FindPeerByUuid(BgpConfigManager::kMasterInstance, + uuid); + BgpPeer *peer_b = b_->FindPeerByUuid(BgpConfigManager::kMasterInstance, + uuid); + TASK_UTIL_EXPECT_TRUE(peer_a->flap_count() > flap_count_a[j]); + TASK_UTIL_EXPECT_TRUE(peer_b->flap_count() > flap_count_b[j]); + TASK_UTIL_EXPECT_TRUE(peer_a->IsAdminDown()); + TASK_UTIL_EXPECT_TRUE(peer_b->IsAdminDown()); + } + + // + // Set bgp-router on A and B to not be admin down. + // Verify that sessions come up. + // + SetupPeers(peer_count, a_->session_manager()->GetPort(), + b_->session_manager()->GetPort(), false, + false, false, false, false, + BgpConfigManager::kDefaultAutonomousSystem, + BgpConfigManager::kDefaultAutonomousSystem, + BgpConfigManager::kDefaultAutonomousSystem, + BgpConfigManager::kDefaultAutonomousSystem); + VerifyPeers(peer_count); +} + +TEST_F(BgpServerUnitTest, ConfigAdminDown4) { + int peer_count = 3; + BgpPeerTest::verbose_name(true); + + // + // Set neighbors on A and B to be admin down. + // + SetupPeers(peer_count, a_->session_manager()->GetPort(), + b_->session_manager()->GetPort(), false, + false, false, true, true, + BgpConfigManager::kDefaultAutonomousSystem, + BgpConfigManager::kDefaultAutonomousSystem, + BgpConfigManager::kDefaultAutonomousSystem, + BgpConfigManager::kDefaultAutonomousSystem); + + // + // Make sure that the peers are admin down. + // + for (int j = 0; j < peer_count; j++) { + string uuid = BgpConfigParser::session_uuid("A", "B", j + 1); + BgpPeer *peer_a = a_->FindPeerByUuid(BgpConfigManager::kMasterInstance, + uuid); + BgpPeer *peer_b = b_->FindPeerByUuid(BgpConfigManager::kMasterInstance, + uuid); + TASK_UTIL_EXPECT_TRUE(peer_a->IsAdminDown()); + TASK_UTIL_EXPECT_TRUE(peer_b->IsAdminDown()); + } + + // + // Set neighbors on A and B to not be admin down. + // Verify that sessions come up. + // + SetupPeers(peer_count, a_->session_manager()->GetPort(), + b_->session_manager()->GetPort(), false, + false, false, false, false, + BgpConfigManager::kDefaultAutonomousSystem, + BgpConfigManager::kDefaultAutonomousSystem, + BgpConfigManager::kDefaultAutonomousSystem, + BgpConfigManager::kDefaultAutonomousSystem); + VerifyPeers(peer_count); +} + +TEST_F(BgpServerUnitTest, ConfigAdminDown5) { + int peer_count = 3; + BgpPeerTest::verbose_name(true); + + // + // Set neighbors on A and B to not be admin down. + // Verify that sessions come up. + // + SetupPeers(peer_count, a_->session_manager()->GetPort(), + b_->session_manager()->GetPort(), false, + false, false, false, false, + BgpConfigManager::kDefaultAutonomousSystem, + BgpConfigManager::kDefaultAutonomousSystem, + BgpConfigManager::kDefaultAutonomousSystem, + BgpConfigManager::kDefaultAutonomousSystem); + VerifyPeers(peer_count); + + vector flap_count_a; + vector flap_count_b; + + // + // Note down the current flap count + // + for (int j = 0; j < peer_count; j++) { + string uuid = BgpConfigParser::session_uuid("A", "B", j + 1); + BgpPeer *peer_a = a_->FindPeerByUuid(BgpConfigManager::kMasterInstance, + uuid); + BgpPeer *peer_b = b_->FindPeerByUuid(BgpConfigManager::kMasterInstance, + uuid); + flap_count_a.push_back(peer_a->flap_count()); + flap_count_b.push_back(peer_b->flap_count()); + } + + // + // Set neighbors on A and B to be admin down. + // + SetupPeers(peer_count, a_->session_manager()->GetPort(), + b_->session_manager()->GetPort(), false, + false, false, true, true, + BgpConfigManager::kDefaultAutonomousSystem, + BgpConfigManager::kDefaultAutonomousSystem, + BgpConfigManager::kDefaultAutonomousSystem, + BgpConfigManager::kDefaultAutonomousSystem); + + // + // Make sure that the peers flapped and are admin down now. + // + for (int j = 0; j < peer_count; j++) { + string uuid = BgpConfigParser::session_uuid("A", "B", j + 1); + BgpPeer *peer_a = a_->FindPeerByUuid(BgpConfigManager::kMasterInstance, + uuid); + BgpPeer *peer_b = b_->FindPeerByUuid(BgpConfigManager::kMasterInstance, + uuid); + TASK_UTIL_EXPECT_TRUE(peer_a->flap_count() > flap_count_a[j]); + TASK_UTIL_EXPECT_TRUE(peer_b->flap_count() > flap_count_b[j]); + TASK_UTIL_EXPECT_TRUE(peer_a->IsAdminDown()); + TASK_UTIL_EXPECT_TRUE(peer_b->IsAdminDown()); + } + + // + // Set neighbors on A and B to not be admin down. + // Verify that sessions come up. + // + SetupPeers(peer_count, a_->session_manager()->GetPort(), + b_->session_manager()->GetPort(), false, + false, false, false, false, + BgpConfigManager::kDefaultAutonomousSystem, + BgpConfigManager::kDefaultAutonomousSystem, + BgpConfigManager::kDefaultAutonomousSystem, + BgpConfigManager::kDefaultAutonomousSystem); + VerifyPeers(peer_count); +} + +TEST_F(BgpServerUnitTest, ConfigAdminDown6) { + int peer_count = 3; + BgpPeerTest::verbose_name(true); + + // + // Set neighbors on A and B to not be admin down. + // Verify that sessions come up. + // + SetupPeers(peer_count, a_->session_manager()->GetPort(), + b_->session_manager()->GetPort(), false, + false, false, false, false, + BgpConfigManager::kDefaultAutonomousSystem, + BgpConfigManager::kDefaultAutonomousSystem, + BgpConfigManager::kDefaultAutonomousSystem, + BgpConfigManager::kDefaultAutonomousSystem); + VerifyPeers(peer_count); + + vector flap_count_a; + vector flap_count_b; + + // + // Note down the current flap count + // + for (int j = 0; j < peer_count; j++) { + string uuid = BgpConfigParser::session_uuid("A", "B", j + 1); + BgpPeer *peer_a = a_->FindPeerByUuid(BgpConfigManager::kMasterInstance, + uuid); + BgpPeer *peer_b = b_->FindPeerByUuid(BgpConfigManager::kMasterInstance, + uuid); + flap_count_a.push_back(peer_a->flap_count()); + flap_count_b.push_back(peer_b->flap_count()); + } + + // + // Set neighbor on A to be admin down. + // + SetupPeers(peer_count, a_->session_manager()->GetPort(), + b_->session_manager()->GetPort(), false, + false, false, true, false, + BgpConfigManager::kDefaultAutonomousSystem, + BgpConfigManager::kDefaultAutonomousSystem, + BgpConfigManager::kDefaultAutonomousSystem, + BgpConfigManager::kDefaultAutonomousSystem); + + // + // Make sure that the peers flapped. + // Verify that peers on A are admin down and peers on B are not. + // + for (int j = 0; j < peer_count; j++) { + string uuid = BgpConfigParser::session_uuid("A", "B", j + 1); + BgpPeer *peer_a = a_->FindPeerByUuid(BgpConfigManager::kMasterInstance, + uuid); + BgpPeer *peer_b = b_->FindPeerByUuid(BgpConfigManager::kMasterInstance, + uuid); + TASK_UTIL_EXPECT_TRUE(peer_a->flap_count() > flap_count_a[j]); + TASK_UTIL_EXPECT_TRUE(peer_b->flap_count() > flap_count_b[j]); + TASK_UTIL_EXPECT_TRUE(peer_a->IsAdminDown()); + TASK_UTIL_EXPECT_FALSE(peer_b->IsAdminDown()); + } + + // + // Set neighbors on A and B to not be admin down. + // Verify that sessions come up. + // + SetupPeers(peer_count, a_->session_manager()->GetPort(), + b_->session_manager()->GetPort(), false, + false, false, false, false, + BgpConfigManager::kDefaultAutonomousSystem, + BgpConfigManager::kDefaultAutonomousSystem, + BgpConfigManager::kDefaultAutonomousSystem, + BgpConfigManager::kDefaultAutonomousSystem); + VerifyPeers(peer_count); +} + TEST_F(BgpServerUnitTest, ResetStatsOnFlap) { int peer_count = 3; @@ -1548,6 +1980,7 @@ TEST_F(BgpServerUnitTest, DISABLED_ChangeBgpPort) { vector families_b; string config = GetConfigStr(peer_count, a_->session_manager()->GetPort(), b_->session_manager()->GetPort(), + false, false, false, false, BgpConfigManager::kDefaultAutonomousSystem, BgpConfigManager::kDefaultAutonomousSystem, BgpConfigManager::kDefaultAutonomousSystem, diff --git a/src/bgp/test/bgp_xmpp_basic_test.cc b/src/bgp/test/bgp_xmpp_basic_test.cc index d27df3b318a..c79cc7fa127 100644 --- a/src/bgp/test/bgp_xmpp_basic_test.cc +++ b/src/bgp/test/bgp_xmpp_basic_test.cc @@ -48,6 +48,26 @@ static const char *bgp_config_template = "\ \ "; +static const char *bgp_admin_down_config_template = "\ +\ + \ + true\ + 192.168.0.1\ +
127.0.0.1
\ + %d\ + %d\ + %d\ +
\ + \ + 1\ + \ + \ + blue\ + target:1:1\ + \ +
\ +"; + static const char *bgp_unconfig = "\ \ \ @@ -592,6 +612,87 @@ TEST_P(BgpXmppBasicParamTest, NoSelfBgpConfiguration2) { DestroyAgents(); } +TEST_P(BgpXmppBasicParamTest, BgpAdminDown1) { + Configure(bgp_admin_down_config_template, 64512, 64512); + task_util::WaitForIdle(); + TASK_UTIL_EXPECT_TRUE(bs_x_->HasSelfConfiguration()); + TASK_UTIL_EXPECT_TRUE(bs_x_->admin_down()); + + CreateAgents(); + + uint32_t client_flap_a = agent_a_->flap_count(); + uint32_t client_flap_b = agent_b_->flap_count(); + uint32_t client_flap_c = agent_c_->flap_count(); + + uint32_t server_flap_a = GetXmppConnectionFlapCount(agent_a_->hostname()); + uint32_t server_flap_b = GetXmppConnectionFlapCount(agent_b_->hostname()); + uint32_t server_flap_c = GetXmppConnectionFlapCount(agent_c_->hostname()); + + TASK_UTIL_EXPECT_TRUE(agent_a_->flap_count() > client_flap_a + 3); + TASK_UTIL_EXPECT_TRUE(agent_b_->flap_count() > client_flap_b + 3); + TASK_UTIL_EXPECT_TRUE(agent_c_->flap_count() > client_flap_c + 3); + + TASK_UTIL_EXPECT_TRUE( + GetXmppConnectionFlapCount(agent_a_->hostname()) > server_flap_a + 3); + TASK_UTIL_EXPECT_TRUE( + GetXmppConnectionFlapCount(agent_b_->hostname()) > server_flap_b + 3); + TASK_UTIL_EXPECT_TRUE( + GetXmppConnectionFlapCount(agent_c_->hostname()) > server_flap_c + 3); + + TASK_UTIL_EXPECT_FALSE(agent_a_->IsEstablished()); + TASK_UTIL_EXPECT_FALSE(agent_b_->IsEstablished()); + TASK_UTIL_EXPECT_FALSE(agent_c_->IsEstablished()); + + DestroyAgents(); +} + +TEST_P(BgpXmppBasicParamTest, BgpAdminDown2) { + CreateAgents(); + + TASK_UTIL_EXPECT_TRUE(agent_a_->IsEstablished()); + TASK_UTIL_EXPECT_TRUE(agent_b_->IsEstablished()); + TASK_UTIL_EXPECT_TRUE(agent_c_->IsEstablished()); + + uint32_t client_flap_a = agent_a_->flap_count(); + uint32_t client_flap_b = agent_b_->flap_count(); + uint32_t client_flap_c = agent_c_->flap_count(); + + uint32_t server_flap_a = GetXmppConnectionFlapCount(agent_a_->hostname()); + uint32_t server_flap_b = GetXmppConnectionFlapCount(agent_b_->hostname()); + uint32_t server_flap_c = GetXmppConnectionFlapCount(agent_c_->hostname()); + + Configure(bgp_admin_down_config_template, 64512, 64512); + task_util::WaitForIdle(); + TASK_UTIL_EXPECT_TRUE(bs_x_->HasSelfConfiguration()); + TASK_UTIL_EXPECT_TRUE(bs_x_->admin_down()); + + TASK_UTIL_EXPECT_TRUE(agent_a_->flap_count() > client_flap_a + 3); + TASK_UTIL_EXPECT_TRUE(agent_b_->flap_count() > client_flap_b + 3); + TASK_UTIL_EXPECT_TRUE(agent_c_->flap_count() > client_flap_c + 3); + + TASK_UTIL_EXPECT_TRUE( + GetXmppConnectionFlapCount(agent_a_->hostname()) > server_flap_a + 3); + TASK_UTIL_EXPECT_TRUE( + GetXmppConnectionFlapCount(agent_b_->hostname()) > server_flap_b + 3); + TASK_UTIL_EXPECT_TRUE( + GetXmppConnectionFlapCount(agent_c_->hostname()) > server_flap_c + 3); + + TASK_UTIL_EXPECT_FALSE(agent_a_->IsEstablished()); + TASK_UTIL_EXPECT_FALSE(agent_b_->IsEstablished()); + TASK_UTIL_EXPECT_FALSE(agent_c_->IsEstablished()); + + Configure(bgp_config_template, 64512, 64512); + task_util::WaitForIdle(); + TASK_UTIL_EXPECT_TRUE(bs_x_->HasSelfConfiguration()); + TASK_UTIL_EXPECT_FALSE(bs_x_->admin_down()); + + TASK_UTIL_EXPECT_TRUE(agent_a_->IsEstablished()); + TASK_UTIL_EXPECT_TRUE(agent_b_->IsEstablished()); + TASK_UTIL_EXPECT_TRUE(agent_c_->IsEstablished()); + + DestroyAgents(); +} + TEST_P(BgpXmppBasicParamTest, ClientConnectionBackoff) { XmppStateMachineTest::set_hold_time_msecs(300); Unconfigure(); diff --git a/src/control-node/main.cc b/src/control-node/main.cc index 4eed15ed6d0..cc0ab6e0ba2 100644 --- a/src/control-node/main.cc +++ b/src/control-node/main.cc @@ -287,6 +287,13 @@ bool ControlNodeInfoLogger(BgpServer *server, CpuLoadData::FillCpuInfo(cpu_load_info, false); state.set_name(server->localname()); + uint32_t admin_down = server->admin_down(); + if (admin_down != prev_state.get_admin_down() || first) { + state.set_admin_down(admin_down); + prev_state.set_admin_down(admin_down); + change = true; + } + string router_id = server->bgp_identifier_string(); if (router_id != prev_state.get_router_id() || first) { state.set_router_id(router_id); @@ -480,6 +487,9 @@ static void ControlNodeGetProcessStateCb(const BgpServer *bgp_server, } else if (!bgp_server->HasSelfConfiguration()) { state = ProcessState::NON_FUNCTIONAL; message = "No BGP configuration for self"; + } else if (bgp_server->admin_down()) { + state = ProcessState::NON_FUNCTIONAL; + message = "BGP is administratively down"; } } @@ -493,6 +503,10 @@ static bool ControlNodeReEvalPublishCb(const BgpServer *bgp_server, message = "No BGP configuration for self"; return false; } + if (bgp_server->admin_down()) { + message = "BGP is administratively down"; + return false; + } message = "OK"; return true; } diff --git a/src/control-node/sandesh/control_node.sandesh b/src/control-node/sandesh/control_node.sandesh index 59f8eda5a57..a51f87f188e 100644 --- a/src/control-node/sandesh/control_node.sandesh +++ b/src/control-node/sandesh/control_node.sandesh @@ -11,6 +11,7 @@ struct BgpRouterState { 27: optional string router_id; 28: optional u32 local_asn; 29: optional u32 global_asn; + 30: optional bool admin_down 2: optional bool deleted 3: optional u64 uptime; 7: optional u32 output_queue_depth; diff --git a/src/schema/bgp_schema.xsd b/src/schema/bgp_schema.xsd index 01f5e66e842..75411b70154 100644 --- a/src/schema/bgp_schema.xsd +++ b/src/schema/bgp_schema.xsd @@ -49,6 +49,7 @@ + @@ -98,6 +99,7 @@ +