bgp4r 0.0.9 → 0.0.10
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/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
|