Showing posts with label EV Best Practices. Show all posts
Showing posts with label EV Best Practices. Show all posts

Monday, February 24, 2020

The Complete Guide to Using UCDialplans.com for Microsoft Teams Direct Routing

Seasoned veterans of my dusty, long-dormant blog will remember I did a comprehensive post (in 2012! EIGHT YEARS AGO!!!!) on how to use the Lync Optimizer to automatically create dialplans for your Lync deployments. That guide is still useful for every on-prem version of Lync and Skype for Business since then.  I did a similar guide for Skype for Business Online in 2017 (a mere 3 years ago). With all the changes that Teams has brought (Direct Routing, and so much more!), I figure its about time I did an updated guide on how to use UCDialplans.com in Direct Routing scenarios.
Who could forget the 2012 Hoff masterpiece Piranha 3DD? I didn't know this existed until just now. I know what I'm watching tonight!

A Milestone

Another reason why I'm doing this now (February 2020) is because for the first time, the monthly total number of S4BOnline/Teams rulesets generated by UCDialplans.com has surpassed the number of S4B On-prem rulesets. This is an unofficial barometer of which platform is more popular for Enterprise Voice deployments. I could go on about how many S4B On-prem deployments are at a mature state and generally don't require many net-new dialplans compared to Teams where many are just starting to move their voice loads to it, but SEMANTICS! Just look at the chart!

Who should use this guide?

If you're on MS Teams and you are using Teams as your phone system, you'll be using it in one of two modes (or both in some cases):

If you're using Teams Direct Routing (using your own SBCs to provide dialtone), then you should definitely use this guide. It makes the entire process of creating voice routing policies, routes, PSTN usages etc. so much easier. If you are already confused by the above terms, then I HIGHLY recommend you use this tool.

If you're using Microsoft Phone System (where Microsoft is your telephony provider), then I suggest you read my blog post on Tenant Dialplans in Skype for Business Online. It will tell you why UCDialplans.com is still useful when your entire telephony infrastructure is managed by Microsoft. Even though it was written for SfBO, it still applies to Teams.

What can UCDialplans.com do for me?

In a Direct Routing environment, UCDialplans.com will automatically create the following:
  • Dialplans with normalization rules appropriate for your country, so users can dial phone numbers as they are accustomed.
  • Voice routing policies so you can selectively control who can dial locally, nationally and internationally.
  • Voice routes, which determine where calls are routed
  • PSTN usages, which are the glue between voice routing policies and voice routes
In a Microsoft Phone System environment, UCDialplans.com will automatically create the following:
  • Dialplans with normalization rules appropriate for your country, so users can dial phone numbers as they are accustomed.

What won't UCDialplans.com do for me?

If you're using Direct Routing, the "only" thing UCDialplans.com can't do is setup your SBC infrastructure and configure the link between Teams and your SBC. That has to be done prior to applying a UCDialplans.com script to your environment. Its not a small task, and could take you a while. Don't worry, I'll be here when you're ready. 

To get familiar with what's required, read the excellent documentation on Microsoft's site starting with the Overview, then Plan Direct Routing, followed by Configure Direct Routing, but stop when you get to the section listed Configure Voice Routing. This is the point where UCDialplans.com takes over.

Getting Started

For those using Direct Routing, I'm assuming you've already setup your SBC infrastructure and have paired your SBCs to your Office 365 tenant. UCDialplans.com PowerShell scripts will check for the existence of at least one SBC via Get-CsOnlinePSTNGateway. If one isn't found, then the script will stop after creating a dialplan.

Generate your customized dialplan script

Go to UCDialplans.com and sign in with a Microsoft account. Once validated, you will see the webform for creating your dialplan become visible.

  1. Select Microsoft Teams as your gateway type
  2. Select the country and city/region where your SBCs are located.
  3. Some countries require special prefixes/suffixes for certain phone calls. Enter any prefixes in the provided boxes.
  4. If your SBCs are connected to the PSTN via SIP trunk, select SIP Trunk. If you are connected via a legacy T1/E1/analog connection or you are required to send numbers formatted to the local number standards, select T1/E1/ISDN/Analog. NOTE: There is a bug in the Microsoft PS commands used to create outbound translation rules that limits rule length to 50 characters (every other PS command allows 1024 characters). This may have an adverse effect. 
  5. If you are connecting to a legacy PBX that requires adding a prefix to external numbers, enter one here. 
  6. Add up to 50 internal extension ranges. If it works for your deployment, add every extension range used across your deployment here. You will see why at the Assign internal dialing rules to the local or Global dialplan? question during script execution (see a few sections lower down for details).
  7. If you don't like the auto-generated rulename example shown, you can change it here. Note that you can only control what's in the middle of the rulename. The country name and ruletype are fixed.
  8. If you don't want to control who can make local/national/international calls, you can select Simple Ruleset. 
  9. If the ruleset is for a country where English isn't the first language, you can force English rulenames. It will also remove any non-English standard characters from city/region names and replace them with the English equivalent. 
  10. Once you're satisfied with the configuration, press GENERATE RULES
UCDialplans will start whipping its army of trained monkeys and in no time flat, you will have a customized PowerShell script ready for download.
Notice the Donate button? Not many people see this. :)

Click the DOWNLOAD RULESET HERE button, and save the script as a .PS1 somewhere on your system. You will probably have to unblock it to make it usable without prompting. Right-click the file and select Properties. Click Unblock, and then OK.



Backup your existing Teams EV config

If you've already got a functional Teams EV environment, I strongly suggest you backup your EV details, by downloading and running my suite of Teams Backup/Restore scripts. For more details, see this post, or go to Github to download the latest version directly.

Run the script via PowerShell

Open a PowerShell window, navigate to where the script is located and run the script. You might be blocked from running the script due to PowerShell policies. If this is the case, then run the following command from an elevated PowerShell prompt:
Set-ExecutionPolicy RemoteSigned
Or you can open your kimono and use Unrestricted in place of RemoteSigned.

Run the script from a PowerShell prompt. If you are not already signed into your Office365 tenant, you will be prompted for credentials. If your admin account is not in the same domain as your tenant (ie. uses an @tenantname.onmicrosoft.com address), then use the -OverrideAdminDomain switch.

You can also use the -PSTNGateway switch to enter the FQDNs of the SBCs you want to use. If using more than one, put them in quotes and separate by commas, like this .\US-Chicago-MSTeams.ps1 -PSTNGateway "GW1.contoso.com, GW2.contoso.com". If you're using Microsoft "Super Trunks", you'll need to use the -PSTNGateway switch because the script won't detect any PSTN gateways installed in your tenant.

When the script starts, you'll be presented with several questions:

Create global or user-level dialplan?

You can either assign the dialplan (which controls how users can dial phone numbers) to everyone by default via the Global dialplan or a user-level dialplan (the default selection). If the majority of your users are in the same location, you can use the Global dialplan, which requires one less step when enabling new users for voice. If you will be creating multiple dialplans, then its probably best to select User. The script will create normalization rules as desired.

Assign internal dialing rules to the local or Global dialplan?

If you entered extension ranges via the UCDialplans UI, you will be prompted with this question. If you say Global, the extension ranges you entered will be added to the Global tenant dialplan. This means that any new dialplans created in the future will add those normalization rules to the top. This takes advantage of an undocumented feature described in this post. If you don't want to take advantage of this, select Local.

Assign PSTN usages to Global Voice Policy?

A voice policy defines exactly what numbers a user can dial. You can use voice policies to allow only certain users to dial internationally, or set common-area phones to only dial local numbers (as examples). If you have a simple deployment where the majority of users will be assigned the same voice policy, you can set this globally by selecting either Local, National, or International. Local means that users will only be able to dial local numbers. National means they can dial any number within the country, and International has no restrictions.  If you do not assign anything at the global level, you will have to manually assign voice policies to all users.

Select primary/secondary PSTN gateway to apply routes

If there is a single PSTN gateway defined, the script will automatically use this for all defined routes. If there is more than one, the script will prompt you for which will be the primary gateway and which will be the secondary (if desired). This question will not be asked if you used the -PSTNGateway switch.

Configure voice policies for least-cost/failover routing

If the script detects the presence of existing voice policies created with UCDialplans, it will ask if you want to leverage least-cost/failover routing for these voice policies. If you say Yes, the script will assign the existing voice policies in a way that will route calls using the cheapest path possible, as well as ensure that calls can still work if the main PSTN gateways are down. See this post for more info (was written for Lync, but still applies to MS Teams)

Final Steps

Once done, you should have a fully functional voice infrastructure in MS Teams. If you didn't use the Global options for the dialplan and/or voice policy, you'll have to assign policies to your users. A simple example is as follows (assumes you're assigning to all EV-enabled users):
Get-CsOnlineUser | Where {$_.TenantDialplan -eq $NULL  -and $_.EnterpriseVoiceEnabled -eq $TRUE} | Grant-CsTenantDialPlan -PolicyName BR-SaoPaulo
Get-CsOnlineUser | Where {$_.VoiceRoutingPolicy -eq $NULL  -and $_.EnterpriseVoiceEnabled -eq $TRUE} | Grant-CsOnlineVoiceRoutingPolicy -PolicyName BR-SaoPaulo-National
It will take some time for these to take effect, and will probably require users to restart Teams at some point.

Oooops! I screwed up!

If you accidentally screw up applying a UCDialplans.com script and want to revert to a "clean" setup, you can run the following commands, which will wipe out all custom dialplans, voice policies etc. Don't run this if you've already got a working system.
Get-CsTenantDialPlan | Remove-CsTenantDialPlan
Get-CsOnlineVoiceRoute | Remove-CsOnlineVoiceRoute
Get-CsOnlineVoiceRoutingPolicy | Remove-CsOnlineVoiceRoutingPolicy
Set-CsOnlinePstnUsage Global -Usage $NULL
$GWList = Get-CsOnlinePSTNGateway
ForEach ($GW in $GWList) { Set-CsOnlinePSTNGateway -Identity $GW.FQDN -OutboundTeamsNumberTranslationRules $NULL -OutboundPSTNNumberTranslationRules $NULL -InboundTeamsNumberTranslationRules $NULL -InboundPSTNNumberTranslationRules $NULL }
Get-CsTeamsTranslationRule | Remove-CsTeamsTranslationRule 

Additional Tips and Tricks

UCDialplans.com scripts can be used for some interesting use-cases. For example, assume you're a company that has a single SIP trunk infrastructure that is homed in a single country. For this example, we'll assume its in Canada. Now also assume that you have some users in other countries such as the UK, that have Canadian numbers assigned to them. Those UK users would normally be forced to dial phone numbers as if they were in Canada, which is not something they would be used to.

In this case, you can generate a UK-based script from UCDialplans.com and run it against your deployment using the -DPOnly switch. This will force the script to only create a dialplan for the UK and it won't create extraneous routes/policies etc. You then assign the resulting UK-based dialplan to your UK users and they can dial numbers as they are accustomed to in the UK.




Sunday, February 9, 2020

Migrating SfB Enterprise Voice Configs to MS Teams

I'm flyyyyyyiiiing through the cloud.....get it? Cloud? Teams is in the cloud. Got it? Good.

The UCDialplans.com Winter of Code continues at a torrid pace!

Hot on the heels of the MS Teams EV Backup/Restore scripts is another script that I can't believe someone hasn't already cooked up.

Say that you have a well-oiled Skype for Business Enterprise Voice deployment that you carefully cultivated over the years into a perfectly tuned beast. You're considering migrating to Teams, but aren't terribly enthusiastic about having to recreate all that magic in Teams.

Well, worry no more! I've created a script that will copy all of your Skype for Business Enterprise Voice settings into MS Teams. It will handle the following:
  • SfB dialplans into Teams dialplans (along with all normalization rules, of course)
  • SfB PSTN usages into Teams PSTN usages
  • SfB voice routes into Teams voice routes
  • SfB voice policies into Teams voice routing policies
  • SfB trunk translation rules into Teams translation rules
  • SfB PSTN gateways into Teams PSTN gateways
Most of this is completely automatic, except for the PSTN gateway part. Teams PSTN gateways have to be publicly accessible via FQDN, and that FQDN's domain name has to be registered in the O365 tenant. Chances are pretty good that the SfB PSTN gateways won't conform to those requirements. The script will first look for an existing Teams gateway that matches each SfB gateway. If one isn't found, the user will be prompted to do one of the following:
  • match the SfB gateway to an existing Teams gateway with a different FQDN
  • create a new Teams gateway with the same FQDN as the SfB gateway (only works if the SfB gateway already meets the Teams FQDN requirements)
  • create an entirely new Teams gateway
  • don't match the SfB gateway
All this is presented to the user in a straightforward menu. Once all the selections are complete, the selected matches are shown before erasing any existing Teams EV configs and migrating the SfB EV configuration:

The usual trained monkeys will then migrate all the SfB EV settings to Teams, with a few caveats:
  • Since Teams doesn't have "sites", site-level SfB dialplans will be converted to user-level dialplans
  • Same deal with site-level voice policies
  • If there are duplicate translation rules, they will be merged into one, but translation rules with the same name, but different patterns/translations will be changed to include the PSTN gateway name to avoid conflicts.
If all goes well, the script should progress like this:

If you want to see more details around how the secret sauce is made, run the script with the -Verbose switch:


Once complete, your SfB Enterprise Voice config should be completely migrated to Teams. Check things over to be sure. If you elected to create Teams PSTN gateways, you will have to revisit them using Set-CsOnlinePSTNGateway to make sure they're configured correctly. 

Hopefully, this script will help make your transition to Teams that much simpler!

To get the script, go on over to my Github page to get the latest version. If you experience any issues, you can create an bug report through there.

https://github.com/kenlasko/SfBEV2TeamsEV


Tuesday, August 23, 2016

Lync/S4B Client Can Normalize Numbers with Plus Sign?!?!?

One of my central tenets of number normalization in Lync/Skype for Business has always been:
"Lync/Skype for Business will not attempt to normalize a number that already has a plus sign at the beginning"
There are signs that this is no longer true, at least for customers running Skype for Business Server 2015 and the Skype for Business 2016 client (and even the Lync 2010 client). I was messing around with normalization rules last night and realized that my Skype for Business 2016 client (version 16.0.7030.1021 32-bit) WAS normalizing numbers that started with a plus sign.  I later validated this with a Lync 2010 client against the same Skype for Business 2016 server.  And a commenter below said he's pretty sure he did this with Lync Server 2013.  So this means that either it has ALWAYS worked this way and I never realized it, or its something relatively new on the server-side.

I should clarify here and state that the normalization rule in question was specifically constructed to include a plus sign in the normalization pattern (as highlighted below):
^\+?(?:011)?(1|7|2[07]|3[0-46]|39\d|4[013-9]|5[1-8]|6[0-6]|8[1246]|9[0-58]|2[1-689]\d|3[578]\d|42|5[09]\d|6[789]\d|8[035789]\d|9[679]\d)(?:0)?(\d{6,14})(\D+\d+)?$
This DOES NOT mean that the Skype for Business client will suddenly normalize all numbers that start with a plus. If your normalization rules do not include a plus sign, it will not normalize a number with a plus sign.

This has all sorts of ramifications, all of them positive. That means that dealing with improperly formatted click-to-dial numbers in Internet Explorer is much simpler.  We can now fix this with a simple normalization rule, instead of doing it in a trunk translation rule or route.


This also means that dialing contact phone numbers from Outlook can also be much more reliable, especially if an extension is entered.  Before, if a user entered a contact phone number with an extension in Outlook using the "Phone number builder", it would format the number like "+1 (212) 555-1212 x 345".  If you clicked this number, Lync would parse the "x" as a "9" and the number would come out in Lync like "+121255512129345" and would likely fail.

I have no idea how long this new behaviour has been available.  It works on a Skype for Business Server 2015 environment with both Skype for Business 2016 clients and Lync 2010 clients.  I don't have a Lync 2013 or older environment to test with.  I tried to see if this behaviour extended to server-side normalization scenarios with no luck. I tried to change the destination phone number on an incoming call that started with a plus sign.  It didn't work, which implies that this is a client-only thing. The MSPL workaround is still required.

If this is only new to me, then I apologize for wasting everybody's time.  I've incorporated my new findings into the Lync Optimizer (as you would expect), because it does allow for several dialing scenarios to work better than before.

If anybody has any information on this or can test other versions of Lync server/client, drop me a line.

UPDATE (2016-Aug-24): Updated to clarify that a normalization rule has to explicitly look for a plus sign for this to work. Original post implied that any valid, matching normalization rule would be applied to a number that had a plus sign on the front.  Also made changes based on further observations with older clients.

Wednesday, August 10, 2016

North American Call Authorization Tricks

Almost every country in the world has a dedicated country code assigned to it for telephony purposes (see countrycode.org for a full list). There is one very large exception to this rule and that is countries in North America (US and Canada) and a good portion of the Caribbean.  These countries all share the same country code of +1 and are collectively part of the North American Numbering Plan (NANP), which is managed by the North American Numbering Plan Association (NANPA).

A NANP number consists of the country code +1, a 3-digit area code, and a 7-digit subscriber number, often formatted like +1 (212) 222-3333.  You'll sometimes see the +1 omitted from the number on business cards and websites that don't think globally.

Dialing numbers in North America is quite different from most places in the world.  In the rest of the world, if you want to dial a long-distance or national number, you have to dial a national access code.  In a lot of countries, this number is 0.  However, in NANP countries, you have to dial 1 for long-distance/national numbers. That's right, you have to dial the actual NANP country code as the long-distance access code, which is unique among all other countries.  Incidentally, the international access code is 011 (in many other countries, its 00).
"Connect me with the German Chancellor immediately! I have an idea for a new album!"
If you want to dial Canada from the US, or the US from Canada, or any of the Caribbean countries in NANP, you don't dial the international access code 011, you just dial the number as you would any other long-distance number.  So, if I want to dial Toronto, Canada from Vancouver, Canada I would dial +1 416 555 1111.  If I wanted to dial New York City from Vancouver, I'd dial +1 212 555 1111.

It gets even better.  NANP area codes are allocated by a trio of over-caffeinated spider monkeys who press numbers on a giant keypad at random to assign a new area code (well, that's how it appears).  There is no logical separation between area codes between any of the countries.  For example, area code 646 is in New York, USA, 647 is in Ontario, Canada, and 649 is in the Turks & Caicos (Caribbean island nation). Click here for a current list of area code allocations in NANP.

These days, calls between the US and Canada are often priced identically to a domestic long-distance call.  But calls to the NANP Caribbean countries are usually priced much higher, akin to dialing some very remote international destinations.  Continuing the previous example, a US user that has signed up for Microsoft's Skype for Business Online PSTN Calling Plan can expect to pay $0.013 per minute  (just over 1 cent a minute) to call area code 647 in Ontario, but would end up paying $0.583 (almost 45x more expensive) to $0.741 per minute to call area code 649 in the Turks & Caicos.

Since it is nigh impossible for a regular person to distinguish a Caribbean country from US/Canada based solely on the area code, it is easy for people to accidentally incur high phone charges when calling these countries.
He had an Apple watch long before anybody else. True trendsetter, even if it took 30 years.
Skype for Business administrators often want to prevent certain users from dialing these Caribbean countries, and it can be easily done with some fancy routing rules.  Assuming you've already configured voice polices for national and international access, then you just have to modify the National level voice route to block Caribbean destinations.  You could do some research to determine the Caribbean area codes, and create your own regular expression to block them, but I figure I should do SOMETHING useful with this post and provide you with that information.

This Skype for Business route number pattern will block all Caribbean countries that are part of NANP, except for the US Virgin Islands and Puerto Rico (which are often not priced much differently than US numbers, when calling from the US):
\+1(?!(24[26]|26[48]|284|345|441|473|649|664|721|758|767|784|8[024]9|86[89]|876|900|976))[2-9]\d\d[2-9]\d{6}$
If you want to also block US Virgin Islands and Puerto Rico, then use this one:
^\+1(?!(24[26]|26[48]|284|34[05]|441|473|649|664|721|758|767|78[47]|8[024]9|86[89]|876|900|939|976))[2-9]\d\d[2-9]\d{6}$
You may note that I've also made sure to exclude premium area codes like 900 and 976.

To make sure that people assigned an International voice policy can dial those Caribbean countries, your international route should include a pattern for North American numbers and look something like this:
^\+((1(?!(900|976))[2-9]\d\d[2-9]\d{6})|([2-9]\d{6,14}))$
If you REALLY wanted to get draconian and block calls to Canada from the US, and vice versa, you could use the following rules:

Block Canadian and Caribbean calls:
^\+1(?!(900|976))(20[^04]|21[^1]|22[4589]|23[149]|24[08]|25[12346]|26[0279]|27[026]|30[^06]|31[^1]|32[0135]|33[^2358]|34[067]|35[12]|36[01]|38[056]|40[^03]|41[^168]|42[345]|43[0245]|44[023]|47[0589]|48[04]|50[^06]|51[^149]|53[0149]|54[01]|55[19]|56[12347]|57[01345]|58[056]|60[^04]|61[^13]|62[03689]|63[016]|64[16]|65[017]|66[01279]|67[018]|68[124]|70[^059]|71[^01]|72[0457]|73[1247]|74[037]|75[47]|76[02359]|77[^1678]|78[1567]|80[^079]|81[^19]|83[012]|84[3578]|85[^1235]|86[02345]|87[028]|90[^025]|91[^1]|92[0589]|93[16789]|94[0179]|95[12469]|97[^4567]|98[0459]|281|458|469|520|828)[2-9]\d{6}$
Block American and Caribbean calls:
^\+1(?!(900|976))(41[68]|43[178]|51[49]|58[17]|70[59]|78[02]|90[25]|204|226|236|249|250|289|306|343|365|403|450|506|548|579|604|613|639|647|778|807|819|825|867|873)[2-9]\d{6}$
The above rules are formatted slightly differently from the ones that block Caribbean countries.  The Caribbean rules show which area codes to BLOCK.  The other rules show which area codes to ALLOW.  Of course, I didn't roll these rules by hand, since there are tens of dozens of area codes allocated to each country, and do change from time to time.   I used the super handy-dandy Lync Optimizer.  As you might expect, these options are available in the Lync Optimizer via the "Treat as National" option (only shows for North American dial rules).  You can select one of the following options with regards to dialing other countries within NANP:
  1. In-Country Only - Treat all calls to NANP countries other than your own as international, even though users don't have to dial 011 to reach them. As such, users will have to be a member of a voice policy that allows international dialing.
  2. US/Canada - Treat calls to anywhere in US/Canada as national calls, excluding the Caribbean. To dial Caribbean countries, users will have to be a member of a voice policy that allows international dialing. Not available for Caribbean rulesets.
  3. US/Canada/Caribbean - Treats calls to anywhere in NANPA (US/Canada/Caribbean) as national calls (along with the potentially higher call costs).

If you are creating a ruleset for a Caribbean country that uses +1 as the country code, you won't be able to select US/Canada, since this would make dialing within that Caribbean country difficult.

Selecting the Simple Ruleset option prevents usage of this feature, and will default to US/Canada/Caribbean. You won't be able to control how people dial other NANP countries when there is only a single simple routing rule.

So, there you go.  A lesson in the finer details of dialing numbers in North America that the rest of the world might not be aware of. Try to contain your excitement.

Tuesday, March 8, 2016

Dealing with Trunk Prefixes in Phone Numbers in Skype for Business

First of all, I spend far too much time thinking about dial rules.

For those who don't know, a trunk prefix is a number (or numbers) that typically has to be dialled prior to dialling a phone number within the subscriber's country, but outside the subscriber's home area code.  The trunk prefix is a way to signal the telephone network that the dialed number is a long-distance or national-level call.

For example, the trunk prefix for UK national calls is 0.  If I were sitting in Liverpool and wanted to dial someone in London, I would have to dial 0, then the area code for London (20), then the subscriber phone number (say 3456 7890).  For example, 02034567890.

Not every country uses a trunk prefix, but those that do generally use 0 as a trunk prefix. The actual national trunk prefix usage breakdown (based on my research) is below:
  • 101 countries don't use a trunk prefix at all
  • 95 countries use 0
  • 26 countries use 1 (these are countries that are part of NANPA, like US/Canada and many Caribbean countries)
  • Russia and 5 other former USSR states use 8
  • Mexico uses 01
  • Hungary uses 06

NANPA countries are unique in that the country code 1 is also used as a sort of trunk prefix for long-distance calls. Italy is another unique case in that they don't have a national trunk prefix, but they DO use 0 as the beginning of the area code, which can confuse people.

Trunk prefixes are NOT used outside of the country. Continuing my earlier example, dialling that same London, UK phone number from the US would start with my international call prefix (011), then the UK country code (44), the London area code (20), and finally the subscriber number (3456 7890), resulting in 011442034567890.  If that US person tried to insert the UK national call prefix in the number (0114402034567890), it would fail to connect because trunk prefixes are not used outside the home country.

Now, the UK user shouldn't be expected to know the international trunk prefix for countries other than his own, so when presenting their number on business cards, web pages or emails, they should use the internationally recognized standard for phone number presentation, which is (DRUMROLL)......E.164!!!!  Regular readers of my blog and anyone who knows Lync/Skype for Business should be intimately familiar with E.164 formatted numbers.  If you need a refresher, look back at a very old (from 2010!), but still useful blog post on the subject.

The UK user should present their number like this:
+44 20 3456 7890

However, in many cases the UK user presents their number with the trunk prefix, like this:
+44 (0) 20 3456 7890
or
+44 (0) 203 456 7890

People within the UK understand what the (0) represents, but people outside the UK would assume the 0 is part of the phone number and try to dial it as shown, resulting in call failure. This particular practice is very common in the UK, France and to a lesser extent, Australia. There are likely others (please let me know). Below are some screenshots from various webpages from GLOBAL companies that exhibit this problem:

Astra Zeneca

BAE Systems

Rolls Royce

Since this blog sadly only reaches a very small percentage of the world's population, there's no way I can expect everyone to get their act together and format their phone numbers properly.  Others have ranted about this exact practice before, and it hasn't seemed to help.

As you may be aware, when you're using Internet Explorer with the Skype for Business/Lync client plug-in, many phone numbers on web pages can be directly dialled by clicking the wee little Skype/Lync icon beside the phone number on the right.  You can see this on the Astra Zeneca and Rolls Royce page samples above. You can click those icons, and it will dial the phone number as its presented on the page.  Clicking the number for Astra Zeneca's media department will give you this:

This is not going to work for anybody, since the trunk prefix 0 will be dialled as part of the number and will fail. You might be thinking that you could write a normalization rule that could deal with this, but Lync/Skype for Business will not normalize a number that has a + in front, because it assumes that any number starting with a + is already normalized.  No matter what you do, a phone number that already has the + can't be modified at the source.

If you're anywhere other than the UK, your international routes probably aren't so strict that it would "know" that putting the UK trunk prefix in the number is wrong, so Lync/SfB will happily send the call on through, only to get dumped by your PSTN carrier as an invalid number.

What you CAN do, is create a trunk translation rule that will catch any instances where a 0 is immediately after the country code and strip it before sending it to the PSTN.  There are only a few countries where 0 is actually a part of the phone number (land line numbers in Italy and mobile numbers in the Republic of the Congo), so the regular expression we create can deal with this.

The below rule should work nicely:
Pattern: ^\+(1|7|2[07]|3[0-46]|39\d|4[013-9]|5[1-8]|6[0-6]|8[1246]|9[0-58]|2[1235689]\d|24[013-9]|242\d|3[578]\d|42|5[09]\d|6[789]\d|8[035789]\d|9[679]\d)(?:0)?(\d{6,14})(;ext=\d+)?$
Translation: +$1$2
The first part of the expression with all the digits is the regex for every possible country code in the world. The (?:0) means that if 0 is present immediately after the country code, it will be dropped. Then we accept anything from 6 to 14 other digits.  We separate out Italy (39\d), Republic of the Congo (242\d) to allow for 0 in the cases where they are allowed in those countries.

If you are located in a country that is guilty of the crime of not using E.164 formatted numbers everywhere (I'm looking at you, United Kingdom), then there is the additional step of modifying the appropriate voice routes to allow for numbers coming through the system with a 0 in the wrong spot.  Using UK's national route as an example:

Old route pattern: ^\+44(1[1-9]\d{7,8}|2[03489]\d{8}|3[0347]\d{8}|5[56]\d{8}|8((4[2-5]|70)\d{7}|45464\d))$
New route pattern: ^\+440?(1[1-9]\d{7,8}|2[03489]\d{8}|3[0347]\d{8}|5[56]\d{8}|8((4[2-5]|70)\d{7}|45464\d))$

Note the presence of the 0? after the +44, which indicates that 0 may or may not be present for the route pattern to match. As of right now, the Optimizer will create modified routes only for countries that I'm aware of that flaunt the E.164 rules on a regular basis:

  • UK
  • France
  • Australia

If there are others, please let me know, either directly or via blog comments.

All the above logic has been incorporated into the Lync/Skype4B Dialing Rule Optimizer, so if you are using that tool for creating your EV dialplans/routing, then you'll be covered.

Friday, May 1, 2015

Address Book Normalization in Skype for Business

A constant problem with Enterprise Voice in Lync is the fact that phone numbers stored in Active Directory often are not stored in the E.164 format that Lync requires for proper functionality.  If the numbers aren't recognizable, then the Lync client won't show phone numbers like office, mobile or home numbers to other users. The best thing to do is to update all phone numbers in AD to conform to E.164 standards, but this is often not practical for many reasons.

In Lync Server 2013 and older, you could use a special oddly named text file called the Company_Phone_Number_Normalization_Rules.txt to normalize AD phone numbers to E.164 standards as they are being added to the Lync Address Book.  This saved administrators a lot of work, especially when they are unable to change the core numbers in AD.  However, the fact that you had to create this text file and place it in a certain folder on every Lync server was not the most effective way to manage address book normalization.

Thankfully, things have changed in Skype for Business to finally make address book normalization part of a new suite of PowerShell commands, *-CsAddressBookNormalizationConfiguration and *-CsAddressBookNormalizationRule (where * is the typical Get, Set, New).  The Company_Phone_Number_Normalization_Rules.txt is no longer necessary and is ignored in Skype for Business.

When you first install Skype for Business, it is populated by a default set of address book normalization rules, which you can see by typing:
(Get-CsAddressBookNormalizationConfiguration).AddressBookNormalizationRules
You will get back the default set of rules stored in the Global config as below:
Description :
Pattern     : E164
Translation : null
Name        : Generic_E164
Description :
Pattern     : \++(\d+)[Xx]+(\d{1,15})
Translation : +$1;ext=$2
Name        : Generic_WithExtension
Description :
Pattern     : \++(\d+)ext[=]?(\d{1,15})
Translation : +$1;ext=$2
Name        : Generic_WithLongExtension
Description :
Pattern     : \++(\d+)EXT[=]?(\d{1,15})
Translation : +$1;ext=$2
Name        : Generic_WithLongExtensionUpper
Description :
Pattern     : \++(\d+)
Translation : +$1
Name        : Generic_All
In my opinion, these rules are not well-constructed.  Unless there is some hidden feature I'm not aware of, the E164 rule does absolutely nothing. (UPDATE 2015-Aug-13: Hany Elkady noted in the comments below that removing the E164 rule seemed to stop AD phone numbers already stored in E.164 format from appearing in the address book.  I personally haven't seen this occur but you might want to leave that rule in place.)  The other rules are oddly formatted. You can do the same in a much more flexible way with fewer rules. You can add/delete/modify rules to this by using:
 New/Remove/Set-CsAddressBookNormalizationRule
To start with a clean slate, you might want to get rid of the default rules, by running Get-CsAddressBookNormalizationRule | Where {$_.Name -ne 'Generic_E164'} | Remove-CsAddressBookNormalizationRule.

For my typical North American address book file, I add the following rules (assumes North American numbers are stored as either 10 or 11 digits without the +):
New-CsAddressBookNormalizationRule -Parent Global -Name 'NANPA-10-Digit' -Pattern '1?([2-9]\d{9})' -Translation '+1$1' -Priority 0
New-CsAddressBookNormalizationRule -Parent Global -Name 'NANPA-10-Digit-Ext' -Pattern '1?([2-9]\d{9})\D+(\d+)' -Translation '+1$1;ext=$2' -Priority 1
For a more global approach, you might use something like:
New-CsAddressBookNormalizationRule -Parent Global -Name 'Global' -Pattern '((1[2-9]\d\d[2-9]\d{6})|([2-9]\d{6,14}))' -Translation '+$1' -Priority 0 
New-CsAddressBookNormalizationRule -Parent Global -Name 'Global-Ext' -Pattern '((1[2-9]\d\d[2-9]\d{6})|([2-9]\d{6,14}))\D+(\d+)' -Translation '+$1;ext=$2' -Priority 1
The rules you add will be determined by the format phone numbers are stored in Active Directory. It appears that the normalization rule engine hasn't changed since the older versions of Lync, which means that you will still have to enter your normalization rules exactly as you did with the old Company_Phone_Number_Normalization_Rules.txt.

As with older versions of Lync, you can force an update of the address book by running Update-CsAddressBook.  Any phone numbers that aren't normalized are stored in the Invalid_AD_Phone_Numbers.txt file in your address book share under \x-WebServices-x\ABFiles\00000000-0000-0000-0000-000000000000\00000000-0000-0000-0000-000000000000.

You can import existing rules from the Company_Phone_Number_Normalization_Rules.txt file by using the command Import-CsCompanyPhoneNormalizationRules.  The RTM upgrade process really should take care of this for you, but it doesn't appear to (at least for me, but I first did Skype for Business months ago).

With this post, I hope to never again have to type the oh-so-memorable filename Company_Phone_Number_Normalization_Rules.txt.


Tuesday, October 7, 2014

Lync Enterprise Voice Misconceptions #3 - Inter-trunk Routing

During my travels across the Lync Enterprise Voice landscape, I come across numerous Lync deployments that make some fundamental mistakes in how to manage phone numbers, call routing and other details.  I've covered a lot of these details in parts of my OTHER Enterprise Voice Best Practices, but its obviously a lot to take in, and I've seen enough of the same sort of errors in the wild that prompted me to do this series.

Last week's episode talked about how to properly use the external access prefix in Lync. This week, we're talking about...

#3 - Inter-Trunk Routing

If you've ever manually created trunk translation rules for a PSTN gateway in Lync, you've probably noticed the "Associated PSTN Usages" section.


The wording is vague, and even Technet's description of the setting doesn't tell you much.


From what I've seen in multiple deployments, people tend to add the PSTN Usages that were created specifically for the particular trunk, which sort of makes sense if you use Technet's description as your only guide.

Some other places on the Internet take this idea even further, and imply that this section is used to define the PSTN usages that are allowed to use the specified trunk. If you think about it, you already accomplish this by defining the PSTN Usage/route combination without having to do anything else, so that can't be right either.

Now, you might be aware that Microsoft mentions in their Technet planning documentation that Lync can do "inter-trunk routing".  From their own documentation:
This new capability enables Lync Server to provide call control functionalities to downstream telephony systems. Intertrunk routing can interconnect an IP-PBX to a public switched telephone network (PSTN) gateway so that calls from a private branch exchange (PBX) phone can be routed to the PSTN, and incoming PSTN calls can be routed to a PBX phone. Similarly, Lync Server can interconnect two or more IP-PBX systems so that calls can be placed and received between PBX phones from the different IP-PBX systems.

In more general terms, Lync can pass inbound phone calls on to a different destination, which could be another PBX system or even back out to the PSTN.  So, now you're thinking "That's a great feature, but what does this have to do with Associated PSTN Usages?"  Since the title of this article says "Inter-Trunk Routing", it should dawn on you that "Associated PSTN Usages" has something to do with inter-trunk routing.  If it doesn't, then lie down a while and come back after a good nap.

As you hopefully have surmised by now, inter-trunk routing is done using "Associated PSTN Usages" from within a trunk.  The details behind how to do this are helpfully discussed in some of my own blog posts, Technet and also those by fellow Lync MVP Richard Brynteson:
http://ucken.blogspot.com/2013/06/inter-trunk-routing-in-lync-2013.html
http://masteringlync.com/2013/06/07/inter-trunk-routing-deep-dive/
http://technet.microsoft.com/en-us/library/gg425831.aspx

To summarize those blog posts, if an incoming call from a trunk can't be routed to an internal user, it will attempt to route the call to an alternate trunk, if there is a matching PSTN Usage/route combination assigned to the incoming trunk.

When people add the PSTN usages to a trunk that are already assigned to that very same trunk, incoming calls could potentially be sent back out the same way they came in, if there isn't a matching user in Lync. This could result in odd behaviour, including calls bouncing back and forth between a PBX and Lync, in what I call the "Telecom Routing Donut of Doom".  Fortunately, in most cases, adding PSTN usages to the trunk has no effect, since there is almost always a Lync user assigned to the incoming phone numbers.

I've seen numerous deployments where they've added PSTN usages willy-nilly (my Word-of-the-Day calendar entry for today).  If I see those, my next question is "Oh, so you're using inter-trunk routing."  If the reply I get back is some variation of  "What's inter-trunk routing?", then I remove those PSTN usages from the trunk configuration.

There you have it.  Tune in next time (not necessarily next week, since I'm bad at reading calendars) where we talk about something else that I haven't quite figured out yet.

Thursday, September 25, 2014

Lync Enterprise Voice Misconceptions #2 - External Access Prefixes

During my travels across the Lync Enterprise Voice landscape, I come across numerous Lync deployments that make some fundamental mistakes in how to manage phone numbers, call routing and other details.  I've covered a lot of these details in parts of my OTHER Enterprise Voice Best Practices, but its obviously a lot to take in, and I've seen enough of the same sort of errors in the wild that prompted me to do this series.

Last week's episode talked about common errors when setting up resiliency/failover routing. This week, we're talking about...

#2 - External Access Prefixes

A lasting legacy of the PBX era is the concept of dialing an external access prefix to make a call to the outside world.  In many deployments, you have to dial a 9 or 8 or something to open a channel to the PSTN.  In some systems, when you press 9 (or whatever the prefix is, I'm going to assume the external access prefix is 9 throughout this article), you can hear the change in dial tone as you actually open a connection to the PSTN.

There are many reasons for using an external access prefix, one of the biggest is to provide a clear demarcation between internal and external calls. When dialing "off-hook" - meaning the user picks up the handset, hears a dialtone then starts dialing the number on the keypad - the PBX needs to know where to send the call based on the digits entered on the keypad.  This might sound obvious, but if you've punched in the digits 2-1-2-3, the PBX needs to know if you want to connect to someone at extension 2123, or if you're just in the process of dialing an external New York number that happens to start with 2123.  If you punched in 2123 and meant to reach extension 2123, then the PBX will connect your call to that extension and everybody's happy. But if you meant to dial New York number 2123334444, then you will be understandably frustrated that you were connected to extension 2123 instead.

The external access prefix deals with this issue in a neat and tidy way. When you dial off-hook, if you enter the external access prefix before dialing your number, then the PBX will not attempt to connect you to an internal extension as you punch in digits.  So, when you dial 92123, the PBX won't attempt to route your call to extension 2123, and will instead wait for the user to enter the remaining digits necessary to complete a call on the PSTN.

In many Lync Enterprise Voice deployments, Lync is connected to the PSTN through an existing PBX which gives Lync both access to the PSTN as well as phones on the PBX. Since Lync's PSTN access is via the PBX, then this means that calls that come from Lync usually needs to have the PBX's external access prefix added in front of PSTN-bound calls.

I've seen many deployments where administrators do one of two things:
  1. They normalize dialed numbers in Lync to include the 9
  2. They create a normalization rule where users have to dial 9, but they strip it out, leaving a properly formatted E.164 number, using a rule like ^9(\d{10})$ --> +1$1. They then add the 9 using a trunk translation rule before sending to the PBX.
With #1, this breaks Ken's universal E.164 rule, which states: "NORMALIZE EVERY NUMBER TO E.164!!!"  If you don't know what E.164 is, I recommend you check out this post on the topic.  For example, if your normalized number for our earlier example is +912123334444, that number is technically a phone number in Chinchwad, India (which incidentally is now on my list of funny-sounding place names).  91 is the country code for India, and 212 is the area code for Chinchwad.

The ramifications of choosing this path is that you have to adjust everything else in Lync to accommodate what you started with adding the 9 to all normalized numbers.  This means routes, and even phone numbers in Active Directory.  You may argue that this is OK for you, because you have a single site, and you don't have any need to call India. But AD phone numbers can populate users' contact lists on their mobile phones, and they most certainly don't want to be dialing India when they mean to call New York. You could do some additional work to deal with this situation, but it gets messy very fast and doesn't scale beyond a single site.  For example, what if you have a second site that doesn't use 9 for dialing externally?  If you have to route calls from the first site for redundancy, then you'd have to make all sorts of rules in Site B to deal with how you initially set things up in Site A.  As you add sites, this scheme would quickly become unmanageable. 

Case #2 is closer to the correct way to do things. Dialed numbers are ultimately formatted to E.164 standards which is good. Since the PBX ultimately requires numbers are prepended with a 9, we can do this with trunk translation rules. Its trivial to add a 9 to every call that routes out to the PBX. However, you shouldn't have to manually create normalization rules that force users to enter a 9.  If you recall from the beginning of this article, the external access prefix is meant to help people who do off-hook dialing. When dialing from the Lync softclient, there is no off-hook dialing.  You enter the digits, then you press the call button, or ENTER or whatever. Entering a 9 is superfluous in those cases.  However, you do want to ensure a good experience when people do off-hook dialing from a Lync desk phone. How do you support on-hook and off-hook dialing without forcing EVERYONE to enter an external access prefix in Lync?  Use the External Access Prefix option in the Lync dial plan, as shown below.   

This option does several things, firstly it allows people to dial phone numbers in Lync the same way they're accustomed to on the PBX without having to adjust normalization rules.  It also makes Lync work the same way a PBX phone works when dialing off-hook.  The kicker is that you're not forced to enter a 9 when dialing. You either enter a 9 when dialing from the Lync softclient, or you don't. Either way, the call goes through as expected. Same thing for the Lync deskphone. You're not forced to enter a 9, but if you habitually dial off-hook, then you'll want to, or you'll stand a good chance of reaching an internal extension instead of the PSTN number you dialed. 

Rather than rehash what's been said before, have a read of one of my blog posts from waaay back in Lync 2010 days on this topic (don't worry, things haven't changed since then).  It shows how to set your Lync deployment up for extension dialing and external access prefixes the no-muss, no-fuss way. It also shows some examples on how the Lync softclient behaves when using an external access prefix.

You can use this in pure Lync Enterprise Voice deployments, or when integrated with an existing PBX.  In cases where you connect to a PBX, you still have to create a trunk translation rule to add the 9, if necessary. For more information on trunk translation rules, you can read my blog post on the subject, or refer to Technet

Tune in next week, where we talk about inter-trunk routing, and how people inadvertently set it up without meaning to.

Wednesday, September 17, 2014

Lync Enterprise Voice Misconceptions #1 - Failover Routing

During my travels across the Lync Enterprise Voice landscape, I come across numerous Lync deployments that make some fundamental mistakes in how to manage phone numbers, call routing and other details.  They're always fixed by the end of the engagement, but I'd like to share some of these to help keep others from making the same mistakes.  This will be an ongoing series of unknown duration.

#1 - Failover/Resiliency Routing

This is one of the more misunderstood concepts in Lync Enterprise Voice. Its a question that often trips people up on the Lync Voice exam (70-337), and is something that even respected websites like Windows IT Pro gets wrong (despite my attempts to get them to correct it).

The idea behind failover or resiliency routing is that you want to use a particular PSTN gateway for your normal day-to-day call routing, but have a backup PSTN trunk ready in case the primary one is down. This is different from load-balanced routing, where your goal is to evenly spread call traffic between two or more trunks.

For example, say you have a Lync deployment in your Boston office and another one in your Seattle office.  For reasons that should be obvious, you want to ensure that your Boston users always use the Boston PSTN gateway for outbound calls to reduce WAN traffic and call latency. If the Boston trunk is down, calls should failover to the Seattle PSTN trunk.  The same goes for your Seattle users. We could make things more interesting by bringing least-cost routing into play, but we're going to keep it simple here.

A common error people make in an attempt to make things simple and easier to manage is to create a single route for all calls, and place both the Boston and Seattle trunks inside that route.  Since they added the Boston trunk first, it appears first in the list, and they are lulled into thinking that calls will always use the Boston trunk unless its down, at which point the Seattle trunk is used.

In actual fact, calls will load-balance themselves between the Boston and Seattle trunks. Sure, if Boston is down, all calls will route via Seattle, but any well-designed EV deployment should never needlessly send calls across the country on the corporate WAN unless absolutely necessary.  If your other site is in a different country, you could be left with some pretty high phone bills since half of your national calls will be routed out the other country's gateway as an international call.

Voice Policy
PSTN Usage
Route
Trunks
Global
AllCalls
AllCalls
BostonGW
SeattleGW


A clue to this behaviour can be found when you look at a route in the Control Panel.  You'll notice that while you can add/remove trunks to a route, there is no way to change the order of the trunks. This should be a clue to the fact that you have no control over which trunk is used within a route.


The proper way to achieve failover routing is via PSTN Usage ordering. Instead of creating a single route with multiple gateways inside it, you create a Boston PSTN Usage with a route to the Boston PSTN gateway, and another Seattle PSTN Usage with a route to the Seattle gateway.  In the voice policy assigned to your Boston users, add both the Boston and Seattle PSTN usages, ensuring the Boston one is above the Seattle one.  For your Seattle voice policy, put Seattle first.
Voice Policy
PSTN Usage
Route
Trunks
Boston
Boston-AllCalls
Boston-AllCalls
BostonGW
Seattle-AllCalls
Seattle-AllCalls
SeattleGW

Now, you have achieved true failover routing.  For Boston users, all calls will route out the Boston trunk, unless it is down.  The same thing works for your Seattle users.

Incidentally, putting multiple trunks  in a single route does have its uses. If you have multiple PSTN gateways within the same datacentre for redundancy, its OK to do things this way, since you usually don't really care which trunk is used for outbound calls. Calls will be load-balanced between all the trunks, skipping any gateways marked as down. The above picture shows exactly that situation (although its not obvious since most of the trunk name is truncated). However this should never be considered failover routing, simply round-robin or load-balanced routing.

Voice Policy
PSTN Usage
Route
Trunks
Boston
Boston-AllCalls
Boston-AllCalls
BostonGW1
BostonGW2
Seattle-AllCalls
Seattle-AllCalls
SeattleGW1
SeattleGW2

Essentially, you want to avoid placing trunks from different locations within the same route. This ensures you have control over how your calls are routed, keeping WAN utilization and costs low.

Tune in next week for our next exciting episode: "PBX External Access Prefixes"


Tuesday, June 4, 2013

Inter-trunk Routing in Lync 2013

Introduction - What is Inter-trunk Routing?

Inter-trunk routing is a new feature in Lync 2013 that allows Lync Server to be the central call processor for a multi-PBX deployment.  In previous versions, Lync was only capable of being the final destination for phone calls.  If an inbound phone call couldn't be matched to a Lync user, the call would fail.  There was no way to have Lync forward calls on to another PBX, which limited the configuration options available to administrators.

Inter-trunk routing gives Lync administrators the ability to take calls in from a variety of sources and forward them on to other non-Lync destinations if there isn't a matching Lync user with the target phone number. 

The Problem

Recently, I had to deploy inter-trunk routing for a Lync deployment that had calls coming in from a variety of sources to a centralized Lync Server 2013 Enterprise Edition deployment:
  • a Lync-certified SIP trunk
  • a Canada-based T1 line connected to a PSTN gateway
  • two US-based Mitel PBXs. 
The inter-trunk routing requirements were very specific: forward four phone numbers entering Lync from the SIP trunk to one of the US-based PBXs.  The four phone numbers were +1 (289) 555-3926, +1 (289) 555-6733, +1 (289) 555-6734 and +1 (289) 555-6780.

The Solution

Having never done Lync inter-trunk routing, I turned to the trusty Internet for answers.  I found lots of information on WHAT Lync inter-trunk routing was all about, but almost nothing on exactly HOW to configure inter-trunk routing in Lync.  I saw references to assigning PSTN usages to trunks, and saw the place in the Lync Control Panel to add it, but nothing but vague allusions to the process of actually implementing it.

UPDATE 10-June-2013: Richard Brynteson posted a more knowledgable deep-dive into inter-trunk routing mere days after I posted this. I made a slight adjustment to my process based on what I read in his blog, so its definitely worth reading.

As usual, when I come across such a situation, I assume that it must be so simple to configure that it didn't occur to anyone to actually document the HOW.  I then assume I must be a complete idiot for not knowing something so plainly obvious to every other Lync administrator on the planet. So, after much flailing around, I figured out a solution that works using inter-trunk routing.

Since I wanted to route only four specific phone numbers between trunks, I needed to make sure that I enabled inter-trunk routing for those numbers and no others.  If I allowed inter-trunk routing for too wide a range of phone numbers, we could get into a situation where calls could enter Lync, pass onto the target PBX and route back into Lync, causing a call loop.  Rather than leave it to the target PBX to ensure a call loop doesn't happen, I figured it best to ensure Lync only pass the specific numbers to the PBX.

I started by editing the site-level voice policy attached to the Lync site where the incoming SIP trunk calls came into Lync.  I created a dedicated PSTN usage/route combination for those four numbers.  The PSTN usage was called NA-ON-Cooksville-289555-MitelForward to keep with the naming convention used by the Lync Dialing Rule Optimizer.  The route was called NA-ON-Cooksville-289555-MitelForward with a route pattern of ^\+1289555(3926|67(33|34|80))$ pointing to the PBX at 1.1.1.1. 

The PSTN usage was placed at the very top of each voice policy's PSTN usage list to ensure that any Lync user that tries to dial those numbers will forward the calls to the desired PBX. For good measure, I also added the PSTN usage to the Global voice policy, although I'm not sure this is necessary.

Next, I assigned the new PSTN usage to the incoming SIP trunk under Trunk Configuration.  If the trunk doesn't exist, add it as a new pool trunk.  I then added a trunk for the PBX and added trunk translation rules to strip the number down to 5 digits, which is what the target PBX is expecting.

Once done, I committed the changes and waited a few minutes for the changes to bake to a nice golden brown.

The moment of truth came when I was able to call one of those four numbers and listen as Lync seamlessly passed the calls onto the Mitel PBX.  Great success!

Conclusion

I'd like to say it was my deep, Yoda-like knowledge of how call routing works in Lync that allowed me to think through the process of determining how inter-trunk routing works. Unfortunately, the truth is that I tried random combinations of things until I stumbled blindly onto the solution.  There's a reason why I chose that picture of the Hoff looking vacant and stunned at the same time as my avatar....it's how I look and feel much of the time.

To summarize the process:
  1. Create a PSTN usage/route combination that is specific to the phone numbers required to be forwarded to the PBX.
  2. Place the PSTN usage at the top of all voice policies to ensure that both inbound calls from the PSTN and calls made by internal Lync users are routed to the proper destination.
  3. Assign the PSTN usage to the incoming trunk.
When complete, the whole call process should function as follows:
  1. Inbound call comes into Lync via SIP trunk.
  2. Lync normalizes the number into an E.164 phone number
  3. Lync does a reverse number lookup to check for a Lync user with the same number
  4. If no match in Lync, then it looks for a matching usage/route assigned to a trunk
  5. When found, applies any outbound normalization rules and sends the call to the next hop
For a more detailed description on how the call flow will proceed, check out the Mastering Lync blog.  Richard Brynteson did a series on the nitty gritty details behind dialing behaviours in Lync. His post on Inter-trunk dialing is a deep-dive into the details that I don't get into here.

If there's anyone else out there trying to figure out how to implement Lync inter-trunk routing, I hope this helps figure things out.  As always, if you have any questions or can correct any misunderstanding I might have on the process, just leave a comment.

Monday, November 7, 2011

Migrating PBX Users to Lync Enterprise Voice

In all my previous blog entries about Lync Enterprise Voice Best Practices, I've assumed that the Lync deployments described are pure Lync.  There is no mention about connecting to legacy PBXs and how to best setup Lync to integrate with them.  Well, today is the day that we deal with that thorny issue.

Typically, there are two types of PBXs.  The oldest style are purely analog devices and are known in the industry as TDM PBXs.  TDM is short for Time Division Multiplexing - the old analog way of slicing up a telephony pipe to allow multiple calls.  Since Lync is not an analog phone system, you require an IP-PSTN gateway to communicate with TDM PBXs.  There are several gateway vendors out there that provide Lync-compatible gateways.  Some of my favourites include Audiocodes, Dialogic and NET.

The other type of PBX is called an IP-PBX, which is digital in nature and uses TCP/IP for its voice backbone.  Pretty much every PBX sold today is IP-based.  An IP-PBX may use SIP or other proprietary protocol for communications.  If the IP-PBX uses SIP, then there is a fairly good chance it can communicate directly with Lync over TCP/IP.  This is by no means a sure thing, because every vendor interprets the SIP standard differently, and this often means that two different SIP-based telephony systems can't communicate with each other.  In that case, you'll need to use an IP-PSTN gateway to bridge the two.  Even if you can get Lync to talk to the PBX for basic calls, you may encounter issues with transferring or forwarding, which is again due to the different ways that vendors interpret the SIP standard.

Connecting a PBX to Lync
There are two ways to connect an IP-PSTN gateway to a PBX. The most obvious way is to put the gateway behind the PBX (as shown below) connected via a T1 crossover cable. This is the lowest impact solution for the PBX side of things, but it can make routing calls to Lync difficult, because you will be relying on the capabilities of the PBX for such decisions. If you are not well-versed in the operation of the PBX, this will usually require the services of a PBX technician, which can cost both money and time. If you are working with a TDM-PBX, then you are also relying on the availability of a spare PRI card on the PBX. This may not be available due to limited expansion capabilities or availability of hardware.

This may be the only workable solution if your users are assigned extensions, rather than direct numbers (DIDs), because the gateway will always just see the main office number on inbound calls, and won't be able to tell if the call should go to Lync or the PBX.  Also, if you rely on an autoattendant for routing calls, you will need to route all calls to the PBX until you've migrated all users to Lync.

If your users all have DIDs or your PBX doesn't have any expansion slots available for an additional PRI card, then the more preferred solution is to place the IP-PSTN gateway in front of the PBX.  This requires 2 PRI interfaces on the gateway (or more if you have multiple lines coming in to the PBX).  Most gateways allow you to set the interfaces in pass-through mode, so that a failure in the gateway will just pass all calls through as if it weren't even there.

Now inbound routing logic is controlled by the gateway, which is much easier to manage than most PBXs.  Usually, you set a default rule for calls bound to the PBX, and insert rules to forward calls to Lync users as you see fit.  Many gateways provides Active Directory-based routing that can detect if the user is enabled in Lync and route calls accordingly.

Outbound routing from the PBX should be relatively easy as well.  In some cases, you would create a default rule that would route any extension that doesn't have an internal match out of the PBX, and the gateway will route the call to Lync.  Other cases may involve setting up forwarding on the internal extension to a pre-defined extension range, that then gets transferred to the gateway and on to Lync.


Setting Up Lync to Route Calls to a PBX
Once you've got the hardware setup, you need to connect Lync to the PBX or gateway.  This guide won't get into the details of setting up a specific gateway to work with an given PBX.  There are lots of those out there.  Once you've got a working connection, you need to define the IP address of the gateway in your Lync topology document.  You define the gateway under the PSTN gateways node of your Lync site.  A PSTN gateway needs to connect to a mediation pool, which is often collocated with the front-end Lync server role. 

As followers of this blog may know, I am a big proponent of e.164 formatting for phone numbers.  Ideally, all the phone numbers you define for Lync use - from the actual number assigned to an Enterprise Voice enabled user to the phone numbers listed in Active Directory - should be formatted in e.164 format.  If your users have DIDs, then this should be straightforward.  For users that only have extensions, you should use the format +<countrycode><officenumber>;ext=<extension>as explained in my blog post on Internal Extensions.  Resist the temptation to use only the extension as the user's phone number.

As you transition to Lync, you should allow your Lync users to dial others using the methods they are familiar with.  For most, this means dialing by extension.  You will want to allow extension dialing in Lync with the least amount of administrative overhead as you migrate users from the legacy system to Lync.

You achieve this by creating normalization rules that translate extensions to full e.164 phone numbers and outbound translation rules that turn e.164 phone numbers BACK into extensions.  An example with a company whose main number is +1 (212) 555-1111 that uses 3-digit extensions starting with 2 is below:

Normalization Rule: ^(2\d{2})$ --> +12125551111;ext=$1
Outbound Translation Rule: ^\+12125551111;ext=(2\d{2})$ --> $1

Sample scenario:
Dial 234 --> normalize to +12125551111;ext=234 --> strip to 234 --> send to PBX

You may wonder why go through the trouble of normalizing 3-digit extensions to e.164 when we just strip it back down to 3-digits at the gateway.  A long time ago, I evangelized the reasons why you should use e.164 formatting for your user phone numbers.  I won't rehash what was said there, but it suffices to say that e.164 formatting is the way to go in almost every situation.  So, using the above example with +1 (212) 555-1111 as the main office number, assign phone numbers to your Lync users like this:  tel:+12125551111;ext=201.  If a Lync user dials 201, it will normalize to the full e.164 format, find a match in its database and ring the user.

If someone dials an extension that doesn't yet exist in Lync, say 299, it will normalize to e.164, fail to find a match in its database, and then route it out to the PBX after stripping it back down to 3-digits. 

The Lync Dialing Rule Optimizer can help ease the workload involved in setting up this routing logic.  Simply select the Use Extensions checkbox (coming soon), and enter up to 10 extension ranges.  The Optimizer will take care of the rest, including proper ordering and placement of rules.

Migrating PBX Users to Lync
Following this generalized plan makes migrating users to Lync very simple:
  1. Enable user in Lync with the proper e.164 phone number.  Lync-initiated calls to their extension should now be intercepted by Lync.
  2. Depending on the layout of your legacy PBX, you may just need to simply delete the users extension, and PBX-initiated calls to that number should default to routing out to the gateway.  Other PBXs may require additional work to ensure calls to that specific user route to the gateway.
  3. Depending on the gateway, you may need to modify your PSTN-inbound rule to route inbound PSTN calls for that user to Lync.  As mentioned earlier, some gateways can detect the user is enabled on Lync and route the call accordingly.
The first few times I had to go through this exercise, it took me a while to wrap my head around what I now think is the best way to do things.  I hope this will help others get over some of the hurdles of deploying Enterprise Voice and do thing right the first time.

Links to my other posts in my Enterprise Voice Best Practices series:
E.164 Formatting
Normalization
Usages and Routes
Extensions