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