aboutsummaryrefslogtreecommitdiffstats
path: root/lib/diameter/src/transport/diameter_sctp.erl
diff options
context:
space:
mode:
authorAnders Svensson <[email protected]>2017-09-03 13:31:40 +0200
committerAnders Svensson <[email protected]>2017-09-03 13:31:40 +0200
commit58d6f069744d9528a5059b8b4398f3368c798150 (patch)
tree7760c042d59ed9809f8ac2ddbe99a427281c99a9 /lib/diameter/src/transport/diameter_sctp.erl
parent50da40f8404969b5a1533026d49e2e2669ffadff (diff)
parenta3749fd240260958053f90539b0f7e04e720d070 (diff)
downloadotp-58d6f069744d9528a5059b8b4398f3368c798150.tar.gz
otp-58d6f069744d9528a5059b8b4398f3368c798150.tar.bz2
otp-58d6f069744d9528a5059b8b4398f3368c798150.zip
Merge branch 'anders/diameter/sctp/OTP-10889' into maint
* anders/diameter/sctp/OTP-10889: Send unordered on all outbound diameter_sctp streams Delay rotation of diameter_sctp outbound streams Exercise unordered delivery in traffic suite Use unordered delivery on a lone outbound stream in diameter_sctp
Diffstat (limited to 'lib/diameter/src/transport/diameter_sctp.erl')
-rw-r--r--lib/diameter/src/transport/diameter_sctp.erl33
1 files changed, 29 insertions, 4 deletions
diff --git a/lib/diameter/src/transport/diameter_sctp.erl b/lib/diameter/src/transport/diameter_sctp.erl
index 8de19e904e..4eb3379d59 100644
--- a/lib/diameter/src/transport/diameter_sctp.erl
+++ b/lib/diameter/src/transport/diameter_sctp.erl
@@ -102,6 +102,7 @@
streams :: {uint(), uint()} %% {InStream, OutStream} counts
| undefined,
os = 0 :: uint(), %% next output stream
+ rotate = 1 :: boolean() | 0 | 1, %% rotate os?
packet = true :: boolean() %% legacy transport_data?
| raw,
message_cb = false :: false | diameter:eval(),
@@ -692,11 +693,16 @@ send(#diameter_packet{transport_data = {outstream, SId}}
= S) ->
send(SId rem OS, Msg, S);
-%% ... or not: rotate through all streams.
-send(Msg, #transport{streams = {_, OS},
+%% ... or not: rotate when sending on multiple streams ...
+send(Msg, #transport{rotate = true,
+ streams = {_, OS},
os = N}
= S) ->
- send(N, Msg, S#transport{os = (N + 1) rem OS}).
+ send(N, Msg, S#transport{os = (N + 1) rem OS});
+
+%% ... or send on the only stream available.
+send(Msg, S) ->
+ send(0, Msg, S).
%% send/3
@@ -764,7 +770,7 @@ recv({[#sctp_sndrcvinfo{assoc_id = Id}], _Bin}
%% Inbound Diameter message.
recv({[#sctp_sndrcvinfo{}], Bin} = Msg, S)
when is_binary(Bin) ->
- message(recv, Msg, S);
+ message(recv, Msg, recv(S));
recv({_, #sctp_shutdown_event{}}, _) ->
stop;
@@ -784,6 +790,25 @@ recv({_, #sctp_paddr_change{}}, _) ->
recv({_, #sctp_pdapi_event{}}, _) ->
ok.
+%% recv/1
+%%
+%% Start sending unordered after the second reception, so that an
+%% outgoing CER/CEA will arrive at the peer before another request.
+
+recv(#transport{rotate = B} = S)
+ when is_boolean(B) ->
+ S;
+
+recv(#transport{rotate = 0, streams = {_,N}, socket = Sock} = S) ->
+ ok = inet:setopts(Sock, [{sctp_default_send_param,
+ #sctp_sndrcvinfo{flags = [unordered]}}]),
+ S#transport{rotate = 1 < N};
+
+recv(#transport{rotate = N} = S) ->
+ S#transport{rotate = N-1}.
+
+%% publish/4
+
publish(T, Ref, Id, Sock) ->
true = diameter_reg:add_new({?MODULE, T, {Ref, {Id, Sock}}}),
putr(?INFO_KEY, {gen_sctp, Sock}). %% for info/1