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