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
@@ -183,6 +183,14 @@ class BGP::Update < BGP::Message
183
183
  s.join("\n") + "\n" + msg.hexlify.join("\n") + "\n"
184
184
  end
185
185
 
186
+ def to_hash
187
+ h = {}
188
+ h[:withdrawns] = @withdrawn.to_ary if @withdrawn
189
+ h[:path_attributes] = @path_attribute.to_hash if @path_attribute
190
+ h[:nlris] = @nlri.to_ary if @nlri
191
+ h
192
+ end
193
+
186
194
  def self.withdrawn(u)
187
195
  if u.nlri and u.nlri.size>0
188
196
  Update.new(Withdrawn.new(*(u.nlri.nlris.collect { |n| n.to_s})))
data/bgp/nlris/label.rb CHANGED
@@ -58,8 +58,10 @@ module BGP
58
58
  @label_stack=[]
59
59
  if args.size==1 and args[0].is_a?(String) and args[0].is_packed?
60
60
  parse(args[0])
61
+ elsif args.size==1 and args[0].is_a?(Hash)
62
+ @label_stack = args[0][:labels].collect { |l| Label.new(l) }
61
63
  else
62
- args.each { |arg| @label_stack << (arg.is_a?(Label) ? arg : Label.new(arg)) }
64
+ @label_stack = args.collect { |arg| (arg.is_a?(Label) ? arg : Label.new(arg)) }
63
65
  end
64
66
  end
65
67
  def size
@@ -84,6 +86,12 @@ module BGP
84
86
  "Label Stack=#{@label_stack.collect{ |l| l.label }.join(',')} (bottom)"
85
87
  end
86
88
  end
89
+ def to_ary
90
+ @label_stack.collect { |e| e.label }
91
+ end
92
+ def to_hash
93
+ @label_stack.size==1 ? {:label=>@label_stack[0].label} : {:labels=> to_ary}
94
+ end
87
95
  def bit_length
88
96
  @label_stack.compact.size*24
89
97
  end
data/bgp/nlris/labeled.rb CHANGED
@@ -17,6 +17,11 @@ module BGP
17
17
  def initialize(*args)
18
18
  if args.size>0 and args[0].is_a?(String) and args[0].is_packed?
19
19
  parse(*args)
20
+ elsif args.size==1 and args[0].is_a?(Hash)
21
+ # TODO: a new_prefix :prefix=>, :labels=>
22
+ # :other=> ...
23
+ @prefix = Prefix.new(args[0][:prefix]) # assuming it's a Prefix, which it may not be
24
+ @labels = Label_stack.new(*args[0][:labels])
20
25
  else
21
26
  @prefix, *labels = args
22
27
  @labels = Label_stack.new(*labels)
@@ -25,6 +30,9 @@ module BGP
25
30
  #FIXME... a mixin path_id ????
26
31
  def path_id
27
32
  @prefix.path_id
33
+ rescue
34
+ # return nil
35
+ # RD: 0/0
28
36
  end
29
37
  def path_id=(val)
30
38
  @prefix.path_id=val
@@ -40,6 +48,9 @@ module BGP
40
48
  s
41
49
  end
42
50
  end
51
+ def to_hash
52
+ @labels.to_hash.merge(@prefix.to_hash)
53
+ end
43
54
  def to_s
44
55
  "#{@labels} #{@prefix}"
45
56
  end
data/bgp/nlris/nlri.rb CHANGED
@@ -94,18 +94,29 @@ module BGP
94
94
  def to_s(indent=0)
95
95
  @nlris.join("\n#{([' ']*indent).join}")
96
96
  end
97
-
97
+
98
98
  def size
99
99
  @nlris.size
100
100
  end
101
101
 
102
+ def to_ary
103
+ @nlris.collect { |n| n.to_s }
104
+ end
105
+
102
106
  end
103
107
 
104
108
  unless const_defined?(:Nlri)
105
- Nlri = Class.new(Base_nlri)
106
- Withdrawn = Class.new(Base_nlri)
109
+ Nlri = Class.new(Base_nlri) do
110
+ def to_hash
111
+ {:nlris=>to_ary}
112
+ end
113
+ end
114
+ Withdrawn = Class.new(Base_nlri) do
115
+ def to_hash
116
+ {:withdrawns=>to_ary}
117
+ end
118
+ end
107
119
  end
108
-
109
120
  class Nlri
110
121
  def self.factory(s, afi, safi, path_id=nil)
111
122
  if afi== 1 and safi==1
data/bgp/nlris/prefix.rb CHANGED
@@ -54,6 +54,9 @@ class Prefix
54
54
  @path_id=nil
55
55
  if args.size>1 and args[0].is_a?(Integer)
56
56
  @path_id, pfx, afi = args
57
+ elsif args.size==1 and args[0].is_a?(Hash)
58
+ @path_id = args[0][:path_id]
59
+ pfx = args[0][:prefix]
57
60
  else
58
61
  pfx, afi = args
59
62
  end
@@ -108,6 +111,14 @@ class Prefix
108
111
  end
109
112
  end
110
113
 
114
+ def to_hash
115
+ if extended?
116
+ {:prefix=> pfx_to_s}.merge({:path_id=>@path_id})
117
+ else
118
+ {:prefix=> pfx_to_s}
119
+ end
120
+ end
121
+
111
122
  def nexthop
112
123
  to_s.split('/')[0]
113
124
  end
data/bgp/nlris/rd.rb CHANGED
@@ -54,9 +54,21 @@ module BGP
54
54
  else
55
55
  @admin, @assign, @enc_type, = admin, assign, 0
56
56
  end
57
+ elsif args.size==1 and args[0].is_a?(Hash)
58
+ # assuming Rd.new :rd=> [100,100]
59
+ parse(Rd.new(*args[0][:rd]).encode)
57
60
  end
58
61
  end
59
-
62
+
63
+ def to_hash
64
+ #FIXME
65
+ if @admin.is_a?(IPAddr)
66
+ {:rd=> [@admin.to_s, @assign]}
67
+ else
68
+ {:rd=> [@admin, @assign]}
69
+ end
70
+ end
71
+
60
72
  def encode
61
73
  case @enc_type
62
74
  when 0
data/bgp/nlris/vpn.rb CHANGED
@@ -11,12 +11,20 @@ module BGP
11
11
  class Vpn
12
12
  attr_reader :prefix, :rd
13
13
  def initialize(*args)
14
+ @prefix=nil
14
15
  if args.size>0 and args[0].is_a?(String) and args[0].is_packed?
15
16
  parse(*args)
16
17
  else
17
- prefix, *rd = args
18
- self.prefix=(prefix)
19
- self.rd=rd
18
+ case args[0]
19
+ when String, Prefix
20
+ prefix, *rd = args
21
+ self.prefix=(prefix)
22
+ self.rd=rd
23
+ when Rd
24
+ *rd = args
25
+ @prefix=nil
26
+ self.rd=rd
27
+ end
20
28
  end
21
29
  end
22
30
  def prefix=(arg)
@@ -42,23 +50,38 @@ module BGP
42
50
  end
43
51
  def encode(len_included=true)
44
52
  if len_included
45
- [bit_length, @rd.encode, @prefix.encode_with_len_without_path_id].pack('Ca*a*')
53
+ [bit_length, @rd.encode, encode_prefix(false)].pack('Ca*a*')
46
54
  else
47
- @rd.encode + @prefix.encode_without_len_without_path_id
55
+ @rd.encode + encode_prefix(false)
48
56
  end
49
57
  end
58
+
59
+ def encode_prefix(len_included)
60
+ if @prefix
61
+ if len_included
62
+ @prefix.encode_with_len_without_path_id
63
+ else
64
+ @prefix.encode_without_len_without_path_id
65
+ end
66
+ else
67
+ ''
68
+ end
69
+ end
70
+
50
71
  def encode_without_len_without_path_id
51
72
  encode(false)
52
73
  end
74
+
53
75
  def path_id
54
76
  @prefix.path_id
55
- rescue
56
77
  end
57
78
  def path_id=(val)
58
79
  @prefix.path_id=val
59
80
  end
60
81
  def bit_length
61
- @rd.bit_length + @prefix.mlen
82
+ len = @rd.bit_length
83
+ len += @prefix.mlen if @prefix
84
+ len
62
85
  end
63
86
  def ipv4?
64
87
  @prefix.ipv4?
@@ -73,14 +96,40 @@ module BGP
73
96
  nbits = s.slice!(0,1).unpack('C')[0]
74
97
  rd,vpn = s.slice!(0,(7+nbits)/8).unpack("a8a*")
75
98
  @rd = Rd.new(rd.is_packed)
76
- @prefix= Prefix.new_ntop([nbits-64,vpn].pack('Ca*'), afi)
99
+ @prefix= Prefix.new_ntop([nbits-64,vpn].pack('Ca*'), afi) if vpn.size>0
77
100
  end
78
101
  def nexthop
79
102
  @prefix.nexthop
80
103
  end
81
- def to_s
104
+ def to_s(afi=1)
82
105
  #Label Stack=5806 (bottom) RD=3215:317720610, IPv4=10.45.142.64/32
83
- "#{@rd.to_s(false)}, #{@prefix.to_s_with_afi}"
106
+ "#{@rd.to_s(false)}, #{prefix_to_s(afi)}"
107
+ end
108
+
109
+ def to_hash
110
+ if @prefix
111
+ @rd.to_hash.merge(@prefix.to_hash)
112
+ else
113
+ @rd.to_hash
114
+ end
84
115
  end
116
+
117
+ private
118
+
119
+ def prefix_to_s(afi)
120
+ if @prefix
121
+ @prefix.to_s_with_afi
122
+ else
123
+ case afi
124
+ when 1 ; 'IPv4=0.0.0.0/0'
125
+ when 2 ; 'IPv6=0::0/0'
126
+ else
127
+ ''
128
+ end
129
+ end
130
+ end
131
+
85
132
  end
86
133
  end
134
+
135
+ load "../../test/unit/nlris/#{ File.basename($0.gsub(/.rb/,'_test.rb'))}" if __FILE__ == $0
@@ -36,6 +36,9 @@ module BGP
36
36
  @as = args[1]
37
37
  elsif args[0].is_a?(self.class)
38
38
  parse(args[0].encode, *args[1..-1])
39
+ elsif args[0].is_a?(Hash)
40
+ @ip_address = IPAddr.create(args[0][:address])
41
+ @as = args[0][:asn]
39
42
  else
40
43
  raise ArgumentError, "invalid argument, #{args.inspect}"
41
44
  end
@@ -48,6 +51,10 @@ module BGP
48
51
  def address
49
52
  @ip_address.to_s
50
53
  end
54
+
55
+ def asn
56
+ @as
57
+ end
51
58
 
52
59
  def as(sep='')
53
60
  case sep
@@ -78,6 +85,10 @@ module BGP
78
85
  super([@as].pack(f) + @ip_address.hton)
79
86
  end
80
87
 
88
+ def to_hash
89
+ {:asn=> asn, :address=> address}
90
+ end
91
+
81
92
  end
82
93
 
83
94
  class As4_aggregator < Aggregator
@@ -98,6 +109,14 @@ module BGP
98
109
  end
99
110
 
100
111
  end
112
+
113
+ class Aggregator
114
+ class << self
115
+ def new_hash(arg={})
116
+ new arg[:address], arg[:as]
117
+ end
118
+ end
119
+ end
101
120
 
102
121
  end
103
122
 
@@ -0,0 +1,63 @@
1
+ require 'bgp/path_attributes/attribute'
2
+
3
+ module BGP
4
+
5
+ class Aigp < Attr
6
+
7
+ def initialize(*args)
8
+ @flags, @type = OPTIONAL_NON_TRANSITIVE, ACCUMULATED_IGP_METRIC
9
+ if args[0].is_a?(String) and args[0].is_packed?
10
+ parse(args[0])
11
+ elsif args[0].is_a?(self.class)
12
+ parse(args[0].encode, *args[1..-1])
13
+ elsif args.size==1 and args[0].is_a?(Integer)
14
+ @aigp = args[0]
15
+ elsif args.empty?
16
+ @aigp=0
17
+ else
18
+ raise
19
+ end
20
+ end
21
+
22
+ def to_i
23
+ @aigp.to_i
24
+ end
25
+
26
+ def to_hash
27
+ {:metric=> to_i}
28
+ end
29
+
30
+ def accumulated_igp_metric
31
+ format("(0x%8.8x) %d", to_i, to_i)
32
+ end
33
+ alias metric accumulated_igp_metric
34
+
35
+ def to_s(method=:default)
36
+ super(accumulated_igp_metric, method)
37
+ end
38
+
39
+ def encode
40
+ super([1, 11, @aigp >> 32, @aigp & 0xffffffff].pack('CnN2'))
41
+ end
42
+
43
+ def parse(s)
44
+ @flags, @type, len, value=super(s)
45
+ _, _, high, low = value.unpack('CnNN')
46
+ @aigp = (high << 32) + low
47
+ end
48
+
49
+ end
50
+
51
+ class Aigp
52
+ class << self
53
+ def new_hash(_arg={})
54
+ arg = {:metric=>0}.merge(_arg)
55
+ new arg[:metric]
56
+ end
57
+ end
58
+ end
59
+
60
+
61
+ end
62
+
63
+ load "../../test/unit/path_attributes/#{ File.basename($0.gsub(/.rb/,'_test.rb'))}" if __FILE__ == $0
@@ -117,6 +117,9 @@ module BGP
117
117
  super(:set, *args)
118
118
  end
119
119
  end
120
+ def to_hash
121
+ {:set=> as}
122
+ end
120
123
  end
121
124
 
122
125
  class As_path::Sequence < As_path::Segment
@@ -127,6 +130,9 @@ module BGP
127
130
  super(:sequence, *args)
128
131
  end
129
132
  end
133
+ def to_hash
134
+ {:sequence=> as}
135
+ end
130
136
  end
131
137
 
132
138
  class As_path::Confed_set < As_path::Segment
@@ -137,6 +143,9 @@ module BGP
137
143
  super(:confed_set, *args)
138
144
  end
139
145
  end
146
+ def to_hash
147
+ {:confed_set=> as}
148
+ end
140
149
  end
141
150
 
142
151
  class As_path::Confed_sequence < As_path::Segment
@@ -147,6 +156,9 @@ module BGP
147
156
  super(:confed_sequence, *args)
148
157
  end
149
158
  end
159
+ def to_hash
160
+ {:confed_sequence=> as}
161
+ end
150
162
  end
151
163
 
152
164
  def integer?(arg)
@@ -204,6 +216,12 @@ module BGP
204
216
  @segments.find { |s| s.seg_type == SEQUENCE }
205
217
  end
206
218
 
219
+ def to_hash
220
+ h = {}
221
+ @segments.each { |s| h = h.merge(s.to_hash) }
222
+ { :as_path=> h}
223
+ end
224
+
207
225
  private
208
226
 
209
227
  def parse(s,as4byte=false)
@@ -225,6 +243,45 @@ module BGP
225
243
  end
226
244
  end
227
245
 
246
+ class As_path
247
+ class << self
248
+ def new_hash(arg={})
249
+ o = new
250
+ [:set, :sequence, :confed_sequence, :confed_set].each do |set_type|
251
+ next unless arg.has_key? set_type
252
+ case set_type
253
+ when :set
254
+ o << As_path::Set.new(*arg[:set])
255
+ when :sequence
256
+ o << As_path::Sequence.new(*arg[:sequence])
257
+ when :confed_set
258
+ o << As_path::Confed_set.new(*arg[:confed_set])
259
+ when :confed_sequence
260
+ o << As_path::Confed_sequence.new(*arg[:confed_sequence])
261
+ else
262
+ raise
263
+ end
264
+ end
265
+ o
266
+ end
267
+ end
268
+
269
+ class << self
270
+ def new_set(*args)
271
+ new_hash :set=>args
272
+ end
273
+ def new_sequence(*args)
274
+ new_hash :sequence=>args
275
+ end
276
+ def new_confed_set(*args)
277
+ new_hash :confed_set=>args
278
+ end
279
+ def new_confed_sequence(*args)
280
+ new_hash :confed_sequence=>args
281
+ end
282
+ end
283
+ end
284
+
228
285
  end
229
286
 
230
287
  load "../../test/unit/path_attributes/#{ File.basename($0.gsub(/.rb/,'_test.rb'))}" if __FILE__ == $0
@@ -35,6 +35,9 @@ module BGP
35
35
  raise ArgumentError, "invalid argument, #{arg.class} #{arg}"
36
36
  end
37
37
  end
38
+ def to_hash
39
+ {}
40
+ end
38
41
  end
39
42
 
40
43
  end
@@ -45,6 +45,8 @@ module BGP
45
45
  AS4_PATH = 17
46
46
  AS4_AGGREGATOR = 18
47
47
 
48
+ ACCUMULATED_IGP_METRIC = 26
49
+
48
50
  SET = 1
49
51
  SEQUENCE = 2
50
52
  CONFED_SEQUENCE = 3
@@ -136,6 +138,14 @@ module BGP
136
138
  s +="]"
137
139
  end
138
140
 
141
+ def is_optional?
142
+ (@flags&8>0)
143
+ end
144
+
145
+ def is_transitive?
146
+ (@flags&4>0)
147
+ end
148
+
139
149
  def attribute_name
140
150
  name.split('_').collect { |w| w.capitalize }.join(' ')
141
151
  end
@@ -12,6 +12,7 @@
12
12
  mp_unreach
13
13
  extended_communities
14
14
  path_attribute
15
+ aigp
15
16
  }.each do |attr|
16
17
  require "bgp/path_attributes/#{attr}"
17
18
  end
@@ -100,7 +100,11 @@ module BGP
100
100
  def sort
101
101
  Cluster_list.new(to_ary.sort)
102
102
  end
103
-
103
+
104
+ def to_hash
105
+ {:cluster_ids=>@cluster_ids.collect { |c| c.to_s }}
106
+ end
107
+
104
108
  def sort!
105
109
  @cluster_ids = @cluster_ids.sort_by { |c| c.to_i }
106
110
  self
@@ -111,6 +115,25 @@ module BGP
111
115
  end
112
116
 
113
117
  end
118
+
119
+ class Cluster_list
120
+ class << self
121
+ def new_hash(arg={})
122
+ o = new
123
+ [:cluster_ids].each do |set_type|
124
+ next unless arg.has_key? set_type
125
+ case set_type
126
+ when :cluster_ids
127
+ o << arg[set_type]
128
+ else
129
+ raise
130
+ end
131
+ end
132
+ o
133
+
134
+ end
135
+ end
136
+ end
114
137
 
115
138
  end
116
139
 
@@ -27,7 +27,17 @@ module BGP
27
27
  class Communities < Attr
28
28
 
29
29
  class Community
30
-
30
+
31
+ class << self
32
+ def method_missing(name, *args, &block)
33
+ if name.to_s =~ /^(no_export|no_advertise|no_export_sub_confed|no_peer)$/
34
+ new name
35
+ else
36
+ super
37
+ end
38
+ end
39
+ end
40
+
31
41
  unless const_defined? :NO_EXPORT
32
42
  NO_EXPORT = 0xFFFFFF01
33
43
  NO_ADVERTISE = 0xFFFFFF02
@@ -79,6 +89,22 @@ module BGP
79
89
 
80
90
  end
81
91
 
92
+ class << self
93
+ def new_hash(arg={})
94
+ o = new
95
+ [:communities].each do |set_type|
96
+ next unless arg.has_key? set_type
97
+ case set_type
98
+ when :communities
99
+ o << arg[set_type]
100
+ else
101
+ raise
102
+ end
103
+ end
104
+ o
105
+ end
106
+ end
107
+
82
108
  def initialize(*args)
83
109
  @flags, @type = OPTIONAL_TRANSITIVE, COMMUNITIES
84
110
  if args[0].is_a?(String) and args[0].is_packed?
@@ -114,6 +140,10 @@ module BGP
114
140
  def to_s(method=:default)
115
141
  super(communities, method)
116
142
  end
143
+
144
+ def to_hash
145
+ { :communities=> @communities.collect { |comm| comm.to_s } }
146
+ end
117
147
 
118
148
  def encode
119
149
  super(@communities.collect { |comm| comm.encode }.join)
@@ -171,4 +201,5 @@ module BGP
171
201
  end
172
202
 
173
203
  end
204
+
174
205
  load "../../test/unit/path_attributes/#{ File.basename($0.gsub(/.rb/,'_test.rb'))}" if __FILE__ == $0
@@ -28,6 +28,26 @@ module BGP
28
28
 
29
29
  class Extended_communities < Attr
30
30
 
31
+ class << self
32
+ def new_hash(arg={})
33
+ o = new
34
+ arg.keys.each do |comm|
35
+ case comm
36
+ when :color ; o << Color.new(*arg[comm])
37
+ when :route_target ; o << Route_target.new(*arg[comm])
38
+ when :link_bandwidth ; o << Link_bandwidth.new(*arg[comm])
39
+ when :ospf_domain_id ; o << Ospf_domain_id.new(*arg[comm])
40
+ when :encapsulation ; o << Encapsulation.new(*arg[comm])
41
+ when :route_origin ; o << Route_origin.new(*arg[comm])
42
+ when :ospf_router_id ; o << Ospf_router_id.new(arg[comm])
43
+ else
44
+ raise
45
+ end
46
+ end
47
+ o
48
+ end
49
+ end
50
+
31
51
  attr_reader :communities
32
52
 
33
53
  def initialize(*args)
@@ -59,6 +79,12 @@ module BGP
59
79
  end
60
80
  alias << add
61
81
 
82
+ def to_hash
83
+ h = {}
84
+ @communities.each { |c| h = h.merge( { c.class.to_s.split('::').last.downcase.to_sym => c.instance_eval { value2 } }) }
85
+ h
86
+ end
87
+
62
88
  def extended_communities
63
89
  len = @communities.size*8
64
90
  s=[]