Line data Source code
1 : /* 2 : * Copyright (c) 2017 Juniper Networks, Inc. All rights reserved. 3 : * Copyright Contributors to the OpenSDN project 4 : */ 5 : 6 : #include <cmn/agent_cmn.h> 7 : #include <init/agent_init.h> 8 : #include <oper/interface.h> 9 : #include <oper/vm_interface.h> 10 : #include <oper/metadata_ip.h> 11 : #include <pkt/proto.h> 12 : #include <pkt/proto_handler.h> 13 : #include <diag/diag_proto.h> 14 : #include <diag/diag_pkt_handler.h> 15 : #include <diag/segment_health_check.h> 16 : 17 2 : DiagProto::DiagProto(Agent *agent, boost::asio::io_context &io) 18 : : Proto(agent, "Agent::Diag", PktHandler::DIAG, io), 19 2 : session_map_(), stats_mutex_(), stats_() { 20 2 : agent->health_check_table()->RegisterHealthCheckCallback( 21 : boost::bind(&DiagProto::SegmentHealthCheckProcess, this, _1, _2), 22 : HealthCheckService::SEGMENT); 23 2 : } 24 : 25 0 : ProtoHandler *DiagProto::AllocProtoHandler(boost::shared_ptr<PktInfo> info, 26 : boost::asio::io_context &io) { 27 0 : return new DiagPktHandler(agent(), info, io); 28 : } 29 : 30 0 : bool DiagProto::SegmentHealthCheckProcess( 31 : HealthCheckTable::HealthCheckServiceAction action, 32 : HealthCheckInstanceService *service) { 33 : 34 0 : uint32_t intf_id = service->interface()->id(); 35 0 : SessionMap::iterator it = session_map_.find(intf_id); 36 : 37 0 : switch (action) { 38 0 : case HealthCheckTable::CREATE_SERVICE: 39 : case HealthCheckTable::UPDATE_SERVICE: 40 : { 41 : /* When we get create/update request for already created service, 42 : * we update the existing object to reflect change in properties 43 : * of service. 44 : */ 45 0 : if (it != session_map_.end()) { 46 0 : SegmentHealthCheckPkt *old_ptr = it->second; 47 0 : old_ptr->set_service(NULL); 48 0 : old_ptr->UpdateService(service); 49 0 : return true; 50 : } 51 : SegmentHealthCheckPkt *ptr = 52 0 : new SegmentHealthCheckPkt(service, agent_->diag_table()); 53 : 54 0 : session_map_.insert(SessionPair(intf_id, ptr)); 55 : /* Init will add ptr to DiagTable and sends 56 : * health-check-packets 57 : */ 58 0 : ptr->Init(); 59 0 : break; 60 : } 61 : 62 0 : case HealthCheckTable::DELETE_SERVICE: 63 : { 64 : /* Ignore delete request if we are not sending any 65 : * health-check-packets on this interface. 66 : */ 67 0 : if (it == session_map_.end()) { 68 0 : return true; 69 : } 70 0 : SegmentHealthCheckPkt *old_ptr = it->second; 71 0 : old_ptr->set_service(NULL); 72 0 : old_ptr->StopDelayTimer(); 73 0 : session_map_.erase(it); 74 : 75 : /* DeleteEnqueue will remove old_ptr from DiagTable and 76 : * frees it */ 77 0 : old_ptr->EnqueueForceDelete(); 78 0 : break; 79 : } 80 : 81 0 : case HealthCheckTable::RUN_SERVICE: 82 0 : break; 83 : 84 0 : case HealthCheckTable::STOP_SERVICE: 85 0 : break; 86 : 87 0 : default: 88 0 : assert(0); 89 : } 90 : 91 0 : return true; 92 : } 93 : 94 0 : void DiagProto::IncrementDiagStats(uint32_t itf_id, DiagStatsType type) { 95 0 : std::scoped_lock lock(stats_mutex_); 96 0 : DiagStats new_entry; 97 0 : std::pair<DiagStatsMap::iterator, bool> ret = stats_.insert(DiagStatsPair 98 : (itf_id, 99 : new_entry)); 100 0 : DiagStats &entry = ret.first->second; 101 0 : switch (type) { 102 0 : case REQUESTS_SENT: 103 0 : entry.requests_sent++; 104 0 : break; 105 0 : case REQUESTS_RECEIVED: 106 0 : entry.requests_received++; 107 0 : break; 108 0 : case REPLIES_SENT: 109 0 : entry.replies_sent++; 110 0 : break; 111 0 : case REPLIES_RECEIVED: 112 0 : entry.replies_received++; 113 0 : break; 114 0 : default: 115 0 : assert(0); 116 : } 117 0 : } 118 : 119 0 : void DiagProto::FillSandeshHealthCheckResponse(SegmentHealthCheckPktStatsResp 120 : *resp) { 121 : vector<SegmentHealthCheckStats> &list = 122 0 : const_cast<std::vector<SegmentHealthCheckStats>&>(resp->get_stats()); 123 0 : std::scoped_lock lock(stats_mutex_); 124 0 : DiagProto::DiagStatsMap::const_iterator it = stats_.begin(); 125 0 : while (it != stats_.end()) { 126 0 : SegmentHealthCheckStats item; 127 0 : DiagProto::DiagStats source = it->second; 128 0 : item.set_interface_index(it->first); 129 0 : item.set_requests_sent(source.requests_sent); 130 0 : item.set_requests_received(source.requests_received); 131 0 : item.set_replies_sent(source.replies_sent); 132 0 : item.set_replies_received(source.replies_received); 133 0 : list.push_back(item); 134 0 : ++it; 135 0 : } 136 0 : } 137 : 138 0 : void SegmentHealthCheckPktStats::HandleRequest() const { 139 0 : DiagProto *proto = Agent::GetInstance()->diag_table()->diag_proto(); 140 0 : SegmentHealthCheckPktStatsResp *resp = new SegmentHealthCheckPktStatsResp(); 141 0 : proto->FillSandeshHealthCheckResponse(resp); 142 0 : resp->set_context(context()); 143 0 : resp->Response(); 144 0 : return; 145 : }