Local Calls with Globalized Dial Plan in Cisco CUCM

Jeremy Worden
automate builders
Published in
4 min readSep 8, 2022

Cisco first introduced a Globalized Dial Plan Approach in Solution Reference Network Designs (SRND) version 12. This dial plan featured a way to implement simplified call routing based on globalized numbers, more common known as E.164 format. E.164 numbers are unique by definition and allow system administrators to have one dialing habit for their users. Calls can easily be defined as on-net and off-net. All off-net calls use an E.164 format beginning with a +. This greatly simplifies the amount of route patterns needed in a cluster. In most installations I’ve had a single NANP route pattern of \+!, which will route calls for any pattern that begins with the + character.

Figure 1: Variable length route pattern

Of course to achieve this, you need your users to give up local dialing. Users typically need to be re-trained to dial either full 10 digit or 11 digits to make all off-net calls. Otherwise you need to either have a large number of translation patterns per local area exchange to accommodate local dialing.

I’ve always wanted to come up with a creative way to have both. While playing around in my lab I found a solution via SIP Normalization. My lab deployment consist of a number of translation patterns that handle the conversion to E.164. Basically phones can dial translation patterns and the patterns translated up to E.164. Once translated the patterns can then access the route pattern. This insures that only numbers fully formatted to the E.164 standard can access off-net routes. Here is an example of my US National dialing patterns (NANP).

Figure 2: Translation patterns for NANP calls

Users dial 9 to get an outside line and then either the 10 digit or 11 digit number. The translation pattern adds either a +1 or just a plus (+) to the number and drops everything before the predot. It then sends the number off to the route pattern and away it goes. Every phone in the network has access to these patterns which is where the simplization comes from. No need to have individual patterns per site, at the cost of losing local dialing. But what if you could have a globalized local pattern, that could detect what the area exchange was of the phone that was dialing and add it to the outbound call? Let’s see if we can accomplish this via SIP Normalization. First let’s look at the translation pattern.

Figure 3: Translation pattern for local NANP calls

Looks familiar right? Basically is an even shorter version of the 10 digit pattern we used earlier. Just this time around we will need to add more than just a +1. In my lab I prepended a +1999 to all calls matching this translation pattern. Then my newly translated number (example: +19995551122) would be sent to my variable length route pattern (Figure 1).

NOTE: Having this shorter pattern will introduce some inter-digit timeout to the user. A couple options to mitigate this would be shorten the timer or remove the option to have 10 digit dialing.

In my lab the \+! route pattern sends the fully formatted E.164 number to a SIP trunk then off to Twilio. However before sending to Twilio the following LUA script is used to normalize calls matching the pattern of +1999XXXXXXX.

M ={}function M.outbound_INVITE(msg) -- Get the TO and FROM Header local from = msg:getHeader(“From”)
local to = msg:getHeader(“To”)
-- Find the start of the sip: string & extract areaExchange local dummy,userStart = string.find(from, “sip:”)
local areaExchange = string.sub(from, userStart+3, userStart+5)
-- Replace 999 in TO header with the extracted areaExchange
local newExchange = string.gsub(to,”999",areaExchange)
msg:modifyHeader(“To”, newExchange)
-- Update Request URI with new area exchange as well local method, ruri, ver = msg:getRequestLine()
local uri = string.gsub (ruri, “999”,areaExchange)
msg:setRequestUri(uri)
endreturn M

The script gathers the TO and FROM headers of the outbound SIP INVITE message. It then extracts the area exchange of both. If the TO header matches 999 the script will update it with the area exchange in the FROM header.

Example would be the following: User with number of +15035551212 dials, 95551213. Call Manager (CUCM) would match this to the local translation pattern shown above (Figure 3). CUCM would then drop the 9 off the dialed digits and replace it with +19995551213. This would then match the variable length route pattern (Figure 1) and head toward the SIP trunk. The SIP trunk would then apply the SIP normalization script and convert +19995551213 to +15035551213.

Neat huh?

Anyways hopefully this is useful to someone. You can download the script from Github.

If you would like to support my work and the time I put in creating the code, you can always buy me a coffee. I would really appreciate it (but is not required).

Thanks and enjoy!

--

--