diff --git a/src/ksync/ksync_object.cc b/src/ksync/ksync_object.cc index ec23b1e0c5a..c4160fa0d5a 100644 --- a/src/ksync/ksync_object.cc +++ b/src/ksync/ksync_object.cc @@ -1517,7 +1517,9 @@ void KSyncObject::BackRefReEval(KSyncEntry *key) { bool KSyncObjectManager::Process(KSyncObjectEvent *event) { switch(event->event_) { case KSyncObjectEvent::UNREGISTER: - delete event->obj_; + if (event->obj_->Size() == 0) { + delete event->obj_; + } break; case KSyncObjectEvent::DELETE: { diff --git a/src/vnsw/agent/oper/agent_route.cc b/src/vnsw/agent/oper/agent_route.cc index dc3effe5c7c..0d64f484164 100644 --- a/src/vnsw/agent/oper/agent_route.cc +++ b/src/vnsw/agent/oper/agent_route.cc @@ -351,8 +351,8 @@ void AgentRouteTable::Input(DBTablePartition *part, DBClient *client, } if (req->oper == DBRequest::DB_ENTRY_ADD_CHANGE) { - // Ignore ADD_CHANGE if received on deleted VRF - if(vrf->IsDeleted()) { + if (vrf->IsDeleted() && + vrf->allow_route_add_on_deleted_vrf() == false) { return; } diff --git a/src/vnsw/agent/oper/vrf.cc b/src/vnsw/agent/oper/vrf.cc index 46d94ca1f7a..75ee0da13c3 100644 --- a/src/vnsw/agent/oper/vrf.cc +++ b/src/vnsw/agent/oper/vrf.cc @@ -63,7 +63,7 @@ VrfEntry::VrfEntry(const string &name, uint32_t flags, Agent *agent) : table_label_(MplsTable::kInvalidLabel), vxlan_id_(VxLanTable::kInvalidvxlan_id), rt_table_delete_bmap_(0), - route_resync_walker_(NULL) { + route_resync_walker_(NULL), allow_route_add_on_deleted_vrf_(false) { } VrfEntry::~VrfEntry() { diff --git a/src/vnsw/agent/oper/vrf.h b/src/vnsw/agent/oper/vrf.h index 0a35a6683e1..edcf80b16ce 100644 --- a/src/vnsw/agent/oper/vrf.h +++ b/src/vnsw/agent/oper/vrf.h @@ -121,6 +121,14 @@ class VrfEntry : AgentRefCount, public AgentOperDBEntry { void SetRouteTableDeleted(uint8_t table_type); void DeleteRouteTables(); void ResyncRoutes(); + bool allow_route_add_on_deleted_vrf() const { + return allow_route_add_on_deleted_vrf_; + } + + //To be set in test cases only + void set_allow_route_add_on_deleted_vrf(bool val) { + allow_route_add_on_deleted_vrf_ = val; + } private: friend class VrfTable; @@ -140,6 +148,7 @@ class VrfEntry : AgentRefCount, public AgentOperDBEntry { uint32_t rt_table_delete_bmap_; IFMapDependencyManager::IFMapNodePtr vrf_node_ptr_; boost::scoped_ptr route_resync_walker_; + bool allow_route_add_on_deleted_vrf_; DISALLOW_COPY_AND_ASSIGN(VrfEntry); }; diff --git a/src/vnsw/agent/test/test_vrf.cc b/src/vnsw/agent/test/test_vrf.cc index ab5787d9d92..f3998055287 100644 --- a/src/vnsw/agent/test/test_vrf.cc +++ b/src/vnsw/agent/test/test_vrf.cc @@ -59,6 +59,7 @@ class VrfTest : public ::testing::Test { }; virtual void SetUp() { + agent = Agent::GetInstance(); Agent::GetInstance()->controller()->Cleanup(); client->WaitForIdle(); Agent::GetInstance()->controller()->DisConnect(); @@ -100,6 +101,7 @@ class VrfTest : public ::testing::Test { EventManager evm_; ServerThread *thread_; test::ControlNodeMock *bgp_peer1; + Agent *agent; }; //Add VRF1 and fabric VRF @@ -371,6 +373,38 @@ TEST_F(VrfTest, DelReqonDeletedVrfRouteTable) { vrf_ref = NULL; } +//Test case for bug #1580733 +//If route ADD is notified to ksync after route ksync object +//is notified, ksyncobject would unregister from table before +//all the states are cleared +TEST_F(VrfTest, AddReqonDeletedVrfRouteTable) { + client->Reset(); + VrfAddReq("vrf1"); + EXPECT_TRUE(client->VrfNotifyWait(1)); + client->WaitForIdle(); + + // take reference of vrf entry + VrfEntryRef vrf_ref = VrfGet("vrf1"); + + vrf_ref->set_allow_route_add_on_deleted_vrf(true); + + VrfDelReq("vrf1"); + Ip4Address vip(0); + Ip4Address server_ip(0); + Inet4TunnelRouteAdd(agent->local_peer(), "vrf1", vip, 32, + server_ip, TunnelType::AllType(), + 16, "vn1", SecurityGroupList(), PathPreference()); + client->WaitForIdle(); + agent->fabric_inet4_unicast_table()->DeleteReq(agent->local_peer(), "vrf1", + vip, 32, NULL); + client->WaitForIdle(); + + // release the VRF reference + vrf_ref = NULL; + client->WaitForIdle(); + EXPECT_TRUE(VrfFind("vrf1", true) == false); +} + int main(int argc, char **argv) { GETUSERARGS(); client = TestInit(init_file, ksync_init, false, true, false); diff --git a/src/vnsw/agent/vrouter/ksync/route_ksync.cc b/src/vnsw/agent/vrouter/ksync/route_ksync.cc index 8a2e79c534e..2f710a7560d 100644 --- a/src/vnsw/agent/vrouter/ksync/route_ksync.cc +++ b/src/vnsw/agent/vrouter/ksync/route_ksync.cc @@ -724,6 +724,18 @@ RouteKSyncObject::~RouteKSyncObject() { table_delete_ref_.Reset(NULL); } +KSyncDBObject::DBFilterResp +RouteKSyncObject::DBEntryFilter(const DBEntry *entry, + const KSyncDBEntry *ksync) { + const AgentRoute *route = static_cast(entry); + // Ignore Add/Change notifications when VRF is deleted + if (route->vrf()->IsDeleted() == true) { + return DBFilterIgnore; + } + + return DBFilterAccept; +} + KSyncEntry *RouteKSyncObject::Alloc(const KSyncEntry *entry, uint32_t index) { const RouteKSyncEntry *route = static_cast(entry); RouteKSyncEntry *ksync = new RouteKSyncEntry(this, route, index); diff --git a/src/vnsw/agent/vrouter/ksync/route_ksync.h b/src/vnsw/agent/vrouter/ksync/route_ksync.h index 8b51fb5a690..b7c1da9988d 100644 --- a/src/vnsw/agent/vrouter/ksync/route_ksync.h +++ b/src/vnsw/agent/vrouter/ksync/route_ksync.h @@ -109,6 +109,7 @@ class RouteKSyncObject : public KSyncDBObject { void ManagedDelete(); void Unregister(); virtual void EmptyTable(); + DBFilterResp DBEntryFilter(const DBEntry *entry, const KSyncDBEntry *ksync); private: KSync *ksync_;