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