Skip to content

Commit

Permalink
Handle duplicate VxLan ID for two different VNs
Browse files Browse the repository at this point in the history
Issue:
------
QFX doesnot handle duplicate VxLan ID for two different
VNs, since OVSDB schema doesnot consider VxLan ID as key
it ends up into commit failures on QFX

Fix:
----
- if VxLan ID for a VN is already in use avoid programming
  it to QFX till it is available
- Added VxLan resource managing infra.
- UT added for the same
- TODO need to handle cyclic change in VxLAN ID

Partial-Bug: 1466731

Committing on behalf of Prabhjot.
Change-Id: I8c05208c788c75b2ced8eb263a5ec8cde23183d1
  • Loading branch information
haripk committed Nov 13, 2015
1 parent e569def commit 6324dfd
Show file tree
Hide file tree
Showing 15 changed files with 494 additions and 23 deletions.
1 change: 1 addition & 0 deletions src/vnsw/agent/ovs_tor_agent/ovsdb_client/SConscript
Original file line number Diff line number Diff line change
Expand Up @@ -35,6 +35,7 @@ libovsdbclient = env.Library('ovsdbclient',
'ovsdb_client_tcp.cc',
'ovsdb_entry.cc',
'ovsdb_object.cc',
'ovsdb_resource_vxlan_id.cc',
'ovsdb_route_data.cc',
'ovsdb_route_peer.cc',
'ovsdb_sandesh.cc',
Expand Down
75 changes: 64 additions & 11 deletions src/vnsw/agent/ovs_tor_agent/ovsdb_client/logical_switch_ovsdb.cc
Original file line number Diff line number Diff line change
Expand Up @@ -26,13 +26,15 @@ LogicalSwitchEntry::LogicalSwitchEntry(OvsdbDBObject *table,
const std::string &name) :
OvsdbDBEntry(table), name_(name), device_name_(), vxlan_id_(0),
mcast_local_row_(NULL), mcast_remote_row_(NULL), tor_ip_(),
mc_flood_entry_(NULL) {
mc_flood_entry_(NULL),
res_vxlan_id_(table->client_idl()->vxlan_table(), this) {
}

LogicalSwitchEntry::LogicalSwitchEntry(OvsdbDBObject *table,
const PhysicalDeviceVn *entry) : OvsdbDBEntry(table),
name_(UuidToString(entry->vn()->GetUuid())), mcast_local_row_(NULL),
mcast_remote_row_(NULL), mc_flood_entry_(NULL) {
mcast_remote_row_(NULL), mc_flood_entry_(NULL),
res_vxlan_id_(table->client_idl()->vxlan_table(), this) {
vxlan_id_ = entry->vxlan_id();
device_name_ = entry->device_display_name();
tor_ip_ = entry->tor_ip();
Expand All @@ -41,7 +43,8 @@ LogicalSwitchEntry::LogicalSwitchEntry(OvsdbDBObject *table,
LogicalSwitchEntry::LogicalSwitchEntry(OvsdbDBObject *table,
const LogicalSwitchEntry *entry) : OvsdbDBEntry(table),
mcast_local_row_(NULL), mcast_remote_row_(NULL),
mc_flood_entry_(NULL) {
mc_flood_entry_(NULL),
res_vxlan_id_(table->client_idl()->vxlan_table(), this) {
name_ = entry->name_;
vxlan_id_ = entry->vxlan_id_;;
device_name_ = entry->device_name_;
Expand All @@ -52,7 +55,8 @@ LogicalSwitchEntry::LogicalSwitchEntry(OvsdbDBObject *table,
struct ovsdb_idl_row *entry) : OvsdbDBEntry(table, entry),
name_(ovsdb_wrapper_logical_switch_name(entry)), device_name_(""),
vxlan_id_(ovsdb_wrapper_logical_switch_tunnel_key(entry)),
mcast_remote_row_(NULL), tor_ip_(), mc_flood_entry_(NULL) {
mcast_remote_row_(NULL), tor_ip_(), mc_flood_entry_(NULL),
res_vxlan_id_(table->client_idl()->vxlan_table(), this) {
}

LogicalSwitchEntry::~LogicalSwitchEntry() {
Expand All @@ -74,9 +78,10 @@ void LogicalSwitchEntry::AddMsg(struct ovsdb_idl_txn *txn) {
// skip add encoding for stale entry
return;
}

struct ovsdb_idl_row *row =
ovsdb_wrapper_add_logical_switch(txn, ovs_entry_, name_.c_str(),
vxlan_id_);
res_vxlan_id_.VxLanId());

// Encode Delete for Old remote multicast entries
DeleteOldMcastRemoteMac();
Expand Down Expand Up @@ -175,6 +180,10 @@ const IpAddress &LogicalSwitchEntry::tor_ip() const {
return tor_ip_;
}

const OvsdbResourceVxLanId &LogicalSwitchEntry::res_vxlan_id() const {
return res_vxlan_id_;
}

bool LogicalSwitchEntry::Sync(DBEntry *db_entry) {
PhysicalDeviceVn *entry =
static_cast<PhysicalDeviceVn *>(db_entry);
Expand Down Expand Up @@ -207,8 +216,11 @@ KSyncEntry *LogicalSwitchEntry::UnresolvedReference() {
// while creating stale entry we should not wait for physical
// switch object since it will not be available till config
// comes up
// for stale entry we should always be able to acquire vxlan id
assert(res_vxlan_id_.AcquireVxLanId((uint32_t)vxlan_id_));
return NULL;
}

PhysicalSwitchTable *p_table = table_->client_idl()->physical_switch_table();
PhysicalSwitchEntry key(p_table, device_name_.c_str());
PhysicalSwitchEntry *p_switch =
Expand All @@ -217,6 +229,12 @@ KSyncEntry *LogicalSwitchEntry::UnresolvedReference() {
return p_switch;
}

bool ret = res_vxlan_id_.AcquireVxLanId((uint32_t)vxlan_id_);
if (!ret) {
// failed to get vxlan-id hold entry in defer state
return KSyncObjectManager::default_defer_entry();
}

// check if physical locator is available
std::string dest_ip = table_->client_idl()->tsn_ip().to_string();
PhysicalLocatorTable *pl_table =
Expand All @@ -240,11 +258,27 @@ bool LogicalSwitchEntry::IsLocalMacsRef() const {
}

void LogicalSwitchEntry::Ack(bool success) {
if (success) {
if (ovs_entry_ != NULL) {
uint32_t active_vxlan_id =
(uint32_t)ovsdb_wrapper_logical_switch_tunnel_key(ovs_entry_);
res_vxlan_id_.set_active_vxlan_id(active_vxlan_id);
} else {
res_vxlan_id_.set_active_vxlan_id(0);
}
}
ReleaseLocatorCreateReference();
OvsdbDBEntry::Ack(success);
}

void LogicalSwitchEntry::TxnDoneNoMessage() {
if (ovs_entry_ != NULL) {
uint32_t active_vxlan_id =
(uint32_t)ovsdb_wrapper_logical_switch_tunnel_key(ovs_entry_);
res_vxlan_id_.set_active_vxlan_id(active_vxlan_id);
} else {
res_vxlan_id_.set_active_vxlan_id(0);
}
ReleaseLocatorCreateReference();
}

Expand Down Expand Up @@ -569,13 +603,19 @@ LogicalSwitchSandeshTask::LogicalSwitchSandeshTask(
if (false == args.Get("name", &name_)) {
name_ = "";
}
int vxlan_id = 0;
if (false == args.Get("vxlan_id", &vxlan_id)) {
vxlan_id = 0;
}
vxlan_id_ = vxlan_id;
}

LogicalSwitchSandeshTask::LogicalSwitchSandeshTask(std::string resp_ctx,
const std::string &ip,
uint32_t port,
const std::string &name) :
OvsdbSandeshTask(resp_ctx, ip, port), name_(name) {
const std::string &name,
uint32_t vxlan_id) :
OvsdbSandeshTask(resp_ctx, ip, port), name_(name), vxlan_id_(vxlan_id) {
}

LogicalSwitchSandeshTask::~LogicalSwitchSandeshTask() {
Expand All @@ -585,16 +625,26 @@ void LogicalSwitchSandeshTask::EncodeArgs(AgentSandeshArguments &args) {
if (!name_.empty()) {
args.Add("name", name_);
}
if (vxlan_id_ != 0) {
args.Add("vxlan_id", vxlan_id_);
}
}

OvsdbSandeshTask::FilterResp
LogicalSwitchSandeshTask::Filter(KSyncEntry *kentry) {
if (!name_.empty()) {
LogicalSwitchEntry *entry = static_cast<LogicalSwitchEntry *>(kentry);
if (entry->name().find(name_) != std::string::npos) {
return FilterAllow;
if (entry->name().find(name_) == std::string::npos) {
return FilterDeny;
}
}
if (vxlan_id_ != 0) {
LogicalSwitchEntry *entry = static_cast<LogicalSwitchEntry *>(kentry);
const OvsdbResourceVxLanId &res = entry->res_vxlan_id();
if (entry->vxlan_id() != vxlan_id_ &&
res.active_vxlan_id() != vxlan_id_) {
return FilterDeny;
}
return FilterDeny;
}
return FilterAllow;
}
Expand All @@ -608,6 +658,9 @@ void LogicalSwitchSandeshTask::UpdateResp(KSyncEntry *kentry,
lentry.set_physical_switch(entry->device_name());
lentry.set_vxlan_id(entry->vxlan_id());
lentry.set_tor_service_node(entry->tor_service_node());
const OvsdbResourceVxLanId &res = entry->res_vxlan_id();
lentry.set_vxlan_id_available(res.VxLanId() != 0);
lentry.set_ovs_vxlan_id(res.active_vxlan_id());
if (entry->IsDeleted() && entry->IsLocalMacsRef()) {
lentry.set_message("Waiting for Local Macs Cleanup");
}
Expand All @@ -632,7 +685,7 @@ void OvsdbLogicalSwitchReq::HandleRequest() const {
LogicalSwitchSandeshTask *task =
new LogicalSwitchSandeshTask(context(), get_session_remote_ip(),
get_session_remote_port(),
get_name());
get_name(), get_vxlan_id());
TaskScheduler *scheduler = TaskScheduler::GetInstance();
scheduler->Enqueue(task);
}
Original file line number Diff line number Diff line change
Expand Up @@ -8,12 +8,14 @@
#include <ovsdb_entry.h>
#include <ovsdb_object.h>
#include <ovsdb_client_idl.h>
#include <ovsdb_resource_vxlan_id.h>

class PhysicalDeviceVn;

namespace OVSDB {
class MulticastMacLocalEntry;
class LogicalSwitchEntry;
class OvsdbResourceVxLanId;

class LogicalSwitchTable : public OvsdbDBObject {
public:
Expand Down Expand Up @@ -82,6 +84,7 @@ class LogicalSwitchEntry : public OvsdbDBEntry {
int64_t vxlan_id() const;
std::string tor_service_node() const;
const IpAddress &tor_ip() const;
const OvsdbResourceVxLanId &res_vxlan_id() const;

bool Sync(DBEntry*);
bool IsLess(const KSyncEntry&) const;
Expand Down Expand Up @@ -122,6 +125,7 @@ class LogicalSwitchEntry : public OvsdbDBEntry {
OvsdbIdlRowList ucast_local_row_list_;
IpAddress tor_ip_;
MulticastMacLocalEntry *mc_flood_entry_;
OvsdbResourceVxLanId res_vxlan_id_;
DISALLOW_COPY_AND_ASSIGN(LogicalSwitchEntry);
};
};
Expand Down
7 changes: 5 additions & 2 deletions src/vnsw/agent/ovs_tor_agent/ovsdb_client/ovsdb.sandesh
Original file line number Diff line number Diff line change
Expand Up @@ -131,8 +131,10 @@ struct OvsdbLogicalSwitchEntry {
2: string name;
3: string physical_switch;
4: i64 vxlan_id;
5: string tor_service_node;
6: optional string message;
5: bool vxlan_id_available;
6: i64 ovs_vxlan_id;
7: string tor_service_node;
8: optional string message;
}

response sandesh OvsdbLogicalSwitchResp {
Expand All @@ -143,6 +145,7 @@ request sandesh OvsdbLogicalSwitchReq {
1: string session_remote_ip;
2: u16 session_remote_port;
3: string name;
4: u32 vxlan_id;
}

struct SandeshLogicalSwitchInfo {
Expand Down
7 changes: 7 additions & 0 deletions src/vnsw/agent/ovs_tor_agent/ovsdb_client/ovsdb_client_idl.cc
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,7 @@ extern "C" {
#include <vm_interface_ksync.h>
#include <vn_ovsdb.h>
#include <vrf_ovsdb.h>
#include <ovsdb_resource_vxlan_id.h>

SandeshTraceBufferPtr OvsdbTraceBuf(SandeshTraceBufferCreate("Ovsdb", 5000));
SandeshTraceBufferPtr OvsdbSMTraceBuf(SandeshTraceBufferCreate("Ovsdb SM", 5000));
Expand All @@ -51,6 +52,7 @@ using OVSDB::MulticastMacLocalOvsdb;
using OVSDB::VrfOvsdbObject;
using OVSDB::VnOvsdbObject;
using OVSDB::ConnectionStateTable;
using OVSDB::OvsdbResourceVxLanIdTable;

namespace OVSDB {
void ovsdb_wrapper_idl_callback(void *idl_base, int op,
Expand Down Expand Up @@ -151,6 +153,7 @@ OvsdbClientIdl::OvsdbClientIdl(OvsdbClientSession *session, Agent *agent,
callback_[i] = NULL;
}
route_peer_.reset(manager->Allocate(session_->remote_ip()));
vxlan_table_.reset(new OvsdbResourceVxLanIdTable());
vm_interface_table_.reset(new VMInterfaceKSyncObject(this,
(DBTable *)agent->interface_table()));
physical_switch_table_.reset(new PhysicalSwitchTable(this));
Expand Down Expand Up @@ -378,6 +381,10 @@ VnOvsdbObject *OvsdbClientIdl::vn_ovsdb() {
return vn_ovsdb_.get();
}

OvsdbResourceVxLanIdTable *OvsdbClientIdl::vxlan_table() {
return vxlan_table_.get();
}

bool OvsdbClientIdl::IsKeepAliveTimerActive() {
return !keepalive_timer_->cancelled();
}
Expand Down
3 changes: 3 additions & 0 deletions src/vnsw/agent/ovs_tor_agent/ovsdb_client/ovsdb_client_idl.h
Original file line number Diff line number Diff line change
Expand Up @@ -49,6 +49,7 @@ class VrfOvsdbObject;
class VnOvsdbObject;
class OvsdbEntryBase;
class ConnectionStateTable;
class OvsdbResourceVxLanIdTable;

class OvsdbClientIdl;
typedef boost::intrusive_ptr<OvsdbClientIdl> OvsdbClientIdlPtr;
Expand Down Expand Up @@ -156,6 +157,7 @@ class OvsdbClientIdl {
MulticastMacLocalOvsdb *multicast_mac_local_ovsdb();
VrfOvsdbObject *vrf_ovsdb();
VnOvsdbObject *vn_ovsdb();
OvsdbResourceVxLanIdTable *vxlan_table();

// Used by Test case
bool IsKeepAliveTimerActive();
Expand Down Expand Up @@ -214,6 +216,7 @@ class OvsdbClientIdl {
std::auto_ptr<MulticastMacLocalOvsdb> multicast_mac_local_ovsdb_;
std::auto_ptr<VrfOvsdbObject> vrf_ovsdb_;
std::auto_ptr<VnOvsdbObject> vn_ovsdb_;
std::auto_ptr<OvsdbResourceVxLanIdTable> vxlan_table_;
DISALLOW_COPY_AND_ASSIGN(OvsdbClientIdl);
};
}; // namespace OVSDB
Expand Down
6 changes: 1 addition & 5 deletions src/vnsw/agent/ovs_tor_agent/ovsdb_client/ovsdb_object.cc
Original file line number Diff line number Diff line change
Expand Up @@ -20,13 +20,9 @@ OvsdbObject::OvsdbObject(OvsdbClientIdl *idl) : KSyncObject(),
OvsdbObject::~OvsdbObject() {
}

bool OvsdbObject::IsActiveEntry(KSyncEntry *entry) {
return (entry->GetState() != KSyncEntry::TEMP && !entry->IsDeleted());
}

KSyncEntry *OvsdbObject::FindActiveEntry(KSyncEntry *key) {
KSyncEntry *entry = Find(key);
if (entry != NULL && IsActiveEntry(entry)) {
if (entry != NULL && entry->IsActive()) {
return entry;
}
return NULL;
Expand Down
1 change: 0 additions & 1 deletion src/vnsw/agent/ovs_tor_agent/ovsdb_client/ovsdb_object.h
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,6 @@ class OvsdbObject : public KSyncObject {
OvsdbObject(OvsdbClientIdl *idl);
virtual ~OvsdbObject();

bool IsActiveEntry(KSyncEntry *entry);
KSyncEntry *FindActiveEntry(KSyncEntry *key);
// Trigger delete of object table
void DeleteTable(void);
Expand Down

0 comments on commit 6324dfd

Please sign in to comment.