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: 626 988 63.4 %
Date: 2026-11-09 02:10:49 Functions: 75 99 75.8 %
Legend: Lines: hit not hit

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

Generated by: LCOV version 1.14