diff --git a/features/open_flow13/copy_field.feature b/features/open_flow13/copy_field.feature new file mode 100644 index 00000000..0b7b8dca --- /dev/null +++ b/features/open_flow13/copy_field.feature @@ -0,0 +1,21 @@ +@open_flow13 +Feature: Pio::CopyField + + Scenario: new(from: :arp_sender_hardware_address, to: :arp_target_hardware_address) + When I try to create an OpenFlow action with: + """ + Pio::CopyField.new(from: :arp_sender_hardware_address, to: :arp_target_hardware_address) + """ + Then it should finish successfully + And the action has the following fields and values: + | field | value | + | action_type.to_hex | 0xffff | + | action_length | 32 | + | experimenter_id.to_hex | 0x4f4e4600 | + | experimenter_type | 3200 | + | from | :arp_sender_hardware_address | + | oxm_ids[0].oxm_field | 24 | + | oxm_ids[0].oxm_length | 6 | + | to | :arp_target_hardware_address | + | oxm_ids[1].oxm_field | 25 | + | oxm_ids[1].oxm_length | 6 | diff --git a/lib/pio/open_flow.rb b/lib/pio/open_flow.rb index b183e574..bab23bf8 100644 --- a/lib/pio/open_flow.rb +++ b/lib/pio/open_flow.rb @@ -21,7 +21,7 @@ def self.switch_version(version) :FlowStats, :DescriptionStats, :AggregateStats, :TableStats, :PortStats, :QueueStats, :Error, :NiciraResubmit, :SetArpOperation, :SetArpSenderProtocolAddress, :SetArpSenderHardwareAddress, - :NiciraResubmitTable].each do |each| + :NiciraResubmitTable, :CopyField].each do |each| set_message_class_name each, version @version = version.to_s end diff --git a/lib/pio/open_flow13.rb b/lib/pio/open_flow13.rb index 29ea0da4..ac786135 100644 --- a/lib/pio/open_flow13.rb +++ b/lib/pio/open_flow13.rb @@ -13,6 +13,7 @@ require 'pio/open_flow13/stats_request' # Actions +require 'pio/open_flow13/copy_field' require 'pio/open_flow13/send_out_port' require 'pio/open_flow13/set_arp_operation' require 'pio/open_flow13/set_arp_sender_hardware_address' diff --git a/lib/pio/open_flow13/copy_field.rb b/lib/pio/open_flow13/copy_field.rb new file mode 100644 index 00000000..36c12497 --- /dev/null +++ b/lib/pio/open_flow13/copy_field.rb @@ -0,0 +1,42 @@ +require 'active_support/core_ext/string/inflections' +require 'pio/open_flow/action' + +module Pio + module OpenFlow13 + # Copy-field action (ONF extension 320) + class CopyField < OpenFlow::Action + action_header action_type: 0xffff, action_length: 32 + uint32 :experimenter_id, value: 0x4f4e4600 + uint16 :experimenter_type, value: 3200 + string :padding1, length: 2 + hide :padding1 + uint16 :n_bits + uint16 :source_offset, value: 0 + uint16 :destination_offset, value: 0 + string :padding2, length: 2 + hide :padding2 + array :oxm_ids, initial_length: 2 do + uint16 :oxm_class, value: Match::OXM_CLASS_OPENFLOW_BASIC + bit7 :oxm_field + bit1 :oxm_hasmask, value: 0 + uint8 :oxm_length + end + string :padding3, length: 4 + hide :padding3 + + attr_reader :from + attr_reader :to + + def initialize(options) + @from = options.fetch(:from) + @to = options.fetch(:to) + from_klass = Match.const_get(@from.to_s.classify) + to_klass = Match.const_get(@to.to_s.classify) + super(oxm_ids: [{ oxm_field: from_klass.const_get(:OXM_FIELD), + oxm_length: from_klass.new.length }, + { oxm_field: to_klass.const_get(:OXM_FIELD), + oxm_length: to_klass.new.length }]) + end + end + end +end diff --git a/pio.gemspec b/pio.gemspec index e4766efe..5d7ecfb5 100644 --- a/pio.gemspec +++ b/pio.gemspec @@ -29,6 +29,7 @@ Gem::Specification.new do |gem| gem.required_ruby_version = '>= 2.0.0' gem.add_dependency 'bindata', '~> 2.1.0' + gem.add_dependency 'activesupport', '~> 4.2', '>= 4.2.4' gem.add_development_dependency 'bundler', '~> 1.10.6' gem.add_development_dependency 'pry', '~> 0.10.3'