In the last post we have seen a basic SIP (VoLTE) session. This time we should analyze in more detail, what headers are used by network elements for their routing decisions and how they discover what port and IP to use. In practice that’s what people are not always sure about. They know the flow, order of signalling messages, but when something goes wrong, they are just guessing what could be the reason.
Let’s recap what we have learnt so far. We use loose routing. So if a SIP message contains a Route header, we will use the top most one for the routing. If there is no Route header the routing is done based on the Request-URI, which contains the address of the final recipient. Don’t forget, network elements are able to add and modify the headers. The way how we handle the messages and modify their content within the IMS is described in 3GPP standards.
We will go once again through the routing of the original SIP INVITE message. We can take a closer look on what are the SIP headers used for the routing in IMS.
Please note, the flow is simplified and the particular values are used just for an illustration. The flow and headers differ operator to operator. Still we can see, that from a great part the routing is done based on the Route header. The information where to route SIP INVITE message to was pre-shared during the Registration (Service-Route, Contact) and Third Party Registration (Contact header sent by TAS). The R-URI is analyzed firstly by O-TAS, which can apply normalization, translations, can trigger to ENUM server, etc. Triggering to ENUM can be done also by S-CSCF before it tries to deliver the SIP INVITE to a terminating IMS. Routing towards I-CSCF is done based on the content of the R-URI.
In the terminating phase, firstly the I-CSCF locates the right S-CSCF using LIR/LIA diameter messages. SIP routing is usually done internally within IMS Core, otherwise a Route header pointing to S-CSCF would be used. Then the S-CSCF sends the message to a T-TAS.
How does the TAS knows whether to apply originating or terminating services? The information is inserted in the SIP messages by S-CSCF, which knows from where the message comes. If it comes from A-SBC, we apply originating services and an ‘orig’ tag is inserted in the TAS Route header. If the message comes from I-CSCF, the S-CSCF doesn’t add the ‘orig; tag, so TAS is applying terminating services.
When the T-TAS is finished, it sends the message back using a Route header inserted previously by the S-CSCF, S-CSCF then modifies the R-URI (Contact header from Registration) and forwards to SBC using a Route header (Path from Registration).
Routing of responses is very simple, we simply follow the Via headers.
When a client creates a request, it inserts a Via into that request. The protocol name and protocol version is always SIP and 2.0. The Via header field value also contains a branch parameter, which identifies the transaction created by that request. The branch parameter is used by both the client and the server. Each proxy on the path then firstly determines (e.g. using DNS) the next hop (including the transport layer!) and inserts itself into Via headers.
SIP/2.0 183 Session Progress Via: SIP/2.0/UDP proxy.operator.com;branch=z9hG4bKkjsh77 Via: SIP/2.0/UDP 10.0.0.1:5040;received=192.0.2.1;rport=6677;branch=z9hG4bKabcd123
The value of the Via header field contains transport, IP and a port. If the port is missing a default value is used based on the transport layer. In case the proxy is behind a NAT, the receiving network element can note down the original IP address and the original port, using received and rport tags as described in the RFC 3581.
Locating SIP Servers
But that’s just a beginning. We mentioned that already and you probably noticed that as well – before we can really send a SIP message to a next hop, we have to firstly decide, what type of transport will be used (UDP/TCP/TLS/SCTP), what port and what IP.
If the target (R-URI or the top most Route header) is a numeric IP, we use UDP transport layer.
If no transport is specified, but port is specified, we also use UDP.
Otherwise we can specify the transport directly.
For sips we always use TLS.
If none of the rules specified above applies, then we have to use DNS to resolve the address.
; order pref flags service regexp replacement IN NAPTR 10 50 "s" "SIPS+D2T" "" _sips._tcp.tas.ims.operator.com. IN NAPTR 20 50 "s" "SIP+D2T" "" _sip._tcp.tas.ims.operator.com. IN NAPTR 100 50 "s" "SIP+D2U" "" _sip._udp.tas.ims.operator.com.
The third column defines, what will be the order/priority. The row with the lowest value has the highest priority. In case when more rows have the same priority, then we loadshare using preference/weights in the fourth column. The flag “s” then tells to us, that the next step is the DNS SRV request. Again, for more details, please refer to RFC.
It is even easier. If the port is specified, simply us it.
If the target is a numeric IP address, we use default ports for given transport layers.
sip:firstname.lastname@example.org;transport=tls => port 5061 sip:email@example.com;transport=tcp => port 5060 sip:firstname.lastname@example.org;transport=udp => port 5060
Otherwise we send an SRV request to DNS.
;; Priority Weight Port Target IN SRV 0 1 5060 tas1.ims.operator.com IN SRV 0 2 5060 tas2.ims.operator.com
To discover an exact IP address is just a piece of cake. Either the numeric IP is present, then we will use it.
Or, if the SRV request was already done, use the returned IP address if present. If it wasn’t present, perform A query based on that result.
If we haven’t done SRV request, then do A query using the SIP URI domain name. Use the numeric IP in the order returned by DNS.
tas1.ims.operator.com 1800 IN A 10.10.1.1 tas2.ims.operator.com 1800 IN A 10.20.1.1
Requests within a Dialog
The last time we have seen, that there can be more SIP requests sent during a session. For routing of these subsequent requests we use the same algorithm as for the original INVITE. The difference is how we set the R-URI and Route header list.
When a UAC receives a provisional response, it will take the Contact header and its value will be used as a R-URI for a subsequent request. If any of Proxies on the path want to process also subsequent messages, they insert a Record-Route header. For a new request the Record-Route values will be interested as Route header fields.
Contact and Record-Route are not limited to responses, they are used in requests too. One of the reasons is that the roles of a SIP Server/Client can change within one session (e.g. later the original UAS can send a re-INVITE or BYE message).
After all it’s no rocket science. From a proxy perspective, each network element is following a simple set of rules defined by RFC 3261.
For each target, the proxy forwards the request following these steps:
- Make a copy of the received request
- Update the Request-URI
- Update the Max-Forwards header field
- Optionally add a Record-route header field value
- Optionally add additional header fields
- Postprocess routing information
- Determine the next-hop address, port, and transport
- Add a Via header field value
- Add a Content-Length header field if necessary
- Forward the new request
- Set timer C
And for a response:
- Find the appropriate response context
- Update timer C for provisional responses
- Remove the topmost Via
- Add the response to the response context
- Check to see if this response should be forwarded immediately
- When necessary, choose the best final response from the response context
If no final response has been forwarded after every client transaction associated with the response context has been terminated, the proxy must choose and forward the “best” response from those it has seen so far. The following processing is performed on each response that is forwarded. It is likely that more than one response to each request will be forwarded: at least each provisional and one final response.
- Aggregate authorization header field values if necessary
- Optionally rewrite Record-Route header field values
- Forward the response
- Generate any necessary CANCEL requests
As you can see it is not that difficult, but still there is a lot of to learn. Perhaps the next time we can see, how to close or cancel a session.