Implementing Loop Prevention on CUBE

We work quite a lot with a single ITSP in our smaller deployments, but keep hitting a problem with number porting.  We’re repeatedly facing a problem whereby the number porting is done up front, and often in the case of BE6K installations includes numerous number ranges, BRI’s, analog extensions etc.  Often at the time of porting we need to account for 20+ different patterns across 5 or so sites.

The problem crops up when asking for all these ported patterns/ranges in a single list to place on the CUBE.  Quickly it appears that different people requested it, the porting requests were done piecemeal, etc – long story getting all the numbers up front can become a bit tricky.  Not that there is a good reason from it.  It’s a bit of a joke.  But this is what happens.

Come to porting, and we miss a pattern or five.  Now (my favourite part), the upstream provider for our ITSP starts crying because (and wait for it)… we have brought down their network.  They can’t seem to implement loop prevention, and somehow the looping that results from an inbound INVITE only matching the intended outbound dial-peers bombs the providers Media Server – but my little 2RU 2921 stands firm.  I kid you not. 🙂

So, after laughing for about 5min, let’s implement Loop Prevention on our side.  This can be done with COR Lists (vomit), but I prefer to use the newer features in IOS 15.4+, and stick to whats prescribed in the CVD BE6K Edge document.

Here’s the dial plan config that’s pretty much completely scalable – implemented with only 2 dial peers!

 

!
voice class uri 1 sip
host ipv4:<cucm-ip-sub-primary>
host ipv4:<cucm-ip-sub-secondary>
!
voice class uri 2 sip
host ipv4:<itsp-ip>
!
voice class e164-pattern-map 1
description *** To CUCM ***
e164 <internal-dn-range1>
e164 <internal-dn-range2>
e164 <internal-dn-range3>
!
voice class e164-pattern-map 2
description *** To ITSP ***
e164 .T
!
voice class dpg 1
dial-peer 100
!
voice class dpg 2
dial-peer 200
!
voice class server-group 1
ipv4 <cucm-ip-sub-primary>
ipv4 <cucm-ip-sub-secondary> pref 1
description *** CUCM ***
!
voice class server-group 2
ipv4 <itsp-ip>
description *** ITSP ***
!
dial-peer voice 100 voip
description *** CUCM ***
session protocol sipv2
session server-group 1
destination dpg 2
destination e164-pattern-map 1
incoming uri via 1
voice-class codec 1
dtmf-relay rtp-nte sip-kpml
no vad
!
dial-peer voice 200 voip
description *** ITSP ***
session protocol sipv2
session server-group 2
destination dpg 1
destination e164-pattern-map 2
incoming uri via 2
voice-class codec 1
voice-class sip bind control source-interface <external-interface>
voice-class sip bind media source-interface <external-interface>
no vad
dtmf-relay rtp-nte sip-kpml
!

 

Some Notes:

  • The loop prevention hinges on the face that you exclude dial peers using dial-peer groups.  An absolutely fantastic feature.
  • Outbound destinations are serviced by server groups – another brilliant addition.
  • Inbound matching is done using the URI Enhancements provided in 15.x and up
  • I tend to prefer to localize E.164 in CUCM for a Central Breakout Design.  I just like the extensible nature of Called and Calling Transformations.  I believe that this is more in line with the CVD/SRND – could be debated though.

 

A possible modification could drop the server groups (the limitation is that these only support IP), and instead route using DNS SRVs.  I like this approach a lot, and try and implement as such whenever possible.

What’s lovely about this is that the skeleton never changes – I get my patterns added to the e164 pattern map, adjust my IP’s and I’m good to go.

 

Voila!  CUBE implemented in under 5min.  Hope this helps some of you out there.

 

42 thoughts on “Implementing Loop Prevention on CUBE

  1. It’s awesome, Jonathan! You summarized plenty of Cisco Best Practices documents in a single config, very good job. Thank you for sharing this publicly. 🙂

    Like

    1. Hi Yorick

      Thank you very much for your feedback – glad that you found value out of this article! I have implemented a number of CUBE’s with this set-up with high levels of success.

      Please let me know if you have any thoughts on it’s improvement/extensions – feedback is always welcome!

      – Jonathan

      Like

      1. I have actually one comment/question. In the Cisco doc, it’s said that the Outbound dial-peer must have a destination-pattern configured, even if it’s not used for matching.
        So I understand that the destination criteria is never evaluated by the IOS to select the Outbound DP, when the selected Inbound DP is configured to use a DPG.

        In conclusion, I think that the e164-pattern-map commands are not useful here. As soon as the Inbound DP is matched, the Outbound DP is matched automatically.

        What do you think?

        Like

  2. You will always need a dial-peer for the inbound and outbound legs.

    As you can see, I achieve the trivial CUBE configuration with only 2 dial-peers. This means that each dial-peer acts as inbound/outbound depending on the call flow direction. The The e164-pattern-map’s are ONLY used for outbound.

    So, in our ITSP > INTERNAL CUCM call flow:

    – Dial-peer 200 is matched based on the URI presented from the ITSP – I suggest matching on “via” header.
    – This dial-peer specifies voice class dpg 1 that only allows outbound routing via dial-peer 100.
    – Dial-peer 100, in turn, has an e164-pattern-map that lists the PATTERNS that the can be matched the RURI of the INVITE received from the ITSP.
    – If there is a match against any of the listed patterns, the call is routed out dial-peer 100.
    – If not, the call fails with a 404 NOT FOUND sent to the ITSP, which is what we want in this case to ensure Loop Prevention!

    As you can see the e164-pattern-map is a key config requirement. If it confuses you, remember all that it is doing is consolidating multiple destination-patterns into a single dial-peer – before we would have had to duplicate dial-peers for different destinations. This new feature allows you to decouple “what pattern is being matched” from “where the call is routed”.

    HTH.

    Like

    1. Thank you Jonathan for this good recap. I got the logic behind this whole config and I would have done it the same way, mixing DPG and E164-map exactly like you. But, I’m very confused by the Cisco documentation that explains the things a bit differently that the way we would do it.

      Look at this up-to-date guide:
      http://www.cisco.com/c/en/us/td/docs/ios-xml/ios/voice/cube/configuration/cube-book/multiple-outbound-dial-peer.html#reference_F3A9DB8F62C44AABAD4252A026DC4D10

      It’s said: “The destination-pattern command is required on the outbound dial peer even matching is not done based on this command.”

      Also: “Once an incoming call is matched by an inbound dial peer with an active destination dial-peer group, dial peers from this group are used to route the incoming call. No other outbound dial-peer provisioning to select outbound dial peers is used.”

      And in the config details: “Configures a destination pattern. This step is required even though the value is not used for dial-peer matching.”

      And finally in the example, the destination-pattern values seem very dummy, and unrelated to the “incoming called-number value” configured in the inbound dial-peer.

      So, in my understanding, when we force the match of the oubound DP based on the inbound DP, the destination patterns (or E164-map) seem simply ignored.

      In the next weeks I’ll have to implement a new CUBE, so I’ll test it in real-life and see what is the correct behavior.

      Thank you.

      Like

      1. Ignore this, in my opinion it’s a mistake in the guide, or the guide was written before considering e164-pattern-maps. My post is a working config, and I’ve deployed as such on numerous occasions.

        Regarding the destination-pattern matching, again please see my comments regarding outbound dial-peer matching. Nothing has ever changed in this logic, even with the introduction of pattern-maps.

        Let me know how your new CUBE goes! Please feel free to ping me if you have any questions. Always happy to help! 🙂

        Like

  3. Hi Jonathan,

    Thanks for this great article! This simplifies dial-peers considerably and reduces the risk of calls looping. There are some great commands that help with this now.

    I have been running some tests in a lab and whilst I can get inbound and outbound calls routing as expected the ‘e164-pattern-map’ on the dial-peers seems to have no effect strangely. If I add numbers into the pattern maps it’s as if it ignores them and lets any number through regardless. If I remove the e164-pattern-map from the dial-peers the calls still flow as well.

    At present inbound calls to unknown numbers are being forwarded to my UCM server which just sends back a 404 as expected.

    Any thoughts would be much appreciated.

    Thanks,
    Mark

    Like

  4. Hi Mark

    Thanks for your comment.

    “voice class dpg” controls reachability for inbound dial peers. If you are getting a 404, it probably means that it’s not matching an inbound dial peer. I’d suggest running “debug voip dialpeer” to confirm this. You should see the dpg matching in the debug.

    voice class “e164-pattern-map” is simply an aggregator for outbound dial-peers. If your dpg provides reachability to your dial peer that has the pattern map, then your outbound routing should work correctly.

    Share a config, maybe I can help.

    Regards,
    Jonathan

    Like

    1. Hi Jonathan,

      Thanks for your reply.

      I am wondering if this is a Cisco bug. If I run a debug voip dialpeer it is matching the relevant dial peer regardless of what is in the e164-pattern-map. It is as if it is mapped via the incoming URI to the dial peer it completely ignores the e164-pattern-map for the destination dpg and just forwards to the destination dpg regardless.

      Whilst inbound and outbound calling works as expected with your configuration above I can’t filter unknown numbers from going to my UCM server to the pattern map being ignored.

      The config I have is exactly the same as yours above apart from some translation rules I am running for called/calling numbers.

      You can also see in the dial-peer voice configuration the destination being mapped with the e164-pattern-map correctly:

      VoiceOverIpPeer100
      peer type = voice, system default peer = FALSE, information type = voice,
      description = `*** Cisco UCM Cluster ***’,
      tag = 100, destination-pattern = `’,
      destination e164-pattern-map tag = 1 status = valid,
      destination dpg tag = 2 status = valid,

      VoiceOverIpPeer200
      peer type = voice, system default peer = FALSE, information type = voice,
      description = `*** SIP Provider ***’,
      tag = 200, destination-pattern = `’,
      destination e164-pattern-map tag = 2 status = valid,
      destination dpg tag = 1 status = valid,

      A bit odd…

      Any further thoughts would be appreciated before I fault this out to TAC.

      Mark

      Like

      1. Hi Mark

        So before you go to TAC…

        let’s assume the call is from CUCM and you want to dial the PSTN. The incoming called number is +1234567890.

        – call matches inbound dial peer by matching voice class uri with the CUCM IP Address (in my example this is on dial-peer 100). Called number does not take precedence over uri.

        – dial-peer 100 has a voice class dpg 2 -> this limits reachability to dial-peer 200 for outbound dial peer matching (only 200 is specified in the dpg config)

        – dial-peer 200 has an e164-pattern-map that includes a pattern “.T”. +1234567890 matched on .T and the call routes.

        I think there may be an error in your understanding here? I’ve never seen a problem with pattern matching across several versions. If you’re certain this is a problem, maybe do an IOS upgrade on your router (assuming this is in a lab?). May be faster.

        – Jonathan

        Like

  5. Hi Jonathan,

    I’m not so worried about the outbound routing as that is set to allow .T anyway. The call flow I am testing is as follows:

    There is an incoming call from the PSTN to CUCM. The incoming called number is +1234557890.

    – call matches inbound dial peer by matching voice class uri with the SIP provider IP Address (in your example this is on dial-peer 200).

    – dial-peer 200 has a voice class dpg 1 -> this limits reachability to dial-peer 100 for outbound dial peer matching (only 100 is specified in the dpg config)

    – dial-peer 200 has an e164-pattern-map that includes a pattern “+0112233445” only which should therefore block “+1234557890” and send back a 404 immediately. -> This isn’t happening and the call is then sent to the IP address of the UCM server (via session server-group 1) with the UCM server giving the 404 instead.

    I have just upgraded from 15.4(3)M3 to 15.4(3)M6 in the last 5 minutes on my test SBC’s and it has unfortunately made no difference.

    Mark

    Like

  6. I just tested this on a 2911 and didn’t have to implement E164 maps at all. Logic being we only have one SIP provider who should only be sending us what we own and we only have one CUCM cluster, so we just send everything to it.

    So glad I found this as I was about to head down the road of having to implement dozens if not over a hundred dial peers for DID ranges that must have been ordered by a masochist. Now, I only have TWO dial peers. Amazing.

    In case it helps anyone here is what I implemented my test setup. Just a chopped down version of this page really. Use your imagination for the server-groups and incoming uri:

    voice class dpg 1
    dial-peer 1000
    !
    voice class dpg 2
    dial-peer 2000

    dial-peer voice 1000 voip
    description CUCM
    session protocol sipv2
    session server-group 10
    destination dpg 2
    incoming uri via CUCM
    voice-class sip bind control source-interface GigabitEthernet0/0
    voice-class sip bind media source-interface GigabitEthernet0/0
    dtmf-relay rtp-nte sip-notify
    codec g711ulaw
    no vad
    !
    dial-peer voice 2000 voip
    description ITSP
    call-block translation-profile incoming BlockInbound
    call-block disconnect-cause incoming invalid-number
    session protocol sipv2
    session server-group 999
    destination dpg 1
    incoming uri via FreePBX
    voice-class sip bind control source-interface GigabitEthernet0/2
    voice-class sip bind media source-interface GigabitEthernet0/2
    dtmf-relay rtp-nte sip-notify
    codec g711ulaw
    no vad

    Like

    1. Hey Jim

      Glad it helped you as well! I like your config by the way. The e164-maps eliminate the “trust” in your ITSP with your assumption. If you get sent gibberish, this prevents it from being backhauled to your SIP server. I prefer this method as it adds to your application-layer boundary. I see that you’re maybe doing something similar with a translation-profile though.

      – Jonathan

      Like

  7. This is an excellent post. Thanks, Jonathan. Looking forward to Jim’s response re translation profiles configs to block unwanted incoming numbers from ITSP.

    -Thanks/Anil

    Like

  8. This is flipping awesome!!!! Most people don’t really this, but upgrade the code on your CUBE is beneficial! We had a similar issue where we didn’t have the new DID block programmed on our CUBE, but turned up on provider’s end…. Well someone for whatever reason was attempting to call one of the new DID numbers and of course it wasn’t provisioned on the cube(dial-peer)… so cube sent it back to and out sip provider spit it back to us causing a loop!!!! soo annoying…. eating up most of our ccp’s! here are a few recommendations I would make… Basically also, voice gateways hunt by default, so if a failure is received from Call Manager (first pattern in the example), the second route (ITSP) is attempted, starting the loop.

    1.) Code on CUBE is important taking advantage of cmd’s for example below:
    no voice hunt invalid-number
    no voice hunt user-busy
    no voice hunt unassigned-number

    https://www.cisco.com/c/en/us/td/docs/ios-xml/ios/voice/vcr5/vcr5-cr-book/vcr-v2.html#wp3173390130

    2.) Making sure you provision the new did’s at the same time it’s provisioned on the providers end :).

    Like

    1. Hi Joel,

      Thanks for the message! Glad you found it useful. I’ve used some of these voice hunt features before, but will certainly look at extending my standard templates… Thanks for the share.

      – Jonathan

      Like

  9. Hey Johnathan,

    Curious to know what version of IOS are you running on your CUBE? Thinking about upgrading our CUBE in one location and would like to know what version you are running? It’s a 2901 CUBE… additionally we are looking to upgrade to a newer model since it’s EOS.. perhaps a 4431. Any feedback you can provide on that model?

    Like

    1. Hey Joel,

      I’ve been stuck in more of a design capacity of late, and got stuck maintaining other people’s CUBE configs. Haven’t tried this on the 4000 platforms… Can’t remember the last IOS version I tried this on, but all that config will work on the latest stable v15.x train… I can’t see why there’d be any issues on 4000, but, its new, and has had a lot of bugs. Sorry, can’t help you there man…

      – Jonathan

      Like

      1. I personally don’t see the value proposition for the 4000 Series ISR for Collab. At all. Waste of money. No major features with jumping about. Just lots of bugs. Better for other verticals.

        Like

      2. It’s a pleasure, Sir! Sadly, I haven’t had enough time to blog recently… If you have any ideas for topics you’d be interested in, please let me know!

        Like

  10. FYI below is another way of accomplishing it as well:

    voice class e164-pattern-map 10
    description OUTBOUND-CALLS
    e164 911
    e164 91[2-9]..[2-9]……
    e164 1[2-9]..[2-9]……
    e164 9[2-9]..[2-9]……
    e164 9[^1]T
    !
    !
    voice class e164-pattern-map 20
    description INBOUND-CALLS
    e164 +1312XXXXX..
    e164 1312XXX….
    !
    COLLAZOLAB2911R#show running-config | s dial-peer
    dial-peer voice 10 voip
    description ITSP-SIP-FLOWROUTE
    translate-outgoing called 10
    session protocol sipv2
    session target sip-server
    destination e164-pattern-map 10
    voice-class codec 1
    voice-class sip bind control source-interface GigabitEthernet0/1
    voice-class sip bind media source-interface GigabitEthernet0/1
    dtmf-relay rtp-nte
    no vad
    dial-peer voice 20 voip
    description CUCM
    call-block disconnect-cause incoming invalid-number
    session protocol sipv2
    session server-group 20
    destination e164-pattern-map 20
    voice-class codec 1
    voice-class sip bind control source-interface GigabitEthernet0/0
    voice-class sip bind media source-interface GigabitEthernet0/0
    dtmf-relay rtp-nte
    no vad

    Liked by 1 person

  11. Hi! Me again! Would love to get your guidance on a project I’m working…. I’m currently working on a new voice implementation design in a new datacenter. Just curious on your opinion on the cube location. Options below:

    1. Cube Directly connected to our internal facing network, using the cube as a border, address hiding, ip trust list and acl.
    2 interface facing internal with a loopback for rtp streaming and signaling… 1 interface directly connected to the ITSP – dedicated internet xc. This what I’m familiar with honestly :).

    2. Cube directly connected to the firewall and have sip inspection enabled/Alg layer 7 configured. ITSP will directly connect to the cube on one of interfaces- dedicated internet. Not so familiar with :).

    What are your thoughts on 1 and 2? Additionally, someone asked me why can’t we have the itsp provider connect to the firewall or in front of the cube and not on the cube. I was stumped and couldn’t answer it.

    Any feedback would be greatly appreciated!!!!!!!!!

    Liked by 1 person

  12. option 1 is always easier (with two physical interfaces), as it’s typically directly routed and the config is easy to do.

    option 2 is more difficult, as it involves NAT. its very doable, but you’ll need to play with settings for CUBE and/or FW doing ALG functions. I have done this less. Last time I did it, we had to play around with FW settings and CUBE NAT config. Sadly, I didn’t document a working config.

    In short – option 1 if you can. If option 2, set up testing slot where both you and FW team can make changes on the fly while you test your configs. Have a good test plan to run through normal calls and midcall signalling scenarios – transfer, call forward, music on/off hold, etc.

    Like

      1. Hi! Me again :).

        Do you have anything on e164 Globalized Dial-plan in CUCM with Sip Trunk? Basically having a hard time getting the e164 redial missed call and transformation any incoming calls to e164 for local and international calls. Any help would be appreciated!!!

        Like

      2. Either apply transformations on your SIP Trunk in CUCM using calling/called party transformation CSSs, or do this in IOS before inbound to CUCM. A key decision point is often if you require SRST, and how that affects your dial plan. Its hard to give a simple answer as there are many ways to cut this. Personally, I prefer IOS translation rules for SIP gateways (inbound and outbound dailling), but have employed both.

        Like

  13. Hi This is really good. tho I am having issues with outbound call from an IP Phone. It turns out busy tone. What should i look for?

    configuration as per below

    voice class uri 1 sip
    host ipv4:N.N.N.N
    !
    voice class uri 2 sip
    host dns:yourawesome.dns.com

    voice class e164-pattern-map 1
    description ***to CUCM***
    e164 123456..
    e164 1234….
    !
    !
    voice class e164-pattern-map 2
    description *** To ITSP ***
    e164 .T
    !
    !
    voice class server-group 1
    ipv4 N.N.N.N
    ipv4 N.N.N.N preference 1
    description *** CUCM ***
    !
    voice class server-group 2
    ipv4 N.N.N.N
    description *** ITSP ***
    !
    voice class dpg 1
    dial-peer 700
    !
    voice class dpg 2
    dial-peer 701

    dial-peer voice 700 voip
    description *** CUCM ***
    translation-profile outgoing TEST
    session protocol sipv2
    session server-group 1
    destination dpg 2
    destination e164-pattern-map 1
    incoming uri via 1
    voice-class codec 2
    dtmf-relay rtp-nte sip-kpml sip-notify
    no vad
    !
    dial-peer voice 701 voip
    description *** ITSP ***
    session protocol sipv2
    session server-group 2
    destination dpg 1
    destination e164-pattern-map 2
    incoming uri via 2
    voice-class codec 2
    dtmf-relay rtp-nte sip-kpml sip-notify
    no vad

    Liked by 1 person

    1. Start with the sip message message flow for a sample error call, and look for the 4XX or 5XX final SIP message that should explain or hint at the cause of the issue. Look for a cause code as well.

      Always best to start with debugs before looking at config.

      Like

      1. Hi Jonathan,

        Thanks. with regards to the below which is the destination pattern map to CUCM. Should I be including the internal DNs? or stick with a translation profile on the dial peer itself?

        voice class e164-pattern-map 1
        description ***to CUCM***
        e164 123456..
        e164 1234….

        ***
        dial-peer voice 700 voip
        description *** CUCM ***
        translation-profile outgoing TEST

        Liked by 1 person

      2. Your snipped doesn’t include a “destination e164-pattern-map XXXX” statement, so i can’t see what you’re doing as destinations for routing purposes. The choice to use E164 or DNs in your pattern map depends on your dial plan. In your example you’ve applied “translation-profile outgoing”, meaning that the translation occurs after routing to the destination. This will affect your dial plan, so plan accordingly.

        Like

  14. Hi Jonathan,

    thanks again. desitnation e164 was on the dial peer

    dial-peer voice 700 voip
    description *** CUCM ***
    translation-profile outgoing TEST
    session protocol sipv2
    session server-group 1
    destination dpg 2
    destination e164-pattern-map 1

    I actually figured out what is causing the issue and it has something to do with the server group. i have to use session target instead of server group as it looks like our ISP is not recognising uri when we send using IP if that make sense?

    Liked by 1 person

    1. Yeah, that can be a requirement for some ITSPs. The server group construct makes sense if there are multiple potential destinations. If just one, a session target also works fine. As an aside, you can also specify ipv4 addressing in the server group.

      Like

  15. Hi (me again)

    Sorry to bug you, but I had a real world question that maybe you can perhaps guide me through.

    I have a London site that is been in production for a few years with a cube configuration with Colt the itsp (sip-server ip4:84.14.x.x).We’re now opening a Dublin Ireland site and we need v voice connectivity but our Ireland datacenter isn’t ready and since we’re using the same provider colt we can leverage our circuit in London…. leveraging the same cube public ip to the carrier, but they provided us a new signaling ip. Is it possible to use separate/second signaling ip’s for 212.36.x.x aka “sip-server ip4:212.36.x.x”?

    Like

Leave a comment

This site uses Akismet to reduce spam. Learn how your comment data is processed.