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
@@ -0,0 +1,210 @@
|
|
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/attributes'
|
25
|
+
|
26
|
+
module BGP
|
27
|
+
|
28
|
+
class Path_attribute
|
29
|
+
include BGP::ATTR
|
30
|
+
def initialize(*args)
|
31
|
+
if args.size <= 2 and args[0].is_a?(String) and args[0].is_packed?
|
32
|
+
s = args[0]
|
33
|
+
@attributes=[]
|
34
|
+
while s.size>0
|
35
|
+
@attributes << Attr.factory(s)
|
36
|
+
end
|
37
|
+
else
|
38
|
+
add(*args)
|
39
|
+
end
|
40
|
+
end
|
41
|
+
def add(*args)
|
42
|
+
@attributes ||=[]
|
43
|
+
args.each { |arg| @attributes << arg if arg.is_a?(BGP::Attr) }
|
44
|
+
self
|
45
|
+
end
|
46
|
+
alias << add
|
47
|
+
|
48
|
+
def to_ary
|
49
|
+
@attributes
|
50
|
+
end
|
51
|
+
|
52
|
+
def to_s(method=:default,as4byte=false)
|
53
|
+
"Path Attributes:" + ([""] + @attributes.collect { |a|
|
54
|
+
if as4byte and a.is_a?(As_path)
|
55
|
+
a.to_s(method, as4byte)
|
56
|
+
else
|
57
|
+
a.to_s(method)
|
58
|
+
end
|
59
|
+
}).join("\n ")
|
60
|
+
end
|
61
|
+
|
62
|
+
def find(klass)
|
63
|
+
@attributes.find { |a| a.is_a?(klass) }
|
64
|
+
end
|
65
|
+
|
66
|
+
def size
|
67
|
+
@attributes.size
|
68
|
+
end
|
69
|
+
|
70
|
+
def [](type)
|
71
|
+
case type
|
72
|
+
when ORIGIN, :origin
|
73
|
+
find(Origin)
|
74
|
+
when AS_PATH, :as_path
|
75
|
+
find(As_path)
|
76
|
+
when NEXT_HOP, :next_hop
|
77
|
+
find(Next_hop)
|
78
|
+
when MULTI_EXIT_DISC, :multi_exit_disc
|
79
|
+
find(Multi_exit_disc)
|
80
|
+
when LOCAL_PREF, :local_pref
|
81
|
+
find(Local_pref)
|
82
|
+
when ATOMIC_AGGREGATE, :atomic_aggregate
|
83
|
+
find(Atomic_aggregate)
|
84
|
+
when AGGREGATOR, :aggregator
|
85
|
+
find(Aggregator)
|
86
|
+
when COMMUNITIES, :communities
|
87
|
+
find(Communities)
|
88
|
+
when ORIGINATOR_ID, :originator_id
|
89
|
+
find(Originator_id)
|
90
|
+
when CLUSTER_LIST, :cluster_list
|
91
|
+
find(Cluster_list)
|
92
|
+
when MP_REACH, :mp_reach
|
93
|
+
find(Mp_reach)
|
94
|
+
when MP_UNREACH, :mp_unreach
|
95
|
+
find(Mp_unreach)
|
96
|
+
when EXTENDED_COMMUNITY, :extended_community
|
97
|
+
find(Extended_communities)
|
98
|
+
when AS4_PATH, :as4_path
|
99
|
+
find(As4_path)
|
100
|
+
when AS4_AGGREGATOR, :as4_aggregator
|
101
|
+
find(As4_aggregator)
|
102
|
+
end
|
103
|
+
end
|
104
|
+
|
105
|
+
def has?(klass=nil)
|
106
|
+
if klass
|
107
|
+
@attributes.find { |a| a.is_a?(klass) }.nil? ? false : true
|
108
|
+
else
|
109
|
+
@attributes.collect { |attr| attr.class }
|
110
|
+
end
|
111
|
+
end
|
112
|
+
|
113
|
+
def encode(as4byte=false)
|
114
|
+
[@attributes.compact.collect { |x| as4byte ? x.encode4 : x.encode }.join].pack('a*')
|
115
|
+
end
|
116
|
+
|
117
|
+
def insert(*args)
|
118
|
+
for arg in args
|
119
|
+
next unless arg.is_a?(Attr)
|
120
|
+
to_ary.insert(0,arg)
|
121
|
+
end
|
122
|
+
self
|
123
|
+
end
|
124
|
+
|
125
|
+
def append(*args)
|
126
|
+
for arg in args
|
127
|
+
next unless arg.is_a?(Attr)
|
128
|
+
to_ary << (arg)
|
129
|
+
end
|
130
|
+
self
|
131
|
+
end
|
132
|
+
|
133
|
+
def replace(*args)
|
134
|
+
for arg in args
|
135
|
+
next unless arg.is_a?(Attr)
|
136
|
+
attr = to_ary.find { |x| x.class == arg.class }
|
137
|
+
if attr.nil?
|
138
|
+
append(arg)
|
139
|
+
else
|
140
|
+
index = to_ary.index(attr)
|
141
|
+
to_ary[index] = arg
|
142
|
+
end
|
143
|
+
end
|
144
|
+
self
|
145
|
+
end
|
146
|
+
|
147
|
+
def delete(*klasses)
|
148
|
+
for klass in klasses
|
149
|
+
next unless klass.is_a?(Class)
|
150
|
+
to_ary.delete_if { |x| x.class == klass }
|
151
|
+
end
|
152
|
+
self
|
153
|
+
end
|
154
|
+
|
155
|
+
end
|
156
|
+
|
157
|
+
end
|
158
|
+
|
159
|
+
module BGP
|
160
|
+
|
161
|
+
class Attr
|
162
|
+
include BGP::ATTR
|
163
|
+
def self.factory(s)
|
164
|
+
flags, type = s.unpack('CC')
|
165
|
+
case type
|
166
|
+
when ORIGIN
|
167
|
+
Origin.new(s)
|
168
|
+
when AS_PATH
|
169
|
+
As_path.new(s)
|
170
|
+
when NEXT_HOP
|
171
|
+
Next_hop.new(s)
|
172
|
+
when MULTI_EXIT_DISC
|
173
|
+
Multi_exit_disc.new(s)
|
174
|
+
when LOCAL_PREF
|
175
|
+
Local_pref.new(s)
|
176
|
+
when ATOMIC_AGGREGATE
|
177
|
+
Atomic_aggregate.new(s)
|
178
|
+
when AGGREGATOR
|
179
|
+
Aggregator.new(s)
|
180
|
+
when COMMUNITIES
|
181
|
+
Communities.new(s)
|
182
|
+
when ATOMIC_AGGREGATE
|
183
|
+
Atomic_aggregate.new(s)
|
184
|
+
when ORIGINATOR_ID
|
185
|
+
Originator_id.new(s)
|
186
|
+
when CLUSTER_LIST
|
187
|
+
Cluster_list.new(s)
|
188
|
+
when MP_REACH
|
189
|
+
Mp_reach.new(s)
|
190
|
+
when MP_UNREACH
|
191
|
+
Mp_unreach.new(s)
|
192
|
+
when EXTENDED_COMMUNITY
|
193
|
+
Extended_communities.new(s)
|
194
|
+
else
|
195
|
+
if flags & 0x10==1
|
196
|
+
len = s.slice!(0,2).unpack("n")[0]
|
197
|
+
else
|
198
|
+
len = s.slice!(0,1).unpack('C')[0]
|
199
|
+
end
|
200
|
+
s.slice!(0,len)
|
201
|
+
raise RuntimeError, "factory for #{type} to be implemented soon"
|
202
|
+
nil
|
203
|
+
end
|
204
|
+
end
|
205
|
+
|
206
|
+
end
|
207
|
+
|
208
|
+
end
|
209
|
+
|
210
|
+
load "../test/#{ File.basename($0.gsub(/.rb/,'_test.rb'))}" if __FILE__ == $0
|
data/bgp/prefix_orf.rb
ADDED
@@ -0,0 +1,263 @@
|
|
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/nlri'
|
25
|
+
require 'bgp/orf'
|
26
|
+
|
27
|
+
module BGP
|
28
|
+
|
29
|
+
class Prefix_entry < Orf::Entry
|
30
|
+
|
31
|
+
@_seqn_ = -10
|
32
|
+
class << self
|
33
|
+
attr_accessor :_seqn_
|
34
|
+
def seqn ; Address_prefix_orf_entry._seqn_ +=10 ;end
|
35
|
+
end
|
36
|
+
|
37
|
+
def initialize(*args)
|
38
|
+
if args[0].is_a?(String) and args[0].is_packed?
|
39
|
+
_parse_(*args)
|
40
|
+
elsif args.size==6
|
41
|
+
@action, @match, @seqn, @min, @max, prefix = args
|
42
|
+
@prefix = BGP::Prefix.new(prefix)
|
43
|
+
elsif args.size==4
|
44
|
+
@min, @max = 0, 0
|
45
|
+
@action, @match, @seqn, prefix = args
|
46
|
+
@prefix = BGP::Prefix.new(prefix)
|
47
|
+
elsif args.size==1 and args[0].is_a?(Hash)
|
48
|
+
set(args[0])
|
49
|
+
else
|
50
|
+
p args
|
51
|
+
raise
|
52
|
+
end
|
53
|
+
end
|
54
|
+
|
55
|
+
def action=(val)
|
56
|
+
case val
|
57
|
+
when 0, :add
|
58
|
+
@action=0
|
59
|
+
when 1, :remove
|
60
|
+
@action=1
|
61
|
+
when 2, :remove_all
|
62
|
+
@action=2
|
63
|
+
end
|
64
|
+
end
|
65
|
+
|
66
|
+
def action_to_i
|
67
|
+
@action
|
68
|
+
end
|
69
|
+
|
70
|
+
def action_to_s
|
71
|
+
case @action
|
72
|
+
when 0 ; 'add'
|
73
|
+
when 1 ; 'remove'
|
74
|
+
when 2 ; 'remove all'
|
75
|
+
else
|
76
|
+
'unknown action'
|
77
|
+
end
|
78
|
+
end
|
79
|
+
|
80
|
+
def match_to_i
|
81
|
+
@match
|
82
|
+
end
|
83
|
+
|
84
|
+
def match_to_s
|
85
|
+
case @match
|
86
|
+
when 0 ; 'permit'
|
87
|
+
when 1 ; 'deny'
|
88
|
+
end
|
89
|
+
end
|
90
|
+
|
91
|
+
def match=(val)
|
92
|
+
case val
|
93
|
+
when 0, :permit ; @match=0
|
94
|
+
when 1, :deny ; @match=1
|
95
|
+
else
|
96
|
+
raise
|
97
|
+
end
|
98
|
+
end
|
99
|
+
|
100
|
+
def set(h)
|
101
|
+
self.action = h[:action] ||= 0
|
102
|
+
self.match = h[:match] ||= 0
|
103
|
+
@seqn = h[:seqn] ||= 0
|
104
|
+
@min = h[:min] ||= 0
|
105
|
+
@max = h[:max] ||= 0
|
106
|
+
@prefix = BGP::Prefix.new(h[:prefix]) if h[:prefix]
|
107
|
+
end
|
108
|
+
|
109
|
+
def encode
|
110
|
+
[_first_octet_,@seqn, @min, @max, @prefix.encode(true)].pack('CNCCa*')
|
111
|
+
end
|
112
|
+
|
113
|
+
def to_s
|
114
|
+
#FIXME unit-test
|
115
|
+
s = format("seq %3s %6s %s", @seqn, action_to_s, @prefix)
|
116
|
+
s += " ge #{@min}" if @min>0
|
117
|
+
s += " le #{@max}" if @max>0
|
118
|
+
s += " #{match_to_s}"
|
119
|
+
s
|
120
|
+
end
|
121
|
+
|
122
|
+
private
|
123
|
+
|
124
|
+
def _first_octet_
|
125
|
+
(@action<<6) | ((@match & 0x1) << 5)
|
126
|
+
end
|
127
|
+
|
128
|
+
def size
|
129
|
+
@prefix.nbyte+7+1
|
130
|
+
end
|
131
|
+
|
132
|
+
def _parse_(s, afi=1)
|
133
|
+
#puts "s before parse: #{s.unpack('H*')}"
|
134
|
+
o1, @seqn, @min, @max, prefix = s.unpack('CNCCa*')
|
135
|
+
@action = o1 >> 6
|
136
|
+
@match = (o1 >> 5) & 1
|
137
|
+
@prefix = BGP::Prefix.new(prefix.is_packed, afi)
|
138
|
+
#puts "size of orf entry is : #{size}"
|
139
|
+
s.slice!(0,size)
|
140
|
+
#puts "s after parse: #{s.unpack('H*')}"
|
141
|
+
end
|
142
|
+
|
143
|
+
def self.add(*args) ; Prefix_entry.new(0,*args) ; end
|
144
|
+
def self.add_and_deny(*args) ; Prefix_entry.new(0,1,*args) ; end
|
145
|
+
def self.add_and_permit(*args) ; Prefix_entry.new(0,0,*args) ; end
|
146
|
+
def self.remove(*args) ; Prefix_entry.new(1,*args) ; end
|
147
|
+
def self.remove_and_deny(*args) ; Prefix_entry.new(1,1,*args) ; end
|
148
|
+
def self.remove_and_permit(*args) ; Prefix_entry.new(1,0,*args) ; end
|
149
|
+
def self.remove_all(*args) ; Prefix_entry.new(2,0) ; end
|
150
|
+
|
151
|
+
end
|
152
|
+
|
153
|
+
end
|
154
|
+
|
155
|
+
class BGP::Prefix_orf < BGP::Orf
|
156
|
+
|
157
|
+
def initialize(*args)
|
158
|
+
if args[0].is_a?(String) and args[0].is_packed?
|
159
|
+
_parse_(*args)
|
160
|
+
elsif args[0].is_a?(self.class) and args[0].respond_to?(:encode)
|
161
|
+
_parse_(args[0].encode)
|
162
|
+
else
|
163
|
+
super(64, *args)
|
164
|
+
end
|
165
|
+
end
|
166
|
+
|
167
|
+
def add(e)
|
168
|
+
raise ArgumentError, "invalid argument" unless e.is_a?(BGP::Prefix_entry)
|
169
|
+
super(e)
|
170
|
+
end
|
171
|
+
|
172
|
+
def _parse_(s)
|
173
|
+
@entries=[]
|
174
|
+
@type, len, entries = s.unpack('Cna*')
|
175
|
+
while entries.size>0
|
176
|
+
#p entries.unpack('H*')
|
177
|
+
@entries << BGP::Prefix_entry.new(entries.is_packed)
|
178
|
+
end
|
179
|
+
end
|
180
|
+
|
181
|
+
def cisco_prefix_entry_type
|
182
|
+
@type=130
|
183
|
+
end
|
184
|
+
|
185
|
+
end
|
186
|
+
|
187
|
+
load "../test/#{ File.basename($0.gsub(/.rb/,'_test.rb'))}" if __FILE__ == $0
|
188
|
+
|
189
|
+
__END__
|
190
|
+
|
191
|
+
|
192
|
+
2. Address Prefix ORF-Type
|
193
|
+
|
194
|
+
The Address Prefix ORF-Type allows one to express ORFs in terms of
|
195
|
+
address prefixes. That is, it provides address prefix based route
|
196
|
+
filtering, including prefix length or range based matching, as well
|
197
|
+
as wild-card address prefix matching.
|
198
|
+
|
199
|
+
Conceptually an Address Prefix ORF entry consists of the fields
|
200
|
+
<Sequence, Match, Length, Prefix, Minlen, Maxlen>.
|
201
|
+
|
202
|
+
The "Sequence" field specifies the relative ordering of the entry
|
203
|
+
among all the Address Prefix ORF entries.
|
204
|
+
|
205
|
+
The "Match" field specifies whether this entry is "PERMIT" (value 0),
|
206
|
+
or "DENY" (value 1).
|
207
|
+
|
208
|
+
The "Length" field indicates the length in bits of the address
|
209
|
+
prefix. A length of zero indicates a prefix that matches all (as
|
210
|
+
specified by the address family) addresses (with prefix itself of
|
211
|
+
zero octets).
|
212
|
+
|
213
|
+
The "Prefix" field contains an address prefix of an address family.
|
214
|
+
|
215
|
+
The "Minlen" field indicates the minimum prefix length in bits that
|
216
|
+
is required for "matching". The field is considered as un-specified
|
217
|
+
with value 0.
|
218
|
+
|
219
|
+
The "Maxlen" field indicates the maximum prefix length in bits that
|
220
|
+
is required for "matching". The field is considered as un-specified
|
221
|
+
with value 0.
|
222
|
+
|
223
|
+
The fields "Sequence", "Length", "Minlen", and "Maxlen" are all
|
224
|
+
unsigned integers.
|
225
|
+
|
226
|
+
This document imposes the following requirement on the values of
|
227
|
+
these fields:
|
228
|
+
|
229
|
+
0 <= Length < Minlen <= Maxlen
|
230
|
+
|
231
|
+
In addition, the "Maxlen" must be no more than the maximum length (in
|
232
|
+
bits) of a host address for a given address family [BGP-MP].
|
233
|
+
|
234
|
+
|
235
|
+
3. Address Prefix ORF Encoding
|
236
|
+
|
237
|
+
The value of the ORF-Type for the Address Prefix ORF-Type is 64.
|
238
|
+
|
239
|
+
An Address Prefix ORF entry is encoded as follows. The "Match" field
|
240
|
+
of the entry is encoded in the "Match" field of the common part [BGP-
|
241
|
+
ORF], and the remaining fields of the entry is encoded in the "Type
|
242
|
+
specific part" as shown in Figure 1.
|
243
|
+
|
244
|
+
|
245
|
+
+--------------------------------+
|
246
|
+
| Sequence (4 octets) |
|
247
|
+
+--------------------------------+
|
248
|
+
| Minlen (1 octet) |
|
249
|
+
+--------------------------------+
|
250
|
+
| Maxlen (1 octet) |
|
251
|
+
+--------------------------------+
|
252
|
+
| Length (1 octet) |
|
253
|
+
+--------------------------------+
|
254
|
+
| Prefix (variable length) |
|
255
|
+
+--------------------------------+
|
256
|
+
|
257
|
+
Figure 1: Address Prefix ORF Encoding
|
258
|
+
|
259
|
+
|
260
|
+
Note that the Prefix field contains the address prefix followed by
|
261
|
+
enough trailing bits to make the end of the field fall on an octet
|
262
|
+
boundary. The value of the trailing bits is irrelevant.
|
263
|
+
|
data/bgp/rd.rb
ADDED
@@ -0,0 +1,107 @@
|
|
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/common'
|
25
|
+
module BGP
|
26
|
+
class Rd
|
27
|
+
attr_reader :admin, :assign
|
28
|
+
def bit_length ; 64 ; end
|
29
|
+
def initialize(*args)
|
30
|
+
if args.size==1 and args[0].is_a?(String) and args[0].is_packed?
|
31
|
+
parse(args[0])
|
32
|
+
elsif args[0].is_a?(self.class)
|
33
|
+
parse(args[0].encode, *args[1..-1])
|
34
|
+
elsif args.empty?
|
35
|
+
@enc_type, @admin, @assign = [0]*3
|
36
|
+
elsif args.size==3
|
37
|
+
admin, assign, @enc_type = args
|
38
|
+
case @enc_type
|
39
|
+
when 0
|
40
|
+
@admin, @assign,@enc_type = admin, assign, 0
|
41
|
+
when 1
|
42
|
+
@enc_type = 1
|
43
|
+
@admin = IPAddr.new(admin)
|
44
|
+
@assign = assign
|
45
|
+
when 2
|
46
|
+
@admin, @assign, @enc_type, = admin, assign, 2
|
47
|
+
end
|
48
|
+
elsif args.size==2
|
49
|
+
admin, assign = args
|
50
|
+
if admin.is_a?(String)
|
51
|
+
@admin, @assign, @enc_type = IPAddr.new(admin), assign, 1
|
52
|
+
elsif assign.is_a?(String)
|
53
|
+
@admin, @assign, @enc_type, = admin, IPAddr.new(assign).to_i, 2
|
54
|
+
else
|
55
|
+
@admin, @assign, @enc_type, = admin, assign, 0
|
56
|
+
end
|
57
|
+
end
|
58
|
+
end
|
59
|
+
|
60
|
+
def encode
|
61
|
+
case @enc_type
|
62
|
+
when 0
|
63
|
+
[@enc_type, @admin, @assign].pack('nnN')
|
64
|
+
when 1
|
65
|
+
[@enc_type, @admin.hton, @assign].pack('na*n')
|
66
|
+
when 2
|
67
|
+
[@enc_type, @admin, @assign].pack('nNn')
|
68
|
+
end
|
69
|
+
end
|
70
|
+
|
71
|
+
def parse(s)
|
72
|
+
case s[0,2].unpack('n')[0]
|
73
|
+
when 0
|
74
|
+
@enc_type, @admin, @assign = s.unpack('nnN')
|
75
|
+
when 1
|
76
|
+
@enc_type, admin, @assign = s.unpack('na4n')
|
77
|
+
@admin = IPAddr.new_ntoh(admin)
|
78
|
+
when 2
|
79
|
+
@enc_type, @admin, @assign = s.unpack('nNn')
|
80
|
+
else
|
81
|
+
puts "Bogus rd ? #{s.unpack('H*')}"
|
82
|
+
end
|
83
|
+
end
|
84
|
+
|
85
|
+
def to_s(verbose=true)
|
86
|
+
if verbose
|
87
|
+
case @enc_type
|
88
|
+
when 0 ; format "RD=%d:%d (0x%02x 0x%04x)", @admin, @assign, @assign, @assign
|
89
|
+
when 1 ; format "RD=%s:%d (0x%04x 0x%02x)", @admin, @assign, @admin.to_i, @assign
|
90
|
+
when 2 ; format "RD=%d:%d (0x%04x 0x%02x)", @admin, @assign, @admin, @assign
|
91
|
+
end
|
92
|
+
else
|
93
|
+
case @enc_type
|
94
|
+
when 0 ; format "RD=%d:%d", @admin, @assign
|
95
|
+
when 1 ; format "RD=%s:%d", @admin, @assign
|
96
|
+
when 2 ; format "RD=%d:%d", @admin, @assign
|
97
|
+
end
|
98
|
+
end
|
99
|
+
end
|
100
|
+
|
101
|
+
def encoding_type?
|
102
|
+
@enc_type
|
103
|
+
end
|
104
|
+
|
105
|
+
end
|
106
|
+
end
|
107
|
+
load "../test/#{ File.basename($0.gsub(/.rb/,'_test.rb'))}" if __FILE__ == $0
|
data/examples/bgp
ADDED
@@ -0,0 +1,65 @@
|
|
1
|
+
#--
|
2
|
+
#
|
3
|
+
# Copyright 2008, 2009 Jean-Michel Esnault.
|
4
|
+
# All rights reserved.
|
5
|
+
# See LICENSE.txt for permissions.
|
6
|
+
#
|
7
|
+
#++
|
8
|
+
|
9
|
+
require 'bgp4r'
|
10
|
+
include BGP
|
11
|
+
|
12
|
+
# Start loggin
|
13
|
+
Log.create
|
14
|
+
Log.level=Logger::DEBUG
|
15
|
+
|
16
|
+
# Create a neighbor and set optional capabilities.
|
17
|
+
neighbor = Neighbor.new \
|
18
|
+
:version=> 4,
|
19
|
+
:my_as=> 100,
|
20
|
+
:remote_addr => '192.168.1.199',
|
21
|
+
:local_addr => '192.168.1.5',
|
22
|
+
:id=> '1.1.1.1', :holdtime=> 180
|
23
|
+
|
24
|
+
neighbor.capability :as4_byte
|
25
|
+
neighbor.capability :route_refresh
|
26
|
+
neighbor.capability :route_refresh, 128
|
27
|
+
neighbor.capability :mbgp, :ipv4, :unicast
|
28
|
+
neighbor.capability :mbgp, :ipv4, :multicast
|
29
|
+
|
30
|
+
# A call back to handle received messages we are interested in.
|
31
|
+
def self.update(msg)
|
32
|
+
case msg.class.to_s
|
33
|
+
when /Notification/
|
34
|
+
Log.warn "Going down !"
|
35
|
+
# Ignore uninterested ones.
|
36
|
+
# when /Open/
|
37
|
+
# when /Keepalive/
|
38
|
+
when /Update/
|
39
|
+
Log.info "RecvUpdate\n#{m}"
|
40
|
+
end
|
41
|
+
end
|
42
|
+
|
43
|
+
neighbor.add_observer(self)
|
44
|
+
|
45
|
+
# Start peering (will block til the session is established)
|
46
|
+
neighbor.start :auto_retry
|
47
|
+
|
48
|
+
# An BGP Update object
|
49
|
+
an_update = Update.new(
|
50
|
+
Path_attribute.new(
|
51
|
+
Origin.new(2),
|
52
|
+
Next_hop.new('192.168.1.5'),
|
53
|
+
Multi_exit_disc.new(100),
|
54
|
+
Local_pref.new(100),
|
55
|
+
As_path.new(400,300,200),
|
56
|
+
Communities.new('1311:1 311:59 2805:64')
|
57
|
+
),
|
58
|
+
Nlri.new('77.0.0.0/17', '78.0.0.0/18', '79.0.0.0/19')
|
59
|
+
)
|
60
|
+
|
61
|
+
# Ship it!
|
62
|
+
neighbor.send_message an_update
|
63
|
+
|
64
|
+
# Keep session up.
|
65
|
+
Thread.stop
|