Hey UC Pros! The need to interoperate across organizational and logical borders with different numbering requirements exists since the very beginning of the digital telephony.
Whether you interconnect with a SIP ITSP or your own legacy PBX, you will likely need to manipulate digits you exchange on both ends.
In Cisco IOS (and IOS-XE later) running either CUBE or Voice Gateway, Voice Translation Rules and Profiles come to a play to help you get things done.
In this article, we are going to demonstrate how this powerful feature works in general and how it applies to most common interoperability scenarios in real UC world.
Let’s begin.
Build pro IOS configs. FAST.
Contents
Introduction to Cisco IOS Voice Translation Rules
Like many things in IOS, Voice translations mechanism uses a modular approach:
- voice translation-rule [rule-index] is an ordered set of translation rules.
- voice translation-profile [profile-name] is a container for voice translation-rule sets you to apply to your dialplan elements.
IOS voice translations engine is protocol agnostic. This means that you merely define the digit manipulations and apply it with a profile wherever you need. Then IOS deals with the actual signaling and headers rewriting on its own.
Configuring a voice translation-rule
You can add a voice translation-rule in a global configuration mode:
vg#conf t
vg(config)#voice translation-rule [rule-index]
Voice translation-rule is identified by a numeric index between 1 and 10737441823 (upper bound vary). Each voice translation-rule can contain up to 100 ordered rules of two types:
- Match and Replace Rule
This type of rule is used for digit manipulations.
Rule format:
rule precedence /match-pattern/ /replace-pattern/ [type {match-type replace-type} [plan {match-type replace-type}]]
- Reject Rule
This type of rules is used as a part of a side call-reject feature.
Rule format for your reference:
rule precedence reject /match-pattern/ [type match-type [plan match-type]]
Voice Translation Rules Regular Expression Syntax
Voice Translation Rule patterns use SED-like format and regular expression syntax with minor differences and limitations:
/match-pattern/ /replace-pattern/ — forward slashes are used as delimiters.
. — dot matches any single character. Valid characters are: digits from 0 to 9; letters A, B, C, D (in fact, these letters are valid DTMF tones); asterisk sign (‘*’); pound sign (‘#’).
– — hyphen denotes a range. For example, /1-3/ matches a single digit from 1 to 3.
[list] — square brackets denote a single character from a list between them. For example, /[123] also matches a single digit from 1 to 3. A list may contain a range: /[15-7]/ — this whole construction matches a single digit of 1 or 5 or 6 or 7.
^ — caret sign denotes the beginning of the string.
$ — dollar sign denotes an end of the string.
[^list] — caret inside the brackets negates the list. This means any character that is not on the list. /[^12]/ – this matches any single character that is not ‘1’ nor ‘2’.
() — round brackets denote a group of characters between them.
* — asterisk sign denotes zero or more occurrences of preceding character or group. /.*/ matches any string, including none.
+ — plus sign denotes one or more occurrences of preceding character or group. /.+/ matches any non-empty string.
? — question mark denotes zero or one occurrence of preceding character or group. /123?/ matches 12 and 123.
— backslash is an escape character. Any single character in a match pattern after a backslash is interpreted as a string. /+/ matches plus sign, /./ matches dot, /*/ matches asterisk and so on.
Combined, this allows you to manipulate number strings in a very tricky manner to achieve the desired output.
Let’s take a look at some generic examples to demonstrate the logic.
It is important to notice that the replace-pattern is applied to all occurrences of the match-pattern within the input string.
/4/ /77/ — this will replace any occurrence of 4 with 77. For ‘142434’, it would result ‘177277377’.
Whenever match position matters, use caret and dollar special characters.
/^.*/ /777/ — this would replace the whole variable length number by replace-pattern of ‘777’. For ‘142434’, it would result in ‘777’.
/^1234567$/ /777/ — this would replace a full string match of ‘1234567’ number by replace-pattern of ‘777’.
Group extraction with round brackets is another extremely helpful method. Anything between brackets in a match-pattern becomes a logical group. You can define multiple groups within your pattern. Each group can be called from replace pattern by its reference number which is basically a group position from left to right.
/^….(….)$/ /1/ — A match-pattern /^….(….)$/ defines an eight-digit number string. The last four digits are inside round brackets so that they form a group. This single group is referenced by 1 placeholder in replace-pattern afterward. This placeholder passes the content of the matched group to a replace-pattern resulting string. For ‘12345678’ number this would result ‘5678’.
/^(…).(….)$/ /12/— now we grouped first three digits into a group 1 and last four digits into a group 2. Replace-pattern puts group 1 and group 2. As a result, we cut off the fourth digit from the input string. For ’12345678’, it would result in ‘1235678’.
Another thing to mention is the Type of Number and Number Plan manipulation with translation rules. TON and NP are optional and only applicable to ISDN connections. Some telephony service providers can require these options to be set to specific values.
// // type any national plan isnd — empty match and replace patterns do not modify the number itself. Only TON is changed to ‘national’ and NP to ‘isdn’.
/^9(…….)$/ /1/ type any subscriber — this matches an eight-digit number starting with ‘9’. ‘9’ is then stripped, TON is set to ‘subscriber’, NP is unchanged.
Now we are ready to construct a rule set with a voice translation-rule.
Voice Translation Rule Matching
Rules inside a voice translation-rule set are ordered.
Input number string is compared with match-patterns of the rules from top to bottom until the first match.
The Replace-pattern of this first match rule is then applied to any occurrence of the match-pattern within the input string.
The remaining rules in the set are ignored.
No match on a defined rule set results no changes and rewrites.
So it is advised to put more specific patterns on top while leaving wildcard patterns on the bottom of the voice translation-rule.
Some examples:
voice translation-rule 100
rule 10 /^100$/ /1111/
rule 20 /^200$/ /2222/
rule 99 /^.*/ /9999/
Applying voice translations with translation-profiles
You can create a voice translation-profile in a global configuration mode. Any profile is identified by an alphanumeric name:
vg(config)#voice translation-profile [profile-name]
vg(config-tr-prof)#translate [number-type] [rule-index]
Inside the voice translation-profile, you can specify a translation-rule set for each number type from the following list:
- Calling Number
- Called Number
- Redirect Called Number
The first two types will typically be used in 99% of scenarios.
All the above can be referenced by synonyms terms in the documentation, specifications, and requirements.
Calling Number can also be called as a Calling Line ID (CLID) or as Automatic Number Identification (ANI).
Called Number can be called as Dialed Number Identification Service (DNIS) while Redirected Called Number can be called Redirected Dialed Number Identification Service (RDNIS).
Voice translation-rule set can be applied by its unique index.
You can use the same rule index for multiple number types within the single translation-profile if you need to.
You can only specify the number type(s) you actually need to modify.
Implicit ‘do nothing’ is applied to the rest. Any unspecified behavior results in no changes and rewrites.
voice translation-rule 100
rule 1 /^.*/ /100/
voice translation-rule 200
rule 1 /^.*/ /200/
voice translation-profile profilename translate calling 100 translate called 200
Where you can apply a voice translation profile
Basically, you can expect the translation profile to be applicable anywhere the digits are being exchanged:
Dial Peer
Dial Peers are the most common place to find a voice translation-profile applied. Direction matters. You can apply two voice translation profiles to each dial-peer — one for incoming and one for outgoing calls:
#dial-peer voice 100 voip
#translation-profile incoming [profile-name]
#translation-profile outgoing [profile-name]
It is allowed to use the same profile for both directions.
CME Ephone and Voice Register Pool
Voice translation-profiles are applicable to individual SCCP and SIP phone entities. This is helpful in cases when you need to provide some specific dialing behavior for some phones. Two profiles are allowed for each:
#translation-profile incoming [profile-name]
#translation-profile outgoing [profile-name]
Please note: incoming and outgoing direction makes sense from the router’s perspective in this case. Incoming direction applies to calls from the phone.
Outgoing direction applies to calls to the phone.
SRST call-manager-fallback and Voice Register Pool
For SRST, you can specify incoming and outgoing profiles on a global SRST configuration element.
Then the same logic applies to registered phones as for CME case.
This is helpful in cases when you have to preserve some user dialing habits while the fallback is active.
Voice Port, Trunk Group, NFAS Interface
For these POTS dialplan elements, you can assign voice translation-profiles for incoming and outgoing calls.
NFAS Interface translation profile has a higher precedence than a translation profile of its member voice port.
VoIP Incoming and Source IP Group
You can specify a translation profile for all incoming VoIP calls or for calls from specific IP addresses.
Specific Source IP Group translation profile setting has a higher precedence than a global VoIP Incoming translation profile settings for its member IP sources.
Usage Examples
Finally, let’s take a look at some real-world cases.
The most common scenario of translations usage is PSTN access.
Organizations typically use their own dialpans internally. Extension number format usually differs from E.164 PSTN global number format.
For outside dialing, some access prefix is used.
Furthermore, telephony provider requirements on number formats for calls to different destinations may vary.
To make it all operable, some translations have to be done.
Outgoing PSTN Calls
There are usually two aspects outgoing calls:
- Calling Number should be translated from internal format to some PSTN number allocated for you.
- Called Number should be translated to follow TSP dialing requirements.
Example:
An organization uses three-digit 1XX extension numbers on their Call Manager Express.
‘9’ prefix is used for PSTN access to avoid overlapping with the internal extensions.
They have a single PSTN number +1-555-9876543 and a SIP trunk with an ITSP.
ITSP requires that you place your calls with the following format of the called number:
- 7 digits for local calls.
- 10 digits for national calls.
- 11 digit for long-distance calls.
- variable length number prefixed by 011 for international calls.
ITSP requires that you send your calling number in a 10-digit format.
Let’s compose a basic configuration to follow those requirements.
!
voice translation-rule 91
rule 10 /^9(…….)$/ /1/
rule 20 /^9(..........)$/ /1/
rule 30 /^91(..........)$/ /11/
rule 40 /^9011(.*)$/ /0111/
!
voice translation-rule 92
rule 10 /^1..$/ /5559876543/
!
voice translation-profile pstn-out
translate called 91
translate calling 92
!
dial-peer voice 9 VoIP
translation-profile outgoing pstn-outgoing
destination pattern 9.T
!dialpeer configuration omitted
!
Incoming PSTN Calls
There are usually two aspects of incoming calls:
- Calling Number should be translated to allow a callback from the phone history. Usually, this means you should prepend your internal PSTN access code.
- Called Number should be translated to reach some internal destination. There are multiple options here. For instance, internal destination can be a regular extension or an IVR.
Example:
The organization from our previous example has an IVR on 199 pilot.
All incoming PSTN calls should go to the IVR.
For incoming calls, ITSP sends called number in 10-digit format (5559876543).
Calling numbers arrive from the ITSP in the following format:
- 7 digits for local calls.
- 10 digits for national calls.
- 11 digits for long-distance calls.
- Variable-length E.164 numbers for international calls.
Let’s build a configuration for that.
!
voice translation-rule 93
rule 10 /^(.......)$/ /91/
rule 20 /^(..........)$/ /91/
rule 30 /^(1..........)$/ /91/
rule 30 /^+(.*)$/ /90111/
!
voice translation-rule 94
rule 10 /^5559876543$/ /199/
!
voice translation-profile pstn-in
translate called 93
translate calling 94
!
dial-peer voice 5559876543 VoIP
translation-profile incoming pstn-in
incoming called-number 5559876543
!dialpeer configuration omitted
!
That should be enough to start receiving and sending PSTN calls in terms of numbering consistency in a given scenario.
Troubleshooting Cisco Voice Translation Rules
Finally, let’s discuss how to troubleshoot voice translations.
Our toolset looks as follows:
Test Tool
This tool allows you to verify the result of the voice translation-rule work on various input numbers.
It is available in exec mode:
#test voice translation-rule [rule-index] [input-number]
Some usage examples for the rules we previously configured:
This is what rule 91 will result for ‘92345678’ dial string:
#test voice translation-rule 91 92345678
Matched with rule 10
Original number: 92345678 Translated number: 2345678
Original number type: none Translated number type: none
Original number plan: none Translated number plan: none
‘9’ prefix is stripped as expected.
You can see both original and translated numbers in the output, and also rule precedence (10 in this case) inside the translation-rule which effectively matches and applies.
This is what rule 92 will result for ‘123’ extension number:
#test voice translation-rule 92 123
Matched with rule 10
Original number: 123 Translated number: 5559876543
Original number type: none Translated number type: none
Original number plan: none Translated number plan: none
It is converted to ‘5559876543’ PSTN number as expected.
For ‘321’ it does not match any rule inside translation-rule 92 as we defined the match-rule as /^1..$/
#test voice translation-rule 92 321
321 Didn’t match with any of rules
Show Commands
show voice translation-rule [rule-index]
show voice translation-profile [profile-name]
show run
Debug Commands
debug voice translations
debug voip ccapi inout
debug ccsip messages
debug isdn q931
And other protocol-specific debugs.
Summary/Outro
We went through the most important aspects of IOS Voice Translation Rules and Profiles. Hope this helps in your studies and researches.
Feel free to comment on your questions, feedback, and observations.
Build pro IOS configs. FAST.
I have used this feature very well but have never seen it explained this way before. Very nice work 👍