File 0172-ssl-Make-benchmarks-work-again.patch of Package erlang

From e3b7b5950079ee865ec3530051d995b08137fb1c Mon Sep 17 00:00:00 2001
From: Dan Gudmundsson <dgud@erlang.org>
Date: Mon, 6 Apr 2020 12:38:12 +0200
Subject: [PATCH] ssl: Make benchmarks work again

It have been broken for a while.

Add more variants.
---
 lib/ssl/test/ssl_bench_SUITE.erl | 237 +++++++++++++++++++--------------------
 1 file changed, 113 insertions(+), 124 deletions(-)

diff --git a/lib/ssl/test/ssl_bench_SUITE.erl b/lib/ssl/test/ssl_bench_SUITE.erl
index 5d15b69f5e..b96830646b 100644
--- a/lib/ssl/test/ssl_bench_SUITE.erl
+++ b/lib/ssl/test/ssl_bench_SUITE.erl
@@ -25,13 +25,12 @@
 
 suite() -> [{ct_hooks,[{ts_install_cth,[{nodenames,2}]}]}].
 
-all() -> [{group, basic}, {group, setup}, {group, payload}, {group, pem_cache}].
+all() -> [{group, setup}, {group, payload}].
 
 groups() ->
-    [{basic, [], [basic_pem_cache]},
-     {setup, [{repeat, 3}], [setup_sequential, setup_concurrent]},
-     {payload, [{repeat, 3}], [payload_simple]},
-     {pem_cache, [{repeat, 3}], [use_pem_cache, bypass_pem_cache]}
+    [{setup, [{repeat, 3}], [setup_sequential, setup_sequential_noreuse, setup_sequential_13,
+                             setup_concurrent, setup_concurrent_noreuse, setup_concurrent_13]},
+     {payload, [{repeat, 3}], [payload, payload_13]}
     ].
 
 init_per_group(_GroupName, Config) ->
@@ -53,25 +52,9 @@ init_per_suite(Config) ->
 end_per_suite(_Config) ->
     ok.
 
-init_per_testcase(TC, Conf) when TC =:= use_pem_cache;
-                                 TC =:= bypass_pem_cache;
-                                 TC =:= basic_pem_cache ->
-    case bypass_pem_cache_supported() of
-        false -> {skipped, "PEM cache bypass support required"};
-        true ->
-            application:set_env(ssl, bypass_pem_cache, false),
-            Conf
-    end;
 init_per_testcase(_Func, Conf) ->
     Conf.
 
-end_per_testcase(TC, _Config) when TC =:= use_pem_cache;
-                                   TC =:= bypass_pem_cache;
-                                   TC =:= basic_pem_cache ->
-    case bypass_pem_cache_supported() of
-        false -> ok;
-        true -> application:set_env(ssl, bypass_pem_cache, false)
-    end;
 end_per_testcase(_Func, _Conf) ->
     ok.
 
@@ -89,73 +72,112 @@ end_per_testcase(_Func, _Conf) ->
 setup_sequential(Config) ->
     Server = proplists:get_value(server_node, Config),
     Server =/= undefined orelse error(no_server),
-    {ok, Result} = do_test(ssl, setup_connection, ?COUNT * 20, 1, Server),
+    Cfg = [{version, 'tlsv1.2'}],
+    {ok, Result} = do_test(ssl, {setup_connection,Cfg}, ?COUNT * 20, 1, Server),
     ct_event:notify(#event{name = benchmark_data,
 			   data=[{value, Result},
 				 {suite, "ssl"}, {name, "Sequential setup"}]}),
     ok.
 
+setup_sequential_noreuse(Config) ->
+    Server = proplists:get_value(server_node, Config),
+    Server =/= undefined orelse error(no_server),
+    Cfg = [{version, 'tlsv1.2'}, no_reuse],
+    {ok, Result} = do_test(ssl, {setup_connection,Cfg}, ?COUNT * 20, 1, Server),
+    ct_event:notify(#event{name = benchmark_data,
+			   data=[{value, Result},
+				 {suite, "ssl"}, {name, "Seq setup 1.2 no session"}]}),
+    ok.
+
+setup_sequential_13(Config) ->
+    Server = proplists:get_value(server_node, Config),
+    Server =/= undefined orelse error(no_server),
+    Cfg = [{version, 'tlsv1.3'}],
+    {ok, Result} = do_test(ssl, {setup_connection,Cfg}, ?COUNT * 20, 1, Server),
+    ct_event:notify(#event{name = benchmark_data,
+			   data=[{value, Result},
+				 {suite, "ssl"}, {name, "Seq setup 1.3"}]}),
+    ok.
+
 setup_concurrent(Config) ->
     Server = proplists:get_value(server_node, Config),
     Server =/= undefined orelse error(no_server),
-    {ok, Result} = do_test(ssl, setup_connection, ?COUNT, 100, Server),
+    Cfg = [{version, 'tlsv1.2'}],
+    {ok, Result} = do_test(ssl, {setup_connection,Cfg}, ?COUNT, 100, Server),
     ct_event:notify(#event{name = benchmark_data,
 			   data=[{value, Result},
 				 {suite, "ssl"}, {name, "Concurrent setup"}]}),
     ok.
 
-payload_simple(Config) ->
+setup_concurrent_noreuse(Config) ->
     Server = proplists:get_value(server_node, Config),
     Server =/= undefined orelse error(no_server),
-    {ok, Result} = do_test(ssl, payload, ?COUNT*300, 10, Server),
+    Cfg = [{version, 'tlsv1.2'}, no_reuse],
+    {ok, Result} = do_test(ssl, {setup_connection,Cfg}, ?COUNT, 100, Server),
     ct_event:notify(#event{name = benchmark_data,
 			   data=[{value, Result},
-				 {suite, "ssl"}, {name, "Payload simple"}]}),
+				 {suite, "ssl"}, {name, "Conc setup 1.2 no session"}]}),
     ok.
 
-basic_pem_cache(_Config) ->
-    do_test(ssl, pem_cache, 10, 5, node()).
-
-use_pem_cache(_Config) ->
-    {ok, Result} = do_test(ssl, pem_cache, 100, 500, node()),
+setup_concurrent_13(Config) ->
+    Server = proplists:get_value(server_node, Config),
+    Server =/= undefined orelse error(no_server),
+    Cfg = [{version, 'tlsv1.3'}],
+    {ok, Result} = do_test(ssl, {setup_connection,Cfg}, ?COUNT, 100, Server),
     ct_event:notify(#event{name = benchmark_data,
-                           data=[{value, Result},
-                                 {suite, "ssl"}, {name, "Use PEM cache"}]}).
+			   data=[{value, Result},
+				 {suite, "ssl"}, {name, "Conc setup 1.3"}]}),
+    ok.
 
-bypass_pem_cache(_Config) ->
-    {ok, Result} = do_test(ssl, pem_cache, 100, 500, node()),
+payload(Config) ->
+    Server = proplists:get_value(server_node, Config),
+    Server =/= undefined orelse error(no_server),
+    Cfg = [{version, 'tlsv1.2'}],
+    {ok, Result} = do_test(ssl, {payload, Cfg}, ?COUNT*300, 10, Server),
     ct_event:notify(#event{name = benchmark_data,
-                           data=[{value, Result},
-                                 {suite, "ssl"}, {name, "Bypass PEM cache"}]}).
+			   data=[{value, Result},
+				 {suite, "ssl"}, {name, "Payload simple"}]}),
+    ok.
 
+payload_13(Config) ->
+    Server = proplists:get_value(server_node, Config),
+    Server =/= undefined orelse error(no_server),
+    Cfg = [{version, 'tlsv1.3'}],
+    {ok, Result} = do_test(ssl, {payload, Cfg}, ?COUNT*300, 10, Server),
+    ct_event:notify(#event{name = benchmark_data,
+			   data=[{value, Result},
+				 {suite, "ssl"}, {name, "Payload 1.3"}]}),
+    ok.
 
 ssl() ->
     test(ssl, ?COUNT).
 
 test(Type, Count) ->
     Server = ssl_bench_test_lib:setup(perf_server),
-    (do_test(Type, setup_connection, Count * 20, 1, Server)),
-    (do_test(Type, setup_connection, Count, 100, Server)),
-    (do_test(Type, payload, Count*300, 10, Server)),
+    (do_test(Type, {setup_connection, [{version, 'tlsv1.2'}]}, Count * 20, 1, Server)),
+    (do_test(Type, {setup_connection, [{version, 'tlsv1.3'}]}, Count * 20, 1, Server)),
+    (do_test(Type, {setup_connection, [{version, 'tlsv1.2'}, no_reuse]}, Count * 20, 1, Server)),
+    (do_test(Type, {setup_connection, [{version, 'tlsv1.2'}]}, Count, 100, Server)),
+    (do_test(Type, {payload, [{version, 'tlsv1.2'}]}, Count*300, 10, Server)),
     ok.
 
-do_test(Type, TC, Loop, ParallellConnections, Server) ->
+do_test(Type, {Func, _}=TC, Loop, ParallellConnections, Server) ->
     _ = ssl:stop(),
     {ok, _} = ensure_all_started(ssl, []),
-
+    Certs = cert_data(),
     {ok, {SPid, Host, Port}} = rpc:call(Server, ?MODULE, setup_server_init,
-					[Type, TC, Loop, ParallellConnections]),
+					[Type, TC, Loop, ParallellConnections, Certs]),
     link(SPid),
     Me = self(),
     Test = fun(Id) ->
-		   CData = client_init(Me, Type, TC, Host, Port),
+		   CData = client_init(Me, Type, TC, Host, Port, Certs),
 		   receive
 		       go ->
 			   ?FPROF_CLIENT andalso Id =:= 1 andalso
 			       start_profile(fprof, [self(),new]),
 			   ?EPROF_CLIENT andalso Id =:= 1 andalso
 			       start_profile(eprof, [ssl_connection_sup, ssl_manager]),
-			   ok = ?MODULE:TC(Loop, Type, CData),
+			   ok = ?MODULE:Func(Loop, Type, CData),
 			   ?FPROF_CLIENT andalso Id =:= 1 andalso
 			       stop_profile(fprof, "test_connection_client_res.fprof"),
 			   ?EPROF_CLIENT andalso Id =:= 1 andalso
@@ -177,7 +199,7 @@ do_test(Type, TC, Loop, ParallellConnections, Server) ->
     TestPerSecond = case TimeInMicro of
                         0 ->
                             undefined;
-                        _ -> 
+                        _ ->
                             1000000 * TotalTests div TimeInMicro
                     end,
     io:format("TC ~p ~p ~p ~p 1/s~n", [TC, Type, ParallellConnections, TestPerSecond]),
@@ -185,8 +207,8 @@ do_test(Type, TC, Loop, ParallellConnections, Server) ->
     SPid ! quit,
     {ok, TestPerSecond}.
 
-server_init(ssl, setup_connection, _, _, Server) ->
-    {ok, LSocket} = ssl:listen(0, ssl_opts(listen)),
+server_init(ssl, {setup_connection, Opts}, _, _, Server, Certs) ->
+    {ok, LSocket} = ssl:listen(0, ssl_opts(listen, Opts, Certs)),
     {ok, {_Host, Port}} = ssl:sockname(LSocket),
     {ok, Host} = inet:gethostname(),
     ?FPROF_SERVER andalso start_profile(fprof, [whereis(ssl_manager), new]),
@@ -198,20 +220,8 @@ server_init(ssl, setup_connection, _, _, Server) ->
 		   ssl:close(Socket)
 	   end,
     setup_server_connection(LSocket, Test);
-server_init(ssl, payload, Loop, _, Server) ->
-    {ok, LSocket} = ssl:listen(0, ssl_opts(listen)),
-    {ok, {_Host, Port}} = ssl:sockname(LSocket),
-    {ok, Host} = inet:gethostname(),
-    Server ! {self(), {init, Host, Port}},
-    Test = fun(TSocket) ->
-		   {ok, Socket} = ssl:handshake(TSocket),
-		   Size = byte_size(msg()),
-		   server_echo(Socket, Size, Loop),
-		   ssl:close(Socket)
-	   end,
-    setup_server_connection(LSocket, Test);
-server_init(ssl, pem_cache, Loop, _, Server) ->
-    {ok, LSocket} = ssl:listen(0, ssl_opts(listen_der)),
+server_init(ssl, {payload, Opts}, Loop, _, Server, Certs) ->
+    {ok, LSocket} = ssl:listen(0, ssl_opts(listen, Opts, Certs)),
     {ok, {_Host, Port}} = ssl:sockname(LSocket),
     {ok, Host} = inet:gethostname(),
     Server ! {self(), {init, Host, Port}},
@@ -223,24 +233,19 @@ server_init(ssl, pem_cache, Loop, _, Server) ->
 	   end,
     setup_server_connection(LSocket, Test);
 
-server_init(Type, Tc, _, _, Server) ->
+server_init(Type, Tc, _, _, Server, _) ->
     io:format("No server init code for ~p ~p~n",[Type, Tc]),
     Server ! {self(), no_init}.
 
-client_init(Master, ssl, setup_connection, Host, Port) ->
+client_init(Master, ssl, {setup_connection, Opts}, Host, Port, Certs) ->
     Master ! {self(), init},
-    {Host, Port, ssl_opts(connect)};
-client_init(Master, ssl, payload, Host, Port) ->
-    {ok, Sock} = ssl:connect(Host, Port, ssl_opts(connect)),
-    Master ! {self(), init},
-    Size = byte_size(msg()),
-    {Sock, Size};
-client_init(Master, ssl, pem_cache, Host, Port) ->
-    {ok, Sock} = ssl:connect(Host, Port, ssl_opts(connect_der)),
+    {Host, Port, ssl_opts(connect, Opts, Certs)};
+client_init(Master, ssl, {payload, Opts}, Host, Port, Certs) ->
+    {ok, Sock} = ssl:connect(Host, Port, ssl_opts(connect, Opts, Certs)),
     Master ! {self(), init},
     Size = byte_size(msg()),
     {Sock, Size};
-client_init(_Me, Type, Tc, Host, Port) ->
+client_init(_Me, Type, Tc, Host, Port, _) ->
     io:format("No client init code for ~p ~p~n",[Type, Tc]),
     {Host, Port}.
 
@@ -282,13 +287,6 @@ payload(Loop, ssl, D = {Socket, Size}) when Loop > 0 ->
 payload(_, _, {Socket, _}) ->
     ssl:close(Socket).
 
-pem_cache(N, ssl, Data = {Socket, Size}) when N > 0 ->
-    ok = ssl:send(Socket, msg()),
-    {ok, _} = ssl:recv(Socket, Size),
-    pem_cache(N-1, ssl, Data);
-pem_cache(_, _, {Socket, _}) ->
-    ssl:close(Socket).
-
 msg() ->
     <<"Hello", 
       0:(512*8), 
@@ -308,11 +306,11 @@ ensure_all_started(App, Ack) ->
 	    {ok, Ack}
     end.
 
-setup_server_init(Type, Tc, Loop, PC) ->
+setup_server_init(Type, Tc, Loop, PC, Certs) ->
     _ = ssl:stop(),
     {ok, _} = ensure_all_started(ssl, []),
     Me = self(),
-    Pid = spawn_link(fun() -> server_init(Type, Tc, Loop, PC, Me) end),
+    Pid = spawn_link(fun() -> server_init(Type, Tc, Loop, PC, Me, Certs) end),
     Res = receive
 	      {Pid, {init, Host, Port}} -> {ok, {Pid, Host, Port}};
 	      {Pid, Error} -> {error, Error}
@@ -355,48 +353,39 @@ stop_profile(fprof, File) ->
     fprof:stop(),
     ok.
 
-ssl_opts(listen) ->
-    [{backlog, 500} | ssl_opts("server")];
-ssl_opts(connect) ->
-    [{verify, verify_peer} | ssl_opts("client")];
-ssl_opts(listen_der) ->
-    [{backlog, 500} | ssl_opts("server_der")];
-ssl_opts(connect_der) ->
-    [{verify, verify_peer} | ssl_opts("client_der")];
-ssl_opts(Role) ->
-    CertData = cert_data(Role),
-    Opts = [{active, false},
-            {depth, 2},
-            {reuseaddr, true},
-            {mode,binary},
-            {nodelay, true},
-            {ciphers, [{dhe_rsa,aes_256_cbc,sha}]}
-            |CertData],
-    case Role of
-        "client" ++ _ ->
-            [{server_name_indication, disable} | Opts];
-        "server" ++ _ ->
-            Opts
-    end.
-
-cert_data(Der) when Der =:= "server_der"; Der =:= "client_der" ->
-    [Role,_] = string:tokens(Der, "_"),
-    Dir = filename:join([code:lib_dir(ssl), "examples", "certs", "etc"]),
-    {ok, CaCert0} = file:read_file(filename:join([Dir, Role, "cacerts.pem"])),
-    {ok, Cert0} = file:read_file(filename:join([Dir, Role, "cert.pem"])),
-    {ok, Key0} = file:read_file(filename:join([Dir, Role, "key.pem"])),
-    [{_, Cert, _}] = public_key:pem_decode(Cert0),
-    CaCert1 = public_key:pem_decode(CaCert0),
-    CaCert = [CCert || {_, CCert, _} <- CaCert1],
-    [{KeyType, Key, _}] = public_key:pem_decode(Key0),
-    [{cert, Cert},
-     {cacerts, CaCert},
-     {key, {KeyType, Key}}];
-cert_data(Role) ->
-    Dir = filename:join([code:lib_dir(ssl), "examples", "certs", "etc"]),
-    [{cacertfile, filename:join([Dir, Role, "cacerts.pem"])},
-     {certfile, filename:join([Dir, Role, "cert.pem"])},
-     {keyfile, filename:join([Dir, Role, "key.pem"])}].
+ssl_opts(listen, Opts, Certs) ->
+    [{backlog, 500} | ssl_opts(server_config, Opts, Certs)];
+ssl_opts(connect, Opts, Certs) ->
+    [{verify, verify_peer} | ssl_opts(client_config, Opts, Certs)];
+ssl_opts(Role, TCOpts, Certs) ->
+    CertData = maps:get(Role, Certs),
+    {Version, KeyEx} =
+        case proplists:get_value(version, TCOpts) of
+            'tlsv1.2' = V -> {V, ecdhe_ecdsa};
+            'tlsv1.3' = V -> {V, any}
+        end,
+    Opts0 = [{active, false},
+             {depth, 2},
+             {reuseaddr, true},
+             {mode,binary},
+             {nodelay, true},
+             {versions, [Version]},
+             {ciphers, [ #{key_exchange => KeyEx, cipher => aes_128_gcm,
+                           mac => aead, prf => sha256}
+                       ]}
+            | CertData ],
+    Opts1 = case Role of
+                client_config -> [{server_name_indication, disable} | Opts0];
+                server_config -> Opts0
+            end,
+    Opts = case proplists:get_value(no_reuse, TCOpts) of
+               true -> [{reuse_sessions, false}|Opts1];
+               _ -> Opts1
+           end,
+    Opts.
+
+cert_data() ->
+    ssl_test_lib:make_cert_chains_der(ecdhe_ecdsa, []).
 
 bypass_pem_cache_supported() ->
     %% This function is currently critical to support cache bypass
-- 
2.16.4

openSUSE Build Service is sponsored by