pio 0.11.2 → 0.12.0

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: 0a56473e633e294a1756d819645ccee51e6440cd
4
- data.tar.gz: 8d6d9fc9c7625281475858f76e090a9e4f1038d6
3
+ metadata.gz: 2bb4195ca95f655a64ce7c02ec9884a3bad1fd7c
4
+ data.tar.gz: 33cd84c8eb3e5289672c80e27d27b9c189b71303
5
5
  SHA512:
6
- metadata.gz: 1fadec47b009cab08eb3565b864952f050aa2a82477b2e9298a760691958fc998cdcf34ddc5fdbade680b5849e9e79c6ee61b8ab452b43e803ec64c3bfda93df
7
- data.tar.gz: 5dcb89e55d28bc69dd59325829ac1bb740bfbde2516980aa41af5f15aafb01fac17e3f6d4224503e5c18a07f05a9c38473735076192863c6bf2ddbec1b6663e3
6
+ metadata.gz: cea7f5346912379c9f0cf5800a8f57d997694126679c241dacefaeb0f4bcc0597f5debfd63ca151d8e2226418b59beba0aa8fabab5cb60068f4ba0751dffedad
7
+ data.tar.gz: 98b9e42fc3995ba700d0d1d75bc852bd3bd9a4a1c30b538802b6b56b8d80f95ce53d0711226bd778aca87d1f7d3736976d124fd98add04843302a6d8847c2e12
@@ -1,5 +1,14 @@
1
1
  # Changelog
2
2
 
3
+ ## develop (unreleased)
4
+
5
+
6
+ ## 0.12.0 (2/5/2015)
7
+
8
+ ### New features
9
+ * [#123](https://github.com/trema/pio/pull/123): Add new class `Pio::ExactMatch`.
10
+
11
+
3
12
  ## 0.11.2 (1/29/2015)
4
13
 
5
14
  ### Bugs fixed
@@ -0,0 +1,38 @@
1
+ Feature: Pio::ExactMatch.new
2
+ Scenario: packet_in_arp_request.raw
3
+ Given a packet data file "packet_in_arp_request.raw"
4
+ When I try to create an exact match from the packet
5
+ And the parsed data have the following field and value:
6
+ | field | value |
7
+ | wildcards | {} |
8
+ | in_port | 1 |
9
+ | dl_src | ac:5d:10:31:37:79 |
10
+ | dl_dst | ff:ff:ff:ff:ff:ff |
11
+ | dl_vlan | 65535 |
12
+ | dl_vlan_pcp | 0 |
13
+ | dl_type | 2054 |
14
+ | nw_tos | 0 |
15
+ | nw_proto | 1 |
16
+ | nw_src | 192.168.2.254 |
17
+ | nw_dst | 192.168.2.5 |
18
+ | tp_src | 0 |
19
+ | tp_dst | 0 |
20
+
21
+ Scenario: packet_in_cbench.raw (ARP request)
22
+ Given a packet data file "packet_in_cbench.raw"
23
+ When I try to create an exact match from the packet
24
+ And the parsed data have the following field and value:
25
+ | field | value |
26
+ | wildcards | {} |
27
+ | in_port | 1 |
28
+ | dl_src | 00:00:00:00:00:01 |
29
+ | dl_dst | 80:00:00:00:00:01 |
30
+ | dl_vlan | 65535 |
31
+ | dl_vlan_pcp | 0 |
32
+ | dl_type | 2048 |
33
+ | nw_tos | 0 |
34
+ | nw_proto | 255 |
35
+ | nw_src | 192.168.0.40 |
36
+ | nw_dst | 192.168.1.40 |
37
+ | tp_src | 31256 |
38
+ | tp_dst | 22635 |
@@ -1,6 +1,6 @@
1
1
  Feature: Pio::PacketIn.read
2
- Scenario: packet_in.raw
3
- Given a packet data file "packet_in.raw"
2
+ Scenario: packet_in_arp_request.raw
3
+ Given a packet data file "packet_in_arp_request.raw"
4
4
  When I try to parse the file with "PacketIn" class
5
5
  Then it should finish successfully
6
6
  And the parsed data have the following field and value:
@@ -25,6 +25,10 @@ When(/^I try to parse the file with "(.*?)" class$/) do |parser|
25
25
  end
26
26
  end
27
27
 
28
+ When(/^I try to create an exact match from the packet$/) do
29
+ @result = Pio::ExactMatch.new(Pio::PacketIn.read(IO.read(@raw)))
30
+ end
31
+
28
32
  Then(/^it should finish successfully$/) do
29
33
  # Noop.
30
34
  end
data/lib/pio.rb CHANGED
@@ -3,6 +3,7 @@ require 'pio/parse_error'
3
3
  require 'pio/arp'
4
4
  require 'pio/dhcp'
5
5
  require 'pio/echo'
6
+ require 'pio/exact_match'
6
7
  require 'pio/features'
7
8
  require 'pio/flow_mod'
8
9
  require 'pio/hello'
@@ -1,32 +1,19 @@
1
- require 'forwardable'
2
1
  require 'pio/arp/format'
3
2
 
4
3
  module Pio
5
4
  class Arp
6
5
  # Base class of ARP Request and Reply
7
6
  class Message
8
- extend Forwardable
9
-
10
- def_delegators :@format, :destination_mac
11
- def_delegators :@format, :source_mac
12
- def_delegators :@format, :ether_type
13
- def_delegators :@format, :hardware_type
14
- def_delegators :@format, :protocol_type
15
- def_delegators :@format, :hardware_length
16
- def_delegators :@format, :protocol_length
17
- def_delegators :@format, :operation
18
- def_delegators :@format, :sender_hardware_address
19
- def_delegators :@format, :sender_protocol_address
20
- def_delegators :@format, :target_hardware_address
21
- def_delegators :@format, :target_protocol_address
22
- def_delegators :@format, :to_binary
23
-
24
7
  private_class_method :new
25
8
 
26
9
  def initialize(user_options)
27
10
  options = self.class.const_get(:Options).new(user_options.dup.freeze)
28
11
  @format = Arp::Format.new(options.to_hash)
29
12
  end
13
+
14
+ def method_missing(method, *args)
15
+ @format.__send__ method, *args
16
+ end
30
17
  end
31
18
  end
32
19
  end
@@ -0,0 +1,106 @@
1
+ require 'pio/match'
2
+ require 'pio/type/ethernet_header'
3
+
4
+ module Pio
5
+ # OpenFlow 1.0 exact match
6
+ class ExactMatch
7
+ # Pio::PacketIn#data parser
8
+ class PacketInDataParser
9
+ # Ethernet header parser
10
+ class EthernetHeaderParser < BinData::Record
11
+ extend Pio::Type::EthernetHeader
12
+
13
+ endian :big
14
+
15
+ ethernet_header
16
+ rest :payload
17
+ end
18
+
19
+ # IPv4 packet parser
20
+ class IPv4Packet < BinData::Record
21
+ extend Pio::Type::EthernetHeader
22
+ extend Type::IPv4Header
23
+
24
+ endian :big
25
+
26
+ ethernet_header
27
+ ipv4_header
28
+
29
+ uint16 :transport_source_port
30
+ uint16 :transport_destination_port
31
+ rest :rest
32
+ end
33
+
34
+ def self.read(raw_data)
35
+ ethernet_header = EthernetHeaderParser.read(raw_data)
36
+ case ethernet_header.ether_type
37
+ when 0x0800
38
+ IPv4Packet.read raw_data
39
+ when 0x0806
40
+ Pio::Arp.read raw_data
41
+ else
42
+ fail 'Failed to parse packet_in data.'
43
+ end
44
+ end
45
+ end
46
+
47
+ extend Forwardable
48
+
49
+ # rubocop:disable MethodLength
50
+ # rubocop:disable AbcSize
51
+ def initialize(packet_in)
52
+ data = PacketInDataParser.read(packet_in.data)
53
+ case data
54
+ when PacketInDataParser::IPv4Packet
55
+ options = {
56
+ in_port: packet_in.in_port,
57
+ dl_src: data.source_mac,
58
+ dl_dst: data.destination_mac,
59
+ dl_vlan: data.vlan_vid,
60
+ dl_vlan_pcp: data.vlan_pcp,
61
+ dl_type: data.ether_type,
62
+ nw_tos: data.ip_type_of_service,
63
+ nw_proto: data.ip_protocol,
64
+ nw_src: data.ip_source_address,
65
+ nw_dst: data.ip_destination_address,
66
+ tp_src: data.transport_source_port,
67
+ tp_dst: data.transport_destination_port
68
+ }
69
+ when Arp::Request
70
+ options = {
71
+ in_port: packet_in.in_port,
72
+ dl_src: data.source_mac,
73
+ dl_dst: data.destination_mac,
74
+ dl_vlan: data.vlan_vid,
75
+ dl_vlan_pcp: data.vlan_pcp,
76
+ dl_type: data.ether_type,
77
+ nw_tos: 0,
78
+ nw_proto: data.operation,
79
+ nw_src: data.sender_protocol_address,
80
+ nw_dst: data.target_protocol_address,
81
+ tp_src: 0,
82
+ tp_dst: 0
83
+ }
84
+ end
85
+ @match = Pio::Match.new(options)
86
+ end
87
+ # rubocop:enable MethodLength
88
+ # rubocop:enable AbcSize
89
+
90
+ def_delegator :@match, :wildcards
91
+ def_delegator :@match, :in_port
92
+ def_delegator :@match, :dl_src
93
+ def_delegator :@match, :dl_dst
94
+ def_delegator :@match, :dl_vlan
95
+ def_delegator :@match, :dl_vlan_pcp
96
+ def_delegator :@match, :dl_type
97
+ def_delegator :@match, :nw_tos
98
+ def_delegator :@match, :nw_proto
99
+ def_delegator :@match, :nw_src
100
+ def_delegator :@match, :nw_dst
101
+ def_delegator :@match, :tp_src
102
+ def_delegator :@match, :tp_dst
103
+ def_delegator :@match, :to_binary_s
104
+ def_delegator :@match, :to_binary_s, :to_binary
105
+ end
106
+ end
@@ -26,10 +26,8 @@ module Pio
26
26
  @value = IPAddr.new(addr, Socket::AF_INET)
27
27
  when String
28
28
  @value = IPAddr.new(addr)
29
- when IPv4Address
30
- @value = addr.value
31
29
  else
32
- fail TypeError, "Invalid IPv4 address: #{addr.inspect}"
30
+ @value = addr.value
33
31
  end
34
32
  end
35
33
 
@@ -4,13 +4,40 @@ module Pio
4
4
  module Type
5
5
  # Adds ethernet_header macro.
6
6
  module EthernetHeader
7
- def ethernet_header(options)
7
+ # rubocop:disable MethodLength
8
+ # rubocop:disable AbcSize
9
+ def ethernet_header(options = { ether_type: 0x0800 })
8
10
  class_eval do
9
11
  mac_address :destination_mac
10
12
  mac_address :source_mac
11
- uint16 :ether_type, value: options[:ether_type]
13
+ uint16 :ether_type_internal, initial_value: options[:ether_type]
14
+
15
+ bit3 :vlan_pcp_internal, onlyif: -> { vlan? }
16
+ bit1 :vlan_cfi, onlyif: -> { vlan? }
17
+ bit12 :vlan_vid_internal, onlyif: -> { vlan? }
18
+
19
+ uint16 :ether_type_vlan, onlyif: -> { vlan? },
20
+ initial_value: options[:ether_type]
21
+
22
+ def ether_type
23
+ ether_type_internal
24
+ end
25
+
26
+ def vlan_vid
27
+ vlan? ? vlan_vid_internal : 0xffff
28
+ end
29
+
30
+ def vlan_pcp
31
+ vlan? ? vlan_pcp_internal : 0
32
+ end
33
+
34
+ def vlan?
35
+ ether_type == 0x8100
36
+ end
12
37
  end
13
38
  end
39
+ # rubocop:enable MethodLength
40
+ # rubocop:enable AbcSize
14
41
  end
15
42
  end
16
43
  end
@@ -7,22 +7,23 @@ module Pio
7
7
  # This method smells of :reek:TooManyStatements
8
8
  # rubocop:disable MethodLength
9
9
  # rubocop:disable AbcSize
10
- def ipv4_header(options)
10
+ def ipv4_header(options = {})
11
11
  class_eval do
12
12
  bit4 :ip_version, initial_value: 0x4
13
13
  bit4 :ip_header_length, initial_value: 0x5
14
14
  uint8 :ip_type_of_service, initial_value: 0
15
15
  uint16be :ip_total_length,
16
- initial_value: options[:ip_total_length]
16
+ initial_value: options[:ip_total_length] || 0
17
17
  uint16be :ip_identifier, initial_value: 0
18
18
  bit3 :ip_flag, initial_value: 0
19
19
  bit13 :ip_fragment, initial_value: 0
20
20
  uint8 :ip_ttl, initial_value: 128
21
- uint8 :ip_protocol, value: options[:ip_protocol]
21
+ uint8 :ip_protocol, initial_value: options[:ip_protocol] || 0
22
22
  uint16be :ip_header_checksum,
23
- initial_value: options[:ip_header_checksum]
23
+ initial_value: options[:ip_header_checksum] || 0
24
24
  ip_address :ip_source_address
25
25
  ip_address :ip_destination_address
26
+ string :option, read_length: -> { 20 - ip_header_length * 4 }
26
27
  end
27
28
  end
28
29
  # rubocop:enable AbcSize
@@ -1,5 +1,5 @@
1
1
  # Base module.
2
2
  module Pio
3
3
  # gem version.
4
- VERSION = '0.11.2'.freeze
4
+ VERSION = '0.12.0'.freeze
5
5
  end
@@ -57,12 +57,12 @@ Gem::Specification.new do |gem|
57
57
 
58
58
  # Test
59
59
  gem.add_development_dependency 'codeclimate-test-reporter', '~> 0.4.6'
60
- gem.add_development_dependency 'coveralls', '~> 0.7.3'
60
+ gem.add_development_dependency 'coveralls', '~> 0.7.9'
61
61
  gem.add_development_dependency 'cucumber', '~> 1.3.18'
62
- gem.add_development_dependency 'flay', '~> 2.6.0'
63
- gem.add_development_dependency 'flog', '~> 4.3.1'
62
+ gem.add_development_dependency 'flay', '~> 2.6.1'
63
+ gem.add_development_dependency 'flog', '~> 4.3.2'
64
64
  gem.add_development_dependency 'reek', '~> 1.6.4'
65
- gem.add_development_dependency 'rspec', '~> 3.1.0'
65
+ gem.add_development_dependency 'rspec', '~> 3.2.0'
66
66
  gem.add_development_dependency 'rspec-given', '~> 3.6.0'
67
67
  gem.add_development_dependency 'rubocop', '~> 0.28.0'
68
68
  end
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: pio
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.11.2
4
+ version: 0.12.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Yasuhito Takamiya
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2015-01-29 00:00:00.000000000 Z
11
+ date: 2015-02-05 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: bindata
@@ -240,14 +240,14 @@ dependencies:
240
240
  requirements:
241
241
  - - ~>
242
242
  - !ruby/object:Gem::Version
243
- version: 0.7.3
243
+ version: 0.7.9
244
244
  type: :development
245
245
  prerelease: false
246
246
  version_requirements: !ruby/object:Gem::Requirement
247
247
  requirements:
248
248
  - - ~>
249
249
  - !ruby/object:Gem::Version
250
- version: 0.7.3
250
+ version: 0.7.9
251
251
  - !ruby/object:Gem::Dependency
252
252
  name: cucumber
253
253
  requirement: !ruby/object:Gem::Requirement
@@ -268,28 +268,28 @@ dependencies:
268
268
  requirements:
269
269
  - - ~>
270
270
  - !ruby/object:Gem::Version
271
- version: 2.6.0
271
+ version: 2.6.1
272
272
  type: :development
273
273
  prerelease: false
274
274
  version_requirements: !ruby/object:Gem::Requirement
275
275
  requirements:
276
276
  - - ~>
277
277
  - !ruby/object:Gem::Version
278
- version: 2.6.0
278
+ version: 2.6.1
279
279
  - !ruby/object:Gem::Dependency
280
280
  name: flog
281
281
  requirement: !ruby/object:Gem::Requirement
282
282
  requirements:
283
283
  - - ~>
284
284
  - !ruby/object:Gem::Version
285
- version: 4.3.1
285
+ version: 4.3.2
286
286
  type: :development
287
287
  prerelease: false
288
288
  version_requirements: !ruby/object:Gem::Requirement
289
289
  requirements:
290
290
  - - ~>
291
291
  - !ruby/object:Gem::Version
292
- version: 4.3.1
292
+ version: 4.3.2
293
293
  - !ruby/object:Gem::Dependency
294
294
  name: reek
295
295
  requirement: !ruby/object:Gem::Requirement
@@ -310,14 +310,14 @@ dependencies:
310
310
  requirements:
311
311
  - - ~>
312
312
  - !ruby/object:Gem::Version
313
- version: 3.1.0
313
+ version: 3.2.0
314
314
  type: :development
315
315
  prerelease: false
316
316
  version_requirements: !ruby/object:Gem::Requirement
317
317
  requirements:
318
318
  - - ~>
319
319
  - !ruby/object:Gem::Version
320
- version: 3.1.0
320
+ version: 3.2.0
321
321
  - !ruby/object:Gem::Dependency
322
322
  name: rspec-given
323
323
  requirement: !ruby/object:Gem::Requirement
@@ -385,6 +385,7 @@ files:
385
385
  - features/arp_read.feature
386
386
  - features/dhcp_read.feature
387
387
  - features/echo_read.feature
388
+ - features/exact_match.feature
388
389
  - features/features_read.feature
389
390
  - features/flow_mod_read.feature
390
391
  - features/hello_read.feature
@@ -418,7 +419,8 @@ files:
418
419
  - features/packet_data/icmp.pcap
419
420
  - features/packet_data/lldp.detailed.pcap
420
421
  - features/packet_data/lldp.minimal.pcap
421
- - features/packet_data/packet_in.raw
422
+ - features/packet_data/packet_in_arp_request.raw
423
+ - features/packet_data/packet_in_cbench.raw
422
424
  - features/packet_data/packet_out.raw
423
425
  - features/packet_data/port_mod.raw
424
426
  - features/packet_data/port_stats_reply.raw
@@ -463,6 +465,7 @@ files:
463
465
  - lib/pio/dhcp/request.rb
464
466
  - lib/pio/echo.rb
465
467
  - lib/pio/enqueue.rb
468
+ - lib/pio/exact_match.rb
466
469
  - lib/pio/features.rb
467
470
  - lib/pio/flow_mod.rb
468
471
  - lib/pio/hello.rb
@@ -583,7 +586,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
583
586
  version: '0'
584
587
  requirements: []
585
588
  rubyforge_project:
586
- rubygems_version: 2.4.3
589
+ rubygems_version: 2.2.2
587
590
  signing_key:
588
591
  specification_version: 4
589
592
  summary: Packet parser and generator.
@@ -638,12 +641,12 @@ test_files:
638
641
  - features/packet_data/flow_mod_modify_strict.raw
639
642
  - features/packet_data/flow_mod_add.raw
640
643
  - features/packet_data/features_reply.raw
641
- - features/packet_data/packet_in.raw
642
644
  - features/packet_data/aggregate_stats_reply.raw
643
645
  - features/packet_data/queue_get_config_reply.raw
644
646
  - features/packet_data/arp.pcap
645
647
  - features/packet_data/features_request.raw
646
648
  - features/packet_data/flow_stats_request.raw
649
+ - features/packet_data/packet_in_arp_request.raw
647
650
  - features/packet_data/port_stats_request.raw
648
651
  - features/packet_data/flow_mod_delete_strict.raw
649
652
  - features/packet_data/barrier_reply.raw
@@ -658,6 +661,7 @@ test_files:
658
661
  - features/packet_data/port_stats_reply.raw
659
662
  - features/packet_data/packet_out.raw
660
663
  - features/packet_data/table_stats_reply.raw
664
+ - features/packet_data/packet_in_cbench.raw
661
665
  - features/packet_data/queue_get_config_request.raw
662
666
  - features/packet_data/error.raw
663
667
  - features/packet_data/vendor_stats_request.raw
@@ -673,6 +677,7 @@ test_files:
673
677
  - features/packet_data/lldp.detailed.pcap
674
678
  - features/packet_data/aggregate_stats_request.raw
675
679
  - features/packet_data/echo_request.raw
680
+ - features/exact_match.feature
676
681
  - features/icmp_read.feature
677
682
  - features/arp_read.feature
678
683
  - features/step_definitions/pending_steps.rb