bgp4r 0.0.3
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.
- data/COPYING +674 -0
- data/LICENSE.txt +53 -0
- data/README.rdoc +259 -0
- data/bgp/aggregator.rb +104 -0
- data/bgp/as_path.rb +223 -0
- data/bgp/atomic_aggregate.rb +42 -0
- data/bgp/attribute.rb +181 -0
- data/bgp/attributes.rb +34 -0
- data/bgp/cluster_list.rb +117 -0
- data/bgp/common.rb +204 -0
- data/bgp/communities.rb +139 -0
- data/bgp/extended_communities.rb +107 -0
- data/bgp/extended_community.rb +254 -0
- data/bgp/iana.rb +269 -0
- data/bgp/io.rb +116 -0
- data/bgp/label.rb +94 -0
- data/bgp/local_pref.rb +75 -0
- data/bgp/message.rb +894 -0
- data/bgp/mp_reach.rb +208 -0
- data/bgp/multi_exit_disc.rb +76 -0
- data/bgp/neighbor.rb +291 -0
- data/bgp/next_hop.rb +63 -0
- data/bgp/nlri.rb +303 -0
- data/bgp/orf.rb +88 -0
- data/bgp/origin.rb +88 -0
- data/bgp/originator_id.rb +73 -0
- data/bgp/path_attribute.rb +210 -0
- data/bgp/prefix_orf.rb +263 -0
- data/bgp/rd.rb +107 -0
- data/examples/bgp +65 -0
- data/examples/routegen +85 -0
- data/examples/routegen.yml +50 -0
- data/test/aggregator_test.rb +66 -0
- data/test/as_path_test.rb +149 -0
- data/test/atomic_aggregate_test.rb +35 -0
- data/test/attribute_test.rb +57 -0
- data/test/cluster_list_test.rb +39 -0
- data/test/common_test.rb +68 -0
- data/test/communities_test.rb +75 -0
- data/test/extended_communities_test.rb +111 -0
- data/test/extended_community_test.rb +93 -0
- data/test/label_test.rb +50 -0
- data/test/local_pref_test.rb +43 -0
- data/test/message_test.rb +294 -0
- data/test/mp_reach_test.rb +143 -0
- data/test/multi_exit_disc_test.rb +46 -0
- data/test/neighbor_test.rb +50 -0
- data/test/next_hop_test.rb +37 -0
- data/test/nlri_test.rb +189 -0
- data/test/origin_test.rb +57 -0
- data/test/originator_id_test.rb +38 -0
- data/test/path_attribute_test.rb +127 -0
- data/test/prefix_orf_test.rb +97 -0
- data/test/rd_test.rb +44 -0
- metadata +133 -0
data/bgp/attribute.rb
ADDED
@@ -0,0 +1,181 @@
|
|
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 'bgp/common'
|
24
|
+
|
25
|
+
module BGP
|
26
|
+
|
27
|
+
module ATTR
|
28
|
+
|
29
|
+
### http://www.iana.org/assignments/bgp-parameters/bgp-parameters.xhtml#bgp-parameters-2
|
30
|
+
|
31
|
+
ORIGIN = 1
|
32
|
+
AS_PATH = 2
|
33
|
+
NEXT_HOP = 3
|
34
|
+
MULTI_EXIT_DISC = 4
|
35
|
+
LOCAL_PREF = 5
|
36
|
+
ATOMIC_AGGREGATE = 6
|
37
|
+
AGGREGATOR = 7
|
38
|
+
COMMUNITIES = 8
|
39
|
+
ORIGINATOR_ID = 9
|
40
|
+
CLUSTER_LIST = 10
|
41
|
+
|
42
|
+
MP_REACH = 14
|
43
|
+
MP_UNREACH = 15
|
44
|
+
EXTENDED_COMMUNITY = 16
|
45
|
+
AS4_PATH = 17
|
46
|
+
AS4_AGGREGATOR = 18
|
47
|
+
|
48
|
+
SET = 1
|
49
|
+
SEQUENCE = 2
|
50
|
+
CONFED_SEQUENCE = 3
|
51
|
+
CONFED_SET = 4
|
52
|
+
|
53
|
+
OPTIONAL = 0x8
|
54
|
+
TRANSITIVE = 0x4
|
55
|
+
PARTIAL = 0x2
|
56
|
+
EXTENDED_LENGTH = 0x1
|
57
|
+
NONE = 0x0
|
58
|
+
|
59
|
+
WELL_KNOWN_MANDATORY = TRANSITIVE
|
60
|
+
WELL_KNOWN_DISCRETIONARY = TRANSITIVE
|
61
|
+
OPTIONAL_TRANSITIVE = OPTIONAL | TRANSITIVE
|
62
|
+
OPTIONAL_NON_TRANSITIVE = OPTIONAL
|
63
|
+
|
64
|
+
def encode(value='',value_fmt=nil)
|
65
|
+
len, len_fmt = value.size, 'C'
|
66
|
+
if len>255
|
67
|
+
@flags |= EXTENDED_LENGTH
|
68
|
+
len_fmt='n'
|
69
|
+
end
|
70
|
+
if value_fmt
|
71
|
+
[@flags<<4, @type, len, *value].pack("CC#{len_fmt}#{value_fmt}")
|
72
|
+
else
|
73
|
+
([@flags<<4, @type, len].pack("CC#{len_fmt}") + value).is_packed
|
74
|
+
end
|
75
|
+
end
|
76
|
+
|
77
|
+
def parse(*args)
|
78
|
+
_parse_(*args)
|
79
|
+
end
|
80
|
+
|
81
|
+
def _parse_(s,vf=nil)
|
82
|
+
value, arr = '', []
|
83
|
+
flags = s.unpack('C')[0]
|
84
|
+
if flags & 0x10>0
|
85
|
+
arr = s.unpack("CCn")
|
86
|
+
len = arr[2]
|
87
|
+
if vf
|
88
|
+
value = s[4..-1].unpack(vf)
|
89
|
+
else
|
90
|
+
value = s[4..-1].unpack("a#{len}")
|
91
|
+
end
|
92
|
+
s.slice!(0,arr[2]+4).is_packed
|
93
|
+
else
|
94
|
+
arr = s.unpack("CCC")
|
95
|
+
len = arr[2]
|
96
|
+
if vf
|
97
|
+
value = s[3..-1].unpack(vf)
|
98
|
+
else
|
99
|
+
value = s[3..-1].unpack("a#{len}")
|
100
|
+
end
|
101
|
+
s.slice!(0,arr[2]+3).is_packed
|
102
|
+
end
|
103
|
+
arr[0]= arr[0] >>4
|
104
|
+
value[0].is_packed unless vf
|
105
|
+
arr + value
|
106
|
+
end
|
107
|
+
|
108
|
+
def name
|
109
|
+
self.class.to_s.split('::').last
|
110
|
+
end
|
111
|
+
|
112
|
+
def flags
|
113
|
+
flags = @flags
|
114
|
+
s ="["
|
115
|
+
(flags&8>0) ? s +="O" : s += "w"
|
116
|
+
(flags&4>0) ? s +="T" : s += "n"
|
117
|
+
(flags&2>0) ? s +="P" : s += "c"
|
118
|
+
(flags&1>0) ? s +="E" : s += "r"
|
119
|
+
s +="]"
|
120
|
+
end
|
121
|
+
|
122
|
+
def flags_short
|
123
|
+
flags = @flags
|
124
|
+
s ="["
|
125
|
+
s +="O" if (flags&8>0)
|
126
|
+
s +="T" if (flags&4>0)
|
127
|
+
s +="P" if (flags&2>0)
|
128
|
+
s +="E" if (flags&1>0)
|
129
|
+
s +="]"
|
130
|
+
end
|
131
|
+
|
132
|
+
def attribute_name
|
133
|
+
name.split('_').collect { |w| w.capitalize }.join(' ')
|
134
|
+
end
|
135
|
+
|
136
|
+
def to_s(value='', mode=:tcpdump, as4byte=false)
|
137
|
+
|
138
|
+
shex = as4byte ? to_shex4_len(20) : to_shex_len(20)
|
139
|
+
|
140
|
+
mode = :brief unless [:tcpdump, :brief, :hexlify].include?(mode)
|
141
|
+
|
142
|
+
case mode
|
143
|
+
when :brief
|
144
|
+
sprintf "%s %4s %10s: [%s]%s", flags, "(#{@type})", attribute_name, shex, "#{value.size>0 ? " '#{value}'" :''}"
|
145
|
+
when :hexlify
|
146
|
+
s = sprintf "%s %4s %10s: [%s]%s", flags, "(#{@type})", attribute_name, shex, "#{value.size>0 ? " '#{value}" :''}"
|
147
|
+
s +="\n\n"
|
148
|
+
if as4byte
|
149
|
+
s += self.encode4.hexlify.join("\n")
|
150
|
+
else
|
151
|
+
s += self.encode.hexlify.join("\n")
|
152
|
+
end
|
153
|
+
when :tcpdump
|
154
|
+
if as4byte
|
155
|
+
f, t, len, enc_value = _parse_(self.encode4, nil)
|
156
|
+
else
|
157
|
+
f, t, len, enc_value = _parse_(self.encode, nil)
|
158
|
+
end
|
159
|
+
s = sprintf "%s (%d), length: %d, Flags %s: %s", attribute_name, @type, len, flags_short, value
|
160
|
+
s += enc_value.hexlify.join(("\n "))
|
161
|
+
end
|
162
|
+
end
|
163
|
+
|
164
|
+
end
|
165
|
+
|
166
|
+
class Attr
|
167
|
+
|
168
|
+
include ATTR
|
169
|
+
include Comparable
|
170
|
+
|
171
|
+
def method_missing(name, *args, &block)
|
172
|
+
if name == :encode4
|
173
|
+
send :encode, *args, &block
|
174
|
+
else
|
175
|
+
super
|
176
|
+
end
|
177
|
+
end
|
178
|
+
|
179
|
+
end
|
180
|
+
|
181
|
+
end
|
data/bgp/attributes.rb
ADDED
@@ -0,0 +1,34 @@
|
|
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 'bgp/origin'
|
24
|
+
require 'bgp/next_hop'
|
25
|
+
require 'bgp/local_pref'
|
26
|
+
require 'bgp/multi_exit_disc'
|
27
|
+
require 'bgp/as_path'
|
28
|
+
require 'bgp/communities'
|
29
|
+
require 'bgp/aggregator'
|
30
|
+
require 'bgp/atomic_aggregate'
|
31
|
+
require 'bgp/originator_id'
|
32
|
+
require 'bgp/cluster_list'
|
33
|
+
require 'bgp/mp_reach'
|
34
|
+
require 'bgp/extended_communities'
|
data/bgp/cluster_list.rb
ADDED
@@ -0,0 +1,117 @@
|
|
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
|
+
|
24
|
+
require 'bgp/attribute'
|
25
|
+
|
26
|
+
module BGP
|
27
|
+
|
28
|
+
class Cluster_list < Attr
|
29
|
+
|
30
|
+
##########################################################
|
31
|
+
# CLUSTER ID #
|
32
|
+
##########################################################
|
33
|
+
class Id
|
34
|
+
def initialize(id)
|
35
|
+
@id = IPAddr.create(id)
|
36
|
+
end
|
37
|
+
def to_s
|
38
|
+
@id.to_s
|
39
|
+
end
|
40
|
+
def to_i
|
41
|
+
@id.to_i
|
42
|
+
end
|
43
|
+
def encode
|
44
|
+
@id.hton
|
45
|
+
end
|
46
|
+
end
|
47
|
+
|
48
|
+
##########################################################
|
49
|
+
# CLUSTER_LIST ATTRIBUTE #
|
50
|
+
##########################################################
|
51
|
+
|
52
|
+
def initialize(*args)
|
53
|
+
@flags, @type = OPTIONAL, CLUSTER_LIST
|
54
|
+
if args[0].is_a?(String) and args[0].is_packed?
|
55
|
+
parse(args[0])
|
56
|
+
elsif args[0].is_a?(self.class)
|
57
|
+
parse(args[0].encode, *args[1..-1])
|
58
|
+
else
|
59
|
+
add(*args)
|
60
|
+
end
|
61
|
+
end
|
62
|
+
|
63
|
+
def add(*args)
|
64
|
+
@cluster_ids ||=[]
|
65
|
+
args.flatten.each do |arg|
|
66
|
+
if arg.is_a?(String) and arg.split(' ').size>1
|
67
|
+
arg.split.each { |v| @cluster_ids << Id.new(v) }
|
68
|
+
elsif arg.is_a?(String) and arg.split(',').size>1
|
69
|
+
arg.split(',').each { |v| @cluster_ids << Id.new(v) }
|
70
|
+
elsif arg.is_a?(Id)
|
71
|
+
@cluster_ids << arg
|
72
|
+
else
|
73
|
+
@cluster_ids << Id.new(arg)
|
74
|
+
end
|
75
|
+
end
|
76
|
+
end
|
77
|
+
alias << add
|
78
|
+
|
79
|
+
def cluster_list
|
80
|
+
@cluster_ids.collect { |comm| comm.to_s }.join(' ')
|
81
|
+
end
|
82
|
+
|
83
|
+
def to_s(method=:default)
|
84
|
+
super(cluster_list, method)
|
85
|
+
end
|
86
|
+
|
87
|
+
def to_ary
|
88
|
+
@cluster_ids.collect { |c| c.to_i }
|
89
|
+
end
|
90
|
+
|
91
|
+
def encode
|
92
|
+
super(@cluster_ids.collect { |comm| comm.encode }.join)
|
93
|
+
end
|
94
|
+
|
95
|
+
def parse(s)
|
96
|
+
@flags, @type, len, value=super(s)
|
97
|
+
self << value.unpack("N#{len/4}")
|
98
|
+
end
|
99
|
+
|
100
|
+
def sort
|
101
|
+
Cluster_list.new(to_ary.sort)
|
102
|
+
end
|
103
|
+
|
104
|
+
def sort!
|
105
|
+
@cluster_ids = @cluster_ids.sort_by { |c| c.to_i }
|
106
|
+
self
|
107
|
+
end
|
108
|
+
|
109
|
+
def <=>(other)
|
110
|
+
self.sort.to_shex <=> other.sort.to_shex
|
111
|
+
end
|
112
|
+
|
113
|
+
end
|
114
|
+
|
115
|
+
end
|
116
|
+
|
117
|
+
load "../test/#{ File.basename($0.gsub(/.rb/,'_test.rb'))}" if __FILE__ == $0
|
data/bgp/common.rb
ADDED
@@ -0,0 +1,204 @@
|
|
1
|
+
# This file is part of BGP4R.
|
2
|
+
#
|
3
|
+
# BGP4R is free software: you can redistribute it and/or modify
|
4
|
+
# it under the terms of the GNU General Public License as published by
|
5
|
+
# the Free Software Foundation, either version 3 of the License, or
|
6
|
+
# (at your option) any later version.
|
7
|
+
#
|
8
|
+
# BGP4R is distributed in the hope that it will be useful,
|
9
|
+
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
10
|
+
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
11
|
+
# GNU General Public License for more details.
|
12
|
+
#
|
13
|
+
# You should have received a copy of the GNU General Public License
|
14
|
+
# along with Foobar. If not, see <http://www.gnu.org/licenses/>.
|
15
|
+
|
16
|
+
require 'ipaddr'
|
17
|
+
require 'logger'
|
18
|
+
|
19
|
+
class IPAddr
|
20
|
+
alias encode hton
|
21
|
+
|
22
|
+
def self.create(arg)
|
23
|
+
if arg.is_a?(String) and arg.is_packed?
|
24
|
+
IPAddr.new_ntoh(arg)
|
25
|
+
elsif arg.is_a?(Integer)
|
26
|
+
IPAddr.new_ntoh([arg].pack('N'))
|
27
|
+
elsif arg.is_a?(Array) and arg[0].is_a?(Fixnum)
|
28
|
+
IPAddr.new_ntoh([arg].pack('C*'))
|
29
|
+
else
|
30
|
+
IPAddr.new(arg)
|
31
|
+
end
|
32
|
+
end
|
33
|
+
|
34
|
+
#TODO: if not used, get rid of it.
|
35
|
+
def self.new_nlri4(arg)
|
36
|
+
if arg.is_a?(String) and arg.is_packed?
|
37
|
+
arg +=([0]*3).pack('C*')
|
38
|
+
plen, *nlri = arg.unpack('CC4')
|
39
|
+
ipaddr = nlri.collect { |n| n.to_s }.join('.') + "/" + plen .to_s
|
40
|
+
IPAddr.new(ipaddr)
|
41
|
+
else
|
42
|
+
IPAddr.new(arg)
|
43
|
+
end
|
44
|
+
end
|
45
|
+
|
46
|
+
def _mlen_
|
47
|
+
m = @mask_addr
|
48
|
+
len = ipv6? ? 128 : 32
|
49
|
+
loop do
|
50
|
+
break if m & 1 > 0
|
51
|
+
m = m >> 1
|
52
|
+
len += -1
|
53
|
+
end
|
54
|
+
len
|
55
|
+
end
|
56
|
+
|
57
|
+
def mlen
|
58
|
+
@_jme_mlen_ ||= _mlen_
|
59
|
+
end
|
60
|
+
|
61
|
+
def _generate_network_inc_
|
62
|
+
max_len = ipv4? ? 32 : 128
|
63
|
+
Proc.new { |n| n*(2**(max_len - mlen)) }
|
64
|
+
end
|
65
|
+
def +(i)
|
66
|
+
[IPAddr.create(to_i + i).to_s, mlen].join("/")
|
67
|
+
end
|
68
|
+
def ^(i)
|
69
|
+
@increment ||= _generate_network_inc_
|
70
|
+
[IPAddr.create(to_i + @increment.call(i)).to_s, mlen].join("/")
|
71
|
+
end
|
72
|
+
private :_generate_network_inc_
|
73
|
+
|
74
|
+
def netmask
|
75
|
+
if ipv4?
|
76
|
+
[@mask_addr].pack('N').unpack('C4').collect { |x| x.to_s}.join('.')
|
77
|
+
else
|
78
|
+
#TODO netmask ipv6
|
79
|
+
@mask_addr
|
80
|
+
end
|
81
|
+
end
|
82
|
+
|
83
|
+
end
|
84
|
+
|
85
|
+
|
86
|
+
class Object
|
87
|
+
def to_shex(*args)
|
88
|
+
self.respond_to?(:encode) ? self.encode(*args).unpack('H*')[0] : ""
|
89
|
+
end
|
90
|
+
alias to_s_hexlify to_shex
|
91
|
+
def to_shex4(*args)
|
92
|
+
self.respond_to?(:encode4) ? self.encode4(*args).unpack('H*')[0] : ""
|
93
|
+
end
|
94
|
+
def to_shex_len(len, *args)
|
95
|
+
s = to_shex(*args)
|
96
|
+
"#{s[0..len]}#{s.size>len ? '...' : ''}"
|
97
|
+
end
|
98
|
+
def to_shex4_len(len, *args)
|
99
|
+
s = to_shex4(*args)
|
100
|
+
"#{s[0..len]}#{s.size>len ? '...' : ''}"
|
101
|
+
end
|
102
|
+
end
|
103
|
+
|
104
|
+
class Array
|
105
|
+
alias_method :old_pack, :pack
|
106
|
+
def pack(*args)
|
107
|
+
s = self.old_pack(*args)
|
108
|
+
s.instance_eval { @__is_packed__ = true }
|
109
|
+
s
|
110
|
+
end
|
111
|
+
end
|
112
|
+
|
113
|
+
class String
|
114
|
+
def is_packed?
|
115
|
+
defined?(@__is_packed__) and @__is_packed__
|
116
|
+
end
|
117
|
+
def is_packed
|
118
|
+
@__is_packed__ = true
|
119
|
+
self
|
120
|
+
end
|
121
|
+
alias packed? :is_packed?
|
122
|
+
|
123
|
+
def hexlify
|
124
|
+
return self unless is_packed?
|
125
|
+
s=self.dup
|
126
|
+
ls=[""]
|
127
|
+
n=0
|
128
|
+
while s.size>0
|
129
|
+
l = s.slice!(0,16)
|
130
|
+
ls << format("0x%4.4x: %s", n,
|
131
|
+
l.unpack("n#{l.size/2}").collect { |x| format("%4.4x",x) }.join(' '))
|
132
|
+
n+=1
|
133
|
+
end
|
134
|
+
ls
|
135
|
+
end
|
136
|
+
|
137
|
+
end
|
138
|
+
|
139
|
+
class Log < Logger
|
140
|
+
private_class_method :new
|
141
|
+
@@logger = nil
|
142
|
+
def initialize(s)
|
143
|
+
super(s)
|
144
|
+
@@time=Time.now
|
145
|
+
self.datetime_format = "%M:%S"
|
146
|
+
self.level = Logger::INFO
|
147
|
+
end
|
148
|
+
def Log.time_reset
|
149
|
+
@time = Time.now
|
150
|
+
end
|
151
|
+
def Log.create(s=STDERR)
|
152
|
+
@@logger ||= new(s)
|
153
|
+
end
|
154
|
+
def Log.set_filename(s)
|
155
|
+
@@logger = new(s)
|
156
|
+
end
|
157
|
+
def Log.level=(level)
|
158
|
+
return unless (0..4) === level
|
159
|
+
@@logger.level=(level)
|
160
|
+
end
|
161
|
+
def Log.level
|
162
|
+
case @@logger.level
|
163
|
+
when Logger::INFO ; "(#{Logger::INFO }) 'INFO'"
|
164
|
+
when Logger::DEBUG ; "(#{Logger::DEBUG }) 'DEBUG'"
|
165
|
+
when Logger::WARN ; "(#{Logger::WARN }) 'WARN'"
|
166
|
+
when Logger::ERROR ; "(#{Logger::ERROR }) 'ERROR'"
|
167
|
+
when Logger::FATAL ; "(#{Logger::FATAL }) 'FATAL'"
|
168
|
+
end
|
169
|
+
end
|
170
|
+
def Log.clear
|
171
|
+
`rm #{Log.filename}`
|
172
|
+
Log.set_filename(Log.filename)
|
173
|
+
end
|
174
|
+
def Log.filename
|
175
|
+
@@logger.instance_eval { @logdev.filename }
|
176
|
+
end
|
177
|
+
def Log.start(*arg)
|
178
|
+
Log.create(*arg)
|
179
|
+
end
|
180
|
+
def Log.info(txt)
|
181
|
+
@@logger.info(txt) unless @@logger.nil?
|
182
|
+
end
|
183
|
+
def Log.fatal(txt)
|
184
|
+
@@logger.fatal(txt) unless @@logger.nil?
|
185
|
+
end
|
186
|
+
def Log.error(txt)
|
187
|
+
@@logger.error(txt) unless @@logger.nil?
|
188
|
+
end
|
189
|
+
def Log.debug(txt)
|
190
|
+
@@logger.debug(txt) unless @@logger.nil?
|
191
|
+
end
|
192
|
+
def Log.warn(txt)
|
193
|
+
@@logger.warn(txt) unless @@logger.nil?
|
194
|
+
end
|
195
|
+
def Log.<<(txt)
|
196
|
+
elapsed = Time.now - @@time
|
197
|
+
@@logger << "<< #{format "%4.6f", elapsed}: #{txt}\n" unless @@logger.nil?
|
198
|
+
end
|
199
|
+
def Log.>>(txt)
|
200
|
+
elapsed = Time.now.to_f - @@time.to_f
|
201
|
+
@@logger << ">> #{format "%4.6f", elapsed}: #{txt}\n" unless @@logger.nil?
|
202
|
+
end
|
203
|
+
end
|
204
|
+
|
data/bgp/communities.rb
ADDED
@@ -0,0 +1,139 @@
|
|
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
|
+
|
24
|
+
require 'bgp/attribute'
|
25
|
+
|
26
|
+
|
27
|
+
module BGP
|
28
|
+
|
29
|
+
class Communities < Attr
|
30
|
+
|
31
|
+
class Community
|
32
|
+
|
33
|
+
def initialize(arg)
|
34
|
+
if arg.is_a?(Symbol)
|
35
|
+
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
|
40
|
+
else
|
41
|
+
raise ArgumentError, "invalid argument #{val}"
|
42
|
+
end
|
43
|
+
elsif arg.is_a?(String) and arg.split(':').size==2
|
44
|
+
self.value=arg.split(':').collect { |n| n.to_i }.pack('n2').unpack('N')[0]
|
45
|
+
else
|
46
|
+
self.value=arg
|
47
|
+
end
|
48
|
+
end
|
49
|
+
|
50
|
+
def value=(val)
|
51
|
+
raise ArgumentError, "invalid argument #{val}" unless val.is_a?(Fixnum) or val.is_a?(Bignum)
|
52
|
+
@value=val
|
53
|
+
end
|
54
|
+
|
55
|
+
def to_i
|
56
|
+
@value
|
57
|
+
end
|
58
|
+
|
59
|
+
def to_s
|
60
|
+
[@value >> 16, @value & 0xffff].join(':')
|
61
|
+
end
|
62
|
+
|
63
|
+
# The community attribute values ranging from 0x0000000 through
|
64
|
+
# 0x0000FFFF and 0xFFFF0000 through 0xFFFFFFFF are hereby reserved.
|
65
|
+
def is_reserved?
|
66
|
+
(0x0000000..0x0000FFFF ) === @value or (0xFFFF0000..0xFFFFFFFF) === @value
|
67
|
+
end
|
68
|
+
|
69
|
+
def encode
|
70
|
+
[@value].pack('N')
|
71
|
+
end
|
72
|
+
|
73
|
+
end
|
74
|
+
|
75
|
+
def initialize(*args)
|
76
|
+
@flags, @type = OPTIONAL_TRANSITIVE, COMMUNITIES
|
77
|
+
if args[0].is_a?(String) and args[0].is_packed?
|
78
|
+
parse(args[0])
|
79
|
+
elsif args[0].is_a?(self.class) and args[0].respond_to?(:encode)
|
80
|
+
parse(args[0].encode, *args[1..-1])
|
81
|
+
else
|
82
|
+
add(*args)
|
83
|
+
end
|
84
|
+
end
|
85
|
+
|
86
|
+
def add(*args)
|
87
|
+
@communities ||=[]
|
88
|
+
args.flatten.each do |arg|
|
89
|
+
if arg.is_a?(String) and arg.split(' ').size>1
|
90
|
+
arg.split.each { |v| @communities << Community.new(v) }
|
91
|
+
elsif arg.is_a?(String) and arg.split(',').size>1
|
92
|
+
arg.split(',').each { |v| @communities << Community.new(v) }
|
93
|
+
elsif arg.is_a?(Community)
|
94
|
+
@communities << arg
|
95
|
+
else
|
96
|
+
@communities << Community.new(arg)
|
97
|
+
end
|
98
|
+
end
|
99
|
+
end
|
100
|
+
alias << add
|
101
|
+
|
102
|
+
def communities
|
103
|
+
@communities.collect { |comm| comm.to_s }.join(' ')
|
104
|
+
end
|
105
|
+
|
106
|
+
def to_s(method=:default)
|
107
|
+
super(communities, method)
|
108
|
+
end
|
109
|
+
|
110
|
+
def to_ary
|
111
|
+
@communities.collect { |c| c.to_i }
|
112
|
+
end
|
113
|
+
|
114
|
+
def encode
|
115
|
+
super(@communities.collect { |comm| comm.encode }.join)
|
116
|
+
end
|
117
|
+
|
118
|
+
def parse(s)
|
119
|
+
@flags, @type, len, value=super(s)
|
120
|
+
self << value.unpack("N#{len/4}")
|
121
|
+
end
|
122
|
+
|
123
|
+
def sort
|
124
|
+
Communities.new(to_ary.sort)
|
125
|
+
end
|
126
|
+
|
127
|
+
def sort!
|
128
|
+
@communities = @communities.sort_by { |c| c.to_i }
|
129
|
+
self
|
130
|
+
end
|
131
|
+
|
132
|
+
def <=>(other)
|
133
|
+
self.sort.to_shex <=> other.sort.to_shex
|
134
|
+
end
|
135
|
+
|
136
|
+
end
|
137
|
+
|
138
|
+
end
|
139
|
+
load "../test/#{ File.basename($0.gsub(/.rb/,'_test.rb'))}" if __FILE__ == $0
|