trema 0.1.3

Sign up to get free protection for your applications and to get access to all the features.
Files changed (560) hide show
  1. data/.mono.rant +4107 -0
  2. data/.rspec +1 -0
  3. data/.yardopts +4 -0
  4. data/Doxyfile +1679 -0
  5. data/GPL2 +339 -0
  6. data/Gemfile +22 -0
  7. data/Gemfile.lock +71 -0
  8. data/README.md +135 -0
  9. data/Rakefile +140 -0
  10. data/Rantfile +834 -0
  11. data/VERSION +1 -0
  12. data/build.rb +32 -0
  13. data/cruise.rb +389 -0
  14. data/features/example.dumper.feature +87 -0
  15. data/features/example.learning_switch.feature +39 -0
  16. data/features/example.list_switches.feature +38 -0
  17. data/features/example.message.echo_reply.feature +26 -0
  18. data/features/example.message.echo_request.feature +25 -0
  19. data/features/example.message.features_request.feature +84 -0
  20. data/features/example.message.hello.feature +25 -0
  21. data/features/example.message.set_config.feature +27 -0
  22. data/features/example.multi_learning_switch.feature +135 -0
  23. data/features/example.packetin_filter_config.feature +91 -0
  24. data/features/example.repeater_hub.feature +49 -0
  25. data/features/example.switch_monitor.feature +39 -0
  26. data/features/packetin_filter.feature +49 -0
  27. data/features/step_definitions/kill_steps.rb +30 -0
  28. data/features/step_definitions/log_steps.rb +90 -0
  29. data/features/step_definitions/misc_steps.rb +64 -0
  30. data/features/step_definitions/off_steps.rb +30 -0
  31. data/features/step_definitions/run_steps.rb +91 -0
  32. data/features/step_definitions/send_packets_steps.rb +42 -0
  33. data/features/step_definitions/show_stats_steps.rb +43 -0
  34. data/features/step_definitions/stats_steps.rb +39 -0
  35. data/features/support/env.rb +75 -0
  36. data/features/support/hooks.rb +8 -0
  37. data/features/switch_manager.feature +35 -0
  38. data/features/trema-config.feature +68 -0
  39. data/features/trema.dump_flows.feature +25 -0
  40. data/features/trema.feature +25 -0
  41. data/features/trema.kill.feature +53 -0
  42. data/features/trema.killall.feature +30 -0
  43. data/features/trema.reset_stats.feature +14 -0
  44. data/features/trema.run.feature +46 -0
  45. data/features/trema.send_packets.feature +56 -0
  46. data/features/trema.show_stats.feature +67 -0
  47. data/features/tutorial.hello_trema.feature +27 -0
  48. data/features/tutorial.packet_in.feature +47 -0
  49. data/features/tutorial.switch_info.feature +55 -0
  50. data/ruby/.gitignore +4 -0
  51. data/ruby/blocker.rb +78 -0
  52. data/ruby/extconf.rb +71 -0
  53. data/ruby/sub-process.rb +291 -0
  54. data/ruby/trema/action-common.c +60 -0
  55. data/ruby/trema/action-common.h +42 -0
  56. data/ruby/trema/action-enqueue.c +161 -0
  57. data/ruby/trema/action-enqueue.h +40 -0
  58. data/ruby/trema/action-output.c +169 -0
  59. data/ruby/trema/action-output.h +42 -0
  60. data/ruby/trema/action-set-dl-dst.c +131 -0
  61. data/ruby/trema/action-set-dl-dst.h +44 -0
  62. data/ruby/trema/action-set-dl-src.c +131 -0
  63. data/ruby/trema/action-set-dl-src.h +44 -0
  64. data/ruby/trema/action-set-nw-dst.c +135 -0
  65. data/ruby/trema/action-set-nw-dst.h +42 -0
  66. data/ruby/trema/action-set-nw-src.c +140 -0
  67. data/ruby/trema/action-set-nw-src.h +42 -0
  68. data/ruby/trema/action-set-nw-tos.c +124 -0
  69. data/ruby/trema/action-set-nw-tos.h +42 -0
  70. data/ruby/trema/action-set-tp-dst.c +122 -0
  71. data/ruby/trema/action-set-tp-dst.h +42 -0
  72. data/ruby/trema/action-set-tp-src.c +124 -0
  73. data/ruby/trema/action-set-tp-src.h +42 -0
  74. data/ruby/trema/action-set-vlan-pcp.c +128 -0
  75. data/ruby/trema/action-set-vlan-pcp.h +42 -0
  76. data/ruby/trema/action-set-vlan-vid.c +125 -0
  77. data/ruby/trema/action-set-vlan-vid.h +42 -0
  78. data/ruby/trema/action-strip-vlan.c +81 -0
  79. data/ruby/trema/action-strip-vlan.h +42 -0
  80. data/ruby/trema/action-vendor.c +121 -0
  81. data/ruby/trema/action-vendor.h +42 -0
  82. data/ruby/trema/aggregate-stats-reply.rb +70 -0
  83. data/ruby/trema/app.rb +112 -0
  84. data/ruby/trema/barrier-reply.c +99 -0
  85. data/ruby/trema/barrier-reply.h +46 -0
  86. data/ruby/trema/barrier-request.c +108 -0
  87. data/ruby/trema/barrier-request.h +44 -0
  88. data/ruby/trema/cli.rb +269 -0
  89. data/ruby/trema/command.rb +40 -0
  90. data/ruby/trema/command/dump_flows.rb +62 -0
  91. data/ruby/trema/command/kill.rb +71 -0
  92. data/ruby/trema/command/killall.rb +56 -0
  93. data/ruby/trema/command/reset_stats.rb +61 -0
  94. data/ruby/trema/command/ruby.rb +55 -0
  95. data/ruby/trema/command/run.rb +120 -0
  96. data/ruby/trema/command/send_packets.rb +130 -0
  97. data/ruby/trema/command/shell.rb +61 -0
  98. data/ruby/trema/command/show_stats.rb +84 -0
  99. data/ruby/trema/command/usage.rb +61 -0
  100. data/ruby/trema/command/version.rb +39 -0
  101. data/ruby/trema/controller.c +595 -0
  102. data/ruby/trema/controller.h +44 -0
  103. data/ruby/trema/controller.rb +81 -0
  104. data/ruby/trema/daemon.rb +167 -0
  105. data/ruby/trema/dsl.rb +34 -0
  106. data/ruby/trema/dsl/configuration.rb +153 -0
  107. data/ruby/trema/dsl/context.rb +71 -0
  108. data/ruby/trema/dsl/link.rb +41 -0
  109. data/ruby/trema/dsl/parser.rb +70 -0
  110. data/ruby/trema/dsl/run.rb +49 -0
  111. data/ruby/trema/dsl/runner.rb +165 -0
  112. data/ruby/trema/dsl/stanza.rb +53 -0
  113. data/ruby/trema/dsl/switch.rb +78 -0
  114. data/ruby/trema/dsl/syntax-error.rb +33 -0
  115. data/ruby/trema/dsl/syntax.rb +109 -0
  116. data/ruby/trema/dsl/vhost.rb +108 -0
  117. data/ruby/trema/dsl/vswitch.rb +47 -0
  118. data/ruby/trema/echo-reply.c +107 -0
  119. data/ruby/trema/echo-reply.h +42 -0
  120. data/ruby/trema/echo-request.c +140 -0
  121. data/ruby/trema/echo-request.h +42 -0
  122. data/ruby/trema/error.c +253 -0
  123. data/ruby/trema/error.h +44 -0
  124. data/ruby/trema/exact-match.rb +36 -0
  125. data/ruby/trema/executables.rb +95 -0
  126. data/ruby/trema/features-reply.c +238 -0
  127. data/ruby/trema/features-reply.h +60 -0
  128. data/ruby/trema/features-request.c +109 -0
  129. data/ruby/trema/features-request.h +44 -0
  130. data/ruby/trema/flow-removed.c +275 -0
  131. data/ruby/trema/flow-removed.h +46 -0
  132. data/ruby/trema/flow-stats-reply.rb +109 -0
  133. data/ruby/trema/flow.rb +56 -0
  134. data/ruby/trema/get-config-reply.c +159 -0
  135. data/ruby/trema/get-config-reply.h +52 -0
  136. data/ruby/trema/get-config-request.c +107 -0
  137. data/ruby/trema/get-config-request.h +44 -0
  138. data/ruby/trema/hello.c +110 -0
  139. data/ruby/trema/hello.h +44 -0
  140. data/ruby/trema/host.rb +257 -0
  141. data/ruby/trema/ip.rb +101 -0
  142. data/ruby/trema/link.rb +176 -0
  143. data/ruby/trema/list-switches-reply.c +46 -0
  144. data/ruby/trema/list-switches-reply.h +40 -0
  145. data/ruby/trema/logger.c +162 -0
  146. data/ruby/trema/logger.h +44 -0
  147. data/ruby/trema/mac.rb +151 -0
  148. data/ruby/trema/match.c +594 -0
  149. data/ruby/trema/match.h +36 -0
  150. data/ruby/trema/monkey-patch/integer.rb +35 -0
  151. data/ruby/trema/monkey-patch/integer/base-conversions.rb +36 -0
  152. data/ruby/trema/monkey-patch/integer/ranges.rb +51 -0
  153. data/ruby/trema/monkey-patch/module.rb +33 -0
  154. data/ruby/trema/monkey-patch/module/deprecation.rb +41 -0
  155. data/ruby/trema/monkey-patch/string.rb +33 -0
  156. data/ruby/trema/monkey-patch/string/inflectors.rb +54 -0
  157. data/ruby/trema/network-component.rb +153 -0
  158. data/ruby/trema/ofctl.rb +62 -0
  159. data/ruby/trema/open-vswitch.rb +154 -0
  160. data/ruby/trema/openflow-error.c +191 -0
  161. data/ruby/trema/openflow-error.h +53 -0
  162. data/ruby/trema/openflow-switch.rb +88 -0
  163. data/ruby/trema/ordered-hash.rb +74 -0
  164. data/ruby/trema/packet-queue.rb +178 -0
  165. data/ruby/trema/packet_in.c +736 -0
  166. data/ruby/trema/packet_in.h +46 -0
  167. data/ruby/trema/packetin-filter.rb +126 -0
  168. data/ruby/trema/path.rb +135 -0
  169. data/ruby/trema/phost.rb +69 -0
  170. data/ruby/trema/port-mod.c +226 -0
  171. data/ruby/trema/port-mod.h +36 -0
  172. data/ruby/trema/port-stats-reply.rb +111 -0
  173. data/ruby/trema/port-status.c +156 -0
  174. data/ruby/trema/port-status.h +45 -0
  175. data/ruby/trema/port.c +295 -0
  176. data/ruby/trema/port.h +47 -0
  177. data/ruby/trema/process.rb +76 -0
  178. data/ruby/trema/queue-get-config-reply.c +200 -0
  179. data/ruby/trema/queue-get-config-reply.h +47 -0
  180. data/ruby/trema/queue-get-config-request.c +141 -0
  181. data/ruby/trema/queue-get-config-request.h +44 -0
  182. data/ruby/trema/queue-stats-reply.rb +78 -0
  183. data/ruby/trema/set-config.c +171 -0
  184. data/ruby/trema/set-config.h +44 -0
  185. data/ruby/trema/shell.rb +39 -0
  186. data/ruby/trema/shell/down.rb +39 -0
  187. data/ruby/trema/shell/killall.rb +40 -0
  188. data/ruby/trema/shell/link.rb +61 -0
  189. data/ruby/trema/shell/reset_stats.rb +50 -0
  190. data/ruby/trema/shell/run.rb +67 -0
  191. data/ruby/trema/shell/send_packets.rb +42 -0
  192. data/ruby/trema/shell/show_stats.rb +49 -0
  193. data/ruby/trema/shell/up.rb +43 -0
  194. data/ruby/trema/shell/vhost.rb +44 -0
  195. data/ruby/trema/shell/vswitch.rb +49 -0
  196. data/ruby/trema/stats-helper.rb +65 -0
  197. data/ruby/trema/stats-reply.c +483 -0
  198. data/ruby/trema/stats-reply.h +53 -0
  199. data/ruby/trema/stats-request.c +634 -0
  200. data/ruby/trema/stats-request.h +42 -0
  201. data/ruby/trema/switch-daemon.rb +74 -0
  202. data/ruby/trema/switch-disconnected.c +40 -0
  203. data/ruby/trema/switch-disconnected.h +38 -0
  204. data/ruby/trema/switch-manager.rb +121 -0
  205. data/ruby/trema/switch.rb +37 -0
  206. data/ruby/trema/table-stats-reply.rb +87 -0
  207. data/ruby/trema/timers.rb +97 -0
  208. data/ruby/trema/trema.c +122 -0
  209. data/ruby/trema/tremashark.rb +39 -0
  210. data/ruby/trema/util.rb +84 -0
  211. data/ruby/trema/vendor-request.c +193 -0
  212. data/ruby/trema/vendor-request.h +44 -0
  213. data/ruby/trema/vendor-stats-reply.rb +62 -0
  214. data/ruby/trema/vendor.c +152 -0
  215. data/ruby/trema/vendor.h +52 -0
  216. data/ruby/trema/version.rb +30 -0
  217. data/spec/spec_helper.rb +153 -0
  218. data/spec/support/openflow-message.rb +94 -0
  219. data/spec/trema/action-enqueue_spec.rb +100 -0
  220. data/spec/trema/action-output_spec.rb +116 -0
  221. data/spec/trema/action-set-dl-dst_spec.rb +95 -0
  222. data/spec/trema/action-set-dl-src_spec.rb +92 -0
  223. data/spec/trema/action-set-nw-dst_spec.rb +96 -0
  224. data/spec/trema/action-set-nw-src_spec.rb +97 -0
  225. data/spec/trema/action-set-nw-tos_spec.rb +88 -0
  226. data/spec/trema/action-set-tp-dst_spec.rb +88 -0
  227. data/spec/trema/action-set-tp-src_spec.rb +88 -0
  228. data/spec/trema/action-set-vlan-pcp_spec.rb +91 -0
  229. data/spec/trema/action-set-vlan-vid_spec.rb +91 -0
  230. data/spec/trema/action-strip-vlan_spec.rb +57 -0
  231. data/spec/trema/action-vendor_spec.rb +90 -0
  232. data/spec/trema/app_spec.rb +90 -0
  233. data/spec/trema/barrier-reply_spec.rb +45 -0
  234. data/spec/trema/barrier-request_spec.rb +83 -0
  235. data/spec/trema/cli_spec.rb +160 -0
  236. data/spec/trema/controller_spec.rb +100 -0
  237. data/spec/trema/dsl/configuration_spec.rb +122 -0
  238. data/spec/trema/dsl/link_spec.rb +54 -0
  239. data/spec/trema/dsl/run_spec.rb +78 -0
  240. data/spec/trema/dsl/runner_spec.rb +239 -0
  241. data/spec/trema/dsl/switch_spec.rb +77 -0
  242. data/spec/trema/dsl/syntax_spec.rb +121 -0
  243. data/spec/trema/dsl/vhost_spec.rb +148 -0
  244. data/spec/trema/dsl/vswitch_spec.rb +90 -0
  245. data/spec/trema/echo-reply_spec.rb +49 -0
  246. data/spec/trema/echo-request_spec.rb +75 -0
  247. data/spec/trema/error_spec.rb +142 -0
  248. data/spec/trema/executables_spec.rb +75 -0
  249. data/spec/trema/features-reply_spec.rb +57 -0
  250. data/spec/trema/features-request_spec.rb +66 -0
  251. data/spec/trema/flow-removed_spec.rb +146 -0
  252. data/spec/trema/get-config-reply_spec.rb +43 -0
  253. data/spec/trema/get-config-request_spec.rb +82 -0
  254. data/spec/trema/hello_spec.rb +49 -0
  255. data/spec/trema/host_spec.rb +193 -0
  256. data/spec/trema/link_spec.rb +64 -0
  257. data/spec/trema/list-switches-reply_spec.rb +48 -0
  258. data/spec/trema/logger_spec.rb +48 -0
  259. data/spec/trema/mac_spec.rb +115 -0
  260. data/spec/trema/match_spec.rb +113 -0
  261. data/spec/trema/open-vswitch_spec.rb +123 -0
  262. data/spec/trema/openflow-error_spec.rb +141 -0
  263. data/spec/trema/openflow-switch_spec.rb +56 -0
  264. data/spec/trema/packet-in_spec.rb +168 -0
  265. data/spec/trema/packet-out_spec.rb +128 -0
  266. data/spec/trema/packetin-filter_spec.rb +41 -0
  267. data/spec/trema/port-mod_spec.rb +101 -0
  268. data/spec/trema/port-status_spec.rb +108 -0
  269. data/spec/trema/port_spec.rb +61 -0
  270. data/spec/trema/process_spec.rb +71 -0
  271. data/spec/trema/queue-get-config-reply_spec.rb +66 -0
  272. data/spec/trema/queue-get-config-request_spec.rb +69 -0
  273. data/spec/trema/set-config_spec.rb +80 -0
  274. data/spec/trema/shell/vhost_spec.rb +57 -0
  275. data/spec/trema/shell/vswitch_spec.rb +89 -0
  276. data/spec/trema/stats-reply_spec.rb +306 -0
  277. data/spec/trema/stats-request_spec.rb +151 -0
  278. data/spec/trema/switch-disconnected_spec.rb +58 -0
  279. data/spec/trema/switch-manager_spec.rb +43 -0
  280. data/spec/trema/tremashark_spec.rb +41 -0
  281. data/spec/trema/util_spec.rb +93 -0
  282. data/spec/trema/vendor-request_spec.rb +79 -0
  283. data/src/examples/cbench_switch/README +21 -0
  284. data/src/examples/cbench_switch/cbench-switch.rb +39 -0
  285. data/src/examples/cbench_switch/cbench_switch.c +68 -0
  286. data/src/examples/dumper/dumper.c +370 -0
  287. data/src/examples/dumper/dumper.conf +7 -0
  288. data/src/examples/dumper/dumper.rb +196 -0
  289. data/src/examples/hello_trema/README +13 -0
  290. data/src/examples/hello_trema/hello_trema.c +51 -0
  291. data/src/examples/hello_trema/hello_trema.conf +3 -0
  292. data/src/examples/hello_trema/hello_trema.rb +35 -0
  293. data/src/examples/learning_switch/README +15 -0
  294. data/src/examples/learning_switch/fdb.rb +112 -0
  295. data/src/examples/learning_switch/learning-switch.rb +88 -0
  296. data/src/examples/learning_switch/learning_switch.c +236 -0
  297. data/src/examples/learning_switch/learning_switch.conf +18 -0
  298. data/src/examples/list_switches/README +19 -0
  299. data/src/examples/list_switches/list-switches.rb +45 -0
  300. data/src/examples/list_switches/list_switches.c +81 -0
  301. data/src/examples/list_switches/list_switches.conf +15 -0
  302. data/src/examples/match_compare/match-compare.conf +30 -0
  303. data/src/examples/match_compare/match-compare.rb +99 -0
  304. data/src/examples/multi_learning_switch/README +14 -0
  305. data/src/examples/multi_learning_switch/multi-learning-switch.rb +96 -0
  306. data/src/examples/multi_learning_switch/multi_learning_switch.c +296 -0
  307. data/src/examples/multi_learning_switch/multi_learning_switch.conf +17 -0
  308. data/src/examples/openflow_message/README +11 -0
  309. data/src/examples/openflow_message/echo-reply.rb +59 -0
  310. data/src/examples/openflow_message/echo-request.rb +58 -0
  311. data/src/examples/openflow_message/echo_reply.c +70 -0
  312. data/src/examples/openflow_message/echo_request.c +70 -0
  313. data/src/examples/openflow_message/example.rb +63 -0
  314. data/src/examples/openflow_message/features-request.rb +97 -0
  315. data/src/examples/openflow_message/features_request.c +168 -0
  316. data/src/examples/openflow_message/hello.c +70 -0
  317. data/src/examples/openflow_message/hello.rb +58 -0
  318. data/src/examples/openflow_message/set-config.rb +59 -0
  319. data/src/examples/openflow_message/set_config.c +70 -0
  320. data/src/examples/packet_in/README +15 -0
  321. data/src/examples/packet_in/packet_in.c +55 -0
  322. data/src/examples/packet_in/packet_in.conf +15 -0
  323. data/src/examples/packet_in/packet_in.rb +34 -0
  324. data/src/examples/packetin_filter_config/README +12 -0
  325. data/src/examples/packetin_filter_config/add_filter.c +73 -0
  326. data/src/examples/packetin_filter_config/delete_filter.c +65 -0
  327. data/src/examples/packetin_filter_config/delete_filter_strict.c +75 -0
  328. data/src/examples/packetin_filter_config/dump_filter.c +65 -0
  329. data/src/examples/packetin_filter_config/dump_filter_strict.c +75 -0
  330. data/src/examples/packetin_filter_config/packetin_filter_config.c +134 -0
  331. data/src/examples/packetin_filter_config/packetin_filter_config.conf +7 -0
  332. data/src/examples/packetin_filter_config/utils.c +102 -0
  333. data/src/examples/packetin_filter_config/utils.h +42 -0
  334. data/src/examples/repeater_hub/README +8 -0
  335. data/src/examples/repeater_hub/repeater-hub.rb +43 -0
  336. data/src/examples/repeater_hub/repeater-hub_spec.rb +156 -0
  337. data/src/examples/repeater_hub/repeater_hub.c +83 -0
  338. data/src/examples/repeater_hub/repeater_hub.conf +28 -0
  339. data/src/examples/switch_info/README +13 -0
  340. data/src/examples/switch_info/switch_info.c +80 -0
  341. data/src/examples/switch_info/switch_info.conf +3 -0
  342. data/src/examples/switch_info/switch_info.rb +46 -0
  343. data/src/examples/switch_monitor/switch-monitor.conf +3 -0
  344. data/src/examples/switch_monitor/switch-monitor.rb +58 -0
  345. data/src/examples/switch_monitor/switch_monitor.c +154 -0
  346. data/src/examples/traffic_monitor/counter.c +74 -0
  347. data/src/examples/traffic_monitor/counter.h +48 -0
  348. data/src/examples/traffic_monitor/counter.rb +46 -0
  349. data/src/examples/traffic_monitor/fdb.c +76 -0
  350. data/src/examples/traffic_monitor/fdb.h +50 -0
  351. data/src/examples/traffic_monitor/fdb.rb +44 -0
  352. data/src/examples/traffic_monitor/traffic-monitor.rb +100 -0
  353. data/src/examples/traffic_monitor/traffic_monitor.c +163 -0
  354. data/src/examples/traffic_monitor/traffic_monitor.conf +16 -0
  355. data/src/lib/arp.h +61 -0
  356. data/src/lib/bool.h +49 -0
  357. data/src/lib/buffer.c +305 -0
  358. data/src/lib/buffer.h +56 -0
  359. data/src/lib/byteorder.c +547 -0
  360. data/src/lib/byteorder.h +110 -0
  361. data/src/lib/checks.h +42 -0
  362. data/src/lib/daemon.c +302 -0
  363. data/src/lib/daemon.h +42 -0
  364. data/src/lib/doubly_linked_list.c +281 -0
  365. data/src/lib/doubly_linked_list.h +88 -0
  366. data/src/lib/ether.c +48 -0
  367. data/src/lib/ether.h +94 -0
  368. data/src/lib/etherip.h +46 -0
  369. data/src/lib/event_handler.c +389 -0
  370. data/src/lib/event_handler.h +64 -0
  371. data/src/lib/hash_table.c +417 -0
  372. data/src/lib/hash_table.h +138 -0
  373. data/src/lib/icmp.h +74 -0
  374. data/src/lib/igmp.h +50 -0
  375. data/src/lib/ipv4.h +50 -0
  376. data/src/lib/linked_list.c +199 -0
  377. data/src/lib/linked_list.h +84 -0
  378. data/src/lib/log.c +402 -0
  379. data/src/lib/log.h +78 -0
  380. data/src/lib/match.h +84 -0
  381. data/src/lib/match_table.c +608 -0
  382. data/src/lib/match_table.h +51 -0
  383. data/src/lib/message_queue.c +143 -0
  384. data/src/lib/message_queue.h +61 -0
  385. data/src/lib/messenger.c +1714 -0
  386. data/src/lib/messenger.h +145 -0
  387. data/src/lib/openflow_application_interface.c +1673 -0
  388. data/src/lib/openflow_application_interface.h +329 -0
  389. data/src/lib/openflow_message.c +4051 -0
  390. data/src/lib/openflow_message.h +288 -0
  391. data/src/lib/openflow_service_interface.h +59 -0
  392. data/src/lib/packet_info.c +230 -0
  393. data/src/lib/packet_info.h +209 -0
  394. data/src/lib/packet_parser.c +502 -0
  395. data/src/lib/packetin_filter_interface.c +294 -0
  396. data/src/lib/packetin_filter_interface.h +127 -0
  397. data/src/lib/persistent_storage.c +480 -0
  398. data/src/lib/persistent_storage.h +46 -0
  399. data/src/lib/stat.c +213 -0
  400. data/src/lib/stat.h +44 -0
  401. data/src/lib/tcp.h +67 -0
  402. data/src/lib/timer.c +350 -0
  403. data/src/lib/timer.h +53 -0
  404. data/src/lib/trema.c +710 -0
  405. data/src/lib/trema.h +79 -0
  406. data/src/lib/trema_private.c +177 -0
  407. data/src/lib/trema_private.h +60 -0
  408. data/src/lib/trema_wrapper.c +56 -0
  409. data/src/lib/trema_wrapper.h +64 -0
  410. data/src/lib/udp.h +43 -0
  411. data/src/lib/utility.c +515 -0
  412. data/src/lib/utility.h +67 -0
  413. data/src/lib/wrapper.c +100 -0
  414. data/src/lib/wrapper.h +76 -0
  415. data/src/packetin_filter/README +17 -0
  416. data/src/packetin_filter/packetin_filter.c +575 -0
  417. data/src/switch_manager/README +20 -0
  418. data/src/switch_manager/cookie_table.c +292 -0
  419. data/src/switch_manager/cookie_table.h +72 -0
  420. data/src/switch_manager/dpid_table.c +110 -0
  421. data/src/switch_manager/dpid_table.h +46 -0
  422. data/src/switch_manager/management_interface.h +44 -0
  423. data/src/switch_manager/ofpmsg_recv.c +482 -0
  424. data/src/switch_manager/ofpmsg_recv.h +42 -0
  425. data/src/switch_manager/ofpmsg_send.c +235 -0
  426. data/src/switch_manager/ofpmsg_send.h +50 -0
  427. data/src/switch_manager/secure_channel_listener.c +281 -0
  428. data/src/switch_manager/secure_channel_listener.h +42 -0
  429. data/src/switch_manager/secure_channel_receiver.c +126 -0
  430. data/src/switch_manager/secure_channel_receiver.h +43 -0
  431. data/src/switch_manager/secure_channel_sender.c +126 -0
  432. data/src/switch_manager/secure_channel_sender.h +43 -0
  433. data/src/switch_manager/service_interface.c +181 -0
  434. data/src/switch_manager/service_interface.h +46 -0
  435. data/src/switch_manager/switch.c +538 -0
  436. data/src/switch_manager/switch.h +51 -0
  437. data/src/switch_manager/switch_manager.c +448 -0
  438. data/src/switch_manager/switch_manager.h +63 -0
  439. data/src/switch_manager/switchinfo.h +72 -0
  440. data/src/switch_manager/xid_table.c +184 -0
  441. data/src/switch_manager/xid_table.h +56 -0
  442. data/src/tremashark/README +78 -0
  443. data/src/tremashark/packet_capture.c +357 -0
  444. data/src/tremashark/pcap_private.h +47 -0
  445. data/src/tremashark/pcap_queue.c +197 -0
  446. data/src/tremashark/pcap_queue.h +58 -0
  447. data/src/tremashark/plugin/.gitignore +6 -0
  448. data/src/tremashark/plugin/packet-trema/.gitignore +5 -0
  449. data/src/tremashark/plugin/packet-trema/Makefile +77 -0
  450. data/src/tremashark/plugin/packet-trema/Makefile.am +110 -0
  451. data/src/tremashark/plugin/packet-trema/Makefile.common +31 -0
  452. data/src/tremashark/plugin/packet-trema/moduleinfo.h +41 -0
  453. data/src/tremashark/plugin/packet-trema/packet-trema.c +1659 -0
  454. data/src/tremashark/plugin/packet-trema/plugin.c +31 -0
  455. data/src/tremashark/plugin/user_dlts +2 -0
  456. data/src/tremashark/queue.c +168 -0
  457. data/src/tremashark/queue.h +60 -0
  458. data/src/tremashark/stdin_relay.c +257 -0
  459. data/src/tremashark/syslog_relay.c +247 -0
  460. data/src/tremashark/tremashark.c +556 -0
  461. data/trema +93 -0
  462. data/trema-config +61 -0
  463. data/unittests/buffer_stubs.c +74 -0
  464. data/unittests/cmockery_trema.c +123 -0
  465. data/unittests/cmockery_trema.h +96 -0
  466. data/unittests/lib/buffer_test.c +370 -0
  467. data/unittests/lib/byteorder_test.c +1717 -0
  468. data/unittests/lib/daemon_test.c +664 -0
  469. data/unittests/lib/doubly_linked_list_test.c +346 -0
  470. data/unittests/lib/ether_test.c +127 -0
  471. data/unittests/lib/hash_table_test.c +278 -0
  472. data/unittests/lib/linked_list_test.c +343 -0
  473. data/unittests/lib/log_test.c +459 -0
  474. data/unittests/lib/match_table_test.c +1509 -0
  475. data/unittests/lib/message_queue_test.c +379 -0
  476. data/unittests/lib/messenger_test.c +438 -0
  477. data/unittests/lib/openflow_application_interface_test.c +3488 -0
  478. data/unittests/lib/openflow_message_test.c +7337 -0
  479. data/unittests/lib/packet_info_test.c +544 -0
  480. data/unittests/lib/packet_parser_test.c +703 -0
  481. data/unittests/lib/packetin_filter_interface_test.c +723 -0
  482. data/unittests/lib/persistent_storage_test.c +802 -0
  483. data/unittests/lib/stat_test.c +291 -0
  484. data/unittests/lib/test_packets/arp_rep.cap +0 -0
  485. data/unittests/lib/test_packets/arp_req.cap +0 -0
  486. data/unittests/lib/test_packets/icmp_echo_rep.cap +0 -0
  487. data/unittests/lib/test_packets/icmp_echo_req.cap +0 -0
  488. data/unittests/lib/test_packets/igmp_query_v2.cap +0 -0
  489. data/unittests/lib/test_packets/ipx.cap +0 -0
  490. data/unittests/lib/test_packets/lldp.cap +0 -0
  491. data/unittests/lib/test_packets/lldp_over_ip.cap +0 -0
  492. data/unittests/lib/test_packets/tcp.cap +0 -0
  493. data/unittests/lib/test_packets/tcp_syn.cap +0 -0
  494. data/unittests/lib/test_packets/udp.cap +0 -0
  495. data/unittests/lib/test_packets/udp_frag_head.cap +0 -0
  496. data/unittests/lib/test_packets/udp_frag_next.cap +0 -0
  497. data/unittests/lib/test_packets/vtag_icmp_echo_rep.cap +0 -0
  498. data/unittests/lib/test_packets/vtag_icmp_echo_req.cap +0 -0
  499. data/unittests/lib/timer_test.c +248 -0
  500. data/unittests/lib/trema_private_test.c +323 -0
  501. data/unittests/lib/trema_test.c +985 -0
  502. data/unittests/lib/utility_test.c +628 -0
  503. data/unittests/lib/wrapper_test.c +201 -0
  504. data/unittests/packetin_filter/packetin_filter_test.c +477 -0
  505. data/unittests/switch_manager/switch_manager_test.c +1178 -0
  506. data/unittests/wrapper_stubs.c +39 -0
  507. data/vendor/.gitignore +6 -0
  508. data/vendor/README +30 -0
  509. data/vendor/cmockery-20110428.tar.gz +0 -0
  510. data/vendor/oflops-0.03.tar.gz +0 -0
  511. data/vendor/oflops_no_snmp+1.0.0.patch +340 -0
  512. data/vendor/openflow-1.0.0.tar.gz +0 -0
  513. data/vendor/openflow.git.tar.gz +0 -0
  514. data/vendor/openvswitch-1.2.2.tar.gz +0 -0
  515. data/vendor/ruby-ifconfig-1.2/COPYING +340 -0
  516. data/vendor/ruby-ifconfig-1.2/Changelog +16 -0
  517. data/vendor/ruby-ifconfig-1.2/INSTALL +239 -0
  518. data/vendor/ruby-ifconfig-1.2/README +38 -0
  519. data/vendor/ruby-ifconfig-1.2/Rakefile +14 -0
  520. data/vendor/ruby-ifconfig-1.2/TODO +8 -0
  521. data/vendor/ruby-ifconfig-1.2/ifconfig_examples/darwin.txt +17 -0
  522. data/vendor/ruby-ifconfig-1.2/ifconfig_examples/dragonflybsd.txt +10 -0
  523. data/vendor/ruby-ifconfig-1.2/ifconfig_examples/dragonflybsd_netstat.txt +14 -0
  524. data/vendor/ruby-ifconfig-1.2/ifconfig_examples/freebsd.txt +17 -0
  525. data/vendor/ruby-ifconfig-1.2/ifconfig_examples/freebsd_netstat.txt +24 -0
  526. data/vendor/ruby-ifconfig-1.2/ifconfig_examples/linux.txt +60 -0
  527. data/vendor/ruby-ifconfig-1.2/ifconfig_examples/linux_ethernet.txt +20 -0
  528. data/vendor/ruby-ifconfig-1.2/ifconfig_examples/netbsd.txt +10 -0
  529. data/vendor/ruby-ifconfig-1.2/ifconfig_examples/openbsd.txt +36 -0
  530. data/vendor/ruby-ifconfig-1.2/ifconfig_examples/sunos.txt +10 -0
  531. data/vendor/ruby-ifconfig-1.2/lib/ifconfig.rb +71 -0
  532. data/vendor/ruby-ifconfig-1.2/lib/ifconfig/bsd/ifconfig.rb +72 -0
  533. data/vendor/ruby-ifconfig-1.2/lib/ifconfig/bsd/interface_types.rb +69 -0
  534. data/vendor/ruby-ifconfig-1.2/lib/ifconfig/bsd/network_types.rb +3 -0
  535. data/vendor/ruby-ifconfig-1.2/lib/ifconfig/common/ifconfig.rb +84 -0
  536. data/vendor/ruby-ifconfig-1.2/lib/ifconfig/common/interface_types.rb +130 -0
  537. data/vendor/ruby-ifconfig-1.2/lib/ifconfig/common/network_types.rb +49 -0
  538. data/vendor/ruby-ifconfig-1.2/lib/ifconfig/linux/ifconfig.rb +43 -0
  539. data/vendor/ruby-ifconfig-1.2/lib/ifconfig/linux/interface_types.rb +112 -0
  540. data/vendor/ruby-ifconfig-1.2/lib/ifconfig/linux/network_types.rb +55 -0
  541. data/vendor/ruby-ifconfig-1.2/lib/ifconfig/sunos/ifconfig.rb +38 -0
  542. data/vendor/ruby-ifconfig-1.2/lib/ifconfig/sunos/interface_types.rb +77 -0
  543. data/vendor/ruby-ifconfig-1.2/lib/ifconfig/sunos/network_types.rb +4 -0
  544. data/vendor/ruby-ifconfig-1.2/setup.rb +1306 -0
  545. data/vendor/ruby-ifconfig-1.2/test/test_bsd.rb +35 -0
  546. data/vendor/ruby-ifconfig-1.2/test/test_darwin.rb +33 -0
  547. data/vendor/ruby-ifconfig-1.2/test/test_dragonflybsd.rb +35 -0
  548. data/vendor/ruby-ifconfig-1.2/test/test_helper.rb +4 -0
  549. data/vendor/ruby-ifconfig-1.2/test/test_linux.rb +31 -0
  550. data/vendor/ruby-ifconfig-1.2/test/test_netbsd.rb +33 -0
  551. data/vendor/ruby-ifconfig-1.2/test/test_openbsd.rb +33 -0
  552. data/vendor/ruby-ifconfig-1.2/test/test_sunos.rb +35 -0
  553. data/vendor/ruby-ifconfig-1.2/test/unit/tc_darwin.rb +40 -0
  554. data/vendor/ruby-ifconfig-1.2/test/unit/tc_dragonflybsd.rb +39 -0
  555. data/vendor/ruby-ifconfig-1.2/test/unit/tc_freebsd.rb +40 -0
  556. data/vendor/ruby-ifconfig-1.2/test/unit/tc_linux.rb +49 -0
  557. data/vendor/ruby-ifconfig-1.2/test/unit/tc_netbsd.rb +39 -0
  558. data/vendor/ruby-ifconfig-1.2/test/unit/tc_openbsd.rb +39 -0
  559. data/vendor/ruby-ifconfig-1.2/test/unit/tc_sunos.rb +44 -0
  560. metadata +856 -0
@@ -0,0 +1,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
+ */