Skip to content

Commit

Permalink
ToR Agent Performance - monitor request
Browse files Browse the repository at this point in the history
Issue:
------
During initial response for monitor request, we end up
generating too many partial update for Physical port
entries causing lots of unneccessary processing on half
baked data. resulting in bad performance.

Fix:
----
Delay Creation of Physical Port entries, to be done
after processing of initial response to monitor request
is complete. This avoids processing triggers for partial
updates on physical port entries. Once we unable physical
port creation it will create physical port and stale
entries for vlan port bindings with completed information.

Partial-Bug: #1456284
Change-Id: I03984ac9749cea6197feb1f8c43c87cdfe48833d
(cherry picked from commit 06b82cb)
  • Loading branch information
Prabhjot Singh Sethi committed Jun 1, 2015
1 parent b3f67b3 commit df3d055
Show file tree
Hide file tree
Showing 3 changed files with 70 additions and 31 deletions.
5 changes: 5 additions & 0 deletions src/vnsw/agent/ovs_tor_agent/ovsdb_client/ovsdb_client_idl.cc
Expand Up @@ -259,6 +259,11 @@ bool OvsdbClientIdl::ProcessMessage(OvsdbMsg *msg) {
// after processing the response to monitor request
// connect to oper db.
if (connect_oper_db) {
// enable physical port updation, before connect to
// Oper DB, to allow creation of stale entries for
// vlan port bindings.
physical_switch_table_->StartUpdatePorts();

ConnectOperDB();
}
}
Expand Down
78 changes: 48 additions & 30 deletions src/vnsw/agent/ovs_tor_agent/ovsdb_client/physical_switch_ovsdb.cc
Expand Up @@ -78,7 +78,7 @@ void PhysicalSwitchEntry::SendTrace(Trace event) const {
}

PhysicalSwitchTable::PhysicalSwitchTable(OvsdbClientIdl *idl) :
OvsdbObject(idl) {
OvsdbObject(idl), update_ports_(false) {
idl->Register(OvsdbClientIdl::OVSDB_PHYSICAL_SWITCH,
boost::bind(&PhysicalSwitchTable::Notify, this, _1, _2));
}
Expand All @@ -91,18 +91,11 @@ void PhysicalSwitchTable::Notify(OvsdbClientIdl::Op op,
PhysicalSwitchEntry key(this, ovsdb_wrapper_physical_switch_name(row));
PhysicalSwitchEntry *entry =
static_cast<PhysicalSwitchEntry *>(FindActiveEntry(&key));
PhysicalPortTable *p_table = client_idl()->physical_port_table();
if (op == OvsdbClientIdl::OVSDB_DEL) {
if (entry != NULL) {
entry->SendTrace(PhysicalSwitchEntry::DEL);
PhysicalSwitchEntry::InterfaceList::iterator it =
entry->intf_list_.begin();
while (it != entry->intf_list_.end()) {
// trigger del notify for ovs idl row
p_table->DeletePortEntry(*it);
entry->intf_list_.erase(it);
it = entry->intf_list_.begin();
}
entry->ovs_entry_ = NULL;
UpdatePorts(entry);
Delete(entry);
}
} else if (op == OvsdbClientIdl::OVSDB_ADD) {
Expand All @@ -111,26 +104,11 @@ void PhysicalSwitchTable::Notify(OvsdbClientIdl::Op op,
entry->SendTrace(PhysicalSwitchEntry::ADD);
}
entry->set_tunnel_ip(ovsdb_wrapper_physical_switch_tunnel_ip(row));
std::size_t count = ovsdb_wrapper_physical_switch_ports_count(row);
struct ovsdb_idl_row *ports[count];
ovsdb_wrapper_physical_switch_ports(row, ports, count);
PhysicalSwitchEntry::InterfaceList old = entry->intf_list_;
std::size_t i = 0;
entry->intf_list_.clear();
while (i < count) {
entry->intf_list_.insert(ports[i]);
if (old.erase(ports[i]) == 0) {
// if entry was not present eariler trigger Add.
p_table->CreatePortEntry(ports[i], entry->name());
}
i++;
}
PhysicalSwitchEntry::InterfaceList::iterator it = old.begin();
while (it != old.end()) {
// trigger del notify for ovs idl row
p_table->DeletePortEntry(*it);
old.erase(it);
it = old.begin();
entry->ovs_entry_ = row;

// check if we need to skip ports updation
if (update_ports_) {
UpdatePorts(entry);
}
} else {
assert(0);
Expand All @@ -144,6 +122,46 @@ KSyncEntry *PhysicalSwitchTable::Alloc(const KSyncEntry *key, uint32_t index) {
return entry;
}

void PhysicalSwitchTable::StartUpdatePorts() {
if (update_ports_) {
return;
}
update_ports_ = true;
PhysicalSwitchEntry *entry = static_cast<PhysicalSwitchEntry *>(Next(NULL));
while (entry != NULL) {
// Trigger Update Ports to update pending physical port entries
UpdatePorts(entry);
entry = static_cast<PhysicalSwitchEntry *>(Next(entry));
}
}

void PhysicalSwitchTable::UpdatePorts(PhysicalSwitchEntry *entry) {
PhysicalPortTable *p_table = client_idl()->physical_port_table();
PhysicalSwitchEntry::InterfaceList old = entry->intf_list_;
entry->intf_list_.clear();
if (entry->ovs_entry_ != NULL) {
std::size_t count =
ovsdb_wrapper_physical_switch_ports_count(entry->ovs_entry_);
struct ovsdb_idl_row *ports[count];
ovsdb_wrapper_physical_switch_ports(entry->ovs_entry_, ports, count);
std::size_t i = 0;
while (i < count) {
entry->intf_list_.insert(ports[i]);
if (old.erase(ports[i]) == 0) {
// if entry was not present eariler trigger Add.
p_table->CreatePortEntry(ports[i], entry->name());
}
i++;
}
}
PhysicalSwitchEntry::InterfaceList::iterator it = old.begin();
while (it != old.end()) {
// trigger del notify for ovs idl row
p_table->DeletePortEntry(*it);
old.erase(it);
it = old.begin();
}
}

/////////////////////////////////////////////////////////////////////////////
// Sandesh routines
Expand Down
Expand Up @@ -9,14 +9,29 @@
#include <ovsdb_object.h>

namespace OVSDB {
class PhysicalSwitchEntry;

class PhysicalSwitchTable : public OvsdbObject {
public:
PhysicalSwitchTable(OvsdbClientIdl *idl);
virtual ~PhysicalSwitchTable();

void Notify(OvsdbClientIdl::Op, struct ovsdb_idl_row *);
KSyncEntry *Alloc(const KSyncEntry *key, uint32_t index);

void StartUpdatePorts();

private:
void UpdatePorts(PhysicalSwitchEntry *entry);

// By default update ports is set to false to avoid updation
// of physical port entries in ovsdb client context, which
// helps to ignore partial updates on physical ports from
// ovsdb library to avoid useless processing on half cooked
// information. once the initial monitor request processing
// is complete OvsdbClientIdl triggers StartUpdatePorts to
// update the pending ports and allow further ports updation
bool update_ports_;
DISALLOW_COPY_AND_ASSIGN(PhysicalSwitchTable);
};

Expand All @@ -40,10 +55,11 @@ class PhysicalSwitchEntry : public OvsdbEntry {
bool IsLess(const KSyncEntry&) const;
std::string ToString() const {return "Physical Switch";}
KSyncEntry* UnresolvedReference();

private:
friend class PhysicalSwitchTable;
void SendTrace(Trace event) const;

friend class PhysicalSwitchTable;
std::string name_;
Ip4Address tunnel_ip_;
InterfaceList intf_list_;
Expand Down

0 comments on commit df3d055

Please sign in to comment.