forked from rfc1036/rpsltool
-
Notifications
You must be signed in to change notification settings - Fork 0
/
routesdiff
executable file
·133 lines (105 loc) · 3.36 KB
/
routesdiff
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
#!/usr/bin/perl
#
# Copyright 2005, 2006 by Marco d'Itri <[email protected]>
#
# This program is free software; you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation; either version 2 of the License, or
# (at your option) any later version.
use warnings;
use strict;
use FindBin;
use lib "$FindBin::RealBin/lib";
use RPSLToolUtils;
use RPSLToolNet;
##############################################################################
my $Routes_Dir = $ARGV[0] or usage(1);
my $peers = list_peers($Routes_Dir);
my $Ignore = read_commented_list();
##############################################################################
my %MaxPrefs;
iterate_peers($peers, sub {
my ($peer, $afi) = @_;
# skip the backup sessions
my $uniquepeer = "$peer->{as} $afi";
return if exists $MaxPrefs{$uniquepeer};
$MaxPrefs{$uniquepeer} = undef;
read_all_routes($peer, $afi);
$MaxPrefs{$uniquepeer} = scalar @{$peer->{routes_accepted}};
report_accepted_routes($peer, $Ignore);
});
print "=" x 72 . "\n";
print "ASN routes\n";
foreach my $as_afi (sort { $MaxPrefs{$b} <=> $MaxPrefs{$a} } keys %MaxPrefs) {
my ($asn, $afi) = $as_afi =~ /^(\S+) +(\S+)$/;
printf("%-7s%s%s\n", $asn, $MaxPrefs{$as_afi},
$afi ne 'ipv4' ? " ($afi)" : '');
}
exit 0;
##############################################################################
sub report_accepted_routes {
my ($peer, $ignore) = @_;
my $rr = $peer->{routes_received};
my $ra = $peer->{routes_accepted};
my $diff = difference($rr, $ra);
return if not @$diff;
if ($ignore) {
$diff = filter_networks($diff, $ignore, 1);
return if not @$diff;
}
print "=" x 72 . "\n";
print "Checking $peer->{ip} (AS$peer->{as}).\n";
printf("Accepted %d of %d routes (%.2f%%). Not accepted:\n",
scalar @$ra, scalar @$rr, scalar @$ra * 100 / scalar @$rr);
if (@$diff > 50) {
print "[Too many routes... List partially suppressed.]\n";
@$diff = @{$diff}[0,50];
}
my $paths = $peer->{paths};
printf("%-20s %s\n", $_, $paths->{$_}) foreach sort {
my @pa = split(/\s+/, $paths->{$a});
my @pb = split(/\s+/, $paths->{$b});
return $pa[$#pa] <=> $pb[$#pb] || $a cmp $b; # XXX use by_ip
} @$diff;
print "\n\n";
}
##############################################################################
sub read_all_routes {
my ($peer, $afi) = @_;
$peer->{paths} = { };
$peer->{routes_received} = [ ];
$peer->{routes_accepted} = [ ];
read_routes("$Routes_Dir$peer->{as}_$peer->{ip}_${afi}_rr",
$peer->{routes_received}, $peer->{paths});
read_routes("$Routes_Dir$peer->{as}_$peer->{ip}_${afi}_ra",
$peer->{routes_accepted}, undef);
}
##############################################################################
# XXX neighbors with multiple AFIs on the same IP address are not supported
# by this function, hence multicast neighbors are ignored
sub list_peers {
my ($dir) = @_;
return {
map { $_->[1] => { as => $_->[0], ip => $_->[1], $_->[2] => { } } }
map { s#.*/##; s#_rr$##; [ split(/_/, $_) ] }
glob($dir . '*_ipv?_rr')
};
}
sub by_routes {
scalar @{$b->{routes_accepted}} <=> scalar @{$a->{routes_accepted}}
}
sub usage {
print STDERR <<END;
Usage: routesdiff ROUTES-DIR
END
exit(shift);
}
__DATA__
0.0.0.0/0^25-32
# this is very rough and ignores all legitimate more specifics
2000::/4^33-128
3FFE::/18^25-128
3FFE:4000::/18^33-128
3FFE:8000::/17^29-128
# 6to4
2002::/16