diff --git a/src/vnsw/agent/ovs_tor_agent/ovsdb_client/logical_switch_ovsdb.cc b/src/vnsw/agent/ovs_tor_agent/ovsdb_client/logical_switch_ovsdb.cc index fc7b8260792..270b162ae48 100644 --- a/src/vnsw/agent/ovs_tor_agent/ovsdb_client/logical_switch_ovsdb.cc +++ b/src/vnsw/agent/ovs_tor_agent/ovsdb_client/logical_switch_ovsdb.cc @@ -350,6 +350,10 @@ bool LogicalSwitchEntry::ProcessDeleteOvsReqTask::Run() { entry->TriggerDeleteAdd(); } + // on task completion reset intrusive pointer in context of task itself + // rather than processing it in the Task destructor, since in case of + // task completion task destructor will be called in context of scheduler + entry_ = NULL; return true; } diff --git a/src/vnsw/agent/ovs_tor_agent/ovsdb_client/ovsdb_client_idl.cc b/src/vnsw/agent/ovs_tor_agent/ovsdb_client/ovsdb_client_idl.cc index 821d3db6152..4de4f4be1d2 100644 --- a/src/vnsw/agent/ovs_tor_agent/ovsdb_client/ovsdb_client_idl.cc +++ b/src/vnsw/agent/ovs_tor_agent/ovsdb_client/ovsdb_client_idl.cc @@ -287,6 +287,7 @@ bool OvsdbClientIdl::ProcessMessage(OvsdbMsg *msg) { struct ovsdb_idl_txn *OvsdbClientIdl::CreateTxn(OvsdbEntryBase *entry, KSyncEntry::KSyncEvent ack_event) { + assert(ConcurrencyCheck()); if (deleted_) { // Don't create new transactions for deleted idl. return NULL; @@ -317,6 +318,7 @@ struct ovsdb_idl_txn *OvsdbClientIdl::CreateTxn(OvsdbEntryBase *entry, struct ovsdb_idl_txn *OvsdbClientIdl::CreateBulkTxn(OvsdbEntryBase *entry, KSyncEntry::KSyncEvent ack_event) { + assert(ConcurrencyCheck()); if (deleted_) { // Don't create new transactions for deleted idl. return NULL; @@ -347,6 +349,7 @@ struct ovsdb_idl_txn *OvsdbClientIdl::CreateBulkTxn(OvsdbEntryBase *entry, bool OvsdbClientIdl::EncodeSendTxn(struct ovsdb_idl_txn *txn, OvsdbEntryBase *skip_entry) { + assert(ConcurrencyCheck()); // return false to wait for bulk txn to complete if (txn == bulk_txn_) { return false; @@ -374,6 +377,7 @@ bool OvsdbClientIdl::EncodeSendTxn(struct ovsdb_idl_txn *txn, } void OvsdbClientIdl::DeleteTxn(struct ovsdb_idl_txn *txn) { + assert(ConcurrencyCheck()); pending_txn_.erase(txn); // third party code and handle only one txn at a time, // if there is a pending bulk entry encode and send before @@ -577,6 +581,32 @@ uint64_t OvsdbClientIdl::pending_send_msg_count() const { return pending_send_msgs_.size(); } +bool OvsdbClientIdl::ConcurrencyCheck() const { + Task *current = Task::Running(); + static int ksync_task_id = -1; + static int db_task_id = -1; + + if (ksync_task_id == -1) + ksync_task_id = agent_->task_scheduler()->GetTaskId("Agent::KSync"); + + if (db_task_id == -1) + db_task_id = agent_->task_scheduler()->GetTaskId("db::DBTable"); + + if (current == NULL) { + return session_->TestConcurrencyAllow(); + } + + if (current->GetTaskId() == ksync_task_id) { + return true; + } + + if (current->GetTaskId() == db_task_id) { + return true; + } + + return false; +} + void OvsdbClientIdl::ConnectOperDB() { OVSDB_SESSION_TRACE(Trace, session_, "Received Monitor Response connecting to OperDb"); diff --git a/src/vnsw/agent/ovs_tor_agent/ovsdb_client/ovsdb_client_idl.h b/src/vnsw/agent/ovs_tor_agent/ovsdb_client/ovsdb_client_idl.h index cbff436ea32..6435f7c233f 100644 --- a/src/vnsw/agent/ovs_tor_agent/ovsdb_client/ovsdb_client_idl.h +++ b/src/vnsw/agent/ovs_tor_agent/ovsdb_client/ovsdb_client_idl.h @@ -181,6 +181,10 @@ class OvsdbClientIdl { uint64_t pending_txn_count() const; uint64_t pending_send_msg_count() const; + // Concurrency Check to validate all idl transactions happen only in + // db::DBTable or Agent::KSync task context + bool ConcurrencyCheck() const; + private: friend void ovsdb_wrapper_idl_callback(void *, int, struct ovsdb_idl_row *); friend void ovsdb_wrapper_idl_txn_ack(void *, struct ovsdb_idl_txn *); diff --git a/src/vnsw/agent/ovs_tor_agent/ovsdb_client/ovsdb_client_session.h b/src/vnsw/agent/ovs_tor_agent/ovsdb_client/ovsdb_client_session.h index 98efbfb7750..66b6ae6590f 100644 --- a/src/vnsw/agent/ovs_tor_agent/ovsdb_client/ovsdb_client_session.h +++ b/src/vnsw/agent/ovs_tor_agent/ovsdb_client/ovsdb_client_session.h @@ -56,6 +56,9 @@ class OvsdbClientSession { void AddSessionInfo(SandeshOvsdbClientSession &session); + // UT overrides this to allow concurrency check on NULL task + virtual bool TestConcurrencyAllow() { return false; } + protected: // ovsdb io task ID. static int ovsdb_io_task_id_; diff --git a/src/vnsw/agent/ovs_tor_agent/ovsdb_client/test/test_ovs_agent_init.h b/src/vnsw/agent/ovs_tor_agent/ovsdb_client/test/test_ovs_agent_init.h index 3130707fc3f..474081100ff 100644 --- a/src/vnsw/agent/ovs_tor_agent/ovsdb_client/test/test_ovs_agent_init.h +++ b/src/vnsw/agent/ovs_tor_agent/ovsdb_client/test/test_ovs_agent_init.h @@ -33,6 +33,8 @@ class OvsdbClientTcpSessionTest : public OvsdbClientTcpSession { TcpServer *server, Socket *sock, bool async_ready = true); virtual ~OvsdbClientTcpSessionTest(); + + virtual bool TestConcurrencyAllow() { return true; } }; class OvsdbClientTcpTest : public OvsdbClientTcp {