pio 0.19.0 → 0.20.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 (121) hide show
  1. checksums.yaml +4 -4
  2. data/CHANGELOG.md +9 -0
  3. data/README.md +20 -18
  4. data/features/{packet_data/arp-storm.pcap → arp-storm.pcap} +0 -0
  5. data/features/arp.feature +1 -1
  6. data/features/{packet_data/arp.pcap → arp.pcap} +0 -0
  7. data/features/dhcp.feature +210 -3
  8. data/features/{packet_data/dhcp.pcap → dhcp.pcap} +0 -0
  9. data/features/icmp.feature +1 -1
  10. data/features/{packet_data/icmp.pcap → icmp.pcap} +0 -0
  11. data/features/{packet_data/lldp.detailed.pcap → lldp.detailed.pcap} +0 -0
  12. data/features/lldp.feature +5 -5
  13. data/features/{packet_data/lldp.minimal.pcap → lldp.minimal.pcap} +0 -0
  14. data/features/{packet_data → open_flow10}/aggregate_stats_reply.raw +0 -0
  15. data/features/{packet_data → open_flow10}/aggregate_stats_request.raw +0 -0
  16. data/features/{packet_data → open_flow10}/barrier_reply.raw +0 -0
  17. data/features/{packet_data → open_flow10}/barrier_request.raw +0 -0
  18. data/features/{packet_data → open_flow10}/desc_stats_reply.raw +0 -0
  19. data/features/{packet_data → open_flow10}/desc_stats_request.raw +0 -0
  20. data/features/open_flow10/echo_reply.feature +10 -10
  21. data/features/{packet_data → open_flow10}/echo_reply.raw +0 -0
  22. data/features/open_flow10/echo_request.feature +10 -10
  23. data/features/{packet_data → open_flow10}/echo_request.raw +0 -0
  24. data/features/{packet_data → open_flow10}/error.raw +0 -0
  25. data/features/open_flow10/exact_match.feature +33 -33
  26. data/features/open_flow10/features_reply.feature +71 -71
  27. data/features/{packet_data → open_flow10}/features_reply.raw +0 -0
  28. data/features/open_flow10/features_request.feature +9 -9
  29. data/features/{packet_data → open_flow10}/features_request.raw +0 -0
  30. data/features/open_flow10/flow_mod.feature +167 -167
  31. data/features/{packet_data → open_flow10}/flow_mod_add.raw +0 -0
  32. data/features/{packet_data → open_flow10}/flow_mod_delete.raw +0 -0
  33. data/features/{packet_data → open_flow10}/flow_mod_delete_strict.raw +0 -0
  34. data/features/{packet_data → open_flow10}/flow_mod_modify.raw +0 -0
  35. data/features/{packet_data → open_flow10}/flow_mod_modify_strict.raw +0 -0
  36. data/features/{packet_data → open_flow10}/flow_removed.raw +0 -0
  37. data/features/{packet_data → open_flow10}/flow_stats_reply.raw +0 -0
  38. data/features/{packet_data → open_flow10}/flow_stats_request.raw +0 -0
  39. data/features/{packet_data → open_flow10}/get_config_reply.raw +0 -0
  40. data/features/{packet_data → open_flow10}/get_config_request.raw +0 -0
  41. data/features/open_flow10/hello.feature +9 -9
  42. data/features/{packet_data → open_flow10}/hello.raw +0 -0
  43. data/features/open_flow10/packet_in.feature +4 -4
  44. data/features/{packet_data → open_flow10}/packet_in_arp_request.raw +0 -0
  45. data/features/{packet_data → open_flow10}/packet_in_cbench.raw +0 -0
  46. data/features/open_flow10/packet_out.feature +3 -3
  47. data/features/{packet_data → open_flow10}/packet_out.raw +0 -0
  48. data/features/{packet_data → open_flow10}/port_mod.raw +0 -0
  49. data/features/{packet_data → open_flow10}/port_stats_reply.raw +0 -0
  50. data/features/{packet_data → open_flow10}/port_stats_request.raw +0 -0
  51. data/features/open_flow10/port_status.feature +3 -3
  52. data/features/{packet_data → open_flow10}/port_status.raw +0 -0
  53. data/features/{packet_data → open_flow10}/queue_get_config_reply.raw +0 -0
  54. data/features/{packet_data → open_flow10}/queue_get_config_request.raw +0 -0
  55. data/features/{packet_data → open_flow10}/set_config.raw +0 -0
  56. data/features/{packet_data → open_flow10}/table_stats_reply.raw +0 -0
  57. data/features/{packet_data → open_flow10}/table_stats_request.raw +0 -0
  58. data/features/{packet_data → open_flow10}/vendor.raw +0 -0
  59. data/features/{packet_data → open_flow10}/vendor_stats_request.raw +0 -0
  60. data/features/open_flow13/echo_reply.feature +64 -61
  61. data/features/{packet_data/echo13_reply_body.raw → open_flow13/echo_reply_body.raw} +0 -0
  62. data/features/{packet_data/echo13_reply_no_body.raw → open_flow13/echo_reply_no_body.raw} +0 -0
  63. data/features/open_flow13/echo_request.feature +64 -61
  64. data/features/{packet_data/echo13_request_body.raw → open_flow13/echo_request_body.raw} +0 -0
  65. data/features/{packet_data/echo13_request_no_body.raw → open_flow13/echo_request_no_body.raw} +0 -0
  66. data/features/open_flow13/features_reply.feature +53 -0
  67. data/features/open_flow13/features_reply.raw +0 -0
  68. data/features/open_flow13/features_request.feature +89 -0
  69. data/features/open_flow13/features_request.raw +0 -0
  70. data/features/open_flow13/hello.feature +26 -23
  71. data/features/{packet_data/hello13_no_version_bitmap.raw → open_flow13/hello_no_version_bitmap.raw} +0 -0
  72. data/features/{packet_data/hello13_version_bitmap.raw → open_flow13/hello_version_bitmap.raw} +0 -0
  73. data/features/step_definitions/open_flow_steps.rb +3 -0
  74. data/features/step_definitions/packet_data_steps.rb +9 -9
  75. data/features/udp.feature +3 -3
  76. data/features/{packet_data/udp_no_payload.raw → udp_no_payload.raw} +0 -0
  77. data/features/{packet_data/udp_with_payload.raw → udp_with_payload.raw} +0 -0
  78. data/lib/pio.rb +1 -9
  79. data/lib/pio/open_flow/actions.rb +8 -8
  80. data/lib/pio/open_flow/open_flow_header.rb +10 -0
  81. data/lib/pio/open_flow10.rb +15 -0
  82. data/lib/pio/open_flow10/echo.rb +15 -0
  83. data/lib/pio/open_flow10/exact_match.rb +51 -0
  84. data/lib/pio/{features.rb → open_flow10/features.rb} +8 -7
  85. data/lib/pio/{flow_mod.rb → open_flow10/flow_mod.rb} +1 -1
  86. data/lib/pio/{hello.rb → open_flow10/hello.rb} +0 -0
  87. data/lib/pio/{match.rb → open_flow10/match.rb} +46 -43
  88. data/lib/pio/{packet_in.rb → open_flow10/packet_in.rb} +0 -0
  89. data/lib/pio/{packet_out.rb → open_flow10/packet_out.rb} +0 -0
  90. data/lib/pio/{port_status.rb → open_flow10/port_status.rb} +0 -0
  91. data/lib/pio/open_flow13.rb +12 -0
  92. data/lib/pio/{echo.rb → open_flow13/echo.rb} +9 -13
  93. data/lib/pio/open_flow13/features_reply.rb +91 -0
  94. data/lib/pio/open_flow13/features_request.rb +54 -0
  95. data/lib/pio/{hello13.rb → open_flow13/hello.rb} +4 -1
  96. data/lib/pio/{set_eth_addr.rb → set_ether_address.rb} +7 -7
  97. data/lib/pio/{set_ip_addr.rb → set_ip_address.rb} +7 -7
  98. data/lib/pio/set_ip_tos.rb +1 -1
  99. data/lib/pio/set_transport_port.rb +2 -2
  100. data/lib/pio/version.rb +1 -1
  101. data/pio.gemspec +2 -2
  102. data/spec/pio/flow_mod_spec.rb +45 -45
  103. data/spec/pio/match_spec.rb +122 -120
  104. data/spec/pio/{hello13_spec.rb → open_flow13/hello_spec.rb} +11 -11
  105. data/spec/pio/packet_out_spec.rb +19 -19
  106. data/spec/pio/set_ether_destination_address_spec.rb +28 -0
  107. data/spec/pio/set_ether_source_address_spec.rb +28 -0
  108. data/spec/pio/set_ip_destination_address_spec.rb +27 -0
  109. data/spec/pio/set_ip_source_address_spec.rb +25 -0
  110. data/spec/pio/set_transport_destination_port_spec.rb +44 -0
  111. data/spec/pio/set_transport_source_port_spec.rb +44 -0
  112. data/spec/pio/wildcards_spec.rb +23 -21
  113. metadata +179 -165
  114. data/bin/byebug +0 -16
  115. data/lib/pio/exact_match.rb +0 -51
  116. data/spec/pio/set_eth_dst_addr_spec.rb +0 -28
  117. data/spec/pio/set_eth_src_addr_spec.rb +0 -28
  118. data/spec/pio/set_ip_dst_addr_spec.rb +0 -25
  119. data/spec/pio/set_ip_src_addr_spec.rb +0 -25
  120. data/spec/pio/set_transport_dst_port_spec.rb +0 -42
  121. data/spec/pio/set_transport_src_port_spec.rb +0 -42
@@ -0,0 +1,53 @@
1
+ Feature: Pio::Features::Reply
2
+ Background:
3
+ Given I use OpenFlow 1.3
4
+
5
+ Scenario: new
6
+ When I try to create an OpenFlow message with:
7
+ """
8
+ Pio::Features::Reply.new(
9
+ dpid: 0x123,
10
+ n_buffers: 0x100,
11
+ n_tables: 0xfe,
12
+ capabilities: [:flow_stats, :table_stats, :port_stats, :group_stats, :ip_reasm, :queue_stats, :port_blocked]
13
+ )
14
+ """
15
+ Then it should finish successfully
16
+ And the message have the following fields and values:
17
+ | field | value |
18
+ | class | Pio::Features::Reply |
19
+ | ofp_version | 4 |
20
+ | message_type | 6 |
21
+ | message_length | 32 |
22
+ | transaction_id | 0 |
23
+ | xid | 0 |
24
+ | datapath_id | 291 |
25
+ | dpid | 291 |
26
+ | n_buffers | 256 |
27
+ | n_tables | 254 |
28
+ | auxiliary_id | 0 |
29
+ | capabilities | [:flow_stats, :table_stats, :port_stats, :group_stats, :ip_reasm, :queue_stats, :port_blocked] |
30
+ | reserved | 0 |
31
+
32
+ Scenario: read
33
+ When I try to parse a file named "open_flow13/features_reply.raw" with "Pio::Features::Reply" class
34
+ Then it should finish successfully
35
+ And the message have the following fields and values:
36
+ | field | value |
37
+ | class | Pio::Features::Reply |
38
+ | ofp_version | 4 |
39
+ | message_type | 6 |
40
+ | message_length | 32 |
41
+ | transaction_id | 0 |
42
+ | xid | 0 |
43
+ | datapath_id | 281474976710657 |
44
+ | dpid | 281474976710657 |
45
+ | n_buffers | 256 |
46
+ | n_tables | 1 |
47
+ | auxiliary_id | 0 |
48
+ | capabilities | [:flow_stats, :table_stats, :port_stats, :group_stats, :ip_reasm, :queue_stats, :port_blocked] |
49
+ | reserved | 0 |
50
+
51
+ Scenario: parse error
52
+ When I try to parse a file named "open_flow10/echo_request.raw" with "Pio::Features::Reply" class
53
+ Then it should fail with "Pio::ParseError", "Invalid Features Reply 1.3 message."
@@ -0,0 +1,89 @@
1
+ Feature: Pio::Features::Request
2
+ Background:
3
+ Given I use OpenFlow 1.3
4
+
5
+ Scenario: new
6
+ When I try to create an OpenFlow message with:
7
+ """
8
+ Pio::Features::Request.new
9
+ """
10
+ Then it should finish successfully
11
+ And the message have the following fields and values:
12
+ | field | value |
13
+ | class | Pio::Features::Request |
14
+ | ofp_version | 4 |
15
+ | message_type | 5 |
16
+ | message_length | 8 |
17
+ | transaction_id | 0 |
18
+ | xid | 0 |
19
+ | body | |
20
+
21
+ Scenario: new(transaction_id: 123)
22
+ When I try to create an OpenFlow message with:
23
+ """
24
+ Pio::Features::Request.new(transaction_id: 123)
25
+ """
26
+ Then it should finish successfully
27
+ And the message have the following fields and values:
28
+ | field | value |
29
+ | class | Pio::Features::Request |
30
+ | ofp_version | 4 |
31
+ | message_type | 5 |
32
+ | message_length | 8 |
33
+ | transaction_id | 123 |
34
+ | xid | 123 |
35
+ | body | |
36
+
37
+ Scenario: new(xid: 123)
38
+ When I try to create an OpenFlow message with:
39
+ """
40
+ Pio::Features::Request.new(xid: 123)
41
+ """
42
+ Then it should finish successfully
43
+ And the message have the following fields and values:
44
+ | field | value |
45
+ | class | Pio::Features::Request |
46
+ | ofp_version | 4 |
47
+ | message_type | 5 |
48
+ | message_length | 8 |
49
+ | transaction_id | 123 |
50
+ | xid | 123 |
51
+ | body | |
52
+
53
+ Scenario: new(xid: -1) and error
54
+ When I try to create an OpenFlow message with:
55
+ """
56
+ Pio::Features::Request.new(xid: -1)
57
+ """
58
+ Then it should fail with "ArgumentError", "Transaction ID should be an unsigned 32-bit integer."
59
+
60
+ Scenario: new(xid: 2**32) and error
61
+ When I try to create an OpenFlow message with:
62
+ """
63
+ Pio::Features::Request.new(xid: 2**32)
64
+ """
65
+ Then it should fail with "ArgumentError", "Transaction ID should be an unsigned 32-bit integer."
66
+
67
+ Scenario: new(unknown_attr: 'foo') and error
68
+ When I try to create an OpenFlow message with:
69
+ """
70
+ Pio::Features::Request.new(unknown_attr: 'foo')
71
+ """
72
+ Then it should fail with "RuntimeError", "Unknown keyword: unknown_attr"
73
+
74
+ Scenario: read
75
+ When I try to parse a file named "open_flow13/features_request.raw" with "Pio::Features::Request" class
76
+ Then it should finish successfully
77
+ And the message have the following fields and values:
78
+ | field | value |
79
+ | class | Pio::Features::Request |
80
+ | ofp_version | 4 |
81
+ | message_type | 5 |
82
+ | message_length | 8 |
83
+ | transaction_id | 0 |
84
+ | xid | 0 |
85
+ | body | |
86
+
87
+ Scenario: parse error
88
+ When I try to parse a file named "open_flow10/hello.raw" with "Pio::Features::Request" class
89
+ Then it should fail with "Pio::ParseError", "Invalid Features Request 1.3 message."
@@ -1,13 +1,16 @@
1
- Feature: Hello
2
- Scenario: create
1
+ Feature: Pio::Hello
2
+ Background:
3
+ Given I use OpenFlow 1.3
4
+
5
+ Scenario: new
3
6
  When I try to create an OpenFlow message with:
4
7
  """
5
- Pio::Hello13.new
8
+ Pio::Hello.new
6
9
  """
7
10
  Then it should finish successfully
8
11
  And the message have the following fields and values:
9
12
  | field | value |
10
- | class | Pio::Hello13 |
13
+ | class | Pio::Hello |
11
14
  | ofp_version | 4 |
12
15
  | message_type | 0 |
13
16
  | message_length | 16 |
@@ -15,15 +18,15 @@ Feature: Hello
15
18
  | xid | 0 |
16
19
  | supported_versions | [:open_flow13] |
17
20
 
18
- Scenario: create (transaction_id: 123)
21
+ Scenario: new(transaction_id: 123)
19
22
  When I try to create an OpenFlow message with:
20
23
  """
21
- Pio::Hello13.new(transaction_id: 123)
24
+ Pio::Hello.new(transaction_id: 123)
22
25
  """
23
26
  Then it should finish successfully
24
27
  And the message have the following fields and values:
25
28
  | field | value |
26
- | class | Pio::Hello13 |
29
+ | class | Pio::Hello |
27
30
  | ofp_version | 4 |
28
31
  | message_type | 0 |
29
32
  | message_length | 16 |
@@ -31,15 +34,15 @@ Feature: Hello
31
34
  | xid | 123 |
32
35
  | supported_versions | [:open_flow13] |
33
36
 
34
- Scenario: create (xid: 123)
37
+ Scenario: new(xid: 123)
35
38
  When I try to create an OpenFlow message with:
36
39
  """
37
- Pio::Hello13.new(xid: 123)
40
+ Pio::Hello.new(xid: 123)
38
41
  """
39
42
  Then it should finish successfully
40
43
  And the message have the following fields and values:
41
44
  | field | value |
42
- | class | Pio::Hello13 |
45
+ | class | Pio::Hello |
43
46
  | ofp_version | 4 |
44
47
  | message_type | 0 |
45
48
  | message_length | 16 |
@@ -47,25 +50,25 @@ Feature: Hello
47
50
  | xid | 123 |
48
51
  | supported_versions | [:open_flow13] |
49
52
 
50
- Scenario: parse (no version bitmap)
51
- When I try to parse a file named "hello13_no_version_bitmap.raw" with "Hello13" class
53
+ Scenario: read (no version bitmap)
54
+ When I try to parse a file named "open_flow13/hello_no_version_bitmap.raw" with "Pio::Hello" class
52
55
  Then it should finish successfully
53
56
  And the message have the following fields and values:
54
- | field | value |
55
- | class | Pio::Hello13 |
56
- | ofp_version | 4 |
57
- | message_type | 0 |
58
- | message_length | 8 |
59
- | transaction_id | 0 |
60
- | xid | 0 |
61
- | supported_versions | [] |
57
+ | field | value |
58
+ | class | Pio::Hello |
59
+ | ofp_version | 4 |
60
+ | message_type | 0 |
61
+ | message_length | 8 |
62
+ | transaction_id | 0 |
63
+ | xid | 0 |
64
+ | supported_versions | [] |
62
65
 
63
- Scenario: parse
64
- When I try to parse a file named "hello13_version_bitmap.raw" with "Hello13" class
66
+ Scenario: read
67
+ When I try to parse a file named "open_flow13/hello_version_bitmap.raw" with "Pio::Hello" class
65
68
  Then it should finish successfully
66
69
  And the message have the following fields and values:
67
70
  | field | value |
68
- | class | Pio::Hello13 |
71
+ | class | Pio::Hello |
69
72
  | ofp_version | 4 |
70
73
  | message_type | 0 |
71
74
  | message_length | 16 |
@@ -0,0 +1,3 @@
1
+ Given(/^I use OpenFlow 1\.3$/) do
2
+ require 'pio/open_flow13'
3
+ end
@@ -11,9 +11,9 @@ When(/^I try to create an OpenFlow message with:$/) do |ruby_code|
11
11
  end
12
12
 
13
13
  # rubocop:disable LineLength
14
- When(/^I try to parse a file named "(.*?)\.raw" with "(.*?)" class$/) do |file_name, klass|
15
- path = File.expand_path(File.join(__dir__, '..', 'packet_data', file_name + '.raw'))
16
- raw_data = IO.read(path)
14
+ When(/^I try to parse a file named "(.*?\.raw)" with "(.*?)" class$/) do |path, klass|
15
+ full_path = File.expand_path(File.join(__dir__, '..', path))
16
+ raw_data = IO.read(full_path)
17
17
  parser_klass = Pio.const_get(klass)
18
18
  begin
19
19
  @result = parser_klass.read(raw_data)
@@ -24,9 +24,9 @@ end
24
24
  # rubocop:enable LineLength
25
25
 
26
26
  # rubocop:disable LineLength
27
- When(/^I try to parse a file named "(.*?)\.pcap" with "(.*?)" class$/) do |file_name, klass|
28
- path = File.expand_path(File.join(__dir__, '..', 'packet_data', file_name + '.pcap'))
29
- pcap = Pio::Pcap::Frame.read(IO.read(path))
27
+ When(/^I try to parse a file named "(.*?\.pcap)" with "(.*?)" class$/) do |path, klass|
28
+ full_path = File.expand_path(File.join(__dir__, '..', path))
29
+ pcap = Pio::Pcap::Frame.read(IO.read(full_path))
30
30
  parser_klass = Pio.const_get(klass)
31
31
  begin
32
32
  @result = pcap.records.each_with_object([]) do |each, result|
@@ -47,9 +47,9 @@ Then(/^it should fail with "([^"]*)", "([^"]*)"$/) do |error, message|
47
47
  expect(@last_error.message).to eq(message)
48
48
  end
49
49
 
50
- When(/^I create an exact match from "(.*?)"$/) do |file_name|
51
- path = File.expand_path(File.join(__dir__, '..', 'packet_data', file_name))
52
- @result = Pio::ExactMatch.new(Pio::PacketIn.read(IO.read(path)))
50
+ When(/^I create an exact match from "(.*?)"$/) do |path|
51
+ full_path = File.expand_path(File.join(__dir__, '..', path))
52
+ @result = Pio::ExactMatch.new(Pio::PacketIn.read(IO.read(full_path)))
53
53
  end
54
54
 
55
55
  Then(/^the packet have the following fields and values:$/) do |table|
data/features/udp.feature CHANGED
@@ -1,6 +1,6 @@
1
- Feature: UDP
2
- Scenario: dhcp.pcap
3
- When I try to parse a file named "dhcp.pcap" with "Udp" class
1
+ Feature: Pio::Udp
2
+ Scenario: parse dhcp.pcap
3
+ When I try to parse a file named "dhcp.pcap" with "Pio::Udp" class
4
4
  Then it should finish successfully
5
5
  And the message #1 have the following fields and values:
6
6
  | field | value |
data/lib/pio.rb CHANGED
@@ -2,16 +2,8 @@ require 'pio/parse_error'
2
2
 
3
3
  require 'pio/arp'
4
4
  require 'pio/dhcp'
5
- require 'pio/echo'
6
- require 'pio/exact_match'
7
- require 'pio/features'
8
- require 'pio/flow_mod'
9
- require 'pio/hello'
10
- require 'pio/hello13'
11
5
  require 'pio/icmp'
12
6
  require 'pio/lldp'
13
7
  require 'pio/mac'
14
- require 'pio/packet_in'
15
- require 'pio/packet_out'
16
- require 'pio/port_status'
8
+ require 'pio/open_flow10'
17
9
  require 'pio/udp'
@@ -1,8 +1,8 @@
1
1
  require 'bindata'
2
2
  require 'pio/enqueue'
3
3
  require 'pio/send_out_port'
4
- require 'pio/set_eth_addr'
5
- require 'pio/set_ip_addr'
4
+ require 'pio/set_ether_address'
5
+ require 'pio/set_ip_address'
6
6
  require 'pio/set_ip_tos'
7
7
  require 'pio/set_transport_port'
8
8
  require 'pio/set_vlan_priority'
@@ -18,13 +18,13 @@ module Pio
18
18
  1 => Pio::SetVlanVid,
19
19
  2 => Pio::SetVlanPriority,
20
20
  3 => Pio::StripVlanHeader,
21
- 4 => Pio::SetEthSrcAddr,
22
- 5 => Pio::SetEthDstAddr,
23
- 6 => Pio::SetIpSrcAddr,
24
- 7 => Pio::SetIpDstAddr,
21
+ 4 => Pio::SetEtherSourceAddr,
22
+ 5 => Pio::SetEtherDestinationAddr,
23
+ 6 => Pio::SetIpSourceAddress,
24
+ 7 => Pio::SetIpDestinationAddress,
25
25
  8 => Pio::SetIpTos,
26
- 9 => Pio::SetTransportSrcPort,
27
- 10 => Pio::SetTransportDstPort,
26
+ 9 => Pio::SetTransportSourcePort,
27
+ 10 => Pio::SetTransportDestinationPort,
28
28
  11 => Pio::Enqueue
29
29
  }
30
30
 
@@ -2,6 +2,16 @@ require 'bindata'
2
2
  require 'pio/open_flow/transaction_id'
3
3
 
4
4
  module Pio
5
+ # OpenFlow message header parser
6
+ class OpenFlowHeaderParser < BinData::Record
7
+ endian :big
8
+
9
+ uint8 :ofp_version
10
+ uint8 :message_type
11
+ uint16 :message_length
12
+ transaction_id :transaction_id
13
+ end
14
+
5
15
  # OpenFlow message header.
6
16
  class OpenFlowHeader < BinData::Record
7
17
  endian :big
@@ -0,0 +1,15 @@
1
+ module Pio
2
+ # OpenFlow specific types.
3
+ module OpenFlow
4
+ VERSION = 1
5
+ end
6
+ end
7
+
8
+ require 'pio/open_flow10/echo'
9
+ require 'pio/open_flow10/exact_match'
10
+ require 'pio/open_flow10/features'
11
+ require 'pio/open_flow10/flow_mod'
12
+ require 'pio/open_flow10/hello'
13
+ require 'pio/open_flow10/packet_in'
14
+ require 'pio/open_flow10/packet_out'
15
+ require 'pio/open_flow10/port_status'
@@ -0,0 +1,15 @@
1
+ require 'forwardable'
2
+ require 'pio/open_flow'
3
+
4
+ module Pio
5
+ # OpenFlow 1.0 Echo Request and Reply message.
6
+ module Echo
7
+ # OpenFlow 1.0 Echo Request message.
8
+ class Request; end
9
+ OpenFlow::Message.factory(Request, OpenFlow::ECHO_REQUEST)
10
+
11
+ # OpenFlow 1.0 Echo Reply message.
12
+ class Reply; end
13
+ OpenFlow::Message.factory(Reply, OpenFlow::ECHO_REPLY)
14
+ end
15
+ end
@@ -0,0 +1,51 @@
1
+ require 'pio/open_flow10/match'
2
+
3
+ module Pio
4
+ # OpenFlow 1.0 exact match
5
+ class ExactMatch
6
+ # rubocop:disable MethodLength
7
+ # rubocop:disable AbcSize
8
+ def initialize(packet_in)
9
+ data = packet_in.data
10
+ case data
11
+ when PacketIn::DataParser::IPv4Packet
12
+ options = {
13
+ in_port: packet_in.in_port,
14
+ ether_source_address: packet_in.source_mac,
15
+ ether_destination_address: packet_in.destination_mac,
16
+ vlan_vid: data.vlan_vid,
17
+ vlan_priority: data.vlan_pcp,
18
+ ether_type: data.ether_type,
19
+ ip_tos: data.ip_type_of_service,
20
+ ip_protocol: data.ip_protocol,
21
+ ip_source_address: data.ip_source_address,
22
+ ip_destination_address: data.ip_destination_address,
23
+ transport_source_port: data.transport_source_port,
24
+ transport_destination_port: data.transport_destination_port
25
+ }
26
+ when Arp::Request
27
+ options = {
28
+ in_port: packet_in.in_port,
29
+ ether_source_address: packet_in.source_mac,
30
+ ether_destination_address: packet_in.destination_mac,
31
+ vlan_vid: data.vlan_vid,
32
+ vlan_priority: data.vlan_pcp,
33
+ ether_type: data.ether_type,
34
+ ip_tos: 0,
35
+ ip_protocol: data.operation,
36
+ ip_source_address: data.sender_protocol_address,
37
+ ip_destination_address: data.target_protocol_address,
38
+ transport_source_port: 0,
39
+ transport_destination_port: 0
40
+ }
41
+ end
42
+ @match = Pio::Match.new(options)
43
+ end
44
+ # rubocop:enable MethodLength
45
+ # rubocop:enable AbcSize
46
+
47
+ def method_missing(method, *args, &block)
48
+ @match.__send__ method, *args, &block
49
+ end
50
+ end
51
+ end