OpenSDN source code
dns_proto.cc
Go to the documentation of this file.
1 /*
2  * Copyright (c) 2013 Juniper Networks, Inc. All rights reserved.
3  */
4 
5 #include <sys/types.h>
6 #include <boost/uuid/uuid_io.hpp>
7 #include "base/address_util.h"
8 #include "init/agent_init.h"
10 #include "services/dns_proto.h"
11 #include "bind/bind_resolver.h"
12 #include "cmn/agent_cmn.h"
13 #include "init/agent_param.h"
14 #include "ifmap/ifmap_link.h"
15 #include "ifmap/ifmap_table.h"
16 #include "pkt/pkt_init.h"
18 #include "oper/global_qos_config.h"
19 #include "oper/vn.h"
20 #include "oper/route_common.h"
21 #include <fstream>
22 
24 const Ip6Address DnsProto::ip6_unspec_ = Ip6Address::from_string("::");
25 
28 
29  for (DnsBindQueryMap::iterator it = dns_query_map_.begin();
30  it != dns_query_map_.end(); ) {
31  DnsBindQueryMap::iterator next = it++;
32  delete it->second;
33  it = next;
34  }
35 
36  curr_vm_requests_.clear();
37  // Following tables should be deleted when all VMs are gone
38  assert(update_set_.empty());
39  assert(all_vms_.empty());
40 }
41 
46  this));
47  std::vector<BindResolver::DnsServer> dns_servers;
48  for (int i = 0; i < MAX_XMPP_SERVERS; i++) {
49  std::string server = agent()->dns_server(i);
50  if (server != "")
51  dns_servers.push_back(BindResolver::DnsServer(
52  server, agent()->dns_server_port(i)));
53  }
54  GlobalQosConfig* qos = NULL;
55  uint8_t dscp = 0;
56  if (agent_->oper_db()) {
57  qos = agent_->oper_db()->global_qos_config();
58  }
59  if (qos && qos->control_dscp() != GlobalQosConfig::kInvalidDscp) {
60  dscp = qos->dns_dscp();
61  }
62  BindResolver::Init(*agent()->event_manager()->io_service(), dns_servers,
63  agent()->params()->dns_client_port(),
64  boost::bind(&DnsProto::SendDnsIpc, this, _1, _2), dscp);
65 }
66 
67 DnsProto::DnsProto(Agent *agent, boost::asio::io_context &io) :
68  Proto(agent, "Agent::Services", PktHandler::DNS, io),
69  xid_(0), timeout_(agent->params()->dns_timeout()),
70  max_retries_(agent->params()->dns_max_retries()) {
71  // limit the number of entries in the workqueue
73  work_queue_.SetBounded(true);
74  def_server_list_.clear();
77  GetTaskId("Agent::Services"), PktHandler::DNS);
78 
80  boost::bind(&DnsProto::InterfaceNotify, this, _2));
82  boost::bind(&DnsProto::VnNotify, this, _2));
83  if (agent->tsn_enabled()) {
86  this, _2));
87  }
89  boost::bind(&DnsProto::IpamNotify, this, _1));
91  boost::bind(&DnsProto::VdnsNotify, this, _1));
93  (boost::bind(&DnsProto::UpdateFloatingIp, this, _1, _2, _3, _4));
94 
96  (boost::bind(&DnsProto::SendDnsUpdateIpc, this, _1, _2, _3, _4));
98  (boost::bind(&DnsProto::SendDnsUpdateIpc, this, _1));
99 }
100 
102 }
103 
107  if (agent_->tsn_enabled()) {
109  }
112 }
113 
115  def_server_list_ = BuildDefaultServerListImpl(); // assign new contents
116  return true;
117 }
118 
119 std::vector<IpAddress> DnsProto::GetDefaultServerList() {
120  return def_server_list_;
121 }
122 
123 ProtoHandler *DnsProto::AllocProtoHandler(boost::shared_ptr<PktInfo> info,
124  boost::asio::io_context &io) {
125  return new DnsHandler(agent(), info, io);
126 }
127 
129  Interface *itf = static_cast<Interface *>(entry);
130  if (itf->type() != Interface::VM_INTERFACE)
131  return;
132 
133  const VmInterface *vmitf = static_cast<VmInterface *>(entry);
134  if (entry->IsDeleted()) {
135  SendDnsUpdateIpc(NULL, DnsAgentXmpp::Update, vmitf, false);
136  SendDnsUpdateIpc(NULL, DnsAgentXmpp::Update, vmitf, true);
137  all_vms_.erase(vmitf);
138  DNS_BIND_TRACE(DnsBindTrace, "Vm Interface deleted : " <<
139  vmitf->vm_name());
140  // remove floating ip entries from fip list
141  const VmInterface::FloatingIpList &fip = vmitf->floating_ip_list();
142  for (VmInterface::FloatingIpSet::iterator it = fip.list_.begin(),
143  next = fip.list_.begin(); it != fip.list_.end(); it = next) {
144  ++next;
145  UpdateFloatingIp(vmitf, it->vn_.get(), it->floating_ip_,true);
146  }
147  } else {
148  autogen::VirtualDnsType vdns_type;
149  std::string vdns_name;
150  GetVdnsData(vmitf->vn(), vmitf->primary_ip_addr(),
151  vmitf->primary_ip6_addr(),
152  vdns_name, vdns_type);
153  VmDataMap::iterator it = all_vms_.find(vmitf);
154  if (it == all_vms_.end()) {
155  if (!UpdateDnsEntry(vmitf, vmitf->vn(), vmitf->vm_name(), vdns_name,
156  vmitf->primary_ip_addr(), vmitf->primary_ip6_addr(),
157  false, false))
158  vdns_name = "";
159  IpVdnsMap vmdata;
160  vmdata.insert(IpVdnsPair(vmitf->primary_ip_addr().to_ulong(), vdns_name));
161  all_vms_.insert(VmDataPair(vmitf, vmdata));
162  DNS_BIND_TRACE(DnsBindTrace, "Vm Interface added : " <<
163  vmitf->vm_name());
164  } else {
165  CheckForUpdate(it->second, vmitf, vmitf->vn(),
166  vmitf->primary_ip_addr(), vmitf->primary_ip6_addr(),
167  vdns_name, vdns_type);
168  }
169 
170  // Floating ip records follow the floating ip configuration, not the
171  // forwarding state of the interface; publish every configured entry,
172  // including the ones that are not installed because the interface is
173  // inactive (instance powered off). Withdrawal happens when the entry
174  // leaves the configuration, from CleanupFloatingIpList().
175  // If tenant name is also required in the fip name, it may not be
176  // available during activate if the vm interface doesnt have vn at
177  // that time. Invoke Update here to handle that case.
178  if (vmitf->vn()) {
179  const VmInterface::FloatingIpList &fip = vmitf->floating_ip_list();
180  for (VmInterface::FloatingIpSet::iterator it = fip.list_.begin();
181  it != fip.list_.end(); ++it) {
182  // FloatingIp::Copy() assigns vn_ only while it is NULL, so a
183  // reference to an already deleted VnEntry survives here.
184  // Republishing on such an entry would resurrect the record
185  // VnNotify() has just withdrawn, and nothing would withdraw it
186  // again - VnNotify() does not fire twice for the same VN and
187  // CleanupFloatingIpList() cannot resolve a deleted VN.
188  if (it->del_pending() == false && it->vn_.get() != NULL &&
189  it->vn_->IsDeleted() == false) {
190  UpdateFloatingIp(vmitf, it->vn_.get(),
191  it->floating_ip_, false);
192  }
193  }
194  }
195  }
196 }
197 
199  const VnEntry *vn = static_cast<const VnEntry *>(entry);
200  if (vn->IsDeleted()) {
201  // remove floating ip entries from this vn in floating ip list
202  // Ip4Address is the smallest address
203  IpAddress ip_key = Ip4Address(0);
204  DnsFipEntryPtr key(new DnsFipEntry(vn, ip_key, NULL));
205  DnsFipSet::iterator it = fip_list_.upper_bound(key);
206  while (it != fip_list_.end()) {
207  DnsFipEntry *entry = (*it).get();
208  if (entry->vn_ != vn) {
209  break;
210  }
211  ++it;
212  UpdateFloatingIp(entry->interface_, entry->vn_,
213  entry->floating_ip_, true);
214  }
215  return;
216  }
217  if (vn->GetVnIpam().size() == 0)
218  return;
219  DNS_BIND_TRACE(DnsBindTrace, "Vn Notify : " << vn->GetName());
220  for (VmDataMap::iterator it = all_vms_.begin(); it != all_vms_.end(); ++it) {
221  if (it->first->vn() == vn) {
222  std::string vdns_name;
223  autogen::VirtualDnsType vdns_type;
224  GetVdnsData(vn, it->first->primary_ip_addr(),
225  it->first->primary_ip6_addr(),
226  vdns_name, vdns_type);
227  CheckForUpdate(it->second, it->first, it->first->vn(),
228  it->first->primary_ip_addr(),
229  it->first->primary_ip6_addr(),
230  vdns_name, vdns_type);
231  }
232  }
233  IpAddress ip_key = Ip4Address(0);
234  DnsFipEntryPtr key(new DnsFipEntry(vn, ip_key, NULL));
235  DnsFipSet::iterator it = fip_list_.upper_bound(key);
236  while (it != fip_list_.end()) {
237  std::string fip_vdns_name;
238  DnsFipEntry *entry = (*it).get();
239  if (entry->vn_ != vn) {
240  break;
241  }
242  autogen::VirtualDnsType fip_vdns_type;
243  Ip4Address ip4 = ip4_unspec_;
244  Ip6Address ip6 = ip6_unspec_;
245  if (entry->floating_ip_.is_v4()) {
246  ip4 = entry->floating_ip_.to_v4();
247  }
248  if (entry->floating_ip_.is_v6()) {
249  ip6 = entry->floating_ip_.to_v6();
250  }
251  GetVdnsData(entry->vn_, ip4, ip6,
252  fip_vdns_name, fip_vdns_type);
253  CheckForFipUpdate(entry, fip_vdns_name, fip_vdns_type);
254  ++it;
255  }
256 }
257 
259  VrfEntry *vrf = static_cast<VrfEntry *>(entry);
260  if (vrf->GetName() == agent_->fabric_vrf_name())
261  return;
262  MacAddress address(agent_->vhost_interface()->mac());
263 
264  if (entry->IsDeleted()) {
266  address, -1);
267  return;
268  }
269 
270  if (vrf->vn()) {
272  vrf->GetName(),
273  address,
274  vrf->vn()->GetName(),
275  "pkt0", true);
276  }
277 }
278 
280  if (node->IsDeleted())
281  return;
282  DNS_BIND_TRACE(DnsBindTrace, "Ipam Notify : " << node->name());
283  ProcessNotify(node->name(), node->IsDeleted(), true);
284 }
285 
287  DNS_BIND_TRACE(DnsBindTrace, "Vdns Notify : " << node->name());
288  // Update any existing records prior to checking for new ones
289  if (!node->IsDeleted()) {
290  autogen::VirtualDns *virtual_dns =
291  static_cast <autogen::VirtualDns *> (node->GetObject());
292  autogen::VirtualDnsType vdns_type = virtual_dns->data();
293  std::string name = node->name();
294  MoveVDnsEntry(NULL, name, name, vdns_type, false);
295  }
296  ProcessNotify(node->name(), node->IsDeleted(), false);
297 }
298 
299 void DnsProto::ProcessNotify(std::string name, bool is_deleted, bool is_ipam) {
300  for (VmDataMap::iterator it = all_vms_.begin(); it != all_vms_.end(); ++it) {
301  std::string vdns_name;
302  autogen::VirtualDnsType vdns_type;
303  GetVdnsData(it->first->vn(), it->first->primary_ip_addr(),
304  it->first->primary_ip6_addr(), vdns_name, vdns_type);
305  // in case of VDNS delete, clear the name
306  if (!is_ipam && is_deleted && vdns_name == name)
307  vdns_name.clear();
308  CheckForUpdate(it->second, it->first, it->first->vn(),
309  it->first->primary_ip_addr(),
310  it->first->primary_ip6_addr(),
311  vdns_name, vdns_type);
312  }
313  DnsFipSet::iterator it = fip_list_.begin();
314  while (it != fip_list_.end()) {
315  std::string fip_vdns_name;
316  DnsFipEntry *entry = (*it).get();
317  autogen::VirtualDnsType fip_vdns_type;
318  Ip4Address ip4 = ip4_unspec_;
319  Ip6Address ip6 = ip6_unspec_;
320  if (entry->floating_ip_.is_v4()) {
321  ip4 = entry->floating_ip_.to_v4();
322  }
323  if (entry->floating_ip_.is_v6()) {
324  ip6 = entry->floating_ip_.to_v6();
325  }
326  GetVdnsData(entry->vn_, ip4, ip6,
327  fip_vdns_name, fip_vdns_type);
328  CheckForFipUpdate(entry, fip_vdns_name, fip_vdns_type);
329  ++it;
330  }
331 }
332 
333 void DnsProto::CheckForUpdate(IpVdnsMap &ipvdns, const VmInterface *vmitf,
334  const VnEntry *vn, const Ip4Address &ip,
335  const Ip6Address &ip6, std::string &vdns_name,
336  const autogen::VirtualDnsType &vdns_type) {
337  IpVdnsMap::iterator vmdata_it = ipvdns.find(ip.to_ulong());
338  if (vmdata_it == ipvdns.end()) {
339  if (UpdateDnsEntry(vmitf, vn, vmitf->vm_name(),
340  vdns_name, ip, ip6, false, false))
341  ipvdns.insert(IpVdnsPair(ip.to_ulong(), vdns_name));
342  else
343  ipvdns.insert(IpVdnsPair(ip.to_ulong(), ""));
344  return;
345  }
346  if (vmdata_it->second.empty() && vmdata_it->second != vdns_name) {
347  if (UpdateDnsEntry(vmitf, vn, vmitf->vm_name(),
348  vdns_name, ip, ip6, false, false))
349  vmdata_it->second = vdns_name;
350  } else if (vmdata_it->second != vdns_name) {
351  if (MoveVDnsEntry(vmitf, vdns_name, vmdata_it->second,
352  vdns_type, false))
353  vmdata_it->second = vdns_name;
354  }
355 }
356 
357 void DnsProto::CheckForFipUpdate(DnsFipEntry *entry, std::string &vdns_name,
358  const autogen::VirtualDnsType &vdns_type) {
359  if (entry->vdns_name_.empty() && entry->vdns_name_ != vdns_name) {
360  std::string fip_name;
361  if (!GetFipName(entry->interface_, vdns_type,
362  entry->floating_ip_, fip_name))
363  vdns_name = "";
364 
365  Ip4Address ip4 = ip4_unspec_;
366  Ip6Address ip6 = ip6_unspec_;
367  if (entry->floating_ip_.is_v4()) {
368  ip4 = entry->floating_ip_.to_v4();
369  }
370  if (entry->floating_ip_.is_v6()) {
371  ip6 = entry->floating_ip_.to_v6();
372  }
373  if (UpdateDnsEntry(entry->interface_, entry->vn_, fip_name,
374  vdns_name, ip4, ip6, true, false)) {
375  entry->vdns_name_.assign(vdns_name);
376  entry->fip_name_ = fip_name;
377  }
378  } else if (entry->vdns_name_ != vdns_name) {
379  if (MoveVDnsEntry(entry->interface_, vdns_name, entry->vdns_name_,
380  vdns_type, true)) {
381  entry->vdns_name_.assign(vdns_name);
382  }
383  }
384 }
385 
386 // Send A & PTR record entries
388  const std::string &name,
389  const Ip4Address &ip, uint32_t plen,
390  const Ip6Address &ip6, uint32_t plen6,
391  const std::string &vdns_name,
392  const autogen::VirtualDnsType &vdns_type,
393  bool is_floating, bool is_delete) {
394  if (!name.size() || !vdns_type.dynamic_records_from_client) {
395  DNS_BIND_TRACE(DnsBindTrace, "Not adding DNS entry; Name = " <<
396  name << "Dynamic records allowed = " <<
397  (vdns_type.dynamic_records_from_client ? "yes" : "no"));
398  return false;
399  }
400 
401  DnsUpdateData *data = new DnsUpdateData();
402  data->virtual_dns = vdns_name;
403  data->zone = vdns_type.domain_name;
404 
405  std::string vm_uuid;
406  if (vmitf) {
407  vm_uuid = boost::uuids::to_string(vmitf->GetUuid());
408  }
409 
410  // Add a DNS record
411  DnsItem item;
412  if (!ip.is_unspecified()) {
413  item.eclass = is_delete ? DNS_CLASS_NONE : DNS_CLASS_IN;
414  item.type = DNS_A_RECORD;
415  item.ttl = is_delete ? 0 : vdns_type.default_ttl_seconds;
416  item.name = name;
417  item.vm_uuid = vm_uuid;
418  boost::system::error_code ec;
419  item.data = ip.to_string(ec);
420  data->items.push_back(item);
421  }
422 
423  DnsItem ip6_item;
424  if (!ip6.is_unspecified()) {
425  ip6_item.eclass = is_delete ? DNS_CLASS_NONE : DNS_CLASS_IN;
426  ip6_item.type = DNS_AAAA_RECORD;
427  ip6_item.ttl = is_delete ? 0 : vdns_type.default_ttl_seconds;
428  ip6_item.name = name;
429  ip6_item.vm_uuid = vm_uuid;
430  boost::system::error_code ec;
431  ip6_item.data = ip6.to_string(ec);
432  data->items.push_back(ip6_item);
433  }
434 
435  if (data->items.size()) {
436  DNS_BIND_TRACE(DnsBindTrace,
437  "DNS update sent for : " << item.ToString() <<
438  " IPv6 : " << ip6_item.ToString() <<
439  " VDNS : " << data->virtual_dns <<
440  " Zone : " << data->zone);
441  SendDnsUpdateIpc(data, DnsAgentXmpp::Update, vmitf, is_floating);
442  } else {
443  DNS_BIND_TRACE(DnsBindTrace, "Not adding DNS entry; Name = " <<
444  name << "Address unspecified");
445  return false;
446  }
447 
448  // Add a PTR record as well
449  DnsUpdateData *ptr_data = new DnsUpdateData();
450  ptr_data->virtual_dns = vdns_name;
451  BindUtil::GetReverseZone(ip, plen, ptr_data->zone);
452 
453  item.type = DNS_PTR_RECORD;
454  item.data.swap(item.name);
456  ptr_data->items.push_back(item);
457 
458  DNS_BIND_TRACE(DnsBindTrace, "DNS update sent for : " << item.ToString() <<
459  " VDNS : " << ptr_data->virtual_dns <<
460  " Zone : " << ptr_data->zone);
461  SendDnsUpdateIpc(ptr_data, DnsAgentXmpp::Update, vmitf, is_floating);
462 
463  // Add a PTR record for IPv6, if present
464  if (!ip6.is_unspecified()) {
465  DnsUpdateData *ptr6_data = new DnsUpdateData();
466  ptr6_data->virtual_dns = vdns_name;
467  BindUtil::GetReverseZone(ip6, plen6, ptr6_data->zone);
468 
469  ip6_item.type = DNS_PTR_RECORD;
470  ip6_item.data.swap(ip6_item.name);
471 
472  ip6_item.name = BindUtil::GetPtrNameFromAddr(ip6);
473  ptr6_data->items.push_back(ip6_item);
474 
475  DNS_BIND_TRACE(DnsBindTrace, "DNS update sent for : " << ip6_item.ToString() <<
476  " VDNS : " << ptr6_data->virtual_dns <<
477  " Zone : " << ptr6_data->zone);
478  SendDnsUpdateIpc(ptr6_data, DnsAgentXmpp::Update, vmitf, is_floating);
479  }
480 
481  return true;
482 }
483 
484 // Update the floating ip entries
485 bool DnsProto::UpdateFloatingIp(const VmInterface *vmitf, const VnEntry *vn,
486  const IpAddress &ip, bool is_deleted) {
487  Ip4Address ip4 = ip4_unspec_;
488  Ip6Address ip6 = ip6_unspec_;
489  if (ip.is_v6()) {
490  ip6 = ip.to_v6();
491  }
492  if (ip.is_v4()) {
493  ip4 = ip.to_v4();
494  }
495  bool is_floating = true;
496  std::string vdns_name;
497  autogen::VirtualDnsType vdns_type;
498  GetVdnsData(vn, ip4, ip6, vdns_name, vdns_type);
499  DnsFipEntryPtr key(new DnsFipEntry(vn, ip, vmitf));
500  DnsFipSet::iterator it = fip_list_.find(key);
501  if (it == fip_list_.end()) {
502  if (is_deleted)
503  return true;
504  std::string fip_name;
505  if (!GetFipName(vmitf, vdns_type, ip, fip_name))
506  vdns_name = "";
507  if (!UpdateDnsEntry(vmitf, vn, fip_name,
508  vdns_name, ip4, ip6, is_floating, false))
509  vdns_name = "";
510  key.get()->vdns_name_ = vdns_name;
511  key.get()->fip_name_ = fip_name;
512  fip_list_.insert(key);
513  } else {
514  if (is_deleted) {
515  std::string fip_name;
516  UpdateDnsEntry(vmitf, vn, (*it)->fip_name_,
517  (*it)->vdns_name_, ip4, ip6, is_floating, true);
518  fip_list_.erase(key);
519  } else {
520  DnsFipEntry *entry = (*it).get();
521  CheckForFipUpdate(entry, vdns_name, vdns_type);
522  }
523  }
524  return true;
525 }
526 
527 bool DnsProto::UpdateDnsEntry(const VmInterface *vmitf, const VnEntry *vn,
528  const std::string &vm_name,
529  const std::string &vdns_name,
530  const Ip4Address &ip,
531  const Ip6Address &ip6,
532  bool is_floating, bool is_deleted) {
533  if (!vdns_name.empty()) {
534  uint32_t plen = 0;
535  const std::vector<VnIpam> &ipam = vn->GetVnIpam();
536  unsigned int i;
537  if (!ip.is_unspecified()) {
538  for (i = 0; i < ipam.size(); ++i) {
539  if (ipam[i].IsV4() &&
540  IsIp4SubnetMember(ip, ipam[i].ip_prefix.to_v4(), ipam[i].plen)) {
541  plen = ipam[i].plen;
542  break;
543  }
544  }
545  if (i == ipam.size()) {
546  DNS_BIND_TRACE(DnsBindTrace, "UpdateDnsEntry for VM <" <<
547  vm_name << "> not done for vn <" <<
548  vn->GetName() << "> IPAM doesnt have Ipv4 subnet; " <<
549  ((is_deleted)? "delete" : "update"));
550  return false;
551  }
552  }
553 
554  uint32_t plen6 = 0;
555  if (!ip6.is_unspecified()) {
556  for (i = 0; i < ipam.size(); ++i) {
557  if (ipam[i].IsV6() &&
558  IsIp6SubnetMember(ip6, ipam[i].ip_prefix.to_v6(), ipam[i].plen)) {
559  plen6 = ipam[i].plen;
560  break;
561  }
562  }
563  if (i == ipam.size()) {
564  DNS_BIND_TRACE(DnsBindTrace, "UpdateDnsEntry for VM <" <<
565  vm_name << "> not done for vn <" <<
566  vn->GetName() << "> IPAM doesnt have Ipv6 subnet; " <<
567  ((is_deleted)? "delete" : "update"));
568  return false;
569  }
570  }
571 
572  autogen::VirtualDnsType vdns_type;
573  if (agent_->domain_config_table()->GetVDns(vdns_name, &vdns_type)) {
574  return SendUpdateDnsEntry(vmitf, vm_name, ip, plen, ip6, plen6,
575  vdns_name, vdns_type, is_floating,
576  is_deleted);
577  } else {
578  DNS_BIND_TRACE(DnsBindTrace, "UpdateDnsEntry for VM <" <<
579  vm_name << "> entry not " <<
580  ((is_deleted)? "deleted; " : "updated; ") <<
581  "VDNS info for " << vdns_name << " not present");
582  return false;
583  }
584  }
585 
586  return true;
587 }
588 
589 // Move DNS entries for a VM from one VDNS to another
591  std::string &new_vdns_name,
592  std::string &old_vdns_name,
593  const autogen::VirtualDnsType &vdns_type,
594  bool is_floating) {
595  std::string name = (vmitf ? vmitf->vm_name() : "All Vms");
596  DNS_BIND_TRACE(DnsBindTrace, "VDNS modify for VM <" << name <<
597  " old VDNS : " << old_vdns_name <<
598  " new VDNS : " << new_vdns_name <<
599  " ttl : " << vdns_type.default_ttl_seconds <<
600  " floating : " << (is_floating ? "yes" : "no"));
601  SendDnsUpdateIpc(vmitf, new_vdns_name,
602  old_vdns_name, vdns_type.domain_name,
603  (uint32_t)vdns_type.default_ttl_seconds, is_floating);
604  return true;
605 }
606 
607 bool DnsProto::GetVdnsData(const VnEntry *vn, const Ip4Address &v4_addr,
608  const Ip6Address &v6_addr, std::string &vdns_name,
609  autogen::VirtualDnsType &vdns_type) {
610  if (!vn)
611  return false;
612 
613  autogen::IpamType ipam_type;
614  if ((!v4_addr.to_ulong() ||
615  !vn->GetIpamVdnsData(v4_addr, &ipam_type, &vdns_type)) &&
616  (v6_addr.is_unspecified() ||
617  !vn->GetIpamVdnsData(v6_addr, &ipam_type, &vdns_type))) {
618  DNS_BIND_TRACE(DnsBindTrace, "Unable to retrieve VDNS data; VN : " <<
619  vn->GetName() << " IPv4 : " << v4_addr.to_string() <<
620  " IPv6 : " << v6_addr.to_string());
621  return false;
622  }
623 
624  vdns_name = ipam_type.ipam_dns_server.virtual_dns_server_name;
625  return true;
626 }
627 
629  const autogen::VirtualDnsType &vdns_type,
630  const IpAddress &ip, std::string &fip_name) const {
631  std::string fip_name_notation =
632  boost::to_lower_copy(vdns_type.floating_ip_record);
633 
634  std::string name;
635  if (fip_name_notation == "" ||
636  fip_name_notation == "dashed-ip" ||
637  fip_name_notation == "dashed-ip-tenant-name") {
638  name = ip.to_string();
639  boost::replace_all(name, ".", "-");
640  } else {
641  name = vmitf->vm_name();
642  }
643 
644  if (fip_name_notation == "" ||
645  fip_name_notation == "dashed-ip-tenant-name" ||
646  fip_name_notation == "vm-name-tenant-name") {
647  if (!vmitf->vn())
648  return false;
649  name += "." + vmitf->vn()->GetProject();
650  }
651 
652  fip_name = name;
653  return true;
654 }
655 
657  return (++xid_ == 0 ? ++xid_ : xid_);
658 }
659 
660 void DnsProto::SendDnsIpc(uint8_t *pkt, std::size_t length) {
661  DnsIpc *ipc = new DnsIpc(pkt, length, 0, NULL, DnsProto::DNS_BIND_RESPONSE);
663 }
664 
665 void DnsProto::SendDnsIpc(InterTaskMessage cmd, uint16_t xid, uint8_t *msg,
666  DnsHandler *handler) {
667  DnsIpc *ipc = new DnsIpc(msg, 0, xid, handler, cmd);
669 }
670 
673  const VmInterface *vm, bool floating) {
674  DnsUpdateIpc *ipc = new DnsUpdateIpc(type, data, vm, floating);
676 }
677 
679  const std::string &new_vdns,
680  const std::string &old_vdns,
681  const std::string &new_dom,
682  uint32_t ttl, bool is_floating) {
683  DnsUpdateIpc *ipc = new DnsUpdateIpc(vm, new_vdns, old_vdns, new_dom,
684  ttl, is_floating);
686 }
687 
689  DnsUpdateAllIpc *ipc = new DnsUpdateAllIpc(channel);
691 }
692 
693 void DnsProto::AddDnsQuery(uint16_t xid, DnsHandler *handler) {
694  dns_query_map_.insert(DnsBindQueryPair(xid, handler));
695 }
696 
697 void DnsProto::DelDnsQuery(uint16_t xid) {
698  dns_query_map_.erase(xid);
699 }
700 
701 bool DnsProto::IsDnsQueryInProgress(uint16_t xid) {
702  return dns_query_map_.find(xid) != dns_query_map_.end();
703 }
704 
706  for (DnsBindQueryMap::iterator it = dns_query_map_.begin();
707  it != dns_query_map_.end(); it++) {
708  if (it->second == handler) {
709  return true;
710  }
711  }
712  return false;
713 }
714 
716  for (DnsBindQueryMap::iterator it = dns_query_map_.begin();
717  it != dns_query_map_.end();) {
718  if (it->second == handler) {
719  dns_query_map_.erase(it++);
720  continue;
721  }
722  ++it;
723  }
724 }
725 
727  DnsBindQueryMap::iterator it = dns_query_map_.find(xid);
728  if (it != dns_query_map_.end())
729  return it->second;
730  return NULL;
731 }
732 
733 void DnsProto::AddDnsQueryIndex(uint16_t xid, int16_t srv_idx) {
734  dns_query_index_map_.insert(DnsBindQueryIndexPair(xid, srv_idx));
735 }
736 
737 void DnsProto::DelDnsQueryIndex(uint16_t xid) {
738  dns_query_index_map_.erase(xid);
739 }
740 
741 int16_t DnsProto::GetDnsQueryServerIndex(uint16_t xid) {
742  DnsBindQueryIndexMap::iterator it = dns_query_index_map_.find(xid);
743  if (it != dns_query_index_map_.end())
744  return it->second;
745  return -1;
746 }
747 
748 
750  curr_vm_requests_.insert(*key);
751 }
752 
754  curr_vm_requests_.erase(*key);
755 }
756 
758  return curr_vm_requests_.find(*key) != curr_vm_requests_.end();
759 }
760 
762  const VmInterface *itf)
763  : vn_(vn), floating_ip_(fip), interface_(itf) {
764 }
765 
767 }
768 
770  const DnsFipEntryPtr &rhs) const {
771  return lhs->IsLess(rhs.get());
772 }
773 
775  if (vn_ != rhs->vn_) {
776  return vn_ < rhs->vn_;
777  }
778  if (floating_ip_ != rhs->floating_ip_) {
779  return floating_ip_ < rhs->floating_ip_;
780  }
781  return interface_ < rhs->interface_;
782 }
boost::asio::ip::address_v6 Ip6Address
Definition: address.h:15
boost::asio::ip::address IpAddress
Definition: address.h:13
boost::asio::ip::address_v4 Ip4Address
Definition: address.h:14
bool IsIp6SubnetMember(const Ip6Address &ip, const Ip6Address &subnet, uint8_t plen)
Definition: address_util.cc:29
bool IsIp4SubnetMember(const Ip4Address &ip, const Ip4Address &prefix_ip, uint16_t plen)
Definition: address_util.cc:19
#define MAX_XMPP_SERVERS
Definition: agent.h:291
#define DNS_A_RECORD
Definition: bind_util.h:36
#define DNS_BIND_TRACE(obj, arg)
Definition: bind_util.h:21
#define DNS_PTR_RECORD
Definition: bind_util.h:40
#define DNS_CLASS_IN
Definition: bind_util.h:31
#define DNS_AAAA_RECORD
Definition: bind_util.h:43
#define DNS_CLASS_NONE
Definition: bind_util.h:33
static void set_dns_message_handler_cb(DnsMessageHandler cb)
static void set_dns_xmpp_event_handler_cb(DnsXmppEventHandler cb)
uint32_t services_queue_limit()
Definition: agent_param.h:415
Definition: agent.h:360
InterfaceTable * interface_table() const
Definition: agent.h:467
OperDB * oper_db() const
Definition: agent.cc:1016
DomainConfig * domain_config_table() const
Definition: agent.cc:1032
const std::string & dns_server(uint8_t idx) const
Definition: agent.h:859
AgentParam * params() const
Definition: agent.h:1226
VrfTable * vrf_table() const
Definition: agent.h:487
const Peer * local_peer() const
Definition: agent.h:1024
bool tsn_enabled() const
Definition: agent.h:1164
VnTable * vn_table() const
Definition: agent.h:497
const Interface * vhost_interface() const
Definition: agent.h:937
const std::string & fabric_vrf_name() const
Definition: agent.h:905
PktModule * pkt() const
Definition: agent.cc:968
static void Shutdown()
static void Init(boost::asio::io_context &io, const std::vector< DnsServer > &dns_servers, uint16_t client_port, Callback cb, uint8_t dscp)
static std::string GetPtrNameFromAddr(const Ip4Address &ip)
Definition: bind_util.cc:959
static void GetReverseZone(const Ip4Address &addr, uint32_t plen, std::string &zone)
Definition: bind_util.cc:812
static void AddBridgeReceiveRoute(const Peer *peer, const std::string &vrf_name, const MacAddress &mac, const std::string &vn_name, const std::string &interface, bool policy)
static void Delete(const Peer *peer, const std::string &vrf_name, const MacAddress &mac, uint32_t ethernet_tag)
bool IsDeleted() const
Definition: db_entry.h:48
ListenerId Register(ChangeCallback callback, const std::string &name="unspecified")
Definition: db_table.cc:207
void Unregister(ListenerId listener)
Definition: db_table.cc:212
bool operator()(const DnsFipEntryPtr &lhs, const DnsFipEntryPtr &rhs) const
Definition: dns_proto.cc:769
std::pair< uint32_t, int16_t > DnsBindQueryIndexPair
Definition: dns_proto.h:149
void DelDnsQuery(uint16_t xid)
Definition: dns_proto.cc:697
DefaultServerList GetDefaultServerList()
Definition: dns_proto.cc:119
void InterfaceNotify(DBEntryBase *entry)
Definition: dns_proto.cc:128
bool SendUpdateDnsEntry(const VmInterface *vmitf, const std::string &name, const Ip4Address &ip, uint32_t plen, const Ip6Address &ip6, uint32_t plen6, const std::string &vdns_name, const autogen::VirtualDnsType &vdns_type, bool is_floating, bool is_delete)
Definition: dns_proto.cc:387
void CheckForFipUpdate(DnsFipEntry *entry, std::string &vdns_name, const autogen::VirtualDnsType &vdns_type)
Definition: dns_proto.cc:357
DBTableBase::ListenerId vrf_table_listener_id_
Definition: dns_proto.h:270
void AddDnsQueryIndex(uint16_t xid, int16_t srv_idx)
Definition: dns_proto.cc:733
DnsFipSet fip_list_
Definition: dns_proto.h:267
InterTaskMessage
Definition: dns_proto.h:25
@ DNS_BIND_RESPONSE
Definition: dns_proto.h:28
bool UpdateDnsEntry(const VmInterface *vmitf, const VnEntry *vn, const std::string &vm_name, const std::string &vdns_name, const Ip4Address &ip, const Ip6Address &ip6, bool is_floating, bool is_deleted)
Definition: dns_proto.cc:527
DBTableBase::ListenerId lid_
Definition: dns_proto.h:268
DefaultServerList BuildDefaultServerListImpl()
uint16_t GetTransId()
Definition: dns_proto.cc:656
bool IsDnsQueryInProgress(uint16_t xid)
Definition: dns_proto.cc:701
void SendDnsIpc(uint8_t *pkt, std::size_t length)
Definition: dns_proto.cc:660
void VdnsNotify(IFMapNode *node)
Definition: dns_proto.cc:286
DnsHandler * GetDnsQueryHandler(uint16_t xid)
Definition: dns_proto.cc:726
std::pair< uint32_t, DnsHandler * > DnsBindQueryPair
Definition: dns_proto.h:140
void ConfigInit()
Definition: dns_proto.cc:42
bool BuildDefaultServerList()
Definition: dns_proto.cc:114
void SendDnsUpdateIpc(DnsUpdateData *data, DnsAgentXmpp::XmppType type, const VmInterface *vm, bool floating)
Definition: dns_proto.cc:671
void AddVmRequest(DnsHandler::QueryKey *key)
Definition: dns_proto.cc:749
ProtoHandler * AllocProtoHandler(boost::shared_ptr< PktInfo > info, boost::asio::io_context &io)
Definition: dns_proto.cc:123
void DelDnsQueryIndex(uint16_t xid)
Definition: dns_proto.cc:737
bool GetFipName(const VmInterface *vmitf, const autogen::VirtualDnsType &vdns_type, const IpAddress &ip, std::string &fip_name) const
Definition: dns_proto.cc:628
uint16_t xid_
Definition: dns_proto.h:255
std::map< uint32_t, std::string > IpVdnsMap
Definition: dns_proto.h:143
bool MoveVDnsEntry(const VmInterface *vmitf, std::string &new_vdns_name, std::string &old_vdns_name, const autogen::VirtualDnsType &vdns_type, bool is_floating)
Definition: dns_proto.cc:590
virtual ~DnsProto()
Definition: dns_proto.cc:101
bool IsDnsHandlerInUse(DnsHandler *handler)
Definition: dns_proto.cc:705
DnsVmRequestSet curr_vm_requests_
Definition: dns_proto.h:258
void VnNotify(DBEntryBase *entry)
Definition: dns_proto.cc:198
DnsUpdateSet update_set_
Definition: dns_proto.h:256
static const Ip4Address ip4_unspec_
Definition: dns_proto.h:17
DnsBindQueryIndexMap dns_query_index_map_
Definition: dns_proto.h:259
void ProcessNotify(std::string name, bool is_deleted, bool is_ipam)
Definition: dns_proto.cc:299
bool GetVdnsData(const VnEntry *vn, const Ip4Address &v4_addr, const Ip6Address &v6_addr, std::string &vdns_name, autogen::VirtualDnsType &vdns_type)
Definition: dns_proto.cc:607
bool IsVmRequestDuplicate(DnsHandler::QueryKey *key)
Definition: dns_proto.cc:757
void AddDnsQuery(uint16_t xid, DnsHandler *handler)
Definition: dns_proto.cc:693
DnsBindQueryMap dns_query_map_
Definition: dns_proto.h:257
void IpamNotify(IFMapNode *node)
Definition: dns_proto.cc:279
DBTableBase::ListenerId Vnlid_
Definition: dns_proto.h:269
void CheckForUpdate(IpVdnsMap &ipvdns, const VmInterface *vmitf, const VnEntry *vn, const Ip4Address &ip, const Ip6Address &ip6, std::string &vdns_name, const autogen::VirtualDnsType &vdns_type)
Definition: dns_proto.cc:333
std::pair< uint32_t, std::string > IpVdnsPair
Definition: dns_proto.h:144
bool UpdateFloatingIp(const VmInterface *vmitf, const VnEntry *vn, const IpAddress &ip, bool is_deleted)
Definition: dns_proto.cc:485
boost::shared_ptr< DnsFipEntry > DnsFipEntryPtr
Definition: dns_proto.h:132
DnsProto(Agent *agent, boost::asio::io_context &io)
Definition: dns_proto.cc:67
DefaultServerList def_server_list_
Definition: dns_proto.h:260
int16_t GetDnsQueryServerIndex(uint16_t xid)
Definition: dns_proto.cc:741
Timer * default_slist_timer_
Definition: dns_proto.h:264
static const Ip6Address ip6_unspec_
Definition: dns_proto.h:18
void VrfNotify(DBEntryBase *entry)
Definition: dns_proto.cc:258
std::pair< const VmInterface *, IpVdnsMap > VmDataPair
Definition: dns_proto.h:146
VmDataMap all_vms_
Definition: dns_proto.h:266
void IoShutdown()
Definition: dns_proto.cc:26
void DelDnsQueryHandler(DnsHandler *handler)
Definition: dns_proto.cc:715
static const uint32_t kDnsDefaultSlistInterval
Definition: dns_proto.h:22
void DelVmRequest(DnsHandler::QueryKey *key)
Definition: dns_proto.cc:753
void Shutdown()
Definition: dns_proto.cc:104
void RegisterIpamCb(Callback cb)
Definition: vn.cc:1442
bool GetVDns(const std::string &vdns, autogen::VirtualDnsType *vdns_type)
Definition: vn.cc:1568
void RegisterVdnsCb(Callback cb)
Definition: vn.cc:1446
const std::string & name() const
Definition: ifmap_node.h:48
IFMapObject * GetObject()
Definition: ifmap_node.cc:63
void set_update_floatingip_cb(UpdateFloatingIpFn fn)
Definition: interface.cc:629
@ VM_INTERFACE
Definition: interface.h:37
const MacAddress & mac() const
Definition: interface.h:133
const boost::uuids::uuid & GetUuid() const
Definition: interface.h:115
Type type() const
Definition: interface.h:114
GlobalQosConfig * global_qos_config() const
Definition: operdb_init.h:81
void SendMessage(PktModuleName mod, InterTaskMsg *msg)
PktHandler * pkt_handler() const
Definition: pkt_init.h:31
static TaskScheduler * GetInstance()
Definition: task.cc:573
static bool DeleteTimer(Timer *Timer)
Definition: timer.cc:221
static Timer * CreateTimer(boost::asio::io_context &service, const std::string &name, int task_id=Timer::GetTimerTaskId(), int task_instance=Timer::GetTimerInstanceId(), bool delete_on_completion=false)
Definition: timer.cc:200
bool Cancel()
Definition: timer.cc:149
bool Start(int time, Handler handler, ErrorHandler error_handler=NULL)
Definition: timer.cc:107
const FloatingIpList & floating_ip_list() const
VnEntryRef vn_
const VnEntry * vn() const
const Ip4Address & primary_ip_addr() const
const std::string & vm_name() const
const Ip6Address & primary_ip6_addr() const
Definition: vn.h:151
bool GetIpamVdnsData(const IpAddress &vm_addr, autogen::IpamType *ipam_type, autogen::VirtualDnsType *vdns_type) const
Definition: vn.cc:685
const std::vector< VnIpam > & GetVnIpam() const
Definition: vn.h:171
const string & GetName() const
Definition: vn.h:162
std::string GetProject() const
Definition: vn.cc:717
Definition: vrf.h:89
const string & GetName() const
Definition: vrf.h:103
VnEntry * vn() const
Definition: vrf.h:104
void SetBounded(bool bounded)
Definition: queue_task.h:200
void SetSize(size_t size)
Definition: queue_task.h:196
uint8_t type
Definition: load_balance.h:2
Definition: io_utils.cc:11
std::string name
Definition: bind_util.h:158
uint16_t eclass
Definition: bind_util.h:149
std::string vm_uuid
Definition: bind_util.h:160
uint16_t type
Definition: bind_util.h:150
std::string ToString() const
Definition: bind_util.cc:63
uint32_t ttl
Definition: bind_util.h:151
std::string data
Definition: bind_util.h:161
const VnEntry * vn_
Definition: dns_proto.h:125
bool IsLess(const DnsFipEntry *rhs) const
Definition: dns_proto.cc:774
virtual ~DnsFipEntry()
Definition: dns_proto.cc:766
IpAddress floating_ip_
Definition: dns_proto.h:126
const VmInterface * interface_
Definition: dns_proto.h:127
std::string fip_name_
Definition: dns_proto.h:129
DnsFipEntry(const VnEntry *vn, const IpAddress &fip, const VmInterface *itf)
Definition: dns_proto.cc:761
std::string vdns_name_
Definition: dns_proto.h:128
DnsItems items
Definition: bind_util.h:216
std::string virtual_dns
Definition: bind_util.h:214
std::string zone
Definition: bind_util.h:215
static const uint8_t kInvalidDscp
uint8_t control_dscp() const
uint8_t dns_dscp() const