PageRenderTime 39ms CodeModel.GetById 11ms RepoModel.GetById 0ms app.codeStats 1ms

/test/msdpls

http://snmp-session.googlecode.com/
Perl | 303 lines | 287 code | 12 blank | 4 comment | 25 complexity | 7e6e55649d54f679d9d34527738258a2 MD5 | raw file
  1. #!/usr/local/bin/perl -w
  2. use strict;
  3. use SNMP_Session;
  4. use BER;
  5. use Socket;
  6. my $version = '1';
  7. my $port = 161;
  8. my $debug = 0;
  9. my $group;
  10. my $numericp = 0;
  11. ### Prototypes
  12. sub msdp_list_duplicate_sas ($ );
  13. sub msdp_collect_sas ($ );
  14. sub msdp_fill_in_duplicates ($$);
  15. sub msdp_report_duplicate_sas ($$$$);
  16. sub msdp_duplicate_report_header ($$$$);
  17. sub msdp_duplicate_report_trailer ($ );
  18. sub msdp_map_group ($$$$);
  19. sub msdp_map_sg ($$$$$ );
  20. sub msdp_list_group ($$);
  21. sub pretty_ip_html ($ );
  22. sub pretty_ip ($ );
  23. sub usage ($ );
  24. while (defined $ARGV[0] && $ARGV[0] =~ /^-/) {
  25. if ($ARGV[0] =~ /^-v/) {
  26. if ($ARGV[0] eq '-v') {
  27. shift @ARGV;
  28. usage (1) unless defined $ARGV[0];
  29. } else {
  30. $ARGV[0] = substr($ARGV[0], 2);
  31. }
  32. if ($ARGV[0] eq '1') {
  33. $version = '1';
  34. } elsif ($ARGV[0] eq '2c') {
  35. $version = '2c';
  36. } else {
  37. usage (1);
  38. }
  39. } elsif ($ARGV[0] =~ /^-p/) {
  40. if ($ARGV[0] eq '-p') {
  41. shift @ARGV;
  42. usage (1) unless defined $ARGV[0];
  43. } else {
  44. $ARGV[0] = substr($ARGV[0], 2);
  45. }
  46. if ($ARGV[0] =~ /^[0-9]+$/) {
  47. $port = $ARGV[0];
  48. } else {
  49. usage (1);
  50. }
  51. } elsif ($ARGV[0] eq '-d') {
  52. ++$debug;
  53. } elsif ($ARGV[0] eq '-n') {
  54. ++$numericp;
  55. } elsif ($ARGV[0] eq '-h') {
  56. usage (0);
  57. exit 0;
  58. } elsif ($ARGV[0] eq '-g') {
  59. shift @ARGV;
  60. $group = $ARGV[0] or usage (1);
  61. } else {
  62. usage (1);
  63. }
  64. shift @ARGV;
  65. }
  66. my $host = shift @ARGV || usage (1);
  67. my $community = shift @ARGV || "public";
  68. usage (1) if $#ARGV >= $[;
  69. my $session =
  70. ($version eq '1' ? SNMPv1_Session->open ($host, $community, $port)
  71. : $version eq '2c' ? SNMPv2c_Session->open ($host, $community, $port)
  72. : die "Unknown SNMP version $version")
  73. || die "Opening SNMP_Session";
  74. $session->debug (1) if $debug;
  75. $session->{max_repetitions} = 100;
  76. my $msdpSACachePeerLearnedFrom = [1,3,6,1,3,92,1,1,6,1,4];
  77. my $msdpSACacheRPFPeer = [1,3,6,1,3,92,1,1,6,1,5];
  78. my $msdpSACacheInSAs = [1,3,6,1,3,92,1,1,6,1,6];
  79. my $msdpSACacheInDataPackets = [1,3,6,1,3,92,1,1,6,1,7];
  80. my $msdpSACacheUpTime = [1,3,6,1,3,92,1,1,6,1,8];
  81. my $msdpSACacheExpiryTime = [1,3,6,1,3,92,1,1,6,1,9];
  82. my $msdpSACacheStatus = [1,3,6,1,3,92,1,1,6,1,10];
  83. if (defined $group) {
  84. msdp_list_group ($session, inet_aton ($group));
  85. } else {
  86. msdp_list_duplicate_sas ($session);
  87. }
  88. 1;
  89. sub msdp_list_duplicate_sas ($ ) {
  90. my ($session) = @_;
  91. my ($announcements, $nsas, $nsgs, $ndups);
  92. ($announcements, $nsas) = msdp_collect_sas ($session);
  93. $nsgs = keys %{$announcements};
  94. ($announcements, $ndups) = msdp_fill_in_duplicates ($session, $announcements);
  95. msdp_report_duplicate_sas ($announcements, $nsas, $nsgs, $ndups);
  96. }
  97. sub msdp_collect_sas ($ ) {
  98. my ($session) = @_;
  99. my @oids = ($msdpSACacheStatus);
  100. my $nsa = 0;
  101. my %announcements;
  102. $session->map_table
  103. (\@oids,
  104. sub () {
  105. my ($index, $sa_status) = @_;
  106. die "index: $index"
  107. unless $index =~ /^(\d+\.\d+\.\d+\.\d+)\.(\d+\.\d+\.\d+\.\d+)\.(\d+\.\d+\.\d+\.\d+)$/;
  108. my ($group, $source, $rp) = ($1, $2, $3);
  109. warn ("S/G/RP entry (status): $group $source $rp ("
  110. .pretty_print ($sa_status).")\n")
  111. if $debug;
  112. return 0 unless pretty_print ($sa_status) == 1; # active(1)
  113. ++$nsa;
  114. push @{$announcements{$source,$group}}, {rp => $rp};
  115. });
  116. (\%announcements, $nsa);
  117. }
  118. sub msdp_fill_in_duplicates ($$) {
  119. my ($session, $announcements) = @_;
  120. my %result = ();
  121. my ($oldreps, $key, $anns, $dupannouncements, $nrps);
  122. $oldreps = $session->{max_repetitions};
  123. $session->{max_repetitions} = 5;
  124. $dupannouncements = 0;
  125. foreach $key (keys %{$announcements}) {
  126. my ($source, $group) = split ($;,$key);
  127. $anns = $announcements->{$key};
  128. if ($#{$anns} > 0) {
  129. $nrps = 0;
  130. my @newanns = ();
  131. msdp_map_sg ($session, $group, $source,
  132. [$msdpSACachePeerLearnedFrom,
  133. $msdpSACacheRPFPeer,
  134. $msdpSACacheInSAs,
  135. $msdpSACacheInDataPackets,
  136. $msdpSACacheUpTime,
  137. $msdpSACacheExpiryTime,
  138. $msdpSACacheStatus],
  139. sub () {
  140. my ($rp,
  141. $peer_learned_from,$rpf_peer,
  142. $in_sas,$in_data_packets,
  143. $up_time,$expiry_time,$status) = @_;
  144. return 1 unless $status == 1; # active(1)
  145. push @newanns, {rp => $rp,
  146. ## peer_learned_from => $peer_learned_from,
  147. ## rpf_peer => $rpf_peer,
  148. in_sas => $in_sas,
  149. in_data_packets => $in_data_packets,
  150. up_time => $up_time,
  151. expiry_time => $expiry_time,
  152. };
  153. ++$nrps;
  154. });
  155. if ($nrps > 1) {
  156. ++$dupannouncements;
  157. $result{$key} = \@newanns;
  158. }
  159. }
  160. }
  161. $session->{max_repetitions} = $oldreps;
  162. (\%result, $dupannouncements);
  163. }
  164. sub msdp_report_duplicate_sas ($$$$) {
  165. my ($announcements, $nsas, $nsgs, $ndups) = @_;
  166. msdp_duplicate_report_header ($announcements, $nsas, $nsgs, $ndups);
  167. foreach my $key (sort keys %{$announcements}) {
  168. my ($source, $group) = split ($;,$key);
  169. my $announcements = $announcements->{$key};
  170. if ($#{$announcements} > 0) {
  171. printf STDOUT ("<tr><th colspan=\"3\">(%s,%s)</th></tr>\n",
  172. pretty_ip_html ($source),
  173. pretty_ip_html ($group));
  174. foreach my $announcement (@{$announcements}) {
  175. printf STDOUT ("<tr><td>%s</td><td align=\"right\">%d</td><td align=\"right\">%d</td></tr>\n",
  176. pretty_ip_html ($announcement->{rp}),
  177. $announcement->{in_sas},
  178. $announcement->{in_data_packets});
  179. }
  180. }
  181. }
  182. msdp_duplicate_report_trailer ($announcements);
  183. }
  184. sub msdp_duplicate_report_header ($$$$) {
  185. my ($announcements, $nsas, $nsgs, $ndups) = @_;
  186. print STDOUT ("<html><head><title>MSDP Duplicate SA Report</title></head>\n");
  187. print STDOUT <<EOM;
  188. <style type="text/css"> <!--
  189. body{background-color:#ffffff; color:black; font-family:helvetica }
  190. tt{font-family:courier,lucidatypewriter }
  191. th{font-family:helvetica,arial }
  192. td{font-family:helvetica,arial }
  193. pre{font-family:courier,lucidatypewriter,monaco,monospaced }
  194. -->
  195. </style>
  196. EOM
  197. print STDOUT ("<body><h1>MSDP Duplicate SA Report</h1>\n");
  198. printf STDOUT ("<p> %d (S,G) pairs found in %d SAs in <tt>%s</tt>'s cache. \n",
  199. $nsgs, $nsas, $host);
  200. printf STDOUT ("Total number of (S,G) pairs with multiple RPs: %d </p>\n",
  201. $ndups);
  202. printf STDOUT ("<table border=\"0\">\n<tr><th>RP</th><th>#SAs</th><th>#data pkts</th></tr>\n");
  203. }
  204. sub msdp_duplicate_report_trailer ($ ) {
  205. my ($announcements) = @_;
  206. print STDOUT "</table>\n</body></html>\n";
  207. }
  208. sub msdp_map_group ($$$$) {
  209. my ($session, $group, $cols, $mapfn) = @_;
  210. my @group_subids = split (/\./, inet_ntoa ($group), 4);
  211. my @oids = map { $_ = [@{$_},@group_subids] } @{$cols};
  212. $session->map_table
  213. (\@oids,
  214. sub () {
  215. my ($index, @colvals) = @_;
  216. map { $_ = pretty_print $_ if defined $_ } (@colvals);
  217. my ($source,$rp);
  218. (($source,$rp) = ($index =~ /^([0-9]+\.[0-9]+\.[0-9]+\.[0-9]+)\.([0-9]+\.[0-9]+\.[0-9]+\.[0-9]+)$/))
  219. || die "?";
  220. &$mapfn ($source,$rp,@colvals);
  221. });
  222. }
  223. sub msdp_map_sg ($$$$$ ) {
  224. my ($session, $group, $source, $cols, $mapfn) = @_;
  225. my @group_subids = split (/\./, $group, 4);
  226. my @source_subids = split (/\./, $source, 4);
  227. my @oids = map { $_ = [@{$_},@group_subids,@source_subids] } @{$cols};
  228. $session->map_table
  229. (\@oids,
  230. sub () {
  231. my ($index, @colvals) = @_;
  232. map { $_ = pretty_print $_ if defined $_ } (@colvals);
  233. my ($rp);
  234. (($rp) = ($index =~ /^([0-9]+\.[0-9]+\.[0-9]+\.[0-9]+)$/))
  235. || die "?";
  236. &$mapfn ($rp,@colvals);
  237. });
  238. }
  239. sub msdp_list_group ($$) {
  240. my ($session, $group) = @_;
  241. msdp_map_group ($session,$group,
  242. [$msdpSACachePeerLearnedFrom,
  243. $msdpSACacheRPFPeer,
  244. $msdpSACacheInSAs,
  245. $msdpSACacheInDataPackets,
  246. $msdpSACacheUpTime,
  247. $msdpSACacheExpiryTime,
  248. $msdpSACacheStatus],
  249. sub () {
  250. my ($source,$rp,
  251. $peer_learned_from,$rpf_peer,
  252. $in_sas,$in_data_packets,
  253. $up_time,$expiry_time,$status) = @_;
  254. #return unless $in_data_packets;
  255. print " ",pretty_ip ($source)," $in_data_packets pkts\n";
  256. print " $peer_learned_from (learned-from) != $rpf_peer (RPF peer)\n"
  257. if $peer_learned_from ne $rpf_peer;
  258. });
  259. }
  260. sub pretty_ip_html ($ ) {
  261. return "<tt>".pretty_ip ($_[0])."</tt>";
  262. }
  263. sub pretty_ip ($ ) {
  264. my ($ip) = @_;
  265. my ($name);
  266. !$numericp && ($name = gethostbyaddr (inet_aton ($ip),AF_INET))
  267. ? "$name [$ip]"
  268. : "$ip";
  269. }
  270. sub usage ($ ) {
  271. print STDERR
  272. ("Usage: $0 [OPTIONS...] ROUTER [COMMUNITY]\n\n",
  273. " OPTIONS:\n\n",
  274. " -v 1|2c select SNMPv1 or SNMPv2c (community-based SNMPv2)\n",
  275. " -p PORT specify an alternate UDP port to contact SNMP agent\n",
  276. " -g GROUP list sources for a specific group\n",
  277. " -d print debugging output\n",
  278. " -n don't resolve hostnames\n",
  279. "\n",
  280. " ROUTER which agent to contact - must implement the MSDP MIB\n",
  281. " COMMUNITY specifies the SNMP community string, defaults to \"public\"\n");
  282. exit $_[0];
  283. }