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

Generated by: LCOV version 1.14