Line data Source code
1 : /*
2 : * Copyright (c) 2013 Juniper Networks, Inc. All rights reserved.
3 : */
4 :
5 : #include <base/contrail_ports.h>
6 : #include <cmn/dns.h>
7 : #include <bind/bind_util.h>
8 : #include <mgr/dns_mgr.h>
9 : #include <mgr/dns_oper.h>
10 : #include <bind/bind_resolver.h>
11 : #include <bind/named_config.h>
12 : #include <agent/agent_xmpp_channel.h>
13 :
14 15 : DnsManager::DnsManager()
15 15 : : bind_status_(boost::bind(&DnsManager::BindEventHandler, this, _1)),
16 15 : end_of_config_(false),
17 15 : record_send_count_(TaskScheduler::GetInstance()->HardwareThreadCount()),
18 15 : named_max_retransmissions_(kMaxRetransmitCount),
19 15 : named_retransmission_interval_(kPendingRecordReScheduleTime),
20 15 : named_lo_watermark_(kNamedLoWaterMark),
21 15 : named_hi_watermark_(kNamedHiWaterMark),
22 15 : named_send_throttled_(false),
23 15 : pending_done_queue_(TaskScheduler::GetInstance()->GetTaskId("dns::NamedSndRcv"), 0,
24 : boost::bind(&DnsManager::PendingDone, this, _1)),
25 45 : idx_(kMaxIndexAllocator) {
26 15 : std::vector<BindResolver::DnsServer> bind_servers;
27 15 : bind_servers.push_back(BindResolver::DnsServer("127.0.0.1",
28 15 : Dns::GetDnsPort()));
29 30 : BindResolver::Init(*Dns::GetEventManager()->io_service(), bind_servers,
30 15 : ContrailPorts::ContrailDnsClientUdpPort(),
31 : boost::bind(&DnsManager::HandleUpdateResponse,
32 : this, _1, _2), 0);
33 :
34 15 : Dns::SetDnsConfigManager(&config_mgr_);
35 15 : DnsConfigManager::Observers obs;
36 : obs.virtual_dns = boost::bind(&DnsManager::ProcessConfig<VirtualDnsConfig>,
37 15 : this, _1, _2, _3);
38 : obs.virtual_dns_record =
39 : boost::bind(&DnsManager::ProcessConfig<VirtualDnsRecordConfig>,
40 15 : this, _1, _2, _3);
41 15 : obs.ipam = boost::bind(&DnsManager::ProcessConfig<IpamConfig>, this, _1, _2, _3);
42 15 : obs.vnni = boost::bind(&DnsManager::ProcessConfig<VnniConfig>, this, _1, _2, _3);
43 : obs.global_qos = boost::bind(&DnsManager::ProcessConfig<GlobalQosConfig>,
44 15 : this, _1, _2, _3);
45 15 : Dns::GetDnsConfigManager()->RegisterObservers(obs);
46 :
47 15 : DnsConfig::VdnsCallback = boost::bind(&DnsManager::DnsView, this, _1, _2);
48 : DnsConfig::VdnsRecordCallback = boost::bind(&DnsManager::DnsRecord, this,
49 15 : _1, _2);
50 : DnsConfig::VdnsZoneCallback = boost::bind(&DnsManager::DnsPtrZone, this,
51 15 : _1, _2, _3);
52 15 : pending_timer_ =
53 15 : TimerManager::CreateTimer(*Dns::GetEventManager()->io_service(),
54 : "DnsRetransmitTimer",
55 : TaskScheduler::GetInstance()->GetTaskId("dns::NamedSndRcv"), 0);
56 :
57 15 : end_of_config_check_timer_ =
58 15 : TimerManager::CreateTimer(*Dns::GetEventManager()->io_service(),
59 : "Check_EndofConfig_Timer",
60 : TaskScheduler::GetInstance()->GetTaskId("dns::Config"), 0);
61 :
62 : // PreAllocate index 0 as it cannot be used as transaction id.
63 15 : idx_.AllocIndex();
64 15 : }
65 :
66 0 : void DnsManager::Initialize(DB *config_db, DBGraph *config_graph,
67 : const std::string& named_config_dir,
68 : const std::string& named_config_file,
69 : const std::string& named_log_file,
70 : const std::string& rndc_config_file,
71 : const std::string& rndc_secret,
72 : const std::string& named_max_cache_size,
73 : const uint16_t named_max_retransmissions,
74 : const uint16_t named_retranmission_interval) {
75 0 : NamedConfig::Init(named_config_dir, named_config_file,
76 : named_log_file, rndc_config_file, rndc_secret,
77 : named_max_cache_size);
78 0 : config_mgr_.Initialize(config_db, config_graph);
79 0 : named_max_retransmissions_ = named_max_retransmissions;
80 0 : named_retransmission_interval_ = named_retranmission_interval;
81 0 : }
82 :
83 15 : DnsManager::~DnsManager() {
84 15 : pending_timer_->Cancel();
85 15 : TimerManager::DeleteTimer(pending_timer_);
86 15 : end_of_config_check_timer_->Cancel();
87 15 : TimerManager::DeleteTimer(end_of_config_check_timer_);
88 15 : pending_done_queue_.Shutdown();
89 15 : }
90 :
91 15 : void DnsManager::Shutdown() {
92 15 : config_mgr_.Terminate();
93 15 : NamedConfig::Shutdown();
94 15 : BindResolver::Shutdown();
95 15 : }
96 :
97 : template <typename ConfigType>
98 171 : void DnsManager::ProcessConfig(IFMapNodeProxy *proxy,
99 : const std::string &name,
100 : DnsConfigManager::EventType event) {
101 171 : IFMapNode *node = proxy->node();
102 171 : ConfigType *config = ConfigType::Find(name);
103 171 : switch (event) {
104 58 : case DnsConfigManager::CFG_ADD:
105 58 : if (!config) {
106 50 : config = new ConfigType(node);
107 : }
108 58 : config->OnAdd(node);
109 58 : break;
110 :
111 55 : case DnsConfigManager::CFG_CHANGE:
112 55 : if (config)
113 55 : config->OnChange(node);
114 55 : break;
115 :
116 58 : case DnsConfigManager::CFG_DELETE:
117 58 : if (config) {
118 58 : config->OnDelete();
119 58 : delete config;
120 : }
121 58 : break;
122 :
123 0 : default:
124 0 : assert(0);
125 : }
126 171 : }
127 :
128 2 : void DnsManager::ProcessAgentUpdate(BindUtil::Operation event,
129 : const std::string &name,
130 : const std::string &vdns_name,
131 : const DnsItem &item) {
132 2 : std::scoped_lock lock(mutex_);
133 2 : VirtualDnsRecordConfig *config = VirtualDnsRecordConfig::Find(name);
134 2 : switch (event) {
135 1 : case BindUtil::ADD_UPDATE:
136 1 : if (!config) {
137 0 : config = new VirtualDnsRecordConfig(name, vdns_name, item);
138 : }
139 1 : config->rec_.source_name = item.source_name;
140 1 : config->rec_.vm_uuid = item.vm_uuid;
141 1 : config->OnAdd();
142 1 : break;
143 :
144 0 : case BindUtil::CHANGE_UPDATE:
145 0 : if (config)
146 0 : config->OnChange(item);
147 0 : break;
148 :
149 1 : case BindUtil::DELETE_UPDATE: {
150 1 : if (config) {
151 : // Ownership is the (vm_uuid, source_name) pair, not either
152 : // half alone. vm_uuid alone is not enough: a live-migrated
153 : // VM keeps its VMI UUID, so the cleanup DELETE from the
154 : // source compute would wipe the record the destination
155 : // compute has just published. source_name alone is not
156 : // enough either: a recreated VM landing on the same compute
157 : // reuses the JID (PRODX-61399). Agents that do not send
158 : // vm_uuid fall back to source_name only, and so do
159 : // records whose stored owner carries no vm_uuid: the
160 : // config path (VirtualDnsRecordConfig::GetObject) has no
161 : // schema field for it, so requiring a match there would
162 : // strand the record in named forever.
163 : bool same_owner =
164 1 : (config->rec_.source_name == item.source_name) &&
165 0 : (item.vm_uuid.empty() || config->rec_.vm_uuid.empty() ||
166 0 : config->rec_.vm_uuid == item.vm_uuid);
167 1 : if (same_owner) {
168 0 : config->OnDelete();
169 0 : delete config;
170 : }
171 : }
172 1 : break;
173 : }
174 :
175 0 : default:
176 0 : assert(0);
177 : }
178 2 : }
179 :
180 30 : void DnsManager::DnsView(const DnsConfig *cfg, DnsConfig::DnsConfigEvent ev) {
181 :
182 30 : if (!end_of_config_)
183 0 : return;
184 :
185 30 : if (!bind_status_.IsUp())
186 0 : return;
187 :
188 30 : const VirtualDnsConfig *config = static_cast<const VirtualDnsConfig *>(cfg);
189 30 : DNS_BIND_TRACE(DnsBindTrace, "Virtual DNS <" << config->GetName() <<
190 : "> " << DnsConfig::ToEventString(ev));
191 30 : config->ClearNotified();
192 30 : std::string dns_domain = config->GetDomainName();
193 30 : if (dns_domain.empty()) {
194 0 : DNS_BIND_TRACE(DnsBindTrace, "Virtual DNS <" << config->GetName() <<
195 : "> doesnt have domain; ignoring event : " <<
196 : DnsConfig::ToEventString(ev));
197 0 : return;
198 : }
199 :
200 30 : NamedConfig *ncfg = NamedConfig::GetNamedConfigObject();
201 30 : if (ev == DnsConfig::CFG_ADD) {
202 11 : if (!CheckName(config->GetName(), dns_domain)) {
203 0 : return;
204 : }
205 11 : config->MarkNotified();
206 11 : ncfg->AddView(config);
207 19 : } else if (ev == DnsConfig::CFG_CHANGE) {
208 8 : if (CheckName(config->GetName(), dns_domain)) {
209 8 : config->MarkNotified();
210 : }
211 8 : ncfg->ChangeView(config);
212 8 : if (dns_domain != config->GetOldDomainName()) {
213 0 : NotifyAllDnsRecords(config, ev);
214 8 : } else if (config->HasReverseResolutionChanged()) {
215 8 : bool reverse_resolution = config->IsReverseResolutionEnabled();
216 : // if reverse resolution is enabled now, add the reverse records
217 : // if reverse resolution is disabled now, mark them as not notified
218 8 : NotifyReverseDnsRecords(config, ev, reverse_resolution);
219 : }
220 : } else {
221 11 : ncfg->DelView(config);
222 11 : PendingListViewDelete(config);
223 : }
224 30 : }
225 :
226 42 : void DnsManager::DnsPtrZone(const Subnet &subnet, const VirtualDnsConfig *vdns,
227 : DnsConfig::DnsConfigEvent ev) {
228 :
229 42 : if (!end_of_config_)
230 0 : return;
231 :
232 42 : if (!bind_status_.IsUp())
233 0 : return;
234 :
235 42 : std::string dns_domain = vdns->GetDomainName();
236 42 : if (dns_domain.empty()) {
237 0 : DNS_BIND_TRACE(DnsBindTrace, "Ptr Zone <" << vdns->GetName() <<
238 : "> ; ignoring event: " << DnsConfig::ToEventString(ev) <<
239 : " Domain: " << dns_domain << " Reverse Resolution: " <<
240 : (vdns->IsReverseResolutionEnabled()? "enabled" :
241 : "disabled"));
242 0 : return;
243 : }
244 :
245 42 : NamedConfig *ncfg = NamedConfig::GetNamedConfigObject();
246 42 : if (ev == DnsConfig::CFG_DELETE) {
247 29 : ncfg->DelZone(subnet, vdns);
248 29 : PendingListZoneDelete(subnet, vdns);
249 : } else {
250 13 : ncfg->AddZone(subnet, vdns);
251 : }
252 42 : DNS_BIND_TRACE(DnsBindTrace, "Virtual DNS <" << vdns->GetName() << "> " <<
253 : subnet.prefix.to_string() << "/" << subnet.plen << " " <<
254 : DnsConfig::ToEventString(ev));
255 42 : }
256 :
257 41 : void DnsManager::DnsRecord(const DnsConfig *cfg, DnsConfig::DnsConfigEvent ev) {
258 :
259 41 : if (!end_of_config_)
260 0 : return;
261 :
262 41 : if (!bind_status_.IsUp())
263 0 : return;
264 :
265 41 : if (named_send_throttled_)
266 0 : return;
267 :
268 41 : const VirtualDnsRecordConfig *config =
269 : static_cast<const VirtualDnsRecordConfig *>(cfg);
270 41 : config->ClearNotified();
271 41 : const DnsItem &item = config->GetRecord();
272 41 : if (item.name == "" || item.data == "") {
273 0 : DNS_BIND_TRACE(DnsBindError, "Virtual DNS Record <" <<
274 : config->GetName() <<
275 : "> doesnt have name / data; ignoring event : " <<
276 : DnsConfig::ToEventString(ev));
277 0 : return;
278 : }
279 :
280 41 : if (config->GetViewName() == "" || !config->GetVirtualDns()->IsValid()) {
281 0 : return;
282 : }
283 :
284 41 : switch (ev) {
285 23 : case DnsConfig::CFG_ADD:
286 : case DnsConfig::CFG_CHANGE:
287 23 : if (SendRecordUpdate(BindUtil::ADD_UPDATE, config))
288 23 : config->MarkNotified();
289 23 : break;
290 :
291 18 : case DnsConfig::CFG_DELETE:
292 18 : if (SendRecordUpdate(BindUtil::DELETE_UPDATE, config))
293 18 : config->ClearNotified();
294 18 : break;
295 :
296 0 : default:
297 0 : assert(0);
298 : }
299 : }
300 :
301 41 : bool DnsManager::SendRecordUpdate(BindUtil::Operation op,
302 : const VirtualDnsRecordConfig *config) {
303 41 : DnsItem item = config->GetRecord();
304 41 : const autogen::VirtualDnsType vdns = config->GetVDns();
305 :
306 41 : std::string zone;
307 41 : if (item.type == DNS_PTR_RECORD) {
308 2 : if (!vdns.reverse_resolution) {
309 0 : DNS_BIND_TRACE(DnsBindTrace, "Virtual DNS Record <" <<
310 : config->GetName() << "> PTR name " << item.name <<
311 : " not added - reverse resolution is not enabled");
312 0 : return false;
313 : }
314 2 : IpAddress addr;
315 2 : if (BindUtil::IsIP(item.name, addr)) {
316 0 : BindUtil::GetReverseZone(addr, addr.is_v4() ? 32 : 128, item.name);
317 : } else {
318 2 : if (!BindUtil::GetAddrFromPtrName(item.name, addr)) {
319 0 : DNS_BIND_TRACE(DnsBindError, "Virtual DNS Record <" <<
320 : config->GetName() << "> invalid PTR name " <<
321 : item.name << "; ignoring");
322 0 : return false;
323 : }
324 : }
325 2 : if (!CheckName(config->GetName(), item.data)) {
326 0 : return false;
327 : }
328 2 : Subnet net;
329 2 : if (!config->GetVirtualDns()->GetSubnet(addr, net)) {
330 0 : DNS_BIND_TRACE(DnsBindError, "Virtual DNS Record <" <<
331 : config->GetName() <<
332 : "> doesnt belong to a known subnet; ignoring");
333 0 : return false;
334 : }
335 2 : BindUtil::GetReverseZone(addr, net.plen, zone);
336 2 : item.data = BindUtil::GetFQDN(item.data, vdns.domain_name, ".");
337 : } else {
338 : // Bind allows special chars in CNAME, NS names and in CNAME data
339 78 : if ((item.type == DNS_A_RECORD || item.type == DNS_AAAA_RECORD) &&
340 78 : !CheckName(config->GetName(), item.name)) {
341 0 : return false;
342 : }
343 39 : if (BindUtil::IsReverseZone(item.name)) {
344 0 : if (item.type != DNS_NS_RECORD) {
345 0 : DNS_BIND_TRACE(DnsBindError, "Virtual DNS Record <" <<
346 : config->GetName() <<
347 : "> only PTR and NS records allowed in reverse zone; ignoring");
348 0 : return false;
349 : }
350 0 : if (!vdns.reverse_resolution) {
351 0 : DNS_BIND_TRACE(DnsBindTrace, "Virtual DNS Record <" <<
352 : config->GetName() << "> NS name " << item.name <<
353 : " not added - reverse resolution is not enabled");
354 0 : return false;
355 : }
356 0 : IpAddress addr;
357 0 : if (!BindUtil::GetAddrFromPtrName(item.name, addr)) {
358 0 : DNS_BIND_TRACE(DnsBindError, "Virtual DNS Record <" <<
359 : config->GetName() << "> invalid reverse name " <<
360 : item.name << "; ignoring");
361 0 : return false;
362 : }
363 0 : Subnet net;
364 0 : if (!config->GetVirtualDns()->GetSubnet(addr, net)) {
365 0 : DNS_BIND_TRACE(DnsBindError, "Virtual DNS Record <" <<
366 : config->GetName() <<
367 : "> doesnt belong to a known subnet; ignoring");
368 0 : return false;
369 : }
370 0 : BindUtil::GetReverseZone(addr, net.plen, zone);
371 : } else {
372 39 : zone = config->GetVDns().domain_name;
373 78 : item.name = BindUtil::GetFQDN(item.name,
374 39 : vdns.domain_name, vdns.domain_name);
375 : }
376 39 : if (item.type == DNS_CNAME_RECORD || item.type == DNS_MX_RECORD)
377 0 : item.data = BindUtil::GetFQDN(item.data, vdns.domain_name, ".");
378 : // In case of NS record, ensure that there are no special characters in data.
379 : // When it is virtual dns name, we could have chars like ':'
380 39 : if (item.type == DNS_NS_RECORD)
381 0 : BindUtil::RemoveSpecialChars(item.data);
382 : }
383 : /* Fix for CEM-21076
384 : * If we have a static DNS record and a VM with the hostname same as the static DNS record
385 : * and we delete the VM, then we should not call SendUpdate() after deleting the VM,
386 : * because after calling SendUpdate(), DNS queries for the static DNS record will not be resolved
387 : */
388 41 : if (config->src_ == VirtualDnsRecordConfig::Agent && op == BindUtil::DELETE_UPDATE) {
389 0 : VirtualDnsConfig *virt_dns = config->GetVirtualDns();
390 0 : for (VirtualDnsConfig::VDnsRec::const_iterator it =
391 0 : virt_dns->virtual_dns_records_.begin();
392 0 : it != virt_dns->virtual_dns_records_.end(); ++it) {
393 0 : if (((*it)->rec_.name + "." + virt_dns->GetDomainName() == item.name) && (*it)->src_ == VirtualDnsRecordConfig::Config) {
394 0 : return false;
395 : }
396 : }
397 : }
398 41 : DnsItems items;
399 41 : items.push_back(item);
400 41 : std::string view_name = config->GetViewName();
401 41 : return (SendUpdate(op, view_name, zone, items));
402 41 : }
403 :
404 41 : bool DnsManager::SendUpdate(BindUtil::Operation op, const std::string &view,
405 : const std::string &zone, DnsItems &items) {
406 :
407 41 : if (pending_map_.size() >= named_hi_watermark_) {
408 0 : DNS_OPERATIONAL_LOG(
409 : g_vns_constants.CategoryNames.find(Category::DNSAGENT)->second,
410 : SandeshLevel::SYS_NOTICE, "Bind named Send Throttled");
411 :
412 0 : named_send_throttled_ = true;
413 0 : return false;
414 : }
415 :
416 41 : uint16_t xid = GetTransId();
417 41 : return (AddPendingList(xid, view, zone, items, op));
418 : }
419 :
420 0 : void DnsManager::SendRetransmit(uint16_t xid, BindUtil::Operation op,
421 : const std::string &view,
422 : const std::string &zone, DnsItems &items,
423 : uint32_t retransmit_count) {
424 :
425 0 : uint8_t *pkt = new uint8_t[BindResolver::max_pkt_size];
426 0 : int len = BindUtil::BuildDnsUpdate(pkt, op, xid, view, zone, items);
427 0 : if (BindResolver::Resolver()->DnsSend(pkt, 0, len)) {
428 0 : DNS_BIND_TRACE(DnsBindTrace,
429 : "DNS transmit sent for DNS record; xid = " <<
430 : xid << "; View = " << view << "; Zone = " << zone << "; " <<
431 : DnsItemsToString(items) << " Retry = " <<
432 : retransmit_count);
433 : }
434 0 : }
435 :
436 0 : void DnsManager::UpdateAll() {
437 :
438 0 : if (!bind_status_.IsUp()) {
439 0 : return;
440 : }
441 :
442 0 : if (!end_of_config_) {
443 0 : return;
444 : }
445 :
446 : // Start dumping records to named
447 0 : named_send_throttled_ = false;
448 :
449 0 : VirtualDnsConfig::DataMap vmap = VirtualDnsConfig::GetVirtualDnsMap();
450 0 : for (VirtualDnsConfig::DataMap::iterator it = vmap.begin();
451 0 : it != vmap.end(); ++it) {
452 0 : VirtualDnsConfig *vdns = it->second;
453 0 : if (!vdns->GetDomainName().empty() &&
454 0 : CheckName(vdns->GetName(), vdns->GetDomainName())) {
455 0 : vdns->MarkNotified();
456 0 : DNS_BIND_TRACE(DnsBindTrace, "Virtual DNS <" << vdns->GetName() <<
457 : "> Add");
458 : } else {
459 0 : vdns->ClearNotified();
460 : }
461 : }
462 0 : NamedConfig *ncfg = NamedConfig::GetNamedConfigObject();
463 0 : ncfg->AddAllViews();
464 0 : for (VirtualDnsConfig::DataMap::iterator it = vmap.begin();
465 0 : it != vmap.end(); ++it) {
466 0 : VirtualDnsConfig *vdns = it->second;
467 0 : if (!vdns->IsNotified())
468 0 : continue;
469 0 : NotifyAllDnsRecords(vdns, DnsConfig::CFG_ADD);
470 : }
471 :
472 0 : DNS_OPERATIONAL_LOG(
473 : g_vns_constants.CategoryNames.find(Category::DNSAGENT)->second,
474 : SandeshLevel::SYS_NOTICE,
475 : "Bulk sync has been done (the DB has been synced with named)");
476 0 : }
477 :
478 0 : void DnsManager::HandleUpdateResponse(uint8_t *pkt, std::size_t length) {
479 : dns_flags flags;
480 : uint16_t xid;
481 0 : DnsItems ques, ans, auth, add;
482 0 : if (BindUtil::ParseDnsResponse(pkt, length, xid, flags,
483 : ques, ans, auth, add)) {
484 0 : if (flags.ret) {
485 0 : DNS_BIND_TRACE(DnsBindError, "Update failed : " <<
486 : BindUtil::DnsResponseCode(flags.ret) <<
487 : "; xid = " << xid);
488 : } else {
489 0 : DNS_BIND_TRACE(DnsBindTrace, "Update successful; xid = " << xid);
490 0 : pending_done_queue_.Enqueue(xid);
491 : }
492 : }
493 0 : delete [] pkt;
494 0 : }
495 :
496 0 : bool DnsManager::PendingDone(uint16_t xid) {
497 0 : DeletePendingList(xid);
498 0 : return true;
499 : }
500 :
501 0 : bool DnsManager::ResendRecordsinBatch() {
502 : static uint16_t start_index = 0;
503 0 : uint16_t sent_count = 0;
504 :
505 0 : PendingListMap::iterator it;
506 0 : if (start_index == 0) {
507 0 : it = pending_map_.upper_bound(start_index);
508 : } else {
509 0 : it = pending_map_.lower_bound(start_index);
510 : }
511 :
512 0 : for (; it != pending_map_.end() ; ) {
513 0 : if (it->second.retransmit_count > named_max_retransmissions_) {
514 0 : DNS_BIND_TRACE(DnsBindTrace, "DNS records max retransmits reached;"
515 : << "no more retransmission; xid = " << it->first);
516 :
517 0 : dp_pending_map_.insert(PendingListPair(it->first,
518 0 : PendingList(it->first, it->second.view,
519 0 : it->second.zone, it->second.items,
520 0 : it->second.op,
521 0 : it->second.retransmit_count)));
522 0 : ResetTransId(it->first);
523 0 : pending_map_.erase(it++);
524 : } else {
525 0 : sent_count++;
526 0 : it->second.retransmit_count++;
527 0 : SendRetransmit(it->first, it->second.op, it->second.view,
528 0 : it->second.zone, it->second.items,
529 0 : it->second.retransmit_count);
530 0 : it++;
531 : }
532 0 : if (sent_count >= record_send_count_) break;
533 : }
534 :
535 0 : if (it != pending_map_.end()) {
536 0 : start_index = it->first;
537 0 : pending_timer_->Reschedule(named_retransmission_interval_);
538 : /* Return true to trigger auto-restart of timer */
539 0 : return true;
540 : } else {
541 0 : if (pending_map_.size() == 0) {
542 0 : start_index = 0;
543 0 : return false;
544 : }
545 0 : start_index = pending_map_.begin()->first;
546 0 : pending_timer_->Reschedule(named_retransmission_interval_);
547 : }
548 :
549 0 : return true;
550 : }
551 :
552 41 : bool DnsManager::AddPendingList(uint16_t xid, const std::string &view,
553 : const std::string &zone, const DnsItems &items,
554 : BindUtil::Operation op) {
555 : // delete earlier entries for the same items
556 41 : UpdatePendingList(view, zone, items, op);
557 :
558 41 : std::pair<PendingListMap::iterator,bool> status;
559 82 : status = pending_map_.insert(PendingListPair(xid, PendingList(xid, view,
560 41 : zone, items, op)));
561 41 : if (status.second == false) {
562 0 : dp_pending_map_.insert(PendingListPair(xid, PendingList(xid, view,
563 : zone, items, op)));
564 0 : return true;
565 : } else {
566 41 : StartPendingTimer(named_retransmission_interval_*3);
567 41 : return true;
568 : }
569 : }
570 :
571 : // Compare items by record identity - type, name and data.
572 : //
573 : // ttl is deliberately not compared. It is not part of the identity, and it is
574 : // exactly what changes when a record is republished with a different TTL: the
575 : // vDNS default_ttl_seconds edited, or DnsProto::MoveVDnsEntry() moving the VM
576 : // to a vDNS that carries another one. Comparing it would leave the pending
577 : // DELETE in place and let both datagrams reach named.
578 : //
579 : // eclass is not compared because it carries no information here. Both sides
580 : // come from VirtualDnsRecordConfig::rec_ - SendRecordUpdate() builds the ADD
581 : // and the DELETE alike from config->GetRecord(), and ProcessAgentUpdate()
582 : // does not copy the agent's delete item into rec_ - so it is the class the
583 : // record was added with in both. (The agent does stamp DNS_CLASS_NONE and
584 : // ttl 0 on the delete it sends, but those values never reach this list.)
585 : //
586 : // View and zone are checked by the caller.
587 0 : static bool DnsItemsMatchByRecord(const DnsItems &a, const DnsItems &b) {
588 0 : if (a.size() != b.size())
589 0 : return false;
590 0 : for (DnsItems::const_iterator ai = a.begin(), bi = b.begin();
591 0 : ai != a.end(); ++ai, ++bi) {
592 0 : if (ai->type != bi->type || ai->name != bi->name ||
593 0 : ai->data != bi->data)
594 0 : return false;
595 : }
596 0 : return true;
597 : }
598 :
599 : // if there is an update for an item which is already in pending list,
600 : // remove it from the pending list
601 41 : void DnsManager::UpdatePendingList(const std::string &view,
602 : const std::string &zone,
603 : const DnsItems &items,
604 : BindUtil::Operation op) {
605 41 : for (PendingListMap::iterator it = pending_map_.begin();
606 235 : it != pending_map_.end(); ) {
607 262 : bool exact = (it->second.view == view &&
608 262 : it->second.zone == zone &&
609 63 : it->second.items == items);
610 : // When ADD arrives for a record whose DELETE is still pending, cancel
611 : // the DELETE so only the ADD reaches named. Without this, both UDP
612 : // datagrams are sent and named processes them in non-deterministic
613 : // order, leaving control-node backends in diverged state.
614 63 : bool delete_superseded = (op == BindUtil::ADD_UPDATE &&
615 63 : it->second.op == BindUtil::DELETE_UPDATE &&
616 0 : it->second.view == view &&
617 257 : it->second.zone == zone &&
618 0 : DnsItemsMatchByRecord(it->second.items, items));
619 194 : if (exact || delete_superseded) {
620 18 : ResetTransId(it->first);
621 18 : pending_map_.erase(it++);
622 : } else {
623 176 : it++;
624 : }
625 : }
626 41 : }
627 :
628 0 : void DnsManager::DeletePendingList(uint16_t xid) {
629 0 : ResetTransId(xid);
630 0 : pending_map_.erase(xid);
631 0 : if (pending_map_.size() <= named_lo_watermark_) {
632 0 : if (named_send_throttled_) {
633 0 : DNS_OPERATIONAL_LOG(
634 : g_vns_constants.CategoryNames.find(Category::DNSAGENT)->second,
635 : SandeshLevel::SYS_NOTICE, "BIND named Send UnThrottled");
636 :
637 0 : named_send_throttled_ = false;
638 0 : NotifyThrottledDnsRecords();
639 : }
640 : }
641 0 : }
642 :
643 0 : void DnsManager::ClearPendingList() {
644 0 : pending_map_.clear();
645 0 : }
646 :
647 : // Remove entries from pending list, upon a view delete
648 11 : void DnsManager::PendingListViewDelete(const VirtualDnsConfig *config) {
649 11 : for (PendingListMap::iterator it = pending_map_.begin();
650 48 : it != pending_map_.end(); ) {
651 37 : if (it->second.view == config->GetViewName()) {
652 23 : ResetTransId(it->first);
653 23 : pending_map_.erase(it++);
654 : } else {
655 14 : it++;
656 : }
657 : }
658 11 : }
659 :
660 57 : bool DnsManager::CheckZoneDelete(ZoneList &zones, PendingList &pend) {
661 172 : for (uint32_t i = 0; i < zones.size(); i++) {
662 115 : if (zones[i] == pend.zone)
663 0 : return true;
664 : }
665 57 : return false;
666 : }
667 :
668 : // Remove entries from pending list, upon a zone delete
669 29 : void DnsManager::PendingListZoneDelete(const Subnet &subnet,
670 : const VirtualDnsConfig *config) {
671 29 : ZoneList zones;
672 29 : subnet.GetReverseZones(zones);
673 :
674 29 : for (PendingListMap::iterator it = pending_map_.begin();
675 236 : it != pending_map_.end(); ) {
676 264 : if (it->second.view == config->GetViewName() &&
677 57 : CheckZoneDelete(zones, it->second)) {
678 0 : ResetTransId(it->first);
679 0 : pending_map_.erase(it++);
680 : } else {
681 207 : it++;
682 : }
683 : }
684 29 : }
685 :
686 41 : void DnsManager::StartPendingTimer(int msec) {
687 41 : if (!pending_timer_->running()) {
688 5 : pending_timer_->Start(msec,
689 : boost::bind(&DnsManager::PendingTimerExpiry, this));
690 : }
691 41 : }
692 :
693 0 : void DnsManager::CancelPendingTimer() {
694 0 : pending_timer_->Cancel();
695 0 : }
696 :
697 0 : bool DnsManager::PendingTimerExpiry() {
698 0 : return ResendRecordsinBatch();
699 : }
700 :
701 0 : void DnsManager::NotifyThrottledDnsRecords() {
702 :
703 0 : if (!end_of_config_)
704 0 : return;
705 :
706 0 : if (!bind_status_.IsUp())
707 0 : return;
708 :
709 0 : VirtualDnsConfig::DataMap vmap = VirtualDnsConfig::GetVirtualDnsMap();
710 0 : for (VirtualDnsConfig::DataMap::iterator it = vmap.begin();
711 0 : it != vmap.end(); ++it) {
712 0 : VirtualDnsConfig *vdns = it->second;
713 0 : if (!vdns->IsNotified())
714 0 : continue;
715 :
716 0 : for (VirtualDnsConfig::VDnsRec::const_iterator it =
717 0 : vdns->virtual_dns_records_.begin();
718 0 : it != vdns->virtual_dns_records_.end(); ++it) {
719 0 : if ((*it)->IsValid()) {
720 0 : if (!((*it)->IsNotified())) {
721 0 : DnsRecord(*it, DnsConfig::CFG_ADD);
722 : }
723 : }
724 : }
725 : }
726 0 : }
727 :
728 0 : void DnsManager::NotifyAllDnsRecords(const VirtualDnsConfig *config,
729 : DnsConfig::DnsConfigEvent ev) {
730 :
731 0 : if (!end_of_config_)
732 0 : return;
733 :
734 0 : if (!bind_status_.IsUp())
735 0 : return;
736 :
737 0 : for (VirtualDnsConfig::VDnsRec::const_iterator it =
738 0 : config->virtual_dns_records_.begin();
739 0 : it != config->virtual_dns_records_.end(); ++it) {
740 : // ClearNotified() to all DnsRecords
741 0 : (*it)->ClearNotified();
742 0 : if ((*it)->IsValid())
743 0 : DnsRecord(*it, ev);
744 : }
745 : }
746 :
747 8 : void DnsManager::NotifyReverseDnsRecords(const VirtualDnsConfig *config,
748 : DnsConfig::DnsConfigEvent ev,
749 : bool notify) {
750 :
751 8 : if (!end_of_config_)
752 0 : return;
753 :
754 8 : if (!bind_status_.IsUp())
755 0 : return;
756 :
757 8 : for (VirtualDnsConfig::VDnsRec::const_iterator it =
758 8 : config->virtual_dns_records_.begin();
759 24 : it != config->virtual_dns_records_.end(); ++it) {
760 16 : DnsItem item = (*it)->GetRecord();
761 16 : if (item.type == DNS_PTR_RECORD) {
762 0 : (*it)->ClearNotified();
763 0 : if ((*it)->IsValid() && notify) {
764 0 : DnsRecord(*it, ev);
765 : }
766 : }
767 16 : }
768 : }
769 :
770 41 : inline uint16_t DnsManager::GetTransId() {
771 41 : return (idx_.AllocIndex());
772 : }
773 :
774 41 : inline void DnsManager::ResetTransId(uint16_t xid) {
775 41 : idx_.FreeIndex(xid);
776 41 : }
777 :
778 60 : inline bool DnsManager::CheckName(std::string rec_name, std::string name) {
779 60 : if (BindUtil::HasSpecialChars(name)) {
780 0 : DNS_CONFIGURATION_LOG(
781 : g_vns_constants.CategoryNames.find(Category::DNSAGENT)->second,
782 : SandeshLevel::SYS_ERR,
783 : "Invalid DNS Name - cannot use special characters in DNS name",
784 : rec_name, name);
785 0 : return false;
786 : }
787 60 : return true;
788 : }
789 :
790 0 : void DnsManager::BindEventHandler(BindStatus::Event event) {
791 0 : switch (event) {
792 0 : case BindStatus::Up: {
793 :
794 0 : DNS_OPERATIONAL_LOG(
795 : g_vns_constants.CategoryNames.find(Category::DNSAGENT)->second,
796 : SandeshLevel::SYS_NOTICE, "BIND named up; DNS is operational");
797 0 : ClearDeportedPendingList();
798 0 : UpdateAll();
799 0 : break;
800 : }
801 :
802 0 : case BindStatus::Down: {
803 :
804 0 : DNS_OPERATIONAL_LOG(
805 : g_vns_constants.CategoryNames.find(Category::DNSAGENT)->second,
806 : SandeshLevel::SYS_NOTICE, "BIND named down; DNS is not operational");
807 0 : NamedConfig *ncfg = NamedConfig::GetNamedConfigObject();
808 0 : ncfg->Reset();
809 0 : ClearPendingList();
810 0 : break;
811 : }
812 :
813 0 : default:
814 0 : assert(0);
815 : }
816 0 : }
817 :
818 0 : void DnsManager::StartEndofConfigTimer() {
819 0 : if (!end_of_config_check_timer_->running()) {
820 0 : end_of_config_check_timer_->Start(kEndOfConfigCheckTime,
821 : boost::bind(&DnsManager::EndofConfigTimerExpiry, this));
822 : }
823 0 : }
824 :
825 0 : void DnsManager::CancelEndofConfigTimer() {
826 0 : end_of_config_check_timer_->Cancel();
827 0 : }
828 :
829 0 : bool DnsManager::EndofConfigTimerExpiry() {
830 0 : bool current_config_state = IsEndOfConfig();
831 0 : if ((current_config_state != end_of_config_) && current_config_state) {
832 0 : end_of_config_ = current_config_state;
833 0 : UpdateAll();
834 : } else {
835 0 : end_of_config_ = current_config_state;
836 : }
837 0 : return true;
838 : }
839 :
840 0 : void SandeshError(const std::string &msg, const std::string &context) {
841 0 : ErrorResp *resp = new ErrorResp();
842 0 : resp->set_resp(msg);
843 0 : resp->set_context(context);
844 0 : resp->Response();
845 0 : }
846 :
847 0 : void ShowVirtualDnsServers::HandleRequest() const {
848 0 : DnsManager *dns_manager = Dns::GetDnsManager();
849 0 : if(dns_manager) {
850 0 : dns_manager->VdnsServersMsgHandler("", context());
851 : } else {
852 0 : SandeshError("Invalid Request No DnsManager Object", context());
853 : }
854 0 : }
855 :
856 0 : void DnsManager::MakeSandeshPageReq(PageReqData *req, VirtualDnsConfig::DataMap &vdns,
857 : VirtualDnsConfig::DataMap::iterator vdns_it,
858 : VirtualDnsConfig::DataMap::iterator vdns_iter,
859 : const std::string &key, const std::string &req_name) const {
860 : // Set table size
861 0 : req->set_table_size(vdns.size());
862 :
863 : //Next page link
864 0 : if(vdns_iter != vdns.end()) {
865 0 : req->set_next_page(vdns_iter->first + req_name);
866 : }
867 :
868 : // First page link
869 0 : if(vdns.size() != 0) {
870 0 : req->set_first_page((vdns.begin())->first + req_name);
871 : }
872 :
873 : // Set Entries
874 0 : uint16_t start_entry=0, end_entry=0;
875 0 : std::stringstream ss1, ss2;
876 0 : if(vdns.size() != 0) {
877 0 : start_entry = std::distance(vdns.begin(), vdns_it);
878 0 : start_entry++;
879 0 : if(start_entry != vdns.size()) {
880 0 : end_entry = std::distance(vdns.begin(), --vdns_iter);
881 0 : end_entry++;
882 : } else {
883 0 : end_entry = start_entry;
884 : }
885 : }
886 0 : ss1 << start_entry;
887 0 : ss2 << end_entry;
888 0 : req->set_entries(ss1.str() + " - " + ss2.str());
889 :
890 : // Previous page link
891 0 : if(vdns_it != vdns.begin()) {
892 0 : for (int i=0; i < (DnsManager::max_records_per_sandesh); i++) {
893 0 : vdns_it--;
894 0 : if(vdns_it == vdns.begin())
895 0 : break;
896 : }
897 0 : req->set_prev_page(vdns_it->first + req_name);
898 : }
899 :
900 : // Set link to show all entries in a single page
901 0 : req->set_all("AllEntries" + req_name);
902 0 : }
903 :
904 0 : void DnsManager::VdnsServersMsgHandler(const std::string &key,
905 : const std::string &context) const {
906 : VirtualDnsServersResponse *resp;
907 0 : uint16_t count = 0;
908 0 : uint16_t sandesh_msg_limit = DnsManager::max_records_per_sandesh;
909 0 : VirtualDnsConfig::DataMap vdns = VirtualDnsConfig::GetVirtualDnsMap();
910 0 : VirtualDnsConfig::DataMap::iterator vdns_it, vdns_iter;
911 0 : std::vector<VirtualDnsServersSandesh> vdns_list_sandesh;
912 0 : if(key == "AllEntries") {
913 0 : sandesh_msg_limit = vdns.size();
914 0 : vdns_it = vdns.begin();
915 0 : } else if(key != "") {
916 0 : vdns_it = vdns.lower_bound(key);
917 : } else {
918 0 : vdns_it = vdns.begin();
919 : }
920 :
921 0 : for (vdns_iter= vdns_it; vdns_iter != vdns.end(); ++vdns_iter) {
922 :
923 0 : if (count++ == sandesh_msg_limit) {
924 0 : break;
925 : }
926 0 : VirtualDnsConfig *vdns_config = vdns_iter->second;
927 0 : VirtualDnsServersSandesh vdns_sandesh;
928 0 : VirtualDnsTraceData vdns_trace_data;
929 0 : vdns_config->VirtualDnsTrace(vdns_trace_data);
930 :
931 0 : std::vector<std::string> net_list_sandesh;
932 0 : for (VirtualDnsConfig::IpamList::iterator ipam_iter =
933 0 : vdns_config->ipams_.begin();
934 0 : ipam_iter != vdns_config->ipams_.end(); ++ipam_iter) {
935 0 : IpamConfig *ipam = *ipam_iter;
936 0 : const IpamConfig::VnniList &vnni = ipam->GetVnniList();
937 0 : for (IpamConfig::VnniList::iterator vnni_it = vnni.begin();
938 0 : vnni_it != vnni.end(); ++vnni_it) {
939 0 : Subnets &subnets = (*vnni_it)->GetSubnets();
940 0 : for (unsigned int i = 0; i < subnets.size(); i++) {
941 0 : std::stringstream str;
942 0 : str << subnets[i].prefix.to_string();
943 0 : str << "/";
944 0 : str << subnets[i].plen;
945 0 : net_list_sandesh.push_back(str.str());
946 0 : }
947 : }
948 : }
949 :
950 0 : vdns_sandesh.set_virtual_dns(vdns_trace_data);
951 0 : vdns_sandesh.set_records(vdns_config->GetName());
952 0 : vdns_sandesh.set_num_records(vdns_config->virtual_dns_records_.size());
953 0 : vdns_sandesh.set_subnets(net_list_sandesh);
954 0 : vdns_list_sandesh.push_back(vdns_sandesh);
955 0 : }
956 :
957 0 : resp = new VirtualDnsServersResponse();
958 0 : resp->set_context(context);
959 0 : resp->set_virtual_dns_servers(vdns_list_sandesh);
960 0 : resp->set_more(true);
961 0 : resp->Response();
962 :
963 0 : Pagination *page = new Pagination();
964 0 : PageReqData req;
965 0 : MakeSandeshPageReq(&req, vdns, vdns_it, vdns_iter, key, " VdnsServersReq");
966 0 : page->set_context(context);
967 0 : page->set_req(req);
968 0 : page->Response();
969 :
970 0 : }
971 :
972 0 : void ShowDnsConfig::HandleRequest() const {
973 0 : DnsManager *dns_manager = Dns::GetDnsManager();
974 0 : if(dns_manager) {
975 0 : dns_manager->DnsConfigMsgHandler("", context());
976 : } else {
977 0 : SandeshError("Invalid Request No DnsManager Object", context());
978 : }
979 0 : }
980 :
981 0 : void DnsManager::DnsConfigMsgHandler(const std::string &key,
982 : const std::string &context) const {
983 0 : DnsConfigResponse *resp = new DnsConfigResponse();
984 0 : uint16_t count = 0;
985 0 : uint16_t sandesh_msg_limit = DnsManager::max_records_per_sandesh;
986 0 : VirtualDnsConfig::DataMap vdns = VirtualDnsConfig::GetVirtualDnsMap();
987 0 : VirtualDnsConfig::DataMap::iterator vdns_it, vdns_iter;
988 0 : std::vector<VirtualDnsSandesh> vdns_list_sandesh;
989 0 : if(key == "AllEntries") {
990 0 : sandesh_msg_limit = vdns.size();
991 0 : vdns_it = vdns.begin();
992 0 : } else if(key != "") {
993 0 : vdns_it = vdns.lower_bound(key);
994 : } else {
995 0 : vdns_it = vdns.begin();
996 : }
997 :
998 0 : for (vdns_iter = vdns_it; vdns_iter != vdns.end(); ++vdns_iter) {
999 0 : if (count++ == sandesh_msg_limit) {
1000 0 : break;
1001 : }
1002 0 : VirtualDnsConfig *vdns_config = vdns_iter->second;
1003 0 : VirtualDnsSandesh vdns_sandesh;
1004 0 : VirtualDnsTraceData vdns_trace_data;
1005 0 : vdns_config->VirtualDnsTrace(vdns_trace_data);
1006 :
1007 0 : std::vector<VirtualDnsRecordTraceData> rec_list_sandesh;
1008 0 : for (VirtualDnsConfig::VDnsRec::iterator rec_it =
1009 0 : vdns_config->virtual_dns_records_.begin();
1010 0 : rec_it != vdns_config->virtual_dns_records_.end(); ++rec_it) {
1011 0 : VirtualDnsRecordTraceData rec_trace_data;
1012 0 : (*rec_it)->VirtualDnsRecordTrace(rec_trace_data);
1013 0 : rec_list_sandesh.push_back(rec_trace_data);
1014 0 : }
1015 :
1016 0 : std::vector<std::string> net_list_sandesh;
1017 0 : for (VirtualDnsConfig::IpamList::iterator ipam_iter =
1018 0 : vdns_config->ipams_.begin();
1019 0 : ipam_iter != vdns_config->ipams_.end(); ++ipam_iter) {
1020 0 : IpamConfig *ipam = *ipam_iter;
1021 0 : const IpamConfig::VnniList &vnni = ipam->GetVnniList();
1022 0 : for (IpamConfig::VnniList::iterator vnni_it = vnni.begin();
1023 0 : vnni_it != vnni.end(); ++vnni_it) {
1024 0 : Subnets &subnets = (*vnni_it)->GetSubnets();
1025 0 : for (unsigned int i = 0; i < subnets.size(); i++) {
1026 0 : std::stringstream str;
1027 0 : str << subnets[i].prefix.to_string();
1028 0 : str << "/";
1029 0 : str << subnets[i].plen;
1030 0 : net_list_sandesh.push_back(str.str());
1031 0 : }
1032 : }
1033 : }
1034 :
1035 0 : vdns_sandesh.set_virtual_dns(vdns_trace_data);
1036 0 : vdns_sandesh.set_records(rec_list_sandesh);
1037 0 : vdns_sandesh.set_subnets(net_list_sandesh);
1038 0 : vdns_list_sandesh.push_back(vdns_sandesh);
1039 0 : }
1040 :
1041 0 : resp->set_context(context);
1042 0 : resp->set_virtual_dns(vdns_list_sandesh);
1043 0 : resp->set_more(true);
1044 0 : resp->Response();
1045 :
1046 0 : Pagination *page = new Pagination();
1047 0 : PageReqData req;
1048 0 : MakeSandeshPageReq(&req, vdns, vdns_it, vdns_iter, key, " DnsConfigReq");
1049 0 : page->set_context(context);
1050 0 : page->set_req(req);
1051 0 : page->Response();
1052 0 : }
1053 :
1054 0 : void ShowVirtualDnsRecords::HandleRequest() const {
1055 0 : DnsManager *dns_manager = Dns::GetDnsManager();
1056 0 : if(dns_manager) {
1057 0 : dns_manager->VdnsRecordsMsgHandler(get_virtual_dns_server(), context());
1058 : } else {
1059 0 : SandeshError("Invalid Request No DnsManager Object", context());
1060 : }
1061 0 : }
1062 :
1063 0 : void DnsManager::VdnsRecordsMsgHandler(const std::string &key,
1064 : const std::string &context, bool show_all) const {
1065 0 : VirtualDnsRecordsResponse *resp = new VirtualDnsRecordsResponse();
1066 0 : VirtualDnsConfig::DataMap vdns = VirtualDnsConfig::GetVirtualDnsMap();
1067 :
1068 0 : std::stringstream ss(key);
1069 0 : std::stringstream str;
1070 0 : std::string vdns_server, next_iterator;
1071 0 : VirtualDnsRecordConfig *next_iterator_key = NULL;
1072 0 : std::getline(ss, vdns_server, '@');
1073 0 : std::getline(ss, next_iterator);
1074 0 : uint16_t sandesh_msg_limit = DnsManager::max_records_per_sandesh;
1075 0 : if (!next_iterator.empty()) {
1076 0 : std::stringstream next_iter(next_iterator);
1077 0 : uint64_t value = 0;
1078 0 : next_iter >> value;
1079 0 : next_iterator_key = (VirtualDnsRecordConfig *) value;
1080 0 : }
1081 0 : std::vector<VirtualDnsRecordTraceData> rec_list_sandesh;
1082 0 : VirtualDnsConfig::VDnsRec::iterator rec_it, rec_it1;
1083 0 : VirtualDnsConfig::DataMap::iterator vdns_it = vdns.find(vdns_server);
1084 0 : if (vdns_it != vdns.end()) {
1085 0 : VirtualDnsConfig *vdns_config = vdns_it->second;
1086 0 : uint16_t count = 0;
1087 0 : uint16_t size = vdns_config->virtual_dns_records_.size();
1088 0 : if(show_all) {
1089 0 : rec_it1 = vdns_config->virtual_dns_records_.begin();
1090 0 : sandesh_msg_limit = size;
1091 : } else {
1092 0 : rec_it1 = vdns_config->virtual_dns_records_.lower_bound(next_iterator_key);
1093 : }
1094 0 : for(rec_it = rec_it1;
1095 0 : rec_it != vdns_config->virtual_dns_records_.end(); ++rec_it) {
1096 0 : VirtualDnsRecordTraceData rec_trace_data;
1097 0 : (*rec_it)->VirtualDnsRecordTrace(rec_trace_data);
1098 0 : rec_list_sandesh.push_back(rec_trace_data);
1099 0 : if (++count == sandesh_msg_limit) {
1100 0 : if (++rec_it == vdns_config->virtual_dns_records_.end())
1101 0 : break;
1102 0 : uint64_t value = (uint64_t)(*rec_it);
1103 0 : str << vdns_server << "@" << value;
1104 0 : break;
1105 : }
1106 0 : }
1107 :
1108 0 : resp->set_context(context);
1109 0 : resp->set_virtual_dns_server(vdns_server);
1110 0 : resp->set_records(rec_list_sandesh);
1111 0 : resp->set_more(true);
1112 0 : resp->Response();
1113 :
1114 0 : Pagination *page = new Pagination();
1115 0 : PageReqData req;
1116 :
1117 : // Set table size
1118 0 : req.set_table_size(size);
1119 :
1120 : //Next page link
1121 0 : if(rec_it != vdns_config->virtual_dns_records_.end()) {
1122 0 : req.set_next_page(str.str() + " VdnsRecordsReq");
1123 : }
1124 :
1125 : // First page link
1126 0 : if(size != 0) {
1127 0 : std::stringstream str;
1128 0 : uint64_t value = (uint64_t)(*(vdns_config->virtual_dns_records_.begin()));
1129 0 : str << vdns_server << "@" << value;
1130 0 : req.set_first_page(str.str() + " VdnsRecordsReq");
1131 0 : }
1132 :
1133 : // Set Entries
1134 0 : int start_entry=0, end_entry=0;
1135 0 : std::stringstream ss1, ss2;
1136 0 : if( size != 0) {
1137 0 : start_entry = std::distance(vdns_config->virtual_dns_records_.begin(), rec_it1);
1138 0 : start_entry++;
1139 0 : if(start_entry != size) {
1140 0 : end_entry = std::distance(vdns_config->virtual_dns_records_.begin(), --rec_it);
1141 0 : end_entry++;
1142 : } else {
1143 0 : end_entry = start_entry;
1144 : }
1145 : }
1146 :
1147 0 : ss1 << start_entry;
1148 0 : ss2 << end_entry;
1149 0 : req.set_entries(ss1.str() + " - " + ss2.str());
1150 :
1151 : // Previous page link
1152 0 : if(rec_it1 != vdns_config->virtual_dns_records_.begin()) {
1153 0 : for (int i=0; i < (sandesh_msg_limit); i++) {
1154 0 : rec_it1--;
1155 0 : if(rec_it1 == vdns_config->virtual_dns_records_.begin())
1156 0 : break;
1157 : }
1158 0 : std::stringstream str;
1159 0 : uint64_t value = (uint64_t)(*rec_it1);
1160 0 : str << vdns_server << "@" << value;
1161 0 : req.set_prev_page(str.str() + " VdnsRecordsReq");
1162 0 : }
1163 :
1164 : // Set link to show all entries in a single page
1165 0 : std::stringstream str;
1166 0 : uint64_t value = 0;
1167 0 : str << vdns_server << "@" << value;
1168 0 : req.set_all(str.str() + " AllEntriesVdnsRecordsReq");
1169 :
1170 0 : page->set_context(context);
1171 0 : page->set_req(req);
1172 0 : page->Response();
1173 :
1174 0 : } else {
1175 0 : SandeshError("Invalid Request Enter Vdns Server Name", context);
1176 0 : delete resp;
1177 : }
1178 0 : }
1179 :
1180 0 : void ShowBindPendingList::HandleRequest() const {
1181 0 : DnsManager *dns_manager = Dns::GetDnsManager();
1182 0 : if(dns_manager) {
1183 0 : dns_manager->BindPendingMsgHandler("", context());
1184 : } else {
1185 0 : SandeshError("Invalid Request No DnsManager Object", context());
1186 : }
1187 0 : }
1188 :
1189 0 : void DnsManager::BindPendingMsgHandler(const std::string &key,
1190 : const std::string &context) const {
1191 0 : BindPendingListResponse *resp = new BindPendingListResponse();
1192 0 : DnsManager *dns_manager = Dns::GetDnsManager();
1193 0 : if (dns_manager) {
1194 0 : uint16_t count =0;
1195 0 : uint16_t index=0;
1196 0 : stringToInteger(key, index);
1197 0 : uint16_t sandesh_msg_limit = DnsManager::max_records_per_sandesh;
1198 : DnsManager::PendingListMap map =
1199 0 : dns_manager->GetDeportedPendingListMap();
1200 0 : uint16_t size = map.size();
1201 : std::vector<PendingListEntry> &pending_list =
1202 0 : const_cast<std::vector<PendingListEntry>&>(resp->get_data());
1203 0 : DnsManager::PendingListMap::iterator map_it, map_iter;
1204 0 : if(key == "AllEntries") {
1205 0 : sandesh_msg_limit = size;
1206 0 : map_it = map.begin();
1207 : }
1208 0 : else if(key != "") {
1209 0 : map_it = map.lower_bound(index);
1210 : }
1211 : else {
1212 0 : map_it = map.begin();
1213 : }
1214 :
1215 0 : for (map_iter = map_it; map_iter!= map.end(); ++map_iter) {
1216 0 : if (count++ == sandesh_msg_limit) {
1217 0 : break;
1218 : }
1219 0 : PendingListEntry entry;
1220 0 : entry.set_xid(map_iter->second.xid);
1221 0 : entry.set_view(map_iter->second.view);
1222 0 : entry.set_zone(map_iter->second.zone);
1223 0 : entry.set_retry_count(map_iter->second.retransmit_count);
1224 0 : entry.set_items(DnsItemsToString(map_iter->second.items));
1225 :
1226 0 : pending_list.push_back(entry);
1227 0 : }
1228 :
1229 0 : resp->set_context(context);
1230 0 : resp->set_more(true);
1231 0 : resp->Response();
1232 :
1233 0 : Pagination *page = new Pagination();
1234 0 : PageReqData req;
1235 :
1236 : // Set table size
1237 0 : req.set_table_size(size);
1238 :
1239 : //Next page link
1240 0 : if(map_iter != map.end()) {
1241 0 : std::stringstream ss;
1242 0 : ss << map_iter->first;
1243 0 : req.set_next_page(ss.str() + " BindPendingListReq");
1244 0 : }
1245 :
1246 : // First page link
1247 0 : if(size != 0) {
1248 0 : std::stringstream ss;
1249 0 : ss << map.begin()->first;
1250 0 : req.set_first_page(ss.str()+ " BindPendingListReq");
1251 0 : }
1252 :
1253 : // Set Entries
1254 0 : int start_entry=0, end_entry=0;
1255 0 : std::stringstream ss1, ss2;
1256 0 : if(size != 0) {
1257 0 : start_entry = std::distance(map.begin(), map_it);
1258 0 : start_entry++;
1259 0 : if(start_entry != size) {
1260 0 : end_entry = std::distance(map.begin(), --map_iter);
1261 0 : end_entry++;
1262 : } else {
1263 0 : end_entry = start_entry;
1264 : }
1265 :
1266 : }
1267 0 : ss1 << start_entry;
1268 0 : ss2 << end_entry;
1269 0 : req.set_entries(ss1.str() + " - " + ss2.str());
1270 :
1271 : // Previous page link
1272 0 : if(map_it != map.begin()) {
1273 0 : for (int i=0; i < (sandesh_msg_limit); i++) {
1274 0 : map_it--;
1275 0 : if(map_it == map.begin())
1276 0 : break;
1277 : }
1278 0 : std::stringstream ss;
1279 0 : ss << map_it->first;
1280 0 : req.set_prev_page(ss.str() + " BindPendingListReq");
1281 0 : }
1282 :
1283 : // Set link to show all entries in a single page
1284 0 : req.set_all("AllEntries BindPendingListReq");
1285 :
1286 0 : page->set_context(context);
1287 0 : page->set_req(req);
1288 0 : page->Response();
1289 :
1290 0 : } else {
1291 0 : SandeshError("Invalid Request No DnsManager Object ", context);
1292 0 : delete resp;
1293 : }
1294 0 : }
1295 :
1296 0 : void PageReq::HandleRequest() const {
1297 0 : string req_name, search_key;
1298 0 : vector<string> tokens;
1299 0 : boost::split(tokens, get_key(), boost::is_any_of(" "));
1300 0 : DnsManager *dns_manager = Dns::GetDnsManager();
1301 0 : if(dns_manager && (tokens.size() == 2)) {
1302 0 : search_key = tokens[0];
1303 0 : req_name = tokens[1];
1304 0 : if(req_name == "VdnsServersReq") {
1305 0 : dns_manager->VdnsServersMsgHandler(search_key, context());
1306 0 : } else if(req_name == "DnsConfigReq") {
1307 0 : dns_manager->DnsConfigMsgHandler(search_key, context());
1308 0 : } else if(req_name == "VdnsRecordsReq") {
1309 0 : dns_manager->VdnsRecordsMsgHandler(search_key, context());
1310 0 : } else if(req_name == "AllEntriesVdnsRecordsReq") {
1311 0 : dns_manager->VdnsRecordsMsgHandler(search_key, context(), true);
1312 0 : } else if (req_name == "BindPendingListReq") {
1313 0 : dns_manager->BindPendingMsgHandler(search_key, context());
1314 : } else {
1315 0 : SandeshError("Invalid Request", context());
1316 : }
1317 : } else {
1318 0 : SandeshError("Invalid Request", context());
1319 : }
1320 0 : }
1321 :
1322 0 : void ShowGlobalQosConfig::HandleRequest() const {
1323 0 : GlobalQosConfigResponse *resp = new GlobalQosConfigResponse();
1324 0 : GlobalQosConfig *obj = GlobalQosConfig::Find("");
1325 0 : resp->set_control_dscp(obj->control_dscp_);
1326 0 : resp->set_analytics_dscp(obj->analytics_dscp_);
1327 0 : resp->set_context(context());
1328 0 : resp->set_more(false);
1329 0 : resp->Response();
1330 0 : }
|