ospfv2 0.0.1

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.
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,393 @@
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 'lsa/lsa'
24
+
25
+ require 'ie/metric'
26
+ require 'ie/mt_metric'
27
+ require 'ie/id'
28
+
29
+
30
+ module OSPFv2
31
+
32
+ Netmask = Class.new(Id)
33
+
34
+ class Summary_Base < Lsa
35
+
36
+ attr_reader :metric, :netmask, :mt_metrics
37
+
38
+ def initialize(arg={})
39
+ @netmask=nil
40
+ @metric=nil
41
+ @mt_metrics=[]
42
+ super
43
+ end
44
+
45
+ def mt_metrics=(val)
46
+ [val].flatten.each { |x| self << x }
47
+ end
48
+
49
+ def <<(metric)
50
+ @mt_metrics ||=[]
51
+ @mt_metrics << MtMetric.new(metric)
52
+ end
53
+
54
+ def encode
55
+ @netmask ||= Netmask.new
56
+ @metric ||= Metric.new
57
+ summary =[]
58
+ summary << netmask.encode
59
+ summary << metric.encode
60
+ summary << mt_metrics.collect { |x| x.encode } if mt_metrics
61
+ super summary.join
62
+ end
63
+
64
+ def parse(s)
65
+ netmask, metric, mt_metrics = super(s).unpack('NNa*')
66
+ @netmask = Netmask.new netmask
67
+ @metric = Metric.new metric
68
+ while mt_metrics.size>0
69
+ self << MtMetric.new(mt_metrics.slice!(0,4))
70
+ end
71
+ end
72
+
73
+ def to_hash
74
+ super
75
+ end
76
+
77
+ def to_s_default(*args)
78
+ super +
79
+ ['',netmask, metric, *mt_metrics].collect { |x| x.to_s }.join("\n ")
80
+ end
81
+
82
+ def to_s_junos_verbose
83
+ mask = "mask #{netmask.to_ip}"
84
+ super +
85
+ ['', mask, metric.to_s_junos, *mt_metrics.collect{|m| m.to_s_junos}].join("\n ")
86
+ end
87
+ def to_s_junos
88
+ super
89
+ end
90
+
91
+ end
92
+
93
+ class Summary < Summary_Base
94
+ class << self
95
+ def count
96
+ @count ||= 0
97
+ end
98
+
99
+ def incr_count
100
+ self.count
101
+ @count += 1
102
+ end
103
+
104
+ def reset
105
+ @count = nil
106
+ end
107
+
108
+ def base_ip_addr(addr=SUMMARY_BASE_ADDRESS)
109
+ @base_addr ||= IPAddr.new(addr)
110
+ end
111
+
112
+ def network
113
+ @base_addr + count
114
+ end
115
+
116
+ def new_lsdb(arg={})
117
+ new({:network=> base_ip_addr ^ incr_count}.merge(arg))
118
+ end
119
+
120
+ end
121
+
122
+
123
+ def initialize(arg={})
124
+ if arg.is_a?(Hash)
125
+ arg = fix_hash(arg).merge!({:ls_type => :summary_lsa,})
126
+ end
127
+ super
128
+ end
129
+
130
+ private
131
+
132
+ def fix_hash(arg)
133
+ if arg[:network]
134
+ addr = IPAddr.new arg[:network]
135
+ arg.delete :network
136
+ arg.store :netmask, addr.netmask
137
+ arg.store :ls_id, addr.to_s
138
+ end
139
+ arg
140
+ end
141
+
142
+ end
143
+
144
+ class AsbrSummary < Summary_Base
145
+ def initialize(arg={})
146
+ arg.merge!({:ls_type => :asbr_summary_lsa,}) if arg.is_a?(Hash)
147
+ super
148
+ end
149
+ end
150
+
151
+ class Summary_Base
152
+ def self.new_hash(hash)
153
+ raise ArgumentError, "Invalid argument" unless hash.is_a?(Hash)
154
+ new(hash)
155
+ end
156
+ end
157
+
158
+ end
159
+
160
+
161
+ load "../../../test/ospfv2/lsa/#{ File.basename($0.gsub(/.rb/,'_test.rb'))}" if __FILE__ == $0
162
+
163
+ __END__
164
+
165
+ # if arg.is_a?(Hash)
166
+ # arg.merge!({:ls_type=> :summary_lsa}) unless arg.has_key?(:ls_type)
167
+ # set arg
168
+ # super
169
+ # elsif arg.is_a?(String)
170
+ # parse arg
171
+ # elsif arg.is_a?(self.class)
172
+ # parse arg.encode
173
+ # else
174
+ # raise ArgumentError, "Invalid argument", caller
175
+ # end
176
+
177
+ =begin rdoc
178
+
179
+
180
+ A.4.4 Summary-LSAs
181
+
182
+ Summary-LSAs are the Type 3 and 4 LSAs. These LSAs are originated
183
+ by area border routers. Summary-LSAs describe inter-area
184
+ destinations. For details concerning the construction of summary-
185
+ LSAs, see Section 12.4.3.
186
+
187
+ Type 3 summary-LSAs are used when the destination is an IP network.
188
+ In this case the LSA's Link State ID field is an IP network number
189
+ (if necessary, the Link State ID can also have one or more of the
190
+ network's "host" bits set; see Appendix E for details). When the
191
+ destination is an AS boundary router, a Type 4 summary-LSA is used,
192
+ and the Link State ID field is the AS boundary router's OSPF Router
193
+ ID. (To see why it is necessary to advertise the location of each
194
+ ASBR, consult Section 16.4.) Other than the difference in the Link
195
+ State ID field, the format of Type 3 and 4 summary-LSAs is
196
+ identical.
197
+
198
+
199
+ 0 1 2 3
200
+ 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
201
+ +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
202
+ | LS age | Options | 3 or 4 |
203
+ +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
204
+ | Link State ID |
205
+ +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
206
+ | Advertising Router |
207
+ +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
208
+ | LS sequence number |
209
+ +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
210
+ | LS checksum | length |
211
+ +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
212
+ | Network Mask |
213
+ +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
214
+ | 0 | metric |
215
+ +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
216
+ | TOS | TOS metric |
217
+ +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
218
+ | ... |
219
+
220
+
221
+ For stub areas, Type 3 summary-LSAs can also be used to describe a
222
+ (per-area) default route. Default summary routes are used in stub
223
+ areas instead of flooding a complete set of external routes. When
224
+ describing a default summary route, the summary-LSA's Link State ID
225
+ is always set to DefaultDestination (0.0.0.0) and the Network Mask
226
+ is set to 0.0.0.0.
227
+
228
+ Network Mask
229
+ For Type 3 summary-LSAs, this indicates the destination
230
+ network's IP address mask. For example, when advertising the
231
+ location of a class A network the value 0xff000000 would be
232
+ used. This field is not meaningful and must be zero for Type 4
233
+ summary-LSAs.
234
+
235
+ metric
236
+ The cost of this route. Expressed in the same units as the
237
+ interface costs in the router-LSAs.
238
+
239
+ Additional TOS-specific information may also be included, for
240
+ backward compatibility with previous versions of the OSPF
241
+ specification ([Ref9]). For each desired TOS, TOS-specific
242
+ information is encoded as follows:
243
+
244
+ TOS IP Type of Service that this metric refers to. The encoding of
245
+ TOS in OSPF LSAs is described in Section 12.3.
246
+
247
+ TOS metric
248
+ TOS-specific metric information.
249
+
250
+
251
+ =end
252
+
253
+
254
+ module Ospf
255
+ module Summary_Shared
256
+ private
257
+ def __to_s_junos_style__(sum_type, rtype=' ')
258
+ enc
259
+ s = @header.to_s_junos_style(sum_type,rtype)
260
+ s +="\n mask #{netmask}"
261
+ s +="\n Topology default (ID #{@mt_id[0].id}) -> Metric: #{@mt_id[0].metric}"
262
+ s += @mt_id[1..-1].collect { |mt| "\n #{mt.to_s_junos_style}" }.join
263
+ s
264
+ end
265
+ def __to_hash__(sum_type)
266
+ enc
267
+ h = @header.to_hash.merge({:lsa_type=>sum_type, :netmask => netmask,})
268
+ if @mt_id.size > 1 or @mt_id[0].id != 0
269
+ h[:mt_id] = @mt_id.collect { |mt_id| mt_id.to_hash } unless @mt_id.nil?
270
+ else
271
+ h[:metric] = @mt_id[0].metric
272
+ end
273
+ h
274
+ end
275
+ private :__to_s_junos_style__, :__to_hash__
276
+
277
+ end
278
+ end
279
+
280
+ require 'lsa_header'
281
+
282
+ module Ospf
283
+
284
+ class SummaryLSAs < LSA
285
+ include Ospf
286
+ include Ospf::Ip
287
+ include Ospf::Summary_Shared
288
+
289
+ attr :header
290
+ attr_accessor :mt_id
291
+
292
+ def initialize(arg={})
293
+ @netmask, @mt_id = 0, []
294
+ if arg.is_a?(Hash) then
295
+ arg[:lstype]=3 if arg[:lstype].nil?
296
+ @header = LSA_Header.new(arg)
297
+ set(arg)
298
+ elsif arg.is_a?(String)
299
+ __parse(arg)
300
+ else
301
+ raise ArgumentError, "Invalid argument", caller
302
+ end
303
+ end
304
+
305
+ def set(arg)
306
+ return self unless arg.is_a?(Hash)
307
+ @header.set(arg)
308
+ unless arg[:netmask].nil?
309
+ _netmask = arg[:netmask]
310
+ @netmask = _netmask.is_a?(String) ? ip2long(_netmask) : _netmask
311
+ end
312
+
313
+ unless arg[:metric].nil?
314
+ metric=arg[:metric]
315
+ @mt_id << MT.new({:metric=>metric})
316
+ end
317
+ unless arg[:mt_id].nil?
318
+ arg[:mt_id].each { |mt_id|
319
+ mt_id.is_a?(MT) ? @mt_id << mt_id : @mt_id << MT.new(mt_id)
320
+ }
321
+ end
322
+ self
323
+ end
324
+
325
+ def <<(arg)
326
+ append_metric(arg)
327
+ end
328
+
329
+ def enc
330
+ packet = @header.enc
331
+ packet+= __enc([[@netmask,'N'],])
332
+ packet +=@mt_id.collect {|mt_id| mt_id.enc}.join
333
+ packet_size(packet,@header)
334
+ packet_fletchsum(packet)
335
+ end
336
+
337
+ def __parse(s)
338
+ @header = LSA_Header.new(s)
339
+ arr = s[20..24].unpack("N")
340
+ @netmask = arr[0]
341
+ mt_ids = s[24..-1]
342
+ while mt_ids.size>0
343
+ @mt_id << MT.new(mt_ids.slice!(0,4))
344
+ end
345
+ end
346
+ private :__parse
347
+
348
+ def to_s
349
+ enc
350
+ s = @header.to_s
351
+ s += "\n netmask #{netmask}"
352
+ s += "\n " if @mt_id.size>0
353
+ s += @mt_id.collect { |mt| mt.to_s }.join("\n ")
354
+ end
355
+
356
+ def metric
357
+ @mt_id[0].metric
358
+ end
359
+
360
+ end
361
+
362
+ class SummaryLSA < SummaryLSAs
363
+ def initialize(arg={})
364
+ arg.merge!({:lstype => 3,}) if arg.is_a?(Hash)
365
+ super
366
+ end
367
+ def to_s_junos_style(rtype=' ')
368
+ __to_s_junos_style__('Summary', rtype)
369
+ end
370
+ def to_hash
371
+ __to_hash__('Summary')
372
+ end
373
+ end
374
+
375
+ class ASBR_SummaryLSA < SummaryLSAs
376
+ def initialize(arg={})
377
+ arg.merge!({:lstype => 4, :metric=>0}) if arg.is_a?(Hash)
378
+ super(arg)
379
+ end
380
+ def to_s_junos_style(rtype=' ')
381
+ __to_s_junos_style__('ASBRSum', rtype)
382
+ end
383
+ def to_hash
384
+ __to_hash__('ASBRSum')
385
+ end
386
+ end
387
+ end
388
+
389
+ if __FILE__ == $0
390
+ load '../test/lsa_summary_test.rb'
391
+ end
392
+
393
+
@@ -0,0 +1,298 @@
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
+ require 'thread'
25
+ require 'logger'
26
+ require 'infra/ospf_common'
27
+ require 'neighbor_sm/neighbor_state'
28
+ require 'infra/ospf_socket'
29
+ require 'infra/ospf_io'
30
+ require 'packet/ospf_packet'
31
+ require 'infra/timer'
32
+ require 'infra/ospf_constants'
33
+ require 'ls_db/link_state_database'
34
+
35
+ require 'neighbor/neighbor_event_handler'
36
+
37
+ module OSPFv2
38
+
39
+ class Neighbor
40
+
41
+ class Trace
42
+ def initialize(io=$stdout)
43
+ @logger = Logger.new(io)
44
+ end
45
+ def trace(s)
46
+ "{Time.to_ts} #{s}"
47
+ @logger << s
48
+ end
49
+ end
50
+
51
+ include OSPFv2::Common
52
+ include OSPFv2::NeighborState
53
+ include OSPFv2
54
+ attr_reader :address, :inactivity_timer, :hello, :dd_rxmt_interval
55
+
56
+ InactivityTimer = Class.new(Timer)
57
+ HelloTimer = Class.new(PeriodicTimer)
58
+ RxmtIntervalTimer = Class.new(PeriodicTimer)
59
+ RefreshTimer = Class.new(PeriodicTimer)
60
+ RouterId = Class.new(Id)
61
+ AreadId = Class.new(Id)
62
+
63
+ attr_writer :hello_int, :dead_int
64
+
65
+ def initialize(arg={})
66
+ #TODO: accept prefix arg and set @address and @netmask in hello...
67
+ @address = arg[:src_addr] || '127.0.0.1'
68
+ @state = NeighborState::Down.new
69
+ @inactivity_timer = InactivityTimer.new(self.dead_int)
70
+ @periodic_hellos = HelloTimer.new(self.hello_int)
71
+ @router_id= RouterId.new arg[:router_id] || '1.1.1.1'
72
+ @area_id= AreaId.new arg[:aread_id] || '0.0.0.0'
73
+ @lsa_request_list = {}
74
+ @ls_db=nil
75
+ if arg[:log_fname]
76
+ @trace = Trace.new(arg[:log_fname])
77
+ else
78
+ @trace = Trace.new
79
+ end
80
+ end
81
+
82
+ def hello_int
83
+ @hello_int ||= 10
84
+ end
85
+ def dead_int
86
+ @dead_int ||= hello_int*4
87
+ end
88
+
89
+ def state
90
+ @state.class.to_s.split('::').last.downcase.to_sym
91
+ end
92
+
93
+ def in_state?(*states)
94
+ if states.size==0
95
+ state
96
+ else
97
+ states.include? state
98
+ end
99
+ end
100
+
101
+ def ls_db=(val)
102
+ raise ArgumentError, "expecting a LinkStateDatabase object!" unless val.is_a?(LSDB::LinkStateDatabase)
103
+ @ls_db=val
104
+ end
105
+
106
+ def log(ev, obj)
107
+ if obj.is_a?(String)
108
+ @trace.trace "\n#{Time.to_ts} #{ev}: #{obj}"
109
+ else
110
+ s = []
111
+ s << "\n#{Time.to_ts} (#{state}) #{ev} #{obj.name.to_camel}:\n#{obj}"
112
+ s << obj.encode.hexlify.join("\n ") if defined?($debug) and $debug == 1
113
+ s << "\n"
114
+ @trace.trace s.join
115
+ end
116
+ end
117
+
118
+ def debug(obj)
119
+ log :debug, obj if defined? $debug and $debug ==1
120
+ end
121
+
122
+ def clear_lsa_request_list
123
+ @lsa_request_list={}
124
+ end
125
+
126
+ def router_id
127
+ hello.router_id
128
+ end
129
+
130
+ def change_state(new_state, event=nil)
131
+ @num ||=0
132
+ @num +=1
133
+ log 'state change', "#{@num}\# [#{event}]: #{state} -> #{new_state.class.to_s.split('::').last}"
134
+ @state = new_state
135
+ end
136
+ alias :new_state :change_state
137
+
138
+ def dd_sequence_number
139
+ @dd_sequence_number = DatabaseDescription.seqn
140
+ end
141
+ def start
142
+ unless @ev
143
+ @ev = NeighborEventHandler.new(self)
144
+ @evQ = Queue.new
145
+ end
146
+ @dd_rxmt_interval = RxmtIntervalTimer.new(5,@ev)
147
+ @periodic_rxmt = RxmtIntervalTimer.new(5,@ev)
148
+ @periodic_refresh = RefreshTimer.new(60,@ev)
149
+ init_sockets @address
150
+ init_io
151
+ start_io
152
+ start_periodic_hellos
153
+ @state.start(self)
154
+ self
155
+ end
156
+
157
+ def stop
158
+ debug "*** stopping #{router_id}"
159
+ @periodic_hellos.cancel
160
+ @periodic_rxmt.cancel
161
+ @periodic_refresh.cancel
162
+ stop_io
163
+ close_sockets
164
+ rescue Exception => e
165
+ debug "#{e} while stopping neighor"
166
+ ensure
167
+ @state.kill_nbr(self)
168
+ self
169
+ end
170
+
171
+ def update(*args)
172
+ @evQ.enq *args
173
+ end
174
+ def send(packet, dest=OSPFv2::AllSPFRouters)
175
+ return unless @output
176
+ [packet].flatten.each { |p|
177
+ log :snd, p
178
+ @output.enq [p,dest]
179
+ }
180
+ end
181
+
182
+ # AllSPFRouters = "224.0.0.5"
183
+ # AllDRouters = "224.0.0.6"
184
+ def flood(lsas, dest=AllSPFRouters)
185
+ # return unless @output
186
+ send (LinkStateUpdate.new_lsas lsas), dest
187
+ end
188
+
189
+ def start_periodic_hellos
190
+ @periodic_hellos.cancel
191
+ hh = {
192
+ :router_id=> @router_id,
193
+ :netmask=> 0xffffff00,
194
+ :designated_router_id=> '0.0.0.0',
195
+ :backup_designated_router_id=> '0.0.0.0',
196
+ :helloInt=>hello_int,
197
+ :options=>2,
198
+ :rtr_pri=>0,
199
+ :deadInt=>dead_int,
200
+ }
201
+ @hello = Hello.new(hh)
202
+ @periodic_hellos.start {
203
+ send(@hello)
204
+ }
205
+ end
206
+
207
+ def start_periodic_rxmt
208
+ debug "*** about to start periodic rxmt timer ***"
209
+ @periodic_rxmt.start {
210
+ if @ls_req_list
211
+ debug "There are #{@ls_req_list.size} LS Request to re-transmit!"
212
+ send LinkStateRequest.new :area_id => @area_id, :router_id=> @router_id, :requests=> @ls_req_list.keys \
213
+ unless @ls_req_list.empty?
214
+ end
215
+ if @ls_db
216
+ lsas = @ls_db.all_not_acked
217
+ debug "There are #{lsas.size} LSA to re-transmit!"
218
+ send LinkStateUpdate.new_lsas :router_id=> @router_id,
219
+ :area_id => @area_id, :lsas => lsas unless lsas.empty?
220
+ end
221
+ }
222
+ end
223
+
224
+ def start_ls_refresh
225
+ return unless @ls_db
226
+ debug "*** about to start periodic refresh timer ***"
227
+ @periodic_refresh.start {
228
+ @ls_db.refresh if in_state? :full, :loading, :exchange
229
+ }
230
+ nil
231
+ end
232
+
233
+
234
+ def negotiation_done
235
+ @state.negotiation_done
236
+ end
237
+ def exchange_done
238
+ @state.exchange_done(self)
239
+ end
240
+
241
+ def send_dd(dd, rxmt=false)
242
+ dd_rxmt_interval.cancel
243
+ dd_rxmt_interval.start { debug "\n\n\n*** re-transmitting #{dd} ***\n\n\n" ; send dd } if rxmt
244
+ send dd, @neighbor_ip
245
+ @sent_dd = dd
246
+ end
247
+
248
+ def method_missing(method, *args, &block)
249
+ if method.to_s =~ /^(recv|unpack)/
250
+ puts %{
251
+
252
+ Method missing : #{method} !!!! #{@neighbor_state}
253
+
254
+ }
255
+ puts caller.reverse.join("\n")
256
+ raise
257
+ else
258
+ super
259
+ end
260
+ end
261
+
262
+ private
263
+
264
+ def init_sockets(src_addr)
265
+ begin
266
+ @rsock = RecvSocket.new(src_addr)
267
+ @ssock = SendSocket.new(src_addr)
268
+ rescue(Errno::EPERM) => e
269
+ STDERR.puts "\n**** root permission required, neighbor cannot be started.\n"
270
+ return
271
+ end
272
+ end
273
+
274
+ def close_sockets
275
+ @rsock.close
276
+ @ssock.close
277
+ rescue
278
+ end
279
+
280
+ def init_io
281
+ @input = Input.new(@rsock,self, @ev)
282
+ @output = OutputQ.new(@ssock,self, @ev)
283
+ end
284
+ def start_io
285
+ @input.start
286
+ @output.start
287
+ end
288
+ def stop_io
289
+ @input.stop
290
+ @output.stop
291
+ end
292
+
293
+ end
294
+
295
+ end
296
+
297
+ require 'neighbor/recv_ospf_packet'
298
+