ospfv2 0.0.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.
Files changed (56) hide show
  1. data/bin/ospfv2 +136 -0
  2. data/lib/ie/au_type.rb +79 -0
  3. data/lib/ie/external_route.rb +181 -0
  4. data/lib/ie/id.rb +97 -0
  5. data/lib/ie/interface_mtu.rb +64 -0
  6. data/lib/ie/ls_age.rb +89 -0
  7. data/lib/ie/ls_type.rb +148 -0
  8. data/lib/ie/metric.rb +63 -0
  9. data/lib/ie/mt_metric.rb +119 -0
  10. data/lib/ie/options.rb +356 -0
  11. data/lib/ie/ospf_version.rb +67 -0
  12. data/lib/ie/packet_type.rb +65 -0
  13. data/lib/ie/router_link.rb +167 -0
  14. data/lib/ie/router_link_factory.rb +53 -0
  15. data/lib/ie/router_link_type.rb +86 -0
  16. data/lib/ie/sequence_number.rb +144 -0
  17. data/lib/ie/tos_metric.rb +102 -0
  18. data/lib/infra/ospf_common.rb +291 -0
  19. data/lib/infra/ospf_constants.rb +73 -0
  20. data/lib/infra/ospf_io.rb +133 -0
  21. data/lib/infra/ospf_socket.rb +126 -0
  22. data/lib/infra/parse_options.rb +135 -0
  23. data/lib/infra/timer.rb +104 -0
  24. data/lib/infra/to_s.rb +38 -0
  25. data/lib/ls_db/advertised_routers.rb +78 -0
  26. data/lib/ls_db/common.rb +31 -0
  27. data/lib/ls_db/link_state_database.rb +376 -0
  28. data/lib/ls_db/link_state_database_build.rb +181 -0
  29. data/lib/ls_db/link_state_database_links.rb +178 -0
  30. data/lib/ls_db/links.rb +160 -0
  31. data/lib/lsa/external.rb +347 -0
  32. data/lib/lsa/lsa.rb +438 -0
  33. data/lib/lsa/lsa_factory.rb +59 -0
  34. data/lib/lsa/network.rb +166 -0
  35. data/lib/lsa/router.rb +336 -0
  36. data/lib/lsa/summary.rb +393 -0
  37. data/lib/neighbor/neighbor.rb +298 -0
  38. data/lib/neighbor/neighbor_event_handler.rb +61 -0
  39. data/lib/neighbor/recv_database_description.rb +153 -0
  40. data/lib/neighbor/recv_hello.rb +53 -0
  41. data/lib/neighbor/recv_ospf_packet.rb +68 -0
  42. data/lib/neighbor_sm/attempt_state.rb +44 -0
  43. data/lib/neighbor_sm/down_state.rb +46 -0
  44. data/lib/neighbor_sm/exchange_state.rb +32 -0
  45. data/lib/neighbor_sm/exstart_state.rb +69 -0
  46. data/lib/neighbor_sm/full_state.rb +36 -0
  47. data/lib/neighbor_sm/init_state.rb +43 -0
  48. data/lib/neighbor_sm/loading_state.rb +33 -0
  49. data/lib/neighbor_sm/neighbor_state.rb +87 -0
  50. data/lib/packet/database_description.rb +300 -0
  51. data/lib/packet/hello.rb +327 -0
  52. data/lib/packet/link_state_ack.rb +144 -0
  53. data/lib/packet/link_state_request.rb +153 -0
  54. data/lib/packet/link_state_update.rb +189 -0
  55. data/lib/packet/ospf_packet.rb +306 -0
  56. metadata +116 -0
@@ -0,0 +1,67 @@
1
+ #--
2
+ # Copyright 2010 Jean-Michel Esnault.
3
+ # All rights reserved.
4
+ # See LICENSE.txt for permissions.
5
+ #
6
+ #
7
+ # This file is part of OSPFv2.
8
+ #
9
+ # OSPFv2 is free software: you can redistribute it and/or modify
10
+ # it under the terms of the GNU General Public License as published by
11
+ # the Free Software Foundation, either version 3 of the License, or
12
+ # (at your option) any later version.
13
+ #
14
+ # OSPFv2 is distributed in the hope that it will be useful,
15
+ # but WITHOUT ANY WARRANTY; without even the implied warranty of
16
+ # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
17
+ # GNU General Public License for more details.
18
+ #
19
+ # You should have received a copy of the GNU General Public License
20
+ # along with OSPFv2. If not, see <http://www.gnu.org/licenses/>.
21
+ #++
22
+
23
+ module OSPFv2
24
+ class OspfVersion
25
+ def initialize(version=2)
26
+ case version
27
+ when :v2, 2 ; @ospf_version = 2
28
+ when :v3, 3 ; @ospf_version = 3
29
+ else
30
+ @ospf_version = 0
31
+ end
32
+ end
33
+ def to_s
34
+ case @ospf_version
35
+ when 2 ; '2'
36
+ when 3 ; '3'
37
+ else
38
+ 'unknown'
39
+ end
40
+ end
41
+ def to_hash
42
+ to_i
43
+ end
44
+ def to_i
45
+ @ospf_version
46
+ end
47
+ def to_s
48
+ self.class.to_s.split('::').last + ": #{to_sym}"
49
+ end
50
+ def to_sym
51
+ case @ospf_version
52
+ when 2 ; :v2
53
+ when 3 ; :v3
54
+ else
55
+ ':v?'
56
+ end
57
+ end
58
+
59
+ def encode
60
+ [@ospf_version].pack('C')
61
+ end
62
+ alias :enc :encode
63
+
64
+ end
65
+ end
66
+
67
+ load "../../../test/ospfv2/ie/#{ File.basename($0.gsub(/.rb/,'_test.rb'))}" if __FILE__ == $0
@@ -0,0 +1,65 @@
1
+ #--
2
+ # Copyright 2010 Jean-Michel Esnault.
3
+ # All rights reserved.
4
+ # See LICENSE.txt for permissions.
5
+ #
6
+ #
7
+ # This file is part of OSPFv2.
8
+ #
9
+ # OSPFv2 is free software: you can redistribute it and/or modify
10
+ # it under the terms of the GNU General Public License as published by
11
+ # the Free Software Foundation, either version 3 of the License, or
12
+ # (at your option) any later version.
13
+ #
14
+ # OSPFv2 is distributed in the hope that it will be useful,
15
+ # but WITHOUT ANY WARRANTY; without even the implied warranty of
16
+ # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
17
+ # GNU General Public License for more details.
18
+ #
19
+ # You should have received a copy of the GNU General Public License
20
+ # along with OSPFv2. If not, see <http://www.gnu.org/licenses/>.
21
+ #++
22
+
23
+ module OSPFv2
24
+ class PacketType
25
+ def initialize(value=0)
26
+ case value
27
+ when 1, :hello ; @packet_type = 1
28
+ when 2, :dd ; @packet_type = 2
29
+ when 3, :ls_request ; @packet_type = 3
30
+ when 4, :ls_update ; @packet_type = 4
31
+ when 5, :ls_ack ; @packet_type = 5
32
+ else
33
+ @packet_type = 0
34
+ end
35
+ end
36
+ def to_hash
37
+ to_sym
38
+ end
39
+ def to_i
40
+ @packet_type
41
+ end
42
+ def to_s
43
+ self.class.to_s.split('::').last + ": #{to_sym}"
44
+ end
45
+ def to_sym
46
+ case @packet_type
47
+ when 1 ; :hello
48
+ when 2 ; :dd
49
+ when 3 ; :ls_request
50
+ when 4 ; :ls_update
51
+ when 5 ; :ls_ack
52
+ else
53
+ 'unknown'
54
+ end
55
+ end
56
+
57
+ def encode
58
+ [@packet_type].pack('C')
59
+ end
60
+ alias :enc :encode
61
+
62
+ end
63
+ end
64
+
65
+ load "../../../test/ospfv2/ie/#{ File.basename($0.gsub(/.rb/,'_test.rb'))}" if __FILE__ == $0
@@ -0,0 +1,167 @@
1
+ #--
2
+ # Copyright 2010 Jean-Michel Esnault.
3
+ # All rights reserved.
4
+ # See LICENSE.txt for permissions.
5
+ #
6
+ #
7
+ # This file is part of OSPFv2.
8
+ #
9
+ # OSPFv2 is free software: you can redistribute it and/or modify
10
+ # it under the terms of the GNU General Public License as published by
11
+ # the Free Software Foundation, either version 3 of the License, or
12
+ # (at your option) any later version.
13
+ #
14
+ # OSPFv2 is distributed in the hope that it will be useful,
15
+ # but WITHOUT ANY WARRANTY; without even the implied warranty of
16
+ # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
17
+ # GNU General Public License for more details.
18
+ #
19
+ # You should have received a copy of the GNU General Public License
20
+ # along with OSPFv2. If not, see <http://www.gnu.org/licenses/>.
21
+ #++
22
+
23
+ require 'infra/ospf_common'
24
+ require 'ie/id'
25
+ require 'ie/metric'
26
+ require 'ie/mt_metric'
27
+ require 'ie/router_link_type'
28
+
29
+ module OSPFv2
30
+
31
+ class RouterLink
32
+ include Common
33
+
34
+ LinkId = Class.new(Id)
35
+ LinkData = Class.new(Id)
36
+
37
+ attr_reader :link_id, :link_data, :router_link_type, :metric, :mt_metrics
38
+
39
+ attr_writer_delegate :link_id, :link_data, :router_link_type
40
+
41
+ def initialize(arg={})
42
+ arg = arg.dup
43
+ if arg.is_a?(Hash)
44
+ @link_id, @link_data, @router_link_type, @metric = nil, nil, nil, nil
45
+ @mt_metrics = []
46
+ set arg
47
+ elsif arg.is_a?(String)
48
+ parse arg
49
+ elsif arg.is_a?(self.class)
50
+ parse arg.encode
51
+ else
52
+ raise ArgumentError, "Invalid Argument: #{arg.inspect}"
53
+ end
54
+ end
55
+
56
+ # +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
57
+ # | Link ID |
58
+ # +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
59
+ # | Link Data |
60
+ # +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
61
+ # | Type | # TOS | metric |
62
+ # +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
63
+ # | ... |
64
+ # +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
65
+ # | TOS | 0 | TOS metric |
66
+ # +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
67
+ def encode
68
+ @link_id ||= LinkId.new
69
+ @link_data ||= LinkData.new
70
+ @router_link_type ||= RouterLinkType.new
71
+ @metric ||= Metric.new
72
+ rlink =[]
73
+ rlink << link_id.encode
74
+ rlink << link_data.encode
75
+ rlink << router_link_type.encode
76
+ rlink << [mt_metrics.size].pack('C')
77
+ rlink << metric.encode('n')
78
+ rlink << mt_metrics.collect { |x| x.encode }
79
+ rlink.join
80
+ end
81
+
82
+ # TODO: if self.class is not RouterLink do not display RouterLinkType info....
83
+ def to_s(ident=2)
84
+ encode unless @router_link_type
85
+ self.class.to_s.split('::').last + ":" +
86
+ ['',link_id, link_data, router_link_type, metric, *mt_metrics].compact.collect { |x| x.to_s }.join("\n"+" "*ident)
87
+ end
88
+
89
+ def to_s_junos_style
90
+ s = " id #{id}, data #{data}, Type #{RouterLink.type_to_s_junos_style[@type]} (#{@type})"
91
+ s +="\n Topology count: #{@mt_id.size}, Default metric: #{@metric}"
92
+ s += @mt_id.collect { |mt| "\n #{mt.to_s_junos_style}" }.join
93
+ s
94
+ end
95
+
96
+ def to_s_junos
97
+ s = " id #{link_id.to_ip}, data #{link_data.to_ip}, Type #{RouterLinkType.to_junos(router_link_type.to_i)} (#{router_link_type.to_i})"
98
+ s +="\n Topology count: #{@mt_metrics.size}, Default metric: #{metric.to_i}"
99
+ s += @mt_metrics.collect { |mt| "\n #{mt.to_s}" }.join
100
+
101
+ end
102
+
103
+ class << self
104
+ class_eval {
105
+ RouterLinkType.each { |x|
106
+ define_method "new_#{x}" do |*args|
107
+ OSPFv2::RouterLink.const_get(x.to_klass).send :new, *args
108
+ end
109
+ }
110
+ }
111
+ end
112
+
113
+ RouterLinkType.each { |x|
114
+ klassname = Class.new(self) do
115
+ define_method(:initialize) do |arg|
116
+ arg ||={}
117
+ arg[:router_link_type] = x if arg.is_a?(Hash)
118
+ super arg
119
+ end
120
+ define_method(:to_hash) do
121
+ super.merge :router_link_type => x
122
+ end
123
+ end
124
+ self.const_set(x.to_klass, klassname)
125
+ }
126
+
127
+ # FIXME: same as summary.rb ... mixin candidate
128
+ def mt_metrics=(val)
129
+ [val].flatten.each { |x| self << x }
130
+ end
131
+
132
+ def <<(metric)
133
+ @mt_metrics ||=[]
134
+ @mt_metrics << MtMetric.new(metric)
135
+ self
136
+ end
137
+
138
+ def parse(s)
139
+ @mt_metrics ||=[]
140
+ link_id, link_data, router_link_type, ntos, metric, mt_metrics = s.unpack('NNCCna*')
141
+ @link_id = LinkId.new link_id
142
+ @link_data = LinkData.new link_data
143
+ @router_link_type = RouterLinkType.new router_link_type
144
+ @metric = Metric.new metric
145
+ while mt_metrics.size>0
146
+ self << MtMetric.new(mt_metrics.slice!(0,4))
147
+ end
148
+ end
149
+
150
+ end
151
+ #
152
+ # require 'pp'
153
+ # h = {:router_link_type=>1, :metric=>1,:mt_metrics=>[{:id=>20, :metric=>33}, {:id=>255, :metric=>34}], :link_data=>"10.254.233.233",:link_id=>"2.2.2.2"}
154
+ #
155
+ # pp RouterLink.new(h)
156
+ #
157
+ # puts RouterLink.new(h)
158
+ # puts RouterLink.new(h).to_shex
159
+
160
+
161
+
162
+
163
+ end
164
+
165
+
166
+
167
+ load "../../../test/ospfv2/ie/#{ File.basename($0.gsub(/.rb/,'_test.rb'))}" if __FILE__ == $0
@@ -0,0 +1,53 @@
1
+ #--
2
+ # Copyright 2010 Jean-Michel Esnault.
3
+ # All rights reserved.
4
+ # See LICENSE.txt for permissions.
5
+ #
6
+ #
7
+ # This file is part of OSPFv2.
8
+ #
9
+ # OSPFv2 is free software: you can redistribute it and/or modify
10
+ # it under the terms of the GNU General Public License as published by
11
+ # the Free Software Foundation, either version 3 of the License, or
12
+ # (at your option) any later version.
13
+ #
14
+ # OSPFv2 is distributed in the hope that it will be useful,
15
+ # but WITHOUT ANY WARRANTY; without even the implied warranty of
16
+ # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
17
+ # GNU General Public License for more details.
18
+ #
19
+ # You should have received a copy of the GNU General Public License
20
+ # along with OSPFv2. If not, see <http://www.gnu.org/licenses/>.
21
+ #++
22
+
23
+ require 'infra/ospf_common'
24
+ require 'ie/router_link'
25
+
26
+ module OSPFv2
27
+ class RouterLink
28
+ def self.factory(arg)
29
+ if arg.is_a?(Hash)
30
+ raise ArgumentError, "no link type specified" unless arg[:router_link_type]
31
+ case arg[:router_link_type]
32
+ when 1,:point_to_point ; PointToPoint.new(arg)
33
+ when 2,:transit_network ; TransitNetwork.new(arg)
34
+ when 3,:stub_network ; StubNetwork.new(arg)
35
+ when 4,:virtual_link ; VirtualLink.new(arg)
36
+ end
37
+ elsif arg.is_a?(String)
38
+ case arg[8,1].unpack('C')[0]
39
+ when 1 ; PointToPoint.new(arg)
40
+ when 2 ; TransitNetwork.new(arg)
41
+ when 3 ; StubNetwork.new(arg)
42
+ when 4 ; VirtualLink.new(arg)
43
+ else
44
+ raise ArgumentError, "Invalid Argument: #{arg[8,1].unpack('C')[0]} #{arg.inspect}/#{arg.unpack('H*')}"
45
+ end
46
+ elsif arg.is_a?(RouterLink)
47
+ factory(arg.encode)
48
+ end
49
+ end
50
+ end
51
+ end
52
+
53
+ load "../../../test/ospfv2/ie/#{ File.basename($0.gsub(/.rb/,'_test.rb'))}" if __FILE__ == $0
@@ -0,0 +1,86 @@
1
+ #--
2
+ # Copyright 2010 Jean-Michel Esnault.
3
+ # All rights reserved.
4
+ # See LICENSE.txt for permissions.
5
+ #
6
+ #
7
+ # This file is part of OSPFv2.
8
+ #
9
+ # OSPFv2 is free software: you can redistribute it and/or modify
10
+ # it under the terms of the GNU General Public License as published by
11
+ # the Free Software Foundation, either version 3 of the License, or
12
+ # (at your option) any later version.
13
+ #
14
+ # OSPFv2 is distributed in the hope that it will be useful,
15
+ # but WITHOUT ANY WARRANTY; without even the implied warranty of
16
+ # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
17
+ # GNU General Public License for more details.
18
+ #
19
+ # You should have received a copy of the GNU General Public License
20
+ # along with OSPFv2. If not, see <http://www.gnu.org/licenses/>.
21
+ #++
22
+
23
+ # Router Link:
24
+ # Type Description
25
+ # __________________________________________________
26
+ # 1 Point-to-point connection to another router
27
+ # 2 Connection to a transit network
28
+ # 3 Connection to a stub network
29
+ # 4 Virtual link
30
+
31
+ module OSPFv2
32
+ class RouterLinkType
33
+ def self.each
34
+ [:point_to_point, :transit_network, :stub_network, :virtual_link].each { |x| yield(x) } if block_given?
35
+ end
36
+ def self.to_i(arg)
37
+ return arg unless arg.is_a?(Symbol)
38
+ [:point_to_point, :transit_network, :stub_network, :virtual_link].index(arg)+1
39
+ end
40
+ def self.to_junos(type)
41
+ case type.to_i
42
+ when 1 ; 'Point-to-point'
43
+ when 2 ; 'Transit'
44
+ when 3 ; 'Stub'
45
+ when 4 ; 'Virtual-link'
46
+ else ; type.to_i
47
+ end
48
+ end
49
+ def initialize(router_link_type=1)
50
+ case router_link_type
51
+ when 1, :point_to_point ; @router_link_type=1
52
+ when 2, :transit_network ; @router_link_type=2
53
+ when 3, :stub_network ; @router_link_type=3
54
+ when 4, :virtual_link ; @router_link_type=4
55
+ else
56
+ raise ArgumentError, "Invalid RouterLinkType #{router_link_type}"
57
+ end
58
+ end
59
+ def to_i
60
+ @router_link_type
61
+ end
62
+ def to_s
63
+ self.class.to_s.split('::').last + ": #{to_sym}"
64
+ end
65
+ def to_sym
66
+ case @router_link_type
67
+ when 1 ; :point_to_point
68
+ when 2 ; :transit_network
69
+ when 3 ; :stub_network
70
+ when 4 ; :virtual_link
71
+ end
72
+ end
73
+ def encode
74
+ [@router_link_type].pack('C')
75
+ end
76
+ alias :enc :encode
77
+
78
+ def to_hash
79
+ to_sym
80
+ end
81
+
82
+ end
83
+ end
84
+
85
+ load "../../../test/ospfv2/ie/#{ File.basename($0.gsub(/.rb/,'_test.rb'))}" if __FILE__ == $0
86
+
@@ -0,0 +1,144 @@
1
+ #--
2
+ # Copyright 2010 Jean-Michel Esnault.
3
+ # All rights reserved.
4
+ # See LICENSE.txt for permissions.
5
+ #
6
+ #
7
+ # This file is part of OSPFv2.
8
+ #
9
+ # OSPFv2 is free software: you can redistribute it and/or modify
10
+ # it under the terms of the GNU General Public License as published by
11
+ # the Free Software Foundation, either version 3 of the License, or
12
+ # (at your option) any later version.
13
+ #
14
+ # OSPFv2 is distributed in the hope that it will be useful,
15
+ # but WITHOUT ANY WARRANTY; without even the implied warranty of
16
+ # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
17
+ # GNU General Public License for more details.
18
+ #
19
+ # You should have received a copy of the GNU General Public License
20
+ # along with OSPFv2. If not, see <http://www.gnu.org/licenses/>.
21
+ #++
22
+
23
+ require 'infra/ospf_constants'
24
+
25
+ module OSPFv2
26
+
27
+ class SequenceNumber
28
+ include OSPFv2
29
+ include Comparable
30
+
31
+ def SequenceNumber.initial
32
+ [N + 1].pack('I').unpack('i')[0]
33
+ end
34
+
35
+ def SequenceNumber.max
36
+ [N - 1].pack('I').unpack('i')[0]
37
+ end
38
+
39
+ def SequenceNumber.N
40
+ [N].pack('I').unpack('i')[0]
41
+ end
42
+
43
+ def SequenceNumber.to_s(seqn)
44
+ new(seqn).to_s
45
+ end
46
+
47
+ def initialize(seqn=:init)
48
+ if seqn.is_a?(Symbol)
49
+ if seqn == :max
50
+ @seqn= MaxSequenceNumber
51
+ elsif seqn == :init
52
+ @seqn = InitialSequenceNumber
53
+ elsif seqn == :reserved
54
+ @seqn = N
55
+ end
56
+ elsif seqn.is_a?(self.class)
57
+ @seqn = seqn.to_I
58
+ else
59
+ @seqn=seqn
60
+ end
61
+ @seqn = [@seqn].pack('I')
62
+ end
63
+
64
+ def <=>(o)
65
+ to_i <=> o.to_i
66
+ end
67
+
68
+ def to_i
69
+ @seqn.unpack('i')[0]
70
+ end
71
+ def to_I
72
+ @seqn.unpack('I')[0]
73
+ end
74
+
75
+ def to_s
76
+ "0x"+ sprintf("%08.8x", to_I)
77
+ end
78
+
79
+ def +(num)
80
+ seqn = (@seqn.unpack('i')[0]+num)
81
+ @seqn = [seqn].pack('I')
82
+ self
83
+ end
84
+
85
+ def -(num)
86
+ self.+(-num)
87
+ end
88
+
89
+ def encode
90
+ #FIXME: unit-test and check if 'i' or 'I'
91
+ [to_i].pack('N')
92
+ end
93
+
94
+ def to_hash
95
+ to_I
96
+ end
97
+
98
+ end
99
+
100
+ end
101
+
102
+ load "../../../test/ospfv2/ie/#{ File.basename($0.gsub(/.rb/,'_test.rb'))}" if __FILE__ == $0
103
+
104
+ __END__
105
+
106
+
107
+ =begin rdoc
108
+ 12.1.6. LS sequence number
109
+
110
+ The sequence number field is a signed 32-bit integer. It is
111
+ used to detect old and duplicate LSAs. The space of
112
+ sequence numbers is linearly ordered. The larger the
113
+ sequence number (when compared as signed 32-bit integers)
114
+ the more recent the LSA. To describe to sequence number
115
+ space more precisely, let N refer in the discussion below to
116
+ the constant 2**31.
117
+
118
+ The sequence number -N (0x80000000) is reserved (and
119
+ unused). This leaves -N + 1 (0x80000001) as the smallest
120
+ (and therefore oldest) sequence number; this sequence number
121
+ is referred to as the constant InitialSequenceNumber. A
122
+ router uses InitialSequenceNumber the first time it
123
+ originates any LSA. Afterwards, the LSA's sequence number
124
+ is incremented each time the router originates a new
125
+ instance of the LSA. When an attempt is made to increment
126
+ the sequence number past the maximum value of N - 1
127
+ (0x7fffffff; also referred to as MaxSequenceNumber), the
128
+ current instance of the LSA must first be flushed from the
129
+ routing domain. This is done by prematurely aging the LSA
130
+ (see Section 14.1) and reflooding it. As soon as this flood
131
+ has been acknowledged by all adjacent neighbors, a new
132
+ instance can be originated with sequence number of
133
+ InitialSequenceNumber.
134
+
135
+ The router may be forced to promote the sequence number of
136
+ one of its LSAs when a more recent instance of the LSA is
137
+ unexpectedly received during the flooding process. This
138
+ should be a rare event. This may indicate that an out-of-
139
+ date LSA, originated by the router itself before its last
140
+ restart/reload, still exists in the Autonomous System. For
141
+ more information see Section 13.4.
142
+
143
+
144
+ =end
@@ -0,0 +1,102 @@
1
+ #--
2
+ # Copyright 2010 Jean-Michel Esnault.
3
+ # All rights reserved.
4
+ # See LICENSE.txt for permissions.
5
+ #
6
+ #
7
+ # This file is part of OSPFv2.
8
+ #
9
+ # OSPFv2 is free software: you can redistribute it and/or modify
10
+ # it under the terms of the GNU General Public License as published by
11
+ # the Free Software Foundation, either version 3 of the License, or
12
+ # (at your option) any later version.
13
+ #
14
+ # OSPFv2 is distributed in the hope that it will be useful,
15
+ # but WITHOUT ANY WARRANTY; without even the implied warranty of
16
+ # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
17
+ # GNU General Public License for more details.
18
+ #
19
+ # You should have received a copy of the GNU General Public License
20
+ # along with OSPFv2. If not, see <http://www.gnu.org/licenses/>.
21
+ #++
22
+
23
+ # +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
24
+ # | 0 | metric |
25
+ # +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
26
+ # | TOS | TOS metric |
27
+ # +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
28
+ # | ... |
29
+ #
30
+ # Network Mask
31
+ # For Type 3 summary-LSAs, this indicates the destination
32
+ # network's IP address mask. For example, when advertising the
33
+ # location of a class A network the value 0xff000000 would be
34
+ # used. This field is not meaningful and must be zero for Type 4
35
+ # summary-LSAs.
36
+ #
37
+ # metric
38
+ # The cost of this route. Expressed in the same units as the
39
+ # interface costs in the router-LSAs.
40
+ #
41
+ # Additional TOS-specific information may also be included, for
42
+ # backward compatibility with previous versions of the OSPF
43
+ # specification ([Ref9]). For each desired TOS, TOS-specific
44
+ # information is encoded as follows:
45
+ #
46
+ # TOS IP Type of Service that this metric refers to. The encoding of
47
+ # TOS in OSPF LSAs is described in Section 12.3.
48
+ #
49
+ # TOS metric
50
+ # TOS-specific metric information.
51
+ #
52
+
53
+ require 'infra/ospf_common'
54
+ module OSPFv2
55
+
56
+ class TosMetric
57
+ include Common
58
+
59
+ attr_reader :tos, :cost
60
+
61
+ def initialize(arg={})
62
+ arg = arg.dup
63
+ @tos,@cost=0,0
64
+ if arg.is_a?(Hash)
65
+ set arg
66
+ elsif arg.is_a?(String)
67
+ parse arg
68
+ elsif arg.is_a?(self.class)
69
+ parse arg.encode
70
+ elsif arg.is_a?(Array) and arg.size==2
71
+ @tos, @cost = arg
72
+ else
73
+ raise ArgumentError, "Invalid Argument: #{arg.inspect}"
74
+ end
75
+ end
76
+
77
+ alias :id :tos
78
+
79
+ def encode
80
+ m = []
81
+ m << [tos].pack('C')
82
+ m << [cost].pack('N').unpack('C4')[1..-1].pack('C3')
83
+ m.join
84
+ end
85
+
86
+ def parse(s)
87
+ @tos, *cost = s.unpack('C4')
88
+ @cost = [0,*cost].pack('C4').unpack('N')[0]
89
+ end
90
+
91
+ def to_s
92
+ self.class.to_s.split('::').last + ": tos: #{tos} cost: #{cost}"
93
+ end
94
+
95
+ def to_s_junos_style
96
+ "Topology (ID #{id}) -> Metric: #{cost}"
97
+ end
98
+
99
+ end
100
+ end
101
+
102
+ load "../../../test/ospfv2/ie/#{ File.basename($0.gsub(/.rb/,'_test.rb'))}" if __FILE__ == $0