pio 0.20.0 → 0.20.1
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/CHANGELOG.md +5 -0
- data/Rakefile +2 -2
- data/features/open_flow13/match.feature +370 -0
- data/features/open_flow13/oxm_ether_destination_field.raw +0 -0
- data/features/open_flow13/oxm_ether_source_field.raw +0 -0
- data/features/open_flow13/oxm_ether_type_field.raw +0 -0
- data/features/open_flow13/oxm_in_phy_port_field.raw +0 -0
- data/features/open_flow13/oxm_in_port_field.raw +0 -0
- data/features/open_flow13/oxm_ipv4_destination_field.raw +0 -0
- data/features/open_flow13/oxm_ipv4_source_field.raw +0 -0
- data/features/open_flow13/oxm_ipv6_destination_field.raw +0 -0
- data/features/open_flow13/oxm_ipv6_source_field.raw +0 -0
- data/features/open_flow13/oxm_masked_ether_destination_field.raw +0 -0
- data/features/open_flow13/oxm_masked_ether_source_field.raw +0 -0
- data/features/open_flow13/oxm_masked_ipv4_destination_field.raw +0 -0
- data/features/open_flow13/oxm_masked_ipv4_source_field.raw +0 -0
- data/features/open_flow13/oxm_masked_ipv6_destination_field.raw +0 -0
- data/features/open_flow13/oxm_masked_ipv6_source_field.raw +0 -0
- data/features/open_flow13/oxm_metadata_field.raw +0 -0
- data/features/open_flow13/oxm_metadata_masked_field.raw +0 -0
- data/features/open_flow13/oxm_no_fields.raw +0 -0
- data/features/open_flow13/oxm_tcp_destination_field.raw +0 -0
- data/features/open_flow13/oxm_tcp_field.raw +0 -0
- data/features/open_flow13/oxm_tcp_source_field.raw +0 -0
- data/features/open_flow13/oxm_udp_destination_field.raw +0 -0
- data/features/open_flow13/oxm_udp_field.raw +0 -0
- data/features/open_flow13/oxm_udp_source_field.raw +0 -0
- data/lib/pio/ipv4_header.rb +0 -2
- data/lib/pio/open_flow/message.rb +18 -54
- data/lib/pio/open_flow10/packet_in.rb +1 -1
- data/lib/pio/open_flow13/match.rb +452 -0
- data/lib/pio/open_flow13.rb +7 -0
- data/lib/pio/type/ipv6_address.rb +21 -0
- data/lib/pio/version.rb +1 -1
- data/pio.gemspec +8 -8
- data/spec/pio/mac_spec.rb +2 -2
- data/spec/pio/open_flow13/match_spec.rb +387 -0
- data/spec/pio/packet_out_spec.rb +1 -2
- metadata +73 -19
@@ -0,0 +1,452 @@
|
|
1
|
+
require 'bindata'
|
2
|
+
require 'pio/type/ip_address'
|
3
|
+
require 'pio/type/ipv6_address'
|
4
|
+
require 'pio/type/mac_address'
|
5
|
+
|
6
|
+
# Base module.
|
7
|
+
module Pio
|
8
|
+
# OpenFlow 1.3.
|
9
|
+
module OpenFlow13
|
10
|
+
# OFPMT_OXM
|
11
|
+
MATCH_TYPE_OXM = 1
|
12
|
+
|
13
|
+
# OpenFlow eXtensible Match (OXM)
|
14
|
+
class Match
|
15
|
+
OXM_CLASS_OPENFLOW_BASIC = 0x8000
|
16
|
+
|
17
|
+
# The value of OXM_OF_IN_PORT match field.
|
18
|
+
class InPort < BinData::Record
|
19
|
+
OXM_FIELD = 0
|
20
|
+
|
21
|
+
endian :big
|
22
|
+
|
23
|
+
uint32 :in_port
|
24
|
+
|
25
|
+
def length
|
26
|
+
4
|
27
|
+
end
|
28
|
+
end
|
29
|
+
|
30
|
+
# The value of OXM_OF_ETH_DST match field.
|
31
|
+
class EtherDestinationAddress < BinData::Record
|
32
|
+
OXM_FIELD = 3
|
33
|
+
|
34
|
+
endian :big
|
35
|
+
|
36
|
+
mac_address :ether_destination_address
|
37
|
+
|
38
|
+
def length
|
39
|
+
6
|
40
|
+
end
|
41
|
+
end
|
42
|
+
|
43
|
+
# The value of OXM_OF_ETH_SRC match field.
|
44
|
+
class EtherSourceAddress < BinData::Record
|
45
|
+
OXM_FIELD = 4
|
46
|
+
|
47
|
+
endian :big
|
48
|
+
|
49
|
+
mac_address :ether_source_address
|
50
|
+
|
51
|
+
def length
|
52
|
+
6
|
53
|
+
end
|
54
|
+
end
|
55
|
+
|
56
|
+
# Masked OXM_OF_ETH_DST match field.
|
57
|
+
class MaskedEtherDestinationAddress < BinData::Record
|
58
|
+
endian :big
|
59
|
+
|
60
|
+
mac_address :ether_destination_address
|
61
|
+
mac_address :ether_destination_address_mask
|
62
|
+
|
63
|
+
def length
|
64
|
+
12
|
65
|
+
end
|
66
|
+
end
|
67
|
+
|
68
|
+
# Masked OXM_OF_ETH_SRC match field.
|
69
|
+
class MaskedEtherSourceAddress < BinData::Record
|
70
|
+
endian :big
|
71
|
+
|
72
|
+
mac_address :ether_source_address
|
73
|
+
mac_address :ether_source_address_mask
|
74
|
+
|
75
|
+
def length
|
76
|
+
12
|
77
|
+
end
|
78
|
+
end
|
79
|
+
|
80
|
+
# The value of OXM_OF_ETH_TYPE match field.
|
81
|
+
class EtherType < BinData::Record
|
82
|
+
OXM_FIELD = 5
|
83
|
+
|
84
|
+
endian :big
|
85
|
+
|
86
|
+
uint16 :ether_type
|
87
|
+
|
88
|
+
def length
|
89
|
+
2
|
90
|
+
end
|
91
|
+
end
|
92
|
+
|
93
|
+
# The value of OXM_OF_IP_PROTO
|
94
|
+
class IpProtocol < BinData::Record
|
95
|
+
OXM_FIELD = 10
|
96
|
+
|
97
|
+
endian :big
|
98
|
+
|
99
|
+
uint8 :ip_protocol
|
100
|
+
|
101
|
+
def length
|
102
|
+
1
|
103
|
+
end
|
104
|
+
end
|
105
|
+
|
106
|
+
# The value of OXM_OF_IPV4_SRC
|
107
|
+
class Ipv4SourceAddress < BinData::Record
|
108
|
+
OXM_FIELD = 11
|
109
|
+
|
110
|
+
endian :big
|
111
|
+
|
112
|
+
ip_address :ipv4_source_address
|
113
|
+
|
114
|
+
def length
|
115
|
+
4
|
116
|
+
end
|
117
|
+
end
|
118
|
+
|
119
|
+
# The value of masked OXM_OF_IPV4_SRC
|
120
|
+
class MaskedIpv4SourceAddress < BinData::Record
|
121
|
+
OXM_FIELD = 11
|
122
|
+
|
123
|
+
endian :big
|
124
|
+
ip_address :ipv4_source_address
|
125
|
+
ip_address :ipv4_source_address_mask
|
126
|
+
|
127
|
+
def length
|
128
|
+
8
|
129
|
+
end
|
130
|
+
end
|
131
|
+
|
132
|
+
# The value of OXM_OF_IPV4_DST
|
133
|
+
class Ipv4DestinationAddress < BinData::Record
|
134
|
+
OXM_FIELD = 12
|
135
|
+
|
136
|
+
endian :big
|
137
|
+
|
138
|
+
ip_address :ipv4_destination_address
|
139
|
+
|
140
|
+
def length
|
141
|
+
4
|
142
|
+
end
|
143
|
+
end
|
144
|
+
|
145
|
+
# The value of masked OXM_OF_IPV4_DST
|
146
|
+
class MaskedIpv4DestinationAddress < BinData::Record
|
147
|
+
OXM_FIELD = 12
|
148
|
+
|
149
|
+
endian :big
|
150
|
+
ip_address :ipv4_destination_address
|
151
|
+
ip_address :ipv4_destination_address_mask
|
152
|
+
|
153
|
+
def length
|
154
|
+
8
|
155
|
+
end
|
156
|
+
end
|
157
|
+
|
158
|
+
# The value of OXM_OF_TCP_SRC
|
159
|
+
class TcpSourcePort < BinData::Record
|
160
|
+
OXM_FIELD = 13
|
161
|
+
|
162
|
+
endian :big
|
163
|
+
|
164
|
+
uint16 :tcp_source_port
|
165
|
+
|
166
|
+
def length
|
167
|
+
16
|
168
|
+
end
|
169
|
+
end
|
170
|
+
|
171
|
+
# The value of OXM_OF_TCP_DST
|
172
|
+
class TcpDestinationPort < BinData::Record
|
173
|
+
OXM_FIELD = 14
|
174
|
+
|
175
|
+
endian :big
|
176
|
+
|
177
|
+
uint16 :tcp_destination_port
|
178
|
+
|
179
|
+
def length
|
180
|
+
16
|
181
|
+
end
|
182
|
+
end
|
183
|
+
|
184
|
+
# The value of OXM_OF_UDP_SRC
|
185
|
+
class UdpSourcePort < BinData::Record
|
186
|
+
OXM_FIELD = 15
|
187
|
+
|
188
|
+
endian :big
|
189
|
+
|
190
|
+
uint16 :udp_source_port
|
191
|
+
|
192
|
+
def length
|
193
|
+
16
|
194
|
+
end
|
195
|
+
end
|
196
|
+
|
197
|
+
# The value of OXM_OF_UDP_SRC
|
198
|
+
class UdpDestinationPort < BinData::Record
|
199
|
+
OXM_FIELD = 16
|
200
|
+
|
201
|
+
endian :big
|
202
|
+
|
203
|
+
uint16 :udp_destination_port
|
204
|
+
|
205
|
+
def length
|
206
|
+
16
|
207
|
+
end
|
208
|
+
end
|
209
|
+
|
210
|
+
# The value of OXM_OF_IPV6_SRC
|
211
|
+
class Ipv6SourceAddress < BinData::Record
|
212
|
+
OXM_FIELD = 26
|
213
|
+
|
214
|
+
endian :big
|
215
|
+
|
216
|
+
ipv6_address :ipv6_source_address
|
217
|
+
|
218
|
+
def length
|
219
|
+
128
|
220
|
+
end
|
221
|
+
end
|
222
|
+
|
223
|
+
# The value of masked OXM_OF_IPV6_SRC
|
224
|
+
class MaskedIpv6SourceAddress < BinData::Record
|
225
|
+
OXM_FIELD = 26
|
226
|
+
|
227
|
+
endian :big
|
228
|
+
|
229
|
+
ipv6_address :ipv6_source_address
|
230
|
+
ipv6_address :ipv6_source_address_mask
|
231
|
+
|
232
|
+
def length
|
233
|
+
256
|
234
|
+
end
|
235
|
+
end
|
236
|
+
|
237
|
+
# The value of OXM_OF_IPV6_DST
|
238
|
+
class Ipv6DestinationAddress < BinData::Record
|
239
|
+
OXM_FIELD = 27
|
240
|
+
|
241
|
+
endian :big
|
242
|
+
|
243
|
+
ipv6_address :ipv6_destination_address
|
244
|
+
|
245
|
+
def length
|
246
|
+
128
|
247
|
+
end
|
248
|
+
end
|
249
|
+
|
250
|
+
# The value of OXM_OF_IPV6_DST
|
251
|
+
class MaskedIpv6DestinationAddress < BinData::Record
|
252
|
+
OXM_FIELD = 27
|
253
|
+
|
254
|
+
endian :big
|
255
|
+
|
256
|
+
ipv6_address :ipv6_destination_address
|
257
|
+
ipv6_address :ipv6_destination_address_mask
|
258
|
+
|
259
|
+
def length
|
260
|
+
256
|
261
|
+
end
|
262
|
+
end
|
263
|
+
|
264
|
+
# OXM format
|
265
|
+
class Format < BinData::Record
|
266
|
+
# OXM match field.
|
267
|
+
class MatchField < BinData::Record
|
268
|
+
endian :big
|
269
|
+
|
270
|
+
uint16 :oxm_class, value: OXM_CLASS_OPENFLOW_BASIC
|
271
|
+
bit7 :oxm_field
|
272
|
+
bit1 :oxm_hasmask
|
273
|
+
uint8 :oxm_length, value: -> { tlv_value.length }
|
274
|
+
choice :tlv_value,
|
275
|
+
read_length: :oxm_length,
|
276
|
+
selection: :choose_tlv_value do
|
277
|
+
in_port InPort
|
278
|
+
ether_destination_address EtherDestinationAddress
|
279
|
+
masked_ether_destination_address MaskedEtherDestinationAddress
|
280
|
+
ether_source_address EtherSourceAddress
|
281
|
+
masked_ether_source_address MaskedEtherSourceAddress
|
282
|
+
ether_type EtherType
|
283
|
+
ipv4_source_address Ipv4SourceAddress
|
284
|
+
masked_ipv4_source_address MaskedIpv4SourceAddress
|
285
|
+
ipv4_destination_address Ipv4DestinationAddress
|
286
|
+
masked_ipv4_destination_address MaskedIpv4DestinationAddress
|
287
|
+
ip_protocol IpProtocol
|
288
|
+
tcp_source_port TcpSourcePort
|
289
|
+
tcp_destination_port TcpDestinationPort
|
290
|
+
udp_source_port UdpSourcePort
|
291
|
+
udp_destination_port UdpDestinationPort
|
292
|
+
ipv6_source_address Ipv6SourceAddress
|
293
|
+
masked_ipv6_source_address MaskedIpv6SourceAddress
|
294
|
+
ipv6_destination_address Ipv6DestinationAddress
|
295
|
+
masked_ipv6_destination_address MaskedIpv6DestinationAddress
|
296
|
+
end
|
297
|
+
|
298
|
+
def length
|
299
|
+
tlv_value.length + 4
|
300
|
+
end
|
301
|
+
|
302
|
+
def masked?
|
303
|
+
oxm_hasmask == 1
|
304
|
+
end
|
305
|
+
|
306
|
+
def method_missing(method, *args, &block)
|
307
|
+
tlv_value.__send__ method, *args, &block
|
308
|
+
end
|
309
|
+
|
310
|
+
private
|
311
|
+
|
312
|
+
# rubocop:disable MethodLength
|
313
|
+
# rubocop:disable CyclomaticComplexity
|
314
|
+
# rubocop:disable PerceivedComplexity
|
315
|
+
# rubocop:disable AbcSize
|
316
|
+
def choose_tlv_value
|
317
|
+
case oxm_field
|
318
|
+
when InPort::OXM_FIELD
|
319
|
+
InPort
|
320
|
+
when EtherDestinationAddress::OXM_FIELD
|
321
|
+
masked? ? MaskedEtherDestinationAddress : EtherDestinationAddress
|
322
|
+
when EtherSourceAddress::OXM_FIELD
|
323
|
+
masked? ? MaskedEtherSourceAddress : EtherSourceAddress
|
324
|
+
when EtherType::OXM_FIELD
|
325
|
+
EtherType
|
326
|
+
when Ipv4SourceAddress::OXM_FIELD
|
327
|
+
masked? ? MaskedIpv4SourceAddress : Ipv4SourceAddress
|
328
|
+
when Ipv4DestinationAddress::OXM_FIELD
|
329
|
+
masked? ? MaskedIpv4DestinationAddress : Ipv4DestinationAddress
|
330
|
+
when IpProtocol::OXM_FIELD
|
331
|
+
IpProtocol
|
332
|
+
when TcpSourcePort::OXM_FIELD
|
333
|
+
TcpSourcePort
|
334
|
+
when TcpDestinationPort::OXM_FIELD
|
335
|
+
TcpDestinationPort
|
336
|
+
when UdpSourcePort::OXM_FIELD
|
337
|
+
UdpSourcePort
|
338
|
+
when UdpDestinationPort::OXM_FIELD
|
339
|
+
UdpDestinationPort
|
340
|
+
when Ipv6SourceAddress::OXM_FIELD
|
341
|
+
masked? ? MaskedIpv6SourceAddress : Ipv6SourceAddress
|
342
|
+
when Ipv6DestinationAddress::OXM_FIELD
|
343
|
+
masked? ? MaskedIpv6DestinationAddress : Ipv6DestinationAddress
|
344
|
+
else
|
345
|
+
fail "Unknown OXM field value: #{oxm_field}"
|
346
|
+
end
|
347
|
+
end
|
348
|
+
# rubocop:enable MethodLength
|
349
|
+
# rubocop:enable CyclomaticComplexity
|
350
|
+
# rubocop:enable PerceivedComplexity
|
351
|
+
# rubocop:enable AbcSize
|
352
|
+
end
|
353
|
+
|
354
|
+
endian :big
|
355
|
+
|
356
|
+
uint16 :match_type, value: MATCH_TYPE_OXM
|
357
|
+
uint16 :match_length, initial_value: -> { 4 + tlv_total_length }
|
358
|
+
array(:match_fields,
|
359
|
+
type: :match_field,
|
360
|
+
read_until: -> { tlv_length_left <= 5 },
|
361
|
+
onlyif: -> { match_length > 4 })
|
362
|
+
string :padding, length: :padding_length
|
363
|
+
hide :padding
|
364
|
+
|
365
|
+
def method_missing(method, *args, &block)
|
366
|
+
match_fields.each do |each|
|
367
|
+
next unless each.tlv_value.respond_to?(method)
|
368
|
+
return each.tlv_value.__send__(method, *args, &block)
|
369
|
+
end
|
370
|
+
fail NoMethodError, method.to_s
|
371
|
+
end
|
372
|
+
|
373
|
+
private
|
374
|
+
|
375
|
+
def tlv_length_left
|
376
|
+
match_length - tlv_total_length
|
377
|
+
end
|
378
|
+
|
379
|
+
def tlv_total_length
|
380
|
+
if match_fields.size > 0
|
381
|
+
match_fields.map(&:length).inject(&:+)
|
382
|
+
else
|
383
|
+
0
|
384
|
+
end
|
385
|
+
end
|
386
|
+
|
387
|
+
def padding_length
|
388
|
+
(match_length + 7) / 8 * 8 - match_length
|
389
|
+
end
|
390
|
+
end
|
391
|
+
|
392
|
+
# Match.new option parser.
|
393
|
+
class Options
|
394
|
+
# rubocop:disable MethodLength
|
395
|
+
# rubocop:disable AbcSize
|
396
|
+
def initialize(user_attrs)
|
397
|
+
@match_fields = []
|
398
|
+
|
399
|
+
[:in_port, :ether_type, :ip_protocol,
|
400
|
+
:tcp_source_port, :tcp_destination_port,
|
401
|
+
:udp_source_port, :udp_destination_port].each do |each|
|
402
|
+
next unless user_attrs.key?(each)
|
403
|
+
klass = Match.const_get(each.to_s.split('_').map(&:capitalize).join)
|
404
|
+
@match_fields << { oxm_field: klass.const_get(:OXM_FIELD),
|
405
|
+
tlv_value: { each => user_attrs.fetch(each) } }
|
406
|
+
end
|
407
|
+
|
408
|
+
[:ether_destination_address, :ether_source_address,
|
409
|
+
:ipv4_source_address, :ipv4_destination_address,
|
410
|
+
:ipv6_source_address, :ipv6_destination_address].each do |each|
|
411
|
+
next unless user_attrs.key?(each)
|
412
|
+
klass = Match.const_get(each.to_s.split('_').map(&:capitalize).join)
|
413
|
+
mask_key = "#{each}_mask".to_sym
|
414
|
+
@match_fields <<
|
415
|
+
{ oxm_field: klass.const_get(:OXM_FIELD),
|
416
|
+
oxm_hasmask: user_attrs.key?(mask_key) ? 1 : 0,
|
417
|
+
tlv_value: { each => user_attrs[each],
|
418
|
+
mask_key => user_attrs[mask_key] } }
|
419
|
+
end
|
420
|
+
end
|
421
|
+
# rubocop:enable MethodLength
|
422
|
+
# rubocop:enable AbcSize
|
423
|
+
|
424
|
+
def to_hash
|
425
|
+
{ match_fields: @match_fields }
|
426
|
+
end
|
427
|
+
end
|
428
|
+
|
429
|
+
def self.read(raw_data)
|
430
|
+
allocate.tap do |message|
|
431
|
+
message.instance_variable_set(:@format, Format.read(raw_data))
|
432
|
+
end
|
433
|
+
end
|
434
|
+
|
435
|
+
def initialize(user_attrs = {})
|
436
|
+
@format = if user_attrs.empty?
|
437
|
+
Format.new
|
438
|
+
else
|
439
|
+
Format.new(Options.new(user_attrs).to_hash)
|
440
|
+
end
|
441
|
+
end
|
442
|
+
|
443
|
+
def length
|
444
|
+
@format.to_binary_s.length
|
445
|
+
end
|
446
|
+
|
447
|
+
def method_missing(method, *args, &block)
|
448
|
+
@format.__send__ method, *args, &block
|
449
|
+
end
|
450
|
+
end
|
451
|
+
end
|
452
|
+
end
|
data/lib/pio/open_flow13.rb
CHANGED
@@ -10,3 +10,10 @@ require 'pio/open_flow13/echo'
|
|
10
10
|
require 'pio/open_flow13/features_reply'
|
11
11
|
require 'pio/open_flow13/features_request'
|
12
12
|
require 'pio/open_flow13/hello'
|
13
|
+
require 'pio/open_flow13/match'
|
14
|
+
|
15
|
+
# Base module.
|
16
|
+
module Pio
|
17
|
+
remove_const :Match
|
18
|
+
Match = OpenFlow13::Match
|
19
|
+
end
|
@@ -0,0 +1,21 @@
|
|
1
|
+
require 'bindata'
|
2
|
+
require 'ipaddr'
|
3
|
+
|
4
|
+
module Pio
|
5
|
+
module Type
|
6
|
+
# IPv6 address
|
7
|
+
class Ipv6Address < BinData::Primitive
|
8
|
+
endian :big
|
9
|
+
|
10
|
+
uint128 :ipv6_address
|
11
|
+
|
12
|
+
def set(value)
|
13
|
+
self.ipv6_address = IPAddr.new(value, Socket::Constants::AF_INET6)
|
14
|
+
end
|
15
|
+
|
16
|
+
def get
|
17
|
+
IPAddr.new(ipv6_address, Socket::Constants::AF_INET6).to_s
|
18
|
+
end
|
19
|
+
end
|
20
|
+
end
|
21
|
+
end
|
data/lib/pio/version.rb
CHANGED
data/pio.gemspec
CHANGED
@@ -31,33 +31,33 @@ Gem::Specification.new do |gem|
|
|
31
31
|
gem.add_dependency 'bindata', '~> 2.1.0'
|
32
32
|
|
33
33
|
gem.add_development_dependency 'rake'
|
34
|
-
gem.add_development_dependency 'bundler', '~> 1.
|
34
|
+
gem.add_development_dependency 'bundler', '~> 1.10.3'
|
35
35
|
gem.add_development_dependency 'pry', '~> 0.10.1'
|
36
36
|
|
37
37
|
# Guard
|
38
|
-
gem.add_development_dependency 'guard', '~> 2.12.
|
38
|
+
gem.add_development_dependency 'guard', '~> 2.12.6'
|
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.5.
|
41
|
+
gem.add_development_dependency 'guard-rspec', '~> 4.5.2'
|
42
42
|
gem.add_development_dependency 'guard-rubocop', '~> 1.2.0'
|
43
43
|
gem.add_development_dependency 'rb-fchange', '~> 0.0.6'
|
44
|
-
gem.add_development_dependency 'rb-fsevent', '~> 0.9.
|
44
|
+
gem.add_development_dependency 'rb-fsevent', '~> 0.9.5'
|
45
45
|
gem.add_development_dependency 'rb-inotify', '~> 0.9.5'
|
46
46
|
gem.add_development_dependency 'terminal-notifier-guard', '~> 1.6.4'
|
47
47
|
|
48
48
|
# Docs
|
49
|
-
gem.add_development_dependency 'inch', '~> 0.
|
49
|
+
gem.add_development_dependency 'inch', '~> 0.6.2'
|
50
50
|
gem.add_development_dependency 'relish', '~> 0.7.1'
|
51
51
|
gem.add_development_dependency 'yard', '~> 0.8.7.6'
|
52
52
|
|
53
53
|
# Test
|
54
54
|
gem.add_development_dependency 'codeclimate-test-reporter', '~> 0.4.7'
|
55
|
-
gem.add_development_dependency 'coveralls', '~> 0.8.
|
55
|
+
gem.add_development_dependency 'coveralls', '~> 0.8.1'
|
56
56
|
gem.add_development_dependency 'cucumber', '~> 2.0.0'
|
57
57
|
gem.add_development_dependency 'flay', '~> 2.6.1'
|
58
58
|
gem.add_development_dependency 'flog', '~> 4.3.2'
|
59
|
-
gem.add_development_dependency 'reek', '~> 2.1
|
59
|
+
gem.add_development_dependency 'reek', '~> 2.2.1'
|
60
60
|
gem.add_development_dependency 'rspec', '~> 3.2.0'
|
61
61
|
gem.add_development_dependency 'rspec-given', '~> 3.7.0'
|
62
|
-
gem.add_development_dependency 'rubocop', '~> 0.
|
62
|
+
gem.add_development_dependency 'rubocop', '~> 0.32.0'
|
63
63
|
end
|
data/spec/pio/mac_spec.rb
CHANGED
@@ -142,9 +142,9 @@ describe Pio::Mac do
|
|
142
142
|
context 'with reserved address' do
|
143
143
|
(0x0..0xf).each do |each|
|
144
144
|
octet = format('%02x', each)
|
145
|
-
reserved_address = "01:80:c2:00:00:#{
|
145
|
+
reserved_address = "01:80:c2:00:00:#{octet}"
|
146
146
|
|
147
|
-
context "when #{
|
147
|
+
context "when #{reserved_address}" do
|
148
148
|
let(:value) { reserved_address }
|
149
149
|
|
150
150
|
describe '#reserved?' do
|