Revised OpenFlow Library  v0.6.0dev
 All Classes Files Functions Variables Friends Groups Pages
crofchan.h
1 /*
2  * crofchan.h
3  *
4  * Created on: 31.12.2013
5  * Author: andreas
6  */
7 
8 #ifndef CROFCHAN_H_
9 #define CROFCHAN_H_
10 
11 #include <map>
12 #include <bitset>
13 #include <inttypes.h>
14 
15 #include "rofl/common/croflexception.h"
16 #include "rofl/common/ciosrv.h"
17 #include "rofl/common/crofconn.h"
18 #include "rofl/common/openflow/messages/cofmsg.h"
19 #include "rofl/common/openflow/cofhelloelemversionbitmap.h"
20 #include "rofl/common/crandom.h"
21 #include "rofl/common/ctimerid.h"
22 #include "rofl/common/cauxid.h"
23 
24 namespace rofl {
25 
26 class eRofChanBase : public RoflException {};
27 class eRofChanNotFound : public eRofChanBase {};
28 class eRofChanExists : public eRofChanBase {};
29 class eRofChanInval : public eRofChanBase {};
31 
32 class crofchan; // forward declaration
33 
40 class crofchan_env {
41  static std::set<crofchan_env*> rofchan_envs;
42 
43 public:
44 
49  { crofchan_env::rofchan_envs.insert(this); };
50 
54  virtual
56  { crofchan_env::rofchan_envs.erase(this); };
57 
58 protected:
59 
60  friend class crofchan;
61 
65  virtual void
67  crofchan& chan,
68  const rofl::cauxid& auxid)
69  {};
70 
74  virtual void
76  crofchan& chan,
77  const rofl::cauxid& auxid)
78  {};
79 
83  virtual void
85  crofchan& chan,
86  const rofl::cauxid& auxid)
87  {};
88 
92  virtual void
94  crofchan& chan,
95  const rofl::cauxid& auxid)
96  {};
97 
107  virtual void
108  handle_write(crofchan& chan, const cauxid& auxid) = 0;
109 
120  virtual void
121  recv_message(crofchan& chan, const cauxid& aux_id, rofl::openflow::cofmsg *msg) = 0;
122 
128  virtual uint32_t
129  get_async_xid(crofchan& chan) = 0;
130 
136  virtual uint32_t
137  get_sync_xid(crofchan& chan, uint8_t msg_type = 0, uint16_t msg_sub_type = 0) = 0;
138 
144  virtual void
145  release_sync_xid(crofchan& chan, uint32_t xid) = 0;
146 };
147 
148 
149 
154 class crofchan :
155  public rofl::ciosrv,
156  public crofconn_env
157 {
158  enum crofchan_event_t {
159  EVENT_NONE = 0,
160  EVENT_CONN_ESTABLISHED = 1,
161  EVENT_CONN_TERMINATED = 2, // by peer
162  EVENT_CONN_REFUSED = 3,
163  EVENT_CONN_FAILED = 4,
164  };
165 
166  enum crofchan_timer_t {
167  TIMER_NONE = 0,
168  TIMER_RUN_ENGINE = 1,
169  };
170 
171  enum crofchan_flag_t {
172  FLAG_ENGINE_IS_RUNNING = 0,
173  };
174 
175 public:
176 
180  crofchan() :
181  env(NULL),
182  ofp_version(rofl::openflow::OFP_VERSION_UNKNOWN)
183  {};
184 
188  crofchan(
189  crofchan_env *env,
190  rofl::openflow::cofhello_elem_versionbitmap const& versionbitmap) :
191  env(env),
192  versionbitmap(versionbitmap),
193  ofp_version(rofl::openflow::OFP_VERSION_UNKNOWN)
194  {};
195 
199  virtual
200  ~crofchan() {
201  close();
202  };
203 
204 public:
205 
209  bool
210  is_established() const;
211 
215  uint8_t
216  get_version() const
217  { return ofp_version; };
218 
223  get_versionbitmap() const
224  { return versionbitmap; };
225 
229  void
230  close();
231 
235  unsigned int
236  send_message(
237  const cauxid& aux_id, rofl::openflow::cofmsg *msg);
238 
239 
240 public:
241 
245  cauxid
246  get_next_auxid();
247 
251  std::list<cauxid>
252  get_conn_index() const;
253 
257  crofconn&
258  add_conn(
259  const cauxid& aux_id,
260  enum rofl::csocket::socket_type_t socket_type,
261  cparams const& socket_params);
262 
266  crofconn&
267  add_conn(
268  const cauxid& aux_id, crofconn* conn);
269 
273  crofconn&
274  set_conn(
275  const cauxid& aux_id);
276 
280  const crofconn&
281  get_conn(
282  const cauxid& aux_id) const;
283 
287  void
288  drop_conn(
289  const cauxid& aux_id);
290 
294  bool
295  has_conn(
296  const cauxid& aux_id) const;
297 
298 private:
299 
303  virtual void
304  handle_connect_refused(crofconn& conn) {
305  rofl::logging::debug2 << "[rofl-common][crofchan] "
306  << "connection refused, auxid: " << conn.get_aux_id().str() << std::endl;
307  rofl::RwLock rwlock(conns_refused_rwlock, rofl::RwLock::RWLOCK_WRITE);
308  conns_refused.push_back(conn.get_aux_id());
309  push_on_eventqueue(EVENT_CONN_REFUSED);
310  if (rofl::cauxid(0) == conn.get_aux_id()) {
311  for (std::map<rofl::cauxid, crofconn*>::iterator
312  it = conns.begin(); it != conns.end(); ++it) {
313  if (conn.get_aux_id() == it->first) {
314  continue;
315  }
316  if (it->second->is_established()) {
317  it->second->close();
318  conns_terminated.push_back(it->first);
319  }
320  }
321  push_on_eventqueue(EVENT_CONN_TERMINATED);
322  }
323  };
324 
328  virtual void
329  handle_connect_failed(crofconn& conn) {
330  rofl::logging::debug2 << "[rofl-common][crofchan] "
331  << "connection failed, auxid: " << conn.get_aux_id().str() << std::endl;
332  rofl::RwLock rwlock(conns_failed_rwlock, rofl::RwLock::RWLOCK_WRITE);
333  conns_failed.push_back(conn.get_aux_id());
334  push_on_eventqueue(EVENT_CONN_FAILED);
335  if (rofl::cauxid(0) == conn.get_aux_id()) {
336  for (std::map<rofl::cauxid, crofconn*>::iterator
337  it = conns.begin(); it != conns.end(); ++it) {
338  if (conn.get_aux_id() == it->first) {
339  continue;
340  }
341  if (it->second->is_established()) {
342  it->second->close();
343  conns_terminated.push_back(it->first);
344  }
345  }
346  push_on_eventqueue(EVENT_CONN_TERMINATED);
347  }
348  };
349 
353  virtual void
354  handle_connected(crofconn& conn, uint8_t ofp_version) {
355  rofl::logging::debug2 << "[rofl-common][crofchan] "
356  << "connection established, auxid: "
357  << conn.get_aux_id().str() << std::endl;
358  if (rofl::cauxid(0) == conn.get_aux_id()) {
359  this->ofp_version = ofp_version;
360 
361  for (std::map<cauxid, crofconn*>::iterator
362  it = conns.begin(); it != conns.end(); ++it) {
363  if (0 == it->first.get_id())
364  continue;
365  if (it->second->is_actively_established()) {
366  it->second->reconnect(true);
367  }
368  }
369 
370  } else {
371  if (this->ofp_version != ofp_version) {
372  rofl::logging::warn << "[rofl-common][crofchan] "
373  << "auxiliary connection with invalid OFP version "
374  << "negotiated, closing connection. " << conn.str() << std::endl;
375 
376  drop_conn(conn.get_aux_id());
377  return;
378 
379  }
380  }
381  rofl::RwLock rwlock(conns_established_rwlock, rofl::RwLock::RWLOCK_WRITE);
382  conns_established.push_back(conn.get_aux_id());
383  push_on_eventqueue(EVENT_CONN_ESTABLISHED);
384  };
385 
389  virtual void
390  handle_closed(crofconn& conn) {
391  rofl::logging::debug2 << "[rofl-common][crofchan] "
392  << "connection terminated, auxid: " << conn.get_aux_id().str() << std::endl;
393  if (conn.get_aux_id() == rofl::cauxid(0)) {
394  this->ofp_version = rofl::openflow::OFP_VERSION_UNKNOWN;
395  }
396  rofl::RwLock rwlock(conns_terminated_rwlock, rofl::RwLock::RWLOCK_WRITE);
397  conns_terminated.push_back(conn.get_aux_id());
398  push_on_eventqueue(EVENT_CONN_TERMINATED);
399  if (rofl::cauxid(0) == conn.get_aux_id()) {
400  for (std::map<rofl::cauxid, crofconn*>::iterator
401  it = conns.begin(); it != conns.end(); ++it) {
402  if (conn.get_aux_id() == it->first) {
403  continue;
404  }
405  if (it->second->is_established()) {
406  it->second->close();
407  conns_terminated.push_back(it->first);
408  }
409  }
410  }
411  };
412 
416  virtual void
417  handle_write(crofconn& conn) {
418  env->handle_write(*this, conn.get_aux_id());
419  };
420 
421  virtual void
422  recv_message(crofconn& conn, rofl::openflow::cofmsg *msg) {
423  env->recv_message(*this, conn.get_aux_id(), msg);
424  };
425 
429  virtual uint32_t
430  get_async_xid(crofconn& conn) {
431  return env->get_async_xid(*this);
432  };
433 
437  virtual uint32_t
438  get_sync_xid(crofconn& conn, uint8_t msg_type = 0, uint16_t msg_sub_type = 0) {
439  return env->get_sync_xid(*this, msg_type, msg_sub_type);
440  };
441 
445  virtual void
446  release_sync_xid(crofconn& conn, uint32_t xid) {
447  env->release_sync_xid(*this, xid);
448  };
449 
450 private:
451 
455  virtual void
456  handle_timeout(
457  int opaque, void* data = (void*)0);
458 
462  void
463  push_on_eventqueue(
464  enum crofchan_event_t event = EVENT_NONE);
465 
469  void
470  work_on_eventqueue();
471 
475  void
476  event_conn_established();
477 
481  void
482  event_conn_terminated();
483 
487  void
488  event_conn_refused();
489 
493  void
494  event_conn_failed();
495 
499  crofchan_env&
500  call_env() {
501  if (crofchan_env::rofchan_envs.find(env) == crofchan_env::rofchan_envs.end()) {
502  throw eRofChanNotFound();
503  }
504  return *env;
505  };
506 
507 public:
508 
509  friend std::ostream&
510  operator<< (std::ostream& os, crofchan const& chan) {
511  os << indent(0) << "<crofchan established:" << chan.is_established()
512  << " ofp-version: " << (int)chan.ofp_version << " >" << std::endl;
513  indent i(2);
514  os << chan.versionbitmap;
515  for (std::map<cauxid, crofconn*>::const_iterator
516  it = chan.conns.begin(); it != chan.conns.end(); ++it) {
517  os << *(it->second);
518  }
519  return os;
520  };
521 
522 
523  std::string
524  str() const {
525  std::stringstream ss;
526  ss << "OFP version: " << (int)get_version() << " ";
527  if (conns.empty() ||
528  (conns.find(rofl::cauxid(0)) == conns.end()) ||
529  (not (conns.begin()->second)->is_established())) {
530  ss << " state: -disconnected- ";
531  } else {
532  ss << " state: -established- ";
533  }
534  ss << "auxids: ";
535  for (std::map<cauxid, crofconn*>::const_iterator
536  it = conns.begin(); it != conns.end(); ++it) {
537  ss << "{" << (int)it->first.get_id() << ":"
538  << (it->second->is_established() ? "-established-" : "-disconnected-") << "} ";
539  }
540  return ss.str();
541  };
542 
543 private:
544 
545  // owner of this crofchan instance
546  crofchan_env* env;
547  // main and auxiliary connections
548  std::map<cauxid, crofconn*> conns;
549  // supported OFP versions
551  versionbitmap;
552  // OFP version negotiated
553  uint8_t ofp_version;
554  // state related flags
555  std::bitset<32> flags;
556  // event queue
557  std::deque<enum crofchan_event_t> events;
558 
559  // established connection ids
560  std::list<rofl::cauxid> conns_established;
561  // rwlock
562  PthreadRwLock conns_established_rwlock;
563  // terminated connection ids
564  std::list<rofl::cauxid> conns_terminated;
565  // rwlock
566  PthreadRwLock conns_terminated_rwlock;
567  // refused connection ids
568  std::list<rofl::cauxid> conns_refused;
569  // rwlock
570  PthreadRwLock conns_refused_rwlock;
571  // failed connection ids
572  std::list<rofl::cauxid> conns_failed;
573  // rwlock
574  PthreadRwLock conns_failed_rwlock;
575 };
576 
577 }; /* namespace rofl */
578 
579 #endif /* CROFCHAN_H_ */
Definition: cauxid.h:30
cauxid const & get_aux_id() const
Return auxialiary_id.
Definition: crofconn.h:334
Definition: cparams.h:20
virtual void handle_conn_failed(crofchan &chan, const rofl::cauxid &auxid)
Called in the event of a connection failed (except refused)
Definition: crofchan.h:93
virtual void handle_write(crofchan &chan, const cauxid &auxid)=0
Called after a congestion situation has been resolved.
Definition: cofhelloelemversionbitmap.h:22
Environment expected by a rofl::crofchan instance.
Definition: crofchan.h:40
A single OpenFlow control connection.
Definition: crofconn.h:145
Definition: thread_helper.h:25
Environment expected by a rofl::crofconn instance.
Definition: crofconn.h:40
virtual uint32_t get_async_xid(crofchan &chan)=0
Acquires an OpenFlow transaction ID for an asynchronous message.
Definition: thread_helper.h:88
virtual void handle_conn_terminated(crofchan &chan, const rofl::cauxid &auxid)
Called upon a peer initiated termination of a control connection within the control channel...
Definition: crofchan.h:75
crofchan_env()
crofchan_env constructor
Definition: crofchan.h:48
Definition: crofchan.h:27
virtual ~crofchan_env()
crofchan_env destructor
Definition: crofchan.h:55
Definition: crofchan.h:26
Base class for IO services.
Definition: ciosrv.h:491
Definition: logging.h:76
Definition: crofchan.h:30
Definition: crofchan.h:29
virtual void handle_conn_established(crofchan &chan, const rofl::cauxid &auxid)
Called upon establishment of a control connection within the control channel.
Definition: crofchan.h:66
Definition: crofchan.h:28
virtual uint32_t get_sync_xid(crofchan &chan, uint8_t msg_type=0, uint16_t msg_sub_type=0)=0
Acquires an OpenFlow transaction ID for a synchronous message.
virtual void recv_message(crofchan &chan, const cauxid &aux_id, rofl::openflow::cofmsg *msg)=0
Called upon reception of an OpenFlow message by the peer entity.
An OpenFlow control channel grouping multiple control connections.
Definition: crofchan.h:154
crofconn & add_conn(const cauxid &aux_id, enum rofl::csocket::socket_type_t socket_type, cparams const &socket_params)
Add a new connection while creating a new crofconn instance and do a socket connect.
Definition: crofchan.cc:69
virtual void release_sync_xid(crofchan &chan, uint32_t xid)=0
Releases a synchronous transaction ID after reception of an OpenFlow reply.
virtual void handle_conn_refused(crofchan &chan, const rofl::cauxid &auxid)
Called in the event of a connection refused.
Definition: crofchan.h:84
Definition: croflexception.h:27
Definition: cofmsg.h:62