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,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