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.
@@ -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