bgp4r 0.0.11 → 0.0.12
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.
- data/bgp/common.rb +14 -13
- data/bgp/iana.rb +26 -1
- data/bgp/messages/capability.rb +3 -2
- data/bgp/messages/message.rb +3 -2
- data/bgp/messages/open.rb +2 -1
- data/bgp/messages/update.rb +80 -30
- data/bgp/neighbor/add_path_cap.rb +125 -0
- data/bgp/{neighbor.rb → neighbor/neighbor.rb} +64 -68
- data/bgp/nlris/nlri.rb +289 -15
- data/bgp/nlris/prefix.rb +3 -2
- data/bgp/nlris/vpn.rb +1 -8
- data/bgp/optional_parameters/add_path.rb +160 -0
- data/bgp/optional_parameters/capabilities.rb +1 -0
- data/bgp/optional_parameters/capability.rb +6 -0
- data/bgp/optional_parameters/graceful_restart.rb +6 -6
- data/bgp/optional_parameters/optional_parameter.rb +1 -0
- data/bgp/path_attributes/as_path.rb +1 -1
- data/bgp/path_attributes/attribute.rb +12 -5
- data/bgp/path_attributes/mp_reach.rb +142 -96
- data/bgp/path_attributes/mp_unreach.rb +73 -20
- data/bgp/path_attributes/path_attribute.rb +28 -5
- data/bgp4r.gemspec +21 -6
- data/bgp4r.rb +1 -1
- data/examples/unit-testing/malformed_update.rb +2 -1
- data/examples/unit-testing/test.rb +82 -0
- data/examples/unit-testing/test1.rb +82 -0
- data/examples/unit-testing/test2.rb +44 -0
- data/test/common_test.rb +7 -0
- data/test/helpers/server.rb +20 -0
- data/test/iana_test.rb +43 -0
- data/test/messages/open_test.rb +7 -2
- data/test/messages/update_test.rb +133 -36
- data/test/neighbor/add_path_cap_test.rb +54 -0
- data/test/neighbor/neighbor_test.rb +161 -0
- data/test/nlris/ext_nlri_test.rb +25 -60
- data/test/nlris/nlri_test.rb +93 -115
- data/test/optional_parameters/add_path_test.rb +53 -0
- data/test/optional_parameters/capability_test.rb +10 -0
- data/test/optional_parameters/graceful_restart_test.rb +1 -0
- data/test/path_attributes/mp_reach_test.rb +206 -8
- data/test/path_attributes/mp_unreach_test.rb +113 -5
- data/test/path_attributes/path_attribute_test.rb +34 -2
- metadata +20 -7
- data/test/neighbor_test.rb +0 -62
@@ -24,21 +24,13 @@ require 'socket'
|
|
24
24
|
require 'thread'
|
25
25
|
require 'observer'
|
26
26
|
require 'bgp/io'
|
27
|
+
require 'bgp/neighbor/add_path_cap'
|
27
28
|
|
28
29
|
module BGP
|
29
30
|
|
30
31
|
class Neighbor
|
31
32
|
include Observable
|
32
33
|
|
33
|
-
# def self.deprecate(old_method, new_method)
|
34
|
-
# define_method(old_method) do |*args, &block|
|
35
|
-
# log_warn "#{old_method}() is deprecated. Use #{new_method}()."
|
36
|
-
# __send__(new_method, *args, &block)
|
37
|
-
# end
|
38
|
-
# end
|
39
|
-
#
|
40
|
-
# deprecate :send_message, :send
|
41
|
-
|
42
34
|
def log_info(txt)
|
43
35
|
Log.info "#{self.class} #{txt}"
|
44
36
|
end
|
@@ -63,8 +55,8 @@ module BGP
|
|
63
55
|
else
|
64
56
|
@version, @my_as, @holdtime, @id, @remote_addr, @local_addr = args
|
65
57
|
end
|
66
|
-
@as4byte=false
|
67
58
|
@state = :Idle
|
59
|
+
@session_info=nil
|
68
60
|
@threads=ThreadGroup.new
|
69
61
|
@mutex = Mutex.new
|
70
62
|
@eventQ = Queue.new
|
@@ -77,12 +69,15 @@ module BGP
|
|
77
69
|
end
|
78
70
|
end
|
79
71
|
|
72
|
+
# FIXME:
|
73
|
+
# neighbor.add_capability
|
74
|
+
# neighbor.remove_capability
|
80
75
|
# neighbor.capability :as4_byte | :as4 | :as4byte
|
81
76
|
# neighbor.capability :route_refresh, :rr
|
82
77
|
# neighbor.capability :route_refresh, 128
|
83
78
|
# neighbor.capability :mbgp, :ipv4, :unicast
|
84
79
|
# neighbor.capability :mbgp, :ipv4, :multicast
|
85
|
-
|
80
|
+
|
86
81
|
def capability(*args)
|
87
82
|
@opt_parms << if args[0].is_a?(Symbol)
|
88
83
|
case args[0]
|
@@ -103,6 +98,7 @@ module BGP
|
|
103
98
|
raise ArgumentError, "Invalid argument"
|
104
99
|
end
|
105
100
|
end
|
101
|
+
alias :add_cap :capability
|
106
102
|
|
107
103
|
def state
|
108
104
|
"#{@state}"
|
@@ -115,7 +111,7 @@ module BGP
|
|
115
111
|
Thread.current['name']='restart'
|
116
112
|
loop do
|
117
113
|
enable if @state == :Idle
|
118
|
-
sleep(
|
114
|
+
sleep(4)
|
119
115
|
end
|
120
116
|
end
|
121
117
|
|
@@ -132,7 +128,7 @@ module BGP
|
|
132
128
|
ev, type, m = eventQ.deq
|
133
129
|
case ev
|
134
130
|
when :ev_msg
|
135
|
-
msg = BGP::Message.factory(m, @
|
131
|
+
msg = BGP::Message.factory(m, @session_info)
|
136
132
|
log_info "Recv#{msg.class.to_s.split('::').last}"
|
137
133
|
log_debug "Recv #{msg}\n"
|
138
134
|
if msg.is_a?(Update)
|
@@ -153,17 +149,17 @@ module BGP
|
|
153
149
|
changed and notify_observers(msg)
|
154
150
|
when :ev_conn_reset
|
155
151
|
Log.warn "#{type}"
|
156
|
-
|
152
|
+
stop
|
157
153
|
when :ev_holdtime_expire
|
158
154
|
Log.warn "Holdtime expire: #{type}"
|
159
|
-
|
155
|
+
stop
|
160
156
|
else
|
161
157
|
Log.error "unexpected event #{ev}"
|
162
158
|
end
|
163
159
|
end
|
164
160
|
end
|
165
161
|
end
|
166
|
-
|
162
|
+
|
167
163
|
def clean
|
168
164
|
@threads.list.each { |x|
|
169
165
|
x.exit; x.join
|
@@ -183,42 +179,42 @@ module BGP
|
|
183
179
|
@holdtime ||= 180
|
184
180
|
end
|
185
181
|
|
186
|
-
def
|
182
|
+
def start_session(session)
|
183
|
+
@socket=session
|
184
|
+
return unless @state == :Idle
|
185
|
+
init_io
|
186
|
+
send_open :ev_send_open
|
187
|
+
end
|
188
|
+
|
189
|
+
def start(arg={})
|
190
|
+
options = {:port=> 179, :auto_retry=> false, :no_blocking=>false, :waitfor=> :Established}.merge(arg)
|
187
191
|
return if @state == :Established
|
188
|
-
|
189
|
-
|
190
|
-
|
192
|
+
stop unless @state == :Idle
|
193
|
+
if options[:session]
|
194
|
+
@socket = session
|
195
|
+
else
|
196
|
+
@socket = TCPSocket.new(@remote_addr, options[:port])
|
197
|
+
end
|
191
198
|
init_io
|
192
|
-
|
193
|
-
[@in, @out].each { |io|
|
194
|
-
io.start
|
195
|
-
@threads.add io.thread
|
196
|
-
}
|
197
|
-
|
198
199
|
send_open :ev_send_open
|
199
|
-
|
200
|
-
|
201
|
-
|
202
|
-
if wait == :wait
|
200
|
+
retry_thread if options[:auto_retry] == true
|
201
|
+
unless options[:no_blocking] == true
|
203
202
|
loop do
|
204
203
|
sleep(0.3)
|
205
|
-
break if @state == :
|
204
|
+
break if @state == options[:waitfor]
|
206
205
|
end
|
207
206
|
log_info "#{self} started"
|
208
207
|
end
|
209
|
-
|
210
208
|
rescue => e
|
211
209
|
Log.error "#{e}"
|
212
|
-
|
210
|
+
stop
|
213
211
|
end
|
214
|
-
alias start enable
|
215
212
|
|
216
|
-
def
|
213
|
+
def stop
|
217
214
|
@socket.close if defined?(@socket) and not @socket.closed?
|
218
215
|
clean
|
219
216
|
new_state :Idle, "Disable"
|
220
217
|
end
|
221
|
-
alias stop disable
|
222
218
|
|
223
219
|
define_method(:in) do
|
224
220
|
@in.thread
|
@@ -227,7 +223,11 @@ module BGP
|
|
227
223
|
@out.thread
|
228
224
|
end
|
229
225
|
|
230
|
-
attr_reader :as4byte
|
226
|
+
attr_reader :as4byte, :session_info
|
227
|
+
|
228
|
+
def as4byte?
|
229
|
+
@session_info.as4byte?
|
230
|
+
end
|
231
231
|
|
232
232
|
def send_message(m)
|
233
233
|
raise if m.nil?
|
@@ -236,30 +236,23 @@ module BGP
|
|
236
236
|
log_info "Send#{m.class.to_s.split('::')[-1]}"
|
237
237
|
log_debug "Send #{m.is_a?(Update) ? m.to_s : m }\n"
|
238
238
|
end
|
239
|
-
#FIXME: enqueue [m, as4byte]
|
240
239
|
if m.is_a?(Update)
|
241
|
-
|
240
|
+
send_update m
|
242
241
|
else
|
243
242
|
@out.enq m
|
244
243
|
end
|
245
244
|
end
|
246
|
-
|
247
|
-
def init_socket
|
248
|
-
@socket = Socket.new(Socket::PF_INET, Socket::SOCK_STREAM, Socket::IPPROTO_TCP)
|
249
|
-
remote = Socket.pack_sockaddr_in(179, @remote_addr)
|
250
|
-
local = Socket.pack_sockaddr_in(0, @local_addr) unless @local_addr.nil?
|
251
|
-
remote_sock_addr = Socket.pack_sockaddr_in(179, @remote_addr)
|
252
|
-
local_sock_addr = Socket.pack_sockaddr_in(0, @local_addr) unless @local_addr.nil?
|
253
|
-
@socket.bind(local_sock_addr) unless @local_addr.nil?
|
254
|
-
@socket.connect(remote_sock_addr)
|
255
|
-
end
|
256
|
-
|
245
|
+
|
257
246
|
def init_io
|
258
247
|
@in = BGP::IO::Input.new(@socket, holdtime, self)
|
259
248
|
@out = BGP::IO::Output.new(@socket, @holdtime, self)
|
260
249
|
new_state(:Active, "Open Socket")
|
250
|
+
[@in, @out].each { |io|
|
251
|
+
io.start
|
252
|
+
@threads.add io.thread
|
253
|
+
}
|
261
254
|
end
|
262
|
-
|
255
|
+
|
263
256
|
def update(*args)
|
264
257
|
@eventQ.enq(args)
|
265
258
|
end
|
@@ -268,7 +261,11 @@ module BGP
|
|
268
261
|
log_info "#{txt} old state #{@state} new state #{state}"
|
269
262
|
@state = state
|
270
263
|
end
|
271
|
-
|
264
|
+
|
265
|
+
def send_update(u)
|
266
|
+
@out.enq u.encode(@session_info)
|
267
|
+
end
|
268
|
+
|
272
269
|
def send_open(ev)
|
273
270
|
case @state
|
274
271
|
when :OpenRecv
|
@@ -277,18 +274,17 @@ module BGP
|
|
277
274
|
send_message open ; new_state :OpenSent, ev
|
278
275
|
else
|
279
276
|
Log.warn "#{self.class}: attempt to send OPEN msg while in #{@state}"
|
280
|
-
end
|
277
|
+
end
|
281
278
|
end
|
282
279
|
|
283
|
-
def rcv_open(
|
284
|
-
@
|
285
|
-
|
286
|
-
@
|
287
|
-
|
288
|
-
|
289
|
-
|
290
|
-
|
291
|
-
|
280
|
+
def rcv_open(peer_open)
|
281
|
+
@session_info = Neighbor::Capabilities.new open, peer_open
|
282
|
+
|
283
|
+
@rmt_version = peer_open.version
|
284
|
+
@rmt_as = peer_open.local_as
|
285
|
+
@rmt_bgp_id = peer_open.bgp_id
|
286
|
+
@out.holdtime = @in.holdtime = peer_open.holdtime if @holdtime > peer_open.holdtime
|
287
|
+
|
292
288
|
case @state
|
293
289
|
when :OpenSent
|
294
290
|
send_message(BGP::Message.keepalive)
|
@@ -299,7 +295,7 @@ module BGP
|
|
299
295
|
else
|
300
296
|
Log.warn "#{self.class}: received open message while in state #{@state}"
|
301
297
|
end
|
302
|
-
|
298
|
+
|
303
299
|
end
|
304
300
|
|
305
301
|
def rcv_keepalive
|
@@ -317,25 +313,25 @@ module BGP
|
|
317
313
|
@threads.add(@keepalive_thread)
|
318
314
|
end
|
319
315
|
end
|
320
|
-
|
316
|
+
|
321
317
|
def rcv_notification(m)
|
322
318
|
log_info "#{m}"
|
323
319
|
changed and notify_observers(m)
|
324
|
-
|
320
|
+
stop
|
325
321
|
end
|
326
322
|
|
327
323
|
def rcv_route_refresh(m)
|
328
324
|
end
|
329
|
-
|
325
|
+
|
330
326
|
def rcv_update(m)
|
331
327
|
end
|
332
328
|
|
333
329
|
def to_s
|
334
330
|
"version: #{version}, id: #{@id}, as: #{@my_as}, holdtime: #{@holdtime}, peer addr: #{@remote_addr}, local addr: #{@local_addr}"
|
335
331
|
end
|
336
|
-
|
332
|
+
|
337
333
|
end
|
338
334
|
|
339
335
|
end
|
340
336
|
|
341
|
-
load "
|
337
|
+
load "../../test/neighbor/#{ File.basename($0.gsub(/.rb/,'_test.rb'))}" if __FILE__ == $0
|
data/bgp/nlris/nlri.rb
CHANGED
@@ -29,6 +29,7 @@ module BGP
|
|
29
29
|
class Base_nlri
|
30
30
|
|
31
31
|
class Nlri_element < IPAddr
|
32
|
+
|
32
33
|
def to_s
|
33
34
|
[super, mlen].join('/')
|
34
35
|
end
|
@@ -36,7 +37,7 @@ module BGP
|
|
36
37
|
hton
|
37
38
|
end
|
38
39
|
def nbyte
|
39
|
-
|
40
|
+
(mlen+7)/8
|
40
41
|
end
|
41
42
|
def encode(len_included=true)
|
42
43
|
nbyte = (mlen+7)/8
|
@@ -46,13 +47,14 @@ module BGP
|
|
46
47
|
[hton].pack("a#{nbyte}")
|
47
48
|
end
|
48
49
|
end
|
49
|
-
def
|
50
|
+
def parse(arg)
|
50
51
|
s = arg.dup
|
51
52
|
s +=([0]*3).pack('C*')
|
52
53
|
plen, *nlri = s.unpack('CC4')
|
53
54
|
arg.slice!(0,1+(plen+7)/8) # trim arg accordingly
|
54
55
|
ipaddr = nlri.collect { |n| n.to_s }.join('.') + "/" + plen .to_s
|
55
56
|
end
|
57
|
+
alias :parse4 :parse
|
56
58
|
def parse6(arg)
|
57
59
|
s = arg.dup
|
58
60
|
s +=([0]*16).pack('C*')
|
@@ -71,6 +73,10 @@ module BGP
|
|
71
73
|
else
|
72
74
|
super(arg)
|
73
75
|
end
|
76
|
+
rescue => e
|
77
|
+
p e
|
78
|
+
p arg
|
79
|
+
raise
|
74
80
|
end
|
75
81
|
end
|
76
82
|
|
@@ -86,18 +92,90 @@ module BGP
|
|
86
92
|
end
|
87
93
|
end
|
88
94
|
|
95
|
+
class Ext_Nlri_element < Nlri_element
|
96
|
+
def initialize(*args)
|
97
|
+
if args.size>1
|
98
|
+
@path_id = args.shift
|
99
|
+
super
|
100
|
+
elsif args.size==1 and args[0].is_a?(String)
|
101
|
+
super parse(*args)
|
102
|
+
elsif args.size==1 and args[0].is_a?(Hash)
|
103
|
+
@path_id=args[0][:path_id]
|
104
|
+
super args[0][:nlri_element]
|
105
|
+
else
|
106
|
+
raise
|
107
|
+
end
|
108
|
+
rescue => e
|
109
|
+
p e
|
110
|
+
p args
|
111
|
+
raise
|
112
|
+
end
|
113
|
+
attr_reader :path_id
|
114
|
+
def encode
|
115
|
+
[path_id, super].pack('Na*')
|
116
|
+
end
|
117
|
+
def to_s
|
118
|
+
"ID: #{path_id}, #{super}"
|
119
|
+
end
|
120
|
+
def parse(s)
|
121
|
+
@path_id = s.slice!(0,4).unpack('N')[0]
|
122
|
+
super s
|
123
|
+
end
|
124
|
+
end
|
125
|
+
|
89
126
|
attr_reader :nlris
|
127
|
+
|
128
|
+
class << self
|
129
|
+
def new_ntop(s, extended=false)
|
130
|
+
if extended
|
131
|
+
nlri = new
|
132
|
+
while s.size>0
|
133
|
+
nlri.add Base_nlri::Ext_Nlri_element.new(s)
|
134
|
+
end
|
135
|
+
nlri
|
136
|
+
else
|
137
|
+
new(s.is_packed)
|
138
|
+
end
|
139
|
+
end
|
140
|
+
end
|
90
141
|
|
91
142
|
def initialize(*args)
|
92
143
|
if args[0].is_a?(String) and args[0].is_packed?
|
93
|
-
parse(args
|
144
|
+
parse(*args)
|
94
145
|
else
|
95
146
|
add(*args)
|
96
147
|
end
|
97
148
|
end
|
98
149
|
def add(*args)
|
99
150
|
@nlris ||=[]
|
100
|
-
args.
|
151
|
+
args.each { |arg|
|
152
|
+
case arg
|
153
|
+
when Hash
|
154
|
+
if arg.has_key? :path_id
|
155
|
+
@nlris << Ext_Nlri_element.new(arg)
|
156
|
+
else
|
157
|
+
raise
|
158
|
+
end
|
159
|
+
when String
|
160
|
+
# p "JME: IN ADD/ STRING:"
|
161
|
+
# p arg
|
162
|
+
# p arg.is_packed?
|
163
|
+
# p "---"
|
164
|
+
o = Ip4.new(arg)
|
165
|
+
# p o
|
166
|
+
@nlris << o
|
167
|
+
when Array
|
168
|
+
if arg[0].is_a?(Integer)
|
169
|
+
@nlris << Ext_Nlri_element.new(*arg)
|
170
|
+
else
|
171
|
+
raise
|
172
|
+
end
|
173
|
+
when Ext_Nlri_element, Ip4
|
174
|
+
@nlris << arg
|
175
|
+
else
|
176
|
+
raise ArgumentError, "Invalid argument #{arg.class} #{arg.inspect}"
|
177
|
+
end
|
178
|
+
}
|
101
179
|
end
|
102
180
|
alias << add
|
103
181
|
|
@@ -117,10 +195,10 @@ module BGP
|
|
117
195
|
end
|
118
196
|
end
|
119
197
|
|
120
|
-
def to_s
|
121
|
-
@nlris.join("\n")
|
198
|
+
def to_s(indent=0)
|
199
|
+
@nlris.join("\n#{([' ']*indent).join}")
|
122
200
|
end
|
123
|
-
|
201
|
+
|
124
202
|
def size
|
125
203
|
@nlris.size
|
126
204
|
end
|
@@ -132,23 +210,219 @@ module BGP
|
|
132
210
|
super
|
133
211
|
end
|
134
212
|
end
|
213
|
+
|
135
214
|
class Withdrawn < Base_nlri
|
136
|
-
|
137
|
-
|
215
|
+
class << self
|
216
|
+
def new_top(*args)
|
217
|
+
super
|
218
|
+
end
|
219
|
+
end
|
220
|
+
class << self
|
221
|
+
def new_ntop(s, extended=false)
|
222
|
+
if extended
|
223
|
+
nlri = new
|
224
|
+
while s.size>0
|
225
|
+
nlri.add Base_nlri::Ext_Nlri_element.new(s)
|
226
|
+
end
|
227
|
+
nlri
|
228
|
+
else
|
229
|
+
new(s.is_packed)
|
230
|
+
end
|
231
|
+
end
|
232
|
+
end
|
233
|
+
def encode
|
234
|
+
super
|
138
235
|
end
|
139
236
|
end
|
140
237
|
|
141
238
|
class Nlri
|
142
|
-
def self.factory(s, afi, safi)
|
143
|
-
|
144
|
-
|
145
|
-
|
146
|
-
|
147
|
-
|
239
|
+
def self.factory(s, afi, safi, extended=false)
|
240
|
+
if afi== 1 and safi==1
|
241
|
+
Nlri.new_ntop(s.is_packed, extended)
|
242
|
+
else
|
243
|
+
case safi
|
244
|
+
when 1,2
|
245
|
+
Prefix.new(s.is_packed, afi)
|
246
|
+
when 4,128,129
|
247
|
+
Labeled.new(s.is_packed, afi, safi)
|
248
|
+
else
|
249
|
+
raise RuntimeError, "Afi #{afi} Safi #{safi} not supported!"
|
250
|
+
end
|
148
251
|
end
|
149
252
|
end
|
150
253
|
end
|
151
254
|
|
255
|
+
class Ext_Nlri
|
256
|
+
def self.factory(s, afi, safi)
|
257
|
+
new_ntop s, afi, safi
|
258
|
+
end
|
259
|
+
def self.new_ntop(s, afi=1, safi=1)
|
260
|
+
path_id = s.slice!(0,4).unpack('N')[0]
|
261
|
+
nlri = Nlri.factory(s, afi, safi)
|
262
|
+
new path_id, nlri
|
263
|
+
end
|
264
|
+
attr :path_id, :nlri
|
265
|
+
def initialize(path_id, nlri)
|
266
|
+
@path_id=path_id
|
267
|
+
@nlri = nlri
|
268
|
+
end
|
269
|
+
def afi
|
270
|
+
@nlri.afi
|
271
|
+
end
|
272
|
+
def to_s
|
273
|
+
s = []
|
274
|
+
s << "ID=#{@path_id}"
|
275
|
+
s << @nlri.to_s
|
276
|
+
s.join(", ")
|
277
|
+
end
|
278
|
+
def encode
|
279
|
+
[@path_id, @nlri.encode].pack('Na*')
|
280
|
+
end
|
281
|
+
end
|
282
|
+
|
152
283
|
end
|
153
284
|
|
154
285
|
load "../../test/nlris/#{ File.basename($0.gsub(/.rb/,'_test.rb'))}" if __FILE__ == $0
|
286
|
+
|
287
|
+
|
288
|
+
__END__
|
289
|
+
|
290
|
+
|
291
|
+
Nlri is a collection of Nlri_elements or a collection of Path_nlri_elements
|
292
|
+
|
293
|
+
|
294
|
+
Path_nlri_element
|
295
|
+
|
296
|
+
- path_id
|
297
|
+
- Nlri_element
|
298
|
+
|
299
|
+
|
300
|
+
|
301
|
+
3. Extended NLRI Encodings
|
302
|
+
|
303
|
+
In order to carry the Path Identifier in an UPDATE message, the
|
304
|
+
existing NLRI encodings are extended by prepending the Path
|
305
|
+
Identifier field, which is of four-octets.
|
306
|
+
|
307
|
+
For example, the NLRI encodings specified in [RFC4271, RFC4760] are
|
308
|
+
extended as the following:
|
309
|
+
|
310
|
+
|
311
|
+
+--------------------------------+
|
312
|
+
| Path Identifier (4 octets) |
|
313
|
+
+--------------------------------+
|
314
|
+
| Length (1 octet) |
|
315
|
+
+--------------------------------+
|
316
|
+
| Prefix (variable) |
|
317
|
+
+--------------------------------+
|
318
|
+
|
319
|
+
|
320
|
+
and the NLRI encoding specified in [RFC3107] is extended as the
|
321
|
+
following:
|
322
|
+
|
323
|
+
|
324
|
+
|
325
|
+
|
326
|
+
|
327
|
+
Walton, et al Expiration Date February 2011 [Page 3]
|
328
|
+
|
329
|
+
|
330
|
+
|
331
|
+
|
332
|
+
|
333
|
+
INTERNET DRAFT draft-ietf-idr-add-paths-04.txt August 2010
|
334
|
+
|
335
|
+
|
336
|
+
+--------------------------------+
|
337
|
+
| Path Identifier (4 octets) |
|
338
|
+
+--------------------------------+
|
339
|
+
| Length (1 octet) |
|
340
|
+
+--------------------------------+
|
341
|
+
| Label (3 octets) |
|
342
|
+
+--------------------------------+
|
343
|
+
| ... |
|
344
|
+
+--------------------------------+
|
345
|
+
| Prefix (variable) |
|
346
|
+
+--------------------------------+
|
347
|
+
|
348
|
+
|
349
|
+
The usage of the extended NLRI encodings is specified in the
|
350
|
+
Operation section.
|
351
|
+
|
352
|
+
|
353
|
+
|
354
|
+
=======
|
355
|
+
|
356
|
+
RFC 3107 Carrying Label Information in BGP-4 May 2001
|
357
|
+
|
358
|
+
|
359
|
+
3. Carrying Label Mapping Information
|
360
|
+
|
361
|
+
Label mapping information is carried as part of the Network Layer
|
362
|
+
Reachability Information (NLRI) in the Multiprotocol Extensions
|
363
|
+
attributes. The AFI indicates, as usual, the address family of the
|
364
|
+
associated route. The fact that the NLRI contains a label is
|
365
|
+
indicated by using SAFI value 4.
|
366
|
+
|
367
|
+
The Network Layer Reachability information is encoded as one or more
|
368
|
+
triples of the form <length, label, prefix>, whose fields are
|
369
|
+
described below:
|
370
|
+
|
371
|
+
+---------------------------+
|
372
|
+
| Length (1 octet) |
|
373
|
+
+---------------------------+
|
374
|
+
| Label (3 octets) |
|
375
|
+
+---------------------------+
|
376
|
+
.............................
|
377
|
+
+---------------------------+
|
378
|
+
| Prefix (variable) |
|
379
|
+
+---------------------------+
|
380
|
+
|
381
|
+
The use and the meaning of these fields are as follows:
|
382
|
+
|
383
|
+
a) Length:
|
384
|
+
|
385
|
+
The Length field indicates the length in bits of the address
|
386
|
+
prefix plus the label(s).
|
387
|
+
|
388
|
+
b) Label:
|
389
|
+
|
390
|
+
The Label field carries one or more labels (that corresponds to
|
391
|
+
the stack of labels [MPLS-ENCAPS]). Each label is encoded as 3
|
392
|
+
octets, where the high-order 20 bits contain the label value,
|
393
|
+
and the low order bit contains "Bottom of Stack" (as defined in
|
394
|
+
[MPLS-ENCAPS]).
|
395
|
+
|
396
|
+
c) Prefix:
|
397
|
+
|
398
|
+
The Prefix field contains address prefixes followed by enough
|
399
|
+
trailing bits to make the end of the field fall on an octet
|
400
|
+
boundary. Note that the value of trailing bits is irrelevant.
|
401
|
+
|
402
|
+
|
403
|
+
|
404
|
+
Rekhter & Rosen Standards Track [Page 3]
|
405
|
+
|
406
|
+
RFC 3107 Carrying Label Information in BGP-4 May 2001
|
407
|
+
|
408
|
+
|
409
|
+
The label(s) specified for a particular route (and associated with
|
410
|
+
its address prefix) must be assigned by the LSR which is identified
|
411
|
+
by the value of the Next Hop attribute of the route.
|
412
|
+
|
413
|
+
When a BGP speaker redistributes a route, the label(s) assigned to
|
414
|
+
that route must not be changed (except by omission), unless the
|
415
|
+
speaker changes the value of the Next Hop attribute of the route.
|
416
|
+
|
417
|
+
A BGP speaker can withdraw a previously advertised route (as well as
|
418
|
+
the binding between this route and a label) by either (a) advertising
|
419
|
+
a new route (and a label) with the same NLRI as the previously
|
420
|
+
advertised route, or (b) listing the NLRI of the previously
|
421
|
+
advertised route in the Withdrawn Routes field of an Update message.
|
422
|
+
The label information carried (as part of NLRI) in the Withdrawn
|
423
|
+
Routes field should be set to 0x800000. (Of course, terminating the
|
424
|
+
BGP session also withdraws all the previously advertised routes.)
|
425
|
+
|
426
|
+
|
427
|
+
|
428
|
+
|
data/bgp/nlris/prefix.rb
CHANGED
@@ -1,6 +1,6 @@
|
|
1
1
|
require 'bgp/nlris/nlri'
|
2
2
|
module BGP
|
3
|
-
class Prefix <
|
3
|
+
class Prefix < Base_nlri::Nlri_element
|
4
4
|
def initialize(*args)
|
5
5
|
if args[0].is_a?(String) and args[0].packed?
|
6
6
|
afi = args[1] ||=1
|
@@ -30,4 +30,5 @@ module BGP
|
|
30
30
|
end
|
31
31
|
end
|
32
32
|
|
33
|
-
|
33
|
+
# FIXME:
|
34
|
+
# load "../../test/nlris/#{ File.basename($0.gsub(/.rb/,'_test.rb'))}" if __FILE__ == $0
|
data/bgp/nlris/vpn.rb
CHANGED
@@ -52,17 +52,10 @@ module BGP
|
|
52
52
|
@prefix.ipv6?
|
53
53
|
end
|
54
54
|
def parse(s, afi=1)
|
55
|
-
# p "-----------"
|
56
|
-
# p s.unpack('H*')
|
57
|
-
# p afi
|
58
55
|
nbits = s.slice!(0,1).unpack('C')[0]
|
59
56
|
rd,vpn = s.slice!(0,(7+nbits)/8).unpack("a8a*")
|
60
57
|
@rd = Rd.new(rd.is_packed)
|
61
|
-
|
62
|
-
# p nbits
|
63
|
-
# p vpn.unpack('H*')
|
64
|
-
raise if nbits-64==0
|
65
|
-
@prefix= Prefix.new([nbits-64,vpn].pack('Ca*'), afi) if nbits-64>0
|
58
|
+
@prefix= Prefix.new([nbits-64,vpn].pack('Ca*'), afi)
|
66
59
|
end
|
67
60
|
def nexthop
|
68
61
|
@prefix.nexthop
|