Line data Source code
1 : /*
2 : * Copyright (c) 2013 Juniper Networks, Inc. All rights reserved.
3 : */
4 :
5 : #include <sstream>
6 : #include <fstream>
7 : #include <sandesh/common/vns_types.h>
8 : #include <uve/vrouter_uve_entry.h>
9 : #include <cfg/cfg_init.h>
10 : #include <init/agent_param.h>
11 : #include <oper/interface_common.h>
12 : #include <oper/interface.h>
13 : #include <oper/vm.h>
14 : #include <oper/vn.h>
15 : #include <oper/mirror_table.h>
16 : #include <controller/controller_peer.h>
17 : #include <uve/agent_uve_base.h>
18 : #include <cmn/agent_stats.h>
19 : #include <base/cpuinfo.h>
20 : #include <base/util.h>
21 : #include <cmn/agent_cmn.h>
22 : #include <oper/operdb_init.h>
23 : #include <oper/bgp_as_service.h>
24 :
25 : using namespace std;
26 :
27 : extern const std::string BuildInfo;
28 :
29 6 : VrouterUveEntryBase::VrouterUveEntryBase(Agent *agent)
30 6 : : agent_(agent), phy_intf_set_(), prev_stats_(), prev_vrouter_(),
31 6 : cpu_stats_count_(0), do_vn_walk_(false), do_vm_walk_(false),
32 6 : do_interface_walk_(false), vn_walk_ref_(NULL), vm_walk_ref_(NULL),
33 6 : interface_walk_ref_(NULL), vn_listener_id_(DBTableBase::kInvalidId),
34 6 : vm_listener_id_(DBTableBase::kInvalidId),
35 6 : intf_listener_id_(DBTableBase::kInvalidId),
36 6 : physical_device_listener_id_(DBTableBase::kInvalidId),
37 12 : timer_(TimerManager::CreateTimer(
38 6 : *(agent_->event_manager())->io_service(), "UveDBWalkTimer",
39 6 : TaskScheduler::GetInstance()->GetTaskId(kTaskDBExclude), 0)) {
40 6 : StartTimer();
41 :
42 6 : }
43 :
44 6 : VrouterUveEntryBase::~VrouterUveEntryBase() {
45 6 : }
46 :
47 6 : void VrouterUveEntryBase::StartTimer() {
48 6 : timer_->Cancel();
49 6 : uint32_t tm_interval = AgentUveBase::kDefaultInterval;
50 6 : if (agent_ != nullptr && agent_->uve() != nullptr) {
51 0 : tm_interval = agent_->uve()->default_interval();
52 : }
53 6 : timer_->Start(tm_interval,
54 : boost::bind(&VrouterUveEntryBase::TimerExpiry, this));
55 6 : }
56 :
57 0 : bool VrouterUveEntryBase::TimerExpiry() {
58 0 : bool restart = Run();
59 0 : return restart;
60 : }
61 :
62 0 : bool VrouterUveEntryBase::Run() {
63 : /* We don't do vn, vm and interface walks simultaneously to avoid creation
64 : * of multiple threads (caused by start of walks). After all the walks are
65 : * done we re-start the timer */
66 0 : bool walk_started = StartVnWalk();
67 :
68 : /* If VN walk is not started, start VM walk */
69 0 : if (!walk_started) {
70 0 : walk_started = StartVmWalk();
71 :
72 : /* If neither VN nor VM walks have started, start interface walk */
73 0 : if (!walk_started) {
74 0 : walk_started = StartInterfaceWalk();
75 :
76 : /* If none of the walks are started, return true to trigger
77 : * auto restart of timer */
78 0 : if (!walk_started) {
79 0 : return true;
80 : }
81 : }
82 : }
83 :
84 0 : return false;
85 : }
86 :
87 2 : void VrouterUveEntryBase::PhysicalDeviceNotify(DBTablePartBase *partition,
88 : DBEntryBase *e) {
89 2 : const PhysicalDevice *pr = static_cast<const PhysicalDevice *>(e);
90 : VrouterPhysicalDeviceState *state = static_cast<VrouterPhysicalDeviceState *>
91 2 : (e->GetState(partition->parent(), physical_device_listener_id_));
92 2 : if (e->IsDeleted()) {
93 1 : if (state) {
94 1 : e->ClearState(partition->parent(), physical_device_listener_id_);
95 1 : delete state;
96 : }
97 : } else {
98 1 : if (!state) {
99 1 : state = new VrouterPhysicalDeviceState();
100 1 : e->SetState(partition->parent(), physical_device_listener_id_,
101 : state);
102 1 : do_interface_walk_ = true;
103 : } else {
104 0 : if (state->master_ != pr->master()) {
105 0 : do_interface_walk_ = true;
106 : }
107 : }
108 1 : state->master_ = pr->master();
109 : }
110 2 : }
111 :
112 3 : void VrouterUveEntryBase::RegisterDBClients() {
113 3 : VnTable *vn_table = agent_->vn_table();
114 3 : vn_listener_id_ = vn_table->Register
115 3 : (boost::bind(&VrouterUveEntryBase::VnNotify, this, _1, _2));
116 :
117 3 : VmTable *vm_table = agent_->vm_table();
118 3 : vm_listener_id_ = vm_table->Register
119 3 : (boost::bind(&VrouterUveEntryBase::VmNotify, this, _1, _2));
120 :
121 3 : InterfaceTable *intf_table = agent_->interface_table();
122 3 : intf_listener_id_ = intf_table->Register
123 3 : (boost::bind(&VrouterUveEntryBase::InterfaceNotify, this, _1, _2));
124 :
125 3 : PhysicalDeviceTable *pd_table = agent_->physical_device_table();
126 3 : physical_device_listener_id_ = pd_table->Register
127 3 : (boost::bind(&VrouterUveEntryBase::PhysicalDeviceNotify, this, _1, _2));
128 3 : }
129 :
130 6 : void VrouterUveEntryBase::Shutdown(void) {
131 6 : if (physical_device_listener_id_ != DBTableBase::kInvalidId)
132 3 : agent_->physical_device_table()->
133 3 : Unregister(physical_device_listener_id_);
134 6 : if (intf_listener_id_ != DBTableBase::kInvalidId)
135 3 : agent_->interface_table()->Unregister(intf_listener_id_);
136 6 : if (vm_listener_id_ != DBTableBase::kInvalidId)
137 3 : agent_->vm_table()->Unregister(vm_listener_id_);
138 6 : if (vn_listener_id_ != DBTableBase::kInvalidId)
139 3 : agent_->vn_table()->Unregister(vn_listener_id_);
140 6 : if (interface_walk_ref_.get() != NULL)
141 0 : agent_->interface_table()->ReleaseWalker(interface_walk_ref_);
142 6 : if (vn_walk_ref_.get() != NULL)
143 0 : agent_->vn_table()->ReleaseWalker(vn_walk_ref_);
144 6 : if (vm_walk_ref_.get() != NULL)
145 0 : agent_->vm_table()->ReleaseWalker(vm_walk_ref_);
146 6 : if (timer_) {
147 6 : timer_->Cancel();
148 6 : TimerManager::DeleteTimer(timer_);
149 6 : timer_ = NULL;
150 : }
151 6 : vn_walk_ref_ = NULL;
152 6 : vm_walk_ref_ = NULL;
153 6 : interface_walk_ref_ = NULL;
154 6 : }
155 :
156 0 : void VrouterUveEntryBase::DispatchVrouterMsg(const VrouterAgent &uve) {
157 0 : UveVrouterAgent::Send(uve);
158 0 : }
159 :
160 0 : void VrouterUveEntryBase::VmWalkDone(DBTableBase *base, StringVectorPtr list) {
161 0 : VrouterAgent vrouter_agent;
162 0 : vrouter_agent.set_name(agent_->agent_name());
163 0 : vrouter_agent.set_virtual_machine_list(*(list.get()));
164 0 : VrouterAgentObjectCount vm_count;
165 0 : vm_count.set_active(list.get()->size());
166 0 : vrouter_agent.set_vm_count(vm_count);
167 0 : DispatchVrouterMsg(vrouter_agent);
168 :
169 : /* Start Interface Walk after we are done with Vm Walk */
170 0 : bool walk_started = StartInterfaceWalk();
171 :
172 : /* If interface walk has not started, restart the timer */
173 0 : if (!walk_started) {
174 0 : StartTimer();
175 : }
176 0 : (*list).clear();
177 0 : }
178 :
179 0 : bool VrouterUveEntryBase::AppendVm(DBTablePartBase *part, DBEntryBase *entry,
180 : StringVectorPtr list) {
181 0 : VmEntry *vm = static_cast<VmEntry *>(entry);
182 :
183 0 : if (!vm->IsDeleted()) {
184 0 : std::ostringstream ostr;
185 0 : ostr << vm->GetUuid();
186 0 : list.get()->push_back(ostr.str());
187 0 : }
188 0 : return true;
189 : }
190 :
191 0 : bool VrouterUveEntryBase::StartVmWalk() {
192 0 : if (!do_vm_walk_) {
193 : /* There is no change in VM list. No need of walk */
194 0 : return false;
195 : }
196 0 : if (vm_walk_ref_.get() == NULL) {
197 0 : StringVectorPtr vm_list(new vector<string>());
198 0 : vm_walk_ref_ = agent_->vm_table()->AllocWalker(
199 0 : boost::bind(&VrouterUveEntryBase::AppendVm, this, _1, _2, vm_list),
200 0 : boost::bind(&VrouterUveEntryBase::VmWalkDone, this, _2, vm_list));
201 0 : }
202 0 : agent_->vm_table()->WalkAgain(vm_walk_ref_);
203 0 : do_vm_walk_ = false;
204 0 : return true;
205 : }
206 :
207 24 : void VrouterUveEntryBase::VmNotify(DBTablePartBase *partition, DBEntryBase *e) {
208 : DBState *state = static_cast<DBState *>
209 24 : (e->GetState(partition->parent(), vm_listener_id_));
210 :
211 24 : if (e->IsDeleted()) {
212 12 : if (state) {
213 12 : do_vm_walk_ = true;
214 12 : e->ClearState(partition->parent(), vm_listener_id_);
215 12 : delete state;
216 : }
217 12 : return;
218 : }
219 :
220 12 : if (!state) {
221 12 : state = new DBState();
222 12 : e->SetState(partition->parent(), vm_listener_id_, state);
223 : //Send vrouter object only for a add/delete
224 12 : do_vm_walk_ = true;
225 : }
226 : }
227 :
228 0 : void VrouterUveEntryBase::VnWalkDone(DBTableBase *base, StringVectorPtr list) {
229 0 : VrouterAgent vrouter_agent;
230 0 : vrouter_agent.set_name(agent_->agent_name());
231 0 : vrouter_agent.set_connected_networks(*(list.get()));
232 0 : vrouter_agent.set_vn_count((*list).size());
233 0 : DispatchVrouterMsg(vrouter_agent);
234 :
235 : //Update prev_vrouter_ fields. Currently used only in UT
236 0 : prev_vrouter_.set_connected_networks(*(list.get()));
237 0 : prev_vrouter_.set_vn_count((*list).size());
238 :
239 : /* Start Vm Walk after we are done with Vn Walk */
240 0 : bool walk_started = StartVmWalk();
241 :
242 : /* If VM walk has not started, start interface walk */
243 0 : if (!walk_started) {
244 0 : walk_started = StartInterfaceWalk();
245 :
246 : /* If interface walk has not started, restart the timer */
247 0 : if (!walk_started) {
248 0 : StartTimer();
249 : }
250 : }
251 0 : (*list).clear();
252 0 : }
253 :
254 0 : bool VrouterUveEntryBase::AppendVn(DBTablePartBase *part, DBEntryBase *entry,
255 : StringVectorPtr list) {
256 0 : VnEntry *vn = static_cast<VnEntry *>(entry);
257 :
258 0 : if (!vn->IsDeleted()) {
259 0 : list.get()->push_back(vn->GetName());
260 : }
261 0 : return true;
262 : }
263 :
264 0 : bool VrouterUveEntryBase::StartVnWalk() {
265 0 : if (!do_vn_walk_) {
266 : /* There is no change in VN list. No need of walk */
267 0 : return false;
268 : }
269 0 : if (vn_walk_ref_.get() == NULL) {
270 0 : StringVectorPtr vn_list(new vector<string>());
271 0 : vn_walk_ref_ = agent_->vn_table()->AllocWalker(
272 0 : boost::bind(&VrouterUveEntryBase::AppendVn, this, _1, _2, vn_list),
273 0 : boost::bind(&VrouterUveEntryBase::VnWalkDone, this, _2, vn_list));
274 :
275 0 : }
276 0 : agent_->vn_table()->WalkAgain(vn_walk_ref_);
277 0 : do_vn_walk_ = false;
278 0 : return true;
279 : }
280 :
281 19 : void VrouterUveEntryBase::VnNotify(DBTablePartBase *partition, DBEntryBase *e) {
282 : DBState *state = static_cast<DBState *>
283 19 : (e->GetState(partition->parent(), vn_listener_id_));
284 :
285 19 : if (e->IsDeleted()) {
286 6 : if (state) {
287 6 : do_vn_walk_ = true;
288 6 : e->ClearState(partition->parent(), vn_listener_id_);
289 6 : delete state;
290 : }
291 6 : return;
292 : }
293 :
294 13 : if (!state) {
295 6 : state = new DBState();
296 6 : e->SetState(partition->parent(), vn_listener_id_, state);
297 6 : do_vn_walk_ = true;
298 : }
299 : }
300 :
301 0 : void VrouterUveEntryBase::InterfaceWalkDone(DBTableBase *base,
302 : StringVectorPtr if_list,
303 : StringVectorPtr err_if_list,
304 : StringVectorPtr nova_if_list,
305 : StringVectorPtr unmanaged_list) {
306 0 : VrouterAgent vrouter_agent;
307 0 : vrouter_agent.set_name(agent_->agent_name());
308 0 : vrouter_agent.set_interface_list(*(if_list.get()));
309 0 : vrouter_agent.set_error_intf_list(*(err_if_list.get()));
310 0 : vrouter_agent.set_no_config_intf_list(*(nova_if_list.get()));
311 0 : if (agent_->tsn_enabled()) {
312 0 : vrouter_agent.set_unmanaged_if_list(*(unmanaged_list.get()));
313 0 : prev_vrouter_.set_unmanaged_if_list(*(unmanaged_list.get()));
314 : }
315 :
316 0 : VrouterAgentObjectCount vmi_count;
317 0 : vmi_count.set_active((if_list.get()->size() + nova_if_list.get()->size()));
318 0 : vrouter_agent.set_vmi_count(vmi_count);
319 0 : vrouter_agent.set_down_interface_count((err_if_list.get()->size() +
320 0 : nova_if_list.get()->size()));
321 0 : DispatchVrouterMsg(vrouter_agent);
322 :
323 : //Update prev_vrouter_ fields. This is being used now only for UT
324 0 : prev_vrouter_.set_interface_list(*(if_list.get()));
325 0 : prev_vrouter_.set_error_intf_list(*(err_if_list.get()));
326 0 : prev_vrouter_.set_no_config_intf_list(*(nova_if_list.get()));
327 :
328 0 : (*if_list).clear();
329 0 : (*err_if_list).clear();
330 0 : (*nova_if_list).clear();
331 0 : (*unmanaged_list).clear();
332 : /* Restart the timer after we are done with the walk */
333 0 : StartTimer();
334 0 : }
335 :
336 0 : bool VrouterUveEntryBase::AppendInterface(DBTablePartBase *part,
337 : DBEntryBase *entry,
338 : StringVectorPtr intf_list,
339 : StringVectorPtr err_if_list,
340 : StringVectorPtr nova_if_list,
341 : StringVectorPtr unmanaged_list) {
342 0 : Interface *intf = static_cast<Interface *>(entry);
343 :
344 0 : if (intf->type() == Interface::VM_INTERFACE) {
345 0 : const VmInterface *port = static_cast<const VmInterface *>(intf);
346 0 : if (!entry->IsDeleted()) {
347 0 : if (port->cfg_name() == agent_->NullString()) {
348 0 : nova_if_list.get()->push_back(UuidToString(port->GetUuid()));
349 : } else {
350 0 : if (agent_->tsn_enabled()) {
351 : /* For TSN nodes send VMI in interface_list if the VMI's
352 : * physical device has tsn_enabled set to true. Otherwise
353 : * send the VMI in unmanaged_list */
354 0 : PhysicalDevice *pd = VmiToPhysicalDevice(port);
355 0 : if (!pd || !pd->master()) {
356 0 : unmanaged_list.get()->push_back(port->cfg_name());
357 0 : return true;
358 : }
359 0 : AppendInterfaceInternal(port, intf_list, err_if_list);
360 : } else {
361 0 : AppendInterfaceInternal(port, intf_list, err_if_list);
362 : }
363 : }
364 : }
365 : }
366 0 : else if (intf->type() == Interface::PHYSICAL) {
367 0 : const PhysicalInterface *phy_intf = static_cast<const
368 : PhysicalInterface *>(intf);
369 0 : if (phy_intf) {
370 : PhysicalInterface::BondChildIntfMap bond_childIntf_map =
371 0 : phy_intf->getBondChildIntfMap();
372 : PhysicalInterface::BondChildIntfMapIterator it =
373 0 : bond_childIntf_map.begin();
374 0 : for(; it != bond_childIntf_map.end(); it++) {
375 0 : PhysicalInterface::Bond_ChildIntf bond_intf;
376 0 : bond_intf = it->second;
377 0 : if(!bond_intf.intf_status) {
378 0 : err_if_list.get()->push_back(it->first);
379 : }
380 0 : }
381 0 : }
382 : }
383 0 : return true;
384 : }
385 :
386 0 : void VrouterUveEntryBase::AppendInterfaceInternal(const VmInterface *port,
387 : StringVectorPtr intf_list,
388 : StringVectorPtr err_if_list) {
389 0 : intf_list.get()->push_back(port->cfg_name());
390 0 : if (!port->IsUveActive()) {
391 0 : err_if_list.get()->push_back(port->cfg_name());
392 : }
393 0 : }
394 :
395 0 : PhysicalDevice *VrouterUveEntryBase::VmiToPhysicalDevice
396 : (const VmInterface *port) {
397 0 : const boost::uuids::uuid u = port->logical_interface();
398 0 : if (u == boost::uuids::nil_uuid()) {
399 0 : return NULL;
400 : }
401 : LogicalInterface *intf;
402 0 : VlanLogicalInterfaceKey key(u, "");
403 0 : intf = static_cast<LogicalInterface *>
404 0 : (agent_->interface_table()->FindActiveEntry(&key));
405 0 : if (!intf || !intf->physical_interface()) {
406 0 : return NULL;
407 : }
408 0 : return InterfaceToPhysicalDevice(intf->physical_interface());
409 0 : }
410 :
411 0 : PhysicalDevice *VrouterUveEntryBase::InterfaceToPhysicalDevice(Interface *intf) {
412 0 : PhysicalDevice *pde = NULL;
413 : const RemotePhysicalInterface *rpintf;
414 : const PhysicalInterface *pintf;
415 0 : if (intf->type() == Interface::REMOTE_PHYSICAL) {
416 0 : rpintf = static_cast<const RemotePhysicalInterface *>(intf);
417 0 : pde = rpintf->physical_device();
418 0 : } else if (intf->type() == Interface::PHYSICAL) {
419 0 : pintf = static_cast<const PhysicalInterface *>(intf);
420 0 : pde = pintf->physical_device();
421 : }
422 0 : return pde;
423 : }
424 :
425 0 : bool VrouterUveEntryBase::StartInterfaceWalk() {
426 0 : if (!do_interface_walk_) {
427 : /* There is no change in interface list. No need of walk */
428 0 : return false;
429 : }
430 0 : if (interface_walk_ref_.get() == NULL) {
431 0 : StringVectorPtr intf_list(new std::vector<std::string>());
432 0 : StringVectorPtr err_if_list(new std::vector<std::string>());
433 0 : StringVectorPtr nova_if_list(new std::vector<std::string>());
434 0 : StringVectorPtr unmanaged_list(new std::vector<std::string>());
435 :
436 0 : interface_walk_ref_ = agent_->interface_table()->AllocWalker(
437 0 : boost::bind(&VrouterUveEntryBase::AppendInterface, this, _1, _2,
438 : intf_list, err_if_list, nova_if_list, unmanaged_list),
439 0 : boost::bind(&VrouterUveEntryBase::InterfaceWalkDone, this, _2,
440 0 : intf_list, err_if_list, nova_if_list, unmanaged_list));
441 0 : }
442 0 : agent_->interface_table()->WalkAgain(interface_walk_ref_);
443 0 : do_interface_walk_ = false;
444 0 : return true;
445 : }
446 :
447 98 : void VrouterUveEntryBase::InterfaceNotify(DBTablePartBase *partition,
448 : DBEntryBase *e) {
449 98 : const Interface *intf = static_cast<const Interface *>(e);
450 98 : bool set_state = false, reset_state = false;
451 :
452 : VrouterUveInterfaceState *state = static_cast<VrouterUveInterfaceState *>
453 98 : (e->GetState(partition->parent(), intf_listener_id_));
454 98 : bool vmport_active = false;
455 98 : const VmInterface *vm_port = NULL;
456 98 : switch(intf->type()) {
457 71 : case Interface::VM_INTERFACE:
458 71 : vm_port = static_cast<const VmInterface*>(intf);
459 71 : if (!e->IsDeleted() && !state) {
460 17 : set_state = true;
461 17 : vmport_active = vm_port->IsUveActive();
462 17 : do_interface_walk_ = true;
463 54 : } else if (e->IsDeleted()) {
464 17 : if (state) {
465 17 : reset_state = true;
466 17 : do_interface_walk_ = true;
467 : }
468 : } else {
469 37 : if (state && vm_port->IsUveActive() != state->vmport_active_) {
470 14 : do_interface_walk_ = true;
471 14 : state->vmport_active_ = vm_port->IsUveActive();
472 : }
473 : }
474 71 : break;
475 13 : case Interface::PHYSICAL:
476 13 : if (e->IsDeleted()) {
477 6 : if (state) {
478 5 : reset_state = true;
479 5 : phy_intf_set_.erase(intf);
480 : }
481 : } else {
482 7 : const PhysicalInterface* phy_if =
483 : static_cast<const PhysicalInterface*>(intf);
484 : /* Ignore PhysicalInterface notifications if it is not of subtype
485 : * FABRIC */
486 7 : if (phy_if->subtype() != PhysicalInterface::FABRIC) {
487 2 : return;
488 : }
489 5 : if (!state) {
490 5 : set_state = true;
491 5 : phy_intf_set_.insert(intf);
492 : }
493 5 : if (phy_if) {
494 : PhysicalInterface::BondChildIntfMap bond_childIntf_map =
495 5 : phy_if->getBondChildIntfMap();
496 : PhysicalInterface::BondChildIntfMapIterator it =
497 5 : bond_childIntf_map.begin();
498 5 : for(; it != bond_childIntf_map.end(); it++) {
499 0 : PhysicalInterface::Bond_ChildIntf bond_intf;
500 0 : bond_intf = it->second;
501 0 : if(!bond_intf.intf_status) {
502 0 : do_interface_walk_ = true;
503 : }
504 : else {
505 : std::vector<std::string> prev_err_if_list =
506 0 : prev_vrouter_.get_error_intf_list();
507 0 : if (std::find(prev_err_if_list.begin(),
508 0 : prev_err_if_list.end(), it->first)
509 0 : != prev_err_if_list.end()) {
510 0 : do_interface_walk_ = true;
511 : }
512 0 : }
513 0 : }
514 5 : }
515 : }
516 11 : break;
517 14 : default:
518 14 : break;
519 : }
520 96 : if (set_state) {
521 22 : state = new VrouterUveInterfaceState(vmport_active);
522 22 : e->SetState(partition->parent(), intf_listener_id_, state);
523 74 : } else if (reset_state) {
524 22 : e->ClearState(partition->parent(), intf_listener_id_);
525 22 : delete state;
526 : }
527 96 : return;
528 : }
529 :
530 0 : void VrouterUveEntryBase::SubnetToStringList
531 : (VirtualGatewayConfig::SubnetList &source_list, vector<string> &target_list) {
532 : VirtualGatewayConfig::SubnetList::iterator subnet_it =
533 0 : source_list.begin();
534 0 : while (subnet_it != source_list.end()) {
535 0 : string subnet_str = subnet_it->ip_.to_string() + "/" +
536 0 : integerToString(subnet_it->plen_);
537 0 : target_list.push_back(subnet_str);
538 0 : ++subnet_it;
539 0 : }
540 0 : }
541 :
542 0 : void VrouterUveEntryBase::BuildAgentConfig(VrouterAgent &vrouter_agent) {
543 0 : AgentVhostConfig vhost_cfg;
544 0 : AgentXenConfig xen_cfg;
545 0 : AgentVmwareConfig vmware_cfg;
546 0 : string hypervisor;
547 0 : vector<AgentVgwConfig> gw_cfg_list;
548 :
549 0 : AgentParam *param = agent_->params();
550 :
551 0 : vrouter_agent.set_log_file(param->log_file());
552 0 : vrouter_agent.set_config_file(param->config_file());
553 0 : vrouter_agent.set_log_local(param->log_local());
554 0 : vrouter_agent.set_log_flow(param->log_flow());
555 0 : vrouter_agent.set_log_category(param->log_category());
556 0 : vrouter_agent.set_log_level(param->log_level());
557 0 : vrouter_agent.set_sandesh_http_port(param->http_server_port());
558 0 : vrouter_agent.set_tunnel_type(param->tunnel_type());
559 0 : vrouter_agent.set_hostname_cfg(param->host_name());
560 0 : vrouter_agent.set_flow_cache_timeout_cfg(param->flow_cache_timeout());
561 :
562 0 : vrouter_agent.set_dns_server_list_cfg(param->dns_server_list());
563 0 : vrouter_agent.set_control_node_list_cfg(param->controller_server_list());
564 :
565 0 : vrouter_agent.set_ll_max_system_flows_cfg(param->linklocal_system_flows());
566 0 : vrouter_agent.set_ll_max_vm_flows_cfg(param->linklocal_vm_flows());
567 0 : vrouter_agent.set_control_ip(param->mgmt_ip().to_string());
568 :
569 0 : vhost_cfg.set_name(param->vhost_name());
570 0 : if (agent_->is_l3mh() == false) {
571 0 : vhost_cfg.set_ip(param->vhost_addr().to_string());
572 0 : vhost_cfg.set_ip_prefix_len(param->vhost_plen());
573 0 : if (param->gateway_list().empty() == false) {
574 0 : vhost_cfg.set_gateway(param->gateway_list()[0].to_string());
575 : }
576 : }
577 0 : vrouter_agent.set_vhost_cfg(vhost_cfg);
578 :
579 0 : vrouter_agent.set_eth_name(param->eth_port_list());
580 :
581 0 : if (param->isKvmMode()) {
582 0 : hypervisor = "kvm";
583 0 : } else if (param->isXenMode()) {
584 0 : hypervisor = "xen";
585 0 : xen_cfg.set_xen_ll_port(param->xen_ll_name());
586 0 : xen_cfg.set_xen_ll_ip(param->xen_ll_addr().to_string());
587 0 : xen_cfg.set_xen_ll_prefix_len(param->xen_ll_plen());
588 0 : vrouter_agent.set_xen_cfg(xen_cfg);
589 0 : } else if (param->isVmwareMode()) {
590 0 : hypervisor = "vmware";
591 0 : vmware_cfg.set_vmware_port(param->vmware_physical_port());
592 0 : vrouter_agent.set_vmware_cfg(vmware_cfg);
593 : }
594 0 : vrouter_agent.set_hypervisor(hypervisor);
595 :
596 0 : VirtualGatewayConfigTable *table = param->vgw_config_table();
597 0 : VirtualGatewayConfigTable::Table::iterator it = table->table().begin();
598 0 : while (it != table->table().end()) {
599 0 : AgentVgwConfig gw_cfg;
600 0 : VirtualGatewayConfig::SubnetList subnet_list = it->subnets();
601 0 : VirtualGatewayConfig::SubnetList route_list = it->routes();
602 0 : vector<string> ip_blocks_list;
603 0 : vector<string> route_str_list;
604 :
605 0 : SubnetToStringList(subnet_list, ip_blocks_list);
606 0 : SubnetToStringList(route_list, route_str_list);
607 :
608 0 : gw_cfg.set_interface_name(it->interface_name());
609 0 : gw_cfg.set_vrf_name(it->vrf_name());
610 0 : gw_cfg.set_ip_blocks_list(ip_blocks_list);
611 0 : gw_cfg.set_route_list(route_str_list);
612 :
613 0 : gw_cfg_list.push_back(gw_cfg);
614 0 : ++it;
615 0 : }
616 0 : vrouter_agent.set_gateway_cfg_list(gw_cfg_list);
617 0 : vrouter_agent.set_headless_mode_cfg(true);
618 0 : vrouter_agent.set_collector_server_list_cfg(param->collector_server_list());
619 0 : vrouter_agent.set_bgpaas_enabled(
620 0 : agent_->oper_db()->bgp_as_a_service()->IsConfigured());
621 0 : vrouter_agent.set_port_mirror_enabled(MirrorTable::GetInstance()->IsConfigured());
622 0 : vrouter_agent.set_loopback_ip(param->loopback_ip().to_string());
623 0 : std::vector<string> gateway_list;
624 0 : for (std::vector<Ip4Address>::const_iterator iter = param->gateway_list().begin();
625 0 : iter != param->gateway_list().end(); ++iter) {
626 0 : gateway_list.push_back((*iter).to_string());
627 : }
628 0 : vrouter_agent.set_gateway_list(gateway_list);
629 0 : }
630 :
631 :
632 0 : bool VrouterUveEntryBase::SendVrouterMsg() {
633 0 : VrouterAgent vrouter_agent;
634 0 : bool changed = false, bgp_aas, port_mirror;
635 : static bool first = true;
636 0 : vrouter_agent.set_name(agent_->agent_name());
637 0 : Ip4Address rid = agent_->router_id();
638 0 : vector<string> ip_list;
639 0 : vector<string> dns_list;
640 :
641 0 : if (first) {
642 : //Physical interface list
643 0 : vnsConstants vnsVrouterType;
644 : //vhost attributes
645 0 : const Interface *vhost = agent_->vhost_interface();
646 0 : if (vhost) {
647 0 : AgentInterface vitf;
648 0 : vitf.set_name(vhost->name());
649 0 : vitf.set_mac_address(GetMacAddress(vhost->mac()));
650 0 : vrouter_agent.set_vhost_if(vitf);
651 0 : }
652 :
653 : //Configuration. Needs to be sent only once because whenever config
654 : //changes agent will be restarted
655 0 : BuildAgentConfig(vrouter_agent);
656 :
657 : //Set the Agent mode
658 0 : if (agent_->tor_agent_enabled()) {
659 0 : vrouter_agent.set_mode(vnsVrouterType.VrouterAgentTypeMap.at
660 0 : (VrouterAgentType::VROUTER_AGENT_TOR));
661 0 : } else if (agent_->tsn_enabled()) {
662 0 : vrouter_agent.set_mode(vnsVrouterType.VrouterAgentTypeMap.at
663 0 : (VrouterAgentType::VROUTER_AGENT_TSN));
664 : } else {
665 0 : vrouter_agent.set_mode(vnsVrouterType.VrouterAgentTypeMap.at
666 0 : (VrouterAgentType::VROUTER_AGENT_EMBEDDED));
667 : }
668 :
669 0 : if (agent_->vrouter_on_nic_mode()) {
670 0 : vrouter_agent.set_platform(vnsVrouterType.
671 : VrouterAgentPlatformTypeMap.at
672 0 : (VrouterAgentPlatformType::
673 : VROUTER_AGENT_ON_NIC));
674 0 : } else if (agent_->vrouter_on_host_dpdk()) {
675 0 : vrouter_agent.set_platform(vnsVrouterType.
676 : VrouterAgentPlatformTypeMap.at
677 0 : (VrouterAgentPlatformType::
678 : VROUTER_AGENT_ON_HOST_DPDK));
679 0 : } else if (agent_->vrouter_on_host()) {
680 0 : vrouter_agent.set_platform(vnsVrouterType.
681 : VrouterAgentPlatformTypeMap.at
682 0 : (VrouterAgentPlatformType::
683 : VROUTER_AGENT_ON_HOST));
684 : }
685 :
686 0 : vrouter_agent.set_subcluster_name(agent_->subcluster_name());
687 0 : vrouter_agent.set_vr_high_watermark(agent_->vr_limit_high_watermark());
688 0 : vrouter_agent.set_vr_low_watermark(agent_->vr_limit_low_watermark());
689 0 : first = false;
690 0 : changed = true;
691 0 : }
692 :
693 0 : VrouterObjectLimits vr_limits = agent_->GetVrouterObjectLimits();
694 0 : VrouterObjectLimits prev_vr_limits = prev_vrouter_.get_vr_limits();
695 0 : if (vr_limits != prev_vr_limits) {
696 0 : vrouter_agent.set_vr_limits(vr_limits);
697 0 : prev_vrouter_.set_vr_limits(vr_limits);
698 0 : changed = true;
699 : }
700 :
701 0 : if (prev_vrouter_.get_build_info() != BuildInfo) {
702 0 : vrouter_agent.set_build_info(BuildInfo);
703 0 : prev_vrouter_.set_build_info(BuildInfo);
704 0 : changed = true;
705 : }
706 :
707 0 : bgp_aas = agent_->oper_db()->bgp_as_a_service()->IsConfigured();
708 0 : if (prev_vrouter_.get_bgpaas_enabled() != bgp_aas) {
709 0 : vrouter_agent.set_bgpaas_enabled(bgp_aas);
710 0 : prev_vrouter_.set_bgpaas_enabled(bgp_aas);
711 0 : changed = true;
712 : }
713 :
714 0 : port_mirror = MirrorTable::GetInstance()->IsConfigured();
715 0 : if (prev_vrouter_.get_port_mirror_enabled() != port_mirror) {
716 0 : vrouter_agent.set_port_mirror_enabled(port_mirror);
717 0 : prev_vrouter_.set_port_mirror_enabled(port_mirror);
718 0 : changed = true;
719 : }
720 :
721 0 : vector<AgentInterface> phy_if_list;
722 0 : PhysicalInterfaceSet::iterator it = phy_intf_set_.begin();
723 0 : while (it != phy_intf_set_.end()) {
724 0 : AgentInterface pitf;
725 0 : const Interface *intf = *it;
726 0 : const PhysicalInterface *port = static_cast
727 : <const PhysicalInterface *>(intf);
728 0 : pitf.set_name(intf->name());
729 0 : pitf.set_mac_address(GetMacAddress(port->mac()));
730 0 : phy_if_list.push_back(pitf);
731 0 : ++it;
732 0 : }
733 0 : if (prev_vrouter_.get_phy_if() != phy_if_list) {
734 0 : vrouter_agent.set_phy_if(phy_if_list);
735 0 : prev_vrouter_.set_phy_if(phy_if_list);
736 0 : changed = true;
737 : }
738 :
739 0 : std::vector<AgentXmppPeer> xmpp_list;
740 0 : for (int count = 0; count < MAX_XMPP_SERVERS; count++) {
741 0 : AgentXmppPeer peer;
742 0 : if (!agent_->controller_ifmap_xmpp_server(count).empty()) {
743 0 : peer.set_ip(agent_->controller_ifmap_xmpp_server(count));
744 0 : AgentXmppChannel *ch = agent_->controller_xmpp_channel(count);
745 0 : if (ch == NULL) {
746 0 : continue;
747 : }
748 0 : XmppChannel *xc = ch->GetXmppChannel();
749 0 : if (xc == NULL) {
750 0 : continue;
751 : }
752 0 : if (ch->bgp_peer_id() && xc->GetPeerState() == xmps::READY) {
753 0 : peer.set_status(true);
754 : } else {
755 0 : peer.set_status(false);
756 : }
757 0 : peer.set_setup_time(agent_->controller_xmpp_channel_setup_time(count));
758 0 : if (agent_->ifmap_active_xmpp_server_index() == count) {
759 0 : peer.set_primary(true);
760 : } else {
761 0 : peer.set_primary(false);
762 : }
763 0 : xmpp_list.push_back(peer);
764 : }
765 0 : }
766 :
767 0 : if (!prev_vrouter_.__isset.xmpp_peer_list ||
768 0 : prev_vrouter_.get_xmpp_peer_list() != xmpp_list) {
769 0 : vrouter_agent.set_xmpp_peer_list(xmpp_list);
770 0 : prev_vrouter_.set_xmpp_peer_list(xmpp_list);
771 0 : changed = true;
772 : }
773 : /* Self IP list should be populated only if router_id is configured */
774 0 : if (agent_->router_id_configured()) {
775 0 : ip_list.push_back(rid.to_string());
776 0 : if (!prev_vrouter_.__isset.self_ip_list ||
777 0 : prev_vrouter_.get_self_ip_list() != ip_list) {
778 :
779 0 : vrouter_agent.set_self_ip_list(ip_list);
780 0 : prev_vrouter_.set_self_ip_list(ip_list);
781 0 : changed = true;
782 : }
783 : }
784 :
785 0 : for (int idx = 0; idx < MAX_XMPP_SERVERS; idx++) {
786 0 : if (!agent_->dns_server(idx).empty()) {
787 0 : dns_list.push_back(agent_->dns_server(idx));
788 : }
789 : }
790 :
791 0 : if (!prev_vrouter_.__isset.dns_servers ||
792 0 : prev_vrouter_.get_dns_servers() != dns_list) {
793 0 : vrouter_agent.set_dns_servers(dns_list);
794 0 : prev_vrouter_.set_dns_servers(dns_list);
795 0 : changed = true;
796 : }
797 :
798 0 : std::vector<VrouterAgentResUsage> limit_exceeded_list;
799 0 : VrouterAgentResUsage usage;
800 0 : bool limit_exceeded = false;
801 0 : bool table_limit = false;
802 0 : VrLimitExceeded res_usage_map = agent_->get_vr_limits_exceeded_map();
803 0 : for(VrLimitExceeded::iterator res_map_it = res_usage_map.begin();
804 0 : res_map_it != res_usage_map.end(); ++res_map_it ) {
805 0 : if (res_map_it->second != "Normal") {
806 0 : usage.set_name(res_map_it->first);
807 0 : usage.set_status(res_map_it->second);
808 0 : limit_exceeded_list.push_back(usage);
809 0 : if (res_map_it->second == "TableLimit" && !table_limit) {
810 0 : table_limit = true;
811 0 : limit_exceeded = true;
812 0 : } else if (res_map_it->second == "Exceeded" && !limit_exceeded ) {
813 0 : limit_exceeded = true;
814 0 : table_limit = false;
815 : }
816 : }
817 : }
818 :
819 0 : if (!prev_vrouter_.__isset.vr_limit_exceeded_list ||
820 0 : prev_vrouter_.get_vr_limit_exceeded_list() != limit_exceeded_list) {
821 0 : vrouter_agent.set_vr_limit_exceeded_list(limit_exceeded_list);
822 0 : prev_vrouter_.set_vr_limit_exceeded_list(limit_exceeded_list);
823 0 : vrouter_agent.set_res_limit(limit_exceeded);
824 0 : vrouter_agent.set_res_table_limit(table_limit);
825 0 : changed = true;
826 : }
827 :
828 0 : if (agent_->is_l3mh()) {
829 0 : std::vector<L3mhPhysicalInterfaceStatus> vr_l3mh_intf_list;
830 0 : bool l3mh_phy_interface_down = false;
831 0 : PhysicalInterfaceSet::iterator it = phy_intf_set_.begin();
832 0 : while (it != phy_intf_set_.end()) {
833 0 : L3mhPhysicalInterfaceStatus l3mh_interface_status;
834 0 : const Interface *intf = *it;
835 0 : l3mh_interface_status.set_name(intf->name());
836 0 : l3mh_interface_status.set_active(intf->os_oper_state());
837 0 : vr_l3mh_intf_list.push_back(l3mh_interface_status);
838 0 : if (!intf->os_oper_state())
839 0 : l3mh_phy_interface_down = true;
840 0 : ++it;
841 0 : }
842 :
843 0 : if (!prev_vrouter_.__isset.vr_l3mh_intf_list ||
844 0 : prev_vrouter_.get_vr_l3mh_intf_list() != vr_l3mh_intf_list) {
845 0 : vrouter_agent.set_vr_l3mh_intf_list(vr_l3mh_intf_list);
846 0 : prev_vrouter_.set_vr_l3mh_intf_list(vr_l3mh_intf_list);
847 0 : vrouter_agent.set_l3mh_phy_interface_down(l3mh_phy_interface_down);
848 0 : changed = true;
849 : }
850 :
851 0 : }
852 0 : if (changed) {
853 0 : DispatchVrouterMsg(vrouter_agent);
854 : }
855 :
856 0 : VrouterStatsAgent stats;
857 0 : stats.set_name(agent_->agent_name());
858 0 : cpu_stats_count_++;
859 : /* CPU stats needs to be sent every minute. We are using '% 2' below
860 : * because timer is fired every 30 secs. If the timer interval is changed
861 : * we need to fix the '%' value below accordingly */
862 0 : if ((cpu_stats_count_ % 2) == 0) {
863 : static bool cpu_first = true;
864 0 : CpuLoadInfo cpu_load_info;
865 0 : CpuLoadData::FillCpuInfo(cpu_load_info, true);
866 0 : if (prev_stats_.get_cpu_info() != cpu_load_info || cpu_first) {
867 0 : stats.set_cpu_info(cpu_load_info);
868 0 : prev_stats_.set_cpu_info(cpu_load_info);
869 0 : changed = true;
870 0 : cpu_first = false;
871 0 : DispatchVrouterStatsMsg(stats);
872 : }
873 :
874 : //Stats oracle interface for cpu and mem stats. Needs to be sent
875 : //always regardless of whether the stats have changed since last send
876 0 : BuildAndSendComputeCpuStateMsg(cpu_load_info);
877 0 : cpu_stats_count_ = 0;
878 0 : }
879 0 : return changed;
880 0 : }
881 :
882 1 : void VrouterUveEntryBase::SendVrouterProuterAssociation
883 : (const vector<string> &list) {
884 2 : VrouterAgent vrouter_agent;
885 1 : vrouter_agent.set_name(agent_->agent_name());
886 1 : if (agent_->tor_agent_enabled()) {
887 0 : vrouter_agent.set_tor_prouter_list(list);
888 1 : } else if (agent_->tsn_enabled()) {
889 0 : vrouter_agent.set_tsn_prouter_list(list);
890 : } else {
891 1 : vrouter_agent.set_embedded_prouter_list(list);
892 : }
893 1 : DispatchVrouterMsg(vrouter_agent);
894 1 : }
895 :
896 0 : string VrouterUveEntryBase::GetMacAddress(const MacAddress &mac) const {
897 0 : return mac.ToString();
898 : }
899 :
900 0 : void VrouterUveEntryBase::DispatchVrouterStatsMsg(const VrouterStatsAgent &uve) {
901 0 : VrouterStats::Send(uve);
902 0 : }
903 :
904 0 : void VrouterUveEntryBase::DispatchComputeCpuStateMsg(const ComputeCpuState &ccs) {
905 0 : ComputeCpuStateTrace::Send(ccs);
906 0 : }
907 :
908 0 : void VrouterUveEntryBase::BuildAndSendComputeCpuStateMsg(const CpuLoadInfo &info) {
909 0 : ComputeCpuState astate;
910 0 : VrouterCpuInfo ainfo;
911 0 : vector<VrouterCpuInfo> aciv;
912 :
913 0 : astate.set_name(agent_->agent_name());
914 0 : ainfo.set_cpu_share(info.get_cpu_share());
915 0 : ainfo.set_mem_virt(info.get_meminfo().get_virt());
916 0 : ainfo.set_mem_res(info.get_meminfo().get_res());
917 0 : const SysMemInfo &sys_mem_info(info.get_sys_mem_info());
918 0 : ainfo.set_used_sys_mem(sys_mem_info.get_used() -
919 0 : sys_mem_info.get_buffers() - sys_mem_info.get_cached());
920 0 : ainfo.set_one_min_cpuload(info.get_cpuload().get_one_min_avg());
921 0 : aciv.push_back(ainfo);
922 0 : astate.set_cpu_info(aciv);
923 0 : DispatchComputeCpuStateMsg(astate);
924 0 : }
|