Skip to content

Commit

Permalink
Merge "* If VRF for mirror ACL is absent, retry mirror add once vrf i…
Browse files Browse the repository at this point in the history
…s created. -Test case for same Closes-bug:#1527489"
  • Loading branch information
Zuul authored and opencontrail-ci-admin committed Jan 13, 2016
2 parents f9bdc2e + 43e800e commit 78c80bb
Show file tree
Hide file tree
Showing 5 changed files with 335 additions and 16 deletions.
167 changes: 153 additions & 14 deletions src/vnsw/agent/oper/mirror_table.cc
Expand Up @@ -54,7 +54,6 @@ DBEntry *MirrorTable::Add(const DBRequest *req) {
MirrorEntry *mirror_entry = new MirrorEntry(key->analyzer_name_);
//Get Mirror NH
OnChange(mirror_entry, req);
LOG(DEBUG, "Mirror Add");
return mirror_entry;
}

Expand All @@ -63,24 +62,139 @@ bool MirrorTable::OnChange(DBEntry *entry, const DBRequest *req) {
MirrorEntry *mirror_entry = static_cast<MirrorEntry *>(entry);
MirrorEntryData *data = static_cast<MirrorEntryData *>(req->data.get());

MirrorNHKey nh_key(data->vrf_name_, data->sip_, data->sport_,
data->dip_, data->dport_);
mirror_entry->vrf_name_ = data->vrf_name_;
mirror_entry->sip_ = data->sip_;
mirror_entry->sport_ = data->sport_;
mirror_entry->dip_ = data->dip_;
mirror_entry->dport_ = data->dport_;

DBRequest nh_req;
nh_req.oper = DBRequest::DB_ENTRY_ADD_CHANGE;
MirrorNHKey *nh_key = new MirrorNHKey(data->vrf_name_, data->sip_,
data->sport_, data->dip_, data->dport_);
nh_req.key.reset(nh_key);
nh_req.data.reset(NULL);
agent()->nexthop_table()->Process(nh_req);

VrfKey key(data->vrf_name_);
VrfEntry *vrf =
static_cast<VrfEntry *>(agent()->vrf_table()->FindActiveEntry(&key));

NextHop *nh = static_cast<NextHop *>
(Agent::GetInstance()->nexthop_table()->FindActiveEntry(&nh_key));
assert(nh);
(agent()->nexthop_table()->FindActiveEntry(nh_key));
if (nh == NULL || vrf == NULL) {
//Make the mirror NH point to discard
//and change the nexthop once the VRF is
//available
AddUnresolved(mirror_entry);
DiscardNH key;
nh = static_cast<NextHop *>
(agent()->nexthop_table()->FindActiveEntry(&key));
} else {
AddResolvedVrfMirrorEntry(mirror_entry);
}

if (mirror_entry->nh_ != nh) {
mirror_entry->nh_ = nh;
mirror_entry->sip_ = data->sip_;
mirror_entry->sport_ = data->sport_;
mirror_entry->dip_ = data->dip_;
mirror_entry->dport_ = data->dport_;
mirror_entry->vrf_ = Agent::GetInstance()->vrf_table()->FindVrfFromName(data->vrf_name_);
mirror_entry->vrf_ =
agent()->vrf_table()->FindVrfFromName(data->vrf_name_);
ret = true;
}
return ret;
}

bool MirrorTable::Delete(DBEntry *entry, const DBRequest *request) {
MirrorEntry *mirror_entry = static_cast<MirrorEntry *>(entry);
RemoveUnresolved(mirror_entry);
DeleteResolvedVrfMirrorEntry(mirror_entry);
return true;
}

void MirrorTable::Add(VrfMirrorEntryList &vrf_entry_map, MirrorEntry *entry) {
VrfMirrorEntryList::iterator it = vrf_entry_map.find(entry->vrf_name_);

if (it != vrf_entry_map.end()) {
MirrorEntryList::const_iterator list_it = it->second.begin();
for (; list_it != it->second.end(); list_it++) {
if (*list_it == entry) {
//Entry already present
return;
}
}
it->second.push_back(entry);
return;
}

MirrorEntryList list;
list.push_back(entry);
vrf_entry_map.insert(VrfMirrorEntry(entry->vrf_name_, list));
}

void MirrorTable::Delete(VrfMirrorEntryList &list, MirrorEntry *entry) {
VrfMirrorEntryList::iterator it = list.find(entry->vrf_name_);
if (it == list.end()) {
return;
}

MirrorEntryList::iterator list_it = it->second.begin();
for(;list_it != it->second.end(); list_it++) {
if (*list_it == entry) {
it->second.erase(list_it);
break;
}
}
}

void MirrorTable::ResyncMirrorEntry(VrfMirrorEntryList &list,
const VrfEntry *vrf) {
VrfMirrorEntryList::iterator it = list.find(vrf->GetName());
if (it == list.end()) {
return;
}

MirrorEntryList::iterator list_it = it->second.begin();
for(;list_it != it->second.end(); list_it++) {
DBRequest req;
req.oper = DBRequest::DB_ENTRY_ADD_CHANGE;

MirrorEntryKey *key = new MirrorEntryKey((*list_it)->GetAnalyzerName());
key->sub_op_ = AgentKey::RESYNC;
MirrorEntryData *data = new MirrorEntryData((*list_it)->vrf_name(),
*((*list_it)->GetSip()),
(*list_it)->GetSPort(),
*((*list_it)->GetDip()),
(*list_it)->GetDPort());
req.key.reset(key);
req.data.reset(data);
Enqueue(&req);
}
list.erase(it);
}

void MirrorTable::AddUnresolved(MirrorEntry *entry) {
Add(unresolved_entry_list_, entry);
}

void MirrorTable::RemoveUnresolved(MirrorEntry *entry) {
Delete(unresolved_entry_list_, entry);
}

void MirrorTable::AddResolvedVrfMirrorEntry(MirrorEntry *entry) {
Add(resolved_entry_list_, entry);
}

void MirrorTable::DeleteResolvedVrfMirrorEntry(MirrorEntry *entry) {
Delete(resolved_entry_list_, entry);
}

void MirrorTable::ResyncResolvedMirrorEntry(const VrfEntry *vrf) {
ResyncMirrorEntry(resolved_entry_list_, vrf);
}

void MirrorTable::ResyncUnresolvedMirrorEntry(const VrfEntry *vrf) {
ResyncMirrorEntry(unresolved_entry_list_, vrf);
}

void MirrorTable::AddMirrorEntry(const std::string &analyzer_name,
const std::string &vrf_name,
const Ip4Address &sip, uint16_t sport,
Expand All @@ -93,7 +207,7 @@ void MirrorTable::AddMirrorEntry(const std::string &analyzer_name,
MirrorNHKey *nh_key = new MirrorNHKey(vrf_name, sip, sport, dip, dport);
req.key.reset(nh_key);
req.data.reset(NULL);
Agent::GetInstance()->nexthop_table()->Enqueue(&req);
mirror_table_->agent()->nexthop_table()->Enqueue(&req);

req.oper = DBRequest::DB_ENTRY_ADD_CHANGE;
MirrorEntryKey *key = new MirrorEntryKey(analyzer_name);
Expand Down Expand Up @@ -124,6 +238,27 @@ DBTableBase *MirrorTable::CreateTable(DB *db, const std::string &name) {
return mirror_table_;
};

void MirrorTable::Initialize() {
VrfListenerInit();
}

void MirrorTable::VrfListenerInit() {
vrf_listener_id_ = agent()->vrf_table()->
Register(boost::bind(&MirrorTable::VrfNotify,
this, _1, _2));
}

void MirrorTable::VrfNotify(DBTablePartBase *base, DBEntryBase *entry) {
const VrfEntry *vrf = static_cast<VrfEntry *>(entry);
if (vrf->IsDeleted()) {
//VRF is getting deleted remove all the mirror nexthop
ResyncResolvedMirrorEntry(vrf);
return;
}

ResyncUnresolvedMirrorEntry(vrf);
}

void MirrorTable::ReadHandler(const boost::system::error_code &ec,
size_t bytes_transferred) {

Expand All @@ -142,7 +277,7 @@ void MirrorTable::ReadHandler(const boost::system::error_code &ec,
void MirrorTable::MirrorSockInit(void) {
EventManager *event_mgr;

event_mgr = Agent::GetInstance()->event_manager();
event_mgr = agent()->event_manager();
boost::asio::io_service &io = *event_mgr->io_service();
ip::udp::endpoint ep(ip::udp::v4(), 0);

Expand All @@ -157,7 +292,7 @@ void MirrorTable::MirrorSockInit(void) {

ip::udp::endpoint sock_ep = udp_sock_->local_endpoint(ec);
assert(ec.value() == 0);
Agent::GetInstance()->set_mirror_port(sock_ep.port());
agent()->set_mirror_port(sock_ep.port());

udp_sock_->async_receive(boost::asio::buffer(rx_buff_, sizeof(rx_buff_)),
boost::bind(&MirrorTable::ReadHandler, this,
Expand All @@ -166,7 +301,11 @@ void MirrorTable::MirrorSockInit(void) {
}

VrfEntry *MirrorTable::FindVrfEntry(const string &vrf_name) const {
return Agent::GetInstance()->vrf_table()->FindVrfFromName(vrf_name);
return agent()->vrf_table()->FindVrfFromName(vrf_name);
}

void MirrorTable::Shutdown() {
agent()->vrf_table()->Unregister(vrf_listener_id_);
}

uint32_t MirrorEntry::vrf_id() const {
Expand Down
31 changes: 29 additions & 2 deletions src/vnsw/agent/oper/mirror_table.h
Expand Up @@ -31,7 +31,8 @@ struct MirrorEntryData : public AgentData {
class MirrorEntry : AgentRefCount<MirrorEntry>, public AgentDBEntry {
public:
MirrorEntry(std::string analyzer_name) :
analyzer_name_(analyzer_name), vrf_(NULL, this), nh_(NULL) { };
analyzer_name_(analyzer_name), vrf_(NULL, this), nh_(NULL),
vrf_name_("") { };
virtual ~MirrorEntry() { };

virtual bool IsLess(const DBEntry &rhs) const;
Expand All @@ -55,6 +56,7 @@ class MirrorEntry : AgentRefCount<MirrorEntry>, public AgentDBEntry {
const Ip4Address *GetDip() const {return &dip_;}
uint16_t GetDPort() const {return dport_;}
const NextHop *GetNH() const {return nh_.get();}
const std::string vrf_name() const {return vrf_name_;}

private:
std::string analyzer_name_;
Expand All @@ -64,12 +66,17 @@ class MirrorEntry : AgentRefCount<MirrorEntry>, public AgentDBEntry {
Ip4Address dip_;
uint16_t dport_;
NextHopRef nh_;
std::string vrf_name_;
friend class MirrorTable;
};

class MirrorTable : public AgentDBTable {
public:
const static unsigned bufLen = 512;
typedef std::vector<MirrorEntry *> MirrorEntryList;
typedef std::map<std::string , MirrorEntryList> VrfMirrorEntryList;
typedef std::pair<std::string , MirrorEntryList> VrfMirrorEntry;

MirrorTable(DB *db, const std::string &name) : AgentDBTable(db, name) {
}
virtual ~MirrorTable();
Expand All @@ -79,7 +86,11 @@ class MirrorTable : public AgentDBTable {

virtual DBEntry *Add(const DBRequest *req);
virtual bool OnChange(DBEntry *entry, const DBRequest *req);
virtual bool Delete(DBEntry *entry, const DBRequest *request) { return true; }
virtual bool Delete(DBEntry *entry, const DBRequest *request);
virtual bool Resync(DBEntry *entry, const DBRequest *req) {
bool ret = OnChange(entry, req);
return ret;
}
virtual AgentSandeshPtr GetAgentSandesh(const AgentSandeshArguments *args,
const std::string &context);
VrfEntry *FindVrfEntry(const std::string &vrf_name) const;
Expand All @@ -93,10 +104,26 @@ class MirrorTable : public AgentDBTable {
static MirrorTable *GetInstance() {return mirror_table_;}
void MirrorSockInit(void);
void ReadHandler(const boost::system::error_code& error, size_t bytes);
void AddUnresolved(MirrorEntry *entry);
void RemoveUnresolved(MirrorEntry *entry);
void AddResolvedVrfMirrorEntry(MirrorEntry *entry);
void DeleteResolvedVrfMirrorEntry(MirrorEntry *entry);
void ResyncMirrorEntry(VrfMirrorEntryList &list, const VrfEntry *vrf);
void ResyncResolvedMirrorEntry(const VrfEntry *vrf);
void ResyncUnresolvedMirrorEntry(const VrfEntry *vrf);
void Add(VrfMirrorEntryList &vrf_entry_map, MirrorEntry *entry);
void Delete(VrfMirrorEntryList &vrf_entry_map, MirrorEntry *entry);
void VrfListenerInit();
void VrfNotify(DBTablePartBase *root, DBEntryBase *entry);
void Shutdown();
void Initialize();

private:
std::auto_ptr<boost::asio::ip::udp::socket> udp_sock_;
static MirrorTable *mirror_table_;
char rx_buff_[bufLen];
VrfMirrorEntryList unresolved_entry_list_;
VrfMirrorEntryList resolved_entry_list_;
DBTableBase::ListenerId vrf_listener_id_;
};
#endif
5 changes: 5 additions & 0 deletions src/vnsw/agent/oper/nexthop.cc
Expand Up @@ -865,6 +865,11 @@ void TunnelNH::SendObjectLog(const NextHopTable *table,
// Mirror NH routines
/////////////////////////////////////////////////////////////////////////////
bool MirrorNH::CanAdd() const {
if (vrf_ == NULL) {
LOG(ERROR, "Invalid VRF in mirror NH");
return false;
}

return true;
}

Expand Down
4 changes: 4 additions & 0 deletions src/vnsw/agent/oper/operdb_init.cc
Expand Up @@ -157,6 +157,7 @@ void OperDB::CreateDBTables(DB *db) {
assert(mirror_table);
agent_->set_mirror_table(mirror_table);
mirror_table->set_agent(agent_);
mirror_table->Initialize();

VrfAssignTable *vassign_table = static_cast<VrfAssignTable *>
(db->CreateTable("db.vrf_assign.0"));
Expand Down Expand Up @@ -302,6 +303,9 @@ void OperDB::Shutdown() {
route_preference_module_->Shutdown();
domain_config_->Terminate();
vrouter_.reset();
if (agent()->mirror_table()) {
agent()->mirror_table()->Shutdown();
}
}

void OperDB::DeleteRoutes() {
Expand Down

0 comments on commit 78c80bb

Please sign in to comment.