RFC 7415

Session Initiation Protocol (SIP) Rate Control

πŸ“… published February 2015, from ietf

Hey Bestie, Meet RFC 7415 πŸ’–

This one is by E. Noel (AT&T Labs) and P. Williams (BT Innovate & Design), published in February 2015 as a Standards Track document, which means it's an official Internet Standard πŸŽ€ It's ISSN 2070-1721 if you want to look it up. The header doesn't list anything it obsoletes or updates, so it's standing on its own. It's all about Session Initiation Protocol (SIP) Rate Control πŸ¦‹

Abstract ✨

okay so SIP is everywhere in Next Generation Networks now 🌈, which means SIP networks need solid control mechanisms to keep their transaction throughput up. The whole point is stopping congestion collapse when traffic spikes πŸ’€ There's already a loss-based fix for the known problems with the SIP 503 (Service Unavailable) overload control mechanism. This doc uses that same signaling to add a rate-based control scheme that works alongside the loss-based one 🫢

Status of This Memo

This is an Internet Standards Track document. πŸŽ€

This document is a product of the Internet Engineering Task Force (IETF). It represents the consensus of the IETF community. It has received public review and has been approved for publication by the Internet Engineering Steering Group (IESG). Further information on Internet Standards is available in Section 2 of RFC 5741. ✨

Information about the current status of this document, any errata, and how to provide feedback on it may be obtained at http://www.rfc-editor.org/info/rfc7415. πŸ’…

Copyright (c) 2015 IETF Trust and the persons identified as the document authors. All rights reserved. πŸ”₯

This document is subject to BCP 78 and the IETF Trust's Legal Provisions Relating to IETF Documents (http://trustee.ietf.org/license-info) in effect on the date of publication of this document. Please review these documents carefully, as they describe your rights and restrictions with respect to this document. Code Components extracted from this document must include Simplified BSD License text as described in Section 4.e of the Trust Legal Provisions and are provided without warranty as described in the Simplified BSD License. πŸ“œ

Table of Contents 🧚

1. Introduction ....................................................2
2. Terminology .....................................................3
3. Rate-Based Algorithm Scheme .....................................3
   3.1. Overview ...................................................3
   3.2. Via Header Field Parameters for Overload Control ...........4
   3.3. Client and Server Rate-Based Control Algorithm Selection ...4
   3.4. Server Operation ...........................................5
   3.5. Client Operation ...........................................6
        3.5.1. Default Algorithm ...................................6
        3.5.2. Priority Treatment ..................................9
        3.5.3. Optional Enhancement: Avoidance of Resonance .......10
4. Example ........................................................12
5. Syntax .........................................................13
6. Security Considerations ........................................13
7. IANA Considerations ............................................13
8. References .....................................................14
   8.1. Normative References ......................................14
   8.2. Informative References ....................................14
Acknowledgments ...................................................14
Contributors ......................................................14
Authors' Addresses ................................................15

1. Introduction ✨

okay so SIP [RFC3261] is being used in big Next Generation Networks, and that means SIP-based networks need proper control mechanisms to handle traffic growth πŸ“ˆ The main thing is handling overloads gracefully, keeping transaction throughput going and preventing congestion collapse πŸ’–

There's a promising SIP-based overload control solution in [RFC7339] πŸ¦‹ It gives overload control algorithms a way to communicate, and it includes a default loss-based algorithm so a group of clients can limit how much load they send to an overloaded server. The catch is that a loss-based algorithm is sensitive to load changes, so any increase in load shows up directly in what the clients offer to the overloaded servers 😭 Even more important, a loss-based scheme can't guarantee an upper bound on the load clients send to an overloaded server, and it needs frequent updates that may have implications for stability πŸ™ˆ

So this document, following the framework in [RFC7339], proposes an alternate overload control scheme: the rate-based overload control scheme 🌸 The rate-based algorithm guarantees an upper bound on the rate of requests clients send to an overloaded server, and that rate stays constant between server updates. The trade-off is algorithmic complexity, since the overloaded server is more likely to give each client a different target (maximum rate) than it would with the loss-based approach 🧠

The proposed rate-based algorithm eases congestion in SIP networks while sticking to the overload signaling scheme in [RFC7339]. It's presented as an optional alternative to the default loss-based control scheme in [RFC7339] πŸŽ€

2. Terminology πŸ’…

The key words "MUST", "MUST NOT", "REQUIRED", "SHALL", "SHALL NOT", "SHOULD", "SHOULD NOT", "RECOMMENDED", "MAY", and "OPTIONAL" in this document are to be interpreted as described in [RFC2119]. πŸ”₯

Unless otherwise specified, all SIP entities described in this document are assumed to support this specification. 🫢

3. Rate-Based Algorithm Scheme 🌈

3.1. Overview πŸ¦‹

The server is the one protected by the overload control algorithm defined here, and the client is the one that throttles traffic towards the server. πŸ‘‘

Following the procedures defined in [RFC7339], the server and clients signal one another support for rate-based overload control. ✨

Then, periodically, the server relies on internal measurements (e.g., CPU utilization or queueing delay) to evaluate its overload state and estimate a target maximum SIP request rate in number of requests per second (as opposed to target percent loss in the case of loss-based control). πŸ“Š

When in overload, the server uses the "oc" parameter in the Via header field [RFC7339] of SIP responses in order to inform clients of its overload state and of the target maximum SIP request rate for that client. πŸ“

Upon receiving the "oc" parameter with a target maximum SIP request rate, each client throttles new SIP requests towards the overloaded server. πŸ’œ

3.2. Via Header Field Parameters for Overload Control 🧚

Four Via header parameters are defined in [RFC7339] and are summarized below: 🌸

  • oc: Used by clients in SIP requests to indicate support for overload control per [RFC7339] and by servers to indicate the load reduction amount in the loss-based algorithm and the maximum rate, in messages per second, for the rate-based algorithm described here. πŸŽ€
  • oc-algo: Used by clients in SIP requests to advertise supported overload control algorithms and by servers to notify clients of the algorithm in effect. Supported values are loss (default) and rate (optional). πŸ¦‹
  • oc-validity: Used by servers in SIP responses to indicate an interval of time (in milliseconds) that the load reduction should be in effect. A value of 0 is reserved for the server to stop overload control. A non-zero value is required in all other cases. ⏱️
  • oc-seq: A sequence number associated with the "oc" parameter. πŸ”’

Consult Section 4 for an illustration of the usage of the "oc" parameter in the Via header field. ✨

3.3. Client and Server Rate-Based Control Algorithm Selection πŸ’–

Per [RFC7339], new clients indicate supported overload control algorithms to servers by inserting "oc" and "oc-algo", with the names of the supported algorithms, in the Via header field of SIP requests destined to servers. The inclusion by the client of the token "rate" indicates that the client supports a rate-based algorithm. Conversely, servers notify clients of the selected overload control algorithm through the "oc-algo" parameter in the Via header field of SIP responses to clients. The inclusion by the server of the token "rate" in the "oc-algo" parameter indicates that the rate-based algorithm has been selected by the server. 🫢

Support of rate-based control MUST be indicated by clients including the token "rate" in the "oc-algo" list. Selection of rate-based control MUST be indicated by servers by setting "oc-algo" to the token "rate". πŸ”₯

3.4. Server Operation πŸ‘‘

The actual algorithm used by the server to determine its overload state and estimate a target maximum SIP request rate is beyond the scope of this document. πŸ™ˆ

However, the server MUST periodically evaluate its overload state and estimate a target SIP request rate beyond which it would become overloaded. The server must determine how it will allocate the target SIP request rate among its client. The server may set the same rate for every client or may set different rates for different clients. 🌈

The maximum rate determined by the server for a client applies to the entire stream of SIP requests, even though throttling may only affect a particular subset of the requests, since as per [RFC7339] and REQ 13 of [RFC5390], request prioritization is a client's responsibility. πŸ¦‹

When setting the maximum rate for a particular client, the server may need to take into account the workload (e.g., CPU load per request) of the distribution of message types from that client. Furthermore, because the client may prioritize the specific types of messages it sends while under overload restriction, this distribution of message types may be different from the message distribution for that client under non-overload conditions (e.g., it could have either higher or lower CPU load). 🧠

Note that the "oc" parameter for the rate-based algorithm is an upper bound (in messages per second) on the traffic sent by the client to the server. The client may send traffic at a rate significantly lower than the upper bound for a variety of reasons. πŸ“

In other words, when multiple clients are being controlled by an overloaded server, at any given time, some clients may receive requests at a rate below their target (maximum) SIP request rate while others above that target rate. But the resulting request rate presented to the overloaded server will converge towards the target SIP request rate. πŸ’œ

Upon detection of overload and the determination to invoke overload controls, the server MUST follow the specifications in [RFC7339] to notify its clients of the allocated target SIP request rate and to notify them that rate-based control is in effect. πŸŽ€

The server MUST use the "oc" parameter defined in [RFC7339] to send a target SIP request rate to each of its clients. 🌸

When a client supports the default loss-based algorithm and not the rate-based algorithm, the client would be handled in the same way as in Section 5.10.2 of [RFC7339]. 🧚

3.5. Client Operation πŸ¦‹

3.5.1. Default Algorithm πŸ¦‹

Okay bestie, so when the client is deciding whether to actually send a message, it can use basically any algorithm that keeps the rate at or under the "oc" parameter (in messages per second) πŸ’…. To make things easy we define T = 1 / ["oc" parameter] as the target inter-SIP request interval ✨. The algorithm can be strictly deterministic or probabilistic 🌸. It may, or may not, have a tolerance factor for short bursts, as long as the long-term rate stays below 1/T 🫢.

The algorithm may have provisions for prioritizing traffic in accordance with REQ 13 of [RFC5390] πŸ‘‘.

If the algorithm needs other parameters (on top of T, which is 1 / ["oc" parameter]), the client can set them itself, or they can be negotiated between client and server separately from the SIP-based overload control solution 🧚.

Either way, that coordination is out of scope for this doc πŸ™ˆ. The default algorithms here (one with priority provisions and one without) are just examples, not the only options πŸ’–.

To throttle new SIP requests at the rate the server sends in its "oc" parameter, the client MAY use the proposed default algorithm for rate-based control, or any other equivalent algorithm that forwards messages in line with the upper bound of 1/T messages per second πŸ”₯.

The default leaky bucket algorithm here is based on [ITU-T-I.371], Appendix A.2 ✨. It lets clients deliver SIP requests at the rate in the "oc" parameter, with a tolerance parameter TAU (ideally configurable) πŸ¦‹.

Conceptually, picture a finite-capacity bucket πŸͺ£. Its real-valued contents drain out at a continuous rate of 1 unit per time unit, and every forwarded SIP request adds the increment T. And T is just the inverse of the "oc" rate, T = 1 / ["oc" parameter] πŸ’….

Quick heads-up 🚨: when the "oc" parameter is 0 and "oc-validity" is non-zero, the client should reject 100% of SIP requests headed to the overloaded server. But if "oc-validity" is 0, the client should immediately stop throttling πŸ’€.

When a new SIP request arrives, if the bucket content is less than or equal to the limit TAU, the request gets forwarded to the server. Otherwise it gets rejected 😭.

The capacity of the bucket (the upper bound of the counter) is (T + TAU) πŸ“.

The tolerance parameter TAU decides how close the long-term admitted rate gets to an ideal control. That ideal would admit every SIP request when arrival rates are below 1/T, and then admit exactly 1/T worth of requests when arrival rates go above it 🌈. Near mean arrival rates of 1/T, TAU sets how much the inter-arrival time is allowed to wobble away from T. The bigger TAU, the more wobble it tolerates from the inter-departure interval T ⭐.

That wobble affects how bursty the admitted rate is, meaning how many requests in a row get forwarded to the server. The burst size is proportional to TAU divided by the difference between 1/T and the arrival rate πŸ™ˆ.

If clients know something about the server (say, from operator pre-provisioning), it can be a great move to pick a TAU based on how many clients will be sending requests to that server πŸŽ€.

Servers with a huge number of clients, each sending a fairly small rate, usually benefit from a smaller TAU. That limits queuing (and so response times) when all the clients suddenly surge at once πŸ”₯. On the flip side, a server with fewer clients, each sending a proportionally bigger rate, will benefit from a larger TAU πŸ‘‘.

Once control has been activated, when the k-th new SIP request arrives at time ta(k), the bucket content is provisionally updated to:

X' = X - (ta(k) - LCT)

where X is the leaky bucket counter after the last forwarded SIP request arrived, and LCT is the time that last SIP request was forwarded πŸ’–.

If X' is less than or equal to the limit TAU, the new SIP request is forwarded, the counter X gets set to X' (or to 0 if X' is negative) plus the increment T, and LCT gets set to the current time ta(k) ✨. If X' is greater than TAU, the new SIP request is rejected, and X and LCT stay exactly as they were 🫢.

When the first response from the server arrives showing control activation (oc-validity>0), LCT is set to the time of activation. The leaky bucket counter gets initialized to the parameter TAU0 (ideally configurable), which is 0 or larger but less than or equal to TAU 🌸.

TAU can be any positive real number, and it isn't necessarily bounded by T πŸ¦‹.

TAU=4*T is a reasonable compromise between burst size and throttled rate adaptation at low offered rates πŸ’….

Also, picking a value for TAU and any communication or coordination between servers is beyond the scope of this document πŸ™ˆ.

Here's a reference algorithm. First, the no-priority case 🧚:

// T: inter-transmission interval, set to 1 / ["oc" parameter]
// TAU: tolerance parameter
// ta: arrival time of the most recent arrival received by the
//     client
// LCT: arrival time of last SIP request that was sent to the server
//      (initialized to the first arrival time)
// X: current value of the leaky bucket counter (initialized to
//    TAU0)

// After most recent arrival, calculate auxiliary variable Xp
Xp = X - (ta - LCT);

if (Xp <= TAU) {
  // Transmit SIP request
  // Update X and LCT
  X = max (0, Xp) + T;
  LCT = ta;
} else {
  // Reject SIP request
  // Do not update X and LCT
}

3.5.2. Priority Treatment πŸ‘‘

Just like the loss-based algorithm in [RFC7339], a client running the rate-based algorithm also sorts messages into two or more categories of requests πŸ’…. For example, there are requests that are candidates for reduction, and requests that aren't subject to reduction (except under extenuating circumstances, when there aren't any messages in the first category that can be reduced) 🫢.

So the proposed leaky bucket gets tweaked to support priority, using two thresholds for SIP requests that are candidates for reduction ✨. With two priorities, the leaky bucket needs two thresholds, TAU1 and TAU2 (where TAU1 < TAU2) 🌈:

  • All new requests would be admitted when the leaky bucket counter is at or below TAU1.
  • Only higher-priority requests would be admitted when the leaky bucket counter is between TAU1 and TAU2.
  • All requests would be rejected when the bucket counter is at or above TAU2.

This can be generalized to n priorities using n thresholds for n>2, in the obvious way 🧚.

With a priority scheme that relies on two tolerance parameters (TAU2 influences the priority traffic, and TAU1 influences the non-priority traffic), always set TAU1 < TAU2 (TAU gets replaced by TAU1 and TAU2) πŸŽ€. Setting both tolerance parameters to the same value is the same as having no priority at all πŸ™ˆ. TAU1 affects the admitted rate the same way TAU does when no priority is set 🌸. The bigger the gap between TAU1 and TAU2, the closer the control gets to strict priority queueing πŸ”₯.

TAU1 and TAU2 can be any positive real number, and they aren't necessarily bounded by T πŸ¦‹.

Reasonable values for TAU0, TAU1, and TAU2 are:

  • TAU0 = 0,
  • TAU1 = 1/2 * TAU2, and
  • TAU2 = 10 * T.

Specifying values for TAU1 and TAU2, plus any communication or coordination between servers, is beyond the scope of this document πŸ’–.

Here's the reference algorithm for the priority case πŸ’…:

// T: inter-transmission interval, set to 1 / ["oc" parameter]
// TAU1: tolerance parameter of no-priority SIP requests
// TAU2: tolerance parameter of priority SIP requests
// ta: arrival time of the most recent arrival received by the
//     client
// LCT: arrival time of last SIP request that was sent to the server
//      (initialized to the first arrival time)
// X: current value of the leaky bucket counter (initialized to
//    TAU0)

// After most recent arrival, calculate auxiliary variable Xp
Xp = X - (ta - LCT);

if (AnyRequestReceived && Xp <= TAU1) || (PriorityRequestReceived &&
Xp <= TAU2 && Xp > TAU1) {
  // Transmit SIP request
  // Update X and LCT
  X = max (0, Xp) + T;
  LCT = ta;
} else {
  // Reject SIP request
  // Do not update X and LCT
}

3.5.3. Optional Enhancement: Avoidance of Resonance ✨

As the number of client traffic sources goes up, or the server's throughput goes down, the maximum rate each client admits has to drop. That means the value of T gets bigger 🫢. Under some circumstances (say, if traffic arrives really quickly and at the same time from lots of sources), the bucket occupancies can get synchronized 😭. Then the admissions from each source land close together in time, batched or very "peaky" at the server. That causes control instability, plus really poor delays and even lost messages πŸ’€. The term for this is 'resonance' [Erramilli] 🌈.

If the network topology is such that resonance can happen, a simple way to avoid it is to randomize the bucket occupancy at two appropriate points: when control is activated, and whenever the bucket empties πŸ¦‹. Here's how 🧚:

After updating the leaky bucket value to X', generate a value u like this:

  if X' > 0, then u = 0

  else if X' <= 0, then let u be set to a random value uniformly
                   distributed between -1/2 and +1/2

Then, only if the arrival is admitted, increase the bucket by an amount T + uT. That's just T if the bucket hadn't emptied, or somewhere between T/2 and 3T/2 if it had πŸ“.

This randomization should also happen when control is activated. So instead of just setting the leaky bucket counter to TAU0, set it to TAU0 + uT, where u is uniformly distributed as above πŸ’…. Since activation was triggered by a response to a request the client sent, the second term can be read as the bucket increment that followed that admission πŸŽ€.

This method has the following characteristics πŸ”₯:

  • If TAU0 is chosen to be equal to TAU, and all sources activate control at the same time because of an extremely high request rate, then the time until the first request admitted by each client is uniformly distributed over [0,T].
  • The maximum occupancy is TAU + (3/2)T, rather than TAU + T without randomization.
  • For the special case of 'classic gapping' where TAU=0, the minimum time between admissions is uniformly distributed over [T/2, 3T/2], and the mean time between admissions is the same, i.e., T+1/R where R is the request arrival rate πŸ‘‘.
  • Since high-load randomization rarely happens, there's no loss of precision in the admitted rate, even though the randomized 'phasing' of the buckets sticks around 🌸.

4. Example ✨

okay so this section is literally a glow-up of the example in Section 6 of [RFC7339] πŸ¦‹ where client P1 is sending requests to a downstream server P2 πŸ’…

        INVITE sips:user@example.com SIP/2.0

        Via: SIP/2.0/TLS p1.example.net;

         branch=z9hG4bK2d4790.1;received=192.0.2.111;

         oc;oc-algo="loss,rate"

        ...

        SIP/2.0 100 Trying

        Via: SIP/2.0/TLS p1.example.net;

         branch=z9hG4bK2d4790.1;received=192.0.2.111;

         oc=0;oc-algo="rate";oc-validity=0;

         oc-seq=1282321615.781

        ...

so the first message πŸ“¨ is P1 sending to P2. it's a SIP request, and bc P1 supports overload control, it drops the "oc" parameter into the topmost Via header field it made πŸŽ€ P1 is serving two overload control algorithms: loss and rate 🌸

the second message is a SIP response πŸ’– it shows that topmost Via header field after P2 has amended it (per this spec) and sent it back to P1 🫢 bc P2 also supports overload control, it picks the rate-based scheme and sends that back to P1 in the "oc-algo" parameter πŸ”₯ it uses oc-validity=0 to say "no overload control rn" πŸ™ˆ in this example "oc=0", but honestly "oc" could be any value bc "oc" gets ignored when "oc-validity=0" πŸ’…

later on, P2 starts to get overloaded 😭 and it sends this SIP message saying P1 should send SIP requests at a rate no greater than or equal to 150 SIP requests per second, for a duration of 1,000 milliseconds ⏱️

        SIP/2.0 180 Ringing

        Via: SIP/2.0/TLS p1.example.net;

         branch=z9hG4bK2d4790.1;received=192.0.2.111;

         oc=150;oc-algo="rate";oc-validity=1000;

         oc-seq=1282321615.782

         ...

5. Syntax 🧚

okay so this spec extends the existing definition of the Via header field parameters from [RFC7339] like this πŸ¦‹

algo-list =/ "rate"

6. Security Considerations πŸ”πŸ’€

okay this one is SERIOUS bestie 😭 aside from the resonance concerns we talked about in Section 3.5.3, this mechanism doesn't add any security concerns beyond the general overload control security issues covered in [RFC7339] 🫢 ways to reduce the risk of resonance are in Section 3.5.3 πŸ’œ


7. IANA Considerations πŸ“

IANA has registered the "oc-algo" parameter of the Via header field in the "Header Field Parameters and Parameter Values" subregistry of the "Session Initiation Protocol (SIP) Parameters" registry ✨ the entry looks like this:

Header     Parameter     Predefined     References
Field      Name          Values
___________________________________________________________

Via        oc-algo       Yes            [RFC7339] [RFC7415]

8. References πŸ“š

8.1. Normative References

[RFC2119]     Bradner, S., "Key words for use in RFCs to Indicate
              Requirement Levels", BCP 14, RFC 2119, March 1997,
              <http://www.rfc-editor.org/info/rfc2119>.

[RFC3261]     Rosenberg, J., Schulzrinne, H., Camarillo, G.,
              Johnston, A., Peterson, J., Sparks, R., Handley, M.,
              and E. Schooler, "SIP: Session Initiation Protocol",
              RFC 3261, June 2002,
              <http://www.rfc-editor.org/info/rfc3261>.

[RFC5390]     Rosenberg, J., "Requirements for Management of Overload
              in the Session Initiation Protocol", RFC 5390, December
              2008, <http://www.rfc-editor.org/info/rfc5390>.

[RFC7339]     Gurbani, V., Ed., Hilt, V., and H. Schulzrinne,
              "Session Initiation Protocol (SIP) Overload Control",
              RFC 7339, September 2014,
              <http://www.rfc-editor.org/info/rfc7339>.

8.2. Informative References

[ITU-T-I.371] ITU-T, "Traffic control and congestion control in
              B-ISDN", ITU-T Recommendation I.371, March 2004.

[Erramilli]   Erramilli, A., and L. Forys, "Traffic Synchronization
              Effects In Teletraffic Systems", ITC-13, 1991.

Acknowledgments 🫢

Many thanks to the following individuals for comments and feedback on this document: Richard Barnes, Keith Drage, Vijay Gurbany, Volker Hilt, Christer Holmberg, Winston Hong, Peter Yee, and James Yu. πŸ’–

Contributors 🌈

Significant contributions to this document were made by Janet Gunn. ✨

Authors' Addresses πŸŽ€

Eric Noel
AT&T Labs
200 S Laurel Avenue
Middletown, NJ 07747
United States

EMail: eric.noel@att.com


Philip M. Williams
BT Innovate & Design
Ipswich, IP5 3RE
United Kingdom

EMail: phil.m.williams@bt.com
πŸ“¦ where this page comes from