pio 0.18.2 → 0.19.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.
- checksums.yaml +4 -4
- data/CHANGELOG.md +3 -0
- data/README.md +40 -344
- data/Rakefile +32 -0
- data/bin/_guard-core +16 -0
- data/bin/byebug +16 -0
- data/bin/cc-tddium-post-worker +16 -0
- data/bin/cdiff +16 -0
- data/bin/coderay +16 -0
- data/bin/colortab +16 -0
- data/bin/coveralls +16 -0
- data/bin/cucumber +16 -0
- data/bin/decolor +16 -0
- data/bin/flay +16 -0
- data/bin/flog +16 -0
- data/bin/guard +16 -0
- data/bin/htmldiff +16 -0
- data/bin/inch +16 -0
- data/bin/ldiff +16 -0
- data/bin/listen +16 -0
- data/bin/minitar +16 -0
- data/bin/pry +16 -0
- data/bin/rake +16 -0
- data/bin/reek +16 -0
- data/bin/relish +16 -0
- data/bin/restclient +16 -0
- data/bin/rspec +16 -0
- data/bin/rubocop +16 -0
- data/bin/ruby-parse +16 -0
- data/bin/ruby-rewrite +16 -0
- data/bin/ruby_parse +16 -0
- data/bin/ruby_parse_extract_error +16 -0
- data/bin/sparkr +16 -0
- data/bin/term_display +16 -0
- data/bin/term_mandel +16 -0
- data/bin/thor +16 -0
- data/bin/unparser +16 -0
- data/bin/yard +16 -0
- data/bin/yardoc +16 -0
- data/bin/yri +16 -0
- data/features/arp.feature +61 -0
- data/features/dhcp.feature +4 -0
- data/features/icmp.feature +130 -0
- data/features/lldp.feature +47 -0
- data/features/open_flow10/echo_reply.feature +95 -0
- data/features/open_flow10/echo_request.feature +95 -0
- data/features/open_flow10/exact_match.feature +36 -0
- data/features/{features_read.feature → open_flow10/features_reply.feature} +54 -17
- data/features/open_flow10/features_request.feature +79 -0
- data/features/{flow_mod_read.feature → open_flow10/flow_mod.feature} +16 -21
- data/features/open_flow10/hello.feature +79 -0
- data/features/open_flow10/packet_in.feature +58 -0
- data/features/{packet_out_read.feature → open_flow10/packet_out.feature} +4 -5
- data/features/open_flow10/port_status.feature +23 -0
- data/features/open_flow13/echo_reply.feature +115 -0
- data/features/open_flow13/echo_request.feature +115 -0
- data/features/open_flow13/hello.feature +74 -0
- data/features/packet_data/echo13_reply_body.raw +0 -0
- data/features/packet_data/echo13_reply_no_body.raw +0 -0
- data/features/packet_data/echo13_request_body.raw +0 -0
- data/features/packet_data/echo13_request_no_body.raw +0 -0
- data/features/packet_data/hello13_no_version_bitmap.raw +0 -0
- data/features/packet_data/hello13_version_bitmap.raw +0 -0
- data/features/packet_data/udp_no_payload.raw +0 -0
- data/features/packet_data/udp_with_payload.raw +0 -0
- data/features/step_definitions/packet_data_steps.rb +49 -29
- data/features/support/env.rb +3 -0
- data/features/{udp_read.feature → udp.feature} +3 -4
- data/lib/pio.rb +1 -0
- data/lib/pio/echo.rb +67 -0
- data/lib/pio/hello13.rb +111 -0
- data/lib/pio/open_flow/message.rb +2 -1
- data/lib/pio/open_flow/open_flow_header.rb +21 -38
- data/lib/pio/open_flow/transaction_id.rb +25 -0
- data/lib/pio/version.rb +1 -1
- data/pio.gemspec +9 -14
- data/spec/pio/flow_mod_spec.rb +1 -1
- data/spec/pio/hello13_spec.rb +114 -0
- metadata +182 -138
- data/examples/arp_new.rb +0 -16
- data/examples/arp_read.rb +0 -4
- data/examples/dhcp_new.rb +0 -34
- data/examples/dhcp_read.rb +0 -4
- data/examples/echo_new.rb +0 -9
- data/examples/echo_read.rb +0 -4
- data/examples/features_new.rb +0 -28
- data/examples/features_read.rb +0 -4
- data/examples/flow_mod_new.rb +0 -13
- data/examples/flow_mod_read.rb +0 -6
- data/examples/hello_new.rb +0 -4
- data/examples/hello_read.rb +0 -4
- data/examples/icmp_new.rb +0 -21
- data/examples/icmp_read.rb +0 -4
- data/examples/lldp_new.rb +0 -4
- data/examples/lldp_read.rb +0 -4
- data/examples/packet_in_new.rb +0 -17
- data/examples/packet_in_read.rb +0 -5
- data/examples/packet_out_new.rb +0 -18
- data/examples/packet_out_read.rb +0 -6
- data/features/arp_read.feature +0 -10
- data/features/dhcp_read.feature +0 -6
- data/features/echo_read.feature +0 -29
- data/features/exact_match.feature +0 -38
- data/features/hello_read.feature +0 -14
- data/features/icmp_read.feature +0 -55
- data/features/lldp_read.feature +0 -26
- data/features/packet_in_read.feature +0 -22
- data/features/port_status_read.feature +0 -24
- data/features/step_definitions/pending_steps.rb +0 -3
- data/spec/pio/echo/reply_spec.rb +0 -135
- data/spec/pio/echo/request_spec.rb +0 -137
- data/spec/pio/features/reply_spec.rb +0 -137
- data/spec/pio/features/request_spec.rb +0 -112
- data/spec/pio/hello_spec.rb +0 -106
- data/spec/pio/lldp_spec.rb +0 -244
- data/spec/pio/packet_in_spec.rb +0 -146
checksums.yaml
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
---
|
|
2
2
|
SHA1:
|
|
3
|
-
metadata.gz:
|
|
4
|
-
data.tar.gz:
|
|
3
|
+
metadata.gz: d398d469faa1ab4517f72921247962e703371504
|
|
4
|
+
data.tar.gz: 2861613dfbf72b3a32a7eab8020f1120ecdbfd9e
|
|
5
5
|
SHA512:
|
|
6
|
-
metadata.gz:
|
|
7
|
-
data.tar.gz:
|
|
6
|
+
metadata.gz: 2510e49704a383db42c738e2b34e41b19b232ace5392a5f3f2e107b917abde8280eb892e001a7e0e3e7aad4ece7d4440f55b1edf68f7ac1bd544854a9d3285f0
|
|
7
|
+
data.tar.gz: ae229fe4badbb4a0fc24bb8cf58ead7e1e667632a47f031f5d42c09de0d60309ce10df5cf50b15bfc43049ab0d0b65a565889a7e7e3768bb3282373bdb55673b
|
data/CHANGELOG.md
CHANGED
|
@@ -1,6 +1,9 @@
|
|
|
1
1
|
# Changelog
|
|
2
2
|
|
|
3
3
|
## develop (unreleased)
|
|
4
|
+
### New features
|
|
5
|
+
* [#132](https://github.com/trema/pio/pull/132): Add new class `Pio::Hello13`.
|
|
6
|
+
* [#136](https://github.com/trema/pio/pull/136): Add new class `Pio::Echo13::Request` and `Pio::Echo13::Reply`.
|
|
4
7
|
|
|
5
8
|
|
|
6
9
|
## 0.18.2 (3/12/2015)
|
data/README.md
CHANGED
|
@@ -13,345 +13,36 @@
|
|
|
13
13
|
Pio is a ruby gem to easily parse and generate network packets. It
|
|
14
14
|
supports the following packet formats:
|
|
15
15
|
|
|
16
|
-
-
|
|
17
|
-
-
|
|
18
|
-
-
|
|
19
|
-
-
|
|
20
|
-
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
-
|
|
16
|
+
- [ICMP](https://relishapp.com/trema/pio/docs/misc/icmp)
|
|
17
|
+
- [ARP](https://relishapp.com/trema/pio/docs/misc/arp)
|
|
18
|
+
- [LLDP](https://relishapp.com/trema/pio/docs/misc/lldp)
|
|
19
|
+
- [DHCP](https://relishapp.com/trema/pio/docs/misc/dhcp)
|
|
20
|
+
- [UDP](https://relishapp.com/trema/pio/docs/misc/udp)
|
|
21
|
+
- OpenFlow 1.0
|
|
22
|
+
- [Hello](https://relishapp.com/trema/pio/docs/open-flow10/hello)
|
|
23
|
+
- [Echo Request](https://relishapp.com/trema/pio/docs/open-flow10/echo-request)
|
|
24
|
+
- [Echo Reply](https://relishapp.com/trema/pio/docs/open-flow10/echo-reply)
|
|
25
|
+
- [Features Request](https://relishapp.com/trema/pio/docs/open-flow10/features-request)
|
|
26
|
+
- [Features Reply](https://relishapp.com/trema/pio/docs/open-flow10/features-reply)
|
|
27
|
+
- [Packet In](https://relishapp.com/trema/pio/docs/open-flow10/packet-in)
|
|
28
|
+
- [Packet Out](https://relishapp.com/trema/pio/docs/open-flow10/packet-out)
|
|
29
|
+
- [Flow Mod](https://relishapp.com/trema/pio/docs/open-flow10/flow-mod)
|
|
30
|
+
- [Port Status](https://relishapp.com/trema/pio/docs/open-flow10/port-status)
|
|
31
|
+
- [Exact Match](https://relishapp.com/trema/pio/docs/open-flow10/exact-match)
|
|
32
|
+
- OpenFlow 1.3
|
|
33
|
+
- [Hello](https://relishapp.com/trema/pio/docs/open-flow13/hello)
|
|
34
|
+
- [Echo Request](https://relishapp.com/trema/pio/docs/open-flow13/echo-request)
|
|
35
|
+
- [Echo Reply](https://relishapp.com/trema/pio/docs/open-flow13/echo-reply)
|
|
29
36
|
|
|
30
37
|
## Features Overview
|
|
31
38
|
|
|
32
|
-
-
|
|
33
|
-
|
|
34
|
-
-
|
|
35
|
-
|
|
36
|
-
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
## Examples
|
|
40
|
-
|
|
41
|
-
Its usage is dead simple.
|
|
42
|
-
|
|
43
|
-
### ICMP
|
|
44
|
-
|
|
45
|
-
To parse an ICMP frame, use the API `Pio::Icmp.read` and you can
|
|
46
|
-
access each field of the parsed ICMP frame.
|
|
47
|
-
|
|
48
|
-
require 'pio'
|
|
49
|
-
|
|
50
|
-
icmp = Pio::Icmp.read(binary_data)
|
|
51
|
-
icmp.source_mac.to_s # => '00:26:82:eb:ea:d1'
|
|
52
|
-
|
|
53
|
-
Also you can use `Pio::Icmp::Request#new` or `Pio::Icmp::Reply#new` to
|
|
54
|
-
generate an Icmp Request/Reply frame like below:
|
|
55
|
-
|
|
56
|
-
require 'pio'
|
|
57
|
-
|
|
58
|
-
request = Pio::Icmp::Request.new(
|
|
59
|
-
source_mac: '00:16:9d:1d:9c:c4',
|
|
60
|
-
destination_mac: '00:26:82:eb:ea:d1',
|
|
61
|
-
ip_source_address: '192.168.83.3',
|
|
62
|
-
ip_destination_address: '192.168.83.254'
|
|
63
|
-
)
|
|
64
|
-
request.to_binary # => ICMP Request frame in binary format.
|
|
65
|
-
|
|
66
|
-
reply = Pio::Icmp::Reply.new(
|
|
67
|
-
source_mac: '00:26:82:eb:ea:d1',
|
|
68
|
-
destination_mac: '00:16:9d:1d:9c:c4',
|
|
69
|
-
ip_source_address: '192.168.83.254',
|
|
70
|
-
ip_destination_address: '192.168.83.3',
|
|
71
|
-
# The ICMP Identifier and the ICMP Sequence number
|
|
72
|
-
# should be same as those of the request.
|
|
73
|
-
identifier: request.icmp_identifier,
|
|
74
|
-
sequence_number: request.icmp_sequence_number
|
|
75
|
-
)
|
|
76
|
-
reply.to_binary # => ICMP Reply frame in binary format.
|
|
77
|
-
|
|
78
|
-
### ARP
|
|
79
|
-
|
|
80
|
-
To parse an ARP frame, use the API `Pio::Arp.read` and you can access
|
|
81
|
-
each field of the parsed ARP frame.
|
|
82
|
-
|
|
83
|
-
require 'pio'
|
|
84
|
-
|
|
85
|
-
arp = Pio::Arp.read(binary_data)
|
|
86
|
-
arp.source_mac.to_s # => '00:26:82:eb:ea:d1'
|
|
87
|
-
|
|
88
|
-
Also you can use `Pio::Arp::Request#new` or `Pio::Arp::Reply#new` to
|
|
89
|
-
generate an Arp Request/Reply frame like below:
|
|
90
|
-
|
|
91
|
-
require 'pio'
|
|
92
|
-
|
|
93
|
-
request = Pio::Arp::Request.new(
|
|
94
|
-
source_mac: '00:26:82:eb:ea:d1',
|
|
95
|
-
sender_protocol_address: '192.168.83.3',
|
|
96
|
-
target_protocol_address: '192.168.83.254'
|
|
97
|
-
)
|
|
98
|
-
request.to_binary # => Arp Request frame in binary format.
|
|
99
|
-
|
|
100
|
-
reply = Pio::Arp::Reply.new(
|
|
101
|
-
source_mac: '00:16:9d:1d:9c:c4',
|
|
102
|
-
destination_mac: '00:26:82:eb:ea:d1',
|
|
103
|
-
sender_protocol_address: '192.168.83.254',
|
|
104
|
-
target_protocol_address: '192.168.83.3'
|
|
105
|
-
)
|
|
106
|
-
reply.to_binary # => Arp Reply frame in binary format.
|
|
107
|
-
|
|
108
|
-
### LLDP
|
|
109
|
-
|
|
110
|
-
To parse an LLDP frame, use the API `Pio::Lldp.read` and you can
|
|
111
|
-
access each field of the parsed LLDP frame.
|
|
112
|
-
|
|
113
|
-
require 'pio'
|
|
114
|
-
|
|
115
|
-
lldp = Pio::Lldp.read(binary_data)
|
|
116
|
-
lldp.ttl # => 120
|
|
117
|
-
|
|
118
|
-
Also you can use `Pio::Lldp#new` to generate an LLDP frame like below:
|
|
119
|
-
|
|
120
|
-
require 'pio'
|
|
121
|
-
|
|
122
|
-
lldp = Pio::Lldp.new(dpid: 0x123, port_number: 12)
|
|
123
|
-
lldp.to_binary # => LLDP frame in binary format.
|
|
124
|
-
|
|
125
|
-
### DHCP
|
|
126
|
-
|
|
127
|
-
To parse a DHCP frame, use the API `Pio::Dhcp.read` and you can access
|
|
128
|
-
each field of the parsed DHCP frame.
|
|
129
|
-
|
|
130
|
-
require 'pio'
|
|
131
|
-
|
|
132
|
-
dhcp = Pio::Dhcp.read(binary_data)
|
|
133
|
-
dhcp.destination_mac.to_s # => 'ff:ff:ff:ff:ff:ff'
|
|
134
|
-
|
|
135
|
-
Also you can use `Pio::Dhcp::Discover#new`,
|
|
136
|
-
`Pio::Dhcp::Offer#new`, `Pio::Dhcp::Request#new` and
|
|
137
|
-
`Pio::Dhcp::Ack#new` to generate a DHCP frame like below:
|
|
138
|
-
|
|
139
|
-
require 'pio'
|
|
140
|
-
|
|
141
|
-
dhcp_client_mac_address = '24:db:ac:41:e5:5b'
|
|
142
|
-
|
|
143
|
-
dhcp_server_options =
|
|
144
|
-
{
|
|
145
|
-
source_mac: '00:26:82:eb:ea:d1',
|
|
146
|
-
destination_mac: '24:db:ac:41:e5:5b',
|
|
147
|
-
ip_source_address: '192.168.0.100',
|
|
148
|
-
ip_destination_address: '192.168.0.1'
|
|
149
|
-
}
|
|
150
|
-
|
|
151
|
-
# Client side
|
|
152
|
-
discover = Pio::Dhcp::Discover.new(source_mac: dhcp_client_mac_address)
|
|
153
|
-
discover.to_binary # => DHCP Discover frame in binary format
|
|
154
|
-
|
|
155
|
-
# Server side
|
|
156
|
-
offer = Pio::Dhcp::Offer.new(dhcp_server_options
|
|
157
|
-
.merge(transaction_id: discover.transaction_id))
|
|
158
|
-
offer.to_binary # => DHCP Offer frame in binary format
|
|
159
|
-
|
|
160
|
-
# Client side
|
|
161
|
-
request = Pio::Dhcp::Request.new(
|
|
162
|
-
source_mac: dhcp_client_mac_address,
|
|
163
|
-
server_identifier: dhcp_server_options[:ip_source_address],
|
|
164
|
-
requested_ip_address: dhcp_server_options[:ip_destination_address],
|
|
165
|
-
transaction_id: offer.transaction_id
|
|
166
|
-
)
|
|
167
|
-
request.to_binary # => DHCP Request frame in binary format
|
|
168
|
-
|
|
169
|
-
# Server side
|
|
170
|
-
ack = Pio::Dhcp::Ack.new(dhcp_server_options
|
|
171
|
-
.merge(transaction_id: request.transaction_id))
|
|
172
|
-
ack.to_binary # => DHCP Ack frame in binary format
|
|
173
|
-
|
|
174
|
-
### Hello
|
|
175
|
-
|
|
176
|
-
To parse an OpenFlow 1.0 Hello message, use the API `Pio::Hello.read`
|
|
177
|
-
and you can access each field of the parsed Hello message.
|
|
178
|
-
|
|
179
|
-
require 'pio'
|
|
180
|
-
|
|
181
|
-
hello = Pio::Hello.read(binary_data)
|
|
182
|
-
hello.transaction_id # => 123
|
|
183
|
-
|
|
184
|
-
Also you can use `Pio::Hello#new` to generate a Hello message like
|
|
185
|
-
below:
|
|
186
|
-
|
|
187
|
-
require 'pio'
|
|
188
|
-
|
|
189
|
-
hello = Pio::Hello.new(transaction_id: 123)
|
|
190
|
-
hello.to_binary # => HELLO message in binary format.
|
|
191
|
-
|
|
192
|
-
### Echo
|
|
193
|
-
|
|
194
|
-
To parse an OpenFlow 1.0 Echo message, use the API `Pio::Echo.read`
|
|
195
|
-
and you can access each field of the parsed Echo message.
|
|
196
|
-
|
|
197
|
-
require 'pio'
|
|
198
|
-
|
|
199
|
-
echo = Pio::Echo::Request.read(binary_data)
|
|
200
|
-
echo.xid # => 123
|
|
201
|
-
|
|
202
|
-
Also you can use `Pio::Echo::Request#new` or `Pio::Echo::Reply#new` to
|
|
203
|
-
generate an Echo Request/Reply message like below:
|
|
204
|
-
|
|
205
|
-
require 'pio'
|
|
206
|
-
|
|
207
|
-
request = Pio::Echo::Request.new
|
|
208
|
-
request.to_binary # => ECHO Request message in binary format.
|
|
209
|
-
|
|
210
|
-
# The ECHO xid (transaction_id)
|
|
211
|
-
# should be same as that of the request.
|
|
212
|
-
reply = Pio::Echo::Reply.new(xid: request.xid)
|
|
213
|
-
reply.to_binary # => ECHO Reply message in binary format.
|
|
214
|
-
|
|
215
|
-
### Features
|
|
216
|
-
|
|
217
|
-
To parse an OpenFlow 1.0 Features message, use the API
|
|
218
|
-
`Pio::Features.read` and you can access each field of the parsed
|
|
219
|
-
Features message.
|
|
220
|
-
|
|
221
|
-
require 'pio'
|
|
222
|
-
|
|
223
|
-
features = Pio::Features::Request.read(binary_data)
|
|
224
|
-
features.xid # => 123
|
|
225
|
-
|
|
226
|
-
Also you can use `Pio::Features::Request#new` or `Pio::Features::Reply#new` to
|
|
227
|
-
generate an Features Request/Reply message like below:
|
|
228
|
-
|
|
229
|
-
require 'pio'
|
|
230
|
-
|
|
231
|
-
request = Pio::Features::Request.new
|
|
232
|
-
request.to_binary # => Features Request message in binary format.
|
|
233
|
-
|
|
234
|
-
# The Features xid (transaction_id)
|
|
235
|
-
# should be same as that of the request.
|
|
236
|
-
reply =
|
|
237
|
-
Pio::Features::Reply.new(xid: request.xid,
|
|
238
|
-
dpid: 0x123,
|
|
239
|
-
n_buffers: 0x100,
|
|
240
|
-
n_tables: 0xfe,
|
|
241
|
-
capabilities: [:flow_stats, :table_stats,
|
|
242
|
-
:port_stats, :queue_stats,
|
|
243
|
-
:arp_match_ip],
|
|
244
|
-
actions: [:output, :set_vlan_vid,
|
|
245
|
-
:set_vlan_pcp, :strip_vlan,
|
|
246
|
-
:set_dl_src, :set_dl_dst,
|
|
247
|
-
:set_nw_src, :set_nw_dst,
|
|
248
|
-
:set_nw_tos, :set_tp_src,
|
|
249
|
-
:set_tp_dst, :enqueue],
|
|
250
|
-
ports: [{ port_no: 1,
|
|
251
|
-
hardware_address: '11:22:33:44:55:66',
|
|
252
|
-
name: 'port123',
|
|
253
|
-
config: [:port_down],
|
|
254
|
-
state: [:link_down],
|
|
255
|
-
curr: [:port_10gb_fd, :port_copper] }])
|
|
256
|
-
reply.to_binary # => Features Reply message in binary format.
|
|
257
|
-
|
|
258
|
-
### Packet-In
|
|
259
|
-
|
|
260
|
-
To parse an OpenFlow 1.0 Packet-In message, use the API
|
|
261
|
-
`Pio::PacketIn.read` and you can access each field of the parsed
|
|
262
|
-
Packet-In message.
|
|
263
|
-
|
|
264
|
-
require 'pio'
|
|
265
|
-
|
|
266
|
-
packet_in = Pio::PacketIn.read(binary_data)
|
|
267
|
-
packet_in.in_port # => 1
|
|
268
|
-
packet_in.buffer_id # => 4294967040
|
|
269
|
-
|
|
270
|
-
Also you can use `Pio::PacketIn#new` to generate a Packet-In message
|
|
271
|
-
like below:
|
|
272
|
-
|
|
273
|
-
require 'pio'
|
|
274
|
-
|
|
275
|
-
data_dump = [
|
|
276
|
-
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xac, 0x5d, 0x10, 0x31, 0x37,
|
|
277
|
-
0x79, 0x08, 0x06, 0x00, 0x01, 0x08, 0x00, 0x06, 0x04, 0x00, 0x01,
|
|
278
|
-
0xac, 0x5d, 0x10, 0x31, 0x37, 0x79, 0xc0, 0xa8, 0x02, 0xfe, 0xff,
|
|
279
|
-
0xff, 0xff, 0xff, 0xff, 0xff, 0xc0, 0xa8, 0x02, 0x05, 0x00, 0x00,
|
|
280
|
-
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
|
281
|
-
0x00, 0x00, 0x00, 0x00, 0x00
|
|
282
|
-
].pack('C*')
|
|
283
|
-
|
|
284
|
-
packet_in = Pio::PacketIn.new(transaction_id: 0,
|
|
285
|
-
buffer_id: 0xffffff00,
|
|
286
|
-
in_port: 1,
|
|
287
|
-
reason: :no_match,
|
|
288
|
-
raw_data: data_dump)
|
|
289
|
-
packet_in.to_binary # => Packet-In message in binary format.
|
|
290
|
-
|
|
291
|
-
### Packet-Out
|
|
292
|
-
|
|
293
|
-
To parse an OpenFlow 1.0 Packet-Out message, use the API
|
|
294
|
-
`Pio::PacketOut.read` and you can access each field of the parsed
|
|
295
|
-
Packet-Out message.
|
|
296
|
-
|
|
297
|
-
require 'pio'
|
|
298
|
-
|
|
299
|
-
packet_out = Pio::PacketOut.read(binary_data)
|
|
300
|
-
packet_out.actions.length # => 1
|
|
301
|
-
packet_out.actions[0] # => Pio::SendOutPort
|
|
302
|
-
packet_out.actions[0].port_number # => 2
|
|
303
|
-
|
|
304
|
-
Also you can use `Pio::PacketOut#new` to generate a Packet-Out message
|
|
305
|
-
like below:
|
|
306
|
-
|
|
307
|
-
require 'pio'
|
|
308
|
-
|
|
309
|
-
data_dump = [
|
|
310
|
-
0x01, 0x80, 0xc2, 0x00, 0x00, 0x0e, 0x01, 0x02, 0x03, 0x04,
|
|
311
|
-
0x05, 0x06, 0x88, 0xcc, 0x02, 0x09, 0x07, 0x00, 0x00, 0x00,
|
|
312
|
-
0x00, 0x00, 0x00, 0x01, 0x23, 0x04, 0x05, 0x07, 0x00, 0x00,
|
|
313
|
-
0x00, 0x0c, 0x06, 0x02, 0x00, 0x78, 0x00, 0x00, 0x00, 0x00,
|
|
314
|
-
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
|
315
|
-
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
|
316
|
-
0x00, 0x00, 0x00, 0x00
|
|
317
|
-
].pack('C*')
|
|
318
|
-
|
|
319
|
-
packet_out = Pio::PacketOut.new(transaction_id: 0x16,
|
|
320
|
-
buffer_id: 0xffffffff,
|
|
321
|
-
in_port: 0xffff,
|
|
322
|
-
actions: Pio::SendOutPort.new(2),
|
|
323
|
-
raw_data: data_dump)
|
|
324
|
-
packet_out.to_binary # => Packet-Out message in binary format.
|
|
325
|
-
|
|
326
|
-
### Flow Mod
|
|
327
|
-
|
|
328
|
-
To parse an OpenFlow 1.0 flow mod message, use the API
|
|
329
|
-
`Pio::FlowMod.read` and you can access each field of the parsed
|
|
330
|
-
flow mod message.
|
|
331
|
-
|
|
332
|
-
require 'pio'
|
|
333
|
-
|
|
334
|
-
flow_mod = Pio::FlowMod.read(binary_data)
|
|
335
|
-
flow_mod.match.in_port # => 1
|
|
336
|
-
flow_mod.match.dl_src # => '00:00:00:00:00:0a'
|
|
337
|
-
# ...
|
|
338
|
-
|
|
339
|
-
Also you can use `Pio::FlowMod#new` and `Pio::Match#new` to generate a
|
|
340
|
-
flow mod message like below:
|
|
341
|
-
|
|
342
|
-
require 'pio'
|
|
343
|
-
|
|
344
|
-
flow_mod = Pio::FlowMod.new(transaction_id: 0x15,
|
|
345
|
-
buffer_id: 0xffffffff,
|
|
346
|
-
match: Pio::Match.new(in_port: 1),
|
|
347
|
-
cookie: 1,
|
|
348
|
-
command: :add,
|
|
349
|
-
priority: 0xffff,
|
|
350
|
-
out_port: 2,
|
|
351
|
-
flags: [:send_flow_rem, :check_overwrap],
|
|
352
|
-
actions: Pio::SendOutPort.new(2))
|
|
353
|
-
|
|
354
|
-
flow_mod.to_binary # => Flow mod message in binary format.
|
|
39
|
+
- Pure Ruby. No additional dependency on other external tools to
|
|
40
|
+
parse/generate packets.
|
|
41
|
+
- Multi-Platform. Runs on major operating systems (recent Windows,
|
|
42
|
+
Linux, and MacOSX).
|
|
43
|
+
- Clean Code. Pio is built on
|
|
44
|
+
[BinData](https://github.com/dmendel/bindata)'s declarative binary
|
|
45
|
+
format DSL so that it is easy to read and debug by human beings.
|
|
355
46
|
|
|
356
47
|
## Installation
|
|
357
48
|
|
|
@@ -359,20 +50,24 @@ The simplest way to install Pio is to use [Bundler](http://gembundler.com/).
|
|
|
359
50
|
|
|
360
51
|
Add Pio to your `Gemfile`:
|
|
361
52
|
|
|
362
|
-
|
|
53
|
+
```ruby
|
|
54
|
+
gem 'pio'
|
|
55
|
+
```
|
|
363
56
|
|
|
364
57
|
and install it by running Bundler:
|
|
365
58
|
|
|
366
|
-
|
|
59
|
+
```bash
|
|
60
|
+
bundle
|
|
61
|
+
```
|
|
367
62
|
|
|
368
63
|
## Documents
|
|
369
64
|
|
|
370
|
-
-
|
|
65
|
+
- [API document generated with YARD](http://rubydoc.info/github/trema/pio/frames/file/README.md)
|
|
371
66
|
|
|
372
67
|
## Team
|
|
373
68
|
|
|
374
|
-
-
|
|
375
|
-
-
|
|
69
|
+
- [Yasuhito Takamiya](https://github.com/yasuhito) ([@yasuhito](https://twitter.com/yasuhito))
|
|
70
|
+
- [Eishun Kondoh](https://github.com/shun159) ([@Eishun\_Kondoh](https://twitter.com/Eishun_Kondoh))
|
|
376
71
|
|
|
377
72
|
### Contributors
|
|
378
73
|
|
|
@@ -380,10 +75,11 @@ and install it by running Bundler:
|
|
|
380
75
|
|
|
381
76
|
## Alternatives
|
|
382
77
|
|
|
383
|
-
-
|
|
384
|
-
-
|
|
78
|
+
- PacketFu: <https://github.com/todb/packetfu>
|
|
79
|
+
- Racket: <http://spoofed.org/files/racket/>
|
|
385
80
|
|
|
386
81
|
## License
|
|
387
82
|
|
|
388
83
|
Pio is released under the GNU General Public License version 3.0:
|
|
389
|
-
|
|
84
|
+
|
|
85
|
+
- <http://www.gnu.org/licenses/gpl.html>
|
data/Rakefile
CHANGED
|
@@ -1,5 +1,7 @@
|
|
|
1
1
|
require 'bundler/gem_tasks'
|
|
2
2
|
|
|
3
|
+
RELISH_PROJECT = 'trema/pio'
|
|
4
|
+
|
|
3
5
|
# rubocop:disable HashSyntax
|
|
4
6
|
|
|
5
7
|
task :default => :travis
|
|
@@ -12,3 +14,33 @@ task :quality => [:reek, :flog, :flay, :rubocop]
|
|
|
12
14
|
# rubocop:enable HashSyntax
|
|
13
15
|
|
|
14
16
|
Dir.glob('tasks/*.rake').each { |each| import each }
|
|
17
|
+
|
|
18
|
+
require 'pio/pcap'
|
|
19
|
+
|
|
20
|
+
def dump_in_hex(data)
|
|
21
|
+
hexdump = data.unpack('C*').map do |each|
|
|
22
|
+
format('0x%02x', each)
|
|
23
|
+
end
|
|
24
|
+
puts "[#{hexdump.join(', ')}]"
|
|
25
|
+
end
|
|
26
|
+
|
|
27
|
+
desc 'Dump packet data file in Array'
|
|
28
|
+
task :dump do
|
|
29
|
+
unless ENV['PACKET_FILE']
|
|
30
|
+
fail 'Usage: rake PACKET_FILE="foobar.{pcap,raw}" dump'
|
|
31
|
+
end
|
|
32
|
+
packet_file = File.join(File.dirname(__FILE__),
|
|
33
|
+
'../features/packet_data', ENV['PACKET_FILE'])
|
|
34
|
+
case File.extname(packet_file)
|
|
35
|
+
when '.raw'
|
|
36
|
+
dump_in_hex(IO.read(packet_file))
|
|
37
|
+
when '.pcap'
|
|
38
|
+
File.open(packet_file) do |file|
|
|
39
|
+
Pio::Pcap::Frame.read(file).records.each do |each|
|
|
40
|
+
dump_in_hex(each.data)
|
|
41
|
+
end
|
|
42
|
+
end
|
|
43
|
+
else
|
|
44
|
+
fail "Unsupported file extension: #{ENV['PACKET_FILE']}"
|
|
45
|
+
end
|
|
46
|
+
end
|