bgp4r 0.0.9 → 0.0.10

Sign up to get free protection for your applications and to get access to all the features.
@@ -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