From aeb18951dd7a3f2f70dad6fa17c8ae0a688ce72b Mon Sep 17 00:00:00 2001 From: ashoksingh Date: Thu, 30 Apr 2015 14:28:18 +0530 Subject: [PATCH] Send Interface information in UVE of its own. -Defined new UVEs for VM interface, Logical interface and Physical interface. The parent object for these interfaces will have only the key value. All the attributes for interfaces will go in UVE of its own. -Update VM UVE to send only keys of VMIs belonging to VM -Update VN UVE to not send aggregate statistics per VN. This is not required because VM Interface UVE stats can now be queried on a per VN basis. -Update Prouter UVE to send only keys in lists of logical_interface and physical_interface -Update viz.sandesh to define new tables for new UVEs (changes on behalf of sundar) Partial-Bug: #1449433 (cherry picked from commit 49371d81ac36d21f987e5318f786bb5f6da18ee2) Change-Id: I0e096a8b27cf5e9247b89ef7dbbdcb68131d5067 --- src/analytics/viz.sandesh | 52 + src/base/timer.h | 4 + src/vnsw/agent/test/SConscript | 1 + src/vnsw/agent/test/test_util.cc | 22 - src/vnsw/agent/uve/SConscript | 5 +- src/vnsw/agent/uve/agent_uve.cc | 3 + src/vnsw/agent/uve/agent_uve_base.cc | 4 + src/vnsw/agent/uve/agent_uve_base.h | 9 +- src/vnsw/agent/uve/interface.sandesh | 59 ++ .../agent/uve/interface_uve_stats_table.cc | 176 ++++ .../agent/uve/interface_uve_stats_table.h | 40 + src/vnsw/agent/uve/interface_uve_table.cc | 466 +++++++++ src/vnsw/agent/uve/interface_uve_table.h | 159 +++ src/vnsw/agent/uve/prouter.sandesh | 40 +- src/vnsw/agent/uve/prouter_uve_table.cc | 524 ++++++---- src/vnsw/agent/uve/prouter_uve_table.h | 98 +- src/vnsw/agent/uve/test/SConscript | 2 + src/vnsw/agent/uve/test/agent_uve_test.cc | 5 + .../uve/test/interface_uve_table_test.cc | 73 ++ .../agent/uve/test/interface_uve_table_test.h | 31 + .../agent/uve/test/prouter_uve_table_test.cc | 38 + .../agent/uve/test/prouter_uve_table_test.h | 16 + src/vnsw/agent/uve/test/test_interface_uve.cc | 935 ++++++++++++++++++ src/vnsw/agent/uve/test/test_port_bitmap.cc | 8 +- src/vnsw/agent/uve/test/test_prouter_uve.cc | 335 ++++++- src/vnsw/agent/uve/test/test_stats_mock.cc | 43 - src/vnsw/agent/uve/test/test_uve_util.h | 17 + src/vnsw/agent/uve/test/test_vm_uve.cc | 569 +---------- src/vnsw/agent/uve/test/test_vn_uve.cc | 66 -- src/vnsw/agent/uve/test/vm_uve_entry_test.h | 31 - src/vnsw/agent/uve/test/vm_uve_table_test.cc | 33 - src/vnsw/agent/uve/test/vm_uve_table_test.h | 4 - src/vnsw/agent/uve/virtual_machine.sandesh | 70 +- src/vnsw/agent/uve/virtual_network.sandesh | 4 - src/vnsw/agent/uve/vm_uve_entry.cc | 173 +--- src/vnsw/agent/uve/vm_uve_entry.h | 16 +- src/vnsw/agent/uve/vm_uve_entry_base.cc | 294 +----- src/vnsw/agent/uve/vm_uve_entry_base.h | 95 +- src/vnsw/agent/uve/vm_uve_table.cc | 7 +- src/vnsw/agent/uve/vm_uve_table_base.cc | 45 +- src/vnsw/agent/uve/vm_uve_table_base.h | 11 +- src/vnsw/agent/uve/vn_uve_entry.cc | 56 -- src/vnsw/agent/uve/vn_uve_entry.h | 2 - src/vnsw/agent/uve/vn_uve_entry_base.cc | 10 - src/vnsw/agent/uve/vn_uve_entry_base.h | 2 - .../flow_stats/flow_stats_collector.cc | 25 +- .../vrouter/flow_stats/flow_stats_collector.h | 4 +- .../stats_collector/agent_stats_collector.cc | 5 + 48 files changed, 2865 insertions(+), 1822 deletions(-) create mode 100644 src/vnsw/agent/uve/interface.sandesh create mode 100644 src/vnsw/agent/uve/interface_uve_stats_table.cc create mode 100644 src/vnsw/agent/uve/interface_uve_stats_table.h create mode 100644 src/vnsw/agent/uve/interface_uve_table.cc create mode 100644 src/vnsw/agent/uve/interface_uve_table.h create mode 100644 src/vnsw/agent/uve/test/interface_uve_table_test.cc create mode 100644 src/vnsw/agent/uve/test/interface_uve_table_test.h create mode 100644 src/vnsw/agent/uve/test/test_interface_uve.cc 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) {