From 306d40ec6d52d539e4313e2e61b8847551e449e9 Mon Sep 17 00:00:00 2001 From: Hari Date: Tue, 26 Jul 2016 16:01:40 +0530 Subject: [PATCH] In case of Static Mirroring, need to set Destination network with Mirroring flag so that insted of choosing VRF NH for VXLAN, will choose composite Interface NH. For creating compositeNH, registerd for Vminterface creation notification upon receving the notification will attach each interface NH to the composite list and inturn will program the vrouter. partial-bug: #1592049 In the case of Static Mirroring Case, need to set Destination network with Mirroring flag so that insted of choosing VRF NH for VXLAN will choose composite Interface NH. partial-bug: #1592049 (submitting on behalf of Jayaram Satya) Change-Id: Idc2672666561484ae4bcd96696daa3baccc30560 --- src/schema/vnc_cfg.xsd | 3 + src/vnsw/agent/oper/operdb_init.cc | 5 + src/vnsw/agent/oper/vn.cc | 28 ++- src/vnsw/agent/oper/vn.h | 14 +- src/vnsw/agent/oper/vxlan.cc | 169 +++++++++++++++++-- src/vnsw/agent/oper/vxlan.h | 30 +++- src/vnsw/agent/vrouter/ksync/mirror_ksync.cc | 5 +- 7 files changed, 216 insertions(+), 38 deletions(-) diff --git a/src/schema/vnc_cfg.xsd b/src/schema/vnc_cfg.xsd index dd38ade2c41..81e8ac65f26 100644 --- a/src/schema/vnc_cfg.xsd +++ b/src/schema/vnc_cfg.xsd @@ -1161,6 +1161,9 @@ targetNamespace="http://www.contrailsystems.com/2012/VNC-CONFIG/0"> + + diff --git a/src/vnsw/agent/oper/operdb_init.cc b/src/vnsw/agent/oper/operdb_init.cc index 283c9900503..9a770682f45 100644 --- a/src/vnsw/agent/oper/operdb_init.cc +++ b/src/vnsw/agent/oper/operdb_init.cc @@ -179,6 +179,7 @@ void OperDB::CreateDBTables(DB *db) { assert(vxlan_table); agent_->set_vxlan_table(vxlan_table); vxlan_table->set_agent(agent_); + vxlan_table->Initialize(); QosQueueTable *qos_queue_table; qos_queue_table = @@ -325,6 +326,10 @@ void OperDB::Shutdown() { agent()->mirror_table()->Shutdown(); } + if (agent()->vxlan_table()) { + agent()->vxlan_table()->Shutdown(); + } + profile_.reset(); } diff --git a/src/vnsw/agent/oper/vn.cc b/src/vnsw/agent/oper/vn.cc index cc952645dc5..4740157dee5 100644 --- a/src/vnsw/agent/oper/vn.cc +++ b/src/vnsw/agent/oper/vn.cc @@ -96,7 +96,8 @@ VnEntry::VnEntry(Agent *agent, uuid id) : admin_state_(true), table_label_(0), enable_rpf_(true), flood_unknown_unicast_(false), old_vxlan_id_(0), forwarding_mode_(Agent::L2_L3), - route_resync_walker_(new AgentRouteResync(agent)) { + route_resync_walker_(new AgentRouteResync(agent)), mirror_destination_(false) +{ route_resync_walker_.get()-> set_walkable_route_tables((1 << Agent::INET4_UNICAST) | (1 << Agent::INET6_UNICAST)); @@ -343,7 +344,8 @@ bool VnTable::RebakeVxlan(VnEntry *vn, bool op_del) { if (vxlan) { vn->old_vxlan_id_ = vxlan; vn->vxlan_id_ref_ = table->Locate(vxlan, vn->uuid_, vn->vrf_->GetName(), - vn->flood_unknown_unicast_); + vn->flood_unknown_unicast_, + vn->mirror_destination_); } return (old_vxlan != vn->vxlan_id_ref_.get()); @@ -578,6 +580,12 @@ bool VnTable::ChangeHandler(DBEntry *entry, const DBRequest *req) { ret = true; } + if (vn->mirror_destination_ != data->mirror_destination_) { + vn->mirror_destination_ = data->mirror_destination_; + rebake_vxlan = true; + ret = true; + } + if (rebake_vxlan) { ret |= RebakeVxlan(vn, false); } @@ -684,7 +692,8 @@ int VnTable::ComputeCfgVxlanId(IFMapNode *node) { void VnTable::CfgForwardingFlags(IFMapNode *node, bool *l2, bool *l3, bool *rpf, bool *flood_unknown_unicast, - Agent::ForwardingMode *forwarding_mode) { + Agent::ForwardingMode *forwarding_mode, + bool *mirror_destination) { *rpf = true; VirtualNetwork *cfg = static_cast (node->GetObject()); @@ -695,7 +704,7 @@ void VnTable::CfgForwardingFlags(IFMapNode *node, bool *l2, bool *l3, } *flood_unknown_unicast = cfg->flood_unknown_unicast(); - + *mirror_destination = properties.mirror_destination; //dervived forwarding mode is resultant of configured VN forwarding and global //configure forwarding mode. It is then used to setup the VN forwarding //mode. @@ -832,16 +841,18 @@ VnData *VnTable::BuildData(IFMapNode *node) { bool layer3_forwarding; bool enable_rpf; bool flood_unknown_unicast; + bool mirror_destination; Agent::ForwardingMode forwarding_mode; CfgForwardingFlags(node, &bridging, &layer3_forwarding, &enable_rpf, - &flood_unknown_unicast, &forwarding_mode); + &flood_unknown_unicast, &forwarding_mode, + &mirror_destination); return new VnData(agent(), node, node->name(), acl_uuid, vrf_name, mirror_acl_uuid, mirror_cfg_acl_uuid, vn_ipam, vn_ipam_data, cfg->properties().vxlan_network_identifier, GetCfgVnId(cfg), bridging, layer3_forwarding, cfg->id_perms().enable, enable_rpf, flood_unknown_unicast, forwarding_mode, - qos_config_uuid); + qos_config_uuid, mirror_destination); } bool VnTable::IFNodeToUuid(IFMapNode *node, boost::uuids::uuid &u) { @@ -888,13 +899,15 @@ void VnTable::AddVn(const uuid &vn_uuid, const string &name, const VnData::VnIpamDataMap &vn_ipam_data, int vn_id, int vxlan_id, bool admin_state, bool enable_rpf, bool flood_unknown_unicast) { + bool mirror_destination = false; DBRequest req; VnKey *key = new VnKey(vn_uuid); VnData *data = new VnData(agent(), NULL, name, acl_id, vrf_name, nil_uuid(), nil_uuid(), ipam, vn_ipam_data, vn_id, vxlan_id, true, true, admin_state, enable_rpf, - flood_unknown_unicast, Agent::NONE, nil_uuid()); + flood_unknown_unicast, Agent::NONE, nil_uuid(), + mirror_destination); req.oper = DBRequest::DB_ENTRY_ADD_CHANGE; req.key.reset(key); @@ -1182,7 +1195,6 @@ bool VnEntry::DBEntrySandesh(Sandesh *sresp, std::string &name) const { data.set_admin_state(admin_state()); data.set_enable_rpf(enable_rpf()); data.set_flood_unknown_unicast(flood_unknown_unicast()); - std::vector &list = const_cast&>(resp->get_vn_list()); list.push_back(data); diff --git a/src/vnsw/agent/oper/vn.h b/src/vnsw/agent/oper/vn.h index bf9708c6160..10e7b7d0f08 100644 --- a/src/vnsw/agent/oper/vn.h +++ b/src/vnsw/agent/oper/vn.h @@ -94,7 +94,7 @@ struct VnData : public AgentOperDBData { int vxlan_id, int vnid, bool bridging, bool layer3_forwarding, bool admin_state, bool enable_rpf, bool flood_unknown_unicast, Agent::ForwardingMode forwarding_mode, - const boost::uuids::uuid &qos_config_uuid) : + const boost::uuids::uuid &qos_config_uuid, bool mirror_destination) : AgentOperDBData(agent, node), 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), @@ -102,7 +102,8 @@ struct VnData : public AgentOperDBData { layer3_forwarding_(layer3_forwarding), admin_state_(admin_state), enable_rpf_(enable_rpf), flood_unknown_unicast_(flood_unknown_unicast), - forwarding_mode_(forwarding_mode), qos_config_uuid_(qos_config_uuid) { + forwarding_mode_(forwarding_mode), qos_config_uuid_(qos_config_uuid), + mirror_destination_(mirror_destination){ }; virtual ~VnData() { } @@ -122,6 +123,7 @@ struct VnData : public AgentOperDBData { bool flood_unknown_unicast_; Agent::ForwardingMode forwarding_mode_; boost::uuids::uuid qos_config_uuid_; + bool mirror_destination_; }; class VnEntry : AgentRefCount, public AgentOperDBEntry { @@ -192,6 +194,10 @@ class VnEntry : AgentRefCount, public AgentOperDBEntry { return qos_config_.get(); } + const bool mirror_destination() const { + return mirror_destination_; + } + private: friend class VnTable; @@ -217,6 +223,7 @@ class VnEntry : AgentRefCount, public AgentOperDBEntry { Agent::ForwardingMode forwarding_mode_; boost::scoped_ptr route_resync_walker_; AgentQosConfigConstRef qos_config_; + bool mirror_destination_; DISALLOW_COPY_AND_ASSIGN(VnEntry); }; @@ -246,7 +253,8 @@ class VnTable : public AgentOperDBTable { int ComputeCfgVxlanId(IFMapNode *node); void CfgForwardingFlags(IFMapNode *node, bool *l2, bool *l3, bool *rpf, bool *flood_unknown_unicast, - Agent::ForwardingMode *forwarding_mode); + Agent::ForwardingMode *forwarding_mode, + bool *mirror_destination); static DBTableBase *CreateTable(DB *db, const std::string &name); diff --git a/src/vnsw/agent/oper/vxlan.cc b/src/vnsw/agent/oper/vxlan.cc index 679adae5ea3..33d97636422 100644 --- a/src/vnsw/agent/oper/vxlan.cc +++ b/src/vnsw/agent/oper/vxlan.cc @@ -31,6 +31,96 @@ void VxLanId::SetKey(const DBRequestKey *k) { vxlan_id_ = key->vxlan_id(); } +void VxLanTable::Initialize() { + Register(); +} + +void VxLanTable::Register() { + interface_listener_id_ = agent()->interface_table()->Register( + boost::bind(&VxLanTable::VmInterfaceNotify, this, _1, _2)); + +} + +void VxLanTable::Shutdown() { + agent()->interface_table()->Unregister(interface_listener_id_); +} + +void VxLanTable::VmInterfaceNotify(DBTablePartBase *partition, DBEntryBase *e) { + const Interface *intf = static_cast(e); + const VmInterface *vm_itf; + bool composite_nh_modified = false; + if (intf->type() != Interface::VM_INTERFACE) { + return; + } + + vm_itf = static_cast(intf); + + if (vm_itf->vn() == NULL) { + return; + } + + const VnEntry *vn = vm_itf->vn(); + if (!vn->mirror_destination()) { + return; + } + + ComponentNHKeyPtr nh_key(new ComponentNHKey(vm_itf->label(),vm_itf->GetUuid(), + InterfaceNHFlags::BRIDGE, + vm_itf->mac())); + // if the interface deleted remove the entry from map + // else add it to composite NH list + if (intf->IsDeleted() || ((vm_itf->l2_active() == false) && + (vm_itf->ipv4_active() == false) && + (vm_itf->ipv6_active() == false))) { + composite_nh_modified = DeleteCompositeNH(vm_itf->vxlan_id(), nh_key); + } else { + composite_nh_modified = AddCompositeNH(vm_itf->vxlan_id(), nh_key); + } + + if (composite_nh_modified) { + Create(vm_itf->vxlan_id(), vm_itf->vrf()->GetName(), + vn->flood_unknown_unicast(), vn->mirror_destination()); + } + return; +} + +bool VxLanTable::DeleteCompositeNH(uint32_t vxlan_id, + ComponentNHKeyPtr nh_key) { + VxlanCompositeNHList::iterator it = vxlan_composite_nh_map_.find(vxlan_id); + if (it != vxlan_composite_nh_map_.end()) { + ComponentNHKeyList::iterator list_it = it->second.begin(); + for (; list_it != it->second.end(); list_it++) { + if (**list_it == *nh_key) { + // release the ComponentNHKeyPtr + (*list_it).reset(); + return true; + } + } + return false; + } + return false; +} + +bool VxLanTable::AddCompositeNH(uint32_t vxlan_id, ComponentNHKeyPtr nh_key) { + VxlanCompositeNHList::iterator it = vxlan_composite_nh_map_.find(vxlan_id); + if (it != vxlan_composite_nh_map_.end()) { + ComponentNHKeyList::const_iterator list_it = it->second.begin(); + for (; list_it != it->second.end(); list_it++) { + if (**list_it == *nh_key) { + // already there no modification + return false; + } + } + it->second.push_back(nh_key); + return true; + } + ComponentNHKeyList list; + list.push_back(nh_key); + vxlan_composite_nh_map_.insert(VxlanCompositeNHEntry(vxlan_id, list)); + return true; +} + + std::auto_ptr VxLanTable::AllocEntry(const DBRequestKey *k) const { const VxLanIdKey *key = static_cast(k); VxLanId *vxlan_id = new VxLanId(key->vxlan_id()); @@ -67,10 +157,33 @@ bool VxLanTable::ChangeHandler(VxLanId *vxlan_id, const DBRequest *req) { VxLanIdData *data = static_cast(req->data.get()); Agent::GetInstance()->nexthop_table()->Process(data->nh_req()); - - VrfNHKey nh_key(data->vrf_name(), false, true); - NextHop *nh = static_cast - (Agent::GetInstance()->nexthop_table()->FindActiveEntry(&nh_key)); + NextHop *nh; + // if VN is enabled with mirror destination point the vxlan nh + // to CompositeNH + if (data->mirror_destination()) { + VxlanCompositeNHList::iterator it = + vxlan_composite_nh_map_.find(vxlan_id->vxlan_id()); + if (it != vxlan_composite_nh_map_.end()) { + CompositeNHKey nh_key(Composite::L2INTERFACE, false, it->second, + data->vrf_name()); + nh = static_cast + (Agent::GetInstance()->nexthop_table()->FindActiveEntry(&nh_key)); + } else { + // vm interface notification arraived at so create dummy CompositeNH + ComponentNHKeyPtr nh_ptr; + nh_ptr.reset(); + ComponentNHKeyList list; + list.push_back(nh_ptr); + CompositeNHKey nh_key(Composite::L2INTERFACE, false, list, + data->vrf_name()); + nh = static_cast + (agent()->nexthop_table()->FindActiveEntry(&nh_key)); + } + } else { + VrfNHKey nh_key(data->vrf_name(), false, true); + nh = static_cast + (Agent::GetInstance()->nexthop_table()->FindActiveEntry(&nh_key)); + } if (vxlan_id->nh_ != nh) { vxlan_id->nh_ = nh; @@ -106,7 +219,8 @@ void VxLanTable::OnZeroRefcount(AgentDBEntry *e) { // - vxlan dbentry if "vn" is "active" // - NULL if "vn" is "inactive" VxLanId *VxLanTable::Locate(uint32_t vxlan_id, const boost::uuids::uuid &vn, - const std::string &vrf, bool flood_unknown_unicast){ + const std::string &vrf, bool flood_unknown_unicast, + bool mirror_destination){ // Treat a request without VRF as delete of config entry if (vrf.empty()) { Delete(vxlan_id, vn); @@ -121,8 +235,8 @@ VxLanId *VxLanTable::Locate(uint32_t vxlan_id, const boost::uuids::uuid &vn, if (it == config_tree_.end() || it->first.vxlan_id_ != vxlan_id) { config_tree_.insert(make_pair(ConfigKey(vxlan_id, vn), ConfigEntry(vrf, flood_unknown_unicast, - true))); - Create(vxlan_id, vrf, flood_unknown_unicast); + true, mirror_destination))); + Create(vxlan_id, vrf, flood_unknown_unicast, mirror_destination); return Find(vxlan_id); } @@ -131,10 +245,11 @@ VxLanId *VxLanTable::Locate(uint32_t vxlan_id, const boost::uuids::uuid &vn, if (it != config_tree_.end()) { it->second.vrf_ = vrf; it->second.flood_unknown_unicast_ = flood_unknown_unicast; + it->second.mirror_destination_ = mirror_destination; // If entry is active, update vxlan dbentry with new information if (it->second.active_) { - Create(vxlan_id, vrf, flood_unknown_unicast); + Create(vxlan_id, vrf, flood_unknown_unicast, mirror_destination); return Find(vxlan_id); } // If entry inactive, return NULL @@ -144,7 +259,7 @@ VxLanId *VxLanTable::Locate(uint32_t vxlan_id, const boost::uuids::uuid &vn, // Entry not present, add it to config-tree config_tree_.insert(make_pair(ConfigKey(vxlan_id, vn), ConfigEntry(vrf, flood_unknown_unicast, - false))); + false, mirror_destination))); // Return NULL since the VN is active return NULL; } @@ -168,7 +283,8 @@ VxLanId *VxLanTable::Delete(uint32_t vxlan_id, const boost::uuids::uuid &vn) { return NULL; it->second.active_ = true; - Create(vxlan_id, it->second.vrf_, it->second.flood_unknown_unicast_); + Create(vxlan_id, it->second.vrf_, it->second.flood_unknown_unicast_, + it->second.mirror_destination_); agent()->vn_table()->ResyncVxlan(it->first.vn_); return NULL; } @@ -180,23 +296,42 @@ DBTableBase *VxLanTable::CreateTable(DB *db, const std::string &name) { } void VxLanTable::Create(uint32_t vxlan_id, const string &vrf_name, - bool flood_unknown_unicast) { + bool flood_unknown_unicast, bool mirror_destination) { DBRequest nh_req(DBRequest::DB_ENTRY_ADD_CHANGE); - nh_req.key.reset(new VrfNHKey(vrf_name, false, true)); - nh_req.data.reset(new VrfNHData(flood_unknown_unicast)); - + if (mirror_destination) { + VxlanCompositeNHList::iterator it = + vxlan_composite_nh_map_.find(vxlan_id); + if (it != vxlan_composite_nh_map_.end()) { + nh_req.key.reset(new CompositeNHKey(Composite::L2INTERFACE, false, + it->second, vrf_name)); + } else { + ComponentNHKeyPtr nh_ptr; + nh_ptr.reset(); + ComponentNHKeyList list; + list.push_back(nh_ptr); + nh_req.key.reset(new CompositeNHKey(Composite::L2INTERFACE, false, + list, vrf_name)); + } + nh_req.data.reset(new CompositeNHData()); + } else { + nh_req.key.reset(new VrfNHKey(vrf_name, false, true)); + nh_req.data.reset(new VrfNHData(flood_unknown_unicast)); + } DBRequest req(DBRequest::DB_ENTRY_ADD_CHANGE); req.key.reset(new VxLanIdKey(vxlan_id)); - req.data.reset(new VxLanIdData(vrf_name, nh_req)); - + req.data.reset(new VxLanIdData(vrf_name, nh_req, mirror_destination)); Process(req); return; } - + void VxLanTable::Delete(uint32_t vxlan_id) { DBRequest req(DBRequest::DB_ENTRY_DELETE); req.key.reset(new VxLanIdKey(vxlan_id)); req.data.reset(NULL); + VxlanCompositeNHList::iterator it = vxlan_composite_nh_map_.find(vxlan_id); + if (it != vxlan_composite_nh_map_.end()) { + vxlan_composite_nh_map_.erase(it); + } Process(req); } diff --git a/src/vnsw/agent/oper/vxlan.h b/src/vnsw/agent/oper/vxlan.h index 2a2b64423c5..bb51f1339c3 100644 --- a/src/vnsw/agent/oper/vxlan.h +++ b/src/vnsw/agent/oper/vxlan.h @@ -9,7 +9,7 @@ #include #include #include - +#include using namespace std; class VxLanId : AgentRefCount, public AgentDBEntry { @@ -56,17 +56,19 @@ class VxLanIdKey : public AgentKey { class VxLanIdData : public AgentData { public: - VxLanIdData(const string &vrf_name, DBRequest &req) : + VxLanIdData(const string &vrf_name, DBRequest &req, bool mirror_destination) : vrf_name_(vrf_name) { nh_req_.Swap(&req); + mirror_destination_ = mirror_destination; }; virtual ~VxLanIdData() { }; string &vrf_name() {return vrf_name_;} DBRequest &nh_req() {return nh_req_;} - + bool mirror_destination() const {return mirror_destination_;} private: string vrf_name_; DBRequest nh_req_; + bool mirror_destination_; }; ///////////////////////////////////////////////////////////////////////////// @@ -114,17 +116,19 @@ class VxLanTable : public AgentDBTable { struct ConfigEntry { ConfigEntry(const std::string &vrf, bool flood_unknown_unicast, - bool active) : + bool active, bool mirror_destination) : vrf_(vrf), flood_unknown_unicast_(flood_unknown_unicast), - active_(active) { + active_(active), mirror_destination_(mirror_destination) { } std::string vrf_; bool flood_unknown_unicast_; bool active_; + bool mirror_destination_; }; typedef std::map ConfigTree; - + typedef std::mapVxlanCompositeNHList; + typedef std::pair VxlanCompositeNHEntry; static const uint32_t kInvalidvxlan_id = 0; VxLanTable(DB *db, const std::string &name) : AgentDBTable(db, name) { }; virtual ~VxLanTable() { }; @@ -143,21 +147,29 @@ class VxLanTable : public AgentDBTable { void Process(DBRequest &req); void Create(uint32_t vxlan_id, const std::string &vrf_name, - bool flood_unknown_unicast); + bool flood_unknown_unicast, bool mirror_destination); void Delete(uint32_t vxlan_id); VxLanId *Find(uint32_t vxlan_id); VxLanId *FindNoLock(uint32_t vxlan_id); VxLanId *Locate(uint32_t vxlan_id, const boost::uuids::uuid &vn, - const std::string &vrf, bool flood_unknown_unicast); + const std::string &vrf, bool flood_unknown_unicast, + bool mirror_destination); VxLanId *Delete(uint32_t vxlan_id, const boost::uuids::uuid &vn); const ConfigTree &config_tree() const { return config_tree_; } static DBTableBase *CreateTable(DB *db, const std::string &name); - + void Initialize(); + void Register(); + void Shutdown(); + void VmInterfaceNotify(DBTablePartBase *partition, DBEntryBase *e); + bool AddCompositeNH(uint32_t vxlan_id, ComponentNHKeyPtr nh_key); + bool DeleteCompositeNH(uint32_t vxlan_id, ComponentNHKeyPtr nh_key); private: bool ChangeHandler(VxLanId *vxlan_id, const DBRequest *req); ConfigTree config_tree_; DBTableBase::ListenerId vn_table_listener_id_; + DBTableBase::ListenerId interface_listener_id_; + VxlanCompositeNHList vxlan_composite_nh_map_; DISALLOW_COPY_AND_ASSIGN(VxLanTable); }; diff --git a/src/vnsw/agent/vrouter/ksync/mirror_ksync.cc b/src/vnsw/agent/vrouter/ksync/mirror_ksync.cc index b0b340436df..d816727f345 100644 --- a/src/vnsw/agent/vrouter/ksync/mirror_ksync.cc +++ b/src/vnsw/agent/vrouter/ksync/mirror_ksync.cc @@ -7,6 +7,7 @@ #include "vrouter/ksync/nexthop_ksync.h" #include "vrouter/ksync/ksync_init.h" #include +#include "vr_mirror.h" MirrorKSyncEntry::MirrorKSyncEntry(MirrorKSyncObject *obj, const MirrorKSyncEntry *entry, @@ -93,7 +94,9 @@ int MirrorKSyncEntry::Encode(sandesh_op::type op, char *buf, int buf_len) { encoder.set_mirr_rid(0); encoder.set_mirr_nhid(nh_entry->nh_id()); encoder.set_mirr_vni(vni_); - encoder.set_mirr_flags(mirror_flag_); + if (mirror_flag_ == MirrorEntryData::DynamicNH_With_JuniperHdr) { + encoder.set_mirr_flags(VR_MIRROR_FLAG_DYNAMIC); + } int error = 0; encode_len = encoder.WriteBinary((uint8_t *)buf, buf_len, &error); assert(error == 0);