LCOV - code coverage report
Current view: top level - vnsw/agent/oper - global_vrouter.cc (source / functions) Hit Total Coverage
Test: OpenSDN C/C++ coverage (all TARGET_SET jobs) Lines: 224 710 31.5 %
Date: 2026-06-04 02:06:09 Functions: 31 64 48.4 %
Legend: Lines: hit not hit

          Line data    Source code
       1             : /*
       2             :  * Copyright (c) 2013 Juniper Networks, Inc. All rights reserved.
       3             :  */
       4             : 
       5             : // global_vrouter.cc - operational data for global vrouter configuration
       6             : 
       7             : #include <mutex>
       8             : 
       9             : #include <boost/foreach.hpp>
      10             : #include <base/util.h>
      11             : #include <cmn/agent_cmn.h>
      12             : #include <cfg/cfg_init.h>
      13             : #include <route/route.h>
      14             : 
      15             : #include <vnc_cfg_types.h>
      16             : #include <agent_types.h>
      17             : #include <ifmap/ifmap_link.h>
      18             : #include <ifmap/ifmap_node.h>
      19             : 
      20             : #include <oper/operdb_init.h>
      21             : #include <oper/peer.h>
      22             : #include <oper/vrf.h>
      23             : #include <oper/interface_common.h>
      24             : #include <oper/nexthop.h>
      25             : #include <oper/vn.h>
      26             : #include <oper/mirror_table.h>
      27             : #include <oper/vxlan.h>
      28             : #include <oper/mpls.h>
      29             : #include <oper/route_common.h>
      30             : #include <oper/ecmp_load_balance.h>
      31             : #include <oper/config_manager.h>
      32             : #include <oper/crypt_tunnel.h>
      33             : 
      34             : #include <oper/agent_route_walker.h>
      35             : #include <oper/agent_route_resync.h>
      36             : #include <oper/global_vrouter.h>
      37             : #include <vrouter/flow_stats/flow_stats_collector.h>
      38             : 
      39             : const std::string GlobalVrouter::kMetadataService = "metadata";
      40             : const std::string GlobalVrouter::kMetadataService6 = "metadata6";
      41             : const Ip4Address GlobalVrouter::kLoopBackIp = Ip4Address(0x7f000001);
      42             : 
      43           0 : static int ProtocolToString(const std::string proto) {
      44           0 :     if (proto == "TCP" || proto == "tcp") {
      45           0 :         return IPPROTO_TCP;
      46             :     }
      47             : 
      48           0 :     if (proto == "UDP" || proto == "udp") {
      49           0 :         return IPPROTO_UDP;
      50             :     }
      51             : 
      52           0 :     if (proto == "ICMP" || proto == "icmp") {
      53           0 :         return IPPROTO_ICMP;
      54             :     }
      55             : 
      56           0 :     if (proto == "SCTP" || proto == "sctp") {
      57           0 :         return IPPROTO_SCTP;
      58             :     }
      59             : 
      60           0 :     if (proto == "all") {
      61           0 :         return 0;
      62             :     }
      63             : 
      64           0 :     return atoi(proto.c_str());
      65             : }
      66             : 
      67          21 : void GlobalVrouter::UpdateFlowAging(autogen::GlobalVrouterConfig *cfg) {
      68          21 :     if (agent()->flow_stats_req_handler() == NULL) {
      69           0 :         return;
      70             :     }
      71             : 
      72             :     std::vector<autogen::FlowAgingTimeout>::const_iterator new_list_it =
      73          21 :         cfg->flow_aging_timeout_list().begin();
      74          21 :     FlowAgingTimeoutMap new_flow_aging_timeout_map;
      75             : 
      76          21 :     while (new_list_it != cfg->flow_aging_timeout_list().end()) {
      77           0 :         int proto = ProtocolToString(new_list_it->protocol);
      78           0 :         if (proto < 0 || proto > 0xFF) {
      79           0 :             new_list_it++;
      80           0 :             continue;
      81             :         }
      82           0 :         FlowAgingTimeoutKey key(proto, new_list_it->port);
      83           0 :         agent()->flow_stats_req_handler()(agent(), proto, new_list_it->port,
      84           0 :                                           new_list_it->timeout_in_seconds);
      85             : 
      86           0 :         flow_aging_timeout_map_.erase(key);
      87           0 :         new_flow_aging_timeout_map.insert(
      88           0 :                 FlowAgingTimeoutPair(key, new_list_it->timeout_in_seconds));
      89           0 :         new_list_it++;
      90             :     }
      91             : 
      92             :     FlowAgingTimeoutMap::const_iterator old_list_it =
      93          21 :         flow_aging_timeout_map_.begin();
      94          21 :     while (old_list_it != flow_aging_timeout_map_.end()) {
      95           0 :         agent()->flow_stats_req_handler()(agent(), old_list_it->first.protocol,
      96           0 :                                           old_list_it->first.port, 0);
      97           0 :         old_list_it++;
      98             :     }
      99          21 :     flow_aging_timeout_map_ = new_flow_aging_timeout_map;
     100          21 : }
     101             : 
     102          11 : void GlobalVrouter::DeleteFlowAging() {
     103             : 
     104          11 :     if (agent()->flow_stats_req_handler() == NULL) {
     105           0 :         return;
     106             :     }
     107             : 
     108             :     FlowAgingTimeoutMap::const_iterator old_list_it =
     109          11 :         flow_aging_timeout_map_.begin();
     110          11 :     while (old_list_it != flow_aging_timeout_map_.end()) {
     111           0 :         agent()->flow_stats_req_handler()(agent(), old_list_it->first.protocol,
     112           0 :                                           old_list_it->first.port, 0);
     113           0 :         old_list_it++;
     114             :     }
     115          11 :     flow_aging_timeout_map_.clear();
     116             : }
     117             : 
     118          21 : void GlobalVrouter::UpdatePortConfig(autogen::GlobalVrouterConfig *cfg) {
     119          21 :     if (agent()->port_config_handler() == NULL) {
     120           0 :         return;
     121             :     }
     122             : 
     123          21 :     ProtocolPortSet new_protocol_port_set;
     124             :     std::vector<autogen::PortTranslationPool>::const_iterator new_list_it =
     125          21 :         cfg->port_translation_pools().begin();
     126          21 :     for (;new_list_it != cfg->port_translation_pools().end(); new_list_it++) {
     127           0 :         int proto = ProtocolToString(new_list_it->protocol);
     128           0 :         if (proto < 0 || proto > 0xFF) {
     129           0 :             new_list_it++;
     130           0 :             continue;
     131             :         }
     132             : 
     133           0 :         if (proto != IPPROTO_TCP && proto != IPPROTO_UDP) {
     134           0 :             continue;
     135             :         }
     136             : 
     137           0 :         uint16_t port_count = 0;
     138           0 :         std::stringstream str(new_list_it->port_count);
     139           0 :         str >> port_count;
     140             : 
     141           0 :         protocol_port_set_.erase(proto);
     142           0 :         if (new_list_it->port_range.start_port != 0 &&
     143           0 :                 new_list_it->port_range.end_port != 0) {
     144           0 :             PortConfig::PortRange range(new_list_it->port_range.start_port,
     145           0 :                                         new_list_it->port_range.end_port);
     146           0 :             new_protocol_port_set[proto].port_range.push_back(range);
     147           0 :         } else if (port_count != 0) {
     148           0 :             new_protocol_port_set[proto].port_count = port_count;
     149             :         }
     150           0 :     }
     151             : 
     152             :     struct rlimit rl;
     153          21 :     int result = getrlimit(RLIMIT_NOFILE, &rl);
     154          21 :     int avail_count = 0;
     155          21 :     if (result == 0) {
     156          21 :         avail_count = rl.rlim_max - Agent::kMaxOtherOpenFds;
     157          21 :         if (avail_count < 0) {
     158           0 :             avail_count = 0;
     159             :         }
     160             :     }
     161             : 
     162             : 
     163          21 :     ProtocolPortSet::const_iterator old_list_it = protocol_port_set_.begin();
     164          21 :     for (; old_list_it != protocol_port_set_.end(); old_list_it++) {
     165           0 :         PortConfig pc;
     166           0 :         agent()->port_config_handler()(agent(), old_list_it->first, &pc);
     167           0 :     }
     168             : 
     169          21 :     int total_port_count = 0;
     170          21 :     ProtocolPortSet::iterator pc_list_it = new_protocol_port_set.begin();
     171          21 :     for (; pc_list_it != new_protocol_port_set.end(); pc_list_it++) {
     172           0 :         pc_list_it->second.Trim();
     173           0 :         total_port_count += pc_list_it->second.port_count;
     174             :     }
     175             : 
     176          21 :     float avail_percent = 1;
     177          21 :     if (total_port_count > avail_count) {
     178           0 :         avail_percent = (float)avail_count / (float)total_port_count;
     179             :     }
     180             : 
     181          21 :     pc_list_it = new_protocol_port_set.begin();
     182          21 :     for (; pc_list_it != new_protocol_port_set.end(); pc_list_it++) {
     183           0 :         pc_list_it->second.port_count *= avail_percent;
     184           0 :         agent()->port_config_handler()(agent(), pc_list_it->first,
     185           0 :                                        &(pc_list_it->second));
     186             :     }
     187             : 
     188          21 :     protocol_port_set_ = new_protocol_port_set;
     189          21 : }
     190             : 
     191          11 : void GlobalVrouter::DeletePortConfig() {
     192          11 :     ProtocolPortSet::const_iterator it = protocol_port_set_.begin();
     193          11 :     for (; it != protocol_port_set_.end(); it++) {
     194           0 :         PortConfig pc;
     195           0 :         agent()->port_config_handler()(agent(), it->first, &pc);
     196           0 :     }
     197             : 
     198          11 :     protocol_port_set_.clear();
     199          11 : }
     200             : 
     201          21 : void GlobalVrouter::ReadFlowsLimits(const autogen::GlobalVrouterConfig &cfg) {
     202             :     uint32_t max_vm_flows_percent;
     203             :     uint32_t global_max_vmi_flows;
     204          21 :     if (cfg.IsPropertySet(autogen::GlobalVrouterConfig::MAX_VM_FLOWS_PERCENT)) {
     205           0 :         max_vm_flows_percent = cfg.max_vm_flows_percent();
     206             :     } else {
     207          21 :         max_vm_flows_percent = FLOWS_LIMIT_UNLIMITED;
     208             :     }
     209          21 :     if (cfg.IsPropertySet(autogen::GlobalVrouterConfig::GLOBAL_MAX_VMI_FLOWS)) {
     210           0 :         global_max_vmi_flows = cfg.global_max_vmi_flows();
     211             :     } else {
     212          21 :         global_max_vmi_flows = FLOWS_LIMIT_UNLIMITED;
     213             :     }
     214          21 :     Agent *agent = this->agent();
     215          21 :     agent->set_max_vm_flows_perc(max_vm_flows_percent);
     216          21 :     agent->set_global_max_vmi_flows(global_max_vmi_flows);
     217          21 :     agent->update_max_vm_flows(agent->flow_table_size());
     218          21 : }
     219             : 
     220             : ////////////////////////////////////////////////////////////////////////////////
     221             : 
     222             : // Link local service
     223           0 : GlobalVrouter::LinkLocalService::LinkLocalService(
     224             :                          const std::string &service_name,
     225             :                          const std::string &fabric_dns_name,
     226             :                          const std::vector<Ip4Address> &fabric_ip,
     227           0 :                          uint16_t fabric_port)
     228           0 :     : linklocal_service_name(service_name),
     229           0 :       ipfabric_dns_service_name(fabric_dns_name),
     230           0 :       ipfabric_service_ip(fabric_ip),
     231           0 :       ipfabric_service_port(fabric_port) {
     232           0 : }
     233             : 
     234           0 : bool GlobalVrouter::LinkLocalService::operator==(
     235             :                     const LinkLocalService &rhs) const {
     236           0 :     if (linklocal_service_name == rhs.linklocal_service_name &&
     237           0 :         ipfabric_dns_service_name == rhs.ipfabric_dns_service_name &&
     238           0 :         ipfabric_service_ip == rhs.ipfabric_service_ip &&
     239           0 :         ipfabric_service_port == rhs.ipfabric_service_port)
     240           0 :         return true;
     241           0 :     return false;
     242             : }
     243             : 
     244           0 : bool GlobalVrouter::LinkLocalService::IsAddressInUse(const Ip4Address &ip) const {
     245           0 :      BOOST_FOREACH(Ip4Address ipfabric_addr, ipfabric_service_ip) {
     246           0 :          if (ipfabric_addr == ip)
     247           0 :              return true;
     248             :     }
     249           0 :     return false;
     250             : }
     251             : 
     252           0 : bool GlobalVrouter::LinkLocalServiceKey::operator<(
     253             :                     const LinkLocalServiceKey &rhs) const {
     254           0 :     if (linklocal_service_ip != rhs.linklocal_service_ip)
     255           0 :         return linklocal_service_ip < rhs.linklocal_service_ip;
     256           0 :     return linklocal_service_port < rhs.linklocal_service_port;
     257             : }
     258             : 
     259             : ////////////////////////////////////////////////////////////////////////////////
     260             : 
     261             : // Async resolve DNS names (used to resolve names given in linklocal config)
     262             : class GlobalVrouter::FabricDnsResolver {
     263             : public:
     264             :     typedef boost::asio::ip::udp boost_udp;
     265             :     static const uint32_t kDnsTimeout = 15 * 60 * 1000; // fifteen minutes
     266             : 
     267           2 :     FabricDnsResolver(GlobalVrouter *vrouter, boost::asio::io_service &io)
     268           4 :         : request_count_(0), response_count_(0), global_vrouter_(vrouter),
     269           2 :         io_(io) {
     270             :         // start timer to re-resolve the DNS names to IP addresses
     271           2 :         timer_ = TimerManager::CreateTimer(io_, "DnsHandlerTimer");
     272           2 :         timer_->Start(kDnsTimeout,
     273             :                       boost::bind(&GlobalVrouter::FabricDnsResolver::OnTimeout, this));
     274           2 :     }
     275           4 :     virtual ~FabricDnsResolver() {
     276           2 :         timer_->Cancel();
     277           2 :         TimerManager::DeleteTimer(timer_);
     278           4 :     }
     279             : 
     280             :     // Called in DB context, gives the list of names to be resolved
     281          32 :     void ResolveList(const std::vector<std::string> &name_list) {
     282          32 :         std::vector<Ip4Address> empty_addr_list;
     283          32 :         ResolveMap new_addr_map;
     284          32 :         std::scoped_lock lock(mutex_);
     285          32 :         BOOST_FOREACH(std::string name, name_list) {
     286           0 :             ResolveName(name);
     287           0 :             ResolveMap::iterator it = address_map_.find(name);
     288           0 :             if (it != address_map_.end()) {
     289           0 :                 new_addr_map.insert(ResolvePair(name, it->second));
     290           0 :                 address_map_.erase(it);
     291             :             } else {
     292           0 :                 new_addr_map.insert(ResolvePair(name, empty_addr_list));
     293             :             }
     294           0 :         }
     295          32 :         address_map_.swap(new_addr_map);
     296          32 :     }
     297             : 
     298             :     // Called from client tasks to resolve name to address
     299           0 :     bool Resolve(const std::string &name, Ip4Address *address) {
     300           0 :         std::scoped_lock lock(mutex_);
     301           0 :         ResolveMap::iterator it = address_map_.find(name);
     302           0 :         if (it != address_map_.end() && it->second.size()) {
     303           0 :             int index = rand() % it->second.size();
     304           0 :             *address = it->second[index];
     305           0 :             if (*address == kLoopBackIp) {
     306           0 :                 *address = global_vrouter_->agent()->router_id();
     307             :             }
     308           0 :             return true;
     309             :         }
     310           0 :         return false;
     311           0 :     }
     312             : 
     313             :     // Timer handler; re-resolve all DNS names
     314           0 :     bool OnTimeout() {
     315           0 :         std::scoped_lock lock(mutex_);
     316           0 :         for (ResolveMap::const_iterator it = address_map_.begin();
     317           0 :              it != address_map_.end(); ++it) {
     318           0 :             ResolveName(it->first);
     319             :         }
     320           0 :         return true;
     321           0 :     }
     322             : 
     323             :     // Called in DB context
     324           0 :     bool IsAddressInUse(const Ip4Address &ip) {
     325           0 :         std::scoped_lock lock(mutex_);
     326           0 :         for (ResolveMap::const_iterator it = address_map_.begin();
     327           0 :              it != address_map_.end(); ++it) {
     328           0 :             BOOST_FOREACH(Ip4Address address, it->second) {
     329           0 :                 if (address == ip)
     330           0 :                     return true;
     331             :             }
     332             :         }
     333           0 :         return false;
     334           0 :     }
     335             : 
     336           0 :     uint64_t PendingRequests() const {
     337           0 :         return request_count_ - response_count_;
     338             :     }
     339             : 
     340             : private:
     341             :     typedef std::map<std::string, std::vector<Ip4Address> > ResolveMap;
     342             :     typedef std::pair<std::string, std::vector<Ip4Address> > ResolvePair;
     343             : 
     344           0 :     void ResolveName(const std::string &name) {
     345           0 :         boost_udp::resolver *resolver = new boost_udp::resolver(io_);
     346             : 
     347           0 :         resolver->async_resolve(
     348           0 :             boost_udp::resolver::query(boost_udp::v4(), name, "domain"),
     349           0 :             boost::bind(&GlobalVrouter::FabricDnsResolver::ResolveHandler, this,
     350             :                         _1, _2, name, resolver));
     351           0 :         request_count_++;
     352           0 :     }
     353             : 
     354             :     // called in asio context, handle resolve response
     355           0 :     void ResolveHandler(const boost::system::error_code& error,
     356             :                         boost_udp::resolver::iterator resolve_it,
     357             :                         std::string &name, boost_udp::resolver *resolver) {
     358           0 :         std::vector<Ip4Address> old_list;
     359           0 :         ResolveMap::iterator addr_it;
     360           0 :         std::scoped_lock lock(mutex_);
     361           0 :         addr_it = address_map_.find(name);
     362           0 :         if (addr_it != address_map_.end()) {
     363           0 :             old_list.swap(addr_it->second);
     364           0 :             if (!error) {
     365           0 :                 boost_udp::resolver::iterator end;
     366           0 :                 while (resolve_it != end) {
     367           0 :                     boost_udp::endpoint ep = *resolve_it;
     368           0 :                     addr_it->second.push_back(ep.address().to_v4());
     369           0 :                     resolve_it++;
     370             :                 }
     371           0 :             }
     372           0 :             global_vrouter_->LinkLocalRouteUpdate(addr_it->second);
     373             :         }
     374           0 :         response_count_++;
     375           0 :         delete resolver;
     376           0 :     }
     377             : 
     378             :     Timer *timer_;
     379             :     std::mutex mutex_;
     380             :     ResolveMap address_map_;
     381             :     uint64_t request_count_;
     382             :     uint64_t response_count_;
     383             :     GlobalVrouter *global_vrouter_;
     384             :     boost::asio::io_service &io_;
     385             : };
     386             : 
     387             : ////////////////////////////////////////////////////////////////////////////////
     388             : 
     389             : // Add / delete routes to ip fabric servers used for link local services
     390             : // Also, add / delete receive routes for link local addresses in different VRFs
     391             : class GlobalVrouter::LinkLocalRouteManager {
     392             : public:
     393           2 :     LinkLocalRouteManager(GlobalVrouter *vrouter)
     394           2 :         : global_vrouter_(vrouter), vn_id_(DBTableBase::kInvalidId){
     395           2 :     }
     396             : 
     397           4 :     virtual ~LinkLocalRouteManager() {
     398           2 :         DeleteDBClients();
     399           2 :         ipfabric_address_list_.clear();
     400           2 :         linklocal_address_list_.clear();
     401           4 :     }
     402             : 
     403             :     void CreateDBClients();
     404             :     void DeleteDBClients();
     405             :     void AddArpRoute(const Ip4Address &srv);
     406             :     void UpdateAllVns(const LinkLocalServiceKey &key, bool is_add);
     407             : 
     408             : private:
     409             :     bool VnUpdateWalk(DBEntryBase *entry, const LinkLocalServiceKey key,
     410             :                       bool is_add);
     411             :     void VnWalkDone(DBTable::DBTableWalkRef ref);
     412             :     bool VnNotify(DBTablePartBase *partition, DBEntryBase *entry);
     413             : 
     414             :     GlobalVrouter *global_vrouter_;
     415             :     DBTableBase::ListenerId vn_id_;
     416             :     std::set<Ip4Address> ipfabric_address_list_;
     417             :     std::set<IpAddress> linklocal_address_list_;
     418             : };
     419             : 
     420           2 : void GlobalVrouter::LinkLocalRouteManager::CreateDBClients() {
     421           2 :     vn_id_ = global_vrouter_->agent()->vn_table()->Register(
     422             :              boost::bind(&GlobalVrouter::LinkLocalRouteManager::VnNotify,
     423             :                          this, _1, _2));
     424           2 : }
     425             : 
     426           2 : void GlobalVrouter::LinkLocalRouteManager::DeleteDBClients() {
     427           2 :     global_vrouter_->agent()->vn_table()->Unregister(vn_id_);
     428           2 : }
     429             : 
     430           0 : void GlobalVrouter::LinkLocalRouteManager::AddArpRoute(const Ip4Address &srv) {
     431           0 :     std::set<Ip4Address>::iterator it;
     432           0 :     std::pair<std::set<Ip4Address>::iterator, bool> ret;
     433             : 
     434           0 :     ret = ipfabric_address_list_.insert(srv);
     435           0 :     if (ret.second == false) {
     436           0 :         return;
     437             :     }
     438             : 
     439           0 :     Agent *agent = global_vrouter_->agent();
     440           0 :     VnListType vn_list;
     441           0 :     vn_list.insert(agent->fabric_vn_name());
     442           0 :     InetUnicastAgentRouteTable::CheckAndAddArpReq(agent->fabric_vrf_name(),
     443             :                                                   srv, agent->vhost_interface(),
     444           0 :                                                   vn_list, SecurityGroupList(),
     445           0 :                                                   TagList());
     446           0 : }
     447             : 
     448             : // Walk thru all the VNs
     449           0 : void GlobalVrouter::LinkLocalRouteManager::UpdateAllVns(
     450             :                     const LinkLocalServiceKey &key, bool is_add) {
     451           0 :     if (is_add) {
     452           0 :         if (!linklocal_address_list_.insert(key.linklocal_service_ip).second)
     453           0 :             return;
     454             :     } else {
     455           0 :         if (!linklocal_address_list_.erase(key.linklocal_service_ip))
     456           0 :             return;
     457             :     }
     458             :     // This walker allocation has to be done everytime as function argument
     459             :     // takes key and is_add which keeps varying. So boost bind needs to be
     460             :     // redone.
     461             :     // Also thats the reason why previous walk is also not stopped and it runs
     462             :     // to completion.
     463             :     // TODO: Evaluate if this can be optimized
     464             :     DBTable::DBTableWalkRef walk_ref =
     465           0 :         global_vrouter_->agent()->vn_table()->AllocWalker(
     466           0 :                boost::bind(&GlobalVrouter::LinkLocalRouteManager::VnUpdateWalk,
     467             :                            this, _2, key, is_add),
     468             :                boost::bind(&GlobalVrouter::LinkLocalRouteManager::VnWalkDone,
     469           0 :                            this, _1));
     470           0 :     global_vrouter_->agent()->vn_table()->WalkAgain(walk_ref);
     471           0 : }
     472             : 
     473             : // Vn Walk method
     474             : // For each Vn, add or delete receive route for the specified linklocal service
     475           0 : bool GlobalVrouter::LinkLocalRouteManager::VnUpdateWalk(
     476             :     DBEntryBase *entry, const LinkLocalServiceKey key, bool is_add) {
     477             : 
     478           0 :     VnEntry *vn_entry = static_cast<VnEntry *>(entry);
     479           0 :     if (vn_entry->IsDeleted()) {
     480           0 :         return true;
     481             :     }
     482             : 
     483           0 :     VrfEntry *vrf_entry = vn_entry->GetVrf();
     484           0 :     if (!vrf_entry) {
     485           0 :         return true;
     486             :     }
     487             : 
     488           0 :     Agent *agent = global_vrouter_->agent();
     489             :     // Do not create the routes for the default VRF
     490           0 :     if (agent->fabric_vrf_name() == vrf_entry->GetName()) {
     491           0 :         return true;
     492             :     }
     493             : 
     494             :     InetUnicastAgentRouteTable *rt_table =
     495           0 :         vrf_entry->GetInetUnicastRouteTable(key.linklocal_service_ip);
     496             : 
     497             :     LinkLocalDBState *state = static_cast<LinkLocalDBState *>
     498           0 :         (vn_entry->GetState(vn_entry->get_table_partition()->parent(), vn_id_));
     499           0 :     if (!state) {
     500           0 :         return true;
     501             :     }
     502             : 
     503           0 :     if (is_add) {
     504           0 :         if (vn_entry->layer3_forwarding()) {
     505           0 :             state->Add(key.linklocal_service_ip);
     506             :             VmInterfaceKey vmi_key(AgentKey::ADD_DEL_CHANGE,
     507           0 :                                    boost::uuids::nil_uuid(),
     508           0 :                                    agent->vhost_interface_name());
     509             : 
     510           0 :             rt_table->AddVHostRecvRoute(agent->link_local_peer(),
     511             :                 vrf_entry->GetName(),
     512             :                 vmi_key,
     513           0 :                 key.linklocal_service_ip,
     514           0 :                 key.linklocal_service_ip.is_v4() ? 32 : 128,
     515             :                 vn_entry->GetName(),
     516             :                 true, false, false);
     517           0 :         }
     518             :     } else {
     519           0 :         state->Delete(key.linklocal_service_ip);
     520           0 :         rt_table->DeleteReq(agent->link_local_peer(), vrf_entry->GetName(),
     521           0 :             key.linklocal_service_ip,
     522           0 :             key.linklocal_service_ip.is_v4() ? 32 : 128, NULL);
     523             :     }
     524           0 :     return true;
     525             : }
     526             : 
     527             : void
     528           0 : GlobalVrouter::LinkLocalRouteManager::VnWalkDone(DBTable::DBTableWalkRef ref) {
     529           0 :     global_vrouter_->agent()->vn_table()->ReleaseWalker(ref);
     530           0 : }
     531             : 
     532             : // VN notify handler
     533          61 : bool GlobalVrouter::LinkLocalRouteManager::VnNotify(DBTablePartBase *partition,
     534             :                                                     DBEntryBase *entry) {
     535          61 :     VnEntry *vn_entry = static_cast<VnEntry *>(entry);
     536          61 :     VrfEntry *vrf_entry = vn_entry->GetVrf();
     537          61 :     Agent *agent = global_vrouter_->agent();
     538          61 :     if (vn_entry->IsDeleted() || !vn_entry->layer3_forwarding() || !vrf_entry) {
     539             :         LinkLocalDBState *state = static_cast<LinkLocalDBState *>
     540          44 :             (vn_entry->GetState(partition->parent(), vn_id_));
     541          44 :         if (!state)
     542          27 :             return true;
     543          17 :         for (std::set<IpAddress>::const_iterator it =
     544          34 :              state->addresses_.begin(); it != state->addresses_.end(); ++it) {
     545             :             InetUnicastAgentRouteTable *rt_table =
     546           0 :                 state->vrf_->GetInetUnicastRouteTable(*it);
     547           0 :             rt_table->DeleteReq(agent->link_local_peer(),
     548           0 :                 state->vrf_->GetName(), *it, it->is_v4() ? 32 : 128, NULL);
     549             :         }
     550          17 :         vn_entry->ClearState(partition->parent(), vn_id_);
     551          17 :         delete state;
     552          17 :         return true;
     553             :     }
     554             : 
     555             :     // Do not create the routes for the default VRF
     556          17 :     if (agent->fabric_vrf_name() == vrf_entry->GetName()) {
     557           0 :         return true;
     558             :     }
     559             : 
     560          17 :     if (vn_entry->layer3_forwarding()) {
     561          17 :         if (vn_entry->GetState(partition->parent(), vn_id_))
     562           0 :             return true;
     563          17 :         LinkLocalDBState *state = new LinkLocalDBState(vrf_entry);
     564          17 :         vn_entry->SetState(partition->parent(), vn_id_, state);
     565          17 :         InetUnicastAgentRouteTable *rt_table = NULL;
     566             :         const GlobalVrouter::LinkLocalServicesMap &services =
     567          17 :                    global_vrouter_->linklocal_services_map();
     568          17 :         for (GlobalVrouter::LinkLocalServicesMap::const_iterator it =
     569          34 :                 services.begin(); it != services.end(); ++it) {
     570             :             VmInterfaceKey key(AgentKey::ADD_DEL_CHANGE,
     571           0 :                                boost::uuids::nil_uuid(),
     572           0 :                                agent->vhost_interface_name());
     573             :             rt_table =
     574           0 :                 vrf_entry->GetInetUnicastRouteTable(it->first.linklocal_service_ip);
     575           0 :             state->Add(it->first.linklocal_service_ip);
     576           0 :             rt_table->AddVHostRecvRoute(agent->link_local_peer(),
     577             :                 vrf_entry->GetName(),
     578             :                 key,
     579           0 :                 it->first.linklocal_service_ip,
     580           0 :                 it->first.linklocal_service_ip.is_v4() ? 32 : 128,
     581             :                 vn_entry->GetName(),
     582             :                 true, false, false);
     583           0 :         }
     584             :     }
     585          17 :     return true;
     586             : }
     587             : 
     588             : ////////////////////////////////////////////////////////////////////////////////
     589             : 
     590           2 : GlobalVrouter::GlobalVrouter(Agent *agent) :
     591           2 :     OperIFMapTable(agent), linklocal_services_map_(),
     592           2 :     crypt_tunnels_map_(), crypt_mode_(CRYPT_NONE),
     593           2 :     linklocal_route_mgr_(new LinkLocalRouteManager(this)),
     594           2 :     fabric_dns_resolver_(new FabricDnsResolver
     595           2 :                          (this, *(agent->event_manager()->io_service()))),
     596           2 :     forwarding_mode_(Agent::L2_L3), flow_export_rate_(kDefaultFlowExportRate),
     597           2 :     ecmp_load_balance_(), configured_(false),
     598           6 :     slo_uuid_(boost::uuids::nil_uuid()) {
     599             :         agent_route_resync_walker_.reset
     600           2 :             (new AgentRouteResync("GlobalVrouterRouteWalker", agent));
     601             :         agent->oper_db()->agent_route_walk_manager()->
     602           2 :             RegisterWalker(static_cast<AgentRouteWalker *>
     603             :                            (agent_route_resync_walker_.get()));
     604           2 :     }
     605             : 
     606           4 : GlobalVrouter::~GlobalVrouter() {
     607             :     agent()->oper_db()->agent_route_walk_manager()->
     608           2 :         ReleaseWalker(agent_route_resync_walker_.get());
     609           4 : }
     610             : 
     611             : 
     612           0 : uint64_t GlobalVrouter::PendingFabricDnsRequests() const {
     613           0 :     return fabric_dns_resolver_.get()->PendingRequests();
     614             : }
     615             : 
     616           2 : void GlobalVrouter::CreateDBClients() {
     617           2 :     linklocal_route_mgr_->CreateDBClients();
     618           2 : }
     619             : 
     620          11 : void GlobalVrouter::ConfigDelete(IFMapNode *node) {
     621          11 :     GlobalVrouterConfig(node);
     622          11 :     configured_ = false;
     623          11 :     agent()->connection_state()->Update();
     624          11 :     return;
     625             : }
     626             : 
     627          21 : void GlobalVrouter::ConfigAddChange(IFMapNode *node) {
     628          21 :     GlobalVrouterConfig(node);
     629          21 :     configured_ = true;
     630          21 :     agent()->connection_state()->Update();
     631          21 :     return;
     632             : }
     633             : 
     634          21 : void GlobalVrouter::ConfigManagerEnqueue(IFMapNode *node) {
     635          21 :     agent()->config_manager()->AddGlobalVrouterNode(node);
     636          21 : }
     637             : 
     638          21 : void GlobalVrouter::UpdateSLOConfig(IFMapNode *node) {
     639          21 :     IFMapAgentTable *table = static_cast<IFMapAgentTable *>(node->table());
     640          21 :     DBGraph *graph = table->GetGraph();
     641          21 :     for (DBGraphVertex::adjacency_iterator iter = node->begin(graph);
     642          21 :          iter != node->end(table->GetGraph()); ++iter) {
     643             : 
     644           0 :         IFMapNode *adj_node = static_cast<IFMapNode *>(iter.operator->());
     645           0 :         if (agent()->config_manager()->SkipNode(adj_node)) {
     646           0 :             continue;
     647             :         }
     648             : 
     649           0 :         if (adj_node->table() == agent()->cfg()->cfg_slo_table()) {
     650             :             autogen::SecurityLoggingObject *slo =
     651             :                 static_cast<autogen::SecurityLoggingObject *>(adj_node->
     652           0 :                                                               GetObject());
     653           0 :             autogen::IdPermsType id_perms = slo->id_perms();
     654           0 :             CfgUuidSet(id_perms.uuid.uuid_mslong, id_perms.uuid.uuid_lslong,
     655           0 :                        slo_uuid_);
     656           0 :         }
     657             :     }
     658          21 : }
     659             : 
     660             : // Handle incoming global vrouter configuration
     661          32 : void GlobalVrouter::GlobalVrouterConfig(IFMapNode *node) {
     662          32 :     Agent::VxLanNetworkIdentifierMode cfg_vxlan_network_identifier_mode =
     663             :                                             Agent::AUTOMATIC;
     664          32 :     bool resync_vn = false; //resync_vn walks internally calls VMI walk.
     665          32 :     bool resync_route = false;
     666             : 
     667          32 :     if (node->IsDeleted() == false) {
     668          21 :         UpdateSLOConfig(node);
     669             : 
     670             :         autogen::GlobalVrouterConfig *cfg =
     671          21 :             static_cast<autogen::GlobalVrouterConfig *>(node->GetObject());
     672             : 
     673          21 :         agent()->set_global_slo_status(cfg->enable_security_logging());
     674             : 
     675             :         resync_route =
     676          21 :             TunnelType::EncapPrioritySync(cfg->encapsulation_priorities());
     677          21 :         if (cfg->vxlan_network_identifier_mode() == "configured") {
     678           0 :             cfg_vxlan_network_identifier_mode = Agent::CONFIGURED;
     679             :         }
     680          21 :         UpdateLinkLocalServiceConfig(cfg->linklocal_services());
     681          21 :         UpdateCryptTunnelEndpointConfig(cfg->encryption_tunnel_endpoints(),
     682          21 :                                         cfg->encryption_mode());
     683             : 
     684             :         //Take the forwarding mode if its set, else fallback to l2_l3.
     685             :         Agent::ForwardingMode new_forwarding_mode =
     686          21 :             agent()->TranslateForwardingMode(cfg->forwarding_mode());
     687          21 :         if (new_forwarding_mode != forwarding_mode_) {
     688           2 :             forwarding_mode_ = new_forwarding_mode;
     689           2 :             resync_route = true;
     690           2 :             resync_vn = true;
     691             :         }
     692          21 :         if (cfg->IsPropertySet
     693          21 :                 (autogen::GlobalVrouterConfig::FLOW_EXPORT_RATE)) {
     694           1 :             flow_export_rate_ = cfg->flow_export_rate();
     695             :         } else {
     696          20 :             flow_export_rate_ = kDefaultFlowExportRate;
     697             :         }
     698          21 :         UpdateFlowAging(cfg);
     699          21 :         UpdatePortConfig(cfg);
     700          21 :         EcmpLoadBalance ecmp_load_balance;
     701          21 :         if (cfg->ecmp_hashing_include_fields().hashing_configured) {
     702           0 :             ecmp_load_balance.UpdateFields(cfg->
     703           0 :                                            ecmp_hashing_include_fields());
     704             :         }
     705          21 :         if (ecmp_load_balance_ != ecmp_load_balance) {
     706           0 :             ecmp_load_balance_ = ecmp_load_balance;
     707           0 :             resync_vn = true;
     708             :         }
     709          21 :         ReadFlowsLimits(*cfg);
     710          21 :     } else {
     711          11 :         DeleteLinkLocalServiceConfig();
     712          11 :         TunnelType::DeletePriorityList();
     713          11 :         resync_route = true;
     714          11 :         flow_export_rate_ = kDefaultFlowExportRate;
     715          11 :         DeleteFlowAging();
     716          11 :         DeletePortConfig();
     717             :     }
     718             : 
     719          32 :     if (cfg_vxlan_network_identifier_mode !=
     720          32 :         agent()->vxlan_network_identifier_mode()) {
     721             :         agent()->set_vxlan_network_identifier_mode
     722           0 :             (cfg_vxlan_network_identifier_mode);
     723           0 :         resync_vn = true;
     724             :     }
     725             : 
     726             :     //Rebakes
     727          32 :     if (resync_route) {
     728             :         //Resync vm_interfaces to handle ethernet tag change if vxlan changed to
     729             :         //mpls or vice versa.
     730             :         //Update all routes irrespectively as this will handle change of
     731             :         //priority between MPLS-UDP to MPLS-GRE and vice versa.
     732          23 :         ResyncRoutes();
     733          23 :         resync_vn = true;
     734             :     }
     735             : 
     736             :     //Rebakes VN and then all interfaces.
     737          32 :     if (resync_vn)
     738          23 :         agent()->vn_table()->GlobalVrouterConfigChanged();
     739          32 : }
     740             : 
     741             : // Get link local service configuration info, for a given service name
     742           0 : bool GlobalVrouter::FindLinkLocalService(const std::string &service_name,
     743             :                                          IpAddress *service_ip,
     744             :                                          uint16_t *service_port,
     745             :                                          std::string *fabric_hostname,
     746             :                                          Ip4Address *fabric_ip,
     747             :                                          uint16_t *fabric_port) const {
     748           0 :     std::string name = boost::to_lower_copy(service_name);
     749             : 
     750           0 :     for (GlobalVrouter::LinkLocalServicesMap::const_iterator it =
     751           0 :          linklocal_services_map_.begin();
     752           0 :          it != linklocal_services_map_.end(); ++it) {
     753           0 :         if (it->second.linklocal_service_name == name) {
     754           0 :             *service_ip = it->first.linklocal_service_ip;
     755           0 :             *service_port = it->first.linklocal_service_port;
     756           0 :             *fabric_port = it->second.ipfabric_service_port;
     757           0 :             *fabric_hostname = it->second.ipfabric_dns_service_name;
     758           0 :             if (it->second.ipfabric_service_ip.size()) {
     759             :                 // if there are multiple addresses, return one of them
     760           0 :                 int index = rand() % it->second.ipfabric_service_ip.size();
     761           0 :                 *fabric_ip = it->second.ipfabric_service_ip[index];
     762           0 :                 if (*fabric_ip == kLoopBackIp) {
     763           0 :                     *fabric_ip = agent()->router_id();
     764             :                 }
     765           0 :                 if (it->second.ipfabric_dns_service_name.empty())
     766           0 :                     *fabric_hostname = fabric_ip->to_string();
     767           0 :                 return true;
     768           0 :             } else if (!it->second.ipfabric_dns_service_name.empty()) {
     769           0 :                 return fabric_dns_resolver_->Resolve(
     770           0 :                        it->second.ipfabric_dns_service_name, fabric_ip);
     771             :             }
     772             :         }
     773             :     }
     774           0 :     return false;
     775           0 : }
     776             : 
     777             : // Get link local service info for a given linklocal service <ip, port>
     778          18 : bool GlobalVrouter::FindLinkLocalService(const IpAddress &service_ip,
     779             :                                          uint16_t service_port,
     780             :                                          std::string *service_name,
     781             :                                          Ip4Address *fabric_ip,
     782             :                                          uint16_t *fabric_port) const {
     783             :     LinkLocalServicesMap::const_iterator it =
     784          18 :         linklocal_services_map_.find(LinkLocalServiceKey(service_ip,
     785             :                                                          service_port));
     786          18 :     if (it == linklocal_services_map_.end()) {
     787             : #if 0
     788             :         if (!service_port) {
     789             :             // to support ping to metadata address
     790             :             IpAddress metadata_service_ip;
     791             :             Ip4Address metadata_fabric_ip;
     792             :             uint16_t metadata_service_port, metadata_fabric_port;
     793             :             if (FindLinkLocalService(GlobalVrouter::kMetadataService,
     794             :                                      &metadata_service_ip,
     795             :                                      &metadata_service_port,
     796             :                                      &metadata_fabric_ip,
     797             :                                      &metadata_fabric_port) &&
     798             :                 service_ip == metadata_service_ip) {
     799             :                 *fabric_port = agent()->metadata_server_port();
     800             :                 *fabric_ip = agent()->router_id();
     801             :                 return true;
     802             :             }
     803             :         }
     804             : #endif
     805          18 :         return false;
     806             :     }
     807             : 
     808           0 :     *service_name = it->second.linklocal_service_name;
     809           0 :     if (service_name->find(GlobalVrouter::kMetadataService)
     810           0 :         != std::string::npos) {
     811             :         // for metadata, return vhost0 ip and HTTP proxy port
     812           0 :         *fabric_port = agent()->metadata_server_port();
     813           0 :         *fabric_ip = agent()->router_id();
     814           0 :         return true;
     815             :     }
     816             : 
     817           0 :     *fabric_port = it->second.ipfabric_service_port;
     818             :     // if there are multiple addresses, return one of them
     819           0 :     if (it->second.ipfabric_service_ip.size()) {
     820           0 :         int index = rand() % it->second.ipfabric_service_ip.size();
     821           0 :         *fabric_ip = it->second.ipfabric_service_ip[index];
     822           0 :         if (*fabric_ip == kLoopBackIp) {
     823           0 :             *fabric_ip = agent()->router_id();
     824             :         }
     825           0 :         return true;
     826           0 :     } else if (!it->second.ipfabric_dns_service_name.empty()) {
     827           0 :         return fabric_dns_resolver_->Resolve(
     828           0 :                it->second.ipfabric_dns_service_name, fabric_ip);
     829             :     }
     830           0 :     return false;
     831             : }
     832             : 
     833             : // Get link local services, for a given service name
     834           0 : bool GlobalVrouter::FindLinkLocalService(const std::string &service_name,
     835             :                                          std::set<IpAddress> *service_ip
     836             :                                         ) const {
     837           0 :     if (service_name.empty())
     838           0 :         return false;
     839             : 
     840           0 :     std::string name = boost::to_lower_copy(service_name);
     841           0 :     for (GlobalVrouter::LinkLocalServicesMap::const_iterator it =
     842           0 :          linklocal_services_map_.begin();
     843           0 :          it != linklocal_services_map_.end(); ++it) {
     844           0 :         if (it->second.linklocal_service_name == name) {
     845           0 :             service_ip->insert(it->first.linklocal_service_ip);
     846             :         }
     847             :     }
     848             : 
     849           0 :     return (service_ip->size() > 0);
     850           0 : }
     851             : 
     852             : // Get link local services info for a given linklocal service <ip>
     853           0 : bool GlobalVrouter::FindLinkLocalService(const IpAddress &service_ip,
     854             :                                          std::set<std::string> *service_names
     855             :                                         ) const {
     856             :     LinkLocalServicesMap::const_iterator it =
     857           0 :         linklocal_services_map_.lower_bound(LinkLocalServiceKey(service_ip, 0));
     858             : 
     859           0 :     while (it != linklocal_services_map_.end() &&
     860           0 :            it->first.linklocal_service_ip == service_ip) {
     861           0 :         service_names->insert(it->second.linklocal_service_name);
     862           0 :         it++;
     863             :     }
     864             : 
     865           0 :     return (service_names->size() > 0);
     866             : }
     867             : 
     868             : // Handle changes to link local service configuration
     869          21 : void GlobalVrouter::UpdateLinkLocalServiceConfig(
     870             :     const LinkLocalServiceList &linklocal_list) {
     871             : 
     872          21 :     std::vector<std::string> dns_name_list;
     873          21 :     LinkLocalServicesMap linklocal_services_map;
     874          21 :     for (std::vector<autogen::LinklocalServiceEntryType>::const_iterator it =
     875          42 :          linklocal_list.begin(); it != linklocal_list.end(); it++) {
     876           0 :         boost::system::error_code ec;
     877           0 :         IpAddress llip = IpAddress::from_string(it->linklocal_service_ip, ec);
     878           0 :         std::vector<Ip4Address> fabric_ip;
     879           0 :         BOOST_FOREACH(std::string ip_fabric_ip, it->ip_fabric_service_ip) {
     880           0 :             Ip4Address ip = Ip4Address::from_string(ip_fabric_ip, ec);
     881           0 :             if (ec) continue;
     882           0 :             fabric_ip.push_back(ip);
     883           0 :         }
     884           0 :         std::string name = boost::to_lower_copy(it->linklocal_service_name);
     885           0 :         linklocal_services_map.insert(LinkLocalServicesPair(
     886           0 :             LinkLocalServiceKey(llip, it->linklocal_service_port),
     887           0 :             LinkLocalService(name, it->ip_fabric_DNS_service_name,
     888           0 :                              fabric_ip, it->ip_fabric_service_port)));
     889           0 :         if (!it->ip_fabric_DNS_service_name.empty())
     890           0 :             dns_name_list.push_back(it->ip_fabric_DNS_service_name);
     891           0 :     }
     892             : 
     893          21 :     linklocal_services_map_.swap(linklocal_services_map);
     894          21 :     fabric_dns_resolver_->ResolveList(dns_name_list);
     895          21 :     ChangeNotify(&linklocal_services_map, &linklocal_services_map_);
     896          21 : }
     897             : 
     898          11 : void GlobalVrouter::DeleteLinkLocalServiceConfig() {
     899          11 :     std::vector<std::string> dns_name_list;
     900          11 :     LinkLocalServicesMap linklocal_services_map;
     901             : 
     902          11 :     linklocal_services_map_.swap(linklocal_services_map);
     903          11 :     fabric_dns_resolver_->ResolveList(dns_name_list);
     904          11 :     ChangeNotify(&linklocal_services_map, &linklocal_services_map_);
     905          11 : }
     906             : 
     907             : // Identify linklocal service configuration changes from old to new
     908          32 : bool GlobalVrouter::ChangeNotify(LinkLocalServicesMap *old_value,
     909             :                                  LinkLocalServicesMap *new_value) {
     910          32 :     bool change = false;
     911          32 :     LinkLocalServicesMap::iterator it_old = old_value->begin();
     912          32 :     LinkLocalServicesMap::iterator it_new = new_value->begin();
     913          32 :     while (it_old != old_value->end() && it_new != new_value->end()) {
     914           0 :         if (it_old->first < it_new->first) {
     915             :             // old entry is deleted
     916           0 :             DeleteLinkLocalService(it_old);
     917           0 :             change = true;
     918           0 :             it_old++;
     919           0 :         } else if (it_new->first < it_old->first) {
     920             :             // new entry
     921           0 :             AddLinkLocalService(it_new);
     922           0 :             change = true;
     923           0 :             it_new++;
     924           0 :         } else if (it_new->second == it_old->second) {
     925             :             // no change in entry
     926           0 :             it_old++;
     927           0 :             it_new++;
     928             :         } else {
     929             :             // change in entry
     930           0 :             ChangeLinkLocalService(it_old, it_new);
     931           0 :             change = true;
     932           0 :             it_old++;
     933           0 :             it_new++;
     934             :         }
     935             :     }
     936             : 
     937             :     // delete remaining old entries
     938          32 :     for (; it_old != old_value->end(); ++it_old) {
     939           0 :         DeleteLinkLocalService(it_old);
     940           0 :         change = true;
     941             :     }
     942             : 
     943             :     // add remaining new entries
     944          32 :     for (; it_new != new_value->end(); ++it_new) {
     945           0 :         AddLinkLocalService(it_new);
     946           0 :         change = true;
     947             :     }
     948             : 
     949          32 :     return change;
     950             : }
     951             : 
     952             : // New link local service
     953           0 : void GlobalVrouter::AddLinkLocalService(
     954             :                     const LinkLocalServicesMap::iterator &it) {
     955           0 :     linklocal_route_mgr_->UpdateAllVns(it->first, true);
     956           0 :     BOOST_FOREACH(Ip4Address ip, it->second.ipfabric_service_ip) {
     957           0 :         linklocal_route_mgr_->AddArpRoute(ip);
     958             :     }
     959           0 : }
     960             : 
     961             : // Link local service deleted
     962           0 : void GlobalVrouter::DeleteLinkLocalService(
     963             :                     const LinkLocalServicesMap::iterator &it) {
     964           0 :     if (!IsLinkLocalAddressInUse(it->first.linklocal_service_ip))
     965           0 :         linklocal_route_mgr_->UpdateAllVns(it->first, false);
     966           0 : }
     967             : 
     968             : // Change in Link local service
     969           0 : void GlobalVrouter::ChangeLinkLocalService(
     970             :                     const LinkLocalServicesMap::iterator &old_it,
     971             :                     const LinkLocalServicesMap::iterator &new_it) {
     972           0 :     if (old_it->first.linklocal_service_ip !=
     973           0 :         new_it->first.linklocal_service_ip) {
     974           0 :         if (!IsLinkLocalAddressInUse(old_it->first.linklocal_service_ip))
     975           0 :             linklocal_route_mgr_->UpdateAllVns(old_it->first, false);
     976           0 :         linklocal_route_mgr_->UpdateAllVns(new_it->first, true);
     977             :     }
     978           0 :     LinkLocalRouteUpdate(new_it->second.ipfabric_service_ip);
     979           0 : }
     980             : 
     981           0 : void GlobalVrouter::LinkLocalRouteUpdate(
     982             :                     const std::vector<Ip4Address> &addr_list) {
     983           0 :     BOOST_FOREACH(Ip4Address ip, addr_list) {
     984           0 :         linklocal_route_mgr_->AddArpRoute(ip);
     985             :     }
     986           0 : }
     987             : 
     988           0 : bool GlobalVrouter::IsAddressInUse(const Ip4Address &ip) const {
     989           0 :     for (LinkLocalServicesMap::const_iterator it =
     990           0 :          linklocal_services_map_.begin(); it != linklocal_services_map_.end();
     991           0 :          ++it) {
     992           0 :         if (it->second.IsAddressInUse(ip))
     993           0 :             return true;
     994             :     }
     995           0 :     return fabric_dns_resolver_->IsAddressInUse(ip);
     996             : }
     997             : 
     998           0 : bool GlobalVrouter::IsLinkLocalAddressInUse(const IpAddress &ip) const {
     999           0 :     for (LinkLocalServicesMap::const_iterator it =
    1000           0 :          linklocal_services_map_.begin(); it != linklocal_services_map_.end();
    1001           0 :          ++it) {
    1002           0 :         if (it->first.linklocal_service_ip == ip)
    1003           0 :             return true;
    1004             :     }
    1005           0 :     return false;
    1006             : }
    1007             : 
    1008          23 : void GlobalVrouter::ResyncRoutes() {
    1009          23 :     (static_cast<AgentRouteResync *>(agent_route_resync_walker_.get()))->
    1010          23 :         Update();
    1011          23 : }
    1012             : 
    1013          41 : const EcmpLoadBalance &GlobalVrouter::ecmp_load_balance() const {
    1014          41 :     return ecmp_load_balance_;
    1015             : }
    1016             : 
    1017             : ////////////////////////////////////////////////////////////////////////////////
    1018             : 
    1019           0 : void LinkLocalServiceInfo::HandleRequest() const {
    1020           0 :     LinkLocalServiceResponse *resp = new LinkLocalServiceResponse();
    1021           0 :     std::vector<LinkLocalServiceData> linklocal_list;
    1022             :     const GlobalVrouter::LinkLocalServicesMap &services =
    1023             :                    Agent::GetInstance()->oper_db()->
    1024           0 :                    global_vrouter()->linklocal_services_map();
    1025             : 
    1026           0 :     for (GlobalVrouter::LinkLocalServicesMap::const_iterator it =
    1027           0 :          services.begin(); it != services.end(); ++it) {
    1028           0 :         LinkLocalServiceData service;
    1029           0 :         service.linklocal_service_name = it->second.linklocal_service_name;
    1030             :         service.linklocal_service_ip =
    1031           0 :                      it->first.linklocal_service_ip.to_string();
    1032           0 :         service.linklocal_service_port = it->first.linklocal_service_port;
    1033           0 :         service.ipfabric_dns_name = it->second.ipfabric_dns_service_name;
    1034           0 :         BOOST_FOREACH(Ip4Address ip, it->second.ipfabric_service_ip) {
    1035           0 :             service.ipfabric_ip.push_back(ip.to_string());
    1036             :         }
    1037           0 :         service.ipfabric_port = it->second.ipfabric_service_port;
    1038           0 :         linklocal_list.push_back(service);
    1039           0 :     }
    1040             : 
    1041           0 :     resp->set_service_list(linklocal_list);
    1042           0 :     resp->set_context(context());
    1043           0 :     resp->Response();
    1044           0 : }
    1045             : 
    1046             : ////////////////////////////////////////////////////////////////////////////////
    1047             : 
    1048           0 : bool GlobalVrouter::IsVrouterPresentCryptTunnelConfig(
    1049             :     const EncryptionTunnelEndpointList &endpoint_list) {
    1050           0 :     bool vrouter_present = false;
    1051           0 :     for (EncryptionTunnelEndpointList::const_iterator it = endpoint_list.begin();
    1052           0 :          it != endpoint_list.end(); it++) {
    1053           0 :          if (it->tunnel_remote_ip_address.compare(agent()->router_id().to_string()) == 0) {
    1054           0 :              vrouter_present = true;
    1055           0 :              break;
    1056             :          }
    1057             :     }
    1058           0 :     return vrouter_present;
    1059             : }
    1060             : 
    1061             : // Handle changes for cryptunnels
    1062          21 : void GlobalVrouter::UpdateCryptTunnelEndpointConfig(
    1063             :     const EncryptionTunnelEndpointList &endpoint_list, const std::string encrypt_mode_str) {
    1064          21 :     CryptMode mode = GlobalVrouter::CRYPT_NONE;
    1065          21 :     CryptTunnelsMap crypt_tunnels_map;
    1066          21 :     if (!agent()->crypt_interface())
    1067          21 :         return;
    1068           0 :     if (IsVrouterPresentCryptTunnelConfig(endpoint_list)) {
    1069           0 :         if (boost::iequals(encrypt_mode_str, "all"))
    1070           0 :             mode = GlobalVrouter::CRYPT_ALL_TRAFFIC;
    1071           0 :         for (EncryptionTunnelEndpointList::const_iterator it = endpoint_list.begin();
    1072           0 :             it != endpoint_list.end(); it++) {
    1073           0 :             if (it->tunnel_remote_ip_address.compare(agent()->router_id().to_string()) == 0) {
    1074           0 :                 continue;
    1075             :             }
    1076           0 :             crypt_tunnels_map.insert(CryptTunnelsPair(CryptTunnelKey(it->tunnel_remote_ip_address),
    1077           0 :                                                   CryptTunnel(mode)));
    1078             :         }
    1079             :     }
    1080           0 :     crypt_tunnels_map_.swap(crypt_tunnels_map);
    1081           0 :     ChangeNotifyCryptTunnels(&crypt_tunnels_map, &crypt_tunnels_map_);
    1082          21 : }
    1083             : 
    1084           0 : void GlobalVrouter::DeleteCryptTunnelEndpointConfig() {
    1085           0 : }
    1086             : 
    1087           0 : bool GlobalVrouter::ChangeNotifyCryptTunnels(CryptTunnelsMap *old_value,
    1088             :                                              CryptTunnelsMap *new_value) {
    1089           0 :     bool change = false;
    1090           0 :     CryptTunnelsMap::iterator it_old = old_value->begin();
    1091           0 :     CryptTunnelsMap::iterator it_new = new_value->begin();
    1092           0 :     while (it_old != old_value->end() && it_new != new_value->end()) {
    1093           0 :         if (it_old->first < it_new->first) {
    1094             :             // old entry is deleted
    1095           0 :             DeleteCryptTunnelEndpoint(it_old);
    1096           0 :             change = true;
    1097           0 :             it_old++;
    1098           0 :         } else if (it_new->first < it_old->first) {
    1099             :             // new entry
    1100           0 :             AddCryptTunnelEndpoint(it_new);
    1101           0 :             change = true;
    1102           0 :             it_new++;
    1103           0 :         } else if (it_new->second == it_old->second) {
    1104             :             // no change in entry
    1105           0 :             it_old++;
    1106           0 :             it_new++;
    1107             :         } else {
    1108             :             // change in entry
    1109           0 :             ChangeCryptTunnelEndpoint(it_old, it_new);
    1110           0 :             change = true;
    1111           0 :             it_old++;
    1112           0 :             it_new++;
    1113             :         }
    1114             :     }
    1115             : 
    1116             :     // delete remaining old entries
    1117           0 :     for (; it_old != old_value->end(); ++it_old) {
    1118           0 :         DeleteCryptTunnelEndpoint(it_old);
    1119           0 :         change = true;
    1120             :     }
    1121             : 
    1122             :     // add remaining new entries
    1123           0 :     for (; it_new != new_value->end(); ++it_new) {
    1124           0 :         AddCryptTunnelEndpoint(it_new);
    1125           0 :         change = true;
    1126             :     }
    1127             : 
    1128           0 :     return change;
    1129             : }
    1130             : 
    1131           0 : void GlobalVrouter::AddCryptTunnelEndpoint(const CryptTunnelsMap::iterator &it) {
    1132           0 :     bool crypt_traffic = false;
    1133           0 :     if (it->second.mode == GlobalVrouter::CRYPT_ALL_TRAFFIC)
    1134           0 :         crypt_traffic = true;
    1135           0 :     agent()->crypt_tunnel_table()->Create(it->first, crypt_traffic);
    1136           0 : }
    1137             : 
    1138           0 : void GlobalVrouter::DeleteCryptTunnelEndpoint(const CryptTunnelsMap::iterator &it) {
    1139           0 :     agent()->crypt_tunnel_table()->Delete(it->first);
    1140           0 : }
    1141             : 
    1142           0 : void GlobalVrouter::ChangeCryptTunnelEndpoint(const CryptTunnelsMap::iterator &old_it,
    1143             :                                               const CryptTunnelsMap::iterator &new_it) {
    1144           0 :     AddCryptTunnelEndpoint(new_it);
    1145           0 : }
    1146             : 
    1147           0 : void PortConfig::Trim() {
    1148           0 :     if (port_range.size() != 0) {
    1149           0 :         port_count = 0;
    1150             :     }
    1151             : 
    1152             :     //Only port range specified
    1153             :     //nothing more to be done
    1154           0 :     if (port_count != 0) {
    1155           0 :         return;
    1156             :     }
    1157             : 
    1158           0 :     for (uint16_t index = 0; index < port_range.size(); index++) {
    1159             :         //Ignore invalid range
    1160           0 :         if (port_range[index].port_start > port_range[index].port_end) {
    1161           0 :             port_range[index].port_start = 0;
    1162           0 :             port_range[index].port_end = 0;
    1163             :         }
    1164             : 
    1165           0 :         if (port_range[index].port_start == 0 &&
    1166           0 :             port_range[index].port_end == 0) {
    1167           0 :             continue;
    1168             :         }
    1169             : 
    1170             :         //Check if given range is a subset or intersecting with any other range
    1171           0 :         for (uint16_t sub_index = 0; sub_index < port_range.size(); sub_index++) {
    1172           0 :             if (index == sub_index) {
    1173           0 :                 continue;
    1174             :             }
    1175             : 
    1176             :             //Two ranges are same
    1177           0 :             if (port_range[index].port_start ==
    1178           0 :                     port_range[sub_index].port_start &&
    1179           0 :                 port_range[index].port_end == port_range[sub_index].port_end) {
    1180           0 :                 port_range[index].port_start = 0;
    1181           0 :                 port_range[index].port_end = 0;
    1182           0 :                 break;
    1183             :             }
    1184             : 
    1185             :             //Range is a subset of other range
    1186           0 :             if (port_range[index].port_start >=
    1187           0 :                     port_range[sub_index].port_start &&
    1188           0 :                 port_range[index].port_end <= port_range[sub_index].port_end) {
    1189           0 :                 port_range[index].port_start = 0;
    1190           0 :                 port_range[index].port_end = 0;
    1191           0 :                 break;
    1192             :             }
    1193             : 
    1194             :             //Overlapping range with index range lesser than sub index range
    1195             :             //Ex 10-15, 15-20
    1196           0 :             if (port_range[index].port_start <=
    1197           0 :                     port_range[sub_index].port_start &&
    1198           0 :                 port_range[index].port_end >=
    1199           0 :                     port_range[sub_index].port_start &&
    1200           0 :                 port_range[index].port_end < port_range[sub_index].port_end) {
    1201           0 :                 port_range[index].port_end = port_range[sub_index].port_start;
    1202           0 :                 port_range[sub_index].port_start =
    1203           0 :                     port_range[sub_index].port_start + 1;
    1204             :             }
    1205             :         }
    1206             :     }
    1207             : 
    1208           0 :     port_count = 0;
    1209             :     //Update count
    1210           0 :     std::vector<PortRange>::iterator it = port_range.begin();
    1211           0 :     while (it != port_range.end()) {
    1212           0 :         std::vector<PortRange>::iterator prev_it = it++;
    1213           0 :         if (prev_it->port_end == 0 &&
    1214           0 :             prev_it->port_start == 0) {
    1215           0 :             continue;
    1216             :         }
    1217             : 
    1218           0 :         port_count += (prev_it->port_end - prev_it->port_start) + 1;
    1219             :     }
    1220             : }

Generated by: LCOV version 1.14