Class: OSPFv2::Lsa

Inherits:
Object show all
Includes:
Comparable, Common, Constant
Defined in:
lib/ls_db/link_state_database_links.rb,
lib/lsa/lsa.rb,
lib/lsa/lsa_factory.rb

Overview

FIXME extend class Lsa instead…

Defined Under Namespace

Classes: Header

Constant Summary collapse

AdvertisingRouter =
Class.new(Id) do
  def to_s_ios
    "Advertising Router: " + to_ip
  end
end
LsId =
Class.new(Id) do
  def to_s_ios
    "Link State ID: " + to_ip
  end
end
LsAge =
Class.new(LsAge)
MODX =
4102

Constants included from Constant

Constant::DATABASE_DESCRIPTION, Constant::HELLO, Constant::LINK_STATE_ACKNOWLEDGEMENT, Constant::LINK_STATE_REQUEST, Constant::LINK_STATE_UPDATE, Constant::V2, Constant::V3

Instance Attribute Summary collapse

Class Method Summary collapse

Instance Method Summary collapse

Methods included from Common

#ivar_to_klassname, #ivars, #set

Constructor Details

#initialize(arg = {}) ⇒ Lsa

Returns a new instance of Lsa.



223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
# File 'lib/lsa/lsa.rb', line 223

def initialize(arg={})
  arg = arg.dup
  
  @ls_age = LsAge.new
  @sequence_number = SequenceNumber.new
  @options = Options.new
  @ls_id = LsId.new
  @ls_id = nil
  if is_opaque?
    @opaque_id   = OpaqueId.new
    @opaque_type = OpaqueType.new
  else
    @ls_id=LsId.new
  end
  @advertising_router = AdvertisingRouter.new
  @_length = 0
  @_rxmt_ = false
  
  if arg.is_a?(Hash)
    set arg
  elsif arg.is_a?(String)
    parse arg
  elsif arg.is_a?(self.class)
    parse arg.encode
  else        
    raise ArgumentError, "Invalid Argument: #{arg.inspect}"
  end
  
end

Dynamic Method Handling

This class handles dynamic methods through the method_missing method

#method_missing(method, *args, &block) ⇒ Object



492
493
494
495
496
497
498
499
500
501
502
# File 'lib/lsa/lsa.rb', line 492

def method_missing(method, *args, &block)
  if method.to_s =~ /^to_s_(ios|junos)_verbose/
    p " #{self.class}: #{method} IS MISSING!!! defaulting to :to_s_verbose"
    __send__ :to_s_verbose, *args, &block
  elsif method.to_s =~ /^to_s_(ios|junos)$/
    p $1
    __send__ :to_s, *args, &block
  else
    raise "missing: #{method} #{caller[0..2]}"
  end
end

Instance Attribute Details

#advertising_routerObject (readonly)

Returns the value of attribute advertising_router.



211
212
213
# File 'lib/lsa/lsa.rb', line 211

def advertising_router
  @advertising_router
end

#ls_ageObject (readonly)

Returns the value of attribute ls_age.



209
210
211
# File 'lib/lsa/lsa.rb', line 209

def ls_age
  @ls_age
end

#ls_idObject (readonly)

Returns the value of attribute ls_id.



210
211
212
# File 'lib/lsa/lsa.rb', line 210

def ls_id
  @ls_id
end

#opaque_idObject (readonly)

Returns the value of attribute opaque_id.



213
214
215
# File 'lib/lsa/lsa.rb', line 213

def opaque_id
  @opaque_id
end

#opaque_typeObject (readonly)

Returns the value of attribute opaque_type.



213
214
215
# File 'lib/lsa/lsa.rb', line 213

def opaque_type
  @opaque_type
end

#optionsObject (readonly)

Returns the value of attribute options.



209
210
211
# File 'lib/lsa/lsa.rb', line 209

def options
  @options
end

#sequence_numberObject

Returns the value of attribute sequence_number.



212
213
214
# File 'lib/lsa/lsa.rb', line 212

def sequence_number
  @sequence_number
end

Class Method Details

.factory(arg) ⇒ Object



33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
# File 'lib/lsa/lsa_factory.rb', line 33

def factory(arg)
  if arg.is_a?(String)
    return unless (arg.size>=20)
    case arg.slice(3,1).unpack('C')[0]
    when 1 ; OSPFv2::Router.new_ntop(arg)
    when 2 ; OSPFv2::Network.new_ntop(arg)
    when 3 ; OSPFv2::Summary.new_ntop(arg)
    when 4 ; OSPFv2::AsbrSummary.new_ntop(arg)
    when 5 ; OSPFv2::AsExternal.new_ntop(arg)
    when 7 ; OSPFv2::AsExternal7.new_ntop(arg)
    when 9,10,11
      _, opaque_type = arg.unpack('NC')
      case opaque_type
      when 1
        OSPFv2::TrafficEngineering.new_ntop(arg)
      end
    else 
      raise
    end
  elsif arg.is_a?(Hash)
    case arg[:ls_type]
    when :router        ; OSPFv2::Router.new_hash(arg)
    when :network       ; OSPFv2::Network.new_hash(arg)
    when :summary       ; OSPFv2::Summary.new_hash(arg)
    when :asbr_summary  ; OSPFv2::AsbrSummary.new_hash(arg)
    when :as_external   ; OSPFv2::AsExternal.new_hash(arg)
    when :as_external7  ; OSPFv2::AsExternal7.new_hash(arg)
    when :area, :link_local, :domain
      case arg[:opaque_type]
      when 1, :te_lsa
        OSPFv2::TrafficEngineering.new_hash(arg)
      else
        raise
      end
    else
      raise
    end
  elsif arg.is_a?(Lsa)
    factory(arg.encode)
  end
end

.new_ntop(arg) ⇒ Object



177
178
179
180
181
182
183
184
185
186
187
# File 'lib/lsa/lsa.rb', line 177

def new_ntop(arg)
  lsa = new
  if arg.is_a?(String)
    lsa.parse(arg)
  elsif arg.is_a?(self)
    lsa.parse arg.encode
  else
    raise ArgumentError, "Invalid Argument: #{arg.inspect}"
  end
  lsa
end

Instance Method Details

#<=>(other) ⇒ Object

-1 self older than other

0  self equivalent to other

+1 self newer than other TODO: compare advr router id.

Raises:

  • (RuntimeError)


423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
# File 'lib/lsa/lsa.rb', line 423

def <=>(other)
  raise RuntimeError unless self.key == other.key
  if self.sequence_number < other.sequence_number
    # puts "*** jme: our lsa older than other: our seq less than other seq ***"        
    -1
  elsif self.sequence_number > other.sequence_number
    # puts "*** jme: our lsa newer than other: our seq greater than other seq ***"        
    +1
  else
    if self.csum_to_i < other.csum_to_i
      # puts "*** jme: our lsa older than other: our csum less than other csum ***"        
      -1
    elsif self.csum_to_i > other.csum_to_i
      # puts "*** jme: our lsa newer than other: our csum greater than other csum ***"        
      +1
    else
      if (self.ls_age != other.ls_age and other.ls_age >= MaxAge) or
        ((other.ls_age - self.ls_age) > OSPFv2::MaxAgeDiff)
        # puts "*** jme: our lsa newer than other: age diff < maxage diff: #{(other.ls_age - self.ls_age)} ***"
        +1
      else
        # puts "*** jme: same lsa: age diff < maxage diff: #{(other.ls_age - self.ls_age)} ***"
        0
      end
    end
  end
end

#ackObject



193
194
195
# File 'lib/lsa/lsa.rb', line 193

def ack
  @_rxmt_=false
end

#encode(content = '') ⇒ Object



380
381
382
383
384
385
386
387
388
# File 'lib/lsa/lsa.rb', line 380

def encode(content='')
  lsa = []
  lsa << encode_header
  lsa << content
  lsa = lsa.join
  lsa[18..19]= @_size = [lsa.size].pack('n')
  lsa[16..17]= self.csum = cheksum(lsa[2..-1], 15).pack('CC')
  lsa
end

#encode_headerObject Also known as: header_encode



351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
# File 'lib/lsa/lsa.rb', line 351

def encode_header
  header = []
  header << ls_age.encode
  header << [options.to_i].pack('C')
  header << ls_type.encode
  if is_opaque?
    header << @opaque_type.encode
    header << @opaque_id.encode
  else
    header << ls_id.encode
  end
  header << advertising_router.encode
  header << sequence_number.encode
  header << [''].pack('a4')
  header.join
rescue => e
  p ls_age
  p ls_type
  p ls_id
  p advertising_router
  p sequence_number
  raise
end

#encode_requestObject



390
391
392
393
394
395
396
# File 'lib/lsa/lsa.rb', line 390

def encode_request
  req=[]
  req << ls_id.encode
  req << ls_type.encode
  req << @advertising_router.encode
  req.join
end


38
39
40
# File 'lib/ls_db/link_state_database_links.rb', line 38

def find_lsa_from_link(id)
  all.find_all { |l| l.lsdb_link_id==id  }
end

#force_refresh(seqn) ⇒ Object



461
462
463
464
465
466
467
# File 'lib/lsa/lsa.rb', line 461

def force_refresh(seqn)
  @sequence_number = SequenceNumber.new(seqn) if seqn
  @sequence_number.incr
  @ls_age = LsAge.new
  retransmit
  self
end

#header_lsaObject



376
377
378
# File 'lib/lsa/lsa.rb', line 376

def header_lsa
  self.class.new self
end

#is_acked?Boolean Also known as: acked?

returns

true  if lsa has been acked by neighbor
false otherwise

Returns:

  • (Boolean)


203
204
205
# File 'lib/lsa/lsa.rb', line 203

def is_acked?
  @_rxmt_ == false
end

#is_opaque?Boolean

Returns:

  • (Boolean)


347
348
349
# File 'lib/lsa/lsa.rb', line 347

def is_opaque?
  ls_type.is_opaque?
end

#keyObject



415
416
417
# File 'lib/lsa/lsa.rb', line 415

def key
  [ls_type.to_i, ls_id.to_i, advertising_router.to_i]
end

#ls_typeObject



253
254
255
# File 'lib/lsa/lsa.rb', line 253

def ls_type
  @ls_type ||= LsType.new(1)
end


32
33
34
# File 'lib/ls_db/link_state_database_links.rb', line 32

def lsdb_link_id
  @_lsdb_link_id
end


35
36
37
# File 'lib/ls_db/link_state_database_links.rb', line 35

def lsdb_link_id=(val)
  @_lsdb_link_id= val
end

#maxageObject



477
478
479
480
# File 'lib/lsa/lsa.rb', line 477

def maxage
  ls_age.maxage and retransmit
  self
end

#maxaged?Boolean

Returns:

  • (Boolean)


482
483
484
# File 'lib/lsa/lsa.rb', line 482

def maxaged?
  @ls_age.maxaged?
end

#parse(s) ⇒ Object



398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
# File 'lib/lsa/lsa.rb', line 398

def parse(s)
  validate_checksum(s)
  ls_age, options, ls_type, ls_id, advr, seqn, csum, length, lsa = s.unpack('nCCNNNnna*')
  @ls_type = LsType.new ls_type
  @options = Options.new options
  @ls_age = LsAge.new ls_age
  @sequence_number = SequenceNumber.new seqn
  @advertising_router = AdvertisingRouter.new advr
  if is_opaque?
    @opaque_type = OpaqueType.new(ls_id>>24)
    @opaque_id = OpaqueId.new(ls_id & 0xffffff)
  else
    @ls_id = LsId.new ls_id
  end
  lsa
end

#refresh(advertised_routers, refresh_time, seqn = nil) ⇒ Object



451
452
453
454
455
456
457
458
459
# File 'lib/lsa/lsa.rb', line 451

def refresh(advertised_routers, refresh_time, seqn=nil)
  return unless advertised_routers.has?(advertising_router)
  return unless refresh?(refresh_time)
  @sequence_number = SequenceNumber.new(seqn) if seqn
  @sequence_number.incr
  @ls_age = LsAge.new
  retransmit
  self
end

#refresh2(advertised_routers, age) ⇒ Object



469
470
471
472
473
474
475
# File 'lib/lsa/lsa.rb', line 469

def refresh2(advertised_routers, age)
  return unless advertised_routers.has?(advertising_router)
  @sequence_number.incr
  @ls_age = LsAge.new(age)
  retransmit
  self
end

#retransmitObject



196
197
198
# File 'lib/lsa/lsa.rb', line 196

def retransmit
  @_rxmt_=true
end

#to_hashObject



486
487
488
489
490
# File 'lib/lsa/lsa.rb', line 486

def to_hash
  h = super
  h.delete(:time)
  h
end

#to_sObject Also known as: to_s_dd, to_s_header



270
271
272
273
274
275
276
277
278
279
280
# File 'lib/lsa/lsa.rb', line 270

def to_s
  len = encode.size
  if is_opaque?
    ls_id = Id.new_ntoh(@opaque_type.encode + @opaque_id.encode)
    sprintf("%-4.0d  0x%2.2x  %-8s  %-15.15s %-15.15s 0x%8.8x  0x%4.4x   %-7d", 
    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)
  else
    sprintf("%-4.0d  0x%2.2x  %-8s  %-15.15s %-15.15s 0x%8.8x  0x%4.4x   %-7d", 
    ls_age.to_i, options.to_i, ls_type.to_s_short, self.ls_id.to_ip, advertising_router.to_ip, seqn.to_I,csum_to_i,len)
  end
end

#to_s_iosObject



261
262
263
264
265
266
267
268
# File 'lib/lsa/lsa.rb', line 261

def to_s_ios
  sprintf("%-15.15s %-15.15s %-4.0d        0x%8.8X 0x%6.6X ", 
        is_opaque? ? ls_id = Id.new_ntoh(@opaque_type.encode + @opaque_id.encode).to_ip : self.ls_id.to_ip, 
        advertising_router.to_ip, 
        ls_age.to_i, 
        seqn.to_I, 
        csum_to_i)
end

#to_s_ios_verboseObject

LS age: 44 Options: (No TOS-capability, No DC) LS Type: Opaque Area Link Link State ID: 1.0.0.0 Opaque Type: 1 Opaque ID: 0 Advertising Router: 0.0.0.3 LS Seq Number: 80000001 Checksum: 0xD12 Length: 116 Fragment number : 0



294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
# File 'lib/lsa/lsa.rb', line 294

def to_s_ios_verbose
  len = encode.size
  s = []
  s << ''
  s << ls_age.to_s_ios
  s << options.to_s_ios
  s << ls_type.to_s_ios
  if is_opaque?
    s << "Opaque Type: #{opaque_type.to_i}"
    s << "Opaque ID: #{opaque_id.to_i}"
  else
    s << "#{ls_id.to_s_ios} #{summary? ? "(summary Network Number)" : ''}"
  end
  s << advertising_router.to_s_ios
  s << sequence_number.to_s_ios
  s << "Checksum: #{format "0x%4X", csum_to_i}" if @_csum
  s << "Length: #{len}"
  s.join("\n  ")
end

#to_s_junosObject



335
336
337
338
339
340
341
# File 'lib/lsa/lsa.rb', line 335

def to_s_junos
  len = encode.size
  if is_opaque?
  else
    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)
  end
end

#to_s_junos_verboseObject



343
344
345
# File 'lib/lsa/lsa.rb', line 343

def to_s_junos_verbose
  to_s_junos
end

#to_s_verboseObject



314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
# File 'lib/lsa/lsa.rb', line 314

def to_s_verbose
  len = encode.size
  s=[]
  s << self.class.to_s.split('::').last + ":"
  s << ls_age.to_s
  s << options.to_s
  s << ls_type.to_s
  s << advertising_router.to_s
  if is_opaque?
    # s << ls_id.to_s
  else
    s << ls_id.to_s
  end
  s << "SequenceNumber: " + sequence_number.to_s
  s << "LS checksum: #{format "%4x", csum_to_i}" if @_csum
  s << "length: #{@_size.unpack('n')}" if @_size
  s.join("\n   ")
end