bgp4r 0.0.9 → 0.0.10
Sign up to get free protection for your applications and to get access to all the features.
- data/bgp/messages/message.rb +12 -1
- data/bgp/messages/messages.rb +6 -2
- data/bgp/messages/update.rb +5 -1
- data/bgp/misc/live_feed.rb +49 -0
- data/bgp/neighbor.rb +18 -2
- data/bgp/path_attributes/as_path.rb +12 -4
- data/bgp/path_attributes/attribute.rb +4 -0
- data/bgp/path_attributes/attributes.rb +18 -17
- data/bgp/path_attributes/communities.rb +43 -14
- data/bgp/path_attributes/local_pref.rb +4 -0
- data/bgp/path_attributes/multi_exit_disc.rb +4 -0
- data/bgp/path_attributes/path_attribute.rb +61 -31
- data/bgp4r.gemspec +8 -3
- data/examples/a_live_feed +77 -0
- data/examples/routegen +0 -2
- data/examples/unit-testing/malformed_update.rb +1 -5
- data/examples/unit-testing/no_export.rb +111 -0
- data/test/messages/message_test.rb +7 -0
- data/test/messages/update_test.rb +30 -2
- data/test/nlris/ext_nlri_test.rb +67 -0
- data/test/path_attributes/as_path_test.rb +5 -1
- data/test/path_attributes/communities_test.rb +17 -1
- data/test/path_attributes/local_pref_test.rb +8 -0
- data/test/path_attributes/multi_exit_disc_test.rb +8 -0
- data/test/path_attributes/path_attribute_test.rb +8 -1
- metadata +9 -7
data/bgp/messages/message.rb
CHANGED
@@ -76,9 +76,20 @@ module BGP
|
|
76
76
|
end
|
77
77
|
def self.route_refresh(afi,safi)
|
78
78
|
Route_refresh.new(afi,safi).encode
|
79
|
+
end
|
80
|
+
%w{update keepalive open notification capabity route_refresh }.each do |m|
|
81
|
+
define_method("is_a_#{m}?") do
|
82
|
+
is_a?(BGP.const_get(m.capitalize))
|
83
|
+
end
|
84
|
+
eval "alias :is_an_#{m}? :is_a_#{m}?" if (m =~ /^[aeiou]/)
|
85
|
+
end
|
86
|
+
def has_no_path_attribute?
|
87
|
+
path_attribute.nil?
|
88
|
+
end
|
89
|
+
def has_a_path_attribute?
|
90
|
+
! has_no_path_attribute?
|
79
91
|
end
|
80
92
|
end
|
81
|
-
|
82
93
|
end
|
83
94
|
|
84
95
|
load "../../test/messages/#{ File.basename($0.gsub(/.rb/,'_test.rb'))}" if __FILE__ == $0
|
data/bgp/messages/messages.rb
CHANGED
@@ -7,11 +7,15 @@ module BGP
|
|
7
7
|
rescue
|
8
8
|
end
|
9
9
|
|
10
|
-
%w{ update keepalive open notification
|
11
|
-
autoload "#{m}".capitalize.to_sym, "bgp/messages/#{m}"
|
10
|
+
%w{ update keepalive open notification capabity}.each do |m|
|
11
|
+
autoload "#{m}".capitalize.to_sym, "bgp/messages/#{m}"
|
12
12
|
end
|
13
13
|
autoload :Route_refresh, 'bgp/messages/route_refresh'
|
14
14
|
autoload :Orf_route_refresh, 'bgp/messages/route_refresh'
|
15
15
|
autoload :Prefix_orf, 'bgp/orfs/prefix_orf'
|
16
16
|
|
17
17
|
end
|
18
|
+
|
19
|
+
|
20
|
+
|
21
|
+
require 'bgp/messages/markers'
|
data/bgp/messages/update.rb
CHANGED
@@ -46,6 +46,8 @@ class Update < Message
|
|
46
46
|
def as4byte?
|
47
47
|
@as4byte ||= false
|
48
48
|
end
|
49
|
+
alias as4byte as4byte?
|
50
|
+
|
49
51
|
def initialize(*args)
|
50
52
|
if args[0].is_a?(String) and args[0].is_packed?
|
51
53
|
@as4byte=false
|
@@ -125,8 +127,10 @@ class Update < Message
|
|
125
127
|
end
|
126
128
|
end
|
127
129
|
|
128
|
-
def to_s(as4byte=@as4byte
|
130
|
+
def to_s(as4byte=@as4byte)
|
131
|
+
# def to_s(fmt=:tcpdump)
|
129
132
|
msg = encode(as4byte)
|
133
|
+
fmt=:tcpdump
|
130
134
|
s = []
|
131
135
|
s << @withdrawn.to_s if defined?(@withdrawn) and @withdrawn
|
132
136
|
s << @path_attribute.to_s(fmt, as4byte) if defined?(@path_attribute) and @path_attribute
|
@@ -0,0 +1,49 @@
|
|
1
|
+
require 'net/telnet'
|
2
|
+
require 'bgp4r'
|
3
|
+
|
4
|
+
|
5
|
+
class LiveFeed
|
6
|
+
def initialize
|
7
|
+
@host = '129.82.138.6'
|
8
|
+
@port = '50001'
|
9
|
+
@timeout = 10
|
10
|
+
end
|
11
|
+
|
12
|
+
def open
|
13
|
+
|
14
|
+
@buf = ''
|
15
|
+
@queue = Queue.new
|
16
|
+
|
17
|
+
th = Thread.new do
|
18
|
+
feed = Net::Telnet.new('Host'=> @host,
|
19
|
+
'Port' => @port,
|
20
|
+
'Timeout'=> 5,
|
21
|
+
'Telnetmode' => false)
|
22
|
+
loop do
|
23
|
+
@buf += feed.recv(2000)
|
24
|
+
end
|
25
|
+
end
|
26
|
+
Thread.new do
|
27
|
+
loop do
|
28
|
+
pos = (@buf =~ /<OCTETS length=.*>([^<]*)<\/OCTETS>/)
|
29
|
+
if pos
|
30
|
+
@queue.enq [$1].pack('H*')
|
31
|
+
@buf.slice!(0,pos+10)
|
32
|
+
sleep(0.1)
|
33
|
+
end
|
34
|
+
end
|
35
|
+
end
|
36
|
+
end
|
37
|
+
|
38
|
+
def read
|
39
|
+
@queue.deq
|
40
|
+
end
|
41
|
+
|
42
|
+
alias msg read
|
43
|
+
alias readmessage read
|
44
|
+
|
45
|
+
end
|
46
|
+
|
47
|
+
|
48
|
+
|
49
|
+
|
data/bgp/neighbor.rb
CHANGED
@@ -30,10 +30,23 @@ module BGP
|
|
30
30
|
class Neighbor
|
31
31
|
include Observable
|
32
32
|
|
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
|
+
|
33
42
|
def log_info(txt)
|
34
43
|
Log.info "#{self.class} #{txt}"
|
35
44
|
end
|
36
45
|
|
46
|
+
def log_warn(txt)
|
47
|
+
Log.warn "#{self.class} #{txt}"
|
48
|
+
end
|
49
|
+
|
37
50
|
def log_debug(txt)
|
38
51
|
Log.debug "#{self.class} #{txt}"
|
39
52
|
end
|
@@ -214,16 +227,18 @@ module BGP
|
|
214
227
|
@out.thread
|
215
228
|
end
|
216
229
|
|
230
|
+
attr_reader :as4byte
|
217
231
|
|
218
232
|
def send_message(m)
|
219
233
|
raise if m.nil?
|
220
234
|
return unless @out
|
221
235
|
unless m.is_a?(String)
|
222
236
|
log_info "Send#{m.class.to_s.split('::')[-1]}"
|
223
|
-
log_debug "Send #{m.is_a?(Update) ? m.to_s
|
237
|
+
log_debug "Send #{m.is_a?(Update) ? m.to_s : m }\n"
|
224
238
|
end
|
239
|
+
#FIXME: enqueue [m, as4byte]
|
225
240
|
if m.is_a?(Update)
|
226
|
-
@out.enq m.encode(
|
241
|
+
@out.enq m.encode(as4byte)
|
227
242
|
else
|
228
243
|
@out.enq m
|
229
244
|
end
|
@@ -305,6 +320,7 @@ module BGP
|
|
305
320
|
|
306
321
|
def rcv_notification(m)
|
307
322
|
log_info "#{m}"
|
323
|
+
changed and notify_observers(m)
|
308
324
|
disable
|
309
325
|
end
|
310
326
|
|
@@ -26,8 +26,6 @@ module BGP
|
|
26
26
|
|
27
27
|
class As_path < Attr
|
28
28
|
|
29
|
-
##############################
|
30
|
-
|
31
29
|
class Segment
|
32
30
|
include ATTR
|
33
31
|
|
@@ -62,6 +60,10 @@ module BGP
|
|
62
60
|
@seg_type
|
63
61
|
end
|
64
62
|
|
63
|
+
def prepend(as)
|
64
|
+
@as.insert(0,as)
|
65
|
+
end
|
66
|
+
|
65
67
|
def seg_type=(val)
|
66
68
|
case val
|
67
69
|
when :set ; @seg_type = SET
|
@@ -147,8 +149,6 @@ module BGP
|
|
147
149
|
end
|
148
150
|
end
|
149
151
|
|
150
|
-
##############################
|
151
|
-
|
152
152
|
def integer?(arg)
|
153
153
|
arg.is_a?(Fixnum) or arg.is_a?(Bignum)
|
154
154
|
end
|
@@ -196,6 +196,14 @@ module BGP
|
|
196
196
|
super(as_path, method, as4byte)
|
197
197
|
end
|
198
198
|
|
199
|
+
def find_set
|
200
|
+
@segments.find { |s| s.seg_type == SET }
|
201
|
+
end
|
202
|
+
|
203
|
+
def find_sequence
|
204
|
+
@segments.find { |s| s.seg_type == SEQUENCE }
|
205
|
+
end
|
206
|
+
|
199
207
|
private
|
200
208
|
|
201
209
|
def parse(s,as4byte=false)
|
@@ -1,21 +1,22 @@
|
|
1
1
|
|
2
2
|
module BGP
|
3
|
+
%w{
|
4
|
+
origin next_hop
|
5
|
+
local_pref
|
6
|
+
multi_exit_disc
|
7
|
+
as_path
|
8
|
+
communities
|
9
|
+
aggregator
|
10
|
+
atomic_aggregate
|
11
|
+
originator_id
|
12
|
+
cluster_list
|
13
|
+
mp_reach
|
14
|
+
mp_unreach
|
15
|
+
extended_communities
|
16
|
+
path_attribute
|
17
|
+
}.each do |attr|
|
18
|
+
autoload attr.capitalize.to_sym,"bgp/path_attributes/#{attr}"
|
19
|
+
end
|
20
|
+
autoload :As4_path, 'bgp/path_attributes/as_path'
|
3
21
|
end
|
4
22
|
|
5
|
-
%w{
|
6
|
-
origin next_hop
|
7
|
-
local_pref
|
8
|
-
multi_exit_disc
|
9
|
-
as_path
|
10
|
-
communities
|
11
|
-
aggregator
|
12
|
-
atomic_aggregate
|
13
|
-
originator_id
|
14
|
-
cluster_list
|
15
|
-
mp_reach
|
16
|
-
mp_unreach
|
17
|
-
extended_communities
|
18
|
-
path_attribute
|
19
|
-
}.each do |attr|
|
20
|
-
BGP.autoload attr.capitalize.to_sym,"bgp/path_attributes/#{attr}"
|
21
|
-
end
|
@@ -20,35 +20,42 @@
|
|
20
20
|
# along with BGP4R. If not, see <http://www.gnu.org/licenses/>.
|
21
21
|
#++
|
22
22
|
|
23
|
-
|
24
23
|
require 'bgp/path_attributes/attribute'
|
25
24
|
|
26
|
-
|
27
25
|
module BGP
|
28
26
|
|
29
27
|
class Communities < Attr
|
30
28
|
|
31
29
|
class Community
|
32
30
|
|
31
|
+
unless const_defined? :NO_EXPORT
|
32
|
+
NO_EXPORT = 0xFFFFFF01
|
33
|
+
NO_ADVERTISE = 0xFFFFFF02
|
34
|
+
NO_EXPORT_SUB_CONFED = 0xFFFFFF03
|
35
|
+
NO_PEER = 0xFFFFFF04
|
36
|
+
end
|
37
|
+
|
33
38
|
def initialize(arg)
|
34
39
|
if arg.is_a?(Symbol)
|
35
40
|
case arg
|
36
|
-
when :no_export
|
37
|
-
when :no_advertise
|
38
|
-
when :no_export_sub_confed ; @value=
|
39
|
-
when :no_peer
|
41
|
+
when :no_export ; @value=NO_EXPORT
|
42
|
+
when :no_advertise ; @value=NO_ADVERTISE
|
43
|
+
when :no_export_sub_confed ; @value=NO_EXPORT_SUB_CONFED
|
44
|
+
when :no_peer ; @value=NO_PEER
|
40
45
|
else
|
41
|
-
raise ArgumentError, "invalid argument #{
|
46
|
+
raise ArgumentError, "invalid argument #{arg.inspect}"
|
42
47
|
end
|
43
48
|
elsif arg.is_a?(String) and arg.split(':').size==2
|
44
49
|
self.value=arg.split(':').collect { |n| n.to_i }.pack('n2').unpack('N')[0]
|
50
|
+
elsif arg.respond_to?(:to_i)
|
51
|
+
self.value= arg.to_i
|
45
52
|
else
|
46
53
|
self.value=arg
|
47
54
|
end
|
48
55
|
end
|
49
56
|
|
50
57
|
def value=(val)
|
51
|
-
raise ArgumentError, "invalid argument #{val}" unless val.is_a?(
|
58
|
+
raise ArgumentError, "invalid argument #{val.inspect}" unless val.is_a?(Integer)
|
52
59
|
@value=val
|
53
60
|
end
|
54
61
|
|
@@ -96,6 +103,7 @@ module BGP
|
|
96
103
|
@communities << Community.new(arg)
|
97
104
|
end
|
98
105
|
end
|
106
|
+
self
|
99
107
|
end
|
100
108
|
alias << add
|
101
109
|
|
@@ -107,10 +115,6 @@ module BGP
|
|
107
115
|
super(communities, method)
|
108
116
|
end
|
109
117
|
|
110
|
-
def to_ary
|
111
|
-
@communities.collect { |c| c.to_i }
|
112
|
-
end
|
113
|
-
|
114
118
|
def encode
|
115
119
|
super(@communities.collect { |comm| comm.encode }.join)
|
116
120
|
end
|
@@ -121,7 +125,7 @@ module BGP
|
|
121
125
|
end
|
122
126
|
|
123
127
|
def sort
|
124
|
-
Communities.new(
|
128
|
+
Communities.new(to_a.sort)
|
125
129
|
end
|
126
130
|
|
127
131
|
def sort!
|
@@ -132,8 +136,33 @@ module BGP
|
|
132
136
|
def <=>(other)
|
133
137
|
self.sort.to_shex <=> other.sort.to_shex
|
134
138
|
end
|
139
|
+
|
140
|
+
def has?(arg)
|
141
|
+
! has_no?(arg)
|
142
|
+
end
|
135
143
|
|
136
|
-
|
144
|
+
def has_no?(arg)
|
145
|
+
@communities.find { |c| c.to_i == arg_comm_to_i(arg) }.nil?
|
146
|
+
end
|
147
|
+
|
148
|
+
%w{ no_export no_advertise no_export_sub_confed no_peer }.each do |wkc|
|
149
|
+
define_method("has_#{wkc}?") do
|
150
|
+
! has? Community.const_get(wkc.upcase)
|
151
|
+
end
|
152
|
+
end
|
153
|
+
|
154
|
+
private
|
155
|
+
|
156
|
+
def arg_comm_to_i(arg)
|
157
|
+
return arg if arg.is_a?(Integer)
|
158
|
+
Community.new(arg).to_i
|
159
|
+
end
|
137
160
|
|
161
|
+
def to_a
|
162
|
+
@communities.collect { |c| c.to_i }
|
163
|
+
end
|
164
|
+
|
165
|
+
end
|
166
|
+
|
138
167
|
end
|
139
168
|
load "../../test/path_attributes/#{ File.basename($0.gsub(/.rb/,'_test.rb'))}" if __FILE__ == $0
|
@@ -27,6 +27,8 @@ module BGP
|
|
27
27
|
|
28
28
|
class Path_attribute
|
29
29
|
include BGP::ATTR
|
30
|
+
attr_reader :attributes
|
31
|
+
|
30
32
|
def initialize(*args)
|
31
33
|
if args.size <= 2 and args[0].is_a?(String) and args[0].is_packed?
|
32
34
|
s = args[0]
|
@@ -45,10 +47,6 @@ module BGP
|
|
45
47
|
end
|
46
48
|
alias << add
|
47
49
|
|
48
|
-
def to_ary
|
49
|
-
@attributes
|
50
|
-
end
|
51
|
-
|
52
50
|
def to_s(method=:default,as4byte=false)
|
53
51
|
"Path Attributes:" + ([""] + @attributes.collect { |a|
|
54
52
|
if as4byte and a.is_a?(As_path)
|
@@ -90,7 +88,7 @@ module BGP
|
|
90
88
|
find(Atomic_aggregate)
|
91
89
|
when AGGREGATOR, :aggregator
|
92
90
|
find(Aggregator)
|
93
|
-
when COMMUNITIES, :communities
|
91
|
+
when COMMUNITIES, :communities, :community
|
94
92
|
find(Communities)
|
95
93
|
when ORIGINATOR_ID, :originator_id
|
96
94
|
find(Originator_id)
|
@@ -105,6 +103,8 @@ module BGP
|
|
105
103
|
when AS4_PATH, :as4_path
|
106
104
|
find(As4_path)
|
107
105
|
when AS4_AGGREGATOR, :as4_aggregator
|
106
|
+
else
|
107
|
+
find(type)
|
108
108
|
end
|
109
109
|
end
|
110
110
|
|
@@ -121,6 +121,10 @@ module BGP
|
|
121
121
|
end
|
122
122
|
end
|
123
123
|
|
124
|
+
def has_no?(arg)
|
125
|
+
! has?(arg)
|
126
|
+
end
|
127
|
+
|
124
128
|
def encode(as4byte=false)
|
125
129
|
[@attributes.compact.collect { |x| as4byte ? x.encode4 : x.encode }.join].pack('a*')
|
126
130
|
end
|
@@ -128,7 +132,7 @@ module BGP
|
|
128
132
|
def insert(*args)
|
129
133
|
for arg in args
|
130
134
|
next unless arg.is_a?(Attr)
|
131
|
-
|
135
|
+
attributes.insert(0,arg)
|
132
136
|
end
|
133
137
|
self
|
134
138
|
end
|
@@ -136,7 +140,7 @@ module BGP
|
|
136
140
|
def append(*args)
|
137
141
|
for arg in args
|
138
142
|
next unless arg.is_a?(Attr)
|
139
|
-
|
143
|
+
attributes << (arg)
|
140
144
|
end
|
141
145
|
self
|
142
146
|
end
|
@@ -144,12 +148,11 @@ module BGP
|
|
144
148
|
def replace(*args)
|
145
149
|
for arg in args
|
146
150
|
next unless arg.is_a?(Attr)
|
147
|
-
|
148
|
-
if
|
149
|
-
|
151
|
+
ind = attributes.find_index { |x| x.class == arg.class }
|
152
|
+
if ind
|
153
|
+
attributes[ind] = arg
|
150
154
|
else
|
151
|
-
|
152
|
-
to_ary[index] = arg
|
155
|
+
append(arg)
|
153
156
|
end
|
154
157
|
end
|
155
158
|
self
|
@@ -158,35 +161,63 @@ module BGP
|
|
158
161
|
def delete(*klasses)
|
159
162
|
for klass in klasses
|
160
163
|
next unless klass.is_a?(Class)
|
161
|
-
|
164
|
+
attributes.delete_if { |x| x.class == klass }
|
162
165
|
end
|
163
166
|
self
|
164
167
|
end
|
165
|
-
|
168
|
+
|
169
|
+
%w{
|
170
|
+
origin
|
171
|
+
next_hop
|
172
|
+
local_pref
|
173
|
+
multi_exit_disc
|
174
|
+
as_path
|
175
|
+
communities
|
176
|
+
aggregator
|
177
|
+
atomic_aggregate
|
178
|
+
originator_id
|
179
|
+
cluster_list
|
180
|
+
mp_reach
|
181
|
+
mp_unreach
|
182
|
+
extended_communities
|
183
|
+
}.each do |attr|
|
184
|
+
define_method("has_a_#{attr}_attr?") do
|
185
|
+
has? BGP.const_get(attr.capitalize)
|
186
|
+
end
|
187
|
+
eval "alias :has_an_#{attr}? :has_a_#{attr}_attr?" if (attr =~ /^[aeiou]/)
|
188
|
+
end
|
189
|
+
|
190
|
+
private
|
191
|
+
|
192
|
+
def att_sym_to_klass(sym)
|
193
|
+
case sym
|
194
|
+
when :communities, :community ; Communities
|
195
|
+
end
|
196
|
+
end
|
166
197
|
end
|
167
|
-
|
168
198
|
end
|
169
199
|
|
170
200
|
module BGP
|
171
201
|
|
172
202
|
class Attr
|
173
|
-
|
174
|
-
|
175
|
-
|
176
|
-
|
177
|
-
|
178
|
-
|
179
|
-
|
203
|
+
unless const_defined? :Unknown
|
204
|
+
Unknown = Class.new(Attr) do
|
205
|
+
attr_reader :type, :flags, :value
|
206
|
+
def initialize(*args)
|
207
|
+
if args.size>1
|
208
|
+
@flags, @type, len, @value=args
|
209
|
+
else
|
210
|
+
parse(*args)
|
211
|
+
end
|
212
|
+
end
|
213
|
+
def encode
|
214
|
+
super(@value)
|
215
|
+
end
|
216
|
+
def parse(s)
|
217
|
+
@flags, @type, len, @value = super
|
180
218
|
end
|
181
|
-
end
|
182
|
-
def encode
|
183
|
-
super(@value)
|
184
|
-
end
|
185
|
-
def parse(s)
|
186
|
-
@flags, @type, len, @value = super
|
187
219
|
end
|
188
220
|
end
|
189
|
-
|
190
221
|
include BGP::ATTR
|
191
222
|
def self.factory(s, as4byte=false)
|
192
223
|
flags, type = s.unpack('CC')
|
@@ -223,9 +254,8 @@ module BGP
|
|
223
254
|
Unknown.new(s)
|
224
255
|
end
|
225
256
|
end
|
226
|
-
|
257
|
+
|
227
258
|
end
|
228
|
-
|
229
259
|
end
|
230
260
|
|
231
261
|
load "../../test/path_attributes/#{ File.basename($0.gsub(/.rb/,'_test.rb'))}" if __FILE__ == $0
|
data/bgp4r.gemspec
CHANGED
@@ -5,11 +5,11 @@
|
|
5
5
|
|
6
6
|
Gem::Specification.new do |s|
|
7
7
|
s.name = %q{bgp4r}
|
8
|
-
s.version = "0.0.
|
8
|
+
s.version = "0.0.10"
|
9
9
|
|
10
10
|
s.required_rubygems_version = Gem::Requirement.new(">= 0") if s.respond_to? :required_rubygems_version=
|
11
11
|
s.authors = ["Jean-Michel Esnault"]
|
12
|
-
s.date = %q{2010-10-
|
12
|
+
s.date = %q{2010-10-30}
|
13
13
|
s.description = %q{BGP4R is a BGP-4 ruby library to create, send, and receive BGP messages in an object oriented manner}
|
14
14
|
s.email = %q{jesnault@gmail.com}
|
15
15
|
s.extra_rdoc_files = [
|
@@ -32,6 +32,7 @@ Gem::Specification.new do |s|
|
|
32
32
|
"bgp/messages/open.rb",
|
33
33
|
"bgp/messages/route_refresh.rb",
|
34
34
|
"bgp/messages/update.rb",
|
35
|
+
"bgp/misc/live_feed.rb",
|
35
36
|
"bgp/neighbor.rb",
|
36
37
|
"bgp/nlris/inet.rb",
|
37
38
|
"bgp/nlris/label.rb",
|
@@ -71,10 +72,12 @@ Gem::Specification.new do |s|
|
|
71
72
|
"bgp/path_attributes/path_attribute.rb",
|
72
73
|
"bgp4r.gemspec",
|
73
74
|
"bgp4r.rb",
|
75
|
+
"examples/a_live_feed",
|
74
76
|
"examples/routegen",
|
75
77
|
"examples/routegen.yml",
|
76
78
|
"examples/simple.rb",
|
77
79
|
"examples/unit-testing/malformed_update.rb",
|
80
|
+
"examples/unit-testing/no_export.rb",
|
78
81
|
"examples/unit-testing/prepend_aspath.rb",
|
79
82
|
"examples/unit-testing/unknown_transitive_attr.rb",
|
80
83
|
"test/common_test.rb",
|
@@ -87,6 +90,7 @@ Gem::Specification.new do |s|
|
|
87
90
|
"test/messages/route_refresh_test.rb",
|
88
91
|
"test/messages/update_test.rb",
|
89
92
|
"test/neighbor_test.rb",
|
93
|
+
"test/nlris/ext_nlri_test.rb",
|
90
94
|
"test/nlris/inet_test.rb",
|
91
95
|
"test/nlris/labeled_test.rb",
|
92
96
|
"test/nlris/nlri_test.rb",
|
@@ -118,7 +122,7 @@ Gem::Specification.new do |s|
|
|
118
122
|
"test/path_attributes/path_attribute_test.rb"
|
119
123
|
]
|
120
124
|
s.homepage = %q{http://github.com/jesnault/bgp4r/tree/master}
|
121
|
-
s.rdoc_options = ["--
|
125
|
+
s.rdoc_options = ["--charset=UTF-8"]
|
122
126
|
s.require_paths = ["."]
|
123
127
|
s.required_ruby_version = Gem::Requirement.new(">= 1.8.6")
|
124
128
|
s.rubyforge_project = %q{bgp4r}
|
@@ -137,6 +141,7 @@ Gem::Specification.new do |s|
|
|
137
141
|
"test/messages/update_test.rb",
|
138
142
|
"test/neighbor_test.rb",
|
139
143
|
"test/nlris",
|
144
|
+
"test/nlris/ext_nlri_test.rb",
|
140
145
|
"test/nlris/inet_test.rb",
|
141
146
|
"test/nlris/labeled_test.rb",
|
142
147
|
"test/nlris/nlri_test.rb",
|
@@ -0,0 +1,77 @@
|
|
1
|
+
|
2
|
+
require 'bgp4r'
|
3
|
+
require 'bgp/misc/live_feed'
|
4
|
+
|
5
|
+
include BGP
|
6
|
+
|
7
|
+
Log.create
|
8
|
+
Log.level=Logger::DEBUG
|
9
|
+
|
10
|
+
def start_peering
|
11
|
+
[@n100].each { |n| n.start }
|
12
|
+
end
|
13
|
+
|
14
|
+
class RecvMsgHandler
|
15
|
+
def initialize(q)
|
16
|
+
@q = q
|
17
|
+
end
|
18
|
+
def update(bgp_msg)
|
19
|
+
@q.enq bgp_msg if bgp_msg.is_a_notification?
|
20
|
+
end
|
21
|
+
end
|
22
|
+
|
23
|
+
N100 = Class.new(Neighbor)
|
24
|
+
@n100 = N100.new(:my_as=> 100,
|
25
|
+
:remote_addr => '40.0.0.2',
|
26
|
+
:local_addr => '40.0.0.1',
|
27
|
+
:id=> '13.11.19.59')
|
28
|
+
|
29
|
+
queue = Queue.new
|
30
|
+
@n100.add_observer RecvMsgHandler.new(queue)
|
31
|
+
|
32
|
+
start_peering
|
33
|
+
|
34
|
+
feed = LiveFeed.new
|
35
|
+
feed.open
|
36
|
+
|
37
|
+
(1..20000).each do |_n|
|
38
|
+
|
39
|
+
msg = Message.factory(feed.msg)
|
40
|
+
|
41
|
+
if msg.is_an_update? and msg.has_a_path_attribute?
|
42
|
+
|
43
|
+
path_attr = msg.path_attribute
|
44
|
+
|
45
|
+
# pick and choose the update we want
|
46
|
+
next if path_attr.has?(Mp_reach) ||
|
47
|
+
path_attr.has?(Mp_unreach) ||
|
48
|
+
path_attr.has?(Atomic_aggregate)
|
49
|
+
|
50
|
+
# and set the path attribute.
|
51
|
+
path_attr.replace Next_hop.new('40.0.0.1')
|
52
|
+
path_attr[:as_path].find_sequence.prepend(100)
|
53
|
+
path_attr.has?(Communities) ? path_attr[Communities].add('13:11') : path_attr.insert(Communities.new'13:11')
|
54
|
+
|
55
|
+
if queue.size > 1
|
56
|
+
puts $prev_msg
|
57
|
+
puts queue.deq
|
58
|
+
p queue.deq
|
59
|
+
exit
|
60
|
+
end
|
61
|
+
|
62
|
+
# ship it!
|
63
|
+
@n100.send_message msg
|
64
|
+
$prev_msg = msg
|
65
|
+
|
66
|
+
elsif msg.is_an_update? and msg.has_no_path_attribute?
|
67
|
+
|
68
|
+
# it's a withdrawn,
|
69
|
+
@n100.send_message msg
|
70
|
+
|
71
|
+
end
|
72
|
+
|
73
|
+
end
|
74
|
+
|
75
|
+
sleep(200)
|
76
|
+
|
77
|
+
__END__
|
data/examples/routegen
CHANGED
@@ -0,0 +1,111 @@
|
|
1
|
+
require "test/unit"
|
2
|
+
require 'bgp4r'
|
3
|
+
require 'timeout'
|
4
|
+
|
5
|
+
Thread.abort_on_exception=true
|
6
|
+
|
7
|
+
class TestBgp < Test::Unit::TestCase
|
8
|
+
|
9
|
+
include BGP
|
10
|
+
|
11
|
+
Log.create
|
12
|
+
Log.level=Logger::DEBUG
|
13
|
+
|
14
|
+
N100 = Class.new(BGP::Neighbor)
|
15
|
+
N300 = Class.new(BGP::Neighbor)
|
16
|
+
|
17
|
+
class RecvMsgHandler
|
18
|
+
def initialize(q)
|
19
|
+
@q = q
|
20
|
+
end
|
21
|
+
def update(m)
|
22
|
+
@q.enq m if m.is_an_update?
|
23
|
+
end
|
24
|
+
end
|
25
|
+
|
26
|
+
def setup
|
27
|
+
@n100 = N100.new(:my_as=> 100, :remote_addr => '40.0.0.2', :local_addr => '40.0.0.1', :id=> '13.11.19.59')
|
28
|
+
@n300 = N300.new(:my_as=> 300, :remote_addr => '40.0.1.1', :local_addr => '40.0.1.2', :id=> '13.11.19.57')
|
29
|
+
start_peering
|
30
|
+
end
|
31
|
+
|
32
|
+
def test_verify_that_route_a_route_with_no_export_community_set_is_not_advertised
|
33
|
+
assert @n100.is_established?, "Expected to be in Established state. <> #{@n100.state}"
|
34
|
+
assert @n300.is_established?, "Expected to be in Established state. <> #{@n300.state}"
|
35
|
+
queue = Queue.new
|
36
|
+
@n300.add_observer RecvMsgHandler.new(queue)
|
37
|
+
|
38
|
+
# advertise a bunch of routes and verity they are advertised as expected.
|
39
|
+
@n100.send_message an_exportable_update
|
40
|
+
msg = recv(queue)
|
41
|
+
assert msg, "Did not receive expected BGP update message."
|
42
|
+
assert msg.path_attribute.has_a_communities_attr?, "It should have contained a COMMUNITY attribute."
|
43
|
+
assert msg.path_attribute[:communities].has?('1311:1'), "It should have contained community 1311:11."
|
44
|
+
|
45
|
+
# send it again with no_export set.
|
46
|
+
# we should be asked to withdraw the previously advertise routes.
|
47
|
+
@n100.send_message a_non_exportable_update
|
48
|
+
msg = recv(queue)
|
49
|
+
assert(msg)
|
50
|
+
assert msg.is_an_update?
|
51
|
+
assert msg.has_no_path_attribute?, "We should have received a route withdrawal with previous advertised routes."
|
52
|
+
assert_equal "77.0.0.0/17\n78.0.0.0/18\n79.0.0.0/19", msg.withdrawn.to_s
|
53
|
+
|
54
|
+
# send it again, this time nothing to withdraw, hence no update to receive.
|
55
|
+
@n100.send_message a_non_exportable_update
|
56
|
+
msg = recv(queue)
|
57
|
+
assert_nil(msg)
|
58
|
+
|
59
|
+
# advertise yet again without no_export and we shall receive an update from n300
|
60
|
+
@n100.send_message an_exportable_update
|
61
|
+
msg = recv(queue)
|
62
|
+
assert msg, "Did not receive expected BGP update message."
|
63
|
+
assert msg.path_attribute.has_a_communities_attr?, "It should have contained a COMMUNITY attribute."
|
64
|
+
assert msg.path_attribute[:communities].has?('1311:1'), "It should have contained community 1311:11."
|
65
|
+
end
|
66
|
+
|
67
|
+
def teardown
|
68
|
+
[@n100, @n300].each { |n| n.stop }
|
69
|
+
sleep(0.5)
|
70
|
+
end
|
71
|
+
|
72
|
+
private
|
73
|
+
|
74
|
+
def start_peering
|
75
|
+
[@n100, @n300].each { |n|
|
76
|
+
n.capability :as4_byte
|
77
|
+
n.start
|
78
|
+
}
|
79
|
+
end
|
80
|
+
|
81
|
+
def recv(q, timeout=5)
|
82
|
+
begin
|
83
|
+
Timeout::timeout(timeout) do |t|
|
84
|
+
msg = q.deq
|
85
|
+
end
|
86
|
+
rescue Timeout::Error => e
|
87
|
+
nil
|
88
|
+
end
|
89
|
+
end
|
90
|
+
|
91
|
+
def an_exportable_update
|
92
|
+
update = Update.new(
|
93
|
+
Path_attribute.new(
|
94
|
+
Origin.new(0),
|
95
|
+
Next_hop.new('40.0.0.1'),
|
96
|
+
Multi_exit_disc.new(100),
|
97
|
+
Local_pref.new(100),
|
98
|
+
As_path.new(100),
|
99
|
+
Communities.new('1311:1 311:59 2805:64')
|
100
|
+
),
|
101
|
+
Nlri.new('77.0.0.0/17', '78.0.0.0/18', '79.0.0.0/19')
|
102
|
+
)
|
103
|
+
end
|
104
|
+
|
105
|
+
def a_non_exportable_update
|
106
|
+
update = an_exportable_update.clone
|
107
|
+
update.path_attribute[:communities].add(:no_export)
|
108
|
+
update
|
109
|
+
end
|
110
|
+
|
111
|
+
end
|
@@ -40,4 +40,11 @@ class Message_Test < Test::Unit::TestCase
|
|
40
40
|
msg2 = MyMessage.new(msg1.encode)
|
41
41
|
assert_equal('abcdefghihjklmopqrstuvwxyz',msg2.data)
|
42
42
|
end
|
43
|
+
def test_2
|
44
|
+
msg = MyMessage.new
|
45
|
+
assert msg.respond_to? :is_an_update?
|
46
|
+
assert msg.respond_to? :is_an_open?
|
47
|
+
assert msg.respond_to? :is_a_notification?
|
48
|
+
assert msg.respond_to? :is_a_route_refresh?
|
49
|
+
end
|
43
50
|
end
|
@@ -126,8 +126,36 @@ class Update_Test < Test::Unit::TestCase
|
|
126
126
|
originator-id: 10.0.0.2
|
127
127
|
cluster: 0.0.0.1
|
128
128
|
"
|
129
|
-
|
130
|
-
|
131
129
|
end
|
130
|
+
|
131
|
+
def test_7
|
132
|
+
s = 'FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF0072020000001F4001010040020A0204212C051319351AFE400304557200D9C00804212C045C175D76D6175D76DE1659299C175929981659235C16592D6417592D6417592D6617592D6217C3D228185D73241859284417C3FE84165C727015592190'
|
133
|
+
m = Update.new([s].pack('H*'), true)
|
134
|
+
pa = m.path_attribute
|
135
|
+
assert_equal '556533011 422910718', pa[As_path].as_path
|
136
|
+
assert_equal '85.114.0.217', pa[Next_hop].next_hop
|
137
|
+
pa.replace Next_hop.new('10.0.0.1')
|
138
|
+
assert_equal '10.0.0.1', pa[Next_hop].next_hop
|
139
|
+
pa[:as_path].find_sequence.prepend(100)
|
140
|
+
assert_equal '100 556533011 422910718', pa[As_path].as_path
|
141
|
+
end
|
142
|
+
|
143
|
+
# def test_8
|
144
|
+
# s = 'FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF002302000C16D403741755C68816D408300000'
|
145
|
+
# m = Update.new([s].pack('H*'))
|
146
|
+
# end
|
147
|
+
#
|
148
|
+
# def test_9
|
149
|
+
# s = 'ffff ffff ffff ffff ffff ffff ffff ffff
|
150
|
+
# 005f 0200 0000 4440 0101 0040 020e 0206
|
151
|
+
# 0064 212c 232a 0ddd 53f9 5ba0 4003 0428
|
152
|
+
# 0000 01c0 0810 212c 044d 232a 232a 232a
|
153
|
+
# fc9d 000d 000b f011 1202 0400 0023 2a00
|
154
|
+
# 000d dd00 0053 f900 0302 9e18 5bd9 c5
|
155
|
+
# '.split.join
|
156
|
+
# m = Update.new([s].pack('H*'))
|
157
|
+
# p m
|
158
|
+
# end
|
159
|
+
|
132
160
|
|
133
161
|
end
|
@@ -0,0 +1,67 @@
|
|
1
|
+
#--
|
2
|
+
# Copyright 2008, 2009 Jean-Michel Esnault.
|
3
|
+
# All rights reserved.
|
4
|
+
# See LICENSE.txt for permissions.
|
5
|
+
#
|
6
|
+
#
|
7
|
+
# This file is part of BGP4R.
|
8
|
+
#
|
9
|
+
# BGP4R 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
|
+
# BGP4R 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 BGP4R. If not, see <http://www.gnu.org/licenses/>.
|
21
|
+
#++
|
22
|
+
|
23
|
+
require 'test/unit'
|
24
|
+
require 'bgp/nlris/nlris'
|
25
|
+
|
26
|
+
class TestExtNlri < Test::Unit::TestCase
|
27
|
+
include BGP
|
28
|
+
def test_1
|
29
|
+
nlri1 = Nlri.new
|
30
|
+
nlri1 << Nlri::Ip4.new('20.0.0.0/15')
|
31
|
+
nlri1 << '20.0.0.0/17'
|
32
|
+
nlri1 << '20.0.0.0/24'
|
33
|
+
s = '0f140010140011140000'
|
34
|
+
nlri2 = Nlri.new([s].pack('H*'))
|
35
|
+
assert_equal('0f140010140011140000', nlri2.to_shex)
|
36
|
+
assert_raise(ArgumentError) { nlri2.to_shex(true) }
|
37
|
+
assert_equal(3,nlri2.nlris.size)
|
38
|
+
end
|
39
|
+
end
|
40
|
+
|
41
|
+
class Nlri_Test < Test::Unit::TestCase
|
42
|
+
include BGP
|
43
|
+
def test_1
|
44
|
+
nlri1 = Nlri.new
|
45
|
+
nlri1 << Nlri::Ip4.new('20.0.0.0/15')
|
46
|
+
nlri1 << '20.0.0.0/17'
|
47
|
+
nlri1 << '20.0.0.0/24'
|
48
|
+
s = '0f140010140011140000'
|
49
|
+
nlri2 = Nlri.new([s].pack('H*'))
|
50
|
+
assert_equal('0f140010140011140000', nlri2.to_shex)
|
51
|
+
assert_raise(ArgumentError) { nlri2.to_shex(true) }
|
52
|
+
assert_equal(3,nlri2.nlris.size)
|
53
|
+
|
54
|
+
end
|
55
|
+
|
56
|
+
def test_2
|
57
|
+
nlri1 = Nlri.new
|
58
|
+
nlri1 << Nlri::Ip4.new('20.0.0.0/15')
|
59
|
+
nlri1 << '20.0.0.0/17'
|
60
|
+
nlri1 << '20.0.0.0/24'
|
61
|
+
s = '0f140010140011140000'
|
62
|
+
nlri2 = Nlri.new([s].pack('H*'))
|
63
|
+
assert_equal('0f140010140011140000', nlri2.to_shex)
|
64
|
+
assert_raise(ArgumentError) { nlri2.to_shex(true) }
|
65
|
+
assert_equal(3,nlri2.nlris.size)
|
66
|
+
end
|
67
|
+
end
|
@@ -85,6 +85,10 @@ class As_path_Test < Test::Unit::TestCase
|
|
85
85
|
assert_equal('400218020300010002000301030001000200030303000100020003', path.to_shex)
|
86
86
|
assert_equal('40021802030...', path.to_shex_len(10))
|
87
87
|
assert_equal("[wTcr] (2) As Path: [400218020300010002000...] '1 2 3 {1, 2, 3} (1 2 3)'", path.to_s)
|
88
|
+
path.find_set.prepend(100)
|
89
|
+
assert_equal '1 2 3 {100, 1, 2, 3} (1 2 3)', path.as_path
|
90
|
+
path.find_sequence.prepend(100)
|
91
|
+
assert_equal '100 1 2 3 {100, 1, 2, 3} (1 2 3)', path.as_path
|
88
92
|
end
|
89
93
|
def test_3
|
90
94
|
path = As_path.new(1,2,3)
|
@@ -105,7 +109,7 @@ class As_path_Test < Test::Unit::TestCase
|
|
105
109
|
assert_equal("{1, 2, 3}", As_path.new(As_path::Set.new(1,2,3)).as_path)
|
106
110
|
assert_equal("(1 2 3)", As_path.new(As_path::Segment.new(:confed_sequence,1,2,3)).as_path)
|
107
111
|
assert_equal("[1, 2, 3]", As_path.new(As_path::Segment.new(:confed_set,1,2,3)).as_path)
|
108
|
-
assert_equal("[wTcr] (2) As Path: [400208040300010002000...] '[1, 2, 3]'", As_path.new(As_path::Segment.new(:confed_set,1,2,3)).to_s)
|
112
|
+
assert_equal("[wTcr] (2) As Path: [400208040300010002000...] '[1, 2, 3]'", As_path.new(As_path::Segment.new(:confed_set,1,2,3)).to_s)
|
109
113
|
end
|
110
114
|
def test_5
|
111
115
|
two_byte_as = '4002080203000100020003'
|
@@ -31,6 +31,7 @@ class Community_Test < Test::Unit::TestCase
|
|
31
31
|
assert_equal(0xFFFFFF03,Communities::Community.new(:no_export_sub_confed).to_i)
|
32
32
|
assert_equal(0xFFFFFF04,Communities::Community.new(:no_peer).to_i)
|
33
33
|
assert_equal(0xdeadbeef,Communities::Community.new(0xdeadbeef).to_i)
|
34
|
+
assert_equal '5:1234', Communities::Community.new(Communities::Community.new('5:1234')).to_s
|
34
35
|
end
|
35
36
|
end
|
36
37
|
class Communities_Test < Test::Unit::TestCase
|
@@ -51,7 +52,6 @@ class Communities_Test < Test::Unit::TestCase
|
|
51
52
|
com1 = Communities.new("145:30", "145:40", "145:50", "145:60")
|
52
53
|
com2 = Communities.new("145:30,145:40,145:50,145:60")
|
53
54
|
assert_equal(com1.to_shex, com2.to_shex)
|
54
|
-
assert_equal(["0x91001e", "0x910028", "0x910032", "0x91003c"], com2.to_ary.collect { |c| "0x#{c.to_s(16)}" })
|
55
55
|
assert_equal('c008100091001e00910028009100320091003c',com1.to_shex)
|
56
56
|
com3 = Communities.new(0x91001E, 0x910028, 0x910032, 0x91003c)
|
57
57
|
assert_equal('c008100091001e00910028009100320091003c',com3.to_shex)
|
@@ -70,6 +70,22 @@ class Communities_Test < Test::Unit::TestCase
|
|
70
70
|
com3 = Communities.new(com1)
|
71
71
|
assert_equal(com1.encode, com3.encode)
|
72
72
|
end
|
73
|
+
def test_3
|
74
|
+
assert Communities.new("145:60 145:10 145:30 145:20").has_no? '1:1'
|
75
|
+
assert ! Communities.new("145:60 145:10 145:30 145:20").has?(0xff)
|
76
|
+
assert Communities.new("145:60 145:10 145:30 145:20").has?(Communities::Community.new('145:60'))
|
77
|
+
assert ! Communities.new("145:60 145:10 145:30 145:20").has?(Communities::Community.new(0xff))
|
78
|
+
assert ! Communities.new("145:60 145:10 145:30 145:20").has_no?('145:60')
|
79
|
+
assert Communities.new("145:60 145:10 145:30 145:20").has?('145:60')
|
80
|
+
end
|
81
|
+
def test_4
|
82
|
+
assert Communities.new("145:60 145:10").has_no_export?
|
83
|
+
assert Communities.new("145:60 145:10").has_no_advertise?
|
84
|
+
assert Communities.new("145:60 145:10").has_no_export_sub_confed?
|
85
|
+
assert ! Communities.new("145:60 145:10").add(:no_export_sub_confed).has_no_export_sub_confed?
|
86
|
+
assert ! Communities.new("145:60 145:10").add(:no_export).has_no_export?
|
87
|
+
assert ! Communities.new("145:60 145:10").add(:no_advertise).has_no_advertise?
|
88
|
+
end
|
73
89
|
end
|
74
90
|
|
75
91
|
#MiniTest::Unit.autorun
|
@@ -40,4 +40,12 @@ class Local_pref_Test < Test::Unit::TestCase
|
|
40
40
|
lp1 = Local_pref.new(lp)
|
41
41
|
assert_equal(lp.encode, lp1.encode)
|
42
42
|
end
|
43
|
+
def test_3
|
44
|
+
lp = Local_pref.new(200)
|
45
|
+
assert_equal 200, lp.to_i
|
46
|
+
lp + 13
|
47
|
+
assert_equal 213, lp.to_i
|
48
|
+
lp + -13
|
49
|
+
assert_equal 200, lp.to_i
|
50
|
+
end
|
43
51
|
end
|
@@ -43,4 +43,12 @@ class Multi_exit_disc_Test < Test::Unit::TestCase
|
|
43
43
|
mp1 = Multi_exit_disc.new(mp)
|
44
44
|
assert_equal(mp.encode, mp.encode)
|
45
45
|
end
|
46
|
+
def test_3
|
47
|
+
med = Multi_exit_disc.new(200)
|
48
|
+
assert_equal 200, med.to_i
|
49
|
+
med + 13
|
50
|
+
assert_equal 213, med.to_i
|
51
|
+
med + -13
|
52
|
+
assert_equal 200, med.to_i
|
53
|
+
end
|
46
54
|
end
|
@@ -101,9 +101,9 @@ class Path_attribute_Test < Test::Unit::TestCase # :nodoc:
|
|
101
101
|
)
|
102
102
|
|
103
103
|
path_attr.replace(
|
104
|
-
Origin.new(2),
|
105
104
|
As_path.new(100,200),
|
106
105
|
Local_pref.new(11),
|
106
|
+
Origin.new(2),
|
107
107
|
Multi_exit_disc.new(21)
|
108
108
|
)
|
109
109
|
|
@@ -135,4 +135,11 @@ class Path_attribute_Test < Test::Unit::TestCase # :nodoc:
|
|
135
135
|
assert_equal 0, sbin.size
|
136
136
|
end
|
137
137
|
|
138
|
+
def test_6
|
139
|
+
assert @pa.has_a_origin_attr?
|
140
|
+
assert @pa.has_a_next_hop_attr?
|
141
|
+
assert @pa.has_a_local_pref_attr?
|
142
|
+
assert ! @pa.has_a_aggregator_attr?
|
143
|
+
assert ! @pa.has_a_mp_unreach_attr?
|
144
|
+
end
|
138
145
|
end
|
metadata
CHANGED
@@ -5,8 +5,8 @@ version: !ruby/object:Gem::Version
|
|
5
5
|
segments:
|
6
6
|
- 0
|
7
7
|
- 0
|
8
|
-
-
|
9
|
-
version: 0.0.
|
8
|
+
- 10
|
9
|
+
version: 0.0.10
|
10
10
|
platform: ruby
|
11
11
|
authors:
|
12
12
|
- Jean-Michel Esnault
|
@@ -14,7 +14,7 @@ autorequire:
|
|
14
14
|
bindir: bin
|
15
15
|
cert_chain: []
|
16
16
|
|
17
|
-
date: 2010-10-
|
17
|
+
date: 2010-10-30 00:00:00 -07:00
|
18
18
|
default_executable:
|
19
19
|
dependencies: []
|
20
20
|
|
@@ -43,6 +43,7 @@ files:
|
|
43
43
|
- bgp/messages/open.rb
|
44
44
|
- bgp/messages/route_refresh.rb
|
45
45
|
- bgp/messages/update.rb
|
46
|
+
- bgp/misc/live_feed.rb
|
46
47
|
- bgp/neighbor.rb
|
47
48
|
- bgp/nlris/inet.rb
|
48
49
|
- bgp/nlris/label.rb
|
@@ -82,10 +83,12 @@ files:
|
|
82
83
|
- bgp/path_attributes/path_attribute.rb
|
83
84
|
- bgp4r.gemspec
|
84
85
|
- bgp4r.rb
|
86
|
+
- examples/a_live_feed
|
85
87
|
- examples/routegen
|
86
88
|
- examples/routegen.yml
|
87
89
|
- examples/simple.rb
|
88
90
|
- examples/unit-testing/malformed_update.rb
|
91
|
+
- examples/unit-testing/no_export.rb
|
89
92
|
- examples/unit-testing/prepend_aspath.rb
|
90
93
|
- examples/unit-testing/unknown_transitive_attr.rb
|
91
94
|
- test/common_test.rb
|
@@ -98,6 +101,7 @@ files:
|
|
98
101
|
- test/messages/route_refresh_test.rb
|
99
102
|
- test/messages/update_test.rb
|
100
103
|
- test/neighbor_test.rb
|
104
|
+
- test/nlris/ext_nlri_test.rb
|
101
105
|
- test/nlris/inet_test.rb
|
102
106
|
- test/nlris/labeled_test.rb
|
103
107
|
- test/nlris/nlri_test.rb
|
@@ -133,10 +137,7 @@ licenses: []
|
|
133
137
|
|
134
138
|
post_install_message:
|
135
139
|
rdoc_options:
|
136
|
-
- --
|
137
|
-
- --title
|
138
|
-
- A BGP-4 Ruby Library
|
139
|
-
- --line-numbers
|
140
|
+
- --charset=UTF-8
|
140
141
|
require_paths:
|
141
142
|
- .
|
142
143
|
required_ruby_version: !ruby/object:Gem::Requirement
|
@@ -173,6 +174,7 @@ test_files:
|
|
173
174
|
- test/messages/route_refresh_test.rb
|
174
175
|
- test/messages/update_test.rb
|
175
176
|
- test/neighbor_test.rb
|
177
|
+
- test/nlris/ext_nlri_test.rb
|
176
178
|
- test/nlris/inet_test.rb
|
177
179
|
- test/nlris/labeled_test.rb
|
178
180
|
- test/nlris/nlri_test.rb
|