Monday, July 18, 2016

Using the Lync Optimizer to Configure a Single Multi-Country SIP Trunk

As SIP trunking becomes more reliable and trusted, companies are taking advantage of the ability to consolidate standard PSTN phone lines from multiple office locations into a single SIP trunk.  Most of the larger SIP providers can provide phone numbers for multiple countries, allowing for even further consolidation of telephony resources.

Skype for Business is very well suited to this sort of consolidation.  Typically, larger companies deploy large centralized Enterprise Edition pools in a few central datacentres that serve offices spread across entire continents.  These centralized pools in turn connect to a SIP trunk over a trusted, secure connection.

As mentioned, these SIP trunks can provide phone numbers for multiple countries, and price those calls as if they originated from those countries.  So, if a company has a SIP trunk in London, UK, they can give out phone numbers to other countries.  For example, users could have Germany-based phone numbers served out of the London SIP trunk, and calls from those numbers would be priced as if they originated from Germany. If a German user placed a call to another German phone number, they would be charged as a local or national call, even though the SIP trunk may physically reside outside of Germany.  Conversely, if that same German user called a London phone number, the call would be charged as an international call.

Setting up Skype for Business dial plans and voice policies in this situation can get tricky, but fortunately I've come up with a very clean and easy to execute plan on how this can be accomplished using the Lync (Skype) Dialing Rule Optimizer.

Let's use an example of a company with a central Skype for Business deployment in London, UK with a single SIP trunk assigned to that location.  This company has offices in the following locations:
  • London, UK
  • Berlin, Germany
  • Paris, France
All user phone numbers for all three locations are hosted out of the London SIP trunk.

The company has the following requirements:
  • Users must be able to dial as they are accustomed to in their respective country
  • Must be able to limit dialing for certain groups to the local, national or international level for their respective country
Let's assume this is a greenfield deployment, and nothing has been done yet in terms of Enterprise Voice configuration outside of getting the London SIP trunk connected to Skype for Business.

The first thing to do is to generate rulesets for each of the three locations using the Dialing Rule Optimizer.

First, London:

Then Berlin:

Note that I selected the "Force English Rulenames", which I did just because I can't read German or French and would prefer English rule names and descriptions throughout my Skype for Business deployment.

And finally Paris...

The resulting .PS1 rulesets are then copied to one of the Skype for Business servers. 

First, the London ruleset is applied to the deployment, creating user-level dial plans and voice policies when prompted.  When complete, there will be a single London dial plan and 3 voice policies. All routes use the single SIP trunk (as you would expect, since its the only one available).
Dial Plan page after running London ruleset
Voice Policy page after running London ruleset

In this state, we can easily assign a UK dial plan and voice policies to UK users as appropriate.

Next, run the rulesets for Berlin and Paris.  This is done for multiple reasons. Firstly, it will create German and French dial plans, so users in those countries can dial numbers as they do in those countries.  Secondly, it will allow administrators to assign country-specific local, national and international policies.  Someone assigned to a German national policy will only be able to dial phone numbers in Germany and nowhere else, regardless of the physical location of the SIP trunk.

When running the rulesets, make sure NOT to select the option to use least-cost routing. Least-cost routing only works with multiple SIP trunks from different providers. With a single SIP trunk, as in this example, implementing least-cost routing adds unnecessary PSTN usages to voice policies that ultimately don't accomplish anything.  If we make a call from a German number to London using a London route, the call will still be billed as an international call from Germany, as the SIP provider will see the German number as the source and bill accordingly.

To make things easier and faster to run, I recommend the use of the multiple PowerShell command-line switches available with rulesets.  It makes applying multiple rulesets faster and less prone to errors.  For the rulesets in this example, I used the following switches (using the Paris ruleset as an example):
 .\FR-Paris-Lync.ps1 -SiteID 1 -DialPlanType user -LeastCostRouting:$FALSE -OverwriteSiteVoicePolicy:$FALSE -LocationBasedRouting:$FALSE -PSTNGateway gatewayname -MediationPool mediationpoolname
For a full listing of the available command-line options, use the command:
Get-Help .\FR-Paris-Lync.ps1 -Full

Once done, the dial plans and voice policies will look as below.
Dial Plan page after running Berlin and Paris rulesets

Voice Policy page after running Berlin and Paris rulesets

This might seem more complicated than absolutely necessary, and you would be right. You could certainly just use London-based rules for all locations, but it would limit your options severely.

Setting up things in this way will allow users to dial numbers exactly as they do at home, and also allows administrators very granular control over dialing capabilities.  Common area phones in Paris can be limited to local dialing in Paris.  First level helpdesk employees in Germany can be limited to dialing only German numbers.

This shows how easy it is to use the Dialing Rule Optimizer to quickly setup flexible dial plans and voice policies in even the largest voice deployments.  If you have any questions about this method, please leave a comment.

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
+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, October 16, 2015

Capturing Network Traceroutes in Lync/Skype for Business

If you've ever trolled through the QoEMetrics database (a great way to while away a lazy Saturday afternoon) you may have come across a few tables that made you go "What the....?".  One table that might catch your eye is the TraceRoute table.  In all likelihood,  this table is probably empty, which might make you wonder what it's for.

Microsoft publishes pretty detailed information on the structure of the QoEMetrics database where you can find information about the TraceRoute table in this Technet article.

As you can surmise by the name, this table is meant to capture trace route information for calls. However, the table description gives no information on how to enable this feature.

You can enable this by adding a custom policy entry to a Lync/SfB client policy.  Custom policy entries are used to enable features that Microsoft has decided not to make too obvious for users for one reason or another.  If you've got custom policy entries, you'll see them at the top of the list when you run Get-CsClientPolicy.  If you have several of those, you can see it in a more readable format by typing (Get-CsClientPolicy policyname).PolicyEntry

The relevant policy entry for enabling tracerouting is called "EnableTraceRouteReporting", and you can add it to a client policy by running the following commands:
$x = New-CsClientPolicyEntry -Name "EnableTraceRouteReporting" -Value "TRUE"

$y = Get-CsClientPolicy -Identity policyname

Set-CsClientPolicy -Instance $y
Whoever has that policy applied to them will now publish trace route reports to the QoEMetrics database. However, the built-in Lync/SfB reports do not expose this anywhere, so you would only want to turn this setting on if you are using a 3rd party reporting and analytics tool such as Event Zero's UC Commander (FYI, if you don't already know, I work for them).

Sample screenshot of traceroute data as it appears in UC Commander

This can be very useful to help track down network issues in the call path. This won't necessarily point the finger at a specific switch or router in every circumstance, but it can help.

Be warned that enabling this will add a bit of size to your QoEMetrics database. The additional data isn't huge but its not negligible either.  You should carefully evaluate the impact before turning this on.

Monday, September 28, 2015

Response Groups Stop Responding

Our company (Event Zero - makers of the best Skype for Business analytics software out there BTW) relies on Skype for Business response groups for our sales and support queues.  Last week, I noticed that every single one of them on two separate pools were no longer accepting calls.  It wasn't a SIP trunk or mediation issue, because I couldn't get to them by directly entering in their SIP address in the Skype for Business client.  They appeared available (green presence) but would not accept calls. Snooper logs showed they were throwing 480 Temporarily Unavailable errors.

It was especially odd that it happened on two separate S4B pools at roughly the same time.  I tried numerous things, from restarting the RGS service on the affected servers to restarting the servers.  So, yeah, not a lot of tools in my RGS troubleshooting arsenal apparently.

What I found DID work, was to change the Tel URI of one of the workflows to a slightly different number, then changing it back.  Within a few minutes, that particular workflow started working again. 

Rather than doing the same thing to all 20-odd response groups (which would take a LOOONG time because the RGS Workflow web page is so slow), I created a Powershell script to do the same thing.

WARNING: Use script at your own risk. It worked fine for me, but hey I'm not a programmer. Also, this script will use the Description field of the workflow to store the original Tel URI of the response group.  Whatever is there now will get wiped out. You can do this script in other ways, but I was strapped for time and we weren't using the Description field for anything.
$Workflows = Get-CsRgsWorkflow 
Foreach ($WF in $Workflows)
 Write-Host "Adding dummy extension to " $WF.Name
 $WF.Description = $WF.LineURI
 $WF.LineURI = $WF.LineURI + ";ext=0"
 Set-CSRgsWorkflow -Instance $WF
Foreach ($WF in $Workflows)
 Write-Host "Reverting back to original number for " $WF.Name
 $WF.LineURI = $WF.Description
 Set-CSRgsWorkflow -Instance $WF

I don't know what caused the problem to start with, but at least this fixed it. Presumably, something happened to "break" the connection between RGS and the associated contact objects, and resetting the Tel URI re-linked them.

Hopefully, this might help others who come across the same thing. If anybody has any insight into why it broke, and why this fix worked, please enlighten me!

Friday, September 18, 2015

Testing Inbound PSTN Connectivity Directly from Lync/Skype for Business

File this one under "It's obvious once you think about it for even a second"...

I was recently attempting to get a SIP trunk working to a new Sonus gateway located in Event Zero's head office in Brisbane, Australia.  I wanted to test inbound calls to the gateway by calling one of our response group workflows.

Normally, I would pick up my mobile or home phone and dial the number to test, but since I was dialing Australia, and I'm a cheap bastard, I didn't want to do that.  It was also the middle of the night in Australia, so I couldn't get someone local to do it for me.  If I dialed the number from Skype for Business, then it would do a reverse-number lookup, find an internal match and route me to the response group internally without going through the PSTN, which wouldn't achieve my goal.

My goal was to route a call to our Australian response group via Skype for Business via the PSTN in the easiest, laziest, least-expensive-to-my-own-wallet way possible (this is sounding like an exam question).  Pick one of the following answers:
  1. Suck it up princess and eat the $2.05 it will cost to call Australia for a few seconds.
  2. Wake up someone in Australia at 2 in the morning, claiming its an emergency.
  3. Convince yourself that since outbound calls work fine, inbound should too.
  4. Use a trunk translation rule to route a dummy phone number to the correct destination.
  5. Give up and start drinking, because its Friday afternoon dammit!
The correct answer is #4 (although the judges will also accept #5).

If you've ever been at one of Doug Lawty's Enterprise Voice sessions at LyncConf or Ignite, you have probably seen his infamous diagram showing how a PSTN call works its way through the system.  To save you the pain, here the relevant details in a very small nutshell:
  1. Dialed number gets normalized to E.164
  2. Skype for Business does a reverse number lookup to see if there's an internal user or service that is assigned that number. 
  3. If there's a match, routes the call internally directly to the user/service.
  4. If there isn't an internal match, it finds a valid route through a PSTN trunk
  5. It applies any outbound number translation to make the number conform to local standards and sends it on its merry way out the gateway to the PSTN.
Since reverse number lookup happens before handing off the call to the routing engine, we can simply call a dummy PSTN number of our choosing, and once it reaches the trunk translation rule stage, change that dummy number back to the proper number assigned to the Response Group workflow.

In the above example, all I do is create a trunk translation rule to change the non-existent North American phone number +1 (555) 999-0000, and translate it to the proper number.  Once the call has progressed to the point where outbound translation is happening, Skype for Business won't be doing another reverse number lookup, so it will continue to route that number out to the PSTN, at which point it should route to the correct destination (which could be right back where it came from). 

So, a simple solution to overcome my unwillingness to waste money on stuff I don't have to.

Thursday, August 13, 2015

Selective Caller ID Blocking in Lync/Skype for Business

Once in a while, a customer asks how they can block caller ID on outgoing calls in Lync/Skype for Business. If they're interested in blocking caller ID on all calls, then the answer has always been simple: use the Alternate Caller ID field in Voice Routes.

Easy enough, right? But what if administrators want to give users the ability to selectively block caller ID at the individual call level?  When on the traditional PSTN, users in most places can enter a code prior to dialing the number if they want to block their caller ID.  In most North American markets, this code is usually *67.  So, a user could dial *6715552224444 and their caller ID would be blocked for that call.

In Lync/Skype for Business, you can replicate this functionality but it takes some work. Since the caller ID blocking feature is done at the route level, you will need to have a separate route for calls with an alternate caller ID.  For calls to use that route, you will need some unique signifier that would not occur in normal day-to-day dialing.

Since the caller ID block code you use on the PSTN should be unique, you can incorporate that into your dialplan, routes and trunk translation rules.  When I first tried this, I wanted to use *67 in my dialplan, but the Lync client didn't like the * so much. It threw up the virtual equivalent of giving me the finger and refused to work, so I had to go about it differently.  Thankfully, things have improved recently so that the Skype for Business client will happily accept the * (or # if you want).

My earlier version of this blog post simply put the *67 in front of the number and sent it through the system, stripping the *67 just before sending off to the PSTN.  Kevin Bingham from Cerium Networks suggested it might work by adding a custom parameter suffix, such as ;callerid=blocked (custom parameters are allowed by RFC3966).

So, after a bit of trial and error, I managed to make it work. This method is much nicer as it conforms to the standard RFCs and is fully E.164 compliant. Also, when someone types *67 and a number, it normalizes without showing the parameter suffix, which looks nicer to the user.

Here's a simplified example using the North American dialplan. First, you'll need a normalization rule in your dial plan that will accept the caller ID block code.
Pattern: ^\*67(\d{10})$
Translation Rule: +1$1;callerid=blocked

This will take any number that starts with *67 and is 10-digits long and translate it to +1 then the 10-digit number, followed by ;callerid=blocked. The client won't see this part of the normalization string.

Then you will need a special route that will accept numbers with that pattern and will apply the alternate caller ID:

Make sure you assign the appropriate PSTN gateway to the route and add the voice route to the appropriate PSTN Usages.

Finally, you will have to create a trunk translation rule on the selected trunk to strip the ;callerid=blocked from the dialed number before sending it out to the PSTN.

I've tested this using the latest Skype for Business server and client (as of August 2015), and the 5.4 firmware on a VVX 600 as well as a CX600 deskphone.  Let me know if this doesn't work on an older platform. I originally attempted this several years ago, and the Lync client (or server...can't recall), didn't deal with the *67 so well.

Incidentally, you might have issues with the alternate caller ID not being sent.  I've seen this on our own SIP provider.  Checking the SIP traces, I can see that I'm presenting the alternate caller ID as a P-Asserted-Identity, which is the way it should work, so my SIP provider seems to be ignoring it.

The example above used "callerid=blocked" as the custom parameter. You can name your custom parameter whatever you want as long as it is in lower case and uses the same format as ;parametername=value. Custom parameters have to also be placed after any ;ext= parameter.

As you might expect, I've incorporated this functionality into the Lync Optimizer.  Try it out and let me know how it works for you.

Wednesday, July 8, 2015

In-Call QoE Reports in Skype for Business

When a Lync or Skype for Business user is in a call, the client is continually capturing call quality data that is invaluable in helping diagnose call issues. There are lots of metrics that are recorded, like round-trip times, network jitter, packet loss and even things like "Insufficient CPU event ratio" that indicates the call quality was affected by a heavily loaded processor.

Prior to Skype for Business, all these call quality metrics were stored by the client until the end of the call, at which point it would send a summary report of this data via SIP.  This summary included minimum, maximums and averages for some metrics (such as round-trip times), and just an average for many others.  If you do a trace with OCSLogger, look for a SERVICE message after the final BYE message.  There will be one for each participant (assuming both users are in the same company). The SERVICE message body contains the quality report in XML format and looks something like this:
There's a LOT more than what I've shown here, but you get the idea
The Lync Server takes this information and sends it on to the monitoring database (QoEMetrics for those of you keeping track), at which point it's available for review.  It's because of this behaviour that you won't see any information about the call in Lync Monitoring Reports until the call is done.

For people who use Lync Monitoring Reports, having to wait for the end of the call before you see any data is a minor annoyance. For users of 3rd party tools such as Event Zero's UC Commander (full disclosure, I work for EZ), it's highly annoying. Tools such as UC Commander are able to see calls that are active at any given moment, which is great, but since the client holds the quality report tightly until the call is done, it is unable to provide much information about the call until the client sends off the report.  UC Commander makes sure to let you know this in a big red banner when you're looking at details on an active call (see below).

"Uh, yeah...I'm calling you about that.....accounting.....thing. It would be easier to explain in person."

Skype for Business changes things so that Skype for Business clients can report call quality while the call is active. You won't have to wait until the end of the call to see call quality data. The feature is off by default, but can be enabled via PowerShell using the following command:

Set-CsMediaConfiguration -Identity Global -EnableInCallQoS:$TRUE -InCallQoSIntervalSeconds x (where x is a digit from 1 to 65535).
You may have noticed the commands say QoS, when they really should say QoE. QoS is all about Quality of Service at the network layer, where QoE is Quality of Experience, which is what we're talking about here.  I flagged this during the beta, but was pretty much told to suck it up and live with it. 

Setting the interval to something like 1 second doesn't necessarily mean your network will be flooded with QoE reports every single second.  The client only sends this if there is a change detected.  So, in a stable network, you may not see many additional QoE reports. 

To turn this feature on, you require Skype for Business on the server-side, and the Office 2016 Skype for Business client (currently in beta at time of writing), NOT the Lync client with the Skype for Business UI patch.  I've heard that the Skype for Business patched version of Lync 2013 will eventually get this in a future patch.  Pretty much the only way to tell if you're running the Office 2016 version of Skype for Business is to look at the version number.  Patched Lync 2013 clients will have a version of 15.x.x.x, where the Office 2016 Skype for Business client will have a version of 16.x.x.x.

With this feature enabled, you can see call quality statistics while the call is active, which can be especially useful when the CEO is breathing down your neck complaining about the poor quality call he's on RIGHT THIS MINUTE.  Keep in mind that if you want to make good use of this, you have to use a 3rd party Skype for Business analytics tool that supports this feature, such as *cough cough* Event Zero's UC Commander.  

Thursday, June 18, 2015

Dealing with Overdialing in Lync/Skype for Business

If you've never heard the term "overdialing", you're not alone. I hadn't heard of the term either until Greig Sheridan mentioned the term to me one day. But after reading a few definitions on the web, I realized that I knew about it, but didn't know it had a name.  Granted, the definitions I found were all from Australian sites, so maybe its an Aussie thing. My Australian exposure has gone up dramatically since joining Event Zero back in February, so maybe it's to be expected, along with the increased incidents of me saying things like "mate", "throw another shrimp on the barbie", and "a dingo ate my baby."

Anyways..."overdialing" can be thought of as what happens when people try to dial a phone number with more digits than are actually allowed by the PSTN carrier.  This often pops up with numbers that are presented as words, like 1-800-BUYSTUFF, which has 1 too many digits/letters for the North American dial plan (all numbers are 11-digits long, including the 1).

A somewhat little known fact is that you can type the above example exactly like that in Lync/SfB and it will automagically translate the letters to the corresponding numbers and show the number 1-800-289-78333.  Again, notice its got one too many digits and hasn't normalized (note the lack of + sign at the beginning of the number).

The reason for this is because most typical normalization rules only match a very specific number of digits.  Take for example, this typical North American normalization rule and translation pattern for North American national numbers:

^1?(\d{10}) --> +1$1

For the uninitiated, this normalization rule will accept any 10-digit number, with or without a leading 1, and will translate it to a valid 11-digit North American national number.  So, if you dial 5552223333 or 15552223333, it will normalize it to +15552223333.

But if you dial one or more extra digits, it will no longer match the normalization rule and will just show the digits you typed. If you typed 55522233331, and try to dial that number in Lync/Skype for Business, it may or may not fail depending on how you created your route patterns. For example, if you've structured your route pattern to accept numbers without a leading plus sign, it would route through Lync/S4B (ie.  ^\+?\d+$ would accept any number of digits with or without a plus).  I don't advise this, because its messy and makes advanced routing decisions harder. Plus it goes against the general advice of E.164 EVERYWHERE.

If you allowed a number to get through to the PSTN with too many digits, the carrier will reject any extra digits and dial the number properly, but for systems like Lync/Skype for Business, you should take care to ensure you deal with overdialed numbers seamlessly.

To make sure any overdialed numbers are normalized correctly, a simple extra few characters added to the end of a normalization rule will fix the problem nicely. Using the first example, we simply add a \d* to signify "any number of digits", followed by a $ to signify the end of the string.  So, ultimately we have:

^1?(\d{10})\d*$ --> +1$1

Now, when we dial that same number with too many digits, we get the following properly formatted normalized result:

In the end, a simple change to an otherwise generic normalization rules can end up making your users' lives just a little bit easier.

Thanks to the aforementioned Greig Sheridan, who suggested I write a blog post around this esoteric topic. I owe you a Foster's, mate!

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:
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:
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.

Thursday, February 12, 2015

Large Scale Extension Dialing in Lync

I was recently working a pretty large Enterprise Voice deployment that had more than a hundred sites located around the world. Every site used DIDs for their users phone numbers, but wanted to be able to reach every other site using a 3-digit site code, plus the last 4 digits of the user's phone number (total 7 digits). This would be pretty easy except for the following wrinkle: they wanted people within any one site to be able to dial just the last 4-digits of other people within that site, rather than the 7-digit "global" extension or full DID. To complicate matters, multiple sites had overlaps with the last 4 digits of their numbers.

Unfortunately, this meant that every single site would require their own dedicated Lync dial plan, with only one rule that is different from the other sites. Management of these sites can be a nightmare, especially when you consider what has to happen when a new site gets added. Not only do you have to add the other sites extension normalization rule to the new site, but every other site has to have their dial plans updated with the new site's extension normalization rule. With many sites, this can become difficult to manage.

Thankfully, Powershell can take a daunting task such as this and make it much easier. I've developed a process to manage large numbers of extension ranges that is scalable and easy to replicate at other sites. Of course, this being me, the core of it is based around Lync Optimizer generated rulesets, and the associated scripts assume you follow the same naming convention. So, without further ado....

For this particular company, I decided on a naming convention for 7-digit extension normalization rules that follow the format CountryID-StateProv-City-7Ext0x (eg. US-TX-Dallas-7Ext01, US-TX-Dallas-7Ext02 etc). 4-digit extension rules for specific sites use the format CountryID-StateProv-City-4Ext0x (eg. US-TX-Dallas-4Ext01).  Every site's dial plan would end up with a large number of 7Ext normalization rules, and a single 4Ext normalization rule specific to that site.

I kept a repository of 7-digit extension dialing rules for all sites, organized alphabetically in a manually created dialplan called ZZ-ExtensionList. This dialplan was only used for the scripts I used later to populate new site lists.

Each site used the Lync Dialing Rule Optimizer to generate rulesets for each site. I used the Extensions entry page to generate the local site's 7Ext0x normalization rule.  For this particular company, since we were using a 3-digit site code and the last 4-digits of the user's DID, the extension entry page looked something like this:

For the above example, the 3-digit site code is 350, and user's phone numbers are in the range +442055662000 to +442055662099.  The # of Ext Digits in DID field tells the Optimizer that only the last 4 digits of the 7-digit extension is actually part of the DID.

I ran the Optimizer generated script against the deployment as per usual, which generated the standard ruleset for the given site. Once complete, I opened the ZZ-ExtensionList dial plan and added the newly generated 7Ext0x rule(s) to the list, making sure to maintain alphabetical order.

I then ran the custom script AddExtensionsToDP.ps1 (see below) with the switch -DialPlan set to the name of the newly added dialplan (ie .\AddExtensionsToDP.ps1 -DialPlan UK-London) This script does two things. First, it adds all the extension dialing rules from ZZ-ExtensionList into the new dialplan. Secondly, it modifies the 7Ext0x rule(s) specific to the new site into a 4Ext0x rule(s). So, for the above example:
Original Pattern/Translation: ^350(20\d{2})$          -->    +44205566$1
New Pattern/Translation:       ^(?:350)?(20\d{2})$  -->    +44205566$1
The new pattern allows users within the site to either dial 20xx or 35020xx for other users within the site.


Once that script was done, then I ran the UpdateNormRules.ps1 script (shown below) with the -NormRuleBase switch to specify the name of the dial plan created at the beginning. (ie. .\UpdateNormRules.ps1 -NormRuleBase UK-London). This script adds the normalization rules for the new site to all the other site-specific dialplans, in the proper alphabetical order.


Once complete, the new site had all the existing site-level extension normalization rules for every other site, and all existing sites also had the new site's extension normalization rule inserted into their dial plans. This ensured that all sites could dial any other site using their site code and extension.

So, to summarize the workflow:
  1. Manually create an empty dialplan called ZZ-ExtensionList
  2. Generate a Lync Optimizer dialplan for your selected area, populating the Extensions using the appropriate format for your deployment. Make sure the Suffix is set to 7Ext01 (and 02 etc).
  3. Run the Lync Optimizer generated ruleset against your deployment.
  4. Copy the -7Ext0x rule(s) to the ZZ-ExtensionList dialplan ensuring proper alphabetical order.
  5. Run the AddExtensionsToDP.ps1 script to add all the extension rules in ZZ-ExtensionList to the new dialplan.
  6. Run the UpdateNormRules.ps1 to update all other dial plans with the newly created extension normalization rule.
  7. Repeat steps 2-6 as necessary.

Rinse and repeat for each new dial plan you want to add to your environment. This process along with the attached scripts should make managing large dial plans much simpler. As always, be cautious when running these scripts, as I can't be responsible for any issues this causes.  Always make a backup of your existing Lync EV environment before running these or any scripts provided by strange people who pretend they look like David Hasselhoff.