From a6adb73d42847ebb66e8ac451c5e4fa21fbeb69d Mon Sep 17 00:00:00 2001 From: Naveen N Date: Fri, 20 May 2016 15:17:40 +0530 Subject: [PATCH] * Handle route add messages on delete marked route ksync object If route ksync object is marked for deletion and its empty, then request to deleted ksync object is enqueued. In the mean time if any route add messages comes they should be ignored, handling the same. Closes-bug:#1582534 Change-Id: I5b102633fdb472f9220dfcb4e50ed35475fbd35c --- src/ksync/ksync_object.cc | 4 ++- src/vnsw/agent/oper/agent_route.cc | 4 +-- src/vnsw/agent/oper/vrf.cc | 2 +- src/vnsw/agent/oper/vrf.h | 9 ++++++ src/vnsw/agent/test/test_vrf.cc | 34 +++++++++++++++++++++ src/vnsw/agent/vrouter/ksync/route_ksync.cc | 12 ++++++++ src/vnsw/agent/vrouter/ksync/route_ksync.h | 1 + 7 files changed, 62 insertions(+), 4 deletions(-) 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_;