trema 0.1.3

Sign up to get free protection for your applications and to get access to all the features.
Files changed (560) hide show
  1. data/.mono.rant +4107 -0
  2. data/.rspec +1 -0
  3. data/.yardopts +4 -0
  4. data/Doxyfile +1679 -0
  5. data/GPL2 +339 -0
  6. data/Gemfile +22 -0
  7. data/Gemfile.lock +71 -0
  8. data/README.md +135 -0
  9. data/Rakefile +140 -0
  10. data/Rantfile +834 -0
  11. data/VERSION +1 -0
  12. data/build.rb +32 -0
  13. data/cruise.rb +389 -0
  14. data/features/example.dumper.feature +87 -0
  15. data/features/example.learning_switch.feature +39 -0
  16. data/features/example.list_switches.feature +38 -0
  17. data/features/example.message.echo_reply.feature +26 -0
  18. data/features/example.message.echo_request.feature +25 -0
  19. data/features/example.message.features_request.feature +84 -0
  20. data/features/example.message.hello.feature +25 -0
  21. data/features/example.message.set_config.feature +27 -0
  22. data/features/example.multi_learning_switch.feature +135 -0
  23. data/features/example.packetin_filter_config.feature +91 -0
  24. data/features/example.repeater_hub.feature +49 -0
  25. data/features/example.switch_monitor.feature +39 -0
  26. data/features/packetin_filter.feature +49 -0
  27. data/features/step_definitions/kill_steps.rb +30 -0
  28. data/features/step_definitions/log_steps.rb +90 -0
  29. data/features/step_definitions/misc_steps.rb +64 -0
  30. data/features/step_definitions/off_steps.rb +30 -0
  31. data/features/step_definitions/run_steps.rb +91 -0
  32. data/features/step_definitions/send_packets_steps.rb +42 -0
  33. data/features/step_definitions/show_stats_steps.rb +43 -0
  34. data/features/step_definitions/stats_steps.rb +39 -0
  35. data/features/support/env.rb +75 -0
  36. data/features/support/hooks.rb +8 -0
  37. data/features/switch_manager.feature +35 -0
  38. data/features/trema-config.feature +68 -0
  39. data/features/trema.dump_flows.feature +25 -0
  40. data/features/trema.feature +25 -0
  41. data/features/trema.kill.feature +53 -0
  42. data/features/trema.killall.feature +30 -0
  43. data/features/trema.reset_stats.feature +14 -0
  44. data/features/trema.run.feature +46 -0
  45. data/features/trema.send_packets.feature +56 -0
  46. data/features/trema.show_stats.feature +67 -0
  47. data/features/tutorial.hello_trema.feature +27 -0
  48. data/features/tutorial.packet_in.feature +47 -0
  49. data/features/tutorial.switch_info.feature +55 -0
  50. data/ruby/.gitignore +4 -0
  51. data/ruby/blocker.rb +78 -0
  52. data/ruby/extconf.rb +71 -0
  53. data/ruby/sub-process.rb +291 -0
  54. data/ruby/trema/action-common.c +60 -0
  55. data/ruby/trema/action-common.h +42 -0
  56. data/ruby/trema/action-enqueue.c +161 -0
  57. data/ruby/trema/action-enqueue.h +40 -0
  58. data/ruby/trema/action-output.c +169 -0
  59. data/ruby/trema/action-output.h +42 -0
  60. data/ruby/trema/action-set-dl-dst.c +131 -0
  61. data/ruby/trema/action-set-dl-dst.h +44 -0
  62. data/ruby/trema/action-set-dl-src.c +131 -0
  63. data/ruby/trema/action-set-dl-src.h +44 -0
  64. data/ruby/trema/action-set-nw-dst.c +135 -0
  65. data/ruby/trema/action-set-nw-dst.h +42 -0
  66. data/ruby/trema/action-set-nw-src.c +140 -0
  67. data/ruby/trema/action-set-nw-src.h +42 -0
  68. data/ruby/trema/action-set-nw-tos.c +124 -0
  69. data/ruby/trema/action-set-nw-tos.h +42 -0
  70. data/ruby/trema/action-set-tp-dst.c +122 -0
  71. data/ruby/trema/action-set-tp-dst.h +42 -0
  72. data/ruby/trema/action-set-tp-src.c +124 -0
  73. data/ruby/trema/action-set-tp-src.h +42 -0
  74. data/ruby/trema/action-set-vlan-pcp.c +128 -0
  75. data/ruby/trema/action-set-vlan-pcp.h +42 -0
  76. data/ruby/trema/action-set-vlan-vid.c +125 -0
  77. data/ruby/trema/action-set-vlan-vid.h +42 -0
  78. data/ruby/trema/action-strip-vlan.c +81 -0
  79. data/ruby/trema/action-strip-vlan.h +42 -0
  80. data/ruby/trema/action-vendor.c +121 -0
  81. data/ruby/trema/action-vendor.h +42 -0
  82. data/ruby/trema/aggregate-stats-reply.rb +70 -0
  83. data/ruby/trema/app.rb +112 -0
  84. data/ruby/trema/barrier-reply.c +99 -0
  85. data/ruby/trema/barrier-reply.h +46 -0
  86. data/ruby/trema/barrier-request.c +108 -0
  87. data/ruby/trema/barrier-request.h +44 -0
  88. data/ruby/trema/cli.rb +269 -0
  89. data/ruby/trema/command.rb +40 -0
  90. data/ruby/trema/command/dump_flows.rb +62 -0
  91. data/ruby/trema/command/kill.rb +71 -0
  92. data/ruby/trema/command/killall.rb +56 -0
  93. data/ruby/trema/command/reset_stats.rb +61 -0
  94. data/ruby/trema/command/ruby.rb +55 -0
  95. data/ruby/trema/command/run.rb +120 -0
  96. data/ruby/trema/command/send_packets.rb +130 -0
  97. data/ruby/trema/command/shell.rb +61 -0
  98. data/ruby/trema/command/show_stats.rb +84 -0
  99. data/ruby/trema/command/usage.rb +61 -0
  100. data/ruby/trema/command/version.rb +39 -0
  101. data/ruby/trema/controller.c +595 -0
  102. data/ruby/trema/controller.h +44 -0
  103. data/ruby/trema/controller.rb +81 -0
  104. data/ruby/trema/daemon.rb +167 -0
  105. data/ruby/trema/dsl.rb +34 -0
  106. data/ruby/trema/dsl/configuration.rb +153 -0
  107. data/ruby/trema/dsl/context.rb +71 -0
  108. data/ruby/trema/dsl/link.rb +41 -0
  109. data/ruby/trema/dsl/parser.rb +70 -0
  110. data/ruby/trema/dsl/run.rb +49 -0
  111. data/ruby/trema/dsl/runner.rb +165 -0
  112. data/ruby/trema/dsl/stanza.rb +53 -0
  113. data/ruby/trema/dsl/switch.rb +78 -0
  114. data/ruby/trema/dsl/syntax-error.rb +33 -0
  115. data/ruby/trema/dsl/syntax.rb +109 -0
  116. data/ruby/trema/dsl/vhost.rb +108 -0
  117. data/ruby/trema/dsl/vswitch.rb +47 -0
  118. data/ruby/trema/echo-reply.c +107 -0
  119. data/ruby/trema/echo-reply.h +42 -0
  120. data/ruby/trema/echo-request.c +140 -0
  121. data/ruby/trema/echo-request.h +42 -0
  122. data/ruby/trema/error.c +253 -0
  123. data/ruby/trema/error.h +44 -0
  124. data/ruby/trema/exact-match.rb +36 -0
  125. data/ruby/trema/executables.rb +95 -0
  126. data/ruby/trema/features-reply.c +238 -0
  127. data/ruby/trema/features-reply.h +60 -0
  128. data/ruby/trema/features-request.c +109 -0
  129. data/ruby/trema/features-request.h +44 -0
  130. data/ruby/trema/flow-removed.c +275 -0
  131. data/ruby/trema/flow-removed.h +46 -0
  132. data/ruby/trema/flow-stats-reply.rb +109 -0
  133. data/ruby/trema/flow.rb +56 -0
  134. data/ruby/trema/get-config-reply.c +159 -0
  135. data/ruby/trema/get-config-reply.h +52 -0
  136. data/ruby/trema/get-config-request.c +107 -0
  137. data/ruby/trema/get-config-request.h +44 -0
  138. data/ruby/trema/hello.c +110 -0
  139. data/ruby/trema/hello.h +44 -0
  140. data/ruby/trema/host.rb +257 -0
  141. data/ruby/trema/ip.rb +101 -0
  142. data/ruby/trema/link.rb +176 -0
  143. data/ruby/trema/list-switches-reply.c +46 -0
  144. data/ruby/trema/list-switches-reply.h +40 -0
  145. data/ruby/trema/logger.c +162 -0
  146. data/ruby/trema/logger.h +44 -0
  147. data/ruby/trema/mac.rb +151 -0
  148. data/ruby/trema/match.c +594 -0
  149. data/ruby/trema/match.h +36 -0
  150. data/ruby/trema/monkey-patch/integer.rb +35 -0
  151. data/ruby/trema/monkey-patch/integer/base-conversions.rb +36 -0
  152. data/ruby/trema/monkey-patch/integer/ranges.rb +51 -0
  153. data/ruby/trema/monkey-patch/module.rb +33 -0
  154. data/ruby/trema/monkey-patch/module/deprecation.rb +41 -0
  155. data/ruby/trema/monkey-patch/string.rb +33 -0
  156. data/ruby/trema/monkey-patch/string/inflectors.rb +54 -0
  157. data/ruby/trema/network-component.rb +153 -0
  158. data/ruby/trema/ofctl.rb +62 -0
  159. data/ruby/trema/open-vswitch.rb +154 -0
  160. data/ruby/trema/openflow-error.c +191 -0
  161. data/ruby/trema/openflow-error.h +53 -0
  162. data/ruby/trema/openflow-switch.rb +88 -0
  163. data/ruby/trema/ordered-hash.rb +74 -0
  164. data/ruby/trema/packet-queue.rb +178 -0
  165. data/ruby/trema/packet_in.c +736 -0
  166. data/ruby/trema/packet_in.h +46 -0
  167. data/ruby/trema/packetin-filter.rb +126 -0
  168. data/ruby/trema/path.rb +135 -0
  169. data/ruby/trema/phost.rb +69 -0
  170. data/ruby/trema/port-mod.c +226 -0
  171. data/ruby/trema/port-mod.h +36 -0
  172. data/ruby/trema/port-stats-reply.rb +111 -0
  173. data/ruby/trema/port-status.c +156 -0
  174. data/ruby/trema/port-status.h +45 -0
  175. data/ruby/trema/port.c +295 -0
  176. data/ruby/trema/port.h +47 -0
  177. data/ruby/trema/process.rb +76 -0
  178. data/ruby/trema/queue-get-config-reply.c +200 -0
  179. data/ruby/trema/queue-get-config-reply.h +47 -0
  180. data/ruby/trema/queue-get-config-request.c +141 -0
  181. data/ruby/trema/queue-get-config-request.h +44 -0
  182. data/ruby/trema/queue-stats-reply.rb +78 -0
  183. data/ruby/trema/set-config.c +171 -0
  184. data/ruby/trema/set-config.h +44 -0
  185. data/ruby/trema/shell.rb +39 -0
  186. data/ruby/trema/shell/down.rb +39 -0
  187. data/ruby/trema/shell/killall.rb +40 -0
  188. data/ruby/trema/shell/link.rb +61 -0
  189. data/ruby/trema/shell/reset_stats.rb +50 -0
  190. data/ruby/trema/shell/run.rb +67 -0
  191. data/ruby/trema/shell/send_packets.rb +42 -0
  192. data/ruby/trema/shell/show_stats.rb +49 -0
  193. data/ruby/trema/shell/up.rb +43 -0
  194. data/ruby/trema/shell/vhost.rb +44 -0
  195. data/ruby/trema/shell/vswitch.rb +49 -0
  196. data/ruby/trema/stats-helper.rb +65 -0
  197. data/ruby/trema/stats-reply.c +483 -0
  198. data/ruby/trema/stats-reply.h +53 -0
  199. data/ruby/trema/stats-request.c +634 -0
  200. data/ruby/trema/stats-request.h +42 -0
  201. data/ruby/trema/switch-daemon.rb +74 -0
  202. data/ruby/trema/switch-disconnected.c +40 -0
  203. data/ruby/trema/switch-disconnected.h +38 -0
  204. data/ruby/trema/switch-manager.rb +121 -0
  205. data/ruby/trema/switch.rb +37 -0
  206. data/ruby/trema/table-stats-reply.rb +87 -0
  207. data/ruby/trema/timers.rb +97 -0
  208. data/ruby/trema/trema.c +122 -0
  209. data/ruby/trema/tremashark.rb +39 -0
  210. data/ruby/trema/util.rb +84 -0
  211. data/ruby/trema/vendor-request.c +193 -0
  212. data/ruby/trema/vendor-request.h +44 -0
  213. data/ruby/trema/vendor-stats-reply.rb +62 -0
  214. data/ruby/trema/vendor.c +152 -0
  215. data/ruby/trema/vendor.h +52 -0
  216. data/ruby/trema/version.rb +30 -0
  217. data/spec/spec_helper.rb +153 -0
  218. data/spec/support/openflow-message.rb +94 -0
  219. data/spec/trema/action-enqueue_spec.rb +100 -0
  220. data/spec/trema/action-output_spec.rb +116 -0
  221. data/spec/trema/action-set-dl-dst_spec.rb +95 -0
  222. data/spec/trema/action-set-dl-src_spec.rb +92 -0
  223. data/spec/trema/action-set-nw-dst_spec.rb +96 -0
  224. data/spec/trema/action-set-nw-src_spec.rb +97 -0
  225. data/spec/trema/action-set-nw-tos_spec.rb +88 -0
  226. data/spec/trema/action-set-tp-dst_spec.rb +88 -0
  227. data/spec/trema/action-set-tp-src_spec.rb +88 -0
  228. data/spec/trema/action-set-vlan-pcp_spec.rb +91 -0
  229. data/spec/trema/action-set-vlan-vid_spec.rb +91 -0
  230. data/spec/trema/action-strip-vlan_spec.rb +57 -0
  231. data/spec/trema/action-vendor_spec.rb +90 -0
  232. data/spec/trema/app_spec.rb +90 -0
  233. data/spec/trema/barrier-reply_spec.rb +45 -0
  234. data/spec/trema/barrier-request_spec.rb +83 -0
  235. data/spec/trema/cli_spec.rb +160 -0
  236. data/spec/trema/controller_spec.rb +100 -0
  237. data/spec/trema/dsl/configuration_spec.rb +122 -0
  238. data/spec/trema/dsl/link_spec.rb +54 -0
  239. data/spec/trema/dsl/run_spec.rb +78 -0
  240. data/spec/trema/dsl/runner_spec.rb +239 -0
  241. data/spec/trema/dsl/switch_spec.rb +77 -0
  242. data/spec/trema/dsl/syntax_spec.rb +121 -0
  243. data/spec/trema/dsl/vhost_spec.rb +148 -0
  244. data/spec/trema/dsl/vswitch_spec.rb +90 -0
  245. data/spec/trema/echo-reply_spec.rb +49 -0
  246. data/spec/trema/echo-request_spec.rb +75 -0
  247. data/spec/trema/error_spec.rb +142 -0
  248. data/spec/trema/executables_spec.rb +75 -0
  249. data/spec/trema/features-reply_spec.rb +57 -0
  250. data/spec/trema/features-request_spec.rb +66 -0
  251. data/spec/trema/flow-removed_spec.rb +146 -0
  252. data/spec/trema/get-config-reply_spec.rb +43 -0
  253. data/spec/trema/get-config-request_spec.rb +82 -0
  254. data/spec/trema/hello_spec.rb +49 -0
  255. data/spec/trema/host_spec.rb +193 -0
  256. data/spec/trema/link_spec.rb +64 -0
  257. data/spec/trema/list-switches-reply_spec.rb +48 -0
  258. data/spec/trema/logger_spec.rb +48 -0
  259. data/spec/trema/mac_spec.rb +115 -0
  260. data/spec/trema/match_spec.rb +113 -0
  261. data/spec/trema/open-vswitch_spec.rb +123 -0
  262. data/spec/trema/openflow-error_spec.rb +141 -0
  263. data/spec/trema/openflow-switch_spec.rb +56 -0
  264. data/spec/trema/packet-in_spec.rb +168 -0
  265. data/spec/trema/packet-out_spec.rb +128 -0
  266. data/spec/trema/packetin-filter_spec.rb +41 -0
  267. data/spec/trema/port-mod_spec.rb +101 -0
  268. data/spec/trema/port-status_spec.rb +108 -0
  269. data/spec/trema/port_spec.rb +61 -0
  270. data/spec/trema/process_spec.rb +71 -0
  271. data/spec/trema/queue-get-config-reply_spec.rb +66 -0
  272. data/spec/trema/queue-get-config-request_spec.rb +69 -0
  273. data/spec/trema/set-config_spec.rb +80 -0
  274. data/spec/trema/shell/vhost_spec.rb +57 -0
  275. data/spec/trema/shell/vswitch_spec.rb +89 -0
  276. data/spec/trema/stats-reply_spec.rb +306 -0
  277. data/spec/trema/stats-request_spec.rb +151 -0
  278. data/spec/trema/switch-disconnected_spec.rb +58 -0
  279. data/spec/trema/switch-manager_spec.rb +43 -0
  280. data/spec/trema/tremashark_spec.rb +41 -0
  281. data/spec/trema/util_spec.rb +93 -0
  282. data/spec/trema/vendor-request_spec.rb +79 -0
  283. data/src/examples/cbench_switch/README +21 -0
  284. data/src/examples/cbench_switch/cbench-switch.rb +39 -0
  285. data/src/examples/cbench_switch/cbench_switch.c +68 -0
  286. data/src/examples/dumper/dumper.c +370 -0
  287. data/src/examples/dumper/dumper.conf +7 -0
  288. data/src/examples/dumper/dumper.rb +196 -0
  289. data/src/examples/hello_trema/README +13 -0
  290. data/src/examples/hello_trema/hello_trema.c +51 -0
  291. data/src/examples/hello_trema/hello_trema.conf +3 -0
  292. data/src/examples/hello_trema/hello_trema.rb +35 -0
  293. data/src/examples/learning_switch/README +15 -0
  294. data/src/examples/learning_switch/fdb.rb +112 -0
  295. data/src/examples/learning_switch/learning-switch.rb +88 -0
  296. data/src/examples/learning_switch/learning_switch.c +236 -0
  297. data/src/examples/learning_switch/learning_switch.conf +18 -0
  298. data/src/examples/list_switches/README +19 -0
  299. data/src/examples/list_switches/list-switches.rb +45 -0
  300. data/src/examples/list_switches/list_switches.c +81 -0
  301. data/src/examples/list_switches/list_switches.conf +15 -0
  302. data/src/examples/match_compare/match-compare.conf +30 -0
  303. data/src/examples/match_compare/match-compare.rb +99 -0
  304. data/src/examples/multi_learning_switch/README +14 -0
  305. data/src/examples/multi_learning_switch/multi-learning-switch.rb +96 -0
  306. data/src/examples/multi_learning_switch/multi_learning_switch.c +296 -0
  307. data/src/examples/multi_learning_switch/multi_learning_switch.conf +17 -0
  308. data/src/examples/openflow_message/README +11 -0
  309. data/src/examples/openflow_message/echo-reply.rb +59 -0
  310. data/src/examples/openflow_message/echo-request.rb +58 -0
  311. data/src/examples/openflow_message/echo_reply.c +70 -0
  312. data/src/examples/openflow_message/echo_request.c +70 -0
  313. data/src/examples/openflow_message/example.rb +63 -0
  314. data/src/examples/openflow_message/features-request.rb +97 -0
  315. data/src/examples/openflow_message/features_request.c +168 -0
  316. data/src/examples/openflow_message/hello.c +70 -0
  317. data/src/examples/openflow_message/hello.rb +58 -0
  318. data/src/examples/openflow_message/set-config.rb +59 -0
  319. data/src/examples/openflow_message/set_config.c +70 -0
  320. data/src/examples/packet_in/README +15 -0
  321. data/src/examples/packet_in/packet_in.c +55 -0
  322. data/src/examples/packet_in/packet_in.conf +15 -0
  323. data/src/examples/packet_in/packet_in.rb +34 -0
  324. data/src/examples/packetin_filter_config/README +12 -0
  325. data/src/examples/packetin_filter_config/add_filter.c +73 -0
  326. data/src/examples/packetin_filter_config/delete_filter.c +65 -0
  327. data/src/examples/packetin_filter_config/delete_filter_strict.c +75 -0
  328. data/src/examples/packetin_filter_config/dump_filter.c +65 -0
  329. data/src/examples/packetin_filter_config/dump_filter_strict.c +75 -0
  330. data/src/examples/packetin_filter_config/packetin_filter_config.c +134 -0
  331. data/src/examples/packetin_filter_config/packetin_filter_config.conf +7 -0
  332. data/src/examples/packetin_filter_config/utils.c +102 -0
  333. data/src/examples/packetin_filter_config/utils.h +42 -0
  334. data/src/examples/repeater_hub/README +8 -0
  335. data/src/examples/repeater_hub/repeater-hub.rb +43 -0
  336. data/src/examples/repeater_hub/repeater-hub_spec.rb +156 -0
  337. data/src/examples/repeater_hub/repeater_hub.c +83 -0
  338. data/src/examples/repeater_hub/repeater_hub.conf +28 -0
  339. data/src/examples/switch_info/README +13 -0
  340. data/src/examples/switch_info/switch_info.c +80 -0
  341. data/src/examples/switch_info/switch_info.conf +3 -0
  342. data/src/examples/switch_info/switch_info.rb +46 -0
  343. data/src/examples/switch_monitor/switch-monitor.conf +3 -0
  344. data/src/examples/switch_monitor/switch-monitor.rb +58 -0
  345. data/src/examples/switch_monitor/switch_monitor.c +154 -0
  346. data/src/examples/traffic_monitor/counter.c +74 -0
  347. data/src/examples/traffic_monitor/counter.h +48 -0
  348. data/src/examples/traffic_monitor/counter.rb +46 -0
  349. data/src/examples/traffic_monitor/fdb.c +76 -0
  350. data/src/examples/traffic_monitor/fdb.h +50 -0
  351. data/src/examples/traffic_monitor/fdb.rb +44 -0
  352. data/src/examples/traffic_monitor/traffic-monitor.rb +100 -0
  353. data/src/examples/traffic_monitor/traffic_monitor.c +163 -0
  354. data/src/examples/traffic_monitor/traffic_monitor.conf +16 -0
  355. data/src/lib/arp.h +61 -0
  356. data/src/lib/bool.h +49 -0
  357. data/src/lib/buffer.c +305 -0
  358. data/src/lib/buffer.h +56 -0
  359. data/src/lib/byteorder.c +547 -0
  360. data/src/lib/byteorder.h +110 -0
  361. data/src/lib/checks.h +42 -0
  362. data/src/lib/daemon.c +302 -0
  363. data/src/lib/daemon.h +42 -0
  364. data/src/lib/doubly_linked_list.c +281 -0
  365. data/src/lib/doubly_linked_list.h +88 -0
  366. data/src/lib/ether.c +48 -0
  367. data/src/lib/ether.h +94 -0
  368. data/src/lib/etherip.h +46 -0
  369. data/src/lib/event_handler.c +389 -0
  370. data/src/lib/event_handler.h +64 -0
  371. data/src/lib/hash_table.c +417 -0
  372. data/src/lib/hash_table.h +138 -0
  373. data/src/lib/icmp.h +74 -0
  374. data/src/lib/igmp.h +50 -0
  375. data/src/lib/ipv4.h +50 -0
  376. data/src/lib/linked_list.c +199 -0
  377. data/src/lib/linked_list.h +84 -0
  378. data/src/lib/log.c +402 -0
  379. data/src/lib/log.h +78 -0
  380. data/src/lib/match.h +84 -0
  381. data/src/lib/match_table.c +608 -0
  382. data/src/lib/match_table.h +51 -0
  383. data/src/lib/message_queue.c +143 -0
  384. data/src/lib/message_queue.h +61 -0
  385. data/src/lib/messenger.c +1714 -0
  386. data/src/lib/messenger.h +145 -0
  387. data/src/lib/openflow_application_interface.c +1673 -0
  388. data/src/lib/openflow_application_interface.h +329 -0
  389. data/src/lib/openflow_message.c +4051 -0
  390. data/src/lib/openflow_message.h +288 -0
  391. data/src/lib/openflow_service_interface.h +59 -0
  392. data/src/lib/packet_info.c +230 -0
  393. data/src/lib/packet_info.h +209 -0
  394. data/src/lib/packet_parser.c +502 -0
  395. data/src/lib/packetin_filter_interface.c +294 -0
  396. data/src/lib/packetin_filter_interface.h +127 -0
  397. data/src/lib/persistent_storage.c +480 -0
  398. data/src/lib/persistent_storage.h +46 -0
  399. data/src/lib/stat.c +213 -0
  400. data/src/lib/stat.h +44 -0
  401. data/src/lib/tcp.h +67 -0
  402. data/src/lib/timer.c +350 -0
  403. data/src/lib/timer.h +53 -0
  404. data/src/lib/trema.c +710 -0
  405. data/src/lib/trema.h +79 -0
  406. data/src/lib/trema_private.c +177 -0
  407. data/src/lib/trema_private.h +60 -0
  408. data/src/lib/trema_wrapper.c +56 -0
  409. data/src/lib/trema_wrapper.h +64 -0
  410. data/src/lib/udp.h +43 -0
  411. data/src/lib/utility.c +515 -0
  412. data/src/lib/utility.h +67 -0
  413. data/src/lib/wrapper.c +100 -0
  414. data/src/lib/wrapper.h +76 -0
  415. data/src/packetin_filter/README +17 -0
  416. data/src/packetin_filter/packetin_filter.c +575 -0
  417. data/src/switch_manager/README +20 -0
  418. data/src/switch_manager/cookie_table.c +292 -0
  419. data/src/switch_manager/cookie_table.h +72 -0
  420. data/src/switch_manager/dpid_table.c +110 -0
  421. data/src/switch_manager/dpid_table.h +46 -0
  422. data/src/switch_manager/management_interface.h +44 -0
  423. data/src/switch_manager/ofpmsg_recv.c +482 -0
  424. data/src/switch_manager/ofpmsg_recv.h +42 -0
  425. data/src/switch_manager/ofpmsg_send.c +235 -0
  426. data/src/switch_manager/ofpmsg_send.h +50 -0
  427. data/src/switch_manager/secure_channel_listener.c +281 -0
  428. data/src/switch_manager/secure_channel_listener.h +42 -0
  429. data/src/switch_manager/secure_channel_receiver.c +126 -0
  430. data/src/switch_manager/secure_channel_receiver.h +43 -0
  431. data/src/switch_manager/secure_channel_sender.c +126 -0
  432. data/src/switch_manager/secure_channel_sender.h +43 -0
  433. data/src/switch_manager/service_interface.c +181 -0
  434. data/src/switch_manager/service_interface.h +46 -0
  435. data/src/switch_manager/switch.c +538 -0
  436. data/src/switch_manager/switch.h +51 -0
  437. data/src/switch_manager/switch_manager.c +448 -0
  438. data/src/switch_manager/switch_manager.h +63 -0
  439. data/src/switch_manager/switchinfo.h +72 -0
  440. data/src/switch_manager/xid_table.c +184 -0
  441. data/src/switch_manager/xid_table.h +56 -0
  442. data/src/tremashark/README +78 -0
  443. data/src/tremashark/packet_capture.c +357 -0
  444. data/src/tremashark/pcap_private.h +47 -0
  445. data/src/tremashark/pcap_queue.c +197 -0
  446. data/src/tremashark/pcap_queue.h +58 -0
  447. data/src/tremashark/plugin/.gitignore +6 -0
  448. data/src/tremashark/plugin/packet-trema/.gitignore +5 -0
  449. data/src/tremashark/plugin/packet-trema/Makefile +77 -0
  450. data/src/tremashark/plugin/packet-trema/Makefile.am +110 -0
  451. data/src/tremashark/plugin/packet-trema/Makefile.common +31 -0
  452. data/src/tremashark/plugin/packet-trema/moduleinfo.h +41 -0
  453. data/src/tremashark/plugin/packet-trema/packet-trema.c +1659 -0
  454. data/src/tremashark/plugin/packet-trema/plugin.c +31 -0
  455. data/src/tremashark/plugin/user_dlts +2 -0
  456. data/src/tremashark/queue.c +168 -0
  457. data/src/tremashark/queue.h +60 -0
  458. data/src/tremashark/stdin_relay.c +257 -0
  459. data/src/tremashark/syslog_relay.c +247 -0
  460. data/src/tremashark/tremashark.c +556 -0
  461. data/trema +93 -0
  462. data/trema-config +61 -0
  463. data/unittests/buffer_stubs.c +74 -0
  464. data/unittests/cmockery_trema.c +123 -0
  465. data/unittests/cmockery_trema.h +96 -0
  466. data/unittests/lib/buffer_test.c +370 -0
  467. data/unittests/lib/byteorder_test.c +1717 -0
  468. data/unittests/lib/daemon_test.c +664 -0
  469. data/unittests/lib/doubly_linked_list_test.c +346 -0
  470. data/unittests/lib/ether_test.c +127 -0
  471. data/unittests/lib/hash_table_test.c +278 -0
  472. data/unittests/lib/linked_list_test.c +343 -0
  473. data/unittests/lib/log_test.c +459 -0
  474. data/unittests/lib/match_table_test.c +1509 -0
  475. data/unittests/lib/message_queue_test.c +379 -0
  476. data/unittests/lib/messenger_test.c +438 -0
  477. data/unittests/lib/openflow_application_interface_test.c +3488 -0
  478. data/unittests/lib/openflow_message_test.c +7337 -0
  479. data/unittests/lib/packet_info_test.c +544 -0
  480. data/unittests/lib/packet_parser_test.c +703 -0
  481. data/unittests/lib/packetin_filter_interface_test.c +723 -0
  482. data/unittests/lib/persistent_storage_test.c +802 -0
  483. data/unittests/lib/stat_test.c +291 -0
  484. data/unittests/lib/test_packets/arp_rep.cap +0 -0
  485. data/unittests/lib/test_packets/arp_req.cap +0 -0
  486. data/unittests/lib/test_packets/icmp_echo_rep.cap +0 -0
  487. data/unittests/lib/test_packets/icmp_echo_req.cap +0 -0
  488. data/unittests/lib/test_packets/igmp_query_v2.cap +0 -0
  489. data/unittests/lib/test_packets/ipx.cap +0 -0
  490. data/unittests/lib/test_packets/lldp.cap +0 -0
  491. data/unittests/lib/test_packets/lldp_over_ip.cap +0 -0
  492. data/unittests/lib/test_packets/tcp.cap +0 -0
  493. data/unittests/lib/test_packets/tcp_syn.cap +0 -0
  494. data/unittests/lib/test_packets/udp.cap +0 -0
  495. data/unittests/lib/test_packets/udp_frag_head.cap +0 -0
  496. data/unittests/lib/test_packets/udp_frag_next.cap +0 -0
  497. data/unittests/lib/test_packets/vtag_icmp_echo_rep.cap +0 -0
  498. data/unittests/lib/test_packets/vtag_icmp_echo_req.cap +0 -0
  499. data/unittests/lib/timer_test.c +248 -0
  500. data/unittests/lib/trema_private_test.c +323 -0
  501. data/unittests/lib/trema_test.c +985 -0
  502. data/unittests/lib/utility_test.c +628 -0
  503. data/unittests/lib/wrapper_test.c +201 -0
  504. data/unittests/packetin_filter/packetin_filter_test.c +477 -0
  505. data/unittests/switch_manager/switch_manager_test.c +1178 -0
  506. data/unittests/wrapper_stubs.c +39 -0
  507. data/vendor/.gitignore +6 -0
  508. data/vendor/README +30 -0
  509. data/vendor/cmockery-20110428.tar.gz +0 -0
  510. data/vendor/oflops-0.03.tar.gz +0 -0
  511. data/vendor/oflops_no_snmp+1.0.0.patch +340 -0
  512. data/vendor/openflow-1.0.0.tar.gz +0 -0
  513. data/vendor/openflow.git.tar.gz +0 -0
  514. data/vendor/openvswitch-1.2.2.tar.gz +0 -0
  515. data/vendor/ruby-ifconfig-1.2/COPYING +340 -0
  516. data/vendor/ruby-ifconfig-1.2/Changelog +16 -0
  517. data/vendor/ruby-ifconfig-1.2/INSTALL +239 -0
  518. data/vendor/ruby-ifconfig-1.2/README +38 -0
  519. data/vendor/ruby-ifconfig-1.2/Rakefile +14 -0
  520. data/vendor/ruby-ifconfig-1.2/TODO +8 -0
  521. data/vendor/ruby-ifconfig-1.2/ifconfig_examples/darwin.txt +17 -0
  522. data/vendor/ruby-ifconfig-1.2/ifconfig_examples/dragonflybsd.txt +10 -0
  523. data/vendor/ruby-ifconfig-1.2/ifconfig_examples/dragonflybsd_netstat.txt +14 -0
  524. data/vendor/ruby-ifconfig-1.2/ifconfig_examples/freebsd.txt +17 -0
  525. data/vendor/ruby-ifconfig-1.2/ifconfig_examples/freebsd_netstat.txt +24 -0
  526. data/vendor/ruby-ifconfig-1.2/ifconfig_examples/linux.txt +60 -0
  527. data/vendor/ruby-ifconfig-1.2/ifconfig_examples/linux_ethernet.txt +20 -0
  528. data/vendor/ruby-ifconfig-1.2/ifconfig_examples/netbsd.txt +10 -0
  529. data/vendor/ruby-ifconfig-1.2/ifconfig_examples/openbsd.txt +36 -0
  530. data/vendor/ruby-ifconfig-1.2/ifconfig_examples/sunos.txt +10 -0
  531. data/vendor/ruby-ifconfig-1.2/lib/ifconfig.rb +71 -0
  532. data/vendor/ruby-ifconfig-1.2/lib/ifconfig/bsd/ifconfig.rb +72 -0
  533. data/vendor/ruby-ifconfig-1.2/lib/ifconfig/bsd/interface_types.rb +69 -0
  534. data/vendor/ruby-ifconfig-1.2/lib/ifconfig/bsd/network_types.rb +3 -0
  535. data/vendor/ruby-ifconfig-1.2/lib/ifconfig/common/ifconfig.rb +84 -0
  536. data/vendor/ruby-ifconfig-1.2/lib/ifconfig/common/interface_types.rb +130 -0
  537. data/vendor/ruby-ifconfig-1.2/lib/ifconfig/common/network_types.rb +49 -0
  538. data/vendor/ruby-ifconfig-1.2/lib/ifconfig/linux/ifconfig.rb +43 -0
  539. data/vendor/ruby-ifconfig-1.2/lib/ifconfig/linux/interface_types.rb +112 -0
  540. data/vendor/ruby-ifconfig-1.2/lib/ifconfig/linux/network_types.rb +55 -0
  541. data/vendor/ruby-ifconfig-1.2/lib/ifconfig/sunos/ifconfig.rb +38 -0
  542. data/vendor/ruby-ifconfig-1.2/lib/ifconfig/sunos/interface_types.rb +77 -0
  543. data/vendor/ruby-ifconfig-1.2/lib/ifconfig/sunos/network_types.rb +4 -0
  544. data/vendor/ruby-ifconfig-1.2/setup.rb +1306 -0
  545. data/vendor/ruby-ifconfig-1.2/test/test_bsd.rb +35 -0
  546. data/vendor/ruby-ifconfig-1.2/test/test_darwin.rb +33 -0
  547. data/vendor/ruby-ifconfig-1.2/test/test_dragonflybsd.rb +35 -0
  548. data/vendor/ruby-ifconfig-1.2/test/test_helper.rb +4 -0
  549. data/vendor/ruby-ifconfig-1.2/test/test_linux.rb +31 -0
  550. data/vendor/ruby-ifconfig-1.2/test/test_netbsd.rb +33 -0
  551. data/vendor/ruby-ifconfig-1.2/test/test_openbsd.rb +33 -0
  552. data/vendor/ruby-ifconfig-1.2/test/test_sunos.rb +35 -0
  553. data/vendor/ruby-ifconfig-1.2/test/unit/tc_darwin.rb +40 -0
  554. data/vendor/ruby-ifconfig-1.2/test/unit/tc_dragonflybsd.rb +39 -0
  555. data/vendor/ruby-ifconfig-1.2/test/unit/tc_freebsd.rb +40 -0
  556. data/vendor/ruby-ifconfig-1.2/test/unit/tc_linux.rb +49 -0
  557. data/vendor/ruby-ifconfig-1.2/test/unit/tc_netbsd.rb +39 -0
  558. data/vendor/ruby-ifconfig-1.2/test/unit/tc_openbsd.rb +39 -0
  559. data/vendor/ruby-ifconfig-1.2/test/unit/tc_sunos.rb +44 -0
  560. metadata +856 -0
@@ -0,0 +1,145 @@
1
+ /*
2
+ * Trema messenger library.
3
+ *
4
+ * Author: Toshio Koide
5
+ *
6
+ * Copyright (C) 2008-2012 NEC Corporation
7
+ *
8
+ * This program is free software; you can redistribute it and/or modify
9
+ * it under the terms of the GNU General Public License, version 2, as
10
+ * published by the Free Software Foundation.
11
+ *
12
+ * This program is distributed in the hope that it will be useful,
13
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
14
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15
+ * GNU General Public License for more details.
16
+ *
17
+ * You should have received a copy of the GNU General Public License along
18
+ * with this program; if not, write to the Free Software Foundation, Inc.,
19
+ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
20
+ */
21
+
22
+
23
+ #ifndef MESSENGER_H
24
+ #define MESSENGER_H
25
+
26
+
27
+ #include <net/if.h>
28
+ #include <stdint.h>
29
+ #include <stdlib.h>
30
+ #include <time.h>
31
+ #include "checks.h"
32
+ #include "bool.h"
33
+
34
+
35
+ #define MESSENGER_SERVICE_NAME_LENGTH 32
36
+
37
+
38
+ typedef struct message_header {
39
+ uint8_t version; // version = 0 (unused)
40
+ uint8_t message_type; // MESSAGE_TYPE_
41
+ uint16_t tag; // user defined
42
+ uint32_t message_length; // message length including header
43
+ uint8_t value[ 0 ];
44
+ } message_header;
45
+
46
+ typedef struct messenger_context_handle {
47
+ uint32_t transaction_id;
48
+ uint16_t service_name_len;
49
+ uint16_t pad;
50
+ char service_name[ 0 ];
51
+ } messenger_context_handle;
52
+
53
+ /* message dump format:
54
+ * +-------------------+--------+------------+----+
55
+ * |message_dump_header|app_name|service_name|data|
56
+ * +-------------------+--------+------------+----+
57
+ */
58
+ typedef struct message_dump_header {
59
+ struct { // same as struct timespec but fixed length
60
+ uint32_t sec;
61
+ uint32_t nsec;
62
+ } sent_time;
63
+ uint16_t app_name_length;
64
+ uint16_t service_name_length;
65
+ uint32_t data_length;
66
+ } message_dump_header;
67
+
68
+ enum {
69
+ MESSENGER_DUMP_SENT,
70
+ MESSENGER_DUMP_RECEIVED,
71
+ MESSENGER_DUMP_RECV_CONNECTED,
72
+ MESSENGER_DUMP_RECV_OVERFLOW,
73
+ MESSENGER_DUMP_RECV_CLOSED,
74
+ MESSENGER_DUMP_SEND_CONNECTED,
75
+ MESSENGER_DUMP_SEND_REFUSED,
76
+ MESSENGER_DUMP_SEND_OVERFLOW,
77
+ MESSENGER_DUMP_SEND_CLOSED,
78
+ MESSENGER_DUMP_LOGGER,
79
+ MESSENGER_DUMP_PCAP,
80
+ MESSENGER_DUMP_SYSLOG,
81
+ MESSENGER_DUMP_TEXT,
82
+ };
83
+
84
+ typedef struct pcap_dump_header {
85
+ uint32_t datalink;
86
+ uint8_t interface[ IF_NAMESIZE ];
87
+ } pcap_dump_header;
88
+
89
+ typedef struct logger_dump_header {
90
+ struct {
91
+ uint32_t sec;
92
+ uint32_t nsec;
93
+ } sent_time;
94
+ } logger_dump_header;
95
+
96
+ typedef struct syslog_dump_header {
97
+ struct {
98
+ uint32_t sec;
99
+ uint32_t nsec;
100
+ } sent_time;
101
+ } syslog_dump_header;
102
+
103
+ typedef struct text_dump_header {
104
+ struct {
105
+ uint32_t sec;
106
+ uint32_t nsec;
107
+ } sent_time;
108
+ } text_dump_header;
109
+
110
+
111
+ typedef void ( *callback_message_received )( uint16_t tag, void *data, size_t len );
112
+
113
+
114
+ extern bool ( *add_message_received_callback )( const char *service_name, const callback_message_received function );
115
+ extern bool ( *rename_message_received_callback )( const char *old_service_name, const char *new_service_name );
116
+ extern bool ( *delete_message_received_callback )( const char *service_name, void ( *callback )( uint16_t tag, void *data, size_t len ) );
117
+ extern bool ( *add_message_requested_callback )( const char *service_name, void ( *callback )( const messenger_context_handle *handle, uint16_t tag, void *data, size_t len ) );
118
+ extern bool ( *delete_message_requested_callback )( const char *service_name, void ( *callback )( const messenger_context_handle *handle, uint16_t tag, void *data, size_t len ) );
119
+ extern bool ( *add_message_replied_callback )( const char *service_name, void ( *callback )( uint16_t tag, void *data, size_t len, void *user_data ) );
120
+ extern bool ( *delete_message_replied_callback )( const char *service_name, void ( *callback )( uint16_t tag, void *data, size_t len, void *user_data ) );
121
+ extern bool ( *send_message )( const char *service_name, const uint16_t tag, const void *data, size_t len );
122
+ extern bool ( *send_request_message )( const char *to_service_name, const char *from_service_name, const uint16_t tag, const void *data, size_t len, void *user_data );
123
+ extern bool ( *send_reply_message )( const messenger_context_handle *handle, const uint16_t tag, const void *data, size_t len );
124
+
125
+ bool init_messenger( const char *working_directory );
126
+ bool finalize_messenger( void );
127
+
128
+ bool start_messenger( void );
129
+ int flush_messenger( void );
130
+ bool stop_messenger( void );
131
+
132
+ void start_messenger_dump( const char *dump_app_name, const char *dump_service_name );
133
+ void stop_messenger_dump( void );
134
+ bool messenger_dump_enabled( void );
135
+
136
+
137
+ #endif // MESSENGER_H
138
+
139
+
140
+ /*
141
+ * Local variables:
142
+ * c-basic-offset: 2
143
+ * indent-tabs-mode: nil
144
+ * End:
145
+ */
@@ -0,0 +1,1673 @@
1
+ /*
2
+ * Author: Yasunobu Chiba
3
+ *
4
+ * Copyright (C) 2008-2012 NEC Corporation
5
+ *
6
+ * This program is free software; you can redistribute it and/or modify
7
+ * it under the terms of the GNU General Public License, version 2, as
8
+ * published by the Free Software Foundation.
9
+ *
10
+ * This program is distributed in the hope that it will be useful,
11
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
12
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13
+ * GNU General Public License for more details.
14
+ *
15
+ * You should have received a copy of the GNU General Public License along
16
+ * with this program; if not, write to the Free Software Foundation, Inc.,
17
+ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
18
+ */
19
+
20
+
21
+ #include <assert.h>
22
+ #include <inttypes.h>
23
+ #include <stdio.h>
24
+ #include <string.h>
25
+ #include <unistd.h>
26
+ #include "trema.h"
27
+ #include "log.h"
28
+ #include "messenger.h"
29
+ #include "openflow_application_interface.h"
30
+ #include "openflow_message.h"
31
+ #include "packet_info.h"
32
+ #include "wrapper.h"
33
+
34
+
35
+ #ifdef UNIT_TESTING
36
+
37
+ #define static
38
+
39
+ #ifdef get_trema_name
40
+ #undef get_trema_name
41
+ #endif
42
+ #define get_trema_name mock_get_trema_name
43
+ const char *mock_get_trema_name( void );
44
+
45
+ #ifdef send_message
46
+ #undef send_message
47
+ #endif
48
+ #define send_message mock_send_message
49
+ bool mock_send_message( char *service_name, uint16_t tag, void *data, size_t len );
50
+
51
+ #ifdef send_request_message
52
+ #undef send_request_message
53
+ #endif
54
+ #define send_request_message mock_send_request_message
55
+ bool mock_send_request_message( const char *to_service_name, char *from_service_name, uint16_t tag,
56
+ void *data, size_t len, void *user_data );
57
+
58
+ #ifdef init_openflow_message
59
+ #undef init_openflow_message
60
+ #endif
61
+ #define init_openflow_message mock_init_openflow_message
62
+ bool mock_init_openflow_message( void );
63
+
64
+ #ifdef add_message_received_callback
65
+ #undef add_message_received_callback
66
+ #endif
67
+ #define add_message_received_callback mock_add_message_received_callback
68
+ bool mock_add_message_received_callback( char *service_name,
69
+ void ( *callback )( uint16_t tag, void *data, size_t len ) );
70
+
71
+ #ifdef add_message_replied_callback
72
+ #undef add_message_replied_callback
73
+ #endif
74
+ #define add_message_replied_callback mock_add_message_replied_callback
75
+ bool mock_add_message_replied_callback( char *service_name,
76
+ void ( *callback )( uint16_t tag, void *data, size_t len, void *yser_data ) );
77
+
78
+ #ifdef delete_message_received_callback
79
+ #undef delete_message_received_callback
80
+ #endif
81
+ #define delete_message_received_callback mock_delete_message_received_callback
82
+ bool mock_delete_message_received_callback( char *service_name,
83
+ void ( *callback )( uint16_t tag, void *data, size_t len ) );
84
+
85
+ #ifdef delete_message_replied_callback
86
+ #undef delete_message_replied_callback
87
+ #endif
88
+ #define delete_message_replied_callback mock_delete_message_replied_callback
89
+ bool mock_delete_message_replied_callback( char *service_name,
90
+ void ( *callback )( uint16_t tag, void *data, size_t len, void *user_data ) );
91
+
92
+ #ifdef getpid
93
+ #undef getpid
94
+ #endif
95
+ #define getpid mock_getpid
96
+ pid_t mock_getpid( void );
97
+
98
+ #ifdef parse_packet
99
+ #undef parse_packet
100
+ #endif
101
+ #define parse_packet mock_parse_packet
102
+ bool mock_parse_packet( buffer *buf );
103
+
104
+ #ifdef die
105
+ #undef die
106
+ #endif
107
+ #define die mock_die
108
+ void mock_die( const char *format, ... );
109
+
110
+ #ifdef debug
111
+ #undef debug
112
+ #endif
113
+ #define debug mock_debug
114
+ extern void mock_debug( const char *format, ... );
115
+
116
+ #ifdef info
117
+ #undef info
118
+ #endif
119
+ #define info mock_info
120
+ extern void mock_info( const char *format, ... );
121
+
122
+ #ifdef warn
123
+ #undef warn
124
+ #endif
125
+ #define warn mock_warn
126
+ extern void mock_warn( const char *format, ... );
127
+
128
+ #ifdef error
129
+ #undef error
130
+ #endif
131
+ #define error mock_error
132
+ extern void mock_error( const char *format, ... );
133
+
134
+ #ifdef critical
135
+ #undef critical
136
+ #endif
137
+ #define critical mock_critical
138
+ extern void mock_critical( const char *format, ... );
139
+
140
+ #endif // UNIT_TESTING
141
+
142
+ static bool openflow_application_interface_initialized = false;
143
+ static openflow_event_handlers_t event_handlers;
144
+ static char service_name[ MESSENGER_SERVICE_NAME_LENGTH ];
145
+
146
+
147
+ static void handle_message( uint16_t message_type, void *data, size_t length );
148
+ static void handle_list_switches_reply( uint16_t message_type, void *dpid, size_t length, void *user_data );
149
+
150
+
151
+ enum {
152
+ OPENFLOW_MESSAGE_SEND = 0,
153
+ OPENFLOW_MESSAGE_RECEIVE,
154
+ };
155
+
156
+
157
+ bool
158
+ openflow_application_interface_is_initialized() {
159
+ return openflow_application_interface_initialized;
160
+ }
161
+
162
+
163
+ static bool
164
+ maybe_init_openflow_application_interface() {
165
+ if ( !openflow_application_interface_is_initialized() ) {
166
+ debug( "OpenFlow Application Interface is not initialized yet. Initializing..." );
167
+ return init_openflow_application_interface( get_trema_name() );
168
+ }
169
+ return true;
170
+ }
171
+
172
+
173
+ bool
174
+ init_openflow_application_interface( const char *custom_service_name ) {
175
+ assert( custom_service_name != NULL );
176
+
177
+ debug( "Initializing OpenFlow Application Interface." );
178
+
179
+ if ( openflow_application_interface_is_initialized() ) {
180
+ error( "OpenFlow Application Interface is already initialized." );
181
+ return false;
182
+ }
183
+
184
+ memset( &event_handlers, 0, sizeof( openflow_event_handlers_t ) );
185
+ memset( service_name, '\0', sizeof( service_name ) );
186
+
187
+ size_t length = strlen( custom_service_name ) + 1;
188
+ if ( length > MESSENGER_SERVICE_NAME_LENGTH ) {
189
+ error( "Too long custom service name ( %s ).", custom_service_name );
190
+ return false;
191
+ }
192
+ assert( length <= sizeof( service_name ) );
193
+ memcpy( service_name, custom_service_name, length );
194
+
195
+ init_openflow_message();
196
+
197
+ add_message_received_callback( service_name, handle_message );
198
+ add_message_replied_callback( service_name, handle_list_switches_reply );
199
+
200
+ openflow_application_interface_initialized = true;
201
+
202
+ return true;
203
+ }
204
+
205
+
206
+ bool
207
+ finalize_openflow_application_interface() {
208
+ debug( "Finalizing OpenFlow Application Interface." );
209
+
210
+ assert( openflow_application_interface_initialized );
211
+
212
+ delete_message_received_callback( service_name, handle_message );
213
+ delete_message_replied_callback( service_name, handle_list_switches_reply );
214
+
215
+ memset( &event_handlers, 0, sizeof( openflow_event_handlers_t ) );
216
+ memset( service_name, '\0', sizeof( service_name ) );
217
+
218
+ openflow_application_interface_initialized = false;
219
+
220
+ return true;
221
+ }
222
+
223
+
224
+ bool
225
+ set_openflow_event_handlers( const openflow_event_handlers_t handlers ) {
226
+ maybe_init_openflow_application_interface();
227
+ assert( openflow_application_interface_initialized );
228
+
229
+ memcpy( &event_handlers, &handlers, sizeof( event_handlers ) );
230
+
231
+ return true;
232
+ }
233
+
234
+
235
+ bool
236
+ _set_switch_ready_handler( bool simple_callback, void *callback, void *user_data ) {
237
+ if ( callback == NULL ) {
238
+ die( "Invalid callback function for switch_ready event." );
239
+ }
240
+ assert( callback != NULL );
241
+
242
+ maybe_init_openflow_application_interface();
243
+ assert( openflow_application_interface_initialized );
244
+
245
+ debug( "Setting a switch ready handler ( callback = %p, user_data = %p ).",
246
+ callback, user_data );
247
+
248
+ event_handlers.simple_switch_ready_callback = simple_callback;
249
+ event_handlers.switch_ready_callback = callback;
250
+ event_handlers.switch_ready_user_data = user_data;
251
+
252
+ return true;
253
+ }
254
+
255
+
256
+ bool
257
+ set_switch_disconnected_handler( switch_disconnected_handler callback, void *user_data ) {
258
+ if ( callback == NULL ) {
259
+ die( "Callback function ( switch_disconnected_handler ) must not be NULL." );
260
+ }
261
+ assert( callback != NULL );
262
+
263
+ maybe_init_openflow_application_interface();
264
+ assert( openflow_application_interface_initialized );
265
+
266
+ debug( "Setting a switch disconnected handler ( callback = %p, user_data = %p ).",
267
+ callback, user_data );
268
+
269
+ event_handlers.switch_disconnected_callback = callback;
270
+ event_handlers.switch_disconnected_user_data = user_data;
271
+
272
+ return true;
273
+ }
274
+
275
+
276
+ bool
277
+ set_error_handler( error_handler callback, void *user_data ) {
278
+ if ( callback == NULL ) {
279
+ die( "Callback function ( error_handler ) must not be NULL." );
280
+ }
281
+ assert( callback != NULL );
282
+
283
+ maybe_init_openflow_application_interface();
284
+ assert( openflow_application_interface_initialized );
285
+
286
+ debug( "Setting an error handler ( callback = %p, user_data = %p ).",
287
+ callback, user_data );
288
+
289
+ event_handlers.error_callback = callback;
290
+ event_handlers.error_user_data = user_data;
291
+
292
+ return true;
293
+ }
294
+
295
+
296
+ bool
297
+ set_vendor_handler( vendor_handler callback, void *user_data ) {
298
+ if ( callback == NULL ) {
299
+ die( "Callback function ( vendor_handler ) must not be NULL." );
300
+ }
301
+ assert( callback != NULL );
302
+
303
+ maybe_init_openflow_application_interface();
304
+ assert( openflow_application_interface_initialized );
305
+
306
+ debug( "Setting a vendor handler ( callback = %p, user_data = %p ).",
307
+ callback, user_data );
308
+
309
+ event_handlers.vendor_callback = callback;
310
+ event_handlers.vendor_user_data = user_data;
311
+
312
+ return true;
313
+ }
314
+
315
+
316
+ bool
317
+ set_features_reply_handler( features_reply_handler callback, void *user_data ) {
318
+ if ( callback == NULL ) {
319
+ die( "Callback function ( features_reply_handler ) must not be NULL." );
320
+ }
321
+ assert( callback != NULL );
322
+
323
+ maybe_init_openflow_application_interface();
324
+ assert( openflow_application_interface_initialized );
325
+
326
+ debug( "Setting a features reply handler ( callback = %p, user_data = %p ).",
327
+ callback, user_data );
328
+
329
+ event_handlers.features_reply_callback = callback;
330
+ event_handlers.features_reply_user_data = user_data;
331
+
332
+ return true;
333
+ }
334
+
335
+
336
+ bool
337
+ set_get_config_reply_handler( get_config_reply_handler callback, void *user_data ) {
338
+ if ( callback == NULL ) {
339
+ die( "Callback function ( get_config_reply_handler ) must not be NULL." );
340
+ }
341
+ assert( callback != NULL );
342
+
343
+ maybe_init_openflow_application_interface();
344
+ assert( openflow_application_interface_initialized );
345
+
346
+ debug( "Setting a get config reply handler ( callback = %p, user_data = %p ).",
347
+ callback, user_data );
348
+
349
+ event_handlers.get_config_reply_callback = callback;
350
+ event_handlers.get_config_reply_user_data = user_data;
351
+
352
+ return true;
353
+ }
354
+
355
+
356
+ bool
357
+ _set_packet_in_handler( bool simple_callback, void *callback, void *user_data ) {
358
+ if ( callback == NULL ) {
359
+ die( "Callback function (packet_in_handler) must not be NULL." );
360
+ }
361
+ assert( callback != NULL );
362
+
363
+ maybe_init_openflow_application_interface();
364
+ assert( openflow_application_interface_initialized );
365
+
366
+ debug( "Setting a packet-in handler (callback = %p, user_data = %p).", callback, user_data );
367
+
368
+ event_handlers.simple_packet_in_callback = simple_callback;
369
+ event_handlers.packet_in_callback = callback;
370
+ event_handlers.packet_in_user_data = user_data;
371
+
372
+ return true;
373
+ }
374
+
375
+
376
+ bool
377
+ _set_flow_removed_handler( bool simple_callback, void *callback, void *user_data ) {
378
+ if ( callback == NULL ) {
379
+ die( "Callback function (flow_removed_handler) must not be NULL." );
380
+ }
381
+ assert( callback != NULL );
382
+
383
+ maybe_init_openflow_application_interface();
384
+ assert( openflow_application_interface_initialized );
385
+
386
+ debug( "Setting a flow removed handler (callback = %p, user_data = %p).", callback, user_data );
387
+
388
+ event_handlers.simple_flow_removed_callback = simple_callback;
389
+ event_handlers.flow_removed_callback = callback;
390
+ event_handlers.flow_removed_user_data = user_data;
391
+
392
+ return true;
393
+ }
394
+
395
+
396
+ bool
397
+ set_port_status_handler( port_status_handler callback, void *user_data ) {
398
+ if ( callback == NULL ) {
399
+ die( "Callback function ( port_status_handler ) must not be NULL." );
400
+ }
401
+ assert( callback != NULL );
402
+
403
+ maybe_init_openflow_application_interface();
404
+ assert( openflow_application_interface_initialized );
405
+
406
+ debug( "Setting a port status handler ( callback = %p, user_data = %p ).",
407
+ callback, user_data );
408
+
409
+ event_handlers.port_status_callback = callback;
410
+ event_handlers.port_status_user_data = user_data;
411
+
412
+ return true;
413
+ }
414
+
415
+
416
+ bool
417
+ set_stats_reply_handler( stats_reply_handler callback, void *user_data ) {
418
+ if ( callback == NULL ) {
419
+ die( "Callback function ( stats_reply_handler ) must not be NULL." );
420
+ }
421
+ assert( callback != NULL );
422
+
423
+ maybe_init_openflow_application_interface();
424
+ assert( openflow_application_interface_initialized );
425
+
426
+ debug( "Setting a stats reply handler ( callback = %p, user_data = %p ).",
427
+ callback, user_data );
428
+
429
+ event_handlers.stats_reply_callback = callback;
430
+ event_handlers.stats_reply_user_data = user_data;
431
+
432
+ return true;
433
+ }
434
+
435
+
436
+ bool
437
+ set_barrier_reply_handler( barrier_reply_handler callback, void *user_data ) {
438
+ if ( callback == NULL ) {
439
+ die( "Callback function ( barrier_reply_handler ) must not be NULL." );
440
+ }
441
+ assert( callback != NULL );
442
+
443
+ maybe_init_openflow_application_interface();
444
+ assert( openflow_application_interface_initialized );
445
+
446
+ debug( "Setting a barrier reply handler ( callback = %p, user_data = %p ).",
447
+ callback, user_data );
448
+
449
+ event_handlers.barrier_reply_callback = callback;
450
+ event_handlers.barrier_reply_user_data = user_data;
451
+
452
+ return true;
453
+ }
454
+
455
+
456
+ bool
457
+ set_queue_get_config_reply_handler( queue_get_config_reply_handler callback, void *user_data ) {
458
+ if ( callback == NULL ) {
459
+ die( "Callback function ( queue_get_config_reply_handler ) must not be NULL." );
460
+ }
461
+ assert( callback != NULL );
462
+
463
+ maybe_init_openflow_application_interface();
464
+ assert( openflow_application_interface_initialized );
465
+
466
+ debug( "Setting a queue get config reply handler ( callback = %p, user_data = %p ).",
467
+ callback, user_data );
468
+
469
+ event_handlers.queue_get_config_reply_callback = callback;
470
+ event_handlers.queue_get_config_reply_user_data = user_data;
471
+
472
+ return true;
473
+ }
474
+
475
+
476
+ bool
477
+ set_list_switches_reply_handler( list_switches_reply_handler callback ) {
478
+ if ( callback == NULL ) {
479
+ die( "Callback function ( list_switches_reply_handler ) must not be NULL." );
480
+ }
481
+ assert( callback != NULL );
482
+
483
+ maybe_init_openflow_application_interface();
484
+ assert( openflow_application_interface_initialized );
485
+
486
+ debug( "Setting a list switches reply handler ( callback = %p ).", callback );
487
+
488
+ event_handlers.list_switches_reply_callback = callback;
489
+
490
+ return true;
491
+ }
492
+
493
+
494
+ static void
495
+ handle_error( const uint64_t datapath_id, buffer *data ) {
496
+ uint16_t type, code;
497
+ uint32_t transaction_id;
498
+ buffer *body;
499
+ struct ofp_error_msg *error_msg;
500
+
501
+ if ( ( data == NULL ) || ( ( data != NULL ) && ( data->length == 0 ) ) ) {
502
+ critical( "An OpenFlow message must be filled before calling handle_error()." );
503
+ assert( 0 );
504
+ }
505
+
506
+ error_msg = ( struct ofp_error_msg * ) data->data;
507
+
508
+ transaction_id = ntohl( error_msg->header.xid );
509
+ type = ntohs( error_msg->type );
510
+ code = ntohs( error_msg->code );
511
+
512
+ body = duplicate_buffer( data );
513
+ remove_front_buffer( body, offsetof( struct ofp_error_msg, data ) );
514
+
515
+ debug( "An error message is received from %#lx "
516
+ "( transaction_id = %#x, type = %u, code = %u, data length = %u ).",
517
+ datapath_id, transaction_id, type, code, body->length );
518
+
519
+ if ( event_handlers.error_callback == NULL ) {
520
+ debug( "Callback function for error events is not set." );
521
+ free_buffer( body );
522
+ return;
523
+ }
524
+
525
+ debug( "Calling error handler ( callback = %p, user_data = %p ).",
526
+ event_handlers.error_callback, event_handlers.error_user_data );
527
+
528
+ event_handlers.error_callback( datapath_id,
529
+ transaction_id,
530
+ type,
531
+ code,
532
+ body,
533
+ event_handlers.error_user_data );
534
+
535
+ free_buffer( body );
536
+ }
537
+
538
+
539
+ static void
540
+ handle_vendor( const uint64_t datapath_id, buffer *data ) {
541
+ uint16_t body_length;
542
+ uint32_t vendor, transaction_id;
543
+ buffer *body;
544
+ struct ofp_vendor_header *vendor_header;
545
+
546
+ if ( ( data == NULL ) || ( ( data != NULL ) && ( data->length == 0 ) ) ) {
547
+ critical( "An OpenFlow message must be filled before calling handle_vendor()." );
548
+ assert( 0 );
549
+ }
550
+
551
+ vendor_header = ( struct ofp_vendor_header * ) data->data;
552
+
553
+ transaction_id = ntohl( vendor_header->header.xid );
554
+ vendor = ntohl( vendor_header->vendor );
555
+
556
+ body_length = ( uint16_t ) ( ntohs( vendor_header->header.length )
557
+ - sizeof( struct ofp_vendor_header ) );
558
+
559
+ debug( "A vendor message is received from %#" PRIx64
560
+ " ( transaction_id = %#x, vendor = %#x, body length = %u ).",
561
+ datapath_id, transaction_id, vendor, body_length );
562
+
563
+ if ( event_handlers.vendor_callback == NULL ) {
564
+ debug( "Callback function for vendor events is not set." );
565
+ return;
566
+ }
567
+
568
+ if ( body_length > 0 ) {
569
+ body = duplicate_buffer( data );
570
+ remove_front_buffer( body, sizeof( struct ofp_vendor_header ) );
571
+ }
572
+ else {
573
+ body = NULL;
574
+ }
575
+
576
+ debug( "Calling vendor handler ( callback = %p, user_data = %p ).",
577
+ event_handlers.vendor_callback, event_handlers.vendor_user_data );
578
+
579
+ event_handlers.vendor_callback( datapath_id,
580
+ transaction_id,
581
+ vendor,
582
+ body,
583
+ event_handlers.vendor_user_data );
584
+
585
+ if ( body != NULL ) {
586
+ free_buffer( body );
587
+ }
588
+ }
589
+
590
+
591
+ static void
592
+ handle_features_reply( const uint64_t datapath_id, buffer *data ) {
593
+ char description[ 1024 ];
594
+ int i, n_phy_ports;
595
+ uint8_t n_tables;
596
+ uint16_t phy_ports_length;
597
+ uint32_t transaction_id, n_buffers, capabilities, actions;
598
+ list_element *element, *phy_ports_head;
599
+ struct ofp_phy_port *p, *phy_port;
600
+ struct ofp_switch_features *switch_features;
601
+
602
+ if ( ( data == NULL ) || ( ( data != NULL ) && ( data->length == 0 ) ) ) {
603
+ critical( "An OpenFlow message must be filled before calling handle_features_reply()." );
604
+ assert( 0 );
605
+ }
606
+
607
+ switch_features = ( struct ofp_switch_features * ) data->data;
608
+
609
+ transaction_id = ntohl( switch_features->header.xid );
610
+ n_buffers = ntohl( switch_features->n_buffers );
611
+ n_tables = switch_features->n_tables;
612
+ capabilities = ntohl( switch_features->capabilities );
613
+ actions = ntohl( switch_features->actions );
614
+
615
+ phy_ports_length = ( uint16_t ) ( ntohs( switch_features->header.length )
616
+ - offsetof( struct ofp_switch_features, ports ) );
617
+
618
+ n_phy_ports = phy_ports_length / sizeof( struct ofp_phy_port );
619
+
620
+ debug( "A features reply message is received from %#" PRIx64
621
+ " ( transaction_id = %#x, n_buffers = %u, n_tables = %u, "
622
+ "capabilities = %#x, actions = %#x, # of phy ports = %u ).",
623
+ datapath_id, transaction_id, n_buffers, n_tables,
624
+ capabilities, actions, n_phy_ports );
625
+
626
+ if ( n_phy_ports > 0 ) {
627
+ create_list( &phy_ports_head );
628
+ phy_port = ( struct ofp_phy_port * ) switch_features->ports;
629
+ for ( i = 0; i < n_phy_ports; i++ ) {
630
+ p = ( struct ofp_phy_port * ) xcalloc( 1, sizeof( struct ofp_phy_port ) );
631
+ ntoh_phy_port( p, phy_port );
632
+ append_to_tail( &phy_ports_head, ( void * ) p );
633
+ phy_port_to_string( p, description, sizeof( description ) );
634
+ debug( "[%u] %s", phy_port, description );
635
+ phy_port++;
636
+ }
637
+ }
638
+ else {
639
+ phy_ports_head = NULL;
640
+ }
641
+
642
+ if ( event_handlers.features_reply_callback == NULL ) {
643
+ debug( "Callback function for features reply events is not set." );
644
+ if( phy_ports_head != NULL ) {
645
+ element = phy_ports_head;
646
+ while ( element != NULL ) {
647
+ xfree( element->data );
648
+ element = element->next;
649
+ }
650
+ delete_list( phy_ports_head );
651
+ }
652
+ return;
653
+ }
654
+
655
+ debug( "Calling features reply handler ( callback = %p, user_data = %p ).",
656
+ event_handlers.features_reply_callback, event_handlers.features_reply_user_data );
657
+
658
+ event_handlers.features_reply_callback( datapath_id,
659
+ transaction_id,
660
+ n_buffers,
661
+ n_tables,
662
+ capabilities,
663
+ actions,
664
+ phy_ports_head,
665
+ event_handlers.features_reply_user_data );
666
+
667
+ if ( phy_ports_head != NULL ) {
668
+ element = phy_ports_head;
669
+ while ( element != NULL ) {
670
+ xfree( element->data );
671
+ element = element->next;
672
+ }
673
+ delete_list( phy_ports_head );
674
+ }
675
+ }
676
+
677
+
678
+ static void
679
+ handle_get_config_reply( const uint64_t datapath_id, buffer *data ) {
680
+ uint16_t flags, miss_send_len;
681
+ uint32_t transaction_id;
682
+ struct ofp_switch_config *switch_config;
683
+
684
+ if ( ( data == NULL ) || ( ( data != NULL ) && ( data->length == 0 ) ) ) {
685
+ critical( "An OpenFlow message must be filled before calling handle_get_config_reply()." );
686
+ assert( 0 );
687
+ }
688
+
689
+ switch_config = ( struct ofp_switch_config * ) data->data;
690
+
691
+ transaction_id = ntohl( switch_config->header.xid );
692
+ flags = ntohs( switch_config->flags );
693
+ miss_send_len = ntohs( switch_config->miss_send_len );
694
+
695
+ debug( "A get config reply message is received from %#" PRIx64
696
+ " ( transaction_id = %#x, flags = %#x, miss_send_len = %u ).",
697
+ datapath_id, transaction_id, flags, miss_send_len );
698
+
699
+ if ( event_handlers.get_config_reply_callback == NULL ) {
700
+ debug( "Callback function for get config reply events is not set." );
701
+ return;
702
+ }
703
+
704
+ debug( "Calling get config reply handler ( callback = %p, user_data = %p ).",
705
+ event_handlers.get_config_reply_callback, event_handlers.get_config_reply_user_data );
706
+
707
+ event_handlers.get_config_reply_callback( datapath_id,
708
+ transaction_id,
709
+ flags,
710
+ miss_send_len,
711
+ event_handlers.get_config_reply_user_data );
712
+ }
713
+
714
+
715
+ static bool
716
+ empty( const buffer *data ) {
717
+ return ( data == NULL ) || ( ( data != NULL ) && ( data->length == 0 ) );
718
+ }
719
+
720
+
721
+ static void
722
+ handle_packet_in( const uint64_t datapath_id, buffer *data ) {
723
+ if ( empty( data ) ) {
724
+ die( "handle_packet_in(): packet_in message should not be empty." );
725
+ }
726
+
727
+ struct ofp_packet_in *_packet_in = ( struct ofp_packet_in * ) data->data;
728
+ uint32_t transaction_id = ntohl( _packet_in->header.xid );
729
+ uint32_t buffer_id = ntohl( _packet_in->buffer_id );
730
+ uint16_t total_len = ntohs( _packet_in->total_len );
731
+ uint16_t in_port = ntohs( _packet_in->in_port );
732
+ uint8_t reason = _packet_in->reason;
733
+ uint16_t body_length = ( uint16_t ) ( ntohs( _packet_in->header.length ) - offsetof( struct ofp_packet_in, data ) );
734
+
735
+ debug(
736
+ "A packet_in message is received from %#" PRIx64
737
+ " (transaction_id = %#x, buffer_id = %#x, total_len = %u, in_port = %u, reason = %#x, body length = %u).",
738
+ datapath_id,
739
+ transaction_id,
740
+ buffer_id,
741
+ total_len,
742
+ in_port,
743
+ reason,
744
+ body_length
745
+ );
746
+
747
+ if ( event_handlers.packet_in_callback == NULL ) {
748
+ debug( "Callback function for packet_in events is not set." );
749
+ return;
750
+ }
751
+
752
+ buffer *body = NULL;
753
+ if ( body_length > 0 ) {
754
+ body = duplicate_buffer( data );
755
+ remove_front_buffer( body, offsetof( struct ofp_packet_in, data ) );
756
+ bool parse_ok = parse_packet( body );
757
+ if ( !parse_ok ) {
758
+ error( "Failed to parse a packet." );
759
+ // ???: Is it OK to drop malformed packets?
760
+ free_buffer( body );
761
+ return;
762
+ }
763
+ }
764
+ else {
765
+ body = NULL;
766
+ }
767
+
768
+ assert( event_handlers.packet_in_callback != NULL );
769
+ debug( "Calling packet_in handler (callback = %p, user_data = %p).",
770
+ event_handlers.packet_in_callback,
771
+ event_handlers.packet_in_user_data
772
+ );
773
+ if ( event_handlers.simple_packet_in_callback ) {
774
+ packet_in message = {
775
+ datapath_id,
776
+ transaction_id,
777
+ buffer_id,
778
+ total_len,
779
+ in_port,
780
+ reason,
781
+ body,
782
+ event_handlers.packet_in_user_data
783
+ };
784
+ ( ( simple_packet_in_handler * ) event_handlers.packet_in_callback )( datapath_id, message );
785
+ }
786
+ else {
787
+ ( ( packet_in_handler * ) event_handlers.packet_in_callback )(
788
+ datapath_id,
789
+ transaction_id,
790
+ buffer_id,
791
+ total_len,
792
+ in_port,
793
+ reason,
794
+ body,
795
+ event_handlers.packet_in_user_data
796
+ );
797
+ }
798
+
799
+ if ( body != NULL ) {
800
+ free_buffer( body );
801
+ }
802
+ }
803
+
804
+
805
+ static void
806
+ handle_flow_removed( const uint64_t datapath_id, buffer *data ) {
807
+ if ( ( data == NULL ) || ( ( data != NULL ) && ( data->length == 0 ) ) ) {
808
+ critical( "An OpenFlow message must be filled before calling handle_flow_removed()." );
809
+ assert( 0 );
810
+ }
811
+
812
+ struct ofp_flow_removed *_flow_removed = ( struct ofp_flow_removed * ) data->data;
813
+ uint32_t transaction_id = ntohl( _flow_removed->header.xid );
814
+ struct ofp_match match;
815
+ ntoh_match( &match, &_flow_removed->match );
816
+ uint64_t cookie = ntohll( _flow_removed->cookie );
817
+ uint16_t priority = ntohs( _flow_removed->priority );
818
+ uint8_t reason = _flow_removed->reason;
819
+ uint32_t duration_sec = ntohl( _flow_removed->duration_sec );
820
+ uint32_t duration_nsec = ntohl( _flow_removed->duration_nsec );
821
+ uint16_t idle_timeout = ntohs( _flow_removed->idle_timeout );
822
+ uint64_t packet_count = ntohll( _flow_removed->packet_count );
823
+ uint64_t byte_count = ntohll( _flow_removed->byte_count );
824
+
825
+ char match_string[ 1024 ];
826
+ match_to_string( &match, match_string, sizeof( match_string ) );
827
+
828
+ debug(
829
+ "A flow removed message is received from %#" PRIx64
830
+ " ( transaction_id = %#x, match = [%s], cookie = %#" PRIx64 ", "
831
+ "priority = %u, reason = %#x, duration_sec = %u, duration_nsec = %u, "
832
+ "idle_timeout = %u, packet_count = %" PRIu64 ", byte_count = %" PRIu64 " ).",
833
+ datapath_id,
834
+ transaction_id,
835
+ match_string,
836
+ cookie,
837
+ priority,
838
+ reason,
839
+ duration_sec,
840
+ duration_nsec,
841
+ idle_timeout,
842
+ packet_count,
843
+ byte_count
844
+ );
845
+
846
+ if ( event_handlers.flow_removed_callback == NULL ) {
847
+ debug( "Callback function for flow removed events is not set." );
848
+ return;
849
+ }
850
+
851
+ debug(
852
+ "Calling flow removed handler (callback = %p, user_data = %p).",
853
+ event_handlers.flow_removed_callback,
854
+ event_handlers.flow_removed_user_data
855
+ );
856
+ if ( event_handlers.simple_flow_removed_callback ) {
857
+ flow_removed message = {
858
+ datapath_id,
859
+ transaction_id,
860
+ match,
861
+ cookie,
862
+ priority,
863
+ reason,
864
+ duration_sec,
865
+ duration_nsec,
866
+ idle_timeout,
867
+ packet_count,
868
+ byte_count,
869
+ event_handlers.flow_removed_user_data
870
+ };
871
+ ( ( simple_flow_removed_handler * ) event_handlers.flow_removed_callback )( datapath_id, message );
872
+ }
873
+ else {
874
+ ( ( flow_removed_handler * ) event_handlers.flow_removed_callback )(
875
+ datapath_id,
876
+ transaction_id,
877
+ match,
878
+ cookie,
879
+ priority,
880
+ reason,
881
+ duration_sec,
882
+ duration_nsec,
883
+ idle_timeout,
884
+ packet_count,
885
+ byte_count,
886
+ event_handlers.flow_removed_user_data
887
+ );
888
+ }
889
+ }
890
+
891
+
892
+ static void
893
+ handle_port_status( const uint64_t datapath_id, buffer *data ) {
894
+ char description[ 1024 ];
895
+ uint8_t reason;
896
+ uint32_t transaction_id;
897
+ struct ofp_phy_port phy_port;
898
+ struct ofp_port_status *port_status;
899
+
900
+ if ( ( data == NULL ) || ( ( data != NULL ) && ( data->length == 0 ) ) ) {
901
+ critical( "An OpenFlow message must be filled before calling handle_port_status()." );
902
+ assert( 0 );
903
+ }
904
+
905
+ port_status = ( struct ofp_port_status * ) data->data;
906
+
907
+ transaction_id = ntohl( port_status->header.xid );
908
+ reason = port_status->reason;
909
+ ntoh_phy_port( &phy_port, &port_status->desc );
910
+
911
+ phy_port_to_string( &phy_port, description, sizeof( description ) );
912
+
913
+ debug( "A port status message is received from %#" PRIx64
914
+ " ( transaction_id = %#x, reason = %#x, desc = [%s] ).",
915
+ datapath_id, transaction_id, reason, description );
916
+
917
+ if ( event_handlers.port_status_callback == NULL ) {
918
+ debug( "Callback function for port status events is not set." );
919
+ return;
920
+ }
921
+
922
+ debug( "Calling port status handler ( callback = %p, user_data = %p ).",
923
+ event_handlers.port_status_callback, event_handlers.port_status_user_data );
924
+
925
+ event_handlers.port_status_callback( datapath_id,
926
+ transaction_id,
927
+ reason,
928
+ phy_port,
929
+ event_handlers.port_status_user_data );
930
+ }
931
+
932
+
933
+ static void
934
+ handle_stats_reply( const uint64_t datapath_id, buffer *data ) {
935
+ uint16_t type, flags, body_length;
936
+ uint32_t transaction_id;
937
+ buffer *body = NULL;
938
+ buffer *body_h = NULL;
939
+ struct ofp_stats_reply *stats_reply;
940
+
941
+ if ( ( data == NULL ) || ( ( data != NULL ) && ( data->length == 0 ) ) ) {
942
+ critical( "An OpenFlow message must be filled before calling handle_stats_reply()." );
943
+ assert( 0 );
944
+ }
945
+
946
+ stats_reply = ( struct ofp_stats_reply * ) data->data;
947
+
948
+ transaction_id = ntohl( stats_reply->header.xid );
949
+ type = ntohs( stats_reply->type );
950
+ flags = ntohs( stats_reply->flags );
951
+
952
+ body_length = ( uint16_t ) ( ntohs( stats_reply->header.length )
953
+ - offsetof( struct ofp_stats_reply, body ) );
954
+
955
+ debug( "A stats reply message is received from %#" PRIx64
956
+ " ( transaction_id = %#x, type = %#x, flags = %#x, body length = %u ).",
957
+ datapath_id, transaction_id, type, flags, body_length );
958
+
959
+ if ( event_handlers.stats_reply_callback == NULL ) {
960
+ debug( "Callback function for stats reply events is not set." );
961
+ return;
962
+ }
963
+
964
+ if ( body_length > 0 ) {
965
+ body = duplicate_buffer( data );
966
+ remove_front_buffer( body, offsetof( struct ofp_stats_reply, body ) );
967
+ }
968
+
969
+ if ( body != NULL ) {
970
+ switch ( type ) {
971
+ case OFPST_DESC:
972
+ {
973
+ body_h = body;
974
+ body = NULL;
975
+ }
976
+ break;
977
+ case OFPST_FLOW:
978
+ {
979
+ struct ofp_flow_stats *src, *dst;
980
+
981
+ body_h = alloc_buffer_with_length( body_length );
982
+ append_back_buffer( body_h, body_length );
983
+
984
+ src = ( struct ofp_flow_stats * ) body->data;
985
+ dst = ( struct ofp_flow_stats * ) body_h->data;
986
+
987
+ while ( body_length > 0 ) {
988
+ ntoh_flow_stats( dst, src );
989
+
990
+ body_length = ( uint16_t ) ( body_length - dst->length );
991
+
992
+ src = ( struct ofp_flow_stats * ) ( ( char * ) src + dst->length );
993
+ dst = ( struct ofp_flow_stats * ) ( ( char * ) dst + dst->length );
994
+ }
995
+ }
996
+ break;
997
+ case OFPST_AGGREGATE:
998
+ {
999
+ struct ofp_aggregate_stats_reply *src, *dst;
1000
+
1001
+ body_h = alloc_buffer_with_length( body_length );
1002
+ append_back_buffer( body_h, body_length );
1003
+
1004
+ src = ( struct ofp_aggregate_stats_reply * ) body->data;
1005
+ dst = ( struct ofp_aggregate_stats_reply * ) body_h->data;
1006
+
1007
+ ntoh_aggregate_stats( dst, src );
1008
+ }
1009
+ break;
1010
+ case OFPST_TABLE:
1011
+ {
1012
+ struct ofp_table_stats *src, *dst;
1013
+
1014
+ body_h = alloc_buffer_with_length( body_length );
1015
+ append_back_buffer( body_h, body_length );
1016
+
1017
+ src = ( struct ofp_table_stats * ) body->data;
1018
+ dst = ( struct ofp_table_stats * ) body_h->data;
1019
+
1020
+ while ( body_length > 0 ) {
1021
+ ntoh_table_stats( dst, src );
1022
+
1023
+ body_length = ( uint16_t ) ( body_length - sizeof( struct ofp_table_stats ) );
1024
+
1025
+ src++;
1026
+ dst++;
1027
+ }
1028
+ }
1029
+ break;
1030
+ case OFPST_PORT:
1031
+ {
1032
+ struct ofp_port_stats *src, *dst;
1033
+
1034
+ body_h = alloc_buffer_with_length( body_length );
1035
+ append_back_buffer( body_h, body_length );
1036
+
1037
+ src = ( struct ofp_port_stats * ) body->data;
1038
+ dst = ( struct ofp_port_stats * ) body_h->data;
1039
+
1040
+ while ( body_length > 0 ) {
1041
+ ntoh_port_stats( dst, src );
1042
+
1043
+ body_length = ( uint16_t ) ( body_length - sizeof( struct ofp_port_stats ) );
1044
+
1045
+ src++;
1046
+ dst++;
1047
+ }
1048
+ }
1049
+ break;
1050
+ case OFPST_QUEUE:
1051
+ {
1052
+ struct ofp_queue_stats *src, *dst;
1053
+
1054
+ body_h = alloc_buffer_with_length( body_length );
1055
+ append_back_buffer( body_h, body_length );
1056
+
1057
+ src = ( struct ofp_queue_stats * ) body->data;
1058
+ dst = ( struct ofp_queue_stats * ) body_h->data;
1059
+
1060
+ while ( body_length > 0 ) {
1061
+ ntoh_queue_stats( dst, src );
1062
+
1063
+ body_length = ( uint16_t ) ( body_length - sizeof( struct ofp_queue_stats ) );
1064
+
1065
+ src++;
1066
+ dst++;
1067
+ }
1068
+ }
1069
+ break;
1070
+ case OFPST_VENDOR:
1071
+ {
1072
+ uint32_t *src, *dst;
1073
+ body_h = alloc_buffer_with_length( body_length );
1074
+ append_back_buffer( body_h, body_length );
1075
+
1076
+ memcpy( body_h->data, body->data, body_length );
1077
+
1078
+ src = ( uint32_t * ) body->data;
1079
+ dst = ( uint32_t * ) body_h->data;
1080
+
1081
+ *dst = ntohl( *src ); // vendor id
1082
+ }
1083
+ break;
1084
+ default:
1085
+ if ( body != NULL ) {
1086
+ free_buffer( body );
1087
+ }
1088
+ critical( "Unhandled stats type ( type = %u ).", type );
1089
+ assert( 0 );
1090
+ break;
1091
+ }
1092
+ }
1093
+
1094
+ debug( "Calling stats reply handler ( callback = %p, user_data = %p ).",
1095
+ event_handlers.stats_reply_callback, event_handlers.stats_reply_user_data );
1096
+
1097
+ event_handlers.stats_reply_callback( datapath_id,
1098
+ transaction_id,
1099
+ type,
1100
+ flags,
1101
+ body_h,
1102
+ event_handlers.stats_reply_user_data );
1103
+
1104
+ if ( body != NULL ) {
1105
+ free_buffer( body );
1106
+ }
1107
+ if ( body_h != NULL ) {
1108
+ free_buffer( body_h );
1109
+ }
1110
+ }
1111
+
1112
+
1113
+ static void
1114
+ handle_barrier_reply( const uint64_t datapath_id, buffer *data ) {
1115
+ uint32_t transaction_id;
1116
+ struct ofp_header *header;
1117
+
1118
+ if ( ( data == NULL ) || ( ( data != NULL ) && ( data->length == 0 ) ) ) {
1119
+ critical( "An OpenFlow message must be filled before calling handle_barrier_reply()." );
1120
+ assert( 0 );
1121
+ }
1122
+
1123
+ header = ( struct ofp_header * ) data->data;
1124
+
1125
+ transaction_id = ntohl( header->xid );
1126
+
1127
+ debug( "A barrier reply message is received from %#" PRIx64 " ( transaction_id = %#x ).",
1128
+ datapath_id, transaction_id );
1129
+
1130
+ if ( event_handlers.barrier_reply_callback == NULL ) {
1131
+ debug( "Callback function for barrier reply events is not set." );
1132
+ return;
1133
+ }
1134
+
1135
+ debug( "Calling barrier reply handler ( callback = %p, user_data = %p ).",
1136
+ event_handlers.barrier_reply_callback, event_handlers.barrier_reply_user_data );
1137
+
1138
+ event_handlers.barrier_reply_callback( datapath_id,
1139
+ transaction_id,
1140
+ event_handlers.barrier_reply_user_data );
1141
+ }
1142
+
1143
+
1144
+ static void
1145
+ handle_queue_get_config_reply( const uint64_t datapath_id, buffer *data ) {
1146
+ uint16_t port, queues_length;
1147
+ uint32_t transaction_id;
1148
+ list_element *queues_head = NULL;
1149
+ list_element *element = NULL;
1150
+ struct ofp_packet_queue *pq, *packet_queue;
1151
+ struct ofp_queue_get_config_reply *queue_get_config_reply;
1152
+
1153
+ if ( ( data == NULL ) || ( ( data != NULL ) && ( data->length == 0 ) ) ) {
1154
+ critical( "An OpenFlow message must be filled before calling handle_queue_get_config_reply()." );
1155
+ assert( 0 );
1156
+ }
1157
+
1158
+ queue_get_config_reply = ( struct ofp_queue_get_config_reply * ) data->data;
1159
+
1160
+ transaction_id = ntohl( queue_get_config_reply->header.xid );
1161
+ port = ntohs( queue_get_config_reply->port );
1162
+
1163
+ queues_length = ( uint16_t ) ( ntohs( queue_get_config_reply->header.length )
1164
+ - offsetof( struct ofp_queue_get_config_reply, queues ) );
1165
+
1166
+ debug( "A queue get config reply message is received from %#" PRIx64
1167
+ " ( transaction_id = %#x, port = %u, queues length = %u ).",
1168
+ datapath_id, transaction_id, port, queues_length );
1169
+
1170
+ if ( event_handlers.queue_get_config_reply_callback == NULL ) {
1171
+ debug( "Callback function for queue get config reply events is not set." );
1172
+ return;
1173
+ }
1174
+
1175
+ if ( queues_length > 0 ) {
1176
+ create_list( &queues_head );
1177
+ }
1178
+ else {
1179
+ critical( "No queues found." );
1180
+ assert( 0 );
1181
+ }
1182
+
1183
+ packet_queue = ( struct ofp_packet_queue * ) queue_get_config_reply->queues;
1184
+
1185
+ while ( queues_length > 0 ) {
1186
+ pq = ( struct ofp_packet_queue * ) xcalloc( 1, ntohs( packet_queue->len ) );
1187
+
1188
+ ntoh_packet_queue( pq, packet_queue );
1189
+ append_to_tail( &queues_head, pq );
1190
+
1191
+ packet_queue = ( struct ofp_packet_queue * ) ( ( char * ) packet_queue + pq->len );
1192
+ queues_length = ( uint16_t ) ( queues_length - pq->len );
1193
+ }
1194
+
1195
+ debug( "Calling queue get config reply handler ( callback = %p, user_data = %p ).",
1196
+ event_handlers.queue_get_config_reply_callback,
1197
+ event_handlers.queue_get_config_reply_user_data );
1198
+
1199
+ event_handlers.queue_get_config_reply_callback( datapath_id,
1200
+ transaction_id,
1201
+ port,
1202
+ queues_head,
1203
+ event_handlers.queue_get_config_reply_user_data );
1204
+
1205
+ if ( queues_head != NULL ) {
1206
+ element = queues_head;
1207
+ while ( element != NULL ) {
1208
+ xfree( element->data );
1209
+ element = element->next;
1210
+ }
1211
+ delete_list( queues_head );
1212
+ }
1213
+ }
1214
+
1215
+
1216
+ static void
1217
+ update_switch_event_stats( uint16_t type, int send_receive, bool result ) {
1218
+ char key[ STAT_KEY_LENGTH ];
1219
+ char suffix[ 16 ];
1220
+ char direction[ 16 ];
1221
+ const char *prefix = "openflow_application_interface.";
1222
+
1223
+ memset( suffix, '\0', sizeof( suffix ) );
1224
+
1225
+ if ( result ) {
1226
+ sprintf( suffix, "_succeeded" );
1227
+ }
1228
+ else {
1229
+ sprintf( suffix, "_failed" );
1230
+ }
1231
+
1232
+ memset( direction, '\0', sizeof( direction ) );
1233
+
1234
+ switch ( send_receive ) {
1235
+ case OPENFLOW_MESSAGE_SEND:
1236
+ sprintf( direction, "_send" );
1237
+ break;
1238
+ case OPENFLOW_MESSAGE_RECEIVE:
1239
+ sprintf( direction, "_receive" );
1240
+ break;
1241
+ default:
1242
+ return;
1243
+ }
1244
+
1245
+ switch ( type ) {
1246
+ case MESSENGER_OPENFLOW_CONNECTED:
1247
+ snprintf( key, STAT_KEY_LENGTH, "%s%s%s%s", prefix, "switch_connected", direction, suffix );
1248
+ break;
1249
+ case MESSENGER_OPENFLOW_READY:
1250
+ snprintf( key, STAT_KEY_LENGTH, "%s%s%s%s", prefix, "switch_ready", direction, suffix );
1251
+ break;
1252
+ case MESSENGER_OPENFLOW_DISCONNECTED:
1253
+ snprintf( key, STAT_KEY_LENGTH, "%s%s%s%s", prefix, "switch_disconnected", direction, suffix );
1254
+ break;
1255
+ default:
1256
+ snprintf( key, STAT_KEY_LENGTH, "%s%s%s%s", prefix, "undefined_switch_event", direction, suffix );
1257
+ break;
1258
+ }
1259
+
1260
+ increment_stat( key );
1261
+ }
1262
+
1263
+
1264
+ static void
1265
+ handle_switch_ready( uint64_t datapath_id ) {
1266
+ if ( event_handlers.switch_ready_callback == NULL ) {
1267
+ debug( "Callback function for switch_ready events is not set." );
1268
+ return;
1269
+ }
1270
+
1271
+ assert( event_handlers.switch_ready_callback != NULL );
1272
+ if ( event_handlers.simple_switch_ready_callback ) {
1273
+ switch_ready event = {
1274
+ datapath_id,
1275
+ event_handlers.switch_ready_user_data
1276
+ };
1277
+ ( ( simple_switch_ready_handler * ) event_handlers.switch_ready_callback )( event );
1278
+ }
1279
+ else {
1280
+ ( ( switch_ready_handler * ) event_handlers.switch_ready_callback )(
1281
+ datapath_id,
1282
+ event_handlers.switch_ready_user_data
1283
+ );
1284
+ }
1285
+ }
1286
+
1287
+
1288
+ static void
1289
+ handle_switch_events( uint16_t type, void *data, size_t length ) {
1290
+ uint64_t datapath_id;
1291
+ openflow_service_header_t *message;
1292
+
1293
+ assert( data != NULL );
1294
+ assert( length == sizeof( openflow_service_header_t ) );
1295
+
1296
+ debug( "A switch event is received from remote ( type = %u ).", type );
1297
+
1298
+ message = ( openflow_service_header_t * ) data;
1299
+
1300
+ datapath_id = ntohll( message->datapath_id );
1301
+
1302
+ switch ( type ) {
1303
+ case MESSENGER_OPENFLOW_CONNECTED:
1304
+ break;
1305
+ case MESSENGER_OPENFLOW_READY:
1306
+ handle_switch_ready( datapath_id );
1307
+ break;
1308
+ case MESSENGER_OPENFLOW_DISCONNECTED:
1309
+ if ( event_handlers.switch_disconnected_callback != NULL ) {
1310
+ debug( "Calling switch disconnected handler ( callback = %p, user_data = %p ).",
1311
+ event_handlers.switch_disconnected_callback, event_handlers.switch_disconnected_user_data );
1312
+ event_handlers.switch_disconnected_callback( datapath_id,
1313
+ event_handlers.switch_disconnected_user_data );
1314
+ }
1315
+ else {
1316
+ debug( "Callback function for switch disconnected events is not set." );
1317
+ }
1318
+ break;
1319
+ default:
1320
+ error( "Unhandled switch event ( type = %u ).", type );
1321
+ break;
1322
+ }
1323
+
1324
+ update_switch_event_stats( type, OPENFLOW_MESSAGE_RECEIVE, true );
1325
+ }
1326
+
1327
+
1328
+ static void
1329
+ update_openflow_stats( uint8_t type, int send_receive, bool result ) {
1330
+ char key[ STAT_KEY_LENGTH ];
1331
+ char suffix[ 16 ];
1332
+ char direction[ 16 ];
1333
+ const char *prefix = "openflow_application_interface.";
1334
+
1335
+ memset( suffix, '\0', sizeof( suffix ) );
1336
+
1337
+ if ( result ) {
1338
+ sprintf( suffix, "_succeeded" );
1339
+ }
1340
+ else {
1341
+ sprintf( suffix, "_failed" );
1342
+ }
1343
+
1344
+ memset( direction, '\0', sizeof( direction ) );
1345
+
1346
+ switch ( send_receive ) {
1347
+ case OPENFLOW_MESSAGE_SEND:
1348
+ sprintf( direction, "_send" );
1349
+ break;
1350
+ case OPENFLOW_MESSAGE_RECEIVE:
1351
+ sprintf( direction, "_receive" );
1352
+ break;
1353
+ default:
1354
+ return;
1355
+ }
1356
+
1357
+ switch ( type ) {
1358
+ case OFPT_HELLO:
1359
+ snprintf( key, STAT_KEY_LENGTH, "%s%s%s%s", prefix, "hello", direction, suffix );
1360
+ break;
1361
+ case OFPT_ERROR:
1362
+ snprintf( key, STAT_KEY_LENGTH, "%s%s%s%s", prefix, "error", direction, suffix );
1363
+ break;
1364
+ case OFPT_ECHO_REQUEST:
1365
+ snprintf( key, STAT_KEY_LENGTH, "%s%s%s%s", prefix, "echo_request", direction, suffix );
1366
+ break;
1367
+ case OFPT_ECHO_REPLY:
1368
+ snprintf( key, STAT_KEY_LENGTH, "%s%s%s%s", prefix, "echo_reply", direction, suffix );
1369
+ break;
1370
+ case OFPT_VENDOR:
1371
+ snprintf( key, STAT_KEY_LENGTH, "%s%s%s%s", prefix, "vendor", direction, suffix );
1372
+ break;
1373
+ case OFPT_FEATURES_REQUEST:
1374
+ snprintf( key, STAT_KEY_LENGTH, "%s%s%s%s", prefix, "features_request", direction, suffix );
1375
+ break;
1376
+ case OFPT_FEATURES_REPLY:
1377
+ snprintf( key, STAT_KEY_LENGTH, "%s%s%s%s", prefix, "features_reply", direction, suffix );
1378
+ break;
1379
+ case OFPT_GET_CONFIG_REQUEST:
1380
+ snprintf( key, STAT_KEY_LENGTH, "%s%s%s%s", prefix, "get_config_request", direction, suffix );
1381
+ break;
1382
+ case OFPT_GET_CONFIG_REPLY:
1383
+ snprintf( key, STAT_KEY_LENGTH, "%s%s%s%s", prefix, "get_config_reply", direction, suffix );
1384
+ break;
1385
+ case OFPT_SET_CONFIG:
1386
+ snprintf( key, STAT_KEY_LENGTH, "%s%s%s%s", prefix, "set_config", direction, suffix );
1387
+ break;
1388
+ case OFPT_PACKET_IN:
1389
+ snprintf( key, STAT_KEY_LENGTH, "%s%s%s%s", prefix, "packet_in", direction, suffix );
1390
+ break;
1391
+ case OFPT_FLOW_REMOVED:
1392
+ snprintf( key, STAT_KEY_LENGTH, "%s%s%s%s", prefix, "flow_removed", direction, suffix );
1393
+ break;
1394
+ case OFPT_PORT_STATUS:
1395
+ snprintf( key, STAT_KEY_LENGTH, "%s%s%s%s", prefix, "port_status", direction, suffix );
1396
+ break;
1397
+ case OFPT_PACKET_OUT:
1398
+ snprintf( key, STAT_KEY_LENGTH, "%s%s%s%s", prefix, "packet_out", direction, suffix );
1399
+ break;
1400
+ case OFPT_FLOW_MOD:
1401
+ snprintf( key, STAT_KEY_LENGTH, "%s%s%s%s", prefix, "flow_mod", direction, suffix );
1402
+ break;
1403
+ case OFPT_PORT_MOD:
1404
+ snprintf( key, STAT_KEY_LENGTH, "%s%s%s%s", prefix, "port_mod", direction, suffix );
1405
+ break;
1406
+ case OFPT_STATS_REQUEST:
1407
+ snprintf( key, STAT_KEY_LENGTH, "%s%s%s%s", prefix, "stats_request", direction, suffix );
1408
+ break;
1409
+ case OFPT_STATS_REPLY:
1410
+ snprintf( key, STAT_KEY_LENGTH, "%s%s%s%s", prefix, "stats_reply", direction, suffix );
1411
+ break;
1412
+ case OFPT_BARRIER_REQUEST:
1413
+ snprintf( key, STAT_KEY_LENGTH, "%s%s%s%s", prefix, "barrier_request", direction, suffix );
1414
+ break;
1415
+ case OFPT_BARRIER_REPLY:
1416
+ snprintf( key, STAT_KEY_LENGTH, "%s%s%s%s", prefix, "barrier_reply", direction, suffix );
1417
+ break;
1418
+ case OFPT_QUEUE_GET_CONFIG_REQUEST:
1419
+ snprintf( key, STAT_KEY_LENGTH, "%s%s%s%s", prefix, "queue_get_config_request", direction, suffix );
1420
+ break;
1421
+ case OFPT_QUEUE_GET_CONFIG_REPLY:
1422
+ snprintf( key, STAT_KEY_LENGTH, "%s%s%s%s", prefix, "queue_get_config_reply", direction, suffix );
1423
+ break;
1424
+ default:
1425
+ snprintf( key, STAT_KEY_LENGTH, "%s%s%s%s", prefix, "undefined_message_type", direction, suffix );
1426
+ break;
1427
+ }
1428
+
1429
+ increment_stat( key );
1430
+ }
1431
+
1432
+
1433
+ static void
1434
+ handle_openflow_message( void *data, size_t length ) {
1435
+ void *p;
1436
+ int ret;
1437
+ uint64_t datapath_id;
1438
+ buffer *buffer;
1439
+ struct ofp_header *header;
1440
+ openflow_service_header_t *message;
1441
+
1442
+ assert( data != NULL );
1443
+ assert( length >= ( sizeof( openflow_service_header_t ) + sizeof( struct ofp_header ) ) );
1444
+
1445
+ debug( "An OpenFlow message is received from remote." );
1446
+
1447
+ message = ( openflow_service_header_t * ) data;
1448
+
1449
+ datapath_id = ntohll( message->datapath_id );
1450
+
1451
+ buffer = alloc_buffer_with_length( length );
1452
+
1453
+ assert( buffer != NULL );
1454
+
1455
+ p = append_back_buffer( buffer, length );
1456
+ memcpy( p, data, length );
1457
+ remove_front_buffer( buffer, sizeof( openflow_service_header_t ) );
1458
+
1459
+ ret = validate_openflow_message( buffer );
1460
+
1461
+ if ( ret < 0 ) {
1462
+ error( "Failed to validate an OpenFlow message ( code = %d, length = %u ).", ret, length );
1463
+ free_buffer( buffer );
1464
+
1465
+ return;
1466
+ }
1467
+
1468
+ header = ( struct ofp_header * ) buffer->data;
1469
+
1470
+ switch ( header->type ) {
1471
+ case OFPT_ERROR:
1472
+ handle_error( datapath_id, buffer );
1473
+ break;
1474
+ case OFPT_VENDOR:
1475
+ handle_vendor( datapath_id, buffer );
1476
+ break;
1477
+ case OFPT_FEATURES_REPLY:
1478
+ handle_features_reply( datapath_id, buffer );
1479
+ break;
1480
+ case OFPT_GET_CONFIG_REPLY:
1481
+ handle_get_config_reply( datapath_id, buffer );
1482
+ break;
1483
+ case OFPT_PACKET_IN:
1484
+ handle_packet_in( datapath_id, buffer );
1485
+ break;
1486
+ case OFPT_FLOW_REMOVED:
1487
+ handle_flow_removed( datapath_id, buffer );
1488
+ break;
1489
+ case OFPT_PORT_STATUS:
1490
+ handle_port_status( datapath_id, buffer );
1491
+ break;
1492
+ case OFPT_STATS_REPLY:
1493
+ handle_stats_reply( datapath_id, buffer );
1494
+ break;
1495
+ case OFPT_BARRIER_REPLY:
1496
+ handle_barrier_reply( datapath_id, buffer );
1497
+ break;
1498
+ case OFPT_QUEUE_GET_CONFIG_REPLY:
1499
+ handle_queue_get_config_reply( datapath_id, buffer );
1500
+ break;
1501
+ default:
1502
+ error( "Unhandled OpenFlow message ( type = %u ).", header->type );
1503
+ break;
1504
+ }
1505
+
1506
+ update_openflow_stats( header->type, OPENFLOW_MESSAGE_RECEIVE, true );
1507
+
1508
+ free_buffer( buffer );
1509
+ }
1510
+
1511
+
1512
+ static void
1513
+ handle_message( uint16_t type, void *data, size_t length ) {
1514
+ assert( data != NULL );
1515
+ assert( length >= sizeof( openflow_service_header_t ) );
1516
+
1517
+ debug( "A message is received from remote ( type = %u ).", type );
1518
+
1519
+ switch ( type ) {
1520
+ case MESSENGER_OPENFLOW_MESSAGE:
1521
+ return handle_openflow_message( data, length );
1522
+ case MESSENGER_OPENFLOW_CONNECTED:
1523
+ case MESSENGER_OPENFLOW_READY:
1524
+ case MESSENGER_OPENFLOW_DISCONNECTED:
1525
+ return handle_switch_events( type, data, length );
1526
+ default:
1527
+ error( "Unhandled message ( type = %u ).", type );
1528
+ update_switch_event_stats( type, OPENFLOW_MESSAGE_RECEIVE, true );
1529
+ break;
1530
+ }
1531
+ }
1532
+
1533
+
1534
+ static void
1535
+ insert_dpid( list_element **head, uint64_t *dpid ) {
1536
+ assert( head != NULL );
1537
+ assert( dpid != NULL );
1538
+
1539
+ list_element *element;
1540
+ for ( element = *head; element != NULL; element = element->next ) {
1541
+ if ( *dpid <= *( uint64_t * ) element->data ) {
1542
+ break;
1543
+ }
1544
+ }
1545
+ if ( element == NULL ) {
1546
+ append_to_tail( head, dpid );
1547
+ }
1548
+ else if ( element == *head ) {
1549
+ insert_in_front( head, dpid );
1550
+ }
1551
+ else {
1552
+ insert_before( head, element->data, dpid );
1553
+ }
1554
+ }
1555
+
1556
+
1557
+ static void
1558
+ handle_list_switches_reply( uint16_t message_type, void *data, size_t length, void *user_data ) {
1559
+ UNUSED( message_type );
1560
+ assert( data != NULL );
1561
+
1562
+ uint64_t *dpid = ( uint64_t *) data;
1563
+ size_t num_switch = length / sizeof( uint64_t );
1564
+
1565
+ debug( "A list switches reply message is received ( number of switches = %u ).",
1566
+ num_switch );
1567
+
1568
+ if ( event_handlers.list_switches_reply_callback == NULL ) {
1569
+ debug( "Callback function for list switches reply events is not set." );
1570
+ return;
1571
+ }
1572
+
1573
+ list_element *switches;
1574
+ create_list( &switches );
1575
+
1576
+ unsigned int i;
1577
+ for ( i = 0; i < num_switch; ++i ) {
1578
+ uint64_t *datapath_id = ( uint64_t *) xmalloc( sizeof( uint64_t ) );
1579
+ *datapath_id = ntohll( dpid[ i ] );
1580
+ insert_dpid( &switches, datapath_id );
1581
+ }
1582
+
1583
+ debug( "Calling list switches reply handler ( callback = %p ).",
1584
+ event_handlers.list_switches_reply_callback );
1585
+
1586
+ event_handlers.list_switches_reply_callback( switches, user_data );
1587
+
1588
+ list_element *element;
1589
+ for ( element = switches; element != NULL; element = element->next ) {
1590
+ xfree( element->data );
1591
+ }
1592
+ delete_list( switches );
1593
+ }
1594
+
1595
+
1596
+ bool
1597
+ send_openflow_message( const uint64_t datapath_id, buffer *message ) {
1598
+ bool ret;
1599
+ void *data;
1600
+ char remote_service_name[ MESSENGER_SERVICE_NAME_LENGTH ];
1601
+ uint16_t header_length;
1602
+ buffer *buffer;
1603
+ struct ofp_header *ofp;
1604
+ openflow_service_header_t header;
1605
+
1606
+ maybe_init_openflow_application_interface();
1607
+ assert( openflow_application_interface_initialized );
1608
+
1609
+ if ( ( message == NULL ) || ( ( message != NULL ) && ( message->length == 0 ) ) ) {
1610
+ critical( "An OpenFlow message must be passed to send_openflow_message()." );
1611
+ assert( 0 );
1612
+ }
1613
+
1614
+ ofp = ( struct ofp_header * ) message->data;
1615
+ buffer = duplicate_buffer( message );
1616
+
1617
+ assert( buffer != NULL );
1618
+
1619
+ header_length = ( uint16_t ) ( sizeof( openflow_service_header_t )
1620
+ + strlen( service_name ) + 1 );
1621
+
1622
+ header.datapath_id = htonll( datapath_id );
1623
+ header.service_name_length = htons( ( uint16_t ) ( strlen( service_name ) + 1 ) );
1624
+
1625
+ data = append_front_buffer( buffer, header_length );
1626
+ memset( data, '\0', header_length );
1627
+ memcpy( data, &header, sizeof( openflow_service_header_t ) );
1628
+ memcpy( ( char * ) data + sizeof( openflow_service_header_t ),
1629
+ service_name, strlen( service_name ) );
1630
+
1631
+ memset( remote_service_name, '\0', sizeof( remote_service_name ) );
1632
+ snprintf( remote_service_name, sizeof( remote_service_name ),
1633
+ "switch.%#" PRIx64, datapath_id );
1634
+
1635
+ debug( "Sending an OpenFlow message to %#" PRIx64
1636
+ " ( service_name = %s, remote_service_name = %s, "
1637
+ "ofp_header = [version = %#x, type = %#x, length = %u, transaction_id = %#x] ).",
1638
+ datapath_id, service_name, remote_service_name,
1639
+ ofp->version, ofp->type, ntohs( ofp->length ), ntohl( ofp->xid ) );
1640
+
1641
+ ret = send_message( remote_service_name, MESSENGER_OPENFLOW_MESSAGE,
1642
+ buffer->data, buffer->length );
1643
+
1644
+ free_buffer( buffer );
1645
+
1646
+ update_openflow_stats( ofp->type, OPENFLOW_MESSAGE_SEND, ret );
1647
+
1648
+ return ret;
1649
+ }
1650
+
1651
+
1652
+ bool
1653
+ send_list_switches_request( void *user_data ) {
1654
+ uint16_t message_type = 0;
1655
+ void *data = NULL;
1656
+ size_t data_length = 0;
1657
+
1658
+ maybe_init_openflow_application_interface();
1659
+ assert( openflow_application_interface_initialized );
1660
+
1661
+ debug( "Sending a list switches request ( service_name = %s ).", service_name );
1662
+
1663
+ return send_request_message( "switch_manager", service_name, message_type,
1664
+ data, data_length, user_data );
1665
+ }
1666
+
1667
+
1668
+ /*
1669
+ * Local variables:
1670
+ * c-basic-offset: 2
1671
+ * indent-tabs-mode: nil
1672
+ * End:
1673
+ */