One document matched: draft-roach-dime-overload-ctrl-01.xml
<?xml version="1.0" encoding="US-ASCII"?>
<!DOCTYPE rfc SYSTEM "rfc2629.dtd"[
<!ENTITY rfc2119 PUBLIC '' 'http://xml.resource.org/public/rfc/bibxml/reference.RFC.2119.xml'>
<!ENTITY rfc3588 PUBLIC '' 'http://xml.resource.org/public/rfc/bibxml/reference.RFC.3588.xml'>
<!ENTITY rfc6357 PUBLIC '' 'http://xml.resource.org/public/rfc/bibxml/reference.RFC.6357.xml'>
<!ENTITY rfc3588bis PUBLIC "" "http://xml.resource.org/public/rfc/bibxml3/reference.I-D.ietf-dime-rfc3588bis.xml">
<!ENTITY soc PUBLIC "" "http://xml.resource.org/public/rfc/bibxml3/reference.I-D.ietf-soc-overload-control.xml">
<!ENTITY reqs PUBLIC "" "http://xml.resource.org/public/rfc/bibxml3/reference.I-D.ietf-dime-overload-reqs.xml">
<!ENTITY nbsp " ">
<!ENTITY li-code "1600">
<!ENTITY ss-code "1601">
<!ENTITY oa-code "1602">
<!ENTITY ois-code "1603">
<!ENTITY om-code "1604">
<!ENTITY pov-code "1605">
<!ENTITY sg-code "1606">
<!ENTITY l-code "1607">
<!ENTITY disconnect-cause-negotiation-failure "128 [actual value TBD]">
<!ENTITY peer-in-overload "4128 [actual value TBD]">
<!ENTITY rfcnum "xxxx">
]>
<?xml-stylesheet type='text/xsl' href='rfc2629.xslt' ?>
<?rfc toc="yes"?>
<?rfc compact="yes" ?>
<?rfc sortrefs="yes" ?>
<?rfc symrefs="yes" ?>
<rfc category="std"
ipr="trust200902" >
<front>
<title abbrev='Diameter Overload Control'>
A Mechanism for Diameter Overload Control
</title>
<author fullname="Adam Roach" initials="A. B." surname="Roach">
<organization>Tekelec</organization>
<address>
<postal>
<street>17210 Campbell Rd.</street>
<street>Suite 250</street>
<city>Dallas</city>
<region>TX</region>
<code>75252</code>
<country>US</country>
</postal>
<email>adam@nostrum.com</email>
</address>
</author>
<date/> <!-- Date is auto-generated -->
<area>Operations</area>
<workgroup>DIME</workgroup>
<abstract>
<t>
When a Diameter server or agent becomes overloaded, it needs
to be able to gracefully reduce its load, typically by
informing clients to reduce or stop sending traffic for
some period of time. Otherwise, it must continue to expend
resources parsing and responding to Diameter messages.
</t>
<t>
This document proposes a concrete, application-independent
mechanism to address the challenge of communicating load
and overload state among Diameter peers, and specifies an
algorithm for load abatement to address such overload
conditions as they occur. The load abatement algorithm is
extensible, allowing for future documents to define additional
load abatement approaches.
</t>
</abstract>
</front>
<middle>
<section title="Introduction">
<t>
When a Diameter
<xref target="I-D.ietf-dime-rfc3588bis"/>
server or agent becomes overloaded, it needs
to be able to gracefully reduce its load, typically by
informing clients to reduce or stop sending traffic for
some period of time. Otherwise, it must continue to expend
resources parsing and responding to Diameter messages.
</t>
<t>
This document defines a mechanism for communicating the
load and overload information among Diameter nodes.
It also
defines a base algorithm for shedding traffic under
overload circumstances. The design of the mechanism
described in this document allows for the definition of
alternate load abatement algorithms as well.
</t>
<t>
The mechanism proposed in this document is heavily influenced
by the work performed in the IETF Session Initiation Protocol
(SIP) Overload Control Working Group, and draws on the conclusions
reached by that working group after extensive network modeling.
</t>
<t>
The solution described in this document is intended to
satisfy the requirements described in
<xref target="I-D.ietf-dime-overload-reqs"/>, with the
exception of REQ 35. As discussed in
that document, the intention of a Diameter overload mechanism
is to handle overload of the actual message processing
portions of Diameter servers. This is in contrast to
congestion, which is the inability of the underlying switching
and routing fabric of the network to carry the volume of
traffic at the volume that IP hosts wish to send it. Handling
of congestion is relegated to the underlying transport
protocol (TCP or SCTP), and will not be discussed.
</t>
<t>
Philosophically, the approach in designing this mechanism
is based on the prospect that building a base-level, fully
compliant implementation should be a very simple and straightforward
exercise. However, the protocol includes many additional
features that may be implemented to allow Diameter nodes to apply
increasingly sophisticated behaviors.
This approach gives implementors the freedom to implement as
sophisticated a scheme as they desire, while freeing them
from the burden of unnecessary complexity.
By doing so, the mechanism allows for the rapid
development and deployment of the mechanism followed by a period of
steady and gradual improvements as implementations become more
capable.
</t>
<section title="Mechanism Properties">
<t>
The core Diameter overload mechanism described in this document
is fundamentally hop-by-hop. The rationale for using a hop-by-hop
approach is the same as is described in section 5.1 of
<xref target="RFC6357"/>.
However, due to the fact that Diameter networks frequently
have traffic that is easily grouped into a few well-defined
categories, we have added some concepts that allow Diameter
agents to push back on subsets of traffic that correspond
to certain well-defined and client-visible constructs
(such as Destination-Host, Destination-Realm, and
Application-ID). These constructs are termed "Scopes"
in this document. A more
complete discussion of Scopes is found in <xref target="scopes"/>.
</t>
<t>
The key information transmitted between Diameter peers
is the current server load (to allow for better balancing
of traffic, so as to preempt overload in the first place)
as well as an indication of overload state and severity
(overload information). The actual load and overload
information is conveyed as a new compound AVP, added to
any Diameter messages that allow for
extensibility. As discussed in section 3.2 of
<xref target="I-D.ietf-dime-rfc3588bis"/>,
all CCFs are encouraged to include AVP-level extensibility
by inclusion of a "* [ AVP ]" construct in their syntax
definition. The document author has conducted an extensive
(although admittedly not exhaustive) audit of existing
applications, and found none lacking this property. The inclusion
of load and overload information in existing messages has
the property that the frequency with which information
can be exchanged increases as load on the system goes up.
</t>
<t>
For the purpose of grouping the several different parts
of load information together, this mechanism makes use of
a Grouped AVP, called "Load-Info". The Load-Info AVP
may appear one or more times in any extensible command,
with the restriction that each instance of the Load-Info
AVP must contain different Scopes.
</t>
<t>
Load and overload information can
be conveyed during times of inter-node quiescence through
the use of DWR/DWA exchanges. These exchanges can also be
used to proactively change the overload or load level of
a server when no other transaction is ready to be sent.
Finally, in the unlikely event that an application is defined
that precludes the inclusion of new AVPs in its commands,
DWR/DWA exchanges can be sent at any rate acceptable to the
server in order to convey load and overload information.
</t>
<t><list style="hanging"><t>
In <xref target="RFC3588"/>, the DWR and DWA message
syntax did not allow for the addition of new AVPs in the
DWR and DWA messages. This oversight was fixed in
<xref target="I-D.ietf-dime-rfc3588bis"/>. To allow for
transmission of load information on quiescent links,
implementations of the mechanism described in this document
are expected to correctly handle extension AVPs in DWR
and DWA messages, even if such implementations have not
otherwise been upgraded to support
<xref target="I-D.ietf-dime-rfc3588bis"/>.
</t></list></t>
</section>
<section title="Overview of Operation">
<t>
During the capabilities exchange phase of connection
establishment, peers determine whether the connection will
make use of the overload control mechanism; and, if so,
which optional behaviors are to be employed.
</t>
<t>
The information sent between adjacent nodes includes two
key metrics: Load (which, roughly speaking, provides a
linear metric of how busy the node is), and Overload-Metric
(which is input to the negotiated load abatement algorithm).
</t>
<t>
Message originators (whether originating a request or an answer)
include one or more Load-Info AVPs in messages when they form
them. These Load-Info AVPs reflect the originators' own
load and overload state.
</t>
<t>
Because information is being used on a hop-by-hop
basis, it is exchanged only between adjacent nodes.
This means that any Diameter agent that forwards a
message (request or answer) is required to remove
any information received from the previous hop, and
act upon it as necessary. Agents
also add their own load and overload information
(which may, at implementors' preference, take previous-hop
information into account) into a new Load-Info AVP
before sending the request or answer along.
</t>
<t><list style='hanging'><t>
Because the mechanism requires affirmative indication
of support in the capabilities exchange phase of connection
establishment, load and overload information will never
be sent to intermediaries that do not support the overload
mechanism. Therefore, no special provisions need to be
made for removal of information at such intermediaries --
it will simply not be sent to them.
</t></list></t>
<t>
Message recipients are responsible for reading and
acting upon load and overload information that
they receive in such messages.
</t>
</section>
<section title="Documentation Conventions">
<t>
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 <xref target="RFC2119" />.
</t>
</section>
</section>
<section title="Overload Scopes" anchor="scopes">
<t>
In normal operation, a Diameter node may be overloaded for
some but not all possible requests. For example, an agent
that supports two realms (realm A and realm B in this example)
may route traffic to one set of servers for realm A, and another
set of servers for realm B. If the realm A servers are overloaded
but realm B servers are not, then the agent is effectively
overloaded for realm A but not for realm B.
</t>
<t>
Despite the fact that Diameter agents can report on scopes
that semantically map to constructs elsewhere in the
network, it is important to keep in mind that overload
state is still reported on a hop-by-hop basis. In other
words, the overload state reported for realm A in the
example above represents the aggregate of the agent's
overload state along with the overload state being
reported by applicable upstream servers (those serving
realm A).
</t>
<t>
Even without the use of Diameter agents, similar situations may
arise in servers that need to make use of external resources for
certain applications but not for others. For example, if a single
server is handling two applications, one of which uses an external
database while the other does not, it may become overloaded for
the application that uses the external database when the database
response latency increases.
</t>
<t>
The indication of scopes for overload information
(using the Overload-Info-Scope AVP; see <xref target="ois"/>)
allows a node to indicate a subset of requests to which overload
information is to be applied. This document defines seven
scopes; only "Connection" scope is mandatory to implement. The use of
the optional scopes, along with the use of any additional
scopes defined in other documents, is negotiated at connection establishment
time; see <xref target="conn-setup"/>.
</t>
<section title="Scope Descriptions" anchor="scope-list">
<t>
<list style="hanging" hangIndent="6">
<t hangText="Destination-Realm:">
This scope, which nodes SHOULD implement, pertains to all
transactions that have a Destination-Realm AVP matching
the indicated value.
<vspace blankLines="1"/>
</t>
<t hangText="Application-ID:">
This scope, which nodes SHOULD implement, pertains to all
transactions that contain an Application-ID field matching
the indicated value.
<vspace blankLines="1"/>
</t>
<t hangText="Destination-Host:">
This scope, which nodes SHOULD implement, pertains to all
transactions that have a Destination-Host AVP matching
the indicated value.
<vspace blankLines="1"/>
</t>
<t hangText="Host:">
This scope, which nodes SHOULD implement, pertains to all
transactions sent directly to the host matching the indicated
value.
<vspace blankLines="1"/>
</t>
<t hangText="Connection:">
This scope, which nodes MUST implement, pertains to
all transactions sent on the same TCP connection or
SCTP association. This scope has no details indicating
which connection or association it applies to; instead,
the recipient of an indication of "Connection" scope is
to use the connection or association on which the
message was received as the indicated connection or
association. In other words, any use of Connection
scope applies to "this connection."
<vspace blankLines="1"/>
</t>
<t hangText="Session-Group:">
This scope, which nodes MAY implement, pertains
to all transactions in a session that has been assigned
to the indicated group. For more information on assigning
sessions to groups, see <xref target="session-setup"/>.
<vspace blankLines="1"/>
</t>
<t hangText="Session:">
This scope, which nodes MAY implement, pertains
to all transactions in the indicated session.
<vspace blankLines="1"/>
</t>
</list>
</t>
<t>
Some applications do not have long-running sessions
containing multiple transactions. For such applications,
the use of "Session-Group" and "Session" scopes do not
make sense. Such applications will instead make use
of the most applicable of the remaining five scopes
(plus any negotiated extension scopes) to achieve
overload control.
</t>
<t>OPEN ISSUE: Is there value to including a stream-level
scope for SCTP? We haven't been able to come up with a use
case for doing so yet, but it wouldn't necessarily be
unreasonable.</t>
</section>
<section title="Combining Scopes" anchor="combining">
<t>
To allow for the expression of more complicated scopes than
the primitives defined above, multiple Overload-Info-Scope
AVPs may be included in a single Load-Info AVP. Semantically,
these scopes are included in the following way:
<vspace blankLines="1"/>
<list style="symbols">
<t>Attributes of the different kinds are logically and-ed
together (e.g., if both "Destination-Realm" and "Application-ID"
are present, the information applies to requests sent
that match both the realm and the application).
<vspace blankLines="1"/></t>
<t>Attributes of the same kind are logically or-ed together
(e.g., if two "Destination-Realm"s are present, the
information applies to requests sent to either realm).
<vspace blankLines="1"/></t>
<t>If a transaction falls within more than one scope, the
"most overloaded" scope is used for traffic shaping.
<vspace blankLines="1"/></t>
</list>
</t>
<t>
To prevent the complexity of implementing arbitrary scope
combination rules, only the following combinations of scopes
are allowed (OPEN ISSUE -- we need to figure out what makes
most sense for expressing these combinations. Formal grammar?
Prose? A table of some kind? For now, they're expressed as
a pseudo-ABNF):<vspace blankLines="1"/>
<list style="symbols">
<t>1*(Destination-Realm) 0*1(Application-ID)</t>
<t>1*(Application-ID) 0*1(Destination-Realm)</t>
<t>1*(Application-ID) 0*1(Destination-Host)</t>
<t>1*(Application-ID) 0*1(Host)</t>
<t>1*(Application-ID) 0*1(Connection)</t>
<t>1*(Destination-Host)</t>
<t>1*1(Host)</t>
<t>1*1(Connection)</t>
<t>1*(Session-Group) 0*1(Host | Connection)</t>
<t>1*(Session) 0*1(Host | Connection)</t>
</list>
<list style="hanging"><t><vspace blankLines="1"/>
OPEN ISSUE: Is this the right set of scope combinations? Is there a
need for more? Are any of these unnecessary? Ideally, this should
be the smallest set of combinations that lets nodes report what
they realistically need to report.
</t></list>
</t>
<t>
Any document that creates additional scopes MUST define how they may be
combined with all scopes registered with IANA at the time of their
publication.
</t>
</section>
</section>
<section title="Diameter Node Behavior">
<t>
The following sections outline the behavior expected of
Diameter clients, servers, and agents that implement
the overload control mechanism.
</t>
<t> OPEN ISSUE: SIP Overload Control includes a sequence parameter
to ensure that out-of-order messages do not cause the receiver
to act on state that is no longer accurate. Is message reordering
a concern in Diameter? That is, do we need
to include sequence numbers in the messages to ensure that the
receiver does not act on stale state information? Because Diameter
uses only reliable, in-order transports, it seems that this isn't
likely to be an issue. Is there room for a race when multiple
connections are in use?</t>
<section title="Connection Establishment Procedures" anchor="conn-setup">
<t>
Negotiation for support of this mechanism is performed
during Diameter capabilities exchange. Optional protocol
features and extensions to this mechanism are also negotiated
at this time. No provision is provided for renegotiation of
mechanism use or extensions during the course of a connection.
If peers wish to make changes to the mechanism, they must
create a new connection to do so.
</t>
<t>
The connection initiator includes a
Load-Info AVP in the CER (Capabilities-Exchange-Request) message
that it sends after establishing the connection. This Load-Info
AVP MUST contain a Supported-Scopes AVP and an Overload-Algorithm
AVP. The Supported-Scopes AVP includes
a comprehensive list
of scopes supported that the connection initiator can receive
and understand.
See <xref target="ss"/> for information on the format of the
Supported-Scopes AVP.
</t>
<t>
The Load-Info AVP in a CER message also
MAY contain one or more Overload-Algorithm AVPs. If present,
these AVPs indicate every Overload-Algorithm the connection
initiator is willing to support for the connection that is
being established. If the connection initiator supports only
the "Loss" algorithm, it MAY indicate this fact by omitting
the Overload-Algorithm altogether.
</t>
<t>
The Load-Info AVP in a CER message MAY also contain additional
AVPs, as defined in other documents, for the purpose of negotiation
extensions to the Overload mechanism.
</t>
<t>
The Diameter node that receives a CER message first examines
it for the presence of a Load-Info AVP. If no such AVP is
present, the node concludes that the overload control mechanism
is not supported for this connection, and no further
overload-related negotiation is performed. If the received
CER contains a Load-Info AVP, the recipient of that message
stores that information
locally in the context of the connection being established.
It then examines the Overload-Algorithm AVPs, if present,
and selects a single algorithm from that list. If no
Overload-Algorithm is indicated, then the base "Loss"
algorithm is used for the connection. In either case,
the recipient of the CER stores this algorithm in the context
of the connection.
</t>
<t>
When a node conformant to this specification sends a
Capabilities-Exchange-Answer (CEA) message
in answer to a CER that contained a Load-Info AVP,
the CEA MUST contain a Load-Info AVP. This Load-Info AVP
MUST contain a Supported-Scopes AVP that includes
a comprehensive list
of scopes supported that the connection initiator can receive
and understand.
The CEA also contains
zero or one Overload-Algorithm AVPs. If present, this
Overload-Algorithm MUST match one of the Overload-Algorithm
AVPs sent in the CER, and it indicates the overload
control algorithm that will be used for the connection.
If the CEA contains no Overload-Algorithm, the connection
will use the "Loss" algorithm.
</t>
<t>
When a node receives a CEA message, it examines it
for the presence of a Load-Info AVP. If no such AVP
is present, the node concludes that the overload
mechanism is not supported for this connection.
If the received CEA contains a Load-Info AVP, then
the recipient extracts the Supported-Scopes information,
and stores them locally in the context of the connection
being established. It then checks for the presence of
an Overload-Algorithm AVP. If present, this AVP indicates
the overload control algorithm that will be used for the
connection. If absent, then the connection will use
the "Loss" algorithm.
</t>
<t>
If a node receives a CEA message that indicates support
for a scope that it did not indicate in its CER or which
selects an overload control algorithm that it did not
advertise in its CER, then it MUST terminate the connection
by sending a DPR with a Disconnect-Cause of
NEGOTIATION_FAILURE, (&disconnect-cause-negotiation-failure;)
indicating that the CEA sender has failed to properly
follow the negotiation process described above.
</t>
<t>
Note that the Supported-Scopes announcement during capabilities
exchange is a set of mutual advertisements of which scopes
the two nodes are willing to receive information about. It
is not a negotiation. It is perfectly acceptable for a node
to send information for scopes it did not include in the
Supported-Scopes AVP it sent, as long as the recipient
indicated support for receiving such a scope. For example,
a Diameter agent, during connection establishment with a client,
may indicate support for receiving only "Connection" and
"Host" scope; however, if the client indicated support for
"Application" scope, then the agent is free to send Load-Info
AVPs that make use of "Application" scope to the client.
</t>
</section>
<section title="Diameter Client and Diameter Server Behavior" anchor="client-server">
<t>
The following sections describe the behavior that Diameter
clients and Diameter servers implement for the overload
control mechanism. Behavior at Diameter Agents is described
in <xref target="agent"/>.
</t>
<t>
To implement overload control, Diameter nodes need
to keep track of three important metrics for each of
the scopes for which information has been received:
the overload metric for the scope, the period of
validity for that overload metric, and the load within
that scope. Conceptually, these are data records indexed
by the scope to which they apply. In the following
sections, we refer to these data records with the
term "scope entry." Further, when it is necessary to
distinguish between those scope entries referring to
the load information received from other
nodes and those referring to the load information
sent to other nodes, we use the term "remote scope entry"
to refer to the information received from other nodes,
and "local scope entry" to refer to that information that
is being maintained to send to other nodes.
</t>
<t>
In order to allow recipients of overload information
to perform certain performance optimizations, we also define
a new command flag, called 'O'verload. This bit, when
set, indicates that the message contains at least one
Load-Info AVP with a non-zero Overload-Metric -- in
other words, the sending node is overloaded for at least
one context. See <xref target='overload-bit'/> for the
definition of the 'O'verload bit.
</t>
<t><list style='hanging'><t>
OPEN ISSUE: Is there anything we can do to make this
'O'verload bit even more useful? Perhaps setting it
only when the overload value has changed, or changed
by a certain amount?
</t></list></t>
<section title="Sending a Request" anchor="req-send">
<t>
This section applies only to those requests sent
to peers who negotiated use of the overload control
mechanism during capabilities exchange. Requests
sent over other connections are handled the same
as they would in the absence of the overload control
mechanism.
</t>
<t>
Before sending a request, a Diameter node must first
determine which scope applies. It does this as
follows: first, a next hop host and connection
are determined, according to normal Diameter
procedures (potentially modified as described in
<xref target="recv-load"/>).
The sending node then searches through its list of
remote scope entries (ignoring any whose Period-of-Validity
has expired) to determine which ones
match the combination of the fields in the
current request, the next-hop host, and the selected
connection. If none of the matching scope entries
are in overload, then the message is handled normally,
and no additional processing is required.
</t>
<t>
As an optimization, a sending node MAY choose to track
whether any of its peers are in overload, and to skip
the preceding step if it knows that no scopes are in
overload.
</t>
<t>
If one or more matching scope entries are in overload,
then the sending node determines which scope is
most overloaded. The sending node then sends, drops,
queues, or otherwise modifies handling of the
request according to the negotiated overload control
algorithm, using the Overload-Metric from the selected
scope entry as input to the algorithm.
</t>
<t>
When determining which requests are impacted by the
overload control algorithm, request senders MAY take
into account the type of message being sent and its
contents. For example, messages within an existing
session may be prioritized over those that create
a new session. The exact rules for such prioritization
will likely vary from application to application.
The authors expect that specifications that define
or specify the use of specific Diameter Applications
may choose to formally define a set of rules for
such prioritization on a per-Application basis.
</t>
<t>
The foregoing notwithstanding, senders MUST NOT use the
content or type of request to exempt that request from
overload handling. For example, if a peer requests a
50% decrease in sent traffic using the "Loss" algorithm
(see <xref target="loss"/>), but the traffic that the
sending node wishes to send consists 65% of traffic
that the sender considers critical, then the sender is
nonetheless obliged to drop some portion of that critical
traffic (e.g., it may elect to drop all non-critical
traffic and 23% of the critical traffic, resulting in
an overall 50% reduction).
</t>
<t>
The sending node then inserts one or more Load-Info AVPs
(see <xref target="li"/>)
into the request. If the sender inserts more than
one Load-Info AVP, then each Load-Info AVP MUST contain
a unique scope, as specified by the Overload-Scope AVP(s)
inside the Load-Info AVP.
</t>
<t>
Each Load-Info AVP in the request MUST contain
an Overload-Metric (see <xref target="om"/>),
indicating whether (and to what
degree) the sender is overloaded for the indicated
scope. If this metric is not zero, then the Load-Info
AVP MUST also contain a Period-Of-Validity AVP
(see <xref target="pov"/>), indicating the
maximum period the recipient should consider the
Overload-Metric to be valid.
Any message containing
a non-zero Overload-Metric also MUST set the 'O'verload
bit in the Command Flags field to indicate to the
recipient that the message contains an overload indication.
See <xref target='overload-bit'/> for the definition of the
'O'verload bit.
</t>
<t>
Each Load-Info AVP MUST also contain a
Load AVP, indicating the server's load level
within the context of the indicated scope. See
<xref target="send-load"/> for details on generating
this load metric. Note that a server's load may
frequently be identical for all the scopes for which
it sends information.
</t>
</section>
<section title="Receiving a Request" anchor="req-recv">
<section title="Receiving a Request from a Compliant Peer">
<t>
A node that receives a request from a peer that has
negotiated support for the overload control mechanism
will extract the Load-Info AVPs from the request and
use each of them to update its remote scope entries.
First, the node attempts to locate an existing scope
entry that corresponds to the Overload-Scope indicated
in the Load-Info AVP. If one does not exist, it is
created. The scope entry is then populated with
the overload metric, period of validity, and load
information. The message is then processed as normal.
</t>
</section>
<section title="Receiving a Request from a Noncompliant Peer">
<t>
An important aspect of the overload control mechanism
is that Diameter nodes that do not implement the
mechanism cannot have an advantage over those that
do. In other words, it is necessary to prevent
the situation that a network in overload will cease
servicing those transactions from overload-compliant
nodes in favor of those sent by those nodes that do
not implement the overload control mechanism.
To achieve this goal, message recipients need to
track the overload control metric on behalf of
those sending nodes that do not implement overload,
and to reject messages from those nodes that would have
been dropped if the sender had implemented the
overload mechanism.
</t>
<t>
A node that receives a request from a peer that has
not negotiated support for the overload control mechanism
searches through its list of local scope entries to
determine which ones match the combination of the
fields in the received request. (These are the
entries that indicate the Overload-Metric that the
node would have sent to the peer if the peer had
supported the overload mechanism).
If none of the matching scope entries
are in overload, then the message is sent normally,
and no additional processing is required.
</t>
<t>
If one or more matching local scope entries are in overload,
then the node determines which scope is
most overloaded. The node then executes the "Loss"
overload control algorithm (see <xref target="loss"/>)
using the overload metric
in that most overloaded scope. If the result of
running that algorithm determines that a sender who
had implemented the overload control mechanism would
have dropped the message, then the recipient MUST
reply to the request with a DIAMETER_PEER_IN_OVERLOAD
response (see <xref target="peer-in-overload"/>).
</t>
</section>
</section>
<section title="Sending an Answer" anchor="rsp-send">
<t>
This section applies only to those answers sent
to peers who negotiated use of the overload control
mechanism during capabilities exchange.
</t>
<t>
When sending an answer, a Diameter node inserts one
or more Load-Info AVPs (see <xref target="li"/>)
into the answer. If the sender inserts more than
one Load-Info AVP, then each Load-Info AVP MUST contain
a unique scope, as specified by the Overload-Scope AVP(s)
inside the Load-Info AVP.
</t>
<t>
Each Load-Info AVP in the answer MUST contain
an Overload-Metric (see <xref target="om"/>),
indicating whether (and to what
degree) the server is overloaded for the indicated
scope. If this metric is not zero, then the Load-Info
AVP MUST also contain a Period-Of-Validity AVP
(see <xref target="pov"/>), indicating the
maximum period the recipient should consider the
Overload-Metric to be valid.
Any message containing
a non-zero Overload-Metric also MUST set the 'O'verload
bit in the Command Flags field to indicate to the
recipient that the message contains an overload indication.
See <xref target='overload-bit'/> for the definition of the
'O'verload bit.
</t>
<t>
Each Load-Info AVP MUST also contain a
Load AVP, indicating the server's load level
within the context of the indicated scope. See
<xref target="send-load"/> for details on generating
this load metric. Note that a server's load may
frequently be identical for all the scopes for which
it sends information.
</t>
</section>
<section title="Receiving an Answer" anchor="rsp-recv">
<t>
A node that receives a answer from a peer that has
negotiated support for the overload control mechanism
will extract the Load-Info AVPs from the answer and
use each of them to update its remote scope entries.
First, the node attempts to locate an existing scope
entry that corresponds to the Overload-Scope indicated
in the Load-Info AVP. If one does not exist, it is
created. The scope entry is then populated with
the overload metric, period of validity, and load
information. The message is then processed as normal.
</t>
</section>
</section>
<section title="Diameter Agent Behavior" anchor="agent">
<t>
This section discusses the behavior of a Diameter Agent acting
as a Proxy or Relay. Diameter Agents that provide redirect or
translation services behave the same as Diameter Servers for
the purpose of overload control, and follow the procedures
defined in <xref target='client-server'/>.
</t>
<t>
Whenever sending a request or an answer, Agents MUST include
a Load-Info AVP reflecting the a Agent's overload
and load information. In formulating this information,
the Agent may choose to use only that information
relating to its own local resources. However,
better network behavior can be achieved if agents
incorporate information received from their peers
when generating overload information. The exact
means for incorporating such information is left
to local policy at the agent.
</t>
<t>
For example: consider an agent that distributes
sessions and transactions among three Diameter
servers, each hosting a different Diameter application.
While it would be compliant for the Agent to only
report its own overload state (i.e., at
"Host" scope), overall network behavior would
be improved if it chose to also report overload
state for up to three additional scopes (i.e. at "Application-ID"
scope), incorporating the Overload information received
from each server in these scopes.
</t>
<section title="Proxying a Request" anchor="req-proxy">
<t>
Upon receiving a request, a Diameter Proxy or Relay
performs the steps detailed in <xref target="req-recv"/>.
</t>
<t>
The agent then MUST remove all Load-Info AVPs from the request:
Load-Info is never passed through a Proxy or Relay
transparently.
</t>
<t>
When the Diameter Agent proxies or relays a request, it
follows the process outlined in <xref target="req-send"/>.
</t>
</section>
<section title="Proxying an Answer" anchor="rsp-proxy">
<t>
Upon receiving an answer, a Diameter Agent
follows the process described in <xref target="rsp-recv"/>
to update its remote scope entries.
</t>
<t>
The Agent then
MUST remove all Load-Info AVPs from the answer:
Load-Info is never passed through a Proxy or Relay
transparently.
</t>
<t>
When the Diameter Agent proxies or relays a response, it
follows the process outlined in <xref target="rsp-send"/>.
</t>
</section>
</section>
<section title="Proactive Load and Overload Communication" anchor="proactive">
<t>
Because not all Diameter links will have constant
traffic, it may be occasionally necessary to send
overload and/or load information over links that would
otherwise be quiescent. To proactively send such
information to peers, the Diameter node with information
to convey may choose to send a Diameter Watchdog Request (DWR)
message to its peers. The procedure described in
<xref target="req-send"/> applies to these requests,
which provides the means to send load and overload information.
</t>
<t>
In order to prevent unnecessarily diminished throughput
between peers, a Diameter node SHOULD proactively send
a DWR to all its peers whenever it leaves an overload
state. Similarly, in order to provide peers the proper
data for load distribution, nodes SHOULD send DWR
messages to a peer if the load information most
recently sent to that peer has changed by more than 20%
and is more than 5 seconds old.
</t>
</section>
<section title="Load Processing" anchor="load">
<t>
While the remainder of the mechanism described in this
document is aimed at handling overload situations once
they occur, it is far better for a system if overload
can be avoided altogether. In order to facilitate
overload avoidance, the overload mechanism includes
the ability to convey node load information.
</t>
<t>
Semantically, the Load information sent by a Diameter
node indicates the current utilization of its most
constrained resource. It is a linear scale from 0
(least loaded) to 65535 (most loaded).
</t>
<t>
It is critical to distinguish between the value conveyed
in the Load AVP and the value conveyed in the
Overload-Metric AVP. The Load AVP is computed and used
independent of the Overload-Algorithm selected for a
connection, while the Overload-Metric is meaningful
only in the context of the selected algorithm. Most
importantly, the Load information never has any impact
on the behavior specified in the overload algorithm.
If a node reports a Load of 65535, but the Overload-Metric
does not indicate any need to apply the selected overload
control algorithm, then the sender MUST NOT apply the
selected overload control algorithm. Conversely,
if a node is reporting an Overload-Metric that requires
the recipient to take action to reduce traffic, those
actions MUST be taken, even if the node is simultaneously
reporting a Load value of 0.
</t>
<section title="Sending Load Information" anchor='send-load'>
<t>
Diameter nodes implementing the overload mechanism
described in this document MUST include a Load
AVP (inside a Load-Info AVP) in every Diameter message
(request and answer)
they send over a connection that has been negotiated
to use the overload control mechanism. Note that this
requirement does not necessitate calculation of the Load
metric each time a message is sent; the Load value may
be calculated periodically (e.g., every 100 ms), and
used for every message sent until it is recalculated.
</t>
<t>
The algorithm
for generation of the load metric is a matter of
local policy at the Diameter node, and may vary widely
based on the internal software architecture of that node.
</t>
<t>
For advanced calculations of Load, anticipated inputs
to the computation include CPU utilization, network
utilization, processor interrupts, I/O throughput,
and internal message queue depths.
</t>
<t>
To free implementors from the potential complexity of determining
an optimal calculation for load, we define a very
simple, baseline load calculation that MAY be used
for the purpose of populating the Load AVP.
Implementations using this simplified calculation will
use a
configured, hard-coded, or Service Level Agreement
(SLA)-defined maximum number of transactions per second
(TPS) which a node is known to be able to support without
issue. These implementations simply report their
load as a linear representation of how much of this known
capacity is currently in use:
</t>
<figure><artwork>
Load = MIN(Current_TPS * 65535 / Maximum_TPS, 65535)
</artwork></figure>
<t>
To prevent rapid fluctuations in the load metric,
nodes SHOULD report a rolling average of the calculated
load rather than the actual instantaneous load at any
given moment.
</t>
<t>
Load information is scoped to the level indicated
by the Overload-Info-Scope AVP present in the
Load-Info AVP in which the Load AVP appears.
</t>
</section>
<section title="Receiving Load Information" anchor='recv-load'>
<t>
While sending load information is mandatory, the actual
processing of load information at a recipient is
completely optional. Ideally, recipients will use
the load information as input to a decision regarding
which of multiple equivalent servers to use when
initiating a new connection. Recipients may choose
to update load information on receipt of every message;
alternately, they may periodically "sample" messages
from a host to determine the load it is currently
reporting.
</t>
<section title="Example Load Handling">
<t>
This section describes a non-normative example
of how recipients can use Load information received
from other Diameter nodes. At a high level,
the concept is that received load metrics are
used to scale the distribution algorithm that the
node uses for selection of a server from a group of
equivalent servers.
</t>
<t>
Consider a client that uses DNS to resolve a
host name into IP addresses. In this example,
the client is attempting to reach the server
for the realm example.com. It performs a
NAPTR query for the "AAA+D2T" record for
that domain, and receives a result pointing
to the SRV record "_diameter._tcp.example.com".
Querying for this SRV record, in turn, results
in three entries, with the same priorities:
</t>
<texttable>
<ttcol>SRV Weight</ttcol><ttcol>Server Name</ttcol>
<c>20</c> <c>server-a.example.com</c>
<c>20</c> <c>server-b.example.com</c>
<c>60</c> <c>server-c.example.com</c>
</texttable>
<t>
The client then examines the currently reported loads
for each of the three servers. In this example, we
are asserting that the reported load metrics are
as follows:
</t>
<texttable>
<ttcol>Load</ttcol><ttcol>Server Name</ttcol>
<c>13107 (20%)</c> <c>server-a.example.com</c>
<c>26214 (60%)</c> <c>server-b.example.com</c>
<c>52428 (80%)</c> <c>server-c.example.com</c>
</texttable>
<t>
Based on this load information, the client scales the
SRV weights proportional to each server's reported
load; the general formula is:
</t>
<figure><artwork>
new_weight = original_weight * (65535 - load) / 65535
</artwork></figure>
<t>
The node then calculates a new set of weights
for the destination hosts:
<vspace blankLines="1"/>
<list style="symbols">
<t> server-a: new_weight = 20 * (65535 - 13107) / 65535 = 16</t>
<t> server-b: new_weight = 20 * (65535 - 26214) / 65535 = 12</t>
<t> server-c: new_weight = 60 * (65535 - 52428) / 65535 = 12</t>
</list>
</t>
<t>
These three new weights (16, 12, and 12) are then used as input
to the random selection process traditionally used when selecting
among several SRV records.
</t>
<t>
Note that this example is provided in the context of DNS SRV
processing; however, it works equally well in the case that
server processing weights are provisioned or made available
through an alternate resolution process.
</t>
</section>
</section>
</section>
<section title="Session Establishment for Session Groups" anchor="session-setup">
<t>
The procedure in this section applies
to any Diameter operation that may result in the creation
of a new Diameter session. Note that these operations are
performed in addition to any normal message processing,
and in addition to the operations described in the following
sections.
</t>
<section title="Session Group Concepts">
<t>
At the time a session is established, the server and/or the
client may choose to assign the newly created session to a
Session Group that they can use to refer to the session
(and other sessions in the same group) in later
overload-related messages. This grouping is intended to be
used by servers that have visibility into resources that
may be independently overloaded, but which do not correspond
to an existing Diameter construct (such as Application,
Realm, or Destination Server).
</t>
<t>
One example of a server having visibility into resources
that don't have a corresponding Diameter construct is
a Diameter Agent servicing a mixed community of users --
say, one authenticated by a "Business" server, and another
authenticated by a "Residential" server.
The client in this network does not know which group
any given session belongs in; the routing of
sessions is based on information available only to the agent.
</t>
<figure><artwork>
+-------------+ +-------------+
| | | |
| Server A | | Server B |
| (Business) | |(Residential)|
| | | |
+-------------+ +-------------+
`. ,'
`. ,'
`. ,'
+-----+---+-----+
| |
| Agent |
| |
+---------------+
^
|
+-------+-------+
| |
| Client |
| |
+---------------+
</artwork></figure>
<t>
In this case, the Agent may wish to assign sessions to
two client-visible Session Groups when the session is
established. By doing so, the Agent gains the ability
to report Load and Overload metrics to the Client
independently for the two classes of users. This can be
extremely helpful, for example, in allowing the Agent
to ask the Client to throttle traffic for the
Residential server when it becomes overload, without
impacting sessions pertaining to the Business server.
</t>
<t>
Similar situations can arise even without
the presence of Diameter Agents in the network: a
server may have a class of sessions that require
access to an off-board database (which can, itself,
become overloaded), while also servicing a class of
sessions that is handled entirely by a local authentication
table. The server can use Session Groups to assign these
two classes of sessions to different groups, and report
overload on the class using the (overloaded) off-board
database without impacting the other sessions.
</t>
<t>
In some applications, it is possible to have the session
established by one peer (e.g., in the upstream direction),
while some subsequent in-session transactions are initiated
by the other peer (e.g., in the downstream direction).
Because of this possibility, the overload mechanism allows
both peers to establish a Session Group at the time the
session is set up. The session identifiers
are scoped to the node that sends them. In other words,
if a server assigns a session to a group called "Residential",
this group is not related to a client group (if any) by
the same name. For clarity, this document will refer to the
session group assigned by the server performing the processing
as a "local session group," and the session group assigned
by the remote node as a "remote session group."
</t>
<t>
Nodes that send a session-creating request follow normal
Diameter procedures, along with the additional behavior
described in <xref target="req-send"/> and
<xref target="req-proxy"/>, as appropriate. Such nodes
may also assign the session to a Session Group, as long
as the peer to which they are communicating indicated
support for the "Session-Group" scope during capabilities
exchange. Whether to do so and what group to assign a
session to is done according to local policy.
To perform such assignment, the node will include a
Session-Group AVP (see <xref target="sg"/> in the
Load-Info AVP for the session creating request.
These nodes also store the assigned name as the session's
local session group.
</t>
</section>
<section title="Session Group Procedures">
<t>
The procedures in this section only apply on connections
for which support for the "Session-Group" scope has been
negotiated during capabilities exchange. See
<xref target="conn-setup"/>.
</t>
<t>
When a node receives a
session creating request, it MUST check that request
for the presence for a Session-Group AVP in its Load-Info
AVP. If one is present, it stores that session group
name as the remote session group name for that server.
This allows clients to assign the session to a group,
allowing it to indicate overload for server-initiated
transactions in the resulting session.
</t>
<t>
When a node replies to a session creating request, it can
choose to assign the newly-established session to a
session group. Whether it chooses to do so is independent
of whether the remote node assigned the session to a session
group. To perform such an assignment, the node includes a
Session-Group AVP in the Load-Info AVP sent in answer
to the session-creating request.
These nodes also store the assigned name as the session's
local session group.
</t>
<t>
Finally, when a node that has sent a session-creating
request receives a corresponding answer message, it MUST
check that answer for the presence of a Session-Group AVP
in its Load-Info AVP. If one is present, it stores that
session group name as the remote session group name for
that server.
</t>
</section>
</section>
</section>
<section title="Loss-Based Overload Control Algorithm" anchor="loss">
<t>
This section describes a baseline, mandatory-to-implement
overload control algorithm, identified by the indicator
"Loss". This algorithm allows a Diameter peer to ask
its peers to reduce the number of requests they would
ordinarily send by a specified percentage. For example,
if a peer requests of another peer that it reduce the
traffic it is sending by 10%, then that peer will
redirect, reject, or treat as failed, 10% of the traffic
that would have otherwise been sent to this Diameter node.
</t>
<section title="Overload-Metric values for the 'Loss' Algorithm">
<t>
A Diameter node entering the overload state for any
of the scopes that it uses with its peers will calculate
a value for its Overload Metric, in the range of 0 to 100
(inclusive). This value indicates the percentage traffic
reduction the Diameter node wishes its peers to implement.
The computation of the exact value for this parameter is
left as an implementation choice at the sending node.
It is acceptable for implementations to request different
levels of traffic reduction to different peers according
to local policy at the Diameter node. These Overload Metrics
are then communicated to peers using the Overload-Metric
AVP in requests and answers sent by this node.
</t>
<t>
Recipients of Overload-Metric AVPs on connections for which
the "Loss" algorithm has been specified MUST reduce the
number of requests sent in the corresponding scope by
that percentage, either by redirecting them to an alternate
destination, or by failing the request. For a Diameter Agent,
these failures are indicated to the peer who originated the
request by sending a DIAMETER_PEER_IN_OVERLOAD
response (see <xref target="peer-in-overload"/>).
For diameter clients, these failures cause the client
to behave as if they received a transient error in
response to the request.
</t>
<t>
It is acceptable, when implementing the "Loss" algorithm,
for the reduction in transactions to make use of a
statistical loss function (e.g., random assignment
of transactions into "success" and "failure" categories
based on the indicated percentage). In such a case,
the actual traffic reduction might vary slightly from
the percentage indicated, albeit in an insignificant
amount.
</t>
<t>
The selection of which messages to withhold from sending
does not need to be arbitrary. For example, implementations
are allowed to distinguish between higher-priority and
lower-priority messages, and drop the lower-priority
messages in favor of dropping the higher priority
messages, as long as the total reduction in traffic
conforms to the Overload-Metric in effect at the time.
The selection of which messages to prioritize over
others will likely vary from application to application
(and may even be subject to standardization as part
of the application definition). One example of such
a prioritization scheme would be to treat those messages
that result in the creation of a new session as lower
priority then those messages sent in the context of
an established session.
</t>
</section>
<section title="Example Implementation">
<t>
The exact means a client uses to implement the requirement
that it reduce traffic by a requested percentage is left
to the discretion of the implementor. However, to aid in
understanding the nature of such an implementation, we
present an example of a valid implementation in pseudo-code.
</t>
<t>
In this example, we consider that the sending node maintains
two classes of request. The first category are considered
of lower priority than the second category. If a reduction
in traffic is required, then these lower priority requests
will be dropped before any of the higher priority requests
are dropped.
</t>
<t>
The sending Diameter node determines the mix of requests
falling into the first category, and those falling into
the second category. For example, 40% of the requests
may be in the lower-priority category, while 60% are
in the higher-priority category.
</t>
<t>
When a node receives an overload indication from one of
its peers, it converts the Overload-Metric value to a value
that applies to the first category of requests. For example,
if the Overload-Metric for the applicable context is "10", and
40% of the requests are in the lower-priority category,
then:
</t>
<figure><artwork>
10 / 40 * 100 = 25
</artwork></figure>
<t>
Or 25% of the requests in the first category can be dropped,
with an overall reduction in sent traffic of 10%. The sender
then drops 25% of all category 1 requests. This can be
done stochastically, by selecting a random number for each
sent packet between 1 to 100 (inclusive), and dropping any
packet for which the resulting percentage is equal to or less
than 25. In this set of circumstances, messages in the
second category do not require any reduction to meet the
requirement of 25% traffic reduction.
</t>
<t>
A reference algorithm is shown below, using pseudo-code.
</t>
<figure><artwork> <![CDATA[
cat1 := 80.0 // Category 1 --- subject to reduction
cat2 := 100.0 - cat1 // Category 2 --- Under normal operations
// only subject to reduction after category 1 is exhausted.
// Note that the above ratio is simply a reasonable default.
// The actual values will change through periodic sampling
// as the traffic mix changes over time.
while (true) {
// We're modeling message processing as a single work queue
// that contains both incoming and outgoing messages.
msg := get_next_message_from_work_queue()
update_mix(cat1, cat2) // See Note below
switch (msg.type) {
case outbound request:
destination := get_next_hop(msg)
oc_context := get_oc_scope(destination,msg)
if (we are in overload) {
add_overload_avps(msg)
}
if (oc_context == null) {
send_to_network(msg) // Process it normally by sending the
// request to the next hop since this particular
// destination is not subject to overload
}
else {
// Determine if server wants to enter in overload or is in
// overload
in_oc := extract_in_oc(oc_context)
oc_value := extract_oc(oc_context)
oc_validity := extract_oc_validity(oc_context)
if (in_oc == false or oc_validity is not in effect) {
send_to_network(msg) // Process it normally by sending
// the request to the next hop since this particular
// destination is not subject to overload. Optionally,
// clear the oc context for this server (not shown).
}
else { // Begin perform overload control
r := random()
drop_msg := false
if (cat1 >= cat2) {
category := assign_msg_to_category(msg)
pct_to_reduce_cat2 := 0
pct_to_reduce_cat1 := oc_value / cat1 * 100
if (pct_to_reduce_cat1 > 100) {
// Get remaining messages from category 2
pct_to_reduce_cat2 := 100 - pct_to_reduce_cat1
pct_to_reduce_cat1 := 100
}
if (category == cat1) {
if (r <= pct_to_reduce_cat1) {
drop_msg := true
}
}
else { // Message from category 2
if (r <= pct_to_reduce_cat2) {
drop_msg := true
}
}
}
else { // More category 2 messages than category 1;
// indicative of an emergency situation. Since
// there are more category 2 messages, don't
// bother distinguishing between category 1 or
// 2 --- treat them equal (for simplicity).
if (r <= oc_value)
drop_msg := true
}
if (drop_msg == false) {
send_to_network(msg) // Process it normally by
// sending the request to the next hop
}
else {
// Do not send request downstream, handle locally by
// generating response (if a proxy) or treating as
// an error (if a user agent).
}
} // End perform overload control
}
end case // outbound request
case outbound answer:
if (we are in overload) {
add_overload_avps(msg)
}
send_to_network(msg)
end case // outbound answer
case inbound answer:
create_or_update_oc_scope() // For the specific server
// that sent the answer, create or update the oc scope;
// i.e., extract the values of the overload AVPs
// and store them in the proper scopes for later use.
process_msg(msg)
end case // inbound answer
case inbound request:
create_or_update_oc_scope()
if (we are not in overload) {
process_msg(msg)
}
else { // We are in overload
if ( connection supports overload)
process_msg(msg)
}
else { // Sender does not support oc
if (local_policy(msg) says process message) {
process_msg(msg)
}
else {
send_answer(msg, DIAMETER_PEER_IN_OVERLOAD)
}
}
}
end case // inbound request
}
}
]]></artwork></figure>
<t>
A simple way to sample the traffic mix for category 1 and
category 2 is to associate a counter with each category
of message. Periodically (every 5-10s), get the value
of the counters and calculate the ratio of category 1
messages to category 2 messages since the last calculation.
</t>
<t>
Example: In the last 5 seconds, a total of 500 requests
were scheduled to be sent. Assume that 450 out of 500 were
messages subject to reduction and 50 out of 500 were
classified as requests not subject to reduction. Based
on this ratio, cat1 := 90 and cat2 := 10, or a 90/10 mix
will be used in overload calculations.
</t>
<t>
Of course, this scheme can be generalized to include an arbitrary
number of priorities, depending on how many different classes
of messages make sense for the given application.
</t>
</section>
</section>
<section title="Diameter AVPs for Overload" anchor="avps">
<t>
NOTE: THE AVP NUMBERS IN THIS SECTION ARE USED FOR EXAMPLE
PURPOSES ONLY. THE FINAL AVP CODES TO BE USED WILL BE ASSIGNED
BY IANA DURING THE PUBLICATION PROCESS, WHEN AND IF THIS DOCUMENT
IS PUBLISHED AS AN RFC.
</t>
<texttable>
<ttcol>Attribute Name</ttcol>
<ttcol>AVP Code</ttcol>
<ttcol>Sec. Def.</ttcol>
<ttcol>Data Type</ttcol>
<ttcol>MUST</ttcol>
<ttcol>MUST NOT</ttcol>
<c>Load-Info</c>
<c>&li-code;</c>
<c><xref target="li" format="counter"/></c>
<c>Grouped</c>
<c></c>
<c>M,V</c>
<c>Supported-Scopes</c>
<c>&ss-code;</c>
<c><xref target="ss" format="counter"/></c>
<c>Unsigned64</c>
<c></c>
<c>M,V</c>
<c>Overload-Algorithm</c>
<c>&oa-code;</c>
<c><xref target="oa" format="counter"/></c>
<c>Enumerated</c>
<c></c>
<c>M,V</c>
<c>Overload-Info-Scope</c>
<c>&ois-code;</c>
<c><xref target="ois" format="counter"/></c>
<c>OctetString</c>
<c></c>
<c>M,V</c>
<c>Overload-Metric</c>
<c>&om-code;</c>
<c><xref target="om" format="counter"/></c>
<c>Unsigned32</c>
<c></c>
<c>M,V</c>
<c>Period-Of-Validity</c>
<c>&pov-code;</c>
<c><xref target="pov" format="counter"/></c>
<c>Unsigned32</c>
<c></c>
<c>M,V</c>
<c>Session-Group</c>
<c>&sg-code;</c>
<c><xref target="sg" format="counter"/></c>
<c>UTF8String</c>
<c></c>
<c>M,V</c>
<c>Load</c>
<c>&l-code;</c>
<c><xref target="l" format="counter"/></c>
<c>Unsigned32</c>
<c></c>
<c>M,V</c>
</texttable>
<section anchor="li" title="Load-Info AVP">
<t>
The Load-Info AVP (AVP code &li-code;) is of type
Grouped, and is used as a top-level container
to group together all information pertaining to load
and overload information. Every Load-Info AVP MUST
contain one Overload-Information-Scope AVP,
and one Overload-Metric AVP.
</t>
<t>
The Grouped Data field of the Load-Info AVP has the
following CCF grammar:
</t>
<!-- Why not a figure? Well, it turns out that
xml2rfc is broken in a very ugly way. Entity
substitution inside artwork doesn't work, and
ends up truncating the figure. This isn't
very pretty in the source, but it looks fine
when rendered. -->
<t>
< Load-Info > ::= < AVP Header: &li-code; ><vspace/>
< Overload-Metric ><vspace/>
* { Overload-Info-Scope }<vspace/>
[ Supported-Scopes ]<vspace/>
* [ Overload-Algorithm ]<vspace/>
[ Period-Of-Validity ]<vspace/>
[ Session-Group ]<vspace/>
[ Load ]<vspace/>
* [ AVP ]<vspace/>
</t>
</section>
<section anchor="ss" title="Supported-Scopes AVP">
<t>
The Supported-Scopes AVP (AVP code &ss-code;) is of type
Uint64, and is used during capabilities exchange
to indicate the scopes that a given node can receive
on the connection.
Nodes that support the mechanism
defined in this document MUST include a Supported-Scopes
AVP in all CER messages. It also MUST appear in any
CEA messages sent in answer to a CER message
containing a Load-Info AVP.
The Supported-Scopes AVP MUST NOT appear
in any other message types.
See <xref target="ois"/> for an initial list of
scopes.
</t>
<t>
The Supported-Scopes AVP contains a bitmap that indicates
the scopes supported by the sender.
Within the bitmap, the least
significant bit indicates support for scope 1 (Destination-Realm),
while the next least significant bit indicates support for scope
2 (Application-ID), and so on. In general, if we consider the bits
to be numbered from 0 (LSB) to 63 (MSB), then any bit n
corresponds to the scope type numbered n+1. This scheme allows for
up to 64 total scopes to be supported. More formally, the bitmask
used to indicate support for any specific context is calculated as
follows (where the symbol "<<" indicates a bit shift left):
</t>
<figure><artwork>
bitmask = 1 << (n - 1)
</artwork></figure>
<t>
For additional clarity, the bitmasks for the
scopes defined in this document are as follows:
</t>
<texttable>
<ttcol>Scope</ttcol> <ttcol>Bitmask </ttcol> <ttcol>Scope</ttcol>
<c>1</c><c>0x0000000000000001</c><c>Destination-Realm</c>
<c>2</c><c>0x0000000000000002</c><c>Application-ID</c>
<c>3</c><c>0x0000000000000004</c><c>Destination-Host</c>
<c>4</c><c>0x0000000000000008</c><c>Host</c>
<c>5</c><c>0x0000000000000010</c><c>Connection</c>
<c>6</c><c>0x0000000000000020</c><c>Session-Group</c>
<c>7</c><c>0x0000000000000040</c><c>Session</c>
</texttable>
<t>
The advertisement process that makes use of the Supported-Scopes AVP
is described in <xref target="conn-setup"/>.
</t>
</section>
<section anchor="oa" title="Overload-Algorithm AVP">
<t>
The Overload-Algorithm AVP (AVP code &oa-code;) is of type
Enumerated, and is used to negotiate the algorithm
that will be used for load abatement. The Overload-Algorithm
AVP MAY appear in CER and CEA messages, and MUST NOT appear
in any other message types. If absent, an Overload Algorithm
of type 1 (Loss) is indicated. Additional values
can be registered by other documents; see <xref target="new-algorithms"/>.
Initial values for the
enumeration are as follows:
</t>
<texttable>
<ttcol>AVP Values</ttcol> <ttcol>Attribute Name</ttcol> <ttcol>Reference</ttcol>
<c>0</c><c>Reserved</c><c>-</c>
<c>1</c><c>Loss</c><c>[RFC &rfcnum;]</c>
</texttable>
</section>
<section anchor="ois" title="Overload-Info-Scope AVP">
<t>
The Overload-Info-Scope AVP (AVP code &ois-code;) is of type
OctetString, and is used to indicate to which scope the
Overload-Metric applies.
</t>
<t>
See <xref target="scopes"/> for a definition of the
different scope types and a formal description of how
they are applied. Other documents may define additional
scopes; see <xref target="new-scopes"/> for details.
</t>
<figure><artwork>
0 1 2 3
0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
| Scope | |
+-+-+-+-+-+-+-+-+ Details |
| |
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
</artwork></figure>
<texttable>
<ttcol>Scope</ttcol> <ttcol>Attribute Name</ttcol> <ttcol>Reference</ttcol>
<c>0</c><c>Reserved</c><c>[RFC &rfcnum;]</c>
<c>1</c><c>Destination-Realm</c><c>[RFC &rfcnum;]</c>
<c>2</c><c>Application-ID</c><c>[RFC &rfcnum;]</c>
<c>3</c><c>Destination-Host</c><c>[RFC &rfcnum;]</c>
<c>4</c><c>Host</c><c>[RFC &rfcnum;]</c>
<c>5</c><c>Connection</c><c>[RFC &rfcnum;]</c>
<c>6</c><c>Session-Group</c><c>[RFC &rfcnum;]</c>
<c>7</c><c>Session</c><c>[RFC &rfcnum;]</c>
</texttable>
<t>
Each Overload-Info-Scope has a different encoding, according
to the identifier used to designate the corresponding
scope. The formats for the seven scopes defined in this
document are given in the following section.
</t>
<section title="Realm Scope">
<figure><artwork>
0 1 2 3
0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
| 1 | |
+-+-+-+-+-+-+-+-+ Realm (DiameterIdentity) |
| |
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
</artwork></figure>
</section>
<section title="Application-ID Scope">
<figure><artwork>
0 1 2 3
0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
| 2 | Reserved (set to zeros) |
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
| Application-ID (Unsigned32) |
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
</artwork></figure>
</section>
<section title="Host Scope">
<figure><artwork>
0 1 2 3
0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
| 3 | |
+-+-+-+-+-+-+-+-+ Host (DiameterIdentity) |
| |
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
</artwork></figure>
</section>
<section title="Session Scope">
<figure><artwork>
0 1 2 3
0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
| 4 | |
+-+-+-+-+-+-+-+-+ Session-ID (UTF8String) |
| |
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
</artwork></figure>
</section>
<section title="Connection Scope">
<figure><artwork>
0 1 2 3
0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
| 5 | Reserved (set to zeros) |
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
</artwork></figure>
</section>
<section title="Session Group Scope">
<figure><artwork>
0 1 2 3
0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
| 6 | |
+-+-+-+-+-+-+-+-+ Group Name (UTF8String) |
| |
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
</artwork></figure>
</section>
</section>
<section anchor="om" title="Overload-Metric AVP">
<t>
The Overload-Metric AVP (AVP code &om-code;) is of type
Unsigned32, and is used as input to the load mitigation
algorithm. Its definition and interpretation is left up
to each individual algorithm, with the exception that an
Overload-Metric of "0" always indicates that the node
is not in overload (that is, no load abatement procedures
are in effect) for the indicated scope.
</t>
</section>
<section anchor = "pov" title="Period-Of-Validity AVP">
<t>
The Period-Of-Validity AVP (AVP code &pov-code;) is of type
Unsigned32, and is used to indicate the length of time,
in seconds,
the Overload-Metric is to be considered valid (unless
overridden by a subsequent Overload-Metric in the same
scope). It MUST NOT be present if the Overload-Metric
is '0', and MUST be present otherwise.
</t>
</section>
<section anchor = "sg" title="Session-Group AVP">
<t>
The Session-Group AVP (AVP code &sg-code;) is of type
UTF8String, and is used to assign a new session to the
session group that it names. The Session-Group AVP
MAY appear once in the answer to a session-creating
request, and MUST NOT appear in any other message
types.
</t>
</section>
<section anchor = "l" title="Load AVP">
<t>
The Load AVP (AVP code &l-code;) is of type
Unsigned32, and is used to indicate the load
level of the scope in which it appears.
See <xref target="load"/> for additional
information.
</t>
</section>
</section>
<section title="Security Considerations">
<t>
A key concern for recipients of overload metrics and
load information is whether the peer from which
the information has been received is authorized
to speak for the indicated scope. For scopes
such as "Host" and "Connection", such
authorization is obvious. For other scopes,
such as "Application-ID" and "Realm", the potential
for a peer to maliciously or accidentally
reduce traffic to a third party is evident.
Implementations may choose to ignore indications
from hosts which do not clearly have authority over
the indicated scope; alternately, they may wish
to further restrict the scope to apply only to
the host from which the information has been
received.
</t>
<t>
On the other hand, multiple nodes that are under the
same administrative control (or a tightly controlled
confederation of control) may be implicitly
trusted to speak for all scopes within that domain
of control. Implementations are encouraged to allow
configuration of inherently trusted servers to which
the foregoing restrictions are not applied.
</t>
<t>
Open Issue: There are almost certainly other security
issues to take into consideration here. For example,
we might need to include guidance around who gets to
see our own load information, and potentially changing
the granularity of information presented based on
trust relationships.
</t>
</section>
<section title="IANA Considerations">
<t>
This document defines new entries in several
existing IANA tables. It also creates two
new tables.
</t>
<section title="New Diameter AVPs">
<t>
The following entries are added to the
"AVP Codes" table under the "aaa-parameters"
registry.
</t>
<texttable>
<ttcol>AVP Code</ttcol>
<ttcol>Attribute Name</ttcol>
<ttcol>Reference</ttcol>
<c>&li-code;</c>
<c>Load-Info</c>
<c>RFC &rfcnum;</c>
<c>&ss-code;</c>
<c>Supported-Scopes</c>
<c>RFC &rfcnum;</c>
<c>&oa-code;</c>
<c>Overload-Algorithm</c>
<c>RFC &rfcnum;</c>
<c>&ois-code;</c>
<c>Overload-Info-Scope</c>
<c>RFC &rfcnum;</c>
<c>&om-code;</c>
<c>Overload-Metric</c>
<c>RFC &rfcnum;</c>
<c>&pov-code;</c>
<c>Period-Of-Validity</c>
<c>RFC &rfcnum;</c>
<c>&sg-code;</c>
<c>Session-Group</c>
<c>RFC &rfcnum;</c>
<c>&l-code;</c>
<c>Load</c>
<c>RFC &rfcnum;</c>
</texttable>
<t>
</t>
</section>
<section title="New Diameter Disconnect-Cause">
<t>
The following entry is added to the "Disconnect-Cause AVP
Values (code 273)" table in the "aaa-parameters" registry:
</t>
<texttable>
<ttcol>AVP Values</ttcol>
<ttcol>Attribute Name</ttcol>
<ttcol>Reference</ttcol>
<c>&disconnect-cause-negotiation-failure;</c>
<c>NEGOTIATION_FAILURE</c>
<c>RFC &rfcnum;</c>
</texttable>
</section>
<section title="New Diameter Response Code" anchor="peer-in-overload">
<t>
The following entry is added to the
"Result-Code AVP Values (code 268) - Transient Failures"
table in the "aaa-parameters" registry:
</t>
<texttable>
<ttcol>AVP Values</ttcol>
<ttcol>Attribute Name</ttcol>
<ttcol>Reference</ttcol>
<c>&peer-in-overload;</c>
<c>DIAMETER_PEER_IN_OVERLOAD</c>
<c>RFC &rfcnum;</c>
</texttable>
</section>
<section title="New Command Flag" anchor="overload-bit">
<t>
The following entry is added to the
"Command Flags" table in the "aaa-parameters" registry:
</t>
<texttable>
<ttcol>bit</ttcol>
<ttcol>Name</ttcol>
<ttcol>Reference</ttcol>
<c>4</c>
<c>'O'verload</c>
<c>RFC &rfcnum;</c>
</texttable>
</section>
<section title="Overload Algorithm Registry">
<t>
This document defines a new table, to be titled
"Overload-Algorithm Values (code &oa-code;)",
in the "aaa-parameters" registry. Its initial
values are to be taken from the table in
<xref target="oa"/>.
</t>
<t>
New entries in this table follow the IANA
policy of "Specification Required."
(Open Issue: The WG should discuss registration
policy to ensure that we think this is the
right balance).
</t>
</section>
<section title="Overload Scope Registry">
<t>
This document defines a new table, to be titled
"Overload-Info-Scope Values (code &ois-code;)",
in the "aaa-parameters" registry. Its initial
values are to be taken from the table in
<xref target="ois"/>.
</t>
<t>
New entries in this table follow the IANA
policy of "Specification Required."
(Open Issue: The WG should discuss registration
policy to ensure that we think this is the
right balance).
</t>
</section>
</section>
</middle>
<back>
<references title="Normative References">
&rfc2119;
&rfc3588bis;
&reqs;
</references>
<references title="Informative References">
&soc;
&rfc3588;
&rfc6357;
</references>
<section title="Acknowledgements">
<t>
This work was inspired by and borrows heavily from
the SIP overload control mechanism described in
<xref target="I-D.ietf-soc-overload-control"/>.
The authors of this document are deeply grateful
to the editor and authors of that work, as well
as its many contributors.
</t>
<t>
Thanks to Ben Campbell and Eric McMurry for significant input to
the initial mechanism design.
The author also thanks Martin Dolly, Bob Wallace, John Gilmore,
Matt McCann, Jonathan Palmer, Kedar Karmarkar, Imtiaz Shaikh,
Jouni Korhonen, Uri Baniel, Jianrong Wang, Brian Freeman, and
Eric Noel for early feedback on the mechanism.
</t>
</section>
<section title="Requirements Analysis">
<t>
This section analyzes the mechanism described in this document
against the set of requirements detailed in
<xref target="I-D.ietf-dime-overload-reqs"/>.
</t>
<t>
Open Issue: This analysis to be performed after requirements
have been finalized.
</t>
</section>
<section title="Extending the Overload Mechanism" anchor='extending'>
<t>
This specification includes two key extension points to allow
for new behaviors to be smoothly added to the mechanism
in the future. The following sections discuss the means by which
future documents are expected to extend the mechanism.
</t>
<section title="New Algorithms" anchor="new-algorithms">
<t>
In order to provide the ability for different means
of traffic abatement in the future, this specification
allows for descriptions of new traffic reduction algorithms.
In general, documents that define new
algorithms need to describe externally-observable
node behavior in sufficient detail as to allow
interoperation.
</t>
<t>
At a minimum, such description needs to include:
</t>
<t><list style="numbers">
<t>The name and IANA-registered number for negotiating the algorithm (see <xref target="oa"/>).</t>
<t>A clear description of how the Overload-Metric AVP is to be interpreted, keeping in mind that "0" is reserved to indicate that no overload condition exists.</t>
<t>An example, proof-of-concept description (preferably in pseudo-code) of how nodes can implement the algorithm.</t>
</list></t>
<t>
New algorithms must be capable of working with all applications,
not just a subset of applications.
</t>
</section>
<section title="New Scopes" anchor="new-scopes">
<t>
Because it is impossible to foresee all the potential constructs that
it might be useful to scope operations to for the purposes of
overload, we allow for the registration of new scopes.
</t>
<t>
At a minimum, such description needs to include:
</t>
<t><list style="numbers">
<t>The name and IANA-registered number for negotiating and indicating the scope (see <xref target="ois"/>).</t>
<t>A syntax for the "Details" field of the Overload-Info-Scope AVP, preferably derived from one of the base Diameter data types.</t>
<t>An explicit and unambiguous description of how both parties to the overload control mechanism can determine which transactions correspond to the indicated scope.</t>
<t>A clear and exhaustive list that extends the one in <xref target="combining"/>, indicating exactly which combinations of scopes are allowed with the new scope. This list must take into account all of the IANA-registered scopes at the time of its publication.</t>
</list></t>
<t>
It is acceptable for new scopes to be specific to constructs within
one or several applications. In other words, it may be desirable
to define scopes that can be applied to one kind of application
while not making sense for another. Extension documents should
be very clear that such is the case, however, if they choose
to do so.
</t>
</section>
</section>
<section title="Design Rationale">
<t>
The current design proposed in this document takes into
account several trade-offs and requirements that may
not be immediately obvious. The remainder of this appendix
highlights some of the potentially more controversial and/or
non-obvious of these, and attempts to explain why such decisions
were made they way they were.
</t>
<t>
That said, none of the following text is intended to represent
a line in the sand. All of the decisions can be revisited
if necessary, especially if additional facts are brought into
the analysis that change the balance of the decisions.
</t>
<section title="Piggybacking">
<t>
The decision to piggyback load information on existing
messages derives primarily from REQ 14 in
<xref target="I-D.ietf-dime-overload-reqs"/>:
"The mechanism SHOULD provide for increased feedback when
traffic levels increase. The mechanism MUST NOT do this
in such a way that it increases the number of messages
while at high loads."
</t>
<t>
If we were to introduce new messaging -- say, by defining
a new overload control Application -- then a node in overload
would be required to generate more messages at high
load in order to keep overload information in its peers
up-to-date.
</t>
<t>
If further analysis determines that other factors are
ultimately more important than the provisions of REQ 14,
several factors would need to be considered.
</t>
<t>
First and foremost would be the prohibition, in the base
Diameter specification (<xref target="I-D.ietf-dime-rfc3588bis"/>),
against adding new commands to an existing application.
Specifically, section 1.3.4 stipulates: "[A] new Diameter
application MUST be created when one or more of the following
criteria are met:... A new command is used within the existing
application either because an additional command is added,
an existing command has been modified so that a new Command
Code had to be registered, or a command has been deleted."
Because of this stipulation, the addition of new command codes
to existing applications would require registration of entirely
new application IDs for those applications to support overload
control. We consider this to be too disruptive a change to
consider.
</t>
<t>
By the author's reading, there is no provision that exempts
the "Diameter Common Messages" Application (Application ID 0)
from the above clauses. This effectively prohibits the
additional of new messages to this Application. While it may
be theoretically possible to specify behavior that hijacks
the DWR/DWA watchdog messages for the purpose of overload
control messaging, doing so requires a complete redefinition
of their behavior and, fundamentally, their semantics. This
approach seems, at first blush, to be an unacceptable
change to the base Application.
</t>
<t>
The remaining approach -- defining a new application for
overload control -- has some promise, if we decide not
to fulfill REQ 14. It remains to be seen whether the
users of the Diameter protocol, including other SDOs who
define applications for Diameter, are willing to specify
the use of multiple Diameter Applications for use on a single
reference point.
</t>
</section>
<section title="Load AVP in All Packets">
<t>
Some have questioned the currently specified behavior
of message senders including a Load AVP in every
message sent. This is being proposed as a potential
performance enhancement, with the idea being that
message recipients can save processing time by examining
arbitrarily selected messages for load information, rather
than looking for a Load AVP in every message that arrives.
Of course, to enable this kind of sampling, the Load AVP
must be guaranteed to be present; otherwise, attempts to
find it will occasionally fail.
</t>
<t>
The reciprocal approach, of sending a Load AVP only when
the Load has changed (or changed by more than a certain amount),
requires the recipient to search through the Load-Info
grouped AVP in every message received in order to determine
whether a Load AVP is present.
</t>
<t>
On a cursory analysis, we determined that appending a Load AVP
to each message is fundamentally a cheaper operation than
traversing the contents of each Load-Info AVP to determine
whether a Load AVP is present.
</t>
<t>
If a later decision is made to require examination of each
message to determine whether it include a Load AVP, we may
be able to obtain some efficiencies by requiring Load to be
the first AVP in the Load-Info AVP.
</t>
</section>
<section title="Graceful Failure">
<t>
Some commenters have raised the question of whether a node
can reject an incoming connection upon recognizing that
the remote node does not support the Diameter overload
control mechanism. One suggestion has been to add a
response code to indicate exactly such a situation.
</t>
<t>
So far, we have opted against doing so. Instead, we
anticipate an incremental deployment of the overload
control mechanism, which will likely consist of a
mixture of nodes that support and node that do not
support the mechanism. Were we to allow the rejection of
connections that do not support the mechanism,
we would create a situation that necessitates a
"flag day," on which every Diameter node in a network
is required to simultaneously, and in perfect
synchronization, switch from not supporting the
overload mechanism, to supporting it.
</t>
<t>
Given the operational difficulty of the foregoing,
we have decided that defining a response code, even
if optional, that was to be used to reject connections
merely for the lack of overload control support, would
form an attractive nuisance for implementors. The result
could easily be a potential operational nightmare for network
operators.
</t>
</section>
</section>
</back>
</rfc>
| PAFTECH AB 2003-2026 | 2026-04-24 04:05:04 |