pio 0.1.0

Sign up to get free protection for your applications and to get access to all the features.
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: