pio 0.1.1 → 0.2.1
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/.rspec +2 -0
- data/Gemfile +3 -2
- data/Guardfile +4 -1
- data/README.md +44 -6
- data/Rakefile +5 -23
- data/lib/pio.rb +15 -0
- data/lib/pio/arp.rb +31 -0
- data/lib/pio/arp/frame.rb +38 -0
- data/lib/pio/arp/message.rb +66 -0
- data/lib/pio/arp/reply.rb +55 -0
- data/lib/pio/arp/request.rb +55 -0
- data/lib/pio/ip.rb +90 -0
- data/lib/pio/lldp.rb +74 -12
- data/lib/pio/lldp/frame.rb +53 -4
- data/lib/pio/lldp/management-address-value.rb +7 -1
- data/lib/pio/lldp/optional-tlv.rb +3 -1
- data/lib/pio/lldp/organizationally-specific-value.rb +23 -0
- data/lib/pio/mac.rb +156 -0
- data/lib/pio/type/ethernet-header.rb +16 -0
- data/lib/pio/type/ip-address.rb +28 -0
- data/lib/pio/{lldp → type}/mac-address.rb +4 -3
- data/lib/pio/version.rb +1 -19
- data/pio.org +518 -0
- data/pio.org_archive +389 -0
- data/spec/pio/arp/reply_spec.rb +150 -0
- data/spec/pio/arp/request_spec.rb +131 -0
- data/spec/pio/arp_spec.rb +136 -0
- data/spec/pio/ip_spec.rb +38 -0
- data/spec/pio/lldp_spec.rb +195 -38
- data/spec/pio/mac_spec.rb +82 -0
- data/spec/spec_helper.rb +9 -0
- metadata +27 -17
- data/spec/pio/lldp/chassis-id-tlv_spec.rb +0 -27
- data/spec/pio/lldp/end-of-lldpdu-value_spec.rb +0 -20
- data/spec/pio/lldp/frame_spec.rb +0 -82
- data/spec/pio/lldp/mac-address_spec.rb +0 -20
- data/spec/pio/lldp/optional-tlv_spec.rb +0 -81
- data/spec/pio/lldp/port-id-tlv_spec.rb +0 -27
- data/spec/pio/lldp/ttl-tlv_spec.rb +0 -26
@@ -0,0 +1,131 @@
|
|
1
|
+
require File.join( File.dirname( __FILE__ ), "..", "..", "spec_helper" )
|
2
|
+
require "pio/arp/request"
|
3
|
+
|
4
|
+
|
5
|
+
module Pio
|
6
|
+
class Arp
|
7
|
+
describe Request do
|
8
|
+
context ".new" do
|
9
|
+
subject {
|
10
|
+
Arp::Request.new(
|
11
|
+
:source_mac => source_mac,
|
12
|
+
:sender_protocol_address => sender_protocol_address,
|
13
|
+
:target_protocol_address => target_protocol_address
|
14
|
+
)
|
15
|
+
}
|
16
|
+
|
17
|
+
let( :arp_request_dump ) {
|
18
|
+
[
|
19
|
+
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, # destination mac address
|
20
|
+
0x00, 0x26, 0x82, 0xeb, 0xea, 0xd1, # source mac address
|
21
|
+
0x08, 0x06, # ethernet type
|
22
|
+
0x00, 0x01, # arp hardware type
|
23
|
+
0x08, 0x00, # arp protocol type
|
24
|
+
0x06, # hardware address size
|
25
|
+
0x04, # protocol address size
|
26
|
+
0x00, 0x01, # operational code
|
27
|
+
0x00, 0x26, 0x82, 0xeb, 0xea, 0xd1, # sender hardware address
|
28
|
+
0xc0, 0xa8, 0x53, 0x03, # sender protocol address
|
29
|
+
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, # target hardware address
|
30
|
+
0xc0, 0xa8, 0x53, 0xfe, # target protocol address
|
31
|
+
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, # padding
|
32
|
+
0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
33
|
+
0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
34
|
+
0x00, 0x00, 0x00, 0x00,
|
35
|
+
].pack( "C*" )
|
36
|
+
}
|
37
|
+
|
38
|
+
|
39
|
+
context "with Integer MAC and IP address" do
|
40
|
+
let( :source_mac ) { 0x002682ebead1 }
|
41
|
+
let( :sender_protocol_address ) { 0xc0a85303 }
|
42
|
+
let( :target_protocol_address ) { 0xc0a853fe }
|
43
|
+
|
44
|
+
context "#to_binary" do
|
45
|
+
it "returns an Arp Request binary String" do
|
46
|
+
expect( subject.to_binary ).to eq arp_request_dump
|
47
|
+
end
|
48
|
+
|
49
|
+
it "returns a valid ether frame with size = 64" do
|
50
|
+
expect( subject.to_binary.size ).to eq 64
|
51
|
+
end
|
52
|
+
end
|
53
|
+
end
|
54
|
+
|
55
|
+
|
56
|
+
context "with String MAC and IP address" do
|
57
|
+
let( :source_mac ) { "00:26:82:eb:ea:d1" }
|
58
|
+
let( :sender_protocol_address ) { 0xc0a85303 }
|
59
|
+
let( :target_protocol_address ) { 0xc0a853fe }
|
60
|
+
|
61
|
+
context "#to_binary" do
|
62
|
+
it "returns an Arp Request binary String" do
|
63
|
+
expect( subject.to_binary ).to eq arp_request_dump
|
64
|
+
end
|
65
|
+
|
66
|
+
it "returns a valid ether frame with size = 64" do
|
67
|
+
expect( subject.to_binary.size ).to eq 64
|
68
|
+
end
|
69
|
+
end
|
70
|
+
end
|
71
|
+
|
72
|
+
|
73
|
+
context "with Integer MAC and String IP address" do
|
74
|
+
let( :source_mac ) { 0x002682ebead1 }
|
75
|
+
let( :sender_protocol_address ) { "192.168.83.3" }
|
76
|
+
let( :target_protocol_address ) { "192.168.83.254" }
|
77
|
+
|
78
|
+
context "#to_binary" do
|
79
|
+
it "returns an Arp Request binary String" do
|
80
|
+
expect( subject.to_binary ).to eq arp_request_dump
|
81
|
+
end
|
82
|
+
|
83
|
+
it "returns a valid ether frame with size = 64" do
|
84
|
+
expect( subject.to_binary.size ).to eq 64
|
85
|
+
end
|
86
|
+
end
|
87
|
+
end
|
88
|
+
|
89
|
+
|
90
|
+
context "when :source_mac is not set" do
|
91
|
+
let( :source_mac ) { nil }
|
92
|
+
let( :sender_protocol_address ) { "192.168.83.3" }
|
93
|
+
let( :target_protocol_address ) { "192.168.83.254" }
|
94
|
+
|
95
|
+
it "raises an invalid MAC address error" do
|
96
|
+
expect { subject }.to raise_error( "Invalid MAC address: nil" )
|
97
|
+
end
|
98
|
+
end
|
99
|
+
|
100
|
+
|
101
|
+
context "when :sender_protocol_address is not set" do
|
102
|
+
let( :source_mac ) { 0x002682ebead1 }
|
103
|
+
let( :sender_protocol_address ) { nil }
|
104
|
+
let( :target_protocol_address ) { "192.168.83.254" }
|
105
|
+
|
106
|
+
it "raises an invalid IP address error" do
|
107
|
+
expect { subject }.to raise_error( "Invalid IP address: nil" )
|
108
|
+
end
|
109
|
+
end
|
110
|
+
|
111
|
+
|
112
|
+
context "when :target_protocol_address is not set" do
|
113
|
+
let( :source_mac ) { 0x002682ebead1 }
|
114
|
+
let( :sender_protocol_address ) { "192.168.83.254" }
|
115
|
+
let( :target_protocol_address ) { nil }
|
116
|
+
|
117
|
+
it "raises an invalid IP address error" do
|
118
|
+
expect { subject }.to raise_error( "Invalid IP address: nil" )
|
119
|
+
end
|
120
|
+
end
|
121
|
+
end
|
122
|
+
end
|
123
|
+
end
|
124
|
+
end
|
125
|
+
|
126
|
+
|
127
|
+
### Local variables:
|
128
|
+
### mode: Ruby
|
129
|
+
### coding: utf-8-unix
|
130
|
+
### indent-tabs-mode: nil
|
131
|
+
### End:
|
@@ -0,0 +1,136 @@
|
|
1
|
+
require File.join( File.dirname( __FILE__ ), "..", "spec_helper" )
|
2
|
+
require "pio"
|
3
|
+
|
4
|
+
|
5
|
+
module Pio
|
6
|
+
describe Arp do
|
7
|
+
context ".read" do
|
8
|
+
subject { Arp.read( data.pack( "C*" ) ) }
|
9
|
+
|
10
|
+
context "with an ARP Request packet" do
|
11
|
+
let( :data ) {
|
12
|
+
[
|
13
|
+
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, # destination mac address
|
14
|
+
0x00, 0x26, 0x82, 0xeb, 0xea, 0xd1, # source mac address
|
15
|
+
0x08, 0x06, # ethernet type
|
16
|
+
0x00, 0x01, # arp hardware type
|
17
|
+
0x08, 0x00, # arp protocol type
|
18
|
+
0x06, # hardware address size
|
19
|
+
0x04, # protocol address size
|
20
|
+
0x00, 0x01, # operational code
|
21
|
+
0x00, 0x26, 0x82, 0xeb, 0xea, 0xd1, # sender hardware address
|
22
|
+
0xc0, 0xa8, 0x53, 0x03, # sender protocol address
|
23
|
+
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, # target hardware address
|
24
|
+
0xc0, 0xa8, 0x53, 0xfe, # target protocol address
|
25
|
+
]
|
26
|
+
}
|
27
|
+
|
28
|
+
its( :class ) { should be Arp::Request }
|
29
|
+
its( "destination_mac.to_s" ) { should eq "ff:ff:ff:ff:ff:ff" }
|
30
|
+
its( "source_mac.to_s" ) { should eq "00:26:82:eb:ea:d1" }
|
31
|
+
its( :ether_type ) { should eq 0x0806 }
|
32
|
+
its( :hardware_type ) { should eq 1 }
|
33
|
+
its( :protocol_type ) { should eq 0x800 }
|
34
|
+
its( :hardware_length ) { should eq 6 }
|
35
|
+
its( :protocol_length ) { should eq 4 }
|
36
|
+
its( :operation ) { should eq 1 }
|
37
|
+
its( "sender_hardware_address.to_s" ) { should eq "00:26:82:eb:ea:d1" }
|
38
|
+
its( "sender_protocol_address.to_s" ) { should eq "192.168.83.3" }
|
39
|
+
its( "target_hardware_address.to_s" ) { should eq "00:00:00:00:00:00" }
|
40
|
+
its( "target_protocol_address.to_s" ) { should eq "192.168.83.254" }
|
41
|
+
end
|
42
|
+
|
43
|
+
|
44
|
+
context "with an ARP Reply packet" do
|
45
|
+
let( :data ) {
|
46
|
+
[
|
47
|
+
0x00, 0x26, 0x82, 0xeb, 0xea, 0xd1, # destination mac address
|
48
|
+
0x00, 0x16, 0x9d, 0x1d, 0x9c, 0xc4, # source mac address
|
49
|
+
0x08, 0x06, # ethernet type
|
50
|
+
0x00, 0x01, # arp hardware type
|
51
|
+
0x08, 0x00, # arp protocol type
|
52
|
+
0x06, # hardware address size
|
53
|
+
0x04, # protocol address size
|
54
|
+
0x00, 0x02, # operational code
|
55
|
+
0x00, 0x16, 0x9d, 0x1d, 0x9c, 0xc4, # sender hardware address
|
56
|
+
0xc0, 0xa8, 0x53, 0xfe, # sender protocol address
|
57
|
+
0x00, 0x26, 0x82, 0xeb, 0xea, 0xd1, # target hardware address
|
58
|
+
0xc0, 0xa8, 0x53, 0x03, # target protocol address
|
59
|
+
]
|
60
|
+
}
|
61
|
+
|
62
|
+
its( :class ) { should be Arp::Reply }
|
63
|
+
its( "destination_mac.to_s" ) { should eq "00:26:82:eb:ea:d1" }
|
64
|
+
its( "source_mac.to_s" ) { should eq "00:16:9d:1d:9c:c4" }
|
65
|
+
its( :ether_type ) { should eq 0x0806 }
|
66
|
+
its( :hardware_type ) { should eq 1 }
|
67
|
+
its( :protocol_type ) { should eq 0x800 }
|
68
|
+
its( :hardware_length ) { should eq 6 }
|
69
|
+
its( :protocol_length ) { should eq 4 }
|
70
|
+
its( :operation ) { should eq 2 }
|
71
|
+
its( "sender_hardware_address.to_s" ) { should eq "00:16:9d:1d:9c:c4" }
|
72
|
+
its( "sender_protocol_address.to_s" ) { should eq "192.168.83.254" }
|
73
|
+
its( "target_hardware_address.to_s" ) { should eq "00:26:82:eb:ea:d1" }
|
74
|
+
its( "target_protocol_address.to_s" ) { should eq "192.168.83.3" }
|
75
|
+
end
|
76
|
+
|
77
|
+
|
78
|
+
context "with an ARP Request captured in real environment" do
|
79
|
+
let( :data ) {
|
80
|
+
[
|
81
|
+
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x5c, 0x9a, 0xd8, 0xea,
|
82
|
+
0x37, 0x32, 0x08, 0x06, 0x00, 0x01, 0x08, 0x00, 0x06, 0x04,
|
83
|
+
0x00, 0x01, 0x5c, 0x9a, 0xd8, 0xea, 0x37, 0x32, 0xc0, 0xa8,
|
84
|
+
0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xc0, 0xa8,
|
85
|
+
0x00, 0xfe
|
86
|
+
]
|
87
|
+
it { expect { subject }.not_to raise_error }
|
88
|
+
}
|
89
|
+
end
|
90
|
+
|
91
|
+
|
92
|
+
context "with an ARP Request from a real OpenFlow switch" do
|
93
|
+
let( :data ) {
|
94
|
+
[
|
95
|
+
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x11, 0x22, 0x33, 0x44,
|
96
|
+
0x55, 0x66, 0x08, 0x06, 0x00, 0x01, 0x08, 0x00, 0x06, 0x04,
|
97
|
+
0x00, 0x01, 0x11, 0x22, 0x33, 0x44, 0x55, 0x66, 0xc0, 0xa8,
|
98
|
+
0x00, 0xfe, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xc0, 0xa8,
|
99
|
+
0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
100
|
+
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
101
|
+
0x00, 0x00, 0x00, 0x00
|
102
|
+
]
|
103
|
+
it { expect { subject }.not_to raise_error }
|
104
|
+
}
|
105
|
+
end
|
106
|
+
|
107
|
+
|
108
|
+
context "with an ARP Reply captured in real environment" do
|
109
|
+
let( :data ) {
|
110
|
+
[
|
111
|
+
0x11, 0x22, 0x33, 0x44, 0x55, 0x66, 0x5c, 0x9a, 0xd8, 0xea,
|
112
|
+
0x37, 0x32, 0x08, 0x06, 0x00, 0x01, 0x08, 0x00, 0x06, 0x04,
|
113
|
+
0x00, 0x02, 0x5c, 0x9a, 0xd8, 0xea, 0x37, 0x32, 0xc0, 0xa8,
|
114
|
+
0x00, 0x01, 0x11, 0x22, 0x33, 0x44, 0x55, 0x66, 0xc0, 0xa8,
|
115
|
+
0x00, 0xfe
|
116
|
+
]
|
117
|
+
it { expect { subject }.not_to raise_error }
|
118
|
+
}
|
119
|
+
end
|
120
|
+
|
121
|
+
|
122
|
+
context "with an invalid ARP packet" do
|
123
|
+
let( :data ) { [] }
|
124
|
+
|
125
|
+
it { expect { subject }.to raise_error( Pio::ParseError ) }
|
126
|
+
end
|
127
|
+
end
|
128
|
+
end
|
129
|
+
end
|
130
|
+
|
131
|
+
|
132
|
+
### Local variables:
|
133
|
+
### mode: Ruby
|
134
|
+
### coding: utf-8-unix
|
135
|
+
### indent-tabs-mode: nil
|
136
|
+
### End:
|
data/spec/pio/ip_spec.rb
ADDED
@@ -0,0 +1,38 @@
|
|
1
|
+
require File.join( File.dirname( __FILE__ ), "..", "spec_helper" )
|
2
|
+
require "pio/ip"
|
3
|
+
|
4
|
+
|
5
|
+
module Pio
|
6
|
+
describe IP do
|
7
|
+
context ".new" do
|
8
|
+
subject { IP.new( ip_address, prefixlen ) }
|
9
|
+
|
10
|
+
|
11
|
+
context %{with "192.168.1.1", 32} do
|
12
|
+
let( :ip_address ) { "192.168.1.1" }
|
13
|
+
let( :prefixlen ) { 32 }
|
14
|
+
|
15
|
+
its( :to_s ) { should eq "192.168.1.1" }
|
16
|
+
its( :to_i ) { should eq 3232235777 }
|
17
|
+
its( :to_a ) { should eq [ 0xc0, 0xa8, 0x01, 0x01 ] }
|
18
|
+
end
|
19
|
+
|
20
|
+
|
21
|
+
context %{with "10.1.1.1", 8} do
|
22
|
+
let( :ip_address ) { "10.1.1.1" }
|
23
|
+
let( :prefixlen ) { 8 }
|
24
|
+
|
25
|
+
its( :to_s ) { should eq "10.0.0.0" }
|
26
|
+
its( :to_i ) { should eq 10 * 256 * 256 * 256 }
|
27
|
+
its( :to_a ) { should eq [ 0x0a, 0x00, 0x00, 0x00 ] }
|
28
|
+
end
|
29
|
+
end
|
30
|
+
end
|
31
|
+
end
|
32
|
+
|
33
|
+
|
34
|
+
### Local variables:
|
35
|
+
### mode: Ruby
|
36
|
+
### coding: utf-8-unix
|
37
|
+
### indent-tabs-mode: nil
|
38
|
+
### End:
|
data/spec/pio/lldp_spec.rb
CHANGED
@@ -1,55 +1,212 @@
|
|
1
1
|
require File.join( File.dirname( __FILE__ ), "..", "spec_helper" )
|
2
|
-
require "pio
|
2
|
+
require "pio"
|
3
3
|
|
4
4
|
|
5
5
|
module Pio
|
6
6
|
describe Lldp do
|
7
|
-
|
8
|
-
|
9
|
-
|
10
|
-
|
11
|
-
|
12
|
-
|
13
|
-
|
14
|
-
|
15
|
-
0x02, 0x07, 0x04, 0x00, 0x19, 0x2f, 0xa7, 0xb2, 0x8d, # Chassis ID TLV
|
16
|
-
0x04, 0x0d, 0x01, 0x55, 0x70, 0x6c, 0x69, 0x6e, 0x6b, 0x20, 0x74, 0x6f, 0x20, 0x53, 0x31, # Port ID TLV
|
17
|
-
0x06, 0x02, 0x00, 0x78, # Time to live TLV
|
18
|
-
0x00, 0x00 # End of LLDPDU TLV
|
19
|
-
]
|
7
|
+
context ".new" do
|
8
|
+
subject {
|
9
|
+
Lldp.new(
|
10
|
+
:dpid => dpid,
|
11
|
+
:port_number => port_number,
|
12
|
+
:source_mac => source_mac,
|
13
|
+
:destination_mac => destination_mac
|
14
|
+
)
|
20
15
|
}
|
21
16
|
|
22
|
-
its( :dpid ) { should eq 108173701773 }
|
23
17
|
|
24
|
-
|
25
|
-
|
18
|
+
context "with :dpid and :port_number" do
|
19
|
+
let( :dpid ) { 108173701773 }
|
20
|
+
let( :port_number ) { 1 }
|
21
|
+
let( :source_mac ) { nil }
|
22
|
+
let( :destination_mac ) { nil }
|
23
|
+
let( :lldp_dump ) {
|
24
|
+
[
|
25
|
+
0x01, 0x80, 0xc2, 0x00, 0x00, 0x0e, # Destination MAC
|
26
|
+
0x01, 0x02, 0x03, 0x04, 0x05, 0x06, # Source MAC
|
27
|
+
0x88, 0xcc, # Ethertype
|
28
|
+
0x02, 0x09, 0x07, 0x00, 0x00, 0x00, 0x19, 0x2f, 0xa7, 0xb2, 0x8d, # Chassis ID TLV
|
29
|
+
0x04, 0x05, 0x07, 0x00, 0x00, 0x00, 0x01, # Port ID TLV
|
30
|
+
0x06, 0x02, 0x00, 0x78, # Time to live TLV
|
31
|
+
0x00, 0x00, # End of LLDPDU TLV
|
32
|
+
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, # Padding
|
33
|
+
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
34
|
+
0x00, 0x00
|
35
|
+
]
|
36
|
+
}
|
37
|
+
|
38
|
+
context "#to_binary" do
|
39
|
+
it "returns an LLDP binary string" do
|
40
|
+
expect( subject.to_binary.unpack( "C*" ) ).to eq lldp_dump
|
41
|
+
end
|
42
|
+
|
43
|
+
it "returns a valid ether frame with size = 64" do
|
44
|
+
expect( subject.to_binary.size ).to eq 64
|
45
|
+
end
|
46
|
+
end
|
47
|
+
end
|
48
|
+
|
49
|
+
|
50
|
+
context "with :dpid, :port_number and :source_mac" do
|
51
|
+
let( :dpid ) { 108173701773 }
|
52
|
+
let( :port_number ) { 1 }
|
53
|
+
let( :source_mac ) { "06:05:04:03:02:01" }
|
54
|
+
let( :destination_mac ) { nil }
|
55
|
+
let( :lldp_dump ) {
|
56
|
+
[
|
57
|
+
0x01, 0x80, 0xc2, 0x00, 0x00, 0x0e, # Destination MAC
|
58
|
+
0x06, 0x05, 0x04, 0x03, 0x02, 0x01, # Source MAC
|
59
|
+
0x88, 0xcc, # Ethertype
|
60
|
+
0x02, 0x09, 0x07, 0x00, 0x00, 0x00, 0x19, 0x2f, 0xa7, 0xb2, 0x8d, # Chassis ID TLV
|
61
|
+
0x04, 0x05, 0x07, 0x00, 0x00, 0x00, 0x01, # Port ID TLV
|
62
|
+
0x06, 0x02, 0x00, 0x78, # Time to live TLV
|
63
|
+
0x00, 0x00, # End of LLDPDU TLV
|
64
|
+
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, # Padding
|
65
|
+
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
66
|
+
0x00, 0x00
|
67
|
+
]
|
68
|
+
}
|
69
|
+
|
70
|
+
context "#to_binary" do
|
71
|
+
it "returns an LLDP binary string" do
|
72
|
+
expect( subject.to_binary.unpack( "C*" ) ).to eq lldp_dump
|
73
|
+
end
|
74
|
+
|
75
|
+
it "returns a valid ether frame with size = 64" do
|
76
|
+
expect( subject.to_binary.size ).to eq 64
|
77
|
+
end
|
78
|
+
end
|
79
|
+
end
|
80
|
+
|
81
|
+
|
82
|
+
context "with :dpid, :port_number, :source_mac and :destination_mac" do
|
83
|
+
let( :dpid ) { 108173701773 }
|
84
|
+
let( :port_number ) { 1 }
|
85
|
+
let( :source_mac ) { "06:05:04:03:02:01" }
|
86
|
+
let( :destination_mac ) { "01:02:03:04:05:06" }
|
87
|
+
let( :lldp_dump ) {
|
88
|
+
[
|
89
|
+
0x01, 0x02, 0x03, 0x04, 0x05, 0x06, # Destination MAC
|
90
|
+
0x06, 0x05, 0x04, 0x03, 0x02, 0x01, # Source MAC
|
91
|
+
0x88, 0xcc, # Ethertype
|
92
|
+
0x02, 0x09, 0x07, 0x00, 0x00, 0x00, 0x19, 0x2f, 0xa7, 0xb2, 0x8d, # Chassis ID TLV
|
93
|
+
0x04, 0x05, 0x07, 0x00, 0x00, 0x00, 0x01, # Port ID TLV
|
94
|
+
0x06, 0x02, 0x00, 0x78, # Time to live TLV
|
95
|
+
0x00, 0x00, # End of LLDPDU TLV
|
96
|
+
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, # Padding
|
97
|
+
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
98
|
+
0x00, 0x00
|
99
|
+
]
|
100
|
+
}
|
101
|
+
|
102
|
+
context "#to_binary" do
|
103
|
+
it "returns an LLDP binary string" do
|
104
|
+
expect( subject.to_binary.unpack( "C*" ) ).to eq lldp_dump
|
105
|
+
end
|
106
|
+
|
107
|
+
it "returns a valid ether frame with size = 64" do
|
108
|
+
expect( subject.to_binary.size ).to eq 64
|
109
|
+
end
|
110
|
+
end
|
111
|
+
end
|
112
|
+
|
113
|
+
|
114
|
+
context "when :dpid is not set" do
|
115
|
+
let( :dpid ) { nil }
|
116
|
+
let( :port_number ) { 1 }
|
117
|
+
let( :source_mac ) { nil }
|
118
|
+
let( :destination_mac ) { nil }
|
119
|
+
|
120
|
+
it { expect { subject }.to raise_error( "Invalid DPID: nil" ) }
|
121
|
+
end
|
122
|
+
|
123
|
+
|
124
|
+
context "when :port_number is not set" do
|
125
|
+
let( :dpid ) { 108173701773 }
|
126
|
+
let( :port_number ) { nil }
|
127
|
+
let( :source_mac ) { nil }
|
128
|
+
let( :destination_mac ) { nil }
|
129
|
+
|
130
|
+
it { expect { subject }.to raise_error( "Invalid port number: nil" ) }
|
26
131
|
end
|
27
132
|
end
|
28
133
|
|
29
134
|
|
30
|
-
context "
|
31
|
-
|
32
|
-
|
33
|
-
|
34
|
-
|
35
|
-
|
36
|
-
|
37
|
-
|
38
|
-
|
39
|
-
|
40
|
-
|
41
|
-
|
42
|
-
|
43
|
-
|
44
|
-
|
45
|
-
|
46
|
-
|
47
|
-
|
135
|
+
context ".read" do
|
136
|
+
subject { Lldp.read( data.pack( "C*" ) ) }
|
137
|
+
|
138
|
+
context "with a minimal LLDP frame" do
|
139
|
+
let( :data ) {
|
140
|
+
[
|
141
|
+
0x01, 0x80, 0xc2, 0x00, 0x00, 0x0e, # Destination MAC
|
142
|
+
0x00, 0x19, 0x2f, 0xa7, 0xb2, 0x8d, # Source MAC
|
143
|
+
0x88, 0xcc, # Ethertype
|
144
|
+
0x02, 0x07, 0x04, 0x00, 0x19, 0x2f, 0xa7, 0xb2, 0x8d, # Chassis ID TLV
|
145
|
+
0x04, 0x0d, 0x01, 0x55, 0x70, 0x6c, 0x69, 0x6e, 0x6b, 0x20, 0x74, 0x6f, 0x20, 0x53, 0x31, # Port ID TLV
|
146
|
+
0x06, 0x02, 0x00, 0x78, # Time to live TLV
|
147
|
+
0x00, 0x00 # End of LLDPDU TLV
|
148
|
+
]
|
149
|
+
}
|
150
|
+
|
151
|
+
its( "destination_mac.to_s" ) { should eq "01:80:c2:00:00:0e" }
|
152
|
+
its( "source_mac.to_s" ) { should eq "00:19:2f:a7:b2:8d" }
|
153
|
+
its( :ether_type ) { should eq 0x88cc }
|
154
|
+
its( :dpid ) { should eq 108173701773 }
|
155
|
+
its( :chassis_id ) { should eq 108173701773 }
|
156
|
+
its( :port_id ) { should eq "Uplink to S1" }
|
157
|
+
its( :port_number ) { should eq "Uplink to S1" }
|
158
|
+
its( :ttl ) { should eq 120 }
|
159
|
+
its( :port_description ) { should be_nil }
|
160
|
+
its( :system_name ) { should be_nil }
|
161
|
+
its( :system_description ) { should be_nil }
|
162
|
+
its( :system_capabilities ) { should be_nil }
|
163
|
+
its( :management_address ) { should be_nil }
|
164
|
+
end
|
165
|
+
|
166
|
+
|
167
|
+
context "with a detailed LLDP frame" do
|
168
|
+
let( :data ) {
|
169
|
+
[
|
170
|
+
0x01, 0x80, 0xc2, 0x00, 0x00, 0x0e, # Destination MAC
|
171
|
+
0x00, 0x19, 0x2f, 0xa7, 0xb2, 0x8d, # Source MAC
|
172
|
+
0x88, 0xcc, # Ethertype
|
173
|
+
0x02, 0x07, 0x04, 0x00, 0x19, 0x2f, 0xa7, 0xb2, 0x8d, # Chassis ID TLV
|
174
|
+
0x04, 0x0d, 0x01, 0x55, 0x70, 0x6c, 0x69, 0x6e, 0x6b, 0x20, 0x74, 0x6f, 0x20, 0x53, 0x31, # Port ID TLV
|
175
|
+
0x06, 0x02, 0x00, 0x78, # Time to live TLV
|
176
|
+
0x08, 0x17, 0x53, 0x75, 0x6d, 0x6d, 0x69, 0x74, 0x33, 0x30, 0x30, 0x2d, 0x34, 0x38, 0x2d, 0x50, 0x6f, 0x72, 0x74, 0x20, 0x31, 0x30, 0x30, 0x31, 0x00, # Port Description
|
177
|
+
0x0a, 0x0d, 0x53, 0x75, 0x6d, 0x6d, 0x69, 0x74, 0x33, 0x30, 0x30, 0x2d, 0x34, 0x38, 0x00, # System Name
|
178
|
+
0x0c, 0x4c, 0x53, 0x75, 0x6d, 0x6d, 0x69, 0x74, 0x33, 0x30, 0x30, 0x2d, 0x34, 0x38, 0x20, 0x2d, 0x20, 0x56, 0x65, 0x72, 0x73, 0x69, 0x6f, 0x6e, 0x20, 0x37, 0x2e, 0x34, 0x65, 0x2e, 0x31, 0x20, 0x28, 0x42, 0x75, 0x69, 0x6c, 0x64, 0x20, 0x35, 0x29, 0x20, 0x62, 0x79, 0x20, 0x52, 0x65, 0x6c, 0x65, 0x61, 0x73, 0x65, 0x5f, 0x4d, 0x61, 0x73, 0x74, 0x65, 0x72, 0x20, 0x30, 0x35, 0x2f, 0x32, 0x37, 0x2f, 0x30, 0x35, 0x20, 0x30, 0x34, 0x3a, 0x35, 0x33, 0x3a, 0x31, 0x31, 0x00, # System Description
|
179
|
+
0x0e, 0x04, 0x00, 0x14, 0x00, 0x14, # System Capabilities
|
180
|
+
0x10, 0x0e, 0x07, 0x06, 0x00, 0x01, 0x30, 0xf9, 0xad, 0xa0, 0x02, 0x00, 0x00, 0x03, 0xe9, 0x00, # Management Address
|
181
|
+
0xfe, 0x07, 0x00, 0x12, 0x0f, 0x02, 0x07, 0x01, 0x00, # Organizationally Specific
|
182
|
+
0x00, 0x00 # End of LLDPDU TLV
|
183
|
+
]
|
184
|
+
}
|
185
|
+
|
186
|
+
its( "destination_mac.to_s" ) { should eq "01:80:c2:00:00:0e" }
|
187
|
+
its( "source_mac.to_s" ) { should eq "00:19:2f:a7:b2:8d" }
|
188
|
+
its( :ether_type ) { should eq 0x88cc }
|
189
|
+
its( :dpid ) { should eq 108173701773 }
|
190
|
+
its( :chassis_id ) { should eq 108173701773 }
|
191
|
+
its( :port_id ) { should eq "Uplink to S1" }
|
192
|
+
its( :port_number ) { should eq "Uplink to S1" }
|
193
|
+
its( :ttl ) { should eq 120 }
|
194
|
+
its( :port_description ) { should eq "Summit300-48-Port 1001" }
|
195
|
+
its( :system_name ) { should eq "Summit300-48" }
|
196
|
+
its( :system_description ) { should eq "Summit300-48 - Version 7.4e.1 (Build 5) by Release_Master 05/27/05 04:53:11" }
|
197
|
+
its( "system_capabilities.system_capabilities" ) { should eq 20 }
|
198
|
+
its( "system_capabilities.enabled_capabilities" ) { should eq 20 }
|
199
|
+
its( :management_address ) { should eq [ 0x00, 0x01, 0x30, 0xf9, 0xad, 0xa0 ].pack( "C*" ) }
|
200
|
+
its( "organizationally_specific.oui" ) { should eq 4623 }
|
201
|
+
its( "organizationally_specific.subtype" ) { should eq 2 }
|
202
|
+
its( "organizationally_specific.information" ) { should eq "\a\x01" }
|
203
|
+
end
|
204
|
+
|
48
205
|
|
49
|
-
|
206
|
+
context "with an invalid Lldp frame" do
|
207
|
+
let( :data ) { [] }
|
50
208
|
|
51
|
-
|
52
|
-
lambda { subject }.should_not raise_error
|
209
|
+
it { expect { subject }.to raise_error( Pio::ParseError ) }
|
53
210
|
end
|
54
211
|
end
|
55
212
|
end
|