diff --git a/src/analytics/viz.sandesh b/src/analytics/viz.sandesh index 8e0121568b1..9aabcbd1653 100644 --- a/src/analytics/viz.sandesh +++ b/src/analytics/viz.sandesh @@ -54,6 +54,7 @@ const string OBJECT_TABLE = "ObjectTable" //The following are the object tables and some of them are UVEs const string VN_TABLE = "ObjectVNTable" const string VM_TABLE = "ObjectVMTable" +const string VMI_TABLE = "ObjectVMITable" const string SI_TABLE = "ObjectSITable" const string VROUTER_TABLE = "ObjectVRouter" const string BGP_PEER_TABLE = "ObjectBgpPeer" @@ -76,9 +77,12 @@ const string DISK_TABLE = "ObjectDiskTable" const string SERVER_TABLE = "ObjectServerTable" const string PROUTER_TABLE = "ObjectPRouter" const string CONFIG_OBJECT_TABLE_USER = "ConfigObjectTableByUser" +const string PHYSICAL_IF_TABLE = "ObjectPhysicalInterfaceTable" +const string LOGICAL_IF_TABLE = "ObjectLogicalInterfaceTable" const string VN_DISPLAY_NAME = "Virtual Network" const string VM_DISPLAY_NAME = "Virtual Machine" +const string VMI_DISPLAY_NAME = "Virtual Machine Interface" const string SI_DISPLAY_NAME = "Service Instance" const string VROUTER_DISPLAY_NAME = "vRouter" const string BGP_PEER_DISPLAY_NAME = "BGP Peer" @@ -101,6 +105,8 @@ const string STORAGE_DISK_DISPLAY_NAME = "Storage RawDisk" const string SERVER_TABLE_DISPLAY_NAME = "Server Table Info" const string PROUTER_DISPLAY_NAME = "pRouter" const string CONFIG_OBJECT_USER_DISPLAY_NAME = "Config Object by User Table" +const string LOGICAL_IF_DISPLAY_NAME = "Logical Interface" +const string PHYSICAL_IF_DISPLAY_NAME = "Physical Interface" const string SYSTEM_LOG = "SystemLog" const string OBJECT_LOG = "ObjectLog" @@ -329,6 +335,7 @@ const i32 AnalyticsTTL = 48 const map UVE_MAP = { "virtual-network" : VN_TABLE, "virtual-machine" : VM_TABLE, + "virtual-machine-interface" : VMI_TABLE, "service-instance" : SI_TABLE, "vrouter" : VROUTER_TABLE, "control-node" : BGP_ROUTER_TABLE, @@ -345,6 +352,8 @@ const map UVE_MAP = { "storage-disk" : DISK_TABLE, "server" : SERVER_TABLE, "prouter" : PROUTER_TABLE, + "physical-interface" : PHYSICAL_IF_TABLE, + "logical-interface" : LOGICAL_IF_TABLE } struct objtable_info { @@ -365,6 +374,10 @@ const map _OBJECT_TABLES = { 'objtable_display_name' : VM_DISPLAY_NAME 'log_query_name' : "virtual-machine" } + VMI_TABLE : { + 'objtable_display_name' : VMI_DISPLAY_NAME + 'log_query_name' : "virtual-machine-interface" + } SI_TABLE : { 'objtable_display_name' : SI_DISPLAY_NAME 'log_query_name' : "service-instance" @@ -445,6 +458,14 @@ const map _OBJECT_TABLES = { 'objtable_display_name' : CONFIG_OBJECT_USER_DISPLAY_NAME 'log_query_name' : "config-user" } + PHYSICAL_IF_TABLE : { + 'objtable_display_name' : PHYSICAL_IF_DISPLAY_NAME + 'log_query_name' : "physical-interface" + } + LOGICAL_IF_TABLE : { + 'objtable_display_name' : LOGICAL_IF_DISPLAY_NAME + 'log_query_name' : "logical-interface" + } } // Analytics table schema defination @@ -1217,6 +1238,37 @@ const list _STAT_TABLES = [ { 'name' : 'disk_usage_info.partition_space_available_1k', 'datatype' : 'int', 'index' : false }, ] }, + { + 'display_name' : 'Virtual Machine Floating IP Statistics', + 'stat_type' : 'UveVMInterfaceAgent' + 'stat_attr' : 'fip_diff_stats', + 'obj_table' : VMI_TABLE, + 'attributes': [ + { 'name' : 'virtual_network', 'datatype' : 'string', 'index' : true }, + { 'name' : 'fip_diff_stats.other_vn', 'datatype' : 'string', 'index' : true }, + { 'name' : 'fip_diff_stats.ip_address', 'datatype' : 'string', 'index' : true }, + { 'name' : 'fip_diff_stats.in_pkts', 'datatype' : 'int', 'index' : false }, + { 'name' : 'fip_diff_stats.in_bytes', 'datatype' : 'int', 'index' : false }, + { 'name' : 'fip_diff_stats.out_pkts', 'datatype' : 'int', 'index' : false }, + { 'name' : 'fip_diff_stats.out_bytes', 'datatype' : 'int', 'index' : false } + ] + }, + { + 'display_name' : 'Virtual Machine Interface Statistics', + 'stat_type' : 'UveVMInterfaceAgent' + 'stat_attr' : 'if_stats', + 'obj_table' : VMI_TABLE, + 'attributes': [ + { 'name' : 'vm_name', 'datatype' : 'string', 'index' : true }, + { 'name' : 'virtual_network', 'datatype' : 'string', 'index' : true }, + { 'name' : 'if_stats.in_pkts', 'datatype' : 'int', 'index' : false }, + { 'name' : 'if_stats.in_bytes', 'datatype' : 'int', 'index' : false }, + { 'name' : 'if_stats.out_pkts', 'datatype' : 'int', 'index' : false }, + { 'name' : 'if_stats.out_bytes', 'datatype' : 'int', 'index' : false }, + { 'name' : 'if_stats.in_bw_usage', 'datatype' : 'int', 'index' : false }, + { 'name' : 'if_stats.out_bw_usage', 'datatype' : 'int', 'index' : false } + ] + } ] const list _TABLES = [ diff --git a/src/base/timer.h b/src/base/timer.h index 25df9e270b3..c7b7ddc674d 100644 --- a/src/base/timer.h +++ b/src/base/timer.h @@ -92,6 +92,10 @@ class Timer { return (state_ == Fired); } + int time() const { + return time_; + } + bool cancelled() const { tbb::mutex::scoped_lock lock(mutex_); return (state_ == Cancelled); diff --git a/src/vnsw/agent/test/SConscript b/src/vnsw/agent/test/SConscript index 9efaf11051b..2a40bfde4bf 100644 --- a/src/vnsw/agent/test/SConscript +++ b/src/vnsw/agent/test/SConscript @@ -45,6 +45,7 @@ test_lib_srcs = ['test_agent_init.cc', '../uve/test/agent_param_test.cc', '../uve/test/agent_uve_test.cc', '../uve/test/agent_stats_collector_test.cc', + '../uve/test/interface_uve_table_test.cc', '../uve/test/prouter_uve_table_test.cc', '../uve/test/vm_uve_table_test.cc', '../uve/test/vn_uve_table_test.cc', diff --git a/src/vnsw/agent/test/test_util.cc b/src/vnsw/agent/test/test_util.cc index 3ae9513a024..2bf3f9bdcf6 100644 --- a/src/vnsw/agent/test/test_util.cc +++ b/src/vnsw/agent/test/test_util.cc @@ -793,28 +793,6 @@ bool VrfStatsMatchPrev(int vrf_id, uint64_t discards, uint64_t resolves, return false; } -bool VnStatsMatch(char *vn, uint64_t in_bytes, uint64_t in_pkts, - uint64_t out_bytes, uint64_t out_pkts) { - VnUveTableTest *vnut = static_cast - (Agent::GetInstance()->uve()->vn_uve_table()); - const VnUveEntry* entry = vnut->GetVnUveEntry(string(vn)); - if (!entry) { - LOG(DEBUG, "Vn " << string(vn) << " NOT FOUND"); - return false; - } - uint64_t match_in_bytes, match_out_bytes, match_in_pkts, match_out_pkts; - entry->GetInStats(&match_in_bytes, &match_in_pkts); - entry->GetOutStats(&match_out_bytes, &match_out_pkts); - - if (match_in_bytes == in_bytes && match_in_pkts == in_pkts && - match_out_bytes == out_bytes && match_out_pkts == out_pkts) { - return true; - } - LOG(DEBUG, "in_bytes " << match_in_bytes << " in_tpkts " << match_in_pkts << - "out bytes " << match_out_bytes << " out_tpkts " << match_out_pkts); - return false; -} - bool VmPortStats(PortInfo *input, int id, uint32_t bytes, uint32_t pkts) { Interface *intf; VmInterfaceKey key(AgentKey::ADD_DEL_CHANGE, MakeUuid(input[id].intf_id), diff --git a/src/vnsw/agent/uve/SConscript b/src/vnsw/agent/uve/SConscript index cdc76955162..c13d1ed8233 100644 --- a/src/vnsw/agent/uve/SConscript +++ b/src/vnsw/agent/uve/SConscript @@ -69,7 +69,8 @@ env.Default(sdist_gen) env.Alias("vrouter:node_mgr", sdist_gen) # Generate the C++ source files -SandeshGenFiles = env.SandeshGenCpp('port_bmap.sandesh') +SandeshGenFiles = env.SandeshGenCpp('interface.sandesh') +SandeshGenFiles += env.SandeshGenCpp('port_bmap.sandesh') SandeshGenFiles += env.SandeshGenCpp('vrouter.sandesh') SandeshGenFiles += env.SandeshGenCpp('virtual_machine.sandesh') SandeshGenFiles += env.SandeshGenCpp('virtual_network.sandesh') @@ -91,6 +92,7 @@ libuve = env.Library('uve', SandeshGenObjs + [ 'agent_uve_base.cc', + 'interface_uve_table.cc', 'l4_port_bitmap.cc', 'prouter_uve_table.cc', 'vm_uve_entry_base.cc', @@ -105,6 +107,7 @@ libstatsuve = env.Library('statsuve', StatsSandeshGenObjs + [ 'agent_uve.cc', + 'interface_uve_stats_table.cc', 'stats_manager.cc', 'vm_stat.cc', 'vm_uve_entry.cc', diff --git a/src/vnsw/agent/uve/agent_uve.cc b/src/vnsw/agent/uve/agent_uve.cc index 63ab408b4c2..a41cf7ab51d 100644 --- a/src/vnsw/agent/uve/agent_uve.cc +++ b/src/vnsw/agent/uve/agent_uve.cc @@ -17,6 +17,7 @@ #include #include #include +#include AgentUve::AgentUve(Agent *agent, uint64_t intvl, uint32_t default_intvl, uint32_t incremental_intvl) @@ -26,6 +27,8 @@ AgentUve::AgentUve(Agent *agent, uint64_t intvl, uint32_t default_intvl, vn_uve_table_.reset(new VnUveTable(agent, default_intvl)); vm_uve_table_.reset(new VmUveTable(agent, default_intvl)); vrouter_uve_entry_.reset(new VrouterUveEntry(agent)); + interface_uve_table_.reset(new InterfaceUveStatsTable(agent, + default_intvl)); } AgentUve::~AgentUve() { diff --git a/src/vnsw/agent/uve/agent_uve_base.cc b/src/vnsw/agent/uve/agent_uve_base.cc index 823809cff9d..4baf90377cd 100644 --- a/src/vnsw/agent/uve/agent_uve_base.cc +++ b/src/vnsw/agent/uve/agent_uve_base.cc @@ -31,6 +31,7 @@ AgentUveBase::AgentUveBase(Agent *agent, uint64_t intvl, bool create_objects, uint32_t default_intvl, uint32_t incremental_intvl) : vn_uve_table_(NULL), vm_uve_table_(NULL), vrouter_uve_entry_(NULL), prouter_uve_table_(new ProuterUveTable(agent, default_intvl)), + interface_uve_table_(NULL), default_interval_(default_intvl), incremental_interval_(incremental_intvl), agent_(agent), bandwidth_intvl_(intvl), @@ -41,6 +42,7 @@ AgentUveBase::AgentUveBase(Agent *agent, uint64_t intvl, bool create_objects, vn_uve_table_.reset(new VnUveTableBase(agent, default_intvl)); vm_uve_table_.reset(new VmUveTableBase(agent, default_intvl)); vrouter_uve_entry_.reset(new VrouterUveEntryBase(agent)); + interface_uve_table_.reset(new InterfaceUveTable(agent, default_intvl)); } singleton_ = this; } @@ -53,6 +55,7 @@ void AgentUveBase::Shutdown() { vm_uve_table_.get()->Shutdown(); vrouter_uve_entry_.get()->Shutdown(); prouter_uve_table_.get()->Shutdown(); + interface_uve_table_.get()->Shutdown(); connection_state_manager_->Shutdown(); vrouter_stats_collector_->Shutdown(); } @@ -189,5 +192,6 @@ void AgentUveBase::RegisterDBClients() { vm_uve_table_.get()->RegisterDBClients(); vrouter_uve_entry_.get()->RegisterDBClients(); prouter_uve_table_.get()->RegisterDBClients(); + interface_uve_table_.get()->RegisterDBClients(); } diff --git a/src/vnsw/agent/uve/agent_uve_base.h b/src/vnsw/agent/uve/agent_uve_base.h index 7802a226ca4..25dc0f6a0f6 100644 --- a/src/vnsw/agent/uve/agent_uve_base.h +++ b/src/vnsw/agent/uve/agent_uve_base.h @@ -10,6 +10,7 @@ #include #include #include +#include #include class VrouterStatsCollector; @@ -41,7 +42,12 @@ class AgentUveBase { VrouterUveEntryBase* vrouter_uve_entry() const { return vrouter_uve_entry_.get(); } - ProuterUveTable* prouter_uve_table() const { return prouter_uve_table_.get(); } + ProuterUveTable* prouter_uve_table() const { + return prouter_uve_table_.get(); + } + InterfaceUveTable* interface_uve_table() const { + return interface_uve_table_.get(); + } VrouterStatsCollector *vrouter_stats_collector() const { return vrouter_stats_collector_.get(); } @@ -57,6 +63,7 @@ class AgentUveBase { boost::scoped_ptr vm_uve_table_; boost::scoped_ptr vrouter_uve_entry_; boost::scoped_ptr prouter_uve_table_; + boost::scoped_ptr interface_uve_table_; uint32_t default_interval_; uint32_t incremental_interval_; static AgentUveBase *singleton_; diff --git a/src/vnsw/agent/uve/interface.sandesh b/src/vnsw/agent/uve/interface.sandesh new file mode 100644 index 00000000000..a66d92ad263 --- /dev/null +++ b/src/vnsw/agent/uve/interface.sandesh @@ -0,0 +1,59 @@ +/* + * Copyright (c) 2015 Juniper Networks, Inc. All rights reserved. + */ + +include "vnsw/agent/uve/port_bmap.sandesh" + +struct VmFloatingIPAgent { + 1: string virtual_network; + 2: string ip_address; +} + +struct VmFloatingIPStats { + 1: string virtual_network; + 2: string ip_address; + 3: u64 in_pkts; + 4: u64 in_bytes; + 5: u64 out_pkts; + 6: u64 out_bytes; +} + +/* + * VM's interfaces' stats samples (diff stats) + */ +struct VmInterfaceStats { + 1: u64 in_pkts; + 2: u64 in_bytes; + 3: u64 out_pkts; + 4: u64 out_bytes; + 5: u64 in_bw_usage; + 6: u64 out_bw_usage; +} + +struct UveVMInterfaceAgent { + 1: string name (key="ObjectVMITable") + 2: optional bool deleted + 3: optional string ip_address; + 4: string virtual_network; + 5: optional string mac_address; + 6: optional u32 label; + 7: optional bool active; + 8: string vm_name; + 9: optional string gateway; + 10: optional bool l2_active; + 11: optional string uuid; + 12: optional string ip6_address; + 13: optional bool ip6_active; + 14: optional port_bmap.PortBucketBitmap port_bucket_bmap; + 15: optional list floating_ips; + /* List of Floating Ips along with total stats */ + 16: optional list fip_agg_stats; + 17: optional list fip_diff_stats (tags=".virtual_network,.ip_address") + /* Will have only 1 element if_stats list. Made as list because of analytics + * stats infra restriction */ + 18: optional list if_stats (tags="vm_name, virtual_network") +} + +uve sandesh UveVMInterfaceAgentTrace { + 1: UveVMInterfaceAgent data; +} diff --git a/src/vnsw/agent/uve/interface_uve_stats_table.cc b/src/vnsw/agent/uve/interface_uve_stats_table.cc new file mode 100644 index 00000000000..3a8893da460 --- /dev/null +++ b/src/vnsw/agent/uve/interface_uve_stats_table.cc @@ -0,0 +1,176 @@ +/* + * Copyright (c) 2015 Juniper Networks, Inc. All rights reserved. + */ + +#include +#include +#include + +InterfaceUveStatsTable::InterfaceUveStatsTable(Agent *agent, + uint32_t default_intvl) + : InterfaceUveTable(agent, default_intvl) { +} + +InterfaceUveStatsTable::~InterfaceUveStatsTable() { +} + +bool InterfaceUveStatsTable::FrameInterfaceStatsMsg(UveInterfaceEntry* entry, + UveVMInterfaceAgent *uve) const { + uint64_t in_band, out_band; + vector if_stats_list; + VmInterfaceStats if_stats; + vector agg_fip_list; + vector diff_fip_list; + + const VmInterface *vm_intf = entry->intf_; + assert(!entry->deleted_); + if (vm_intf->cfg_name().empty()) { + return false; + } + uve->set_name(vm_intf->cfg_name()); + entry->SetVnVmName(uve); + + const Interface *intf = static_cast(vm_intf); + AgentUve *agent_uve = static_cast(agent_->uve()); + StatsManager::InterfaceStats *s = + agent_uve->stats_manager()->GetInterfaceStats(intf); + if (s == NULL) { + return false; + } + + /* Only diff since previous send needs to be sent as we export + * stats via StatsOracle infra provided by analytics module */ + uint64_t in_b, in_p, out_b, out_p; + s->GetDiffStats(&in_b, &in_p, &out_b, &out_p); + if_stats.set_in_pkts(in_p); + if_stats.set_in_bytes(in_b); + if_stats.set_out_pkts(out_p); + if_stats.set_out_bytes(out_b); + in_band = GetVmPortBandwidth(s, true); + out_band = GetVmPortBandwidth(s, false); + if_stats.set_in_bw_usage(in_band); + if_stats.set_out_bw_usage(out_band); + s->stats_time = UTCTimestampUsec(); + + /* Make sure that update of prev_in_bytes and prev_out_bytes are done only + * after GetVmPortBandwidth is done for both directions as they get used + * in those APIs. */ + s->UpdatePrevStats(); + + PortBucketBitmap map; + L4PortBitmap &port_bmap = entry->port_bitmap_; + port_bmap.Encode(map); + uve->set_port_bucket_bmap(map); + + FrameFipStatsMsg(vm_intf, agg_fip_list, diff_fip_list); + if (entry->FipAggStatsChanged(agg_fip_list)) { + uve->set_fip_agg_stats(agg_fip_list); + entry->uve_info_.set_fip_agg_stats(agg_fip_list); + } + /* Diff stats are sent always regardless of whether there are + * any changes are not. */ + uve->set_fip_diff_stats(diff_fip_list); + + if_stats_list.push_back(if_stats); + uve->set_if_stats(if_stats_list); + + return true; +} + +void InterfaceUveStatsTable::SendInterfaceStatsMsg(UveInterfaceEntry* entry) { + if (entry->deleted_) { + return; + } + UveVMInterfaceAgent uve; + + bool send = FrameInterfaceStatsMsg(entry, &uve); + if (send) { + DispatchInterfaceMsg(uve); + } +} + +void InterfaceUveStatsTable::SendInterfaceStats(void) { + InterfaceMap::iterator it = interface_tree_.begin(); + while (it != interface_tree_.end()) { + UveInterfaceEntry* entry = it->second.get(); + SendInterfaceStatsMsg(entry); + it++; + } +} + +uint64_t InterfaceUveStatsTable::GetVmPortBandwidth + (StatsManager::InterfaceStats *s, bool dir_in) const { + if (s->stats_time == 0) { + return 0; + } + uint64_t bits; + if (dir_in) { + bits = (s->in_bytes - s->prev_in_bytes) * 8; + } else { + bits = (s->out_bytes - s->prev_out_bytes) * 8; + } + uint64_t cur_time = UTCTimestampUsec(); + uint64_t b_intvl = agent_->uve()->bandwidth_intvl(); + uint64_t diff_seconds = (cur_time - s->stats_time) / b_intvl; + if (diff_seconds == 0) { + return 0; + } + return bits/diff_seconds; +} + +void InterfaceUveStatsTable::UpdateFloatingIpStats(const FipInfo &fip_info) { + Interface *intf = InterfaceTable::GetInstance()->FindInterface + (fip_info.fip_vm_port_id_); + VmInterface *vmi = static_cast(intf); + InterfaceMap::iterator intf_it = interface_tree_.find(vmi->cfg_name()); + + /* + * 1. VM interface with floating-ip becomes active + * 2. Flow is created on this interface and interface floating ip info is + * stored in flow record + * 3. VM Interface is disassociated from VM + * 4. VM Interface info is removed from interface_tree_ because of + * disassociation + * 5. FlowStats collection task initiates export of flow stats + * 6. Since interface is absent in interface_tree_ we cannot update + * stats in this case + */ + if (intf_it != interface_tree_.end()) { + UveInterfaceEntry *entry = intf_it->second.get(); + entry->UpdateFloatingIpStats(fip_info); + } +} + +bool InterfaceUveStatsTable::FrameFipStatsMsg(const VmInterface *itf, + vector &fip_list, + vector &diff_list) const { + bool changed = false; + InterfaceMap::const_iterator it = interface_tree_.find(itf->cfg_name()); + + if (it != interface_tree_.end()) { + UveInterfaceEntry *entry = it->second.get(); + changed = entry->FillFloatingIpStats(fip_list, diff_list); + } + return changed; +} + + +void InterfaceUveStatsTable::UpdatePortBitmap + (const string &name, uint8_t proto, uint16_t sport, uint16_t dport) { + InterfaceMap::const_iterator it = interface_tree_.find(name); + + if (it != interface_tree_.end()) { + UveInterfaceEntry *entry = it->second.get(); + entry->port_bitmap_.AddPort(proto, sport, dport); + } +} + +InterfaceUveTable::FloatingIp * InterfaceUveStatsTable::FipEntry + (uint32_t fip, const string &vn, Interface *intf) { + VmInterface *vmi = static_cast(intf); + InterfaceMap::iterator intf_it = interface_tree_.find(vmi->cfg_name()); + + assert (intf_it != interface_tree_.end()); + UveInterfaceEntry *entry = intf_it->second.get(); + return entry->FipEntry(fip, vn); +} diff --git a/src/vnsw/agent/uve/interface_uve_stats_table.h b/src/vnsw/agent/uve/interface_uve_stats_table.h new file mode 100644 index 00000000000..f4c9415869a --- /dev/null +++ b/src/vnsw/agent/uve/interface_uve_stats_table.h @@ -0,0 +1,40 @@ +/* + * Copyright (c) 2015 Juniper Networks, Inc. All rights reserved. + */ + +#ifndef vnsw_agent_interface_uve_stats_table_h +#define vnsw_agent_interface_uve_stats_table_h + +#include +#include +#include +#include +#include + +class InterfaceUveStatsTable : public InterfaceUveTable { +public: + InterfaceUveStatsTable(Agent *agent, uint32_t default_intvl); + virtual ~InterfaceUveStatsTable(); + void UpdateBitmap(const VmEntry* vm, uint8_t proto, uint16_t sport, + uint16_t dport); + void SendInterfaceStats(void); + void UpdateFloatingIpStats(const FipInfo &fip_info); + InterfaceUveTable::FloatingIp * FipEntry + (uint32_t fip, const string &vn, Interface *intf); + void UpdatePortBitmap + (const string &name, uint8_t proto, uint16_t sport, uint16_t dport); + +private: + void SendInterfaceStatsMsg(UveInterfaceEntry* entry); + uint64_t GetVmPortBandwidth + (StatsManager::InterfaceStats *s, bool dir_in) const; + bool FrameFipStatsMsg(const VmInterface *vm_intf, + vector &fip_list, + vector &diff_list) const; + bool FrameInterfaceStatsMsg(UveInterfaceEntry* entry, + UveVMInterfaceAgent *uve) const; + + DISALLOW_COPY_AND_ASSIGN(InterfaceUveStatsTable); +}; + +#endif // vnsw_agent_interface_uve_stats_table_h diff --git a/src/vnsw/agent/uve/interface_uve_table.cc b/src/vnsw/agent/uve/interface_uve_table.cc new file mode 100644 index 00000000000..d53a3e2494f --- /dev/null +++ b/src/vnsw/agent/uve/interface_uve_table.cc @@ -0,0 +1,466 @@ +/* + * Copyright (c) 2015 Juniper Networks, Inc. All rights reserved. + */ + +#include +#include +#include + +InterfaceUveTable::InterfaceUveTable(Agent *agent, uint32_t default_intvl) + : agent_(agent), interface_tree_(), + intf_listener_id_(DBTableBase::kInvalidId), + timer_last_visited_(""), + timer_(TimerManager::CreateTimer + (*(agent->event_manager())->io_service(), + "InterfaceUveTimer", + TaskScheduler::GetInstance()->GetTaskId("db::DBTable"), 0)) { + expiry_time_ = default_intvl; + timer_->Start(expiry_time_, + boost::bind(&InterfaceUveTable::TimerExpiry, this)); +} + +InterfaceUveTable::~InterfaceUveTable() { +} + +bool InterfaceUveTable::TimerExpiry() { + InterfaceMap::iterator it = interface_tree_.lower_bound(timer_last_visited_); + if (it == interface_tree_.end()) { + timer_last_visited_ = ""; + return true; + } + + uint32_t count = 0; + while (it != interface_tree_.end() && + count < AgentUveBase::kUveCountPerTimer) { + string cfg_name = it->first; + UveInterfaceEntry* entry = it->second.get(); + InterfaceMap::iterator prev = it; + it++; + count++; + + if (entry->deleted_) { + SendInterfaceDeleteMsg(cfg_name); + if (!entry->renewed_) { + interface_tree_.erase(prev); + } else { + entry->deleted_ = false; + entry->renewed_ = false; + entry->changed_ = false; + SendInterfaceMsg(cfg_name, entry); + } + } else if (entry->changed_) { + SendInterfaceMsg(cfg_name, entry); + entry->changed_ = false; + /* Clear renew flag to be on safer side. Not really required */ + entry->renewed_ = false; + } + } + + if (it == interface_tree_.end()) { + timer_last_visited_ = ""; + set_expiry_time(agent_->uve()->default_interval()); + } else { + timer_last_visited_ = it->first; + set_expiry_time(agent_->uve()->incremental_interval()); + } + /* Return true to trigger auto-restart of timer */ + return true; +} + +void InterfaceUveTable::set_expiry_time(int time) { + if (time != expiry_time_) { + expiry_time_ = time; + timer_->Reschedule(expiry_time_); + } +} + +void InterfaceUveTable::UveInterfaceEntry::SetVnVmName(UveVMInterfaceAgent *uve) + const { + /* VM interfaces which are not created by Nova will not have VM name set. + * In that case pick VM name from VM object instead of VMI object */ + if (!intf_->vm_name().empty()) { + uve->set_vm_name(intf_->vm_name()); + } else { + const VmEntry *vm = intf_->vm(); + if (vm) { + uve->set_vm_name(vm->GetCfgName()); + } + } + if (intf_->vn() != NULL) { + uve->set_virtual_network(intf_->vn()->GetName()); + } else { + uve->set_virtual_network(""); + } +} + + +bool InterfaceUveTable::UveInterfaceEntry::FrameInterfaceMsg(const string &name, + UveVMInterfaceAgent *s_intf) const { + s_intf->set_name(name); + SetVnVmName(s_intf); + s_intf->set_ip_address(intf_->ip_addr().to_string()); + s_intf->set_mac_address(intf_->vm_mac()); + s_intf->set_ip6_address(intf_->ip6_addr().to_string()); + s_intf->set_ip6_active(intf_->ipv6_active()); + + vector uve_fip_list; + if (intf_->HasFloatingIp(Address::INET)) { + const VmInterface::FloatingIpList fip_list = + intf_->floating_ip_list(); + VmInterface::FloatingIpSet::const_iterator it = + fip_list.list_.begin(); + while(it != fip_list.list_.end()) { + const VmInterface::FloatingIp &ip = *it; + /* Don't export FIP entry if it is not installed. When FIP entry + * is not installed it will have NULL VN pointer. We can receive + * notifications for VM interface with un-installed FIP entries + * when the VM interface is not "L3 Active". + */ + if (ip.installed_) { + VmFloatingIPAgent uve_fip; + uve_fip.set_ip_address(ip.floating_ip_.to_string()); + uve_fip.set_virtual_network(ip.vn_.get()->GetName()); + uve_fip_list.push_back(uve_fip); + } + it++; + } + } + s_intf->set_floating_ips(uve_fip_list); + + s_intf->set_label(intf_->label()); + s_intf->set_active(intf_->ipv4_active()); + s_intf->set_l2_active(intf_->l2_active()); + s_intf->set_uuid(to_string(intf_->GetUuid())); + string gw; + if (GetVmInterfaceGateway(intf_, gw)) { + s_intf->set_gateway(gw); + } + + return true; +} + +void InterfaceUveTable::UveInterfaceEntry::Reset() { + intf_ = NULL; + port_bitmap_.Reset(); + prev_fip_tree_.clear(); + fip_tree_.clear(); + + deleted_ = true; + renewed_ = false; +} + +bool InterfaceUveTable::UveInterfaceEntry::FipAggStatsChanged + (const vector &list) const { + if (list != uve_info_.get_fip_agg_stats()) { + return true; + } + return false; +} + +bool InterfaceUveTable::UveInterfaceEntry::GetVmInterfaceGateway( + const VmInterface *vm_intf, string &gw) const { + const VnEntry *vn = vm_intf->vn(); + if (vn == NULL) { + return false; + } + const vector &list = vn->GetVnIpam(); + Ip4Address vm_addr = vm_intf->ip_addr(); + unsigned int i; + for (i = 0; i < list.size(); i++) { + if (list[i].IsSubnetMember(vm_addr)) + break; + } + if (i == list.size()) { + return false; + } + gw = list[i].default_gw.to_string(); + return true; +} + +void InterfaceUveTable::SendInterfaceDeleteMsg(const string &config_name) { + UveVMInterfaceAgent uve; + uve.set_name(config_name); + uve.set_deleted(true); + DispatchInterfaceMsg(uve); +} + +InterfaceUveTable::UveInterfaceEntryPtr +InterfaceUveTable::Allocate(const VmInterface *itf) { + UveInterfaceEntryPtr uve(new UveInterfaceEntry(itf)); + return uve; +} + +void InterfaceUveTable::DispatchInterfaceMsg(const UveVMInterfaceAgent &uve) { + UveVMInterfaceAgentTrace::Send(uve); +} + +void InterfaceUveTable::SendInterfaceMsg(const string &name, + UveInterfaceEntry *entry) { + UveVMInterfaceAgent uve; + if (entry->FrameInterfaceMsg(name, &uve)) { + DispatchInterfaceMsg(uve); + } +} + +void InterfaceUveTable::InterfaceAddHandler(const VmInterface* itf, + const VmInterface::FloatingIpSet &old_list) { + UveInterfaceEntryPtr uve = Allocate(itf); + pair ret; + ret = interface_tree_.insert(InterfacePair(itf->cfg_name(), uve)); + InterfaceMap::iterator it = ret.first; + UveInterfaceEntry* entry = it->second.get(); + if (entry->deleted_) { + entry->renewed_ = true; + entry->intf_ = itf; + } + + /* Mark the entry as changed to account for change in any fields of VMI */ + entry->changed_ = true; + + /* We need to handle only floating-ip deletion. The add of floating-ip is + * taken care when stats are available for them during flow stats + * collection */ + const VmInterface::FloatingIpSet &new_list = itf->floating_ip_list().list_; + /* We need to look for entries which are present in old_list and not + * in new_list */ + VmInterface::FloatingIpSet::const_iterator old_it = old_list.begin(); + while (old_it != old_list.end()) { + VmInterface::FloatingIp fip = *old_it; + ++old_it; + /* Skip entries which are not installed as they wouldn't have been + * added + */ + if (!fip.installed_) { + continue; + } + VmInterface::FloatingIpSet::const_iterator new_it = new_list.find(fip); + if (new_it == new_list.end()) { + entry->RemoveFloatingIp(fip); + } + } +} + +void InterfaceUveTable::InterfaceDeleteHandler(const string &name) { + InterfaceMap::iterator it = interface_tree_.find(name); + if (it == interface_tree_.end()) { + return; + } + UveInterfaceEntry* entry = it->second.get(); + /* We need to reset all non-key fields to ensure that they have right + * values since the entry is getting re-used. Also update the 'deleted_' + * and 'renewed_' flags */ + entry->Reset(); + return; +} + +void InterfaceUveTable::InterfaceNotify(DBTablePartBase *partition, + DBEntryBase *e) { + const VmInterface *vm_port = dynamic_cast(e); + if (vm_port == NULL) { + return; + } + + UveInterfaceState *state = static_cast + (e->GetState(partition->parent(), intf_listener_id_)); + if (e->IsDeleted() && state) { + InterfaceDeleteHandler(state->cfg_name_); + state->fip_list_.clear(); + e->ClearState(partition->parent(), intf_listener_id_); + delete state; + } else { + VmInterface::FloatingIpSet old_list; + if (vm_port->cfg_name().empty()) { + /* Skip Add/change notifications if the config_name is empty */ + return; + } + + if (!state) { + state = new UveInterfaceState(vm_port); + e->SetState(partition->parent(), intf_listener_id_, state); + } else { + old_list = state->fip_list_; + state->fip_list_ = vm_port->floating_ip_list().list_; + } + if (state->cfg_name_ != vm_port->cfg_name()) { + InterfaceDeleteHandler(state->cfg_name_); + state->cfg_name_ = vm_port->cfg_name(); + } + InterfaceAddHandler(vm_port, old_list); + } +} + +void InterfaceUveTable::RegisterDBClients() { + InterfaceTable *intf_table = agent_->interface_table(); + intf_listener_id_ = intf_table->Register + (boost::bind(&InterfaceUveTable::InterfaceNotify, this, _1, _2)); + +} + +void InterfaceUveTable::Shutdown(void) { + if (intf_listener_id_ != DBTableBase::kInvalidId) + agent_->interface_table()->Unregister(intf_listener_id_); + + if (timer_) { + timer_->Cancel(); + TimerManager::DeleteTimer(timer_); + timer_ = NULL; + } +} + +void InterfaceUveTable::UveInterfaceEntry::UpdateFloatingIpStats + (const FipInfo &fip_info) { + tbb::mutex::scoped_lock lock(mutex_); + FloatingIp *entry = FipEntry(fip_info.fip_, fip_info.vn_); + entry->UpdateFloatingIpStats(fip_info); +} + +InterfaceUveTable::FloatingIp *InterfaceUveTable::UveInterfaceEntry::FipEntry + (uint32_t ip, const string &vn) { + Ip4Address addr(ip); + FloatingIpPtr key(new FloatingIp(addr, vn)); + FloatingIpSet::iterator fip_it = fip_tree_.find(key); + if (fip_it == fip_tree_.end()) { + fip_tree_.insert(key); + return key.get(); + } else { + return (*fip_it).get(); + } +} +void InterfaceUveTable::FloatingIp::UpdateFloatingIpStats(const FipInfo &fip_info) { + if (fip_info.is_local_flow_) { + if (fip_info.is_reverse_flow_) { + out_bytes_ += fip_info.bytes_; + out_packets_ += fip_info.packets_; + + if (fip_info.rev_fip_) { + /* This is the case where Source and Destination VMs (part of + * same compute node) ping to each other to their respective + * Floating IPs. In this case for each flow we need to increment + * stats for both the VMs */ + fip_info.rev_fip_->out_bytes_ += fip_info.bytes_; + fip_info.rev_fip_->out_packets_ += fip_info.packets_; + } + } else { + in_bytes_ += fip_info.bytes_; + in_packets_ += fip_info.packets_; + if (fip_info.rev_fip_) { + /* This is the case where Source and Destination VMs (part of + * same compute node) ping to each other to their respective + * Floating IPs. In this case for each flow we need to increment + * stats for both the VMs */ + fip_info.rev_fip_->in_bytes_ += fip_info.bytes_; + fip_info.rev_fip_->in_packets_ += fip_info.packets_; + } + } + } else { + if (fip_info.is_ingress_flow_) { + in_bytes_ += fip_info.bytes_; + in_packets_ += fip_info.packets_; + } else { + out_bytes_ += fip_info.bytes_; + out_packets_ += fip_info.packets_; + } + } +} + + +bool InterfaceUveTable::UveInterfaceEntry::FillFloatingIpStats + (vector &result, + vector &diff_list) { + const VmInterface *vm_intf = static_cast(intf_); + tbb::mutex::scoped_lock lock(mutex_); + if (vm_intf->HasFloatingIp()) { + const VmInterface::FloatingIpList fip_list = + vm_intf->floating_ip_list(); + VmInterface::FloatingIpSet::const_iterator it = + fip_list.list_.begin(); + while(it != fip_list.list_.end()) { + const VmInterface::FloatingIp &ip = *it; + /* Skip FIP entries which are not yet activated */ + if (!ip.installed_) { + it++; + continue; + } + VmFloatingIPStats uve_fip; + VmFloatingIPStats diff_uve; + uve_fip.set_ip_address(ip.floating_ip_.to_string()); + uve_fip.set_virtual_network(ip.vn_.get()->GetName()); + + diff_uve.set_ip_address(ip.floating_ip_.to_string()); + diff_uve.set_virtual_network(ip.vn_.get()->GetName()); + + FloatingIpPtr key(new FloatingIp(ip.floating_ip_, + ip.vn_.get()->GetName())); + FloatingIpSet::iterator fip_it = fip_tree_.find(key); + if (fip_it == fip_tree_.end()) { + SetStats(uve_fip, 0, 0, 0, 0); + SetDiffStats(diff_uve, 0, 0, 0, 0); + } else { + FloatingIp *fip = (*fip_it).get(); + SetStats(uve_fip, fip->in_bytes_, fip->in_packets_, + fip->out_bytes_, fip->out_packets_); + FloatingIpSet::iterator prev_it = prev_fip_tree_.find(key); + if (prev_it == prev_fip_tree_.end()) { + SetDiffStats(diff_uve, fip->in_bytes_, fip->in_packets_, + fip->out_bytes_, fip->out_packets_); + FloatingIpPtr prev_fip_ptr(new FloatingIp(ip.floating_ip_, + ip.vn_.get()->GetName(), + fip->in_bytes_, + fip->in_packets_, + fip->out_bytes_, + fip->out_packets_)); + prev_fip_tree_.insert(prev_fip_ptr); + } else { + FloatingIp *pfip = (*prev_it).get(); + SetDiffStats(diff_uve, (fip->in_bytes_ - pfip->in_bytes_), + (fip->in_packets_ - pfip->in_packets_), + (fip->out_bytes_ - pfip->out_bytes_), + (fip->out_packets_ - pfip->out_packets_)); + pfip->in_bytes_ = fip->in_bytes_; + pfip->in_packets_ = fip->in_packets_; + pfip->out_bytes_ = fip->out_bytes_; + pfip->out_packets_ = fip->out_packets_; + } + + } + result.push_back(uve_fip); + diff_list.push_back(diff_uve); + it++; + } + return true; + } + return false; +} + +void InterfaceUveTable::UveInterfaceEntry::SetDiffStats + (VmFloatingIPStats &fip, uint64_t in_bytes, uint64_t in_pkts, + uint64_t out_bytes, uint64_t out_pkts) const { + fip.set_in_bytes(in_bytes); + fip.set_in_pkts(in_pkts); + fip.set_out_bytes(out_bytes); + fip.set_out_pkts(out_pkts); +} + +void InterfaceUveTable::UveInterfaceEntry::SetStats + (VmFloatingIPStats &fip, uint64_t in_bytes, uint64_t in_pkts, + uint64_t out_bytes, uint64_t out_pkts) const { + fip.set_in_bytes(in_bytes); + fip.set_in_pkts(in_pkts); + fip.set_out_bytes(out_bytes); + fip.set_out_pkts(out_pkts); +} + +void InterfaceUveTable::UveInterfaceEntry::RemoveFloatingIp + (const VmInterface::FloatingIp &fip) { + tbb::mutex::scoped_lock lock(mutex_); + FloatingIpPtr key(new FloatingIp(fip.floating_ip_, fip.vn_.get()->GetName())); + FloatingIpSet::iterator it = fip_tree_.find(key); + if (it != fip_tree_.end()) { + fip_tree_.erase(it); + } + FloatingIpSet::iterator prev_it = prev_fip_tree_.find(key); + if (prev_it != prev_fip_tree_.end()) { + prev_fip_tree_.erase(prev_it); + } +} + diff --git a/src/vnsw/agent/uve/interface_uve_table.h b/src/vnsw/agent/uve/interface_uve_table.h new file mode 100644 index 00000000000..b2562c2829a --- /dev/null +++ b/src/vnsw/agent/uve/interface_uve_table.h @@ -0,0 +1,159 @@ +/* + * Copyright (c) 2015 Juniper Networks, Inc. All rights reserved. + */ + +#ifndef vnsw_agent_interface_uve_table_h +#define vnsw_agent_interface_uve_table_h + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +//#include "base/queue_task.h" + +//The container class for objects representing VMInterface UVEs +//Defines routines for storing and managing (add, delete, change and send) +//VMInterface UVEs +class InterfaceUveTable { +public: + struct UveInterfaceState :public DBState { + UveInterfaceState(const VmInterface *intf) + : cfg_name_(intf->cfg_name()), + fip_list_(intf->floating_ip_list().list_) {} + std::string cfg_name_; + VmInterface::FloatingIpSet fip_list_; + }; + + struct FloatingIp; + + struct FipInfo { + uint64_t bytes_; + uint64_t packets_; + uint32_t fip_; + uint32_t fip_vm_port_id_; + bool is_local_flow_; + bool is_ingress_flow_; + bool is_reverse_flow_; + std::string vn_; + FloatingIp *rev_fip_; + }; + struct FloatingIp { + FloatingIp(const IpAddress &ip, const std::string &vn) + : family_(ip.is_v4() ? Address::INET : Address::INET6), + fip_(ip), vn_(vn) { + in_bytes_ = 0; + in_packets_ = 0; + out_bytes_ = 0; + out_packets_ = 0; + } + FloatingIp(const IpAddress &ip, const std::string &vn, uint64_t in_b, + uint64_t in_p, uint64_t out_b, uint64_t out_p) + : family_(ip.is_v4() ? Address::INET : Address::INET6), + fip_(ip), vn_(vn), in_bytes_(in_b), in_packets_(in_p), + out_bytes_(out_b), out_packets_(out_p) { + } + void UpdateFloatingIpStats(const FipInfo &fip_info); + + Address::Family family_; + IpAddress fip_; + std::string vn_; + uint64_t in_bytes_; + uint64_t in_packets_; + uint64_t out_bytes_; + uint64_t out_packets_; + }; + typedef boost::shared_ptr FloatingIpPtr; + + class FloatingIpCmp { + public: + bool operator()(const FloatingIpPtr &lhs, + const FloatingIpPtr &rhs) const { + if (lhs.get()->fip_ != rhs.get()->fip_) { + return lhs.get()->fip_ < rhs.get()->fip_; + } + return (lhs.get()->vn_ < rhs.get()->vn_); + } + }; + typedef std::set FloatingIpSet; + + struct UveInterfaceEntry { + const VmInterface *intf_; + boost::uuids::uuid uuid_; + L4PortBitmap port_bitmap_; + FloatingIpSet fip_tree_; + FloatingIpSet prev_fip_tree_; + bool changed_; + bool deleted_; + bool renewed_; + UveVMInterfaceAgent uve_info_; + /* For exclusion between Agent::StatsCollector and Agent::Uve tasks */ + tbb::mutex mutex_; + + UveInterfaceEntry(const VmInterface *i) : intf_(i), + uuid_(i->GetUuid()), port_bitmap_(), + fip_tree_(), prev_fip_tree_(), changed_(true), deleted_(false), + renewed_(false), uve_info_() { } + virtual ~UveInterfaceEntry() {} + void UpdateFloatingIpStats(const FipInfo &fip_info); + bool FillFloatingIpStats(vector &result, + vector &diff_list); + void SetStats(VmFloatingIPStats &fip, uint64_t in_bytes, + uint64_t in_pkts, uint64_t out_bytes, uint64_t out_pkts) const; + void SetDiffStats(VmFloatingIPStats &fip, uint64_t in_bytes, + uint64_t in_pkts, uint64_t out_bytes, uint64_t out_pkts) const; + void RemoveFloatingIp(const VmInterface::FloatingIp &fip); + InterfaceUveTable::FloatingIp *FipEntry(uint32_t ip, + const std::string &vn); + bool FrameInterfaceMsg(const std::string &name, + UveVMInterfaceAgent *s_intf) const; + bool GetVmInterfaceGateway(const VmInterface *vm_intf, + std::string &gw) const; + bool FipAggStatsChanged(const vector &list) const; + void SetVnVmName(UveVMInterfaceAgent *uve) const; + void Reset(); + }; + typedef boost::shared_ptr UveInterfaceEntryPtr; + + typedef std::map InterfaceMap; + typedef std::pair InterfacePair; + + InterfaceUveTable(Agent *agent, uint32_t default_intvl); + virtual ~InterfaceUveTable(); + void RegisterDBClients(); + void Shutdown(void); + virtual void DispatchInterfaceMsg(const UveVMInterfaceAgent &uve); + bool TimerExpiry(); + +protected: + void SendInterfaceDeleteMsg(const std::string &config_name); + + Agent *agent_; + InterfaceMap interface_tree_; +private: + virtual UveInterfaceEntryPtr Allocate(const VmInterface *vm); + void InterfaceNotify(DBTablePartBase *partition, DBEntryBase *e); + void InterfaceAddHandler(const VmInterface* intf, + const VmInterface::FloatingIpSet &old_list); + void InterfaceDeleteHandler(const std::string &name); + void set_expiry_time(int time); + void SendInterfaceMsg(const std::string &name, UveInterfaceEntry *entry); + + DBTableBase::ListenerId intf_listener_id_; + // Last visited Interface by timer + std::string timer_last_visited_; + Timer *timer_; + int expiry_time_; + DISALLOW_COPY_AND_ASSIGN(InterfaceUveTable); +}; + +#endif // vnsw_agent_interface_uve_table_h diff --git a/src/vnsw/agent/uve/prouter.sandesh b/src/vnsw/agent/uve/prouter.sandesh index 534544153af..8c07a025f46 100644 --- a/src/vnsw/agent/uve/prouter.sandesh +++ b/src/vnsw/agent/uve/prouter.sandesh @@ -2,27 +2,37 @@ * Copyright (c) 2014 Juniper Networks, Inc. All rights reserved. */ -struct UveLogicalInterfaceData { - 1: string name (aggtype="listkey") - 2: string uuid - 3: u16 vlan - 4: optional list vm_interface_list -} - -struct UvePhysicalInterfaceData { - 1: string name (aggtype="listkey") - 2: string uuid - 3: optional list logical_interface_list -} - struct ProuterData { 1: string name (key="ObjectPRouter") 2: optional bool deleted 3: string uuid - 4: optional list physical_interface_list - 5: optional list logical_interface_list + 4: optional list physical_interface_list + 5: optional list logical_interface_list } uve sandesh UveProuterAgent { 1: ProuterData data } + +struct UveLogicalInterfaceAgent { + 1: string name (key="ObjectLogicalInterfaceTable") + 2: optional bool deleted + 3: optional string config_name + 4: optional u16 vlan + 5: optional list vm_interface_list +} + +uve sandesh UveLogicalInterfaceAgentTrace { + 1: UveLogicalInterfaceAgent data; +} + +struct UvePhysicalInterfaceAgent { + 1: string name (key="ObjectPhysicalInterfaceTable") + 2: optional bool deleted + 3: optional string uuid + 4: optional list logical_interface_list +} + +uve sandesh UvePhysicalInterfaceAgentTrace { + 1: UvePhysicalInterfaceAgent data; +} diff --git a/src/vnsw/agent/uve/prouter_uve_table.cc b/src/vnsw/agent/uve/prouter_uve_table.cc index 008c9c3f27c..eb9062914c3 100644 --- a/src/vnsw/agent/uve/prouter_uve_table.cc +++ b/src/vnsw/agent/uve/prouter_uve_table.cc @@ -10,29 +10,48 @@ ProuterUveTable::ProuterUveTable(Agent *agent, uint32_t default_intvl) : uve_prouter_map_(), uve_phy_interface_map_(), agent_(agent), physical_device_listener_id_(DBTableBase::kInvalidId), interface_listener_id_(DBTableBase::kInvalidId), - timer_last_visited_(nil_uuid()), - timer_(TimerManager::CreateTimer + pr_timer_last_visited_(nil_uuid()), + pr_timer_(TimerManager::CreateTimer (*(agent->event_manager())->io_service(), "ProuterUveTimer", + TaskScheduler::GetInstance()->GetTaskId("db::DBTable"), 0)), + pi_timer_last_visited_(""), + pi_timer_(TimerManager::CreateTimer + (*(agent->event_manager())->io_service(), + "PIUveTimer", + TaskScheduler::GetInstance()->GetTaskId("db::DBTable"), 0)), + li_timer_last_visited_(nil_uuid()), + li_timer_(TimerManager::CreateTimer + (*(agent->event_manager())->io_service(), + "LIUveTimer", TaskScheduler::GetInstance()->GetTaskId("db::DBTable"), 0)) { - expiry_time_ = default_intvl; - timer_->Start(expiry_time_, + + pr_timer_->Start(default_intvl, boost::bind(&ProuterUveTable::TimerExpiry, this)); + pi_timer_->Start(default_intvl, + boost::bind(&ProuterUveTable::PITimerExpiry, this)); + li_timer_->Start(default_intvl, + boost::bind(&ProuterUveTable::LITimerExpiry, this)); } ProuterUveTable::~ProuterUveTable() { - if (timer_) { - timer_->Cancel(); - TimerManager::DeleteTimer(timer_); - timer_ = NULL; + TimerCleanup(pr_timer_); + TimerCleanup(pi_timer_); + TimerCleanup(li_timer_); +} + +void ProuterUveTable::TimerCleanup(Timer *timer) { + if (timer) { + timer->Cancel(); + TimerManager::DeleteTimer(timer); } } bool ProuterUveTable::TimerExpiry() { UveProuterMap::iterator it = uve_prouter_map_.lower_bound - (timer_last_visited_); + (pr_timer_last_visited_); if (it == uve_prouter_map_.end()) { - timer_last_visited_ = nil_uuid(); + pr_timer_last_visited_ = nil_uuid(); return true; } @@ -64,26 +83,122 @@ bool ProuterUveTable::TimerExpiry() { } if (it == uve_prouter_map_.end()) { - timer_last_visited_ = nil_uuid(); - set_expiry_time(agent_->uve()->default_interval()); + pr_timer_last_visited_ = nil_uuid(); + set_expiry_time(agent_->uve()->default_interval(), pr_timer_); } else { - timer_last_visited_ = it->first; - set_expiry_time(agent_->uve()->incremental_interval()); + pr_timer_last_visited_ = it->first; + set_expiry_time(agent_->uve()->incremental_interval(), pr_timer_); } /* Return true to trigger auto-restart of timer */ return true; } -void ProuterUveTable::set_expiry_time(int time) { - if (time != expiry_time_) { - expiry_time_ = time; - timer_->Reschedule(expiry_time_); +bool ProuterUveTable::PITimerExpiry() { + UvePhyInterfaceMap::iterator it = uve_phy_interface_map_.lower_bound + (pi_timer_last_visited_); + if (it == uve_phy_interface_map_.end()) { + pi_timer_last_visited_ = ""; + return true; + } + + uint32_t count = 0; + while (it != uve_phy_interface_map_.end() && + count < AgentUveBase::kUveCountPerTimer) { + PhyInterfaceUveEntry* entry = it->second.get(); + string cfg_name = it->first; + UvePhyInterfaceMap::iterator prev = it; + it++; + count++; + + if (entry->deleted_) { + SendPhysicalInterfaceDeleteMsg(cfg_name); + if (!entry->renewed_) { + uve_phy_interface_map_.erase(prev); + } else { + entry->deleted_ = false; + entry->renewed_ = false; + entry->changed_ = false; + SendPhysicalInterfaceMsg(cfg_name, entry); + } + } else if (entry->changed_) { + SendPhysicalInterfaceMsg(cfg_name, entry); + entry->changed_ = false; + /* Clear renew flag to be on safer side. Not really required */ + entry->renewed_ = false; + } + } + + if (it == uve_phy_interface_map_.end()) { + pi_timer_last_visited_ = ""; + set_expiry_time(agent_->uve()->default_interval(), pi_timer_); + } else { + pi_timer_last_visited_ = it->first; + set_expiry_time(agent_->uve()->incremental_interval(), pi_timer_); } + /* Return true to trigger auto-restart of timer */ + return true; } -ProuterUveTable::PhyInterfaceAttrEntry::PhyInterfaceAttrEntry - (const Interface *itf) : - uuid_(itf->GetUuid()) { +bool ProuterUveTable::LITimerExpiry() { + LogicalInterfaceMap::iterator it = uve_logical_interface_map_.lower_bound + (li_timer_last_visited_); + if (it == uve_logical_interface_map_.end()) { + li_timer_last_visited_ = nil_uuid(); + return true; + } + + uint32_t count = 0; + while (it != uve_logical_interface_map_.end() && + count < AgentUveBase::kUveCountPerTimer) { + LogicalInterfaceUveEntry* entry = it->second.get(); + boost::uuids::uuid u = it->first; + LogicalInterfaceMap::iterator prev = it; + it++; + count++; + + if (entry->deleted_) { + SendLogicalInterfaceDeleteMsg(entry->name_); + if (!entry->renewed_) { + uve_logical_interface_map_.erase(prev); + } else { + entry->deleted_ = false; + entry->renewed_ = false; + entry->changed_ = false; + SendLogicalInterfaceMsg(u, entry); + } + } else if (entry->changed_) { + SendLogicalInterfaceMsg(u, entry); + entry->changed_ = false; + /* Clear renew flag to be on safer side. Not really required */ + entry->renewed_ = false; + } + } + + if (it == uve_logical_interface_map_.end()) { + li_timer_last_visited_ = nil_uuid(); + set_expiry_time(agent_->uve()->default_interval(), li_timer_); + } else { + li_timer_last_visited_ = it->first; + set_expiry_time(agent_->uve()->incremental_interval(), li_timer_); + } + /* Return true to trigger auto-restart of timer */ + return true; +} + +void ProuterUveTable::set_expiry_time(int time, Timer *timer) { + if (time != timer->time()) { + timer->Reschedule(time); + } +} + +ProuterUveTable::PhyInterfaceUveEntry::PhyInterfaceUveEntry + (const Interface *pintf) : + uuid_(pintf->GetUuid()), logical_interface_set_(), changed_(true), + deleted_(false), renewed_(false) { + Update(pintf); +} + +void ProuterUveTable::PhyInterfaceUveEntry::Update(const Interface *pintf) { } ProuterUveTable::ProuterUveEntry::ProuterUveEntry(const PhysicalDevice *p) : @@ -92,7 +207,8 @@ ProuterUveTable::ProuterUveEntry::ProuterUveEntry(const PhysicalDevice *p) : } ProuterUveTable::LogicalInterfaceUveEntry::LogicalInterfaceUveEntry - (const LogicalInterface *li) : name_(li->name()) { + (const LogicalInterface *li) : name_(li->name()), vlan_(kInvalidVlanId), + vmi_list_(), changed_(true), deleted_(false), renewed_(false) { Update(li); } @@ -105,12 +221,7 @@ void ProuterUveTable::LogicalInterfaceUveEntry::Update } else { vlan_ = kInvalidVlanId; } - const VmInterface *vmi = li->vm_interface(); - if (vmi) { - vmi_uuid_ = vmi->GetUuid(); - } else { - vmi_uuid_ = nil_uuid(); - } + changed_ = true; } ProuterUveTable::ProuterUveEntry::~ProuterUveEntry() { @@ -125,51 +236,35 @@ void ProuterUveTable::ProuterUveEntry::Reset() { void ProuterUveTable::ProuterUveEntry::AddPhysicalInterface (const Interface *itf) { - UvePhyInterfaceAttrMap::iterator it = physical_interface_set_.find(itf-> - name()); + InterfaceSet::iterator it = physical_interface_set_.find(itf->name()); if (it == physical_interface_set_.end()) { - PhyInterfaceAttrEntryPtr uve(new PhyInterfaceAttrEntry(itf)); - physical_interface_set_.insert(UvePhyInterfaceAttrPair - (itf->name(), uve)); + physical_interface_set_.insert(itf->name()); + changed_ = true; } } void ProuterUveTable::ProuterUveEntry::DeletePhysicalInterface (const Interface *itf) { - UvePhyInterfaceAttrMap::iterator it = physical_interface_set_.find(itf-> - name()); + InterfaceSet::iterator it = physical_interface_set_.find(itf->name()); if (it != physical_interface_set_.end()) { physical_interface_set_.erase(it); + changed_ = true; } } void ProuterUveTable::ProuterUveEntry::AddLogicalInterface (const LogicalInterface *itf) { - LogicalInterfaceMap::iterator it = logical_interface_set_.find + LogicalInterfaceSet::iterator it = logical_interface_set_.find (itf->GetUuid()); if (it == logical_interface_set_.end()) { - LogicalInterfaceUveEntryPtr uve(new LogicalInterfaceUveEntry(itf)); - logical_interface_set_.insert(LogicalInterfacePair(itf->GetUuid(), - uve)); - } -} - -void ProuterUveTable::ProuterUveEntry::UpdateLogicalInterface - (const LogicalInterface *itf) { - LogicalInterfaceMap::iterator it = logical_interface_set_.find - (itf->GetUuid()); - if (it == logical_interface_set_.end()) { - return; - } else { - LogicalInterfaceUveEntry *entry = it->second.get(); - entry->Update(itf); + logical_interface_set_.insert(itf->GetUuid()); } } bool ProuterUveTable::ProuterUveEntry::DeleteLogicalInterface (const LogicalInterface *itf) { bool deleted = false; - LogicalInterfaceMap::iterator it = logical_interface_set_.find(itf-> + LogicalInterfaceSet::iterator it = logical_interface_set_.find(itf-> GetUuid()); if (it != logical_interface_set_.end()) { logical_interface_set_.erase(it); @@ -229,73 +324,51 @@ const PhysicalDevice *ProuterUveTable::InterfaceToProuter return pde; } -void ProuterUveTable::FillVmInterfaceList - (const boost::uuids::uuid &u, vector &vmi_list) const { - LogicalIntf2VmiListMap::const_iterator it = - uve_logical_interface_map_.find(u); - if (it == uve_logical_interface_map_.end()) { - return; - } - LogicalIntf2VmiListEntry *entry = it->second.get(); - ProuterUveTable::VmiSet::iterator vit = entry->vmi_list.begin(); - while (vit != entry->vmi_list.end()) { - vmi_list.push_back(to_string(*vit)); +void ProuterUveTable::LogicalInterfaceUveEntry::FillVmInterfaceList + (vector &vmi_list) const { + ProuterUveTable::InterfaceSet::iterator vit = vmi_list_.begin(); + while (vit != vmi_list_.end()) { + vmi_list.push_back((*vit)); ++vit; } return; } -void ProuterUveTable::FillLogicalInterfaceList - (const LogicalInterfaceMap &in, vector *out) - const { - LogicalInterfaceMap::const_iterator lit = in.begin(); - - while (lit != in.end()) { - UveLogicalInterfaceData lif_data; - vector vmi_list; - LogicalInterfaceUveEntry *lentry = lit->second.get(); - boost::uuids::uuid luuid = lit->first; - - ++lit; - lif_data.set_name(lentry->name_); - lif_data.set_uuid(to_string(luuid)); - if (lentry->vlan_ != kInvalidVlanId) { - lif_data.set_vlan(lentry->vlan_); - } - FillVmInterfaceList(luuid, vmi_list); - lif_data.set_vm_interface_list(vmi_list); - out->push_back(lif_data); +void ProuterUveTable::PhyInterfaceUveEntry::FillLogicalInterfaceList + (vector &list) const { + ProuterUveTable::LogicalInterfaceSet::iterator it = + logical_interface_set_.begin(); + while (it != logical_interface_set_.end()) { + list.push_back((to_string(*it))); + ++it; } + return; } void ProuterUveTable::FrameProuterMsg(ProuterUveEntry *entry, ProuterData *uve) const { - vector phy_if_list; - vector logical_list; + vector phy_if_list; + vector logical_list; /* We are using hostname instead of fq-name because Prouter UVE sent by * other modules to send topology information uses hostname and we want * both these information to be seen in same UVE */ uve->set_name(entry->name_); uve->set_uuid(to_string(entry->uuid_)); - UvePhyInterfaceAttrMap::iterator pit = entry->physical_interface_set_. - begin(); + InterfaceSet::iterator pit = entry->physical_interface_set_.begin(); while (pit != entry->physical_interface_set_.end()) { - UvePhysicalInterfaceData pif_data; - vector lif_list; - string pname = pit->first; - PhyInterfaceAttrEntry *pentry = pit->second.get(); + phy_if_list.push_back(*pit); ++pit; - PhyInterfaceUveEntry *ientry = NameToPhyInterfaceUveEntry(pname); - if (ientry != NULL) { - FillLogicalInterfaceList(ientry->logical_interface_set_, &lif_list); - } - pif_data.set_name(pname); - pif_data.set_uuid(to_string(pentry->uuid_)); - pif_data.set_logical_interface_list(lif_list); - phy_if_list.push_back(pif_data); } uve->set_physical_interface_list(phy_if_list); - FillLogicalInterfaceList(entry->logical_interface_set_, &logical_list); + + + LogicalInterfaceSet::const_iterator lit = entry->logical_interface_set_. + begin(); + + while (lit != entry->logical_interface_set_.end()) { + logical_list.push_back(to_string(*lit)); + ++lit; + } uve->set_logical_interface_list(logical_list); } @@ -371,48 +444,58 @@ void ProuterUveTable::DeleteHandler(const PhysicalDevice *p) { entry->Reset(); } -void ProuterUveTable::UpdateLogicalInterface(const Interface *pintf, - const LogicalInterface *intf) { - UvePhyInterfaceMap::iterator it = uve_phy_interface_map_.find(pintf-> - name()); - PhyInterfaceUveEntry *ientry = NULL; - if (it == uve_phy_interface_map_.end()) { - return; - } else { - ientry = it->second.get(); +void ProuterUveTable::MarkDeletedLogical(const LogicalInterface *itf) { + LogicalInterfaceMap::iterator it = uve_logical_interface_map_.find(itf-> + GetUuid()); + if (it != uve_logical_interface_map_.end()) { + LogicalInterfaceUveEntry *entry = it->second.get(); + entry->deleted_ = true; } - LogicalInterfaceMap::iterator lit = ientry->logical_interface_set_. - find(intf->GetUuid()); - if (lit == ientry->logical_interface_set_.end()) { +} + +void ProuterUveTable::AddUpdateLogicalInterface(const LogicalInterface *itf) { + LogicalInterfaceMap::iterator it = uve_logical_interface_map_.find(itf-> + GetUuid()); + if (it == uve_logical_interface_map_.end()) { + LogicalInterfaceUveEntryPtr uve(new LogicalInterfaceUveEntry(itf)); + uve_logical_interface_map_.insert(LogicalInterfacePair(itf->GetUuid(), + uve)); return; } else { - LogicalInterfaceUveEntry *lentry = lit->second.get(); - lentry->Update(intf); + LogicalInterfaceUveEntry *entry = it->second.get(); + entry->Update(itf); + } +} + +void ProuterUveTable::MarkDeletedPhysical(const Interface *pintf) { + UvePhyInterfaceMap::iterator it = uve_phy_interface_map_.find(pintf-> + name()); + PhyInterfaceUveEntry *entry = NULL; + if (it != uve_phy_interface_map_.end()) { + entry = it->second.get(); + entry->deleted_ = true; } - SendProuterMsgFromPhyInterface(pintf); } -void ProuterUveTable::AddLogicalInterface(const Interface *pintf, - const LogicalInterface *intf) { +void ProuterUveTable::AddLogicalToPhysical(const Interface *pintf, + const LogicalInterface *intf) { UvePhyInterfaceMap::iterator it = uve_phy_interface_map_.find(pintf-> name()); PhyInterfaceUveEntry *ientry = NULL; if (it == uve_phy_interface_map_.end()) { - PhyInterfaceUveEntryPtr entry(new PhyInterfaceUveEntry()); + PhyInterfaceUveEntryPtr entry(new PhyInterfaceUveEntry(pintf)); uve_phy_interface_map_.insert(UvePhyInterfacePair(pintf->name(), entry)); ientry = entry.get(); } else { ientry = it->second.get(); } - LogicalInterfaceMap::iterator lit = ientry->logical_interface_set_. + LogicalInterfaceSet::iterator lit = ientry->logical_interface_set_. find(intf->GetUuid()); if (lit == ientry->logical_interface_set_.end()) { - LogicalInterfaceUveEntryPtr uve(new LogicalInterfaceUveEntry(intf)); - ientry->logical_interface_set_.insert(LogicalInterfacePair - (intf->GetUuid(), uve)); + ientry->logical_interface_set_.insert(intf->GetUuid()); + ientry->changed_ = true; } - SendProuterMsgFromPhyInterface(pintf); } void ProuterUveTable::AddProuterLogicalInterface @@ -427,36 +510,17 @@ void ProuterUveTable::AddProuterLogicalInterface entry->changed_ = true; } -void ProuterUveTable::UpdateProuterLogicalInterface - (const PhysicalDevice *p, const LogicalInterface *intf) { - UveProuterMap::iterator it = uve_prouter_map_.find(p->uuid()); - if (it == uve_prouter_map_.end()) { - return; - } - - ProuterUveEntry* entry = it->second.get(); - entry->UpdateLogicalInterface(intf); - entry->changed_ = true; -} - -void ProuterUveTable::DeleteLogicalInterface(const string &name, +void ProuterUveTable::DeleteLogicalFromPhysical(const string &name, const LogicalInterface *intf) { PhyInterfaceUveEntry *entry = NameToPhyInterfaceUveEntry(name); if (entry != NULL) { - LogicalInterfaceMap::iterator it = entry->logical_interface_set_. + LogicalInterfaceSet::iterator it = entry->logical_interface_set_. find(intf->GetUuid()); if (it != entry->logical_interface_set_.end()) { entry->logical_interface_set_.erase(it); + entry->changed_ = true; } } - const Interface *pintf = NameToInterface(name); - if (pintf) { - /* If Physical interface is not found (because it is marked for delete), - * then required UVEs will be sent as part of physical interface - * delete notification - */ - SendProuterMsgFromPhyInterface(pintf); - } } void ProuterUveTable::DeleteProuterLogicalInterface @@ -500,8 +564,8 @@ void ProuterUveTable::PhysicalDeviceNotify(DBTablePartBase *partition, } } -void ProuterUveTable::DisassociatePhysicalInterface(const Interface *intf, - const boost::uuids::uuid &u) { +void ProuterUveTable::DeletePhysicalFromProuter(const Interface *intf, + const boost::uuids::uuid &u) { ProuterUveEntry *entry = PDEntryToProuterUveEntry(u); if (!entry) { return; @@ -510,8 +574,22 @@ void ProuterUveTable::DisassociatePhysicalInterface(const Interface *intf, entry->changed_ = true; } +void ProuterUveTable::AddUpdatePhysicalInterface(const Interface *intf) { + UvePhyInterfaceMap::iterator it = uve_phy_interface_map_.find(intf->name()); + if (it == uve_phy_interface_map_.end()) { + PhyInterfaceUveEntryPtr uve(new PhyInterfaceUveEntry(intf)); + uve_phy_interface_map_.insert(UvePhyInterfacePair(intf->name(), uve)); + return; + } + PhyInterfaceUveEntry *entry = it->second.get(); + entry->Update(intf); +} + void ProuterUveTable::PhysicalInterfaceHandler(const Interface *intf, const boost::uuids::uuid &u) { + if (intf->IsDeleted()) { + MarkDeletedPhysical(intf); + } /* Ignore notifications for PhysicalInterface if it has no PhysicalDevice */ if (u == nil_uuid()) { @@ -524,62 +602,47 @@ void ProuterUveTable::PhysicalInterfaceHandler(const Interface *intf, return; } if (intf->IsDeleted()) { - UvePhyInterfaceMap::iterator pit = uve_phy_interface_map_.find(intf-> - name()); entry->DeletePhysicalInterface(intf); - if (pit != uve_phy_interface_map_.end()) { - uve_phy_interface_map_.erase(pit); - } } else { entry->AddPhysicalInterface(intf); } - entry->changed_ = true; } -void ProuterUveTable::MarkChanged(const boost::uuids::uuid &li) { - VlanLogicalInterfaceKey key(li, ""); - LogicalInterface *intf = static_cast - (agent_->interface_table()->FindActiveEntry(&key)); - if (intf == NULL) { - return; - } - const Interface *physical_interface = intf->physical_interface(); - const PhysicalDevice *pde = intf->physical_device(); - if (physical_interface) { - pde = InterfaceToProuter(physical_interface); - } - MarkPhysicalDeviceChanged(pde); -} - -void ProuterUveTable::LogicalIntf2VmiListMapAdd(const VmInterface *vmi) { - LogicalIntf2VmiListEntry *entry; +void ProuterUveTable::VMInterfaceAdd(const VmInterface *vmi) { + LogicalInterfaceUveEntry *entry; const boost::uuids::uuid li = vmi->logical_interface(); - LogicalIntf2VmiListMap::iterator it = uve_logical_interface_map_.find(li); + LogicalInterfaceMap::iterator it = uve_logical_interface_map_.find(li); if (it != uve_logical_interface_map_.end()) { entry = it->second.get(); } else { - LogicalIntf2VmiListEntryPtr uve(new LogicalIntf2VmiListEntry()); - uve_logical_interface_map_.insert(LogicalIntf2VmiListPair(li, uve)); + LogicalInterface *intf; + VlanLogicalInterfaceKey key(li, ""); + intf = static_cast + (agent_->interface_table()->FindActiveEntry(&key)); + if (!intf) { + return; + } + LogicalInterfaceUveEntryPtr uve(new LogicalInterfaceUveEntry(intf)); + uve_logical_interface_map_.insert(LogicalInterfacePair(li, uve)); entry = uve.get(); } - ProuterUveTable::VmiSet::iterator vit = entry->vmi_list.find - (vmi->GetUuid()); - if (vit == entry->vmi_list.end()) { - entry->vmi_list.insert(vmi->GetUuid()); - MarkChanged(li); + InterfaceSet::iterator vit = entry->vmi_list_.find(vmi->cfg_name()); + if (vit == entry->vmi_list_.end()) { + entry->vmi_list_.insert(vmi->cfg_name()); + entry->changed_ = true; } } -void ProuterUveTable::LogicalIntf2VmiListMapRemove(const boost::uuids::uuid &li, +void ProuterUveTable::VMInterfaceRemove(const boost::uuids::uuid &li, const VmInterface *vmi) { - LogicalIntf2VmiListMap::iterator it = uve_logical_interface_map_.find(li); + LogicalInterfaceMap::iterator it = uve_logical_interface_map_.find(li); if (it != uve_logical_interface_map_.end()) { - LogicalIntf2VmiListEntry *entry = it->second.get(); - ProuterUveTable::VmiSet::iterator vit = entry->vmi_list.find - (vmi->GetUuid()); - if (vit != entry->vmi_list.end()) { - entry->vmi_list.erase(vit); - MarkChanged(li); + LogicalInterfaceUveEntry *entry = it->second.get(); + ProuterUveTable::InterfaceSet::iterator vit = entry->vmi_list_.find + (vmi->cfg_name()); + if (vit != entry->vmi_list_.end()) { + entry->vmi_list_.erase(vit); + entry->changed_ = true; } } } @@ -591,7 +654,7 @@ void ProuterUveTable::VmInterfaceHandler(DBTablePartBase *partition, const VmInterface *intf = static_cast(e); if (e->IsDeleted()) { if (state) { - LogicalIntf2VmiListMapRemove(state->logical_interface_, intf); + VMInterfaceRemove(state->logical_interface_, intf); e->ClearState(partition->parent(), interface_listener_id_); delete state; return; @@ -603,13 +666,13 @@ void ProuterUveTable::VmInterfaceHandler(DBTablePartBase *partition, } if (state->logical_interface_ != intf->logical_interface()) { if (state->logical_interface_ != nil_uuid()) { - LogicalIntf2VmiListMapRemove(state->logical_interface_, intf); - } - if (intf->logical_interface() != nil_uuid()) { - LogicalIntf2VmiListMapAdd(intf); + VMInterfaceRemove(state->logical_interface_, intf); } state->logical_interface_ = intf->logical_interface(); } + if (intf->logical_interface() != nil_uuid()) { + VMInterfaceAdd(intf); + } } void ProuterUveTable::InterfaceNotify(DBTablePartBase *partition, @@ -648,12 +711,14 @@ void ProuterUveTable::InterfaceNotify(DBTablePartBase *partition, PhysicalInterfaceHandler(rpintf, state->physical_device_); } else if (lintf) { if (!state->physical_interface_.empty()) { - DeleteLogicalInterface(state->physical_interface_, lintf); + DeleteLogicalFromPhysical(state->physical_interface_, + lintf); } if (state->physical_device_ != nil_uuid()) { DeleteProuterLogicalInterface(state->physical_device_, lintf); } + MarkDeletedLogical(lintf); } e->ClearState(partition->parent(), interface_listener_id_); delete state; @@ -672,16 +737,15 @@ void ProuterUveTable::InterfaceNotify(DBTablePartBase *partition, pname = physical_interface->name(); } if (intf->type() == Interface::LOGICAL) { - bool uve_send = true; if (state->physical_interface_ != pname) { if (!state->physical_interface_.empty()) { - DeleteLogicalInterface(state->physical_interface_, lintf); + DeleteLogicalFromPhysical(state->physical_interface_, + lintf); } if (physical_interface) { - AddLogicalInterface(physical_interface, lintf); + AddLogicalToPhysical(physical_interface, lintf); } state->physical_interface_ = pname; - uve_send = false; } if (state->physical_device_ != pde_uuid) { if (state->physical_device_ != nil_uuid()) { @@ -692,22 +756,12 @@ void ProuterUveTable::InterfaceNotify(DBTablePartBase *partition, AddProuterLogicalInterface(pde, lintf); } state->physical_device_ = pde_uuid; - uve_send = false; - } - if (uve_send) { - /* There is change in logical interface. Update our - logical interface data and send UVE */ - if (physical_interface) { - UpdateLogicalInterface(physical_interface, lintf); - } else if (pde) { - UpdateProuterLogicalInterface(pde, lintf); - } } + AddUpdateLogicalInterface(lintf); } else { if (state->physical_device_ != pde_uuid) { if (state->physical_device_ != nil_uuid()) { - DisassociatePhysicalInterface(intf, - state->physical_device_); + DeletePhysicalFromProuter(intf, state->physical_device_); } if (pde) { if (pintf) { @@ -718,6 +772,7 @@ void ProuterUveTable::InterfaceNotify(DBTablePartBase *partition, } state->physical_device_ = pde_uuid; } + AddUpdatePhysicalInterface(intf); } } } @@ -739,3 +794,56 @@ void ProuterUveTable::Shutdown(void) { if (interface_listener_id_ != DBTableBase::kInvalidId) agent_->interface_table()->Unregister(interface_listener_id_); } + +void ProuterUveTable::SendLogicalInterfaceDeleteMsg(const string &config_name) { + UveLogicalInterfaceAgent uve; + uve.set_name(config_name); + uve.set_deleted(true); + DispatchLogicalInterfaceMsg(uve); +} + +void ProuterUveTable::SendLogicalInterfaceMsg(const boost::uuids::uuid &u, + LogicalInterfaceUveEntry *entry) { + UveLogicalInterfaceAgent uve; + vector list; + + uve.set_name(to_string(u)); + uve.set_config_name(entry->name_); + uve.set_vlan(entry->vlan_); + + entry->FillVmInterfaceList(list); + uve.set_vm_interface_list(list); + + DispatchLogicalInterfaceMsg(uve); +} + +void ProuterUveTable::DispatchLogicalInterfaceMsg + (const UveLogicalInterfaceAgent &uve) { + UveLogicalInterfaceAgentTrace::Send(uve); +} + +void ProuterUveTable::SendPhysicalInterfaceDeleteMsg(const string &cfg_name) { + UvePhysicalInterfaceAgent uve; + uve.set_name(cfg_name); + uve.set_deleted(true); + DispatchPhysicalInterfaceMsg(uve); +} + +void ProuterUveTable::SendPhysicalInterfaceMsg(const string &cfg_name, + PhyInterfaceUveEntry *entry) { + UvePhysicalInterfaceAgent uve; + vector list; + + uve.set_name(cfg_name); + uve.set_uuid(to_string(entry->uuid_)); + + entry->FillLogicalInterfaceList(list); + uve.set_logical_interface_list(list); + + DispatchPhysicalInterfaceMsg(uve); +} + +void ProuterUveTable::DispatchPhysicalInterfaceMsg + (const UvePhysicalInterfaceAgent &uve) { + UvePhysicalInterfaceAgentTrace::Send(uve); +} diff --git a/src/vnsw/agent/uve/prouter_uve_table.h b/src/vnsw/agent/uve/prouter_uve_table.h index 1fff333eb03..264dac72db2 100644 --- a/src/vnsw/agent/uve/prouter_uve_table.h +++ b/src/vnsw/agent/uve/prouter_uve_table.h @@ -25,23 +25,18 @@ // Prouter UVEs class ProuterUveTable { public: - struct PhyInterfaceAttrEntry { - boost::uuids::uuid uuid_; - explicit PhyInterfaceAttrEntry(const Interface *itf); - }; - typedef boost::shared_ptr PhyInterfaceAttrEntryPtr; - typedef std::map - UvePhyInterfaceAttrMap; - typedef std::pair - UvePhyInterfaceAttrPair; - + typedef std::set InterfaceSet; struct LogicalInterfaceUveEntry { const std::string name_; uint16_t vlan_; - boost::uuids::uuid vmi_uuid_; + InterfaceSet vmi_list_; + bool changed_; + bool deleted_; + bool renewed_; explicit LogicalInterfaceUveEntry(const LogicalInterface *li); void Update(const LogicalInterface *li); + void FillVmInterfaceList(std::vector &vmi_list) const; }; typedef boost::shared_ptr LogicalInterfaceUveEntryPtr; @@ -67,20 +62,20 @@ class ProuterUveTable { } }; + typedef std::set LogicalInterfaceSet; struct ProuterUveEntry { explicit ProuterUveEntry(const PhysicalDevice *p); ~ProuterUveEntry(); void AddPhysicalInterface(const Interface *itf); void DeletePhysicalInterface(const Interface *itf); void AddLogicalInterface(const LogicalInterface *itf); - void UpdateLogicalInterface(const LogicalInterface *itf); bool DeleteLogicalInterface(const LogicalInterface *itf); void Reset(); std::string name_; boost::uuids::uuid uuid_; - UvePhyInterfaceAttrMap physical_interface_set_; - LogicalInterfaceMap logical_interface_set_; + InterfaceSet physical_interface_set_; + LogicalInterfaceSet logical_interface_set_; bool changed_; bool deleted_; bool renewed_; @@ -90,7 +85,15 @@ class ProuterUveTable { typedef std::pair UveProuterPair; struct PhyInterfaceUveEntry { - LogicalInterfaceMap logical_interface_set_; + explicit PhyInterfaceUveEntry(const Interface *pintf); + void Update(const Interface *pintf); + void FillLogicalInterfaceList(std::vector &list) const; + + boost::uuids::uuid uuid_; + LogicalInterfaceSet logical_interface_set_; + bool changed_; + bool deleted_; + bool renewed_; }; typedef boost::shared_ptr PhyInterfaceUveEntryPtr; typedef std::map @@ -98,29 +101,23 @@ class ProuterUveTable { typedef std::pair UvePhyInterfacePair; - typedef std::set VmiSet; - struct LogicalIntf2VmiListEntry { - VmiSet vmi_list; - }; - typedef boost::shared_ptr - LogicalIntf2VmiListEntryPtr; - typedef std::map - LogicalIntf2VmiListMap; - typedef std::pair - LogicalIntf2VmiListPair; - static const uint16_t kInvalidVlanId = 0xFFFF; explicit ProuterUveTable(Agent *agent, uint32_t default_intvl); virtual ~ProuterUveTable(); void RegisterDBClients(); void Shutdown(void); virtual void DispatchProuterMsg(const ProuterData &uve); + virtual void DispatchLogicalInterfaceMsg(const UveLogicalInterfaceAgent &u); + virtual void DispatchPhysicalInterfaceMsg + (const UvePhysicalInterfaceAgent &uve); bool TimerExpiry(); + bool PITimerExpiry(); + bool LITimerExpiry(); protected: UveProuterMap uve_prouter_map_; UvePhyInterfaceMap uve_phy_interface_map_; - LogicalIntf2VmiListMap uve_logical_interface_map_; + LogicalInterfaceMap uve_logical_interface_map_; private: ProuterUveEntryPtr Allocate(const PhysicalDevice *pr); @@ -128,48 +125,57 @@ class ProuterUveTable { PhyInterfaceUveEntry *NameToPhyInterfaceUveEntry(const std::string &name) const; const Interface *NameToInterface(const std::string &name) const; - void FillLogicalInterfaceList(const LogicalInterfaceMap &in, - std::vector *out) const; void FrameProuterMsg(ProuterUveEntry *entry, ProuterData *uve) const; void SendProuterDeleteMsg(ProuterUveEntry *e); bool SendProuterMsg(ProuterUveEntry *entry); void SendProuterMsgFromPhyInterface(const Interface *pi); void PhysicalDeviceNotify(DBTablePartBase *partition, DBEntryBase *e); void PhysicalInterfaceHandler(const Interface *i, const boost::uuids::uuid &u); - void DisassociatePhysicalInterface(const Interface *i, - const boost::uuids::uuid &u); + void MarkDeletedPhysical(const Interface *pintf); + void DeletePhysicalFromProuter(const Interface *i, + const boost::uuids::uuid &u); void InterfaceNotify(DBTablePartBase *partition, DBEntryBase *e); ProuterUveEntry* AddHandler(const PhysicalDevice *p); void DeleteHandler(const PhysicalDevice *p); - void AddLogicalInterface(const Interface *p, const LogicalInterface *i); - void UpdateLogicalInterface(const Interface *p, const LogicalInterface *i); - void DeleteLogicalInterface(const std::string &name, - const LogicalInterface *i); + void AddLogicalToPhysical(const Interface *p, const LogicalInterface *i); + void AddUpdateLogicalInterface(const LogicalInterface *i); + void MarkDeletedLogical(const LogicalInterface *pintf); + void DeleteLogicalFromPhysical(const std::string &name, + const LogicalInterface *i); void AddProuterLogicalInterface(const PhysicalDevice *p, const LogicalInterface *intf); - void UpdateProuterLogicalInterface(const PhysicalDevice *p, - const LogicalInterface *intf); void DeleteProuterLogicalInterface(const boost::uuids::uuid &u, const LogicalInterface *intf); const PhysicalDevice *InterfaceToProuter(const Interface *intf); void SendProuterVrouterAssociation(); - void set_expiry_time(int time); + void set_expiry_time(int time, Timer *timer); + void TimerCleanup(Timer *timer); void VmInterfaceHandler(DBTablePartBase *partition, DBEntryBase *e); - void LogicalIntf2VmiListMapAdd(const VmInterface *vmi); - void LogicalIntf2VmiListMapRemove(const boost::uuids::uuid &li, + void VMInterfaceAdd(const VmInterface *vmi); + void VMInterfaceRemove(const boost::uuids::uuid &li, const VmInterface *vmi); - void FillVmInterfaceList(const boost::uuids::uuid &u, - std::vector &vmi_list) const; void MarkPhysicalDeviceChanged(const PhysicalDevice *pde); void MarkChanged(const boost::uuids::uuid &li); + void AddUpdatePhysicalInterface(const Interface *intf); + void SendPhysicalInterfaceDeleteMsg(const std::string &cfg_name); + void SendPhysicalInterfaceMsg(const std::string &name, + PhyInterfaceUveEntry *entry); + void SendLogicalInterfaceDeleteMsg(const std::string &config_name); + void SendLogicalInterfaceMsg(const boost::uuids::uuid &u, + LogicalInterfaceUveEntry *entry); Agent *agent_; DBTableBase::ListenerId physical_device_listener_id_; DBTableBase::ListenerId interface_listener_id_; - // Last visited VmEntry by timer - boost::uuids::uuid timer_last_visited_; - Timer *timer_; - int expiry_time_; + // Last visited Prouter by timer + boost::uuids::uuid pr_timer_last_visited_; + Timer *pr_timer_; + + std::string pi_timer_last_visited_; + Timer *pi_timer_; + + boost::uuids::uuid li_timer_last_visited_; + Timer *li_timer_; DISALLOW_COPY_AND_ASSIGN(ProuterUveTable); }; diff --git a/src/vnsw/agent/uve/test/SConscript b/src/vnsw/agent/uve/test/SConscript index 73dd874eed8..0a07ff02aed 100644 --- a/src/vnsw/agent/uve/test/SConscript +++ b/src/vnsw/agent/uve/test/SConscript @@ -25,6 +25,8 @@ test_vrouter_uve = AgentEnv.MakeTestCmd(env, 'test_vrouter_uve', uve_test_suite) test_prouter_uve = AgentEnv.MakeTestCmd(env, 'test_prouter_uve', uve_test_suite) +test_interface_uve = AgentEnv.MakeTestCmd(env, 'test_interface_uve', + uve_test_suite) flaky_test = env.TestSuite('agent-flaky-test', uve_flaky_test_suite) env.Alias('controller/src/vnsw/agent/uve:flaky_test', flaky_test) diff --git a/src/vnsw/agent/uve/test/agent_uve_test.cc b/src/vnsw/agent/uve/test/agent_uve_test.cc index e8e4f9d9067..6c2f5da5886 100644 --- a/src/vnsw/agent/uve/test/agent_uve_test.cc +++ b/src/vnsw/agent/uve/test/agent_uve_test.cc @@ -11,6 +11,7 @@ #include #include #include +#include #include AgentUveBaseTest::AgentUveBaseTest(Agent *agent, uint64_t intvl, @@ -26,12 +27,16 @@ AgentUveBaseTest::AgentUveBaseTest(Agent *agent, uint64_t intvl, if (vrouter_uve_entry_) { vrouter_uve_entry_->Shutdown(); } + if (interface_uve_table_) { + interface_uve_table_->Shutdown(); + } if (prouter_uve_table_) { prouter_uve_table_->Shutdown(); } vn_uve_table_.reset(new VnUveTableTest(agent, default_intvl)); vm_uve_table_.reset(new VmUveTableTest(agent, default_intvl)); vrouter_uve_entry_.reset(new VrouterUveEntryTest(agent)); + interface_uve_table_.reset(new InterfaceUveTableTest(agent, default_intvl)); prouter_uve_table_.reset(new ProuterUveTableTest(agent, default_intvl)); } diff --git a/src/vnsw/agent/uve/test/interface_uve_table_test.cc b/src/vnsw/agent/uve/test/interface_uve_table_test.cc new file mode 100644 index 00000000000..d5310b1c19a --- /dev/null +++ b/src/vnsw/agent/uve/test/interface_uve_table_test.cc @@ -0,0 +1,73 @@ +/* + * Copyright (c) 2015 Juniper Networks, Inc. All rights reserved. + */ + +#include +#include +#include +#include +#include +#include + + +InterfaceUveTableTest::InterfaceUveTableTest(Agent *agent, uint32_t intvl) : + InterfaceUveStatsTable(agent, intvl) { +} + +void InterfaceUveTableTest::DispatchInterfaceMsg(const UveVMInterfaceAgent &u) { + send_count_++; + if (u.get_deleted()) { + delete_count_++; + } + uve_ = u; +} + +void InterfaceUveTableTest::ClearCount() { + send_count_ = 0; + delete_count_ = 0; +} + +L4PortBitmap* InterfaceUveTableTest::GetVmIntfPortBitmap + (const VmInterface* itf) { + InterfaceMap::iterator it = interface_tree_.find(itf->cfg_name()); + if (it != interface_tree_.end()) { + UveInterfaceEntry *entry = it->second.get(); + return &(entry->port_bitmap_); + } + return NULL; +} + +UveVMInterfaceAgent* InterfaceUveTableTest::InterfaceUveObject + (const VmInterface *itf) { + InterfaceMap::iterator it = interface_tree_.find(itf->cfg_name()); + if (it != interface_tree_.end()) { + UveInterfaceEntry *entry = it->second.get(); + return &(entry->uve_info_); + } + return NULL; +} + +uint32_t InterfaceUveTableTest::GetVmIntfFipCount(const VmInterface* itf) { + InterfaceMap::iterator it = interface_tree_.find(itf->cfg_name()); + if (it != interface_tree_.end()) { + UveInterfaceEntry *entry = it->second.get(); + return entry->fip_tree_.size(); + } + return 0; +} + +const InterfaceUveTable::FloatingIp *InterfaceUveTableTest::GetVmIntfFip + (const VmInterface* itf, const string &fip, const string &vn) { + InterfaceMap::iterator it = interface_tree_.find(itf->cfg_name()); + if (it != interface_tree_.end()) { + UveInterfaceEntry *entry = it->second.get(); + boost::system::error_code ec; + Ip4Address ip = Ip4Address::from_string(fip, ec); + FloatingIpPtr key(new FloatingIp(ip, vn)); + FloatingIpSet::iterator fip_it = entry->fip_tree_.find(key); + if (fip_it != entry->fip_tree_.end()) { + return (*fip_it).get(); + } + } + return NULL; +} diff --git a/src/vnsw/agent/uve/test/interface_uve_table_test.h b/src/vnsw/agent/uve/test/interface_uve_table_test.h new file mode 100644 index 00000000000..768cfb47d23 --- /dev/null +++ b/src/vnsw/agent/uve/test/interface_uve_table_test.h @@ -0,0 +1,31 @@ +/* + * Copyright (c) 2015 Juniper Networks, Inc. All rights reserved. + */ + +#ifndef vnsw_agent_interface_uve_table_test_h +#define vnsw_agent_interface_uve_table_test_h + +#include + +class InterfaceUveTableTest : public InterfaceUveStatsTable { +public: + InterfaceUveTableTest(Agent *agent, uint32_t default_intvl); + virtual void DispatchInterfaceMsg(const UveVMInterfaceAgent &uve); + uint32_t send_count() const { return send_count_; } + uint32_t delete_count() const { return delete_count_; } + uint32_t InterfaceUveCount() const { return interface_tree_.size(); } + void ClearCount(); + L4PortBitmap* GetVmIntfPortBitmap(const VmInterface* intf); + UveVMInterfaceAgent* InterfaceUveObject(const VmInterface *itf); + uint32_t GetVmIntfFipCount(const VmInterface* intf); + const InterfaceUveTable::FloatingIp *GetVmIntfFip(const VmInterface* intf, + const string &fip, const string &vn); + const UveVMInterfaceAgent &last_sent_uve() const { return uve_; } +private: + uint32_t send_count_; + uint32_t delete_count_; + UveVMInterfaceAgent uve_; + DISALLOW_COPY_AND_ASSIGN(InterfaceUveTableTest); +}; + +#endif // vnsw_agent_interface_uve_table_test_h diff --git a/src/vnsw/agent/uve/test/prouter_uve_table_test.cc b/src/vnsw/agent/uve/test/prouter_uve_table_test.cc index 967fd866042..b0bec8f884a 100644 --- a/src/vnsw/agent/uve/test/prouter_uve_table_test.cc +++ b/src/vnsw/agent/uve/test/prouter_uve_table_test.cc @@ -22,5 +22,43 @@ void ProuterUveTableTest::DispatchProuterMsg(const ProuterData &uve) { void ProuterUveTableTest::ClearCount() { send_count_ = 0; delete_count_ = 0; + pi_send_count_ = 0; + pi_delete_count_ = 0; + li_send_count_ = 0; + li_delete_count_ = 0; } +void ProuterUveTableTest::DispatchPhysicalInterfaceMsg + (const UvePhysicalInterfaceAgent &uve) { + pi_send_count_++; + if (uve.get_deleted()) { + pi_delete_count_++; + } +} + +void ProuterUveTableTest::DispatchLogicalInterfaceMsg + (const UveLogicalInterfaceAgent &uve) { + li_send_count_++; + if (uve.get_deleted()) { + li_delete_count_++; + } + li_uve_ = uve; +} + +uint32_t ProuterUveTableTest::PhysicalIntfListCount() const { + return uve_phy_interface_map_.size(); +} + +uint32_t ProuterUveTableTest::LogicalIntfListCount() const { + return uve_logical_interface_map_.size(); +} + +uint32_t ProuterUveTableTest::VMIListCount(const LogicalInterface *itf) const { + LogicalInterfaceMap::const_iterator it = uve_logical_interface_map_.find + (itf->GetUuid()); + if (it != uve_logical_interface_map_.end()) { + LogicalInterfaceUveEntry *entry = it->second.get(); + return entry->vmi_list_.size(); + } + return 0; +} diff --git a/src/vnsw/agent/uve/test/prouter_uve_table_test.h b/src/vnsw/agent/uve/test/prouter_uve_table_test.h index 60bf1f18efb..108c83188a1 100644 --- a/src/vnsw/agent/uve/test/prouter_uve_table_test.h +++ b/src/vnsw/agent/uve/test/prouter_uve_table_test.h @@ -14,16 +14,32 @@ class ProuterUveTableTest : public ProuterUveTable { void DispatchProuterMsg(const ProuterData &uve); uint32_t send_count() const { return send_count_; } uint32_t delete_count() const { return delete_count_; } + uint32_t pi_send_count() const { return pi_send_count_; } + uint32_t pi_delete_count() const { return pi_delete_count_; } + uint32_t li_send_count() const { return li_send_count_; } + uint32_t li_delete_count() const { return li_delete_count_; } + uint32_t PhysicalIntfListCount() const; + uint32_t LogicalIntfListCount() const; + uint32_t VMIListCount(const LogicalInterface *itf) const; + void ClearCount(); const ProuterData &last_sent_uve() const { return uve_; } + const UveLogicalInterfaceAgent &last_sent_li_uve() const { return li_uve_; } uint32_t ProuterUveCount() const { return uve_prouter_map_.size(); } uint32_t PhysicalInterfaceCount() const { return uve_phy_interface_map_.size(); } + void DispatchPhysicalInterfaceMsg(const UvePhysicalInterfaceAgent &uve); + void DispatchLogicalInterfaceMsg(const UveLogicalInterfaceAgent &uve); private: uint32_t send_count_; uint32_t delete_count_; + uint32_t pi_send_count_; + uint32_t pi_delete_count_; + uint32_t li_send_count_; + uint32_t li_delete_count_; ProuterData uve_; + UveLogicalInterfaceAgent li_uve_; }; #endif // vnsw_agent_prouter_uve_entry_test_h diff --git a/src/vnsw/agent/uve/test/test_interface_uve.cc b/src/vnsw/agent/uve/test/test_interface_uve.cc new file mode 100644 index 00000000000..7b61b29982d --- /dev/null +++ b/src/vnsw/agent/uve/test/test_interface_uve.cc @@ -0,0 +1,935 @@ +/* + * Copyright (c) 2015 Juniper Networks, Inc. All rights reserved. + */ + +#include "base/os.h" +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include "testing/gunit.h" +#include "test/test_cmn_util.h" +#include "pkt/test/test_flow_util.h" +#include "pkt/test/flow_table_test.h" +#include "ksync/ksync_sock_user.h" +#include "vr_types.h" +#include +#include "uve/test/test_uve_util.h" + +using namespace std; + +#define vm1_ip "11.1.1.1" +#define vm2_ip "11.1.1.2" +#define vm4_ip "14.1.1.1" +#define vm1_fip "14.1.1.100" + +#define vm_a_ip "15.0.0.1" +#define vm_b_ip "16.0.0.1" +#define vm_c_ip "17.0.0.1" +#define vm_c_fip1 "17.0.0.10" +#define vm_c_fip2 "17.0.0.11" + + +#define remote_vm_fip "14.1.1.101" +#define remote_router_ip "10.1.1.2" + +struct PortInfo input[] = { + {"flow0", 6, vm1_ip, "00:00:00:01:01:01", 5, 1}, + {"flow1", 7, vm2_ip, "00:00:00:01:01:02", 5, 2}, +}; + +struct PortInfo input2[] = { + {"flow2", 8, vm4_ip, "00:00:00:01:01:06", 4, 3}, +}; + +struct PortInfo fip_input1[] = { + {"flowa", 3, vm_a_ip, "00:00:00:02:01:01", 6, 6}, + {"flowb", 4, vm_b_ip, "00:00:00:02:01:02", 7, 7}, +}; + +struct PortInfo fip_input2[] = { + {"flowc", 5, vm_c_ip, "00:00:00:02:01:03", 8, 8}, +}; + +VmInterface *flow0; +VmInterface *flow1; +VmInterface *flow2; + +VmInterface *flowa; +VmInterface *flowb; +VmInterface *flowc; + +void RouterIdDepInit(Agent *agent) { +} + +class InterfaceUveTest : public ::testing::Test { +public: + InterfaceUveTest() : util_(), peer_(NULL), agent_(Agent::GetInstance()) { + } + void FlowSetUp() { + EXPECT_EQ(0U, Agent::GetInstance()->pkt()->flow_table()->Size()); + client->Reset(); + CreateVmportEnv(input, 2, 1); + client->WaitForIdle(5); + CreateVmportFIpEnv(input2, 1, 0); + client->WaitForIdle(5); + + EXPECT_TRUE(VmPortActive(input, 0)); + EXPECT_TRUE(VmPortActive(input, 1)); + EXPECT_TRUE(VmPortPolicyEnable(input, 0)); + EXPECT_TRUE(VmPortPolicyEnable(input, 1)); + EXPECT_TRUE(VmPortActive(input2, 0)); + + flow0 = VmInterfaceGet(input[0].intf_id); + assert(flow0); + flow1 = VmInterfaceGet(input[1].intf_id); + assert(flow1); + flow2 = VmInterfaceGet(input2[0].intf_id); + assert(flow2); + + // Configure Floating-IP + AddFloatingIpPool("fip-pool1", 1); + AddFloatingIp("fip1", 1, vm1_fip); + AddLink("floating-ip", "fip1", "floating-ip-pool", "fip-pool1"); + AddLink("floating-ip-pool", "fip-pool1", "virtual-network", "default-project:vn4"); + AddLink("virtual-machine-interface", "flow0", "floating-ip", "fip1"); + client->WaitForIdle(); + EXPECT_TRUE(flow0->HasFloatingIp()); + } + + void FlowTearDown() { + FlushFlowTable(); + client->Reset(); + + DeleteVmportEnv(input, 2, true, 1); + client->WaitForIdle(3); + client->PortDelNotifyWait(2); + EXPECT_FALSE(VmPortFind(input, 0)); + EXPECT_FALSE(VmPortFind(input, 1)); + + client->Reset(); + DeleteVmportFIpEnv(input2, 1, true); + client->WaitForIdle(3); + client->PortDelNotifyWait(1); + EXPECT_FALSE(VmPortFind(input2, 0)); + } + + void FlowTearDown2() { + FlushFlowTable(); + client->Reset(); + + DeleteVmportEnv(fip_input1, 2, true, 1); + client->WaitForIdle(3); + client->PortDelNotifyWait(2); + EXPECT_FALSE(VmPortFind(fip_input1, 0)); + EXPECT_FALSE(VmPortFind(fip_input1, 1)); + + client->Reset(); + DeleteVmportFIpEnv(fip_input2, 1, true); + client->WaitForIdle(3); + client->PortDelNotifyWait(1); + EXPECT_FALSE(VmPortFind(fip_input2, 0)); + } + + void FlowSetUp2() { + EXPECT_EQ(0U, Agent::GetInstance()->pkt()->flow_table()->Size()); + client->Reset(); + CreateVmportEnv(fip_input1, 2, 1); + client->WaitForIdle(5); + CreateVmportFIpEnv(fip_input2, 1, 0); + client->WaitForIdle(5); + + EXPECT_TRUE(VmPortActive(fip_input1, 0)); + EXPECT_TRUE(VmPortActive(fip_input1, 1)); + EXPECT_TRUE(VmPortPolicyEnable(fip_input1, 0)); + EXPECT_TRUE(VmPortPolicyEnable(fip_input1, 1)); + EXPECT_TRUE(VmPortActive(fip_input2, 0)); + + flowa = VmInterfaceGet(fip_input1[0].intf_id); + assert(flowa); + flowb = VmInterfaceGet(fip_input1[1].intf_id); + assert(flowb); + flowc = VmInterfaceGet(fip_input2[0].intf_id); + assert(flowc); + + // Configure Floating-IP + AddFloatingIpPool("fip-poolc", 1); + AddFloatingIp("fipc1", 1, vm_c_fip1); + AddFloatingIp("fipc2", 1, vm_c_fip2); + AddLink("floating-ip", "fipc1", "floating-ip-pool", "fip-poolc"); + AddLink("floating-ip", "fipc2", "floating-ip-pool", "fip-poolc"); + AddLink("floating-ip-pool", "fip-poolc", "virtual-network", "default-project:vn8"); + AddLink("virtual-machine-interface", "flowa", "floating-ip", "fipc1"); + AddLink("virtual-machine-interface", "flowb", "floating-ip", "fipc2"); + client->WaitForIdle(); + EXPECT_TRUE(flowa->HasFloatingIp()); + EXPECT_TRUE(flowb->HasFloatingIp()); + } + + void RemoveFipConfig() { + DelLink("virtual-machine-interface", "flow0", "floating-ip", "fip1"); + DelLink("floating-ip", "fip1", "floating-ip-pool", "fip-pool1"); + DelLink("floating-ip-pool", "fip-pool1", + "virtual-network", "default-project:vn4"); + DelFloatingIp("fip1"); + DelFloatingIpPool("fip-pool1"); + client->WaitForIdle(3); + } + + void RemoveFipConfig2() { + DelLink("virtual-machine-interface", "flowa", "floating-ip", "fipc1"); + DelLink("virtual-machine-interface", "flowb", "floating-ip", "fipc2"); + DelLink("floating-ip-pool", "fip-poolc", + "virtual-network", "default-project:vn8"); + DelLink("floating-ip", "fipc1", "floating-ip-pool", "fip-poolc"); + DelLink("floating-ip", "fipc2", "floating-ip-pool", "fip-poolc"); + DelFloatingIp("fipc1"); + DelFloatingIp("fipc2"); + DelFloatingIpPool("fip-poolc"); + client->WaitForIdle(3); + } + + void CreatePeer() { + boost::system::error_code ec; + peer_ = CreateBgpPeer(Ip4Address::from_string("0.0.0.1", ec), + "xmpp channel"); + } + + void DeletePeer() { + DeleteBgpPeer(peer_); + } + + Agent *agent() {return agent_;} + + TestUveUtil util_; + BgpPeer *peer_; + Agent *agent_; +}; + +TEST_F(InterfaceUveTest, VmIntfAddDel_1) { + struct PortInfo input[] = { + {"vnet1", 1, "1.1.1.1", "00:00:00:01:01:01", 1, 1}, + }; + + InterfaceUveTableTest *vmut = static_cast + (Agent::GetInstance()->uve()->interface_uve_table()); + vmut->ClearCount(); + EXPECT_EQ(0U, vmut->InterfaceUveCount()); + + //Add VN + util_.VnAdd(input[0].vn_id); + + // Nova Port add message + util_.NovaPortAdd(input); + + // Config Port add + util_.ConfigPortAdd(input); + + //Add VM + util_.VmAdd(input[0].vm_id); + client->WaitForIdle(); + + util_.EnqueueSendVmiUveTask(); + client->WaitForIdle(); + + //Verify send_count after VM addition + EXPECT_TRUE((vmut->send_count() > 0)); + uint32_t send_count = vmut->send_count(); + + //Add necessary objects and links to make vm-intf active + util_.VrfAdd(input[0].vn_id); + AddLink("virtual-network", "vn1", "routing-instance", "vrf1"); + client->WaitForIdle(); + AddLink("virtual-network", "vn1", "virtual-machine-interface", "vnet1"); + client->WaitForIdle(); + AddLink("virtual-machine", "vm1", "virtual-machine-interface", "vnet1"); + client->WaitForIdle(); + AddVmPortVrf("vnet1", "", 0); + client->WaitForIdle(); + AddInstanceIp("instance0", input[0].vm_id, input[0].addr); + AddLink("virtual-machine-interface", input[0].name, + "instance-ip", "instance0"); + client->WaitForIdle(); + AddLink("virtual-machine-interface-routing-instance", "vnet1", + "routing-instance", "vrf1"); + client->WaitForIdle(); + AddLink("virtual-machine-interface-routing-instance", "vnet1", + "virtual-machine-interface", "vnet1"); + client->WaitForIdle(); + EXPECT_TRUE(VmPortActive(input, 0)); + + util_.EnqueueSendVmiUveTask(); + client->WaitForIdle(); + + //Verify UVE + const VmInterface *vmi = VmInterfaceGet(input[0].intf_id); + EXPECT_TRUE(vmi != NULL); + const UveVMInterfaceAgent uve1 = vmut->last_sent_uve(); + EXPECT_TRUE((vmut->send_count() > send_count)); + + //Verify interface config name + std::string intf_entry = uve1.get_name(); + string cfg_name = vmi->cfg_name(); + EXPECT_STREQ(cfg_name.c_str(), intf_entry.c_str()); + + // Delete virtual-machine-interface to vrf link attribute + DelLink("virtual-machine-interface-routing-instance", "vnet1", + "routing-instance", "vrf1"); + DelLink("virtual-machine-interface-routing-instance", "vnet1", + "virtual-machine-interface", "vnet1"); + client->WaitForIdle(); + + //other cleanup + util_.VnDelete(input[0].vn_id); + DelLink("virtual-machine", "vm1", "virtual-machine-interface", "vnet1"); + DelLink("virtual-network", "vn1", "virtual-machine-interface", "vnet1"); + client->WaitForIdle(); + + DelLink("virtual-machine-interface", input[0].name, + "instance-ip", "instance0"); + DelLink("virtual-network", "vn1", "routing-instance", "vrf1"); + DelNode("virtual-machine-interface-routing-instance", "vnet1"); + DelNode("virtual-machine", "vm1"); + DelNode("routing-instance", "vrf1"); + DelNode("virtual-network", "vn1"); + DelNode("virtual-machine-interface", "vnet1"); + DelInstanceIp("instance0"); + client->WaitForIdle(); + IntfCfgDel(input, 0); + client->WaitForIdle(); + + util_.EnqueueSendVmiUveTask(); + client->WaitForIdle(); + WAIT_FOR(1000, 500, ((vmut->InterfaceUveCount() == 0U))); + + //Verify UVE + EXPECT_EQ(1U, vmut->delete_count()); + + //clear counters at the end of test case + client->Reset(); + vmut->ClearCount(); +} + +/* Vm Dissassociation from VMI, VM Delete --> Vm Add, Vm Reassociation */ +TEST_F(InterfaceUveTest, VmIntfAddDel_2) { + struct PortInfo input[] = { + {"vnet1", 1, "1.1.1.1", "00:00:00:01:01:01", 1, 1}, + }; + + InterfaceUveTableTest *vmut = static_cast + (Agent::GetInstance()->uve()->interface_uve_table()); + vmut->ClearCount(); + EXPECT_EQ(0U, vmut->InterfaceUveCount()); + + //Add VN + util_.VnAdd(input[0].vn_id); + + // Nova Port add message + util_.NovaPortAdd(input); + + // Config Port add + util_.ConfigPortAdd(input); + + //Add VM + util_.VmAdd(input[0].vm_id); + + util_.EnqueueSendVmiUveTask(); + client->WaitForIdle(); + + //Verify send_count after VM addition + EXPECT_EQ(1U, vmut->send_count()); + + //Add necessary objects and links to make vm-intf active + util_.VrfAdd(input[0].vn_id); + AddLink("virtual-network", "vn1", "routing-instance", "vrf1"); + client->WaitForIdle(); + AddLink("virtual-network", "vn1", "virtual-machine-interface", "vnet1"); + client->WaitForIdle(); + AddLink("virtual-machine", "vm1", "virtual-machine-interface", "vnet1"); + client->WaitForIdle(); + AddVmPortVrf("vnet1", "", 0); + client->WaitForIdle(); + AddInstanceIp("instance0", input[0].vm_id, input[0].addr); + AddLink("virtual-machine-interface", input[0].name, + "instance-ip", "instance0"); + client->WaitForIdle(); + AddLink("virtual-machine-interface-routing-instance", "vnet1", + "routing-instance", "vrf1"); + client->WaitForIdle(); + AddLink("virtual-machine-interface-routing-instance", "vnet1", + "virtual-machine-interface", "vnet1"); + client->WaitForIdle(); + EXPECT_TRUE(VmPortActive(input, 0)); + + util_.EnqueueSendVmiUveTask(); + client->WaitForIdle(); + + //Verify UVE + EXPECT_EQ(2U, vmut->send_count()); + + //Disassociate VM from VMI and delete the VM + DelLink("virtual-machine", "vm1", "virtual-machine-interface", "vnet1"); + util_.VmDelete(input[0].vm_id); + client->WaitForIdle(); + + util_.EnqueueSendVmiUveTask(); + client->WaitForIdle(); + + //Verify that no additional interface UVEs are sent + EXPECT_TRUE((vmut->send_count() == 3U)); + EXPECT_EQ(0U, vmut->delete_count()); + + //Add the VM back and re-associate it with same VMI + util_.VmAdd(input[0].vm_id); + AddLink("virtual-machine", "vm1", "virtual-machine-interface", "vnet1"); + client->WaitForIdle(); + + util_.EnqueueSendVmiUveTask(); + client->WaitForIdle(); + + //Verify UVE + EXPECT_TRUE((vmut->send_count() >= 4U)); + + // Delete virtual-machine-interface to vrf link attribute + DelLink("virtual-machine-interface-routing-instance", "vnet1", + "routing-instance", "vrf1"); + DelLink("virtual-machine-interface-routing-instance", "vnet1", + "virtual-machine-interface", "vnet1"); + client->WaitForIdle(); + + //Verify that the port is inactive + EXPECT_TRUE(VmPortInactive(input, 0)); + + util_.EnqueueSendVmiUveTask(); + client->WaitForIdle(); + + //Verify UVE + EXPECT_TRUE((vmut->send_count() >= 5U)); + + //Activate the interface again + AddLink("virtual-machine-interface-routing-instance", "vnet1", + "routing-instance", "vrf1"); + AddLink("virtual-machine-interface-routing-instance", "vnet1", + "virtual-machine-interface", "vnet1"); + client->WaitForIdle(); + + util_.EnqueueSendVmiUveTask(); + client->WaitForIdle(); + + //Verify UVE + EXPECT_TRUE((vmut->send_count() >= 6U)); + + // Delete virtual-machine-interface to vrf link attribute + DelLink("virtual-machine-interface-routing-instance", "vnet1", + "routing-instance", "vrf1"); + DelLink("virtual-machine-interface-routing-instance", "vnet1", + "virtual-machine-interface", "vnet1"); + client->WaitForIdle(); + + //Verify that the port is inactive + EXPECT_TRUE(VmPortInactive(input, 0)); + + util_.EnqueueSendVmiUveTask(); + client->WaitForIdle(); + + //Verify UVE + EXPECT_TRUE((vmut->send_count() >= 7U)); + + //other cleanup + util_.VnDelete(input[0].vn_id); + DelLink("virtual-machine", "vm1", "virtual-machine-interface", "vnet1"); + DelLink("virtual-network", "vn1", "virtual-machine-interface", "vnet1"); + client->WaitForIdle(); + EXPECT_TRUE(VmPortInactive(input, 0)); + + DelLink("virtual-machine-interface", input[0].name, + "instance-ip", "instance0"); + DelLink("virtual-network", "vn1", "routing-instance", "vrf1"); + DelNode("virtual-machine-interface-routing-instance", "vnet1"); + DelNode("virtual-machine", "vm1"); + DelNode("routing-instance", "vrf1"); + DelNode("virtual-network", "vn1"); + DelNode("virtual-machine-interface", "vnet1"); + DelInstanceIp("instance0"); + client->WaitForIdle(); + IntfCfgDel(input, 0); + client->WaitForIdle(); + + util_.EnqueueSendVmiUveTask(); + client->WaitForIdle(); + WAIT_FOR(1000, 500, ((vmut->InterfaceUveCount() == 0U))); + + //Verify UVE + EXPECT_EQ(1U, vmut->delete_count()); + + //clear counters at the end of test case + client->Reset(); + vmut->ClearCount(); +} + +TEST_F(InterfaceUveTest, FipStats_1) { + InterfaceUveTableTest *vmut = static_cast + (Agent::GetInstance()->uve()->interface_uve_table()); + vmut->ClearCount(); + EXPECT_EQ(0U, vmut->InterfaceUveCount()); + + FlowSetUp(); + FlowStatsCollector *fsc = Agent::GetInstance()->flow_stats_collector(); + TestFlow flow[] = { + { + TestFlowPkt(Address::INET, vm1_ip, vm4_ip, 1, 0, 0, "vrf5", + flow0->id(), 1), + { + new VerifyNat(vm4_ip, vm1_fip, 1, 0, 0) + } + } + }; + + CreateFlow(flow, 1); + EXPECT_EQ(2U, Agent::GetInstance()->pkt()->flow_table()->Size()); + + //Verify Floating IP flows are created. + const FlowEntry *f1 = flow[0].pkt_.FlowFetch(); + const FlowEntry *rev = f1->reverse_flow_entry(); + EXPECT_TRUE(FlowGet(VrfGet("vrf5")->vrf_id(), vm1_ip, vm4_ip, 1, 0, 0, + flow0->flow_key_nh()->id())); + EXPECT_TRUE(FlowGet(VrfGet("default-project:vn4:vn4")->vrf_id(), vm4_ip, + vm1_fip, 1, 0, 0, rev->key().nh)); + + //Verify that stats FIP entry is absent until flow stats are updated + EXPECT_EQ(0U, vmut->GetVmIntfFipCount(flow0)); + + //Update FIP stats which resuts in creation of stats FIP entry + fsc->UpdateFloatingIpStats(f1, 300, 3); + fsc->UpdateFloatingIpStats(rev, 300, 3); + + //Verify that stats FIP entry is created + EXPECT_EQ(1U, vmut->GetVmIntfFipCount(flow0)); + + //Fetch stats FIP entry and verify its statistics + const InterfaceUveTable::FloatingIp *fip = vmut->GetVmIntfFip(flow0, + vm1_fip, "default-project:vn4"); + EXPECT_EQ(3U, fip->in_packets_); + EXPECT_EQ(3U, fip->out_packets_); + EXPECT_EQ(300U, fip->in_bytes_); + EXPECT_EQ(300U, fip->out_bytes_); + + //cleanup + FlowTearDown(); + RemoveFipConfig(); + util_.EnqueueSendVmiUveTask(); + client->WaitForIdle(); + WAIT_FOR(1000, 500, ((vmut->InterfaceUveCount() == 0U))); + vmut->ClearCount(); +} + +// Delete FIP config and verify stats entry for that FIP is removed from +// our data-structures +TEST_F(InterfaceUveTest, FipStats_2) { + InterfaceUveTableTest *vmut = static_cast + (Agent::GetInstance()->uve()->interface_uve_table()); + vmut->ClearCount(); + EXPECT_EQ(0U, vmut->InterfaceUveCount()); + + FlowSetUp(); + FlowStatsCollector *fsc = Agent::GetInstance()->flow_stats_collector(); + TestFlow flow[] = { + { + TestFlowPkt(Address::INET, vm1_ip, vm4_ip, 1, 0, 0, "vrf5", + flow0->id(), 1), + { + new VerifyNat(vm4_ip, vm1_fip, 1, 0, 0) + } + } + }; + + CreateFlow(flow, 1); + EXPECT_EQ(2U, Agent::GetInstance()->pkt()->flow_table()->Size()); + + //Verify Floating IP flows are created. + const FlowEntry *f1 = flow[0].pkt_.FlowFetch(); + const FlowEntry *rev = f1->reverse_flow_entry(); + EXPECT_TRUE(FlowGet(VrfGet("vrf5")->vrf_id(), vm1_ip, vm4_ip, 1, 0, 0, + flow0->flow_key_nh()->id())); + EXPECT_TRUE(FlowGet(VrfGet("default-project:vn4:vn4")->vrf_id(), vm4_ip, + vm1_fip, 1, 0, 0, rev->key().nh)); + + //Verify that stats FIP entry is absent until flow stats are updated + EXPECT_EQ(0U, vmut->GetVmIntfFipCount(flow0)); + + //Update FIP stats which resuts in creation of stats FIP entry + fsc->UpdateFloatingIpStats(f1, 300, 3); + fsc->UpdateFloatingIpStats(rev, 300, 3); + + //Verify that stats FIP entry is created + EXPECT_EQ(1U, vmut->GetVmIntfFipCount(flow0)); + + //Remove floating-IP configuration + RemoveFipConfig(); + + //Verify that stats FIP entry is created + EXPECT_EQ(0U, vmut->GetVmIntfFipCount(flow0)); + + //cleanup + FlowTearDown(); + + util_.EnqueueSendVmiUveTask(); + client->WaitForIdle(); + WAIT_FOR(1000, 500, ((vmut->InterfaceUveCount() == 0U))); + vmut->ClearCount(); +} + +// Update FIP stats and verify dispatched VM Stats UVE has the expected stats +TEST_F(InterfaceUveTest, FipStats_3) { + InterfaceUveTableTest *vmut = static_cast + (Agent::GetInstance()->uve()->interface_uve_table()); + vmut->ClearCount(); + EXPECT_EQ(0U, vmut->InterfaceUveCount()); + + FlowSetUp(); + FlowStatsCollector *fsc = Agent::GetInstance()->flow_stats_collector(); + TestFlow flow[] = { + { + TestFlowPkt(Address::INET, vm1_ip, vm4_ip, 1, 0, 0, "vrf5", + flow0->id(), 1), + { + new VerifyNat(vm4_ip, vm1_fip, 1, 0, 0) + } + } + }; + + CreateFlow(flow, 1); + EXPECT_EQ(2U, Agent::GetInstance()->pkt()->flow_table()->Size()); + EXPECT_EQ(3U, vmut->InterfaceUveCount()); + + //Send the required UVEs which clears changed flag set on UVE objects. + util_.EnqueueSendVmiUveTask(); + client->WaitForIdle(); + vmut->ClearCount(); + + //Verify Floating IP flows are created. + const FlowEntry *f1 = flow[0].pkt_.FlowFetch(); + const FlowEntry *rev = f1->reverse_flow_entry(); + EXPECT_TRUE(FlowGet(VrfGet("vrf5")->vrf_id(), vm1_ip, vm4_ip, 1, 0, 0, + flow0->flow_key_nh()->id())); + EXPECT_TRUE(FlowGet(VrfGet("default-project:vn4:vn4")->vrf_id(), vm4_ip, + vm1_fip, 1, 0, 0, rev->key().nh)); + + //Verify that stats FIP entry is absent until flow stats are updated + EXPECT_EQ(0U, vmut->GetVmIntfFipCount(flow0)); + + //Update FIP stats which resuts in creation of stats FIP entry + fsc->UpdateFloatingIpStats(f1, 300, 3); + fsc->UpdateFloatingIpStats(rev, 300, 3); + client->WaitForIdle(); + + //Verify that stats FIP entry is created + EXPECT_EQ(1U, vmut->GetVmIntfFipCount(flow0)); + + //Fetch stats FIP entry and verify its statistics + const InterfaceUveTable::FloatingIp *fip = vmut->GetVmIntfFip(flow0, + vm1_fip, "default-project:vn4"); + EXPECT_EQ(3U, fip->in_packets_); + EXPECT_EQ(3U, fip->out_packets_); + EXPECT_EQ(300U, fip->in_bytes_); + EXPECT_EQ(300U, fip->out_bytes_); + + //Trigger Interface UVE send + vmut->ClearCount(); + vmut->SendInterfaceStats(); + EXPECT_EQ(3U, vmut->send_count()); + EXPECT_EQ(0U, vmut->delete_count()); + + //Verify UVE + UveVMInterfaceAgent *uve1 = vmut->InterfaceUveObject(flow0); + EXPECT_EQ(1U, uve1->get_fip_agg_stats().size()); + + //Verify stats values in UVE + const VmFloatingIPStats &stats = uve1->get_fip_agg_stats().front(); + EXPECT_EQ(3U, stats.get_in_pkts()); + EXPECT_EQ(3U, stats.get_out_pkts()); + EXPECT_EQ(300U, stats.get_in_bytes()); + EXPECT_EQ(300U, stats.get_out_bytes()); + + //cleanup + FlowTearDown(); + RemoveFipConfig(); + + util_.EnqueueSendVmiUveTask(); + client->WaitForIdle(); + WAIT_FOR(1000, 500, ((vmut->InterfaceUveCount() == 0U))); + vmut->ClearCount(); +} + +// Update FIP stats and verify dispatched VM Stats UVE has the expected stats. +// The VMs representing source and destination IP of flow should have a FIP each +// assigned from a common third VN's floating IP pool. Both VMs are part of same +// compute node (Local Flow case) +TEST_F(InterfaceUveTest, FipStats_4) { + InterfaceUveTableTest *vmut = static_cast + (Agent::GetInstance()->uve()->interface_uve_table()); + vmut->ClearCount(); + EXPECT_EQ(0U, vmut->InterfaceUveCount()); + + FlowSetUp2(); + FlowStatsCollector *fsc = Agent::GetInstance()->flow_stats_collector(); + TestFlow flow[] = { + { + TestFlowPkt(Address::INET, vm_a_ip, vm_c_fip2, 1, 0, 0, "vrf6", + flowa->id(), 1), + { + new VerifyNat(vm_b_ip, vm_c_fip1, 1, 0, 0) + } + } + }; + + CreateFlow(flow, 1); + EXPECT_EQ(2U, Agent::GetInstance()->pkt()->flow_table()->Size()); + + //Verify Floating IP flows are created. + const FlowEntry *f1 = flow[0].pkt_.FlowFetch(); + const FlowEntry *rev = f1->reverse_flow_entry(); + EXPECT_TRUE(FlowGet(VrfGet("vrf6")->vrf_id(), vm_a_ip, vm_c_fip2, 1, 0, 0, + flowa->flow_key_nh()->id())); + EXPECT_TRUE(FlowGet(VrfGet("vrf7")->vrf_id(), vm_b_ip, vm_c_fip1, 1, 0, 0, + rev->key().nh)); + + //Verify that stats FIP entry is absent until flow stats are updated + EXPECT_EQ(0U, vmut->GetVmIntfFipCount(flowa)); + + //Update FIP stats which resuts in creation of stats FIP entry + fsc->UpdateFloatingIpStats(f1, 300, 3); + fsc->UpdateFloatingIpStats(rev, 300, 3); + + //Verify that stats FIP entry is created + EXPECT_EQ(1U, vmut->GetVmIntfFipCount(flowa)); + + //Fetch stats FIP entry and verify its statistics + const InterfaceUveTable::FloatingIp *fip = vmut->GetVmIntfFip(flowa, + vm_c_fip1, "default-project:vn8"); + EXPECT_EQ(3U, fip->in_packets_); + EXPECT_EQ(3U, fip->out_packets_); + EXPECT_EQ(300U, fip->in_bytes_); + EXPECT_EQ(300U, fip->out_bytes_); + + //Trigger VM UVE send + vmut->ClearCount(); + vmut->SendInterfaceStats(); + EXPECT_EQ(3U, vmut->send_count()); + EXPECT_EQ(0U, vmut->delete_count()); + + //Verify UVE + UveVMInterfaceAgent *uve1 = vmut->InterfaceUveObject(flowa); + EXPECT_EQ(1U, uve1->get_fip_agg_stats().size()); + + //Verify stats values in UVE + const VmFloatingIPStats &stats = uve1->get_fip_agg_stats().front(); + EXPECT_EQ(3U, stats.get_in_pkts()); + EXPECT_EQ(3U, stats.get_out_pkts()); + EXPECT_EQ(300U, stats.get_in_bytes()); + EXPECT_EQ(300U, stats.get_out_bytes()); + + //cleanup + FlowTearDown2(); + RemoveFipConfig2(); + + util_.EnqueueSendVmiUveTask(); + client->WaitForIdle(); + WAIT_FOR(1000, 500, ((vmut->InterfaceUveCount() == 0U))); + + vmut->ClearCount(); + EXPECT_EQ(0U, vmut->GetVmIntfFipCount(flowa)); +} + +// Update FIP stats and verify dispatched VM Stats UVE has the expected stats. +// The VMs representing source and destination IP of flow should have a FIP each +// assigned from a common third VN's floating IP pool. The destination VM is in +// different compute node. (Non Local flow case) +TEST_F(InterfaceUveTest, FipStats_5) { + InterfaceUveTableTest *vmut = static_cast + (Agent::GetInstance()->uve()->interface_uve_table()); + vmut->ClearCount(); + EXPECT_EQ(0U, vmut->InterfaceUveCount()); + + FlowSetUp(); + FlowStatsCollector *fsc = Agent::GetInstance()->flow_stats_collector(); + CreatePeer(); + util_.CreateRemoteRoute("default-project:vn4:vn4", remote_vm_fip, + remote_router_ip, 30, "default-project:vn4", peer_); + client->WaitForIdle(); + TestFlow flow[] = { + { + TestFlowPkt(Address::INET, vm1_ip, remote_vm_fip, 1, 0, 0, "vrf5", + flow0->id(), 1001), + {} + } + }; + + CreateFlow(flow, 1); + EXPECT_EQ(2U, Agent::GetInstance()->pkt()->flow_table()->Size()); + + //Verify Floating IP flows are created. + const FlowEntry *f1 = flow[0].pkt_.FlowFetch(); + const FlowEntry *rev = f1->reverse_flow_entry(); + EXPECT_TRUE(FlowGet(VrfGet("vrf5")->vrf_id(), vm1_ip, remote_vm_fip, 1, 0, 0, + flow0->flow_key_nh()->id())); + EXPECT_TRUE(FlowGet(VrfGet("vrf5")->vrf_id(), remote_vm_fip, vm1_fip, 1, 0, 0, + rev->key().nh)); + + //Verify that stats FIP entry is absent until flow stats are updated + EXPECT_EQ(0U, vmut->GetVmIntfFipCount(flow0)); + + //Update FIP stats which resuts in creation of stats FIP entry + fsc->UpdateFloatingIpStats(f1, 300, 3); + fsc->UpdateFloatingIpStats(rev, 300, 3); + + //Verify that stats FIP entry is created + EXPECT_EQ(1U, vmut->GetVmIntfFipCount(flow0)); + + //Fetch stats FIP entry and verify its statistics + const InterfaceUveTable::FloatingIp *fip = vmut->GetVmIntfFip(flow0, + vm1_fip, "default-project:vn4"); + EXPECT_EQ(3U, fip->in_packets_); + EXPECT_EQ(3U, fip->out_packets_); + EXPECT_EQ(300U, fip->in_bytes_); + EXPECT_EQ(300U, fip->out_bytes_); + + //Trigger VM UVE send + vmut->ClearCount(); + vmut->SendInterfaceStats(); + WAIT_FOR(1000, 500, (3U == vmut->send_count())); + EXPECT_EQ(0U, vmut->delete_count()); + + //Verify UVE + UveVMInterfaceAgent *uve1 = vmut->InterfaceUveObject(flow0); + EXPECT_EQ(1U, uve1->get_fip_agg_stats().size()); + + //Verify stats values in UVE + const VmFloatingIPStats &stats = uve1->get_fip_agg_stats().front(); + EXPECT_EQ(3U, stats.get_in_pkts()); + EXPECT_EQ(3U, stats.get_out_pkts()); + EXPECT_EQ(300U, stats.get_in_bytes()); + EXPECT_EQ(300U, stats.get_out_bytes()); + //cleanup + FlowTearDown(); + util_.DeleteRemoteRoute("default-project:vn4:vn4", remote_vm_fip, peer_); + RemoveFipConfig(); + DeletePeer(); + + util_.EnqueueSendVmiUveTask(); + client->WaitForIdle(); + WAIT_FOR(1000, 500, ((vmut->InterfaceUveCount() == 0U))); + + vmut->ClearCount(); +} + +/* Verify that VM name is not NULL-string in the interface UVE sent as part of + * VM UVE */ +TEST_F(InterfaceUveTest, VmNameInInterfaceList) { + InterfaceUveTableTest *vmut = static_cast + (Agent::GetInstance()->uve()->interface_uve_table()); + vmut->ClearCount(); + EXPECT_EQ(0U, vmut->InterfaceUveCount()); + struct PortInfo input[] = { + {"vmi1", 1, "1.1.1.1", "00:00:00:01:01:01", 1, 1} + }; + + //Add physical-device and physical-interface and add their association + util_.VmAdd(input[0].vm_id); + AddPhysicalDevice("prouter1", 1); + AddPhysicalInterface("pi1", 1, "pid1"); + AddLogicalInterface("li1", 1, "lid1"); + AddPort("vmi1", 1); + AddLink("physical-router", "prouter1", "physical-interface", "pi1"); + AddLink("physical-interface", "pi1", "logical-interface", "li1"); + AddLink("virtual-machine-interface", "vmi1", "logical-interface", "li1"); + AddLink("virtual-machine-interface", "vmi1", "virtual-machine", "vm1"); + client->WaitForIdle(); + WAIT_FOR(1000, 500, (PhysicalDeviceGet(1) != NULL)); + WAIT_FOR(1000, 500, (PhysicalInterfaceGet("pi1") != NULL)); + WAIT_FOR(1000, 500, (LogicalInterfaceGet(1, "li1") != NULL)); + WAIT_FOR(1000, 500, (VmInterfaceGet(1) != NULL)); + + util_.EnqueueSendVmiUveTask(); + client->WaitForIdle(); + + //Verify UVE + VmEntry *vm = VmGet(input[0].vm_id); + EXPECT_TRUE(vm != NULL); + VmInterface *vmi = VmInterfaceGet(input[0].intf_id); + EXPECT_TRUE(vmi != NULL); + EXPECT_TRUE(vmi->vm() != NULL); + EXPECT_TRUE(vmi->vm() == vm); + EXPECT_TRUE(!vm->GetCfgName().empty()); + UveVMInterfaceAgent uve1 = vmut->last_sent_uve(); + + //Verify that VMI does not have VM Name set + //EXPECT_TRUE((vmi->vm_name() == agent_->NullString())); + EXPECT_TRUE((vmi->vm_name().empty())); + + //Verify that UVE has sent VM name for VMI + EXPECT_TRUE((uve1.get_vm_name() == vm->GetCfgName())); + + //cleanup + DelLink("virtual-machine-interface", "vmi1", "virtual-machine", "vm1"); + DelNode("virtual-machine", "vm1"); + //Disassociate VMI from logical-interface + DelLink("virtual-machine-interface", "vmi1", "logical-interface", "li1"); + //Disassociate logical-interface from physical_interface + DelLink("physical-interface", "pi1", "logical-interface", "li1"); + //Disassociate physical-device from physical-interface + DelLink("physical-router", "prouter1", "physical-interface", "pi1"); + //Delete physical-device and physical-interface + DelPort("vmi1"); + DeleteLogicalInterface("li1"); + DeletePhysicalInterface("pi1"); + DeletePhysicalDevice("prouter1"); + client->WaitForIdle(); + WAIT_FOR(1000, 500, (PhysicalInterfaceGet("pi1") == NULL)); + WAIT_FOR(1000, 500, (PhysicalDeviceGet(1) == NULL)); + WAIT_FOR(1000, 500, (LogicalInterfaceGet(1, "li1") == NULL)); + + //clear counters at the end of test case + client->Reset(); + util_.EnqueueSendVmiUveTask(); + client->WaitForIdle(); + WAIT_FOR(1000, 500, ((vmut->InterfaceUveCount() == 0U))); + vmut->ClearCount(); +} + +TEST_F(InterfaceUveTest, PhysicalIntfAddDel_1) { +} + +TEST_F(InterfaceUveTest, LogicalIntfAddDel_1) { +} + +int main(int argc, char **argv) { + GETUSERARGS(); + client = TestInit(init_file, ksync_init, true, false, true, + (10 * 60 * 1000), (10 * 60 * 1000), true, true, + (10 * 60 * 1000)); + + usleep(10000); + int ret = RUN_ALL_TESTS(); + client->WaitForIdle(); + TestShutdown(); + delete client; + return ret; +} diff --git a/src/vnsw/agent/uve/test/test_port_bitmap.cc b/src/vnsw/agent/uve/test/test_port_bitmap.cc index 51e24162c47..5115cf2993d 100644 --- a/src/vnsw/agent/uve/test/test_port_bitmap.cc +++ b/src/vnsw/agent/uve/test/test_port_bitmap.cc @@ -24,6 +24,7 @@ #include #include #include +#include #include #include "testing/gunit.h" @@ -211,14 +212,13 @@ class UvePortBitmapTest : public ::testing::Test { uint16_t dport) { PortBucketBitmap port_uve; bool ret = true; - VmUveTableTest *vut = static_cast - (Agent::GetInstance()->uve()->vm_uve_table()); + InterfaceUveTableTest *vut = static_cast + (Agent::GetInstance()->uve()->interface_uve_table()); const VmInterface *intf = static_cast (flow->data().intf_entry.get()); - const VmEntry *vm = intf->vm(); - L4PortBitmap *bmap = vut->GetVmIntfPortBitmap(vm, intf); + L4PortBitmap *bmap = vut->GetVmIntfPortBitmap(intf); if (bmap) { bmap->Encode(port_uve); if (ValidateBmap(port_uve, proto, sport, dport) == false) { diff --git a/src/vnsw/agent/uve/test/test_prouter_uve.cc b/src/vnsw/agent/uve/test/test_prouter_uve.cc index 7af1520589a..c806c164b23 100644 --- a/src/vnsw/agent/uve/test/test_prouter_uve.cc +++ b/src/vnsw/agent/uve/test/test_prouter_uve.cc @@ -46,6 +46,28 @@ class ProuterUveSendTask : public Task { } }; +class PIUveSendTask : public Task { +public: + PIUveSendTask() : + Task((TaskScheduler::GetInstance()->GetTaskId("db::DBTable")), 0) { + } + virtual bool Run() { + Agent::GetInstance()->uve()->prouter_uve_table()->PITimerExpiry(); + return true; + } +}; + +class LIUveSendTask : public Task { +public: + LIUveSendTask() : + Task((TaskScheduler::GetInstance()->GetTaskId("db::DBTable")), 0) { + } + virtual bool Run() { + Agent::GetInstance()->uve()->prouter_uve_table()->LITimerExpiry(); + return true; + } +}; + class UveProuterUveTest : public ::testing::Test { public: void EnqueueSendProuterUveTask() { @@ -53,6 +75,16 @@ class UveProuterUveTest : public ::testing::Test { ProuterUveSendTask *task = new ProuterUveSendTask(); scheduler->Enqueue(task); } + void EnqueueSendPIUveTask() { + TaskScheduler *scheduler = TaskScheduler::GetInstance(); + PIUveSendTask *task = new PIUveSendTask(); + scheduler->Enqueue(task); + } + void EnqueueSendLIUveTask() { + TaskScheduler *scheduler = TaskScheduler::GetInstance(); + LIUveSendTask *task = new LIUveSendTask(); + scheduler->Enqueue(task); + } }; @@ -90,7 +122,7 @@ TEST_F(UveProuterUveTest, ProuterAddDel_1) { EXPECT_EQ(0U, uve2.get_embedded_prouter_list().size()); } -//Verify that no UVEs are sent when physical interfaces added/removed. +//Verify that no Prouter UVEs are sent when physical interfaces added/removed. //(when physical interfaces are not associated with physical devices) TEST_F(UveProuterUveTest, PhysicalInterfaceAddDel_1) { AgentUve *u = static_cast(Agent::GetInstance()->uve()); @@ -112,6 +144,10 @@ TEST_F(UveProuterUveTest, PhysicalInterfaceAddDel_1) { EXPECT_EQ(0U, pr->send_count()); EXPECT_EQ(0U, pr->delete_count()); + + EnqueueSendPIUveTask(); + client->WaitForIdle(); + WAIT_FOR(1000, 500, (pr->PhysicalIntfListCount() == 1U)); } TEST_F(UveProuterUveTest, PhysicalInterfaceAddDel_2) { @@ -159,6 +195,38 @@ TEST_F(UveProuterUveTest, PhysicalInterfaceAddDel_2) { WAIT_FOR(1000, 500, (pr->ProuterUveCount() == 0U)); //Verify that Delete UVE is sent out WAIT_FOR(1000, 500, (pr->delete_count() == 1U)); + + EnqueueSendPIUveTask(); + client->WaitForIdle(); + WAIT_FOR(1000, 500, (pr->PhysicalIntfListCount() == 1U)); +} + +//Verify PhysicalInterface UVE is send on PhysicalInterface Add/del +TEST_F(UveProuterUveTest, PhysicalInterfaceAddDel_3) { + AgentUve *u = static_cast(Agent::GetInstance()->uve()); + ProuterUveTableTest *pr = static_cast + (u->prouter_uve_table()); + pr->ClearCount(); + + AddPhysicalInterface("pi1", 1, "pid1"); + client->WaitForIdle(); + WAIT_FOR(1000, 500, (PhysicalInterfaceGet("pi1") != NULL)); + + EnqueueSendPIUveTask(); + client->WaitForIdle(); + + //Verify that PhysicalInterface UVE is sent + WAIT_FOR(1000, 500, (pr->pi_send_count() > 0U)); + + DeletePhysicalInterface("pi1"); + client->WaitForIdle(); + WAIT_FOR(1000, 500, (PhysicalInterfaceGet("pi1") == NULL)); + + EnqueueSendPIUveTask(); + client->WaitForIdle(); + + //Verify that PhysicalInterface 'delete' UVE is sent + WAIT_FOR(1000, 500, (pr->pi_delete_count() == 1U)); } //Verify that no UVEs are sent when logical interfaces added/removed. @@ -187,6 +255,11 @@ TEST_F(UveProuterUveTest, LogicalInterfaceAddDel_1) { EXPECT_EQ(0U, pr->send_count()); EXPECT_EQ(0U, pr->delete_count()); + + //The following is required for cleanup of logical interface list + EnqueueSendLIUveTask(); + client->WaitForIdle(); + WAIT_FOR(1000, 500, (pr->LogicalIntfListCount() == 0U)); } TEST_F(UveProuterUveTest, LogicalInterfaceAddDel_2) { @@ -212,9 +285,6 @@ TEST_F(UveProuterUveTest, LogicalInterfaceAddDel_2) { WAIT_FOR(1000, 500, (pr->last_sent_uve().get_physical_interface_list(). size() == 1U)); - UvePhysicalInterfaceData data = pr->last_sent_uve(). - get_physical_interface_list().front(); - EXPECT_EQ(1U, data.get_logical_interface_list().size()); //Disassociate logical-interface from physical_interface uint32_t send_count = pr->send_count(); @@ -226,9 +296,8 @@ TEST_F(UveProuterUveTest, LogicalInterfaceAddDel_2) { EnqueueSendProuterUveTask(); client->WaitForIdle(); - WAIT_FOR(1000, 500, (pr->send_count() > send_count)); - data = pr->last_sent_uve().get_physical_interface_list().front(); - EXPECT_EQ(0U, data.get_logical_interface_list().size()); + //Verify that Prouter UVE is not sent + EXPECT_TRUE((pr->send_count() == send_count)); //Disassociate physical-device from physical-interface DelLink("physical-router", "prouter1", "physical-interface", "pi1"); @@ -246,6 +315,15 @@ TEST_F(UveProuterUveTest, LogicalInterfaceAddDel_2) { WAIT_FOR(1000, 500, (pr->ProuterUveCount() == 0U)); WAIT_FOR(1000, 500, (pr->delete_count() == 1U)); + + EnqueueSendPIUveTask(); + client->WaitForIdle(); + WAIT_FOR(1000, 500, (pr->PhysicalIntfListCount() == 1U)); + + //The following is required for cleanup of logical interface list + EnqueueSendLIUveTask(); + client->WaitForIdle(); + WAIT_FOR(1000, 500, (pr->LogicalIntfListCount() == 0U)); } TEST_F(UveProuterUveTest, LogicalInterfaceAddDel_3) { @@ -271,9 +349,6 @@ TEST_F(UveProuterUveTest, LogicalInterfaceAddDel_3) { WAIT_FOR(1000, 500, (pr->last_sent_uve().get_physical_interface_list(). size() == 1U)); - UvePhysicalInterfaceData data = pr->last_sent_uve(). - get_physical_interface_list().front(); - EXPECT_EQ(1U, data.get_logical_interface_list().size()); //Disassociate logical-interface from physical_interface uint32_t send_count = pr->send_count(); @@ -309,8 +384,16 @@ TEST_F(UveProuterUveTest, LogicalInterfaceAddDel_3) { EnqueueSendProuterUveTask(); client->WaitForIdle(); WAIT_FOR(1000, 500, (pr->ProuterUveCount() == 0U)); - WAIT_FOR(1000, 500, (pr->delete_count() == 1U)); + + EnqueueSendPIUveTask(); + client->WaitForIdle(); + WAIT_FOR(1000, 500, (pr->PhysicalIntfListCount() == 1U)); + + //The following is required for cleanup of logical interface list + EnqueueSendLIUveTask(); + client->WaitForIdle(); + WAIT_FOR(1000, 500, (pr->LogicalIntfListCount() == 0U)); } //Associate logical interface with prouter (instead of physical-interface) @@ -360,8 +443,16 @@ TEST_F(UveProuterUveTest, LogicalInterfaceAddDel_4) { EnqueueSendProuterUveTask(); client->WaitForIdle(); WAIT_FOR(1000, 500, (pr->ProuterUveCount() == 0U)); - WAIT_FOR(1000, 500, (pr->delete_count() == 1U)); + + EnqueueSendPIUveTask(); + client->WaitForIdle(); + WAIT_FOR(1000, 500, (pr->PhysicalIntfListCount() == 1U)); + + //The following is required for cleanup of logical interface list + EnqueueSendLIUveTask(); + client->WaitForIdle(); + WAIT_FOR(1000, 500, (pr->LogicalIntfListCount() == 0U)); } //Associate logical interface with prouter. Verify change of prouter for a @@ -429,8 +520,39 @@ TEST_F(UveProuterUveTest, LogicalInterfaceAddDel_5) { EnqueueSendProuterUveTask(); client->WaitForIdle(); WAIT_FOR(1000, 500, (pr->ProuterUveCount() == 0U)); - WAIT_FOR(1000, 500, (pr->delete_count() == 2U)); + + //The following is required for cleanup of logical interface list + EnqueueSendLIUveTask(); + client->WaitForIdle(); + WAIT_FOR(1000, 500, (pr->LogicalIntfListCount() == 0U)); +} + +TEST_F(UveProuterUveTest, LogicalInterfaceAddDel_6) { + AgentUve *u = static_cast(Agent::GetInstance()->uve()); + ProuterUveTableTest *pr = static_cast + (u->prouter_uve_table()); + pr->ClearCount(); + + AddLogicalInterface("li1", 1, "lid1"); + client->WaitForIdle(); + WAIT_FOR(1000, 500, (LogicalInterfaceGet(1, "li1") != NULL)); + + EnqueueSendLIUveTask(); + client->WaitForIdle(); + + //Verify LogicalInterface UVE is sent + WAIT_FOR(1000, 500, (pr->li_send_count() == 1U)); + + DeleteLogicalInterface("li1"); + client->WaitForIdle(); + WAIT_FOR(1000, 500, (LogicalInterfaceGet(1, "li1") == NULL)); + + EnqueueSendLIUveTask(); + client->WaitForIdle(); + + //Verify LogicalInterface 'delete' UVE is sent + WAIT_FOR(1000, 500, (pr->li_delete_count() == 1U)); } //Delete PhysicalDevice before deleting logical interface @@ -457,9 +579,6 @@ TEST_F(UveProuterUveTest, PhysicalDeviceDel_1) { WAIT_FOR(1000, 500, (pr->last_sent_uve().get_physical_interface_list(). size() == 1U)); - UvePhysicalInterfaceData data = pr->last_sent_uve(). - get_physical_interface_list().front(); - EXPECT_EQ(1U, data.get_logical_interface_list().size()); //Disassociate physical-device from physical-interface and delete //physical-device @@ -489,8 +608,16 @@ TEST_F(UveProuterUveTest, PhysicalDeviceDel_1) { EnqueueSendProuterUveTask(); client->WaitForIdle(); - WAIT_FOR(1000, 500, (pr->delete_count() == 1U)); + + EnqueueSendPIUveTask(); + client->WaitForIdle(); + WAIT_FOR(1000, 500, (pr->PhysicalIntfListCount() == 1U)); + + //The following is required for cleanup of logical interface list + EnqueueSendLIUveTask(); + client->WaitForIdle(); + WAIT_FOR(1000, 500, (pr->LogicalIntfListCount() == 0U)); } //Delete PhysicalDevice and associate Physical interface with different @@ -518,9 +645,6 @@ TEST_F(UveProuterUveTest, PhysicalDeviceDel_2) { WAIT_FOR(1000, 500, (pr->last_sent_uve().get_physical_interface_list(). size() == 1U)); - UvePhysicalInterfaceData data = pr->last_sent_uve(). - get_physical_interface_list().front(); - EXPECT_EQ(1U, data.get_logical_interface_list().size()); //Disassociate physical-device from physical-interface and delete //physical-device @@ -549,8 +673,6 @@ TEST_F(UveProuterUveTest, PhysicalDeviceDel_2) { WAIT_FOR(1000, 500, (pr->ProuterUveCount() == 1U)); WAIT_FOR(1000, 500, (pr->send_count() > send_count)); - data = pr->last_sent_uve().get_physical_interface_list().front(); - EXPECT_EQ(1U, data.get_logical_interface_list().size()); //Disassociate logical-interface from physical_interface //Delete physical-device and physical-interface @@ -567,11 +689,22 @@ TEST_F(UveProuterUveTest, PhysicalDeviceDel_2) { EnqueueSendProuterUveTask(); client->WaitForIdle(); WAIT_FOR(1000, 500, (pr->ProuterUveCount() == 0U)); - WAIT_FOR(1000, 500, (2U == pr->delete_count())); + + EnqueueSendPIUveTask(); + client->WaitForIdle(); + WAIT_FOR(1000, 500, (pr->PhysicalIntfListCount() == 1U)); + + //The following is required for cleanup of logical interface list + EnqueueSendLIUveTask(); + client->WaitForIdle(); + WAIT_FOR(1000, 500, (pr->LogicalIntfListCount() == 0U)); } TEST_F(UveProuterUveTest, VMI_Logical_Assoc_1) { + AgentUve *u = static_cast(Agent::GetInstance()->uve()); + ProuterUveTableTest *pr = static_cast + (u->prouter_uve_table()); struct PortInfo input[] = { {"vmi1", 1, "1.1.1.1", "00:00:00:01:01:01", 1, 1} }; @@ -596,6 +729,11 @@ TEST_F(UveProuterUveTest, VMI_Logical_Assoc_1) { client->WaitForIdle(); WAIT_FOR(1000, 500, (LogicalInterfaceGet(1, "li1") == NULL)); WAIT_FOR(1000, 500, (VmInterfaceGet(1) == NULL)); + + //The following is required for cleanup of logical interface list + EnqueueSendLIUveTask(); + client->WaitForIdle(); + WAIT_FOR(1000, 500, (pr->LogicalIntfListCount() == 0U)); } TEST_F(UveProuterUveTest, VMIAddDel_1) { @@ -628,11 +766,6 @@ TEST_F(UveProuterUveTest, VMIAddDel_1) { WAIT_FOR(1000, 500, (pr->last_sent_uve().get_physical_interface_list(). size() == 1U)); - UvePhysicalInterfaceData data = pr->last_sent_uve(). - get_physical_interface_list().front(); - EXPECT_EQ(1U, data.get_logical_interface_list().size()); - UveLogicalInterfaceData ldata = data.get_logical_interface_list().front(); - EXPECT_EQ(1U, ldata.get_vm_interface_list().size()); //Disassociate logical-interface from physical_interface DelLink("physical-interface", "pi1", "logical-interface", "li1"); @@ -654,8 +787,15 @@ TEST_F(UveProuterUveTest, VMIAddDel_1) { EnqueueSendProuterUveTask(); client->WaitForIdle(); WAIT_FOR(1000, 500, (pr->ProuterUveCount() == 0U)); - WAIT_FOR(1000, 500, (1U == pr->delete_count())); + + EnqueueSendPIUveTask(); + client->WaitForIdle(); + WAIT_FOR(1000, 500, (pr->PhysicalIntfListCount() == 1U)); + + EnqueueSendLIUveTask(); + client->WaitForIdle(); + WAIT_FOR(1000, 500, (pr->LogicalIntfListCount() == 0U)); } TEST_F(UveProuterUveTest, VMIAddDel_2) { @@ -688,11 +828,6 @@ TEST_F(UveProuterUveTest, VMIAddDel_2) { WAIT_FOR(1000, 500, (pr->last_sent_uve().get_physical_interface_list(). size() == 1U)); - UvePhysicalInterfaceData data = pr->last_sent_uve(). - get_physical_interface_list().front(); - EXPECT_EQ(1U, data.get_logical_interface_list().size()); - UveLogicalInterfaceData ldata = data.get_logical_interface_list().front(); - EXPECT_EQ(1U, ldata.get_vm_interface_list().size()); uint32_t send_count = pr->send_count(); //Disassociate VMI from logical-interface @@ -705,14 +840,9 @@ TEST_F(UveProuterUveTest, VMIAddDel_2) { EnqueueSendProuterUveTask(); client->WaitForIdle(); - //Verify Prouter UVE send has happened after disassociation - WAIT_FOR(1000, 500, (pr->send_count() > send_count)); - //Verify that the sent UVE does not have any VMI - data = pr->last_sent_uve().get_physical_interface_list().front(); - EXPECT_EQ(1U, data.get_logical_interface_list().size()); - ldata = data.get_logical_interface_list().front(); - EXPECT_EQ(0U, ldata.get_vm_interface_list().size()); + //Verify that no Prouter UVE is sent after disassociation + EXPECT_TRUE((pr->send_count() == send_count)); //Disassociate logical-interface from physical_interface DelLink("physical-interface", "pi1", "logical-interface", "li1"); @@ -732,8 +862,15 @@ TEST_F(UveProuterUveTest, VMIAddDel_2) { EnqueueSendProuterUveTask(); client->WaitForIdle(); WAIT_FOR(1000, 500, (pr->ProuterUveCount() == 0U)); - WAIT_FOR(1000, 500, (1U == pr->delete_count())); + + EnqueueSendPIUveTask(); + client->WaitForIdle(); + WAIT_FOR(1000, 500, (pr->PhysicalIntfListCount() == 1U)); + + EnqueueSendLIUveTask(); + client->WaitForIdle(); + WAIT_FOR(1000, 500, (pr->LogicalIntfListCount() == 0U)); } TEST_F(UveProuterUveTest, VMIAddDel_3) { @@ -773,11 +910,6 @@ TEST_F(UveProuterUveTest, VMIAddDel_3) { WAIT_FOR(1000, 500, (pr->last_sent_uve().get_physical_interface_list(). size() == 1U)); - UvePhysicalInterfaceData data = pr->last_sent_uve(). - get_physical_interface_list().front(); - EXPECT_EQ(1U, data.get_logical_interface_list().size()); - UveLogicalInterfaceData ldata = data.get_logical_interface_list().front(); - EXPECT_EQ(2U, ldata.get_vm_interface_list().size()); uint32_t send_count = pr->send_count(); //Disassociate one of the VMI from Logical interface @@ -786,13 +918,9 @@ TEST_F(UveProuterUveTest, VMIAddDel_3) { EnqueueSendProuterUveTask(); client->WaitForIdle(); - WAIT_FOR(1000, 500, (pr->send_count() >= (send_count + 1U))); - //Verify that VMI list count in last sent UVE is reduced by 1 - data = pr->last_sent_uve().get_physical_interface_list().front(); - EXPECT_EQ(1U, data.get_logical_interface_list().size()); - ldata = data.get_logical_interface_list().front(); - EXPECT_EQ(1U, ldata.get_vm_interface_list().size()); + //Verify that no Prouter UVE is sent + EXPECT_TRUE((pr->send_count() == send_count)); //Disassociate logical-interface from physical_interface DelLink("physical-interface", "pi1", "logical-interface", "li1"); @@ -816,8 +944,107 @@ TEST_F(UveProuterUveTest, VMIAddDel_3) { EnqueueSendProuterUveTask(); client->WaitForIdle(); WAIT_FOR(1000, 500, (pr->ProuterUveCount() == 0U)); - WAIT_FOR(1000, 500, (1U == pr->delete_count())); + + EnqueueSendPIUveTask(); + client->WaitForIdle(); + WAIT_FOR(1000, 500, (pr->PhysicalIntfListCount() == 1U)); + + EnqueueSendLIUveTask(); + client->WaitForIdle(); + WAIT_FOR(1000, 500, (pr->LogicalIntfListCount() == 0U)); +} + +TEST_F(UveProuterUveTest, VMIAddDel_4) { + AgentUve *u = static_cast(Agent::GetInstance()->uve()); + ProuterUveTableTest *pr = static_cast + (u->prouter_uve_table()); + pr->ClearCount(); + struct PortInfo input[] = { + {"vmi1", 1, "1.1.1.1", "00:00:00:01:01:01", 1, 1}, + {"vmi1", 2, "1.1.1.2", "00:00:00:01:01:02", 1, 2} + }; + + //Add physical-device and physical-interface and add their association + IntfCfgAdd(input, 0); + AddPhysicalDevice("prouter1", 1); + AddPhysicalInterface("pi1", 1, "pid1"); + AddLogicalInterface("li1", 1, "lid1"); + AddPort("vmi1", 1); + AddLink("physical-router", "prouter1", "physical-interface", "pi1"); + AddLink("physical-interface", "pi1", "logical-interface", "li1"); + AddLink("virtual-machine-interface", "vmi1", "logical-interface", "li1"); + client->WaitForIdle(); + WAIT_FOR(1000, 500, (PhysicalDeviceGet(1) != NULL)); + WAIT_FOR(1000, 500, (PhysicalInterfaceGet("pi1") != NULL)); + WAIT_FOR(1000, 500, (LogicalInterfaceGet(1, "li1") != NULL)); + WAIT_FOR(1000, 500, (VmInterfaceGet(1) != NULL)); + + //Create one more VMI and associate with the above logical interface + IntfCfgAdd(input, 1); + AddPort("vmi2", 2); + AddLink("virtual-machine-interface", "vmi2", "logical-interface", "li1"); + client->WaitForIdle(); + WAIT_FOR(1000, 500, (VmInterfaceGet(2) != NULL)); + VmInterface *vm1 = VmInterfaceGet(1); + VmInterface *vm2 = VmInterfaceGet(2); + WAIT_FOR(1000, 500, (vm1->logical_interface() != nil_uuid())); + WAIT_FOR(1000, 500, (vm2->logical_interface() != nil_uuid())); + const LogicalInterface *li1 = LogicalInterfaceGet(1, "li1"); + + EnqueueSendLIUveTask(); + client->WaitForIdle(); + WAIT_FOR(1000, 500, (pr->LogicalIntfListCount() == 1U)); + WAIT_FOR(1000, 500, (pr->li_send_count() > 0U)); + WAIT_FOR(1000, 500, (pr->VMIListCount(li1) == 2U)); + + WAIT_FOR(1000, 500, (pr->last_sent_li_uve().get_vm_interface_list(). + size() == 2U)); + + uint32_t send_count = pr->send_count(); + //Disassociate one of the VMI from Logical interface + DelLink("virtual-machine-interface", "vmi2", "logical-interface", "li1"); + client->WaitForIdle(); + + EnqueueSendLIUveTask(); + client->WaitForIdle(); + + //Verify that LI UVE is sent with one less VMI + WAIT_FOR(1000, 500, (pr->last_sent_li_uve().get_vm_interface_list(). + size() == 1U)); + EXPECT_TRUE((pr->li_send_count() > send_count)); + + //Disassociate logical-interface from physical_interface + DelLink("physical-interface", "pi1", "logical-interface", "li1"); + //Disassociate physical-device from physical-interface + DelLink("physical-router", "prouter1", "physical-interface", "pi1"); + DelLink("virtual-machine-interface", "vmi1", "logical-interface", "li1"); + //Delete physical-device and physical-interface + DelPort("vmi1"); + DelPort("vmi2"); + DeleteLogicalInterface("li1"); + DeletePhysicalInterface("pi1"); + DeletePhysicalDevice("prouter1"); + IntfCfgDel(input, 0); + IntfCfgDel(input, 1); + + client->WaitForIdle(); + WAIT_FOR(1000, 500, (PhysicalInterfaceGet("pi1") == NULL)); + WAIT_FOR(1000, 500, (PhysicalDeviceGet(1) == NULL)); + WAIT_FOR(1000, 500, (LogicalInterfaceGet(1, "li1") == NULL)); + + EnqueueSendProuterUveTask(); + client->WaitForIdle(); + WAIT_FOR(1000, 500, (pr->ProuterUveCount() == 0U)); + + EnqueueSendPIUveTask(); + client->WaitForIdle(); + WAIT_FOR(1000, 500, (pr->PhysicalIntfListCount() == 1U)); + + EnqueueSendLIUveTask(); + client->WaitForIdle(); + WAIT_FOR(1000, 500, (pr->LogicalIntfListCount() == 0U)); + WAIT_FOR(1000, 500, (1U == pr->li_delete_count())); } int main(int argc, char **argv) { diff --git a/src/vnsw/agent/uve/test/test_stats_mock.cc b/src/vnsw/agent/uve/test/test_stats_mock.cc index 38aef1d0ce3..133dc5f1ff8 100644 --- a/src/vnsw/agent/uve/test/test_stats_mock.cc +++ b/src/vnsw/agent/uve/test/test_stats_mock.cc @@ -822,49 +822,6 @@ TEST_F(StatsTestMock, VrfStatsTest) { //Remove vrf stats object from mock Kernel KSyncSockTypeMap::VrfStatsDelete(vrf41_id); KSyncSockTypeMap::VrfStatsDelete(vrf42_id); - -} - -TEST_F(StatsTestMock, VnStatsTest) { - AgentStatsCollectorTest *collector = static_cast - (Agent::GetInstance()->stats_collector()); - collector->interface_stats_responses_ = 0; - client->IfStatsTimerWait(1); - - //Verify vn stats at the start of test case - char vn_name[20]; - sprintf(vn_name, "vn%d", stats_if[0].vn_id); - - EXPECT_TRUE(VnStatsMatch(vn_name, 0, 0, 0, 0)); - - EXPECT_TRUE(VmPortStatsMatch(test0, 0,0,0,0)); - EXPECT_TRUE(VmPortStatsMatch(test1, 0,0,0,0)); - - //Change the stats on one interface of vn - KSyncSockTypeMap::IfStatsUpdate(test0->id(), 50, 1, 0, 20, 1, 0); - - //Wait for stats to be updated - collector->interface_stats_responses_ = 0; - client->IfStatsTimerWait(1); - - //Verify the updated vn stats - EXPECT_TRUE(VnStatsMatch(vn_name, 50, 1, 20, 1)); - - if (stats_if[0].vn_id == stats_if[1].vn_id) { - //Change the stats on the other interface of same vn - KSyncSockTypeMap::IfStatsUpdate(test1->id(), 50, 1, 0, 20, 1, 0); - - //Wait for stats to be updated - collector->interface_stats_responses_ = 0; - client->IfStatsTimerWait(1); - - //Verify the updated vn stats - EXPECT_TRUE(VnStatsMatch(vn_name, 100, 2, 40, 2)); - } - - //Reset the stats so that repeat of this test case works - KSyncSockTypeMap::IfStatsSet(test0->id(), 0, 0, 0, 0, 0, 0); - KSyncSockTypeMap::IfStatsSet(test1->id(), 0, 0, 0, 0, 0, 0); } //Flow parameters (vrouter, peer_vrouter and tunnel_type) verification for diff --git a/src/vnsw/agent/uve/test/test_uve_util.h b/src/vnsw/agent/uve/test/test_uve_util.h index 2d961a2edd3..1bee4f837a4 100644 --- a/src/vnsw/agent/uve/test/test_uve_util.h +++ b/src/vnsw/agent/uve/test/test_uve_util.h @@ -70,6 +70,17 @@ class VmUveSendTask : public Task { } }; +class VmiUveSendTask : public Task { +public: + VmiUveSendTask() : + Task((TaskScheduler::GetInstance()->GetTaskId("db::DBTable")), 0) { + } + virtual bool Run() { + Agent::GetInstance()->uve()->interface_uve_table()->TimerExpiry(); + return true; + } +}; + class TestUveUtil { public: void EnqueueAgentStatsCollectorTask(int count) { @@ -102,6 +113,12 @@ class TestUveUtil { scheduler->Enqueue(task); } + void EnqueueSendVmiUveTask() { + TaskScheduler *scheduler = TaskScheduler::GetInstance(); + VmiUveSendTask *task = new VmiUveSendTask(); + scheduler->Enqueue(task); + } + void VnAdd(int id) { char vn_name[80]; diff --git a/src/vnsw/agent/uve/test/test_vm_uve.cc b/src/vnsw/agent/uve/test/test_vm_uve.cc index 2ca847e07f7..f0480daa962 100644 --- a/src/vnsw/agent/uve/test/test_vm_uve.cc +++ b/src/vnsw/agent/uve/test/test_vm_uve.cc @@ -206,65 +206,6 @@ class UveVmUveTest : public ::testing::Test { client->WaitForIdle(3); } - void FlowSetUp3() { - EXPECT_EQ(0U, Agent::GetInstance()->pkt()->flow_table()->Size()); - client->Reset(); - CreateVmportEnv(input, 2, 1); - client->WaitForIdle(5); - //CreateVmportFIpEnv(input2, 1, 0); - //client->WaitForIdle(5); - - EXPECT_TRUE(VmPortActive(input, 0)); - EXPECT_TRUE(VmPortActive(input, 1)); - EXPECT_TRUE(VmPortPolicyEnable(input, 0)); - EXPECT_TRUE(VmPortPolicyEnable(input, 1)); - //EXPECT_TRUE(VmPortActive(input2, 0)); - - flow0 = VmInterfaceGet(input[0].intf_id); - assert(flow0); - flow1 = VmInterfaceGet(input[1].intf_id); - assert(flow1); - //flow2 = VmInterfaceGet(input2[0].intf_id); - //assert(flow2); - - // Configure Floating-IP - AddFloatingIpPool("fip-pool1", 1); - AddFloatingIp("fip1", 1, vm1_fip); - AddLink("floating-ip", "fip1", "floating-ip-pool", "fip-pool1"); - AddLink("floating-ip-pool", "fip-pool1", - "virtual-network", "default-project:vn4"); - AddLink("virtual-machine-interface", "flow0", "floating-ip", "fip1"); - client->WaitForIdle(); - EXPECT_TRUE(flow0->HasFloatingIp()); - } - - void FlowTearDown3() { - FlushFlowTable(); - client->Reset(); - - DeleteVmportEnv(input, 2, true, 1); - client->WaitForIdle(3); - client->PortDelNotifyWait(2); - EXPECT_FALSE(VmPortFind(input, 0)); - EXPECT_FALSE(VmPortFind(input, 1)); - - /*client->Reset(); - DeleteVmportFIpEnv(input2, 1, true); - client->WaitForIdle(3); - client->PortDelNotifyWait(1); - EXPECT_FALSE(VmPortFind(input2, 0));*/ - } - - void CreatePeer() { - boost::system::error_code ec; - peer_ = CreateBgpPeer(Ip4Address::from_string("0.0.0.1", ec), - "xmpp channel"); - } - - void DeletePeer() { - DeleteBgpPeer(peer_); - } - Agent *agent() {return agent_;} TestUveUtil util_; @@ -406,11 +347,11 @@ TEST_F(UveVmUveTest, VmIntfAddDel_1) { EXPECT_EQ(1U, uve1->get_interface_list().size()); //Verify interface UUID - VmInterfaceAgent intf_entry = uve1->get_interface_list().front(); + std::string intf_entry = uve1->get_interface_list().front(); VmInterface *vmi = VmInterfaceGet(input[0].intf_id); assert(vmi); - string uuid_str = to_string(vmi->GetUuid()); - EXPECT_STREQ(uuid_str.c_str(), intf_entry.get_uuid().c_str()); + string cfg_name = vmi->cfg_name(); + EXPECT_STREQ(cfg_name.c_str(), intf_entry.c_str()); // Delete virtual-machine-interface to vrf link attribute DelLink("virtual-machine-interface-routing-instance", "vnet1", @@ -425,8 +366,8 @@ TEST_F(UveVmUveTest, VmIntfAddDel_1) { util_.EnqueueSendVmUveTask(); client->WaitForIdle(); - //Verify UVE - EXPECT_EQ(3U, vmut->send_count()); + //Verify that no UVE is sent on VMI deactivation + EXPECT_EQ(2U, vmut->send_count()); EXPECT_EQ(1U, uve1->get_interface_list().size()); //Activate the interface again @@ -439,8 +380,8 @@ TEST_F(UveVmUveTest, VmIntfAddDel_1) { util_.EnqueueSendVmUveTask(); client->WaitForIdle(); - //Verify UVE - EXPECT_EQ(4U, vmut->send_count()); + //Verify that no UVE is sent on VMI reactivation + EXPECT_EQ(2U, vmut->send_count()); EXPECT_EQ(1U, uve1->get_interface_list().size()); // Delete virtual-machine-interface to vrf link attribute @@ -456,9 +397,10 @@ TEST_F(UveVmUveTest, VmIntfAddDel_1) { util_.EnqueueSendVmUveTask(); client->WaitForIdle(); - //Verify UVE - EXPECT_EQ(5U, vmut->send_count()); + //Verify that no UVE is sent on VMI deactivation + EXPECT_EQ(2U, vmut->send_count()); EXPECT_EQ(1U, uve1->get_interface_list().size()); + uint32_t send_count = vmut->send_count(); //other cleanup util_.VnDelete(input[0].vn_id); @@ -483,7 +425,8 @@ TEST_F(UveVmUveTest, VmIntfAddDel_1) { client->WaitForIdle(); WAIT_FOR(1000, 500, ((vmut->VmUveCount() == 0U))); - //Verify UVE + //Verify UVE + EXPECT_TRUE((vmut->send_count() > send_count)); EXPECT_EQ(1U, vmut->delete_count()); //clear counters at the end of test case @@ -584,6 +527,11 @@ TEST_F(UveVmUveTest, VmIntfAddDel_2) { //Verify UVE EXPECT_TRUE((vmut->send_count() >= 4U)); EXPECT_EQ(1U, vmut->delete_count()); + vm = VmGet(input[0].vm_id); + EXPECT_TRUE(vm != NULL); + uve1 = vmut->VmUveObject(vm); + EXPECT_TRUE(uve1 != NULL); + EXPECT_EQ(1U, uve1->get_interface_list().size()); // Delete virtual-machine-interface to vrf link attribute DelLink("virtual-machine-interface-routing-instance", "vnet1", @@ -603,7 +551,9 @@ TEST_F(UveVmUveTest, VmIntfAddDel_2) { EXPECT_TRUE(vm != NULL); uve1 = vmut->VmUveObject(vm); EXPECT_TRUE(uve1 != NULL); - EXPECT_TRUE((vmut->send_count() >= 5U)); + + //Verify that no more VM uves are sent on VMI deactivation + EXPECT_TRUE((vmut->send_count() >= 4U)); EXPECT_EQ(1U, uve1->get_interface_list().size()); //Activate the interface again @@ -616,8 +566,8 @@ TEST_F(UveVmUveTest, VmIntfAddDel_2) { util_.EnqueueSendVmUveTask(); client->WaitForIdle(); - //Verify UVE - EXPECT_TRUE((vmut->send_count() >= 6U)); + //Verify that no more VM uves are sent on VMI re-activation + EXPECT_TRUE((vmut->send_count() >= 4U)); EXPECT_EQ(1U, uve1->get_interface_list().size()); // Delete virtual-machine-interface to vrf link attribute @@ -633,8 +583,8 @@ TEST_F(UveVmUveTest, VmIntfAddDel_2) { util_.EnqueueSendVmUveTask(); client->WaitForIdle(); - //Verify UVE - EXPECT_TRUE((vmut->send_count() >= 7U)); + //Verify that no more VM uves are sent on VMI deactivation + EXPECT_TRUE((vmut->send_count() >= 4U)); EXPECT_EQ(1U, uve1->get_interface_list().size()); //other cleanup @@ -662,6 +612,7 @@ TEST_F(UveVmUveTest, VmIntfAddDel_2) { WAIT_FOR(1000, 500, ((vmut->VmUveCount() == 0U))); //Verify UVE + EXPECT_TRUE((vmut->send_count() >= 5U)); EXPECT_EQ(2U, vmut->delete_count()); //clear counters at the end of test case @@ -900,405 +851,6 @@ TEST_F(UveVmUveTest, FipUninstalledRemove) { vmut->ClearCount(); } -TEST_F(UveVmUveTest, FipStats_1) { - VmUveTableTest *vmut = static_cast - (Agent::GetInstance()->uve()->vm_uve_table()); - - EXPECT_EQ(0U, vmut->VmUveCount()); - FlowSetUp(); - FlowStatsCollector *fsc = Agent::GetInstance()->flow_stats_collector(); - TestFlow flow[] = { - { - TestFlowPkt(Address::INET, vm1_ip, vm4_ip, 1, 0, 0, "vrf5", - flow0->id(), 1), - { - new VerifyNat(vm4_ip, vm1_fip, 1, 0, 0) - } - } - }; - - CreateFlow(flow, 1); - EXPECT_EQ(2U, Agent::GetInstance()->pkt()->flow_table()->Size()); - - //Verify Floating IP flows are created. - const FlowEntry *f1 = flow[0].pkt_.FlowFetch(); - const FlowEntry *rev = f1->reverse_flow_entry(); - EXPECT_TRUE(FlowGet(VrfGet("vrf5")->vrf_id(), vm1_ip, vm4_ip, 1, 0, 0, - flow0->flow_key_nh()->id())); - EXPECT_TRUE(FlowGet(VrfGet("default-project:vn4:vn4")->vrf_id(), vm4_ip, - vm1_fip, 1, 0, 0, rev->key().nh)); - - //Verify that stats FIP entry is absent until flow stats are updated - EXPECT_EQ(0U, vmut->GetVmIntfFipCount(flow0->vm(), flow0)); - - //Update FIP stats which resuts in creation of stats FIP entry - fsc->UpdateFloatingIpStats(f1, 300, 3); - fsc->UpdateFloatingIpStats(rev, 300, 3); - - //Verify that stats FIP entry is created - EXPECT_EQ(1U, vmut->GetVmIntfFipCount(flow0->vm(), flow0)); - - //Fetch stats FIP entry and verify its statistics - const VmUveEntry::FloatingIp *fip = vmut->GetVmIntfFip(flow0->vm(), flow0, - vm1_fip, "default-project:vn4"); - EXPECT_EQ(3U, fip->in_packets_); - EXPECT_EQ(3U, fip->out_packets_); - EXPECT_EQ(300U, fip->in_bytes_); - EXPECT_EQ(300U, fip->out_bytes_); - - //cleanup - FlowTearDown(); - RemoveFipConfig(); - util_.EnqueueSendVmUveTask(); - client->WaitForIdle(); - WAIT_FOR(1000, 500, ((vmut->VmUveCount() == 0U))); - vmut->ClearCount(); -} - -// Delete FIP config and verify stats entry for that FIP is removed from -// our data-structures -TEST_F(UveVmUveTest, FipStats_2) { - VmUveTableTest *vmut = static_cast - (Agent::GetInstance()->uve()->vm_uve_table()); - - EXPECT_EQ(0U, vmut->VmUveCount()); - FlowSetUp(); - FlowStatsCollector *fsc = Agent::GetInstance()->flow_stats_collector(); - TestFlow flow[] = { - { - TestFlowPkt(Address::INET, vm1_ip, vm4_ip, 1, 0, 0, "vrf5", - flow0->id(), 1), - { - new VerifyNat(vm4_ip, vm1_fip, 1, 0, 0) - } - } - }; - - CreateFlow(flow, 1); - EXPECT_EQ(2U, Agent::GetInstance()->pkt()->flow_table()->Size()); - - //Verify Floating IP flows are created. - const FlowEntry *f1 = flow[0].pkt_.FlowFetch(); - const FlowEntry *rev = f1->reverse_flow_entry(); - EXPECT_TRUE(FlowGet(VrfGet("vrf5")->vrf_id(), vm1_ip, vm4_ip, 1, 0, 0, - flow0->flow_key_nh()->id())); - EXPECT_TRUE(FlowGet(VrfGet("default-project:vn4:vn4")->vrf_id(), vm4_ip, - vm1_fip, 1, 0, 0, rev->key().nh)); - - //Verify that stats FIP entry is absent until flow stats are updated - EXPECT_EQ(0U, vmut->GetVmIntfFipCount(flow0->vm(), flow0)); - - //Update FIP stats which resuts in creation of stats FIP entry - fsc->UpdateFloatingIpStats(f1, 300, 3); - fsc->UpdateFloatingIpStats(rev, 300, 3); - - //Verify that stats FIP entry is created - EXPECT_EQ(1U, vmut->GetVmIntfFipCount(flow0->vm(), flow0)); - - //Remove floating-IP configuration - RemoveFipConfig(); - - //Verify that stats FIP entry is created - EXPECT_EQ(0U, vmut->GetVmIntfFipCount(flow0->vm(), flow0)); - - //cleanup - FlowTearDown(); - - util_.EnqueueSendVmUveTask(); - client->WaitForIdle(); - WAIT_FOR(1000, 500, ((vmut->VmUveCount() == 0U))); - vmut->ClearCount(); -} - -// Update FIP stats and verify dispatched VM Stats UVE has the expected stats -TEST_F(UveVmUveTest, FipStats_3) { - VmUveTableTest *vmut = static_cast - (Agent::GetInstance()->uve()->vm_uve_table()); - - EXPECT_EQ(0U, vmut->VmUveCount()); - FlowSetUp(); - FlowStatsCollector *fsc = Agent::GetInstance()->flow_stats_collector(); - TestFlow flow[] = { - { - TestFlowPkt(Address::INET, vm1_ip, vm4_ip, 1, 0, 0, "vrf5", - flow0->id(), 1), - { - new VerifyNat(vm4_ip, vm1_fip, 1, 0, 0) - } - } - }; - - CreateFlow(flow, 1); - EXPECT_EQ(2U, Agent::GetInstance()->pkt()->flow_table()->Size()); - EXPECT_EQ(3U, vmut->VmUveCount()); - - //Send the required UVEs which clears changed flag set on UVE objects. - util_.EnqueueSendVmUveTask(); - client->WaitForIdle(); - vmut->ClearCount(); - - //Verify Floating IP flows are created. - const FlowEntry *f1 = flow[0].pkt_.FlowFetch(); - const FlowEntry *rev = f1->reverse_flow_entry(); - EXPECT_TRUE(FlowGet(VrfGet("vrf5")->vrf_id(), vm1_ip, vm4_ip, 1, 0, 0, - flow0->flow_key_nh()->id())); - EXPECT_TRUE(FlowGet(VrfGet("default-project:vn4:vn4")->vrf_id(), vm4_ip, - vm1_fip, 1, 0, 0, rev->key().nh)); - - //Verify that stats FIP entry is absent until flow stats are updated - EXPECT_EQ(0U, vmut->GetVmIntfFipCount(flow0->vm(), flow0)); - - //Update FIP stats which resuts in creation of stats FIP entry - fsc->UpdateFloatingIpStats(f1, 300, 3); - fsc->UpdateFloatingIpStats(rev, 300, 3); - client->WaitForIdle(); - - //Verify that stats FIP entry is created - EXPECT_EQ(1U, vmut->GetVmIntfFipCount(flow0->vm(), flow0)); - - //Fetch stats FIP entry and verify its statistics - const VmUveEntry::FloatingIp *fip = vmut->GetVmIntfFip(flow0->vm(), flow0, - vm1_fip, "default-project:vn4"); - EXPECT_EQ(3U, fip->in_packets_); - EXPECT_EQ(3U, fip->out_packets_); - EXPECT_EQ(300U, fip->in_bytes_); - EXPECT_EQ(300U, fip->out_bytes_); - - //Trigger VM UVE send - vmut->ClearCount(); - vmut->SendVmStats(); - EXPECT_EQ(3U, vmut->send_count()); - EXPECT_EQ(0U, vmut->delete_count()); - - //Verify UVE - UveVirtualMachineAgent *uve1 = vmut->VmUveObject(flow0->vm()); - EXPECT_EQ(1U, uve1->get_fip_stats_list().size()); - - //Verify stats values in UVE - const VmFloatingIPStats &stats = uve1->get_fip_stats_list().front(); - EXPECT_EQ(3U, stats.get_in_pkts()); - EXPECT_EQ(3U, stats.get_out_pkts()); - EXPECT_EQ(300U, stats.get_in_bytes()); - EXPECT_EQ(300U, stats.get_out_bytes()); - - //cleanup - FlowTearDown(); - RemoveFipConfig(); - - util_.EnqueueSendVmUveTask(); - client->WaitForIdle(); - WAIT_FOR(1000, 500, ((vmut->VmUveCount() == 0U))); - vmut->ClearCount(); -} - -// Update FIP stats and verify dispatched VM Stats UVE has the expected stats. -// The VMs representing source and destination IP of flow should have a FIP each -// assigned from a common third VN's floating IP pool. Both VMs are part of same -// compute node (Local Flow case) -TEST_F(UveVmUveTest, FipStats_4) { - VmUveTableTest *vmut = static_cast - (Agent::GetInstance()->uve()->vm_uve_table()); - - EXPECT_EQ(0U, vmut->VmUveCount()); - FlowSetUp2(); - FlowStatsCollector *fsc = Agent::GetInstance()->flow_stats_collector(); - TestFlow flow[] = { - { - TestFlowPkt(Address::INET, vm_a_ip, vm_c_fip2, 1, 0, 0, "vrf6", - flowa->id(), 1), - { - new VerifyNat(vm_b_ip, vm_c_fip1, 1, 0, 0) - } - } - }; - - CreateFlow(flow, 1); - EXPECT_EQ(2U, Agent::GetInstance()->pkt()->flow_table()->Size()); - - //Verify Floating IP flows are created. - const FlowEntry *f1 = flow[0].pkt_.FlowFetch(); - const FlowEntry *rev = f1->reverse_flow_entry(); - EXPECT_TRUE(FlowGet(VrfGet("vrf6")->vrf_id(), vm_a_ip, vm_c_fip2, 1, 0, 0, - flowa->flow_key_nh()->id())); - EXPECT_TRUE(FlowGet(VrfGet("vrf7")->vrf_id(), vm_b_ip, vm_c_fip1, 1, 0, 0, - rev->key().nh)); - - //Verify that stats FIP entry is absent until flow stats are updated - EXPECT_EQ(0U, vmut->GetVmIntfFipCount(flowa->vm(), flowa)); - - //Update FIP stats which resuts in creation of stats FIP entry - fsc->UpdateFloatingIpStats(f1, 300, 3); - fsc->UpdateFloatingIpStats(rev, 300, 3); - - //Verify that stats FIP entry is created - EXPECT_EQ(1U, vmut->GetVmIntfFipCount(flowa->vm(), flowa)); - - //Fetch stats FIP entry and verify its statistics - const VmUveEntry::FloatingIp *fip = vmut->GetVmIntfFip(flowa->vm(), flowa, - vm_c_fip1, "default-project:vn8"); - EXPECT_EQ(3U, fip->in_packets_); - EXPECT_EQ(3U, fip->out_packets_); - EXPECT_EQ(300U, fip->in_bytes_); - EXPECT_EQ(300U, fip->out_bytes_); - - //Trigger VM UVE send - vmut->ClearCount(); - vmut->SendVmStats(); - EXPECT_EQ(3U, vmut->send_count()); - EXPECT_EQ(0U, vmut->delete_count()); - - //Verify UVE - UveVirtualMachineAgent *uve1 = vmut->VmUveObject(flowa->vm()); - EXPECT_EQ(1U, uve1->get_fip_stats_list().size()); - - //Verify stats values in UVE - const VmFloatingIPStats &stats = uve1->get_fip_stats_list().front(); - EXPECT_EQ(3U, stats.get_in_pkts()); - EXPECT_EQ(3U, stats.get_out_pkts()); - EXPECT_EQ(300U, stats.get_in_bytes()); - EXPECT_EQ(300U, stats.get_out_bytes()); - - //cleanup - FlowTearDown2(); - RemoveFipConfig2(); - - util_.EnqueueSendVmUveTask(); - client->WaitForIdle(); - WAIT_FOR(1000, 500, ((vmut->VmUveCount() == 0U))); - - vmut->ClearCount(); - EXPECT_EQ(0U, vmut->GetVmIntfFipCount(flowa->vm(), flowa)); -} - -// Update FIP stats and verify dispatched VM Stats UVE has the expected stats. -// The VMs representing source and destination IP of flow should have a FIP each -// assigned from a common third VN's floating IP pool. The destination VM is in -// different compute node. (Non Local flow case) -TEST_F(UveVmUveTest, FipStats_5) { - VmUveTableTest *vmut = static_cast - (Agent::GetInstance()->uve()->vm_uve_table()); - - EXPECT_EQ(0U, vmut->VmUveCount()); - FlowSetUp(); - FlowStatsCollector *fsc = Agent::GetInstance()->flow_stats_collector(); - CreatePeer(); - util_.CreateRemoteRoute("default-project:vn4:vn4", remote_vm_fip, - remote_router_ip, 30, "default-project:vn4", peer_); - client->WaitForIdle(); - TestFlow flow[] = { - { - TestFlowPkt(Address::INET, vm1_ip, remote_vm_fip, 1, 0, 0, "vrf5", - flow0->id(), 1001), - {} - } - }; - - CreateFlow(flow, 1); - EXPECT_EQ(2U, Agent::GetInstance()->pkt()->flow_table()->Size()); - - //Verify Floating IP flows are created. - const FlowEntry *f1 = flow[0].pkt_.FlowFetch(); - const FlowEntry *rev = f1->reverse_flow_entry(); - EXPECT_TRUE(FlowGet(VrfGet("vrf5")->vrf_id(), vm1_ip, remote_vm_fip, 1, 0, 0, - flow0->flow_key_nh()->id())); - EXPECT_TRUE(FlowGet(VrfGet("vrf5")->vrf_id(), remote_vm_fip, vm1_fip, 1, 0, 0, - rev->key().nh)); - - //Verify that stats FIP entry is absent until flow stats are updated - EXPECT_EQ(0U, vmut->GetVmIntfFipCount(flow0->vm(), flow0)); - - //Update FIP stats which resuts in creation of stats FIP entry - fsc->UpdateFloatingIpStats(f1, 300, 3); - fsc->UpdateFloatingIpStats(rev, 300, 3); - - //Verify that stats FIP entry is created - EXPECT_EQ(1U, vmut->GetVmIntfFipCount(flow0->vm(), flow0)); - - //Fetch stats FIP entry and verify its statistics - const VmUveEntry::FloatingIp *fip = vmut->GetVmIntfFip(flow0->vm(), flow0, - vm1_fip, "default-project:vn4"); - EXPECT_EQ(3U, fip->in_packets_); - EXPECT_EQ(3U, fip->out_packets_); - EXPECT_EQ(300U, fip->in_bytes_); - EXPECT_EQ(300U, fip->out_bytes_); - - //Trigger VM UVE send - vmut->ClearCount(); - vmut->SendVmStats(); - WAIT_FOR(1000, 500, (3U == vmut->send_count())); - EXPECT_EQ(0U, vmut->delete_count()); - - //Verify UVE - UveVirtualMachineAgent *uve1 = vmut->VmUveObject(flow0->vm()); - EXPECT_EQ(1U, uve1->get_fip_stats_list().size()); - - //Verify stats values in UVE - const VmFloatingIPStats &stats = uve1->get_fip_stats_list().front(); - EXPECT_EQ(3U, stats.get_in_pkts()); - EXPECT_EQ(3U, stats.get_out_pkts()); - EXPECT_EQ(300U, stats.get_in_bytes()); - EXPECT_EQ(300U, stats.get_out_bytes()); - //cleanup - FlowTearDown(); - util_.DeleteRemoteRoute("default-project:vn4:vn4", remote_vm_fip, peer_); - RemoveFipConfig(); - DeletePeer(); - - util_.EnqueueSendVmUveTask(); - client->WaitForIdle(); - util_.EnqueueSendVmUveTask(); - client->WaitForIdle(); - WAIT_FOR(1000, 500, ((vmut->VmUveCount() == 0U))); - - vmut->ClearCount(); -} - -// Update FIP stats and verify dispatched VM Stats UVE has the expected stats -TEST_F(UveVmUveTest, VmUVE_Name_1) { - VmUveTableTest *vmut = static_cast - (Agent::GetInstance()->uve()->vm_uve_table()); - - EXPECT_EQ(0U, vmut->VmUveCount()); - FlowSetUp(); - - //Trigger VM UVE send - vmut->ClearCount(); - vmut->SendVmStats(); - - //Verify the count based on number of VMs we have. - EXPECT_EQ(3U, vmut->send_count()); - EXPECT_EQ(3U, vmut->vm_stats_send_count()); - - //Verify that VM name was not empty - const UveVirtualMachineAgent uve = vmut->last_sent_uve(); - const VirtualMachineStats stats_uve = vmut->last_sent_stats_uve(); - EXPECT_STRNE(uve.get_name().c_str(), ""); - EXPECT_STRNE(stats_uve.get_name().c_str(), ""); - - //cleanup - vmut->ClearCount(); - FlowTearDown(); - - util_.EnqueueSendVmUveTask(); - client->WaitForIdle(); - - //Verify dispatched UVE deletes match the number of VMs deleted - EXPECT_EQ(3U, vmut->delete_count()); - EXPECT_EQ(3U, vmut->vm_stats_delete_count()); - - //Verify that VM name was not empty in delete msg - const UveVirtualMachineAgent uve2 = vmut->last_sent_uve(); - const VirtualMachineStats stats_uve2 = vmut->last_sent_stats_uve(); - EXPECT_STRNE(uve2.get_name().c_str(), ""); - EXPECT_STRNE(stats_uve2.get_name().c_str(), ""); - vmut->ClearCount(); - - RemoveFipConfig(); - util_.EnqueueSendVmUveTask(); - client->WaitForIdle(); - WAIT_FOR(1000, 500, ((vmut->VmUveCount() == 0U))); -} - /* Change the VM associated with a VMI to a different VM * Verify that the old and new VM UVEs have correct interfaces */ @@ -1398,77 +950,6 @@ TEST_F(UveVmUveTest, VmChangeOnVMI) { vmut->ClearCount(); } -/* Verify that VM name is not NULL-string in the interface list sent as part of - * VM UVE */ -TEST_F(UveVmUveTest, VmNameInInterfaceList) { - VmUveTableTest *vmut = static_cast - (Agent::GetInstance()->uve()->vm_uve_table()); - struct PortInfo input[] = { - {"vmi1", 1, "1.1.1.1", "00:00:00:01:01:01", 1, 1} - }; - EXPECT_EQ(0U, vmut->VmUveCount()); - - //Add physical-device and physical-interface and add their association - util_.VmAdd(input[0].vm_id); - AddPhysicalDevice("prouter1", 1); - AddPhysicalInterface("pi1", 1, "pid1"); - AddLogicalInterface("li1", 1, "lid1"); - AddPort("vmi1", 1); - AddLink("physical-router", "prouter1", "physical-interface", "pi1"); - AddLink("physical-interface", "pi1", "logical-interface", "li1"); - AddLink("virtual-machine-interface", "vmi1", "logical-interface", "li1"); - AddLink("virtual-machine-interface", "vmi1", "virtual-machine", "vm1"); - client->WaitForIdle(); - WAIT_FOR(1000, 500, (PhysicalDeviceGet(1) != NULL)); - WAIT_FOR(1000, 500, (PhysicalInterfaceGet("pi1") != NULL)); - WAIT_FOR(1000, 500, (LogicalInterfaceGet(1, "li1") != NULL)); - WAIT_FOR(1000, 500, (VmInterfaceGet(1) != NULL)); - - util_.EnqueueSendVmUveTask(); - client->WaitForIdle(); - - //Verify UVE - VmEntry *vm = VmGet(input[0].vm_id); - EXPECT_TRUE(vm != NULL); - UveVirtualMachineAgent *uve1 = vmut->VmUveObject(vm); - EXPECT_TRUE(uve1 != NULL); - EXPECT_EQ(1U, uve1->get_interface_list().size()); - - //Verify that VMI does not have VM Name set - VmInterface *vmi = VmInterfaceGet(input[0].intf_id); - EXPECT_TRUE((vmi->vm_name() == agent_->NullString())); - - //Verify that UVE has sent VM name for VMI - VmInterfaceAgent intf_entry = uve1->get_interface_list().front(); - EXPECT_TRUE((intf_entry.get_vm_name() == vm->GetCfgName())); - - //cleanup - DelLink("virtual-machine-interface", "vmi1", "virtual-machine", "vm1"); - DelNode("virtual-machine", "vm1"); - //Disassociate VMI from logical-interface - DelLink("virtual-machine-interface", "vmi1", "logical-interface", "li1"); - //Disassociate logical-interface from physical_interface - DelLink("physical-interface", "pi1", "logical-interface", "li1"); - //Disassociate physical-device from physical-interface - DelLink("physical-router", "prouter1", "physical-interface", "pi1"); - //Delete physical-device and physical-interface - DelPort("vmi1"); - DeleteLogicalInterface("li1"); - DeletePhysicalInterface("pi1"); - DeletePhysicalDevice("prouter1"); - client->WaitForIdle(); - WAIT_FOR(1000, 500, (PhysicalInterfaceGet("pi1") == NULL)); - WAIT_FOR(1000, 500, (PhysicalDeviceGet(1) == NULL)); - WAIT_FOR(1000, 500, (LogicalInterfaceGet(1, "li1") == NULL)); - - //clear counters at the end of test case - client->Reset(); - util_.EnqueueSendVmUveTask(); - client->WaitForIdle(); - WAIT_FOR(1000, 500, ((vmut->VmUveCount() == 0U))); - vmut->ClearCount(); -} - //Verfiy Source IP overriden for NAT flows in flow-log messages exported by agent TEST_F(UveVmUveTest, SIP_override) { FlowSetUp(); diff --git a/src/vnsw/agent/uve/test/test_vn_uve.cc b/src/vnsw/agent/uve/test/test_vn_uve.cc index be21cceb278..04fc55871ee 100644 --- a/src/vnsw/agent/uve/test/test_vn_uve.cc +++ b/src/vnsw/agent/uve/test/test_vn_uve.cc @@ -1045,72 +1045,6 @@ TEST_F(UveVnUveTest, LinkLocalVn_Xen) { vnut->ClearCount(); } -TEST_F(UveVnUveTest, VnThroughput) { - struct PortInfo input[30]; - VmInterface *intf[30]; - uint8_t size = Agent::GetInstance()->interface_config_table()->Size(); - for (int i = 0; i < 30; i++) { - int id = (i + 10); - sprintf(input[i].name, "myvnet%d", id); - input[i].intf_id = id; - sprintf(input[i].addr, "1.1.1.%d", id); - sprintf(input[i].mac, "00:00:00:01:01:%02d", id); - input[i].vn_id = 8; - input[i].vm_id = id; - } - CreateVmportEnv(input, 30); - client->WaitForIdle(); - EXPECT_EQ((size + 30), Agent::GetInstance()->interface_config_table()-> - Size()); - - AgentStatsCollectorTest *collector = static_cast - (Agent::GetInstance()->stats_collector()); - collector->Run(); - client->WaitForIdle(); - for (int i = 0; i < 30; i++) { - intf[i] = VmInterfaceGet(input[i].intf_id); - EXPECT_TRUE(intf[i] != NULL); - EXPECT_TRUE(VmPortStatsMatch(intf[i], 0,0,0,0)); - KSyncSockTypeMap::IfStatsUpdate(intf[i]->id(), 50, 1, 0, 20, 1, 0); - } - - collector->Run(); - client->WaitForIdle(); - - for (int i = 0; i < 30; i++) { - EXPECT_TRUE(VmPortStatsMatch(intf[i], 50, 1, 20, 1)); - } - - VnUveTableTest *vnut = static_cast - (Agent::GetInstance()->uve()->vn_uve_table()); - - const VnUveEntry *entry = vnut->GetVnUveEntry("vn8"); - EXPECT_TRUE((entry->deleted() == false)); - - util_.EnqueueSendVnUveTask(); - client->WaitForIdle(); - WAIT_FOR(1000, 500, (vnut->VnUveObject(intf[0]->vn()->GetName()) != NULL)); - - vnut->SendVnStats(false); - client->WaitForIdle(3); - - UveVirtualNetworkAgent *uve1 = vnut->VnUveObject(intf[0]->vn()->GetName()); - EXPECT_EQ(30U, uve1->get_in_tpkts()); - EXPECT_EQ(30U, uve1->get_out_tpkts()); - EXPECT_EQ((30 * 50), uve1->get_in_bytes()); - EXPECT_EQ((30 * 20), uve1->get_out_bytes()); - - //cleanup - DeleteVmportEnv(input, 30, true); - client->WaitForIdle(); - EXPECT_EQ(size, Agent::GetInstance()->interface_config_table()->Size()); - - util_.EnqueueSendVnUveTask(); - client->WaitForIdle(); - WAIT_FOR(1000, 500, (vnut->delete_count() == 1U)); - vnut->ClearCount(); -} - //Inter VN stats test between same VN(VMport to VMport - Same VN) TEST_F(UveVnUveTest, InterVnStats_1) { KSyncSockTypeMap *ksock = KSyncSockTypeMap::GetKSyncSockTypeMap(); diff --git a/src/vnsw/agent/uve/test/vm_uve_entry_test.h b/src/vnsw/agent/uve/test/vm_uve_entry_test.h index 0cbd84d2c8e..8e38c68d119 100644 --- a/src/vnsw/agent/uve/test/vm_uve_entry_test.h +++ b/src/vnsw/agent/uve/test/vm_uve_entry_test.h @@ -12,37 +12,6 @@ class VmUveEntryTest : public VmUveEntry { virtual ~VmUveEntryTest() {} int InterfaceCount() const { return interface_tree_.size(); } L4PortBitmap* port_bitmap() { return &port_bitmap_; } - L4PortBitmap* InterfaceBitmap(const Interface *intf) { - UveInterfaceEntryPtr entry(new UveInterfaceEntry(intf)); - InterfaceSet::iterator it = interface_tree_.find(entry); - if (it != interface_tree_.end()) { - return &((*it)->port_bitmap_); - } - return NULL; - } - uint32_t FloatingIpCount(const Interface *intf) { - UveInterfaceEntryPtr entry(new UveInterfaceEntry(intf)); - InterfaceSet::iterator it = interface_tree_.find(entry); - if (it != interface_tree_.end()) { - return ((*it)->fip_tree_.size()); - } - return 0; - } - const VmUveEntry::FloatingIp *IntfFloatingIp(const Interface *intf, - const std::string &fip, const std::string &vn) { - UveInterfaceEntryPtr entry(new UveInterfaceEntry(intf)); - InterfaceSet::iterator it = interface_tree_.find(entry); - if (it != interface_tree_.end()) { - boost::system::error_code ec; - Ip4Address ip = Ip4Address::from_string(fip, ec); - FloatingIpPtr key(new FloatingIp(ip, vn)); - FloatingIpSet::iterator fip_it = ((*it)->fip_tree_.find(key)); - if (fip_it != ((*it)->fip_tree_.end())) { - return (*fip_it).get(); - } - } - return NULL; - } UveVirtualMachineAgent* uve_info() { return &uve_info_; } private: DISALLOW_COPY_AND_ASSIGN(VmUveEntryTest); diff --git a/src/vnsw/agent/uve/test/vm_uve_table_test.cc b/src/vnsw/agent/uve/test/vm_uve_table_test.cc index 2acffa909a6..600846b8065 100644 --- a/src/vnsw/agent/uve/test/vm_uve_table_test.cc +++ b/src/vnsw/agent/uve/test/vm_uve_table_test.cc @@ -32,16 +32,6 @@ L4PortBitmap* VmUveTableTest::GetVmUvePortBitmap(const VmEntry *vm) { return NULL; } -L4PortBitmap* VmUveTableTest::GetVmIntfPortBitmap(const VmEntry *vm, - const Interface *intf) { - UveVmMap::iterator it = uve_vm_map_.find(vm->GetUuid()); - if (it != uve_vm_map_.end()) { - VmUveEntryTest *entry = static_cast( - it->second.get()); - return entry->InterfaceBitmap(intf); - } - return NULL; -} VmUveTable::VmUveEntryPtr VmUveTableTest::Allocate(const VmEntry *vm) { VmUveEntryPtr uve(new VmUveEntryTest(agent_, vm->GetCfgName())); @@ -73,29 +63,6 @@ UveVirtualMachineAgent* VmUveTableTest::VmUveObject(const VmEntry *vm) { return uve->uve_info(); } -uint32_t VmUveTableTest::GetVmIntfFipCount(const VmEntry *vm, - const Interface* intf) { - UveVmMap::iterator it = uve_vm_map_.find(vm->GetUuid()); - if (it != uve_vm_map_.end()) { - VmUveEntryTest *entry = static_cast( - it->second.get()); - return entry->FloatingIpCount(intf); - } - return 0; -} - -const VmUveEntry::FloatingIp *VmUveTableTest::GetVmIntfFip - (const VmEntry *vm, const Interface* intf, const string &fip, - const string &vn) { - UveVmMap::iterator it = uve_vm_map_.find(vm->GetUuid()); - if (it != uve_vm_map_.end()) { - VmUveEntryTest *entry = static_cast( - it->second.get()); - return entry->IntfFloatingIp(intf, fip, vn); - } - return NULL; -} - void VmUveTableTest::DispatchVmStatsMsg(const VirtualMachineStats &uve) { vm_stats_send_count_++; if (uve.get_deleted()) { diff --git a/src/vnsw/agent/uve/test/vm_uve_table_test.h b/src/vnsw/agent/uve/test/vm_uve_table_test.h index 33fef23c440..929693a54b8 100644 --- a/src/vnsw/agent/uve/test/vm_uve_table_test.h +++ b/src/vnsw/agent/uve/test/vm_uve_table_test.h @@ -20,13 +20,9 @@ class VmUveTableTest : public VmUveTable { int GetVmUveInterfaceCount(const std::string &vm) const; void ClearCount(); L4PortBitmap* GetVmUvePortBitmap(const VmEntry *vm); - L4PortBitmap* GetVmIntfPortBitmap(const VmEntry *vm, const Interface* intf); UveVirtualMachineAgent* VmUveObject(const VmEntry *vm); virtual void VmStatCollectionStart(VmUveVmState *st, const VmEntry *vm) {} virtual void VmStatCollectionStop(VmUveVmState *state) {} - uint32_t GetVmIntfFipCount(const VmEntry *vm, const Interface* intf); - const VmUveEntry::FloatingIp *GetVmIntfFip(const VmEntry *vm, - const Interface* intf, const string &fip, const string &vn); const VirtualMachineStats &last_sent_stats_uve() const { return stats_uve_; } const UveVirtualMachineAgent &last_sent_uve() const { return uve_; } private: diff --git a/src/vnsw/agent/uve/virtual_machine.sandesh b/src/vnsw/agent/uve/virtual_machine.sandesh index 4ff27a539ac..b49c2e42fee 100644 --- a/src/vnsw/agent/uve/virtual_machine.sandesh +++ b/src/vnsw/agent/uve/virtual_machine.sandesh @@ -1,45 +1,9 @@ /* - * Copyright (c) 2013 Juniper Networks, Inc. All rights reserved. + * Copyright (c) 2015 Juniper Networks, Inc. All rights reserved. */ include "vnsw/agent/uve/port_bmap.sandesh" -struct VmFloatingIPStats { - 1: string virtual_network (aggtype="listkey") - 2: string ip_address; - 3: string iface_name; - 4: u64 in_pkts; - 5: u64 in_bytes; - 6: u64 out_pkts; - 7: u64 out_bytes; -} - -struct VmFloatingIPAgent { - 1: string virtual_network; - 2: string ip_address; -} - -struct VmInterfaceAgentBMap { - 1: string name (aggtype="listkey") - 2: port_bmap.PortBucketBitmap port_bucket_bmap; -} - -struct VmInterfaceAgent { - 1: string name (aggtype="listkey") - 2: string ip_address; - 3: string virtual_network; - 4: list floating_ips; - 5: string mac_address; - 6: u32 label; - 7: bool active; - 8: string vm_name; - 9: string gateway; - 10: bool l2_active; - 11: string uuid; - 12: string ip6_address; - 13: bool ip6_active; -} - struct VmCpuStats { 1: double cpu_one_min_avg; 2: u64 vm_memory_quota; @@ -55,14 +19,12 @@ struct UveVirtualMachineAgent { 1: string name (key="ObjectVMTable") 2: optional bool deleted 3: optional list attached_groups; - 4: optional list interface_list; + 4: optional list interface_list; 5: optional string vrouter; - 7: optional list if_bmap_list; 9: optional list udp_sport_bitmap; 10: optional list udp_dport_bitmap; 11: optional list tcp_sport_bitmap; 12: optional list tcp_dport_bitmap; - 13: optional list fip_stats_list; 14: optional VmCpuStats cpu_info; 15: optional string uuid; } @@ -71,37 +33,9 @@ uve sandesh UveVirtualMachineAgentTrace { 1: UveVirtualMachineAgent data; } -/* - * VM's floating ip stats samples - */ -struct VmFloatingIPStatSamples { - 1: string vn; - 2: string ip_address; - 3: string iface_name; - 4: u64 in_pkts; - 5: u64 in_bytes; - 6: u64 out_pkts; - 7: u64 out_bytes; -} - -/* - * VM's interfaces' stats samples - */ -struct VmInterfaceStats { - 1: string name; - 2: u64 in_pkts; - 3: u64 in_bytes; - 4: u64 out_pkts; - 5: u64 out_bytes; - 6: u64 in_bw_usage; - 7: u64 out_bw_usage; -} - struct VirtualMachineStats { 1: string name (key="ObjectVMTable") 2: optional bool deleted - 3: optional list fip_stats (tags=".vn,.iface_name,.ip_address") - 4: optional list if_stats (tags=".name") 5: optional list cpu_stats (tags="") } diff --git a/src/vnsw/agent/uve/virtual_network.sandesh b/src/vnsw/agent/uve/virtual_network.sandesh index 04a877736af..4cd52eb6d65 100644 --- a/src/vnsw/agent/uve/virtual_network.sandesh +++ b/src/vnsw/agent/uve/virtual_network.sandesh @@ -43,10 +43,6 @@ struct UveVirtualNetworkAgent { 2: optional bool deleted 3: optional i32 total_acl_rules; 4: optional list interface_list (aggtype="union") - 5: optional u64 in_tpkts (aggtype="counter") - 6: optional u64 in_bytes (aggtype="counter") - 7: optional u64 out_tpkts (aggtype="counter") - 8: optional u64 out_bytes (aggtype="counter") 9: optional list in_stats (aggtype="append") 10: optional list out_stats (aggtype="append") 11: optional list virtualmachine_list (aggtype="union") diff --git a/src/vnsw/agent/uve/vm_uve_entry.cc b/src/vnsw/agent/uve/vm_uve_entry.cc index 1768cc2e1ed..f4da05b88a8 100644 --- a/src/vnsw/agent/uve/vm_uve_entry.cc +++ b/src/vnsw/agent/uve/vm_uve_entry.cc @@ -3,6 +3,7 @@ */ #include +#include #include using namespace std; @@ -14,54 +15,17 @@ VmUveEntry::VmUveEntry(Agent *agent, const string &vm_name) VmUveEntry::~VmUveEntry() { } -bool VmUveEntry::FrameInterfaceStatsMsg(const VmInterface *vm_intf, - VmInterfaceStats *s_intf) const { - uint64_t in_band, out_band; - assert(!deleted_); - if (vm_intf->cfg_name() == agent_->NullString()) { - return false; - } - s_intf->set_name(vm_intf->cfg_name()); - - const Interface *intf = static_cast(vm_intf); - AgentUve *uve = static_cast(agent_->uve()); - StatsManager::InterfaceStats *s = - uve->stats_manager()->GetInterfaceStats(intf); - if (s == NULL) { - return false; - } - - /* Only diff since previous send needs to be sent as we export - * stats via StatsOracle infra provided by analytics module */ - uint64_t in_b, in_p, out_b, out_p; - s->GetDiffStats(&in_b, &in_p, &out_b, &out_p); - s_intf->set_in_pkts(in_p); - s_intf->set_in_bytes(in_b); - s_intf->set_out_pkts(out_p); - s_intf->set_out_bytes(out_b); - in_band = GetVmPortBandwidth(s, true); - out_band = GetVmPortBandwidth(s, false); - s_intf->set_in_bw_usage(in_band); - s_intf->set_out_bw_usage(out_band); - s->stats_time = UTCTimestampUsec(); - - /* Make sure that update of prev_in_bytes and prev_out_bytes are done only - * after GetVmPortBandwidth is done for both directions as they get used - * in those APIs. */ - s->UpdatePrevStats(); - - return true; -} - void VmUveEntry::UpdatePortBitmap(uint8_t proto, uint16_t sport, uint16_t dport) { //Update VM bitmap port_bitmap_.AddPort(proto, sport, dport); + InterfaceUveStatsTable *table = static_cast + (agent_->uve()->interface_uve_table()); //Update vm interfaces bitmap InterfaceSet::iterator it = interface_tree_.begin(); while(it != interface_tree_.end()) { - (*it).get()->port_bitmap_.AddPort(proto, sport, dport); + table->UpdatePortBitmap(*it, proto, sport, dport); ++it; } } @@ -95,144 +59,17 @@ bool VmUveEntry::SetVmPortBitmap(UveVirtualMachineAgent *uve) { return changed; } -bool VmUveEntry::FrameVmStatsMsg(UveVirtualMachineAgent *uve, - VirtualMachineStats *stats_uve, - bool *stats_uve_changed) { +bool VmUveEntry::FrameVmStatsMsg(UveVirtualMachineAgent *uve) { bool changed = false; uve->set_name(vm_config_name()); - stats_uve->set_name(vm_config_name()); - vector s_intf_list; - vector if_bmap_list; - vector s_fip_list; - vector fip_list; - vector s_diff_list; - vector diff_list; - - InterfaceSet::iterator it = interface_tree_.begin(); - while(it != interface_tree_.end()) { - VmInterfaceStats s_intf; - const Interface *intf = (*it).get()->intf_; - const VmInterface *vm_port = - static_cast(intf); - if (FrameInterfaceStatsMsg(vm_port, &s_intf)) { - s_intf_list.push_back(s_intf); - } - PortBucketBitmap map; - VmInterfaceAgentBMap vmif_map; - L4PortBitmap &port_bmap = (*it).get()->port_bitmap_; - port_bmap.Encode(map); - vmif_map.set_name(vm_port->cfg_name()); - vmif_map.set_port_bucket_bmap(map); - if_bmap_list.push_back(vmif_map); - - fip_list.clear(); - diff_list.clear(); - if (FrameFipStatsMsg(vm_port, fip_list, diff_list)) { - s_fip_list.insert(s_fip_list.end(), fip_list.begin(), - fip_list.end()); - } - s_diff_list.insert(s_diff_list.end(), diff_list.begin(), - diff_list.end()); - - ++it; - } - - if (uve_info_.get_if_bmap_list() != if_bmap_list) { - uve->set_if_bmap_list(if_bmap_list); - uve_info_.set_if_bmap_list(if_bmap_list); - changed = true; - } if (SetVmPortBitmap(uve)) { changed = true; } - if (UveVmFipStatsListChanged(s_fip_list)) { - uve->set_fip_stats_list(s_fip_list); - uve_info_.set_fip_stats_list(s_fip_list); - changed = true; - } - /* VirtualMachineStats are sent always regardless of whether there are - * any changes are not. */ - stats_uve->set_if_stats(s_intf_list); - stats_uve->set_fip_stats(s_diff_list); - *stats_uve_changed = true; - return changed; } -uint64_t VmUveEntry::GetVmPortBandwidth(StatsManager::InterfaceStats *s, - bool dir_in) const { - if (s->stats_time == 0) { - return 0; - } - uint64_t bits; - if (dir_in) { - bits = (s->in_bytes - s->prev_in_bytes) * 8; - } else { - bits = (s->out_bytes - s->prev_out_bytes) * 8; - } - uint64_t cur_time = UTCTimestampUsec(); - uint64_t b_intvl = agent_->uve()->bandwidth_intvl(); - uint64_t diff_seconds = (cur_time - s->stats_time) / b_intvl; - if (diff_seconds == 0) { - return 0; - } - return bits/diff_seconds; -} - -void VmUveEntry::UpdateFloatingIpStats(const FipInfo &fip_info) { - Interface *intf = InterfaceTable::GetInstance()->FindInterface - (fip_info.fip_vm_port_id_); - UveInterfaceEntryPtr entry(new UveInterfaceEntry(intf)); - InterfaceSet::iterator intf_it = interface_tree_.find(entry); - - /* - * 1. VM interface with floating-ip becomes active - * 2. Flow is created on this interface and interface floating ip info is - * stored in flow record - * 3. VM Interface is disassociated from VM - * 4. VM Interface info is removed from interface_tree_ because of - * disassociation - * 5. FlowStats collection task initiates export of flow stats - * 6. Since interface is absent in interface_tree_ we cannot update - * stats in this case - */ - if (intf_it != interface_tree_.end()) { - (*intf_it).get()->UpdateFloatingIpStats(fip_info); - } -} - -bool VmUveEntry::FrameFipStatsMsg(const VmInterface *vm_intf, - vector &fip_list, - vector &diff_list) const { - bool changed = false; - UveInterfaceEntryPtr entry(new UveInterfaceEntry(vm_intf)); - InterfaceSet::iterator intf_it = interface_tree_.find(entry); - - if (intf_it != interface_tree_.end()) { - changed = (*intf_it).get()->FillFloatingIpStats(fip_list, diff_list); - } - return changed; -} - -bool VmUveEntry::UveVmFipStatsListChanged - (const vector &new_list) const { - if (new_list != uve_info_.get_fip_stats_list()) { - return true; - } - return false; -} - -VmUveEntryBase::FloatingIp * VmUveEntry::FipEntry(uint32_t fip, const string &vn, - Interface *intf) { - UveInterfaceEntryPtr entry(new UveInterfaceEntry(intf)); - InterfaceSet::iterator intf_it = interface_tree_.find(entry); - - assert (intf_it != interface_tree_.end()); - return (*intf_it).get()->FipEntry(fip, vn); -} - void VmUveEntry::Reset() { VmUveEntryBase::Reset(); port_bitmap_.Reset(); diff --git a/src/vnsw/agent/uve/vm_uve_entry.h b/src/vnsw/agent/uve/vm_uve_entry.h index a3b116d5877..eafea69c2a8 100644 --- a/src/vnsw/agent/uve/vm_uve_entry.h +++ b/src/vnsw/agent/uve/vm_uve_entry.h @@ -6,7 +6,6 @@ #define vnsw_agent_vm_uve_entry_h #include -#include //The class that defines data-structures to store VirtualMachine information //required for sending VirtualMachine UVE. @@ -15,25 +14,12 @@ class VmUveEntry : public VmUveEntryBase { VmUveEntry(Agent *agent, const string &vm_name); virtual ~VmUveEntry(); void UpdatePortBitmap(uint8_t proto, uint16_t sport, uint16_t dport); - bool FrameVmStatsMsg(UveVirtualMachineAgent *uve, - VirtualMachineStats *stats_uve, - bool *stats_uve_changed); - void UpdateFloatingIpStats(const FipInfo &fip_info); - VmUveEntryBase::FloatingIp * FipEntry(uint32_t fip, const std::string &vn, - Interface *intf); + bool FrameVmStatsMsg(UveVirtualMachineAgent *uve); virtual void Reset(); protected: - uint64_t GetVmPortBandwidth - (StatsManager::InterfaceStats *s, bool dir_in) const; L4PortBitmap port_bitmap_; private: bool SetVmPortBitmap(UveVirtualMachineAgent *uve); - bool FrameInterfaceStatsMsg(const VmInterface *vm_intf, - VmInterfaceStats *s_intf) const; - bool FrameFipStatsMsg(const VmInterface *vm_intf, - std::vector &fip_list, - std::vector &diff_list) const; - bool UveVmFipStatsListChanged(const vector &new_l) const; DISALLOW_COPY_AND_ASSIGN(VmUveEntry); }; #endif // vnsw_agent_vm_uve_entry_h diff --git a/src/vnsw/agent/uve/vm_uve_entry_base.cc b/src/vnsw/agent/uve/vm_uve_entry_base.cc index b8363029031..edfffab819d 100644 --- a/src/vnsw/agent/uve/vm_uve_entry_base.cc +++ b/src/vnsw/agent/uve/vm_uve_entry_base.cc @@ -24,46 +24,16 @@ bool VmUveEntryBase::Update(const VmEntry *vm) { return false; } -void VmUveEntryBase::InterfaceAdd(const Interface *intf, - const VmInterface::FloatingIpSet &old_list) { - UveInterfaceEntry *ientry; - UveInterfaceEntryPtr entry(new UveInterfaceEntry(intf)); - InterfaceSet::iterator it = interface_tree_.find(entry); +void VmUveEntryBase::InterfaceAdd(const std::string &intf_cfg_name) { + InterfaceSet::iterator it = interface_tree_.find(intf_cfg_name); if (it == interface_tree_.end()) { - interface_tree_.insert(entry); - ientry = entry.get(); - } else { - ientry = (*it).get(); - } - /* We need to handle only floating-ip deletion. The add of floating-ip is - * taken care when stats are available for them during flow stats - * collection */ - const VmInterface *vm_itf = static_cast(intf); - const VmInterface::FloatingIpSet &new_list = vm_itf->floating_ip_list().list_; - /* We need to look for entries which are present in old_list and not - * in new_list */ - VmInterface::FloatingIpSet::const_iterator old_it = old_list.begin(); - while (old_it != old_list.end()) { - VmInterface::FloatingIp fip = *old_it; - ++old_it; - /* Skip entries which are not installed as they wouldn't have been - * added - */ - if (!fip.installed_) { - continue; - } - VmInterface::FloatingIpSet::const_iterator new_it = new_list.find(fip); - if (new_it == new_list.end()) { - ientry->RemoveFloatingIp(fip); - } + interface_tree_.insert(intf_cfg_name); } } -void VmUveEntryBase::InterfaceDelete(const Interface *intf) { - UveInterfaceEntryPtr entry(new UveInterfaceEntry(intf)); - InterfaceSet::iterator intf_it = interface_tree_.find(entry); +void VmUveEntryBase::InterfaceDelete(const std::string &intf_cfg_name) { + InterfaceSet::iterator intf_it = interface_tree_.find(intf_cfg_name); if (intf_it != interface_tree_.end()) { - ((*intf_it).get())->fip_tree_.clear(); interface_tree_.erase(intf_it); } if (!add_by_vm_notify_ && (interface_tree_.size() == 0)) { @@ -72,93 +42,12 @@ void VmUveEntryBase::InterfaceDelete(const Interface *intf) { } } -bool VmUveEntryBase::GetVmInterfaceGateway(const VmInterface *vm_intf, - string &gw) const { - const VnEntry *vn = vm_intf->vn(); - if (vn == NULL) { - return false; - } - const vector &list = vn->GetVnIpam(); - Ip4Address vm_addr = vm_intf->ip_addr(); - unsigned int i; - for (i = 0; i < list.size(); i++) { - if (list[i].IsSubnetMember(vm_addr)) - break; - } - if (i == list.size()) { - return false; - } - gw = list[i].default_gw.to_string(); - return true; -} - -bool VmUveEntryBase::FrameInterfaceMsg(const VmInterface *vm_intf, - VmInterfaceAgent *s_intf) const { - if (vm_intf->cfg_name() == agent_->NullString()) { - return false; - } - s_intf->set_name(vm_intf->cfg_name()); - /* VM interfaces which are not created by Nova will not have VM name set. - * In that case pick VM name from VM object instead of VMI object */ - if (vm_intf->vm_name() != agent_->NullString()) { - s_intf->set_vm_name(vm_intf->vm_name()); - } else { - const VmEntry *vm = vm_intf->vm(); - if (vm) { - s_intf->set_vm_name(vm->GetCfgName()); - } - } - if (vm_intf->vn() != NULL) { - s_intf->set_virtual_network(vm_intf->vn()->GetName()); - } else { - s_intf->set_virtual_network(""); - } - s_intf->set_ip_address(vm_intf->ip_addr().to_string()); - s_intf->set_mac_address(vm_intf->vm_mac()); - s_intf->set_ip6_address(vm_intf->ip6_addr().to_string()); - s_intf->set_ip6_active(vm_intf->ipv6_active()); - - vector uve_fip_list; - if (vm_intf->HasFloatingIp(Address::INET)) { - const VmInterface::FloatingIpList fip_list = - vm_intf->floating_ip_list(); - VmInterface::FloatingIpSet::const_iterator it = - fip_list.list_.begin(); - while(it != fip_list.list_.end()) { - const VmInterface::FloatingIp &ip = *it; - /* Don't export FIP entry if it is not installed. When FIP entry - * is not installed it will have NULL VN pointer. We can receive - * notifications for VM interface with un-installed FIP entries - * when the VM interface is not "L3 Active". - */ - if (ip.installed_) { - VmFloatingIPAgent uve_fip; - uve_fip.set_ip_address(ip.floating_ip_.to_string()); - uve_fip.set_virtual_network(ip.vn_.get()->GetName()); - uve_fip_list.push_back(uve_fip); - } - it++; - } - } - s_intf->set_floating_ips(uve_fip_list); - s_intf->set_label(vm_intf->label()); - s_intf->set_active(vm_intf->ipv4_active()); - s_intf->set_l2_active(vm_intf->l2_active()); - s_intf->set_uuid(to_string(vm_intf->GetUuid())); - string gw; - if (GetVmInterfaceGateway(vm_intf, gw)) { - s_intf->set_gateway(gw); - } - - return true; -} - bool VmUveEntryBase::FrameVmMsg(const boost::uuids::uuid &u, UveVirtualMachineAgent *uve) { bool changed = false; assert(!deleted_); uve->set_name(vm_config_name_); - vector s_intf_list; + vector s_intf_list; if (!uve_info_.__isset.uuid) { uve->set_uuid(to_string(u)); @@ -167,13 +56,7 @@ bool VmUveEntryBase::FrameVmMsg(const boost::uuids::uuid &u, } InterfaceSet::iterator it = interface_tree_.begin(); while(it != interface_tree_.end()) { - VmInterfaceAgent s_intf; - const Interface *intf = (*it).get()->intf_; - const VmInterface *vm_port = - static_cast(intf); - if (FrameInterfaceMsg(vm_port, &s_intf)) { - s_intf_list.push_back(s_intf); - } + s_intf_list.push_back(*it); ++it; } @@ -204,7 +87,7 @@ bool VmUveEntryBase::UveVmVRouterChanged(const string &new_value) const { } bool VmUveEntryBase::UveVmInterfaceListChanged - (const vector &new_list) + (const vector &new_list) const { if (new_list != uve_info_.get_interface_list()) { return true; @@ -212,167 +95,6 @@ bool VmUveEntryBase::UveVmInterfaceListChanged return false; } -void VmUveEntryBase::UveInterfaceEntry::UpdateFloatingIpStats - (const FipInfo &fip_info) { - tbb::mutex::scoped_lock lock(mutex_); - //string vn = fip_info.flow_->data().source_vn; - //FloatingIp *entry = FipEntry(fip_info.flow_->stats().fip, fip_info.vn_); - FloatingIp *entry = FipEntry(fip_info.fip_, fip_info.vn_); - entry->UpdateFloatingIpStats(fip_info); -} - -VmUveEntryBase::FloatingIp *VmUveEntryBase::UveInterfaceEntry::FipEntry - (uint32_t ip, const string &vn) { - Ip4Address addr(ip); - FloatingIpPtr key(new FloatingIp(addr, vn)); - FloatingIpSet::iterator fip_it = fip_tree_.find(key); - if (fip_it == fip_tree_.end()) { - fip_tree_.insert(key); - return key.get(); - } else { - return (*fip_it).get(); - } -} -void VmUveEntryBase::FloatingIp::UpdateFloatingIpStats(const FipInfo &fip_info) { - if (fip_info.is_local_flow_) { - if (fip_info.is_reverse_flow_) { - out_bytes_ += fip_info.bytes_; - out_packets_ += fip_info.packets_; - - if (fip_info.rev_fip_) { - /* This is the case where Source and Destination VMs (part of - * same compute node) ping to each other to their respective - * Floating IPs. In this case for each flow we need to increment - * stats for both the VMs */ - fip_info.rev_fip_->out_bytes_ += fip_info.bytes_; - fip_info.rev_fip_->out_packets_ += fip_info.packets_; - } - } else { - in_bytes_ += fip_info.bytes_; - in_packets_ += fip_info.packets_; - if (fip_info.rev_fip_) { - /* This is the case where Source and Destination VMs (part of - * same compute node) ping to each other to their respective - * Floating IPs. In this case for each flow we need to increment - * stats for both the VMs */ - fip_info.rev_fip_->in_bytes_ += fip_info.bytes_; - fip_info.rev_fip_->in_packets_ += fip_info.packets_; - } - } - } else { - if (fip_info.is_ingress_flow_) { - in_bytes_ += fip_info.bytes_; - in_packets_ += fip_info.packets_; - } else { - out_bytes_ += fip_info.bytes_; - out_packets_ += fip_info.packets_; - } - } -} - - -bool VmUveEntryBase::UveInterfaceEntry::FillFloatingIpStats - (vector &result, - vector &diff_list) { - const VmInterface *vm_intf = static_cast(intf_); - tbb::mutex::scoped_lock lock(mutex_); - if (vm_intf->HasFloatingIp()) { - const VmInterface::FloatingIpList fip_list = - vm_intf->floating_ip_list(); - VmInterface::FloatingIpSet::const_iterator it = - fip_list.list_.begin(); - while(it != fip_list.list_.end()) { - const VmInterface::FloatingIp &ip = *it; - /* Skip FIP entries which are not yet activated */ - if (!ip.installed_) { - it++; - continue; - } - VmFloatingIPStats uve_fip; - VmFloatingIPStatSamples diff_uve; - uve_fip.set_ip_address(ip.floating_ip_.to_string()); - uve_fip.set_virtual_network(ip.vn_.get()->GetName()); - uve_fip.set_iface_name(vm_intf->cfg_name()); - - diff_uve.set_ip_address(ip.floating_ip_.to_string()); - diff_uve.set_vn(ip.vn_.get()->GetName()); - diff_uve.set_iface_name(vm_intf->cfg_name()); - - FloatingIpPtr key(new FloatingIp(ip.floating_ip_, - ip.vn_.get()->GetName())); - FloatingIpSet::iterator fip_it = fip_tree_.find(key); - if (fip_it == fip_tree_.end()) { - SetStats(uve_fip, 0, 0, 0, 0); - SetDiffStats(diff_uve, 0, 0, 0, 0); - } else { - FloatingIp *fip = (*fip_it).get(); - SetStats(uve_fip, fip->in_bytes_, fip->in_packets_, - fip->out_bytes_, fip->out_packets_); - FloatingIpSet::iterator prev_it = prev_fip_tree_.find(key); - if (prev_it == prev_fip_tree_.end()) { - SetDiffStats(diff_uve, fip->in_bytes_, fip->in_packets_, - fip->out_bytes_, fip->out_packets_); - FloatingIpPtr prev_fip_ptr(new FloatingIp(ip.floating_ip_, - ip.vn_.get()->GetName(), - fip->in_bytes_, - fip->in_packets_, - fip->out_bytes_, - fip->out_packets_)); - prev_fip_tree_.insert(prev_fip_ptr); - } else { - FloatingIp *pfip = (*prev_it).get(); - SetDiffStats(diff_uve, (fip->in_bytes_ - pfip->in_bytes_), - (fip->in_packets_ - pfip->in_packets_), - (fip->out_bytes_ - pfip->out_bytes_), - (fip->out_packets_ - pfip->out_packets_)); - pfip->in_bytes_ = fip->in_bytes_; - pfip->in_packets_ = fip->in_packets_; - pfip->out_bytes_ = fip->out_bytes_; - pfip->out_packets_ = fip->out_packets_; - } - - } - result.push_back(uve_fip); - diff_list.push_back(diff_uve); - it++; - } - return true; - } - return false; -} - -void VmUveEntryBase::UveInterfaceEntry::SetDiffStats - (VmFloatingIPStatSamples &fip, uint64_t in_bytes, uint64_t in_pkts, - uint64_t out_bytes, uint64_t out_pkts) const { - fip.set_in_bytes(in_bytes); - fip.set_in_pkts(in_pkts); - fip.set_out_bytes(out_bytes); - fip.set_out_pkts(out_pkts); -} - -void VmUveEntryBase::UveInterfaceEntry::SetStats - (VmFloatingIPStats &fip, uint64_t in_bytes, uint64_t in_pkts, - uint64_t out_bytes, uint64_t out_pkts) const { - fip.set_in_bytes(in_bytes); - fip.set_in_pkts(in_pkts); - fip.set_out_bytes(out_bytes); - fip.set_out_pkts(out_pkts); -} - -void VmUveEntryBase::UveInterfaceEntry::RemoveFloatingIp - (const VmInterface::FloatingIp &fip) { - tbb::mutex::scoped_lock lock(mutex_); - FloatingIpPtr key(new FloatingIp(fip.floating_ip_, fip.vn_.get()->GetName())); - FloatingIpSet::iterator it = fip_tree_.find(key); - if (it != fip_tree_.end()) { - fip_tree_.erase(it); - } - FloatingIpSet::iterator prev_it = prev_fip_tree_.find(key); - if (prev_it != prev_fip_tree_.end()) { - prev_fip_tree_.erase(prev_it); - } -} - void VmUveEntryBase::Reset() { UveVirtualMachineAgent uve; diff --git a/src/vnsw/agent/uve/vm_uve_entry_base.h b/src/vnsw/agent/uve/vm_uve_entry_base.h index df970de5f7c..ca11bf1231a 100644 --- a/src/vnsw/agent/uve/vm_uve_entry_base.h +++ b/src/vnsw/agent/uve/vm_uve_entry_base.h @@ -24,91 +24,8 @@ //required for sending VirtualMachine UVE. class VmUveEntryBase { public: - struct FloatingIp; - struct FipInfo { - uint64_t bytes_; - uint64_t packets_; - uint32_t fip_; - uint32_t fip_vm_port_id_; - bool is_local_flow_; - bool is_ingress_flow_; - bool is_reverse_flow_; - std::string vn_; - FloatingIp *rev_fip_; - }; - struct FloatingIp { - FloatingIp(const IpAddress &ip, const std::string &vn) - : family_(ip.is_v4() ? Address::INET : Address::INET6), - fip_(ip), vn_(vn) { - in_bytes_ = 0; - in_packets_ = 0; - out_bytes_ = 0; - out_packets_ = 0; - } - FloatingIp(const IpAddress &ip, const std::string &vn, uint64_t in_b, - uint64_t in_p, uint64_t out_b, uint64_t out_p) - : family_(ip.is_v4() ? Address::INET : Address::INET6), - fip_(ip), vn_(vn), in_bytes_(in_b), in_packets_(in_p), - out_bytes_(out_b), out_packets_(out_p) { - } - void UpdateFloatingIpStats(const FipInfo &fip_info); - - Address::Family family_; - IpAddress fip_; - std::string vn_; - uint64_t in_bytes_; - uint64_t in_packets_; - uint64_t out_bytes_; - uint64_t out_packets_; - }; - typedef boost::shared_ptr FloatingIpPtr; - - class FloatingIpCmp { - public: - bool operator()(const FloatingIpPtr &lhs, - const FloatingIpPtr &rhs) const { - if (lhs.get()->fip_ != rhs.get()->fip_) { - return lhs.get()->fip_ < rhs.get()->fip_; - } - return (lhs.get()->vn_ < rhs.get()->vn_); - } - }; - typedef std::set FloatingIpSet; - - struct UveInterfaceEntry { - const Interface *intf_; - L4PortBitmap port_bitmap_; - FloatingIpSet fip_tree_; - FloatingIpSet prev_fip_tree_; - /* For exclusion between Agent::StatsCollector and Agent::Uve tasks */ - tbb::mutex mutex_; - - UveInterfaceEntry(const Interface *i) : intf_(i), port_bitmap_(), - fip_tree_(), prev_fip_tree_() { } - virtual ~UveInterfaceEntry() {} - void UpdateFloatingIpStats(const FipInfo &fip_info); - bool FillFloatingIpStats(vector &result, - vector &diff_list); - void SetStats(VmFloatingIPStats &fip, uint64_t in_bytes, - uint64_t in_pkts, uint64_t out_bytes, uint64_t out_pkts) const; - void SetDiffStats(VmFloatingIPStatSamples &fip, uint64_t in_bytes, - uint64_t in_pkts, uint64_t out_bytes, uint64_t out_pkts) const; - void RemoveFloatingIp(const VmInterface::FloatingIp &fip); - VmUveEntryBase::FloatingIp *FipEntry(uint32_t ip, const std::string &vn); - }; - typedef boost::shared_ptr UveInterfaceEntryPtr; - - class UveInterfaceEntryCmp { - public: - bool operator()(const UveInterfaceEntryPtr &lhs, - const UveInterfaceEntryPtr &rhs) const { - if (lhs.get()->intf_ < rhs.get()->intf_) - return true; - return false; - } - }; - typedef std::set InterfaceSet; + typedef std::set InterfaceSet; VmUveEntryBase(Agent *agent, const std::string &vm_name); virtual ~VmUveEntryBase(); @@ -116,9 +33,8 @@ class VmUveEntryBase { bool add_by_vm_notify() const { return add_by_vm_notify_; } void set_add_by_vm_notify(bool value) { add_by_vm_notify_ = value; } - void InterfaceAdd(const Interface *intf, - const VmInterface::FloatingIpSet &olist); - void InterfaceDelete(const Interface *intf); + void InterfaceAdd(const std::string &intf_cfg_name); + void InterfaceDelete(const std::string &intf_cfg_name); bool FrameVmMsg(const boost::uuids::uuid &u, UveVirtualMachineAgent *uve); bool Update(const VmEntry *vm); void set_changed(bool val) { changed_ = val; } @@ -139,11 +55,8 @@ class VmUveEntryBase { bool renewed_; private: bool UveVmInterfaceListChanged - (const std::vector &new_l) const; + (const std::vector &new_l) const; bool UveVmVRouterChanged(const std::string &new_value) const; - bool FrameInterfaceMsg(const VmInterface *intf, VmInterfaceAgent *itf) - const; - bool GetVmInterfaceGateway(const VmInterface *intf, std::string &gw) const; bool add_by_vm_notify_; std::string vm_config_name_; diff --git a/src/vnsw/agent/uve/vm_uve_table.cc b/src/vnsw/agent/uve/vm_uve_table.cc index 66c68bf3c0e..07822aef1c4 100644 --- a/src/vnsw/agent/uve/vm_uve_table.cc +++ b/src/vnsw/agent/uve/vm_uve_table.cc @@ -61,19 +61,14 @@ void VmUveTable::SendVmStatsMsg(const boost::uuids::uuid &u) { return; } UveVirtualMachineAgent uve; - VirtualMachineStats stats_uve; - bool stats_uve_send = false; /* Two VM UVEs will be sent for all VM stats. VirtualMachineStats will * have VM stats and UveVirtualMachineAgent will have port bitmap for VM * and all its containing interfaces */ - bool send = entry->FrameVmStatsMsg(&uve, &stats_uve, &stats_uve_send); + bool send = entry->FrameVmStatsMsg(&uve); if (send) { DispatchVmMsg(uve); } - if (stats_uve_send) { - DispatchVmStatsMsg(stats_uve); - } } void VmUveTable::VmStatCollectionStart(VmUveVmState *state, const VmEntry *vm) { diff --git a/src/vnsw/agent/uve/vm_uve_table_base.cc b/src/vnsw/agent/uve/vm_uve_table_base.cc index 3ffe6067510..b264f86a95a 100644 --- a/src/vnsw/agent/uve/vm_uve_table_base.cc +++ b/src/vnsw/agent/uve/vm_uve_table_base.cc @@ -154,22 +154,22 @@ void VmUveTableBase::MarkChanged(const boost::uuids::uuid &u) { return; } -void VmUveTableBase::InterfaceAddHandler(const VmEntry* vm, const Interface* itf, - const VmInterface::FloatingIpSet &old_list) { +void VmUveTableBase::InterfaceAddHandler(const VmEntry* vm, + const string &intf_cfg_name) { VmUveEntryBase *vm_uve_entry = Add(vm, false); - vm_uve_entry->InterfaceAdd(itf, old_list); + vm_uve_entry->InterfaceAdd(intf_cfg_name); vm_uve_entry->set_changed(true); } void VmUveTableBase::InterfaceDeleteHandler(const boost::uuids::uuid &u, - const Interface* intf) { + const string &intf_cfg_name) { VmUveEntryBase* entry = UveEntryFromVm(u); if (entry == NULL) { return; } - entry->InterfaceDelete(intf); + entry->InterfaceDelete(intf_cfg_name); entry->set_changed(true); } @@ -184,31 +184,38 @@ void VmUveTableBase::InterfaceNotify(DBTablePartBase *partition, (e->GetState(partition->parent(), intf_listener_id_)); if (e->IsDeleted() || ((vm_port->vm() == NULL))) { if (state) { - InterfaceDeleteHandler(state->vm_uuid_, vm_port); - state->fip_list_.clear(); - if (e->IsDeleted()) { - e->ClearState(partition->parent(), intf_listener_id_); - delete state; - } + InterfaceDeleteHandler(state->vm_uuid_, state->interface_cfg_name_); + e->ClearState(partition->parent(), intf_listener_id_); + delete state; } } else { const VmEntry *vm = vm_port->vm(); VmInterface::FloatingIpSet old_list; if (!state) { - state = new VmUveInterfaceState(vm->GetUuid(), - vm_port->floating_ip_list().list_); + /* Skip Add notification if it does not have config name */ + if (vm_port->cfg_name().empty()) { + return; + } + state = new VmUveInterfaceState(nil_uuid(), ""); e->SetState(partition->parent(), intf_listener_id_, state); - } else { - old_list = state->fip_list_; - state->fip_list_ = vm_port->floating_ip_list().list_; } /* Handle Change of VM in a given VM interface */ - if (vm->GetUuid() != state->vm_uuid_) { + if ((vm->GetUuid() != state->vm_uuid_) || + (vm_port->cfg_name() != state->interface_cfg_name_)) { //Handle disassociation of old VM from the VMI - InterfaceDeleteHandler(state->vm_uuid_, vm_port); + if (state->vm_uuid_ != nil_uuid() && + !state->interface_cfg_name_.empty()) { + InterfaceDeleteHandler(state->vm_uuid_, + state->interface_cfg_name_); + } + if (vm->GetUuid() != nil_uuid() && + !vm_port->cfg_name().empty()) { + InterfaceAddHandler(vm, vm_port->cfg_name()); + } + state->vm_uuid_ = vm->GetUuid(); + state->interface_cfg_name_ = vm_port->cfg_name(); } - InterfaceAddHandler(vm, vm_port, old_list); } } diff --git a/src/vnsw/agent/uve/vm_uve_table_base.h b/src/vnsw/agent/uve/vm_uve_table_base.h index 4c63276098c..01fe44de2e2 100644 --- a/src/vnsw/agent/uve/vm_uve_table_base.h +++ b/src/vnsw/agent/uve/vm_uve_table_base.h @@ -30,10 +30,10 @@ class VmUveTableBase { public: struct VmUveInterfaceState :public DBState { VmUveInterfaceState(const boost::uuids::uuid u, - const VmInterface::FloatingIpSet &fip_l) - : vm_uuid_(u), fip_list_(fip_l) {} + const std::string cfg_name) + : vm_uuid_(u), interface_cfg_name_(cfg_name) {} boost::uuids::uuid vm_uuid_; - VmInterface::FloatingIpSet fip_list_; + std::string interface_cfg_name_; }; class VmUveVmState: public DBState { @@ -64,10 +64,9 @@ class VmUveTableBase { virtual VmUveEntryPtr Allocate(const VmEntry *vm); void InterfaceNotify(DBTablePartBase *partition, DBEntryBase *e); void VmNotify(DBTablePartBase *partition, DBEntryBase *e); - void InterfaceAddHandler(const VmEntry* vm, const Interface* intf, - const VmInterface::FloatingIpSet &old_list); + void InterfaceAddHandler(const VmEntry* vm, const std::string &if_cfg_name); void InterfaceDeleteHandler(const boost::uuids::uuid &u, - const Interface* intf); + const std::string &intf_cfg_name); void MarkChanged(const boost::uuids::uuid &u); VmUveEntryBase* Add(const VmEntry *vm, bool vm_notify); void Delete(const boost::uuids::uuid &u); diff --git a/src/vnsw/agent/uve/vn_uve_entry.cc b/src/vnsw/agent/uve/vn_uve_entry.cc index b45c55115fd..f8905430318 100644 --- a/src/vnsw/agent/uve/vn_uve_entry.cc +++ b/src/vnsw/agent/uve/vn_uve_entry.cc @@ -94,34 +94,6 @@ bool VnUveEntry::UveVnFipCountChanged(int32_t size) const { return false; } -bool VnUveEntry::UveVnInterfaceInStatsChanged(uint64_t bytes, uint64_t pkts) - const { - if (!uve_info_.__isset.in_bytes || !uve_info_.__isset.in_tpkts) { - return true; - } - uint64_t bytes2 = (uint64_t)uve_info_.get_in_bytes(); - uint64_t pkts2 = (uint64_t)uve_info_.get_in_tpkts(); - - if ((bytes != bytes2) || (pkts != pkts2)) { - return true; - } - return false; -} - -bool VnUveEntry::UveVnInterfaceOutStatsChanged(uint64_t bytes, uint64_t pkts) - const { - if (!uve_info_.__isset.out_bytes || !uve_info_.__isset.out_tpkts) { - return true; - } - uint64_t bytes2 = (uint64_t)uve_info_.get_out_bytes(); - uint64_t pkts2 = (uint64_t)uve_info_.get_out_tpkts(); - - if ((bytes != bytes2) || (pkts != pkts2)) { - return true; - } - return false; -} - bool VnUveEntry::UveVnInBandChanged(uint64_t in_band) const { if (!uve_info_.__isset.in_bandwidth_usage) { return true; @@ -344,9 +316,7 @@ bool VnUveEntry::FrameVnStatsMsg(const VnEntry *vn, assert(!deleted_); uve.set_name(vn->GetName()); - uint64_t in_pkts = 0; uint64_t in_bytes = 0; - uint64_t out_pkts = 0; uint64_t out_bytes = 0; if (UpdateVrfStats(vn, uve)) { @@ -365,36 +335,10 @@ bool VnUveEntry::FrameVnStatsMsg(const VnEntry *vn, const VmInterface *vm_port = static_cast(intf); fip_count += vm_port->GetFloatingIpCount(); - - AgentUve *uve = static_cast(agent_->uve()); - const StatsManager::InterfaceStats *s = - uve->stats_manager()->GetInterfaceStats(intf); - if (s == NULL) { - continue; - } - in_pkts += s->in_pkts; - in_bytes += s->in_bytes; - out_pkts += s->out_pkts; - out_bytes += s->out_bytes; } uint64_t diff_in_bytes = 0; - if (UveVnInterfaceInStatsChanged(in_bytes, in_pkts)) { - uve.set_in_tpkts(in_pkts); - uve.set_in_bytes(in_bytes); - uve_info_.set_in_tpkts(in_pkts); - uve_info_.set_in_bytes(in_bytes); - changed = true; - } - uint64_t diff_out_bytes = 0; - if (UveVnInterfaceOutStatsChanged(out_bytes, out_pkts)) { - uve.set_out_tpkts(out_pkts); - uve.set_out_bytes(out_bytes); - uve_info_.set_out_tpkts(out_pkts); - uve_info_.set_out_bytes(out_bytes); - changed = true; - } uint64_t diff_seconds = 0; uint64_t cur_time = UTCTimestampUsec(); diff --git a/src/vnsw/agent/uve/vn_uve_entry.h b/src/vnsw/agent/uve/vn_uve_entry.h index 519dffcb10b..66a4355df35 100644 --- a/src/vnsw/agent/uve/vn_uve_entry.h +++ b/src/vnsw/agent/uve/vn_uve_entry.h @@ -75,8 +75,6 @@ class VnUveEntry : public VnUveEntryBase { private: bool SetVnPortBitmap(UveVirtualNetworkAgent &uve); - bool UveVnInterfaceInStatsChanged(uint64_t bytes, uint64_t pkts) const; - bool UveVnInterfaceOutStatsChanged(uint64_t bytes, uint64_t pkts) const; bool UveVnInBandChanged(uint64_t out_band) const; bool UveVnOutBandChanged(uint64_t out_band) const; bool UpdateVnFlowCount(const VnEntry *vn, UveVirtualNetworkAgent &s_vn); diff --git a/src/vnsw/agent/uve/vn_uve_entry_base.cc b/src/vnsw/agent/uve/vn_uve_entry_base.cc index 02b174819e4..9db7ee44b2d 100644 --- a/src/vnsw/agent/uve/vn_uve_entry_base.cc +++ b/src/vnsw/agent/uve/vn_uve_entry_base.cc @@ -209,16 +209,6 @@ bool VnUveEntryBase::FrameVnMsg(const VnEntry *vn, UveVirtualNetworkAgent &uve) return changed; } -void VnUveEntryBase::GetInStats(uint64_t *in_bytes, uint64_t *in_pkts) const { - *in_bytes = uve_info_.get_in_bytes(); - *in_pkts = uve_info_.get_in_tpkts(); -} - -void VnUveEntryBase::GetOutStats(uint64_t *out_bytes, uint64_t *out_pkts) const { - *out_bytes = uve_info_.get_out_bytes(); - *out_pkts = uve_info_.get_out_tpkts(); -} - void VnUveEntryBase::Reset() { UveVirtualNetworkAgent uve; diff --git a/src/vnsw/agent/uve/vn_uve_entry_base.h b/src/vnsw/agent/uve/vn_uve_entry_base.h index 5808c456a29..f7d25e861f8 100644 --- a/src/vnsw/agent/uve/vn_uve_entry_base.h +++ b/src/vnsw/agent/uve/vn_uve_entry_base.h @@ -39,8 +39,6 @@ class VnUveEntryBase { bool BuildInterfaceVmList(UveVirtualNetworkAgent &s_vn); bool FrameVnMsg(const VnEntry *vn, UveVirtualNetworkAgent &uve); const VnEntry *vn() const { return vn_; } - void GetInStats(uint64_t *in_bytes, uint64_t *in_pkts) const; - void GetOutStats(uint64_t *out_bytes, uint64_t *out_pkts) const; bool FrameVnAclRuleCountMsg(const VnEntry *vn, UveVirtualNetworkAgent *uve); diff --git a/src/vnsw/agent/vrouter/flow_stats/flow_stats_collector.cc b/src/vnsw/agent/vrouter/flow_stats/flow_stats_collector.cc index a7d0439e8da..0145d2d5f27 100644 --- a/src/vnsw/agent/vrouter/flow_stats/flow_stats_collector.cc +++ b/src/vnsw/agent/vrouter/flow_stats/flow_stats_collector.cc @@ -19,6 +19,7 @@ #include #include #include +#include #include #include #include @@ -114,7 +115,7 @@ uint64_t FlowStatsCollector::GetUpdatedFlowPackets(const FlowStats *stats, void FlowStatsCollector::UpdateFloatingIpStats(const FlowEntry *flow, uint64_t bytes, uint64_t pkts) { - VmUveEntry::FipInfo fip_info; + InterfaceUveTable::FipInfo fip_info; /* Ignore Non-Floating-IP flow */ if (!flow->stats().fip || @@ -122,13 +123,8 @@ void FlowStatsCollector::UpdateFloatingIpStats(const FlowEntry *flow, return; } - VmUveTable *vm_table = static_cast - (agent_uve_->vm_uve_table()); - VmUveEntry *entry = vm_table->InterfaceIdToVmUveEntry - (flow->stats().fip_vm_port_id); - if (entry == NULL) { - return; - } + InterfaceUveStatsTable *table = static_cast + (agent_uve_->interface_uve_table()); fip_info.bytes_ = bytes; fip_info.packets_ = pkts; @@ -148,21 +144,20 @@ void FlowStatsCollector::UpdateFloatingIpStats(const FlowEntry *flow, fip_info.rev_fip_ = ReverseFlowFip(flow); } - entry->UpdateFloatingIpStats(fip_info); + table->UpdateFloatingIpStats(fip_info); } -VmUveEntry::FloatingIp *FlowStatsCollector::ReverseFlowFip +InterfaceUveTable::FloatingIp *FlowStatsCollector::ReverseFlowFip (const FlowEntry *flow) { uint32_t fip = flow->reverse_flow_fip(); const string &vn = flow->data().source_vn; uint32_t intf_id = flow->reverse_flow_vmport_id(); Interface *intf = InterfaceTable::GetInstance()->FindInterface(intf_id); - VmUveTable *vm_table = static_cast - (agent_uve_->vm_uve_table()); - VmUveEntry *entry = vm_table->InterfaceIdToVmUveEntry(intf_id); - if (entry != NULL) { - return entry->FipEntry(fip, vn, intf); + if (intf) { + InterfaceUveStatsTable *table = static_cast + (agent_uve_->interface_uve_table()); + return table->FipEntry(fip, vn, intf); } return NULL; } diff --git a/src/vnsw/agent/vrouter/flow_stats/flow_stats_collector.h b/src/vnsw/agent/vrouter/flow_stats/flow_stats_collector.h index bc3b823e258..9a3e649e4fe 100644 --- a/src/vnsw/agent/vrouter/flow_stats/flow_stats_collector.h +++ b/src/vnsw/agent/vrouter/flow_stats/flow_stats_collector.h @@ -7,7 +7,7 @@ #include #include -#include +#include #include #include @@ -55,7 +55,7 @@ class FlowStatsCollector : public StatsCollector { uint64_t curr_time); uint64_t GetUpdatedFlowPackets(const FlowStats *stats, uint64_t k_flow_pkts); uint64_t GetUpdatedFlowBytes(const FlowStats *stats, uint64_t k_flow_bytes); - VmUveEntry::FloatingIp *ReverseFlowFip(const FlowEntry *flow); + InterfaceUveTable::FloatingIp *ReverseFlowFip(const FlowEntry *flow); AgentUveBase *agent_uve_; FlowKey flow_iteration_key_; uint64_t flow_age_time_intvl_; diff --git a/src/vnsw/agent/vrouter/stats_collector/agent_stats_collector.cc b/src/vnsw/agent/vrouter/stats_collector/agent_stats_collector.cc index 7743a9773a2..1c8e0ab25bb 100644 --- a/src/vnsw/agent/vrouter/stats_collector/agent_stats_collector.cc +++ b/src/vnsw/agent/vrouter/stats_collector/agent_stats_collector.cc @@ -18,6 +18,7 @@ #include #include #include +#include #include #include #include @@ -128,6 +129,10 @@ void AgentStatsCollector::SendStats() { VmUveTable *vmt = static_cast (agent_->uve()->vm_uve_table()); vmt->SendVmStats(); + + InterfaceUveStatsTable *it = static_cast + (agent_->uve()->interface_uve_table()); + it->SendInterfaceStats(); } void AgentStatsCollector::Shutdown(void) {