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