Cisco introduced some pretty cool URI enhancements for CUBE from 15.4(1)T that have added some great extensions to the CUBE feature set, and specifically include some fine-grained SIP routing control. These have been long overdue as IOS-based VoIP routing has been heavily dependent on numerical pattern matching due to Cisco’s ongoing support for H.323-style legacy configuration.
These enhancements are covered in a lovely Cisco doc here. I’ve also blogged previously on a similar topic on how to utilize these and other new CUBE SIP features to provide Loop Prevention on CUBE.
To start, the basic configuration for URI dial-peer matching is somewhat trivial:
!voice class uri voice-class-uri-tag sip|telhost hostname-patternhost ipv4:ipv4-addresshost ipv6:ipv6-addresshost dns:dns-addresspattern uri-patternuser-id username-pattern!dial-peer voice tag voipsession protocol sipv2incoming uri { from | request | to | via } voice-class-uri-tag!
Here we see that incoming called-number is dropped and is instead routing using incoming uri. Typically, we’d match the URI on a via header, with our voice class uri container applying a match on our preferred IP Address / DNS address.
I am referring to RFC compliant behaviour for the Via header from RFC 3261:
8.1.1.7 Via The Via header field indicates the transport used for the transaction and identifies the location where the response is to be sent. A Via header field value is added only after the transport that will be used to reach the next hop has been selected (which may involve the usage of the procedures in [4]). When the UAC creates a request, it MUST insert a Via into that request. The protocol name and protocol version in the header field MUST be SIP and 2.0, respectively. The Via header field value MUST contain a branch parameter. This parameter is used to identify the transaction created by that request. This parameter is used by both the client and the server.
Here we note that a SIP Request can contain multiple Via headers. This is used as a loop prevention mechanism for SIP Routing. This becomes incredibly import when multiple SIP Proxies forward requests. This is well described here for the SIP initiate.
With this in mind, I came across an interesting scenario recently where a call route through an ITSP’s SIP Proxy network changed without my knowledge, meaning that the Via header ordered list in the inbound INVITE changed. This resulted in not matching my voice class uri configuration. This stymied me at first until I noted the following for this feature:
In a scenario where multiple SIP hops are involved in a call, there would
be multiple via headers involved, and the topmost via header of an
incoming SIP invite represents the last hop that forwarded the SIP
request, and the bottom-most via header would represent the originator
of the SIP request. This feature supports matching by the last hop that
forwarded the request (neighboringSIPentity), which is the topmost via
header.
From the PDF link’s worked examples, we can see the matching will use the following behaviour:
INVITE sip:123@1.2.3.4:5060 SIP/2.0
Via: SIP/2.0/TCP 10.10.10.1:5093;branch=z9hG4bK-17716-1-0
Via: SIP/2.0/TCP 10.10.14.20:5093;branch=z9hG4bK-28280-1-0
In my situation, I’d been using a voice class uri that looked something like this:
!voice class uri ITSP siphost ipv4:10.10.14.20!dial-peer voice tag voipsession protocol sipv2incoming uri via ITSP!