line |
stmt |
bran |
cond |
sub |
pod |
time |
code |
1
|
|
|
|
|
|
|
#!/usr/bin/perl |
2
|
|
|
|
|
|
|
|
3
|
|
|
|
|
|
|
package Net::BGP::ASPath; |
4
|
|
|
|
|
|
|
|
5
|
7
|
|
|
7
|
|
4046
|
use strict; |
|
7
|
|
|
|
|
29
|
|
|
7
|
|
|
|
|
241
|
|
6
|
7
|
|
|
|
|
666
|
use vars qw( |
7
|
|
|
|
|
|
|
$VERSION @ISA @EXPORT @EXPORT_OK %EXPORT_TAGS @PATHTYPES |
8
|
|
|
|
|
|
|
@BGP_PATH_ATTR_COUNTS |
9
|
7
|
|
|
7
|
|
35
|
); |
|
7
|
|
|
|
|
17
|
|
10
|
|
|
|
|
|
|
|
11
|
|
|
|
|
|
|
## Inheritance and Versioning ## |
12
|
|
|
|
|
|
|
|
13
|
|
|
|
|
|
|
@ISA = qw( Exporter ); |
14
|
|
|
|
|
|
|
$VERSION = '0.17'; |
15
|
|
|
|
|
|
|
|
16
|
|
|
|
|
|
|
## Module Imports ## |
17
|
|
|
|
|
|
|
|
18
|
7
|
|
|
7
|
|
50
|
use Carp; |
|
7
|
|
|
|
|
12
|
|
|
7
|
|
|
|
|
455
|
|
19
|
7
|
|
|
7
|
|
2069
|
use IO::Socket; |
|
7
|
|
|
|
|
77565
|
|
|
7
|
|
|
|
|
44
|
|
20
|
|
|
|
|
|
|
use overload |
21
|
|
|
|
|
|
|
'<=>' => \&len_compare, |
22
|
|
|
|
|
|
|
'<' => \&len_lessthen, |
23
|
|
|
|
|
|
|
'>' => \&len_greaterthen, |
24
|
|
|
|
|
|
|
'==' => \&len_equal, |
25
|
|
|
|
|
|
|
'!=' => \&len_notequal, |
26
|
|
|
|
|
|
|
'""' => \&as_string, |
27
|
0
|
|
|
0
|
|
0
|
'+' => sub { my $x = shift->clone; $x->prepend(shift); }, |
|
0
|
|
|
|
|
0
|
|
28
|
7
|
|
|
|
|
157
|
'+=' => \&prepend, |
29
|
|
|
|
|
|
|
'eq' => \&equal, |
30
|
|
|
|
|
|
|
'ne' => \¬equal, |
31
|
|
|
|
|
|
|
'@{}' => \&asarray, |
32
|
7
|
|
|
7
|
|
4082
|
'fallback' => 1; |
|
7
|
|
|
|
|
17
|
|
33
|
|
|
|
|
|
|
|
34
|
7
|
|
|
7
|
|
4632
|
use Net::BGP::ASPath::AS; |
|
7
|
|
|
|
|
18
|
|
|
7
|
|
|
|
|
230
|
|
35
|
7
|
|
|
7
|
|
3023
|
use Net::BGP::ASPath::AS_CONFED_SEQUENCE; |
|
7
|
|
|
|
|
18
|
|
|
7
|
|
|
|
|
205
|
|
36
|
7
|
|
|
7
|
|
3002
|
use Net::BGP::ASPath::AS_CONFED_SET; |
|
7
|
|
|
|
|
18
|
|
|
7
|
|
|
|
|
202
|
|
37
|
7
|
|
|
7
|
|
44
|
use Net::BGP::ASPath::AS_SEQUENCE; |
|
7
|
|
|
|
|
13
|
|
|
7
|
|
|
|
|
128
|
|
38
|
7
|
|
|
7
|
|
30
|
use Net::BGP::ASPath::AS_SET; |
|
7
|
|
|
|
|
19
|
|
|
7
|
|
|
|
|
19925
|
|
39
|
|
|
|
|
|
|
|
40
|
|
|
|
|
|
|
## Public Class Methods ## |
41
|
|
|
|
|
|
|
|
42
|
|
|
|
|
|
|
sub new { |
43
|
111
|
|
|
111
|
1
|
6046
|
my $class = shift; |
44
|
111
|
|
|
|
|
165
|
my $value = shift; |
45
|
111
|
|
|
|
|
162
|
my $options = shift; |
46
|
|
|
|
|
|
|
|
47
|
111
|
50
|
|
|
|
233
|
if (!defined($options)) { $options = {}; } |
|
111
|
|
|
|
|
176
|
|
48
|
111
|
|
50
|
|
|
483
|
$options->{as4} ||= 0; |
49
|
|
|
|
|
|
|
|
50
|
111
|
100
|
|
|
|
255
|
return clone Net::BGP::ASPath($value) if (ref $value eq 'Net::BGP::ASPath'); |
51
|
|
|
|
|
|
|
|
52
|
|
|
|
|
|
|
my $this = { |
53
|
|
|
|
|
|
|
_as_path => [], |
54
|
|
|
|
|
|
|
_as4 => $options->{as4} |
55
|
110
|
|
|
|
|
286
|
}; |
56
|
|
|
|
|
|
|
|
57
|
110
|
|
|
|
|
221
|
bless($this, $class); |
58
|
|
|
|
|
|
|
|
59
|
110
|
100
|
|
|
|
251
|
if (defined($value)) { |
60
|
57
|
100
|
|
|
|
104
|
if (ref $value) { |
61
|
1
|
50
|
|
|
|
5
|
if (ref $value eq 'ARRAY') { |
62
|
1
|
|
|
|
|
5
|
$this->_setfromstring(join ' ', @$value); |
63
|
|
|
|
|
|
|
} else { |
64
|
0
|
|
|
|
|
0
|
croak "Unknown ASPath constructor argument type: " . ref $value |
65
|
|
|
|
|
|
|
} |
66
|
|
|
|
|
|
|
} else { |
67
|
|
|
|
|
|
|
# Scalar/string |
68
|
56
|
|
|
|
|
99
|
$this->_setfromstring($value); |
69
|
|
|
|
|
|
|
} |
70
|
|
|
|
|
|
|
} |
71
|
|
|
|
|
|
|
|
72
|
110
|
|
|
|
|
410
|
return ($this); |
73
|
|
|
|
|
|
|
} |
74
|
|
|
|
|
|
|
|
75
|
|
|
|
|
|
|
sub _setfromstring { |
76
|
203
|
|
|
203
|
|
383
|
my ($this, $value) = @_; |
77
|
203
|
|
|
|
|
797
|
$this->{_as_path} = []; |
78
|
|
|
|
|
|
|
|
79
|
|
|
|
|
|
|
# Normalize string |
80
|
203
|
|
|
|
|
1896
|
$value =~ s/\s+/ /g; |
81
|
203
|
|
|
|
|
453
|
$value =~ s/^\s//; |
82
|
203
|
|
|
|
|
342
|
$value =~ s/\s$//; |
83
|
203
|
|
|
|
|
565
|
$value =~ s/\s?,\s?/,/g; |
84
|
|
|
|
|
|
|
|
85
|
203
|
|
|
|
|
451
|
while ($value ne '') { |
86
|
|
|
|
|
|
|
|
87
|
|
|
|
|
|
|
# Note that the AS_SEQUENCE can't be > 255 path elements. The entire len |
88
|
|
|
|
|
|
|
# of the AS_PATH can be > 255 octets, true, but not an individual AS_SET |
89
|
|
|
|
|
|
|
# segment. |
90
|
|
|
|
|
|
|
# TODO: We should do the same for other path types and also take care to |
91
|
|
|
|
|
|
|
# not allow ourselves to overflow the 65535 byte length limit if this is |
92
|
|
|
|
|
|
|
# converted back to a usable path. |
93
|
|
|
|
|
|
|
# TODO: It would be better to put the short AS PATH at end of the path, |
94
|
|
|
|
|
|
|
# not the beginning of the path, so that it is easier for other routers |
95
|
|
|
|
|
|
|
# to process. |
96
|
355
|
50
|
100
|
|
|
3171
|
confess 'Invalid path segments for path object: >>' . $value . '<<' |
|
|
|
66
|
|
|
|
|
97
|
|
|
|
|
|
|
unless ( |
98
|
|
|
|
|
|
|
($value =~ /^(\([^\)]*\))( (.*))?$/) || # AS_CONFED_* segment |
99
|
|
|
|
|
|
|
($value =~ /^(\{[^\}]*\})( (.*))?$/) || # AS_SET segment |
100
|
|
|
|
|
|
|
($value =~ /^(([0-9]+\s*){1,255})(.*)?$/) |
101
|
|
|
|
|
|
|
); # AS_SEQUENCE seqment |
102
|
|
|
|
|
|
|
|
103
|
355
|
|
100
|
|
|
1194
|
$value = $3 || ''; |
104
|
355
|
|
|
|
|
849
|
my $segment = Net::BGP::ASPath::AS->new($1); |
105
|
|
|
|
|
|
|
|
106
|
355
|
|
|
|
|
486
|
push(@{ $this->{_as_path} }, $segment); |
|
355
|
|
|
|
|
1006
|
|
107
|
|
|
|
|
|
|
} |
108
|
203
|
|
|
|
|
496
|
return $this; |
109
|
|
|
|
|
|
|
} |
110
|
|
|
|
|
|
|
|
111
|
|
|
|
|
|
|
sub clone { |
112
|
162
|
|
|
162
|
1
|
554
|
my $proto = shift; |
113
|
162
|
|
66
|
|
|
404
|
my $class = ref $proto || $proto; |
114
|
162
|
100
|
|
|
|
317
|
$proto = shift unless ref $proto; |
115
|
|
|
|
|
|
|
|
116
|
162
|
|
|
|
|
359
|
my $clone = { _as_path => [] }; |
117
|
|
|
|
|
|
|
|
118
|
162
|
|
|
|
|
232
|
foreach my $p (@{ $proto->{_as_path} }) { |
|
162
|
|
|
|
|
353
|
|
119
|
253
|
|
|
|
|
345
|
push(@{ $clone->{_as_path} }, $p->clone); |
|
253
|
|
|
|
|
650
|
|
120
|
|
|
|
|
|
|
} |
121
|
|
|
|
|
|
|
|
122
|
162
|
|
|
|
|
384
|
return (bless($clone, $class)); |
123
|
|
|
|
|
|
|
} |
124
|
|
|
|
|
|
|
|
125
|
|
|
|
|
|
|
# This takes two buffers. The first buffer is the standard AS_PATH buffer and |
126
|
|
|
|
|
|
|
# should always be defined. |
127
|
|
|
|
|
|
|
# |
128
|
|
|
|
|
|
|
# The second buffer is the AS4_PATH buffer. |
129
|
|
|
|
|
|
|
# |
130
|
|
|
|
|
|
|
# The third parameter is true if AS4 is natively supported, false if AS4 is not |
131
|
|
|
|
|
|
|
sub _new_from_msg { |
132
|
31
|
|
|
31
|
|
85
|
my ($class, $buffer, $buffer2, $options) = @_; |
133
|
31
|
|
|
|
|
78
|
my $this = $class->new; |
134
|
|
|
|
|
|
|
|
135
|
31
|
100
|
|
|
|
84
|
if (!defined($options)) { $options = {}; } |
|
14
|
|
|
|
|
23
|
|
136
|
31
|
|
100
|
|
|
120
|
$options->{as4} ||= 0; |
137
|
|
|
|
|
|
|
|
138
|
31
|
100
|
|
|
|
76
|
my $size = $options->{as4} ? 4 : 2; |
139
|
|
|
|
|
|
|
|
140
|
31
|
100
|
|
|
|
66
|
if (!defined($buffer2)) { $buffer2 = ''; } |
|
13
|
|
|
|
|
22
|
|
141
|
|
|
|
|
|
|
|
142
|
31
|
|
|
|
|
45
|
my $segment; |
143
|
31
|
|
|
|
|
73
|
while ($buffer ne '') { |
144
|
|
|
|
|
|
|
|
145
|
39
|
|
|
|
|
125
|
($segment, $buffer) |
146
|
|
|
|
|
|
|
= Net::BGP::ASPath::AS->_new_from_msg($buffer, $options); |
147
|
|
|
|
|
|
|
|
148
|
|
|
|
|
|
|
# Error handling |
149
|
39
|
50
|
|
|
|
111
|
if ( !(defined $segment) ) { |
150
|
0
|
|
|
|
|
0
|
return undef; |
151
|
|
|
|
|
|
|
} |
152
|
39
|
50
|
66
|
|
|
123
|
if ( length($buffer) && ( ( length($buffer) - 2 ) % $size) ) { |
153
|
0
|
|
|
|
|
0
|
return undef; |
154
|
|
|
|
|
|
|
} |
155
|
|
|
|
|
|
|
|
156
|
39
|
|
|
|
|
58
|
push(@{ $this->{_as_path} }, $segment); |
|
39
|
|
|
|
|
210
|
|
157
|
|
|
|
|
|
|
} |
158
|
|
|
|
|
|
|
|
159
|
|
|
|
|
|
|
# We ignore AS4_PATHs on native AS4 speaker sessions |
160
|
|
|
|
|
|
|
# So we stop here. |
161
|
31
|
100
|
|
|
|
80
|
if ($options->{as4}) { |
162
|
4
|
|
|
|
|
13
|
return $this; |
163
|
|
|
|
|
|
|
} |
164
|
|
|
|
|
|
|
|
165
|
27
|
|
|
|
|
45
|
my @as4_path; |
166
|
|
|
|
|
|
|
|
167
|
27
|
|
|
|
|
57
|
while ($buffer2 ne '') { |
168
|
|
|
|
|
|
|
|
169
|
5
|
|
|
|
|
19
|
($segment, $buffer2) |
170
|
|
|
|
|
|
|
= Net::BGP::ASPath::AS->_new_from_msg( |
171
|
|
|
|
|
|
|
$buffer2, |
172
|
|
|
|
|
|
|
{ as4 => 1 } |
173
|
|
|
|
|
|
|
); |
174
|
|
|
|
|
|
|
|
175
|
|
|
|
|
|
|
# TODO: Should make sure type is only AS_SEQUENCE or AS_SET! |
176
|
|
|
|
|
|
|
|
177
|
5
|
50
|
|
|
|
18
|
if ( !(defined $segment) ) { |
178
|
0
|
|
|
|
|
0
|
return undef; |
179
|
|
|
|
|
|
|
} |
180
|
5
|
50
|
66
|
|
|
18
|
if ( length($buffer2) && ( ( length($buffer2) - 2 ) % 4) ) { |
181
|
0
|
|
|
|
|
0
|
return undef; |
182
|
|
|
|
|
|
|
} |
183
|
|
|
|
|
|
|
|
184
|
5
|
|
|
|
|
11
|
push (@as4_path, $segment); |
185
|
|
|
|
|
|
|
} |
186
|
|
|
|
|
|
|
|
187
|
27
|
|
|
|
|
70
|
my $as_count = $this->_length_helper( $this->{_as_path} ); |
188
|
27
|
|
|
|
|
60
|
my $as4_count = $this->_length_helper( \@as4_path ); |
189
|
|
|
|
|
|
|
|
190
|
27
|
50
|
|
|
|
57
|
if ($as_count < $as4_count) { |
191
|
|
|
|
|
|
|
# We ignroe the AS4 stuff per RFC4893 in this case |
192
|
0
|
|
|
|
|
0
|
return $this; |
193
|
|
|
|
|
|
|
} |
194
|
|
|
|
|
|
|
|
195
|
27
|
|
|
|
|
39
|
my $remove = $as4_count; |
196
|
|
|
|
|
|
|
|
197
|
27
|
|
|
|
|
66
|
while ($remove > 0) { |
198
|
5
|
|
|
|
|
8
|
my $ele = pop @{ $this->{_as_path} }; |
|
5
|
|
|
|
|
10
|
|
199
|
5
|
100
|
|
|
|
23
|
if ($ele->length <= $remove) { |
200
|
2
|
|
|
|
|
6
|
$remove -= $ele->length; |
201
|
|
|
|
|
|
|
} else { |
202
|
3
|
|
|
|
|
5
|
push @{ $this->{_as_path} }, $ele->remove_tail($remove); |
|
3
|
|
|
|
|
8
|
|
203
|
3
|
|
|
|
|
10
|
$remove = 0; |
204
|
|
|
|
|
|
|
} |
205
|
|
|
|
|
|
|
} |
206
|
|
|
|
|
|
|
|
207
|
27
|
|
|
|
|
43
|
push @{ $this->{_as_path} }, @as4_path; |
|
27
|
|
|
|
|
53
|
|
208
|
|
|
|
|
|
|
|
209
|
27
|
|
|
|
|
80
|
return $this; |
210
|
|
|
|
|
|
|
} |
211
|
|
|
|
|
|
|
|
212
|
|
|
|
|
|
|
## Public Object Methods ## |
213
|
|
|
|
|
|
|
|
214
|
|
|
|
|
|
|
# This encodes the AS_PATH and AS4_PATH elements (both are returned) |
215
|
|
|
|
|
|
|
# |
216
|
|
|
|
|
|
|
# If the AS4_PATH element is undef, that indicates an AS4_PATH is not |
217
|
|
|
|
|
|
|
# needed - either we're encoding in 32-bit clear format, or all |
218
|
|
|
|
|
|
|
# elements have only 16 bit ASNs. |
219
|
|
|
|
|
|
|
sub _encode { |
220
|
25
|
|
|
25
|
|
52
|
my ($this, $args) = @_; |
221
|
|
|
|
|
|
|
|
222
|
25
|
100
|
|
|
|
61
|
if (!defined($args)) { $args = {}; } |
|
14
|
|
|
|
|
26
|
|
223
|
25
|
|
100
|
|
|
125
|
$args->{as4} ||= 0; |
224
|
|
|
|
|
|
|
|
225
|
25
|
|
|
|
|
37
|
my $has_as4; |
226
|
25
|
|
|
|
|
40
|
my $msg = ''; |
227
|
25
|
|
|
|
|
38
|
foreach my $segment (@{ $this->{_as_path} }) { |
|
25
|
|
|
|
|
72
|
|
228
|
33
|
|
|
|
|
136
|
$msg .= $segment->_encode($args); |
229
|
|
|
|
|
|
|
|
230
|
33
|
100
|
|
|
|
106
|
if ($segment->_has_as4()) { $has_as4 = 1; } |
|
6
|
|
|
|
|
14
|
|
231
|
|
|
|
|
|
|
} |
232
|
|
|
|
|
|
|
|
233
|
25
|
|
|
|
|
44
|
my $as4; |
234
|
25
|
100
|
100
|
|
|
94
|
if ( ( !($args->{as4} ) ) && ($has_as4) ) { |
235
|
1
|
|
|
|
|
4
|
$as4 = ''; |
236
|
|
|
|
|
|
|
|
237
|
1
|
|
|
|
|
2
|
foreach my $segment (@{ $this->{_as_path} }) { |
|
1
|
|
|
|
|
3
|
|
238
|
2
|
50
|
|
|
|
9
|
if ( !(ref($segment) =~ /_CONFED_/) ) { |
239
|
2
|
|
|
|
|
6
|
$as4 .= $segment->_encode( { as4 => 1 } ); |
240
|
|
|
|
|
|
|
} |
241
|
|
|
|
|
|
|
} |
242
|
|
|
|
|
|
|
} |
243
|
|
|
|
|
|
|
|
244
|
25
|
|
|
|
|
100
|
return ($msg, $as4); |
245
|
|
|
|
|
|
|
} |
246
|
|
|
|
|
|
|
|
247
|
|
|
|
|
|
|
sub prepend { |
248
|
46
|
|
|
46
|
1
|
165
|
my $this = shift; |
249
|
46
|
|
|
|
|
69
|
my $value = shift; |
250
|
46
|
100
|
|
|
|
138
|
return $this->prepend_confed($value) if ($value =~ /^\(/); |
251
|
31
|
|
|
|
|
75
|
$this->strip; |
252
|
|
|
|
|
|
|
|
253
|
31
|
|
|
|
|
62
|
my @list = ($value); |
254
|
31
|
100
|
|
|
|
68
|
@list = @{$value} if (ref $value eq 'ARRAY'); |
|
1
|
|
|
|
|
4
|
|
255
|
31
|
100
|
|
|
|
66
|
@list = split(' ', $list[0]) if $list[0] =~ / /; |
256
|
|
|
|
|
|
|
|
257
|
|
|
|
|
|
|
# Ugly - slow - but simple! Should be improved later! |
258
|
31
|
|
|
|
|
113
|
return $this->_setfromstring(join(' ', @list) . ' ' . $this)->cleanup; |
259
|
|
|
|
|
|
|
} |
260
|
|
|
|
|
|
|
|
261
|
|
|
|
|
|
|
sub prepend_confed { |
262
|
33
|
|
|
33
|
1
|
116
|
my $this = shift; |
263
|
|
|
|
|
|
|
|
264
|
33
|
|
|
|
|
50
|
my $value = shift; |
265
|
33
|
100
|
|
|
|
136
|
$value =~ s/^\((.*)\)$/$1/ unless ref $value; |
266
|
|
|
|
|
|
|
|
267
|
33
|
|
|
|
|
81
|
my @list = ($value); |
268
|
33
|
100
|
|
|
|
67
|
@list = @{$value} if (ref $value eq 'ARRAY'); |
|
1
|
|
|
|
|
3
|
|
269
|
33
|
100
|
|
|
|
83
|
@list = split(' ', $list[0]) if $list[0] =~ / /; |
270
|
|
|
|
|
|
|
|
271
|
|
|
|
|
|
|
# Ugly - slow - but simple! Should be improved later! |
272
|
33
|
|
|
|
|
116
|
return $this->_setfromstring('(' . join(' ', @list) . ') ' . $this) |
273
|
|
|
|
|
|
|
->cleanup; |
274
|
|
|
|
|
|
|
} |
275
|
|
|
|
|
|
|
|
276
|
|
|
|
|
|
|
sub cleanup { |
277
|
82
|
|
|
82
|
1
|
136
|
my $this = shift; |
278
|
|
|
|
|
|
|
|
279
|
|
|
|
|
|
|
# Ugly - slow - but simple! Should be improved later! |
280
|
82
|
|
|
|
|
162
|
my $str = $this->as_string; |
281
|
82
|
|
|
|
|
226
|
$str =~ s/\{\}//g; |
282
|
82
|
|
|
|
|
133
|
$str =~ s/\(\)//g; |
283
|
82
|
|
|
|
|
211
|
$str =~ s/(\d)\) +\((\d)/$1 $2/g; |
284
|
82
|
|
|
|
|
169
|
return $this->_setfromstring($str); |
285
|
|
|
|
|
|
|
} |
286
|
|
|
|
|
|
|
|
287
|
|
|
|
|
|
|
sub _confed { |
288
|
12
|
|
|
12
|
|
22
|
my $this = shift->clone; |
289
|
12
|
|
|
|
|
29
|
@{ $this->{_as_path} } = |
290
|
12
|
|
|
|
|
17
|
grep { (ref $_) =~ /_CONFED_/ } @{ $this->{_as_path} }; |
|
25
|
|
|
|
|
64
|
|
|
12
|
|
|
|
|
21
|
|
291
|
12
|
|
|
|
|
26
|
return $this; |
292
|
|
|
|
|
|
|
} |
293
|
|
|
|
|
|
|
|
294
|
|
|
|
|
|
|
sub strip { |
295
|
71
|
|
|
71
|
1
|
128
|
my $this = shift; |
296
|
71
|
|
|
|
|
174
|
@{ $this->{_as_path} } = |
297
|
71
|
|
|
|
|
89
|
grep { (ref $_) !~ /_CONFED_/ } @{ $this->{_as_path} }; |
|
117
|
|
|
|
|
336
|
|
|
71
|
|
|
|
|
151
|
|
298
|
71
|
|
|
|
|
123
|
return $this; |
299
|
|
|
|
|
|
|
} |
300
|
|
|
|
|
|
|
|
301
|
|
|
|
|
|
|
sub striped { |
302
|
26
|
|
|
26
|
1
|
53
|
return shift->clone->strip(@_); |
303
|
|
|
|
|
|
|
} |
304
|
|
|
|
|
|
|
|
305
|
|
|
|
|
|
|
sub aggregate { |
306
|
4
|
|
|
4
|
1
|
358
|
my @olist = @_; |
307
|
4
|
100
|
|
|
|
11
|
shift(@olist) unless ref $olist[0]; |
308
|
|
|
|
|
|
|
|
309
|
|
|
|
|
|
|
# Sets |
310
|
4
|
|
|
|
|
13
|
my $cset = Net::BGP::ASPath::AS_CONFED_SET->new; |
311
|
4
|
|
|
|
|
10
|
my $nset = Net::BGP::ASPath::AS_SET->new; |
312
|
|
|
|
|
|
|
|
313
|
|
|
|
|
|
|
# Lists of confed / normal part of paths |
314
|
4
|
|
|
|
|
9
|
my @clist = map { $_->_confed } @olist; |
|
12
|
|
|
|
|
19
|
|
315
|
4
|
|
|
|
|
9
|
my @nlist = map { $_->striped } @olist; |
|
12
|
|
|
|
|
21
|
|
316
|
|
|
|
|
|
|
|
317
|
4
|
|
|
|
|
9
|
my $res = ''; |
318
|
4
|
|
|
|
|
10
|
foreach my $pair ([ \@clist, $cset ], [ \@nlist, $nset ]) { |
319
|
8
|
|
|
|
|
12
|
my ($list, $set) = @{$pair}; |
|
8
|
|
|
|
|
80
|
|
320
|
|
|
|
|
|
|
|
321
|
|
|
|
|
|
|
# Find common head |
322
|
8
|
|
|
|
|
22
|
my $head = $list->[0]->_head; |
323
|
8
|
|
|
|
|
17
|
foreach my $obj (@{$list}[ 1 .. @{$list} - 1 ]) { |
|
8
|
|
|
|
|
17
|
|
|
8
|
|
|
|
|
15
|
|
324
|
16
|
|
|
|
|
30
|
my $s = $obj->_head; |
325
|
16
|
|
|
|
|
27
|
$head = _longest_common_head($head, $s); |
326
|
|
|
|
|
|
|
} |
327
|
|
|
|
|
|
|
|
328
|
|
|
|
|
|
|
# Find tail set |
329
|
8
|
|
|
|
|
16
|
foreach my $obj (@{$list}) { |
|
8
|
|
|
|
|
13
|
|
330
|
24
|
|
|
|
|
46
|
my $tail = $obj->_tail($head); |
331
|
24
|
100
|
|
|
|
70
|
$tail = '(' . $tail if $tail =~ /^[^\(]*\).*$/; # Fix tail |
332
|
24
|
|
|
|
|
55
|
$obj = Net::BGP::ASPath->new($tail); |
333
|
24
|
|
|
|
|
68
|
$set->merge($obj); |
334
|
|
|
|
|
|
|
} |
335
|
8
|
100
|
|
|
|
25
|
$head .= ')' if $head =~ /^\([^\)]+$/; # Fix head |
336
|
8
|
|
|
|
|
26
|
$res .= "$head $set "; |
337
|
|
|
|
|
|
|
} |
338
|
|
|
|
|
|
|
|
339
|
|
|
|
|
|
|
# Construct result |
340
|
4
|
|
|
|
|
13
|
return Net::BGP::ASPath->new($res)->cleanup; |
341
|
|
|
|
|
|
|
} |
342
|
|
|
|
|
|
|
|
343
|
|
|
|
|
|
|
## Utility functions (not methods!) ## |
344
|
|
|
|
|
|
|
sub _longest_common_head { |
345
|
16
|
|
|
16
|
|
32
|
my ($s1, $s2) = @_; |
346
|
16
|
|
|
|
|
52
|
my $pos = 0; |
347
|
16
|
|
|
|
|
31
|
$s1 .= ' '; |
348
|
16
|
|
|
|
|
36
|
$s2 .= ' '; |
349
|
16
|
|
|
|
|
44
|
for my $i (0 .. length($s1) - 1) { |
350
|
80
|
100
|
|
|
|
150
|
last unless substr($s1, $i, 1) eq substr($s2, $i, 1); |
351
|
76
|
100
|
|
|
|
144
|
$pos = $i if substr($s1, $i, 1) eq ' '; |
352
|
|
|
|
|
|
|
} |
353
|
16
|
|
|
|
|
56
|
return substr($s1, 0, $pos); |
354
|
|
|
|
|
|
|
} |
355
|
|
|
|
|
|
|
|
356
|
|
|
|
|
|
|
sub _head |
357
|
|
|
|
|
|
|
|
358
|
|
|
|
|
|
|
# Head means the leading non-set part of the path |
359
|
|
|
|
|
|
|
{ |
360
|
24
|
|
|
24
|
|
43
|
my $this = shift->clone; |
361
|
24
|
|
|
|
|
34
|
my $ok = 1; |
362
|
|
|
|
|
|
|
$this->{_as_path} = |
363
|
25
|
100
|
66
|
|
|
121
|
[ grep { $ok &&= (ref $_) =~ /_SEQUENCE$/; $_ = undef unless $ok; } |
|
25
|
|
|
|
|
84
|
|
364
|
24
|
|
|
|
|
28
|
@{ $this->{_as_path} } ]; |
|
24
|
|
|
|
|
47
|
|
365
|
24
|
|
|
|
|
46
|
return $this; |
366
|
|
|
|
|
|
|
} |
367
|
|
|
|
|
|
|
|
368
|
|
|
|
|
|
|
sub _tail |
369
|
|
|
|
|
|
|
|
370
|
|
|
|
|
|
|
# Tail means everything after the "head" given as argument. |
371
|
|
|
|
|
|
|
# The tail is returned as a string. Returns undef if "head" is invalid. |
372
|
|
|
|
|
|
|
{ |
373
|
24
|
|
|
24
|
|
41
|
my $thisstr = shift() . " "; |
374
|
24
|
|
|
|
|
45
|
my $head = shift() . " "; |
375
|
24
|
|
|
|
|
58
|
$head =~ s/\(/\\(/g; |
376
|
24
|
|
|
|
|
34
|
$head =~ s/\)/\\)/g; |
377
|
24
|
50
|
|
|
|
199
|
return undef unless $thisstr =~ s/^$head//; |
378
|
24
|
|
|
|
|
63
|
$thisstr =~ s/ $//; |
379
|
24
|
|
|
|
|
49
|
return $thisstr; |
380
|
|
|
|
|
|
|
} |
381
|
|
|
|
|
|
|
|
382
|
|
|
|
|
|
|
# For compatability |
383
|
|
|
|
|
|
|
sub asstring { |
384
|
7
|
|
|
7
|
0
|
22
|
my $this = shift; |
385
|
7
|
|
|
|
|
18
|
return $this->as_string(@_); |
386
|
|
|
|
|
|
|
} |
387
|
|
|
|
|
|
|
|
388
|
|
|
|
|
|
|
sub as_string { |
389
|
517
|
|
|
517
|
1
|
1039
|
my $this = shift; |
390
|
|
|
|
|
|
|
|
391
|
517
|
|
|
|
|
974
|
return $this->_as_string_helper($this->{_as_path}); |
392
|
|
|
|
|
|
|
} |
393
|
|
|
|
|
|
|
|
394
|
|
|
|
|
|
|
sub _as_string_helper { |
395
|
517
|
|
|
517
|
|
798
|
my ($this, $path) = @_; |
396
|
|
|
|
|
|
|
|
397
|
517
|
|
|
|
|
665
|
return join(' ', map { $_->as_string; } @{ $path }); |
|
818
|
|
|
|
|
1661
|
|
|
517
|
|
|
|
|
921
|
|
398
|
|
|
|
|
|
|
} |
399
|
|
|
|
|
|
|
|
400
|
|
|
|
|
|
|
|
401
|
|
|
|
|
|
|
sub asarray { |
402
|
26
|
|
|
26
|
0
|
331
|
my $this = shift; |
403
|
26
|
|
|
|
|
33
|
my @res; |
404
|
26
|
|
|
|
|
34
|
foreach my $s (@{ $this->{_as_path} }) { |
|
26
|
|
|
|
|
48
|
|
405
|
26
|
|
|
|
|
33
|
push(@res, @{ $s->asarray }); |
|
26
|
|
|
|
|
53
|
|
406
|
|
|
|
|
|
|
} |
407
|
26
|
|
|
|
|
73
|
return \@res; |
408
|
|
|
|
|
|
|
} |
409
|
|
|
|
|
|
|
|
410
|
|
|
|
|
|
|
sub len_equal { |
411
|
1
|
|
|
1
|
0
|
4
|
my ($this, $other) = @_; |
412
|
1
|
50
|
|
|
|
4
|
return 0 unless defined($other); |
413
|
1
|
50
|
|
|
|
4
|
return ($this->length == $other->length) ? 1 : 0; |
414
|
|
|
|
|
|
|
} |
415
|
|
|
|
|
|
|
|
416
|
|
|
|
|
|
|
sub len_notequal { |
417
|
0
|
|
|
0
|
0
|
0
|
my ($this, $other) = @_; |
418
|
0
|
0
|
|
|
|
0
|
return 1 unless defined($other); |
419
|
0
|
0
|
|
|
|
0
|
return ($this->length != $other->length) ? 1 : 0; |
420
|
|
|
|
|
|
|
} |
421
|
|
|
|
|
|
|
|
422
|
|
|
|
|
|
|
sub len_lessthen { |
423
|
1
|
|
|
1
|
0
|
5
|
my ($this, $other) = @_; |
424
|
1
|
50
|
|
|
|
5
|
return 0 unless defined($other); |
425
|
1
|
50
|
|
|
|
3
|
return ($this->length < $other->length) ? 1 : 0; |
426
|
|
|
|
|
|
|
} |
427
|
|
|
|
|
|
|
|
428
|
|
|
|
|
|
|
sub len_greaterthen { |
429
|
1
|
|
|
1
|
0
|
407
|
my ($this, $other) = @_; |
430
|
1
|
50
|
|
|
|
5
|
return 1 unless defined($other); |
431
|
1
|
50
|
|
|
|
4
|
return ($this->length > $other->length) ? 1 : 0; |
432
|
|
|
|
|
|
|
} |
433
|
|
|
|
|
|
|
|
434
|
|
|
|
|
|
|
sub len_compare { |
435
|
10
|
|
|
10
|
0
|
32
|
my ($this, $other) = @_; |
436
|
10
|
50
|
|
|
|
17
|
return 1 unless defined($other); |
437
|
10
|
|
|
|
|
22
|
return $this->length <=> $other->length; |
438
|
|
|
|
|
|
|
} |
439
|
|
|
|
|
|
|
|
440
|
|
|
|
|
|
|
sub equal { |
441
|
21
|
|
|
21
|
0
|
406
|
my ($this, $other) = @_; |
442
|
21
|
50
|
|
|
|
45
|
return 0 unless defined($other); |
443
|
21
|
50
|
|
|
|
48
|
confess "Cannot compare " . (ref $this) . " with a " . (ref $other) . "\n" |
444
|
|
|
|
|
|
|
unless ref $other eq ref $this; |
445
|
21
|
100
|
|
|
|
47
|
return $this->as_string eq $other->as_string ? 1 : 0; |
446
|
|
|
|
|
|
|
} |
447
|
|
|
|
|
|
|
|
448
|
|
|
|
|
|
|
sub notequal { |
449
|
1
|
|
|
1
|
0
|
4
|
my ($this, $other) = @_; |
450
|
1
|
50
|
|
|
|
4
|
return 1 unless defined($other); |
451
|
1
|
50
|
|
|
|
3
|
return $this->as_string ne $other->as_string ? 1 : 0; |
452
|
|
|
|
|
|
|
} |
453
|
|
|
|
|
|
|
|
454
|
|
|
|
|
|
|
sub length { |
455
|
47
|
|
|
47
|
1
|
164
|
my ($this) = @_; |
456
|
|
|
|
|
|
|
|
457
|
47
|
|
|
|
|
96
|
return $this->_length_helper($this->{_as_path}); |
458
|
|
|
|
|
|
|
} |
459
|
|
|
|
|
|
|
|
460
|
|
|
|
|
|
|
sub _length_helper { |
461
|
101
|
|
|
101
|
|
157
|
my ($this, $path) = @_; |
462
|
|
|
|
|
|
|
|
463
|
101
|
|
|
|
|
132
|
my $res = 0; |
464
|
101
|
|
|
|
|
133
|
foreach my $p (@{ $path }) { |
|
101
|
|
|
|
|
179
|
|
465
|
140
|
|
|
|
|
301
|
$res += $p->length; |
466
|
|
|
|
|
|
|
} |
467
|
101
|
|
|
|
|
243
|
return $res; |
468
|
|
|
|
|
|
|
} |
469
|
|
|
|
|
|
|
|
470
|
|
|
|
|
|
|
## POD ## |
471
|
|
|
|
|
|
|
|
472
|
|
|
|
|
|
|
=pod |
473
|
|
|
|
|
|
|
|
474
|
|
|
|
|
|
|
=head1 NAME |
475
|
|
|
|
|
|
|
|
476
|
|
|
|
|
|
|
Net::BGP::ASPath - Class encapsulating BGP-4 AS Path information |
477
|
|
|
|
|
|
|
|
478
|
|
|
|
|
|
|
=head1 SYNOPSIS |
479
|
|
|
|
|
|
|
|
480
|
|
|
|
|
|
|
use Net::BGP::ASPath; |
481
|
|
|
|
|
|
|
|
482
|
|
|
|
|
|
|
# Constructor |
483
|
|
|
|
|
|
|
$aspath = Net::BGP::ASPath->new(undef, { as4 => 1 }); |
484
|
|
|
|
|
|
|
$aspath2 = Net::BGP::ASPath->new([65001,65002]); |
485
|
|
|
|
|
|
|
$aspath3 = Net::BGP::ASPath->new("(65001 65002) 65010"); |
486
|
|
|
|
|
|
|
$aspath4 = Net::BGP::ASPath->new("65001 {65011,65010}"); |
487
|
|
|
|
|
|
|
|
488
|
|
|
|
|
|
|
# Object Copy |
489
|
|
|
|
|
|
|
$clone = $aspath->clone(); |
490
|
|
|
|
|
|
|
|
491
|
|
|
|
|
|
|
# Modifiers; |
492
|
|
|
|
|
|
|
$aspath = $aspath->prepend(64999); |
493
|
|
|
|
|
|
|
$aspath = $aspath->prepend("64999 65998"); |
494
|
|
|
|
|
|
|
$aspath = $aspath->prepend([64999,65998]); |
495
|
|
|
|
|
|
|
|
496
|
|
|
|
|
|
|
$aspath = $aspath->prepend("(64999 65998)"); |
497
|
|
|
|
|
|
|
$aspath = $aspath->prepend_confed("64999 65998"); |
498
|
|
|
|
|
|
|
|
499
|
|
|
|
|
|
|
$aspath += "65001 65002"; # Same as $aspath->prepend("65001 65002") |
500
|
|
|
|
|
|
|
|
501
|
|
|
|
|
|
|
$aspath5 = $aspath->striped; # New object |
502
|
|
|
|
|
|
|
$aspath = $aspath->strip; # Same modified |
503
|
|
|
|
|
|
|
|
504
|
|
|
|
|
|
|
$aspath = $aspath->cleanup # Same modified |
505
|
|
|
|
|
|
|
|
506
|
|
|
|
|
|
|
# Aggregation |
507
|
|
|
|
|
|
|
$aspath = $aspath1->aggregate($aspath2,$aspath3); |
508
|
|
|
|
|
|
|
$aspath = Net::BGP::ASPath->aggregate($aspath1,$aspath2,$aspath3); |
509
|
|
|
|
|
|
|
|
510
|
|
|
|
|
|
|
|
511
|
|
|
|
|
|
|
# Accessor Methods |
512
|
|
|
|
|
|
|
$length = $aspath->length; |
513
|
|
|
|
|
|
|
$string = $aspath->as_string; |
514
|
|
|
|
|
|
|
$array_ref = $aspath->asarray |
515
|
|
|
|
|
|
|
|
516
|
|
|
|
|
|
|
# In context |
517
|
|
|
|
|
|
|
$string = "The AS path is: " . $aspath; |
518
|
|
|
|
|
|
|
$firstas = $aspath[0]; |
519
|
|
|
|
|
|
|
|
520
|
|
|
|
|
|
|
# Length comparisons |
521
|
|
|
|
|
|
|
if ($aspath < $aspath2) { ... }; |
522
|
|
|
|
|
|
|
if ($aspath > $aspath2) { ... }; |
523
|
|
|
|
|
|
|
if ($aspath == $aspath2) { ... }; |
524
|
|
|
|
|
|
|
if ($aspath != $aspath2) { ... }; |
525
|
|
|
|
|
|
|
@sorted = sort { $a <=> $b } ($aspath, $aspath2, $aspath3, $aspath4); |
526
|
|
|
|
|
|
|
|
527
|
|
|
|
|
|
|
# Path comparisons |
528
|
|
|
|
|
|
|
if ($aspath eq $aspath2) { ... }; |
529
|
|
|
|
|
|
|
if ($aspath ne $aspath2) { ... }; |
530
|
|
|
|
|
|
|
|
531
|
|
|
|
|
|
|
=head1 DESCRIPTION |
532
|
|
|
|
|
|
|
|
533
|
|
|
|
|
|
|
This module encapsulates the data contained in a BGP-4 AS_PATH, inluding |
534
|
|
|
|
|
|
|
confederation extentions. |
535
|
|
|
|
|
|
|
|
536
|
|
|
|
|
|
|
=head1 CONSTRUCTOR |
537
|
|
|
|
|
|
|
|
538
|
|
|
|
|
|
|
=over 4 |
539
|
|
|
|
|
|
|
|
540
|
|
|
|
|
|
|
=item new() - create a new Net::BGP::ASPath object |
541
|
|
|
|
|
|
|
|
542
|
|
|
|
|
|
|
$aspath = Net::BGP::ASPath->new( PATHDATA, OPTIONS ); |
543
|
|
|
|
|
|
|
|
544
|
|
|
|
|
|
|
This is the constructor for Net::BGP::ASPath objects. It returns a |
545
|
|
|
|
|
|
|
reference to the newly created object. The first parameter may be either: |
546
|
|
|
|
|
|
|
|
547
|
|
|
|
|
|
|
=over 4 |
548
|
|
|
|
|
|
|
|
549
|
|
|
|
|
|
|
=item ARRAY_REF |
550
|
|
|
|
|
|
|
|
551
|
|
|
|
|
|
|
An array ref containing AS numbers inteperted as an AS_PATH_SEQUENCE. |
552
|
|
|
|
|
|
|
|
553
|
|
|
|
|
|
|
=item SCALAR |
554
|
|
|
|
|
|
|
|
555
|
|
|
|
|
|
|
A string with AS numbers seperated by spaces (AS_PATH_SEQUANCE). |
556
|
|
|
|
|
|
|
AS_PATH_SETs is written using "{}" with "," to seperate AS numbers. |
557
|
|
|
|
|
|
|
AS_PATH_CONFED_* is writen equally, but encapsulated in "()". |
558
|
|
|
|
|
|
|
|
559
|
|
|
|
|
|
|
=item Net::BGP::ASPath |
560
|
|
|
|
|
|
|
|
561
|
|
|
|
|
|
|
Another ASPath object, in which case a clone is constructed. |
562
|
|
|
|
|
|
|
|
563
|
|
|
|
|
|
|
=item C |
564
|
|
|
|
|
|
|
|
565
|
|
|
|
|
|
|
This will create the ASPath object with empty contents |
566
|
|
|
|
|
|
|
|
567
|
|
|
|
|
|
|
=back |
568
|
|
|
|
|
|
|
|
569
|
|
|
|
|
|
|
Following the PATHDATA, the OPTIONS may be specified. Currently the |
570
|
|
|
|
|
|
|
only valid option is c, which, if true, builds ASPath objects |
571
|
|
|
|
|
|
|
usable for talking to an peer that supports 32 bit ASNs. False, or |
572
|
|
|
|
|
|
|
the default value, assumes that the peer does not support 32 bit ASNs, |
573
|
|
|
|
|
|
|
which affects the decode routines. Note that the encode routines |
574
|
|
|
|
|
|
|
are not dependent upon this option. |
575
|
|
|
|
|
|
|
|
576
|
|
|
|
|
|
|
Basically, if as4 is true, AS_PATH is populated from messages assuming |
577
|
|
|
|
|
|
|
4 byte ASNs and AS4_PATH is not used. Encoded AS_PATH attributes also |
578
|
|
|
|
|
|
|
assume a 4 byte ASN. |
579
|
|
|
|
|
|
|
|
580
|
|
|
|
|
|
|
If as4 is false, AS_PATH is populated from messages assuming 2 byte ASNs, |
581
|
|
|
|
|
|
|
and, if available, AS4_PATH is used to replace occurences of 23456 |
582
|
|
|
|
|
|
|
when possible when outputing to user-readable formats. Encoding routines |
583
|
|
|
|
|
|
|
will also allow output of AS4_PATH objects when appropriate. |
584
|
|
|
|
|
|
|
|
585
|
|
|
|
|
|
|
=back |
586
|
|
|
|
|
|
|
|
587
|
|
|
|
|
|
|
=head1 OBJECT COPY |
588
|
|
|
|
|
|
|
|
589
|
|
|
|
|
|
|
=over 4 |
590
|
|
|
|
|
|
|
|
591
|
|
|
|
|
|
|
=item clone() - clone a Net::BGP::ASPath object |
592
|
|
|
|
|
|
|
|
593
|
|
|
|
|
|
|
$clone = $aspath->clone(); |
594
|
|
|
|
|
|
|
|
595
|
|
|
|
|
|
|
This method creates an exact copy of the Net::BGP::ASPath object. |
596
|
|
|
|
|
|
|
|
597
|
|
|
|
|
|
|
=back |
598
|
|
|
|
|
|
|
|
599
|
|
|
|
|
|
|
=head1 ACCESSOR METHODS |
600
|
|
|
|
|
|
|
|
601
|
|
|
|
|
|
|
=over 4 |
602
|
|
|
|
|
|
|
|
603
|
|
|
|
|
|
|
=item length() |
604
|
|
|
|
|
|
|
|
605
|
|
|
|
|
|
|
Return the path-length used in BGP path selection. This is the sum |
606
|
|
|
|
|
|
|
of the lengths of all AS_PATH elements. This does however not include |
607
|
|
|
|
|
|
|
AS_PATH_CONFED_* elements and AS_SEGMENTS count as one BGP hop. |
608
|
|
|
|
|
|
|
|
609
|
|
|
|
|
|
|
=item as_string() |
610
|
|
|
|
|
|
|
|
611
|
|
|
|
|
|
|
Returns the path as a string in same notation as the constructor accept. |
612
|
|
|
|
|
|
|
|
613
|
|
|
|
|
|
|
=item cleanup() |
614
|
|
|
|
|
|
|
|
615
|
|
|
|
|
|
|
Reduce the path by removing meaningless AS_PATH elements (empty sets or |
616
|
|
|
|
|
|
|
sequences) and joining neighbour elements of same _SET type. |
617
|
|
|
|
|
|
|
|
618
|
|
|
|
|
|
|
=item strip() |
619
|
|
|
|
|
|
|
|
620
|
|
|
|
|
|
|
Strips AS_CONFED_* segments from the path. |
621
|
|
|
|
|
|
|
|
622
|
|
|
|
|
|
|
=item striped() |
623
|
|
|
|
|
|
|
|
624
|
|
|
|
|
|
|
Returns a strip() 'ed clone() of the path. |
625
|
|
|
|
|
|
|
|
626
|
|
|
|
|
|
|
=item prepend(ARRAY) |
627
|
|
|
|
|
|
|
|
628
|
|
|
|
|
|
|
=item prepend(SCALAR) |
629
|
|
|
|
|
|
|
|
630
|
|
|
|
|
|
|
Strips AS_CONFED_* segments from the path and prepends one or more AS numbers |
631
|
|
|
|
|
|
|
to the path as given as arguments, either as an array of AS numbers or as a |
632
|
|
|
|
|
|
|
string with space seperated AS numbers. If string has "()" arround, prepend_confed |
633
|
|
|
|
|
|
|
will be used instead. |
634
|
|
|
|
|
|
|
|
635
|
|
|
|
|
|
|
=item prepend_confed(ARRAY) |
636
|
|
|
|
|
|
|
|
637
|
|
|
|
|
|
|
=item prepend_confed(SCALAR) |
638
|
|
|
|
|
|
|
|
639
|
|
|
|
|
|
|
Prepends one or more confederation AS numbers to the path as given as |
640
|
|
|
|
|
|
|
arguments, either as an array of AS numbers or as a string with space |
641
|
|
|
|
|
|
|
seperated AS numbers. "()" arround the string is ignored. |
642
|
|
|
|
|
|
|
|
643
|
|
|
|
|
|
|
=item aggregate(ASPath) |
644
|
|
|
|
|
|
|
|
645
|
|
|
|
|
|
|
=item aggregate(ARRAY) |
646
|
|
|
|
|
|
|
|
647
|
|
|
|
|
|
|
Aggregates the current ASPath with the ASPath(s) given as argument. |
648
|
|
|
|
|
|
|
If invoked as class method, aggregate all ASPaths given as argument. |
649
|
|
|
|
|
|
|
|
650
|
|
|
|
|
|
|
To aggregate means to find the longest common substring (of the paths of all |
651
|
|
|
|
|
|
|
objects that should be aggregated) and keep them, but |
652
|
|
|
|
|
|
|
replacing the non-common substrings with AS_SET segments. Currently only |
653
|
|
|
|
|
|
|
the longest common normal and confederation head will be found and the remaing |
654
|
|
|
|
|
|
|
will be left as an AS_SET and AS_CONFED_SET. |
655
|
|
|
|
|
|
|
|
656
|
|
|
|
|
|
|
Returns the aggregated object. The objects self are not modified. |
657
|
|
|
|
|
|
|
|
658
|
|
|
|
|
|
|
=back |
659
|
|
|
|
|
|
|
|
660
|
|
|
|
|
|
|
=head1 SEE ALSO |
661
|
|
|
|
|
|
|
|
662
|
|
|
|
|
|
|
B, B, Net::BGP, Net::BGP::Process, Net::BGP::Peer, |
663
|
|
|
|
|
|
|
Net::BGP::Notification, Net::BGP::NLRI, Net::BGP::Update |
664
|
|
|
|
|
|
|
|
665
|
|
|
|
|
|
|
=head1 AUTHOR |
666
|
|
|
|
|
|
|
|
667
|
|
|
|
|
|
|
Martin Lorensen |
668
|
|
|
|
|
|
|
|
669
|
|
|
|
|
|
|
=cut |
670
|
|
|
|
|
|
|
|
671
|
|
|
|
|
|
|
## End Package Net::BGP::ASPath ## |