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