bgp4r 0.0.13 → 0.0.14

Sign up to get free protection for your applications and to get access to all the features.
Files changed (50) hide show
  1. data/bgp/messages/update.rb +8 -0
  2. data/bgp/nlris/label.rb +9 -1
  3. data/bgp/nlris/labeled.rb +11 -0
  4. data/bgp/nlris/nlri.rb +15 -4
  5. data/bgp/nlris/prefix.rb +11 -0
  6. data/bgp/nlris/rd.rb +13 -1
  7. data/bgp/nlris/vpn.rb +59 -10
  8. data/bgp/path_attributes/aggregator.rb +19 -0
  9. data/bgp/path_attributes/aigp.rb +63 -0
  10. data/bgp/path_attributes/as_path.rb +57 -0
  11. data/bgp/path_attributes/atomic_aggregate.rb +3 -0
  12. data/bgp/path_attributes/attribute.rb +10 -0
  13. data/bgp/path_attributes/attributes.rb +1 -0
  14. data/bgp/path_attributes/cluster_list.rb +24 -1
  15. data/bgp/path_attributes/communities.rb +32 -1
  16. data/bgp/path_attributes/extended_communities.rb +26 -0
  17. data/bgp/path_attributes/extended_community.rb +101 -16
  18. data/bgp/path_attributes/local_pref.rb +10 -0
  19. data/bgp/path_attributes/mp_reach.rb +21 -2
  20. data/bgp/path_attributes/mp_unreach.rb +5 -1
  21. data/bgp/path_attributes/multi_exit_disc.rb +10 -0
  22. data/bgp/path_attributes/next_hop.rb +20 -0
  23. data/bgp/path_attributes/origin.rb +14 -0
  24. data/bgp/path_attributes/originator_id.rb +17 -6
  25. data/bgp/path_attributes/path_attribute.rb +87 -2
  26. data/bgp/path_attributes/tlvs/tlv.rb +18 -0
  27. data/test/unit/messages/update_test.rb +79 -5
  28. data/test/unit/neighbor/neighbor_test.rb +0 -1
  29. data/test/unit/nlris/label_test.rb +6 -0
  30. data/test/unit/nlris/labeled_test.rb +12 -0
  31. data/test/unit/nlris/prefix_test.rb +5 -1
  32. data/test/unit/nlris/rd_test.rb +2 -0
  33. data/test/unit/nlris/vpn_test.rb +50 -0
  34. data/test/unit/path_attributes/aggregator_test.rb +6 -0
  35. data/test/unit/path_attributes/{aigp.rb → aigp_test.rb} +29 -0
  36. data/test/unit/path_attributes/as_path_test.rb +53 -0
  37. data/test/unit/path_attributes/atomic_aggregate_test.rb +3 -0
  38. data/test/unit/path_attributes/cluster_list_test.rb +15 -10
  39. data/test/unit/path_attributes/communities_test.rb +9 -4
  40. data/test/unit/path_attributes/extended_communities_test.rb +31 -3
  41. data/test/unit/path_attributes/extended_community_test.rb +52 -9
  42. data/test/unit/path_attributes/local_pref_test.rb +5 -0
  43. data/test/unit/path_attributes/mp_reach_test.rb +51 -4
  44. data/test/unit/path_attributes/mp_unreach_test.rb +9 -7
  45. data/test/unit/path_attributes/next_hop_test.rb +3 -0
  46. data/test/unit/path_attributes/origin_test.rb +1 -0
  47. data/test/unit/path_attributes/path_attribute_test.rb +53 -2
  48. data/test/unit/path_attributes/tlvs/tlv_test.rb +33 -0
  49. data/test/unit/path_attributes/tunnel_encapsulation_test (Jean-Michel's Laptop's conflicted copy 2011-11-02).rb +388 -0
  50. metadata +14 -4
@@ -34,15 +34,21 @@ module BGP
34
34
  OSPF_DOMAIN_ID = 5
35
35
  OSPF_ROUTER_ID = 7
36
36
  BGP_DATA_COLLECT = 8
37
+ COLOR = 11
38
+ ENCAPSULATION = 12
37
39
 
38
- IANA_AUTHORITY_BIT = 0x8
39
- NON_TRANSITIVE = 0x4
40
+ IANA_AUTHORITY_BIT = 0x80
41
+ TRANSITIVE = 0x0
42
+ NON_TRANSITIVE = 0x40
40
43
 
41
44
  TWO_OCTET_AS = 0
42
45
  IPV4_ADDR = 1
43
46
  OPAQUE = 3
44
47
  FLOAT = -1
45
48
 
49
+ DEFAULT_OPAQUE_ENCODING = 'H12'
50
+
51
+
46
52
  def encode
47
53
  [@type, @subtype, _encoded_value_].pack('CCa6')
48
54
  end
@@ -54,7 +60,14 @@ module BGP
54
60
  when IPV4_ADDR
55
61
  @global, @local = s.unpack('Nn')
56
62
  when OPAQUE
57
- @global = s.unpack('H12')
63
+ case self
64
+ when Color
65
+ _,@global = s.unpack('nN')
66
+ when Encapsulation
67
+ _,@global = s.unpack('Nn')
68
+ else
69
+ @global = s.unpack('H12')
70
+ end
58
71
  when FLOAT
59
72
  _, @global = s.unpack('ng')
60
73
  end
@@ -112,23 +125,36 @@ module BGP
112
125
  def name
113
126
  self.class.to_s.split('::').last.gsub('_',' ')
114
127
  end
115
-
116
128
  def to_s
129
+ "#{name}: #{value}"
130
+ end
131
+
132
+ private
133
+
134
+ def value
117
135
  case community_structure
118
136
  when TWO_OCTET_AS
119
- "#{name}: #{@global}:#{@local}"
137
+ "#{@global}:#{@local}"
120
138
  when IPV4_ADDR
121
- "#{name}: #{IPAddr.create(@global)}:#{@local}"
139
+ "#{IPAddr.create(@global)}:#{@local}"
122
140
  when OPAQUE
123
- "#{name}: #{@global}"
141
+ "#{@global}"
124
142
  when FLOAT
125
- "#{name}: #{[@global].pack('g').unpack('g')[0]}"
143
+ "#{[@global].pack('g').unpack('g')[0]}"
126
144
  else
127
145
  raise RuntimeError, "bogus type: #{@type}"
128
146
  end
147
+
129
148
  end
130
149
 
131
- private
150
+ def value2
151
+ case community_structure
152
+ when FLOAT ; @global
153
+ when IPV4_ADDR ; ["#{IPAddr.create(@global)}",@local]
154
+ else
155
+ [@global, @local]
156
+ end
157
+ end
132
158
 
133
159
  def community_structure
134
160
  cs = @type & 3
@@ -143,7 +169,14 @@ module BGP
143
169
  when IPV4_ADDR
144
170
  [@global, @local].pack('Nn')
145
171
  when OPAQUE
146
- [@global].pack('H12')
172
+ case self
173
+ when BGP::Color
174
+ [0,@global].pack('nN')
175
+ when BGP::Encapsulation
176
+ [0,@global].pack('Nn')
177
+ else
178
+ [@global].pack('H12')
179
+ end
147
180
  when FLOAT
148
181
  [0,@global].pack('ng')
149
182
  else
@@ -172,8 +205,10 @@ module BGP
172
205
  when OSPF_ROUTER_ID ; Ospf_router_id.new(s)
173
206
  when BGP_DATA_COLLECT ; Bgp_data_collect.new(s)
174
207
  when LINK_BANDWIDTH ; Link_bandwidth.new(s)
208
+ when COLOR ; Color.new(s)
209
+ when ENCAPSULATION ; Encapsulation.new(s)
175
210
  else
176
- puts "too bad type #{type}, subtype #{subtype} : #{s.unpack('H*')}"
211
+ puts "too bad type #{type.to_s(16)}, subtype #{subtype.to_s(16)} : #{s.unpack('H*')}"
177
212
  Extended_community.new(s)
178
213
  end
179
214
  end
@@ -184,9 +219,10 @@ module BGP
184
219
  parse(args[0])
185
220
  elsif args.size==3
186
221
  @type, @subtype, value = args
187
- raise ArgumentError, "invalid argument #{args.inspect}" unless instance_of?(Opaque)
222
+ raise ArgumentError, "invalid argument #{args.inspect}" unless is_a?(Opaque)
188
223
  @type |= OPAQUE
189
224
  @global, @local=value, nil
225
+
190
226
  elsif args.size==4
191
227
  raise ArgumentError, "This is a base class and should not be instanciated" if instance_of?(Extended_community)
192
228
  @type, @subtype, @global, @local = args
@@ -202,8 +238,6 @@ module BGP
202
238
  raise ArgumentError, "invalid arg #{args.inspect}"
203
239
  end
204
240
  end
205
-
206
-
207
241
  end
208
242
 
209
243
  class Route_target < Extended_community
@@ -235,6 +269,9 @@ module BGP
235
269
  super(1,OSPF_DOMAIN_ID,*args)
236
270
  end
237
271
  end
272
+ def value2
273
+ "#{IPAddr.create(@global)}"
274
+ end
238
275
  end
239
276
 
240
277
  class Ospf_router_id < Extended_community
@@ -246,6 +283,9 @@ module BGP
246
283
  super(1,OSPF_ROUTER_ID,*args)
247
284
  end
248
285
  end
286
+ def value2
287
+ "#{IPAddr.create(@global)}"
288
+ end
249
289
  end
250
290
 
251
291
  class Bgp_data_collect < Extended_community
@@ -263,8 +303,7 @@ module BGP
263
303
  if args[0].is_a?(String) and args[0].is_packed?
264
304
  super(*args)
265
305
  else
266
- raise ArgumentError, "not an opaque extended community" if [2,3,5,7,8].include?(args[0])
267
- super(0,*args)
306
+ super(*args)
268
307
  end
269
308
  end
270
309
  end
@@ -278,6 +317,52 @@ module BGP
278
317
  super(NON_TRANSITIVE | TWO_OCTET_AS, LINK_BANDWIDTH, *args)
279
318
  end
280
319
  end
320
+ def value2
321
+ @global
322
+ end
281
323
  end
282
324
 
325
+ class Color < Opaque
326
+ def initialize(*args)
327
+ args = 0 if args.empty?
328
+ if args[0].is_a?(String) and args[0].is_packed?
329
+ super(*args)
330
+ else
331
+ super(TRANSITIVE, COLOR, *args)
332
+ end
333
+ end
334
+ def value2
335
+ @global
336
+ end
337
+ end
338
+
339
+ class Encapsulation < Opaque
340
+ def initialize(*args)
341
+ args = 0 if args.empty?
342
+ if args[0].is_a?(String) and args[0].is_packed?
343
+ super(*args)
344
+ else
345
+ case args[0]
346
+ when :l2tpv3 ; tunnel_type = 1
347
+ when :gre ; tunnel_type = 2
348
+ when :ipip ; tunnel_type = 7
349
+ else
350
+ tunnel_type = *args
351
+ end
352
+ super(TRANSITIVE, ENCAPSULATION, tunnel_type)
353
+ end
354
+ end
355
+ def value2
356
+ case @global
357
+ when 1 ; :l2tpv3
358
+ when 2 ; :gre
359
+ when 7 ; :ipip
360
+ else
361
+ @global
362
+ end
363
+ end
364
+ end
365
+
283
366
  end
367
+
368
+ load "../../test/unit/path_attributes/#{ File.basename($0.gsub(/.rb/,'_test.rb'))}" if __FILE__ == $0
@@ -27,6 +27,12 @@ module BGP
27
27
 
28
28
  class Local_pref < Attr
29
29
 
30
+ class << self
31
+ def new_hash(arg={})
32
+ new arg
33
+ end
34
+ end
35
+
30
36
  def initialize(arg=100)
31
37
  @flags, @type = WELL_KNOWN_MANDATORY, LOCAL_PREF
32
38
  if arg.is_a?(String) and arg.is_packed?
@@ -54,6 +60,10 @@ module BGP
54
60
  def to_i
55
61
  @local_pref
56
62
  end
63
+
64
+ def to_hash
65
+ {:local_pref=>to_i}
66
+ end
57
67
 
58
68
  def encode
59
69
  super([to_i].pack('N'))
@@ -70,6 +70,25 @@ module BGP
70
70
  self
71
71
  end
72
72
 
73
+ def to_hash
74
+ h_afi_safi = {:safi=> @safi, :afi=>@afi}
75
+ h_nlris = @nlris.size>1 ? @nlris.collect { |n| nlri_to_hash(n) } : nlri_to_hash(@nlris[0])
76
+ h = if @nexthops.empty?
77
+ h_afi_safi.merge(:nlris=>h_nlris)
78
+ else
79
+ h_afi_safi.merge(:nlris=>h_nlris).merge({:nexthop=>@nexthops.collect { |n| n.nexthop.to_s }} )
80
+ end
81
+ end
82
+
83
+ def nlri_to_hash(nlri)
84
+ if nlri.is_a?(Prefix) and ! nlri.extended?
85
+ nlri.to_s
86
+ else
87
+ nlri.to_hash
88
+ end
89
+ end
90
+ private :nlri_to_hash
91
+
73
92
  module ClassMethods
74
93
  def afi_from_nlris(arg)
75
94
  case arg
@@ -157,8 +176,8 @@ module BGP
157
176
  def to_s(method=:default)
158
177
  super(mp_reach, method)
159
178
  end
160
-
161
179
  def to_hash
180
+ {:mp_reach=>super}
162
181
  end
163
182
 
164
183
  def parse(s,arg=false)
@@ -206,7 +225,7 @@ module BGP
206
225
  end
207
226
  raise RuntimeError, "leftover afer parsing: #{value.unpack('H*')}" if value.size>0
208
227
  end
209
-
228
+
210
229
  def parse_iso_mapped_next_hops(s)
211
230
  raise unless @afi == 3
212
231
  while s.size>0
@@ -59,7 +59,7 @@ module BGP
59
59
  def to_s(method=:default)
60
60
  super(mp_unreach, method)
61
61
  end
62
-
62
+
63
63
  def parse(s,arg=false)
64
64
 
65
65
  @flags, @type, len, value = super(s)
@@ -86,6 +86,10 @@ module BGP
86
86
  p nlris[0].prefix
87
87
  raise
88
88
  end
89
+
90
+ def to_hash
91
+ {:mp_unreach=>super}
92
+ end
89
93
 
90
94
  end
91
95
 
@@ -27,6 +27,12 @@ module BGP
27
27
 
28
28
  class Multi_exit_disc < Attr
29
29
 
30
+ class << self
31
+ def new_hash(arg={})
32
+ new arg
33
+ end
34
+ end
35
+
30
36
  def initialize(arg=0)
31
37
  @flags, @type=OPTIONAL, MULTI_EXIT_DISC
32
38
  if arg.is_a?(String) and arg.is_packed?
@@ -68,6 +74,10 @@ module BGP
68
74
  super(multi_exit_disc, method)
69
75
  end
70
76
 
77
+ def to_hash
78
+ {:multi_exit_disc=>to_i}
79
+ end
80
+
71
81
  private
72
82
 
73
83
  def parse(s)
@@ -27,12 +27,28 @@ module BGP
27
27
 
28
28
  class Next_hop < Attr
29
29
 
30
+ # class << self
31
+ # def new_hash(arg={})
32
+ # if arg.has_key?(:next_hop)
33
+ # new( arg[:next_hop])
34
+ # elsif arg.has_key?(:nexthop)
35
+ # new( arg[:nexthop])
36
+ # end
37
+ # end
38
+ # end
39
+
30
40
  def initialize(*args)
31
41
  @flags, @type = WELL_KNOWN_MANDATORY, NEXT_HOP
32
42
  if args[0].is_a?(String) and args[0].is_packed?
33
43
  parse(args[0])
34
44
  elsif args[0].is_a?(self.class)
35
45
  parse(args[0].encode, *args[1..-1])
46
+ elsif args[0].is_a?(Hash)
47
+ if args[0].has_key?(:next_hop)
48
+ @next_hop = IPAddr.create(args[0][:next_hop])
49
+ elsif arg.has_key?(:nexthop)
50
+ @next_hop = IPAddr.create(args[0][:nexthop])
51
+ end
36
52
  else
37
53
  @next_hop = IPAddr.create(*args)
38
54
  end
@@ -44,6 +60,10 @@ module BGP
44
60
  def to_s(method=:default)
45
61
  super(next_hop, method)
46
62
  end
63
+
64
+ def to_hash
65
+ {:next_hop=> next_hop }
66
+ end
47
67
 
48
68
  def to_i
49
69
  @next_hop.to_i
@@ -59,6 +59,20 @@ module BGP
59
59
  def to_i
60
60
  @origin
61
61
  end
62
+
63
+ def to_sym
64
+ case @origin
65
+ when 1 ; :egp
66
+ when 2 ; :incomplete
67
+ when 0 ; :igp
68
+ else
69
+ :undefined
70
+ end
71
+ end
72
+
73
+ def to_hash
74
+ {:origin=> to_sym}
75
+ end
62
76
 
63
77
  def origin
64
78
  case to_i
@@ -30,6 +30,13 @@ module BGP
30
30
 
31
31
  class Originator_id < Attr
32
32
 
33
+ class << self
34
+ def new_hash(arg={})
35
+ new arg[:origin_id]
36
+ end
37
+ end
38
+
39
+
33
40
  def initialize(*args)
34
41
  @flags, @type = OPTIONAL, ORIGINATOR_ID
35
42
  if args[0].is_a?(String) and args[0].is_packed?
@@ -42,27 +49,31 @@ module BGP
42
49
  end
43
50
 
44
51
  def to_i
45
- @next_hop.to_i
52
+ @origin_id.to_i
46
53
  end
47
54
  def parse(s)
48
55
  @flags, @type, len, value = super(s)
49
- @next_hop = IPAddr.create(value)
56
+ @origin_id = IPAddr.create(value)
50
57
  end
51
58
 
52
59
  def encode
53
- super(@next_hop.encode)
60
+ super(@origin_id.encode)
54
61
  end
55
62
 
56
63
  def to_s(method=:default)
57
- super(@next_hop.to_s, method)
64
+ super(@origin_id.to_s, method)
58
65
  end
59
66
 
60
67
  def originator_id
61
- @next_hop.to_s
68
+ @origin_id.to_s
69
+ end
70
+
71
+ def to_hash
72
+ {:origin_id=> originator_id}
62
73
  end
63
74
 
64
75
  def originator_id=(val)
65
- @next_hop=IPAddr.create(val)
76
+ @origin_id=IPAddr.create(val)
66
77
  end
67
78
 
68
79
 
@@ -36,9 +36,37 @@ module BGP
36
36
  while s.size>0
37
37
  @attributes << Attr.factory(*args)
38
38
  end
39
+ elsif args.size ==1 and args[0].is_a?(Hash)
40
+ @attributes = []
41
+ @attributes = args[0].keys.collect { |attr|
42
+ case attr
43
+ when :next_hop, :nexthop ; Next_hop.new(args[0][attr])
44
+ when :local_pref ; Local_pref.new(args[0][attr])
45
+ when :med, :multi_exit_disc ; Multi_exit_disc.new(args[0][attr])
46
+ when :mp_reach ; Mp_reach.new(args[0][attr])
47
+ when :mp_unreach ; Mp_unreach.new(args[0][attr])
48
+ when :as_path ; As_path.new_hash(args[0][attr])
49
+ when :as4_path ; As4_path.new_hash(args[0][attr])
50
+ when :origin ; Origin.new(args[0][attr])
51
+ when :cluster_list ; Cluster_list.new(*args[0][attr])
52
+ when :aggregator ; Aggregator.new(args[0][attr])
53
+ when :as4_aggregator ; As4_aggregator.new(args[0][attr])
54
+ when :originator_id ; Originator_id.new(args[0][attr])
55
+ when :communities, :community; Communities.new(args[0][attr])
56
+ when :extended_communities, :extended_community
57
+ Extended_communities.new_hash(args[0][attr])
58
+ when :atomic_aggregate ; Atomic_aggregate.new
59
+ # FIXME: add other attr here ...
60
+ else
61
+ puts "#{attr} to be implemented!"
62
+ end
63
+ }.compact
39
64
  else
40
65
  add(*args)
41
66
  end
67
+
68
+ yield(self) if block_given?
69
+
42
70
  end
43
71
 
44
72
  def add(*args)
@@ -53,7 +81,12 @@ module BGP
53
81
  if as4byte and a.is_a?(As_path)
54
82
  a.to_s(method, as4byte)
55
83
  else
84
+ begin
56
85
  a.to_s(method)
86
+ rescue => e
87
+ p e
88
+ p a.class
89
+ end
57
90
  end
58
91
  }).join("\n ")
59
92
  end
@@ -187,7 +220,16 @@ module BGP
187
220
  end
188
221
  eval "alias :has_an_#{attr}? :has_a_#{attr}_attr?" if (attr =~ /^[aeiou]/)
189
222
  end
190
-
223
+
224
+ def to_hash
225
+ h = {}
226
+ @attributes.each { |att|
227
+ _h = att.to_hash
228
+ h = h.merge(_h) if _h
229
+ }
230
+ h
231
+ end
232
+
191
233
  private
192
234
 
193
235
  def att_sym_to_klass(sym)
@@ -276,8 +318,51 @@ module BGP
276
318
  Unknown.new(s)
277
319
  end
278
320
  end
321
+
322
+ # def self.new_hash(_arg={:arg=>nil})
323
+ # #FIXME:
324
+ #
325
+ # arg = _arg.delete(:arg)
326
+ #
327
+ # if arg.is_a?(Neighbor::Capabilities)
328
+ # as4byte_flag = arg.as4byte?
329
+ # path_id_flag = arg
330
+ # elsif arg.is_a?(Hash)
331
+ # as4byte_flag=arg[:as4byte]
332
+ # path_id_flag=arg[:path_id]
333
+ # elsif arg.is_a?(TrueClass)
334
+ # as4byte_flag=true
335
+ # path_id_flag=nil
336
+ # elsif arg.respond_to? :as4byte?
337
+ # as4byte_flag = arg.as4byte?
338
+ # path_id_flag = arg
339
+ # else
340
+ # as4byte_flag=nil
341
+ # path_id_flag=nil
342
+ # end
343
+ #
344
+ # _arg.keys.each { |attr|
345
+ # case attr
346
+ # when :local_pref ; Local_pref.new(_arg[attr])
347
+ # when :next_hop ; Next_hop.new(_arg[attr])
348
+ # else
349
+ # end
350
+ # }
351
+ # end
352
+
353
+
279
354
 
280
355
  end
281
- end
282
356
 
357
+ # require 'bgp/path_attributes/local_pref'
358
+ # require 'bgp/path_attributes/next_hop'
359
+ # require 'bgp/path_attributes/multi_exit_disc'
360
+ #
361
+ # p = Path_attribute.new :local_pref=>100, :next_hop => '10.0.0.1', :med=>300
362
+ # # p p
363
+ # puts p
364
+
365
+
366
+
367
+ end
283
368
  load "../../test/unit/path_attributes/#{ File.basename($0.gsub(/.rb/,'_test.rb'))}" if __FILE__ == $0
@@ -0,0 +1,18 @@
1
+ module BGP
2
+ module TLV
3
+ attr_accessor :tlv_type
4
+ def encode(value)
5
+ p 'IN ENCODE TLV'
6
+ [@tlv_type, value.size, value].pack('nna*')
7
+ end
8
+ end
9
+ module STLV
10
+ attr_accessor :stlv_type
11
+ def encode(value)
12
+ [@stlv_type, value.size, value].pack('CCa*')
13
+ end
14
+ end
15
+ end
16
+
17
+ load "../../../test/unit/path_attributes/tlvs/#{ File.basename($0.gsub(/.rb/,'_test.rb'))}" if __FILE__ == $0
18
+