Juniper-set-rsvp-metrics
From Initech Technical Wiki
#!/usr/bin/php <?php function usage () { echo "\n"; echo "Juniper RSVP Metric Analysis and Reset tool"; echo "\n"; echo "Usage: juniper-set-rsvp-metrics [--size=<ping_size>] [--count=<ping_count>] [-r] [--routers=<router1>,<router2>] [-q]\n"; echo "\n"; echo " --routers=<router1>,<router2> Optionally provide a list of routers to run this script against, if ommitted it will\n"; echo " attempt to discover the list of routers from stored rancid configurations\n"; echo " --size=<ping_size> What size ICMP packets to test against each OSPF neighbor - the default is 8,900 bytes"; echo " --count=<ping_count> How many ICMP packets to send to each OSPF neighbor - the default is 10,000"; echo " -r Use rapid ICMP mode, the default is non-rapid"; echo " -q Run this script without prompting to continue, useful to run automatically from cron\n"; echo " -d Print a LOT of debug output about what exactly it's doing\n"; echo " -h|--help Display this help text\n"; echo "\n"; exit; } function arguments($argv) { $_ARG = array(); foreach ($argv as $arg) { if (ereg('--([^=]+)=(.*)',$arg,$reg)) { $_ARG[$reg[1]] = $reg[2]; } elseif(ereg('-([a-zA-Z0-9])',$arg,$reg)) { $_ARG[$reg[1]] = 'true'; } } return $_ARG; } // Parse command-line aguments into an array calles $arguments $arguments=arguments($argv); // Output usage information if the user has involked the -h or --help arguments if((isset($arguments['h']))&&($arguments['h']==true)) { usage(); } if(!isset($arguments['size'])) { $arguments['size']=8900; } if(!isset($arguments['count'])) { $arguments['count']=10000; } $arguments['timeout']=$arguments['count']+($arguments['count']/2); if(!isset($arguments['r'])) { $arguments['r']="NON-RAPID"; } else { $arguments['r']="RAPID"; } // Verify that the user is rancid, this script can only effectively be run by the rancid user if(trim(`whoami`) !== 'rancid') { echo "You must be the rancid user to run this script, exiting\n"; exit(1); } // Echo welcome message if -q wasn't involked at the command line or if -d was if((!isset($arguments['q']))||(isset($arguments['d']))) { echo "\n"; echo "Welcome to the Juniper RSVP Metric Analysis and Reset tool.\n"; } if(isset($arguments['d'])) { echo "DEBUG: Begin dump of command-line arguments\n"; var_dump($arguments); echo "DEBUG: End dump of command-line arguments\n"; } // Make the user confirm their actions if -q wasn't issued at the command line if(!isset($arguments['q'])) { echo "Type 'yes' to continue or just press enter to quit: "; $handle = fopen ("php://stdin","r"); $line = fgets($handle); if(trim($line) != 'yes'){ echo "Quiting\n"; exit; } fclose($handle); echo "\n"; echo "Thank you, continuing...\n"; } // Get list of routers, either from command-line or by detecting traffic-engineering in rancid stored configs if(isset($arguments['routers'])) { if(isset($arguments['d'])) { echo "DEBUG: Router list was provided at command-line, exploding it into an array\n"; } $candidate_list_of_routers=explode(',',$arguments['routers']); } else { if(isset($arguments['d'])) { echo "DEBUG: Router list was provided at command-line, exploding it into an array\n"; } exec("grep 'traffic-engineering' ~rancid/managed_devices/configs/* 2>&1 | grep -v 'grep' |grep -v '.new:'| awk '{print $1}' | awk -F\: '{print $1}' | sort | uniq | xargs -I arg1 basename arg1", $candidate_list_of_routers); } if(isset($arguments['d'])) { echo "DEBUG: Begin router array dump\n"; var_dump($candidate_list_of_routers); echo "DEBUG: End router array dump\n"; } // Make sure that each router is a juniper if(isset($arguments['d'])) { echo "DEBUG: Processing each router to make sure it's a juniper\n"; } foreach ($candidate_list_of_routers as $router) { if(trim(`grep '#RANCID-CONTENT-TYPE: juniper' ~rancid/managed_devices/configs/$router 2>&1`) == '#RANCID-CONTENT-TYPE: juniper') { if(isset($arguments['d'])) { echo "DEBUG: OK - $router detected as juniper\n"; } $list_of_routers[$router]=array(); } else { if(isset($arguments['d'])) { echo "DEBUG: PROBLEM - $router is not a juniper, ignoring it\n"; } } } // For each router create a temp file and dump the config out to that file in set format if(isset($arguments['d'])) { echo "\n"; echo "------------------------section break----------------------------\n"; echo "\n"; echo "DEBUG: Logging into each router and grabbing its current config\n"; } foreach ($list_of_routers as $router_name => &$router_ref) { $tempfile=trim(`mktemp`); if(isset($arguments['d'])) { echo "DEBUG: Create $tempfile for $router_name config\n"; } $router_ref['config_file']=$tempfile; `jlogin -c 'show configuration | display inheritance | display set | no-more' $router_name | grep '^set' > $tempfile`; } // For each router login and grab the OSPF neighbors, Remote end IP and interface name if(isset($arguments['d'])) { echo "\n"; echo "DEBUG: Processing each router to grab its OSPF neighbors\n"; } foreach ($list_of_routers as $router_name => &$router_ref) { if(isset($arguments['d'])) { echo "DEBUG: Logging into $router_name with jlogin and issuing command 'show ospf neighbor'\n"; } exec("jlogin -c 'show ospf neighbor' $router_name | grep 'Full' | awk '{print $1\",\"$2}'",$ospf_neighbor_list); if(isset($arguments['d'])) { echo "DEBUG: begin dump of OSPF output\n"; var_dump($ospf_neighbor_list); echo "DEBUG: end dump of OSPF output\n"; } // Parse output, split ip address and interface name and grab some more details about each interface if(isset($arguments['d'])) { echo "DEBUG: For each OSPF neighbor split the neighbor IP and the interface and parse more information for each interface from the saved configs\n"; } foreach ($ospf_neighbor_list as $neighbor) { list($ip,$interface)=explode(",",$neighbor); if(isset($arguments['d'])) { "DEBUG: Parsing interface $interface and neighbor $ip\n"; } // Setup a sub-array within the router variable $router_ref['neighbors'][$ip]['interface']['name']=$interface; // Split the interface into its component parts; list($unit,$subunit)=explode(".",$interface); $router_ref['neighbors'][$ip]['interface']['unit']=$unit; $router_ref['neighbors'][$ip]['interface']['subunit']=$subunit; // Grab the interface description from the saved config $router_ref['neighbors'][$ip]['interface']['description']=trim(`grep '^set interfaces $unit unit $subunit description ' {$router_ref['config_file']} | awk -F\" '{print $2}'`); // Grab current TE metric from saved config $router_ref['neighbors'][$ip]['interface']['current_metric']=trim(`grep '^set protocols ospf area 0.0.0.0 interface {$unit}.{$subunit} te-metric ' {$router_ref['config_file']} | awk '{print $9}'`); if($router_ref['neighbors'][$ip]['interface']['current_metric']=="") { $router_ref['neighbors'][$ip]['interface']['current_metric']="unset"; } if(isset($arguments['d'])) { echo "DEBUG: Begin var_dump of neighbor $ip\n"; var_dump($router_ref['neighbors'][$ip]); echo "DEBUG: End var_dump of neighbor $ip\n"; } } // Destroy the ospf neighbor list array for reuse next time unset($ospf_neighbor_list); } // Login to each router and ping each OSPF neighbor with large packets to figure out the lowest RTT, this will be the new interface metric if(isset($arguments['d'])) { echo "\n"; echo "------------------------section break----------------------------\n"; echo "\n"; echo "DEBUG: Login to each router and ping each OSPF neighbor with large packets to figure out the lowest RTT, this will be the new interface metric\n"; echo "\n"; } foreach ($list_of_routers as $router_name => &$router_ref) { if(isset($arguments['d'])) { echo "-------------------------------\n"; echo "DEBUG: Begin router {$router_name}\n\n"; } foreach ($router_ref['neighbors'] as $neighbor_ip => &$neighbor_ref) { if(isset($arguments['d'])) { echo "DEBUG: Logging into $router_name and {$arguments['r']} pinging neighbor ip $neighbor_ip on interface {$neighbor_ref['interface']['name']} ({$neighbor_ref['interface']['description']})\n"; echo "DEBUG: We will send {$arguments['count']} ICMP packets at {$arguments['size']} bytes each\n"; } if($arguments['r']=="RAPID") { $rtt=trim(`jlogin -t {$arguments['timeout']} -c 'ping no-resolve do-not-fragment size {$arguments['size']} rapid count {$arguments['count']} $neighbor_ip' $router_name |grep 'round-trip min' | awk '{print $4}' | awk -F/ '{print $1}'`); } else { $rtt=trim(`jlogin -t {$arguments['timeout']} -c 'ping no-resolve do-not-fragment size {$arguments['size']} count {$arguments['count']} $neighbor_ip' $router_name |grep 'round-trip min' | awk '{print $4}' | awk -F/ '{print $1}'`); } $neighbor_ref['interface']['rtt']=$rtt; if($rtt<1) { $neighbor_ref['interface']['new_metric']=1; } else { $neighbor_ref['interface']['new_metric']=floor($rtt); } if(isset($arguments['d'])) { echo "DEBUG: Finished, minimum round trip time on this interface was {$neighbor_ref['interface']['rtt']}ms, new metric recommendation is {$neighbor_ref['interface']['new_metric']}\n\n"; } } if(isset($arguments['d'])) { echo "DEBUG: End router {$router_name}\n"; echo "-------------------------------\n"; } } // Output recommendations if not implementing them ourselves if(isset($arguments['d'])) { echo "\n"; echo "------------------------section break----------------------------\n"; echo "\n"; echo "DEBUG: Output of configuration change recommendations\n"; } foreach ($list_of_routers as $router_name => &$router_ref) { $header_printed=false; foreach ($router_ref['neighbors'] as $neighbor_ip => &$neighbor_ref) { if($neighbor_ref['interface']['new_metric'] !== $neighbor_ref['interface']['current_metric']) { if($header_printed==false) { echo "\n"; echo "**************************************************************\n"; echo "* {$router_name}\n"; echo "**************************************************************\n"; $header_printed=true; } echo "set protocols ospf area 0.0.0.0 interface {$neighbor_ref['interface']['unit']}.{$neighbor_ref['interface']['subunit']} te-metric {$neighbor_ref['interface']['new_metric']}\n"; } } } // Clean up temp files before exit if(isset($arguments['d'])) { echo "\n"; echo "------------------------section break----------------------------\n"; echo "\n"; echo "DEBUG: Delete all temporary config files before process exit\n"; } foreach ($list_of_routers as $router_name => &$router_ref) { if(isset($arguments['d'])) { echo "DEBUG: Deleting ". $router_ref['config_file'] ." for $router_name\n"; } unlink ($router_ref['config_file']); } ?>