lib/pio/open_flow.rb in pio-0.30.0 vs lib/pio/open_flow.rb in pio-0.30.1

- old
+ new

@@ -1,67 +1,53 @@ -require 'pio/open_flow/datapath_id' -require 'pio/open_flow/error' -require 'pio/open_flow/flags' -require 'pio/open_flow/message' -require 'pio/open_flow/open_flow_header' -require 'pio/open_flow10' -require 'pio/open_flow13' +require 'active_support/core_ext/array/access' +require 'active_support/core_ext/module/attribute_accessors' +require 'active_support/core_ext/module/introspection' +require 'pio/open_flow/header' +require 'pio/open_flow/parser' module Pio # Common OpenFlow modules/classes. module OpenFlow - def self.version - fail unless @version - @version - end + mattr_reader :version, instance_reader: false - def self.switch_version(version) - [:Barrier, :Echo, :Features, :FlowMod, :Hello, :Match, - :PacketIn, :FlowRemoved, :PacketOut, :SendOutPort, - :SetSourceMacAddress, :SetDestinationMacAddress, :PortStatus, :Stats, - :FlowStats, :DescriptionStats, :AggregateStats, :TableStats, :PortStats, - :QueueStats, :Error, :SetArpOperation, :SetArpSenderProtocolAddress, - :SetArpSenderHardwareAddress, :NiciraRegMove, :SetMetadata, - :NiciraRegLoad, :NiciraSendOutPort].each do |each| - set_message_class_name each, version - @version = version.to_s + def self.version=(version) + return if OpenFlow.version == version.to_sym + find_all_class_by_version(version).each do |each| + alias_open_flow_class each end + @@version = version.to_sym # rubocop:disable ClassVars + rescue NameError + raise "#{version} is not supported yet." end - # rubocop:disable MethodLength def self.read(binary) - parser = { - 0 => Pio::Hello, - 1 => Pio::OpenFlow::Error, - 2 => Pio::Echo::Request, - 3 => Pio::Echo::Reply, - 5 => Pio::Features::Request, - 6 => Pio::Features::Reply, - 10 => Pio::PacketIn, - 11 => Pio::FlowRemoved, - 12 => Pio::PortStatus, - 13 => Pio::PacketOut, - 14 => Pio::FlowMod, - 16 => Pio::Stats::Request, - 17 => Pio::Stats::Reply, - 18 => Pio::Barrier::Request, - 19 => Pio::Barrier::Reply - } - header = OpenFlowHeaderParser.read(binary) - parser.fetch(header.message_type).read(binary) + header = OpenFlow::Header.read(binary) + self.version = header.version + Parser.find_by_type!(header.type).read(binary) end - # rubocop:enable MethodLength - def self.set_message_class_name(klass_name, version) - open_flow_module = Pio.const_get(version) - return unless open_flow_module.const_defined?(klass_name) - Pio.__send__ :remove_const, klass_name if Pio.const_defined?(klass_name) - Pio.const_set(klass_name, open_flow_module.const_get(klass_name)) - rescue NameError - raise "#{version} is not supported yet." + def self.find_all_class_by_version(version) + all_class = [Message, Instruction, Action, FlowMatch]. + inject([]) do |result, each| + result + each.descendants + end + all_class.select do |each| + each.parents.include?(Class.const_get("Pio::#{version}")) + end end - private_class_method :set_message_class_name + private_class_method :find_all_class_by_version - # The default OpenFlow version is 1.0 - switch_version 'OpenFlow10' + # Pio::OpenFlow10::Hello -> Pio::Hello + def self.alias_open_flow_class(klass) + version = klass.name.split('::').second + class_name = klass.name.split('::').third + if Pio.const_defined?(class_name) + Pio.module_eval { remove_const class_name } + end + Pio.const_set(class_name, "Pio::#{version}::#{class_name}".constantize) + end + private_class_method :alias_open_flow_class end end + +# The default OpenFlow version is 1.0 +Pio::OpenFlow.version = :OpenFlow10