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