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: 252 861 29.3 %
Date: 2026-11-09 02:10:49 Functions: 24 55 43.6 %
Legend: Lines: hit not hit

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

Generated by: LCOV version 1.14