ospfv2 0.0.1

Sign up to get free protection for your applications and to get access to all the features.
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,178 @@
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 'ls_db/link_state_database'
24
+ require 'ls_db/links'
25
+ require 'lsa/lsa'
26
+
27
+ module OSPFv2
28
+
29
+
30
+ class Lsa
31
+ def lsdb_link_id
32
+ @_lsdb_link_id
33
+ end
34
+ def lsdb_link_id=(val)
35
+ @_lsdb_link_id= val
36
+ end
37
+ def find_lsa_from_link(id)
38
+ all.find_all { |l| l.lsdb_link_id==id }
39
+ end
40
+ end
41
+
42
+ end
43
+
44
+ module OSPFv2::LSDB
45
+
46
+ class LinkStateDatabase
47
+
48
+ def self.router_id(row, col, base_rid=ROUTER_ID_BASE)
49
+ (row << 16) + col + base_rid
50
+ end
51
+
52
+ def router_id(*args)
53
+ LinkStateDatabase.router_id(*args)
54
+ end
55
+
56
+ # lsdb = LinkStateDatabase.create 10, 10, :prefix => '192.168.0.0/24'
57
+ # lsdb = LinkStateDatabase.create 10, 10, :prefix_base => '192.168.0.0/24', :router_id_base =>
58
+ def self.create(arg={})
59
+ arg = {:area_id=> 0, :columns=>2, :rows=>2, :base_router_id=> 0, :base_prefix=>'172.21.0.0/30'}.merge(arg)
60
+ ls_db = new arg
61
+ rows=arg[:rows]
62
+ cols=arg[:columns]
63
+ @base_router_id = arg[:base_router_id]
64
+ if arg[:base_prefix]
65
+ Link.reset_ip_addr
66
+ Link.base_ip_addr arg[:base_prefix]
67
+ end
68
+ @base_prefix = arg[:base_prefix]
69
+ router_id = lambda { |c,r| (r<<16) + c + @base_router_id }
70
+ 1.upto(rows) do |r|
71
+ 1.upto(cols) do |c|
72
+ ls_db.new_link(:router_id=> router_id.call(c,r-1), :neighbor_id=> router_id.call(c,r)) if r > 1
73
+ ls_db.new_link(:router_id=> router_id.call(c-1,r), :neighbor_id=> router_id.call(c,r)) if c > 1
74
+ end
75
+ end
76
+ ls_db
77
+ end
78
+
79
+ # link, :dir => :local_only
80
+ # link_hash, :direction => :remote_only
81
+
82
+ def new_link(*args)
83
+
84
+ # get a link object
85
+ local, remote = true, true
86
+ if args.size==1 and args[0].is_a?(Hash)
87
+ link = Link.new args[0]
88
+ elsif args[0].is_a?(Link)
89
+ link = args[0]
90
+ else
91
+ raise ArgumentError, "invalid argument: #{args.inspect}"
92
+ end
93
+
94
+ # local, remote or both
95
+ dir = args[0][:direction] ||= :both
96
+ local = false if dir and dir == :remote_only
97
+ remote = false if dir and dir == :local_only
98
+
99
+ if local
100
+ lsa = add_p2p_adjacency :router_id => link.router_id.to_i, :neighbor_router_id => link.neighbor_id.to_i, :prefix => link.local_prefix, :metric=>1
101
+ lsa.lsdb_link_id = link.id
102
+ link.local_lsa = lsa.key
103
+ end
104
+
105
+ if remote
106
+ lsa = add_p2p_adjacency :router_id => link.neighbor_id.to_i, :neighbor_router_id => link.router_id.to_i, :prefix => link.remote_prefix, :metric=>1
107
+ lsa.lsdb_link_id = link.id
108
+ link.remote_lsa = lsa.key
109
+ end
110
+
111
+ end
112
+
113
+ def link(link, action)
114
+ raise ArgumentError, "invalid argument: #{link.class}" unless link.is_a?(Link)
115
+ case action
116
+ when :up ; link_up(link)
117
+ when :down ; link_down(link)
118
+ end
119
+ end
120
+
121
+ def link_up(link)
122
+ raise ArgumentError, "invalid argument: #{link.class}" unless link.is_a?(Link)
123
+ add_adjacency :router_id=> link.router_id.to_i,
124
+ :neighbor_router_id => link.neighbor_id.to_i,
125
+ :prefix=> link.local_prefix,
126
+ :metric => link.metric
127
+ add_adjacency :router_id=> link.neighbor_id.to_i,
128
+ :neighbor_router_id => link.router_id.to_i,
129
+ :prefix=> link.remote_prefix,
130
+ :metric => link.metric
131
+ end
132
+
133
+ def link_down(link)
134
+ lsa = @ls_db[link.local_lsa]
135
+ lsa.delete(1, link.neighbor_id.to_ip)
136
+ lsa = @ls_db[link.remote_lsa]
137
+ lsa.delete(1, link.router_id.to_ip)
138
+ end
139
+
140
+ def link_refresh
141
+
142
+ end
143
+
144
+ def link_maxage
145
+
146
+ end
147
+
148
+ end
149
+
150
+ # @ls_db = LinkStateDatabase.new :area_id=>0
151
+ # @ls_db.new_link :router_id=> 1, :neighbor_id=>2
152
+ # @ls_db.new_link :router_id=> 1, :neighbor_id=>3
153
+ # @ls_db.new_link :router_id=> 1, :neighbor_id=>4
154
+ # @ls_db.new_link :router_id=> 1, :neighbor_id=>5
155
+ #
156
+ # puts @ls_db
157
+ #
158
+ # # p Link[1]
159
+ #
160
+ # rlsa = @ls_db[1,1]
161
+ # p rlsa.links.size
162
+ # p rlsa
163
+ # rlsa.delete(:point_to_point,'0.0.0.2')
164
+ # p rlsa.links.size
165
+ #
166
+ # rlsa = @ls_db[1,2]
167
+ # p rlsa.links.size
168
+ # p rlsa
169
+ # rlsa.delete(:point_to_point,'0.0.0.1')
170
+ # p rlsa.links.size
171
+ #
172
+ # puts @ls_db
173
+
174
+
175
+ end
176
+
177
+ load "../../../test/ospfv2/ls_db/#{ File.basename($0.gsub(/.rb/,'_test.rb'))}" if __FILE__ == $0
178
+
@@ -0,0 +1,160 @@
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 'infra/ospf_common'
24
+ require 'ie/id'
25
+ require 'ie/metric'
26
+ require 'ie/mt_metric'
27
+ require 'ls_db/common'
28
+
29
+ module OSPFv2::LSDB
30
+
31
+ class Link
32
+
33
+ class << self
34
+
35
+ def <<(val)
36
+ @_links ||={}
37
+ @_links.store(val.id, val)
38
+ end
39
+
40
+ def all
41
+ @_links ||={}
42
+ @_links
43
+ end
44
+
45
+ def ids
46
+ @_links ||={}
47
+ @_links.keys
48
+ end
49
+
50
+ def count
51
+ @count ||= 0
52
+ end
53
+
54
+ def incr_count
55
+ self.count
56
+ @count += 1
57
+ end
58
+
59
+ def reset
60
+ @_links={}
61
+ @count = nil
62
+ end
63
+
64
+ def base_ip_addr(addr=LINK_BASE_ADDRESS)
65
+ @base_addr ||= IPAddr.new(addr)
66
+ end
67
+
68
+ def find_by_id(router_id)
69
+ all.find_all { |k,v| v.router_id.to_ip == router_id }
70
+ end
71
+
72
+ def reset_ip_addr
73
+ @base_addr=nil
74
+ end
75
+
76
+ def [](val)
77
+ @_links[val]
78
+ end
79
+
80
+ end
81
+
82
+ include OSPFv2::Common
83
+
84
+ #FIXME: all IE should be in an IE namespace
85
+ RouterId = Class.new(OSPFv2::Id)
86
+ NeighborId = Class.new(OSPFv2::Id)
87
+
88
+ attr_reader :router_id, :neighbor_id, :metric
89
+
90
+ #TODO: :metric => [10,20] ... revisit
91
+ # :metric_ifa => 10, :metric_ifb=>20
92
+ def initialize(arg={})
93
+ @_state = :down
94
+ @_id = self.class.incr_count
95
+ @prefix=nil
96
+ @router_id= RouterId.new arg[:router_id] || '1.1.1.1'
97
+ @neighbor_id= NeighborId.new arg[:neighbor_id] || '2.2.2.2'
98
+ @metric = 0
99
+ set arg
100
+ @lsas=[]
101
+ Link << self
102
+ self
103
+ end
104
+ [:local, :remote].each_with_index { |n,i|
105
+ define_method("#{n}_prefix") do
106
+ instance_variable_set("@_#{n}_prefix", _address_(i+1))
107
+ end
108
+ }
109
+
110
+ def id
111
+ @_id
112
+ end
113
+
114
+ attr_reader :local_lsa, :remote_lsa
115
+
116
+ def local_lsa=(lsa)
117
+ @local_lsa=lsa
118
+ end
119
+
120
+ def remote_lsa=(lsa)
121
+ @remote_lsa=lsa
122
+ end
123
+
124
+ def network
125
+ @network ||=IPAddr.new(Link.base_ip_addr.^(@_id-1))
126
+ end
127
+
128
+ def to_s
129
+ rid = router_id.to_s.split(":")
130
+ nid = neighbor_id.to_s.split(":")
131
+ sprintf("%3d\# %s: %-15.15s %s:%-15.15s Network %-15.15s %s",
132
+ @_id, rid[0], rid[1], nid[0], nid[1], network_to_s, metric)
133
+ end
134
+
135
+ def network_to_s
136
+ [network, network.mlen].join('/')
137
+ end
138
+
139
+ def method_missing(name, *args, &block)
140
+ if name.to_s =~ /^(local|remote)_address/
141
+ (__send__ "#{$1}_prefix").split('/')[0]
142
+ else
143
+ p name
144
+ raise
145
+ end
146
+ end
147
+
148
+
149
+ private
150
+
151
+
152
+ def _address_(host=1)
153
+ network + host
154
+ end
155
+
156
+ end
157
+
158
+ end
159
+
160
+ load "../../../test/ospfv2/ls_db/#{ File.basename($0.gsub(/.rb/,'_test.rb'))}" if __FILE__ == $0
@@ -0,0 +1,347 @@
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
+ =begin rdoc
24
+
25
+ A.4.5 AS-external-LSAs
26
+
27
+ AS-external-LSAs are the Type 5 LSAs. These LSAs are originated by
28
+ AS boundary routers, and describe destinations external to the AS.
29
+ For details concerning the construction of AS-external-LSAs, see
30
+ Section 12.4.3.
31
+
32
+ AS-external-LSAs usually describe a particular external destination.
33
+ For these LSAs the Link State ID field specifies an IP network
34
+ number (if necessary, the Link State ID can also have one or more of
35
+ the network's "host" bits set; see Appendix E for details). AS-
36
+ external-LSAs are also used to describe a default route. Default
37
+ routes are used when no specific route exists to the destination.
38
+ When describing a default route, the Link State ID is always set to
39
+ DefaultDestination (0.0.0.0) and the Network Mask is set to 0.0.0.0.
40
+
41
+
42
+ 0 1 2 3
43
+ 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
44
+ +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
45
+ | LS age | Options | 5 |
46
+ +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
47
+ | Link State ID |
48
+ +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
49
+ | Advertising Router |
50
+ +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
51
+ | LS sequence number |
52
+ +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
53
+ | LS checksum | length |
54
+ +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
55
+ | Network Mask |
56
+ +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
57
+ |E| 0 | metric |
58
+ +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
59
+ | Forwarding address |
60
+ +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
61
+ | External Route Tag |
62
+ +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
63
+ |E| TOS | TOS metric |
64
+ +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
65
+ | Forwarding address |
66
+ +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
67
+ | External Route Tag |
68
+ +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
69
+ | ... |
70
+
71
+
72
+
73
+ Network Mask
74
+ The IP address mask for the advertised destination. For
75
+ example, when advertising a class A network the mask 0xff000000
76
+ would be used.
77
+
78
+ bit E
79
+ The type of external metric. If bit E is set, the metric
80
+ specified is a Type 2 external metric. This means the metric is
81
+ considered larger than any link state path. If bit E is zero,
82
+ the specified metric is a Type 1 external metric. This means
83
+ that it is expressed in the same units as the link state metric
84
+ (i.e., the same units as interface cost).
85
+
86
+ metric
87
+ The cost of this route. Interpretation depends on the external
88
+ type indication (bit E above).
89
+
90
+ Forwarding address
91
+ Data traffic for the advertised destination will be forwarded to
92
+ this address. If the Forwarding address is set to 0.0.0.0, data
93
+ traffic will be forwarded instead to the LSA's originator (i.e.,
94
+ the responsible AS boundary router).
95
+
96
+ External Route Tag
97
+ A 32-bit field attached to each external route. This is not
98
+ used by the OSPF protocol itself. It may be used to communicate
99
+ information between AS boundary routers; the precise nature of
100
+ such information is outside the scope of this specification.
101
+
102
+ Additional TOS-specific information may also be included, for
103
+ backward compatibility with previous versions of the OSPF
104
+ specification ([Ref9]). For each desired TOS, TOS-specific
105
+ information is encoded as follows:
106
+
107
+ TOS The Type of Service that the following fields concern. The
108
+ encoding of TOS in OSPF LSAs is described in Section 12.3.
109
+
110
+ bit E
111
+ For backward-compatibility with [Ref9].
112
+
113
+ TOS metric
114
+ TOS-specific metric information.
115
+
116
+ Forwarding address
117
+ For backward-compatibility with [Ref9].
118
+
119
+ External Route Tag
120
+ For backward-compatibility with [Ref9].
121
+
122
+
123
+
124
+ (RFC 4915)
125
+
126
+ +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
127
+ | Network Mask |
128
+ +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
129
+ |E| 0 | metric |
130
+ +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
131
+ | Forwarding address |
132
+ +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
133
+ | External Route Tag |
134
+ +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
135
+ |E| MT-ID | MT-ID metric |
136
+ +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
137
+ | Forwarding address |
138
+ +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
139
+ | External Route Tag |
140
+ +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
141
+ | ... |
142
+ +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
143
+
144
+ =end
145
+
146
+
147
+ require 'lsa/lsa'
148
+
149
+ require 'ie/metric'
150
+ require 'ie/mt_metric'
151
+ require 'ie/id'
152
+ require 'ie/external_route'
153
+
154
+ module OSPFv2
155
+
156
+ class External_Base < Lsa
157
+
158
+ Netmask = Class.new(OSPFv2::Id)
159
+ ExternalRoute = Class.new(OSPFv2::ExternalRoute)
160
+
161
+
162
+ attr_reader :netmask, :external_route, :mt_metrics
163
+ attr_writer_delegate :netmask, :external_route
164
+
165
+ def initialize(arg={})
166
+ @netmask, @external_route = nil
167
+ @mt_metrics=[]
168
+ super
169
+ end
170
+
171
+ def encode
172
+ @netmask ||= Netmask.new
173
+ external =[]
174
+ external << netmask.encode
175
+ external << external_route.encode
176
+ external << mt_metrics.collect { |x| x.encode } if mt_metrics
177
+ super external.join
178
+ end
179
+
180
+ def parse(s)
181
+ s = super(s)
182
+ netmask, external_route = s.slice!(0,16).unpack('Na*')
183
+ @netmask = Netmask.new netmask
184
+ @external_route = ExternalRoute.new external_route
185
+ while s.size>0
186
+ self << MtExternalRoute.new(s.slice!(0,12))
187
+ end
188
+ end
189
+
190
+ def to_hash
191
+ super
192
+ end
193
+
194
+ def to_s_default
195
+ mt_metrics = self.mt_metrics.collect
196
+ super +
197
+ ['',netmask, external_route, *mt_metrics ].collect { |x| x.to_s }.join("\n ")
198
+ end
199
+
200
+ def to_s_junos
201
+ super
202
+ end
203
+
204
+ # Extern 50.0.2.0 128.3.0.1 0x80000001 39 0x0 0x1454 48
205
+ # mask 255.255.255.0
206
+ # Topology default (ID 0)
207
+ # Type: 1, Metric: 0, Fwd addr: 0.0.0.0, Tag: 0.0.0.0
208
+ # Topology default (ID 0)
209
+ # Type: 1, Metric: 30, Fwd addr: 0.0.0.0, Tag: 0.0.0.10
210
+ def to_s_junos_verbose
211
+ mt_metrics = self.mt_metrics.collect
212
+ super +
213
+ ['',netmask, external_route, *mt_metrics ].collect { |x| x.to_s }.join("\n ")
214
+ end
215
+
216
+ def mt_metrics=(val)
217
+ # p "in mt_metrics=(val)"
218
+ # p val
219
+ [val].flatten.each { |x| self << x }
220
+ end
221
+
222
+ def <<(ext_route)
223
+ @mt_metrics ||=[]
224
+ # p "calling MtExternalRoute with #{ext_route.inspect}"
225
+ route = MtExternalRoute.new(ext_route)
226
+ # p route
227
+ @mt_metrics << route
228
+ self
229
+ end
230
+
231
+ def forwarding_address=(val)
232
+ @external_route.forwarding_address=(val)
233
+ end
234
+
235
+ def type=(val)
236
+ @external_route.type=(val)
237
+ end
238
+
239
+ def tag=(val)
240
+ @external_route.tag=(val)
241
+ end
242
+
243
+ def metric=(val)
244
+ @external_route.metric=(val)
245
+ end
246
+
247
+ # FIXME: should be a mixin and extended Summary and External?
248
+ class << self
249
+ def count
250
+ @count ||= 0
251
+ end
252
+
253
+ def incr_count
254
+ self.count
255
+ @count += 1
256
+ end
257
+
258
+ def reset
259
+ @count = nil
260
+ end
261
+
262
+ def base_ip_addr(addr=EXTERNAL_BASE_ADDRESS)
263
+ @base_addr ||= IPAddr.new(addr)
264
+ end
265
+
266
+ def network
267
+ @base_addr + count
268
+ end
269
+
270
+ def new_lsdb(arg={})
271
+ new({:network=> base_ip_addr ^ incr_count}.merge(arg))
272
+ end
273
+
274
+ end
275
+
276
+ end
277
+
278
+ class AsExternal < External_Base
279
+
280
+ ExternalRoute = Class.new(OSPFv2::ExternalRoute)
281
+
282
+ class << self
283
+ def count
284
+ @count ||= 0
285
+ end
286
+
287
+ def incr_count
288
+ self.count
289
+ @count += 1
290
+ end
291
+
292
+ def reset
293
+ @count = nil
294
+ end
295
+
296
+ def base_ip_addr(addr=EXTERNAL_BASE_ADDRESS)
297
+ @base_addr ||= IPAddr.new(addr)
298
+ end
299
+
300
+ def network
301
+ @base_addr + count
302
+ end
303
+
304
+ def new_lsdb(arg={})
305
+ new({:network=> base_ip_addr ^ incr_count}.merge(arg))
306
+ end
307
+
308
+ end
309
+
310
+ 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
316
+
317
+ private
318
+
319
+ def fix_hash(arg)
320
+ # p 'HERE'
321
+ # p arg
322
+ if arg[:network]
323
+ addr = IPAddr.new arg[:network]
324
+ arg.delete :network
325
+ arg.store :netmask, addr.netmask
326
+ arg.store :ls_id, addr.to_s
327
+ end
328
+ route = arg[:external_route] ||={}
329
+ [:metric, :forwarding_address, :type, :tag].each do |e|
330
+ next unless arg[e]
331
+ route.store(e, arg[e]) if arg[e]
332
+ arg.delete(e)
333
+ end
334
+ arg.merge!(:external_route=>route)
335
+ # p "FIXED arg: #{arg.inspect}"
336
+ arg
337
+ end
338
+
339
+ end
340
+
341
+ def AsExternal.new_hash(h)
342
+ new(h)
343
+ end
344
+
345
+ end
346
+
347
+ load "../../../test/ospfv2/lsa/#{ File.basename($0.gsub(/.rb/,'_test.rb'))}" if __FILE__ == $0