LCOV - code coverage report
Current view: top level - vnsw/agent/diag - diag.cc (source / functions) Hit Total Coverage
Test: OpenSDN C/C++ coverage (all TARGET_SET jobs) Lines: 17 125 13.6 %
Date: 2026-06-11 01:56:02 Functions: 3 19 15.8 %
Legend: Lines: hit not hit

          Line data    Source code
       1             : /*
       2             :  * Copyright (c) 2013 Juniper Networks, Inc. All rights reserved.
       3             :  */
       4             : 
       5             : #include <stdint.h>
       6             : #include "base/os.h"
       7             : #include <map>
       8             : #include "vr_defs.h"
       9             : #include "base/timer.h"
      10             : #include "cmn/agent_cmn.h"
      11             : #include "pkt/proto.h"
      12             : #include "pkt/proto_handler.h"
      13             : #include "diag/diag.h"
      14             : #include "diag/diag_proto.h"
      15             : #include "diag/ping.h"
      16             : #include "oper/mirror_table.h"
      17             : #include "diag/diag_pkt_handler.h"
      18             : 
      19             : 
      20             : const std::string KDiagName("DiagTimeoutHandler");
      21             : const std::string DiagTable::kDiagData = "diagshc";
      22             : using namespace boost::posix_time;
      23             : ////////////////////////////////////////////////////////////////////////////////
      24             : 
      25           0 : DiagEntry::DiagEntry(const std::string &sip, const std::string &dip,
      26             :                      uint8_t proto, uint16_t sport, uint16_t dport,
      27             :                      const std::string &vrf_name, int timeout,
      28           0 :                      int attempts, DiagTable *diag_table) :
      29           0 :     sip_(IpAddress::from_string(sip, ec_)),
      30           0 :     dip_(IpAddress::from_string(dip, ec_)),
      31           0 :     proto_(proto), sport_(sport), dport_(dport),
      32           0 :     vrf_name_(vrf_name), diag_table_(diag_table), timeout_(timeout),
      33           0 :     timer_(TimerManager::CreateTimer(*(diag_table->agent()->event_manager())->io_service(),
      34             :                          "DiagTimeoutHandler",
      35             :                          TaskScheduler::GetInstance()->GetTaskId("Agent::Diag"),
      36             :                          PktHandler::DIAG)),
      37           0 :     max_attempts_(attempts), seq_no_(0) {
      38           0 : }
      39             : 
      40           0 : DiagEntry::~DiagEntry() {
      41           0 :     timer_->Cancel();
      42           0 :     TimerManager::DeleteTimer(timer_);
      43             :     //Delete entry in DiagTable
      44           0 :     diag_table_->Delete(this);
      45           0 : }
      46             : 
      47           0 : void DiagEntry::Init() {
      48           0 :     DiagEntryOp *entry_op = new DiagEntryOp(DiagEntryOp::ADD, this);
      49           0 :     diag_table_->Enqueue(entry_op);
      50           0 : }
      51             : 
      52           0 : void DiagEntry::EnqueueForceDelete() {
      53           0 :     DiagEntryOp *entry_op = new DiagEntryOp(DiagEntryOp::FORCE_DELETE, this);
      54           0 :     diag_table_->Enqueue(entry_op);
      55           0 : }
      56             : 
      57           0 : void DiagEntry::RestartTimer() {
      58             :     //Cancel timer of running
      59           0 :     timer_->Cancel();
      60           0 :     timer_->Start(timeout_, boost::bind(&DiagEntry::TimerExpiry, this, seq_no_));
      61           0 : }
      62             : 
      63           0 : bool DiagEntry::IsDone() {
      64           0 :     return (GetSeqNo() == GetMaxAttempts()) ? true : false;
      65             : }
      66             : 
      67           0 : bool DiagEntry::TimerExpiry( uint32_t seq_no) {
      68             :     DiagEntryOp *op;
      69           0 :     RequestTimedOut(seq_no);
      70           0 :     if (IsDone()) {
      71           0 :         op = new DiagEntryOp(DiagEntryOp::DEL, this);
      72           0 :         diag_table_->Enqueue(op);
      73           0 :         return false;
      74             :     }
      75             : 
      76           0 :     if (ResendOnTimerExpiry()) {
      77           0 :         SendRequest();
      78           0 :         return true;
      79             :     }
      80             : 
      81           0 :     return false;
      82             : }
      83             : 
      84           0 : void DiagEntry::Retry() {
      85           0 :     SendRequest();
      86           0 :     RestartTimer();
      87           0 : }
      88             : 
      89           0 : bool DiagTable::Process(DiagEntryOp *op) {
      90           0 :     switch (op->op_) {
      91           0 :     case DiagEntryOp::ADD:
      92           0 :         Add(op->de_);
      93           0 :         break;
      94             : 
      95           0 :     case DiagEntryOp::DEL:
      96           0 :         if (op->de_->TimerCancel() == true) {
      97           0 :             op->de_->SendSummary();
      98           0 :             delete op->de_;
      99             :         }
     100           0 :         break;
     101             : 
     102           0 :     case DiagEntryOp::FORCE_DELETE:
     103           0 :         op->de_->TimerCancel();
     104           0 :         delete op->de_;
     105           0 :         break;
     106             : 
     107           0 :     case DiagEntryOp::RETRY:
     108           0 :         op->de_->Retry();
     109           0 :         break;
     110             :     }
     111             : 
     112           0 :     delete op;
     113           0 :     return true;
     114             : }
     115             : 
     116           2 : DiagTable::DiagTable(Agent *agent):agent_(agent) {
     117           2 :     diag_proto_.reset(
     118           2 :         new DiagProto(agent, *(agent->event_manager())->io_service()));
     119           4 :     entry_op_queue_ = new WorkQueue<DiagEntryOp *>
     120           4 :                     (TaskScheduler::GetInstance()->GetTaskId("Agent::Diag"),
     121             :                      PktHandler::DIAG,
     122           2 :                      boost::bind(&DiagTable::Process, this, _1));
     123           2 :     entry_op_queue_->set_name("Diagnostics Table");
     124           2 :     index_ = 1;
     125           2 : }
     126             : 
     127           2 : void DiagTable::Shutdown() {
     128           2 :     entry_op_queue_->Shutdown();
     129           2 :     delete entry_op_queue_;
     130           2 :     diag_proto_.reset(NULL);
     131           2 : }
     132             : 
     133           2 : DiagTable::~DiagTable() {
     134           2 :     assert(tree_.size() == 0);
     135           2 : }
     136             : 
     137           0 : void DiagTable::Add(DiagEntry *de) {
     138           0 :     de->SetKey(index_++);
     139           0 :     tree_.insert(std::make_pair(de->GetKey(), de));
     140           0 :     de->SendRequest();
     141           0 :     de->RestartTimer();
     142           0 : }
     143             : 
     144           0 : void DiagTable::Delete(DiagEntry *de) {
     145           0 :     tree_.erase(de->GetKey());
     146           0 : }
     147             : 
     148           0 : DiagEntry* DiagTable::Find(DiagEntry::DiagKey &key) {
     149           0 :     DiagEntryTree::const_iterator it;
     150             : 
     151           0 :     it = tree_.find(key);
     152           0 :     if (it == tree_.end()) {
     153           0 :         return NULL;
     154             :     }
     155             : 
     156           0 :     return static_cast<DiagEntry *>(it->second);
     157             : }
     158             : 
     159           0 : void DiagTable::Enqueue(DiagEntryOp *op) {
     160           0 :     entry_op_queue_->Enqueue(op);
     161           0 : }
     162             : 
     163           0 : uint32_t DiagEntry::HashValUdpSourcePort() {
     164           0 :     std::size_t seed = 0;
     165           0 :     boost::hash_combine(seed, sip_.to_v4().to_ulong());
     166           0 :     boost::hash_combine(seed, dip_.to_v4().to_ulong());
     167           0 :     boost::hash_combine(seed, proto_);
     168           0 :     boost::hash_combine(seed, sport_);
     169           0 :     boost::hash_combine(seed, dport_);
     170           0 :     return seed;
     171             : }
     172             : 
     173           0 : void DiagEntry::FillOamPktHeader(OverlayOamPktData *pktdata, uint32_t vxlan_id,
     174             :                                  const boost::posix_time::ptime &time) {
     175           0 :     pktdata->msg_type_ = AgentDiagPktData::DIAG_REQUEST;
     176           0 :     pktdata->reply_mode_ = OverlayOamPktData::REPLY_OVERLAY_SEGMENT;
     177           0 :     pktdata->org_handle_ = htons(key_);
     178           0 :     pktdata->seq_no_ = htonl(seq_no_);
     179             : 
     180             :     boost::posix_time::ptime
     181           0 :         epoch(boost::gregorian::date(1970, boost::gregorian::Jan, 1));
     182           0 :     boost::posix_time::time_duration td = time - epoch;
     183           0 :     pktdata->timesent_sec_ = htonl(td.total_seconds());
     184           0 :     pktdata->timesent_misec_ = htonl(td.total_microseconds());
     185             : 
     186           0 :     if (sip_.is_v4()) {
     187           0 :         pktdata->oamtlv_.type_ = htons(OamTlv::VXLAN_PING_IPv4);
     188           0 :         pktdata->oamtlv_.length_ = htons(sizeof(OamTlv::VxlanOamV4Tlv));
     189           0 :         OamTlv::VxlanOamV4Tlv *vxlan_tlv =
     190             :             (OamTlv::VxlanOamV4Tlv *) pktdata->oamtlv_.data_;
     191           0 :         vxlan_tlv->vxlan_id_ = htonl(vxlan_id);
     192           0 :         vxlan_tlv->sip_ = htonl(sip_.to_v4().to_ulong());
     193             :     } else {
     194           0 :         pktdata->oamtlv_.type_ = htons(OamTlv::VXLAN_PING_IPv6);
     195           0 :         pktdata->oamtlv_.length_ = htons(sizeof(OamTlv::VxlanOamV6Tlv));
     196           0 :         OamTlv::VxlanOamV6Tlv *vxlan_tlv =
     197             :             (OamTlv::VxlanOamV6Tlv *) pktdata->oamtlv_.data_;
     198           0 :         vxlan_tlv->vxlan_id_ = htonl(vxlan_id);
     199           0 :         memcpy(vxlan_tlv->sip_, sip_.to_v6().to_bytes().data(), 16);
     200             :     }
     201           0 : }

Generated by: LCOV version 1.14