Friday, 3 May 2013

Lync 2013 Database Mirror Manager Tool

In Lync 2013 we have been given a new SQL High Availability option for Lync databases to replace the old and more complicated SQL Clustering method from Lync 2010. The Lync 2013 SQL Mirroring method is easy to provision using topology builder, and can be managed using Powershell commands.


Managing Mirrored Databases


The mirror state of the databases can be controlled by Lync Powershell commands (probably best not to go fiddling with the SQL configuration directly). The command used to change the state of databases is shown below:

Invoke-CsDatabaseFailover -DatabaseType <Application | Archiving | Monitoring | User | Provision | CentralAdmin | Lyss | Registrar | Edge | PersistentChat | PersistentChatCompliance | CentralMgmt> -NewPrincipal <Primary | Mirror> -PoolFqdn <Fqdn> [-Confirm [<SwitchParameter>]] [-ExcludeDatabaseList <String[]>] [-Force <SwitchParameter>] [-LocalStore <SwitchParameter>] [-Report <String>] [-WhatIf [<SwitchParameter>]]

The Invoke command is broken down into Database Types. These ‘database types’ do not line up with the actual names of the databases within SQL, but instead, are given function names that relate to their role within Lync. The ‘database types’ can also contain more than one physical database. Here is how the database types are mapped to SQL names:

DatabaseType
Databases
Application
Rgsconfig
Rgsdyn
Cpsdyn

Archiving
Lcslog

Monitoring
Lcscdr
Qoemetrics

User
Rtcab
Rtcxds
Rtcshared

CentralMgmt
Xds
Lis

PersistentChat
Mgc

PersistentChatCompliance
Mgccomp

Provision

Not Implemented
CentralAdmin

Not Implemented
Lyss

Not Implemented
Registrar

Not Implemented

Note: When you Invoke a changeover on the Archiving or Monitoring database, Lync will ask you if you want to accept the action to perform changeover on the target "Registrar". Kind of weird that it refers to these databases in that way... At any rate, you can't actually call the invoke command on a 'database type' of "Registrar" so don't try it.
Edge

Not Implemented
Cls
Not Implemented
Note: The Not Implemented database types above are listed on Technet as being database types. However, you can’t actually call the Invoke command on these 'database types' in Powershell.  I’m assuming this is a documentation error…

You can see the physical databases within SQL. Here’s what they look like:



What you might notice in the picture above is that some of the physical databases that are grouped together within the Powershell database type categories are actually in different database states. For example, cpsdyn and rgsdyn are in mirrored state, whilst rgsconfig is in Principal state. This is because SQL manages these databases mirrored state per physical database, and not in the groupings that Microsoft chose to build the Invoke changeover command.

By running a Get-CsDatabaseMirrorState command, we can see that these databases are not in the same state:

PS > Get-CsDatabaseMirrorState

cmdlet Get-CsDatabaseMirrorState at command pipeline position 1
Supply values for the following parameters:
PoolFqdn: pool.domain.com


DatabaseName             : rtcab
StateOnPrimary           : Mirror
StateOnMirror            : Principal
MirroringStatusOnPrimary : synchronized
MirroringStatusOnMirror  : synchronized

DatabaseName             : rtcxds
StateOnPrimary           : Principal
StateOnMirror            : Mirror
MirroringStatusOnPrimary : synchronized
MirroringStatusOnMirror  : synchronized

DatabaseName             : rtcshared
StateOnPrimary           : Principal
StateOnMirror            : Mirror
MirroringStatusOnPrimary : synchronized
MirroringStatusOnMirror  : synchronized

DatabaseName             : lcscdr
StateOnPrimary           : Principal
StateOnMirror            : Mirror
MirroringStatusOnPrimary : synchronized
MirroringStatusOnMirror  : synchronized

DatabaseName             : qoemetrics
StateOnPrimary           : Principal
StateOnMirror            : Mirror
MirroringStatusOnPrimary : synchronized
MirroringStatusOnMirror  : synchronized

DatabaseName             : lcslog
StateOnPrimary           : Mirror
StateOnMirror            : Principal
MirroringStatusOnPrimary : synchronized
MirroringStatusOnMirror  : synchronized

DatabaseName             : rgsconfig
StateOnPrimary           : Principal
StateOnMirror            : Mirror
MirroringStatusOnPrimary : synchronized
MirroringStatusOnMirror  : synchronized

DatabaseName             : rgsdyn
StateOnPrimary           : Mirror
StateOnMirror            : Principal
MirroringStatusOnPrimary : synchronized
MirroringStatusOnMirror  : synchronized

DatabaseName             : cpsdyn
StateOnPrimary           : Mirror
StateOnMirror            : Principal
MirroringStatusOnPrimary : synchronized
MirroringStatusOnMirror  : synchronized

DatabaseName             : xds
StateOnPrimary           : Mirror
StateOnMirror            : Principal
MirroringStatusOnPrimary : synchronized
MirroringStatusOnMirror  : synchronized

DatabaseName             : lis
StateOnPrimary           : Principal
StateOnMirror            : Mirror
MirroringStatusOnPrimary : synchronized
MirroringStatusOnMirror  : synchronized
Note: I refer to this as being ‘out of sync’, which is not to be confused with their synchronisation state…

If I was to run the Invoke command on the User database here, I would end up with the following:

Invoke-CsDatabaseFailover -PoolFqdn pool.domain.com -DatabaseType "User" -NewPrincipal "Primary"

This causes the rtcab to move back to the primary mirror with the other user services:
PS > Invoke-CsDatabaseFailover -PoolFqdn pool.domain.com -DatabaseType "User" -NewPrincipal "Primary"

Confirm
Are you sure you want to perform this action?
Performing operation "Invoke-CsDatabaseFailover" on Target "UserServices".
[Y] Yes  [A] Yes to All  [N] No  [L] No to All  [S] Suspend  [?] Help (default is "Y"): y

DatabaseName                                              FailoverResult
------------                                              --------------
rtcab                                                            Success
rtcxds                SucceededAsNewPrincipalAlreadyOwnsThePrincipalRole
rtcshared             SucceededAsNewPrincipalAlreadyOwnsThePrincipalRole


PS > Get-CsDatabaseMirrorState -PoolFqdn pool.domain.com -DatabaseType User


DatabaseName             : rtcab
StateOnPrimary           : Principal
StateOnMirror            : Mirror
MirroringStatusOnPrimary : synchronized
MirroringStatusOnMirror  : synchronized

DatabaseName             : rtcxds
StateOnPrimary           : Principal
StateOnMirror            : Mirror
MirroringStatusOnPrimary : synchronized
MirroringStatusOnMirror  : synchronized

DatabaseName             : rtcshared
StateOnPrimary           : Principal
StateOnMirror            : Mirror
MirroringStatusOnPrimary : synchronized
MirroringStatusOnMirror  : synchronized

Now all the physical databases within the User Database Type are all in the Principal state.
Alternatively the databases can be failed over as a single database. However, you need to run a more complicated powershell command:

Invoke-CsDatabaseFailover -PoolFqdn pool.domain.com –DatabaseType “User” -NewPrincipal "Primary" -ExcludeDatabaseList "rtcxds", "rtcshared"

Note: There’s an error on technet that includes an additional switch “-ExcludeDatabase” which isn’t actually needed (or available, for that matter).
 
Running the command will look something like this:

PS > Invoke-CsDatabaseFailover -PoolFqdn pool.domain.com -NewPrincipal "Mirror" -DatabaseType "User" -ExcludeDatabaseList "rtcxds", "rtcshared"

Confirm
Are you sure you want to perform this action?
Performing operation "Invoke-CsDatabaseFailover" on Target "UserServices".
[Y] Yes  [A] Yes to All  [N] No  [L] No to All  [S] Suspend  [?] Help (default is "Y"): y

DatabaseName                        FailoverResult
------------                        --------------
rtcab                                      Success

It makes sense that Microsoft designed the commands to force functionally associated databases to be running on the one SQL machine. However, it can make it a bit confusing to administer from a Powershell perspective. Which brings me to the real point of this article…


Lync 2013 Database Mirror Manager Tool


Wouldn’t it be much easier to just have GUI interface that shows you the state of the database? And be able to simply click to choose which ones you wanted to fail over? Well, today is your lucky day. I’ve made another GUI based tool that does just that. It looks like this:


Lync Front End Mirroring
Lync Persistent Chat Mirroring


UPDATE (27/5/2015):

1.01 Enhancements: 
  • Added enhanced handling of error states so the GUI doesn't display the option to change the mirror state of databases that aren't mirrored. I noticed this when doing CU updates and disconnected mirrors giving "DatabaseInaccessibleOrMirroringNotEnabled" errors that need to be handled in a way that makes sense in the GUI.
  • Change the foreground colour of the database name label when the user has selected to change the state. This gives a visual indication of what is going to be changed when the Invoke button is pressed (ie. Any database with a green label will be changed over when the Invoke button is pressed.)

1.02 Update:
  • Added a check box for automatically agreeing to changeover without having to explicitly agree to every database change in the Powershell window.
  • Script now checks for the location of the central management store for Migration scenarios when it still resides on Lync 2010. This previously resulted in an error.
  • Suppressed warnings from Powershell window that would be displayed when getting status of databases that weren't available.
  • Write the commands being run to Powershell window for more feedback to the user.
  • Database names are now listed in Powershell window with mirror state when refresh is done.
  • Script is now signed.
  • Updated the form icon.
  • Removed the dedicated Close button because it's unnecessary.
1.03 Update
  • Added Powershell pre-req checks and Module loading.
  • Updated reporting of database status in PS window
  • Added Up and Down keys in the pool listbox 
  • Updated to work with Skype for Business!

1.04 Update
  • There were reports of issues on some versions of Powershell with version 1.03. ErrorVariable flags have been removed in 1.04 this version to fix these issues.
1.05 Update
  • Updated Signature

Download Version 1.05: 

DOWNLOAD HERE

It’s pretty straightforward to use (much more than Powershell anyway!). You simply select the pool from the list, and the databases that have mirroring enabled will display check boxes that show you the current Primary/Mirror status of the databases. If you decide you want to change one, or many, of the states, you simply click on the desired state check box for each database type, and then hit the Invoke button.

Note: You will be prompted in the Powershell window for each database that the tool is changing over. The tool will not make any changes without your knowledge.

So, what if databases within the Database groups get out of sync, like I described earlier in the article? Well, the tool is smart enough to realise this, and will inform you that the underlying physical databases within a 'database type' are out of sync. At this point you can choose to leave them out of sync, or invoke a change-over.

Out of Sync Error


Note: If you want to have your databases out of sync (because you just love defying Microsoft’s best practices), then don't press the invoke button. If you do, it will re-sync the databases back to the value selected in the check box for that database type.

Let me know if you find the tool useful or have any ideas on how you would like it improved.

The Wrap Up


The Evil Queen: "Mirror, mirror upon the wall, Who is the fairest of all?"
SQL Mirror: "O Lady Queen, though fair ye be, Lync Mirroring is the fairest of them all."
The Evil Queen: "Fair enough.”

See y’all next time. Enjoy!


Read more →

Friday, 19 April 2013

Microsoft Lync: The Facts about Fax


I find that fax is often misunderstood, especially when it comes to way it works on VoIP networks. Also, I’ve noticed that there is very little information on the internet about how to deploy fax on Lync. In my years working with VoIP, I have run into many fax issues on many different platforms. So I thought I might write an article that explains exactly how Lync does, and doesn’t, support fax.

This article is not designed to be a walk-through of how to configure fax on your specific gateway, but instead to provide you with information that will help you troubleshoot your own fax problems in the future. After all; "If you give a man a fish you feed him for a day. If you teach a man to fish you feed him for a lifetime."

The best place to start here will be to talk about the Protocols used for fax communications and how they relate to each other. There are loads of protocols when it comes to fax transmissions; however, there are only a few we really need to understand the basics of for this article. Here are the main offenders:  

T.30 – Is an ITU recommendation that describes procedures for sending faxes over the PSTN (via modem tones). These include: call establishment and call release; compatibility checking, status and control command; checking and supervision of line conditions; control functions and facsimile operator recall. If you would like to read the spec you can download it here.

V.34 (and other V.x protocols) – The V protocols describe the modulation and demodulation (modem) techniques used to pass data (in our case, fax) over a phone line.

T.38 – Is a protocol that describes how to relay T.30 fax messages over a VoIP network. The relaying of fax is done hop by hop through the data network between VoIP gateway devices. The end fax devices are not aware that this relay process is happening (unless it’s a fax gateway that directly supports T.38), and it uses T.30 protocol directly with the Gateway that is closest to it. The gateway terminates the T.30 protocol and converts the stream into a packetised byte stream that it relays to the next hop gateway over an IP network. The Gateway on the other side receiving the T.38 stream will then convert the messaging back into T.30 protocol and pass it to the end fax machine.



CNG Tone: A word that will also come up in this article is “CNG Tone”. CNG tone is basically a tone that the originator of a fax call plays on the line to indicate that it is a fax call, and that it’s ready to start fax handshaking. The CNG signal is simply an 1100 Hz tone that plays for half a second, and then repeats every three seconds.

T.38 Calls on Lync


The T.38 protocol works in conjunction with SIP in a two step process. The first step is to set up a voice stream session. The voice stream is used by the originating fax machine to transmit its CNG tone to the far end fax machine. The far end fax machine then responds with an answer signal (ANSam) over the voice stream. It’s at this point that the gateway can recognise that the call is a fax call, and now move into T.38 transmission processing. To do this a re-invite is sent out by the receiving gateway that includes T.38 settings in the SDP, and the gateways agree upon updating the media session to a T.38 image transmission.

The re-invite message will look like this:

INVITE sip:192.168.0.191:5068;transport=Tcp;maddr=192.168.0.191;ms-opaque=b584fc305c6ad126 SIP/2.0
Call-ID: 5eb671a0-9a63-4701-b186-ed8c87f64b3a
Contact: <sip:1300368999@192.168.0.220;user=phone>
Content-Length: 258
Content-Type: application/sdp
CSeq: 517 INVITE
From: <sip:1300368999@DX001.domain.com;user=phone>;tag=c0a800dc-18ed8
Max-Forwards: 70
To: "Fax Test Device"<sip:0395551111@domain.com;user=phone>;epid=1C2A8F4B3B;tag=3088606813
User-Agent: Quintum/1.0.0 SN/0030E101408B SW/P108-09-21
Via: SIP/2.0/TCP 192.168.0.220;branch=z9hG4bK-tenor-c0a8-00dc-00af

v=0
o=Quintum 131 131 IN IP4 192.168.0.220
s=VoipCall
c=IN IP4 192.168.0.220
t=0 0
m=image 10428 udptl t38
c=IN IP4 192.168.0.220
a=T38FaxVersion:0
a=T38MaxBitRate:14400
a=T38FaxFillBitRemoval:0
a=T38FaxTranscodingMMR:0
a=T38FaxTranscodingJBIG:0

When the Lync server receives this message it tries to parse the SDP of the Invite before it forwards it back to the Analog Gateway (with the fax machine connected to it). When it parses the message it finds the m field equals image (m=image), which it doesn’t support. This results in an Invalid SDP message being sent back to the far end gateway and the call being torn down.

SIP/2.0 488 Invalid SDP: The offer from Gateway during a re-INVITE has changed an existing m-line (Media Name)
FROM: <sip:1300368999@DX001.domain.com;user=phone>;tag=c0a800dc-18ee0
TO: "Fax Test Device"<sip:0395551111@domain.com;user=phone>;epid=1C2A8F4B3B;tag=87d3f0ce82
CSEQ: 522 INVITE
CALL-ID: e2a7db66-3311-44cf-a08a-17befafb3b0f
VIA: SIP/2.0/TCP 192.168.0.220;branch=z9hG4bK-tenor-c0a8-00dc-00b1
CONTENT-LENGTH: 0
SUPPORTED: 100rel
SERVER: RTCC/5.0.0.0 MediationServer

A completed T.38 negotiation process is described in the following diagram:

This concludes the sad fact that Lync (2010 and 2013) does not support T.38 protocol negotiation directly with Analog and PSTN Gateways.



 Lync Fax Settings


If you’ve ever tried to connect a fax machine to Lync before, you will no doubt have seen the only setting on the system that relates to Fax. This setting is in the New/Set-AnalogDevice command, and is a Boolean setting called AnalogFax. The command looks something like this:

New-CsAnalogDevice -LineUri tel:+61399991111 -DisplayName "Name of Fax Machine" -RegistrarPool lyncpool.domain.com -AnalogFax $True -Gateway <IP/FQDN> -OU "ou=LyncUsers,dc=domain,dc=com"

So I would expect that the first thing a good IT professional would do when installing a fax machine is turn this setting on, because it’s a fax machine, right? So I definitely should tell the system that it’s a fax machine, right!? Well, not necessarily. As it turns out, this setting is very specific in its operation, and is what, at best, I would describe as a work around solution for fax.

Basically, if an analog device is marked as being AnalogFax it invokes a special ‘hairpinning’ routing procedure within Lync when the device makes an outbound call. This procedure basically means that Lync bypasses regular routing rules and sends the invite message straight back to the gateway that sent it. The idea of this is that the analog gateway is supposed to send the call out a PSTN line that is also directly connected to it, and in the process avoids sending the fax media stream over the IP network all together.  

So, when AnalogFax is set to true, AND the system is configured with Media Bypass turned on, any outbound call from the analog device with this setting will be automatically routed back to the gateway that sent the call. The call scenario looks like this:

|Time     | 192.168.0.49                          | 192.168.0.191
|         |                                       |                  
|0.000    |         Request: INVITE sip           |SIP/SDP: Request: INVITE sip:130036899
|         |(62301)  ------------------>  (5068)   |
|0.001    |         Status: 100 Trying            |SIP: Status: 100 Trying
|         |(62301)  <------------------  (5068)   |
|0.220    |         Status: 183 Session           |SIP/SDP: Status: 183 Session Progress
|         |(62301)  <------------------  (5068)   |
|0.269    |         Request: PRACK sip:           |SIP: Request: PRACK
|         |(62301)  ------------------>  (5068)   |
|0.270    |         Status: 200 OK                |SIP: Status: 200 OK
|         |(62301)  <------------------  (5068)   |
|0.532    |         Status: 200 OK                |SIP/SDP: Status: 200 OK
|         |(5060)   ------------------>  (61427)  |
|0.845    |         Request: INVITE sip           |SIP/SDP: Request: INVITE sip:+611300368999
|         |(5060)   <------------------  (61429)  |
|0.893    |         Status: 404 Not Fou           |SIP: Status: 404 Not Found
|         |(5060)   ------------------>  (61429)  |
|0.893    |         Request: ACK sip:+6           |SIP: Request: ACK sip:+611300368999
|         |(5060)   <------------------  (61429)  |
Note: My gateway didn’t accept the call, and as a result sent a 404 Not Found back to Lync. After this the call fails.

So, why don’t you just don’t save the money on the gateway and connect the fax machine directly to the network? The only reason is that if you do this, there will be no CDR records output by Lync for calls made from fax machines. So the question is, how much are CDR records worth to you? If the answer is more than the price of an analog VoIP gateway with FXS and FXO ports, then you’ve come to the right place!


What are the options available on Lync for fax?


Option 1 – Bypass Lync Altogether

The first option, as I have already described above, is to connect the fax machine directly to the network and bypass Lync altogether. There are two problems with this method: the first is that it requires individual analog/digital carrier services brought into the premises; the second is that there will be no CDR records reporting in Lync for these calls.


Diagram:

Option 2: Fax Hairpinning

This is the method that Microsoft officially supports for fax calls. On Technet it is described as “hairpinning”. The way it works is that once you enable the AnalogFax setting within the New/GetCsAnalogDevice command, and enable Media Bypass, calls from this device to external numbers will get sent directly back the device by Lync. This actually bypasses all of the regular routing flow within Lync.

Lync configuration:
  • Set-CsAnalogDevice -AnalogFax $true
  • Enable Media Bypass on Lync. (If you do not enable this the hairpinning will not work)
  • Use an analog gateway with FXS, and FXO/ISDN ports. Ensure that calls get routed inbound from SIP to the FXO/ISDN ports. Note that Lync will normalise the number before it's sent back, so you will have to do something with the “+<prefix>” before sending it to the carrier.

Diagram:





Option 3: Connect Fax over G.711 to SIP Carrier

In this scenario the fax tones are sent directly over G.711 out to the SIP network (either direct, or through an SBC). Whilst this may work, it depends heavily on what happens to the G.711 RTP stream over the network. If there is significant network jitter or packet loss whilst the fax is being sent, then the transmission may fail. Microsoft explicitly states that it does not support this scenario. Technet states: “Fax calls are not supported through a SIP trunk.”

Lync configuration:
  • Set-CsAnalogDevice -AnalogFax $false
  • Enable Media Bypass on Lync.
  • Grant a Voice Policy with appropriate PSTN Usages for the Analog Device.
  • Configure your VoIP gateway to use G.711 for fax. This usually involves disabling T.38 settings.


Diagram:



Option 4: Fax over G.711 to PSTN VoIP Gateway

For this scenario the fax stream is sent via G.711 to a local ISDN/Analog gateway and then on to the carrier. This scenario can be achieved as long as you can ensure that there is no network jitter or packet loss issues between the two gateways. So I would not recommend making fax calls from an Analog gateway across a WAN to the PSTN gateway, as you may not be able to guarantee the quality of the voice stream.

Lync configuration:
  • Set-CsAnalogDevice -AnalogFax $false
  • Enable Media Bypass on Lync.
  • Grant a Voice Policy with appropriate PSTN Usages for the Analog Device.
  • Configure your VoIP gateways to use G.711 for fax. This usually involves disabling T.38 settings.

Diagram:


Option 5: Fax via SBC with T.38 to SIP Trunk

This is the most complex scenario on the list, because you have to ensure that internally you are using G.711 between the gateways and externally you are using T.38. Note, this will only work if the Carrier SIP trunk provider supports T.38 protocol. So ensure that you consult with your carrier before attempting this kind of configuration.

Lync and Gateway configuration:

  • Set-CsAnalogDevice -AnalogFax $false
  • Enable Media Bypass on Lync.
  • Grant a Voice Policy with appropriate PSTN Usages for the Analog Device.
  • Configure the fax connected analog gateway to use G.711. This usually involves disabling T.38 settings.
  • On the Lync facing SIP leg of the SBC ensure that fax calls are configured for G.711. This usually involves disabling T.38 settings.
  • Enable T.38 on the external SIP trunk that faces the SIP Carrier.

Diagram:



On a AudioCodes Gateway this would look like this:

Lync Facing Trunk Setting:
Open the 'IP Profile Settings' page for the Lync Trunk (Configuration tab > VoIP menu > Coders And Profiles > IP Profile Settings).



SIP Trunk Facing Trunk setting:
Open the 'IP Profile Settings' page for the SIP Carrier (Configuration tab > VoIP menu > Coders And Profiles > IP Profile Settings).




Call Routing for Analog Devices

Note: Voice Routing, as described below, only works when the AnalogFax setting is set to $false.

I’ve seen different things mentioned around the web for how routing works with Analog Devices. My testing has shown that a Voice Policy must be granted on a Analog Device before you can get it to route externally. If you do not set a VoicePolicy to the Analog Device, then you will receive the following error when dialling an external number:

SIP/2.0 403 Forbidden
FROM: "Fax Test Device"<sip:+61395551111@domain.com;user=phone>;epid=1D3FB4561B;tag=ffa63dd9c5TO: <sip:0407555999;phone-context=Melbourne_Site@domain.com;user=phone>;tag=1A8C27C7FDB2A881C9C77A96575A9CCCCSEQ: 6895 INVITECALL-ID: 4e9c791b-3235-40c0-8c37-47431a1ba82dVIA: SIP/2.0/TLS 192.168.0.191:57505;branch=z9hG4bKbcf5ff8;ms-received-port=57505;ms-received-cid=2CCA00CONTENT-LENGTH: 0SERVER: OutboundRouting/5.0.0.0ms-diagnostics: 12001;reason="User Policy does not contain phone route usage";source="2013ENTFE001.DOMAIN.COM";UserUri="sip:+61395551111@domain.com";appName="OutboundRouting"ms-application-via: ms-udc.cdr%3D09e4c67d9b3eeb2bbdb82e47464ebb80%3A5;ms-pool=melbfepool.domain.com;ms-application=http%3A%2F%2Fwww.microsoft.com%2FLCS%2FUdcAgent;ms-server=2013ENTFE001.domain.com

If you do a Get-CsAnalogDevice on the system you will see the Voice Policies that have been applied to your Analog Devices:

> Get-CsAnalogDevice


Identity           : CN=Fax Test Device,OU=LyncUsers,DC=mylynclab,DC=com
VoicePolicy        :
VoiceRoutingPolicy :
RegistrarPool      : melbfepool.domain.com
Gateway            : AudioCodes.domain.com
AnalogFax          : False
Enabled            : True
SipAddress         : sip:79c6c937-8a6b-40fd-8dd9-aacca43f5f1b@domain.com
LineURI            : tel:+61395551111
DisplayName        : Fax Test Device
DisplayNumber      :
ExUmEnabled        : False
Note: Above there is no VoicePolicy assigned to this user. This will result in external calls failing.

So we need to Grant a Voice Policy to the Analog Device. Here’s an example:

> Grant-CsVoicePolicy -Identity "Fax Test Device" -PolicyName ExecutiveUserPolicy-International

Now the Get-AnalogDevice should show that a Policy has been granted:

> Get-CsAnalogDevice


Identity           : CN=Fax Test Device,OU=LyncUsers,DC=mylynclab,DC=com
VoicePolicy        : ExecutiveUserPolicy-International
VoiceRoutingPolicy :
RegistrarPool      : melbfepool.domain.com
Gateway            : AudioCodes.domain.com
AnalogFax          : False
Enabled            : True
SipAddress         : sip:79c6c937-8a6b-40fd-8dd9-aacca43f5f1b@domain.com
LineURI            : tel:+61395551111
DisplayName        : Fax Test Device
DisplayNumber      :
ExUmEnabled        : False

So now your Analog Device has a Voice Policy, which is great for allowing it to dial out. What if a user was to dial an un-normalised number from an Analog Station though, will it get normalised? Well, this is where things get interesting… The short answer is that it will get Normalised, however, which normalisation rules are used is the bigger issue.

I’ve analysed logs from the server and found that Analog Device function as follows:

If there is no Site based rules configured on the system, then the Analog device gets normalised under the DefaultProfile (which equates to the Global dial plan):

SIP/2.0 101 Progress Report
FROM: <sip:+61395551111@domain.com;user=phone>;epid=1D3FB4561B;tag=bd71af9e4a
TO: <sip:0407555999;phone-context=DefaultProfile@domain.com;user=phone>
CSEQ: 6940 INVITE
CALL-ID: 4c88062c-60d7-459d-96f0-7005702a5f51
VIA: SIP/2.0/TLS 192.168.0.191:58292;branch=z9hG4bK8a8934bc;ms-received-port=58292;ms-received-cid=2D1200
CONTENT-LENGTH: 0
SERVER: TranslationService/5.0.0.0
ms-diagnostics: 14011;reason="Called Number translated";source="2013ENTFE001.DOMAIN.COM";RuleName="Keep All";CalledNumber="0407555999";TranslatedNumber="+0407555999";appName="TranslationService"


If there is a Site based Dial Plan Policy deployed for the Pool that the Analog Device is deployed on, then the Site Policy will be used:

SIP/2.0 101 Progress Report
FROM: <sip:+61395551111@domain.com;user=phone>;epid=1D3FB4561B;tag=ffa63dd9c5
TO: <sip:0407555999;phone-context=Melbourne_Site@domain.com;user=phone>
CSEQ: 6895 INVITE
CALL-ID: 4e9c791b-3235-40c0-8c37-47431a1ba82d
VIA: SIP/2.0/TLS 192.168.0.191:57505;branch=z9hG4bKbcf5ff8;ms-received-port=57505;ms-received-cid=2CCA00
CONTENT-LENGTH: 0
SERVER: TranslationService/5.0.0.0
ms-diagnostics: 14011;reason="Called Number translated";source="2013ENTFE001.DOMAIN.COM";RuleName="AU-Mobile";CalledNumber="0407555999";TranslatedNumber="+61407555999";appName="TranslationService"
Note: the TranslatedNumber is different  in both cases, the first case used my Melbourne Site dial plan and the second used my Global dial plan.

So now you might be wondering what happens if you force a User Policy onto the Analog Device. Well, here’s what happens.

Configure a User Policy onto the Analog Device:

Grant-CsDialPlan -Identity "Fax Test Device" -PolicyName AnalogTest

The above command is accepted by the system. If we run Get-CsAnalogDevice we will see the following:
> Get-CsAnalogDevice


Identity           : CN=Fax Test Device,OU=LyncUsers,DC=domain,DC=com
VoicePolicy        : ExecutiveUserPolicy-International
VoiceRoutingPolicy :
RegistrarPool      : melbfepool.domain.com
Gateway            : AudioCodes.domain.com
AnalogFax          : False
Enabled            : True
SipAddress         : sip:79c6c937-8a6b-40fd-8dd9-aacca43f5f1b@domain.com
LineURI            : tel:+61395551111
DisplayName        : Fax Test Device
DisplayNumber      :
ExUmEnabled        : False

There is no Dial Plan Policy listed in the above get command. So what if you run a full get on the Analog Device:

> Get-CsAnalogDevice |fl *

Gateway                  : AudioCodes.domain.com
AnalogFax                : False
Created                  : True
DisplayName              : Fax Test Device
DisplayNumber            :
ProxyAddresses           : {sip:79c6c937-8a6b-40fd-8dd9-aacca43f5f1b@domain.com}
HomeServer               : CN=Lc Services,CN=Microsoft,CN=1:1,CN=Pools,CN=RTC Service,CN=Services,CN=Configuration,DC=domain,DC=com
TargetServerIfMoving     :
EnabledForFederation     : True
EnabledForInternetAccess : True
PublicNetworkEnabled     : True
EnterpriseVoiceEnabled   : True
EnabledForRichPresence   : True
ExchangeArchivingPolicy  : Uninitialized
LineURI                  : tel:+61395551111
SipAddress               : sip:79c6c937-8a6b-40fd-8dd9-aacca43f5f1b@domain.com
Enabled                  : True
TenantId                 : 00000000-0000-0000-0000-000000000000
UserRoutingGroupId       : 1c864cc6-c83f-5683-b379-0f0d7bdfbb45
TargetRegistrarPool      :
VoicePolicy              : ExecutiveUserPolicy-International
MobilityPolicy           :
ConferencingPolicy       :
PresencePolicy           :
VoiceRoutingPolicy       :
RegistrarPool            : melbfepool.domain.com
DialPlan                 : AnalogTest
LocationPolicy           :
ClientPolicy             : AnalogClientPolicy
ClientVersionPolicy      :
ArchivingPolicy          :
LegalInterceptPolicy     :
PinPolicy                :
ExternalAccessPolicy     :
HostedVoicemailPolicy    :
PersistentChatPolicy     :
UserServicesPolicy       :
ExperiencePolicy         :
HostingProvider          : SRV:
ObjectId                 : 00000000-0000-0000-0000-000000000000
ExUmEnabled              : False
Name                     : Fax Test Device
DistinguishedName        : CN=Fax Test Device,OU=LyncUsers,DC=domain,DC=com
Identity                 : CN=Fax Test Device,OU=LyncUsers,DC=domain,DC=com
Guid                     : 9839f2a2-5206-4d20-942a-2144a69840d8
ObjectCategory           : CN=Person,CN=Schema,CN=Configuration,DC=domain,DC=com
ObjectClass              : {top, person, organizationalPerson, contact}
WhenChanged              : 22/04/2013 2:16:02 PM
WhenCreated              : 12/04/2013 6:01:18 PM
OriginatingServer        : 2013ENTDC001.domain.com
IsByPassValidation       : False
IsValid                  : True
ObjectState              : Unchanged

This list up reveals that the setting was actually applied to the Contact Object within active directory. So now the expectation would be that this would now try and Normalise based on the applied User Policy, right? Actually, unfortunately, this is wrong. The Analog Device still continues to get Normalised via the Site Policy and not the user Policy:

SIP/2.0 101 Progress Report
FROM: <sip:+61395551111@domain.com;user=phone>;epid=1D3FB4561B;tag=ffa63dd9c5
TO: <sip:0407555999;phone-context=Melbourne_Site@domain.com;user=phone>
CSEQ: 6895 INVITE
CALL-ID: 4e9c791b-3235-40c0-8c37-47431a1ba82d
VIA: SIP/2.0/TLS 192.168.0.191:57505;branch=z9hG4bKbcf5ff8;ms-received-port=57505;ms-received-cid=2CCA00
CONTENT-LENGTH: 0
SERVER: TranslationService/5.0.0.0
ms-diagnostics: 14011;reason="Called Number translated";source="2013ENTFE001.DOMAIN.COM";RuleName="AU-Mobile";CalledNumber="0407555999";TranslatedNumber="+61407555999";appName="TranslationService"

It would seem that the fact that Lync doesn't list the DialPlan parameter within Get-CsAnalogDevice is a hint to tell you that it doesn't actually apply this setting on Analog Devices. So why does Lync let you set this value if it’s not used by Lync? My guess is because the Contact Object still contains a msRTCSIP-UserPolicies attribute that it can write to, so it writes to it without giving you an error:



The moral of this long winded story is that you must set a Voice Policy for the Analog Device. When it comes to Dial Plan normalisation you have two choices, either normalise the number on the gateway (using translation rules of the gateway) before sending it to Lync, or use the Global or Site based default rules to normalise the number once it reaches Lync.


Enabling Media Bypass


All of the configurations for fax require that media bypass is enabled on the internal leg of the call. This will avoid any additional jitter and delays that might be caused by sending the stream via the mediation server. Here’s how you do it:

Enable Media Bypass for the Gateway:

>Set-CsTrunkConfiguration -Identity “PstnGateway:DX001.domain.com” -EnableBypass $True –EnableReferSupport $True

Or if Refer is not supported by the gateway:

> Set-CsTrunkConfiguration -Identity "PstnGateway:DX001.domain.com" -EnableBypass $True -RTCPActiveCalls $False -RTCPCallsOnHold $False

>Set-CsTrunkConfiguration -Identity "PstnGateway:DX001.mylynclab.com" –EnableSessionTimer $True
Note: There are some other special requirements that the gateway has to support here. 

Turn on Media Bypass at a System Level:



If you are not using CAC then you can select “Always Bypass” as the option. In this configuration, both client and trunk subnets are mapped to one and only one bypass ID, which is computed by the system.

- If CAC is enabled then the processing works as follows:
If you enable CAC, you cannot select Always Bypass, and vice-versa, because the two configurations are mutually exclusive. That is, only one of the two will apply to any given PSTN call. First, a check is made to determine if media bypass applies to the call. If it does, then CAC is not used. This makes sense, because if a call is eligible for bypass, it is by definition using a connection where CAC is not needed. If bypass cannot be applied to the call (that is, if the client’s and gateway’s bypass IDs do not match), then CAC is applied to the call.

- CAC not enabled and Media Bypass set to Use Site and Region Information.
Where Use Site and Region Information is enabled, bypass determination works essentially the same way, regardless of whether CAC is enabled or not. That is, for any given PSTN call, the client’s subnet is mapped to a particular site, and the bypass ID for that subnet is extracted. Similarly, the gateway’s subnet is mapped to a particular site, and the bypass ID for that subnet is extracted. Only if the two bypass IDs are identical will bypass happen for the call. If they are not identical, media bypass will not occur. 

Even though CAC is disabled globally, bandwidth policy needs to be defined for each site and link if you want to use site-and-region configuration to control the bypass decision. The actual value of the bandwidth constraint or its modality doesn’t matter. The ultimate goal is to have the system automatically calculate different bypass IDs to associate with different locales that are not well connected. Defining a bandwidth constraint by definition means a link is not well connected.


Other Settings that Affect Fax


Just when you thought you were safe, there are actually more settings that can adversely affect your fax transmissions. In addition to the settings mentioned above for Lync there are other settings that can affect Fax transmission over G.711 connection. You need to be careful of the following: 

  • Faxes don’t like jitter that is caused from variable delays in packetised voice networks. So some gateways will actively try and reduce the amount of jitter by increasing the Jitter Buffers (perhaps to 100ms) for calls that they detect as being fax calls. What this does is reduce the chance of Jitter affecting the media stream, by increasing the overall end to end latency on the call. This trade off works because fax was built to handle fixed latency caused in long distance PSTN calling scenarios back in the good old days of TDM voice networks. This functionality does not usually have explicit settings in a VoIP gateway. However, if there is a fax setting that allows you to choose G.711 (passthrough), then it can often be a built in function of this setting.  
  • Ensure that you turn off Silence Suppression (Voice Activity Detection) on all hops. Silence Suppression means that when the gateway detects that audio is under a certain threshold on the call, in an effort to save bandwidth, it will stop sending RTP on the link. For voice calls, this is fine, but for fax calls this is not a good idea.

Note: this is called different things on different gateways. The other most common name is Voice Activity Detection (VAD).


Quintum Silence Suppression Example

Note on AudioCodes: On AudioCodes Media Pack gateways, I’ve had issues with the silence suppression not working. By this I mean that Voice Activity Detection is still being enforced, and the RTP stream is being suppressed during breaks in fax tone. This unfortunately doesn’t mix well with fax.


When you have “No Fax” set in combination with this setting (with the Silence Suppression bug), the fax tones get treated the same as voice.



If you set “G.711 Transport” as the Fax Signalling Method this bug gets bypassed.

  • When you are using a G.711 codec, ensure that you test your volume levels. In Australia we have a great service offered by Telstra called “FaxStream” (1300368999) that allows you to send a fax to it, and get sent back a return fax that details if the audio levels on the call were acceptable or not. Based on the response on some gateways you can tweak the Tx and Rx levels of the voice stream. An example is on Quintum gateways: this is set under the IP Routing Groups->Advanced Tab.
  • Ensure that configuration on the Analog Gateways that the fax machine is connected to, the PSTN Gateway, the SBC, and the carrier SIP network are all correct. Each hop matters as much as the others, so don't fall into the trap of assuming it's one specific device that's the problem without first checking them all.


Wrap Up

Wow! That was a lot of stuff about fax… Who would have dreamed it could be so complicated? So anyway, I hope this helps some of the IT people out there that don’t necessarily have a background in telecommunications. In keeping with the eastern philosophy from the start of the article, I will now leave you with the great words of Mr Miyagi: “Fax on, Fax off, Daniel-san.”


Read more →

Popular Posts