pio 0.1.0
Sign up to get free protection for your applications and to get access to all the features.
- data/.gitignore +19 -0
- data/Gemfile +32 -0
- data/Guardfile +16 -0
- data/LICENSE +674 -0
- data/README.md +4 -0
- data/Rakefile +89 -0
- data/lib/pio/lldp.rb +45 -0
- data/lib/pio/lldp/chassis-id-tlv.rb +57 -0
- data/lib/pio/lldp/end-of-lldpdu-value.rb +21 -0
- data/lib/pio/lldp/frame.rb +38 -0
- data/lib/pio/lldp/mac-address.rb +28 -0
- data/lib/pio/lldp/management-address-value.rb +21 -0
- data/lib/pio/lldp/optional-tlv.rb +73 -0
- data/lib/pio/lldp/port-description-value.rb +21 -0
- data/lib/pio/lldp/port-id-tlv.rb +44 -0
- data/lib/pio/lldp/system-capabilities-value.rb +22 -0
- data/lib/pio/lldp/system-description-value.rb +21 -0
- data/lib/pio/lldp/system-name-value.rb +21 -0
- data/lib/pio/lldp/ttl-tlv.rb +33 -0
- data/lib/pio/version.rb +30 -0
- data/pio.gemspec +31 -0
- data/spec/pio/lldp/chassis-id-tlv_spec.rb +27 -0
- data/spec/pio/lldp/end-of-lldpdu-value_spec.rb +20 -0
- data/spec/pio/lldp/frame_spec.rb +82 -0
- data/spec/pio/lldp/mac-address_spec.rb +20 -0
- data/spec/pio/lldp/optional-tlv_spec.rb +81 -0
- data/spec/pio/lldp/port-id-tlv_spec.rb +27 -0
- data/spec/pio/lldp/ttl-tlv_spec.rb +26 -0
- data/spec/pio/lldp_spec.rb +63 -0
- data/spec/spec_helper.rb +18 -0
- metadata +96 -0
data/README.md
ADDED
data/Rakefile
ADDED
@@ -0,0 +1,89 @@
|
|
1
|
+
#
|
2
|
+
# Copyright (C) 2013 NEC Corporation
|
3
|
+
#
|
4
|
+
# This program is free software; you can redistribute it and/or modify
|
5
|
+
# it under the terms of the GNU General Public License, version 3, as
|
6
|
+
# published by the Free Software Foundation.
|
7
|
+
#
|
8
|
+
# This program is distributed in the hope that it will be useful,
|
9
|
+
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
10
|
+
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
11
|
+
# GNU General Public License for more details.
|
12
|
+
#
|
13
|
+
# You should have received a copy of the GNU General Public License along
|
14
|
+
# with this program; if not, write to the Free Software Foundation, Inc.,
|
15
|
+
# 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
|
16
|
+
#
|
17
|
+
|
18
|
+
|
19
|
+
require "bundler/gem_tasks"
|
20
|
+
require "flay"
|
21
|
+
require "rake/tasklib"
|
22
|
+
require "flay_task"
|
23
|
+
require "flog"
|
24
|
+
require "reek/rake/task"
|
25
|
+
require "rspec/core"
|
26
|
+
require "rspec/core/rake_task"
|
27
|
+
require "yard"
|
28
|
+
|
29
|
+
|
30
|
+
$ruby_source = FileList[ "lib/**/*.rb" ]
|
31
|
+
|
32
|
+
|
33
|
+
task :quality => [ :reek, :flog, :flay ]
|
34
|
+
|
35
|
+
|
36
|
+
RSpec::Core::RakeTask.new do | task |
|
37
|
+
task.rspec_opts = "--format documentation --color"
|
38
|
+
end
|
39
|
+
|
40
|
+
|
41
|
+
Reek::Rake::Task.new do | t |
|
42
|
+
t.fail_on_error = true
|
43
|
+
t.verbose = false
|
44
|
+
t.ruby_opts = [ "-rubygems" ]
|
45
|
+
t.reek_opts = "--quiet"
|
46
|
+
t.source_files = $ruby_source
|
47
|
+
end
|
48
|
+
|
49
|
+
|
50
|
+
desc "Analyze for code complexity"
|
51
|
+
task :flog do
|
52
|
+
flog = Flog.new( :continue => true )
|
53
|
+
flog.flog( *$ruby_source )
|
54
|
+
threshold = 10
|
55
|
+
|
56
|
+
bad_methods = flog.totals.select do | name, score |
|
57
|
+
( not ( /##{flog.no_method}$/=~ name ) ) and score > threshold
|
58
|
+
end
|
59
|
+
bad_methods.sort do | a, b |
|
60
|
+
a[ 1 ] <=> b[ 1 ]
|
61
|
+
end.reverse.each do | name, score |
|
62
|
+
puts "%8.1f: %s" % [ score, name ]
|
63
|
+
end
|
64
|
+
unless bad_methods.empty?
|
65
|
+
raise "#{ bad_methods.size } methods have a flog complexity > #{ threshold }"
|
66
|
+
end
|
67
|
+
end
|
68
|
+
|
69
|
+
|
70
|
+
FlayTask.new do | t |
|
71
|
+
t.dirs = $ruby_source.collect do | each |
|
72
|
+
each[ /[^\/]+/ ]
|
73
|
+
end.uniq
|
74
|
+
t.threshold = 0
|
75
|
+
t.verbose = $trace
|
76
|
+
end
|
77
|
+
|
78
|
+
|
79
|
+
YARD::Rake::YardocTask.new do | t |
|
80
|
+
t.options = [ "--no-private" ]
|
81
|
+
t.options << "--debug" << "--verbose" if $trace
|
82
|
+
end
|
83
|
+
|
84
|
+
|
85
|
+
### Local variables:
|
86
|
+
### mode: Ruby
|
87
|
+
### coding: utf-8-unix
|
88
|
+
### indent-tabs-mode: nil
|
89
|
+
### End:
|
data/lib/pio/lldp.rb
ADDED
@@ -0,0 +1,45 @@
|
|
1
|
+
require "rubygems"
|
2
|
+
|
3
|
+
require "bindata"
|
4
|
+
require "forwardable"
|
5
|
+
require "pio/lldp/frame"
|
6
|
+
|
7
|
+
|
8
|
+
module Pio
|
9
|
+
# LLDP frame parser and generator.
|
10
|
+
class Lldp
|
11
|
+
extend Forwardable
|
12
|
+
|
13
|
+
|
14
|
+
def self.read raw_data
|
15
|
+
frame = Frame.read( raw_data )
|
16
|
+
new frame.dpid, frame.port_id
|
17
|
+
end
|
18
|
+
|
19
|
+
|
20
|
+
def initialize dpid, port_number, destination_mac = "01:80:c2:00:00:0e"
|
21
|
+
@frame = Frame.new
|
22
|
+
@frame.destination_mac = destination_mac
|
23
|
+
@frame.source_mac = "11:22:33:44:55:66" # FIXME
|
24
|
+
@frame.chassis_id = dpid
|
25
|
+
@frame.port_id = port_number
|
26
|
+
end
|
27
|
+
|
28
|
+
|
29
|
+
def_delegator :@frame, :dpid
|
30
|
+
def_delegator :@frame, :optional_tlv
|
31
|
+
def_delegator :@frame, :port_id, :port_number
|
32
|
+
|
33
|
+
|
34
|
+
def to_binary
|
35
|
+
@frame.to_binary_s + "\000" * ( 64 - @frame.num_bytes )
|
36
|
+
end
|
37
|
+
end
|
38
|
+
end
|
39
|
+
|
40
|
+
|
41
|
+
### Local variables:
|
42
|
+
### mode: Ruby
|
43
|
+
### coding: utf-8-unix
|
44
|
+
### indent-tabs-mode: nil
|
45
|
+
### End:
|
@@ -0,0 +1,57 @@
|
|
1
|
+
require "rubygems"
|
2
|
+
require "bindata"
|
3
|
+
|
4
|
+
|
5
|
+
module Pio
|
6
|
+
class Lldp
|
7
|
+
# Chassis ID TLV
|
8
|
+
class ChassisIdTlv < BinData::Primitive
|
9
|
+
endian :big
|
10
|
+
|
11
|
+
bit7 :tlv_type, :value => 1
|
12
|
+
bit9 :tlv_info_length, :value => lambda { subtype.num_bytes + chassis_id.length }
|
13
|
+
uint8 :subtype, :initial_value => 7
|
14
|
+
string :chassis_id, :read_length => lambda { tlv_info_length - subtype.num_bytes }
|
15
|
+
|
16
|
+
|
17
|
+
def get
|
18
|
+
tmp_chassis_id = chassis_id
|
19
|
+
|
20
|
+
case subtype
|
21
|
+
when 4
|
22
|
+
mac_address
|
23
|
+
when 7
|
24
|
+
BinData::Uint64be.read tmp_chassis_id
|
25
|
+
else
|
26
|
+
tmp_chassis_id
|
27
|
+
end
|
28
|
+
end
|
29
|
+
|
30
|
+
|
31
|
+
def set value
|
32
|
+
self.chassis_id = if value.kind_of?( Fixnum ) and subtype == 7
|
33
|
+
BinData::Uint64be.new( value ).to_binary_s
|
34
|
+
else
|
35
|
+
value
|
36
|
+
end
|
37
|
+
end
|
38
|
+
|
39
|
+
|
40
|
+
##########################################################################
|
41
|
+
private
|
42
|
+
##########################################################################
|
43
|
+
|
44
|
+
|
45
|
+
def mac_address
|
46
|
+
chassis_id.unpack( "C6" ).collect { | each | "%02x" % each }.join( "" ).hex
|
47
|
+
end
|
48
|
+
end
|
49
|
+
end
|
50
|
+
end
|
51
|
+
|
52
|
+
|
53
|
+
### Local variables:
|
54
|
+
### mode: Ruby
|
55
|
+
### coding: utf-8-unix
|
56
|
+
### indent-tabs-mode: nil
|
57
|
+
### End:
|
@@ -0,0 +1,21 @@
|
|
1
|
+
require "rubygems"
|
2
|
+
require "bindata"
|
3
|
+
|
4
|
+
|
5
|
+
module Pio
|
6
|
+
class Lldp
|
7
|
+
# End Of LLDPDU
|
8
|
+
class EndOfLldpduValue < BinData::Record
|
9
|
+
endian :big
|
10
|
+
|
11
|
+
stringz :tlv_info_string, :length => 0, :value => ""
|
12
|
+
end
|
13
|
+
end
|
14
|
+
end
|
15
|
+
|
16
|
+
|
17
|
+
### Local variables:
|
18
|
+
### mode: Ruby
|
19
|
+
### coding: utf-8-unix
|
20
|
+
### indent-tabs-mode: nil
|
21
|
+
### End:
|
@@ -0,0 +1,38 @@
|
|
1
|
+
require "rubygems"
|
2
|
+
require "bindata"
|
3
|
+
|
4
|
+
require "pio/lldp/chassis-id-tlv"
|
5
|
+
require "pio/lldp/mac-address"
|
6
|
+
require "pio/lldp/optional-tlv"
|
7
|
+
require "pio/lldp/port-id-tlv"
|
8
|
+
require "pio/lldp/ttl-tlv"
|
9
|
+
|
10
|
+
|
11
|
+
module Pio
|
12
|
+
class Lldp
|
13
|
+
# LLDP frame
|
14
|
+
class Frame < BinData::Record
|
15
|
+
endian :big
|
16
|
+
|
17
|
+
mac_address :destination_mac
|
18
|
+
mac_address :source_mac
|
19
|
+
uint16 :ethertype, :value => 0x88cc
|
20
|
+
chassis_id_tlv :chassis_id
|
21
|
+
port_id_tlv :port_id
|
22
|
+
ttl_tlv :ttl, :initial_value => 120
|
23
|
+
array :optional_tlv, :type => :optional_tlv, :read_until => lambda { element.end_of_lldpdu? }
|
24
|
+
|
25
|
+
|
26
|
+
def dpid
|
27
|
+
chassis_id
|
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:
|
@@ -0,0 +1,28 @@
|
|
1
|
+
require "bindata"
|
2
|
+
|
3
|
+
|
4
|
+
module Pio
|
5
|
+
class Lldp
|
6
|
+
# MAC address
|
7
|
+
class MacAddress < BinData::Primitive
|
8
|
+
array :octets, :type => :uint8, :initial_length => 6
|
9
|
+
|
10
|
+
|
11
|
+
def set value
|
12
|
+
self.octets = value.split( /:/ ).collect { | each | each.hex }
|
13
|
+
end
|
14
|
+
|
15
|
+
|
16
|
+
def get
|
17
|
+
octets.inject( "" ) { | str, each | str + ( "%02x" % each ) }.hex
|
18
|
+
end
|
19
|
+
end
|
20
|
+
end
|
21
|
+
end
|
22
|
+
|
23
|
+
|
24
|
+
### Local variables:
|
25
|
+
### mode: Ruby
|
26
|
+
### coding: utf-8-unix
|
27
|
+
### indent-tabs-mode: nil
|
28
|
+
### End:
|
@@ -0,0 +1,21 @@
|
|
1
|
+
require "rubygems"
|
2
|
+
require "bindata"
|
3
|
+
|
4
|
+
|
5
|
+
module Pio
|
6
|
+
class Lldp
|
7
|
+
# TLV value field of management address TLV
|
8
|
+
class ManagementAddressValue < BinData::Record
|
9
|
+
endian :big
|
10
|
+
|
11
|
+
stringz :management_address
|
12
|
+
end
|
13
|
+
end
|
14
|
+
end
|
15
|
+
|
16
|
+
|
17
|
+
### Local variables:
|
18
|
+
### mode: Ruby
|
19
|
+
### coding: utf-8-unix
|
20
|
+
### indent-tabs-mode: nil
|
21
|
+
### End:
|
@@ -0,0 +1,73 @@
|
|
1
|
+
require "pio/lldp/port-description-value"
|
2
|
+
require "pio/lldp/system-name-value"
|
3
|
+
require "pio/lldp/system-description-value"
|
4
|
+
require "pio/lldp/system-capabilities-value"
|
5
|
+
require "pio/lldp/management-address-value"
|
6
|
+
require "pio/lldp/end-of-lldpdu-value"
|
7
|
+
|
8
|
+
|
9
|
+
module Pio
|
10
|
+
class Lldp
|
11
|
+
# Optional TLV and End Of LLDPDU
|
12
|
+
class OptionalTlv < BinData::Record
|
13
|
+
endian :big
|
14
|
+
|
15
|
+
bit7 :tlv_type
|
16
|
+
bit9 :tlv_info_length
|
17
|
+
choice :tlv_value,
|
18
|
+
:read_length => :tlv_info_length,
|
19
|
+
:onlyif => lambda { not end_of_lldpdu? },
|
20
|
+
:selection => :chooser do
|
21
|
+
end_of_lldpdu_value 0
|
22
|
+
port_description_value 4
|
23
|
+
system_name_value 5
|
24
|
+
system_description_value 6
|
25
|
+
system_capabilities_value 7
|
26
|
+
management_address_value 8
|
27
|
+
string "unknown"
|
28
|
+
end
|
29
|
+
|
30
|
+
|
31
|
+
def end_of_lldpdu?
|
32
|
+
tlv_type == 0
|
33
|
+
end
|
34
|
+
|
35
|
+
|
36
|
+
def chooser
|
37
|
+
if valid_optional_tlv?
|
38
|
+
tlv_type
|
39
|
+
else
|
40
|
+
"unknown"
|
41
|
+
end
|
42
|
+
end
|
43
|
+
|
44
|
+
|
45
|
+
##########################################################################
|
46
|
+
private
|
47
|
+
##########################################################################
|
48
|
+
|
49
|
+
|
50
|
+
def valid_optional_tlv?
|
51
|
+
optional_tlv? or end_of_lldpdu_tlv?
|
52
|
+
end
|
53
|
+
|
54
|
+
|
55
|
+
def optional_tlv?
|
56
|
+
tmp_tlv_type = tlv_type
|
57
|
+
4 <= tmp_tlv_type and tmp_tlv_type <= 8
|
58
|
+
end
|
59
|
+
|
60
|
+
|
61
|
+
def end_of_lldpdu_tlv?
|
62
|
+
tlv_type == 0
|
63
|
+
end
|
64
|
+
end
|
65
|
+
end
|
66
|
+
end
|
67
|
+
|
68
|
+
|
69
|
+
### Local variables:
|
70
|
+
### mode: Ruby
|
71
|
+
### coding: utf-8-unix
|
72
|
+
### indent-tabs-mode: nil
|
73
|
+
### End:
|
@@ -0,0 +1,21 @@
|
|
1
|
+
require "rubygems"
|
2
|
+
require "bindata"
|
3
|
+
|
4
|
+
|
5
|
+
module Pio
|
6
|
+
class Lldp
|
7
|
+
# TLV value field of port description TLV
|
8
|
+
class PortDescriptionValue < BinData::Record
|
9
|
+
endian :big
|
10
|
+
|
11
|
+
stringz :port_description
|
12
|
+
end
|
13
|
+
end
|
14
|
+
end
|
15
|
+
|
16
|
+
|
17
|
+
### Local variables:
|
18
|
+
### mode: Ruby
|
19
|
+
### coding: utf-8-unix
|
20
|
+
### indent-tabs-mode: nil
|
21
|
+
### End:
|
@@ -0,0 +1,44 @@
|
|
1
|
+
require "rubygems"
|
2
|
+
require "bindata"
|
3
|
+
|
4
|
+
|
5
|
+
module Pio
|
6
|
+
class Lldp
|
7
|
+
# Port ID TLV
|
8
|
+
class PortIdTlv < BinData::Primitive
|
9
|
+
endian :big
|
10
|
+
|
11
|
+
bit7 :tlv_type, :value => 2
|
12
|
+
bit9 :tlv_info_length, :initial_value => lambda { port_id.num_bytes + 1 }
|
13
|
+
uint8 :subtype, :initial_value => 7
|
14
|
+
string :port_id, :read_length => lambda { tlv_info_length - 1 }
|
15
|
+
|
16
|
+
|
17
|
+
def get
|
18
|
+
tmp_id = port_id
|
19
|
+
|
20
|
+
if subtype == 7
|
21
|
+
BinData::Uint32be.read tmp_id
|
22
|
+
else
|
23
|
+
tmp_id
|
24
|
+
end
|
25
|
+
end
|
26
|
+
|
27
|
+
|
28
|
+
def set value
|
29
|
+
self.port_id = if value.kind_of?( Fixnum ) and subtype == 7
|
30
|
+
BinData::Uint32be.new( value ).to_binary_s
|
31
|
+
else
|
32
|
+
value
|
33
|
+
end
|
34
|
+
end
|
35
|
+
end
|
36
|
+
end
|
37
|
+
end
|
38
|
+
|
39
|
+
|
40
|
+
### Local variables:
|
41
|
+
### mode: Ruby
|
42
|
+
### coding: utf-8-unix
|
43
|
+
### indent-tabs-mode: nil
|
44
|
+
### End:
|