Age | Commit message (Collapse) | Author |
|
|
|
|
|
|
|
* anders/diameter/config_consistency/OTP-14555:
Let strict_mbit and incoming_maxlen be configured per transport
Let a service configure default transport options
Rename type evaluable -> eval
|
|
* anders/diameter/loopback_any/OTP-14544:
Use loopback/any config in examples suite
Handle loopback/any as local address in diameter_tcp/sctp
|
|
Export the old type as a synonym for backwards compatability. The name
evaluable is a bit too awkward.
|
|
The support is implied by documentation, but wasn't handled in code. Be
consistent in retrieving the address from the sock rather than the
configuration, and in accepting both ip and ifaddr for a local address.
|
|
* anders/diameter/performance/OTP-14521:
Work around unexpected common_test behaviour
Randomly skip groups in traffic suite
Randomly disable traffic counters in traffic suite
Add service_opt() traffic_counters
Fix type spec
Split AVPs at decode
Avoid unnecessary copying of binaries in diameter_tcp
Don't update diameter_tcp state unnecessarily
Don't update diameter_tcp state unnecessarily
Simplify extraction of incoming Diameter messages in diameter_tcp
Restructure/simplify message reception in diameter_peer_fsm
Sleep randomly at the start of (parallel) traffic testcases
Fix ct return value in traffic suite
Fix type spec
Optimize sub-binaries
Optimize sub-binaries
Count AVPs in #diameter_avp.index
Don't extract options unnecessarily at encode
Redo message decode as a single pass
|
|
Since messages are accumulated by appending binaries as of three
commits back, the accumulated binary is prone to being copied, as
discussed in the Efficiency Guide. Matching the Message Length header
as bytes are being accumulated is one cause of this, so work around it
by splitting the binary and extracting the length without a match.
This doesn't feel like something that should be necessary: that matching
a binary would cause an append to copy isn't obvious. The first attempt
at simplifying the accumulation was simply to append an incoming binary
to the current fragment, match against <<_, Len:24, _/binary>> to
extract the length, and then test if there are enough bytes for a
message. This lead to horrible performance (response times for 2 MB
messages approximately 100 times worse than previously), and it wasn't
at all obvious that the reason was the accumulated binary being copied
with each append as a result of the match. Using split_binary avoids the
match context that forces the copying.
|
|
Not with each setopts to re-activate the socket.
|
|
Only reset the fragment after all messages have been extracted.
|
|
Appending to a binary is efficient, so just append message fragments
Only match out the length once per message since doing so for every
packet from TCP causes the binary to be copied.
|
|
Since the actions can request that a previously passive socket be made
active.
Missed in commits 636a7199 and 373cd07c.
|
|
To let a recv callback for an incoming request set transport_data and
have it returned in a send callback.
|
|
From the receiver process, that can return binaries to send/receive and
stop the transport process from reading on the socket.
This is still undocumented, and may change.
|
|
With sends still from the receiving process by default, since changing
the default behaviour may well have negative effects. A separate sender
probably implies a greater need for some form of load regulation for
one, since a blocking send would no longer imply that incoming messages
are no longer recevied. Dealing with this could result in the same
deadlock that the sending process intends to avoid, but the user should
be in control over how/when incoming traffic is regulated.
|
|
Added in commit 2afd1fe5. Only rename variables in diameter_tcp, no
functional change.
|
|
This:
diameter_tcp.erl:241: Record construction #transport{parent::'false',ssl::boolean() | maybe_improper_list(),frag::<<>>,tref::'false',flush::'false',pending::0,reset::{1 | 4,0 | 2},throttled::boolean(),q::{0,queue:queue(_)},monitor::'undefined' | pid()} violates the declared type of field parent::pid()
The problem isn't #transport.pid at all, it's #monitor.pid, and the only
relation is that the pid that's assigned to the latter is also (later)
assigned to the former. There is no record construction that assigns
false to #transport.parent.
Introduced in commit 33a535e4.
|
|
Commits starting at 472a080c added a throttle_cb option to diameter_tcp
to let a callback apply backpressure when it decides that additional
requests should not be read. It didn't provide a hook for knowing that
an answer was sent however, which is needed when sends no longer take
place in the receiver process, and is more complicated than it should
be. Strip it all away, in preparation for a simpler incarnation.
|
|
Which dialyzer itself has never complained about.
|
|
Both diameter_tcp and diameter_sctp are susceptible to deadlock since a
peer that blocks send also prevents additional messages from being
received. Send from a process that's paired with the transport process
to avoid this. Use the existing monitor process in the TCP case, add one
in the SCTP case.
This has been the reason for many sporadic testcase failures, mostly in
diameter_traffic_SUITE.
|
|
Should be ssl:close/1.
|
|
Since smooth upgrade won't be supported in this branch.
|
|
Commit 5ca5fb71 ensured that they were closed immediately at transport
removal, but in so doing broke their closing at stop service completely,
by removing the timer that caused sockets to be closed even belatedly.
Monitor on the service process to make it happen.
This could still be improved, since stop_service listening ports aren't
closed until after the service process has died. They could be closed
earlier in the case of stop_service.
|
|
The transport interface documented in diameter_transport(3) is used to
start/stop accepting/connecting transport processes: they're started
with a function call, and told to die with their parent process. In the
accepting case, both diameter_tcp and diameter_sctp start a listening
process when the first accepting transport is started. However, there's
no way for a listening process to find out that that it should stop
listening when transport configuration is removed.
Both diameter_tcp and diameter_sctp have used a timer to terminate the
listening process after all existing accepting processes have died as a
consequence of transport removal. The problem with this is that nothing
stops a new client from connecting before this, and also that no new
transport can succeed in opening the same listening port (eg.
reconfiguration) until the old listener dies.
This commit solves the problem by adding diameter_reg:subscribe/2, to
allow callers to subscribe to messages about added/removed associations.
A call to diameter:add_transport/2 results in a new child process that
registers a term that a listening process subscribes to. Transport
removal results in the death of the child, and the resulting
notification to the listener causes the latter to close its socket and
terminate.
This is still an internal interface, but the subscription mechanism
should probably be made external (eg. a diameter:subscribe/1 that can
be used to subscribe to specified messages), so that transport modules
other than diameter's own can make use of it. There is no support for
soft upgrade.
|
|
* 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
|
|
This one:
diameter_tcp.erl:928: (call)
The call diameter_tcp:throttle({'timeout',_},#transport{socket::port() | {'sslsocket',_,_},parent::pid(),module::atom(),frag::binary() | {non_neg_integer(),non_neg_integer(),binary(),[binary()]},ssl::boolean() | [any()],timeout::'infinity' | non_neg_integer(),tref::'false' | reference(),flush::boolean(),throttle_cb::'false' | fun() | maybe_improper_list(fun() | maybe_improper_list(any(),[any()]) | {atom(),atom(),[any()]},[any()]) | {atom(),atom(),[any()]},throttled::'true' | binary()})
will never return since it differs in the 1st argument from the
success typing arguments:
('discard' | 'ok' | binary() | pid() | {'discard' | 'ok' | binary() | pid(),'false' | fun() | [fun() | [any()] | {atom(),atom(),[any()]}] | {atom(),atom(),[any()]}},#transport{socket::port() | {'sslsocket',_,_},parent::pid(),module::atom(),frag::binary() | {non_neg_integer(),non_neg_integer(),binary(),[binary()]},ssl::boolean() | [any()],timeout::'infinity' | non_neg_integer(),tref::'false' | reference(),flush::boolean(),throttle_cb::'false' | fun() | [fun() | [any()] | {atom(),atom(),[any()]}] | {atom(),atom(),[any()]},throttled::binary()})
It's true that the clause doesn't return, because of the throw, and
that's the intention.
|
|
Orphaned in commit 9298872b.
|
|
That is, don't assume that it's only diameter_tcp doing so: allow it to
be received when not throttling. This lets a callback module trigger a
new throttling callback itself, but it's not clear if this will be
useful in practice.
|
|
In particular, let a callback decide when to receive the initial
message.
|
|
TCP packets can contain more than one message, so only ask to receive
another message if it hasn't already been received.
|
|
As discussed in the parent commit. This is easier said than done in
practice, but there's no harm in allowing it.
|
|
This can be used as a simple form of overload protection, discarding the
message before it's passed into diameter to become one more request
process in a flood. Replying with 3004 would be more appropriate when
the request has been directed at a specific server (the RFC's
requirement) however, and possibly it should be possible for a callback
to do this as well.
|
|
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.
|
|
The callback is now applied to the atom 'false' when asking if another
message should be received on the socket, and to a received binary
message after reception. Throttling on received messages makes it
possible to distinguish between requests and answers.
There is no callback on outgoing messages since these don't have to go
through the transport process, even if they currently do.
|
|
To let a callback module decide whether or to receive another message
from the peer, so that backpressure can be applied when it's
inappropriate. This is to let a callback protect against reading more
than can be processed, which is otherwise possible since diameter_tcp
otherwise always asks for more.
A callback is made after each message, and can answer to continue
reading or to ask again after a timeout. It's each message instead of
each packet partly for simplicity, but also since this should be
sufficiently fine-grained. Per packet would require some interaction
with the fragment timer that flushes partial messages that haven't been
completely received.
|
|
Record field types have been modified due to commit 8ce35b2:
"Take out automatic insertion of 'undefined' from typed record fields".
|
|
|
|
In particular, that starts for the same transport reference can now be
concurrent. Looking up a listener process and starting a new one if not
found did handle this (more than one process could find no listener),
and diameter_sctp assumed there could only be one transport process
waiting for an association.
|
|
Option 'accept' allows remote addresses to be configured as tuples or
regular expressions. The remote addresses for any incoming (aka
accepted) connection/association are matched against the configured
values, any non-matching address causing the connection/association to
be aborted.
|
|
The third argument to start/3 was just wrong.
|
|
|
|
Use the default address address (as selected by gen_tcp) if none is
configured, passing it in the new 'connected' message introduced by the
previous commit.
The corresponding update to diameter_sctp has to wait until problems
with inet:sockname/1 are resolved: the function currently only returns
one address, and sometimes {0,0,0,0}. See OTP-11018.
|
|
|
|
Don't start a new timer with each incoming message. Instead, start a
timer at timeout and flush after two successive timeouts with no message
reception.
|
|
Which will be the case in R16B.
|
|
Which will be the case with R16B in this case.
|
|
|
|
* anders/diameter/R15B02_release:
Dialyzer spec fix
Learn to keep time in diameter_gen_sctp_SUITE
Update command line test for changed ct:run_test/1 return value
OTP-10243
|
|
|