SIP Illustrated 5: SIP Session Routing

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.

SIP Message Routing

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.

SIP INVITE Routing – Originating part

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.

SIP INVITE Routing – Terminating IMS

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.

Route: <;orig;transport=udp;lr>

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.

SIP Via header – Response routing

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;branch=z9hG4bKkjsh77 
Via: SIP/2.0/UDP;received=;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.

The rules are described in RFC 3263 and RFC 7984. If you are serious about SIP, take your time and read it. For others I’ll try to simplify.

Transport discovery

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.;transport=tcp

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"   ""
IN NAPTR 20    50   "s"   "SIP+D2T"    ""
IN NAPTR 100   50   "s"   "SIP+D2U"    ""

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.

Port Discovery

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:2233445566@;transport=tls    => port 5061
sip:2233445566@;transport=tcp    => port 5060
sip:2233445566@;transport=udp    => port 5060

Otherwise we send an SRV request to DNS.

 ;;          Priority Weight Port   Target
       IN SRV  0        1      5060
       IN SRV  0        2      5060


IP Discovery

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. 1800 IN A 1800 IN A

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.

Record-Route and Contact headers

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:

  1. Make a copy of the received request
  2. Update the Request-URI
  3. Update the Max-Forwards header field
  4. Optionally add a Record-route header field value
  5. Optionally add additional header fields
  6. Postprocess routing information
  7. Determine the next-hop address, port, and transport
  8. Add a Via header field value
  9. Add a Content-Length header field if necessary
  10. Forward the new request
  11. Set timer C

And for a response:

  1. Find the appropriate response context
  2. Update timer C for provisional responses
  3. Remove the topmost Via
  4. Add the response to the response context
  5. Check to see if this response should be forwarded immediately
  6. 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.

  1. Aggregate authorization header field values if necessary
  2. Optionally rewrite Record-Route header field values
  3. Forward the response
  4. 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.

Related posts:


4 thoughts on “SIP Illustrated 5: SIP Session Routing

  1. As per RFC3261 only an INVITE or re-INVITE record-route list can modify future SIP Requests’ Route header lists even if Record-Route is for instance present in an in dialogue UPDATE method. However, I have the following question because I cannot find it: User Agent sending the INVITE is getting informed about the Record-Route set list in any kind of response ? Meaning, can it be both a provisional and a final response or only a final one (200 OK) ? Also, is the record-route info reaching the UE back in response or this info is stored in the P-CSCF/SBC for the corresponding session ? I am asking because in a test environment setup record-route info never reaches the UE directly and I was wondering if there is a rule for it.

    Thanks in advance,


    • Hi Chris,
      yes, provisional responses are updating future Route setting too. UE usually doesn’t get these headers, as it is sitting behind SBC (P-CSCF), which acts as B2BUA. The best place the verify the Route/record-Route headers in your IMS is to check 3GPP 24.229. (Sorry for the brief answer, I’m traveling now).



      • Thanks, the answer is totally clear, I just asked because in the picture above it was like the UE was directly receiving the “Record-Route” list.



      • yes, that was meant in a bit more general way. In IMS SBC is the SIP client.



Leave a Reply

Fill in your details below or click an icon to log in: Logo

You are commenting using your account. Log Out /  Change )

Facebook photo

You are commenting using your Facebook account. Log Out /  Change )

Connecting to %s