OpenSDN source code
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Pages
crypt_tunnel.cc
Go to the documentation of this file.
1 /*
2  * Copyright (c) 2018 Juniper Networks, Inc. All rights reserved.
3  */
4 
5 #include <algorithm>
6 #include <boost/uuid/uuid_io.hpp>
7 #include <base/parse_object.h>
8 #include <ifmap/ifmap_link.h>
9 #include <ifmap/ifmap_table.h>
10 #include <vnc_cfg_types.h>
11 #include <agent_types.h>
12 
13 #include <cmn/agent_cmn.h>
14 #include <cfg/cfg_init.h>
15 #include <oper/instance_task.h>
16 #include <oper/crypt_tunnel.h>
17 #include <oper/agent_sandesh.h>
18 #include <oper/config_manager.h>
19 #include <oper/nexthop.h>
20 
21 using namespace autogen;
22 using namespace std;
23 
25  CryptTunnelTraceBuf(SandeshTraceBufferCreate("CryptTunnel", 5000));
26 
27 const std::string CryptTunnelTask::kCryptTunnelCmd
28 ("/usr/bin/contrail_crypt_tunnel_client.py");
29 
30 
32 
33 bool CryptTunnelEntry::IsLess(const DBEntry &rhs) const {
34  const CryptTunnelEntry &a = static_cast<const CryptTunnelEntry &>(rhs);
35  return (remote_ip_ < a.remote_ip_);
36 }
37 
39  return remote_ip_.to_string();
40 }
41 
43  CryptTunnelKey *key = new CryptTunnelKey(remote_ip_);
44  return DBEntryBase::KeyPtr(key);
45 }
46 
48  const CryptTunnelKey *k = static_cast<const CryptTunnelKey *>(key);
49  remote_ip_ = k->remote_ip_;
50 }
51 
53  UpdateTunnelReference();
54  ResyncNH();
55 }
57  Agent *agent = static_cast<CryptTunnelTable *>(get_table())->agent();
58  typedef std::list<TunnelType::Type> TunnelTypeList;
59  TunnelTypeList type_list;
60  type_list.push_back(TunnelType::MPLS_GRE);
61  type_list.push_back(TunnelType::MPLS_UDP);
62  type_list.push_back(TunnelType::VXLAN);
63  for (TunnelTypeList::const_iterator it = type_list.begin();
64  it != type_list.end(); it++) {
66  TunnelNHKey *tnh_key =
67  new TunnelNHKey(agent->fabric_vrf_name(), agent->router_id(),
68  remote_ip_.to_v4(), false, *it);
69  tnh_key->sub_op_ = AgentKey::RESYNC;
70  nh_req.key.reset(tnh_key);
71  agent->nexthop_table()->Process(nh_req);
72  }
73 }
74 
76  agent()->ConcurrencyCheck();
77  DBTablePartition *tpart =
78  static_cast<DBTablePartition *>(GetTablePartition(req.key.get()));
79  Input(tpart, NULL, &req);
80 }
81 
82 void CryptTunnelTable::CryptAvailability(const std::string &remote_ip,
83  bool &crypt_traffic,
84  bool &crypt_path_available) {
85  crypt_traffic = false;
86  crypt_path_available = false;
87  CryptTunnelEntry *entry = Find(remote_ip);
88  if (entry) {
89  crypt_traffic = entry->GetVRToVRCrypt();
90  crypt_path_available = entry->GetTunnelAvailable();
91  }
92 }
93 
94 bool CryptTunnelTable::IsCryptPathAvailable(const std::string &remote_ip) {
95  bool ret = false;
96  CryptTunnelEntry *entry = Find(remote_ip);
97  if (entry && entry->GetTunnelAvailable())
98  ret = true;
99  return ret;
100 }
101 
102 bool CryptTunnelTable::IsCryptTraffic(const std::string &remote_ip) {
103  bool ret = false;
104  CryptTunnelEntry *entry = Find(remote_ip);
105  if (entry && entry->GetVRToVRCrypt())
106  ret = true;
107  return ret;
108 }
109 
110 CryptTunnelEntry *CryptTunnelTable::Find(const std::string &remote_ip) {
111  boost::system::error_code ec;
112  IpAddress ip = IpAddress::from_string(remote_ip, ec);
113  if (ec) {
114  return NULL;
115  }
116  CryptTunnelKey key(ip);
117  return static_cast<CryptTunnelEntry *>(FindActiveEntry(&key));
118 }
119 
120 void CryptTunnelTable::Delete(const std::string &remote_ip) {
122  boost::system::error_code ec;
123  IpAddress ip = IpAddress::from_string(remote_ip, ec);
124  if (ec) {
125  return;
126  }
127  req.key.reset(new CryptTunnelKey(ip));
128  req.data.reset(NULL);
129  Process(req);
130  return;
131 }
132 
133 void CryptTunnelTable::Create(const std::string &remote_ip, bool vr_to_vr_crypt) {
135  boost::system::error_code ec;
136  IpAddress ip = IpAddress::from_string(remote_ip, ec);
137  if (ec) {
138  return;
139  }
140  req.key.reset(new CryptTunnelKey(ip));
141  req.data.reset(new CryptTunnelConfigData(vr_to_vr_crypt));
142  Process(req);
143 }
144 
145 DBTableBase *CryptTunnelTable::CreateTable(Agent *agent, DB *db, const std::string &name) {
146  CryptTunnelTable *crypt_tunnel_table = new CryptTunnelTable(agent, db, name);
147  (static_cast<DBTable *>(crypt_tunnel_table))->Init();
148  crypt_tunnel_table_ = crypt_tunnel_table;
149  return crypt_tunnel_table;
150 };
151 
152 std::unique_ptr<DBEntry> CryptTunnelTable::AllocEntry(const DBRequestKey *k) const {
153  const CryptTunnelKey *key = static_cast<const CryptTunnelKey *>(k);
155  return std::unique_ptr<DBEntry>(static_cast<DBEntry *>(e));
156 }
157 
159  const CryptTunnelKey *key = static_cast<const CryptTunnelKey *>(req->key.get());
160  CryptTunnelEntry *crypt_tunnel_entry = new CryptTunnelEntry(key->remote_ip_);
161  ChangeHandler(crypt_tunnel_entry, req);
162  crypt_tunnel_entry->SendObjectLog(GetOperDBTraceBuf(), AgentLogEvent::ADD);
163  return crypt_tunnel_entry;
164 }
165 
167  bool ret = false;
168  CryptTunnelConfigData *cdata = dynamic_cast<CryptTunnelConfigData *>(req->data.get());
169  if (cdata && cdata->vr_to_vr_crypt_ != entry->vr_to_vr_crypt_) {
170  entry->vr_to_vr_crypt_ = cdata->vr_to_vr_crypt_;
171  ret = true;
172  }
173  CryptTunnelAvailableData *tdata = dynamic_cast<CryptTunnelAvailableData *>(req->data.get());
174  if (tdata && tdata->tunnel_available_ != entry->tunnel_available_) {
175  entry->tunnel_available_ = tdata->tunnel_available_;
176  ret = true;
177  }
178  if (!entry->tunnel_task_) {
179  entry->StartCryptTunnel();
180  ret = true;
181  }
182  boost::system::error_code ec;
183  IpAddress source_ip = IpAddress::from_string(agent()->router_id().to_string(), ec);
184  entry->source_ip_ = source_ip;
185  return ret;
186 }
187 
188 bool CryptTunnelTable::OnChange(DBEntry *entry, const DBRequest *req) {
189  bool ret;
190  CryptTunnelEntry *crypt_tunnel_entry = static_cast<CryptTunnelEntry *>(entry);
191  ret = ChangeHandler(crypt_tunnel_entry, req);
192  if (ret)
193  crypt_tunnel_entry->ResyncNH();
194  crypt_tunnel_entry->UpdateTunnelReference();
195  crypt_tunnel_entry->SendObjectLog(GetOperDBTraceBuf(), AgentLogEvent::CHANGE);
196  return ret;
197 }
198 
199 bool CryptTunnelTable::Resync(DBEntry *entry, const DBRequest *req) {
200  bool ret;
201  CryptTunnelEntry *crypt_tunnel_entry = static_cast<CryptTunnelEntry *>(entry);
202  ret = ChangeHandler(crypt_tunnel_entry, req);
203  if (ret)
204  crypt_tunnel_entry->ResyncNH();
205  crypt_tunnel_entry->SendObjectLog(GetOperDBTraceBuf(), AgentLogEvent::RESYNC);
206  return ret;
207 }
208 
209 bool CryptTunnelTable::Delete(DBEntry *entry, const DBRequest *req) {
210  CryptTunnelEntry *crypt_tunnel_entry = static_cast<CryptTunnelEntry *>(entry);
211  crypt_tunnel_entry->StopCryptTunnel();
212  crypt_tunnel_entry->SendObjectLog(GetOperDBTraceBuf(), AgentLogEvent::DEL);
213  return true;
214 }
215 
216 CryptTunnelTable::CryptTunnelTable(Agent *agent, DB *db, const std::string &name) :
217  AgentDBTable(db, name), vr_to_vr_crypt_(false), crypt_interface_(NULL),
218  tunnel_event_queue_(agent->task_scheduler()->GetTaskId(kTaskCryptTunnel), 0,
219  boost::bind(&CryptTunnelTable::TunnelEventProcess, this, _1)) {
220  tunnel_event_queue_.set_name("CryptTunnel event queue");
221  set_agent(agent);
222 }
223 
226 }
227 
229 // Introspect routines
231 bool CryptTunnelEntry::DBEntrySandesh(Sandesh *sresp, std::string &name) const {
232  CryptTunnelResp *resp = static_cast<CryptTunnelResp *>(sresp);
233  if (name.empty() ||
234  name == remote_ip_.to_string()) {
235  CryptTunnelSandeshData data;
236  data.set_source(std::string());
237  data.set_remote(remote_ip_.to_string());
238  data.set_available(tunnel_available_);
239  data.set_crypt(vr_to_vr_crypt_);
240  std::vector<CryptTunnelSandeshData> &list =
241  const_cast<std::vector<CryptTunnelSandeshData>&>(resp->get_crypt_tunnel_list());
242  list.push_back(data);
243  return true;
244  }
245  return false;
246 }
247 
249  AgentLogEvent::type event) const {
250  CryptTunnelObjectLogInfo info;
251  string str;
252  switch(event) {
253  case AgentLogEvent::ADD:
254  str.assign("Addition");
255  break;
256  case AgentLogEvent::DEL:
257  str.assign("Deletion");
258  break;
259  case AgentLogEvent::CHANGE:
260  str.assign("Modification");
261  break;
262  case AgentLogEvent::RESYNC:
263  str.assign("Resync");
264  break;
265  default:
266  str.assign("");
267  break;
268  }
269  info.set_event(str);
270  info.set_remote(remote_ip_.to_string());
271  info.set_source(std::string());
272  info.set_available(tunnel_available_);
273  info.set_crypt(vr_to_vr_crypt_);
274  CRYPT_TUNNEL_OBJECT_LOG_LOG("CryptTunnel", SandeshLevel::SYS_INFO, info);
275  CRYPT_TUNNEL_TRACE_TRACE(buf, info);
276 }
277 
278 void CryptTunnelReq::HandleRequest() const {
279  AgentSandeshPtr sand(new AgentCryptTunnelSandesh(context(), get_remote()));
280  sand->DoSandesh(sand);
281 }
282 
284  const std::string &context) {
285  return AgentSandeshPtr(new AgentCryptTunnelSandesh(context,
286  args->GetString("remote")));
287 }
288 
289 
290 
293  const std::string &message) :
294  tunnel_task_(task), entry_(entry), type_(type), message_(message) {
295 }
296 
298 }
299 
300 
302 // Instance base class methods
305  entry_(NULL), active_(false), last_update_time_("-"), deleted_(false) {
306 }
307 
309  entry_ = NULL;
310 }
311 
312 void CryptTunnelTaskBase::UpdateTunnel(const CryptTunnelEntry *entry, bool available) const {
313  DBRequest req;
315  CryptTunnelKey *key = new CryptTunnelKey(*entry->GetRemoteIp());
316  key->sub_op_ = AgentKey::RESYNC;
317  req.key.reset(key);
318  CryptTunnelTable *ctable = static_cast<CryptTunnelTable *>(entry->get_table());
319  req.data.reset(new CryptTunnelAvailableData(available));
320  ctable->Process(req);
321 }
322 
324  if (entry_ == entry) {
326  return;
327  }
328  entry_ = entry;
330 }
331 
333  std::string str("Instance for crypt tunnel ");
334  str += entry_->ToString();
335  return str;
336 }
337 
338 void CryptTunnelTaskBase::OnRead(const std::string &data) {
339  CryptTunnelEvent *event =
340  new CryptTunnelEvent(this, entry_.get(),
342  data);
343  static_cast<CryptTunnelTable *>(entry_->get_table())->TunnelEventEnqueue(event);
344 }
345 
346 void CryptTunnelTaskBase::OnExit(const boost::system::error_code &ec) {
347  CryptTunnelEvent *event =
348  new CryptTunnelEvent(this, entry_.get(),
350  static_cast<CryptTunnelTable *>(entry_->get_table())->TunnelEventEnqueue(event);
351 }
352 
354  CryptTunnelEvent *event =
355  new CryptTunnelEvent(this, entry,
357  static_cast<CryptTunnelTable *>(entry_->get_table())->TunnelEventEnqueue(event);
358 }
359 
361  CryptTunnelEvent *event =
362  new CryptTunnelEvent(this, entry,
364  static_cast<CryptTunnelTable *>(entry_->get_table())->TunnelEventEnqueue(event);
365 }
366 
367 
369 
371  CryptTunnelTaskBase(entry),
372  task_(NULL) {
373 }
374 
376 }
377 
379  if (!deleted_ && task_.get() != NULL) {
380  return false;
381  }
382 
383  deleted_ = false;
384 
385  CRYPT_TUNNEL_TASK_TRACE(Trace, "Starting " + this->to_string());
386 
387  Agent *agent = static_cast<CryptTunnelTable *>(entry_->get_table())->agent();
388  task_.reset(new CryptTunnelProcessTunnel("CryptTunnel", "", 0,
389  agent->event_manager()));
390  if (task_.get() != NULL) {
391  task_->set_pipe_stdout(true);
392  task_->set_on_data_cb(
393  boost::bind(&CryptTunnelTaskBase::OnRead, this, _2));
394  task_->set_on_exit_cb(
395  boost::bind(&CryptTunnelTaskBase::OnExit, this, _2));
397  }
398 
399  return false;
400 }
401 
403  if (deleted_) {
404  return true;
405  }
406  if (task_.get() == NULL) {
407  return false;
408  }
409 
410  CRYPT_TUNNEL_TASK_TRACE(Trace, "Deleting " + this->to_string());
411  deleted_ = true;
412  active_ = false;
413  //StopTunnelTask();
415  return true;
416 }
417 
419  UpdateTunnelTaskCommand(cmd_type);
420  return task_->Run();
421 }
422 
424  task_->Stop();
425  return true;
426 }
427 
429  Agent *agent = static_cast<CryptTunnelTable *>(entry_->get_table())->agent();
430  if (agent->test_mode()) {
431  // in test mode, set task instance to run no-op shell
432  task_->set_cmd("echo success");
433  return;
434  }
435  std::stringstream cmd_str;
436  cmd_str << kCryptTunnelCmd;
437  switch (cmd_type) {
439  {
440  cmd_str << " --oper create ";
441  }
442  break;
444  {
445  cmd_str << " --oper update ";
446  }
447  break;
449  {
450  cmd_str << " --oper status ";
451  }
452  break;
454  {
455  cmd_str << " --oper delete ";
456  }
457  break;
458  default:
459  // not supported
460  assert(0);
461  }
462  cmd_str << " --source_ip " << entry_->GetSourceIp()->to_string();
463  cmd_str << " --remote_ip " << entry_->GetRemoteIp()->to_string();
464  task_->set_cmd(cmd_str.str());
465 }
466 
468  return (task_.get() != NULL ? task_->is_running(): false);
469 }
470 
472 
474  if (tunnel_task_)
476 }
477 
479  if (!tunnel_task_) {
480  tunnel_task_ = new CryptTunnelTask(this);
481  }
482  return tunnel_task_;
483 }
484 
487  delete tunnel_task_;
488  tunnel_task_ = NULL;
489  }
490  tunnel_available_ = false;
491  vr_to_vr_crypt_ = false;
492  ResyncNH();
493 }
494 
495 void
498 }
499 
501  CryptTunnelTaskBase *tunnel_task = event->tunnel_task_;
502  switch (event->type_) {
504  {
505  if (tunnel_task->deleted_)
506  break;
508  std::string msg = event->message_;
509  boost::algorithm::to_lower(msg);
510  if (msg.find("success") != std::string::npos) {
511  if (!tunnel_task->active_) {
512  tunnel_task->active_ = true;
513  tunnel_task->UpdateTunnel(tunnel_task->entry_.get(), true);
514  }
515  }
516  if (msg.find("failure") != std::string::npos) {
517  if (tunnel_task->active_) {
518  tunnel_task->active_ = false;
519  tunnel_task->UpdateTunnel(tunnel_task->entry_.get(), false);
520  }
521  }
522  //CRYPT_TUNNEL_TASK_TRACE(Trace, tunnel_task->to_string() +
523  // " Received msg = " + event->message_);
524  }
525  break;
526 
528  if (tunnel_task->deleted_) {
529  CRYPT_TUNNEL_TASK_TRACE(Trace, "Exit Deleted " + tunnel_task->to_string());
530  delete tunnel_task;
531  } else {
533  }
534  break;
535 
537  tunnel_task->set_tunnel_entry(event->entry_);
538  break;
539 
541  if (!tunnel_task->DestroyTunnelTask()) {
542  CRYPT_TUNNEL_TASK_TRACE(Trace, "Stopped " + tunnel_task->to_string());
543  delete tunnel_task;
544  }
545  break;
546 
547  default:
548  // unhandled event
549  assert(0);
550  }
551 
552  delete event;
553  return true;
554 }
virtual std::unique_ptr< DBEntry > AllocEntry(const DBRequestKey *k) const
void Delete(const std::string &remote_ip)
virtual KeyPtr GetDBRequestKey() const
Definition: crypt_tunnel.cc:42
bool test_mode() const
Definition: agent.h:1191
void Shutdown(bool delete_entries=true)
Definition: queue_task.h:152
void TunnelEventEnqueue(CryptTunnelEvent *event)
virtual bool IsRunning() const
std::string GetString(const std::string &key) const
virtual bool IsLess(const DBEntry &rhs) const
Definition: crypt_tunnel.cc:33
NextHopTable * nexthop_table() const
Definition: agent.h:475
DBTableBase * get_table() const
Definition: db_entry.cc:119
virtual DBEntry * Add(const DBRequest *req)
void CryptAvailability(const std::string &remote_ip, bool &crypt_traffic, bool &crypt_path_available)
Definition: crypt_tunnel.cc:82
virtual bool DestroyTunnelTask()
virtual bool DestroyTunnelTask()=0
boost::asio::ip::address IpAddress
Definition: address.h:13
IpAddress source_ip_
Definition: crypt_tunnel.h:81
uint8_t sub_op_
Definition: agent_db.h:106
virtual bool UpdateTunnelTask()
Definition: crypt_tunnel.h:177
virtual bool CreateTunnelTask()
std::unique_ptr< DBRequestData > data
Definition: db_table.h:49
virtual bool RunTunnelTask(CommandType cmd_type)
virtual bool CreateTunnelTask()=0
virtual bool StopTunnelTask()
Definition: task_int.h:10
bool GetTunnelAvailable() const
Definition: crypt_tunnel.h:67
bool IsCryptPathAvailable(const std::string &remote_ip)
Definition: crypt_tunnel.cc:94
virtual ~CryptTunnelTask()
boost::shared_ptr< TraceBuffer< SandeshTrace > > SandeshTraceBufferPtr
Definition: sandesh_trace.h:18
void UpdateTunnel(const CryptTunnelEntry *entry, bool available) const
std::unique_ptr< DBRequestKey > KeyPtr
Definition: db_entry.h:25
void Process(DBRequest &req)
Definition: crypt_tunnel.cc:75
CryptTunnelEvent(CryptTunnelTaskBase *inst, CryptTunnelEntry *entry, EventType type, const std::string &message)
const IpAddress * GetRemoteIp() const
Definition: crypt_tunnel.h:69
virtual void SetKey(const DBRequestKey *key)
Definition: crypt_tunnel.cc:47
static CryptTunnelTable * crypt_tunnel_table_
Definition: crypt_tunnel.h:126
virtual AgentSandeshPtr GetAgentSandesh(const AgentSandeshArguments *args, const std::string &context)
const std::string & fabric_vrf_name() const
Definition: agent.h:903
Definition: db.h:24
std::string to_string()
bool GetVRToVRCrypt() const
Definition: crypt_tunnel.h:68
void UpdateTunnelTaskCommand(CommandType cmd_type)
CryptTunnelTaskBase * StartCryptTunnel()
uint8_t type
Definition: load_balance.h:109
IpAddress remote_ip_
Definition: crypt_tunnel.h:32
Definition: agent.h:358
CryptTunnelTask(CryptTunnelEntry *entry)
Ip4Address router_id() const
Definition: agent.h:666
std::unique_ptr< DBRequestKey > key
Definition: db_table.h:48
EventManager * event_manager() const
Definition: agent.h:1103
IpAddress remote_ip_
Definition: crypt_tunnel.h:80
DBOperation oper
Definition: db_table.h:42
Definition: trace.h:220
SandeshTraceBufferPtr CryptTunnelTraceBuf
CryptTunnelEntryRef entry_
Definition: crypt_tunnel.h:200
bool TunnelEventProcess(CryptTunnelEvent *event)
void set_tunnel_entry(CryptTunnelEntry *entry)
virtual ~CryptTunnelEvent()
class boost::shared_ptr< AgentSandesh > AgentSandeshPtr
Definition: agent_db.h:18
CryptTunnelTaskBase(CryptTunnelEntry *entry)
#define kTaskCryptTunnel
Definition: agent.h:334
virtual bool OnChange(DBEntry *entry, const DBRequest *req)
bool IsCryptTraffic(const std::string &remote_ip)
CryptTunnelTask * tunnel_task_
Definition: crypt_tunnel.h:84
void OnRead(const std::string &data)
CryptTunnelEntry * Find(const std::string &remote_ip)
virtual string ToString() const
Definition: crypt_tunnel.cc:38
void SetTunnelEntry(CryptTunnelEntry *entry)
virtual bool RunTunnelTask(CommandType cmd_type)=0
#define CRYPT_TUNNEL_TASK_TRACE(obj,...)
Definition: crypt_tunnel.h:14
static uint64_t UTCTimestampUsec()
Definition: time_util.h:13
void Process(DBRequest &req)
Definition: nexthop.cc:367
bool DBEntrySandesh(Sandesh *sresp, std::string &name) const
virtual bool Resync(DBEntry *entry, const DBRequest *req)
static const std::string kCryptTunnelCmd
Definition: crypt_tunnel.h:218
CryptTunnelEntry * entry() const
Definition: crypt_tunnel.h:193
WorkQueue< CryptTunnelEvent * > tunnel_event_queue_
Definition: crypt_tunnel.h:130
void SendObjectLog(SandeshTraceBufferPtr ptr, AgentLogEvent::type event) const
void Create(const std::string &remote_ip, bool crypt)
void StopTask(CryptTunnelEntry *service)
CryptTunnelTable(Agent *agent, DB *db, const std::string &name)
void OnExit(const boost::system::error_code &ec)
void UpdateTunnelReference()
CryptTunnelEntry * entry_
Definition: crypt_tunnel.h:151
InstanceTaskExecvp CryptTunnelProcessTunnel
Definition: crypt_tunnel.h:217
bool Enqueue(QueueEntryT entry)
Definition: queue_task.h:248
static DBTableBase * CreateTable(Agent *agent, DB *db, const std::string &name)
bool ChangeHandler(CryptTunnelEntry *entry, const DBRequest *req)
void set_name(const std::string &name)
Definition: queue_task.h:307
struct task_ task
void set_agent(Agent *agent)
Definition: agent_db.h:212
std::string last_update_time_
Definition: crypt_tunnel.h:205
virtual ~CryptTunnelTaskBase()
SandeshTraceBufferPtr SandeshTraceBufferCreate(const std::string &buf_name, size_t buf_size, bool trace_enable=true)
Definition: sandesh_trace.h:46
virtual ~CryptTunnelTable()
static std::string UTCUsecToString(uint64_t tstamp)
Definition: time_util.h:54