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.

Monday, February 9, 2015

Out of the Gutter: The Ken Lasko Story, Part 3, Part II

One day in the late 1990's, I got a call from an old co-worker from my Microsoft days asking me if I wanted to help out on a 3-month long consulting job for the provincial government managing their Microsoft Mail 3.5 system. I told him that I've never even HEARD of MS-Mail, let alone know anything about it. He assured me that I'd be able to figure it out and strongly suggested that I give it a try. Since the pay I would get in three months was going to be as much as I was making at my current job in a year, I jumped at it.

So began my consulting career.

Working with this was as dirty as this package implies.
I started work with a third guy we both knew from Microsoft support and got a crash course in MS-Mail. Since there wasn't
all that much to it, it didn't take long. MS-Mail was a collection of "post offices" that worked more or less completely independently of any other post office.  There was no central management console, so you'd have to connect to each post office individually to do any maintenance or troubleshooting. The provincial government had more than 220 post offices in their deployment, so management was a nightmare. Since there was no central management to speak of, there was no way we could tell there was a problem unless we went and signed into every single post office to check the status of mail delivery, GAL synchronization and that sort of thing. Since that wasn't feasible, we operated in reactive mode, where we would wait for someone to call in to report an issue. We would then log into the affected post office, fix the issue and continue on.  We got pretty good at it, so our contract kept getting extended more and more.

The job proved to be both time-consuming and monotonous. We decided to figure out a way to make our job easier so we could free up time for web-surfing and game playing. My counterpart worked on developing a Windows service that would collect all the pertinent information from each post office and put it into a central repository.  I worked on a web-based front-end that would show us near real-time information from each post office.  Problems would be highlighted in red, and we got it to the point that you could just click on the red counter, and it would initiate the typically required fix for that issue.

After many months of development, we were at the point where we would show up to work, bring up the webpage, and quickly deal with any issues by literally clicking on a red button to trigger the required fixes on any number of post offices. Call volumes dropped dramatically, and we both realized we were sitting on a goldmine. We could have become rich if it weren't for an annoying software development from Microsoft called Exchange Server.

The provincial government had decided to start moving to Exchange Server 5.5 in 1999.  While we weren't directly involved in the design of the environment, we had our hands deep in the support and migration away from MS Mail. By the time the 21st century had arrived (well, not technically since it was still 2000), we were both pretty adept at working with Exchange Server 5.5.  Eventually, support moved to a central call centre far north of where we lived and our services were no longer needed. So 2.5 years after I left my previous job for that short, high-paying, 3-month consulting gig, I was looking for another job.

The same person who got me on the MS-Mail gig introduced me to the right people at what was then Software Spectrum, and I started work as a consultant. Soon after, Software Spectrum sold their consulting business to Buchanan Associates (now Buchanan Technologies). I primarily consulted on Active Directory and Exchange projects, and had my hand in quite a few of them over the years. I got to work in some pretty fun places, especially Bermuda, where I was on a Citrix and Exchange gig with our IBM partner for several months.

In 2007, my boss at the time said that he wanted me to become the company expert in Office Communications Server (OCS).  The first thing I said was "OK. What's OCS?". The second thing I said after I found out what OCS did was "You want me to be the instant messaging expert???" At the time, Exchange had flirted with including some IM capabilities, but it was never used by many in the corporate world.  IM was seen as something used by kids.  I had images of "OMG Ponies!!!" and "LOL" and thought my boss was trying to make me quit my job.

When I dug in deeper into OCS, I saw there was some telephony integration capabilities and became intrigued, mostly because I had no idea how you could use your computer to make telephone calls. When Office Communications Server 2007 R2 came out, we jumped aboard in a big way and moved a chunk of our users over to it for all their telephony.  OCS, and then Lync became my sole focus, and I moved entirely away from Exchange and AD consulting.

My first go at the Optimizer was a VBScript HTA program.
Around 2010, I thought it might be a good idea to start blogging some of the things I couldn't find answers for about Lync. At the time, I thought I was late to the blogging party. My first post was in fact titled "Late to the Party".  I also began work on a locally run version of what would become the Lync Dialing Rule Optimizer to deal with the odd local vs. long distance conundrum that exists in North America.

Fast-forward five years, and my blog is quite heavily read, I've spoken at numerous events and the Lync Optimizer now supports 100 countries. I became the Lync Practice Manager for Buchanan Technologies and was overseeing how we deliver Lync to our customers. I always felt that Buchanan took care of me, and made sure I was happy in my career. Life was busy, but good.

But along came David Tucker from Event Zero, riding in on a white stallion with the promise of greater things. After much whining and dining, I finally decided to make the jump from Buchanan Technologies, a consulting company with 500 people worldwide, where I spent 15 years of my life to the Event Zero team.

If you don't know Event Zero and their phenomenal Dossier product line, you really should check it out. The best way I can describe it is "Lync Monitoring Reports on 'roids, but without the rage". It extends the not-so-real-time, slow to respond, frustrating, and hard to use reports that comes with Lync, into something that provides real-time, useful and easy-to-get-to reports on all aspects of Lync activity. There are also numerous other add-ons that can really make your Lync deployment work better for you.

I've been brought on to help drive Event Zero Dossier deployments, and ensure clients are getting the most out of their Lync deployments through effective reporting.

For me to leave my Buchanan Technologies "family" after 15 years, you know that I must have seen something special in Event Zero, and no, it wasn't the fact that Dave loves to cuddle on cold winter nights (which don't happen often in Australia).

My big career switch made me somewhat nostalgic, which led me to doing this series. There weren't nearly as many explosions or top-secret espionage capers as I would have hoped to have achieved at this point in my life, but there is still time.  Maybe the next chapter in this series will deliver on that....

Until then......adios!