LCOV - code coverage report
Current view: top level - vnsw/agent/uve - agent_uve_base.cc (source / functions) Hit Total Coverage
Test: OpenSDN C/C++ coverage (all TARGET_SET jobs) Lines: 112 223 50.2 %
Date: 2026-08-03 02:19:58 Functions: 10 16 62.5 %
Legend: Lines: hit not hit

          Line data    Source code
       1             : /*
       2             :  * Copyright (c) 2013 Juniper Networks, Inc. All rights reserved.
       3             :  */
       4             : 
       5             : #include <base/cpuinfo.h>
       6             : #include <db/db.h>
       7             : #include <cmn/agent_cmn.h>
       8             : #include <oper/interface_common.h>
       9             : #include <oper/interface.h>
      10             : 
      11             : #include "vr_genetlink.h"
      12             : #include "nl_util.h"
      13             : 
      14             : #include <uve/agent_uve_base.h>
      15             : #include <uve/vn_uve_table_base.h>
      16             : #include <uve/stats_interval_types.h>
      17             : #include <init/agent_param.h>
      18             : #include <oper/mirror_table.h>
      19             : #include <oper/global_vrouter.h>
      20             : #include <oper/tag.h>
      21             : #include <uve/vrouter_stats_collector.h>
      22             : #include <cmn/agent_stats.h>
      23             : 
      24             : using process::ConnectionInfo;
      25             : using process::ConnectionType;
      26             : using process::ProcessState;
      27             : using process::ConnectionStatus;
      28             : using process::ConnectionState;
      29             : using process::ConnectionStateManager;
      30             : using process::g_process_info_constants;
      31             : 
      32             : 
      33             : const uint32_t AgentUveBase::kUveCountPerTimer;
      34             : 
      35             : const uint32_t AgentUveBase::kDefaultInterval;
      36             : 
      37             : const uint32_t AgentUveBase::kIncrementalInterval;
      38             : 
      39             : const uint64_t AgentUveBase::kBandwidthInterval;
      40             : 
      41             : 
      42             : AgentUveBase *AgentUveBase::singleton_;
      43             : 
      44           3 : AgentUveBase::AgentUveBase(Agent *agent, uint64_t intvl,
      45           3 :                            uint32_t default_intvl, uint32_t incremental_intvl)
      46           3 :     : vn_uve_table_(NULL), vm_uve_table_(NULL), vrouter_uve_entry_(NULL),
      47           3 :       prouter_uve_table_(new ProuterUveTable(agent, default_intvl)),
      48           3 :       interface_uve_table_(NULL),
      49           3 :       default_interval_(default_intvl),
      50           3 :       incremental_interval_(incremental_intvl),
      51           3 :       agent_(agent), bandwidth_intvl_(intvl),
      52           3 :       vrouter_stats_collector_(new VrouterStatsCollector(
      53           3 :                                    *(agent->event_manager()->io_service()),
      54           6 :                                    this)) {
      55           3 :     singleton_ = this;
      56           3 : }
      57             : 
      58           3 : AgentUveBase::~AgentUveBase() {
      59           3 : }
      60             : 
      61           0 : void AgentUveBase::BuildTagNamesFromList(const TagList &tl, UveTagData *info)
      62             :     const {
      63           0 :     TagTable *table = agent_->tag_table();
      64           0 :     TagList::const_iterator it = tl.begin();
      65           0 :     while (it != tl.end()) {
      66           0 :         uint64_t type = ((uint64_t)*it >> TagEntry::kTagTypeBitShift);
      67           0 :         switch (type) {
      68           0 :         case TagTable::APPLICATION:
      69           0 :             info->application = table->TagName(*it);
      70           0 :             break;
      71           0 :         case TagTable::TIER:
      72           0 :             info->tier = table->TagName(*it);
      73           0 :             break;
      74           0 :         case TagTable::SITE:
      75           0 :             info->site = table->TagName(*it);
      76           0 :             break;
      77           0 :         case TagTable::DEPLOYMENT:
      78           0 :             info->deployment = table->TagName(*it);
      79           0 :             break;
      80           0 :         case TagTable::LABEL:
      81           0 :             if (info->fill_type == UveTagData::SET) {
      82           0 :                 info->label_set.insert(table->TagName(*it));
      83           0 :                 break;
      84           0 :             } else if (info->fill_type == UveTagData::VECTOR) {
      85           0 :                 info->label_vector.push_back(table->TagName(*it));
      86           0 :                 break;
      87             :             }
      88           0 :             if (!info->labels.empty()) {
      89           0 :                 info->labels += ";";
      90             :             }
      91           0 :             info->labels.append(table->TagName(*it));
      92           0 :             break;
      93           0 :         case TagTable::NEUTRON_FWAAS:
      94           0 :             info->application = table->TagName(*it);
      95           0 :             break;
      96           0 :         default:
      97           0 :             if (info->fill_type == UveTagData::SET) {
      98           0 :                 info->custom_tag_set.insert(table->TagName(*it));
      99           0 :                 break;
     100           0 :             } else if (info->fill_type == UveTagData::VECTOR) {
     101           0 :                 info->custom_tag_vector.push_back(table->TagName(*it));
     102           0 :                 break;
     103             :             }
     104           0 :             if (!info->custom_tags.empty()) {
     105           0 :                 info->custom_tags += ";";
     106             :             }
     107           0 :             info->custom_tags.append(table->TagName(*it));
     108           0 :             break;
     109             :         }
     110           0 :         ++it;
     111             :     }
     112           0 : }
     113             : 
     114             : /* Web-UI requires tag-id to returned as hex string. This should start with 0x
     115             :  * and have exactly 12 digits/characters. Zero should be used for filling leading
     116             :  * characters if the tag-id is not 12 digits wide. Web-UI uses this id to do
     117             :  * lookup in API server */
     118           0 : string AgentUveBase::TagIDToHexString(uint64_t value) const {
     119           0 :     std::stringstream ss;
     120             :     ss << "0x" << std::setfill('0') <<
     121           0 :         std::setw(12) << std::hex << (uint64_t)value;
     122           0 :     return ss.str();
     123           0 : }
     124             : 
     125           0 : void AgentUveBase::BuildTagIdsFromList(const TagList &tl, UveTagData *info)
     126             :     const {
     127           0 :     TagList::const_iterator it = tl.begin();
     128           0 :     while (it != tl.end()) {
     129           0 :         uint64_t type = ((uint64_t)*it >> TagEntry::kTagTypeBitShift);
     130           0 :         switch (type) {
     131           0 :         case TagTable::APPLICATION:
     132           0 :             info->application = TagIDToHexString(*it);
     133           0 :             break;
     134           0 :         case TagTable::TIER:
     135           0 :             info->tier = TagIDToHexString(*it);
     136           0 :             break;
     137           0 :         case TagTable::SITE:
     138           0 :             info->site = TagIDToHexString(*it);
     139           0 :             break;
     140           0 :         case TagTable::DEPLOYMENT:
     141           0 :             info->deployment = TagIDToHexString(*it);
     142           0 :             break;
     143           0 :         case TagTable::LABEL:
     144           0 :             if (info->fill_type == UveTagData::SET) {
     145           0 :                 info->label_set.insert(TagIDToHexString(*it));
     146           0 :                 break;
     147           0 :             } else if (info->fill_type == UveTagData::VECTOR) {
     148           0 :                 info->label_vector.push_back(TagIDToHexString(*it));
     149           0 :                 break;
     150             :             }
     151           0 :             if (!info->labels.empty()) {
     152           0 :                 info->labels += ";";
     153             :             }
     154           0 :             info->labels.append(TagIDToHexString(*it));
     155           0 :             break;
     156           0 :         case TagTable::NEUTRON_FWAAS:
     157           0 :             info->application = TagIDToHexString(*it);
     158           0 :             break;
     159           0 :         default:
     160           0 :             if (info->fill_type == UveTagData::SET) {
     161           0 :                 info->custom_tag_set.insert(TagIDToHexString(*it));
     162           0 :                 break;
     163           0 :             } else if (info->fill_type == UveTagData::VECTOR) {
     164           0 :                 info->custom_tag_vector.push_back(TagIDToHexString(*it));
     165           0 :                 break;
     166             :             }
     167           0 :             if (!info->custom_tags.empty()) {
     168           0 :                 info->custom_tags += ";";
     169             :             }
     170           0 :             info->custom_tags.append(TagIDToHexString(*it));
     171           0 :             break;
     172             :         }
     173           0 :         ++it;
     174             :     }
     175           0 : }
     176             : 
     177           0 : void AgentUveBase::set_default_interval(uint32_t new_interval) {
     178           0 :     if (new_interval == 0) {
     179           0 :         default_interval_ = kDefaultInterval;
     180             :     } else {
     181           0 :         default_interval_ = new_interval;
     182             :     }
     183           0 : }
     184             : 
     185           0 : void AgentUveBase::set_incremental_interval(uint32_t new_interval) {
     186           0 :     if (new_interval == 0) {
     187           0 :         incremental_interval_ = kIncrementalInterval;
     188             :     } else {
     189           0 :         incremental_interval_ = new_interval;
     190             :     }
     191           0 : }
     192             : 
     193           3 : void AgentUveBase::Shutdown() {
     194           3 :     vn_uve_table_.get()->Shutdown();
     195           3 :     vm_uve_table_.get()->Shutdown();
     196           3 :     vrouter_uve_entry_.get()->Shutdown();
     197           3 :     prouter_uve_table_.get()->Shutdown();
     198           3 :     interface_uve_table_.get()->Shutdown();
     199           3 :     connection_state_manager_->Shutdown();
     200           3 :     vrouter_stats_collector_->Shutdown();
     201           3 : }
     202             : 
     203           3 : void AgentUveBase::Init() {
     204           3 :     std::string module_id(agent_->module_name());
     205           3 :     std::string instance_id(agent_->instance_id());
     206           3 :     EventManager *evm = agent_->event_manager();
     207           3 :     boost::asio::io_context &io = *evm->io_service();
     208             : 
     209           3 :     CpuLoadData::Init();
     210           3 :     connection_state_manager_ =
     211             :         ConnectionStateManager::
     212           3 :             GetInstance();
     213           3 :     agent_->set_connection_state(ConnectionState::GetInstance());
     214           3 :     connection_state_manager_->Init(io, agent_->agent_name(),
     215             :             module_id, instance_id,
     216             :             boost::bind(&AgentUveBase::VrouterAgentProcessState,
     217             :                         this, _1, _2, _3), "ObjectVRouter");
     218           3 : }
     219             : 
     220          35 : uint8_t AgentUveBase::ExpectedConnections(uint8_t &num_control_nodes,
     221             :                                           uint8_t &num_dns_servers) {
     222          35 :     uint8_t count = 0;
     223          35 :     AgentParam *cfg = agent_->params();
     224             : 
     225         105 :     for (int i = 0; i < MAX_XMPP_SERVERS; i++) {
     226          70 :         if (!agent_->controller_ifmap_xmpp_server(i).empty()) {
     227          39 :             num_control_nodes++;
     228          39 :             count++;
     229             :         }
     230          70 :         if (agent_->services() && !agent_->dns_server(i).empty()) {
     231          13 :             num_dns_servers++;
     232          13 :             count++;
     233             :         }
     234             :     }
     235             :     //Increment 1 for collector service
     236          35 :     if (cfg->collector_server_list().size() != 0) {
     237          35 :         count++;
     238             :     }
     239             : 
     240          35 :     return count;
     241             : }
     242             : 
     243          74 : void AgentUveBase::UpdateMessage(const ConnectionInfo &cinfo,
     244             :                              std::string &message) {
     245          74 :     if (message.empty()) {
     246          35 :         message = cinfo.get_type();
     247             :     } else {
     248          39 :         message += ", " + cinfo.get_type();
     249             :     }
     250          74 :     const std::string &name(cinfo.get_name());
     251          74 :     if (!name.empty()) {
     252          39 :         message += ":" + name;
     253             :     }
     254          74 : }
     255             : 
     256          35 : bool AgentUveBase::HasSelfConfiguration() const {
     257          35 :     if (!agent_ || !agent_->oper_db() || !agent_->oper_db()->global_vrouter()) {
     258           0 :         return false;
     259             :     }
     260          35 :     return agent_->oper_db()->global_vrouter()->configured();
     261             : }
     262             : 
     263          35 : void AgentUveBase::VrouterAgentProcessState
     264             :     (const std::vector<ConnectionInfo> &cinfos,
     265             :      ProcessState::type &pstate, std::string &message) {
     266          35 :     size_t num_conns = 0;
     267          35 :     uint8_t num_control_nodes = 0, num_dns_servers = 0;
     268          35 :     uint8_t down_control_nodes = 0;
     269          35 :     uint8_t expected_conns = ExpectedConnections(num_control_nodes,
     270          35 :                                                  num_dns_servers);
     271             :     std::string cup(g_process_info_constants.ConnectionStatusNames.
     272          35 :         find(ConnectionStatus::UP)->second);
     273          35 :     bool is_cup = true;
     274          35 :     bool is_tor_connected = false;
     275             :     string tor_type(g_process_info_constants.ConnectionTypeNames.
     276          35 :             find(ConnectionType::TOR)->second);
     277             :     // Iterate to determine process connectivity status
     278          35 :     for (std::vector<ConnectionInfo>::const_iterator it = cinfos.begin();
     279         113 :          it != cinfos.end(); it++) {
     280          78 :         const ConnectionInfo &cinfo(*it);
     281          78 :         const std::string &conn_status(cinfo.get_status());
     282          78 :         if (cinfo.get_type() == tor_type) {
     283           0 :             is_tor_connected = true;
     284           0 :             continue;
     285             :         }
     286             :         /* Don't consider ConnectionType::TOR type for counting connections.
     287             :          * contrail-tor-agent is not supposed to report as Non-Functional when
     288             :          * it is in backup mode, but contrail-tor-agent does not have a way to
     289             :          * figure out that it is in backup mode. Hence for contrail-tor-agent
     290             :          * (both active and backup modes) we don't consider connection to TOR
     291             :          * for reporting Node Status */
     292          78 :         num_conns++;
     293          78 :         if (conn_status != cup) {
     294         148 :             if (cinfo.get_name().compare(0, 13,
     295         148 :                 agent_->xmpp_control_node_prefix()) == 0) {
     296          30 :                 down_control_nodes++;
     297             :             }
     298          74 :             is_cup = false;
     299          74 :             UpdateMessage(cinfo, message);
     300             :         }
     301             :     }
     302          35 :     if ((num_control_nodes == 0) || (num_control_nodes == down_control_nodes)) {
     303          21 :         pstate = ProcessState::NON_FUNCTIONAL;
     304          21 :         if ((num_control_nodes == 0) && message.empty()) {
     305           0 :             message = "No control-nodes configured";
     306             :         }
     307          14 :     } else if (!is_tor_connected && agent_->tor_agent_enabled()) {
     308             :         // waiting for first TOR config to arrive
     309           0 :         pstate = ProcessState::NON_FUNCTIONAL;
     310           0 :         message += " No ToR Config";
     311             :     } else {
     312          14 :         pstate = ProcessState::FUNCTIONAL;
     313             :     }
     314          35 :     if (!is_cup) {
     315          35 :         message += " connection down";
     316             :     }
     317          35 :     if (!HasSelfConfiguration()) {
     318             :         // waiting for Global vrouter config
     319          27 :         pstate = ProcessState::NON_FUNCTIONAL;
     320          27 :         if (message.empty()) {
     321           0 :             message = "No Configuration for self";
     322             :         } else {
     323          27 :             message += ", No Configuration for self";
     324             :         }
     325             :     }
     326         102 :     for (int i = 0; i < MAX_XMPP_SERVERS; i++) {
     327          70 :         if (!agent_->controller_ifmap_xmpp_server(i).empty()) {
     328          39 :             if (agent_->stats()->xmpp_reconnects(i) >= 1) {
     329           3 :                 break;
     330             :             }
     331             :         }
     332             :     }
     333             : 
     334          35 :     if (num_conns != expected_conns) {
     335          22 :         message += " Number of connections:" + integerToString(num_conns) +
     336          33 :             ", Expected: " + integerToString(expected_conns);
     337          11 :         return;
     338             :     }
     339          24 :     return;
     340          35 : }
     341             : 
     342           3 : void AgentUveBase::RegisterDBClients() {
     343           3 :     vn_uve_table_.get()->RegisterDBClients();
     344           3 :     vm_uve_table_.get()->RegisterDBClients();
     345           3 :     vrouter_uve_entry_.get()->RegisterDBClients();
     346           3 :     prouter_uve_table_.get()->RegisterDBClients();
     347           3 :     interface_uve_table_.get()->RegisterDBClients();
     348           3 : }
     349             : 
     350           3 : void AgentUveBase::InitDone() {
     351           3 :     vrouter_stats_collector_->InitDone();
     352           3 : }

Generated by: LCOV version 1.14