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: 601 988 60.8 %
Date: 2026-06-11 01:56:02 Functions: 74 99 74.7 %
Legend: Lines: hit not hit

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

Generated by: LCOV version 1.14