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 : }