Line data Source code
1 : /* 2 : * Copyright (c) 2015 Juniper Networks, Inc. All rights reserved. 3 : */ 4 : 5 : #include <oper/interface_common.h> 6 : #include <uve/interface_uve_stats_table.h> 7 : #include <uve/agent_uve_stats.h> 8 : 9 6 : InterfaceUveStatsTable::InterfaceUveStatsTable(Agent *agent, 10 6 : uint32_t default_intvl) 11 6 : : InterfaceUveTable(agent, default_intvl) { 12 6 : } 13 : 14 9 : InterfaceUveStatsTable::~InterfaceUveStatsTable() { 15 9 : } 16 : 17 0 : bool InterfaceUveStatsTable::FrameInterfaceObjectLog(UveInterfaceEntry* entry, 18 : EndpointSecurityStats *obj) const { 19 0 : assert(!entry->deleted_); 20 0 : const VmInterface *vm_intf = entry->intf_; 21 0 : if (vm_intf->cfg_name().empty()) { 22 0 : return false; 23 : } 24 0 : entry->FillEndpointStats(agent_, obj); 25 0 : return true; 26 : } 27 : 28 0 : bool InterfaceUveStatsTable::FrameInterfaceStatsMsg(UveInterfaceEntry* entry, 29 : VMIStats *uve) const { 30 0 : uint64_t in_band = 0, out_band = 0; 31 0 : bool diff_fip_list_non_zero = false; 32 0 : VmInterfaceStats if_stats; 33 0 : vector<VmFloatingIPStats> agg_fip_list; 34 0 : vector<VmFloatingIPStats> diff_fip_list; 35 : 36 0 : const VmInterface *vm_intf = entry->intf_; 37 0 : assert(!entry->deleted_); 38 0 : if (vm_intf->cfg_name().empty()) { 39 0 : return false; 40 : } 41 0 : uve->set_name(vm_intf->cfg_name()); 42 0 : entry->SetVMIStatsVnVm(uve); 43 : 44 0 : const Interface *intf = static_cast<const Interface *>(vm_intf); 45 0 : AgentUveStats *agent_uve = static_cast<AgentUveStats *>(agent_->uve()); 46 : StatsManager::InterfaceStats *s = 47 0 : agent_uve->stats_manager()->GetInterfaceStats(intf); 48 0 : if (s == NULL) { 49 0 : return false; 50 : } 51 : 52 0 : AgentDropStats ds; 53 0 : agent_uve->stats_manager()->BuildDropStats(s->drop_stats, ds); 54 0 : uve->set_raw_drop_stats(ds); 55 : 56 : /* Send aggregate interface stats always */ 57 0 : if_stats.set_in_pkts(s->in_pkts); 58 0 : if_stats.set_in_bytes(s->in_bytes); 59 0 : if_stats.set_out_pkts(s->out_pkts); 60 0 : if_stats.set_out_bytes(s->out_bytes); 61 0 : uve->set_raw_if_stats(if_stats); 62 : 63 : /* Compute bandwidth only if there is change in statistics */ 64 : uint64_t in_b, out_b; 65 0 : s->GetDiffStats(&in_b, &out_b); 66 0 : if ((in_b != 0) || (out_b != 0)) { 67 0 : in_band = GetVmPortBandwidth(s, true); 68 0 : out_band = GetVmPortBandwidth(s, false); 69 : } 70 : 71 0 : if (entry->InBandChanged(in_band)) { 72 0 : uve->set_in_bw_usage(in_band); 73 0 : entry->uve_stats_.set_in_bw_usage(in_band); 74 : } 75 0 : if (entry->OutBandChanged(out_band)) { 76 0 : uve->set_out_bw_usage(out_band); 77 0 : entry->uve_stats_.set_out_bw_usage(out_band); 78 : } 79 0 : s->stats_time = UTCTimestampUsec(); 80 : 81 : /* Make sure that update of prev_in_bytes and prev_out_bytes are done only 82 : * after GetVmPortBandwidth is done for both directions as they get used 83 : * in those APIs. */ 84 0 : s->UpdatePrevStats(); 85 : 86 0 : PortBucketBitmap map; 87 0 : L4PortBitmap &port_bmap = entry->port_bitmap_; 88 0 : port_bmap.Encode(map); 89 0 : if (entry->PortBitmapChanged(map)) { 90 0 : uve->set_port_bucket_bmap(map); 91 0 : entry->uve_stats_.set_port_bucket_bmap(map); 92 : } 93 : 94 0 : FrameFipStatsMsg(vm_intf, agg_fip_list, diff_fip_list, 95 : diff_fip_list_non_zero); 96 0 : if (entry->FipAggStatsChanged(agg_fip_list)) { 97 0 : uve->set_fip_agg_stats(agg_fip_list); 98 0 : entry->uve_stats_.set_fip_agg_stats(agg_fip_list); 99 : } 100 : /* Diff stats need not be sent if the value of the stats is 0. 101 : * If any of the entry in diff_fip_list has non-zero stats, then 102 : * diff_fip_list_non_zero is expected to be true */ 103 0 : if (diff_fip_list_non_zero) { 104 0 : uve->set_fip_diff_stats(diff_fip_list); 105 : } 106 : 107 0 : VrouterFlowRate flow_rate; 108 0 : uint64_t created = 0, aged = 0; 109 0 : uint32_t active_flows = 0; 110 0 : agent_->pkt()->get_flow_proto()->InterfaceFlowCount(vm_intf, &created, 111 : &aged, &active_flows); 112 0 : bool built = agent_uve->stats_manager()->BuildFlowRate(s->added, s->deleted, 113 0 : s->flow_info, 114 : flow_rate); 115 0 : if (built) { 116 0 : flow_rate.set_active_flows(active_flows); 117 0 : uve->set_flow_rate(flow_rate); 118 : } 119 : /* Populate TagSet and policy-list in UVE */ 120 0 : entry->FillTagSetAndPolicyList(uve); 121 : 122 0 : return true; 123 0 : } 124 : 125 0 : void InterfaceUveStatsTable::SendInterfaceStatsMsg(UveInterfaceEntry* entry) { 126 0 : if (entry->deleted_) { 127 0 : return; 128 : } 129 0 : VMIStats uve; 130 : 131 0 : bool send = FrameInterfaceStatsMsg(entry, &uve); 132 0 : if (send) { 133 0 : DispatchVMIStatsMsg(uve); 134 : } 135 0 : EndpointSecurityStats *obj_log = ENDPOINT_SECURITY_STATS_CREATE(); 136 0 : send = FrameInterfaceObjectLog(entry, obj_log); 137 0 : if (send) { 138 0 : DispatchInterfaceObjectLog(obj_log); 139 : } 140 0 : } 141 : 142 0 : void InterfaceUveStatsTable::SendInterfaceStats(void) { 143 0 : InterfaceMap::iterator it = interface_tree_.begin(); 144 0 : while (it != interface_tree_.end()) { 145 0 : UveInterfaceEntry* entry = it->second.get(); 146 : { 147 0 : std::scoped_lock lock(entry->mutex_); 148 0 : SendInterfaceStatsMsg(entry); 149 0 : } 150 0 : it++; 151 : } 152 0 : } 153 : 154 0 : uint64_t InterfaceUveStatsTable::GetVmPortBandwidth 155 : (StatsManager::InterfaceStats *s, bool dir_in) const { 156 0 : if (s->stats_time == 0) { 157 0 : return 0; 158 : } 159 : uint64_t bits; 160 0 : if (dir_in) { 161 0 : bits = (s->in_bytes - s->prev_in_bytes) * 8; 162 : } else { 163 0 : bits = (s->out_bytes - s->prev_out_bytes) * 8; 164 : } 165 0 : uint64_t cur_time = UTCTimestampUsec(); 166 0 : uint64_t b_intvl = agent_->uve()->bandwidth_intvl(); 167 0 : uint64_t diff_seconds = (cur_time - s->stats_time) / b_intvl; 168 0 : if (diff_seconds == 0) { 169 0 : return 0; 170 : } 171 0 : return bits/diff_seconds; 172 : } 173 : 174 0 : void InterfaceUveStatsTable::UpdateFloatingIpStats(const FipInfo &fip_info) { 175 0 : Interface *intf = dynamic_cast<Interface *> 176 0 : (agent_->interface_table()->FindActiveEntry(&fip_info.fip_vmi_)); 177 0 : if (intf == NULL) { 178 0 : return; 179 : } 180 0 : std::scoped_lock lock(interface_tree_mutex_); 181 0 : VmInterface *vmi = static_cast<VmInterface *>(intf); 182 0 : InterfaceMap::iterator intf_it = interface_tree_.find(vmi->cfg_name()); 183 : 184 : /* 185 : * 1. VM interface with floating-ip becomes active 186 : * 2. Flow is created on this interface and interface floating ip info is 187 : * stored in flow record 188 : * 3. VM Interface is disassociated from VM 189 : * 4. VM Interface info is removed from interface_tree_ because of 190 : * disassociation 191 : * 5. FlowStats collection task initiates export of flow stats 192 : * 6. Since interface is absent in interface_tree_ we cannot update 193 : * stats in this case 194 : */ 195 0 : if (intf_it != interface_tree_.end()) { 196 0 : UveInterfaceEntry *entry = intf_it->second.get(); 197 0 : entry->UpdateFloatingIpStats(fip_info); 198 : } 199 0 : } 200 : 201 0 : bool InterfaceUveStatsTable::FrameFipStatsMsg(const VmInterface *itf, 202 : vector<VmFloatingIPStats> &fip_list, 203 : vector<VmFloatingIPStats> &diff_list, 204 : bool &diff_list_send) const { 205 0 : bool changed = false; 206 0 : diff_list_send = false; 207 0 : InterfaceMap::const_iterator it = interface_tree_.find(itf->cfg_name()); 208 : 209 0 : if (it != interface_tree_.end()) { 210 0 : UveInterfaceEntry *entry = it->second.get(); 211 0 : changed = entry->FillFloatingIpStats(fip_list, diff_list, 212 : diff_list_send); 213 : } 214 0 : return changed; 215 : } 216 : 217 : 218 52 : void InterfaceUveStatsTable::UpdatePortBitmap 219 : (const string &name, uint8_t proto, uint16_t sport, uint16_t dport) { 220 52 : std::scoped_lock lock(interface_tree_mutex_); 221 52 : InterfaceMap::const_iterator it = interface_tree_.find(name); 222 : 223 52 : if (it != interface_tree_.end()) { 224 52 : UveInterfaceEntry *entry = it->second.get(); 225 52 : entry->UpdatePortBitmap(proto, sport, dport); 226 : } 227 52 : } 228 : 229 0 : InterfaceUveTable::FloatingIp * InterfaceUveStatsTable::FipEntry 230 : (uint32_t fip, const string &vn, Interface *intf) { 231 0 : std::scoped_lock lock(interface_tree_mutex_); 232 0 : VmInterface *vmi = static_cast<VmInterface *>(intf); 233 0 : InterfaceMap::iterator intf_it = interface_tree_.find(vmi->cfg_name()); 234 : 235 0 : if (intf_it == interface_tree_.end()) { 236 0 : return NULL; 237 : } 238 : 239 0 : UveInterfaceEntry *entry = intf_it->second.get(); 240 0 : return entry->FipEntry(fip, vn); 241 0 : } 242 : 243 68 : void InterfaceUveStatsTable::IncrInterfaceAceStats 244 : (const FlowUveStatsRequest *req) { 245 68 : if (!req->sg_info_valid()) { 246 10 : return; 247 : } 248 58 : InterfaceMap::iterator intf_it = interface_tree_.find(req->interface()); 249 : 250 58 : if (intf_it != interface_tree_.end()) { 251 58 : UveInterfaceEntry *entry = intf_it->second.get(); 252 58 : entry->UpdateInterfaceAceStats(req->sg_rule_uuid()); 253 : } 254 : } 255 : 256 88 : bool InterfaceUveStatsTable::IncrInterfaceEndpointHits(const string &itf, 257 : const FlowUveFwPolicyInfo &info) { 258 88 : if (!info.is_valid_) { 259 15 : return false; 260 : } 261 73 : InterfaceMap::iterator intf_it = interface_tree_.find(itf); 262 : 263 73 : if (intf_it != interface_tree_.end()) { 264 73 : UveInterfaceEntry *entry = intf_it->second.get(); 265 : /* We don't send EndpointSecurityStats objectlog for deleted interfaces. 266 : * So, there is no need to update stats on deleted interfaces */ 267 73 : if (entry->deleted_) { 268 67 : return false; 269 : } 270 6 : entry->UpdateInterfaceFwPolicyStats(info); 271 6 : return true; 272 : } 273 0 : return false; 274 : } 275 : 276 0 : void InterfaceUveStatsTable::SendInterfaceAceStats(const string &name, 277 : UveInterfaceEntry *entry) { 278 0 : VMIStats uve; 279 0 : if (entry->FrameInterfaceAceStatsMsg(name, &uve)) { 280 0 : DispatchVMIStatsMsg(uve); 281 : } 282 0 : } 283 : 284 19 : void InterfaceUveStatsTable::UpdateVmiTagBasedStats(const EndpointStatsInfo 285 : &info) { 286 19 : std::scoped_lock lock(interface_tree_mutex_); 287 19 : InterfaceMap::iterator intf_it = interface_tree_.find(info.vmi->cfg_name()); 288 19 : if (intf_it != interface_tree_.end()) { 289 2 : UveInterfaceEntry *entry = intf_it->second.get(); 290 2 : entry->UpdateSecurityPolicyStats(info); 291 : } 292 19 : } 293 : 294 0 : void InterfaceUveStatsTable::BuildInterfaceUveInfo(InterfaceUveInfoResp *r) { 295 : 296 : vector<InterfaceUveInfo> &list = 297 0 : const_cast<std::vector<InterfaceUveInfo>&>(r->get_resp_list()); 298 0 : std::scoped_lock lock(interface_tree_mutex_); 299 0 : InterfaceMap::iterator intf_it = interface_tree_.begin(); 300 0 : while (intf_it != interface_tree_.end()) { 301 0 : InterfaceUveInfo item; 302 0 : UveInterfaceEntry *entry = intf_it->second.get(); 303 0 : ++intf_it; 304 0 : entry->BuildInterfaceUveInfo(&item); 305 0 : list.push_back(item); 306 0 : } 307 : 308 0 : } 309 : 310 0 : void InterfaceUveInfoReq::HandleRequest() const { 311 0 : InterfaceUveInfoResp *resp = new InterfaceUveInfoResp(); 312 0 : Agent *agent = Agent::GetInstance(); 313 : InterfaceUveStatsTable *table = static_cast<InterfaceUveStatsTable *> 314 0 : (agent->uve()->interface_uve_table()); 315 0 : table->BuildInterfaceUveInfo(resp); 316 0 : resp->set_context(context()); 317 0 : resp->Response(); 318 0 : return; 319 : }