ospfv2 0.0.1 → 0.0.2
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/bin/ospfv2 +3 -6
- data/changelog.txt +8 -0
- data/lib/ie/au_type.rb +1 -1
- data/lib/ie/external_route.rb +6 -3
- data/lib/ie/interface_mtu.rb +0 -1
- data/lib/ie/ls_age.rb +2 -16
- data/lib/ie/ls_type.rb +106 -73
- data/lib/ie/metric.rb +13 -0
- data/lib/ie/options.rb +42 -21
- data/lib/ie/ospf_version.rb +0 -8
- data/lib/ie/router_link.rb +7 -28
- data/lib/ie/sequence_number.rb +6 -1
- data/lib/infra/ospf_common.rb +2 -13
- data/lib/infra/ospf_constants.rb +8 -8
- data/lib/infra/ospf_io.rb +1 -1
- data/lib/infra/ospf_socket.rb +12 -20
- data/lib/infra/parse_options.rb +3 -3
- data/lib/infra/timer.rb +2 -1
- data/lib/ls_db/advertised_routers.rb +30 -28
- data/lib/ls_db/link_state_database.rb +8 -50
- data/lib/ls_db/link_state_database_build.rb +5 -5
- data/lib/ls_db/links.rb +1 -4
- data/lib/lsa/external.rb +13 -11
- data/lib/lsa/lsa.rb +81 -43
- data/lib/lsa/lsa_base.rb +430 -0
- data/lib/lsa/lsa_factory.rb +5 -1
- data/lib/lsa/network.rb +7 -2
- data/lib/lsa/opaque.rb +143 -0
- data/lib/lsa/router.rb +17 -25
- data/lib/lsa/summary.rb +17 -171
- data/lib/lsa/tlv/tlv.rb +0 -0
- data/lib/neighbor/neighbor.rb +24 -9
- data/lib/neighbor/recv_hello.rb +0 -5
- data/lib/neighbor/recv_ospf_packet.rb +1 -2
- data/lib/neighbor_sm/exstart_state.rb +9 -12
- data/lib/neighbor_sm/init_state.rb +5 -7
- data/lib/packet/database_description.rb +7 -7
- data/lib/packet/hello.rb +94 -12
- data/lib/packet/link_state_ack.rb +2 -2
- data/lib/packet/link_state_update.rb +1 -1
- data/lib/packet/ospf_packet.rb +4 -5
- metadata +16 -8
@@ -52,14 +52,14 @@ module OSPFv2::LSDB
|
|
52
52
|
raise ArgumentError, "missing prefix" unless prefix
|
53
53
|
raise ArgumentError, "missing neighbor router id" unless neighbor_id
|
54
54
|
|
55
|
-
_, addr, plen, network, netmask = IPAddr.
|
55
|
+
_, addr, plen, network, netmask = IPAddr.to_arr(prefix)
|
56
56
|
|
57
57
|
# if not set assume router id is the interface address given to us in :prefix
|
58
58
|
router_id ||= addr
|
59
59
|
|
60
60
|
|
61
61
|
# router_id to list of advertised routers
|
62
|
-
advertised_routers
|
62
|
+
advertised_routers << router_id
|
63
63
|
|
64
64
|
rlsa = find_router_lsa router_id
|
65
65
|
|
@@ -72,7 +72,7 @@ module OSPFv2::LSDB
|
|
72
72
|
:ls_type=>:router_lsa,
|
73
73
|
:options=> 0x22
|
74
74
|
|
75
|
-
advertised_routers
|
75
|
+
advertised_routers << router_id
|
76
76
|
|
77
77
|
# add to lsdb
|
78
78
|
self << rlsa
|
@@ -97,7 +97,7 @@ module OSPFv2::LSDB
|
|
97
97
|
|
98
98
|
def remove_adjacency(rid, neighbor_id, prefix)
|
99
99
|
if (rlsa = lookup(:router_lsa, rid))
|
100
|
-
addr, source_address, plen, network, netmask = IPAddr.
|
100
|
+
addr, source_address, plen, network, netmask = IPAddr.to_arr(prefix)
|
101
101
|
rlsa.delete(:point_to_point,id2ip(neighbor_id))
|
102
102
|
rlsa.delete(3,network)
|
103
103
|
end
|
@@ -139,7 +139,7 @@ module OSPFv2::LSDB
|
|
139
139
|
:ls_type=>:router_lsa,
|
140
140
|
:options=> 0x22
|
141
141
|
|
142
|
-
advertised_routers
|
142
|
+
advertised_routers << router_id
|
143
143
|
|
144
144
|
# add to lsdb
|
145
145
|
self << rlsa
|
data/lib/ls_db/links.rb
CHANGED
@@ -140,15 +140,12 @@ module OSPFv2::LSDB
|
|
140
140
|
if name.to_s =~ /^(local|remote)_address/
|
141
141
|
(__send__ "#{$1}_prefix").split('/')[0]
|
142
142
|
else
|
143
|
-
|
144
|
-
raise
|
143
|
+
super
|
145
144
|
end
|
146
145
|
end
|
147
146
|
|
148
|
-
|
149
147
|
private
|
150
148
|
|
151
|
-
|
152
149
|
def _address_(host=1)
|
153
150
|
network + host
|
154
151
|
end
|
data/lib/lsa/external.rb
CHANGED
@@ -155,17 +155,19 @@ module OSPFv2
|
|
155
155
|
|
156
156
|
class External_Base < Lsa
|
157
157
|
|
158
|
-
|
159
|
-
|
160
|
-
|
158
|
+
unless const_defined?(:Netmask)
|
159
|
+
Netmask = Class.new(OSPFv2::Id)
|
160
|
+
ExternalRoute = Class.new(OSPFv2::ExternalRoute)
|
161
|
+
end
|
161
162
|
|
162
163
|
attr_reader :netmask, :external_route, :mt_metrics
|
163
164
|
attr_writer_delegate :netmask, :external_route
|
164
165
|
|
165
|
-
def initialize(arg={})
|
166
|
+
def initialize(ls_type, arg={})
|
166
167
|
@netmask, @external_route = nil
|
167
168
|
@mt_metrics=[]
|
168
|
-
|
169
|
+
@ls_type = LsType.new(ls_type)
|
170
|
+
super arg
|
169
171
|
end
|
170
172
|
|
171
173
|
def encode
|
@@ -277,7 +279,9 @@ module OSPFv2
|
|
277
279
|
|
278
280
|
class AsExternal < External_Base
|
279
281
|
|
280
|
-
|
282
|
+
unless const_defined?(:ExternalRoute)
|
283
|
+
ExternalRoute = Class.new(OSPFv2::ExternalRoute)
|
284
|
+
end
|
281
285
|
|
282
286
|
class << self
|
283
287
|
def count
|
@@ -308,11 +312,9 @@ module OSPFv2
|
|
308
312
|
end
|
309
313
|
|
310
314
|
def initialize(arg={})
|
311
|
-
|
312
|
-
|
313
|
-
|
314
|
-
super
|
315
|
-
end
|
315
|
+
arg = fix_hash(arg) if arg.is_a?(Hash)
|
316
|
+
super 5, arg
|
317
|
+
end
|
316
318
|
|
317
319
|
private
|
318
320
|
|
data/lib/lsa/lsa.rb
CHANGED
@@ -49,6 +49,28 @@ are also contained in the LSA header.
|
|
49
49
|
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
|
50
50
|
|
51
51
|
|
52
|
+
0 1 2 3
|
53
|
+
0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1
|
54
|
+
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
|
55
|
+
| LS age | Options | 9, 10, or 11 |
|
56
|
+
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
|
57
|
+
| Opaque Type | Opaque ID |
|
58
|
+
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
|
59
|
+
| Advertising Router |
|
60
|
+
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
|
61
|
+
| LS Sequence Number |
|
62
|
+
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
|
63
|
+
| LS checksum | Length |
|
64
|
+
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
|
65
|
+
| |
|
66
|
+
+ +
|
67
|
+
| Opaque Information |
|
68
|
+
+ +
|
69
|
+
| ... |
|
70
|
+
#
|
71
|
+
|
72
|
+
|
73
|
+
|
52
74
|
LS age
|
53
75
|
The time in seconds since the LSA was originated.
|
54
76
|
|
@@ -118,9 +140,12 @@ module OSPFv2
|
|
118
140
|
class Lsa
|
119
141
|
include Comparable
|
120
142
|
|
121
|
-
|
122
|
-
|
123
|
-
|
143
|
+
unless const_defined?(:AdvertisingRouter)
|
144
|
+
AdvertisingRouter = Class.new(Id)
|
145
|
+
LsId = Class.new(Id)
|
146
|
+
LsAge = Class.new(LsAge)
|
147
|
+
MODX=4102
|
148
|
+
end
|
124
149
|
|
125
150
|
class << self
|
126
151
|
def new_ntop(arg)
|
@@ -152,7 +177,7 @@ module OSPFv2
|
|
152
177
|
alias :acked? :is_acked?
|
153
178
|
alias :ack? :acked?
|
154
179
|
|
155
|
-
attr_reader :ls_age, :options
|
180
|
+
attr_reader :ls_age, :options
|
156
181
|
attr_reader :ls_id
|
157
182
|
attr_reader :advertising_router
|
158
183
|
attr_reader :sequence_number
|
@@ -164,12 +189,16 @@ module OSPFv2
|
|
164
189
|
@ls_age = LsAge.new
|
165
190
|
@sequence_number = SequenceNumber.new
|
166
191
|
@options = Options.new
|
167
|
-
@ls_type = LsType.new klass_to_ls_type
|
168
192
|
@ls_id = LsId.new
|
169
193
|
@advertising_router = AdvertisingRouter.new
|
170
194
|
@_length = 0
|
171
195
|
@_rxmt_ = false
|
172
196
|
|
197
|
+
# unless @ls_type
|
198
|
+
# # raise if caller[-2].grep(/test\/unit/).empty?
|
199
|
+
# @ls_type = LsType.new(1)
|
200
|
+
# end
|
201
|
+
|
173
202
|
if arg.is_a?(Hash)
|
174
203
|
set arg
|
175
204
|
elsif arg.is_a?(String)
|
@@ -182,15 +211,21 @@ module OSPFv2
|
|
182
211
|
|
183
212
|
end
|
184
213
|
|
214
|
+
def ls_type
|
215
|
+
@ls_type ||= LsType.new(1)
|
216
|
+
end
|
217
|
+
|
185
218
|
def sequence_number=(seqn)
|
186
219
|
@sequence_number = SequenceNumber.new(seqn)
|
187
220
|
end
|
188
221
|
|
189
222
|
def to_s_default
|
190
223
|
len = encode.size
|
191
|
-
|
192
|
-
|
193
|
-
|
224
|
+
if is_opaque?
|
225
|
+
else
|
226
|
+
sprintf("%-4.0d 0x%2.2x %-8s %-15.15s %-15.15s 0x%8.8x 0x%4.4x %-7d",
|
227
|
+
ls_age.to_i, options.to_i, ls_type.to_s_short, ls_id.to_ip, advertising_router.to_ip, seqn.to_I,csum_to_i,len)
|
228
|
+
end
|
194
229
|
end
|
195
230
|
alias :to_s_dd :to_s_default
|
196
231
|
|
@@ -202,7 +237,11 @@ module OSPFv2
|
|
202
237
|
s << options.to_s
|
203
238
|
s << ls_type.to_s
|
204
239
|
s << advertising_router.to_s
|
205
|
-
|
240
|
+
if is_opaque?
|
241
|
+
# s << ls_id.to_s
|
242
|
+
else
|
243
|
+
s << ls_id.to_s
|
244
|
+
end
|
206
245
|
s << "SequenceNumber: " + sequence_number.to_s
|
207
246
|
s << "LS checksum: #{format "%4x", csum_to_i}" if @_csum
|
208
247
|
s << "length: #{@_size.unpack('n')}" if @_size
|
@@ -213,31 +252,39 @@ module OSPFv2
|
|
213
252
|
|
214
253
|
def to_s_junos
|
215
254
|
len = encode.size
|
216
|
-
|
255
|
+
if is_opaque?
|
256
|
+
else
|
257
|
+
sprintf("%-7s %-1.1s%-15.15s %-15.15s 0x%8.8x %4.0d 0x%2.2x 0x%4.4x %3d", ls_type.to_junos, '', ls_id.to_ip, advertising_router.to_ip, seqn.to_I, ls_age.to_i, options.to_i, csum_to_i, len)
|
258
|
+
end
|
217
259
|
end
|
218
260
|
include OSPFv2::TO_S
|
219
261
|
alias :to_s_junos_verbose :to_s_junos
|
220
|
-
|
221
|
-
|
222
|
-
|
223
|
-
|
224
|
-
|
225
|
-
# when :junos_verbose ; to_s_junos_verbose(*args)
|
226
|
-
# else
|
227
|
-
# to_s_default(*args)
|
228
|
-
# end
|
229
|
-
# end
|
230
|
-
|
262
|
+
|
263
|
+
def is_opaque?
|
264
|
+
ls_type.is_opaque?
|
265
|
+
end
|
266
|
+
|
231
267
|
def encode_header
|
232
268
|
header = []
|
233
269
|
header << ls_age.encode
|
234
270
|
header << [options.to_i].pack('C')
|
235
271
|
header << ls_type.encode
|
236
|
-
|
272
|
+
if is_opaque?
|
273
|
+
header << [(@opaque_type << 24) + @opaque_id].pack('N')
|
274
|
+
else
|
275
|
+
header << ls_id.encode
|
276
|
+
end
|
237
277
|
header << advertising_router.encode
|
238
278
|
header << sequence_number.encode
|
239
279
|
header << [''].pack('a4')
|
240
280
|
header.join
|
281
|
+
rescue => e
|
282
|
+
p ls_age
|
283
|
+
p ls_type
|
284
|
+
p ls_id
|
285
|
+
p advertising_router
|
286
|
+
p sequence_number
|
287
|
+
raise
|
241
288
|
end
|
242
289
|
alias :header_encode :encode_header
|
243
290
|
|
@@ -271,7 +318,12 @@ module OSPFv2
|
|
271
318
|
@ls_age = LsAge.new ls_age
|
272
319
|
@sequence_number = SequenceNumber.new seqn
|
273
320
|
@advertising_router = AdvertisingRouter.new advr
|
274
|
-
|
321
|
+
if is_opaque?
|
322
|
+
@opaque_id = ls_id >> 24
|
323
|
+
@opaque_type = ls_id & 0xffffff
|
324
|
+
else
|
325
|
+
@ls_id = LsId.new ls_id
|
326
|
+
end
|
275
327
|
lsa
|
276
328
|
end
|
277
329
|
|
@@ -282,7 +334,6 @@ module OSPFv2
|
|
282
334
|
# -1 self older than other
|
283
335
|
# 0 self equivalent to other
|
284
336
|
# +1 self newer than other
|
285
|
-
# FIXME: rename to 'newer'
|
286
337
|
# TODO: compare advr router id.
|
287
338
|
def <=>(other)
|
288
339
|
raise RuntimeError unless self.key == other.key
|
@@ -316,7 +367,7 @@ module OSPFv2
|
|
316
367
|
return unless advertised_routers.has?(advertising_router)
|
317
368
|
return unless refresh?(refresh_time)
|
318
369
|
@sequence_number = SequenceNumber.new(seqn) if seqn
|
319
|
-
@sequence_number
|
370
|
+
@sequence_number.incr
|
320
371
|
@ls_age = LsAge.new
|
321
372
|
retransmit
|
322
373
|
self
|
@@ -324,7 +375,7 @@ module OSPFv2
|
|
324
375
|
|
325
376
|
def force_refresh(seqn)
|
326
377
|
@sequence_number = SequenceNumber.new(seqn) if seqn
|
327
|
-
@sequence_number
|
378
|
+
@sequence_number.incr
|
328
379
|
@ls_age = LsAge.new
|
329
380
|
retransmit
|
330
381
|
self
|
@@ -346,8 +397,8 @@ module OSPFv2
|
|
346
397
|
end
|
347
398
|
|
348
399
|
def method_missing(method, *args, &block)
|
349
|
-
puts "
|
350
|
-
|
400
|
+
# puts "&&&&& #{self.class}: method: #{method}"
|
401
|
+
# p caller[0]
|
351
402
|
if method == :to_s_junos
|
352
403
|
:to_s_default
|
353
404
|
else
|
@@ -385,19 +436,7 @@ module OSPFv2
|
|
385
436
|
puts "*** checksum error ? #{cheksum(s[2..-1], 0)}"
|
386
437
|
end
|
387
438
|
end
|
388
|
-
|
389
|
-
def klass_to_ls_type
|
390
|
-
case self.class.to_s
|
391
|
-
when /Router/ ; 1
|
392
|
-
when /Network/ ; 2
|
393
|
-
when /Summary/ ; 3
|
394
|
-
else
|
395
|
-
1
|
396
|
-
end
|
397
|
-
end
|
398
|
-
|
399
|
-
MODX=4102
|
400
|
-
|
439
|
+
|
401
440
|
def cheksum(mess, k=0)
|
402
441
|
len = mess.size
|
403
442
|
|
@@ -418,7 +457,7 @@ module OSPFv2
|
|
418
457
|
c0 = c0%255
|
419
458
|
c1 = c1%255
|
420
459
|
|
421
|
-
ip = (c1
|
460
|
+
ip = (c1<<8) + c0
|
422
461
|
|
423
462
|
if k>0
|
424
463
|
iq = ((len-k)*c0 - c1)%255 ; iq += 255 if (iq <= 0)
|
@@ -435,4 +474,3 @@ module OSPFv2
|
|
435
474
|
end
|
436
475
|
|
437
476
|
load "../../../test/ospfv2/lsa/#{ File.basename($0.gsub(/.rb/,'_test.rb'))}" if __FILE__ == $0
|
438
|
-
|
data/lib/lsa/lsa_base.rb
ADDED
@@ -0,0 +1,430 @@
|
|
1
|
+
|
2
|
+
=begin rdoc
|
3
|
+
|
4
|
+
A.4.1 The LSA header
|
5
|
+
|
6
|
+
All LSAs begin with a common 20 byte header. This header contains
|
7
|
+
enough information to uniquely identify the LSA (LS type, Link State
|
8
|
+
ID, and Advertising Router). Multiple instances of the LSA may
|
9
|
+
exist in the routing domain at the same time. It is then necessary
|
10
|
+
to determine which instance is more recent. This is accomplished by
|
11
|
+
examining the LS age, LS sequence number and LS checksum fields that
|
12
|
+
are also contained in the LSA header.
|
13
|
+
|
14
|
+
|
15
|
+
0 1 2 3
|
16
|
+
0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1
|
17
|
+
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
|
18
|
+
| LS age | Options | LS type |
|
19
|
+
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
|
20
|
+
| Link State ID |
|
21
|
+
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
|
22
|
+
| Advertising Router |
|
23
|
+
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
|
24
|
+
| LS sequence number |
|
25
|
+
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
|
26
|
+
| LS checksum | length |
|
27
|
+
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
|
28
|
+
|
29
|
+
|
30
|
+
|
31
|
+
0 1 2 3
|
32
|
+
0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1
|
33
|
+
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
|
34
|
+
| LS age | Options | 9, 10, or 11 |
|
35
|
+
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
|
36
|
+
| Opaque Type | Opaque ID |
|
37
|
+
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
|
38
|
+
| Advertising Router |
|
39
|
+
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
|
40
|
+
| LS Sequence Number |
|
41
|
+
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
|
42
|
+
| LS checksum | Length |
|
43
|
+
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
|
44
|
+
| |
|
45
|
+
+ +
|
46
|
+
| Opaque Information |
|
47
|
+
+ +
|
48
|
+
| ... |
|
49
|
+
#
|
50
|
+
|
51
|
+
|
52
|
+
|
53
|
+
LS age
|
54
|
+
The time in seconds since the LSA was originated.
|
55
|
+
|
56
|
+
Options
|
57
|
+
The optional capabilities supported by the described portion of
|
58
|
+
the routing domain. OSPF's optional capabilities are documented
|
59
|
+
in Section A.2.
|
60
|
+
|
61
|
+
LS type
|
62
|
+
The type of the LSA. Each LSA type has a separate advertisement
|
63
|
+
format. The LSA types defined in this memo are as follows (see
|
64
|
+
Section 12.1.3 for further explanation):
|
65
|
+
|
66
|
+
|
67
|
+
LS Type Description
|
68
|
+
___________________________________
|
69
|
+
1 Router-LSAs
|
70
|
+
2 Network-LSAs
|
71
|
+
3 Summary-LSAs (IP network)
|
72
|
+
4 Summary-LSAs (ASBR)
|
73
|
+
5 AS-external-LSAs
|
74
|
+
|
75
|
+
|
76
|
+
Link State ID
|
77
|
+
This field identifies the portion of the internet environment
|
78
|
+
that is being described by the LSA. The contents of this field
|
79
|
+
depend on the LSA's LS type. For example, in network-LSAs the
|
80
|
+
Link State ID is set to the IP interface address of the
|
81
|
+
network's Designated Router (from which the network's IP address
|
82
|
+
can be derived). The Link State ID is further discussed in
|
83
|
+
Section 12.1.4.
|
84
|
+
|
85
|
+
Advertising Router
|
86
|
+
The Router ID of the router that originated the LSA. For
|
87
|
+
example, in network-LSAs this field is equal to the Router ID of
|
88
|
+
the network's Designated Router.
|
89
|
+
|
90
|
+
LS sequence number
|
91
|
+
Detects old or duplicate LSAs. Successive instances of an LSA
|
92
|
+
are given successive LS sequence numbers. See Section 12.1.6
|
93
|
+
for more details.
|
94
|
+
|
95
|
+
LS checksum
|
96
|
+
The Fletcher checksum of the complete contents of the LSA,
|
97
|
+
including the LSA header but excluding the LS age field. See
|
98
|
+
Section 12.1.7 for more details.
|
99
|
+
|
100
|
+
length
|
101
|
+
The length in bytes of the LSA. This includes the 20 byte LSA
|
102
|
+
header.
|
103
|
+
|
104
|
+
=end
|
105
|
+
|
106
|
+
require 'infra/ospf_common'
|
107
|
+
require 'infra/ospf_constants'
|
108
|
+
require 'ie/id'
|
109
|
+
require 'ie/ls_type'
|
110
|
+
require 'ie/ls_age'
|
111
|
+
require 'ie/sequence_number'
|
112
|
+
require 'ie/options'
|
113
|
+
require 'ls_db/advertised_routers'
|
114
|
+
|
115
|
+
require 'infra/to_s'
|
116
|
+
|
117
|
+
module OSPFv2
|
118
|
+
|
119
|
+
class Lsa_Base
|
120
|
+
include Comparable
|
121
|
+
|
122
|
+
AdvertisingRouter = Class.new(Id)
|
123
|
+
LsId = Class.new(Id)
|
124
|
+
LsAge = Class.new(LsAge)
|
125
|
+
|
126
|
+
class << self
|
127
|
+
def new_ntop(arg)
|
128
|
+
lsa = new
|
129
|
+
if arg.is_a?(String)
|
130
|
+
lsa.parse(arg)
|
131
|
+
elsif arg.is_a?(self)
|
132
|
+
lsa.parse arg.encode
|
133
|
+
else
|
134
|
+
raise ArgumentError, "Invalid Argument: #{arg.inspect}"
|
135
|
+
end
|
136
|
+
lsa
|
137
|
+
end
|
138
|
+
end
|
139
|
+
|
140
|
+
include OSPFv2::Common
|
141
|
+
include OSPFv2::Constant
|
142
|
+
|
143
|
+
# FIXME: when adding LSA in LSDB should be acked when init, rxmt otherwise ....
|
144
|
+
def ack
|
145
|
+
@_rxmt_=false
|
146
|
+
end
|
147
|
+
def retransmit
|
148
|
+
@_rxmt_=true
|
149
|
+
end
|
150
|
+
def is_acked?
|
151
|
+
@_rxmt_ == false
|
152
|
+
end
|
153
|
+
alias :acked? :is_acked?
|
154
|
+
alias :ack? :acked?
|
155
|
+
|
156
|
+
attr_reader :ls_age, :options, :ls_type
|
157
|
+
attr_reader :ls_id
|
158
|
+
attr_reader :advertising_router
|
159
|
+
attr_reader :sequence_number
|
160
|
+
|
161
|
+
attr_writer_delegate :advertising_router, :ls_id, :ls_age
|
162
|
+
|
163
|
+
def initialize(arg={})
|
164
|
+
arg = arg.dup
|
165
|
+
@ls_age = LsAge.new
|
166
|
+
@sequence_number = SequenceNumber.new
|
167
|
+
@options = Options.new
|
168
|
+
@ls_type = LsType.new klass_to_ls_type
|
169
|
+
@ls_id = LsId.new
|
170
|
+
@advertising_router = AdvertisingRouter.new
|
171
|
+
@_length = 0
|
172
|
+
@_rxmt_ = false
|
173
|
+
|
174
|
+
if arg.is_a?(Hash)
|
175
|
+
set arg
|
176
|
+
elsif arg.is_a?(String)
|
177
|
+
parse arg
|
178
|
+
elsif arg.is_a?(self.class)
|
179
|
+
parse arg.encode
|
180
|
+
else
|
181
|
+
raise ArgumentError, "Invalid Argument: #{arg.inspect}"
|
182
|
+
end
|
183
|
+
|
184
|
+
end
|
185
|
+
|
186
|
+
def sequence_number=(seqn)
|
187
|
+
@sequence_number = SequenceNumber.new(seqn)
|
188
|
+
end
|
189
|
+
|
190
|
+
def to_s_default
|
191
|
+
len = encode.size
|
192
|
+
ls_type_to_s = ls_type.to_sym.to_s.chomp('_lsa')
|
193
|
+
sprintf("%-4.0d 0x%2.2x %-8s %-15.15s %-15.15s 0x%8.8x 0x%4.4x %-7d",
|
194
|
+
ls_age.to_i, options.to_i, ls_type.to_s_short, ls_id.to_ip, advertising_router.to_ip, seqn.to_I,csum_to_i,len)
|
195
|
+
end
|
196
|
+
alias :to_s_dd :to_s_default
|
197
|
+
|
198
|
+
def to_s_verbose
|
199
|
+
len = encode.size
|
200
|
+
s=[]
|
201
|
+
s << self.class.to_s.split('::').last + ":"
|
202
|
+
s << ls_age.to_s
|
203
|
+
s << options.to_s
|
204
|
+
s << ls_type.to_s
|
205
|
+
s << advertising_router.to_s
|
206
|
+
s << ls_id.to_s
|
207
|
+
s << "SequenceNumber: " + sequence_number.to_s
|
208
|
+
s << "LS checksum: #{format "%4x", csum_to_i}" if @_csum
|
209
|
+
s << "length: #{@_size.unpack('n')}" if @_size
|
210
|
+
s.join("\n ")
|
211
|
+
end
|
212
|
+
|
213
|
+
alias :to_s_header :to_s
|
214
|
+
|
215
|
+
def to_s_junos
|
216
|
+
len = encode.size
|
217
|
+
sprintf("%-7s %-1.1s%-15.15s %-15.15s 0x%8.8x %4.0d 0x%2.2x 0x%4.4x %3d", LsType.to_junos(ls_type.to_i), '', ls_id.to_ip, advertising_router.to_ip, seqn.to_I, ls_age.to_i, options.to_i, csum_to_i, len)
|
218
|
+
end
|
219
|
+
include OSPFv2::TO_S
|
220
|
+
alias :to_s_junos_verbose :to_s_junos
|
221
|
+
|
222
|
+
def encode_header
|
223
|
+
header = []
|
224
|
+
header << ls_age.encode
|
225
|
+
header << [options.to_i].pack('C')
|
226
|
+
header << ls_type.encode
|
227
|
+
header << ls_id.encode
|
228
|
+
header << advertising_router.encode
|
229
|
+
header << sequence_number.encode
|
230
|
+
header << [''].pack('a4')
|
231
|
+
header.join
|
232
|
+
end
|
233
|
+
alias :header_encode :encode_header
|
234
|
+
|
235
|
+
def header_lsa
|
236
|
+
self.class.new self
|
237
|
+
end
|
238
|
+
|
239
|
+
def encode(content='')
|
240
|
+
lsa = []
|
241
|
+
lsa << encode_header
|
242
|
+
lsa << content
|
243
|
+
lsa = lsa.join
|
244
|
+
lsa[18..19]= @_size = [lsa.size].pack('n')
|
245
|
+
lsa[16..17]= self.csum = cheksum(lsa[2..-1], 15).pack('CC')
|
246
|
+
lsa
|
247
|
+
end
|
248
|
+
|
249
|
+
def encode_request
|
250
|
+
req=[]
|
251
|
+
req << ls_id.encode
|
252
|
+
req << ls_type.encode
|
253
|
+
req << @advertising_router.encode
|
254
|
+
req.join
|
255
|
+
end
|
256
|
+
|
257
|
+
def parse(s)
|
258
|
+
validate_checksum(s)
|
259
|
+
ls_age, options, ls_type, ls_id, advr, seqn, csum, length, lsa = s.unpack('nCCNNNnna*')
|
260
|
+
@ls_type = LsType.new ls_type
|
261
|
+
@options = Options.new options
|
262
|
+
@ls_age = LsAge.new ls_age
|
263
|
+
@sequence_number = SequenceNumber.new seqn
|
264
|
+
@advertising_router = AdvertisingRouter.new advr
|
265
|
+
@ls_id = LsId.new ls_id
|
266
|
+
lsa
|
267
|
+
end
|
268
|
+
|
269
|
+
def key
|
270
|
+
[ls_type.to_i, ls_id.to_i, advertising_router.to_i]
|
271
|
+
end
|
272
|
+
|
273
|
+
# -1 self older than other
|
274
|
+
# 0 self equivalent to other
|
275
|
+
# +1 self newer than other
|
276
|
+
# FIXME: rename to 'newer'
|
277
|
+
# TODO: compare advr router id.
|
278
|
+
def <=>(other)
|
279
|
+
raise RuntimeError unless self.key == other.key
|
280
|
+
if self.sequence_number < other.sequence_number
|
281
|
+
# puts "*** jme: our lsa older than other: our seq less than other seq ***"
|
282
|
+
-1
|
283
|
+
elsif self.sequence_number > other.sequence_number
|
284
|
+
# puts "*** jme: our lsa newer than other: our seq greater than other seq ***"
|
285
|
+
+1
|
286
|
+
else
|
287
|
+
if self.csum_to_i < other.csum_to_i
|
288
|
+
# puts "*** jme: our lsa older than other: our csum less than other csum ***"
|
289
|
+
-1
|
290
|
+
elsif self.csum_to_i > other.csum_to_i
|
291
|
+
# puts "*** jme: our lsa newer than other: our csum greater than other csum ***"
|
292
|
+
+1
|
293
|
+
else
|
294
|
+
if (self.ls_age != other.ls_age and other.ls_age >= MaxAge) or
|
295
|
+
((other.ls_age - self.ls_age) > OSPFv2::MaxAgeDiff)
|
296
|
+
# puts "*** jme: our lsa newer than other: age diff < maxage diff: #{(other.ls_age - self.ls_age)} ***"
|
297
|
+
+1
|
298
|
+
else
|
299
|
+
# puts "*** jme: same lsa: age diff < maxage diff: #{(other.ls_age - self.ls_age)} ***"
|
300
|
+
0
|
301
|
+
end
|
302
|
+
end
|
303
|
+
end
|
304
|
+
end
|
305
|
+
|
306
|
+
def refresh(advertised_routers, refresh_time, seqn=nil)
|
307
|
+
return unless advertised_routers.has?(advertising_router)
|
308
|
+
return unless refresh?(refresh_time)
|
309
|
+
@sequence_number = SequenceNumber.new(seqn) if seqn
|
310
|
+
@sequence_number + 1
|
311
|
+
@ls_age = LsAge.new
|
312
|
+
retransmit
|
313
|
+
self
|
314
|
+
end
|
315
|
+
|
316
|
+
def force_refresh(seqn)
|
317
|
+
@sequence_number = SequenceNumber.new(seqn) if seqn
|
318
|
+
@sequence_number + 1
|
319
|
+
@ls_age = LsAge.new
|
320
|
+
retransmit
|
321
|
+
self
|
322
|
+
end
|
323
|
+
|
324
|
+
def maxage
|
325
|
+
ls_age.maxage and retransmit
|
326
|
+
self
|
327
|
+
end
|
328
|
+
|
329
|
+
def maxaged?
|
330
|
+
@ls_age.maxaged?
|
331
|
+
end
|
332
|
+
|
333
|
+
def to_hash
|
334
|
+
h = super
|
335
|
+
h.delete(:time)
|
336
|
+
h
|
337
|
+
end
|
338
|
+
|
339
|
+
def method_missing(method, *args, &block)
|
340
|
+
# puts "&&&&& #{self.class}: method: #{method}"
|
341
|
+
# p caller[0]
|
342
|
+
if method == :to_s_junos
|
343
|
+
:to_s_default
|
344
|
+
else
|
345
|
+
super
|
346
|
+
end
|
347
|
+
end
|
348
|
+
|
349
|
+
protected
|
350
|
+
|
351
|
+
def csum_to_i
|
352
|
+
@_csum.unpack('n')[0]
|
353
|
+
rescue Exception => e
|
354
|
+
encode
|
355
|
+
retry
|
356
|
+
end
|
357
|
+
|
358
|
+
|
359
|
+
private
|
360
|
+
|
361
|
+
def csum=(value)
|
362
|
+
raise if value.is_a?(Fixnum)
|
363
|
+
@_csum=value
|
364
|
+
end
|
365
|
+
|
366
|
+
def refresh?(refresh_time)
|
367
|
+
ls_age.to_i > refresh_time
|
368
|
+
end
|
369
|
+
|
370
|
+
def seqn
|
371
|
+
@sequence_number
|
372
|
+
end
|
373
|
+
|
374
|
+
def validate_checksum(s)
|
375
|
+
if ! cheksum(s[2..-1], 0) == [0,0]
|
376
|
+
puts "*** checksum error ? #{cheksum(s[2..-1], 0)}"
|
377
|
+
end
|
378
|
+
end
|
379
|
+
|
380
|
+
#FIXME
|
381
|
+
def klass_to_ls_type
|
382
|
+
case self.class
|
383
|
+
when OSPFv2::Router ; 1
|
384
|
+
when OSPFv2::Network ; 2
|
385
|
+
when OSPFv2::Summary ; 3
|
386
|
+
# when AsExternal ; 5
|
387
|
+
else
|
388
|
+
raise
|
389
|
+
end
|
390
|
+
end
|
391
|
+
|
392
|
+
MODX=4102
|
393
|
+
|
394
|
+
def cheksum(mess, k=0)
|
395
|
+
len = mess.size
|
396
|
+
|
397
|
+
if (k>0)
|
398
|
+
mess[k-1] = [0].pack('C')
|
399
|
+
mess[k] = [0].pack('C')
|
400
|
+
end
|
401
|
+
|
402
|
+
c0,c1,n=0,0,0
|
403
|
+
|
404
|
+
s = mess.dup
|
405
|
+
while s.size>0 and n <= 4102 # MODX
|
406
|
+
n +=1
|
407
|
+
c0 += s.slice!(0,1).unpack('C')[0]
|
408
|
+
c1 +=c0
|
409
|
+
end
|
410
|
+
|
411
|
+
c0 = c0%255
|
412
|
+
c1 = c1%255
|
413
|
+
|
414
|
+
ip = (c1 <<8) + c0
|
415
|
+
|
416
|
+
if k>0
|
417
|
+
iq = ((len-k)*c0 - c1)%255 ; iq += 255 if (iq <= 0)
|
418
|
+
ir = (510 - c0 - iq) ; ir += -255 if (ir>255)
|
419
|
+
return [iq,ir]
|
420
|
+
else
|
421
|
+
[c0,c1]
|
422
|
+
end
|
423
|
+
|
424
|
+
end
|
425
|
+
|
426
|
+
end
|
427
|
+
|
428
|
+
end
|
429
|
+
|
430
|
+
load "../../../test/ospfv2/lsa/#{ File.basename($0.gsub(/.rb/,'_test.rb'))}" if __FILE__ == $0
|