bgp4r 0.0.13 → 0.0.14

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.
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
+