ospfv2 0.0.1

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