Revised OpenFlow Library  v0.6.0dev
 All Classes Files Functions Variables Friends Groups Pages
crofconn.h
1 /*
2  * crofchan.h
3  *
4  * Created on: 31.12.2013
5  * Author: andreas
6  */
7 
8 #ifndef CROFCONN_H_
9 #define CROFCONN_H_
10 
11 #include <inttypes.h>
12 #include <bitset>
13 #include <set>
14 
15 #include "rofl/common/ciosrv.h"
16 #include "rofl/common/crofsock.h"
17 #include "rofl/common/openflow/cofhelloelems.h"
18 #include "rofl/common/openflow/cofhelloelemversionbitmap.h"
19 #include "rofl/common/crandom.h"
20 #include "rofl/common/csegmentation.h"
21 #include "rofl/common/ctimerid.h"
22 #include "rofl/common/cauxid.h"
23 #include "rofl/common/cthread.h"
24 #include "rofl/common/crofqueue.h"
25 
26 namespace rofl {
27 
28 class eRofConnBase : public RoflException {};
30 class eRofConnBusy : public eRofConnBase {}; // connection already established
31 class eRofConnNotFound : public eRofConnBase {};
32 
33 class crofconn; // forward declaration
34 
40 class crofconn_env {
41  static std::set<crofconn_env*> rofconn_envs;
42 public:
43 
47  static crofconn_env&
48  set_env(crofconn_env* env) {
49  if (crofconn_env::rofconn_envs.find(env) == crofconn_env::rofconn_envs.end()) {
50  throw eRofConnNotFound();
51  }
52  return *(env);
53  };
54 
58  static bool
59  has_env(crofconn_env* env) {
60  return (not (crofconn_env::rofconn_envs.find(env) == crofconn_env::rofconn_envs.end()));
61  };
62 
63 public:
64 
68  crofconn_env() {
69  crofconn_env::rofconn_envs.insert(this);
70  };
71 
75  virtual ~crofconn_env() {
76  crofconn_env::rofconn_envs.erase(this);
77  };
78 
79 protected:
80 
81  friend class crofconn;
82 
86  virtual void
87  handle_connect_refused(crofconn& conn) = 0;
88 
92  virtual void
93  handle_connect_failed(crofconn& conn) = 0;
94 
98  virtual void
99  handle_connected(crofconn& conn, uint8_t ofp_version) = 0;
100 
104  virtual void
105  handle_closed(crofconn& conn) = 0;
106 
110  virtual void
111  handle_write(crofconn& conn) = 0;
112 
116  virtual void
117  recv_message(crofconn& conn, rofl::openflow::cofmsg *msg) = 0;
118 
122  virtual uint32_t
123  get_async_xid(crofconn& conn) = 0;
124 
128  virtual uint32_t
129  get_sync_xid(crofconn& conn, uint8_t msg_type = 0, uint16_t msg_sub_type = 0) = 0;
130 
134  virtual void
135  release_sync_xid(crofconn& conn, uint32_t xid) = 0;
136 };
137 
138 
139 
140 
145 class crofconn :
146  public crofsock_env,
147  public ciosrv,
148  public rofl::common::cthread
149 {
150  enum outqueue_type_t {
151  QUEUE_OAM = 0, // Echo.request/Echo.reply
152  QUEUE_MGMT = 1, // all remaining packets, except ...
153  QUEUE_FLOW = 2, // Flow-Mod/Flow-Removed
154  QUEUE_PKT = 3, // Packet-In/Packet-Out
155  QUEUE_MAX, // do not use
156  };
157 
158  enum msg_type_t {
159  OFPT_HELLO = 0,
160  OFPT_ERROR = 1,
161  OFPT_ECHO_REQUEST = 2,
162  OFPT_ECHO_REPLY = 3,
163  OFPT_FEATURES_REPLY = 6,
164  OFPT_MULTIPART_REQUEST = 18,
165  OFPT_MULTIPART_REPLY = 19,
166  };
167 
168  enum crofconn_event_t {
169  EVENT_NONE = 0,
170  EVENT_RECONNECT = 1,
171  EVENT_TCP_CONNECTED = 2,
172  EVENT_DISCONNECTED = 3,
173  EVENT_HELLO_RCVD = 4,
174  EVENT_HELLO_EXPIRED = 5,
175  EVENT_FEATURES_RCVD = 6,
176  EVENT_FEATURES_EXPIRED = 7,
177  EVENT_ECHO_RCVD = 8,
178  EVENT_ECHO_EXPIRED = 9,
179  EVENT_NEED_LIFE_CHECK = 10,
180  //
181  EVENT_RXQUEUE = 11,
182  EVENT_CONNECT_FAILED = 13,
183  EVENT_CONNECT_REFUSED = 14,
184  EVENT_LOCAL_DISCONNECT = 15,
185  EVENT_CONGESTION_SOLVED = 16,
186  EVENT_PEER_DISCONNECTED = 17, // socket was closed by peer entity
187  };
188 
189  enum crofconn_state_t {
190  STATE_INIT = 0,
191  STATE_DISCONNECTED = 1,
192  STATE_CONNECT_PENDING = 2,
193  STATE_ACCEPT_PENDING = 3,
194  STATE_WAIT_FOR_HELLO = 4,
195  STATE_WAIT_FOR_FEATURES = 5,
196  STATE_CONNECTED = 6,
197  };
198 
199  enum crofconn_timer_t {
200  TIMER_NEXT_RECONNECT = 1,
201  TIMER_WAIT_FOR_HELLO = 2,
202  TIMER_WAIT_FOR_FEATURES = 3,
203  TIMER_NEED_LIFE_CHECK = 4,
204  TIMER_WAIT_FOR_ECHO = 5,
205  };
206 
207  enum crofconn_flags_t {
208  FLAGS_PASSIVE = 1,
209  FLAGS_CONNECT_REFUSED = 2,
210  FLAGS_CONNECT_FAILED = 3,
211  FLAGS_LOCAL_DISCONNECT = 4,
212  FLAGS_RECONNECTING = 5,
213  FLAGS_RXQUEUE_CONSUMING = 6,
214  FLAGS_CONGESTED = 7,
215  FLAGS_PEER_DISCONNECTED = 8,
216  };
217 
218 public:
219 
220  enum crofconn_flavour_t {
221  FLAVOUR_UNSPECIFIED = 0,
222  FLAVOUR_CTL = 1,
223  FLAVOUR_DPT = 2,
224  };
225 
226 public:
227 
231  crofconn(
232  crofconn_env *env,
233  const rofl::openflow::cofhello_elem_versionbitmap& versionbitmap);
234 
238  virtual ~crofconn();
239 
240 public:
241 
245  enum crofconn_flavour_t
246  get_flavour() const
247  { return flavour; };
248 
252  void
253  accept(
254  enum rofl::csocket::socket_type_t socket_type,
255  const cparams& socket_params,
256  int newsd,
257  enum crofconn_flavour_t flavour);
258 
262  void
263  connect(
264  const cauxid& aux_id,
265  enum rofl::csocket::socket_type_t socket_type,
266  const cparams& socket_params);
267 
271  void
272  reconnect(
273  bool reset_backoff_timer = false);
274 
278  void
279  close();
280 
284  bool
286  { return (STATE_CONNECTED == state); }
287 
291  bool
293  { return not flags.test(FLAGS_PASSIVE); };
294 
298  bool
299  is_congested() const
300  { return flags.test(FLAGS_CONGESTED); };
301 
307  { return versionbitmap; };
308 
314  { return versionbitmap_peer; };
315 
319  uint8_t
320  get_version() const
321  { return ofp_version; };
322 
326  uint64_t
327  get_dpid() const
328  { return dpid; };
329 
333  cauxid const&
334  get_aux_id() const
335  { return auxiliary_id; };
336 
340  crofsock const&
341  get_rofsocket() const
342  { return *rofsock; };
343 
347  unsigned int
350  { return fragment_and_send_message(msg); };
351 
355  void
356  set_env(
357  crofconn_env* env)
358  { this->env = env; };
359 
363  void
364  set_max_backoff(
365  const ctimespec& timespec);
366 
367 protected:
368 
369  virtual void
370  init_thread();
371 
372  virtual void
373  release_thread();
374 
375 private:
376 
377  virtual void
378  handle_connect_refused(
379  crofsock& rofsock) {
380  rofl::logging::warn << "[rofl-common][crofconn] transport connection: connect refused " << std::endl;
381  rofl::ciosrv::notify(rofl::cevent(EVENT_CONNECT_REFUSED));
382  };
383 
384  virtual void
385  handle_connect_failed(
386  crofsock& rofsock) {
387  rofl::logging::debug << "[rofl-common][crofconn] transport connection: connect failed " << std::endl;
388  rofl::ciosrv::notify(rofl::cevent(EVENT_CONNECT_FAILED));
389  };
390 
391  virtual void
392  handle_connected (
393  crofsock& rofsock) {
394  rofl::logging::debug << "[rofl-common][crofconn] transport connection established " << std::endl;
395  rofl::ciosrv::notify(rofl::cevent(EVENT_TCP_CONNECTED));
396  };
397 
398  virtual void
399  handle_closed(
400  crofsock& rofsock) {
401  rofl::logging::debug << "[rofl-common][crofconn] transport connection closed " << std::endl;
402  rofl::ciosrv::notify(rofl::cevent(EVENT_PEER_DISCONNECTED));
403  };
404 
405  virtual void
406  handle_write(
407  crofsock& rofsock) {
408  rofl::logging::debug << "[rofl-common][crofconn] transport connection congested " << std::endl;
409  rofl::ciosrv::notify(rofl::cevent(EVENT_CONGESTION_SOLVED));
410  };
411 
412  virtual void
413  recv_message(
414  crofsock& rofsock,
416 
417 private:
418 
422  void
423  handle_messages();
424 
428  void
429  send_message_to_env(
431 
435  virtual void
436  handle_timeout(
437  int opaque,
438  void *data = (void*)0);
439 
443  virtual void
444  handle_event(
445  const cevent& ev) {
446  switch (ev.get_cmd()) {
447  case EVENT_RXQUEUE: {
448  handle_messages();
449  } break;
450  case EVENT_TCP_CONNECTED: {
451  flags.reset(FLAGS_RECONNECTING);
452  run_engine(EVENT_TCP_CONNECTED);
453  } break;
454  case EVENT_CONNECT_FAILED: {
455  flags.set(FLAGS_CONNECT_FAILED);
456  run_engine(EVENT_DISCONNECTED);
457  } break;
458  case EVENT_CONNECT_REFUSED: {
459  flags.set(FLAGS_CONNECT_REFUSED);
460  run_engine(EVENT_DISCONNECTED);
461  } break;
462  case EVENT_LOCAL_DISCONNECT: {
463  flags.set(FLAGS_LOCAL_DISCONNECT);
464  run_engine(EVENT_DISCONNECTED);
465  } break;
466  case EVENT_CONGESTION_SOLVED: {
467  flags.reset(FLAGS_CONGESTED);
468  crofconn_env::set_env(env).handle_write(*this);
469  } break;
470  case EVENT_PEER_DISCONNECTED: {
471  flags.set(FLAGS_PEER_DISCONNECTED);
472  run_engine(EVENT_DISCONNECTED);
473  } break;
474  }
475  };
476 
480  void
481  run_engine(
482  enum crofconn_event_t event = EVENT_NONE);
483 
487  void
488  event_reconnect();
489 
493  void
494  event_tcp_connected();
495 
499  void
500  event_disconnected();
501 
505  void
506  event_hello_rcvd();
507 
511  void
512  event_hello_expired();
513 
517  void
518  event_features_rcvd();
519 
523  void
524  event_features_expired();
525 
529  void
530  event_echo_rcvd();
531 
535  void
536  event_echo_expired();
537 
541  void
542  event_need_life_check();
543 
547  void
548  action_send_hello_message();
549 
553  void
554  action_send_features_request();
555 
559  void
560  action_disconnect();
561 
565  void
566  action_send_echo_request();
567 
571  void
572  backoff_reconnect(
573  bool reset_timeout = false);
574 
575 private:
576 
580  void
581  hello_rcvd(
583 
587  void
588  echo_request_rcvd(
590 
594  void
595  echo_reply_rcvd(
597 
601  void
602  error_rcvd(
604 
608  void
609  features_reply_rcvd(
611 
615  unsigned int
616  fragment_and_send_message(
618 
622  unsigned int
623  fragment_table_features_stats_request(
625 
629  unsigned int
630  fragment_flow_stats_reply(
632 
636  unsigned int
637  fragment_table_stats_reply(
639 
643  unsigned int
644  fragment_port_stats_reply(
646 
650  unsigned int
651  fragment_queue_stats_reply(
653 
657  unsigned int
658  fragment_group_stats_reply(
660 
664  unsigned int
665  fragment_group_desc_stats_reply(
667 
671  unsigned int
672  fragment_table_features_stats_reply(
674 
678  unsigned int
679  fragment_port_desc_stats_reply(
681 
685  unsigned int
686  fragment_meter_stats_reply(
688 
692  unsigned int
693  fragment_meter_config_stats_reply(
695 
699  void
700  timer_start(
701  crofconn_timer_t type, const ctimespec& timespec);
702 
706  void
707  timer_stop(
708  crofconn_timer_t type);
709 
713  void
714  timer_start_next_reconnect() {
715  timer_start(TIMER_NEXT_RECONNECT, reconnect_timespec);
716  };
717 
721  void
722  timer_stop_next_reconnect() {
723  timer_stop(TIMER_NEXT_RECONNECT);
724  };
725 
729  void
730  timer_start_life_check() {
731  timer_start(TIMER_NEED_LIFE_CHECK, echo_interval);
732  };
733 
737  void
738  timer_stop_life_check() {
739  timer_stop(TIMER_NEED_LIFE_CHECK);
740  };
741 
745  void
746  timer_start_wait_for_hello() {
747  timer_start(TIMER_WAIT_FOR_HELLO, hello_timeout);
748  };
749 
753  void
754  timer_stop_wait_for_hello() {
755  timer_stop(TIMER_WAIT_FOR_HELLO);
756  };
757 
761  void
762  timer_start_wait_for_features() {
763  timer_start(TIMER_WAIT_FOR_FEATURES, echo_interval);
764  };
765 
769  void
770  timer_stop_wait_for_features() {
771  timer_stop(TIMER_WAIT_FOR_FEATURES);
772  };
773 
777  void
778  timer_start_wait_for_echo() {
779  timer_start(TIMER_WAIT_FOR_ECHO, echo_timeout);
780  };
781 
785  void
786  timer_stop_wait_for_echo() {
787  timer_stop(TIMER_WAIT_FOR_ECHO);
788  };
789 
790 public:
791 
792  friend std::ostream&
793  operator<< (std::ostream& os, const crofconn& conn) {
794  os << indent(0) << "<crofconn ofp-version:" << (int)conn.ofp_version
795  << " OFP-transport-connection-established: " << (bool)(conn.state == STATE_CONNECTED)
796  << " >" << std::endl;
797  { rofl::indent i(2); os << conn.get_aux_id(); }
798  if (conn.state == STATE_DISCONNECTED) {
799  os << indent(2) << "<state: -DISCONNECTED- >" << std::endl;
800  }
801  else if (conn.state == STATE_CONNECT_PENDING) {
802  os << indent(2) << "<state: -CONNECT-PENDING- >" << std::endl;
803  }
804  else if (conn.state == STATE_ACCEPT_PENDING) {
805  os << indent(2) << "<state: -ACCEPT-PENDING- >" << std::endl;
806  }
807  else if (conn.state == STATE_WAIT_FOR_HELLO) {
808  os << indent(2) << "<state: -WAIT-FOR-HELLO- >" << std::endl;
809  }
810  else if (conn.state == STATE_WAIT_FOR_FEATURES) {
811  os << indent(2) << "<state: -WAIT-FOR-FEATURES- >" << std::endl;
812  }
813  else if (conn.state == STATE_CONNECTED) {
814  os << indent(2) << "<state: -ESTABLISHED- >" << std::endl;
815  }
816  { os << rofl::indent(2) << "<current-backoff: >" << std::endl; rofl::indent i(4); os << conn.reconnect_timespec; };
817  { os << rofl::indent(2) << "<max-backoff: >" << std::endl; rofl::indent i(4); os << conn.max_backoff; };
818 #if 0
819  os << indent(2) << "<versionbitmap-local: >" << std::endl;
820  { indent i(4); os << conn.versionbitmap; }
821  os << indent(2) << "<versionbitmap-remote: >" << std::endl;
822  { indent i(4); os << conn.versionbitmap_peer; }
823 #endif
824  return os;
825  };
826 
827  std::string
828  str() const {
829  std::stringstream ss;
830  if (state == STATE_DISCONNECTED) {
831  ss << "state: -DISCONNECTED- ";
832  }
833  else if (state == STATE_CONNECT_PENDING) {
834  ss << "state: -CONNECT-PENDING- ";
835  ss << "backoff: " << reconnect_timespec.str();
836  }
837  else if (state == STATE_ACCEPT_PENDING) {
838  ss << "state: -ACCEPT-PENDING- ";
839  }
840  else if (state == STATE_WAIT_FOR_HELLO) {
841  ss << "state: -WAIT-FOR-HELLO- ";
842  }
843  else if (state == STATE_WAIT_FOR_FEATURES) {
844  ss << "state: -WAIT-FOR-FEATURES- ";
845  }
846  else if (state == STATE_CONNECTED) {
847  ss << "state: -ESTABLISHED- ";
848  }
849  return ss.str();
850  };
851 
852 private:
853 
854  crofconn_env* env;
855  uint64_t dpid;
856  cauxid auxiliary_id;
857  crofsock* rofsock;
859  versionbitmap; // supported OFP versions by this entity
861  versionbitmap_peer; // supported OFP versions by peer entity
862  uint8_t ofp_version; // negotiated OFP version
863  std::bitset<32> flags;
864  csegmentation sar; // segmentation and reassembly for multipart messages
865  size_t fragmentation_threshold;// maximum number of bytes for a multipart message before being fragmented
866 
867  static unsigned int const
868  DEFAULT_FRAGMENTATION_THRESHOLD = 65535;
869  static unsigned int const
870  DEFAULT_ETHERNET_MTU_SIZE = 1500;
871  ctimespec max_backoff;
872  ctimespec reconnect_start_timeout;
873  ctimespec reconnect_timespec; // reconnect in x seconds
874  ctimespec reconnect_variance;
875  int reconnect_counter;
876 
877  static const int CROFCONN_RECONNECT_START_TIMEOUT_IN_NSECS = 10000000; // start reconnect timeout (default 10ms)
878  static const int CROFCONN_RECONNECT_VARIANCE_IN_NSECS = 10000000; // reconnect variance (default 10ms)
879 
880  enum crofconn_flavour_t
881  flavour;
882  enum rofl::csocket::socket_type_t
883  socket_type;
885  socket_params;
886  int newsd;
887  std::deque<enum crofconn_event_t>
888  events;
889  enum crofconn_state_t
890  state;
891  std::map<crofconn_timer_t, ctimerid>
892  timer_ids; // timer-ids obtained from ciosrv
893 
894  std::vector<crofqueue>
895  rxqueues; // queues for receiving messages from crofsock instance => // QUEUE_MAX txqueues
896 
897  std::vector<unsigned int>
898  rxweights; // relative scheduling weights for txqueues
899 
900  rofl::crofqueue dlqueue; // delay queue, used for storing asynchronous messages during connection setup
901 
902  static const int DEFAULT_HELLO_TIMEOUT = 5;
903  static const int DEFAULT_ECHO_TIMEOUT = 60;
904  static const int DEFAULT_ECHO_INTERVAL = 60;
905 
906 public:
907 
908  unsigned int hello_timeout;
909  unsigned int echo_timeout;
910  unsigned int echo_interval;
911 
912 };
913 
914 }; /* namespace rofl */
915 
916 #endif /* CROFCHAN_H_ */
Definition: cauxid.h:30
Definition: cofmsg_meter_stats.h:146
cauxid const & get_aux_id() const
Return auxialiary_id.
Definition: crofconn.h:334
Definition: cparams.h:20
Definition: cofmsg_flow_stats.h:164
Definition: cofmsg_port_stats.h:156
Definition: cofhelloelemversionbitmap.h:22
A socket capable of talking OpenFlow via TCP and vice versa.
Definition: crofsock.h:111
bool is_established() const
Returns whether this connection is established.
Definition: crofconn.h:285
void notify(const cevent &event)
Sends a notification to this ciosrv instance.
Definition: ciosrv.h:529
unsigned int send_message(rofl::openflow::cofmsg *msg)
Send OFP message via socket.
Definition: crofconn.h:348
void close()
Instruct crofsock instance to close connection to peer.
Definition: crofconn.cc:159
rofl::openflow::cofhello_elem_versionbitmap & get_versionbitmap()
Returns a reference to the versionbitmap announced by this entity.
Definition: crofconn.h:306
Definition: cofmsg_table_features_stats.h:22
Definition: cofmsg_table_features_stats.h:161
Definition: cofmsg_queue_stats.h:144
Definition: crofconn.h:31
A single OpenFlow control connection.
Definition: crofconn.h:145
Definition: cofmsg_group_stats.h:152
uint8_t get_version() const
Returns the negotiated OFP version (or OFP_UNKNOWN)
Definition: crofconn.h:320
Definition: cofmsg_port_desc_stats.h:123
void connect(const cauxid &aux_id, enum rofl::csocket::socket_type_t socket_type, const cparams &socket_params)
Instruct crofsock instance to connect to peer using specified parameters.
Definition: crofconn.cc:136
Definition: crofconn.h:28
Environment expected by a rofl::crofconn instance.
Definition: crofconn.h:40
Single event used internally by class crofl::cioloop.
Definition: cevent.h:20
Definition: cthread.h:31
bool is_actively_established() const
Returns true when this connection has been actively established.
Definition: crofconn.h:292
Definition: crofqueue.h:20
Base class for IO services.
Definition: ciosrv.h:491
Definition: logging.h:76
uint64_t get_dpid() const
Returns data path id assigned to this connection.
Definition: crofconn.h:327
Definition: cofmsg_group_desc_stats.h:123
crofconn(crofconn_env *env, const rofl::openflow::cofhello_elem_versionbitmap &versionbitmap)
Definition: crofconn.cc:14
bool is_congested() const
Returns true, when the underlying TCP connection is congested.
Definition: crofconn.h:299
Definition: cofmsg_table_stats.h:132
rofl::openflow::cofhello_elem_versionbitmap & get_versionbitmap_peer()
Returns a reference to the versionbitmap seen from the peer.
Definition: crofconn.h:313
Definition: cofmsg_meter_config_stats.h:147
Environment expected by a rofl::crofsock instance.
Definition: crofsock.h:76
Definition: crofconn.h:29
void reconnect(bool reset_backoff_timer=false)
Instruct crofsock instance to reconnect to previously connected peer.
Definition: crofconn.cc:127
Definition: crofconn.h:30
Definition: croflexception.h:27
Definition: cofmsg.h:62