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