ospfv2 0.0.1
Sign up to get free protection for your applications and to get access to all the features.
- data/bin/ospfv2 +136 -0
- data/lib/ie/au_type.rb +79 -0
- data/lib/ie/external_route.rb +181 -0
- data/lib/ie/id.rb +97 -0
- data/lib/ie/interface_mtu.rb +64 -0
- data/lib/ie/ls_age.rb +89 -0
- data/lib/ie/ls_type.rb +148 -0
- data/lib/ie/metric.rb +63 -0
- data/lib/ie/mt_metric.rb +119 -0
- data/lib/ie/options.rb +356 -0
- data/lib/ie/ospf_version.rb +67 -0
- data/lib/ie/packet_type.rb +65 -0
- data/lib/ie/router_link.rb +167 -0
- data/lib/ie/router_link_factory.rb +53 -0
- data/lib/ie/router_link_type.rb +86 -0
- data/lib/ie/sequence_number.rb +144 -0
- data/lib/ie/tos_metric.rb +102 -0
- data/lib/infra/ospf_common.rb +291 -0
- data/lib/infra/ospf_constants.rb +73 -0
- data/lib/infra/ospf_io.rb +133 -0
- data/lib/infra/ospf_socket.rb +126 -0
- data/lib/infra/parse_options.rb +135 -0
- data/lib/infra/timer.rb +104 -0
- data/lib/infra/to_s.rb +38 -0
- data/lib/ls_db/advertised_routers.rb +78 -0
- data/lib/ls_db/common.rb +31 -0
- data/lib/ls_db/link_state_database.rb +376 -0
- data/lib/ls_db/link_state_database_build.rb +181 -0
- data/lib/ls_db/link_state_database_links.rb +178 -0
- data/lib/ls_db/links.rb +160 -0
- data/lib/lsa/external.rb +347 -0
- data/lib/lsa/lsa.rb +438 -0
- data/lib/lsa/lsa_factory.rb +59 -0
- data/lib/lsa/network.rb +166 -0
- data/lib/lsa/router.rb +336 -0
- data/lib/lsa/summary.rb +393 -0
- data/lib/neighbor/neighbor.rb +298 -0
- data/lib/neighbor/neighbor_event_handler.rb +61 -0
- data/lib/neighbor/recv_database_description.rb +153 -0
- data/lib/neighbor/recv_hello.rb +53 -0
- data/lib/neighbor/recv_ospf_packet.rb +68 -0
- data/lib/neighbor_sm/attempt_state.rb +44 -0
- data/lib/neighbor_sm/down_state.rb +46 -0
- data/lib/neighbor_sm/exchange_state.rb +32 -0
- data/lib/neighbor_sm/exstart_state.rb +69 -0
- data/lib/neighbor_sm/full_state.rb +36 -0
- data/lib/neighbor_sm/init_state.rb +43 -0
- data/lib/neighbor_sm/loading_state.rb +33 -0
- data/lib/neighbor_sm/neighbor_state.rb +87 -0
- data/lib/packet/database_description.rb +300 -0
- data/lib/packet/hello.rb +327 -0
- data/lib/packet/link_state_ack.rb +144 -0
- data/lib/packet/link_state_request.rb +153 -0
- data/lib/packet/link_state_update.rb +189 -0
- data/lib/packet/ospf_packet.rb +306 -0
- 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
|
+
|
data/lib/ls_db/links.rb
ADDED
@@ -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
|
data/lib/lsa/external.rb
ADDED
@@ -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
|