Archive for the 'networking' Category

Selective export of routes in an MPLS VRF

I need to be able to export just the public address from the route table inside a VRF, without impacting the existing route imports and exports

The existing VRF configuration is

ip vrf blah
 rd 64512:12345
 route-target export 64512:1
 route-target import 64512:1

In this configuration all routes will be exported to all the other VRF’s that import 64512:1

The VRF has RFC1918 address space in it, but it also has some public IP address space that I need to be able to export to other VRF’s on the network.

After a bit of looking around, it appears the way to do this is to use the export map function, but there are a couple of catches. Firstly, you have to remove the other export statements, and you need bundle a number of match/set route maps together.

First create a couple of access lists

ip access-list standard rfc1918-address-space
 permit 10.0.0.0 0.255.255.255
ip access-list standard public-address-space
 permit 15.3.34.0 0.0.0.255

Now we need to create a route-map to set the exports based on the access lists.

route-map vrf-export-map permit 10
 match ip address rfc1918-address-space
 set extcommunity rt  64512:1
route-map vrf-export-map permit 20
 match ip address public-address-space
  set extcommunity rt 64512:1 64512:1001

The sequence 10 map, matches the rfc1918 address and adds an export of 64512:1 ( which is the existing export ). The sequence 20 map matches the public address space and adds 64512:1, and then also adds 64512:1001.

I think there is also an additive option – but I have not had time to look at it ( if I understand it correctly it address additional exports onto the current list of exports )

Now we just need to modify the VRF so that we pick up the route map.

ip vrf blah
 rd 64512:12345
 export map vrf-export-map
 route-target import 64512:1

You can now import the address space into multiple different VRF’s

This config will get all the address space

ip vrf blah2
 rd 64512:23456
 route-target import 64512:1

This config will just get the public address space

ip vrf blah3
 rd 64512:34567
 route-target import 64512:1001

Cheers
Pete

100% CPU with multihop BGP

I need to look at this more, but for the moment the problem is solved.

I had an issue where I configured BGP multihop, and the router CPU sat at 100% utilisation and stayed there.

The CPU utilisation looked like this

thing#show processes cpu sort
CPU utilization for five seconds: 99%/0%; one minute: 99%; five minutes: 96%
 PID Runtime(uS)     Invoked      uSecs   5Sec   1Min   5Min TTY Process
 295   326764000        7716      42348 48.54% 31.38% 31.09%   0 BGP Router
 154   509856000        3549     143661 44.16% 56.25% 51.87%   0 IP RIB Update
 297     8980000         131      68549  3.97%  1.03%  0.82%   0 BGP Scanner

The BGP config looks ( something ) like

router bgp 1234
 bgp router-id 192.168.10.1
 no bgp default ipv4-unicast
 bgp log-neighbor-changes
 !
 address-family ipv4 vrf blah
  no synchronization
  bgp router-id 1.2.3.4
  network 1.2.3.0
  neighbor peer peer-group
  neighbor peer remote-as 8765
  neighbor peer ebgp-multihop 4
  neighbor peer update-source Loopback9000
  neighbor peer version 4
  neighbor peer send-community both
  neighbor peer soft-reconfiguration inbound
  neighbor 192.168.20.1 peer-group peer
  neighbor 192.168.20.1 activate
 exit-address-family
 !
 

The only really interesting bit, is the ebgp-multihop command – the rest is pretty standard

If I looked at the CEF table, a route that should have been learned via BGP was un-resolved

thing#show ip cef vrf blah 121.0.7.1
121.0.0.0/21
  unresolved via 200.170.81.17

If I kept doing show ip route vrf blah, the routes would appear, and then disappear.

Now I don’t profess to really understand how this has made a difference, but what I did was add a static route for the remove BGP peer.

I already had

ip route vrf blah 0.0.0.0 0.0.0.0 192.168.50.1

but I added

ip route vrf blah 192.168.20.1 255.255.255.255 192.168.50.1

I can see a different in the CEF table now

thing#show ip cef vrf blah 121.0.7.1 detail
121.0.0.0/21, epoch 0, flags rib only nolabel, rib defined all labels
  recursive via 192.168.20.1
    recursive via 192.168.50.1
      attached to Vlan97
thing#

An the CPU has completely calmed down.

Hope it helps!
Pete

Optimise BGP memory using by limiting the number of AS-PATHs

The full route table is getting pretty big, and a simple way to limit the amount of memory usage on your routers, is to limit the number of AS-PATHs that you accept. If you are connected to the Tier 1 providers, then most major networks will only be 3 or 4 AS’s away, so anything else you can just use a default route for.

If I pick up full routes, show bgp all summary looks like this

show bgp all summary

374859 network entries using 53979696 bytes of memory
374859 path entries using 19492668 bytes of memory
63037/63037 BGP path/bestpath attribute entries using 8320884 bytes of memory
56456 BGP AS-PATH entries using 2223352 bytes of memory

and the route table looks like

show ip route summary

Route Source    Networks    Subnets     Replicates  Overhead    Memory (bytes)
connected       0           8           0           448         1376
static          1           0           0           56          172
bgp 64513       144752      229965      0           20984152    64451324
  External: 374717 Internal: 0 Local: 0
internal        4380                                            15466904
Total           149133      229973      0           20984656    79919776

So if I am reading it right, BGP is using 83MB of memory and the route table is using 80MB

If I want to limit the number of paths, I can do that by setting an as-path access list with the right regex

ip as-path access-list 10 permit ^[0-9]+( [0-9]+)( [0-9]+)( [0-9]+)$
ip as-path access-list 10 deny .*

In this example, I am allow 4 AS hops. if I wanted three, I would just remove the last ( [0-9]+) entry.

To apply this access list, you need to add a bgp filter into your bgp config

 address-family ipv4 vrf blah
  neighbor 1.2.3.4 remote-as 1239
  neighbor 1.2.3.4 local-as 1790 no-prepend replace-as
  neighbor 1.2.3.4 version 4
  neighbor 1.2.3.4 send-community both
  neighbor 1.2.3.4 filter-list 10 in
  neighbor 1.2.3.4 activate
 exit-address-family

Now bgp all sum looks like this

show bgp all summary

109629 network entries using 15786576 bytes of memory
109629 path entries using 5700708 bytes of memory
21302/21302 BGP path/bestpath attribute entries using 2811864 bytes of memory
19510 BGP AS-PATH entries using 780400 bytes of memory

Thats about 30MB of memory, rather than 80MB on BGP, and if I look at the route table, its at 23MB rather than 80MB – we have saved about 100MB of memory.

If your going to do this, you need to make sure you do not have soft-reconfigure turned on. Before you turn it off, make sure you understand what it does first :-)

If I turn on soft-reconfigure, even with the filter-list in place, the bgp summary looks like this again ( 83MB )

show bgp all summary

374735 network entries using 53961840 bytes of memory
374735 path entries using 19486220 bytes of memory
63026/21302 BGP path/bestpath attribute entries using 8319432 bytes of memory
56451 BGP AS-PATH entries using 2221352 bytes of memory

Even though the route table does not have all the routes ( 24MB )

show ip route summary

Route Source    Networks    Subnets     Replicates  Overhead    Memory (bytes)
connected       0           8           0           448         1376
static          1           0           0           56          172
bgp 64513       40138       69516       0           6140624     18860488
  External: 109654 Internal: 0 Local: 0
internal        1997                                            4796348
Total           42136       69524       0           6141128     23658384

So, you can save a 100MB of memory with a little tweak, but its a minimal gain really – a better solution is to purchase more ram for your router – its not that expensive.

Cheers
Pete

Identifying bandwidth usage (top talkers) on a Juniper firewall

I have often needed to find out who the top bandwidth users (top talkers) are on a Juniper SSG firewall.

Cisco’s have Netflow, and Junos has Jflow or whatever its called.  Netscreen Juniper make a lot of noise about how good their traffic shaping is on the SSG firewalls, but finding who is using the bandwidth at any point in time has always eluded me, until today.

First you need to enable fprofiling

set fprofile packet enable

Now you need to capture some data

set fprofile packet start

wait a bit, then turn it off

set fprofile packet stop

Now you can see who the top talkers are by looking at the captured data

myfw-> get fprofile packet
packet buffer size(in kilo-packets): 4
total ip packet: 4041
total ip packet time(us): 693434
total none-ip packet: 55
total none-ip packet time(us): 5834
Id  Type        Protocol    Source            Destination             Sport       Dport        Time  Percentage
1  ip          0x06        61.165.32.63    34.52.134.6            80        1369      195490  27.95%
2  ip          0x06        61.165.32.63    192.168.1.10              80       49362      104221  14.90%
3  ip          0x06        192.168.1.10      61.165.32.63         49362          80       78254  11.19%
4  ip          0x06        192.168.1.15       102.168.2.27            64754        4242       72124  10.31%
5  ip          0x06        87.248.210.253    34.52.134.6            80        1954       60716   8.68%
6  ip          0x06        102.168.2.27       192.168.1.15             4242       64754       38429   5.49%
7  ip          0x06        87.248.210.253    192.168.1.11              80       59031       31086   4.44%
8  ip          0x01        192.168.0.5        192.168.1.6                11           0       25952   3.71%
9  ip          0x06        192.168.1.11      87.248.210.253         59031          80       23852   3.41%
10  ip          0x06        34.52.134.6    87.248.211.190          1369          80       18404   2.63%
myfw->

its good practice to clean up at the end

usnet fprofile packet enable

static ipv6 address on solaris 10

This seems silly, but it took quite a while to get a static ipv6 address to configure itself properly on solaris ten.

There were loads of errors, mainly like

  • Failed to configure IPv6 interfaces(s): e1000g0
  • t_optmgmt: System error: Cannot assign requested address

If you read the various versions of the documentation, they suggest you add the following to /etc/hostname6.e1000g0

inet6 ipv6-address up
addif inet6 ipv6-address up
...

But this actually doesn’t seem to work. :-(

This seems to work though

bash-3.00$ cat /etc/inet/ndpd.conf
if-variable-name StatelessAddrConf false
bash-3.00$ cat /etc/hostname6.e1000g0
addif 2001:8e3:ee12:2::36/64 up
bash-3.00$

Putting inet6 into the hostname file seems to be the main issue, and it works just fine without it.

Interestingly, you still get the various address you would normally expect (local and global), so the static address will appear as a sub interface rather than an IP on the primary interface

$ /usr/sbin/ifconfig -a
lo0: flags=2002000849 mtu 8252 index 1
        inet6 ::1/128
e1000g0: flags=2000841 mtu 1500 index 2
        inet6 fe80::20c:23df:fe61:e321/10
e1000g0:1: flags=2000841 mtu 1500 index 2
        inet6 2001:8e3:ee12:2::36/64
e1000g0:2: flags=2080841 mtu 1500 index 2
        inet6 2001:8e3:ee12:2:20c:23df:fe61:e321/64
$

output and exit code when threading remote ssh commands

There are many articles around on the various ways of getting stdout, stderr and exit codes etc from a remotely executed ssh command, but they all seem to be complicated, or they just don’t give you everything you need.

The most common situation I have come across is needing the stdout and stderr merged into ‘output’, and the exit code. The problem has always been around using `back-ticks` which seems to give me output, and system() which gives me exit code, or something more complicated. Often you also see references to using $? which returns the exit code of the last exited child process, but this is fragile if you are spawning multiple children to run things in parallel.

In the end, the simplest and least fragile approach seemed to be to wrap the command appropriately on the remove host, merge stdout and stderr, and then append the exit code to the end of the output and parse it off when I get it back.

The remote executed command for ‘date’, would basically looks like

sh -c "date"; EC=$?; sleep 1; echo $EC 2>&1

A little explanation is required.

  • sh -c wraps the whole command up, so that I can be sure to get the exit code of the whole command rather than part of it
  • Once executed, I grab the exit code and save it as EC
  • The sleep statement gives stdout and stderr time to drain
  • The exit $EC returns the exit code from the command I ran, rather than from the sleep statement.
  • 2>&1 redirects stderr to stdout.

All in all, this ensures I pick up everything from the remote host, including exit code, and i can parallize it without worring about race conditions.

This is all pretty simply wrapped in a few ruby methods

require 'net/ssh'
def extended_command cmd
   "sh -c \""+cmd+"\"; EC=$?; sleep 1; echo $EC 2>&1"
end
 
def parse output
  foo = output.to_a
  @exit_code = foo.pop.to_i
  foo.map! { |line| line.chomp }
  @output = foo.join("\n")
end
 
@host = 'blah'
@uid = 'someuser'
 
Net::SSH.start(@host, @uid ) do |ssh|
    result = ssh.exec!( "#{ extended_command "id;hostname"  }" )
end
 
parse result
 
puts @output
puts @exit_code

The commands can get reasonably complex without anything breaking, separating with ; or using pipes seems to work as expected. If you wanted to redirect output in your command, you need to escape it twice, first you have to escape the escape, then escape the redirect, i.e.

ls -al \\\> directory.list

Cheers
Pete

IPv6 BGP between Cisco router and Juniper SSG firewall

When I signed up with my ISP, I received a /48 of ipv6 address space along with it. I managed to find some time the other day to try set it up. The equipment in use is cisco routers and a juniper SSG firewall. For what its worth I though I would just document what was need to get it working.

I use VRF’s (Virtual Route Forwarders – effectively virtual route tables) a lot on the Cisco routers – they really are quite neat. The VRF’s are ipv4 by default. The ISP connection on the router is inside a VRF, so the first thing to do is to enable ipv6 on the VRF.

vrf upgrade-cli multi-af-mode common-policies

I have only just started looking at ipv6, so I spent some time looking for the address range I should use on the link between myself and the ISP (as I would with ipv4).  I finally worked out that I just need to use an automatically link local address.

This config lives on a PPPoE dialer

!
interface Dialer1
vrf forwarding my-vrf
bandwidth inherit
bandwidth receive inherit
ip address negotiated
encapsulation ppp
dialer pool 1
dialer-group 1
ipv6 address autoconfig default
no cdp enable
ppp chap hostname my-uid
ppp chap password 7 my-hash
!

Which looks like this when it comes up

router# show ipv6 int brie
Dialer1                    [up/up]
    FE80::213:C3FF:FEE7:9FF0

The ipv6 addresses look somewhat complicated at first glance, but they are quite tidy when you play with them a bit, and they are easy carve up if you wish to do so. I started cutting the block into /64 LAN segments.

If you were allocated 2001:8b0:ff00::/48, you can subnet it as

2001:8b0:ff00:1::/64, and make your router 2001:8b0:ff00:1::1 and a host can be statically defined as 2001:8b0:ff00:1::21.

The next subnet could be 2001:8b0:ff00:2::/64 etc

On the router I created the first ipv6 segment for between the router and the SSG firewall.

!
interface FastEthernet0/1.98
 description dirty-net
 vrf forwarding my-vrf
 encapsulation dot1Q 98
 ipv6 address 2001:8B0:FF00:1::1/64
!

the BGP configuration was relatively simple.

!
router bgp 64512
!
address-family ipv4 vrf my-vrf
no synchronization
exit-address-family
!
!
address-family ipv6 vrf my-vrf
neighbor my-vrf peer-group
neighbor my-vrf remote-as 64513
neighbor my-vrf default-originate
neighbor 2001:8B0:FF00:1::2 peer-group my-vrf
neighbor 2001:8B0:FF00:1::2 activate
redistribute connected
no synchronization
exit-address-family
!

On the SSG firewall, I added additional addresses to existing ipv4 interfaces, but first you have to enable ipv6 on the firewall.

set envar ipv6=yes

Now I can configure the interface

set interface "ethernet0/1.1" tag 98 zone "dirty-net"
set interface "ethernet0/1.1" ipv6 mode "router"
set interface "ethernet0/1.1" ipv6 ip 2001:8b0:ff00:1::2/64
set interface "ethernet0/1.1" ipv6 enable
set interface ethernet0/1.1 ipv6 ra link-address
set interface ethernet0/1.1 ipv6 nd nud
set interface ethernet0/1.1 protocol bgp

And then configure BGP (and advertised the /48 block to the cisco router

my-ssg(trust-vr)-> get config
set router-id 10.12.10.3
set adv-inact-interface
set protocol bgp 64513
set neighbor 2001:8b0:ff00:1::1 remote-as 64512 local-ip 2001:8b0:ff00:1::2/64 outgoing-interface ethernet0/1.1
set neighbor 2001:8b0:ff00:1::1 enable
set neighbor 2001:8b0:ff0:1::1 hold-time 10
unset ipv6 synchronization
set ipv6 neighbor 2001:8b0:ff00:1::1 activate
set ipv6 network 2001:8b0:ff00::/48 no-check
pe1-cf-01a(trust-vr)->

On the inside of the firewall I configured the second subnet 2001:8b0:ff00:2/64 and set the interface type to ipv6 router

set interface "ethernet0/1.3" ipv6 mode "router"
set interface "ethernet0/1.3" ipv6 ip 2001:8b0:ff00:3::1/64
set interface "ethernet0/1.3" ipv6 enable

Now all the hosts on the internal network will quite happily pickup an ipv6 address. You can make sure its working by pinging google.

boo:~ pete$ ping6 ipv6.google.com
PING6(56=40+8+8 bytes) 2001:8b0:ff00:2:226:8ea:bea3:e9c5 --> 2a00:1450:8006::63
16 bytes from 2a00:1450:8006::63, icmp_seq=0 hlim=55 time=23.909 ms
16 bytes from 2a00:1450:8006::63, icmp_seq=1 hlim=55 time=23.401 ms
^C
--- ipv6.l.google.com ping6 statistics ---
2 packets transmitted, 2 packets received, 0.0% packet loss
round-trip min/avg/max/std-dev = 23.401/23.655/23.909/0.254 ms

Not exactly an early adopter, but hopefully that helps someone get started

Cheers
Pete

Rack diagrams in OmniGraffle

I needed to draw some rack diagrams in OmniGraffle, but it does not seem to support custom units. What I really want is a vertical scale of RU (1.75 inches) and a horizontal scale of inches (for a 19 inch rack).  Unfortuantely that appears to be a bridge to far, so I ended up with a grid of RU both vertically and horizontally.

To get something working, start with a new sheet. In the inspector, under Canvas: Size, set the Ruler units to inches (sigh..), and set the unit scale to 10 in = 73.5 in.

Canvas-size

Then in Canvas Grid, set the Major Grid Spacing to 1.75 in (1 RU), and the Minor Grid Steps to 1.

Canvas-grid

The end result is workable

Canvas

Here is a document that can be downloaded, and used as a preconfigured stating point.

19 inch rack

Cheers

Pete

Update from OmniGraffle Support

there’s no way to set the x and y grid separately, nor set ruler units to custom units in OmniGraffle. we do have a feature request for such though.  You might take a look at the following stencil for some aid in constructing rack diagrams.

<http://graffletopia.com/stencils/218>

More useful ping output

Sometimes its useful to have smarter output from a ping command. The things I needed were

  • 1 second intervals
  • the time the ping happened
  • how many pings since the last state change
  • the status

I have needed this on several occasions when doing redundancy testing, but it has always been more pressing to do the job, rather than write little scripts, but laziness got the better of me and it was time to make this little task a bit simpler. The result is a very simple ruby script.

#!/usr/bin/ruby
 
host=ARGV[0]
 
ping = `which ping`.chomp
args = " -c 1 -t 1 #{host}"
cmd = "#{ping} #{args}"
 
puts "#{cmd}"
 
`#{cmd}`
state = $?.to_i
newstate = state
count = 0
 
next_time=Time.now+1
 
while ( newstate == state )
      count = count + 1
        time = Time.now
        puts "at #{time.min}:#{time.sec}, count since change is: #{count}, and #{host} is: " + ( state.zero? ? "Up" : "Down")
 
        `#{cmd}`
        newstate = $?.to_i
        if ( newstate != state ) then
                count = 0
                state = newstate
        end
 
        pause = next_time-Time.now
        if pause > 0 then
          sleep pause
        end
 
        next_time=Time.now+1
end

The output is quite useful now

at 14:7, count since change is: 1, and 10.1.32.1 is: Up
at 14:8, count since change is: 2, and 10.1.32.1 is: Up
at 14:9, count since change is: 3, and 10.1.32.1 is: Up
at 14:10, count since change is: 4, and 10.1.32.1 is: Up
at 14:11, count since change is: 5, and 10.1.32.1 is: Up
at 14:12, count since change is: 6, and 10.1.32.1 is: Up
at 14:13, count since change is: 7, and 10.1.32.1 is: Up

There are probably loads of little things that could be changed to make it more useful or to provide better output, throw in any suggestions.

Cheers
Pete

full internet routes

I was playing around today with a BGP configuration that included the full internet routing table.  I struggled to find anywhere, details on what memory was required to hold the current internet route table so since I found out, I figured I would post it here

router#show ip bgp all sum
For address family: VPNv4 Unicast
BGP router identifier 10.1.1.1, local AS number 64512
BGP table version is 282628, main routing table version 282628
282317 network entries using 44041452 bytes of memory
282317 path entries using 19197556 bytes of memory
49377/49376 BGP path/bestpath attribute entries using 7307796 bytes of memory
44107 BGP AS-PATH entries using 1318438 bytes of memory
0 BGP route-map cache entries using 0 bytes of memory
0 BGP filter-list cache entries using 0 bytes of memory
BGP using 71865242 total bytes of memory
BGP activity 282339/22 prefixes, 282339/22 paths, scan interval 15 secs
Neighbor        V    AS MsgRcvd MsgSent   TblVer  InQ OutQ Up/Down  State/PfxRcd
x.x.x.x  4  1239   50806      89   282628    0    0 00:07:29   282317
router#

looks like 72MB of memory, for a total of 44k AS-PATH enteries.

Its not as big as I was expecting. The general recommendation seems to be 512MB of ram which is pretty standard on routers these days.

show ip route

is largely useless.