Monthly Archives: May 2010

Almost Time to Invest

On a related note, BP’s current share price of 42.95 might mean it’s almost time to pickup some of the company on the cheap.

The company has had a five year low of 35.15/share- it’ll be interesting to see how it opens on Tuesday given the failure of the Top Kill solution– I’d say depending on the feasibility of the next idea, if it gets into the low 30’s, it’s probably a good buy.

With the extra money, you can throw a really nice funeral for that part of you that dies.

Oil Makes People Forget

I recently made a trip to Seattle, and to nobodies surprise, the Deepwater Horizon Oil spill is all over the news- fed to the masses in a way only the US media can do.

When they first started talking about it, they referred to how it “could easily be the worst oil spill in history”- which is just an insane over-exaggeration of the facts- then they slowing started pulling that back, to “easily the worst spill in US history”, using the Exxon Valdez spill as a barometer for “badness”.

To put some perspective around this- the Exxon Valdez spill was 37,000 tonnes (~270,000 barrels), which is not even in the top 30 biggest oil spills on record, and it’s only the 3rd worst in US history. The worst on record, was the Gulf War oil spill at ~1,500,000 tonnes (~10,995,000 barrels of oil).

The current, most widely accepted flow rate for the Horizon Oil spill is ~12,000 to 19,000 barrels/day (so ~15,500 barrels / day, or ~2,114 tonnes /day)- which means there has been ~86,000 tonnes (~635,500 barrels) to date- which would make it the third worst in US history next to the Greenpoint Brooklyn and Hawaiian Patriot spills, and around the 20th worst on record in the world.

Obviously, all these numbers are estimates, but the point is, while it’s really really bad, and of course is something that needs to be stopped as soon as possible-  it’s happened before- it’s not new- it’s just the story of the moment, so people are instructed to be outraged right now- but people will lose interested and stop caring- especially if it takes until Aug to drill the relief wells.

Even better,  the Ixtoc spill 31 years ago, which btw- is the second biggest spill ever.

Humans Fail.

Automatic Dial Resource Fail-over in Asterisk

Asterisk is generally pretty reliable, but termination providers aren’t always so good; in a market where anybody can re-sell an upstream provider, or setup a few Asterisk boxes and start routing calls for people, it’s generally a good idea to have a “backup” provider (or three) to route your calls through.

You can easily setup an Asterisk system, to fail-over to secondary systems, if your primary provider fails for some reason- and this can all be done right in the dial plan, using a simple MACRO.

Add this MACRO to your dial plan:

[macro-direct-dial]
exten => s,1,Set(CALL_ATTEMPT=1)
exten => s,2,Set(TERM_PROVIDER=${TERM_PROVIDER1})
exten => s,3,Dial(${TERM_PROVIDER}/${ARG1},60)
exten => s,4,GotoIf($["${CALL_ATTEMPT}" >= "${MAX_PROVIDERS}"]?s-CANCEL,1)
exten => s,5,Set(CALL_ATTEMPT=$[${CALL_ATTEMPT} + 1])
exten => s,6,Goto(s-${DIALSTATUS},1)

exten => s-BUSY,1,Noop()
exten => s-NOANSWER,1,Noop()
exten => s-CANCEL,1,Hangup()
exten => s-HANGUP,1,Hangup()

exten => s-CHANUNAVAIL,1,Set(TERM_PROVIDER=${EVAL(${TERM_PROVIDER${CALL_ATTEMPT}})})
exten => s-CHANUNAVAIL,2,Goto(s,3)

exten => s-CONGESTION,1,Set(TERM_PROVIDER=${EVAL(${TERM_PROVIDER${CALL_ATTEMPT}})})
exten => s-CONGESTION,2,Goto(s,3)

Now you’ll need to route your calls into this MACRO; this can vary by dial plan, as you may have a special configuration for different area codes, or country codes, or based on some least-cost-routing business decisions, but a simple example would be something like this:

[default]
exten => _1NXXNXXXXXX,1,Answer()
exten => _1NXXNXXXXXX,2,Macro(direct-dial,${EXTEN})
exten => _1NXXNXXXXXX,3,Hangup()

This routes any NANPA numbers through the direct-dial MACRO above, passing in the phone number as the first argument to the MACRO.

Now, before this will work, you’ll need to configure some variables; this can be done in many places- in my working configuration, I have these variables dynamically generated via an AGI script, based on the phone number being dialed. This way I can control dial-groups, by phone number, based on a cost/preference/etc.

In this example, we’ll simply set these values in the globals section of the extensions.conf file:

[globals]
TERM_PROVIDER1 = SIP/first_provider
TERM_PROVIDER2 = IAX/second_provider
TERM_PROVIDER3 = SIP/last_provider
MAX_PROVIDERS = 3

So I’ve configured three fictitious termination providers; you can specify as many as you like, as long as the TERM_PROVIDER increments one for each, and you set the MAX_PROVIDERS value to the total number of providers listed.

This is obviously more useful if this list is automatically generated somehow, or changed based on the phone number being dialed, otherwise the retries could simply be hard-coded into the dial plan.

Now when you dial your number, it will start with the first (default) provider; if the dial() function returns a congestion or channel un-available error, the MACRO will cycle to the next provider, until it as gone through all of the providers listed.

Simple FreeBSD Tunnels

It’s pretty easy in FreeBSD to create simple tunnels between two FreeBSD machines, between a FreeBSD machine and a Cisco router, or to any other host that supports the GRE interface.

The GRE (Generic Routing Encapsulation) interface (defined in RFC 1701 and 1702) has been included for a while, and provides a “standard” encapsulation protocol for tunneling.

So lets assume first a host-to-host tunnel:

Host A:

External IP: 192.168.10.1
Tunnel IP: 10.255.255.1/30
Internal Block: 10.10.0.1/24

Host B:

External IP: 192.168.20.1
Tunnel IP: 10.255.255.2/30
Internal Block: 10.20.0.1/24

Obviously, in a real-world situation, the “External IP” value in your setup, would likely be a real, valid, routable IP address. Also, I like to use a “stub” host block for the tunnel IP addresses- this is basically a block of four IP’s (/30, 2 usable), that are simply used to route either end of the tunnel.

Yes, you can use an IP in the internal block as the tunnel interface, which means you wouldn’t need the extra routes to route the local blocks, but this can break OSPF, so it’s just good (maybe?) practice to keep the two blocks separate.

First off, you need to make sure the gre interface type is available; your kernel should be compiled with:

device gre

or, if you’ve built all the modules as loadable, you can add:

if_gre_load="YES"

to your /boot/loader.conf; you can then either reboot, or run:

host> /sbin/kldload /boot/kernel/if_gre.ko

Which should load the module.

Next, you need to configure the interfaces on both machines; this assumes you don’t already have a greN interface setup- if you do, then just use the next logical number instead of 0.

On Host A:

ifconfig gre0 create
ifconfig gre0 10.255.255.1 10.255.255.2 netmask 255.255.255.252
ifconfig gre0 tunnel 192.168.10.1 192.168.20.1

On Host B:

ifconfig gre0 create
ifconfig gre0 10.255.255.2 10.255.255.1 netmask 255.255.255.252
ifconfig gre0 tunnel 192.168.20.1 192.168.10.1

You can run ifconfig gre0 on each host, and the interface should show as UP. You can also confirm it’s up by pinging the other end of the tunnel from each host; so from Host A, ping the 10.255.255.2 IP address (which is the remote end of the tunnel):

hosta> ping -c 3 10.255.255.2
64 bytes from 10.255.255.2: icmp_seq=0 ttl=64 time=43.192 ms
64 bytes from 10.255.255.2: icmp_seq=1 ttl=64 time=51.099 ms
64 bytes from 10.255.255.2: icmp_seq=2 ttl=64 time=51.459 ms

--- 10.255.255.2 ping statistics ---
3 packets transmitted, 3 packets received, 0.0% packet loss
round-trip min/avg/max/stddev = 43.192/48.583/51.459/3.815 ms

Now you need to add routes for your internal blocks, so each end know to route over the tunnel:

On Host A:

route add 10.20.0.1/24 10.255.255.2

On Host B:

route add 10.10.0.1/24 10.255.255.1

Now don’t forget to add this config to your rc.conf files, so the interfaces get setup when the machines reboot:

On Host A:

cloned_interfaces="gre0"
ifconfig_gre0="inet 10.255.255.1 10.255.255.2 netmask 255.255.255.252 
tunnel 192.168.10.1 192.168.20.1"
static_routes="tunnel"
route_tunnel="10.20.0.1/24 10.255.255.2"

On Host B:

cloned_interfaces="gre0"
ifconfig_gre0="inet 10.255.255.2 10.255.255.1 netmask 255.255.255.252 
tunnel 192.168.20.1 192.168.10.1"
static_routes="tunnel"
route_tunnel="10.10.0.1/24 10.255.255.1"

(the ifconfig line was broken for display purposes; it should be one long line in you rc.conf file)

Now if your Host B in this scenario is not a FreeBSD box, but a Cisco device, the Cisco setup goes like this:

interface Tunnel0
  ip address 10.255.255.2 255.255.252
  tunnel mode gre
  tunnel source 192.168.20.1
  tunnel destination 192.168.10.1
!

ip route 10.10.0.1/24 255.255.255.0 10.255.255.2

Remember, this is just a simple encapsulation protocol, and not encryption- so data is not secure. Later, I’ll do an update which includes IPSEC on top of the GRE interface.