OpenSDN source code
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Pages
bfd_proto.cc
Go to the documentation of this file.
1 /*
2  * Copyright (c) 2017 Juniper Networks, Inc. All rights reserved.
3  */
4 
5 #include <sandesh/sandesh_types.h>
6 #include <sandesh/sandesh.h>
7 #include <cmn/agent_cmn.h>
8 #include <init/agent_init.h>
9 #include <oper/interface.h>
10 #include <oper/vm_interface.h>
11 #include <oper/metadata_ip.h>
12 #include <pkt/proto_handler.h>
13 #include "pkt/pkt_init.h"
14 #include <services/bfd_proto.h>
15 #include <services/bfd_handler.h>
16 #include <services/services_types.h>
17 #include <services/services_init.h>
18 #include "base/logging.h"
19 
20 BfdProto::BfdProto(Agent *agent, boost::asio::io_context &io) :
21  Proto(agent, "Agent::Services", PktHandler::BFD, io),
22  msg_(new PktInfo(agent, BFD_TX_BUFF_LEN, PktHandler::BFD, 0)),
23  communicator_(this),
24  server_(new BFD::Server(agent->event_manager(), &communicator_)),
25  client_(new BFD::Client(&communicator_)), handler_(agent, msg_, io) {
26 
27  // limit the number of entries in the workqueue
29  work_queue_.SetBounded(true);
30 
32  boost::bind(&BfdProto::BfdHealthCheckSessionControl, this, _1, _2),
34 }
35 
37 }
38 
39 ProtoHandler *BfdProto::AllocProtoHandler(boost::shared_ptr<PktInfo> info,
40  boost::asio::io_context &io) {
41  return new BfdHandler(agent(), info, io);
42 }
43 
44 bool BfdSessionsKey::IsLess(const BfdSessionsKey &rhs) const {
45  if (id_ != rhs.id_) {
46  return id_ < rhs.id_;
47  }
48  return ip_ < rhs.ip_;
49 }
50 
51 bool BfdSessionsKey::IsEqual(const BfdSessionsKey &rhs) const {
52  if (id_ != rhs.id_) {
53  return false;
54  }
55  if (ip_ != rhs.ip_) {
56  return false;
57  }
58  return true;
59 }
60 
63  HealthCheckInstanceService *service) {
64 
65  uint16_t remote_port = service->is_multi_hop() ?
67  IpAddress source_ip = service->update_source_ip();
68  IpAddress destination_ip = service->destination_ip();
69  if (source_ip.is_unspecified()) {
70  BFD_TRACE(Trace, "Ignore",
71  destination_ip.to_string(),
72  source_ip.to_string(), service->interface()->id(),
73  0, 0, 0);
74  return false;
75  }
76  BFD::SessionKey key(destination_ip,
77  BFD::SessionIndex(service->interface()->id()),
78  remote_port,
79  source_ip);
80 
81  tbb::mutex::scoped_lock lock(mutex_);
82  switch (action) {
85  {
86  if (source_ip.is_v4() &&
87  source_ip.to_v4() == Ip4Address(METADATA_IP_ADDR)) {
88  return false;
89  }
90 
91  uint32_t tx_interval = service->service()->delay() * 1000000 +
92  service->service()->delay_usecs();
93  if (!tx_interval) {
94  tx_interval = kMinTxInterval;
95  }
96  uint32_t rx_interval = service->service()->timeout() * 1000000 +
97  service->service()->timeout_usecs();
98  if (!rx_interval) {
99  rx_interval = kMinRxInterval;
100  }
101  uint32_t multiplier = service->service()->max_retries();
102  if (!multiplier) {
103  multiplier = kMultiplier;
104  }
105 
106  BFD::SessionConfig session_config;
107  session_config.desiredMinTxInterval =
108  boost::posix_time::microseconds(tx_interval);
109  session_config.requiredMinRxInterval =
110  boost::posix_time::microseconds(rx_interval);
111  session_config.detectionTimeMultiplier = multiplier;
112 
113  client_->AddSession(key, session_config);
114  BfdSessionsKey skey(service->interface()->id(),
115  service->destination_ip());
116  sessions_[skey] = service;
117  BFD_TRACE(Trace, "Add / Update",
118  destination_ip.to_string(),
119  source_ip.to_string(), service->interface()->id(),
120  tx_interval, rx_interval, multiplier);
121  break;
122  }
123 
125  {
126  client_->DeleteSession(key);
127  BfdSessionsKey skey(service->interface()->id(),
128  service->destination_ip());
129  Sessions::iterator it = sessions_.find(skey);
130  if (it != sessions_.end()) {
131  sessions_.erase(it);
132  BFD_TRACE(Trace, "Delete",
133  destination_ip.to_string(),
134  source_ip.to_string(), service->interface()->id(),
135  0, 0, 0);
136  } else {
137  // TODO: replace log with trace
138  std::string str("BFD delete session ");
139  str += " interface-id: " + service->interface()->id();
140  str += " source-ip: " + source_ip.to_string();
141  str += " destination-ip: " + destination_ip.to_string();
142 
143  LOG(ERROR, "Duplicate request: " << str);
144  }
145  break;
146  }
147 
149  break;
150 
152  break;
153 
154  default:
155  assert(0);
156  }
157 
158  return true;
159 }
160 
162  IpAddress address,
163  std::string &data) {
164  tbb::mutex::scoped_lock lock(mutex_);
165  BfdSessionsKey key(interface, address);
166  Sessions::iterator it = sessions_.find(key);
167  if (it == sessions_.end()) {
168  return;
169  }
170  it->second->OnRead(data);
171 
172  // log the BFD up/down event
173  std::string str("BFD session ");
174  if (data.find("success") != std::string::npos) {
175  str += "Up,";
176  }
177  if (data.find("failure") != std::string::npos) {
178  str += "Down,";
179  }
180  if (it->second->service()) {
181  str += " service-health-check: " + it->second->service()->name();
182  } else {
183  str += " service: null";
184  }
185  if (it->second->interface()) {
186  str += " interface: " + it->second->interface()->name();
187  if (it->second->interface()->vrf()) {
188  str += " vrf: " + it->second->interface()->vrf()->GetName();
189  } else {
190  str += " vrf: null";
191  }
192  } else {
193  str += " interface: null";
194  }
195  if (!it->second->destination_ip().is_unspecified()) {
196  str += " destination-ip: " + it->second->destination_ip().to_string();
197  } else {
198  str += " destination-ip: null";
199  }
200  LOG(WARN, "SYS_NOTICE " << str);
201 
202 }
203 
205  boost::asio::const_buffer packet,
206  const boost::asio::ip::udp::endpoint &local_endpoint,
207  const boost::asio::ip::udp::endpoint &remote_endpoint,
208  const BFD::SessionIndex &session_index,
209  uint8_t len,
210  boost::system::error_code ec) {
211 
212  tbb::mutex::scoped_lock lock(rx_mutex_);
214  packet, local_endpoint, remote_endpoint,
215  session_index,
216  len, ec);
217 
219 }
220 
222  const boost::asio::ip::udp::endpoint &local_endpoint,
223  const boost::asio::ip::udp::endpoint &remote_endpoint,
224  const BFD::SessionIndex &session_index,
225  const boost::asio::mutable_buffer &packet, int pktSize) {
226  bfd_proto_->handler_.SendPacket(local_endpoint, remote_endpoint,
227  session_index.if_index, packet, pktSize);
229 }
230 
232  const bool &up) {
233  std::string data = up ? "success" : "failure";
234  bfd_proto_->NotifyHealthCheckInstanceService(key.index.if_index,
235  key.remote_address ,data);
236 }
237 
238 bool BfdProto::Enqueue(boost::shared_ptr<PktInfo> msg) {
239 
240  if (msg->is_bfd_keepalive) {
241  // Handle BFD keepalive packets
242  return ProcessBfdKeepAlive(msg);
243  }
244  // Handle BFD control packets
245  return Proto::Enqueue(msg);
246 }
247 
248 // Handle BFD packet stats
250  switch(type) {
253  break;
256  break;
257  default:
258  return;
259  }
260 }
261 
262 bool BfdProto::ProcessBfdKeepAlive(boost::shared_ptr<PktInfo> msg_info) {
263  PktHandler *pkt_handler = Agent::GetInstance()->pkt()->pkt_handler();
264 
265  BfdHandler *handler = new BfdHandler(agent(), msg_info, get_io_service());
266  if (handler->HandleReceive())
267  delete handler;
268 
269  return true;;
270 }
bool Enqueue(boost::shared_ptr< PktInfo > msg)
Definition: bfd_proto.cc:238
void SetBounded(bool bounded)
Definition: queue_task.h:200
InterfaceRef interface() const
Definition: health_check.h:147
void NotifyHealthCheckInstanceService(uint32_t interface, IpAddress address, std::string &data)
Definition: bfd_proto.cc:161
static Agent * GetInstance()
Definition: agent.h:436
virtual void NotifyStateChange(const BFD::SessionKey &key, const bool &up)
Definition: bfd_proto.cc:231
void IncrementKaEnqueueCount()
Definition: bfd_proto.h:129
TimeInterval desiredMinTxInterval
Definition: bfd_common.h:125
bool ProcessBfdKeepAlive(boost::shared_ptr< PktInfo > msg)
Definition: bfd_proto.cc:262
HealthCheckService * service() const
Definition: health_check.h:146
void ProcessStats(PktStatsType::Type type)
Definition: bfd_proto.cc:249
IpAddress destination_ip() const
virtual ~BfdProto()
Definition: bfd_proto.cc:36
boost::asio::ip::address IpAddress
Definition: address.h:13
bool IsEqual(const BfdSessionsKey &rhs) const
Definition: bfd_proto.cc:51
Sessions sessions_
Definition: bfd_proto.h:146
IpAddress ip_
Definition: bfd_proto.h:47
BfdHandler handler_
Definition: bfd_proto.h:145
#define METADATA_IP_ADDR
Definition: agent.h:294
static const uint32_t kMultiplier
Definition: bfd_proto.h:58
bool BfdHealthCheckSessionControl(HealthCheckTable::HealthCheckServiceAction action, HealthCheckInstanceService *service)
Definition: bfd_proto.cc:61
#define BFD_TX_BUFF_LEN
Definition: bfd_proto.h:20
TimeInterval requiredMinRxInterval
Definition: bfd_common.h:126
boost::asio::ip::address remote_address
Definition: bfd_common.h:115
uint32_t timeout() const
Definition: health_check.h:332
virtual bool Enqueue(boost::shared_ptr< PktInfo > msg)
void IncrementReceiveDropCount()
Definition: bfd_proto.h:128
uint8_t type
Definition: load_balance.h:109
void HandleReceiveSafe(boost::asio::const_buffer pkt, const boost::asio::ip::udp::endpoint &local_endpoint, const boost::asio::ip::udp::endpoint &remote_endpoint, const BFD::SessionIndex &session_index, uint8_t pkt_len, boost::system::error_code ec)
Definition: bfd_proto.cc:204
void SetSize(size_t size)
Definition: queue_task.h:196
Definition: agent.h:358
SessionIndex index
Definition: bfd_common.h:116
Definition: trace.h:220
PktHandler * pkt_handler() const
Definition: pkt_init.h:31
bool HandleReceive()
Definition: bfd_handler.cc:20
AgentParam * params() const
Definition: agent.h:1218
tbb::mutex mutex_
Definition: bfd_proto.h:139
boost::asio::io_context & get_io_service() const
boost::asio::ip::address_v4 Ip4Address
Definition: address.h:14
virtual void HandleReceive(const boost::asio::const_buffer &recv_buffer, const boost::asio::ip::udp::endpoint &local_endpoint, const boost::asio::ip::udp::endpoint &remote_endpoint, const SessionIndex &session_index, std::size_t bytes_transferred, const boost::system::error_code &error)
HealthCheckTable * health_check_table() const
Definition: agent.cc:933
uint32_t services_queue_limit()
Definition: agent_param.h:417
BfdCommunicator & bfd_communicator()
Definition: bfd_proto.h:124
IpAddress update_source_ip()
uint32_t delay() const
Definition: health_check.h:330
static const uint32_t kMinTxInterval
Definition: bfd_proto.h:60
BFD::Client * client_
Definition: bfd_proto.h:144
uint32_t max_retries() const
Definition: health_check.h:334
void DeleteSession(const SessionKey &key)
Definition: bfd_client.cc:48
tbb::mutex rx_mutex_
Definition: bfd_proto.h:140
void SendPacket(const boost::asio::ip::udp::endpoint &local_endpoint, const boost::asio::ip::udp::endpoint &remote_endpoint, uint32_t interface_id, const boost::asio::mutable_buffer &packet, int packet_length)
Definition: bfd_handler.cc:50
#define LOG(_Level, _Msg)
Definition: logging.h:33
void AddSession(const SessionKey &key, const SessionConfig &config)
Definition: bfd_client.cc:43
uint32_t id_
Definition: bfd_proto.h:46
#define BFD_TRACE(obj,...)
Definition: bfd_proto.h:22
uint64_t delay_usecs() const
Definition: health_check.h:331
static const uint32_t kMinRxInterval
Definition: bfd_proto.h:59
bool IsLess(const BfdSessionsKey &rhs) const
Definition: bfd_proto.cc:44
PktModule * pkt() const
Definition: agent.cc:965
void RegisterHealthCheckCallback(HealthCheckServiceCallback fn, HealthCheckService::HealthCheckType type)
Definition: health_check.h:441
BfdProto(Agent *agent, boost::asio::io_context &io)
Definition: bfd_proto.cc:20
ProtoHandler * AllocProtoHandler(boost::shared_ptr< PktInfo > info, boost::asio::io_context &io)
Definition: bfd_proto.cc:39
virtual void SendPacket(const boost::asio::ip::udp::endpoint &local_endpoint, const boost::asio::ip::udp::endpoint &remote_endpoint, const BFD::SessionIndex &session_index, const boost::asio::mutable_buffer &packet, int pktSize)
Definition: bfd_proto.cc:221
uint32_t if_index
Definition: bfd_common.h:81
void IncrementSent()
Definition: bfd_proto.h:126
uint64_t timeout_usecs() const
Definition: health_check.h:333
void IncrementReceived()
Definition: bfd_proto.h:127