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.
@@ -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
@@ -7,11 +7,15 @@ module BGP
7
7
  rescue
8
8
  end
9
9
 
10
- %w{ update keepalive open notification capablity}.each do |m|
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'
@@ -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, fmt=:tcpdump)
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(@as4byte) : m }\n"
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(@as4byte)
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)
@@ -170,6 +170,10 @@ module BGP
170
170
 
171
171
  attr_reader :type
172
172
 
173
+ def <=>(o)
174
+ 0
175
+ end
176
+
173
177
  def method_missing(name, *args, &block)
174
178
  if name == :encode4
175
179
  send :encode, *args, &block
@@ -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 ; @value=0xFFFFFF01
37
- when :no_advertise ; @value=0xFFFFFF02
38
- when :no_export_sub_confed ; @value=0xFFFFFF03
39
- when :no_peer ; @value=0xFFFFFF04
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 #{val}"
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?(Fixnum) or val.is_a?(Bignum)
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(to_ary.sort)
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
- end
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
@@ -46,6 +46,10 @@ module BGP
46
46
  raise ArgumentError, "invalid argument" unless val.is_a?(Integer)
47
47
  @local_pref=val
48
48
  end
49
+
50
+ def +(val)
51
+ @local_pref +=val
52
+ end
49
53
 
50
54
  def to_i
51
55
  @local_pref
@@ -52,6 +52,10 @@ module BGP
52
52
  @med
53
53
  end
54
54
 
55
+ def +(val)
56
+ @med +=val
57
+ end
58
+
55
59
  def encode
56
60
  super([to_i].pack('N'))
57
61
  end
@@ -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
- to_ary.insert(0,arg)
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
- to_ary << (arg)
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
- attr = to_ary.find { |x| x.class == arg.class }
148
- if attr.nil?
149
- append(arg)
151
+ ind = attributes.find_index { |x| x.class == arg.class }
152
+ if ind
153
+ attributes[ind] = arg
150
154
  else
151
- index = to_ary.index(attr)
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
- to_ary.delete_if { |x| x.class == klass }
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
- Unknown = Class.new(Attr) do
174
- attr_reader :type, :flags, :value
175
- def initialize(*args)
176
- if args.size>1
177
- @flags, @type, len, @value=args
178
- else
179
- parse(*args)
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.9"
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}
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 = ["--quiet", "--title", "A BGP-4 Ruby Library", "--line-numbers"]
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
@@ -18,8 +18,6 @@ Log.create
18
18
  Log.level=Logger::DEBUG
19
19
  config = YAML::load_file(config_file)
20
20
 
21
- p config
22
-
23
21
  config.keys.each do |k|
24
22
  case k
25
23
  when 'neighbor'
@@ -73,9 +73,5 @@ class TestBgp < Test::Unit::TestCase
73
73
  Nlri.new('77.0.0.0/17', '78.0.0.0/18', '79.0.0.0/19')
74
74
  )
75
75
  end
76
-
77
- def send_update_to(n)
78
- n.send_message update1
79
- end
80
-
76
+
81
77
  end
@@ -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
9
- version: 0.0.9
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-12 00:00:00 -07:00
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
- - --quiet
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