Teams Network Roaming Policies

Roaming policies are a relatively new addition to Microsoft Teams. Their predecessor in Skype for Business was called Call Admission Control, which is an industry term for “should I admit this call onto the link it’s destined for, or will that overload it and cause issues?”.

The SfB configuration for CAC was (is?)…. not fun. You needed to build out policies based on each sites connection to other sites and regions, you had to sort per-user and per-site restrictions, and you had to make broad assumptions around how much bandwidth particular calls may consume. It did allow for calls to be placed from one SfB user to another via the PSTN in situations where the WAN link was at capacity (or down), and that configuration was fun. (Or maybe I was just tired?)

But Dear Reader, bandwidth consumption is highly dependent on payload/user activity! For example, a video of a user sitting in front of a webcam, in front of a blank wall, will consume different amounts of bandwidth if that user is wearing a plain shirt versus a patterned shirt. Why? Video compression/encoding depends on changes between frames, and a patterned shirt will result more changes than an equivalent plain shirt. So I’m supposed to plan bandwidth consumption based on the shirts people wear? Well no, that’s just one example. Screenshares of a static document will consume less than a video, or a screenshare of a web page with ads popping up all over the place. A voice through an SBC call may flip to G711 and consume 64k (plus overhead) across a WAN, where as a voice call between two clients may use a “better” protocol and consume 8 or 16k.

A second consideration was that CAC couldn’t account for backup WAN links, or SDWAN capabilities, it only used the values you told it were available between the two sites. If you had a backup link that had a lower bandwidth and you were adventurous, you could try to restrict usage over that backup link using things like DSCP priority tags – you could, for example, block video traffic from the backup link, allowing voice traffic through.

The other complication with CAC, is that it didn’t take in to consideration what the actual available amount of bandwidth on the link was. You had to ballpark that “this is a 100Mb WAN link, and we’ll say that SfB can use 10Mb of that”. Well, if the actual available bandwidth is 40Mb, why are we restricting SfB to 10Mb? There were thoughts and some options about software defined networks and having the network able to talk to the applications and make dynamic decisions, but that sounds like as much fun as dumping a couple dozen forks in your bed and trying to go to sleep.

When Teams launched, there was no consideration for CAC until Roaming Profiles came along. Roaming profiles greatly simplify things. You don’t need to indicate the size of any links, which makes sense given that Teams could use WAN/SDWAN links or Internet connectivity, and that WAN/SDWAN links might be running as VPNs over the Internet link anyway. The net result is that you can restrict whether users in that site can use video, and the maximum media bitrate that each user can consume.

How this works is pretty simple. The parameters is this policy (applied to the site) override the parameters in the user’s policy (either the global or per user policy), while the user is in the site.

And one more catch: There’s another policy setting that allows the Roaming Policy to take effect if the user isn’t voice enabled:

To enable the network roaming policy for users who are not enterprise voice enabled, you must also enable the AllowNetworkConfigurationSettingsLookup setting in TeamsMeetingPolicy. This setting is off by default.

From https://learn.microsoft.com/en-us/microsoftteams/network-roaming-policy

And

From https://learn.microsoft.com/en-us/powershell/module/skype/set-csteamsmeetingpolicy

Note that the explanation in Teams Admin Center (if you hover your mouse over the i) isn’t clear about the fact this setting is only for non-voice users.

 From Teams Admin Center:

If this policy isn’t configured, then the roaming policy won’t kick in for non-voice users. If you deploy roaming policies, you will likely want to flip this setting on all global and user policies.

Call Queue Timers and Tips

If you need backup or alternate agents to answer a call, Call Queues offer a number of ways to do this with call distribution methods like round robin or serial routing. Every so often, I encounter an organization that wants to have a second Call Queue be a backup or escalation for a primary Call Queue.

This could be because the primary Call Queue already has multiple agents that are busy, so a second Call Queue is needed to add a second list of ordered agents. It can often be because the organization wants a different call routing method used for the backup vs the primary. For example, the primary might be round-robin, and the back might be attendant. That would be a case of “if you’ve tried everyone available in customer service in round-robin, now try everyone in inside sales at the same time”.

There are some considerations here with Call agent alert time (how long each agent rings for) and call timeout handling (how long the caller is in this queue before some timeout action takes place), as well as the Call overflow handling (what to do when there are too many callers waiting in this queue).

Let’s start with a simple example. If you have an Agent Alert time of 15 seconds and a Call Timeout value of 20 seconds, the caller will remain in the queue for 30 seconds:

This is because the “Call Timeout” value is only considered each time the Agent Alert Time expires. At the 15 second mark, the first Agent Alert time has expired, Teams checks the Call Timeout and it has not expired, so it rings another agent and keeps the caller in the Queue.

After 30 seconds when the second Agent Alert time expires, Teams checks the call Timeout and finds it has expired and takes the timeout action that you’ve defined.

Call Overflow handling takes place when a new caller would be added to the Queue. If the Overflow value is 10 and the 11th caller tries to join, Teams will instead use the call Overflow action that you’ve defined.

Let’s say your second queue overflow and timeout actions send the caller to voicemail. Your primary queue call timeout should send callers to the second queue. However, your primary queue overflow should send users directly to the voicemail and not to the second queue. This is because these callers are new and sending them directly to the second queue means that they are skipping the line and now have less time to wait for an agent than those callers waiting in the primary queue:

When Your IP Subnets Span Sites and Break Teams Location Things

Perhaps the most time consuming portion of the Teams voice projects that I’m involved in relates to location…  A Teams user’s location can be used for emergency calling, bandwidth consumption over constricted WAN or internet links, or things like location based routing and local media optimization.

One of the first questions I ask is: “Do you have subnets that span multiple buildings, especially for wifi”. For emergency calling, each building or facility may need to be broken up into “dispatchable locations” if you’re reading legislation or “places” in Teams lingo. Essentially, if you’re a large building like a school or factory, how do the first responders find you? That’s your “emergency response location” or your “place”. You’ll need a network characteristic to establish which place a Teams client is in. That could be subnet, the switch chassis ID, or the switch port on that switch you are connected to, or it could be the BSSID, which reflects which access point you’re connected to.

If you have IP subnets that span buildings, you will need to re-subnet in order to get the proper physical granularity that’s needed for location-based functions in Teams.  There are a couple of exceptions to this.

First, if the only spanned subnets you have are for server/storage infrastructure, you’re fine. Just ensure that phones can’t be plugged into this network (which you should be doing anyway!), especially a server room phone.

The second exception would be if you don’t need any Network Site based policies other than Emergency Calling Policy. This is the one that notifies someone at the facility that an emergency call has been placed. In the US, the FCC website says (this is Kari’s law):

“When a 911 call is placed on a MLTS system, the system must be configured to notify a central location on-site or off-site where someone is likely to see or hear the notification.”

From https://www.fcc.gov/mlts-911-requirements

Typically, you would need to notify someone at that site about the emergency call, and “that site” has IP subnets associated with it, and an Emergency Calling Policy associated with it. The Emergency Calling Policy handles the notifications, so if a subnet spans multiple sites, you can see how this makes it impossible to notify someone only at the site from which the call was placed.

There are two options or scenarios here. The first is one in which you can notify parties at both/all sites, and train them how to tell when a call is from their site, and to take appropriate action. The second would be when you have something like a central security desk that can be notified, and that security desk can then take appropriate action – commonly this is facilitating first responder access to the building, but it could also be first aid or security teams responding to the incident.

A university campus is an example of a site where I common encounter IP subnets that span sites/buildings/facilities. It’s also a great example of a site where this many not matter, and every university that I’ve encountered has security and/or police departments who can handle responses to these notifications.

An example of where things don’t work with spanned subnets would be a wifi subnet that spans the facilities for a municipality that doesn’t have a security desk (though they may have some “in charge” of security). A call to emergency services from a library would need to notify someone at the library, and not HR, IT or city hall reception. This isn’t so much because they couldn’t in turn notify someone else at the library to take action. My concern here would mainly be around availability and hours of work. If the library is open until 9pm and HR, IT, and city hall are all closed, you’re not notifying anyone.

In a case like this, I would recommend the city to re-subnet their wifi. In some cases, depending on their wifi controller(s), this could be a painful exercise, as some wifi controllers cannot have a single SSID (which is desirable) across the organization use a different subnet at each location. Instead, one SSID would need to be created per location, and then all of the wifi clients at that location would need to have their wireless connections updated to the new SSID. That’s no fun but is necessary in many cases to properly meet emergency calling legislation, or to use other location-based policies like Network Roaming (WAN/Internet bandwidth consumption limits for Teams, based on the site).

Change a Resource Account Type Between Auto Attendant and Call Queue

When you create a Resource Account in Teams Admin Center (or via PowerShell), you need to specify whether the Resource Account will be for a Call Queue or an Auto Attendant. Under the hood of Teams, that makes a difference.

Every so often, a customer I’m working with needs to change a Resource Account from an Call Queue to an Auto Attendant, usually to take advantage of schedule that’s present in Auto Attendants. If you need to do this, you can use the Set-CsOnlineApplicationInstance.

First, use Get-CsOnlineApplicationInstance to see what you have

You can tell by the DisplayName field that my first two items are Call Queues, the other three happen to be Auto Attendants.

If I want to change “TestQueue” to be for an Auto Attendant instead, I can do this

Boring, right?


Note that 11cd3e2e-fccb-42ad-ad00-878b93575e07 is the ApplicationID for a Call Queue object, and ce933385-9390-45d1-9512-c8d228074e07 is for Auto Attendants.

Restricting Where Common Area Phones Can Call Internally

Restricting where a user can call internal to your organization is complex. If you must do this for compliance reasons, you need to take a look at Information Barriers.

One of the complexities is that in a Teams client the user can find another user by name and click to call them. They can do this same type of lookup on phones too.

Common Area Phones are more restricted than users, and it’s a simple policy change to allow or prohibit the lookup of users on a phone. We’ll typically see this restriction in place on phones in public areas, like a lobby courtesy phone. If you want to further restrict that public area phone can call by dialing numbers, you have just one option.

In a previous post, we talked about a Dial Plan normalization rule that would translate one phone number into a different, invalid phone number to prevent the original number from being called. If you want to restrict a CAP from calling anything other than one internal number, you can use the same procedure, but instead of the invalid number, translate all numbers to the number you want the phone to be able to call.

This sample rule allows the CAP to only call +14255551212, the security desk in my example:

And if I want the CAP to be able to call HR at 6789 and then have all other calls go to security, I could do something like this with two rules, since they’re processing in top-down sequence:

And you could add as many rules as you wanted, just make sure they’re above the ^(.*)$, which is the catch-all that should be at the bottom of the list.

Blocking Calls to the PSTN with Direct Routing

If you’re on Direct Routing, blocking calls is as “simple” as ensuring that there is no route to the destination in the Voice Routing Policy assigned to the user placing the call.

For example, if we have a voice usage for national calls that looks like this ^\+(1\d{10})$ then any call that matches +1xxxxxxxxxx (that’s ten x if you’re wondering) will be allowed through. Carrying on with our example from previous posts of blocking calls to the 425 area code, we could change the route pattern to

^(\+1((?!425)|(\d{3}))\d{7})$

And calls to the 425 area code would no longer match this entry. That regex looks a bit gnarly. The +1 will always need to be at the start. (?!425) means “not 425”. The | is an OR, and (\d{3}) is any 3 digits. This says “We need +1 then (Not 425 but any other 3 digits) then 7 more digits.

If you have multiple voice usages – perhaps for service numbers, national, and international – you should be able to modify only the voice route associated with the national usage to block calls to the 425 area code.

This will work because a call to +1425xxxxxxx wouldn’t match with other typical usages, like service numbers (2xx-8xx) or international (country codes other than +1). However, if you have a more complex setup of usages and routes, you will need to ensure that a route further down the ordered list of usages does not allow the call. That is because while usages are evaluated top-to-bottom, evaluation continues until a route match is successful AND the call completes OR until the list is exhausted.

If you have ^(\+1((?!425)|(\d{3})\d{7})$ route in a usage above ^(\+1(\d{10})$ then a call to the 425 area code would be blocked by the first usage but would match the second usage.

This will definitely catch people using (.*) as a catchall for international calls at the bottom of their usage list. This also means that you cannot simply create a usage and route that blocks a call and insert it into the list of usages above a rule that would allow it. Your exception/block must take place in the same route regex that would match and permit the call.

Blocking Calls to specific numbers on the PSTN: This solution is good, but may not bulletproof

If you need a “best effort” method to block external calls to specific numbers, but aren’t hugely concerned over whether the solution is perfect, there is an option that will work with Calling Plans, Direct Routing, and Operator Connect.

Teams Dial Plans normalize the number a user enters on the keypad (or clicks on), usually into E.164 format. This allows users to dial based on their habits versus adherence to the E164 format. For example, they might dial 425 555 1212 and Teams will normalize this into +14255551212 to actually place the call. We can take advantage of this for call blocking by creating dial plan normalization rules that translate the dialed number into something other than the proper E164 format.

For example, 425xxxxxxx might get translated into +11001234567. That number doesn’t exist under the number plan for the +1 country code, so the call will fail. (It’s technically invalid, there are no area codes beginning with “1” in the North American Numbering Plan. Yet anyway!).

If you build something like this out, note that the “test” field here won’t allow you to put a + in front. You’ll have to test without the + here, and then test with the + at the client level.

Notice that the rule has \+?1? in front of the condition. That will match a + or 1 if they’re present, but doesn’t require them to be there. This means that even if a user knows how to dial an E164 number, this method can still catch and block the call.

You could get trickier here and translate to an E164 number that belongs to one of your Teams endpoints, and users would wind up connecting to that Teams endpoint. You could use Teams Routing Rules to build a rule that would play a message to the caller if these numbers were dialed.

I did say above that this solution may not be bulletproof. It’s possible that a client may implement number normalization in such a manner that it won’t match on a number in E164 format, on the assumption that it’s already in E164 format so it does not need to be normalized.

This is also where I put on my consultant hat and talk about non-technical aspects. If you have a user who is routinely abusing your phone system, and there is not technical solution to the issue, you may need to implement non-technical measures – a trip to HR, a visit with the school principal, etc..

Blocking Calls to the PSTN

It’s common for an organization to want to restrict where a user or phone can call outside an organization, especially long distance tolled calls. There are a number of different ways to do this, with a variety of different administrative impacts.

If a user has calling plans, the first way would be to only license the account for domestic calling, versus domestic and international. If you do this, note that adding a Communications Credit license to the user will allow them to make international calls on a pay-as-you-go basis. You might want communications credits assigned to a Calling Plan user to allow them to continue to make outgoing calls once the “per user per month” pooled minutes expire. If that’s the case, you’ll need to implement an additional method discussed below.

Regardless of whether a user’s PSTN service is via Calling Plans, Operator Connect, or Direct Routing, you can restrict where they can call in Teams Admin Center:

Here, I can block outbound calling entirely with “Don’t allow”, permit international calling with “Any destination” or only to Karl’s own country/region with the middle option “In the same country or region as the organizer”.

The text here – specifically the word “organizer” – would lead you to believe that this is for dialout from meetings. However, it does also apply to PSTN calls Get-CsOnlineDialOutPolicy (SkypeForBusiness) | Microsoft Learn

Note that this restriction will apply regarding of Operator Connect, Direct Routing, or Calling Plans being the PSTN connectivity option for the user.

This isn’t a terribly granular capability. If you’re on Operator Connect, your operator may be able to do some extra screening for you. There are some other solutions that may work well, or at least well enough, for your scenario, in my next post.