LCOV - code coverage report
Current view: top level - vnsw/agent/oper - vn.cc (source / functions) Hit Total Coverage
Test: OpenSDN C/C++ coverage (all TARGET_SET jobs) Lines: 0 988 0.0 %
Date: 2026-06-22 02:21:21 Functions: 0 99 0.0 %
Legend: Lines: hit not hit

          Line data    Source code
       1             : /*
       2             :  * Copyright (c) 2013 Juniper Networks, Inc. All rights reserved.
       3             :  */
       4             : 
       5             : #include <algorithm>
       6             : #include <boost/uuid/uuid_io.hpp>
       7             : #include <cmn/agent_cmn.h>
       8             : 
       9             : #include <base/os.h>
      10             : #include <base/parse_object.h>
      11             : #include <base/util.h>
      12             : #include <base/address_util.h>
      13             : #include <ifmap/ifmap_link.h>
      14             : #include <ifmap/ifmap_table.h>
      15             : #include <vnc_cfg_types.h>
      16             : #include <agent_types.h>
      17             : 
      18             : #include <cfg/cfg_init.h>
      19             : #include <cfg/cfg_mirror.h>
      20             : 
      21             : #include <oper/route_common.h>
      22             : #include <oper/interface_common.h>
      23             : #include <oper/vn.h>
      24             : #include <oper/nexthop.h>
      25             : #include <oper/mpls.h>
      26             : #include <oper/mirror_table.h>
      27             : #include <oper/agent_sandesh.h>
      28             : #include <oper/oper_dhcp_options.h>
      29             : #include <oper/physical_device_vn.h>
      30             : #include <oper/config_manager.h>
      31             : #include <oper/global_vrouter.h>
      32             : #include <oper/agent_route_resync.h>
      33             : #include <oper/qos_config.h>
      34             : #include <filter/acl.h>
      35             : #include <oper/vxlan_routing_manager.h>
      36             : 
      37             : using namespace autogen;
      38             : using namespace std;
      39             : using namespace boost;
      40             : using boost::assign::map_list_of;
      41             : using boost::assign::list_of;
      42             : 
      43             : VnTable *VnTable::vn_table_;
      44             : 
      45             : /////////////////////////////////////////////////////////////////////////////
      46             : // VnIpam routines
      47             : /////////////////////////////////////////////////////////////////////////////
      48           0 : VnIpam::VnIpam(const std::string& ip, uint32_t len, const std::string& gw,
      49             :                const std::string& dns, bool dhcp, const std::string &name,
      50             :                const std::vector<autogen::DhcpOptionType> &dhcp_options,
      51             :                const std::vector<autogen::RouteType> &host_routes,
      52           0 :                uint32_t alloc)
      53           0 :         : plen(len), installed(false), dhcp_enable(dhcp), dhcp_enable_v6(dhcp), ipam_name(name),
      54           0 :           alloc_unit(alloc) {
      55           0 :     boost::system::error_code ec;
      56           0 :     ip_prefix = IpAddress::from_string(ip, ec);
      57           0 :     default_gw = IpAddress::from_string(gw, ec);
      58           0 :     dns_server = IpAddress::from_string(dns, ec);
      59           0 :     oper_dhcp_options.set_options(dhcp_options);
      60           0 :     oper_dhcp_options.set_host_routes(host_routes);
      61           0 : }
      62             : 
      63           0 : IpAddress VnIpam::GetSubnetAddress() const {
      64           0 :     if (ip_prefix.is_v4()) {
      65           0 :         return Address::GetIp4SubnetAddress(ip_prefix.to_v4(), plen);
      66             :     }
      67           0 :     if (ip_prefix.is_v6()) {
      68           0 :         return Address::GetIp6SubnetAddress(ip_prefix.to_v6(), plen);
      69             :     }
      70           0 :     return IpAddress();
      71             : }
      72             : 
      73           0 : bool VnIpam::IsSubnetMember(const IpAddress &ip) const {
      74           0 :     if (ip_prefix.is_v4() && ip.is_v4()) {
      75           0 :         return ((ip_prefix.to_v4().to_ulong() |
      76           0 :                  ~(0xFFFFFFFF << (32 - plen))) ==
      77           0 :                 (ip.to_v4().to_ulong() | ~(0xFFFFFFFF << (32 - plen))));
      78           0 :     } else if (ip_prefix.is_v6() && ip.is_v6()) {
      79           0 :         return IsIp6SubnetMember(ip.to_v6(), ip_prefix.to_v6(), plen);
      80             :     }
      81           0 :     return false;
      82             : }
      83             : 
      84             : /////////////////////////////////////////////////////////////////////////////
      85             : // VnEntry routines
      86             : /////////////////////////////////////////////////////////////////////////////
      87           0 : VnEntry::VnEntry(Agent *agent, boost::uuids::uuid id) :
      88           0 :     AgentOperDBEntry(), agent_(agent), uuid_(id), vrf_(NULL, this),
      89           0 :     vxlan_id_(0), vnid_(0), active_vxlan_id_(0), bridging_(true),
      90           0 :     layer3_forwarding_(true), admin_state_(true), table_label_(0),
      91           0 :     enable_rpf_(true), flood_unknown_unicast_(false),
      92           0 :     forwarding_mode_(Agent::L2_L3), mirror_destination_(false),
      93           0 :     underlay_forwarding_(false), vxlan_routing_vn_(false),
      94           0 :     logical_router_uuid_(), cfg_igmp_enable_(false), vn_max_flows_(0),
      95           0 :     lr_vrf_(NULL, this) {
      96           0 : }
      97             : 
      98           0 : VnEntry::~VnEntry() {
      99           0 : }
     100             : 
     101           0 : bool VnEntry::IsLess(const DBEntry &rhs) const {
     102           0 :     const VnEntry &a = static_cast<const VnEntry &>(rhs);
     103           0 :     return (uuid_ < a.uuid_);
     104             : }
     105             : 
     106           0 : string VnEntry::ToString() const {
     107           0 :     std::stringstream uuidstring;
     108           0 :     uuidstring << uuid_;
     109           0 :     return uuidstring.str();
     110           0 : }
     111             : 
     112           0 : DBEntryBase::KeyPtr VnEntry::GetDBRequestKey() const {
     113           0 :     return DBEntryBase::KeyPtr(new VnKey(uuid_));
     114             : }
     115             : 
     116           0 : void VnEntry::SetKey(const DBRequestKey *key) {
     117           0 :     const VnKey *k = static_cast<const VnKey *>(key);
     118           0 :     uuid_ = k->uuid_;
     119           0 : }
     120             : 
     121             : // Resync operation for VN. Invoked on change of forwarding-mode or global
     122             : // vxlan-config mode
     123           0 : bool VnEntry::Resync(Agent *agent) {
     124             :     // Evaluate rebake of vxlan
     125           0 :     bool ret = UpdateVxlan(agent, false);
     126             :     // Evaluate forwarding mode change
     127           0 :     ret |= UpdateForwardingMode(agent);
     128             :     // Update routes from Ipam
     129           0 :     ret |= ApplyAllIpam(agent, vrf_.get(), false);
     130           0 :     return ret;
     131             : }
     132             : 
     133           0 : bool VnEntry::ChangeHandler(Agent *agent, const DBRequest *req) {
     134           0 :     bool ret = false;
     135           0 :     VnData *data = static_cast<VnData *>(req->data.get());
     136             : 
     137           0 :     AclKey key(data->acl_id_);
     138           0 :     AclDBEntry *acl = static_cast<AclDBEntry *>
     139           0 :         (agent->acl_table()->FindActiveEntry(&key));
     140           0 :     if (acl_.get() != acl) {
     141           0 :         acl_ = acl;
     142           0 :         ret = true;
     143             :     }
     144             : 
     145           0 :     AclKey mirror_key(data->mirror_acl_id_);
     146           0 :     AclDBEntry *mirror_acl = static_cast<AclDBEntry *>
     147           0 :         (agent->acl_table()->FindActiveEntry(&mirror_key));
     148           0 :     if (mirror_acl_.get() != mirror_acl) {
     149           0 :         mirror_acl_ = mirror_acl;
     150           0 :         ret = true;
     151             :     }
     152             : 
     153           0 :     AclKey mirror_cfg_acl_key(data->mirror_cfg_acl_id_);
     154           0 :     AclDBEntry *mirror_cfg_acl = static_cast<AclDBEntry *>
     155           0 :          (agent->acl_table()->FindActiveEntry(&mirror_cfg_acl_key));
     156           0 :     if (mirror_cfg_acl_.get() != mirror_cfg_acl) {
     157           0 :         mirror_cfg_acl_ = mirror_cfg_acl;
     158           0 :         ret = true;
     159             :     }
     160             : 
     161           0 :     AgentQosConfigKey qos_config_key(data->qos_config_uuid_);
     162           0 :     AgentQosConfig *qos_config = static_cast<AgentQosConfig *>
     163           0 :         (agent->qos_config_table()->FindActiveEntry(&qos_config_key));
     164           0 :     if (qos_config_.get() != qos_config) {
     165           0 :         qos_config_ = qos_config;
     166           0 :         ret = true;
     167             :     }
     168             : 
     169           0 :     VrfKey vrf_key(data->vrf_name_);
     170           0 :     VrfEntry *vrf = static_cast<VrfEntry *>
     171           0 :         (agent->vrf_table()->FindActiveEntry(&vrf_key));
     172           0 :     VrfEntryRef old_vrf = vrf_;
     173           0 :     bool update_vxlan_state = false;
     174           0 :     if (vrf != old_vrf.get()) {
     175           0 :         if (!vrf) {
     176           0 :             ApplyAllIpam(agent, old_vrf.get(), true);
     177             :         }
     178           0 :         vrf_ = vrf;
     179           0 :         update_vxlan_state = true;
     180           0 :         ret = true;
     181             :     }
     182             : 
     183           0 :     if (admin_state_ != data->admin_state_) {
     184           0 :         admin_state_ = data->admin_state_;
     185           0 :         ret = true;
     186             :     }
     187             : 
     188           0 :     if (forwarding_mode_ != data->forwarding_mode_) {
     189           0 :         forwarding_mode_ = data->forwarding_mode_;
     190           0 :         ret = true;
     191             :     }
     192             : 
     193             :     // Recompute the forwarding modes in VN
     194             :     // Must rebake the routes if any change in forwarding modes
     195           0 :     bool resync_routes = false;
     196           0 :     resync_routes = UpdateForwardingMode(agent);
     197           0 :     ret |= resync_routes;
     198             : 
     199             :     // Update the routes derived from IPAM
     200           0 :     ret |= UpdateIpam(agent, data->ipam_);
     201             : 
     202           0 :     if (vn_ipam_data_ != data->vn_ipam_data_) {
     203           0 :         vn_ipam_data_ = data->vn_ipam_data_;
     204           0 :         ret = true;
     205             :     }
     206             : 
     207           0 :     if (enable_rpf_ != data->enable_rpf_) {
     208           0 :         enable_rpf_ = data->enable_rpf_;
     209           0 :         ret = true;
     210             :     }
     211             : 
     212           0 :     if (vxlan_routing_vn_ != data->vxlan_routing_vn_) {
     213           0 :         vxlan_routing_vn_ = data->vxlan_routing_vn_;
     214           0 :         update_vxlan_state = true;
     215           0 :         ret = true;
     216             :     }
     217             : 
     218           0 :     if (vxlan_id_ != data->vxlan_id_) {
     219           0 :         vxlan_id_ = data->vxlan_id_;
     220           0 :         ret = true;
     221           0 :         if ((agent->vxlan_network_identifier_mode() == Agent::CONFIGURED)  || vxlan_routing_vn_ ) {
     222           0 :             update_vxlan_state = true;
     223             :         }
     224             :     }
     225             : 
     226           0 :     if (vnid_ != data->vnid_) {
     227           0 :         vnid_ = data->vnid_;
     228           0 :         ret = true;
     229           0 :         if (agent->vxlan_network_identifier_mode() == Agent::AUTOMATIC) {
     230           0 :             update_vxlan_state = true;
     231             :         }
     232             :     }
     233             : 
     234           0 :     if (flood_unknown_unicast_ != data->flood_unknown_unicast_) {
     235           0 :         flood_unknown_unicast_ = data->flood_unknown_unicast_;
     236           0 :         update_vxlan_state = true;
     237           0 :         ret = true;
     238             :     }
     239             : 
     240           0 :     if (mirror_destination_ != data->mirror_destination_) {
     241           0 :         mirror_destination_ = data->mirror_destination_;
     242           0 :         update_vxlan_state = true;
     243           0 :         ret = true;
     244             :     }
     245             : 
     246           0 :     if (update_vxlan_state) {
     247           0 :         ret |= UpdateVxlan(agent, false);
     248             :     }
     249             : 
     250           0 :     if (resync_routes) {
     251           0 :         if (vrf_.get() != NULL) {
     252             :             AgentRouteResync *resync =
     253           0 :                 (static_cast<AgentRouteResync *>(route_resync_walker_.get()));
     254           0 :             resync->UpdateRoutesInVrf(vrf_.get());
     255             :         }
     256             :     }
     257             : 
     258           0 :     if (pbb_evpn_enable_ != data->pbb_evpn_enable_) {
     259           0 :         pbb_evpn_enable_ = data->pbb_evpn_enable_;
     260           0 :         ret = true;
     261             :     }
     262             : 
     263           0 :     if (pbb_etree_enable_ != data->pbb_etree_enable_) {
     264           0 :         pbb_etree_enable_ = data->pbb_etree_enable_;
     265           0 :         ret = true;
     266             :     }
     267             : 
     268           0 :     if (layer2_control_word_ != data->layer2_control_word_) {
     269           0 :         layer2_control_word_ = data->layer2_control_word_;
     270           0 :         ret = true;
     271             :     }
     272             : 
     273           0 :     if (underlay_forwarding_ != data->underlay_forwarding_) {
     274           0 :         underlay_forwarding_ = data->underlay_forwarding_;
     275           0 :         ret = true;
     276             :     }
     277             : 
     278           0 :     if (slo_list_ != data->slo_list_) {
     279           0 :         slo_list_ = data->slo_list_;
     280             :     }
     281             : 
     282           0 :     if (logical_router_uuid_ != data->logical_router_uuid_) {
     283           0 :         logical_router_uuid_ = data->logical_router_uuid_;
     284           0 :         ret = true;
     285             :     }
     286             : 
     287           0 :     if (mp_list_ != data->mp_list_) {
     288           0 :         mp_list_ = data->mp_list_;
     289             :     }
     290             : 
     291           0 :     if (cfg_igmp_enable_ != data->cfg_igmp_enable_) {
     292           0 :         cfg_igmp_enable_ = data->cfg_igmp_enable_;
     293             :     }
     294             : 
     295           0 :     if (vn_max_flows_ != data->vn_max_flows_) {
     296           0 :         vn_max_flows_ = data->vn_max_flows_;
     297           0 :         ret = true;
     298             :     }
     299             : 
     300           0 :     if (mac_ip_learning_enable_ != data->mac_ip_learning_enable_) {
     301           0 :         mac_ip_learning_enable_ = data->mac_ip_learning_enable_;
     302           0 :         ret = true;
     303             :     }
     304             : 
     305           0 :     if (health_check_uuid_ != data->health_check_uuid_) {
     306           0 :         health_check_uuid_ = data->health_check_uuid_;
     307           0 :         ret = true;
     308             :     }
     309             : 
     310           0 :     return ret;
     311           0 : }
     312             : 
     313             : // Rebake handles
     314             : // - vxlan-id change :
     315             : //   Deletes the config-entry for old-vxlan and adds config-entry for new-vxlan
     316             : //   Might result in change of vxlan_id_ref_ for the VN
     317             : //
     318             : //   If vxlan_id is 0, or vrf is NULL, its treated as delete of config-entry
     319             : // - Delete
     320             : //   Deletes the vxlan-config entry. Will reset the vxlan-id-ref to NULL
     321           0 : bool VnEntry::UpdateVxlan(Agent *agent, bool op_del) {
     322           0 :     int old_vxlan = active_vxlan_id_;
     323           0 :     int new_vxlan = GetVxLanId();
     324             : 
     325           0 :     if (op_del || old_vxlan != new_vxlan || vrf_.get() == NULL) {
     326           0 :         if (old_vxlan != 0) {
     327           0 :             agent->vxlan_table()->Delete(old_vxlan, uuid_);
     328           0 :             vxlan_id_ref_ = NULL;
     329           0 :             active_vxlan_id_ = 0;
     330             :         }
     331             :     }
     332             : 
     333           0 :     if (op_del == false && vrf_.get() != NULL && new_vxlan != 0) {
     334             :         vxlan_id_ref_ = agent->vxlan_table()->Locate
     335           0 :             (new_vxlan, uuid_, vrf_->GetName(), flood_unknown_unicast_,
     336           0 :              mirror_destination_, false, true);
     337           0 :         active_vxlan_id_ = new_vxlan;
     338             :     }
     339             : 
     340           0 :     return (old_vxlan != new_vxlan);
     341             : }
     342             : 
     343             : // Compute the layer3_forwarding_ and bridging mode for the VN.
     344             : // Forwarding mode is picked from VN if its defined. Else, picks forwarding
     345             : // mode from global-vrouter-config
     346           0 : bool VnEntry::UpdateForwardingMode(Agent *agent) {
     347           0 :     Agent::ForwardingMode forwarding_mode = forwarding_mode_;
     348           0 :     if (forwarding_mode == Agent::NONE) {
     349             :         forwarding_mode =
     350           0 :             agent->oper_db()->global_vrouter()->forwarding_mode();
     351             :     }
     352             : 
     353           0 :     bool ret = false;
     354           0 :     bool routing = (forwarding_mode == Agent::L2) ? false : true;
     355           0 :     if (routing != layer3_forwarding_) {
     356           0 :         layer3_forwarding_ = routing;
     357           0 :         ret = true;
     358             :     }
     359             : 
     360           0 :     bool bridging = (forwarding_mode == Agent::L3) ? false : true;
     361           0 :     if (bridging != bridging_) {
     362           0 :         bridging_ = bridging;
     363           0 :         ret = true;
     364             :     }
     365             : 
     366           0 :     return ret;
     367             : }
     368             : 
     369             : // Update all IPAM configurations. Typically invoked when forwarding-mode
     370             : // changes or VRF is set for the VN
     371           0 : bool VnEntry::ApplyAllIpam(Agent *agent, VrfEntry *old_vrf, bool del) {
     372           0 :     bool ret = false;
     373           0 :     for (unsigned int i = 0; i < ipam_.size(); ++i) {
     374           0 :         ret |= ApplyIpam(agent, &ipam_[i], old_vrf, del);
     375             :     }
     376             : 
     377           0 :     return ret;
     378             : }
     379             : 
     380             : // Add/Delete routes dervied from a single IPAM
     381           0 : bool VnEntry::ApplyIpam(Agent *agent, VnIpam *ipam, VrfEntry *old_vrf,
     382             :                         bool del) {
     383           0 :     if (CanInstallIpam(ipam) == false)
     384           0 :         del = true;
     385             : 
     386           0 :     bool old_installed = ipam->installed;
     387           0 :     if (del == false) {
     388           0 :         ipam->installed = AddIpamRoutes(agent, ipam);
     389             :     } else {
     390           0 :         DelIpamRoutes(agent, ipam, old_vrf);
     391           0 :         ipam->installed = false;
     392             :     }
     393             : 
     394           0 :     return old_installed != ipam->installed;
     395             : }
     396             : 
     397           0 : bool VnEntry::CanInstallIpam(const VnIpam *ipam) {
     398           0 :     if (vrf_.get() == NULL || layer3_forwarding_ == false)
     399           0 :         return false;
     400           0 :     return true;
     401             : }
     402             : 
     403             : // Check the old and new Ipam data and update receive routes for GW addresses
     404           0 : bool VnEntry::UpdateIpam(Agent *agent, std::vector<VnIpam> &new_ipam) {
     405           0 :     std::sort(new_ipam.begin(), new_ipam.end());
     406             : 
     407           0 :     std::vector<VnIpam>::iterator it_old = ipam_.begin();
     408           0 :     std::vector<VnIpam>::iterator it_new = new_ipam.begin();
     409           0 :     bool change = false;
     410           0 :     while (it_old != ipam_.end() && it_new != new_ipam.end()) {
     411           0 :         if (*it_old < *it_new) {
     412             :             // old entry is deleted
     413           0 :             ApplyIpam(agent, &(*it_old), vrf_.get(), true);
     414           0 :             change = true;
     415           0 :             it_old++;
     416           0 :         } else if (*it_new < *it_old) {
     417             :             // new entry
     418           0 :             ApplyIpam(agent, &(*it_new), vrf_.get(), false);
     419           0 :             change = true;
     420           0 :             it_new++;
     421             :         } else {
     422           0 :             change |= HandleIpamChange(agent, &(*it_old), &(*it_new));
     423           0 :             it_old++;
     424           0 :             it_new++;
     425             :         }
     426             :     }
     427             : 
     428             :     // delete remaining old entries
     429           0 :     for (; it_old != ipam_.end(); ++it_old) {
     430           0 :         ApplyIpam(agent, &(*it_old), vrf_.get(), true);
     431           0 :         change = true;
     432             :     }
     433             : 
     434             :     // add remaining new entries
     435           0 :     for (; it_new != new_ipam.end(); ++it_new) {
     436           0 :         ApplyIpam(agent, &(*it_new), vrf_.get(), false);
     437           0 :         change = true;
     438             :     }
     439             : 
     440           0 :     ipam_ = new_ipam;
     441           0 :     return change;
     442             : }
     443             : 
     444           0 : static bool IsGwHostRouteRequired(const Agent *agent) {
     445           0 :     return (!agent->tsn_enabled());
     446             : }
     447             : 
     448             : // Evaluate non key members of IPAM for changes. Key fields are not changed
     449             : // Handles changes to gateway-ip and service-ip in the IPAM
     450           0 : bool VnEntry::HandleIpamChange(Agent *agent, VnIpam *old_ipam,
     451             :                                VnIpam *new_ipam) {
     452           0 :     bool install = CanInstallIpam(new_ipam);
     453             : 
     454           0 :     if (install == false && old_ipam->installed == false)
     455           0 :         return false;
     456             : 
     457           0 :     if (install == false && old_ipam->installed == true) {
     458           0 :         ApplyIpam(agent, old_ipam, vrf_.get(), true);
     459           0 :         return true;
     460             :     }
     461             : 
     462           0 :     if (install == true && old_ipam->installed == false) {
     463           0 :         ApplyIpam(agent, new_ipam, vrf_.get(), false);
     464           0 :         return true;
     465             :     }
     466             : 
     467           0 :     new_ipam->installed = install;
     468           0 :     bool changed = false;
     469           0 :     bool policy = (agent->tsn_enabled()) ? false : true;
     470             :     // CEM-4646:don't delete route if is used by DNS/GW
     471             :     // Update: GW changed?NO, DNS changed?YES
     472             :     // action: check if old DNS address is same as GW address
     473             :     // Update: GW changed?YES, DNS changed?NO
     474             :     // action: check if old GW address is same as DNS address
     475             :     // Update: GW changed?YES, DNS changed?YES
     476             :     // action: check if new DNS server address is same as old GW address
     477             : 
     478           0 :     if (vrf_.get() && (vrf_->GetName() != agent->linklocal_vrf_name())) {
     479           0 :         if (old_ipam->default_gw != new_ipam->default_gw) {
     480           0 :             changed = true;
     481           0 :             if (IsGwHostRouteRequired(agent)) {
     482           0 :                 if (old_ipam->default_gw != new_ipam->dns_server) {
     483           0 :                     UpdateHostRoute(agent, old_ipam->default_gw,
     484           0 :                             new_ipam->default_gw, policy);
     485             :                 } else {
     486           0 :                     AddHostRoute(new_ipam->default_gw, policy);
     487             :                 }
     488             :             }
     489             :         }
     490             :     }
     491             : 
     492           0 :     if (old_ipam->dns_server != new_ipam->dns_server) {
     493           0 :         if (old_ipam->dns_server != new_ipam->default_gw) {
     494           0 :             UpdateHostRoute(agent, old_ipam->dns_server,
     495           0 :                     new_ipam->dns_server, policy);
     496             :         } else {
     497           0 :             AddHostRoute(new_ipam->dns_server, policy);
     498             :         }
     499           0 :         changed = true;
     500             :     }
     501             : 
     502             :     // update DHCP options
     503           0 :     old_ipam->oper_dhcp_options = new_ipam->oper_dhcp_options;
     504             : 
     505           0 :     if (old_ipam->dhcp_enable != new_ipam->dhcp_enable) {
     506           0 :         changed = true;
     507             :     }
     508             : 
     509           0 :     if (old_ipam->dhcp_enable_v6 != new_ipam->dhcp_enable_v6) {
     510           0 :         changed = true;
     511             :     }
     512             : 
     513           0 :     return changed;
     514             : }
     515             : 
     516           0 : void VnEntry::UpdateHostRoute(Agent *agent, const IpAddress &old_address,
     517             :                               const IpAddress &new_address,
     518             :                               bool policy) {
     519           0 :     AddHostRoute(new_address, policy);
     520           0 :     DelHostRoute(old_address);
     521           0 : }
     522             : 
     523             : // Add all routes derived from IPAM. IPAM generates following routes,
     524             : // - Subnet route
     525             : // - Gateway route
     526             : // - Service-IP route
     527           0 : bool VnEntry::AddIpamRoutes(Agent *agent, VnIpam *ipam) {
     528           0 :     if (vrf_ == NULL)
     529           0 :         return false;
     530             : 
     531             :     // Do not let the gateway configuration overwrite the receive nh.
     532           0 :     if (vrf_->GetName() == agent->linklocal_vrf_name()) {
     533           0 :         return false;
     534             :     }
     535             : 
     536             :     // Allways policy will be enabled for default Gateway and
     537             :     // Dns server to create flows for BGP as service even
     538             :     // though explicit disable policy config form user.
     539           0 :     bool policy = (agent->tsn_enabled()) ? false : true;
     540           0 :     if (IsGwHostRouteRequired(agent))
     541           0 :         AddHostRoute(ipam->default_gw, policy);
     542           0 :     AddHostRoute(ipam->dns_server, policy);
     543           0 :     AddSubnetRoute(ipam);
     544           0 :     return true;
     545             : }
     546             : 
     547             : // Delete routes generated from an IPAM
     548           0 : void VnEntry::DelIpamRoutes(Agent *agent, VnIpam *ipam, VrfEntry *vrf) {
     549           0 :     if (ipam->installed == false)
     550           0 :         return;
     551             : 
     552           0 :     assert(vrf);
     553           0 :     if (IsGwHostRouteRequired(agent))
     554           0 :         DelHostRoute(ipam->default_gw);
     555           0 :     DelHostRoute(ipam->dns_server);
     556           0 :     DelSubnetRoute(ipam);
     557             : }
     558             : 
     559             : // Add host route for gateway-ip or service-ip
     560           0 : void VnEntry::AddHostRoute(const IpAddress &address, bool policy) {
     561           0 :     if (address.is_v4()) {
     562             :         static_cast<InetUnicastAgentRouteTable *>(vrf_->
     563           0 :             GetInet4UnicastRouteTable())->AddHostRoute(vrf_->GetName(),
     564           0 :                 address.to_v4(), 32, GetName(), policy);
     565           0 :     } else if (address.is_v6()) {
     566             :         static_cast<InetUnicastAgentRouteTable *>(vrf_->
     567           0 :             GetInet6UnicastRouteTable())->AddHostRoute(vrf_->GetName(),
     568           0 :                 address.to_v6(), 128, GetName(), policy);
     569             :     }
     570           0 : }
     571             : 
     572             : // Del host route for gateway-ip or service-ip
     573           0 : void VnEntry::DelHostRoute(const IpAddress &address) {
     574           0 :     Agent *agent = static_cast<VnTable *>(get_table())->agent();
     575           0 :     if (address.is_v4()) {
     576             :         static_cast<InetUnicastAgentRouteTable *>
     577           0 :             (vrf_->GetInet4UnicastRouteTable())->DeleteReq
     578           0 :             (agent->local_peer(), vrf_->GetName(), address.to_v4(), 32, NULL);
     579           0 :     } else if (address.is_v6()) {
     580             :         static_cast<InetUnicastAgentRouteTable *>
     581           0 :             (vrf_->GetInet6UnicastRouteTable())->DeleteReq
     582           0 :             (agent->local_peer(), vrf_->GetName(), address.to_v6(), 128,
     583             :              NULL);
     584             :     }
     585           0 : }
     586             : 
     587             : // Add subnet route for the IPAM
     588           0 : void VnEntry::AddSubnetRoute(VnIpam *ipam) {
     589             :     static_cast<InetUnicastAgentRouteTable *>(vrf_->
     590           0 :             GetInetUnicastRouteTable(ipam->ip_prefix))->AddIpamSubnetRoute
     591           0 :             (vrf_->GetName(), ipam->GetSubnetAddress(), ipam->plen,
     592             :              GetName());
     593           0 : }
     594             : 
     595             : // Del subnet route for the IPAM
     596           0 : void VnEntry::DelSubnetRoute(VnIpam *ipam) {
     597           0 :     Agent *agent = static_cast<VnTable *>(get_table())->agent();
     598             :     static_cast<InetUnicastAgentRouteTable *>(vrf_->
     599           0 :             GetInetUnicastRouteTable(ipam->ip_prefix))->DeleteReq
     600           0 :             (agent->local_peer(), vrf_->GetName(),
     601           0 :              ipam->GetSubnetAddress(), ipam->plen, NULL);
     602           0 : }
     603             : 
     604           0 : void VnEntry::AllocWalker() {
     605           0 :     assert(route_resync_walker_.get() == NULL);
     606             :     route_resync_walker_ = new AgentRouteResync("VnRouteResyncWalker",
     607           0 :                                                 agent_);
     608           0 :     agent_->oper_db()->agent_route_walk_manager()->
     609           0 :         RegisterWalker(static_cast<AgentRouteWalker *>
     610             :                        (route_resync_walker_.get()));
     611           0 : }
     612             : 
     613           0 : void VnEntry::ReleaseWalker() {
     614           0 :     if (route_resync_walker_.get() == NULL)
     615           0 :         return;
     616           0 :     agent_->oper_db()->agent_route_walk_manager()->
     617           0 :         ReleaseWalker(route_resync_walker_.get());
     618           0 :     route_resync_walker_.reset(NULL);
     619             : }
     620             : 
     621           0 : bool VnEntry::GetVnHostRoutes(const std::string &ipam,
     622             :                               std::vector<OperDhcpOptions::HostRoute> *routes) const {
     623           0 :     VnData::VnIpamDataMap::const_iterator it = vn_ipam_data_.find(ipam);
     624           0 :     if (it != vn_ipam_data_.end()) {
     625           0 :         *routes = it->second.oper_dhcp_options_.host_routes();
     626           0 :         return true;
     627             :     }
     628           0 :     return false;
     629             : }
     630             : 
     631           0 : bool VnEntry::GetIpamName(const IpAddress &vm_addr,
     632             :                           std::string *ipam_name) const {
     633           0 :     for (unsigned int i = 0; i < ipam_.size(); i++) {
     634           0 :         if (ipam_[i].IsSubnetMember(vm_addr)) {
     635           0 :             *ipam_name = ipam_[i].ipam_name;
     636           0 :             return true;
     637             :         }
     638             :     }
     639           0 :     return false;
     640             : }
     641             : 
     642           0 : bool VnEntry::GetIpamData(const IpAddress &vm_addr,
     643             :                           std::string *ipam_name,
     644             :                           autogen::IpamType *ipam) const {
     645           0 :     if (!GetIpamName(vm_addr, ipam_name) ||
     646           0 :         !agent_->domain_config_table()->GetIpam(*ipam_name, ipam))
     647           0 :         return false;
     648             : 
     649           0 :     return true;
     650             : }
     651             : 
     652           0 : const VnIpam *VnEntry::GetIpam(const IpAddress &ip) const {
     653           0 :     for (unsigned int i = 0; i < ipam_.size(); i++) {
     654           0 :         if (ipam_[i].IsSubnetMember(ip)) {
     655           0 :             return &ipam_[i];
     656             :         }
     657             :     }
     658           0 :     return NULL;
     659             : }
     660             : 
     661           0 : IpAddress VnEntry::GetGatewayFromIpam(const IpAddress &ip) const {
     662           0 :     const VnIpam *ipam = GetIpam(ip);
     663           0 :     if (ipam) {
     664           0 :         return ipam->default_gw;
     665             :     }
     666           0 :     return IpAddress();
     667             : }
     668             : 
     669           0 : IpAddress VnEntry::GetDnsFromIpam(const IpAddress &ip) const {
     670           0 :     const VnIpam *ipam = GetIpam(ip);
     671           0 :     if (ipam) {
     672           0 :         return ipam->dns_server;
     673             :     }
     674           0 :     return IpAddress();
     675             : }
     676             : 
     677           0 : uint32_t VnEntry::GetAllocUnitFromIpam(const IpAddress &ip) const {
     678           0 :     const VnIpam *ipam = GetIpam(ip);
     679           0 :     if (ipam) {
     680           0 :         return ipam->alloc_unit;
     681             :     }
     682           0 :     return 1;//Default value
     683             : }
     684             : 
     685           0 : bool VnEntry::GetIpamVdnsData(const IpAddress &vm_addr,
     686             :                               autogen::IpamType *ipam_type,
     687             :                               autogen::VirtualDnsType *vdns_type) const {
     688           0 :     std::string ipam_name;
     689           0 :     if (!GetIpamName(vm_addr, &ipam_name) ||
     690           0 :         !agent_->domain_config_table()->GetIpam(ipam_name, ipam_type) ||
     691           0 :         ipam_type->ipam_dns_method != "virtual-dns-server")
     692           0 :         return false;
     693             : 
     694           0 :     if (!agent_->domain_config_table()->GetVDns(
     695           0 :                 ipam_type->ipam_dns_server.virtual_dns_server_name, vdns_type))
     696           0 :         return false;
     697             : 
     698           0 :     return true;
     699           0 : }
     700             : 
     701           0 : bool VnEntry::GetPrefix(const Ip6Address &ip, Ip6Address *prefix,
     702             :                         uint8_t *plen) const {
     703           0 :     for (uint32_t i = 0; i < ipam_.size(); ++i) {
     704           0 :         if (!ipam_[i].IsV6()) {
     705           0 :             continue;
     706             :         }
     707           0 :         if (IsIp6SubnetMember(ip, ipam_[i].ip_prefix.to_v6(),
     708           0 :                               ipam_[i].plen)) {
     709           0 :             *prefix = ipam_[i].ip_prefix.to_v6();
     710           0 :             *plen = (uint8_t)ipam_[i].plen;
     711           0 :             return true;
     712             :         }
     713             :     }
     714           0 :     return false;
     715             : }
     716             : 
     717           0 : std::string VnEntry::GetProject() const {
     718             :     // TODO: update to get the project name from project-vn link.
     719             :     // Currently, this info doesnt come to the agent
     720           0 :     std::string name(name_.c_str());
     721             :     char *saveptr;
     722           0 :     if (strtok_r(const_cast<char *>(name.c_str()), ":", &saveptr) == NULL)
     723           0 :         return "";
     724           0 :     char *project = strtok_r(NULL, ":", &saveptr);
     725           0 :     return (project == NULL) ? "" : std::string(project);
     726           0 : }
     727             : 
     728           0 : int VnEntry::GetVxLanId() const {
     729           0 :     if (agent_->vxlan_network_identifier_mode() == Agent::CONFIGURED) {
     730           0 :         return vxlan_id_;
     731             :     }
     732           0 :     if (vxlan_routing_vn_ && vxlan_id_) {
     733           0 :         return vxlan_id_;
     734             :     }
     735           0 :     return vnid_;
     736             : }
     737             : 
     738           0 : int VnEntry::GetOperVxlanId() const {
     739           0 :     if (agent_->vxlan_network_identifier_mode() == Agent::CONFIGURED) {
     740           0 :         return vxlan_id_;
     741             :     }
     742           0 :     if (bool(vxlan_id_ref_)) {
     743           0 :         return vxlan_id_ref_->vxlan_id();
     744             :     }
     745           0 :     return 0;
     746             : }
     747             : 
     748             : /////////////////////////////////////////////////////////////////////////////
     749             : // VnTable routines
     750             : /////////////////////////////////////////////////////////////////////////////
     751           0 : VnTable::VnTable(DB *db, const std::string &name) : AgentOperDBTable(db, name) {
     752           0 :     walk_ref_ = AllocWalker(boost::bind(&VnTable::VnEntryWalk, this, _1, _2),
     753             :                             boost::bind(&VnTable::VnEntryWalkDone, this, _1,
     754           0 :                                         _2));
     755           0 : }
     756             : 
     757           0 : VnTable::~VnTable() {
     758           0 : }
     759             : 
     760           0 : void VnTable::Clear() {
     761           0 :     ReleaseWalker(walk_ref_);
     762           0 : }
     763             : 
     764           0 : DBTableBase *VnTable::CreateTable(DB *db, const std::string &name) {
     765           0 :     vn_table_ = new VnTable(db, name);
     766           0 :     vn_table_->Init();
     767           0 :     return vn_table_;
     768             : };
     769             : 
     770           0 : VnEntry *VnTable::Find(const boost::uuids::uuid &u) {
     771           0 :     VnKey key(u);
     772           0 :     return static_cast<VnEntry *>(FindActiveEntry(&key));
     773           0 : }
     774             : 
     775           0 : std::unique_ptr<DBEntry> VnTable::AllocEntry(const DBRequestKey *k) const {
     776           0 :     const VnKey *key = static_cast<const VnKey *>(k);
     777           0 :     VnEntry *vn = new VnEntry(agent(), key->uuid_);
     778           0 :     return std::unique_ptr<DBEntry>(static_cast<DBEntry *>(vn));
     779             : }
     780             : 
     781           0 : DBEntry *VnTable::OperDBAdd(const DBRequest *req) {
     782           0 :     VnKey *key = static_cast<VnKey *>(req->key.get());
     783           0 :     VnData *data = static_cast<VnData *>(req->data.get());
     784           0 :     VnEntry *vn = new VnEntry(agent(), key->uuid_);
     785           0 :     vn->name_ = data->name_;
     786           0 :     vn->AllocWalker();
     787             : 
     788           0 :     vn->ChangeHandler(agent(), req);
     789           0 :     vn->SendObjectLog(GetOperDBTraceBuf(), AgentLogEvent::ADD);
     790             : 
     791           0 :     if (vn->name_ == agent()->fabric_vn_name()) {
     792             :         //In case of distributes SNAT we want all
     793             :         //interfaces to revaluated upon receiving
     794             :         //the config
     795           0 :         agent()->set_fabric_vn_uuid(key->uuid_);
     796           0 :         agent()->cfg()->cfg_vm_interface_table()->NotifyAllEntries();
     797             :     }
     798           0 :     return vn;
     799             : }
     800             : 
     801           0 : bool VnTable::OperDBDelete(DBEntry *entry, const DBRequest *req) {
     802           0 :     VnEntry *vn = static_cast<VnEntry *>(entry);
     803           0 :     vn->ApplyAllIpam(agent(), vn->vrf_.get(), true);
     804           0 :     vn->UpdateVxlan(agent(), true);
     805           0 :     vn->ReleaseWalker();
     806           0 :     vn->SendObjectLog(GetOperDBTraceBuf(), AgentLogEvent::DEL);
     807             : 
     808           0 :     if (vn->name_ == agent()->fabric_vn_name()) {
     809           0 :         agent()->set_fabric_vn_uuid(boost::uuids::nil_uuid());
     810           0 :         agent()->cfg()->cfg_vm_interface_table()->NotifyAllEntries();
     811             :     }
     812           0 :     return true;
     813             : }
     814             : 
     815           0 : bool VnTable::OperDBOnChange(DBEntry *entry, const DBRequest *req) {
     816           0 :     VnEntry *vn = static_cast<VnEntry *>(entry);
     817           0 :     bool ret = vn->ChangeHandler(agent(), req);
     818           0 :     vn->SendObjectLog(GetOperDBTraceBuf(), AgentLogEvent::CHANGE);
     819           0 :     if (ret) {
     820           0 :         VnData *data = static_cast<VnData *>(req->data.get());
     821           0 :         if (data && data->ifmap_node()) {
     822             :             agent()->oper_db()->dependency_manager()->PropogateNodeChange
     823           0 :                 (data->ifmap_node());
     824             :         }
     825             :     }
     826           0 :     return ret;
     827             : }
     828             : 
     829           0 : bool VnTable::OperDBResync(DBEntry *entry, const DBRequest *req) {
     830           0 :     VnEntry *vn = static_cast<VnEntry *>(entry);
     831           0 :     return vn->Resync(agent());
     832             : }
     833             : 
     834           0 : bool VnTable::VnEntryWalk(DBTablePartBase *partition, DBEntryBase *entry) {
     835           0 :     VnEntry *vn_entry = static_cast<VnEntry *>(entry);
     836           0 :     if (vn_entry->GetVrf()) {
     837           0 :         ResyncReq(vn_entry->GetUuid());
     838             :     }
     839           0 :     return true;
     840             : }
     841             : 
     842           0 : void VnTable::VnEntryWalkDone(DBTable::DBTableWalkRef walk_ref,
     843             :                               DBTableBase *partition) {
     844           0 :     agent()->interface_table()->GlobalVrouterConfigChanged();
     845             :     agent()->physical_device_vn_table()->
     846           0 :         UpdateVxLanNetworkIdentifierMode();
     847           0 : }
     848             : 
     849           0 : void VnTable::GlobalVrouterConfigChanged() {
     850           0 :     WalkAgain(walk_ref_);
     851           0 : }
     852             : 
     853             : /*
     854             :  * IsVRFServiceChainingInstance
     855             :  * Helper function to identify the service chain vrf.
     856             :  * In VN-VRF mapping config can send multiple VRF for same VN.
     857             :  * Since assumption had been made that VN to VRF is always 1:1 this
     858             :  * situation needs to be handled.
     859             :  * This is a temporary solution in which all VRF other than primary VRF
     860             :  * is ignored.
     861             :  * Example:
     862             :  * VN name: domain:vn1
     863             :  * VRF 1: domain:vn1:vn1 ----> Primary
     864             :  * VRF 2: domain:vn1:service-vn1_vn2 ----> Second vrf linked to vn1
     865             :  * Break the VN and VRF name into tokens based on ':'
     866             :  * So in primary vrf last and second-last token will be same and will be
     867             :  * equal to last token of VN name. Keep this VRF.
     868             :  * The second VRF last and second-last token are not same so it will be ignored.
     869             :  *
     870             :  */
     871           0 : bool IsVRFServiceChainingInstance(const string &vn_name, const string &vrf_name)
     872             : {
     873           0 :     vector<string> vn_token_result;
     874           0 :     vector<string> vrf_token_result;
     875           0 :     uint32_t vrf_token_result_size = 0;
     876             : 
     877           0 :     split(vn_token_result, vn_name, is_any_of(":"), token_compress_on);
     878           0 :     split(vrf_token_result, vrf_name, is_any_of(":"), token_compress_on);
     879           0 :     vrf_token_result_size = vrf_token_result.size();
     880             : 
     881             :     /*
     882             :      * This check is to handle test cases where vrf and vn name
     883             :      * are single word without discriminator ':'
     884             :      * e.g. vrf1 or vn1. In these cases we dont ignore and use
     885             :      * the VRF
     886             :      */
     887           0 :     if (vrf_token_result_size == 1) {
     888           0 :         return false;
     889             :     }
     890           0 :     if ((vrf_token_result.at(vrf_token_result_size - 1) ==
     891           0 :         vrf_token_result.at(vrf_token_result_size - 2)) &&
     892           0 :         (vn_token_result.at(vn_token_result.size() - 1) ==
     893           0 :          vrf_token_result.at(vrf_token_result_size - 1))) {
     894           0 :         return false;
     895             :     }
     896           0 :     return true;
     897           0 : }
     898             : 
     899           0 : IFMapNode *VnTable::FindTarget(IFMapAgentTable *table, IFMapNode *node,
     900             :                                std::string node_type) {
     901           0 :     for (DBGraphVertex::adjacency_iterator it = node->begin(table->GetGraph());
     902           0 :          it != node->end(table->GetGraph()); ++it) {
     903           0 :         IFMapNode *adj_node = static_cast<IFMapNode *>(it.operator->());
     904           0 :         if (adj_node->table()->Typename() == node_type)
     905           0 :             return adj_node;
     906             :     }
     907           0 :     return NULL;
     908             : }
     909             : 
     910           0 : int VnTable::GetCfgVnId(VirtualNetwork *cfg_vn) {
     911           0 :     if (cfg_vn->IsPropertySet(autogen::VirtualNetwork::NETWORK_ID))
     912           0 :         return cfg_vn->network_id();
     913             :     else
     914           0 :         return cfg_vn->properties().network_id;
     915             : }
     916             : 
     917           0 : void VnTable::CfgForwardingFlags(IFMapNode *node,
     918             :                                  bool *rpf, bool *flood_unknown_unicast,
     919             :                                  Agent::ForwardingMode *forwarding_mode,
     920             :                                  bool *mirror_destination) {
     921           0 :     *rpf = true;
     922             : 
     923           0 :     VirtualNetwork *cfg = static_cast <VirtualNetwork *> (node->GetObject());
     924           0 :     autogen::VirtualNetworkType properties = cfg->properties();
     925             : 
     926           0 :     if (properties.rpf == "disable") {
     927           0 :         *rpf = false;
     928             :     }
     929             : 
     930           0 :     *flood_unknown_unicast = cfg->flood_unknown_unicast();
     931           0 :     *mirror_destination = properties.mirror_destination;
     932           0 :     *forwarding_mode =
     933           0 :         agent()->TranslateForwardingMode(properties.forwarding_mode);
     934           0 :  }
     935             : 
     936             : void
     937           0 : VnTable::BuildVnIpamData(const std::vector<autogen::IpamSubnetType> &subnets,
     938             :                          const std::string &ipam_name,
     939             :                          std::vector<VnIpam> *vn_ipam) {
     940           0 :     for (unsigned int i = 0; i < subnets.size(); ++i) {
     941             :         // if the DNS server address is not specified, set this
     942             :         // to be the same as the GW address
     943           0 :         std::string dns_server_address = subnets[i].dns_server_address;
     944           0 :         boost::system::error_code ec;
     945             :         IpAddress dns_server =
     946           0 :             IpAddress::from_string(dns_server_address, ec);
     947           0 :         if (ec.value() || dns_server.is_unspecified()) {
     948           0 :             dns_server_address = subnets[i].default_gateway;
     949             :         }
     950             : 
     951             :         vn_ipam->push_back
     952           0 :             (VnIpam(subnets[i].subnet.ip_prefix,
     953           0 :                     subnets[i].subnet.ip_prefix_len,
     954           0 :                     subnets[i].default_gateway,
     955             :                     dns_server_address,
     956           0 :                     subnets[i].enable_dhcp, ipam_name,
     957           0 :                     subnets[i].dhcp_option_list.dhcp_option,
     958           0 :                     subnets[i].host_routes.route,
     959           0 :                     subnets[i].alloc_unit));
     960           0 :     }
     961           0 : }
     962             : 
     963           0 : VnData *VnTable::BuildData(IFMapNode *node) {
     964             :     using boost::uuids::uuid;
     965             :     using boost::uuids::nil_uuid;
     966           0 :     boost::uuids::uuid mp_uuid = nil_uuid();
     967           0 :     UuidList mp_list;
     968             : 
     969           0 :     VirtualNetwork *cfg = static_cast <VirtualNetwork *> (node->GetObject());
     970           0 :     assert(cfg);
     971             : 
     972           0 :     uuid acl_uuid = nil_uuid();
     973           0 :     uuid mirror_cfg_acl_uuid = nil_uuid();
     974           0 :     uuid qos_config_uuid = nil_uuid();
     975           0 :     string vrf_name = "";
     976           0 :     std::vector<VnIpam> vn_ipam;
     977           0 :     VnData::VnIpamDataMap vn_ipam_data;
     978           0 :     std::string ipam_name;
     979           0 :     UuidList slo_list;
     980           0 :     bool underlay_forwarding = false;
     981           0 :     bool vxlan_routing_vn = false;
     982           0 :     uuid logical_router_uuid = nil_uuid();
     983           0 :     uuid health_check_uuid = nil_uuid();
     984             : 
     985             :     // Find link with ACL / VRF adjacency
     986           0 :     IFMapAgentTable *table = static_cast<IFMapAgentTable *>(node->table());
     987           0 :     DBGraph *graph = table->GetGraph();
     988           0 :     for (DBGraphVertex::adjacency_iterator iter = node->begin(graph);
     989           0 :          iter != node->end(table->GetGraph()); ++iter) {
     990             : 
     991           0 :         IFMapNode *adj_node = static_cast<IFMapNode *>(iter.operator->());
     992           0 :         if (agent()->config_manager()->SkipNode(adj_node)) {
     993           0 :             continue;
     994             :         }
     995             : 
     996           0 :         if (adj_node->table() == agent()->cfg()->cfg_acl_table()) {
     997             :             AccessControlList *acl_cfg = static_cast<AccessControlList *>
     998           0 :                 (adj_node->GetObject());
     999           0 :             assert(acl_cfg);
    1000           0 :             autogen::IdPermsType id_perms = acl_cfg->id_perms();
    1001           0 :             if (acl_cfg->entries().dynamic) {
    1002           0 :                 CfgUuidSet(id_perms.uuid.uuid_mslong, id_perms.uuid.uuid_lslong,
    1003             :                            mirror_cfg_acl_uuid);
    1004             :             } else {
    1005           0 :                 CfgUuidSet(id_perms.uuid.uuid_mslong, id_perms.uuid.uuid_lslong,
    1006             :                            acl_uuid);
    1007             :             }
    1008           0 :         }
    1009             : 
    1010           0 :         if ((adj_node->table() == agent()->cfg()->cfg_vrf_table()) &&
    1011           0 :             (!IsVRFServiceChainingInstance(node->name(), adj_node->name()))) {
    1012           0 :             vrf_name = adj_node->name();
    1013             :         }
    1014             : 
    1015           0 :         if (adj_node->table() == agent()->cfg()->cfg_qos_table()) {
    1016             :             autogen::QosConfig *qc =
    1017           0 :                 static_cast<autogen::QosConfig *>(adj_node->GetObject());
    1018           0 :             autogen::IdPermsType id_perms = qc->id_perms();
    1019           0 :             CfgUuidSet(id_perms.uuid.uuid_mslong, id_perms.uuid.uuid_lslong,
    1020             :                         qos_config_uuid);
    1021           0 :         }
    1022             : 
    1023           0 :         if (adj_node->table() == agent()->cfg()->cfg_slo_table()) {
    1024           0 :             uuid slo_uuid = nil_uuid();
    1025             :             autogen::SecurityLoggingObject *slo =
    1026             :                 static_cast<autogen::SecurityLoggingObject *>(adj_node->
    1027           0 :                                                               GetObject());
    1028           0 :             autogen::IdPermsType id_perms = slo->id_perms();
    1029           0 :             CfgUuidSet(id_perms.uuid.uuid_mslong, id_perms.uuid.uuid_lslong,
    1030             :                        slo_uuid);
    1031           0 :             slo_list.push_back(slo_uuid);
    1032           0 :         }
    1033             : 
    1034           0 :         if (adj_node->table() == agent()->cfg()->cfg_vn_network_ipam_table()) {
    1035           0 :             if (IFMapNode *ipam_node = FindTarget(table, adj_node,
    1036             :                                                   "network-ipam")) {
    1037           0 :                 ipam_name = ipam_node->name();
    1038             :                 VirtualNetworkNetworkIpam *vnni =
    1039             :                     static_cast<VirtualNetworkNetworkIpam *>
    1040           0 :                     (adj_node->GetObject());
    1041           0 :                 VnSubnetsType subnets;
    1042           0 :                 if (vnni)
    1043           0 :                     subnets = vnni->data();
    1044             : 
    1045             :                 autogen::NetworkIpam *network_ipam =
    1046           0 :                     static_cast<autogen::NetworkIpam *>(ipam_node->GetObject());
    1047             :                 const std::string subnet_method =
    1048           0 :                     boost::to_lower_copy(network_ipam->ipam_subnet_method());
    1049             : 
    1050           0 :                 if (subnet_method == "flat-subnet") {
    1051           0 :                     BuildVnIpamData(network_ipam->ipam_subnets(),
    1052             :                                     ipam_name, &vn_ipam);
    1053             :                 } else {
    1054           0 :                     BuildVnIpamData(subnets.ipam_subnets, ipam_name, &vn_ipam);
    1055             :                 }
    1056             : 
    1057           0 :                 VnIpamLinkData ipam_data;
    1058           0 :                 ipam_data.oper_dhcp_options_.set_host_routes(subnets.host_routes.route);
    1059           0 :                 vn_ipam_data.insert(VnData::VnIpamDataPair(ipam_name, ipam_data));
    1060           0 :             }
    1061             :         }
    1062             : 
    1063           0 :         if (adj_node->table() == agent()->cfg()->cfg_vn_table()) {
    1064           0 :             if (agent()->fabric_vn_name() == adj_node->name()) {
    1065           0 :                 underlay_forwarding = true;
    1066             :             }
    1067             :         }
    1068             : 
    1069           0 :         if (strcmp(adj_node->table()->Typename(),
    1070           0 :                    "logical-router-virtual-network") == 0) {
    1071             :             autogen::LogicalRouterVirtualNetwork *lr_vn_node =
    1072           0 :                 dynamic_cast<autogen::LogicalRouterVirtualNetwork *>
    1073           0 :                 (adj_node->GetObject());
    1074           0 :             autogen::LogicalRouter *lr = NULL;
    1075             :             IFMapNode *lr_adj_node =
    1076           0 :                 agent()->config_manager()->FindAdjacentIFMapNode(adj_node,
    1077             :                                                                  "logical-router");
    1078           0 :             if (lr_adj_node) {
    1079           0 :                 lr = dynamic_cast<autogen::LogicalRouter *>(lr_adj_node->
    1080           0 :                                                             GetObject());
    1081             :             }
    1082             : 
    1083           0 :             if (lr_vn_node && lr) {
    1084           0 :                 autogen::IdPermsType id_perms = lr->id_perms();
    1085           0 :                 CfgUuidSet(id_perms.uuid.uuid_mslong,
    1086             :                            id_perms.uuid.uuid_lslong,
    1087             :                            logical_router_uuid);
    1088             :                 autogen::LogicalRouterVirtualNetworkType data =
    1089           0 :                     lr_vn_node->data();
    1090           0 :                 if (data.logical_router_virtual_network_type ==
    1091             :                     "InternalVirtualNetwork")
    1092             :                 {
    1093           0 :                     vxlan_routing_vn = true;
    1094             :                 }
    1095           0 :             }
    1096             :         }
    1097             : 
    1098           0 :         if (adj_node->table() ==
    1099           0 :                             agent()->cfg()->cfg_multicast_policy_table()) {
    1100             :             MulticastPolicy *mcast_group = static_cast<MulticastPolicy *>
    1101           0 :                             (adj_node->GetObject());
    1102           0 :             assert(mcast_group);
    1103           0 :             autogen::IdPermsType id_perms = mcast_group->id_perms();
    1104           0 :             CfgUuidSet(id_perms.uuid.uuid_mslong, id_perms.uuid.uuid_lslong,
    1105             :                            mp_uuid);
    1106           0 :             mp_list.push_back(mp_uuid);
    1107           0 :         }
    1108             : 
    1109           0 :         if (adj_node->table() ==
    1110           0 :                             agent()->cfg()->cfg_health_check_table()) {
    1111             :             autogen::ServiceHealthCheck *hc =
    1112           0 :                 static_cast<autogen::ServiceHealthCheck *> (adj_node->GetObject());
    1113           0 :             assert(hc);
    1114           0 :             if (hc->properties().health_check_type.find("vn-ip-list") == std::string::npos)
    1115           0 :                 continue;
    1116           0 :             autogen::IdPermsType id_perms = hc->id_perms();
    1117           0 :             CfgUuidSet(id_perms.uuid.uuid_mslong, id_perms.uuid.uuid_lslong,
    1118             :                        health_check_uuid);
    1119           0 :         }
    1120             :     }
    1121             : 
    1122           0 :     uuid mirror_acl_uuid = agent()->mirror_cfg_table()->GetMirrorUuid(node->name());
    1123           0 :     std::sort(vn_ipam.begin(), vn_ipam.end());
    1124             : 
    1125             :     // Fetch VN forwarding Properties
    1126             :     bool enable_rpf;
    1127             :     bool flood_unknown_unicast;
    1128             :     bool mirror_destination;
    1129           0 :     bool pbb_evpn_enable = cfg->pbb_evpn_enable();
    1130           0 :     bool pbb_etree_enable = cfg->pbb_etree_enable();
    1131           0 :     bool layer2_control_word = cfg->layer2_control_word();
    1132           0 :     bool cfg_igmp_enable = cfg->igmp_enable();
    1133           0 :     uint32_t vn_max_flows = cfg->properties().max_flows;
    1134           0 :     bool mac_ip_learning_enable = cfg->mac_ip_learning_enable();
    1135             :     Agent::ForwardingMode forwarding_mode;
    1136           0 :     CfgForwardingFlags(node, &enable_rpf, &flood_unknown_unicast,
    1137             :                        &forwarding_mode, &mirror_destination);
    1138           0 :     return new VnData(agent(), node, node->name(), acl_uuid, vrf_name,
    1139             :                       mirror_acl_uuid, mirror_cfg_acl_uuid, vn_ipam,
    1140           0 :                       vn_ipam_data, cfg->properties().vxlan_network_identifier,
    1141           0 :                       GetCfgVnId(cfg), cfg->id_perms().enable, enable_rpf,
    1142             :                       flood_unknown_unicast, forwarding_mode,
    1143             :                       qos_config_uuid, mirror_destination, pbb_etree_enable,
    1144             :                       pbb_evpn_enable, layer2_control_word, slo_list,
    1145             :                       underlay_forwarding, vxlan_routing_vn,
    1146             :                       logical_router_uuid, mp_list, cfg_igmp_enable,
    1147             :                       vn_max_flows, mac_ip_learning_enable,
    1148           0 :                       health_check_uuid);
    1149           0 : }
    1150             : 
    1151           0 : bool VnTable::IFNodeToUuid(IFMapNode *node, boost::uuids::uuid &u) {
    1152           0 :     VirtualNetwork *cfg = static_cast <VirtualNetwork *> (node->GetObject());
    1153           0 :     assert(cfg);
    1154           0 :     autogen::IdPermsType id_perms = cfg->id_perms();
    1155           0 :     CfgUuidSet(id_perms.uuid.uuid_mslong, id_perms.uuid.uuid_lslong, u);
    1156           0 :     return true;
    1157           0 : }
    1158             : 
    1159           0 : bool VnTable::IFNodeToReq(IFMapNode *node, DBRequest &req,
    1160             :         const boost::uuids::uuid &u) {
    1161             : 
    1162           0 :     assert(!u.is_nil());
    1163             : 
    1164           0 :     if ((req.oper == DBRequest::DB_ENTRY_DELETE) || node->IsDeleted()) {
    1165           0 :         req.key.reset(new VnKey(u));
    1166           0 :         req.oper = DBRequest::DB_ENTRY_DELETE;
    1167           0 :         Enqueue(&req);
    1168           0 :         return false;
    1169             :     }
    1170             : 
    1171           0 :     agent()->config_manager()->AddVnNode(node);
    1172           0 :     return false;
    1173             : }
    1174             : 
    1175           0 : bool VnTable::ProcessConfig(IFMapNode *node, DBRequest &req,
    1176             :         const boost::uuids::uuid &u) {
    1177             : 
    1178           0 :     if (node->IsDeleted()) {
    1179           0 :         return false;
    1180             :     }
    1181             : 
    1182           0 :     req.oper = DBRequest::DB_ENTRY_ADD_CHANGE;
    1183           0 :     req.key.reset(new VnKey(u));
    1184           0 :     req.data.reset(BuildData(node));
    1185           0 :     Enqueue(&req);
    1186           0 :     return false;
    1187             : }
    1188             : 
    1189           0 : void VnTable::AddVn(const boost::uuids::uuid &vn_uuid, const string &name,
    1190             :                     const boost::uuids::uuid &acl_id, const string &vrf_name,
    1191             :                     const std::vector<VnIpam> &ipam,
    1192             :                     const VnData::VnIpamDataMap &vn_ipam_data, int vn_id,
    1193             :                     int vxlan_id, bool admin_state, bool enable_rpf,
    1194             :                     bool flood_unknown_unicast, bool pbb_etree_enable,
    1195             :                     bool pbb_evpn_enable, bool layer2_control_word) {
    1196             :     using boost::uuids::nil_uuid;
    1197             : 
    1198           0 :     DBRequest req(DBRequest::DB_ENTRY_ADD_CHANGE);
    1199           0 :     UuidList empty_list;
    1200           0 :     req.key.reset(new VnKey(vn_uuid));
    1201           0 :     bool mirror_destination = false;
    1202           0 :     VnData *data = new VnData(agent(), NULL, name, acl_id, vrf_name, nil_uuid(),
    1203           0 :                               nil_uuid(), ipam, vn_ipam_data,
    1204             :                               vxlan_id, vn_id, admin_state, enable_rpf,
    1205           0 :                               flood_unknown_unicast, Agent::NONE, nil_uuid(),
    1206             :                               mirror_destination, pbb_etree_enable,
    1207             :                               pbb_evpn_enable, layer2_control_word, empty_list,
    1208           0 :                               false, false, nil_uuid(), empty_list, false, 0,
    1209           0 :                               false, nil_uuid());
    1210             : 
    1211           0 :     req.data.reset(data);
    1212           0 :     Enqueue(&req);
    1213           0 : }
    1214             : 
    1215           0 : void VnTable::DelVn(const boost::uuids::uuid &vn_uuid) {
    1216           0 :     DBRequest req(DBRequest::DB_ENTRY_DELETE);
    1217           0 :     req.key.reset(new VnKey(vn_uuid));
    1218           0 :     req.data.reset(NULL);
    1219           0 :     Enqueue(&req);
    1220           0 : }
    1221             : 
    1222           0 : void VnTable::ResyncReq(const boost::uuids::uuid &vn) {
    1223           0 :     DBRequest req(DBRequest::DB_ENTRY_ADD_CHANGE);
    1224           0 :     VnKey *key = new VnKey(vn);
    1225           0 :     key->sub_op_ = AgentKey::RESYNC;
    1226           0 :     req.key.reset(key);
    1227           0 :     req.data.reset(NULL);
    1228           0 :     Enqueue(&req);
    1229           0 : }
    1230             : 
    1231             : /////////////////////////////////////////////////////////////////////////////
    1232             : // Introspect routines
    1233             : /////////////////////////////////////////////////////////////////////////////
    1234           0 : bool VnEntry::DBEntrySandesh(Sandesh *sresp, std::string &name)  const {
    1235           0 :     VnListResp *resp = static_cast<VnListResp *>(sresp);
    1236             : 
    1237           0 :     VnSandeshData data;
    1238           0 :     data.set_name(GetName());
    1239           0 :     data.set_uuid(UuidToString(GetUuid()));
    1240           0 :     data.set_vxlan_id(GetVxLanId());
    1241           0 :     data.set_config_vxlan_id(vxlan_id_);
    1242           0 :     data.set_vn_id(vnid_);
    1243           0 :     if (GetAcl()) {
    1244           0 :         data.set_acl_uuid(UuidToString(GetAcl()->GetUuid()));
    1245             :     } else {
    1246           0 :         data.set_acl_uuid("");
    1247             :     }
    1248             : 
    1249           0 :     if (GetVrf()) {
    1250           0 :         data.set_vrf_name(GetVrf()->GetName());
    1251             :     } else {
    1252           0 :         data.set_vrf_name("");
    1253             :     }
    1254             : 
    1255           0 :     if (GetMirrorAcl()) {
    1256           0 :         data.set_mirror_acl_uuid(UuidToString(GetMirrorAcl()->GetUuid()));
    1257             :     } else {
    1258           0 :         data.set_mirror_acl_uuid("");
    1259             :     }
    1260             : 
    1261           0 :     if (GetMirrorCfgAcl()) {
    1262           0 :         data.set_mirror_cfg_acl_uuid(UuidToString(GetMirrorCfgAcl()->GetUuid()));
    1263             :     } else {
    1264           0 :         data.set_mirror_cfg_acl_uuid("");
    1265             :     }
    1266             : 
    1267           0 :     std::vector<VnIpamData> vn_subnet_sandesh_list;
    1268           0 :     const std::vector<VnIpam> &vn_ipam = GetVnIpam();
    1269           0 :     for (unsigned int i = 0; i < vn_ipam.size(); ++i) {
    1270           0 :         VnIpamData entry;
    1271           0 :         entry.set_ip_prefix(vn_ipam[i].ip_prefix.to_string());
    1272           0 :         entry.set_prefix_len(vn_ipam[i].plen);
    1273           0 :         entry.set_gateway(vn_ipam[i].default_gw.to_string());
    1274           0 :         entry.set_ipam_name(vn_ipam[i].ipam_name);
    1275           0 :         entry.set_dhcp_enable(vn_ipam[i].dhcp_enable ? "true" : "false");
    1276           0 :         entry.set_dhcp_enable_v6(vn_ipam[i].dhcp_enable_v6 ? "true" : "false");
    1277           0 :         entry.set_dns_server(vn_ipam[i].dns_server.to_string());
    1278           0 :         vn_subnet_sandesh_list.push_back(entry);
    1279           0 :     }
    1280           0 :     data.set_ipam_data(vn_subnet_sandesh_list);
    1281             : 
    1282           0 :     std::vector<VnIpamHostRoutes> vn_ipam_host_routes_list;
    1283           0 :     for (VnData::VnIpamDataMap::const_iterator it = vn_ipam_data_.begin();
    1284           0 :         it != vn_ipam_data_.end(); ++it) {
    1285           0 :         VnIpamHostRoutes vn_ipam_host_routes;
    1286           0 :         vn_ipam_host_routes.ipam_name = it->first;
    1287             :         const std::vector<OperDhcpOptions::HostRoute> &host_routes =
    1288           0 :             it->second.oper_dhcp_options_.host_routes();
    1289           0 :         for (uint32_t i = 0; i < host_routes.size(); ++i) {
    1290           0 :             vn_ipam_host_routes.host_routes.push_back(
    1291           0 :                 host_routes[i].ToString());
    1292             :         }
    1293           0 :         vn_ipam_host_routes_list.push_back(vn_ipam_host_routes);
    1294           0 :     }
    1295           0 :     data.set_ipam_host_routes(vn_ipam_host_routes_list);
    1296           0 :     data.set_ipv4_forwarding(layer3_forwarding());
    1297           0 :     data.set_layer2_forwarding(bridging());
    1298           0 :     data.set_bridging(bridging());
    1299           0 :     data.set_admin_state(admin_state());
    1300           0 :     data.set_enable_rpf(enable_rpf());
    1301           0 :     data.set_flood_unknown_unicast(flood_unknown_unicast());
    1302           0 :     data.set_pbb_etree_enabled(pbb_etree_enable());
    1303           0 :     data.set_layer2_control_word(layer2_control_word());
    1304           0 :     std::vector<SecurityLoggingObjectLink> slo_list;
    1305           0 :     UuidList::const_iterator sit = slo_list_.begin();
    1306           0 :     while (sit != slo_list_.end()) {
    1307           0 :         SecurityLoggingObjectLink slo_entry;
    1308           0 :         slo_entry.set_slo_uuid(to_string(*sit));
    1309           0 :         slo_list.push_back(slo_entry);
    1310           0 :         ++sit;
    1311           0 :     }
    1312           0 :     data.set_slo_list(slo_list);
    1313             :     std::vector<VnSandeshData> &list =
    1314           0 :         const_cast<std::vector<VnSandeshData>&>(resp->get_vn_list());
    1315           0 :     std::vector<MulticastPolicyLink> mp_list;
    1316           0 :     UuidList::const_iterator mpit = mp_list_.begin();
    1317           0 :     while (mpit != mp_list_.end()) {
    1318           0 :         MulticastPolicyLink mp_entry;
    1319           0 :         mp_entry.set_mp_uuid(to_string(*mpit));
    1320           0 :         mp_list.push_back(mp_entry);
    1321           0 :         ++mpit;
    1322           0 :     }
    1323           0 :     data.set_mp_list(mp_list);
    1324           0 :     data.set_cfg_igmp_enable(cfg_igmp_enable());
    1325           0 :     data.set_max_flows(vn_max_flows());
    1326           0 :     data.set_mac_ip_learning_enable(mac_ip_learning_enable());
    1327           0 :     data.set_health_check_uuid(to_string(health_check_uuid()));
    1328           0 :     data.set_logical_router_uuid(UuidToString(logical_router_uuid()));
    1329           0 :     data.set_vxlan_routing_vn(vxlan_routing_vn());
    1330             : 
    1331           0 :     list.push_back(data);
    1332           0 :     return true;
    1333           0 : }
    1334             : 
    1335           0 : void VnEntry::SendObjectLog(SandeshTraceBufferPtr buf,
    1336             :                             AgentLogEvent::type event) const {
    1337           0 :     VnObjectLogInfo info;
    1338           0 :     string str;
    1339           0 :     string vn_uuid = UuidToString(GetUuid());
    1340           0 :     const AclDBEntry *acl = GetAcl();
    1341           0 :     const AclDBEntry *mirror_acl = GetMirrorAcl();
    1342           0 :     const AclDBEntry *mirror_cfg_acl = GetMirrorCfgAcl();
    1343           0 :     string acl_uuid;
    1344           0 :     string mirror_acl_uuid;
    1345           0 :     string mirror_cfg_acl_uuid;
    1346             : 
    1347           0 :     info.set_uuid(vn_uuid);
    1348           0 :     info.set_name(GetName());
    1349           0 :     switch (event) {
    1350           0 :         case AgentLogEvent::ADD:
    1351           0 :             str.assign("Addition ");
    1352           0 :             break;
    1353           0 :         case AgentLogEvent::DEL:
    1354           0 :             str.assign("Deletion ");
    1355           0 :             info.set_event(str);
    1356           0 :             VN_OBJECT_LOG_LOG("AgentVn", SandeshLevel::SYS_INFO, info);
    1357           0 :             return;
    1358           0 :         case AgentLogEvent::CHANGE:
    1359           0 :             str.assign("Modification ");
    1360           0 :             break;
    1361           0 :         default:
    1362           0 :             str.assign("");
    1363           0 :             break;
    1364             :     }
    1365             : 
    1366           0 :     info.set_event(str);
    1367           0 :     if (acl) {
    1368           0 :         acl_uuid.assign(UuidToString(acl->GetUuid()));
    1369           0 :         info.set_acl_uuid(acl_uuid);
    1370             :     }
    1371           0 :     if (mirror_acl) {
    1372           0 :         mirror_acl_uuid.assign(UuidToString(mirror_acl->GetUuid()));
    1373           0 :         info.set_mirror_acl_uuid(mirror_acl_uuid);
    1374             :     }
    1375           0 :     if (mirror_cfg_acl) {
    1376           0 :         mirror_cfg_acl_uuid.assign(UuidToString(mirror_cfg_acl->GetUuid()));
    1377           0 :         info.set_mirror_cfg_acl_uuid(mirror_cfg_acl_uuid);
    1378             :     }
    1379           0 :     VrfEntry *vrf = GetVrf();
    1380           0 :     if (vrf) {
    1381           0 :         info.set_vrf(vrf->GetName());
    1382             :     }
    1383           0 :     vector<VnObjectLogIpam> ipam_list;
    1384           0 :     VnObjectLogIpam sandesh_ipam;
    1385           0 :     vector<VnIpam>::const_iterator it = ipam_.begin();
    1386           0 :     while (it != ipam_.end()) {
    1387           0 :         VnIpam ipam = *it;
    1388           0 :         sandesh_ipam.set_ip_prefix(ipam.ip_prefix.to_string());
    1389           0 :         sandesh_ipam.set_prefix_len(ipam.plen);
    1390           0 :         sandesh_ipam.set_gateway_ip(ipam.default_gw.to_string());
    1391           0 :         sandesh_ipam.set_ipam_name(ipam.ipam_name);
    1392           0 :         sandesh_ipam.set_dhcp_enable(ipam.dhcp_enable ? "true" : "false");
    1393           0 :         sandesh_ipam.set_dhcp_enable_v6(ipam.dhcp_enable_v6 ? "true" : "false");
    1394           0 :         sandesh_ipam.set_dns_server(ipam.dns_server.to_string());
    1395           0 :         ipam_list.push_back(sandesh_ipam);
    1396           0 :         ++it;
    1397           0 :     }
    1398             : 
    1399           0 :     if (ipam_list.size()) {
    1400           0 :         info.set_ipam_list(ipam_list);
    1401             :     }
    1402           0 :     info.set_bridging(bridging());
    1403           0 :     info.set_oper_vxlan_id(GetOperVxlanId());
    1404           0 :     info.set_ipv4_forwarding(layer3_forwarding());
    1405           0 :     info.set_admin_state(admin_state());
    1406           0 :     info.set_logical_router_uuid(UuidToString(logical_router_uuid()));
    1407           0 :     info.set_vxlan_routing_vn(vxlan_routing_vn());
    1408           0 :     VN_OBJECT_LOG_LOG("AgentVn", SandeshLevel::SYS_INFO, info);
    1409           0 :     VN_OBJECT_TRACE_TRACE(buf, info);
    1410           0 : }
    1411             : 
    1412           0 : void VnListReq::HandleRequest() const {
    1413           0 :     AgentSandeshPtr sand(new AgentVnSandesh(context(), get_name(), get_uuid(),
    1414           0 :                                             get_vxlan_id(), get_ipam_name()));
    1415           0 :     sand->DoSandesh(sand);
    1416           0 : }
    1417             : 
    1418           0 : AgentSandeshPtr VnTable::GetAgentSandesh(const AgentSandeshArguments *args,
    1419             :                                          const std::string &context) {
    1420             :     return AgentSandeshPtr
    1421           0 :         (new AgentVnSandesh(context, args->GetString("name"),
    1422           0 :                             args->GetString("uuid"),
    1423           0 :                             args->GetString("vxlan_id"),
    1424           0 :                             args->GetString("ipam_name")));
    1425             : }
    1426             : 
    1427             : /////////////////////////////////////////////////////////////////////////////
    1428             : // DomainConfig routines
    1429             : /////////////////////////////////////////////////////////////////////////////
    1430           0 : DomainConfig::DomainConfig(Agent *agent) {
    1431           0 : }
    1432             : 
    1433           0 : DomainConfig::~DomainConfig() {
    1434           0 : }
    1435             : 
    1436           0 : void DomainConfig::Init() {
    1437           0 : }
    1438             : 
    1439           0 : void DomainConfig::Terminate() {
    1440           0 : }
    1441             : 
    1442           0 : void DomainConfig::RegisterIpamCb(Callback cb) {
    1443           0 :     ipam_callback_.push_back(cb);
    1444           0 : }
    1445             : 
    1446           0 : void DomainConfig::RegisterVdnsCb(Callback cb) {
    1447           0 :     vdns_callback_.push_back(cb);
    1448           0 : }
    1449             : 
    1450             : // Callback is invoked only if there is change in IPAM properties.
    1451             : // In case of change in a link with IPAM, callback is not invoked.
    1452           0 : void DomainConfig::IpamDelete(IFMapNode *node) {
    1453           0 :     CallIpamCb(node);
    1454           0 :     ipam_config_.erase(node->name());
    1455           0 :     return;
    1456             : }
    1457             : 
    1458           0 : void DomainConfig::IpamAddChange(IFMapNode *node) {
    1459             :     autogen::NetworkIpam *network_ipam =
    1460           0 :         static_cast <autogen::NetworkIpam *> (node->GetObject());
    1461           0 :     assert(network_ipam);
    1462             : 
    1463           0 :     bool change = false;
    1464           0 :     IpamDomainConfigMap::iterator it = ipam_config_.find(node->name());
    1465           0 :     if (it != ipam_config_.end()) {
    1466           0 :         if (IpamChanged(it->second, network_ipam->mgmt())) {
    1467           0 :             it->second = network_ipam->mgmt();
    1468           0 :             change = true;
    1469             :         }
    1470             :     } else {
    1471           0 :         ipam_config_.insert(IpamDomainConfigPair(node->name(),
    1472           0 :                                                  network_ipam->mgmt()));
    1473           0 :         change = true;
    1474             :     }
    1475           0 :     if (change)
    1476           0 :         CallIpamCb(node);
    1477           0 : }
    1478             : 
    1479           0 : void DomainConfig::VDnsDelete(IFMapNode *node) {
    1480           0 :     CallVdnsCb(node);
    1481           0 :     vdns_config_.erase(node->name());
    1482           0 :     return;
    1483             : }
    1484             : 
    1485           0 : void DomainConfig::VDnsAddChange(IFMapNode *node) {
    1486             :     autogen::VirtualDns *virtual_dns =
    1487           0 :         static_cast <autogen::VirtualDns *> (node->GetObject());
    1488           0 :     assert(virtual_dns);
    1489             : 
    1490           0 :     VdnsDomainConfigMap::iterator it = vdns_config_.find(node->name());
    1491           0 :     if (it != vdns_config_.end()) {
    1492           0 :         it->second = virtual_dns->data();
    1493             :     } else {
    1494           0 :         vdns_config_.insert(VdnsDomainConfigPair(node->name(),
    1495           0 :                                                  virtual_dns->data()));
    1496             :     }
    1497           0 :     CallVdnsCb(node);
    1498           0 : }
    1499             : 
    1500           0 : void DomainConfig::CallIpamCb(IFMapNode *node) {
    1501           0 :     for (unsigned int i = 0; i < ipam_callback_.size(); ++i) {
    1502           0 :         ipam_callback_[i](node);
    1503             :     }
    1504           0 : }
    1505             : 
    1506           0 : void DomainConfig::CallVdnsCb(IFMapNode *node) {
    1507           0 :     for (unsigned int i = 0; i < vdns_callback_.size(); ++i) {
    1508           0 :         vdns_callback_[i](node);
    1509             :     }
    1510           0 : }
    1511             : 
    1512           0 : bool DomainConfig::IpamChanged(const autogen::IpamType &old,
    1513             :                                const autogen::IpamType &cur) const {
    1514           0 :     if (old.ipam_method != cur.ipam_method ||
    1515           0 :         old.ipam_dns_method != cur.ipam_dns_method)
    1516           0 :         return true;
    1517             : 
    1518           0 :     if ((old.ipam_dns_server.virtual_dns_server_name !=
    1519           0 :          cur.ipam_dns_server.virtual_dns_server_name) ||
    1520           0 :         (old.ipam_dns_server.tenant_dns_server_address.ip_address !=
    1521           0 :          cur.ipam_dns_server.tenant_dns_server_address.ip_address))
    1522           0 :         return true;
    1523             : 
    1524           0 :     if (old.cidr_block.ip_prefix != cur.cidr_block.ip_prefix ||
    1525           0 :         old.cidr_block.ip_prefix_len != cur.cidr_block.ip_prefix_len)
    1526           0 :         return true;
    1527             : 
    1528           0 :     if (old.dhcp_option_list.dhcp_option.size() !=
    1529           0 :         cur.dhcp_option_list.dhcp_option.size())
    1530           0 :         return true;
    1531             : 
    1532           0 :     for (uint32_t i = 0; i < old.dhcp_option_list.dhcp_option.size(); i++) {
    1533           0 :         if ((old.dhcp_option_list.dhcp_option[i].dhcp_option_name !=
    1534           0 :              cur.dhcp_option_list.dhcp_option[i].dhcp_option_name) ||
    1535           0 :             (old.dhcp_option_list.dhcp_option[i].dhcp_option_value !=
    1536           0 :              cur.dhcp_option_list.dhcp_option[i].dhcp_option_value) ||
    1537           0 :             (old.dhcp_option_list.dhcp_option[i].dhcp_option_value_bytes !=
    1538           0 :              cur.dhcp_option_list.dhcp_option[i].dhcp_option_value_bytes))
    1539           0 :             return true;
    1540             :     }
    1541             : 
    1542           0 :     if (old.host_routes.route.size() != cur.host_routes.route.size())
    1543           0 :         return true;
    1544             : 
    1545           0 :     for (uint32_t i = 0; i < old.host_routes.route.size(); i++) {
    1546           0 :         if ((old.host_routes.route[i].prefix !=
    1547           0 :              cur.host_routes.route[i].prefix) ||
    1548           0 :             (old.host_routes.route[i].next_hop !=
    1549           0 :              cur.host_routes.route[i].next_hop) ||
    1550           0 :             (old.host_routes.route[i].next_hop_type !=
    1551           0 :              cur.host_routes.route[i].next_hop_type) ||
    1552           0 :             (old.host_routes.route[i].community_attributes.community_attribute !=
    1553           0 :              cur.host_routes.route[i].community_attributes.community_attribute))
    1554           0 :             return true;
    1555             :     }
    1556             : 
    1557           0 :     return false;
    1558             : }
    1559             : 
    1560           0 : bool DomainConfig::GetIpam(const std::string &name, autogen::IpamType *ipam) {
    1561           0 :     IpamDomainConfigMap::iterator it = ipam_config_.find(name);
    1562           0 :     if (it == ipam_config_.end())
    1563           0 :         return false;
    1564           0 :     *ipam = it->second;
    1565           0 :     return true;
    1566             : }
    1567             : 
    1568           0 : bool DomainConfig::GetVDns(const std::string &vdns,
    1569             :                            autogen::VirtualDnsType *vdns_type) {
    1570           0 :     VdnsDomainConfigMap::iterator it = vdns_config_.find(vdns);
    1571           0 :     if (it == vdns_config_.end())
    1572           0 :         return false;
    1573           0 :     *vdns_type = it->second;
    1574           0 :     return true;
    1575             : }
    1576             : 
    1577             : /////////////////////////////////////////////////////////////////////////////
    1578             : // OperNetworkIpam routines
    1579             : /////////////////////////////////////////////////////////////////////////////
    1580           0 : OperNetworkIpam::OperNetworkIpam(Agent *agent, DomainConfig *domain_config) :
    1581           0 :     OperIFMapTable(agent), domain_config_(domain_config) {
    1582           0 : }
    1583             : 
    1584           0 : OperNetworkIpam::~OperNetworkIpam() {
    1585           0 : }
    1586             : 
    1587           0 : void OperNetworkIpam::ConfigDelete(IFMapNode *node) {
    1588           0 :     domain_config_->IpamDelete(node);
    1589           0 : }
    1590             : 
    1591           0 : void OperNetworkIpam::ConfigAddChange(IFMapNode *node) {
    1592           0 :     domain_config_->IpamAddChange(node);
    1593           0 : }
    1594             : 
    1595           0 : void OperNetworkIpam::ConfigManagerEnqueue(IFMapNode *node) {
    1596           0 :     agent()->config_manager()->AddNetworkIpamNode(node);
    1597           0 : }
    1598             : 
    1599           0 : OperVirtualDns::OperVirtualDns(Agent *agent, DomainConfig *domain_config) :
    1600           0 :     OperIFMapTable(agent), domain_config_(domain_config) {
    1601           0 : }
    1602             : 
    1603           0 : OperVirtualDns::~OperVirtualDns() {
    1604           0 : }
    1605             : 
    1606           0 : void OperVirtualDns::ConfigDelete(IFMapNode *node) {
    1607           0 :     domain_config_->VDnsDelete(node);
    1608           0 : }
    1609             : 
    1610           0 : void OperVirtualDns::ConfigAddChange(IFMapNode *node) {
    1611           0 :     domain_config_->VDnsAddChange(node);
    1612           0 : }
    1613             : 
    1614           0 : void OperVirtualDns::ConfigManagerEnqueue(IFMapNode *node) {
    1615           0 :     agent()->config_manager()->AddVirtualDnsNode(node);
    1616           0 : }

Generated by: LCOV version 1.14