Last active
December 11, 2015 05:08
-
-
Save jeremyschulman/4549891 to your computer and use it in GitHub Desktop.
A simple example tracking down a routing path through a BGP/MPLS/LDP Junos network.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
require 'highline/import' | |
require 'net/netconf/jnpr' | |
target = ARGV[0] || begin | |
puts "You must specify a starting target device" | |
exit 1 | |
end | |
dst_route = ARGV[1] || begin | |
puts "You need to specify a destination route" | |
exit 1 | |
end | |
my_username = ENV["USER"] | |
puts "login: #{my_username}" | |
my_password = ask("password: "){|a| a.echo = false} | |
module ScannerLDP | |
def get_lldp_nei( ifd_name ) | |
ifd_name.gsub!(/\.\d+/, '') # drop the IFL | |
rsp = @rpc.command "show lldp neighbors interface #{ifd_name}" | |
if_nei = rsp.xpath('lldp-neighbor-information') | |
rmt_sysname = if_nei.xpath('lldp-remote-system-name').text | |
rmt_ip = if_nei.xpath('lldp-remote-management-address').text | |
{ :rmtsys => rmt_sysname, :rmtip => rmt_ip } | |
end | |
def get_lacp_ifds( ae_name ) | |
ae_name.gsub!(/\.\d+/, '') # drop the IFL | |
rsp = @rpc.get_lacp_interface_information( :interface_name => ae_name ) | |
rsp.xpath('//lag-lacp-protocol/name').collect{|i| i.text} | |
end | |
def nh_proc( nh ) | |
nh_table = nh.xpath('nh-table').text | |
nh_mpls = nh.xpath('mpls-label').text | |
rdat = {} | |
rdat[:protocol] = nh.xpath('../protocol-name').text | |
rdat[:nh] = nh.xpath('to').text | |
rdat[:via] = nh.xpath('via').text | |
rdat[:table] = nh_table unless nh_table.empty? | |
rdat[:mpls] = nh_mpls unless nh_mpls.empty? | |
rdat | |
end | |
def get_active_route( opts ) | |
rpc_args = {} | |
rpc_args[:destination] = opts[:dest] | |
rpc_args[:active_path] = true | |
rpc_args[:table] = opts[:table] if opts[:table] | |
as_txt = (opts[:as_txt]) ? { :format => 'text' } : nil | |
rsp = @rpc.get_route_information( rpc_args, as_txt ) | |
if as_txt | |
rsp.text | |
else | |
nh = rsp.xpath('//nh[selected-next-hop]')[0] || rsp.xpath('//nh')[0] | |
nh_proc( nh ) | |
end | |
end | |
def get_mpls_route( label ) | |
rsp = @rpc.get_route_information( :table => 'mpls', :label => label ) | |
nh = rsp.xpath('//nh')[0] | |
nh_proc( nh ) | |
end | |
def get_next_rtr( nhop ) | |
ifd_name = nhop[:via] | |
if ifd_name.match /ae\d/ | |
ifd_name = get_lacp_ifds( ifd_name )[0] | |
end | |
lldp_nei = get_lldp_nei( ifd_name ) | |
end | |
end | |
def mpls_stack_proc( mpls_stack, mpls_txt_acts ) | |
mpls_txt_acts.scan(/(\w+)\s?(\d+)?,?/).each do |action| | |
case action[0] | |
when "Push" | |
mpls_stack.unshift action[1] | |
when "Pop" | |
mpls_stack.shift | |
when "Swap" | |
mpls_stack[0] = action[1] | |
end | |
end | |
mpls_stack | |
end | |
login = { :username => my_username, :password => my_password } | |
login[:target] = target | |
mpls_stack = [] | |
done = false | |
until done | |
puts "\nLOGGING INTO: #{target} ..." | |
dev = Netconf::SSH.new( login ) | |
dev.extend ScannerLDP | |
dev.open | |
if mpls_stack.empty? | |
nhop = dev.get_active_route( :table => 'wireless', :dest => dst_route ) | |
else | |
nhop = dev.get_mpls_route( mpls_stack[0] ) | |
end | |
if nhop[:mpls] | |
mpls_stack_proc( mpls_stack, nhop[:mpls] ) | |
end | |
if mpls_stack.empty? | |
puts "MPLS stack is empty, we're at the end ..." | |
nhop = dev.get_active_route( :table => nhop[:table], :dest => dst_route, :as_txt => true ) | |
puts nhop | |
puts "\nDONE!" | |
done = true | |
else | |
puts "MPLS stack is now: " + mpls_stack.join(",") | |
next_rtr = dev.get_next_rtr( nhop ) | |
login[:target] = next_rtr[:rmtip] | |
target = next_rtr[:rmtsys] | |
end | |
dev.close | |
end |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
$ ruby trace-route-ldp.rb mx240-176 192.168.199.0 | |
login: jschulman | |
password: | |
LOGGING INTO: mx240-176 ... | |
MPLS stack is now: 300896,18 | |
LOGGING INTO: MX480-R244 ... | |
MPLS stack is now: 301088,18 | |
LOGGING INTO: MX240-R178 ... | |
MPLS stack is now: 18 | |
LOGGING INTO: MX240-R130-re0 ... | |
MPLS stack is empty, we're at the end ... | |
wireless.inet.0: 13 destinations, 26 routes (13 active, 0 holddown, 0 hidden) | |
+ = Active Route, - = Last Active, * = Both | |
192.168.199.0/24 *[OSPF/10] 20:38:57, metric 2 | |
> to 10.0.0.33 via xe-2/1/2.110 | |
DONE! |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment