Boundary Group Caching and Missing Boundaries

Boundary Group Caching and Missing Boundaries

What is Boundary Group Caching

Boundary group caching was introduced with the first version of System Center Configuration Manager (ConfigMgr) Current Branch (CB): version 1511. As the term implies, clients cache the name of their current boundary groups. They are then able to send this cached boundary group name to the management point during content location requests. By caching the boundary group and sending it along with each content location request, the management point no longer needs to look up a client’s boundary or boundary group for each and every content location request. This dramatically reduces the additional load on management points and the site’s SQL Server instance caused by these repetitive, redundant lookups.

When Do Clients Cache Their Boundary Group

Similar to management point assignment, client’s refresh their current boundary group at three “times”:

  • Every 25 hours
  • At client agent startup
  • When a network change is detected

Where Do Clients Cache Their Boundary Group

As with most things in ConfigMgr and on a ConfigMgr managed system, in particular, the answer is in WMI. Specifically, in the root\ccm\LocationServices namespace in a BoundaryGroupCache class object. This class contains two attributes:

  1. BoundaryGroupIDs — An array of IDs corresponding to the IDs of the boundary groups that the client is a member of.
  2. CacheToken — The time the cache was refreshed last.

The following screenshot is from WMI Explorer on one of my lab clients and shows the content of an instance of this class. If the client does not fall within the scope of any boundary groups, then the BoundaryGroupIDs attribute will not exist in the instance of the class.

The BoundaryGroupCache class in WMI

Note

As of CB 1610, all clients that do not fall within the scope of a defined boundary group will be associated with the Default Boundary Group. This is not reflected in the BoundaryGroupCache class. Essentially, if the instance of the BoundaryGroupCache class contains no BoundaryGroupIDs, then the client is considered within the scope of the Default Boundary Group.

The Boundary Group IDs aren’t shown directly in the ConfigMgr console; however, you can quickly get them in PowerShell, via WMI (from the site’s SMS Provider), or SQL. With PowerShell, connect to your site and use the Get-CMBoundaryGroup cmdlet.

Boundary Group Names and IDs from Get-CMBoundaryGroup

In SQL, merely query the vSMS_BoundaryGroup view.

Boundary Group Names and IDs from the vSMS_BoundaryGroup view

Note

I can find no evidence of boundary caching activity in any standard client logs so if you need to check the values or when the boundary group was cached, check WMI.

WMI You Say

Yes, WMI. That means that we can add this class to hardware inventory to collect the information from the clients periodically.

Add BoundaryGroupCache to Hardware Inventory

Missing Boundaries

Once ConfigMgr collects the Boundary Group Cache information using hardware inventory, you’ll be able to easily identify clients that do not fall within the scope of a defined boundary group. To do this, create a new Query in the ConfigMgr console with the following specified on the General tab:

Class Attribute
System Resource NetBIOS Name
BoundaryGroupCache BoundaryGroupIDs

Boundary Group Query

Note

Always use the NetBIOS Name attribute in your queries when you want to show the name of a system from the System Resource class as this attribute is backed by an indexed column in the SQL Server database.

Alternatively, you can use the following WQL in your query:

select SMS_R_System.NetbiosName
, SMS_G_System_BOUNDARYGROUPCACHE.BoundaryGroupIDs
from SMS_R_System
inner join SMS_G_System_BOUNDARYGROUPCACHE
on SMS_G_System_BOUNDARYGROUPCACHE.ResourceId
= SMS_R_System.ResourceId

In my lab, running this query results in an easy view of which clients do not fall within a defined boundary group (hint: it’s Win301 because the second column is blank for it).

Boundary Groups Query Results

You can, of course, modify, incorporate, improve, etc. this query as you see fit to give you exactly the results that you need. You can even translate it into a SQL query or report. Here’s a SQL statement to start with (note that this requires SQL Server 2016 and the database to be set at compatibility level 130 for the STRING_SPLIT function):

SELECT
rsys.Netbios_Name0 As Name
, (SELECT
bg.Name
FROM vSMS_BoundaryGroup bg
WHERE bg.GroupID = value) As 'Boundary Group'
FROM v_R_System rsys
INNER JOIN v_GS_BOUNDARYGROUPCACHE bgc
ON bgc.ResourceID = rsys.ResourceID
OUTER APPLY STRING_SPLIT(bgc.BoundaryGroupIDs0, ',')

Not being within the scope of a boundary group means one of two things — both of which are probably problematic and should be addressed:

  1. The client is not within the scope of any boundary.
  2. The client is within the scope of a boundary, but that boundary is not included in any boundary groups.

Either way, the client will automatically and immediately fallback to the Default Boundary Group and the site systems associated with it. This is probably not the desired result. If not, the next step is to lookup the IP Address of the client and see if it falls within a defined boundary. If not, it’s time to adjust your boundaries or create a new one. If it does fall within a defined boundary, then it’s time to figure out why that boundary is not included in a boundary group and either include it in an existing boundary group or create a new one.

19 Comments

Cancel

  1. Mad skills, Jason. This is very helpful to me in my site evaluations. Thanks.

  2. Great article. I also added the IP Address column to the query so I can spot any ranges I might be missing.

    • Awesome. Blog it 🙂

      • Please do share Mike how you added the IP column to the query to spot any ranges missing

        • Which query are you referring to?

        • Here is the ConfigMgr query which also shows the IP address and the AD site name.

          select SMS_R_System.NetbiosName, SMS_G_System_BOUNDARYGROUPCACHE.BoundaryGroupIDs, SMS_R_System.ADSiteName, SMS_R_System.IPAddresses from SMS_R_System inner join SMS_G_System_BOUNDARYGROUPCACHE on SMS_G_System_BOUNDARYGROUPCACHE.ResourceID = SMS_R_System.ResourceId

          • Hey Jason, Hope you’re doing well. Sharing with you my query that, looks to me to be super inefficient, but it runs against 40k records in 4 seconds and appears to give me the results i need without having to modify the SQL Compatibility level, which can cause some other issues with SCCM if you change from 110 to get that fancy split_string function.

            Here it is – I would be curious to know how this works for others:

            select count(distinct resourceid) [#SystemsPerBoundaryGroup], bg.name
            from vsms_boundarygroup bg
            left join (
            select bgn.name, bgc.BoundaryGroupIDs0, bgn.groupid, bgc.resourceid from v_gs_boundarygroupcache bgc
            join (select groupid, name from vsms_boundarygroup) bgn on bgc.BoundaryGroupIDs0 like ‘%’ + cast(bgn.groupid as varchar(max)) + ‘%’
            ) BoundariesSplitUp on bg.groupID = BoundariesSplitUp.GroupID
            group by bg.name
            order by bg.name

  3. Thanks Jason,

    any idea if it’s possible to temporary add a BoundaryGroupID to the array?

    I tried

    $bdryGrpCache = Get-WmiObject -Namespace ‘Root\ccm\LocationServices’ -Query “Select * From BoundaryGroupCache”

    $bdryGrpCache.BoundaryGroupIDs += 16777219

    It works, but the added ID is immediately removed. And my skills ended 😀 Any idea how to avoid the removal, if possible?

    Thanks you.

    • I doubt that this is possible. I can see it being used for testing but local manipulation of these things could be pretty bad management wise so it makes sense that it just gets overwritten right away.

  4. i dont see boundarygroupcache table in the database , please advise.

    • Where exactly are you looking for it and what exactly are you looking for?

      Did you add the WMI class to your hardware inventory?

  5. Hey Jason –

    Great post – thanks! How were you able to determine the three “times” that clients refresh their boundary group assignment? Is it documented somewhere (a cursory search of MicrosoftDocs didn’t seem to give me anything) or is it reflected in the client logs somewhere?

  6. Thanks Jason, great article, I’m sure this will come in handy. However I have a different issue where I have removed a boundary from a boundary group( as a test). A client in that boundary, still says its part of the boundary group. We have no fallback setup. I’m having issues of clients in a second domain going across the firewall for content from the DPs instead of its own DP, assigned by boundary groups. Microsoft are stumped with this one too.

    • Clients won’t rediscover their boundary group until they detect a client-side network change, 25 hours, or the agent is restarted (whichever comes first).

      What kind of boundaries are you using?

      • All IP ranges. Test machines have been turned on and off multiple times, client reinstalled. Even create a new boundary group, moved the test boundary over, restarted the machines, ran wbemtest, its now part of the new group and the old one.
        Think I need to delete that old group. Is there anyway of moving the boundaries from one group to another? There are 750 boundaries to move.

  7. Hi Jason,

    I am looking for a way to exclude clients from software deplpyment when they are in particular boundary groups. I have created BoundaryGroups with IP addresses when the clients use VPN. I would like to deploy software, but the clients should only get the software if they are NOT in the desired boundary (VPN). Do you know how I can implement this as a query? Your solution here is already going in the right direction.

    Thank you!

    • Assuming your VPN is configured for split-tunneling, why not configure the boundary group to prefer cloud sources for content?