trema 0.1.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 (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
+ */