Age | Commit message (Collapse) | Author |
|
* anders/diameter/performance/OTP-14521:
Fix append of Route-Record AVPs
|
|
Commit b3d9e0c0 did away with the reordering of diameter_avp lists, so
prepending the AVP to the list means prepending it in the message, which
is not what the RFC requires.
Appending to a list isn't ideal, but right now there's no better way.
|
|
* anders/diameter/DOIC/OTP-14588:
Exercise avp_dictionaries in traffic suite
Let generic AVPs be encoded/decoded in alternate dictionaries
Rename field in codec map: dictionary -> app_dictionary
Add RFC 7683 Diameter Overload Indicator Conveyance text and dictionary
Fix decode undef
Fix dictionary compilation error message
|
|
To support specifications like RFC 7683 DOIC, that only define AVPs, not
applications. AVPs that aren't known to the application dictionary in
question could previously not be decoded. Configuring alternate
dictionaries with the new transport/service option avp_dictionaries
changes this, so that AVPs like DOIC's Grouped OC-OLR can presented in
their fully decoded glory. Encode is also extended, allowing things like
the following to be encoded in an outgoing message:
'AVP' => [{'OC-OLR', #{'OC-Sequence-Number' => 1,
'OC-Report-Type' => 0,
'OC-Reduction-Percentage' => [25]}}]
A diameter_gen_doic_rfc7683 dictionary is installed, but
avp_dictionaries isn't specific to DOIC.
This commit also solves the problem demonstrated a few commits back,
that application AVPs aren't decoded in answers setting the E-bit. Test
coverage will come in a subsequent commit.
|
|
To better reflect what the field is: field 'module' is the dictionary
module that's calling diameter_gen to decode a list of AVP, while field
'app_dictionary' is the dictionary module defining the message being
decoded.
|
|
* anders/diameter/decode_format/OTP-14511:
Map less in traffic suite
Fix decode_format doc oversights
Rename decode_format false to none
Tweak {decode_format, false} semantics
Fix dialyzer spec
|
|
* anders/diameter/Proxy-Info/OTP-9869:
Fix handling of Proxy-Info in answers formulated by diameter
|
|
* anders/diameter/Experimental-Result/OTP-14511:
Fix extraction of Experimental-Result for counter keys
|
|
Represent the decoded message by its atom-valued name in
diameter_packet.msg, which makes trace much more readable. A
diameter_avp.value is untouched (ie. undefined): the AVP name is already
in the name field.
|
|
RFC 6733 says this:
6.2. Diameter Answer Processing
When a request is locally processed, the following procedures MUST be
applied to create the associated answer, in addition to any
additional procedures that MAY be discussed in the Diameter
application defining the command:
...
o Any Proxy-Info AVPs in the request MUST be added to the answer
message, in the same order they were present in the request.
This wasn't done when a handle_request callback returned a Result-Code
in an 'answer-message' or protocol_error tuple, causing diameter itself
to construct the answer message. This form of answer is just a
convenience, since the callback can always return an answer that it
constructs itself.
|
|
The introduction of decode_format in commit 722fa415 (and then 55e65b26)
meant the value was not necessarily the intended tuple.
|
|
* anders/diameter/upgrade/OTP-14552:
Fix compatibility of remote send
|
|
By changing the definition of the request record, commit f489c0d5 broke
sending an outgoing request over a peer connection terminated on a
remote node running an older version of diameter. The modified fields
aren't even used on the remote node, so simply reintroduce one of the
fields so that the size of the tuple is unchanged.
|
|
To be able to disable the counting of messages for which application
callbacks take place. Messages sent/handled by diameter itself are
always counted.
|
|
That dialyzer hasn't noticed is broken.
|
|
That dialyzer hasn't noticed is broken.
|
|
Decode has previously been two passes: first chunk the message into a
reversed list of toplevel diameter_avp records, then fold through the
reversed list to build the full result. Various workarounds have made it
a bit more convoluted than it should be however. Rework it completely,
turning the previous 2-pass tail-recursive implementation into a 1-pass
body recursive one.
The relay decode still exists in diameter_codec, as a stripped down
version of the full decode in diameter_gen.
|
|
To be able to disable the relatively expensive check that the number of
AVPs received in a message or grouped AVP agrees with the dictionary in
question. The may well be easier for the user in handle_request/answer
callbacks, when digesting the received message, and in some cases may
not be important.
The check at encode can also be disabled, allowing messages that don't
agree with the dictionary in question to be sent, which can be useful in
test (at least).
|
|
Use the same [MsgName | Avps] representation as for the list decode, but
with Avps a map instead of a AVP name/values list. As a result, don't
set the message/AVP name on an additional key in the map, which felt a
bit odd. Messages are [MsgName :: atom() | map()], Grouped AVPs are just
map().
Fix at least one problem in the traffic suite along the way: with
decode_format false, the own decode in to_map/2 didn't know whether or
not to decode strings, resulting on some failures.
|
|
{record_decode, map} is a bit too quirky.
|
|
That is, decode to the same format that encode already accepts. Only a
message has its name at the head of the list since AVPs are already
name/value pairs.
|
|
With {record_decode, map}. The option name is arguably a bit misleading
now, but not too objectionable given that the encode/decode in question
has historically only been of records.
One advantage of the map decode is that the map only contains values for
those AVPs existing in the message or grouped AVP in question. The name
of the message or grouped AVP is stored in with key ':name', the leading
colon ensuring that the key isn't a diameter-name.
Decoding to maps makes the hrl files generated from dictionary files
largely irrelevant. There are value defines generated into these, but
they're typically so long as to be unusable.
|
|
To control whether or not messages and grouped AVPs are decoded to
records, in #diameter_packet.msg and #diameter_avp.value respectively.
The decode became unnecessary for diameter's needs in parent commit,
which decoupled it from the checking of AVP arities.
|
|
* anders/diameter/capx_vs_dpr/OTP-14338:
Let candidate peers be passed to diameter:call/4
Comment on RFC ambiguity regarding application identifiers
Remove trailing whitespace
|
|
By accepting an MFA that is applied to the fun that is otherwise spawned
for each incoming request, to allow handler processes to be reused. This
is not yet documented and may change, but the motivation is to let spawn
be replaced by process pool, from which the MFA selects. A list-valued
spawn_opt is equivalent to {erlang, spawn_opt, [Opts]}.
|
|
To solve the problem of being able to send messages to a peer that
hasn't advertised support for the application in question, as discussed
in the parent commit. diameter:call/4 can be passed 'peer' options to
identify candidates, and the only requirement is that an appropriate
dictionary be configured for encode. Filters are applied as if
candidates had been selected by advertised application.
|
|
As in commit fb14eac9, but for outgoing answers.
|
|
To simplify the call chains and intermediate terms, that had become a
little convoluted over time.
|
|
To allow list-valued messaged to be encoded in the specified order,
instead of in the dictionary order by first converting the list to a
record. This is not yet exposed in configuration.
|
|
The parent commit removed the convenience of setting something like the
following in the errors field of the diameter_packet of an answer
message.
[#diameter_avp{} = A2, {5001, #diameter_avp{} = A1}]
This results in Result-Code = 5001 and Failed-AVP = [A1,A2], but is
currently undocumented. Probably useful, so restore it.
Also accept {RC, [#diameter_avp{}]} at encode, which is probably more
useful; eg. [{5001, [A || {5001, A} <- Errors]}]
Anyone who wants full control can set errors = false and formulate
Result-Code/Failed-AVP themselves. (As opposed to not setting a value
explicitly, which results in setting from the decoded errors list. A bit
quirky, but documented and historical.)
|
|
When setting the Result-Code/Failed-AVP of an outgoing answer from an
errors list either returned from or not discarded by a handle_request
callback, more than the AVP paired with the Result-Code in question
could be set in Failed-AVP.
RFC 6733:
7.5. Failed-AVP AVP
The Failed-AVP AVP (AVP Code 279) is of type Grouped and provides
debugging information in cases where a request is rejected or not
fully processed due to erroneous information in a specific AVP. The
value of the Result-Code AVP will provide information on the reason
for the Failed-AVP AVP. A Diameter answer message SHOULD contain an
instance of the Failed-AVP AVP that corresponds to the error
indicated by the Result-Code AVP. For practical purposes, this
Failed-AVP would typically refer to the first AVP processing error
that a Diameter node encounters.
|
|
In this case the diameter_packet of an answer message for encode. The
record itself could be avoided, but that requires a new interface in
diameter_codec, probably for little gain.
|
|
In the theme of the previous two commits, creating the required
diameter_header of diameter_packet record only once.
|
|
As in the parent commit, recreating the options record is relatively
costly.
|
|
This old construction is approximately two to four times slower from
best (no elements modified) to worst (all modified) case, with the new
construction having constant speed.
|
|
The tuple is returned from and passed to callbacks, so retain the tuple
instead of its elements.
|
|
By passing additional arguments through it.
|
|
Since value is ignored.
|
|
|
|
What's interesting when implementing some form of load regulation is
when an incoming request has been answered or discarded. Acknowledge
exactly this, not the identity of handler processes as previously. A
transport process can request acks of nonforthcoming answers by sending
{diameter, ack} to the parent peer_fsm, a handler processes identifies
itself with a {handler, pid()} message, and the peer_fsm monitors on
this to be able to send a notification to the transport if the handler
dies before sending an answer.
|
|
When relaying outgoing requests through transport on a remote node,
terms that were stripped when sending to the transport process weren't
stripped when spawning a process on the remote node.
Also, don't save the request to the process dictionary in a process that
just relays an answer.
|
|
The table has existed forever, to route incoming answers to a waiting
request process: each outgoing request writes to the table, and each
incoming answer reads. This has been seen to suffer from lock contention
at high load however, so this commit moves the routing into the
diameter_peer_fsm processes that are diameter's conduit to transport
processes. The request table is still used for failover detection, but
entries are only written when a watchdog state transitions leaves or
enters state OKAY.
|
|
Commit 9a878743 addressed inefficiency at failover, but introduced
inefficiency in the sending of outgoing requests in so doing: each
outgoing request added an request table entry keyed on a transport pid,
then looked for a specific element with this key, and then (later)
removed the inserted element. Since the request table is a bag, this
results in linear searches over a potentially long list of element
keyed on the same pid. The higher the rate of outgoing calls, the more
costly it becomes.
Instead of writing entries to the request table, the peer_up/down calls
to diameter_traffic that mirror transitions to and from the OKAY state
in the RFC 3539 watchdog state machine now result in a process for
request processes to monitor in order to detect failover.
|
|
* anders/diameter/19.1/OTP-13838:
vsn -> 1.12.1
Update appup for 19.1
Fix xmllint errors in documentation
Remove documentation overkill
Don't run traffic tests in parallel when {string_decode, true}
Remove copyright from generated dictionary modules
Fix dictionary function typo
Fix dictionary typo in relay example
|
|
* anders/diameter/failover/OTP-13412:
Make peer failover more efficient
|
|
It's '#get-'/2, not 'get-'/2. Only failed if the dictionary in question
defined no Failed-AVP, which is rarely the case in practice.
Thanks to Ferenc Holzhauser.
|
|
* anders/diameter/overload/OTP-13330:
Suppress dialyzer warning
Remove dead case clause
Let throttling callback send a throttle message
Acknowledge answers to notification pids when throttling
Throttle properly with TLS
Don't ask throttling callback to receive more unless needed
Let a throttling callback answer a received message
Let a throttling callback discard a received message
Let throttling callback return a notification pid
Make throttling callbacks on message reception
Add diameter_tcp option throttle_cb
|
|
Failover caused the entire request table to be scanned in search of
entries with the transport process in question. With many entries
(possibly as a result of the leak fixed in commit 6c9cbd96), this can
lead to the service process hanging in ets:select_trap/1, with memory
growth when many request processes write concurrently. Now write entries
keyed on the transport pid, so that finding request processes at
failover is a lookup rather than a select scanning the entire table.
There is no upgrade handling in that new code doesn't consider that old
code didn't write entries on the transport pid. Thus, a request whose
table entries were written in old code will timeout rather than failover
in new code. That is, there is a small window for failover to be missed
(since request processes are short-lived), but it requires that it take
place during the upgrade.
As a minor aside, don't ignore failovers when sending binaries (which
isn't officially supported), let prepare_retransmit callbacks deal with
modifying the binary as required.
|
|
By sending {diameter, {answer, pid()}} when an incoming answer is sent
to the specified pid, instead of a discard message as previously. The
latter now literally means that the message has been discarded.
|
|
In addition to returning ok or {timeout, Tmo}, let a throttling callback
for message reception return a pid(), which is then notified if the
message in question is either discarded or results in a request process.
Notification is by way of messages of the form
{diameter, discard | {request, pid()}}
where the pid is that of a request process resulting from the received
message. This allows the notification process to keep track of the
maximum number of request processes a peer connection can have given
rise to.
|