ospfv2 0.0.1 → 0.0.2

Sign up to get free protection for your applications and to get access to all the features.
@@ -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.to_ary(prefix)
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 + router_id
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 + router_id
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.to_ary(prefix)
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 + router_id
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
- p name
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
- Netmask = Class.new(OSPFv2::Id)
159
- ExternalRoute = Class.new(OSPFv2::ExternalRoute)
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
- super
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
- ExternalRoute = Class.new(OSPFv2::ExternalRoute)
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
- if arg.is_a?(Hash)
312
- arg = fix_hash(arg).merge!({:ls_type => :as_external_lsa,})
313
- end
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
- AdvertisingRouter = Class.new(Id)
122
- LsId = Class.new(Id)
123
- LsAge = Class.new(LsAge)
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, :ls_type
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
- ls_type_to_s = ls_type.to_sym.to_s.chomp('_lsa')
192
- sprintf("%-4.0d 0x%2.2x %-8s %-15.15s %-15.15s 0x%8.8x 0x%4.4x %-7d",
193
- 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)
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
- s << ls_id.to_s
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
- 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)
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
- # def to_s(*args)
222
- # return to_s_default(*args) unless defined?($style)
223
- # case $style
224
- # when :junos ; to_s_junos(*args)
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
- header << ls_id.encode
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
- @ls_id = LsId.new ls_id
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 + 1
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 + 1
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 "Method missing in #{self.class}: method: #{method}"
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 <<8) + c0
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
-
@@ -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