Skip to content

Commit

Permalink
Fix Agent crash on AgentRouteTable::RetryDelete
Browse files Browse the repository at this point in the history
Issue:
------
unregister of RouteTable is causing Notify on VRF Entry
outside the context of db::DBTable task, and if this
happens in parallel from two different task running in
parallel can cause change list append issues with tries
for double enqueues

Fix:
----
Do not notify entry in any other context other than
db::DBTable task

Closes-Bug: 1579180
Related-Bug: 1574958
Change-Id: Ied06b53500f56a68a8e2443f704a647773686de2
(cherry picked from commit 5141aee)
  • Loading branch information
Prabhjot Singh Sethi committed May 11, 2016
1 parent a26f806 commit 245d635
Showing 1 changed file with 16 additions and 8 deletions.
24 changes: 16 additions & 8 deletions src/vnsw/agent/oper/vrf.cc
Original file line number Diff line number Diff line change
Expand Up @@ -366,11 +366,12 @@ void VrfEntry::ResyncRoutes() {
void VrfEntry::RetryDelete() {
if (AllRouteTablesEmpty() == false)
return;
Agent *agent = (static_cast<VrfTable *>(get_table()))->agent();
agent->ConcurrencyCheck();
DBTablePartBase *tpart =
static_cast<DBTablePartition *>(get_table()->GetTablePartition(this));
tpart->Notify(this);

// Enqueue a DB Request to notify the entry, entry should always be
// notified in db::DBTable task context
DBRequest req(DBRequest::DB_ENTRY_NOTIFY);
req.key = GetDBRequestKey();
(static_cast<VrfTable *>(get_table()))->Enqueue(&req);
}

bool VrfEntry::AllRouteTablesEmpty() const {
Expand Down Expand Up @@ -634,9 +635,16 @@ void VrfTable::Input(DBTablePartition *partition, DBClient *client,
VrfEntry *entry = static_cast<VrfEntry *>(partition->Find(key));

if (entry && entry->IsDeleted()) {
OPER_TRACE(Vrf, "VRF pending delete, Ignoring DB operation for ",
entry->GetName());
return;
if (req->oper != DBRequest::DB_ENTRY_NOTIFY) {
OPER_TRACE(Vrf, "VRF pending delete, Ignoring DB operation for ",
entry->GetName());
return;
} else {
// Allow DB Operation for DB Entry Notify, along with
// validation for sub op as ADD_DEL_CHANGE
AgentKey *key = static_cast<AgentKey *>(req->key.get());
assert(key->sub_op_ == AgentKey::ADD_DEL_CHANGE);
}
}

AgentDBTable::Input(partition, client, req);
Expand Down

0 comments on commit 245d635

Please sign in to comment.