pio 0.22.0 → 0.23.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 +7 -0
- data/README.md +1 -0
- data/Rakefile +1 -1
- data/features/open_flow13/match.feature +215 -0
- data/features/open_flow13/oxm_arp_op_field.raw +0 -0
- data/features/open_flow13/oxm_arp_sha_field.raw +0 -0
- data/features/open_flow13/oxm_arp_spa_field.raw +0 -0
- data/features/open_flow13/oxm_arp_tha_field.raw +0 -0
- data/features/open_flow13/oxm_arp_tpa_field.raw +0 -0
- data/features/open_flow13/oxm_masked_arp_sha_field.raw +0 -0
- data/features/open_flow13/oxm_masked_arp_spa_field.raw +0 -0
- data/features/open_flow13/oxm_masked_arp_tha_field.raw +0 -0
- data/features/open_flow13/oxm_masked_arp_tpa_field.raw +0 -0
- data/features/open_flow13/oxm_masked_tunnel_id_field.raw +0 -0
- data/features/open_flow13/oxm_tunnel_id_field.raw +0 -0
- data/features/open_flow13/packet_out.feature +96 -0
- data/lib/pio/open_flow13.rb +1 -0
- data/lib/pio/open_flow13/actions.rb +42 -0
- data/lib/pio/open_flow13/apply.rb +1 -39
- data/lib/pio/open_flow13/buffer_id.rb +17 -0
- data/lib/pio/open_flow13/flow_mod.rb +1 -16
- data/lib/pio/open_flow13/match.rb +197 -4
- data/lib/pio/open_flow13/packet_out.rb +90 -0
- data/lib/pio/version.rb +1 -1
- data/spec/pio/open_flow13/match_spec.rb +290 -0
- metadata +29 -2
@@ -1,48 +1,10 @@
|
|
1
1
|
require 'bindata'
|
2
2
|
require 'forwardable'
|
3
|
+
require 'pio/open_flow13/actions'
|
3
4
|
|
4
5
|
module Pio
|
5
6
|
# An instruction to apply a list of actions to a packet in-order.
|
6
7
|
class Apply
|
7
|
-
# Actions not yet implemented.
|
8
|
-
class UnsupportedAction < BinData::Record
|
9
|
-
endian :big
|
10
|
-
|
11
|
-
uint16 :action_type
|
12
|
-
uint16 :action_length
|
13
|
-
end
|
14
|
-
|
15
|
-
# Actions list of actions-apply instruction.
|
16
|
-
class Actions < BinData::Primitive
|
17
|
-
mandatory_parameter :length
|
18
|
-
|
19
|
-
endian :big
|
20
|
-
|
21
|
-
string :binary, read_length: :length
|
22
|
-
|
23
|
-
def set(value)
|
24
|
-
self.binary = [value].flatten.map(&:to_binary).join
|
25
|
-
end
|
26
|
-
|
27
|
-
# rubocop:disable MethodLength
|
28
|
-
def get
|
29
|
-
actions = []
|
30
|
-
tmp = binary
|
31
|
-
while tmp.length > 0
|
32
|
-
action = case BinData::Uint16be.read(tmp)
|
33
|
-
when 0
|
34
|
-
SendOutPort.read(tmp)
|
35
|
-
else
|
36
|
-
UnsupportedAction.read(tmp)
|
37
|
-
end
|
38
|
-
tmp = tmp[action.action_length..-1]
|
39
|
-
actions << action
|
40
|
-
end
|
41
|
-
actions
|
42
|
-
end
|
43
|
-
# rubocop:enable MethodLength
|
44
|
-
end
|
45
|
-
|
46
8
|
# OpenFlow 1.3.4 OFPIT_APPLY_ACTIONS instruction format.
|
47
9
|
class Format < BinData::Record
|
48
10
|
endian :big
|
@@ -0,0 +1,17 @@
|
|
1
|
+
module Pio
|
2
|
+
# Buffered packet to apply to, or :no_buffer.
|
3
|
+
class BufferId < BinData::Primitive
|
4
|
+
NO_BUFFER = 0xffffffff
|
5
|
+
|
6
|
+
endian :big
|
7
|
+
uint32 :buffer_id, initial_value: NO_BUFFER
|
8
|
+
|
9
|
+
def get
|
10
|
+
(buffer_id == NO_BUFFER) ? :no_buffer : buffer_id
|
11
|
+
end
|
12
|
+
|
13
|
+
def set(value)
|
14
|
+
self.buffer_id = (value == :no_buffer ? NO_BUFFER : value)
|
15
|
+
end
|
16
|
+
end
|
17
|
+
end
|
@@ -1,5 +1,6 @@
|
|
1
1
|
require 'forwardable'
|
2
2
|
require 'pio/open_flow'
|
3
|
+
require 'pio/open_flow13/buffer_id'
|
3
4
|
require 'pio/open_flow13/match'
|
4
5
|
|
5
6
|
# Base module.
|
@@ -29,22 +30,6 @@ module Pio
|
|
29
30
|
end
|
30
31
|
end
|
31
32
|
|
32
|
-
# Buffered packet to apply to, or :no_buffer.
|
33
|
-
class BufferId < BinData::Primitive
|
34
|
-
NO_BUFFER = 0xffffffff
|
35
|
-
|
36
|
-
endian :big
|
37
|
-
uint32 :buffer_id, initial_value: NO_BUFFER
|
38
|
-
|
39
|
-
def get
|
40
|
-
(buffer_id == NO_BUFFER) ? :no_buffer : buffer_id
|
41
|
-
end
|
42
|
-
|
43
|
-
def set(value)
|
44
|
-
self.buffer_id = (value == :no_buffer ? NO_BUFFER : value)
|
45
|
-
end
|
46
|
-
end
|
47
|
-
|
48
33
|
# For delete commands, require matching entries to include this as
|
49
34
|
# an output port.
|
50
35
|
class OutPort < BinData::Primitive
|
@@ -348,6 +348,125 @@ module Pio
|
|
348
348
|
end
|
349
349
|
end
|
350
350
|
|
351
|
+
# The value of OXM_OF_ARP_OP
|
352
|
+
class ArpOp < BinData::Record
|
353
|
+
OXM_FIELD = 21
|
354
|
+
|
355
|
+
endian :big
|
356
|
+
|
357
|
+
uint16 :arp_op
|
358
|
+
|
359
|
+
def length
|
360
|
+
2
|
361
|
+
end
|
362
|
+
end
|
363
|
+
|
364
|
+
# The value of OXM_OF_ARP_SPA
|
365
|
+
class ArpSenderProtocolAddress < BinData::Record
|
366
|
+
OXM_FIELD = 22
|
367
|
+
|
368
|
+
endian :big
|
369
|
+
|
370
|
+
ip_address :arp_sender_protocol_address
|
371
|
+
|
372
|
+
def length
|
373
|
+
4
|
374
|
+
end
|
375
|
+
end
|
376
|
+
|
377
|
+
# The value of masked OXM_OF_ARP_SPA
|
378
|
+
class MaskedArpSenderProtocolAddress < BinData::Record
|
379
|
+
OXM_FIELD = 22
|
380
|
+
|
381
|
+
endian :big
|
382
|
+
ip_address :arp_sender_protocol_address
|
383
|
+
ip_address :arp_sender_protocol_address_mask
|
384
|
+
|
385
|
+
def length
|
386
|
+
8
|
387
|
+
end
|
388
|
+
end
|
389
|
+
|
390
|
+
# The value of OXM_OF_ARP_TPA
|
391
|
+
class ArpTargetProtocolAddress < BinData::Record
|
392
|
+
OXM_FIELD = 23
|
393
|
+
|
394
|
+
endian :big
|
395
|
+
|
396
|
+
ip_address :arp_target_protocol_address
|
397
|
+
|
398
|
+
def length
|
399
|
+
4
|
400
|
+
end
|
401
|
+
end
|
402
|
+
|
403
|
+
# The value of masked OXM_OF_ARP_TPA
|
404
|
+
class MaskedArpTargetProtocolAddress < BinData::Record
|
405
|
+
OXM_FIELD = 23
|
406
|
+
|
407
|
+
endian :big
|
408
|
+
ip_address :arp_target_protocol_address
|
409
|
+
ip_address :arp_target_protocol_address_mask
|
410
|
+
|
411
|
+
def length
|
412
|
+
8
|
413
|
+
end
|
414
|
+
end
|
415
|
+
|
416
|
+
# The value of OXM_OF_ARP_SHA match field.
|
417
|
+
class ArpSenderHardwareAddress < BinData::Record
|
418
|
+
OXM_FIELD = 24
|
419
|
+
|
420
|
+
endian :big
|
421
|
+
|
422
|
+
mac_address :arp_sender_hardware_address
|
423
|
+
|
424
|
+
def length
|
425
|
+
6
|
426
|
+
end
|
427
|
+
end
|
428
|
+
|
429
|
+
# Masked OXM_OF_ARP_SHA match field.
|
430
|
+
class MaskedArpSenderHardwareAddress < BinData::Record
|
431
|
+
OXM_FIELD = 24
|
432
|
+
|
433
|
+
endian :big
|
434
|
+
|
435
|
+
mac_address :arp_sender_hardware_address
|
436
|
+
mac_address :arp_sender_hardware_address_mask
|
437
|
+
|
438
|
+
def length
|
439
|
+
12
|
440
|
+
end
|
441
|
+
end
|
442
|
+
|
443
|
+
# The value of OXM_OF_ARP_THA match field.
|
444
|
+
class ArpTargetHardwareAddress < BinData::Record
|
445
|
+
OXM_FIELD = 25
|
446
|
+
|
447
|
+
endian :big
|
448
|
+
|
449
|
+
mac_address :arp_target_hardware_address
|
450
|
+
|
451
|
+
def length
|
452
|
+
6
|
453
|
+
end
|
454
|
+
end
|
455
|
+
|
456
|
+
# Masked OXM_OF_ARP_THA match field.
|
457
|
+
class MaskedArpTargetHardwareAddress < BinData::Record
|
458
|
+
OXM_FIELD = 25
|
459
|
+
|
460
|
+
endian :big
|
461
|
+
|
462
|
+
mac_address :arp_target_hardware_address
|
463
|
+
mac_address :arp_target_hardware_address_mask
|
464
|
+
|
465
|
+
def length
|
466
|
+
12
|
467
|
+
end
|
468
|
+
end
|
469
|
+
|
351
470
|
# The value of OXM_OF_IPV6_SRC
|
352
471
|
class Ipv6SourceAddress < BinData::Record
|
353
472
|
OXM_FIELD = 26
|
@@ -402,9 +521,35 @@ module Pio
|
|
402
521
|
end
|
403
522
|
end
|
404
523
|
|
524
|
+
# The value of OXM_OF_TUNNEL_ID match field
|
525
|
+
class TunnelId < BinData::Record
|
526
|
+
OXM_FIELD = 38
|
527
|
+
|
528
|
+
endian :big
|
529
|
+
|
530
|
+
uint64 :tunnel_id
|
531
|
+
|
532
|
+
def length
|
533
|
+
8
|
534
|
+
end
|
535
|
+
end
|
536
|
+
|
537
|
+
# Masked OXM_OF_TUNNEL_ID match field
|
538
|
+
class MaskedTunnelId < BinData::Record
|
539
|
+
endian :big
|
540
|
+
|
541
|
+
uint64 :tunnel_id
|
542
|
+
uint64 :tunnel_id_mask
|
543
|
+
|
544
|
+
def length
|
545
|
+
16
|
546
|
+
end
|
547
|
+
end
|
548
|
+
|
405
549
|
# OXM format
|
406
550
|
class Oxm < BinData::Record
|
407
551
|
# OXM match field.
|
552
|
+
# rubocop:disable ClassLength
|
408
553
|
class MatchField < BinData::Record
|
409
554
|
endian :big
|
410
555
|
|
@@ -438,12 +583,23 @@ module Pio
|
|
438
583
|
udp_destination_port UdpDestinationPort
|
439
584
|
sctp_source_port SctpSourcePort
|
440
585
|
sctp_destination_port SctpDestinationPort
|
586
|
+
arp_op ArpOp
|
587
|
+
arp_sender_protocol_address ArpSenderProtocolAddress
|
588
|
+
masked_arp_sender_protocol_address MaskedArpSenderProtocolAddress
|
589
|
+
arp_target_protocol_address ArpTargetProtocolAddress
|
590
|
+
masked_arp_target_protocol_address MaskedArpTargetProtocolAddress
|
591
|
+
arp_sender_hardware_address ArpSenderHardwareAddress
|
592
|
+
masked_arp_sender_hardware_address MaskedArpSenderHardwareAddress
|
593
|
+
arp_target_hardware_address ArpTargetHardwareAddress
|
594
|
+
masked_arp_target_hardware_address MaskedArpTargetHardwareAddress
|
441
595
|
icmpv4_type Icmpv4Type
|
442
596
|
icmpv4_code Icmpv4Code
|
443
597
|
ipv6_source_address Ipv6SourceAddress
|
444
598
|
masked_ipv6_source_address MaskedIpv6SourceAddress
|
445
599
|
ipv6_destination_address Ipv6DestinationAddress
|
446
600
|
masked_ipv6_destination_address MaskedIpv6DestinationAddress
|
601
|
+
tunnel_id TunnelId
|
602
|
+
masked_tunnel_id MaskedTunnelId
|
447
603
|
end
|
448
604
|
|
449
605
|
def length
|
@@ -506,10 +662,42 @@ module Pio
|
|
506
662
|
Icmpv4Type
|
507
663
|
when Icmpv4Code::OXM_FIELD
|
508
664
|
Icmpv4Code
|
665
|
+
when ArpOp::OXM_FIELD
|
666
|
+
ArpOp
|
667
|
+
when ArpSenderProtocolAddress::OXM_FIELD
|
668
|
+
if masked?
|
669
|
+
MaskedArpSenderProtocolAddress
|
670
|
+
else
|
671
|
+
ArpSenderProtocolAddress
|
672
|
+
end
|
673
|
+
when ArpTargetProtocolAddress::OXM_FIELD
|
674
|
+
if masked?
|
675
|
+
MaskedArpTargetProtocolAddress
|
676
|
+
else
|
677
|
+
ArpTargetProtocolAddress
|
678
|
+
end
|
679
|
+
when ArpSenderHardwareAddress::OXM_FIELD
|
680
|
+
if masked?
|
681
|
+
MaskedArpSenderHardwareAddress
|
682
|
+
else
|
683
|
+
ArpSenderHardwareAddress
|
684
|
+
end
|
685
|
+
when ArpTargetHardwareAddress::OXM_FIELD
|
686
|
+
if masked?
|
687
|
+
MaskedArpTargetHardwareAddress
|
688
|
+
else
|
689
|
+
ArpTargetHardwareAddress
|
690
|
+
end
|
509
691
|
when Ipv6SourceAddress::OXM_FIELD
|
510
|
-
masked?
|
692
|
+
if masked?
|
693
|
+
MaskedIpv6SourceAddress
|
694
|
+
else
|
695
|
+
Ipv6SourceAddress
|
696
|
+
end
|
511
697
|
when Ipv6DestinationAddress::OXM_FIELD
|
512
698
|
masked? ? MaskedIpv6DestinationAddress : Ipv6DestinationAddress
|
699
|
+
when TunnelId::OXM_FIELD
|
700
|
+
masked? ? MaskedTunnelId : TunnelId
|
513
701
|
else
|
514
702
|
fail "Unknown OXM field value: #{oxm_field}"
|
515
703
|
end
|
@@ -519,6 +707,7 @@ module Pio
|
|
519
707
|
# rubocop:enable PerceivedComplexity
|
520
708
|
# rubocop:enable AbcSize
|
521
709
|
end
|
710
|
+
# rubocop:enable MethodLength
|
522
711
|
|
523
712
|
endian :big
|
524
713
|
|
@@ -571,8 +760,9 @@ module Pio
|
|
571
760
|
|
572
761
|
[:in_port, :ether_type, :ip_protocol, :vlan_vid, :vlan_pcp,
|
573
762
|
:ip_dscp, :ip_ecn, :tcp_source_port, :tcp_destination_port,
|
574
|
-
:udp_source_port, :udp_destination_port,
|
575
|
-
:
|
763
|
+
:udp_source_port, :udp_destination_port,
|
764
|
+
:sctp_source_port, :sctp_destination_port,
|
765
|
+
:icmpv4_type, :icmpv4_code, :arp_op].each do |each|
|
576
766
|
next unless user_attrs.key?(each)
|
577
767
|
klass = Match.const_get(each.to_s.split('_').map(&:capitalize).join)
|
578
768
|
@match_fields << { oxm_field: klass.const_get(:OXM_FIELD),
|
@@ -581,7 +771,10 @@ module Pio
|
|
581
771
|
|
582
772
|
[:metadata, :ether_destination_address, :ether_source_address,
|
583
773
|
:ipv4_source_address, :ipv4_destination_address,
|
584
|
-
:
|
774
|
+
:arp_sender_protocol_address, :arp_target_protocol_address,
|
775
|
+
:arp_sender_hardware_address, :arp_target_hardware_address,
|
776
|
+
:ipv6_source_address, :ipv6_destination_address,
|
777
|
+
:tunnel_id].each do |each|
|
585
778
|
next unless user_attrs.key?(each)
|
586
779
|
klass = Match.const_get(each.to_s.split('_').map(&:capitalize).join)
|
587
780
|
mask_key = "#{each}_mask".to_sym
|
@@ -0,0 +1,90 @@
|
|
1
|
+
require 'bindata'
|
2
|
+
require 'pio/open_flow13/actions'
|
3
|
+
require 'pio/open_flow13/buffer_id'
|
4
|
+
|
5
|
+
# Base module.
|
6
|
+
module Pio
|
7
|
+
remove_const :PacketOut
|
8
|
+
|
9
|
+
# OpenFlow 1.3 PacketOut message parser and generator
|
10
|
+
class PacketOut
|
11
|
+
# Packet's input port or :controller
|
12
|
+
class InPort < BinData::Primitive
|
13
|
+
CONTROLLER = 0xfffffffd
|
14
|
+
|
15
|
+
endian :big
|
16
|
+
uint32 :in_port
|
17
|
+
|
18
|
+
def get
|
19
|
+
(in_port == CONTROLLER) ? :controller : in_port
|
20
|
+
end
|
21
|
+
|
22
|
+
def set(value)
|
23
|
+
self.in_port = (value == :controller ? NO_CONTROLLER : value)
|
24
|
+
end
|
25
|
+
end
|
26
|
+
|
27
|
+
# OpenFlow 1.3 PacketOut message body
|
28
|
+
class Body < BinData::Record
|
29
|
+
endian :big
|
30
|
+
|
31
|
+
buffer_id :buffer_id
|
32
|
+
in_port :in_port
|
33
|
+
uint16 :actions_length, initial_value: -> { actions.binary.length }
|
34
|
+
string :padding, length: 6
|
35
|
+
actions :actions, length: :actions_length
|
36
|
+
string :raw_data, read_length: -> { message_length - 24 - actions_length }
|
37
|
+
|
38
|
+
def length
|
39
|
+
10 + padding.length + actions_length + raw_data.length
|
40
|
+
end
|
41
|
+
|
42
|
+
def data
|
43
|
+
@data ||= Pio::Parser.read(raw_data)
|
44
|
+
end
|
45
|
+
|
46
|
+
def method_missing(method, *args)
|
47
|
+
data.__send__(method, *args).snapshot
|
48
|
+
end
|
49
|
+
end
|
50
|
+
|
51
|
+
# OpenFlow 1.3 PacketOut message body
|
52
|
+
class Format < BinData::Record
|
53
|
+
extend Forwardable
|
54
|
+
|
55
|
+
endian :big
|
56
|
+
|
57
|
+
open_flow_header :open_flow_header,
|
58
|
+
ofp_version_value: 4, message_type_value: 13
|
59
|
+
body :body
|
60
|
+
|
61
|
+
def_delegators :open_flow_header, :ofp_version
|
62
|
+
def_delegators :open_flow_header, :message_type
|
63
|
+
def_delegators :open_flow_header, :message_length
|
64
|
+
def_delegators :open_flow_header, :transaction_id
|
65
|
+
def_delegator :open_flow_header, :transaction_id, :xid
|
66
|
+
|
67
|
+
def method_missing(method, *args, &block)
|
68
|
+
body.__send__ method, *args, &block
|
69
|
+
end
|
70
|
+
end
|
71
|
+
|
72
|
+
def self.read(raw_data)
|
73
|
+
allocate.tap do |message|
|
74
|
+
message.instance_variable_set(:@format, Format.read(raw_data))
|
75
|
+
end
|
76
|
+
end
|
77
|
+
|
78
|
+
def initialize(user_attrs = {})
|
79
|
+
header_attrs = OpenFlowHeader::Options.parse(user_attrs)
|
80
|
+
body_attrs = { actions: user_attrs[:actions],
|
81
|
+
raw_data: user_attrs[:raw_data] }
|
82
|
+
@format = Format.new(open_flow_header: header_attrs,
|
83
|
+
body: body_attrs)
|
84
|
+
end
|
85
|
+
|
86
|
+
def method_missing(method, *args, &block)
|
87
|
+
@format.__send__ method, *args, &block
|
88
|
+
end
|
89
|
+
end
|
90
|
+
end
|