If you’re familiar with making translations changes on the Metaswitch Call Feature Server (CFS), you will likely appreciate the range of tools available to test your changes before activating them for your whole network.
On the CFS, not only can you run Route Verification Tests (RVTs), but you can also assign an Overriding Config Set to a test line, so that all calls from that subscriber use your new translations – allowing you to thoroughly validate your updates without endangering the rest of the traffic on your network.
However, if you are making changes to call policy sets on the Perimeta Session Border Controller (SBC) you don’t have the same tools available. On the Perimeta all calls use the same active call policy set – you can’t assign a different call policy set for test lines. This means that if you are making some large/risky changes to your routing policies, there’s no easy way to test before making them active for your entire network.
We encountered this problem recently on a client migration project and were able to find a pretty decent workaround to the problem, which I’ll share in this article.
Perimeta call policy set design
At a high level, we took the following approach:
- Create duplicates of key routing tables (or perhaps the whole call-policy-set) with a tweaked name (e.g. tablename-new) and implement your routing changes in these new tables (while leaving the old tables in place).
- Add a new table of type rtg-src-id-table which filters calls based on caller ID, and use this to identify calls from specific test lines and route them to your new tables.
- We used a rtg-least-cost-table to provide an overflow route for standard calls (that didn’t match the filter) as we had some problems using the default match regex tools in some circumstances.
Putting that all together, the flow looks something like this.

Filtering on Caller ID in Perimeta
Let’s look in more detail at that FilterCallerID table. Here’s some sample code that we used.
rtg-src-id-table FilterCallerID
entry 10
match-id digits 2345556789
action next-table mynexttable-new
entry 20
match-id digits 2025556789
action next-table mynexttable-new
entry 100
match-id digits "[0-9+#*A-Fa-f]" prefix
action next-table mynexttable-old
entry 101
match-id text-regex .*
action next-table mynexttable-old
This type of table: rtg-src-id-table looks at the calling number, and then matches on that. So in our case we’re matching on a couple of test numbers (234-555-6789 and 202-555-6789) and if the caller ID matches we’re moving to the “-new” routing table to use the new translations we’ve built.
Entries 100 and 101 are an attempt to provide a default match. The first matches any caller ID that begins with any digit as a prefix, and then sends it to the original routing logic. The second handles a text-based caller ID, and matches any text value and sends to the original routing logic.
You would think this was sufficient to split out test calls from regular calls, but we actually found an edge case that wasn’t covered. If the caller ID is totally blank (i.e. a SIP URI that looks like <sip:192.168.1.2>) then this doesn’t match. That may be pretty unlikely, but in case you run into the same problem, we found a work-around, and that’s what leads to FirstTable in the above logic.
Overflow routing if no match is found
If no match is found in the FilterCallerID table, we want the routing logic to have a backup plan – and that’s why we created FirstTable. This table is a least cost routing table, to force it to always check for a match in the FilterCallerID table first, but if none is found we have a higher-cost overflow route into our standard / original routing logic.
Here’s the sample configuration.
rtg-least-cost-table FirstTable
description "Create an overflow route if no match"
entry 10
cost 10
action next-table FilterCallerID
entry 20
cost 20
action next-table mynexttable-old
By combining these two tables, and inserting them in front of your new and old call policy set logic, it’s possible to activate your Perimeta translations, but have the new logic apply only to those test numbers you define in the FilterCallerID table.
Once you’ve tested and you’re happy it all works, you can remove the extra tables – or better yet simply replace all the references to mynexttable-old with mynexttable-new, but leave the framework in place so that it’s easy to test the next set of changes.
I hope you find this useful. There may well be other methods of testing large Perimeta changes – including better options – so if you have a different approach I’d love to hear from you.
And of course, if you need help adding some new functionality to your Perimeta, feel free to contact us.