diff --git a/src/vnsw/agent/controller/controller_init.cc b/src/vnsw/agent/controller/controller_init.cc index 0db4043b88d..3c585647823 100644 --- a/src/vnsw/agent/controller/controller_init.cc +++ b/src/vnsw/agent/controller/controller_init.cc @@ -31,6 +31,10 @@ using namespace boost::asio; SandeshTraceBufferPtr ControllerTraceBuf(SandeshTraceBufferCreate( "Controller", 1000)); +ControllerDiscoveryData::ControllerDiscoveryData(std::vector resp) : + ControllerWorkQueueData(), discovery_response_(resp) { +} + VNController::VNController(Agent *agent) : agent_(agent), multicast_sequence_number_(0), unicast_cleanup_timer_(agent), multicast_cleanup_timer_(agent), @@ -229,6 +233,22 @@ void VNController::DnsXmppServerDisConnect() { } +//During delete of xmpp channel, check if BGP peer is deleted. +//If not agent never got a channel down state and is being removed +//as it is not part of discovery list. +//Artificially inject NOT_READY in agent xmpp channel. +void VNController::DeleteAgentXmppChannel(AgentXmppChannel *channel) { + if (!channel) + return; + + BgpPeer *bgp_peer = channel->bgp_peer_id(); + if (bgp_peer != NULL) { + AgentXmppChannel::HandleAgentXmppClientChannelEvent(channel, + xmps::NOT_READY); + } + delete channel; +} + //Trigger shutdown and cleanup of routes for the client void VNController::DisConnect() { XmppServerDisConnect(); @@ -302,11 +322,11 @@ void VNController::DisConnectControllerIfmapServer(uint8_t idx) { //cleanup AgentXmppChannel agent_->ResetAgentMcastLabelRange(idx); - delete agent_->controller_xmpp_channel(idx); + DeleteAgentXmppChannel(agent_->controller_xmpp_channel(idx)); agent_->set_controller_xmpp_channel(NULL, idx); //cleanup AgentIfmapXmppChannel - delete agent_->ifmap_xmpp_channel(idx); + delete agent_->ifmap_xmpp_channel(idx); agent_->set_ifmap_xmpp_channel(NULL, idx); agent_->controller_ifmap_xmpp_init(idx)->Reset(); @@ -330,7 +350,13 @@ bool VNController::AgentXmppServerExists(const std::string &server_ip, } void VNController::ApplyDiscoveryXmppServices(std::vector resp) { + ControllerDiscoveryDataType data(new ControllerDiscoveryData(resp)); + ControllerWorkQueueDataType base_data = + boost::static_pointer_cast(data); + work_queue_.Enqueue(base_data); +} +bool VNController::ApplyDiscoveryXmppServicesInternal(std::vector resp) { std::vector::iterator iter; int8_t count = -1; for (iter = resp.begin(); iter != resp.end(); iter++) { @@ -414,6 +440,7 @@ void VNController::ApplyDiscoveryXmppServices(std::vector resp) { } XmppServerConnect(); + return true; } AgentDnsXmppChannel *VNController::FindAgentDnsXmppChannel( @@ -696,6 +723,13 @@ bool VNController::ControllerWorkQueueProcess(ControllerWorkQueueDataType data) return ControllerPeerHeadlessAgentDelDone(derived_walk_done_data-> bgp_peer()); } + //Discovery response for servers + ControllerDiscoveryDataType discovery_data = + boost::dynamic_pointer_cast(data); + if (discovery_data) { + return ApplyDiscoveryXmppServicesInternal(discovery_data-> + discovery_response_); + } return true; } diff --git a/src/vnsw/agent/controller/controller_init.h b/src/vnsw/agent/controller/controller_init.h index 906b7b08f4b..e102f9c93c5 100644 --- a/src/vnsw/agent/controller/controller_init.h +++ b/src/vnsw/agent/controller/controller_init.h @@ -66,11 +66,21 @@ class ControllerXmppData : public ControllerWorkQueueData { DISALLOW_COPY_AND_ASSIGN(ControllerXmppData); }; +class ControllerDiscoveryData : public ControllerWorkQueueData { +public: + ControllerDiscoveryData(std::vector resp); + virtual ~ControllerDiscoveryData() {} + + std::vector discovery_response_; + DISALLOW_COPY_AND_ASSIGN(ControllerDiscoveryData); +}; + class VNController { public: typedef boost::shared_ptr ControllerXmppDataType; typedef boost::shared_ptr ControllerDeletePeerDataType; typedef boost::shared_ptr ControllerWorkQueueDataType; + typedef boost::shared_ptr ControllerDiscoveryDataType; typedef boost::shared_ptr BgpPeerPtr; typedef std::list >::iterator BgpPeerIterator; VNController(Agent *agent); @@ -86,8 +96,8 @@ class VNController { void XmppServerDisConnect(); void DnsXmppServerDisConnect(); - void ApplyDiscoveryXmppServices(std::vector resp); - void ApplyDiscoveryDnsXmppServices(std::vector resp); + void ApplyDiscoveryXmppServices(std::vector resp); + void ApplyDiscoveryDnsXmppServices(std::vector resp); void DisConnectControllerIfmapServer(uint8_t idx); void DisConnectDnsServer(uint8_t idx); @@ -129,6 +139,7 @@ class VNController { bool XmppMessageProcess(ControllerXmppDataType data); Agent *agent() {return agent_;} void Enqueue(ControllerWorkQueueDataType data); + void DeleteAgentXmppChannel(AgentXmppChannel *ch); private: AgentXmppChannel *FindAgentXmppChannel(const std::string &server_ip); @@ -137,6 +148,7 @@ class VNController { const std::string MakeConnectionPrefix(bool is_dns) const; bool AgentXmppServerExists(const std::string &server_ip, std::vector resp); + bool ApplyDiscoveryXmppServicesInternal(std::vector resp); Agent *agent_; uint64_t multicast_sequence_number_; diff --git a/src/vnsw/agent/controller/controller_peer.cc b/src/vnsw/agent/controller/controller_peer.cc index eb27dfba4ac..a13c85bb192 100644 --- a/src/vnsw/agent/controller/controller_peer.cc +++ b/src/vnsw/agent/controller/controller_peer.cc @@ -81,6 +81,8 @@ AgentXmppChannel::AgentXmppChannel(Agent *agent, } AgentXmppChannel::~AgentXmppChannel() { + BgpPeer *bgp_peer = bgp_peer_id_.get(); + assert(bgp_peer == NULL); channel_->UnRegisterReceive(xmps::BGP); } diff --git a/src/vnsw/agent/test/test_route.cc b/src/vnsw/agent/test/test_route.cc index 65d500fd7dd..4731ebefe2a 100644 --- a/src/vnsw/agent/test/test_route.cc +++ b/src/vnsw/agent/test/test_route.cc @@ -2124,6 +2124,43 @@ TEST_F(RouteTest, ArpRouteDelete) { EXPECT_FALSE(FindNH(&key)); } +TEST_F(RouteTest, verify_channel_delete_results_in_path_delete) { + client->Reset(); + struct PortInfo input[] = { + {"vnet1", 1, "1.1.1.1", "00:00:00:01:01:01", 1, 1}, + }; + + IpamInfo ipam_info[] = { + {"1.1.1.0", 24, "1.1.1.200", true}, + }; + client->Reset(); + CreateVmportEnv(input, 1, 0); + client->WaitForIdle(); + AddIPAM("vn1", ipam_info, 1); + client->WaitForIdle(); + + BgpPeer *peer = CreateBgpPeer("127.0.0.1", "remote"); + FillEvpnNextHop(peer, "vrf1", 1000, TunnelType::MplsType()); + client->WaitForIdle(); + //Get Channel and delete it. + AgentXmppChannel *ch = peer->GetBgpXmppPeer(); + XmppChannelMock *xmpp_channel = static_cast + (ch->GetXmppChannel()); + delete ch; + delete xmpp_channel; + client->WaitForIdle(); + + client->Reset(); + DelIPAM("vn1"); + client->WaitForIdle(); + FlushEvpnNextHop(peer, "vrf1", 0); + DeleteVmportEnv(input, 1, 1, 0); + client->WaitForIdle(); + DeleteBgpPeer(NULL); + client->WaitForIdle(); +} + + int main(int argc, char *argv[]) { ::testing::InitGoogleTest(&argc, argv); GETUSERARGS(); diff --git a/src/vnsw/agent/test/test_util.cc b/src/vnsw/agent/test/test_util.cc index 588cfdbcdef..e55d0986ae7 100644 --- a/src/vnsw/agent/test/test_util.cc +++ b/src/vnsw/agent/test/test_util.cc @@ -3127,11 +3127,12 @@ BgpPeer *CreateBgpPeer(const Ip4Address &addr, std::string name) { void DeleteBgpPeer(Peer *peer) { BgpPeer *bgp_peer = static_cast(peer); - if (!bgp_peer) - return; - AgentXmppChannel *channel = bgp_peer->GetBgpXmppPeer(); - AgentXmppChannel::HandleAgentXmppClientChannelEvent(channel, xmps::NOT_READY); + AgentXmppChannel *channel = NULL; + if (bgp_peer) { + channel = bgp_peer->GetBgpXmppPeer(); + AgentXmppChannel::HandleAgentXmppClientChannelEvent(channel, xmps::NOT_READY); + } client->WaitForIdle(); TaskScheduler::GetInstance()->Stop(); Agent::GetInstance()->controller()->unicast_cleanup_timer().cleanup_timer_-> @@ -3144,10 +3145,12 @@ void DeleteBgpPeer(Peer *peer) { client->WaitForIdle(); Agent::GetInstance()->controller()->Cleanup(); client->WaitForIdle(); - XmppChannelMock *xmpp_channel = static_cast - (channel->GetXmppChannel()); - delete channel; - delete xmpp_channel; + if (channel) { + XmppChannelMock *xmpp_channel = static_cast + (channel->GetXmppChannel()); + delete channel; + delete xmpp_channel; + } } void FillEvpnNextHop(BgpPeer *peer, std::string vrf_name,