trema 0.2.2.1 → 0.2.3

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (250) hide show
  1. data/.gitmodules +3 -0
  2. data/.travis.yml +13 -0
  3. data/.yardopts +4 -0
  4. data/Gemfile +2 -3
  5. data/README.md +43 -97
  6. data/Rakefile +60 -4
  7. data/Rantfile +11 -10
  8. data/cruise.rb +4 -6
  9. data/features/example.packetin_filter_config.feature +10 -10
  10. data/features/example.switch_monitor.feature +14 -2
  11. data/features/step_definitions/kill_steps.rb +2 -2
  12. data/features/step_definitions/{off_steps.rb → killall_steps.rb} +2 -2
  13. data/features/step_definitions/misc_steps.rb +1 -1
  14. data/features/step_definitions/up_steps.rb +30 -0
  15. data/features/trema.feature +1 -0
  16. data/features/trema.run.feature +1 -0
  17. data/locale/README.ja.md +19 -0
  18. data/locale/ja/yard.po +3762 -0
  19. data/locale/yard.pot +3740 -0
  20. data/ruby/extconf.rb +4 -1
  21. data/ruby/trema/action-common.c +3 -17
  22. data/ruby/trema/action-common.h +3 -7
  23. data/ruby/trema/action.rb +33 -0
  24. data/ruby/trema/app.rb +1 -1
  25. data/ruby/trema/barrier-request.c +1 -0
  26. data/ruby/trema/command/run.rb +13 -9
  27. data/ruby/trema/command/usage.rb +1 -0
  28. data/ruby/trema/command/version.rb +1 -1
  29. data/ruby/trema/controller.c +133 -50
  30. data/ruby/trema/controller.rb +2 -2
  31. data/ruby/trema/desc-stats-reply.rb +77 -0
  32. data/ruby/trema/dsl/configuration.rb +3 -14
  33. data/ruby/trema/dsl/rswitch.rb +47 -0
  34. data/ruby/trema/dsl/runner.rb +4 -1
  35. data/ruby/trema/dsl/syntax.rb +11 -8
  36. data/ruby/trema/echo-reply.c +59 -45
  37. data/ruby/trema/echo-reply.h +1 -3
  38. data/ruby/trema/echo-request.c +49 -71
  39. data/ruby/trema/echo-request.h +0 -2
  40. data/ruby/trema/echo.c +99 -0
  41. data/ruby/trema/{action-enqueue.h → echo.h} +6 -7
  42. data/ruby/trema/enqueue.rb +87 -0
  43. data/ruby/trema/error.c +109 -104
  44. data/ruby/trema/error.h +0 -2
  45. data/ruby/trema/features-reply.c +89 -35
  46. data/ruby/trema/features-reply.h +0 -6
  47. data/ruby/trema/features-request.c +63 -37
  48. data/ruby/trema/features-request.h +0 -2
  49. data/ruby/trema/flow-mod.c +149 -0
  50. data/ruby/trema/{action-output.h → flow-mod.h} +6 -6
  51. data/ruby/trema/get-config-request.c +1 -0
  52. data/ruby/trema/hardware-switch.rb +88 -0
  53. data/ruby/trema/hello.c +55 -31
  54. data/ruby/trema/hello.h +0 -2
  55. data/ruby/trema/ip.rb +12 -2
  56. data/ruby/trema/logger.rb +29 -0
  57. data/ruby/trema/mac.rb +57 -36
  58. data/ruby/trema/match.c +7 -9
  59. data/ruby/trema/monkey-patch/integer/ranges.rb +0 -2
  60. data/ruby/trema/network-component.rb +1 -1
  61. data/ruby/trema/open-vswitch.rb +2 -2
  62. data/ruby/trema/openflow-switch.rb +3 -54
  63. data/ruby/trema/{packet_in.c → packet-in.c} +262 -175
  64. data/ruby/trema/{packet_in.h → packet-in.h} +0 -2
  65. data/ruby/trema/packet-queue.rb +4 -3
  66. data/ruby/trema/port-mod.c +8 -9
  67. data/ruby/trema/port-status-add.rb +60 -0
  68. data/ruby/trema/port-status-delete.rb +60 -0
  69. data/ruby/trema/port-status-modify.rb +60 -0
  70. data/ruby/trema/port-status.c +48 -15
  71. data/ruby/trema/port-status.h +6 -8
  72. data/ruby/trema/port.c +63 -8
  73. data/ruby/trema/queue-get-config-request.c +1 -0
  74. data/ruby/trema/ruby-switch.rb +62 -0
  75. data/ruby/trema/send-out-port.rb +97 -0
  76. data/ruby/trema/set-config.c +1 -0
  77. data/ruby/trema/set-eth-addr.rb +45 -0
  78. data/ruby/trema/set-eth-dst-addr.rb +54 -0
  79. data/ruby/trema/set-eth-src-addr.rb +54 -0
  80. data/ruby/trema/set-ip-addr.rb +47 -0
  81. data/ruby/trema/set-ip-dst-addr.rb +53 -0
  82. data/ruby/trema/set-ip-src-addr.rb +52 -0
  83. data/ruby/trema/set-ip-tos.rb +63 -0
  84. data/ruby/trema/set-transport-dst-port.rb +53 -0
  85. data/ruby/trema/set-transport-port.rb +52 -0
  86. data/ruby/trema/set-transport-src-port.rb +54 -0
  87. data/ruby/trema/set-vlan-priority.rb +65 -0
  88. data/ruby/trema/set-vlan-vid.rb +64 -0
  89. data/ruby/trema/shell/down.rb +1 -1
  90. data/ruby/trema/shell/link.rb +4 -4
  91. data/ruby/trema/shell/run.rb +8 -6
  92. data/ruby/trema/shell/up.rb +3 -3
  93. data/ruby/trema/stats-reply.c +27 -2
  94. data/ruby/trema/stats-request.c +64 -23
  95. data/ruby/trema/strip-vlan-header.rb +41 -0
  96. data/ruby/trema/switch.c +196 -0
  97. data/ruby/trema/{action-vendor.h → switch.h} +5 -7
  98. data/ruby/trema/switch.rb +28 -9
  99. data/ruby/trema/trema-ruby-utils.c +66 -0
  100. data/ruby/trema/{action-set-dl-src.h → trema-ruby-utils.h} +9 -11
  101. data/ruby/trema/trema.c +61 -61
  102. data/ruby/trema/vendor-action.rb +73 -0
  103. data/ruby/trema/vendor.c +121 -52
  104. data/ruby/trema/vendor.h +6 -10
  105. data/ruby/trema/version.rb +1 -1
  106. data/spec/spec_helper.rb +1 -1
  107. data/spec/support/action.rb +52 -0
  108. data/spec/support/mandatory-option.rb +56 -0
  109. data/spec/support/openflow-message.rb +91 -7
  110. data/spec/support/port-status.rb +38 -0
  111. data/spec/trema/controller_spec.rb +0 -26
  112. data/spec/trema/dsl/configuration_spec.rb +3 -3
  113. data/spec/trema/dsl/runner_spec.rb +12 -32
  114. data/spec/trema/dsl/syntax_spec.rb +2 -11
  115. data/spec/trema/echo-reply_spec.rb +49 -14
  116. data/spec/trema/echo-request_spec.rb +86 -34
  117. data/spec/trema/enqueue_spec.rb +76 -0
  118. data/spec/trema/error_spec.rb +43 -58
  119. data/spec/trema/features-reply_spec.rb +58 -24
  120. data/spec/trema/features-request_spec.rb +54 -28
  121. data/spec/trema/flow-mod_spec.rb +99 -0
  122. data/spec/trema/{openflow-switch_spec.rb → hardware-switch_spec.rb} +3 -3
  123. data/spec/trema/hello_spec.rb +28 -14
  124. data/spec/trema/ip_spec.rb +54 -0
  125. data/spec/trema/mac_spec.rb +49 -64
  126. data/spec/trema/match_spec.rb +1 -1
  127. data/spec/trema/open-vswitch_spec.rb +7 -7
  128. data/spec/trema/packet-in_spec.rb +73 -16
  129. data/spec/trema/port-status-add_spec.rb +32 -0
  130. data/spec/trema/port-status-delete_spec.rb +32 -0
  131. data/spec/trema/port-status-modify_spec.rb +71 -0
  132. data/spec/trema/port-status_spec.rb +5 -76
  133. data/spec/trema/{action-output_spec.rb → send-out-port_spec.rb} +20 -47
  134. data/spec/trema/set-eth-dst-addr_spec.rb +75 -0
  135. data/spec/trema/set-eth-src-addr_spec.rb +72 -0
  136. data/spec/trema/set-ip-dst-addr_spec.rb +58 -0
  137. data/spec/trema/set-ip-src-addr_spec.rb +58 -0
  138. data/spec/trema/set-ip-tos_spec.rb +65 -0
  139. data/spec/trema/set-transport-dst-port_spec.rb +65 -0
  140. data/spec/trema/set-transport-src-port_spec.rb +65 -0
  141. data/spec/trema/set-vlan-priority_spec.rb +65 -0
  142. data/spec/trema/set-vlan-vid_spec.rb +65 -0
  143. data/spec/trema/shell/vhost_spec.rb +4 -1
  144. data/spec/trema/shell/vswitch_spec.rb +11 -11
  145. data/spec/trema/stats-reply_spec.rb +59 -13
  146. data/spec/trema/stats-request_spec.rb +6 -0
  147. data/spec/trema/{action-strip-vlan_spec.rb → strip-vlan-header_spec.rb} +3 -17
  148. data/spec/trema/switch-daemon_spec.rb +39 -0
  149. data/spec/trema/vendor-action_spec.rb +81 -0
  150. data/spec/trema/vendor_spec.rb +76 -0
  151. data/spec/trema_spec.rb +56 -0
  152. data/src/examples/dumper/dumper.c +0 -8
  153. data/src/examples/dumper/dumper.rb +52 -52
  154. data/src/examples/hello_trema/hello_trema.c +0 -2
  155. data/src/examples/learning_switch/learning-switch.rb +3 -3
  156. data/src/examples/multi_learning_switch/multi-learning-switch.rb +3 -3
  157. data/src/examples/openflow_message/features-request.rb +3 -3
  158. data/src/examples/packetin_filter_config/utils.c +4 -4
  159. data/src/examples/repeater_hub/repeater-hub.rb +3 -3
  160. data/src/examples/switch_info/switch_info.rb +2 -2
  161. data/src/examples/switch_monitor/switch_monitor.c +1 -1
  162. data/src/examples/traffic_monitor/traffic-monitor.rb +3 -3
  163. data/src/lib/arp.h +4 -1
  164. data/src/lib/chibach.c +391 -0
  165. data/src/lib/chibach.h +71 -0
  166. data/src/lib/chibach_private.c +170 -0
  167. data/src/lib/chibach_private.h +52 -0
  168. data/src/lib/ether.c +2 -1
  169. data/src/lib/ether.h +0 -1
  170. data/src/lib/ipv4.h +13 -14
  171. data/{ruby/trema/action-set-nw-src.h → src/lib/ipv6.h} +13 -9
  172. data/src/lib/log.c +161 -58
  173. data/src/lib/log.h +11 -16
  174. data/src/lib/messenger.c +36 -1
  175. data/src/lib/messenger.h +1 -0
  176. data/src/lib/openflow_application_interface.c +128 -28
  177. data/src/lib/openflow_application_interface.h +31 -6
  178. data/src/lib/openflow_message.c +2 -1
  179. data/src/lib/openflow_service_interface.h +1 -0
  180. data/src/lib/openflow_switch_interface.c +1380 -0
  181. data/src/lib/openflow_switch_interface.h +264 -0
  182. data/src/lib/packet_info.c +94 -11
  183. data/src/lib/packet_info.h +22 -3
  184. data/src/lib/packet_parser.c +38 -2
  185. data/src/lib/secure_channel.c +498 -0
  186. data/{ruby/trema/vendor-request.h → src/lib/secure_channel.h} +11 -10
  187. data/src/lib/tcp.h +0 -3
  188. data/src/lib/trema.c +38 -5
  189. data/{ruby/trema/action-set-nw-dst.h → src/lib/trema.hpp} +17 -8
  190. data/src/lib/trema_wrapper.c +5 -0
  191. data/src/lib/trema_wrapper.h +4 -0
  192. data/src/lib/utility.c +93 -4
  193. data/src/lib/utility.h +1 -0
  194. data/src/lib/wrapper.c +30 -7
  195. data/src/lib/wrapper.h +2 -0
  196. data/src/switch_manager/ofpmsg_recv.c +44 -30
  197. data/src/switch_manager/ofpmsg_send.c +40 -1
  198. data/src/switch_manager/ofpmsg_send.h +2 -0
  199. data/src/switch_manager/switch.c +153 -8
  200. data/src/switch_manager/switch.h +1 -0
  201. data/src/switch_manager/switchinfo.h +5 -0
  202. data/src/tremashark/README +2 -2
  203. data/src/tremashark/plugin/packet-trema/packet-trema.c +1 -0
  204. data/trema +1 -1
  205. data/unittests/lib/log_test.c +158 -34
  206. data/unittests/lib/openflow_application_interface_test.c +252 -69
  207. data/unittests/lib/openflow_message_test.c +3 -1
  208. data/unittests/lib/packet_parser_test.c +60 -15
  209. data/unittests/lib/test_packets/icmp6_echo_rep.cap +0 -0
  210. data/unittests/lib/test_packets/icmp6_echo_req.cap +0 -0
  211. data/unittests/lib/trema_test.c +2 -0
  212. data/unittests/lib/utility_test.c +65 -2
  213. data/unittests/lib/wrapper_test.c +29 -0
  214. data/vendor/{README → README.md} +2 -12
  215. data/vendor/packet-openflow.diff +13 -0
  216. metadata +86 -53
  217. data/GPL2 +0 -339
  218. data/ruby/trema/action-enqueue.c +0 -161
  219. data/ruby/trema/action-output.c +0 -169
  220. data/ruby/trema/action-set-dl-dst.c +0 -131
  221. data/ruby/trema/action-set-dl-dst.h +0 -44
  222. data/ruby/trema/action-set-dl-src.c +0 -131
  223. data/ruby/trema/action-set-nw-dst.c +0 -135
  224. data/ruby/trema/action-set-nw-src.c +0 -140
  225. data/ruby/trema/action-set-nw-tos.c +0 -124
  226. data/ruby/trema/action-set-nw-tos.h +0 -42
  227. data/ruby/trema/action-set-tp-dst.c +0 -122
  228. data/ruby/trema/action-set-tp-dst.h +0 -42
  229. data/ruby/trema/action-set-tp-src.c +0 -124
  230. data/ruby/trema/action-set-tp-src.h +0 -42
  231. data/ruby/trema/action-set-vlan-pcp.c +0 -128
  232. data/ruby/trema/action-set-vlan-pcp.h +0 -42
  233. data/ruby/trema/action-set-vlan-vid.c +0 -125
  234. data/ruby/trema/action-set-vlan-vid.h +0 -42
  235. data/ruby/trema/action-strip-vlan.c +0 -81
  236. data/ruby/trema/action-strip-vlan.h +0 -42
  237. data/ruby/trema/action-vendor.c +0 -121
  238. data/ruby/trema/vendor-request.c +0 -193
  239. data/spec/trema/action-enqueue_spec.rb +0 -100
  240. data/spec/trema/action-set-dl-dst_spec.rb +0 -95
  241. data/spec/trema/action-set-dl-src_spec.rb +0 -92
  242. data/spec/trema/action-set-nw-dst_spec.rb +0 -96
  243. data/spec/trema/action-set-nw-src_spec.rb +0 -97
  244. data/spec/trema/action-set-nw-tos_spec.rb +0 -88
  245. data/spec/trema/action-set-tp-dst_spec.rb +0 -88
  246. data/spec/trema/action-set-tp-src_spec.rb +0 -88
  247. data/spec/trema/action-set-vlan-pcp_spec.rb +0 -91
  248. data/spec/trema/action-set-vlan-vid_spec.rb +0 -91
  249. data/spec/trema/action-vendor_spec.rb +0 -90
  250. data/spec/trema/vendor-request_spec.rb +0 -79
@@ -130,36 +130,38 @@ ofpmsg_recv_error( struct switch_info *sw_info, buffer *buf ) {
130
130
  free_buffer( buf );
131
131
  return 0;
132
132
  }
133
- cookie_entry_t *entry = lookup_cookie_entry_by_cookie( &cookie );
134
- if ( entry != NULL ) {
135
- flow_mod->cookie = htonll( entry->application.cookie );
136
- if ( length >= offsetof( struct ofp_flow_mod, actions ) ) {
137
- flow_mod->flags = htons( entry->application.flags );
138
- }
139
- }
140
-
141
- if ( length >= offsetof( struct ofp_flow_mod, idle_timeout ) ) {
142
- uint16_t command = ntohs( flow_mod->command );
143
- switch ( command ) {
144
- case OFPFC_ADD:
145
- {
146
- if ( entry != NULL ) {
147
- delete_cookie_entry( entry );
148
- }
149
- else {
150
- error( "No cookie entry found ( cookie = %#" PRIx64 " ).", cookie );
133
+ if ( sw_info->cookie_translation ) {
134
+ cookie_entry_t *entry = lookup_cookie_entry_by_cookie( &cookie );
135
+ if ( entry != NULL ) {
136
+ flow_mod->cookie = htonll( entry->application.cookie );
137
+ if ( length >= offsetof( struct ofp_flow_mod, actions ) ) {
138
+ flow_mod->flags = htons( entry->application.flags );
151
139
  }
152
140
  }
153
- break;
154
141
 
155
- case OFPFC_MODIFY:
156
- case OFPFC_MODIFY_STRICT:
157
- case OFPFC_DELETE:
158
- case OFPFC_DELETE_STRICT:
142
+ if ( length >= offsetof( struct ofp_flow_mod, idle_timeout ) ) {
143
+ uint16_t command = ntohs( flow_mod->command );
144
+ switch ( command ) {
145
+ case OFPFC_ADD:
146
+ {
147
+ if ( entry != NULL ) {
148
+ delete_cookie_entry( entry );
149
+ }
150
+ else {
151
+ error( "No cookie entry found ( cookie = %#" PRIx64 " ).", cookie );
152
+ }
153
+ }
159
154
  break;
160
155
 
161
- default:
162
- error( "Undefined flow_mod command ( command = %#x ).", command );
156
+ case OFPFC_MODIFY:
157
+ case OFPFC_MODIFY_STRICT:
158
+ case OFPFC_DELETE:
159
+ case OFPFC_DELETE_STRICT:
160
+ break;
161
+
162
+ default:
163
+ error( "Undefined flow_mod command ( command = %#x ).", command );
164
+ }
163
165
  }
164
166
  }
165
167
  }
@@ -190,9 +192,13 @@ int
190
192
  ofpmsg_recv_echoreply( struct switch_info *sw_info, buffer *buf ) {
191
193
  ofpmsg_debug( "Receive 'echo reply' from a switch." );
192
194
 
193
- // TODO: implement keepalive mechanism
195
+ int ret = switch_event_recv_echoreply( sw_info, buf );
196
+ if ( ret < 0 ) {
197
+ free_buffer( buf );
198
+ return ret;
199
+ }
194
200
 
195
- free_buffer( buf );
201
+ send_transaction_reply( sw_info, buf );
196
202
 
197
203
  return 0;
198
204
  }
@@ -274,14 +280,22 @@ ofpmsg_recv_flowremoved( struct switch_info *sw_info, buffer *buf ) {
274
280
  return 0;
275
281
  }
276
282
 
283
+ if ( !sw_info->cookie_translation ) {
284
+ service_send_to_application( sw_info->state_service_name_list, MESSENGER_OPENFLOW_MESSAGE,
285
+ &sw_info->datapath_id, buf );
286
+ free_buffer( buf );
287
+ return 0;
288
+ }
289
+
277
290
  entry = lookup_cookie_entry_by_cookie( &cookie );
278
291
  if ( entry == NULL ) {
279
292
  error( "No cookie entry found ( cookie = %#" PRIx64 " ).", cookie );
280
293
  free_buffer( buf );
281
294
  return 0;
282
295
  }
283
- debug( "Cookie found ( cookie = %#" PRIx64 ", application = [ cookie = %#" PRIx64 ", service name = %s, flags = %#x ], "
284
- "reference_count = %d, expire_at = %u ).",
296
+
297
+ debug( "Cookie found ( cookie = %#" PRIx64 ", application = [ cookie = %#" PRIx64
298
+ ", service name = %s, flags = %#x ], reference_count = %d, expire_at = %u ).",
285
299
  cookie, entry->application.cookie, entry->application.service_name, entry->application.flags,
286
300
  entry->reference_count, entry->expire_at );
287
301
 
@@ -319,7 +333,7 @@ ofpmsg_recv_statsreply( struct switch_info *sw_info, buffer *buf ) {
319
333
 
320
334
  ofpmsg_debug( "Receive 'statistics reply' from a switch." );
321
335
 
322
- if ( type == OFPST_FLOW ) {
336
+ if ( type == OFPST_FLOW && sw_info->cookie_translation ) {
323
337
  size_t body_offset = offsetof( struct ofp_stats_reply, body );
324
338
  int body_length = ntohs( stats_reply->header.length ) - ( int ) body_offset;
325
339
  struct ofp_flow_stats *flow_stats = ( void * ) ( ( char * ) stats_reply + body_offset );
@@ -46,6 +46,23 @@ ofpmsg_send_hello( struct switch_info *sw_info ) {
46
46
  }
47
47
 
48
48
 
49
+ int
50
+ ofpmsg_send_echorequest( struct switch_info *sw_info, uint32_t xid, buffer *body ) {
51
+ int ret;
52
+ buffer *buf;
53
+
54
+ buf = create_echo_request( xid, body );
55
+ free_buffer( body );
56
+
57
+ ret = send_to_secure_channel( sw_info, buf );
58
+ if ( ret == 0 ) {
59
+ debug( "Send 'echo request' to a switch %#" PRIx64 ".", sw_info->datapath_id );
60
+ }
61
+
62
+ return ret;
63
+ }
64
+
65
+
49
66
  int
50
67
  ofpmsg_send_echoreply( struct switch_info *sw_info, uint32_t xid, buffer *body ) {
51
68
  int ret;
@@ -187,7 +204,7 @@ ofpmsg_send( struct switch_info *sw_info, buffer *buf, char *service_name ) {
187
204
  new_xid = insert_xid_entry( ntohl( ofp_header->xid ), service_name );
188
205
  ofp_header->xid = htonl( new_xid );
189
206
 
190
- if ( ofp_header->type == OFPT_FLOW_MOD ) {
207
+ if ( ofp_header->type == OFPT_FLOW_MOD && sw_info->cookie_translation ) {
191
208
  ret = update_flowmod_cookie( buf, service_name );
192
209
  if ( ret < 0 ) {
193
210
  error( "Failed to update cookie value ( ret = %d ).", ret );
@@ -227,6 +244,28 @@ ofpmsg_send_delete_all_flows( struct switch_info *sw_info ) {
227
244
  }
228
245
 
229
246
 
247
+ int
248
+ ofpmsg_send_deny_all( struct switch_info *sw_info ) {
249
+ int ret;
250
+ struct ofp_match match;
251
+ buffer *buf;
252
+
253
+ memset( &match, 0, sizeof( match ) );
254
+ match.wildcards = OFPFW_ALL;
255
+ const uint16_t timeout = 10;
256
+
257
+ buf = create_flow_mod( generate_xid(), match, RESERVED_COOKIE,
258
+ OFPFC_ADD, 0, timeout, UINT16_MAX, UINT32_MAX, OFPP_NONE, 0, NULL );
259
+
260
+ ret = send_to_secure_channel( sw_info, buf );
261
+ if ( ret == 0 ) {
262
+ debug( "Send 'flow mod (deny all)' to a switch %#" PRIx64 ".", sw_info->datapath_id );
263
+ }
264
+
265
+ return ret;
266
+ }
267
+
268
+
230
269
  /*
231
270
  * Local variables:
232
271
  * c-basic-offset: 2
@@ -30,12 +30,14 @@
30
30
 
31
31
 
32
32
  int ofpmsg_send_hello( struct switch_info *sw_info );
33
+ int ofpmsg_send_echorequest( struct switch_info *sw_info, uint32_t xid, buffer *body );
33
34
  int ofpmsg_send_echoreply( struct switch_info *sw_info, uint32_t xid, buffer *body );
34
35
  int ofpmsg_send_featuresrequest( struct switch_info *sw_info );
35
36
  int ofpmsg_send_setconfig( struct switch_info *sw_info );
36
37
  int ofpmsg_send_error_msg( struct switch_info *sw_info, uint16_t type, uint16_t code, buffer *data );
37
38
  int ofpmsg_send( struct switch_info *sw_info, buffer *buf, char *service_name );
38
39
  int ofpmsg_send_delete_all_flows( struct switch_info *sw_info );
40
+ int ofpmsg_send_deny_all( struct switch_info *sw_info );
39
41
 
40
42
 
41
43
  #endif // OFPMSG_SEND_H
@@ -42,13 +42,29 @@
42
42
  #include "xid_table.h"
43
43
 
44
44
 
45
+ #define SUB_TIMESPEC( _a, _b, _return ) \
46
+ do { \
47
+ ( _return )->tv_sec = ( _a )->tv_sec - ( _b )->tv_sec; \
48
+ ( _return )->tv_nsec = ( _a )->tv_nsec - ( _b )->tv_nsec; \
49
+ if ( ( _return )->tv_nsec < 0 ) { \
50
+ ( _return )->tv_sec--; \
51
+ ( _return )->tv_nsec += 1000000000; \
52
+ } \
53
+ } \
54
+ while ( 0 )
55
+
56
+
45
57
  enum long_options_val {
46
58
  NO_FLOW_CLEANUP_LONG_OPTION_VALUE = 1,
59
+ NO_COOKIE_TRANSLATION_LONG_OPTION_VALUE = 2,
60
+ NO_PACKET_IN_LONG_OPTION_VALUE = 3,
47
61
  };
48
62
 
49
63
  static struct option long_options[] = {
50
64
  { "socket", 1, NULL, 's' },
51
65
  { "no-flow-cleanup", 0, NULL, NO_FLOW_CLEANUP_LONG_OPTION_VALUE },
66
+ { "no-cookie-translation", 0, NULL, NO_COOKIE_TRANSLATION_LONG_OPTION_VALUE },
67
+ { "no-packet_in", 0, NULL, NO_PACKET_IN_LONG_OPTION_VALUE },
52
68
  { NULL, 0, NULL, 0 },
53
69
  };
54
70
 
@@ -58,9 +74,16 @@ static char short_options[] = "s:";
58
74
  struct switch_info switch_info;
59
75
 
60
76
  static const time_t COOKIE_TABLE_AGING_INTERVAL = 3600;
77
+ static const time_t ECHO_REQUEST_INTERVAL = 60;
78
+ static const time_t ECHO_REPLY_TIMEOUT = 2;
61
79
 
62
80
  static bool age_cookie_table_enabled = false;
63
81
 
82
+ typedef struct {
83
+ uint64_t datapath_id;
84
+ uint32_t sec;
85
+ uint32_t nsec;
86
+ } echo_body;
64
87
 
65
88
  void
66
89
  usage() {
@@ -71,7 +94,9 @@ usage() {
71
94
  " -s, --socket=fd secure channnel socket\n"
72
95
  " -n, --name=SERVICE_NAME service name\n"
73
96
  " -l, --logging_level=LEVEL set logging level\n"
74
- " --no-flow-cleanup do not cleanup flows on start\n"
97
+ " --no-flow-cleanup do not cleanup flows on startup\n"
98
+ " --no-cookie-translation do not translate cookie values\n"
99
+ " --no-packet_in do not allow packet-ins on startup\n"
75
100
  " -h, --help display this help and exit\n"
76
101
  "\n"
77
102
  "DESTINATION-RULE:\n"
@@ -109,6 +134,8 @@ option_parser( int argc, char *argv[] ) {
109
134
 
110
135
  switch_info.secure_channel_fd = 0; // stdin
111
136
  switch_info.flow_cleanup = true;
137
+ switch_info.cookie_translation = true;
138
+ switch_info.deny_packet_in_on_startup = false;
112
139
  while ( ( c = getopt_long( argc, argv, short_options, long_options, NULL ) ) != -1 ) {
113
140
  switch ( c ) {
114
141
  case 's':
@@ -119,6 +146,14 @@ option_parser( int argc, char *argv[] ) {
119
146
  switch_info.flow_cleanup = false;
120
147
  break;
121
148
 
149
+ case NO_COOKIE_TRANSLATION_LONG_OPTION_VALUE:
150
+ switch_info.cookie_translation = false;
151
+ break;
152
+
153
+ case NO_PACKET_IN_LONG_OPTION_VALUE:
154
+ switch_info.deny_packet_in_on_startup = true;
155
+ break;
156
+
122
157
  default:
123
158
  usage();
124
159
  exit( EXIT_SUCCESS );
@@ -259,6 +294,13 @@ switch_event_recv_hello( struct switch_info *sw_info ) {
259
294
  // cancel to hello_wait-timeout timer
260
295
  switch_unset_timeout( switch_event_timeout_hello, NULL );
261
296
 
297
+ if ( sw_info->deny_packet_in_on_startup ) {
298
+ ret = ofpmsg_send_deny_all( sw_info );
299
+ if ( ret < 0 ) {
300
+ return ret;
301
+ }
302
+ }
303
+
262
304
  ret = ofpmsg_send_featuresrequest( sw_info );
263
305
  if ( ret < 0 ) {
264
306
  return ret;
@@ -273,6 +315,66 @@ switch_event_recv_hello( struct switch_info *sw_info ) {
273
315
  }
274
316
 
275
317
 
318
+ static void
319
+ echo_reply_timeout( void *user_data ) {
320
+ UNUSED( user_data );
321
+
322
+ error( "Echo request timeout ( datapath id %#" PRIx64 ").", switch_info.datapath_id );
323
+ switch_event_disconnected( &switch_info );
324
+ }
325
+
326
+
327
+ int
328
+ switch_event_recv_echoreply( struct switch_info *sw_info, buffer *buf ) {
329
+ if ( buf->length != sizeof( struct ofp_header ) + sizeof( echo_body ) ) {
330
+ return 0;
331
+ }
332
+ struct ofp_header *header = buf->data;
333
+ if ( ntohl( header->xid ) != sw_info->echo_request_xid ) {
334
+ return 0;
335
+ }
336
+
337
+ echo_body *body = ( echo_body * ) ( header + 1 );
338
+ if ( ntohll( body->datapath_id ) != sw_info->datapath_id ) {
339
+ return 0;
340
+ }
341
+ switch_unset_timeout( echo_reply_timeout, NULL );
342
+ struct timespec now, tim;
343
+ clock_gettime( CLOCK_MONOTONIC, &now );
344
+ tim.tv_sec = ( time_t ) ntohl( body->sec );
345
+ tim.tv_nsec = ( long ) ntohl( body->nsec );
346
+
347
+ SUB_TIMESPEC( &now, &tim, &tim );
348
+
349
+ info( "echo round-trip time %u.%09u.", ( uint32_t ) tim.tv_sec, ( uint32_t ) tim.tv_nsec );
350
+
351
+ return 0;
352
+ }
353
+
354
+
355
+ static void
356
+ echo_request_interval( void *user_data ) {
357
+ struct switch_info *sw_info = user_data;
358
+
359
+ buffer *buf = alloc_buffer();
360
+ echo_body *body = append_back_buffer( buf, sizeof( echo_body ) );
361
+ body->datapath_id = htonll( switch_info.datapath_id );
362
+ struct timespec now;
363
+ clock_gettime( CLOCK_MONOTONIC, &now );
364
+ body->sec = htonl( ( uint32_t ) now.tv_sec );
365
+ body->nsec = htonl( ( uint32_t ) now.tv_nsec );
366
+ sw_info->echo_request_xid = generate_xid();
367
+
368
+ int err = ofpmsg_send_echorequest( sw_info, sw_info->echo_request_xid, buf );
369
+ if ( err < 0 ) {
370
+ switch_event_disconnected( &switch_info );
371
+ return;
372
+ }
373
+
374
+ switch_set_timeout( ECHO_REPLY_TIMEOUT, echo_reply_timeout, NULL );
375
+ }
376
+
377
+
276
378
  int
277
379
  switch_event_recv_featuresreply( struct switch_info *sw_info, uint64_t *dpid ) {
278
380
  int ret;
@@ -323,6 +425,7 @@ switch_event_recv_featuresreply( struct switch_info *sw_info, uint64_t *dpid ) {
323
425
  return ret;
324
426
  }
325
427
  }
428
+ add_periodic_event_callback( ECHO_REQUEST_INTERVAL, echo_request_interval, sw_info );
326
429
  break;
327
430
 
328
431
  case SWITCH_STATE_COMPLETED:
@@ -342,8 +445,14 @@ switch_event_recv_featuresreply( struct switch_info *sw_info, uint64_t *dpid ) {
342
445
 
343
446
  int
344
447
  switch_event_disconnected( struct switch_info *sw_info ) {
448
+ int old_state = sw_info->state;
449
+
345
450
  sw_info->state = SWITCH_STATE_DISCONNECTED;
346
451
 
452
+ if ( old_state == SWITCH_STATE_COMPLETED ) {
453
+ delete_timer_event( echo_request_interval, sw_info );
454
+ }
455
+
347
456
  if ( sw_info->fragment_buf != NULL ) {
348
457
  free_buffer( sw_info->fragment_buf );
349
458
  sw_info->fragment_buf = NULL;
@@ -368,13 +477,16 @@ switch_event_disconnected( struct switch_info *sw_info ) {
368
477
  sw_info->secure_channel_fd = -1;
369
478
  }
370
479
 
371
- // send secure channle disconnect state to application
372
- service_send_state( sw_info, &sw_info->datapath_id, MESSENGER_OPENFLOW_DISCONNECTED );
480
+ if ( old_state != SWITCH_STATE_COMPLETED ) {
481
+ service_send_state( sw_info, &sw_info->datapath_id, MESSENGER_OPENFLOW_FAILD_TO_CONNECT );
482
+ }
483
+ else {
484
+ // send secure channle disconnect state to application
485
+ service_send_state( sw_info, &sw_info->datapath_id, MESSENGER_OPENFLOW_DISCONNECTED );
486
+ }
373
487
  flush_messenger();
374
- debug( "send disconnected state" );
375
488
 
376
- stop_event_handler();
377
- stop_messenger();
489
+ stop_trema();
378
490
 
379
491
  return 0;
380
492
  }
@@ -426,10 +538,16 @@ management_recv( uint16_t tag, void *data, size_t data_len ) {
426
538
  break;
427
539
 
428
540
  case DUMP_COOKIE_TABLE:
541
+ if ( !switch_info.cookie_translation ) {
542
+ break;
543
+ }
429
544
  dump_cookie_table();
430
545
  break;
431
546
 
432
547
  case TOGGLE_COOKIE_AGING:
548
+ if ( !switch_info.cookie_translation ) {
549
+ break;
550
+ }
433
551
  if ( age_cookie_table_enabled ) {
434
552
  delete_timer_event( age_cookie_table, NULL );
435
553
  age_cookie_table_enabled = false;
@@ -446,6 +564,22 @@ management_recv( uint16_t tag, void *data, size_t data_len ) {
446
564
  }
447
565
 
448
566
 
567
+ static void
568
+ stop_switch_daemon( void ) {
569
+ switch_event_disconnected( &switch_info );
570
+ }
571
+
572
+
573
+ static void
574
+ handle_sigterm( int signum ) {
575
+ UNUSED( signum );
576
+
577
+ if ( !set_external_callback( stop_switch_daemon ) ) {
578
+ stop_trema();
579
+ }
580
+ }
581
+
582
+
449
583
  int
450
584
  main( int argc, char *argv[] ) {
451
585
  int ret;
@@ -485,6 +619,12 @@ main( int argc, char *argv[] ) {
485
619
  }
486
620
  }
487
621
 
622
+ struct sigaction signal_exit;
623
+ memset( &signal_exit, 0, sizeof( struct sigaction ) );
624
+ signal_exit.sa_handler = handle_sigterm;
625
+ sigaction( SIGINT, &signal_exit, NULL );
626
+ sigaction( SIGTERM, &signal_exit, NULL );
627
+
488
628
  fcntl( switch_info.secure_channel_fd, F_SETFL, O_NONBLOCK );
489
629
 
490
630
  set_fd_handler( switch_info.secure_channel_fd, secure_channel_read, NULL, secure_channel_write, NULL );
@@ -499,9 +639,12 @@ main( int argc, char *argv[] ) {
499
639
  switch_info.send_queue = create_message_queue();
500
640
  switch_info.recv_queue = create_message_queue();
501
641
  switch_info.running_timer = false;
642
+ switch_info.echo_request_xid = 0;
502
643
 
503
644
  init_xid_table();
504
- init_cookie_table();
645
+ if ( switch_info.cookie_translation ) {
646
+ init_cookie_table();
647
+ }
505
648
 
506
649
  add_message_received_callback( get_trema_name(), service_recv );
507
650
 
@@ -520,7 +663,9 @@ main( int argc, char *argv[] ) {
520
663
  start_trema();
521
664
 
522
665
  finalize_xid_table();
523
- finalize_cookie_table();
666
+ if ( switch_info.cookie_translation ) {
667
+ finalize_cookie_table();
668
+ }
524
669
 
525
670
  if ( switch_info.secure_channel_fd >= 0 ) {
526
671
  delete_fd_handler( switch_info.secure_channel_fd );