pio 0.1.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.
data/README.md ADDED
@@ -0,0 +1,4 @@
1
+ pio
2
+ ===
3
+
4
+ Packet parser and generator
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: