diff options
-rw-r--r-- | lib/diameter/src/transport/diameter_sctp.erl | 47 | ||||
-rw-r--r-- | lib/diameter/test/diameter_traffic_SUITE.erl | 19 |
2 files changed, 49 insertions, 17 deletions
diff --git a/lib/diameter/src/transport/diameter_sctp.erl b/lib/diameter/src/transport/diameter_sctp.erl index 4eb3379d59..64b34da690 100644 --- a/lib/diameter/src/transport/diameter_sctp.erl +++ b/lib/diameter/src/transport/diameter_sctp.erl @@ -103,6 +103,8 @@ | undefined, os = 0 :: uint(), %% next output stream rotate = 1 :: boolean() | 0 | 1, %% rotate os? + unordered = false :: boolean() %% always send unordered? + | pos_integer(),% or if =< N outbound streams? packet = true :: boolean() %% legacy transport_data? | raw, message_cb = false :: false | diameter:eval(), @@ -242,8 +244,11 @@ i(#monitor{transport = TPid} = S) -> i({listen, Ref, {Opts, SvcPid, Addrs}}) -> monitor(process, SvcPid), [_] = diameter_config:subscribe(Ref, transport), %% assert existence - {Split, Rest} - = proplists:split(Opts, [accept, packet, sender, message_cb]), + {Split, Rest} = proplists:split(Opts, [accept, + packet, + sender, + message_cb, + unordered]), OwnOpts = lists:append(Split), {LAs, Sock} = AS = open(Addrs, Rest, ?DEFAULT_PORT), ok = gen_sctp:listen(Sock, true), @@ -255,12 +260,16 @@ i({listen, Ref, {Opts, SvcPid, Addrs}}) -> opts = [[[M] || {accept, M} <- OwnOpts], proplists:get_value(packet, OwnOpts, true) | [proplists:get_value(K, OwnOpts, false) - || K <- [sender, message_cb]]]}; + || K <- [sender, message_cb, unordered]]]}; %% A connecting transport. i({connect, Pid, Opts, Addrs, Ref}) -> - {[Ps | Split], Rest} - = proplists:split(Opts, [rport, raddr, packet, sender, message_cb]), + {[Ps | Split], Rest} = proplists:split(Opts, [rport, + raddr, + packet, + sender, + message_cb, + unordered]), OwnOpts = lists:append(Split), CB = proplists:get_value(message_cb, OwnOpts, false), false == CB orelse (Pid ! {diameter, ack}), @@ -274,6 +283,7 @@ i({connect, Pid, Opts, Addrs, Ref}) -> mode = {connect, connect(Sock, RAs, RP, [])}, socket = Sock, message_cb = CB, + unordered = proplists:get_value(ordered, OwnOpts, false), packet = proplists:get_value(packet, OwnOpts, true), send = proplists:get_value(sender, OwnOpts, false)}; @@ -311,12 +321,13 @@ i({K, Ref}, #transport{mode = {accept, _}} = S) -> S#transport{parent = Pid}; {K, T, Opts} when K == peeloff -> %% association {sctp, Sock, _RA, _RP, _Data} = T, - [Matches, Packet, Sender, CB] = Opts, + [Matches, Packet, Sender, CB, Unordered] = Opts, ok = accept_peer(Sock, Matches), demonitor(Ref, [flush]), false == CB orelse (S#transport.parent ! {diameter, ack}), t(T, S#transport{socket = Sock, message_cb = CB, + unordered = Unordered, packet = Packet, send = Sender}); accept_timeout = T -> @@ -799,14 +810,30 @@ 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 = 0, + streams = {_,OS}, + socket = Sock, + unordered = B} + = S) -> + ok = unordered(Sock, OS, B), + S#transport{rotate = 1 < OS}; recv(#transport{rotate = N} = S) -> S#transport{rotate = N-1}. +%% unordered/3 + +unordered(Sock, OS, B) + when B; + is_integer(B), OS =< B -> + inet:setopts(Sock, [{sctp_default_send_param, + #sctp_sndrcvinfo{flags = [unordered]}}]); + +unordered(_, OS, B) + when not B; + is_integer(B), B < OS -> + ok. + %% publish/4 publish(T, Ref, Id, Sock) -> diff --git a/lib/diameter/test/diameter_traffic_SUITE.erl b/lib/diameter/test/diameter_traffic_SUITE.erl index ffb4a508cd..c224f9a27e 100644 --- a/lib/diameter/test/diameter_traffic_SUITE.erl +++ b/lib/diameter/test/diameter_traffic_SUITE.erl @@ -533,9 +533,10 @@ add_transports(Config) -> LRef = ?util:listen(SN, [T, {sender, SS}, - {message_cb, ST andalso {?MODULE, message, [0]}} - | [{packet, hd(?util:scramble([false, raw]))} - || T == sctp andalso CS]], + {message_cb, ST andalso {?MODULE, message, [0]}}] + ++ [{packet, hd(?util:scramble([false, raw]))} + || T == sctp andalso CS] + ++ [{unordered, unordered()} || T == sctp], [{capabilities_cb, fun capx/2}, {pool_size, 8} | server_apps()] @@ -551,13 +552,17 @@ add_transports(Config) -> Id <- [{D,E}]], ?util:write_priv(Config, "transport", [LRef | Cs]). +unordered() -> + element(rand:uniform(4), {true, false, 1, 2}). + client_opts(tcp) -> []; client_opts(sctp) -> - [{sctp_initmsg, #sctp_initmsg{num_ostreams = N, - max_instreams = 5}} - || N <- [rand:uniform(8)], - N =< 6]. + [{unordered, unordered()} + | [{sctp_initmsg, #sctp_initmsg{num_ostreams = N, + max_instreams = 5}} + || N <- [rand:uniform(8)], + N =< 6]]. server_apps() -> B = have_nas(), |