pio 0.24.2 → 0.25.0

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.
Files changed (51) hide show
  1. checksums.yaml +4 -4
  2. data/CHANGELOG.md +5 -0
  3. data/README.md +2 -0
  4. data/bin/byebug +16 -0
  5. data/features/arp.feature +2 -2
  6. data/features/dhcp.feature +4 -4
  7. data/features/icmp.feature +2 -2
  8. data/features/lldp.feature +1 -1
  9. data/features/open_flow10/barrier_reply.feature +4 -4
  10. data/features/open_flow10/barrier_request.feature +4 -4
  11. data/features/open_flow10/echo_reply.feature +6 -6
  12. data/features/open_flow10/echo_request.feature +6 -6
  13. data/features/open_flow10/exact_match.feature +2 -2
  14. data/features/open_flow10/features_reply.feature +2 -2
  15. data/features/open_flow10/features_request.feature +4 -4
  16. data/features/open_flow10/flow_mod.feature +6 -6
  17. data/features/open_flow10/flow_stats_reply.feature +105 -0
  18. data/features/open_flow10/flow_stats_request.feature +90 -0
  19. data/features/open_flow10/hello.feature +4 -4
  20. data/features/open_flow10/packet_in.feature +2 -2
  21. data/features/open_flow10/packet_out.feature +1 -1
  22. data/features/open_flow10/port_status.feature +1 -1
  23. data/features/open_flow13/apply_actions.feature +3 -3
  24. data/features/open_flow13/echo_reply.feature +7 -7
  25. data/features/open_flow13/echo_request.feature +7 -7
  26. data/features/open_flow13/features_reply.feature +2 -2
  27. data/features/open_flow13/features_request.feature +4 -4
  28. data/features/open_flow13/flow_mod.feature +5 -5
  29. data/features/open_flow13/goto_table.feature +2 -2
  30. data/features/open_flow13/hello.feature +5 -5
  31. data/features/open_flow13/match.feature +81 -81
  32. data/features/open_flow13/meter.feature +2 -2
  33. data/features/open_flow13/packet_in.feature +3 -3
  34. data/features/open_flow13/packet_out.feature +3 -3
  35. data/features/open_flow13/send_out_port.feature +2 -2
  36. data/features/open_flow13/write_metadata.feature +2 -2
  37. data/features/open_flow_read.feature +12 -10
  38. data/features/step_definitions/packet_data_steps.rb +3 -3
  39. data/lib/pio/open_flow.rb +4 -1
  40. data/lib/pio/open_flow/message.rb +3 -0
  41. data/lib/pio/open_flow10.rb +2 -0
  42. data/lib/pio/open_flow10/flow_mod.rb +1 -16
  43. data/lib/pio/open_flow10/flow_stats_reply.rb +59 -0
  44. data/lib/pio/open_flow10/flow_stats_request.rb +64 -0
  45. data/lib/pio/open_flow10/match.rb +17 -0
  46. data/lib/pio/open_flow10/stats_type.rb +27 -0
  47. data/lib/pio/version.rb +1 -1
  48. data/pio.gemspec +2 -2
  49. data/spec/pio/open_flow10/flow_stats_reply_spec.rb +39 -0
  50. data/spec/pio/open_flow10/flow_stats_request_spec.rb +38 -0
  51. metadata +185 -173
@@ -6,7 +6,7 @@ Feature: Pio::Meter
6
6
  Pio::Meter.new(1)
7
7
  """
8
8
  Then it should finish successfully
9
- And the message have the following fields and values:
9
+ And the message has the following fields and values:
10
10
  | field | value |
11
11
  | class | Pio::Meter |
12
12
  | instruction_type | 6 |
@@ -17,7 +17,7 @@ Feature: Pio::Meter
17
17
  Scenario: read
18
18
  When I try to parse a file named "open_flow13/instruction_meter.raw" with "Pio::Meter" class
19
19
  Then it should finish successfully
20
- And the message have the following fields and values:
20
+ And the message has the following fields and values:
21
21
  | field | value |
22
22
  | class | Pio::Meter |
23
23
  | instruction_type | 6 |
@@ -6,7 +6,7 @@ Feature: Pio::PacketIn
6
6
  Pio::PacketIn.new
7
7
  """
8
8
  Then it should finish successfully
9
- And the message have the following fields and values:
9
+ And the message has the following fields and values:
10
10
  | field | value |
11
11
  | ofp_version | 4 |
12
12
  | message_type | 10 |
@@ -36,7 +36,7 @@ Feature: Pio::PacketIn
36
36
  Pio::PacketIn.new(raw_data: data_dump)
37
37
  """
38
38
  Then it should finish successfully
39
- And the message have the following fields and values:
39
+ And the message has the following fields and values:
40
40
  | field | value |
41
41
  | ofp_version | 4 |
42
42
  | message_length | 94 |
@@ -55,7 +55,7 @@ Feature: Pio::PacketIn
55
55
  Scenario: read
56
56
  When I try to parse a file named "open_flow13/packet_in.raw" with "PacketIn" class
57
57
  Then it should finish successfully
58
- And the message have the following fields and values:
58
+ And the message has the following fields and values:
59
59
  | field | value |
60
60
  | ofp_version | 4 |
61
61
  | message_type | 10 |
@@ -6,7 +6,7 @@ Feature: Pio::PacketOut
6
6
  Pio::PacketOut.new
7
7
  """
8
8
  Then it should finish successfully
9
- And the message have the following fields and values:
9
+ And the message has the following fields and values:
10
10
  | field | value |
11
11
  | ofp_version | 4 |
12
12
  | message_type | 13 |
@@ -34,7 +34,7 @@ Feature: Pio::PacketOut
34
34
  Pio::PacketOut.new(raw_data: data_dump, actions: Pio::SendOutPort.new(1))
35
35
  """
36
36
  Then it should finish successfully
37
- And the message have the following fields and values:
37
+ And the message has the following fields and values:
38
38
  | field | value |
39
39
  | ofp_version | 4 |
40
40
  | message_type | 13 |
@@ -63,7 +63,7 @@ Feature: Pio::PacketOut
63
63
  Scenario: read
64
64
  When I try to parse a file named "open_flow13/packet_out.raw" with "PacketOut" class
65
65
  Then it should finish successfully
66
- And the message have the following fields and values:
66
+ And the message has the following fields and values:
67
67
  | field | value |
68
68
  | ofp_version | 4 |
69
69
  | message_type | 13 |
@@ -6,7 +6,7 @@ Feature: Pio::SendOutPort
6
6
  Pio::SendOutPort.new(1)
7
7
  """
8
8
  Then it should finish successfully
9
- And the message have the following fields and values:
9
+ And the message has the following fields and values:
10
10
  | field | value |
11
11
  | action_type | 0 |
12
12
  | action_length | 16 |
@@ -16,7 +16,7 @@ Feature: Pio::SendOutPort
16
16
  Scenario: read
17
17
  When I try to parse a file named "open_flow13/send_out_port.raw" with "Pio::SendOutPort" class
18
18
  Then it should finish successfully
19
- And the message have the following fields and values:
19
+ And the message has the following fields and values:
20
20
  | field | value |
21
21
  | action_type | 0 |
22
22
  | action_length | 16 |
@@ -6,7 +6,7 @@ Feature: Pio::WriteMetadata
6
6
  Pio::WriteMetadata.new(metadata: 1)
7
7
  """
8
8
  Then it should finish successfully
9
- And the message have the following fields and values:
9
+ And the message has the following fields and values:
10
10
  | field | value |
11
11
  | class | Pio::WriteMetadata |
12
12
  | instruction_type | 2 |
@@ -18,7 +18,7 @@ Feature: Pio::WriteMetadata
18
18
  Scenario: read
19
19
  When I try to parse a file named "open_flow13/instruction_write_metadata.raw" with "Pio::WriteMetadata" class
20
20
  Then it should finish successfully
21
- And the message have the following fields and values:
21
+ And the message has the following fields and values:
22
22
  | field | value |
23
23
  | class | Pio::WriteMetadata |
24
24
  | instruction_type | 2 |
@@ -2,13 +2,15 @@ Feature: Pio::OpenFlow.read
2
2
  Scenario: OpenFlow10
3
3
  Given I switch the Pio::OpenFlow version to "OpenFlow10"
4
4
  Then the following each raw file should be parsed into its corresponding object using OpenFlow.read
5
- | raw file | result object |
6
- | open_flow10/hello.raw | Pio::OpenFlow10::Hello |
7
- | open_flow10/echo_request.raw | Pio::OpenFlow10::Echo::Request |
8
- | open_flow10/echo_reply.raw | Pio::OpenFlow10::Echo::Reply |
9
- | open_flow10/features_request.raw | Pio::OpenFlow10::Features::Request |
10
- | open_flow10/features_reply.raw | Pio::OpenFlow10::Features::Reply |
11
- | open_flow10/packet_in.raw | Pio::OpenFlow10::PacketIn |
12
- | open_flow10/port_status.raw | Pio::OpenFlow10::PortStatus |
13
- | open_flow10/barrier_request.raw | Pio::OpenFlow10::Barrier::Request |
14
- | open_flow10/barrier_reply.raw | Pio::OpenFlow10::Barrier::Reply |
5
+ | raw file | result object |
6
+ | open_flow10/hello.raw | Pio::OpenFlow10::Hello |
7
+ | open_flow10/echo_request.raw | Pio::OpenFlow10::Echo::Request |
8
+ | open_flow10/echo_reply.raw | Pio::OpenFlow10::Echo::Reply |
9
+ | open_flow10/features_request.raw | Pio::OpenFlow10::Features::Request |
10
+ | open_flow10/features_reply.raw | Pio::OpenFlow10::Features::Reply |
11
+ | open_flow10/packet_in.raw | Pio::OpenFlow10::PacketIn |
12
+ | open_flow10/port_status.raw | Pio::OpenFlow10::PortStatus |
13
+ | open_flow10/barrier_request.raw | Pio::OpenFlow10::Barrier::Request |
14
+ | open_flow10/barrier_reply.raw | Pio::OpenFlow10::Barrier::Reply |
15
+ | open_flow10/flow_stats_request.raw | Pio::OpenFlow10::FlowStats::Request |
16
+ | open_flow10/flow_stats_reply.raw | Pio::OpenFlow10::FlowStats::Reply |
@@ -44,7 +44,7 @@ Then(/^the message should be a "([^"]*)"$/) do |expected_klass|
44
44
  expect(@result.class.to_s).to eq(expected_klass)
45
45
  end
46
46
 
47
- Then(/^the packet have the following fields and values:$/) do |table|
47
+ Then(/^the packet has the following fields and values:$/) do |table|
48
48
  table.hashes.each do |each|
49
49
  output = @result.instance_eval("self.#{each['field']}")
50
50
  if /^:/ =~ output.inspect
@@ -55,8 +55,8 @@ Then(/^the packet have the following fields and values:$/) do |table|
55
55
  end
56
56
  end
57
57
 
58
- Then(/^the message have the following fields and values:$/) do |table|
59
- step 'the packet have the following fields and values:', table
58
+ Then(/^the message has the following fields and values:$/) do |table|
59
+ step 'the packet has the following fields and values:', table
60
60
  end
61
61
 
62
62
  # rubocop:disable LineLength
@@ -18,7 +18,8 @@ module Pio
18
18
 
19
19
  def self.switch_version(version)
20
20
  [:Barrier, :Echo, :Features, :FlowMod, :Hello, :Match,
21
- :PacketIn, :PacketOut, :SendOutPort, :PortStatus].each do |each|
21
+ :PacketIn, :PacketOut, :SendOutPort, :PortStatus,
22
+ :FlowStats].each do |each|
22
23
  set_message_class_name each, version
23
24
  @version = version.to_s
24
25
  end
@@ -34,6 +35,8 @@ module Pio
34
35
  6 => Pio::Features::Reply,
35
36
  10 => Pio::PacketIn,
36
37
  12 => Pio::PortStatus,
38
+ 16 => Pio::FlowStats::Request,
39
+ 17 => Pio::FlowStats::Reply,
37
40
  18 => Pio::Barrier::Request,
38
41
  19 => Pio::Barrier::Reply
39
42
  }
@@ -1,3 +1,6 @@
1
+ require 'bindata'
2
+ require 'pio/parse_error'
3
+
1
4
  module Pio
2
5
  module OpenFlow
3
6
  # OpenFlow messages.
@@ -4,6 +4,8 @@ require 'pio/open_flow10/echo'
4
4
  require 'pio/open_flow10/exact_match'
5
5
  require 'pio/open_flow10/features'
6
6
  require 'pio/open_flow10/flow_mod'
7
+ require 'pio/open_flow10/flow_stats_reply'
8
+ require 'pio/open_flow10/flow_stats_request'
7
9
  require 'pio/open_flow10/hello'
8
10
  require 'pio/open_flow10/packet_in'
9
11
  require 'pio/open_flow10/packet_out'
@@ -31,21 +31,6 @@ module Pio
31
31
 
32
32
  # Message body of FlowMod.
33
33
  class Body < BinData::Record
34
- # Pio::MatchFormat wrapper.
35
- class Match < BinData::Primitive
36
- endian :big
37
-
38
- string :match, read_length: 40
39
-
40
- def set(object)
41
- self.match = object.to_binary_s
42
- end
43
-
44
- def get
45
- Pio::OpenFlow10::Match.read match
46
- end
47
- end
48
-
49
34
  extend OpenFlow::Flags
50
35
 
51
36
  flags_16bit :flags,
@@ -55,7 +40,7 @@ module Pio
55
40
 
56
41
  endian :big
57
42
 
58
- match :match
43
+ match_open_flow10 :match
59
44
  uint64 :cookie
60
45
  command :command
61
46
  uint16 :idle_timeout
@@ -0,0 +1,59 @@
1
+ require 'pio/open_flow10/actions'
2
+ require 'pio/open_flow10/stats_type'
3
+
4
+ # Base module.
5
+ module Pio
6
+ # OpenFlow 1.0 messages
7
+ module OpenFlow10
8
+ # OpenFlow 1.0 FlowStats messages
9
+ module FlowStats
10
+ # OpenFlow 1.0 Flow Stats Reply message
11
+ class Reply < OpenFlow::Message
12
+ # Body of reply to Flow Stats Request.
13
+ class FlowStatsEntry < BinData::Record
14
+ endian :big
15
+
16
+ uint16 :entry_length
17
+ uint8 :table_id
18
+ string :padding1, length: 1
19
+ hide :padding1
20
+ match_open_flow10 :match
21
+ uint32 :duration_sec
22
+ uint32 :duration_nsec
23
+ uint16 :priority
24
+ uint16 :idle_timeout
25
+ uint16 :hard_timeout
26
+ string :padding2, length: 6
27
+ hide :padding2
28
+ uint64 :cookie
29
+ uint64 :packet_count
30
+ uint64 :byte_count
31
+ actions :actions, length: -> { entry_length - 88 }
32
+ end
33
+
34
+ # Message body of Flow Stats Reply.
35
+ class Body < BinData::Record
36
+ endian :big
37
+
38
+ stats_type :stats_type, value: -> { :flow }
39
+ uint16 :flags
40
+ array(:stats,
41
+ type: :flow_stats_entry,
42
+ read_until: :eof)
43
+
44
+ def length
45
+ 4 + stats.to_binary_s.length
46
+ end
47
+ end
48
+
49
+ # OpenFlow 1.0 Flow Stats Reply message format.
50
+ class Format < BinData::Record
51
+ extend OpenFlow::Format
52
+
53
+ header version: 1, message_type: 17
54
+ body :body
55
+ end
56
+ end
57
+ end
58
+ end
59
+ end
@@ -0,0 +1,64 @@
1
+ require 'pio/open_flow10/match'
2
+ require 'pio/open_flow10/stats_type'
3
+ require 'pio/open_flow/format'
4
+ require 'pio/open_flow/message'
5
+
6
+ # Base module.
7
+ module Pio
8
+ # OpenFlow 1.0 messages
9
+ module OpenFlow10
10
+ # OpenFlow 1.0 FlowStats messages
11
+ module FlowStats
12
+ # OpenFlow 1.0 Flow Stats Request message
13
+ class Request < OpenFlow::Message
14
+ # Body for Stats Request of type :flow
15
+ class FlowStatsRequestBody < BinData::Record
16
+ endian :big
17
+
18
+ match_open_flow10 :match
19
+ uint8 :table_id, initial_value: 0xff
20
+ string :padding, length: 1
21
+ hide :padding
22
+ port_number :out_port, initial_value: -> { :none }
23
+ end
24
+
25
+ # Message body of Flow Stats Request.
26
+ class Body < BinData::Record
27
+ endian :big
28
+
29
+ stats_type :stats_type, value: -> { :flow }
30
+ uint16 :flags
31
+ choice :stats_request_body, selection: -> { stats_type.to_s } do
32
+ flow_stats_request_body 'flow'
33
+ string :default
34
+ end
35
+
36
+ def length
37
+ 48
38
+ end
39
+
40
+ def method_missing(method, *args, &block)
41
+ stats_request_body.__send__(method, *args, &block)
42
+ end
43
+ end
44
+
45
+ # OpenFlow 1.0 Flow Stats Request message format.
46
+ class Format < BinData::Record
47
+ extend OpenFlow::Format
48
+
49
+ header version: 1, message_type: 16
50
+ body :body
51
+ end
52
+
53
+ body_option :match
54
+
55
+ def initialize(user_options = {})
56
+ validate_user_options user_options
57
+ header_options = parse_header_options(user_options)
58
+ @format = Format.new(header: header_options,
59
+ body: { stats_request_body: user_options })
60
+ end
61
+ end
62
+ end
63
+ end
64
+ end
@@ -161,5 +161,22 @@ module Pio
161
161
  @format.__send__ method, *args, &block
162
162
  end
163
163
  end
164
+
165
+ # Pio::MatchFormat wrapper.
166
+ class MatchOpenFlow10 < BinData::Primitive
167
+ endian :big
168
+
169
+ string :match,
170
+ read_length: 40,
171
+ initial_value: Pio::OpenFlow10::Match.new.to_binary_s
172
+
173
+ def set(object)
174
+ self.match = object.to_binary_s
175
+ end
176
+
177
+ def get
178
+ Pio::OpenFlow10::Match.read match
179
+ end
180
+ end
164
181
  end
165
182
  end
@@ -0,0 +1,27 @@
1
+ module Pio
2
+ module OpenFlow10
3
+ # enum ofp_stats_types
4
+ class StatsType < BinData::Primitive
5
+ STATS_TYPES = {
6
+ description: 0,
7
+ flow: 1,
8
+ aggregate: 2,
9
+ table: 3,
10
+ port: 4,
11
+ queue: 5,
12
+ vendor: 0xffff
13
+ }
14
+
15
+ endian :big
16
+ uint16 :command
17
+
18
+ def get
19
+ STATS_TYPES.invert.fetch(command)
20
+ end
21
+
22
+ def set(value)
23
+ self.command = STATS_TYPES.fetch(value)
24
+ end
25
+ end
26
+ end
27
+ end
@@ -1,5 +1,5 @@
1
1
  # Base module.
2
2
  module Pio
3
3
  # gem version.
4
- VERSION = '0.24.2'.freeze
4
+ VERSION = '0.25.0'.freeze
5
5
  end
@@ -38,7 +38,7 @@ Gem::Specification.new do |gem|
38
38
  gem.add_development_dependency 'guard', '~> 2.13.0'
39
39
  gem.add_development_dependency 'guard-bundler', '~> 2.1.0'
40
40
  gem.add_development_dependency 'guard-cucumber', '~> 1.6.0'
41
- gem.add_development_dependency 'guard-rspec', '~> 4.6.3'
41
+ gem.add_development_dependency 'guard-rspec', '~> 4.6.4'
42
42
  gem.add_development_dependency 'guard-rubocop', '~> 1.2.0'
43
43
  gem.add_development_dependency 'rb-fchange', '~> 0.0.6'
44
44
  gem.add_development_dependency 'rb-fsevent', '~> 0.9.5'
@@ -59,5 +59,5 @@ Gem::Specification.new do |gem|
59
59
  gem.add_development_dependency 'reek', '~> 3.1'
60
60
  gem.add_development_dependency 'rspec', '~> 3.3.0'
61
61
  gem.add_development_dependency 'rspec-given', '~> 3.7.1'
62
- gem.add_development_dependency 'rubocop', '~> 0.32.1'
62
+ gem.add_development_dependency 'rubocop', '~> 0.33.0'
63
63
  end
@@ -0,0 +1,39 @@
1
+ require 'pio/open_flow10/flow_stats_reply'
2
+
3
+ describe Pio::OpenFlow10::FlowStats::Reply do
4
+ describe '.read' do
5
+ context 'with a Flow Stats Reply binary' do
6
+ Given(:binary) do
7
+ [0x01, 0x11, 0x00, 0xe4, 0x00, 0x00, 0x00, 0x06, 0x00, 0x01,
8
+ 0x00, 0x00, 0x00, 0x68, 0x03, 0x00, 0x00, 0x3f, 0xff, 0xff,
9
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
10
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
11
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
12
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01,
13
+ 0x00, 0x00, 0x00, 0x02, 0x00, 0x64, 0x00, 0x05, 0x00, 0x0a,
14
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x23, 0x45, 0x67,
15
+ 0x89, 0xab, 0xcd, 0xef, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
16
+ 0x00, 0x0a, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x03, 0xe8,
17
+ 0x00, 0x00, 0x00, 0x08, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00,
18
+ 0x00, 0x08, 0x00, 0x02, 0x00, 0x00, 0x00, 0x70, 0x04, 0x00,
19
+ 0x00, 0x3f, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
20
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
21
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
22
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
23
+ 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x02, 0x00, 0x64,
24
+ 0x00, 0x05, 0x00, 0x0a, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
25
+ 0x01, 0x23, 0x45, 0x67, 0x89, 0xab, 0xcd, 0xef, 0x00, 0x00,
26
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x0a, 0x00, 0x00, 0x00, 0x00,
27
+ 0x00, 0x00, 0x03, 0xe8, 0x00, 0x00, 0x00, 0x08, 0x00, 0x01,
28
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x08, 0x00, 0x02, 0x00, 0x00,
29
+ 0x00, 0x00, 0x00, 0x08, 0x00, 0x03, 0x00, 0x00].pack('C*')
30
+ end
31
+
32
+ When(:flow_stats_reply) do
33
+ Pio::OpenFlow10::FlowStats::Reply.read(binary)
34
+ end
35
+
36
+ Then { flow_stats_reply.class == Pio::OpenFlow10::FlowStats::Reply }
37
+ end
38
+ end
39
+ end