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