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,329 @@
1
+ /*
2
+ * An OpenFlow application interface library.
3
+ *
4
+ * Author: Yasunobu Chiba
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 OPENFLOW_APPLICATION_INTERFACE_H
24
+ #define OPENFLOW_APPLICATION_INTERFACE_H
25
+
26
+
27
+ #include "buffer.h"
28
+ #include "linked_list.h"
29
+ #include "openflow.h"
30
+ #include "openflow_service_interface.h"
31
+
32
+
33
+ /********************************************************************************
34
+ * Functions for initializing/finalizing the OpenFlow application interface.
35
+ ********************************************************************************/
36
+
37
+ bool init_openflow_application_interface( const char *service_name );
38
+ bool finalize_openflow_application_interface( void );
39
+ bool openflow_application_interface_is_initialized( void );
40
+
41
+
42
+ /********************************************************************************
43
+ * Event handler definitions.
44
+ ********************************************************************************/
45
+
46
+ typedef struct {
47
+ uint64_t datapath_id;
48
+ void *user_data;
49
+ } switch_ready;
50
+
51
+ typedef void ( simple_switch_ready_handler )( switch_ready event );
52
+
53
+ typedef void ( switch_ready_handler )(
54
+ uint64_t datapath_id,
55
+ void *user_data
56
+ );
57
+
58
+
59
+ typedef void ( *switch_disconnected_handler )(
60
+ uint64_t datapath_id,
61
+ void *user_data
62
+ );
63
+
64
+
65
+ typedef void ( *error_handler )(
66
+ uint64_t datapath_id,
67
+ uint32_t transaction_id,
68
+ uint16_t type,
69
+ uint16_t code,
70
+ const buffer *data,
71
+ void *user_data
72
+ );
73
+
74
+
75
+ typedef void ( *vendor_handler )(
76
+ uint64_t datapath_id,
77
+ uint32_t transaction_id,
78
+ uint32_t vendor,
79
+ const buffer *data,
80
+ void *user_data
81
+ );
82
+
83
+
84
+ typedef void ( *features_reply_handler )(
85
+ uint64_t datapath_id,
86
+ uint32_t transaction_id,
87
+ uint32_t n_buffers,
88
+ uint8_t n_tables,
89
+ uint32_t capabilities,
90
+ uint32_t actions,
91
+ const list_element *phy_ports,
92
+ void *user_data
93
+ );
94
+
95
+
96
+ typedef void ( *get_config_reply_handler )(
97
+ uint64_t datapath_id,
98
+ uint32_t transaction_id,
99
+ uint16_t flags,
100
+ uint16_t miss_send_len,
101
+ void *user_data
102
+ );
103
+
104
+
105
+ typedef struct {
106
+ uint64_t datapath_id;
107
+ uint32_t transaction_id;
108
+ uint32_t buffer_id;
109
+ uint16_t total_len;
110
+ uint16_t in_port;
111
+ uint8_t reason;
112
+ const buffer *data;
113
+ void *user_data;
114
+ } packet_in;
115
+
116
+ typedef void ( simple_packet_in_handler )( uint64_t datapath_id, packet_in message );
117
+ typedef void ( packet_in_handler )(
118
+ uint64_t datapath_id,
119
+ uint32_t transaction_id,
120
+ uint32_t buffer_id,
121
+ uint16_t total_len,
122
+ uint16_t in_port,
123
+ uint8_t reason,
124
+ const buffer *data,
125
+ void *user_data
126
+ );
127
+
128
+
129
+ typedef struct {
130
+ uint64_t datapath_id;
131
+ uint32_t transaction_id;
132
+ struct ofp_match match;
133
+ uint64_t cookie;
134
+ uint16_t priority;
135
+ uint8_t reason;
136
+ uint32_t duration_sec;
137
+ uint32_t duration_nsec;
138
+ uint16_t idle_timeout;
139
+ uint64_t packet_count;
140
+ uint64_t byte_count;
141
+ void *user_data;
142
+ } flow_removed;
143
+
144
+ typedef void ( simple_flow_removed_handler )( uint64_t datapath_id, flow_removed message );
145
+ typedef void ( flow_removed_handler )(
146
+ uint64_t datapath_id,
147
+ uint32_t transaction_id,
148
+ struct ofp_match match,
149
+ uint64_t cookie,
150
+ uint16_t priority,
151
+ uint8_t reason,
152
+ uint32_t duration_sec,
153
+ uint32_t duration_nsec,
154
+ uint16_t idle_timeout,
155
+ uint64_t packet_count,
156
+ uint64_t byte_count,
157
+ void *user_data
158
+ );
159
+
160
+
161
+ typedef void ( *port_status_handler )(
162
+ uint64_t datapath_id,
163
+ uint32_t transaction_id,
164
+ uint8_t reason,
165
+ struct ofp_phy_port phy_port,
166
+ void *user_data
167
+ );
168
+
169
+
170
+ typedef void ( *stats_reply_handler )(
171
+ uint64_t datapath_id,
172
+ uint32_t transaction_id,
173
+ uint16_t type,
174
+ uint16_t flags,
175
+ const buffer *data,
176
+ void *user_data
177
+ );
178
+
179
+
180
+ typedef void ( *barrier_reply_handler )(
181
+ uint64_t datapath_id,
182
+ uint32_t transaction_id,
183
+ void *user_data
184
+ );
185
+
186
+
187
+ typedef void ( *queue_get_config_reply_handler )(
188
+ uint64_t datapath_id,
189
+ uint32_t transaction_id,
190
+ uint16_t port,
191
+ const list_element *queues,
192
+ void *user_data
193
+ );
194
+
195
+
196
+ typedef void ( *list_switches_reply_handler )(
197
+ const list_element *switches,
198
+ void *user_data
199
+ );
200
+
201
+
202
+ typedef struct openflow_event_handlers {
203
+ bool simple_switch_ready_callback;
204
+ void *switch_ready_callback;
205
+ void *switch_ready_user_data;
206
+
207
+ switch_disconnected_handler switch_disconnected_callback;
208
+ void *switch_disconnected_user_data;
209
+
210
+ error_handler error_callback;
211
+ void *error_user_data;
212
+
213
+ vendor_handler vendor_callback;
214
+ void *vendor_user_data;
215
+
216
+ features_reply_handler features_reply_callback;
217
+ void *features_reply_user_data;
218
+
219
+ get_config_reply_handler get_config_reply_callback;
220
+ void *get_config_reply_user_data;
221
+
222
+ bool simple_packet_in_callback;
223
+ void *packet_in_callback;
224
+ void *packet_in_user_data;
225
+
226
+ bool simple_flow_removed_callback;
227
+ void *flow_removed_callback;
228
+ void *flow_removed_user_data;
229
+
230
+ port_status_handler port_status_callback;
231
+ void *port_status_user_data;
232
+
233
+ stats_reply_handler stats_reply_callback;
234
+ void *stats_reply_user_data;
235
+
236
+ barrier_reply_handler barrier_reply_callback;
237
+ void *barrier_reply_user_data;
238
+
239
+ queue_get_config_reply_handler queue_get_config_reply_callback;
240
+ void *queue_get_config_reply_user_data;
241
+
242
+ list_switches_reply_handler list_switches_reply_callback;
243
+ } openflow_event_handlers_t;
244
+
245
+
246
+ /********************************************************************************
247
+ * Functions for setting callback functions for OpenFlow related events.
248
+ ********************************************************************************/
249
+
250
+ bool set_openflow_event_handlers( const openflow_event_handlers_t handlers );
251
+
252
+ #define set_switch_ready_handler( callback, user_data ) \
253
+ { \
254
+ if ( __builtin_types_compatible_p( typeof( callback ), simple_switch_ready_handler ) ) { \
255
+ _set_switch_ready_handler( true, callback, user_data ); \
256
+ } \
257
+ else if ( __builtin_types_compatible_p( typeof( callback ), switch_ready_handler ) ) { \
258
+ _set_switch_ready_handler( false, callback, user_data ); \
259
+ } \
260
+ else { \
261
+ _set_switch_ready_handler( false, NULL, NULL ); \
262
+ } \
263
+ }
264
+ bool _set_switch_ready_handler( bool simple_callback, void *callback, void *user_data );
265
+
266
+
267
+ bool set_switch_disconnected_handler( switch_disconnected_handler callback, void *user_data );
268
+ bool set_error_handler( error_handler callback, void *user_data );
269
+ bool set_vendor_handler( vendor_handler callback, void *user_data );
270
+ bool set_features_reply_handler( features_reply_handler callback, void *user_data );
271
+ bool set_get_config_reply_handler( get_config_reply_handler callback, void *user_data );
272
+
273
+
274
+ #define set_packet_in_handler( callback, user_data ) \
275
+ { \
276
+ if ( __builtin_types_compatible_p( typeof( callback ), simple_packet_in_handler ) ) { \
277
+ _set_packet_in_handler( true, callback, user_data ); \
278
+ } \
279
+ else if ( __builtin_types_compatible_p( typeof( callback ), packet_in_handler ) ) { \
280
+ _set_packet_in_handler( false, callback, user_data ); \
281
+ } \
282
+ else { \
283
+ _set_packet_in_handler( false, NULL, NULL ); \
284
+ } \
285
+ }
286
+ bool _set_packet_in_handler( bool simple_callback, void *callback, void *user_data );
287
+
288
+
289
+ #define set_flow_removed_handler( callback, user_data ) \
290
+ { \
291
+ if ( __builtin_types_compatible_p( typeof( callback ), simple_flow_removed_handler ) ) { \
292
+ _set_flow_removed_handler( true, callback, user_data ); \
293
+ } \
294
+ else if ( __builtin_types_compatible_p( typeof( callback ), flow_removed_handler ) ) { \
295
+ _set_flow_removed_handler( false, callback, user_data ); \
296
+ } \
297
+ else { \
298
+ _set_flow_removed_handler( false, NULL, NULL ); \
299
+ } \
300
+ }
301
+ bool _set_flow_removed_handler( bool simple_callback, void *callback, void *user_data );
302
+
303
+
304
+ bool set_port_status_handler( port_status_handler callback, void *user_data );
305
+ bool set_stats_reply_handler( stats_reply_handler callback, void *user_data );
306
+ bool set_barrier_reply_handler( barrier_reply_handler callback, void *user_data );
307
+ bool set_queue_get_config_reply_handler( queue_get_config_reply_handler callback, void *user_data );
308
+
309
+ bool set_list_switches_reply_handler( list_switches_reply_handler callback );
310
+
311
+
312
+ /********************************************************************************
313
+ * Function for sending an OpenFlow message to an OpenFlow switch.
314
+ ********************************************************************************/
315
+
316
+ bool send_openflow_message( const uint64_t datapath_id, buffer *message );
317
+
318
+ bool send_list_switches_request( void *user_data );
319
+
320
+
321
+ #endif // OPENFLOW_APPLICATION_INTERFACE_H
322
+
323
+
324
+ /*
325
+ * Local variables:
326
+ * c-basic-offset: 2
327
+ * indent-tabs-mode: nil
328
+ * End:
329
+ */
@@ -0,0 +1,4051 @@
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 <arpa/inet.h>
22
+ #include <assert.h>
23
+ #include <inttypes.h>
24
+ #include <pthread.h>
25
+ #include <string.h>
26
+ #include <sys/socket.h>
27
+ #include <sys/types.h>
28
+ #include <unistd.h>
29
+ #include "openflow_message.h"
30
+ #include "packet_info.h"
31
+ #include "wrapper.h"
32
+ #include "log.h"
33
+
34
+
35
+ #ifdef UNIT_TESTING
36
+
37
+ // Allow static functions to be called from unit tests.
38
+ #define static
39
+
40
+ /* Redirect getpid to a function in the test application so it's
41
+ * possible to test if pid value is correctly used. */
42
+ #ifdef getpid
43
+ #undef getpid
44
+ #endif // getpid
45
+ #define getpid mock_getpid
46
+ extern pid_t mock_getpid( void );
47
+
48
+ /* Redirect debug to a function in the test application so it's
49
+ * possible to test if debug messages are generated expectedly. */
50
+ #ifdef debug
51
+ #undef debug
52
+ #endif // debug
53
+ #define debug mock_debug
54
+ extern void mock_debug( const char *format, ... );
55
+
56
+ #endif // UNIT_TESTING
57
+
58
+
59
+ #define VLAN_VID_MASK 0x0fff // 12 bits
60
+ #define VLAN_PCP_MASK 0x07 // 3 bits
61
+ #define NW_TOS_MASK 0xfc // upper 6 bits
62
+ #define ARP_OP_MASK 0x00ff // 8 bits
63
+
64
+ #define PORT_CONFIG ( OFPPC_PORT_DOWN | OFPPC_NO_STP | OFPPC_NO_RECV \
65
+ | OFPPC_NO_RECV_STP | OFPPC_NO_FLOOD | OFPPC_NO_FWD \
66
+ | OFPPC_NO_PACKET_IN )
67
+ #define PORT_STATE ( OFPPS_LINK_DOWN | OFPPS_STP_LISTEN | OFPPS_STP_LEARN \
68
+ | OFPPS_STP_FORWARD | OFPPS_STP_BLOCK | OFPPS_STP_MASK )
69
+ #define PORT_FEATURES ( OFPPF_10MB_HD | OFPPF_10MB_FD | OFPPF_100MB_HD \
70
+ | OFPPF_100MB_FD | OFPPF_1GB_HD | OFPPF_1GB_FD \
71
+ | OFPPF_10GB_FD | OFPPF_COPPER | OFPPF_FIBER \
72
+ | OFPPF_AUTONEG | OFPPF_PAUSE | OFPPF_PAUSE_ASYM )
73
+ #define FLOW_MOD_FLAGS ( OFPFF_SEND_FLOW_REM | OFPFF_CHECK_OVERLAP | OFPFF_EMERG )
74
+
75
+
76
+ static uint32_t transaction_id = 0;
77
+ static pthread_mutex_t transaction_id_mutex = PTHREAD_RECURSIVE_MUTEX_INITIALIZER_NP;
78
+
79
+ static uint64_t cookie = 0;
80
+ static pthread_mutex_t cookie_mutex = PTHREAD_RECURSIVE_MUTEX_INITIALIZER_NP;
81
+
82
+
83
+ bool
84
+ init_openflow_message( void ) {
85
+ pid_t pid;
86
+
87
+ pid = getpid();
88
+
89
+ pthread_mutex_lock( &transaction_id_mutex );
90
+ transaction_id = ( uint32_t ) pid << 16;
91
+ pthread_mutex_unlock( &transaction_id_mutex );
92
+
93
+ pthread_mutex_lock( &cookie_mutex );
94
+ cookie = ( uint64_t ) pid << 48;
95
+ pthread_mutex_unlock( &cookie_mutex );
96
+
97
+ debug( "transaction_id and cookie are initialized ( transaction_id = %#x, cookie = %#" PRIx64 " ).",
98
+ transaction_id, cookie );
99
+
100
+ return true;
101
+ }
102
+
103
+
104
+ static buffer *
105
+ create_header( const uint32_t transaction_id, const uint8_t type, const uint16_t length ) {
106
+ debug( "Creating an OpenFlow header (version = %#x, type = %#x, length = %u, xid = %#x).",
107
+ OFP_VERSION, type, length, transaction_id );
108
+
109
+ assert( length >= sizeof( struct ofp_header ) );
110
+
111
+ buffer *buffer = alloc_buffer();
112
+ assert( buffer != NULL );
113
+
114
+ struct ofp_header *header = append_back_buffer( buffer, length );
115
+ assert( header != NULL );
116
+ memset( header, 0, length );
117
+
118
+ header->version = OFP_VERSION;
119
+ header->type = type;
120
+ header->length = htons( length );
121
+ header->xid = htonl( transaction_id );
122
+
123
+ return buffer;
124
+ }
125
+
126
+
127
+ buffer *
128
+ create_error( const uint32_t transaction_id, const uint16_t type,
129
+ const uint16_t code, const buffer *data ) {
130
+ uint16_t length;
131
+ uint16_t data_len = 0;
132
+ buffer *buffer;
133
+ struct ofp_error_msg *error_msg;
134
+
135
+ if ( ( data != NULL ) && ( data->length > 0 ) ) {
136
+ data_len = ( uint16_t ) data->length;
137
+ }
138
+
139
+ debug( "Creating an error ( xid = %#x, type = %#x, code = %#x, data length = %u ).",
140
+ transaction_id, type, code, data_len );
141
+
142
+ length = ( uint16_t ) ( sizeof( struct ofp_error_msg ) + data_len );
143
+ buffer = create_header( transaction_id, OFPT_ERROR, length );
144
+ assert( buffer != NULL );
145
+
146
+ error_msg = ( struct ofp_error_msg * ) buffer->data;
147
+ error_msg->type = htons( type );
148
+ error_msg->code = htons( code );
149
+
150
+ if ( data_len > 0 ) {
151
+ memcpy( error_msg->data, data->data, data->length );
152
+ }
153
+
154
+ return buffer;
155
+ }
156
+
157
+
158
+ buffer *
159
+ create_hello( const uint32_t transaction_id ) {
160
+ debug( "Creating a hello ( xid = %#x ).", transaction_id );
161
+
162
+ return create_header( transaction_id, OFPT_HELLO, sizeof( struct ofp_header ) );
163
+ }
164
+
165
+
166
+ buffer *
167
+ create_echo_request( const uint32_t transaction_id, const buffer *body ) {
168
+ uint16_t data_length = 0;
169
+
170
+ if ( ( body != NULL ) && ( body->length > 0 ) ) {
171
+ data_length = ( uint16_t ) body->length;
172
+ }
173
+
174
+ debug( "Creating an echo request ( xid = %#x, data length = %u ).", transaction_id, data_length );
175
+
176
+ buffer *echo_request = create_header( transaction_id, OFPT_ECHO_REQUEST, ( uint16_t ) ( sizeof( struct ofp_header ) + data_length ) );
177
+ assert( echo_request != NULL );
178
+
179
+ if ( data_length > 0 ) {
180
+ memcpy( ( char * ) echo_request->data + sizeof( struct ofp_header ), body->data, data_length );
181
+ }
182
+
183
+ return echo_request;
184
+ }
185
+
186
+
187
+ buffer *
188
+ create_echo_reply( const uint32_t transaction_id, const buffer *body ) {
189
+ uint16_t data_length = 0;
190
+
191
+ if ( ( body != NULL ) && ( body->length > 0 ) ) {
192
+ data_length = ( uint16_t ) body->length;
193
+ }
194
+
195
+ debug( "Creating an echo reply ( xid = %#x, data length = %u ).", transaction_id, data_length );
196
+
197
+ buffer *echo_reply = create_header( transaction_id, OFPT_ECHO_REPLY, ( uint16_t ) ( sizeof( struct ofp_header ) + data_length ) );
198
+ assert( echo_reply != NULL );
199
+
200
+ if ( data_length > 0 ) {
201
+ memcpy( ( char * ) echo_reply->data + sizeof( struct ofp_header ), body->data, data_length );
202
+ }
203
+
204
+ return echo_reply;
205
+ }
206
+
207
+
208
+ buffer *
209
+ create_vendor( const uint32_t transaction_id, const uint32_t vendor, const buffer *data ) {
210
+ void *d;
211
+ uint16_t length;
212
+ uint16_t data_length = 0;
213
+ buffer *buffer;
214
+ struct ofp_vendor_header *vendor_header;
215
+
216
+ if ( ( data != NULL ) && ( data->length > 0 ) ) {
217
+ data_length = ( uint16_t ) data->length;
218
+ }
219
+
220
+ debug( "Creating a vendor ( xid = %#x, vendor = %#x, data length = %u ).",
221
+ transaction_id, vendor, data_length );
222
+
223
+ length = ( uint16_t ) ( sizeof( struct ofp_vendor_header ) + data_length );
224
+ buffer = create_header( transaction_id, OFPT_VENDOR, length );
225
+ assert( buffer != NULL );
226
+
227
+ vendor_header = ( struct ofp_vendor_header * ) buffer->data;
228
+ vendor_header->vendor = htonl( vendor );
229
+
230
+ if ( data_length > 0 ) {
231
+ d = ( void * ) ( ( char * ) buffer->data + sizeof( struct ofp_vendor_header ) );
232
+ memcpy( d, data->data, data_length );
233
+ }
234
+
235
+ return buffer;
236
+ }
237
+
238
+
239
+ buffer *
240
+ create_features_request( const uint32_t transaction_id ) {
241
+ debug( "Creating a features request ( xid = %#x ).", transaction_id );
242
+
243
+ return create_header( transaction_id, OFPT_FEATURES_REQUEST, sizeof( struct ofp_header ) );
244
+ }
245
+
246
+
247
+ buffer *
248
+ create_features_reply( const uint32_t transaction_id, const uint64_t datapath_id,
249
+ const uint32_t n_buffers, const uint8_t n_tables,
250
+ const uint32_t capabilities, const uint32_t actions,
251
+ const list_element *ports ) {
252
+ char port_str[ 1024 ];
253
+ int count = 0;
254
+ uint16_t n_ports = 0;
255
+ buffer *buffer;
256
+ struct ofp_switch_features *switch_features;
257
+ struct ofp_phy_port *phy_port;
258
+ struct ofp_phy_port pn;
259
+ list_element *p = NULL, *port;
260
+
261
+ debug( "Creating a features reply "
262
+ "( xid = %#x, datapath_id = %#" PRIx64 ", n_buffers = %u, n_tables = %u, capabilities = %#x, actions = %#x ).",
263
+ transaction_id, datapath_id, n_buffers, n_tables, capabilities, actions );
264
+
265
+ if ( ports != NULL ) {
266
+ p = ( list_element * ) xmalloc( sizeof( list_element ) );
267
+ memcpy( p, ports, sizeof( list_element ) );
268
+
269
+ port = p;
270
+ while ( port != NULL ) {
271
+ port = port->next;
272
+ n_ports++;
273
+ }
274
+ }
275
+
276
+ debug( "# of ports = %u.", n_ports );
277
+
278
+ buffer = create_header( transaction_id, OFPT_FEATURES_REPLY,
279
+ ( uint16_t ) ( offsetof( struct ofp_switch_features, ports )
280
+ + sizeof( struct ofp_phy_port ) * n_ports ) );
281
+ assert( buffer != NULL );
282
+
283
+ switch_features = ( struct ofp_switch_features * ) buffer->data;
284
+ switch_features->datapath_id = htonll( datapath_id );
285
+ switch_features->n_buffers = htonl( n_buffers );
286
+ switch_features->n_tables = n_tables;
287
+ memset( switch_features->pad, 0, sizeof( switch_features->pad ) );
288
+ switch_features->capabilities = htonl( capabilities );
289
+ switch_features->actions = htonl( actions );
290
+
291
+ if ( n_ports ) {
292
+ phy_port = ( struct ofp_phy_port * ) ( ( char * ) buffer->data
293
+ + offsetof( struct ofp_switch_features, ports) );
294
+ port = p;
295
+ while ( port != NULL ) {
296
+ phy_port_to_string( port->data, port_str, sizeof( port_str ) );
297
+ debug( "[%u] %s", count++, port_str );
298
+ hton_phy_port( &pn, ( struct ofp_phy_port * ) port->data );
299
+ memcpy( phy_port, &pn, sizeof( struct ofp_phy_port ) );
300
+ port = port->next;
301
+ phy_port++;
302
+ }
303
+
304
+ xfree( p );
305
+ }
306
+
307
+ return buffer;
308
+ }
309
+
310
+
311
+ buffer *
312
+ create_get_config_request( const uint32_t transaction_id ) {
313
+ debug( "Creating a get config request ( xid = %#x ).", transaction_id );
314
+
315
+ return create_header( transaction_id, OFPT_GET_CONFIG_REQUEST, sizeof( struct ofp_header ) );
316
+ }
317
+
318
+
319
+ buffer *
320
+ create_get_config_reply( const uint32_t transaction_id, const uint16_t flags,
321
+ const uint16_t miss_send_len ) {
322
+ buffer *buffer;
323
+ struct ofp_switch_config *switch_config;
324
+
325
+ debug( "Creating a get config reply ( xid = %#x, flags = %#x, miss_send_len = %u ).",
326
+ transaction_id, flags, miss_send_len );
327
+
328
+ buffer = create_header( transaction_id, OFPT_GET_CONFIG_REPLY, sizeof( struct ofp_switch_config ) );
329
+ assert( buffer != NULL );
330
+
331
+ switch_config = ( struct ofp_switch_config * ) buffer->data;
332
+ switch_config->flags = htons( flags );
333
+ switch_config->miss_send_len = htons( miss_send_len );
334
+
335
+ return buffer;
336
+ }
337
+
338
+
339
+ buffer *
340
+ create_set_config( const uint32_t transaction_id, const uint16_t flags, uint16_t miss_send_len ) {
341
+ debug( "Creating a set config ( xid = %#x, flags = %#x, miss_send_len = %u ).",
342
+ transaction_id, flags, miss_send_len );
343
+
344
+ buffer *set_config = create_header( transaction_id, OFPT_SET_CONFIG, sizeof( struct ofp_switch_config ) );
345
+ assert( set_config != NULL );
346
+
347
+ struct ofp_switch_config *switch_config = ( struct ofp_switch_config * ) set_config->data;
348
+ switch_config->flags = htons( flags );
349
+ switch_config->miss_send_len = htons( miss_send_len );
350
+ return set_config;
351
+ }
352
+
353
+
354
+ buffer *
355
+ create_packet_in( const uint32_t transaction_id, const uint32_t buffer_id, const uint16_t total_len,
356
+ uint16_t in_port, const uint8_t reason, const buffer *data ) {
357
+ uint16_t data_length = 0;
358
+ buffer *buffer;
359
+ struct ofp_packet_in *packet_in;
360
+
361
+ if ( ( data != NULL ) && ( data->length > 0 ) ) {
362
+ data_length = ( uint16_t ) data->length;
363
+ }
364
+
365
+ debug( "Creating a packet-in "
366
+ "( xid = %#x, buffer_id = %#x, total_len = %u, "
367
+ "in_port = %u, reason = %#x, data length = %u ).",
368
+ transaction_id, buffer_id, total_len,
369
+ in_port, reason, data_length );
370
+
371
+ buffer = create_header( transaction_id, OFPT_PACKET_IN,
372
+ ( uint16_t ) ( offsetof( struct ofp_packet_in, data ) + data_length ) );
373
+ assert( buffer != NULL );
374
+
375
+ packet_in = ( struct ofp_packet_in * ) buffer->data;
376
+ packet_in->buffer_id = htonl( buffer_id );
377
+ packet_in->total_len = htons( total_len );
378
+ packet_in->in_port = htons( in_port );
379
+ packet_in->reason = reason;
380
+ packet_in->pad = 0;
381
+
382
+ if ( data_length > 0 ) {
383
+ memcpy( packet_in->data, data->data, data_length );
384
+ }
385
+
386
+ return buffer;
387
+ }
388
+
389
+
390
+ buffer *
391
+ create_flow_removed( const uint32_t transaction_id, const struct ofp_match match,
392
+ const uint64_t cookie, const uint16_t priority,
393
+ const uint8_t reason, const uint32_t duration_sec,
394
+ const uint32_t duration_nsec, const uint16_t idle_timeout,
395
+ const uint64_t packet_count, const uint64_t byte_count ) {
396
+ char match_str[ 1024 ];
397
+ buffer *buffer;
398
+ struct ofp_match m = match;
399
+ struct ofp_flow_removed *flow_removed;
400
+
401
+ // Because match_to_string() is costly, we check logging_level first.
402
+ if ( get_logging_level() >= LOG_DEBUG ) {
403
+ match_to_string( &m, match_str, sizeof( match_str ) );
404
+ debug( "Creating a flow removed "
405
+ "( xid = %#x, match = [%s], cookie = %#" PRIx64 ", priority = %u, "
406
+ "reason = %#x, duration_sec = %u, duration_nsec = %u, "
407
+ "idle_timeout = %u, packet_count = %" PRIu64 ", byte_count = %" PRIu64 " ).",
408
+ transaction_id, match_str, cookie, priority,
409
+ reason, duration_sec, duration_nsec,
410
+ idle_timeout, packet_count, byte_count );
411
+ }
412
+
413
+ buffer = create_header( transaction_id, OFPT_FLOW_REMOVED, sizeof( struct ofp_flow_removed ) );
414
+ assert( buffer != NULL );
415
+
416
+ flow_removed = ( struct ofp_flow_removed * ) buffer->data;
417
+ hton_match( &flow_removed->match, &m );
418
+ flow_removed->cookie = htonll( cookie );
419
+ flow_removed->priority = htons( priority );
420
+ flow_removed->reason = reason;
421
+ memset( &flow_removed->pad, 0, sizeof( flow_removed->pad ) );
422
+ flow_removed->duration_sec = htonl( duration_sec );
423
+ flow_removed->duration_nsec = htonl( duration_nsec );
424
+ flow_removed->idle_timeout = htons( idle_timeout );
425
+ memset( &flow_removed->pad2, 0, sizeof( flow_removed->pad2 ) );
426
+ flow_removed->packet_count = htonll( packet_count );
427
+ flow_removed->byte_count = htonll( byte_count );
428
+
429
+ return buffer;
430
+ }
431
+
432
+
433
+ buffer *
434
+ create_port_status( const uint32_t transaction_id, const uint8_t reason,
435
+ const struct ofp_phy_port desc) {
436
+ char desc_str[ 1024 ];
437
+ buffer *buffer;
438
+ struct ofp_phy_port d = desc;
439
+ struct ofp_port_status *port_status;
440
+
441
+ phy_port_to_string( &d, desc_str, sizeof( desc_str ) );
442
+ debug( "Creating a port status ( xid = %#x, reason = %#x, desc = [%s] ).",
443
+ transaction_id, reason, desc_str );
444
+
445
+ buffer = create_header( transaction_id, OFPT_PORT_STATUS, sizeof( struct ofp_port_status ) );
446
+ assert( buffer != NULL );
447
+
448
+ port_status = ( struct ofp_port_status * ) buffer->data;
449
+ port_status->reason = reason;
450
+ memset( &port_status->pad, 0, sizeof( port_status->pad ) );
451
+ hton_phy_port( &port_status->desc, &d );
452
+
453
+ return buffer;
454
+ }
455
+
456
+
457
+ static uint16_t
458
+ get_actions_length( const openflow_actions *actions ) {
459
+ int actions_length = 0;
460
+ struct ofp_action_header *action_header;
461
+ list_element *action;
462
+
463
+ debug( "Calculating the total length of actions." );
464
+
465
+ assert( actions != NULL );
466
+
467
+ action = actions->list;
468
+ while ( action != NULL ) {
469
+ action_header = ( struct ofp_action_header * ) action->data;
470
+
471
+ if ( ( action_header->type <= OFPAT_ENQUEUE ) || ( action_header->type == OFPAT_VENDOR ) ) {
472
+ actions_length += action_header->len;
473
+ }
474
+ else {
475
+ critical( "Undefined action type ( type = %#x ).", action_header->type );
476
+ assert( 0 );
477
+ }
478
+
479
+ action = action->next;
480
+ }
481
+
482
+ debug( "Total length of actions = %u.", actions_length );
483
+
484
+ if ( actions_length > UINT16_MAX ) {
485
+ critical( "Too many actions ( # of actions = %d, actions length = %u ).",
486
+ actions->n_actions, actions_length );
487
+ assert( 0 );
488
+ }
489
+
490
+ return ( uint16_t ) actions_length;
491
+ }
492
+
493
+
494
+ buffer *
495
+ create_packet_out( const uint32_t transaction_id, const uint32_t buffer_id, const uint16_t in_port,
496
+ const openflow_actions *actions, const buffer *data ) {
497
+ void *a, *d;
498
+ uint16_t length;
499
+ uint16_t data_length = 0;
500
+ uint16_t action_length = 0;
501
+ uint16_t actions_length = 0;
502
+ buffer *buffer;
503
+ struct ofp_packet_out *packet_out;
504
+ struct ofp_action_header *action_header;
505
+ list_element *action;
506
+
507
+ if ( ( data != NULL ) && ( data->length > 0 ) ) {
508
+ data_length = ( uint16_t ) data->length;
509
+ }
510
+
511
+ debug( "Creating a packet-out ( xid = %#x, buffer_id = %#x, in_port = %u, data length = %u ).",
512
+ transaction_id, buffer_id, in_port, data_length );
513
+
514
+ if ( buffer_id == UINT32_MAX ) {
515
+ if ( data == NULL ) {
516
+ die( "An Ethernet frame must be provided if buffer_id is equal to %#x", UINT32_MAX );
517
+ }
518
+ if ( data->length + ETH_FCS_LENGTH < ETH_MINIMUM_LENGTH ) {
519
+ die( "The length of the provided Ethernet frame is shorter than the minimum length of an Ethernet frame (= %d bytes).", ETH_MINIMUM_LENGTH );
520
+ }
521
+ }
522
+
523
+ if ( actions != NULL ) {
524
+ debug( "# of actions = %d.", actions->n_actions );
525
+ actions_length = get_actions_length( actions );
526
+ }
527
+
528
+ length = ( uint16_t ) ( offsetof( struct ofp_packet_out, actions ) + actions_length + data_length );
529
+ buffer = create_header( transaction_id, OFPT_PACKET_OUT, length );
530
+ assert( buffer != NULL );
531
+
532
+ packet_out = ( struct ofp_packet_out * ) buffer->data;
533
+ packet_out->buffer_id = htonl( buffer_id );
534
+ packet_out->in_port = htons( in_port );
535
+ packet_out->actions_len = htons( actions_length );
536
+
537
+ if ( actions_length > 0 ) {
538
+ a = ( void * ) ( ( char * ) buffer->data + offsetof( struct ofp_packet_out, actions ) );
539
+
540
+ action = actions->list;
541
+ while ( action != NULL ) {
542
+ action_header = ( struct ofp_action_header * ) action->data;
543
+ action_length = action_header->len;
544
+ hton_action( ( struct ofp_action_header * ) a, action_header );
545
+ a = ( void * ) ( ( char * ) a + action_length );
546
+ action = action->next;
547
+ }
548
+ }
549
+
550
+ if ( data_length > 0 ) {
551
+ d = ( void * ) ( ( char * ) buffer->data
552
+ + offsetof( struct ofp_packet_out, actions ) + actions_length );
553
+ memcpy( d, data->data, data_length );
554
+ }
555
+
556
+ return buffer;
557
+ }
558
+
559
+
560
+ buffer *
561
+ create_flow_mod( const uint32_t transaction_id, const struct ofp_match match,
562
+ const uint64_t cookie, const uint16_t command,
563
+ const uint16_t idle_timeout, const uint16_t hard_timeout,
564
+ const uint16_t priority, const uint32_t buffer_id,
565
+ const uint16_t out_port, const uint16_t flags,
566
+ const openflow_actions *actions ) {
567
+ void *a;
568
+ char match_str[ 1024 ];
569
+ uint16_t length;
570
+ uint16_t action_length = 0;
571
+ uint16_t actions_length = 0;
572
+ buffer *buffer;
573
+ struct ofp_match m = match;
574
+ struct ofp_flow_mod *flow_mod;
575
+ struct ofp_action_header *action_header;
576
+ list_element *action;
577
+
578
+ // Because match_to_string() is costly, we check logging_level first.
579
+ if ( get_logging_level() >= LOG_DEBUG ) {
580
+ match_to_string( &m, match_str, sizeof( match_str ) );
581
+ debug( "Creating a flow modification "
582
+ "( xid = %#x, match = [%s], cookie = %#" PRIx64 ", command = %#x, "
583
+ "idle_timeout = %u, hard_timeout = %u, priority = %u, "
584
+ "buffer_id = %#x, out_port = %u, flags = %#x ).",
585
+ transaction_id, match_str, cookie, command,
586
+ idle_timeout, hard_timeout, priority,
587
+ buffer_id, out_port, flags );
588
+ }
589
+
590
+ if ( actions != NULL ) {
591
+ debug( "# of actions = %d.", actions->n_actions );
592
+ actions_length = get_actions_length( actions );
593
+ }
594
+
595
+ length = ( uint16_t ) ( offsetof( struct ofp_flow_mod, actions ) + actions_length );
596
+ buffer = create_header( transaction_id, OFPT_FLOW_MOD, length );
597
+ assert( buffer != NULL );
598
+
599
+ flow_mod = ( struct ofp_flow_mod * ) buffer->data;
600
+ hton_match( &flow_mod->match, &m );
601
+ flow_mod->cookie = htonll( cookie );
602
+ flow_mod->command = htons( command );
603
+ flow_mod->idle_timeout = htons( idle_timeout );
604
+ flow_mod->hard_timeout = htons( hard_timeout );
605
+ flow_mod->priority = htons( priority );
606
+ flow_mod->buffer_id = htonl( buffer_id );
607
+ flow_mod->out_port = htons( out_port );
608
+ flow_mod->flags = htons( flags );
609
+
610
+ if ( actions_length > 0 ) {
611
+ a = ( void * ) ( ( char * ) buffer->data + offsetof( struct ofp_flow_mod, actions ) );
612
+
613
+ action = actions->list;
614
+ while ( action != NULL ) {
615
+ action_header = ( struct ofp_action_header * ) action->data;
616
+ action_length = action_header->len;
617
+ hton_action( ( struct ofp_action_header * ) a, action_header );
618
+ a = ( void * ) ( ( char * ) a + action_length );
619
+ action = action->next;
620
+ }
621
+ }
622
+
623
+ return buffer;
624
+ }
625
+
626
+
627
+ buffer *
628
+ create_port_mod( const uint32_t transaction_id, const uint16_t port_no,
629
+ const uint8_t hw_addr[ OFP_ETH_ALEN ], const uint32_t config,
630
+ const uint32_t mask, const uint32_t advertise ) {
631
+ buffer *buffer;
632
+ struct ofp_port_mod *port_mod;
633
+
634
+ debug( "Creating a port modification "
635
+ "( xid = %#x, port_no = %u, hw_addr = %02x:%02x:%02x:%02x:%02x:%02x, "
636
+ "config = %#x, mask = %#x, advertise = %#x ).",
637
+ transaction_id, port_no,
638
+ hw_addr[ 0 ], hw_addr[ 1 ], hw_addr[ 2 ], hw_addr[ 3 ], hw_addr[ 4 ], hw_addr[ 5 ],
639
+ config, mask, advertise );
640
+
641
+ buffer = create_header( transaction_id, OFPT_PORT_MOD, sizeof( struct ofp_port_mod ) );
642
+ assert( buffer != NULL );
643
+
644
+ port_mod = ( struct ofp_port_mod * ) buffer->data;
645
+ port_mod->port_no = htons( port_no );
646
+ memcpy( port_mod->hw_addr, hw_addr, OFP_ETH_ALEN );
647
+ port_mod->config = htonl( config );
648
+ port_mod->mask = htonl( mask );
649
+ port_mod->advertise = htonl( advertise );
650
+ memset( port_mod->pad, 0, sizeof( port_mod->pad ) );
651
+
652
+ return buffer;
653
+ }
654
+
655
+
656
+ static buffer *
657
+ create_stats_request( const uint32_t transaction_id, const uint16_t type,
658
+ const uint16_t length, const uint16_t flags ) {
659
+ buffer *buffer;
660
+ struct ofp_stats_request *stats_request;
661
+
662
+ debug( "Creating a stats request ( xid = %#x, type = %#x, length = %u, flags = %#x ).",
663
+ transaction_id, type, length, flags );
664
+
665
+ buffer = create_header( transaction_id, OFPT_STATS_REQUEST, length );
666
+ assert( buffer != NULL );
667
+
668
+ stats_request = ( struct ofp_stats_request * ) buffer->data;
669
+ stats_request->type = htons( type );
670
+ stats_request->flags = htons( flags );
671
+
672
+ return buffer;
673
+ }
674
+
675
+
676
+ buffer *
677
+ create_desc_stats_request( const uint32_t transaction_id, const uint16_t flags ) {
678
+ debug( "Creating a description stats request ( xid = %#x, flags = %#x ).",
679
+ transaction_id, flags );
680
+
681
+ return create_stats_request( transaction_id, OFPST_DESC,
682
+ sizeof( struct ofp_stats_request ), flags );
683
+ }
684
+
685
+
686
+ buffer *
687
+ create_flow_stats_request( const uint32_t transaction_id, const uint16_t flags,
688
+ const struct ofp_match match, const uint8_t table_id,
689
+ const uint16_t out_port ) {
690
+ char match_str[ 1024 ];
691
+ uint16_t length;
692
+ buffer *buffer;
693
+ struct ofp_match m = match;
694
+ struct ofp_flow_stats_request *flow_stats_request;
695
+
696
+ // Because match_to_string() is costly, we check logging_level first.
697
+ if ( get_logging_level() >= LOG_DEBUG ) {
698
+ match_to_string( &m, match_str, sizeof( match_str ) );
699
+ debug( "Creating a flow stats request ( xid = %#x, flags = %#x, match = [%s], table_id = %u, out_port = %u ).",
700
+ transaction_id, flags, match_str, table_id, out_port );
701
+ }
702
+
703
+ length = ( uint16_t ) ( offsetof( struct ofp_stats_request, body )
704
+ + sizeof( struct ofp_flow_stats_request ) );
705
+ buffer = create_stats_request( transaction_id, OFPST_FLOW, length, flags );
706
+ assert( buffer != NULL );
707
+
708
+ flow_stats_request = ( struct ofp_flow_stats_request * ) ( ( char * ) buffer->data
709
+ + offsetof( struct ofp_stats_request, body ) );
710
+ hton_match( &flow_stats_request->match, &m );
711
+ flow_stats_request->table_id = table_id;
712
+ flow_stats_request->pad = 0;
713
+ flow_stats_request->out_port = htons( out_port );
714
+
715
+ return buffer;
716
+ }
717
+
718
+
719
+ buffer *
720
+ create_aggregate_stats_request( const uint32_t transaction_id,
721
+ const uint16_t flags, const struct ofp_match match,
722
+ const uint8_t table_id, const uint16_t out_port ) {
723
+ char match_str[ 1024 ];
724
+ uint16_t length;
725
+ buffer *buffer;
726
+ struct ofp_match m = match;
727
+ struct ofp_aggregate_stats_request *aggregate_stats_request;
728
+
729
+ // Because match_to_string() is costly, we check logging_level first.
730
+ if ( get_logging_level() >= LOG_DEBUG ) {
731
+ match_to_string( &m, match_str, sizeof( match_str ) );
732
+ debug( "Creating an aggregate stats request ( xid = %#x, flags = %#x, match = [%s], table_id = %u, out_port = %u ).",
733
+ transaction_id, flags, match_str, table_id, out_port );
734
+ }
735
+
736
+ length = ( uint16_t ) ( offsetof( struct ofp_stats_request, body )
737
+ + sizeof( struct ofp_aggregate_stats_request ) );
738
+ buffer = create_stats_request( transaction_id, OFPST_AGGREGATE, length, flags );
739
+ assert( buffer != NULL );
740
+
741
+ aggregate_stats_request = ( struct ofp_aggregate_stats_request * ) ( ( char * ) buffer->data
742
+ + offsetof( struct ofp_stats_request, body ) );
743
+ hton_match( &aggregate_stats_request->match, &m );
744
+ aggregate_stats_request->table_id = table_id;
745
+ aggregate_stats_request->pad = 0;
746
+ aggregate_stats_request->out_port = htons( out_port );
747
+
748
+ return buffer;
749
+ }
750
+
751
+
752
+ buffer *
753
+ create_table_stats_request( const uint32_t transaction_id, const uint16_t flags ) {
754
+ debug( "Creating a table stats request ( xid = %#x, flags = %#x ).", transaction_id, flags );
755
+
756
+ return create_stats_request( transaction_id, OFPST_TABLE,
757
+ sizeof( struct ofp_stats_request ), flags );
758
+ }
759
+
760
+
761
+ buffer *
762
+ create_port_stats_request( const uint32_t transaction_id, const uint16_t flags,
763
+ const uint16_t port_no ) {
764
+ uint16_t length;
765
+ buffer *buffer;
766
+ struct ofp_port_stats_request *port_stats_request;
767
+
768
+ debug( "Creating a port stats request ( xid = %#x, flags = %#x, port_no = %u ).",
769
+ transaction_id, flags, port_no );
770
+
771
+ length = ( uint16_t ) ( offsetof( struct ofp_stats_request, body )
772
+ + sizeof( struct ofp_port_stats_request ) );
773
+ buffer = create_stats_request( transaction_id, OFPST_PORT, length, flags );
774
+ assert( buffer != NULL );
775
+
776
+ port_stats_request = ( struct ofp_port_stats_request * ) ( ( char * ) buffer->data
777
+ + offsetof( struct ofp_stats_request, body ) );
778
+ port_stats_request->port_no = htons( port_no );
779
+ memset( &port_stats_request->pad, 0, sizeof( port_stats_request->pad ) );
780
+
781
+ return buffer;
782
+ }
783
+
784
+
785
+ buffer *
786
+ create_queue_stats_request( const uint32_t transaction_id, const uint16_t flags,
787
+ const uint16_t port_no, const uint32_t queue_id ) {
788
+ uint16_t length;
789
+ buffer *buffer;
790
+ struct ofp_queue_stats_request *queue_stats_request;
791
+
792
+ debug( "Creating a queue stats request ( xid = %#x, flags = %#x, port_no = %u, queue_id = %u ).",
793
+ transaction_id, flags, port_no, queue_id );
794
+
795
+ length = ( uint16_t ) ( offsetof( struct ofp_stats_request, body )
796
+ + sizeof( struct ofp_queue_stats_request ) );
797
+ buffer = create_stats_request( transaction_id, OFPST_QUEUE, length, flags );
798
+ assert( buffer != NULL );
799
+
800
+ queue_stats_request = ( struct ofp_queue_stats_request * ) ( ( char * ) buffer->data
801
+ + offsetof( struct ofp_stats_request, body ) );
802
+ queue_stats_request->port_no = htons( port_no );
803
+ memset( &queue_stats_request->pad, 0, sizeof( queue_stats_request->pad ) );
804
+ queue_stats_request->queue_id = htonl( queue_id );
805
+
806
+ return buffer;
807
+ }
808
+
809
+
810
+ buffer *
811
+ create_vendor_stats_request( const uint32_t transaction_id, const uint16_t flags,
812
+ const uint32_t vendor, const buffer *body ) {
813
+ void *b;
814
+ uint16_t length;
815
+ uint16_t data_length = 0;
816
+ uint32_t *v;
817
+ buffer *buffer;
818
+
819
+ if ( ( body != NULL ) && ( body->length > 0 ) ) {
820
+ data_length = ( uint16_t ) body->length;
821
+ }
822
+
823
+ debug( "Creating a vendor stats request ( xid = %#x, flags = %#x, vendor = %#x, data length = %u ).",
824
+ transaction_id, flags, vendor, data_length );
825
+
826
+ length = ( uint16_t ) ( offsetof( struct ofp_stats_request, body ) + sizeof( uint32_t )
827
+ + data_length );
828
+ buffer = create_stats_request( transaction_id, OFPST_VENDOR, length, flags );
829
+ assert( buffer != NULL );
830
+
831
+ v = ( uint32_t * ) ( ( char * ) buffer->data + offsetof( struct ofp_stats_request, body ) );
832
+ *v = htonl( vendor );
833
+
834
+ if ( data_length > 0 ) {
835
+ b = ( void * ) ( ( char * ) buffer->data
836
+ + offsetof( struct ofp_stats_request, body ) + sizeof( uint32_t ) );
837
+
838
+ memcpy( b, body->data, data_length );
839
+ }
840
+
841
+ return buffer;
842
+ }
843
+
844
+
845
+ static buffer *
846
+ create_stats_reply( const uint32_t transaction_id, const uint16_t type,
847
+ const uint16_t length, const uint16_t flags ) {
848
+ buffer *buffer;
849
+ struct ofp_stats_reply *stats_reply;
850
+
851
+ debug( "Creating a stats reply ( xid = %#x, type = %#x, length = %u, flags = %#x ).",
852
+ transaction_id, type, length, flags );
853
+
854
+ buffer = create_header( transaction_id, OFPT_STATS_REPLY, length );
855
+ assert( buffer != NULL );
856
+
857
+ stats_reply = ( struct ofp_stats_reply * ) buffer->data;
858
+ stats_reply->type = htons( type );
859
+ stats_reply->flags = htons( flags );
860
+
861
+ return buffer;
862
+ }
863
+
864
+
865
+ buffer *
866
+ create_desc_stats_reply( const uint32_t transaction_id, const uint16_t flags,
867
+ const char mfr_desc[ DESC_STR_LEN ],
868
+ const char hw_desc[ DESC_STR_LEN ],
869
+ const char sw_desc[ DESC_STR_LEN ],
870
+ const char serial_num[ SERIAL_NUM_LEN ],
871
+ const char dp_desc[ DESC_STR_LEN ] ) {
872
+ uint16_t length;
873
+ buffer *buffer;
874
+ struct ofp_stats_reply *stats_reply;
875
+ struct ofp_desc_stats *desc_stats;
876
+
877
+ debug( "Creating a description stats reply "
878
+ "( xid = %#x, flags = %#x, mfr_desc = %s, hw_desc = %s, sw_desc = %s, serial_num = %s, dp_desc = %s ).",
879
+ transaction_id, flags, mfr_desc, hw_desc, sw_desc, serial_num, dp_desc );
880
+
881
+ length = ( uint16_t ) ( offsetof( struct ofp_stats_reply, body )
882
+ + sizeof( struct ofp_desc_stats ) );
883
+ buffer = create_stats_reply( transaction_id, OFPST_DESC, length, flags );
884
+ assert( buffer != NULL );
885
+
886
+ stats_reply = ( struct ofp_stats_reply * ) buffer->data;
887
+ desc_stats = ( struct ofp_desc_stats * ) stats_reply->body;
888
+ memcpy( desc_stats->mfr_desc, mfr_desc, DESC_STR_LEN );
889
+ memcpy( desc_stats->hw_desc, hw_desc, DESC_STR_LEN );
890
+ memcpy( desc_stats->sw_desc, sw_desc, DESC_STR_LEN );
891
+ memcpy( desc_stats->serial_num, serial_num, DESC_STR_LEN );
892
+ memcpy( desc_stats->dp_desc, dp_desc, DESC_STR_LEN );
893
+
894
+ return buffer;
895
+ }
896
+
897
+
898
+ buffer *
899
+ create_flow_stats_reply( const uint32_t transaction_id, const uint16_t flags,
900
+ const list_element *flows_stats_head ) {
901
+ int n_flows = 0;
902
+ uint16_t length = 0;
903
+ buffer *buffer;
904
+ list_element *f = NULL;
905
+ list_element *flow = NULL;
906
+ struct ofp_stats_reply *stats_reply;
907
+ struct ofp_flow_stats *fs, *flow_stats;
908
+
909
+ debug( "Creating a flow stats reply ( xid = %#x, flags = %#x ).", transaction_id, flags );
910
+
911
+ if ( flows_stats_head != NULL ) {
912
+ f = ( list_element * ) xmalloc( sizeof( list_element ) );
913
+ memcpy( f, flows_stats_head, sizeof( list_element ) );
914
+ }
915
+
916
+ flow = f;
917
+ while ( flow != NULL ) {
918
+ flow_stats = flow->data;
919
+ length = ( uint16_t ) ( length + flow_stats->length );
920
+ n_flows++;
921
+ flow = flow->next;
922
+ }
923
+
924
+ debug( "# of flows = %u.", n_flows );
925
+
926
+ length = ( uint16_t ) ( offsetof( struct ofp_stats_reply, body ) + length );
927
+
928
+ buffer = create_stats_reply( transaction_id, OFPST_FLOW, length, flags );
929
+ assert( buffer != NULL );
930
+
931
+ stats_reply = ( struct ofp_stats_reply * ) buffer->data;
932
+ flow_stats = ( struct ofp_flow_stats * ) stats_reply->body;
933
+
934
+ flow = f;
935
+ while ( flow != NULL ) {
936
+ fs = ( struct ofp_flow_stats * ) flow->data;
937
+ hton_flow_stats( flow_stats, fs );
938
+ flow_stats = ( struct ofp_flow_stats * ) ( ( char * ) flow_stats + fs->length );
939
+ flow = flow->next;
940
+ }
941
+
942
+ if ( f != NULL ) {
943
+ xfree( f );
944
+ }
945
+
946
+ return buffer;
947
+ }
948
+
949
+
950
+ buffer *
951
+ create_aggregate_stats_reply( const uint32_t transaction_id, const uint16_t flags,
952
+ const uint64_t packet_count, const uint64_t byte_count,
953
+ const uint32_t flow_count ) {
954
+ uint16_t length;
955
+ buffer *buffer;
956
+ struct ofp_stats_reply *stats_reply;
957
+ struct ofp_aggregate_stats_reply *aggregate_stats_reply;
958
+
959
+ debug( "Creating an aggregate stats reply "
960
+ "( xid = %#x, flags = %#x, packet_count = %" PRIu64 ", byte_count = %" PRIu64 ", flow_count = %u ).",
961
+ transaction_id, flags, packet_count, byte_count, flow_count );
962
+
963
+ length = ( uint16_t ) ( offsetof( struct ofp_stats_reply, body )
964
+ + sizeof( struct ofp_aggregate_stats_reply ) );
965
+ buffer = create_stats_reply( transaction_id, OFPST_AGGREGATE, length, flags );
966
+ assert( buffer != NULL );
967
+
968
+ stats_reply = ( struct ofp_stats_reply * ) buffer->data;
969
+ aggregate_stats_reply = ( struct ofp_aggregate_stats_reply * ) stats_reply->body;
970
+ aggregate_stats_reply->packet_count = htonll( packet_count );
971
+ aggregate_stats_reply->byte_count = htonll( byte_count );
972
+ aggregate_stats_reply->flow_count = htonl( flow_count );
973
+ memset( &aggregate_stats_reply->pad, 0, sizeof( aggregate_stats_reply->pad ) );
974
+
975
+ return buffer;
976
+ }
977
+
978
+
979
+ buffer *
980
+ create_table_stats_reply( const uint32_t transaction_id, const uint16_t flags,
981
+ const list_element *table_stats_head ) {
982
+ uint16_t length;
983
+ uint16_t n_tables = 0;
984
+ buffer *buffer;
985
+ list_element *t = NULL;
986
+ list_element *table = NULL;
987
+ struct ofp_stats_reply *stats_reply;
988
+ struct ofp_table_stats *ts, *table_stats;
989
+
990
+ debug( "Creating a table stats reply ( xid = %#x, flags = %#x ).", transaction_id, flags );
991
+
992
+ if ( table_stats_head != NULL ) {
993
+ t = ( list_element * ) xmalloc( sizeof( list_element ) );
994
+ memcpy( t, table_stats_head, sizeof( list_element ) );
995
+ }
996
+
997
+ table = t;
998
+ while ( table != NULL ) {
999
+ n_tables++;
1000
+ table = table->next;
1001
+ }
1002
+
1003
+ debug( "# of tables = %u.", n_tables );
1004
+
1005
+ length = ( uint16_t ) ( offsetof( struct ofp_stats_reply, body )
1006
+ + sizeof( struct ofp_table_stats ) * n_tables );
1007
+ buffer = create_stats_reply( transaction_id, OFPST_TABLE, length, flags );
1008
+ assert( buffer != NULL );
1009
+
1010
+ stats_reply = ( struct ofp_stats_reply * ) buffer->data;
1011
+ table_stats = ( struct ofp_table_stats * ) stats_reply->body;
1012
+
1013
+ table = t;
1014
+ while ( table != NULL ) {
1015
+ ts = ( struct ofp_table_stats * ) table->data;
1016
+ hton_table_stats( table_stats, ts );
1017
+ table = table->next;
1018
+ table_stats++;
1019
+ }
1020
+
1021
+ if ( t != NULL ) {
1022
+ xfree( t );
1023
+ }
1024
+
1025
+ return buffer;
1026
+ }
1027
+
1028
+
1029
+ buffer *
1030
+ create_port_stats_reply( const uint32_t transaction_id, const uint16_t flags,
1031
+ const list_element *port_stats_head ) {
1032
+ uint16_t length;
1033
+ uint16_t n_ports = 0;
1034
+ buffer *buffer;
1035
+ list_element *p = NULL;
1036
+ list_element *port = NULL;
1037
+ struct ofp_stats_reply *stats_reply;
1038
+ struct ofp_port_stats *ps, *port_stats;
1039
+
1040
+ debug( "Creating a port stats reply ( xid = %#x, flags = %#x ).", transaction_id, flags );
1041
+
1042
+ if ( port_stats_head != NULL ) {
1043
+ p = ( list_element * ) xmalloc( sizeof( list_element ) );
1044
+ memcpy( p, port_stats_head, sizeof( list_element ) );
1045
+ }
1046
+
1047
+ port = p;
1048
+ while ( port != NULL ) {
1049
+ n_ports++;
1050
+ port = port->next;
1051
+ }
1052
+
1053
+ debug( "# of ports = %u.", n_ports );
1054
+
1055
+ length = ( uint16_t ) ( offsetof( struct ofp_stats_reply, body )
1056
+ + sizeof( struct ofp_port_stats ) * n_ports );
1057
+ buffer = create_stats_reply( transaction_id, OFPST_PORT, length, flags );
1058
+ assert( buffer != NULL );
1059
+
1060
+ stats_reply = ( struct ofp_stats_reply * ) buffer->data;
1061
+ port_stats = ( struct ofp_port_stats * ) stats_reply->body;
1062
+
1063
+ port = p;
1064
+ while ( port != NULL ) {
1065
+ ps = ( struct ofp_port_stats * ) port->data;
1066
+ hton_port_stats( port_stats, ps );
1067
+ port = port->next;
1068
+ port_stats++;
1069
+ }
1070
+
1071
+ if ( p != NULL ) {
1072
+ xfree( p );
1073
+ }
1074
+
1075
+ return buffer;
1076
+ }
1077
+
1078
+
1079
+ buffer *
1080
+ create_queue_stats_reply( const uint32_t transaction_id, const uint16_t flags,
1081
+ const list_element *queue_stats_head ) {
1082
+ uint16_t length;
1083
+ uint16_t n_queues = 0;
1084
+ buffer *buffer;
1085
+ list_element *q = NULL;
1086
+ list_element *queue = NULL;
1087
+ struct ofp_stats_reply *stats_reply;
1088
+ struct ofp_queue_stats *qs, *queue_stats;
1089
+
1090
+ debug( "Creating a queue stats reply ( xid = %#x, flags = %#x ).", transaction_id, flags );
1091
+
1092
+ if ( queue_stats_head != NULL ) {
1093
+ q = ( list_element * ) xmalloc( sizeof( list_element ) );
1094
+ memcpy( q, queue_stats_head, sizeof( list_element ) );
1095
+ }
1096
+
1097
+ queue = q;
1098
+ while ( queue != NULL ) {
1099
+ n_queues++;
1100
+ queue = queue->next;
1101
+ }
1102
+
1103
+ debug( "# of queues = %u.", n_queues );
1104
+
1105
+ length = ( uint16_t ) ( offsetof( struct ofp_stats_reply, body )
1106
+ + sizeof( struct ofp_queue_stats ) * n_queues );
1107
+ buffer = create_stats_reply( transaction_id, OFPST_QUEUE, length, flags );
1108
+ assert( buffer != NULL );
1109
+
1110
+ stats_reply = ( struct ofp_stats_reply * ) buffer->data;
1111
+ queue_stats = ( struct ofp_queue_stats * ) stats_reply->body;
1112
+
1113
+ queue = q;
1114
+ while ( queue != NULL ) {
1115
+ qs = ( struct ofp_queue_stats * ) queue->data;
1116
+ hton_queue_stats( queue_stats, qs );
1117
+ queue = queue->next;
1118
+ queue_stats++;
1119
+ }
1120
+
1121
+ if ( q != NULL ) {
1122
+ xfree( q );
1123
+ }
1124
+
1125
+ return buffer;
1126
+ }
1127
+
1128
+
1129
+ buffer *
1130
+ create_vendor_stats_reply( const uint32_t transaction_id, const uint16_t flags,
1131
+ const uint32_t vendor, const buffer *body ) {
1132
+ void *b;
1133
+ uint16_t length;
1134
+ uint16_t data_length = 0;
1135
+ uint32_t *v;
1136
+ buffer *buffer;
1137
+ struct ofp_stats_reply *stats_reply;
1138
+
1139
+ if ( ( body != NULL ) && ( body->length > 0 ) ) {
1140
+ data_length = ( uint16_t ) body->length;
1141
+ }
1142
+
1143
+ debug( "Creating a vendor stats reply ( xid = %#x, flags = %#x, vendor = %#x, data length = %u ).",
1144
+ transaction_id, flags, vendor, data_length );
1145
+
1146
+ length = ( uint16_t ) ( offsetof( struct ofp_stats_reply, body )
1147
+ + sizeof( uint32_t ) + data_length );
1148
+ buffer = create_stats_reply( transaction_id, OFPST_VENDOR, length, flags );
1149
+ assert( buffer != NULL );
1150
+
1151
+ stats_reply = ( struct ofp_stats_reply * ) buffer->data;
1152
+ v = ( uint32_t * ) stats_reply->body;
1153
+ *v = htonl( vendor );
1154
+
1155
+ if ( data_length > 0 ) {
1156
+ b = ( void * ) ( ( char * ) v + sizeof( uint32_t ) );
1157
+ memcpy( b, body->data, data_length );
1158
+ }
1159
+
1160
+ return buffer;
1161
+ }
1162
+
1163
+
1164
+ buffer *
1165
+ create_barrier_request( const uint32_t transaction_id ) {
1166
+ debug( "Creating a barrier request ( xid = %#x ).", transaction_id );
1167
+
1168
+ return create_header( transaction_id, OFPT_BARRIER_REQUEST, sizeof( struct ofp_header ) );
1169
+ }
1170
+
1171
+
1172
+ buffer *
1173
+ create_barrier_reply( const uint32_t transaction_id ) {
1174
+ debug( "Creating a barrier reply ( xid = %#x ).", transaction_id );
1175
+
1176
+ return create_header( transaction_id, OFPT_BARRIER_REPLY, sizeof( struct ofp_header ) );
1177
+ }
1178
+
1179
+
1180
+ buffer *
1181
+ create_queue_get_config_request( const uint32_t transaction_id, const uint16_t port ) {
1182
+ buffer *buffer;
1183
+ struct ofp_queue_get_config_request *queue_get_config_request;
1184
+
1185
+ debug( "Creating a queue get config request ( xid = %#x, port = %u ).", transaction_id, port );
1186
+
1187
+ buffer = create_header( transaction_id, OFPT_QUEUE_GET_CONFIG_REQUEST,
1188
+ sizeof( struct ofp_queue_get_config_request ) );
1189
+ assert( buffer != NULL );
1190
+
1191
+ queue_get_config_request = ( struct ofp_queue_get_config_request * ) buffer->data;
1192
+ queue_get_config_request->port = htons( port );
1193
+ memset( queue_get_config_request->pad, 0, sizeof( queue_get_config_request->pad ) );
1194
+
1195
+ return buffer;
1196
+ }
1197
+
1198
+
1199
+ buffer *
1200
+ create_queue_get_config_reply( const uint32_t transaction_id, const uint16_t port,
1201
+ const list_element *queues ) {
1202
+ uint16_t length;
1203
+ uint16_t n_queues = 0;
1204
+ uint16_t queues_length = 0;
1205
+ buffer *buffer;
1206
+ list_element *q, *queue;
1207
+ struct ofp_queue_get_config_reply *queue_get_config_reply;
1208
+ struct ofp_packet_queue *pq, *packet_queue;
1209
+
1210
+ debug( "Creating a queue get config reply ( xid = %#x, port = %u ).", transaction_id, port );
1211
+
1212
+ #ifndef UNIT_TESTING
1213
+ assert( queues != NULL );
1214
+ #endif
1215
+
1216
+ if ( queues != NULL ) {
1217
+ q = ( list_element * ) xmalloc( sizeof( list_element ) );
1218
+ memcpy( q, queues, sizeof( list_element ) );
1219
+
1220
+ queue = q;
1221
+ while ( queue != NULL ) {
1222
+ packet_queue = ( struct ofp_packet_queue * ) queue->data;
1223
+ queues_length = ( uint16_t ) ( queues_length + packet_queue->len );
1224
+ n_queues++;
1225
+ queue = queue->next;
1226
+ }
1227
+ }
1228
+
1229
+ debug( "# of queues = %u.", n_queues );
1230
+
1231
+ length = ( uint16_t ) ( offsetof( struct ofp_queue_get_config_reply, queues ) + queues_length );
1232
+ buffer = create_header( transaction_id, OFPT_QUEUE_GET_CONFIG_REPLY, length );
1233
+ assert( buffer != NULL );
1234
+
1235
+ queue_get_config_reply = ( struct ofp_queue_get_config_reply * ) buffer->data;
1236
+ queue_get_config_reply->port = htons( port );
1237
+ memset( &queue_get_config_reply->pad, 0, sizeof( queue_get_config_reply->pad ) );
1238
+ packet_queue = ( struct ofp_packet_queue * ) queue_get_config_reply->queues;
1239
+
1240
+ if ( n_queues ) {
1241
+ queue = q;
1242
+ while ( queue != NULL ) {
1243
+ pq = ( struct ofp_packet_queue * ) queue->data;
1244
+
1245
+ hton_packet_queue( packet_queue, pq );
1246
+
1247
+ packet_queue = ( struct ofp_packet_queue * ) ( ( char * ) packet_queue + pq->len );
1248
+ queue = queue->next;
1249
+ }
1250
+
1251
+ xfree( q );
1252
+ }
1253
+
1254
+ return buffer;
1255
+ }
1256
+
1257
+
1258
+ uint32_t
1259
+ get_transaction_id( void ) {
1260
+ debug( "Generating a transaction id." );
1261
+
1262
+ pthread_mutex_lock( &transaction_id_mutex );
1263
+
1264
+ if ( ( transaction_id & 0xffff ) == 0xffff ) {
1265
+ transaction_id = transaction_id & 0xffff0000;
1266
+ }
1267
+ else {
1268
+ transaction_id++;
1269
+ }
1270
+
1271
+ pthread_mutex_unlock( &transaction_id_mutex );
1272
+
1273
+ debug( "Transaction id = %#x.", transaction_id );
1274
+
1275
+ return transaction_id;
1276
+ }
1277
+
1278
+
1279
+ uint64_t
1280
+ get_cookie( void ) {
1281
+ debug( "Generating a cookie." );
1282
+
1283
+ pthread_mutex_lock( &cookie_mutex );
1284
+
1285
+ if ( ( cookie & 0x0000ffffffffffffULL ) == 0x0000ffffffffffffULL ) {
1286
+ cookie = cookie & 0xffff000000000000ULL;
1287
+ }
1288
+ else {
1289
+ cookie++;
1290
+ }
1291
+
1292
+ pthread_mutex_unlock( &cookie_mutex );
1293
+
1294
+ debug( "Cookie = %#" PRIx64 ".", cookie );
1295
+
1296
+ return cookie;
1297
+ }
1298
+
1299
+
1300
+ openflow_actions *
1301
+ create_actions() {
1302
+ openflow_actions *actions;
1303
+
1304
+ debug( "Creating an empty actions list." );
1305
+
1306
+ actions = ( openflow_actions * ) xmalloc( sizeof( openflow_actions ) );
1307
+
1308
+ if ( create_list( &actions->list ) == false ) {
1309
+ assert( 0 );
1310
+ }
1311
+
1312
+ actions->n_actions = 0;
1313
+
1314
+ return actions;
1315
+ }
1316
+
1317
+
1318
+ bool
1319
+ delete_actions( openflow_actions *actions ) {
1320
+ list_element *element;
1321
+
1322
+ debug( "Deleting an actions list." );
1323
+
1324
+ assert( actions != NULL );
1325
+
1326
+ debug( "# of actions = %d.", actions->n_actions );
1327
+
1328
+ element = actions->list;
1329
+ while ( element != NULL ) {
1330
+ xfree( element->data );
1331
+ element = element->next;
1332
+ }
1333
+
1334
+ delete_list( actions->list );
1335
+ xfree( actions );
1336
+
1337
+ return true;
1338
+ }
1339
+
1340
+
1341
+ bool
1342
+ append_action_output( openflow_actions *actions, const uint16_t port, const uint16_t max_len ) {
1343
+ bool ret;
1344
+ struct ofp_action_output *action_output;
1345
+
1346
+ debug( "Appending an output action ( port = %u, max_len = %u ).", port, max_len );
1347
+
1348
+ assert( actions != NULL );
1349
+
1350
+ action_output = ( struct ofp_action_output * ) xcalloc( 1, sizeof( struct ofp_action_output ) );
1351
+ action_output->type = OFPAT_OUTPUT;
1352
+ action_output->len = sizeof( struct ofp_action_output );
1353
+ action_output->port = port;
1354
+ action_output->max_len = max_len;
1355
+
1356
+ ret = append_to_tail( &actions->list, ( void * ) action_output );
1357
+ if ( ret ) {
1358
+ actions->n_actions++;
1359
+ }
1360
+
1361
+ return ret;
1362
+ }
1363
+
1364
+
1365
+ bool
1366
+ append_action_set_vlan_vid( openflow_actions *actions, const uint16_t vlan_vid ) {
1367
+ bool ret;
1368
+ struct ofp_action_vlan_vid *action_vlan_vid;
1369
+
1370
+ debug( "Appending a set vlan action ( vlan_vid = %#x ).", vlan_vid );
1371
+
1372
+ assert( actions != NULL );
1373
+ assert( ( vlan_vid & ~VLAN_VID_MASK ) == 0 );
1374
+
1375
+ action_vlan_vid = ( struct ofp_action_vlan_vid * ) xcalloc( 1, sizeof( struct ofp_action_vlan_vid ) );
1376
+ action_vlan_vid->type = OFPAT_SET_VLAN_VID;
1377
+ action_vlan_vid->len = sizeof( struct ofp_action_vlan_vid );
1378
+ action_vlan_vid->vlan_vid = vlan_vid;
1379
+
1380
+ ret = append_to_tail( &actions->list, ( void * ) action_vlan_vid );
1381
+ if ( ret ) {
1382
+ actions->n_actions++;
1383
+ }
1384
+
1385
+ return ret;
1386
+ }
1387
+
1388
+
1389
+ bool
1390
+ append_action_set_vlan_pcp( openflow_actions *actions, const uint8_t vlan_pcp ) {
1391
+ bool ret;
1392
+ struct ofp_action_vlan_pcp *action_vlan_pcp;
1393
+
1394
+ debug( "Appending a set vlan pcp action ( vlan_pcp = %#x ).", vlan_pcp );
1395
+
1396
+ assert( actions != NULL );
1397
+ assert( ( vlan_pcp & ~VLAN_PCP_MASK ) == 0 );
1398
+
1399
+ action_vlan_pcp = ( struct ofp_action_vlan_pcp * ) xcalloc( 1, sizeof( struct ofp_action_vlan_pcp ) );
1400
+ action_vlan_pcp->type = OFPAT_SET_VLAN_PCP;
1401
+ action_vlan_pcp->len = sizeof( struct ofp_action_vlan_pcp );
1402
+ action_vlan_pcp->vlan_pcp = vlan_pcp;
1403
+
1404
+ ret = append_to_tail( &actions->list, ( void * ) action_vlan_pcp );
1405
+ if ( ret ) {
1406
+ actions->n_actions++;
1407
+ }
1408
+
1409
+ return ret;
1410
+ }
1411
+
1412
+
1413
+ bool
1414
+ append_action_strip_vlan( openflow_actions *actions ) {
1415
+ bool ret;
1416
+ struct ofp_action_header *action_strip_vlan;
1417
+
1418
+ debug( "Appending a strip vlan action." );
1419
+
1420
+ assert( actions != NULL );
1421
+
1422
+ action_strip_vlan = ( struct ofp_action_header * ) xcalloc( 1, sizeof( struct ofp_action_header ) );
1423
+ action_strip_vlan->type = OFPAT_STRIP_VLAN;
1424
+ action_strip_vlan->len = sizeof( struct ofp_action_header );
1425
+
1426
+ ret = append_to_tail( &actions->list, ( void * ) action_strip_vlan );
1427
+ if ( ret ) {
1428
+ actions->n_actions++;
1429
+ }
1430
+
1431
+ return ret;
1432
+ }
1433
+
1434
+
1435
+ static bool
1436
+ append_action_set_dl_addr( openflow_actions *actions, const uint16_t type,
1437
+ const uint8_t hw_addr[ OFP_ETH_ALEN ] ) {
1438
+ bool ret;
1439
+ struct ofp_action_dl_addr *action_dl_addr;
1440
+
1441
+ debug( "Appending a set dl_src/dl_dst action ( type = %#x, hw_addr = %02x:%02x:%02x:%02x:%02x:%02x ).",
1442
+ type, hw_addr[ 0 ], hw_addr[ 1 ], hw_addr[ 2 ], hw_addr[ 3 ], hw_addr[ 4 ], hw_addr[ 5 ] );
1443
+
1444
+ assert( actions != NULL );
1445
+
1446
+ action_dl_addr = ( struct ofp_action_dl_addr * ) xcalloc( 1, sizeof( struct ofp_action_dl_addr ) );
1447
+ action_dl_addr->type = type;
1448
+ action_dl_addr->len = sizeof( struct ofp_action_dl_addr );
1449
+ memcpy( action_dl_addr->dl_addr, hw_addr, OFP_ETH_ALEN );
1450
+
1451
+ ret = append_to_tail( &actions->list, ( void * ) action_dl_addr );
1452
+ if ( ret ) {
1453
+ actions->n_actions++;
1454
+ }
1455
+
1456
+ return ret;
1457
+ }
1458
+
1459
+
1460
+ bool
1461
+ append_action_set_dl_src( openflow_actions *actions, const uint8_t hw_addr[ OFP_ETH_ALEN ] ) {
1462
+ debug( "Appending a set dl_src action ( hw_addr = %02x:%02x:%02x:%02x:%02x:%02x ).",
1463
+ hw_addr[ 0 ], hw_addr[ 1 ], hw_addr[ 2 ], hw_addr[ 3 ], hw_addr[ 4 ], hw_addr[ 5 ] );
1464
+
1465
+ assert( actions != NULL );
1466
+ return append_action_set_dl_addr( actions, OFPAT_SET_DL_SRC, hw_addr );
1467
+ }
1468
+
1469
+
1470
+ bool
1471
+ append_action_set_dl_dst( openflow_actions *actions, const uint8_t hw_addr[ OFP_ETH_ALEN ] ) {
1472
+ debug( "Appending a set dl_dst action ( hw_addr = %02x:%02x:%02x:%02x:%02x:%02x ).",
1473
+ hw_addr[ 0 ], hw_addr[ 1 ], hw_addr[ 2 ], hw_addr[ 3 ], hw_addr[ 4 ], hw_addr[ 5 ] );
1474
+
1475
+ assert( actions != NULL );
1476
+ return append_action_set_dl_addr( actions, OFPAT_SET_DL_DST, hw_addr );
1477
+ }
1478
+
1479
+
1480
+ static bool
1481
+ append_action_set_nw_addr( openflow_actions *actions, const uint16_t type, const uint32_t nw_addr ) {
1482
+ bool ret;
1483
+ char addr_str[ 16 ];
1484
+ struct in_addr addr;
1485
+ struct ofp_action_nw_addr *action_nw_addr;
1486
+
1487
+ addr.s_addr = htonl( nw_addr );
1488
+ memset( addr_str, '\0', sizeof( addr_str ) );
1489
+ inet_ntop( AF_INET, &addr, addr_str, sizeof( addr_str ) );
1490
+ debug( "Appending a set nw_src/nw_dst action ( type = %#x, nw_addr = %s ).", type, addr_str );
1491
+
1492
+ assert( actions != NULL );
1493
+
1494
+ action_nw_addr = ( struct ofp_action_nw_addr * ) xcalloc( 1, sizeof( struct ofp_action_nw_addr ) );
1495
+ action_nw_addr->type = type;
1496
+ action_nw_addr->len = sizeof( struct ofp_action_nw_addr );
1497
+ action_nw_addr->nw_addr = nw_addr;
1498
+
1499
+ ret = append_to_tail( &actions->list, ( void * ) action_nw_addr );
1500
+ if ( ret ) {
1501
+ actions->n_actions++;
1502
+ }
1503
+
1504
+ return ret;
1505
+ }
1506
+
1507
+
1508
+ bool
1509
+ append_action_set_nw_src( openflow_actions *actions, const uint32_t nw_addr ) {
1510
+ char addr_str[ 16 ];
1511
+ struct in_addr addr;
1512
+
1513
+ addr.s_addr = htonl( nw_addr );
1514
+ memset( addr_str, '\0', sizeof( addr_str ) );
1515
+ inet_ntop( AF_INET, &addr, addr_str, sizeof( addr_str ) );
1516
+ debug( "Appending a set nw_src action ( nw_addr = %s ).", addr_str );
1517
+
1518
+ assert( actions != NULL );
1519
+ return append_action_set_nw_addr( actions, OFPAT_SET_NW_SRC, nw_addr );
1520
+ }
1521
+
1522
+
1523
+ bool
1524
+ append_action_set_nw_dst( openflow_actions *actions, const uint32_t nw_addr ) {
1525
+ char addr_str[ 16 ];
1526
+ struct in_addr addr;
1527
+
1528
+ addr.s_addr = htonl( nw_addr );
1529
+ memset( addr_str, '\0', sizeof( addr_str ) );
1530
+ inet_ntop( AF_INET, &addr, addr_str, sizeof( addr_str ) );
1531
+ debug( "Appending a set nw_dst action ( nw_addr = %s ).", addr_str );
1532
+
1533
+ assert( actions != NULL );
1534
+ return append_action_set_nw_addr( actions, OFPAT_SET_NW_DST, nw_addr );
1535
+ }
1536
+
1537
+
1538
+ bool
1539
+ append_action_set_nw_tos( openflow_actions *actions, const uint8_t nw_tos ) {
1540
+ bool ret;
1541
+ struct ofp_action_nw_tos *action_nw_tos;
1542
+
1543
+ debug( "Appending a set nw_tos action ( nw_tos = %#x ).", nw_tos );
1544
+
1545
+ assert( actions != NULL );
1546
+ assert( ( nw_tos & ~NW_TOS_MASK ) == 0 );
1547
+
1548
+ action_nw_tos = ( struct ofp_action_nw_tos * ) xcalloc( 1, sizeof( struct ofp_action_nw_tos ) );
1549
+ action_nw_tos->type = OFPAT_SET_NW_TOS;
1550
+ action_nw_tos->len = sizeof( struct ofp_action_nw_tos );
1551
+ action_nw_tos->nw_tos = nw_tos;
1552
+
1553
+ ret = append_to_tail( &actions->list, ( void * ) action_nw_tos );
1554
+ if ( ret ) {
1555
+ actions->n_actions++;
1556
+ }
1557
+
1558
+ return ret;
1559
+ }
1560
+
1561
+
1562
+ static bool
1563
+ append_action_set_tp_port( openflow_actions *actions, const uint16_t type, const uint16_t tp_port ) {
1564
+ bool ret;
1565
+ struct ofp_action_tp_port *action_tp_port;
1566
+
1567
+ debug( "Appending a set tp_src/tp_dst action ( type = %#x, tp_port = %u ).", type, tp_port );
1568
+
1569
+ assert( actions != NULL );
1570
+
1571
+ action_tp_port = ( struct ofp_action_tp_port * ) xcalloc( 1, sizeof( struct ofp_action_tp_port ) );
1572
+ action_tp_port->type = type;
1573
+ action_tp_port->len = sizeof( struct ofp_action_tp_port );
1574
+ action_tp_port->tp_port = tp_port;
1575
+
1576
+ ret = append_to_tail( &actions->list, ( void * ) action_tp_port );
1577
+ if ( ret ) {
1578
+ actions->n_actions++;
1579
+ }
1580
+
1581
+ return ret;
1582
+ }
1583
+
1584
+
1585
+ bool
1586
+ append_action_set_tp_src( openflow_actions *actions, const uint16_t tp_port ) {
1587
+ debug( "Appending a set tp_src action ( tp_port = %u ).", tp_port );
1588
+
1589
+ assert( actions != NULL );
1590
+ return append_action_set_tp_port( actions, OFPAT_SET_TP_SRC, tp_port );
1591
+ }
1592
+
1593
+
1594
+ bool
1595
+ append_action_set_tp_dst( openflow_actions *actions, const uint16_t tp_port ) {
1596
+ debug( "Appending a set tp_dst action ( tp_port = %u ).", tp_port );
1597
+
1598
+ assert( actions != NULL );
1599
+ return append_action_set_tp_port( actions, OFPAT_SET_TP_DST, tp_port );
1600
+ }
1601
+
1602
+
1603
+ bool
1604
+ append_action_enqueue( openflow_actions *actions, const uint16_t port, const uint32_t queue_id ) {
1605
+ bool ret;
1606
+ struct ofp_action_enqueue *action_enqueue;
1607
+
1608
+ debug( "Appending an enqueue action ( port = %u, queue_id = %u ).", port, queue_id );
1609
+
1610
+ assert( actions != NULL );
1611
+
1612
+ action_enqueue = ( struct ofp_action_enqueue * ) xcalloc( 1, sizeof( struct ofp_action_enqueue ) );
1613
+ action_enqueue->type = OFPAT_ENQUEUE;
1614
+ action_enqueue->len = sizeof( struct ofp_action_enqueue );
1615
+ action_enqueue->port = port;
1616
+ action_enqueue->queue_id = queue_id;
1617
+
1618
+ ret = append_to_tail( &actions->list, ( void * ) action_enqueue );
1619
+ if ( ret ) {
1620
+ actions->n_actions++;
1621
+ }
1622
+
1623
+ return ret;
1624
+ }
1625
+
1626
+
1627
+ bool
1628
+ append_action_vendor( openflow_actions *actions, const uint32_t vendor, const buffer *body ) {
1629
+ bool ret;
1630
+ uint16_t body_length = 0;
1631
+ struct ofp_action_vendor_header *action_vendor;
1632
+
1633
+ if ( ( body != NULL ) && ( body->length > 0 ) ) {
1634
+ body_length = ( uint16_t ) body->length;
1635
+ }
1636
+
1637
+ debug( "Appending a vendor action ( vendor = %#" PRIx64 ", body length = %u ).", vendor, body_length );
1638
+
1639
+ assert( actions != NULL );
1640
+
1641
+ action_vendor = ( struct ofp_action_vendor_header * )
1642
+ xcalloc( 1, sizeof( struct ofp_action_vendor_header ) + body_length );
1643
+ action_vendor->type = OFPAT_VENDOR;
1644
+ action_vendor->len = ( uint16_t ) ( sizeof( struct ofp_action_vendor_header ) + body_length );
1645
+ action_vendor->vendor = vendor;
1646
+
1647
+ ret = append_to_tail( &actions->list, ( void * ) action_vendor );
1648
+ if ( ret ) {
1649
+ actions->n_actions++;
1650
+ }
1651
+
1652
+ return ret;
1653
+ }
1654
+
1655
+
1656
+ static int
1657
+ validate_header( const buffer *message, const uint8_t type,
1658
+ const uint16_t min_length, const uint16_t max_length ) {
1659
+ struct ofp_header *header;
1660
+
1661
+ assert( message != NULL );
1662
+ if ( message->length < sizeof( struct ofp_header ) ) {
1663
+ return ERROR_TOO_SHORT_MESSAGE;
1664
+ }
1665
+
1666
+ header = ( struct ofp_header * ) message->data;
1667
+ if ( header->version != OFP_VERSION ) {
1668
+ return ERROR_UNSUPPORTED_VERSION;
1669
+ }
1670
+ if ( header->type > OFPT_QUEUE_GET_CONFIG_REPLY ) {
1671
+ return ERROR_UNDEFINED_TYPE;
1672
+ }
1673
+ if ( header->type != type ) {
1674
+ return ERROR_INVALID_TYPE;
1675
+ }
1676
+ if ( ntohs( header->length ) > max_length ) {
1677
+ return ERROR_TOO_LONG_MESSAGE;
1678
+ }
1679
+ else if ( ntohs( header->length ) < min_length ) {
1680
+ return ERROR_TOO_SHORT_MESSAGE;
1681
+ }
1682
+ if ( ntohs( header->length ) < message->length ) {
1683
+ return ERROR_TOO_LONG_MESSAGE;
1684
+ }
1685
+ else if ( ntohs( header->length ) > message->length ) {
1686
+ return ERROR_TOO_SHORT_MESSAGE;
1687
+ }
1688
+
1689
+ if ( message->length > max_length ) {
1690
+ return ERROR_TOO_LONG_MESSAGE;
1691
+ }
1692
+
1693
+ return 0;
1694
+ }
1695
+
1696
+
1697
+ int
1698
+ validate_hello( const buffer *message ) {
1699
+ assert( message != NULL );
1700
+ return validate_header( message, OFPT_HELLO, sizeof( struct ofp_header ), sizeof( struct ofp_header ) );
1701
+ }
1702
+
1703
+
1704
+ int
1705
+ validate_error( const buffer *message ) {
1706
+ int ret;
1707
+
1708
+ assert( message != NULL );
1709
+
1710
+ ret = validate_header( message, OFPT_ERROR, sizeof( struct ofp_error_msg ), UINT16_MAX );
1711
+ if ( ret < 0 ) {
1712
+ return ret;
1713
+ }
1714
+
1715
+ return 0;
1716
+ }
1717
+
1718
+
1719
+ int
1720
+ validate_echo_request( const buffer *message ) {
1721
+ int ret;
1722
+ struct ofp_header *header;
1723
+
1724
+ assert( message != NULL );
1725
+
1726
+ ret = validate_header( message, OFPT_ECHO_REQUEST, sizeof( struct ofp_header ), UINT16_MAX );
1727
+ if ( ret < 0 ) {
1728
+ return ret;
1729
+ }
1730
+
1731
+ header = ( struct ofp_header * ) message->data;
1732
+ if ( message->length != ntohs( header->length ) ) {
1733
+ return ERROR_INVALID_LENGTH;
1734
+ }
1735
+
1736
+ return 0;
1737
+ }
1738
+
1739
+
1740
+ int
1741
+ validate_echo_reply( const buffer *message ) {
1742
+ int ret;
1743
+ struct ofp_header *header;
1744
+
1745
+ assert( message != NULL );
1746
+
1747
+ ret = validate_header( message, OFPT_ECHO_REPLY, sizeof( struct ofp_header ), UINT16_MAX );
1748
+ if ( ret < 0 ) {
1749
+ return ret;
1750
+ }
1751
+
1752
+ header = ( struct ofp_header * ) message->data;
1753
+ if ( message->length != ntohs( header->length ) ) {
1754
+ return ERROR_INVALID_LENGTH;
1755
+ }
1756
+
1757
+ return 0;
1758
+ }
1759
+
1760
+
1761
+ int
1762
+ validate_vendor( const buffer *message ) {
1763
+ int ret;
1764
+ struct ofp_vendor_header *vendor_header;
1765
+
1766
+ assert( message != NULL );
1767
+
1768
+ ret = validate_header( message, OFPT_VENDOR, sizeof( struct ofp_vendor_header ), UINT16_MAX );
1769
+ if ( ret < 0 ) {
1770
+ return ret;
1771
+ }
1772
+
1773
+ vendor_header = ( struct ofp_vendor_header * ) message->data;
1774
+ if ( message->length != ntohs( vendor_header->header.length ) ) {
1775
+ return ERROR_INVALID_LENGTH;
1776
+ }
1777
+
1778
+ return 0;
1779
+ }
1780
+
1781
+
1782
+ int
1783
+ validate_features_request( const buffer *message ) {
1784
+ assert( message != NULL );
1785
+ return validate_header( message, OFPT_FEATURES_REQUEST, sizeof( struct ofp_header ),
1786
+ sizeof( struct ofp_header ) );
1787
+ }
1788
+
1789
+
1790
+ static int
1791
+ validate_phy_port_no( const uint16_t port_no ) {
1792
+ if ( ( port_no == 0 ) || ( ( port_no > OFPP_MAX ) && ( port_no < OFPP_IN_PORT ) ) ) {
1793
+ return ERROR_INVALID_PORT_NO;
1794
+ }
1795
+
1796
+ return 0;
1797
+ }
1798
+
1799
+
1800
+ static int
1801
+ validate_phy_port( struct ofp_phy_port *port ) {
1802
+ int ret;
1803
+ struct ofp_phy_port port_h;
1804
+
1805
+ assert( port != NULL );
1806
+
1807
+ ntoh_phy_port( &port_h, port );
1808
+
1809
+ ret = validate_phy_port_no( port_h.port_no );
1810
+ if ( ret < 0 ) {
1811
+ return ret;
1812
+ }
1813
+
1814
+ if ( ( port_h.config & ( uint32_t ) ~PORT_CONFIG ) != 0 ) {
1815
+ return ERROR_INVALID_PORT_CONFIG;
1816
+ }
1817
+ if ( ( port_h.state & ( uint32_t ) ~PORT_STATE ) != 0 ) {
1818
+ return ERROR_INVALID_PORT_STATE;
1819
+ }
1820
+ if ( ( port_h.curr & ( uint32_t ) ~PORT_FEATURES ) != 0
1821
+ || ( port_h.advertised & ( uint32_t ) ~PORT_FEATURES ) != 0
1822
+ || ( port_h.supported & ( uint32_t ) ~PORT_FEATURES ) != 0
1823
+ || ( port_h.peer & ( uint32_t ) ~PORT_FEATURES ) != 0 ) {
1824
+ return ERROR_INVALID_PORT_FEATURES;
1825
+ }
1826
+
1827
+ return 0;
1828
+ }
1829
+
1830
+
1831
+ static int
1832
+ validate_phy_ports( struct ofp_phy_port *ports, const int n_ports ) {
1833
+ int i;
1834
+ int ret;
1835
+ struct ofp_phy_port *port;
1836
+
1837
+ assert( ports != NULL );
1838
+ assert( n_ports );
1839
+
1840
+ port = ports;
1841
+ for ( i = 0; i < n_ports; i++ ) {
1842
+ ret = validate_phy_port( port );
1843
+ if ( ret < 0 ) {
1844
+ return ret;
1845
+ }
1846
+ port++;
1847
+ }
1848
+
1849
+ return 0;
1850
+ }
1851
+
1852
+
1853
+ int
1854
+ validate_features_reply( const buffer *message ) {
1855
+ void *p;
1856
+ int ret;
1857
+ int n_ports;
1858
+ uint16_t port_length;
1859
+ struct ofp_switch_features *switch_features;
1860
+
1861
+ assert( message != NULL );
1862
+
1863
+ ret = validate_header( message, OFPT_FEATURES_REPLY, sizeof( struct ofp_switch_features ), UINT16_MAX );
1864
+ if ( ret < 0 ) {
1865
+ return ret;
1866
+ }
1867
+
1868
+ switch_features = ( struct ofp_switch_features * ) message->data;
1869
+
1870
+ // switch_features->datapath_id
1871
+ // switch_features->n_buffers
1872
+
1873
+ if ( switch_features->n_tables == 0 ) {
1874
+ return ERROR_NO_TABLE_AVAILABLE;
1875
+ }
1876
+
1877
+ port_length = ( uint16_t ) ( ntohs( switch_features->header.length )
1878
+ - sizeof( struct ofp_switch_features ) );
1879
+ if ( port_length % sizeof( struct ofp_phy_port ) != 0 ) {
1880
+ return ERROR_INVALID_LENGTH;
1881
+ }
1882
+
1883
+ if ( port_length > 0 ) {
1884
+ p = ( void * ) ( ( char * ) message->data + offsetof( struct ofp_switch_features, ports ) );
1885
+ n_ports = port_length / sizeof( struct ofp_phy_port );
1886
+
1887
+ ret = validate_phy_ports( p, n_ports );
1888
+ if ( ret < 0 ) {
1889
+ return ret;
1890
+ }
1891
+ }
1892
+
1893
+ return 0;
1894
+ }
1895
+
1896
+
1897
+ int
1898
+ validate_get_config_request( const buffer *message ) {
1899
+ assert( message != NULL );
1900
+ return validate_header( message, OFPT_GET_CONFIG_REQUEST, sizeof( struct ofp_header ),
1901
+ sizeof( struct ofp_header ) );
1902
+ }
1903
+
1904
+
1905
+ static int
1906
+ validate_switch_config( const buffer *message, const uint8_t type ) {
1907
+ int ret;
1908
+ struct ofp_switch_config *switch_config;
1909
+
1910
+ assert( message != NULL );
1911
+ assert( ( type == OFPT_GET_CONFIG_REPLY ) || ( type == OFPT_SET_CONFIG ) );
1912
+
1913
+ ret = validate_header( message, type, sizeof( struct ofp_switch_config ),
1914
+ sizeof( struct ofp_switch_config ) );
1915
+ if ( ret < 0 ) {
1916
+ return ret;
1917
+ }
1918
+
1919
+ switch_config = ( struct ofp_switch_config * ) message->data;
1920
+ if ( ntohs( switch_config->flags ) > OFPC_FRAG_MASK ) {
1921
+ return ERROR_INVALID_SWITCH_CONFIG;
1922
+ }
1923
+
1924
+ // switch_config->miss_send_len
1925
+
1926
+ return 0;
1927
+ }
1928
+
1929
+
1930
+ int
1931
+ validate_get_config_reply( const buffer *message ) {
1932
+ assert( message != NULL );
1933
+ return validate_switch_config( message, OFPT_GET_CONFIG_REPLY );
1934
+ }
1935
+
1936
+
1937
+ int
1938
+ validate_set_config( const buffer *message ) {
1939
+ assert( message != NULL );
1940
+ return validate_switch_config( message, OFPT_SET_CONFIG );
1941
+ }
1942
+
1943
+
1944
+ int
1945
+ validate_packet_in( const buffer *message ) {
1946
+ int ret;
1947
+ uint16_t data_length;
1948
+ struct ofp_packet_in *packet_in;
1949
+
1950
+ assert( message != NULL );
1951
+
1952
+ ret = validate_header( message, OFPT_PACKET_IN, offsetof( struct ofp_packet_in, data ), UINT16_MAX );
1953
+ if ( ret < 0 ) {
1954
+ return ret;
1955
+ }
1956
+
1957
+ packet_in = ( struct ofp_packet_in * ) message->data;
1958
+
1959
+ // packet_in->buffer_id
1960
+ // packet_in->total_len
1961
+ // packet_in->in_port
1962
+
1963
+ ret = validate_phy_port_no( ntohs( packet_in->in_port ) );
1964
+ if ( ret < 0 ) {
1965
+ return ret;
1966
+ }
1967
+
1968
+ if ( packet_in->reason > OFPR_ACTION ) {
1969
+ return ERROR_INVALID_PACKET_IN_REASON;
1970
+ }
1971
+
1972
+ data_length = ( uint16_t ) ( ntohs( packet_in->header.length ) - offsetof( struct ofp_packet_in, data ) );
1973
+ if ( data_length > 0 ) {
1974
+ // FIXME: it may be better to check if this is a valid Ethernet frame or not.
1975
+ }
1976
+
1977
+ return 0;
1978
+ }
1979
+
1980
+
1981
+ static int
1982
+ validate_wildcards( const uint32_t wildcards ) {
1983
+ if ( ( wildcards & ( uint32_t ) ~OFPFW_ALL ) != 0 ) {
1984
+ return ERROR_INVALID_WILDCARDS;
1985
+ }
1986
+
1987
+ return 0;
1988
+ }
1989
+
1990
+
1991
+ static int
1992
+ validate_vlan_vid( const uint16_t vid ) {
1993
+ if ( ( vid != UINT16_MAX ) && ( ( vid & ~VLAN_VID_MASK ) != 0 ) ) {
1994
+ return ERROR_INVALID_VLAN_VID;
1995
+ }
1996
+
1997
+ return 0;
1998
+ }
1999
+
2000
+
2001
+ static int
2002
+ validate_vlan_pcp( const uint8_t pcp ) {
2003
+ if ( ( pcp & ~VLAN_PCP_MASK ) != 0 ) {
2004
+ return ERROR_INVALID_VLAN_PCP;
2005
+ }
2006
+
2007
+ return 0;
2008
+ }
2009
+
2010
+
2011
+ static int
2012
+ validate_nw_tos( const uint8_t tos ) {
2013
+ if ( ( tos & ~NW_TOS_MASK ) != 0 ) {
2014
+ return ERROR_INVALID_NW_TOS;
2015
+ }
2016
+
2017
+ return 0;
2018
+ }
2019
+
2020
+
2021
+ static int
2022
+ validate_match( const struct ofp_match match ) {
2023
+ int ret;
2024
+
2025
+ ret = validate_wildcards( match.wildcards );
2026
+ if ( ret < 0 ) {
2027
+ return ret;
2028
+ }
2029
+
2030
+ ret = validate_vlan_vid( match.dl_vlan );
2031
+ if ( ret < 0 ) {
2032
+ return ret;
2033
+ }
2034
+
2035
+ ret = validate_vlan_pcp( match.dl_vlan_pcp );
2036
+ if ( ret < 0 ) {
2037
+ return ret;
2038
+ }
2039
+
2040
+ ret = validate_nw_tos( match.nw_tos );
2041
+ if ( ret < 0 ) {
2042
+ return ret;
2043
+ }
2044
+
2045
+ return 0;
2046
+ }
2047
+
2048
+
2049
+ int
2050
+ validate_flow_removed( const buffer *message ) {
2051
+ int ret;
2052
+ struct ofp_match match;
2053
+ struct ofp_flow_removed *flow_removed;
2054
+
2055
+ assert( message != NULL );
2056
+
2057
+ ret = validate_header( message, OFPT_FLOW_REMOVED, sizeof( struct ofp_flow_removed ),
2058
+ sizeof( struct ofp_flow_removed ) );
2059
+ if ( ret < 0 ) {
2060
+ return ret;
2061
+ }
2062
+
2063
+ flow_removed = ( struct ofp_flow_removed * ) message->data;
2064
+
2065
+ ntoh_match( &match, &flow_removed->match );
2066
+
2067
+ ret = validate_match( match );
2068
+ if ( ret < 0 ) {
2069
+ return ret;
2070
+ }
2071
+
2072
+ // flow_removed->cookie
2073
+
2074
+ if ( ( ( match.wildcards & OFPFW_ALL ) == 0 ) && ( ntohs( flow_removed->priority ) != UINT16_MAX ) ) {
2075
+ return ERROR_INVALID_FLOW_PRIORITY;
2076
+ }
2077
+
2078
+ if ( flow_removed->reason > OFPRR_DELETE ) {
2079
+ return ERROR_INVALID_FLOW_REMOVED_REASON;
2080
+ }
2081
+
2082
+ // flow_removed->duration_sec
2083
+ // flow_removed->duration_nsec
2084
+ // flow_removed->idle_timeout
2085
+ // flow_removed->packet_count
2086
+ // flow_removed->byte_count
2087
+
2088
+ return 0;
2089
+ }
2090
+
2091
+
2092
+ int
2093
+ validate_port_status( const buffer *message ) {
2094
+ int ret;
2095
+ struct ofp_port_status *port_status;
2096
+
2097
+ assert( message != NULL );
2098
+
2099
+ ret = validate_header( message, OFPT_PORT_STATUS, sizeof( struct ofp_port_status ),
2100
+ sizeof( struct ofp_port_status ) );
2101
+ if ( ret < 0 ) {
2102
+ return ret;
2103
+ }
2104
+
2105
+ port_status = ( struct ofp_port_status * ) message->data;
2106
+ if ( port_status->reason > OFPPR_MODIFY ) {
2107
+ return ERROR_INVALID_PORT_STATUS_REASON;
2108
+ }
2109
+
2110
+ ret = validate_phy_port( &port_status->desc );
2111
+ if ( ret < 0 ) {
2112
+ return ret;
2113
+ }
2114
+
2115
+ return 0;
2116
+ }
2117
+
2118
+
2119
+ int
2120
+ validate_packet_out( const buffer *message ) {
2121
+ int ret;
2122
+ uint16_t data_length;
2123
+ struct ofp_packet_out *packet_out;
2124
+
2125
+ assert( message != NULL );
2126
+
2127
+ ret = validate_header( message, OFPT_PACKET_OUT, offsetof( struct ofp_packet_out, actions ),
2128
+ UINT16_MAX );
2129
+ if ( ret < 0 ) {
2130
+ return ret;
2131
+ }
2132
+
2133
+ packet_out = ( struct ofp_packet_out * ) message->data;
2134
+
2135
+ ret = validate_phy_port_no( ntohs( packet_out->in_port ) );
2136
+ if ( ret < 0 ) {
2137
+ return ret;
2138
+ }
2139
+
2140
+ if ( ntohs( packet_out->actions_len ) > 0 ) {
2141
+ ret = validate_actions( packet_out->actions, ntohs( packet_out->actions_len ) );
2142
+ if ( ret < 0 ) {
2143
+ return ret;
2144
+ }
2145
+ }
2146
+
2147
+ data_length = ( uint16_t ) ( ntohs( packet_out->header.length )
2148
+ - offsetof( struct ofp_packet_out, actions )
2149
+ - ntohs( packet_out->actions_len ) );
2150
+
2151
+ if ( data_length > 0 ) {
2152
+ // FIXME: it may be better to check if this is a valid Ethernet frame or not.
2153
+ }
2154
+
2155
+ return 0;
2156
+ }
2157
+
2158
+
2159
+ int
2160
+ validate_flow_mod( const buffer *message ) {
2161
+ int ret;
2162
+ uint16_t actions_length;
2163
+ struct ofp_match match;
2164
+ struct ofp_flow_mod *flow_mod;
2165
+
2166
+ assert( message != NULL );
2167
+
2168
+ ret = validate_header( message, OFPT_FLOW_MOD, offsetof( struct ofp_flow_mod, actions ),
2169
+ UINT16_MAX );
2170
+ if ( ret < 0 ) {
2171
+ return ret;
2172
+ }
2173
+
2174
+ flow_mod = ( struct ofp_flow_mod * ) message->data;
2175
+
2176
+ ntoh_match( &match, &flow_mod->match );
2177
+
2178
+ ret = validate_match( match );
2179
+ if ( ret < 0 ) {
2180
+ return ret;
2181
+ }
2182
+
2183
+ // flow_mod->cookie
2184
+
2185
+ if ( ntohs( flow_mod->command ) > OFPFC_DELETE_STRICT ) {
2186
+ return ERROR_UNDEFINED_FLOW_MOD_COMMAND;
2187
+ }
2188
+
2189
+ // flow_mod->idle_timeout
2190
+ // flow_mod->hard_timeout
2191
+
2192
+ if ( ( ( match.wildcards & OFPFW_ALL ) == 0 ) && ( ntohs( flow_mod->priority ) != UINT16_MAX ) ) {
2193
+ return ERROR_INVALID_FLOW_PRIORITY;
2194
+ }
2195
+
2196
+ // flow_mod->buffer_id
2197
+
2198
+ if ( ( ntohs( flow_mod->command ) == OFPFC_DELETE )
2199
+ || ( ntohs( flow_mod->command ) == OFPFC_DELETE_STRICT ) ) {
2200
+ if ( ntohs( flow_mod->out_port ) != OFPP_NONE ) {
2201
+ ret = validate_phy_port_no( ntohs( flow_mod->out_port ) );
2202
+ if ( ret < 0 ) {
2203
+ return ret;
2204
+ }
2205
+ }
2206
+ }
2207
+
2208
+ if ( ( ntohs( flow_mod->flags ) & ~FLOW_MOD_FLAGS ) != 0 ) {
2209
+ return ERROR_INVALID_FLOW_MOD_FLAGS;
2210
+ }
2211
+
2212
+ actions_length = ( uint16_t ) ( ntohs( flow_mod->header.length )
2213
+ - offsetof( struct ofp_flow_mod, actions ) );
2214
+
2215
+ if ( actions_length > 0 ) {
2216
+ ret = validate_actions( flow_mod->actions, actions_length );
2217
+ if ( ret < 0 ) {
2218
+ return ret;
2219
+ }
2220
+
2221
+ }
2222
+
2223
+ return 0;
2224
+ }
2225
+
2226
+
2227
+ int
2228
+ validate_port_mod( const buffer *message ) {
2229
+ int ret;
2230
+ struct ofp_port_mod *port_mod;
2231
+
2232
+ assert( message != NULL );
2233
+
2234
+ ret = validate_header( message, OFPT_PORT_MOD, sizeof( struct ofp_port_mod ),
2235
+ sizeof( struct ofp_port_mod ) );
2236
+ if ( ret < 0 ) {
2237
+ return ret;
2238
+ }
2239
+
2240
+ port_mod = ( struct ofp_port_mod * ) message->data;
2241
+
2242
+ ret = validate_phy_port_no( ntohs( port_mod->port_no ) );
2243
+ if ( ret < 0 ) {
2244
+ return ret;
2245
+ }
2246
+ if ( ( ntohs( port_mod->port_no ) > OFPP_MAX ) && ( ntohs( port_mod->port_no ) != OFPP_LOCAL ) ) {
2247
+ return ERROR_INVALID_PORT_NO;
2248
+ }
2249
+
2250
+ // port_mod->hw_addr
2251
+
2252
+ if ( ( ntohl( port_mod->config ) & ( uint32_t ) ~PORT_CONFIG ) != 0 ) {
2253
+ return ERROR_INVALID_PORT_CONFIG;
2254
+ }
2255
+ if ( ( ntohl( port_mod->mask ) & ( uint32_t ) ~PORT_CONFIG ) != 0 ) {
2256
+ return ERROR_INVALID_PORT_MASK;
2257
+ }
2258
+ if ( ( ntohl( port_mod->advertise ) & ( uint32_t ) ~PORT_CONFIG ) != 0 ) {
2259
+ return ERROR_INVALID_PORT_FEATURES;
2260
+ }
2261
+
2262
+ return 0;
2263
+ }
2264
+
2265
+
2266
+ int
2267
+ validate_desc_stats_request( const buffer *message ) {
2268
+ int ret;
2269
+ struct ofp_stats_request *stats_request;
2270
+
2271
+ assert( message != NULL );
2272
+
2273
+ ret = validate_header( message, OFPT_STATS_REQUEST, sizeof( struct ofp_stats_request ),
2274
+ sizeof( struct ofp_stats_request ) );
2275
+ if ( ret < 0 ) {
2276
+ return ret;
2277
+ }
2278
+
2279
+ stats_request = ( struct ofp_stats_request * ) message->data;
2280
+
2281
+ if ( ntohs( stats_request->type ) != OFPST_DESC ) {
2282
+ return ERROR_INVALID_STATS_TYPE;
2283
+ }
2284
+ if ( ntohs( stats_request->flags ) != 0 ) {
2285
+ return ERROR_INVALID_STATS_REQUEST_FLAGS;
2286
+ }
2287
+
2288
+ return 0;
2289
+ }
2290
+
2291
+
2292
+ int
2293
+ validate_flow_stats_request( const buffer *message ) {
2294
+ int ret;
2295
+ struct ofp_match match;
2296
+ struct ofp_stats_request *stats_request;
2297
+ struct ofp_flow_stats_request *flow_stats_request;
2298
+
2299
+ assert( message != NULL );
2300
+
2301
+ ret = validate_header( message, OFPT_STATS_REQUEST,
2302
+ offsetof( struct ofp_stats_request, body )
2303
+ + sizeof( struct ofp_flow_stats_request ),
2304
+ offsetof( struct ofp_stats_request, body )
2305
+ + sizeof( struct ofp_flow_stats_request ) );
2306
+ if ( ret < 0 ) {
2307
+ return ret;
2308
+ }
2309
+
2310
+ stats_request = ( struct ofp_stats_request * ) message->data;
2311
+
2312
+ if ( ntohs( stats_request->type ) != OFPST_FLOW ) {
2313
+ return ERROR_INVALID_STATS_TYPE;
2314
+ }
2315
+
2316
+ if ( ntohs( stats_request->flags ) != 0 ) {
2317
+ return ERROR_INVALID_STATS_REQUEST_FLAGS;
2318
+ }
2319
+
2320
+ flow_stats_request = ( struct ofp_flow_stats_request * ) stats_request->body;
2321
+ ntoh_match( &match, &flow_stats_request->match );
2322
+
2323
+ ret = validate_match( match );
2324
+ if ( ret < 0 ) {
2325
+ return ret;
2326
+ }
2327
+
2328
+ // flow_stats_request->table_id
2329
+
2330
+ ret = validate_phy_port_no( ntohs( flow_stats_request->out_port ) );
2331
+ if ( ret < 0 ) {
2332
+ return ret;
2333
+ }
2334
+
2335
+ return 0;
2336
+ }
2337
+
2338
+
2339
+ int
2340
+ validate_aggregate_stats_request( const buffer *message ) {
2341
+ int ret;
2342
+ struct ofp_match match;
2343
+ struct ofp_stats_request *stats_request;
2344
+ struct ofp_aggregate_stats_request *aggregate_stats_request;
2345
+
2346
+ assert( message != NULL );
2347
+
2348
+ ret = validate_header( message, OFPT_STATS_REQUEST,
2349
+ offsetof( struct ofp_stats_request, body )
2350
+ + sizeof( struct ofp_aggregate_stats_request ),
2351
+ offsetof( struct ofp_stats_request, body )
2352
+ + sizeof( struct ofp_aggregate_stats_request ) );
2353
+ if ( ret < 0 ) {
2354
+ return ret;
2355
+ }
2356
+
2357
+ stats_request = ( struct ofp_stats_request * ) message->data;
2358
+
2359
+ if ( ntohs( stats_request->type ) != OFPST_AGGREGATE ) {
2360
+ return ERROR_INVALID_STATS_TYPE;
2361
+ }
2362
+ if ( ntohs( stats_request->flags ) != 0 ) {
2363
+ return ERROR_INVALID_STATS_REQUEST_FLAGS;
2364
+ }
2365
+
2366
+ aggregate_stats_request = ( struct ofp_aggregate_stats_request * ) stats_request->body;
2367
+ ntoh_match( &match, &aggregate_stats_request->match );
2368
+
2369
+ ret = validate_match( match );
2370
+ if ( ret < 0 ) {
2371
+ return ret;
2372
+ }
2373
+
2374
+ // aggregate_stats_request->table_id
2375
+
2376
+ ret = validate_phy_port_no( ntohs( aggregate_stats_request->out_port ) );
2377
+ if ( ret < 0 ) {
2378
+ return ret;
2379
+ }
2380
+
2381
+ return 0;
2382
+ }
2383
+
2384
+
2385
+ int
2386
+ validate_table_stats_request( const buffer *message ) {
2387
+ int ret;
2388
+ struct ofp_stats_request *stats_request;
2389
+
2390
+ assert( message != NULL );
2391
+
2392
+ ret = validate_header( message, OFPT_STATS_REQUEST, offsetof( struct ofp_stats_request, body ),
2393
+ offsetof( struct ofp_stats_request, body ) );
2394
+ if ( ret < 0 ) {
2395
+ return ret;
2396
+ }
2397
+
2398
+ stats_request = ( struct ofp_stats_request * ) message->data;
2399
+
2400
+ if ( ntohs( stats_request->type ) != OFPST_TABLE ) {
2401
+ return ERROR_INVALID_STATS_TYPE;
2402
+ }
2403
+ if ( ntohs( stats_request->flags ) != 0 ) {
2404
+ return ERROR_INVALID_STATS_REQUEST_FLAGS;
2405
+ }
2406
+
2407
+ return 0;
2408
+ }
2409
+
2410
+
2411
+ int
2412
+ validate_port_stats_request( const buffer *message ) {
2413
+ int ret;
2414
+ struct ofp_stats_request *stats_request;
2415
+ struct ofp_port_stats_request *port_stats_request;
2416
+
2417
+ assert( message != NULL );
2418
+
2419
+ ret = validate_header( message, OFPT_STATS_REQUEST,
2420
+ offsetof( struct ofp_stats_request, body )
2421
+ + sizeof( struct ofp_port_stats_request ),
2422
+ offsetof( struct ofp_stats_request, body )
2423
+ + sizeof( struct ofp_port_stats_request ) );
2424
+ if ( ret < 0 ) {
2425
+ return ret;
2426
+ }
2427
+
2428
+ stats_request = ( struct ofp_stats_request * ) message->data;
2429
+
2430
+ if ( ntohs( stats_request->type ) != OFPST_PORT ) {
2431
+ return ERROR_INVALID_STATS_TYPE;
2432
+ }
2433
+ if ( ntohs( stats_request->flags ) != 0 ) {
2434
+ return ERROR_INVALID_STATS_REQUEST_FLAGS;
2435
+ }
2436
+
2437
+ port_stats_request = ( struct ofp_port_stats_request * ) stats_request->body;
2438
+
2439
+ ret = validate_phy_port_no( ntohs( port_stats_request->port_no ) );
2440
+ if ( ret < 0 ) {
2441
+ return ret;
2442
+ }
2443
+
2444
+ if ( ntohs( port_stats_request->port_no ) > OFPP_MAX
2445
+ && ntohs( port_stats_request->port_no ) != OFPP_NONE
2446
+ && ntohs( port_stats_request->port_no ) != OFPP_LOCAL ) {
2447
+ return ERROR_INVALID_PORT_NO;
2448
+ }
2449
+
2450
+ return 0;
2451
+ }
2452
+
2453
+
2454
+ int
2455
+ validate_queue_stats_request( const buffer *message ) {
2456
+ int ret;
2457
+ struct ofp_stats_request *stats_request;
2458
+ struct ofp_queue_stats_request *queue_stats_request;
2459
+
2460
+ assert( message != NULL );
2461
+
2462
+ ret = validate_header( message, OFPT_STATS_REQUEST,
2463
+ offsetof( struct ofp_stats_request, body )
2464
+ + sizeof( struct ofp_queue_stats_request ),
2465
+ offsetof( struct ofp_stats_request, body )
2466
+ + sizeof( struct ofp_queue_stats_request ) );
2467
+ if ( ret < 0 ) {
2468
+ return ret;
2469
+ }
2470
+
2471
+ stats_request = ( struct ofp_stats_request * ) message->data;
2472
+
2473
+ if ( ntohs( stats_request->type ) != OFPST_QUEUE ) {
2474
+ return ERROR_INVALID_STATS_TYPE;
2475
+ }
2476
+ if ( ntohs( stats_request->flags ) != 0 ) {
2477
+ return ERROR_INVALID_STATS_REQUEST_FLAGS;
2478
+ }
2479
+
2480
+ queue_stats_request = ( struct ofp_queue_stats_request * ) stats_request->body;
2481
+
2482
+ ret = validate_phy_port_no( ntohs( queue_stats_request->port_no ) );
2483
+ if ( ret < 0 ) {
2484
+ return ret;
2485
+ }
2486
+
2487
+ // queue_stats_request->queue_id
2488
+ return 0;
2489
+ }
2490
+
2491
+
2492
+ int
2493
+ validate_vendor_stats_request( const buffer *message ) {
2494
+ int ret;
2495
+ struct ofp_stats_request *stats_request;
2496
+
2497
+ assert( message != NULL );
2498
+
2499
+ ret = validate_header( message, OFPT_STATS_REQUEST,
2500
+ offsetof( struct ofp_stats_request, body ) + sizeof( uint32_t ),
2501
+ UINT16_MAX );
2502
+ if ( ret < 0 ) {
2503
+ return ret;
2504
+ }
2505
+
2506
+ stats_request = ( struct ofp_stats_request * ) message->data;
2507
+
2508
+ if ( ntohs( stats_request->type ) != OFPST_VENDOR ) {
2509
+ return ERROR_INVALID_STATS_TYPE;
2510
+ }
2511
+ if ( ntohs( stats_request->flags ) != 0 ) {
2512
+ return ERROR_INVALID_STATS_REQUEST_FLAGS;
2513
+ }
2514
+
2515
+ // vendor_id
2516
+ return 0;
2517
+ }
2518
+
2519
+
2520
+ int
2521
+ validate_stats_request( const buffer *message ) {
2522
+ struct ofp_stats_request *request;
2523
+
2524
+ assert( message != NULL );
2525
+
2526
+ request = ( struct ofp_stats_request * ) message->data;
2527
+
2528
+ // TODO: if ( request->header.type != OFPT_STATS_REQUEST ) { ... }
2529
+
2530
+ switch ( ntohs( request->type ) ) {
2531
+ case OFPST_DESC:
2532
+ return validate_desc_stats_request( message );
2533
+ case OFPST_FLOW:
2534
+ return validate_flow_stats_request( message );
2535
+ case OFPST_AGGREGATE:
2536
+ return validate_aggregate_stats_request( message );
2537
+ case OFPST_TABLE:
2538
+ return validate_table_stats_request( message );
2539
+ case OFPST_PORT:
2540
+ return validate_port_stats_request( message );
2541
+ case OFPST_QUEUE:
2542
+ return validate_queue_stats_request( message );
2543
+ case OFPST_VENDOR:
2544
+ return validate_vendor_stats_request( message );
2545
+ default:
2546
+ break;
2547
+ }
2548
+
2549
+ return ERROR_UNSUPPORTED_STATS_TYPE;
2550
+ }
2551
+
2552
+
2553
+ int
2554
+ validate_desc_stats_reply( const buffer *message ) {
2555
+ int ret;
2556
+ struct ofp_stats_reply *stats_reply;
2557
+
2558
+ assert( message != NULL );
2559
+
2560
+ ret = validate_header( message, OFPT_STATS_REPLY,
2561
+ offsetof( struct ofp_stats_reply, body ) + sizeof( struct ofp_desc_stats ),
2562
+ offsetof( struct ofp_stats_reply, body ) + sizeof( struct ofp_desc_stats ) );
2563
+ if ( ret < 0 ) {
2564
+ return ret;
2565
+ }
2566
+
2567
+ stats_reply = ( struct ofp_stats_reply * ) message->data;
2568
+ if ( ntohs( stats_reply->flags ) != 0 ) {
2569
+ return ERROR_INVALID_STATS_REPLY_FLAGS;
2570
+ }
2571
+
2572
+ return 0;
2573
+ }
2574
+
2575
+
2576
+ int
2577
+ validate_flow_stats_reply( const buffer *message ) {
2578
+ int ret;
2579
+ uint16_t offset;
2580
+ uint16_t flow_length;
2581
+ uint16_t actions_length;
2582
+ struct ofp_stats_reply *stats_reply;
2583
+ struct ofp_flow_stats *flow_stats;
2584
+ struct ofp_action_header *actions_head;
2585
+ struct ofp_match match;
2586
+
2587
+ assert( message != NULL );
2588
+
2589
+ ret = validate_header( message, OFPT_STATS_REPLY, offsetof( struct ofp_stats_reply, body ),
2590
+ UINT16_MAX );
2591
+ if ( ret < 0 ) {
2592
+ return ret;
2593
+ }
2594
+
2595
+ stats_reply = ( struct ofp_stats_reply * ) message->data;
2596
+ if ( ( ntohs( stats_reply->flags ) & ~OFPSF_REPLY_MORE ) != 0 ) {
2597
+ return ERROR_INVALID_STATS_REPLY_FLAGS;
2598
+ }
2599
+
2600
+ flow_length = ( uint16_t ) ( ntohs( stats_reply->header.length )
2601
+ - offsetof( struct ofp_stats_reply, body ) );
2602
+ offset = offsetof( struct ofp_stats_reply, body );
2603
+ flow_stats = ( struct ofp_flow_stats * ) ( ( char * ) message->data + offset );
2604
+
2605
+ while ( flow_length > 0 ) {
2606
+ // flow_stats->length
2607
+ // flow_stats->table_id
2608
+
2609
+ ntoh_match( &match, &flow_stats->match );
2610
+
2611
+ ret = validate_match( match );
2612
+ if ( ret < 0 ) {
2613
+ return ret;
2614
+ }
2615
+
2616
+ // flow_stats->duration_sec
2617
+ // flow_stats->duration_nsec
2618
+
2619
+ if ( ( ( match.wildcards & OFPFW_ALL ) == 0 ) && ( ntohs( flow_stats->priority ) < UINT16_MAX ) ) {
2620
+ return ERROR_INVALID_FLOW_PRIORITY;
2621
+ }
2622
+
2623
+ // flow_stats->idle_timeout
2624
+ // flow_stats->hard_timeout
2625
+ // flow_stats->cookie
2626
+ // flow_stats->packet_count
2627
+ // flow_stats->byte_count
2628
+
2629
+ actions_length = ( uint16_t ) ( ntohs( flow_stats->length )
2630
+ - offsetof( struct ofp_flow_stats, actions ) );
2631
+
2632
+ if ( actions_length > 0 ) {
2633
+ actions_head = ( struct ofp_action_header * ) ( ( char * ) flow_stats
2634
+ + offsetof( struct ofp_flow_stats, actions ) );
2635
+
2636
+ ret = validate_actions( actions_head, actions_length );
2637
+ if ( ret < 0 ) {
2638
+ return ret;
2639
+ }
2640
+ }
2641
+
2642
+ flow_length = ( uint16_t ) ( flow_length - ntohs( flow_stats->length ) );
2643
+ flow_stats = ( struct ofp_flow_stats * ) ( ( char * ) flow_stats + ntohs( flow_stats->length ) );
2644
+ }
2645
+
2646
+ return 0;
2647
+ }
2648
+
2649
+
2650
+ int
2651
+ validate_aggregate_stats_reply( const buffer *message ) {
2652
+ int ret;
2653
+ struct ofp_stats_reply *stats_reply;
2654
+
2655
+ assert( message != NULL );
2656
+
2657
+ ret = validate_header( message, OFPT_STATS_REPLY,
2658
+ offsetof( struct ofp_stats_reply, body ) + sizeof( struct ofp_aggregate_stats_reply ),
2659
+ offsetof( struct ofp_stats_reply, body ) + sizeof( struct ofp_aggregate_stats_reply ) );
2660
+ if ( ret < 0 ) {
2661
+ return ret;
2662
+ }
2663
+
2664
+ stats_reply = ( struct ofp_stats_reply * ) message->data;
2665
+ if ( ntohs( stats_reply->flags ) != 0 ) {
2666
+ return ERROR_INVALID_STATS_REPLY_FLAGS;
2667
+ }
2668
+
2669
+ // uint16_t offset = offsetof( struct ofp_stats_reply, body );
2670
+ // struct ofp_aggregate_stats_reply *aggregate_stats = ( struct ofp_aggregate_stats_reply * ) ( ( char * ) message->data + offset );
2671
+
2672
+ // aggregate_stats->packet_count
2673
+ // aggregate_stats->byte_count
2674
+ // aggregate_stats->flow_count
2675
+
2676
+ return 0;
2677
+ }
2678
+
2679
+
2680
+ int
2681
+ validate_table_stats_reply( const buffer *message ) {
2682
+ int i;
2683
+ int ret;
2684
+ uint16_t tables_length;
2685
+ uint16_t n_tables;
2686
+ uint16_t offset;
2687
+ struct ofp_stats_reply *stats_reply;
2688
+ struct ofp_table_stats *table_stats;
2689
+
2690
+ assert( message != NULL );
2691
+
2692
+ ret = validate_header( message, OFPT_STATS_REPLY,
2693
+ offsetof( struct ofp_stats_reply, body ) + sizeof( struct ofp_table_stats ),
2694
+ UINT16_MAX );
2695
+ if ( ret < 0 ) {
2696
+ return ret;
2697
+ }
2698
+
2699
+ stats_reply = ( struct ofp_stats_reply * ) message->data;
2700
+ if ( ( ntohs( stats_reply->flags ) & ~OFPSF_REPLY_MORE ) != 0 ) {
2701
+ return ERROR_INVALID_STATS_REPLY_FLAGS;
2702
+ }
2703
+
2704
+ tables_length = ( uint16_t ) ( ntohs( stats_reply->header.length )
2705
+ - offsetof( struct ofp_stats_reply, body ) );
2706
+ if ( tables_length % sizeof( struct ofp_table_stats ) != 0 ) {
2707
+ return ERROR_INVALID_LENGTH;
2708
+ }
2709
+
2710
+ offset = offsetof( struct ofp_stats_reply, body );
2711
+ table_stats = ( struct ofp_table_stats * ) ( ( char * ) message->data + offset );
2712
+
2713
+ n_tables = tables_length / sizeof( struct ofp_table_stats );
2714
+
2715
+ for ( i = 0; i < n_tables; i++ ) {
2716
+ // table_stats->table_id
2717
+
2718
+ ret = validate_wildcards( ntohl( table_stats->wildcards ) );
2719
+ if ( ret < 0 ) {
2720
+ return ret;
2721
+ }
2722
+
2723
+ // table_stats->max_entries
2724
+ // table_stats->active_count
2725
+ // table_stats->lookup_count
2726
+ // table_stats->matched_count
2727
+
2728
+ table_stats++;
2729
+ }
2730
+
2731
+ return 0;
2732
+ }
2733
+
2734
+
2735
+ int
2736
+ validate_port_stats_reply( const buffer *message ) {
2737
+ int i;
2738
+ int ret;
2739
+ uint16_t ports_length;
2740
+ uint16_t n_ports;
2741
+ uint16_t offset;
2742
+ struct ofp_stats_reply *stats_reply;
2743
+ struct ofp_port_stats *port_stats;
2744
+
2745
+ assert( message != NULL );
2746
+
2747
+ ret = validate_header( message, OFPT_STATS_REPLY,
2748
+ offsetof( struct ofp_stats_reply, body ) + sizeof( struct ofp_port_stats ),
2749
+ UINT16_MAX );
2750
+ if ( ret < 0 ) {
2751
+ return ret;
2752
+ }
2753
+
2754
+ stats_reply = ( struct ofp_stats_reply * ) message->data;
2755
+ if ( ( ntohs( stats_reply->flags ) & ~OFPSF_REPLY_MORE ) != 0 ) {
2756
+ return ERROR_INVALID_STATS_REPLY_FLAGS;
2757
+ }
2758
+
2759
+ ports_length = ( uint16_t ) ( ntohs( stats_reply->header.length )
2760
+ - offsetof( struct ofp_stats_reply, body ) );
2761
+ if ( ports_length % sizeof( struct ofp_port_stats ) != 0 ) {
2762
+ return ERROR_INVALID_LENGTH;
2763
+ }
2764
+
2765
+ offset = offsetof( struct ofp_stats_reply, body );
2766
+ port_stats = ( struct ofp_port_stats * ) ( ( char * ) message->data + offset );
2767
+
2768
+ n_ports = ports_length / sizeof( struct ofp_port_stats );
2769
+ for ( i = 0; i < n_ports; i++ ) {
2770
+ ret = validate_phy_port_no( ntohs( port_stats->port_no ) );
2771
+
2772
+ if ( ret < 0 ) {
2773
+ return ret;
2774
+ }
2775
+
2776
+ // port_stats->rx_packets
2777
+ // port_stats->tx_packets
2778
+ // port_stats->rx_bytes
2779
+ // port_stats->tx_bytes
2780
+ // port_stats->rx_dropped
2781
+ // port_stats->tx_dropped
2782
+ // port_stats->rx_errors
2783
+ // port_stats->tx_errors
2784
+ // port_stats->rx_frame_err
2785
+ // port_stats->rx_over_err
2786
+ // port_stats->rx_crc_err
2787
+ // port_stats->collisions
2788
+
2789
+ port_stats++;
2790
+ }
2791
+
2792
+ return 0;
2793
+ }
2794
+
2795
+
2796
+ int
2797
+ validate_queue_stats_reply( const buffer *message ) {
2798
+ int i;
2799
+ int ret;
2800
+ uint16_t queues_length;
2801
+ uint16_t n_queues;
2802
+ uint16_t offset;
2803
+ struct ofp_stats_reply *stats_reply;
2804
+ struct ofp_queue_stats *queue_stats;
2805
+
2806
+ assert( message != NULL );
2807
+
2808
+ ret = validate_header( message, OFPT_STATS_REPLY,
2809
+ offsetof( struct ofp_stats_reply, body ),
2810
+ UINT16_MAX );
2811
+ if ( ret < 0 ) {
2812
+ return ret;
2813
+ }
2814
+
2815
+ stats_reply = ( struct ofp_stats_reply * ) message->data;
2816
+ if ( ( ntohs( stats_reply->flags ) & ~OFPSF_REPLY_MORE ) != 0 ) {
2817
+ return ERROR_INVALID_STATS_REPLY_FLAGS;
2818
+ }
2819
+
2820
+ queues_length = ( uint16_t ) ( ntohs( stats_reply->header.length )
2821
+ - offsetof( struct ofp_stats_reply, body ) );
2822
+ if ( queues_length % sizeof( struct ofp_queue_stats ) != 0 ) {
2823
+ return ERROR_INVALID_LENGTH;
2824
+ }
2825
+
2826
+ offset = offsetof( struct ofp_stats_reply, body );
2827
+ queue_stats = ( struct ofp_queue_stats * ) ( ( char * ) message->data + offset );
2828
+
2829
+ n_queues = queues_length / sizeof( struct ofp_queue_stats );
2830
+ for ( i = 0; i < n_queues; i++ ) {
2831
+ ret = validate_phy_port_no( ntohs( queue_stats->port_no ) );
2832
+ if ( ret < 0 ) {
2833
+ return ret;
2834
+ }
2835
+
2836
+ // queue_stats->queue_id
2837
+ // queue_stats->tx_bytes
2838
+ // queue_stats->tx_packets
2839
+ // queue_stats->tx_errors
2840
+
2841
+ queue_stats++;
2842
+ }
2843
+
2844
+ return 0;
2845
+ }
2846
+
2847
+
2848
+ int
2849
+ validate_vendor_stats_reply( const buffer *message ) {
2850
+ void *body;
2851
+ int ret;
2852
+ uint16_t body_length;
2853
+ uint16_t offset;
2854
+ struct ofp_stats_reply *stats_reply;
2855
+
2856
+ assert( message != NULL );
2857
+
2858
+ ret = validate_header( message, OFPT_STATS_REPLY,
2859
+ offsetof( struct ofp_stats_reply, body ) + sizeof( uint32_t ),
2860
+ UINT16_MAX );
2861
+ if ( ret < 0 ) {
2862
+ return ret;
2863
+ }
2864
+
2865
+ stats_reply = ( struct ofp_stats_reply * ) message->data;
2866
+
2867
+ if ( ( ntohs( stats_reply->flags ) & ~OFPSF_REPLY_MORE ) != 0 ) {
2868
+ return ERROR_INVALID_STATS_REPLY_FLAGS;
2869
+ }
2870
+
2871
+ body_length = ( uint16_t ) ( ntohs( stats_reply->header.length )
2872
+ - offsetof( struct ofp_stats_reply, body ) );
2873
+
2874
+ offset = offsetof( struct ofp_stats_reply, body );
2875
+ body = ( void * ) ( ( char * ) message->data + offset );
2876
+ if ( ( body_length > 0 ) && ( body != NULL ) ) {
2877
+ // FIXME: validate body here
2878
+ }
2879
+
2880
+ return 0;
2881
+ }
2882
+
2883
+
2884
+ int
2885
+ validate_stats_reply( const buffer *message ) {
2886
+ struct ofp_stats_reply *reply;
2887
+
2888
+ assert( message != NULL );
2889
+ assert( message->data != NULL );
2890
+
2891
+ reply = ( struct ofp_stats_reply * ) message->data;
2892
+
2893
+ // TODO: if ( reply->header.type != OFPT_STATS_REPLY ) { ... }
2894
+
2895
+ switch ( ntohs( reply->type ) ) {
2896
+ case OFPST_DESC:
2897
+ return validate_desc_stats_reply( message );
2898
+ case OFPST_FLOW:
2899
+ return validate_flow_stats_reply( message );
2900
+ case OFPST_AGGREGATE:
2901
+ return validate_aggregate_stats_reply( message );
2902
+ case OFPST_TABLE:
2903
+ return validate_table_stats_reply( message );
2904
+ case OFPST_PORT:
2905
+ return validate_port_stats_reply( message );
2906
+ case OFPST_QUEUE:
2907
+ return validate_queue_stats_reply( message );
2908
+ case OFPST_VENDOR:
2909
+ return validate_vendor_stats_reply( message );
2910
+ default:
2911
+ break;
2912
+ }
2913
+
2914
+ return ERROR_UNSUPPORTED_STATS_TYPE;
2915
+ }
2916
+
2917
+
2918
+ int
2919
+ validate_barrier_request( const buffer *message ) {
2920
+ return validate_header( message, OFPT_BARRIER_REQUEST, sizeof( struct ofp_header ),
2921
+ sizeof( struct ofp_header ) );
2922
+ }
2923
+
2924
+
2925
+ int
2926
+ validate_barrier_reply( const buffer *message ) {
2927
+ return validate_header( message, OFPT_BARRIER_REPLY, sizeof( struct ofp_header ),
2928
+ sizeof( struct ofp_header ) );
2929
+ }
2930
+
2931
+
2932
+ int
2933
+ validate_queue_get_config_request( const buffer *message ) {
2934
+ int ret;
2935
+ struct ofp_queue_get_config_request *queue_get_config_request;
2936
+
2937
+ ret = validate_header( message, OFPT_QUEUE_GET_CONFIG_REQUEST,
2938
+ sizeof( struct ofp_queue_get_config_request ),
2939
+ sizeof( struct ofp_queue_get_config_request ) );
2940
+ if ( ret < 0 ) {
2941
+ return ret;
2942
+ }
2943
+
2944
+ queue_get_config_request = ( struct ofp_queue_get_config_request * ) message->data;
2945
+
2946
+ ret = validate_phy_port_no( ntohs( queue_get_config_request->port ) );
2947
+ if ( ret < 0 ) {
2948
+ return ret;
2949
+ }
2950
+
2951
+ return 0;
2952
+ }
2953
+
2954
+
2955
+ static int
2956
+ validate_queue_property( const struct ofp_queue_prop_header *property ) {
2957
+ uint16_t property_length = ntohs( property->len );
2958
+
2959
+ if ( property_length < sizeof( struct ofp_queue_prop_header ) ) {
2960
+ return ERROR_TOO_SHORT_QUEUE_PROPERTY;
2961
+ }
2962
+
2963
+ switch ( ntohs( property->property ) ) {
2964
+ case OFPQT_NONE:
2965
+ if ( property_length < sizeof( struct ofp_queue_prop_header ) ) {
2966
+ return ERROR_TOO_SHORT_QUEUE_PROPERTY;
2967
+ }
2968
+ else if ( property_length > sizeof( struct ofp_queue_prop_header ) ) {
2969
+ return ERROR_TOO_LONG_QUEUE_PROPERTY;
2970
+ }
2971
+ break;
2972
+ case OFPQT_MIN_RATE:
2973
+ if ( property_length < sizeof( struct ofp_queue_prop_min_rate ) ) {
2974
+ return ERROR_TOO_SHORT_QUEUE_PROPERTY;
2975
+ }
2976
+ else if ( property_length > sizeof( struct ofp_queue_prop_min_rate ) ) {
2977
+ return ERROR_TOO_LONG_QUEUE_PROPERTY;
2978
+ }
2979
+ break;
2980
+ default:
2981
+ return ERROR_UNDEFINED_QUEUE_PROPERTY;
2982
+ }
2983
+
2984
+ return 0;
2985
+ }
2986
+
2987
+
2988
+ static int
2989
+ validate_queue_properties( struct ofp_queue_prop_header *prop_head,
2990
+ const uint16_t properties_length ) {
2991
+ int ret;
2992
+ uint16_t offset = 0;
2993
+ struct ofp_queue_prop_header *property;
2994
+
2995
+ property = prop_head;
2996
+ while ( offset < properties_length ) {
2997
+ ret = validate_queue_property( property );
2998
+ if ( ret < 0 ) {
2999
+ return ret;
3000
+ }
3001
+
3002
+ offset = ( uint16_t ) ( offset + ntohs( property->len ) );
3003
+ property = ( struct ofp_queue_prop_header * ) ( ( char * ) prop_head + offset );
3004
+ }
3005
+
3006
+ return 0;
3007
+ }
3008
+
3009
+
3010
+ static int
3011
+ validate_packet_queue( struct ofp_packet_queue *queue ) {
3012
+ int ret;
3013
+ uint16_t properties_length;
3014
+ struct ofp_queue_prop_header *prop_head;
3015
+
3016
+ assert( queue != NULL );
3017
+
3018
+ // queue->queue_id
3019
+
3020
+ if ( ntohs( queue->len ) < ( offsetof( struct ofp_packet_queue, properties )
3021
+ + sizeof( struct ofp_queue_prop_header ) ) ) {
3022
+ return ERROR_TOO_SHORT_QUEUE_DESCRIPTION;
3023
+ }
3024
+
3025
+ prop_head = ( struct ofp_queue_prop_header * ) ( ( char * ) queue
3026
+ + offsetof( struct ofp_packet_queue, properties ) );
3027
+ properties_length = ( uint16_t ) ( ntohs( queue->len )
3028
+ - offsetof( struct ofp_packet_queue, properties ) );
3029
+
3030
+ ret = validate_queue_properties( prop_head, properties_length );
3031
+ if ( ret < 0 ) {
3032
+ return ret;
3033
+ }
3034
+
3035
+ return 0;
3036
+ }
3037
+
3038
+
3039
+ static int
3040
+ validate_packet_queues( struct ofp_packet_queue *queue_head, const int n_queues ) {
3041
+ int i;
3042
+ int ret;
3043
+ struct ofp_packet_queue *queue;
3044
+
3045
+ assert( queue_head != NULL );
3046
+
3047
+ queue = queue_head;
3048
+ for ( i = 0; i < n_queues; i++ ) {
3049
+ ret = validate_packet_queue( queue );
3050
+ if ( ret < 0 ) {
3051
+ return ret;
3052
+ }
3053
+ queue = ( struct ofp_packet_queue * ) ( ( char * ) queue + ntohs( queue->len ) );
3054
+ }
3055
+
3056
+ return 0;
3057
+ }
3058
+
3059
+
3060
+ int
3061
+ validate_queue_get_config_reply( const buffer *message ) {
3062
+ int ret;
3063
+ int n_queues = 0;
3064
+ uint16_t queues_length;
3065
+ struct ofp_queue_get_config_reply *queue_get_config_reply;
3066
+ struct ofp_packet_queue *queue_head, *queue;
3067
+
3068
+ assert( message != NULL );
3069
+
3070
+ ret = validate_header( message, OFPT_QUEUE_GET_CONFIG_REPLY,
3071
+ sizeof( struct ofp_queue_get_config_reply ) + sizeof( struct ofp_packet_queue ),
3072
+ UINT16_MAX );
3073
+ if ( ret < 0 ) {
3074
+ return ret;
3075
+ }
3076
+
3077
+ queue_get_config_reply = ( struct ofp_queue_get_config_reply * ) message->data;
3078
+
3079
+ ret = validate_phy_port_no( ntohs( queue_get_config_reply->port ) );
3080
+ if ( ret < 0 ) {
3081
+ return ret;
3082
+ }
3083
+
3084
+ queues_length = ( uint16_t ) ( ntohs( queue_get_config_reply->header.length )
3085
+ - offsetof( struct ofp_queue_get_config_reply, queues ) );
3086
+
3087
+ queue_head = ( struct ofp_packet_queue * ) ( ( char * ) message->data
3088
+ + offsetof( struct ofp_queue_get_config_reply, queues ) );
3089
+
3090
+ queue = queue_head;
3091
+ while ( queues_length > offsetof( struct ofp_packet_queue, properties ) ) {
3092
+ queues_length = ( uint16_t ) ( queues_length - ntohs( queue->len ) );
3093
+ queue = ( struct ofp_packet_queue * ) ( ( char * ) queue + ntohs( queue->len ) );
3094
+ n_queues++;
3095
+ }
3096
+
3097
+ if ( queues_length != 0 ) {
3098
+ return ERROR_INVALID_LENGTH;
3099
+ }
3100
+
3101
+ if ( n_queues > 0 ) {
3102
+ ret = validate_packet_queues( queue_head, n_queues );
3103
+ if ( ret < 0 ) {
3104
+ return ret;
3105
+ }
3106
+ }
3107
+
3108
+ return 0;
3109
+ }
3110
+
3111
+
3112
+ static int
3113
+ validate_action( struct ofp_action_header *action ) {
3114
+ if ( ntohs( action->len ) < sizeof( struct ofp_action_header ) ) {
3115
+ return ERROR_TOO_SHORT_ACTION;
3116
+ }
3117
+
3118
+ switch ( ntohs( action->type ) ) {
3119
+ case OFPAT_OUTPUT:
3120
+ return validate_action_output( ( struct ofp_action_output * ) action );
3121
+ case OFPAT_SET_VLAN_VID:
3122
+ return validate_action_set_vlan_vid( ( struct ofp_action_vlan_vid * ) action );
3123
+ case OFPAT_SET_VLAN_PCP:
3124
+ return validate_action_set_vlan_pcp( ( struct ofp_action_vlan_pcp * ) action );
3125
+ case OFPAT_STRIP_VLAN:
3126
+ return validate_action_strip_vlan( ( struct ofp_action_header * ) action );
3127
+ case OFPAT_SET_DL_SRC:
3128
+ return validate_action_set_dl_src( ( struct ofp_action_dl_addr * ) action );
3129
+ case OFPAT_SET_DL_DST:
3130
+ return validate_action_set_dl_dst( ( struct ofp_action_dl_addr * ) action );
3131
+ case OFPAT_SET_NW_SRC:
3132
+ return validate_action_set_nw_src( ( struct ofp_action_nw_addr * ) action );
3133
+ case OFPAT_SET_NW_DST:
3134
+ return validate_action_set_nw_dst( ( struct ofp_action_nw_addr * ) action );
3135
+ case OFPAT_SET_NW_TOS:
3136
+ return validate_action_set_nw_tos( ( struct ofp_action_nw_tos * ) action );
3137
+ case OFPAT_SET_TP_SRC:
3138
+ return validate_action_set_tp_src( ( struct ofp_action_tp_port * ) action );
3139
+ case OFPAT_SET_TP_DST:
3140
+ return validate_action_set_tp_dst( ( struct ofp_action_tp_port * ) action );
3141
+ case OFPAT_ENQUEUE:
3142
+ return validate_action_enqueue( ( struct ofp_action_enqueue * ) action );
3143
+ case OFPAT_VENDOR:
3144
+ return validate_action_vendor( ( struct ofp_action_vendor_header * ) action );
3145
+ default:
3146
+ break;
3147
+ }
3148
+
3149
+ return ERROR_UNDEFINED_ACTION_TYPE;
3150
+ }
3151
+
3152
+
3153
+ int
3154
+ validate_actions( struct ofp_action_header *actions_head, const uint16_t length ) {
3155
+ int ret;
3156
+ uint16_t offset = 0;
3157
+ struct ofp_action_header *action;
3158
+
3159
+ action = actions_head;
3160
+ while ( offset < length ) {
3161
+ ret = validate_action( action );
3162
+ if ( ret < 0 ) {
3163
+ return ret;
3164
+ }
3165
+
3166
+ offset = ( uint16_t ) ( offset + ntohs( action->len ) );
3167
+ action = ( struct ofp_action_header * ) ( ( char * ) actions_head + offset );
3168
+ }
3169
+
3170
+ return 0;
3171
+ }
3172
+
3173
+
3174
+ int
3175
+ validate_action_output( const struct ofp_action_output *action ) {
3176
+ int ret;
3177
+ struct ofp_action_output output;
3178
+
3179
+ ntoh_action_output( &output, action );
3180
+ if ( output.type != OFPAT_OUTPUT ) {
3181
+ return ERROR_INVALID_ACTION_TYPE;
3182
+ }
3183
+ if ( output.len < sizeof( struct ofp_action_output ) ) {
3184
+ return ERROR_TOO_SHORT_ACTION_OUTPUT;
3185
+ }
3186
+ else if ( output.len > sizeof( struct ofp_action_output ) ) {
3187
+ return ERROR_TOO_LONG_ACTION_OUTPUT;
3188
+ }
3189
+
3190
+ ret = validate_phy_port_no( output.port );
3191
+ if ( ret < 0 ) {
3192
+ return ret;
3193
+ }
3194
+
3195
+ // output.max_len
3196
+
3197
+ return 0;
3198
+ }
3199
+
3200
+
3201
+ int
3202
+ validate_action_set_vlan_vid( const struct ofp_action_vlan_vid *action ) {
3203
+ int ret;
3204
+ struct ofp_action_vlan_vid vlan_vid;
3205
+
3206
+ ntoh_action_vlan_vid( &vlan_vid, action );
3207
+
3208
+ if ( vlan_vid.type != OFPAT_SET_VLAN_VID ) {
3209
+ return ERROR_INVALID_ACTION_TYPE;
3210
+ }
3211
+ if ( vlan_vid.len < sizeof( struct ofp_action_vlan_vid ) ) {
3212
+ return ERROR_TOO_SHORT_ACTION_VLAN_VID;
3213
+ }
3214
+ else if ( vlan_vid.len > sizeof( struct ofp_action_vlan_vid ) ) {
3215
+ return ERROR_TOO_LONG_ACTION_VLAN_VID;
3216
+ }
3217
+
3218
+ ret = validate_vlan_vid( vlan_vid.vlan_vid );
3219
+ if ( ret < 0 ) {
3220
+ return ret;
3221
+ }
3222
+
3223
+ return 0;
3224
+ }
3225
+
3226
+
3227
+ int
3228
+ validate_action_set_vlan_pcp( const struct ofp_action_vlan_pcp *action ) {
3229
+ int ret;
3230
+ struct ofp_action_vlan_pcp vlan_pcp;
3231
+
3232
+ ntoh_action_vlan_pcp( &vlan_pcp, action );
3233
+
3234
+ if ( vlan_pcp.type != OFPAT_SET_VLAN_PCP ) {
3235
+ return ERROR_INVALID_ACTION_TYPE;
3236
+ }
3237
+ if ( vlan_pcp.len < sizeof( struct ofp_action_vlan_pcp ) ) {
3238
+ return ERROR_TOO_SHORT_ACTION_VLAN_PCP;
3239
+ }
3240
+ else if ( vlan_pcp.len > sizeof( struct ofp_action_vlan_pcp ) ) {
3241
+ return ERROR_TOO_LONG_ACTION_VLAN_PCP;
3242
+ }
3243
+
3244
+ ret = validate_vlan_pcp( vlan_pcp.vlan_pcp );
3245
+ if ( ret < 0 ) {
3246
+ return ret;
3247
+ }
3248
+
3249
+ return 0;
3250
+ }
3251
+
3252
+
3253
+ int
3254
+ validate_action_strip_vlan( const struct ofp_action_header *action ) {
3255
+ struct ofp_action_header strip_vlan;
3256
+
3257
+ ntoh_action_strip_vlan( &strip_vlan, action );
3258
+
3259
+ if ( strip_vlan.type != OFPAT_STRIP_VLAN ) {
3260
+ return ERROR_INVALID_ACTION_TYPE;
3261
+ }
3262
+ if ( strip_vlan.len < sizeof( struct ofp_action_header ) ) {
3263
+ return ERROR_TOO_SHORT_ACTION_STRIP_VLAN;
3264
+ }
3265
+ else if ( strip_vlan.len > sizeof( struct ofp_action_header ) ) {
3266
+ return ERROR_TOO_LONG_ACTION_STRIP_VLAN;
3267
+ }
3268
+
3269
+ return 0;
3270
+ }
3271
+
3272
+
3273
+ int
3274
+ validate_action_set_dl_src( const struct ofp_action_dl_addr *action ) {
3275
+ struct ofp_action_dl_addr dl_src;
3276
+
3277
+ ntoh_action_dl_addr( &dl_src, action );
3278
+
3279
+ if ( dl_src.type != OFPAT_SET_DL_SRC ) {
3280
+ return ERROR_INVALID_ACTION_TYPE;
3281
+ }
3282
+ if ( dl_src.len < sizeof( struct ofp_action_dl_addr ) ) {
3283
+ return ERROR_TOO_SHORT_ACTION_DL_SRC;
3284
+ }
3285
+ else if ( dl_src.len > sizeof( struct ofp_action_dl_addr ) ) {
3286
+ return ERROR_TOO_LONG_ACTION_DL_SRC;
3287
+ }
3288
+
3289
+ return 0;
3290
+ }
3291
+
3292
+
3293
+ int
3294
+ validate_action_set_dl_dst( const struct ofp_action_dl_addr *action ) {
3295
+ struct ofp_action_dl_addr dl_dst;
3296
+
3297
+ ntoh_action_dl_addr( &dl_dst, action );
3298
+
3299
+ if ( dl_dst.type != OFPAT_SET_DL_DST ) {
3300
+ return ERROR_INVALID_ACTION_TYPE;
3301
+ }
3302
+ if ( dl_dst.len < sizeof( struct ofp_action_dl_addr ) ) {
3303
+ return ERROR_TOO_SHORT_ACTION_DL_DST;
3304
+ }
3305
+ else if ( dl_dst.len > sizeof( struct ofp_action_dl_addr ) ) {
3306
+ return ERROR_TOO_LONG_ACTION_DL_DST;
3307
+ }
3308
+
3309
+ return 0;
3310
+ }
3311
+
3312
+
3313
+ int
3314
+ validate_action_set_nw_src( const struct ofp_action_nw_addr *action ) {
3315
+ struct ofp_action_nw_addr nw_src;
3316
+
3317
+ ntoh_action_nw_addr( &nw_src, action );
3318
+
3319
+ if ( nw_src.type != OFPAT_SET_NW_SRC ) {
3320
+ return ERROR_INVALID_ACTION_TYPE;
3321
+ }
3322
+ if ( nw_src.len < sizeof( struct ofp_action_nw_addr ) ) {
3323
+ return ERROR_TOO_SHORT_ACTION_NW_SRC;
3324
+ }
3325
+ else if ( nw_src.len > sizeof( struct ofp_action_nw_addr ) ) {
3326
+ return ERROR_TOO_LONG_ACTION_NW_SRC;
3327
+ }
3328
+
3329
+ return 0;
3330
+ }
3331
+
3332
+
3333
+ int
3334
+ validate_action_set_nw_dst( const struct ofp_action_nw_addr *action ) {
3335
+ struct ofp_action_nw_addr nw_dst;
3336
+
3337
+ ntoh_action_nw_addr( &nw_dst, action );
3338
+
3339
+ if ( nw_dst.type != OFPAT_SET_NW_DST ) {
3340
+ return ERROR_INVALID_ACTION_TYPE;
3341
+ }
3342
+ if ( nw_dst.len < sizeof( struct ofp_action_nw_addr ) ) {
3343
+ return ERROR_TOO_SHORT_ACTION_NW_DST;
3344
+ }
3345
+ else if ( nw_dst.len > sizeof( struct ofp_action_nw_addr ) ) {
3346
+ return ERROR_TOO_LONG_ACTION_NW_DST;
3347
+ }
3348
+
3349
+ return 0;
3350
+ }
3351
+
3352
+
3353
+ int
3354
+ validate_action_set_nw_tos( const struct ofp_action_nw_tos *action ) {
3355
+ int ret;
3356
+ struct ofp_action_nw_tos nw_tos;
3357
+
3358
+ ntoh_action_nw_tos( &nw_tos, action );
3359
+
3360
+ if ( nw_tos.type != OFPAT_SET_NW_TOS ) {
3361
+ return ERROR_INVALID_ACTION_TYPE;
3362
+ }
3363
+ if ( nw_tos.len < sizeof( struct ofp_action_nw_addr ) ) {
3364
+ return ERROR_TOO_SHORT_ACTION_NW_TOS;
3365
+ }
3366
+ else if ( nw_tos.len > sizeof( struct ofp_action_nw_addr ) ) {
3367
+ return ERROR_TOO_LONG_ACTION_NW_TOS;
3368
+ }
3369
+
3370
+ ret = validate_nw_tos( nw_tos.nw_tos );
3371
+ if ( ret < 0 ) {
3372
+ return ret;
3373
+ }
3374
+
3375
+ return 0;
3376
+ }
3377
+
3378
+
3379
+ int
3380
+ validate_action_set_tp_src( const struct ofp_action_tp_port *action ) {
3381
+ struct ofp_action_tp_port tp_src;
3382
+
3383
+ ntoh_action_tp_port( &tp_src, action );
3384
+
3385
+ if ( tp_src.type != OFPAT_SET_TP_SRC ) {
3386
+ return ERROR_INVALID_ACTION_TYPE;
3387
+ }
3388
+ if ( tp_src.len < sizeof( struct ofp_action_tp_port ) ) {
3389
+ return ERROR_TOO_SHORT_ACTION_TP_SRC;
3390
+ }
3391
+ else if ( tp_src.len > sizeof( struct ofp_action_tp_port ) ) {
3392
+ return ERROR_TOO_LONG_ACTION_TP_SRC;
3393
+ }
3394
+
3395
+ return 0;
3396
+ }
3397
+
3398
+
3399
+ int
3400
+ validate_action_set_tp_dst( const struct ofp_action_tp_port *action ) {
3401
+ struct ofp_action_tp_port tp_dst;
3402
+
3403
+ ntoh_action_tp_port( &tp_dst, action );
3404
+
3405
+ if ( tp_dst.type != OFPAT_SET_TP_DST ) {
3406
+ return ERROR_INVALID_ACTION_TYPE;
3407
+ }
3408
+ if ( tp_dst.len < sizeof( struct ofp_action_tp_port ) ) {
3409
+ return ERROR_TOO_SHORT_ACTION_TP_DST;
3410
+ }
3411
+ else if ( tp_dst.len > sizeof( struct ofp_action_tp_port ) ) {
3412
+ return ERROR_TOO_LONG_ACTION_TP_DST;
3413
+ }
3414
+
3415
+ return 0;
3416
+ }
3417
+
3418
+
3419
+ int
3420
+ validate_action_enqueue( const struct ofp_action_enqueue *action ) {
3421
+ int ret;
3422
+ struct ofp_action_enqueue enqueue;
3423
+
3424
+ ntoh_action_enqueue( &enqueue, action );
3425
+
3426
+ if ( enqueue.type != OFPAT_ENQUEUE ) {
3427
+ return ERROR_INVALID_ACTION_TYPE;
3428
+ }
3429
+ if ( enqueue.len < sizeof( struct ofp_action_enqueue ) ) {
3430
+ return ERROR_TOO_SHORT_ACTION_ENQUEUE;
3431
+ }
3432
+ else if ( enqueue.len > sizeof( struct ofp_action_enqueue ) ) {
3433
+ return ERROR_TOO_LONG_ACTION_ENQUEUE;
3434
+ }
3435
+
3436
+ ret = validate_phy_port_no( enqueue.port );
3437
+ if ( ret < 0 ) {
3438
+ return ret;
3439
+ }
3440
+
3441
+ // enqueue.queue_id
3442
+
3443
+ return 0;
3444
+ }
3445
+
3446
+
3447
+ int
3448
+ validate_action_vendor( const struct ofp_action_vendor_header *action ) {
3449
+ struct ofp_action_vendor_header vendor;
3450
+
3451
+ ntoh_action_vendor( &vendor, action );
3452
+
3453
+ if ( vendor.type != OFPAT_VENDOR ) {
3454
+ return ERROR_INVALID_ACTION_TYPE;
3455
+ }
3456
+ if ( vendor.len < sizeof( struct ofp_action_vendor_header ) ) {
3457
+ return ERROR_TOO_SHORT_ACTION_VENDOR;
3458
+ }
3459
+
3460
+ // vendor.vendor
3461
+
3462
+ return 0;
3463
+ }
3464
+
3465
+
3466
+ int
3467
+ validate_openflow_message( const buffer *message ) {
3468
+ int ret;
3469
+
3470
+ assert( message != NULL );
3471
+ assert( message->data != NULL );
3472
+
3473
+ struct ofp_header *header = ( struct ofp_header * ) message->data;
3474
+
3475
+ debug( "Validating an OpenFlow message ( version = %#x, type = %#x, length = %u, xid = %#x ).",
3476
+ header->version, header->type, ntohs( header->length ), ntohl( header->xid ) );
3477
+
3478
+ switch ( header->type ) {
3479
+ case OFPT_HELLO:
3480
+ ret = validate_hello( message );
3481
+ break;
3482
+ case OFPT_ERROR:
3483
+ ret = validate_error( message );
3484
+ break;
3485
+ case OFPT_ECHO_REQUEST:
3486
+ ret = validate_echo_request( message );
3487
+ break;
3488
+ case OFPT_ECHO_REPLY:
3489
+ ret = validate_echo_reply( message );
3490
+ break;
3491
+ case OFPT_VENDOR:
3492
+ ret = validate_vendor( message );
3493
+ break;
3494
+ case OFPT_FEATURES_REQUEST:
3495
+ ret = validate_features_request( message );
3496
+ break;
3497
+ case OFPT_FEATURES_REPLY:
3498
+ ret = validate_features_reply( message );
3499
+ break;
3500
+ case OFPT_GET_CONFIG_REQUEST:
3501
+ ret = validate_get_config_request( message );
3502
+ break;
3503
+ case OFPT_GET_CONFIG_REPLY:
3504
+ ret = validate_get_config_reply( message );
3505
+ break;
3506
+ case OFPT_SET_CONFIG:
3507
+ ret = validate_set_config( message );
3508
+ break;
3509
+ case OFPT_PACKET_IN:
3510
+ ret = validate_packet_in( message );
3511
+ break;
3512
+ case OFPT_FLOW_REMOVED:
3513
+ ret = validate_flow_removed( message );
3514
+ break;
3515
+ case OFPT_PORT_STATUS:
3516
+ ret = validate_port_status( message );
3517
+ break;
3518
+ case OFPT_PACKET_OUT:
3519
+ ret = validate_packet_out( message );
3520
+ break;
3521
+ case OFPT_FLOW_MOD:
3522
+ ret = validate_flow_mod( message );
3523
+ break;
3524
+ case OFPT_PORT_MOD:
3525
+ ret = validate_port_mod( message );
3526
+ break;
3527
+ case OFPT_STATS_REQUEST:
3528
+ ret = validate_stats_request( message );
3529
+ break;
3530
+ case OFPT_STATS_REPLY:
3531
+ ret = validate_stats_reply( message );
3532
+ break;
3533
+ case OFPT_BARRIER_REQUEST:
3534
+ ret = validate_barrier_request( message );
3535
+ break;
3536
+ case OFPT_BARRIER_REPLY:
3537
+ ret = validate_barrier_reply( message );
3538
+ break;
3539
+ case OFPT_QUEUE_GET_CONFIG_REQUEST:
3540
+ ret = validate_queue_get_config_request( message );
3541
+ break;
3542
+ case OFPT_QUEUE_GET_CONFIG_REPLY:
3543
+ ret = validate_queue_get_config_reply( message );
3544
+ break;
3545
+ default:
3546
+ ret = ERROR_UNDEFINED_TYPE;
3547
+ break;
3548
+ }
3549
+
3550
+ debug( "Validation completed ( ret = %d ).", ret );
3551
+
3552
+ return ret;
3553
+ }
3554
+
3555
+
3556
+ bool
3557
+ valid_openflow_message( const buffer *message ) {
3558
+ if ( validate_openflow_message( message ) < 0 ) {
3559
+ return false;
3560
+ }
3561
+
3562
+ return true;
3563
+ }
3564
+
3565
+
3566
+ static struct error_map {
3567
+ uint8_t type; // One of the OFPT_ constants.
3568
+ struct map {
3569
+ int error_no; // Internal error number.
3570
+ uint16_t error_type; // OpenFlow error type.
3571
+ uint16_t error_code; // OpenFlow error code.
3572
+ } maps[ 64 ];
3573
+ } error_maps[] = {
3574
+ {
3575
+ OFPT_HELLO,
3576
+ {
3577
+ { ERROR_UNSUPPORTED_VERSION, OFPET_HELLO_FAILED, OFPHFC_INCOMPATIBLE },
3578
+ { ERROR_TOO_SHORT_MESSAGE, OFPET_BAD_REQUEST, OFPBRC_BAD_LEN },
3579
+ { ERROR_TOO_LONG_MESSAGE, OFPET_BAD_REQUEST, OFPBRC_BAD_LEN },
3580
+ { ERROR_UNDEFINED_TYPE, OFPET_BAD_REQUEST, OFPBRC_BAD_TYPE },
3581
+ { ERROR_INVALID_TYPE, OFPET_BAD_REQUEST, OFPBRC_BAD_TYPE },
3582
+ { 0, 0, 0 },
3583
+ }
3584
+ },
3585
+ {
3586
+ OFPT_ERROR,
3587
+ {
3588
+ { ERROR_UNSUPPORTED_VERSION, OFPET_BAD_REQUEST, OFPBRC_BAD_VERSION },
3589
+ { ERROR_TOO_SHORT_MESSAGE, OFPET_BAD_REQUEST, OFPBRC_BAD_LEN },
3590
+ { ERROR_TOO_LONG_MESSAGE, OFPET_BAD_REQUEST, OFPBRC_BAD_LEN },
3591
+ { ERROR_UNDEFINED_TYPE, OFPET_BAD_REQUEST, OFPBRC_BAD_TYPE },
3592
+ { ERROR_INVALID_TYPE, OFPET_BAD_REQUEST, OFPBRC_BAD_TYPE },
3593
+ { 0, 0, 0 },
3594
+ }
3595
+ },
3596
+ {
3597
+ OFPT_ECHO_REQUEST,
3598
+ {
3599
+ { ERROR_UNSUPPORTED_VERSION, OFPET_BAD_REQUEST, OFPBRC_BAD_VERSION },
3600
+ { ERROR_TOO_SHORT_MESSAGE, OFPET_BAD_REQUEST, OFPBRC_BAD_LEN },
3601
+ { ERROR_TOO_LONG_MESSAGE, OFPET_BAD_REQUEST, OFPBRC_BAD_LEN },
3602
+ { ERROR_UNDEFINED_TYPE, OFPET_BAD_REQUEST, OFPBRC_BAD_TYPE },
3603
+ { ERROR_INVALID_TYPE, OFPET_BAD_REQUEST, OFPBRC_BAD_TYPE },
3604
+ { 0, 0, 0 },
3605
+ }
3606
+ },
3607
+ {
3608
+ OFPT_ECHO_REPLY,
3609
+ {
3610
+ { ERROR_UNSUPPORTED_VERSION, OFPET_BAD_REQUEST, OFPBRC_BAD_VERSION },
3611
+ { ERROR_TOO_SHORT_MESSAGE, OFPET_BAD_REQUEST, OFPBRC_BAD_LEN },
3612
+ { ERROR_TOO_LONG_MESSAGE, OFPET_BAD_REQUEST, OFPBRC_BAD_LEN },
3613
+ { ERROR_UNDEFINED_TYPE, OFPET_BAD_REQUEST, OFPBRC_BAD_TYPE },
3614
+ { ERROR_INVALID_TYPE, OFPET_BAD_REQUEST, OFPBRC_BAD_TYPE },
3615
+ { 0, 0, 0 },
3616
+ }
3617
+ },
3618
+ {
3619
+ OFPT_VENDOR,
3620
+ {
3621
+ { ERROR_UNSUPPORTED_VERSION, OFPET_BAD_REQUEST, OFPBRC_BAD_VERSION },
3622
+ { ERROR_TOO_SHORT_MESSAGE, OFPET_BAD_REQUEST, OFPBRC_BAD_LEN },
3623
+ { ERROR_TOO_LONG_MESSAGE, OFPET_BAD_REQUEST, OFPBRC_BAD_LEN },
3624
+ { ERROR_UNDEFINED_TYPE, OFPET_BAD_REQUEST, OFPBRC_BAD_TYPE },
3625
+ { ERROR_INVALID_TYPE, OFPET_BAD_REQUEST, OFPBRC_BAD_TYPE },
3626
+ { 0, 0, 0 },
3627
+ }
3628
+ },
3629
+ {
3630
+ OFPT_FEATURES_REQUEST,
3631
+ {
3632
+ { ERROR_UNSUPPORTED_VERSION, OFPET_BAD_REQUEST, OFPBRC_BAD_VERSION },
3633
+ { ERROR_TOO_SHORT_MESSAGE, OFPET_BAD_REQUEST, OFPBRC_BAD_LEN },
3634
+ { ERROR_TOO_LONG_MESSAGE, OFPET_BAD_REQUEST, OFPBRC_BAD_LEN },
3635
+ { ERROR_UNDEFINED_TYPE, OFPET_BAD_REQUEST, OFPBRC_BAD_TYPE },
3636
+ { ERROR_INVALID_TYPE, OFPET_BAD_REQUEST, OFPBRC_BAD_TYPE },
3637
+ { 0, 0, 0 },
3638
+ }
3639
+ },
3640
+ {
3641
+ OFPT_FEATURES_REPLY,
3642
+ {
3643
+ { ERROR_UNSUPPORTED_VERSION, OFPET_BAD_REQUEST, OFPBRC_BAD_VERSION },
3644
+ { ERROR_TOO_SHORT_MESSAGE, OFPET_BAD_REQUEST, OFPBRC_BAD_LEN },
3645
+ { ERROR_TOO_LONG_MESSAGE, OFPET_BAD_REQUEST, OFPBRC_BAD_LEN },
3646
+ { ERROR_UNDEFINED_TYPE, OFPET_BAD_REQUEST, OFPBRC_BAD_TYPE },
3647
+ { ERROR_INVALID_TYPE, OFPET_BAD_REQUEST, OFPBRC_BAD_TYPE },
3648
+ { 0, 0, 0 },
3649
+ }
3650
+ },
3651
+ {
3652
+ OFPT_GET_CONFIG_REQUEST,
3653
+ {
3654
+ { ERROR_UNSUPPORTED_VERSION, OFPET_BAD_REQUEST, OFPBRC_BAD_VERSION },
3655
+ { ERROR_TOO_SHORT_MESSAGE, OFPET_BAD_REQUEST, OFPBRC_BAD_LEN },
3656
+ { ERROR_TOO_LONG_MESSAGE, OFPET_BAD_REQUEST, OFPBRC_BAD_LEN },
3657
+ { ERROR_UNDEFINED_TYPE, OFPET_BAD_REQUEST, OFPBRC_BAD_TYPE },
3658
+ { ERROR_INVALID_TYPE, OFPET_BAD_REQUEST, OFPBRC_BAD_TYPE },
3659
+ { 0, 0, 0 },
3660
+ }
3661
+ },
3662
+ {
3663
+ OFPT_GET_CONFIG_REPLY,
3664
+ {
3665
+ { ERROR_UNSUPPORTED_VERSION, OFPET_BAD_REQUEST, OFPBRC_BAD_VERSION },
3666
+ { ERROR_TOO_SHORT_MESSAGE, OFPET_BAD_REQUEST, OFPBRC_BAD_LEN },
3667
+ { ERROR_TOO_LONG_MESSAGE, OFPET_BAD_REQUEST, OFPBRC_BAD_LEN },
3668
+ { ERROR_UNDEFINED_TYPE, OFPET_BAD_REQUEST, OFPBRC_BAD_TYPE },
3669
+ { ERROR_INVALID_TYPE, OFPET_BAD_REQUEST, OFPBRC_BAD_TYPE },
3670
+ { 0, 0, 0 },
3671
+ }
3672
+ },
3673
+ {
3674
+ OFPT_SET_CONFIG,
3675
+ {
3676
+ { ERROR_UNSUPPORTED_VERSION, OFPET_BAD_REQUEST, OFPBRC_BAD_VERSION },
3677
+ { ERROR_TOO_SHORT_MESSAGE, OFPET_BAD_REQUEST, OFPBRC_BAD_LEN },
3678
+ { ERROR_TOO_LONG_MESSAGE, OFPET_BAD_REQUEST, OFPBRC_BAD_LEN },
3679
+ { ERROR_UNDEFINED_TYPE, OFPET_BAD_REQUEST, OFPBRC_BAD_TYPE },
3680
+ { ERROR_INVALID_TYPE, OFPET_BAD_REQUEST, OFPBRC_BAD_TYPE },
3681
+ { ERROR_INVALID_SWITCH_CONFIG, OFPET_BAD_REQUEST, OFPBRC_EPERM }, // FIXME
3682
+ { 0, 0, 0 },
3683
+ }
3684
+ },
3685
+ {
3686
+ OFPT_PACKET_IN, // FIXME: Should we return an error for packet_in ?
3687
+ {
3688
+ { ERROR_UNSUPPORTED_VERSION, OFPET_BAD_REQUEST, OFPBRC_BAD_VERSION },
3689
+ { ERROR_TOO_SHORT_MESSAGE, OFPET_BAD_REQUEST, OFPBRC_BAD_LEN },
3690
+ { ERROR_TOO_LONG_MESSAGE, OFPET_BAD_REQUEST, OFPBRC_BAD_LEN },
3691
+ { ERROR_UNDEFINED_TYPE, OFPET_BAD_REQUEST, OFPBRC_BAD_TYPE },
3692
+ { ERROR_INVALID_TYPE, OFPET_BAD_REQUEST, OFPBRC_BAD_TYPE },
3693
+ { ERROR_INVALID_PACKET_IN_REASON, OFPET_BAD_REQUEST, OFPBRC_EPERM }, // FIXME
3694
+ { 0, 0, 0 },
3695
+ }
3696
+ },
3697
+ {
3698
+ OFPT_FLOW_REMOVED, // FIXME: Should we return an error for flow_removed ?
3699
+ {
3700
+ { ERROR_UNSUPPORTED_VERSION, OFPET_BAD_REQUEST, OFPBRC_BAD_VERSION },
3701
+ { ERROR_TOO_SHORT_MESSAGE, OFPET_BAD_REQUEST, OFPBRC_BAD_LEN },
3702
+ { ERROR_TOO_LONG_MESSAGE, OFPET_BAD_REQUEST, OFPBRC_BAD_LEN },
3703
+ { ERROR_UNDEFINED_TYPE, OFPET_BAD_REQUEST, OFPBRC_BAD_TYPE },
3704
+ { ERROR_INVALID_TYPE, OFPET_BAD_REQUEST, OFPBRC_BAD_TYPE },
3705
+ { ERROR_INVALID_FLOW_PRIORITY, OFPET_BAD_REQUEST, OFPBRC_EPERM }, // FIXME
3706
+ { ERROR_INVALID_FLOW_REMOVED_REASON, OFPET_BAD_REQUEST, OFPBRC_EPERM }, // FIXME
3707
+ { 0, 0, 0 },
3708
+ }
3709
+ },
3710
+ {
3711
+ OFPT_PORT_STATUS, // FIXME: Should we return an error for port_status ?
3712
+ {
3713
+ { ERROR_UNSUPPORTED_VERSION, OFPET_BAD_REQUEST, OFPBRC_BAD_VERSION },
3714
+ { ERROR_TOO_SHORT_MESSAGE, OFPET_BAD_REQUEST, OFPBRC_BAD_LEN },
3715
+ { ERROR_TOO_LONG_MESSAGE, OFPET_BAD_REQUEST, OFPBRC_BAD_LEN },
3716
+ { ERROR_UNDEFINED_TYPE, OFPET_BAD_REQUEST, OFPBRC_BAD_TYPE },
3717
+ { ERROR_INVALID_TYPE, OFPET_BAD_REQUEST, OFPBRC_BAD_TYPE },
3718
+ { ERROR_INVALID_PORT_STATUS_REASON, OFPET_BAD_REQUEST, OFPBRC_EPERM }, // FIXME
3719
+ { 0, 0, 0 },
3720
+ }
3721
+ },
3722
+ {
3723
+ OFPT_PACKET_OUT,
3724
+ {
3725
+ { ERROR_UNSUPPORTED_VERSION, OFPET_BAD_REQUEST, OFPBRC_BAD_VERSION },
3726
+ { ERROR_TOO_SHORT_MESSAGE, OFPET_BAD_REQUEST, OFPBRC_BAD_LEN },
3727
+ { ERROR_TOO_LONG_MESSAGE, OFPET_BAD_REQUEST, OFPBRC_BAD_LEN },
3728
+ { ERROR_UNDEFINED_TYPE, OFPET_BAD_REQUEST, OFPBRC_BAD_TYPE },
3729
+ { ERROR_INVALID_TYPE, OFPET_BAD_REQUEST, OFPBRC_BAD_TYPE },
3730
+ { ERROR_INVALID_ACTION_TYPE, OFPET_BAD_ACTION, OFPBAC_BAD_TYPE },
3731
+ { ERROR_TOO_SHORT_ACTION_OUTPUT, OFPET_BAD_ACTION, OFPBAC_BAD_LEN },
3732
+ { ERROR_TOO_LONG_ACTION_OUTPUT, OFPET_BAD_ACTION, OFPBAC_BAD_LEN },
3733
+ { ERROR_INVALID_PORT_NO, OFPET_BAD_ACTION, OFPBAC_BAD_OUT_PORT },
3734
+ { ERROR_TOO_SHORT_ACTION_VLAN_VID, OFPET_BAD_ACTION, OFPBAC_BAD_LEN },
3735
+ { ERROR_TOO_LONG_ACTION_VLAN_VID, OFPET_BAD_ACTION, OFPBAC_BAD_LEN },
3736
+ { ERROR_INVALID_VLAN_VID, OFPET_BAD_ACTION, OFPBAC_BAD_ARGUMENT },
3737
+ { ERROR_TOO_SHORT_ACTION_VLAN_PCP, OFPET_BAD_ACTION, OFPBAC_BAD_LEN },
3738
+ { ERROR_TOO_LONG_ACTION_VLAN_PCP, OFPET_BAD_ACTION, OFPBAC_BAD_LEN },
3739
+ { ERROR_INVALID_VLAN_PCP, OFPET_BAD_ACTION, OFPBAC_BAD_ARGUMENT },
3740
+ { ERROR_TOO_SHORT_ACTION_STRIP_VLAN, OFPET_BAD_ACTION, OFPBAC_BAD_LEN },
3741
+ { ERROR_TOO_LONG_ACTION_STRIP_VLAN, OFPET_BAD_ACTION, OFPBAC_BAD_LEN },
3742
+ { ERROR_TOO_SHORT_ACTION_DL_SRC, OFPET_BAD_ACTION, OFPBAC_BAD_LEN },
3743
+ { ERROR_TOO_LONG_ACTION_DL_SRC, OFPET_BAD_ACTION, OFPBAC_BAD_LEN },
3744
+ { ERROR_TOO_SHORT_ACTION_DL_DST, OFPET_BAD_ACTION, OFPBAC_BAD_LEN },
3745
+ { ERROR_TOO_LONG_ACTION_DL_DST, OFPET_BAD_ACTION, OFPBAC_BAD_LEN },
3746
+ { ERROR_TOO_SHORT_ACTION_NW_SRC, OFPET_BAD_ACTION, OFPBAC_BAD_LEN },
3747
+ { ERROR_TOO_LONG_ACTION_NW_SRC, OFPET_BAD_ACTION, OFPBAC_BAD_LEN },
3748
+ { ERROR_TOO_SHORT_ACTION_NW_DST, OFPET_BAD_ACTION, OFPBAC_BAD_LEN },
3749
+ { ERROR_TOO_LONG_ACTION_NW_DST, OFPET_BAD_ACTION, OFPBAC_BAD_LEN },
3750
+ { ERROR_TOO_SHORT_ACTION_NW_TOS, OFPET_BAD_ACTION, OFPBAC_BAD_LEN },
3751
+ { ERROR_TOO_LONG_ACTION_NW_TOS, OFPET_BAD_ACTION, OFPBAC_BAD_LEN },
3752
+ { ERROR_TOO_SHORT_ACTION_TP_SRC, OFPET_BAD_ACTION, OFPBAC_BAD_LEN },
3753
+ { ERROR_TOO_LONG_ACTION_TP_SRC, OFPET_BAD_ACTION, OFPBAC_BAD_LEN },
3754
+ { ERROR_TOO_SHORT_ACTION_TP_DST, OFPET_BAD_ACTION, OFPBAC_BAD_LEN },
3755
+ { ERROR_TOO_LONG_ACTION_TP_DST, OFPET_BAD_ACTION, OFPBAC_BAD_LEN },
3756
+ { ERROR_TOO_SHORT_ACTION_ENQUEUE, OFPET_BAD_ACTION, OFPBAC_BAD_LEN },
3757
+ { ERROR_TOO_LONG_ACTION_ENQUEUE, OFPET_BAD_ACTION, OFPBAC_BAD_LEN },
3758
+ { ERROR_INVALID_PORT_NO, OFPET_BAD_ACTION, OFPBAC_BAD_OUT_PORT },
3759
+ { ERROR_TOO_SHORT_ACTION_VENDOR, OFPET_BAD_ACTION, OFPBAC_BAD_LEN },
3760
+ { ERROR_UNDEFINED_ACTION_TYPE, OFPET_BAD_ACTION, OFPBAC_BAD_TYPE },
3761
+ { 0, 0, 0 },
3762
+ }
3763
+ },
3764
+ {
3765
+ OFPT_FLOW_MOD,
3766
+ {
3767
+ { ERROR_UNSUPPORTED_VERSION, OFPET_BAD_REQUEST, OFPBRC_BAD_VERSION },
3768
+ { ERROR_TOO_SHORT_MESSAGE, OFPET_BAD_REQUEST, OFPBRC_BAD_LEN },
3769
+ { ERROR_TOO_LONG_MESSAGE, OFPET_BAD_REQUEST, OFPBRC_BAD_LEN },
3770
+ { ERROR_UNDEFINED_TYPE, OFPET_BAD_REQUEST, OFPBRC_BAD_TYPE },
3771
+ { ERROR_INVALID_TYPE, OFPET_BAD_REQUEST, OFPBRC_BAD_TYPE },
3772
+ { ERROR_INVALID_ACTION_TYPE, OFPET_BAD_ACTION, OFPBAC_BAD_TYPE },
3773
+ { ERROR_TOO_SHORT_ACTION_OUTPUT, OFPET_BAD_ACTION, OFPBAC_BAD_LEN },
3774
+ { ERROR_TOO_LONG_ACTION_OUTPUT, OFPET_BAD_ACTION, OFPBAC_BAD_LEN },
3775
+ { ERROR_INVALID_PORT_NO, OFPET_BAD_ACTION, OFPBAC_BAD_OUT_PORT },
3776
+ { ERROR_TOO_SHORT_ACTION_VLAN_VID, OFPET_BAD_ACTION, OFPBAC_BAD_LEN },
3777
+ { ERROR_TOO_LONG_ACTION_VLAN_VID, OFPET_BAD_ACTION, OFPBAC_BAD_LEN },
3778
+ { ERROR_INVALID_VLAN_VID, OFPET_BAD_ACTION, OFPBAC_BAD_ARGUMENT },
3779
+ { ERROR_TOO_SHORT_ACTION_VLAN_PCP, OFPET_BAD_ACTION, OFPBAC_BAD_LEN },
3780
+ { ERROR_TOO_LONG_ACTION_VLAN_PCP, OFPET_BAD_ACTION, OFPBAC_BAD_LEN },
3781
+ { ERROR_INVALID_VLAN_PCP, OFPET_BAD_ACTION, OFPBAC_BAD_ARGUMENT },
3782
+ { ERROR_TOO_SHORT_ACTION_STRIP_VLAN, OFPET_BAD_ACTION, OFPBAC_BAD_LEN },
3783
+ { ERROR_TOO_LONG_ACTION_STRIP_VLAN, OFPET_BAD_ACTION, OFPBAC_BAD_LEN },
3784
+ { ERROR_TOO_SHORT_ACTION_DL_SRC, OFPET_BAD_ACTION, OFPBAC_BAD_LEN },
3785
+ { ERROR_TOO_LONG_ACTION_DL_SRC, OFPET_BAD_ACTION, OFPBAC_BAD_LEN },
3786
+ { ERROR_TOO_SHORT_ACTION_DL_DST, OFPET_BAD_ACTION, OFPBAC_BAD_LEN },
3787
+ { ERROR_TOO_LONG_ACTION_DL_DST, OFPET_BAD_ACTION, OFPBAC_BAD_LEN },
3788
+ { ERROR_TOO_SHORT_ACTION_NW_SRC, OFPET_BAD_ACTION, OFPBAC_BAD_LEN },
3789
+ { ERROR_TOO_LONG_ACTION_NW_SRC, OFPET_BAD_ACTION, OFPBAC_BAD_LEN },
3790
+ { ERROR_TOO_SHORT_ACTION_NW_DST, OFPET_BAD_ACTION, OFPBAC_BAD_LEN },
3791
+ { ERROR_TOO_LONG_ACTION_NW_DST, OFPET_BAD_ACTION, OFPBAC_BAD_LEN },
3792
+ { ERROR_TOO_SHORT_ACTION_NW_TOS, OFPET_BAD_ACTION, OFPBAC_BAD_LEN },
3793
+ { ERROR_TOO_LONG_ACTION_NW_TOS, OFPET_BAD_ACTION, OFPBAC_BAD_LEN },
3794
+ { ERROR_TOO_SHORT_ACTION_TP_SRC, OFPET_BAD_ACTION, OFPBAC_BAD_LEN },
3795
+ { ERROR_TOO_LONG_ACTION_TP_SRC, OFPET_BAD_ACTION, OFPBAC_BAD_LEN },
3796
+ { ERROR_TOO_SHORT_ACTION_TP_DST, OFPET_BAD_ACTION, OFPBAC_BAD_LEN },
3797
+ { ERROR_TOO_LONG_ACTION_TP_DST, OFPET_BAD_ACTION, OFPBAC_BAD_LEN },
3798
+ { ERROR_TOO_SHORT_ACTION_ENQUEUE, OFPET_BAD_ACTION, OFPBAC_BAD_LEN },
3799
+ { ERROR_TOO_LONG_ACTION_ENQUEUE, OFPET_BAD_ACTION, OFPBAC_BAD_LEN },
3800
+ { ERROR_INVALID_PORT_NO, OFPET_BAD_ACTION, OFPBAC_BAD_OUT_PORT },
3801
+ { ERROR_TOO_SHORT_ACTION_VENDOR, OFPET_BAD_ACTION, OFPBAC_BAD_LEN },
3802
+ { ERROR_UNDEFINED_ACTION_TYPE, OFPET_BAD_ACTION, OFPBAC_BAD_TYPE },
3803
+ { ERROR_INVALID_WILDCARDS, OFPET_FLOW_MOD_FAILED, OFPFMFC_EPERM }, // FIXME
3804
+ { ERROR_UNDEFINED_FLOW_MOD_COMMAND, OFPET_FLOW_MOD_FAILED, OFPFMFC_BAD_COMMAND },
3805
+ { ERROR_INVALID_FLOW_PRIORITY, OFPET_FLOW_MOD_FAILED, OFPFMFC_EPERM }, // FIXME
3806
+ { ERROR_INVALID_FLOW_MOD_FLAGS, OFPET_FLOW_MOD_FAILED, OFPFMFC_EPERM }, // FIXME
3807
+ { 0, 0, 0 },
3808
+ }
3809
+ },
3810
+ {
3811
+ OFPT_PORT_MOD,
3812
+ {
3813
+ { ERROR_UNSUPPORTED_VERSION, OFPET_BAD_REQUEST, OFPBRC_BAD_VERSION },
3814
+ { ERROR_TOO_SHORT_MESSAGE, OFPET_BAD_REQUEST, OFPBRC_BAD_LEN },
3815
+ { ERROR_TOO_LONG_MESSAGE, OFPET_BAD_REQUEST, OFPBRC_BAD_LEN },
3816
+ { ERROR_UNDEFINED_TYPE, OFPET_BAD_REQUEST, OFPBRC_BAD_TYPE },
3817
+ { ERROR_INVALID_TYPE, OFPET_BAD_REQUEST, OFPBRC_BAD_TYPE },
3818
+ { ERROR_INVALID_PORT_NO, OFPET_PORT_MOD_FAILED, OFPPMFC_BAD_PORT },
3819
+ { ERROR_INVALID_PORT_CONFIG, OFPET_BAD_REQUEST, OFPBRC_EPERM }, // FIXME
3820
+ { ERROR_INVALID_PORT_MASK, OFPET_BAD_REQUEST, OFPBRC_EPERM }, // FIXME
3821
+ { ERROR_INVALID_PORT_FEATURES, OFPET_BAD_REQUEST, OFPBRC_EPERM }, // FIXME
3822
+ { 0, 0, 0 },
3823
+ }
3824
+ },
3825
+ {
3826
+ OFPT_STATS_REQUEST,
3827
+ {
3828
+ { ERROR_UNSUPPORTED_VERSION, OFPET_BAD_REQUEST, OFPBRC_BAD_VERSION },
3829
+ { ERROR_TOO_SHORT_MESSAGE, OFPET_BAD_REQUEST, OFPBRC_BAD_LEN },
3830
+ { ERROR_TOO_LONG_MESSAGE, OFPET_BAD_REQUEST, OFPBRC_BAD_LEN },
3831
+ { ERROR_UNDEFINED_TYPE, OFPET_BAD_REQUEST, OFPBRC_BAD_TYPE },
3832
+ { ERROR_INVALID_TYPE, OFPET_BAD_REQUEST, OFPBRC_BAD_TYPE },
3833
+ { ERROR_UNSUPPORTED_STATS_TYPE, OFPET_BAD_REQUEST, OFPBRC_BAD_STAT },
3834
+ { ERROR_INVALID_STATS_TYPE, OFPET_BAD_REQUEST, OFPBRC_BAD_STAT },
3835
+ { ERROR_INVALID_STATS_REQUEST_FLAGS, OFPET_BAD_REQUEST, OFPBRC_EPERM }, // FIXME
3836
+ { ERROR_INVALID_PORT_NO, OFPET_BAD_REQUEST, OFPBRC_EPERM }, // FIXME
3837
+ { ERROR_INVALID_WILDCARDS, OFPET_BAD_REQUEST, OFPBRC_EPERM }, // FIXME
3838
+ { ERROR_INVALID_VLAN_VID, OFPET_BAD_REQUEST, OFPBRC_EPERM }, // FIXME
3839
+ { ERROR_INVALID_VLAN_PCP, OFPET_BAD_REQUEST, OFPBRC_EPERM }, // FIXME
3840
+ { ERROR_INVALID_NW_TOS, OFPET_BAD_REQUEST, OFPBRC_EPERM }, // FIXME
3841
+ { 0, 0, 0 },
3842
+ }
3843
+ },
3844
+ {
3845
+ OFPT_STATS_REPLY,
3846
+ {
3847
+ { ERROR_UNSUPPORTED_VERSION, OFPET_BAD_REQUEST, OFPBRC_BAD_VERSION },
3848
+ { ERROR_TOO_SHORT_MESSAGE, OFPET_BAD_REQUEST, OFPBRC_BAD_LEN },
3849
+ { ERROR_TOO_LONG_MESSAGE, OFPET_BAD_REQUEST, OFPBRC_BAD_LEN },
3850
+ { ERROR_UNDEFINED_TYPE, OFPET_BAD_REQUEST, OFPBRC_BAD_TYPE },
3851
+ { ERROR_INVALID_TYPE, OFPET_BAD_REQUEST, OFPBRC_BAD_TYPE },
3852
+ { 0, 0, 0 },
3853
+ }
3854
+ },
3855
+ {
3856
+ OFPT_BARRIER_REQUEST,
3857
+ {
3858
+ { ERROR_UNSUPPORTED_VERSION, OFPET_BAD_REQUEST, OFPBRC_BAD_VERSION },
3859
+ { ERROR_TOO_SHORT_MESSAGE, OFPET_BAD_REQUEST, OFPBRC_BAD_LEN },
3860
+ { ERROR_TOO_LONG_MESSAGE, OFPET_BAD_REQUEST, OFPBRC_BAD_LEN },
3861
+ { ERROR_UNDEFINED_TYPE, OFPET_BAD_REQUEST, OFPBRC_BAD_TYPE },
3862
+ { ERROR_INVALID_TYPE, OFPET_BAD_REQUEST, OFPBRC_BAD_TYPE },
3863
+ { 0, 0, 0 },
3864
+ }
3865
+ },
3866
+ {
3867
+ OFPT_BARRIER_REPLY,
3868
+ {
3869
+ { ERROR_UNSUPPORTED_VERSION, OFPET_BAD_REQUEST, OFPBRC_BAD_VERSION },
3870
+ { ERROR_TOO_SHORT_MESSAGE, OFPET_BAD_REQUEST, OFPBRC_BAD_LEN },
3871
+ { ERROR_TOO_LONG_MESSAGE, OFPET_BAD_REQUEST, OFPBRC_BAD_LEN },
3872
+ { ERROR_UNDEFINED_TYPE, OFPET_BAD_REQUEST, OFPBRC_BAD_TYPE },
3873
+ { ERROR_INVALID_TYPE, OFPET_BAD_REQUEST, OFPBRC_BAD_TYPE },
3874
+ { 0, 0, 0 },
3875
+ }
3876
+ },
3877
+ {
3878
+ OFPT_QUEUE_GET_CONFIG_REQUEST,
3879
+ {
3880
+ { ERROR_UNSUPPORTED_VERSION, OFPET_BAD_REQUEST, OFPBRC_BAD_VERSION },
3881
+ { ERROR_TOO_SHORT_MESSAGE, OFPET_BAD_REQUEST, OFPBRC_BAD_LEN },
3882
+ { ERROR_TOO_LONG_MESSAGE, OFPET_BAD_REQUEST, OFPBRC_BAD_LEN },
3883
+ { ERROR_UNDEFINED_TYPE, OFPET_BAD_REQUEST, OFPBRC_BAD_TYPE },
3884
+ { ERROR_INVALID_TYPE, OFPET_BAD_REQUEST, OFPBRC_BAD_TYPE },
3885
+ { ERROR_INVALID_PORT_NO, OFPET_QUEUE_OP_FAILED, OFPQOFC_BAD_PORT },
3886
+ { 0, 0, 0 },
3887
+ }
3888
+ },
3889
+ {
3890
+ OFPT_QUEUE_GET_CONFIG_REPLY,
3891
+ {
3892
+ { ERROR_UNSUPPORTED_VERSION, OFPET_BAD_REQUEST, OFPBRC_BAD_VERSION },
3893
+ { ERROR_TOO_SHORT_MESSAGE, OFPET_BAD_REQUEST, OFPBRC_BAD_LEN },
3894
+ { ERROR_TOO_LONG_MESSAGE, OFPET_BAD_REQUEST, OFPBRC_BAD_LEN },
3895
+ { ERROR_UNDEFINED_TYPE, OFPET_BAD_REQUEST, OFPBRC_BAD_TYPE },
3896
+ { ERROR_INVALID_TYPE, OFPET_BAD_REQUEST, OFPBRC_BAD_TYPE },
3897
+ { 0, 0, 0 },
3898
+ }
3899
+ },
3900
+ };
3901
+
3902
+
3903
+ bool
3904
+ get_error_type_and_code( const uint8_t type, const int error_no,
3905
+ uint16_t *error_type, uint16_t *error_code ) {
3906
+ if ( type > OFPT_QUEUE_GET_CONFIG_REPLY ) {
3907
+ *error_type = OFPET_BAD_REQUEST;
3908
+ *error_code = OFPBRC_BAD_TYPE;
3909
+ debug( "Undefined OpenFlow message type ( type = %u ).", type );
3910
+ return true;
3911
+ }
3912
+
3913
+ int i = 0;
3914
+ for ( i = 0; error_maps[ type ].maps[ i ].error_no != 0; i++ ) {
3915
+ if ( error_no == error_maps[ type ].maps[ i ].error_no ) {
3916
+ *error_type = error_maps[ type ].maps[ i ].error_type;
3917
+ *error_code = error_maps[ type ].maps[ i ].error_code;
3918
+ return true;
3919
+ }
3920
+ }
3921
+
3922
+ return false;
3923
+ }
3924
+
3925
+
3926
+ void
3927
+ set_match_from_packet( struct ofp_match *match, const uint16_t in_port,
3928
+ const uint32_t wildcards, const buffer *packet ) {
3929
+ // Note that wildcards must be filled before calling this function.
3930
+
3931
+ assert( packet != NULL );
3932
+ assert( packet->user_data != NULL );
3933
+
3934
+ memset( match, 0, sizeof( struct ofp_match ) );
3935
+ match->wildcards = wildcards;
3936
+
3937
+ if ( !( wildcards & OFPFW_IN_PORT ) ) {
3938
+ match->in_port = in_port;
3939
+ }
3940
+ if ( !( wildcards & OFPFW_DL_SRC ) ) {
3941
+ memcpy( match->dl_src, ( ( packet_info * ) packet->user_data )->eth_macsa, OFP_ETH_ALEN );
3942
+ }
3943
+ if ( !( wildcards & OFPFW_DL_DST ) ) {
3944
+ memcpy( match->dl_dst, ( ( packet_info * ) packet->user_data )->eth_macda, OFP_ETH_ALEN );
3945
+ }
3946
+ if ( !( wildcards & OFPFW_DL_VLAN ) ) {
3947
+ if ( packet_type_eth_vtag( packet ) ) {
3948
+ match->dl_vlan = ( ( packet_info * ) packet->user_data )->vlan_vid;
3949
+ if ( ( match->dl_vlan & ~VLAN_VID_MASK ) != 0 ) {
3950
+ warn( "Invalid vlan id ( change %u to %u )", match->dl_vlan, match->dl_vlan & VLAN_VID_MASK );
3951
+ match->dl_vlan = ( uint16_t ) ( match->dl_vlan & VLAN_VID_MASK );
3952
+ }
3953
+ }
3954
+ else {
3955
+ match->dl_vlan = UINT16_MAX;
3956
+ }
3957
+ }
3958
+ if ( !( wildcards & OFPFW_DL_VLAN_PCP ) ) {
3959
+ if ( packet_type_eth_vtag( packet ) ) {
3960
+ match->dl_vlan_pcp = ( ( packet_info * ) packet->user_data )->vlan_prio;
3961
+ if ( ( match->dl_vlan_pcp & ~VLAN_PCP_MASK ) != 0 ) {
3962
+ warn( "Invalid vlan pcp ( change %u to %u )", match->dl_vlan_pcp, match->dl_vlan_pcp & VLAN_PCP_MASK );
3963
+ match->dl_vlan_pcp = ( uint8_t ) ( match->dl_vlan_pcp & VLAN_PCP_MASK );
3964
+ }
3965
+ }
3966
+ }
3967
+ if ( !( wildcards & OFPFW_DL_TYPE ) ) {
3968
+ match->dl_type = ( ( packet_info * ) packet->user_data )->eth_type;
3969
+ }
3970
+ if ( match->dl_type == ETH_ETHTYPE_IPV4 ) {
3971
+ if ( !( wildcards & OFPFW_NW_TOS ) ) {
3972
+ match->nw_tos = ( ( packet_info * ) packet->user_data )->ipv4_tos;
3973
+ if ( ( match->nw_tos & ~NW_TOS_MASK ) != 0 ) {
3974
+ warn( "Invalid ipv4 tos ( change %u to %u )", match->nw_tos, match->nw_tos & NW_TOS_MASK );
3975
+ match->nw_tos = ( uint8_t ) ( match->nw_tos & NW_TOS_MASK );
3976
+ }
3977
+ }
3978
+ if ( !( wildcards & OFPFW_NW_PROTO ) ) {
3979
+ match->nw_proto = ( ( packet_info * ) packet->user_data )->ipv4_protocol;
3980
+ }
3981
+ if ( ( wildcards & OFPFW_NW_SRC_MASK ) == 0 ) {
3982
+ match->nw_src = ( ( packet_info * ) packet->user_data )->ipv4_saddr;
3983
+ }
3984
+ else {
3985
+ match->nw_src = ( ( packet_info * ) packet->user_data )->ipv4_saddr &
3986
+ ( ( wildcards & OFPFW_NW_SRC_MASK ) >> OFPFW_NW_SRC_SHIFT );
3987
+ }
3988
+ if ( ( wildcards & OFPFW_NW_DST_MASK ) == 0 ) {
3989
+ match->nw_dst = ( ( packet_info * ) packet->user_data )->ipv4_daddr;
3990
+ }
3991
+ else {
3992
+ match->nw_dst = ( ( packet_info * ) packet->user_data )->ipv4_daddr &
3993
+ ( ( wildcards & OFPFW_NW_DST_MASK ) >> OFPFW_NW_DST_SHIFT );
3994
+ }
3995
+
3996
+ switch ( match->nw_proto ) {
3997
+ case IPPROTO_ICMP:
3998
+ if ( !( wildcards & OFPFW_ICMP_TYPE ) ) {
3999
+ match->icmp_type = ( ( packet_info * ) packet->user_data )->icmpv4_type;
4000
+ }
4001
+ if ( !( wildcards & OFPFW_ICMP_CODE ) ) {
4002
+ match->icmp_code = ( ( packet_info * ) packet->user_data )->icmpv4_code;
4003
+ }
4004
+ break;
4005
+ case IPPROTO_TCP:
4006
+ if ( !( wildcards & OFPFW_TP_SRC ) ) {
4007
+ match->tp_src = ( ( packet_info * ) packet->user_data )->tcp_src_port;
4008
+ }
4009
+ if ( !( wildcards & OFPFW_TP_DST ) ) {
4010
+ match->tp_dst = ( ( packet_info * ) packet->user_data )->tcp_dst_port;
4011
+ }
4012
+ break;
4013
+ case IPPROTO_UDP:
4014
+ if ( !( wildcards & OFPFW_TP_SRC ) ) {
4015
+ match->tp_src = ( ( packet_info * ) packet->user_data )->udp_src_port;
4016
+ }
4017
+ if ( !( wildcards & OFPFW_TP_DST ) ) {
4018
+ match->tp_dst = ( ( packet_info * ) packet->user_data )->udp_dst_port;
4019
+ }
4020
+ break;
4021
+
4022
+ default:
4023
+ break;
4024
+ }
4025
+ }
4026
+ if ( match->dl_type == ETH_ETHTYPE_ARP ) {
4027
+ if ( !( wildcards & OFPFW_NW_PROTO ) ) {
4028
+ match->nw_proto = ( uint8_t ) ( ( ( packet_info * ) packet->user_data )->arp_ar_op & ARP_OP_MASK );
4029
+ }
4030
+ if ( ( wildcards & OFPFW_NW_SRC_MASK ) == 0 ) {
4031
+ match->nw_src = ( ( packet_info * ) packet->user_data )->arp_spa;
4032
+ }
4033
+ else {
4034
+ match->nw_src = ( ( packet_info * ) packet->user_data )->arp_spa & ( ( wildcards & OFPFW_NW_SRC_MASK ) >> OFPFW_NW_SRC_SHIFT );
4035
+ }
4036
+ if ( ( wildcards & OFPFW_NW_DST_MASK ) == 0 ) {
4037
+ match->nw_dst = ( ( packet_info * ) packet->user_data )->arp_tpa;
4038
+ }
4039
+ else {
4040
+ match->nw_dst = ( ( packet_info * ) packet->user_data )->arp_tpa & ( ( wildcards & OFPFW_NW_DST_MASK ) >> OFPFW_NW_DST_SHIFT );
4041
+ }
4042
+ }
4043
+ }
4044
+
4045
+
4046
+ /*
4047
+ * Local variables:
4048
+ * c-basic-offset: 2
4049
+ * indent-tabs-mode: nil
4050
+ * End:
4051
+ */