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: 602 988 60.9 %
Date: 2026-06-04 02:06:09 Functions: 74 99 74.7 %
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         116 : 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         116 :                uint32_t alloc)
      53         116 :         : plen(len), installed(false), dhcp_enable(dhcp), dhcp_enable_v6(dhcp), ipam_name(name),
      54         232 :           alloc_unit(alloc) {
      55         116 :     boost::system::error_code ec;
      56         116 :     ip_prefix = IpAddress::from_string(ip, ec);
      57         116 :     default_gw = IpAddress::from_string(gw, ec);
      58         116 :     dns_server = IpAddress::from_string(dns, ec);
      59         116 :     oper_dhcp_options.set_options(dhcp_options);
      60         116 :     oper_dhcp_options.set_host_routes(host_routes);
      61         116 : }
      62             : 
      63          34 : IpAddress VnIpam::GetSubnetAddress() const {
      64          34 :     if (ip_prefix.is_v4()) {
      65          34 :         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         751 : bool VnIpam::IsSubnetMember(const IpAddress &ip) const {
      74         751 :     if (ip_prefix.is_v4() && ip.is_v4()) {
      75         536 :         return ((ip_prefix.to_v4().to_ulong() |
      76         536 :                  ~(0xFFFFFFFF << (32 - plen))) ==
      77         536 :                 (ip.to_v4().to_ulong() | ~(0xFFFFFFFF << (32 - plen))));
      78         215 :     } else if (ip_prefix.is_v6() && ip.is_v6()) {
      79           0 :         return IsIp6SubnetMember(ip.to_v6(), ip_prefix.to_v6(), plen);
      80             :     }
      81         215 :     return false;
      82             : }
      83             : 
      84             : /////////////////////////////////////////////////////////////////////////////
      85             : // VnEntry routines
      86             : /////////////////////////////////////////////////////////////////////////////
      87         607 : VnEntry::VnEntry(Agent *agent, boost::uuids::uuid id) :
      88         607 :     AgentOperDBEntry(), agent_(agent), uuid_(id), vrf_(NULL, this),
      89         607 :     vxlan_id_(0), vnid_(0), active_vxlan_id_(0), bridging_(true),
      90        1214 :     layer3_forwarding_(true), admin_state_(true), table_label_(0),
      91         607 :     enable_rpf_(true), flood_unknown_unicast_(false),
      92        1214 :     forwarding_mode_(Agent::L2_L3), mirror_destination_(false),
      93         607 :     underlay_forwarding_(false), vxlan_routing_vn_(false),
      94        1214 :     logical_router_uuid_(), cfg_igmp_enable_(false), vn_max_flows_(0),
      95        1214 :     lr_vrf_(NULL, this) {
      96         607 : }
      97             : 
      98        1214 : VnEntry::~VnEntry() {
      99        1214 : }
     100             : 
     101        1259 : bool VnEntry::IsLess(const DBEntry &rhs) const {
     102        1259 :     const VnEntry &a = static_cast<const VnEntry &>(rhs);
     103        1259 :     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         116 : bool VnEntry::ChangeHandler(Agent *agent, const DBRequest *req) {
     134         116 :     bool ret = false;
     135         116 :     VnData *data = static_cast<VnData *>(req->data.get());
     136             : 
     137         116 :     AclKey key(data->acl_id_);
     138         116 :     AclDBEntry *acl = static_cast<AclDBEntry *>
     139         116 :         (agent->acl_table()->FindActiveEntry(&key));
     140         116 :     if (acl_.get() != acl) {
     141           0 :         acl_ = acl;
     142           0 :         ret = true;
     143             :     }
     144             : 
     145         116 :     AclKey mirror_key(data->mirror_acl_id_);
     146         116 :     AclDBEntry *mirror_acl = static_cast<AclDBEntry *>
     147         116 :         (agent->acl_table()->FindActiveEntry(&mirror_key));
     148         116 :     if (mirror_acl_.get() != mirror_acl) {
     149           0 :         mirror_acl_ = mirror_acl;
     150           0 :         ret = true;
     151             :     }
     152             : 
     153         116 :     AclKey mirror_cfg_acl_key(data->mirror_cfg_acl_id_);
     154         116 :     AclDBEntry *mirror_cfg_acl = static_cast<AclDBEntry *>
     155         116 :          (agent->acl_table()->FindActiveEntry(&mirror_cfg_acl_key));
     156         116 :     if (mirror_cfg_acl_.get() != mirror_cfg_acl) {
     157           0 :         mirror_cfg_acl_ = mirror_cfg_acl;
     158           0 :         ret = true;
     159             :     }
     160             : 
     161         116 :     AgentQosConfigKey qos_config_key(data->qos_config_uuid_);
     162         116 :     AgentQosConfig *qos_config = static_cast<AgentQosConfig *>
     163         116 :         (agent->qos_config_table()->FindActiveEntry(&qos_config_key));
     164         116 :     if (qos_config_.get() != qos_config) {
     165           0 :         qos_config_ = qos_config;
     166           0 :         ret = true;
     167             :     }
     168             : 
     169         116 :     VrfKey vrf_key(data->vrf_name_);
     170         116 :     VrfEntry *vrf = static_cast<VrfEntry *>
     171         116 :         (agent->vrf_table()->FindActiveEntry(&vrf_key));
     172         116 :     VrfEntryRef old_vrf = vrf_;
     173         116 :     bool update_vxlan_state = false;
     174         116 :     if (vrf != old_vrf.get()) {
     175          20 :         if (!vrf) {
     176           3 :             ApplyAllIpam(agent, old_vrf.get(), true);
     177             :         }
     178          20 :         vrf_ = vrf;
     179          20 :         update_vxlan_state = true;
     180          20 :         ret = true;
     181             :     }
     182             : 
     183         116 :     if (admin_state_ != data->admin_state_) {
     184           0 :         admin_state_ = data->admin_state_;
     185           0 :         ret = true;
     186             :     }
     187             : 
     188         116 :     if (forwarding_mode_ != data->forwarding_mode_) {
     189          20 :         forwarding_mode_ = data->forwarding_mode_;
     190          20 :         ret = true;
     191             :     }
     192             : 
     193             :     // Recompute the forwarding modes in VN
     194             :     // Must rebake the routes if any change in forwarding modes
     195         116 :     bool resync_routes = false;
     196         116 :     resync_routes = UpdateForwardingMode(agent);
     197         116 :     ret |= resync_routes;
     198             : 
     199             :     // Update the routes derived from IPAM
     200         116 :     ret |= UpdateIpam(agent, data->ipam_);
     201             : 
     202         116 :     if (vn_ipam_data_ != data->vn_ipam_data_) {
     203          20 :         vn_ipam_data_ = data->vn_ipam_data_;
     204          20 :         ret = true;
     205             :     }
     206             : 
     207         116 :     if (enable_rpf_ != data->enable_rpf_) {
     208           0 :         enable_rpf_ = data->enable_rpf_;
     209           0 :         ret = true;
     210             :     }
     211             : 
     212         116 :     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         116 :     if (vxlan_id_ != data->vxlan_id_) {
     219          18 :         vxlan_id_ = data->vxlan_id_;
     220          18 :         ret = true;
     221          18 :         if ((agent->vxlan_network_identifier_mode() == Agent::CONFIGURED)  || vxlan_routing_vn_ ) {
     222           0 :             update_vxlan_state = true;
     223             :         }
     224             :     }
     225             : 
     226         116 :     if (vnid_ != data->vnid_) {
     227          18 :         vnid_ = data->vnid_;
     228          18 :         ret = true;
     229          18 :         if (agent->vxlan_network_identifier_mode() == Agent::AUTOMATIC) {
     230          18 :             update_vxlan_state = true;
     231             :         }
     232             :     }
     233             : 
     234         116 :     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         116 :     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         116 :     if (update_vxlan_state) {
     247          38 :         ret |= UpdateVxlan(agent, false);
     248             :     }
     249             : 
     250         116 :     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         116 :     if (pbb_evpn_enable_ != data->pbb_evpn_enable_) {
     259           7 :         pbb_evpn_enable_ = data->pbb_evpn_enable_;
     260           7 :         ret = true;
     261             :     }
     262             : 
     263         116 :     if (pbb_etree_enable_ != data->pbb_etree_enable_) {
     264           7 :         pbb_etree_enable_ = data->pbb_etree_enable_;
     265           7 :         ret = true;
     266             :     }
     267             : 
     268         116 :     if (layer2_control_word_ != data->layer2_control_word_) {
     269           7 :         layer2_control_word_ = data->layer2_control_word_;
     270           7 :         ret = true;
     271             :     }
     272             : 
     273         116 :     if (underlay_forwarding_ != data->underlay_forwarding_) {
     274           0 :         underlay_forwarding_ = data->underlay_forwarding_;
     275           0 :         ret = true;
     276             :     }
     277             : 
     278         116 :     if (slo_list_ != data->slo_list_) {
     279           0 :         slo_list_ = data->slo_list_;
     280             :     }
     281             : 
     282         116 :     if (logical_router_uuid_ != data->logical_router_uuid_) {
     283           0 :         logical_router_uuid_ = data->logical_router_uuid_;
     284           0 :         ret = true;
     285             :     }
     286             : 
     287         116 :     if (mp_list_ != data->mp_list_) {
     288           0 :         mp_list_ = data->mp_list_;
     289             :     }
     290             : 
     291         116 :     if (cfg_igmp_enable_ != data->cfg_igmp_enable_) {
     292           0 :         cfg_igmp_enable_ = data->cfg_igmp_enable_;
     293             :     }
     294             : 
     295         116 :     if (vn_max_flows_ != data->vn_max_flows_) {
     296           0 :         vn_max_flows_ = data->vn_max_flows_;
     297           0 :         ret = true;
     298             :     }
     299             : 
     300         116 :     if (mac_ip_learning_enable_ != data->mac_ip_learning_enable_) {
     301           7 :         mac_ip_learning_enable_ = data->mac_ip_learning_enable_;
     302           7 :         ret = true;
     303             :     }
     304             : 
     305         116 :     if (health_check_uuid_ != data->health_check_uuid_) {
     306           7 :         health_check_uuid_ = data->health_check_uuid_;
     307           7 :         ret = true;
     308             :     }
     309             : 
     310         116 :     return ret;
     311         116 : }
     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          95 : bool VnEntry::UpdateVxlan(Agent *agent, bool op_del) {
     322          95 :     int old_vxlan = active_vxlan_id_;
     323          95 :     int new_vxlan = GetVxLanId();
     324             : 
     325          95 :     if (op_del || old_vxlan != new_vxlan || vrf_.get() == NULL) {
     326          95 :         if (old_vxlan != 0) {
     327          17 :             agent->vxlan_table()->Delete(old_vxlan, uuid_);
     328          17 :             vxlan_id_ref_ = NULL;
     329          17 :             active_vxlan_id_ = 0;
     330             :         }
     331             :     }
     332             : 
     333          95 :     if (op_del == false && vrf_.get() != NULL && new_vxlan != 0) {
     334             :         vxlan_id_ref_ = agent->vxlan_table()->Locate
     335          34 :             (new_vxlan, uuid_, vrf_->GetName(), flood_unknown_unicast_,
     336          17 :              mirror_destination_, false, true);
     337          17 :         active_vxlan_id_ = new_vxlan;
     338             :     }
     339             : 
     340          95 :     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         116 : bool VnEntry::UpdateForwardingMode(Agent *agent) {
     347         116 :     Agent::ForwardingMode forwarding_mode = forwarding_mode_;
     348         116 :     if (forwarding_mode == Agent::NONE) {
     349             :         forwarding_mode =
     350         116 :             agent->oper_db()->global_vrouter()->forwarding_mode();
     351             :     }
     352             : 
     353         116 :     bool ret = false;
     354         116 :     bool routing = (forwarding_mode == Agent::L2) ? false : true;
     355         116 :     if (routing != layer3_forwarding_) {
     356           0 :         layer3_forwarding_ = routing;
     357           0 :         ret = true;
     358             :     }
     359             : 
     360         116 :     bool bridging = (forwarding_mode == Agent::L3) ? false : true;
     361         116 :     if (bridging != bridging_) {
     362           0 :         bridging_ = bridging;
     363           0 :         ret = true;
     364             :     }
     365             : 
     366         116 :     return ret;
     367             : }
     368             : 
     369             : // Update all IPAM configurations. Typically invoked when forwarding-mode
     370             : // changes or VRF is set for the VN
     371          60 : bool VnEntry::ApplyAllIpam(Agent *agent, VrfEntry *old_vrf, bool del) {
     372          60 :     bool ret = false;
     373         120 :     for (unsigned int i = 0; i < ipam_.size(); ++i) {
     374          60 :         ret |= ApplyIpam(agent, &ipam_[i], old_vrf, del);
     375             :     }
     376             : 
     377          60 :     return ret;
     378             : }
     379             : 
     380             : // Add/Delete routes dervied from a single IPAM
     381          97 : bool VnEntry::ApplyIpam(Agent *agent, VnIpam *ipam, VrfEntry *old_vrf,
     382             :                         bool del) {
     383          97 :     if (CanInstallIpam(ipam) == false)
     384          36 :         del = true;
     385             : 
     386          97 :     bool old_installed = ipam->installed;
     387          97 :     if (del == false) {
     388          17 :         ipam->installed = AddIpamRoutes(agent, ipam);
     389             :     } else {
     390          80 :         DelIpamRoutes(agent, ipam, old_vrf);
     391          80 :         ipam->installed = false;
     392             :     }
     393             : 
     394          97 :     return old_installed != ipam->installed;
     395             : }
     396             : 
     397         193 : bool VnEntry::CanInstallIpam(const VnIpam *ipam) {
     398         193 :     if (vrf_.get() == NULL || layer3_forwarding_ == false)
     399          77 :         return false;
     400         116 :     return true;
     401             : }
     402             : 
     403             : // Check the old and new Ipam data and update receive routes for GW addresses
     404         116 : bool VnEntry::UpdateIpam(Agent *agent, std::vector<VnIpam> &new_ipam) {
     405         116 :     std::sort(new_ipam.begin(), new_ipam.end());
     406             : 
     407         116 :     std::vector<VnIpam>::iterator it_old = ipam_.begin();
     408         116 :     std::vector<VnIpam>::iterator it_new = new_ipam.begin();
     409         116 :     bool change = false;
     410         212 :     while (it_old != ipam_.end() && it_new != new_ipam.end()) {
     411          96 :         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          96 :         } 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          96 :             change |= HandleIpamChange(agent, &(*it_old), &(*it_new));
     423          96 :             it_old++;
     424          96 :             it_new++;
     425             :         }
     426             :     }
     427             : 
     428             :     // delete remaining old entries
     429         116 :     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         136 :     for (; it_new != new_ipam.end(); ++it_new) {
     436          20 :         ApplyIpam(agent, &(*it_new), vrf_.get(), false);
     437          20 :         change = true;
     438             :     }
     439             : 
     440         116 :     ipam_ = new_ipam;
     441         116 :     return change;
     442             : }
     443             : 
     444          34 : static bool IsGwHostRouteRequired(const Agent *agent) {
     445          34 :     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          96 : bool VnEntry::HandleIpamChange(Agent *agent, VnIpam *old_ipam,
     451             :                                VnIpam *new_ipam) {
     452          96 :     bool install = CanInstallIpam(new_ipam);
     453             : 
     454          96 :     if (install == false && old_ipam->installed == false)
     455          41 :         return false;
     456             : 
     457          55 :     if (install == false && old_ipam->installed == true) {
     458           0 :         ApplyIpam(agent, old_ipam, vrf_.get(), true);
     459           0 :         return true;
     460             :     }
     461             : 
     462          55 :     if (install == true && old_ipam->installed == false) {
     463          17 :         ApplyIpam(agent, new_ipam, vrf_.get(), false);
     464          17 :         return true;
     465             :     }
     466             : 
     467          38 :     new_ipam->installed = install;
     468          38 :     bool changed = false;
     469          38 :     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          38 :     if (vrf_.get() && (vrf_->GetName() != agent->linklocal_vrf_name())) {
     479          38 :         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          38 :     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          38 :     old_ipam->oper_dhcp_options = new_ipam->oper_dhcp_options;
     504             : 
     505          38 :     if (old_ipam->dhcp_enable != new_ipam->dhcp_enable) {
     506           0 :         changed = true;
     507             :     }
     508             : 
     509          38 :     if (old_ipam->dhcp_enable_v6 != new_ipam->dhcp_enable_v6) {
     510           0 :         changed = true;
     511             :     }
     512             : 
     513          38 :     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          17 : bool VnEntry::AddIpamRoutes(Agent *agent, VnIpam *ipam) {
     528          17 :     if (vrf_ == NULL)
     529           0 :         return false;
     530             : 
     531             :     // Do not let the gateway configuration overwrite the receive nh.
     532          17 :     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          17 :     bool policy = (agent->tsn_enabled()) ? false : true;
     540          17 :     if (IsGwHostRouteRequired(agent))
     541          17 :         AddHostRoute(ipam->default_gw, policy);
     542          17 :     AddHostRoute(ipam->dns_server, policy);
     543          17 :     AddSubnetRoute(ipam);
     544          17 :     return true;
     545             : }
     546             : 
     547             : // Delete routes generated from an IPAM
     548          80 : void VnEntry::DelIpamRoutes(Agent *agent, VnIpam *ipam, VrfEntry *vrf) {
     549          80 :     if (ipam->installed == false)
     550          63 :         return;
     551             : 
     552          17 :     assert(vrf);
     553          17 :     if (IsGwHostRouteRequired(agent))
     554          17 :         DelHostRoute(ipam->default_gw);
     555          17 :     DelHostRoute(ipam->dns_server);
     556          17 :     DelSubnetRoute(ipam);
     557             : }
     558             : 
     559             : // Add host route for gateway-ip or service-ip
     560          34 : void VnEntry::AddHostRoute(const IpAddress &address, bool policy) {
     561          34 :     if (address.is_v4()) {
     562             :         static_cast<InetUnicastAgentRouteTable *>(vrf_->
     563          68 :             GetInet4UnicastRouteTable())->AddHostRoute(vrf_->GetName(),
     564          68 :                 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          34 : }
     571             : 
     572             : // Del host route for gateway-ip or service-ip
     573          34 : void VnEntry::DelHostRoute(const IpAddress &address) {
     574          34 :     Agent *agent = static_cast<VnTable *>(get_table())->agent();
     575          34 :     if (address.is_v4()) {
     576             :         static_cast<InetUnicastAgentRouteTable *>
     577          34 :             (vrf_->GetInet4UnicastRouteTable())->DeleteReq
     578          34 :             (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          34 : }
     586             : 
     587             : // Add subnet route for the IPAM
     588          17 : void VnEntry::AddSubnetRoute(VnIpam *ipam) {
     589             :     static_cast<InetUnicastAgentRouteTable *>(vrf_->
     590          17 :             GetInetUnicastRouteTable(ipam->ip_prefix))->AddIpamSubnetRoute
     591          17 :             (vrf_->GetName(), ipam->GetSubnetAddress(), ipam->plen,
     592             :              GetName());
     593          17 : }
     594             : 
     595             : // Del subnet route for the IPAM
     596          17 : void VnEntry::DelSubnetRoute(VnIpam *ipam) {
     597          17 :     Agent *agent = static_cast<VnTable *>(get_table())->agent();
     598             :     static_cast<InetUnicastAgentRouteTable *>(vrf_->
     599          17 :             GetInetUnicastRouteTable(ipam->ip_prefix))->DeleteReq
     600          17 :             (agent->local_peer(), vrf_->GetName(),
     601          17 :              ipam->GetSubnetAddress(), ipam->plen, NULL);
     602          17 : }
     603             : 
     604          20 : void VnEntry::AllocWalker() {
     605          20 :     assert(route_resync_walker_.get() == NULL);
     606             :     route_resync_walker_ = new AgentRouteResync("VnRouteResyncWalker",
     607          20 :                                                 agent_);
     608          20 :     agent_->oper_db()->agent_route_walk_manager()->
     609          20 :         RegisterWalker(static_cast<AgentRouteWalker *>
     610             :                        (route_resync_walker_.get()));
     611          20 : }
     612             : 
     613          57 : void VnEntry::ReleaseWalker() {
     614          57 :     if (route_resync_walker_.get() == NULL)
     615          37 :         return;
     616          20 :     agent_->oper_db()->agent_route_walk_manager()->
     617          20 :         ReleaseWalker(route_resync_walker_.get());
     618          20 :     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          86 : bool VnEntry::GetIpamName(const IpAddress &vm_addr,
     632             :                           std::string *ipam_name) const {
     633         121 :     for (unsigned int i = 0; i < ipam_.size(); i++) {
     634          86 :         if (ipam_[i].IsSubnetMember(vm_addr)) {
     635          51 :             *ipam_name = ipam_[i].ipam_name;
     636          51 :             return true;
     637             :         }
     638             :     }
     639          35 :     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         665 : const VnIpam *VnEntry::GetIpam(const IpAddress &ip) const {
     653         845 :     for (unsigned int i = 0; i < ipam_.size(); i++) {
     654         665 :         if (ipam_[i].IsSubnetMember(ip)) {
     655         485 :             return &ipam_[i];
     656             :         }
     657             :     }
     658         180 :     return NULL;
     659             : }
     660             : 
     661          26 : IpAddress VnEntry::GetGatewayFromIpam(const IpAddress &ip) const {
     662          26 :     const VnIpam *ipam = GetIpam(ip);
     663          26 :     if (ipam) {
     664          26 :         return ipam->default_gw;
     665             :     }
     666           0 :     return IpAddress();
     667             : }
     668             : 
     669          26 : IpAddress VnEntry::GetDnsFromIpam(const IpAddress &ip) const {
     670          26 :     const VnIpam *ipam = GetIpam(ip);
     671          26 :     if (ipam) {
     672          26 :         return ipam->dns_server;
     673             :     }
     674           0 :     return IpAddress();
     675             : }
     676             : 
     677          68 : uint32_t VnEntry::GetAllocUnitFromIpam(const IpAddress &ip) const {
     678          68 :     const VnIpam *ipam = GetIpam(ip);
     679          68 :     if (ipam) {
     680          42 :         return ipam->alloc_unit;
     681             :     }
     682          26 :     return 1;//Default value
     683             : }
     684             : 
     685          86 : bool VnEntry::GetIpamVdnsData(const IpAddress &vm_addr,
     686             :                               autogen::IpamType *ipam_type,
     687             :                               autogen::VirtualDnsType *vdns_type) const {
     688          86 :     std::string ipam_name;
     689          86 :     if (!GetIpamName(vm_addr, &ipam_name) ||
     690         137 :         !agent_->domain_config_table()->GetIpam(ipam_name, ipam_type) ||
     691          51 :         ipam_type->ipam_dns_method != "virtual-dns-server")
     692          86 :         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          86 : }
     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         336 : int VnEntry::GetVxLanId() const {
     729         336 :     if (agent_->vxlan_network_identifier_mode() == Agent::CONFIGURED) {
     730           0 :         return vxlan_id_;
     731             :     }
     732         336 :     if (vxlan_routing_vn_ && vxlan_id_) {
     733           0 :         return vxlan_id_;
     734             :     }
     735         336 :     return vnid_;
     736             : }
     737             : 
     738         116 : int VnEntry::GetOperVxlanId() const {
     739         116 :     if (agent_->vxlan_network_identifier_mode() == Agent::CONFIGURED) {
     740           0 :         return vxlan_id_;
     741             :     }
     742         116 :     if (bool(vxlan_id_ref_)) {
     743          55 :         return vxlan_id_ref_->vxlan_id();
     744             :     }
     745          61 :     return 0;
     746             : }
     747             : 
     748             : /////////////////////////////////////////////////////////////////////////////
     749             : // VnTable routines
     750             : /////////////////////////////////////////////////////////////////////////////
     751           2 : VnTable::VnTable(DB *db, const std::string &name) : AgentOperDBTable(db, name) {
     752           4 :     walk_ref_ = AllocWalker(boost::bind(&VnTable::VnEntryWalk, this, _1, _2),
     753             :                             boost::bind(&VnTable::VnEntryWalkDone, this, _1,
     754           2 :                                         _2));
     755           2 : }
     756             : 
     757           4 : VnTable::~VnTable() {
     758           4 : }
     759             : 
     760           0 : void VnTable::Clear() {
     761           0 :     ReleaseWalker(walk_ref_);
     762           0 : }
     763             : 
     764           2 : DBTableBase *VnTable::CreateTable(DB *db, const std::string &name) {
     765           2 :     vn_table_ = new VnTable(db, name);
     766           2 :     vn_table_->Init();
     767           2 :     return vn_table_;
     768             : };
     769             : 
     770         294 : VnEntry *VnTable::Find(const boost::uuids::uuid &u) {
     771         294 :     VnKey key(u);
     772         588 :     return static_cast<VnEntry *>(FindActiveEntry(&key));
     773         294 : }
     774             : 
     775         587 : std::unique_ptr<DBEntry> VnTable::AllocEntry(const DBRequestKey *k) const {
     776         587 :     const VnKey *key = static_cast<const VnKey *>(k);
     777         587 :     VnEntry *vn = new VnEntry(agent(), key->uuid_);
     778         587 :     return std::unique_ptr<DBEntry>(static_cast<DBEntry *>(vn));
     779             : }
     780             : 
     781          20 : DBEntry *VnTable::OperDBAdd(const DBRequest *req) {
     782          20 :     VnKey *key = static_cast<VnKey *>(req->key.get());
     783          20 :     VnData *data = static_cast<VnData *>(req->data.get());
     784          20 :     VnEntry *vn = new VnEntry(agent(), key->uuid_);
     785          20 :     vn->name_ = data->name_;
     786          20 :     vn->AllocWalker();
     787             : 
     788          20 :     vn->ChangeHandler(agent(), req);
     789          20 :     vn->SendObjectLog(GetOperDBTraceBuf(), AgentLogEvent::ADD);
     790             : 
     791          20 :     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          20 :     return vn;
     799             : }
     800             : 
     801          57 : bool VnTable::OperDBDelete(DBEntry *entry, const DBRequest *req) {
     802          57 :     VnEntry *vn = static_cast<VnEntry *>(entry);
     803          57 :     vn->ApplyAllIpam(agent(), vn->vrf_.get(), true);
     804          57 :     vn->UpdateVxlan(agent(), true);
     805          57 :     vn->ReleaseWalker();
     806          57 :     vn->SendObjectLog(GetOperDBTraceBuf(), AgentLogEvent::DEL);
     807             : 
     808          57 :     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          57 :     return true;
     813             : }
     814             : 
     815          96 : bool VnTable::OperDBOnChange(DBEntry *entry, const DBRequest *req) {
     816          96 :     VnEntry *vn = static_cast<VnEntry *>(entry);
     817          96 :     bool ret = vn->ChangeHandler(agent(), req);
     818          96 :     vn->SendObjectLog(GetOperDBTraceBuf(), AgentLogEvent::CHANGE);
     819          96 :     if (ret) {
     820          21 :         VnData *data = static_cast<VnData *>(req->data.get());
     821          21 :         if (data && data->ifmap_node()) {
     822             :             agent()->oper_db()->dependency_manager()->PropogateNodeChange
     823          21 :                 (data->ifmap_node());
     824             :         }
     825             :     }
     826          96 :     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          23 : void VnTable::VnEntryWalkDone(DBTable::DBTableWalkRef walk_ref,
     843             :                               DBTableBase *partition) {
     844          23 :     agent()->interface_table()->GlobalVrouterConfigChanged();
     845             :     agent()->physical_device_vn_table()->
     846          23 :         UpdateVxLanNetworkIdentifierMode();
     847          23 : }
     848             : 
     849          23 : void VnTable::GlobalVrouterConfigChanged() {
     850          23 :     WalkAgain(walk_ref_);
     851          23 : }
     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         129 : bool IsVRFServiceChainingInstance(const string &vn_name, const string &vrf_name)
     872             : {
     873         129 :     vector<string> vn_token_result;
     874         129 :     vector<string> vrf_token_result;
     875         129 :     uint32_t vrf_token_result_size = 0;
     876             : 
     877         129 :     split(vn_token_result, vn_name, is_any_of(":"), token_compress_on);
     878         129 :     split(vrf_token_result, vrf_name, is_any_of(":"), token_compress_on);
     879         129 :     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         129 :     if (vrf_token_result_size == 1) {
     888         129 :         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         129 : }
     898             : 
     899         116 : IFMapNode *VnTable::FindTarget(IFMapAgentTable *table, IFMapNode *node,
     900             :                                std::string node_type) {
     901         116 :     for (DBGraphVertex::adjacency_iterator it = node->begin(table->GetGraph());
     902         116 :          it != node->end(table->GetGraph()); ++it) {
     903         116 :         IFMapNode *adj_node = static_cast<IFMapNode *>(it.operator->());
     904         116 :         if (adj_node->table()->Typename() == node_type)
     905         116 :             return adj_node;
     906             :     }
     907           0 :     return NULL;
     908             : }
     909             : 
     910         116 : int VnTable::GetCfgVnId(VirtualNetwork *cfg_vn) {
     911         116 :     if (cfg_vn->IsPropertySet(autogen::VirtualNetwork::NETWORK_ID))
     912          73 :         return cfg_vn->network_id();
     913             :     else
     914          43 :         return cfg_vn->properties().network_id;
     915             : }
     916             : 
     917         116 : void VnTable::CfgForwardingFlags(IFMapNode *node,
     918             :                                  bool *rpf, bool *flood_unknown_unicast,
     919             :                                  Agent::ForwardingMode *forwarding_mode,
     920             :                                  bool *mirror_destination) {
     921         116 :     *rpf = true;
     922             : 
     923         116 :     VirtualNetwork *cfg = static_cast <VirtualNetwork *> (node->GetObject());
     924         116 :     autogen::VirtualNetworkType properties = cfg->properties();
     925             : 
     926         116 :     if (properties.rpf == "disable") {
     927           0 :         *rpf = false;
     928             :     }
     929             : 
     930         116 :     *flood_unknown_unicast = cfg->flood_unknown_unicast();
     931         116 :     *mirror_destination = properties.mirror_destination;
     932         116 :     *forwarding_mode =
     933         116 :         agent()->TranslateForwardingMode(properties.forwarding_mode);
     934         116 :  }
     935             : 
     936             : void
     937         116 : VnTable::BuildVnIpamData(const std::vector<autogen::IpamSubnetType> &subnets,
     938             :                          const std::string &ipam_name,
     939             :                          std::vector<VnIpam> *vn_ipam) {
     940         232 :     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         116 :         std::string dns_server_address = subnets[i].dns_server_address;
     944         116 :         boost::system::error_code ec;
     945             :         IpAddress dns_server =
     946         116 :             IpAddress::from_string(dns_server_address, ec);
     947         116 :         if (ec.value() || dns_server.is_unspecified()) {
     948           0 :             dns_server_address = subnets[i].default_gateway;
     949             :         }
     950             : 
     951             :         vn_ipam->push_back
     952         116 :             (VnIpam(subnets[i].subnet.ip_prefix,
     953         116 :                     subnets[i].subnet.ip_prefix_len,
     954         116 :                     subnets[i].default_gateway,
     955             :                     dns_server_address,
     956         116 :                     subnets[i].enable_dhcp, ipam_name,
     957         116 :                     subnets[i].dhcp_option_list.dhcp_option,
     958         116 :                     subnets[i].host_routes.route,
     959         116 :                     subnets[i].alloc_unit));
     960         116 :     }
     961         116 : }
     962             : 
     963         116 : VnData *VnTable::BuildData(IFMapNode *node) {
     964             :     using boost::uuids::uuid;
     965             :     using boost::uuids::nil_uuid;
     966         116 :     boost::uuids::uuid mp_uuid = nil_uuid();
     967         116 :     UuidList mp_list;
     968             : 
     969         116 :     VirtualNetwork *cfg = static_cast <VirtualNetwork *> (node->GetObject());
     970         116 :     assert(cfg);
     971             : 
     972         116 :     uuid acl_uuid = nil_uuid();
     973         116 :     uuid mirror_cfg_acl_uuid = nil_uuid();
     974         116 :     uuid qos_config_uuid = nil_uuid();
     975         116 :     string vrf_name = "";
     976         116 :     std::vector<VnIpam> vn_ipam;
     977         116 :     VnData::VnIpamDataMap vn_ipam_data;
     978         116 :     std::string ipam_name;
     979         116 :     UuidList slo_list;
     980         116 :     bool underlay_forwarding = false;
     981         116 :     bool vxlan_routing_vn = false;
     982         116 :     uuid logical_router_uuid = nil_uuid();
     983         116 :     uuid health_check_uuid = nil_uuid();
     984             : 
     985             :     // Find link with ACL / VRF adjacency
     986         116 :     IFMapAgentTable *table = static_cast<IFMapAgentTable *>(node->table());
     987         116 :     DBGraph *graph = table->GetGraph();
     988         116 :     for (DBGraphVertex::adjacency_iterator iter = node->begin(graph);
     989         361 :          iter != node->end(table->GetGraph()); ++iter) {
     990             : 
     991         245 :         IFMapNode *adj_node = static_cast<IFMapNode *>(iter.operator->());
     992         245 :         if (agent()->config_manager()->SkipNode(adj_node)) {
     993          13 :             continue;
     994             :         }
     995             : 
     996         232 :         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         288 :         if ((adj_node->table() == agent()->cfg()->cfg_vrf_table()) &&
    1011          56 :             (!IsVRFServiceChainingInstance(node->name(), adj_node->name()))) {
    1012          56 :             vrf_name = adj_node->name();
    1013             :         }
    1014             : 
    1015         232 :         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         232 :         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         232 :         if (adj_node->table() == agent()->cfg()->cfg_vn_network_ipam_table()) {
    1035         116 :             if (IFMapNode *ipam_node = FindTarget(table, adj_node,
    1036             :                                                   "network-ipam")) {
    1037         116 :                 ipam_name = ipam_node->name();
    1038             :                 VirtualNetworkNetworkIpam *vnni =
    1039             :                     static_cast<VirtualNetworkNetworkIpam *>
    1040         116 :                     (adj_node->GetObject());
    1041         116 :                 VnSubnetsType subnets;
    1042         116 :                 if (vnni)
    1043         116 :                     subnets = vnni->data();
    1044             : 
    1045             :                 autogen::NetworkIpam *network_ipam =
    1046         116 :                     static_cast<autogen::NetworkIpam *>(ipam_node->GetObject());
    1047             :                 const std::string subnet_method =
    1048         116 :                     boost::to_lower_copy(network_ipam->ipam_subnet_method());
    1049             : 
    1050         116 :                 if (subnet_method == "flat-subnet") {
    1051           0 :                     BuildVnIpamData(network_ipam->ipam_subnets(),
    1052             :                                     ipam_name, &vn_ipam);
    1053             :                 } else {
    1054         116 :                     BuildVnIpamData(subnets.ipam_subnets, ipam_name, &vn_ipam);
    1055             :                 }
    1056             : 
    1057         116 :                 VnIpamLinkData ipam_data;
    1058         116 :                 ipam_data.oper_dhcp_options_.set_host_routes(subnets.host_routes.route);
    1059         116 :                 vn_ipam_data.insert(VnData::VnIpamDataPair(ipam_name, ipam_data));
    1060         116 :             }
    1061             :         }
    1062             : 
    1063         232 :         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         232 :         if (strcmp(adj_node->table()->Typename(),
    1070         232 :                    "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         464 :         if (adj_node->table() ==
    1099         232 :                             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         464 :         if (adj_node->table() ==
    1110         232 :                             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         116 :     uuid mirror_acl_uuid = agent()->mirror_cfg_table()->GetMirrorUuid(node->name());
    1123         116 :     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         116 :     bool pbb_evpn_enable = cfg->pbb_evpn_enable();
    1130         116 :     bool pbb_etree_enable = cfg->pbb_etree_enable();
    1131         116 :     bool layer2_control_word = cfg->layer2_control_word();
    1132         116 :     bool cfg_igmp_enable = cfg->igmp_enable();
    1133         116 :     uint32_t vn_max_flows = cfg->properties().max_flows;
    1134         116 :     bool mac_ip_learning_enable = cfg->mac_ip_learning_enable();
    1135             :     Agent::ForwardingMode forwarding_mode;
    1136         116 :     CfgForwardingFlags(node, &enable_rpf, &flood_unknown_unicast,
    1137             :                        &forwarding_mode, &mirror_destination);
    1138         116 :     return new VnData(agent(), node, node->name(), acl_uuid, vrf_name,
    1139             :                       mirror_acl_uuid, mirror_cfg_acl_uuid, vn_ipam,
    1140         116 :                       vn_ipam_data, cfg->properties().vxlan_network_identifier,
    1141         116 :                       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         232 :                       health_check_uuid);
    1149         116 : }
    1150             : 
    1151         238 : bool VnTable::IFNodeToUuid(IFMapNode *node, boost::uuids::uuid &u) {
    1152         238 :     VirtualNetwork *cfg = static_cast <VirtualNetwork *> (node->GetObject());
    1153         238 :     assert(cfg);
    1154         238 :     autogen::IdPermsType id_perms = cfg->id_perms();
    1155         238 :     CfgUuidSet(id_perms.uuid.uuid_mslong, id_perms.uuid.uuid_lslong, u);
    1156         238 :     return true;
    1157         238 : }
    1158             : 
    1159         238 : bool VnTable::IFNodeToReq(IFMapNode *node, DBRequest &req,
    1160             :         const boost::uuids::uuid &u) {
    1161             : 
    1162         238 :     assert(!u.is_nil());
    1163             : 
    1164         238 :     if ((req.oper == DBRequest::DB_ENTRY_DELETE) || node->IsDeleted()) {
    1165          57 :         req.key.reset(new VnKey(u));
    1166          57 :         req.oper = DBRequest::DB_ENTRY_DELETE;
    1167          57 :         Enqueue(&req);
    1168          57 :         return false;
    1169             :     }
    1170             : 
    1171         181 :     agent()->config_manager()->AddVnNode(node);
    1172         181 :     return false;
    1173             : }
    1174             : 
    1175         117 : bool VnTable::ProcessConfig(IFMapNode *node, DBRequest &req,
    1176             :         const boost::uuids::uuid &u) {
    1177             : 
    1178         117 :     if (node->IsDeleted()) {
    1179           1 :         return false;
    1180             :     }
    1181             : 
    1182         116 :     req.oper = DBRequest::DB_ENTRY_ADD_CHANGE;
    1183         116 :     req.key.reset(new VnKey(u));
    1184         116 :     req.data.reset(BuildData(node));
    1185         116 :     Enqueue(&req);
    1186         116 :     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         173 : void VnEntry::SendObjectLog(SandeshTraceBufferPtr buf,
    1336             :                             AgentLogEvent::type event) const {
    1337         346 :     VnObjectLogInfo info;
    1338         173 :     string str;
    1339         173 :     string vn_uuid = UuidToString(GetUuid());
    1340         173 :     const AclDBEntry *acl = GetAcl();
    1341         173 :     const AclDBEntry *mirror_acl = GetMirrorAcl();
    1342         173 :     const AclDBEntry *mirror_cfg_acl = GetMirrorCfgAcl();
    1343         173 :     string acl_uuid;
    1344         173 :     string mirror_acl_uuid;
    1345         173 :     string mirror_cfg_acl_uuid;
    1346             : 
    1347         173 :     info.set_uuid(vn_uuid);
    1348         173 :     info.set_name(GetName());
    1349         173 :     switch (event) {
    1350          20 :         case AgentLogEvent::ADD:
    1351          20 :             str.assign("Addition ");
    1352          20 :             break;
    1353          57 :         case AgentLogEvent::DEL:
    1354          57 :             str.assign("Deletion ");
    1355          57 :             info.set_event(str);
    1356          57 :             VN_OBJECT_LOG_LOG("AgentVn", SandeshLevel::SYS_INFO, info);
    1357          57 :             return;
    1358          96 :         case AgentLogEvent::CHANGE:
    1359          96 :             str.assign("Modification ");
    1360          96 :             break;
    1361           0 :         default:
    1362           0 :             str.assign("");
    1363           0 :             break;
    1364             :     }
    1365             : 
    1366         116 :     info.set_event(str);
    1367         116 :     if (acl) {
    1368           0 :         acl_uuid.assign(UuidToString(acl->GetUuid()));
    1369           0 :         info.set_acl_uuid(acl_uuid);
    1370             :     }
    1371         116 :     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         116 :     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         116 :     VrfEntry *vrf = GetVrf();
    1380         116 :     if (vrf) {
    1381          55 :         info.set_vrf(vrf->GetName());
    1382             :     }
    1383         232 :     vector<VnObjectLogIpam> ipam_list;
    1384         116 :     VnObjectLogIpam sandesh_ipam;
    1385         116 :     vector<VnIpam>::const_iterator it = ipam_.begin();
    1386         232 :     while (it != ipam_.end()) {
    1387         116 :         VnIpam ipam = *it;
    1388         116 :         sandesh_ipam.set_ip_prefix(ipam.ip_prefix.to_string());
    1389         116 :         sandesh_ipam.set_prefix_len(ipam.plen);
    1390         116 :         sandesh_ipam.set_gateway_ip(ipam.default_gw.to_string());
    1391         116 :         sandesh_ipam.set_ipam_name(ipam.ipam_name);
    1392         116 :         sandesh_ipam.set_dhcp_enable(ipam.dhcp_enable ? "true" : "false");
    1393         116 :         sandesh_ipam.set_dhcp_enable_v6(ipam.dhcp_enable_v6 ? "true" : "false");
    1394         116 :         sandesh_ipam.set_dns_server(ipam.dns_server.to_string());
    1395         116 :         ipam_list.push_back(sandesh_ipam);
    1396         116 :         ++it;
    1397         116 :     }
    1398             : 
    1399         116 :     if (ipam_list.size()) {
    1400         116 :         info.set_ipam_list(ipam_list);
    1401             :     }
    1402         116 :     info.set_bridging(bridging());
    1403         116 :     info.set_oper_vxlan_id(GetOperVxlanId());
    1404         116 :     info.set_ipv4_forwarding(layer3_forwarding());
    1405         116 :     info.set_admin_state(admin_state());
    1406         116 :     info.set_logical_router_uuid(UuidToString(logical_router_uuid()));
    1407         116 :     info.set_vxlan_routing_vn(vxlan_routing_vn());
    1408         116 :     VN_OBJECT_LOG_LOG("AgentVn", SandeshLevel::SYS_INFO, info);
    1409         116 :     VN_OBJECT_TRACE_TRACE(buf, info);
    1410         458 : }
    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           2 : DomainConfig::DomainConfig(Agent *agent) {
    1431           2 : }
    1432             : 
    1433           4 : DomainConfig::~DomainConfig() {
    1434           4 : }
    1435             : 
    1436           2 : void DomainConfig::Init() {
    1437           2 : }
    1438             : 
    1439           2 : void DomainConfig::Terminate() {
    1440           2 : }
    1441             : 
    1442           2 : void DomainConfig::RegisterIpamCb(Callback cb) {
    1443           2 :     ipam_callback_.push_back(cb);
    1444           2 : }
    1445             : 
    1446           2 : void DomainConfig::RegisterVdnsCb(Callback cb) {
    1447           2 :     vdns_callback_.push_back(cb);
    1448           2 : }
    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          56 : void DomainConfig::IpamDelete(IFMapNode *node) {
    1453          56 :     CallIpamCb(node);
    1454          56 :     ipam_config_.erase(node->name());
    1455          56 :     return;
    1456             : }
    1457             : 
    1458          41 : void DomainConfig::IpamAddChange(IFMapNode *node) {
    1459             :     autogen::NetworkIpam *network_ipam =
    1460          41 :         static_cast <autogen::NetworkIpam *> (node->GetObject());
    1461          41 :     assert(network_ipam);
    1462             : 
    1463          41 :     bool change = false;
    1464          41 :     IpamDomainConfigMap::iterator it = ipam_config_.find(node->name());
    1465          41 :     if (it != ipam_config_.end()) {
    1466          23 :         if (IpamChanged(it->second, network_ipam->mgmt())) {
    1467           0 :             it->second = network_ipam->mgmt();
    1468           0 :             change = true;
    1469             :         }
    1470             :     } else {
    1471          18 :         ipam_config_.insert(IpamDomainConfigPair(node->name(),
    1472          18 :                                                  network_ipam->mgmt()));
    1473          18 :         change = true;
    1474             :     }
    1475          41 :     if (change)
    1476          18 :         CallIpamCb(node);
    1477          41 : }
    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          74 : void DomainConfig::CallIpamCb(IFMapNode *node) {
    1501         148 :     for (unsigned int i = 0; i < ipam_callback_.size(); ++i) {
    1502          74 :         ipam_callback_[i](node);
    1503             :     }
    1504          74 : }
    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          23 : bool DomainConfig::IpamChanged(const autogen::IpamType &old,
    1513             :                                const autogen::IpamType &cur) const {
    1514          46 :     if (old.ipam_method != cur.ipam_method ||
    1515          23 :         old.ipam_dns_method != cur.ipam_dns_method)
    1516           0 :         return true;
    1517             : 
    1518          46 :     if ((old.ipam_dns_server.virtual_dns_server_name !=
    1519          46 :          cur.ipam_dns_server.virtual_dns_server_name) ||
    1520          23 :         (old.ipam_dns_server.tenant_dns_server_address.ip_address !=
    1521          23 :          cur.ipam_dns_server.tenant_dns_server_address.ip_address))
    1522           0 :         return true;
    1523             : 
    1524          46 :     if (old.cidr_block.ip_prefix != cur.cidr_block.ip_prefix ||
    1525          23 :         old.cidr_block.ip_prefix_len != cur.cidr_block.ip_prefix_len)
    1526           0 :         return true;
    1527             : 
    1528          46 :     if (old.dhcp_option_list.dhcp_option.size() !=
    1529          23 :         cur.dhcp_option_list.dhcp_option.size())
    1530           0 :         return true;
    1531             : 
    1532          23 :     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          23 :     if (old.host_routes.route.size() != cur.host_routes.route.size())
    1543           0 :         return true;
    1544             : 
    1545          23 :     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          23 :     return false;
    1558             : }
    1559             : 
    1560          51 : bool DomainConfig::GetIpam(const std::string &name, autogen::IpamType *ipam) {
    1561          51 :     IpamDomainConfigMap::iterator it = ipam_config_.find(name);
    1562          51 :     if (it == ipam_config_.end())
    1563           0 :         return false;
    1564          51 :     *ipam = it->second;
    1565          51 :     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           2 : OperNetworkIpam::OperNetworkIpam(Agent *agent, DomainConfig *domain_config) :
    1581           2 :     OperIFMapTable(agent), domain_config_(domain_config) {
    1582           2 : }
    1583             : 
    1584           4 : OperNetworkIpam::~OperNetworkIpam() {
    1585           4 : }
    1586             : 
    1587          56 : void OperNetworkIpam::ConfigDelete(IFMapNode *node) {
    1588          56 :     domain_config_->IpamDelete(node);
    1589          56 : }
    1590             : 
    1591          41 : void OperNetworkIpam::ConfigAddChange(IFMapNode *node) {
    1592          41 :     domain_config_->IpamAddChange(node);
    1593          41 : }
    1594             : 
    1595          77 : void OperNetworkIpam::ConfigManagerEnqueue(IFMapNode *node) {
    1596          77 :     agent()->config_manager()->AddNetworkIpamNode(node);
    1597          77 : }
    1598             : 
    1599           2 : OperVirtualDns::OperVirtualDns(Agent *agent, DomainConfig *domain_config) :
    1600           2 :     OperIFMapTable(agent), domain_config_(domain_config) {
    1601           2 : }
    1602             : 
    1603           4 : OperVirtualDns::~OperVirtualDns() {
    1604           4 : }
    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