diff --git a/src/ifmap/ifmap_agent.sandesh b/src/ifmap/ifmap_agent.sandesh index 2aeffe4f36b..6ba45381255 100644 --- a/src/ifmap/ifmap_agent.sandesh +++ b/src/ifmap/ifmap_agent.sandesh @@ -19,6 +19,7 @@ struct IFMapAgentDefLink { 1: i64 seq_num; 2: string left_node; 3: string right_node; + 4: string metadata; } response sandesh ShowIFMapAgentDefLinkResp { diff --git a/src/ifmap/ifmap_agent_sandesh.cc b/src/ifmap/ifmap_agent_sandesh.cc index 8c6ef05f488..7d24f439878 100644 --- a/src/ifmap/ifmap_agent_sandesh.cc +++ b/src/ifmap/ifmap_agent_sandesh.cc @@ -288,8 +288,8 @@ void ShowIFMapAgentDefLinkReq::HandleRequest() const { ShowIFMapAgentTable::db_->FindTable(IFMAP_AGENT_LINK_DB_NAME)); IFMapAgentLinkTable::LinkDefMap::const_iterator dlist_it; - std::list *ent; - std::list::iterator it; + std::list *ent; + std::list::iterator it; //Get linktables's deferred list const IFMapAgentLinkTable::LinkDefMap &def_list = link_table->GetLinkDefMap(); @@ -306,9 +306,12 @@ void ShowIFMapAgentDefLinkReq::HandleRequest() const { //Iterate the right nodes corresponding to above left node for(it = ent->begin(); it != ent->end(); it++) { IFMapAgentDefLink data; - data.set_seq_num((*it).id_seq_num); - data.set_left_node(temp.id_type + ":" + temp.id_name); - data.set_right_node((*it).id_type + ":" + (*it).id_name); + data.set_seq_num((*it).node_key.id_seq_num); + data.set_left_node(temp.id_type + ":" + + temp.id_name); + data.set_metadata((*it).link_metadata); + data.set_right_node((*it).node_key.id_type + ":" + + (*it).node_key.id_name); list.push_back(data); } } diff --git a/src/ifmap/ifmap_agent_table.cc b/src/ifmap/ifmap_agent_table.cc index 1899191b403..3585f993d49 100644 --- a/src/ifmap/ifmap_agent_table.cc +++ b/src/ifmap/ifmap_agent_table.cc @@ -109,6 +109,7 @@ void IFMapAgentTable::HandlePendingLinks(IFMapNode *node) { iter++; edge = graph_->GetEdge(node, right); assert(edge); + IFMapLink *l = static_cast(edge); // Create both the request keys auto_ptr req_key (new IFMapAgentLinkTable::RequestKey); @@ -119,6 +120,7 @@ void IFMapAgentTable::HandlePendingLinks(IFMapNode *node) { req_key->right_key.id_name = right->name(); req_key->right_key.id_type = right->table()->Typename(); req_key->right_key.id_seq_num = right->GetObject()->sequence_number(); + req_key->metadata = l->metadata(); DBRequest req; req.oper = DBRequest::DB_ENTRY_ADD_CHANGE; @@ -159,14 +161,14 @@ void IFMapAgentTable::NotifyNode(IFMapNode *node) { void IFMapAgentLinkTable::LinkDefAdd(DBRequest *request) { RequestKey *key = static_cast(request->key.get()); - std::list::iterator it; + std::list::iterator it; - std::list *left = NULL; + std::list *left = NULL; LinkDefMap::iterator left_it = link_def_map_.find(key->left_key); if (link_def_map_.end() != left_it) left = left_it->second; - std::list *right = NULL; + std::list *right = NULL; LinkDefMap::iterator right_it = link_def_map_.find(key->right_key); if (link_def_map_.end() != right_it) right = right_it->second; @@ -175,8 +177,8 @@ void IFMapAgentLinkTable::LinkDefAdd(DBRequest *request) { // remove left->right entry if (left) { for(it = left->begin(); it != left->end(); it++) { - if (((*it).id_type == key->right_key.id_type) && - ((*it).id_name == key->right_key.id_name)) { + if (((*it).node_key.id_type == key->right_key.id_type) && + ((*it).node_key.id_name == key->right_key.id_name)) { left->erase(it); break; } @@ -187,8 +189,8 @@ void IFMapAgentLinkTable::LinkDefAdd(DBRequest *request) { // remove right->left entry if (right) { for(it = right->begin(); it != right->end(); it++) { - if (((*it).id_type == key->left_key.id_type) && - ((*it).id_name == key->left_key.id_name)) { + if (((*it).node_key.id_type == key->left_key.id_type) && + ((*it).node_key.id_name == key->left_key.id_name)) { right->erase(it); break; } @@ -205,15 +207,16 @@ void IFMapAgentLinkTable::LinkDefAdd(DBRequest *request) { if (left) { // If list already contains, just update the seq number for(it = left->begin(); it != left->end(); it++) { - if (((*it).id_type == key->right_key.id_type) && - ((*it).id_name == key->right_key.id_name)) { - (*it).id_seq_num = key->right_key.id_seq_num; + if (((*it).node_key.id_type == key->right_key.id_type) && + ((*it).node_key.id_name == key->right_key.id_name)) { + (*it).node_key.id_seq_num = key->right_key.id_seq_num; + (*it).link_metadata = key->metadata; push_left = false; break; } } } else { - left = new std::list(); + left = new std::list(); link_def_map_[key->left_key] = left; } @@ -222,23 +225,30 @@ void IFMapAgentLinkTable::LinkDefAdd(DBRequest *request) { if (right) { // If list already contains, just update the seq number for(it = right->begin(); it != right->end(); it++) { - if (((*it).id_type == key->left_key.id_type) && - ((*it).id_name == key->left_key.id_name)) { - (*it).id_seq_num = key->left_key.id_seq_num; + if (((*it).node_key.id_type == key->left_key.id_type) && + ((*it).node_key.id_name == key->left_key.id_name)) { + (*it).node_key.id_seq_num = key->left_key.id_seq_num; + (*it).link_metadata = key->metadata; push_right = false; break; } } } else { - right = new std::list(); + right = new std::list(); link_def_map_[key->right_key] = right; } // Add it to the end of the list - if (push_left) - left->push_back(key->right_key); - if (push_right) - right->push_back(key->left_key); + struct DeferredNode dn; + dn.link_metadata = key->metadata; + if (push_left) { + dn.node_key = key->right_key; + left->push_back(dn); + } + if (push_right) { + dn.node_key = key->left_key; + right->push_back(dn); + } return; } @@ -449,9 +459,9 @@ void IFMapAgentLinkTable::Input(DBTablePartition *partition, DBClient *client, bool IFMapAgentLinkTable::RemoveDefListEntry (LinkDefMap *map, LinkDefMap::iterator &map_it, - std::list::iterator *list_it) { + std::list::iterator *list_it) { - std::list *list = map_it->second; + std::list *list = map_it->second; if (list_it) { list->erase(*list_it); } @@ -475,36 +485,38 @@ void IFMapAgentLinkTable::EvalDefLink(IFMapTable::RequestKey *key) { if (link_def_map_.end() == link_defmap_it) return; - std::list *left_list = link_defmap_it->second; - std::list::iterator left_it, left_list_entry; + std::list *left_list = link_defmap_it->second; + std::list::iterator left_it, left_list_entry; for(left_it = left_list->begin(); left_it != left_list->end();) { left_list_entry = left_it++; // If link seq is older, dont consider the link. - if ((*left_list_entry).id_seq_num < key->id_seq_num) + if ((*left_list_entry).node_key.id_seq_num < key->id_seq_num) continue; // Skip if right-node is not yet present - if (IFMapAgentTable::TableEntryLookup(database(), &(*left_list_entry)) + if (IFMapAgentTable::TableEntryLookup(database(), + &((*left_list_entry).node_key)) == NULL) { continue; } // left->right entry found defer-list. Find the right->left entry - LinkDefMap::iterator right_defmap_it = link_def_map_.find(*left_list_entry); + LinkDefMap::iterator right_defmap_it = + link_def_map_.find((*left_list_entry).node_key); assert(link_def_map_.end() != right_defmap_it); - std::list *right_list = right_defmap_it->second; - std::list::iterator right_it, right_list_entry; + std::list *right_list = right_defmap_it->second; + std::list::iterator right_it, right_list_entry; for(right_it = right_list->begin(); right_it != right_list->end();) { right_list_entry = right_it++; // If link seq is older, dont consider the link. - if ((*right_list_entry).id_seq_num < key->id_seq_num) + if ((*right_list_entry).node_key.id_seq_num < key->id_seq_num) continue; - if ((*right_list_entry).id_type == key->id_type && - (*right_list_entry).id_name == key->id_name) { + if ((*right_list_entry).node_key.id_type == key->id_type && + (*right_list_entry).node_key.id_name == key->id_name) { RemoveDefListEntry(&link_def_map_, right_defmap_it, &right_list_entry); break; @@ -514,7 +526,8 @@ void IFMapAgentLinkTable::EvalDefLink(IFMapTable::RequestKey *key) { //Remove from deferred list before enqueing auto_ptr req_key (new RequestKey); req_key->left_key = *key; - req_key->right_key = *left_list_entry; + req_key->right_key = (*left_list_entry).node_key; + req_key->metadata = (*left_list_entry).link_metadata; // Dont delete left_list_entry. Its passed in req structure left_list->erase(left_list_entry); @@ -529,8 +542,8 @@ void IFMapAgentLinkTable::EvalDefLink(IFMapTable::RequestKey *key) { } void IFMapAgentLinkTable::DestroyDefLink(uint64_t seq) { - std::list *ent; - std::list::iterator it, list_entry; + std::list *ent; + std::list::iterator it, list_entry; IFMapAgentLinkTable::LinkDefMap::iterator dlist_it, temp; for(dlist_it = link_def_map_.begin(); dlist_it != link_def_map_.end(); ) { @@ -540,7 +553,7 @@ void IFMapAgentLinkTable::DestroyDefLink(uint64_t seq) { list_entry = it++; //Delete the deferred link if it is old seq - if ((*list_entry).id_seq_num < seq) { + if ((*list_entry).node_key.id_seq_num < seq) { if (RemoveDefListEntry(&link_def_map_, temp, &list_entry) == true) { //The list has been deleted. Move to the next map diff --git a/src/ifmap/ifmap_agent_table.h b/src/ifmap/ifmap_agent_table.h index 4752ea7d379..03c9716dbc0 100644 --- a/src/ifmap/ifmap_agent_table.h +++ b/src/ifmap/ifmap_agent_table.h @@ -29,6 +29,7 @@ class IFMapNode; class IFMapAgentTable : public IFMapTable { public: + struct IFMapAgentData : DBRequestData { std::auto_ptrcontent; }; @@ -66,6 +67,11 @@ class IFMapAgentLinkTable : public IFMapLinkTable { std::string metadata; }; + struct DeferredNode { + IFMapTable::RequestKey node_key; + std::string link_metadata; + }; + class comp { public: bool operator()(const IFMapTable::RequestKey &left, @@ -78,7 +84,7 @@ class IFMapAgentLinkTable : public IFMapLinkTable { }; IFMapAgentLinkTable(DB *db, const std::string &name, DBGraph *graph); - typedef std::map *, comp> LinkDefMap; + typedef std::map *, comp> LinkDefMap; virtual void Input(DBTablePartition *partition, DBClient *client, DBRequest *req); void IFMapAgentLinkTable_Init(DB *db, DBGraph *graph); @@ -86,7 +92,7 @@ class IFMapAgentLinkTable : public IFMapLinkTable { DBGraph *graph); void EvalDefLink(IFMapTable::RequestKey *key); bool RemoveDefListEntry(LinkDefMap *map, LinkDefMap::iterator &map_it, - std::list::iterator *list_it); + std::list::iterator *list_it); void DestroyDefLink(uint64_t); const LinkDefMap &GetLinkDefMap() const { return link_def_map_; diff --git a/src/ifmap/ifmap_link_table.cc b/src/ifmap/ifmap_link_table.cc index 0a38098cb46..7ac059511d1 100644 --- a/src/ifmap/ifmap_link_table.cc +++ b/src/ifmap/ifmap_link_table.cc @@ -66,7 +66,6 @@ void IFMapLinkTable::AddLink(DBGraphBase::edge_descriptor edge, } link->SetProperties(edge, left, right, metadata, sequence_number, origin); graph_->SetEdgeProperty(link); - IFMAP_DEBUG(IFMapLinkOperation, "Creating", link->ToString()); } IFMapLink *IFMapLinkTable::FindLink(const string &name) { @@ -80,7 +79,6 @@ IFMapLink *IFMapLinkTable::FindLink(const string &name) { void IFMapLinkTable::DeleteLink(DBGraphEdge *edge) { IFMapLink *link = static_cast(edge); - IFMAP_DEBUG(IFMapLinkOperation, "Deleting", link->ToString()); link->set_last_change_at_to_now(); link->ClearNodes(); DBTablePartition *partition = diff --git a/src/vnsw/agent/cfg/cfg_filter.cc b/src/vnsw/agent/cfg/cfg_filter.cc index 0189db3b9cf..7f2cc0a9354 100644 --- a/src/vnsw/agent/cfg/cfg_filter.cc +++ b/src/vnsw/agent/cfg/cfg_filter.cc @@ -66,23 +66,50 @@ bool CfgFilter::CheckProperty(DBTable *table, IFMapNode *node, DBRequest *req, void CfgFilter::Init() { agent_cfg_->cfg_vm_table()->RegisterPreFilter - (boost::bind(&CfgFilter::CheckProperty, this, _1, _2, _3, + (boost::bind(&CfgFilter::CheckProperty, this, _1, _2, _3, VirtualMachine::ID_PERMS)); agent_cfg_->cfg_vn_table()->RegisterPreFilter - (boost::bind(&CfgFilter::CheckProperty, this, _1, _2, _3, + (boost::bind(&CfgFilter::CheckProperty, this, _1, _2, _3, VirtualNetwork::ID_PERMS)); agent_cfg_->cfg_vm_interface_table()->RegisterPreFilter - (boost::bind(&CfgFilter::CheckProperty, this, _1, _2, _3, + (boost::bind(&CfgFilter::CheckProperty, this, _1, _2, _3, VirtualMachineInterface::ID_PERMS)); agent_cfg_->cfg_acl_table()->RegisterPreFilter - (boost::bind(&CfgFilter::CheckProperty, this, _1, _2, _3, + (boost::bind(&CfgFilter::CheckProperty, this, _1, _2, _3, AccessControlList::ID_PERMS)); + + agent_cfg_->cfg_loadbalancer_table()->RegisterPreFilter + (boost::bind(&CfgFilter::CheckProperty, this, _1, _2, _3, + LoadbalancerPool::ID_PERMS)); + + agent_cfg_->cfg_service_instance_table()->RegisterPreFilter + (boost::bind(&CfgFilter::CheckProperty, this, _1, _2, _3, + ServiceInstance::ID_PERMS)); + + agent_cfg_->cfg_security_group_table()->RegisterPreFilter + (boost::bind(&CfgFilter::CheckProperty, this, _1, _2, _3, + SecurityGroup::ID_PERMS)); + + agent_cfg_->cfg_logical_port_table()->RegisterPreFilter + (boost::bind(&CfgFilter::CheckProperty, this, _1, _2, _3, + LogicalInterface::ID_PERMS)); + + agent_cfg_->cfg_physical_device_table()->RegisterPreFilter + (boost::bind(&CfgFilter::CheckProperty, this, _1, _2, _3, + PhysicalRouter::ID_PERMS)); } void CfgFilter::Shutdown() { agent_cfg_->cfg_vm_table()->RegisterPreFilter(NULL); agent_cfg_->cfg_vn_table()->RegisterPreFilter(NULL); + agent_cfg_->cfg_vm_interface_table()->RegisterPreFilter(NULL); + agent_cfg_->cfg_acl_table()->RegisterPreFilter(NULL); + agent_cfg_->cfg_loadbalancer_table()->RegisterPreFilter(NULL); + agent_cfg_->cfg_service_instance_table()->RegisterPreFilter(NULL); + agent_cfg_->cfg_security_group_table()->RegisterPreFilter(NULL); + agent_cfg_->cfg_logical_port_table()->RegisterPreFilter(NULL); + agent_cfg_->cfg_physical_device_table()->RegisterPreFilter(NULL); } diff --git a/src/vnsw/agent/cfg/cfg_init.cc b/src/vnsw/agent/cfg/cfg_init.cc index c74f11982c5..3cb5ebe3920 100644 --- a/src/vnsw/agent/cfg/cfg_init.cc +++ b/src/vnsw/agent/cfg/cfg_init.cc @@ -128,9 +128,9 @@ void AgentConfig::RegisterDBClients(DB *db) { cfg_listener_->Register("virtual-network-network-ipam", boost::bind(&VnTable::IpamVnSync, _1), -1); cfg_listener_->Register("network-ipam", boost::bind(&DomainConfig::IpamSync, - agent_->domain_config_table(), _1), NetworkIpam::ID_PERMS); + agent_->domain_config_table(), _1), -1); cfg_listener_->Register("virtual-DNS", boost::bind(&DomainConfig::VDnsSync, - agent_->domain_config_table(), _1), VirtualDns::ID_PERMS); + agent_->domain_config_table(), _1), -1); cfg_listener_->Register ("virtual-machine-interface-routing-instance", boost::bind(&InterfaceTable::VmInterfaceVrfSync, @@ -162,6 +162,10 @@ void AgentConfig::RegisterDBClients(DB *db) { ("virtual-network", agent_->vn_table()); cfg_listener_->LinkRegister ("routing-instance", agent_->vrf_table()); + cfg_listener_->LinkRegister + ("security-group", agent_->sg_table()); + cfg_listener_->LinkRegister + ("access-control-list", agent_->acl_table()); cfg_vm_interface_table_ = (static_cast (IFMapTable::FindTable(agent_->db(), "virtual-machine-interface"))); @@ -214,10 +218,25 @@ void AgentConfig::RegisterDBClients(DB *db) { assert(cfg_vm_port_vrf_table_); cfg_route_table_ = (static_cast - (IFMapTable::FindTable(agent_->db(), + (IFMapTable::FindTable(agent_->db(), "interface-route-table"))); assert(cfg_route_table_); + cfg_loadbalancer_table_ = (static_cast + (IFMapTable::FindTable(agent_->db(), + "loadbalancer_pool"))); + assert(cfg_loadbalancer_table_); + + cfg_service_instance_table_ = (static_cast + (IFMapTable::FindTable(agent_->db(), + "service_instance"))); + assert(cfg_service_instance_table_); + + cfg_security_group_table_ = (static_cast + (IFMapTable::FindTable(agent_->db(), + "security_group"))); + assert(cfg_security_group_table_); + cfg_subnet_table_ = (static_cast (IFMapTable::FindTable(agent_->db(), "subnet"))); @@ -228,6 +247,12 @@ void AgentConfig::RegisterDBClients(DB *db) { "logical-interface"))); assert(cfg_logical_port_table_); + cfg_physical_device_table_ = (static_cast + (IFMapTable::FindTable(agent_->db(), + "physical-router"))); + assert(cfg_physical_device_table_); + + cfg_interface_client_->Init(); } diff --git a/src/vnsw/agent/cfg/cfg_init.h b/src/vnsw/agent/cfg/cfg_init.h index d099027623d..91ab06f944d 100644 --- a/src/vnsw/agent/cfg/cfg_init.h +++ b/src/vnsw/agent/cfg/cfg_init.h @@ -65,6 +65,22 @@ class AgentConfig { return cfg_logical_port_table_; } + IFMapAgentTable *cfg_loadbalancer_table() const { + return cfg_loadbalancer_table_; + } + + IFMapAgentTable *cfg_service_instance_table() const { + return cfg_service_instance_table_; + } + + IFMapAgentTable *cfg_security_group_table() const { + return cfg_security_group_table_; + } + + IFMapAgentTable *cfg_physical_device_table() const { + return cfg_physical_device_table_; + } + Agent *agent() const { return agent_; } CfgFilter *cfg_filter() const { return cfg_filter_.get(); } CfgListener *cfg_listener() const { return cfg_listener_.get(); } @@ -118,6 +134,10 @@ class AgentConfig { IFMapAgentTable *cfg_service_template_table_; IFMapAgentTable *cfg_subnet_table_; IFMapAgentTable *cfg_logical_port_table_; + IFMapAgentTable *cfg_loadbalancer_table_; + IFMapAgentTable *cfg_service_instance_table_; + IFMapAgentTable *cfg_security_group_table_; + IFMapAgentTable *cfg_physical_device_table_; DISALLOW_COPY_AND_ASSIGN(AgentConfig); }; diff --git a/src/vnsw/agent/cfg/cfg_listener.cc b/src/vnsw/agent/cfg/cfg_listener.cc index 3b79efa9128..92f1d1440c6 100644 --- a/src/vnsw/agent/cfg/cfg_listener.cc +++ b/src/vnsw/agent/cfg/cfg_listener.cc @@ -66,6 +66,7 @@ void CfgListener::Shutdown() { cfg_listener_id_map_.clear(); } + // Get CfgDBState set for an IFNode CfgDBState *CfgListener::GetCfgDBState(IFMapTable *table, DBEntryBase *dbe, DBTableBase::ListenerId &id) { @@ -78,6 +79,19 @@ CfgDBState *CfgListener::GetCfgDBState(IFMapTable *table, DBEntryBase *dbe, return static_cast(dbe->GetState(table, id)); } + +bool CfgListener::GetCfgDBStateUuid(IFMapNode *node, boost::uuids::uuid &id) { + + DBEntryBase *dbe = static_cast (node); + DBTableBase::ListenerId lid = 0; + CfgDBState *state = GetCfgDBState(node->table(), dbe, lid); + if (!state || (state->uuid_ == boost::uuids::nil_uuid())) + return false; + + id = state->uuid_; + return true; +} + // When traversing graph, check if an IFMapNode can be used. Conditions are, // - The node is not in deleted state // - The node was notified earlier @@ -144,6 +158,11 @@ AgentDBTable* CfgListener::GetOperDBTable(IFMapNode *node) { return NULL; } const CfgTableListenerInfo *info = &loc->second; + + // IF delete operation lets not bother about mandatory fields + if (node->IsDeleted()) + return info->table_; + // Check for presence of ID_PERMS if configured if (info->need_property_id_ >= 0) { const IFMapObject *obj = node->GetObject(); @@ -210,8 +229,8 @@ CfgListener::NodeListenerCb CfgListener::GetCallback(IFMapNode *node) { return info->cb_; } -void CfgListener::LinkNotify(IFMapLink *link, IFMapNode *node, - IFMapNode *peer, CfgDBState *state, +void CfgListener::LinkNotify(IFMapLink *link, IFMapNode *node, IFMapNode *peer, + const string &peer_type, CfgDBState *state, DBTableBase::ListenerId id) { if (node == NULL) { return; @@ -224,23 +243,22 @@ void CfgListener::LinkNotify(IFMapLink *link, IFMapNode *node, // Check if link notifier is registered. If there is no callback // registered for links, use IFNodeToReq iteself AgentDBTable *oper_table = NULL; - // Invoke link notifier only if peer node is known - if (peer) { - oper_table = GetLinkOperDBTable(node); - // Link callback registered - if (oper_table) { - // Skip link notification if node was not notified earlier - if (state == NULL || oper_table->CanNotify(node) == false) - return; + oper_table = GetLinkOperDBTable(node); + // Invoke IFLinkToReq under following conditions, + // - Link notification registered for the object + // - Object is already notified (state is set) + if (oper_table && state != NULL) { + // Skip link notification if node cannot be notified + if (oper_table->CanNotify(node)) { // Link can only result in update to existing entry. So, ADD_CHANGE // is the only operation needed DBRequest req(DBRequest::DB_ENTRY_ADD_CHANGE); - if (oper_table->IFLinkToReq(link, node, peer, req)) { + if (oper_table->IFLinkToReq(link, node, peer_type, peer, req)) { oper_table->Enqueue(&req); } - return; } + return; } oper_table = GetOperDBTable(node); @@ -267,11 +285,13 @@ void CfgListener::LinkListener(DBTablePartBase *partition, DBEntryBase *dbe) { CfgDBState *lstate = NULL; CfgDBState *rstate = NULL; + const IFMapNode::Descriptor &ldescriptor = link->left_id(); IFMapNode *lnode = link->LeftNode(database_); if (lnode) { lstate = GetCfgDBState(lnode->table(), lnode, lid); } + const IFMapNode::Descriptor &rdescriptor = link->right_id(); IFMapNode *rnode = link->RightNode(database_); if (rnode) { rstate = GetCfgDBState(rnode->table(), rnode, rid); @@ -291,14 +311,14 @@ void CfgListener::LinkListener(DBTablePartBase *partition, DBEntryBase *dbe) { // If right node is not notified, notify right followed by left. // Else, notify left followed by right if (lstate != NULL && rstate != NULL) { - LinkNotify(link, lnode, rnode, lstate, lid); - LinkNotify(link, rnode, lnode, rstate, rid); + LinkNotify(link, lnode, rnode, rdescriptor.first, lstate, lid); + LinkNotify(link, rnode, lnode, ldescriptor.first, rstate, rid); } else if (lstate == NULL) { - LinkNotify(link, lnode, rnode, lstate, lid); - LinkNotify(link, rnode, lnode, rstate, rid); + LinkNotify(link, lnode, rnode, rdescriptor.first, lstate, lid); + LinkNotify(link, rnode, lnode, ldescriptor.first, rstate, rid); } else if (rstate == NULL) { - LinkNotify(link, rnode, lnode, rstate, rid); - LinkNotify(link, lnode, rnode, lstate, lid); + LinkNotify(link, rnode, lnode, ldescriptor.first, rstate, rid); + LinkNotify(link, lnode, rnode, rdescriptor.first, lstate, lid); } } @@ -307,6 +327,10 @@ void CfgListener::NodeNotify(AgentDBTable *oper_table, IFMapNode *node) { if (node->IsDeleted()) { req.oper = DBRequest::DB_ENTRY_DELETE; } else { + DBEntryBase *dbe = static_cast (node); + DBTableBase::ListenerId lid = 0; + CfgDBState *state = GetCfgDBState(node->table(), dbe, lid); + oper_table->IFNodeToUuid(node, state->uuid_); req.oper = DBRequest::DB_ENTRY_ADD_CHANGE; } diff --git a/src/vnsw/agent/cfg/cfg_listener.h b/src/vnsw/agent/cfg/cfg_listener.h index 28323b51616..e216b900f4f 100644 --- a/src/vnsw/agent/cfg/cfg_listener.h +++ b/src/vnsw/agent/cfg/cfg_listener.h @@ -13,8 +13,9 @@ class DB; class CfgDBState : public DBState { public: - CfgDBState() : notify_count_(0) { }; - bool notify_count_; + CfgDBState() : notify_count_(0), uuid_(boost::uuids::nil_uuid()) { }; + uint32_t notify_count_; + boost::uuids::uuid uuid_; }; class CfgListener { @@ -67,6 +68,8 @@ class CfgListener { bool SkipNode(IFMapNode *node); bool SkipNode(IFMapNode *node, IFMapAgentTable *table); + bool GetCfgDBStateUuid(IFMapNode *node, boost::uuids::uuid &id); + // Callback invoked for each IFMap neighbor node typedef boost::function multicast_peer_; std::auto_ptr multicast_tor_peer_; std::auto_ptr multicast_tree_builder_peer_; + std::auto_ptr mac_vm_binding_peer_; std::auto_ptr agent_signal_; diff --git a/src/vnsw/agent/cmn/agent_db.cc b/src/vnsw/agent/cmn/agent_db.cc index 8bc345f4546..9222d9fcdb4 100644 --- a/src/vnsw/agent/cmn/agent_db.cc +++ b/src/vnsw/agent/cmn/agent_db.cc @@ -93,6 +93,10 @@ void AgentDBTablePartition::Remove(DBEntryBase *entry) { DBTablePartition::Remove(entry); } +bool AgentDBTable::IFNodeToUuid(IFMapNode *node, boost::uuids::uuid &id) { + return false; +} + void AgentDBTable::Input(DBTablePartition *partition, DBClient *client, DBRequest *req) { AgentKey *key = static_cast(req->key.get()); diff --git a/src/vnsw/agent/cmn/agent_db.h b/src/vnsw/agent/cmn/agent_db.h index 02364b9322b..000f2f20225 100644 --- a/src/vnsw/agent/cmn/agent_db.h +++ b/src/vnsw/agent/cmn/agent_db.h @@ -150,11 +150,14 @@ class AgentDBTable : public DBTable { assert(0); return false; } - virtual bool IFLinkToReq(IFMapLink *link, IFMapNode *node, IFMapNode *peer, + virtual bool IFLinkToReq(IFMapLink *link, IFMapNode *node, + const std::string &peer_name, IFMapNode *peer, DBRequest &req) { assert(0); return false; } + virtual bool IFNodeToUuid(IFMapNode *node, boost::uuids::uuid &id); + virtual DBTablePartition *AllocPartition(int index) { return new AgentDBTablePartition(this, index); }; diff --git a/src/vnsw/agent/filter/acl.cc b/src/vnsw/agent/filter/acl.cc index 72cc52d5a7b..52be7239f01 100644 --- a/src/vnsw/agent/filter/acl.cc +++ b/src/vnsw/agent/filter/acl.cc @@ -16,6 +16,7 @@ #include #include +#include #include #include @@ -313,11 +314,19 @@ static void AclObjectTrace(AgentLogEvent::type event, AclSpec &acl_spec) } } -bool AclTable::IFNodeToReq(IFMapNode *node, DBRequest &req) { +bool AclTable::IFNodeToUuid(IFMapNode *node, boost::uuids::uuid &u) { AccessControlList *cfg_acl = static_cast (node->GetObject()); autogen::IdPermsType id_perms = cfg_acl->id_perms(); - boost::uuids::uuid u; CfgUuidSet(id_perms.uuid.uuid_mslong, id_perms.uuid.uuid_lslong, u); + return true; +} + +bool AclTable::IFNodeToReq(IFMapNode *node, DBRequest &req) { + + AccessControlList *cfg_acl = static_cast (node->GetObject()); + uuid u; + if (agent()->cfg_listener()->GetCfgDBStateUuid(node, u) == false) + return false; // Delete ACL if (req.oper == DBRequest::DB_ENTRY_DELETE) { @@ -406,6 +415,23 @@ bool AclTable::IFNodeToReq(IFMapNode *node, DBRequest &req) { return false; } +bool AclTable::IFLinkToReq(IFMapLink *link, IFMapNode *node, + const std::string &peer_type, IFMapNode *peer, + DBRequest &req) { + if (peer && peer->table() == agent()->cfg()->cfg_vn_table()) { + DBRequest vn_req; + req.oper = DBRequest::DB_ENTRY_ADD_CHANGE; + agent()->vn_table()->IFNodeToReq(peer, vn_req); + } + + if (peer && peer->table() == agent()->cfg()->cfg_sg_table()) { + DBRequest sg_req; + req.oper = DBRequest::DB_ENTRY_ADD_CHANGE; + agent()->sg_table()->IFNodeToReq(peer, sg_req); + } + return false; +} + // ACL methods void AclDBEntry::SetAclEntries(AclEntries &entries) { diff --git a/src/vnsw/agent/filter/acl.h b/src/vnsw/agent/filter/acl.h index 4e946298b27..553cb1dc739 100644 --- a/src/vnsw/agent/filter/acl.h +++ b/src/vnsw/agent/filter/acl.h @@ -145,6 +145,10 @@ class AclTable : public AgentDBTable { virtual bool Delete(DBEntry *entry, const DBRequest *req); virtual bool IFNodeToReq(IFMapNode *node, DBRequest &req); + virtual bool IFNodeToUuid(IFMapNode *node, boost::uuids::uuid &u); + virtual bool IFLinkToReq(IFMapLink *link, IFMapNode *node, + const std::string &peer_type, IFMapNode *peer, + DBRequest &req); static DBTableBase *CreateTable(DB *db, const std::string &name); TrafficAction::Action ConvertActionString(std::string action) const; diff --git a/src/vnsw/agent/kstate/test/test_kstate.cc b/src/vnsw/agent/kstate/test/test_kstate.cc index b42af42e72e..3b921639a3b 100644 --- a/src/vnsw/agent/kstate/test/test_kstate.cc +++ b/src/vnsw/agent/kstate/test/test_kstate.cc @@ -214,7 +214,6 @@ class KStateTest : public ::testing::Test { }; bool KStateTest::ksync_init_; - TEST_F(KStateTest, IfDumpTest) { int if_count = 0; TestIfKState::Init(); @@ -267,7 +266,6 @@ TEST_F(KStateTest, NHDumpTest) { DeletePorts(max_ports); } - TEST_F(KStateTest, NHGetTest) { int nh_count = 0; TestNHKState::Init(); diff --git a/src/vnsw/agent/oper/SConscript b/src/vnsw/agent/oper/SConscript index df003207019..03a1b117544 100644 --- a/src/vnsw/agent/oper/SConscript +++ b/src/vnsw/agent/oper/SConscript @@ -37,7 +37,6 @@ vnswoperdb = env.Library('vnswoperdb', 'loadbalancer_haproxy.cc', 'loadbalancer_properties.cc', 'logical_interface.cc', - 'mac_vm_binding.cc', 'mirror_table.cc', 'mpls.cc', 'multicast.cc', diff --git a/src/vnsw/agent/oper/agent.sandesh b/src/vnsw/agent/oper/agent.sandesh index c21cd4b268e..da594100849 100644 --- a/src/vnsw/agent/oper/agent.sandesh +++ b/src/vnsw/agent/oper/agent.sandesh @@ -233,6 +233,7 @@ struct PathSandeshData { 15: optional string info; 16: optional i32 active_label; 17: optional string flood_dhcp; + 18: optional string vm_name; } struct RouteUcSandeshData { diff --git a/src/vnsw/agent/oper/agent_path.cc b/src/vnsw/agent/oper/agent_path.cc index cb6379e1acc..1316abc8b4a 100644 --- a/src/vnsw/agent/oper/agent_path.cc +++ b/src/vnsw/agent/oper/agent_path.cc @@ -402,12 +402,6 @@ bool EvpnDerivedPathData::AddChangePath(Agent *agent, AgentPath *path, ret = true; } - bool flood_dhcp = reference_path_->flood_dhcp(); - if (evpn_path->flood_dhcp() != flood_dhcp) { - evpn_path->set_flood_dhcp(flood_dhcp); - ret = true; - } - return ret; } @@ -1096,7 +1090,12 @@ void AgentPath::SetSandeshData(PathSandeshData &pdata) const { path_preference_.wait_for_traffic()); pdata.set_path_preference_data(path_preference_data); pdata.set_active_label(GetActiveLabel()); - pdata.set_flood_dhcp(flood_dhcp() ? "true" : "false"); + if (peer()->GetType() == Peer::MAC_VM_BINDING_PEER) { + const MacVmBindingPath *dhcp_path = + static_cast(this); + pdata.set_flood_dhcp(dhcp_path->flood_dhcp() ? "true" : "false"); + pdata.set_vm_name(dhcp_path->vm_interface()->ToString()); + } } void AgentPath::set_local_ecmp_mpls_label(MplsLabel *mpls) { @@ -1170,3 +1169,47 @@ const Ip4Address *AgentPath::NexthopIp(Agent *agent) const { return peer_->NexthopIp(agent, this); } + +MacVmBindingPath::MacVmBindingPath(const Peer *peer) : + AgentPath(peer, NULL) { +} + +bool MacVmBindingPath::IsLess(const AgentPath &r_path) const { + return peer()->IsLess(r_path.peer()); +} + +const NextHop *MacVmBindingPath::ComputeNextHop(Agent *agent) const { + return nexthop(); +} + +AgentPath *MacVmBindingPathData::CreateAgentPath(const Peer *peer, + AgentRoute *rt) const { + const Peer *mac_vm_binding_peer = + dynamic_cast(peer); + assert(mac_vm_binding_peer != NULL); + return (new MacVmBindingPath(mac_vm_binding_peer)); +} + +bool MacVmBindingPathData::AddChangePath(Agent *agent, AgentPath *path, + const AgentRoute *rt) { + bool ret = false; + MacVmBindingPath *dhcp_path = + dynamic_cast(path); + + NextHop *nh = agent->nexthop_table()->discard_nh(); + if (path->ChangeNH(agent, nh) == true) + ret = true; + + bool flood_dhcp = !(vm_intf_->dhcp_enable_config()); + if (dhcp_path->flood_dhcp() != flood_dhcp) { + dhcp_path->set_flood_dhcp(flood_dhcp); + ret = true; + } + + if (dhcp_path->vm_interface() != vm_intf_) { + dhcp_path->set_vm_interface(vm_intf_); + ret = true; + } + + return ret; +} diff --git a/src/vnsw/agent/oper/agent_path.h b/src/vnsw/agent/oper/agent_path.h index 338c1f8b757..1809fbc65a8 100644 --- a/src/vnsw/agent/oper/agent_path.h +++ b/src/vnsw/agent/oper/agent_path.h @@ -628,4 +628,53 @@ class Inet4UnicastInterfaceRoute : public AgentRouteData { DISALLOW_COPY_AND_ASSIGN(Inet4UnicastInterfaceRoute); }; +//MacVmBindingPath is used to store VM interface from which +//this route was added. This helps in retrieving the +//VM using MAC in a VRF. Also it stores the flood dhcp +//flag which is used to decide if DHCP request are to +//be answered by agent or external DHCP server. +class MacVmBindingPath : public AgentPath { +public: + MacVmBindingPath(const Peer *peer); + virtual ~MacVmBindingPath() { } + + virtual const NextHop *ComputeNextHop(Agent *agent) const; + virtual bool IsLess(const AgentPath &right) const; + + //Data get/set + const VmInterface *vm_interface() const { + return dynamic_cast(vm_interface_.get()); + } + void set_vm_interface(const VmInterface *vm_interface) { + vm_interface_ = vm_interface; + } + bool flood_dhcp() const {return flood_dhcp_;} + void set_flood_dhcp(bool flood_dhcp) {flood_dhcp_ = flood_dhcp;} + +private: + //Key parameters for comparision + InterfaceConstRef vm_interface_; + bool flood_dhcp_; + DISALLOW_COPY_AND_ASSIGN(MacVmBindingPath); +}; + +//MacVmBindingPathData is expected to be used only in +//inline calls as it is carrying interface pointer. +//In case request is required key will have to be +//provided. +class MacVmBindingPathData : public AgentRouteData { +public: + MacVmBindingPathData(const VmInterface *vm_intf) : + AgentRouteData(false), vm_intf_(vm_intf) { } + virtual ~MacVmBindingPathData() { } + virtual AgentPath *CreateAgentPath(const Peer *peer, AgentRoute *rt) const; + virtual bool AddChangePath(Agent *agent, AgentPath *path, + const AgentRoute *rt); + virtual std::string ToString() const {return "MacVmBindingPathData";} + +private: + const VmInterface *vm_intf_; + DISALLOW_COPY_AND_ASSIGN(MacVmBindingPathData); +}; + #endif // vnsw_agent_path_hpp diff --git a/src/vnsw/agent/oper/bridge_route.cc b/src/vnsw/agent/oper/bridge_route.cc index dd816e15b84..20a807ea53b 100644 --- a/src/vnsw/agent/oper/bridge_route.cc +++ b/src/vnsw/agent/oper/bridge_route.cc @@ -68,18 +68,10 @@ DBTableBase *BridgeAgentRouteTable::CreateTable(DB *db, return table; } -BridgeRouteEntry *BridgeAgentRouteTable::FindRoute(const Agent *agent, - const string &vrf_name, - const MacAddress &mac) { - VrfEntry *vrf = agent->vrf_table()->FindVrfFromName(vrf_name); - if (vrf == NULL) - return NULL; - - BridgeRouteKey key(agent->local_vm_peer(), vrf_name, mac, 0); - BridgeAgentRouteTable *table = static_cast - (vrf->GetBridgeRouteTable()); +BridgeRouteEntry *BridgeAgentRouteTable::FindRoute(const MacAddress &mac) { + BridgeRouteKey key(agent()->local_vm_peer(), vrf_name(), mac, 0); BridgeRouteEntry *route = - static_cast(table->FindActiveEntry(&key)); + static_cast(FindActiveEntry(&key)); return route; } @@ -135,6 +127,26 @@ void BridgeAgentRouteTable::AddBridgeRoute(const AgentRoute *rt) { BridgeTableProcess(agent(), vrf_name(), req); } +void BridgeAgentRouteTable::AddMacVmBindingRoute(const Peer *peer, + const std::string &vrf_name, + const MacAddress &mac, + const VmInterface *vm_intf) { + DBRequest req(DBRequest::DB_ENTRY_ADD_CHANGE); + req.key.reset(new BridgeRouteKey(peer, vrf_name, mac, 0)); + req.data.reset(new MacVmBindingPathData(vm_intf)); + BridgeTableProcess(agent(), vrf_name, req); +} + +void BridgeAgentRouteTable::DeleteMacVmBindingRoute(const Peer *peer, + const std::string &vrf_name, + const MacAddress &mac, + const VmInterface *vm_intf) { + DBRequest req(DBRequest::DB_ENTRY_DELETE); + req.key.reset(new BridgeRouteKey(peer, vrf_name, mac, 0)); + req.data.reset(new MacVmBindingPathData(vm_intf)); + BridgeTableProcess(agent(), vrf_name, req); +} + void BridgeAgentRouteTable::DeleteBridgeRoute(const AgentRoute *rt) { const EvpnRouteEntry *evpn_rt = static_cast(rt); @@ -203,6 +215,19 @@ void BridgeAgentRouteTable::DeleteBroadcastReq(const Peer *peer, BridgeTableEnqueue(Agent::GetInstance(), &req); } +const VmInterface *BridgeAgentRouteTable::FindVmFromDhcpBinding +(const MacAddress &mac) { + const BridgeRouteEntry *l2_rt = FindRoute(mac); + if (l2_rt == NULL) + return NULL; + + const MacVmBindingPath *dhcp_path = dynamic_cast + (l2_rt->FindMacVmBindingPath()); + if (dhcp_path == NULL) + return NULL; + return dhcp_path->vm_interface(); +} + ///////////////////////////////////////////////////////////////////////////// // BridgeRouteEntry methods ///////////////////////////////////////////////////////////////////////////// @@ -248,12 +273,19 @@ uint32_t BridgeRouteEntry::GetActiveLabel() const { AgentPath *BridgeRouteEntry::FindPathUsingKeyData (const AgentRouteKey *key, const AgentRouteData *data) const { const Peer *peer = key->peer(); - const EvpnPeer * evpn_peer = dynamic_cast(peer); + const EvpnPeer *evpn_peer = dynamic_cast(peer); + if (is_multicast()) + return FindMulticastPathUsingKeyData(key, data); + + if (evpn_peer != NULL) + return FindEvpnPathUsingKeyData(key, data); - //For non multicast route not programmed via EVPN route table, - //use Findpath. - if ((is_multicast() == false) && (evpn_peer == NULL)) - return FindPath(key->peer()); + return FindPath(peer); +} + +AgentPath *BridgeRouteEntry::FindMulticastPathUsingKeyData +(const AgentRouteKey *key, const AgentRouteData *data) const { + assert(is_multicast()); Route::PathList::const_iterator it; for (it = GetPathList().begin(); it != GetPathList().end(); @@ -262,30 +294,45 @@ AgentPath *BridgeRouteEntry::FindPathUsingKeyData if (path->peer() != key->peer()) continue; - if (is_multicast()) { - //Handle multicast peer matching, - //In case of BGP peer also match VXLAN id. - if (path->peer()->GetType() != Peer::BGP_PEER) - return const_cast(path); + //Handle multicast peer matching, + //In case of BGP peer also match VXLAN id. + if (path->peer()->GetType() != Peer::BGP_PEER) + return const_cast(path); - const MulticastRoute *multicast_data = - dynamic_cast(data); - assert(multicast_data != NULL); - if (multicast_data->vxlan_id() != path->vxlan_id()) - continue; - } else { - //Handle mac route added via evpn route. - const EvpnDerivedPath *evpn_path = - dynamic_cast(path); - const EvpnDerivedPathData *evpn_data = - dynamic_cast(data); - assert(evpn_path != NULL); - assert(evpn_data != NULL); - if (evpn_path->ethernet_tag() != evpn_data->ethernet_tag()) - continue; - if (evpn_path->ip_addr() != evpn_data->ip_addr()) - continue; - } + const MulticastRoute *multicast_data = + dynamic_cast(data); + assert(multicast_data != NULL); + if (multicast_data->vxlan_id() != path->vxlan_id()) + continue; + + return const_cast(path); + } + return NULL; +} + +AgentPath *BridgeRouteEntry::FindEvpnPathUsingKeyData +(const AgentRouteKey *key, const AgentRouteData *data) const { + const Peer *peer = key->peer(); + const EvpnPeer *evpn_peer = dynamic_cast(peer); + assert(evpn_peer != NULL); + + Route::PathList::const_iterator it; + for (it = GetPathList().begin(); it != GetPathList().end(); it++) { + const AgentPath *path = static_cast(it.operator->()); + if (path->peer() != key->peer()) + continue; + + //Handle mac route added via evpn route. + const EvpnDerivedPath *evpn_path = + dynamic_cast(path); + const EvpnDerivedPathData *evpn_data = + dynamic_cast(data); + assert(evpn_path != NULL); + assert(evpn_data != NULL); + if (evpn_path->ethernet_tag() != evpn_data->ethernet_tag()) + continue; + if (evpn_path->ip_addr() != evpn_data->ip_addr()) + continue; return const_cast(path); } return NULL; @@ -346,6 +393,11 @@ void BridgeRouteEntry::DeletePathUsingKeyData(const AgentRouteKey *key, } } +const AgentPath *BridgeRouteEntry::FindMacVmBindingPath() const { + Agent *agent = (static_cast (get_table()))->agent(); + return FindPath(agent->mac_vm_binding_peer()); +} + bool BridgeRouteEntry::ReComputePathAdd(AgentPath *path) { if (is_multicast()) { //evaluate add of path diff --git a/src/vnsw/agent/oper/bridge_route.h b/src/vnsw/agent/oper/bridge_route.h index 6ed0425de4e..8b497a60d10 100644 --- a/src/vnsw/agent/oper/bridge_route.h +++ b/src/vnsw/agent/oper/bridge_route.h @@ -22,6 +22,10 @@ class BridgeAgentRouteTable : public AgentRouteTable { static DBTableBase *CreateTable(DB *db, const std::string &name); + void AddMacVmBindingRoute(const Peer *peer, + const std::string &vrf_name, + const MacAddress &mac, + const VmInterface *vm_intf); void AddBridgeRoute(const AgentRoute *rt); static void AddBridgeBroadcastRoute(const Peer *peer, const std::string &vrf_name, @@ -53,9 +57,12 @@ class BridgeAgentRouteTable : public AgentRouteTable { const std::string &vrf_name, uint32_t ethernet_tag); void DeleteBridgeRoute(const AgentRoute *rt); - static BridgeRouteEntry *FindRoute(const Agent *agent, - const std::string &vrf_name, - const MacAddress &mac); + void DeleteMacVmBindingRoute(const Peer *peer, + const std::string &vrf_name, + const MacAddress &mac, + const VmInterface *vm_intf); + const VmInterface *FindVmFromDhcpBinding(const MacAddress &mac); + BridgeRouteEntry *FindRoute(const MacAddress &mac); private: DBTableWalker::WalkId walkid_; @@ -96,9 +103,14 @@ class BridgeRouteEntry : public AgentRoute { bool force_delete); const MacAddress &mac() const {return mac_;} + const AgentPath *FindMacVmBindingPath() const; private: bool ReComputeMulticastPaths(AgentPath *path, bool del); + AgentPath *FindEvpnPathUsingKeyData(const AgentRouteKey *key, + const AgentRouteData *data) const; + AgentPath *FindMulticastPathUsingKeyData(const AgentRouteKey *key, + const AgentRouteData *data) const; MacAddress mac_; DISALLOW_COPY_AND_ASSIGN(BridgeRouteEntry); diff --git a/src/vnsw/agent/oper/evpn_route.cc b/src/vnsw/agent/oper/evpn_route.cc index bc22b6f8ad1..55eac26f392 100644 --- a/src/vnsw/agent/oper/evpn_route.cc +++ b/src/vnsw/agent/oper/evpn_route.cc @@ -12,7 +12,6 @@ #include #include #include -#include #include #include #include @@ -347,41 +346,6 @@ uint32_t EvpnRouteEntry::GetActiveLabel() const { return GetActivePath()->GetActiveLabel(); } -bool EvpnRouteEntry::FloodDhcpRequired() const { - VnEntry *vn = vrf()->vn(); - if (vn) { - IpAddress ip = ip_addr_; - if (ip.is_unspecified()) { - Agent *agent = - (static_cast (get_table()))->agent(); - const Interface *interface = agent->interface_table()-> - mac_vm_binding().FindMacVmBinding(mac_, - GetActivePath()->vxlan_id()); - if (!interface) - return true; - const VmInterface *vm_interface = - static_cast(interface); - return !(vm_interface->dhcp_enable_config()); - } - //VM is TAP VM. - const VnIpam *vn_ipam = vn->GetIpam(ip_addr_); - if (vn_ipam) - return !(vn_ipam->dhcp_enable); - } - return false; -} - -bool EvpnRouteEntry::RecomputeRoutePath(Agent *agent, DBTablePartition *part, - AgentPath *path, AgentRouteData *data) { - bool ret = false; - bool flood_dhcp_required = FloodDhcpRequired(); - - if (path->flood_dhcp() != flood_dhcp_required) { - path->set_flood_dhcp(flood_dhcp_required); - ret = true; - } - return ret; -} ///////////////////////////////////////////////////////////////////////////// // Sandesh related methods ///////////////////////////////////////////////////////////////////////////// diff --git a/src/vnsw/agent/oper/evpn_route.h b/src/vnsw/agent/oper/evpn_route.h index b510b2f5e33..3d2b602568d 100644 --- a/src/vnsw/agent/oper/evpn_route.h +++ b/src/vnsw/agent/oper/evpn_route.h @@ -110,10 +110,6 @@ class EvpnRouteEntry : public AgentRoute { } virtual bool DBEntrySandesh(Sandesh *sresp, bool stale) const; virtual uint32_t GetActiveLabel() const; - virtual bool RecomputeRoutePath(Agent *agent, - DBTablePartition *part, - AgentPath *path, - AgentRouteData *data); const MacAddress &mac() const {return mac_;} const IpAddress &ip_addr() const {return ip_addr_;} @@ -121,7 +117,6 @@ class EvpnRouteEntry : public AgentRoute { uint32_t ethernet_tag() const {return ethernet_tag_;} private: - bool FloodDhcpRequired() const; MacAddress mac_; IpAddress ip_addr_; diff --git a/src/vnsw/agent/oper/ifmap_dependency_manager.cc b/src/vnsw/agent/oper/ifmap_dependency_manager.cc index 6bc20ba61f9..ffe4f23b5c4 100644 --- a/src/vnsw/agent/oper/ifmap_dependency_manager.cc +++ b/src/vnsw/agent/oper/ifmap_dependency_manager.cc @@ -21,39 +21,13 @@ using namespace boost::assign; using namespace std; -class IFMapDependencyManager::IFMapNodeState : public DBState { - public: - IFMapNodeState(IFMapDependencyManager *manager, IFMapNode *node) - : manager_(manager), node_(node), object_(NULL), refcount_(0) { - } - - IFMapNode *node() { return node_; } - DBEntry *object() { return object_; } - void set_object(DBEntry *object) { - object_ = object; - ++refcount_; - } - // Caller decrements refcount. - void clear_object() { - object_ = NULL; - } - - private: - friend void intrusive_ptr_add_ref(IFMapNodeState *state); - friend void intrusive_ptr_release(IFMapNodeState *state); - - IFMapDependencyManager *manager_; - IFMapNode *node_; - DBEntry *object_; - int refcount_; -}; - -void intrusive_ptr_add_ref(IFMapDependencyManager::IFMapNodeState *state) { +void intrusive_ptr_add_ref(IFMapNodeState *state) { ++state->refcount_; } -void intrusive_ptr_release(IFMapDependencyManager::IFMapNodeState *state) { +void intrusive_ptr_release(IFMapNodeState *state) { if (--state->refcount_ == 0) { + assert(state->object_ == NULL); state->manager_->IFMapNodeReset(state->node_); delete state; } @@ -199,7 +173,6 @@ void IFMapDependencyManager::Terminate() { iter != table_map_.end(); ++iter) { DBTable *table = static_cast( database_->FindTable(iter->first)); - DBTable::DBStateClear(table, iter->second); table->Unregister(iter->second); } } @@ -250,7 +223,7 @@ void IFMapDependencyManager::ChangeListAdd(IFMapNode *node) { change_list_.push_back(IFMapNodePtr(state)); } -IFMapDependencyManager::IFMapNodeState * +IFMapNodeState * IFMapDependencyManager::IFMapNodeGet(IFMapNode *node) { IFMapTable *table = node->table(); TableMap::const_iterator loc = table_map_.find(table->name()); @@ -262,15 +235,6 @@ IFMapDependencyManager::IFMapNodeGet(IFMapNode *node) { return state; } -void IFMapDependencyManager::IFMapNodeSet(IFMapNode *node, DBEntry *entry) { - IFMapTable *table = node->table(); - TableMap::const_iterator loc = table_map_.find(table->name()); - assert(loc != table_map_.end()); - IFMapNodeState *state = new IFMapNodeState(this, node); - state->set_object(entry); - node->SetState(table, loc->second, state); -} - void IFMapDependencyManager::IFMapNodeReset(IFMapNode *node) { IFMapTable *table = node->table(); TableMap::const_iterator loc = table_map_.find(table->name()); @@ -286,35 +250,37 @@ void IFMapDependencyManager::IFMapNodeReset(IFMapNode *node) { * responsibility to create a new mapping to IFMapNodeSet (private). */ void IFMapDependencyManager::SetObject(IFMapNode *node, DBEntry *entry) { + IFMapNodeState *state = IFMapNodeGet(node); - assert(entry); - if (state == NULL) { - IFMapNodeSet(node, entry); - } else { + assert(state); + + DBEntry *old_entry = state->object(); + + if (old_entry) + state->clear_object(); + + if (entry) state->set_object(entry); - } + tracker_->NodeEvent(node); trigger_->Set(); } -void IFMapDependencyManager::SetState(IFMapNode *node) { - IFMapNodeState *state = IFMapNodeGet(node); - if (state == NULL) { - IFMapNodeSet(node, NULL); - } -} +IFMapDependencyManager::IFMapNodePtr +IFMapDependencyManager::SetState(IFMapNode *node) { + IFMapTable *table = node->table(); + TableMap::const_iterator loc = table_map_.find(table->name()); + if (loc == table_map_.end()) + return NULL; -/* - * Reset the association between the IFMapNode and the operation DB - * entry. - */ -void IFMapDependencyManager::ResetObject(IFMapNode *node) { - IFMapNodeState *state = IFMapNodeGet(node); - if (state == NULL) { - return; + IFMapNodeState *state = + static_cast(node->GetState(table, loc->second)); + + if (!state) { + state = new IFMapNodeState(this, node); + node->SetState(table, loc->second, state); } - state->clear_object(); - intrusive_ptr_release(state); + return IFMapNodePtr(state); } /* diff --git a/src/vnsw/agent/oper/ifmap_dependency_manager.h b/src/vnsw/agent/oper/ifmap_dependency_manager.h index 724e649f7ec..eb6e6b94af0 100644 --- a/src/vnsw/agent/oper/ifmap_dependency_manager.h +++ b/src/vnsw/agent/oper/ifmap_dependency_manager.h @@ -18,9 +18,48 @@ class DBGraph; class IFMapDependencyTracker; class IFMapNode; class TaskTrigger; +class IFMapDependencyManager; + +//IFMapNodeState is a DBState for IFMapNode with listener ID +// of IFMapDependency Manager. DBState is created when the first +// time SetState is invoked. The caller of SetState gets intrusive +// pointer to IFMapNodeState enabling the caller hold IFMapNode +// till reference is removed. Caller does not need to invoke +// clear state as it gets automatically cleared when references are +// removed. Optionally a DBEntry can be added to this IFMapNodeState +// to trigger the IFMapDependency tracker. +// IFMapDependency tracker also uses the same state, to ensure that +// across the traversal, IFMapNode is not removed. +class IFMapNodeState : public DBState { + public: + IFMapNodeState(IFMapDependencyManager *manager, IFMapNode *node) + : manager_(manager), node_(node), object_(NULL), refcount_(0) { + } + + IFMapNode *node() { return node_; } + DBEntry *object() { return object_; } + void set_object(DBEntry *object) { + object_ = object; + } + + void clear_object() { + object_ = NULL; + } + + private: + friend void intrusive_ptr_add_ref(IFMapNodeState *state); + friend void intrusive_ptr_release(IFMapNodeState *state); + + IFMapDependencyManager *manager_; + IFMapNode *node_; + DBEntry *object_; + int refcount_; +}; + class IFMapDependencyManager { public: + typedef boost::intrusive_ptr IFMapNodePtr; typedef boost::function ChangeEventHandler; IFMapDependencyManager(DB *database, DBGraph *graph); virtual ~IFMapDependencyManager(); @@ -46,16 +85,10 @@ class IFMapDependencyManager { */ void SetObject(IFMapNode *node, DBEntry *entry); - /* - * Reset the association between the IFMapNode and the operation DB - * entry. - */ - void ResetObject(IFMapNode *node); - /* * Add DBState to an IFMapNode */ - void SetState(IFMapNode *node); + IFMapNodePtr SetState(IFMapNode *node); /* * Register a notification callback. */ @@ -66,17 +99,16 @@ class IFMapDependencyManager { */ void Unregister(const std::string &type); + private: /* * IFMapNodeState (DBState) should exist: * a) if the object is set * b) if the entry is on the change list. */ - class IFMapNodeState; friend void intrusive_ptr_add_ref(IFMapNodeState *state); friend void intrusive_ptr_release(IFMapNodeState *state); - typedef boost::intrusive_ptr IFMapNodePtr; typedef std::vector ChangeList; typedef std::map TableMap; typedef std::map EventMap; @@ -87,7 +119,6 @@ class IFMapDependencyManager { void LinkObserver(DBTablePartBase *root, DBEntryBase *db_entry); void ChangeListAdd(IFMapNode *node); - void IFMapNodeSet(IFMapNode *node, DBEntry *object); void IFMapNodeReset(IFMapNode *node); IFMapNodeState *IFMapNodeGet(IFMapNode *node); diff --git a/src/vnsw/agent/oper/inet_unicast_route.cc b/src/vnsw/agent/oper/inet_unicast_route.cc index 86bd892db94..57b3e2d2189 100644 --- a/src/vnsw/agent/oper/inet_unicast_route.cc +++ b/src/vnsw/agent/oper/inet_unicast_route.cc @@ -1170,7 +1170,15 @@ InetUnicastAgentRouteTable::ArpRoute(DBRequest::DBOperation op, const SecurityGroupList &sg) { Agent *agent = Agent::GetInstance(); DBRequest nh_req(DBRequest::DB_ENTRY_ADD_CHANGE); - nh_req.key.reset(new ArpNHKey(nexthop_vrf_name, ip, policy)); + ArpNHKey *nh_key = new ArpNHKey(nexthop_vrf_name, ip, policy); + if (op == DBRequest::DB_ENTRY_DELETE) { + //In case of delete we want to set the + //nexthop as invalid, hence use resync operation + //We dont want the nexthop to created again + //in case of duplicate delete + nh_key->sub_op_ = AgentKey::RESYNC; + } + nh_req.key.reset(nh_key); ArpNHData *arp_data = new ArpNHData(mac, static_cast(intf.GetDBRequestKey().release()), resolved); diff --git a/src/vnsw/agent/oper/interface.cc b/src/vnsw/agent/oper/interface.cc index 74d4894f03a..637c1ea7027 100644 --- a/src/vnsw/agent/oper/interface.cc +++ b/src/vnsw/agent/oper/interface.cc @@ -83,6 +83,18 @@ void InterfaceTable::RegisterDBClients(IFMapDependencyManager *dep) { autogen::LogicalInterface::ID_PERMS); } +bool InterfaceTable::IFNodeToUuid(IFMapNode *node, boost::uuids::uuid &u) { + if (strcmp(node->table()->Typename(), "virtual-machine-interface") == 0) { + return VmiIFNodeToUuid(node, u); + } + + if (strcmp(node->table()->Typename(), "logical-interface") == 0) { + return LogicalInterfaceIFNodeToUuid(node, u); + } + + return false; +} + bool InterfaceTable::IFNodeToReq(IFMapNode *node, DBRequest &req) { if (strcmp(node->table()->Typename(), "physical-interface") == 0) { return PhysicalInterfaceIFNodeToReq(node, req); diff --git a/src/vnsw/agent/oper/interface.h b/src/vnsw/agent/oper/interface.h index d3763bc434f..0812da15d2f 100644 --- a/src/vnsw/agent/oper/interface.h +++ b/src/vnsw/agent/oper/interface.h @@ -13,7 +13,6 @@ #include #include #include -#include struct InterfaceData; class VmInterface; @@ -275,10 +274,13 @@ class InterfaceTable : public AgentOperDBTable { // Config handlers bool VmiIFNodeToReq(IFMapNode *node, DBRequest &req); + bool VmiIFNodeToUuid(IFMapNode *node, boost::uuids::uuid &u); + bool LogicalInterfaceIFNodeToUuid(IFMapNode *node, boost::uuids::uuid &u); bool PhysicalInterfaceIFNodeToReq(IFMapNode *node, DBRequest &req); bool LogicalInterfaceIFNodeToReq(IFMapNode *node, DBRequest &req); bool RemotePhysicalInterfaceIFNodeToReq(IFMapNode *node, DBRequest &req); bool IFNodeToReq(IFMapNode *node, DBRequest &req); + bool IFNodeToUuid(IFMapNode *node, boost::uuids::uuid &u); // Handle change in config VRF for the interface void VmInterfaceVrfSync(IFMapNode *node); @@ -320,7 +322,6 @@ class InterfaceTable : public AgentOperDBTable { static InterfaceTable *GetInstance() { return interface_table_; } Agent *agent() const { return agent_; } OperDB *operdb() const { return operdb_; } - MacVmBinding &mac_vm_binding() {return mac_vm_binding_;} private: bool L2VmInterfaceWalk(DBTablePartBase *partition, @@ -338,7 +339,6 @@ class InterfaceTable : public AgentOperDBTable { DhcpSnoopMap dhcp_snoop_map_; UpdateFloatingIpFn update_floatingip_cb_; VmiToVmiTypeMap vmi_to_vmitype_map_; - MacVmBinding mac_vm_binding_; DISALLOW_COPY_AND_ASSIGN(InterfaceTable); }; diff --git a/src/vnsw/agent/oper/loadbalancer.cc b/src/vnsw/agent/oper/loadbalancer.cc index 5f990634982..9068d0a27e7 100644 --- a/src/vnsw/agent/oper/loadbalancer.cc +++ b/src/vnsw/agent/oper/loadbalancer.cc @@ -8,6 +8,7 @@ #include "loadbalancer_properties.h" #include #include +#include class LoadbalancerData : public AgentData { public: @@ -213,6 +214,8 @@ DBEntry *LoadbalancerTable::Add(const DBRequest *request) { static_cast(request->data.get()); loadbalancer->set_node(data->node()); assert(dependency_manager_); + loadbalancer->SetIFMapNodeState( + dependency_manager_->SetState(data->node())); dependency_manager_->SetObject(data->node(), loadbalancer); return loadbalancer; @@ -221,7 +224,8 @@ DBEntry *LoadbalancerTable::Add(const DBRequest *request) { bool LoadbalancerTable::Delete(DBEntry *entry, const DBRequest *request) { Loadbalancer *loadbalancer = static_cast(entry); assert(dependency_manager_); - dependency_manager_->ResetObject(loadbalancer->node()); + dependency_manager_->SetObject(loadbalancer->node(), NULL); + loadbalancer->SetIFMapNodeState(NULL); return true; } @@ -248,11 +252,26 @@ void LoadbalancerTable::Initialize( boost::bind(&LoadbalancerTable::ChangeEventHandler, this, _1)); } -bool LoadbalancerTable::IFNodeToReq(IFMapNode *node, DBRequest &request) { +bool LoadbalancerTable::IFNodeToUuid(IFMapNode *node, boost::uuids::uuid &u) { autogen::LoadbalancerPool *pool = - static_cast(node->GetObject()); + static_cast(node->GetObject()); const autogen::IdPermsType &id = pool->id_perms(); - request.key.reset(new LoadbalancerKey(IdPermsGetUuid(id))); + u = IdPermsGetUuid(id); + return true; +} + +bool LoadbalancerTable::IFNodeToReq(IFMapNode *node, DBRequest &request) { + boost::uuids::uuid id; + if (agent() && agent()->cfg_listener()) { + agent()->cfg_listener()->GetCfgDBStateUuid(node, id); + } else { + IFNodeToUuid(node, id); + } + if (boost::uuids::nil_uuid() == id) + return false; + + request.key.reset(new LoadbalancerKey(id)); + if (!node->IsDeleted()) { request.oper = DBRequest::DB_ENTRY_ADD_CHANGE; request.data.reset(new LoadbalancerData(node)); diff --git a/src/vnsw/agent/oper/loadbalancer.h b/src/vnsw/agent/oper/loadbalancer.h index a5a3ed12e44..8b370693d96 100644 --- a/src/vnsw/agent/oper/loadbalancer.h +++ b/src/vnsw/agent/oper/loadbalancer.h @@ -7,6 +7,7 @@ #include #include "cmn/agent_db.h" +#include "oper/ifmap_dependency_manager.h" class IFMapDependencyManager; class LoadbalancerProperties; @@ -55,11 +56,15 @@ class Loadbalancer : public AgentRefCount, const boost::uuids::uuid &uuid() const { return uuid_; } + void SetIFMapNodeState(IFMapDependencyManager::IFMapNodePtr ref) { + ifmap_node_state_ref_ = ref; + } + private: boost::uuids::uuid uuid_; IFMapNode *node_; std::auto_ptr properties_; - + IFMapDependencyManager::IFMapNodePtr ifmap_node_state_ref_; DISALLOW_COPY_AND_ASSIGN(Loadbalancer); }; @@ -89,6 +94,7 @@ class LoadbalancerTable : public AgentDBTable { * Convert the ifmap node to a (key,data) pair stored in the database. */ virtual bool IFNodeToReq(IFMapNode *node, DBRequest &req); + virtual bool IFNodeToUuid(IFMapNode *node, boost::uuids::uuid &u); static DBTableBase *CreateTable(DB *db, const std::string &name); diff --git a/src/vnsw/agent/oper/logical_interface.cc b/src/vnsw/agent/oper/logical_interface.cc index db5fb2677ad..83f39af6576 100644 --- a/src/vnsw/agent/oper/logical_interface.cc +++ b/src/vnsw/agent/oper/logical_interface.cc @@ -220,10 +220,7 @@ void VlanLogicalInterface::SetSandeshData(SandeshLogicalInterface *data) const { // Config handling routines ///////////////////////////////////////////////////////////////////////////// static LogicalInterfaceKey *BuildKey(IFMapNode *node, - const autogen::LogicalInterface *port) { - autogen::IdPermsType id_perms = port->id_perms(); - boost::uuids::uuid u; - CfgUuidSet(id_perms.uuid.uuid_mslong, id_perms.uuid.uuid_lslong, u); + boost::uuids::uuid &u) { return new VlanLogicalInterfaceKey(u, node->name()); } @@ -283,13 +280,29 @@ static LogicalInterfaceData *BuildData(Agent *agent, IFMapNode *node, port->vlan_tag()); } +bool InterfaceTable::LogicalInterfaceIFNodeToUuid(IFMapNode *node, + boost::uuids::uuid &u) { + + autogen::LogicalInterface *port = + static_cast (node->GetObject()); + assert(port); + + autogen::IdPermsType id_perms = port->id_perms(); + CfgUuidSet(id_perms.uuid.uuid_mslong, id_perms.uuid.uuid_lslong, u); + return true; +} + bool InterfaceTable::LogicalInterfaceIFNodeToReq(IFMapNode *node, DBRequest &req) { autogen::LogicalInterface *port = static_cast (node->GetObject()); assert(port); - req.key.reset(BuildKey(node, port)); + boost::uuids::uuid u; + if (agent()->cfg_listener()->GetCfgDBStateUuid(node, u) == false) + return false; + + req.key.reset(BuildKey(node, u)); if (node->IsDeleted()) { req.oper = DBRequest::DB_ENTRY_DELETE; return true; diff --git a/src/vnsw/agent/oper/mac_vm_binding.cc b/src/vnsw/agent/oper/mac_vm_binding.cc deleted file mode 100644 index 905b4272ddd..00000000000 --- a/src/vnsw/agent/oper/mac_vm_binding.cc +++ /dev/null @@ -1,83 +0,0 @@ -/* - * Copyright (c) 2013 Juniper Networks, Inc. All rights reserved. - */ - -#include -#include -#include - -#include "base/logging.h" -#include "db/db.h" -#include "db/db_entry.h" -#include "db/db_table.h" -#include "net/address_util.h" - -#include "oper/operdb_init.h" -#include "oper/agent_types.h" -#include "oper/mac_vm_binding.h" -#include "oper/interface.h" -#include "oper/vm_interface.h" -#include "oper/vn.h" - -MacVmBinding::MacVmBinding() : mac_vm_binding_set_() { -} - -MacVmBinding::~MacVmBinding() { -} - -void MacVmBinding::AddMacVmBinding(const VmInterface *vm_interface) { - UpdateBinding(vm_interface, false); -} - -void MacVmBinding::DeleteMacVmBinding(const VmInterface *vm_interface) { - UpdateBinding(vm_interface, true); -} - -void MacVmBinding::UpdateBinding(const VmInterface *vm_interface, - bool del) { - if (vm_interface->vm_mac().empty()) - return; - - boost::system::error_code ec; - MacAddress address(vm_interface->vm_mac(), &ec); - if (ec) { - return; - } - - MacVmBindingSet::iterator it = FindInterfaceUsingMac(address, vm_interface); - if (it != mac_vm_binding_set_.end()) - mac_vm_binding_set_.erase(it); - - if (!del) { - if (!vm_interface->vn() || vm_interface->vn()->GetVxLanId() == 0) { - return; - } - // assumed that VM mac does not change - MacVmBindingKey key(address, vm_interface->vn()->GetVxLanId(), - vm_interface); - mac_vm_binding_set_.insert(key); - } -} - -MacVmBinding::MacVmBindingSet::iterator -MacVmBinding::FindInterfaceUsingMac(MacAddress &address, - const Interface *interface) { - MacVmBindingSet::iterator it = - mac_vm_binding_set_.lower_bound(MacVmBindingKey(address, 0, NULL)); - while (it != mac_vm_binding_set_.end()) { - if (it->interface == interface) - return it; - it++; - } - - return it; -} - -const Interface * -MacVmBinding::FindMacVmBinding(const MacAddress &address, int vxlan) const { - MacVmBindingKey key(address, vxlan, NULL); - MacVmBindingSet::iterator it = mac_vm_binding_set_.find(key); - if (it == mac_vm_binding_set_.end()) - return NULL; - return it->interface.get(); -} diff --git a/src/vnsw/agent/oper/mac_vm_binding.h b/src/vnsw/agent/oper/mac_vm_binding.h deleted file mode 100644 index 0a6c9bd0b0c..00000000000 --- a/src/vnsw/agent/oper/mac_vm_binding.h +++ /dev/null @@ -1,45 +0,0 @@ -/* - * Copyright (c) 2013 Juniper Networks, Inc. All rights reserved. - */ - -#ifndef vnsw_agent_mac_vm_binding_h_ -#define vnsw_agent_mac_vm_binding_h_ - -#include -#include - -class VmInterface; - -class MacVmBinding { -public: - MacVmBinding(); - virtual ~MacVmBinding(); - const Interface *FindMacVmBinding(const MacAddress &address, - int vxlan) const; - void AddMacVmBinding(const VmInterface *vm_interface); - void DeleteMacVmBinding(const VmInterface *vm_interface); - -private: - struct MacVmBindingKey { - MacAddress mac; - int vxlan; - InterfaceConstRef interface; - - MacVmBindingKey(const MacAddress &m, int v, InterfaceConstRef intf) : - mac(m), vxlan(v), interface(intf) {} - bool operator<(const MacVmBindingKey &rhs) const { - if (mac != rhs.mac) - return mac < rhs.mac; - - return vxlan < rhs.vxlan; - } - }; - typedef std::set MacVmBindingSet; - void UpdateBinding(const VmInterface *vm_interface, bool del); - MacVmBindingSet::iterator FindInterfaceUsingMac(MacAddress &address, - const Interface *interface); - - MacVmBindingSet mac_vm_binding_set_; -}; - -#endif // vnsw_agent_mac_vm_binding_h_ diff --git a/src/vnsw/agent/oper/multicast.cc b/src/vnsw/agent/oper/multicast.cc index 68526524139..104a51f89ed 100644 --- a/src/vnsw/agent/oper/multicast.cc +++ b/src/vnsw/agent/oper/multicast.cc @@ -946,9 +946,11 @@ void MulticastHandler::Shutdown() { GetMulticastObjList().begin(); it != GetMulticastObjList().end(); it++) { MulticastGroupObject *obj = (*it); + BridgeAgentRouteTable *bridge_table = + static_cast + (agent_->vrf_table()->GetBridgeRouteTable(obj->vrf_name())); AgentRoute *route = - BridgeAgentRouteTable::FindRoute(agent_, obj->vrf_name(), - MacAddress::BroadcastMac()); + bridge_table->FindRoute(MacAddress::BroadcastMac()); if (route == NULL) return; diff --git a/src/vnsw/agent/oper/oper_db.h b/src/vnsw/agent/oper/oper_db.h index 4ffd2a81fcf..deb2f83f3f2 100644 --- a/src/vnsw/agent/oper/oper_db.h +++ b/src/vnsw/agent/oper/oper_db.h @@ -29,36 +29,62 @@ struct AgentOperDBKey : public AgentKey { }; struct AgentOperDBData : public AgentData { - AgentOperDBData(Agent *agent, IFMapNode *node) : - AgentData(), ifmap_node_(NULL) { - SetIFMapNode(agent, node); + + AgentOperDBData(const Agent *agent, IFMapNode *node) : + AgentData(), agent_(agent) { + SetIFMapNode(node); + } + virtual ~AgentOperDBData() { + SetIFMapNode(NULL); } - virtual ~AgentOperDBData() { } - void SetIFMapNode(Agent *agent, IFMapNode *node) { - if (node == NULL) + + void SetIFMapNode(IFMapNode *node) { + + if (node == NULL) { + ifmap_node_state_ = NULL; return; - IFMapDependencyManager *dep = agent->oper_db()->dependency_manager(); - dep->SetState(node); - ifmap_node_ = node; + } + + assert(agent_); + + // We dont allow changing the node + assert(!ifmap_node_state_); + + IFMapDependencyManager *dep = agent_->oper_db()->dependency_manager(); + ifmap_node_state_ = dep->SetState(node); } - IFMapNode *ifmap_node() const { return ifmap_node_; } + IFMapNode *ifmap_node() const { + if (!ifmap_node_state_) + return NULL; + IFMapNodeState *state = ifmap_node_state_.get(); + return state->node(); + } private: + const Agent *agent_; // IFMap Node pointer for the object - IFMapNode *ifmap_node_; + IFMapDependencyManager::IFMapNodePtr ifmap_node_state_; }; class AgentOperDBEntry : public AgentDBEntry { public: - AgentOperDBEntry() : AgentDBEntry(), ifmap_node_(NULL) { } + AgentOperDBEntry() : AgentDBEntry() { } virtual ~AgentOperDBEntry() { } - IFMapNode *ifmap_node() const { return ifmap_node_; } + IFMapNode *ifmap_node() const { + if (!ifmap_node_state_) + return NULL; + IFMapNodeState *state = ifmap_node_state_.get(); + return state->node(); + } + + void SetIFMapNodeState(IFMapDependencyManager::IFMapNodePtr sref) { + ifmap_node_state_ = sref; + } private: friend class AgentOperDBTable; - // IFMapNode for the DBEntry - IFMapNode *ifmap_node_; + IFMapDependencyManager::IFMapNodePtr ifmap_node_state_; DISALLOW_COPY_AND_ASSIGN(AgentOperDBEntry); }; @@ -91,9 +117,9 @@ class AgentOperDBTable : public AgentDBTable { return; AgentOperDBEntry *agent_entry = static_cast(entry); - if (agent_entry->ifmap_node_) { + if (agent_entry->ifmap_node()) { DBRequest req; - if (IFNodeToReq(agent_entry->ifmap_node_, req) == true) { + if (IFNodeToReq(agent_entry->ifmap_node(), req) == true) { Enqueue(&req); } } @@ -106,16 +132,21 @@ class AgentOperDBTable : public AgentDBTable { if (entry == NULL) return; - if (entry->ifmap_node_ == node) + IFMapNode *old_node = entry->ifmap_node(); + + if (old_node == node) return; IFMapDependencyManager *dep = agent()->oper_db()->dependency_manager(); - if (entry->ifmap_node_ != NULL) - dep->ResetObject(entry->ifmap_node_); + if (old_node) { + dep->SetObject(old_node, NULL); + entry->SetIFMapNodeState(NULL); + } - entry->ifmap_node_ = node; - if (entry->ifmap_node_) + if (node) { + entry->SetIFMapNodeState(dep->SetState(node)); dep->SetObject(node, entry); + } } // Implement Add, Delete, OnChange to provide common agent functionality @@ -123,7 +154,6 @@ class AgentOperDBTable : public AgentDBTable { virtual DBEntry *Add(const DBRequest *req) { AgentOperDBEntry *entry = static_cast (OperDBAdd(req)); - AgentOperDBData *data = static_cast(req->data.get()); if (data && data->ifmap_node()) UpdateIfMapNode(entry, data->ifmap_node()); @@ -153,6 +183,7 @@ class AgentOperDBTable : public AgentDBTable { virtual bool Delete(DBEntry *entry, const DBRequest *req) { AgentOperDBEntry *oper_entry = static_cast(entry); bool ret = OperDBDelete(entry, req); + UpdateIfMapNode(oper_entry, NULL); return ret; } diff --git a/src/vnsw/agent/oper/operdb_init.cc b/src/vnsw/agent/oper/operdb_init.cc index a77da400e1e..f279ae8a3d7 100644 --- a/src/vnsw/agent/oper/operdb_init.cc +++ b/src/vnsw/agent/oper/operdb_init.cc @@ -160,12 +160,14 @@ void OperDB::CreateDBTables(DB *db) { db->CreateTable("db.service-instance.0")); agent_->set_service_instance_table(si_table); si_table->Initialize(agent_->cfg()->cfg_graph(), dependency_manager_.get()); + si_table->set_agent(agent_); LoadbalancerTable *lb_table = static_cast(db->CreateTable("db.loadbalancer-pool.0")); agent_->set_loadbalancer_table(lb_table); lb_table->Initialize(agent_->cfg()->cfg_graph(), dependency_manager_.get()); + lb_table->set_agent(agent_); PhysicalDeviceTable *dev_table = DBTableCreate(db, agent_, this, diff --git a/src/vnsw/agent/oper/operdb_init.h b/src/vnsw/agent/oper/operdb_init.h index 56058f9e526..681449c0fd1 100644 --- a/src/vnsw/agent/oper/operdb_init.h +++ b/src/vnsw/agent/oper/operdb_init.h @@ -17,7 +17,6 @@ class PathPreferenceModule; class IFMapDependencyManager; class MulticastHandler; class InstanceManager; -class MacVmBinding; class NexthopManager; class OperDB { diff --git a/src/vnsw/agent/oper/peer.h b/src/vnsw/agent/oper/peer.h index 88a5c18ec6a..c5f27e44749 100644 --- a/src/vnsw/agent/oper/peer.h +++ b/src/vnsw/agent/oper/peer.h @@ -22,6 +22,7 @@ #define MULTICAST_PEER_NAME "Multicast" #define MULTICAST_TOR_PEER_NAME "Multicast TOR" #define MULTICAST_FABRIC_TREE_BUILDER_NAME "MulticastTreeBuilder" +#define MAC_VM_BINDING_PEER_NAME "MacVmBindingPeer" class AgentXmppChannel; class ControllerRouteWalker; @@ -45,7 +46,8 @@ class Peer { VGW_PEER, MULTICAST_FABRIC_TREE_BUILDER, OVS_PEER, - MULTICAST_TOR_PEER + MULTICAST_TOR_PEER, + MAC_VM_BINDING_PEER }; Peer(Type type, const std::string &name, bool controller_export); diff --git a/src/vnsw/agent/oper/physical_device.cc b/src/vnsw/agent/oper/physical_device.cc index df2093b93ee..7f17b26de28 100644 --- a/src/vnsw/agent/oper/physical_device.cc +++ b/src/vnsw/agent/oper/physical_device.cc @@ -9,6 +9,7 @@ #include #include #include +#include #include #include #include @@ -174,10 +175,8 @@ void PhysicalDeviceTable::RegisterDBClients(IFMapDependencyManager *dep) { autogen::PhysicalRouter::ID_PERMS); } -static PhysicalDeviceKey *BuildKey(const autogen::PhysicalRouter *router) { - autogen::IdPermsType id_perms = router->id_perms(); - boost::uuids::uuid u; - CfgUuidSet(id_perms.uuid.uuid_mslong, id_perms.uuid.uuid_lslong, u); +static PhysicalDeviceKey *BuildKey(const autogen::PhysicalRouter + *router, boost::uuids::uuid &u) { return new PhysicalDeviceKey(u); } @@ -192,12 +191,24 @@ static PhysicalDeviceData *BuildData(Agent *agent, IFMapNode *node, router->vendor_name(), ip, mip, "OVS", node); } +bool PhysicalDeviceTable::IFNodeToUuid(IFMapNode *node, boost::uuids::uuid &u) { + autogen::PhysicalRouter *router = static_cast + (node->GetObject()); + autogen::IdPermsType id_perms = router->id_perms(); + CfgUuidSet(id_perms.uuid.uuid_mslong, id_perms.uuid.uuid_lslong, u); + return true; +} + bool PhysicalDeviceTable::IFNodeToReq(IFMapNode *node, DBRequest &req) { autogen::PhysicalRouter *router = static_cast (node->GetObject()); assert(router); - req.key.reset(BuildKey(router)); + boost::uuids::uuid u; + if (agent()->cfg_listener()->GetCfgDBStateUuid(node, u) == false) + return false; + + req.key.reset(BuildKey(router, u)); if (node->IsDeleted()) { req.oper = DBRequest::DB_ENTRY_DELETE; agent()->physical_device_vn_table()->ConfigUpdate(node); diff --git a/src/vnsw/agent/oper/physical_device.h b/src/vnsw/agent/oper/physical_device.h index a2fdcfea44d..2430b0192a8 100644 --- a/src/vnsw/agent/oper/physical_device.h +++ b/src/vnsw/agent/oper/physical_device.h @@ -96,6 +96,7 @@ class PhysicalDeviceTable : public AgentOperDBTable { virtual bool OperDBOnChange(DBEntry *entry, const DBRequest *req); virtual bool OperDBDelete(DBEntry *entry, const DBRequest *req); virtual bool IFNodeToReq(IFMapNode *node, DBRequest &req); + virtual bool IFNodeToUuid(IFMapNode *node, boost::uuids::uuid &u); PhysicalDevice *Find(const boost::uuids::uuid &u); diff --git a/src/vnsw/agent/oper/physical_device_vn.cc b/src/vnsw/agent/oper/physical_device_vn.cc index ae178a0e35c..a022b8b8252 100644 --- a/src/vnsw/agent/oper/physical_device_vn.cc +++ b/src/vnsw/agent/oper/physical_device_vn.cc @@ -105,7 +105,6 @@ bool PhysicalDeviceVnTable::OnChange(DBEntry *e, const DBRequest *req) { PhysicalDeviceVnData *data = static_cast(req->data.get()); bool ret = entry->Copy(this, data); - entry->SendObjectLog(AgentLogEvent::CHANGE); return ret; } @@ -114,7 +113,6 @@ bool PhysicalDeviceVnTable::Resync(DBEntry *e, const DBRequest *req) { PhysicalDeviceVnData *data = static_cast(req->data.get()); bool ret = entry->Copy(this, data); - entry->SendObjectLog(AgentLogEvent::RESYNC); return ret; } diff --git a/src/vnsw/agent/oper/service_instance.cc b/src/vnsw/agent/oper/service_instance.cc index eec009f48ca..642ec68d449 100644 --- a/src/vnsw/agent/oper/service_instance.cc +++ b/src/vnsw/agent/oper/service_instance.cc @@ -10,6 +10,7 @@ #include "oper/ifmap_dependency_manager.h" #include "oper/operdb_init.h" #include +#include #include #include #include @@ -672,6 +673,8 @@ DBEntry *ServiceInstanceTable::Add(const DBRequest *request) { static_cast(request->data.get()); svc_instance->set_node(data->node()); assert(dependency_manager_); + svc_instance->SetIFMapNodeState + (dependency_manager_->SetState(data->node())); dependency_manager_->SetObject(data->node(), svc_instance); return svc_instance; @@ -680,7 +683,8 @@ DBEntry *ServiceInstanceTable::Add(const DBRequest *request) { bool ServiceInstanceTable::Delete(DBEntry *entry, const DBRequest *request) { ServiceInstance *svc_instance = static_cast(entry); assert(dependency_manager_); - dependency_manager_->ResetObject(svc_instance->node()); + dependency_manager_->SetObject(svc_instance->node(), NULL); + svc_instance->SetIFMapNodeState(NULL); return true; } @@ -716,10 +720,11 @@ void ServiceInstanceTable::Initialize( } bool ServiceInstanceTable::IFNodeToReq(IFMapNode *node, DBRequest &request) { - autogen::ServiceInstance *svc_instance = - static_cast(node->GetObject()); - const autogen::IdPermsType &id = svc_instance->id_perms(); - request.key.reset(new ServiceInstanceKey(IdPermsGetUuid(id))); + uuid id; + if (agent()->cfg_listener()->GetCfgDBStateUuid(node, id) == false) + return false; + + request.key.reset(new ServiceInstanceKey(id)); if (!node->IsDeleted()) { request.oper = DBRequest::DB_ENTRY_ADD_CHANGE; request.data.reset(new ServiceInstanceCreate(node)); @@ -729,6 +734,13 @@ bool ServiceInstanceTable::IFNodeToReq(IFMapNode *node, DBRequest &request) { return true; } +bool ServiceInstanceTable::IFNodeToUuid(IFMapNode *node, uuid &idperms_uuid) { + autogen::ServiceInstance *svc_instance = + static_cast(node->GetObject()); + const autogen::IdPermsType &id = svc_instance->id_perms(); + idperms_uuid = IdPermsGetUuid(id); + return true; +} void ServiceInstanceTable::ChangeEventHandler(DBEntry *entry) { ServiceInstance *svc_instance = static_cast(entry); diff --git a/src/vnsw/agent/oper/service_instance.h b/src/vnsw/agent/oper/service_instance.h index fd6ae2d10bb..32572c1f471 100644 --- a/src/vnsw/agent/oper/service_instance.h +++ b/src/vnsw/agent/oper/service_instance.h @@ -8,6 +8,7 @@ #include #include #include "cmn/agent_db.h" +#include "oper/ifmap_dependency_manager.h" class DBGraph; class IFMapDependencyManager; @@ -122,10 +123,15 @@ class ServiceInstance : public AgentRefCount, bool IsUsable() const; + void SetIFMapNodeState(IFMapDependencyManager::IFMapNodePtr ref) { + ifmap_node_state_ref_ = ref; + } + private: boost::uuids::uuid uuid_; IFMapNode *node_; Properties properties_; + IFMapDependencyManager::IFMapNodePtr ifmap_node_state_ref_; DISALLOW_COPY_AND_ASSIGN(ServiceInstance); }; @@ -155,6 +161,7 @@ class ServiceInstanceTable : public AgentDBTable { * Convert the ifmap node to a (key,data) pair stored in the database. */ virtual bool IFNodeToReq(IFMapNode *node, DBRequest &req); + virtual bool IFNodeToUuid(IFMapNode *node, boost::uuids::uuid &id); static DBTableBase *CreateTable(DB *db, const std::string &name); diff --git a/src/vnsw/agent/oper/sg.cc b/src/vnsw/agent/oper/sg.cc index a1226b4b13a..9c34538f109 100644 --- a/src/vnsw/agent/oper/sg.cc +++ b/src/vnsw/agent/oper/sg.cc @@ -100,13 +100,21 @@ DBTableBase *SgTable::CreateTable(DB *db, const std::string &name) { return sg_table_; }; -bool SgTable::IFNodeToReq(IFMapNode *node, DBRequest &req) { +bool SgTable::IFNodeToUuid(IFMapNode *node, boost::uuids::uuid &u) { SecurityGroup *cfg = static_cast(node->GetObject()); assert(cfg); - autogen::IdPermsType id_perms = cfg->id_perms(); - boost::uuids::uuid u; CfgUuidSet(id_perms.uuid.uuid_mslong, id_perms.uuid.uuid_lslong, u); + return true; +} + +bool SgTable::IFNodeToReq(IFMapNode *node, DBRequest &req) { + SecurityGroup *cfg = static_cast(node->GetObject()); + assert(cfg); + + uuid u; + if (agent()->cfg_listener()->GetCfgDBStateUuid(node, u) == false) + return false; SgKey *key = new SgKey(u); SgData *data = NULL; @@ -177,6 +185,28 @@ bool SgTable::IFNodeToReq(IFMapNode *node, DBRequest &req) { return false; } +bool SgTable::IFLinkToReq(IFMapLink *link, IFMapNode *node, + const std::string &peer_type, IFMapNode *peer, + DBRequest &req) { + // Add/Delete of link other than VMInterface will most likely need re-eval + // of VN. + if (peer_type != "virtual-machine-interface") { + return IFNodeToReq(node, req); + } + + // If peer is VMI, invoke re-eval if peer node is present + if (peer && peer->table() == agent()->cfg()->cfg_vm_interface_table()) { + DBRequest vmi_req; + if (agent()->interface_table()->IFNodeToReq(peer, vmi_req) == true) { + LOG(DEBUG, "SG change sync for Port " << peer->name()); + agent()->interface_table()->Enqueue(&vmi_req); + } + return false; + } + + return false; +} + bool SgEntry::DBEntrySandesh(Sandesh *sresp, std::string &name) const { SgListResp *resp = static_cast(sresp); std::string str_uuid = UuidToString(GetSgUuid()); diff --git a/src/vnsw/agent/oper/sg.h b/src/vnsw/agent/oper/sg.h index e23104e6723..3d7c6fe317e 100644 --- a/src/vnsw/agent/oper/sg.h +++ b/src/vnsw/agent/oper/sg.h @@ -83,6 +83,10 @@ class SgTable : public AgentDBTable { virtual bool Delete(DBEntry *entry, const DBRequest *req); virtual bool IFNodeToReq(IFMapNode *node, DBRequest &req); + virtual bool IFNodeToUuid(IFMapNode *node, boost::uuids::uuid &u); + virtual bool IFLinkToReq(IFMapLink *link, IFMapNode *node, + const std::string &peer_type, IFMapNode *peer, + DBRequest &req); static DBTableBase *CreateTable(DB *db, const std::string &name); static SgTable *GetInstance() {return sg_table_;}; diff --git a/src/vnsw/agent/oper/test/ifmap_dependency_manager_test.cc b/src/vnsw/agent/oper/test/ifmap_dependency_manager_test.cc index 7ec81cadbaf..bc332def3a7 100644 --- a/src/vnsw/agent/oper/test/ifmap_dependency_manager_test.cc +++ b/src/vnsw/agent/oper/test/ifmap_dependency_manager_test.cc @@ -141,7 +141,7 @@ class IFMapDependencyManagerTest : public ::testing::Test { for (DBEntry *entry = tslice->GetFirst(); entry; entry = tslice->GetNext(entry)) { TestEntry *test_entry = static_cast(entry); - manager_->ResetObject(test_entry->node()); + manager_->SetObject(test_entry->node(), NULL); test_entry->reset_node(); list.push_back(test_entry->name()); } diff --git a/src/vnsw/agent/oper/test/loadbalancer_test.cc b/src/vnsw/agent/oper/test/loadbalancer_test.cc index 3cc9d313b24..1de13068d45 100644 --- a/src/vnsw/agent/oper/test/loadbalancer_test.cc +++ b/src/vnsw/agent/oper/test/loadbalancer_test.cc @@ -48,15 +48,15 @@ class LoadbalancerTest : public ::testing::Test { } virtual void TearDown() { - manager_->Terminate(); + loadbalancer_table_->Clear(); config_listener_.Shutdown(); + manager_->Terminate(); IFMapLinkTable *link_table = static_cast( database_.FindTable(IFMAP_AGENT_LINK_DB_NAME)); assert(link_table); link_table->Clear(); - loadbalancer_table_->Clear(); db_util::Clear(&database_); DB::ClearFactoryRegistry(); } @@ -172,6 +172,7 @@ TEST_F(LoadbalancerTest, ConfigPool) { EXPECT_EQ("127.0.0.1", addresses.at(0)); EXPECT_EQ("127.0.0.2", addresses.at(1)); ASSERT_EQ(2, props->healthmonitors().size()); + manager_->SetObject(loadbalancer->node(), NULL); } static void SetUp() { diff --git a/src/vnsw/agent/oper/test/physical-device-vn.xml b/src/vnsw/agent/oper/test/physical-device-vn.xml index 99e7d238313..c2844c37fc2 100644 --- a/src/vnsw/agent/oper/test/physical-device-vn.xml +++ b/src/vnsw/agent/oper/test/physical-device-vn.xml @@ -1,6 +1,9 @@ - + + + @@ -93,4 +96,116 @@ /> + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/src/vnsw/agent/oper/test/test_intf.cc b/src/vnsw/agent/oper/test/test_intf.cc index db8615b7e24..4d0b69db9aa 100644 --- a/src/vnsw/agent/oper/test/test_intf.cc +++ b/src/vnsw/agent/oper/test/test_intf.cc @@ -2637,6 +2637,29 @@ TEST_F(IntfTest, VrfTranslateAddDelete) { client->WaitForIdle(); } +TEST_F(IntfTest, VMI_Sequence_1) { + AddVn("vn1", 1); + AddPort("vmi1", 1, ""); + client->WaitForIdle(); + + AddLink("virtual-machine-interface", "vmi1", "virtual-network", "vn1"); + AddVrf("vrf1"); + AddLink("virtual-network", "vn1", "routing-instance", "vrf1"); + client->WaitForIdle(); + + VrfEntry *vrf = VrfGet("vrf1"); + VnEntry *vn = VnGet(1); + EXPECT_TRUE(vn->GetVrf() != NULL); + EXPECT_TRUE(vrf->vn() != NULL); + + DelLink("virtual-machine-interface", "vmi1", "virtual-network", "vn1"); + DelLink("virtual-network", "vn1", "routing-instance", "vrf1"); + DelVrf("vrf1"); + DelVn("vn1"); + DelPort("vmi1"); + client->WaitForIdle(); +} + int main(int argc, char **argv) { GETUSERARGS(); diff --git a/src/vnsw/agent/oper/vm.cc b/src/vnsw/agent/oper/vm.cc index 498a4d91ca1..6d6fe121360 100644 --- a/src/vnsw/agent/oper/vm.cc +++ b/src/vnsw/agent/oper/vm.cc @@ -11,6 +11,7 @@ #include #include #include +#include using namespace std; using namespace autogen; @@ -114,16 +115,22 @@ DBTableBase *VmTable::CreateTable(DB *db, const std::string &name) { vm_table_->Init(); return vm_table_; }; - -bool VmTable::IFNodeToReq(IFMapNode *node, DBRequest &req){ +bool VmTable::IFNodeToUuid(IFMapNode *node, boost::uuids::uuid &u) { VirtualMachine *cfg = static_cast (node->GetObject()); assert(cfg); autogen::IdPermsType id_perms = cfg->id_perms(); - boost::uuids::uuid u; CfgUuidSet(id_perms.uuid.uuid_mslong, id_perms.uuid.uuid_lslong, u); + return true; +} + +bool VmTable::IFNodeToReq(IFMapNode *node, DBRequest &req){ + uuid id; + if (agent()->cfg_listener()->GetCfgDBStateUuid(node, id) == false) + return false; + string virtual_router_type = "none"; - VmKey *key = new VmKey(u); + VmKey *key = new VmKey(id); VmData *data = NULL; if (node->IsDeleted()) { req.oper = DBRequest::DB_ENTRY_DELETE; diff --git a/src/vnsw/agent/oper/vm.h b/src/vnsw/agent/oper/vm.h index 1649b0360db..af1f3c82b38 100644 --- a/src/vnsw/agent/oper/vm.h +++ b/src/vnsw/agent/oper/vm.h @@ -70,6 +70,7 @@ class VmTable : public AgentDBTable { virtual bool OnChange(DBEntry *entry, const DBRequest *req); virtual bool Delete(DBEntry *entry, const DBRequest *req); virtual bool IFNodeToReq(IFMapNode *node, DBRequest &req); + virtual bool IFNodeToUuid(IFMapNode *node, boost::uuids::uuid &u); static DBTableBase *CreateTable(DB *db, const std::string &name); static VmTable *GetInstance() {return vm_table_;} diff --git a/src/vnsw/agent/oper/vm_interface.cc b/src/vnsw/agent/oper/vm_interface.cc index 9593c9f4705..3d3ce157b23 100644 --- a/src/vnsw/agent/oper/vm_interface.cc +++ b/src/vnsw/agent/oper/vm_interface.cc @@ -31,7 +31,6 @@ #include #include #include -#include #include #include @@ -708,11 +707,10 @@ static void ComputeTypeInfo(Agent *agent, VmInterfaceConfigData *data, autogen::LogicalInterface *port = static_cast (logical_node->GetObject()); - data->rx_vlan_id_ = port->vlan_tag(); - data->tx_vlan_id_ = port->vlan_tag(); - } else { - data->rx_vlan_id_ = 0; - data->tx_vlan_id_ = 0; + if (port->vlan_tag()) { + data->rx_vlan_id_ = port->vlan_tag(); + data->tx_vlan_id_ = port->vlan_tag(); + } } return; } else { @@ -765,6 +763,15 @@ static bool DeleteVmi(InterfaceTable *table, const uuid &u, DBRequest *req) { } } +bool InterfaceTable::VmiIFNodeToUuid(IFMapNode *node, boost::uuids::uuid &u) { + + VirtualMachineInterface *cfg = static_cast + (node->GetObject()); + autogen::IdPermsType id_perms = cfg->id_perms(); + CfgUuidSet(id_perms.uuid.uuid_mslong, id_perms.uuid.uuid_lslong, u); + return true; +} + // Virtual Machine Interface is added or deleted into oper DB from Nova // messages. The Config notify is used only to change interface. bool InterfaceTable::VmiIFNodeToReq(IFMapNode *node, DBRequest &req) { @@ -772,9 +779,9 @@ bool InterfaceTable::VmiIFNodeToReq(IFMapNode *node, DBRequest &req) { VirtualMachineInterface *cfg = static_cast (node->GetObject()); assert(cfg); - autogen::IdPermsType id_perms = cfg->id_perms(); - boost::uuids::uuid u; - CfgUuidSet(id_perms.uuid.uuid_mslong, id_perms.uuid.uuid_lslong, u); + uuid u; + if (agent()->cfg_listener()->GetCfgDBStateUuid(node, u) == false) + return false; // Handle object delete if (node->IsDeleted()) { @@ -789,8 +796,8 @@ bool InterfaceTable::VmiIFNodeToReq(IFMapNode *node, DBRequest &req) { // Update interface configuration req.oper = DBRequest::DB_ENTRY_ADD_CHANGE; - VmInterfaceConfigData *data = new VmInterfaceConfigData(NULL, NULL); - data->SetIFMapNode(agent(), node); + VmInterfaceConfigData *data = new VmInterfaceConfigData(agent(), NULL); + data->SetIFMapNode(node); IFMapNode *vn_node = NULL; @@ -987,6 +994,7 @@ bool VmInterface::Resync(const InterfaceTable *table, Ip4Address old_subnet = subnet_; uint8_t old_subnet_plen = subnet_plen_; int old_ethernet_tag = ethernet_tag_; + bool old_dhcp_enable = dhcp_enable_; if (data) { ret = data->OnResync(table, this, &sg_changed, &ecmp_changed, @@ -1017,7 +1025,8 @@ bool VmInterface::Resync(const InterfaceTable *table, ApplyConfig(old_ipv4_active, old_l2_active, old_policy, old_vrf.get(), old_addr, old_ethernet_tag, old_need_linklocal_ip, sg_changed, old_ipv6_active, old_v6_addr, ecmp_changed, - local_pref_changed, old_subnet, old_subnet_plen); + local_pref_changed, old_subnet, old_subnet_plen, + old_dhcp_enable); return ret; } @@ -1163,6 +1172,35 @@ const MacAddress& VmInterface::GetVifMac(const Agent *agent) const { } } +void VmInterface::ApplyConfigCommon(const VrfEntry *old_vrf, + bool old_l2_active, + bool old_dhcp_enable) { + //DHCP MAC IP binding + ApplyMacVmBindingConfig(old_vrf, old_l2_active, old_dhcp_enable); + //Security Group update + if (IsActive()) + UpdateSecurityGroup(); + else + DeleteSecurityGroup(); + +} + +void VmInterface::ApplyMacVmBindingConfig(const VrfEntry *old_vrf, + bool old_l2_active, + bool old_dhcp_enable) { + if (L2Deactivated(old_l2_active)) { + DeleteMacVmBinding(old_vrf); + return; + } + + //Interface has been activated or + //dhcp toggled for already activated interface + if (L2Activated(old_l2_active) || + (l2_active_ && (old_dhcp_enable != dhcp_enable_))) { + UpdateMacVmBinding(); + } +} + // Apply the latest configuration void VmInterface::ApplyConfig(bool old_ipv4_active, bool old_l2_active, bool old_policy, VrfEntry *old_vrf, const Ip4Address &old_addr, @@ -1171,19 +1209,9 @@ void VmInterface::ApplyConfig(bool old_ipv4_active, bool old_l2_active, bool old const Ip6Address &old_v6_addr, bool ecmp_mode_changed, bool local_pref_changed, const Ip4Address &old_subnet, - uint8_t old_subnet_plen) { - //MAC VM binding is handled for all VM interface - if (l2_active_ && bridging_) { - UpdateMacVmBinding(old_l2_active); - } else { - DeleteMacVmBinding(old_l2_active); - } - - if (IsActive()) - UpdateSecurityGroup(); - else - DeleteSecurityGroup(); - + uint8_t old_subnet_plen, + bool old_dhcp_enable) { + ApplyConfigCommon(old_vrf, old_l2_active, old_dhcp_enable); //Need not apply config for TOR VMI as it is more of an inidicative //interface. No route addition or NH addition happens for this interface. if (device_type_ == VmInterface::TOR && @@ -2077,46 +2105,14 @@ void VmInterface::UpdateFlowKeyNextHop() { agent->nexthop_table()->FindActiveEntry(&key)); } -void VmInterface::UpdateMacVmBinding(bool old_l2_active) { - if (L2Activated(old_l2_active)) { - InterfaceTable *table = static_cast(get_table()); - table->mac_vm_binding().AddMacVmBinding(this); - int vxlan_id = vn_.get() ? vn_.get()->GetVxLanId() : 0; - EvpnAgentRouteTable *evpn_table = static_cast - (vrf_.get()->GetEvpnRouteTable()); - EvpnRouteEntry *evpn_rt = - evpn_table->FindRoute(MacAddress::FromString(vm_mac_), Ip4Address(), - vxlan_id); - if (evpn_rt == NULL) - evpn_rt = evpn_table->FindRoute(MacAddress::FromString(vm_mac_), Ip6Address(), - vxlan_id); - if (evpn_rt) { - for(Route::PathList::const_iterator it = evpn_rt->GetPathList().begin(); - it != evpn_rt->GetPathList().end(); it++) { - const AgentPath *path = static_cast(it.operator->()); - if (path) { - path->set_flood_dhcp(!dhcp_enable_config()); - } - } - evpn_table->NotifyEntry(evpn_rt); - } - BridgeRouteEntry *br_rt = - BridgeAgentRouteTable::FindRoute(evpn_table->agent(), - vrf_.get()->GetName(), - MacAddress::FromString(vm_mac_)); - BridgeAgentRouteTable *br_table = static_cast - (vrf_.get()->GetBridgeRouteTable()); - if (br_rt) { - for(Route::PathList::const_iterator it = br_rt->GetPathList().begin(); - it != br_rt->GetPathList().end(); it++) { - const AgentPath *path = static_cast(it.operator->()); - if (path) { - path->set_flood_dhcp(!dhcp_enable_config()); - } - } - br_table->NotifyEntry(br_rt); - } - } +void VmInterface::UpdateMacVmBinding() { + BridgeAgentRouteTable *table = static_cast + (vrf_->GetBridgeRouteTable()); + Agent *agent = table->agent(); + table->AddMacVmBindingRoute(agent->mac_vm_binding_peer(), + vrf_->GetName(), + MacAddress::FromString(vm_mac_), + this); } void VmInterface::UpdateL2NextHop(bool old_l2_active) { @@ -2137,11 +2133,16 @@ void VmInterface::UpdateL3NextHop(bool old_ipv4_active, bool old_ipv6_active) { } } -void VmInterface::DeleteMacVmBinding(bool old_l2_active) { - if (L2Deactivated(old_l2_active)) { - InterfaceTable *table = static_cast(get_table()); - table->mac_vm_binding().DeleteMacVmBinding(this); - } +void VmInterface::DeleteMacVmBinding(const VrfEntry *old_vrf) { + if (old_vrf == NULL) + return; + BridgeAgentRouteTable *table = static_cast + (old_vrf->GetBridgeRouteTable()); + Agent *agent = table->agent(); + table->DeleteMacVmBindingRoute(agent->mac_vm_binding_peer(), + old_vrf->GetName(), + MacAddress::FromString(vm_mac_), + this); } void VmInterface::DeleteL2NextHop(bool old_l2_active) { diff --git a/src/vnsw/agent/oper/vm_interface.h b/src/vnsw/agent/oper/vm_interface.h index 2e7ffc5c539..e28f0601457 100644 --- a/src/vnsw/agent/oper/vm_interface.h +++ b/src/vnsw/agent/oper/vm_interface.h @@ -522,6 +522,12 @@ class VmInterface : public Interface { bool ResyncConfig(VmInterfaceConfigData *data); bool CopyIpAddress(Ip4Address &addr); bool CopyIp6Address(const Ip6Address &addr); + void ApplyMacVmBindingConfig(const VrfEntry *old_vrf, + bool old_l2_active, + bool old_dhcp_enable); + void ApplyConfigCommon(const VrfEntry *old_vrf, + bool old_l2_active, + bool old_dhcp_enable); bool CopyConfig(const InterfaceTable *table, const VmInterfaceConfigData *data, bool *sg_changed, bool *ecmp_changed, bool *local_pref_changed); @@ -531,7 +537,7 @@ class VmInterface : public Interface { bool sg_changed, bool old_ipv6_active, const Ip6Address &old_v6_addr, bool ecmp_changed, bool local_pref_changed, const Ip4Address &old_subnet, - const uint8_t old_subnet_plen); + const uint8_t old_subnet_plen, bool old_dhcp_enable); void UpdateL3(bool old_ipv4_active, VrfEntry *old_vrf, const Ip4Address &old_addr, int old_ethernet_tag, bool force_update, bool policy_change, bool old_ipv6_active, @@ -553,11 +559,11 @@ class VmInterface : public Interface { void DeleteL3TunnelId(); void UpdateMulticastNextHop(bool old_ipv4_active, bool old_l2_active); void DeleteMulticastNextHop(); - void UpdateMacVmBinding(bool old_l2_active); + void UpdateMacVmBinding(); void UpdateL2NextHop(bool old_l2_active); void UpdateFlowKeyNextHop(); void DeleteL2NextHop(bool old_l2_active); - void DeleteMacVmBinding(bool old_l2_active); + void DeleteMacVmBinding(const VrfEntry *old_vrf); void UpdateL3NextHop(bool old_ipv4_active, bool old_ipv6_active); void DeleteL3NextHop(bool old_ipv4_active, bool old_ipv6_active); bool L2Activated(bool old_l2_active); diff --git a/src/vnsw/agent/oper/vn.cc b/src/vnsw/agent/oper/vn.cc index afb159d468c..22ea1e87dd1 100644 --- a/src/vnsw/agent/oper/vn.cc +++ b/src/vnsw/agent/oper/vn.cc @@ -623,7 +623,7 @@ VnData *VnTable::BuildData(IFMapNode *node) { bool bridging = true; bool layer3_forwarding = true; - return new VnData(node->name(), acl_uuid, vrf_name, mirror_acl_uuid, + return new VnData(agent(), node->name(), acl_uuid, vrf_name, mirror_acl_uuid, mirror_cfg_acl_uuid, vn_ipam, vn_ipam_data, cfg->properties().vxlan_network_identifier, cfg->properties().network_id, bridging, layer3_forwarding, @@ -658,38 +658,53 @@ void VnTable::ResyncVmInterface(IFMapNode *node) { } } -bool VnTable::IFLinkToReq(IFMapLink *link, IFMapNode *node, IFMapNode *peer, - DBRequest &req) { + +bool VnTable::IFNodeToUuid(IFMapNode *node, boost::uuids::uuid &u) { VirtualNetwork *cfg = static_cast (node->GetObject()); assert(cfg); autogen::IdPermsType id_perms = cfg->id_perms(); - boost::uuids::uuid u; CfgUuidSet(id_perms.uuid.uuid_mslong, id_perms.uuid.uuid_lslong, u); - req.key.reset(new VnKey(u)); + return true; +} + +bool VnTable::IFLinkToReq(IFMapLink *link, IFMapNode *node, + const string &peer_type, IFMapNode *peer, + DBRequest &req) { + // Add/Delete of link other than VMInterface will most likely need re-eval - // of VN - if (peer->table() != agent()->cfg()->cfg_vm_interface_table()) { + // of VN. + if (peer_type != "virtual-machine-interface") { + VirtualNetwork *cfg = static_cast (node->GetObject()); + assert(cfg); + boost::uuids::uuid u; + agent()->cfg_listener()->GetCfgDBStateUuid(node, u); + req.key.reset(new VnKey(u)); req.data.reset(BuildData(node)); Enqueue(&req); } - // Any change to ACL/IPAM will need re-eval of all VMInterface on this VN - if (peer->table() == agent()->cfg()->cfg_acl_table() || - peer->table() == agent()->cfg()->cfg_vn_network_ipam_table()) { - ResyncVmInterface(node); - } - - if (peer->table() == agent()->cfg()->cfg_vm_interface_table()) { - DBRequest req; - if (agent()->interface_table()->IFNodeToReq(peer, req) == true) { + // If peer is VMI, invoke re-eval if peer node is present + if (peer && peer->table() == agent()->cfg()->cfg_vm_interface_table()) { + DBRequest vmi_req; + if (agent()->interface_table()->IFNodeToReq(peer, vmi_req) == true) { LOG(DEBUG, "VN change sync for Port " << peer->name()); - agent()->interface_table()->Enqueue(&req); + agent()->interface_table()->Enqueue(&vmi_req); } + return false; + } + + // Any change to ACL/IPAM will need re-eval of all VMInterface on this VN + if (peer_type == "virtual-network-network-ipam" || + peer_type == "access-control-list") { + ResyncVmInterface(node); + return false; } - if (peer->table() == agent()->cfg()->cfg_floatingip_pool_table()) { + // If peer is known and is floating-ip pool, propogate change to it + if (peer && peer->table() == agent()->cfg()->cfg_floatingip_pool_table()) { VmInterface::FloatingIpPoolSync(agent()->interface_table(), peer); + return false; } return false; @@ -700,7 +715,9 @@ bool VnTable::IFNodeToReq(IFMapNode *node, DBRequest &req) { assert(cfg); autogen::IdPermsType id_perms = cfg->id_perms(); boost::uuids::uuid u; - CfgUuidSet(id_perms.uuid.uuid_mslong, id_perms.uuid.uuid_lslong, u); + if (agent()->cfg_listener()->GetCfgDBStateUuid(node, u) == false) + return false; + req.key.reset(new VnKey(u)); VnData *data = NULL; @@ -710,7 +727,7 @@ bool VnTable::IFNodeToReq(IFMapNode *node, DBRequest &req) { req.oper = DBRequest::DB_ENTRY_ADD_CHANGE; data = BuildData(node); req.data.reset(data); - data->SetIFMapNode(agent(), node); + data->SetIFMapNode(node); } Enqueue(&req); @@ -756,7 +773,7 @@ void VnTable::AddVn(const uuid &vn_uuid, const string &name, int vxlan_id, bool admin_state, bool enable_rpf) { DBRequest req; VnKey *key = new VnKey(vn_uuid); - VnData *data = new VnData(name, acl_id, vrf_name, nil_uuid(), + VnData *data = new VnData(agent(), name, acl_id, vrf_name, nil_uuid(), nil_uuid(), ipam, vn_ipam_data, vxlan_id, vxlan_id, true, true, admin_state, enable_rpf); diff --git a/src/vnsw/agent/oper/vn.h b/src/vnsw/agent/oper/vn.h index 11311fcef25..8d80e92c4c9 100644 --- a/src/vnsw/agent/oper/vn.h +++ b/src/vnsw/agent/oper/vn.h @@ -83,12 +83,12 @@ struct VnData : public AgentOperDBData { typedef std::map VnIpamDataMap; typedef std::pair VnIpamDataPair; - VnData(const string &name, const uuid &acl_id, const string &vrf_name, - const uuid &mirror_acl_id, const uuid &mc_acl_id, + VnData(const Agent *agent, const string &name, const uuid &acl_id, + const string &vrf_name, const uuid &mirror_acl_id, const uuid &mc_acl_id, const std::vector &ipam, const VnIpamDataMap &vn_ipam_data, int vxlan_id, int vnid, bool bridging, bool layer3_forwarding, bool admin_state, bool enable_rpf) : - AgentOperDBData(NULL, NULL), name_(name), vrf_name_(vrf_name), + AgentOperDBData(agent, NULL), name_(name), vrf_name_(vrf_name), acl_id_(acl_id), mirror_acl_id_(mirror_acl_id), mirror_cfg_acl_id_(mc_acl_id), ipam_(ipam), vn_ipam_data_(vn_ipam_data), vxlan_id_(vxlan_id), vnid_(vnid), bridging_(bridging), @@ -152,7 +152,7 @@ class VnEntry : AgentRefCount, public AgentOperDBEntry { bool ReEvaluateVxlan(VrfEntry *old_vrf, int new_vxlan_id, int new_vnid, bool new_bridging, bool vxlan_network_identifier_mode_changed); - void UpdateDhcpFloodFlag(); + void UpdateMacVmBindingFloodFlag(); const VxLanId *vxlan_id_ref() const {return vxlan_id_ref_.get();} const VxLanId *vxlan_id() const {return vxlan_id_ref_.get();} @@ -209,8 +209,10 @@ class VnTable : public AgentOperDBTable { void ResyncVmInterface(IFMapNode *node); virtual bool IFNodeToReq(IFMapNode *node, DBRequest &req); - virtual bool IFLinkToReq(IFMapLink *link, IFMapNode *node, IFMapNode *peer, + virtual bool IFLinkToReq(IFMapLink *link, IFMapNode *node, + const std::string &peer_type, IFMapNode *peer, DBRequest &req); + virtual bool IFNodeToUuid(IFMapNode *node, boost::uuids::uuid &u); static DBTableBase *CreateTable(DB *db, const std::string &name); static VnTable *GetInstance() {return vn_table_;}; diff --git a/src/vnsw/agent/oper/vrf.cc b/src/vnsw/agent/oper/vrf.cc index e760fb22e85..827d977d0cb 100644 --- a/src/vnsw/agent/oper/vrf.cc +++ b/src/vnsw/agent/oper/vrf.cc @@ -607,23 +607,27 @@ static VrfData *BuildData(Agent *agent, IFMapNode *node) { return new VrfData(VrfData::ConfigVrf, vn_uuid); } -bool VrfTable::IFLinkToReq(IFMapLink *link, IFMapNode *node, IFMapNode *peer, +bool VrfTable::IFLinkToReq(IFMapLink *link, IFMapNode *node, + const string &peer_type, IFMapNode *peer, DBRequest &req) { - req.oper = DBRequest::DB_ENTRY_ADD_CHANGE; - req.key.reset(new VrfKey(node->name())); - - if (peer->table() == agent()->cfg()->cfg_vn_table()) { - // Change in VN neighbour can change VN in the VRF - req.data.reset(BuildData(agent(), node)); - Enqueue(&req); - - // Resync dependent Floating-IP - VmInterface::FloatingIpVnSync(agent()->interface_table(), peer); - } - - // Change to virtual-machine-interface-routing-instance can modify VRF - // in connected VMInterface - if (peer->table() == agent()->cfg()->cfg_vm_port_vrf_table()) { + // If peer is VN, it means there is change in VRF to VN link. This can + // affect config for config modules. Invoke IFNodeToReq iteself. This + // should not affect scaling since we dont expect many changes for + // VN to VRF link + if (peer_type == "virtual-network") { + return IFNodeToReq(node, req); + } + + // Another neighbour we are interested in + // virtual-machine-interface-routing-instance. Change to think link can + // modify VRF for connected interface. There are two cases here, + // peer is NULL : + // Means, virtual-machine-interface-routing-instance node is deleted. + // It also means, VMI link is also deleted and it would have taken + // care of the necessary changes. + // peer is Non-NULL: + // Propogate change till the connected VMI + if (peer && peer->table() == agent()->cfg()->cfg_vm_port_vrf_table()) { if (agent()->cfg_listener()->SkipNode (peer, agent()->cfg()->cfg_vm_port_vrf_table())) { return false; diff --git a/src/vnsw/agent/oper/vrf.h b/src/vnsw/agent/oper/vrf.h index 1bd4bde223c..bb8d43209d0 100644 --- a/src/vnsw/agent/oper/vrf.h +++ b/src/vnsw/agent/oper/vrf.h @@ -169,7 +169,8 @@ class VrfTable : public AgentDBTable { static VrfTable *GetInstance() {return vrf_table_;}; virtual bool IFNodeToReq(IFMapNode *node, DBRequest &req); - virtual bool IFLinkToReq(IFMapLink *link, IFMapNode *node, IFMapNode *peer, + virtual bool IFLinkToReq(IFMapLink *link, IFMapNode *node, + const string &peer_type, IFMapNode *peer, DBRequest &req); VrfEntry *FindVrfFromName(const string &name); 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 9dbd0747be2..950565ec467 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 @@ -154,6 +154,10 @@ OvsdbClientIdl::OvsdbMsg::OvsdbMsg(struct jsonrpc_msg *m) : msg(m) { } OvsdbClientIdl::OvsdbMsg::~OvsdbMsg() { + if (this->msg != NULL) { + ovsdb_wrapper_jsonrpc_msg_destroy(this->msg); + this->msg = NULL; + } } void OvsdbClientIdl::OnEstablish() { @@ -244,9 +248,9 @@ void OvsdbClientIdl::MessageProcess(const u_int8_t *buf, std::size_t len) { bool OvsdbClientIdl::ProcessMessage(OvsdbMsg *msg) { if (!deleted_) { ovsdb_wrapper_idl_msg_process(idl_, msg->msg); + // msg->msg is freed by process method above + msg->msg = NULL; } - // msg->msg is freed by process method above - msg->msg = NULL; delete msg; return true; } 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 6e80a9de2cd..0599fcaa572 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 @@ -108,6 +108,7 @@ class OvsdbClientIdl { KSyncObjectManager *ksync_obj_manager(); OvsPeer *route_peer(); + bool deleted() { return deleted_; } Agent *agent() {return agent_;} VMInterfaceKSyncObject *vm_interface_table(); PhysicalSwitchTable *physical_switch_table(); diff --git a/src/vnsw/agent/ovs_tor_agent/ovsdb_client/ovsdb_route_peer.cc b/src/vnsw/agent/ovs_tor_agent/ovsdb_client/ovsdb_route_peer.cc index 7ee3d1719fa..467b1718769 100644 --- a/src/vnsw/agent/ovs_tor_agent/ovsdb_client/ovsdb_route_peer.cc +++ b/src/vnsw/agent/ovs_tor_agent/ovsdb_client/ovsdb_route_peer.cc @@ -51,9 +51,9 @@ bool OvsPeer::AddOvsRoute(const VnEntry *vn, uint32_t vxlan_id = vn->vxlan_id()->vxlan_id(); SecurityGroupList sg_list; - InterfaceTable *intf_table = agent->interface_table(); - const VmInterface *vmi = dynamic_cast - (intf_table->mac_vm_binding().FindMacVmBinding(mac, vxlan_id)); + BridgeAgentRouteTable *bridge_table = + dynamic_cast(vrf->GetBridgeRouteTable()); + const VmInterface *vmi = bridge_table->FindVmFromDhcpBinding(mac); if (vmi) { vmi->CopySgIdList(&sg_list); } diff --git a/src/vnsw/agent/ovs_tor_agent/ovsdb_client/unicast_mac_remote_ovsdb.cc b/src/vnsw/agent/ovs_tor_agent/ovsdb_client/unicast_mac_remote_ovsdb.cc index fe5f3659ed2..5ab20fe20d8 100644 --- a/src/vnsw/agent/ovs_tor_agent/ovsdb_client/unicast_mac_remote_ovsdb.cc +++ b/src/vnsw/agent/ovs_tor_agent/ovsdb_client/unicast_mac_remote_ovsdb.cc @@ -280,6 +280,17 @@ OvsdbDBEntry *UnicastMacRemoteTable::AllocOvsEntry(struct ovsdb_idl_row *row) { return static_cast(Create(&key)); } +KSyncDBObject::DBFilterResp UnicastMacRemoteTable::DBEntryFilter( + const DBEntry *db_entry) { + // Since Object delete for unicast remote table happens by db + // walk on vrf table, it needs to implement filter to ignore + // db Add/Change notifications if idl is marked deleted. + if (client_idl()->deleted()) { + return DBFilterIgnore; + } + return DBFilterAccept; +} + void UnicastMacRemoteTable::ManagedDelete() { deleted_ = true; Unregister(); diff --git a/src/vnsw/agent/ovs_tor_agent/ovsdb_client/unicast_mac_remote_ovsdb.h b/src/vnsw/agent/ovs_tor_agent/ovsdb_client/unicast_mac_remote_ovsdb.h index 20dfd7857e4..a776547c733 100644 --- a/src/vnsw/agent/ovs_tor_agent/ovsdb_client/unicast_mac_remote_ovsdb.h +++ b/src/vnsw/agent/ovs_tor_agent/ovsdb_client/unicast_mac_remote_ovsdb.h @@ -25,6 +25,9 @@ class UnicastMacRemoteTable : public OvsdbDBObject { KSyncEntry *Alloc(const KSyncEntry *key, uint32_t index); KSyncEntry *DBToKSyncEntry(const DBEntry*); OvsdbDBEntry *AllocOvsEntry(struct ovsdb_idl_row *row); + + KSyncDBObject::DBFilterResp DBEntryFilter(const DBEntry *entry); + void ManagedDelete(); void Unregister(); virtual void EmptyTable(); diff --git a/src/vnsw/agent/ovs_tor_agent/tor_agent_init.cc b/src/vnsw/agent/ovs_tor_agent/tor_agent_init.cc index 37fc2d06356..fc7fb87a3b1 100644 --- a/src/vnsw/agent/ovs_tor_agent/tor_agent_init.cc +++ b/src/vnsw/agent/ovs_tor_agent/tor_agent_init.cc @@ -76,7 +76,8 @@ void TorAgentInit::CreateModules() { ovsdb_client_.reset(OvsdbClient::Allocate(agent(), static_cast(agent_param()), ovs_peer_manager())); - uve_.reset(new AgentUveBase(agent(), AgentUveBase::kBandwidthInterval)); + uve_.reset(new AgentUveBase(agent(), AgentUveBase::kBandwidthInterval, + true)); agent()->set_uve(uve_.get()); } diff --git a/src/vnsw/agent/pkt/flow_table.cc b/src/vnsw/agent/pkt/flow_table.cc index e7ea3dfbd53..c230ce2558f 100644 --- a/src/vnsw/agent/pkt/flow_table.cc +++ b/src/vnsw/agent/pkt/flow_table.cc @@ -3043,7 +3043,7 @@ AgentRoute *FlowTable::GetL2Route(const VrfEntry *vrf, const MacAddress &mac) { BridgeAgentRouteTable *table = static_cast (vrf->GetBridgeRouteTable()); - return table->FindRoute(agent(), vrf->GetName(), mac); + return table->FindRoute(mac); } AgentRoute *FlowTable::GetUcRoute(const VrfEntry *entry, diff --git a/src/vnsw/agent/pkt/pkt_flow_info.cc b/src/vnsw/agent/pkt/pkt_flow_info.cc index 94e3da9f17f..d6b185619ac 100644 --- a/src/vnsw/agent/pkt/pkt_flow_info.cc +++ b/src/vnsw/agent/pkt/pkt_flow_info.cc @@ -258,7 +258,20 @@ static bool NhDecode(const NextHop *nh, const PktInfo *pkt, PktFlowInfo *info, const InetUnicastRouteEntry *rt = static_cast(in->rt_); if (rt != NULL && rt->GetLocalNextHop()) { - out->nh_ = GetPolicyEnabledNH(rt->GetLocalNextHop())->id(); + const NextHop *local_nh = rt->GetLocalNextHop(); + out->nh_ = local_nh->id(); + if (local_nh->GetType() == NextHop::INTERFACE) { + const Interface *local_intf = + static_cast(local_nh)->GetInterface(); + //Get policy enabled nexthop only for + //vm interface, in case of vgw or service interface in + //transparent mode we should still + //use policy disabled interface + if (local_intf && + local_intf->type() == Interface::VM_INTERFACE) { + out->nh_ = GetPolicyEnabledNH(local_nh)->id(); + } + } } else { out->nh_ = in->nh_; } diff --git a/src/vnsw/agent/pkt/pkt_handler.cc b/src/vnsw/agent/pkt/pkt_handler.cc index 47b3c50c662..ffcdbaca36c 100644 --- a/src/vnsw/agent/pkt/pkt_handler.cc +++ b/src/vnsw/agent/pkt/pkt_handler.cc @@ -16,7 +16,6 @@ #include "oper/route_common.h" #include "oper/vrf.h" #include "oper/tunnel_nh.h" -#include "oper/mac_vm_binding.h" #include "pkt/control_interface.h" #include "pkt/pkt_handler.h" #include "pkt/proto.h" @@ -229,7 +228,7 @@ void PktHandler::ComputeForwardingMode(PktInfo *pkt_info) const { BridgeAgentRouteTable *l2_table = static_cast (vrf->GetBridgeRouteTable()); AgentRoute *rt = static_cast - (l2_table->FindRoute(agent_, vrf->GetName(), pkt_info->dmac)); + (l2_table->FindRoute(pkt_info->dmac)); if (rt == NULL) { return; } @@ -363,6 +362,17 @@ int PktHandler::ParseIpPacket(PktInfo *pkt_info, PktType::Type &pkt_type, if (icmp->icmp_type == ICMP_ECHO || icmp->icmp_type == ICMP_ECHOREPLY) { pkt_info->dport = ICMP_ECHOREPLY; pkt_info->sport = htons(icmp->icmp_id); + } else if (icmp->icmp_type == ICMP_DEST_UNREACH) { + //Agent has to look at inner payload + //and recalculate the parameter + ParseIpPacket(pkt_info, pkt_type, pkt + len + sizeof(icmp)); + //Swap the key parameter, which would be used as key + IpAddress src_ip = pkt_info->ip_saddr; + pkt_info->ip_saddr = pkt_info->ip_daddr; + pkt_info->ip_daddr = src_ip; + uint16_t port = pkt_info->sport; + pkt_info->sport = pkt_info->dport; + pkt_info->dport = port; } else { pkt_info->sport = 0; } @@ -520,7 +530,6 @@ int PktHandler::ParseUserPkt(PktInfo *pkt_info, Interface *intf, // IP Packets len += ParseIpPacket(pkt_info, pkt_type, (pkt + len)); - // If it is a packet from TOR that we serve, dont parse any further if (IsManagedTORPacket(intf, pkt_info, pkt_type, (pkt + len))) { return len; @@ -614,8 +623,7 @@ bool PktHandler::IsToRDevice(uint32_t vrf_id, const IpAddress &ip) { if (table == NULL) return false; - BridgeRouteEntry *rt = table->FindRoute(agent(), vrf->GetName(), - MacAddress::BroadcastMac()); + BridgeRouteEntry *rt = table->FindRoute(MacAddress::BroadcastMac()); if (rt == NULL) return false; @@ -671,7 +679,6 @@ bool PktHandler::IsManagedTORPacket(Interface *intf, PktInfo *pkt_info, return false; // Get VXLAN id and point to original L2 frame after the VXLAN header - uint32_t vxlan = ntohl(*(uint32_t *)(pkt + 4)) >> 8; pkt += 8; // get to the actual packet header @@ -680,9 +687,14 @@ bool PktHandler::IsManagedTORPacket(Interface *intf, PktInfo *pkt_info, ether_addr addr; memcpy(addr.ether_addr_octet, pkt_info->eth->ether_shost, ETH_ALEN); MacAddress address(addr); - const Interface *vm_intf = - agent_->interface_table()-> - mac_vm_binding().FindMacVmBinding(address, vxlan); + const VrfEntry *vrf = agent_->vrf_table()-> + FindVrfFromId(pkt_info->agent_hdr.vrf); + if (vrf == NULL) + return false; + BridgeAgentRouteTable *bridge_table = + dynamic_cast(vrf->GetBridgeRouteTable()); + assert(bridge_table != NULL); + const VmInterface *vm_intf = bridge_table->FindVmFromDhcpBinding(address); if (vm_intf == NULL) { return false; } @@ -696,7 +708,6 @@ bool PktHandler::IsManagedTORPacket(Interface *intf, PktInfo *pkt_info, pkt_info->agent_hdr.cmd = AgentHdr::TRAP_TOR_CONTROL_PKT; pkt_info->agent_hdr.cmd_param = pkt_info->agent_hdr.ifindex; pkt_info->agent_hdr.ifindex = vm_intf->id(); - pkt_info->agent_hdr.vrf = vm_intf->vrf_id(); // Parse payload if (pkt_info->ether_type == ETHERTYPE_ARP) { diff --git a/src/vnsw/agent/pkt/pkt_handler.h b/src/vnsw/agent/pkt/pkt_handler.h index 5310652514a..7d261fba7c0 100644 --- a/src/vnsw/agent/pkt/pkt_handler.h +++ b/src/vnsw/agent/pkt/pkt_handler.h @@ -297,22 +297,6 @@ class PktHandler { PktModule *pkt_module() const { return pkt_module_; } private: - struct MacVmBindingKey { - MacAddress mac; - int vxlan; - InterfaceConstRef interface; - - MacVmBindingKey(const MacAddress &m, int v, InterfaceConstRef intf) : - mac(m), vxlan(v), interface(intf) {} - bool operator<(const MacVmBindingKey &rhs) const { - if (mac != rhs.mac) - return mac < rhs.mac; - - return vxlan < rhs.vxlan; - } - }; - typedef std::set MacVmBindingSet; - int ParseEthernetHeader(PktInfo *pkt_info, uint8_t *pkt); int ParseMplsHdr(PktInfo *pkt_info, uint8_t *pkt); int ParseIpPacket(PktInfo *pkt_info, PktType::Type &pkt_type, diff --git a/src/vnsw/agent/pkt/test/test_ecmp.cc b/src/vnsw/agent/pkt/test/test_ecmp.cc index aa5a084e888..5b9d96febe3 100644 --- a/src/vnsw/agent/pkt/test/test_ecmp.cc +++ b/src/vnsw/agent/pkt/test/test_ecmp.cc @@ -2263,6 +2263,67 @@ TEST_F(EcmpTest, TrapFlag) { client->WaitForIdle(); } +//Send a packet from vgw to ecmp destination +TEST_F(EcmpTest, VgwFlag) { + Agent *agent = Agent::GetInstance(); + InetInterface::CreateReq(agent->interface_table(), "vgw1", + InetInterface::SIMPLE_GATEWAY, "vrf2", + Ip4Address(0), 0, Ip4Address(0), Agent::NullString(), + ""); + client->WaitForIdle(); + + InetInterfaceKey *intf_key = new InetInterfaceKey("vgw1"); + std::auto_ptr nh_key(new InterfaceNHKey(intf_key, false, + InterfaceNHFlags::INET4)); + + Ip4Address remote_server_ip1 = Ip4Address::from_string("10.10.10.100"); + ComponentNHKeyPtr nh_data1(new ComponentNHKey(16, nh_key)); + ComponentNHKeyPtr nh_data2(new ComponentNHKey(20, agent->fabric_vrf_name(), + agent->router_id(), + remote_server_ip1, + false, + TunnelType::DefaultType())); + Ip4Address ip = Ip4Address::from_string("0.0.0.0"); + ComponentNHKeyList comp_nh_list; + comp_nh_list.push_back(nh_data1); + comp_nh_list.push_back(nh_data2); + EcmpTunnelRouteAdd(bgp_peer, "vrf2", ip, 0, + comp_nh_list, false, "vn2", + SecurityGroupList(), PathPreference()); + client->WaitForIdle(); + + InetInterfaceKey tmp_key("vgw1"); + Interface *intf = + static_cast(agent->interface_table()-> + FindActiveEntry(&tmp_key)); + + //Send packet on vgw interface + TxIpPacket(intf->id(), "100.1.1.1", "2.2.2.2", 1); + client->WaitForIdle(); + + FlowEntry *entry; + FlowEntry *rev_entry; + entry = FlowGet(VrfGet("vrf2")->vrf_id(), + "2.2.2.2", "100.1.1.1", 1, 0, 0, intf->flow_key_nh()->id()); + EXPECT_TRUE(entry != NULL); + EXPECT_TRUE(entry->data().component_nh_idx == + CompositeNH::kInvalidComponentNHIdx); + + rev_entry = FlowGet(VrfGet("vrf2")->vrf_id(), + "100.1.1.1", "2.2.2.2", 1, 0, 0, intf->flow_key_nh()->id()); + EXPECT_TRUE(rev_entry != NULL); + EXPECT_TRUE(rev_entry->data().component_nh_idx == + CompositeNH::kInvalidComponentNHIdx); + + client->WaitForIdle(); + agent->fabric_inet4_unicast_table()->DeleteReq(bgp_peer, "vrf2", + ip, 0, NULL); + InetInterface::DeleteReq(agent->interface_table(), "vgw1"); + client->WaitForIdle(); + WAIT_FOR(1000, 1000, (Agent::GetInstance()->pkt()-> + flow_table()->Size() == 0)); +} + int main(int argc, char *argv[]) { GETUSERARGS(); client = TestInit(init_file, ksync_init, true, true, true, 100*1000); diff --git a/src/vnsw/agent/services/arp_entry.cc b/src/vnsw/agent/services/arp_entry.cc index 274d85c8ef7..3736f9e8232 100644 --- a/src/vnsw/agent/services/arp_entry.cc +++ b/src/vnsw/agent/services/arp_entry.cc @@ -175,7 +175,7 @@ void ArpEntry::SendArpRequest() { ip = vmi->GetGateway(); vrf_id = nh_vrf_->vrf_id(); if (vmi->parent()) { - intf_id = vmi->parent()->id(); + intf_id = vmi->id(); smac = vmi->parent()->mac(); } } else { diff --git a/src/vnsw/agent/services/arp_proto.cc b/src/vnsw/agent/services/arp_proto.cc index e3d5fe7f6cd..4ef4e553217 100644 --- a/src/vnsw/agent/services/arp_proto.cc +++ b/src/vnsw/agent/services/arp_proto.cc @@ -205,12 +205,10 @@ void ArpDBState::UpdateArpRoutes(const InetUnicastRouteEntry *rt) { ArpProto::ArpIterator start_iter = vrf_state_->arp_proto->FindUpperBoundArpEntry(start_key); - if (start_iter->first.vrf != rt->vrf()) { - return; - } - - while (IsIp4SubnetMember(Ip4Address(start_iter->first.ip), + while (start_iter != vrf_state_->arp_proto->arp_cache().end() && + start_iter->first.vrf == rt->vrf() && + IsIp4SubnetMember(Ip4Address(start_iter->first.ip), rt->addr().to_v4(), plen)) { start_iter->second->Resync(policy_, vn_, sg_list_); start_iter++; @@ -226,11 +224,9 @@ void ArpDBState::Delete(const InetUnicastRouteEntry *rt) { ArpProto::ArpIterator start_iter = vrf_state_->arp_proto->FindUpperBoundArpEntry(start_key); - if (start_iter->first.vrf != rt->vrf()) { - return; - } - - while (IsIp4SubnetMember(Ip4Address(start_iter->first.ip), + while (start_iter != vrf_state_->arp_proto->arp_cache().end() && + start_iter->first.vrf == rt->vrf() && + IsIp4SubnetMember(Ip4Address(start_iter->first.ip), rt->addr().to_v4(), plen)) { ArpProto::ArpIterator tmp = start_iter++; if (tmp->second->DeleteArpRoute()) { diff --git a/src/vnsw/agent/services/test/arp_test.cc b/src/vnsw/agent/services/test/arp_test.cc index 98684a351af..f4899c2e88b 100644 --- a/src/vnsw/agent/services/test/arp_test.cc +++ b/src/vnsw/agent/services/test/arp_test.cc @@ -660,6 +660,14 @@ TEST_F(ArpTest, DISABLED_SubnetResolveWithoutPolicy) { EXPECT_TRUE(VmPortFind(8)); client->Reset(); + AddPhysicalDevice(agent->host_name().c_str(), 1); + AddPhysicalInterface("pi1", 1, "pid1"); + AddLogicalInterface("lp1", 1, "lp1", 1); + AddLink("physical-router", "prouter1", "physical-interface", "pi1"); + AddLink("logical-interface", "lp1", "physical-interface", "pi1"); + AddLink("virtual-machine-interface", "vnet8", "logical-interface", "lp1"); + client->WaitForIdle(); + //Add a link to interface subnet and ensure resolve route is added AddSubnetType("subnet", 1, "8.1.1.0", 24); AddLink("virtual-machine-interface", input1[0].name, @@ -830,6 +838,14 @@ TEST_F(ArpTest, DISABLED_SubnetResolveWithSg) { EXPECT_TRUE(VmPortFind(8)); client->Reset(); + AddPhysicalDevice(agent->host_name().c_str(), 1); + AddPhysicalInterface("pi1", 1, "pid1"); + AddLogicalInterface("lp1", 1, "lp1", 1); + AddLink("physical-router", "prouter1", "physical-interface", "pi1"); + AddLink("logical-interface", "lp1", "physical-interface", "pi1"); + AddLink("virtual-machine-interface", "vnet8", "logical-interface", "lp1"); + client->WaitForIdle(); + AddSg("sg1", 1); AddAcl("acl1", 1); AddLink("security-group", "sg1", "access-control-list", "acl1"); @@ -863,6 +879,7 @@ TEST_F(ArpTest, DISABLED_SubnetResolveWithSg) { DelLink("security-group", "sg1", "access-control-list", "acl1"); DelAcl("acl1"); DelNode("security-group", "sg1"); + DelLink("virtual-machine-interface", "vnet8", "security-group", "sg1"); client->WaitForIdle(); DeleteVmportEnv(input1, 1, true, 1); client->WaitForIdle(); @@ -875,6 +892,121 @@ TEST_F(ArpTest, DISABLED_SubnetResolveWithSg) { client->Reset(); } +//Check leaked routes dont get updated +//when original route changes +TEST_F(ArpTest, DISABLED_SubnetResolveWithSg1) { + struct PortInfo input1[] = { + {"vnet8", 8, "8.1.1.1", "00:00:00:01:01:01", 1, 1}, + {"vnet9", 9, "9.1.1.1", "00:00:00:01:01:02", 2, 2} + }; + + client->Reset(); + //Create VM interface with policy + CreateVmportWithEcmp(input1, 2, 1); + client->WaitForIdle(); + EXPECT_TRUE(VmPortActive(input1, 0)); + EXPECT_TRUE(VmPortFind(8)); + client->Reset(); + + AddPhysicalDevice(agent->host_name().c_str(), 1); + AddPhysicalInterface("pi1", 1, "pid1"); + AddLogicalInterface("lp1", 1, "lp1", 1); + AddLink("physical-router", "prouter1", "physical-interface", "pi1"); + AddLink("logical-interface", "lp1", "physical-interface", "pi1"); + AddLink("virtual-machine-interface", "vnet8", "logical-interface", "lp1"); + client->WaitForIdle(); + + VmInterface *vintf8 = VmInterfaceGet(8); + VmInterface *vintf9 = VmInterfaceGet(9); + + AddSg("sg1", 1); + AddAcl("acl1", 1); + AddLink("security-group", "sg1", "access-control-list", "acl1"); + client->WaitForIdle(); + //Add a link to interface subnet and ensure resolve route is added + AddSubnetType("subnet", 1, "8.1.1.0", 24); + AddLink("virtual-machine-interface", input1[0].name, + "subnet", "subnet"); + client->WaitForIdle(); + EXPECT_TRUE(VmPortActive(input1, 0)); + EXPECT_TRUE(RouteFind("vrf1", "8.1.1.0", 24)); + + VmInterfaceKey key(AgentKey::ADD_DEL_CHANGE, MakeUuid(8), "vnet8"); + Ip4Address subnet = Ip4Address::from_string("8.1.1.0"); + InetUnicastAgentRouteTable::AddResolveRoute(vintf9->peer(), "vrf2", + subnet, 24, key, 0, false, + "vn1", SecurityGroupList()); + client->WaitForIdle(); + + Ip4Address sip = Ip4Address::from_string("9.1.1.1"); + Ip4Address dip = Ip4Address::from_string("8.1.1.2"); + Ip4Address dip1 = Ip4Address::from_string("8.1.1.3"); + SendArpReq(vintf9->id(), vintf9->vrf()->vrf_id(), sip.to_ulong(), dip.to_ulong()); + SendArpReq(vintf9->id(), vintf9->vrf()->vrf_id(), sip.to_ulong(), dip1.to_ulong()); + client->WaitForIdle(); + WAIT_FOR(500, 1000, + Agent::GetInstance()->GetArpProto()->GetArpCacheSize() == 5); + + WAIT_FOR(500, 1000, RouteFind("vrf2", "8.1.1.2", 32) == true); + WAIT_FOR(500, 1000, RouteFind("vrf2", "8.1.1.3", 32) == true); + AddLink("virtual-machine-interface", "vnet8", "security-group", "sg1"); + client->WaitForIdle(); + + //Verify that route update on vrf1 doesnt reevaluate vrf2 arp routes + AgentRoute *rt = RouteGet("vrf2", dip, 32); + EXPECT_TRUE(rt->GetActiveNextHop()->GetType() == NextHop::ARP); + EXPECT_TRUE(rt->GetActivePath()->dest_vn_name() == "vn1"); + EXPECT_TRUE(rt->GetActivePath()->sg_list().size() == 0); + rt = RouteGet("vrf2", dip1, 32); + EXPECT_TRUE(rt->GetActiveNextHop()->GetType() == NextHop::ARP); + EXPECT_TRUE(rt->GetActivePath()->dest_vn_name() == "vn1"); + EXPECT_TRUE(rt->GetActivePath()->sg_list().size() == 0); + + rt = RouteGet("vrf1", dip, 32); + EXPECT_TRUE(rt->GetActivePath()->sg_list().size() == 1); + rt = RouteGet("vrf1", dip1, 32); + EXPECT_TRUE(rt->GetActivePath()->sg_list().size() == 1); + + //Resync the same on leaked vrf + InetUnicastAgentRouteTable::AddResolveRoute(vintf9->peer(), "vrf2", + subnet, 24, key, 0, false, + "vn1", SecurityGroupList(1)); + client->WaitForIdle(); + + rt = RouteGet("vrf2", dip, 32); + EXPECT_TRUE(rt->GetActiveNextHop()->GetType() == NextHop::ARP); + EXPECT_TRUE(rt->GetActivePath()->dest_vn_name() == "vn1"); + EXPECT_TRUE(rt->GetActivePath()->sg_list().size() == 1); + + rt = RouteGet("vrf2", dip1, 32); + EXPECT_TRUE(rt->GetActiveNextHop()->GetType() == NextHop::ARP); + EXPECT_TRUE(rt->GetActivePath()->dest_vn_name() == "vn1"); + EXPECT_TRUE(rt->GetActivePath()->sg_list().size() == 1); + + rt = RouteGet("vrf1", dip, 32); + EXPECT_TRUE(rt->GetActivePath()->sg_list().size() == 1); + rt = RouteGet("vrf1", dip1, 32); + EXPECT_TRUE(rt->GetActivePath()->sg_list().size() == 1); + + DelLink("virtual-machine-interface", input1[0].name, + "subnet", "subnet"); + DelLink("security-group", "sg1", "access-control-list", "acl1"); + DelAcl("acl1"); + DelNode("security-group", "sg1"); + InetUnicastAgentRouteTable::DeleteReq(vintf9->peer(), "vrf2", + subnet, 24, NULL); + client->WaitForIdle(); + DeleteVmportEnv(input1, 2, true, 1); + client->WaitForIdle(); + WAIT_FOR(500, 1000, RouteFind("vrf1", "8.1.1.2", 32) == false); + EXPECT_EQ(1U, Agent::GetInstance()->GetArpProto()->GetArpCacheSize()); + + EXPECT_FALSE(VmPortFind(8)); + WAIT_FOR(100, 1000, (Agent::GetInstance()->interface_table()->Find(&key, true) + == NULL)); + client->Reset(); +} + TEST_F(ArpTest, IntfArpReqTest_1) { struct PortInfo input[] = { {"vnet1", 1, "1.1.1.1", "00:00:00:01:01:01", 1, 1}, diff --git a/src/vnsw/agent/test-xml/test_xml_oper.cc b/src/vnsw/agent/test-xml/test_xml_oper.cc index 27e22a28d08..4a625055902 100644 --- a/src/vnsw/agent/test-xml/test_xml_oper.cc +++ b/src/vnsw/agent/test-xml/test_xml_oper.cc @@ -1270,9 +1270,11 @@ bool AgentUtXmlL2RouteValidate::ReadXml() { bool AgentUtXmlL2RouteValidate::Validate() { Agent *agent = Agent::GetInstance(); + BridgeAgentRouteTable *bridge_table = + static_cast + (agent->vrf_table()->GetBridgeRouteTable(vrf_)); BridgeRouteEntry *rt = - BridgeAgentRouteTable::FindRoute(agent, vrf_, - MacAddress::FromString(mac_)); + bridge_table->FindRoute(MacAddress::FromString(mac_)); if (present() == false) return (rt == NULL); diff --git a/src/vnsw/agent/test/test_cfg.cc b/src/vnsw/agent/test/test_cfg.cc index 025e947c9f4..19bfb731614 100644 --- a/src/vnsw/agent/test/test_cfg.cc +++ b/src/vnsw/agent/test/test_cfg.cc @@ -1858,7 +1858,6 @@ TEST_F(CfgTest, StaleTimeoutDeferList) { TestFoo = static_cast(iter.operator->()); EXPECT_EQ("testfoo", TestFoo->name()); } -#if 1 //Repeat the same with two hanging links sprintf(buff, @@ -1978,11 +1977,219 @@ TEST_F(CfgTest, StaleTimeoutDeferList) { TestFoo = static_cast(iter.operator->()); EXPECT_EQ("testfoo", TestFoo->name()); } -#endif delete cl; } +TEST_F(CfgTest, LinkMetadata) { + char buff[1500]; + sprintf(buff, + "\n" + " \n" + " testfoo\n" + " \n" + " \n" + " testbar\n" + " \n" + " \n" + " \n" + " testfoo\n" + " \n" + " \n" + " testbar\n" + " \n" + " " + " \n" + ""); + + IFMapTable *ftable = IFMapTable::FindTable(&db_, "foo"); + ASSERT_TRUE(ftable!=NULL); + + IFMapTable *btable = IFMapTable::FindTable(&db_, "bar"); + ASSERT_TRUE(btable!=NULL); + + IFMapAgentLinkTable *ltable = static_cast( + db_.FindTable(IFMAP_AGENT_LINK_DB_NAME)); + ASSERT_TRUE(ltable!=NULL); + + pugi::xml_parse_result result = xdoc_.load(buff); + EXPECT_TRUE(result); + parser_->ConfigParse(xdoc_, 0); + WaitForIdle(); + + //Ensure that both nodes are added fine along with attribute + IFMapNode *TestFoo = ftable->FindNode("testfoo"); + ASSERT_TRUE(TestFoo !=NULL); + EXPECT_EQ("testfoo", TestFoo->name()); + + IFMapNode *TestBar = btable->FindNode("testbar"); + ASSERT_TRUE(TestBar !=NULL); + EXPECT_EQ("testbar", TestBar->name()); + + IFMapLink *link = static_cast(graph_.GetEdge(TestFoo, TestBar)); + assert(link); + EXPECT_EQ(link->metadata(), "foo-bar"); +} + +TEST_F(CfgTest, DefLinkMetadata) { + char buff[1500]; + sprintf(buff, + "\n" + " \n" + " \n" + " testfoo\n" + " \n" + " \n" + " testbar\n" + " \n" + " " + " \n" + ""); + + IFMapTable *ftable = IFMapTable::FindTable(&db_, "foo"); + ASSERT_TRUE(ftable!=NULL); + + IFMapTable *btable = IFMapTable::FindTable(&db_, "bar"); + ASSERT_TRUE(btable!=NULL); + + IFMapAgentLinkTable *ltable = static_cast( + db_.FindTable(IFMAP_AGENT_LINK_DB_NAME)); + ASSERT_TRUE(ltable!=NULL); + + pugi::xml_parse_result result = xdoc_.load(buff); + EXPECT_TRUE(result); + parser_->ConfigParse(xdoc_, 0); + WaitForIdle(); + + sprintf(buff, + "\n" + " \n" + " testfoo\n" + " \n" + " \n" + " testbar\n" + " \n" + ""); + + result = xdoc_.load(buff); + EXPECT_TRUE(result); + parser_->ConfigParse(xdoc_, 0); + WaitForIdle(); + + //Ensure that both nodes are added fine along with attribute + IFMapNode *TestFoo = ftable->FindNode("testfoo"); + ASSERT_TRUE(TestFoo !=NULL); + EXPECT_EQ("testfoo", TestFoo->name()); + + IFMapNode *TestBar = btable->FindNode("testbar"); + ASSERT_TRUE(TestBar !=NULL); + EXPECT_EQ("testbar", TestBar->name()); + + IFMapLink *link = static_cast(graph_.GetEdge(TestFoo, TestBar)); + assert(link); + EXPECT_EQ(link->metadata(), "foo-bar"); +} + +TEST_F(CfgTest, NodeDelLinkMetadata) { + char buff[1500]; + sprintf(buff, + "\n" + " \n" + " \n" + " testfoo\n" + " \n" + " \n" + " testbar\n" + " \n" + " " + " \n" + ""); + + IFMapTable *ftable = IFMapTable::FindTable(&db_, "foo"); + ASSERT_TRUE(ftable!=NULL); + + IFMapTable *btable = IFMapTable::FindTable(&db_, "bar"); + ASSERT_TRUE(btable!=NULL); + + IFMapAgentLinkTable *ltable = static_cast( + db_.FindTable(IFMAP_AGENT_LINK_DB_NAME)); + ASSERT_TRUE(ltable!=NULL); + + pugi::xml_parse_result result = xdoc_.load(buff); + EXPECT_TRUE(result); + parser_->ConfigParse(xdoc_, 0); + WaitForIdle(); + + sprintf(buff, + "\n" + " \n" + " testfoo\n" + " \n" + " \n" + " testbar\n" + " \n" + ""); + + result = xdoc_.load(buff); + EXPECT_TRUE(result); + parser_->ConfigParse(xdoc_, 0); + WaitForIdle(); + + //Ensure that both nodes are added fine along with attribute + IFMapNode *TestFoo = ftable->FindNode("testfoo"); + ASSERT_TRUE(TestFoo !=NULL); + EXPECT_EQ("testfoo", TestFoo->name()); + + IFMapNode *TestBar = btable->FindNode("testbar"); + ASSERT_TRUE(TestBar !=NULL); + EXPECT_EQ("testbar", TestBar->name()); + + IFMapLink *link = static_cast(graph_.GetEdge(TestFoo, TestBar)); + assert(link); + EXPECT_EQ(link->metadata(), "foo-bar"); + + sprintf(buff, + "\n" + " \n" + " testfoo\n" + " \n" + "\n"); + + result = xdoc_.load(buff); + EXPECT_TRUE(result); + parser_->ConfigParse(xdoc_, 0); + WaitForIdle(); + + //Ensure that there is no link from Bar to foo as well + int count = 0; + for (DBGraphVertex::adjacency_iterator iter = TestBar->begin(&graph_); + iter != TestBar->end(&graph_); ++iter) { + count++; + } + EXPECT_EQ(count, 0); + + + sprintf(buff, + "\n" + " \n" + " testfoo\n" + " \n" + "\n"); + + result = xdoc_.load(buff); + EXPECT_TRUE(result); + parser_->ConfigParse(xdoc_, 0); + WaitForIdle(); + + TestFoo = ftable->FindNode("testfoo"); + ASSERT_TRUE(TestFoo !=NULL); + EXPECT_EQ("testfoo", TestFoo->name()); + + link = static_cast(graph_.GetEdge(TestFoo, TestBar)); + assert(link); + EXPECT_EQ(link->metadata(), "foo-bar"); +} + int main(int argc, char **argv) { LoggingInit(); ::testing::InitGoogleTest(&argc, argv); diff --git a/src/vnsw/agent/test/test_route.cc b/src/vnsw/agent/test/test_route.cc index cc198688ac5..14c9a77cfb4 100644 --- a/src/vnsw/agent/test/test_route.cc +++ b/src/vnsw/agent/test/test_route.cc @@ -123,7 +123,6 @@ class RouteTest : public ::testing::Test { TestRouteTable table3(3); WAIT_FOR(100, 1000, (table3.Size() == 0)); EXPECT_EQ(table3.Size(), 0U); - VrfDelReq(vrf_name_.c_str()); client->WaitForIdle(); WAIT_FOR(100, 1000, (VrfFind(vrf_name_.c_str()) != true)); @@ -1926,6 +1925,179 @@ TEST_F(RouteTest, NonEcmpToEcmpConversion) { EXPECT_TRUE(VrfFind("vrf8", true) == false); } +TEST_F(RouteTest, Dhcp_enabled_ipam) { + client->Reset(); + struct PortInfo input[] = { + {"vnet1", 1, "1.1.1.1", "00:00:00:01:01:01", 1, 1}, + }; + + IpamInfo ipam_info[] = { + {"1.1.1.0", 24, "1.1.1.200", true}, + }; + client->Reset(); + CreateVmportEnv(input, 1, 0); + client->WaitForIdle(); + AddIPAM("vn1", ipam_info, 1); + client->WaitForIdle(); + + //Find Bridge route + BridgeRouteEntry *rt = + L2RouteGet("vrf1", + MacAddress::FromString("00:00:00:01:01:01"), + Ip4Address::from_string("1.1.1.1")); + const AgentPath *path = rt->FindMacVmBindingPath(); + const MacVmBindingPath *dhcp_path = dynamic_cast(path); + EXPECT_TRUE(dhcp_path != NULL); + EXPECT_TRUE(dhcp_path->vm_interface()->GetUuid() == MakeUuid(1)); + EXPECT_TRUE(dhcp_path->nexthop()->GetType() == NextHop::DISCARD); + EXPECT_TRUE(dhcp_path->flood_dhcp() == false); + + client->Reset(); + DelIPAM("vn1"); + client->WaitForIdle(); + DeleteVmportEnv(input, 1, 1, 0); + client->WaitForIdle(); +} + +TEST_F(RouteTest, Dhcp_disabled_ipam) { + client->Reset(); + struct PortInfo input[] = { + {"vnet1", 1, "1.1.1.1", "00:00:00:01:01:01", 1, 1}, + }; + + IpamInfo ipam_info[] = { + {"1.1.1.0", 24, "1.1.1.200", false}, + }; + client->Reset(); + CreateVmportEnv(input, 1, 0); + client->WaitForIdle(); + AddIPAM("vn1", ipam_info, 1); + client->WaitForIdle(); + + //Find Bridge route + BridgeRouteEntry *rt = + L2RouteGet("vrf1", + MacAddress::FromString("00:00:00:01:01:01"), + Ip4Address::from_string("1.1.1.1")); + const MacVmBindingPath *dhcp_path = + dynamic_cast(rt->FindMacVmBindingPath()); + EXPECT_TRUE(dhcp_path != NULL); + EXPECT_TRUE(dhcp_path->vm_interface()->GetUuid() == MakeUuid(1)); + EXPECT_TRUE(dhcp_path->nexthop()->GetType() == NextHop::DISCARD); + EXPECT_TRUE(dhcp_path->flood_dhcp() == true); + + client->Reset(); + DelIPAM("vn1"); + client->WaitForIdle(); + DeleteVmportEnv(input, 1, 1, 0); + client->WaitForIdle(); +} + +TEST_F(RouteTest, Dhcp_mode_toggled_ipam) { + client->Reset(); + struct PortInfo input[] = { + {"vnet1", 1, "1.1.1.1", "00:00:00:01:01:01", 1, 1}, + {"vnet2", 2, "1.1.1.2", "00:00:00:01:01:02", 1, 1}, + }; + + IpamInfo ipam_info[] = { + {"1.1.1.0", 24, "1.1.1.200", true}, + }; + client->Reset(); + CreateVmportEnv(input, 2, 0); + client->WaitForIdle(); + AddIPAM("vn1", ipam_info, 1); + client->WaitForIdle(); + + //Find Bridge route + BridgeRouteEntry *rt = + L2RouteGet("vrf1", + MacAddress::FromString("00:00:00:01:01:01"), + Ip4Address::from_string("1.1.1.1")); + const AgentPath *path = rt->FindMacVmBindingPath(); + const MacVmBindingPath *dhcp_path = dynamic_cast(path); + EXPECT_TRUE(dhcp_path != NULL); + EXPECT_TRUE(dhcp_path->vm_interface()->GetUuid() == MakeUuid(1)); + EXPECT_TRUE(dhcp_path->nexthop()->GetType() == NextHop::DISCARD); + EXPECT_TRUE(dhcp_path->flood_dhcp() == false); + rt = L2RouteGet("vrf1", + MacAddress::FromString("00:00:00:01:01:02"), + Ip4Address::from_string("1.1.1.2")); + dhcp_path = dynamic_cast(rt->FindMacVmBindingPath()); + EXPECT_TRUE(dhcp_path->vm_interface()->GetUuid() == MakeUuid(2)); + EXPECT_TRUE(dhcp_path->nexthop()->GetType() == NextHop::DISCARD); + EXPECT_TRUE(dhcp_path->flood_dhcp() == false); + + //Toggle to disable + IpamInfo ipam_info_disabled[] = { + {"1.1.1.0", 24, "1.1.1.200", false}, + }; + AddIPAM("vn1", ipam_info_disabled, 1); + client->WaitForIdle(); + rt = L2RouteGet("vrf1", + MacAddress::FromString("00:00:00:01:01:01"), + Ip4Address::from_string("1.1.1.1")); + dhcp_path = dynamic_cast(rt->FindMacVmBindingPath()); + EXPECT_TRUE(dhcp_path->vm_interface()->GetUuid() == MakeUuid(1)); + EXPECT_TRUE(dhcp_path->nexthop()->GetType() == NextHop::DISCARD); + EXPECT_TRUE(dhcp_path->flood_dhcp() == true); + rt = L2RouteGet("vrf1", + MacAddress::FromString("00:00:00:01:01:02"), + Ip4Address::from_string("1.1.1.2")); + dhcp_path = dynamic_cast(rt->FindMacVmBindingPath()); + EXPECT_TRUE(dhcp_path->vm_interface()->GetUuid() == MakeUuid(2)); + EXPECT_TRUE(dhcp_path->nexthop()->GetType() == NextHop::DISCARD); + EXPECT_TRUE(dhcp_path->flood_dhcp() == true); + + //Toggle to enable + AddIPAM("vn1", ipam_info, 1); + client->WaitForIdle(); + rt = L2RouteGet("vrf1", + MacAddress::FromString("00:00:00:01:01:01"), + Ip4Address::from_string("1.1.1.1")); + dhcp_path = dynamic_cast(rt->FindMacVmBindingPath()); + EXPECT_TRUE(dhcp_path != NULL); + EXPECT_TRUE(dhcp_path->vm_interface()->GetUuid() == MakeUuid(1)); + EXPECT_TRUE(dhcp_path->nexthop()->GetType() == NextHop::DISCARD); + EXPECT_TRUE(dhcp_path->flood_dhcp() == false); + rt = L2RouteGet("vrf1", + MacAddress::FromString("00:00:00:01:01:02"), + Ip4Address::from_string("1.1.1.2")); + dhcp_path = dynamic_cast(rt->FindMacVmBindingPath()); + EXPECT_TRUE(dhcp_path->vm_interface()->GetUuid() == MakeUuid(2)); + EXPECT_TRUE(dhcp_path->nexthop()->GetType() == NextHop::DISCARD); + EXPECT_TRUE(dhcp_path->flood_dhcp() == false); + + client->Reset(); + DelIPAM("vn1"); + client->WaitForIdle(); + DeleteVmportEnv(input, 2, 1, 0); + client->WaitForIdle(); +} + +//Double delete ARP route and verify that ARP NH +//get deleted, since we always enqueu RESYNC for arp NH change +//from ARP route deletiong path +TEST_F(RouteTest, ArpRouteDelete) { + ArpNHKey key(Agent::GetInstance()->fabric_vrf_name(), server1_ip_, false); + + AddArp(server1_ip_.to_string().c_str(), "0a:0b:0c:0d:0e:0f", eth_name_.c_str()); + client->WaitForIdle(); + EXPECT_TRUE(FindNH(&key)); + EXPECT_TRUE(GetNH(&key)->IsValid() == true); + + //Delete Remote VM route + DelArp(server1_ip_.to_string(), "0a:0b:0c:0d:0e:0f", eth_name_.c_str()); + client->WaitForIdle(); + EXPECT_FALSE(RouteFind(vrf_name_, server1_ip_, 32)); + + DelArp(server1_ip_.to_string(), "0a:0b:0c:0d:0e:0f", eth_name_.c_str()); + client->WaitForIdle(); + EXPECT_FALSE(RouteFind(vrf_name_, server1_ip_, 32)); + + EXPECT_FALSE(FindNH(&key)); +} + int main(int argc, char *argv[]) { ::testing::InitGoogleTest(&argc, argv); GETUSERARGS(); diff --git a/src/vnsw/agent/test/test_util.cc b/src/vnsw/agent/test/test_util.cc index e71704208db..735c0a458fd 100644 --- a/src/vnsw/agent/test/test_util.cc +++ b/src/vnsw/agent/test/test_util.cc @@ -84,6 +84,15 @@ void DelLinkString(char *buff, int &len, const char *node_name1, len = strlen(buff); } +void AddNodeStringWithoutUuid(char *buff, int &len, const char + *node_name, const char *name) { + sprintf(buff + len, + " \n" + " %s\n" + " \n", node_name, name); + len = strlen(buff); +} + void AddNodeString(char *buff, int &len, const char *node_name, const char *name, int id, const char *attr, bool admin_state) { @@ -308,7 +317,10 @@ void AddNode(const char *node_name, const char *name, int id, int len = 0; AddXmlHdr(buff, len); - AddNodeString(buff, len, node_name, name, id, attr, admin_state); + if (id) + AddNodeString(buff, len, node_name, name, id, attr, admin_state); + else + AddNodeStringWithoutUuid(buff, len, node_name, name); AddXmlTail(buff, len); pugi::xml_document xdoc_; pugi::xml_parse_result result = xdoc_.load(buff); @@ -1077,8 +1089,15 @@ bool RouteFindV6(const string &vrf_name, const string &addr, int plen) { bool L2RouteFind(const string &vrf_name, const MacAddress &mac, const IpAddress &ip_addr) { - BridgeRouteEntry *route = - BridgeAgentRouteTable::FindRoute(Agent::GetInstance(), vrf_name, mac); + if (Agent::GetInstance()->vrf_table() == NULL) { + return false; + } + BridgeAgentRouteTable *bridge_table = + static_cast + (Agent::GetInstance()->vrf_table()->GetBridgeRouteTable(vrf_name)); + if (bridge_table == NULL) + return false; + BridgeRouteEntry *route = bridge_table->FindRoute(mac); return (route != NULL); } diff --git a/src/vnsw/agent/test/test_vn.cc b/src/vnsw/agent/test/test_vn.cc index b97feb8abfc..4d1f9ea2874 100644 --- a/src/vnsw/agent/test/test_vn.cc +++ b/src/vnsw/agent/test/test_vn.cc @@ -837,6 +837,133 @@ TEST_F(CfgTest, RpfEnableDisable) { client->WaitForIdle(); } + +TEST_F(CfgTest, CfgDBStateUuid) { + client->WaitForIdle(); + // Add VN with UUID + AddVn("vn1", 1); + client->WaitForIdle(); + + VnEntry *vn = VnGet(1); + ASSERT_TRUE(vn != NULL); + + //Get the config table + IFMapTable *table = + IFMapTable::FindTable(Agent::GetInstance()->db(),"virtual-network"); + ASSERT_TRUE(table != NULL); + + //Get the config node + IFMapNode *node = table->FindNode("vn1"); + ASSERT_TRUE(node != NULL); + + boost::uuids::uuid id; + EXPECT_TRUE(Agent::GetInstance()->cfg()->cfg_listener()-> + GetCfgDBStateUuid(node, id)); + EXPECT_EQ(id, MakeUuid(1)); + client->WaitForIdle(); + + //Ensure that Oper exists + ASSERT_TRUE(VnFind(1)); + + DelVn("vn1"); + client->WaitForIdle(); + + vn = VnGet(1); + ASSERT_TRUE(vn == NULL); + + //Ensure that Oper also does not exists + ASSERT_FALSE(VnFind(1)); +} + +TEST_F(CfgTest, CfgUuidNullDelete) { + client->WaitForIdle(); + // Add VN with UUID + AddVn("vn1", 1); + client->WaitForIdle(); + + VnEntry *vn = VnGet(1); + ASSERT_TRUE(vn != NULL); + + //Get the config table + IFMapTable *table = + IFMapTable::FindTable(Agent::GetInstance()->db(),"virtual-network"); + ASSERT_TRUE(table != NULL); + + //Get the config node + IFMapNode *node = table->FindNode("vn1"); + ASSERT_TRUE(node != NULL); + + boost::uuids::uuid id; + EXPECT_TRUE(Agent::GetInstance()->cfg()->cfg_listener()-> + GetCfgDBStateUuid(node, id)); + EXPECT_EQ(id, MakeUuid(1)); + + //Ensure that Oper exists + ASSERT_TRUE(VnFind(1)); + + //Send Uuid zero and verify that node is deleted + AddVn("vn1", 0); + client->WaitForIdle(); + + node = table->FindNode("vn1"); + ASSERT_TRUE(node == NULL); + + //Ensure that Oper is deleted + ASSERT_FALSE(VnFind(1)); +} + + +TEST_F(CfgTest, CfgUuidChange) { + client->WaitForIdle(); + // Add VN with UUID + AddVn("vn1", 1); + client->WaitForIdle(); + + VnEntry *vn = VnGet(1); + ASSERT_TRUE(vn != NULL); + + //Get the config table + IFMapTable *table = + IFMapTable::FindTable(Agent::GetInstance()->db(),"virtual-network"); + ASSERT_TRUE(table != NULL); + + //Get the config node + IFMapNode *node = table->FindNode("vn1"); + ASSERT_TRUE(node != NULL); + + boost::uuids::uuid id; + EXPECT_TRUE(Agent::GetInstance()->cfg()->cfg_listener()-> + GetCfgDBStateUuid(node, id)); + EXPECT_EQ(id, MakeUuid(1)); + + //Ensure that Oper exists + ASSERT_TRUE(VnFind(1)); + + //Send different Uuid + AddVn("vn1", 2); + client->WaitForIdle(); + + node = table->FindNode("vn1"); + ASSERT_TRUE(node != NULL); + + //Ensure that Oper exists + ASSERT_TRUE(VnFind(2)); + + //Ensure that Oper exists + ASSERT_TRUE(VnFind(1)); + + DelVn("vn1"); + client->WaitForIdle(); + + node = table->FindNode("vn1"); + ASSERT_TRUE(node != NULL); + + //Ensure that Oper exists for only 1 + ASSERT_TRUE(VnFind(1)); + ASSERT_FALSE(VnFind(2)); + +} + int main(int argc, char **argv) { GETUSERARGS(); diff --git a/src/vnsw/agent/uve/agent_uve.cc b/src/vnsw/agent/uve/agent_uve.cc index e683d47de39..36162f0a630 100644 --- a/src/vnsw/agent/uve/agent_uve.cc +++ b/src/vnsw/agent/uve/agent_uve.cc @@ -19,7 +19,7 @@ #include AgentUve::AgentUve(Agent *agent, uint64_t intvl) - : AgentUveBase(agent, intvl), + : AgentUveBase(agent, intvl, false), stats_manager_(new StatsManager(agent)) { //Override vm_uve_table_ to point to derived class object vn_uve_table_.reset(new VnUveTable(agent)); diff --git a/src/vnsw/agent/uve/agent_uve_base.cc b/src/vnsw/agent/uve/agent_uve_base.cc index 27ac62d67e2..e551d799d7c 100644 --- a/src/vnsw/agent/uve/agent_uve_base.cc +++ b/src/vnsw/agent/uve/agent_uve_base.cc @@ -27,15 +27,18 @@ using process::g_process_info_constants; AgentUveBase *AgentUveBase::singleton_; -AgentUveBase::AgentUveBase(Agent *agent, uint64_t intvl) - : vn_uve_table_(new VnUveTableBase(agent)), - vm_uve_table_(new VmUveTableBase(agent)), - vrouter_uve_entry_(new VrouterUveEntryBase(agent)), +AgentUveBase::AgentUveBase(Agent *agent, uint64_t intvl, bool create_objects) + : vn_uve_table_(NULL), vm_uve_table_(NULL), vrouter_uve_entry_(NULL), prouter_uve_table_(new ProuterUveTable(agent)), agent_(agent), bandwidth_intvl_(intvl), vrouter_stats_collector_(new VrouterStatsCollector( *(agent->event_manager()->io_service()), this)) { + if (create_objects) { + vn_uve_table_.reset(new VnUveTableBase(agent)); + vm_uve_table_.reset(new VmUveTableBase(agent)); + vrouter_uve_entry_.reset(new VrouterUveEntryBase(agent)); + } singleton_ = this; } diff --git a/src/vnsw/agent/uve/agent_uve_base.h b/src/vnsw/agent/uve/agent_uve_base.h index f8654222f4b..309e979a5c9 100644 --- a/src/vnsw/agent/uve/agent_uve_base.h +++ b/src/vnsw/agent/uve/agent_uve_base.h @@ -20,7 +20,7 @@ class VrouterStatsCollector; class AgentUveBase { public: static const uint64_t kBandwidthInterval = (1000000); // time in microseconds - AgentUveBase(Agent *agent, uint64_t intvl); + AgentUveBase(Agent *agent, uint64_t intvl, bool create_object); virtual ~AgentUveBase(); virtual void Shutdown(); diff --git a/src/vnsw/agent/uve/prouter_uve_table.cc b/src/vnsw/agent/uve/prouter_uve_table.cc index 9909d3655b1..a8ad13efb0c 100644 --- a/src/vnsw/agent/uve/prouter_uve_table.cc +++ b/src/vnsw/agent/uve/prouter_uve_table.cc @@ -431,6 +431,9 @@ void ProuterUveTable::RegisterDBClients() { } void ProuterUveTable::Shutdown(void) { - agent_->physical_device_table()->Unregister(physical_device_listener_id_); - agent_->interface_table()->Unregister(interface_listener_id_); + if (physical_device_listener_id_ != DBTableBase::kInvalidId) + agent_->physical_device_table()-> + Unregister(physical_device_listener_id_); + if (interface_listener_id_ != DBTableBase::kInvalidId) + agent_->interface_table()->Unregister(interface_listener_id_); } diff --git a/src/vnsw/agent/uve/test/agent_uve_test.cc b/src/vnsw/agent/uve/test/agent_uve_test.cc index abc40f44792..783c4b4b6a4 100644 --- a/src/vnsw/agent/uve/test/agent_uve_test.cc +++ b/src/vnsw/agent/uve/test/agent_uve_test.cc @@ -15,6 +15,18 @@ AgentUveBaseTest::AgentUveBaseTest(Agent *agent, uint64_t intvl) : AgentUve(agent, intvl) { + if (vn_uve_table_) { + vn_uve_table_->Shutdown(); + } + if (vm_uve_table_) { + vm_uve_table_->Shutdown(); + } + if (vrouter_uve_entry_) { + vrouter_uve_entry_->Shutdown(); + } + if (prouter_uve_table_) { + prouter_uve_table_->Shutdown(); + } vn_uve_table_.reset(new VnUveTableTest(agent)); vm_uve_table_.reset(new VmUveTableTest(agent)); vrouter_uve_entry_.reset(new VrouterUveEntryTest(agent)); diff --git a/src/vnsw/agent/uve/vm_uve_table_base.cc b/src/vnsw/agent/uve/vm_uve_table_base.cc index 4cb0b003fa9..a208d0fbb57 100644 --- a/src/vnsw/agent/uve/vm_uve_table_base.cc +++ b/src/vnsw/agent/uve/vm_uve_table_base.cc @@ -188,8 +188,10 @@ void VmUveTableBase::RegisterDBClients() { } void VmUveTableBase::Shutdown(void) { - agent_->vm_table()->Unregister(vm_listener_id_); - agent_->interface_table()->Unregister(intf_listener_id_); + if (vm_listener_id_ != DBTableBase::kInvalidId) + agent_->vm_table()->Unregister(vm_listener_id_); + if (intf_listener_id_ != DBTableBase::kInvalidId) + agent_->interface_table()->Unregister(intf_listener_id_); } diff --git a/src/vnsw/agent/uve/vn_uve_table_base.cc b/src/vnsw/agent/uve/vn_uve_table_base.cc index 0df8ec7c0af..96700c91b2b 100644 --- a/src/vnsw/agent/uve/vn_uve_table_base.cc +++ b/src/vnsw/agent/uve/vn_uve_table_base.cc @@ -27,8 +27,10 @@ void VnUveTableBase::RegisterDBClients() { } void VnUveTableBase::Shutdown(void) { - agent_->vn_table()->Unregister(vn_listener_id_); - agent_->interface_table()->Unregister(intf_listener_id_); + if (vn_listener_id_ != DBTableBase::kInvalidId) + agent_->vn_table()->Unregister(vn_listener_id_); + if (intf_listener_id_ != DBTableBase::kInvalidId) + agent_->interface_table()->Unregister(intf_listener_id_); } void VnUveTableBase::DispatchVnMsg(const UveVirtualNetworkAgent &uve) { diff --git a/src/vnsw/agent/uve/vrouter_uve_entry_base.cc b/src/vnsw/agent/uve/vrouter_uve_entry_base.cc index 4746c6dbe32..fc5169b70ad 100644 --- a/src/vnsw/agent/uve/vrouter_uve_entry_base.cc +++ b/src/vnsw/agent/uve/vrouter_uve_entry_base.cc @@ -26,12 +26,48 @@ VrouterUveEntryBase::VrouterUveEntryBase(Agent *agent) : agent_(agent), phy_intf_set_(), prev_stats_(), cpu_stats_count_(0), vn_listener_id_(DBTableBase::kInvalidId), vm_listener_id_(DBTableBase::kInvalidId), - intf_listener_id_(DBTableBase::kInvalidId), prev_vrouter_() { + intf_listener_id_(DBTableBase::kInvalidId), prev_vrouter_(), + do_vn_walk_(false), do_vm_walk_(false), do_interface_walk_(false), + timer_(NULL), vn_walk_id_(DBTableWalker::kInvalidWalkerId), + vm_walk_id_(DBTableWalker::kInvalidWalkerId), + interface_walk_id_(DBTableWalker::kInvalidWalkerId) { + if (agent_->tsn_enabled() || agent_->tor_agent_enabled()) { + timer_ = TimerManager::CreateTimer( + *(agent_->event_manager())->io_service(), "UveDBWalkTimer", + TaskScheduler::GetInstance()->GetTaskId("db::DBTable"), 0); + timer_->Start(kDBWalkInterval, + boost::bind(&VrouterUveEntryBase::TimerExpiry, this)); + } } VrouterUveEntryBase::~VrouterUveEntryBase() { } +bool VrouterUveEntryBase::TimerExpiry() { + Run(); + /* Return true to request auto-restart of timer */ + return true; +} + +bool VrouterUveEntryBase::Run() { + if (do_vn_walk_ && vn_walk_id_ == DBTableWalker::kInvalidWalkerId) { + do_vn_walk_ = false; + StartVnWalk(); + } + + if (do_vm_walk_ && vm_walk_id_ == DBTableWalker::kInvalidWalkerId) { + do_vm_walk_ = false; + StartVmWalk(); + } + + if (do_interface_walk_ && + interface_walk_id_ == DBTableWalker::kInvalidWalkerId) { + do_interface_walk_ = false; + StartInterfaceWalk(); + } + return true; +} + void VrouterUveEntryBase::RegisterDBClients() { VnTable *vn_table = agent_->vn_table(); vn_listener_id_ = vn_table->Register @@ -43,13 +79,33 @@ void VrouterUveEntryBase::RegisterDBClients() { InterfaceTable *intf_table = agent_->interface_table(); intf_listener_id_ = intf_table->Register - (boost::bind(&VrouterUveEntryBase::InterfaceNotify, this, _1, _2)); + (boost::bind(&VrouterUveEntryBase::InterfaceNotify, this, _1, _2)); } void VrouterUveEntryBase::Shutdown(void) { - agent_->interface_table()->Unregister(intf_listener_id_); - agent_->vm_table()->Unregister(vm_listener_id_); - agent_->vn_table()->Unregister(vn_listener_id_); + if (intf_listener_id_ != DBTableBase::kInvalidId) + agent_->interface_table()->Unregister(intf_listener_id_); + if (vm_listener_id_ != DBTableBase::kInvalidId) + agent_->vm_table()->Unregister(vm_listener_id_); + if (vn_listener_id_ != DBTableBase::kInvalidId) + agent_->vn_table()->Unregister(vn_listener_id_); + DBTableWalker *walker = agent_->db()->GetWalker(); + if (walker) { + if (vn_walk_id_ != DBTableWalker::kInvalidWalkerId) { + walker->WalkCancel(vn_walk_id_); + } + if (vm_walk_id_ != DBTableWalker::kInvalidWalkerId) { + walker->WalkCancel(vm_walk_id_); + } + if (interface_walk_id_ != DBTableWalker::kInvalidWalkerId) { + walker->WalkCancel(interface_walk_id_); + } + } + if (timer_) { + timer_->Cancel(); + TimerManager::DeleteTimer(timer_); + timer_ = NULL; + } } void VrouterUveEntryBase::DispatchVrouterMsg(const VrouterAgent &uve) { @@ -61,6 +117,7 @@ void VrouterUveEntryBase::VmWalkDone(DBTableBase *base, StringVectorPtr list) { vrouter_agent.set_name(agent_->agent_name()); vrouter_agent.set_virtual_machine_list(*(list.get())); DispatchVrouterMsg(vrouter_agent); + vm_walk_id_ = DBTableWalker::kInvalidWalkerId; } bool VrouterUveEntryBase::AppendVm(DBTablePartBase *part, DBEntryBase *entry, @@ -75,23 +132,29 @@ bool VrouterUveEntryBase::AppendVm(DBTablePartBase *part, DBEntryBase *entry, return true; } -void VrouterUveEntryBase::VmNotifyHandler(const VmEntry *vm) { +void VrouterUveEntryBase::StartVmWalk() { StringVectorPtr list(new vector()); DBTableWalker *walker = agent_->db()->GetWalker(); - walker->WalkTable(agent_->vm_table(), NULL, + vm_walk_id_ = walker->WalkTable(agent_->vm_table(), NULL, boost::bind(&VrouterUveEntryBase::AppendVm, this, _1, _2, list), boost::bind(&VrouterUveEntryBase::VmWalkDone, this, _1, list)); } -void VrouterUveEntryBase::VmNotify(DBTablePartBase *partition, DBEntryBase *e) { - const VmEntry *vm = static_cast(e); +void VrouterUveEntryBase::VmNotifyHandler() { + if (timer_) { + do_vm_walk_ = true; + } else { + StartVmWalk(); + } +} +void VrouterUveEntryBase::VmNotify(DBTablePartBase *partition, DBEntryBase *e) { DBState *state = static_cast (e->GetState(partition->parent(), vm_listener_id_)); if (e->IsDeleted()) { if (state) { - VmNotifyHandler(vm); + VmNotifyHandler(); e->ClearState(partition->parent(), vm_listener_id_); delete state; } @@ -102,7 +165,7 @@ void VrouterUveEntryBase::VmNotify(DBTablePartBase *partition, DBEntryBase *e) { state = new DBState(); e->SetState(partition->parent(), vm_listener_id_, state); //Send vrouter object only for a add/delete - VmNotifyHandler(vm); + VmNotifyHandler(); } } @@ -111,6 +174,7 @@ void VrouterUveEntryBase::VnWalkDone(DBTableBase *base, StringVectorPtr list) { vrouter_agent.set_name(agent_->agent_name()); vrouter_agent.set_connected_networks(*(list.get())); DispatchVrouterMsg(vrouter_agent); + vn_walk_id_ = DBTableWalker::kInvalidWalkerId; } bool VrouterUveEntryBase::AppendVn(DBTablePartBase *part, DBEntryBase *entry, @@ -123,23 +187,29 @@ bool VrouterUveEntryBase::AppendVn(DBTablePartBase *part, DBEntryBase *entry, return true; } -void VrouterUveEntryBase::VnNotifyHandler(const VnEntry *vn) { +void VrouterUveEntryBase::StartVnWalk() { StringVectorPtr list(new vector()); DBTableWalker *walker = agent_->db()->GetWalker(); - walker->WalkTable(agent_->vn_table(), NULL, + vn_walk_id_ = walker->WalkTable(agent_->vn_table(), NULL, boost::bind(&VrouterUveEntryBase::AppendVn, this, _1, _2, list), boost::bind(&VrouterUveEntryBase::VnWalkDone, this, _1, list)); } -void VrouterUveEntryBase::VnNotify(DBTablePartBase *partition, DBEntryBase *e) { - const VnEntry *vn = static_cast(e); +void VrouterUveEntryBase::VnNotifyHandler() { + if (timer_) { + do_vn_walk_ = true; + } else { + StartVnWalk(); + } +} +void VrouterUveEntryBase::VnNotify(DBTablePartBase *partition, DBEntryBase *e) { DBState *state = static_cast (e->GetState(partition->parent(), vn_listener_id_)); if (e->IsDeleted()) { if (state) { - VnNotifyHandler(vn); + VnNotifyHandler(); e->ClearState(partition->parent(), vn_listener_id_); delete state; } @@ -149,7 +219,7 @@ void VrouterUveEntryBase::VnNotify(DBTablePartBase *partition, DBEntryBase *e) { if (!state) { state = new DBState(); e->SetState(partition->parent(), vn_listener_id_, state); - VnNotifyHandler(vn); + VnNotifyHandler(); } } @@ -167,6 +237,7 @@ void VrouterUveEntryBase::InterfaceWalkDone(DBTableBase *base, vrouter_agent.set_down_interface_count((err_if_list.get()->size() + nova_if_list.get()->size())); DispatchVrouterMsg(vrouter_agent); + interface_walk_id_ = DBTableWalker::kInvalidWalkerId; } bool VrouterUveEntryBase::AppendInterface(DBTablePartBase *part, @@ -192,19 +263,27 @@ bool VrouterUveEntryBase::AppendInterface(DBTablePartBase *part, return true; } -void VrouterUveEntryBase::InterfaceNotifyHandler(const Interface *intf) { +void VrouterUveEntryBase::StartInterfaceWalk() { StringVectorPtr intf_list(new std::vector()); StringVectorPtr err_if_list(new std::vector()); StringVectorPtr nova_if_list(new std::vector()); DBTableWalker *walker = agent_->db()->GetWalker(); - walker->WalkTable(agent_->interface_table(), NULL, - boost::bind(&VrouterUveEntryBase::AppendInterface, this, _1, _2, intf_list, - err_if_list, nova_if_list), + interface_walk_id_ = walker->WalkTable(agent_->interface_table(), NULL, + boost::bind(&VrouterUveEntryBase::AppendInterface, this, _1, _2, + intf_list, err_if_list, nova_if_list), boost::bind(&VrouterUveEntryBase::InterfaceWalkDone, this, _1, intf_list, err_if_list, nova_if_list)); } +void VrouterUveEntryBase::InterfaceNotifyHandler() { + if (timer_) { + do_interface_walk_ = true; + } else { + StartInterfaceWalk(); + } +} + void VrouterUveEntryBase::InterfaceNotify(DBTablePartBase *partition, DBEntryBase *e) { const Interface *intf = static_cast(e); @@ -222,19 +301,19 @@ void VrouterUveEntryBase::InterfaceNotify(DBTablePartBase *partition, set_state = true; vmport_ipv4_active = vm_port->ipv4_active(); vmport_l2_active = vm_port->l2_active(); - InterfaceNotifyHandler(intf); + InterfaceNotifyHandler(); } else if (e->IsDeleted()) { if (state) { reset_state = true; - InterfaceNotifyHandler(intf); + InterfaceNotifyHandler(); } } else { if (state && vm_port->ipv4_active() != state->vmport_ipv4_active_) { - InterfaceNotifyHandler(intf); + InterfaceNotifyHandler(); state->vmport_ipv4_active_ = vm_port->ipv4_active(); } if (state && vm_port->l2_active() != state->vmport_l2_active_) { - InterfaceNotifyHandler(intf); + InterfaceNotifyHandler(); state->vmport_l2_active_ = vm_port->l2_active(); } } @@ -408,13 +487,13 @@ bool VrouterUveEntryBase::SendVrouterMsg() { //Set the Agent mode if (agent_->tor_agent_enabled()) { vrouter_agent.set_mode(vnsVrouterType.VrouterAgentTypeMap.at - (VrouterAgentType::VROUTER_AGENT_TOR)); + (VrouterAgentType::VROUTER_AGENT_TOR)); } else if (agent_->tsn_enabled()) { vrouter_agent.set_mode(vnsVrouterType.VrouterAgentTypeMap.at - (VrouterAgentType::VROUTER_AGENT_TSN)); + (VrouterAgentType::VROUTER_AGENT_TSN)); } else { vrouter_agent.set_mode(vnsVrouterType.VrouterAgentTypeMap.at - (VrouterAgentType::VROUTER_AGENT_EMBEDDED)); + (VrouterAgentType::VROUTER_AGENT_EMBEDDED)); } first = false; diff --git a/src/vnsw/agent/uve/vrouter_uve_entry_base.h b/src/vnsw/agent/uve/vrouter_uve_entry_base.h index c7d1e116465..a000d68925c 100644 --- a/src/vnsw/agent/uve/vrouter_uve_entry_base.h +++ b/src/vnsw/agent/uve/vrouter_uve_entry_base.h @@ -35,6 +35,7 @@ class VrouterUveEntryBase { static const uint8_t bandwidth_mod_1min = 2; static const uint8_t bandwidth_mod_5min = 10; static const uint8_t bandwidth_mod_10min = 20; + static const uint32_t kDBWalkInterval = (1000); // time in milliseconds typedef std::set PhysicalInterfaceSet; typedef boost::shared_ptr > StringVectorPtr; @@ -74,9 +75,14 @@ class VrouterUveEntryBase { void InterfaceNotify(DBTablePartBase *partition, DBEntryBase *e); void VmNotify(DBTablePartBase *partition, DBEntryBase *e); void VnNotify(DBTablePartBase *partition, DBEntryBase *e); - void VmNotifyHandler(const VmEntry *vm); - void VnNotifyHandler(const VnEntry *vn); - void InterfaceNotifyHandler(const Interface *intf); + void VmNotifyHandler(); + void VnNotifyHandler(); + void InterfaceNotifyHandler(); + void StartVnWalk(); + void StartVmWalk(); + void StartInterfaceWalk(); + bool TimerExpiry(); + bool Run(); std::string GetMacAddress(const MacAddress &mac) const; void SubnetToStringList(VirtualGatewayConfig::SubnetList &l1, std::vector &l2); @@ -86,6 +92,13 @@ class VrouterUveEntryBase { DBTableBase::ListenerId vm_listener_id_; DBTableBase::ListenerId intf_listener_id_; VrouterAgent prev_vrouter_; + bool do_vn_walk_; + bool do_vm_walk_; + bool do_interface_walk_; + Timer *timer_; + DBTableWalker::WalkId vn_walk_id_; + DBTableWalker::WalkId vm_walk_id_; + DBTableWalker::WalkId interface_walk_id_; DISALLOW_COPY_AND_ASSIGN(VrouterUveEntryBase); }; diff --git a/src/vnsw/agent/vrouter/ksync/interface_ksync.cc b/src/vnsw/agent/vrouter/ksync/interface_ksync.cc index 9f13e9fdddc..4def78d48a7 100644 --- a/src/vnsw/agent/vrouter/ksync/interface_ksync.cc +++ b/src/vnsw/agent/vrouter/ksync/interface_ksync.cc @@ -417,7 +417,8 @@ KSyncEntry *InterfaceKSyncEntry::UnresolvedReference() { return NULL; } -bool IsValidOsIndex(size_t os_index, Interface::Type type, uint16_t vlan_id) { +bool IsValidOsIndex(size_t os_index, Interface::Type type, uint16_t vlan_id, + VmInterface::VmiType vmi_type) { if (os_index != Interface::kInvalidIndex) return true; @@ -426,6 +427,10 @@ bool IsValidOsIndex(size_t os_index, Interface::Type type, uint16_t vlan_id) { return true; } + if (vmi_type == VmInterface::GATEWAY) { + return true; + } + return false; } @@ -434,7 +439,7 @@ int InterfaceKSyncEntry::Encode(sandesh_op::type op, char *buf, int buf_len) { int encode_len, error; // Dont send message if interface index not known - if (IsValidOsIndex(os_index_, type_, rx_vlan_id_) == false) { + if (IsValidOsIndex(os_index_, type_, rx_vlan_id_, vmi_type_) == false) { return 0; } @@ -457,8 +462,17 @@ int InterfaceKSyncEntry::Encode(sandesh_op::type op, char *buf, int buf_len) { MacAddress mac; if (parent_.get() != NULL) { encoder.set_vifr_type(VIF_TYPE_VIRTUAL_VLAN); - encoder.set_vifr_vlan_id(rx_vlan_id_); - encoder.set_vifr_ovlan_id(tx_vlan_id_); + if (vmi_type_ == VmInterface::GATEWAY && + tx_vlan_id_ == VmInterface::kInvalidVlanId) { + //By default in case of gateway, untagged packet + //would be considered as belonging to interface + //at tag 0 + encoder.set_vifr_vlan_id(0); + encoder.set_vifr_ovlan_id(0); + } else { + encoder.set_vifr_vlan_id(rx_vlan_id_); + encoder.set_vifr_ovlan_id(tx_vlan_id_); + } InterfaceKSyncEntry *parent = (static_cast (parent_.get())); encoder.set_vifr_parent_vif_idx(parent->interface_id()); diff --git a/src/vnsw/agent/vrouter/ksync/route_ksync.cc b/src/vnsw/agent/vrouter/ksync/route_ksync.cc index b3d54a595d5..31eee135a78 100644 --- a/src/vnsw/agent/vrouter/ksync/route_ksync.cc +++ b/src/vnsw/agent/vrouter/ksync/route_ksync.cc @@ -85,9 +85,6 @@ RouteKSyncEntry::RouteKSyncEntry(RouteKSyncObject* obj, const AgentRoute *rt) : static_cast(rt); mac_ = l2_rt->mac(); prefix_len_ = 0; - const AgentPath *path = l2_rt->GetActivePath(); - if (path) - flood_dhcp_ = path->flood_dhcp(); break; } default: { @@ -210,7 +207,7 @@ std::string RouteKSyncEntry::ToString() const { // Check if NH points to a service-chain interface or a Gateway interface static bool IsGatewayOrServiceInterface(const NextHop *nh) { if (nh->GetType() != NextHop::INTERFACE && - nh->GetType() != NextHop::VLAN) + nh->GetType() != NextHop::VLAN && nh->GetType() != NextHop::ARP) return false; const Interface *intf = NULL; @@ -220,6 +217,8 @@ static bool IsGatewayOrServiceInterface(const NextHop *nh) { return true; } else if (nh->GetType() == NextHop::VLAN) { intf = (static_cast(nh))->GetInterface(); + } else if (nh->GetType() == NextHop::ARP) { + intf = (static_cast(nh))->GetInterface(); } const VmInterface *vmi = dynamic_cast(intf); @@ -337,7 +336,6 @@ const NextHop *RouteKSyncEntry::GetActiveNextHop(const AgentRoute *route) const const AgentPath *path = GetActivePath(route); if (path == NULL) return NULL; - return path->ComputeNextHop(ksync_obj_->ksync()->agent()); } @@ -355,7 +353,7 @@ bool RouteKSyncEntry::Sync(DBEntry *e) { Agent *agent = ksync_obj_->ksync()->agent(); const AgentRoute *route = static_cast(e); - const AgentPath *path = route->GetActivePath(); + const AgentPath *path = GetActivePath(route); if (path->peer() == agent->local_vm_peer()) local_vm_peer_route_ = true; else @@ -415,14 +413,26 @@ bool RouteKSyncEntry::Sync(DBEntry *e) { mac_ = mac; ret = true; } - } - if (BuildArpFlags(e, path, mac_)) - ret = true; + if (BuildArpFlags(e, path, mac_)) + ret = true; + } - if (flood_dhcp_ != path->flood_dhcp()) { - flood_dhcp_ = path->flood_dhcp(); - ret = true; + if (rt_type_ == Agent::BRIDGE) { + const BridgeRouteEntry *l2_rt = + static_cast(route); + + //First search for v4 + const MacVmBindingPath *dhcp_path = dynamic_cast + (l2_rt->FindMacVmBindingPath()); + bool flood_dhcp = false; + if (dhcp_path) + flood_dhcp = dhcp_path->flood_dhcp(); + + if (flood_dhcp_ != flood_dhcp) { + flood_dhcp_ = flood_dhcp; + ret = true; + } } return ret; diff --git a/src/vnsw/agent/vxlan_agent/linux/linux_vxlan_agent_init.cc b/src/vnsw/agent/vxlan_agent/linux/linux_vxlan_agent_init.cc index ca129dccc13..8b0249bd517 100644 --- a/src/vnsw/agent/vxlan_agent/linux/linux_vxlan_agent_init.cc +++ b/src/vnsw/agent/vxlan_agent/linux/linux_vxlan_agent_init.cc @@ -69,7 +69,8 @@ void LinuxVxlanAgentInit::FactoryInit() { void LinuxVxlanAgentInit::CreateModules() { ksync_vxlan_.reset(new KSyncLinuxVxlan(agent())); - uve_.reset(new AgentUveBase(agent(), AgentUveBase::kBandwidthInterval)); + uve_.reset(new AgentUveBase(agent(), AgentUveBase::kBandwidthInterval, + true)); agent()->set_uve(uve_.get()); }