Line data Source code
1 : /*
2 : * Copyright (c) 2015 Juniper Networks, Inc. All rights reserved.
3 : * Copyright Contributors to the OpenSDN project
4 : */
5 :
6 : #include <oper/interface_common.h>
7 : #include <oper/health_check.h>
8 : #include <oper/tag.h>
9 : #include <uve/interface_uve_table.h>
10 : #include <uve/agent_uve_base.h>
11 :
12 4 : InterfaceUveTable::InterfaceUveTable(Agent *agent, uint32_t default_intvl)
13 4 : : agent_(agent), interface_tree_(), interface_tree_mutex_(),
14 4 : intf_listener_id_(DBTableBase::kInvalidId),
15 4 : timer_last_visited_(""),
16 4 : timer_(TimerManager::CreateTimer
17 4 : (*(agent->event_manager())->io_service(),
18 : "InterfaceUveTimer",
19 4 : TaskScheduler::GetInstance()->GetTaskId(kTaskDBExclude), 0)) {
20 4 : expiry_time_ = default_intvl;
21 4 : timer_->Start(expiry_time_,
22 : boost::bind(&InterfaceUveTable::TimerExpiry, this));
23 4 : }
24 :
25 4 : InterfaceUveTable::~InterfaceUveTable() {
26 4 : }
27 :
28 0 : bool InterfaceUveTable::TimerExpiry() {
29 0 : InterfaceMap::iterator it = interface_tree_.lower_bound(timer_last_visited_);
30 0 : if (it == interface_tree_.end()) {
31 0 : timer_last_visited_ = "";
32 0 : return true;
33 : }
34 :
35 0 : uint32_t count = 0;
36 0 : while (it != interface_tree_.end() &&
37 : count < AgentUveBase::kUveCountPerTimer) {
38 0 : string cfg_name = it->first;
39 0 : UveInterfaceEntry* entry = it->second.get();
40 0 : InterfaceMap::iterator prev = it;
41 0 : it++;
42 0 : count++;
43 :
44 0 : if (entry->deleted_) {
45 0 : SendInterfaceDeleteMsg(cfg_name);
46 0 : if (!entry->renewed_) {
47 0 : std::scoped_lock lock(interface_tree_mutex_);
48 0 : interface_tree_.erase(prev);
49 0 : } else {
50 0 : entry->deleted_ = false;
51 0 : entry->renewed_ = false;
52 0 : entry->changed_ = false;
53 0 : SendInterfaceMsg(cfg_name, entry);
54 : // Send Interface ACE stats
55 0 : SendInterfaceAceStats(cfg_name, entry);
56 : }
57 : } else {
58 0 : if (entry->changed_) {
59 0 : SendInterfaceMsg(cfg_name, entry);
60 0 : entry->changed_ = false;
61 : /* Clear renew flag to be on safer side. Not really required */
62 0 : entry->renewed_ = false;
63 : }
64 : // Send Interface ACE stats
65 0 : SendInterfaceAceStats(cfg_name, entry);
66 : }
67 0 : }
68 :
69 :
70 0 : if (it == interface_tree_.end()) {
71 0 : timer_last_visited_ = "";
72 0 : set_expiry_time(agent_->uve()->default_interval());
73 : } else {
74 0 : timer_last_visited_ = it->first;
75 0 : set_expiry_time(agent_->uve()->incremental_interval());
76 : }
77 : /* Return true to trigger auto-restart of timer */
78 0 : return true;
79 : }
80 :
81 0 : void InterfaceUveTable::set_expiry_time(int time) {
82 0 : if (time != expiry_time_) {
83 0 : expiry_time_ = time;
84 0 : timer_->Reschedule(expiry_time_);
85 : }
86 0 : }
87 :
88 : /* VM interfaces which are not created by Nova will not have VM name set.
89 : * In that case pick VM name from VM object instead of VMI object */
90 0 : string InterfaceUveTable::UveInterfaceEntry::GetVmName() const {
91 0 : const VmEntry *vm = intf_->vm();
92 0 : if (!intf_->vm_name().empty()) {
93 0 : return intf_->vm_name();
94 : } else {
95 0 : if (vm) {
96 0 : return vm->GetCfgName();
97 : }
98 : }
99 0 : return "";
100 : }
101 :
102 0 : void InterfaceUveTable::UveInterfaceEntry::SetVnVmInfo(UveVMInterfaceAgent *uve)
103 : const {
104 0 : const VmEntry *vm = intf_->vm();
105 0 : const string &vm_name = GetVmName();
106 0 : if (!vm_name.empty()) {
107 0 : uve->set_vm_name(vm_name);
108 : }
109 0 : if (intf_->vn() != NULL) {
110 0 : uve->set_virtual_network(intf_->vn()->GetName());
111 0 : uve->set_vn_uuid(to_string(intf_->vn()->GetUuid()));
112 : } else {
113 0 : uve->set_virtual_network("");
114 : }
115 0 : if (vm) {
116 0 : uve->set_vm_uuid(to_string(vm->GetUuid()));
117 : } else {
118 0 : uve->set_vm_uuid("");
119 : }
120 0 : }
121 :
122 0 : void InterfaceUveTable::UveInterfaceEntry::SetVMIStatsVnVm(VMIStats *uve)
123 : const {
124 0 : const VmEntry *vm = intf_->vm();
125 0 : const string &vm_name = GetVmName();
126 0 : if (!vm_name.empty()) {
127 0 : uve->set_vm_name(vm_name);
128 : }
129 0 : if (intf_->vn() != NULL) {
130 0 : uve->set_virtual_network(intf_->vn()->GetName());
131 : } else {
132 0 : uve->set_virtual_network("");
133 : }
134 0 : if (vm) {
135 0 : uve->set_vm_uuid(to_string(vm->GetUuid()));
136 : } else {
137 0 : uve->set_vm_uuid("");
138 : }
139 0 : }
140 :
141 0 : bool InterfaceUveTable::UveInterfaceEntry::FrameInterfaceMsg(const string &name,
142 : UveVMInterfaceAgent *s_intf) const {
143 0 : s_intf->set_name(name);
144 0 : SetVnVmInfo(s_intf);
145 0 : s_intf->set_ip_address(intf_->primary_ip_addr().to_string());
146 0 : s_intf->set_mac_address(intf_->vm_mac().ToString());
147 0 : s_intf->set_ip6_address(intf_->primary_ip6_addr().to_string());
148 0 : s_intf->set_ip6_active(intf_->ipv6_active());
149 0 : s_intf->set_is_health_check_active(intf_->is_hc_active());
150 0 : s_intf->set_tx_vlan(intf_->tx_vlan_id());
151 0 : s_intf->set_rx_vlan(intf_->rx_vlan_id());
152 0 : s_intf->set_vhostuser_mode(intf_->vhostuser_mode());
153 0 : if (intf_->GetAnalyzer().empty()) {
154 0 : s_intf->set_port_mirror_enabled(false);
155 : } else {
156 0 : s_intf->set_port_mirror_enabled(true);
157 : }
158 0 : const Interface *parent = intf_->parent();
159 0 : if (parent) {
160 0 : const VmInterface *p_vmi = dynamic_cast<const VmInterface*>(parent);
161 0 : if (p_vmi) {
162 0 : s_intf->set_parent_interface(p_vmi->cfg_name());
163 : } else {
164 0 : s_intf->set_parent_interface(parent->name());
165 : }
166 : }
167 :
168 0 : vector<VmFloatingIPAgent> uve_fip_list;
169 0 : if (intf_->HasFloatingIp(Address::INET)) {
170 : const VmInterface::FloatingIpList fip_list =
171 0 : intf_->floating_ip_list();
172 : VmInterface::FloatingIpSet::const_iterator it =
173 0 : fip_list.list_.begin();
174 0 : while(it != fip_list.list_.end()) {
175 0 : const VmInterface::FloatingIp &ip = *it;
176 : /* Don't export FIP entry if it is not installed. When FIP entry
177 : * is not installed it will have NULL VN pointer. We can receive
178 : * notifications for VM interface with un-installed FIP entries
179 : * when the VM interface is not "L3 Active".
180 : */
181 0 : if (ip.Installed()) {
182 0 : VmFloatingIPAgent uve_fip;
183 0 : uve_fip.set_ip_address(ip.floating_ip_.to_string());
184 0 : uve_fip.set_virtual_network(ip.vn_.get()->GetName());
185 0 : uve_fip_list.push_back(uve_fip);
186 0 : }
187 0 : it++;
188 : }
189 0 : }
190 0 : s_intf->set_floating_ips(uve_fip_list);
191 :
192 0 : vector<VmHealthCheckInstance> uve_hc_list;
193 : const VmInterface::HealthCheckInstanceSet hc_list =
194 0 : intf_->hc_instance_set();
195 : VmInterface::HealthCheckInstanceSet::const_iterator hc_it =
196 0 : hc_list.begin();
197 0 : while (hc_it != hc_list.end()) {
198 0 : HealthCheckInstanceBase *inst = (*hc_it);
199 0 : hc_it++;
200 0 : HealthCheckService *svc = inst->service();
201 0 : if (!svc) {
202 0 : continue;
203 : }
204 0 : VmHealthCheckInstance uve_inst;
205 0 : uve_inst.set_name(svc->name());
206 0 : uve_inst.set_uuid(to_string(svc->uuid()));
207 0 : uve_inst.set_status(inst->active() ? "Active" : "InActive");
208 0 : uve_inst.set_is_running(inst->IsRunning());
209 0 : uve_hc_list.push_back(uve_inst);
210 0 : }
211 0 : s_intf->set_health_check_instance_list(uve_hc_list);
212 :
213 0 : s_intf->set_label(intf_->label());
214 0 : s_intf->set_ip4_active(intf_->ipv4_active());
215 0 : s_intf->set_l2_active(intf_->l2_active());
216 0 : s_intf->set_active(intf_->IsUveActive());
217 0 : s_intf->set_admin_state(intf_->admin_state());
218 :
219 0 : s_intf->set_uuid(to_string(intf_->vmi_cfg_uuid()));
220 0 : string gw;
221 0 : if (GetVmInterfaceGateway(intf_, gw)) {
222 0 : s_intf->set_gateway(gw);
223 : }
224 :
225 0 : std::vector<std::string> fixed_ip4_list;
226 0 : intf_->BuildIpStringList(Address::INET, &fixed_ip4_list);
227 0 : s_intf->set_fixed_ip4_list(fixed_ip4_list);
228 :
229 0 : std::vector<std::string> fixed_ip6_list;
230 0 : intf_->BuildIpStringList(Address::INET6, &fixed_ip6_list);
231 0 : s_intf->set_fixed_ip6_list(fixed_ip6_list);
232 0 : if (intf_->hbs_intf_type() == VmInterface::HBS_INTF_LEFT) {
233 0 : s_intf->set_hbf_intf_type("left");
234 0 : } else if (intf_->hbs_intf_type() == VmInterface::HBS_INTF_RIGHT) {
235 0 : s_intf->set_hbf_intf_type("right");
236 0 : } else if (intf_->hbs_intf_type() == VmInterface::HBS_INTF_MGMT) {
237 0 : s_intf->set_hbf_intf_type("mgmt");
238 : }
239 0 : return true;
240 0 : }
241 :
242 167 : void InterfaceUveTable::UveInterfaceEntry::Reset() {
243 167 : intf_ = NULL;
244 167 : port_bitmap_.Reset();
245 167 : prev_fip_tree_.clear();
246 167 : fip_tree_.clear();
247 167 : ace_set_.clear();
248 167 : security_policy_stats_map_.clear();
249 :
250 167 : ace_stats_changed_ = false;
251 167 : deleted_ = true;
252 167 : renewed_ = false;
253 167 : }
254 :
255 1062 : void InterfaceUveTable::UveInterfaceEntry::HandleTagListChange() {
256 1062 : assert(intf_);
257 : /* No action is required if tags are not added yet. Addition of tags is
258 : * handled via FlowStats module notification */
259 1062 : if (local_tagset_.size() != 0) {
260 0 : TagList new_tag_list;
261 0 : intf_->CopyTagIdList(&new_tag_list);
262 0 : if (local_tagset_ != new_tag_list) {
263 : /* Do not update local_tagset_ with new values. This is handled
264 : * as part of FlowStats module notification */
265 0 : local_tagset_.clear();
266 : }
267 0 : }
268 1062 : }
269 :
270 150 : void InterfaceUveTable::UveInterfaceEntry::UpdatePortBitmap
271 : (uint8_t proto, uint16_t sport, uint16_t dport) {
272 150 : std::scoped_lock lock(mutex_);
273 : /* No need to update stats if the entry is marked for delete and not
274 : * renewed */
275 150 : if (deleted_ && !renewed_) {
276 0 : return;
277 : }
278 150 : port_bitmap_.AddPort(proto, sport, dport);
279 150 : }
280 :
281 0 : bool InterfaceUveTable::UveInterfaceEntry::FipAggStatsChanged
282 : (const vector<VmFloatingIPStats> &list) const {
283 0 : if (list != uve_stats_.get_fip_agg_stats()) {
284 0 : return true;
285 : }
286 0 : return false;
287 : }
288 :
289 0 : bool InterfaceUveTable::UveInterfaceEntry::GetVmInterfaceGateway(
290 : const VmInterface *vm_intf, string &gw) const {
291 0 : const VnEntry *vn = vm_intf->vn();
292 0 : if (vn == NULL) {
293 0 : return false;
294 : }
295 0 : const vector<VnIpam> &list = vn->GetVnIpam();
296 0 : Ip4Address vm_addr = vm_intf->primary_ip_addr();
297 : unsigned int i;
298 0 : for (i = 0; i < list.size(); i++) {
299 0 : if (list[i].IsSubnetMember(vm_addr))
300 0 : break;
301 : }
302 0 : if (i == list.size()) {
303 0 : return false;
304 : }
305 0 : gw = list[i].default_gw.to_string();
306 0 : return true;
307 : }
308 :
309 0 : void InterfaceUveTable::SendInterfaceDeleteMsg(const string &config_name) {
310 0 : UveVMInterfaceAgent uve;
311 0 : uve.set_name(config_name);
312 0 : uve.set_deleted(true);
313 0 : DispatchInterfaceMsg(uve);
314 :
315 0 : VMITags tags_uve;
316 0 : tags_uve.set_name(config_name);
317 0 : tags_uve.set_deleted(true);
318 0 : DispatchVMITagsMsg(tags_uve);
319 :
320 0 : VMIStats s_uve;
321 0 : s_uve.set_name(config_name);
322 0 : s_uve.set_deleted(true);
323 0 : DispatchVMIStatsMsg(s_uve);
324 0 : }
325 :
326 0 : bool InterfaceUveTable::UveInterfaceEntry::FrameTagsUveMsg
327 : (Agent *agent, const string &name, VMITags *obj) {
328 0 : bool changed = false;
329 0 : AgentUveBase *uve = agent->uve();
330 0 : obj->set_name(name);
331 0 : TagList new_tag_list;
332 0 : intf_->CopyTagIdList(&new_tag_list);
333 0 : UveTagData tinfo(UveTagData::VECTOR);
334 0 : uve->BuildTagNamesFromList(new_tag_list, &tinfo);
335 0 : if ((!prev_tags_uve_.__isset.app) ||
336 0 : (prev_tags_uve_.__isset.app && (prev_tags_uve_.get_app() !=
337 : tinfo.application))) {
338 0 : obj->set_app(tinfo.application);
339 0 : prev_tags_uve_.set_app(tinfo.application);
340 0 : changed = true;
341 : }
342 0 : if ((!prev_tags_uve_.__isset.tier) ||
343 0 : (prev_tags_uve_.__isset.tier && (prev_tags_uve_.get_tier() !=
344 : tinfo.tier))) {
345 0 : obj->set_tier(tinfo.tier);
346 0 : prev_tags_uve_.set_tier(tinfo.tier);
347 0 : changed = true;
348 : }
349 0 : if ((!prev_tags_uve_.__isset.site) ||
350 0 : (prev_tags_uve_.__isset.site && (prev_tags_uve_.get_site() !=
351 : tinfo.site))) {
352 0 : obj->set_site(tinfo.site);
353 0 : prev_tags_uve_.set_site(tinfo.site);
354 0 : changed = true;
355 : }
356 0 : if ((!prev_tags_uve_.__isset.deployment) ||
357 0 : (prev_tags_uve_.__isset.deployment &&
358 0 : (prev_tags_uve_.get_deployment() != tinfo.deployment))) {
359 0 : obj->set_deployment(tinfo.deployment);
360 0 : prev_tags_uve_.set_deployment(tinfo.deployment);
361 0 : changed = true;
362 : }
363 0 : if ((!prev_tags_uve_.__isset.labels) ||
364 0 : (prev_tags_uve_.__isset.labels && (prev_tags_uve_.get_labels() !=
365 : tinfo.label_vector))) {
366 0 : obj->set_labels(tinfo.label_vector);
367 0 : prev_tags_uve_.set_labels(tinfo.label_vector);
368 0 : changed = true;
369 : }
370 0 : if ((!prev_tags_uve_.__isset.custom_tags) ||
371 0 : (prev_tags_uve_.__isset.custom_tags &&
372 0 : (prev_tags_uve_.get_custom_tags() != tinfo.custom_tag_vector))) {
373 0 : obj->set_custom_tags(tinfo.custom_tag_vector);
374 0 : prev_tags_uve_.set_custom_tags(tinfo.custom_tag_vector);
375 0 : changed = true;
376 : }
377 0 : return changed;
378 0 : }
379 :
380 : InterfaceUveTable::UveInterfaceEntryPtr
381 1062 : InterfaceUveTable::Allocate(const VmInterface *itf) {
382 1062 : UveInterfaceEntryPtr uve(new UveInterfaceEntry(itf));
383 1062 : return uve;
384 : }
385 :
386 0 : void InterfaceUveTable::DispatchInterfaceMsg(const UveVMInterfaceAgent &uve) {
387 0 : UveVMInterfaceAgentTrace::Send(uve);
388 0 : }
389 :
390 0 : void InterfaceUveTable::DispatchVMIStatsMsg(const VMIStats &uve) {
391 0 : UVEVMIStats::Send(uve);
392 0 : }
393 :
394 0 : void InterfaceUveTable::DispatchVMITagsMsg(const VMITags &uve) const {
395 0 : UVEVMITags::Send(uve);
396 0 : }
397 :
398 0 : void InterfaceUveTable::DispatchInterfaceObjectLog(EndpointSecurityStats *obj) {
399 0 : ENDPOINT_SECURITY_STATS_SEND_SANDESH(obj);
400 0 : }
401 :
402 0 : void InterfaceUveTable::SendInterfaceMsg(const string &name,
403 : UveInterfaceEntry *entry) {
404 0 : UveVMInterfaceAgent uve;
405 0 : if (entry->FrameInterfaceMsg(name, &uve)) {
406 0 : DispatchInterfaceMsg(uve);
407 : }
408 0 : VMITags tags_uve;
409 0 : if (entry->FrameTagsUveMsg(agent_, name, &tags_uve)) {
410 0 : DispatchVMITagsMsg(tags_uve);
411 : }
412 0 : }
413 :
414 1062 : void InterfaceUveTable::InterfaceAddHandler(const VmInterface* itf,
415 : const VmInterface::FloatingIpSet &old_list) {
416 1062 : UveInterfaceEntryPtr uve = Allocate(itf);
417 1062 : pair<InterfaceMap::iterator, bool> ret;
418 1062 : ret = interface_tree_.insert(InterfacePair(itf->cfg_name(), uve));
419 1062 : InterfaceMap::iterator it = ret.first;
420 1062 : UveInterfaceEntry* entry = it->second.get();
421 1062 : if (entry->deleted_) {
422 986 : entry->renewed_ = true;
423 986 : entry->intf_ = itf;
424 : }
425 :
426 : /* Mark the entry as changed to account for change in any fields of VMI */
427 1062 : entry->changed_ = true;
428 :
429 1062 : const VmInterface::FloatingIpSet &new_list = itf->floating_ip_list().list_;
430 : /* Remove old entries, by checking entries which are present in old list,
431 : * but not in new list */
432 1062 : VmInterface::FloatingIpSet::const_iterator old_it = old_list.begin();
433 1247 : while (old_it != old_list.end()) {
434 185 : VmInterface::FloatingIp fip = *old_it;
435 185 : ++old_it;
436 : /* Skip entries which are not installed as they wouldn't have been
437 : * added
438 : */
439 185 : if (!fip.Installed()) {
440 0 : continue;
441 : }
442 185 : VmInterface::FloatingIpSet::const_iterator new_it = new_list.find(fip);
443 185 : if (new_it == new_list.end()) {
444 107 : entry->RemoveFloatingIp(fip);
445 : }
446 185 : }
447 : /* Add entries in new list. Ignore if entries already present */
448 1062 : VmInterface::FloatingIpSet::const_iterator fip_it = new_list.begin();
449 1253 : while (fip_it != new_list.end()) {
450 191 : VmInterface::FloatingIp fip = *fip_it;
451 191 : ++fip_it;
452 : /* Skip entries which are not installed as they wouldn't have been
453 : * added
454 : */
455 191 : if (!fip.Installed()) {
456 0 : continue;
457 : }
458 191 : entry->AddFloatingIp(fip);
459 191 : }
460 1062 : }
461 :
462 167 : void InterfaceUveTable::InterfaceDeleteHandler(const string &name) {
463 167 : InterfaceMap::iterator it = interface_tree_.find(name);
464 167 : if (it == interface_tree_.end()) {
465 0 : return;
466 : }
467 167 : UveInterfaceEntry* entry = it->second.get();
468 167 : std::scoped_lock lock(entry->mutex_);
469 : /* We need to reset all non-key fields to ensure that they have right
470 : * values since the entry is getting re-used. Also update the 'deleted_'
471 : * and 'renewed_' flags */
472 167 : entry->Reset();
473 167 : return;
474 167 : }
475 :
476 1062 : void InterfaceUveTable::HandleVmiTagListChange(const string &name) {
477 1062 : InterfaceMap::iterator it = interface_tree_.find(name);
478 1062 : if (it == interface_tree_.end()) {
479 0 : return;
480 : }
481 1062 : UveInterfaceEntry* entry = it->second.get();
482 1062 : entry->HandleTagListChange();
483 1062 : return;
484 : }
485 :
486 1421 : void InterfaceUveTable::InterfaceNotify(DBTablePartBase *partition,
487 : DBEntryBase *e) {
488 1421 : const VmInterface *vm_port = dynamic_cast<const VmInterface*>(e);
489 1421 : if (vm_port == NULL) {
490 21 : return;
491 : }
492 :
493 : UveInterfaceState *state = static_cast<UveInterfaceState *>
494 1400 : (e->GetState(partition->parent(), intf_listener_id_));
495 1400 : if (e->IsDeleted()) {
496 169 : if (state) {
497 167 : InterfaceDeleteHandler(state->cfg_name_);
498 167 : state->fip_list_.clear();
499 167 : e->ClearState(partition->parent(), intf_listener_id_);
500 167 : delete state;
501 : }
502 : } else {
503 1231 : VmInterface::FloatingIpSet old_list;
504 1231 : if (!state && vm_port->cfg_name().empty()) {
505 : /* Skip Add/change notifications if the config_name is empty */
506 169 : return;
507 : }
508 :
509 1062 : if (!state) {
510 167 : state = new UveInterfaceState(vm_port);
511 167 : e->SetState(partition->parent(), intf_listener_id_, state);
512 : } else {
513 895 : old_list = state->fip_list_;
514 895 : state->fip_list_ = vm_port->floating_ip_list().list_;
515 : }
516 1062 : if (state->cfg_name_ != vm_port->cfg_name()) {
517 0 : InterfaceDeleteHandler(state->cfg_name_);
518 0 : state->cfg_name_ = vm_port->cfg_name();
519 0 : old_list.clear();
520 : }
521 1062 : if (!vm_port->cfg_name().empty()) {
522 1062 : InterfaceAddHandler(vm_port, old_list);
523 1062 : HandleVmiTagListChange(vm_port->cfg_name());
524 : }
525 1231 : }
526 : }
527 :
528 2 : void InterfaceUveTable::RegisterDBClients() {
529 2 : InterfaceTable *intf_table = agent_->interface_table();
530 2 : intf_listener_id_ = intf_table->Register
531 2 : (boost::bind(&InterfaceUveTable::InterfaceNotify, this, _1, _2));
532 :
533 2 : }
534 :
535 4 : void InterfaceUveTable::Shutdown(void) {
536 4 : if (intf_listener_id_ != DBTableBase::kInvalidId)
537 2 : agent_->interface_table()->Unregister(intf_listener_id_);
538 :
539 4 : if (timer_) {
540 4 : timer_->Cancel();
541 4 : TimerManager::DeleteTimer(timer_);
542 4 : timer_ = NULL;
543 : }
544 4 : }
545 :
546 0 : bool InterfaceUveTable::UveInterfaceEntry::PortBitmapChanged
547 : (const PortBucketBitmap &bmap) const {
548 0 : if (!uve_stats_.__isset.port_bucket_bmap) {
549 0 : return true;
550 : }
551 0 : if (bmap != uve_stats_.get_port_bucket_bmap()) {
552 0 : return true;
553 : }
554 0 : return false;
555 : }
556 :
557 0 : bool InterfaceUveTable::UveInterfaceEntry::InBandChanged(uint64_t in_band)
558 : const {
559 0 : if (!uve_stats_.__isset.in_bw_usage) {
560 0 : return true;
561 : }
562 0 : if (in_band != uve_stats_.get_in_bw_usage()) {
563 0 : return true;
564 : }
565 0 : return false;
566 : }
567 :
568 0 : bool InterfaceUveTable::UveInterfaceEntry::OutBandChanged(uint64_t out_band)
569 : const {
570 0 : if (!uve_stats_.__isset.out_bw_usage) {
571 0 : return true;
572 : }
573 0 : if (out_band != uve_stats_.get_out_bw_usage()) {
574 0 : return true;
575 : }
576 0 : return false;
577 : }
578 :
579 22 : void InterfaceUveTable::UveInterfaceEntry::UpdateFloatingIpStats
580 : (const FipInfo &fip_info) {
581 22 : std::scoped_lock lock(mutex_);
582 : /* No need to update stats if the entry is marked for delete and not
583 : * renewed */
584 22 : if (deleted_ && !renewed_) {
585 0 : return;
586 : }
587 22 : FloatingIp *entry = FipEntry(fip_info.fip_, fip_info.vn_);
588 : /* Ignore stats update request if it comes after entry is removed */
589 22 : if (entry == NULL) {
590 0 : return;
591 : }
592 22 : entry->UpdateFloatingIpStats(fip_info);
593 22 : }
594 :
595 22 : InterfaceUveTable::FloatingIp *InterfaceUveTable::UveInterfaceEntry::FipEntry
596 : (uint32_t ip, const string &vn) {
597 22 : Ip4Address addr(ip);
598 22 : FloatingIpPtr key(new FloatingIp(addr, vn));
599 22 : FloatingIpSet::iterator fip_it = fip_tree_.find(key);
600 22 : if (fip_it == fip_tree_.end()) {
601 0 : return NULL;
602 : } else {
603 22 : return (*fip_it).get();
604 : }
605 22 : }
606 :
607 22 : void InterfaceUveTable::FloatingIp::UpdateFloatingIpStats(const FipInfo &fip_info) {
608 22 : if (fip_info.is_local_flow_) {
609 1 : if (fip_info.is_reverse_flow_) {
610 0 : out_bytes_ += fip_info.bytes_;
611 0 : out_packets_ += fip_info.packets_;
612 :
613 0 : if (fip_info.rev_fip_) {
614 : /* This is the case where Source and Destination VMs (part of
615 : * same compute node) ping to each other to their respective
616 : * Floating IPs. In this case for each flow we need to increment
617 : * stats for both the VMs */
618 0 : fip_info.rev_fip_->out_bytes_ += fip_info.bytes_;
619 0 : fip_info.rev_fip_->out_packets_ += fip_info.packets_;
620 : }
621 : } else {
622 1 : in_bytes_ += fip_info.bytes_;
623 1 : in_packets_ += fip_info.packets_;
624 1 : if (fip_info.rev_fip_) {
625 : /* This is the case where Source and Destination VMs (part of
626 : * same compute node) ping to each other to their respective
627 : * Floating IPs. In this case for each flow we need to increment
628 : * stats for both the VMs */
629 0 : fip_info.rev_fip_->in_bytes_ += fip_info.bytes_;
630 0 : fip_info.rev_fip_->in_packets_ += fip_info.packets_;
631 : }
632 : }
633 : } else {
634 21 : if (fip_info.is_ingress_flow_) {
635 10 : in_bytes_ += fip_info.bytes_;
636 10 : in_packets_ += fip_info.packets_;
637 : } else {
638 11 : out_bytes_ += fip_info.bytes_;
639 11 : out_packets_ += fip_info.packets_;
640 : }
641 : }
642 22 : }
643 :
644 :
645 0 : bool InterfaceUveTable::UveInterfaceEntry::FillFloatingIpStats
646 : (vector<VmFloatingIPStats> &result,
647 : vector<VmFloatingIPStats> &diff_list,
648 : bool &diff_list_send) {
649 0 : const VmInterface *vm_intf = static_cast<const VmInterface *>(intf_);
650 0 : if (vm_intf->HasFloatingIp()) {
651 : const VmInterface::FloatingIpList fip_list =
652 0 : vm_intf->floating_ip_list();
653 : VmInterface::FloatingIpSet::const_iterator it =
654 0 : fip_list.list_.begin();
655 0 : while(it != fip_list.list_.end()) {
656 0 : const VmInterface::FloatingIp &ip = *it;
657 : /* Skip FIP entries which are not yet activated */
658 0 : if (!ip.Installed()) {
659 0 : it++;
660 0 : continue;
661 : }
662 0 : VmFloatingIPStats uve_fip;
663 0 : VmFloatingIPStats diff_uve;
664 0 : uve_fip.set_ip_address(ip.floating_ip_.to_string());
665 0 : uve_fip.set_virtual_network(ip.vn_.get()->GetName());
666 :
667 0 : diff_uve.set_ip_address(ip.floating_ip_.to_string());
668 0 : diff_uve.set_virtual_network(ip.vn_.get()->GetName());
669 :
670 0 : FloatingIpPtr key(new FloatingIp(ip.floating_ip_,
671 0 : ip.vn_.get()->GetName()));
672 0 : FloatingIpSet::iterator fip_it = fip_tree_.find(key);
673 0 : if (fip_it == fip_tree_.end()) {
674 0 : SetStats(uve_fip, 0, 0, 0, 0);
675 0 : SetDiffStats(diff_uve, 0, 0, 0, 0, diff_list_send);
676 : } else {
677 0 : FloatingIp *fip = (*fip_it).get();
678 0 : SetStats(uve_fip, fip->in_bytes_, fip->in_packets_,
679 : fip->out_bytes_, fip->out_packets_);
680 0 : FloatingIpSet::iterator prev_it = prev_fip_tree_.find(key);
681 0 : if (prev_it == prev_fip_tree_.end()) {
682 0 : SetDiffStats(diff_uve, fip->in_bytes_, fip->in_packets_,
683 : fip->out_bytes_, fip->out_packets_,
684 : diff_list_send);
685 0 : FloatingIpPtr prev_fip_ptr(new FloatingIp(ip.floating_ip_,
686 0 : ip.vn_.get()->GetName(),
687 : fip->in_bytes_,
688 : fip->in_packets_,
689 : fip->out_bytes_,
690 0 : fip->out_packets_));
691 0 : prev_fip_tree_.insert(prev_fip_ptr);
692 0 : } else {
693 0 : FloatingIp *pfip = (*prev_it).get();
694 0 : SetDiffStats(diff_uve, (fip->in_bytes_ - pfip->in_bytes_),
695 0 : (fip->in_packets_ - pfip->in_packets_),
696 0 : (fip->out_bytes_ - pfip->out_bytes_),
697 0 : (fip->out_packets_ - pfip->out_packets_),
698 : diff_list_send);
699 0 : pfip->in_bytes_ = fip->in_bytes_;
700 0 : pfip->in_packets_ = fip->in_packets_;
701 0 : pfip->out_bytes_ = fip->out_bytes_;
702 0 : pfip->out_packets_ = fip->out_packets_;
703 : }
704 :
705 : }
706 0 : result.push_back(uve_fip);
707 0 : diff_list.push_back(diff_uve);
708 0 : it++;
709 0 : }
710 0 : return true;
711 0 : }
712 0 : return false;
713 : }
714 :
715 0 : void InterfaceUveTable::UveInterfaceEntry::SetDiffStats
716 : (VmFloatingIPStats &fip, uint64_t in_bytes, uint64_t in_pkts,
717 : uint64_t out_bytes, uint64_t out_pkts, bool &diff_list_send) const {
718 0 : fip.set_in_bytes(in_bytes);
719 0 : fip.set_in_pkts(in_pkts);
720 0 : fip.set_out_bytes(out_bytes);
721 0 : fip.set_out_pkts(out_pkts);
722 0 : if ((in_bytes != 0) || (in_pkts != 0) || (out_bytes != 0) ||
723 : (out_pkts != 0)) {
724 0 : diff_list_send = true;
725 : }
726 0 : }
727 :
728 0 : void InterfaceUveTable::UveInterfaceEntry::SetStats
729 : (VmFloatingIPStats &fip, uint64_t in_bytes, uint64_t in_pkts,
730 : uint64_t out_bytes, uint64_t out_pkts) const {
731 0 : fip.set_in_bytes(in_bytes);
732 0 : fip.set_in_pkts(in_pkts);
733 0 : fip.set_out_bytes(out_bytes);
734 0 : fip.set_out_pkts(out_pkts);
735 0 : }
736 :
737 191 : void InterfaceUveTable::UveInterfaceEntry::AddFloatingIp
738 : (const VmInterface::FloatingIp &fip) {
739 191 : FloatingIpPtr key(new FloatingIp(fip.floating_ip_,
740 191 : fip.vn_.get()->GetName()));
741 191 : FloatingIpSet::iterator it = fip_tree_.find(key);
742 191 : if (it != fip_tree_.end()) {
743 78 : return;
744 : }
745 113 : fip_tree_.insert(key);
746 191 : }
747 :
748 107 : void InterfaceUveTable::UveInterfaceEntry::RemoveFloatingIp
749 : (const VmInterface::FloatingIp &fip) {
750 107 : FloatingIpPtr key(new FloatingIp(fip.floating_ip_, fip.vn_.get()->GetName()));
751 107 : FloatingIpSet::iterator it = fip_tree_.find(key);
752 107 : if (it != fip_tree_.end()) {
753 107 : fip_tree_.erase(it);
754 : }
755 107 : FloatingIpSet::iterator prev_it = prev_fip_tree_.find(key);
756 107 : if (prev_it != prev_fip_tree_.end()) {
757 0 : prev_fip_tree_.erase(prev_it);
758 : }
759 107 : }
760 :
761 169 : void InterfaceUveTable::UveInterfaceEntry::UpdateInterfaceAceStats
762 : (const std::string &ace_uuid) {
763 169 : AceStats key(ace_uuid);
764 169 : ace_stats_changed_ = true;
765 169 : AceStatsSet::const_iterator it = ace_set_.find(key);
766 169 : if (it != ace_set_.end()) {
767 129 : it->count++;
768 129 : return;
769 : }
770 40 : key.count = 1;
771 40 : ace_set_.insert(key);
772 169 : }
773 :
774 14 : void InterfaceUveTable::UveInterfaceEntry::UpdateCounters
775 : (const FlowUveFwPolicyInfo &info, UveSecurityPolicyStats *obj) {
776 14 : if (info.added_) {
777 9 : ++obj->added;
778 : } else {
779 5 : ++obj->deleted;
780 : }
781 14 : if (obj->added >= obj->deleted) {
782 14 : obj->active = obj->added - obj->deleted;
783 : }
784 14 : }
785 :
786 14 : void InterfaceUveTable::UveInterfaceEntry::UpdateInterfaceFwPolicyStats
787 : (const FlowUveFwPolicyInfo &info) {
788 14 : ace_stats_changed_ = true;
789 14 : std::scoped_lock lock(mutex_);
790 : /* If TagList of VMI has changed clear the earlier statistics as they are
791 : * valid only for previous TagList.
792 : */
793 14 : if (info.added_) {
794 9 : local_tagset_ = info.local_tagset_;
795 : }
796 : SecurityPolicyStatsMap::iterator it = security_policy_stats_map_.
797 14 : find(info.fw_policy_);
798 : UveSecurityPolicyStatsPtr ep_key(new UveSecurityPolicyStats
799 14 : (info.local_tagset_,
800 14 : info.remote_tagset_,
801 14 : info.remote_prefix_, info.remote_vn_,
802 14 : info.local_vn_, info.action_));
803 14 : if (it != security_policy_stats_map_.end()) {
804 9 : EndpointStatsContainer &cont = it->second;
805 : InterfaceUveTable::SecurityPolicyStatsSet &remote_ep_list =
806 9 : cont.ToList(info.initiator_);
807 9 : SecurityPolicyStatsSet::iterator ep_it = remote_ep_list.find(ep_key);
808 9 : if (ep_it != remote_ep_list.end()) {
809 7 : UveSecurityPolicyStatsPtr entry = *ep_it;
810 7 : UpdateCounters(info, entry.get());
811 7 : return;
812 7 : } else {
813 : /* Ignore delete counter increment request when the entry itself is
814 : * absent
815 : */
816 2 : if (!info.added_) {
817 0 : return;
818 : }
819 2 : UpdateCounters(info, ep_key.get());
820 2 : remote_ep_list.insert(ep_key);
821 : }
822 : } else {
823 5 : UpdateCounters(info, ep_key.get());
824 5 : EndpointStatsContainer cont;
825 5 : SecurityPolicyStatsSet &remote_ep_list = cont.ToList(info.initiator_);
826 5 : remote_ep_list.insert(ep_key);
827 5 : security_policy_stats_map_.insert(SecurityPolicyStatsPair
828 5 : (info.fw_policy_, cont));
829 5 : }
830 21 : }
831 :
832 0 : bool InterfaceUveTable::UveInterfaceEntry::FrameInterfaceAceStatsMsg
833 : (const std::string &name, VMIStats *s_intf) {
834 0 : if (!ace_stats_changed_) {
835 0 : return false;
836 : }
837 0 : std::vector<SgAclRuleStats> list;
838 0 : AceStatsSet::iterator it = ace_set_.begin();
839 0 : bool changed = false;
840 : /* Build the updated list */
841 0 : while (it != ace_set_.end()) {
842 0 : uint64_t diff_count = it->count - it->prev_count;
843 0 : if (diff_count) {
844 : //Update prev_count
845 0 : it->prev_count = it->count;
846 0 : SgAclRuleStats item;
847 0 : item.set_rule(it->ace_uuid);
848 0 : item.set_count(diff_count);
849 0 : list.push_back(item);
850 0 : changed = true;
851 0 : }
852 0 : ++it;
853 : }
854 : /* If all the entries in the list has 0 diff_stats, then UVE won't be
855 : * sent */
856 0 : if (changed) {
857 0 : s_intf->set_name(name);
858 0 : SetVMIStatsVnVm(s_intf);
859 0 : s_intf->set_sg_rule_stats(list);
860 0 : ace_stats_changed_ = false;
861 0 : return true;
862 : }
863 0 : return false;
864 0 : }
865 :
866 27 : void InterfaceUveTable::UveInterfaceEntry::UpdateSecurityPolicyStats
867 : (const EndpointStatsInfo &info) {
868 27 : std::scoped_lock lock(mutex_);
869 27 : local_tagset_ = info.local_tagset;
870 : UveSecurityPolicyStatsPtr stats(new UveSecurityPolicyStats
871 27 : (info.local_tagset, info.remote_tagset,
872 27 : info.remote_prefix, info.remote_vn,
873 27 : info.local_vn, info.action));
874 : SecurityPolicyStatsMap::iterator it =
875 27 : security_policy_stats_map_.find(info.policy);
876 27 : if (it == security_policy_stats_map_.end()) {
877 7 : UpdateSecurityPolicyStatsInternal(info, stats.get());
878 7 : EndpointStatsContainer cont;
879 7 : SecurityPolicyStatsSet &stats_set = cont.ToList(info.client);
880 7 : stats_set.insert(stats);
881 7 : security_policy_stats_map_.insert(SecurityPolicyStatsPair(info.policy,
882 : cont));
883 7 : } else {
884 20 : EndpointStatsContainer &cont = it->second;
885 20 : SecurityPolicyStatsSet &stats_set = cont.ToList(info.client);
886 : std::pair<SecurityPolicyStatsSet::iterator,bool> ret =
887 20 : stats_set.insert(stats);
888 20 : UveSecurityPolicyStatsPtr entry(*ret.first);
889 : /* Update the statistics and action for the entry */
890 20 : UpdateSecurityPolicyStatsInternal(info, entry.get());
891 20 : }
892 27 : }
893 :
894 :
895 27 : void InterfaceUveTable::UveInterfaceEntry::UpdateSecurityPolicyStatsInternal
896 : (const EndpointStatsInfo &info, UveSecurityPolicyStats *stats) {
897 27 : stats->action = info.action;
898 27 : if (info.in_stats) {
899 15 : stats->in_bytes += info.diff_bytes;
900 15 : stats->in_pkts += info.diff_pkts;
901 : } else {
902 12 : stats->out_bytes += info.diff_bytes;
903 12 : stats->out_pkts += info.diff_pkts;
904 : }
905 27 : }
906 :
907 0 : void InterfaceUveTable::UveInterfaceEntry::FillEndpointStats
908 : (Agent *agent, EndpointSecurityStats *obj) {
909 0 : std::map<std::string, EndpointStats> eps;
910 :
911 0 : obj->set_name(intf_->cfg_name());
912 : SecurityPolicyStatsMap::const_iterator it =
913 0 : security_policy_stats_map_.begin();
914 0 : while (it != security_policy_stats_map_.end()) {
915 0 : std::vector<SecurityPolicyFlowStats> traffic_list;
916 0 : const EndpointStatsContainer &cont = it->second;
917 0 : EndpointStats value;
918 0 : value.set_workload(GetVmName());
919 0 : FillSecurityPolicyList(agent, cont.client_list, &value.client);
920 0 : FillSecurityPolicyList(agent, cont.server_list, &value.server);
921 0 : eps.insert(make_pair(it->first, value));
922 0 : ++it;
923 0 : }
924 0 : obj->set_eps(eps);
925 0 : }
926 :
927 0 : void InterfaceUveTable::UveInterfaceEntry::FillSecurityPolicyList
928 : (Agent *agent, const SecurityPolicyStatsSet &ilist,
929 : std::vector<SecurityPolicyFlowStats> *olist) {
930 0 : const AgentUveBase *uve = agent->uve();
931 0 : SecurityPolicyStatsSet::const_iterator sit = ilist.begin();
932 0 : while (sit != ilist.end()) {
933 0 : SecurityPolicyFlowStats item;
934 0 : UveSecurityPolicyStatsPtr entry(*sit);
935 0 : UveTagData tinfo;
936 0 : uve->BuildTagNamesFromList(entry->local_tagset, &tinfo);
937 0 : item.set_app(tinfo.application);
938 0 : item.set_tier(tinfo.tier);
939 0 : item.set_site(tinfo.site);
940 0 : item.set_deployment(tinfo.deployment);
941 0 : item.set_labels(tinfo.labels);
942 0 : item.set_custom_tags(tinfo.custom_tags);
943 0 : tinfo.Reset();
944 0 : uve->BuildTagIdsFromList(entry->remote_tagset, &tinfo);
945 0 : item.set_remote_app_id(tinfo.application);
946 0 : item.set_remote_tier_id(tinfo.tier);
947 0 : item.set_remote_site_id(tinfo.site);
948 0 : item.set_remote_deployment_id(tinfo.deployment);
949 0 : item.set_remote_label_ids(tinfo.labels);
950 0 : item.set_remote_custom_tag_ids(tinfo.custom_tags);
951 :
952 0 : item.set_remote_vn(entry->remote_vn);
953 0 : item.set_local_vn(entry->local_vn);
954 0 : item.set_action(entry->action);
955 0 : item.set_added(entry->added - entry->prev_added);
956 0 : item.set_deleted(entry->deleted - entry->prev_deleted);
957 0 : item.set_active(entry->active);
958 0 : item.set_in_bytes(entry->in_bytes - entry->prev_in_bytes);
959 0 : item.set_in_pkts(entry->in_pkts - entry->prev_in_pkts);
960 0 : item.set_out_bytes(entry->out_bytes - entry->prev_out_bytes);
961 0 : item.set_out_pkts(entry->out_pkts - entry->prev_out_pkts);
962 0 : olist->push_back(item);
963 :
964 0 : entry->prev_in_bytes = entry->in_bytes;
965 0 : entry->prev_in_pkts = entry->in_pkts;
966 0 : entry->prev_out_bytes = entry->out_bytes;
967 0 : entry->prev_out_pkts = entry->out_pkts;
968 0 : entry->prev_added = entry->added;
969 0 : entry->prev_deleted = entry->deleted;
970 :
971 0 : ++sit;
972 0 : }
973 0 : }
974 :
975 0 : void InterfaceUveTable::UveInterfaceEntry::FillTagSetAndPolicyList
976 : (VMIStats *obj) {
977 :
978 0 : vector<string> rule_list;
979 : SecurityPolicyStatsMap::const_iterator it =
980 0 : security_policy_stats_map_.begin();
981 0 : while (it != security_policy_stats_map_.end()) {
982 0 : rule_list.push_back(it->first);
983 0 : ++it;
984 : }
985 0 : obj->set_policy_rules(rule_list);
986 0 : }
987 :
988 0 : void InterfaceUveTable::UveInterfaceEntry::BuildSandeshUveTagList
989 : (const TagList &list, vector<SandeshUveTagInfo> *rts) const {
990 0 : TagList::const_iterator it = list.begin();
991 0 : while (it != list.end()) {
992 0 : SandeshUveTagInfo tag_entry;
993 0 : uint64_t ttype = (uint64_t)*it >> TagEntry::kTagTypeBitShift;
994 0 : tag_entry.set_type(TagEntry::GetTypeStr(ttype));
995 0 : tag_entry.set_id(*it);
996 0 : AgentDBTable *table = static_cast<AgentDBTable *>(intf_->get_table());
997 0 : tag_entry.set_name(table->agent()->tag_table()->TagName(*it));
998 0 : rts->push_back(tag_entry);
999 0 : ++it;
1000 0 : }
1001 0 : }
1002 :
1003 0 : void InterfaceUveTable::UveInterfaceEntry::BuildInterfaceUveSecurityPolicyList
1004 : (const SecurityPolicyStatsSet &ilist,
1005 : vector<SandeshUveRemoteEndpoint> *olist) const {
1006 0 : SecurityPolicyStatsSet::const_iterator sit = ilist.begin();
1007 0 : while (sit != ilist.end()) {
1008 0 : SandeshUveRemoteEndpoint rep;
1009 0 : UveSecurityPolicyStatsPtr entry(*sit);
1010 0 : ++sit;
1011 :
1012 0 : rep.set_remote_vn(entry->remote_vn);
1013 0 : rep.set_local_vn(entry->local_vn);
1014 0 : rep.set_remote_prefix(entry->remote_prefix);
1015 :
1016 0 : vector<SandeshUveTagInfo> lts;
1017 0 : BuildSandeshUveTagList(entry->local_tagset, <s);
1018 0 : rep.set_local_tagset(lts);
1019 0 : vector<SandeshUveTagInfo> rts;
1020 0 : BuildSandeshUveTagList(entry->remote_tagset, &rts);
1021 0 : rep.set_remote_tagset(rts);
1022 0 : rep.set_added(entry->added);
1023 0 : rep.set_deleted(entry->deleted);
1024 0 : rep.set_active(entry->active);
1025 0 : rep.set_dropped_short(entry->dropped_short);
1026 0 : rep.set_in_bytes(entry->in_bytes);
1027 0 : rep.set_in_pkts(entry->in_pkts);
1028 0 : rep.set_out_bytes(entry->out_bytes);
1029 0 : rep.set_out_pkts(entry->out_pkts);
1030 0 : rep.set_prev_in_bytes(entry->prev_in_bytes);
1031 0 : rep.set_prev_in_pkts(entry->prev_in_pkts);
1032 0 : rep.set_prev_out_bytes(entry->prev_out_bytes);
1033 0 : rep.set_prev_out_pkts(entry->prev_out_pkts);
1034 0 : rep.set_action(entry->action);
1035 :
1036 0 : olist->push_back(rep);
1037 0 : }
1038 0 : }
1039 :
1040 0 : void InterfaceUveTable::UveInterfaceEntry::BuildInterfaceUveInfo
1041 : (InterfaceUveInfo *r) const {
1042 0 : r->set_name(intf_->cfg_name());
1043 :
1044 0 : vector<SandeshUveTagInfo> lts;
1045 0 : BuildSandeshUveTagList(local_tagset_, <s);
1046 0 : r->set_local_tagset(lts);
1047 :
1048 0 : vector<SandeshUvePolicyInfo> policy_list;
1049 : SecurityPolicyStatsMap::const_iterator it =
1050 0 : security_policy_stats_map_.begin();
1051 0 : while (it != security_policy_stats_map_.end()) {
1052 0 : SandeshUvePolicyInfo item;
1053 0 : item.set_name(it->first);
1054 0 : const EndpointStatsContainer &cont = it->second;
1055 0 : BuildInterfaceUveSecurityPolicyList(cont.client_list,
1056 : &item.client_list);
1057 0 : BuildInterfaceUveSecurityPolicyList(cont.server_list,
1058 : &item.server_list);
1059 0 : policy_list.push_back(item);
1060 0 : ++it;
1061 0 : }
1062 0 : r->set_policy_list(policy_list);
1063 0 : }
|