LCOV - code coverage report
Current view: top level - dns/mgr - dns_mgr.cc (source / functions) Hit Total Coverage
Test: OpenSDN C/C++ coverage (all TARGET_SET jobs) Lines: 230 838 27.4 %
Date: 2026-10-19 02:12:28 Functions: 23 54 42.6 %
Legend: Lines: hit not hit

          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 : }

Generated by: LCOV version 1.14