Revised OpenFlow Library  v0.6.0dev
 All Classes Files Functions Variables Friends Groups Pages
crofsock.h
1 /*
2  * crofendpnt.h
3  *
4  * Created on: 31.12.2013
5  * Author: andreas
6  */
7 
8 #ifndef CROFENDPNT_H_
9 #define CROFENDPNT_H_
10 
11 #include <inttypes.h>
12 #include <stdio.h>
13 #include <strings.h>
14 #include <map>
15 #include <set>
16 #include <deque>
17 #include <bitset>
18 #include <algorithm>
19 
20 #include "rofl/common/ciosrv.h"
21 #include "rofl/common/cmemory.h"
22 #include "rofl/common/csocket.h"
23 #include "rofl/common/logging.h"
24 #include "rofl/common/crofqueue.h"
25 #include "rofl/common/thread_helper.h"
26 #include "rofl/common/croflexception.h"
27 
28 #include "rofl/common/openflow/messages/cofmsg.h"
29 #include "rofl/common/openflow/messages/cofmsg_hello.h"
30 #include "rofl/common/openflow/messages/cofmsg_echo.h"
31 #include "rofl/common/openflow/messages/cofmsg_error.h"
32 #include "rofl/common/openflow/messages/cofmsg_features.h"
33 #include "rofl/common/openflow/messages/cofmsg_config.h"
34 #include "rofl/common/openflow/messages/cofmsg_packet_out.h"
35 #include "rofl/common/openflow/messages/cofmsg_packet_in.h"
36 #include "rofl/common/openflow/messages/cofmsg_flow_mod.h"
37 #include "rofl/common/openflow/messages/cofmsg_flow_removed.h"
38 #include "rofl/common/openflow/messages/cofmsg_group_mod.h"
39 #include "rofl/common/openflow/messages/cofmsg_table_mod.h"
40 #include "rofl/common/openflow/messages/cofmsg_port_mod.h"
41 #include "rofl/common/openflow/messages/cofmsg_port_status.h"
42 #include "rofl/common/openflow/messages/cofmsg_stats.h"
43 #include "rofl/common/openflow/messages/cofmsg_desc_stats.h"
44 #include "rofl/common/openflow/messages/cofmsg_flow_stats.h"
45 #include "rofl/common/openflow/messages/cofmsg_aggr_stats.h"
46 #include "rofl/common/openflow/messages/cofmsg_table_stats.h"
47 #include "rofl/common/openflow/messages/cofmsg_port_stats.h"
48 #include "rofl/common/openflow/messages/cofmsg_queue_stats.h"
49 #include "rofl/common/openflow/messages/cofmsg_group_stats.h"
50 #include "rofl/common/openflow/messages/cofmsg_group_desc_stats.h"
51 #include "rofl/common/openflow/messages/cofmsg_group_features_stats.h"
52 #include "rofl/common/openflow/messages/cofmsg_port_desc_stats.h"
53 #include "rofl/common/openflow/messages/cofmsg_experimenter_stats.h"
54 #include "rofl/common/openflow/messages/cofmsg_barrier.h"
55 #include "rofl/common/openflow/messages/cofmsg_queue_get_config.h"
56 #include "rofl/common/openflow/messages/cofmsg_role.h"
57 #include "rofl/common/openflow/messages/cofmsg_experimenter.h"
58 #include "rofl/common/openflow/messages/cofmsg_experimenter_stats.h"
59 #include "rofl/common/openflow/messages/cofmsg_async_config.h"
60 #include "rofl/common/openflow/messages/cofmsg_table_features_stats.h"
61 #include "rofl/common/openflow/messages/cofmsg_meter_mod.h"
62 #include "rofl/common/openflow/messages/cofmsg_meter_stats.h"
63 #include "rofl/common/openflow/messages/cofmsg_meter_config_stats.h"
64 #include "rofl/common/openflow/messages/cofmsg_meter_features_stats.h"
65 
66 
67 namespace rofl {
68 
69 class crofsock; // forward declaration
70 
76 class crofsock_env {
77 public:
78  virtual ~crofsock_env() {};
79 
80 protected:
81 
82  friend class crofsock;
83 
84  virtual void
85  handle_connect_refused(crofsock& endpnt) = 0;
86 
87  virtual void
88  handle_connect_failed(crofsock& endpnt) = 0;
89 
90  virtual void
91  handle_connected(crofsock& endpnt) = 0;
92 
93  virtual void
94  handle_closed(crofsock& endpnt) = 0;
95 
96  virtual void
97  handle_write(crofsock& endpnt) = 0;
98 
99  virtual void
100  recv_message(crofsock& endpnt, rofl::openflow::cofmsg *msg) = 0;
101 };
102 
103 class eRofSockBase : public RoflException {};
104 class eRofSockTxAgain : public eRofSockBase {};
106 
111 class crofsock :
112  public ciosrv,
113  public csocket_env
114 {
115  enum outqueue_type_t {
116  QUEUE_OAM = 0, // Echo.request/Echo.reply
117  QUEUE_MGMT = 1, // all remaining packets, except ...
118  QUEUE_FLOW = 2, // Flow-Mod/Flow-Removed
119  QUEUE_PKT = 3, // Packet-In/Packet-Out
120  QUEUE_MAX, // do not use
121  };
122 
123  enum crofsock_event_t {
124  EVENT_NONE = 0,
125  EVENT_CONNECT = 1,
126  EVENT_CONNECT_FAILED = 2,
127  EVENT_CONNECT_REFUSED = 3,
128  EVENT_CONNECTED = 4,
129  EVENT_ACCEPT = 5,
130  EVENT_ACCEPT_REFUSED = 6,
131  EVENT_ACCEPTED = 7,
132  EVENT_PEER_DISCONNECTED = 8,
133  EVENT_LOCAL_DISCONNECT = 9,
134  EVENT_CONGESTION_SOLVED = 10,
135  };
136 
137  enum crofsock_flag_t {
138  FLAGS_CONGESTED = 1,
139  };
140 
141  enum crofsock_state_t {
142  STATE_INIT = 0,
143  STATE_CLOSED = 1,
144  STATE_CONNECTING = 2,
145  STATE_CONNECTED = 3,
146  };
147 
148 public:
149 
153  crofsock(
154  crofsock_env *env);
155 
159  virtual
160  ~crofsock();
161 
162 public:
163 
167  void
168  accept(
169  enum rofl::csocket::socket_type_t socket_type,
170  const cparams& socket_params,
171  int sd) {
172  RwLock rwlock(rofsock_lock, RwLock::RWLOCK_WRITE);
173  this->socket_type = socket_type;
174  this->socket_params = socket_params;
175  this->sd = sd;
176  run_engine(EVENT_ACCEPT);
177  };
178 
182  void
183  connect(
184  enum rofl::csocket::socket_type_t socket_type,
185  const cparams& socket_params) {
186  RwLock rwlock(rofsock_lock, RwLock::RWLOCK_WRITE);
187  this->socket_type = socket_type;
188  this->socket_params = socket_params;
189  run_engine(EVENT_CONNECT);
190  };
191 
195  void
196  reconnect() {
197  RwLock rwlock(rofsock_lock, RwLock::RWLOCK_WRITE);
198  run_engine(EVENT_CONNECT);
199  };
200 
204  void
205  close() {
206  RwLock rwlock(rofsock_lock, RwLock::RWLOCK_WRITE);
207  run_engine(EVENT_LOCAL_DISCONNECT);
208  };
209 
213  csocket const&
214  get_socket() const
215  { return *socket; /* FIXME */ };
216 
220  unsigned int
221  send_message(
223 
227  bool
228  is_established() const
229  { return socket->is_established(); };
230 
231 private:
232 
233 
237  crofsock(
238  const crofsock& endpnt) :
239  env(NULL),
240  socket(NULL),
241  state(STATE_INIT),
242  fragment(NULL),
243  msg_bytes_read(0),
244  max_pkts_rcvd_per_round(DEFAULT_MAX_PKTS_RVCD_PER_ROUND),
245  socket_type(rofl::csocket::SOCKET_TYPE_UNKNOWN),
246  sd(-1)
247  {};
248 
252  crofsock&
253  operator= (
254  const crofsock& endpnt)
255  { return *this; };
256 
257 private:
258 
262  virtual void
263  handle_event(
264  cevent const &ev);
265 
266 private:
267 
271  virtual void
272  handle_listen(
273  csocket& socket,
274  int newsd) {
275  // this should never happen, as passively opened sockets are handled outside of crofsock
276  };
277 
281  virtual void
282  handle_accept_refused(
283  csocket& socket) {
284  run_engine(EVENT_ACCEPT_REFUSED);
285  };
286 
290  virtual void
291  handle_accepted(
292  csocket& socket) {
293  run_engine(EVENT_ACCEPTED);
294  };
295 
299  virtual void
300  handle_connect_refused(
301  csocket& socket) {
302  run_engine(EVENT_CONNECT_REFUSED);
303  };
304 
308  virtual void
309  handle_connect_failed(
310  csocket& socket) {
311  run_engine(EVENT_CONNECT_FAILED);
312  };
313 
317  virtual void
318  handle_connected(
319  csocket& socket) {
320  run_engine(EVENT_CONNECTED);
321  };
322 
326  virtual void
327  handle_write(
328  csocket& socket) {
329  run_engine(EVENT_CONGESTION_SOLVED);
330  };
331 
335  virtual void
336  handle_closed(
337  csocket& socket) {
338  run_engine(EVENT_PEER_DISCONNECTED);
339  };
340 
344  virtual void
345  handle_read(
346  csocket& socket);
347 
348 private:
349 
353  void
354  run_engine(crofsock_event_t event = EVENT_NONE) {
355  if (EVENT_NONE != event) {
356  events.push_back(event);
357  }
358 
359  while (not events.empty()) {
360  enum crofsock_event_t event = events.front();
361  events.pop_front();
362 
363  switch (event) {
364  case EVENT_CONNECT: event_connect(); break;
365  case EVENT_CONNECT_FAILED: event_connect_failed(); break;
366  case EVENT_CONNECT_REFUSED: event_connect_refused(); break;
367  case EVENT_CONNECTED: event_connected(); break;
368  case EVENT_ACCEPT: event_accept(); break;
369  case EVENT_ACCEPT_REFUSED: event_accept_refused(); break;
370  case EVENT_ACCEPTED: event_accepted(); break;
371  case EVENT_PEER_DISCONNECTED: event_peer_disconnected(); return;
372  case EVENT_LOCAL_DISCONNECT: event_local_disconnect(); return;
373  case EVENT_CONGESTION_SOLVED: event_congestion_solved(); break;
374 
375  default: {
376  rofl::logging::error << "[rofl-common][crofsock] unknown event seen, internal error" << std::endl << *this;
377  };
378  }
379  }
380  }
381 
385  void
386  event_connect() {
387  switch (state) {
388  case STATE_INIT:
389  case STATE_CLOSED: {
390  rofl::logging::debug2 << "[rofl-common][crofsock] EVENT-CONNECT => entering state -connecting-" << std::endl;
391  state = STATE_CONNECTING;
392  if (socket)
393  delete socket;
396  (socket = csocket::csocket_factory(socket_type, this))->connect(socket_params);
397  } break;
398  case STATE_CONNECTING: {
399  // do nothing, we are already connecting ...
400  } break;
401  case STATE_CONNECTED: {
402  run_engine(EVENT_LOCAL_DISCONNECT);
403  run_engine(EVENT_CONNECT);
404  } break;
405  default: {
406 
407  };
408  };
409  };
410 
414  void
415  event_connect_failed() {
416  rofl::logging::debug2 << "[rofl-common][crofsock] EVENT-CONNECT-FAILED => entering state -closed-" << std::endl;
417  state = STATE_CLOSED;
418  if (env) env->handle_connect_failed(*this);
419  };
420 
424  void
425  event_connect_refused() {
426  rofl::logging::debug2 << "[rofl-common][crofsock] EVENT-CONNECT-REFUSED => entering state -closed-" << std::endl;
427  state = STATE_CLOSED;
428  if (env) env->handle_connect_refused(*this);
429  };
430 
434  void
435  event_connected() {
436  rofl::logging::debug2 << "[rofl-common][crofsock] EVENT-CONNECTED => entering state -connected-" << std::endl;
437  state = STATE_CONNECTED;
438  if (env) env->handle_connected(*this);
439  };
440 
444  void
445  event_accept() {
446  switch (state) {
447  case STATE_INIT:
448  case STATE_CLOSED: {
449  rofl::logging::debug2 << "[rofl-common][crofsock] EVENT-ACCEPT => entering state -connected-" << std::endl;
450  state = STATE_CONNECTED;
451  if (socket)
452  delete socket;
453 
454  (socket = csocket::csocket_factory(socket_type, this))->accept(socket_params, sd);
455  } break;
456  default: {
457 
458  };
459  }
460  }
461 
465  void
466  event_accept_refused() {
467  rofl::logging::debug2 << "[rofl-common][crofsock] EVENT-ACCEPT-REFUSED => entering state -closed-" << std::endl;
468  state = STATE_CLOSED;
469  };
470 
474  void
475  event_accepted() {
476  rofl::logging::debug2 << "[rofl-common][crofsock] EVENT-ACCEPTED => entering state -connected-" << std::endl;
477  state = STATE_CONNECTED;
478  // do not call handle_connected() here
479  };
480 
484  void
485  event_peer_disconnected() {
486  rofl::logging::debug2 << "[rofl-common][crofsock] EVENT-PEER-DISCONNECTED => entering state -closed-" << std::endl;
487  __close();
488  if (env) env->handle_closed(*this);
489  };
490 
494  void
495  event_local_disconnect() {
496  rofl::logging::debug2 << "[rofl-common][crofsock] EVENT-LOCAL-DISCONNECT => entering state -closed-" << std::endl;
497  __close();
498  if (socket) socket->close();
499  };
500 
504  void
505  event_congestion_solved() {
506  flags.reset(FLAGS_CONGESTED);
507  rofl::ciosrv::notify(rofl::cevent(EVENT_CONGESTION_SOLVED));
508  };
509 
510 private:
511 
515  void
516  __close() {
517  state = STATE_CLOSED;
518  if (fragment) {
519  delete fragment; fragment = NULL;
520  }
521  for (std::vector<crofqueue>::iterator
522  it = txqueues.begin(); it != txqueues.end(); ++it) {
523  (*it).clear();
524  }
527  };
528 
532  void
533  parse_message(
534  cmemory *mem);
535 
539  void
540  parse_of10_message(
541  cmemory *mem, rofl::openflow::cofmsg **pmsg);
542 
546  void
547  parse_of12_message(
548  cmemory *mem, rofl::openflow::cofmsg **pmsg);
549 
553  void
554  parse_of13_message(
555  cmemory *mem, rofl::openflow::cofmsg **pmsg);
556 
560  void
561  send_from_queue();
562 
566  void
567  log_message(
568  std::string const& text, rofl::openflow::cofmsg const& pmsg);
569 
573  void
574  log_of10_message(
575  rofl::openflow::cofmsg const& pmsg);
576 
580  void
581  log_of12_message(
582  rofl::openflow::cofmsg const& pmsg);
583 
587  void
588  log_of13_message(
589  rofl::openflow::cofmsg const& pmsg);
590 
591 
592 public:
593 
594  friend std::ostream&
595  operator<< (std::ostream& os, crofsock const& rofsock) {
596  os << indent(0) << "<crofsock: transport-connection-established: " << rofsock.get_socket().is_established() << ">" << std::endl;
597  return os;
598  };
599 
600  std::string
601  str() const {
602  std::stringstream ss;
603  if (STATE_INIT == state) {
604  ss << "state: -INIT- ";
605  } else
606  if (STATE_CLOSED == state) {
607  ss << "state: -CLOSED- ";
608  } else
609  if (STATE_CONNECTING == state) {
610  ss << "state: -CONNECTING- ";
611  } else
612  if (STATE_CONNECTED == state) {
613  ss << "state: -CONNECTED- ";
614  }
615  return ss.str();
616  };
617 
618 private:
619 
620  // environment for this crofsock instance
621  crofsock_env* env;
622  // socket abstraction towards peer
623  csocket* socket;
624  // various flags for this crofsock instance
625  std::bitset<32> flags;
626  // connection state
627  enum crofsock_state_t state;
628 
629  /*
630  * receiving messages
631  */
632 
633  // incomplete fragment message fragment received in last round
634  cmemory* fragment;
635  // number of bytes already received for current message fragment
636  unsigned int msg_bytes_read;
637  // read not more than this number of packets per round before rescheduling
638  unsigned int max_pkts_rcvd_per_round;
639  // default value for max_pkts_rcvd_per_round
640  static unsigned int const DEFAULT_MAX_PKTS_RVCD_PER_ROUND = 16;
641 
642  /*
643  * scheduler and txqueues
644  */
645 
646  // QUEUE_MAX txqueues
647  std::vector<crofqueue> txqueues;
648  // relative scheduling weights for txqueues
649  std::vector<unsigned int> txweights;
650 
651  enum rofl::csocket::socket_type_t
652  socket_type;
653 
654  rofl::cparams socket_params;
655 
656  int sd;
657 
658  std::deque<enum crofsock_event_t>
659  events;
660 
661  PthreadRwLock rofsock_lock;
662 };
663 
664 } /* namespace rofl */
665 
666 #endif /* CROFENDPNT_H_ */
Definition: crofsock.h:105
Definition: cparams.h:20
A single socket.
Definition: csocket.h:182
A socket capable of talking OpenFlow via TCP and vice versa.
Definition: crofsock.h:111
void notify(const cevent &event)
Sends a notification to this ciosrv instance.
Definition: ciosrv.h:529
void cancel_all_events()
Cancels all pending events of this instance.
Definition: ciosrv.h:780
void cancel_all_timers()
Cancels all pending timers of this instance.
Definition: ciosrv.h:770
virtual void close()=0
Closes this socket.
Definition: thread_helper.h:25
Definition: crofsock.h:103
Definition: thread_helper.h:88
C++ abstraction for malloc'ed memory areas.
Definition: cmemory.h:44
Single event used internally by class crofl::cioloop.
Definition: cevent.h:20
Definition: crofsock.h:104
An abstract interface defining the consumer side of a csocket.
Definition: csocket.h:58
Base class for IO services.
Definition: ciosrv.h:491
Definition: logging.h:76
Environment expected by a rofl::crofsock instance.
Definition: crofsock.h:76
Definition: croflexception.h:27
void clear()
Clears the allocated memory area by setting all bytes to 0.
Definition: cmemory.cc:281
Definition: cofmsg.h:62